frizz-server 0.15.20 → 0.15.23

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 (112) hide show
  1. package/dist/claude-agent-broker.js +371 -39
  2. package/dist/dev-child.js +8255 -6173
  3. package/package.json +1 -1
  4. package/runtime/cc-worker/DECISIONS.md +42 -2
  5. package/runtime/cc-worker/bin/frizz-mcp.mjs +11 -1848
  6. package/runtime/cc-worker/bin/frizzctl +14 -0
  7. package/runtime/cc-worker/bin/frizzctl.cmd +9 -0
  8. package/runtime/cc-worker/bin/frizzctl.mjs +438 -0
  9. package/runtime/cc-worker/hooks/agent-dispatch.mjs +2 -2
  10. package/runtime/cc-worker/hooks/deny-ask.mjs +3 -3
  11. package/runtime/cc-worker/hooks/deny-plan.mjs +2 -2
  12. package/runtime/cc-worker/hooks/perm-policy.mjs +52 -1
  13. package/runtime/cc-worker/hooks/scratchpad.mjs +16 -10
  14. package/runtime/cc-worker/hooks/session-seed.mjs +1 -1
  15. package/runtime/cc-worker/lib/frizz-tools.mjs +2241 -0
  16. package/runtime/cc-worker/skills/gh/SKILL.md +6 -6
  17. package/web-dist/assets/{abnfDiagram-VRR7QNED-B61nQEjt.js → abnfDiagram-VRR7QNED-BW_CIF9J.js} +1 -1
  18. package/web-dist/assets/{arc-CR8_qWI3.js → arc-B475yv46.js} +1 -1
  19. package/web-dist/assets/architecture-TIHT7OUA-wAP7tOoN.js +1 -0
  20. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-6sc4SDOh.js → architectureDiagram-ZJ3FMSHR-DkPvFjFp.js} +1 -1
  21. package/web-dist/assets/{blockDiagram-677ZJIJ3-p-DPTDGB.js → blockDiagram-677ZJIJ3-Rls7Nttu.js} +1 -1
  22. package/web-dist/assets/{c4Diagram-LMCZKHZV-cqvAqZE2.js → c4Diagram-LMCZKHZV-maV0q2bv.js} +1 -1
  23. package/web-dist/assets/channel-Clg0HJPA.js +1 -0
  24. package/web-dist/assets/{chunk-32BRIVSS-BNnoKILR.js → chunk-32BRIVSS-Coi7L0de.js} +1 -1
  25. package/web-dist/assets/{chunk-52WLFC77-BmHIWiVu.js → chunk-52WLFC77-DZaDe-48.js} +1 -1
  26. package/web-dist/assets/{chunk-C7G6YPKG-D7XYFno8.js → chunk-C7G6YPKG-DNQ-JhD9.js} +1 -1
  27. package/web-dist/assets/{chunk-EX3LRPZG-BUViIha7.js → chunk-EX3LRPZG-BQCebwoA.js} +1 -1
  28. package/web-dist/assets/{chunk-FWX5IMBZ-3x5Zky3W.js → chunk-FWX5IMBZ-CqiHtpEB.js} +2 -2
  29. package/web-dist/assets/{chunk-HOUHSVGY-C6_RBSov.js → chunk-HOUHSVGY-Bop69PFg.js} +1 -1
  30. package/web-dist/assets/{chunk-ICXQ74PX-NbVxQ4i1.js → chunk-ICXQ74PX-D3PkeZ6B.js} +1 -1
  31. package/web-dist/assets/{chunk-MOJQB5TN-nRMfcSHe.js → chunk-MOJQB5TN-lidXw8-C.js} +1 -1
  32. package/web-dist/assets/{chunk-OGEWGWER-BbSXfbEB.js → chunk-OGEWGWER-CzD91FAh.js} +1 -1
  33. package/web-dist/assets/{chunk-PUDLZKDR-Byubn9VY.js → chunk-PUDLZKDR-Cilkzvck.js} +1 -1
  34. package/web-dist/assets/{chunk-Q4XR5HBZ-DLq-aZ3t.js → chunk-Q4XR5HBZ-C37UQCfb.js} +1 -1
  35. package/web-dist/assets/{chunk-RYQCIY6F-Dbt66M6V.js → chunk-RYQCIY6F-C0qnX-Ux.js} +1 -1
  36. package/web-dist/assets/{chunk-V7JOEXUC-DNFTmXz6.js → chunk-V7JOEXUC-Da5vOGHX.js} +1 -1
  37. package/web-dist/assets/{chunk-VAUOI2AC-QWrszv3X.js → chunk-VAUOI2AC-FrJadrJY.js} +1 -1
  38. package/web-dist/assets/{chunk-VR4S4FIN-CJdyjwam.js → chunk-VR4S4FIN-DYxK2Z50.js} +1 -1
  39. package/web-dist/assets/{chunk-WYO6CB5R-D_786t-3.js → chunk-WYO6CB5R-C164KTfT.js} +1 -1
  40. package/web-dist/assets/{chunk-XXDRQBXY-Bd_2jBj_.js → chunk-XXDRQBXY-D4wHtxet.js} +1 -1
  41. package/web-dist/assets/{chunk-ZGVPDNZ5-DklPG-LG.js → chunk-ZGVPDNZ5-BXKkVljT.js} +1 -1
  42. package/web-dist/assets/classDiagram-OUVF2IWQ-23bCXfvg.js +1 -0
  43. package/web-dist/assets/classDiagram-v2-EOCWNBFH-23bCXfvg.js +1 -0
  44. package/web-dist/assets/{cose-bilkent-JH36ORCC-C4MtSvEs.js → cose-bilkent-JH36ORCC-BFSgVzNT.js} +1 -1
  45. package/web-dist/assets/{cynefin-VYW2F7L2-Dr0CmMQz.js → cynefin-VYW2F7L2-BSoEbT-s.js} +1 -1
  46. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-BpHXKyDO.js → cynefinDiagram-TSTJHNR4-BBZgLbdX.js} +1 -1
  47. package/web-dist/assets/{dagre-VKFMJZFB-CWAtKn43.js → dagre-VKFMJZFB-Dx6giO7u.js} +1 -1
  48. package/web-dist/assets/{diagram-FQU43EPY-B_6PhpPG.js → diagram-FQU43EPY-BMI3qRca.js} +1 -1
  49. package/web-dist/assets/{diagram-G47NLZAW-DPNrX-3a.js → diagram-G47NLZAW-CJY-MA3L.js} +1 -1
  50. package/web-dist/assets/{diagram-NH7WQ7WH-BL4nqAUm.js → diagram-NH7WQ7WH-CbQVFJ3r.js} +1 -1
  51. package/web-dist/assets/{diagram-OA4YK3LP-CcFbtuCf.js → diagram-OA4YK3LP-CPnrakdY.js} +1 -1
  52. package/web-dist/assets/{diagram-WEI45ONY-Bkl0nXre.js → diagram-WEI45ONY-D9DNwzlo.js} +1 -1
  53. package/web-dist/assets/{dist-krVNNn4H.js → dist-CO93_xVa.js} +1 -1
  54. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-C_51YQqw.js → ebnfDiagram-CCIWWBDH-DNHudB8r.js} +1 -1
  55. package/web-dist/assets/{erDiagram-Q63AITRT-D8oBhiQB.js → erDiagram-Q63AITRT-Cwt63Xz8.js} +1 -1
  56. package/web-dist/assets/eventmodeling-45OFAUF4-Q3Nq1ecc.js +1 -0
  57. package/web-dist/assets/flowDiagram-23GEKE2U-B2snV3ot.js +1 -0
  58. package/web-dist/assets/{ganttDiagram-NO4QXBWP-BOJJvkcQ.js → ganttDiagram-NO4QXBWP-DiFpSJc2.js} +1 -1
  59. package/web-dist/assets/{gitGraph-TEB2WS4Q-DrZGs6X0.js → gitGraph-TEB2WS4Q-2-hTvDOu.js} +1 -1
  60. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-C0pqDVhD.js → gitGraphDiagram-IHSO6WYX-mbc4Il71.js} +1 -1
  61. package/web-dist/assets/index-C6AXnNpg.css +2 -0
  62. package/web-dist/assets/index-DewBdeY0.js +352 -0
  63. package/web-dist/assets/{info-DKCQHKI2-0OcIuVxc.js → info-DKCQHKI2-BO0ZUEnn.js} +1 -1
  64. package/web-dist/assets/{infoDiagram-FWYZ7A6U-CRAc-N7_.js → infoDiagram-FWYZ7A6U-Cn3DmnjS.js} +1 -1
  65. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-D_bHCCxh.js → ishikawaDiagram-FXEZZL3T-Ckwh42aC.js} +1 -1
  66. package/web-dist/assets/{journeyDiagram-5HDEW3XC-Dbvh7D1e.js → journeyDiagram-5HDEW3XC-D26ySLLD.js} +1 -1
  67. package/web-dist/assets/{kanban-definition-HUTT4EX6-CxOWhFpB.js → kanban-definition-HUTT4EX6-CXKwXGxe.js} +1 -1
  68. package/web-dist/assets/{line-BGqbhtvK.js → line-BHqhqZTw.js} +1 -1
  69. package/web-dist/assets/{linear-DRvKJ3WJ.js → linear-Xq8ICqCe.js} +1 -1
  70. package/web-dist/assets/{mermaid-parser.core-C5lIBam8.js → mermaid-parser.core-ByagDKoG.js} +3 -3
  71. package/web-dist/assets/{mermaid.core-ChLUqNEE.js → mermaid.core-CEwbkqrb.js} +3 -3
  72. package/web-dist/assets/{mindmap-definition-LN4V7U3C-BfPv_GOf.js → mindmap-definition-LN4V7U3C-C3S3nEo5.js} +1 -1
  73. package/web-dist/assets/{packet-7NZHBO7P-CH3B2i7_.js → packet-7NZHBO7P-BjcgqWf7.js} +1 -1
  74. package/web-dist/assets/{pegDiagram-2B236MQR-DLuCHUaK.js → pegDiagram-2B236MQR-Due7wPzY.js} +1 -1
  75. package/web-dist/assets/{pie-RZYD4A2V-C-hDlp0h.js → pie-RZYD4A2V-C1X-Fm2K.js} +1 -1
  76. package/web-dist/assets/{pieDiagram-ENE6RG2P-CKVu3PTC.js → pieDiagram-ENE6RG2P-CbKS5jFv.js} +1 -1
  77. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL--tZ3JdyA.js → quadrantDiagram-ABIIQ3AL-CVF1CNNO.js} +1 -1
  78. package/web-dist/assets/{radar-I7S5WNFK-C10EMwWx.js → radar-I7S5WNFK-Co7Otr5p.js} +1 -1
  79. package/web-dist/assets/{railroad-3IZDKUUU-BYegvtJS.js → railroad-3IZDKUUU-BTwZqHtN.js} +1 -1
  80. package/web-dist/assets/railroad-abnf-AHOZXSZD-CEkmgARz.js +1 -0
  81. package/web-dist/assets/railroad-ebnf-EBAXGLYW-D2dXzrFd.js +1 -0
  82. package/web-dist/assets/railroad-peg-LSFZ7HO6-yA2XVaxN.js +1 -0
  83. package/web-dist/assets/{railroadDiagram-RFXS5EU6-CfpRdkA8.js → railroadDiagram-RFXS5EU6-DCymlvVU.js} +1 -1
  84. package/web-dist/assets/{requirementDiagram-TGXJPOKE-CUajgDbc.js → requirementDiagram-TGXJPOKE-CEFbAu30.js} +1 -1
  85. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-DRs5oKTx.js → sankeyDiagram-HTMAVEWB-fnX7WrAj.js} +1 -1
  86. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-BTeEqLFC.js → sequenceDiagram-DBY2YBRQ-BUvsAYkQ.js} +1 -1
  87. package/web-dist/assets/{src-Cf1DXZ3M.js → src-V5VjKILh.js} +1 -1
  88. package/web-dist/assets/{stateDiagram-2N3HPSRC-BPcqMj-B.js → stateDiagram-2N3HPSRC-C9LJKbHM.js} +1 -1
  89. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-Bm1cPGFT.js +1 -0
  90. package/web-dist/assets/{swimlanes-5IMT3BWC-CJTd58TJ.js → swimlanes-5IMT3BWC-aq9B5aBs.js} +1 -1
  91. package/web-dist/assets/swimlanesDiagram-G3AALYLV-DR6Yx_Ic.js +8 -0
  92. package/web-dist/assets/{timeline-definition-FHXFAJF6-CqbaBVpe.js → timeline-definition-FHXFAJF6-DhJ9Jf4f.js} +1 -1
  93. package/web-dist/assets/{treeView-QDETBFTQ-B2OQ8r59.js → treeView-QDETBFTQ-D42FrEH4.js} +1 -1
  94. package/web-dist/assets/{treemap-6X3UGDF4-DGpAdWTA.js → treemap-6X3UGDF4-BV_9JyG6.js} +1 -1
  95. package/web-dist/assets/{vennDiagram-L72KCM5P-BAS_eWHm.js → vennDiagram-L72KCM5P-BkwHzxsN.js} +1 -1
  96. package/web-dist/assets/{wardley-OPB4EBWU-DpNHIH3W.js → wardley-OPB4EBWU-fwm52ei3.js} +1 -1
  97. package/web-dist/assets/{wardleyDiagram-EHGQE667-2N7X1vj8.js → wardleyDiagram-EHGQE667-D_UqvgcE.js} +1 -1
  98. package/web-dist/assets/{xychartDiagram-FW5EYKEG-C8mfLCei.js → xychartDiagram-FW5EYKEG-tKdmcTfS.js} +1 -1
  99. package/web-dist/index.html +2 -2
  100. package/web-dist/assets/architecture-TIHT7OUA-CXyjbDft.js +0 -1
  101. package/web-dist/assets/channel-uFMfT294.js +0 -1
  102. package/web-dist/assets/classDiagram-OUVF2IWQ-D1koMbqS.js +0 -1
  103. package/web-dist/assets/classDiagram-v2-EOCWNBFH-D1koMbqS.js +0 -1
  104. package/web-dist/assets/eventmodeling-45OFAUF4-tWFB9ALb.js +0 -1
  105. package/web-dist/assets/flowDiagram-23GEKE2U-Dz_Opd7B.js +0 -1
  106. package/web-dist/assets/index-BwC7xvWu.js +0 -336
  107. package/web-dist/assets/index-CuXKWysP.css +0 -2
  108. package/web-dist/assets/railroad-abnf-AHOZXSZD-DLmknJDm.js +0 -1
  109. package/web-dist/assets/railroad-ebnf-EBAXGLYW-BoZF0VpA.js +0 -1
  110. package/web-dist/assets/railroad-peg-LSFZ7HO6-Dib7YVqg.js +0 -1
  111. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DiV9dOER.js +0 -1
  112. package/web-dist/assets/swimlanesDiagram-G3AALYLV-BDeobZmn.js +0 -8
