codexuse-cli 3.9.9 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,8 +16,8 @@ import { fileURLToPath } from "node:url";
16
16
  import * as readline$1 from "node:readline";
17
17
  import readline from "node:readline";
18
18
  import * as Net from "node:net";
19
- import fs$1, { mkdir, readFile, stat, writeFile } from "node:fs/promises";
20
19
  import { AsyncLocalStorage } from "node:async_hooks";
20
+ import fs$1, { mkdir, readFile, stat, writeFile } from "node:fs/promises";
21
21
  import { EventEmitter } from "node:events";
22
22
  import path, { join as join$1 } from "path";
23
23
  import util from "node:util";
@@ -30084,7 +30084,7 @@ function make$17(get, mapInput, prefix) {
30084
30084
  function fromEnv(options) {
30085
30085
  const env = options?.env ?? {
30086
30086
  ...globalThis?.process?.env,
30087
- ...import.meta?.env
30087
+ ...import.meta.env
30088
30088
  };
30089
30089
  const trie = buildEnvTrie(env);
30090
30090
  return make$17((path) => succeed$2(nodeAtEnv(trie, env, path)));
@@ -46235,377 +46235,1905 @@ var NetService = class NetService extends Service()("@t3tools/shared/Net/NetServ
46235
46235
  }
46236
46236
  };
46237
46237
  //#endregion
46238
- //#region src/config.ts
46239
- /**
46240
- * ServerConfig - Runtime configuration services.
46241
- *
46242
- * Defines process-level server configuration and networking helpers used by
46243
- * startup and runtime layers.
46244
- *
46245
- * @module ServerConfig
46246
- */
46247
- const DEFAULT_PORT = 3773;
46248
- /**
46249
- * ServerConfig - Service tag for server runtime configuration.
46250
- */
46251
- var ServerConfig$1 = class ServerConfig$1 extends Service()("t3/config/ServerConfig") {
46252
- static {
46253
- this.layerTest = (cwd, statedir) => effect(ServerConfig$1, gen(function* () {
46254
- return {
46255
- cwd,
46256
- stateDir: statedir,
46257
- mode: "web",
46258
- autoBootstrapProjectFromCwd: false,
46259
- logWebSocketEvents: false,
46260
- port: 0,
46261
- host: void 0,
46262
- authToken: void 0,
46263
- keybindingsConfigPath: (yield* Path$1).join(statedir, "keybindings.json"),
46264
- staticDir: void 0,
46265
- devUrl: void 0,
46266
- noBrowser: false
46267
- };
46268
- }));
46238
+ //#region ../../packages/contracts/src/settings/chat-scrollback.ts
46239
+ const CHAT_SCROLLBACK_DEFAULT = 200;
46240
+ const CHAT_SCROLLBACK_MIN = 50;
46241
+ const CHAT_SCROLLBACK_MAX = 5e3;
46242
+ function clampChatScrollbackItems(value) {
46243
+ if (!Number.isFinite(value)) return 200;
46244
+ return Math.max(50, Math.min(CHAT_SCROLLBACK_MAX, Math.round(value)));
46245
+ }
46246
+ function normalizeChatHistoryScrollbackItems(value) {
46247
+ if (value === null) return null;
46248
+ if (typeof value === "number" && Number.isFinite(value)) return clampChatScrollbackItems(value);
46249
+ if (typeof value === "string") {
46250
+ const parsed = Number(value);
46251
+ if (Number.isFinite(parsed)) return clampChatScrollbackItems(parsed);
46269
46252
  }
46270
- };
46271
- const resolveStaticDir = fn(function* () {
46272
- const { join, resolve } = yield* Path$1;
46273
- const { exists } = yield* FileSystem;
46274
- const bundledClient = resolve(join(import.meta.dirname, "client"));
46275
- if (yield* exists(join(bundledClient, "index.html")).pipe(orElseSucceed(() => false))) return bundledClient;
46276
- const monorepoClient = resolve(join(import.meta.dirname, "../../web/dist"));
46277
- if (yield* exists(join(monorepoClient, "index.html")).pipe(orElseSucceed(() => false))) return monorepoClient;
46278
- });
46253
+ return 200;
46254
+ }
46279
46255
  //#endregion
46280
- //#region ../../packages/t3-shared/src/shell.ts
46281
- const SHELL_ENV_NAME_PATTERN = /^[A-Z0-9_]+$/;
46282
- function readPathFromLoginShell(shell, execFile = execFileSync) {
46283
- return readEnvironmentFromLoginShell(shell, ["PATH"], execFile).PATH;
46256
+ //#region ../../packages/contracts/src/settings/commit-message-prompt.ts
46257
+ const DEFAULT_COMMIT_MESSAGE_PROMPT = `Generate a concise git commit message for the following changes. Follow conventional commit format (e.g., feat:, fix:, refactor:, docs:, etc.). Keep the summary line under 72 characters. Only output the commit message, nothing else.
46258
+
46259
+ Changes:
46260
+ {diff}`;
46261
+ function normalizeLineEndings$1(value) {
46262
+ return value.replace(/\r\n/g, "\n");
46284
46263
  }
46285
- function envCaptureStart(name) {
46286
- return `__T3CODE_ENV_${name}_START__`;
46264
+ function normalizeCommitMessagePrompt(value) {
46265
+ if (typeof value !== "string") return null;
46266
+ const normalized = normalizeLineEndings$1(value).trim();
46267
+ return normalized.length > 0 ? normalized : null;
46287
46268
  }
46288
- function envCaptureEnd(name) {
46289
- return `__T3CODE_ENV_${name}_END__`;
46269
+ //#endregion
46270
+ //#region ../../packages/contracts/src/settings/auto-roll.ts
46271
+ const DEFAULT_AUTO_ROLL_ENABLED = false;
46272
+ const DEFAULT_AUTO_ROLL_REARM_REMAINING_THRESHOLD = 15;
46273
+ const DEFAULT_AUTO_ROLL_SWITCH_REMAINING_THRESHOLD = 5;
46274
+ const DEFAULT_RESTART_OFFICIAL_CODEX_ON_AUTO_ROLL = false;
46275
+ const DEFAULT_LAUNCH_OFFICIAL_CODEX_WHEN_CLOSED_ON_AUTO_ROLL = false;
46276
+ const DEFAULT_AUTO_ROLL_PRIORITY_ORDER = [];
46277
+ const DEFAULT_LOW_REMAINING_NOTIFICATION_ENABLED = false;
46278
+ const DEFAULT_LOW_REMAINING_NOTIFICATION_THRESHOLD = 1;
46279
+ const AUTO_ROLL_SWITCH_REMAINING_MIN = 0;
46280
+ const AUTO_ROLL_SWITCH_REMAINING_MAX = 50;
46281
+ const AUTO_ROLL_REARM_REMAINING_MAX = 100;
46282
+ const LOW_REMAINING_NOTIFICATION_MIN = 1;
46283
+ const LOW_REMAINING_NOTIFICATION_MAX = 50;
46284
+ function clampNumber(value, min, max) {
46285
+ return Math.min(max, Math.max(min, value));
46290
46286
  }
46291
- function buildEnvironmentCaptureCommand(names) {
46292
- return names.map((name) => {
46293
- if (!SHELL_ENV_NAME_PATTERN.test(name)) throw new Error(`Unsupported environment variable name: ${name}`);
46294
- return [
46295
- `printf '%s\\n' '${envCaptureStart(name)}'`,
46296
- `printenv ${name} || true`,
46297
- `printf '%s\\n' '${envCaptureEnd(name)}'`
46298
- ].join("; ");
46299
- }).join("; ");
46287
+ function resolveFiniteNumber(value, fallback) {
46288
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
46300
46289
  }
46301
- function extractEnvironmentValue(output, name) {
46302
- const startMarker = envCaptureStart(name);
46303
- const endMarker = envCaptureEnd(name);
46304
- const startIndex = output.indexOf(startMarker);
46305
- if (startIndex === -1) return void 0;
46306
- const valueStartIndex = startIndex + startMarker.length;
46307
- const endIndex = output.indexOf(endMarker, valueStartIndex);
46308
- if (endIndex === -1) return void 0;
46309
- let value = output.slice(valueStartIndex, endIndex);
46310
- if (value.startsWith("\n")) value = value.slice(1);
46311
- if (value.endsWith("\n")) value = value.slice(0, -1);
46312
- return value.length > 0 ? value : void 0;
46290
+ function legacyUsedThresholdToRemaining(value, fallbackUsed) {
46291
+ return 100 - clampNumber(resolveFiniteNumber(value, fallbackUsed), 0, 100);
46313
46292
  }
46314
- const readEnvironmentFromLoginShell = (shell, names, execFile = execFileSync) => {
46315
- if (names.length === 0) return {};
46316
- const output = execFile(shell, ["-ilc", buildEnvironmentCaptureCommand(names)], {
46317
- encoding: "utf8",
46318
- timeout: 5e3
46319
- });
46320
- const environment = {};
46321
- for (const name of names) {
46322
- const value = extractEnvironmentValue(output, name);
46323
- if (value !== void 0) environment[name] = value;
46293
+ function sanitizeAutoRollSwitchRemainingThreshold(value) {
46294
+ return clampNumber(resolveFiniteNumber(value, 5), 0, 50);
46295
+ }
46296
+ function sanitizeAutoRollRearmRemainingThreshold(value, switchRemainingThreshold) {
46297
+ const sanitizedSwitch = sanitizeAutoRollSwitchRemainingThreshold(switchRemainingThreshold);
46298
+ return clampNumber(resolveFiniteNumber(value, 15), sanitizedSwitch + 1, 100);
46299
+ }
46300
+ function sanitizeAutoRollThresholds(rearmRemainingThreshold, switchRemainingThreshold) {
46301
+ const sanitizedSwitch = sanitizeAutoRollSwitchRemainingThreshold(switchRemainingThreshold);
46302
+ return {
46303
+ rearmRemainingThreshold: sanitizeAutoRollRearmRemainingThreshold(rearmRemainingThreshold, sanitizedSwitch),
46304
+ switchRemainingThreshold: sanitizedSwitch
46305
+ };
46306
+ }
46307
+ function sanitizeAutoRollPriorityOrder(value) {
46308
+ if (!Array.isArray(value)) return [...DEFAULT_AUTO_ROLL_PRIORITY_ORDER];
46309
+ const seen = /* @__PURE__ */ new Set();
46310
+ const normalized = [];
46311
+ for (const item of value) {
46312
+ if (typeof item !== "string") continue;
46313
+ const trimmed = item.trim();
46314
+ if (!trimmed || seen.has(trimmed)) continue;
46315
+ seen.add(trimmed);
46316
+ normalized.push(trimmed);
46324
46317
  }
46325
- return environment;
46326
- };
46318
+ return normalized;
46319
+ }
46320
+ function sanitizeLowRemainingNotificationThreshold(value) {
46321
+ return clampNumber(resolveFiniteNumber(value, 1), 1, 50);
46322
+ }
46323
+ function normalizeAutoRollSettings(raw) {
46324
+ const enabled = typeof raw?.enabled === "boolean" ? raw.enabled : false;
46325
+ const rawSwitchRemaining = typeof raw?.switchRemainingThreshold === "number" ? raw.switchRemainingThreshold : legacyUsedThresholdToRemaining(raw?.switchThreshold, 95);
46326
+ const { rearmRemainingThreshold: normalizedRearm, switchRemainingThreshold: normalizedSwitch } = sanitizeAutoRollThresholds(typeof raw?.rearmRemainingThreshold === "number" ? raw.rearmRemainingThreshold : legacyUsedThresholdToRemaining(raw?.warningThreshold, 85), rawSwitchRemaining);
46327
+ return {
46328
+ enabled,
46329
+ rearmRemainingThreshold: normalizedRearm,
46330
+ switchRemainingThreshold: normalizedSwitch,
46331
+ restartOfficialCodexOnAutoRoll: raw?.restartOfficialCodexOnAutoRoll === true ? true : false,
46332
+ launchOfficialCodexWhenClosedOnAutoRoll: raw?.launchOfficialCodexWhenClosedOnAutoRoll === true ? true : false,
46333
+ priorityOrder: sanitizeAutoRollPriorityOrder(raw?.priorityOrder),
46334
+ lowRemainingNotificationEnabled: raw?.lowRemainingNotificationEnabled === true ? true : false,
46335
+ lowRemainingNotificationThreshold: sanitizeLowRemainingNotificationThreshold(typeof raw?.lowRemainingNotificationThreshold === "number" ? raw.lowRemainingNotificationThreshold : NaN)
46336
+ };
46337
+ }
46327
46338
  //#endregion
46328
- //#region src/os-jank.ts
46329
- function fixPath() {
46330
- if (process.platform !== "darwin") return;
46339
+ //#region ../../packages/runtime-app-state/src/storage/documents.ts
46340
+ const APP_STORAGE_TABLE = "app_storage_documents";
46341
+ const APP_STORAGE_DB_DIR = "t3-projects";
46342
+ const APP_STORAGE_DB_NAME = "state.sqlite";
46343
+ const SQLITE_BUSY_TIMEOUT_MS = 5e3;
46344
+ const SQLITE_BUSY_MAX_ATTEMPTS = 3;
46345
+ const SQLITE_BUSY_RETRY_DELAY_MS = 100;
46346
+ const writeQueueByDbPath = /* @__PURE__ */ new Map();
46347
+ const initializedDbPaths = /* @__PURE__ */ new Set();
46348
+ var AppStorageCorruptionError = class extends Error {
46349
+ constructor(message, options) {
46350
+ super(message);
46351
+ this.name = "AppStorageCorruptionError";
46352
+ this.dbPath = options.dbPath;
46353
+ this.namespace = options.namespace ?? null;
46354
+ if (options.cause !== void 0) this.cause = options.cause;
46355
+ }
46356
+ };
46357
+ function isRecord$9(value) {
46358
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
46359
+ }
46360
+ function clone$1(value) {
46361
+ return JSON.parse(JSON.stringify(value));
46362
+ }
46363
+ function safeParseJson(raw) {
46364
+ if (typeof raw !== "string" || raw.trim().length === 0) return null;
46331
46365
  try {
46332
- const result = readPathFromLoginShell(process.env.SHELL ?? "/bin/zsh");
46333
- if (result) process.env.PATH = result;
46366
+ return JSON.parse(raw);
46367
+ } catch {
46368
+ return null;
46369
+ }
46370
+ }
46371
+ function parseJsonStrict(raw, options) {
46372
+ if (typeof raw !== "string" || raw.trim().length === 0) return null;
46373
+ try {
46374
+ return JSON.parse(raw);
46375
+ } catch (error) {
46376
+ throw new AppStorageCorruptionError(`App storage document ${options.namespace} contains invalid JSON.`, {
46377
+ dbPath: options.dbPath,
46378
+ namespace: options.namespace,
46379
+ cause: error
46380
+ });
46381
+ }
46382
+ }
46383
+ function sleep(ms) {
46384
+ return new Promise((resolve) => setTimeout(resolve, ms));
46385
+ }
46386
+ function isSqliteBusyError(error) {
46387
+ if (!error || typeof error !== "object") return false;
46388
+ const sqliteError = error;
46389
+ if (sqliteError.cause && sqliteError.cause !== error && isSqliteBusyError(sqliteError.cause)) return true;
46390
+ if (sqliteError.error && sqliteError.error !== error && isSqliteBusyError(sqliteError.error)) return true;
46391
+ const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : String(error).toLowerCase();
46392
+ return sqliteError.code === "SQLITE_BUSY" || sqliteError.errno === 5 || message.includes("sqlite_busy") || message.includes("database is locked");
46393
+ }
46394
+ function isSqliteCorruptionError(error) {
46395
+ if (!error || typeof error !== "object") return false;
46396
+ const sqliteError = error;
46397
+ if (sqliteError.cause && sqliteError.cause !== error && isSqliteCorruptionError(sqliteError.cause)) return true;
46398
+ if (sqliteError.error && sqliteError.error !== error && isSqliteCorruptionError(sqliteError.error)) return true;
46399
+ const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : "";
46400
+ return sqliteError.code === "SQLITE_CORRUPT" || sqliteError.code === "SQLITE_NOTADB" || sqliteError.errno === 11 || sqliteError.errno === 26 || message.includes("database disk image is malformed") || message.includes("file is not a database") || message.includes("database corruption") || message.includes("sqlite_corrupt") || message.includes("sqlite_notadb");
46401
+ }
46402
+ function isAppStorageCorruptionError(error) {
46403
+ return error instanceof AppStorageCorruptionError || isSqliteCorruptionError(error);
46404
+ }
46405
+ function beginImmediate(db) {
46406
+ db.exec("BEGIN IMMEDIATE");
46407
+ }
46408
+ function commit(db) {
46409
+ db.exec("COMMIT");
46410
+ }
46411
+ function rollback(db) {
46412
+ try {
46413
+ db.exec("ROLLBACK");
46334
46414
  } catch {}
46335
46415
  }
46336
- const expandHomePath$1 = fn(function* (input) {
46337
- const { join } = yield* Path$1;
46338
- if (input === "~") return OS.homedir();
46339
- if (input.startsWith("~/") || input.startsWith("~\\")) return join(OS.homedir(), input.slice(2));
46340
- return input;
46341
- });
46342
- const resolveStateDir = fn(function* (raw) {
46343
- const { join, resolve } = yield* Path$1;
46344
- if (!raw || raw.trim().length === 0) return join(OS.homedir(), ".t3", "userdata");
46345
- return resolve(yield* expandHomePath$1(raw.trim()));
46346
- });
46347
- //#endregion
46348
- //#region ../../packages/t3-contracts/src/baseSchemas.ts
46349
- const TrimmedString = Trim;
46350
- const TrimmedNonEmptyString = TrimmedString.check(isNonEmpty());
46351
- const NonNegativeInt = Int.check(isGreaterThanOrEqualTo(0));
46352
- const PositiveInt = Int.check(isGreaterThanOrEqualTo(1));
46353
- const IsoDateTime = String$1;
46354
- /**
46355
- * Construct a branded identifier. Enforces non-empty trimmed strings
46356
- */
46357
- const makeEntityId = (brand$2) => TrimmedNonEmptyString.pipe(brand(brand$2));
46358
- const ThreadId = makeEntityId("ThreadId");
46359
- const ProjectId = makeEntityId("ProjectId");
46360
- const CommandId = makeEntityId("CommandId");
46361
- const EventId = makeEntityId("EventId");
46362
- const MessageId = makeEntityId("MessageId");
46363
- const TurnId = makeEntityId("TurnId");
46364
- const ProviderItemId = makeEntityId("ProviderItemId");
46365
- const RuntimeSessionId = makeEntityId("RuntimeSessionId");
46366
- const RuntimeItemId = makeEntityId("RuntimeItemId");
46367
- const RuntimeRequestId = makeEntityId("RuntimeRequestId");
46368
- const RuntimeTaskId = makeEntityId("RuntimeTaskId");
46369
- const ApprovalRequestId = makeEntityId("ApprovalRequestId");
46370
- const CheckpointRef = makeEntityId("CheckpointRef");
46371
- //#endregion
46372
- //#region ../../packages/t3-contracts/src/terminal.ts
46373
- const DEFAULT_TERMINAL_ID = "default";
46374
- const TrimmedNonEmptyStringSchema$3 = TrimmedNonEmptyString;
46375
- const TerminalColsSchema = Int.check(isGreaterThanOrEqualTo(1)).check(isLessThanOrEqualTo(1e3));
46376
- const TerminalRowsSchema = Int.check(isGreaterThanOrEqualTo(1)).check(isLessThanOrEqualTo(500));
46377
- const TerminalIdSchema = TrimmedNonEmptyStringSchema$3.check(isMaxLength(128));
46378
- const TerminalEnvKeySchema = String$1.check(isPattern(/^[A-Za-z_][A-Za-z0-9_]*$/)).check(isMaxLength(128));
46379
- const TerminalEnvValueSchema = String$1.check(isMaxLength(8192));
46380
- const TerminalEnvSchema = Record(TerminalEnvKeySchema, TerminalEnvValueSchema).check(isMaxProperties(128));
46381
- const TerminalIdWithDefaultSchema = TerminalIdSchema.pipe(withDecodingDefault(() => DEFAULT_TERMINAL_ID));
46382
- const TerminalThreadInput = Struct({ threadId: TrimmedNonEmptyStringSchema$3 });
46383
- const TerminalSessionInput = Struct({
46384
- ...TerminalThreadInput.fields,
46385
- terminalId: TerminalIdWithDefaultSchema
46386
- });
46387
- const TerminalOpenInput = Struct({
46388
- ...TerminalSessionInput.fields,
46389
- cwd: TrimmedNonEmptyStringSchema$3,
46390
- cols: optional$2(TerminalColsSchema),
46391
- rows: optional$2(TerminalRowsSchema),
46392
- env: optional$2(TerminalEnvSchema)
46393
- });
46394
- const TerminalWriteInput = Struct({
46395
- ...TerminalSessionInput.fields,
46396
- data: String$1.check(isNonEmpty()).check(isMaxLength(65536))
46397
- });
46398
- const TerminalResizeInput = Struct({
46399
- ...TerminalSessionInput.fields,
46400
- cols: TerminalColsSchema,
46401
- rows: TerminalRowsSchema
46402
- });
46403
- const TerminalClearInput = TerminalSessionInput;
46404
- const TerminalRestartInput = Struct({
46405
- ...TerminalSessionInput.fields,
46406
- cwd: TrimmedNonEmptyStringSchema$3,
46407
- cols: TerminalColsSchema,
46408
- rows: TerminalRowsSchema,
46409
- env: optional$2(TerminalEnvSchema)
46410
- });
46411
- const TerminalCloseInput = Struct({
46412
- ...TerminalThreadInput.fields,
46413
- terminalId: optional$2(TerminalIdSchema),
46414
- deleteHistory: optional$2(Boolean$2)
46415
- });
46416
- const TerminalSessionStatus = Literals([
46417
- "starting",
46418
- "running",
46419
- "exited",
46420
- "error"
46421
- ]);
46422
- const TerminalSessionSnapshot = Struct({
46423
- threadId: String$1.check(isNonEmpty()),
46424
- terminalId: String$1.check(isNonEmpty()),
46425
- cwd: String$1.check(isNonEmpty()),
46426
- status: TerminalSessionStatus,
46427
- pid: NullOr(Int.check(isGreaterThan(0))),
46428
- history: String$1,
46429
- exitCode: NullOr(Int),
46430
- exitSignal: NullOr(Int),
46431
- updatedAt: String$1
46432
- });
46433
- const TerminalEventBaseSchema = Struct({
46434
- threadId: String$1.check(isNonEmpty()),
46435
- terminalId: String$1.check(isNonEmpty()),
46436
- createdAt: String$1
46437
- });
46438
- const TerminalStartedEvent = Struct({
46439
- ...TerminalEventBaseSchema.fields,
46440
- type: Literal("started"),
46441
- snapshot: TerminalSessionSnapshot
46442
- });
46443
- const TerminalOutputEvent = Struct({
46444
- ...TerminalEventBaseSchema.fields,
46445
- type: Literal("output"),
46446
- data: String$1
46447
- });
46448
- const TerminalExitedEvent = Struct({
46449
- ...TerminalEventBaseSchema.fields,
46450
- type: Literal("exited"),
46451
- exitCode: NullOr(Int),
46452
- exitSignal: NullOr(Int)
46453
- });
46454
- const TerminalErrorEvent = Struct({
46455
- ...TerminalEventBaseSchema.fields,
46456
- type: Literal("error"),
46457
- message: String$1.check(isNonEmpty())
46458
- });
46459
- const TerminalClearedEvent = Struct({
46460
- ...TerminalEventBaseSchema.fields,
46461
- type: Literal("cleared")
46462
- });
46463
- const TerminalRestartedEvent = Struct({
46464
- ...TerminalEventBaseSchema.fields,
46465
- type: Literal("restarted"),
46466
- snapshot: TerminalSessionSnapshot
46467
- });
46468
- const TerminalActivityEvent = Struct({
46469
- ...TerminalEventBaseSchema.fields,
46470
- type: Literal("activity"),
46471
- hasRunningSubprocess: Boolean$2
46472
- });
46473
- const TerminalEvent = Union([
46474
- TerminalStartedEvent,
46475
- TerminalOutputEvent,
46476
- TerminalExitedEvent,
46477
- TerminalErrorEvent,
46478
- TerminalClearedEvent,
46479
- TerminalRestartedEvent,
46480
- TerminalActivityEvent
46481
- ]);
46482
- //#endregion
46483
- //#region ../../packages/t3-contracts/src/model.ts
46484
- const CODEX_REASONING_EFFORT_OPTIONS = [
46485
- "xhigh",
46486
- "high",
46487
- "medium",
46488
- "low"
46489
- ];
46490
- const CodexModelOptions = Struct({
46491
- reasoningEffort: optional$2(Literals(CODEX_REASONING_EFFORT_OPTIONS)),
46492
- fastMode: optional$2(Boolean$2)
46493
- });
46494
- const ProviderModelOptions = Struct({ codex: optional$2(CodexModelOptions) });
46495
- const MODEL_OPTIONS_BY_PROVIDER = { codex: [
46496
- {
46497
- slug: "gpt-5.5",
46498
- name: "GPT-5.5"
46499
- },
46500
- {
46501
- slug: "gpt-5.4",
46502
- name: "GPT-5.4"
46503
- },
46504
- {
46505
- slug: "gpt-5.4-mini",
46506
- name: "GPT-5.4 Mini"
46507
- },
46508
- {
46509
- slug: "gpt-5.3-codex",
46510
- name: "GPT-5.3 Codex"
46511
- },
46512
- {
46513
- slug: "gpt-5.3-codex-spark",
46514
- name: "GPT-5.3 Codex Spark"
46416
+ function useStatement(db, sql, task) {
46417
+ const statement = db.prepare(sql);
46418
+ try {
46419
+ return task(statement);
46420
+ } finally {
46421
+ statement.finalize?.();
46515
46422
  }
46516
- ] };
46517
- const DEFAULT_MODEL_BY_PROVIDER = { codex: "gpt-5.5" };
46518
- const DEFAULT_GIT_TEXT_GENERATION_MODEL = "gpt-5.4-mini";
46519
- const MODEL_SLUG_ALIASES_BY_PROVIDER = { codex: {
46520
- "gpt-5-codex": "gpt-5.5",
46521
- "5.5": "gpt-5.5",
46522
- "5.4": "gpt-5.4",
46523
- "5.3": "gpt-5.3-codex",
46524
- "gpt-5.3": "gpt-5.3-codex",
46525
- "5.3-spark": "gpt-5.3-codex-spark",
46526
- "gpt-5.3-spark": "gpt-5.3-codex-spark"
46527
- } };
46528
- //#endregion
46529
- //#region ../../packages/t3-contracts/src/orchestration.ts
46530
- const ORCHESTRATION_WS_METHODS = {
46531
- getSnapshot: "orchestration.getSnapshot",
46532
- getThreadSnapshot: "orchestration.getThreadSnapshot",
46533
- subscribeShell: "orchestration.subscribeShell",
46534
- subscribeThread: "orchestration.subscribeThread",
46535
- syncExternalThreads: "orchestration.syncExternalThreads",
46536
- dispatchCommand: "orchestration.dispatchCommand",
46537
- getTurnDiff: "orchestration.getTurnDiff",
46538
- getFullThreadDiff: "orchestration.getFullThreadDiff",
46539
- replayEvents: "orchestration.replayEvents"
46540
- };
46541
- const ORCHESTRATION_WS_CHANNELS = { domainEvent: "orchestration.domainEvent" };
46542
- const ProviderKind = Literal("codex");
46543
- const ProviderApprovalPolicy = Literals([
46544
- "untrusted",
46545
- "on-failure",
46546
- "on-request",
46547
- "never"
46548
- ]);
46549
- const ProviderSandboxMode = Literals([
46550
- "read-only",
46551
- "workspace-write",
46552
- "danger-full-access"
46553
- ]);
46554
- const CodexModelSelection = Struct({
46555
- provider: Literal("codex"),
46556
- model: TrimmedNonEmptyString,
46557
- options: optional$2(CodexModelOptions)
46558
- });
46559
- const ModelSelection = CodexModelSelection;
46560
- const CodexProviderStartOptions$1 = Struct({
46561
- binaryPath: optional$2(TrimmedNonEmptyString),
46562
- args: optional$2(String$1),
46563
- homePath: optional$2(TrimmedNonEmptyString)
46564
- });
46565
- const ProviderStartOptions$1 = Struct({ codex: optional$2(CodexProviderStartOptions$1) });
46566
- const RuntimeMode = Literals(["approval-required", "full-access"]);
46567
- const DEFAULT_RUNTIME_MODE$2 = "full-access";
46568
- const ProviderInteractionMode = Literals(["default", "plan"]);
46569
- const DEFAULT_PROVIDER_INTERACTION_MODE = "default";
46570
- const ThreadOrigin = Literals(["native", "external-import"]);
46571
- const DEFAULT_THREAD_ORIGIN = "native";
46572
- const ProviderRequestKind = Literals([
46573
- "command",
46574
- "file-read",
46575
- "file-change"
46576
- ]);
46577
- const AssistantDeliveryMode = Literals(["buffered", "streaming"]);
46578
- const ProviderApprovalDecision = Literals([
46579
- "accept",
46580
- "acceptForSession",
46581
- "decline",
46582
- "cancel"
46583
- ]);
46584
- const ProviderUserInputAnswers = Record(String$1, Unknown);
46585
- function supportsCheckpointingForThreadOrigin(origin) {
46586
- return origin === "native";
46587
46423
  }
46588
- const PROVIDER_SEND_TURN_MAX_INPUT_CHARS = 12e4;
46589
- const PROVIDER_SEND_TURN_MAX_IMAGE_BYTES = 10 * 1024 * 1024;
46590
- const PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS = 14e6;
46591
- const CHAT_ATTACHMENT_ID_MAX_CHARS = 128;
46592
- const ChatAttachmentId = TrimmedNonEmptyString.check(isMaxLength(CHAT_ATTACHMENT_ID_MAX_CHARS), isPattern(/^[a-z0-9_-]+$/i));
46593
- const ChatImageAttachment = Struct({
46594
- type: Literal("image"),
46595
- id: ChatAttachmentId,
46596
- name: TrimmedNonEmptyString.check(isMaxLength(255)),
46597
- mimeType: TrimmedNonEmptyString.check(isMaxLength(100), isPattern(/^image\//i)),
46598
- sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_IMAGE_BYTES))
46599
- });
46600
- const UploadChatImageAttachment = Struct({
46601
- type: Literal("image"),
46602
- name: TrimmedNonEmptyString.check(isMaxLength(255)),
46603
- mimeType: TrimmedNonEmptyString.check(isMaxLength(100), isPattern(/^image\//i)),
46604
- sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_IMAGE_BYTES)),
46605
- dataUrl: TrimmedNonEmptyString.check(isMaxLength(PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS))
46606
- });
46607
- const ChatAttachment = Union([ChatImageAttachment]);
46608
- const UploadChatAttachment = Union([UploadChatImageAttachment]);
46424
+ async function withWriteQueue(dbPath, task) {
46425
+ const previous = writeQueueByDbPath.get(dbPath) ?? Promise.resolve();
46426
+ let release;
46427
+ const current = new Promise((resolve) => {
46428
+ release = resolve;
46429
+ });
46430
+ writeQueueByDbPath.set(dbPath, current);
46431
+ await previous;
46432
+ try {
46433
+ return await task();
46434
+ } finally {
46435
+ release?.();
46436
+ if (writeQueueByDbPath.get(dbPath) === current) writeQueueByDbPath.delete(dbPath);
46437
+ }
46438
+ }
46439
+ function applyConnectionPragmas(db) {
46440
+ db.exec(`PRAGMA busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS};`);
46441
+ db.exec("PRAGMA journal_mode = WAL;");
46442
+ db.exec("PRAGMA foreign_keys = ON;");
46443
+ }
46444
+ function ensureSchema(db, dbPath) {
46445
+ if (initializedDbPaths.has(dbPath)) return;
46446
+ db.exec(`
46447
+ CREATE TABLE IF NOT EXISTS ${APP_STORAGE_TABLE} (
46448
+ namespace TEXT PRIMARY KEY,
46449
+ value_json TEXT NOT NULL,
46450
+ updated_at TEXT NOT NULL
46451
+ )
46452
+ `);
46453
+ initializedDbPaths.add(dbPath);
46454
+ }
46455
+ async function openDatabase(dbPath) {
46456
+ await promises.mkdir(nodePath.dirname(dbPath), { recursive: true });
46457
+ if (process.versions.bun !== void 0) {
46458
+ const database = new (await (Function("return import('bun:sqlite')")())).Database(dbPath);
46459
+ return {
46460
+ exec: database.exec.bind(database),
46461
+ prepare: database.prepare.bind(database),
46462
+ close: database.close.bind(database)
46463
+ };
46464
+ }
46465
+ const database = new (await (Function("return import('node:sqlite')")())).DatabaseSync(dbPath);
46466
+ return {
46467
+ exec: database.exec.bind(database),
46468
+ prepare: database.prepare.bind(database),
46469
+ close: database.close.bind(database)
46470
+ };
46471
+ }
46472
+ function resetAppStorageInitialization(dbPath) {
46473
+ initializedDbPaths.delete(dbPath);
46474
+ }
46475
+ async function backupCorruptAppStorageDb(dbPath) {
46476
+ const backupPath = `${dbPath}.corrupt-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
46477
+ let moved = false;
46478
+ for (const suffix of [
46479
+ "",
46480
+ "-wal",
46481
+ "-shm"
46482
+ ]) {
46483
+ const source = `${dbPath}${suffix}`;
46484
+ const destination = `${backupPath}${suffix}`;
46485
+ try {
46486
+ if (!(await promises.stat(source)).isFile()) continue;
46487
+ await promises.rename(source, destination);
46488
+ moved = true;
46489
+ } catch (error) {
46490
+ if (error.code !== "ENOENT") throw error;
46491
+ }
46492
+ }
46493
+ resetAppStorageInitialization(dbPath);
46494
+ return moved ? backupPath : null;
46495
+ }
46496
+ async function withDatabase(dbPath, task) {
46497
+ for (let attempt = 1; attempt <= SQLITE_BUSY_MAX_ATTEMPTS; attempt += 1) {
46498
+ let db = null;
46499
+ try {
46500
+ db = await openDatabase(dbPath);
46501
+ applyConnectionPragmas(db);
46502
+ ensureSchema(db, dbPath);
46503
+ return task(db);
46504
+ } catch (error) {
46505
+ if (error instanceof AppStorageCorruptionError) throw error;
46506
+ if (isSqliteCorruptionError(error)) throw new AppStorageCorruptionError("App storage database is corrupt.", {
46507
+ dbPath,
46508
+ cause: error
46509
+ });
46510
+ if (!isSqliteBusyError(error) || attempt >= SQLITE_BUSY_MAX_ATTEMPTS) throw error;
46511
+ } finally {
46512
+ db?.close();
46513
+ }
46514
+ await sleep(SQLITE_BUSY_RETRY_DELAY_MS * attempt);
46515
+ }
46516
+ throw new Error("App storage database remained busy after retrying.");
46517
+ }
46518
+ function resolveAppStorageDbPath(userDataDir) {
46519
+ return nodePath.join(userDataDir, APP_STORAGE_DB_DIR, APP_STORAGE_DB_NAME);
46520
+ }
46521
+ async function readDocument(dbPath, namespace, normalize) {
46522
+ return withDatabase(dbPath, (db) => {
46523
+ const row = useStatement(db, `SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`, (statement) => statement.get(namespace));
46524
+ const parsed = isRecord$9(row) ? safeParseJson(row.valueJson) : null;
46525
+ if (parsed === null) return null;
46526
+ return normalize(parsed);
46527
+ });
46528
+ }
46529
+ async function readDocumentStrict(dbPath, namespace, normalize) {
46530
+ return withDatabase(dbPath, (db) => {
46531
+ const row = useStatement(db, `SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`, (statement) => statement.get(namespace));
46532
+ if (!isRecord$9(row)) return null;
46533
+ const parsed = parseJsonStrict(row.valueJson, {
46534
+ dbPath,
46535
+ namespace
46536
+ });
46537
+ if (parsed === null) throw new AppStorageCorruptionError(`App storage document ${namespace} is empty.`, {
46538
+ dbPath,
46539
+ namespace
46540
+ });
46541
+ try {
46542
+ return normalize(parsed);
46543
+ } catch (error) {
46544
+ throw new AppStorageCorruptionError(`App storage document ${namespace} failed normalization.`, {
46545
+ dbPath,
46546
+ namespace,
46547
+ cause: error
46548
+ });
46549
+ }
46550
+ });
46551
+ }
46552
+ async function writeDocument(dbPath, namespace, value) {
46553
+ return withWriteQueue(dbPath, async () => withDatabase(dbPath, (db) => {
46554
+ const normalizedValue = clone$1(value);
46555
+ beginImmediate(db);
46556
+ try {
46557
+ useStatement(db, `
46558
+ INSERT INTO ${APP_STORAGE_TABLE} (namespace, value_json, updated_at)
46559
+ VALUES (?, ?, ?)
46560
+ ON CONFLICT(namespace)
46561
+ DO UPDATE SET
46562
+ value_json = excluded.value_json,
46563
+ updated_at = excluded.updated_at
46564
+ `, (statement) => statement.run(namespace, JSON.stringify(normalizedValue), (/* @__PURE__ */ new Date()).toISOString()));
46565
+ commit(db);
46566
+ return normalizedValue;
46567
+ } catch (error) {
46568
+ rollback(db);
46569
+ throw error;
46570
+ }
46571
+ }));
46572
+ }
46573
+ async function updateDocument(input) {
46574
+ return withWriteQueue(input.dbPath, async () => withDatabase(input.dbPath, (db) => {
46575
+ beginImmediate(db);
46576
+ try {
46577
+ const row = useStatement(db, `SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`, (statement) => statement.get(input.namespace));
46578
+ const current = isRecord$9(row) ? input.normalize(safeParseJson(row.valueJson) ?? input.fallback()) : input.fallback();
46579
+ const next = input.normalize(input.transform(clone$1(current)));
46580
+ useStatement(db, `
46581
+ INSERT INTO ${APP_STORAGE_TABLE} (namespace, value_json, updated_at)
46582
+ VALUES (?, ?, ?)
46583
+ ON CONFLICT(namespace)
46584
+ DO UPDATE SET
46585
+ value_json = excluded.value_json,
46586
+ updated_at = excluded.updated_at
46587
+ `, (statement) => statement.run(input.namespace, JSON.stringify(next), (/* @__PURE__ */ new Date()).toISOString()));
46588
+ commit(db);
46589
+ return clone$1(next);
46590
+ } catch (error) {
46591
+ rollback(db);
46592
+ throw error;
46593
+ }
46594
+ }));
46595
+ }
46596
+ //#endregion
46597
+ //#region ../../packages/runtime-app-state/src/app/state.ts
46598
+ const LEGACY_APP_STATE_FILE = "app-state.json";
46599
+ const APP_STATE_DOCUMENT = "desktop.app-state";
46600
+ const APP_NAME = "codexuse-desktop";
46601
+ let configuredUserDataDir = null;
46602
+ let appStateCache = null;
46603
+ let writeLock = Promise.resolve();
46604
+ const writeLockContext = new AsyncLocalStorage();
46605
+ function isRecord$8(value) {
46606
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
46607
+ }
46608
+ function clone(value) {
46609
+ return JSON.parse(JSON.stringify(value));
46610
+ }
46611
+ function resolveDefaultUserDataDir() {
46612
+ const home = process.env.HOME || process.env.USERPROFILE || nodeOs.homedir();
46613
+ if (!home) throw new Error("Unable to resolve home directory for app state.");
46614
+ if (process.platform === "darwin") return nodePath.join(home, "Library", "Application Support", APP_NAME);
46615
+ if (process.platform === "win32") {
46616
+ const appData = process.env.APPDATA;
46617
+ if (appData) return nodePath.join(appData, APP_NAME);
46618
+ return nodePath.join(home, "AppData", "Roaming", APP_NAME);
46619
+ }
46620
+ return nodePath.join(home, ".config", APP_NAME);
46621
+ }
46622
+ function getUserDataDir() {
46623
+ return configuredUserDataDir ?? resolveDefaultUserDataDir();
46624
+ }
46625
+ function resolveLegacyAppStatePath() {
46626
+ return nodePath.join(getUserDataDir(), LEGACY_APP_STATE_FILE);
46627
+ }
46628
+ function resolveStorageDbPath() {
46629
+ return resolveAppStorageDbPath(getUserDataDir());
46630
+ }
46631
+ function createDefaultAppState() {
46632
+ return {
46633
+ schemaVersion: 1,
46634
+ autoRoll: {
46635
+ enabled: false,
46636
+ rearmRemainingThreshold: 15,
46637
+ switchRemainingThreshold: 5,
46638
+ restartOfficialCodexOnAutoRoll: false,
46639
+ launchOfficialCodexWhenClosedOnAutoRoll: false,
46640
+ priorityOrder: [],
46641
+ lowRemainingNotificationEnabled: false,
46642
+ lowRemainingNotificationThreshold: 1
46643
+ },
46644
+ officialCodex: {
46645
+ lastProfileSwitchAt: null,
46646
+ lastProfileSwitchProfileKey: null,
46647
+ lastVerifiedLaunchAt: null,
46648
+ lastVerifiedLaunchProfileKey: null,
46649
+ lastObservedPid: null,
46650
+ lastRestartStatus: null,
46651
+ lastRestartReason: null,
46652
+ activity: [],
46653
+ instancesByProfileName: {},
46654
+ pendingRestartDebt: null
46655
+ },
46656
+ app: {
46657
+ lastAppVersion: null,
46658
+ pendingUpdateVersion: null,
46659
+ lastProfileName: null
46660
+ },
46661
+ license: {
46662
+ licenseKey: null,
46663
+ purchaseEmail: null,
46664
+ lastVerifiedAt: null,
46665
+ nextCheckAt: null,
46666
+ lastVerificationError: null,
46667
+ status: "inactive",
46668
+ signature: null
46669
+ },
46670
+ preferences: {
46671
+ excludeFolders: [],
46672
+ enableTaskCompleteBeep: true,
46673
+ preventSleepDuringTasks: true,
46674
+ chatHistoryScrollbackItems: 200,
46675
+ systemNotificationsEnabled: true,
46676
+ subagentSystemNotificationsEnabled: true,
46677
+ folderHistory: [],
46678
+ pinnedPaths: []
46679
+ },
46680
+ runtimeSettings: {},
46681
+ ui: {
46682
+ themeMode: null,
46683
+ layout: { sidebarCollapsed: null },
46684
+ profiles: {
46685
+ viewMode: null,
46686
+ sortBy: null,
46687
+ groupBy: null,
46688
+ planFilter: null,
46689
+ healthFilter: null,
46690
+ customGroupFilter: null,
46691
+ toolbarOpen: null,
46692
+ collapsedSections: {}
46693
+ },
46694
+ onboarding: {
46695
+ welcomeCompleted: false,
46696
+ welcomeCompletedAt: null,
46697
+ welcomeResumeStep: null,
46698
+ milestones: {
46699
+ firstProfileAdded: false,
46700
+ secondProfileAdded: false
46701
+ },
46702
+ sessionCount: 0,
46703
+ nudgeCooldowns: {},
46704
+ nudgeDismissCount: {},
46705
+ proUnlockedCelebrated: false
46706
+ },
46707
+ projectThreadSelections: {},
46708
+ duplicateWarningDismissedKey: null,
46709
+ pendingLicenseActivation: false
46710
+ },
46711
+ profileDashboard: { customGroupsByAccountKey: {} },
46712
+ workspaceSettingsByPath: {},
46713
+ conversationCategoriesByCwd: {},
46714
+ conversationCategoryAssignmentsByCwd: {},
46715
+ git: { commitMessagePrompt: DEFAULT_COMMIT_MESSAGE_PROMPT },
46716
+ skills: {
46717
+ sources: [],
46718
+ installsBySlug: {}
46719
+ },
46720
+ sync: {
46721
+ lastPushAt: null,
46722
+ lastPullAt: null,
46723
+ lastError: null,
46724
+ remoteUpdatedAt: null
46725
+ },
46726
+ analytics: {
46727
+ anonymousId: null,
46728
+ enabled: true,
46729
+ lastFlushAt: null,
46730
+ lastError: null
46731
+ },
46732
+ profilesByName: {},
46733
+ migration: {
46734
+ status: "pending",
46735
+ startedAt: null,
46736
+ completedAt: null,
46737
+ localStorageImportedAt: null,
46738
+ lastError: null
46739
+ }
46740
+ };
46741
+ }
46742
+ function asString$11(value) {
46743
+ if (typeof value !== "string") return null;
46744
+ const trimmed = value.trim();
46745
+ return trimmed.length > 0 ? trimmed : null;
46746
+ }
46747
+ function asNumberOrNull(value) {
46748
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
46749
+ }
46750
+ function asBooleanOrNull(value) {
46751
+ return typeof value === "boolean" ? value : null;
46752
+ }
46753
+ function normalizeAppState(raw) {
46754
+ const defaults = createDefaultAppState();
46755
+ if (!isRecord$8(raw)) return defaults;
46756
+ const rawAutoRoll = isRecord$8(raw.autoRoll) ? raw.autoRoll : void 0;
46757
+ const merged = clone(deepMerge(defaults, raw));
46758
+ merged.schemaVersion = 1;
46759
+ merged.autoRoll = normalizeAutoRollSettings(rawAutoRoll);
46760
+ if (!isRecord$8(merged.officialCodex)) merged.officialCodex = clone(defaults.officialCodex);
46761
+ merged.officialCodex.lastProfileSwitchAt = asNumberOrNull(merged.officialCodex.lastProfileSwitchAt);
46762
+ merged.officialCodex.lastProfileSwitchProfileKey = asString$11(merged.officialCodex.lastProfileSwitchProfileKey);
46763
+ merged.officialCodex.lastVerifiedLaunchAt = asNumberOrNull(merged.officialCodex.lastVerifiedLaunchAt);
46764
+ merged.officialCodex.lastVerifiedLaunchProfileKey = asString$11(merged.officialCodex.lastVerifiedLaunchProfileKey);
46765
+ merged.officialCodex.lastObservedPid = asNumberOrNull(merged.officialCodex.lastObservedPid);
46766
+ merged.officialCodex.lastRestartStatus = asString$11(merged.officialCodex.lastRestartStatus);
46767
+ merged.officialCodex.lastRestartReason = asString$11(merged.officialCodex.lastRestartReason);
46768
+ merged.officialCodex.activity = Array.isArray(merged.officialCodex.activity) ? merged.officialCodex.activity.filter((entry) => isRecord$8(entry)).map((entry) => ({
46769
+ id: asString$11(entry.id) ?? "",
46770
+ at: asString$11(entry.at) ?? (/* @__PURE__ */ new Date(0)).toISOString(),
46771
+ kind: entry.kind === "auto-roll-eval" || entry.kind === "profile-switch" || entry.kind === "auth-verified" || entry.kind === "official-codex-restart" || entry.kind === "reset-window-activation" || entry.kind === "low-remaining-alert" ? entry.kind : "auto-roll-eval",
46772
+ status: asString$11(entry.status) ?? "unknown",
46773
+ reason: asString$11(entry.reason),
46774
+ decisionId: asString$11(entry.decisionId),
46775
+ profileName: asString$11(entry.profileName),
46776
+ sourceProfileName: asString$11(entry.sourceProfileName),
46777
+ targetProfileName: asString$11(entry.targetProfileName),
46778
+ remainingPercent: asNumberOrNull(entry.remainingPercent),
46779
+ threshold: asNumberOrNull(entry.threshold),
46780
+ snapshotAgeMs: asNumberOrNull(entry.snapshotAgeMs),
46781
+ snapshotSource: asString$11(entry.snapshotSource),
46782
+ phase: asString$11(entry.phase),
46783
+ pid: asNumberOrNull(entry.pid),
46784
+ profileKeyHash: asString$11(entry.profileKeyHash),
46785
+ switchVerified: asBooleanOrNull(entry.switchVerified),
46786
+ restartRequested: asBooleanOrNull(entry.restartRequested),
46787
+ restartResult: asString$11(entry.restartResult),
46788
+ observedProfileName: asString$11(entry.observedProfileName),
46789
+ observedProfileKeyHash: asString$11(entry.observedProfileKeyHash),
46790
+ observedProfileMatchSource: asString$11(entry.observedProfileMatchSource)
46791
+ })).filter((entry) => entry.id && entry.at).slice(-50) : [];
46792
+ if (!isRecord$8(merged.officialCodex.instancesByProfileName)) merged.officialCodex.instancesByProfileName = {};
46793
+ else {
46794
+ const nextInstances = {};
46795
+ for (const [key, value] of Object.entries(merged.officialCodex.instancesByProfileName)) {
46796
+ if (!isRecord$8(value)) continue;
46797
+ const profileName = asString$11(value.profileName) ?? asString$11(key);
46798
+ if (!profileName) continue;
46799
+ nextInstances[profileName] = {
46800
+ profileName,
46801
+ profileKey: asString$11(value.profileKey),
46802
+ profileHome: asString$11(value.profileHome),
46803
+ appPath: asString$11(value.appPath),
46804
+ bundleId: asString$11(value.bundleId),
46805
+ pid: asNumberOrNull(value.pid),
46806
+ appServerPid: asNumberOrNull(value.appServerPid),
46807
+ launchedAt: asNumberOrNull(value.launchedAt),
46808
+ lastVerifiedAt: asNumberOrNull(value.lastVerifiedAt),
46809
+ lastStatus: asString$11(value.lastStatus),
46810
+ lastError: asString$11(value.lastError)
46811
+ };
46812
+ }
46813
+ merged.officialCodex.instancesByProfileName = nextInstances;
46814
+ }
46815
+ if (isRecord$8(merged.officialCodex.pendingRestartDebt)) {
46816
+ const debt = merged.officialCodex.pendingRestartDebt;
46817
+ const targetProfileName = asString$11(debt.targetProfileName);
46818
+ merged.officialCodex.pendingRestartDebt = targetProfileName ? {
46819
+ targetProfileName,
46820
+ targetProfileKey: asString$11(debt.targetProfileKey),
46821
+ sourceProfileName: asString$11(debt.sourceProfileName),
46822
+ sourceProfileKey: asString$11(debt.sourceProfileKey),
46823
+ decisionId: asString$11(debt.decisionId),
46824
+ attempts: asNumberOrNull(debt.attempts) ?? 0,
46825
+ lastReason: asString$11(debt.lastReason)
46826
+ } : null;
46827
+ } else merged.officialCodex.pendingRestartDebt = null;
46828
+ merged.app.lastAppVersion = asString$11(merged.app.lastAppVersion);
46829
+ merged.app.pendingUpdateVersion = asString$11(merged.app.pendingUpdateVersion);
46830
+ merged.app.lastProfileName = asString$11(merged.app.lastProfileName);
46831
+ {
46832
+ const allowedAppKeys = new Set(Object.keys(defaults.app));
46833
+ for (const key of Object.keys(merged.app)) if (!allowedAppKeys.has(key)) delete merged.app[key];
46834
+ }
46835
+ merged.license.licenseKey = asString$11(merged.license.licenseKey);
46836
+ merged.license.purchaseEmail = asString$11(merged.license.purchaseEmail);
46837
+ merged.license.lastVerifiedAt = asString$11(merged.license.lastVerifiedAt);
46838
+ merged.license.nextCheckAt = asString$11(merged.license.nextCheckAt);
46839
+ merged.license.lastVerificationError = asString$11(merged.license.lastVerificationError);
46840
+ merged.license.signature = asString$11(merged.license.signature);
46841
+ if (![
46842
+ "inactive",
46843
+ "active",
46844
+ "grace",
46845
+ "error"
46846
+ ].includes(merged.license.status)) merged.license.status = "inactive";
46847
+ if (!Array.isArray(merged.preferences.excludeFolders)) merged.preferences.excludeFolders = [];
46848
+ if (typeof merged.preferences.enableTaskCompleteBeep !== "boolean") merged.preferences.enableTaskCompleteBeep = true;
46849
+ if (typeof merged.preferences.preventSleepDuringTasks !== "boolean") merged.preferences.preventSleepDuringTasks = true;
46850
+ merged.preferences.chatHistoryScrollbackItems = normalizeChatHistoryScrollbackItems(merged.preferences.chatHistoryScrollbackItems);
46851
+ if (typeof merged.preferences.systemNotificationsEnabled !== "boolean") merged.preferences.systemNotificationsEnabled = true;
46852
+ if (typeof merged.preferences.subagentSystemNotificationsEnabled !== "boolean") merged.preferences.subagentSystemNotificationsEnabled = true;
46853
+ if (!Array.isArray(merged.preferences.folderHistory)) merged.preferences.folderHistory = [];
46854
+ if (!Array.isArray(merged.preferences.pinnedPaths)) merged.preferences.pinnedPaths = [];
46855
+ {
46856
+ const allowedPreferenceKeys = new Set(Object.keys(defaults.preferences));
46857
+ for (const key of Object.keys(merged.preferences)) if (!allowedPreferenceKeys.has(key)) delete merged.preferences[key];
46858
+ }
46859
+ if (!isRecord$8(merged.runtimeSettings)) merged.runtimeSettings = {};
46860
+ if (!isRecord$8(merged.ui)) merged.ui = clone(defaults.ui);
46861
+ merged.ui.themeMode = merged.ui.themeMode === "light" || merged.ui.themeMode === "dark" ? merged.ui.themeMode : null;
46862
+ if (!isRecord$8(merged.ui.layout)) merged.ui.layout = clone(defaults.ui.layout);
46863
+ if (typeof merged.ui.layout.sidebarCollapsed !== "boolean") merged.ui.layout.sidebarCollapsed = null;
46864
+ if (!isRecord$8(merged.ui.profiles)) merged.ui.profiles = clone(defaults.ui.profiles);
46865
+ merged.ui.profiles.viewMode = merged.ui.profiles.viewMode === "cards" || merged.ui.profiles.viewMode === "compact" ? merged.ui.profiles.viewMode : null;
46866
+ merged.ui.profiles.sortBy = asString$11(merged.ui.profiles.sortBy);
46867
+ merged.ui.profiles.groupBy = asString$11(merged.ui.profiles.groupBy);
46868
+ merged.ui.profiles.planFilter = asString$11(merged.ui.profiles.planFilter);
46869
+ merged.ui.profiles.healthFilter = asString$11(merged.ui.profiles.healthFilter);
46870
+ merged.ui.profiles.customGroupFilter = asString$11(merged.ui.profiles.customGroupFilter);
46871
+ if (typeof merged.ui.profiles.toolbarOpen !== "boolean") merged.ui.profiles.toolbarOpen = null;
46872
+ if (!isRecord$8(merged.ui.profiles.collapsedSections)) merged.ui.profiles.collapsedSections = {};
46873
+ else merged.ui.profiles.collapsedSections = Object.fromEntries(Object.entries(merged.ui.profiles.collapsedSections).flatMap(([key, value]) => {
46874
+ const normalizedKey = asString$11(key);
46875
+ if (!normalizedKey || typeof value !== "boolean") return [];
46876
+ return [[normalizedKey, value]];
46877
+ }));
46878
+ if (!isRecord$8(merged.ui.onboarding)) merged.ui.onboarding = clone(defaults.ui.onboarding);
46879
+ if (typeof merged.ui.onboarding.welcomeCompleted !== "boolean") merged.ui.onboarding.welcomeCompleted = false;
46880
+ if (!Number.isFinite(merged.ui.onboarding.welcomeCompletedAt)) merged.ui.onboarding.welcomeCompletedAt = null;
46881
+ merged.ui.onboarding.welcomeResumeStep = merged.ui.onboarding.welcomeResumeStep === 2 ? 2 : null;
46882
+ if (!isRecord$8(merged.ui.onboarding.milestones)) merged.ui.onboarding.milestones = clone(defaults.ui.onboarding.milestones);
46883
+ if (typeof merged.ui.onboarding.milestones.firstProfileAdded !== "boolean") merged.ui.onboarding.milestones.firstProfileAdded = false;
46884
+ if (typeof merged.ui.onboarding.milestones.secondProfileAdded !== "boolean") merged.ui.onboarding.milestones.secondProfileAdded = false;
46885
+ if (!Number.isFinite(merged.ui.onboarding.sessionCount)) merged.ui.onboarding.sessionCount = 0;
46886
+ if (!isRecord$8(merged.ui.onboarding.nudgeCooldowns)) merged.ui.onboarding.nudgeCooldowns = {};
46887
+ else merged.ui.onboarding.nudgeCooldowns = Object.fromEntries(Object.entries(merged.ui.onboarding.nudgeCooldowns).flatMap(([key, value]) => {
46888
+ const normalizedKey = asString$11(key);
46889
+ if (!normalizedKey || !Number.isFinite(value)) return [];
46890
+ return [[normalizedKey, Number(value)]];
46891
+ }));
46892
+ if (!isRecord$8(merged.ui.onboarding.nudgeDismissCount)) merged.ui.onboarding.nudgeDismissCount = {};
46893
+ else merged.ui.onboarding.nudgeDismissCount = Object.fromEntries(Object.entries(merged.ui.onboarding.nudgeDismissCount).flatMap(([key, value]) => {
46894
+ const normalizedKey = asString$11(key);
46895
+ if (!normalizedKey || !Number.isFinite(value)) return [];
46896
+ return [[normalizedKey, Number(value)]];
46897
+ }));
46898
+ if (typeof merged.ui.onboarding.proUnlockedCelebrated !== "boolean") merged.ui.onboarding.proUnlockedCelebrated = false;
46899
+ if (!isRecord$8(merged.ui.projectThreadSelections)) merged.ui.projectThreadSelections = {};
46900
+ else merged.ui.projectThreadSelections = Object.fromEntries(Object.entries(merged.ui.projectThreadSelections).flatMap(([projectId, threadId]) => {
46901
+ const normalizedProjectId = asString$11(projectId);
46902
+ if (!normalizedProjectId) return [];
46903
+ return [[normalizedProjectId, typeof threadId === "string" && threadId.trim().length > 0 ? threadId.trim() : null]];
46904
+ }));
46905
+ merged.ui.duplicateWarningDismissedKey = asString$11(merged.ui.duplicateWarningDismissedKey);
46906
+ if (typeof merged.ui.pendingLicenseActivation !== "boolean") merged.ui.pendingLicenseActivation = false;
46907
+ {
46908
+ const allowedUiKeys = new Set(Object.keys(defaults.ui));
46909
+ for (const key of Object.keys(merged.ui)) if (!allowedUiKeys.has(key)) delete merged.ui[key];
46910
+ }
46911
+ if (!isRecord$8(merged.profileDashboard)) merged.profileDashboard = clone(defaults.profileDashboard);
46912
+ if (!isRecord$8(merged.profileDashboard.customGroupsByAccountKey)) merged.profileDashboard.customGroupsByAccountKey = {};
46913
+ else merged.profileDashboard.customGroupsByAccountKey = Object.fromEntries(Object.entries(merged.profileDashboard.customGroupsByAccountKey).flatMap(([key, value]) => {
46914
+ const normalizedKey = asString$11(key);
46915
+ const normalizedValue = asString$11(value);
46916
+ if (!normalizedKey || !normalizedValue) return [];
46917
+ return [[normalizedKey, normalizedValue]];
46918
+ }));
46919
+ {
46920
+ const allowedProfileDashboardKeys = new Set(Object.keys(defaults.profileDashboard));
46921
+ for (const key of Object.keys(merged.profileDashboard)) if (!allowedProfileDashboardKeys.has(key)) delete merged.profileDashboard[key];
46922
+ }
46923
+ const legacyProjectSettingsByPath = isRecord$8(raw.projectSettingsByPath) ? raw.projectSettingsByPath : null;
46924
+ if (!isRecord$8(merged.workspaceSettingsByPath)) merged.workspaceSettingsByPath = {};
46925
+ if (legacyProjectSettingsByPath) merged.workspaceSettingsByPath = {
46926
+ ...legacyProjectSettingsByPath,
46927
+ ...merged.workspaceSettingsByPath
46928
+ };
46929
+ delete merged.projectSettingsByPath;
46930
+ if (!isRecord$8(merged.conversationCategoriesByCwd)) merged.conversationCategoriesByCwd = {};
46931
+ if (!isRecord$8(merged.conversationCategoryAssignmentsByCwd)) merged.conversationCategoryAssignmentsByCwd = {};
46932
+ if (!isRecord$8(merged.git)) merged.git = clone(defaults.git);
46933
+ merged.git.commitMessagePrompt = normalizeCommitMessagePrompt(merged.git.commitMessagePrompt) ?? DEFAULT_COMMIT_MESSAGE_PROMPT;
46934
+ {
46935
+ const allowedGitKeys = new Set(Object.keys(defaults.git));
46936
+ for (const key of Object.keys(merged.git)) if (!allowedGitKeys.has(key)) delete merged.git[key];
46937
+ }
46938
+ if (!isRecord$8(merged.skills)) merged.skills = clone(defaults.skills);
46939
+ if (!Array.isArray(merged.skills.sources)) merged.skills.sources = [];
46940
+ if (!isRecord$8(merged.skills.installsBySlug)) merged.skills.installsBySlug = {};
46941
+ if (!isRecord$8(merged.sync)) merged.sync = clone(defaults.sync);
46942
+ merged.sync.lastPushAt = asString$11(merged.sync.lastPushAt);
46943
+ merged.sync.lastPullAt = asString$11(merged.sync.lastPullAt);
46944
+ merged.sync.lastError = asString$11(merged.sync.lastError);
46945
+ merged.sync.remoteUpdatedAt = asString$11(merged.sync.remoteUpdatedAt);
46946
+ if (!isRecord$8(merged.analytics)) merged.analytics = isRecord$8(merged.telemetry) ? clone(merged.telemetry) : clone(defaults.analytics);
46947
+ merged.analytics.anonymousId = asString$11(merged.analytics.anonymousId);
46948
+ if (!merged.analytics.anonymousId) {
46949
+ const legacyInstallId = asString$11(merged.telemetry?.installId);
46950
+ merged.analytics.anonymousId = legacyInstallId;
46951
+ }
46952
+ if (typeof merged.analytics.enabled !== "boolean") merged.analytics.enabled = true;
46953
+ merged.analytics.lastFlushAt = asString$11(merged.analytics.lastFlushAt);
46954
+ merged.analytics.lastError = asString$11(merged.analytics.lastError);
46955
+ if ("telemetry" in merged) delete merged.telemetry;
46956
+ if (!isRecord$8(merged.profilesByName)) merged.profilesByName = {};
46957
+ if (!isRecord$8(merged.migration)) merged.migration = clone(defaults.migration);
46958
+ if (![
46959
+ "pending",
46960
+ "pending_local_storage",
46961
+ "complete"
46962
+ ].includes(merged.migration.status)) merged.migration.status = "pending";
46963
+ merged.migration.startedAt = asString$11(merged.migration.startedAt);
46964
+ merged.migration.completedAt = asString$11(merged.migration.completedAt);
46965
+ merged.migration.localStorageImportedAt = asString$11(merged.migration.localStorageImportedAt);
46966
+ merged.migration.lastError = asString$11(merged.migration.lastError);
46967
+ return merged;
46968
+ }
46969
+ function deepMerge(base, patch) {
46970
+ if (!isRecord$8(base) || !isRecord$8(patch)) return clone(patch ?? base);
46971
+ const next = { ...base };
46972
+ for (const [key, patchValue] of Object.entries(patch)) {
46973
+ if (patchValue === void 0) continue;
46974
+ const currentValue = next[key];
46975
+ if (Array.isArray(patchValue)) {
46976
+ next[key] = clone(patchValue);
46977
+ continue;
46978
+ }
46979
+ if (isRecord$8(currentValue) && isRecord$8(patchValue)) {
46980
+ next[key] = deepMerge(currentValue, patchValue);
46981
+ continue;
46982
+ }
46983
+ next[key] = clone(patchValue);
46984
+ }
46985
+ return next;
46986
+ }
46987
+ async function readLegacyAppStateFromDisk() {
46988
+ const filePath = resolveLegacyAppStatePath();
46989
+ try {
46990
+ const raw = await promises.readFile(filePath, "utf8");
46991
+ return normalizeAppState(JSON.parse(raw));
46992
+ } catch (error) {
46993
+ if (error.code === "ENOENT") return null;
46994
+ throw error;
46995
+ }
46996
+ }
46997
+ async function readAppStateFromStorage() {
46998
+ return readDocumentStrict(resolveStorageDbPath(), APP_STATE_DOCUMENT, normalizeAppState);
46999
+ }
47000
+ async function writeAppStateToStorage(state) {
47001
+ return writeDocument(resolveStorageDbPath(), APP_STATE_DOCUMENT, normalizeAppState(state));
47002
+ }
47003
+ function compactRecoveryMessage(error) {
47004
+ return (error instanceof Error ? error.message : typeof error === "string" ? error : String(error)).replace(/\s+/g, " ").trim().slice(0, 240) || "unknown corruption";
47005
+ }
47006
+ async function recoverCorruptAppStateStorage(error) {
47007
+ const dbPath = resolveStorageDbPath();
47008
+ if (error instanceof AppStorageCorruptionError && error.namespace === APP_STATE_DOCUMENT) {
47009
+ appStateCache = null;
47010
+ resetAppStorageInitialization(dbPath);
47011
+ const recovered = normalizeAppState(await readLegacyAppStateFromDisk().catch(() => null) ?? null);
47012
+ recovered.migration.lastError = `Recovered app-state document after corruption (${compactRecoveryMessage(error)}). Shared storage database preserved.`;
47013
+ return writeAppStateToStorage(recovered);
47014
+ }
47015
+ const backupPath = await backupCorruptAppStorageDb(dbPath);
47016
+ appStateCache = null;
47017
+ resetAppStorageInitialization(dbPath);
47018
+ const recovered = normalizeAppState(await readLegacyAppStateFromDisk().catch(() => null) ?? null);
47019
+ recovered.migration.lastError = backupPath ? `Recovered app-state storage after corruption (${compactRecoveryMessage(error)}). Backup: ${nodePath.basename(backupPath)}` : `Recovered app-state storage after corruption (${compactRecoveryMessage(error)}). No existing DB file was present.`;
47020
+ return writeAppStateToStorage(recovered);
47021
+ }
47022
+ async function ensureInitialized() {
47023
+ if (appStateCache) return appStateCache;
47024
+ let loaded = null;
47025
+ try {
47026
+ loaded = await readAppStateFromStorage() ?? await readLegacyAppStateFromDisk();
47027
+ } catch (error) {
47028
+ if (!isAppStorageCorruptionError(error)) throw error;
47029
+ appStateCache = await recoverCorruptAppStateStorage(error);
47030
+ return clone(appStateCache);
47031
+ }
47032
+ appStateCache = await writeAppStateToStorage(loaded ?? normalizeAppState(null));
47033
+ return clone(appStateCache);
47034
+ }
47035
+ async function withWriteLock(task) {
47036
+ if (writeLockContext.getStore()) return task();
47037
+ const previous = writeLock;
47038
+ let release;
47039
+ writeLock = new Promise((resolve) => {
47040
+ release = resolve;
47041
+ });
47042
+ await previous;
47043
+ try {
47044
+ return await writeLockContext.run(true, task);
47045
+ } finally {
47046
+ if (release) release();
47047
+ }
47048
+ }
47049
+ async function initializeAppState(userDataDir) {
47050
+ if (configuredUserDataDir !== userDataDir) {
47051
+ configuredUserDataDir = userDataDir;
47052
+ appStateCache = null;
47053
+ resetAppStorageInitialization(resolveStorageDbPath());
47054
+ }
47055
+ return clone(await ensureInitialized());
47056
+ }
47057
+ async function getAppState() {
47058
+ return clone(await ensureInitialized());
47059
+ }
47060
+ async function updateAppState(transform, options = {}) {
47061
+ const mode = options.mode ?? "patch";
47062
+ const allowBeforeMigrationComplete = options.allowBeforeMigrationComplete === true;
47063
+ return withWriteLock(async () => {
47064
+ const nextState = await updateDocument({
47065
+ dbPath: resolveStorageDbPath(),
47066
+ namespace: APP_STATE_DOCUMENT,
47067
+ normalize: normalizeAppState,
47068
+ fallback: createDefaultAppState,
47069
+ transform: (current) => {
47070
+ if (!allowBeforeMigrationComplete && current.migration.status !== "complete") throw new Error("Storage migration is not complete yet.");
47071
+ const transformed = transform(clone(current));
47072
+ return mode === "replace" ? normalizeAppState(transformed) : normalizeAppState(deepMerge(current, transformed));
47073
+ }
47074
+ });
47075
+ appStateCache = nextState;
47076
+ return clone(nextState);
47077
+ });
47078
+ }
47079
+ async function patchAppState(patch) {
47080
+ return updateAppState(() => patch, {
47081
+ mode: "patch",
47082
+ allowBeforeMigrationComplete: false
47083
+ });
47084
+ }
47085
+ //#endregion
47086
+ //#region ../../packages/contracts/src/settings/legacy-localstorage-keys.ts
47087
+ const LEGACY_LOCALSTORAGE_KEYS = [
47088
+ "settings-storage",
47089
+ "provider",
47090
+ "sandbox-storage",
47091
+ "project-settings-storage",
47092
+ "folder-storage",
47093
+ "conversation-categories-storage",
47094
+ "codex:auto-roll-settings"
47095
+ ];
47096
+ //#endregion
47097
+ //#region ../../packages/shared/src/core/logger.ts
47098
+ const isTestEnv = process.env.NODE_ENV === "test" || process.env.VITEST === "true" || process.env.VITEST === "1";
47099
+ function isMocked(fn) {
47100
+ return Boolean(fn && typeof fn === "function" && "mock" in fn);
47101
+ }
47102
+ function logWarn(...args) {
47103
+ if (isTestEnv && !isMocked(console.warn)) return;
47104
+ console.warn(...args);
47105
+ }
47106
+ function logError(...args) {
47107
+ if (isTestEnv && !isMocked(console.error)) return;
47108
+ console.error(...args);
47109
+ }
47110
+ function logInfo(...args) {
47111
+ if (isTestEnv && !isMocked(console.info)) return;
47112
+ console.info(...args);
47113
+ }
47114
+ //#endregion
47115
+ //#region ../../packages/runtime-app-state/src/storage/migrations/v1.ts
47116
+ const SQLITE_STORAGE_DIR = ".f86eb5e712267207";
47117
+ const LEGACY_SETTINGS_FILE = "settings.json";
47118
+ const LEGACY_SETTINGS_BACKUP_FILE = "settings.json.bak";
47119
+ const LEGACY_SYNC_STATE_FILE = "sync-state.json";
47120
+ const LEGACY_APP_SETTINGS_PARITY_FILE = "app-settings-parity.json";
47121
+ const LEGACY_PROFILE_HOMES_DIR = "profile-homes";
47122
+ const LEGACY_SKILLS_DIR = "skills";
47123
+ const LEGACY_SKILL_CACHE_DIR = "skill-cache";
47124
+ const LEGACY_SKILLS_REPOS_FILE = "repos.json";
47125
+ const LEGACY_SKILL_MANIFEST = ".codexuse-skill.json";
47126
+ const LEGACY_LICENSE_SECRET_FILE$1 = "license.secret";
47127
+ function isRecord$7(value) {
47128
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
47129
+ }
47130
+ function asString$10(value) {
47131
+ if (typeof value !== "string") return null;
47132
+ const trimmed = value.trim();
47133
+ return trimmed.length > 0 ? trimmed : null;
47134
+ }
47135
+ function isMissingPathError(error) {
47136
+ return error.code === "ENOENT";
47137
+ }
47138
+ function resolveHomeDir$1() {
47139
+ const home = process.env.HOME || process.env.USERPROFILE || nodeOs.homedir();
47140
+ if (!home) throw new Error("HOME is not set.");
47141
+ return home;
47142
+ }
47143
+ function resolveCodexDir() {
47144
+ return nodePath.join(resolveHomeDir$1(), ".codex");
47145
+ }
47146
+ function resolveLegacyPath(...segments) {
47147
+ return nodePath.join(resolveCodexDir(), ...segments);
47148
+ }
47149
+ async function readJsonFile(filePath) {
47150
+ const raw = await promises.readFile(filePath, "utf8");
47151
+ return JSON.parse(raw);
47152
+ }
47153
+ async function readJsonFileIfExists(filePath) {
47154
+ try {
47155
+ return await readJsonFile(filePath);
47156
+ } catch (error) {
47157
+ if (error.code === "ENOENT") return null;
47158
+ throw error;
47159
+ }
47160
+ }
47161
+ async function copyDirectoryManual(source, destination) {
47162
+ await promises.mkdir(destination, { recursive: true });
47163
+ const entries = await promises.readdir(source, { withFileTypes: true });
47164
+ for (const entry of entries) {
47165
+ const srcPath = nodePath.join(source, entry.name);
47166
+ const destPath = nodePath.join(destination, entry.name);
47167
+ if (entry.isSymbolicLink()) {
47168
+ const linkTarget = await promises.readlink(srcPath);
47169
+ await promises.symlink(linkTarget, destPath).catch((error) => {
47170
+ if (error.code !== "EEXIST") throw error;
47171
+ });
47172
+ continue;
47173
+ }
47174
+ if (entry.isDirectory()) {
47175
+ await copyDirectoryManual(srcPath, destPath);
47176
+ continue;
47177
+ }
47178
+ if (entry.isFile()) await promises.copyFile(srcPath, destPath);
47179
+ }
47180
+ }
47181
+ async function copyDirIfExists(source, destination) {
47182
+ let stats = null;
47183
+ try {
47184
+ stats = await promises.stat(source);
47185
+ } catch (error) {
47186
+ if (error.code === "ENOENT") return;
47187
+ throw error;
47188
+ }
47189
+ if (!stats.isDirectory()) return;
47190
+ await promises.rm(destination, {
47191
+ recursive: true,
47192
+ force: true
47193
+ });
47194
+ await promises.mkdir(nodePath.dirname(destination), { recursive: true });
47195
+ try {
47196
+ await promises.cp(source, destination, {
47197
+ recursive: true,
47198
+ errorOnExist: false,
47199
+ force: true,
47200
+ dereference: false,
47201
+ verbatimSymlinks: true
47202
+ });
47203
+ } catch (error) {
47204
+ if (error.code === "ERR_FS_CP_EINVAL") {
47205
+ await copyDirectoryManual(source, destination);
47206
+ return;
47207
+ }
47208
+ throw error;
47209
+ }
47210
+ }
47211
+ async function copyFileIfExists(source, destination, options) {
47212
+ try {
47213
+ if (!(await promises.stat(source)).isFile()) return;
47214
+ } catch (error) {
47215
+ if (error.code === "ENOENT") return;
47216
+ throw error;
47217
+ }
47218
+ try {
47219
+ if ((await promises.stat(destination)).isFile()) return;
47220
+ } catch (error) {
47221
+ if (error.code !== "ENOENT") throw error;
47222
+ }
47223
+ await promises.mkdir(nodePath.dirname(destination), { recursive: true });
47224
+ await promises.copyFile(source, destination);
47225
+ if (typeof options?.mode === "number") await promises.chmod(destination, options.mode).catch(() => void 0);
47226
+ }
47227
+ async function cleanupCopiedSkillsMetadata(skillsDir) {
47228
+ await removeIfExists(nodePath.join(skillsDir, LEGACY_SKILLS_REPOS_FILE));
47229
+ let entries = [];
47230
+ try {
47231
+ entries = await promises.readdir(skillsDir, { withFileTypes: true });
47232
+ } catch {
47233
+ return;
47234
+ }
47235
+ for (const entry of entries) {
47236
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
47237
+ await removeIfExists(nodePath.join(skillsDir, entry.name, LEGACY_SKILL_MANIFEST));
47238
+ }
47239
+ }
47240
+ async function migrateLegacyDirectoriesToUserData() {
47241
+ const userDataDir = getUserDataDir();
47242
+ const legacyCodexDir = resolveCodexDir();
47243
+ await copyDirIfExists(nodePath.join(legacyCodexDir, LEGACY_PROFILE_HOMES_DIR), nodePath.join(userDataDir, LEGACY_PROFILE_HOMES_DIR));
47244
+ await copyDirIfExists(nodePath.join(legacyCodexDir, LEGACY_SKILLS_DIR), nodePath.join(userDataDir, LEGACY_SKILLS_DIR));
47245
+ await copyDirIfExists(nodePath.join(legacyCodexDir, LEGACY_SKILL_CACHE_DIR), nodePath.join(userDataDir, LEGACY_SKILL_CACHE_DIR));
47246
+ await copyFileIfExists(nodePath.join(legacyCodexDir, LEGACY_LICENSE_SECRET_FILE$1), nodePath.join(userDataDir, LEGACY_LICENSE_SECRET_FILE$1), { mode: 384 });
47247
+ await cleanupCopiedSkillsMetadata(nodePath.join(userDataDir, LEGACY_SKILLS_DIR));
47248
+ }
47249
+ function pickAutoRoll(raw) {
47250
+ if (!raw) return null;
47251
+ try {
47252
+ return normalizeAutoRollSettings(raw);
47253
+ } catch {
47254
+ return null;
47255
+ }
47256
+ }
47257
+ function parseLegacyLicense(raw) {
47258
+ if (!isRecord$7(raw)) return {
47259
+ licenseKey: null,
47260
+ purchaseEmail: null,
47261
+ lastVerifiedAt: null,
47262
+ nextCheckAt: null,
47263
+ lastVerificationError: null,
47264
+ status: "inactive",
47265
+ signature: null
47266
+ };
47267
+ const statusCandidate = asString$10(raw.status);
47268
+ const status = [
47269
+ "inactive",
47270
+ "active",
47271
+ "grace",
47272
+ "error"
47273
+ ].includes(statusCandidate ?? "") ? statusCandidate : "inactive";
47274
+ return {
47275
+ licenseKey: asString$10(raw.licenseKey ?? raw.license_key),
47276
+ purchaseEmail: asString$10(raw.purchaseEmail ?? raw.purchase_email),
47277
+ lastVerifiedAt: asString$10(raw.lastVerifiedAt ?? raw.last_verified_at),
47278
+ nextCheckAt: asString$10(raw.nextCheckAt ?? raw.next_check_at),
47279
+ lastVerificationError: asString$10(raw.lastVerificationError ?? raw.last_verification_error),
47280
+ status,
47281
+ signature: asString$10(raw.signature)
47282
+ };
47283
+ }
47284
+ function parseLegacyProfileRecord(name, raw) {
47285
+ if (!isRecord$7(raw)) return null;
47286
+ const dataRaw = raw.data;
47287
+ let data = null;
47288
+ if (isRecord$7(dataRaw)) data = dataRaw;
47289
+ else if (typeof dataRaw === "string") try {
47290
+ data = JSON.parse(dataRaw);
47291
+ } catch {
47292
+ data = null;
47293
+ }
47294
+ if (!data) return null;
47295
+ return {
47296
+ name,
47297
+ displayName: asString$10(raw.displayName ?? raw.display_name) ?? name,
47298
+ data,
47299
+ metadata: isRecord$7(raw.metadata) ? raw.metadata : void 0,
47300
+ accountId: asString$10(raw.accountId ?? raw.account_id),
47301
+ workspaceId: asString$10(raw.workspaceId ?? raw.workspace_id),
47302
+ workspaceName: asString$10(raw.workspaceName ?? raw.workspace_name),
47303
+ email: asString$10(raw.email),
47304
+ authMethod: asString$10(raw.authMethod ?? raw.auth_method),
47305
+ createdAt: asString$10(raw.createdAt ?? raw.created_at),
47306
+ updatedAt: asString$10(raw.updatedAt ?? raw.updated_at)
47307
+ };
47308
+ }
47309
+ async function loadLegacySettingsPatch() {
47310
+ const raw = await readJsonFileIfExists(resolveLegacyPath(LEGACY_SETTINGS_FILE));
47311
+ if (!isRecord$7(raw)) return {};
47312
+ const autoRoll = pickAutoRoll(raw.autoRoll ?? raw.auto_roll);
47313
+ const license = parseLegacyLicense(raw.license ?? raw.license_data ?? raw.license_state);
47314
+ return {
47315
+ app: {
47316
+ lastAppVersion: asString$10(raw.lastAppVersion ?? raw.last_app_version),
47317
+ pendingUpdateVersion: asString$10(raw.pendingUpdateVersion ?? raw.pending_update_version),
47318
+ lastProfileName: asString$10(raw.lastProfileName ?? raw.last_profile_name)
47319
+ },
47320
+ license,
47321
+ autoRoll: autoRoll ? {
47322
+ enabled: autoRoll.enabled,
47323
+ rearmRemainingThreshold: autoRoll.rearmRemainingThreshold,
47324
+ switchRemainingThreshold: autoRoll.switchRemainingThreshold,
47325
+ restartOfficialCodexOnAutoRoll: autoRoll.restartOfficialCodexOnAutoRoll,
47326
+ launchOfficialCodexWhenClosedOnAutoRoll: autoRoll.launchOfficialCodexWhenClosedOnAutoRoll,
47327
+ priorityOrder: autoRoll.priorityOrder,
47328
+ lowRemainingNotificationEnabled: autoRoll.lowRemainingNotificationEnabled,
47329
+ lowRemainingNotificationThreshold: autoRoll.lowRemainingNotificationThreshold
47330
+ } : void 0
47331
+ };
47332
+ }
47333
+ async function loadLegacySyncPatch() {
47334
+ const raw = await readJsonFileIfExists(resolveLegacyPath(LEGACY_SYNC_STATE_FILE));
47335
+ if (!isRecord$7(raw)) return {};
47336
+ return { sync: {
47337
+ lastPushAt: asString$10(raw.lastPushAt),
47338
+ lastPullAt: asString$10(raw.lastPullAt),
47339
+ lastError: asString$10(raw.lastError),
47340
+ remoteUpdatedAt: asString$10(raw.remoteUpdatedAt)
47341
+ } };
47342
+ }
47343
+ async function loadLegacyAppSettingsParityPatch() {
47344
+ const raw = await readJsonFileIfExists(nodePath.join(getUserDataDir(), LEGACY_APP_SETTINGS_PARITY_FILE));
47345
+ if (!isRecord$7(raw)) return {};
47346
+ return { runtimeSettings: raw };
47347
+ }
47348
+ async function loadLegacyProfilesPatch() {
47349
+ const root = resolveLegacyPath(LEGACY_PROFILE_HOMES_DIR);
47350
+ let entries = [];
47351
+ try {
47352
+ entries = await promises.readdir(root, { withFileTypes: true });
47353
+ } catch (error) {
47354
+ if (error.code === "ENOENT") return {};
47355
+ throw error;
47356
+ }
47357
+ const profilesByName = {};
47358
+ for (const entry of entries) {
47359
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
47360
+ const raw = await readJsonFileIfExists(nodePath.join(root, entry.name, "profile.json"));
47361
+ if (!raw) continue;
47362
+ const parsed = parseLegacyProfileRecord(entry.name, raw);
47363
+ if (!parsed) continue;
47364
+ profilesByName[entry.name] = parsed;
47365
+ }
47366
+ if (Object.keys(profilesByName).length === 0) return {};
47367
+ return { profilesByName };
47368
+ }
47369
+ function parseSkillInstallMetadata(raw) {
47370
+ if (!isRecord$7(raw)) return null;
47371
+ const id = asString$10(raw.id);
47372
+ if (!id) return null;
47373
+ return {
47374
+ id,
47375
+ repo: asString$10(raw.repo),
47376
+ repoPath: asString$10(raw.repoPath),
47377
+ sourceLabel: asString$10(raw.sourceLabel),
47378
+ sourceType: raw.sourceType === "official" || raw.sourceType === "community" || raw.sourceType === "local" ? raw.sourceType : void 0,
47379
+ viewUrl: asString$10(raw.viewUrl),
47380
+ createdAt: asString$10(raw.createdAt)
47381
+ };
47382
+ }
47383
+ async function loadLegacySkillsPatch() {
47384
+ const skillsRoot = resolveLegacyPath(LEGACY_SKILLS_DIR);
47385
+ const reposRaw = await readJsonFileIfExists(nodePath.join(skillsRoot, LEGACY_SKILLS_REPOS_FILE));
47386
+ const installsBySlug = {};
47387
+ let dirEntries = [];
47388
+ try {
47389
+ dirEntries = await promises.readdir(skillsRoot, { withFileTypes: true });
47390
+ } catch (error) {
47391
+ if (error.code !== "ENOENT") throw error;
47392
+ }
47393
+ for (const entry of dirEntries) {
47394
+ if (!entry.isDirectory()) continue;
47395
+ if (entry.name.startsWith(".")) continue;
47396
+ const parsed = parseSkillInstallMetadata(await readJsonFileIfExists(nodePath.join(skillsRoot, entry.name, LEGACY_SKILL_MANIFEST)));
47397
+ if (!parsed) continue;
47398
+ installsBySlug[entry.name] = parsed;
47399
+ }
47400
+ const sources = isRecord$7(reposRaw) && Array.isArray(reposRaw.sources) ? reposRaw.sources : [];
47401
+ if (sources.length === 0 && Object.keys(installsBySlug).length === 0) return {};
47402
+ return { skills: {
47403
+ sources,
47404
+ installsBySlug
47405
+ } };
47406
+ }
47407
+ function mergeLegacyLocalStoragePatch(payload) {
47408
+ const patch = {};
47409
+ const consumedKeys = /* @__PURE__ */ new Set();
47410
+ const skippedKeys = /* @__PURE__ */ new Set();
47411
+ const legacyPayloadKeys = new Set(Object.keys(payload).filter((key) => LEGACY_LOCALSTORAGE_KEYS.includes(key)));
47412
+ const hasKey = (key) => legacyPayloadKeys.has(key);
47413
+ const markSkippedIfPresent = (key, consumed) => {
47414
+ if (!hasKey(key)) return;
47415
+ if (consumed) consumedKeys.add(key);
47416
+ else skippedKeys.add(key);
47417
+ };
47418
+ const settingsStorage = payload["settings-storage"];
47419
+ if (isRecord$7(settingsStorage)) {
47420
+ const nextExcludeFolders = Array.isArray(settingsStorage.excludeFolders) ? settingsStorage.excludeFolders.filter((item) => typeof item === "string") : void 0;
47421
+ const nextBeep = typeof settingsStorage.enableTaskCompleteBeep === "boolean" ? settingsStorage.enableTaskCompleteBeep : void 0;
47422
+ const nextSleep = typeof settingsStorage.preventSleepDuringTasks === "boolean" ? settingsStorage.preventSleepDuringTasks : void 0;
47423
+ patch.preferences = {
47424
+ excludeFolders: nextExcludeFolders,
47425
+ enableTaskCompleteBeep: nextBeep,
47426
+ preventSleepDuringTasks: nextSleep
47427
+ };
47428
+ markSkippedIfPresent("settings-storage", nextExcludeFolders !== void 0 || nextBeep !== void 0 || nextSleep !== void 0);
47429
+ } else markSkippedIfPresent("settings-storage", false);
47430
+ markSkippedIfPresent("provider", hasKey("provider"));
47431
+ markSkippedIfPresent("sandbox-storage", hasKey("sandbox-storage"));
47432
+ const projectSettings = payload["project-settings-storage"];
47433
+ if (isRecord$7(projectSettings) && isRecord$7(projectSettings.settingsByPath)) {
47434
+ patch.workspaceSettingsByPath = projectSettings.settingsByPath;
47435
+ markSkippedIfPresent("project-settings-storage", true);
47436
+ } else markSkippedIfPresent("project-settings-storage", false);
47437
+ const folder = payload["folder-storage"];
47438
+ if (isRecord$7(folder)) {
47439
+ const folderHistory = Array.isArray(folder.folderHistory) ? folder.folderHistory.filter(isRecord$7) : void 0;
47440
+ const pinnedPaths = Array.isArray(folder.pinnedPaths) ? folder.pinnedPaths.filter((item) => typeof item === "string") : void 0;
47441
+ patch.preferences = {
47442
+ ...patch.preferences ?? {},
47443
+ folderHistory,
47444
+ pinnedPaths
47445
+ };
47446
+ markSkippedIfPresent("folder-storage", folderHistory !== void 0 || pinnedPaths !== void 0);
47447
+ } else markSkippedIfPresent("folder-storage", false);
47448
+ const categories = payload["conversation-categories-storage"];
47449
+ let consumedCategories = false;
47450
+ if (isRecord$7(categories)) {
47451
+ if (isRecord$7(categories.categoriesByCwd)) {
47452
+ patch.conversationCategoriesByCwd = categories.categoriesByCwd;
47453
+ consumedCategories = true;
47454
+ }
47455
+ if (isRecord$7(categories.conversationCategoryByCwd)) {
47456
+ patch.conversationCategoryAssignmentsByCwd = categories.conversationCategoryByCwd;
47457
+ consumedCategories = true;
47458
+ }
47459
+ }
47460
+ markSkippedIfPresent("conversation-categories-storage", consumedCategories);
47461
+ const legacyAutoRoll = payload["codex:auto-roll-settings"];
47462
+ const autoRoll = pickAutoRoll(legacyAutoRoll);
47463
+ if (autoRoll) {
47464
+ patch.autoRoll = {
47465
+ enabled: autoRoll.enabled,
47466
+ rearmRemainingThreshold: autoRoll.rearmRemainingThreshold,
47467
+ switchRemainingThreshold: autoRoll.switchRemainingThreshold,
47468
+ restartOfficialCodexOnAutoRoll: autoRoll.restartOfficialCodexOnAutoRoll,
47469
+ launchOfficialCodexWhenClosedOnAutoRoll: autoRoll.launchOfficialCodexWhenClosedOnAutoRoll,
47470
+ priorityOrder: autoRoll.priorityOrder,
47471
+ lowRemainingNotificationEnabled: autoRoll.lowRemainingNotificationEnabled,
47472
+ lowRemainingNotificationThreshold: autoRoll.lowRemainingNotificationThreshold
47473
+ };
47474
+ markSkippedIfPresent("codex:auto-roll-settings", true);
47475
+ } else markSkippedIfPresent("codex:auto-roll-settings", false);
47476
+ return {
47477
+ patch,
47478
+ consumedKeys: Array.from(consumedKeys),
47479
+ skippedKeys: Array.from(skippedKeys)
47480
+ };
47481
+ }
47482
+ async function removeIfExists(target) {
47483
+ await promises.rm(target, {
47484
+ recursive: true,
47485
+ force: true
47486
+ });
47487
+ }
47488
+ async function cleanupLegacyCanonicalSources() {
47489
+ const homeDir = resolveHomeDir$1();
47490
+ await removeIfExists(resolveLegacyAppStatePath());
47491
+ await removeIfExists(nodePath.join(getUserDataDir(), LEGACY_APP_SETTINGS_PARITY_FILE));
47492
+ await removeIfExists(nodePath.join(homeDir, SQLITE_STORAGE_DIR));
47493
+ await removeIfExists(resolveLegacyPath(LEGACY_SETTINGS_FILE));
47494
+ await removeIfExists(resolveLegacyPath(LEGACY_SETTINGS_BACKUP_FILE));
47495
+ await removeIfExists(resolveLegacyPath(LEGACY_SYNC_STATE_FILE));
47496
+ await removeIfExists(resolveLegacyPath(LEGACY_LICENSE_SECRET_FILE$1));
47497
+ await removeIfExists(resolveLegacyPath(LEGACY_SKILLS_DIR, LEGACY_SKILLS_REPOS_FILE));
47498
+ const profileHomesRoot = resolveLegacyPath(LEGACY_PROFILE_HOMES_DIR);
47499
+ try {
47500
+ const profileHomes = await promises.readdir(profileHomesRoot, { withFileTypes: true });
47501
+ for (const profileHome of profileHomes) {
47502
+ if (!profileHome.isDirectory()) continue;
47503
+ const profileDir = nodePath.join(profileHomesRoot, profileHome.name);
47504
+ let files = [];
47505
+ try {
47506
+ files = await promises.readdir(profileDir);
47507
+ } catch {
47508
+ continue;
47509
+ }
47510
+ for (const file of files) {
47511
+ if (!file.startsWith("profile.json")) continue;
47512
+ await removeIfExists(nodePath.join(profileDir, file));
47513
+ }
47514
+ }
47515
+ } catch (error) {
47516
+ if (!isMissingPathError(error)) logWarn("Failed cleaning legacy profile metadata:", {
47517
+ profileHomesRoot,
47518
+ error: error instanceof Error ? error.message : String(error)
47519
+ });
47520
+ }
47521
+ const skillsRoot = resolveLegacyPath(LEGACY_SKILLS_DIR);
47522
+ try {
47523
+ const skillDirs = await promises.readdir(skillsRoot, { withFileTypes: true });
47524
+ for (const entry of skillDirs) {
47525
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
47526
+ await removeIfExists(nodePath.join(skillsRoot, entry.name, LEGACY_SKILL_MANIFEST));
47527
+ }
47528
+ } catch (error) {
47529
+ if (!isMissingPathError(error)) logWarn("Failed cleaning legacy skills metadata:", {
47530
+ skillsRoot,
47531
+ error: error instanceof Error ? error.message : String(error)
47532
+ });
47533
+ }
47534
+ }
47535
+ async function runStorageMigrationV1() {
47536
+ const current = await getAppState();
47537
+ if (current.migration.status === "complete") return current;
47538
+ if (current.migration.status === "pending_local_storage") {
47539
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
47540
+ return updateAppState((state) => ({
47541
+ ...state,
47542
+ migration: {
47543
+ ...state.migration,
47544
+ status: "complete",
47545
+ completedAt,
47546
+ lastError: null
47547
+ }
47548
+ }), {
47549
+ mode: "replace",
47550
+ allowBeforeMigrationComplete: true
47551
+ });
47552
+ }
47553
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
47554
+ try {
47555
+ await migrateLegacyDirectoriesToUserData();
47556
+ const mergedPatch = (await Promise.all([
47557
+ loadLegacySettingsPatch(),
47558
+ loadLegacySyncPatch(),
47559
+ loadLegacyAppSettingsParityPatch(),
47560
+ loadLegacyProfilesPatch(),
47561
+ loadLegacySkillsPatch()
47562
+ ])).reduce((acc, patch) => {
47563
+ return {
47564
+ ...acc,
47565
+ ...patch,
47566
+ app: {
47567
+ ...acc.app ?? {},
47568
+ ...patch.app ?? {}
47569
+ },
47570
+ license: {
47571
+ ...acc.license ?? {},
47572
+ ...patch.license ?? {}
47573
+ },
47574
+ autoRoll: {
47575
+ ...acc.autoRoll ?? {},
47576
+ ...patch.autoRoll ?? {}
47577
+ },
47578
+ runtimeSettings: {
47579
+ ...acc.runtimeSettings ?? {},
47580
+ ...patch.runtimeSettings ?? {}
47581
+ },
47582
+ preferences: {
47583
+ ...acc.preferences ?? {},
47584
+ ...patch.preferences ?? {}
47585
+ },
47586
+ sync: {
47587
+ ...acc.sync ?? {},
47588
+ ...patch.sync ?? {}
47589
+ },
47590
+ profilesByName: {
47591
+ ...acc.profilesByName ?? {},
47592
+ ...patch.profilesByName ?? {}
47593
+ },
47594
+ workspaceSettingsByPath: {
47595
+ ...acc.workspaceSettingsByPath ?? {},
47596
+ ...patch.workspaceSettingsByPath ?? {}
47597
+ },
47598
+ conversationCategoriesByCwd: {
47599
+ ...acc.conversationCategoriesByCwd ?? {},
47600
+ ...patch.conversationCategoriesByCwd ?? {}
47601
+ },
47602
+ conversationCategoryAssignmentsByCwd: {
47603
+ ...acc.conversationCategoryAssignmentsByCwd ?? {},
47604
+ ...patch.conversationCategoryAssignmentsByCwd ?? {}
47605
+ },
47606
+ skills: {
47607
+ ...acc.skills ?? {},
47608
+ ...patch.skills ?? {},
47609
+ sources: patch.skills?.sources ?? acc.skills?.sources,
47610
+ installsBySlug: {
47611
+ ...acc.skills?.installsBySlug ?? {},
47612
+ ...patch.skills?.installsBySlug ?? {}
47613
+ }
47614
+ }
47615
+ };
47616
+ }, {});
47617
+ return await updateAppState((state) => ({
47618
+ ...state,
47619
+ ...mergedPatch,
47620
+ app: {
47621
+ ...state.app,
47622
+ ...mergedPatch.app ?? {}
47623
+ },
47624
+ license: {
47625
+ ...state.license,
47626
+ ...mergedPatch.license ?? {}
47627
+ },
47628
+ autoRoll: {
47629
+ ...state.autoRoll,
47630
+ ...mergedPatch.autoRoll ?? {}
47631
+ },
47632
+ runtimeSettings: {
47633
+ ...state.runtimeSettings,
47634
+ ...mergedPatch.runtimeSettings ?? {}
47635
+ },
47636
+ preferences: {
47637
+ ...state.preferences,
47638
+ ...mergedPatch.preferences ?? {}
47639
+ },
47640
+ sync: {
47641
+ ...state.sync,
47642
+ ...mergedPatch.sync ?? {}
47643
+ },
47644
+ profilesByName: {
47645
+ ...state.profilesByName,
47646
+ ...mergedPatch.profilesByName ?? {}
47647
+ },
47648
+ workspaceSettingsByPath: {
47649
+ ...state.workspaceSettingsByPath,
47650
+ ...mergedPatch.workspaceSettingsByPath ?? {}
47651
+ },
47652
+ conversationCategoriesByCwd: {
47653
+ ...state.conversationCategoriesByCwd,
47654
+ ...mergedPatch.conversationCategoriesByCwd ?? {}
47655
+ },
47656
+ conversationCategoryAssignmentsByCwd: {
47657
+ ...state.conversationCategoryAssignmentsByCwd,
47658
+ ...mergedPatch.conversationCategoryAssignmentsByCwd ?? {}
47659
+ },
47660
+ skills: {
47661
+ ...state.skills,
47662
+ ...mergedPatch.skills ?? {},
47663
+ installsBySlug: {
47664
+ ...state.skills.installsBySlug,
47665
+ ...mergedPatch.skills?.installsBySlug ?? {}
47666
+ }
47667
+ },
47668
+ migration: {
47669
+ ...state.migration,
47670
+ status: "complete",
47671
+ startedAt: state.migration.startedAt ?? startedAt,
47672
+ completedAt: startedAt,
47673
+ localStorageImportedAt: null,
47674
+ lastError: null
47675
+ }
47676
+ }), {
47677
+ mode: "replace",
47678
+ allowBeforeMigrationComplete: true
47679
+ });
47680
+ } catch (error) {
47681
+ const message = error instanceof Error ? error.message : String(error);
47682
+ await updateAppState((state) => ({
47683
+ ...state,
47684
+ migration: {
47685
+ ...state.migration,
47686
+ status: "pending",
47687
+ startedAt: state.migration.startedAt ?? startedAt,
47688
+ lastError: message
47689
+ }
47690
+ }), {
47691
+ mode: "replace",
47692
+ allowBeforeMigrationComplete: true
47693
+ });
47694
+ throw error;
47695
+ }
47696
+ }
47697
+ async function importLegacyLocalStorageOnce(payload) {
47698
+ if ((await getAppState()).migration.status === "pending") return {
47699
+ completed: false,
47700
+ importedKeys: [],
47701
+ skippedKeys: []
47702
+ };
47703
+ if (!payload || !isRecord$7(payload)) return {
47704
+ completed: true,
47705
+ importedKeys: [],
47706
+ skippedKeys: []
47707
+ };
47708
+ const { patch, consumedKeys, skippedKeys } = mergeLegacyLocalStoragePatch(payload);
47709
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
47710
+ if ((await updateAppState((state) => {
47711
+ return {
47712
+ ...state,
47713
+ ...patch,
47714
+ app: {
47715
+ ...state.app,
47716
+ ...patch.app ?? {}
47717
+ },
47718
+ autoRoll: {
47719
+ ...state.autoRoll,
47720
+ ...patch.autoRoll ?? {}
47721
+ },
47722
+ license: {
47723
+ ...state.license,
47724
+ ...patch.license ?? {}
47725
+ },
47726
+ preferences: {
47727
+ ...state.preferences,
47728
+ ...patch.preferences ?? {}
47729
+ },
47730
+ workspaceSettingsByPath: {
47731
+ ...state.workspaceSettingsByPath,
47732
+ ...patch.workspaceSettingsByPath ?? {}
47733
+ },
47734
+ conversationCategoriesByCwd: {
47735
+ ...state.conversationCategoriesByCwd,
47736
+ ...patch.conversationCategoriesByCwd ?? {}
47737
+ },
47738
+ conversationCategoryAssignmentsByCwd: {
47739
+ ...state.conversationCategoryAssignmentsByCwd,
47740
+ ...patch.conversationCategoryAssignmentsByCwd ?? {}
47741
+ },
47742
+ migration: {
47743
+ ...state.migration,
47744
+ status: "complete",
47745
+ completedAt,
47746
+ localStorageImportedAt: completedAt,
47747
+ lastError: null
47748
+ }
47749
+ };
47750
+ }, {
47751
+ mode: "replace",
47752
+ allowBeforeMigrationComplete: true
47753
+ })).migration.status !== "complete") return {
47754
+ completed: false,
47755
+ importedKeys: [],
47756
+ skippedKeys: []
47757
+ };
47758
+ await cleanupLegacyCanonicalSources();
47759
+ return {
47760
+ completed: true,
47761
+ importedKeys: consumedKeys,
47762
+ skippedKeys
47763
+ };
47764
+ }
47765
+ //#endregion
47766
+ //#region src/config.ts
47767
+ /**
47768
+ * ServerConfig - Runtime configuration services.
47769
+ *
47770
+ * Defines process-level server configuration and networking helpers used by
47771
+ * startup and runtime layers.
47772
+ *
47773
+ * @module ServerConfig
47774
+ */
47775
+ const DEFAULT_PORT = 3773;
47776
+ /**
47777
+ * ServerConfig - Service tag for server runtime configuration.
47778
+ */
47779
+ var ServerConfig$1 = class ServerConfig$1 extends Service()("t3/config/ServerConfig") {
47780
+ static {
47781
+ this.layerTest = (cwd, statedir) => effect(ServerConfig$1, gen(function* () {
47782
+ return {
47783
+ cwd,
47784
+ stateDir: statedir,
47785
+ mode: "web",
47786
+ autoBootstrapProjectFromCwd: false,
47787
+ logWebSocketEvents: false,
47788
+ port: 0,
47789
+ host: void 0,
47790
+ authToken: void 0,
47791
+ keybindingsConfigPath: (yield* Path$1).join(statedir, "keybindings.json"),
47792
+ staticDir: void 0,
47793
+ devUrl: void 0,
47794
+ noBrowser: false
47795
+ };
47796
+ }));
47797
+ }
47798
+ };
47799
+ const resolveStaticDir = fn(function* () {
47800
+ const { join, resolve } = yield* Path$1;
47801
+ const { exists } = yield* FileSystem;
47802
+ const bundledClient = resolve(join(import.meta.dirname, "client"));
47803
+ if (yield* exists(join(bundledClient, "index.html")).pipe(orElseSucceed(() => false))) return bundledClient;
47804
+ const monorepoClient = resolve(join(import.meta.dirname, "../../web/dist"));
47805
+ if (yield* exists(join(monorepoClient, "index.html")).pipe(orElseSucceed(() => false))) return monorepoClient;
47806
+ });
47807
+ //#endregion
47808
+ //#region ../../packages/t3-shared/src/shell.ts
47809
+ const SHELL_ENV_NAME_PATTERN = /^[A-Z0-9_]+$/;
47810
+ function readPathFromLoginShell(shell, execFile = execFileSync) {
47811
+ return readEnvironmentFromLoginShell(shell, ["PATH"], execFile).PATH;
47812
+ }
47813
+ function envCaptureStart(name) {
47814
+ return `__T3CODE_ENV_${name}_START__`;
47815
+ }
47816
+ function envCaptureEnd(name) {
47817
+ return `__T3CODE_ENV_${name}_END__`;
47818
+ }
47819
+ function buildEnvironmentCaptureCommand(names) {
47820
+ return names.map((name) => {
47821
+ if (!SHELL_ENV_NAME_PATTERN.test(name)) throw new Error(`Unsupported environment variable name: ${name}`);
47822
+ return [
47823
+ `printf '%s\\n' '${envCaptureStart(name)}'`,
47824
+ `printenv ${name} || true`,
47825
+ `printf '%s\\n' '${envCaptureEnd(name)}'`
47826
+ ].join("; ");
47827
+ }).join("; ");
47828
+ }
47829
+ function extractEnvironmentValue(output, name) {
47830
+ const startMarker = envCaptureStart(name);
47831
+ const endMarker = envCaptureEnd(name);
47832
+ const startIndex = output.indexOf(startMarker);
47833
+ if (startIndex === -1) return void 0;
47834
+ const valueStartIndex = startIndex + startMarker.length;
47835
+ const endIndex = output.indexOf(endMarker, valueStartIndex);
47836
+ if (endIndex === -1) return void 0;
47837
+ let value = output.slice(valueStartIndex, endIndex);
47838
+ if (value.startsWith("\n")) value = value.slice(1);
47839
+ if (value.endsWith("\n")) value = value.slice(0, -1);
47840
+ return value.length > 0 ? value : void 0;
47841
+ }
47842
+ const readEnvironmentFromLoginShell = (shell, names, execFile = execFileSync) => {
47843
+ if (names.length === 0) return {};
47844
+ const output = execFile(shell, ["-ilc", buildEnvironmentCaptureCommand(names)], {
47845
+ encoding: "utf8",
47846
+ timeout: 5e3
47847
+ });
47848
+ const environment = {};
47849
+ for (const name of names) {
47850
+ const value = extractEnvironmentValue(output, name);
47851
+ if (value !== void 0) environment[name] = value;
47852
+ }
47853
+ return environment;
47854
+ };
47855
+ //#endregion
47856
+ //#region src/os-jank.ts
47857
+ function fixPath() {
47858
+ if (process.platform !== "darwin") return;
47859
+ try {
47860
+ const result = readPathFromLoginShell(process.env.SHELL ?? "/bin/zsh");
47861
+ if (result) process.env.PATH = result;
47862
+ } catch {}
47863
+ }
47864
+ const expandHomePath$1 = fn(function* (input) {
47865
+ const { join } = yield* Path$1;
47866
+ if (input === "~") return OS.homedir();
47867
+ if (input.startsWith("~/") || input.startsWith("~\\")) return join(OS.homedir(), input.slice(2));
47868
+ return input;
47869
+ });
47870
+ const resolveStateDir = fn(function* (raw) {
47871
+ const { join, resolve } = yield* Path$1;
47872
+ if (!raw || raw.trim().length === 0) return join(OS.homedir(), ".t3", "userdata");
47873
+ return resolve(yield* expandHomePath$1(raw.trim()));
47874
+ });
47875
+ //#endregion
47876
+ //#region ../../packages/t3-contracts/src/baseSchemas.ts
47877
+ const TrimmedString = Trim;
47878
+ const TrimmedNonEmptyString = TrimmedString.check(isNonEmpty());
47879
+ const NonNegativeInt = Int.check(isGreaterThanOrEqualTo(0));
47880
+ const PositiveInt = Int.check(isGreaterThanOrEqualTo(1));
47881
+ const IsoDateTime = String$1;
47882
+ /**
47883
+ * Construct a branded identifier. Enforces non-empty trimmed strings
47884
+ */
47885
+ const makeEntityId = (brand$2) => TrimmedNonEmptyString.pipe(brand(brand$2));
47886
+ const ThreadId = makeEntityId("ThreadId");
47887
+ const ProjectId = makeEntityId("ProjectId");
47888
+ const CommandId = makeEntityId("CommandId");
47889
+ const EventId = makeEntityId("EventId");
47890
+ const MessageId = makeEntityId("MessageId");
47891
+ const TurnId = makeEntityId("TurnId");
47892
+ const ProviderItemId = makeEntityId("ProviderItemId");
47893
+ const RuntimeSessionId = makeEntityId("RuntimeSessionId");
47894
+ const RuntimeItemId = makeEntityId("RuntimeItemId");
47895
+ const RuntimeRequestId = makeEntityId("RuntimeRequestId");
47896
+ const RuntimeTaskId = makeEntityId("RuntimeTaskId");
47897
+ const ApprovalRequestId = makeEntityId("ApprovalRequestId");
47898
+ const CheckpointRef = makeEntityId("CheckpointRef");
47899
+ //#endregion
47900
+ //#region ../../packages/t3-contracts/src/terminal.ts
47901
+ const DEFAULT_TERMINAL_ID = "default";
47902
+ const TrimmedNonEmptyStringSchema$3 = TrimmedNonEmptyString;
47903
+ const TerminalColsSchema = Int.check(isGreaterThanOrEqualTo(1)).check(isLessThanOrEqualTo(1e3));
47904
+ const TerminalRowsSchema = Int.check(isGreaterThanOrEqualTo(1)).check(isLessThanOrEqualTo(500));
47905
+ const TerminalIdSchema = TrimmedNonEmptyStringSchema$3.check(isMaxLength(128));
47906
+ const TerminalEnvKeySchema = String$1.check(isPattern(/^[A-Za-z_][A-Za-z0-9_]*$/)).check(isMaxLength(128));
47907
+ const TerminalEnvValueSchema = String$1.check(isMaxLength(8192));
47908
+ const TerminalEnvSchema = Record(TerminalEnvKeySchema, TerminalEnvValueSchema).check(isMaxProperties(128));
47909
+ const TerminalIdWithDefaultSchema = TerminalIdSchema.pipe(withDecodingDefault(() => DEFAULT_TERMINAL_ID));
47910
+ const TerminalThreadInput = Struct({ threadId: TrimmedNonEmptyStringSchema$3 });
47911
+ const TerminalSessionInput = Struct({
47912
+ ...TerminalThreadInput.fields,
47913
+ terminalId: TerminalIdWithDefaultSchema
47914
+ });
47915
+ const TerminalOpenInput = Struct({
47916
+ ...TerminalSessionInput.fields,
47917
+ cwd: TrimmedNonEmptyStringSchema$3,
47918
+ cols: optional$2(TerminalColsSchema),
47919
+ rows: optional$2(TerminalRowsSchema),
47920
+ env: optional$2(TerminalEnvSchema)
47921
+ });
47922
+ const TerminalWriteInput = Struct({
47923
+ ...TerminalSessionInput.fields,
47924
+ data: String$1.check(isNonEmpty()).check(isMaxLength(65536))
47925
+ });
47926
+ const TerminalResizeInput = Struct({
47927
+ ...TerminalSessionInput.fields,
47928
+ cols: TerminalColsSchema,
47929
+ rows: TerminalRowsSchema
47930
+ });
47931
+ const TerminalClearInput = TerminalSessionInput;
47932
+ const TerminalRestartInput = Struct({
47933
+ ...TerminalSessionInput.fields,
47934
+ cwd: TrimmedNonEmptyStringSchema$3,
47935
+ cols: TerminalColsSchema,
47936
+ rows: TerminalRowsSchema,
47937
+ env: optional$2(TerminalEnvSchema)
47938
+ });
47939
+ const TerminalCloseInput = Struct({
47940
+ ...TerminalThreadInput.fields,
47941
+ terminalId: optional$2(TerminalIdSchema),
47942
+ deleteHistory: optional$2(Boolean$2)
47943
+ });
47944
+ const TerminalSessionStatus = Literals([
47945
+ "starting",
47946
+ "running",
47947
+ "exited",
47948
+ "error"
47949
+ ]);
47950
+ const TerminalSessionSnapshot = Struct({
47951
+ threadId: String$1.check(isNonEmpty()),
47952
+ terminalId: String$1.check(isNonEmpty()),
47953
+ cwd: String$1.check(isNonEmpty()),
47954
+ status: TerminalSessionStatus,
47955
+ pid: NullOr(Int.check(isGreaterThan(0))),
47956
+ history: String$1,
47957
+ exitCode: NullOr(Int),
47958
+ exitSignal: NullOr(Int),
47959
+ updatedAt: String$1
47960
+ });
47961
+ const TerminalEventBaseSchema = Struct({
47962
+ threadId: String$1.check(isNonEmpty()),
47963
+ terminalId: String$1.check(isNonEmpty()),
47964
+ createdAt: String$1
47965
+ });
47966
+ const TerminalStartedEvent = Struct({
47967
+ ...TerminalEventBaseSchema.fields,
47968
+ type: Literal("started"),
47969
+ snapshot: TerminalSessionSnapshot
47970
+ });
47971
+ const TerminalOutputEvent = Struct({
47972
+ ...TerminalEventBaseSchema.fields,
47973
+ type: Literal("output"),
47974
+ data: String$1
47975
+ });
47976
+ const TerminalExitedEvent = Struct({
47977
+ ...TerminalEventBaseSchema.fields,
47978
+ type: Literal("exited"),
47979
+ exitCode: NullOr(Int),
47980
+ exitSignal: NullOr(Int)
47981
+ });
47982
+ const TerminalErrorEvent = Struct({
47983
+ ...TerminalEventBaseSchema.fields,
47984
+ type: Literal("error"),
47985
+ message: String$1.check(isNonEmpty())
47986
+ });
47987
+ const TerminalClearedEvent = Struct({
47988
+ ...TerminalEventBaseSchema.fields,
47989
+ type: Literal("cleared")
47990
+ });
47991
+ const TerminalRestartedEvent = Struct({
47992
+ ...TerminalEventBaseSchema.fields,
47993
+ type: Literal("restarted"),
47994
+ snapshot: TerminalSessionSnapshot
47995
+ });
47996
+ const TerminalActivityEvent = Struct({
47997
+ ...TerminalEventBaseSchema.fields,
47998
+ type: Literal("activity"),
47999
+ hasRunningSubprocess: Boolean$2
48000
+ });
48001
+ const TerminalEvent = Union([
48002
+ TerminalStartedEvent,
48003
+ TerminalOutputEvent,
48004
+ TerminalExitedEvent,
48005
+ TerminalErrorEvent,
48006
+ TerminalClearedEvent,
48007
+ TerminalRestartedEvent,
48008
+ TerminalActivityEvent
48009
+ ]);
48010
+ //#endregion
48011
+ //#region ../../packages/t3-contracts/src/model.ts
48012
+ const CODEX_REASONING_EFFORT_OPTIONS = [
48013
+ "xhigh",
48014
+ "high",
48015
+ "medium",
48016
+ "low"
48017
+ ];
48018
+ const CodexModelOptions = Struct({
48019
+ reasoningEffort: optional$2(Literals(CODEX_REASONING_EFFORT_OPTIONS)),
48020
+ fastMode: optional$2(Boolean$2)
48021
+ });
48022
+ const ProviderModelOptions = Struct({ codex: optional$2(CodexModelOptions) });
48023
+ const MODEL_OPTIONS_BY_PROVIDER = { codex: [
48024
+ {
48025
+ slug: "gpt-5.5",
48026
+ name: "GPT-5.5"
48027
+ },
48028
+ {
48029
+ slug: "gpt-5.4",
48030
+ name: "GPT-5.4"
48031
+ },
48032
+ {
48033
+ slug: "gpt-5.4-mini",
48034
+ name: "GPT-5.4 Mini"
48035
+ },
48036
+ {
48037
+ slug: "gpt-5.3-codex",
48038
+ name: "GPT-5.3 Codex"
48039
+ },
48040
+ {
48041
+ slug: "gpt-5.3-codex-spark",
48042
+ name: "GPT-5.3 Codex Spark"
48043
+ }
48044
+ ] };
48045
+ const DEFAULT_MODEL_BY_PROVIDER = { codex: "gpt-5.5" };
48046
+ const DEFAULT_GIT_TEXT_GENERATION_MODEL = "gpt-5.4-mini";
48047
+ const MODEL_SLUG_ALIASES_BY_PROVIDER = { codex: {
48048
+ "gpt-5-codex": "gpt-5.5",
48049
+ "5.5": "gpt-5.5",
48050
+ "5.4": "gpt-5.4",
48051
+ "5.3": "gpt-5.3-codex",
48052
+ "gpt-5.3": "gpt-5.3-codex",
48053
+ "5.3-spark": "gpt-5.3-codex-spark",
48054
+ "gpt-5.3-spark": "gpt-5.3-codex-spark"
48055
+ } };
48056
+ //#endregion
48057
+ //#region ../../packages/t3-contracts/src/orchestration.ts
48058
+ const ORCHESTRATION_WS_METHODS = {
48059
+ getSnapshot: "orchestration.getSnapshot",
48060
+ getThreadSnapshot: "orchestration.getThreadSnapshot",
48061
+ subscribeShell: "orchestration.subscribeShell",
48062
+ subscribeThread: "orchestration.subscribeThread",
48063
+ syncExternalThreads: "orchestration.syncExternalThreads",
48064
+ dispatchCommand: "orchestration.dispatchCommand",
48065
+ getTurnDiff: "orchestration.getTurnDiff",
48066
+ getFullThreadDiff: "orchestration.getFullThreadDiff",
48067
+ replayEvents: "orchestration.replayEvents"
48068
+ };
48069
+ const ORCHESTRATION_WS_CHANNELS = { domainEvent: "orchestration.domainEvent" };
48070
+ const ProviderKind = Literal("codex");
48071
+ const ProviderApprovalPolicy = Literals([
48072
+ "untrusted",
48073
+ "on-failure",
48074
+ "on-request",
48075
+ "never"
48076
+ ]);
48077
+ const ProviderSandboxMode = Literals([
48078
+ "read-only",
48079
+ "workspace-write",
48080
+ "danger-full-access"
48081
+ ]);
48082
+ const CodexModelSelection = Struct({
48083
+ provider: Literal("codex"),
48084
+ model: TrimmedNonEmptyString,
48085
+ options: optional$2(CodexModelOptions)
48086
+ });
48087
+ const ModelSelection = CodexModelSelection;
48088
+ const CodexProviderStartOptions$1 = Struct({
48089
+ binaryPath: optional$2(TrimmedNonEmptyString),
48090
+ args: optional$2(String$1),
48091
+ homePath: optional$2(TrimmedNonEmptyString)
48092
+ });
48093
+ const ProviderStartOptions$1 = Struct({ codex: optional$2(CodexProviderStartOptions$1) });
48094
+ const RuntimeMode = Literals(["approval-required", "full-access"]);
48095
+ const DEFAULT_RUNTIME_MODE$2 = "full-access";
48096
+ const ProviderInteractionMode = Literals(["default", "plan"]);
48097
+ const DEFAULT_PROVIDER_INTERACTION_MODE = "default";
48098
+ const ThreadOrigin = Literals(["native", "external-import"]);
48099
+ const DEFAULT_THREAD_ORIGIN = "native";
48100
+ const ProviderRequestKind = Literals([
48101
+ "command",
48102
+ "file-read",
48103
+ "file-change"
48104
+ ]);
48105
+ const AssistantDeliveryMode = Literals(["buffered", "streaming"]);
48106
+ const ProviderApprovalDecision = Literals([
48107
+ "accept",
48108
+ "acceptForSession",
48109
+ "decline",
48110
+ "cancel"
48111
+ ]);
48112
+ const ProviderUserInputAnswers = Record(String$1, Unknown);
48113
+ function supportsCheckpointingForThreadOrigin(origin) {
48114
+ return origin === "native";
48115
+ }
48116
+ const PROVIDER_SEND_TURN_MAX_INPUT_CHARS = 12e4;
48117
+ const PROVIDER_SEND_TURN_MAX_IMAGE_BYTES = 10 * 1024 * 1024;
48118
+ const PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS = 14e6;
48119
+ const CHAT_ATTACHMENT_ID_MAX_CHARS = 128;
48120
+ const ChatAttachmentId = TrimmedNonEmptyString.check(isMaxLength(CHAT_ATTACHMENT_ID_MAX_CHARS), isPattern(/^[a-z0-9_-]+$/i));
48121
+ const ChatImageAttachment = Struct({
48122
+ type: Literal("image"),
48123
+ id: ChatAttachmentId,
48124
+ name: TrimmedNonEmptyString.check(isMaxLength(255)),
48125
+ mimeType: TrimmedNonEmptyString.check(isMaxLength(100), isPattern(/^image\//i)),
48126
+ sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_IMAGE_BYTES))
48127
+ });
48128
+ const UploadChatImageAttachment = Struct({
48129
+ type: Literal("image"),
48130
+ name: TrimmedNonEmptyString.check(isMaxLength(255)),
48131
+ mimeType: TrimmedNonEmptyString.check(isMaxLength(100), isPattern(/^image\//i)),
48132
+ sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_IMAGE_BYTES)),
48133
+ dataUrl: TrimmedNonEmptyString.check(isMaxLength(PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS))
48134
+ });
48135
+ const ChatAttachment = Union([ChatImageAttachment]);
48136
+ const UploadChatAttachment = Union([UploadChatImageAttachment]);
46609
48137
  const ProjectScriptIcon = Literals([
46610
48138
  "play",
46611
48139
  "test",
@@ -48758,6 +50286,8 @@ const WS_METHODS = {
48758
50286
  rateLimitsRefreshNow: "rateLimits.refreshNow",
48759
50287
  licenseGetStatus: "license.getStatus",
48760
50288
  licenseActivate: "license.activate",
50289
+ licenseActivationCreate: "license.activation.create",
50290
+ licenseActivationPoll: "license.activation.poll",
48761
50291
  syncStatus: "sync.status",
48762
50292
  syncPull: "sync.pull",
48763
50293
  syncPush: "sync.push",
@@ -48927,6 +50457,8 @@ const WebSocketRequestBody = Union([
48927
50457
  tagRequestBody(WS_METHODS.rateLimitsRefreshNow, Struct({})),
48928
50458
  tagRequestBody(WS_METHODS.licenseGetStatus, Struct({ force: optional$2(Boolean$2) })),
48929
50459
  tagRequestBody(WS_METHODS.licenseActivate, Struct({ licenseKey: TrimmedNonEmptyString })),
50460
+ tagRequestBody(WS_METHODS.licenseActivationCreate, Struct({})),
50461
+ tagRequestBody(WS_METHODS.licenseActivationPoll, Struct({ sessionId: TrimmedNonEmptyString })),
48930
50462
  tagRequestBody(WS_METHODS.syncStatus, Struct({})),
48931
50463
  tagRequestBody(WS_METHODS.syncPull, Struct({})),
48932
50464
  tagRequestBody(WS_METHODS.syncPush, Struct({})),
@@ -49219,7 +50751,7 @@ const launchDetached = (launch) => gen(function* () {
49219
50751
  });
49220
50752
  const make$9 = gen(function* () {
49221
50753
  const open = yield* tryPromise({
49222
- try: () => import("./open-BWXrZXJl.mjs"),
50754
+ try: () => import("./open-qeX1IlWK.mjs"),
49223
50755
  catch: (cause) => new OpenError({
49224
50756
  message: "failed to load browser opener",
49225
50757
  cause
@@ -50063,8 +51595,8 @@ const runMigrations = gen(function* () {
50063
51595
  //#endregion
50064
51596
  //#region src/persistence/Layers/Sqlite.ts
50065
51597
  const defaultSqliteClientLoaders = {
50066
- bun: () => import("./SqliteClient-CXjquy8x.mjs"),
50067
- node: () => import("./NodeSqliteClient-Cx2_VxdP.mjs")
51598
+ bun: () => import("./SqliteClient-CFZi0MEE.mjs"),
51599
+ node: () => import("./NodeSqliteClient-ColmybgR.mjs")
50068
51600
  };
50069
51601
  const makeRuntimeSqliteLayer = (config) => gen(function* () {
50070
51602
  const loader = defaultSqliteClientLoaders[process.versions.bun !== void 0 ? "bun" : "node"];
@@ -53286,8 +54818,6 @@ const ThreadRevertedPayload = ThreadRevertedPayload$1;
53286
54818
  const ThreadActivityAppendedPayload = ThreadActivityAppendedPayload$1;
53287
54819
  //#endregion
53288
54820
  //#region src/orchestration/projector.ts
53289
- const MAX_THREAD_MESSAGES = 2e3;
53290
- const MAX_THREAD_CHECKPOINTS = 500;
53291
54821
  function checkpointStatusToLatestTurnState(status) {
53292
54822
  if (status === "error") return "error";
53293
54823
  if (status === "missing") return "interrupted";
@@ -53503,7 +55033,7 @@ function projectEvent(model, event) {
53503
55033
  updatedAt: message.updatedAt,
53504
55034
  turnId: message.turnId,
53505
55035
  ...message.attachments !== void 0 ? { attachments: message.attachments } : {}
53506
- } : entry) : [...thread.messages, message]).slice(-MAX_THREAD_MESSAGES);
55036
+ } : entry) : [...thread.messages, message]).slice(-2e3);
53507
55037
  return {
53508
55038
  ...nextBase,
53509
55039
  threads: updateThread(nextBase.threads, payload.threadId, {
@@ -53560,7 +55090,7 @@ function projectEvent(model, event) {
53560
55090
  }, event.type, "checkpoint");
53561
55091
  const existing = thread.checkpoints.find((entry) => entry.turnId === checkpoint.turnId);
53562
55092
  if (existing && existing.status !== "missing" && checkpoint.status === "missing") return nextBase;
53563
- const checkpoints = [...thread.checkpoints.filter((entry) => entry.turnId !== checkpoint.turnId), checkpoint].toSorted((left, right) => left.checkpointTurnCount - right.checkpointTurnCount).slice(-MAX_THREAD_CHECKPOINTS);
55093
+ const checkpoints = [...thread.checkpoints.filter((entry) => entry.turnId !== checkpoint.turnId), checkpoint].toSorted((left, right) => left.checkpointTurnCount - right.checkpointTurnCount).slice(-500);
53564
55094
  return {
53565
55095
  ...nextBase,
53566
55096
  threads: updateThread(nextBase.threads, payload.threadId, {
@@ -53580,9 +55110,9 @@ function projectEvent(model, event) {
53580
55110
  case "thread.reverted": return decodeForEvent(ThreadRevertedPayload, event.payload, event.type, "payload").pipe(map$5((payload) => {
53581
55111
  const thread = nextBase.threads.find((entry) => entry.id === payload.threadId);
53582
55112
  if (!thread) return nextBase;
53583
- const checkpoints = thread.checkpoints.filter((entry) => entry.checkpointTurnCount <= payload.turnCount).toSorted((left, right) => left.checkpointTurnCount - right.checkpointTurnCount).slice(-MAX_THREAD_CHECKPOINTS);
55113
+ const checkpoints = thread.checkpoints.filter((entry) => entry.checkpointTurnCount <= payload.turnCount).toSorted((left, right) => left.checkpointTurnCount - right.checkpointTurnCount).slice(-500);
53584
55114
  const retainedTurnIds = new Set(checkpoints.map((checkpoint) => checkpoint.turnId));
53585
- const messages = retainThreadMessagesAfterRevert(thread.messages, retainedTurnIds, payload.turnCount).slice(-MAX_THREAD_MESSAGES);
55115
+ const messages = retainThreadMessagesAfterRevert(thread.messages, retainedTurnIds, payload.turnCount).slice(-2e3);
53586
55116
  const proposedPlans = retainThreadProposedPlansAfterRevert(thread.proposedPlans, retainedTurnIds).slice(-200);
53587
55117
  const activities = retainThreadActivitiesAfterRevert(thread.activities, retainedTurnIds);
53588
55118
  const latestCheckpoint = checkpoints.at(-1) ?? null;
@@ -58085,839 +59615,113 @@ const makeOrchestrationProjectionPipeline = gen(function* () {
58085
59615
  case "thread.activity-appended": {
58086
59616
  const requestId = extractActivityRequestId(event.payload.activity.payload) ?? event.metadata.requestId ?? null;
58087
59617
  if (requestId === null) return;
58088
- const existingRow = yield* projectionPendingApprovalRepository.getByRequestId({ requestId });
58089
- if (event.payload.activity.kind === "approval.resolved") {
58090
- const resolvedDecisionRaw = typeof event.payload.activity.payload === "object" && event.payload.activity.payload !== null && "decision" in event.payload.activity.payload ? event.payload.activity.payload.decision : null;
58091
- const resolvedDecision = resolvedDecisionRaw === "accept" || resolvedDecisionRaw === "acceptForSession" || resolvedDecisionRaw === "decline" || resolvedDecisionRaw === "cancel" ? resolvedDecisionRaw : null;
58092
- yield* projectionPendingApprovalRepository.upsert({
58093
- requestId,
58094
- threadId: isSome(existingRow) ? existingRow.value.threadId : event.payload.threadId,
58095
- turnId: isSome(existingRow) ? existingRow.value.turnId : event.payload.activity.turnId,
58096
- status: "resolved",
58097
- decision: resolvedDecision,
58098
- createdAt: isSome(existingRow) ? existingRow.value.createdAt : event.payload.activity.createdAt,
58099
- resolvedAt: event.payload.activity.createdAt
58100
- });
58101
- return;
58102
- }
58103
- if (isSome(existingRow) && existingRow.value.status === "resolved") return;
58104
- if (event.payload.activity.kind !== "approval.requested") return;
58105
- yield* projectionPendingApprovalRepository.upsert({
58106
- requestId,
58107
- threadId: event.payload.threadId,
58108
- turnId: event.payload.activity.turnId,
58109
- status: "pending",
58110
- decision: null,
58111
- createdAt: isSome(existingRow) ? existingRow.value.createdAt : event.payload.activity.createdAt,
58112
- resolvedAt: null
58113
- });
58114
- return;
58115
- }
58116
- case "thread.approval-response-requested": {
58117
- const existingRow = yield* projectionPendingApprovalRepository.getByRequestId({ requestId: event.payload.requestId });
58118
- yield* projectionPendingApprovalRepository.upsert({
58119
- requestId: event.payload.requestId,
58120
- threadId: isSome(existingRow) ? existingRow.value.threadId : event.payload.threadId,
58121
- turnId: isSome(existingRow) ? existingRow.value.turnId : null,
58122
- status: "resolved",
58123
- decision: event.payload.decision,
58124
- createdAt: isSome(existingRow) ? existingRow.value.createdAt : event.payload.createdAt,
58125
- resolvedAt: event.payload.createdAt
58126
- });
58127
- return;
58128
- }
58129
- default: return;
58130
- }
58131
- });
58132
- const projectors = [
58133
- {
58134
- name: ORCHESTRATION_PROJECTOR_NAMES.projects,
58135
- apply: applyProjectsProjection
58136
- },
58137
- {
58138
- name: ORCHESTRATION_PROJECTOR_NAMES.threadMessages,
58139
- apply: applyThreadMessagesProjection
58140
- },
58141
- {
58142
- name: ORCHESTRATION_PROJECTOR_NAMES.threadProposedPlans,
58143
- apply: applyThreadProposedPlansProjection
58144
- },
58145
- {
58146
- name: ORCHESTRATION_PROJECTOR_NAMES.threadActivities,
58147
- apply: applyThreadActivitiesProjection
58148
- },
58149
- {
58150
- name: ORCHESTRATION_PROJECTOR_NAMES.threadSessions,
58151
- apply: applyThreadSessionsProjection
58152
- },
58153
- {
58154
- name: ORCHESTRATION_PROJECTOR_NAMES.threadTurns,
58155
- apply: applyThreadTurnsProjection
58156
- },
58157
- {
58158
- name: ORCHESTRATION_PROJECTOR_NAMES.checkpoints,
58159
- apply: applyCheckpointsProjection
58160
- },
58161
- {
58162
- name: ORCHESTRATION_PROJECTOR_NAMES.pendingApprovals,
58163
- apply: applyPendingApprovalsProjection
58164
- },
58165
- {
58166
- name: ORCHESTRATION_PROJECTOR_NAMES.threads,
58167
- apply: applyThreadsProjection
58168
- }
58169
- ];
58170
- const runProjectorForEvent = (projector, event) => gen(function* () {
58171
- const attachmentSideEffects = {
58172
- deletedThreadIds: /* @__PURE__ */ new Set(),
58173
- prunedThreadRelativePaths: /* @__PURE__ */ new Map()
58174
- };
58175
- yield* sql.withTransaction(projector.apply(event, attachmentSideEffects).pipe(flatMap$2(() => projectionStateRepository.upsert({
58176
- projector: projector.name,
58177
- lastAppliedSequence: event.sequence,
58178
- updatedAt: event.occurredAt
58179
- }))));
58180
- yield* runAttachmentSideEffects(attachmentSideEffects).pipe(catch_((cause) => logWarning$1("failed to apply projected attachment side-effects", {
58181
- projector: projector.name,
58182
- sequence: event.sequence,
58183
- eventType: event.type,
58184
- cause
58185
- })));
58186
- });
58187
- const bootstrapProjector = (projector) => projectionStateRepository.getByProjector({ projector: projector.name }).pipe(flatMap$2((stateRow) => runForEach(eventStore.readFromSequence(isSome(stateRow) ? stateRow.value.lastAppliedSequence : 0), (event) => runProjectorForEvent(projector, event))));
58188
- const projectEvent = (event) => forEach$1(projectors, (projector) => runProjectorForEvent(projector, event), { concurrency: 1 }).pipe(provideService(FileSystem, fileSystem), provideService(Path$1, path), provideService(ServerConfig$1, serverConfig), asVoid, catchTag("SqlError", (sqlError) => fail$3(toPersistenceSqlError("ProjectionPipeline.projectEvent:query")(sqlError))));
58189
- return {
58190
- bootstrap: forEach$1(projectors, bootstrapProjector, { concurrency: 1 }).pipe(provideService(FileSystem, fileSystem), provideService(Path$1, path), provideService(ServerConfig$1, serverConfig), asVoid, tap(() => log$1("orchestration projection pipeline bootstrapped").pipe(annotateLogs({ projectors: projectors.length }))), catchTag("SqlError", (sqlError) => fail$3(toPersistenceSqlError("ProjectionPipeline.bootstrap:query")(sqlError)))),
58191
- projectEvent
58192
- };
58193
- });
58194
- const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeline, makeOrchestrationProjectionPipeline).pipe(provideMerge(layer$3), provideMerge(ProjectionProjectRepositoryLive), provideMerge(ProjectionThreadRepositoryLive), provideMerge(ProjectionThreadMessageRepositoryLive), provideMerge(ProjectionThreadProposedPlanRepositoryLive), provideMerge(ProjectionThreadActivityRepositoryLive), provideMerge(ProjectionThreadSessionRepositoryLive), provideMerge(ProjectionTurnRepositoryLive), provideMerge(ProjectionCheckpointRepositoryLive), provideMerge(ProjectionPendingApprovalRepositoryLive), provideMerge(ProjectionStateRepositoryLive));
58195
- //#endregion
58196
- //#region ../../packages/contracts/src/settings/chat-scrollback.ts
58197
- const CHAT_SCROLLBACK_DEFAULT = 200;
58198
- const CHAT_SCROLLBACK_MIN = 50;
58199
- const CHAT_SCROLLBACK_MAX = 5e3;
58200
- function clampChatScrollbackItems(value) {
58201
- if (!Number.isFinite(value)) return 200;
58202
- return Math.max(50, Math.min(CHAT_SCROLLBACK_MAX, Math.round(value)));
58203
- }
58204
- function normalizeChatHistoryScrollbackItems(value) {
58205
- if (value === null) return null;
58206
- if (typeof value === "number" && Number.isFinite(value)) return clampChatScrollbackItems(value);
58207
- if (typeof value === "string") {
58208
- const parsed = Number(value);
58209
- if (Number.isFinite(parsed)) return clampChatScrollbackItems(parsed);
58210
- }
58211
- return 200;
58212
- }
58213
- //#endregion
58214
- //#region ../../packages/contracts/src/settings/commit-message-prompt.ts
58215
- const DEFAULT_COMMIT_MESSAGE_PROMPT = `Generate a concise git commit message for the following changes. Follow conventional commit format (e.g., feat:, fix:, refactor:, docs:, etc.). Keep the summary line under 72 characters. Only output the commit message, nothing else.
58216
-
58217
- Changes:
58218
- {diff}`;
58219
- function normalizeLineEndings$1(value) {
58220
- return value.replace(/\r\n/g, "\n");
58221
- }
58222
- function normalizeCommitMessagePrompt(value) {
58223
- if (typeof value !== "string") return null;
58224
- const normalized = normalizeLineEndings$1(value).trim();
58225
- return normalized.length > 0 ? normalized : null;
58226
- }
58227
- //#endregion
58228
- //#region ../../packages/contracts/src/settings/auto-roll.ts
58229
- const DEFAULT_AUTO_ROLL_ENABLED = false;
58230
- const DEFAULT_AUTO_ROLL_REARM_REMAINING_THRESHOLD = 15;
58231
- const DEFAULT_AUTO_ROLL_SWITCH_REMAINING_THRESHOLD = 5;
58232
- const DEFAULT_RESTART_OFFICIAL_CODEX_ON_AUTO_ROLL = false;
58233
- const DEFAULT_LAUNCH_OFFICIAL_CODEX_WHEN_CLOSED_ON_AUTO_ROLL = false;
58234
- const DEFAULT_AUTO_ROLL_PRIORITY_ORDER = [];
58235
- const DEFAULT_LOW_REMAINING_NOTIFICATION_ENABLED = false;
58236
- const DEFAULT_LOW_REMAINING_NOTIFICATION_THRESHOLD = 1;
58237
- const AUTO_ROLL_SWITCH_REMAINING_MIN = 0;
58238
- const AUTO_ROLL_SWITCH_REMAINING_MAX = 50;
58239
- const AUTO_ROLL_REARM_REMAINING_MAX = 100;
58240
- const LOW_REMAINING_NOTIFICATION_MIN = 1;
58241
- const LOW_REMAINING_NOTIFICATION_MAX = 50;
58242
- function clampNumber(value, min, max) {
58243
- return Math.min(max, Math.max(min, value));
58244
- }
58245
- function resolveFiniteNumber(value, fallback) {
58246
- return typeof value === "number" && Number.isFinite(value) ? value : fallback;
58247
- }
58248
- function legacyUsedThresholdToRemaining(value, fallbackUsed) {
58249
- return 100 - clampNumber(resolveFiniteNumber(value, fallbackUsed), 0, 100);
58250
- }
58251
- function sanitizeAutoRollSwitchRemainingThreshold(value) {
58252
- return clampNumber(resolveFiniteNumber(value, 5), 0, 50);
58253
- }
58254
- function sanitizeAutoRollRearmRemainingThreshold(value, switchRemainingThreshold) {
58255
- const sanitizedSwitch = sanitizeAutoRollSwitchRemainingThreshold(switchRemainingThreshold);
58256
- return clampNumber(resolveFiniteNumber(value, 15), sanitizedSwitch + 1, 100);
58257
- }
58258
- function sanitizeAutoRollThresholds(rearmRemainingThreshold, switchRemainingThreshold) {
58259
- const sanitizedSwitch = sanitizeAutoRollSwitchRemainingThreshold(switchRemainingThreshold);
58260
- return {
58261
- rearmRemainingThreshold: sanitizeAutoRollRearmRemainingThreshold(rearmRemainingThreshold, sanitizedSwitch),
58262
- switchRemainingThreshold: sanitizedSwitch
58263
- };
58264
- }
58265
- function sanitizeAutoRollPriorityOrder(value) {
58266
- if (!Array.isArray(value)) return [...DEFAULT_AUTO_ROLL_PRIORITY_ORDER];
58267
- const seen = /* @__PURE__ */ new Set();
58268
- const normalized = [];
58269
- for (const item of value) {
58270
- if (typeof item !== "string") continue;
58271
- const trimmed = item.trim();
58272
- if (!trimmed || seen.has(trimmed)) continue;
58273
- seen.add(trimmed);
58274
- normalized.push(trimmed);
58275
- }
58276
- return normalized;
58277
- }
58278
- function sanitizeLowRemainingNotificationThreshold(value) {
58279
- return clampNumber(resolveFiniteNumber(value, 1), 1, 50);
58280
- }
58281
- function normalizeAutoRollSettings(raw) {
58282
- const enabled = typeof raw?.enabled === "boolean" ? raw.enabled : false;
58283
- const rawSwitchRemaining = typeof raw?.switchRemainingThreshold === "number" ? raw.switchRemainingThreshold : legacyUsedThresholdToRemaining(raw?.switchThreshold, 95);
58284
- const { rearmRemainingThreshold: normalizedRearm, switchRemainingThreshold: normalizedSwitch } = sanitizeAutoRollThresholds(typeof raw?.rearmRemainingThreshold === "number" ? raw.rearmRemainingThreshold : legacyUsedThresholdToRemaining(raw?.warningThreshold, 85), rawSwitchRemaining);
58285
- return {
58286
- enabled,
58287
- rearmRemainingThreshold: normalizedRearm,
58288
- switchRemainingThreshold: normalizedSwitch,
58289
- restartOfficialCodexOnAutoRoll: raw?.restartOfficialCodexOnAutoRoll === true ? true : false,
58290
- launchOfficialCodexWhenClosedOnAutoRoll: raw?.launchOfficialCodexWhenClosedOnAutoRoll === true ? true : false,
58291
- priorityOrder: sanitizeAutoRollPriorityOrder(raw?.priorityOrder),
58292
- lowRemainingNotificationEnabled: raw?.lowRemainingNotificationEnabled === true ? true : false,
58293
- lowRemainingNotificationThreshold: sanitizeLowRemainingNotificationThreshold(typeof raw?.lowRemainingNotificationThreshold === "number" ? raw.lowRemainingNotificationThreshold : NaN)
58294
- };
58295
- }
58296
- //#endregion
58297
- //#region ../../packages/runtime-app-state/src/storage/documents.ts
58298
- const APP_STORAGE_TABLE = "app_storage_documents";
58299
- const APP_STORAGE_DB_DIR = "t3-projects";
58300
- const APP_STORAGE_DB_NAME = "state.sqlite";
58301
- const SQLITE_BUSY_TIMEOUT_MS = 5e3;
58302
- const SQLITE_BUSY_MAX_ATTEMPTS = 3;
58303
- const SQLITE_BUSY_RETRY_DELAY_MS = 100;
58304
- const writeQueueByDbPath = /* @__PURE__ */ new Map();
58305
- const initializedDbPaths = /* @__PURE__ */ new Set();
58306
- function isRecord$9(value) {
58307
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
58308
- }
58309
- function clone$1(value) {
58310
- return JSON.parse(JSON.stringify(value));
58311
- }
58312
- function safeParseJson(raw) {
58313
- if (typeof raw !== "string" || raw.trim().length === 0) return null;
58314
- try {
58315
- return JSON.parse(raw);
58316
- } catch {
58317
- return null;
58318
- }
58319
- }
58320
- function sleep(ms) {
58321
- return new Promise((resolve) => setTimeout(resolve, ms));
58322
- }
58323
- function isSqliteBusyError(error) {
58324
- if (!error || typeof error !== "object") return false;
58325
- const sqliteError = error;
58326
- const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : "";
58327
- return sqliteError.code === "SQLITE_BUSY" || sqliteError.errno === 5 || message.includes("sqlite_busy") || message.includes("database is locked");
58328
- }
58329
- function beginImmediate(db) {
58330
- db.exec("BEGIN IMMEDIATE");
58331
- }
58332
- function commit(db) {
58333
- db.exec("COMMIT");
58334
- }
58335
- function rollback(db) {
58336
- try {
58337
- db.exec("ROLLBACK");
58338
- } catch {}
58339
- }
58340
- function useStatement(db, sql, task) {
58341
- const statement = db.prepare(sql);
58342
- try {
58343
- return task(statement);
58344
- } finally {
58345
- statement.finalize?.();
58346
- }
58347
- }
58348
- async function withWriteQueue(dbPath, task) {
58349
- const previous = writeQueueByDbPath.get(dbPath) ?? Promise.resolve();
58350
- let release;
58351
- const current = new Promise((resolve) => {
58352
- release = resolve;
58353
- });
58354
- writeQueueByDbPath.set(dbPath, current);
58355
- await previous;
58356
- try {
58357
- return await task();
58358
- } finally {
58359
- release?.();
58360
- if (writeQueueByDbPath.get(dbPath) === current) writeQueueByDbPath.delete(dbPath);
58361
- }
58362
- }
58363
- function applyConnectionPragmas(db) {
58364
- db.exec(`PRAGMA busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS};`);
58365
- db.exec("PRAGMA journal_mode = WAL;");
58366
- db.exec("PRAGMA foreign_keys = ON;");
58367
- }
58368
- function ensureSchema(db, dbPath) {
58369
- if (initializedDbPaths.has(dbPath)) return;
58370
- db.exec(`
58371
- CREATE TABLE IF NOT EXISTS ${APP_STORAGE_TABLE} (
58372
- namespace TEXT PRIMARY KEY,
58373
- value_json TEXT NOT NULL,
58374
- updated_at TEXT NOT NULL
58375
- )
58376
- `);
58377
- initializedDbPaths.add(dbPath);
58378
- }
58379
- async function openDatabase(dbPath) {
58380
- await promises.mkdir(nodePath.dirname(dbPath), { recursive: true });
58381
- if (process.versions.bun !== void 0) {
58382
- const database = new (await (Function("return import('bun:sqlite')")())).Database(dbPath);
58383
- return {
58384
- exec: database.exec.bind(database),
58385
- prepare: database.prepare.bind(database),
58386
- close: database.close.bind(database)
58387
- };
58388
- }
58389
- const database = new (await (Function("return import('node:sqlite')")())).DatabaseSync(dbPath);
58390
- return {
58391
- exec: database.exec.bind(database),
58392
- prepare: database.prepare.bind(database),
58393
- close: database.close.bind(database)
58394
- };
58395
- }
58396
- async function withDatabase(dbPath, task) {
58397
- for (let attempt = 1; attempt <= SQLITE_BUSY_MAX_ATTEMPTS; attempt += 1) {
58398
- const db = await openDatabase(dbPath);
58399
- try {
58400
- applyConnectionPragmas(db);
58401
- ensureSchema(db, dbPath);
58402
- return task(db);
58403
- } catch (error) {
58404
- if (!isSqliteBusyError(error) || attempt >= SQLITE_BUSY_MAX_ATTEMPTS) throw error;
58405
- } finally {
58406
- db.close();
58407
- }
58408
- await sleep(SQLITE_BUSY_RETRY_DELAY_MS * attempt);
58409
- }
58410
- throw new Error("App storage database remained busy after retrying.");
58411
- }
58412
- function resolveAppStorageDbPath(userDataDir) {
58413
- return nodePath.join(userDataDir, APP_STORAGE_DB_DIR, APP_STORAGE_DB_NAME);
58414
- }
58415
- async function readDocument(dbPath, namespace, normalize) {
58416
- return withDatabase(dbPath, (db) => {
58417
- const row = useStatement(db, `SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`, (statement) => statement.get(namespace));
58418
- const parsed = isRecord$9(row) ? safeParseJson(row.valueJson) : null;
58419
- if (parsed === null) return null;
58420
- return normalize(parsed);
58421
- });
58422
- }
58423
- async function writeDocument(dbPath, namespace, value) {
58424
- return withWriteQueue(dbPath, async () => withDatabase(dbPath, (db) => {
58425
- const normalizedValue = clone$1(value);
58426
- beginImmediate(db);
58427
- try {
58428
- useStatement(db, `
58429
- INSERT INTO ${APP_STORAGE_TABLE} (namespace, value_json, updated_at)
58430
- VALUES (?, ?, ?)
58431
- ON CONFLICT(namespace)
58432
- DO UPDATE SET
58433
- value_json = excluded.value_json,
58434
- updated_at = excluded.updated_at
58435
- `, (statement) => statement.run(namespace, JSON.stringify(normalizedValue), (/* @__PURE__ */ new Date()).toISOString()));
58436
- commit(db);
58437
- return normalizedValue;
58438
- } catch (error) {
58439
- rollback(db);
58440
- throw error;
58441
- }
58442
- }));
58443
- }
58444
- async function updateDocument(input) {
58445
- return withWriteQueue(input.dbPath, async () => withDatabase(input.dbPath, (db) => {
58446
- beginImmediate(db);
58447
- try {
58448
- const row = useStatement(db, `SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`, (statement) => statement.get(input.namespace));
58449
- const current = isRecord$9(row) ? input.normalize(safeParseJson(row.valueJson) ?? input.fallback()) : input.fallback();
58450
- const next = input.normalize(input.transform(clone$1(current)));
58451
- useStatement(db, `
58452
- INSERT INTO ${APP_STORAGE_TABLE} (namespace, value_json, updated_at)
58453
- VALUES (?, ?, ?)
58454
- ON CONFLICT(namespace)
58455
- DO UPDATE SET
58456
- value_json = excluded.value_json,
58457
- updated_at = excluded.updated_at
58458
- `, (statement) => statement.run(input.namespace, JSON.stringify(next), (/* @__PURE__ */ new Date()).toISOString()));
58459
- commit(db);
58460
- return clone$1(next);
58461
- } catch (error) {
58462
- rollback(db);
58463
- throw error;
59618
+ const existingRow = yield* projectionPendingApprovalRepository.getByRequestId({ requestId });
59619
+ if (event.payload.activity.kind === "approval.resolved") {
59620
+ const resolvedDecisionRaw = typeof event.payload.activity.payload === "object" && event.payload.activity.payload !== null && "decision" in event.payload.activity.payload ? event.payload.activity.payload.decision : null;
59621
+ const resolvedDecision = resolvedDecisionRaw === "accept" || resolvedDecisionRaw === "acceptForSession" || resolvedDecisionRaw === "decline" || resolvedDecisionRaw === "cancel" ? resolvedDecisionRaw : null;
59622
+ yield* projectionPendingApprovalRepository.upsert({
59623
+ requestId,
59624
+ threadId: isSome(existingRow) ? existingRow.value.threadId : event.payload.threadId,
59625
+ turnId: isSome(existingRow) ? existingRow.value.turnId : event.payload.activity.turnId,
59626
+ status: "resolved",
59627
+ decision: resolvedDecision,
59628
+ createdAt: isSome(existingRow) ? existingRow.value.createdAt : event.payload.activity.createdAt,
59629
+ resolvedAt: event.payload.activity.createdAt
59630
+ });
59631
+ return;
59632
+ }
59633
+ if (isSome(existingRow) && existingRow.value.status === "resolved") return;
59634
+ if (event.payload.activity.kind !== "approval.requested") return;
59635
+ yield* projectionPendingApprovalRepository.upsert({
59636
+ requestId,
59637
+ threadId: event.payload.threadId,
59638
+ turnId: event.payload.activity.turnId,
59639
+ status: "pending",
59640
+ decision: null,
59641
+ createdAt: isSome(existingRow) ? existingRow.value.createdAt : event.payload.activity.createdAt,
59642
+ resolvedAt: null
59643
+ });
59644
+ return;
59645
+ }
59646
+ case "thread.approval-response-requested": {
59647
+ const existingRow = yield* projectionPendingApprovalRepository.getByRequestId({ requestId: event.payload.requestId });
59648
+ yield* projectionPendingApprovalRepository.upsert({
59649
+ requestId: event.payload.requestId,
59650
+ threadId: isSome(existingRow) ? existingRow.value.threadId : event.payload.threadId,
59651
+ turnId: isSome(existingRow) ? existingRow.value.turnId : null,
59652
+ status: "resolved",
59653
+ decision: event.payload.decision,
59654
+ createdAt: isSome(existingRow) ? existingRow.value.createdAt : event.payload.createdAt,
59655
+ resolvedAt: event.payload.createdAt
59656
+ });
59657
+ return;
59658
+ }
59659
+ default: return;
58464
59660
  }
58465
- }));
58466
- }
58467
- //#endregion
58468
- //#region ../../packages/runtime-app-state/src/app/state.ts
58469
- const LEGACY_APP_STATE_FILE = "app-state.json";
58470
- const APP_STATE_DOCUMENT = "desktop.app-state";
58471
- const APP_NAME = "codexuse-desktop";
58472
- let configuredUserDataDir = null;
58473
- let appStateCache = null;
58474
- let writeLock = Promise.resolve();
58475
- const writeLockContext = new AsyncLocalStorage();
58476
- function isRecord$8(value) {
58477
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
58478
- }
58479
- function clone(value) {
58480
- return JSON.parse(JSON.stringify(value));
58481
- }
58482
- function resolveDefaultUserDataDir() {
58483
- const home = process.env.HOME || process.env.USERPROFILE || nodeOs.homedir();
58484
- if (!home) throw new Error("Unable to resolve home directory for app state.");
58485
- if (process.platform === "darwin") return nodePath.join(home, "Library", "Application Support", APP_NAME);
58486
- if (process.platform === "win32") {
58487
- const appData = process.env.APPDATA;
58488
- if (appData) return nodePath.join(appData, APP_NAME);
58489
- return nodePath.join(home, "AppData", "Roaming", APP_NAME);
58490
- }
58491
- return nodePath.join(home, ".config", APP_NAME);
58492
- }
58493
- function getUserDataDir() {
58494
- return configuredUserDataDir ?? resolveDefaultUserDataDir();
58495
- }
58496
- function resolveLegacyAppStatePath() {
58497
- return nodePath.join(getUserDataDir(), LEGACY_APP_STATE_FILE);
58498
- }
58499
- function resolveStorageDbPath() {
58500
- return resolveAppStorageDbPath(getUserDataDir());
58501
- }
58502
- function createDefaultAppState() {
58503
- return {
58504
- schemaVersion: 1,
58505
- autoRoll: {
58506
- enabled: false,
58507
- rearmRemainingThreshold: 15,
58508
- switchRemainingThreshold: 5,
58509
- restartOfficialCodexOnAutoRoll: false,
58510
- launchOfficialCodexWhenClosedOnAutoRoll: false,
58511
- priorityOrder: [],
58512
- lowRemainingNotificationEnabled: false,
58513
- lowRemainingNotificationThreshold: 1
58514
- },
58515
- officialCodex: {
58516
- lastProfileSwitchAt: null,
58517
- lastProfileSwitchProfileKey: null,
58518
- lastVerifiedLaunchAt: null,
58519
- lastVerifiedLaunchProfileKey: null,
58520
- lastObservedPid: null,
58521
- lastRestartStatus: null,
58522
- lastRestartReason: null,
58523
- activity: [],
58524
- instancesByProfileName: {},
58525
- pendingRestartDebt: null
59661
+ });
59662
+ const projectors = [
59663
+ {
59664
+ name: ORCHESTRATION_PROJECTOR_NAMES.projects,
59665
+ apply: applyProjectsProjection
58526
59666
  },
58527
- app: {
58528
- lastAppVersion: null,
58529
- pendingUpdateVersion: null,
58530
- lastProfileName: null
59667
+ {
59668
+ name: ORCHESTRATION_PROJECTOR_NAMES.threadMessages,
59669
+ apply: applyThreadMessagesProjection
58531
59670
  },
58532
- license: {
58533
- licenseKey: null,
58534
- purchaseEmail: null,
58535
- lastVerifiedAt: null,
58536
- nextCheckAt: null,
58537
- lastVerificationError: null,
58538
- status: "inactive",
58539
- signature: null
59671
+ {
59672
+ name: ORCHESTRATION_PROJECTOR_NAMES.threadProposedPlans,
59673
+ apply: applyThreadProposedPlansProjection
58540
59674
  },
58541
- preferences: {
58542
- excludeFolders: [],
58543
- enableTaskCompleteBeep: true,
58544
- preventSleepDuringTasks: true,
58545
- chatHistoryScrollbackItems: 200,
58546
- systemNotificationsEnabled: true,
58547
- subagentSystemNotificationsEnabled: true,
58548
- folderHistory: [],
58549
- pinnedPaths: []
59675
+ {
59676
+ name: ORCHESTRATION_PROJECTOR_NAMES.threadActivities,
59677
+ apply: applyThreadActivitiesProjection
58550
59678
  },
58551
- runtimeSettings: {},
58552
- ui: {
58553
- themeMode: null,
58554
- layout: { sidebarCollapsed: null },
58555
- profiles: {
58556
- viewMode: null,
58557
- sortBy: null,
58558
- groupBy: null,
58559
- planFilter: null,
58560
- healthFilter: null,
58561
- customGroupFilter: null,
58562
- toolbarOpen: null,
58563
- collapsedSections: {}
58564
- },
58565
- onboarding: {
58566
- welcomeCompleted: false,
58567
- welcomeCompletedAt: null,
58568
- welcomeResumeStep: null,
58569
- milestones: {
58570
- firstProfileAdded: false,
58571
- secondProfileAdded: false
58572
- },
58573
- sessionCount: 0,
58574
- nudgeCooldowns: {},
58575
- nudgeDismissCount: {},
58576
- proUnlockedCelebrated: false
58577
- },
58578
- projectThreadSelections: {},
58579
- duplicateWarningDismissedKey: null,
58580
- pendingLicenseActivation: false
59679
+ {
59680
+ name: ORCHESTRATION_PROJECTOR_NAMES.threadSessions,
59681
+ apply: applyThreadSessionsProjection
58581
59682
  },
58582
- profileDashboard: { customGroupsByAccountKey: {} },
58583
- workspaceSettingsByPath: {},
58584
- conversationCategoriesByCwd: {},
58585
- conversationCategoryAssignmentsByCwd: {},
58586
- git: { commitMessagePrompt: DEFAULT_COMMIT_MESSAGE_PROMPT },
58587
- skills: {
58588
- sources: [],
58589
- installsBySlug: {}
59683
+ {
59684
+ name: ORCHESTRATION_PROJECTOR_NAMES.threadTurns,
59685
+ apply: applyThreadTurnsProjection
58590
59686
  },
58591
- sync: {
58592
- lastPushAt: null,
58593
- lastPullAt: null,
58594
- lastError: null,
58595
- remoteUpdatedAt: null
59687
+ {
59688
+ name: ORCHESTRATION_PROJECTOR_NAMES.checkpoints,
59689
+ apply: applyCheckpointsProjection
58596
59690
  },
58597
- analytics: {
58598
- anonymousId: null,
58599
- enabled: true,
58600
- lastFlushAt: null,
58601
- lastError: null
59691
+ {
59692
+ name: ORCHESTRATION_PROJECTOR_NAMES.pendingApprovals,
59693
+ apply: applyPendingApprovalsProjection
58602
59694
  },
58603
- profilesByName: {},
58604
- migration: {
58605
- status: "pending",
58606
- startedAt: null,
58607
- completedAt: null,
58608
- localStorageImportedAt: null,
58609
- lastError: null
58610
- }
58611
- };
58612
- }
58613
- function asString$10(value) {
58614
- if (typeof value !== "string") return null;
58615
- const trimmed = value.trim();
58616
- return trimmed.length > 0 ? trimmed : null;
58617
- }
58618
- function asNumberOrNull(value) {
58619
- return typeof value === "number" && Number.isFinite(value) ? value : null;
58620
- }
58621
- function asBooleanOrNull(value) {
58622
- return typeof value === "boolean" ? value : null;
58623
- }
58624
- function normalizeAppState(raw) {
58625
- const defaults = createDefaultAppState();
58626
- if (!isRecord$8(raw)) return defaults;
58627
- const rawAutoRoll = isRecord$8(raw.autoRoll) ? raw.autoRoll : void 0;
58628
- const merged = clone(deepMerge(defaults, raw));
58629
- merged.schemaVersion = 1;
58630
- merged.autoRoll = normalizeAutoRollSettings(rawAutoRoll);
58631
- if (!isRecord$8(merged.officialCodex)) merged.officialCodex = clone(defaults.officialCodex);
58632
- merged.officialCodex.lastProfileSwitchAt = asNumberOrNull(merged.officialCodex.lastProfileSwitchAt);
58633
- merged.officialCodex.lastProfileSwitchProfileKey = asString$10(merged.officialCodex.lastProfileSwitchProfileKey);
58634
- merged.officialCodex.lastVerifiedLaunchAt = asNumberOrNull(merged.officialCodex.lastVerifiedLaunchAt);
58635
- merged.officialCodex.lastVerifiedLaunchProfileKey = asString$10(merged.officialCodex.lastVerifiedLaunchProfileKey);
58636
- merged.officialCodex.lastObservedPid = asNumberOrNull(merged.officialCodex.lastObservedPid);
58637
- merged.officialCodex.lastRestartStatus = asString$10(merged.officialCodex.lastRestartStatus);
58638
- merged.officialCodex.lastRestartReason = asString$10(merged.officialCodex.lastRestartReason);
58639
- merged.officialCodex.activity = Array.isArray(merged.officialCodex.activity) ? merged.officialCodex.activity.filter((entry) => isRecord$8(entry)).map((entry) => ({
58640
- id: asString$10(entry.id) ?? "",
58641
- at: asString$10(entry.at) ?? (/* @__PURE__ */ new Date(0)).toISOString(),
58642
- kind: entry.kind === "auto-roll-eval" || entry.kind === "profile-switch" || entry.kind === "auth-verified" || entry.kind === "official-codex-restart" || entry.kind === "reset-window-activation" || entry.kind === "low-remaining-alert" ? entry.kind : "auto-roll-eval",
58643
- status: asString$10(entry.status) ?? "unknown",
58644
- reason: asString$10(entry.reason),
58645
- decisionId: asString$10(entry.decisionId),
58646
- profileName: asString$10(entry.profileName),
58647
- sourceProfileName: asString$10(entry.sourceProfileName),
58648
- targetProfileName: asString$10(entry.targetProfileName),
58649
- remainingPercent: asNumberOrNull(entry.remainingPercent),
58650
- threshold: asNumberOrNull(entry.threshold),
58651
- snapshotAgeMs: asNumberOrNull(entry.snapshotAgeMs),
58652
- snapshotSource: asString$10(entry.snapshotSource),
58653
- phase: asString$10(entry.phase),
58654
- pid: asNumberOrNull(entry.pid),
58655
- profileKeyHash: asString$10(entry.profileKeyHash),
58656
- switchVerified: asBooleanOrNull(entry.switchVerified),
58657
- restartRequested: asBooleanOrNull(entry.restartRequested),
58658
- restartResult: asString$10(entry.restartResult),
58659
- observedProfileName: asString$10(entry.observedProfileName),
58660
- observedProfileKeyHash: asString$10(entry.observedProfileKeyHash),
58661
- observedProfileMatchSource: asString$10(entry.observedProfileMatchSource)
58662
- })).filter((entry) => entry.id && entry.at).slice(-50) : [];
58663
- if (!isRecord$8(merged.officialCodex.instancesByProfileName)) merged.officialCodex.instancesByProfileName = {};
58664
- else {
58665
- const nextInstances = {};
58666
- for (const [key, value] of Object.entries(merged.officialCodex.instancesByProfileName)) {
58667
- if (!isRecord$8(value)) continue;
58668
- const profileName = asString$10(value.profileName) ?? asString$10(key);
58669
- if (!profileName) continue;
58670
- nextInstances[profileName] = {
58671
- profileName,
58672
- profileKey: asString$10(value.profileKey),
58673
- profileHome: asString$10(value.profileHome),
58674
- appPath: asString$10(value.appPath),
58675
- bundleId: asString$10(value.bundleId),
58676
- pid: asNumberOrNull(value.pid),
58677
- appServerPid: asNumberOrNull(value.appServerPid),
58678
- launchedAt: asNumberOrNull(value.launchedAt),
58679
- lastVerifiedAt: asNumberOrNull(value.lastVerifiedAt),
58680
- lastStatus: asString$10(value.lastStatus),
58681
- lastError: asString$10(value.lastError)
58682
- };
58683
- }
58684
- merged.officialCodex.instancesByProfileName = nextInstances;
58685
- }
58686
- if (isRecord$8(merged.officialCodex.pendingRestartDebt)) {
58687
- const debt = merged.officialCodex.pendingRestartDebt;
58688
- const targetProfileName = asString$10(debt.targetProfileName);
58689
- merged.officialCodex.pendingRestartDebt = targetProfileName ? {
58690
- targetProfileName,
58691
- targetProfileKey: asString$10(debt.targetProfileKey),
58692
- sourceProfileName: asString$10(debt.sourceProfileName),
58693
- sourceProfileKey: asString$10(debt.sourceProfileKey),
58694
- decisionId: asString$10(debt.decisionId),
58695
- attempts: asNumberOrNull(debt.attempts) ?? 0,
58696
- lastReason: asString$10(debt.lastReason)
58697
- } : null;
58698
- } else merged.officialCodex.pendingRestartDebt = null;
58699
- merged.app.lastAppVersion = asString$10(merged.app.lastAppVersion);
58700
- merged.app.pendingUpdateVersion = asString$10(merged.app.pendingUpdateVersion);
58701
- merged.app.lastProfileName = asString$10(merged.app.lastProfileName);
58702
- {
58703
- const allowedAppKeys = new Set(Object.keys(defaults.app));
58704
- for (const key of Object.keys(merged.app)) if (!allowedAppKeys.has(key)) delete merged.app[key];
58705
- }
58706
- merged.license.licenseKey = asString$10(merged.license.licenseKey);
58707
- merged.license.purchaseEmail = asString$10(merged.license.purchaseEmail);
58708
- merged.license.lastVerifiedAt = asString$10(merged.license.lastVerifiedAt);
58709
- merged.license.nextCheckAt = asString$10(merged.license.nextCheckAt);
58710
- merged.license.lastVerificationError = asString$10(merged.license.lastVerificationError);
58711
- merged.license.signature = asString$10(merged.license.signature);
58712
- if (![
58713
- "inactive",
58714
- "active",
58715
- "grace",
58716
- "error"
58717
- ].includes(merged.license.status)) merged.license.status = "inactive";
58718
- if (!Array.isArray(merged.preferences.excludeFolders)) merged.preferences.excludeFolders = [];
58719
- if (typeof merged.preferences.enableTaskCompleteBeep !== "boolean") merged.preferences.enableTaskCompleteBeep = true;
58720
- if (typeof merged.preferences.preventSleepDuringTasks !== "boolean") merged.preferences.preventSleepDuringTasks = true;
58721
- merged.preferences.chatHistoryScrollbackItems = normalizeChatHistoryScrollbackItems(merged.preferences.chatHistoryScrollbackItems);
58722
- if (typeof merged.preferences.systemNotificationsEnabled !== "boolean") merged.preferences.systemNotificationsEnabled = true;
58723
- if (typeof merged.preferences.subagentSystemNotificationsEnabled !== "boolean") merged.preferences.subagentSystemNotificationsEnabled = true;
58724
- if (!Array.isArray(merged.preferences.folderHistory)) merged.preferences.folderHistory = [];
58725
- if (!Array.isArray(merged.preferences.pinnedPaths)) merged.preferences.pinnedPaths = [];
58726
- {
58727
- const allowedPreferenceKeys = new Set(Object.keys(defaults.preferences));
58728
- for (const key of Object.keys(merged.preferences)) if (!allowedPreferenceKeys.has(key)) delete merged.preferences[key];
58729
- }
58730
- if (!isRecord$8(merged.runtimeSettings)) merged.runtimeSettings = {};
58731
- if (!isRecord$8(merged.ui)) merged.ui = clone(defaults.ui);
58732
- merged.ui.themeMode = merged.ui.themeMode === "light" || merged.ui.themeMode === "dark" ? merged.ui.themeMode : null;
58733
- if (!isRecord$8(merged.ui.layout)) merged.ui.layout = clone(defaults.ui.layout);
58734
- if (typeof merged.ui.layout.sidebarCollapsed !== "boolean") merged.ui.layout.sidebarCollapsed = null;
58735
- if (!isRecord$8(merged.ui.profiles)) merged.ui.profiles = clone(defaults.ui.profiles);
58736
- merged.ui.profiles.viewMode = merged.ui.profiles.viewMode === "cards" || merged.ui.profiles.viewMode === "compact" ? merged.ui.profiles.viewMode : null;
58737
- merged.ui.profiles.sortBy = asString$10(merged.ui.profiles.sortBy);
58738
- merged.ui.profiles.groupBy = asString$10(merged.ui.profiles.groupBy);
58739
- merged.ui.profiles.planFilter = asString$10(merged.ui.profiles.planFilter);
58740
- merged.ui.profiles.healthFilter = asString$10(merged.ui.profiles.healthFilter);
58741
- merged.ui.profiles.customGroupFilter = asString$10(merged.ui.profiles.customGroupFilter);
58742
- if (typeof merged.ui.profiles.toolbarOpen !== "boolean") merged.ui.profiles.toolbarOpen = null;
58743
- if (!isRecord$8(merged.ui.profiles.collapsedSections)) merged.ui.profiles.collapsedSections = {};
58744
- else merged.ui.profiles.collapsedSections = Object.fromEntries(Object.entries(merged.ui.profiles.collapsedSections).flatMap(([key, value]) => {
58745
- const normalizedKey = asString$10(key);
58746
- if (!normalizedKey || typeof value !== "boolean") return [];
58747
- return [[normalizedKey, value]];
58748
- }));
58749
- if (!isRecord$8(merged.ui.onboarding)) merged.ui.onboarding = clone(defaults.ui.onboarding);
58750
- if (typeof merged.ui.onboarding.welcomeCompleted !== "boolean") merged.ui.onboarding.welcomeCompleted = false;
58751
- if (!Number.isFinite(merged.ui.onboarding.welcomeCompletedAt)) merged.ui.onboarding.welcomeCompletedAt = null;
58752
- merged.ui.onboarding.welcomeResumeStep = merged.ui.onboarding.welcomeResumeStep === 2 ? 2 : null;
58753
- if (!isRecord$8(merged.ui.onboarding.milestones)) merged.ui.onboarding.milestones = clone(defaults.ui.onboarding.milestones);
58754
- if (typeof merged.ui.onboarding.milestones.firstProfileAdded !== "boolean") merged.ui.onboarding.milestones.firstProfileAdded = false;
58755
- if (typeof merged.ui.onboarding.milestones.secondProfileAdded !== "boolean") merged.ui.onboarding.milestones.secondProfileAdded = false;
58756
- if (!Number.isFinite(merged.ui.onboarding.sessionCount)) merged.ui.onboarding.sessionCount = 0;
58757
- if (!isRecord$8(merged.ui.onboarding.nudgeCooldowns)) merged.ui.onboarding.nudgeCooldowns = {};
58758
- else merged.ui.onboarding.nudgeCooldowns = Object.fromEntries(Object.entries(merged.ui.onboarding.nudgeCooldowns).flatMap(([key, value]) => {
58759
- const normalizedKey = asString$10(key);
58760
- if (!normalizedKey || !Number.isFinite(value)) return [];
58761
- return [[normalizedKey, Number(value)]];
58762
- }));
58763
- if (!isRecord$8(merged.ui.onboarding.nudgeDismissCount)) merged.ui.onboarding.nudgeDismissCount = {};
58764
- else merged.ui.onboarding.nudgeDismissCount = Object.fromEntries(Object.entries(merged.ui.onboarding.nudgeDismissCount).flatMap(([key, value]) => {
58765
- const normalizedKey = asString$10(key);
58766
- if (!normalizedKey || !Number.isFinite(value)) return [];
58767
- return [[normalizedKey, Number(value)]];
58768
- }));
58769
- if (typeof merged.ui.onboarding.proUnlockedCelebrated !== "boolean") merged.ui.onboarding.proUnlockedCelebrated = false;
58770
- if (!isRecord$8(merged.ui.projectThreadSelections)) merged.ui.projectThreadSelections = {};
58771
- else merged.ui.projectThreadSelections = Object.fromEntries(Object.entries(merged.ui.projectThreadSelections).flatMap(([projectId, threadId]) => {
58772
- const normalizedProjectId = asString$10(projectId);
58773
- if (!normalizedProjectId) return [];
58774
- return [[normalizedProjectId, typeof threadId === "string" && threadId.trim().length > 0 ? threadId.trim() : null]];
58775
- }));
58776
- merged.ui.duplicateWarningDismissedKey = asString$10(merged.ui.duplicateWarningDismissedKey);
58777
- if (typeof merged.ui.pendingLicenseActivation !== "boolean") merged.ui.pendingLicenseActivation = false;
58778
- {
58779
- const allowedUiKeys = new Set(Object.keys(defaults.ui));
58780
- for (const key of Object.keys(merged.ui)) if (!allowedUiKeys.has(key)) delete merged.ui[key];
58781
- }
58782
- if (!isRecord$8(merged.profileDashboard)) merged.profileDashboard = clone(defaults.profileDashboard);
58783
- if (!isRecord$8(merged.profileDashboard.customGroupsByAccountKey)) merged.profileDashboard.customGroupsByAccountKey = {};
58784
- else merged.profileDashboard.customGroupsByAccountKey = Object.fromEntries(Object.entries(merged.profileDashboard.customGroupsByAccountKey).flatMap(([key, value]) => {
58785
- const normalizedKey = asString$10(key);
58786
- const normalizedValue = asString$10(value);
58787
- if (!normalizedKey || !normalizedValue) return [];
58788
- return [[normalizedKey, normalizedValue]];
58789
- }));
58790
- {
58791
- const allowedProfileDashboardKeys = new Set(Object.keys(defaults.profileDashboard));
58792
- for (const key of Object.keys(merged.profileDashboard)) if (!allowedProfileDashboardKeys.has(key)) delete merged.profileDashboard[key];
58793
- }
58794
- const legacyProjectSettingsByPath = isRecord$8(raw.projectSettingsByPath) ? raw.projectSettingsByPath : null;
58795
- if (!isRecord$8(merged.workspaceSettingsByPath)) merged.workspaceSettingsByPath = {};
58796
- if (legacyProjectSettingsByPath) merged.workspaceSettingsByPath = {
58797
- ...legacyProjectSettingsByPath,
58798
- ...merged.workspaceSettingsByPath
58799
- };
58800
- delete merged.projectSettingsByPath;
58801
- if (!isRecord$8(merged.conversationCategoriesByCwd)) merged.conversationCategoriesByCwd = {};
58802
- if (!isRecord$8(merged.conversationCategoryAssignmentsByCwd)) merged.conversationCategoryAssignmentsByCwd = {};
58803
- if (!isRecord$8(merged.git)) merged.git = clone(defaults.git);
58804
- merged.git.commitMessagePrompt = normalizeCommitMessagePrompt(merged.git.commitMessagePrompt) ?? DEFAULT_COMMIT_MESSAGE_PROMPT;
58805
- {
58806
- const allowedGitKeys = new Set(Object.keys(defaults.git));
58807
- for (const key of Object.keys(merged.git)) if (!allowedGitKeys.has(key)) delete merged.git[key];
58808
- }
58809
- if (!isRecord$8(merged.skills)) merged.skills = clone(defaults.skills);
58810
- if (!Array.isArray(merged.skills.sources)) merged.skills.sources = [];
58811
- if (!isRecord$8(merged.skills.installsBySlug)) merged.skills.installsBySlug = {};
58812
- if (!isRecord$8(merged.sync)) merged.sync = clone(defaults.sync);
58813
- merged.sync.lastPushAt = asString$10(merged.sync.lastPushAt);
58814
- merged.sync.lastPullAt = asString$10(merged.sync.lastPullAt);
58815
- merged.sync.lastError = asString$10(merged.sync.lastError);
58816
- merged.sync.remoteUpdatedAt = asString$10(merged.sync.remoteUpdatedAt);
58817
- if (!isRecord$8(merged.analytics)) merged.analytics = isRecord$8(merged.telemetry) ? clone(merged.telemetry) : clone(defaults.analytics);
58818
- merged.analytics.anonymousId = asString$10(merged.analytics.anonymousId);
58819
- if (!merged.analytics.anonymousId) {
58820
- const legacyInstallId = asString$10(merged.telemetry?.installId);
58821
- merged.analytics.anonymousId = legacyInstallId;
58822
- }
58823
- if (typeof merged.analytics.enabled !== "boolean") merged.analytics.enabled = true;
58824
- merged.analytics.lastFlushAt = asString$10(merged.analytics.lastFlushAt);
58825
- merged.analytics.lastError = asString$10(merged.analytics.lastError);
58826
- if ("telemetry" in merged) delete merged.telemetry;
58827
- if (!isRecord$8(merged.profilesByName)) merged.profilesByName = {};
58828
- if (!isRecord$8(merged.migration)) merged.migration = clone(defaults.migration);
58829
- if (![
58830
- "pending",
58831
- "pending_local_storage",
58832
- "complete"
58833
- ].includes(merged.migration.status)) merged.migration.status = "pending";
58834
- merged.migration.startedAt = asString$10(merged.migration.startedAt);
58835
- merged.migration.completedAt = asString$10(merged.migration.completedAt);
58836
- merged.migration.localStorageImportedAt = asString$10(merged.migration.localStorageImportedAt);
58837
- merged.migration.lastError = asString$10(merged.migration.lastError);
58838
- return merged;
58839
- }
58840
- function deepMerge(base, patch) {
58841
- if (!isRecord$8(base) || !isRecord$8(patch)) return clone(patch ?? base);
58842
- const next = { ...base };
58843
- for (const [key, patchValue] of Object.entries(patch)) {
58844
- if (patchValue === void 0) continue;
58845
- const currentValue = next[key];
58846
- if (Array.isArray(patchValue)) {
58847
- next[key] = clone(patchValue);
58848
- continue;
58849
- }
58850
- if (isRecord$8(currentValue) && isRecord$8(patchValue)) {
58851
- next[key] = deepMerge(currentValue, patchValue);
58852
- continue;
59695
+ {
59696
+ name: ORCHESTRATION_PROJECTOR_NAMES.threads,
59697
+ apply: applyThreadsProjection
58853
59698
  }
58854
- next[key] = clone(patchValue);
58855
- }
58856
- return next;
58857
- }
58858
- async function readLegacyAppStateFromDisk() {
58859
- const filePath = resolveLegacyAppStatePath();
58860
- try {
58861
- const raw = await promises.readFile(filePath, "utf8");
58862
- return normalizeAppState(JSON.parse(raw));
58863
- } catch (error) {
58864
- if (error.code === "ENOENT") return null;
58865
- throw error;
58866
- }
58867
- }
58868
- async function readAppStateFromStorage() {
58869
- return readDocument(resolveStorageDbPath(), APP_STATE_DOCUMENT, normalizeAppState);
58870
- }
58871
- async function writeAppStateToStorage(state) {
58872
- return writeDocument(resolveStorageDbPath(), APP_STATE_DOCUMENT, normalizeAppState(state));
58873
- }
58874
- async function ensureInitialized() {
58875
- if (appStateCache) return appStateCache;
58876
- appStateCache = await writeAppStateToStorage(await readAppStateFromStorage() ?? await readLegacyAppStateFromDisk() ?? normalizeAppState(null));
58877
- return clone(appStateCache);
58878
- }
58879
- async function withWriteLock(task) {
58880
- if (writeLockContext.getStore()) return task();
58881
- const previous = writeLock;
58882
- let release;
58883
- writeLock = new Promise((resolve) => {
58884
- release = resolve;
58885
- });
58886
- await previous;
58887
- try {
58888
- return await writeLockContext.run(true, task);
58889
- } finally {
58890
- if (release) release();
58891
- }
58892
- }
58893
- async function getAppState() {
58894
- return clone(await ensureInitialized());
58895
- }
58896
- async function updateAppState(transform, options = {}) {
58897
- const mode = options.mode ?? "patch";
58898
- const allowBeforeMigrationComplete = options.allowBeforeMigrationComplete === true;
58899
- return withWriteLock(async () => {
58900
- const nextState = await updateDocument({
58901
- dbPath: resolveStorageDbPath(),
58902
- namespace: APP_STATE_DOCUMENT,
58903
- normalize: normalizeAppState,
58904
- fallback: createDefaultAppState,
58905
- transform: (current) => {
58906
- if (!allowBeforeMigrationComplete && current.migration.status !== "complete") throw new Error("Storage migration is not complete yet.");
58907
- const transformed = transform(clone(current));
58908
- return mode === "replace" ? normalizeAppState(transformed) : normalizeAppState(deepMerge(current, transformed));
58909
- }
58910
- });
58911
- appStateCache = nextState;
58912
- return clone(nextState);
58913
- });
58914
- }
58915
- async function patchAppState(patch) {
58916
- return updateAppState(() => patch, {
58917
- mode: "patch",
58918
- allowBeforeMigrationComplete: false
59699
+ ];
59700
+ const runProjectorForEvent = (projector, event) => gen(function* () {
59701
+ const attachmentSideEffects = {
59702
+ deletedThreadIds: /* @__PURE__ */ new Set(),
59703
+ prunedThreadRelativePaths: /* @__PURE__ */ new Map()
59704
+ };
59705
+ yield* sql.withTransaction(projector.apply(event, attachmentSideEffects).pipe(flatMap$2(() => projectionStateRepository.upsert({
59706
+ projector: projector.name,
59707
+ lastAppliedSequence: event.sequence,
59708
+ updatedAt: event.occurredAt
59709
+ }))));
59710
+ yield* runAttachmentSideEffects(attachmentSideEffects).pipe(catch_((cause) => logWarning$1("failed to apply projected attachment side-effects", {
59711
+ projector: projector.name,
59712
+ sequence: event.sequence,
59713
+ eventType: event.type,
59714
+ cause
59715
+ })));
58919
59716
  });
58920
- }
59717
+ const bootstrapProjector = (projector) => projectionStateRepository.getByProjector({ projector: projector.name }).pipe(flatMap$2((stateRow) => runForEach(eventStore.readFromSequence(isSome(stateRow) ? stateRow.value.lastAppliedSequence : 0), (event) => runProjectorForEvent(projector, event))));
59718
+ const projectEvent = (event) => forEach$1(projectors, (projector) => runProjectorForEvent(projector, event), { concurrency: 1 }).pipe(provideService(FileSystem, fileSystem), provideService(Path$1, path), provideService(ServerConfig$1, serverConfig), asVoid, catchTag("SqlError", (sqlError) => fail$3(toPersistenceSqlError("ProjectionPipeline.projectEvent:query")(sqlError))));
59719
+ return {
59720
+ bootstrap: forEach$1(projectors, bootstrapProjector, { concurrency: 1 }).pipe(provideService(FileSystem, fileSystem), provideService(Path$1, path), provideService(ServerConfig$1, serverConfig), asVoid, tap(() => log$1("orchestration projection pipeline bootstrapped").pipe(annotateLogs({ projectors: projectors.length }))), catchTag("SqlError", (sqlError) => fail$3(toPersistenceSqlError("ProjectionPipeline.bootstrap:query")(sqlError)))),
59721
+ projectEvent
59722
+ };
59723
+ });
59724
+ const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeline, makeOrchestrationProjectionPipeline).pipe(provideMerge(layer$3), provideMerge(ProjectionProjectRepositoryLive), provideMerge(ProjectionThreadRepositoryLive), provideMerge(ProjectionThreadMessageRepositoryLive), provideMerge(ProjectionThreadProposedPlanRepositoryLive), provideMerge(ProjectionThreadActivityRepositoryLive), provideMerge(ProjectionThreadSessionRepositoryLive), provideMerge(ProjectionTurnRepositoryLive), provideMerge(ProjectionCheckpointRepositoryLive), provideMerge(ProjectionPendingApprovalRepositoryLive), provideMerge(ProjectionStateRepositoryLive));
58921
59725
  //#endregion
58922
59726
  //#region ../../packages/runtime-app-state/src/app/agentChatWorkspace.ts
58923
59727
  const AGENT_CHAT_WORKSPACE_DIRNAME = "agent-chat-workspace";
@@ -58999,7 +59803,7 @@ function asString$9(value) {
58999
59803
  const trimmed = value.trim();
59000
59804
  return trimmed.length > 0 ? trimmed : null;
59001
59805
  }
59002
- function isRecord$7(value) {
59806
+ function isRecord$6(value) {
59003
59807
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
59004
59808
  }
59005
59809
  function parseAutoRoll(raw) {
@@ -59011,7 +59815,7 @@ function parseAutoRoll(raw) {
59011
59815
  }
59012
59816
  }
59013
59817
  function parseStoredLicense(raw) {
59014
- if (!isRecord$7(raw)) return null;
59818
+ if (!isRecord$6(raw)) return null;
59015
59819
  const statusCandidate = asString$9(raw.status);
59016
59820
  const status = [
59017
59821
  "inactive",
@@ -59093,7 +59897,7 @@ async function readCodexSettingsJsonRaw() {
59093
59897
  };
59094
59898
  }
59095
59899
  async function writeCodexSettingsJsonRaw(payload) {
59096
- if (!isRecord$7(payload)) return;
59900
+ if (!isRecord$6(payload)) return;
59097
59901
  const autoRoll = parseAutoRoll(payload.autoRoll ?? payload.auto_roll);
59098
59902
  const license = parseStoredLicense(payload.license);
59099
59903
  await patchAppState({
@@ -59130,17 +59934,17 @@ async function writeCodexSettingsJsonRaw(payload) {
59130
59934
  folderHistory: Array.isArray(payload.folderHistory) ? payload.folderHistory : void 0,
59131
59935
  pinnedPaths: Array.isArray(payload.pinnedPaths) ? payload.pinnedPaths : void 0
59132
59936
  },
59133
- workspaceSettingsByPath: isRecord$7(payload.workspaceSettingsByPath) ? payload.workspaceSettingsByPath : isRecord$7(payload.projectSettingsByPath) ? payload.projectSettingsByPath : void 0,
59134
- conversationCategoriesByCwd: isRecord$7(payload.categoriesByCwd) ? payload.categoriesByCwd : void 0,
59135
- conversationCategoryAssignmentsByCwd: isRecord$7(payload.conversationCategoryByCwd) ? payload.conversationCategoryByCwd : void 0,
59136
- git: isRecord$7(payload.git) ? payload.git : void 0,
59137
- sync: isRecord$7(payload.sync) ? payload.sync : void 0
59937
+ workspaceSettingsByPath: isRecord$6(payload.workspaceSettingsByPath) ? payload.workspaceSettingsByPath : isRecord$6(payload.projectSettingsByPath) ? payload.projectSettingsByPath : void 0,
59938
+ conversationCategoriesByCwd: isRecord$6(payload.categoriesByCwd) ? payload.categoriesByCwd : void 0,
59939
+ conversationCategoryAssignmentsByCwd: isRecord$6(payload.conversationCategoryByCwd) ? payload.conversationCategoryByCwd : void 0,
59940
+ git: isRecord$6(payload.git) ? payload.git : void 0,
59941
+ sync: isRecord$6(payload.sync) ? payload.sync : void 0
59138
59942
  });
59139
59943
  }
59140
59944
  //#endregion
59141
59945
  //#region ../../packages/runtime-profiles/src/license/secret.ts
59142
59946
  const LICENSE_SECRET_DOCUMENT = "desktop.license-secret";
59143
- const LEGACY_LICENSE_SECRET_FILE$1 = "license.secret";
59947
+ const LEGACY_LICENSE_SECRET_FILE = "license.secret";
59144
59948
  async function generateSecret() {
59145
59949
  return crypto$1.randomBytes(32).toString("hex");
59146
59950
  }
@@ -59148,7 +59952,7 @@ function normalizeSecret(value) {
59148
59952
  return typeof value === "string" ? value.trim() : "";
59149
59953
  }
59150
59954
  async function readLegacyLicenseSecret() {
59151
- const legacyPath = nodePath.join(getUserDataDir(), LEGACY_LICENSE_SECRET_FILE$1);
59955
+ const legacyPath = nodePath.join(getUserDataDir(), LEGACY_LICENSE_SECRET_FILE);
59152
59956
  try {
59153
59957
  return normalizeSecret(await promises.readFile(legacyPath, "utf8"));
59154
59958
  } catch (error) {
@@ -59872,7 +60676,7 @@ function buildCodexCommand$1(binaryPath, args, env) {
59872
60676
  }
59873
60677
  //#endregion
59874
60678
  //#region ../../packages/runtime-codex/src/codex/home.ts
59875
- function resolveHomeDir$1() {
60679
+ function resolveHomeDir() {
59876
60680
  return process.env.HOME || process.env.USERPROFILE || nodeOs.homedir();
59877
60681
  }
59878
60682
  function expandHomePrefix(input, homeDir) {
@@ -59888,10 +60692,10 @@ function normalizePathCandidate(value) {
59888
60692
  function normalizeCodexHomePath(input) {
59889
60693
  const configured = normalizePathCandidate(input);
59890
60694
  if (!configured) return null;
59891
- return nodePath.resolve(expandHomePrefix(configured, resolveHomeDir$1()));
60695
+ return nodePath.resolve(expandHomePrefix(configured, resolveHomeDir()));
59892
60696
  }
59893
60697
  function resolveDefaultCodexHomeDir() {
59894
- return nodePath.join(resolveHomeDir$1(), ".codex");
60698
+ return nodePath.join(resolveHomeDir(), ".codex");
59895
60699
  }
59896
60700
  function resolveCodexHomeDir(options) {
59897
60701
  return normalizeCodexHomePath(options?.codexHomePath) ?? resolveDefaultCodexHomeDir();
@@ -59996,26 +60800,8 @@ function buildCliEnv(codexPath, overrides = {}) {
59996
60800
  return env;
59997
60801
  }
59998
60802
  //#endregion
59999
- //#region ../../packages/shared/src/core/logger.ts
60000
- const isTestEnv = process.env.NODE_ENV === "test" || process.env.VITEST === "true" || process.env.VITEST === "1";
60001
- function isMocked(fn) {
60002
- return Boolean(fn && typeof fn === "function" && "mock" in fn);
60003
- }
60004
- function logWarn(...args) {
60005
- if (isTestEnv && !isMocked(console.warn)) return;
60006
- console.warn(...args);
60007
- }
60008
- function logError(...args) {
60009
- if (isTestEnv && !isMocked(console.error)) return;
60010
- console.error(...args);
60011
- }
60012
- function logInfo(...args) {
60013
- if (isTestEnv && !isMocked(console.info)) return;
60014
- console.info(...args);
60015
- }
60016
- //#endregion
60017
60803
  //#region ../../packages/runtime-codex/src/codex/app-server.ts
60018
- function isRecord$6(value) {
60804
+ function isRecord$5(value) {
60019
60805
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
60020
60806
  }
60021
60807
  function asTrimmedString$2(value) {
@@ -60044,10 +60830,10 @@ function isInlineImageValue(value) {
60044
60830
  return normalized.startsWith("data:") || normalized.startsWith("http://") || normalized.startsWith("https://");
60045
60831
  }
60046
60832
  function normalizeSendUserMessageItem(value) {
60047
- if (!isRecord$6(value)) return null;
60833
+ if (!isRecord$5(value)) return null;
60048
60834
  const type = asString$8(value.type).trim();
60049
60835
  if (!type) return null;
60050
- const data = isRecord$6(value.data) ? value.data : {};
60836
+ const data = isRecord$5(value.data) ? value.data : {};
60051
60837
  if (type === "text") {
60052
60838
  const text = asString$8(data.text ?? value.text);
60053
60839
  if (!text.trim()) return null;
@@ -60082,7 +60868,7 @@ function normalizeTurnInputParams(params) {
60082
60868
  if (expectedTurnId && !asString$8(params.expectedTurnId).trim()) normalized.expectedTurnId = expectedTurnId;
60083
60869
  const turnId = asString$8(params.turnId ?? params.turn_id ?? expectedTurnId).trim();
60084
60870
  if (turnId && !asString$8(params.turnId).trim()) normalized.turnId = turnId;
60085
- const providedInput = Array.isArray(params.input) ? params.input.filter((entry) => isRecord$6(entry)) : [];
60871
+ const providedInput = Array.isArray(params.input) ? params.input.filter((entry) => isRecord$5(entry)) : [];
60086
60872
  if (providedInput.length > 0) {
60087
60873
  normalized.input = providedInput;
60088
60874
  return normalized;
@@ -60091,7 +60877,7 @@ function normalizeTurnInputParams(params) {
60091
60877
  if (providedItems.length > 0) {
60092
60878
  const input = providedItems.flatMap((item) => {
60093
60879
  const type = asString$8(item.type).trim();
60094
- const data = isRecord$6(item.data) ? item.data : item;
60880
+ const data = isRecord$5(item.data) ? item.data : item;
60095
60881
  if (type === "text") {
60096
60882
  const text = asString$8(data.text).trim();
60097
60883
  return text ? [{
@@ -60134,7 +60920,7 @@ function pickMethodKind(method, params) {
60134
60920
  const normalized = method.toLowerCase();
60135
60921
  if (normalized.includes("requestapproval")) return "approval";
60136
60922
  if (normalized.includes("requestuserinput")) return "user_input";
60137
- if (isRecord$6(params)) {
60923
+ if (isRecord$5(params)) {
60138
60924
  if ("file_changes" in params || "fileChanges" in params || "grant_root" in params || "grantRoot" in params) return "patch";
60139
60925
  if ("command" in params || "parsed_cmd" in params || "parsedCmd" in params || "cwd" in params) return "exec";
60140
60926
  }
@@ -60336,7 +61122,7 @@ var CodexAppServer = class extends EventEmitter {
60336
61122
  try {
60337
61123
  const response = await this.request("addConversationListener", listenerParams);
60338
61124
  this.addConversationListenerSupported = true;
60339
- return isRecord$6(response) ? response : null;
61125
+ return isRecord$5(response) ? response : null;
60340
61126
  } catch (error) {
60341
61127
  if (isMethodUnavailableError(error, "addConversationListener")) {
60342
61128
  this.addConversationListenerSupported = false;
@@ -60351,7 +61137,7 @@ var CodexAppServer = class extends EventEmitter {
60351
61137
  try {
60352
61138
  const response = await this.request("addConversationListener", listenerParams);
60353
61139
  this.addConversationListenerSupported = true;
60354
- return isRecord$6(response) ? response : null;
61140
+ return isRecord$5(response) ? response : null;
60355
61141
  } catch (resumeError) {
60356
61142
  if (isMethodUnavailableError(resumeError, "addConversationListener")) {
60357
61143
  this.addConversationListenerSupported = false;
@@ -60561,7 +61347,7 @@ var CodexAppServer = class extends EventEmitter {
60561
61347
  listPendingUserInputRequests() {
60562
61348
  return [...this.pendingServerRequests.values()].filter((request) => request.kind === "user_input").map((request) => {
60563
61349
  const workspaceId = asTrimmedString$2(request.params.workspace_id ?? request.params.workspaceId);
60564
- const params = isRecord$6(request.params.params) ? request.params.params : request.params;
61350
+ const params = isRecord$5(request.params.params) ? request.params.params : request.params;
60565
61351
  if (!workspaceId) return null;
60566
61352
  return {
60567
61353
  workspace_id: workspaceId,
@@ -60674,7 +61460,7 @@ var CodexAppServer = class extends EventEmitter {
60674
61460
  this.logParseFailure(line, parseError);
60675
61461
  return true;
60676
61462
  }
60677
- if (!isRecord$6(parsed)) {
61463
+ if (!isRecord$5(parsed)) {
60678
61464
  logWarn("[app-server] unexpected JSON message", parsed);
60679
61465
  return true;
60680
61466
  }
@@ -60763,9 +61549,9 @@ var CodexAppServer = class extends EventEmitter {
60763
61549
  id: request.id,
60764
61550
  kind,
60765
61551
  method: request.method,
60766
- params: isRecord$6(request.params) ? request.params : {}
61552
+ params: isRecord$5(request.params) ? request.params : {}
60767
61553
  });
60768
- const params = isRecord$6(request.params) ? request.params : {};
61554
+ const params = isRecord$5(request.params) ? request.params : {};
60769
61555
  if (kind === "exec") this.emit("codex:exec-command-request", {
60770
61556
  requestToken: token,
60771
61557
  params
@@ -66784,12 +67570,12 @@ function decodeProviderKind(providerName, operation) {
66784
67570
  detail: `Unknown persisted provider '${providerName}'.`
66785
67571
  }));
66786
67572
  }
66787
- function isRecord$5(value) {
67573
+ function isRecord$4(value) {
66788
67574
  return value !== null && typeof value === "object" && !Array.isArray(value);
66789
67575
  }
66790
67576
  function mergeRuntimePayload(existing, next) {
66791
67577
  if (next === void 0) return existing ?? null;
66792
- if (isRecord$5(existing) && isRecord$5(next)) return {
67578
+ if (isRecord$4(existing) && isRecord$4(next)) return {
66793
67579
  ...existing,
66794
67580
  ...next
66795
67581
  };
@@ -72807,7 +73593,7 @@ const FALLBACK_FEATURE_KEYS = [
72807
73593
  ];
72808
73594
  let metadataCache = null;
72809
73595
  let metadataCacheAt = 0;
72810
- function isRecord$4(value) {
73596
+ function isRecord$3(value) {
72811
73597
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
72812
73598
  }
72813
73599
  function uniqueSorted(values) {
@@ -72878,14 +73664,14 @@ function parseFeatureCatalog(output) {
72878
73664
  }
72879
73665
  function parseSchemaKeys(schemaRaw) {
72880
73666
  const parsed = JSON.parse(schemaRaw);
72881
- if (!isRecord$4(parsed)) return {
73667
+ if (!isRecord$3(parsed)) return {
72882
73668
  topLevelKeys: FALLBACK_SCHEMA_TOP_LEVEL_KEYS,
72883
73669
  featureKeys: FALLBACK_FEATURE_KEYS
72884
73670
  };
72885
- const properties = isRecord$4(parsed.properties) ? parsed.properties : {};
73671
+ const properties = isRecord$3(parsed.properties) ? parsed.properties : {};
72886
73672
  const topLevelKeys = uniqueSorted(Object.keys(properties));
72887
- const features = isRecord$4(properties.features) ? properties.features : {};
72888
- const featureProperties = isRecord$4(features.properties) ? features.properties : {};
73673
+ const features = isRecord$3(properties.features) ? properties.features : {};
73674
+ const featureProperties = isRecord$3(features.properties) ? features.properties : {};
72889
73675
  const featureKeys = uniqueSorted(Object.keys(featureProperties));
72890
73676
  return {
72891
73677
  topLevelKeys: topLevelKeys.length > 0 ? topLevelKeys : FALLBACK_SCHEMA_TOP_LEVEL_KEYS,
@@ -73636,7 +74422,7 @@ const ACTIVATION_PROMPT = "Reply with exactly: ok.";
73636
74422
  const ACTIVATION_MODEL = "gpt-5.1-codex-mini";
73637
74423
  const MAX_STDERR_CAPTURE_CHARS = 32768;
73638
74424
  const REFRESH_TOKEN_REDEEMED_SNIPPET$1 = "refresh token was already used";
73639
- function isRecord$3(value) {
74425
+ function isRecord$2(value) {
73640
74426
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
73641
74427
  }
73642
74428
  function asString$3(value) {
@@ -73709,35 +74495,35 @@ function createRpcMessageReader(rl) {
73709
74495
  };
73710
74496
  }
73711
74497
  function readThreadIdFromResult(result) {
73712
- if (!isRecord$3(result)) return null;
73713
- const value = asString$3((isRecord$3(result.thread) ? result.thread : {}).id ?? result.threadId).trim();
74498
+ if (!isRecord$2(result)) return null;
74499
+ const value = asString$3((isRecord$2(result.thread) ? result.thread : {}).id ?? result.threadId).trim();
73714
74500
  return value.length > 0 ? value : null;
73715
74501
  }
73716
74502
  function readTurnIdFromResult(result) {
73717
- if (!isRecord$3(result)) return null;
73718
- const value = asString$3((isRecord$3(result.turn) ? result.turn : {}).id ?? result.turnId).trim();
74503
+ if (!isRecord$2(result)) return null;
74504
+ const value = asString$3((isRecord$2(result.turn) ? result.turn : {}).id ?? result.turnId).trim();
73719
74505
  return value.length > 0 ? value : null;
73720
74506
  }
73721
74507
  function readTurnIdFromNotification(message) {
73722
- if (!isRecord$3(message.params)) return null;
73723
- const value = asString$3((isRecord$3(message.params.turn) ? message.params.turn : {}).id ?? message.params.turnId).trim();
74508
+ if (!isRecord$2(message.params)) return null;
74509
+ const value = asString$3((isRecord$2(message.params.turn) ? message.params.turn : {}).id ?? message.params.turnId).trim();
73724
74510
  return value.length > 0 ? value : null;
73725
74511
  }
73726
74512
  function readTurnStatusFromNotification(message) {
73727
- if (!isRecord$3(message.params)) return {
74513
+ if (!isRecord$2(message.params)) return {
73728
74514
  status: null,
73729
74515
  reason: null
73730
74516
  };
73731
- const turn = isRecord$3(message.params.turn) ? message.params.turn : {};
73732
- const error = isRecord$3(turn.error) ? turn.error : null;
74517
+ const turn = isRecord$2(message.params.turn) ? message.params.turn : {};
74518
+ const error = isRecord$2(turn.error) ? turn.error : null;
73733
74519
  return {
73734
74520
  status: asString$3(turn.status).trim() || null,
73735
74521
  reason: error ? asString$3(error.message).trim() || null : null
73736
74522
  };
73737
74523
  }
73738
74524
  function readLegacyEventTurnId(message) {
73739
- if (!isRecord$3(message.params)) return null;
73740
- const msg = isRecord$3(message.params.msg) ? message.params.msg : {};
74525
+ if (!isRecord$2(message.params)) return null;
74526
+ const msg = isRecord$2(message.params.msg) ? message.params.msg : {};
73741
74527
  const value = asString$3(message.params.id ?? msg.turn_id ?? msg.turnId).trim();
73742
74528
  return value.length > 0 ? value : null;
73743
74529
  }
@@ -76259,7 +77045,7 @@ var AccountPoolTurnFailure = class extends Error {
76259
77045
  this.providerThreadId = input.providerThreadId;
76260
77046
  }
76261
77047
  };
76262
- function isRecord$2(value) {
77048
+ function isRecord$1(value) {
76263
77049
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
76264
77050
  }
76265
77051
  function asString$2(value) {
@@ -76393,7 +77179,7 @@ function createDefaultStore() {
76393
77179
  };
76394
77180
  }
76395
77181
  function normalizeApiKeyRecord(id, value) {
76396
- const record = isRecord$2(value) ? value : null;
77182
+ const record = isRecord$1(value) ? value : null;
76397
77183
  const tokenHash = asString$2(record?.tokenHash);
76398
77184
  const tokenPreview = asString$2(record?.tokenPreview);
76399
77185
  const createdAt = normalizeIsoString(record?.createdAt);
@@ -76408,7 +77194,7 @@ function normalizeApiKeyRecord(id, value) {
76408
77194
  };
76409
77195
  }
76410
77196
  function normalizeLegacySessionRecord(id, value) {
76411
- const record = isRecord$2(value) ? value : null;
77197
+ const record = isRecord$1(value) ? value : null;
76412
77198
  const profileName = asString$2(record?.profileName);
76413
77199
  const threadId = asString$2(record?.threadId);
76414
77200
  const createdAt = normalizeIsoString(record?.createdAt);
@@ -76432,19 +77218,19 @@ function normalizeLegacySessionRecord(id, value) {
76432
77218
  };
76433
77219
  }
76434
77220
  function normalizeLegacyStore(value) {
76435
- const record = isRecord$2(value) ? value : null;
77221
+ const record = isRecord$1(value) ? value : null;
76436
77222
  const apiKeysById = {};
76437
- for (const [id, keyValue] of Object.entries(isRecord$2(record?.apiKeysById) ? record.apiKeysById : {})) {
77223
+ for (const [id, keyValue] of Object.entries(isRecord$1(record?.apiKeysById) ? record.apiKeysById : {})) {
76438
77224
  const normalized = normalizeApiKeyRecord(id, keyValue);
76439
77225
  if (normalized) apiKeysById[id] = normalized;
76440
77226
  }
76441
77227
  const sessionsById = {};
76442
- for (const [id, sessionValue] of Object.entries(isRecord$2(record?.sessionsById) ? record.sessionsById : {})) {
77228
+ for (const [id, sessionValue] of Object.entries(isRecord$1(record?.sessionsById) ? record.sessionsById : {})) {
76443
77229
  const normalized = normalizeLegacySessionRecord(id, sessionValue);
76444
77230
  if (normalized) sessionsById[id] = normalized;
76445
77231
  }
76446
77232
  const responseIndex = {};
76447
- for (const [responseId, sessionId] of Object.entries(isRecord$2(record?.responseIndex) ? record.responseIndex : {})) {
77233
+ for (const [responseId, sessionId] of Object.entries(isRecord$1(record?.responseIndex) ? record.responseIndex : {})) {
76448
77234
  const normalizedSessionId = asString$2(sessionId);
76449
77235
  if (normalizedSessionId) responseIndex[responseId] = normalizedSessionId;
76450
77236
  }
@@ -76457,7 +77243,7 @@ function normalizeLegacyStore(value) {
76457
77243
  };
76458
77244
  }
76459
77245
  function normalizeTranscriptEntry(value) {
76460
- const record = isRecord$2(value) ? value : null;
77246
+ const record = isRecord$1(value) ? value : null;
76461
77247
  const role = asString$2(record?.role);
76462
77248
  const createdAt = normalizeIsoString(record?.createdAt);
76463
77249
  if (role !== "user" && role !== "assistant" || !createdAt) return null;
@@ -76469,7 +77255,7 @@ function normalizeTranscriptEntry(value) {
76469
77255
  };
76470
77256
  }
76471
77257
  function normalizeSessionRecord(id, value) {
76472
- const record = isRecord$2(value) ? value : null;
77258
+ const record = isRecord$1(value) ? value : null;
76473
77259
  const activeSegmentId = asString$2(record?.activeSegmentId);
76474
77260
  const createdAt = normalizeIsoString(record?.createdAt);
76475
77261
  const lastUsedAt = normalizeIsoString(record?.lastUsedAt);
@@ -76502,11 +77288,11 @@ function normalizeSessionRecord(id, value) {
76502
77288
  responseIds: normalizeStringArray(record?.responseIds).slice(0, MAX_RESPONSE_IDS_PER_SESSION),
76503
77289
  rolloverCount: asNumber$1(record?.rolloverCount) ?? 0,
76504
77290
  lastRolloverReason: asString$2(record?.lastRolloverReason),
76505
- transcript: transcript.slice(-MAX_TRANSCRIPT_ENTRIES_PER_SESSION)
77291
+ transcript: transcript.slice(-64)
76506
77292
  };
76507
77293
  }
76508
77294
  function normalizeSegmentRecord(id, value) {
76509
- const record = isRecord$2(value) ? value : null;
77295
+ const record = isRecord$1(value) ? value : null;
76510
77296
  const sessionId = asString$2(record?.sessionId);
76511
77297
  const profileName = asString$2(record?.profileName);
76512
77298
  const threadId = asString$2(record?.threadId);
@@ -76527,7 +77313,7 @@ function normalizeSegmentRecord(id, value) {
76527
77313
  };
76528
77314
  }
76529
77315
  function normalizeProfileStateRecord(value) {
76530
- const record = isRecord$2(value) ? value : null;
77316
+ const record = isRecord$1(value) ? value : null;
76531
77317
  return {
76532
77318
  cooldownUntil: normalizeIsoString(record?.cooldownUntil),
76533
77319
  lastFailureClass: normalizeFailureClass(record?.lastFailureClass),
@@ -76536,7 +77322,7 @@ function normalizeProfileStateRecord(value) {
76536
77322
  };
76537
77323
  }
76538
77324
  function normalizeResponseIndexRecord(value) {
76539
- const record = isRecord$2(value) ? value : null;
77325
+ const record = isRecord$1(value) ? value : null;
76540
77326
  const sessionId = asString$2(record?.sessionId);
76541
77327
  const segmentId = asString$2(record?.segmentId);
76542
77328
  const createdAt = normalizeIsoString(record?.createdAt) ?? (/* @__PURE__ */ new Date(0)).toISOString();
@@ -76548,30 +77334,30 @@ function normalizeResponseIndexRecord(value) {
76548
77334
  };
76549
77335
  }
76550
77336
  function normalizeStore(value) {
76551
- const record = isRecord$2(value) ? value : null;
77337
+ const record = isRecord$1(value) ? value : null;
76552
77338
  const apiKeysById = {};
76553
- for (const [id, keyValue] of Object.entries(isRecord$2(record?.apiKeysById) ? record.apiKeysById : {})) {
77339
+ for (const [id, keyValue] of Object.entries(isRecord$1(record?.apiKeysById) ? record.apiKeysById : {})) {
76554
77340
  const normalized = normalizeApiKeyRecord(id, keyValue);
76555
77341
  if (normalized) apiKeysById[id] = normalized;
76556
77342
  }
76557
77343
  const sessionsById = {};
76558
- for (const [id, sessionValue] of Object.entries(isRecord$2(record?.sessionsById) ? record.sessionsById : {})) {
77344
+ for (const [id, sessionValue] of Object.entries(isRecord$1(record?.sessionsById) ? record.sessionsById : {})) {
76559
77345
  const normalized = normalizeSessionRecord(id, sessionValue);
76560
77346
  if (normalized) sessionsById[id] = normalized;
76561
77347
  }
76562
77348
  const segmentsById = {};
76563
- for (const [id, segmentValue] of Object.entries(isRecord$2(record?.segmentsById) ? record.segmentsById : {})) {
77349
+ for (const [id, segmentValue] of Object.entries(isRecord$1(record?.segmentsById) ? record.segmentsById : {})) {
76564
77350
  const normalized = normalizeSegmentRecord(id, segmentValue);
76565
77351
  if (normalized) segmentsById[id] = normalized;
76566
77352
  }
76567
77353
  const profilesByName = {};
76568
- for (const [name, profileValue] of Object.entries(isRecord$2(record?.profilesByName) ? record.profilesByName : {})) {
77354
+ for (const [name, profileValue] of Object.entries(isRecord$1(record?.profilesByName) ? record.profilesByName : {})) {
76569
77355
  const normalizedName = asString$2(name);
76570
77356
  if (!normalizedName) continue;
76571
77357
  profilesByName[normalizedName] = normalizeProfileStateRecord(profileValue);
76572
77358
  }
76573
77359
  const responseIndex = {};
76574
- for (const [responseId, responseValue] of Object.entries(isRecord$2(record?.responseIndex) ? record.responseIndex : {})) {
77360
+ for (const [responseId, responseValue] of Object.entries(isRecord$1(record?.responseIndex) ? record.responseIndex : {})) {
76575
77361
  const normalized = normalizeResponseIndexRecord(responseValue);
76576
77362
  if (normalized) responseIndex[responseId] = normalized;
76577
77363
  }
@@ -76696,7 +77482,7 @@ function extractTextAndImages(value) {
76696
77482
  text: value.trim() || null,
76697
77483
  images: []
76698
77484
  };
76699
- const record = isRecord$2(value) ? value : null;
77485
+ const record = isRecord$1(value) ? value : null;
76700
77486
  const arrayValue = Array.isArray(value) ? value : Array.isArray(record?.content) ? record?.content : null;
76701
77487
  const directText = asString$2(record?.text) ?? asString$2(record?.content);
76702
77488
  const directImage = asString$2(record?.image_url) ?? asString$2(record?.url) ?? asString$2(record?.imageUrl);
@@ -76711,7 +77497,7 @@ function extractTextAndImages(value) {
76711
77497
  if (entry.trim().length > 0) texts.push(entry.trim());
76712
77498
  continue;
76713
77499
  }
76714
- const part = isRecord$2(entry) ? entry : null;
77500
+ const part = isRecord$1(entry) ? entry : null;
76715
77501
  if (!part) continue;
76716
77502
  const partType = asString$2(part.type) ?? "text";
76717
77503
  const text = asString$2(part.text) ?? asString$2(part.content) ?? asString$2(part.value);
@@ -76732,7 +77518,7 @@ function assistantLabel(value) {
76732
77518
  return normalized && normalized.length > 0 ? normalized : null;
76733
77519
  }
76734
77520
  function isAssistantLikeRecord(value) {
76735
- const record = isRecord$2(value) ? value : null;
77521
+ const record = isRecord$1(value) ? value : null;
76736
77522
  if (!record) return false;
76737
77523
  return [
76738
77524
  assistantLabel(record.role),
@@ -76745,7 +77531,7 @@ function collectTextFragments(value, depth = 0) {
76745
77531
  if (depth > 6) return [];
76746
77532
  if (typeof value === "string") return value.length > 0 ? [value] : [];
76747
77533
  if (Array.isArray(value)) return value.flatMap((entry) => collectTextFragments(entry, depth + 1));
76748
- const record = isRecord$2(value) ? value : null;
77534
+ const record = isRecord$1(value) ? value : null;
76749
77535
  if (!record) return [];
76750
77536
  return [
76751
77537
  asString$2(record.text),
@@ -76774,7 +77560,7 @@ function extractAssistantTextSnapshot(value, depth = 0) {
76774
77560
  }
76775
77561
  return null;
76776
77562
  }
76777
- const record = isRecord$2(value) ? value : null;
77563
+ const record = isRecord$1(value) ? value : null;
76778
77564
  if (!record) return null;
76779
77565
  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);
76780
77566
  if (nestedMatch) return nestedMatch;
@@ -76793,7 +77579,7 @@ function prepareTurnInput(body, fallbackModel) {
76793
77579
  looseText = [looseText, entry.trim()].filter(Boolean).join("\n\n") || null;
76794
77580
  continue;
76795
77581
  }
76796
- const record = isRecord$2(entry) ? entry : null;
77582
+ const record = isRecord$1(entry) ? entry : null;
76797
77583
  if (!record) continue;
76798
77584
  const entryRole = asString$2(record.role);
76799
77585
  const entryType = asString$2(record.type);
@@ -76810,7 +77596,7 @@ function prepareTurnInput(body, fallbackModel) {
76810
77596
  if (text) looseText = [looseText, text].filter(Boolean).join("\n\n") || null;
76811
77597
  looseImages.push(...images);
76812
77598
  }
76813
- else if (isRecord$2(input)) {
77599
+ else if (isRecord$1(input)) {
76814
77600
  const { text, images } = extractTextAndImages(input);
76815
77601
  looseText = text;
76816
77602
  looseImages.push(...images);
@@ -76839,7 +77625,7 @@ function prepareTurnInput(body, fallbackModel) {
76839
77625
  if (transcriptParts.length > 0) promptParts.push(`Conversation so far:\n${transcriptParts.join("\n\n")}`);
76840
77626
  if (finalPrompt) promptParts.push(finalPrompt);
76841
77627
  const normalizedModel = normalizeModelSlug(asString$2(body.model) ?? fallbackModel, "codex") ?? fallbackModel;
76842
- const effort = asString$2((isRecord$2(body.reasoning) ? body.reasoning : null)?.effort) ?? asString$2(body.effort) ?? void 0;
77628
+ const effort = asString$2((isRecord$1(body.reasoning) ? body.reasoning : null)?.effort) ?? asString$2(body.effort) ?? void 0;
76843
77629
  return {
76844
77630
  prompt: promptParts.join("\n\n").trim() || null,
76845
77631
  attachments: [...looseImages, ...finalUserImages].map((url) => ({
@@ -76856,7 +77642,7 @@ function prepareTurnInput(body, fallbackModel) {
76856
77642
  }
76857
77643
  function resolveResponseContinuationKey(body, headers) {
76858
77644
  const previousResponseId = asString$2(body.previous_response_id);
76859
- const conversation = asString$2(body.conversation) ?? (isRecord$2(body.conversation) ? asString$2(body.conversation.id) : null);
77645
+ const conversation = asString$2(body.conversation) ?? (isRecord$1(body.conversation) ? asString$2(body.conversation.id) : null);
76860
77646
  if (conversation && previousResponseId) throw new AccountPoolRequestError({
76861
77647
  statusCode: 400,
76862
77648
  code: "invalid_request_error",
@@ -76935,7 +77721,7 @@ async function readJsonRequestBody(req) {
76935
77721
  const raw = Buffer.concat(chunks).toString("utf8").trim();
76936
77722
  if (!raw) return {};
76937
77723
  const parsed = JSON.parse(raw);
76938
- if (!isRecord$2(parsed)) throw new Error("Expected a JSON object request body.");
77724
+ if (!isRecord$1(parsed)) throw new Error("Expected a JSON object request body.");
76939
77725
  return parsed;
76940
77726
  }
76941
77727
  function stringifyFailureReason(failureClass, message) {
@@ -78112,7 +78898,7 @@ var LocalAccountPool = class LocalAccountPool {
78112
78898
  images: [],
78113
78899
  createdAt: now
78114
78900
  });
78115
- if (session.transcript.length > MAX_TRANSCRIPT_ENTRIES_PER_SESSION) session.transcript = session.transcript.slice(-MAX_TRANSCRIPT_ENTRIES_PER_SESSION);
78901
+ if (session.transcript.length > MAX_TRANSCRIPT_ENTRIES_PER_SESSION) session.transcript = session.transcript.slice(-64);
78116
78902
  segment.lastUsedAt = now;
78117
78903
  segment.closedAt = null;
78118
78904
  segment.closeReason = null;
@@ -78317,17 +79103,17 @@ var LocalAccountPool = class LocalAccountPool {
78317
79103
  if (snapshotText) this.applyObserverTextSnapshot(observer, snapshotText);
78318
79104
  }
78319
79105
  if (event.method === "turn/completed") {
78320
- const payload = isRecord$2(event.payload) ? event.payload : null;
78321
- const turn = isRecord$2(payload?.turn) ? payload?.turn : payload;
79106
+ const payload = isRecord$1(event.payload) ? event.payload : null;
79107
+ const turn = isRecord$1(payload?.turn) ? payload?.turn : payload;
78322
79108
  const turnStatus = asString$2(turn?.status);
78323
- const errorMessage = asString$2(isRecord$2(turn?.error) ? turn.error.message : void 0) ?? asString$2(payload?.message);
79109
+ const errorMessage = asString$2(isRecord$1(turn?.error) ? turn.error.message : void 0) ?? asString$2(payload?.message);
78324
79110
  if (turnStatus === "failed" || errorMessage) {
78325
79111
  observer.done = true;
78326
79112
  observer.reject(new Error(errorMessage ?? "Provider turn failed."));
78327
79113
  this.turnObservers.delete(event.threadId);
78328
79114
  return;
78329
79115
  }
78330
- const usage = isRecord$2(turn?.usage) ? turn?.usage : void 0;
79116
+ const usage = isRecord$1(turn?.usage) ? turn?.usage : void 0;
78331
79117
  const snapshotText = observer.text.length > 0 ? null : extractAssistantTextSnapshot(event.payload);
78332
79118
  if (snapshotText) this.applyObserverTextSnapshot(observer, snapshotText);
78333
79119
  observer.usage = usage;
@@ -78369,15 +79155,15 @@ var LocalAccountPool = class LocalAccountPool {
78369
79155
  else observer.pendingDeltas.push(snapshotText);
78370
79156
  }
78371
79157
  extractEventErrorMessage(payload) {
78372
- if (!isRecord$2(payload)) return null;
78373
- return asString$2((isRecord$2(payload.error) ? payload.error : payload).message) ?? null;
79158
+ if (!isRecord$1(payload)) return null;
79159
+ return asString$2((isRecord$1(payload.error) ? payload.error : payload).message) ?? null;
78374
79160
  }
78375
79161
  readLiveProviderThreadId(threadId) {
78376
79162
  const active = this.manager.listSessions().find((session) => session.threadId === ThreadId.makeUnsafe(threadId));
78377
79163
  return this.readResumeCursorThreadId(active?.resumeCursor);
78378
79164
  }
78379
79165
  readResumeCursorThreadId(resumeCursor) {
78380
- if (!isRecord$2(resumeCursor)) return null;
79166
+ if (!isRecord$1(resumeCursor)) return null;
78381
79167
  return asString$2(resumeCursor.threadId);
78382
79168
  }
78383
79169
  async closeLiveSegment(segmentId) {
@@ -79311,250 +80097,6 @@ async function updateGlobalCliNow() {
79311
80097
  };
79312
80098
  }
79313
80099
  //#endregion
79314
- //#region ../../packages/contracts/src/settings/legacy-localstorage-keys.ts
79315
- const LEGACY_LOCALSTORAGE_KEYS = [
79316
- "settings-storage",
79317
- "provider",
79318
- "sandbox-storage",
79319
- "project-settings-storage",
79320
- "folder-storage",
79321
- "conversation-categories-storage",
79322
- "codex:auto-roll-settings"
79323
- ];
79324
- //#endregion
79325
- //#region ../../packages/runtime-app-state/src/storage/migrations/v1.ts
79326
- const SQLITE_STORAGE_DIR = ".f86eb5e712267207";
79327
- const LEGACY_SETTINGS_FILE = "settings.json";
79328
- const LEGACY_SETTINGS_BACKUP_FILE = "settings.json.bak";
79329
- const LEGACY_SYNC_STATE_FILE = "sync-state.json";
79330
- const LEGACY_APP_SETTINGS_PARITY_FILE = "app-settings-parity.json";
79331
- const LEGACY_PROFILE_HOMES_DIR = "profile-homes";
79332
- const LEGACY_SKILLS_DIR = "skills";
79333
- const LEGACY_SKILLS_REPOS_FILE = "repos.json";
79334
- const LEGACY_SKILL_MANIFEST = ".codexuse-skill.json";
79335
- const LEGACY_LICENSE_SECRET_FILE = "license.secret";
79336
- function isRecord$1(value) {
79337
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
79338
- }
79339
- function isMissingPathError(error) {
79340
- return error.code === "ENOENT";
79341
- }
79342
- function resolveHomeDir() {
79343
- const home = process.env.HOME || process.env.USERPROFILE || nodeOs.homedir();
79344
- if (!home) throw new Error("HOME is not set.");
79345
- return home;
79346
- }
79347
- function resolveCodexDir() {
79348
- return nodePath.join(resolveHomeDir(), ".codex");
79349
- }
79350
- function resolveLegacyPath(...segments) {
79351
- return nodePath.join(resolveCodexDir(), ...segments);
79352
- }
79353
- function pickAutoRoll(raw) {
79354
- if (!raw) return null;
79355
- try {
79356
- return normalizeAutoRollSettings(raw);
79357
- } catch {
79358
- return null;
79359
- }
79360
- }
79361
- function mergeLegacyLocalStoragePatch(payload) {
79362
- const patch = {};
79363
- const consumedKeys = /* @__PURE__ */ new Set();
79364
- const skippedKeys = /* @__PURE__ */ new Set();
79365
- const legacyPayloadKeys = new Set(Object.keys(payload).filter((key) => LEGACY_LOCALSTORAGE_KEYS.includes(key)));
79366
- const hasKey = (key) => legacyPayloadKeys.has(key);
79367
- const markSkippedIfPresent = (key, consumed) => {
79368
- if (!hasKey(key)) return;
79369
- if (consumed) consumedKeys.add(key);
79370
- else skippedKeys.add(key);
79371
- };
79372
- const settingsStorage = payload["settings-storage"];
79373
- if (isRecord$1(settingsStorage)) {
79374
- const nextExcludeFolders = Array.isArray(settingsStorage.excludeFolders) ? settingsStorage.excludeFolders.filter((item) => typeof item === "string") : void 0;
79375
- const nextBeep = typeof settingsStorage.enableTaskCompleteBeep === "boolean" ? settingsStorage.enableTaskCompleteBeep : void 0;
79376
- const nextSleep = typeof settingsStorage.preventSleepDuringTasks === "boolean" ? settingsStorage.preventSleepDuringTasks : void 0;
79377
- patch.preferences = {
79378
- excludeFolders: nextExcludeFolders,
79379
- enableTaskCompleteBeep: nextBeep,
79380
- preventSleepDuringTasks: nextSleep
79381
- };
79382
- markSkippedIfPresent("settings-storage", nextExcludeFolders !== void 0 || nextBeep !== void 0 || nextSleep !== void 0);
79383
- } else markSkippedIfPresent("settings-storage", false);
79384
- markSkippedIfPresent("provider", hasKey("provider"));
79385
- markSkippedIfPresent("sandbox-storage", hasKey("sandbox-storage"));
79386
- const projectSettings = payload["project-settings-storage"];
79387
- if (isRecord$1(projectSettings) && isRecord$1(projectSettings.settingsByPath)) {
79388
- patch.workspaceSettingsByPath = projectSettings.settingsByPath;
79389
- markSkippedIfPresent("project-settings-storage", true);
79390
- } else markSkippedIfPresent("project-settings-storage", false);
79391
- const folder = payload["folder-storage"];
79392
- if (isRecord$1(folder)) {
79393
- const folderHistory = Array.isArray(folder.folderHistory) ? folder.folderHistory.filter(isRecord$1) : void 0;
79394
- const pinnedPaths = Array.isArray(folder.pinnedPaths) ? folder.pinnedPaths.filter((item) => typeof item === "string") : void 0;
79395
- patch.preferences = {
79396
- ...patch.preferences ?? {},
79397
- folderHistory,
79398
- pinnedPaths
79399
- };
79400
- markSkippedIfPresent("folder-storage", folderHistory !== void 0 || pinnedPaths !== void 0);
79401
- } else markSkippedIfPresent("folder-storage", false);
79402
- const categories = payload["conversation-categories-storage"];
79403
- let consumedCategories = false;
79404
- if (isRecord$1(categories)) {
79405
- if (isRecord$1(categories.categoriesByCwd)) {
79406
- patch.conversationCategoriesByCwd = categories.categoriesByCwd;
79407
- consumedCategories = true;
79408
- }
79409
- if (isRecord$1(categories.conversationCategoryByCwd)) {
79410
- patch.conversationCategoryAssignmentsByCwd = categories.conversationCategoryByCwd;
79411
- consumedCategories = true;
79412
- }
79413
- }
79414
- markSkippedIfPresent("conversation-categories-storage", consumedCategories);
79415
- const legacyAutoRoll = payload["codex:auto-roll-settings"];
79416
- const autoRoll = pickAutoRoll(legacyAutoRoll);
79417
- if (autoRoll) {
79418
- patch.autoRoll = {
79419
- enabled: autoRoll.enabled,
79420
- rearmRemainingThreshold: autoRoll.rearmRemainingThreshold,
79421
- switchRemainingThreshold: autoRoll.switchRemainingThreshold,
79422
- restartOfficialCodexOnAutoRoll: autoRoll.restartOfficialCodexOnAutoRoll,
79423
- launchOfficialCodexWhenClosedOnAutoRoll: autoRoll.launchOfficialCodexWhenClosedOnAutoRoll,
79424
- priorityOrder: autoRoll.priorityOrder,
79425
- lowRemainingNotificationEnabled: autoRoll.lowRemainingNotificationEnabled,
79426
- lowRemainingNotificationThreshold: autoRoll.lowRemainingNotificationThreshold
79427
- };
79428
- markSkippedIfPresent("codex:auto-roll-settings", true);
79429
- } else markSkippedIfPresent("codex:auto-roll-settings", false);
79430
- return {
79431
- patch,
79432
- consumedKeys: Array.from(consumedKeys),
79433
- skippedKeys: Array.from(skippedKeys)
79434
- };
79435
- }
79436
- async function removeIfExists(target) {
79437
- await promises.rm(target, {
79438
- recursive: true,
79439
- force: true
79440
- });
79441
- }
79442
- async function cleanupLegacyCanonicalSources() {
79443
- const homeDir = resolveHomeDir();
79444
- await removeIfExists(resolveLegacyAppStatePath());
79445
- await removeIfExists(nodePath.join(getUserDataDir(), LEGACY_APP_SETTINGS_PARITY_FILE));
79446
- await removeIfExists(nodePath.join(homeDir, SQLITE_STORAGE_DIR));
79447
- await removeIfExists(resolveLegacyPath(LEGACY_SETTINGS_FILE));
79448
- await removeIfExists(resolveLegacyPath(LEGACY_SETTINGS_BACKUP_FILE));
79449
- await removeIfExists(resolveLegacyPath(LEGACY_SYNC_STATE_FILE));
79450
- await removeIfExists(resolveLegacyPath(LEGACY_LICENSE_SECRET_FILE));
79451
- await removeIfExists(resolveLegacyPath(LEGACY_SKILLS_DIR, LEGACY_SKILLS_REPOS_FILE));
79452
- const profileHomesRoot = resolveLegacyPath(LEGACY_PROFILE_HOMES_DIR);
79453
- try {
79454
- const profileHomes = await promises.readdir(profileHomesRoot, { withFileTypes: true });
79455
- for (const profileHome of profileHomes) {
79456
- if (!profileHome.isDirectory()) continue;
79457
- const profileDir = nodePath.join(profileHomesRoot, profileHome.name);
79458
- let files = [];
79459
- try {
79460
- files = await promises.readdir(profileDir);
79461
- } catch {
79462
- continue;
79463
- }
79464
- for (const file of files) {
79465
- if (!file.startsWith("profile.json")) continue;
79466
- await removeIfExists(nodePath.join(profileDir, file));
79467
- }
79468
- }
79469
- } catch (error) {
79470
- if (!isMissingPathError(error)) logWarn("Failed cleaning legacy profile metadata:", {
79471
- profileHomesRoot,
79472
- error: error instanceof Error ? error.message : String(error)
79473
- });
79474
- }
79475
- const skillsRoot = resolveLegacyPath(LEGACY_SKILLS_DIR);
79476
- try {
79477
- const skillDirs = await promises.readdir(skillsRoot, { withFileTypes: true });
79478
- for (const entry of skillDirs) {
79479
- if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
79480
- await removeIfExists(nodePath.join(skillsRoot, entry.name, LEGACY_SKILL_MANIFEST));
79481
- }
79482
- } catch (error) {
79483
- if (!isMissingPathError(error)) logWarn("Failed cleaning legacy skills metadata:", {
79484
- skillsRoot,
79485
- error: error instanceof Error ? error.message : String(error)
79486
- });
79487
- }
79488
- }
79489
- async function importLegacyLocalStorageOnce(payload) {
79490
- if ((await getAppState()).migration.status === "pending") return {
79491
- completed: false,
79492
- importedKeys: [],
79493
- skippedKeys: []
79494
- };
79495
- if (!payload || !isRecord$1(payload)) return {
79496
- completed: true,
79497
- importedKeys: [],
79498
- skippedKeys: []
79499
- };
79500
- const { patch, consumedKeys, skippedKeys } = mergeLegacyLocalStoragePatch(payload);
79501
- const completedAt = (/* @__PURE__ */ new Date()).toISOString();
79502
- if ((await updateAppState((state) => {
79503
- return {
79504
- ...state,
79505
- ...patch,
79506
- app: {
79507
- ...state.app,
79508
- ...patch.app ?? {}
79509
- },
79510
- autoRoll: {
79511
- ...state.autoRoll,
79512
- ...patch.autoRoll ?? {}
79513
- },
79514
- license: {
79515
- ...state.license,
79516
- ...patch.license ?? {}
79517
- },
79518
- preferences: {
79519
- ...state.preferences,
79520
- ...patch.preferences ?? {}
79521
- },
79522
- workspaceSettingsByPath: {
79523
- ...state.workspaceSettingsByPath,
79524
- ...patch.workspaceSettingsByPath ?? {}
79525
- },
79526
- conversationCategoriesByCwd: {
79527
- ...state.conversationCategoriesByCwd,
79528
- ...patch.conversationCategoriesByCwd ?? {}
79529
- },
79530
- conversationCategoryAssignmentsByCwd: {
79531
- ...state.conversationCategoryAssignmentsByCwd,
79532
- ...patch.conversationCategoryAssignmentsByCwd ?? {}
79533
- },
79534
- migration: {
79535
- ...state.migration,
79536
- status: "complete",
79537
- completedAt,
79538
- localStorageImportedAt: completedAt,
79539
- lastError: null
79540
- }
79541
- };
79542
- }, {
79543
- mode: "replace",
79544
- allowBeforeMigrationComplete: true
79545
- })).migration.status !== "complete") return {
79546
- completed: false,
79547
- importedKeys: [],
79548
- skippedKeys: []
79549
- };
79550
- await cleanupLegacyCanonicalSources();
79551
- return {
79552
- completed: true,
79553
- importedKeys: consumedKeys,
79554
- skippedKeys
79555
- };
79556
- }
79557
- //#endregion
79558
80100
  //#region ../../packages/runtime-integrations/src/agents/service.ts
79559
80101
  const AGENTS_FILENAME = "AGENTS.md";
79560
80102
  function resolveGlobalPath(options) {
@@ -79566,7 +80108,7 @@ function getCodexDir(options) {
79566
80108
  function isPathSafe(normalizedPath, options) {
79567
80109
  if (nodePath.basename(normalizedPath) !== AGENTS_FILENAME) return false;
79568
80110
  const codexDir = getCodexDir(options);
79569
- const homeDir = resolveHomeDir$1();
80111
+ const homeDir = resolveHomeDir();
79570
80112
  if (normalizedPath === nodePath.join(codexDir, AGENTS_FILENAME)) return true;
79571
80113
  const parentDir = nodePath.dirname(normalizedPath);
79572
80114
  if (!parentDir.startsWith(homeDir + nodePath.sep) && parentDir !== homeDir) return false;
@@ -80052,6 +80594,88 @@ async function assertProfileCreationAllowed(profileManager) {
80052
80594
  if (typeof licenseWithCounts.profileLimit === "number" && licenseWithCounts.profilesRemaining !== null && licenseWithCounts.profilesRemaining <= 0) throw new Error("CodexUse Free supports up to 2 profiles. Upgrade to CodexUse Pro for unlimited profiles.");
80053
80595
  }
80054
80596
  //#endregion
80597
+ //#region ../../packages/runtime-profiles/src/license/activation.ts
80598
+ const ACTIVATION_SESSION_PARAM = "codexuse_session";
80599
+ const DEFAULT_ACTIVATION_API_URL = "https://api.codexuse.com/v1/activation";
80600
+ const ACTIVATION_REQUEST_TIMEOUT_MS = 1e4;
80601
+ const SESSION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
80602
+ function resolveActivationApiUrl() {
80603
+ return (process.env.CODEXUSE_ACTIVATION_API_URL?.trim() || DEFAULT_ACTIVATION_API_URL).replace(/\/+$/, "");
80604
+ }
80605
+ function isValidSessionId(sessionId) {
80606
+ return SESSION_ID_PATTERN.test(sessionId.trim());
80607
+ }
80608
+ function appendActivationSession(checkoutUrl, sessionId) {
80609
+ const url = new URL(checkoutUrl);
80610
+ url.searchParams.set(ACTIVATION_SESSION_PARAM, sessionId);
80611
+ return url.toString();
80612
+ }
80613
+ async function fetchActivationStatus(sessionId) {
80614
+ if (!isValidSessionId(sessionId)) throw new Error("Invalid activation session.");
80615
+ const controller = new AbortController();
80616
+ const timeout = setTimeout(() => controller.abort(), ACTIVATION_REQUEST_TIMEOUT_MS);
80617
+ try {
80618
+ const url = new URL(resolveActivationApiUrl());
80619
+ url.searchParams.set("session", sessionId);
80620
+ const response = await fetch(url, {
80621
+ method: "GET",
80622
+ signal: controller.signal,
80623
+ headers: { Accept: "application/json" }
80624
+ });
80625
+ if (!response.ok) throw new Error(`Activation check failed (${response.status}).`);
80626
+ const payload = await response.json();
80627
+ if (payload.status !== "pending" && payload.status !== "ready" && payload.status !== "revoked") throw new Error("Activation check returned an invalid status.");
80628
+ return payload;
80629
+ } catch (error) {
80630
+ if (error instanceof Error && error.name === "AbortError") throw new Error("Activation check timed out.");
80631
+ if (error instanceof Error && error.message.toLowerCase().includes("activation check")) throw error;
80632
+ const message = error instanceof Error ? error.message : String(error);
80633
+ throw new Error(`Activation check failed: ${message}`);
80634
+ } finally {
80635
+ clearTimeout(timeout);
80636
+ }
80637
+ }
80638
+ function createLicenseActivationSession() {
80639
+ const offer = getActiveOffer();
80640
+ const sessionId = crypto$1.randomUUID();
80641
+ return {
80642
+ sessionId,
80643
+ checkoutUrl: appendActivationSession(buildCheckoutUrl(offer, {
80644
+ directCheckout: true,
80645
+ source: "app",
80646
+ medium: "desktop_checkout",
80647
+ campaign: offer.campaign ?? void 0
80648
+ }), sessionId)
80649
+ };
80650
+ }
80651
+ async function pollLicenseActivation(sessionId) {
80652
+ const current = await licenseService.getCachedStatus();
80653
+ if (current.isPro) return {
80654
+ status: "activated",
80655
+ license: current,
80656
+ message: "Pro is already active."
80657
+ };
80658
+ const payload = await fetchActivationStatus(sessionId);
80659
+ if (payload.status === "pending") return {
80660
+ status: "pending",
80661
+ message: "Waiting for Gumroad confirmation."
80662
+ };
80663
+ if (payload.status === "revoked") return {
80664
+ status: "revoked",
80665
+ message: "This purchase was refunded or disputed."
80666
+ };
80667
+ const licenseKey = payload.licenseKey?.trim();
80668
+ if (!licenseKey) return {
80669
+ status: "pending",
80670
+ message: "Waiting for Gumroad to attach the license key."
80671
+ };
80672
+ return {
80673
+ status: "activated",
80674
+ license: await licenseService.activate(licenseKey),
80675
+ message: "Pro unlocked automatically after purchase."
80676
+ };
80677
+ }
80678
+ //#endregion
80055
80679
  //#region src/codex/runtimeInspection.ts
80056
80680
  const COMMAND_TIMEOUT_MS$1 = 5e3;
80057
80681
  const AUTH_STATUS_TIMEOUT_MS = 8e3;
@@ -82600,7 +83224,6 @@ const LAUNCH_WAIT_MS = 15e3;
82600
83224
  const POLL_INTERVAL_MS = 250;
82601
83225
  const APP_DISCOVERY_CACHE_TTL_MS = 6e4;
82602
83226
  const APP_DISCOVERY_MISS_CACHE_TTL_MS = 5e3;
82603
- const OFFICIAL_CODEX_ACTIVITY_LIMIT = 50;
82604
83227
  let profileActionLock = Promise.resolve();
82605
83228
  let appDiscoveryCache = null;
82606
83229
  function logOfficialCodexRestart(level, message, context) {
@@ -82642,7 +83265,7 @@ async function recordOfficialCodexActivity(input) {
82642
83265
  observedProfileMatchSource: input.observedProfileMatchSource ?? null
82643
83266
  };
82644
83267
  try {
82645
- await updateAppState((state) => ({ officialCodex: { activity: [...state.officialCodex.activity, entry].slice(-OFFICIAL_CODEX_ACTIVITY_LIMIT) } }));
83268
+ await updateAppState((state) => ({ officialCodex: { activity: [...state.officialCodex.activity, entry].slice(-50) } }));
82646
83269
  } catch (error) {
82647
83270
  logOfficialCodexRestart("warn", "Failed to record official Codex activity.", {
82648
83271
  kind: entry.kind,
@@ -83705,6 +84328,38 @@ var ServerLifecycleError = class extends TaggedErrorClass()("ServerLifecycleErro
83705
84328
  operation: String$1,
83706
84329
  cause: optional$2(Defect)
83707
84330
  }) {};
84331
+ const BOOTSTRAP_WS_TIMEOUT_MS = 15e3;
84332
+ const BOOTSTRAP_FAULTS_ENABLED = process.env.CODEXUSE_ENABLE_BOOTSTRAP_FAULTS === "1";
84333
+ const BOOTSTRAP_FAULT = BOOTSTRAP_FAULTS_ENABLED ? process.env.CODEXUSE_BOOTSTRAP_FAULT?.trim() ?? "" : "";
84334
+ function waitForever() {
84335
+ return new Promise(() => {});
84336
+ }
84337
+ function withPromiseTimeout(promise, timeoutMs, message) {
84338
+ return new Promise((resolve, reject) => {
84339
+ const timeout = setTimeout(() => reject(new Error(message)), timeoutMs);
84340
+ timeout.unref?.();
84341
+ promise.then((value) => {
84342
+ clearTimeout(timeout);
84343
+ resolve(value);
84344
+ }, (error) => {
84345
+ clearTimeout(timeout);
84346
+ reject(error);
84347
+ });
84348
+ });
84349
+ }
84350
+ async function runBootstrapWsTask(operation, task) {
84351
+ return withPromiseTimeout((async () => {
84352
+ if (BOOTSTRAP_FAULTS_ENABLED && operation === WS_METHODS.appStateGet) {
84353
+ if (BOOTSTRAP_FAULT === "rpc-hang" || BOOTSTRAP_FAULT === "storage-deadlock") await waitForever();
84354
+ if (BOOTSTRAP_FAULT === "sqlite-lock") {
84355
+ const error = /* @__PURE__ */ new Error("database is locked");
84356
+ error.code = "SQLITE_BUSY";
84357
+ throw error;
84358
+ }
84359
+ }
84360
+ return task();
84361
+ })(), BOOTSTRAP_WS_TIMEOUT_MS, `Bootstrap WS ${operation} timed out after ${BOOTSTRAP_WS_TIMEOUT_MS}ms.`);
84362
+ }
83708
84363
  const createServer = fn(function* () {
83709
84364
  const serverConfig = yield* ServerConfig$1;
83710
84365
  const { port, cwd, staticDir, devUrl, authToken, host, logWebSocketEvents, autoBootstrapProjectFromCwd } = serverConfig;
@@ -85761,7 +86416,7 @@ const createServer = fn(function* () {
85761
86416
  issues: []
85762
86417
  };
85763
86418
  }
85764
- case WS_METHODS.appStateGet: return yield* promise(() => getAppState());
86419
+ case WS_METHODS.appStateGet: return yield* promise(() => runBootstrapWsTask(WS_METHODS.appStateGet, () => getAppState()));
85765
86420
  case WS_METHODS.appStatePatch: {
85766
86421
  const body = stripRequestTag(request.body);
85767
86422
  if (!body.patch || typeof body.patch !== "object" || Array.isArray(body.patch)) return yield* new RouteRequestError({ message: "App state patch must be an object." });
@@ -86133,6 +86788,11 @@ const createServer = fn(function* () {
86133
86788
  throw error;
86134
86789
  }
86135
86790
  }
86791
+ case WS_METHODS.licenseActivationCreate: return createLicenseActivationSession();
86792
+ case WS_METHODS.licenseActivationPoll: {
86793
+ const body = stripRequestTag(request.body);
86794
+ return yield* promise(() => pollLicenseActivation(body.sessionId));
86795
+ }
86136
86796
  case WS_METHODS.syncStatus: return yield* promise(() => getCloudSyncStatus());
86137
86797
  case WS_METHODS.syncPull: {
86138
86798
  const result = yield* promise(() => pullCloudSync());
@@ -86616,6 +87276,9 @@ const reconcileDuplicateProjects = gen(function* () {
86616
87276
  * @module CliConfig
86617
87277
  */
86618
87278
  var StartupError = class extends TaggedError("StartupError") {};
87279
+ const DESKTOP_APP_STATE_INIT_TIMEOUT_MS = 15e3;
87280
+ const DESKTOP_STORAGE_MIGRATION_TIMEOUT_MS = 15e3;
87281
+ const DESKTOP_PROJECTS_STATE_DIRNAME = "t3-projects";
86619
87282
  /**
86620
87283
  * CliConfig - Service tag for startup CLI/runtime helpers.
86621
87284
  */
@@ -86691,6 +87354,24 @@ const ServerConfigLive = (input) => effect(ServerConfig$1, gen(function* () {
86691
87354
  const LayerLive = (input) => empty$7.pipe(provideMerge(makeServerRuntimeServicesLayer()), provideMerge(makeServerProviderLayer()), provideMerge(ProviderHealthLive), provideMerge(ProjectionProjectRepositoryLive), provideMerge(ProjectionThreadRepositoryLive), provideMerge(ProjectionThreadMessageRepositoryLive), provideMerge(ProjectionThreadProposedPlanRepositoryLive), provideMerge(ProjectionThreadActivityRepositoryLive), provideMerge(ProjectionThreadSessionRepositoryLive), provideMerge(ProjectionTurnRepositoryLive), provideMerge(ProjectionCheckpointRepositoryLive), provideMerge(ProjectionStateRepositoryLive), provideMerge(ProviderSessionRuntimeRepositoryLive), provideMerge(layerConfig), provideMerge(ServerLoggerLive), provideMerge(ServerConfigLive(input)));
86692
87355
  const isWildcardHost = (host) => host === "0.0.0.0" || host === "::" || host === "[::]";
86693
87356
  const formatHostForUrl = (host) => host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
87357
+ function withStartupTimeout(promise, timeoutMs, message) {
87358
+ return new Promise((resolve, reject) => {
87359
+ const timeout = setTimeout(() => reject(new Error(message)), timeoutMs);
87360
+ timeout.unref?.();
87361
+ promise.then((value) => {
87362
+ clearTimeout(timeout);
87363
+ resolve(value);
87364
+ }, (error) => {
87365
+ clearTimeout(timeout);
87366
+ reject(error);
87367
+ });
87368
+ });
87369
+ }
87370
+ function resolveDesktopAppUserDataDir(stateDir) {
87371
+ const normalized = nodePath.normalize(stateDir);
87372
+ if (nodePath.basename(normalized) === DESKTOP_PROJECTS_STATE_DIRNAME) return nodePath.dirname(normalized);
87373
+ return normalized;
87374
+ }
86694
87375
  function sendDesktopParentMessage(payload) {
86695
87376
  if (typeof process.send !== "function") return;
86696
87377
  try {
@@ -86744,6 +87425,29 @@ const makeServerProgram = (input) => gen(function* () {
86744
87425
  const config = yield* ServerConfig$1;
86745
87426
  if (!config.devUrl && !config.staticDir) yield* logWarning$1("web bundle missing and no VITE_DEV_SERVER_URL; web UI unavailable", { hint: "Run `bun run --cwd apps/web build` or set VITE_DEV_SERVER_URL for dev mode." });
86746
87427
  yield* start;
87428
+ if (config.mode === "desktop") {
87429
+ const appUserDataDir = resolveDesktopAppUserDataDir(config.stateDir);
87430
+ yield* tryPromise({
87431
+ try: () => withStartupTimeout(initializeAppState(appUserDataDir), DESKTOP_APP_STATE_INIT_TIMEOUT_MS, `Desktop app-state initialization timed out after ${DESKTOP_APP_STATE_INIT_TIMEOUT_MS}ms.`),
87432
+ catch: (cause) => new StartupError({
87433
+ message: "Failed to initialize desktop app state",
87434
+ cause
87435
+ })
87436
+ }).pipe(tap(() => logInfo$1("Desktop app state initialized", { appUserDataDir })), catch_((cause) => logWarning$1("desktop app-state init skipped", {
87437
+ cause,
87438
+ appUserDataDir
87439
+ })));
87440
+ yield* tryPromise({
87441
+ try: () => withStartupTimeout(runStorageMigrationV1(), DESKTOP_STORAGE_MIGRATION_TIMEOUT_MS, `Desktop storage migration timed out after ${DESKTOP_STORAGE_MIGRATION_TIMEOUT_MS}ms.`),
87442
+ catch: (cause) => new StartupError({
87443
+ message: "Failed to run desktop storage migration",
87444
+ cause
87445
+ })
87446
+ }).pipe(tap(() => logInfo$1("Desktop storage migration finished", { appUserDataDir })), catch_((cause) => logWarning$1("desktop storage migration skipped", {
87447
+ cause,
87448
+ appUserDataDir
87449
+ })));
87450
+ }
86747
87451
  yield* sync(() => {
86748
87452
  const elapsedMs = Date.now() - startupStartedAt;
86749
87453
  sendDesktopParentMessage({