frizz 0.7.5 → 0.7.7

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.
Files changed (93) hide show
  1. package/README.md +28 -15
  2. package/dist/dev-child.js +299 -264
  3. package/dist/frizz.js +12895 -6495
  4. package/package.json +5 -3
  5. package/runtime/cc-worker/DECISIONS.md +11 -0
  6. package/web-dist/assets/{TerminalPane-Cyao7kTi.js → TerminalPane-Cb8jOFP9.js} +1 -1
  7. package/web-dist/assets/{abnfDiagram-VRR7QNED-D1U0Q_zY.js → abnfDiagram-VRR7QNED-Dtbg2eZ0.js} +1 -1
  8. package/web-dist/assets/architecture-TIHT7OUA-CTxVpl9_.js +1 -0
  9. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-CtUBwBcU.js → architectureDiagram-ZJ3FMSHR-DzQjWW7u.js} +1 -1
  10. package/web-dist/assets/{blockDiagram-677ZJIJ3-OzqrN18g.js → blockDiagram-677ZJIJ3-BJnpkLMt.js} +1 -1
  11. package/web-dist/assets/{c4Diagram-LMCZKHZV-DgYAtD7L.js → c4Diagram-LMCZKHZV-COdatsYu.js} +1 -1
  12. package/web-dist/assets/channel-COS0Ygbp.js +1 -0
  13. package/web-dist/assets/{chunk-32BRIVSS-CKwBruPa.js → chunk-32BRIVSS-CORMw4Vm.js} +1 -1
  14. package/web-dist/assets/{chunk-52WLFC77-gvoNW_ar.js → chunk-52WLFC77-C7lEadTg.js} +1 -1
  15. package/web-dist/assets/{chunk-C7G6YPKG-EJ5BdmRQ.js → chunk-C7G6YPKG-DZy4F97l.js} +1 -1
  16. package/web-dist/assets/{chunk-EX3LRPZG-DJQF-VwN.js → chunk-EX3LRPZG-HynlfV9p.js} +1 -1
  17. package/web-dist/assets/{chunk-FWX5IMBZ-CXBLvjvR.js → chunk-FWX5IMBZ-BbwKNhKm.js} +2 -2
  18. package/web-dist/assets/{chunk-HOUHSVGY-De3ULdBq.js → chunk-HOUHSVGY-lIhOZSmL.js} +1 -1
  19. package/web-dist/assets/{chunk-ICXQ74PX-aUbMdGsl.js → chunk-ICXQ74PX-WGxaMO8c.js} +1 -1
  20. package/web-dist/assets/{chunk-MOJQB5TN-BLK44SUW.js → chunk-MOJQB5TN-B-cx0f3u.js} +1 -1
  21. package/web-dist/assets/{chunk-OGEWGWER-CQZ3zQ2q.js → chunk-OGEWGWER-DJceVwZH.js} +1 -1
  22. package/web-dist/assets/{chunk-PUDLZKDR-DcdN44K2.js → chunk-PUDLZKDR-CGwHZns8.js} +1 -1
  23. package/web-dist/assets/{chunk-Q4XR5HBZ-Db2ge7fW.js → chunk-Q4XR5HBZ-PTSWtmk1.js} +1 -1
  24. package/web-dist/assets/{chunk-V7JOEXUC-D80jxcmB.js → chunk-V7JOEXUC-VNxHZPcf.js} +1 -1
  25. package/web-dist/assets/{chunk-VAUOI2AC-nDGsXZZE.js → chunk-VAUOI2AC-ZXYCz_Aw.js} +1 -1
  26. package/web-dist/assets/{chunk-VR4S4FIN-BGXgLAsD.js → chunk-VR4S4FIN-9WCtmFJp.js} +1 -1
  27. package/web-dist/assets/{chunk-WYO6CB5R-BbGEK50o.js → chunk-WYO6CB5R-V4EBjpmt.js} +1 -1
  28. package/web-dist/assets/{chunk-ZGVPDNZ5-CjEI23Vu.js → chunk-ZGVPDNZ5-CPW0Z0ae.js} +1 -1
  29. package/web-dist/assets/classDiagram-OUVF2IWQ-Df5TLnrN.js +1 -0
  30. package/web-dist/assets/classDiagram-v2-EOCWNBFH-Df5TLnrN.js +1 -0
  31. package/web-dist/assets/{cynefin-VYW2F7L2-CR69iDgw.js → cynefin-VYW2F7L2-E7PklfJD.js} +1 -1
  32. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-Le_FSC65.js → cynefinDiagram-TSTJHNR4-JIXAPjDf.js} +1 -1
  33. package/web-dist/assets/{dagre-VKFMJZFB-CxAlFDI9.js → dagre-VKFMJZFB-DjXrdcNx.js} +1 -1
  34. package/web-dist/assets/{diagram-FQU43EPY-BFMwv6Pj.js → diagram-FQU43EPY--i9i0qhm.js} +1 -1
  35. package/web-dist/assets/{diagram-G47NLZAW-mWAc5hJ0.js → diagram-G47NLZAW-DxgcENZ_.js} +1 -1
  36. package/web-dist/assets/{diagram-NH7WQ7WH-CC-QXuir.js → diagram-NH7WQ7WH-CUy9Nr90.js} +1 -1
  37. package/web-dist/assets/{diagram-OA4YK3LP-Cqs5o39q.js → diagram-OA4YK3LP-DbTbUaCb.js} +1 -1
  38. package/web-dist/assets/{diagram-WEI45ONY-B9PF6IpG.js → diagram-WEI45ONY-2gk6xhOq.js} +1 -1
  39. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-C1DkTGUE.js → ebnfDiagram-CCIWWBDH-uE2iDETg.js} +1 -1
  40. package/web-dist/assets/{erDiagram-Q63AITRT-CbCG5w3K.js → erDiagram-Q63AITRT-dztd4MUw.js} +1 -1
  41. package/web-dist/assets/eventmodeling-45OFAUF4-DPVPOEaJ.js +1 -0
  42. package/web-dist/assets/flowDiagram-23GEKE2U-BMIMgVYd.js +1 -0
  43. package/web-dist/assets/{ganttDiagram-NO4QXBWP-CaywKz56.js → ganttDiagram-NO4QXBWP-DAds6Aht.js} +1 -1
  44. package/web-dist/assets/{gitGraph-TEB2WS4Q-DhbijOBs.js → gitGraph-TEB2WS4Q-Ci0XVvIa.js} +1 -1
  45. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-DHngf1QZ.js → gitGraphDiagram-IHSO6WYX-C6FULyt8.js} +1 -1
  46. package/web-dist/assets/{index-CxwWndgM.js → index-CNy5uOpI.js} +116 -111
  47. package/web-dist/assets/{index-C-3lsl4q.css → index-D6LsViUY.css} +1 -1
  48. package/web-dist/assets/{info-DKCQHKI2-D2uo8Yq_.js → info-DKCQHKI2-9N77dOiw.js} +1 -1
  49. package/web-dist/assets/{infoDiagram-FWYZ7A6U-Bixn1mvJ.js → infoDiagram-FWYZ7A6U-BymP3PgG.js} +1 -1
  50. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-DG48ASOp.js → ishikawaDiagram-FXEZZL3T-CU_kQBz1.js} +1 -1
  51. package/web-dist/assets/{journeyDiagram-5HDEW3XC-DpQOwYAS.js → journeyDiagram-5HDEW3XC-DZN15HSd.js} +1 -1
  52. package/web-dist/assets/{kanban-definition-HUTT4EX6-Dph0AMZo.js → kanban-definition-HUTT4EX6-J4wR5g_3.js} +1 -1
  53. package/web-dist/assets/{line-hnYRfUMr.js → line-SRzGpiDr.js} +1 -1
  54. package/web-dist/assets/{mermaid-parser.core-DdD3ClpS.js → mermaid-parser.core-CGBscNGo.js} +3 -3
  55. package/web-dist/assets/{mermaid.core-C2DMq9ss.js → mermaid.core-xNdwXb1r.js} +3 -3
  56. package/web-dist/assets/{mindmap-definition-LN4V7U3C-CirJBG-x.js → mindmap-definition-LN4V7U3C-gR2dbzrj.js} +1 -1
  57. package/web-dist/assets/{packet-7NZHBO7P-kD-OtFAF.js → packet-7NZHBO7P-DrR4W6I3.js} +1 -1
  58. package/web-dist/assets/{pegDiagram-2B236MQR-DGmi8fl-.js → pegDiagram-2B236MQR-DN7R-_t4.js} +1 -1
  59. package/web-dist/assets/{pie-RZYD4A2V-DpKplj-N.js → pie-RZYD4A2V-C8VjQAFZ.js} +1 -1
  60. package/web-dist/assets/{pieDiagram-ENE6RG2P-CW-zVLyR.js → pieDiagram-ENE6RG2P-5w64zdD1.js} +1 -1
  61. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-fxSaIvo2.js → quadrantDiagram-ABIIQ3AL-B4rbezq_.js} +1 -1
  62. package/web-dist/assets/{radar-I7S5WNFK-BPu7ClHP.js → radar-I7S5WNFK-CTbbPB8m.js} +1 -1
  63. package/web-dist/assets/{railroad-3IZDKUUU-CoQXFYm6.js → railroad-3IZDKUUU-CY1er15b.js} +1 -1
  64. package/web-dist/assets/railroad-abnf-AHOZXSZD-DfEpkrtJ.js +1 -0
  65. package/web-dist/assets/railroad-ebnf-EBAXGLYW-Csunejgu.js +1 -0
  66. package/web-dist/assets/railroad-peg-LSFZ7HO6-BgRslbM_.js +1 -0
  67. package/web-dist/assets/{railroadDiagram-RFXS5EU6-Bqnz_3Bc.js → railroadDiagram-RFXS5EU6-Bx2HJ3yT.js} +1 -1
  68. package/web-dist/assets/{requirementDiagram-TGXJPOKE-DJHMdBhh.js → requirementDiagram-TGXJPOKE-BLK-Y2rx.js} +1 -1
  69. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-BlxzmT-W.js → sankeyDiagram-HTMAVEWB-Dk-8Miv-.js} +1 -1
  70. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-BT7Rn1Uo.js → sequenceDiagram-DBY2YBRQ-DL2alfR-.js} +1 -1
  71. package/web-dist/assets/{stateDiagram-2N3HPSRC-CDoiFcke.js → stateDiagram-2N3HPSRC-Bka44wf1.js} +1 -1
  72. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-6KcScVPX.js +1 -0
  73. package/web-dist/assets/{swimlanes-5IMT3BWC-DtzTgSSP.js → swimlanes-5IMT3BWC-e0GbMwIr.js} +1 -1
  74. package/web-dist/assets/swimlanesDiagram-G3AALYLV-jaJhlDbE.js +8 -0
  75. package/web-dist/assets/{timeline-definition-FHXFAJF6-Dn63VmSO.js → timeline-definition-FHXFAJF6-CT3GFq89.js} +1 -1
  76. package/web-dist/assets/{treeView-QDETBFTQ-DIfJIc9R.js → treeView-QDETBFTQ-BJauJ0bm.js} +1 -1
  77. package/web-dist/assets/{treemap-6X3UGDF4-n9Fwqngl.js → treemap-6X3UGDF4-DCX7A-nx.js} +1 -1
  78. package/web-dist/assets/{vennDiagram-L72KCM5P-C1thEMxE.js → vennDiagram-L72KCM5P-D4dm2iTR.js} +1 -1
  79. package/web-dist/assets/{wardley-OPB4EBWU-Dl6RiScD.js → wardley-OPB4EBWU-DklTDSId.js} +1 -1
  80. package/web-dist/assets/{wardleyDiagram-EHGQE667-DBelgTwB.js → wardleyDiagram-EHGQE667-CikP5hBd.js} +1 -1
  81. package/web-dist/assets/{xychartDiagram-FW5EYKEG-DFGVnPLj.js → xychartDiagram-FW5EYKEG-FXuOAFpz.js} +1 -1
  82. package/web-dist/index.html +2 -2
  83. package/web-dist/assets/architecture-TIHT7OUA-BS8x9TQa.js +0 -1
  84. package/web-dist/assets/channel-DHZV3ADN.js +0 -1
  85. package/web-dist/assets/classDiagram-OUVF2IWQ-Dcx3TDdU.js +0 -1
  86. package/web-dist/assets/classDiagram-v2-EOCWNBFH-Dcx3TDdU.js +0 -1
  87. package/web-dist/assets/eventmodeling-45OFAUF4-DAhP7KCX.js +0 -1
  88. package/web-dist/assets/flowDiagram-23GEKE2U-Be2iuqwq.js +0 -1
  89. package/web-dist/assets/railroad-abnf-AHOZXSZD-BiqkuXNr.js +0 -1
  90. package/web-dist/assets/railroad-ebnf-EBAXGLYW-CDaukY4Z.js +0 -1
  91. package/web-dist/assets/railroad-peg-LSFZ7HO6-CsUPdvVL.js +0 -1
  92. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DiLnjG8k.js +0 -1
  93. package/web-dist/assets/swimlanesDiagram-G3AALYLV-BqvWOcR2.js +0 -8
package/dist/dev-child.js CHANGED
@@ -12905,6 +12905,16 @@ var init_receipt_bus = __esm({
12905
12905
  }
12906
12906
  });
12907
12907
 
12908
+ // packages/shared/src/relay-protocol.ts
12909
+ var RELAY_MAX_FRAME_BODY, RELAY_MAX_WS_CHUNK;
12910
+ var init_relay_protocol = __esm({
12911
+ "packages/shared/src/relay-protocol.ts"() {
12912
+ "use strict";
12913
+ RELAY_MAX_FRAME_BODY = 512 * 1024;
12914
+ RELAY_MAX_WS_CHUNK = 64 * 1024;
12915
+ }
12916
+ });
12917
+
12908
12918
  // packages/shared/src/index.ts