@@ -2,8 +2,9 @@ import { createRequire as __frizzCreateRequire } from "node:module"; const requi
2
2
 
3
3
  // packages/server/src/backend/claude-agent-broker.ts
4
4
  import net from "node:net";
5
- import { readFileSync as readFileSync6, realpathSync as realpathSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
6
- import { join as join8 } from "node:path";
5
+ import { readFileSync as readFileSync8, realpathSync as realpathSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
6
+ import { homedir as homedir3 } from "node:os";
7
+ import { join as join11 } from "node:path";
7
8
  import { randomUUID } from "node:crypto";
8
9
  import { fileURLToPath } from "node:url";
9
10
 
@@ -26081,11 +26082,6 @@ var LEGACY_DIR_NAME = ".frizz";
26081
26082
  function legacyFrizzRoot(home = homedir()) {
26082
26083
  return join2(home, LEGACY_DIR_NAME);
26083
26084
  }
26084
- function isLegacyStateRoot(root, exists) {
26085
- if (!exists(root)) return false;
26086
- if (!exists(join2(root, ".id")) && !exists(join2(root, ".gitignore"))) return true;
26087
- return exists(join2(root, "projects")) || exists(join2(root, "registry.json"));
26088
- }
26089
26085
  function xdg(env, name) {
26090
26086
  const value = env[name];
26091
26087
  return value && (value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value)) ? value : void 0;
@@ -26128,7 +26124,7 @@ function frizzPaths(options = {}) {
26128
26124
  const home = options.home ?? homedir();
26129
26125
  const exists = options.exists ?? existsSync2;
26130
26126
  const legacyRoot = legacyFrizzRoot(home);
26131
- if (isLegacyStateRoot(legacyRoot, exists)) {
26127
+ if (exists(legacyRoot)) {
26132
26128
  return { data: legacyRoot, state: legacyRoot, cache: legacyRoot, legacy: true };
26133
26129
  }
26134
26130
  const explicit = {
@@ -26505,7 +26501,7 @@ var BoundedAsyncQueue = class {
26505
26501
  if (value !== void 0) return Promise.resolve({ done: false, value });
26506
26502
  if (this.failure) return Promise.reject(this.failure);
26507
26503
  if (this.ended) return Promise.resolve({ done: true, value: void 0 });
26508
- return new Promise((resolve3, reject) => this.waiters.push({ resolve: resolve3, reject }));
26504
+ return new Promise((resolve4, reject) => this.waiters.push({ resolve: resolve4, reject }));
26509
26505
  }
26510
26506
  [Symbol.asyncIterator]() {
26511
26507
  return this;
@@ -26587,6 +26583,7 @@ var RealClaudeQueryHandle = class {
26587
26583
  sdkQuery;
26588
26584
  input;
26589
26585
  diagnostic;
26586
+ rateLimit;
26590
26587
  lifecycleAbort;
26591
26588
  // id → the main-thread turn count at the moment it was sent. A Map rather than a Set plus a
26592
26589
  // parallel order array because insertion order IS send order, which is all the oldest-first
@@ -26596,15 +26593,16 @@ var RealClaudeQueryHandle = class {
26596
26593
  mainThreadResults = 0;
26597
26594
  providerProgressCovered = false;
26598
26595
  closePromise;
26599
- constructor(sdkQuery, input, sessionId, lifecycleAbort, redactor, diagnostic) {
26596
+ constructor(sdkQuery, input, sessionId, lifecycleAbort, redactor, diagnostic, rateLimit) {
26600
26597
  this.sdkQuery = sdkQuery;
26601
26598
  this.input = input;
26602
26599
  this.sessionId = sessionId;
26603
26600
  this.lifecycleAbort = lifecycleAbort;
26604
26601
  this.redactor = redactor;
26605
26602
  this.diagnostic = diagnostic;
26606
- this.readyPromise = new Promise((resolve3, reject) => {
26607
- this.resolveReady = resolve3;
26603
+ this.rateLimit = rateLimit;
26604
+ this.readyPromise = new Promise((resolve4, reject) => {
26605
+ this.resolveReady = resolve4;
26608
26606
  this.rejectReady = reject;
26609
26607
  });
26610
26608
  void this.readyPromise.catch(() => void 0);
@@ -26836,6 +26834,9 @@ var RealClaudeQueryHandle = class {
26836
26834
  async pump() {
26837
26835
  try {
26838
26836
  for await (const raw of this.sdkQuery) {
26837
+ if (this.rateLimit && raw.type === "rate_limit_event") {
26838
+ this.rateLimit(raw.rate_limit_info);
26839
+ }
26839
26840
  let event;
26840
26841
  try {
26841
26842
  event = mapSdkMessage(raw);
@@ -26972,6 +26973,7 @@ function startClaudeQuery(executablePath, options) {
26972
26973
  const environment = buildEnvironment(options.env);
26973
26974
  const redact = createClaudeDiagnosticRedactor(environment);
26974
26975
  const diagnostic = guardDiagnosticCallback(options.onDiagnostic);
26976
+ const rateLimit = guardObserverCallback(options.onRateLimit);
26975
26977
  const permissionMode = validatePermissionMode(options.permissionMode ?? "default");
26976
26978
  const lifecycleAbort = new AbortController();
26977
26979
  const permissionRequests = new BoundedIdempotencyCache(MAX_PERMISSION_REQUESTS, "Claude permission request cache");
@@ -27085,7 +27087,7 @@ function startClaudeQuery(executablePath, options) {
27085
27087
  }
27086
27088
  }
27087
27089
  });
27088
- const handle = new RealClaudeQueryHandle(raw, input, sessionId, lifecycleAbort, redact, diagnostic);
27090
+ const handle = new RealClaudeQueryHandle(raw, input, sessionId, lifecycleAbort, redact, diagnostic, rateLimit);
27089
27091
  if (mcpConfigFile) {
27090
27092
  const drop = () => {
27091
27093
  try {
@@ -27778,13 +27780,13 @@ function canonicalFingerprint(value) {
27778
27780
  }
27779
27781
  function abortableCallback(promise, signal, label) {
27780
27782
  if (signal.aborted) return Promise.reject(new ClaudeAgentSdkProtocolError(`${label} aborted`));
27781
- return new Promise((resolve3, reject) => {
27783
+ return new Promise((resolve4, reject) => {
27782
27784
  const abort = () => reject(new ClaudeAgentSdkProtocolError(`${label} aborted`));
27783
27785
  signal.addEventListener("abort", abort, { once: true });
27784
27786
  promise.then(
27785
27787
  (value) => {
27786
27788
  signal.removeEventListener("abort", abort);
27787
- resolve3(value);
27789
+ resolve4(value);
27788
27790
  },
27789
27791
  (error) => {
27790
27792
  signal.removeEventListener("abort", abort);
@@ -27802,6 +27804,15 @@ function guardDiagnosticCallback(callback) {
27802
27804
  }
27803
27805
  };
27804
27806
  }
27807
+ function guardObserverCallback(callback) {
27808
+ if (!callback) return void 0;
27809
+ return (value) => {
27810
+ try {
27811
+ callback(value);
27812
+ } catch {
27813
+ }
27814
+ };
27815
+ }
27805
27816
  function validateExecutablePath(value) {
27806
27817
  const path = validateAbsolutePath(value, "executablePath");
27807
27818
  try {
@@ -28237,14 +28248,14 @@ data: ${JSON.stringify(message)}
28237
28248
  }
28238
28249
  internalRequest(method, params) {
28239
28250
  const id2 = `frizz-lazy-${++this.nextInternalId}`;
28240
- return new Promise((resolve3) => {
28241
- this.internal.set(id2, resolve3);
28251
+ return new Promise((resolve4) => {
28252
+ this.internal.set(id2, resolve4);
28242
28253
  this.send({ jsonrpc: "2.0", id: id2, method, ...params === void 0 ? {} : { params } });
28243
28254
  });
28244
28255
  }
28245
28256
  forward(message) {
28246
- return new Promise((resolve3) => {
28247
- this.forwarded.set(JSON.stringify(message.id), resolve3);
28257
+ return new Promise((resolve4) => {
28258
+ this.forwarded.set(JSON.stringify(message.id), resolve4);
28248
28259
  this.send(message);
28249
28260
  });
28250
28261
  }
@@ -28280,18 +28291,18 @@ data: ${JSON.stringify(message)}
28280
28291
  const child = this.child;
28281
28292
  if (!child) return;
28282
28293
  this.child = void 0;
28283
- await new Promise((resolve3) => {
28294
+ await new Promise((resolve4) => {
28284
28295
  const timer = setTimeout(() => {
28285
28296
  try {
28286
28297
  child.kill("SIGKILL");
28287
28298
  } catch {
28288
28299
  }
28289
28300
  ;
28290
- resolve3();
28301
+ resolve4();
28291
28302
  }, 2e3);
28292
28303
  child.once("exit", () => {
28293
28304
  clearTimeout(timer);
28294
- resolve3();
28305
+ resolve4();
28295
28306
  });
28296
28307
  try {
28297
28308
  child.stdin?.end();
@@ -28305,7 +28316,7 @@ data: ${JSON.stringify(message)}
28305
28316
  }
28306
28317
  };
28307
28318
  function readBody(request) {
28308
- return new Promise((resolve3, reject) => {
28319
+ return new Promise((resolve4, reject) => {
28309
28320
  let size = 0;
28310
28321
  const chunks = [];
28311
28322
  request.on("data", (chunk) => {
@@ -28317,7 +28328,7 @@ function readBody(request) {
28317
28328
  }
28318
28329
  chunks.push(chunk);
28319
28330
  });
28320
- request.on("end", () => resolve3(Buffer.concat(chunks).toString("utf8")));
28331
+ request.on("end", () => resolve4(Buffer.concat(chunks).toString("utf8")));
28321
28332
  request.on("error", reject);
28322
28333
  });
28323
28334
  }
@@ -28368,13 +28379,13 @@ function startLazyMcpHost(options) {
28368
28379
  })();
28369
28380
  });
28370
28381
  httpServer.requestTimeout = 0;
28371
- return new Promise((resolve3, reject) => {
28382
+ return new Promise((resolve4, reject) => {
28372
28383
  httpServer.once("error", reject);
28373
28384
  httpServer.listen(0, "127.0.0.1", () => {
28374
28385
  httpServer.off("error", reject);
28375
28386
  const address = httpServer.address();
28376
28387
  const port = typeof address === "object" && address ? address.port : 0;
28377
- resolve3({
28388
+ resolve4({
28378
28389
  port,
28379
28390
  mount(stdio, context) {
28380
28391
  mkdirSync4(options.cacheDir, { recursive: true, mode: 448 });
@@ -28401,7 +28412,6 @@ function startLazyMcpHost(options) {
28401
28412
  // packages/server/src/backend/types.ts
28402
28413
  var CLAUDE_WORKER_ENV = {
28403
28414
  CLAUDE_CODE_TOTAL_TOKENS_REMINDER: "infinite",
28404
- BASH_DEFAULT_TIMEOUT_MS: "60000",
28405
28415
  BASH_MAX_TIMEOUT_MS: String(24 * 60 * 60 * 1e3)
28406
28416
  };
28407
28417
  var CLAUDE_AUTO_COMPACT_WINDOW_ENV = "CLAUDE_CODE_AUTO_COMPACT_WINDOW";
@@ -28466,9 +28476,292 @@ function createClaudeBrokerExitWriter(path, meta, now = () => /* @__PURE__ */ ne
28466
28476
  };
28467
28477
  }
28468
28478
 
28479
+ // packages/server/src/backend/claude-plugin-sync.ts
28480
+ import { createHash as createHash4 } from "node:crypto";
28481
+ import { readFileSync as readFileSync7, readdirSync as readdirSync4, statSync as statSync5 } from "node:fs";
28482
+ import { join as join9 } from "node:path";
28483
+
28484
+ // packages/server/src/stable-plugin-path.ts
28485
+ import { createHash as createHash3 } from "node:crypto";
28486
+ import { cpSync, lstatSync as lstatSync3, mkdirSync as mkdirSync6, readFileSync as readFileSync6, readdirSync as readdirSync3, readlinkSync as readlinkSync2, realpathSync as realpathSync2, renameSync as renameSync4, rmSync as rmSync4, statSync as statSync4, symlinkSync } from "node:fs";
28487
+ import { dirname as dirname4, isAbsolute as isAbsolute4, join as join8, resolve as resolve3 } from "node:path";
28488
+ var LINK_TYPE = process.platform === "win32" ? "junction" : void 0;
28489
+ function pluginFiles(root) {
28490
+ const files = [];
28491
+ const walk = (dir, prefix) => {
28492
+ for (const name of readdirSync3(dir).sort()) {
28493
+ const rel = prefix ? `${prefix}/${name}` : name;
28494
+ if (statSync4(join8(dir, name)).isDirectory()) walk(join8(dir, name), rel);
28495
+ else files.push(rel);
28496
+ }
28497
+ };
28498
+ walk(root, "");
28499
+ return files;
28500
+ }
28501
+ function pluginFingerprint(dir) {
28502
+ try {
28503
+ const root = realpathSync2(dir);
28504
+ const hash = createHash3("sha1").update(root);
28505
+ for (const rel of pluginFiles(root)) {
28506
+ const stat = statSync4(join8(root, rel));
28507
+ hash.update(`\0${rel}\0${stat.size}\0${stat.mtimeMs}`);
28508
+ }
28509
+ return hash.digest("hex");
28510
+ } catch {
28511
+ return void 0;
28512
+ }
28513
+ }
28514
+
28515
+ // packages/server/src/backend/claude-plugin-sync.ts
28516
+ function claudePluginSyncEnabled(env = process.env) {
28517
+ return env.FRIZZ_PLUGIN_SYNC_OFF !== "1";
28518
+ }
28519
+ var RELOAD_DEADLINE_MS = 8e3;
28520
+ var RELOAD_ATTEMPTS = 2;
28521
+ var ClosureUnreadable = class extends Error {
28522
+ };
28523
+ function claudeDirEntries(root, entries) {
28524
+ const stamp = (path) => {
28525
+ try {
28526
+ const stat = statSync5(path);
28527
+ if (stat.isFile()) entries.push(`${path}\0${stat.size}\0${stat.mtimeMs}`);
28528
+ } catch {
28529
+ }
28530
+ };
28531
+ const list = (dir) => {
28532
+ try {
28533
+ return readdirSync4(dir).sort();
28534
+ } catch {
28535
+ return [];
28536
+ }
28537
+ };
28538
+ for (const name of list(join9(root, "skills"))) stamp(join9(root, "skills", name, "SKILL.md"));
28539
+ const markdownUnder = (dir, depth) => {
28540
+ for (const name of list(dir)) {
28541
+ const path = join9(dir, name);
28542
+ if (name.endsWith(".md")) stamp(path);
28543
+ else if (depth < 4) markdownUnder(path, depth + 1);
28544
+ }
28545
+ };
28546
+ markdownUnder(join9(root, "agents"), 0);
28547
+ markdownUnder(join9(root, "commands"), 0);
28548
+ for (const file of ["settings.json", "settings.local.json"]) {
28549
+ let raw;
28550
+ try {
28551
+ raw = readFileSync7(join9(root, file), "utf8");
28552
+ } catch {
28553
+ continue;
28554
+ }
28555
+ let enabled;
28556
+ try {
28557
+ enabled = JSON.parse(raw)?.enabledPlugins;
28558
+ } catch {
28559
+ throw new ClosureUnreadable(file);
28560
+ }
28561
+ entries.push(`${join9(root, file)}\0${JSON.stringify(enabled ?? null)}`);
28562
+ }
28563
+ stamp(join9(root, "plugins", "installed_plugins.json"));
28564
+ }
28565
+ function claudeClosureFingerprint(closure) {
28566
+ const plugin = closure.pluginDir ? pluginFingerprint(closure.pluginDir) : "";
28567
+ if (plugin === void 0) return void 0;
28568
+ const entries = [plugin];
28569
+ try {
28570
+ claudeDirEntries(join9(closure.projectDir, ".claude"), entries);
28571
+ claudeDirEntries(closure.configDir, entries);
28572
+ } catch {
28573
+ return void 0;
28574
+ }
28575
+ return createHash4("sha1").update(entries.join("\n")).digest("hex");
28576
+ }
28577
+ function createClaudePluginSync(deps) {
28578
+ let loaded = deps.fingerprint();
28579
+ let busy = false;
28580
+ let inFlight = null;
28581
+ let failed;
28582
+ const say = (message) => {
28583
+ try {
28584
+ deps.log(message);
28585
+ } catch {
28586
+ }
28587
+ };
28588
+ const reloadWithinDeadline = () => new Promise((resolve4, reject) => {
28589
+ const timer = setTimeout(() => reject(new Error("the session did not answer in time")), deps.deadlineMs ?? RELOAD_DEADLINE_MS);
28590
+ timer.unref?.();
28591
+ deps.reload().then(
28592
+ (result) => {
28593
+ clearTimeout(timer);
28594
+ resolve4(result);
28595
+ },
28596
+ (error) => {
28597
+ clearTimeout(timer);
28598
+ reject(error);
28599
+ }
28600
+ );
28601
+ });
28602
+ const check = () => {
28603
+ if (inFlight) return;
28604
+ const current = deps.fingerprint();
28605
+ if (current === void 0 || current === loaded) return;
28606
+ if (failed?.fingerprint === current && failed.attempts >= RELOAD_ATTEMPTS) return;
28607
+ const attempt = reloadWithinDeadline().then(
28608
+ (result) => {
28609
+ loaded = current;
28610
+ failed = void 0;
28611
+ say(`plugin closure changed on disk; reloaded in place${result.errorCount ? ` with ${result.errorCount} load error(s)` : ""}`);
28612
+ },
28613
+ (error) => {
28614
+ failed = { fingerprint: current, attempts: failed?.fingerprint === current ? failed.attempts + 1 : 1 };
28615
+ say(`plugin closure changed on disk but the reload failed (attempt ${failed.attempts}/${RELOAD_ATTEMPTS}): ${error instanceof Error ? error.message : String(error)}`);
28616
+ }
28617
+ ).catch(() => void 0).finally(() => {
28618
+ if (inFlight === attempt) inFlight = null;
28619
+ });
28620
+ inFlight = attempt;
28621
+ };
28622
+ return {
28623
+ beforeInput(startsTurn) {
28624
+ if (startsTurn) {
28625
+ if (!busy) check();
28626
+ busy = true;
28627
+ }
28628
+ return inFlight;
28629
+ },
28630
+ beforeRead() {
28631
+ if (!busy) check();
28632
+ return inFlight;
28633
+ },
28634
+ turnActive() {
28635
+ busy = true;
28636
+ },
28637
+ turnEnded() {
28638
+ busy = false;
28639
+ check();
28640
+ }
28641
+ };
28642
+ }
28643
+
28644
+ // packages/server/src/backend/claude-quota-observed.ts
28645
+ import { createHash as createHash5 } from "node:crypto";
28646
+ import { mkdir, readFile, rename, rm as rm2, writeFile } from "node:fs/promises";
28647
+ import { join as join10 } from "node:path";
28648
+ var WINDOW_IDENTITY = {
28649
+ five_hour: ["5h", "5h"],
28650
+ seven_day: ["weekly", "Weekly"],
28651
+ seven_day_opus: ["weekly-opus", "Opus wk"],
28652
+ seven_day_sonnet: ["weekly-sonnet", "Sonnet wk"]
28653
+ };
28654
+ var OBSERVED_MAX_AGE_MS = 24 * 60 * 6e4;
28655
+ var REWRITE_INTERVAL_MS = 3e4;
28656
+ function finite(value) {
28657
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
28658
+ }
28659
+ function toWindow(name, utilization, resetsAt) {
28660
+ const identity = WINDOW_IDENTITY[name];
28661
+ const fraction = finite(utilization);
28662
+ if (!identity || fraction === void 0 || fraction < 0) return void 0;
28663
+ const resets = finite(resetsAt);
28664
+ return {
28665
+ key: identity[0],
28666
+ label: identity[1],
28667
+ // 0..1 → the endpoint's 0..100, without the binary-float tail (0.65 * 100 is 65.00000000000001).
28668
+ usedPercent: Math.round(fraction * 1e4) / 100,
28669
+ ...resets !== void 0 && resets > 0 ? { resetsAt: Math.round(resets) } : {}
28670
+ };
28671
+ }
28672
+ function windowsFromRateLimitInfo(info) {
28673
+ if (!info || typeof info !== "object") return [];
28674
+ const raw = info;
28675
+ const windows = /* @__PURE__ */ new Map();
28676
+ if (raw.unifiedWindows && typeof raw.unifiedWindows === "object") {
28677
+ for (const [name, value] of Object.entries(raw.unifiedWindows)) {
28678
+ if (!value || typeof value !== "object") continue;
28679
+ const w = value;
28680
+ const window = toWindow(name, w.utilization, w.resetsAt);
28681
+ if (window) windows.set(window.key, window);
28682
+ }
28683
+ }
28684
+ if (typeof raw.rateLimitType === "string") {
28685
+ const window = toWindow(raw.rateLimitType, raw.utilization, raw.resetsAt);
28686
+ if (window && !windows.has(window.key)) windows.set(window.key, window);
28687
+ const identity = WINDOW_IDENTITY[raw.rateLimitType];
28688
+ if (raw.status === "rejected" && identity) {
28689
+ const standing = windows.get(identity[0]);
28690
+ const resets = finite(raw.resetsAt);
28691
+ windows.set(identity[0], {
28692
+ key: identity[0],
28693
+ label: identity[1],
28694
+ usedPercent: Math.max(100, standing?.usedPercent ?? 0),
28695
+ ...standing?.resetsAt !== void 0 ? { resetsAt: standing.resetsAt } : resets !== void 0 && resets > 0 ? { resetsAt: Math.round(resets) } : {}
28696
+ });
28697
+ }
28698
+ }
28699
+ return [...windows.values()];
28700
+ }
28701
+ function observedQuotaPath(cacheDir, configDir) {
28702
+ const profile = createHash5("sha256").update(configDir).digest("hex").slice(0, 12);
28703
+ return join10(cacheDir, `claude-observed-${profile}.json`);
28704
+ }
28705
+ function live(window, now) {
28706
+ if (now - window.at >= OBSERVED_MAX_AGE_MS) return false;
28707
+ return window.resetsAt === void 0 || window.resetsAt * 1e3 > now;
28708
+ }
28709
+ async function readObservedClaudeQuota(cacheDir, configDir, now = Date.now()) {
28710
+ let parsed;
28711
+ try {
28712
+ parsed = JSON.parse(await readFile(observedQuotaPath(cacheDir, configDir), "utf8"));
28713
+ } catch {
28714
+ return void 0;
28715
+ }
28716
+ const list = parsed?.windows;
28717
+ if (!Array.isArray(list)) return void 0;
28718
+ const windows = [];
28719
+ for (const entry of list) {
28720
+ if (!entry || typeof entry !== "object") continue;
28721
+ const w = entry;
28722
+ const at2 = finite(w.at);
28723
+ const usedPercent = finite(w.usedPercent);
28724
+ const resetsAt = finite(w.resetsAt);
28725
+ if (typeof w.key !== "string" || typeof w.label !== "string" || at2 === void 0 || usedPercent === void 0) continue;
28726
+ const window = { key: w.key, label: w.label, usedPercent, at: at2, ...resetsAt === void 0 ? {} : { resetsAt } };
28727
+ if (live(window, now)) windows.push(window);
28728
+ }
28729
+ if (windows.length === 0) return void 0;
28730
+ return { at: Math.max(...windows.map((w) => w.at)), windows };
28731
+ }
28732
+ var lastWritten = /* @__PURE__ */ new Map();
28733
+ async function recordObservedClaudeQuota(info, where) {
28734
+ try {
28735
+ const now = where.now ?? Date.now();
28736
+ const reported = windowsFromRateLimitInfo(info);
28737
+ if (reported.length === 0) return false;
28738
+ const path = observedQuotaPath(where.cacheDir, where.configDir);
28739
+ const signature = JSON.stringify(reported);
28740
+ const last = lastWritten.get(path);
28741
+ if (last && last.signature === signature && now - last.at < REWRITE_INTERVAL_MS) return false;
28742
+ const standing = await readObservedClaudeQuota(where.cacheDir, where.configDir, now);
28743
+ const windows = new Map((standing?.windows ?? []).map((w) => [w.key, w]));
28744
+ for (const window of reported) windows.set(window.key, { ...window, at: now });
28745
+ await mkdir(where.cacheDir, { recursive: true, mode: 448 });
28746
+ const tmp = `${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
28747
+ try {
28748
+ await writeFile(tmp, JSON.stringify({ at: now, windows: [...windows.values()] }), { mode: 384 });
28749
+ await rename(tmp, path);
28750
+ } finally {
28751
+ await rm2(tmp, { force: true }).catch(() => {
28752
+ });
28753
+ }
28754
+ lastWritten.set(path, { at: now, signature });
28755
+ return true;
28756
+ } catch {
28757
+ return false;
28758
+ }
28759
+ }
28760
+
28469
28761
  // packages/server/src/backend/claude-agent-broker.ts
28470
28762
  var BROKER_CAPABILITIES = [CLAUDE_BROKER_CAPABILITY_SUBAGENT_STEER, CLAUDE_BROKER_CAPABILITY_CANCEL_INPUT, CLAUDE_BROKER_CAPABILITY_STOP_TASK, CLAUDE_BROKER_CAPABILITY_RELOAD_PLUGINS, CLAUDE_BROKER_CAPABILITY_RENAME, CLAUDE_BROKER_CAPABILITY_LIST_SKILLS, CLAUDE_BROKER_CAPABILITY_INPUT_ACK];
28471
28763
  var IDLE_EXIT_MS = 6 * 60 * 60 * 1e3;
28764
+ var PERMISSION_SHOW_HOLD_MS = 250;
28472
28765
  var REACHABILITY_CHECK_MS = 3e4;
28473
28766
  var REACHABILITY_STRIKES = 2;
28474
28767
  var EVENT_ERROR_TOLERANCE = 5;
@@ -28511,6 +28804,17 @@ function runClaudeBroker(config, options = {}) {
28511
28804
  const releaseRuntimeLease = leaseRuntime(config.executablePath, "claude-broker");
28512
28805
  const factory = createClaudeQueryFactory({ enabled: true, executablePath: config.executablePath });
28513
28806
  const env = { ...inheritWorkerEnvironment(config.env), ...config.workerEnv ?? {} };
28807
+ const closure = {
28808
+ pluginDir: config.pluginDir,
28809
+ projectDir: config.cwd,
28810
+ // Where claude itself will look, from the environment it is about to be started with.
28811
+ configDir: env.CLAUDE_CONFIG_DIR?.trim() || join11(env.HOME || homedir3(), ".claude")
28812
+ };
28813
+ const pluginSync = claudePluginSyncEnabled() ? createClaudePluginSync({
28814
+ fingerprint: () => claudeClosureFingerprint(closure),
28815
+ reload: () => handle.reloadPlugins(),
28816
+ log: (message) => writeDiagnostic?.({ kind: "stderr", message: `[plugin-sync] ${message}`, truncated: false })
28817
+ }) : void 0;
28514
28818
  const handle = factory.start({
28515
28819
  cwd: config.cwd,
28516
28820
  session: config.resume ? { kind: "resume", sessionId: config.sessionId } : { kind: "new", sessionId: config.sessionId },
@@ -28549,20 +28853,40 @@ function runClaudeBroker(config, options = {}) {
28549
28853
  // and unwinds the tool call (see retirePendingFor in the bridge), so a parked turn is still steerable.
28550
28854
  canUseTool: async (request, context) => {
28551
28855
  const requestId = `perm-${++permSeq}`;
28552
- return await new Promise((resolve3) => {
28856
+ return await new Promise((resolve4) => {
28553
28857
  let settled = false;
28858
+ let showTimer;
28859
+ const entry = { request, shown: false, resolve: (decision) => settle(decision) };
28554
28860
  const settle = (decision) => {
28555
28861
  if (settled) return;
28556
28862
  settled = true;
28863
+ clearTimeout(showTimer);
28557
28864
  pendingPermissions.delete(requestId);
28558
- resolve3(decision);
28865
+ resolve4(decision);
28866
+ };
28867
+ const withdraw = () => {
28868
+ const wasShown = entry.shown;
28869
+ settle({ behavior: "deny", message: "The turn was interrupted before this was answered." });
28870
+ if (wasShown && client) write(client, { t: "permission-withdrawn", requestId });
28559
28871
  };
28560
- pendingPermissions.set(requestId, { request, resolve: settle });
28561
- if (context.signal.aborted) settle({ behavior: "deny", message: "The turn was interrupted before this was answered." });
28562
- else context.signal.addEventListener("abort", () => settle({ behavior: "deny", message: "The turn was interrupted before this was answered." }), { once: true });
28563
- if (!settled && client) write(client, { t: "permission-request", requestId, request });
28872
+ pendingPermissions.set(requestId, entry);
28873
+ if (context.signal.aborted) withdraw();
28874
+ else context.signal.addEventListener("abort", withdraw, { once: true });
28875
+ if (!settled) {
28876
+ showTimer = setTimeout(() => {
28877
+ if (settled || entry.shown || !client) return;
28878
+ entry.shown = true;
28879
+ write(client, { t: "permission-request", requestId, request });
28880
+ }, PERMISSION_SHOW_HOLD_MS);
28881
+ }
28564
28882
  });
28565
28883
  },
28884
+ // The account's plan windows, as every API response reports them to this session. Written by THIS
28885
+ // process because it is the one that sees the stream and it outlives the Frizz server; the server
28886
+ // only reads the file (claude-quota-observed.ts). Fire-and-forget: the recorder never rejects.
28887
+ onRateLimit: (info) => {
28888
+ void recordObservedClaudeQuota(info, { cacheDir: join11(frizzRoots().cache, "quota-cache"), configDir: closure.configDir });
28889
+ },
28566
28890
  onDiagnostic: (diagnostic) => {
28567
28891
  writeDiagnostic?.(diagnostic);
28568
28892
  if (client) write(client, { t: "diagnostic", diagnostic });
@@ -28598,6 +28922,8 @@ function runClaudeBroker(config, options = {}) {
28598
28922
  consecutiveErrors = 0;
28599
28923
  if (next.done) return { reason: "session-stream-ended" };
28600
28924
  emitEvent(next.value);
28925
+ if (next.value.kind === "result") pluginSync?.turnEnded();
28926
+ else if (next.value.kind === "assistant" || next.value.kind === "user") pluginSync?.turnActive();
28601
28927
  }
28602
28928
  })().then(
28603
28929
  (end) => shutdown(0, end.reason, end.detail),
@@ -28612,7 +28938,10 @@ function runClaudeBroker(config, options = {}) {
28612
28938
  client = sock;
28613
28939
  clearTimeout(idleTimer);
28614
28940
  write(sock, { t: "hello", sessionId: handle.sessionId, generation });
28615
- for (const [requestId, { request }] of pendingPermissions) write(sock, { t: "permission-request", requestId, request });
28941
+ for (const [requestId, entry] of pendingPermissions) {
28942
+ entry.shown = true;
28943
+ write(sock, { t: "permission-request", requestId, request: entry.request });
28944
+ }
28616
28945
  while (eventBacklog.length) sock.write(eventBacklog.shift());
28617
28946
  eventBacklogBytes = 0;
28618
28947
  let buf = "";
@@ -28636,7 +28965,7 @@ function runClaudeBroker(config, options = {}) {
28636
28965
  message: `input received: id=${message?.id ?? "?"} chars=${typeof message?.text === "string" ? message.text.length : 0}${message?.parentToolUseId ? ` addressed=${message.parentToolUseId}` : ""}`,
28637
28966
  truncated: false
28638
28967
  });
28639
- void handle.send(message).then(() => {
28968
+ const forward = () => void handle.send(message).then(() => {
28640
28969
  if (requestId) write(sock, { t: "input-result", requestId });
28641
28970
  }, (error) => {
28642
28971
  const detail = error instanceof Error ? error.message : String(error);
@@ -28646,6 +28975,9 @@ function runClaudeBroker(config, options = {}) {
28646
28975
  writeDiagnostic?.(diagnostic);
28647
28976
  if (client) write(client, { t: "diagnostic", diagnostic });
28648
28977
  });
28978
+ const reloading = pluginSync?.beforeInput(!message?.parentToolUseId);
28979
+ if (reloading) void reloading.then(forward);
28980
+ else forward();
28649
28981
  seedSessionTitle(message);
28650
28982
  } else if (msg.t === "permission") {
28651
28983
  const e13 = pendingPermissions.get(msg.requestId);
@@ -28684,7 +29016,7 @@ function runClaudeBroker(config, options = {}) {
28684
29016
  );
28685
29017
  } else if (msg.t === "list-skills") {
28686
29018
  const requestId = msg.requestId;
28687
- void handle.listSkills().then(
29019
+ void (pluginSync?.beforeRead() ?? Promise.resolve()).then(() => handle.listSkills()).then(
28688
29020
  (skills) => write(sock, { t: "skills-result", requestId, skills }),
28689
29021
  (error) => write(sock, { t: "skills-result", requestId, error: error instanceof Error ? error.message : String(error) })
28690
29022
  );
@@ -28705,7 +29037,7 @@ function runClaudeBroker(config, options = {}) {
28705
29037
  const recordOwner = () => {
28706
29038
  if (!config.recordPath) return null;
28707
29039
  try {
28708
- return JSON.parse(readFileSync6(config.recordPath, "utf8")).daemonPid;
29040
+ return JSON.parse(readFileSync8(config.recordPath, "utf8")).daemonPid;
28709
29041
  } catch {
28710
29042
  return null;
28711
29043
  }
@@ -28800,7 +29132,7 @@ function startedAsProcessEntry() {
28800
29132
  const entry = process.argv[1];
28801
29133
  if (!entry) return false;
28802
29134
  try {
28803
- return realpathSync2(fileURLToPath(import.meta.url)) === realpathSync2(entry);
29135
+ return realpathSync3(fileURLToPath(import.meta.url)) === realpathSync3(entry);
28804
29136
  } catch {
28805
29137
  return false;
28806
29138
  }
@@ -28831,7 +29163,7 @@ ${error.stack ?? ""}`.slice(0, 2e3) : String(error));
28831
29163
  ${reason.stack ?? ""}`.slice(0, 2e3) : String(reason));
28832
29164
  process.exit(1);
28833
29165
  });
28834
- const lazyMcpHost = lazyMcpEnabled() ? startLazyMcpHost({ cacheDir: join8(frizzRoots().data, "mcp-cache") }) : Promise.resolve(void 0);
29166
+ const lazyMcpHost = lazyMcpEnabled() ? startLazyMcpHost({ cacheDir: join11(frizzRoots().data, "mcp-cache") }) : Promise.resolve(void 0);
28835
29167
  void lazyMcpHost.catch(() => void 0).then((host) => {
28836
29168
  running = runClaudeBroker(config, { lazyMcpHost: host });
28837
29169
  });