frizz 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dev-child.js CHANGED
@@ -568,6 +568,124 @@ var init_project_identity = __esm({
568
568
  }
569
569
  });
570
570
 
571
+ // packages/server/src/project-root.ts
572
+ import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
573
+ import { closeSync as closeSync2, existsSync as existsSync2, fsyncSync as fsyncSync2, mkdirSync as mkdirSync2, openSync as openSync2, readFileSync as readFileSync3, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
574
+ import { homedir as homedir3 } from "node:os";
575
+ import { dirname as dirname2, join as join3, parse, resolve as resolve2 } from "node:path";
576
+ function projectIdPath(root) {
577
+ return join3(root, FRIZZ_DIR, ID_FILE);
578
+ }
579
+ function readProjectIdFile(root) {
580
+ let raw2;
581
+ try {
582
+ raw2 = readFileSync3(projectIdPath(root), "utf8");
583
+ } catch {
584
+ return void 0;
585
+ }
586
+ try {
587
+ return validateProjectId(raw2.trim());
588
+ } catch {
589
+ throw new Error(`${projectIdPath(root)} is invalid; expected exactly one UUID`);
590
+ }
591
+ }
592
+ function writeProjectIdFile(root, id) {
593
+ const dir = join3(root, FRIZZ_DIR);
594
+ mkdirSync2(dir, { recursive: true });
595
+ const ignore = join3(dir, SELF_IGNORE);
596
+ if (!existsSync2(ignore)) {
597
+ try {
598
+ writeFileSync2(ignore, "*\n", { flag: "wx" });
599
+ } catch {
600
+ }
601
+ }
602
+ const path = projectIdPath(root);
603
+ const temp = join3(dir, `.${ID_FILE}.${process.pid}.${randomUUID3()}.tmp`);
604
+ let fd;
605
+ try {
606
+ fd = openSync2(temp, "wx", 384);
607
+ writeFileSync2(fd, `${id}
608
+ `, "utf8");
609
+ fsyncSync2(fd);
610
+ closeSync2(fd);
611
+ fd = void 0;
612
+ renameSync2(temp, path);
613
+ } catch (error) {
614
+ if (fd !== void 0) {
615
+ try {
616
+ closeSync2(fd);
617
+ } catch {
618
+ }
619
+ }
620
+ try {
621
+ rmSync2(temp, { force: true });
622
+ } catch {
623
+ }
624
+ throw error;
625
+ }
626
+ return id;
627
+ }
628
+ function projectRootLockName(root) {
629
+ return `identity-path-${createHash2("sha256").update(root).digest("hex")}.lock`;
630
+ }
631
+ function ensureProjectIdFile(root, home = homedir3(), seed) {
632
+ const existing = readProjectIdFile(root);
633
+ if (existing) return existing;
634
+ const release = acquireNamedLaunchLockSync(home, projectRootLockName(root));
635
+ try {
636
+ const raced = readProjectIdFile(root);
637
+ if (raced) return raced;
638
+ return writeProjectIdFile(root, seed ? validateProjectId(seed) : randomUUID3());
639
+ } finally {
640
+ release();
641
+ }
642
+ }
643
+ function hasAny(dir, names) {
644
+ return names.some((name) => existsSync2(join3(dir, name)));
645
+ }
646
+ function discoverProjectRoot(cwd = process.cwd(), home = homedir3()) {
647
+ let dir;
648
+ try {
649
+ dir = resolve2(cwd);
650
+ } catch {
651
+ return resolve2(cwd);
652
+ }
653
+ const stop = resolve2(home);
654
+ const filesystemRoot = parse(dir).root;
655
+ for (let at = dir; ; at = dirname2(at)) {
656
+ if (at === stop || at === filesystemRoot) break;
657
+ if (existsSync2(projectIdPath(at))) return at;
658
+ if (hasAny(at, REPO_MARKERS)) return at;
659
+ if (hasAny(at, PROJECT_MARKERS)) return at;
660
+ if (dirname2(at) === at) break;
661
+ }
662
+ return dir;
663
+ }
664
+ var FRIZZ_DIR, ID_FILE, SELF_IGNORE, REPO_MARKERS, PROJECT_MARKERS;
665
+ var init_project_root = __esm({
666
+ "packages/server/src/project-root.ts"() {
667
+ "use strict";
668
+ init_project_identity();
669
+ FRIZZ_DIR = ".frizz";
670
+ ID_FILE = ".id";
671
+ SELF_IGNORE = ".gitignore";
672
+ REPO_MARKERS = [".git", ".jj", ".hg", ".svn"];
673
+ PROJECT_MARKERS = [
674
+ "package.json",
675
+ "pyproject.toml",
676
+ "go.mod",
677
+ "Cargo.toml",
678
+ "deno.json",
679
+ "deno.jsonc",
680
+ "composer.json",
681
+ "Gemfile",
682
+ "pom.xml",
683
+ "build.gradle",
684
+ "Makefile"
685
+ ];
686
+ }
687
+ });
688
+
571
689
  // packages/server/src/sqlite-quiet.ts
572
690
  function isSqliteExperimentalNotice(warning, type) {
573
691
  const name = typeof warning === "string" ? type : warning?.name;
@@ -795,39 +913,39 @@ var init_sqlite = __esm({
795
913
 
796
914
  // packages/server/src/migrate-fray.ts
797
915
  import { execFileSync as execFileSync3 } from "node:child_process";
798
- import { existsSync as existsSync2, lstatSync, readdirSync, realpathSync as realpathSync2, renameSync as renameSync2, rmdirSync } from "node:fs";
799
- import { homedir as homedir3 } from "node:os";
800
- import { join as join3, resolve as resolve2 } from "node:path";
916
+ import { existsSync as existsSync3, lstatSync, readdirSync, realpathSync as realpathSync2, renameSync as renameSync3, rmdirSync } from "node:fs";
917
+ import { homedir as homedir4 } from "node:os";
918
+ import { join as join4, resolve as resolve3 } from "node:path";
801
919
  function xdg2(env, name) {
802
920
  const value = env[name];
803
921
  return value && (value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value)) ? value : void 0;
804
922
  }
805
923
  function movesFor(env, platform3, home) {
806
- const moves = [{ from: join3(home, ".fray"), to: join3(home, ".frizz") }];
924
+ const moves = [{ from: join4(home, ".fray"), to: join4(home, ".frizz") }];
807
925
  if (platform3 === "win32") {
808
- const local = env.LOCALAPPDATA || join3(env.USERPROFILE || home, "AppData", "Local");
809
- moves.push({ from: join3(local, "Fray"), to: join3(local, "Frizz") });
926
+ const local = env.LOCALAPPDATA || join4(env.USERPROFILE || home, "AppData", "Local");
927
+ moves.push({ from: join4(local, "Fray"), to: join4(local, "Frizz") });
810
928
  } else if (platform3 === "darwin") {
811
- const support = join3(home, "Library", "Application Support");
812
- moves.push({ from: join3(support, "Fray"), to: join3(support, "Frizz") });
813
- moves.push({ from: join3(home, "Library", "Caches", "Fray"), to: join3(home, "Library", "Caches", "Frizz") });
929
+ const support = join4(home, "Library", "Application Support");
930
+ moves.push({ from: join4(support, "Fray"), to: join4(support, "Frizz") });
931
+ moves.push({ from: join4(home, "Library", "Caches", "Fray"), to: join4(home, "Library", "Caches", "Frizz") });
814
932
  } else {
815
- moves.push({ from: join3(home, ".local", "share", "fray"), to: join3(home, ".local", "share", "frizz") });
816
- moves.push({ from: join3(home, ".local", "state", "fray"), to: join3(home, ".local", "state", "frizz") });
817
- moves.push({ from: join3(home, ".cache", "fray"), to: join3(home, ".cache", "frizz") });
933
+ moves.push({ from: join4(home, ".local", "share", "fray"), to: join4(home, ".local", "share", "frizz") });
934
+ moves.push({ from: join4(home, ".local", "state", "fray"), to: join4(home, ".local", "state", "frizz") });
935
+ moves.push({ from: join4(home, ".cache", "fray"), to: join4(home, ".cache", "frizz") });
818
936
  }
819
937
  for (const name of ["XDG_DATA_HOME", "XDG_STATE_HOME", "XDG_CACHE_HOME"]) {
820
938
  const base = xdg2(env, name);
821
- if (base) moves.push({ from: join3(base, "fray"), to: join3(base, "frizz") });
939
+ if (base) moves.push({ from: join4(base, "fray"), to: join4(base, "frizz") });
822
940
  }
823
941
  return moves;
824
942
  }
825
943
  function migrateFrayGlobalRoots(options = {}) {
826
944
  const env = options.env ?? process.env;
827
945
  const platform3 = options.platform ?? process.platform;
828
- const home = options.home ?? homedir3();
829
- const exists = options.exists ?? existsSync2;
830
- const rename2 = options.rename ?? renameSync2;
946
+ const home = options.home ?? homedir4();
947
+ const exists = options.exists ?? existsSync3;
948
+ const rename2 = options.rename ?? renameSync3;
831
949
  const merge = options.merge ?? mergeInto;
832
950
  const moved = [];
833
951
  for (const move of movesFor(env, platform3, home)) {
@@ -847,10 +965,10 @@ function migrateFrayGlobalRoots(options = {}) {
847
965
  function mergeInto(from, to) {
848
966
  let moved = false;
849
967
  for (const entry of readdirSync(from, { withFileTypes: true })) {
850
- const src = join3(from, entry.name);
851
- const dst = join3(to, entry.name);
852
- if (!existsSync2(dst)) {
853
- renameSync2(src, dst);
968
+ const src = join4(from, entry.name);
969
+ const dst = join4(to, entry.name);
970
+ if (!existsSync3(dst)) {
971
+ renameSync3(src, dst);
854
972
  moved = true;
855
973
  continue;
856
974
  }
@@ -863,12 +981,12 @@ function mergeInto(from, to) {
863
981
  return moved;
864
982
  }
865
983
  function migrateFrayProjectDir(projectDir) {
866
- const from = join3(projectDir, ".fray");
867
- const to = join3(projectDir, ".frizz");
984
+ const from = join4(projectDir, ".fray");
985
+ const to = join4(projectDir, ".frizz");
868
986
  try {
869
987
  if (!lstatSync(from).isDirectory()) return false;
870
- if (!existsSync2(to)) {
871
- renameSync2(from, to);
988
+ if (!existsSync3(to)) {
989
+ renameSync3(from, to);
872
990
  return true;
873
991
  }
874
992
  return lstatSync(to).isDirectory() ? mergeInto(from, to) : false;
@@ -905,8 +1023,8 @@ function writeId(dir, scope, id) {
905
1023
  return readId(dir, scope, CURRENT_KEY) === id;
906
1024
  }
907
1025
  function hasBoard(id, home) {
908
- const db = join3(projectStateDir(id, home), "ui.db");
909
- if (!existsSync2(db)) return false;
1026
+ const db = join4(projectStateDir(id, home), "ui.db");
1027
+ if (!existsSync3(db)) return false;
910
1028
  let sql;
911
1029
  try {
912
1030
  sql = new Database(db, { readonly: true });
@@ -930,7 +1048,7 @@ function linkedWorktreeScopes(dir) {
930
1048
  env: { ...process.env, LC_ALL: "C" },
931
1049
  stdio: ["ignore", "pipe", "ignore"]
932
1050
  }).trim();
933
- return realpathSync2(resolve2(dir, raw2));
1051
+ return realpathSync2(resolve3(dir, raw2));
934
1052
  } catch {
935
1053
  return void 0;
936
1054
  }
@@ -939,8 +1057,8 @@ function linkedWorktreeScopes(dir) {
939
1057
  const commonGitDir = gitPath("--git-common-dir");
940
1058
  if (!gitDir || !commonGitDir || gitDir === commonGitDir) return void 0;
941
1059
  return {
942
- legacy: ["--file", join3(gitDir, "fray.config")],
943
- current: ["--file", join3(gitDir, "frizz.config")]
1060
+ legacy: ["--file", join4(gitDir, "fray.config")],
1061
+ current: ["--file", join4(gitDir, "frizz.config")]
944
1062
  };
945
1063
  }
946
1064
  function adopt(dir, legacy, current, home) {
@@ -977,15 +1095,14 @@ var init_migrate_fray = __esm({
977
1095
 
978
1096
  // packages/server/src/project.ts
979
1097
  import { execFileSync as execFileSync4 } from "node:child_process";
980
- import { mkdirSync as mkdirSync2, realpathSync as realpathSync3 } from "node:fs";
981
- import { homedir as homedir4, tmpdir } from "node:os";
982
- import { basename, join as join4, resolve as resolve3 } from "node:path";
983
- import { randomUUID as randomUUID3 } from "node:crypto";
1098
+ import { mkdirSync as mkdirSync3, realpathSync as realpathSync3 } from "node:fs";
1099
+ import { homedir as homedir5, tmpdir } from "node:os";
1100
+ import { basename, join as join5, resolve as resolve4 } from "node:path";
984
1101
  function trustedLocalFileRoots(project) {
985
- return [project.dir, tmpdir(), "/tmp", resolve3(homedir4(), "Screenshots"), join4(project.stateDir, "attachments")];
1102
+ return [project.dir, tmpdir(), "/tmp", resolve4(homedir5(), "Screenshots"), join5(project.stateDir, "attachments")];
986
1103
  }
987
1104
  function openableFileRoots(project) {
988
- return [homedir4(), ...trustedLocalFileRoots(project)];
1105
+ return [homedir5(), ...trustedLocalFileRoots(project)];
989
1106
  }
990
1107
  function isNotGitRepositoryError(error) {
991
1108
  if (!error || typeof error !== "object" || !("stderr" in error)) return false;
@@ -1001,15 +1118,23 @@ function resolveProjectDir(cwd = process.cwd()) {
1001
1118
  }).trim();
1002
1119
  return realpathSync3(root);
1003
1120
  } catch (error) {
1004
- if (!isNotGitRepositoryError(error)) throw new Error("unable to resolve Git repository root");
1121
+ if (!isNotGitRepositoryError(error) && !isMissingGitBinary(error)) {
1122
+ throw new Error("unable to resolve Git repository root");
1123
+ }
1124
+ const root = discoverProjectRoot(cwd);
1005
1125
  try {
1006
- return realpathSync3(cwd);
1126
+ return realpathSync3(root);
1007
1127
  } catch {
1008
- return resolve3(cwd);
1128
+ return resolve4(root);
1009
1129
  }
1010
1130
  }
1011
1131
  }
1012
- function resolveProjectIdentity(dir, home = homedir4()) {
1132
+ function isMissingGitBinary(error) {
1133
+ const code = error?.code;
1134
+ return code === "ENOENT" || code === "EACCES";
1135
+ }
1136
+ function resolveProjectIdentity(dir, home = homedir5()) {
1137
+ let insideWorktree = false;
1013
1138
  try {
1014
1139
  const inside = execFileSync4("git", ["rev-parse", "--is-inside-work-tree"], {
1015
1140
  cwd: dir,
@@ -1018,12 +1143,15 @@ function resolveProjectIdentity(dir, home = homedir4()) {
1018
1143
  stdio: ["ignore", "pipe", "pipe"]
1019
1144
  }).trim();
1020
1145
  if (inside !== "true") throw new Error("Git directory is not a worktree");
1146
+ insideWorktree = true;
1021
1147
  } catch (error) {
1022
- if (!isNotGitRepositoryError(error)) throw new Error("unable to inspect Git repository identity");
1023
- return { id: randomUUID3(), scope: "repository", root: dir };
1148
+ if (!isNotGitRepositoryError(error) && !isMissingGitBinary(error)) {
1149
+ throw new Error("unable to inspect Git repository identity");
1150
+ }
1024
1151
  }
1025
- const identity = resolveGitProjectIdentity(dir, home);
1026
- return { id: identity.id, scope: identity.scope, root: identity.root };
1152
+ const git = insideWorktree ? resolveGitProjectIdentity(dir, home) : void 0;
1153
+ const root = git?.root ?? dir;
1154
+ return { id: ensureProjectIdFile(root, home, git?.id), scope: git?.scope ?? "repository", root };
1027
1155
  }
1028
1156
  function cwdSlug(absPath) {
1029
1157
  return absPath.replace(/[/.]/g, "-");
@@ -1054,7 +1182,7 @@ function resolveProjectLabel(dir) {
1054
1182
  return null;
1055
1183
  }
1056
1184
  }
1057
- function resolveProject(cwd = process.cwd(), home = homedir4(), env = process.env, { migrate = false } = {}) {
1185
+ function resolveProject(cwd = process.cwd(), home = homedir5(), env = process.env, { migrate = false } = {}) {
1058
1186
  if (migrate) migrateFrayGlobalRoots({ env, home });
1059
1187
  const projectDir = resolveProjectDir(cwd);
1060
1188
  if (migrate) migrateFrayProjectId(projectDir, { home });
@@ -1063,7 +1191,7 @@ function resolveProject(cwd = process.cwd(), home = homedir4(), env = process.en
1063
1191
  if (migrate) migrateFrayProjectDir(dir);
1064
1192
  const id = identity.id;
1065
1193
  const stateDir = projectStateDir(id, home);
1066
- mkdirSync2(stateDir, { recursive: true });
1194
+ mkdirSync3(stateDir, { recursive: true });
1067
1195
  const name = basename(dir) || dir;
1068
1196
  const target = {
1069
1197
  projectId: id,
@@ -1082,10 +1210,10 @@ function resolveProject(cwd = process.cwd(), home = homedir4(), env = process.en
1082
1210
  };
1083
1211
  }
1084
1212
  function permRequestDir(project) {
1085
- return join4(project.stateDir, "perm-requests");
1213
+ return join5(project.stateDir, "perm-requests");
1086
1214
  }
1087
1215
  function permMarkerPath(project, slug) {
1088
- return join4(permRequestDir(project), `${slug}.json`);
1216
+ return join5(permRequestDir(project), `${slug}.json`);
1089
1217
  }
1090
1218
  function projectLaunchTarget(project) {
1091
1219
  return {
@@ -1118,25 +1246,26 @@ var init_project = __esm({
1118
1246
  "packages/server/src/project.ts"() {
1119
1247
  "use strict";
1120
1248
  init_project_identity();
1249
+ init_project_root();
1121
1250
  init_frizz_paths();
1122
1251
  init_migrate_fray();
1123
1252
  }
1124
1253
  });
1125
1254
 
1126
1255
  // packages/server/src/project-launch.ts
1127
- import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
1256
+ import { createHash as createHash3, randomUUID as randomUUID4 } from "node:crypto";
1128
1257
  import {
1129
- closeSync as closeSync2,
1130
- fsyncSync as fsyncSync2,
1131
- mkdirSync as mkdirSync3,
1132
- openSync as openSync2,
1133
- readFileSync as readFileSync3,
1134
- renameSync as renameSync3,
1135
- rmSync as rmSync2,
1258
+ closeSync as closeSync3,
1259
+ fsyncSync as fsyncSync3,
1260
+ mkdirSync as mkdirSync4,
1261
+ openSync as openSync3,
1262
+ readFileSync as readFileSync4,
1263
+ renameSync as renameSync4,
1264
+ rmSync as rmSync3,
1136
1265
  statSync as statSync2,
1137
- writeFileSync as writeFileSync2
1266
+ writeFileSync as writeFileSync3
1138
1267
  } from "node:fs";
1139
- import { basename as basename2, dirname as dirname2, isAbsolute, join as join5 } from "node:path";
1268
+ import { basename as basename2, dirname as dirname3, isAbsolute, join as join6 } from "node:path";
1140
1269
  function errorCode3(error) {
1141
1270
  return error && typeof error === "object" && "code" in error && typeof error.code === "string" ? error.code : void 0;
1142
1271
  }
@@ -1146,40 +1275,40 @@ function validText(value, max = 4096) {
1146
1275
  function syncDirectory2(path) {
1147
1276
  let fd;
1148
1277
  try {
1149
- fd = openSync2(path, "r");
1150
- fsyncSync2(fd);
1278
+ fd = openSync3(path, "r");
1279
+ fsyncSync3(fd);
1151
1280
  } catch {
1152
1281
  } finally {
1153
1282
  if (fd !== void 0) {
1154
1283
  try {
1155
- closeSync2(fd);
1284
+ closeSync3(fd);
1156
1285
  } catch {
1157
1286
  }
1158
1287
  }
1159
1288
  }
1160
1289
  }
1161
1290
  function atomicJson(path, value) {
1162
- mkdirSync3(dirname2(path), { recursive: true, mode: 448 });
1163
- const temp = join5(dirname2(path), `.${basename2(path)}.${process.pid}.${randomUUID4()}.tmp`);
1291
+ mkdirSync4(dirname3(path), { recursive: true, mode: 448 });
1292
+ const temp = join6(dirname3(path), `.${basename2(path)}.${process.pid}.${randomUUID4()}.tmp`);
1164
1293
  let fd;
1165
1294
  try {
1166
- fd = openSync2(temp, "wx", 384);
1167
- writeFileSync2(fd, `${JSON.stringify(value)}
1295
+ fd = openSync3(temp, "wx", 384);
1296
+ writeFileSync3(fd, `${JSON.stringify(value)}
1168
1297
  `, "utf8");
1169
- fsyncSync2(fd);
1170
- closeSync2(fd);
1298
+ fsyncSync3(fd);
1299
+ closeSync3(fd);
1171
1300
  fd = void 0;
1172
- renameSync3(temp, path);
1173
- syncDirectory2(dirname2(path));
1301
+ renameSync4(temp, path);
1302
+ syncDirectory2(dirname3(path));
1174
1303
  } catch (error) {
1175
1304
  if (fd !== void 0) {
1176
1305
  try {
1177
- closeSync2(fd);
1306
+ closeSync3(fd);
1178
1307
  } catch {
1179
1308
  }
1180
1309
  }
1181
1310
  try {
1182
- rmSync2(temp, { force: true });
1311
+ rmSync3(temp, { force: true });
1183
1312
  } catch {
1184
1313
  }
1185
1314
  throw error;
@@ -1188,12 +1317,12 @@ function atomicJson(path, value) {
1188
1317
  function quarantine(path, suffix) {
1189
1318
  const moved = `${path}.${suffix}-${process.pid}-${randomUUID4()}`;
1190
1319
  try {
1191
- renameSync3(path, moved);
1320
+ renameSync4(path, moved);
1192
1321
  } catch {
1193
1322
  return false;
1194
1323
  }
1195
1324
  try {
1196
- rmSync2(moved, { recursive: true, force: true });
1325
+ rmSync3(moved, { recursive: true, force: true });
1197
1326
  } catch {
1198
1327
  }
1199
1328
  return true;
@@ -1210,7 +1339,7 @@ function parseGeneration(value) {
1210
1339
  }
1211
1340
  function parseGuard(path) {
1212
1341
  try {
1213
- const value = JSON.parse(readFileSync3(path, "utf8"));
1342
+ const value = JSON.parse(readFileSync4(path, "utf8"));
1214
1343
  const generation = parseGeneration(value);
1215
1344
  if (value.version !== 1 || !generation || typeof value.token !== "string" || !UUID_RE.test(value.token) || !validText(value.at, 128)) return null;
1216
1345
  return { version: 1, token: value.token, at: value.at, ...generation };
@@ -1219,25 +1348,25 @@ function parseGuard(path) {
1219
1348
  }
1220
1349
  }
1221
1350
  function acquireMutationGuard(stateDir, timeoutMs = GUARD_TIMEOUT_MS, adapter = defaultProcessPlatformAdapter) {
1222
- const path = join5(stateDir, MUTATION_GUARD_NAME);
1223
- mkdirSync3(stateDir, { recursive: true, mode: 448 });
1351
+ const path = join6(stateDir, MUTATION_GUARD_NAME);
1352
+ mkdirSync4(stateDir, { recursive: true, mode: 448 });
1224
1353
  const deadline = adapter.now() + Math.max(0, timeoutMs);
1225
1354
  for (; ; ) {
1226
1355
  const generation = currentProcessGeneration(adapter);
1227
1356
  const token = randomUUID4();
1228
1357
  let fd;
1229
1358
  try {
1230
- fd = openSync2(path, "wx", 384);
1359
+ fd = openSync3(path, "wx", 384);
1231
1360
  const record = {
1232
1361
  version: 1,
1233
1362
  token,
1234
1363
  at: new Date(adapter.now()).toISOString(),
1235
1364
  ...generation
1236
1365
  };
1237
- writeFileSync2(fd, `${JSON.stringify(record)}
1366
+ writeFileSync3(fd, `${JSON.stringify(record)}
1238
1367
  `, "utf8");
1239
- fsyncSync2(fd);
1240
- closeSync2(fd);
1368
+ fsyncSync3(fd);
1369
+ closeSync3(fd);
1241
1370
  fd = void 0;
1242
1371
  const committed = parseGuard(path);
1243
1372
  if (!committed || committed.token !== token || committed.pid !== generation.pid || committed.processStart !== generation.processStart) continue;
@@ -1252,7 +1381,7 @@ function acquireMutationGuard(stateDir, timeoutMs = GUARD_TIMEOUT_MS, adapter =
1252
1381
  } catch (error) {
1253
1382
  if (fd !== void 0) {
1254
1383
  try {
1255
- closeSync2(fd);
1384
+ closeSync3(fd);
1256
1385
  } catch {
1257
1386
  }
1258
1387
  }
@@ -1290,7 +1419,7 @@ function parseDelegates(value) {
1290
1419
  }
1291
1420
  function parseOwner(path) {
1292
1421
  try {
1293
- const value = JSON.parse(readFileSync3(path, "utf8"));
1422
+ const value = JSON.parse(readFileSync4(path, "utf8"));
1294
1423
  const generation = parseGeneration(value);
1295
1424
  if (value.version !== 1 && value.version !== OWNER_VERSION || !generation || typeof value.token !== "string" || !UUID_RE.test(value.token) || typeof value.projectId !== "string" || !UUID_RE.test(value.projectId) || !validText(value.projectDir) || !isAbsolute(value.projectDir) || !validRole(value.role) || !validText(value.acquiredAt, 128) || !validText(value.updatedAt, 128)) return null;
1296
1425
  const delegates = value.version === 1 ? [] : parseDelegates(value.delegates);
@@ -1313,7 +1442,7 @@ function parseOwner(path) {
1313
1442
  }
1314
1443
  }
1315
1444
  function projectLaunchOwnerPath(stateDir) {
1316
- return join5(stateDir, OWNER_NAME);
1445
+ return join6(stateDir, OWNER_NAME);
1317
1446
  }
1318
1447
  function sameTarget(record, target) {
1319
1448
  return record.projectId === target.projectId && record.projectDir === target.projectDir;
@@ -1323,13 +1452,13 @@ function sameProjectIdentity(record, target) {
1323
1452
  }
1324
1453
  function projectLaunchTokenProof(target, token) {
1325
1454
  if (!UUID_RE.test(token)) throw new Error("invalid Frizz project launch owner token");
1326
- return createHash2("sha256").update("frizz-project-launch-v2\0").update(target.projectId).update("\0").update(target.projectDir).update("\0").update(token).digest("hex");
1455
+ return createHash3("sha256").update("frizz-project-launch-v2\0").update(target.projectId).update("\0").update(target.projectDir).update("\0").update(token).digest("hex");
1327
1456
  }
1328
1457
  function removeStatusesForToken(stateDir, token) {
1329
1458
  for (const name of ["dev-supervisor.lock", "server.lock"]) {
1330
- const path = join5(stateDir, name);
1459
+ const path = join6(stateDir, name);
1331
1460
  try {
1332
- const value = JSON.parse(readFileSync3(path, "utf8"));
1461
+ const value = JSON.parse(readFileSync4(path, "utf8"));
1333
1462
  if (value.ownerToken === token) quarantine(path, "stale");
1334
1463
  } catch {
1335
1464
  }
@@ -1338,17 +1467,17 @@ function removeStatusesForToken(stateDir, token) {
1338
1467
  function writeNewOwner(path, record) {
1339
1468
  let fd;
1340
1469
  try {
1341
- fd = openSync2(path, "wx", 384);
1342
- writeFileSync2(fd, `${JSON.stringify(record)}
1470
+ fd = openSync3(path, "wx", 384);
1471
+ writeFileSync3(fd, `${JSON.stringify(record)}
1343
1472
  `, "utf8");
1344
- fsyncSync2(fd);
1345
- closeSync2(fd);
1473
+ fsyncSync3(fd);
1474
+ closeSync3(fd);
1346
1475
  fd = void 0;
1347
- syncDirectory2(dirname2(path));
1476
+ syncDirectory2(dirname3(path));
1348
1477
  } catch (error) {
1349
1478
  if (fd !== void 0) {
1350
1479
  try {
1351
- closeSync2(fd);
1480
+ closeSync3(fd);
1352
1481
  } catch {
1353
1482
  }
1354
1483
  }
@@ -1576,7 +1705,7 @@ function writeProjectStatus(path, value) {
1576
1705
  }
1577
1706
  function removeProjectStatus(path, expected) {
1578
1707
  try {
1579
- const value = JSON.parse(readFileSync3(path, "utf8"));
1708
+ const value = JSON.parse(readFileSync4(path, "utf8"));
1580
1709
  if (value.pid !== expected.pid || value.processStart !== expected.processStart || value.publisherToken !== expected.publisherToken || value.ownerToken !== expected.ownerToken) return false;
1581
1710
  return quarantine(path, "release");
1582
1711
  } catch {
@@ -1640,7 +1769,7 @@ function createRetryableCleanup(run2) {
1640
1769
  }
1641
1770
  function withPhaseTimeout(name, promise, timeoutMs) {
1642
1771
  if (timeoutMs === void 0 || !Number.isFinite(timeoutMs) || timeoutMs <= 0) return promise;
1643
- return new Promise((resolve9, reject) => {
1772
+ return new Promise((resolve10, reject) => {
1644
1773
  let settled = false;
1645
1774
  const settle = (apply) => {
1646
1775
  if (settled) return;
@@ -1651,18 +1780,18 @@ function withPhaseTimeout(name, promise, timeoutMs) {
1651
1780
  const timer = setTimeout(() => settle(() => reject(new ShutdownPhaseTimeoutError(name, timeoutMs))), timeoutMs);
1652
1781
  timer.unref?.();
1653
1782
  promise.then(
1654
- () => settle(resolve9),
1783
+ () => settle(resolve10),
1655
1784
  (error) => settle(() => reject(error))
1656
1785
  );
1657
1786
  });
1658
1787
  }
1659
1788
  function defaultDeadline(drained, timeoutMs) {
1660
- return new Promise((resolve9, reject) => {
1789
+ return new Promise((resolve10, reject) => {
1661
1790
  const timer = setTimeout(() => reject(new ShutdownTimeoutError(timeoutMs)), timeoutMs);
1662
1791
  void drained.then(
1663
1792
  () => {
1664
1793
  clearTimeout(timer);
1665
- resolve9();
1794
+ resolve10();
1666
1795
  },
1667
1796
  (error) => {
1668
1797
  clearTimeout(timer);
@@ -1795,41 +1924,41 @@ var init_shutdown = __esm({
1795
1924
  // packages/server/src/logging.ts
1796
1925
  import {
1797
1926
  appendFileSync,
1798
- mkdirSync as mkdirSync4,
1799
- openSync as openSync3,
1927
+ mkdirSync as mkdirSync5,
1928
+ openSync as openSync4,
1800
1929
  readdirSync as readdirSync2,
1801
- rmSync as rmSync3,
1930
+ rmSync as rmSync4,
1802
1931
  statSync as statSync3,
1803
1932
  symlinkSync,
1804
- writeFileSync as writeFileSync3,
1933
+ writeFileSync as writeFileSync4,
1805
1934
  writeSync
1806
1935
  } from "node:fs";
1807
- import { homedir as homedir5 } from "node:os";
1808
- import { join as join6 } from "node:path";
1809
- function defaultLogRoot(stateDir, home = homedir5()) {
1810
- return stateDir ? join6(stateDir, "logs") : join6(frizzPaths({ home }).state, "logs");
1936
+ import { homedir as homedir6 } from "node:os";
1937
+ import { join as join7 } from "node:path";
1938
+ function defaultLogRoot(stateDir, home = homedir6()) {
1939
+ return stateDir ? join7(stateDir, "logs") : join7(frizzPaths({ home }).state, "logs");
1811
1940
  }
1812
1941
  function runStamp(at) {
1813
1942
  const pad = (value) => String(value).padStart(2, "0");
1814
1943
  return `${at.getFullYear()}-${pad(at.getMonth() + 1)}-${pad(at.getDate())}T${pad(at.getHours())}-${pad(at.getMinutes())}-${pad(at.getSeconds())}`;
1815
1944
  }
1816
- function runLogPath(stateDir, at = /* @__PURE__ */ new Date(), pid = process.pid, home = homedir5(), env = process.env) {
1945
+ function runLogPath(stateDir, at = /* @__PURE__ */ new Date(), pid = process.pid, home = homedir6(), env = process.env) {
1817
1946
  const name = `frizz-${runStamp(at)}-${pid}.log`;
1818
1947
  const override = env[LOG_PATH_ENV]?.trim();
1819
- if (override) return override.endsWith(".log") ? override : join6(override, name);
1820
- return join6(defaultLogRoot(stateDir, home), name);
1948
+ if (override) return override.endsWith(".log") ? override : join7(override, name);
1949
+ return join7(defaultLogRoot(stateDir, home), name);
1821
1950
  }
1822
1951
  function latestLogPath(dir) {
1823
- return join6(dir, "latest.log");
1952
+ return join7(dir, "latest.log");
1824
1953
  }
1825
1954
  function linkLatest(dir, target) {
1826
1955
  const link = latestLogPath(dir);
1827
1956
  try {
1828
- rmSync3(link, { force: true });
1957
+ rmSync4(link, { force: true });
1829
1958
  symlinkSync(target, link);
1830
1959
  } catch {
1831
1960
  try {
1832
- writeFileSync3(link, `${target}
1961
+ writeFileSync4(link, `${target}
1833
1962
  `, { mode: 384 });
1834
1963
  } catch {
1835
1964
  }
@@ -1844,7 +1973,7 @@ function pruneRunLogs(dir, keep = RETAINED_RUNS, days = RETAINED_DAYS, now = Dat
1844
1973
  }
1845
1974
  const dated = entries.map((name) => {
1846
1975
  try {
1847
- return { name, at: statSync3(join6(dir, name)).mtimeMs };
1976
+ return { name, at: statSync3(join7(dir, name)).mtimeMs };
1848
1977
  } catch {
1849
1978
  return { name, at: 0 };
1850
1979
  }
@@ -1853,7 +1982,7 @@ function pruneRunLogs(dir, keep = RETAINED_RUNS, days = RETAINED_DAYS, now = Dat
1853
1982
  const stale = dated.filter((entry, index) => index >= keep || entry.at < cutoff);
1854
1983
  for (const entry of stale) {
1855
1984
  try {
1856
- rmSync3(join6(dir, entry.name), { force: true });
1985
+ rmSync4(join7(dir, entry.name), { force: true });
1857
1986
  } catch {
1858
1987
  }
1859
1988
  }
@@ -1867,8 +1996,8 @@ function formatDiskLine(record) {
1867
1996
  }
1868
1997
  function openLogFile(path) {
1869
1998
  try {
1870
- mkdirSync4(join6(path, ".."), { recursive: true, mode: 448 });
1871
- return openSync3(path, "a", 384);
1999
+ mkdirSync5(join7(path, ".."), { recursive: true, mode: 448 });
2000
+ return openSync4(path, "a", 384);
1872
2001
  } catch {
1873
2002
  return null;
1874
2003
  }
@@ -1881,7 +2010,7 @@ function createLogger(options = {}) {
1881
2010
  const maxBytes = options.maxBytes ?? MAX_LOG_BYTES;
1882
2011
  let fd = path === null ? null : openLogFile(path);
1883
2012
  if (fd !== null && path !== null && options.owner !== false) {
1884
- const dir = join6(path, "..");
2013
+ const dir = join7(path, "..");
1885
2014
  pruneRunLogs(dir);
1886
2015
  linkLatest(dir, path);
1887
2016
  }
@@ -6746,8 +6875,8 @@ function createDrainableWorker(process2, options = {}) {
6746
6875
  },
6747
6876
  drain() {
6748
6877
  if (closed || queue.length === 0 && inFlight === 0) return Promise.resolve();
6749
- return new Promise((resolve9) => {
6750
- waiters.push(resolve9);
6878
+ return new Promise((resolve10) => {
6879
+ waiters.push(resolve10);
6751
6880
  });
6752
6881
  },
6753
6882
  outstanding: () => queue.length + inFlight,
@@ -10723,15 +10852,15 @@ var init_settings = __esm({
10723
10852
  });
10724
10853
 
10725
10854
  // packages/server/src/discover.ts
10726
- import { readdirSync as readdirSync3, statSync as statSync4, openSync as openSync4, readSync, closeSync as closeSync3 } from "node:fs";
10727
- import { join as join7 } from "node:path";
10855
+ import { readdirSync as readdirSync3, statSync as statSync4, openSync as openSync5, readSync, closeSync as closeSync4 } from "node:fs";
10856
+ import { join as join8 } from "node:path";
10728
10857
  function sentinelFor(sessionId) {
10729
10858
  return `threads/${sessionId}/scratch.md`;
10730
10859
  }
10731
10860
  function readHead(path) {
10732
10861
  let fd;
10733
10862
  try {
10734
- fd = openSync4(path, "r");
10863
+ fd = openSync5(path, "r");
10735
10864
  const buf = Buffer.allocUnsafe(HEAD_BYTES);
10736
10865
  const n = readSync(fd, buf, 0, HEAD_BYTES, 0);
10737
10866
  return buf.toString("utf8", 0, n);
@@ -10740,7 +10869,7 @@ function readHead(path) {
10740
10869
  } finally {
10741
10870
  if (fd !== void 0) {
10742
10871
  try {
10743
- closeSync3(fd);
10872
+ closeSync4(fd);
10744
10873
  } catch {
10745
10874
  }
10746
10875
  }
@@ -10761,7 +10890,7 @@ function discoverTranscriptId(logDir, sessionId, opts = {}) {
10761
10890
  if (name.startsWith(".") || !name.endsWith(".jsonl")) continue;
10762
10891
  const id = name.slice(0, -".jsonl".length);
10763
10892
  if (!id || id === sessionId || exclude?.has(id)) continue;
10764
- const path = join7(logDir, name);
10893
+ const path = join8(logDir, name);
10765
10894
  let mtime;
10766
10895
  try {
10767
10896
  mtime = statSync4(path).mtimeMs;
@@ -10789,12 +10918,12 @@ var init_discover = __esm({
10789
10918
  });
10790
10919
 
10791
10920
  // packages/server/src/session-files.ts
10792
- import { lstatSync as lstatSync2, rmSync as rmSync4 } from "node:fs";
10921
+ import { lstatSync as lstatSync2, rmSync as rmSync5 } from "node:fs";
10793
10922
  import { tmpdir as tmpdir2 } from "node:os";
10794
- import { join as join8 } from "node:path";
10923
+ import { join as join9 } from "node:path";
10795
10924
  function systemPromptPath(sessionId) {
10796
10925
  if (!SESSION_ID_RE.test(sessionId)) throw new Error("invalid session id");
10797
- return join8(SYSTEM_PROMPT_DIR, `${sessionId}.md`);
10926
+ return join9(SYSTEM_PROMPT_DIR, `${sessionId}.md`);
10798
10927
  }
10799
10928
  function isDirectDirectory(path) {
10800
10929
  try {
@@ -10814,9 +10943,9 @@ function pathAbsent(path) {
10814
10943
  }
10815
10944
  function unlinkDirectChild(parent, filename) {
10816
10945
  if (!isDirectDirectory(parent)) return pathAbsent(parent);
10817
- const child = join8(parent, filename);
10946
+ const child = join9(parent, filename);
10818
10947
  try {
10819
- rmSync4(child, { force: true });
10948
+ rmSync5(child, { force: true });
10820
10949
  } catch {
10821
10950
  return false;
10822
10951
  }
@@ -10824,14 +10953,14 @@ function unlinkDirectChild(parent, filename) {
10824
10953
  }
10825
10954
  function cleanupAdoptionSessionFiles(projectDir, sessionId) {
10826
10955
  if (!SESSION_ID_RE.test(sessionId)) return false;
10827
- const frizzDir = join8(projectDir, ".frizz");
10956
+ const frizzDir = join9(projectDir, ".frizz");
10828
10957
  let clean = true;
10829
10958
  if (isDirectDirectory(frizzDir)) {
10830
- const threads = join8(frizzDir, "threads");
10959
+ const threads = join9(frizzDir, "threads");
10831
10960
  if (isDirectDirectory(threads)) {
10832
- const child = join8(threads, sessionId);
10961
+ const child = join9(threads, sessionId);
10833
10962
  try {
10834
- rmSync4(child, { recursive: true, force: true });
10963
+ rmSync5(child, { recursive: true, force: true });
10835
10964
  } catch {
10836
10965
  clean = false;
10837
10966
  }
@@ -10844,7 +10973,7 @@ var SYSTEM_PROMPT_DIR, SESSION_ID_RE;
10844
10973
  var init_session_files = __esm({
10845
10974
  "packages/server/src/session-files.ts"() {
10846
10975
  "use strict";
10847
- SYSTEM_PROMPT_DIR = join8(tmpdir2(), "frizz-sysprompts");
10976
+ SYSTEM_PROMPT_DIR = join9(tmpdir2(), "frizz-sysprompts");
10848
10977
  SESSION_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/;
10849
10978
  }
10850
10979
  });
@@ -11080,10 +11209,10 @@ var init_adoption_recovery = __esm({
11080
11209
  });
11081
11210
 
11082
11211
  // packages/server/src/backend/codex-models.ts
11083
- import { join as join9 } from "node:path";
11084
- import { readFileSync as readFileSync4 } from "node:fs";
11212
+ import { join as join10 } from "node:path";
11213
+ import { readFileSync as readFileSync5 } from "node:fs";
11085
11214
  function cachePath(codexHome) {
11086
- return join9(codexHome, "models_cache.json");
11215
+ return join10(codexHome, "models_cache.json");
11087
11216
  }
11088
11217
  function toCodexModel(raw2) {
11089
11218
  if (!raw2 || typeof raw2 !== "object") return void 0;
@@ -11119,7 +11248,7 @@ function readCodexModels(codexHome = defaultCodexHome()) {
11119
11248
  if (hit && now - hit.at < TTL_MS) return hit.models;
11120
11249
  let models;
11121
11250
  try {
11122
- models = parseCodexModelsCache(readFileSync4(path, "utf8"));
11251
+ models = parseCodexModelsCache(readFileSync5(path, "utf8"));
11123
11252
  } catch {
11124
11253
  models = CODEX_MODELS_FALLBACK;
11125
11254
  }
@@ -11509,17 +11638,17 @@ var init_usage_limit = __esm({
11509
11638
  });
11510
11639
 
11511
11640
  // packages/server/src/backend/claude-broker-diagnostics.ts
11512
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync5, readFileSync as readFileSync5, renameSync as renameSync4, statSync as statSync5 } from "node:fs";
11513
- import { join as join10 } from "node:path";
11641
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync6, readFileSync as readFileSync6, renameSync as renameSync5, statSync as statSync5 } from "node:fs";
11642
+ import { join as join11 } from "node:path";
11514
11643
  function claudeBrokerDiagnosticLogPath(stateDir, sessionId) {
11515
- return join10(stateDir, "claude-broker", `${sessionId}.diagnostics.log`);
11644
+ return join11(stateDir, "claude-broker", `${sessionId}.diagnostics.log`);
11516
11645
  }
11517
11646
  function readClaudeBrokerExit(stateDir, sessionId) {
11518
11647
  let newest = null;
11519
11648
  for (const path of [`${claudeBrokerDiagnosticLogPath(stateDir, sessionId)}.1`, claudeBrokerDiagnosticLogPath(stateDir, sessionId)]) {
11520
11649
  let text;
11521
11650
  try {
11522
- text = readFileSync5(path, "utf8");
11651
+ text = readFileSync6(path, "utf8");
11523
11652
  } catch {
11524
11653
  continue;
11525
11654
  }
@@ -11554,11 +11683,11 @@ var init_claude_broker_diagnostics = __esm({
11554
11683
  });
11555
11684
 
11556
11685
  // packages/server/src/detached-daemons.ts
11557
- import { existsSync as existsSync3 } from "node:fs";
11686
+ import { existsSync as existsSync4 } from "node:fs";
11558
11687
  import { fileURLToPath } from "node:url";
11559
11688
  function resolveDetachedDaemonEntry(moduleUrl, basename9) {
11560
11689
  const candidates = [`./${basename9}.js`, `./${basename9}.ts`].map((rel) => fileURLToPath(new URL(rel, moduleUrl)));
11561
- const found = candidates.find((path) => existsSync3(path));
11690
+ const found = candidates.find((path) => existsSync4(path));
11562
11691
  if (!found) throw new Error(`frizz is missing the ${basename9} entry \u2014 looked for ${candidates.join(" and ")}`);
11563
11692
  return found;
11564
11693
  }
@@ -11570,19 +11699,19 @@ var init_detached_daemons = __esm({
11570
11699
 
11571
11700
  // packages/server/src/backend/claude-broker-host.ts
11572
11701
  import { spawn } from "node:child_process";
11573
- import { createHash as createHash3, randomUUID as randomUUID7 } from "node:crypto";
11574
- import { accessSync, constants as fsConstants, mkdirSync as mkdirSync6, readFileSync as readFileSync6, readdirSync as readdirSync4, unlinkSync } from "node:fs";
11575
- import { delimiter, dirname as dirname3, isAbsolute as isAbsolute2, join as join11 } from "node:path";
11702
+ import { createHash as createHash4, randomUUID as randomUUID7 } from "node:crypto";
11703
+ import { accessSync, constants as fsConstants, mkdirSync as mkdirSync7, readFileSync as readFileSync7, readdirSync as readdirSync4, unlinkSync } from "node:fs";
11704
+ import { delimiter, dirname as dirname4, isAbsolute as isAbsolute2, join as join12 } from "node:path";
11576
11705
  function windowsShimTarget(shimPath) {
11577
11706
  let body;
11578
11707
  try {
11579
- body = readFileSync6(shimPath, "utf8");
11708
+ body = readFileSync7(shimPath, "utf8");
11580
11709
  } catch {
11581
11710
  return void 0;
11582
11711
  }
11583
11712
  const target = WINDOWS_SHIM_TARGET.exec(body)?.[1];
11584
11713
  if (!target) return void 0;
11585
- const full = join11(dirname3(shimPath), target);
11714
+ const full = join12(dirname4(shimPath), target);
11586
11715
  try {
11587
11716
  accessSync(full, fsConstants.F_OK);
11588
11717
  return full;
@@ -11597,17 +11726,17 @@ function resolveClaudeExecutableAbsolute(bin, env = process.env) {
11597
11726
  for (const dir of (env.PATH ?? "").split(delimiter)) {
11598
11727
  if (!dir) continue;
11599
11728
  if (windows) {
11600
- const exe = join11(dir, `${candidate}.exe`);
11729
+ const exe = join12(dir, `${candidate}.exe`);
11601
11730
  try {
11602
11731
  accessSync(exe, fsConstants.F_OK);
11603
11732
  return exe;
11604
11733
  } catch {
11605
11734
  }
11606
- const viaShim = windowsShimTarget(join11(dir, `${candidate}.cmd`));
11735
+ const viaShim = windowsShimTarget(join12(dir, `${candidate}.cmd`));
11607
11736
  if (viaShim) return viaShim;
11608
11737
  continue;
11609
11738
  }
11610
- const full = join11(dir, candidate);
11739
+ const full = join12(dir, candidate);
11611
11740
  try {
11612
11741
  accessSync(full, fsConstants.X_OK);
11613
11742
  return full;
@@ -11617,13 +11746,13 @@ function resolveClaudeExecutableAbsolute(bin, env = process.env) {
11617
11746
  throw new Error(`Claude session broker: could not resolve '${candidate}' to an absolute executable path on PATH (the SDK requires one)`);
11618
11747
  }
11619
11748
  function claudeBrokerSocketPath(stateDir, sessionId) {
11620
- const key = createHash3("sha256").update(stateDir).update("\0").update(sessionId).digest("hex").slice(0, 16);
11749
+ const key = createHash4("sha256").update(stateDir).update("\0").update(sessionId).digest("hex").slice(0, 16);
11621
11750
  if (process.platform === "win32") return `\\\\.\\pipe\\frizz-claude-${key}`;
11622
- return join11(process.env.TMPDIR ?? "/tmp", `frizz-claude-${key}.sock`);
11751
+ return join12(process.env.TMPDIR ?? "/tmp", `frizz-claude-${key}.sock`);
11623
11752
  }
11624
11753
  function claudeBrokerRecordPath(stateDir, sessionId) {
11625
- const key = createHash3("sha256").update(sessionId).digest("hex").slice(0, 16);
11626
- return join11(stateDir, "claude-broker", `${key}.json`);
11754
+ const key = createHash4("sha256").update(sessionId).digest("hex").slice(0, 16);
11755
+ return join12(stateDir, "claude-broker", `${key}.json`);
11627
11756
  }
11628
11757
  function pidAlive(pid) {
11629
11758
  try {
@@ -11635,7 +11764,7 @@ function pidAlive(pid) {
11635
11764
  }
11636
11765
  function readBrokerRecord(recordPath2) {
11637
11766
  try {
11638
- return JSON.parse(readFileSync6(recordPath2, "utf8"));
11767
+ return JSON.parse(readFileSync7(recordPath2, "utf8"));
11639
11768
  } catch {
11640
11769
  return null;
11641
11770
  }
@@ -11652,7 +11781,7 @@ function liveBrokerRecord(recordPath2) {
11652
11781
  return null;
11653
11782
  }
11654
11783
  function liveBrokerRecords(stateDir) {
11655
- const dir = join11(stateDir, "claude-broker");
11784
+ const dir = join12(stateDir, "claude-broker");
11656
11785
  let names;
11657
11786
  try {
11658
11787
  names = readdirSync4(dir);
@@ -11662,7 +11791,7 @@ function liveBrokerRecords(stateDir) {
11662
11791
  const out = [];
11663
11792
  for (const name of names) {
11664
11793
  if (!name.endsWith(".json")) continue;
11665
- const record = liveBrokerRecord(join11(dir, name));
11794
+ const record = liveBrokerRecord(join12(dir, name));
11666
11795
  if (record) out.push(record);
11667
11796
  }
11668
11797
  return out;
@@ -11670,7 +11799,7 @@ function liveBrokerRecords(stateDir) {
11670
11799
  function forkBroker(options) {
11671
11800
  const socketPath = claudeBrokerSocketPath(options.stateDir, options.sessionId);
11672
11801
  const recordPath2 = claudeBrokerRecordPath(options.stateDir, options.sessionId);
11673
- mkdirSync6(dirname3(recordPath2), { recursive: true });
11802
+ mkdirSync7(dirname4(recordPath2), { recursive: true });
11674
11803
  const config = {
11675
11804
  socketPath,
11676
11805
  cwd: options.cwd,
@@ -11701,10 +11830,10 @@ function forkBroker(options) {
11701
11830
  });
11702
11831
  child.unref();
11703
11832
  const deadline = Date.now() + (options.timeoutMs ?? 3e4);
11704
- return new Promise((resolve9, reject) => {
11833
+ return new Promise((resolve10, reject) => {
11705
11834
  const poll = () => {
11706
11835
  const record = readBrokerRecord(recordPath2);
11707
- if (record && pidAlive(record.daemonPid)) return resolve9(record);
11836
+ if (record && pidAlive(record.daemonPid)) return resolve10(record);
11708
11837
  if (Date.now() > deadline) return reject(new Error(`Claude broker for session ${options.sessionId} did not become ready`));
11709
11838
  setTimeout(poll, 50);
11710
11839
  };
@@ -12103,7 +12232,7 @@ var init_delivery_ledger = __esm({
12103
12232
  });
12104
12233
 
12105
12234
  // packages/server/src/codex-subagents.ts
12106
- import { closeSync as closeSync4, openSync as openSync5, readSync as readSync2, statSync as statSync6 } from "node:fs";
12235
+ import { closeSync as closeSync5, openSync as openSync6, readSync as readSync2, statSync as statSync6 } from "node:fs";
12107
12236
  function createCodexSubAgentTracker(deps) {
12108
12237
  const findRollouts = deps.findRollouts ?? ((ids) => findRolloutsByIds(ids, deps.codexHome));
12109
12238
  const readAppended = deps.readAppended ?? defaultReadAppended;
@@ -12294,13 +12423,13 @@ function defaultReadAppended(path, offset) {
12294
12423
  const from = restarted ? 0 : offset;
12295
12424
  if (size <= from) return { text: "", offset: from, restarted };
12296
12425
  try {
12297
- const fd = openSync5(path, "r");
12426
+ const fd = openSync6(path, "r");
12298
12427
  try {
12299
12428
  const buf = Buffer.allocUnsafe(size - from);
12300
12429
  const read = readSync2(fd, buf, 0, buf.length, from);
12301
12430
  return { text: buf.toString("utf8", 0, read), offset: from + read, restarted };
12302
12431
  } finally {
12303
- closeSync4(fd);
12432
+ closeSync5(fd);
12304
12433
  }
12305
12434
  } catch {
12306
12435
  return void 0;
@@ -12396,16 +12525,16 @@ var init_completion_relay = __esm({
12396
12525
  });
12397
12526
 
12398
12527
  // packages/server/src/tail-cache.ts
12399
- import { createHash as createHash4 } from "node:crypto";
12400
- import { closeSync as closeSync5, openSync as openSync6, readFileSync as readFileSync7, readSync as readSync3, statSync as statSync7 } from "node:fs";
12401
- import { join as join12 } from "node:path";
12528
+ import { createHash as createHash5 } from "node:crypto";
12529
+ import { closeSync as closeSync6, openSync as openSync7, readFileSync as readFileSync8, readSync as readSync3, statSync as statSync7 } from "node:fs";
12530
+ import { join as join13 } from "node:path";
12402
12531
  function foldSchemaDigest(dir = import.meta.dirname) {
12403
12532
  if (foldSchemaMemo) return foldSchemaMemo;
12404
- const hash = createHash4("sha256").update("frizz-tail-state-v1\0");
12533
+ const hash = createHash5("sha256").update("frizz-tail-state-v1\0");
12405
12534
  let read = 0;
12406
12535
  for (const name of FOLD_SOURCES) {
12407
12536
  try {
12408
- hash.update(name).update("\0").update(readFileSync7(join12(dir, name)));
12537
+ hash.update(name).update("\0").update(readFileSync8(join13(dir, name)));
12409
12538
  read++;
12410
12539
  } catch {
12411
12540
  hash.update(name).update("\0missing\0");
@@ -12437,14 +12566,14 @@ function measureFence(path, offset) {
12437
12566
  try {
12438
12567
  const stat2 = statSync7(path);
12439
12568
  if (stat2.size < offset) return null;
12440
- fd = openSync6(path, "r");
12569
+ fd = openSync7(path, "r");
12441
12570
  const window = Math.min(SAMPLE_BYTES, offset);
12442
12571
  const head = Buffer.allocUnsafe(window);
12443
12572
  const headRead = readSync3(fd, head, 0, window, 0);
12444
12573
  const tail = Buffer.allocUnsafe(window);
12445
12574
  const tailRead = readSync3(fd, tail, 0, window, offset - window);
12446
12575
  if (headRead !== window || tailRead !== window) return null;
12447
- const contentDigest = createHash4("sha256").update(String(offset)).update("\0").update(head).update("\0").update(tail).digest("hex").slice(0, 32);
12576
+ const contentDigest = createHash5("sha256").update(String(offset)).update("\0").update(head).update("\0").update(tail).digest("hex").slice(0, 32);
12448
12577
  return {
12449
12578
  offset,
12450
12579
  size: stat2.size,
@@ -12457,7 +12586,7 @@ function measureFence(path, offset) {
12457
12586
  } finally {
12458
12587
  if (fd !== void 0) {
12459
12588
  try {
12460
- closeSync5(fd);
12589
+ closeSync6(fd);
12461
12590
  } catch {
12462
12591
  }
12463
12592
  }
@@ -12601,9 +12730,9 @@ var init_tail_cache = __esm({
12601
12730
  });
12602
12731
 
12603
12732
  // packages/server/src/tailer.ts
12604
- import { statSync as statSync8, openSync as openSync7, readSync as readSync4, closeSync as closeSync6, readdirSync as readdirSync5, mkdirSync as mkdirSync7, writeFileSync as writeFileSync4, readFileSync as readFileSync8, existsSync as existsSync4 } from "node:fs";
12605
- import { join as join13 } from "node:path";
12606
- import { homedir as homedir6, tmpdir as tmpdir3 } from "node:os";
12733
+ import { statSync as statSync8, openSync as openSync8, readSync as readSync4, closeSync as closeSync7, readdirSync as readdirSync5, mkdirSync as mkdirSync8, writeFileSync as writeFileSync5, readFileSync as readFileSync9, existsSync as existsSync5 } from "node:fs";
12734
+ import { join as join14 } from "node:path";
12735
+ import { homedir as homedir7, tmpdir as tmpdir3 } from "node:os";
12607
12736
  function activityMinute(at) {
12608
12737
  if (!at) return "";
12609
12738
  const ms = Date.parse(at);
@@ -12865,7 +12994,7 @@ function launchTaskId(text) {
12865
12994
  function readDescendantSidecars(sessionDir, mtimeMs) {
12866
12995
  let names;
12867
12996
  try {
12868
- names = readdirSync5(join13(sessionDir, "subagents"));
12997
+ names = readdirSync5(join14(sessionDir, "subagents"));
12869
12998
  } catch {
12870
12999
  return [];
12871
13000
  }
@@ -12876,7 +13005,7 @@ function readDescendantSidecars(sessionDir, mtimeMs) {
12876
13005
  if (!agentId) continue;
12877
13006
  let parsed;
12878
13007
  try {
12879
- parsed = JSON.parse(readFileSync8(join13(sessionDir, "subagents", name), "utf8"));
13008
+ parsed = JSON.parse(readFileSync9(join14(sessionDir, "subagents", name), "utf8"));
12880
13009
  } catch {
12881
13010
  continue;
12882
13011
  }
@@ -12890,7 +13019,7 @@ function readDescendantSidecars(sessionDir, mtimeMs) {
12890
13019
  agentType: text(meta.agentType),
12891
13020
  parentAgentId: text(meta.parentAgentId),
12892
13021
  spawnDepth: typeof meta.spawnDepth === "number" && Number.isFinite(meta.spawnDepth) ? meta.spawnDepth : void 0,
12893
- spawnedAtMs: mtimeMs(join13(sessionDir, "subagents", name))
13022
+ spawnedAtMs: mtimeMs(join14(sessionDir, "subagents", name))
12894
13023
  });
12895
13024
  }
12896
13025
  return out;
@@ -13338,13 +13467,13 @@ function defaultMtimeMs(path) {
13338
13467
  }
13339
13468
  }
13340
13469
  function defaultLogDir(project) {
13341
- return join13(homedir6(), ".claude", "projects", project.cwdSlug);
13470
+ return join14(homedir7(), ".claude", "projects", project.cwdSlug);
13342
13471
  }
13343
13472
  function defaultReadPermMarker(project) {
13344
13473
  if (!project.stateDir) return () => void 0;
13345
13474
  return (slug) => {
13346
13475
  try {
13347
- const parsed = JSON.parse(readFileSync8(permMarkerPath(project, slug), "utf8"));
13476
+ const parsed = JSON.parse(readFileSync9(permMarkerPath(project, slug), "utf8"));
13348
13477
  return isPermMarker(parsed) ? parsed : void 0;
13349
13478
  } catch {
13350
13479
  return void 0;
@@ -13362,7 +13491,7 @@ function defaultBrokerDaemonAlive(project, now) {
13362
13491
  try {
13363
13492
  const path = claudeBrokerRecordPath(project.stateDir, sessionId);
13364
13493
  const record = readBrokerRecord(path);
13365
- if (!record) alive = existsSync4(path);
13494
+ if (!record) alive = existsSync5(path);
13366
13495
  else if (typeof record.daemonPid !== "number") alive = true;
13367
13496
  else {
13368
13497
  try {
@@ -13508,7 +13637,7 @@ function createTailer(deps) {
13508
13637
  return "";
13509
13638
  }
13510
13639
  const defaultBackend = {
13511
- transcriptPath: (sessionId) => join13(logDir, `${sessionId}.jsonl`),
13640
+ transcriptPath: (sessionId) => join14(logDir, `${sessionId}.jsonl`),
13512
13641
  foldLine: (state, line) => {
13513
13642
  const rec = parseLine(line);
13514
13643
  if (rec) applyRecord(state, rec);
@@ -13629,7 +13758,7 @@ ${ask}`;
13629
13758
  return state.path.replace(/\.jsonl$/, "");
13630
13759
  }
13631
13760
  function descendantSidecars(state) {
13632
- const at = mtimeMs(join13(sessionDirOf(state), "subagents"));
13761
+ const at = mtimeMs(join14(sessionDirOf(state), "subagents"));
13633
13762
  const cached2 = descendantIndex.get(state.slug);
13634
13763
  if (cached2 && cached2.at === at) return cached2.all;
13635
13764
  const all = readDescendantSidecars(sessionDirOf(state), mtimeMs);
@@ -13643,7 +13772,7 @@ ${ask}`;
13643
13772
  return descendantIndex.get(state.slug)?.byToolUse.get(id);
13644
13773
  }
13645
13774
  function descendantTranscript(state, meta) {
13646
- return join13(sessionDirOf(state), "subagents", `agent-${meta.agentId}.jsonl`);
13775
+ return join14(sessionDirOf(state), "subagents", `agent-${meta.agentId}.jsonl`);
13647
13776
  }
13648
13777
  function subAgentDescendantTasks(slug, id) {
13649
13778
  const state = states.get(slug);
@@ -13902,7 +14031,7 @@ ${ask}`;
13902
14031
  if (name.startsWith(".") || !name.endsWith(".jsonl")) continue;
13903
14032
  const id = name.slice(0, -".jsonl".length);
13904
14033
  if (!id || registered.has(id)) continue;
13905
- const path = join13(logDir, name);
14034
+ const path = join14(logDir, name);
13906
14035
  let mtime;
13907
14036
  try {
13908
14037
  mtime = statSync8(path).mtimeMs;
@@ -14106,14 +14235,14 @@ ${ask}`;
14106
14235
  if (size <= state.offset) return;
14107
14236
  let chunk = "";
14108
14237
  try {
14109
- const fd = openSync7(state.path, "r");
14238
+ const fd = openSync8(state.path, "r");
14110
14239
  try {
14111
14240
  const buf = Buffer.allocUnsafe(size - state.offset);
14112
14241
  const read = readSync4(fd, buf, 0, buf.length, state.offset);
14113
14242
  chunk = buf.toString("utf8", 0, read);
14114
14243
  state.offset += read;
14115
14244
  } finally {
14116
- closeSync6(fd);
14245
+ closeSync7(fd);
14117
14246
  }
14118
14247
  } catch {
14119
14248
  return;
@@ -14152,8 +14281,8 @@ ${ask}`;
14152
14281
  `thread ${row.slug} (session ${row.session_id}): no transcript ${DISCOVERY_GRACE_MS / 1e3}s after dispatch \u2014 likely a boot failure. ${isHeadlessRow(row) && !pane.trim() && !authFailure ? "" : "Pane:\n"}${detail.slice(0, 4e3)}`
14153
14282
  );
14154
14283
  try {
14155
- mkdirSync7(STALL_LOG_DIR, { recursive: true });
14156
- writeFileSync4(join13(STALL_LOG_DIR, `${row.slug}.stall.log`), `session_id: ${row.session_id}
14284
+ mkdirSync8(STALL_LOG_DIR, { recursive: true });
14285
+ writeFileSync5(join14(STALL_LOG_DIR, `${row.slug}.stall.log`), `session_id: ${row.session_id}
14157
14286
  captured_at: ${new Date(now()).toISOString()}
14158
14287
 
14159
14288
  ${detail}
@@ -14192,7 +14321,7 @@ ${detail}
14192
14321
  committed = false;
14193
14322
  }
14194
14323
  if (!committed) return false;
14195
- state.path = join13(logDir, `${found}.jsonl`);
14324
+ state.path = join14(logDir, `${found}.jsonl`);
14196
14325
  state.offset = 0;
14197
14326
  state.partial = "";
14198
14327
  state.primed = false;
@@ -14220,7 +14349,7 @@ ${detail}
14220
14349
  let state = states.get(row.slug);
14221
14350
  const runtimeGeneration = row.runtime_generation ?? 0;
14222
14351
  if (!state || state.sessionId !== row.session_id || state.nativeSessionId !== nativeId || state.runtimeGeneration !== runtimeGeneration) {
14223
- const path = backend.transcriptPath(nativeId) ?? join13(logDir, `${nativeId}.jsonl`);
14352
+ const path = backend.transcriptPath(nativeId) ?? join14(logDir, `${nativeId}.jsonl`);
14224
14353
  state = newTailState(row.slug, row.session_id, path, false, nativeId, runtimeGeneration);
14225
14354
  state.dismissedOps = deps.storage.retiredOps(row.slug, row.session_id);
14226
14355
  hydrateFromCache(state, row, nativeId);
@@ -14588,7 +14717,7 @@ var init_tailer = __esm({
14588
14717
  CACHE_FLUSH_MS = 3e4;
14589
14718
  PRIME_PROGRESS_EVERY = 20;
14590
14719
  DISCOVER_RETRY_MS = 15e3;
14591
- STALL_LOG_DIR = join13(tmpdir3(), "frizz-worker-logs");
14720
+ STALL_LOG_DIR = join14(tmpdir3(), "frizz-worker-logs");
14592
14721
  PERM_YES_OPTION = /(^|\n)\s*(❯\s*)?1\.\s+Yes\b/;
14593
14722
  PERM_QUESTION = /\b(?:Do you want|Would you like)\b/;
14594
14723
  PERM_FOOTER = /\bEsc to (cancel|reject)\b/;
@@ -14653,14 +14782,14 @@ var init_tailer = __esm({
14653
14782
  });
14654
14783
 
14655
14784
  // packages/server/src/backend/codex.ts
14656
- import { join as join14 } from "node:path";
14657
- import { homedir as homedir7 } from "node:os";
14785
+ import { join as join15 } from "node:path";
14786
+ import { homedir as homedir8 } from "node:os";
14658
14787
  import { readdirSync as readdirSync6, statSync as statSync9 } from "node:fs";
14659
14788
  function defaultCodexHome() {
14660
- return process.env.CODEX_HOME && process.env.CODEX_HOME.trim() ? process.env.CODEX_HOME : join14(homedir7(), ".codex");
14789
+ return process.env.CODEX_HOME && process.env.CODEX_HOME.trim() ? process.env.CODEX_HOME : join15(homedir8(), ".codex");
14661
14790
  }
14662
14791
  function sessionsDir(codexHome) {
14663
- return join14(codexHome, "sessions");
14792
+ return join15(codexHome, "sessions");
14664
14793
  }
14665
14794
  function codexSandbox(mode) {
14666
14795
  switch (mode) {
@@ -15077,17 +15206,17 @@ function collectRollouts(dir, out, budget) {
15077
15206
  const files = entries.filter((e) => e.isFile() && e.name.startsWith("rollout-") && e.name.endsWith(".jsonl")).sort(descByName);
15078
15207
  for (const d of dirs) {
15079
15208
  if (budget.n <= 0) return;
15080
- collectRollouts(join14(dir, d.name), out, budget);
15209
+ collectRollouts(join15(dir, d.name), out, budget);
15081
15210
  }
15082
15211
  for (const f of files) {
15083
15212
  if (budget.n <= 0) return;
15084
15213
  let mtimeMs;
15085
15214
  try {
15086
- mtimeMs = statSync9(join14(dir, f.name)).mtimeMs;
15215
+ mtimeMs = statSync9(join15(dir, f.name)).mtimeMs;
15087
15216
  } catch {
15088
15217
  continue;
15089
15218
  }
15090
- out.push({ path: join14(dir, f.name), mtimeMs });
15219
+ out.push({ path: join15(dir, f.name), mtimeMs });
15091
15220
  budget.n--;
15092
15221
  }
15093
15222
  }
@@ -17508,7 +17637,7 @@ var require_extension = __commonJS({
17508
17637
  if (dest[name] === void 0) dest[name] = [elem];
17509
17638
  else dest[name].push(elem);
17510
17639
  }
17511
- function parse(header) {
17640
+ function parse2(header) {
17512
17641
  const offers = /* @__PURE__ */ Object.create(null);
17513
17642
  let params = /* @__PURE__ */ Object.create(null);
17514
17643
  let mustUnescape = false;
@@ -17648,7 +17777,7 @@ var require_extension = __commonJS({
17648
17777
  }).join(", ");
17649
17778
  }).join(", ");
17650
17779
  }
17651
- module.exports = { format, parse };
17780
+ module.exports = { format, parse: parse2 };
17652
17781
  }
17653
17782
  });
17654
17783
 
@@ -17661,7 +17790,7 @@ var require_websocket = __commonJS({
17661
17790
  var http = __require("http");
17662
17791
  var net2 = __require("net");
17663
17792
  var tls = __require("tls");
17664
- var { randomBytes: randomBytes2, createHash: createHash15 } = __require("crypto");
17793
+ var { randomBytes: randomBytes2, createHash: createHash16 } = __require("crypto");
17665
17794
  var { Duplex, Readable } = __require("stream");
17666
17795
  var { URL: URL2 } = __require("url");
17667
17796
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -17682,7 +17811,7 @@ var require_websocket = __commonJS({
17682
17811
  var {
17683
17812
  EventTarget: { addEventListener: addEventListener2, removeEventListener }
17684
17813
  } = require_event_target();
17685
- var { format, parse } = require_extension();
17814
+ var { format, parse: parse2 } = require_extension();
17686
17815
  var { toBuffer } = require_buffer_util();
17687
17816
  var kAborted = Symbol("kAborted");
17688
17817
  var protocolVersions = [8, 13];
@@ -18329,7 +18458,7 @@ var require_websocket = __commonJS({
18329
18458
  abortHandshake(websocket, socket, "Invalid Upgrade header");
18330
18459
  return;
18331
18460
  }
18332
- const digest = createHash15("sha1").update(key + GUID).digest("base64");
18461
+ const digest = createHash16("sha1").update(key + GUID).digest("base64");
18333
18462
  if (res.headers["sec-websocket-accept"] !== digest) {
18334
18463
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
18335
18464
  return;
@@ -18359,7 +18488,7 @@ var require_websocket = __commonJS({
18359
18488
  }
18360
18489
  let extensions;
18361
18490
  try {
18362
- extensions = parse(secWebSocketExtensions);
18491
+ extensions = parse2(secWebSocketExtensions);
18363
18492
  } catch (err) {
18364
18493
  const message = "Invalid Sec-WebSocket-Extensions header";
18365
18494
  abortHandshake(websocket, socket, message);
@@ -18651,7 +18780,7 @@ var require_subprotocol = __commonJS({
18651
18780
  "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js"(exports, module) {
18652
18781
  "use strict";
18653
18782
  var { tokenChars } = require_validation();
18654
- function parse(header) {
18783
+ function parse2(header) {
18655
18784
  const protocols = /* @__PURE__ */ new Set();
18656
18785
  let start = -1;
18657
18786
  let end = -1;
@@ -18687,7 +18816,7 @@ var require_subprotocol = __commonJS({
18687
18816
  protocols.add(protocol);
18688
18817
  return protocols;
18689
18818
  }
18690
- module.exports = { parse };
18819
+ module.exports = { parse: parse2 };
18691
18820
  }
18692
18821
  });
18693
18822
 
@@ -18698,7 +18827,7 @@ var require_websocket_server = __commonJS({
18698
18827
  var EventEmitter = __require("events");
18699
18828
  var http = __require("http");
18700
18829
  var { Duplex } = __require("stream");
18701
- var { createHash: createHash15 } = __require("crypto");
18830
+ var { createHash: createHash16 } = __require("crypto");
18702
18831
  var extension2 = require_extension();
18703
18832
  var PerMessageDeflate2 = require_permessage_deflate();
18704
18833
  var subprotocol2 = require_subprotocol();
@@ -19005,7 +19134,7 @@ var require_websocket_server = __commonJS({
19005
19134
  );
19006
19135
  }
19007
19136
  if (this._state > RUNNING) return abortHandshake(socket, 503);
19008
- const digest = createHash15("sha1").update(key + GUID).digest("base64");
19137
+ const digest = createHash16("sha1").update(key + GUID).digest("base64");
19009
19138
  const headers = [
19010
19139
  "HTTP/1.1 101 Switching Protocols",
19011
19140
  "Upgrade: websocket",
@@ -19175,21 +19304,21 @@ var init_codex_mcp = __esm({
19175
19304
  // packages/server/src/backend/codex-app-server-native.ts
19176
19305
  import { spawn as spawn2 } from "node:child_process";
19177
19306
  import { connect } from "node:net";
19178
- import { createHash as createHash5, randomUUID as randomUUID8 } from "node:crypto";
19179
- import { existsSync as existsSync5, mkdirSync as mkdirSync8, readFileSync as readFileSync9, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
19180
- import { join as join15 } from "node:path";
19307
+ import { createHash as createHash6, randomUUID as randomUUID8 } from "node:crypto";
19308
+ import { existsSync as existsSync6, mkdirSync as mkdirSync9, readFileSync as readFileSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "node:fs";
19309
+ import { join as join16 } from "node:path";
19181
19310
  import { PassThrough, Writable } from "node:stream";
19182
19311
  import { StringDecoder } from "node:string_decoder";
19183
19312
  function nativeDir(stateDir) {
19184
- return join15(stateDir, "codex-app-server-native");
19313
+ return join16(stateDir, "codex-app-server-native");
19185
19314
  }
19186
19315
  function nativeRecordPath(stateDir, projectId) {
19187
- return join15(nativeDir(stateDir), `${projectId}.json`);
19316
+ return join16(nativeDir(stateDir), `${projectId}.json`);
19188
19317
  }
19189
19318
  function nativeListenSocketPath(stateDir, projectId) {
19190
- const key = createHash5("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
19319
+ const key = createHash6("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
19191
19320
  if (process.platform === "win32") return `\\\\.\\pipe\\frizz-codex-native-${key}`;
19192
- return join15(process.env.TMPDIR ?? "/tmp", `frizz-codex-native-${key}.sock`);
19321
+ return join16(process.env.TMPDIR ?? "/tmp", `frizz-codex-native-${key}.sock`);
19193
19322
  }
19194
19323
  function pidAlive2(pid) {
19195
19324
  try {
@@ -19201,7 +19330,7 @@ function pidAlive2(pid) {
19201
19330
  }
19202
19331
  function readNativeRecord(stateDir, projectId) {
19203
19332
  try {
19204
- const value = JSON.parse(readFileSync9(nativeRecordPath(stateDir, projectId), "utf8"));
19333
+ const value = JSON.parse(readFileSync10(nativeRecordPath(stateDir, projectId), "utf8"));
19205
19334
  if (typeof value.listenerPid !== "number" || typeof value.socketPath !== "string" || typeof value.generation !== "string") return null;
19206
19335
  return {
19207
19336
  projectId,
@@ -19217,7 +19346,7 @@ function readNativeRecord(stateDir, projectId) {
19217
19346
  function liveNativeRecord(stateDir, projectId) {
19218
19347
  const record = readNativeRecord(stateDir, projectId);
19219
19348
  if (!record) return null;
19220
- if (pidAlive2(record.listenerPid) && existsSync5(record.socketPath)) return record;
19349
+ if (pidAlive2(record.listenerPid) && existsSync6(record.socketPath)) return record;
19221
19350
  try {
19222
19351
  unlinkSync2(nativeRecordPath(stateDir, projectId));
19223
19352
  } catch {
@@ -19242,7 +19371,7 @@ async function stopNativeListener(stateDir, projectId, timeoutMs = 1e4) {
19242
19371
  if (!record) return;
19243
19372
  const deadline = Date.now() + timeoutMs;
19244
19373
  while (pidAlive2(record.listenerPid) && Date.now() < deadline) {
19245
- await new Promise((resolve9) => setTimeout(resolve9, 25));
19374
+ await new Promise((resolve10) => setTimeout(resolve10, 25));
19246
19375
  }
19247
19376
  if (pidAlive2(record.listenerPid)) {
19248
19377
  try {
@@ -19250,16 +19379,16 @@ async function stopNativeListener(stateDir, projectId, timeoutMs = 1e4) {
19250
19379
  } catch {
19251
19380
  }
19252
19381
  while (pidAlive2(record.listenerPid) && Date.now() < deadline + 2e3) {
19253
- await new Promise((resolve9) => setTimeout(resolve9, 25));
19382
+ await new Promise((resolve10) => setTimeout(resolve10, 25));
19254
19383
  }
19255
19384
  }
19256
19385
  }
19257
19386
  function socketAccepting(socketPath) {
19258
- return new Promise((resolve9) => {
19387
+ return new Promise((resolve10) => {
19259
19388
  const probe = connect(socketPath);
19260
19389
  const done = (value) => {
19261
19390
  probe.destroy();
19262
- resolve9(value);
19391
+ resolve10(value);
19263
19392
  };
19264
19393
  probe.once("connect", () => done(true));
19265
19394
  probe.once("error", () => done(false));
@@ -19267,7 +19396,7 @@ function socketAccepting(socketPath) {
19267
19396
  });
19268
19397
  }
19269
19398
  function attach(record, timeoutMs) {
19270
- return new Promise((resolve9, reject) => {
19399
+ return new Promise((resolve10, reject) => {
19271
19400
  const socket = new import_websocket.default(`ws+unix://${record.socketPath}:/`, { perMessageDeflate: false });
19272
19401
  const stdout = new PassThrough();
19273
19402
  const stderr = new PassThrough();
@@ -19320,7 +19449,7 @@ function attach(record, timeoutMs) {
19320
19449
  if (settled) return;
19321
19450
  settled = true;
19322
19451
  clearTimeout(timer);
19323
- resolve9(handle);
19452
+ resolve10(handle);
19324
19453
  });
19325
19454
  socket.on("message", (data) => {
19326
19455
  const text = typeof data === "string" ? data : Buffer.isBuffer(data) ? data.toString("utf8") : Buffer.concat(data).toString("utf8");
@@ -19348,9 +19477,9 @@ function attach(record, timeoutMs) {
19348
19477
  }
19349
19478
  async function startListener(options) {
19350
19479
  const { stateDir, projectId } = options;
19351
- mkdirSync8(nativeDir(stateDir), { recursive: true });
19480
+ mkdirSync9(nativeDir(stateDir), { recursive: true });
19352
19481
  const socketPath = nativeListenSocketPath(stateDir, projectId);
19353
- if (existsSync5(socketPath) && !await socketAccepting(socketPath)) {
19482
+ if (existsSync6(socketPath) && !await socketAccepting(socketPath)) {
19354
19483
  try {
19355
19484
  unlinkSync2(socketPath);
19356
19485
  } catch {
@@ -19371,13 +19500,13 @@ async function startListener(options) {
19371
19500
  socketPath,
19372
19501
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
19373
19502
  };
19374
- writeFileSync5(nativeRecordPath(stateDir, projectId), JSON.stringify(record));
19503
+ writeFileSync6(nativeRecordPath(stateDir, projectId), JSON.stringify(record));
19375
19504
  const deadline = Date.now() + (options.timeoutMs ?? 3e4);
19376
19505
  for (; ; ) {
19377
- if (existsSync5(socketPath) && await socketAccepting(socketPath)) return record;
19506
+ if (existsSync6(socketPath) && await socketAccepting(socketPath)) return record;
19378
19507
  if (!pidAlive2(record.listenerPid)) throw new Error("codex app-server listener exited before it became ready");
19379
19508
  if (Date.now() > deadline) throw new Error("codex app-server listener did not become ready");
19380
- await new Promise((resolve9) => setTimeout(resolve9, 50));
19509
+ await new Promise((resolve10) => setTimeout(resolve10, 50));
19381
19510
  }
19382
19511
  }
19383
19512
  var PRESUMED_LOSSY_REJOIN, nativeListenCodexAppServerHost;
@@ -19438,21 +19567,21 @@ var init_codex_app_server_native = __esm({
19438
19567
  // packages/server/src/backend/codex-app-server-host.ts
19439
19568
  import { spawn as spawn3 } from "node:child_process";
19440
19569
  import { createConnection } from "node:net";
19441
- import { createHash as createHash6, randomUUID as randomUUID9 } from "node:crypto";
19442
- import { existsSync as existsSync6, mkdirSync as mkdirSync9, readFileSync as readFileSync10, unlinkSync as unlinkSync3 } from "node:fs";
19443
- import { join as join16 } from "node:path";
19570
+ import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
19571
+ import { existsSync as existsSync7, mkdirSync as mkdirSync10, readFileSync as readFileSync11, unlinkSync as unlinkSync3 } from "node:fs";
19572
+ import { join as join17 } from "node:path";
19444
19573
  import { PassThrough as PassThrough2, Writable as Writable2 } from "node:stream";
19445
19574
  import { StringDecoder as StringDecoder2 } from "node:string_decoder";
19446
19575
  function daemonDir(stateDir) {
19447
- return join16(stateDir, "codex-app-server");
19576
+ return join17(stateDir, "codex-app-server");
19448
19577
  }
19449
19578
  function recordPath(stateDir, projectId) {
19450
- return join16(daemonDir(stateDir), `${projectId}.json`);
19579
+ return join17(daemonDir(stateDir), `${projectId}.json`);
19451
19580
  }
19452
19581
  function codexAppServerSocketPath(stateDir, projectId) {
19453
- const key = createHash6("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
19582
+ const key = createHash7("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
19454
19583
  if (process.platform === "win32") return `\\\\.\\pipe\\frizz-codex-${key}`;
19455
- return join16(process.env.TMPDIR ?? "/tmp", `frizz-codex-${key}.sock`);
19584
+ return join17(process.env.TMPDIR ?? "/tmp", `frizz-codex-${key}.sock`);
19456
19585
  }
19457
19586
  function pidAlive3(pid) {
19458
19587
  try {
@@ -19464,7 +19593,7 @@ function pidAlive3(pid) {
19464
19593
  }
19465
19594
  function readDaemonRecord(stateDir, projectId) {
19466
19595
  try {
19467
- const value = JSON.parse(readFileSync10(recordPath(stateDir, projectId), "utf8"));
19596
+ const value = JSON.parse(readFileSync11(recordPath(stateDir, projectId), "utf8"));
19468
19597
  if (typeof value.daemonPid !== "number" || typeof value.socketPath !== "string" || typeof value.generation !== "string") return null;
19469
19598
  return {
19470
19599
  projectId,
@@ -19480,7 +19609,7 @@ function readDaemonRecord(stateDir, projectId) {
19480
19609
  }
19481
19610
  function readDaemonExitBreadcrumb(stateDir, projectId) {
19482
19611
  try {
19483
- const value = JSON.parse(readFileSync10(`${recordPath(stateDir, projectId)}.exit`, "utf8"));
19612
+ const value = JSON.parse(readFileSync11(`${recordPath(stateDir, projectId)}.exit`, "utf8"));
19484
19613
  if (typeof value.generation !== "string" || typeof value.reason !== "string") return null;
19485
19614
  return {
19486
19615
  generation: value.generation,
@@ -19522,7 +19651,7 @@ async function stopCodexAppServerDaemon(stateDir, projectId, timeoutMs = 1e4) {
19522
19651
  if (!record) return;
19523
19652
  const deadline = Date.now() + timeoutMs;
19524
19653
  while (pidAlive3(record.daemonPid) && Date.now() < deadline) {
19525
- await new Promise((resolve9) => setTimeout(resolve9, 25));
19654
+ await new Promise((resolve10) => setTimeout(resolve10, 25));
19526
19655
  }
19527
19656
  if (pidAlive3(record.daemonPid)) {
19528
19657
  try {
@@ -19530,13 +19659,13 @@ async function stopCodexAppServerDaemon(stateDir, projectId, timeoutMs = 1e4) {
19530
19659
  } catch {
19531
19660
  }
19532
19661
  while (pidAlive3(record.daemonPid) && Date.now() < deadline + 2e3) {
19533
- await new Promise((resolve9) => setTimeout(resolve9, 25));
19662
+ await new Promise((resolve10) => setTimeout(resolve10, 25));
19534
19663
  }
19535
19664
  }
19536
19665
  }
19537
19666
  function forkDaemon(options) {
19538
19667
  const { stateDir, projectId } = options;
19539
- mkdirSync9(daemonDir(stateDir), { recursive: true });
19668
+ mkdirSync10(daemonDir(stateDir), { recursive: true });
19540
19669
  const record = recordPath(stateDir, projectId);
19541
19670
  try {
19542
19671
  unlinkSync3(record);
@@ -19572,10 +19701,10 @@ function forkDaemon(options) {
19572
19701
  });
19573
19702
  child.unref();
19574
19703
  const deadline = Date.now() + (options.timeoutMs ?? 3e4);
19575
- return new Promise((resolve9, reject) => {
19704
+ return new Promise((resolve10, reject) => {
19576
19705
  const poll = () => {
19577
19706
  const found = readDaemonRecord(stateDir, projectId);
19578
- if (found && pidAlive3(found.daemonPid)) return resolve9(found);
19707
+ if (found && pidAlive3(found.daemonPid)) return resolve10(found);
19579
19708
  if (!pidAlive3(child.pid ?? -1) && !found) return reject(new Error("codex app-server daemon exited before it became ready"));
19580
19709
  if (Date.now() > deadline) return reject(new Error("codex app-server daemon did not become ready"));
19581
19710
  setTimeout(poll, 50);
@@ -19593,7 +19722,7 @@ function helloDropCount(line) {
19593
19722
  }
19594
19723
  }
19595
19724
  function attach2(record, timeoutMs) {
19596
- return new Promise((resolve9, reject) => {
19725
+ return new Promise((resolve10, reject) => {
19597
19726
  const socket = createConnection(record.socketPath);
19598
19727
  const stdout = new PassThrough2();
19599
19728
  const stderr = new PassThrough2();
@@ -19643,7 +19772,7 @@ function attach2(record, timeoutMs) {
19643
19772
  if (!settled) {
19644
19773
  settled = true;
19645
19774
  clearTimeout(timer);
19646
- resolve9({ process: handle, droppedWhileDetached: helloDropCount(trimmed) });
19775
+ resolve10({ process: handle, droppedWhileDetached: helloDropCount(trimmed) });
19647
19776
  }
19648
19777
  continue;
19649
19778
  }
@@ -19711,7 +19840,7 @@ var init_codex_app_server_host = __esm({
19711
19840
  }
19712
19841
  if (process.platform !== "win32") {
19713
19842
  const stale = codexAppServerSocketPath(options.stateDir, options.projectId);
19714
- if (existsSync6(stale) && !liveDaemonRecord(options.stateDir, options.projectId)) {
19843
+ if (existsSync7(stale) && !liveDaemonRecord(options.stateDir, options.projectId)) {
19715
19844
  try {
19716
19845
  unlinkSync3(stale);
19717
19846
  } catch {
@@ -19731,7 +19860,7 @@ var init_codex_app_server_host = __esm({
19731
19860
  });
19732
19861
 
19733
19862
  // packages/server/src/backend/codex-app-server.ts
19734
- import { createHash as createHash7, randomUUID as randomUUID10 } from "node:crypto";
19863
+ import { createHash as createHash8, randomUUID as randomUUID10 } from "node:crypto";
19735
19864
  import { StringDecoder as StringDecoder3 } from "node:string_decoder";
19736
19865
  function selectCodexHostKind(flagValue, platform3, hasSpawn) {
19737
19866
  if (hasSpawn) return "direct";
@@ -19741,11 +19870,11 @@ function selectCodexHostKind(flagValue, platform3, hasSpawn) {
19741
19870
  return nativeSupported ? "native" : "daemon";
19742
19871
  }
19743
19872
  function compareCodexVersions(a, b) {
19744
- const parse = (v) => {
19873
+ const parse2 = (v) => {
19745
19874
  const m = v.match(/^(\d+)\.(\d+)\.(\d+)/);
19746
19875
  return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : [-1, -1, -1];
19747
19876
  };
19748
- const [x, y] = [parse(a), parse(b)];
19877
+ const [x, y] = [parse2(a), parse2(b)];
19749
19878
  for (let i = 0; i < 3; i++) if (x[i] !== y[i]) return x[i] < y[i] ? -1 : 1;
19750
19879
  return 0;
19751
19880
  }
@@ -20078,7 +20207,7 @@ function canonicalJson2(value) {
20078
20207
  return JSON.stringify(normalize2(value));
20079
20208
  }
20080
20209
  function logicalRequestId(method, parts) {
20081
- const digest = createHash7("sha256").update(JSON.stringify([method, ...parts])).digest("hex");
20210
+ const digest = createHash8("sha256").update(JSON.stringify([method, ...parts])).digest("hex");
20082
20211
  return `codex-${digest}`;
20083
20212
  }
20084
20213
  function requestFingerprint(value) {
@@ -20088,7 +20217,7 @@ function requestFingerprint(value) {
20088
20217
  delete record.startedAtMs;
20089
20218
  delete record.autoResolutionMs;
20090
20219
  }
20091
- return createHash7("sha256").update(canonicalJson2(normalized)).digest("hex");
20220
+ return createHash8("sha256").update(canonicalJson2(normalized)).digest("hex");
20092
20221
  }
20093
20222
  function decision(id, semantic, label) {
20094
20223
  return { id, semantic, label };
@@ -20556,12 +20685,12 @@ var init_codex_app_server = __esm({
20556
20685
  if (this.pending.size >= MAX_OUTBOUND_REQUESTS) throw new Error("Codex app-server outbound request queue is full");
20557
20686
  if (!Number.isSafeInteger(this.nextId)) throw new Error("Codex app-server request id space is exhausted");
20558
20687
  const id = this.nextId++;
20559
- const result = new Promise((resolve9, reject) => {
20688
+ const result = new Promise((resolve10, reject) => {
20560
20689
  const timer = setTimeout(() => {
20561
20690
  this.pending.delete(id);
20562
20691
  reject(new Error(`Codex app-server request timed out: ${method}`));
20563
20692
  }, this.timeoutMs);
20564
- this.pending.set(id, { resolve: resolve9, reject, timer });
20693
+ this.pending.set(id, { resolve: resolve10, reject, timer });
20565
20694
  });
20566
20695
  try {
20567
20696
  await this.write({ id, method, params });
@@ -20598,7 +20727,7 @@ var init_codex_app_server = __esm({
20598
20727
  }
20599
20728
  whenIdle() {
20600
20729
  if (!this.draining) return Promise.resolve();
20601
- return new Promise((resolve9) => this.idleWaiters.add(resolve9));
20730
+ return new Promise((resolve10) => this.idleWaiters.add(resolve10));
20602
20731
  }
20603
20732
  consume(chunk) {
20604
20733
  if (this.closed) return;
@@ -20657,7 +20786,7 @@ var init_codex_app_server = __esm({
20657
20786
  queueMicrotask(() => void this.drain());
20658
20787
  }
20659
20788
  if (!this.draining) {
20660
- for (const resolve9 of this.idleWaiters) resolve9();
20789
+ for (const resolve10 of this.idleWaiters) resolve10();
20661
20790
  this.idleWaiters.clear();
20662
20791
  }
20663
20792
  }
@@ -20721,8 +20850,8 @@ var init_codex_app_server = __esm({
20721
20850
  if (Buffer.byteLength(line, "utf8") > MAX_JSONL_BYTES) {
20722
20851
  return Promise.reject(new Error("Codex app-server outbound message exceeded its limit"));
20723
20852
  }
20724
- return new Promise((resolve9, reject) => {
20725
- this.child.stdin.write(line, "utf8", (error) => error ? reject(error) : resolve9());
20853
+ return new Promise((resolve10, reject) => {
20854
+ this.child.stdin.write(line, "utf8", (error) => error ? reject(error) : resolve10());
20726
20855
  });
20727
20856
  }
20728
20857
  fail(reason, error) {
@@ -21303,7 +21432,7 @@ var init_codex_app_server = __esm({
21303
21432
  while (Date.now() - start < ms) {
21304
21433
  const row = this.bindingForScope(threadSlug, sessionId);
21305
21434
  if (!row || row.current_turn_id !== turnId) return;
21306
- await new Promise((resolve9) => setTimeout(resolve9, 50));
21435
+ await new Promise((resolve10) => setTimeout(resolve10, 50));
21307
21436
  }
21308
21437
  }
21309
21438
  async waitForTurnCleared(threadSlug, sessionId, ms) {
@@ -21311,7 +21440,7 @@ var init_codex_app_server = __esm({
21311
21440
  while (Date.now() - start < ms) {
21312
21441
  const row = this.bindingForScope(threadSlug, sessionId);
21313
21442
  if (!row || row.current_turn_id === null) return;
21314
- await new Promise((resolve9) => setTimeout(resolve9, 100));
21443
+ await new Promise((resolve10) => setTimeout(resolve10, 100));
21315
21444
  }
21316
21445
  }
21317
21446
  // Dispatch entry: create a PERSISTED (ephemeral:false, restart-resumable) session with the worker
@@ -21515,14 +21644,14 @@ var init_codex_app_server = __esm({
21515
21644
  released = true;
21516
21645
  this.activeOperations--;
21517
21646
  if (this.activeOperations === 0) {
21518
- for (const resolve9 of this.operationWaiters) resolve9();
21647
+ for (const resolve10 of this.operationWaiters) resolve10();
21519
21648
  this.operationWaiters.clear();
21520
21649
  }
21521
21650
  };
21522
21651
  }
21523
21652
  whenOperationsIdle() {
21524
21653
  if (this.activeOperations === 0) return Promise.resolve();
21525
- return new Promise((resolve9) => this.operationWaiters.add(resolve9));
21654
+ return new Promise((resolve10) => this.operationWaiters.add(resolve10));
21526
21655
  }
21527
21656
  closeDatabase() {
21528
21657
  if (this.dbClosed) return;
@@ -22036,18 +22165,18 @@ var init_codex_app_server = __esm({
22036
22165
  if (set.size === 0) this.settingsWaiters.delete(threadId);
22037
22166
  }
22038
22167
  };
22039
- const promise = new Promise((resolve9) => {
22040
- settle = resolve9;
22168
+ const promise = new Promise((resolve10) => {
22169
+ settle = resolve10;
22041
22170
  listener = (observed) => {
22042
22171
  detach();
22043
- resolve9(observed);
22172
+ resolve10(observed);
22044
22173
  };
22045
22174
  const set = this.settingsWaiters.get(threadId) ?? /* @__PURE__ */ new Set();
22046
22175
  set.add(listener);
22047
22176
  this.settingsWaiters.set(threadId, set);
22048
22177
  timer = setTimeout(() => {
22049
22178
  detach();
22050
- resolve9(void 0);
22179
+ resolve10(void 0);
22051
22180
  }, timeoutMs);
22052
22181
  timer.unref?.();
22053
22182
  });
@@ -22620,11 +22749,11 @@ var init_codex_app_server = __esm({
22620
22749
  });
22621
22750
 
22622
22751
  // packages/server/src/backend/codex-quota.ts
22623
- import { join as join17 } from "node:path";
22624
- import { readdirSync as readdirSync7, statSync as statSync10, openSync as openSync8, readSync as readSync5, fstatSync, closeSync as closeSync7 } from "node:fs";
22752
+ import { join as join18 } from "node:path";
22753
+ import { readdirSync as readdirSync7, statSync as statSync10, openSync as openSync9, readSync as readSync5, fstatSync, closeSync as closeSync8 } from "node:fs";
22625
22754
  import { spawn as spawn4 } from "node:child_process";
22626
22755
  function sessionsDir2(codexHome) {
22627
- return join17(codexHome, "sessions");
22756
+ return join18(codexHome, "sessions");
22628
22757
  }
22629
22758
  function newestRollouts(dir, out, budget) {
22630
22759
  if (budget.n <= 0) return;
@@ -22638,18 +22767,18 @@ function newestRollouts(dir, out, budget) {
22638
22767
  const files = entries.filter((e) => e.isFile() && e.name.startsWith("rollout-") && e.name.endsWith(".jsonl")).map((e) => e.name).sort(descByName2);
22639
22768
  for (const d of dirs) {
22640
22769
  if (budget.n <= 0) return;
22641
- newestRollouts(join17(dir, d), out, budget);
22770
+ newestRollouts(join18(dir, d), out, budget);
22642
22771
  }
22643
22772
  for (const f of files) {
22644
22773
  if (budget.n <= 0) return;
22645
- out.push(join17(dir, f));
22774
+ out.push(join18(dir, f));
22646
22775
  budget.n--;
22647
22776
  }
22648
22777
  }
22649
22778
  function readTail(path) {
22650
22779
  let fd;
22651
22780
  try {
22652
- fd = openSync8(path, "r");
22781
+ fd = openSync9(path, "r");
22653
22782
  const size = fstatSync(fd).size;
22654
22783
  const start = Math.max(0, size - TAIL_BYTES);
22655
22784
  const len = size - start;
@@ -22666,7 +22795,7 @@ function readTail(path) {
22666
22795
  } finally {
22667
22796
  if (fd !== void 0) {
22668
22797
  try {
22669
- closeSync7(fd);
22798
+ closeSync8(fd);
22670
22799
  } catch {
22671
22800
  }
22672
22801
  }
@@ -22747,7 +22876,7 @@ function parseCodexQuotaFromRateLimits(result) {
22747
22876
  return { status: "ok", planType, windows };
22748
22877
  }
22749
22878
  function queryCodexRateLimits(codexHome = defaultCodexHome(), codexBin = "codex", timeoutMs = 12e3) {
22750
- return new Promise((resolve9) => {
22879
+ return new Promise((resolve10) => {
22751
22880
  let child;
22752
22881
  try {
22753
22882
  child = spawn4(codexBin, ["app-server"], {
@@ -22755,7 +22884,7 @@ function queryCodexRateLimits(codexHome = defaultCodexHome(), codexBin = "codex"
22755
22884
  env: { ...process.env, CODEX_HOME: codexHome }
22756
22885
  });
22757
22886
  } catch {
22758
- resolve9(void 0);
22887
+ resolve10(void 0);
22759
22888
  return;
22760
22889
  }
22761
22890
  let settled = false;
@@ -22767,7 +22896,7 @@ function queryCodexRateLimits(codexHome = defaultCodexHome(), codexBin = "codex"
22767
22896
  child.kill("SIGKILL");
22768
22897
  } catch {
22769
22898
  }
22770
- resolve9(quota);
22899
+ resolve10(quota);
22771
22900
  };
22772
22901
  const timer = setTimeout(() => finish(void 0), timeoutMs);
22773
22902
  const send = (msg) => {
@@ -22842,15 +22971,15 @@ var init_codex_quota = __esm({
22842
22971
  });
22843
22972
 
22844
22973
  // packages/server/src/backend/claude-quota.ts
22845
- import { join as join18 } from "node:path";
22846
- import { homedir as homedir8, platform } from "node:os";
22847
- import { createHash as createHash8 } from "node:crypto";
22974
+ import { join as join19 } from "node:path";
22975
+ import { homedir as homedir9, platform } from "node:os";
22976
+ import { createHash as createHash9 } from "node:crypto";
22848
22977
  import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
22849
22978
  import { execFile } from "node:child_process";
22850
22979
  import { promisify } from "node:util";
22851
22980
  function claudeConfigDir() {
22852
22981
  const override = process.env.CLAUDE_CONFIG_DIR;
22853
- return override && override.trim() ? override : join18(homedir8(), ".claude");
22982
+ return override && override.trim() ? override : join19(homedir9(), ".claude");
22854
22983
  }
22855
22984
  function tokenFromCredentialsJson(raw2) {
22856
22985
  let doc;
@@ -22879,7 +23008,7 @@ async function readKeychainToken() {
22879
23008
  }
22880
23009
  async function readAccessToken(configDir) {
22881
23010
  try {
22882
- const fromFile = tokenFromCredentialsJson(await readFile(join18(configDir, ".credentials.json"), "utf8"));
23011
+ const fromFile = tokenFromCredentialsJson(await readFile(join19(configDir, ".credentials.json"), "utf8"));
22883
23012
  if (fromFile) return fromFile;
22884
23013
  } catch {
22885
23014
  }
@@ -22946,10 +23075,10 @@ function parseClaudeUsage(body, planType) {
22946
23075
  return { status: "ok", planType, windows };
22947
23076
  }
22948
23077
  function cachePaths(cacheDir, configDir) {
22949
- const profile = createHash8("sha256").update(configDir).digest("hex").slice(0, 12);
23078
+ const profile = createHash9("sha256").update(configDir).digest("hex").slice(0, 12);
22950
23079
  return {
22951
- data: join18(cacheDir, `claude-${profile}.json`),
22952
- lock: join18(cacheDir, `claude-${profile}.lock`)
23080
+ data: join19(cacheDir, `claude-${profile}.json`),
23081
+ lock: join19(cacheDir, `claude-${profile}.lock`)
22953
23082
  };
22954
23083
  }
22955
23084
  async function readShared(path) {
@@ -22972,7 +23101,7 @@ async function writeShared(path, value) {
22972
23101
  }
22973
23102
  }
22974
23103
  function delay(ms) {
22975
- return new Promise((resolve9) => setTimeout(resolve9, ms));
23104
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
22976
23105
  }
22977
23106
  async function acquireLock(path) {
22978
23107
  const deadline = Date.now() + LOCK_WAIT_MS;
@@ -23141,7 +23270,7 @@ function refreshSharedInBackground(paths, claudeBin, deps, now) {
23141
23270
  async function refreshClaudeQuotaInBackground(claudeBin = "claude", deps = {}) {
23142
23271
  const now = (deps.now ?? Date.now)();
23143
23272
  const configDir = claudeConfigDir();
23144
- const cacheDir = deps.cacheDir ?? join18(frizzRoots().cache, "quota-cache");
23273
+ const cacheDir = deps.cacheDir ?? join19(frizzRoots().cache, "quota-cache");
23145
23274
  try {
23146
23275
  await mkdir(cacheDir, { recursive: true, mode: 448 });
23147
23276
  } catch {
@@ -23152,7 +23281,7 @@ async function refreshClaudeQuotaInBackground(claudeBin = "claude", deps = {}) {
23152
23281
  async function readClaudeQuota(claudeBin = "claude", deps = {}, options = {}) {
23153
23282
  const now = (deps.now ?? Date.now)();
23154
23283
  const configDir = claudeConfigDir();
23155
- const cacheDir = deps.cacheDir ?? join18(frizzRoots().cache, "quota-cache");
23284
+ const cacheDir = deps.cacheDir ?? join19(frizzRoots().cache, "quota-cache");
23156
23285
  const paths = cachePaths(cacheDir, configDir);
23157
23286
  try {
23158
23287
  await mkdir(cacheDir, { recursive: true, mode: 448 });
@@ -23311,20 +23440,20 @@ var init_quota = __esm({
23311
23440
  // packages/server/src/frizz.ts
23312
23441
  import { execFile as execFile2 } from "node:child_process";
23313
23442
  import { lstatSync as lstatSync3, realpathSync as realpathSync4 } from "node:fs";
23314
- import { basename as basename3, dirname as dirname4, join as join19, resolve as resolve4 } from "node:path";
23443
+ import { basename as basename3, dirname as dirname5, join as join20, resolve as resolve5 } from "node:path";
23315
23444
  import { promisify as promisify2 } from "node:util";
23316
23445
  function frizzScriptsDir() {
23317
23446
  if (process.env.FRIZZ_SCRIPTS_DIR) return process.env.FRIZZ_SCRIPTS_DIR;
23318
- return resolve4(import.meta.dirname, "..", "..", "..", "board");
23447
+ return resolve5(import.meta.dirname, "..", "..", "..", "board");
23319
23448
  }
23320
23449
  function directFrizzRoot(projectDir) {
23321
23450
  try {
23322
23451
  const projectRoot = realpathSync4(projectDir);
23323
- const path = join19(projectRoot, ".frizz");
23452
+ const path = join20(projectRoot, ".frizz");
23324
23453
  const stat2 = lstatSync3(path);
23325
23454
  if (!stat2.isDirectory() || stat2.isSymbolicLink()) return null;
23326
23455
  const real = realpathSync4(path);
23327
- return dirname4(real) === projectRoot && basename3(real) === ".frizz" ? real : null;
23456
+ return dirname5(real) === projectRoot && basename3(real) === ".frizz" ? real : null;
23328
23457
  } catch {
23329
23458
  return null;
23330
23459
  }
@@ -23334,7 +23463,7 @@ function frizzDirExists(projectDir) {
23334
23463
  }
23335
23464
  async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
23336
23465
  if (!directFrizzRoot(projectDir)) throw new Error("unsafe or missing .frizz directory");
23337
- const { stdout } = await execFileP("node", [join19(scriptsDir, "index.mjs"), "--json"], {
23466
+ const { stdout } = await execFileP("node", [join20(scriptsDir, "index.mjs"), "--json"], {
23338
23467
  cwd: projectDir,
23339
23468
  env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir },
23340
23469
  maxBuffer: 32 * 1024 * 1024
@@ -23359,7 +23488,7 @@ async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
23359
23488
  };
23360
23489
  }
23361
23490
  async function runThreadUpdate(projectDir, slug, args, scriptsDir = frizzScriptsDir()) {
23362
- await execFileP("node", [join19(scriptsDir, "thread-update.mjs"), slug, ...args], {
23491
+ await execFileP("node", [join20(scriptsDir, "thread-update.mjs"), slug, ...args], {
23363
23492
  cwd: projectDir,
23364
23493
  env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir }
23365
23494
  });
@@ -24202,7 +24331,7 @@ function connectClaudeBroker(socketPath, handlers, options = {}) {
24202
24331
  sendInput: (message) => send({ t: "input", message }),
24203
24332
  answerPermission: (requestId, decision2) => send({ t: "permission", requestId, decision: decision2 }),
24204
24333
  interrupt: () => send({ t: "interrupt" }),
24205
- cancelInput: (id) => new Promise((resolve9, reject) => {
24334
+ cancelInput: (id) => new Promise((resolve10, reject) => {
24206
24335
  if (closed) {
24207
24336
  reject(new Error("the broker connection is closed"));
24208
24337
  return;
@@ -24213,10 +24342,10 @@ function connectClaudeBroker(socketPath, handlers, options = {}) {
24213
24342
  reject(new Error("the Claude session did not answer the unqueue request"));
24214
24343
  }, cancelTimeoutMs);
24215
24344
  if (timer.unref) timer.unref();
24216
- pendingCancels.set(requestId, { settle: resolve9, fail: reject, timer });
24345
+ pendingCancels.set(requestId, { settle: resolve10, fail: reject, timer });
24217
24346
  send({ t: "cancel-input", requestId, id });
24218
24347
  }),
24219
- stopTask: (taskId) => new Promise((resolve9, reject) => {
24348
+ stopTask: (taskId) => new Promise((resolve10, reject) => {
24220
24349
  if (closed) {
24221
24350
  reject(new Error("the broker connection is closed"));
24222
24351
  return;
@@ -24227,12 +24356,12 @@ function connectClaudeBroker(socketPath, handlers, options = {}) {
24227
24356
  reject(new Error("the Claude session did not answer the stop request"));
24228
24357
  }, cancelTimeoutMs);
24229
24358
  if (timer.unref) timer.unref();
24230
- pendingStops.set(requestId, { settle: resolve9, fail: reject, timer });
24359
+ pendingStops.set(requestId, { settle: resolve10, fail: reject, timer });
24231
24360
  send({ t: "stop-task", requestId, taskId });
24232
24361
  }),
24233
24362
  // A reload re-scans the plugin closure and can re-handshake MCP servers, so it gets a longer
24234
24363
  // deadline than an unqueue/stop — those are answered by bookkeeping the CLI already holds.
24235
- reloadPlugins: () => new Promise((resolve9, reject) => {
24364
+ reloadPlugins: () => new Promise((resolve10, reject) => {
24236
24365
  if (closed) {
24237
24366
  reject(new Error("the broker connection is closed"));
24238
24367
  return;
@@ -24243,11 +24372,11 @@ function connectClaudeBroker(socketPath, handlers, options = {}) {
24243
24372
  reject(new Error("the Claude session did not answer the plugin reload"));
24244
24373
  }, reloadTimeoutMs);
24245
24374
  if (timer.unref) timer.unref();
24246
- pendingReloads.set(requestId, { settle: resolve9, fail: reject, timer });
24375
+ pendingReloads.set(requestId, { settle: resolve10, fail: reject, timer });
24247
24376
  send({ t: "reload-plugins", requestId });
24248
24377
  }),
24249
24378
  // Shares the reload deadline: a re-title is a provider round trip, not local bookkeeping.
24250
- renameSession: (description) => new Promise((resolve9, reject) => {
24379
+ renameSession: (description) => new Promise((resolve10, reject) => {
24251
24380
  if (closed) {
24252
24381
  reject(new Error("the broker connection is closed"));
24253
24382
  return;
@@ -24258,7 +24387,7 @@ function connectClaudeBroker(socketPath, handlers, options = {}) {
24258
24387
  reject(new Error("the Claude session did not answer the rename request"));
24259
24388
  }, reloadTimeoutMs);
24260
24389
  if (timer.unref) timer.unref();
24261
- pendingRenames.set(requestId, { settle: resolve9, fail: reject, timer });
24390
+ pendingRenames.set(requestId, { settle: resolve10, fail: reject, timer });
24262
24391
  send({ t: "rename", requestId, description });
24263
24392
  }),
24264
24393
  setPermissionMode: (mode) => send({ t: "set-mode", mode }),
@@ -24449,12 +24578,12 @@ var init_claude_agent_sdk_protocol = __esm({
24449
24578
  });
24450
24579
 
24451
24580
  // packages/server/src/backend/claude-permission-interactions.ts
24452
- import { homedir as homedir9 } from "node:os";
24581
+ import { homedir as homedir10 } from "node:os";
24453
24582
  function clip(text, max) {
24454
24583
  return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
24455
24584
  }
24456
24585
  function tildePath(path) {
24457
- const home = homedir9();
24586
+ const home = homedir10();
24458
24587
  if (!path.startsWith(home)) return path;
24459
24588
  const rest = path.slice(home.length);
24460
24589
  return rest === "" ? "~" : rest.startsWith("/") ? `~${rest}` : path;
@@ -25060,19 +25189,19 @@ var init_claude_agent_broker_bridge = __esm({
25060
25189
  });
25061
25190
 
25062
25191
  // packages/server/src/backend/auth-status.ts
25063
- import { join as join20 } from "node:path";
25064
- import { homedir as homedir10, platform as platform2 } from "node:os";
25065
- import { readFileSync as readFileSync11, statSync as statSync11 } from "node:fs";
25192
+ import { join as join21 } from "node:path";
25193
+ import { homedir as homedir11, platform as platform2 } from "node:os";
25194
+ import { readFileSync as readFileSync12, statSync as statSync11 } from "node:fs";
25066
25195
  import { execFile as execFile3 } from "node:child_process";
25067
25196
  import { promisify as promisify3 } from "node:util";
25068
25197
  function claudeConfigDir2() {
25069
25198
  const override = process.env.CLAUDE_CONFIG_DIR;
25070
- return override && override.trim() ? override : join20(homedir10(), ".claude");
25199
+ return override && override.trim() ? override : join21(homedir11(), ".claude");
25071
25200
  }
25072
25201
  function claudeFileState(configDir) {
25073
25202
  let raw2;
25074
25203
  try {
25075
- raw2 = readFileSync11(join20(configDir, ".credentials.json"), "utf8");
25204
+ raw2 = readFileSync12(join21(configDir, ".credentials.json"), "utf8");
25076
25205
  } catch (err) {
25077
25206
  return err.code === "ENOENT" ? "absent" : "error";
25078
25207
  }
@@ -25105,7 +25234,7 @@ function readCodexAuthState(codexHome = defaultCodexHome()) {
25105
25234
  if (process.env.OPENAI_API_KEY || process.env.CODEX_API_KEY || process.env.CODEX_ACCESS_TOKEN) return "authed";
25106
25235
  let raw2;
25107
25236
  try {
25108
- raw2 = readFileSync11(join20(codexHome, "auth.json"), "utf8");
25237
+ raw2 = readFileSync12(join21(codexHome, "auth.json"), "utf8");
25109
25238
  } catch (err) {
25110
25239
  return err.code === "ENOENT" ? "signed-out" : "unknown";
25111
25240
  }
@@ -25170,7 +25299,7 @@ function asEmail(value) {
25170
25299
  }
25171
25300
  function claudeAccountFile() {
25172
25301
  const override = process.env.CLAUDE_CONFIG_DIR;
25173
- return override && override.trim() ? join20(override, ".claude.json") : join20(homedir10(), ".claude.json");
25302
+ return override && override.trim() ? join21(override, ".claude.json") : join21(homedir11(), ".claude.json");
25174
25303
  }
25175
25304
  function readClaudeAccountEmail(path = claudeAccountFile()) {
25176
25305
  let stat2;
@@ -25183,7 +25312,7 @@ function readClaudeAccountEmail(path = claudeAccountFile()) {
25183
25312
  if (memo3 && memo3.path === path && memo3.mtimeMs === stat2.mtimeMs && memo3.size === stat2.size) return memo3.email;
25184
25313
  let email;
25185
25314
  try {
25186
- const doc = JSON.parse(readFileSync11(path, "utf8"));
25315
+ const doc = JSON.parse(readFileSync12(path, "utf8"));
25187
25316
  email = asEmail(doc?.oauthAccount?.emailAddress);
25188
25317
  } catch {
25189
25318
  email = void 0;
@@ -25194,7 +25323,7 @@ function readClaudeAccountEmail(path = claudeAccountFile()) {
25194
25323
  function readCodexAccountEmail(codexHome = defaultCodexHome()) {
25195
25324
  let doc;
25196
25325
  try {
25197
- doc = JSON.parse(readFileSync11(join20(codexHome, "auth.json"), "utf8"));
25326
+ doc = JSON.parse(readFileSync12(join21(codexHome, "auth.json"), "utf8"));
25198
25327
  } catch {
25199
25328
  return void 0;
25200
25329
  }
@@ -25261,10 +25390,10 @@ var init_auth_status = __esm({
25261
25390
  });
25262
25391
 
25263
25392
  // packages/server/src/dispatch.ts
25264
- import { closeSync as closeSync8, constants, existsSync as existsSync7, fstatSync as fstatSync2, lstatSync as lstatSync4, openSync as openSync9, readFileSync as readFileSync12, realpathSync as realpathSync5, statSync as statSync12, writeFileSync as writeFileSync6, renameSync as renameSync5, mkdirSync as mkdirSync10, rmSync as rmSync5 } from "node:fs";
25265
- import { basename as basename4, join as join21, dirname as dirname5 } from "node:path";
25393
+ import { closeSync as closeSync9, constants, existsSync as existsSync8, fstatSync as fstatSync2, lstatSync as lstatSync4, openSync as openSync10, readFileSync as readFileSync13, realpathSync as realpathSync5, statSync as statSync12, writeFileSync as writeFileSync7, renameSync as renameSync6, mkdirSync as mkdirSync11, rmSync as rmSync6 } from "node:fs";
25394
+ import { basename as basename4, join as join22, dirname as dirname6 } from "node:path";
25266
25395
  import { fileURLToPath as fileURLToPath2 } from "node:url";
25267
- import { createHash as createHash9, randomUUID as randomUUID12 } from "node:crypto";
25396
+ import { createHash as createHash10, randomUUID as randomUUID12 } from "node:crypto";
25268
25397
  function fallbackTitle(prompt) {
25269
25398
  const firstLine = prompt.trim().split("\n", 1)[0].trim();
25270
25399
  let allWords = firstLine.split(/\s+/).filter(Boolean);
@@ -25282,7 +25411,7 @@ function fallbackTitle(prompt) {
25282
25411
  }
25283
25412
  function resolveSlug(frizzDir, base, taken) {
25284
25413
  base = ThreadSlug.parse(base);
25285
- const isTaken = (slug) => existsSync7(join21(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
25414
+ const isTaken = (slug) => existsSync8(join22(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
25286
25415
  if (!isTaken(base)) return base;
25287
25416
  for (let n = 2; ; n++) {
25288
25417
  const suffix = `-${n}`;
@@ -25299,26 +25428,26 @@ function resolveLegacyThreadFile(projectDir, value) {
25299
25428
  if (!parsed.success) return null;
25300
25429
  try {
25301
25430
  const projectRoot = realpathSync5(projectDir);
25302
- const frizzPath = join21(projectRoot, ".frizz");
25431
+ const frizzPath = join22(projectRoot, ".frizz");
25303
25432
  const frizzStat = lstatSync4(frizzPath);
25304
25433
  if (!frizzStat.isDirectory() || frizzStat.isSymbolicLink()) return null;
25305
25434
  const realFrizz = realpathSync5(frizzPath);
25306
- if (dirname5(realFrizz) !== projectRoot || basename4(realFrizz) !== ".frizz") return null;
25307
- const path = join21(realFrizz, `${parsed.data}.md`);
25435
+ if (dirname6(realFrizz) !== projectRoot || basename4(realFrizz) !== ".frizz") return null;
25436
+ const path = join22(realFrizz, `${parsed.data}.md`);
25308
25437
  const before = lstatSync4(path);
25309
25438
  if (!before.isFile() || before.isSymbolicLink()) return null;
25310
25439
  const realPath = realpathSync5(path);
25311
- if (dirname5(realPath) !== realFrizz || basename4(realPath) !== `${parsed.data}.md`) return null;
25440
+ if (dirname6(realPath) !== realFrizz || basename4(realPath) !== `${parsed.data}.md`) return null;
25312
25441
  let contents;
25313
25442
  let openedBefore;
25314
25443
  let openedAfter;
25315
- const fd = openSync9(path, constants.O_RDONLY | constants.O_NOFOLLOW);
25444
+ const fd = openSync10(path, constants.O_RDONLY | constants.O_NOFOLLOW);
25316
25445
  try {
25317
25446
  openedBefore = fstatSync2(fd);
25318
- contents = readFileSync12(fd);
25447
+ contents = readFileSync13(fd);
25319
25448
  openedAfter = fstatSync2(fd);
25320
25449
  } finally {
25321
- closeSync8(fd);
25450
+ closeSync9(fd);
25322
25451
  }
25323
25452
  const after = lstatSync4(path);
25324
25453
  if (before.dev !== openedBefore.dev || before.ino !== openedBefore.ino || openedBefore.dev !== openedAfter.dev || openedBefore.ino !== openedAfter.ino || openedBefore.size !== openedAfter.size || openedBefore.mtimeMs !== openedAfter.mtimeMs || openedBefore.ctimeMs !== openedAfter.ctimeMs || after.dev !== openedAfter.dev || after.ino !== openedAfter.ino || after.size !== openedAfter.size || after.mtimeMs !== openedAfter.mtimeMs || after.ctimeMs !== openedAfter.ctimeMs || !openedAfter.isFile() || !after.isFile() || after.isSymbolicLink()) {
@@ -25333,7 +25462,7 @@ function resolveLegacyThreadFile(projectDir, value) {
25333
25462
  size: after.size,
25334
25463
  mtimeMs: after.mtimeMs,
25335
25464
  ctimeMs: after.ctimeMs,
25336
- digest: createHash9("sha256").update(contents).digest("hex")
25465
+ digest: createHash10("sha256").update(contents).digest("hex")
25337
25466
  };
25338
25467
  } catch {
25339
25468
  return null;
@@ -25348,9 +25477,9 @@ function boardAuthorizesAdoption(board, slug) {
25348
25477
  return !board.errorItems.some((item) => item.file === `${slug}.md`);
25349
25478
  }
25350
25479
  function ensureSafeDirectDirectory(parent, name) {
25351
- const path = join21(parent, name);
25480
+ const path = join22(parent, name);
25352
25481
  try {
25353
- mkdirSync10(path);
25482
+ mkdirSync11(path);
25354
25483
  } catch (error) {
25355
25484
  const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
25356
25485
  if (code !== "EEXIST") throw error;
@@ -25358,7 +25487,7 @@ function ensureSafeDirectDirectory(parent, name) {
25358
25487
  const stat2 = lstatSync4(path);
25359
25488
  if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw new Error("unsafe project directory");
25360
25489
  const real = realpathSync5(path);
25361
- if (dirname5(real) !== parent || basename4(real) !== name) throw new Error("unsafe project directory");
25490
+ if (dirname6(real) !== parent || basename4(real) !== name) throw new Error("unsafe project directory");
25362
25491
  return real;
25363
25492
  }
25364
25493
  function scratchpadContent(title, kind = "claude") {
@@ -25421,14 +25550,14 @@ function writeScratchpad(projectDir, sessionId, title, kind = "claude") {
25421
25550
  const threadsDir = ensureSafeDirectDirectory(frizzDir, "threads");
25422
25551
  const dir = ensureSafeDirectDirectory(threadsDir, sessionId);
25423
25552
  const rel = scratchpadRelPath(sessionId);
25424
- const path = join21(dir, "scratch.md");
25425
- const tmp = join21(dir, ".scratch.tmp");
25553
+ const path = join22(dir, "scratch.md");
25554
+ const tmp = join22(dir, ".scratch.tmp");
25426
25555
  try {
25427
- writeFileSync6(tmp, scratchpadContent(title, kind), { flag: "wx", mode: 384 });
25428
- if (existsSync7(path)) throw new Error("scratchpad already exists");
25429
- renameSync5(tmp, path);
25556
+ writeFileSync7(tmp, scratchpadContent(title, kind), { flag: "wx", mode: 384 });
25557
+ if (existsSync8(path)) throw new Error("scratchpad already exists");
25558
+ renameSync6(tmp, path);
25430
25559
  } catch (error) {
25431
- rmSync5(tmp, { force: true });
25560
+ rmSync6(tmp, { force: true });
25432
25561
  throw error;
25433
25562
  }
25434
25563
  return rel;
@@ -25446,8 +25575,8 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
25446
25575
  }
25447
25576
  ]
25448
25577
  });
25449
- const bashBackgroundHook = join21(dirname5(hookScript), "bash-background.mjs");
25450
- const scratchpadStopHook = join21(dirname5(hookScript), "scratchpad-stop.mjs");
25578
+ const bashBackgroundHook = join22(dirname6(hookScript), "bash-background.mjs");
25579
+ const scratchpadStopHook = join22(dirname6(hookScript), "scratchpad-stop.mjs");
25451
25580
  return {
25452
25581
  bypass_hook_trust: true,
25453
25582
  hooks: {
@@ -25480,7 +25609,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
25480
25609
  }
25481
25610
  function scratchpadHookScript() {
25482
25611
  const plugin = workerPluginDir();
25483
- return plugin ? join21(plugin, "hooks", "scratchpad.mjs") : void 0;
25612
+ return plugin ? join22(plugin, "hooks", "scratchpad.mjs") : void 0;
25484
25613
  }
25485
25614
  function composePrompt(sessionId, prompt, kind = "claude") {
25486
25615
  const scratch = kind === "codex" ? `Your scratchpad is \`.frizz/threads/${sessionId}/scratch.md\` \u2014 an OPTIONAL scratch file kept for you, not a deliverable. A single direct task usually needs nothing in it, and writing in it never substitutes for doing the work. On a long effort it is useful crash insurance and a shared progress document for native sub-agents: keep the approach, what you rejected, and the human's decisions in it as you go, mid-work, then keep working; re-read it after any compaction or resume before asserting anything. Each native sub-agent should merge its own scoped progress into it rather than leaving the root as its sole writer, but must re-read before each edit, preserve all existing content, and never delete, truncate, reinitialize, move, or replace the whole file.` : `Your scratchpad is \`.frizz/threads/${sessionId}/scratch.md\` \u2014 an OPTIONAL scratch file kept for you, not a deliverable. A single direct task usually needs nothing in it, and writing in it never substitutes for doing the work. On a long effort it is useful crash insurance and the shared blackboard for your sub-agents: keep the approach, what you rejected, and the human's decisions in it as you go, mid-work, then keep working; re-read it after any compaction or resume, and pass its path to every sub-agent you dispatch. Each sub-agent should merge its own scoped progress into it rather than leaving the root as its sole writer, but must re-read before each edit, preserve all existing content, and never delete, truncate, reinitialize, move, or replace the whole file.`;
@@ -25497,12 +25626,12 @@ function scratchpadOrientation(sessionId, planPath, kind = "claude") {
25497
25626
  return lines.join("\n");
25498
25627
  }
25499
25628
  function frizzConfigBlock(projectDir) {
25500
- const path = join21(projectDir, "FRIZZ.md");
25629
+ const path = join22(projectDir, "FRIZZ.md");
25501
25630
  let body;
25502
25631
  try {
25503
25632
  const st = statSync12(path);
25504
25633
  if (!st.isFile() || st.size > FRIZZ_MD_MAX_BYTES) return "";
25505
- body = readFileSync12(path, "utf8").trim();
25634
+ body = readFileSync13(path, "utf8").trim();
25506
25635
  } catch {
25507
25636
  return "";
25508
25637
  }
@@ -25516,7 +25645,7 @@ ${clipped}`;
25516
25645
  }
25517
25646
  function validPlanPath(projectDir, planPath) {
25518
25647
  if (!planPath || !PLAN_PATH_RE.test(planPath)) return null;
25519
- return existsSync7(join21(projectDir, planPath)) ? planPath : null;
25648
+ return existsSync8(join22(projectDir, planPath)) ? planPath : null;
25520
25649
  }
25521
25650
  function workerPermissionMode(m) {
25522
25651
  return m === "plan" ? "auto" : m;
@@ -25532,16 +25661,16 @@ function effectivePermissionMode(kind, mode) {
25532
25661
  }
25533
25662
  function systemPromptFlags(sessionId, system) {
25534
25663
  if (!system) return [];
25535
- mkdirSync10(SYSTEM_PROMPT_DIR, { recursive: true });
25664
+ mkdirSync11(SYSTEM_PROMPT_DIR, { recursive: true });
25536
25665
  const path = systemPromptPath(sessionId);
25537
- writeFileSync6(path, system);
25666
+ writeFileSync7(path, system);
25538
25667
  return ["--append-system-prompt-file", path];
25539
25668
  }
25540
25669
  function resolveFrizzMcp(stateDir, moduleUrl = import.meta.url, env = process.env, slug) {
25541
25670
  const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
25542
25671
  if (!pluginDir) return void 0;
25543
- const scriptPath = join21(pluginDir, "bin", FRIZZ_MCP.script);
25544
- if (!existsSync7(scriptPath)) return void 0;
25672
+ const scriptPath = join22(pluginDir, "bin", FRIZZ_MCP.script);
25673
+ if (!existsSync8(scriptPath)) return void 0;
25545
25674
  return { scriptPath, stateDir, ...slug ? { slug } : {} };
25546
25675
  }
25547
25676
  function claudeMcpConfig(mcp) {
@@ -25582,13 +25711,13 @@ function buildClaudeCommand(opts) {
25582
25711
  }
25583
25712
  function resolveWorkerPluginDir(moduleUrl = import.meta.url, env = process.env) {
25584
25713
  const override = env.FRIZZ_WORKER_PLUGIN_DIR;
25585
- if (override && existsSync7(join21(override, ".claude-plugin", "plugin.json")))
25714
+ if (override && existsSync8(join22(override, ".claude-plugin", "plugin.json")))
25586
25715
  return override;
25587
- let current = dirname5(fileURLToPath2(moduleUrl));
25716
+ let current = dirname6(fileURLToPath2(moduleUrl));
25588
25717
  for (; ; ) {
25589
- const candidate = join21(current, "cc-worker");
25590
- if (existsSync7(join21(candidate, ".claude-plugin", "plugin.json"))) return candidate;
25591
- const parent = dirname5(current);
25718
+ const candidate = join22(current, "cc-worker");
25719
+ if (existsSync8(join22(candidate, ".claude-plugin", "plugin.json"))) return candidate;
25720
+ const parent = dirname6(current);
25592
25721
  if (parent === current) return void 0;
25593
25722
  current = parent;
25594
25723
  }
@@ -25629,12 +25758,12 @@ function buildClaudeResumeCommand(opts) {
25629
25758
  }
25630
25759
  function createDispatcher(deps) {
25631
25760
  const readBoardSource = deps.readBoard ?? readBoard;
25632
- const frizzDir = join21(deps.project.dir, ".frizz");
25761
+ const frizzDir = join22(deps.project.dir, ".frizz");
25633
25762
  const adoptionRuntime = deps.adoptionRuntime ?? productionRuntime;
25634
25763
  function cleanupPrewrites(built) {
25635
25764
  for (const path of new Set(built.prewrite.map((file) => file.path))) {
25636
25765
  try {
25637
- rmSync5(path, { force: true });
25766
+ rmSync6(path, { force: true });
25638
25767
  } catch {
25639
25768
  }
25640
25769
  }
@@ -25642,7 +25771,7 @@ function createDispatcher(deps) {
25642
25771
  function cleanupDispatchFiles(scratchRel, built, sessionId) {
25643
25772
  cleanupPrewrites(built);
25644
25773
  try {
25645
- rmSync5(join21(deps.project.dir, scratchRel), { force: true });
25774
+ rmSync6(join22(deps.project.dir, scratchRel), { force: true });
25646
25775
  } catch {
25647
25776
  }
25648
25777
  cleanupAdoptionSessionFiles(deps.project.dir, sessionId);
@@ -26013,28 +26142,28 @@ var init_dispatch = __esm({
26013
26142
 
26014
26143
  // packages/server/src/plan-files.ts
26015
26144
  import {
26016
- closeSync as closeSync9,
26145
+ closeSync as closeSync10,
26017
26146
  constants as constants2,
26018
26147
  fstatSync as fstatSync3,
26019
26148
  lstatSync as lstatSync5,
26020
- openSync as openSync10,
26021
- readFileSync as readFileSync13,
26149
+ openSync as openSync11,
26150
+ readFileSync as readFileSync14,
26022
26151
  readdirSync as readdirSync8,
26023
26152
  realpathSync as realpathSync6,
26024
26153
  unlinkSync as unlinkSync4
26025
26154
  } from "node:fs";
26026
- import { createHash as createHash10 } from "node:crypto";
26027
- import { basename as basename5, dirname as dirname6, join as join22 } from "node:path";
26155
+ import { createHash as createHash11 } from "node:crypto";
26156
+ import { basename as basename5, dirname as dirname7, join as join23 } from "node:path";
26028
26157
  function sameStat(a, b) {
26029
26158
  return a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.size === b.size && a.mtimeMs === b.mtimeMs && a.ctimeMs === b.ctimeMs;
26030
26159
  }
26031
26160
  function directDirectory(parentRealPath, name) {
26032
26161
  try {
26033
- const path = join22(parentRealPath, name);
26162
+ const path = join23(parentRealPath, name);
26034
26163
  const stat2 = lstatSync5(path);
26035
26164
  if (!stat2.isDirectory() || stat2.isSymbolicLink()) return null;
26036
26165
  const realPath = realpathSync6(path);
26037
- if (dirname6(realPath) !== parentRealPath || basename5(realPath) !== name) return null;
26166
+ if (dirname7(realPath) !== parentRealPath || basename5(realPath) !== name) return null;
26038
26167
  return { path, realPath, stat: stat2 };
26039
26168
  } catch {
26040
26169
  return null;
@@ -26068,22 +26197,22 @@ function resolvePlanFile(projectDir, value, hooks = {}) {
26068
26197
  const directoryBefore = planDirectory(projectDir);
26069
26198
  if (!directoryBefore) return null;
26070
26199
  hooks.afterDirectoryCheck?.();
26071
- const path = join22(directoryBefore.plans.realPath, filename);
26200
+ const path = join23(directoryBefore.plans.realPath, filename);
26072
26201
  const before = lstatSync5(path);
26073
26202
  if (!before.isFile() || before.isSymbolicLink()) return null;
26074
26203
  const realPath = realpathSync6(path);
26075
- if (dirname6(realPath) !== directoryBefore.plans.realPath || basename5(realPath) !== filename) return null;
26204
+ if (dirname7(realPath) !== directoryBefore.plans.realPath || basename5(realPath) !== filename) return null;
26076
26205
  hooks.afterFileCheck?.();
26077
26206
  let contents;
26078
26207
  let openedBefore;
26079
26208
  let openedAfter;
26080
- const fd = openSync10(path, constants2.O_RDONLY | constants2.O_NOFOLLOW);
26209
+ const fd = openSync11(path, constants2.O_RDONLY | constants2.O_NOFOLLOW);
26081
26210
  try {
26082
26211
  openedBefore = fstatSync3(fd);
26083
- contents = readFileSync13(fd);
26212
+ contents = readFileSync14(fd);
26084
26213
  openedAfter = fstatSync3(fd);
26085
26214
  } finally {
26086
- closeSync9(fd);
26215
+ closeSync10(fd);
26087
26216
  }
26088
26217
  const after = lstatSync5(path);
26089
26218
  const realPathAfter = realpathSync6(path);
@@ -26100,7 +26229,7 @@ function resolvePlanFile(projectDir, value, hooks = {}) {
26100
26229
  size: after.size,
26101
26230
  mtimeMs: after.mtimeMs,
26102
26231
  ctimeMs: after.ctimeMs,
26103
- digest: createHash10("sha256").update(contents).digest("hex")
26232
+ digest: createHash11("sha256").update(contents).digest("hex")
26104
26233
  };
26105
26234
  } catch {
26106
26235
  return null;
@@ -26144,10 +26273,10 @@ var init_plan_files = __esm({
26144
26273
 
26145
26274
  // packages/server/src/board.ts
26146
26275
  import {
26147
- existsSync as existsSync8,
26276
+ existsSync as existsSync9,
26148
26277
  watch as fsWatch
26149
26278
  } from "node:fs";
26150
- import { join as join23 } from "node:path";
26279
+ import { join as join24 } from "node:path";
26151
26280
  import watcher from "@parcel/watcher";
26152
26281
  function appServerTurnStalled(liveness, lastActivityAt, nowMs) {
26153
26282
  if (!liveness) return false;
@@ -26253,7 +26382,7 @@ function deriveAwaitingBackground(row, tele, runtime, hasActionableInteraction =
26253
26382
  }
26254
26383
  function scratchpadPathIfExists(projectDir, sessionId) {
26255
26384
  const rel = scratchpadRelPath(sessionId);
26256
- return existsSync8(join23(projectDir, rel)) ? rel : void 0;
26385
+ return existsSync9(join24(projectDir, rel)) ? rel : void 0;
26257
26386
  }
26258
26387
  function resolveSessionProfile(row, tele) {
26259
26388
  const persistedModel = row.model?.trim() || void 0;
@@ -26626,7 +26755,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
26626
26755
  if (parcelSub || stopped) return Promise.resolve();
26627
26756
  if (watchSetup) return watchSetup;
26628
26757
  const setup = (async () => {
26629
- const next = await subscribe(join23(project.dir, ".frizz"), () => scheduleRebuild());
26758
+ const next = await subscribe(join24(project.dir, ".frizz"), () => scheduleRebuild());
26630
26759
  if (stopped) {
26631
26760
  await next.unsubscribe();
26632
26761
  return;
@@ -27166,14 +27295,14 @@ function createGithubReviewFetcher(deps = {}) {
27166
27295
  pending = /* @__PURE__ */ new Map();
27167
27296
  if (batch.size === 0) return;
27168
27297
  if (now() < notBeforeMs) {
27169
- for (const entry of batch.values()) for (const resolve9 of entry.resolve) resolve9({ status: "deferred" });
27298
+ for (const entry of batch.values()) for (const resolve10 of entry.resolve) resolve10({ status: "deferred" });
27170
27299
  return;
27171
27300
  }
27172
27301
  const entries = [...batch.values()];
27173
27302
  for (let offset = 0; offset < entries.length; offset += MAX_REFS_PER_REQUEST) {
27174
27303
  const chunk = entries.slice(offset, offset + MAX_REFS_PER_REQUEST);
27175
27304
  if (offset > 0 && now() < rateLimitBlockedUntilMs) {
27176
- for (const entry of chunk) for (const resolve9 of entry.resolve) resolve9({ status: "deferred" });
27305
+ for (const entry of chunk) for (const resolve10 of entry.resolve) resolve10({ status: "deferred" });
27177
27306
  continue;
27178
27307
  }
27179
27308
  let results;
@@ -27193,15 +27322,15 @@ function createGithubReviewFetcher(deps = {}) {
27193
27322
  status: "error",
27194
27323
  failure: { kind: "shape", message: `No GitHub result for ${refKey(entry.ref)}` }
27195
27324
  };
27196
- for (const resolve9 of entry.resolve) resolve9(result);
27325
+ for (const resolve10 of entry.resolve) resolve10(result);
27197
27326
  }
27198
27327
  }
27199
27328
  };
27200
- return (ref) => new Promise((resolve9) => {
27329
+ return (ref) => new Promise((resolve10) => {
27201
27330
  const key = refKey(ref);
27202
27331
  const existing = pending.get(key);
27203
- if (existing) existing.resolve.push(resolve9);
27204
- else pending.set(key, { ref, resolve: [resolve9] });
27332
+ if (existing) existing.resolve.push(resolve10);
27333
+ else pending.set(key, { ref, resolve: [resolve10] });
27205
27334
  if (!flushScheduled) {
27206
27335
  flushScheduled = true;
27207
27336
  queueMicrotask(() => {
@@ -27226,7 +27355,7 @@ var init_github_review = __esm({
27226
27355
  // packages/server/src/scheduler.ts
27227
27356
  import { execFile as execFile5 } from "node:child_process";
27228
27357
  import { promisify as promisify5 } from "node:util";
27229
- import { createHash as createHash11, randomUUID as randomUUID13 } from "node:crypto";
27358
+ import { createHash as createHash12, randomUUID as randomUUID13 } from "node:crypto";
27230
27359
  function parsePrRef(value) {
27231
27360
  const m = value.trim().match(PR_REF_RE);
27232
27361
  if (!m) return void 0;
@@ -27307,7 +27436,7 @@ function fenceIdentity(hints, fenceAt) {
27307
27436
  return `${fenceAt ?? ""}${hintId}`;
27308
27437
  }
27309
27438
  function wakeDeliveryId(slug, sessionId, fenceId) {
27310
- return createHash11("sha256").update(slug).update("\0").update(sessionId).update("\0").update(fenceId).digest("hex");
27439
+ return createHash12("sha256").update(slug).update("\0").update(sessionId).update("\0").update(fenceId).digest("hex");
27311
27440
  }
27312
27441
  function limitFenceId(fault) {
27313
27442
  return `${LIMIT_FENCE_PREFIX}${fault.at}`;
@@ -27326,7 +27455,7 @@ function isReportFenceId(fenceId) {
27326
27455
  return fenceId.startsWith(`${REPORT_FENCE_PREFIX}:`);
27327
27456
  }
27328
27457
  function snoozeFenceId(until, prompt) {
27329
- const digest = createHash11("sha256").update(prompt).digest("hex").slice(0, 16);
27458
+ const digest = createHash12("sha256").update(prompt).digest("hex").slice(0, 16);
27330
27459
  return `${SNOOZE_FENCE_PREFIX}:${until}:${digest}`;
27331
27460
  }
27332
27461
  function isSnoozeFenceId(fenceId) {
@@ -28352,7 +28481,7 @@ var init_resume = __esm({
28352
28481
  });
28353
28482
 
28354
28483
  // packages/server/src/backend/claude.ts
28355
- import { join as join24 } from "node:path";
28484
+ import { join as join25 } from "node:path";
28356
28485
  function toolResultText2(content) {
28357
28486
  if (typeof content === "string") return content;
28358
28487
  if (!Array.isArray(content)) return "";
@@ -28441,7 +28570,7 @@ function createClaudeBackend(opts) {
28441
28570
  return { argv, env: claudeWorkerEnvironment(), prewrite: [] };
28442
28571
  },
28443
28572
  transcriptPath(sessionId) {
28444
- return join24(opts.logDir, `${sessionId}.jsonl`);
28573
+ return join25(opts.logDir, `${sessionId}.jsonl`);
28445
28574
  },
28446
28575
  parseLine(line) {
28447
28576
  return parseClaudeLine(line);
@@ -28936,24 +29065,24 @@ CI: \`gh pr checks {n} -R {repo}\``;
28936
29065
  });
28937
29066
 
28938
29067
  // packages/server/src/backend/codex-app-server-diagnostics.ts
28939
- import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync11, renameSync as renameSync6, statSync as statSync13 } from "node:fs";
28940
- import { join as join25 } from "node:path";
29068
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync12, renameSync as renameSync7, statSync as statSync13 } from "node:fs";
29069
+ import { join as join26 } from "node:path";
28941
29070
  function codexDiagnosticLogPath(stateDir, projectId) {
28942
- return join25(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
29071
+ return join26(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
28943
29072
  }
28944
29073
  function createCodexDiagnosticSink(stateDir, projectId, now = () => /* @__PURE__ */ new Date()) {
28945
- const dir = join25(stateDir, "codex-app-server");
29074
+ const dir = join26(stateDir, "codex-app-server");
28946
29075
  const path = codexDiagnosticLogPath(stateDir, projectId);
28947
29076
  let ensured = false;
28948
29077
  return (event) => {
28949
29078
  if (event.event === "stderr") return;
28950
29079
  try {
28951
29080
  if (!ensured) {
28952
- mkdirSync11(dir, { recursive: true });
29081
+ mkdirSync12(dir, { recursive: true });
28953
29082
  ensured = true;
28954
29083
  }
28955
29084
  try {
28956
- if (statSync13(path).size > MAX_BYTES2) renameSync6(path, `${path}.1`);
29085
+ if (statSync13(path).size > MAX_BYTES2) renameSync7(path, `${path}.1`);
28957
29086
  } catch {
28958
29087
  }
28959
29088
  appendFileSync3(path, `${JSON.stringify({ at: now().toISOString(), ...event })}
@@ -28974,13 +29103,13 @@ var init_codex_app_server_diagnostics = __esm({
28974
29103
  import { execFile as execFile7 } from "node:child_process";
28975
29104
  import { readdirSync as readdirSync9, unlinkSync as unlinkSync5 } from "node:fs";
28976
29105
  import { connect as connectSocket } from "node:net";
28977
- import { join as join26 } from "node:path";
29106
+ import { join as join27 } from "node:path";
28978
29107
  function sweepStaleSockets(options, deps = {}) {
28979
29108
  if (process.platform === "win32") return;
28980
29109
  const keep = new Set(options.keep ?? []);
28981
29110
  let candidates;
28982
29111
  try {
28983
- candidates = (deps.readdir ?? readdirSync9)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join26(options.dir, name)).filter((path) => !keep.has(path));
29112
+ candidates = (deps.readdir ?? readdirSync9)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join27(options.dir, name)).filter((path) => !keep.has(path));
28984
29113
  } catch {
28985
29114
  return;
28986
29115
  }
@@ -29032,7 +29161,7 @@ var init_stale_socket_sweep = __esm({
29032
29161
 
29033
29162
  // packages/server/src/orphan-reaper.ts
29034
29163
  import { execFileSync as execFileSync5 } from "node:child_process";
29035
- import { dirname as dirname7 } from "node:path";
29164
+ import { dirname as dirname8 } from "node:path";
29036
29165
  function firstTokenBasename(command) {
29037
29166
  const first = command.trimStart().split(/\s+/, 1)[0] ?? "";
29038
29167
  const slash = first.lastIndexOf("/");
@@ -29243,7 +29372,7 @@ function sweepOrphansOnce(deps = {}) {
29243
29372
  }
29244
29373
  function sweepStaleBrokerSockets() {
29245
29374
  try {
29246
- sweepStaleSockets({ dir: dirname7(claudeBrokerSocketPath("", "")), prefix: CLAUDE_BROKER_SOCKET_PREFIX });
29375
+ sweepStaleSockets({ dir: dirname8(claudeBrokerSocketPath("", "")), prefix: CLAUDE_BROKER_SOCKET_PREFIX });
29247
29376
  } catch {
29248
29377
  }
29249
29378
  }
@@ -29293,7 +29422,7 @@ var init_orphan_reaper = __esm({
29293
29422
  });
29294
29423
 
29295
29424
  // packages/server/src/context.ts
29296
- import { join as join27 } from "node:path";
29425
+ import { join as join28 } from "node:path";
29297
29426
  import { randomUUID as randomUUID14 } from "node:crypto";
29298
29427
  function reconcileSessions(storage) {
29299
29428
  for (const row of storage.allSessions()) {
@@ -29428,7 +29557,7 @@ async function createContext(opts = {}) {
29428
29557
  }
29429
29558
  function createContextUnchecked(opts, resources) {
29430
29559
  const project = opts.project ?? resolveProject();
29431
- const dbPath = join27(project.stateDir, "ui.db");
29560
+ const dbPath = join28(project.stateDir, "ui.db");
29432
29561
  const storage = createStorage(dbPath);
29433
29562
  resources.storage = storage;
29434
29563
  const bus = new Bus();
@@ -32418,8 +32547,8 @@ var init_server = __esm({
32418
32547
  });
32419
32548
 
32420
32549
  // packages/server/src/repair.ts
32421
- import { existsSync as existsSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "node:fs";
32422
- import { basename as basename6, dirname as dirname8, resolve as resolve6 } from "node:path";
32550
+ import { existsSync as existsSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
32551
+ import { basename as basename6, dirname as dirname9, resolve as resolve7 } from "node:path";
32423
32552
  function quoteValue(v) {
32424
32553
  if (/^[\w./#:+-]+$/.test(v)) return v;
32425
32554
  return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
@@ -32429,12 +32558,12 @@ function deriveTitle(body, slug) {
32429
32558
  return m ? m[1].trim() : slug;
32430
32559
  }
32431
32560
  function repairThreadFile(frizzDir, file) {
32432
- const root = resolve6(frizzDir);
32433
- const abs = resolve6(root, file);
32434
- if (dirname8(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
32561
+ const root = resolve7(frizzDir);
32562
+ const abs = resolve7(root, file);
32563
+ if (dirname9(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
32435
32564
  if (!abs.endsWith(".md")) throw new RepairError(`refusing to repair "${file}": not a .md thread file`);
32436
- if (!existsSync9(abs)) throw new RepairError(`no thread file to repair: ${basename6(abs)}`);
32437
- const content = readFileSync14(abs, "utf8");
32565
+ if (!existsSync10(abs)) throw new RepairError(`no thread file to repair: ${basename6(abs)}`);
32566
+ const content = readFileSync15(abs, "utf8");
32438
32567
  const firstLine = content.replace(/^/, "").split(/\r?\n/).find((l) => l.trim() !== "");
32439
32568
  if (firstLine?.trim() === "---") {
32440
32569
  throw new RepairError(`${basename6(abs)} already opens with a "---" block \u2014 repair only heals a MISSING frontmatter block`);
@@ -32449,7 +32578,7 @@ function repairThreadFile(frizzDir, file) {
32449
32578
  "---",
32450
32579
  ""
32451
32580
  ].join("\n");
32452
- writeFileSync7(abs, frontmatter + content);
32581
+ writeFileSync8(abs, frontmatter + content);
32453
32582
  return { slug };
32454
32583
  }
32455
32584
  var RepairError, REPAIR_STATUS_TEXT;
@@ -32467,7 +32596,7 @@ var init_repair = __esm({
32467
32596
  });
32468
32597
 
32469
32598
  // cc-worker/hooks/bash-background.mjs
32470
- import { readFileSync as readFileSync15 } from "node:fs";
32599
+ import { readFileSync as readFileSync16 } from "node:fs";
32471
32600
  import { basename as basename7 } from "node:path";
32472
32601
  import { pathToFileURL } from "node:url";
32473
32602
  function emit(obj) {
@@ -32616,7 +32745,7 @@ var init_bash_background = __esm({
32616
32745
  if (isDirectHookExecution(process.argv[1], import.meta.url)) {
32617
32746
  try {
32618
32747
  const env = process.argv.includes("--frizz-thread") ? { ...process.env, FRIZZ_THREAD: process.env.FRIZZ_THREAD || "codex-worker" } : process.env;
32619
- emit(evaluateBashBackgroundHook(JSON.parse(readFileSync15(0, "utf8")), env));
32748
+ emit(evaluateBashBackgroundHook(JSON.parse(readFileSync16(0, "utf8")), env));
32620
32749
  } catch {
32621
32750
  emit({});
32622
32751
  }
@@ -32625,11 +32754,11 @@ var init_bash_background = __esm({
32625
32754
  });
32626
32755
 
32627
32756
  // packages/server/src/transcript.ts
32628
- import { closeSync as closeSync10, existsSync as existsSync10, fstatSync as fstatSync4, mkdirSync as mkdirSync12, openSync as openSync11, readdirSync as readdirSync10, readFileSync as readFileSync16, readSync as readSync6, renameSync as renameSync7, statSync as statSync14, unlinkSync as unlinkSync6, writeFileSync as writeFileSync8 } from "node:fs";
32629
- import { createHash as createHash12 } from "node:crypto";
32757
+ import { closeSync as closeSync11, existsSync as existsSync11, fstatSync as fstatSync4, mkdirSync as mkdirSync13, openSync as openSync12, readdirSync as readdirSync10, readFileSync as readFileSync17, readSync as readSync6, renameSync as renameSync8, statSync as statSync14, unlinkSync as unlinkSync6, writeFileSync as writeFileSync9 } from "node:fs";
32758
+ import { createHash as createHash13 } from "node:crypto";
32630
32759
  import { StringDecoder as StringDecoder4 } from "node:string_decoder";
32631
- import { join as join28 } from "node:path";
32632
- import { homedir as homedir11, tmpdir as tmpdir4 } from "node:os";
32760
+ import { join as join29 } from "node:path";
32761
+ import { homedir as homedir12, tmpdir as tmpdir4 } from "node:os";
32633
32762
  function isInjectedNoise(text) {
32634
32763
  const t = text.trimStart();
32635
32764
  return NOISE_PREFIXES.some((p) => t.startsWith(p));
@@ -33121,14 +33250,14 @@ function pruneScreenshotCache() {
33121
33250
  if (entries.length <= SCREENSHOT_CACHE_MAX) return;
33122
33251
  const byMtime = entries.map((n) => {
33123
33252
  try {
33124
- return { n, m: statSync14(join28(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
33253
+ return { n, m: statSync14(join29(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
33125
33254
  } catch {
33126
33255
  return { n, m: 0 };
33127
33256
  }
33128
33257
  }).sort((a, b) => b.m - a.m);
33129
33258
  for (const { n } of byMtime.slice(SCREENSHOT_CACHE_MAX)) {
33130
33259
  try {
33131
- unlinkSync6(join28(SCREENSHOT_CACHE_DIR, n));
33260
+ unlinkSync6(join29(SCREENSHOT_CACHE_DIR, n));
33132
33261
  } catch {
33133
33262
  }
33134
33263
  }
@@ -33157,17 +33286,17 @@ function persistDataUrlImage(dataUrl, idKey) {
33157
33286
  function persistBase64Image(mediaType, data, idKey) {
33158
33287
  const ext = IMAGE_MEDIA_EXT[typeof mediaType === "string" ? mediaType.toLowerCase() : ""];
33159
33288
  if (!ext || !data) return void 0;
33160
- const name = createHash12("sha256").update(idKey).digest("hex").slice(0, 32);
33161
- const path = join28(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
33289
+ const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
33290
+ const path = join29(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
33162
33291
  try {
33163
- if (existsSync10(path)) return path;
33292
+ if (existsSync11(path)) return path;
33164
33293
  if (data.length > SCREENSHOT_MAX_BASE64) return void 0;
33165
33294
  const buf = Buffer.from(data, "base64");
33166
33295
  if (buf.length === 0 || !looksLikeImage(buf, ext)) return void 0;
33167
- mkdirSync12(SCREENSHOT_CACHE_DIR, { recursive: true });
33168
- const tmp = join28(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
33169
- writeFileSync8(tmp, buf);
33170
- renameSync7(tmp, path);
33296
+ mkdirSync13(SCREENSHOT_CACHE_DIR, { recursive: true });
33297
+ const tmp = join29(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
33298
+ writeFileSync9(tmp, buf);
33299
+ renameSync8(tmp, path);
33171
33300
  pruneScreenshotCache();
33172
33301
  return path;
33173
33302
  } catch {
@@ -33179,17 +33308,17 @@ function persistSentFile(srcPath, idKey) {
33179
33308
  if (!ATTACHMENT_IMAGE_EXTENSIONS.includes(ext)) return void 0;
33180
33309
  const outExt = ext === "jpeg" ? "jpg" : ext;
33181
33310
  try {
33182
- const name = createHash12("sha256").update(idKey).digest("hex").slice(0, 32);
33183
- const dest = join28(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
33184
- if (existsSync10(dest)) return dest;
33311
+ const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
33312
+ const dest = join29(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
33313
+ if (existsSync11(dest)) return dest;
33185
33314
  const size = statSync14(srcPath).size;
33186
33315
  if (size === 0 || size > SENT_IMAGE_MAX_BYTES) return void 0;
33187
- const buf = readFileSync16(srcPath);
33316
+ const buf = readFileSync17(srcPath);
33188
33317
  if (!looksLikeImage(buf, outExt)) return void 0;
33189
- mkdirSync12(SCREENSHOT_CACHE_DIR, { recursive: true });
33190
- const tmp = join28(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
33191
- writeFileSync8(tmp, buf);
33192
- renameSync7(tmp, dest);
33318
+ mkdirSync13(SCREENSHOT_CACHE_DIR, { recursive: true });
33319
+ const tmp = join29(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
33320
+ writeFileSync9(tmp, buf);
33321
+ renameSync8(tmp, dest);
33193
33322
  pruneScreenshotCache();
33194
33323
  return dest;
33195
33324
  } catch {
@@ -33536,11 +33665,11 @@ function retainedFoldEntry(path, identityPrefix, fileId, size) {
33536
33665
  return { entry, hit };
33537
33666
  }
33538
33667
  function readTranscript(project, sessionId) {
33539
- const path = join28(homedir11(), ".claude", "projects", project.cwdSlug, `${sessionId}.jsonl`);
33668
+ const path = join29(homedir12(), ".claude", "projects", project.cwdSlug, `${sessionId}.jsonl`);
33540
33669
  const identityPrefix = `claude:${sessionId}`;
33541
33670
  let fd;
33542
33671
  try {
33543
- fd = openSync11(path, "r");
33672
+ fd = openSync12(path, "r");
33544
33673
  const st = fstatSync4(fd);
33545
33674
  const size = st.size;
33546
33675
  const fileId = `${st.dev}:${st.ino}:${Math.trunc(st.birthtimeMs)}`;
@@ -33559,12 +33688,12 @@ function readTranscript(project, sessionId) {
33559
33688
  } catch {
33560
33689
  return [];
33561
33690
  } finally {
33562
- if (fd !== void 0) closeSync10(fd);
33691
+ if (fd !== void 0) closeSync11(fd);
33563
33692
  }
33564
33693
  }
33565
33694
  function verifyIncrementalParse(path, identityPrefix, incremental) {
33566
33695
  try {
33567
- const fresh = parseTranscript(readFileSync16(path, "utf8"), identityPrefix);
33696
+ const fresh = parseTranscript(readFileSync17(path, "utf8"), identityPrefix);
33568
33697
  const a = JSON.stringify(incremental);
33569
33698
  const b = JSON.stringify(fresh);
33570
33699
  if (a !== b) {
@@ -33584,7 +33713,7 @@ function verifyIncrementalParse(path, identityPrefix, incremental) {
33584
33713
  }
33585
33714
  }
33586
33715
  function logDirOf(project) {
33587
- return join28(homedir11(), ".claude", "projects", project.cwdSlug);
33716
+ return join29(homedir12(), ".claude", "projects", project.cwdSlug);
33588
33717
  }
33589
33718
  function projectCodexTranscript(raw2, identityPrefix = "codex") {
33590
33719
  const out = [];
@@ -33842,7 +33971,7 @@ function latestTranscriptWindow(messages) {
33842
33971
  );
33843
33972
  if (tools.length === 0) continue;
33844
33973
  pinned.push({
33845
- sourceId: `pinned-bg:${createHash12("sha256").update(message.sourceId).digest("base64url").slice(0, 24)}`,
33974
+ sourceId: `pinned-bg:${createHash13("sha256").update(message.sourceId).digest("base64url").slice(0, 24)}`,
33846
33975
  pinnedFromSourceId: message.sourceId,
33847
33976
  role: "assistant",
33848
33977
  text: "",
@@ -34495,7 +34624,7 @@ function sourceForThread(project, storage, slug, backendFor) {
34495
34624
  if (row) {
34496
34625
  const backend = row.backend === "codex" ? "codex" : "claude";
34497
34626
  const nativeId = backend === "codex" ? row.agent_session_id ?? row.session_id : row.transcript_id ?? row.session_id;
34498
- const path = backend === "codex" ? (backendFor?.("codex") ?? defaultCodexBackend()).transcriptPath(nativeId) : join28(logDirOf(project), `${nativeId}.jsonl`);
34627
+ const path = backend === "codex" ? (backendFor?.("codex") ?? defaultCodexBackend()).transcriptPath(nativeId) : join29(logDirOf(project), `${nativeId}.jsonl`);
34499
34628
  if (!path) return void 0;
34500
34629
  return {
34501
34630
  slug,
@@ -34513,7 +34642,7 @@ function sourceForThread(project, storage, slug, backendFor) {
34513
34642
  nativeId: slug,
34514
34643
  backend: "claude",
34515
34644
  runtimeGeneration: 0,
34516
- path: join28(logDirOf(project), `${slug}.jsonl`)
34645
+ path: join29(logDirOf(project), `${slug}.jsonl`)
34517
34646
  };
34518
34647
  }
34519
34648
  function discoveredClaudeSource(project, storage, slug, expectedNativeId) {
@@ -34534,13 +34663,13 @@ function discoveredClaudeSource(project, storage, slug, expectedNativeId) {
34534
34663
  nativeId,
34535
34664
  backend: "claude",
34536
34665
  runtimeGeneration: row.runtime_generation ?? 0,
34537
- path: join28(logDirOf(project), `${nativeId}.jsonl`)
34666
+ path: join29(logDirOf(project), `${nativeId}.jsonl`)
34538
34667
  };
34539
34668
  }
34540
34669
  function fixedSnapshot(source) {
34541
34670
  let fd;
34542
34671
  try {
34543
- fd = openSync11(source.path, "r");
34672
+ fd = openSync12(source.path, "r");
34544
34673
  const before = fstatSync4(fd);
34545
34674
  if (!Number.isSafeInteger(before.size) || before.size < 0) throw new Error("transcript is too large to page safely");
34546
34675
  const bytes = Buffer.allocUnsafe(before.size);
@@ -34555,7 +34684,7 @@ function fixedSnapshot(source) {
34555
34684
  throw new Error("transcript changed while it was being read; retry");
34556
34685
  }
34557
34686
  const fileKey = `${before.dev}:${before.ino}:${Math.trunc(before.birthtimeMs)}`;
34558
- const transcriptKey = createHash12("sha256").update(`${source.slug}\0${source.sessionId}\0${source.nativeId}\0${source.backend}\0${source.runtimeGeneration}\0${fileKey}`).digest("base64url").slice(0, 32);
34687
+ const transcriptKey = createHash13("sha256").update(`${source.slug}\0${source.sessionId}\0${source.nativeId}\0${source.backend}\0${source.runtimeGeneration}\0${fileKey}`).digest("base64url").slice(0, 32);
34559
34688
  let rawText;
34560
34689
  return {
34561
34690
  ...source,
@@ -34571,7 +34700,7 @@ function fixedSnapshot(source) {
34571
34700
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") return void 0;
34572
34701
  throw error;
34573
34702
  } finally {
34574
- if (fd !== void 0) closeSync10(fd);
34703
+ if (fd !== void 0) closeSync11(fd);
34575
34704
  }
34576
34705
  }
34577
34706
  function projectSnapshot(snapshot) {
@@ -34586,7 +34715,7 @@ function projectSnapshot(snapshot) {
34586
34715
  return retireStaleQueuedBubbles([...entry.fold.allMessages()]);
34587
34716
  }
34588
34717
  function digestPrefix(bytes, length = bytes.length) {
34589
- return createHash12("sha256").update(bytes.subarray(0, length)).digest("base64url");
34718
+ return createHash13("sha256").update(bytes.subarray(0, length)).digest("base64url");
34590
34719
  }
34591
34720
  function fullDigest(snapshot) {
34592
34721
  const key = `${snapshot.fileKey}\0${snapshot.bytes.length}`;
@@ -34671,7 +34800,7 @@ function emptyTranscriptPage(source) {
34671
34800
  beforeCursor: null,
34672
34801
  hasEarlier: false,
34673
34802
  reachedTurnBoundary: true,
34674
- transcriptKey: createHash12("sha256").update(keySeed).digest("base64url").slice(0, 32)
34803
+ transcriptKey: createHash13("sha256").update(keySeed).digest("base64url").slice(0, 32)
34675
34804
  };
34676
34805
  }
34677
34806
  function readLatestThreadTranscriptPage(project, storage, slug, backendFor) {
@@ -34738,7 +34867,7 @@ function readEarlierThreadTranscriptPage(project, storage, slug, cursor, backend
34738
34867
  }
34739
34868
  function readCodexTranscriptFile(absPath, nativeId = absPath) {
34740
34869
  try {
34741
- return parseCodexTranscript(readFileSync16(absPath, "utf8"), `codex:${nativeId}`);
34870
+ return parseCodexTranscript(readFileSync17(absPath, "utf8"), `codex:${nativeId}`);
34742
34871
  } catch {
34743
34872
  return [];
34744
34873
  }
@@ -34815,8 +34944,8 @@ function projectTranscriptPageAgentLifecycles(page, lookup) {
34815
34944
  }
34816
34945
  function readTranscriptFile(absPath) {
34817
34946
  try {
34818
- const pathKey = createHash12("sha256").update(absPath).digest("base64url").slice(0, 16);
34819
- return parseTranscript(readFileSync16(absPath, "utf8"), `claude-file:${pathKey}`);
34947
+ const pathKey = createHash13("sha256").update(absPath).digest("base64url").slice(0, 16);
34948
+ return parseTranscript(readFileSync17(absPath, "utf8"), `claude-file:${pathKey}`);
34820
34949
  } catch {
34821
34950
  return [];
34822
34951
  }
@@ -34858,7 +34987,7 @@ var init_transcript = __esm({
34858
34987
  "image/gif": "gif",
34859
34988
  "image/webp": "webp"
34860
34989
  };
34861
- SCREENSHOT_CACHE_DIR = join28(tmpdir4(), "frizz-tool-images");
34990
+ SCREENSHOT_CACHE_DIR = join29(tmpdir4(), "frizz-tool-images");
34862
34991
  SCREENSHOT_CACHE_MAX = 200;
34863
34992
  SCREENSHOT_MAX_BASE64 = 32e6;
34864
34993
  screenshotTmpSeq = 0;
@@ -34910,8 +35039,8 @@ var init_open_external = __esm({
34910
35039
  // packages/server/src/local-file.ts
34911
35040
  import { spawn as spawn6 } from "node:child_process";
34912
35041
  import { realpathSync as realpathSync7, statSync as statSync15 } from "node:fs";
34913
- import { homedir as homedir12 } from "node:os";
34914
- import { isAbsolute as isAbsolute3, join as join29, resolve as resolve7, sep } from "node:path";
35042
+ import { homedir as homedir13 } from "node:os";
35043
+ import { isAbsolute as isAbsolute3, join as join30, resolve as resolve8, sep } from "node:path";
34915
35044
  function isUnder(real, root) {
34916
35045
  let rootReal;
34917
35046
  try {
@@ -34938,10 +35067,10 @@ function resolveLocalFile(rawPath, roots) {
34938
35067
  }
34939
35068
  return real;
34940
35069
  }
34941
- function resolveOpenableFile(raw2, projectDir, roots, home = homedir12()) {
35070
+ function resolveOpenableFile(raw2, projectDir, roots, home = homedir13()) {
34942
35071
  const trimmed = raw2.trim().replace(/:\d+(?::\d+)?$/, "");
34943
35072
  if (!trimmed) return null;
34944
- const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ? join29(home, trimmed.slice(2)) : isAbsolute3(trimmed) ? trimmed : resolve7(projectDir, trimmed);
35073
+ const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ? join30(home, trimmed.slice(2)) : isAbsolute3(trimmed) ? trimmed : resolve8(projectDir, trimmed);
34945
35074
  try {
34946
35075
  return resolveLocalFile(abs, roots);
34947
35076
  } catch {
@@ -35007,7 +35136,7 @@ var init_account_actions = __esm({
35007
35136
  });
35008
35137
 
35009
35138
  // packages/server/src/awaiting.ts
35010
- import { createHash as createHash13 } from "node:crypto";
35139
+ import { createHash as createHash14 } from "node:crypto";
35011
35140
  function parsePrRef2(value) {
35012
35141
  const m = value.trim().match(PR_REF_RE2);
35013
35142
  if (!m) return void 0;
@@ -35022,7 +35151,7 @@ function isActionableAwaitingHint(hint) {
35022
35151
  return false;
35023
35152
  }
35024
35153
  function awaitingFenceIdentity(hint, fenceAt) {
35025
- return createHash13("sha256").update(fenceAt).update("\0").update(hint.kind).update("\0").update(hint.value).digest("hex");
35154
+ return createHash14("sha256").update(fenceAt).update("\0").update(hint.kind).update("\0").update(hint.value).digest("hex");
35026
35155
  }
35027
35156
  var PR_REF_RE2;
35028
35157
  var init_awaiting = __esm({
@@ -35109,11 +35238,11 @@ var init_external_terminal = __esm({
35109
35238
  });
35110
35239
 
35111
35240
  // packages/server/src/background-shell-output.ts
35112
- import { closeSync as closeSync11, fstatSync as fstatSync5, openSync as openSync12, readSync as readSync7 } from "node:fs";
35241
+ import { closeSync as closeSync12, fstatSync as fstatSync5, openSync as openSync13, readSync as readSync7 } from "node:fs";
35113
35242
  function readBackgroundShellOutput(path, maxBytes = OUTPUT_TAIL_BYTES) {
35114
35243
  let fd;
35115
35244
  try {
35116
- fd = openSync12(path, "r");
35245
+ fd = openSync13(path, "r");
35117
35246
  const size = fstatSync5(fd).size;
35118
35247
  const length = Math.min(size, maxBytes);
35119
35248
  const offset = Math.max(0, size - length);
@@ -35129,13 +35258,13 @@ function readBackgroundShellOutput(path, maxBytes = OUTPUT_TAIL_BYTES) {
35129
35258
  } catch {
35130
35259
  return { output: "", truncated: false };
35131
35260
  } finally {
35132
- if (fd !== void 0) closeSync11(fd);
35261
+ if (fd !== void 0) closeSync12(fd);
35133
35262
  }
35134
35263
  }
35135
35264
  function backgroundShellLineCount(path) {
35136
35265
  let fd;
35137
35266
  try {
35138
- fd = openSync12(path, "r");
35267
+ fd = openSync13(path, "r");
35139
35268
  const stat2 = fstatSync5(fd);
35140
35269
  const size = stat2.size;
35141
35270
  let state = scans.get(path);
@@ -35174,7 +35303,7 @@ function backgroundShellLineCount(path) {
35174
35303
  } catch {
35175
35304
  return void 0;
35176
35305
  } finally {
35177
- if (fd !== void 0) closeSync11(fd);
35306
+ if (fd !== void 0) closeSync12(fd);
35178
35307
  }
35179
35308
  }
35180
35309
  var OUTPUT_TAIL_BYTES, SCAN_CHUNK_BYTES, SCAN_CEILING_BYTES, SCAN_CACHE_LIMIT, ANSI_ESCAPE_RE, scans;
@@ -35191,8 +35320,8 @@ var init_background_shell_output = __esm({
35191
35320
  });
35192
35321
 
35193
35322
  // packages/server/src/router.ts
35194
- import { readFileSync as readFileSync17 } from "node:fs";
35195
- import { join as join30 } from "node:path";
35323
+ import { readFileSync as readFileSync18 } from "node:fs";
35324
+ import { join as join31 } from "node:path";
35196
35325
  import { randomUUID as randomUUID15 } from "node:crypto";
35197
35326
  function validateGithubDispatchProfile(input) {
35198
35327
  validateThreadProfile(input.backend, input.model, input.effort);
@@ -35328,7 +35457,7 @@ async function stopAndForgetRegisteredRuntime(storage, row, runtime = cachedLive
35328
35457
  return forgotten;
35329
35458
  }
35330
35459
  function createRouter(ctx) {
35331
- const frizzDir = join30(ctx.project.dir, ".frizz");
35460
+ const frizzDir = join31(ctx.project.dir, ".frizz");
35332
35461
  const openRoots = openableFileRoots(ctx.project);
35333
35462
  function isAutoTitledSession(slug) {
35334
35463
  return ctx.storage.getSession(slug)?.title_auto === 1;
@@ -36445,7 +36574,7 @@ function createRouter(ctx) {
36445
36574
  const row = ctx.storage.getSession(input.slug);
36446
36575
  if (!row) return { markdown: "" };
36447
36576
  try {
36448
- return { markdown: readFileSync17(join30(ctx.project.dir, scratchpadRelPath(row.session_id)), "utf8") };
36577
+ return { markdown: readFileSync18(join31(ctx.project.dir, scratchpadRelPath(row.session_id)), "utf8") };
36449
36578
  } catch {
36450
36579
  return { markdown: "" };
36451
36580
  }
@@ -36980,7 +37109,7 @@ var init_local_origin = __esm({
36980
37109
  });
36981
37110
 
36982
37111
  // packages/server/src/local-image.ts
36983
- import { readFileSync as readFileSync18, realpathSync as realpathSync8, statSync as statSync16 } from "node:fs";
37112
+ import { readFileSync as readFileSync19, realpathSync as realpathSync8, statSync as statSync16 } from "node:fs";
36984
37113
  import { extname, isAbsolute as isAbsolute4 } from "node:path";
36985
37114
  function resolveLocalImage(rawPath) {
36986
37115
  if (!rawPath || !isAbsolute4(rawPath)) return { status: 400 };
@@ -36994,7 +37123,7 @@ function resolveLocalImage(rawPath) {
36994
37123
  }
36995
37124
  try {
36996
37125
  if (!statSync16(real).isFile()) return { status: 404 };
36997
- return { status: 200, contentType, body: readFileSync18(real) };
37126
+ return { status: 200, contentType, body: readFileSync19(real) };
36998
37127
  } catch {
36999
37128
  return { status: 404 };
37000
37129
  }
@@ -37014,8 +37143,8 @@ var init_local_image = __esm({
37014
37143
  });
37015
37144
 
37016
37145
  // packages/server/src/local-visualization.ts
37017
- import { readdirSync as readdirSync11, readFileSync as readFileSync19, realpathSync as realpathSync9, statSync as statSync17 } from "node:fs";
37018
- import { join as join31, sep as sep2 } from "node:path";
37146
+ import { readdirSync as readdirSync11, readFileSync as readFileSync20, realpathSync as realpathSync9, statSync as statSync17 } from "node:fs";
37147
+ import { join as join32, sep as sep2 } from "node:path";
37019
37148
  function children(path, pattern) {
37020
37149
  try {
37021
37150
  return readdirSync11(path, { withFileTypes: true }).filter((entry) => entry.isDirectory() && pattern.test(entry.name)).map((entry) => entry.name).sort().reverse();
@@ -37027,7 +37156,7 @@ function isUnder2(path, root) {
37027
37156
  return path === root || path.startsWith(root.endsWith(sep2) ? root : root + sep2);
37028
37157
  }
37029
37158
  function resolveFragment(projectDir, sessionId, file) {
37030
- const base = join31(projectDir, ".codex", "visualizations");
37159
+ const base = join32(projectDir, ".codex", "visualizations");
37031
37160
  let projectReal;
37032
37161
  let baseReal;
37033
37162
  try {
@@ -37038,12 +37167,12 @@ function resolveFragment(projectDir, sessionId, file) {
37038
37167
  }
37039
37168
  if (!isUnder2(baseReal, projectReal)) return null;
37040
37169
  for (const year of children(base, YEAR_PART)) {
37041
- const yearDir = join31(base, year);
37170
+ const yearDir = join32(base, year);
37042
37171
  for (const month of children(yearDir, DATE_PART)) {
37043
- const monthDir = join31(yearDir, month);
37172
+ const monthDir = join32(yearDir, month);
37044
37173
  for (const day of children(monthDir, DATE_PART)) {
37045
- const sessionRoot = join31(baseReal, year, month, day, sessionId);
37046
- const candidate = join31(monthDir, day, sessionId, file);
37174
+ const sessionRoot = join32(baseReal, year, month, day, sessionId);
37175
+ const candidate = join32(monthDir, day, sessionId, file);
37047
37176
  try {
37048
37177
  const real = realpathSync9(candidate);
37049
37178
  if (isUnder2(real, sessionRoot) && statSync17(real).isFile()) return real;
@@ -37129,7 +37258,7 @@ function resolveLocalVisualization(projectDir, sessionId, file) {
37129
37258
  try {
37130
37259
  const size = statSync17(path).size;
37131
37260
  if (size > MAX_FRAGMENT_BYTES) return { status: 413 };
37132
- fragment = readFileSync19(path, "utf8");
37261
+ fragment = readFileSync20(path, "utf8");
37133
37262
  } catch {
37134
37263
  return { status: 404 };
37135
37264
  }
@@ -37171,8 +37300,8 @@ var init_local_visualization = __esm({
37171
37300
  });
37172
37301
 
37173
37302
  // packages/server/src/app.ts
37174
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync9 } from "node:fs";
37175
- import { join as join32 } from "node:path";
37303
+ import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync10 } from "node:fs";
37304
+ import { join as join33 } from "node:path";
37176
37305
  import { randomUUID as randomUUID16 } from "node:crypto";
37177
37306
  function createApp(ctx, options = {}) {
37178
37307
  const app = new Hono2();
@@ -37249,11 +37378,11 @@ function createApp(ctx, options = {}) {
37249
37378
  if (typeof body.data !== "string" || body.data.length > ATTACHMENT_MAX_BASE64_CHARS) return c.json({ error: "bad payload" }, 400);
37250
37379
  const ext = `.${attachmentExtension(name)}`;
37251
37380
  const buf = Buffer.from(body.data, "base64");
37252
- const dir = join32(ctx.project.stateDir, "attachments");
37253
- mkdirSync13(dir, { recursive: true });
37381
+ const dir = join33(ctx.project.stateDir, "attachments");
37382
+ mkdirSync14(dir, { recursive: true });
37254
37383
  const base = name.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]+/g, "-").slice(0, 40) || "file";
37255
- const path = join32(dir, `${Date.now()}-${randomUUID16().slice(0, 8)}-${base}${ext}`);
37256
- writeFileSync9(path, buf);
37384
+ const path = join33(dir, `${Date.now()}-${randomUUID16().slice(0, 8)}-${base}${ext}`);
37385
+ writeFileSync10(path, buf);
37257
37386
  return c.json({ path });
37258
37387
  });
37259
37388
  app.get(
@@ -37280,10 +37409,10 @@ function createApp(ctx, options = {}) {
37280
37409
  const heartbeat = setInterval(() => void stream2.writeSSE({ event: "heartbeat", data: "" }).catch(() => {
37281
37410
  }), 1e4);
37282
37411
  await new Promise(
37283
- (resolve9) => stream2.onAbort(() => {
37412
+ (resolve10) => stream2.onAbort(() => {
37284
37413
  unsubscribe();
37285
37414
  clearInterval(heartbeat);
37286
- resolve9();
37415
+ resolve10();
37287
37416
  })
37288
37417
  );
37289
37418
  })
@@ -37664,13 +37793,13 @@ function createTerminalServer(deps = {}) {
37664
37793
  }
37665
37794
  for (const viewer of [...viewers]) viewer.shutdown();
37666
37795
  let drainTimer;
37667
- const boundedServerDrain = new Promise((resolve9) => {
37796
+ const boundedServerDrain = new Promise((resolve10) => {
37668
37797
  let resolved = false;
37669
37798
  const finish = () => {
37670
37799
  if (resolved) return;
37671
37800
  resolved = true;
37672
37801
  clearTimeout(drainTimer);
37673
- resolve9();
37802
+ resolve10();
37674
37803
  };
37675
37804
  drainTimer = setTimeout(finish, shutdownGraceMs);
37676
37805
  try {
@@ -37710,7 +37839,7 @@ var init_terminal = __esm({
37710
37839
  });
37711
37840
 
37712
37841
  // packages/server/src/app-socket.ts
37713
- import { createHash as createHash14 } from "node:crypto";
37842
+ import { createHash as createHash15 } from "node:crypto";
37714
37843
  function isWsPath(url) {
37715
37844
  return (url ?? "").split("?")[0] === WS_PATH;
37716
37845
  }
@@ -37845,7 +37974,7 @@ function createAppSocketServer(deps) {
37845
37974
  sendEncoded(ws, frame, false);
37846
37975
  }
37847
37976
  function frameSignature(frame) {
37848
- return createHash14("sha256").update(frame.text).digest("base64url");
37977
+ return createHash15("sha256").update(frame.text).digest("base64url");
37849
37978
  }
37850
37979
  const globalReadTimes = [];
37851
37980
  const originReadTimes = /* @__PURE__ */ new Map();
@@ -38343,13 +38472,13 @@ function createAppSocketServer(deps) {
38343
38472
  clearTranscriptSnapshots();
38344
38473
  globalReadTimes.length = 0;
38345
38474
  originReadTimes.clear();
38346
- const socketDrains = [...wss.clients].map((ws) => new Promise((resolve9) => {
38347
- if (ws.readyState === ws.CLOSED) return resolve9();
38348
- ws.once("close", () => resolve9());
38475
+ const socketDrains = [...wss.clients].map((ws) => new Promise((resolve10) => {
38476
+ if (ws.readyState === ws.CLOSED) return resolve10();
38477
+ ws.once("close", () => resolve10());
38349
38478
  try {
38350
38479
  ws.terminate();
38351
38480
  } catch {
38352
- resolve9();
38481
+ resolve10();
38353
38482
  }
38354
38483
  }));
38355
38484
  lastSig.clear();
@@ -38475,10 +38604,10 @@ var init_app_socket = __esm({
38475
38604
  });
38476
38605
 
38477
38606
  // packages/server/src/boot-progress.ts
38478
- import { mkdirSync as mkdirSync14, readFileSync as readFileSync20, renameSync as renameSync8, rmSync as rmSync6, writeFileSync as writeFileSync10 } from "node:fs";
38479
- import { basename as basename8, dirname as dirname9, join as join33 } from "node:path";
38607
+ import { mkdirSync as mkdirSync15, readFileSync as readFileSync21, renameSync as renameSync9, rmSync as rmSync7, writeFileSync as writeFileSync11 } from "node:fs";
38608
+ import { basename as basename8, dirname as dirname10, join as join34 } from "node:path";
38480
38609
  function bootProgressPath(stateDir) {
38481
- return join33(stateDir, BOOT_PROGRESS_NAME);
38610
+ return join34(stateDir, BOOT_PROGRESS_NAME);
38482
38611
  }
38483
38612
  function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
38484
38613
  if (!stateDir) {
@@ -38498,18 +38627,18 @@ function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
38498
38627
  lastAt = now;
38499
38628
  step++;
38500
38629
  try {
38501
- mkdirSync14(dirname9(path), { recursive: true, mode: 448 });
38502
- const temp = join33(dirname9(path), `.${basename8(path)}.${process.pid}.tmp`);
38503
- writeFileSync10(temp, `${JSON.stringify({ pid: process.pid, step, phase, at: new Date(now).toISOString() })}
38630
+ mkdirSync15(dirname10(path), { recursive: true, mode: 448 });
38631
+ const temp = join34(dirname10(path), `.${basename8(path)}.${process.pid}.tmp`);
38632
+ writeFileSync11(temp, `${JSON.stringify({ pid: process.pid, step, phase, at: new Date(now).toISOString() })}
38504
38633
  `, "utf8");
38505
- renameSync8(temp, path);
38634
+ renameSync9(temp, path);
38506
38635
  } catch {
38507
38636
  }
38508
38637
  };
38509
38638
  return Object.assign(write, {
38510
38639
  done: () => {
38511
38640
  try {
38512
- rmSync6(path, { force: true });
38641
+ rmSync7(path, { force: true });
38513
38642
  } catch {
38514
38643
  }
38515
38644
  }
@@ -38534,8 +38663,8 @@ __export(index_exports, {
38534
38663
  startServer: () => startServer
38535
38664
  });
38536
38665
  import { createServer } from "node:http";
38537
- import { readFileSync as readFileSync21, existsSync as existsSync11 } from "node:fs";
38538
- import { join as join34, resolve as resolve8, extname as extname2, normalize } from "node:path";
38666
+ import { readFileSync as readFileSync22, existsSync as existsSync12 } from "node:fs";
38667
+ import { join as join35, resolve as resolve9, extname as extname2, normalize } from "node:path";
38539
38668
  async function pipeToApp(app, req, res, port2, controller) {
38540
38669
  const url = `http://127.0.0.1:${port2}${req.url ?? "/"}`;
38541
38670
  res.on("close", () => {
@@ -38604,11 +38733,11 @@ function createShutdownSignalHandler(options) {
38604
38733
  }
38605
38734
  function serveStatic(distDir, req, res) {
38606
38735
  const rel = normalize((req.url ?? "/").split("?")[0]).replace(/^(\.\.[/\\])+/, "");
38607
- let file = join34(distDir, rel === "/" ? "index.html" : rel);
38608
- if (!file.startsWith(distDir)) file = join34(distDir, "index.html");
38609
- if (!existsSync11(file)) file = join34(distDir, "index.html");
38736
+ let file = join35(distDir, rel === "/" ? "index.html" : rel);
38737
+ if (!file.startsWith(distDir)) file = join35(distDir, "index.html");
38738
+ if (!existsSync12(file)) file = join35(distDir, "index.html");
38610
38739
  try {
38611
- const body = readFileSync21(file);
38740
+ const body = readFileSync22(file);
38612
38741
  res.writeHead(200, { "content-type": MIME[extname2(file)] ?? "application/octet-stream" });
38613
38742
  res.end(body);
38614
38743
  } catch {
@@ -38893,9 +39022,9 @@ async function startServer(opts = {}) {
38893
39022
  } else {
38894
39023
  await phase("wake scheduler", () => void 0);
38895
39024
  }
38896
- statusPath = join34(ctx.project.stateDir, "server.lock");
38897
- const webRoot = resolve8(import.meta.dirname, "..", "..", "web");
38898
- const distDir = opts.webDistDir ? resolve8(opts.webDistDir) : join34(webRoot, "dist");
39025
+ statusPath = join35(ctx.project.stateDir, "server.lock");
39026
+ const webRoot = resolve9(import.meta.dirname, "..", "..", "web");
39027
+ const distDir = opts.webDistDir ? resolve9(opts.webDistDir) : join35(webRoot, "dist");
38899
39028
  startupPhase = "Vite";
38900
39029
  if (opts.dev) {
38901
39030
  try {
@@ -38939,7 +39068,7 @@ async function startServer(opts = {}) {
38939
39068
  if (vite) {
38940
39069
  vite.middlewares(req, res, () => {
38941
39070
  try {
38942
- const html = readFileSync21(join34(webRoot, "index.html"), "utf8");
39071
+ const html = readFileSync22(join35(webRoot, "index.html"), "utf8");
38943
39072
  void vite.transformIndexHtml(url, html).then((out) => {
38944
39073
  res.writeHead(200, { "content-type": "text/html" });
38945
39074
  res.end(out);
@@ -38951,7 +39080,7 @@ async function startServer(opts = {}) {
38951
39080
  });
38952
39081
  return;
38953
39082
  }
38954
- if (existsSync11(distDir)) {
39083
+ if (existsSync12(distDir)) {
38955
39084
  serveStatic(distDir, req, res);
38956
39085
  return;
38957
39086
  }
@@ -39119,8 +39248,8 @@ init_project();
39119
39248
  init_project_launch();
39120
39249
  init_shutdown();
39121
39250
  init_logging();
39122
- import { existsSync as existsSync12 } from "node:fs";
39123
- import { join as join35 } from "node:path";
39251
+ import { existsSync as existsSync13 } from "node:fs";
39252
+ import { join as join36 } from "node:path";
39124
39253
  process.on("uncaughtException", (error) => {
39125
39254
  log.error("dev-child", `uncaught exception: ${error instanceof Error ? error.stack ?? error.message : error}`);
39126
39255
  process.exit(1);
@@ -39158,9 +39287,9 @@ try {
39158
39287
  ["FRIZZ_SCRIPTS_DIR", process.env.FRIZZ_SCRIPTS_DIR, "index.mjs"],
39159
39288
  ["FRIZZ_WORKER_PLUGIN_DIR", process.env.FRIZZ_WORKER_PLUGIN_DIR, ".claude-plugin/plugin.json"]
39160
39289
  ];
39161
- if (!existsSync12(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
39290
+ if (!existsSync13(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
39162
39291
  for (const [name, directory, requiredFile] of required) {
39163
- if (!directory || !existsSync12(join35(directory, requiredFile)))
39292
+ if (!directory || !existsSync13(join36(directory, requiredFile)))
39164
39293
  throw new Error(`stable artifact launch is missing verified ${name}`);
39165
39294
  }
39166
39295
  }