12909
12919
  function attachmentExtension(name) {
12910
12920
  const m = /\.([a-zA-Z0-9]+)$/.exec(name.trim());
@@ -13267,6 +13277,7 @@ var init_src = __esm({
13267
13277
  init_drainable_worker();
13268
13278
  init_interactions();
13269
13279
  init_receipt_bus();
13280
+ init_relay_protocol();
13270
13281
  init_thread_slug();
13271
13282
  ATTACHMENT_IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "gif", "webp"];
13272
13283
  ATTACHMENT_DOC_EXTENSIONS = [
@@ -19534,13 +19545,15 @@ function pickPresent(partial) {
19534
19545
  return out;
19535
19546
  }
19536
19547
  function writeMachineSettings(next, home) {
19537
- const path = machineSettingsPath(home);
19548
+ writeMachineFile(machineSettingsPath(home), next);
19549
+ }
19550
+ function writeMachineFile(path, value) {
19538
19551
  mkdirSync7(dirname6(path), { recursive: true });
19539
19552
  const temp = `${path}.${process.pid}.tmp`;
19540
19553
  let fd;
19541
19554
  try {
19542
19555
  fd = openSync6(temp, "w", 384);
19543
- writeFileSync6(fd, `${JSON.stringify(next, null, 2)}
19556
+ writeFileSync6(fd, `${JSON.stringify(value, null, 2)}
19544
19557
  `, "utf8");
19545
19558
  fsyncSync5(fd);
19546
19559
  closeSync5(fd);
@@ -19603,9 +19616,90 @@ var init_settings = __esm({
19603
19616
  }
19604
19617
  });
19605
19618
 
19619
+ // packages/server/src/dispatch-preferences.ts
19620
+ import { readFileSync as readFileSync7 } from "node:fs";
19621
+ import { join as join10 } from "node:path";
19622
+ function machineDispatchPreferencesPath(home) {
19623
+ return join10(frizzPaths({ home }).data, "dispatch-preferences.json");
19624
+ }
19625
+ function readMachineDispatchPreferences(home) {
19626
+ let raw2;
19627
+ try {
19628
+ raw2 = JSON.parse(readFileSync7(machineDispatchPreferencesPath(home), "utf8"));
19629
+ } catch {
19630
+ return void 0;
19631
+ }
19632
+ const parsed = DispatchPreferences.safeParse(raw2);
19633
+ return parsed.success ? parsed.data : void 0;
19634
+ }
19635
+ function permissionFor(backend, mode) {
19636
+ if (backend === "codex") {
19637
+ if (mode === "plan" || mode === "bypassPermissions") return mode;
19638
+ return "default";
19639
+ }
19640
+ return mode === "plan" ? "auto" : mode;
19641
+ }
19642
+ function defaultDispatchPreferences(settings, codexModels = []) {
19643
+ const backend = settings.backend ?? (codexModels.some((model) => model.slug === settings.model) ? "codex" : "claude");
19644
+ const selected = {
19645
+ ...settings.model ? { model: settings.model } : {},
19646
+ ...settings.effort ? { effort: settings.effort } : {},
19647
+ permissionMode: permissionFor(backend, settings.permissionMode)
19648
+ };
19649
+ return {
19650
+ backend,
19651
+ claude: backend === "claude" ? selected : { permissionMode: "auto" },
19652
+ codex: backend === "codex" ? selected : { permissionMode: "default" }
19653
+ };
19654
+ }
19655
+ function getDispatchPreferences(storage, settings, home, codexModels = []) {
19656
+ const machine = readMachineDispatchPreferences(home);
19657
+ if (machine) return machine;
19658
+ const parsed = DispatchPreferences.safeParse(storage.getSetting(KEY));
19659
+ return parsed.success ? parsed.data : defaultDispatchPreferences(settings, codexModels);
19660
+ }
19661
+ function setDispatchPreference(storage, settings, home, update, codexModels = []) {
19662
+ const current = getDispatchPreferences(storage, settings, home, codexModels);
19663
+ let next;
19664
+ if (update.field === "backend") {
19665
+ next = { ...current, backend: update.value };
19666
+ } else if (update.field === "profile") {
19667
+ next = {
19668
+ ...current,
19669
+ backend: update.backend,
19670
+ [update.backend]: {
19671
+ ...current[update.backend],
19672
+ model: update.model,
19673
+ effort: update.effort
19674
+ }
19675
+ };
19676
+ } else {
19677
+ const profile = current[update.backend];
19678
+ next = {
19679
+ ...current,
19680
+ ...update.field === "model" ? { backend: update.backend } : {},
19681
+ [update.backend]: { ...profile, [update.field]: update.value }
19682
+ };
19683
+ }
19684
+ const validated = DispatchPreferences.parse(next);
19685
+ writeMachineFile(machineDispatchPreferencesPath(home), validated);
19686
+ storage.setSetting(KEY, validated);
19687
+ return validated;
19688
+ }
19689
+ var KEY;
19690
+ var init_dispatch_preferences = __esm({
19691
+ "packages/server/src/dispatch-preferences.ts"() {
19692
+ "use strict";
19693
+ init_src();
19694
+ init_frizz_paths();
19695
+ init_settings();
19696
+ KEY = "dispatch-preferences.v1";
19697
+ }
19698
+ });
19699
+
19606
19700
  // packages/server/src/discover.ts
19607
19701
  import { readdirSync as readdirSync3, statSync as statSync4, openSync as openSync7, readSync, closeSync as closeSync6 } from "node:fs";
19608
- import { dirname as dirname7, join as join10 } from "node:path";
19702
+ import { dirname as dirname7, join as join11 } from "node:path";
19609
19703
  function sentinelFor(sessionId) {
19610
19704
  return `threads/${sessionId}/`;
19611
19705
  }
@@ -19642,7 +19736,7 @@ function discoverTranscriptId(logDir, sessionId, opts = {}) {
19642
19736
  if (name.startsWith(".") || !name.endsWith(".jsonl")) continue;
19643
19737
  const id = name.slice(0, -".jsonl".length);
19644
19738
  if (!id || id === sessionId || exclude?.has(id)) continue;
19645
- const path = join10(logDir, name);
19739
+ const path = join11(logDir, name);
19646
19740
  let mtime;
19647
19741
  try {
19648
19742
  mtime = statSync4(path).mtimeMs;
@@ -19670,7 +19764,7 @@ function discoverTranscriptDir(logDir, sessionId, memo3 = strandedLogDirs) {
19670
19764
  const name = `${sessionId}.jsonl`;
19671
19765
  const better = (best2, dir) => {
19672
19766
  if (dir === logDir) return best2;
19673
- const at = mtimeOfNonEmpty(join10(dir, name));
19767
+ const at = mtimeOfNonEmpty(join11(dir, name));
19674
19768
  if (at === void 0) return best2;
19675
19769
  return !best2 || at > best2.mtimeMs ? { dir, mtimeMs: at } : best2;
19676
19770
  };
@@ -19683,7 +19777,7 @@ function discoverTranscriptDir(logDir, sessionId, memo3 = strandedLogDirs) {
19683
19777
  } catch {
19684
19778
  return void 0;
19685
19779
  }
19686
- for (const entry of entries) best = better(best, join10(dirname7(logDir), entry));
19780
+ for (const entry of entries) best = better(best, join11(dirname7(logDir), entry));
19687
19781
  if (!best) return void 0;
19688
19782
  memo3.add(best.dir);
19689
19783
  return best.dir;
@@ -19702,10 +19796,10 @@ var init_discover = __esm({
19702
19796
 
19703
19797
  // packages/server/src/session-files.ts
19704
19798
  import { lstatSync, rmSync as rmSync7 } from "node:fs";
19705
- import { join as join11 } from "node:path";
19799
+ import { join as join12 } from "node:path";
19706
19800
  function systemPromptPath(sessionId) {
19707
19801
  if (!SESSION_ID_RE.test(sessionId)) throw new Error("invalid session id");
19708
- return join11(SYSTEM_PROMPT_DIR, `${sessionId}.md`);
19802
+ return join12(SYSTEM_PROMPT_DIR, `${sessionId}.md`);
19709
19803
  }
19710
19804
  function isDirectDirectory(path) {
19711
19805
  try {
@@ -19725,7 +19819,7 @@ function pathAbsent(path) {
19725
19819
  }
19726
19820
  function unlinkDirectChild(parent, filename) {
19727
19821
  if (!isDirectDirectory(parent)) return pathAbsent(parent);
19728
- const child = join11(parent, filename);
19822
+ const child = join12(parent, filename);
19729
19823
  try {
19730
19824
  rmSync7(child, { force: true });
19731
19825
  } catch {
@@ -19735,12 +19829,12 @@ function unlinkDirectChild(parent, filename) {
19735
19829
  }
19736
19830
  function cleanupAdoptionSessionFiles(projectDir, sessionId) {
19737
19831
  if (!SESSION_ID_RE.test(sessionId)) return false;
19738
- const frizzDir = join11(projectDir, ".frizz");
19832
+ const frizzDir = join12(projectDir, ".frizz");
19739
19833
  let clean = true;
19740
19834
  if (isDirectDirectory(frizzDir)) {
19741
- const threads = join11(frizzDir, "threads");
19835
+ const threads = join12(frizzDir, "threads");
19742
19836
  if (isDirectDirectory(threads)) {
19743
- const child = join11(threads, sessionId);
19837
+ const child = join12(threads, sessionId);
19744
19838
  try {
19745
19839
  rmSync7(child, { recursive: true, force: true });
19746
19840
  } catch {
@@ -19992,10 +20086,10 @@ var init_adoption_recovery = __esm({
19992
20086
  });
19993
20087
 
19994
20088
  // packages/server/src/backend/codex-models.ts
19995
- import { join as join12 } from "node:path";
19996
- import { readFileSync as readFileSync7 } from "node:fs";
20089
+ import { join as join13 } from "node:path";
20090
+ import { readFileSync as readFileSync8 } from "node:fs";
19997
20091
  function cachePath(codexHome) {
19998
- return join12(codexHome, "models_cache.json");
20092
+ return join13(codexHome, "models_cache.json");
19999
20093
  }
20000
20094
  function toCodexModel(raw2) {
20001
20095
  if (!raw2 || typeof raw2 !== "object") return void 0;
@@ -20031,7 +20125,7 @@ function readCodexModels(codexHome = defaultCodexHome()) {
20031
20125
  if (hit && now - hit.at < TTL_MS) return hit.models;
20032
20126
  let models;
20033
20127
  try {
20034
- models = parseCodexModelsCache(readFileSync7(path, "utf8"));
20128
+ models = parseCodexModelsCache(readFileSync8(path, "utf8"));
20035
20129
  } catch {
20036
20130
  models = CODEX_MODELS_FALLBACK;
20037
20131
  }
@@ -20573,10 +20667,10 @@ var init_claude_agent_sdk_protocol = __esm({
20573
20667
  });
20574
20668
 
20575
20669
  // packages/server/src/backend/claude-broker-diagnostics.ts
20576
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync8, readFileSync as readFileSync8, renameSync as renameSync6, statSync as statSync5 } from "node:fs";
20577
- import { join as join13 } from "node:path";
20670
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync8, readFileSync as readFileSync9, renameSync as renameSync6, statSync as statSync5 } from "node:fs";
20671
+ import { join as join14 } from "node:path";
20578
20672
  function claudeBrokerDiagnosticLogPath(stateDir, sessionId) {
20579
- return join13(stateDir, "claude-broker", `${sessionId}.diagnostics.log`);
20673
+ return join14(stateDir, "claude-broker", `${sessionId}.diagnostics.log`);
20580
20674
  }
20581
20675
  function readClaudeBrokerExit(stateDir, sessionId, generation) {
20582
20676
  if (!generation) return null;
@@ -20584,7 +20678,7 @@ function readClaudeBrokerExit(stateDir, sessionId, generation) {
20584
20678
  for (const path of [`${claudeBrokerDiagnosticLogPath(stateDir, sessionId)}.1`, claudeBrokerDiagnosticLogPath(stateDir, sessionId)]) {
20585
20679
  let text;
20586
20680
  try {
20587
- text = readFileSync8(path, "utf8");
20681
+ text = readFileSync9(path, "utf8");
20588
20682
  } catch {
20589
20683
  continue;
20590
20684
  }
@@ -20648,10 +20742,10 @@ var init_detached_daemons = __esm({
20648
20742
  });
20649
20743
 
20650
20744
  // packages/server/src/backend/ipc-path.ts
20651
- import { join as join14 } from "node:path";
20745
+ import { join as join15 } from "node:path";
20652
20746
  function frizzIpcPath(name) {
20653
20747
  if (process.platform === "win32") return `\\\\.\\pipe\\${name}`;
20654
- return join14(process.env.TMPDIR ?? "/tmp", `${name}.sock`);
20748
+ return join15(process.env.TMPDIR ?? "/tmp", `${name}.sock`);
20655
20749
  }
20656
20750
  var init_ipc_path = __esm({
20657
20751
  "packages/server/src/backend/ipc-path.ts"() {
@@ -20662,18 +20756,18 @@ var init_ipc_path = __esm({
20662
20756
  // packages/server/src/backend/claude-broker-host.ts
20663
20757
  import { spawn } from "node:child_process";
20664
20758
  import { createHash as createHash5, randomUUID as randomUUID8 } from "node:crypto";
20665
- import { accessSync, constants as fsConstants, mkdirSync as mkdirSync9, readFileSync as readFileSync9, readdirSync as readdirSync4, unlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
20666
- import { delimiter, dirname as dirname8, isAbsolute as isAbsolute2, join as join15 } from "node:path";
20759
+ import { accessSync, constants as fsConstants, mkdirSync as mkdirSync9, readFileSync as readFileSync10, readdirSync as readdirSync4, unlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
20760
+ import { delimiter, dirname as dirname8, isAbsolute as isAbsolute2, join as join16 } from "node:path";
20667
20761
  function windowsShimTarget(shimPath) {
20668
20762
  let body;
20669
20763
  try {
20670
- body = readFileSync9(shimPath, "utf8");
20764
+ body = readFileSync10(shimPath, "utf8");
20671
20765
  } catch {
20672
20766
  return void 0;
20673
20767
  }
20674
20768
  const target = WINDOWS_SHIM_TARGET.exec(body)?.[1];
20675
20769
  if (!target) return void 0;
20676
- const full = join15(dirname8(shimPath), target);
20770
+ const full = join16(dirname8(shimPath), target);
20677
20771
  try {
20678
20772
  accessSync(full, fsConstants.F_OK);
20679
20773
  return full;
@@ -20694,17 +20788,17 @@ function resolveClaudeExecutableAbsolute(bin, env = process.env) {
20694
20788
  for (const dir of searchPath(env).split(delimiter)) {
20695
20789
  if (!dir) continue;
20696
20790
  if (windows) {
20697
- const exe = join15(dir, `${candidate}.exe`);
20791
+ const exe = join16(dir, `${candidate}.exe`);
20698
20792
  try {
20699
20793
  accessSync(exe, fsConstants.F_OK);
20700
20794
  return exe;
20701
20795
  } catch {
20702
20796
  }
20703
- const viaShim = windowsShimTarget(join15(dir, `${candidate}.cmd`));
20797
+ const viaShim = windowsShimTarget(join16(dir, `${candidate}.cmd`));
20704
20798
  if (viaShim) return viaShim;
20705
20799
  continue;
20706
20800
  }
20707
- const full = join15(dir, candidate);
20801
+ const full = join16(dir, candidate);
20708
20802
  try {
20709
20803
  accessSync(full, fsConstants.X_OK);
20710
20804
  return full;
@@ -20719,11 +20813,11 @@ function claudeBrokerSocketPath(stateDir, sessionId) {
20719
20813
  }
20720
20814
  function claudeBrokerRecordPath(stateDir, sessionId) {
20721
20815
  const key = createHash5("sha256").update(sessionId).digest("hex").slice(0, 16);
20722
- return join15(stateDir, "claude-broker", `${key}.json`);
20816
+ return join16(stateDir, "claude-broker", `${key}.json`);
20723
20817
  }
20724
20818
  function claudeBrokerRetirementPath(stateDir, sessionId) {
20725
20819
  const key = createHash5("sha256").update(sessionId).digest("hex").slice(0, 16);
20726
- return join15(stateDir, "claude-broker", `${key}.retired`);
20820
+ return join16(stateDir, "claude-broker", `${key}.retired`);
20727
20821
  }
20728
20822
  function markBrokerRetired(stateDir, sessionId, reason, generation) {
20729
20823
  const mark = { at: (/* @__PURE__ */ new Date()).toISOString(), generation, reason };
@@ -20738,7 +20832,7 @@ function takeBrokerRetirement(stateDir, sessionId) {
20738
20832
  const path = claudeBrokerRetirementPath(stateDir, sessionId);
20739
20833
  let mark = null;
20740
20834
  try {
20741
- const parsed = JSON.parse(readFileSync9(path, "utf8"));
20835
+ const parsed = JSON.parse(readFileSync10(path, "utf8"));
20742
20836
  if (typeof parsed?.at === "string" && typeof parsed.generation === "string" && typeof parsed.reason === "string") {
20743
20837
  mark = { at: parsed.at, generation: parsed.generation, reason: parsed.reason };
20744
20838
  }
@@ -20760,7 +20854,7 @@ function pidAlive(pid) {
20760
20854
  }
20761
20855
  function readBrokerRecord(recordPath2) {
20762
20856
  try {
20763
- return JSON.parse(readFileSync9(recordPath2, "utf8"));
20857
+ return JSON.parse(readFileSync10(recordPath2, "utf8"));
20764
20858
  } catch {
20765
20859
  return null;
20766
20860
  }
@@ -20790,7 +20884,7 @@ function liveBrokerRecord(recordPath2) {
20790
20884
  return null;
20791
20885
  }
20792
20886
  function liveBrokerRecords(stateDir) {
20793
- const dir = join15(stateDir, "claude-broker");
20887
+ const dir = join16(stateDir, "claude-broker");
20794
20888
  let names;
20795
20889
  try {
20796
20890
  names = readdirSync4(dir);
@@ -20800,7 +20894,7 @@ function liveBrokerRecords(stateDir) {
20800
20894
  const out = [];
20801
20895
  for (const name of names) {
20802
20896
  if (!name.endsWith(".json")) continue;
20803
- const record = liveBrokerRecord(join15(dir, name));
20897
+ const record = liveBrokerRecord(join16(dir, name));
20804
20898
  if (record) out.push(record);
20805
20899
  }
20806
20900
  return out;
@@ -21608,15 +21702,15 @@ var init_completion_relay = __esm({
21608
21702
 
21609
21703
  // packages/server/src/tail-cache.ts
21610
21704
  import { createHash as createHash6 } from "node:crypto";
21611
- import { closeSync as closeSync8, openSync as openSync9, readFileSync as readFileSync10, readSync as readSync3, statSync as statSync7 } from "node:fs";
21612
- import { join as join16 } from "node:path";
21705
+ import { closeSync as closeSync8, openSync as openSync9, readFileSync as readFileSync11, readSync as readSync3, statSync as statSync7 } from "node:fs";
21706
+ import { join as join17 } from "node:path";
21613
21707
  function foldSchemaDigest(dir = import.meta.dirname) {
21614
21708
  if (foldSchemaMemo) return foldSchemaMemo;
21615
21709
  const hash = createHash6("sha256").update("frizz-tail-state-v1\0");
21616
21710
  let read = 0;
21617
21711
  for (const name of FOLD_SOURCES) {
21618
21712
  try {
21619
- hash.update(name).update("\0").update(readFileSync10(join16(dir, name)));
21713
+ hash.update(name).update("\0").update(readFileSync11(join17(dir, name)));
21620
21714
  read++;
21621
21715
  } catch {
21622
21716
  hash.update(name).update("\0missing\0");
@@ -21812,9 +21906,9 @@ var init_tail_cache = __esm({
21812
21906
  });
21813
21907
 
21814
21908
  // packages/server/src/tailer.ts
21815
- import { statSync as statSync8, openSync as openSync10, readSync as readSync4, closeSync as closeSync9, readdirSync as readdirSync5, realpathSync as realpathSync5, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync11, existsSync as existsSync5 } from "node:fs";
21909
+ import { statSync as statSync8, openSync as openSync10, readSync as readSync4, closeSync as closeSync9, readdirSync as readdirSync5, realpathSync as realpathSync5, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync12, existsSync as existsSync5 } from "node:fs";
21816
21910
  import { execFileSync as execFileSync4 } from "node:child_process";
21817
- import { basename as basename4, join as join17 } from "node:path";
21911
+ import { basename as basename4, join as join18 } from "node:path";
21818
21912
  import { homedir as homedir7 } from "node:os";
21819
21913
  function probeShellAlive(outputFile) {
21820
21914
  if (!existsSync5(outputFile)) return void 0;
@@ -22076,7 +22170,7 @@ function launchTaskId(text) {
22076
22170
  function readDescendantSidecars(sessionDir, mtimeMs) {
22077
22171
  let names;
22078
22172
  try {
22079
- names = readdirSync5(join17(sessionDir, "subagents"));
22173
+ names = readdirSync5(join18(sessionDir, "subagents"));
22080
22174
  } catch {
22081
22175
  return [];
22082
22176
  }
@@ -22087,7 +22181,7 @@ function readDescendantSidecars(sessionDir, mtimeMs) {
22087
22181
  if (!agentId) continue;
22088
22182
  let parsed;
22089
22183
  try {
22090
- parsed = JSON.parse(readFileSync11(join17(sessionDir, "subagents", name), "utf8"));
22184
+ parsed = JSON.parse(readFileSync12(join18(sessionDir, "subagents", name), "utf8"));
22091
22185
  } catch {
22092
22186
  continue;
22093
22187
  }
@@ -22101,7 +22195,7 @@ function readDescendantSidecars(sessionDir, mtimeMs) {
22101
22195
  agentType: text(meta.agentType),
22102
22196
  parentAgentId: text(meta.parentAgentId),
22103
22197
  spawnDepth: typeof meta.spawnDepth === "number" && Number.isFinite(meta.spawnDepth) ? meta.spawnDepth : void 0,
22104
- spawnedAtMs: mtimeMs(join17(sessionDir, "subagents", name))
22198
+ spawnedAtMs: mtimeMs(join18(sessionDir, "subagents", name))
22105
22199
  });
22106
22200
  }
22107
22201
  return out;
@@ -22581,13 +22675,13 @@ function defaultMtimeMs(path) {
22581
22675
  }
22582
22676
  }
22583
22677
  function defaultLogDir(project) {
22584
- return join17(homedir7(), ".claude", "projects", project.cwdSlug);
22678
+ return join18(homedir7(), ".claude", "projects", project.cwdSlug);
22585
22679
  }
22586
22680
  function defaultReadPermMarker(project) {
22587
22681
  if (!project.stateDir) return () => void 0;
22588
22682
  return (slug) => {
22589
22683
  try {
22590
- const parsed = JSON.parse(readFileSync11(permMarkerPath(project, slug), "utf8"));
22684
+ const parsed = JSON.parse(readFileSync12(permMarkerPath(project, slug), "utf8"));
22591
22685
  return isPermMarker(parsed) ? parsed : void 0;
22592
22686
  } catch {
22593
22687
  return void 0;
@@ -22713,7 +22807,7 @@ function createTailer(deps) {
22713
22807
  return paneDead(row.slug);
22714
22808
  }
22715
22809
  const defaultBackend = {
22716
- transcriptPath: (sessionId) => join17(logDir, `${sessionId}.jsonl`),
22810
+ transcriptPath: (sessionId) => join18(logDir, `${sessionId}.jsonl`),
22717
22811
  foldLine: (state, line) => {
22718
22812
  const rec = parseLine(line);
22719
22813
  if (rec) applyRecord(state, rec);
@@ -22838,7 +22932,7 @@ ${ask}`;
22838
22932
  return state.path.replace(/\.jsonl$/, "");
22839
22933
  }
22840
22934
  function descendantSidecars(state) {
22841
- const at = mtimeMs(join17(sessionDirOf(state), "subagents"));
22935
+ const at = mtimeMs(join18(sessionDirOf(state), "subagents"));
22842
22936
  const cached2 = descendantIndex.get(state.slug);
22843
22937
  if (cached2 && cached2.at === at) return cached2.all;
22844
22938
  const all = readDescendantSidecars(sessionDirOf(state), mtimeMs);
@@ -22852,7 +22946,7 @@ ${ask}`;
22852
22946
  return descendantIndex.get(state.slug)?.byToolUse.get(id);
22853
22947
  }
22854
22948
  function descendantTranscript(state, meta) {
22855
- return join17(sessionDirOf(state), "subagents", `agent-${meta.agentId}.jsonl`);
22949
+ return join18(sessionDirOf(state), "subagents", `agent-${meta.agentId}.jsonl`);
22856
22950
  }
22857
22951
  function subAgentDescendantTasks(slug, id) {
22858
22952
  const state = states.get(slug);
@@ -23166,7 +23260,7 @@ ${ask}`;
23166
23260
  if (name.startsWith(".") || !name.endsWith(".jsonl")) continue;
23167
23261
  const id = name.slice(0, -".jsonl".length);
23168
23262
  if (!id || registered.has(id)) continue;
23169
- const path = join17(logDir, name);
23263
+ const path = join18(logDir, name);
23170
23264
  let mtime;
23171
23265
  try {
23172
23266
  mtime = statSync8(path).mtimeMs;
@@ -23438,7 +23532,7 @@ ${ask}`;
23438
23532
  );
23439
23533
  try {
23440
23534
  mkdirSync10(stallLogDir, { recursive: true });
23441
- writeFileSync8(join17(stallLogDir, `${row.slug}.stall.log`), `session_id: ${row.session_id}
23535
+ writeFileSync8(join18(stallLogDir, `${row.slug}.stall.log`), `session_id: ${row.session_id}
23442
23536
  captured_at: ${new Date(now()).toISOString()}
23443
23537
 
23444
23538
  ${detail}
@@ -23466,7 +23560,7 @@ ${detail}
23466
23560
  state.nextDiscoverMs = nowMs + DISCOVER_RETRY_MS;
23467
23561
  const strandedDir = discoverTranscriptDir(logDir, row.session_id);
23468
23562
  if (strandedDir) {
23469
- state.path = join17(strandedDir, `${row.session_id}.jsonl`);
23563
+ state.path = join18(strandedDir, `${row.session_id}.jsonl`);
23470
23564
  state.offset = 0;
23471
23565
  state.partial = "";
23472
23566
  state.primed = false;
@@ -23489,7 +23583,7 @@ ${detail}
23489
23583
  committed = false;
23490
23584
  }
23491
23585
  if (!committed) return false;
23492
- state.path = join17(logDir, `${found}.jsonl`);
23586
+ state.path = join18(logDir, `${found}.jsonl`);
23493
23587
  state.offset = 0;
23494
23588
  state.partial = "";
23495
23589
  state.primed = false;
@@ -23535,7 +23629,7 @@ ${detail}
23535
23629
  let state = states.get(row.slug);
23536
23630
  const runtimeGeneration = row.runtime_generation ?? 0;
23537
23631
  if (!state || state.sessionId !== row.session_id || state.nativeSessionId !== nativeId || state.runtimeGeneration !== runtimeGeneration) {
23538
- const path = backend.transcriptPath(nativeId) ?? join17(logDir, `${nativeId}.jsonl`);
23632
+ const path = backend.transcriptPath(nativeId) ?? join18(logDir, `${nativeId}.jsonl`);
23539
23633
  state = newTailState(row.slug, row.session_id, path, false, nativeId, runtimeGeneration);
23540
23634
  state.dismissedOps = deps.storage.retiredOps(row.slug, row.session_id);
23541
23635
  hydrateFromCache(state, row, nativeId);
@@ -23984,14 +24078,14 @@ var init_tailer = __esm({
23984
24078
  });
23985
24079
 
23986
24080
  // packages/server/src/backend/codex.ts
23987
- import { join as join18 } from "node:path";
24081
+ import { join as join19 } from "node:path";
23988
24082
  import { homedir as homedir8 } from "node:os";
23989
- import { readdirSync as readdirSync6, statSync as statSync9, readFileSync as readFileSync12, openSync as openSync11, readSync as readSync5, closeSync as closeSync10 } from "node:fs";
24083
+ import { readdirSync as readdirSync6, statSync as statSync9, readFileSync as readFileSync13, openSync as openSync11, readSync as readSync5, closeSync as closeSync10 } from "node:fs";
23990
24084
  function defaultCodexHome() {
23991
- return process.env.CODEX_HOME && process.env.CODEX_HOME.trim() ? process.env.CODEX_HOME : join18(homedir8(), ".codex");
24085
+ return process.env.CODEX_HOME && process.env.CODEX_HOME.trim() ? process.env.CODEX_HOME : join19(homedir8(), ".codex");
23992
24086
  }
23993
24087
  function sessionsDir(codexHome) {
23994
- return join18(codexHome, "sessions");
24088
+ return join19(codexHome, "sessions");
23995
24089
  }
23996
24090
  function codexSandbox(mode) {
23997
24091
  switch (mode) {
@@ -24372,17 +24466,17 @@ function collectRollouts(dir, out, budget) {
24372
24466
  const files = entries.filter((e) => e.isFile() && e.name.startsWith("rollout-") && e.name.endsWith(".jsonl")).sort(descByName);
24373
24467
  for (const d of dirs) {
24374
24468
  if (budget.n <= 0) return;
24375
- collectRollouts(join18(dir, d.name), out, budget);
24469
+ collectRollouts(join19(dir, d.name), out, budget);
24376
24470
  }
24377
24471
  for (const f of files) {
24378
24472
  if (budget.n <= 0) return;
24379
24473
  let mtimeMs;
24380
24474
  try {
24381
- mtimeMs = statSync9(join18(dir, f.name)).mtimeMs;
24475
+ mtimeMs = statSync9(join19(dir, f.name)).mtimeMs;
24382
24476
  } catch {
24383
24477
  continue;
24384
24478
  }
24385
- out.push({ path: join18(dir, f.name), mtimeMs });
24479
+ out.push({ path: join19(dir, f.name), mtimeMs });
24386
24480
  budget.n--;
24387
24481
  }
24388
24482
  }
@@ -24426,9 +24520,9 @@ function readCodexThreadNames(codexHome = defaultCodexHome()) {
24426
24520
  const out = /* @__PURE__ */ new Map();
24427
24521
  let raw2;
24428
24522
  try {
24429
- const path = join18(codexHome, "session_index.jsonl");
24523
+ const path = join19(codexHome, "session_index.jsonl");
24430
24524
  if (statSync9(path).size > SESSION_INDEX_MAX_BYTES) return out;
24431
- raw2 = readFileSync12(path, "utf8");
24525
+ raw2 = readFileSync13(path, "utf8");
24432
24526
  } catch {
24433
24527
  return out;
24434
24528
  }
@@ -28464,16 +28558,16 @@ var init_wrapper = __esm({
28464
28558
 
28465
28559
  // packages/server/src/worker-plugin-dir.ts
28466
28560
  import { existsSync as existsSync6 } from "node:fs";
28467
- import { dirname as dirname9, join as join19 } from "node:path";
28561
+ import { dirname as dirname9, join as join20 } from "node:path";
28468
28562
  import { fileURLToPath as fileURLToPath2 } from "node:url";
28469
28563
  function resolveWorkerPluginDir(moduleUrl = import.meta.url, env = process.env) {
28470
28564
  const override = env.FRIZZ_WORKER_PLUGIN_DIR;
28471
- if (override && existsSync6(join19(override, ".claude-plugin", "plugin.json")))
28565
+ if (override && existsSync6(join20(override, ".claude-plugin", "plugin.json")))
28472
28566
  return override;
28473
28567
  let current = dirname9(fileURLToPath2(moduleUrl));
28474
28568
  for (; ; ) {
28475
- const candidate = join19(current, "cc-worker");
28476
- if (existsSync6(join19(candidate, ".claude-plugin", "plugin.json"))) return candidate;
28569
+ const candidate = join20(current, "cc-worker");
28570
+ if (existsSync6(join20(candidate, ".claude-plugin", "plugin.json"))) return candidate;
28477
28571
  const parent = dirname9(current);
28478
28572
  if (parent === current) return void 0;
28479
28573
  current = parent;
@@ -28487,7 +28581,7 @@ var init_worker_plugin_dir = __esm({
28487
28581
 
28488
28582
  // packages/server/src/backend/types.ts
28489
28583
  import { existsSync as existsSync7 } from "node:fs";
28490
- import { join as join20 } from "node:path";
28584
+ import { join as join21 } from "node:path";
28491
28585
  function frizzMcpEnv(mcp) {
28492
28586
  return {
28493
28587
  FRIZZ_STATE_DIR: mcp.stateDir,
@@ -28511,7 +28605,7 @@ function chromeDevtoolsMcpMount() {
28511
28605
  function resolveBrowserMcpScript(moduleUrl = import.meta.url, env = process.env) {
28512
28606
  const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
28513
28607
  if (!pluginDir) return void 0;
28514
- const scriptPath = join20(pluginDir, "bin", CHROME_DEVTOOLS_MCP.script);
28608
+ const scriptPath = join21(pluginDir, "bin", CHROME_DEVTOOLS_MCP.script);
28515
28609
  return existsSync7(scriptPath) ? scriptPath : void 0;
28516
28610
  }
28517
28611
  function workerCap(name, lifted, env) {
@@ -28609,15 +28703,15 @@ import { spawn as spawn2 } from "node:child_process";
28609
28703
  import { connect } from "node:net";
28610
28704
  import { Agent as HttpAgent } from "node:http";
28611
28705
  import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
28612
- import { existsSync as existsSync8, mkdirSync as mkdirSync11, readFileSync as readFileSync13, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
28613
- import { join as join21 } from "node:path";
28706
+ import { existsSync as existsSync8, mkdirSync as mkdirSync11, readFileSync as readFileSync14, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
28707
+ import { join as join22 } from "node:path";
28614
28708
  import { PassThrough, Writable } from "node:stream";
28615
28709
  import { StringDecoder } from "node:string_decoder";
28616
28710
  function nativeDir(stateDir) {
28617
- return join21(stateDir, "codex-app-server-native");
28711
+ return join22(stateDir, "codex-app-server-native");
28618
28712
  }
28619
28713
  function nativeRecordPath(stateDir, projectId) {
28620
- return join21(nativeDir(stateDir), `${projectId}.json`);
28714
+ return join22(nativeDir(stateDir), `${projectId}.json`);
28621
28715
  }
28622
28716
  function nativeListenSocketPath(stateDir, projectId) {
28623
28717
  const key = createHash7("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
@@ -28633,7 +28727,7 @@ function pidAlive2(pid) {
28633
28727
  }
28634
28728
  function readNativeRecord(stateDir, projectId) {
28635
28729
  try {
28636
- const value = JSON.parse(readFileSync13(nativeRecordPath(stateDir, projectId), "utf8"));
28730
+ const value = JSON.parse(readFileSync14(nativeRecordPath(stateDir, projectId), "utf8"));
28637
28731
  if (typeof value.listenerPid !== "number" || typeof value.socketPath !== "string" || typeof value.generation !== "string") return null;
28638
28732
  return {
28639
28733
  projectId,
@@ -28881,15 +28975,15 @@ var init_codex_app_server_native = __esm({
28881
28975
  import { spawn as spawn3, spawnSync } from "node:child_process";
28882
28976
  import { createConnection } from "node:net";
28883
28977
  import { createHash as createHash8, randomUUID as randomUUID10 } from "node:crypto";
28884
- import { existsSync as existsSync9, mkdirSync as mkdirSync12, readFileSync as readFileSync14, unlinkSync as unlinkSync3 } from "node:fs";
28885
- import { join as join22 } from "node:path";
28978
+ import { existsSync as existsSync9, mkdirSync as mkdirSync12, readFileSync as readFileSync15, unlinkSync as unlinkSync3 } from "node:fs";
28979
+ import { join as join23 } from "node:path";
28886
28980
  import { PassThrough as PassThrough2, Writable as Writable2 } from "node:stream";
28887
28981
  import { StringDecoder as StringDecoder2 } from "node:string_decoder";
28888
28982
  function daemonDir(stateDir) {
28889
- return join22(stateDir, "codex-app-server");
28983
+ return join23(stateDir, "codex-app-server");
28890
28984
  }
28891
28985
  function recordPath(stateDir, projectId) {
28892
- return join22(daemonDir(stateDir), `${projectId}.json`);
28986
+ return join23(daemonDir(stateDir), `${projectId}.json`);
28893
28987
  }
28894
28988
  function codexAppServerSocketPath(stateDir, projectId) {
28895
28989
  const key = createHash8("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
@@ -28905,7 +28999,7 @@ function pidAlive3(pid) {
28905
28999
  }
28906
29000
  function readDaemonRecord(stateDir, projectId) {
28907
29001
  try {
28908
- const value = JSON.parse(readFileSync14(recordPath(stateDir, projectId), "utf8"));
29002
+ const value = JSON.parse(readFileSync15(recordPath(stateDir, projectId), "utf8"));
28909
29003
  if (typeof value.daemonPid !== "number" || typeof value.socketPath !== "string" || typeof value.generation !== "string") return null;
28910
29004
  return {
28911
29005
  projectId,
@@ -28921,7 +29015,7 @@ function readDaemonRecord(stateDir, projectId) {
28921
29015
  }
28922
29016
  function readDaemonExitBreadcrumb(stateDir, projectId) {
28923
29017
  try {
28924
- const value = JSON.parse(readFileSync14(`${recordPath(stateDir, projectId)}.exit`, "utf8"));
29018
+ const value = JSON.parse(readFileSync15(`${recordPath(stateDir, projectId)}.exit`, "utf8"));
28925
29019
  if (typeof value.generation !== "string" || typeof value.reason !== "string") return null;
28926
29020
  return {
28927
29021
  generation: value.generation,
@@ -32117,11 +32211,11 @@ var init_codex_app_server = __esm({
32117
32211
  });
32118
32212
 
32119
32213
  // packages/server/src/backend/codex-quota.ts
32120
- import { join as join23 } from "node:path";
32214
+ import { join as join24 } from "node:path";
32121
32215
  import { readdirSync as readdirSync7, statSync as statSync10, openSync as openSync12, readSync as readSync6, fstatSync, closeSync as closeSync11 } from "node:fs";
32122
32216
  import { spawn as spawn4 } from "node:child_process";
32123
32217
  function sessionsDir2(codexHome) {
32124
- return join23(codexHome, "sessions");
32218
+ return join24(codexHome, "sessions");
32125
32219
  }
32126
32220
  function newestRollouts(dir, out, budget) {
32127
32221
  if (budget.n <= 0) return;
@@ -32135,11 +32229,11 @@ function newestRollouts(dir, out, budget) {
32135
32229
  const files = entries.filter((e) => e.isFile() && e.name.startsWith("rollout-") && e.name.endsWith(".jsonl")).map((e) => e.name).sort(descByName2);
32136
32230
  for (const d of dirs) {
32137
32231
  if (budget.n <= 0) return;
32138
- newestRollouts(join23(dir, d), out, budget);
32232
+ newestRollouts(join24(dir, d), out, budget);
32139
32233
  }
32140
32234
  for (const f of files) {
32141
32235
  if (budget.n <= 0) return;
32142
- out.push(join23(dir, f));
32236
+ out.push(join24(dir, f));
32143
32237
  budget.n--;
32144
32238
  }
32145
32239
  }
@@ -32339,7 +32433,7 @@ var init_codex_quota = __esm({
32339
32433
  });
32340
32434
 
32341
32435
  // packages/server/src/backend/claude-quota.ts
32342
- import { join as join24 } from "node:path";
32436
+ import { join as join25 } from "node:path";
32343
32437
  import { homedir as homedir9, platform } from "node:os";
32344
32438
  import { createHash as createHash10 } from "node:crypto";
32345
32439
  import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
@@ -32347,7 +32441,7 @@ import { execFile as execFile2 } from "node:child_process";
32347
32441
  import { promisify as promisify2 } from "node:util";
32348
32442
  function claudeConfigDir() {
32349
32443
  const override = process.env.CLAUDE_CONFIG_DIR;
32350
- return override && override.trim() ? override : join24(homedir9(), ".claude");
32444
+ return override && override.trim() ? override : join25(homedir9(), ".claude");
32351
32445
  }
32352
32446
  function tokenFromCredentialsJson(raw2) {
32353
32447
  let doc;
@@ -32376,7 +32470,7 @@ async function readKeychainToken() {
32376
32470
  }
32377
32471
  async function readAccessToken(configDir) {
32378
32472
  try {
32379
- const fromFile = tokenFromCredentialsJson(await readFile(join24(configDir, ".credentials.json"), "utf8"));
32473
+ const fromFile = tokenFromCredentialsJson(await readFile(join25(configDir, ".credentials.json"), "utf8"));
32380
32474
  if (fromFile) return fromFile;
32381
32475
  } catch {
32382
32476
  }
@@ -32445,8 +32539,8 @@ function parseClaudeUsage(body, planType) {
32445
32539
  function cachePaths(cacheDir, configDir) {
32446
32540
  const profile = createHash10("sha256").update(configDir).digest("hex").slice(0, 12);
32447
32541
  return {
32448
- data: join24(cacheDir, `claude-${profile}.json`),
32449
- lock: join24(cacheDir, `claude-${profile}.lock`)
32542
+ data: join25(cacheDir, `claude-${profile}.json`),
32543
+ lock: join25(cacheDir, `claude-${profile}.lock`)
32450
32544
  };
32451
32545
  }
32452
32546
  async function readShared(path) {
@@ -32642,7 +32736,7 @@ function refreshSharedInBackground(paths, claudeBin, deps, now) {
32642
32736
  async function refreshClaudeQuotaInBackground(claudeBin = "claude", deps = {}) {
32643
32737
  const now = (deps.now ?? Date.now)();
32644
32738
  const configDir = claudeConfigDir();
32645
- const cacheDir = deps.cacheDir ?? join24(frizzRoots().cache, "quota-cache");
32739
+ const cacheDir = deps.cacheDir ?? join25(frizzRoots().cache, "quota-cache");
32646
32740
  try {
32647
32741
  await mkdir(cacheDir, { recursive: true, mode: 448 });
32648
32742
  } catch {
@@ -32653,7 +32747,7 @@ async function refreshClaudeQuotaInBackground(claudeBin = "claude", deps = {}) {
32653
32747
  async function readClaudeQuota(claudeBin = "claude", deps = {}, options = {}) {
32654
32748
  const now = (deps.now ?? Date.now)();
32655
32749
  const configDir = claudeConfigDir();
32656
- const cacheDir = deps.cacheDir ?? join24(frizzRoots().cache, "quota-cache");
32750
+ const cacheDir = deps.cacheDir ?? join25(frizzRoots().cache, "quota-cache");
32657
32751
  const paths = cachePaths(cacheDir, configDir);
32658
32752
  try {
32659
32753
  await mkdir(cacheDir, { recursive: true, mode: 448 });
@@ -32813,7 +32907,7 @@ var init_quota = __esm({
32813
32907
  // packages/server/src/frizz.ts
32814
32908
  import { execFile as execFile3 } from "node:child_process";
32815
32909
  import { lstatSync as lstatSync2, realpathSync as realpathSync6 } from "node:fs";
32816
- import { basename as basename5, dirname as dirname10, join as join25, resolve as resolve4 } from "node:path";
32910
+ import { basename as basename5, dirname as dirname10, join as join26, resolve as resolve4 } from "node:path";
32817
32911
  import { promisify as promisify3 } from "node:util";
32818
32912
  function frizzScriptsDir() {
32819
32913
  if (process.env.FRIZZ_SCRIPTS_DIR) return process.env.FRIZZ_SCRIPTS_DIR;
@@ -32822,7 +32916,7 @@ function frizzScriptsDir() {
32822
32916
  function directFrizzRoot(projectDir) {
32823
32917
  try {
32824
32918
  const projectRoot = realpathSync6(projectDir);
32825
- const path = join25(projectRoot, ".frizz");
32919
+ const path = join26(projectRoot, ".frizz");
32826
32920
  const stat2 = lstatSync2(path);
32827
32921
  if (!stat2.isDirectory() || stat2.isSymbolicLink()) return null;
32828
32922
  const real = realpathSync6(path);
@@ -32836,7 +32930,7 @@ function frizzDirExists(projectDir) {
32836
32930
  }
32837
32931
  async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
32838
32932
  if (!directFrizzRoot(projectDir)) throw new Error("unsafe or missing .frizz directory");
32839
- const { stdout } = await execFileP("node", [join25(scriptsDir, "index.mjs"), "--json"], {
32933
+ const { stdout } = await execFileP("node", [join26(scriptsDir, "index.mjs"), "--json"], {
32840
32934
  cwd: projectDir,
32841
32935
  env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir },
32842
32936
  maxBuffer: 32 * 1024 * 1024
@@ -32861,7 +32955,7 @@ async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
32861
32955
  };
32862
32956
  }
32863
32957
  async function runThreadUpdate(projectDir, slug, args, scriptsDir = frizzScriptsDir()) {
32864
- await execFileP("node", [join25(scriptsDir, "thread-update.mjs"), slug, ...args], {
32958
+ await execFileP("node", [join26(scriptsDir, "thread-update.mjs"), slug, ...args], {
32865
32959
  cwd: projectDir,
32866
32960
  env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir }
32867
32961
  });
@@ -34746,19 +34840,19 @@ var init_claude_agent_broker_bridge = __esm({
34746
34840
  });
34747
34841
 
34748
34842
  // packages/server/src/backend/auth-status.ts
34749
- import { join as join26 } from "node:path";
34843
+ import { join as join27 } from "node:path";
34750
34844
  import { homedir as homedir11, platform as platform2 } from "node:os";
34751
- import { readFileSync as readFileSync15, statSync as statSync11 } from "node:fs";
34845
+ import { readFileSync as readFileSync16, statSync as statSync11 } from "node:fs";
34752
34846
  import { execFile as execFile4 } from "node:child_process";
34753
34847
  import { promisify as promisify4 } from "node:util";
34754
34848
  function claudeConfigDir2() {
34755
34849
  const override = process.env.CLAUDE_CONFIG_DIR;
34756
- return override && override.trim() ? override : join26(homedir11(), ".claude");
34850
+ return override && override.trim() ? override : join27(homedir11(), ".claude");
34757
34851
  }
34758
34852
  function claudeFileState(configDir) {
34759
34853
  let raw2;
34760
34854
  try {
34761
- raw2 = readFileSync15(join26(configDir, ".credentials.json"), "utf8");
34855
+ raw2 = readFileSync16(join27(configDir, ".credentials.json"), "utf8");
34762
34856
  } catch (err) {
34763
34857
  return err.code === "ENOENT" ? "absent" : "error";
34764
34858
  }
@@ -34791,7 +34885,7 @@ function readCodexAuthState(codexHome = defaultCodexHome()) {
34791
34885
  if (process.env.OPENAI_API_KEY || process.env.CODEX_API_KEY || process.env.CODEX_ACCESS_TOKEN) return "authed";
34792
34886
  let raw2;
34793
34887
  try {
34794
- raw2 = readFileSync15(join26(codexHome, "auth.json"), "utf8");
34888
+ raw2 = readFileSync16(join27(codexHome, "auth.json"), "utf8");
34795
34889
  } catch (err) {
34796
34890
  return err.code === "ENOENT" ? "signed-out" : "unknown";
34797
34891
  }
@@ -34856,7 +34950,7 @@ function asEmail(value) {
34856
34950
  }
34857
34951
  function claudeAccountFile() {
34858
34952
  const override = process.env.CLAUDE_CONFIG_DIR;
34859
- return override && override.trim() ? join26(override, ".claude.json") : join26(homedir11(), ".claude.json");
34953
+ return override && override.trim() ? join27(override, ".claude.json") : join27(homedir11(), ".claude.json");
34860
34954
  }
34861
34955
  function readClaudeAccountEmail(path = claudeAccountFile()) {
34862
34956
  let stat2;
@@ -34869,7 +34963,7 @@ function readClaudeAccountEmail(path = claudeAccountFile()) {
34869
34963
  if (memo3 && memo3.path === path && memo3.mtimeMs === stat2.mtimeMs && memo3.size === stat2.size) return memo3.email;
34870
34964
  let email;
34871
34965
  try {
34872
- const doc = JSON.parse(readFileSync15(path, "utf8"));
34966
+ const doc = JSON.parse(readFileSync16(path, "utf8"));
34873
34967
  email = asEmail(doc?.oauthAccount?.emailAddress);
34874
34968
  } catch {
34875
34969
  email = void 0;
@@ -34880,7 +34974,7 @@ function readClaudeAccountEmail(path = claudeAccountFile()) {
34880
34974
  function readCodexAccountEmail(codexHome = defaultCodexHome()) {
34881
34975
  let doc;
34882
34976
  try {
34883
- doc = JSON.parse(readFileSync15(join26(codexHome, "auth.json"), "utf8"));
34977
+ doc = JSON.parse(readFileSync16(join27(codexHome, "auth.json"), "utf8"));
34884
34978
  } catch {
34885
34979
  return void 0;
34886
34980
  }
@@ -34948,8 +35042,8 @@ var init_auth_status = __esm({
34948
35042
  });
34949
35043
 
34950
35044
  // packages/server/src/dispatch.ts
34951
- import { closeSync as closeSync12, constants, existsSync as existsSync10, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as readFileSync16, realpathSync as realpathSync7, statSync as statSync12, writeFileSync as writeFileSync10, mkdirSync as mkdirSync13, rmSync as rmSync8 } from "node:fs";
34952
- import { basename as basename6, join as join27, dirname as dirname11 } from "node:path";
35045
+ import { closeSync as closeSync12, constants, existsSync as existsSync10, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as readFileSync17, realpathSync as realpathSync7, statSync as statSync12, writeFileSync as writeFileSync10, mkdirSync as mkdirSync13, rmSync as rmSync8 } from "node:fs";
35046
+ import { basename as basename6, join as join28, dirname as dirname11 } from "node:path";
34953
35047
  import { createHash as createHash11, randomUUID as randomUUID13 } from "node:crypto";
34954
35048
  function fallbackTitle(prompt) {
34955
35049
  const firstLine2 = prompt.trim().split("\n", 1)[0].trim();
@@ -34968,7 +35062,7 @@ function fallbackTitle(prompt) {
34968
35062
  }
34969
35063
  function resolveSlug(frizzDir, base, taken) {
34970
35064
  base = ThreadSlug.parse(base);
34971
- const isTaken = (slug) => existsSync10(join27(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
35065
+ const isTaken = (slug) => existsSync10(join28(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
34972
35066
  if (!isTaken(base)) return base;
34973
35067
  for (let n = 2; ; n++) {
34974
35068
  const suffix = `-${n}`;
@@ -34985,12 +35079,12 @@ function resolveLegacyThreadFile(projectDir, value) {
34985
35079
  if (!parsed.success) return null;
34986
35080
  try {
34987
35081
  const projectRoot = realpathSync7(projectDir);
34988
- const frizzPath = join27(projectRoot, ".frizz");
35082
+ const frizzPath = join28(projectRoot, ".frizz");
34989
35083
  const frizzStat = lstatSync3(frizzPath);
34990
35084
  if (!frizzStat.isDirectory() || frizzStat.isSymbolicLink()) return null;
34991
35085
  const realFrizz = realpathSync7(frizzPath);
34992
35086
  if (dirname11(realFrizz) !== projectRoot || basename6(realFrizz) !== ".frizz") return null;
34993
- const path = join27(realFrizz, `${parsed.data}.md`);
35087
+ const path = join28(realFrizz, `${parsed.data}.md`);
34994
35088
  const before = lstatSync3(path);
34995
35089
  if (!before.isFile() || before.isSymbolicLink()) return null;
34996
35090
  const realPath = realpathSync7(path);
@@ -35001,7 +35095,7 @@ function resolveLegacyThreadFile(projectDir, value) {
35001
35095
  const fd = openSync13(path, constants.O_RDONLY | constants.O_NOFOLLOW);
35002
35096
  try {
35003
35097
  openedBefore = fstatSync2(fd);
35004
- contents = readFileSync16(fd);
35098
+ contents = readFileSync17(fd);
35005
35099
  openedAfter = fstatSync2(fd);
35006
35100
  } finally {
35007
35101
  closeSync12(fd);
@@ -35034,7 +35128,7 @@ function boardAuthorizesAdoption(board, slug) {
35034
35128
  return !board.errorItems.some((item) => item.file === `${slug}.md`);
35035
35129
  }
35036
35130
  function ensureSafeDirectDirectory(parent, name) {
35037
- const path = join27(parent, name);
35131
+ const path = join28(parent, name);
35038
35132
  try {
35039
35133
  mkdirSync13(path);
35040
35134
  } catch (error) {
@@ -35064,8 +35158,8 @@ function loadWorkerPrompt(kind = "claude") {
35064
35158
  function monitorScriptsDir() {
35065
35159
  const plugin = workerPluginDir();
35066
35160
  if (!plugin) return void 0;
35067
- const dir = join27(plugin, "skills", "gh", "scripts");
35068
- return existsSync10(join27(dir, "ci-watch.mjs")) ? dir : void 0;
35161
+ const dir = join28(plugin, "skills", "gh", "scripts");
35162
+ return existsSync10(join28(dir, "ci-watch.mjs")) ? dir : void 0;
35069
35163
  }
35070
35164
  function codexScratchpadHookConfig(hookScript, sessionId) {
35071
35165
  if (!hookScript || !sessionId) return {};
@@ -35077,7 +35171,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
35077
35171
  }
35078
35172
  ]
35079
35173
  });
35080
- const bashBackgroundHook = join27(dirname11(hookScript), "bash-background.mjs");
35174
+ const bashBackgroundHook = join28(dirname11(hookScript), "bash-background.mjs");
35081
35175
  return {
35082
35176
  bypass_hook_trust: true,
35083
35177
  hooks: {
@@ -35103,7 +35197,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
35103
35197
  }
35104
35198
  function scratchpadHookScript() {
35105
35199
  const plugin = workerPluginDir();
35106
- return plugin ? join27(plugin, "hooks", "scratchpad.mjs") : void 0;
35200
+ return plugin ? join28(plugin, "hooks", "scratchpad.mjs") : void 0;
35107
35201
  }
35108
35202
  function composePrompt(sessionId, prompt, kind = "claude") {
35109
35203
  const children2 = kind === "codex" ? "Native sub-agents share it \u2014 have each write its OWN file rather than all editing one." : "Name it in a sub-agent's prompt when you want its notes to land somewhere you can read; give each child its OWN file rather than having them all edit one.";
@@ -35119,12 +35213,12 @@ function scratchpadOrientation(sessionId, kind = "claude") {
35119
35213
  return `SCRATCH DIRECTORY: .frizz/threads/${sessionId}/ \u2014 yours, free-form, as many files as you like, and nothing is expected in it. A single direct task usually needs none; writing notes is never a substitute for doing the work. On a long effort write the doc you would want if you lost your context (${children2}), then arm mcp__frizz__recurring_prompt with post_compaction: true and a prompt LINKING that file \u2014 frizz hands the link back when your context is compacted. Nothing in this directory is read automatically.`;
35120
35214
  }
35121
35215
  function frizzConfigBlock(projectDir) {
35122
- const path = join27(projectDir, "FRIZZ.md");
35216
+ const path = join28(projectDir, "FRIZZ.md");
35123
35217
  let body;
35124
35218
  try {
35125
35219
  const st = statSync12(path);
35126
35220
  if (!st.isFile() || st.size > FRIZZ_MD_MAX_BYTES) return "";
35127
- body = readFileSync16(path, "utf8").trim();
35221
+ body = readFileSync17(path, "utf8").trim();
35128
35222
  } catch {
35129
35223
  return "";
35130
35224
  }
@@ -35159,7 +35253,7 @@ function resolveFrizzMcp(target, moduleUrl = import.meta.url, env = process.env,
35159
35253
  const { stateDir, serverLock, projectId } = typeof target === "string" ? { stateDir: target } : target;
35160
35254
  const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
35161
35255
  if (!pluginDir) return void 0;
35162
- const scriptPath = join27(pluginDir, "bin", FRIZZ_MCP.script);
35256
+ const scriptPath = join28(pluginDir, "bin", FRIZZ_MCP.script);
35163
35257
  if (!existsSync10(scriptPath)) return void 0;
35164
35258
  return {
35165
35259
  scriptPath,
@@ -35242,7 +35336,7 @@ function buildClaudeResumeCommand(opts) {
35242
35336
  }
35243
35337
  function createDispatcher(deps) {
35244
35338
  const readBoardSource = deps.readBoard ?? readBoard;
35245
- const frizzDir = join27(deps.project.dir, ".frizz");
35339
+ const frizzDir = join28(deps.project.dir, ".frizz");
35246
35340
  const adoptionRuntime = deps.adoptionRuntime ?? productionRuntime;
35247
35341
  function cleanupPrewrites(built) {
35248
35342
  for (const path of new Set(built.prewrite.map((file) => file.path))) {
@@ -35255,7 +35349,7 @@ function createDispatcher(deps) {
35255
35349
  function cleanupDispatchFiles(scratchRel, built, sessionId) {
35256
35350
  cleanupPrewrites(built);
35257
35351
  try {
35258
- rmSync8(join27(deps.project.dir, scratchRel), { force: true, recursive: true });
35352
+ rmSync8(join28(deps.project.dir, scratchRel), { force: true, recursive: true });
35259
35353
  } catch {
35260
35354
  }
35261
35355
  cleanupAdoptionSessionFiles(deps.project.dir, sessionId);
@@ -35688,7 +35782,7 @@ import {
35688
35782
  watch as fsWatch
35689
35783
  } from "node:fs";
35690
35784
  import { homedir as homedir12 } from "node:os";
35691
- import { join as join28 } from "node:path";
35785
+ import { join as join29 } from "node:path";
35692
35786
  import watcher from "@parcel/watcher";
35693
35787
  function appServerTurnStalled(liveness, lastActivityAt, nowMs) {
35694
35788
  if (!liveness) return false;
@@ -36373,7 +36467,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
36373
36467
  if (parcelSub || stopped) return Promise.resolve();
36374
36468
  if (watchSetup) return watchSetup;
36375
36469
  const setup = (async () => {
36376
- const next = await subscribe(join28(project.dir, ".frizz"), () => scheduleRebuild());
36470
+ const next = await subscribe(join29(project.dir, ".frizz"), () => scheduleRebuild());
36377
36471
  if (stopped) {
36378
36472
  await next.unsubscribe();
36379
36473
  return;
@@ -38307,7 +38401,7 @@ var init_resume = __esm({
38307
38401
  });
38308
38402
 
38309
38403
  // packages/server/src/backend/claude.ts
38310
- import { join as join29 } from "node:path";
38404
+ import { join as join30 } from "node:path";
38311
38405
  function toolResultText2(content) {
38312
38406
  if (typeof content === "string") return content;
38313
38407
  if (!Array.isArray(content)) return "";
@@ -38396,7 +38490,7 @@ function createClaudeBackend(opts) {
38396
38490
  return { argv, env: claudeWorkerEnvironment(), prewrite: [] };
38397
38491
  },
38398
38492
  transcriptPath(sessionId) {
38399
- return join29(opts.logDir, `${sessionId}.jsonl`);
38493
+ return join30(opts.logDir, `${sessionId}.jsonl`);
38400
38494
  },
38401
38495
  parseLine(line) {
38402
38496
  return parseClaudeLine(line);
@@ -38566,12 +38660,12 @@ var init_login_utility = __esm({
38566
38660
 
38567
38661
  // packages/server/src/backend/codex-app-server-diagnostics.ts
38568
38662
  import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync14, renameSync as renameSync8, statSync as statSync13 } from "node:fs";
38569
- import { join as join30 } from "node:path";
38663
+ import { join as join31 } from "node:path";
38570
38664
  function codexDiagnosticLogPath(stateDir, projectId) {
38571
- return join30(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
38665
+ return join31(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
38572
38666
  }
38573
38667
  function createCodexDiagnosticSink(stateDir, projectId, now = () => /* @__PURE__ */ new Date()) {
38574
- const dir = join30(stateDir, "codex-app-server");
38668
+ const dir = join31(stateDir, "codex-app-server");
38575
38669
  const path = codexDiagnosticLogPath(stateDir, projectId);
38576
38670
  let ensured = false;
38577
38671
  return (event) => {
@@ -38603,7 +38697,7 @@ var init_codex_app_server_diagnostics = __esm({
38603
38697
  import { execFile as execFile7 } from "node:child_process";
38604
38698
  import { readdirSync as readdirSync8, unlinkSync as unlinkSync4 } from "node:fs";
38605
38699
  import { connect as connectSocket } from "node:net";
38606
- import { join as join31 } from "node:path";
38700
+ import { join as join32 } from "node:path";
38607
38701
  function parseLsofSocketNames(stdout) {
38608
38702
  const referenced = /* @__PURE__ */ new Set();
38609
38703
  for (const line of stdout.split("\n")) {
@@ -38620,7 +38714,7 @@ function sweepStaleSockets(options, deps = {}) {
38620
38714
  const keep = new Set(options.keep ?? []);
38621
38715
  let candidates;
38622
38716
  try {
38623
- candidates = (deps.readdir ?? readdirSync8)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join31(options.dir, name)).filter((path) => !keep.has(path));
38717
+ candidates = (deps.readdir ?? readdirSync8)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join32(options.dir, name)).filter((path) => !keep.has(path));
38624
38718
  } catch {
38625
38719
  return;
38626
38720
  }
@@ -38670,7 +38764,7 @@ var init_stale_socket_sweep = __esm({
38670
38764
 
38671
38765
  // packages/server/src/orphan-reaper.ts
38672
38766
  import { execFileSync as execFileSync5 } from "node:child_process";
38673
- import { readFileSync as readFileSync17 } from "node:fs";
38767
+ import { readFileSync as readFileSync18 } from "node:fs";
38674
38768
  import { dirname as dirname12 } from "node:path";
38675
38769
  function firstTokenBasename(command) {
38676
38770
  const first = command.trimStart().split(/\s+/, 1)[0] ?? "";
@@ -38937,7 +39031,7 @@ var init_orphan_reaper = __esm({
38937
39031
  defaultExec = (file, args) => execFileSync5(file, args, { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 1e4 });
38938
39032
  defaultReadEnv = (pid) => {
38939
39033
  try {
38940
- return readFileSync17(`/proc/${pid}/environ`, "utf8");
39034
+ return readFileSync18(`/proc/${pid}/environ`, "utf8");
38941
39035
  } catch {
38942
39036
  return null;
38943
39037
  }
@@ -39084,7 +39178,7 @@ var init_thread_hibernation = __esm({
39084
39178
  });
39085
39179
 
39086
39180
  // packages/server/src/context.ts
39087
- import { join as join32 } from "node:path";
39181
+ import { join as join33 } from "node:path";
39088
39182
  import { randomUUID as randomUUID15 } from "node:crypto";
39089
39183
  import { homedir as homedir13 } from "node:os";
39090
39184
  function reconcileSessions(storage) {
@@ -39242,7 +39336,7 @@ async function createContext(opts = {}) {
39242
39336
  function createContextUnchecked(opts, resources) {
39243
39337
  const home = opts.home ?? homedir13();
39244
39338
  const project = opts.project ?? resolveProject();
39245
- const dbPath = join32(project.stateDir, "ui.db");
39339
+ const dbPath = join33(project.stateDir, "ui.db");
39246
39340
  const storage = createStorage(dbPath);
39247
39341
  resources.storage = storage;
39248
39342
  const bus = new Bus();
@@ -39570,6 +39664,8 @@ ${wakeDeliveryToken(deliveryId)}`;
39570
39664
  getSettings: () => getSettings(storage, home),
39571
39665
  setSettings: (s) => setSettings(storage, s, home),
39572
39666
  resetSettings: () => resetSettings(storage, home),
39667
+ getDispatchPreferences: (codexModels) => getDispatchPreferences(storage, getSettings(storage, home), home, codexModels),
39668
+ setDispatchPreference: (update, codexModels) => setDispatchPreference(storage, getSettings(storage, home), home, update, codexModels),
39573
39669
  activeTenants: opts.activeTenants,
39574
39670
  claudeBin: opts.claudeBin,
39575
39671
  codexBin: opts.codexBin,
@@ -39585,6 +39681,7 @@ var init_context = __esm({
39585
39681
  init_project();
39586
39682
  init_storage();
39587
39683
  init_settings();
39684
+ init_dispatch_preferences();
39588
39685
  init_quota();
39589
39686
  init_claude_quota();
39590
39687
  init_board();
@@ -42270,7 +42367,7 @@ var init_server = __esm({
42270
42367
  });
42271
42368
 
42272
42369
  // packages/server/src/repair.ts
42273
- import { existsSync as existsSync12, readFileSync as readFileSync18, writeFileSync as writeFileSync11 } from "node:fs";
42370
+ import { existsSync as existsSync12, readFileSync as readFileSync19, writeFileSync as writeFileSync11 } from "node:fs";
42274
42371
  import { basename as basename7, dirname as dirname13, resolve as resolve6 } from "node:path";
42275
42372
  function quoteValue(v) {
42276
42373
  if (/^[\w./#:+-]+$/.test(v)) return v;
@@ -42286,7 +42383,7 @@ function repairThreadFile(frizzDir, file) {
42286
42383
  if (dirname13(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
42287
42384
  if (!abs.endsWith(".md")) throw new RepairError(`refusing to repair "${file}": not a .md thread file`);
42288
42385
  if (!existsSync12(abs)) throw new RepairError(`no thread file to repair: ${basename7(abs)}`);
42289
- const content = readFileSync18(abs, "utf8");
42386
+ const content = readFileSync19(abs, "utf8");
42290
42387
  const firstLine2 = content.replace(/^/, "").split(/\r?\n/).find((l) => l.trim() !== "");
42291
42388
  if (firstLine2?.trim() === "---") {
42292
42389
  throw new RepairError(`${basename7(abs)} already opens with a "---" block \u2014 repair only heals a MISSING frontmatter block`);
@@ -42319,7 +42416,7 @@ var init_repair = __esm({
42319
42416
  });
42320
42417
 
42321
42418
  // cc-worker/hooks/bash-background.mjs
42322
- import { readFileSync as readFileSync19 } from "node:fs";
42419
+ import { readFileSync as readFileSync20 } from "node:fs";
42323
42420
  import { basename as basename8 } from "node:path";
42324
42421
  import { pathToFileURL } from "node:url";
42325
42422
  function emit(obj) {
@@ -42468,7 +42565,7 @@ var init_bash_background = __esm({
42468
42565
  if (isDirectHookExecution(process.argv[1], import.meta.url)) {
42469
42566
  try {
42470
42567
  const env = process.argv.includes("--frizz-thread") ? { ...process.env, FRIZZ_THREAD: process.env.FRIZZ_THREAD || "codex-worker" } : process.env;
42471
- emit(evaluateBashBackgroundHook(JSON.parse(readFileSync19(0, "utf8")), env));
42568
+ emit(evaluateBashBackgroundHook(JSON.parse(readFileSync20(0, "utf8")), env));
42472
42569
  } catch {
42473
42570
  emit({});
42474
42571
  }
@@ -42477,10 +42574,10 @@ var init_bash_background = __esm({
42477
42574
  });
42478
42575
 
42479
42576
  // packages/server/src/transcript.ts
42480
- import { closeSync as closeSync13, existsSync as existsSync13, fstatSync as fstatSync3, mkdirSync as mkdirSync15, openSync as openSync14, readdirSync as readdirSync9, readFileSync as readFileSync20, readSync as readSync7, renameSync as renameSync9, statSync as statSync14, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
42577
+ import { closeSync as closeSync13, existsSync as existsSync13, fstatSync as fstatSync3, mkdirSync as mkdirSync15, openSync as openSync14, readdirSync as readdirSync9, readFileSync as readFileSync21, readSync as readSync7, renameSync as renameSync9, statSync as statSync14, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
42481
42578
  import { createHash as createHash13 } from "node:crypto";
42482
42579
  import { StringDecoder as StringDecoder4 } from "node:string_decoder";
42483
- import { join as join33 } from "node:path";
42580
+ import { join as join34 } from "node:path";
42484
42581
  import { homedir as homedir14 } from "node:os";
42485
42582
  function formatTokens(n) {
42486
42583
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -43030,14 +43127,14 @@ function pruneScreenshotCache() {
43030
43127
  if (entries.length <= SCREENSHOT_CACHE_MAX) return;
43031
43128
  const byMtime = entries.map((n) => {
43032
43129
  try {
43033
- return { n, m: statSync14(join33(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
43130
+ return { n, m: statSync14(join34(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
43034
43131
  } catch {
43035
43132
  return { n, m: 0 };
43036
43133
  }
43037
43134
  }).sort((a, b) => b.m - a.m);
43038
43135
  for (const { n } of byMtime.slice(SCREENSHOT_CACHE_MAX)) {
43039
43136
  try {
43040
- unlinkSync5(join33(SCREENSHOT_CACHE_DIR, n));
43137
+ unlinkSync5(join34(SCREENSHOT_CACHE_DIR, n));
43041
43138
  } catch {
43042
43139
  }
43043
43140
  }
@@ -43067,14 +43164,14 @@ function persistBase64Image(mediaType, data, idKey) {
43067
43164
  const ext = IMAGE_MEDIA_EXT[typeof mediaType === "string" ? mediaType.toLowerCase() : ""];
43068
43165
  if (!ext || !data) return void 0;
43069
43166
  const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
43070
- const path = join33(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
43167
+ const path = join34(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
43071
43168
  try {
43072
43169
  if (existsSync13(path)) return path;
43073
43170
  if (data.length > SCREENSHOT_MAX_BASE64) return void 0;
43074
43171
  const buf = Buffer.from(data, "base64");
43075
43172
  if (buf.length === 0 || !looksLikeImage(buf, ext)) return void 0;
43076
43173
  mkdirSync15(SCREENSHOT_CACHE_DIR, { recursive: true });
43077
- const tmp = join33(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
43174
+ const tmp = join34(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
43078
43175
  writeFileSync12(tmp, buf);
43079
43176
  renameSync9(tmp, path);
43080
43177
  pruneScreenshotCache();
@@ -43089,14 +43186,14 @@ function persistSentFile(srcPath, idKey) {
43089
43186
  const outExt = ext === "jpeg" ? "jpg" : ext;
43090
43187
  try {
43091
43188
  const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
43092
- const dest = join33(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
43189
+ const dest = join34(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
43093
43190
  if (existsSync13(dest)) return dest;
43094
43191
  const size = statSync14(srcPath).size;
43095
43192
  if (size === 0 || size > SENT_IMAGE_MAX_BYTES) return void 0;
43096
- const buf = readFileSync20(srcPath);
43193
+ const buf = readFileSync21(srcPath);
43097
43194
  if (!looksLikeImage(buf, outExt)) return void 0;
43098
43195
  mkdirSync15(SCREENSHOT_CACHE_DIR, { recursive: true });
43099
- const tmp = join33(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
43196
+ const tmp = join34(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
43100
43197
  writeFileSync12(tmp, buf);
43101
43198
  renameSync9(tmp, dest);
43102
43199
  pruneScreenshotCache();
@@ -43513,7 +43610,7 @@ function readTranscript(project, sessionId) {
43513
43610
  }
43514
43611
  function verifyIncrementalParse(path, identityPrefix, incremental) {
43515
43612
  try {
43516
- const fresh = parseTranscript(readFileSync20(path, "utf8"), identityPrefix);
43613
+ const fresh = parseTranscript(readFileSync21(path, "utf8"), identityPrefix);
43517
43614
  const a = JSON.stringify(incremental);
43518
43615
  const b = JSON.stringify(fresh);
43519
43616
  if (a !== b) {
@@ -43533,16 +43630,16 @@ function verifyIncrementalParse(path, identityPrefix, incremental) {
43533
43630
  }
43534
43631
  }
43535
43632
  function logDirOf(project) {
43536
- return join33(homedir14(), ".claude", "projects", project.cwdSlug);
43633
+ return join34(homedir14(), ".claude", "projects", project.cwdSlug);
43537
43634
  }
43538
43635
  function resolveTranscriptPath(project, sessionId) {
43539
- const path = join33(logDirOf(project), `${sessionId}.jsonl`);
43636
+ const path = join34(logDirOf(project), `${sessionId}.jsonl`);
43540
43637
  try {
43541
43638
  if (statSync14(path).size > 0) return path;
43542
43639
  } catch {
43543
43640
  }
43544
43641
  const stranded = discoverTranscriptDir(logDirOf(project), sessionId);
43545
- return stranded ? join33(stranded, `${sessionId}.jsonl`) : path;
43642
+ return stranded ? join34(stranded, `${sessionId}.jsonl`) : path;
43546
43643
  }
43547
43644
  function projectCodexTranscript(raw2, identityPrefix = "codex") {
43548
43645
  const out = [];
@@ -44745,7 +44842,7 @@ function readEarlierThreadTranscriptPage(project, storage, slug, cursor, backend
44745
44842
  }
44746
44843
  function readCodexTranscriptFile(absPath, nativeId = absPath) {
44747
44844
  try {
44748
- return parseCodexTranscript(readFileSync20(absPath, "utf8"), `codex:${nativeId}`);
44845
+ return parseCodexTranscript(readFileSync21(absPath, "utf8"), `codex:${nativeId}`);
44749
44846
  } catch {
44750
44847
  return [];
44751
44848
  }
@@ -44843,7 +44940,7 @@ function projectTranscriptPageAgentLifecycles(page, lookup, peerLookup) {
44843
44940
  function readTranscriptFile(absPath) {
44844
44941
  try {
44845
44942
  const pathKey = createHash13("sha256").update(absPath).digest("base64url").slice(0, 16);
44846
- return parseTranscript(readFileSync20(absPath, "utf8"), `claude-file:${pathKey}`);
44943
+ return parseTranscript(readFileSync21(absPath, "utf8"), `claude-file:${pathKey}`);
44847
44944
  } catch {
44848
44945
  return [];
44849
44946
  }
@@ -44940,9 +45037,9 @@ var init_open_external = __esm({
44940
45037
 
44941
45038
  // packages/server/src/local-file.ts
44942
45039
  import { spawn as spawn6 } from "node:child_process";
44943
- import { readFileSync as readFileSync21, realpathSync as realpathSync8, statSync as statSync15 } from "node:fs";
45040
+ import { readFileSync as readFileSync22, realpathSync as realpathSync8, statSync as statSync15 } from "node:fs";
44944
45041
  import { homedir as homedir15 } from "node:os";
44945
- import { isAbsolute as isAbsolute3, join as join34, resolve as resolve7, sep } from "node:path";
45042
+ import { isAbsolute as isAbsolute3, join as join35, resolve as resolve7, sep } from "node:path";
44946
45043
  function isUnder(real, root) {
44947
45044
  let rootReal;
44948
45045
  try {
@@ -44972,7 +45069,7 @@ function resolveLocalFile(rawPath, roots) {
44972
45069
  function resolveOpenableFile(raw2, projectDir, roots, home = homedir15()) {
44973
45070
  const trimmed = raw2.trim().replace(/:\d+(?::\d+)?$/, "");
44974
45071
  if (!trimmed) return null;
44975
- const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ? join34(home, trimmed.slice(2)) : isAbsolute3(trimmed) ? trimmed : resolve7(projectDir, trimmed);
45072
+ const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ? join35(home, trimmed.slice(2)) : isAbsolute3(trimmed) ? trimmed : resolve7(projectDir, trimmed);
44976
45073
  try {
44977
45074
  return resolveLocalFile(abs, roots);
44978
45075
  } catch {
@@ -44983,7 +45080,7 @@ function readLocalMarkdown(rawPath, roots) {
44983
45080
  if (!MARKDOWN_FILE_EXT.test(rawPath.trim())) throw new Error("Local file is not a Markdown file");
44984
45081
  const path = resolveLocalFile(rawPath, roots);
44985
45082
  if (!MARKDOWN_FILE_EXT.test(path)) throw new Error("Local file is not a Markdown file");
44986
- const bytes = readFileSync21(path);
45083
+ const bytes = readFileSync22(path);
44987
45084
  if (bytes.length <= MARKDOWN_READ_LIMIT) return { path, markdown: bytes.toString("utf8"), truncated: false };
44988
45085
  const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
44989
45086
  const lastBreak = head.lastIndexOf(10);
@@ -45330,67 +45427,6 @@ var init_account_actions = __esm({
45330
45427
  }
45331
45428
  });
45332
45429
 
45333
- // packages/server/src/dispatch-preferences.ts
45334
- function permissionFor(backend, mode) {
45335
- if (backend === "codex") {
45336
- if (mode === "plan" || mode === "bypassPermissions") return mode;
45337
- return "default";
45338
- }
45339
- return mode === "plan" ? "auto" : mode;
45340
- }
45341
- function defaultDispatchPreferences(settings, codexModels = []) {
45342
- const backend = settings.backend ?? (codexModels.some((model) => model.slug === settings.model) ? "codex" : "claude");
45343
- const selected = {
45344
- ...settings.model ? { model: settings.model } : {},
45345
- ...settings.effort ? { effort: settings.effort } : {},
45346
- permissionMode: permissionFor(backend, settings.permissionMode)
45347
- };
45348
- return {
45349
- backend,
45350
- claude: backend === "claude" ? selected : { permissionMode: "auto" },
45351
- codex: backend === "codex" ? selected : { permissionMode: "default" }
45352
- };
45353
- }
45354
- function getDispatchPreferences(storage, settings, codexModels = []) {
45355
- const parsed = DispatchPreferences.safeParse(storage.getSetting(KEY));
45356
- return parsed.success ? parsed.data : defaultDispatchPreferences(settings, codexModels);
45357
- }
45358
- function setDispatchPreference(storage, settings, update, codexModels = []) {
45359
- const current = getDispatchPreferences(storage, settings, codexModels);
45360
- let next;
45361
- if (update.field === "backend") {
45362
- next = { ...current, backend: update.value };
45363
- } else if (update.field === "profile") {
45364
- next = {
45365
- ...current,
45366
- backend: update.backend,
45367
- [update.backend]: {
45368
- ...current[update.backend],
45369
- model: update.model,
45370
- effort: update.effort
45371
- }
45372
- };
45373
- } else {
45374
- const profile = current[update.backend];
45375
- next = {
45376
- ...current,
45377
- ...update.field === "model" ? { backend: update.backend } : {},
45378
- [update.backend]: { ...profile, [update.field]: update.value }
45379
- };
45380
- }
45381
- const validated = DispatchPreferences.parse(next);
45382
- storage.setSetting(KEY, validated);
45383
- return validated;
45384
- }
45385
- var KEY;
45386
- var init_dispatch_preferences = __esm({
45387
- "packages/server/src/dispatch-preferences.ts"() {
45388
- "use strict";
45389
- init_src();
45390
- KEY = "dispatch-preferences.v1";
45391
- }
45392
- });
45393
-
45394
45430
  // packages/server/src/external-terminal.ts
45395
45431
  function shellQuote(value) {
45396
45432
  return `'${value.replace(/'/g, `'"'"'`)}'`;
@@ -45743,8 +45779,8 @@ var init_directory_picker = __esm({
45743
45779
  });
45744
45780
 
45745
45781
  // packages/server/src/router.ts
45746
- import { readFileSync as readFileSync22, statSync as statSync17 } from "node:fs";
45747
- import { join as join35, resolve as resolve8 } from "node:path";
45782
+ import { readFileSync as readFileSync23, statSync as statSync17 } from "node:fs";
45783
+ import { join as join36, resolve as resolve8 } from "node:path";
45748
45784
  import { randomUUID as randomUUID16 } from "node:crypto";
45749
45785
  import { basename as basename9, dirname as dirname14 } from "node:path";
45750
45786
  import { existsSync as existsSync14, mkdirSync as mkdirSync16, rmSync as rmSync9, writeFileSync as writeFileSync13 } from "node:fs";
@@ -45907,7 +45943,7 @@ function projectCard(entry, stale) {
45907
45943
  function addProjectAtPath(input) {
45908
45944
  const typed = input.trim();
45909
45945
  if (!typed) throw new Error("Enter a folder path.");
45910
- const expanded = typed === "~" || typed.startsWith("~/") ? join35(homedir16(), typed.slice(1)) : typed;
45946
+ const expanded = typed === "~" || typed.startsWith("~/") ? join36(homedir16(), typed.slice(1)) : typed;
45911
45947
  const absolute = resolve8(expanded);
45912
45948
  let stats;
45913
45949
  try {
@@ -45952,7 +45988,7 @@ function storeProjectIcon(id, name, bytes) {
45952
45988
  function setProjectIconFromFile(id, file) {
45953
45989
  let bytes;
45954
45990
  try {
45955
- bytes = readFileSync22(file);
45991
+ bytes = readFileSync23(file);
45956
45992
  } catch {
45957
45993
  throw new Error("That file could not be read.");
45958
45994
  }
@@ -45960,7 +45996,7 @@ function setProjectIconFromFile(id, file) {
45960
45996
  return storeProjectIcon(id, file, bytes);
45961
45997
  }
45962
45998
  function createRouter(ctx) {
45963
- const frizzDir = join35(ctx.project.dir, ".frizz");
45999
+ const frizzDir = join36(ctx.project.dir, ".frizz");
45964
46000
  const openRoots = openableFileRoots(ctx.project);
45965
46001
  function isAutoTitledSession(slug) {
45966
46002
  return ctx.storage.getSession(slug)?.title_auto === 1;
@@ -47615,7 +47651,7 @@ ${gapNote}` : input.message;
47615
47651
  for (const entry of listProjects()) {
47616
47652
  if (entry.stale) continue;
47617
47653
  try {
47618
- const db = new sqlite_default(join35(projectStateDir(entry.id), "ui.db"), { readonly: true });
47654
+ const db = new sqlite_default(join36(projectStateDir(entry.id), "ui.db"), { readonly: true });
47619
47655
  try {
47620
47656
  const hit = db.prepare("SELECT 1 FROM session WHERE slug = ? LIMIT 1").get(input.slug);
47621
47657
  if (hit) found.push({ projectSlug: entry.slug, projectName: entry.name ?? entry.slug });
@@ -47645,12 +47681,12 @@ ${gapNote}` : input.message;
47645
47681
  }),
47646
47682
  dispatchPreferencesGet: query({
47647
47683
  output: DispatchPreferences,
47648
- handler: async () => getDispatchPreferences(ctx.storage, ctx.getSettings(), readCodexModels())
47684
+ handler: async () => ctx.getDispatchPreferences(readCodexModels())
47649
47685
  }),
47650
47686
  dispatchPreferenceSet: mutation({
47651
47687
  input: SetDispatchPreferenceInput,
47652
47688
  output: DispatchPreferences,
47653
- handler: async ({ input }) => setDispatchPreference(ctx.storage, ctx.getSettings(), input, readCodexModels())
47689
+ handler: async ({ input }) => ctx.setDispatchPreference(input, readCodexModels())
47654
47690
  }),
47655
47691
  // The shipped GitHub batch-dispatch prompt template (single source of truth: server/github.ts).
47656
47692
  // The Settings UI reads it to prefill the editor and to power "reset to default"; an empty/unset
@@ -47761,7 +47797,6 @@ var init_router5 = __esm({
47761
47797
  init_thread_profiles();
47762
47798
  init_adoption_recovery();
47763
47799
  init_awaiting();
47764
- init_dispatch_preferences();
47765
47800
  init_storage();
47766
47801
  init_external_terminal();
47767
47802
  init_background_shell_output();
@@ -47972,7 +48007,7 @@ var init_compression = __esm({
47972
48007
  });
47973
48008
 
47974
48009
  // packages/server/src/local-image.ts
47975
- import { readFileSync as readFileSync23, realpathSync as realpathSync9, statSync as statSync18 } from "node:fs";
48010
+ import { readFileSync as readFileSync24, realpathSync as realpathSync9, statSync as statSync18 } from "node:fs";
47976
48011
  import { extname as extname2, isAbsolute as isAbsolute4 } from "node:path";
47977
48012
  function resolveLocalImage(rawPath) {
47978
48013
  if (!rawPath || !isAbsolute4(rawPath)) return { status: 400 };
@@ -47986,7 +48021,7 @@ function resolveLocalImage(rawPath) {
47986
48021
  }
47987
48022
  try {
47988
48023
  if (!statSync18(real).isFile()) return { status: 404 };
47989
- return { status: 200, contentType, body: readFileSync23(real) };
48024
+ return { status: 200, contentType, body: readFileSync24(real) };
47990
48025
  } catch {
47991
48026
  return { status: 404 };
47992
48027
  }
@@ -48006,9 +48041,9 @@ var init_local_image = __esm({
48006
48041
  });
48007
48042
 
48008
48043
  // packages/server/src/project-icon.ts
48009
- import { readFileSync as readFileSync24, readdirSync as readdirSync10, realpathSync as realpathSync10, statSync as statSync19 } from "node:fs";
48044
+ import { readFileSync as readFileSync25, readdirSync as readdirSync10, realpathSync as realpathSync10, statSync as statSync19 } from "node:fs";
48010
48045
  import { homedir as homedir17 } from "node:os";
48011
- import { basename as basename10, dirname as dirname15, extname as extname3, join as join36, relative, sep as sep2 } from "node:path";
48046
+ import { basename as basename10, dirname as dirname15, extname as extname3, join as join37, relative, sep as sep2 } from "node:path";
48012
48047
  function normalizeStem(stem) {
48013
48048
  const sized = stem.toLowerCase().replace(/[@-]\d+(\.\d+)?x(\d+)?$/u, "").replace(/[-_]\d{2,4}$/u, "");
48014
48049
  const normalized = sized.replace(VARIANT_SUFFIX, "");
@@ -48026,7 +48061,7 @@ function sizeScore(dimensions) {
48026
48061
  return Math.max(0, Math.min(40, Math.round(Math.log2(edge / 24) * 8)));
48027
48062
  }
48028
48063
  function under(root, relativeDirectory) {
48029
- return relativeDirectory ? join36(root, relativeDirectory) : root;
48064
+ return relativeDirectory ? join37(root, relativeDirectory) : root;
48030
48065
  }
48031
48066
  function listFiles(directory) {
48032
48067
  try {
@@ -48048,19 +48083,19 @@ function iconDirectories(root) {
48048
48083
  for (const asset of ASSET_DIRECTORIES) directories.push(under(root, asset));
48049
48084
  for (const host of HOST_DIRECTORIES) {
48050
48085
  if (!children2.has(host)) continue;
48051
- for (const asset of ASSET_DIRECTORIES) directories.push(under(join36(root, host), asset));
48086
+ for (const asset of ASSET_DIRECTORIES) directories.push(under(join37(root, host), asset));
48052
48087
  }
48053
48088
  for (const extra of EXTRA_DIRECTORIES) directories.push(under(root, extra));
48054
48089
  for (const container of WORKSPACE_CONTAINERS) {
48055
48090
  if (!children2.has(container)) continue;
48056
48091
  let members;
48057
48092
  try {
48058
- members = readdirSync10(join36(root, container), { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
48093
+ members = readdirSync10(join37(root, container), { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
48059
48094
  } catch {
48060
48095
  continue;
48061
48096
  }
48062
48097
  for (const member of members) {
48063
- for (const asset of ASSET_DIRECTORIES) directories.push(under(join36(root, container, member), asset));
48098
+ for (const asset of ASSET_DIRECTORIES) directories.push(under(join37(root, container, member), asset));
48064
48099
  }
48065
48100
  }
48066
48101
  return [...new Set(directories)];
@@ -48068,13 +48103,13 @@ function iconDirectories(root) {
48068
48103
  function manifestIcons(manifestPath) {
48069
48104
  let parsed;
48070
48105
  try {
48071
- parsed = JSON.parse(readFileSync24(manifestPath, "utf8"));
48106
+ parsed = JSON.parse(readFileSync25(manifestPath, "utf8"));
48072
48107
  } catch {
48073
48108
  return [];
48074
48109
  }
48075
48110
  if (!Array.isArray(parsed?.icons)) return [];
48076
48111
  const directory = dirname15(manifestPath);
48077
- return parsed.icons.map((icon) => typeof icon?.src === "string" ? icon.src : void 0).filter((src) => !!src && !/^(https?:)?\/\//u.test(src) && !src.startsWith("data:")).map((src) => join36(directory, src.replace(/[?#].*$/u, "").replace(/^\//u, "")));
48112
+ return parsed.icons.map((icon) => typeof icon?.src === "string" ? icon.src : void 0).filter((src) => !!src && !/^(https?:)?\/\//u.test(src) && !src.startsWith("data:")).map((src) => join37(directory, src.replace(/[?#].*$/u, "").replace(/^\//u, "")));
48078
48113
  }
48079
48114
  function projectIconCandidates(root) {
48080
48115
  const projectStem = normalizeStem(basename10(root)).normalized;
@@ -48093,7 +48128,7 @@ function projectIconCandidates(root) {
48093
48128
  for (const name of listFiles(directory)) {
48094
48129
  const extension2 = extname3(name).toLowerCase();
48095
48130
  if (MANIFEST_NAMES.includes(name.toLowerCase())) {
48096
- for (const icon of manifestIcons(join36(directory, name))) {
48131
+ for (const icon of manifestIcons(join37(directory, name))) {
48097
48132
  if (MEASURABLE_IMAGE_EXTENSIONS.has(extname3(icon).toLowerCase())) {
48098
48133
  fromManifest.add(icon);
48099
48134
  files.push({ path: icon, directory: dirname15(icon) });
@@ -48104,7 +48139,7 @@ function projectIconCandidates(root) {
48104
48139
  if (!MEASURABLE_IMAGE_EXTENSIONS.has(extension2)) continue;
48105
48140
  const stem = name.slice(0, name.length - extension2.length);
48106
48141
  if (normalizeStem(stem).normalized === "favicon") iconHomes.add(directory);
48107
- files.push({ path: join36(directory, name), directory });
48142
+ files.push({ path: join37(directory, name), directory });
48108
48143
  if (files.length >= MAX_CANDIDATES) break;
48109
48144
  }
48110
48145
  }
@@ -48169,7 +48204,7 @@ function resolveProjectIconResponse(id, options = {}) {
48169
48204
  });
48170
48205
  if (!roots.some((root) => real === root || real.startsWith(root + sep2))) return { status: 404 };
48171
48206
  try {
48172
- return { status: 200, contentType, body: readFileSync24(real) };
48207
+ return { status: 200, contentType, body: readFileSync25(real) };
48173
48208
  } catch {
48174
48209
  return { status: 404 };
48175
48210
  }
@@ -48281,8 +48316,8 @@ var init_project_icon = __esm({
48281
48316
  });
48282
48317
 
48283
48318
  // packages/server/src/local-visualization.ts
48284
- import { readdirSync as readdirSync11, readFileSync as readFileSync25, realpathSync as realpathSync11, statSync as statSync20 } from "node:fs";
48285
- import { join as join37, sep as sep3 } from "node:path";
48319
+ import { readdirSync as readdirSync11, readFileSync as readFileSync26, realpathSync as realpathSync11, statSync as statSync20 } from "node:fs";
48320
+ import { join as join38, sep as sep3 } from "node:path";
48286
48321
  function children(path, pattern) {
48287
48322
  try {
48288
48323
  return readdirSync11(path, { withFileTypes: true }).filter((entry) => entry.isDirectory() && pattern.test(entry.name)).map((entry) => entry.name).sort().reverse();
@@ -48294,7 +48329,7 @@ function isUnder2(path, root) {
48294
48329
  return path === root || path.startsWith(root.endsWith(sep3) ? root : root + sep3);
48295
48330
  }
48296
48331
  function resolveFragment(projectDir, sessionId, file) {
48297
- const base = join37(projectDir, ".codex", "visualizations");
48332
+ const base = join38(projectDir, ".codex", "visualizations");
48298
48333
  let projectReal;
48299
48334
  let baseReal;
48300
48335
  try {
@@ -48305,12 +48340,12 @@ function resolveFragment(projectDir, sessionId, file) {
48305
48340
  }
48306
48341
  if (!isUnder2(baseReal, projectReal)) return null;
48307
48342
  for (const year of children(base, YEAR_PART)) {
48308
- const yearDir = join37(base, year);
48343
+ const yearDir = join38(base, year);
48309
48344
  for (const month of children(yearDir, DATE_PART)) {
48310
- const monthDir = join37(yearDir, month);
48345
+ const monthDir = join38(yearDir, month);
48311
48346
  for (const day of children(monthDir, DATE_PART)) {
48312
- const sessionRoot = join37(baseReal, year, month, day, sessionId);
48313
- const candidate = join37(monthDir, day, sessionId, file);
48347
+ const sessionRoot = join38(baseReal, year, month, day, sessionId);
48348
+ const candidate = join38(monthDir, day, sessionId, file);
48314
48349
  try {
48315
48350
  const real = realpathSync11(candidate);
48316
48351
  if (isUnder2(real, sessionRoot) && statSync20(real).isFile()) return real;
@@ -48396,7 +48431,7 @@ function resolveLocalVisualization(projectDir, sessionId, file) {
48396
48431
  try {
48397
48432
  const size = statSync20(path).size;
48398
48433
  if (size > MAX_FRAGMENT_BYTES) return { status: 413 };
48399
- fragment = readFileSync25(path, "utf8");
48434
+ fragment = readFileSync26(path, "utf8");
48400
48435
  } catch {
48401
48436
  return { status: 404 };
48402
48437
  }
@@ -48439,7 +48474,7 @@ var init_local_visualization = __esm({
48439
48474
 
48440
48475
  // packages/server/src/app.ts
48441
48476
  import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync14 } from "node:fs";
48442
- import { join as join38 } from "node:path";
48477
+ import { join as join39 } from "node:path";
48443
48478
  import { randomUUID as randomUUID17 } from "node:crypto";
48444
48479
  function createApp(ctx, options = {}) {
48445
48480
  const app = new Hono2();
@@ -48543,10 +48578,10 @@ function createApp(ctx, options = {}) {
48543
48578
  if (typeof body.data !== "string" || body.data.length > ATTACHMENT_MAX_BASE64_CHARS) return c.json({ error: "bad payload" }, 400);
48544
48579
  const ext = `.${attachmentExtension(name)}`;
48545
48580
  const buf = Buffer.from(body.data, "base64");
48546
- const dir = join38(ctx.project.stateDir, "attachments");
48581
+ const dir = join39(ctx.project.stateDir, "attachments");
48547
48582
  mkdirSync17(dir, { recursive: true });
48548
48583
  const base = name.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]+/g, "-").slice(0, 40) || "file";
48549
- const path = join38(dir, `${Date.now()}-${randomUUID17().slice(0, 8)}-${base}${ext}`);
48584
+ const path = join39(dir, `${Date.now()}-${randomUUID17().slice(0, 8)}-${base}${ext}`);
48550
48585
  writeFileSync14(path, buf);
48551
48586
  return c.json({ path });
48552
48587
  });
@@ -49785,10 +49820,10 @@ var init_app_socket = __esm({
49785
49820
  });
49786
49821
 
49787
49822
  // packages/server/src/boot-progress.ts
49788
- import { mkdirSync as mkdirSync18, readFileSync as readFileSync26, renameSync as renameSync10, rmSync as rmSync10, writeFileSync as writeFileSync15 } from "node:fs";
49789
- import { basename as basename11, dirname as dirname16, join as join39 } from "node:path";
49823
+ import { mkdirSync as mkdirSync18, readFileSync as readFileSync27, renameSync as renameSync10, rmSync as rmSync10, writeFileSync as writeFileSync15 } from "node:fs";
49824
+ import { basename as basename11, dirname as dirname16, join as join40 } from "node:path";
49790
49825
  function bootProgressPath(stateDir) {
49791
- return join39(stateDir, BOOT_PROGRESS_NAME);
49826
+ return join40(stateDir, BOOT_PROGRESS_NAME);
49792
49827
  }
49793
49828
  function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
49794
49829
  if (!stateDir) {
@@ -49809,7 +49844,7 @@ function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
49809
49844
  step++;
49810
49845
  try {
49811
49846
  mkdirSync18(dirname16(path), { recursive: true, mode: 448 });
49812
- const temp = join39(dirname16(path), `.${basename11(path)}.${process.pid}.tmp`);
49847
+ const temp = join40(dirname16(path), `.${basename11(path)}.${process.pid}.tmp`);
49813
49848
  writeFileSync15(temp, `${JSON.stringify({ pid: process.pid, step, phase, at: new Date(now).toISOString() })}
49814
49849
  `, "utf8");
49815
49850
  renameSync10(temp, path);
@@ -49926,11 +49961,11 @@ __export(index_exports, {
49926
49961
  unknownProjectPage: () => unknownProjectPage
49927
49962
  });
49928
49963
  import { createServer } from "node:http";
49929
- import { readFileSync as readFileSync27, existsSync as existsSync15 } from "node:fs";
49930
- import { dirname as dirname17, join as join40, resolve as resolve9, extname as extname4, normalize } from "node:path";
49964
+ import { readFileSync as readFileSync28, existsSync as existsSync15 } from "node:fs";
49965
+ import { dirname as dirname17, join as join41, resolve as resolve9, extname as extname4, normalize } from "node:path";
49931
49966
  function readServerAddressHolder(path) {
49932
49967
  try {
49933
- const value = JSON.parse(readFileSync27(path, "utf8"));
49968
+ const value = JSON.parse(readFileSync28(path, "utf8"));
49934
49969
  if (typeof value?.pid !== "number") return void 0;
49935
49970
  return { pid: value.pid, port: typeof value.port === "number" ? value.port : -1 };
49936
49971
  } catch {
@@ -50030,11 +50065,11 @@ function createShutdownSignalHandler(options) {
50030
50065
  }
50031
50066
  function serveStatic(distDir, req, res) {
50032
50067
  const rel = normalize((req.url ?? "/").split("?")[0]).replace(/^(\.\.[/\\])+/, "");
50033
- let file = join40(distDir, rel === "/" ? "index.html" : rel);
50034
- if (!file.startsWith(distDir)) file = join40(distDir, "index.html");
50035
- if (!existsSync15(file)) file = join40(distDir, "index.html");
50068
+ let file = join41(distDir, rel === "/" ? "index.html" : rel);
50069
+ if (!file.startsWith(distDir)) file = join41(distDir, "index.html");
50070
+ if (!existsSync15(file)) file = join41(distDir, "index.html");
50036
50071
  try {
50037
- const body = readFileSync27(file);
50072
+ const body = readFileSync28(file);
50038
50073
  res.writeHead(200, { "content-type": MIME[extname4(file)] ?? "application/octet-stream" });
50039
50074
  res.end(body);
50040
50075
  } catch {
@@ -50383,7 +50418,7 @@ async function startServer(opts = {}) {
50383
50418
  }
50384
50419
  statusPath = serverLockPathFor(ctx.project);
50385
50420
  const webRoot = resolve9(import.meta.dirname, "..", "..", "web");
50386
- const distDir = opts.webDistDir ? resolve9(opts.webDistDir) : join40(webRoot, "dist");
50421
+ const distDir = opts.webDistDir ? resolve9(opts.webDistDir) : join41(webRoot, "dist");
50387
50422
  startupPhase = "Vite";
50388
50423
  if (opts.dev) {
50389
50424
  try {
@@ -50459,7 +50494,7 @@ async function startServer(opts = {}) {
50459
50494
  if (vite) {
50460
50495
  vite.middlewares(req, res, () => {
50461
50496
  try {
50462
- const html = readFileSync27(join40(webRoot, "index.html"), "utf8");
50497
+ const html = readFileSync28(join41(webRoot, "index.html"), "utf8");
50463
50498
  void vite.transformIndexHtml(url, html).then((out) => {
50464
50499
  res.writeHead(200, { "content-type": "text/html" });
50465
50500
  res.end(out);
@@ -50651,7 +50686,7 @@ var init_index = __esm({
50651
50686
  }
50652
50687
  };
50653
50688
  isApiUrl = (url) => url === FRIZZ_ROUTE_PREFIX || url.startsWith(`${FRIZZ_ROUTE_PREFIX}/`);
50654
- serverLockPathFor = (project) => join40(project.stateDir, "server.lock");
50689
+ serverLockPathFor = (project) => join41(project.stateDir, "server.lock");
50655
50690
  MIME = {
50656
50691
  ".html": "text/html",
50657
50692
  ".js": "text/javascript",
@@ -50670,7 +50705,7 @@ init_project_launch();
50670
50705
  init_shutdown();
50671
50706
  init_logging();
50672
50707
  import { existsSync as existsSync16 } from "node:fs";
50673
- import { join as join41 } from "node:path";
50708
+ import { join as join42 } from "node:path";
50674
50709
  process.on("uncaughtException", (error) => {
50675
50710
  log.error("dev-child", `uncaught exception: ${error instanceof Error ? error.stack ?? error.message : error}`);
50676
50711
  process.exit(1);
@@ -50710,7 +50745,7 @@ try {
50710
50745
  ];
50711
50746
  if (!existsSync16(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
50712
50747
  for (const [name, directory, requiredFile] of required) {
50713
- if (!directory || !existsSync16(join41(directory, requiredFile)))
50748
+ if (!directory || !existsSync16(join42(directory, requiredFile)))
50714
50749
  throw new Error(`stable artifact launch is missing verified ${name}`);
50715
50750
  }
50716
50751
  }