frizz-server 0.14.7 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/acp-daemon.js +407 -0
  2. package/dist/claude-agent-broker.js +9921 -9449
  3. package/dist/dev-child.js +27814 -2954
  4. package/package.json +1 -1
  5. package/web-dist/assets/{TerminalPane-C8QfcEz3.js → TerminalPane-ChkS6RgS.js} +1 -1
  6. package/web-dist/assets/{abnfDiagram-VRR7QNED-BCkC53yx.js → abnfDiagram-VRR7QNED-CZEP8flc.js} +1 -1
  7. package/web-dist/assets/architecture-TIHT7OUA-D3wgsRS5.js +1 -0
  8. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-qMwCFvWm.js → architectureDiagram-ZJ3FMSHR-BEXzrjrX.js} +1 -1
  9. package/web-dist/assets/{blockDiagram-677ZJIJ3-BeASjZMT.js → blockDiagram-677ZJIJ3-CsJ7cQv7.js} +1 -1
  10. package/web-dist/assets/{c4Diagram-LMCZKHZV-Dp96TZw9.js → c4Diagram-LMCZKHZV-BueHBn6U.js} +1 -1
  11. package/web-dist/assets/channel-DCxTKTH_.js +1 -0
  12. package/web-dist/assets/{chunk-32BRIVSS-Bm1fVFlr.js → chunk-32BRIVSS-DxkYbkXg.js} +1 -1
  13. package/web-dist/assets/{chunk-52WLFC77-k-D5pknU.js → chunk-52WLFC77-B4RUR7JZ.js} +1 -1
  14. package/web-dist/assets/{chunk-C7G6YPKG-iQx0auY-.js → chunk-C7G6YPKG-BLRgwvy4.js} +1 -1
  15. package/web-dist/assets/{chunk-EX3LRPZG-qr5p8Ihh.js → chunk-EX3LRPZG-BAtxNbJC.js} +1 -1
  16. package/web-dist/assets/{chunk-FWX5IMBZ-D6hp_VEs.js → chunk-FWX5IMBZ-BSC2st3T.js} +2 -2
  17. package/web-dist/assets/{chunk-HOUHSVGY-DbkitfR6.js → chunk-HOUHSVGY-0dpVw62j.js} +1 -1
  18. package/web-dist/assets/{chunk-ICXQ74PX-D3847Y05.js → chunk-ICXQ74PX-BZZPAhRZ.js} +1 -1
  19. package/web-dist/assets/{chunk-MOJQB5TN-wn0n-Yrh.js → chunk-MOJQB5TN-ooRCpdkt.js} +1 -1
  20. package/web-dist/assets/{chunk-OGEWGWER-BkPQO6mY.js → chunk-OGEWGWER-Ah-NEmel.js} +1 -1
  21. package/web-dist/assets/{chunk-PUDLZKDR-MUWInS1I.js → chunk-PUDLZKDR-LtHfx3UY.js} +1 -1
  22. package/web-dist/assets/{chunk-Q4XR5HBZ-CiDhI1hu.js → chunk-Q4XR5HBZ-Bd3maQzn.js} +1 -1
  23. package/web-dist/assets/{chunk-V7JOEXUC-DgksbXGN.js → chunk-V7JOEXUC-Baak7qeE.js} +1 -1
  24. package/web-dist/assets/{chunk-VAUOI2AC-CR4oDHoM.js → chunk-VAUOI2AC-DmUeRv29.js} +1 -1
  25. package/web-dist/assets/{chunk-VR4S4FIN-BNMjD3L6.js → chunk-VR4S4FIN-BpgSzLFF.js} +1 -1
  26. package/web-dist/assets/{chunk-WYO6CB5R-CFmvKeg7.js → chunk-WYO6CB5R-PnbowZ3i.js} +1 -1
  27. package/web-dist/assets/{chunk-ZGVPDNZ5-Drlbr5w6.js → chunk-ZGVPDNZ5-D5-YXqW9.js} +1 -1
  28. package/web-dist/assets/classDiagram-OUVF2IWQ-DWiNurp2.js +1 -0
  29. package/web-dist/assets/classDiagram-v2-EOCWNBFH-DWiNurp2.js +1 -0
  30. package/web-dist/assets/{cynefin-VYW2F7L2-C-qM9mS_.js → cynefin-VYW2F7L2-8VyxZobI.js} +1 -1
  31. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-DicsRpK8.js → cynefinDiagram-TSTJHNR4-yFUBmk3y.js} +1 -1
  32. package/web-dist/assets/{dagre-VKFMJZFB-DVf54g5Y.js → dagre-VKFMJZFB-wUCK5Cyw.js} +1 -1
  33. package/web-dist/assets/{diagram-FQU43EPY-Dv6Qm_U2.js → diagram-FQU43EPY-CGzrn40X.js} +1 -1
  34. package/web-dist/assets/{diagram-G47NLZAW-l-UWFRdn.js → diagram-G47NLZAW-DuhlaKXR.js} +1 -1
  35. package/web-dist/assets/{diagram-NH7WQ7WH-ImQLwlxq.js → diagram-NH7WQ7WH-CryBrnG8.js} +1 -1
  36. package/web-dist/assets/{diagram-OA4YK3LP-BHUQjbIJ.js → diagram-OA4YK3LP-C_6Ugdyv.js} +1 -1
  37. package/web-dist/assets/{diagram-WEI45ONY-D0rwMtZZ.js → diagram-WEI45ONY-CklWH5cu.js} +1 -1
  38. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-Dqjvram3.js → ebnfDiagram-CCIWWBDH-DmMOqNaR.js} +1 -1
  39. package/web-dist/assets/{erDiagram-Q63AITRT-zIyf9mHs.js → erDiagram-Q63AITRT-DBpmNhHP.js} +1 -1
  40. package/web-dist/assets/eventmodeling-45OFAUF4-CRp1CVTM.js +1 -0
  41. package/web-dist/assets/flowDiagram-23GEKE2U-lZUkMIKX.js +1 -0
  42. package/web-dist/assets/{ganttDiagram-NO4QXBWP-BDI4vRIv.js → ganttDiagram-NO4QXBWP-BVFPEPZK.js} +1 -1
  43. package/web-dist/assets/{gitGraph-TEB2WS4Q-DpxSpGZQ.js → gitGraph-TEB2WS4Q-CdNkzLjA.js} +1 -1
  44. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-w5gm6T_R.js → gitGraphDiagram-IHSO6WYX-BrIGgHoU.js} +1 -1
  45. package/web-dist/assets/index-D5dploZD.js +321 -0
  46. package/web-dist/assets/index-Wees4UUL.css +1 -0
  47. package/web-dist/assets/{info-DKCQHKI2-D9D3wpUe.js → info-DKCQHKI2-BYiyjhUV.js} +1 -1
  48. package/web-dist/assets/{infoDiagram-FWYZ7A6U-OicbdNyT.js → infoDiagram-FWYZ7A6U-5zjTG5N-.js} +1 -1
  49. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-CxW1KZkJ.js → ishikawaDiagram-FXEZZL3T-Ca2QU8ga.js} +1 -1
  50. package/web-dist/assets/{journeyDiagram-5HDEW3XC-Cv_hFPA1.js → journeyDiagram-5HDEW3XC-CzUGQDiX.js} +1 -1
  51. package/web-dist/assets/{kanban-definition-HUTT4EX6-DAxsmFpq.js → kanban-definition-HUTT4EX6-CjTCAZS0.js} +1 -1
  52. package/web-dist/assets/{line-5gxO7MJu.js → line-uxNpP2NX.js} +1 -1
  53. package/web-dist/assets/{mermaid-parser.core-Clo3Gx_r.js → mermaid-parser.core-BADU525L.js} +3 -3
  54. package/web-dist/assets/{mermaid.core-DQVSzFfu.js → mermaid.core-OvwlqnDg.js} +3 -3
  55. package/web-dist/assets/{mindmap-definition-LN4V7U3C-BLAWdXEa.js → mindmap-definition-LN4V7U3C-BtbgfcR8.js} +1 -1
  56. package/web-dist/assets/{packet-7NZHBO7P-CkwoXyyj.js → packet-7NZHBO7P-BsfLS3kE.js} +1 -1
  57. package/web-dist/assets/{pegDiagram-2B236MQR-EoT5o_DR.js → pegDiagram-2B236MQR-CB5AkYXG.js} +1 -1
  58. package/web-dist/assets/{pie-RZYD4A2V-DctUkU05.js → pie-RZYD4A2V-DgnPemgQ.js} +1 -1
  59. package/web-dist/assets/{pieDiagram-ENE6RG2P-_hygR0kV.js → pieDiagram-ENE6RG2P-DgiTOSOg.js} +1 -1
  60. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-C4LSjyl4.js → quadrantDiagram-ABIIQ3AL-D56bxzKq.js} +1 -1
  61. package/web-dist/assets/{radar-I7S5WNFK-cLaZY3cZ.js → radar-I7S5WNFK-Buix85nx.js} +1 -1
  62. package/web-dist/assets/{railroad-3IZDKUUU-C65WXmSn.js → railroad-3IZDKUUU-_-csUIwQ.js} +1 -1
  63. package/web-dist/assets/railroad-abnf-AHOZXSZD-BGBPTyyT.js +1 -0
  64. package/web-dist/assets/railroad-ebnf-EBAXGLYW-isH8svgX.js +1 -0
  65. package/web-dist/assets/railroad-peg-LSFZ7HO6-DAuLC_Z3.js +1 -0
  66. package/web-dist/assets/{railroadDiagram-RFXS5EU6-Dn16txLH.js → railroadDiagram-RFXS5EU6-C5pjXI43.js} +1 -1
  67. package/web-dist/assets/{requirementDiagram-TGXJPOKE-C5YjIKDa.js → requirementDiagram-TGXJPOKE-DKG82b1A.js} +1 -1
  68. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-Cq4PSQlq.js → sankeyDiagram-HTMAVEWB-xNsa0WzO.js} +1 -1
  69. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-Cmp4VsSM.js → sequenceDiagram-DBY2YBRQ-CWHvrs9Q.js} +1 -1
  70. package/web-dist/assets/{stateDiagram-2N3HPSRC-B-0v_Yfp.js → stateDiagram-2N3HPSRC-DirRfNzF.js} +1 -1
  71. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-D58IKdqf.js +1 -0
  72. package/web-dist/assets/{swimlanes-5IMT3BWC-qbvnptVY.js → swimlanes-5IMT3BWC-B0GC66v6.js} +1 -1
  73. package/web-dist/assets/swimlanesDiagram-G3AALYLV-B1vaMvkV.js +8 -0
  74. package/web-dist/assets/{timeline-definition-FHXFAJF6-CqeXaN8j.js → timeline-definition-FHXFAJF6-D-UsR0sc.js} +1 -1
  75. package/web-dist/assets/{treeView-QDETBFTQ-5GicSF76.js → treeView-QDETBFTQ-BcjBpVxS.js} +1 -1
  76. package/web-dist/assets/{treemap-6X3UGDF4-BVW_Tlqy.js → treemap-6X3UGDF4-CrsT6ziM.js} +1 -1
  77. package/web-dist/assets/{vennDiagram-L72KCM5P-_TDGZ9p3.js → vennDiagram-L72KCM5P-DrY93og0.js} +1 -1
  78. package/web-dist/assets/{wardley-OPB4EBWU-DVPKqhtH.js → wardley-OPB4EBWU-D1WgLKZM.js} +1 -1
  79. package/web-dist/assets/{wardleyDiagram-EHGQE667-NeZypG8O.js → wardleyDiagram-EHGQE667-BJ5hU4aG.js} +1 -1
  80. package/web-dist/assets/{xychartDiagram-FW5EYKEG-CEA2obVn.js → xychartDiagram-FW5EYKEG-DS28rhax.js} +1 -1
  81. package/web-dist/index.html +2 -2
  82. package/web-dist/assets/architecture-TIHT7OUA-CT-l-iYs.js +0 -1
  83. package/web-dist/assets/channel-BjRezNGc.js +0 -1
  84. package/web-dist/assets/classDiagram-OUVF2IWQ-DUv3gfcu.js +0 -1
  85. package/web-dist/assets/classDiagram-v2-EOCWNBFH-DUv3gfcu.js +0 -1
  86. package/web-dist/assets/eventmodeling-45OFAUF4-CEMF1uOR.js +0 -1
  87. package/web-dist/assets/flowDiagram-23GEKE2U-KQl_eJg5.js +0 -1
  88. package/web-dist/assets/index-BsKzHpQr.js +0 -321
  89. package/web-dist/assets/index-D956g6KI.css +0 -1
  90. package/web-dist/assets/railroad-abnf-AHOZXSZD-Debv9Btn.js +0 -1
  91. package/web-dist/assets/railroad-ebnf-EBAXGLYW-DaJLFOcZ.js +0 -1
  92. package/web-dist/assets/railroad-peg-LSFZ7HO6-BeXRfi50.js +0 -1
  93. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-CCZrLBaF.js +0 -1
  94. package/web-dist/assets/swimlanesDiagram-G3AALYLV-BjqTNZ-I.js +0 -8
