codexuse-cli 3.6.6 → 3.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ import { execFileSync, spawn, spawnSync } from "node:child_process";
7
7
  import * as Crypto from "node:crypto";
8
8
  import crypto$1, { createHash, randomBytes, randomUUID } from "node:crypto";
9
9
  import * as NFS from "node:fs";
10
- import fs, { accessSync, constants, createReadStream, existsSync, promises, readFileSync, realpathSync, statSync } from "node:fs";
10
+ import fs, { accessSync, constants, existsSync, promises, readFileSync, realpathSync, statSync } from "node:fs";
11
11
  import * as OS from "node:os";
12
12
  import os from "node:os";
13
13
  import * as Path from "node:path";
@@ -16916,7 +16916,7 @@ function fixPath() {
16916
16916
  if (result) process.env.PATH = result;
16917
16917
  } catch {}
16918
16918
  }
16919
- const expandHomePath = fn(function* (input) {
16919
+ const expandHomePath$1 = fn(function* (input) {
16920
16920
  const { join } = yield* Path$1;
16921
16921
  if (input === "~") return OS.homedir();
16922
16922
  if (input.startsWith("~/") || input.startsWith("~\\")) return join(OS.homedir(), input.slice(2));
@@ -16925,7 +16925,7 @@ const expandHomePath = fn(function* (input) {
16925
16925
  const resolveStateDir = fn(function* (raw) {
16926
16926
  const { join, resolve } = yield* Path$1;
16927
16927
  if (!raw || raw.trim().length === 0) return join(OS.homedir(), ".t3", "userdata");
16928
- return resolve(yield* expandHomePath(raw.trim()));
16928
+ return resolve(yield* expandHomePath$1(raw.trim()));
16929
16929
  });
16930
16930
  //#endregion
16931
16931
  //#region ../../packages/t3-contracts/src/baseSchemas.ts
@@ -17115,6 +17115,8 @@ const MODEL_SLUG_ALIASES_BY_PROVIDER = { codex: {
17115
17115
  const ORCHESTRATION_WS_METHODS = {
17116
17116
  getSnapshot: "orchestration.getSnapshot",
17117
17117
  getThreadSnapshot: "orchestration.getThreadSnapshot",
17118
+ subscribeShell: "orchestration.subscribeShell",
17119
+ subscribeThread: "orchestration.subscribeThread",
17118
17120
  syncExternalThreads: "orchestration.syncExternalThreads",
17119
17121
  dispatchCommand: "orchestration.dispatchCommand",
17120
17122
  getTurnDiff: "orchestration.getTurnDiff",
@@ -17361,7 +17363,8 @@ const ProjectMetaUpdateCommand = Struct({
17361
17363
  const ProjectDeleteCommand = Struct({
17362
17364
  type: Literal("project.delete"),
17363
17365
  commandId: CommandId,
17364
- projectId: ProjectId
17366
+ projectId: ProjectId,
17367
+ force: optional$2(Literal(true))
17365
17368
  });
17366
17369
  const ThreadCreateCommand = Struct({
17367
17370
  type: Literal("thread.create"),
@@ -19028,6 +19031,7 @@ const STATIC_KEYBINDING_COMMANDS = [
19028
19031
  "terminal.new",
19029
19032
  "terminal.close",
19030
19033
  "diff.toggle",
19034
+ "commandPalette.toggle",
19031
19035
  "chat.new",
19032
19036
  "chat.newLocal",
19033
19037
  "editor.openFavorite",
@@ -19117,6 +19121,21 @@ const ProjectWriteFileInput = Struct({
19117
19121
  });
19118
19122
  const ProjectWriteFileResult = Struct({ relativePath: TrimmedNonEmptyString });
19119
19123
  //#endregion
19124
+ //#region ../../packages/t3-contracts/src/filesystem.ts
19125
+ const FILESYSTEM_PATH_MAX_LENGTH = 512;
19126
+ const FilesystemBrowseInput = Struct({
19127
+ partialPath: TrimmedNonEmptyString.check(isMaxLength(FILESYSTEM_PATH_MAX_LENGTH)),
19128
+ cwd: optional$2(TrimmedNonEmptyString.check(isMaxLength(FILESYSTEM_PATH_MAX_LENGTH)))
19129
+ });
19130
+ const FilesystemBrowseEntry = Struct({
19131
+ name: TrimmedNonEmptyString,
19132
+ fullPath: TrimmedNonEmptyString
19133
+ });
19134
+ const FilesystemBrowseResult = Struct({
19135
+ parentPath: TrimmedNonEmptyString,
19136
+ entries: Array$1(FilesystemBrowseEntry)
19137
+ });
19138
+ //#endregion
19120
19139
  //#region ../../packages/t3-contracts/src/editor.ts
19121
19140
  const EDITORS = [
19122
19141
  {
@@ -19168,6 +19187,17 @@ const OpenInEditorInput = Struct({
19168
19187
  editor: EditorId
19169
19188
  });
19170
19189
  //#endregion
19190
+ //#region ../../packages/t3-contracts/src/generalChat.ts
19191
+ const GeneralChatConfig = Struct({ workspaceRoot: TrimmedNonEmptyString });
19192
+ const GeneralChatEnsureResult = Struct({
19193
+ projectId: ProjectId,
19194
+ workspaceRoot: TrimmedNonEmptyString,
19195
+ created: Boolean$2
19196
+ });
19197
+ //#endregion
19198
+ //#region ../../packages/t3-contracts/src/agentChat.ts
19199
+ const AgentChatConfig = GeneralChatConfig;
19200
+ //#endregion
19171
19201
  //#region ../../packages/t3-contracts/src/server.ts
19172
19202
  const KeybindingsMalformedConfigIssue = Struct({
19173
19203
  kind: Literal("keybindings.malformed-config"),
@@ -19211,7 +19241,9 @@ const ServerConfig = Struct({
19211
19241
  issues: ServerConfigIssues,
19212
19242
  providers: ServerProviderStatuses,
19213
19243
  availableEditors: Array$1(EditorId),
19214
- projectPolicy: ServerProjectPolicy
19244
+ projectPolicy: ServerProjectPolicy,
19245
+ agentChat: AgentChatConfig,
19246
+ generalChat: GeneralChatConfig
19215
19247
  });
19216
19248
  const ServerUpsertKeybindingResult = Struct({
19217
19249
  keybindings: ResolvedKeybindingsConfig,
@@ -19221,7 +19253,9 @@ const ServerConfigUpdatedPayload = Struct({
19221
19253
  reason: Literals(["keybindings", "projectPolicy"]),
19222
19254
  issues: ServerConfigIssues,
19223
19255
  providers: ServerProviderStatuses,
19224
- projectPolicy: ServerProjectPolicy
19256
+ projectPolicy: ServerProjectPolicy,
19257
+ agentChat: AgentChatConfig,
19258
+ generalChat: GeneralChatConfig
19225
19259
  });
19226
19260
  const ServerProviderUpdatedPayload = Struct({ providers: ServerProviderStatuses });
19227
19261
  //#endregion
@@ -19233,6 +19267,9 @@ const WS_METHODS = {
19233
19267
  projectsEnsure: "projects.ensure",
19234
19268
  projectsSearchEntries: "projects.searchEntries",
19235
19269
  projectsWriteFile: "projects.writeFile",
19270
+ agentChatEnsure: "agentChat.ensure",
19271
+ generalChatEnsure: "generalChat.ensure",
19272
+ filesystemBrowse: "filesystem.browse",
19236
19273
  shellOpenInEditor: "shell.openInEditor",
19237
19274
  gitPull: "git.pull",
19238
19275
  gitStatus: "git.status",
@@ -19292,7 +19329,6 @@ const WS_METHODS = {
19292
19329
  cliStatus: "cli.status",
19293
19330
  cliCheckFreshness: "cli.checkFreshness",
19294
19331
  cliUpdateGlobal: "cli.updateGlobal",
19295
- analyticsGetData: "analytics.getData",
19296
19332
  accountPoolGetStatus: "accountPool.getStatus",
19297
19333
  accountPoolListProfiles: "accountPool.listProfiles",
19298
19334
  accountPoolListSessions: "accountPool.listSessions",
@@ -19332,6 +19368,9 @@ const WebSocketRequestBody = Union([
19332
19368
  tagRequestBody(WS_METHODS.projectsEnsure, ProjectEnsureInput),
19333
19369
  tagRequestBody(WS_METHODS.projectsSearchEntries, ProjectSearchEntriesInput),
19334
19370
  tagRequestBody(WS_METHODS.projectsWriteFile, ProjectWriteFileInput),
19371
+ tagRequestBody(WS_METHODS.agentChatEnsure, Struct({})),
19372
+ tagRequestBody(WS_METHODS.generalChatEnsure, Struct({})),
19373
+ tagRequestBody(WS_METHODS.filesystemBrowse, FilesystemBrowseInput),
19335
19374
  tagRequestBody(WS_METHODS.shellOpenInEditor, OpenInEditorInput),
19336
19375
  tagRequestBody(WS_METHODS.gitPull, GitPullInput),
19337
19376
  tagRequestBody(WS_METHODS.gitStatus, GitStatusInput),
@@ -19433,8 +19472,7 @@ const WebSocketRequestBody = Union([
19433
19472
  tagRequestBody(WS_METHODS.cliInfo, Struct({})),
19434
19473
  tagRequestBody(WS_METHODS.cliStatus, Struct({})),
19435
19474
  tagRequestBody(WS_METHODS.cliCheckFreshness, Struct({})),
19436
- tagRequestBody(WS_METHODS.cliUpdateGlobal, Struct({})),
19437
- tagRequestBody(WS_METHODS.analyticsGetData, Struct({ query: optional$2(Unknown) }))
19475
+ tagRequestBody(WS_METHODS.cliUpdateGlobal, Struct({}))
19438
19476
  ]);
19439
19477
  const WebSocketRequest = Struct({
19440
19478
  id: TrimmedNonEmptyString,
@@ -20433,6 +20471,20 @@ const normalizePersistedJsonColumns = gen(function* () {
20433
20471
  //#region src/persistence/Migrations/020_NormalizePersistedJsonColumns.ts
20434
20472
  var _020_NormalizePersistedJsonColumns_default = normalizePersistedJsonColumns;
20435
20473
  //#endregion
20474
+ //#region src/persistence/Migrations/021_CleanupInvalidProjectionPendingApprovals.ts
20475
+ var _021_CleanupInvalidProjectionPendingApprovals_default = gen(function* () {
20476
+ yield* (yield* SqlClient)`
20477
+ DELETE FROM projection_pending_approvals
20478
+ WHERE request_id NOT IN (
20479
+ SELECT DISTINCT json_extract(payload_json, '$.requestId')
20480
+ FROM projection_thread_activities
20481
+ WHERE kind = 'approval.requested'
20482
+ AND json_valid(payload_json) = 1
20483
+ AND json_extract(payload_json, '$.requestId') IS NOT NULL
20484
+ )
20485
+ `;
20486
+ });
20487
+ //#endregion
20436
20488
  //#region src/persistence/Migrations.ts
20437
20489
  /**
20438
20490
  * Migrations - Migration runner with inline loader
@@ -20473,7 +20525,8 @@ const loader = fromRecord({
20473
20525
  "17_ProjectionThreadsArchivedAt": _017_ProjectionThreadsArchivedAt_default,
20474
20526
  "18_CanonicalizeModelSelections": _018_CanonicalizeModelSelections_default,
20475
20527
  "19_NormalizeProjectionModelSelectionJson": _019_NormalizeProjectionModelSelectionJson_default,
20476
- "20_NormalizePersistedJsonColumns": _020_NormalizePersistedJsonColumns_default
20528
+ "20_NormalizePersistedJsonColumns": _020_NormalizePersistedJsonColumns_default,
20529
+ "21_CleanupInvalidProjectionPendingApprovals": _021_CleanupInvalidProjectionPendingApprovals_default
20477
20530
  });
20478
20531
  /**
20479
20532
  * Migrator run function - no schema dumping needed
@@ -23124,7 +23177,25 @@ const decideOrchestrationCommand = fn("decideOrchestrationCommand")(function* ({
23124
23177
  projectId: command.projectId
23125
23178
  });
23126
23179
  const occurredAt = nowIso$2();
23127
- return {
23180
+ const activeProjectThreads = readModel.threads.filter((thread) => thread.projectId === command.projectId && thread.deletedAt === null);
23181
+ if (activeProjectThreads.length > 0 && command.force !== true) return yield* fail$1(new OrchestrationCommandInvariantError({
23182
+ commandType: command.type,
23183
+ detail: `Project '${command.projectId}' has ${activeProjectThreads.length} thread(s).`
23184
+ }));
23185
+ const threadDeletedEvents = activeProjectThreads.map((thread) => ({
23186
+ ...withEventBase({
23187
+ aggregateKind: "thread",
23188
+ aggregateId: thread.id,
23189
+ occurredAt,
23190
+ commandId: command.commandId
23191
+ }),
23192
+ type: "thread.deleted",
23193
+ payload: {
23194
+ threadId: thread.id,
23195
+ deletedAt: occurredAt
23196
+ }
23197
+ }));
23198
+ const projectDeletedEvent = {
23128
23199
  ...withEventBase({
23129
23200
  aggregateKind: "project",
23130
23201
  aggregateId: command.projectId,
@@ -23137,6 +23208,7 @@ const decideOrchestrationCommand = fn("decideOrchestrationCommand")(function* ({
23137
23208
  deletedAt: occurredAt
23138
23209
  }
23139
23210
  };
23211
+ return [...threadDeletedEvents, projectDeletedEvent];
23140
23212
  }
23141
23213
  case "thread.create":
23142
23214
  yield* requireProject({
@@ -24711,6 +24783,20 @@ const IGNORED_DIRECTORY_NAMES = new Set([
24711
24783
  "out",
24712
24784
  ".cache"
24713
24785
  ]);
24786
+ function expandHomePath(input) {
24787
+ if (input === "~") return os.homedir();
24788
+ if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(os.homedir(), input.slice(2));
24789
+ return input;
24790
+ }
24791
+ function isWindowsAbsolutePath(input) {
24792
+ return /^[a-zA-Z]:[\\/]/.test(input) || /^\\\\[^\\]+\\[^\\]+/.test(input);
24793
+ }
24794
+ function resolveBrowseTarget(input) {
24795
+ if (process.platform !== "win32" && isWindowsAbsolutePath(input.partialPath)) throw new Error("Windows-style paths are only supported on Windows.");
24796
+ const expanded = expandHomePath(input.partialPath);
24797
+ if (path.isAbsolute(expanded) || input.partialPath.startsWith("~")) return path.resolve(expanded);
24798
+ return input.cwd ? path.resolve(expandHomePath(input.cwd), expanded) : path.resolve(expanded);
24799
+ }
24714
24800
  const workspaceIndexCache = /* @__PURE__ */ new Map();
24715
24801
  const inFlightWorkspaceIndexBuilds = /* @__PURE__ */ new Map();
24716
24802
  function toPosixPath(input) {
@@ -25029,6 +25115,22 @@ async function searchWorkspaceEntries(input) {
25029
25115
  truncated: index.truncated || matchedEntryCount > limit
25030
25116
  };
25031
25117
  }
25118
+ async function browseFilesystemEntries(input) {
25119
+ const resolvedInputPath = resolveBrowseTarget(input);
25120
+ const endsWithSeparator = /[\\/]$/.test(input.partialPath) || input.partialPath === "~";
25121
+ const parentPath = endsWithSeparator ? resolvedInputPath : path.dirname(resolvedInputPath);
25122
+ const prefix = endsWithSeparator ? "" : path.basename(resolvedInputPath);
25123
+ const dirents = await fs$1.readdir(parentPath, { withFileTypes: true });
25124
+ const showHidden = endsWithSeparator || prefix.startsWith(".");
25125
+ const lowerPrefix = prefix.toLowerCase();
25126
+ return {
25127
+ parentPath,
25128
+ entries: dirents.filter((dirent) => dirent.isDirectory() && dirent.name.toLowerCase().startsWith(lowerPrefix) && (showHidden || !dirent.name.startsWith("."))).map((dirent) => ({
25129
+ name: dirent.name,
25130
+ fullPath: path.join(parentPath, dirent.name)
25131
+ })).sort((left, right) => left.name.localeCompare(right.name))
25132
+ };
25133
+ }
25032
25134
  //#endregion
25033
25135
  //#region src/provider/Services/ProviderService.ts
25034
25136
  /**
@@ -25586,15 +25688,49 @@ var ProviderCommandReactor = class extends Service()("t3/orchestration/Services/
25586
25688
  */
25587
25689
  var ProviderRuntimeIngestionService = class extends Service()("t3/orchestration/Services/ProviderRuntimeIngestion/ProviderRuntimeIngestionService") {};
25588
25690
  //#endregion
25691
+ //#region src/terminal/Services/Manager.ts
25692
+ var TerminalError = class extends TaggedErrorClass()("TerminalError", {
25693
+ message: String$1,
25694
+ cause: optional$2(Defect)
25695
+ }) {};
25696
+ /**
25697
+ * TerminalManager - Service tag for terminal session orchestration.
25698
+ */
25699
+ var TerminalManager = class extends Service()("t3/terminal/Services/Manager/TerminalManager") {};
25700
+ //#endregion
25589
25701
  //#region src/orchestration/Layers/OrchestrationReactor.ts
25590
25702
  const makeOrchestrationReactor = gen(function* () {
25703
+ const orchestrationEngine = yield* OrchestrationEngineService;
25591
25704
  const providerRuntimeIngestion = yield* ProviderRuntimeIngestionService;
25592
25705
  const providerCommandReactor = yield* ProviderCommandReactor;
25593
25706
  const checkpointReactor = yield* CheckpointReactor;
25707
+ const providerService = yield* ProviderService;
25708
+ const terminalManager = yield* TerminalManager;
25709
+ const startThreadDeletionCleanup = forkScoped(runForEach(orchestrationEngine.streamDomainEvents, (event) => {
25710
+ if (event.type !== "thread.deleted") return void_$1;
25711
+ const threadId = event.payload.threadId;
25712
+ return all([providerService.stopSession({ threadId }).pipe(catchCause((cause) => {
25713
+ if (hasInterruptsOnly(cause)) return failCause(cause);
25714
+ return logWarning$1("failed to stop provider session for deleted thread", {
25715
+ threadId,
25716
+ cause: pretty(cause)
25717
+ });
25718
+ })), terminalManager.close({
25719
+ threadId,
25720
+ deleteHistory: true
25721
+ }).pipe(catchCause((cause) => {
25722
+ if (hasInterruptsOnly(cause)) return failCause(cause);
25723
+ return logWarning$1("failed to close terminals for deleted thread", {
25724
+ threadId,
25725
+ cause: pretty(cause)
25726
+ });
25727
+ }))], { concurrency: "unbounded" }).pipe(asVoid);
25728
+ })).pipe(asVoid);
25594
25729
  return { start: gen(function* () {
25595
25730
  yield* providerRuntimeIngestion.start;
25596
25731
  yield* providerCommandReactor.start;
25597
25732
  yield* checkpointReactor.start;
25733
+ yield* startThreadDeletionCleanup;
25598
25734
  }) };
25599
25735
  });
25600
25736
  const OrchestrationReactorLive = effect(OrchestrationReactor, makeOrchestrationReactor);
@@ -25878,11 +26014,11 @@ const make$5 = gen(function* () {
25878
26014
  },
25879
26015
  createdAt
25880
26016
  });
25881
- const existingSessionThreadId = thread.session && thread.session.status !== "stopped" ? thread.id : null;
26017
+ const activeSession = yield* resolveActiveSession(threadId);
26018
+ const existingSessionThreadId = thread.session && thread.session.status !== "stopped" && activeSession ? thread.id : null;
25882
26019
  if (existingSessionThreadId) {
25883
26020
  const runtimeModeChanged = thread.runtimeMode !== thread.session?.runtimeMode;
25884
26021
  const providerChanged = requestedModelSelection !== void 0 && requestedModelSelection.provider !== currentProvider;
25885
- const activeSession = yield* resolveActiveSession(existingSessionThreadId);
25886
26022
  const sessionModelSwitch = currentProvider === void 0 ? "in-session" : (yield* providerService.getCapabilities(currentProvider)).sessionModelSwitch;
25887
26023
  const modelChanged = requestedModelSelection !== void 0 && requestedModelSelection.model !== activeSession?.model;
25888
26024
  const shouldRestartForModelChange = modelChanged && sessionModelSwitch === "restart-session";
@@ -28429,6 +28565,7 @@ const makeOrchestrationProjectionPipeline = gen(function* () {
28429
28565
  return;
28430
28566
  }
28431
28567
  if (isSome(existingRow) && existingRow.value.status === "resolved") return;
28568
+ if (event.payload.activity.kind !== "approval.requested") return;
28432
28569
  yield* projectionPendingApprovalRepository.upsert({
28433
28570
  requestId,
28434
28571
  threadId: event.payload.threadId,
@@ -28520,43 +28657,6 @@ const makeOrchestrationProjectionPipeline = gen(function* () {
28520
28657
  });
28521
28658
  const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeline, makeOrchestrationProjectionPipeline).pipe(provideMerge(layer$2), provideMerge(ProjectionProjectRepositoryLive), provideMerge(ProjectionThreadRepositoryLive), provideMerge(ProjectionThreadMessageRepositoryLive), provideMerge(ProjectionThreadProposedPlanRepositoryLive), provideMerge(ProjectionThreadActivityRepositoryLive), provideMerge(ProjectionThreadSessionRepositoryLive), provideMerge(ProjectionTurnRepositoryLive), provideMerge(ProjectionCheckpointRepositoryLive), provideMerge(ProjectionPendingApprovalRepositoryLive), provideMerge(ProjectionStateRepositoryLive));
28522
28659
  //#endregion
28523
- //#region ../../packages/contracts/src/settings/auto-roll.ts
28524
- const DEFAULT_AUTO_ROLL_ENABLED = false;
28525
- const DEFAULT_AUTO_ROLL_WARNING_THRESHOLD = 85;
28526
- const DEFAULT_AUTO_ROLL_SWITCH_THRESHOLD = 95;
28527
- const AUTO_ROLL_WARNING_MIN = 50;
28528
- const AUTO_ROLL_WARNING_MAX = 99;
28529
- const AUTO_ROLL_SWITCH_MAX = 100;
28530
- function clampNumber(value, min, max) {
28531
- return Math.min(max, Math.max(min, value));
28532
- }
28533
- function resolveFiniteNumber(value, fallback) {
28534
- return Number.isFinite(value) ? value : fallback;
28535
- }
28536
- function sanitizeAutoRollWarningThreshold(value) {
28537
- return clampNumber(resolveFiniteNumber(value, 85), 50, AUTO_ROLL_WARNING_MAX);
28538
- }
28539
- function sanitizeAutoRollSwitchThreshold(value, warningThreshold) {
28540
- const sanitizedWarning = sanitizeAutoRollWarningThreshold(warningThreshold);
28541
- return clampNumber(resolveFiniteNumber(value, 95), sanitizedWarning + 1, AUTO_ROLL_SWITCH_MAX);
28542
- }
28543
- function sanitizeAutoRollThresholds(warningThreshold, switchThreshold) {
28544
- const sanitizedWarning = sanitizeAutoRollWarningThreshold(warningThreshold);
28545
- return {
28546
- warningThreshold: sanitizedWarning,
28547
- switchThreshold: sanitizeAutoRollSwitchThreshold(switchThreshold, sanitizedWarning)
28548
- };
28549
- }
28550
- function normalizeAutoRollSettings(raw) {
28551
- const enabled = typeof raw?.enabled === "boolean" ? raw.enabled : false;
28552
- const { warningThreshold: normalizedWarning, switchThreshold: normalizedSwitch } = sanitizeAutoRollThresholds(resolveFiniteNumber(typeof raw?.warningThreshold === "number" ? raw.warningThreshold : NaN, 85), resolveFiniteNumber(typeof raw?.switchThreshold === "number" ? raw.switchThreshold : NaN, 95));
28553
- return {
28554
- enabled,
28555
- warningThreshold: normalizedWarning,
28556
- switchThreshold: normalizedSwitch
28557
- };
28558
- }
28559
- //#endregion
28560
28660
  //#region ../../packages/contracts/src/settings/chat-scrollback.ts
28561
28661
  const CHAT_SCROLLBACK_DEFAULT = 200;
28562
28662
  const CHAT_SCROLLBACK_MIN = 50;
@@ -28598,7 +28698,7 @@ const SQLITE_BUSY_MAX_ATTEMPTS = 3;
28598
28698
  const SQLITE_BUSY_RETRY_DELAY_MS = 100;
28599
28699
  const writeQueueByDbPath = /* @__PURE__ */ new Map();
28600
28700
  const initializedDbPaths = /* @__PURE__ */ new Set();
28601
- function isRecord$10(value) {
28701
+ function isRecord$8(value) {
28602
28702
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
28603
28703
  }
28604
28704
  function clone$1(value) {
@@ -28702,7 +28802,7 @@ function resolveAppStorageDbPath(userDataDir) {
28702
28802
  async function readDocument(dbPath, namespace, normalize) {
28703
28803
  return withDatabase(dbPath, (db) => {
28704
28804
  const row = db.prepare(`SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`).get(namespace);
28705
- const parsed = isRecord$10(row) ? safeParseJson(row.valueJson) : null;
28805
+ const parsed = isRecord$8(row) ? safeParseJson(row.valueJson) : null;
28706
28806
  if (parsed === null) return null;
28707
28807
  return normalize(parsed);
28708
28808
  });
@@ -28733,7 +28833,7 @@ async function updateDocument(input) {
28733
28833
  beginImmediate(db);
28734
28834
  try {
28735
28835
  const row = db.prepare(`SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`).get(input.namespace);
28736
- const current = isRecord$10(row) ? input.normalize(safeParseJson(row.valueJson) ?? input.fallback()) : input.fallback();
28836
+ const current = isRecord$8(row) ? input.normalize(safeParseJson(row.valueJson) ?? input.fallback()) : input.fallback();
28737
28837
  const next = input.normalize(input.transform(clone$1(current)));
28738
28838
  db.prepare(`
28739
28839
  INSERT INTO ${APP_STORAGE_TABLE} (namespace, value_json, updated_at)
@@ -28760,7 +28860,7 @@ let configuredUserDataDir = null;
28760
28860
  let appStateCache = null;
28761
28861
  let writeLock = Promise.resolve();
28762
28862
  const writeLockContext = new AsyncLocalStorage();
28763
- function isRecord$9(value) {
28863
+ function isRecord$7(value) {
28764
28864
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
28765
28865
  }
28766
28866
  function clone(value) {
@@ -28838,8 +28938,7 @@ function createDefaultAppState() {
28838
28938
  welcomeResumeStep: null,
28839
28939
  milestones: {
28840
28940
  firstProfileAdded: false,
28841
- secondProfileAdded: false,
28842
- analyticsViewed: false
28941
+ secondProfileAdded: false
28843
28942
  },
28844
28943
  sessionCount: 0,
28845
28944
  nudgeCooldowns: {},
@@ -28888,7 +28987,7 @@ function asString$8(value) {
28888
28987
  }
28889
28988
  function normalizeAppState(raw) {
28890
28989
  const defaults = createDefaultAppState();
28891
- if (!isRecord$9(raw)) return defaults;
28990
+ if (!isRecord$7(raw)) return defaults;
28892
28991
  const merged = clone(deepMerge(defaults, raw));
28893
28992
  merged.schemaVersion = 1;
28894
28993
  if (typeof merged.autoRoll.enabled !== "boolean") merged.autoRoll.enabled = false;
@@ -28927,12 +29026,12 @@ function normalizeAppState(raw) {
28927
29026
  const allowedPreferenceKeys = new Set(Object.keys(defaults.preferences));
28928
29027
  for (const key of Object.keys(merged.preferences)) if (!allowedPreferenceKeys.has(key)) delete merged.preferences[key];
28929
29028
  }
28930
- if (!isRecord$9(merged.runtimeSettings)) merged.runtimeSettings = {};
28931
- if (!isRecord$9(merged.ui)) merged.ui = clone(defaults.ui);
29029
+ if (!isRecord$7(merged.runtimeSettings)) merged.runtimeSettings = {};
29030
+ if (!isRecord$7(merged.ui)) merged.ui = clone(defaults.ui);
28932
29031
  merged.ui.themeMode = merged.ui.themeMode === "light" || merged.ui.themeMode === "dark" ? merged.ui.themeMode : null;
28933
- if (!isRecord$9(merged.ui.layout)) merged.ui.layout = clone(defaults.ui.layout);
29032
+ if (!isRecord$7(merged.ui.layout)) merged.ui.layout = clone(defaults.ui.layout);
28934
29033
  if (typeof merged.ui.layout.sidebarCollapsed !== "boolean") merged.ui.layout.sidebarCollapsed = null;
28935
- if (!isRecord$9(merged.ui.profiles)) merged.ui.profiles = clone(defaults.ui.profiles);
29034
+ if (!isRecord$7(merged.ui.profiles)) merged.ui.profiles = clone(defaults.ui.profiles);
28936
29035
  merged.ui.profiles.viewMode = merged.ui.profiles.viewMode === "cards" || merged.ui.profiles.viewMode === "compact" ? merged.ui.profiles.viewMode : null;
28937
29036
  merged.ui.profiles.sortBy = asString$8(merged.ui.profiles.sortBy);
28938
29037
  merged.ui.profiles.groupBy = asString$8(merged.ui.profiles.groupBy);
@@ -28940,35 +29039,34 @@ function normalizeAppState(raw) {
28940
29039
  merged.ui.profiles.healthFilter = asString$8(merged.ui.profiles.healthFilter);
28941
29040
  merged.ui.profiles.customGroupFilter = asString$8(merged.ui.profiles.customGroupFilter);
28942
29041
  if (typeof merged.ui.profiles.toolbarOpen !== "boolean") merged.ui.profiles.toolbarOpen = null;
28943
- if (!isRecord$9(merged.ui.profiles.collapsedSections)) merged.ui.profiles.collapsedSections = {};
29042
+ if (!isRecord$7(merged.ui.profiles.collapsedSections)) merged.ui.profiles.collapsedSections = {};
28944
29043
  else merged.ui.profiles.collapsedSections = Object.fromEntries(Object.entries(merged.ui.profiles.collapsedSections).flatMap(([key, value]) => {
28945
29044
  const normalizedKey = asString$8(key);
28946
29045
  if (!normalizedKey || typeof value !== "boolean") return [];
28947
29046
  return [[normalizedKey, value]];
28948
29047
  }));
28949
- if (!isRecord$9(merged.ui.onboarding)) merged.ui.onboarding = clone(defaults.ui.onboarding);
29048
+ if (!isRecord$7(merged.ui.onboarding)) merged.ui.onboarding = clone(defaults.ui.onboarding);
28950
29049
  if (typeof merged.ui.onboarding.welcomeCompleted !== "boolean") merged.ui.onboarding.welcomeCompleted = false;
28951
29050
  if (!Number.isFinite(merged.ui.onboarding.welcomeCompletedAt)) merged.ui.onboarding.welcomeCompletedAt = null;
28952
29051
  merged.ui.onboarding.welcomeResumeStep = merged.ui.onboarding.welcomeResumeStep === 2 ? 2 : null;
28953
- if (!isRecord$9(merged.ui.onboarding.milestones)) merged.ui.onboarding.milestones = clone(defaults.ui.onboarding.milestones);
29052
+ if (!isRecord$7(merged.ui.onboarding.milestones)) merged.ui.onboarding.milestones = clone(defaults.ui.onboarding.milestones);
28954
29053
  if (typeof merged.ui.onboarding.milestones.firstProfileAdded !== "boolean") merged.ui.onboarding.milestones.firstProfileAdded = false;
28955
29054
  if (typeof merged.ui.onboarding.milestones.secondProfileAdded !== "boolean") merged.ui.onboarding.milestones.secondProfileAdded = false;
28956
- if (typeof merged.ui.onboarding.milestones.analyticsViewed !== "boolean") merged.ui.onboarding.milestones.analyticsViewed = false;
28957
29055
  if (!Number.isFinite(merged.ui.onboarding.sessionCount)) merged.ui.onboarding.sessionCount = 0;
28958
- if (!isRecord$9(merged.ui.onboarding.nudgeCooldowns)) merged.ui.onboarding.nudgeCooldowns = {};
29056
+ if (!isRecord$7(merged.ui.onboarding.nudgeCooldowns)) merged.ui.onboarding.nudgeCooldowns = {};
28959
29057
  else merged.ui.onboarding.nudgeCooldowns = Object.fromEntries(Object.entries(merged.ui.onboarding.nudgeCooldowns).flatMap(([key, value]) => {
28960
29058
  const normalizedKey = asString$8(key);
28961
29059
  if (!normalizedKey || !Number.isFinite(value)) return [];
28962
29060
  return [[normalizedKey, Number(value)]];
28963
29061
  }));
28964
- if (!isRecord$9(merged.ui.onboarding.nudgeDismissCount)) merged.ui.onboarding.nudgeDismissCount = {};
29062
+ if (!isRecord$7(merged.ui.onboarding.nudgeDismissCount)) merged.ui.onboarding.nudgeDismissCount = {};
28965
29063
  else merged.ui.onboarding.nudgeDismissCount = Object.fromEntries(Object.entries(merged.ui.onboarding.nudgeDismissCount).flatMap(([key, value]) => {
28966
29064
  const normalizedKey = asString$8(key);
28967
29065
  if (!normalizedKey || !Number.isFinite(value)) return [];
28968
29066
  return [[normalizedKey, Number(value)]];
28969
29067
  }));
28970
29068
  if (typeof merged.ui.onboarding.proUnlockedCelebrated !== "boolean") merged.ui.onboarding.proUnlockedCelebrated = false;
28971
- if (!isRecord$9(merged.ui.projectThreadSelections)) merged.ui.projectThreadSelections = {};
29069
+ if (!isRecord$7(merged.ui.projectThreadSelections)) merged.ui.projectThreadSelections = {};
28972
29070
  else merged.ui.projectThreadSelections = Object.fromEntries(Object.entries(merged.ui.projectThreadSelections).flatMap(([projectId, threadId]) => {
28973
29071
  const normalizedProjectId = asString$8(projectId);
28974
29072
  if (!normalizedProjectId) return [];
@@ -28980,8 +29078,8 @@ function normalizeAppState(raw) {
28980
29078
  const allowedUiKeys = new Set(Object.keys(defaults.ui));
28981
29079
  for (const key of Object.keys(merged.ui)) if (!allowedUiKeys.has(key)) delete merged.ui[key];
28982
29080
  }
28983
- if (!isRecord$9(merged.profileDashboard)) merged.profileDashboard = clone(defaults.profileDashboard);
28984
- if (!isRecord$9(merged.profileDashboard.customGroupsByAccountKey)) merged.profileDashboard.customGroupsByAccountKey = {};
29081
+ if (!isRecord$7(merged.profileDashboard)) merged.profileDashboard = clone(defaults.profileDashboard);
29082
+ if (!isRecord$7(merged.profileDashboard.customGroupsByAccountKey)) merged.profileDashboard.customGroupsByAccountKey = {};
28985
29083
  else merged.profileDashboard.customGroupsByAccountKey = Object.fromEntries(Object.entries(merged.profileDashboard.customGroupsByAccountKey).flatMap(([key, value]) => {
28986
29084
  const normalizedKey = asString$8(key);
28987
29085
  const normalizedValue = asString$8(value);
@@ -28992,30 +29090,30 @@ function normalizeAppState(raw) {
28992
29090
  const allowedProfileDashboardKeys = new Set(Object.keys(defaults.profileDashboard));
28993
29091
  for (const key of Object.keys(merged.profileDashboard)) if (!allowedProfileDashboardKeys.has(key)) delete merged.profileDashboard[key];
28994
29092
  }
28995
- const legacyProjectSettingsByPath = isRecord$9(raw.projectSettingsByPath) ? raw.projectSettingsByPath : null;
28996
- if (!isRecord$9(merged.workspaceSettingsByPath)) merged.workspaceSettingsByPath = {};
29093
+ const legacyProjectSettingsByPath = isRecord$7(raw.projectSettingsByPath) ? raw.projectSettingsByPath : null;
29094
+ if (!isRecord$7(merged.workspaceSettingsByPath)) merged.workspaceSettingsByPath = {};
28997
29095
  if (legacyProjectSettingsByPath) merged.workspaceSettingsByPath = {
28998
29096
  ...legacyProjectSettingsByPath,
28999
29097
  ...merged.workspaceSettingsByPath
29000
29098
  };
29001
29099
  delete merged.projectSettingsByPath;
29002
- if (!isRecord$9(merged.conversationCategoriesByCwd)) merged.conversationCategoriesByCwd = {};
29003
- if (!isRecord$9(merged.conversationCategoryAssignmentsByCwd)) merged.conversationCategoryAssignmentsByCwd = {};
29004
- if (!isRecord$9(merged.git)) merged.git = clone(defaults.git);
29100
+ if (!isRecord$7(merged.conversationCategoriesByCwd)) merged.conversationCategoriesByCwd = {};
29101
+ if (!isRecord$7(merged.conversationCategoryAssignmentsByCwd)) merged.conversationCategoryAssignmentsByCwd = {};
29102
+ if (!isRecord$7(merged.git)) merged.git = clone(defaults.git);
29005
29103
  merged.git.commitMessagePrompt = normalizeCommitMessagePrompt(merged.git.commitMessagePrompt) ?? DEFAULT_COMMIT_MESSAGE_PROMPT;
29006
29104
  {
29007
29105
  const allowedGitKeys = new Set(Object.keys(defaults.git));
29008
29106
  for (const key of Object.keys(merged.git)) if (!allowedGitKeys.has(key)) delete merged.git[key];
29009
29107
  }
29010
- if (!isRecord$9(merged.skills)) merged.skills = clone(defaults.skills);
29108
+ if (!isRecord$7(merged.skills)) merged.skills = clone(defaults.skills);
29011
29109
  if (!Array.isArray(merged.skills.sources)) merged.skills.sources = [];
29012
- if (!isRecord$9(merged.skills.installsBySlug)) merged.skills.installsBySlug = {};
29013
- if (!isRecord$9(merged.sync)) merged.sync = clone(defaults.sync);
29110
+ if (!isRecord$7(merged.skills.installsBySlug)) merged.skills.installsBySlug = {};
29111
+ if (!isRecord$7(merged.sync)) merged.sync = clone(defaults.sync);
29014
29112
  merged.sync.lastPushAt = asString$8(merged.sync.lastPushAt);
29015
29113
  merged.sync.lastPullAt = asString$8(merged.sync.lastPullAt);
29016
29114
  merged.sync.lastError = asString$8(merged.sync.lastError);
29017
29115
  merged.sync.remoteUpdatedAt = asString$8(merged.sync.remoteUpdatedAt);
29018
- if (!isRecord$9(merged.analytics)) merged.analytics = isRecord$9(merged.telemetry) ? clone(merged.telemetry) : clone(defaults.analytics);
29116
+ if (!isRecord$7(merged.analytics)) merged.analytics = isRecord$7(merged.telemetry) ? clone(merged.telemetry) : clone(defaults.analytics);
29019
29117
  merged.analytics.anonymousId = asString$8(merged.analytics.anonymousId);
29020
29118
  if (!merged.analytics.anonymousId) {
29021
29119
  const legacyInstallId = asString$8(merged.telemetry?.installId);
@@ -29025,8 +29123,8 @@ function normalizeAppState(raw) {
29025
29123
  merged.analytics.lastFlushAt = asString$8(merged.analytics.lastFlushAt);
29026
29124
  merged.analytics.lastError = asString$8(merged.analytics.lastError);
29027
29125
  if ("telemetry" in merged) delete merged.telemetry;
29028
- if (!isRecord$9(merged.profilesByName)) merged.profilesByName = {};
29029
- if (!isRecord$9(merged.migration)) merged.migration = clone(defaults.migration);
29126
+ if (!isRecord$7(merged.profilesByName)) merged.profilesByName = {};
29127
+ if (!isRecord$7(merged.migration)) merged.migration = clone(defaults.migration);
29030
29128
  if (![
29031
29129
  "pending",
29032
29130
  "pending_local_storage",
@@ -29039,7 +29137,7 @@ function normalizeAppState(raw) {
29039
29137
  return merged;
29040
29138
  }
29041
29139
  function deepMerge(base, patch) {
29042
- if (!isRecord$9(base) || !isRecord$9(patch)) return clone(patch ?? base);
29140
+ if (!isRecord$7(base) || !isRecord$7(patch)) return clone(patch ?? base);
29043
29141
  const next = { ...base };
29044
29142
  for (const [key, patchValue] of Object.entries(patch)) {
29045
29143
  if (patchValue === void 0) continue;
@@ -29048,7 +29146,7 @@ function deepMerge(base, patch) {
29048
29146
  next[key] = clone(patchValue);
29049
29147
  continue;
29050
29148
  }
29051
- if (isRecord$9(currentValue) && isRecord$9(patchValue)) {
29149
+ if (isRecord$7(currentValue) && isRecord$7(patchValue)) {
29052
29150
  next[key] = deepMerge(currentValue, patchValue);
29053
29151
  continue;
29054
29152
  }
@@ -29120,13 +29218,124 @@ async function patchAppState(patch) {
29120
29218
  });
29121
29219
  }
29122
29220
  //#endregion
29221
+ //#region ../../packages/runtime-app-state/src/app/agentChatWorkspace.ts
29222
+ const AGENT_CHAT_WORKSPACE_DIRNAME = "agent-chat-workspace";
29223
+ const AGENT_CHAT_PROJECT_TITLE = "Agent";
29224
+ const AGENT_CHAT_AGENTS_FILENAME = "AGENTS.md";
29225
+ const IS_CASE_INSENSITIVE_PLATFORM$2 = process.platform === "darwin" || process.platform === "win32";
29226
+ function stripTrailingSeparators$2(input) {
29227
+ const trimmed = input.trim();
29228
+ if (trimmed.length === 0) return trimmed;
29229
+ const root = path.parse(trimmed).root;
29230
+ let next = trimmed;
29231
+ while (next.length > root.length && /[\\/]+$/.test(next)) next = next.slice(0, -1);
29232
+ return next;
29233
+ }
29234
+ function canonicalizeWorkspaceRoot$1(input) {
29235
+ const resolved = path.resolve(input.trim());
29236
+ return stripTrailingSeparators$2((() => {
29237
+ try {
29238
+ return realpathSync.native(resolved);
29239
+ } catch {
29240
+ return resolved;
29241
+ }
29242
+ })());
29243
+ }
29244
+ function workspaceRootKey$1(input) {
29245
+ const canonical = canonicalizeWorkspaceRoot$1(input).replaceAll("\\", "/");
29246
+ return IS_CASE_INSENSITIVE_PLATFORM$2 ? canonical.toLowerCase() : canonical;
29247
+ }
29248
+ function resolveAgentChatWorkspaceRoot() {
29249
+ return canonicalizeWorkspaceRoot$1(path.join(getUserDataDir(), AGENT_CHAT_WORKSPACE_DIRNAME));
29250
+ }
29251
+ function resolveAgentChatAgentsPath() {
29252
+ return path.join(resolveAgentChatWorkspaceRoot(), AGENT_CHAT_AGENTS_FILENAME);
29253
+ }
29254
+ function isAgentChatWorkspaceRoot(workspaceRoot) {
29255
+ return workspaceRootKey$1(workspaceRoot) === workspaceRootKey$1(resolveAgentChatWorkspaceRoot());
29256
+ }
29257
+ //#endregion
29258
+ //#region ../../packages/runtime-app-state/src/app/generalChatWorkspace.ts
29259
+ const GENERAL_CHAT_WORKSPACE_DIRNAME = "general-chat-workspace";
29260
+ const GENERAL_CHAT_PROJECT_TITLE = "General Chat";
29261
+ const GENERAL_CHAT_AGENTS_FILENAME = "AGENTS.md";
29262
+ const IS_CASE_INSENSITIVE_PLATFORM$1 = process.platform === "darwin" || process.platform === "win32";
29263
+ function stripTrailingSeparators$1(input) {
29264
+ const trimmed = input.trim();
29265
+ if (trimmed.length === 0) return trimmed;
29266
+ const root = path.parse(trimmed).root;
29267
+ let next = trimmed;
29268
+ while (next.length > root.length && /[\\/]+$/.test(next)) next = next.slice(0, -1);
29269
+ return next;
29270
+ }
29271
+ function canonicalizeWorkspaceRoot(input) {
29272
+ const resolved = path.resolve(input.trim());
29273
+ return stripTrailingSeparators$1((() => {
29274
+ try {
29275
+ return realpathSync.native(resolved);
29276
+ } catch {
29277
+ return resolved;
29278
+ }
29279
+ })());
29280
+ }
29281
+ function workspaceRootKey(input) {
29282
+ const canonical = canonicalizeWorkspaceRoot(input).replaceAll("\\", "/");
29283
+ return IS_CASE_INSENSITIVE_PLATFORM$1 ? canonical.toLowerCase() : canonical;
29284
+ }
29285
+ function resolveGeneralChatWorkspaceRoot() {
29286
+ return canonicalizeWorkspaceRoot(path.join(getUserDataDir(), GENERAL_CHAT_WORKSPACE_DIRNAME));
29287
+ }
29288
+ function resolveGeneralChatAgentsPath() {
29289
+ return path.join(resolveGeneralChatWorkspaceRoot(), GENERAL_CHAT_AGENTS_FILENAME);
29290
+ }
29291
+ function isGeneralChatWorkspaceRoot(workspaceRoot) {
29292
+ return workspaceRootKey(workspaceRoot) === workspaceRootKey(resolveGeneralChatWorkspaceRoot());
29293
+ }
29294
+ //#endregion
29295
+ //#region ../../packages/contracts/src/settings/auto-roll.ts
29296
+ const DEFAULT_AUTO_ROLL_ENABLED = false;
29297
+ const DEFAULT_AUTO_ROLL_WARNING_THRESHOLD = 85;
29298
+ const DEFAULT_AUTO_ROLL_SWITCH_THRESHOLD = 95;
29299
+ const AUTO_ROLL_WARNING_MIN = 50;
29300
+ const AUTO_ROLL_WARNING_MAX = 99;
29301
+ const AUTO_ROLL_SWITCH_MAX = 100;
29302
+ function clampNumber(value, min, max) {
29303
+ return Math.min(max, Math.max(min, value));
29304
+ }
29305
+ function resolveFiniteNumber(value, fallback) {
29306
+ return Number.isFinite(value) ? value : fallback;
29307
+ }
29308
+ function sanitizeAutoRollWarningThreshold(value) {
29309
+ return clampNumber(resolveFiniteNumber(value, 85), 50, AUTO_ROLL_WARNING_MAX);
29310
+ }
29311
+ function sanitizeAutoRollSwitchThreshold(value, warningThreshold) {
29312
+ const sanitizedWarning = sanitizeAutoRollWarningThreshold(warningThreshold);
29313
+ return clampNumber(resolveFiniteNumber(value, 95), sanitizedWarning + 1, AUTO_ROLL_SWITCH_MAX);
29314
+ }
29315
+ function sanitizeAutoRollThresholds(warningThreshold, switchThreshold) {
29316
+ const sanitizedWarning = sanitizeAutoRollWarningThreshold(warningThreshold);
29317
+ return {
29318
+ warningThreshold: sanitizedWarning,
29319
+ switchThreshold: sanitizeAutoRollSwitchThreshold(switchThreshold, sanitizedWarning)
29320
+ };
29321
+ }
29322
+ function normalizeAutoRollSettings(raw) {
29323
+ const enabled = typeof raw?.enabled === "boolean" ? raw.enabled : false;
29324
+ const { warningThreshold: normalizedWarning, switchThreshold: normalizedSwitch } = sanitizeAutoRollThresholds(resolveFiniteNumber(typeof raw?.warningThreshold === "number" ? raw.warningThreshold : NaN, 85), resolveFiniteNumber(typeof raw?.switchThreshold === "number" ? raw.switchThreshold : NaN, 95));
29325
+ return {
29326
+ enabled,
29327
+ warningThreshold: normalizedWarning,
29328
+ switchThreshold: normalizedSwitch
29329
+ };
29330
+ }
29331
+ //#endregion
29123
29332
  //#region ../../packages/runtime-codex/src/codex/settings.ts
29124
29333
  function asString$7(value) {
29125
29334
  if (typeof value !== "string") return null;
29126
29335
  const trimmed = value.trim();
29127
29336
  return trimmed.length > 0 ? trimmed : null;
29128
29337
  }
29129
- function isRecord$8(value) {
29338
+ function isRecord$6(value) {
29130
29339
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
29131
29340
  }
29132
29341
  function parseAutoRoll(raw) {
@@ -29138,7 +29347,7 @@ function parseAutoRoll(raw) {
29138
29347
  }
29139
29348
  }
29140
29349
  function parseStoredLicense(raw) {
29141
- if (!isRecord$8(raw)) return null;
29350
+ if (!isRecord$6(raw)) return null;
29142
29351
  const statusCandidate = asString$7(raw.status);
29143
29352
  const status = [
29144
29353
  "inactive",
@@ -29221,7 +29430,7 @@ async function readCodexSettingsJsonRaw() {
29221
29430
  };
29222
29431
  }
29223
29432
  async function writeCodexSettingsJsonRaw(payload) {
29224
- if (!isRecord$8(payload)) return;
29433
+ if (!isRecord$6(payload)) return;
29225
29434
  const autoRoll = parseAutoRoll(payload.autoRoll ?? payload.auto_roll);
29226
29435
  const license = parseStoredLicense(payload.license);
29227
29436
  await patchAppState({
@@ -29253,11 +29462,11 @@ async function writeCodexSettingsJsonRaw(payload) {
29253
29462
  folderHistory: Array.isArray(payload.folderHistory) ? payload.folderHistory : void 0,
29254
29463
  pinnedPaths: Array.isArray(payload.pinnedPaths) ? payload.pinnedPaths : void 0
29255
29464
  },
29256
- workspaceSettingsByPath: isRecord$8(payload.workspaceSettingsByPath) ? payload.workspaceSettingsByPath : isRecord$8(payload.projectSettingsByPath) ? payload.projectSettingsByPath : void 0,
29257
- conversationCategoriesByCwd: isRecord$8(payload.categoriesByCwd) ? payload.categoriesByCwd : void 0,
29258
- conversationCategoryAssignmentsByCwd: isRecord$8(payload.conversationCategoryByCwd) ? payload.conversationCategoryByCwd : void 0,
29259
- git: isRecord$8(payload.git) ? payload.git : void 0,
29260
- sync: isRecord$8(payload.sync) ? payload.sync : void 0
29465
+ workspaceSettingsByPath: isRecord$6(payload.workspaceSettingsByPath) ? payload.workspaceSettingsByPath : isRecord$6(payload.projectSettingsByPath) ? payload.projectSettingsByPath : void 0,
29466
+ conversationCategoriesByCwd: isRecord$6(payload.categoriesByCwd) ? payload.categoriesByCwd : void 0,
29467
+ conversationCategoryAssignmentsByCwd: isRecord$6(payload.conversationCategoryByCwd) ? payload.conversationCategoryByCwd : void 0,
29468
+ git: isRecord$6(payload.git) ? payload.git : void 0,
29469
+ sync: isRecord$6(payload.sync) ? payload.sync : void 0
29261
29470
  });
29262
29471
  }
29263
29472
  //#endregion
@@ -29654,7 +29863,7 @@ function findActiveProjectByCanonicalRoot(projects, workspaceRoot) {
29654
29863
  function countActiveUniqueProjects(projects) {
29655
29864
  const seen = /* @__PURE__ */ new Set();
29656
29865
  for (const project of projects) {
29657
- if (project.deletedAt !== null) continue;
29866
+ if (project.deletedAt !== null || isGeneralChatWorkspaceRoot(project.workspaceRoot) || isAgentChatWorkspaceRoot(project.workspaceRoot)) continue;
29658
29867
  seen.add(projectRootKey(project.workspaceRoot));
29659
29868
  }
29660
29869
  return seen.size;
@@ -30058,7 +30267,7 @@ function logInfo(...args) {
30058
30267
  }
30059
30268
  //#endregion
30060
30269
  //#region ../../packages/runtime-codex/src/codex/app-server.ts
30061
- function isRecord$7(value) {
30270
+ function isRecord$5(value) {
30062
30271
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
30063
30272
  }
30064
30273
  function asTrimmedString$2(value) {
@@ -30087,10 +30296,10 @@ function isInlineImageValue(value) {
30087
30296
  return normalized.startsWith("data:") || normalized.startsWith("http://") || normalized.startsWith("https://");
30088
30297
  }
30089
30298
  function normalizeSendUserMessageItem(value) {
30090
- if (!isRecord$7(value)) return null;
30299
+ if (!isRecord$5(value)) return null;
30091
30300
  const type = asString$6(value.type).trim();
30092
30301
  if (!type) return null;
30093
- const data = isRecord$7(value.data) ? value.data : {};
30302
+ const data = isRecord$5(value.data) ? value.data : {};
30094
30303
  if (type === "text") {
30095
30304
  const text = asString$6(data.text ?? value.text);
30096
30305
  if (!text.trim()) return null;
@@ -30125,7 +30334,7 @@ function normalizeTurnInputParams(params) {
30125
30334
  if (expectedTurnId && !asString$6(params.expectedTurnId).trim()) normalized.expectedTurnId = expectedTurnId;
30126
30335
  const turnId = asString$6(params.turnId ?? params.turn_id ?? expectedTurnId).trim();
30127
30336
  if (turnId && !asString$6(params.turnId).trim()) normalized.turnId = turnId;
30128
- const providedInput = Array.isArray(params.input) ? params.input.filter((entry) => isRecord$7(entry)) : [];
30337
+ const providedInput = Array.isArray(params.input) ? params.input.filter((entry) => isRecord$5(entry)) : [];
30129
30338
  if (providedInput.length > 0) {
30130
30339
  normalized.input = providedInput;
30131
30340
  return normalized;
@@ -30134,7 +30343,7 @@ function normalizeTurnInputParams(params) {
30134
30343
  if (providedItems.length > 0) {
30135
30344
  const input = providedItems.flatMap((item) => {
30136
30345
  const type = asString$6(item.type).trim();
30137
- const data = isRecord$7(item.data) ? item.data : item;
30346
+ const data = isRecord$5(item.data) ? item.data : item;
30138
30347
  if (type === "text") {
30139
30348
  const text = asString$6(data.text).trim();
30140
30349
  return text ? [{
@@ -30177,7 +30386,7 @@ function pickMethodKind(method, params) {
30177
30386
  const normalized = method.toLowerCase();
30178
30387
  if (normalized.includes("requestapproval")) return "approval";
30179
30388
  if (normalized.includes("requestuserinput")) return "user_input";
30180
- if (isRecord$7(params)) {
30389
+ if (isRecord$5(params)) {
30181
30390
  if ("file_changes" in params || "fileChanges" in params || "grant_root" in params || "grantRoot" in params) return "patch";
30182
30391
  if ("command" in params || "parsed_cmd" in params || "parsedCmd" in params || "cwd" in params) return "exec";
30183
30392
  }
@@ -30379,7 +30588,7 @@ var CodexAppServer = class extends EventEmitter {
30379
30588
  try {
30380
30589
  const response = await this.request("addConversationListener", listenerParams);
30381
30590
  this.addConversationListenerSupported = true;
30382
- return isRecord$7(response) ? response : null;
30591
+ return isRecord$5(response) ? response : null;
30383
30592
  } catch (error) {
30384
30593
  if (isMethodUnavailableError(error, "addConversationListener")) {
30385
30594
  this.addConversationListenerSupported = false;
@@ -30394,7 +30603,7 @@ var CodexAppServer = class extends EventEmitter {
30394
30603
  try {
30395
30604
  const response = await this.request("addConversationListener", listenerParams);
30396
30605
  this.addConversationListenerSupported = true;
30397
- return isRecord$7(response) ? response : null;
30606
+ return isRecord$5(response) ? response : null;
30398
30607
  } catch (resumeError) {
30399
30608
  if (isMethodUnavailableError(resumeError, "addConversationListener")) {
30400
30609
  this.addConversationListenerSupported = false;
@@ -30604,7 +30813,7 @@ var CodexAppServer = class extends EventEmitter {
30604
30813
  listPendingUserInputRequests() {
30605
30814
  return [...this.pendingServerRequests.values()].filter((request) => request.kind === "user_input").map((request) => {
30606
30815
  const workspaceId = asTrimmedString$2(request.params.workspace_id ?? request.params.workspaceId);
30607
- const params = isRecord$7(request.params.params) ? request.params.params : request.params;
30816
+ const params = isRecord$5(request.params.params) ? request.params.params : request.params;
30608
30817
  if (!workspaceId) return null;
30609
30818
  return {
30610
30819
  workspace_id: workspaceId,
@@ -30717,7 +30926,7 @@ var CodexAppServer = class extends EventEmitter {
30717
30926
  this.logParseFailure(line, parseError);
30718
30927
  return true;
30719
30928
  }
30720
- if (!isRecord$7(parsed)) {
30929
+ if (!isRecord$5(parsed)) {
30721
30930
  logWarn("[app-server] unexpected JSON message", parsed);
30722
30931
  return true;
30723
30932
  }
@@ -30806,9 +31015,9 @@ var CodexAppServer = class extends EventEmitter {
30806
31015
  id: request.id,
30807
31016
  kind,
30808
31017
  method: request.method,
30809
- params: isRecord$7(request.params) ? request.params : {}
31018
+ params: isRecord$5(request.params) ? request.params : {}
30810
31019
  });
30811
- const params = isRecord$7(request.params) ? request.params : {};
31020
+ const params = isRecord$5(request.params) ? request.params : {};
30812
31021
  if (kind === "exec") this.emit("codex:exec-command-request", {
30813
31022
  requestToken: token,
30814
31023
  params
@@ -31195,14 +31404,14 @@ async function listParityWorkspaces() {
31195
31404
  //#region src/externalThreadOverrides.ts
31196
31405
  const EXTERNAL_THREAD_OVERRIDES_DOCUMENT = "desktop.external-thread-overrides.v1";
31197
31406
  const EXTERNAL_THREAD_OVERRIDES_VERSION = 1;
31198
- function asRecord$4(value) {
31407
+ function asRecord$3(value) {
31199
31408
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
31200
31409
  }
31201
31410
  function normalizeOptionalTitle(value) {
31202
31411
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
31203
31412
  }
31204
31413
  function sanitizeOverride(value) {
31205
- const record = asRecord$4(value);
31414
+ const record = asRecord$3(value);
31206
31415
  if (!record) return null;
31207
31416
  const suppressed = record.suppressed === true ? true : void 0;
31208
31417
  const localTitle = normalizeOptionalTitle(record.localTitle);
@@ -31243,8 +31452,8 @@ function resolveOverridesDbPath(stateDir) {
31243
31452
  }
31244
31453
  async function readExternalThreadOverrides(stateDir) {
31245
31454
  return await readDocument(resolveOverridesDbPath(stateDir), EXTERNAL_THREAD_OVERRIDES_DOCUMENT, (value) => {
31246
- const record = asRecord$4(value);
31247
- const threadsRecord = asRecord$4(record?.threads) ?? {};
31455
+ const record = asRecord$3(value);
31456
+ const threadsRecord = asRecord$3(record?.threads) ?? {};
31248
31457
  const threads = {};
31249
31458
  for (const [threadId, entry] of Object.entries(threadsRecord)) {
31250
31459
  const sanitized = sanitizeOverride(entry);
@@ -31380,7 +31589,7 @@ let externalCodexThreadSyncWatcherSettleTimer = null;
31380
31589
  let externalCodexThreadSyncWatcherPendingTrigger = null;
31381
31590
  const externalSyncAppServerLeaseCount = /* @__PURE__ */ new Map();
31382
31591
  let externalCodexThreadSyncRefreshQueue = null;
31383
- function asRecord$3(value) {
31592
+ function asRecord$2(value) {
31384
31593
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
31385
31594
  }
31386
31595
  function clearSharedExternalSyncAppServerIdleTimer() {
@@ -31648,9 +31857,9 @@ async function readImportedVisibleMessageTimeline(thread) {
31648
31857
  } catch {
31649
31858
  continue;
31650
31859
  }
31651
- const record = asRecord$3(entry);
31860
+ const record = asRecord$2(entry);
31652
31861
  if (!record || asTrimmedString$1(record.type) !== "event_msg") continue;
31653
- const payload = asRecord$3(record.payload);
31862
+ const payload = asRecord$2(record.payload);
31654
31863
  if (!payload) continue;
31655
31864
  const timestamp = firstNonEmptyString(record.timestamp, payload.timestamp, payload.createdAt, payload.created_at);
31656
31865
  if (!timestamp || !Number.isFinite(Date.parse(timestamp))) continue;
@@ -31677,16 +31886,16 @@ function takeImportedVisibleMessageTimestamp(timeline, role) {
31677
31886
  return nextTimestamp;
31678
31887
  }
31679
31888
  function listThreadSummariesFromResponse(payload) {
31680
- const root = asRecord$3(payload);
31681
- const result = asRecord$3(root?.result) ?? root;
31889
+ const root = asRecord$2(payload);
31890
+ const result = asRecord$2(root?.result) ?? root;
31682
31891
  return {
31683
- threads: (Array.isArray(result?.data) ? result.data : []).map((entry) => asRecord$3(entry)).filter((entry) => Boolean(asTrimmedString$1(entry?.id))),
31892
+ threads: (Array.isArray(result?.data) ? result.data : []).map((entry) => asRecord$2(entry)).filter((entry) => Boolean(asTrimmedString$1(entry?.id))),
31684
31893
  nextCursor: firstNonEmptyString(result?.nextCursor, result?.next_cursor)
31685
31894
  };
31686
31895
  }
31687
31896
  function extractLegacyThread(payload) {
31688
- const root = asRecord$3(payload);
31689
- const thread = asRecord$3((asRecord$3(root?.result) ?? root)?.thread) ?? asRecord$3(root?.thread);
31897
+ const root = asRecord$2(payload);
31898
+ const thread = asRecord$2((asRecord$2(root?.result) ?? root)?.thread) ?? asRecord$2(root?.thread);
31690
31899
  return thread && asTrimmedString$1(thread.id) ? thread : null;
31691
31900
  }
31692
31901
  function normalizeProjectScriptIcon(value) {
@@ -31803,19 +32012,19 @@ const MODEL_KEYS = [
31803
32012
  "model_name"
31804
32013
  ];
31805
32014
  function extractModelFromRecord(record) {
31806
- const payload = asRecord$3(record.payload);
32015
+ const payload = asRecord$2(record.payload);
31807
32016
  const containers = [
31808
32017
  record,
31809
32018
  payload,
31810
- asRecord$3(payload?.info),
31811
- asRecord$3(record.info),
31812
- asRecord$3(record.metadata),
31813
- asRecord$3(record.context),
31814
- asRecord$3(record.turnContext),
31815
- asRecord$3(record.turn_context),
31816
- asRecord$3(record.params),
31817
- asRecord$3(record.settings),
31818
- asRecord$3(record.config)
32019
+ asRecord$2(payload?.info),
32020
+ asRecord$2(record.info),
32021
+ asRecord$2(record.metadata),
32022
+ asRecord$2(record.context),
32023
+ asRecord$2(record.turnContext),
32024
+ asRecord$2(record.turn_context),
32025
+ asRecord$2(record.params),
32026
+ asRecord$2(record.settings),
32027
+ asRecord$2(record.config)
31819
32028
  ].filter((value) => value !== null);
31820
32029
  for (const container of containers) {
31821
32030
  const value = pickString(container, MODEL_KEYS);
@@ -31826,13 +32035,13 @@ function extractModelFromRecord(record) {
31826
32035
  function resolveImportedModel(thread) {
31827
32036
  const turns = Array.isArray(thread.turns) ? thread.turns : [];
31828
32037
  for (let turnIndex = turns.length - 1; turnIndex >= 0; turnIndex -= 1) {
31829
- const turn = asRecord$3(turns[turnIndex]);
32038
+ const turn = asRecord$2(turns[turnIndex]);
31830
32039
  if (!turn) continue;
31831
32040
  const turnLevel = extractModelFromRecord(turn);
31832
32041
  if (turnLevel) return turnLevel;
31833
32042
  const items = Array.isArray(turn.items) ? turn.items : [];
31834
32043
  for (let itemIndex = items.length - 1; itemIndex >= 0; itemIndex -= 1) {
31835
- const item = asRecord$3(items[itemIndex]);
32044
+ const item = asRecord$2(items[itemIndex]);
31836
32045
  if (!item) continue;
31837
32046
  const model = extractModelFromRecord(item);
31838
32047
  if (model) return model;
@@ -31847,7 +32056,7 @@ function resolveThreadTitle(thread) {
31847
32056
  return firstNonEmptyString(thread.name, thread.preview, thread.title)?.split(/\r?\n/, 1)[0]?.trim()?.slice(0, 140) || "Imported thread";
31848
32057
  }
31849
32058
  function readLegacyContentRecord(value) {
31850
- return asRecord$3(value);
32059
+ return asRecord$2(value);
31851
32060
  }
31852
32061
  function readLegacyContentText(item) {
31853
32062
  const data = readLegacyContentRecord(item.data);
@@ -31939,7 +32148,7 @@ async function parseUserMessageContent(input) {
31939
32148
  const attachments = [];
31940
32149
  let imageIndex = 0;
31941
32150
  for (const entry of content) {
31942
- const item = asRecord$3(entry);
32151
+ const item = asRecord$2(entry);
31943
32152
  if (!item) continue;
31944
32153
  const type = asTrimmedString$1(item.type);
31945
32154
  if (type === "text") {
@@ -32010,13 +32219,13 @@ async function buildThreadImportArtifacts(input) {
32010
32219
  let latestArtifactUpdatedAt = createdAt;
32011
32220
  let latestUpdatedAt = summaryUpdatedAt;
32012
32221
  for (const [turnIndex, turnEntry] of turns.entries()) {
32013
- const turn = asRecord$3(turnEntry);
32222
+ const turn = asRecord$2(turnEntry);
32014
32223
  if (!turn) continue;
32015
32224
  const turnIdRaw = firstNonEmptyString(turn.id, turn.turnId, turn.turn_id);
32016
32225
  const turnId = turnIdRaw ? TurnId.makeUnsafe(turnIdRaw) : null;
32017
32226
  const items = Array.isArray(turn.items) ? turn.items : [];
32018
32227
  for (const [itemIndex, itemEntry] of items.entries()) {
32019
- const item = asRecord$3(itemEntry);
32228
+ const item = asRecord$2(itemEntry);
32020
32229
  if (!item) continue;
32021
32230
  const itemId = firstNonEmptyString(item.id) ?? `${turnIndex + 1}-${itemIndex + 1}`;
32022
32231
  const type = asTrimmedString$1(item.type);
@@ -32239,7 +32448,7 @@ async function isDirectory(targetPath) {
32239
32448
  async function readImportMarker(stateDir) {
32240
32449
  const dbPath = resolveStateDbPath(stateDir);
32241
32450
  const stored = await readDocument(dbPath, EXTERNAL_SYNC_MARKER_DOCUMENT, (value) => {
32242
- const version = asFiniteNumber(asRecord$3(value)?.version);
32451
+ const version = asFiniteNumber(asRecord$2(value)?.version);
32243
32452
  if (version === null || version <= 0) return null;
32244
32453
  return { version };
32245
32454
  });
@@ -32247,7 +32456,7 @@ async function readImportMarker(stateDir) {
32247
32456
  const markerPath = path.join(stateDir, EXTERNAL_SYNC_MARKER_FILE);
32248
32457
  try {
32249
32458
  const raw = await fs$1.readFile(markerPath, "utf8");
32250
- const version = asFiniteNumber(asRecord$3(JSON.parse(raw))?.version);
32459
+ const version = asFiniteNumber(asRecord$2(JSON.parse(raw))?.version);
32251
32460
  if (version === null || version <= 0) return null;
32252
32461
  const marker = { version };
32253
32462
  await writeDocument(dbPath, EXTERNAL_SYNC_MARKER_DOCUMENT, marker);
@@ -32327,7 +32536,7 @@ function hasImportedThreadArtifacts(state) {
32327
32536
  return state.messageIds.size > 0 || state.activityIds.size > 0 || state.planIds.size > 0;
32328
32537
  }
32329
32538
  function readProviderThreadIdFromResumeCursor(resumeCursor) {
32330
- const cursor = asRecord$3(resumeCursor);
32539
+ const cursor = asRecord$2(resumeCursor);
32331
32540
  return firstNonEmptyString(cursor?.threadId, cursor?.thread_id, cursor?.conversationId, cursor?.conversation_id) ?? null;
32332
32541
  }
32333
32542
  function resolveLegacyThreadReadIds(input) {
@@ -32779,7 +32988,7 @@ const runExternalCodexThreadSync = gen(function* () {
32779
32988
  }
32780
32989
  const syncTargets = [];
32781
32990
  for (const project of readModel.projects) {
32782
- if (project.deletedAt !== null) continue;
32991
+ if (project.deletedAt !== null || isGeneralChatWorkspaceRoot(project.workspaceRoot) || isAgentChatWorkspaceRoot(project.workspaceRoot)) continue;
32783
32992
  const workspaceRoot = project.workspaceRoot;
32784
32993
  const rootKey = projectRootKey(workspaceRoot);
32785
32994
  if (projectIdByRootKey.has(rootKey)) continue;
@@ -36651,7 +36860,12 @@ const makeProviderService = (options) => gen(function* () {
36651
36860
  allowRecovery: false
36652
36861
  });
36653
36862
  if (routed.isActive) yield* routed.adapter.stopSession(routed.threadId);
36654
- yield* directory.remove(input.threadId);
36863
+ const existingBinding = yield* directory.getBinding(input.threadId);
36864
+ if (isSome(existingBinding)) yield* directory.upsert({
36865
+ ...existingBinding.value,
36866
+ status: "stopped",
36867
+ runtimePayload: { activeTurnId: null }
36868
+ });
36655
36869
  });
36656
36870
  const listSessions = () => gen(function* () {
36657
36871
  const activeSessions = (yield* forEach(adapters, (adapter) => adapter.listSessions())).flatMap((sessions) => sessions);
@@ -36734,12 +36948,12 @@ function decodeProviderKind(providerName, operation) {
36734
36948
  detail: `Unknown persisted provider '${providerName}'.`
36735
36949
  }));
36736
36950
  }
36737
- function isRecord$6(value) {
36951
+ function isRecord$4(value) {
36738
36952
  return value !== null && typeof value === "object" && !Array.isArray(value);
36739
36953
  }
36740
36954
  function mergeRuntimePayload(existing, next) {
36741
36955
  if (next === void 0) return existing ?? null;
36742
- if (isRecord$6(existing) && isRecord$6(next)) return {
36956
+ if (isRecord$4(existing) && isRecord$4(next)) return {
36743
36957
  ...existing,
36744
36958
  ...next
36745
36959
  };
@@ -36892,16 +37106,6 @@ var PtySpawnError = class extends TaggedErrorClass()("PtySpawnError", {
36892
37106
  */
36893
37107
  var PtyAdapter = class extends Service()("t3/terminal/Services/PTY/PtyAdapter") {};
36894
37108
  //#endregion
36895
- //#region src/terminal/Services/Manager.ts
36896
- var TerminalError = class extends TaggedErrorClass()("TerminalError", {
36897
- message: String$1,
36898
- cause: optional$2(Defect)
36899
- }) {};
36900
- /**
36901
- * TerminalManager - Service tag for terminal session orchestration.
36902
- */
36903
- var TerminalManager = class extends Service()("t3/terminal/Services/Manager/TerminalManager") {};
36904
- //#endregion
36905
37109
  //#region src/terminal/Layers/Manager.ts
36906
37110
  const DEFAULT_HISTORY_LINE_LIMIT = 5e3;
36907
37111
  const DEFAULT_PERSIST_DEBOUNCE_MS = 40;
@@ -37857,6 +38061,10 @@ const DEFAULT_KEYBINDINGS = [
37857
38061
  command: "diff.toggle",
37858
38062
  when: "!terminalFocus"
37859
38063
  },
38064
+ {
38065
+ key: "mod+k",
38066
+ command: "commandPalette.toggle"
38067
+ },
37860
38068
  {
37861
38069
  key: "mod+n",
37862
38070
  command: "chat.new",
@@ -40719,9 +40927,8 @@ function makeServerRuntimeServicesLayer() {
40719
40927
  const runtimeIngestionLayer = ProviderRuntimeIngestionLive.pipe(provideMerge(runtimeServicesLayer));
40720
40928
  const providerCommandReactorLayer = ProviderCommandReactorLive.pipe(provideMerge(runtimeServicesLayer), provideMerge(gitCoreLayer), provideMerge(textGenerationLayer));
40721
40929
  const checkpointReactorLayer = CheckpointReactorLive.pipe(provideMerge(runtimeServicesLayer));
40722
- const orchestrationReactorLayer = OrchestrationReactorLive.pipe(provideMerge(runtimeIngestionLayer), provideMerge(providerCommandReactorLayer), provideMerge(checkpointReactorLayer));
40723
40930
  const terminalLayer = TerminalManagerLive.pipe(provide$1(typeof Bun !== "undefined" && process.platform !== "win32" ? BunPtyAdapterLive : NodePtyAdapterLive));
40724
- return mergeAll(orchestrationReactorLayer, gitCoreLayer, GitManagerLive.pipe(provideMerge(gitCoreLayer), provideMerge(GitHubCliLive), provideMerge(textGenerationLayer)), terminalLayer, KeybindingsLive).pipe(provideMerge(layer$2));
40931
+ return mergeAll(OrchestrationReactorLive.pipe(provideMerge(runtimeIngestionLayer), provideMerge(providerCommandReactorLayer), provideMerge(checkpointReactorLayer), provideMerge(terminalLayer)), gitCoreLayer, GitManagerLive.pipe(provideMerge(gitCoreLayer), provideMerge(GitHubCliLive), provideMerge(textGenerationLayer)), terminalLayer, KeybindingsLive).pipe(provideMerge(layer$2));
40725
40932
  }
40726
40933
  //#endregion
40727
40934
  //#region src/provider/Services/ProviderHealth.ts
@@ -41049,7 +41256,7 @@ const LEGACY_APP_SETTINGS_KEYS = new Set([
41049
41256
  "activeRemoteBackendId",
41050
41257
  "keepDaemonRunningAfterAppClose"
41051
41258
  ]);
41052
- function asRecord$2(value) {
41259
+ function asRecord$1(value) {
41053
41260
  return value && typeof value === "object" ? value : {};
41054
41261
  }
41055
41262
  function stripLegacyAppSettingsKeys(settings) {
@@ -41063,10 +41270,10 @@ function stripLegacyAppSettingsKeys(settings) {
41063
41270
  return changed ? next : settings;
41064
41271
  }
41065
41272
  async function readAppSettings() {
41066
- return stripLegacyAppSettingsKeys(asRecord$2((await getAppState()).runtimeSettings));
41273
+ return stripLegacyAppSettingsKeys(asRecord$1((await getAppState()).runtimeSettings));
41067
41274
  }
41068
41275
  async function writeAppSettings(settings, onUpdated) {
41069
- const nextSettings = stripLegacyAppSettingsKeys(asRecord$2(settings));
41276
+ const nextSettings = stripLegacyAppSettingsKeys(asRecord$1(settings));
41070
41277
  await updateAppState((current) => ({
41071
41278
  ...current,
41072
41279
  runtimeSettings: nextSettings
@@ -42711,7 +42918,7 @@ const FALLBACK_FEATURE_KEYS = [
42711
42918
  ];
42712
42919
  let metadataCache = null;
42713
42920
  let metadataCacheAt = 0;
42714
- function isRecord$5(value) {
42921
+ function isRecord$3(value) {
42715
42922
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
42716
42923
  }
42717
42924
  function uniqueSorted(values) {
@@ -42782,14 +42989,14 @@ function parseFeatureCatalog(output) {
42782
42989
  }
42783
42990
  function parseSchemaKeys(schemaRaw) {
42784
42991
  const parsed = JSON.parse(schemaRaw);
42785
- if (!isRecord$5(parsed)) return {
42992
+ if (!isRecord$3(parsed)) return {
42786
42993
  topLevelKeys: FALLBACK_SCHEMA_TOP_LEVEL_KEYS,
42787
42994
  featureKeys: FALLBACK_FEATURE_KEYS
42788
42995
  };
42789
- const properties = isRecord$5(parsed.properties) ? parsed.properties : {};
42996
+ const properties = isRecord$3(parsed.properties) ? parsed.properties : {};
42790
42997
  const topLevelKeys = uniqueSorted(Object.keys(properties));
42791
- const features = isRecord$5(properties.features) ? properties.features : {};
42792
- const featureProperties = isRecord$5(features.properties) ? features.properties : {};
42998
+ const features = isRecord$3(properties.features) ? properties.features : {};
42999
+ const featureProperties = isRecord$3(features.properties) ? features.properties : {};
42793
43000
  const featureKeys = uniqueSorted(Object.keys(featureProperties));
42794
43001
  return {
42795
43002
  topLevelKeys: topLevelKeys.length > 0 ? topLevelKeys : FALLBACK_SCHEMA_TOP_LEVEL_KEYS,
@@ -45712,7 +45919,7 @@ var AccountPoolTurnFailure = class extends Error {
45712
45919
  this.providerThreadId = input.providerThreadId;
45713
45920
  }
45714
45921
  };
45715
- function isRecord$4(value) {
45922
+ function isRecord$2(value) {
45716
45923
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
45717
45924
  }
45718
45925
  function asString$1(value) {
@@ -45846,7 +46053,7 @@ function createDefaultStore() {
45846
46053
  };
45847
46054
  }
45848
46055
  function normalizeApiKeyRecord(id, value) {
45849
- const record = isRecord$4(value) ? value : null;
46056
+ const record = isRecord$2(value) ? value : null;
45850
46057
  const tokenHash = asString$1(record?.tokenHash);
45851
46058
  const tokenPreview = asString$1(record?.tokenPreview);
45852
46059
  const createdAt = normalizeIsoString(record?.createdAt);
@@ -45861,7 +46068,7 @@ function normalizeApiKeyRecord(id, value) {
45861
46068
  };
45862
46069
  }
45863
46070
  function normalizeLegacySessionRecord(id, value) {
45864
- const record = isRecord$4(value) ? value : null;
46071
+ const record = isRecord$2(value) ? value : null;
45865
46072
  const profileName = asString$1(record?.profileName);
45866
46073
  const threadId = asString$1(record?.threadId);
45867
46074
  const createdAt = normalizeIsoString(record?.createdAt);
@@ -45885,19 +46092,19 @@ function normalizeLegacySessionRecord(id, value) {
45885
46092
  };
45886
46093
  }
45887
46094
  function normalizeLegacyStore(value) {
45888
- const record = isRecord$4(value) ? value : null;
46095
+ const record = isRecord$2(value) ? value : null;
45889
46096
  const apiKeysById = {};
45890
- for (const [id, keyValue] of Object.entries(isRecord$4(record?.apiKeysById) ? record.apiKeysById : {})) {
46097
+ for (const [id, keyValue] of Object.entries(isRecord$2(record?.apiKeysById) ? record.apiKeysById : {})) {
45891
46098
  const normalized = normalizeApiKeyRecord(id, keyValue);
45892
46099
  if (normalized) apiKeysById[id] = normalized;
45893
46100
  }
45894
46101
  const sessionsById = {};
45895
- for (const [id, sessionValue] of Object.entries(isRecord$4(record?.sessionsById) ? record.sessionsById : {})) {
46102
+ for (const [id, sessionValue] of Object.entries(isRecord$2(record?.sessionsById) ? record.sessionsById : {})) {
45896
46103
  const normalized = normalizeLegacySessionRecord(id, sessionValue);
45897
46104
  if (normalized) sessionsById[id] = normalized;
45898
46105
  }
45899
46106
  const responseIndex = {};
45900
- for (const [responseId, sessionId] of Object.entries(isRecord$4(record?.responseIndex) ? record.responseIndex : {})) {
46107
+ for (const [responseId, sessionId] of Object.entries(isRecord$2(record?.responseIndex) ? record.responseIndex : {})) {
45901
46108
  const normalizedSessionId = asString$1(sessionId);
45902
46109
  if (normalizedSessionId) responseIndex[responseId] = normalizedSessionId;
45903
46110
  }
@@ -45910,7 +46117,7 @@ function normalizeLegacyStore(value) {
45910
46117
  };
45911
46118
  }
45912
46119
  function normalizeTranscriptEntry(value) {
45913
- const record = isRecord$4(value) ? value : null;
46120
+ const record = isRecord$2(value) ? value : null;
45914
46121
  const role = asString$1(record?.role);
45915
46122
  const createdAt = normalizeIsoString(record?.createdAt);
45916
46123
  if (role !== "user" && role !== "assistant" || !createdAt) return null;
@@ -45922,7 +46129,7 @@ function normalizeTranscriptEntry(value) {
45922
46129
  };
45923
46130
  }
45924
46131
  function normalizeSessionRecord(id, value) {
45925
- const record = isRecord$4(value) ? value : null;
46132
+ const record = isRecord$2(value) ? value : null;
45926
46133
  const activeSegmentId = asString$1(record?.activeSegmentId);
45927
46134
  const createdAt = normalizeIsoString(record?.createdAt);
45928
46135
  const lastUsedAt = normalizeIsoString(record?.lastUsedAt);
@@ -45959,7 +46166,7 @@ function normalizeSessionRecord(id, value) {
45959
46166
  };
45960
46167
  }
45961
46168
  function normalizeSegmentRecord(id, value) {
45962
- const record = isRecord$4(value) ? value : null;
46169
+ const record = isRecord$2(value) ? value : null;
45963
46170
  const sessionId = asString$1(record?.sessionId);
45964
46171
  const profileName = asString$1(record?.profileName);
45965
46172
  const threadId = asString$1(record?.threadId);
@@ -45980,7 +46187,7 @@ function normalizeSegmentRecord(id, value) {
45980
46187
  };
45981
46188
  }
45982
46189
  function normalizeProfileStateRecord(value) {
45983
- const record = isRecord$4(value) ? value : null;
46190
+ const record = isRecord$2(value) ? value : null;
45984
46191
  return {
45985
46192
  cooldownUntil: normalizeIsoString(record?.cooldownUntil),
45986
46193
  lastFailureClass: normalizeFailureClass(record?.lastFailureClass),
@@ -45989,7 +46196,7 @@ function normalizeProfileStateRecord(value) {
45989
46196
  };
45990
46197
  }
45991
46198
  function normalizeResponseIndexRecord(value) {
45992
- const record = isRecord$4(value) ? value : null;
46199
+ const record = isRecord$2(value) ? value : null;
45993
46200
  const sessionId = asString$1(record?.sessionId);
45994
46201
  const segmentId = asString$1(record?.segmentId);
45995
46202
  const createdAt = normalizeIsoString(record?.createdAt) ?? (/* @__PURE__ */ new Date(0)).toISOString();
@@ -46001,30 +46208,30 @@ function normalizeResponseIndexRecord(value) {
46001
46208
  };
46002
46209
  }
46003
46210
  function normalizeStore(value) {
46004
- const record = isRecord$4(value) ? value : null;
46211
+ const record = isRecord$2(value) ? value : null;
46005
46212
  const apiKeysById = {};
46006
- for (const [id, keyValue] of Object.entries(isRecord$4(record?.apiKeysById) ? record.apiKeysById : {})) {
46213
+ for (const [id, keyValue] of Object.entries(isRecord$2(record?.apiKeysById) ? record.apiKeysById : {})) {
46007
46214
  const normalized = normalizeApiKeyRecord(id, keyValue);
46008
46215
  if (normalized) apiKeysById[id] = normalized;
46009
46216
  }
46010
46217
  const sessionsById = {};
46011
- for (const [id, sessionValue] of Object.entries(isRecord$4(record?.sessionsById) ? record.sessionsById : {})) {
46218
+ for (const [id, sessionValue] of Object.entries(isRecord$2(record?.sessionsById) ? record.sessionsById : {})) {
46012
46219
  const normalized = normalizeSessionRecord(id, sessionValue);
46013
46220
  if (normalized) sessionsById[id] = normalized;
46014
46221
  }
46015
46222
  const segmentsById = {};
46016
- for (const [id, segmentValue] of Object.entries(isRecord$4(record?.segmentsById) ? record.segmentsById : {})) {
46223
+ for (const [id, segmentValue] of Object.entries(isRecord$2(record?.segmentsById) ? record.segmentsById : {})) {
46017
46224
  const normalized = normalizeSegmentRecord(id, segmentValue);
46018
46225
  if (normalized) segmentsById[id] = normalized;
46019
46226
  }
46020
46227
  const profilesByName = {};
46021
- for (const [name, profileValue] of Object.entries(isRecord$4(record?.profilesByName) ? record.profilesByName : {})) {
46228
+ for (const [name, profileValue] of Object.entries(isRecord$2(record?.profilesByName) ? record.profilesByName : {})) {
46022
46229
  const normalizedName = asString$1(name);
46023
46230
  if (!normalizedName) continue;
46024
46231
  profilesByName[normalizedName] = normalizeProfileStateRecord(profileValue);
46025
46232
  }
46026
46233
  const responseIndex = {};
46027
- for (const [responseId, responseValue] of Object.entries(isRecord$4(record?.responseIndex) ? record.responseIndex : {})) {
46234
+ for (const [responseId, responseValue] of Object.entries(isRecord$2(record?.responseIndex) ? record.responseIndex : {})) {
46028
46235
  const normalized = normalizeResponseIndexRecord(responseValue);
46029
46236
  if (normalized) responseIndex[responseId] = normalized;
46030
46237
  }
@@ -46149,7 +46356,7 @@ function extractTextAndImages(value) {
46149
46356
  text: value.trim() || null,
46150
46357
  images: []
46151
46358
  };
46152
- const record = isRecord$4(value) ? value : null;
46359
+ const record = isRecord$2(value) ? value : null;
46153
46360
  const arrayValue = Array.isArray(value) ? value : Array.isArray(record?.content) ? record?.content : null;
46154
46361
  const directText = asString$1(record?.text) ?? asString$1(record?.content);
46155
46362
  const directImage = asString$1(record?.image_url) ?? asString$1(record?.url) ?? asString$1(record?.imageUrl);
@@ -46164,7 +46371,7 @@ function extractTextAndImages(value) {
46164
46371
  if (entry.trim().length > 0) texts.push(entry.trim());
46165
46372
  continue;
46166
46373
  }
46167
- const part = isRecord$4(entry) ? entry : null;
46374
+ const part = isRecord$2(entry) ? entry : null;
46168
46375
  if (!part) continue;
46169
46376
  const partType = asString$1(part.type) ?? "text";
46170
46377
  const text = asString$1(part.text) ?? asString$1(part.content) ?? asString$1(part.value);
@@ -46185,7 +46392,7 @@ function assistantLabel(value) {
46185
46392
  return normalized && normalized.length > 0 ? normalized : null;
46186
46393
  }
46187
46394
  function isAssistantLikeRecord(value) {
46188
- const record = isRecord$4(value) ? value : null;
46395
+ const record = isRecord$2(value) ? value : null;
46189
46396
  if (!record) return false;
46190
46397
  return [
46191
46398
  assistantLabel(record.role),
@@ -46198,7 +46405,7 @@ function collectTextFragments(value, depth = 0) {
46198
46405
  if (depth > 6) return [];
46199
46406
  if (typeof value === "string") return value.length > 0 ? [value] : [];
46200
46407
  if (Array.isArray(value)) return value.flatMap((entry) => collectTextFragments(entry, depth + 1));
46201
- const record = isRecord$4(value) ? value : null;
46408
+ const record = isRecord$2(value) ? value : null;
46202
46409
  if (!record) return [];
46203
46410
  return [
46204
46411
  asString$1(record.text),
@@ -46227,7 +46434,7 @@ function extractAssistantTextSnapshot(value, depth = 0) {
46227
46434
  }
46228
46435
  return null;
46229
46436
  }
46230
- const record = isRecord$4(value) ? value : null;
46437
+ const record = isRecord$2(value) ? value : null;
46231
46438
  if (!record) return null;
46232
46439
  const nestedMatch = extractAssistantTextSnapshot(record.turn, depth + 1) ?? extractAssistantTextSnapshot(record.response, depth + 1) ?? extractAssistantTextSnapshot(record.result, depth + 1) ?? extractAssistantTextSnapshot(record.item, depth + 1) ?? extractAssistantTextSnapshot(record.items, depth + 1) ?? extractAssistantTextSnapshot(record.messages, depth + 1) ?? extractAssistantTextSnapshot(record.output, depth + 1) ?? extractAssistantTextSnapshot(record.content, depth + 1);
46233
46440
  if (nestedMatch) return nestedMatch;
@@ -46246,7 +46453,7 @@ function prepareTurnInput(body, fallbackModel) {
46246
46453
  looseText = [looseText, entry.trim()].filter(Boolean).join("\n\n") || null;
46247
46454
  continue;
46248
46455
  }
46249
- const record = isRecord$4(entry) ? entry : null;
46456
+ const record = isRecord$2(entry) ? entry : null;
46250
46457
  if (!record) continue;
46251
46458
  const entryRole = asString$1(record.role);
46252
46459
  const entryType = asString$1(record.type);
@@ -46263,7 +46470,7 @@ function prepareTurnInput(body, fallbackModel) {
46263
46470
  if (text) looseText = [looseText, text].filter(Boolean).join("\n\n") || null;
46264
46471
  looseImages.push(...images);
46265
46472
  }
46266
- else if (isRecord$4(input)) {
46473
+ else if (isRecord$2(input)) {
46267
46474
  const { text, images } = extractTextAndImages(input);
46268
46475
  looseText = text;
46269
46476
  looseImages.push(...images);
@@ -46292,7 +46499,7 @@ function prepareTurnInput(body, fallbackModel) {
46292
46499
  if (transcriptParts.length > 0) promptParts.push(`Conversation so far:\n${transcriptParts.join("\n\n")}`);
46293
46500
  if (finalPrompt) promptParts.push(finalPrompt);
46294
46501
  const normalizedModel = normalizeModelSlug(asString$1(body.model) ?? fallbackModel, "codex") ?? fallbackModel;
46295
- const effort = asString$1((isRecord$4(body.reasoning) ? body.reasoning : null)?.effort) ?? asString$1(body.effort) ?? void 0;
46502
+ const effort = asString$1((isRecord$2(body.reasoning) ? body.reasoning : null)?.effort) ?? asString$1(body.effort) ?? void 0;
46296
46503
  return {
46297
46504
  prompt: promptParts.join("\n\n").trim() || null,
46298
46505
  attachments: [...looseImages, ...finalUserImages].map((url) => ({
@@ -46309,7 +46516,7 @@ function prepareTurnInput(body, fallbackModel) {
46309
46516
  }
46310
46517
  function resolveResponseContinuationKey(body, headers) {
46311
46518
  const previousResponseId = asString$1(body.previous_response_id);
46312
- const conversation = asString$1(body.conversation) ?? (isRecord$4(body.conversation) ? asString$1(body.conversation.id) : null);
46519
+ const conversation = asString$1(body.conversation) ?? (isRecord$2(body.conversation) ? asString$1(body.conversation.id) : null);
46313
46520
  if (conversation && previousResponseId) throw new AccountPoolRequestError({
46314
46521
  statusCode: 400,
46315
46522
  code: "invalid_request_error",
@@ -46388,7 +46595,7 @@ async function readJsonRequestBody(req) {
46388
46595
  const raw = Buffer.concat(chunks).toString("utf8").trim();
46389
46596
  if (!raw) return {};
46390
46597
  const parsed = JSON.parse(raw);
46391
- if (!isRecord$4(parsed)) throw new Error("Expected a JSON object request body.");
46598
+ if (!isRecord$2(parsed)) throw new Error("Expected a JSON object request body.");
46392
46599
  return parsed;
46393
46600
  }
46394
46601
  function stringifyFailureReason(failureClass, message) {
@@ -47545,17 +47752,17 @@ var LocalAccountPool = class LocalAccountPool {
47545
47752
  if (snapshotText) this.applyObserverTextSnapshot(observer, snapshotText);
47546
47753
  }
47547
47754
  if (event.method === "turn/completed") {
47548
- const payload = isRecord$4(event.payload) ? event.payload : null;
47549
- const turn = isRecord$4(payload?.turn) ? payload?.turn : payload;
47755
+ const payload = isRecord$2(event.payload) ? event.payload : null;
47756
+ const turn = isRecord$2(payload?.turn) ? payload?.turn : payload;
47550
47757
  const turnStatus = asString$1(turn?.status);
47551
- const errorMessage = asString$1(isRecord$4(turn?.error) ? turn.error.message : void 0) ?? asString$1(payload?.message);
47758
+ const errorMessage = asString$1(isRecord$2(turn?.error) ? turn.error.message : void 0) ?? asString$1(payload?.message);
47552
47759
  if (turnStatus === "failed" || errorMessage) {
47553
47760
  observer.done = true;
47554
47761
  observer.reject(new Error(errorMessage ?? "Provider turn failed."));
47555
47762
  this.turnObservers.delete(event.threadId);
47556
47763
  return;
47557
47764
  }
47558
- const usage = isRecord$4(turn?.usage) ? turn?.usage : void 0;
47765
+ const usage = isRecord$2(turn?.usage) ? turn?.usage : void 0;
47559
47766
  const snapshotText = observer.text.length > 0 ? null : extractAssistantTextSnapshot(event.payload);
47560
47767
  if (snapshotText) this.applyObserverTextSnapshot(observer, snapshotText);
47561
47768
  observer.usage = usage;
@@ -47597,15 +47804,15 @@ var LocalAccountPool = class LocalAccountPool {
47597
47804
  else observer.pendingDeltas.push(snapshotText);
47598
47805
  }
47599
47806
  extractEventErrorMessage(payload) {
47600
- if (!isRecord$4(payload)) return null;
47601
- return asString$1((isRecord$4(payload.error) ? payload.error : payload).message) ?? null;
47807
+ if (!isRecord$2(payload)) return null;
47808
+ return asString$1((isRecord$2(payload.error) ? payload.error : payload).message) ?? null;
47602
47809
  }
47603
47810
  readLiveProviderThreadId(threadId) {
47604
47811
  const active = this.manager.listSessions().find((session) => session.threadId === ThreadId.makeUnsafe(threadId));
47605
47812
  return this.readResumeCursorThreadId(active?.resumeCursor);
47606
47813
  }
47607
47814
  readResumeCursorThreadId(resumeCursor) {
47608
- if (!isRecord$4(resumeCursor)) return null;
47815
+ if (!isRecord$2(resumeCursor)) return null;
47609
47816
  return asString$1(resumeCursor.threadId);
47610
47817
  }
47611
47818
  async closeLiveSegment(segmentId) {
@@ -48505,7 +48712,7 @@ const LEGACY_SKILLS_DIR = "skills";
48505
48712
  const LEGACY_SKILLS_REPOS_FILE = "repos.json";
48506
48713
  const LEGACY_SKILL_MANIFEST = ".codexuse-skill.json";
48507
48714
  const LEGACY_LICENSE_SECRET_FILE = "license.secret";
48508
- function isRecord$3(value) {
48715
+ function isRecord$1(value) {
48509
48716
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
48510
48717
  }
48511
48718
  function isMissingPathError(error) {
@@ -48542,7 +48749,7 @@ function mergeLegacyLocalStoragePatch(payload) {
48542
48749
  else skippedKeys.add(key);
48543
48750
  };
48544
48751
  const settingsStorage = payload["settings-storage"];
48545
- if (isRecord$3(settingsStorage)) {
48752
+ if (isRecord$1(settingsStorage)) {
48546
48753
  const nextExcludeFolders = Array.isArray(settingsStorage.excludeFolders) ? settingsStorage.excludeFolders.filter((item) => typeof item === "string") : void 0;
48547
48754
  const nextBeep = typeof settingsStorage.enableTaskCompleteBeep === "boolean" ? settingsStorage.enableTaskCompleteBeep : void 0;
48548
48755
  const nextSleep = typeof settingsStorage.preventSleepDuringTasks === "boolean" ? settingsStorage.preventSleepDuringTasks : void 0;
@@ -48556,13 +48763,13 @@ function mergeLegacyLocalStoragePatch(payload) {
48556
48763
  markSkippedIfPresent("provider", hasKey("provider"));
48557
48764
  markSkippedIfPresent("sandbox-storage", hasKey("sandbox-storage"));
48558
48765
  const projectSettings = payload["project-settings-storage"];
48559
- if (isRecord$3(projectSettings) && isRecord$3(projectSettings.settingsByPath)) {
48766
+ if (isRecord$1(projectSettings) && isRecord$1(projectSettings.settingsByPath)) {
48560
48767
  patch.workspaceSettingsByPath = projectSettings.settingsByPath;
48561
48768
  markSkippedIfPresent("project-settings-storage", true);
48562
48769
  } else markSkippedIfPresent("project-settings-storage", false);
48563
48770
  const folder = payload["folder-storage"];
48564
- if (isRecord$3(folder)) {
48565
- const folderHistory = Array.isArray(folder.folderHistory) ? folder.folderHistory.filter(isRecord$3) : void 0;
48771
+ if (isRecord$1(folder)) {
48772
+ const folderHistory = Array.isArray(folder.folderHistory) ? folder.folderHistory.filter(isRecord$1) : void 0;
48566
48773
  const pinnedPaths = Array.isArray(folder.pinnedPaths) ? folder.pinnedPaths.filter((item) => typeof item === "string") : void 0;
48567
48774
  patch.preferences = {
48568
48775
  ...patch.preferences ?? {},
@@ -48573,12 +48780,12 @@ function mergeLegacyLocalStoragePatch(payload) {
48573
48780
  } else markSkippedIfPresent("folder-storage", false);
48574
48781
  const categories = payload["conversation-categories-storage"];
48575
48782
  let consumedCategories = false;
48576
- if (isRecord$3(categories)) {
48577
- if (isRecord$3(categories.categoriesByCwd)) {
48783
+ if (isRecord$1(categories)) {
48784
+ if (isRecord$1(categories.categoriesByCwd)) {
48578
48785
  patch.conversationCategoriesByCwd = categories.categoriesByCwd;
48579
48786
  consumedCategories = true;
48580
48787
  }
48581
- if (isRecord$3(categories.conversationCategoryByCwd)) {
48788
+ if (isRecord$1(categories.conversationCategoryByCwd)) {
48582
48789
  patch.conversationCategoryAssignmentsByCwd = categories.conversationCategoryByCwd;
48583
48790
  consumedCategories = true;
48584
48791
  }
@@ -48659,7 +48866,7 @@ async function importLegacyLocalStorageOnce(payload) {
48659
48866
  importedKeys: [],
48660
48867
  skippedKeys: []
48661
48868
  };
48662
- if (!payload || !isRecord$3(payload)) return {
48869
+ if (!payload || !isRecord$1(payload)) return {
48663
48870
  completed: true,
48664
48871
  importedKeys: [],
48665
48872
  skippedKeys: []
@@ -48722,991 +48929,6 @@ async function importLegacyLocalStorageOnce(payload) {
48722
48929
  };
48723
48930
  }
48724
48931
  //#endregion
48725
- //#region ../../packages/runtime-integrations/src/analytics/store.ts
48726
- const USAGE_FILE_INDEX_NAME = "desktop.analytics.usage-file-index";
48727
- const QUERY_SNAPSHOT_NAME = "desktop.analytics.query-snapshots";
48728
- function resolveUsageFileIndexPath() {
48729
- return USAGE_FILE_INDEX_NAME;
48730
- }
48731
- function resolveQuerySnapshotPath() {
48732
- return QUERY_SNAPSHOT_NAME;
48733
- }
48734
- async function readJsonFile(filePath) {
48735
- return readDocument(resolveAppStorageDbPath(getUserDataDir()), filePath, (value) => value);
48736
- }
48737
- async function writeJsonFileAtomic(filePath, value) {
48738
- await writeDocument(resolveAppStorageDbPath(getUserDataDir()), filePath, value);
48739
- }
48740
- //#endregion
48741
- //#region ../../packages/runtime-codex/src/codex/paths.ts
48742
- function getCodexRoot() {
48743
- const home = process.env.HOME || process.env.USERPROFILE;
48744
- if (!home) throw new Error("HOME is not set");
48745
- return path.join(home, ".codex");
48746
- }
48747
- function getSessionsDir() {
48748
- return path.join(getCodexRoot(), "sessions");
48749
- }
48750
- //#endregion
48751
- //#region ../../packages/runtime-integrations/src/analytics/usage-parse.ts
48752
- const ZERO_USAGE = {
48753
- input_tokens: 0,
48754
- output_tokens: 0,
48755
- reasoning_output_tokens: 0,
48756
- cached_input_tokens: 0,
48757
- total_tokens: 0
48758
- };
48759
- const MAX_ACTIVITY_GAP_MS = 120 * 1e3;
48760
- function asRecord$1(value) {
48761
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
48762
- }
48763
- function normalizeNumber(value) {
48764
- if (typeof value === "number" && Number.isFinite(value)) return value;
48765
- if (typeof value === "string" && value.trim() !== "") {
48766
- const parsed = Number(value);
48767
- return Number.isFinite(parsed) ? parsed : 0;
48768
- }
48769
- return 0;
48770
- }
48771
- function normalizeUsage(raw) {
48772
- const inputTokens = normalizeNumber(raw.input_tokens ?? raw.inputTokens ?? raw.prompt_tokens ?? raw.promptTokens);
48773
- const outputTokens = normalizeNumber(raw.output_tokens ?? raw.outputTokens ?? raw.completion_tokens ?? raw.completionTokens);
48774
- const reasoningOutputTokens = normalizeNumber(raw.reasoning_output_tokens ?? raw.reasoningOutputTokens);
48775
- const cachedInputTokens = normalizeNumber(raw.cached_input_tokens ?? raw.cachedInputTokens ?? raw.cache_read_input_tokens ?? raw.cacheReadInputTokens ?? raw.cache_creation_input_tokens ?? raw.cacheCreationInputTokens);
48776
- const totalTokens = normalizeNumber(raw.total_tokens ?? raw.totalTokens);
48777
- return {
48778
- input_tokens: inputTokens,
48779
- output_tokens: outputTokens,
48780
- reasoning_output_tokens: reasoningOutputTokens,
48781
- cached_input_tokens: cachedInputTokens,
48782
- total_tokens: totalTokens > 0 ? totalTokens : inputTokens + outputTokens + reasoningOutputTokens
48783
- };
48784
- }
48785
- function hasUsage(usage) {
48786
- return usage.input_tokens > 0 || usage.output_tokens > 0 || usage.reasoning_output_tokens > 0 || usage.cached_input_tokens > 0 || usage.total_tokens > 0;
48787
- }
48788
- function parseFilenameMetadata(filePath) {
48789
- const name = path.basename(filePath);
48790
- const tsMatch = /(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})/.exec(name);
48791
- const sessionMatch = /([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})(?:\.jsonl)?$/.exec(name);
48792
- if (!tsMatch || !sessionMatch) return null;
48793
- const [, date, hour, min, sec] = tsMatch;
48794
- const sessionId = sessionMatch[1].toLowerCase();
48795
- const timestamp = `${date}T${hour}:${min}:${sec}Z`;
48796
- const timestampMs = Date.parse(timestamp);
48797
- if (Number.isNaN(timestampMs)) return null;
48798
- return {
48799
- sessionId,
48800
- timestamp,
48801
- timestampMs
48802
- };
48803
- }
48804
- function readTimestampMs(entry) {
48805
- const raw = entry.timestamp;
48806
- if (typeof raw === "string") {
48807
- const parsed = Date.parse(raw);
48808
- return Number.isFinite(parsed) ? parsed : null;
48809
- }
48810
- const numeric = normalizeNumber(raw);
48811
- if (!Number.isFinite(numeric) || numeric <= 0) return null;
48812
- return numeric < 0xe8d4a51000 ? numeric * 1e3 : numeric;
48813
- }
48814
- function findUsageMap(info, keys) {
48815
- for (const key of keys) {
48816
- const value = asRecord$1(info[key]);
48817
- if (value) return value;
48818
- }
48819
- return null;
48820
- }
48821
- function extractProjectPath(entry) {
48822
- const cwd = asRecord$1(entry.payload)?.cwd;
48823
- return typeof cwd === "string" && cwd.trim() ? cwd.trim() : null;
48824
- }
48825
- function extractModelFromTurnContext(entry) {
48826
- const payload = asRecord$1(entry.payload);
48827
- if (!payload) return null;
48828
- const direct = payload.model;
48829
- if (typeof direct === "string" && direct.trim()) return direct.trim().replace(/^models\//i, "");
48830
- const nested = asRecord$1(payload.info)?.model;
48831
- if (typeof nested === "string" && nested.trim()) return nested.trim().replace(/^models\//i, "");
48832
- return null;
48833
- }
48834
- function extractModelFromTokenCount(entry) {
48835
- const payload = asRecord$1(entry.payload);
48836
- const info = asRecord$1(payload?.info);
48837
- const candidates = [
48838
- info?.model,
48839
- info?.model_name,
48840
- payload?.model,
48841
- entry.model
48842
- ];
48843
- for (const candidate of candidates) if (typeof candidate === "string" && candidate.trim()) return candidate.trim().replace(/^models\//i, "");
48844
- return null;
48845
- }
48846
- async function readUsageFromFile(filePath) {
48847
- const stream = createReadStream(filePath, { encoding: "utf8" });
48848
- const rl = readline.createInterface({
48849
- input: stream,
48850
- crlfDelay: Infinity
48851
- });
48852
- let projectPath = null;
48853
- let model = null;
48854
- let usageSnapshot = null;
48855
- let latestTimestampMs = null;
48856
- let agentTimeMs = 0;
48857
- let agentRuns = 0;
48858
- let lastActivityMs = null;
48859
- const seenRunTimestamps = /* @__PURE__ */ new Set();
48860
- const trackActivity = (timestampMs) => {
48861
- if (typeof timestampMs !== "number" || !Number.isFinite(timestampMs)) return;
48862
- if (lastActivityMs !== null) {
48863
- const gapMs = timestampMs - lastActivityMs;
48864
- if (gapMs > 0 && gapMs <= MAX_ACTIVITY_GAP_MS) agentTimeMs += gapMs;
48865
- }
48866
- lastActivityMs = timestampMs;
48867
- if (!latestTimestampMs || timestampMs > latestTimestampMs) latestTimestampMs = timestampMs;
48868
- };
48869
- try {
48870
- for await (const line of rl) {
48871
- if (!line || line.length > 512e3) continue;
48872
- let entry = null;
48873
- try {
48874
- entry = JSON.parse(line);
48875
- } catch {
48876
- continue;
48877
- }
48878
- const entryType = typeof entry.type === "string" ? entry.type : "";
48879
- if (!projectPath && (entryType === "session_meta" || entryType === "turn_context")) projectPath = extractProjectPath(entry);
48880
- if (!model && entryType === "turn_context") model = extractModelFromTurnContext(entry);
48881
- const timestampMs = readTimestampMs(entry);
48882
- if (entryType === "response_item") {
48883
- if (asRecord$1(entry.payload)?.role === "assistant") {
48884
- if (typeof timestampMs === "number" && Number.isFinite(timestampMs) && !seenRunTimestamps.has(timestampMs)) {
48885
- seenRunTimestamps.add(timestampMs);
48886
- agentRuns += 1;
48887
- }
48888
- trackActivity(timestampMs);
48889
- }
48890
- continue;
48891
- }
48892
- if (entryType !== "event_msg" && entryType !== "") continue;
48893
- const payload = asRecord$1(entry.payload);
48894
- if (!payload) continue;
48895
- if (payload.type === "agent_message") {
48896
- if (typeof timestampMs === "number" && Number.isFinite(timestampMs) && !seenRunTimestamps.has(timestampMs)) {
48897
- seenRunTimestamps.add(timestampMs);
48898
- agentRuns += 1;
48899
- }
48900
- trackActivity(timestampMs);
48901
- continue;
48902
- }
48903
- if (payload.type === "agent_reasoning") {
48904
- trackActivity(timestampMs);
48905
- continue;
48906
- }
48907
- if (payload.type !== "token_count") continue;
48908
- trackActivity(timestampMs);
48909
- const info = asRecord$1(payload.info);
48910
- if (!info) continue;
48911
- const totalUsageMap = findUsageMap(info, [
48912
- "total_token_usage",
48913
- "totalTokenUsage",
48914
- "total"
48915
- ]);
48916
- if (totalUsageMap) usageSnapshot = normalizeUsage(totalUsageMap);
48917
- else {
48918
- const lastUsageMap = findUsageMap(info, [
48919
- "last_token_usage",
48920
- "lastTokenUsage",
48921
- "last"
48922
- ]);
48923
- if (lastUsageMap) usageSnapshot = normalizeUsage(lastUsageMap);
48924
- }
48925
- if (!usageSnapshot || !hasUsage(usageSnapshot)) continue;
48926
- if (!model) model = extractModelFromTokenCount(entry);
48927
- }
48928
- } finally {
48929
- rl.close();
48930
- stream.close();
48931
- }
48932
- const usage = usageSnapshot ?? ZERO_USAGE;
48933
- if (!hasUsage(usage) && agentTimeMs <= 0 && agentRuns <= 0) return null;
48934
- return {
48935
- projectPath,
48936
- model,
48937
- usage,
48938
- timestampMs: latestTimestampMs,
48939
- agentTimeMs,
48940
- agentRuns
48941
- };
48942
- }
48943
- //#endregion
48944
- //#region ../../packages/runtime-integrations/src/analytics/usage.ts
48945
- const CACHE_TTL_MS = 3e5;
48946
- const RANGE_SAFETY_BUFFER_MS = 1440 * 60 * 1e3;
48947
- const USAGE_FILE_INDEX_VERSION = 1;
48948
- const cacheByKey = /* @__PURE__ */ new Map();
48949
- const scanPromises = /* @__PURE__ */ new Map();
48950
- function computeValidDirSet(fromTime, toTime) {
48951
- if (fromTime === void 0 && toTime === void 0) return null;
48952
- const from = fromTime !== void 0 ? new Date(fromTime) : /* @__PURE__ */ new Date(0);
48953
- const to = toTime !== void 0 ? new Date(toTime) : /* @__PURE__ */ new Date();
48954
- from.setUTCDate(from.getUTCDate() - 1);
48955
- to.setUTCDate(to.getUTCDate() + 1);
48956
- const years = /* @__PURE__ */ new Set();
48957
- const months = /* @__PURE__ */ new Set();
48958
- const days = /* @__PURE__ */ new Set();
48959
- const cursor = new Date(Date.UTC(from.getUTCFullYear(), from.getUTCMonth(), from.getUTCDate()));
48960
- const end = to.getTime();
48961
- while (cursor.getTime() <= end) {
48962
- const y = String(cursor.getUTCFullYear());
48963
- const m = String(cursor.getUTCMonth() + 1).padStart(2, "0");
48964
- const d = String(cursor.getUTCDate()).padStart(2, "0");
48965
- years.add(y);
48966
- months.add(`${y}/${m}`);
48967
- days.add(`${y}/${m}/${d}`);
48968
- cursor.setUTCDate(cursor.getUTCDate() + 1);
48969
- }
48970
- return {
48971
- years,
48972
- months,
48973
- days
48974
- };
48975
- }
48976
- async function listSessionFiles(rootDir, fromTime, toTime) {
48977
- const validDirs = computeValidDirSet(fromTime, toTime);
48978
- const results = [];
48979
- const scannedDayDirs = /* @__PURE__ */ new Set();
48980
- let yearEntries = [];
48981
- try {
48982
- yearEntries = await promises.readdir(rootDir, { withFileTypes: true });
48983
- } catch {
48984
- return {
48985
- files: results,
48986
- scannedDayDirs
48987
- };
48988
- }
48989
- for (const yearEntry of yearEntries) {
48990
- if (!yearEntry.isDirectory()) continue;
48991
- if (validDirs && !validDirs.years.has(yearEntry.name)) continue;
48992
- const yearPath = path.join(rootDir, yearEntry.name);
48993
- let monthEntries = [];
48994
- try {
48995
- monthEntries = await promises.readdir(yearPath, { withFileTypes: true });
48996
- } catch {
48997
- continue;
48998
- }
48999
- for (const monthEntry of monthEntries) {
49000
- if (!monthEntry.isDirectory()) continue;
49001
- if (validDirs && !validDirs.months.has(`${yearEntry.name}/${monthEntry.name}`)) continue;
49002
- const monthPath = path.join(yearPath, monthEntry.name);
49003
- let dayEntries = [];
49004
- try {
49005
- dayEntries = await promises.readdir(monthPath, { withFileTypes: true });
49006
- } catch {
49007
- continue;
49008
- }
49009
- for (const dayEntry of dayEntries) {
49010
- if (!dayEntry.isDirectory()) continue;
49011
- if (validDirs && !validDirs.days.has(`${yearEntry.name}/${monthEntry.name}/${dayEntry.name}`)) continue;
49012
- const dayPath = path.join(monthPath, dayEntry.name);
49013
- scannedDayDirs.add(dayPath);
49014
- let fileEntries = [];
49015
- try {
49016
- fileEntries = await promises.readdir(dayPath, { withFileTypes: true });
49017
- } catch {
49018
- continue;
49019
- }
49020
- for (const fileEntry of fileEntries) {
49021
- if (!fileEntry.isFile() || !fileEntry.name.endsWith(".jsonl")) continue;
49022
- const filePath = path.join(dayPath, fileEntry.name);
49023
- try {
49024
- const stats = await promises.stat(filePath);
49025
- results.push({
49026
- filePath,
49027
- size: stats.size,
49028
- mtimeMs: stats.mtimeMs
49029
- });
49030
- } catch {
49031
- continue;
49032
- }
49033
- }
49034
- }
49035
- }
49036
- }
49037
- return {
49038
- files: results,
49039
- scannedDayDirs
49040
- };
49041
- }
49042
- function toIsoTimestamp(timestampMs) {
49043
- return new Date(timestampMs).toISOString();
49044
- }
49045
- function compareByTimestampDesc(a, b) {
49046
- const aMs = Date.parse(a.timestamp);
49047
- const bMs = Date.parse(b.timestamp);
49048
- const aValue = Number.isFinite(aMs) ? aMs : 0;
49049
- const bValue = Number.isFinite(bMs) ? bMs : 0;
49050
- if (aValue === bValue) return a.sessionId.localeCompare(b.sessionId);
49051
- return bValue - aValue;
49052
- }
49053
- function normalizeRangeTime(value) {
49054
- if (typeof value !== "number" || !Number.isFinite(value)) return;
49055
- return Math.floor(value);
49056
- }
49057
- function normalizeWorkspacePath$1(value) {
49058
- if (typeof value !== "string" || !value.trim()) return null;
49059
- let normalized = path.normalize(path.resolve(value.trim()));
49060
- const root = path.parse(normalized).root;
49061
- if (normalized !== root) normalized = normalized.replace(/[\\/]+$/, "");
49062
- if (process.platform === "win32") normalized = normalized.toLowerCase();
49063
- return normalized;
49064
- }
49065
- function pathMatchesWorkspace(projectPath, normalizedWorkspacePath) {
49066
- if (!normalizedWorkspacePath) return true;
49067
- const normalizedProjectPath = normalizeWorkspacePath$1(projectPath);
49068
- if (!normalizedProjectPath) return false;
49069
- if (normalizedProjectPath === normalizedWorkspacePath) return true;
49070
- const relativePath = path.relative(normalizedWorkspacePath, normalizedProjectPath);
49071
- return relativePath.length > 0 && !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
49072
- }
49073
- function shouldSkipByRange(timestampMs, options) {
49074
- const fromTime = normalizeRangeTime(options?.fromTime);
49075
- const toTime = normalizeRangeTime(options?.toTime);
49076
- if (fromTime !== void 0 && timestampMs < fromTime - RANGE_SAFETY_BUFFER_MS) return true;
49077
- if (toTime !== void 0 && timestampMs > toTime + RANGE_SAFETY_BUFFER_MS) return true;
49078
- return false;
49079
- }
49080
- function buildCacheKey(options) {
49081
- const fromTime = normalizeRangeTime(options?.fromTime);
49082
- const toTime = normalizeRangeTime(options?.toTime);
49083
- const workspacePath = normalizeWorkspacePath$1(options?.workspacePath);
49084
- return `${fromTime ?? "none"}:${toTime ?? "none"}:${workspacePath ?? "all"}`;
49085
- }
49086
- function isRecord$2(value) {
49087
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
49088
- }
49089
- function toNumber(value) {
49090
- if (typeof value === "number" && Number.isFinite(value)) return value;
49091
- if (typeof value === "string" && value.trim()) {
49092
- const parsed = Number(value);
49093
- return Number.isFinite(parsed) ? parsed : null;
49094
- }
49095
- return null;
49096
- }
49097
- function asTokenUsage(value) {
49098
- if (!isRecord$2(value)) return null;
49099
- const input_tokens = toNumber(value.input_tokens) ?? 0;
49100
- const output_tokens = toNumber(value.output_tokens) ?? 0;
49101
- const reasoning_output_tokens = toNumber(value.reasoning_output_tokens) ?? 0;
49102
- return {
49103
- input_tokens,
49104
- output_tokens,
49105
- reasoning_output_tokens,
49106
- cached_input_tokens: toNumber(value.cached_input_tokens) ?? 0,
49107
- total_tokens: toNumber(value.total_tokens) ?? input_tokens + output_tokens + reasoning_output_tokens
49108
- };
49109
- }
49110
- function asUsageRecord(value) {
49111
- if (!isRecord$2(value)) return null;
49112
- const sessionId = typeof value.sessionId === "string" ? value.sessionId.trim() : "";
49113
- const rolloutPath = typeof value.rolloutPath === "string" ? value.rolloutPath.trim() : "";
49114
- const timestamp = typeof value.timestamp === "string" ? value.timestamp.trim() : "";
49115
- if (!sessionId || !rolloutPath || !timestamp) return null;
49116
- const usage = asTokenUsage(value.usage);
49117
- if (!usage) return null;
49118
- return {
49119
- sessionId,
49120
- rolloutPath,
49121
- projectPath: typeof value.projectPath === "string" && value.projectPath.trim() ? value.projectPath.trim() : null,
49122
- model: typeof value.model === "string" && value.model.trim() ? value.model.trim() : null,
49123
- usage,
49124
- timestamp,
49125
- agentTimeMs: toNumber(value.agentTimeMs) ?? 0,
49126
- agentRuns: toNumber(value.agentRuns) ?? 0
49127
- };
49128
- }
49129
- function asUsageFileIndexEntry(value) {
49130
- if (!isRecord$2(value)) return null;
49131
- const filePath = typeof value.filePath === "string" ? value.filePath.trim() : "";
49132
- if (!filePath) return null;
49133
- const size = toNumber(value.size);
49134
- const mtimeMs = toNumber(value.mtimeMs);
49135
- if (size === null || mtimeMs === null) return null;
49136
- const record = value.record === null ? null : asUsageRecord(value.record);
49137
- if (value.record !== null && !record) return null;
49138
- return {
49139
- filePath,
49140
- size,
49141
- mtimeMs,
49142
- record
49143
- };
49144
- }
49145
- async function readUsageFileIndex() {
49146
- const raw = await readJsonFile(resolveUsageFileIndexPath());
49147
- if (!raw || raw.version !== USAGE_FILE_INDEX_VERSION || !Array.isArray(raw.entries)) return /* @__PURE__ */ new Map();
49148
- const byPath = /* @__PURE__ */ new Map();
49149
- for (const entry of raw.entries) {
49150
- const normalized = asUsageFileIndexEntry(entry);
49151
- if (!normalized) continue;
49152
- byPath.set(normalized.filePath, normalized);
49153
- }
49154
- return byPath;
49155
- }
49156
- async function writeUsageFileIndex(indexByPath) {
49157
- await writeJsonFileAtomic(resolveUsageFileIndexPath(), {
49158
- version: USAGE_FILE_INDEX_VERSION,
49159
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
49160
- entries: Array.from(indexByPath.values())
49161
- });
49162
- }
49163
- function isPathInsideDir(filePath, dirPath) {
49164
- if (filePath === dirPath) return true;
49165
- const relativePath = path.relative(dirPath, filePath);
49166
- return relativePath.length > 0 && !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
49167
- }
49168
- function pruneDeletedEntries(indexByPath, scannedDayDirs, scannedPaths) {
49169
- if (scannedDayDirs.size === 0) return;
49170
- const dayDirs = Array.from(scannedDayDirs.values());
49171
- for (const filePath of Array.from(indexByPath.keys())) {
49172
- if (!dayDirs.some((dayDir) => isPathInsideDir(filePath, dayDir))) continue;
49173
- if (!scannedPaths.has(filePath)) indexByPath.delete(filePath);
49174
- }
49175
- }
49176
- async function scanUsageRecords(options) {
49177
- const startedAt = Date.now();
49178
- const { files, scannedDayDirs } = await listSessionFiles(getSessionsDir(), normalizeRangeTime(options?.fromTime), normalizeRangeTime(options?.toTime));
49179
- const indexByPath = await readUsageFileIndex();
49180
- const nextIndexByPath = new Map(indexByPath);
49181
- const latestBySessionId = /* @__PURE__ */ new Map();
49182
- const normalizedWorkspacePath = normalizeWorkspacePath$1(options?.workspacePath);
49183
- const scannedPaths = /* @__PURE__ */ new Set();
49184
- let parsedFiles = 0;
49185
- let reusedFiles = 0;
49186
- for (const file of files) {
49187
- const filePath = file.filePath;
49188
- scannedPaths.add(filePath);
49189
- const metadata = parseFilenameMetadata(filePath);
49190
- if (!metadata || shouldSkipByRange(metadata.timestampMs, options)) continue;
49191
- const existing = indexByPath.get(filePath);
49192
- const canReuse = existing && existing.mtimeMs === file.mtimeMs && existing.size === file.size;
49193
- let record = null;
49194
- if (canReuse) {
49195
- reusedFiles += 1;
49196
- record = existing.record;
49197
- nextIndexByPath.set(filePath, existing);
49198
- } else {
49199
- parsedFiles += 1;
49200
- const usageData = await readUsageFromFile(filePath);
49201
- if (usageData) {
49202
- const effectiveTimestampMs = typeof usageData.timestampMs === "number" && Number.isFinite(usageData.timestampMs) ? usageData.timestampMs : metadata.timestampMs;
49203
- record = {
49204
- sessionId: metadata.sessionId,
49205
- rolloutPath: filePath,
49206
- projectPath: usageData.projectPath,
49207
- model: usageData.model,
49208
- usage: usageData.usage,
49209
- timestamp: toIsoTimestamp(effectiveTimestampMs),
49210
- agentTimeMs: usageData.agentTimeMs,
49211
- agentRuns: usageData.agentRuns
49212
- };
49213
- }
49214
- nextIndexByPath.set(filePath, {
49215
- filePath,
49216
- size: file.size,
49217
- mtimeMs: file.mtimeMs,
49218
- record
49219
- });
49220
- }
49221
- if (!record || !pathMatchesWorkspace(record.projectPath, normalizedWorkspacePath)) continue;
49222
- const existingRecord = latestBySessionId.get(record.sessionId);
49223
- if (!existingRecord) {
49224
- latestBySessionId.set(record.sessionId, record);
49225
- continue;
49226
- }
49227
- const existingTs = Date.parse(existingRecord.timestamp);
49228
- const nextTs = Date.parse(record.timestamp);
49229
- const existingMs = Number.isFinite(existingTs) ? existingTs : 0;
49230
- if ((Number.isFinite(nextTs) ? nextTs : 0) >= existingMs) latestBySessionId.set(record.sessionId, record);
49231
- }
49232
- pruneDeletedEntries(nextIndexByPath, scannedDayDirs, scannedPaths);
49233
- try {
49234
- await writeUsageFileIndex(nextIndexByPath);
49235
- } catch (error) {
49236
- if (process.env.NODE_ENV !== "production") console.warn("[analytics] failed to persist usage-file-index", error);
49237
- }
49238
- return {
49239
- records: Array.from(latestBySessionId.values()).sort(compareByTimestampDesc),
49240
- meta: {
49241
- source: "fresh",
49242
- parsedFiles,
49243
- reusedFiles,
49244
- scanMs: Date.now() - startedAt
49245
- }
49246
- };
49247
- }
49248
- function cloneUsageReadResult(result, sourceOverride) {
49249
- return {
49250
- records: result.records.slice(),
49251
- meta: {
49252
- source: sourceOverride ?? result.meta.source,
49253
- parsedFiles: result.meta.parsedFiles,
49254
- reusedFiles: result.meta.reusedFiles,
49255
- scanMs: result.meta.scanMs
49256
- }
49257
- };
49258
- }
49259
- async function loadCachedOrScan(options) {
49260
- const key = buildCacheKey(options);
49261
- const forceRefresh = Boolean(options?.forceRefresh);
49262
- if (forceRefresh) cacheByKey.delete(key);
49263
- const now = Date.now();
49264
- if (!forceRefresh) {
49265
- const cached = cacheByKey.get(key);
49266
- if (cached && now - cached.cachedAt < CACHE_TTL_MS) return cloneUsageReadResult(cached.result, "memory");
49267
- }
49268
- if (!forceRefresh) {
49269
- const inFlight = scanPromises.get(key);
49270
- if (inFlight) return inFlight;
49271
- }
49272
- const scanPromise = scanUsageRecords(options).then((result) => {
49273
- cacheByKey.set(key, {
49274
- cachedAt: Date.now(),
49275
- result: cloneUsageReadResult(result)
49276
- });
49277
- return result;
49278
- }).finally(() => {
49279
- scanPromises.delete(key);
49280
- });
49281
- scanPromises.set(key, scanPromise);
49282
- return scanPromise;
49283
- }
49284
- async function readTokenUsageDetailed(options) {
49285
- return loadCachedOrScan(options);
49286
- }
49287
- //#endregion
49288
- //#region ../../packages/runtime-integrations/src/analytics/service.ts
49289
- const MODEL_COSTS = {
49290
- "gpt-5.3-codex": {
49291
- input: 2.5,
49292
- output: 10,
49293
- cache_write: 1.25,
49294
- cache_read: .125
49295
- },
49296
- "gpt-5.2-codex": {
49297
- input: 2.5,
49298
- output: 10,
49299
- cache_write: 1.25,
49300
- cache_read: .125
49301
- },
49302
- "gpt-5-codex": {
49303
- input: 2.5,
49304
- output: 10,
49305
- cache_write: 1.25,
49306
- cache_read: .125
49307
- },
49308
- "gpt-5": {
49309
- input: 2.5,
49310
- output: 10,
49311
- cache_write: 1.25,
49312
- cache_read: .125
49313
- }
49314
- };
49315
- const DEFAULT_MODEL = "gpt-5.3-codex";
49316
- const QUERY_SNAPSHOT_VERSION = 1;
49317
- const QUERY_SNAPSHOT_TTL_MS = 6e4;
49318
- const QUERY_SNAPSHOT_MAX_ENTRIES = 60;
49319
- const MAX_TIMELINE_POINTS = 30;
49320
- const MAX_MODELS = 10;
49321
- const MAX_PROJECTS = 10;
49322
- const OTHER_MODEL_KEY = "Other";
49323
- const OTHER_PROJECT_KEY = "Other";
49324
- function calculateTokenCost(usage, model) {
49325
- const costs = MODEL_COSTS[model] ?? MODEL_COSTS[DEFAULT_MODEL];
49326
- const inputCost = (usage.input_tokens - (usage.cached_input_tokens || 0)) / 1e6 * costs.input;
49327
- const outputCost = usage.output_tokens / 1e6 * costs.output;
49328
- const cacheWriteCost = usage.cached_input_tokens / 1e6 * costs.cache_write;
49329
- return inputCost + outputCost + cacheWriteCost + 0;
49330
- }
49331
- function buildDailyUsage(metrics) {
49332
- const dailyMap = /* @__PURE__ */ new Map();
49333
- for (const metric of metrics) {
49334
- const date = metric.timestamp.toISOString().slice(0, 10);
49335
- const entry = dailyMap.get(date) ?? {
49336
- date,
49337
- totalTokens: 0,
49338
- inputTokens: 0,
49339
- outputTokens: 0,
49340
- cacheCreationTokens: 0,
49341
- cacheReadTokens: 0,
49342
- totalCost: 0,
49343
- sessionCount: 0,
49344
- agentTimeMs: 0,
49345
- agentRuns: 0,
49346
- models: []
49347
- };
49348
- entry.totalTokens += metric.totalTokens;
49349
- entry.inputTokens += metric.inputTokens;
49350
- entry.outputTokens += metric.outputTokens + metric.reasoningOutputTokens;
49351
- entry.cacheCreationTokens += metric.cachedInputTokens;
49352
- entry.totalCost += metric.estimatedCost;
49353
- entry.sessionCount += 1;
49354
- entry.agentTimeMs += metric.agentTimeMs;
49355
- entry.agentRuns += metric.agentRuns;
49356
- if (!entry.models.includes(metric.model)) entry.models.push(metric.model);
49357
- dailyMap.set(date, entry);
49358
- }
49359
- return Array.from(dailyMap.values()).sort((a, b) => a.date.localeCompare(b.date));
49360
- }
49361
- function buildHourlyUsage(metrics) {
49362
- const hourlyMap = /* @__PURE__ */ new Map();
49363
- for (const metric of metrics) {
49364
- const key = `${metric.timestamp.toISOString().slice(0, 10)} ${metric.timestamp.getHours().toString().padStart(2, "0")}:00`;
49365
- const entry = hourlyMap.get(key) ?? {
49366
- hour: key,
49367
- totalTokens: 0,
49368
- inputTokens: 0,
49369
- outputTokens: 0,
49370
- totalCost: 0,
49371
- sessionCount: 0
49372
- };
49373
- entry.totalTokens += metric.totalTokens;
49374
- entry.inputTokens += metric.inputTokens;
49375
- entry.outputTokens += metric.outputTokens + metric.reasoningOutputTokens;
49376
- entry.totalCost += metric.estimatedCost;
49377
- entry.sessionCount += 1;
49378
- hourlyMap.set(key, entry);
49379
- }
49380
- return Array.from(hourlyMap.values()).sort((a, b) => a.hour.localeCompare(b.hour));
49381
- }
49382
- function buildModelUsage(metrics) {
49383
- const modelMap = /* @__PURE__ */ new Map();
49384
- const totalTokens = metrics.reduce((sum, metric) => sum + metric.totalTokens, 0);
49385
- for (const metric of metrics) {
49386
- const entry = modelMap.get(metric.model) ?? {
49387
- model: metric.model,
49388
- tokens: 0,
49389
- inputTokens: 0,
49390
- outputTokens: 0,
49391
- cost: 0,
49392
- percentage: 0,
49393
- sessionCount: 0
49394
- };
49395
- entry.tokens += metric.totalTokens;
49396
- entry.inputTokens += metric.inputTokens;
49397
- entry.outputTokens += metric.outputTokens + metric.reasoningOutputTokens;
49398
- entry.cost += metric.estimatedCost;
49399
- entry.sessionCount += 1;
49400
- modelMap.set(metric.model, entry);
49401
- }
49402
- return Array.from(modelMap.values()).map((entry) => ({
49403
- ...entry,
49404
- percentage: totalTokens > 0 ? entry.tokens / totalTokens * 100 : 0
49405
- })).sort((a, b) => b.tokens - a.tokens);
49406
- }
49407
- function limitModelUsage(data, maxModels = MAX_MODELS) {
49408
- if (data.length <= maxModels) return data;
49409
- const top = data.slice(0, maxModels);
49410
- const rest = data.slice(maxModels);
49411
- if (rest.length === 0) return top;
49412
- const other = rest.reduce((acc, item) => {
49413
- acc.tokens += item.tokens;
49414
- acc.inputTokens += item.inputTokens;
49415
- acc.outputTokens += item.outputTokens;
49416
- acc.cost += item.cost;
49417
- acc.sessionCount += item.sessionCount;
49418
- return acc;
49419
- }, {
49420
- model: OTHER_MODEL_KEY,
49421
- tokens: 0,
49422
- inputTokens: 0,
49423
- outputTokens: 0,
49424
- cost: 0,
49425
- percentage: 0,
49426
- sessionCount: 0
49427
- });
49428
- const total = top.reduce((sum, item) => sum + item.tokens, 0) + other.tokens;
49429
- return [...top.map((item) => ({
49430
- ...item,
49431
- percentage: total > 0 ? item.tokens / total * 100 : 0
49432
- })), {
49433
- ...other,
49434
- percentage: total > 0 ? other.tokens / total * 100 : 0
49435
- }];
49436
- }
49437
- function buildProjectBreakdown(metrics) {
49438
- const projectMap = /* @__PURE__ */ new Map();
49439
- for (const metric of metrics) {
49440
- const key = metric.projectPath?.trim() || "Unknown";
49441
- const entry = projectMap.get(key) ?? {
49442
- sessions: 0,
49443
- cost: 0,
49444
- tokens: 0
49445
- };
49446
- entry.sessions += 1;
49447
- entry.cost += metric.estimatedCost;
49448
- entry.tokens += metric.totalTokens;
49449
- projectMap.set(key, entry);
49450
- }
49451
- return Object.fromEntries(projectMap.entries());
49452
- }
49453
- function limitProjectBreakdown(projectBreakdown, maxProjects = MAX_PROJECTS) {
49454
- const sorted = Object.entries(projectBreakdown).sort((a, b) => b[1].cost - a[1].cost);
49455
- if (sorted.length <= maxProjects) return Object.fromEntries(sorted);
49456
- const top = sorted.slice(0, maxProjects);
49457
- const other = sorted.slice(maxProjects).reduce((acc, entry) => {
49458
- acc.sessions += entry[1].sessions;
49459
- acc.cost += entry[1].cost;
49460
- acc.tokens += entry[1].tokens;
49461
- return acc;
49462
- }, {
49463
- sessions: 0,
49464
- cost: 0,
49465
- tokens: 0
49466
- });
49467
- if (other.sessions > 0 || other.cost > 0 || other.tokens > 0) top.push([OTHER_PROJECT_KEY, other]);
49468
- return Object.fromEntries(top);
49469
- }
49470
- function limitTimelinePoints(data, maxPoints = MAX_TIMELINE_POINTS) {
49471
- if (data.length <= maxPoints) return data;
49472
- return data.slice(-maxPoints);
49473
- }
49474
- function normalizeWorkspacePath(value) {
49475
- if (typeof value !== "string" || !value.trim()) return null;
49476
- let normalized = path.normalize(path.resolve(value.trim()));
49477
- const root = path.parse(normalized).root;
49478
- if (normalized !== root) normalized = normalized.replace(/[\\/]+$/, "");
49479
- if (process.platform === "win32") normalized = normalized.toLowerCase();
49480
- return normalized;
49481
- }
49482
- function resolveLocalTimeZone() {
49483
- try {
49484
- const zone = Intl.DateTimeFormat().resolvedOptions().timeZone;
49485
- if (zone && typeof zone === "string" && zone.trim()) return zone.trim();
49486
- } catch {}
49487
- return "local";
49488
- }
49489
- function normalizeDateInput(value) {
49490
- if (value instanceof Date) return Number.isFinite(value.getTime()) ? value : void 0;
49491
- if (typeof value === "number" && Number.isFinite(value)) {
49492
- const timestamp = Math.abs(value) < 0xe8d4a51000 ? value * 1e3 : value;
49493
- const normalized = new Date(Math.trunc(timestamp));
49494
- return Number.isFinite(normalized.getTime()) ? normalized : void 0;
49495
- }
49496
- if (typeof value === "string") {
49497
- const trimmed = value.trim();
49498
- if (!trimmed) return;
49499
- const numeric = Number(trimmed);
49500
- if (Number.isFinite(numeric)) return normalizeDateInput(numeric);
49501
- const parsed = Date.parse(trimmed);
49502
- if (Number.isFinite(parsed)) return new Date(parsed);
49503
- }
49504
- }
49505
- function normalizeDateRange(dateRange) {
49506
- if (!dateRange) return;
49507
- const from = normalizeDateInput(dateRange.from);
49508
- const to = normalizeDateInput(dateRange.to);
49509
- return from || to ? {
49510
- from,
49511
- to
49512
- } : {};
49513
- }
49514
- function buildSnapshotKey(options) {
49515
- const dateRange = normalizeDateRange(options.dateRange);
49516
- return `${dateRange?.from?.getTime() ?? 0}:${dateRange?.to?.getTime() ?? 0}:${normalizeWorkspacePath(options.workspacePath) ?? "all"}:${resolveLocalTimeZone()}`;
49517
- }
49518
- function isRecord$1(value) {
49519
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
49520
- }
49521
- function normalizeQuerySnapshotEntry(value) {
49522
- if (!isRecord$1(value)) return null;
49523
- const key = typeof value.key === "string" ? value.key.trim() : "";
49524
- const cachedAt = typeof value.cachedAt === "number" ? value.cachedAt : Number(value.cachedAt);
49525
- const generatedAt = typeof value.generatedAt === "string" ? value.generatedAt : "";
49526
- const data = value.data;
49527
- if (!key || !Number.isFinite(cachedAt) || !generatedAt || !data) return null;
49528
- return {
49529
- key,
49530
- cachedAt,
49531
- generatedAt,
49532
- data,
49533
- parsedFiles: typeof value.parsedFiles === "number" && Number.isFinite(value.parsedFiles) ? value.parsedFiles : 0,
49534
- reusedFiles: typeof value.reusedFiles === "number" && Number.isFinite(value.reusedFiles) ? value.reusedFiles : 0,
49535
- scanMs: typeof value.scanMs === "number" && Number.isFinite(value.scanMs) ? value.scanMs : 0
49536
- };
49537
- }
49538
- async function readQuerySnapshotStore() {
49539
- const raw = await readJsonFile(resolveQuerySnapshotPath());
49540
- if (!raw || raw.version !== QUERY_SNAPSHOT_VERSION || !Array.isArray(raw.entries)) return {
49541
- version: QUERY_SNAPSHOT_VERSION,
49542
- entries: [],
49543
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
49544
- };
49545
- const entries = [];
49546
- for (const entry of raw.entries) {
49547
- const normalized = normalizeQuerySnapshotEntry(entry);
49548
- if (normalized) entries.push(normalized);
49549
- }
49550
- return {
49551
- version: QUERY_SNAPSHOT_VERSION,
49552
- entries,
49553
- updatedAt: typeof raw.updatedAt === "string" && raw.updatedAt ? raw.updatedAt : (/* @__PURE__ */ new Date()).toISOString()
49554
- };
49555
- }
49556
- async function writeQuerySnapshotStore(store) {
49557
- await writeJsonFileAtomic(resolveQuerySnapshotPath(), store);
49558
- }
49559
- async function readSnapshotByKey(key) {
49560
- return (await readQuerySnapshotStore()).entries.find((entry) => entry.key === key) ?? null;
49561
- }
49562
- async function upsertSnapshotEntry(entry) {
49563
- const filtered = (await readQuerySnapshotStore()).entries.filter((candidate) => candidate.key !== entry.key);
49564
- filtered.unshift(entry);
49565
- if (filtered.length > QUERY_SNAPSHOT_MAX_ENTRIES) filtered.length = QUERY_SNAPSHOT_MAX_ENTRIES;
49566
- await writeQuerySnapshotStore({
49567
- version: QUERY_SNAPSHOT_VERSION,
49568
- entries: filtered,
49569
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
49570
- });
49571
- }
49572
- function createResultMetaFromSnapshot(snapshot) {
49573
- return {
49574
- source: "persisted",
49575
- stale: Date.now() - snapshot.cachedAt > QUERY_SNAPSHOT_TTL_MS,
49576
- generatedAt: snapshot.generatedAt,
49577
- parsedFiles: snapshot.parsedFiles,
49578
- reusedFiles: snapshot.reusedFiles,
49579
- scanMs: snapshot.scanMs
49580
- };
49581
- }
49582
- function resolveDateRange(options) {
49583
- if (!options) return {};
49584
- if ("dateRange" in options || "mergeProfiles" in options || "includeUnattributedSessions" in options || "forceRefresh" in options || "workspacePath" in options || "loadMode" in options) {
49585
- const query = options;
49586
- return {
49587
- ...query,
49588
- dateRange: normalizeDateRange(query.dateRange)
49589
- };
49590
- }
49591
- return { dateRange: normalizeDateRange(options) };
49592
- }
49593
- async function loadAnalyticsData(dateRangeOrOptions) {
49594
- const startedAt = Date.now();
49595
- const options = resolveDateRange(dateRangeOrOptions);
49596
- const loadMode = options.loadMode ?? "cacheFirst";
49597
- const shouldReadPersisted = loadMode === "cacheFirst" && !options.forceRefresh;
49598
- const snapshotKey = buildSnapshotKey(options);
49599
- const persisted = shouldReadPersisted ? await readSnapshotByKey(snapshotKey) : null;
49600
- if (persisted) return {
49601
- data: persisted.data,
49602
- meta: createResultMetaFromSnapshot(persisted)
49603
- };
49604
- const { dateRange, workspacePath } = options;
49605
- const fromTime = dateRange?.from?.getTime() ?? 0;
49606
- const toTime = dateRange?.to?.getTime() ?? Date.now();
49607
- const usageResult = await readTokenUsageDetailed({
49608
- fromTime,
49609
- toTime,
49610
- forceRefresh: Boolean(options.forceRefresh || loadMode === "freshOnly"),
49611
- workspacePath
49612
- });
49613
- const records = usageResult.records;
49614
- const metrics = [];
49615
- for (const record of records) {
49616
- const ts = Date.parse(record.timestamp);
49617
- if (Number.isNaN(ts)) continue;
49618
- if (ts < fromTime || ts > toTime) continue;
49619
- const model = record.model ?? DEFAULT_MODEL;
49620
- metrics.push({
49621
- sessionId: record.sessionId,
49622
- timestamp: new Date(ts),
49623
- projectPath: record.projectPath,
49624
- model,
49625
- inputTokens: record.usage.input_tokens,
49626
- outputTokens: record.usage.output_tokens,
49627
- reasoningOutputTokens: record.usage.reasoning_output_tokens,
49628
- cachedInputTokens: record.usage.cached_input_tokens,
49629
- totalTokens: record.usage.total_tokens,
49630
- agentTimeMs: record.agentTimeMs,
49631
- agentRuns: record.agentRuns,
49632
- estimatedCost: calculateTokenCost(record.usage, model)
49633
- });
49634
- }
49635
- const totalCost = metrics.reduce((sum, m) => sum + m.estimatedCost, 0);
49636
- const totalSessions = metrics.length;
49637
- const totalTokens = metrics.reduce((sum, m) => sum + m.totalTokens, 0);
49638
- const avgCostPerSession = totalSessions > 0 ? totalCost / totalSessions : 0;
49639
- const avgTokensPerSession = totalSessions > 0 ? totalTokens / totalSessions : 0;
49640
- const totalInputTokens = metrics.reduce((sum, m) => sum + m.inputTokens, 0);
49641
- const totalOutputTokens = metrics.reduce((sum, m) => sum + m.outputTokens + m.reasoningOutputTokens, 0);
49642
- const totalReasoningTokens = metrics.reduce((sum, m) => sum + m.reasoningOutputTokens, 0);
49643
- const totalCachedInputTokens = metrics.reduce((sum, m) => sum + m.cachedInputTokens, 0);
49644
- const totalCacheCreationTokens = metrics.reduce((sum, m) => sum + m.cachedInputTokens, 0);
49645
- const totalCacheReadTokens = 0;
49646
- const totalAgentTimeMs = metrics.reduce((sum, m) => sum + m.agentTimeMs, 0);
49647
- const totalAgentRuns = metrics.reduce((sum, m) => sum + m.agentRuns, 0);
49648
- const dailyUsage = limitTimelinePoints(buildDailyUsage(metrics));
49649
- const hourlyUsage = limitTimelinePoints(buildHourlyUsage(metrics));
49650
- const modelUsage = limitModelUsage(buildModelUsage(metrics));
49651
- const projectBreakdown = limitProjectBreakdown(buildProjectBreakdown(metrics));
49652
- const cacheEfficiencyBase = totalInputTokens + totalCacheCreationTokens;
49653
- const data = {
49654
- summary: {
49655
- totalTokens,
49656
- totalInputTokens,
49657
- totalOutputTokens,
49658
- totalCacheCreationTokens,
49659
- totalCacheReadTokens,
49660
- totalReasoningTokens,
49661
- totalCachedInputTokens,
49662
- totalAgentTimeMs,
49663
- totalAgentRuns,
49664
- totalCost,
49665
- totalSessions,
49666
- avgCostPerSession,
49667
- avgTokensPerSession,
49668
- cacheEfficiency: cacheEfficiencyBase > 0 ? totalCacheCreationTokens / cacheEfficiencyBase * 100 : 0,
49669
- cacheSavings: 0,
49670
- dailyAvgCost: dailyUsage.length > 0 ? totalCost / dailyUsage.length : 0,
49671
- models: modelUsage.map((entry) => entry.model)
49672
- },
49673
- dailyUsage,
49674
- hourlyUsage,
49675
- modelUsage,
49676
- projectBreakdown
49677
- };
49678
- const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
49679
- const result = {
49680
- data,
49681
- meta: {
49682
- source: usageResult.meta.source === "memory" ? "memory" : "fresh",
49683
- stale: false,
49684
- generatedAt,
49685
- parsedFiles: usageResult.meta.parsedFiles,
49686
- reusedFiles: usageResult.meta.reusedFiles,
49687
- scanMs: usageResult.meta.scanMs
49688
- }
49689
- };
49690
- try {
49691
- await upsertSnapshotEntry({
49692
- key: snapshotKey,
49693
- cachedAt: Date.now(),
49694
- generatedAt,
49695
- data,
49696
- parsedFiles: result.meta.parsedFiles,
49697
- reusedFiles: result.meta.reusedFiles,
49698
- scanMs: result.meta.scanMs
49699
- });
49700
- } catch (error) {
49701
- if (process.env.NODE_ENV !== "production") console.warn("[analytics] failed to persist query snapshot", error);
49702
- }
49703
- if (process.env.NODE_ENV !== "production") {
49704
- const elapsedMs = Date.now() - startedAt;
49705
- console.warn(`[analytics] loadAnalyticsData totalMs=${elapsedMs} records=${records.length} source=${result.meta.source} parsedFiles=${result.meta.parsedFiles} reusedFiles=${result.meta.reusedFiles}`);
49706
- }
49707
- return result;
49708
- }
49709
- //#endregion
49710
48932
  //#region ../../packages/runtime-integrations/src/agents/service.ts
49711
48933
  const AGENTS_FILENAME = "AGENTS.md";
49712
48934
  function resolveGlobalPath(options) {
@@ -50573,6 +49795,65 @@ async function inspectCodexRuntime(input) {
50573
49795
  };
50574
49796
  }
50575
49797
  //#endregion
49798
+ //#region src/agentChat.ts
49799
+ const AGENT_CHAT_AGENTS_CONTENT = `# AGENTS.md — Agent
49800
+
49801
+ You are the assistant for CodexUse's Agent surface.
49802
+
49803
+ Default behavior:
49804
+ - Act like a capable local agent, not a casual chat-only assistant.
49805
+ - Use the machine deliberately when the user asks you to inspect files, run commands, edit code, or complete workspace tasks.
49806
+ - Treat this workspace as internal app scaffolding; the real task may still involve other folders on the machine.
49807
+ - Prefer concrete execution over abstract discussion when the user asks for action.
49808
+ - Before destructive, irreversible, security-sensitive, or high-impact machine actions, pause and get confirmation.
49809
+ - Explain when you are about to leave discussion-only mode and start taking actions on the machine.
49810
+ - Keep changes scoped to the user's request, and avoid unrelated file churn.
49811
+ `;
49812
+ function getAgentChatConfig() {
49813
+ return { workspaceRoot: resolveAgentChatWorkspaceRoot() };
49814
+ }
49815
+ async function ensureAgentChatWorkspaceArtifacts() {
49816
+ const workspaceRoot = resolveAgentChatWorkspaceRoot();
49817
+ const agentsPath = resolveAgentChatAgentsPath();
49818
+ await promises.mkdir(workspaceRoot, { recursive: true });
49819
+ try {
49820
+ await promises.access(agentsPath);
49821
+ } catch {
49822
+ await promises.writeFile(agentsPath, AGENT_CHAT_AGENTS_CONTENT, "utf8");
49823
+ }
49824
+ return workspaceRoot;
49825
+ }
49826
+ //#endregion
49827
+ //#region src/generalChat.ts
49828
+ const GENERAL_CHAT_AGENTS_CONTENT = `# AGENTS.md — General Chat
49829
+
49830
+ You are the assistant for CodexUse's General Chat surface.
49831
+
49832
+ Default behavior:
49833
+ - Talk like a normal general-purpose assistant.
49834
+ - Prefer direct answers, discussion, brainstorming, explanations, and everyday help.
49835
+ - Treat this workspace as internal app scaffolding, not as a user project.
49836
+ - For this General Chat workspace, treat this local AGENTS.md as the primary instruction source for behavior and tone.
49837
+ - Ignore or de-prioritize global CODEX_HOME AGENTS.md guidance that is mainly about coding workflows, repository work, file inspection, shell commands, patches, tests, PRs, or other project-task behavior, unless the user explicitly asks to switch into that kind of work.
49838
+ - Do not let coding-oriented global instructions push the conversation into repo/tooling behavior when the user is just using General Chat as a normal assistant.
49839
+ - Do not inspect files, run shell commands, modify the workspace, or take project actions unless the user clearly asks for that kind of help.
49840
+ - If the user explicitly switches into coding or workspace work, proceed deliberately and explain that you are leaving the default general-chat mode.
49841
+ `;
49842
+ function getGeneralChatConfig() {
49843
+ return { workspaceRoot: resolveGeneralChatWorkspaceRoot() };
49844
+ }
49845
+ async function ensureGeneralChatWorkspaceArtifacts() {
49846
+ const workspaceRoot = resolveGeneralChatWorkspaceRoot();
49847
+ const agentsPath = resolveGeneralChatAgentsPath();
49848
+ await promises.mkdir(workspaceRoot, { recursive: true });
49849
+ try {
49850
+ await promises.access(agentsPath);
49851
+ } catch {
49852
+ await promises.writeFile(agentsPath, GENERAL_CHAT_AGENTS_CONTENT, "utf8");
49853
+ }
49854
+ return workspaceRoot;
49855
+ }
49856
+ //#endregion
50576
49857
  //#region src/telegram/bridge.ts
50577
49858
  var TelegramApiRequestError = class extends Error {
50578
49859
  constructor(message) {
@@ -52581,6 +51862,8 @@ const createServer = fn(function* () {
52581
51862
  clients,
52582
51863
  logOutgoingPush
52583
51864
  });
51865
+ const agentChatConfig = getAgentChatConfig();
51866
+ const generalChatConfig = getGeneralChatConfig();
52584
51867
  yield* readiness.markPushBusReady;
52585
51868
  yield* keybindingsManager.start.pipe(mapError((cause) => new ServerLifecycleError({
52586
51869
  operation: "keybindingsRuntimeStart",
@@ -52588,7 +51871,7 @@ const createServer = fn(function* () {
52588
51871
  })));
52589
51872
  yield* readiness.markKeybindingsReady;
52590
51873
  const normalizeProjectWorkspaceRoot = fnUntraced(function* (workspaceRoot) {
52591
- const normalizedWorkspaceRoot = path.resolve(yield* expandHomePath(workspaceRoot.trim()));
51874
+ const normalizedWorkspaceRoot = path.resolve(yield* expandHomePath$1(workspaceRoot.trim()));
52592
51875
  const workspaceStat = yield* fileSystem.stat(normalizedWorkspaceRoot).pipe(catch_(() => succeed(null)));
52593
51876
  if (!workspaceStat) return yield* new RouteRequestError({ message: `Project directory does not exist: ${normalizedWorkspaceRoot}` });
52594
51877
  if (workspaceStat.type !== "Directory") return yield* new RouteRequestError({ message: `Project path is not a directory: ${normalizedWorkspaceRoot}` });
@@ -52970,7 +52253,9 @@ const createServer = fn(function* () {
52970
52253
  reason: "projectPolicy",
52971
52254
  issues: [],
52972
52255
  providers: providerStatuses,
52973
- projectPolicy
52256
+ projectPolicy,
52257
+ agentChat: agentChatConfig,
52258
+ generalChat: generalChatConfig
52974
52259
  });
52975
52260
  })).pipe(forkIn(subscriptionsScope));
52976
52261
  yield* runForEach(keybindingsManager.streamChanges, (event) => gen(function* () {
@@ -52981,7 +52266,9 @@ const createServer = fn(function* () {
52981
52266
  reason: "keybindings",
52982
52267
  issues: event.issues,
52983
52268
  providers: providerStatuses,
52984
- projectPolicy
52269
+ projectPolicy,
52270
+ agentChat: agentChatConfig,
52271
+ generalChat: generalChatConfig
52985
52272
  });
52986
52273
  })).pipe(forkIn(subscriptionsScope));
52987
52274
  yield* provide$2(orchestrationReactor.start, subscriptionsScope);
@@ -53146,7 +52433,7 @@ const createServer = fn(function* () {
53146
52433
  watchedGitStatusCwdsByClient.delete(client);
53147
52434
  for (const cwd of watchedCwds) removeGitStatusWatcherSubscriber(client, cwd);
53148
52435
  };
53149
- yield* addFinalizer$1(sync(() => {
52436
+ yield* addFinalizer$1(() => sync(() => {
53150
52437
  for (const watcher of watchedGitStatusesByCwd.values()) clearInterval(watcher.intervalId);
53151
52438
  watchedGitStatusesByCwd.clear();
53152
52439
  }));
@@ -53161,9 +52448,14 @@ const createServer = fn(function* () {
53161
52448
  writeSettings: (settings) => writeAppSettings(settings),
53162
52449
  isProEnabled: async () => (await licenseService.getStatus()).isPro
53163
52450
  });
53164
- yield* promise(async () => {
53165
- await telegramBridge.applyRuntimeSettings(await readResolvedTelegramRuntimeSettings());
53166
- });
52451
+ let telegramRuntimeSettingsQueue = Promise.resolve();
52452
+ const queueTelegramRuntimeSettingsApply = (settings) => {
52453
+ const applyTask = telegramRuntimeSettingsQueue.catch(() => void 0).then(async () => {
52454
+ await telegramBridge.applyRuntimeSettings(settings);
52455
+ });
52456
+ telegramRuntimeSettingsQueue = applyTask.catch(() => void 0);
52457
+ return applyTask;
52458
+ };
53167
52459
  yield* addFinalizer$1(() => promise(() => telegramBridge.dispose()));
53168
52460
  const refreshTray = () => {
53169
52461
  sendDesktopParentMessage$1({ type: "t3-server:refresh-tray" });
@@ -53241,6 +52533,9 @@ const createServer = fn(function* () {
53241
52533
  });
53242
52534
  });
53243
52535
  yield* readiness.markHttpListening;
52536
+ readResolvedTelegramRuntimeSettings().then((settings) => queueTelegramRuntimeSettingsApply(settings)).catch((error) => {
52537
+ logger.warn("Failed to apply Telegram runtime settings during startup", { error: error instanceof Error ? error.message : String(error) });
52538
+ });
53244
52539
  yield* addFinalizer$1(() => all([
53245
52540
  closeAllClients,
53246
52541
  closeWebSocketServer.pipe(ignoreCause({ log: true })),
@@ -53269,6 +52564,13 @@ const createServer = fn(function* () {
53269
52564
  catch: (cause) => new RouteRequestError({ message: `Failed to search workspace entries: ${String(cause)}` })
53270
52565
  });
53271
52566
  }
52567
+ case WS_METHODS.filesystemBrowse: {
52568
+ const body = stripRequestTag(request.body);
52569
+ return yield* tryPromise({
52570
+ try: () => browseFilesystemEntries(body),
52571
+ catch: (cause) => new RouteRequestError({ message: `Failed to browse filesystem entries: ${cause instanceof Error ? cause.message : String(cause)}` })
52572
+ });
52573
+ }
53272
52574
  case WS_METHODS.projectsEnsure: {
53273
52575
  const body = stripRequestTag(request.body);
53274
52576
  const workspaceRoot = yield* normalizeProjectWorkspaceRoot(body.cwd);
@@ -53308,6 +52610,68 @@ const createServer = fn(function* () {
53308
52610
  created: true
53309
52611
  };
53310
52612
  }
52613
+ case WS_METHODS.agentChatEnsure: {
52614
+ const workspaceRoot = yield* tryPromise({
52615
+ try: () => ensureAgentChatWorkspaceArtifacts(),
52616
+ catch: (cause) => new RouteRequestError({ message: `Failed to prepare Agent workspace: ${String(cause)}` })
52617
+ });
52618
+ const existingProject = findActiveProjectByCanonicalRoot((yield* projectionReadModelQuery.getSnapshot()).projects, workspaceRoot);
52619
+ if (existingProject) return {
52620
+ projectId: existingProject.id,
52621
+ workspaceRoot: existingProject.workspaceRoot,
52622
+ created: false
52623
+ };
52624
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
52625
+ const projectId = ProjectId.makeUnsafe(crypto.randomUUID());
52626
+ yield* orchestrationEngine.dispatch({
52627
+ type: "project.create",
52628
+ commandId: CommandId.makeUnsafe(crypto.randomUUID()),
52629
+ projectId,
52630
+ title: AGENT_CHAT_PROJECT_TITLE,
52631
+ workspaceRoot,
52632
+ defaultModelSelection: {
52633
+ provider: "codex",
52634
+ model: DEFAULT_MODEL_BY_PROVIDER.codex
52635
+ },
52636
+ createdAt
52637
+ });
52638
+ return {
52639
+ projectId,
52640
+ workspaceRoot,
52641
+ created: true
52642
+ };
52643
+ }
52644
+ case WS_METHODS.generalChatEnsure: {
52645
+ const workspaceRoot = yield* tryPromise({
52646
+ try: () => ensureGeneralChatWorkspaceArtifacts(),
52647
+ catch: (cause) => new RouteRequestError({ message: `Failed to prepare General Chat workspace: ${String(cause)}` })
52648
+ });
52649
+ const existingProject = findActiveProjectByCanonicalRoot((yield* projectionReadModelQuery.getSnapshot()).projects, workspaceRoot);
52650
+ if (existingProject) return {
52651
+ projectId: existingProject.id,
52652
+ workspaceRoot: existingProject.workspaceRoot,
52653
+ created: false
52654
+ };
52655
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
52656
+ const projectId = ProjectId.makeUnsafe(crypto.randomUUID());
52657
+ yield* orchestrationEngine.dispatch({
52658
+ type: "project.create",
52659
+ commandId: CommandId.makeUnsafe(crypto.randomUUID()),
52660
+ projectId,
52661
+ title: GENERAL_CHAT_PROJECT_TITLE,
52662
+ workspaceRoot,
52663
+ defaultModelSelection: {
52664
+ provider: "codex",
52665
+ model: DEFAULT_MODEL_BY_PROVIDER.codex
52666
+ },
52667
+ createdAt
52668
+ });
52669
+ return {
52670
+ projectId,
52671
+ workspaceRoot,
52672
+ created: true
52673
+ };
52674
+ }
53311
52675
  case WS_METHODS.projectsWriteFile: {
53312
52676
  const body = stripRequestTag(request.body);
53313
52677
  const target = yield* resolveWorkspaceWritePath({
@@ -53361,7 +52725,10 @@ const createServer = fn(function* () {
53361
52725
  }
53362
52726
  case WS_METHODS.gitCreateWorktree: {
53363
52727
  const body = stripRequestTag(request.body);
53364
- return yield* git.createWorktree(body);
52728
+ const result = yield* git.createWorktree(body);
52729
+ yield* promise(() => scheduleWatchedGitStatusRefresh(body.cwd));
52730
+ yield* promise(() => scheduleWatchedGitStatusRefresh(result.worktree.path));
52731
+ return result;
53365
52732
  }
53366
52733
  case WS_METHODS.gitRemoveWorktree: {
53367
52734
  const body = stripRequestTag(request.body);
@@ -53369,11 +52736,15 @@ const createServer = fn(function* () {
53369
52736
  }
53370
52737
  case WS_METHODS.gitCreateBranch: {
53371
52738
  const body = stripRequestTag(request.body);
53372
- return yield* git.createBranch(body);
52739
+ const result = yield* git.createBranch(body);
52740
+ yield* promise(() => scheduleWatchedGitStatusRefresh(body.cwd));
52741
+ return result;
53373
52742
  }
53374
52743
  case WS_METHODS.gitCheckout: {
53375
52744
  const body = stripRequestTag(request.body);
53376
- return yield* scoped(git.checkoutBranch(body));
52745
+ const result = yield* scoped(git.checkoutBranch(body));
52746
+ yield* promise(() => scheduleWatchedGitStatusRefresh(body.cwd));
52747
+ return result;
53377
52748
  }
53378
52749
  case WS_METHODS.gitInit: {
53379
52750
  const body = stripRequestTag(request.body);
@@ -53414,7 +52785,9 @@ const createServer = fn(function* () {
53414
52785
  issues: keybindingsConfig.issues,
53415
52786
  providers,
53416
52787
  availableEditors,
53417
- projectPolicy
52788
+ projectPolicy,
52789
+ agentChat: agentChatConfig,
52790
+ generalChat: generalChatConfig
53418
52791
  };
53419
52792
  }
53420
52793
  case WS_METHODS.serverRefreshProviders: {
@@ -53446,7 +52819,7 @@ const createServer = fn(function* () {
53446
52819
  const body = stripRequestTag(request.body);
53447
52820
  return yield* promise(async () => {
53448
52821
  return await writeAppSettings(await sanitizeAccountPoolSettingsForLicense(body.settings), async (updatedSettings) => {
53449
- await telegramBridge.applyRuntimeSettings(resolveTelegramRuntimeSettings(updatedSettings));
52822
+ await queueTelegramRuntimeSettingsApply(resolveTelegramRuntimeSettings(updatedSettings));
53450
52823
  });
53451
52824
  });
53452
52825
  }
@@ -53802,10 +53175,6 @@ const createServer = fn(function* () {
53802
53175
  });
53803
53176
  return result;
53804
53177
  }
53805
- case WS_METHODS.analyticsGetData: {
53806
- const body = stripRequestTag(request.body);
53807
- return yield* promise(() => loadAnalyticsData(body.query ?? void 0));
53808
- }
53809
53178
  default: return yield* new RouteRequestError({ message: `Unknown method: ${String(request.body._tag)}` });
53810
53179
  }
53811
53180
  });
@@ -55416,7 +54785,9 @@ const layer = /* @__PURE__ */ layerMergedServices(/* @__PURE__ */ succeed(fetch$
55416
54785
  //#endregion
55417
54786
  //#region src/index.ts
55418
54787
  const RuntimeLayer = empty$6.pipe(provideMerge(CliConfig.layer), provideMerge(ServerLive), provideMerge(OpenLive), provideMerge(NetService.layer), provideMerge(layer$2), provideMerge(layer));
55419
- run$1(t3Cli, { version }).pipe(provide(RuntimeLayer), runMain);
54788
+ const program = run$1(t3Cli, { version });
54789
+ const runnableProgram = provide(program, RuntimeLayer);
54790
+ runMain(runnableProgram);
55420
54791
  //#endregion
55421
54792
  export { make$13 as n, get$1 as t };
55422
54793