@@ -0,0 +1,407 @@
1
+ import { createRequire as __frizzCreateRequire } from "node:module"; const require = __frizzCreateRequire(import.meta.url);
2
+
3
+ // packages/server/src/backend/acp-daemon.ts
4
+ import { spawn } from "node:child_process";
5
+ import { createServer } from "node:net";
6
+ import { existsSync, readFileSync, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
7
+ import { dirname } from "node:path";
8
+ import { StringDecoder } from "node:string_decoder";
9
+
10
+ // packages/server/src/backend/stale-socket-sweep.ts
11
+ import { execFile } from "node:child_process";
12
+ import { readdirSync, unlinkSync } from "node:fs";
13
+ import { connect as connectSocket } from "node:net";
14
+ import { join } from "node:path";
15
+ function parseLsofSocketNames(stdout) {
16
+ const referenced = /* @__PURE__ */ new Set();
17
+ for (const line of stdout.split("\n")) {
18
+ if (!line.startsWith("n/")) continue;
19
+ const raw = line.slice(1);
20
+ referenced.add(raw);
21
+ const meta = raw.indexOf(" type=");
22
+ if (meta > 0) referenced.add(raw.slice(0, meta));
23
+ }
24
+ return referenced;
25
+ }
26
+ var defaultListReferenced = (prefix, done) => {
27
+ execFile("lsof", ["-U", "-F", "n"], { timeout: 3e4, maxBuffer: 16 * 1024 * 1024 }, (error, stdout) => {
28
+ if (!stdout) return done(null);
29
+ if (error && !stdout.includes(prefix)) return done(null);
30
+ done(parseLsofSocketNames(stdout));
31
+ }).unref?.();
32
+ };
33
+ var defaultProbe = (path, verdict) => {
34
+ const probe = connectSocket(path);
35
+ probe.unref?.();
36
+ probe.on("connect", () => {
37
+ probe.destroy();
38
+ verdict(false);
39
+ });
40
+ probe.on("error", (error) => {
41
+ probe.destroy();
42
+ verdict(error.code === "ECONNREFUSED" || error.code === "ENOENT");
43
+ });
44
+ };
45
+ function sweepStaleSockets(options, deps = {}) {
46
+ if (process.platform === "win32") return;
47
+ const keep = new Set(options.keep ?? []);
48
+ let candidates;
49
+ try {
50
+ candidates = (deps.readdir ?? readdirSync)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join(options.dir, name)).filter((path) => !keep.has(path));
51
+ } catch {
52
+ return;
53
+ }
54
+ if (candidates.length === 0) return;
55
+ const probe = deps.probe ?? defaultProbe;
56
+ const unlink = deps.unlink ?? ((path) => {
57
+ try {
58
+ unlinkSync(path);
59
+ } catch {
60
+ }
61
+ });
62
+ (deps.listReferenced ?? defaultListReferenced)(options.prefix, (referenced) => {
63
+ if (!referenced) return;
64
+ for (const path of candidates) {
65
+ if (referenced.has(path)) continue;
66
+ probe(path, (dead) => {
67
+ if (dead) unlink(path);
68
+ });
69
+ }
70
+ });
71
+ }
72
+
73
+ // packages/server/src/backend/acp-daemon.ts
74
+ var MAX_QUEUED_LINES = 2e4;
75
+ var MAX_QUEUED_BYTES = 64 * 1024 * 1024;
76
+ var MAX_LINE_BYTES = 8 * 1024 * 1024;
77
+ var IDLE_EXIT_MS = 6 * 60 * 60 * 1e3;
78
+ var REACHABILITY_CHECK_MS = 3e4;
79
+ var REACHABILITY_STRIKES = 2;
80
+ function readConfig() {
81
+ const raw = process.env.FRIZZ_ACP_DAEMON;
82
+ if (!raw) throw new Error("acp daemon started without FRIZZ_ACP_DAEMON");
83
+ const config = JSON.parse(raw);
84
+ if (!config.socketPath || !config.recordPath || !config.command || !config.generation || !config.sessionId) {
85
+ throw new Error("acp daemon config is incomplete");
86
+ }
87
+ return config;
88
+ }
89
+ function lineReader(onLine, onOverflow) {
90
+ const decoder = new StringDecoder("utf8");
91
+ let buffer = "";
92
+ let overflowed = false;
93
+ return (chunk) => {
94
+ buffer += decoder.write(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
95
+ for (; ; ) {
96
+ const index = buffer.indexOf("\n");
97
+ if (index < 0) break;
98
+ const line = buffer.slice(0, index);
99
+ buffer = buffer.slice(index + 1);
100
+ if (overflowed) {
101
+ overflowed = false;
102
+ continue;
103
+ }
104
+ if (Buffer.byteLength(line) > MAX_LINE_BYTES) {
105
+ onOverflow();
106
+ continue;
107
+ }
108
+ const trimmed = line.trim();
109
+ if (trimmed) onLine(trimmed);
110
+ }
111
+ if (Buffer.byteLength(buffer) > MAX_LINE_BYTES) {
112
+ buffer = "";
113
+ if (!overflowed) onOverflow();
114
+ overflowed = true;
115
+ }
116
+ };
117
+ }
118
+ function main() {
119
+ const config = readConfig();
120
+ const child = spawn(config.command, config.args, {
121
+ cwd: config.cwd,
122
+ env: config.env,
123
+ stdio: ["pipe", "pipe", "pipe"],
124
+ // This daemon is forked `detached`, which on Windows is DETACHED_PROCESS: it owns NO console, and a
125
+ // console-subsystem agent started without CREATE_NO_WINDOW would get a fresh visible one.
126
+ windowsHide: true
127
+ });
128
+ let client = null;
129
+ let queuedLines = [];
130
+ let queuedBytes = 0;
131
+ let dropped = 0;
132
+ let idleTimer = null;
133
+ let published = false;
134
+ const recordOwner = () => {
135
+ try {
136
+ const value = JSON.parse(readFileSync(config.recordPath, "utf8"));
137
+ return typeof value.daemonPid === "number" ? value.daemonPid : null;
138
+ } catch {
139
+ return null;
140
+ }
141
+ };
142
+ const cleanup = () => {
143
+ try {
144
+ client?.destroy();
145
+ } catch {
146
+ }
147
+ const owner = recordOwner();
148
+ if (owner === process.pid) {
149
+ try {
150
+ unlinkSync2(config.recordPath);
151
+ } catch {
152
+ }
153
+ }
154
+ if (published && owner !== null && owner !== process.pid) return;
155
+ if (published && process.platform !== "win32") {
156
+ try {
157
+ unlinkSync2(config.socketPath);
158
+ } catch {
159
+ }
160
+ }
161
+ };
162
+ const writeExitBreadcrumb = (reason) => {
163
+ try {
164
+ writeFileSync(`${config.recordPath}.exit`, JSON.stringify({
165
+ threadSlug: config.threadSlug,
166
+ sessionId: config.sessionId,
167
+ generation: config.generation,
168
+ daemonPid: process.pid,
169
+ childPid: child.pid ?? null,
170
+ reason,
171
+ at: (/* @__PURE__ */ new Date()).toISOString()
172
+ }));
173
+ } catch {
174
+ }
175
+ };
176
+ const die = (code, reason) => {
177
+ writeExitBreadcrumb(reason);
178
+ cleanup();
179
+ process.exit(code);
180
+ };
181
+ const armIdleExit = () => {
182
+ if (idleTimer) clearTimeout(idleTimer);
183
+ idleTimer = setTimeout(() => {
184
+ try {
185
+ child.kill("SIGTERM");
186
+ } catch {
187
+ }
188
+ ;
189
+ die(0, "idle-timeout");
190
+ }, config.idleExitMs ?? IDLE_EXIT_MS);
191
+ idleTimer.unref?.();
192
+ };
193
+ let unreachableStrikes = 0;
194
+ const checkReachable = () => {
195
+ if (client) {
196
+ unreachableStrikes = 0;
197
+ return;
198
+ }
199
+ if (recordOwner() === process.pid) {
200
+ unreachableStrikes = 0;
201
+ return;
202
+ }
203
+ if (++unreachableStrikes < REACHABILITY_STRIKES) return;
204
+ try {
205
+ child.kill("SIGTERM");
206
+ } catch {
207
+ }
208
+ die(0, "self-collected-record-reassigned");
209
+ };
210
+ const toClient = (line) => {
211
+ if (client) {
212
+ try {
213
+ client.write(`${line}
214
+ `);
215
+ return;
216
+ } catch {
217
+ }
218
+ }
219
+ if (queuedLines.length >= MAX_QUEUED_LINES || queuedBytes >= MAX_QUEUED_BYTES) {
220
+ dropped++;
221
+ return;
222
+ }
223
+ queuedLines.push(line);
224
+ queuedBytes += Buffer.byteLength(line) + 1;
225
+ };
226
+ const control = (payload) => JSON.stringify({ frizz: 1, ...payload });
227
+ const pendingFromClient = /* @__PURE__ */ new Map();
228
+ let nextDaemonId = 1e6;
229
+ let initializeResult = null;
230
+ let initializeDaemonId = null;
231
+ let acpSessionId = null;
232
+ const toChild = (message) => {
233
+ try {
234
+ child.stdin.write(`${JSON.stringify(message)}
235
+ `);
236
+ } catch {
237
+ }
238
+ };
239
+ const readChildLine = (line) => {
240
+ let message;
241
+ try {
242
+ message = JSON.parse(line);
243
+ } catch {
244
+ toClient(line);
245
+ return;
246
+ }
247
+ if (message.id !== void 0 && message.method === void 0 && typeof message.id === "number") {
248
+ const owner = pendingFromClient.get(message.id);
249
+ if (owner !== void 0) {
250
+ pendingFromClient.delete(message.id);
251
+ if (message.id === initializeDaemonId && message.error === void 0) initializeResult = message.result ?? null;
252
+ if (owner.method === "session/new" && message.error === void 0) {
253
+ const result = message.result;
254
+ if (typeof result?.sessionId === "string") acpSessionId = result.sessionId;
255
+ }
256
+ if (owner.method === "session/load" && message.error === void 0) {
257
+ const params = owner.params;
258
+ if (typeof params?.sessionId === "string") acpSessionId = params.sessionId;
259
+ }
260
+ toClient(JSON.stringify({ ...message, id: owner.clientId }));
261
+ return;
262
+ }
263
+ }
264
+ if (message.id !== void 0 && message.method !== void 0) {
265
+ pendingFromChild.set(String(message.id), { line, queued: client === null });
266
+ }
267
+ toClient(line);
268
+ };
269
+ const pendingFromChild = /* @__PURE__ */ new Map();
270
+ const readClientLine = (line) => {
271
+ let message;
272
+ try {
273
+ message = JSON.parse(line);
274
+ } catch {
275
+ return;
276
+ }
277
+ if (message.frizz === 1) {
278
+ const adopt = message.adopt;
279
+ if (adopt && typeof adopt.daemonId === "number" && (typeof adopt.clientId === "number" || typeof adopt.clientId === "string")) {
280
+ const owner = pendingFromClient.get(adopt.daemonId);
281
+ if (owner) owner.clientId = adopt.clientId;
282
+ }
283
+ return;
284
+ }
285
+ if (message.method === "initialize" && initializeResult !== null) {
286
+ if (message.id !== void 0) toClient(JSON.stringify({ jsonrpc: "2.0", id: message.id, result: initializeResult }));
287
+ return;
288
+ }
289
+ if (message.id !== void 0 && message.method !== void 0) {
290
+ const daemonId = nextDaemonId++;
291
+ pendingFromClient.set(daemonId, { clientId: message.id, method: String(message.method), params: message.params });
292
+ if (message.method === "initialize" && initializeDaemonId === null) initializeDaemonId = daemonId;
293
+ toChild({ ...message, id: daemonId });
294
+ return;
295
+ }
296
+ if (message.id !== void 0 && message.method === void 0) pendingFromChild.delete(String(message.id));
297
+ toChild(message);
298
+ };
299
+ const writeRecord = () => {
300
+ writeFileSync(config.recordPath, JSON.stringify({
301
+ threadSlug: config.threadSlug,
302
+ sessionId: config.sessionId,
303
+ generation: config.generation,
304
+ daemonPid: process.pid,
305
+ childPid: child.pid,
306
+ socketPath: config.socketPath,
307
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
308
+ }));
309
+ };
310
+ const server = createServer((sock) => {
311
+ if (client) {
312
+ try {
313
+ client.destroy();
314
+ } catch {
315
+ }
316
+ }
317
+ client = sock;
318
+ if (idleTimer) {
319
+ clearTimeout(idleTimer);
320
+ idleTimer = null;
321
+ }
322
+ sock.setNoDelay(true);
323
+ try {
324
+ sock.write(`${control({
325
+ hello: 1,
326
+ generation: config.generation,
327
+ childPid: child.pid,
328
+ droppedWhileDetached: dropped,
329
+ initialize: initializeResult,
330
+ acpSessionId,
331
+ outstanding: [...pendingFromClient].map(([daemonId, owner]) => ({ daemonId, method: owner.method }))
332
+ })}
333
+ `);
334
+ for (const line of queuedLines) sock.write(`${line}
335
+ `);
336
+ for (const entry of pendingFromChild.values()) {
337
+ if (!entry.queued) sock.write(`${entry.line}
338
+ `);
339
+ entry.queued = false;
340
+ }
341
+ } catch {
342
+ }
343
+ queuedLines = [];
344
+ queuedBytes = 0;
345
+ dropped = 0;
346
+ sock.on("data", lineReader((line) => {
347
+ if (!sock.destroyed) readClientLine(line);
348
+ }, () => sock.destroy()));
349
+ const drop = () => {
350
+ if (client !== sock) return;
351
+ client = null;
352
+ armIdleExit();
353
+ };
354
+ sock.on("close", drop);
355
+ sock.on("error", drop);
356
+ });
357
+ const sweepOwnFamily = () => sweepStaleSockets({ dir: dirname(config.socketPath), prefix: "frizz-acp-", keep: [config.socketPath] });
358
+ const startListening = () => {
359
+ if (process.platform !== "win32" && existsSync(config.socketPath)) {
360
+ try {
361
+ unlinkSync2(config.socketPath);
362
+ } catch {
363
+ }
364
+ }
365
+ server.on("error", () => die(6, "socket-listen-error"));
366
+ server.listen(config.socketPath, () => {
367
+ published = true;
368
+ writeRecord();
369
+ armIdleExit();
370
+ const reachability = setInterval(checkReachable, config.reachabilityCheckMs ?? REACHABILITY_CHECK_MS);
371
+ reachability.unref?.();
372
+ setTimeout(sweepOwnFamily, 5e3).unref?.();
373
+ });
374
+ };
375
+ child.stdout.on("data", lineReader(readChildLine, () => {
376
+ dropped++;
377
+ const lostClient = client;
378
+ client = null;
379
+ lostClient?.destroy();
380
+ armIdleExit();
381
+ }));
382
+ child.stderr.on("data", (chunk) => {
383
+ if (!client) return;
384
+ for (const line of String(chunk).split("\n")) {
385
+ if (!line.trim()) continue;
386
+ try {
387
+ client.write(`${control({ stderr: line.slice(0, 2e3) })}
388
+ `);
389
+ } catch {
390
+ }
391
+ }
392
+ });
393
+ child.on("exit", (code, signal) => die(0, signal ? `agent-killed-${signal}` : `agent-exited-code-${code ?? "null"}`));
394
+ child.on("error", () => die(4, "agent-spawn-error"));
395
+ startListening();
396
+ for (const signal of ["SIGTERM", "SIGINT", "SIGHUP"]) {
397
+ process.on(signal, () => {
398
+ try {
399
+ child.kill("SIGTERM");
400
+ } catch {
401
+ }
402
+ ;
403
+ die(0, `signal-${signal}`);
404
+ });
405
+ }
406
+ }
407
+ main();