frayui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -0
  3. package/dist/claude-agent-broker.js +21641 -0
  4. package/dist/codex-app-server-daemon.js +354 -0
  5. package/dist/dev-child.js +40319 -0
  6. package/dist/frayui.js +8738 -0
  7. package/package.json +46 -0
  8. package/runtime/cc/scripts/fray/agent-bindings.mjs +287 -0
  9. package/runtime/cc/scripts/fray/agent-liveness.mjs +367 -0
  10. package/runtime/cc/scripts/fray/agent-status.mjs +178 -0
  11. package/runtime/cc/scripts/fray/config.mjs +982 -0
  12. package/runtime/cc/scripts/fray/decisions.mjs +97 -0
  13. package/runtime/cc/scripts/fray/index.mjs +699 -0
  14. package/runtime/cc/scripts/fray/notify-shared.mjs +90 -0
  15. package/runtime/cc/scripts/fray/notify.mjs +81 -0
  16. package/runtime/cc/scripts/fray/ownership.mjs +120 -0
  17. package/runtime/cc/scripts/fray/rest-detect.mjs +213 -0
  18. package/runtime/cc/scripts/fray/thread-excerpt.mjs +162 -0
  19. package/runtime/cc/scripts/fray/thread-update.mjs +285 -0
  20. package/runtime/cc-worker/.claude-plugin/plugin.json +10 -0
  21. package/runtime/cc-worker/DECISIONS.md +923 -0
  22. package/runtime/cc-worker/LICENSE +21 -0
  23. package/runtime/cc-worker/agents/fable-high.md +8 -0
  24. package/runtime/cc-worker/agents/fable-low.md +8 -0
  25. package/runtime/cc-worker/agents/fable-max.md +8 -0
  26. package/runtime/cc-worker/agents/fable-medium.md +8 -0
  27. package/runtime/cc-worker/agents/fable-xhigh.md +8 -0
  28. package/runtime/cc-worker/agents/haiku.md +7 -0
  29. package/runtime/cc-worker/agents/opus-high.md +8 -0
  30. package/runtime/cc-worker/agents/opus-low.md +8 -0
  31. package/runtime/cc-worker/agents/opus-max.md +8 -0
  32. package/runtime/cc-worker/agents/opus-medium.md +8 -0
  33. package/runtime/cc-worker/agents/opus-xhigh.md +8 -0
  34. package/runtime/cc-worker/agents/sonnet-high.md +8 -0
  35. package/runtime/cc-worker/agents/sonnet-low.md +8 -0
  36. package/runtime/cc-worker/agents/sonnet-max.md +8 -0
  37. package/runtime/cc-worker/agents/sonnet-medium.md +8 -0
  38. package/runtime/cc-worker/agents/sonnet-xhigh.md +8 -0
  39. package/runtime/cc-worker/bin/fray +17 -0
  40. package/runtime/cc-worker/bin/fray-mcp.mjs +248 -0
  41. package/runtime/cc-worker/bin/fray-update +18 -0
  42. package/runtime/cc-worker/hooks/agent-bind.mjs +40 -0
  43. package/runtime/cc-worker/hooks/agent-dispatch.mjs +74 -0
  44. package/runtime/cc-worker/hooks/bash-background.d.mts +6 -0
  45. package/runtime/cc-worker/hooks/bash-background.mjs +188 -0
  46. package/runtime/cc-worker/hooks/deny-ask.mjs +38 -0
  47. package/runtime/cc-worker/hooks/deny-plan.mjs +61 -0
  48. package/runtime/cc-worker/hooks/hooks.json +111 -0
  49. package/runtime/cc-worker/hooks/perm-policy.mjs +211 -0
  50. package/runtime/cc-worker/hooks/precompact-instructions.mjs +122 -0
  51. package/runtime/cc-worker/hooks/scratchpad-stop.mjs +125 -0
  52. package/runtime/cc-worker/hooks/scratchpad.mjs +419 -0
  53. package/runtime/cc-worker/hooks/session-seed.mjs +105 -0
  54. package/runtime/cc-worker/scripts/fray/agent-bindings.mjs +9 -0
  55. package/runtime/cc-worker/scripts/fray/config.mjs +12 -0
  56. package/runtime/cc-worker/skills/gh/SKILL.md +132 -0
  57. package/runtime/cc-worker/skills/gh/scripts/ci-watch.mjs +60 -0
  58. package/runtime/cc-worker/skills/gh/scripts/github-watch.mjs +130 -0
  59. package/runtime/cc-worker/skills/gh/scripts/review-watch.mjs +54 -0
  60. package/runtime/cc-worker/skills/handoff/SKILL.md +203 -0
  61. package/runtime/cc-worker/skills/waits/SKILL.md +83 -0
  62. package/web-dist/apple-touch-icon.png +0 -0
  63. package/web-dist/assets/TerminalPane-fMGrgB-a.js +7 -0
  64. package/web-dist/assets/abnfDiagram-VRR7QNED-BtlrDuYX.js +1 -0
  65. package/web-dist/assets/arc-BSyeo0Gb.js +1 -0
  66. package/web-dist/assets/architecture-TIHT7OUA-CuD8jpr-.js +1 -0
  67. package/web-dist/assets/architectureDiagram-ZJ3FMSHR-CdLQ71be.js +36 -0
  68. package/web-dist/assets/array-BifhSqXX.js +1 -0
  69. package/web-dist/assets/blockDiagram-677ZJIJ3-CBk2FHEj.js +132 -0
  70. package/web-dist/assets/c4Diagram-LMCZKHZV-mZ3HQ6WX.js +10 -0
  71. package/web-dist/assets/channel-C2eUWc74.js +1 -0
  72. package/web-dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  73. package/web-dist/assets/chunk-32BRIVSS-Daxvi7f5.js +1 -0
  74. package/web-dist/assets/chunk-52WLFC77-BGJoZvry.js +10 -0
  75. package/web-dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  76. package/web-dist/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  77. package/web-dist/assets/chunk-C7G6YPKG-Ycd1yheh.js +1 -0
  78. package/web-dist/assets/chunk-EX3LRPZG-BPFhlsHp.js +231 -0
  79. package/web-dist/assets/chunk-FWX5IMBZ--xy8DTon.js +2 -0
  80. package/web-dist/assets/chunk-HOUHSVGY-Dq3zoygp.js +1 -0
  81. package/web-dist/assets/chunk-ICXQ74PX-FfKP-7yM.js +2 -0
  82. package/web-dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  83. package/web-dist/assets/chunk-KEIR6QF5-BfrZ3jm6.js +161 -0
  84. package/web-dist/assets/chunk-MOJQB5TN-BeiHnsLF.js +88 -0
  85. package/web-dist/assets/chunk-OGEWGWER-CjDU_9fC.js +1 -0
  86. package/web-dist/assets/chunk-PUDLZKDR-BO7tm5QX.js +156 -0
  87. package/web-dist/assets/chunk-Q4XR5HBZ-BPefovOg.js +70 -0
  88. package/web-dist/assets/chunk-RYQCIY6F-Cu_KplZW.js +1 -0
  89. package/web-dist/assets/chunk-V7JOEXUC-DWnebFHh.js +206 -0
  90. package/web-dist/assets/chunk-VAUOI2AC-BL6qWFhW.js +1 -0
  91. package/web-dist/assets/chunk-VR4S4FIN-Mfs__7L9.js +1 -0
  92. package/web-dist/assets/chunk-WYO6CB5R-Bf2IYbEU.js +127 -0
  93. package/web-dist/assets/chunk-XXDRQBXY-DYlTP5J-.js +1 -0
  94. package/web-dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  95. package/web-dist/assets/chunk-ZGVPDNZ5-CJ9ZHZgU.js +62 -0
  96. package/web-dist/assets/chunk-ZIRB5QZD-C6fEPe3t.js +32 -0
  97. package/web-dist/assets/classDiagram-OUVF2IWQ-GaOJNgfE.js +1 -0
  98. package/web-dist/assets/classDiagram-v2-EOCWNBFH-GaOJNgfE.js +1 -0
  99. package/web-dist/assets/cose-bilkent-JH36ORCC-BUIsLrGc.js +1 -0
  100. package/web-dist/assets/cynefin-VYW2F7L2-COSC0oNL.js +1 -0
  101. package/web-dist/assets/cynefinDiagram-TSTJHNR4-mInhJdg1.js +62 -0
  102. package/web-dist/assets/cytoscape.esm-B3I8pqwA.js +321 -0
  103. package/web-dist/assets/dagre-CXRCoUWR.js +1 -0
  104. package/web-dist/assets/dagre-VKFMJZFB-D-T5z05M.js +4 -0
  105. package/web-dist/assets/defaultLocale-C8Fc0cco.js +1 -0
  106. package/web-dist/assets/diagram-FQU43EPY-HbMkSb3j.js +3 -0
  107. package/web-dist/assets/diagram-G47NLZAW-DBwZLcZh.js +24 -0
  108. package/web-dist/assets/diagram-NH7WQ7WH-DG_Mhays.js +24 -0
  109. package/web-dist/assets/diagram-OA4YK3LP-hH39gqpu.js +30 -0
  110. package/web-dist/assets/diagram-WEI45ONY-DhKZuwxW.js +41 -0
  111. package/web-dist/assets/dist-DoH_9pyS.js +1 -0
  112. package/web-dist/assets/ebnfDiagram-CCIWWBDH-B7BiO-NR.js +1 -0
  113. package/web-dist/assets/erDiagram-Q63AITRT-DHjG5RDQ.js +85 -0
  114. package/web-dist/assets/eventmodeling-45OFAUF4-C0eV8RBx.js +1 -0
  115. package/web-dist/assets/flowDiagram-23GEKE2U-BbldRZUK.js +1 -0
  116. package/web-dist/assets/ganttDiagram-NO4QXBWP-BZ-98wTa.js +292 -0
  117. package/web-dist/assets/gitGraph-TEB2WS4Q-nF22R2jO.js +1 -0
  118. package/web-dist/assets/gitGraphDiagram-IHSO6WYX-CoYQQ22V.js +106 -0
  119. package/web-dist/assets/graphlib-B8gBHxth.js +1 -0
  120. package/web-dist/assets/index-BHzIN-tQ.js +357 -0
  121. package/web-dist/assets/index-Duiy4w7C.css +1 -0
  122. package/web-dist/assets/info-DKCQHKI2-Cy2BCbBW.js +1 -0
  123. package/web-dist/assets/infoDiagram-FWYZ7A6U-CmhR2R1x.js +2 -0
  124. package/web-dist/assets/init-D6jRqBbL.js +1 -0
  125. package/web-dist/assets/ishikawaDiagram-FXEZZL3T-CfG59afl.js +70 -0
  126. package/web-dist/assets/journeyDiagram-5HDEW3XC-BvFmG20q.js +139 -0
  127. package/web-dist/assets/kanban-definition-HUTT4EX6-BHGEecsY.js +89 -0
  128. package/web-dist/assets/katex-CddkPoXu.js +257 -0
  129. package/web-dist/assets/line-Ds4xvN3d.js +1 -0
  130. package/web-dist/assets/linear-z2V0wJk9.js +1 -0
  131. package/web-dist/assets/map-DsCK-0Cs.js +1 -0
  132. package/web-dist/assets/mermaid-parser.core-Gow4kgYJ.js +7 -0
  133. package/web-dist/assets/mermaid.core-B7Qc_kbm.js +11 -0
  134. package/web-dist/assets/mindmap-definition-LN4V7U3C-ayXKGcy_.js +96 -0
  135. package/web-dist/assets/ordinal-hYBb2elL.js +1 -0
  136. package/web-dist/assets/packet-7NZHBO7P-oLBdtkD8.js +1 -0
  137. package/web-dist/assets/path-BWPyau1x.js +1 -0
  138. package/web-dist/assets/pegDiagram-2B236MQR-DwJyc_1B.js +1 -0
  139. package/web-dist/assets/pie-RZYD4A2V-CXzad3fT.js +1 -0
  140. package/web-dist/assets/pieDiagram-ENE6RG2P-CZzgSGtM.js +39 -0
  141. package/web-dist/assets/quadrantDiagram-ABIIQ3AL--IPIp8yo.js +7 -0
  142. package/web-dist/assets/radar-I7S5WNFK-DldySvtZ.js +1 -0
  143. package/web-dist/assets/railroad-3IZDKUUU-CiWFZfXM.js +1 -0
  144. package/web-dist/assets/railroad-abnf-AHOZXSZD-bXMYUOCD.js +1 -0
  145. package/web-dist/assets/railroad-ebnf-EBAXGLYW-D11ZwZby.js +1 -0
  146. package/web-dist/assets/railroad-peg-LSFZ7HO6-DD1AC5X-.js +1 -0
  147. package/web-dist/assets/railroadDiagram-RFXS5EU6-DcCMNGGb.js +1 -0
  148. package/web-dist/assets/requirementDiagram-TGXJPOKE-C-6j8urk.js +84 -0
  149. package/web-dist/assets/rolldown-runtime-Bh1tDfsg.js +1 -0
  150. package/web-dist/assets/rough.esm-CSKSodPl.js +1 -0
  151. package/web-dist/assets/sankeyDiagram-HTMAVEWB-CPtiOpdz.js +40 -0
  152. package/web-dist/assets/sequenceDiagram-DBY2YBRQ-B8FnQTdn.js +162 -0
  153. package/web-dist/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  154. package/web-dist/assets/src-C4XfhTaE.js +1 -0
  155. package/web-dist/assets/stateDiagram-2N3HPSRC-CxG9nX2P.js +1 -0
  156. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-SGarOFIy.js +1 -0
  157. package/web-dist/assets/swimlanes-5IMT3BWC-D49-t0hV.js +2 -0
  158. package/web-dist/assets/swimlanesDiagram-G3AALYLV-krF0bh4b.js +8 -0
  159. package/web-dist/assets/timeline-definition-FHXFAJF6-C9OEd9SE.js +120 -0
  160. package/web-dist/assets/treeView-QDETBFTQ-D1AKqVPa.js +1 -0
  161. package/web-dist/assets/treemap-6X3UGDF4-BRssB7hM.js +1 -0
  162. package/web-dist/assets/vennDiagram-L72KCM5P-CftkAbY0.js +34 -0
  163. package/web-dist/assets/wardley-OPB4EBWU-RLMgzRq4.js +1 -0
  164. package/web-dist/assets/wardleyDiagram-EHGQE667-BLytgXPS.js +78 -0
  165. package/web-dist/assets/xychartDiagram-FW5EYKEG-BYgK1Y3H.js +7 -0
  166. package/web-dist/favicon-16.png +0 -0
  167. package/web-dist/favicon-32.png +0 -0
  168. package/web-dist/favicon.svg +78 -0
  169. package/web-dist/icon-192.png +0 -0
  170. package/web-dist/icon-512.png +0 -0
  171. package/web-dist/icon-maskable-512.png +0 -0
  172. package/web-dist/index.html +33 -0
  173. package/web-dist/manifest.webmanifest +16 -0
@@ -0,0 +1,354 @@
1
+ import { createRequire as __frayCreateRequire } from "node:module"; const require = __frayCreateRequire(import.meta.url);
2
+
3
+ // packages/server/src/backend/codex-app-server-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
+ var defaultListReferenced = (prefix, done) => {
16
+ execFile("lsof", ["-U", "-F", "n"], { timeout: 3e4, maxBuffer: 16 * 1024 * 1024 }, (error, stdout) => {
17
+ if (!stdout) return done(null);
18
+ if (error && !stdout.includes(prefix)) return done(null);
19
+ const referenced = /* @__PURE__ */ new Set();
20
+ for (const line of stdout.split("\n")) if (line.startsWith("n/")) referenced.add(line.slice(1));
21
+ done(referenced);
22
+ }).unref?.();
23
+ };
24
+ var defaultProbe = (path, verdict) => {
25
+ const probe = connectSocket(path);
26
+ probe.unref?.();
27
+ probe.on("connect", () => {
28
+ probe.destroy();
29
+ verdict(false);
30
+ });
31
+ probe.on("error", (error) => {
32
+ probe.destroy();
33
+ verdict(error.code === "ECONNREFUSED" || error.code === "ENOENT");
34
+ });
35
+ };
36
+ function sweepStaleSockets(options, deps = {}) {
37
+ if (process.platform === "win32") return;
38
+ const keep = new Set(options.keep ?? []);
39
+ let candidates;
40
+ try {
41
+ 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));
42
+ } catch {
43
+ return;
44
+ }
45
+ if (candidates.length === 0) return;
46
+ const probe = deps.probe ?? defaultProbe;
47
+ const unlink = deps.unlink ?? ((path) => {
48
+ try {
49
+ unlinkSync(path);
50
+ } catch {
51
+ }
52
+ });
53
+ (deps.listReferenced ?? defaultListReferenced)(options.prefix, (referenced) => {
54
+ if (!referenced) return;
55
+ for (const path of candidates) {
56
+ if (referenced.has(path)) continue;
57
+ probe(path, (dead) => {
58
+ if (dead) unlink(path);
59
+ });
60
+ }
61
+ });
62
+ }
63
+
64
+ // packages/server/src/backend/codex-app-server-daemon.ts
65
+ var MAX_QUEUED_LINES = 2e4;
66
+ var MAX_QUEUED_BYTES = 64 * 1024 * 1024;
67
+ var MAX_LINE_BYTES = 8 * 1024 * 1024;
68
+ var IDLE_EXIT_MS = 6 * 60 * 60 * 1e3;
69
+ var HANDSHAKE_TIMEOUT_MS = 3e4;
70
+ var REACHABILITY_CHECK_MS = 3e4;
71
+ var REACHABILITY_STRIKES = 2;
72
+ function readConfig() {
73
+ const raw = process.env.FRAY_CODEX_APP_SERVER_DAEMON;
74
+ if (!raw) throw new Error("codex app-server daemon started without FRAY_CODEX_APP_SERVER_DAEMON");
75
+ const config = JSON.parse(raw);
76
+ if (!config.socketPath || !config.recordPath || !config.codexBin || !config.generation) {
77
+ throw new Error("codex app-server daemon config is incomplete");
78
+ }
79
+ return config;
80
+ }
81
+ function lineReader(onLine) {
82
+ const decoder = new StringDecoder("utf8");
83
+ let buffer = "";
84
+ let overflowed = false;
85
+ return (chunk) => {
86
+ buffer += decoder.write(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
87
+ for (; ; ) {
88
+ const index = buffer.indexOf("\n");
89
+ if (index < 0) break;
90
+ const line = buffer.slice(0, index);
91
+ buffer = buffer.slice(index + 1);
92
+ if (overflowed) {
93
+ overflowed = false;
94
+ continue;
95
+ }
96
+ const trimmed = line.trim();
97
+ if (trimmed) onLine(trimmed);
98
+ }
99
+ if (Buffer.byteLength(buffer) > MAX_LINE_BYTES) {
100
+ buffer = "";
101
+ overflowed = true;
102
+ }
103
+ };
104
+ }
105
+ function main() {
106
+ const config = readConfig();
107
+ const child = spawn(config.codexBin, ["app-server", "--stdio"], {
108
+ cwd: config.cwd,
109
+ env: config.env,
110
+ stdio: ["pipe", "pipe", "pipe"]
111
+ });
112
+ let client = null;
113
+ let queuedLines = [];
114
+ let queuedBytes = 0;
115
+ let dropped = 0;
116
+ let idleTimer = null;
117
+ let published = false;
118
+ const recordOwner = () => {
119
+ try {
120
+ const value = JSON.parse(readFileSync(config.recordPath, "utf8"));
121
+ return typeof value.daemonPid === "number" ? value.daemonPid : null;
122
+ } catch {
123
+ return null;
124
+ }
125
+ };
126
+ const cleanup = () => {
127
+ try {
128
+ client?.destroy();
129
+ } catch {
130
+ }
131
+ const owner = recordOwner();
132
+ if (owner === process.pid) {
133
+ try {
134
+ unlinkSync2(config.recordPath);
135
+ } catch {
136
+ }
137
+ }
138
+ if (published && owner !== null && owner !== process.pid) return;
139
+ if (published && process.platform !== "win32") {
140
+ try {
141
+ unlinkSync2(config.socketPath);
142
+ } catch {
143
+ }
144
+ }
145
+ };
146
+ const writeExitBreadcrumb = (reason) => {
147
+ try {
148
+ writeFileSync(`${config.recordPath}.exit`, JSON.stringify({
149
+ projectId: config.projectId,
150
+ generation: config.generation,
151
+ daemonPid: process.pid,
152
+ childPid: child.pid ?? null,
153
+ reason,
154
+ at: (/* @__PURE__ */ new Date()).toISOString()
155
+ }));
156
+ } catch {
157
+ }
158
+ };
159
+ const die = (code, reason) => {
160
+ writeExitBreadcrumb(reason);
161
+ cleanup();
162
+ process.exit(code);
163
+ };
164
+ const armIdleExit = () => {
165
+ if (idleTimer) clearTimeout(idleTimer);
166
+ idleTimer = setTimeout(() => {
167
+ try {
168
+ child.kill("SIGTERM");
169
+ } catch {
170
+ }
171
+ ;
172
+ die(0, "idle-timeout");
173
+ }, IDLE_EXIT_MS);
174
+ idleTimer.unref?.();
175
+ };
176
+ let unreachableStrikes = 0;
177
+ const checkReachable = () => {
178
+ if (client) {
179
+ unreachableStrikes = 0;
180
+ return;
181
+ }
182
+ if (recordOwner() === process.pid) {
183
+ unreachableStrikes = 0;
184
+ return;
185
+ }
186
+ if (++unreachableStrikes < REACHABILITY_STRIKES) return;
187
+ try {
188
+ child.kill("SIGTERM");
189
+ } catch {
190
+ }
191
+ die(0, "self-collected-record-reassigned");
192
+ };
193
+ const toClient = (line) => {
194
+ if (client) {
195
+ try {
196
+ client.write(`${line}
197
+ `);
198
+ return;
199
+ } catch {
200
+ }
201
+ }
202
+ if (queuedLines.length >= MAX_QUEUED_LINES || queuedBytes >= MAX_QUEUED_BYTES) {
203
+ dropped++;
204
+ return;
205
+ }
206
+ queuedLines.push(line);
207
+ queuedBytes += Buffer.byteLength(line) + 1;
208
+ };
209
+ const control = (payload) => JSON.stringify({ fray: 1, ...payload });
210
+ const HANDSHAKE_ID = -1;
211
+ let initializeResult;
212
+ let handshakeDone = false;
213
+ const pendingFromClient = /* @__PURE__ */ new Map();
214
+ let nextDaemonId = 1e6;
215
+ const toServer = (message) => {
216
+ try {
217
+ child.stdin.write(`${JSON.stringify(message)}
218
+ `);
219
+ } catch {
220
+ }
221
+ };
222
+ const readServerLine = (line) => {
223
+ let message;
224
+ try {
225
+ message = JSON.parse(line);
226
+ } catch {
227
+ return;
228
+ }
229
+ if (!handshakeDone && message.id === HANDSHAKE_ID) {
230
+ if (message.error) die(3, "handshake-rejected");
231
+ initializeResult = message.result;
232
+ handshakeDone = true;
233
+ toServer({ method: "initialized" });
234
+ startListening();
235
+ return;
236
+ }
237
+ if (message.id !== void 0 && message.method === void 0 && typeof message.id === "number") {
238
+ const clientId = pendingFromClient.get(message.id);
239
+ if (clientId !== void 0) {
240
+ pendingFromClient.delete(message.id);
241
+ toClient(JSON.stringify({ ...message, id: clientId }));
242
+ return;
243
+ }
244
+ }
245
+ toClient(line);
246
+ };
247
+ const readClientLine = (line) => {
248
+ let message;
249
+ try {
250
+ message = JSON.parse(line);
251
+ } catch {
252
+ return;
253
+ }
254
+ if (message.method === "initialize") {
255
+ if (message.id !== void 0) toClient(JSON.stringify({ id: message.id, result: initializeResult }));
256
+ return;
257
+ }
258
+ if (message.method === "initialized") return;
259
+ if (message.id !== void 0 && message.method !== void 0) {
260
+ const daemonId = nextDaemonId++;
261
+ pendingFromClient.set(daemonId, message.id);
262
+ toServer({ ...message, id: daemonId });
263
+ return;
264
+ }
265
+ toServer(message);
266
+ };
267
+ const writeRecord = () => {
268
+ writeFileSync(config.recordPath, JSON.stringify({
269
+ projectId: config.projectId,
270
+ generation: config.generation,
271
+ daemonPid: process.pid,
272
+ childPid: child.pid,
273
+ socketPath: config.socketPath,
274
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
275
+ }));
276
+ };
277
+ const server = createServer((sock) => {
278
+ if (client) {
279
+ try {
280
+ client.destroy();
281
+ } catch {
282
+ }
283
+ }
284
+ client = sock;
285
+ if (idleTimer) {
286
+ clearTimeout(idleTimer);
287
+ idleTimer = null;
288
+ }
289
+ sock.setNoDelay(true);
290
+ try {
291
+ sock.write(`${control({ hello: 1, generation: config.generation, childPid: child.pid, droppedWhileDetached: dropped })}
292
+ `);
293
+ for (const line of queuedLines) sock.write(`${line}
294
+ `);
295
+ } catch {
296
+ }
297
+ queuedLines = [];
298
+ queuedBytes = 0;
299
+ dropped = 0;
300
+ sock.on("data", lineReader(readClientLine));
301
+ const drop = () => {
302
+ if (client !== sock) return;
303
+ client = null;
304
+ armIdleExit();
305
+ };
306
+ sock.on("close", drop);
307
+ sock.on("error", drop);
308
+ });
309
+ const sweepOwnFamily = () => sweepStaleSockets({ dir: dirname(config.socketPath), prefix: "fray-codex-", keep: [config.socketPath] });
310
+ const startListening = () => {
311
+ if (process.platform !== "win32" && existsSync(config.socketPath)) {
312
+ try {
313
+ unlinkSync2(config.socketPath);
314
+ } catch {
315
+ }
316
+ }
317
+ server.on("error", () => die(6, "socket-listen-error"));
318
+ server.listen(config.socketPath, () => {
319
+ published = true;
320
+ writeRecord();
321
+ armIdleExit();
322
+ const reachability = setInterval(checkReachable, config.reachabilityCheckMs ?? REACHABILITY_CHECK_MS);
323
+ reachability.unref?.();
324
+ setTimeout(sweepOwnFamily, 5e3).unref?.();
325
+ });
326
+ };
327
+ child.stdout.on("data", lineReader(readServerLine));
328
+ child.stderr.resume();
329
+ child.on("exit", (code, signal) => die(0, signal ? `app-server-killed-${signal}` : `app-server-exited-code-${code ?? "null"}`));
330
+ child.on("error", () => die(4, "app-server-spawn-error"));
331
+ toServer({ id: HANDSHAKE_ID, method: "initialize", params: { clientInfo: config.clientInfo, capabilities: config.capabilities } });
332
+ const handshakeTimer = setTimeout(() => {
333
+ if (!handshakeDone) {
334
+ try {
335
+ child.kill("SIGTERM");
336
+ } catch {
337
+ }
338
+ ;
339
+ die(5, "handshake-timeout");
340
+ }
341
+ }, HANDSHAKE_TIMEOUT_MS);
342
+ handshakeTimer.unref?.();
343
+ for (const signal of ["SIGTERM", "SIGINT", "SIGHUP"]) {
344
+ process.on(signal, () => {
345
+ try {
346
+ child.kill("SIGTERM");
347
+ } catch {
348
+ }
349
+ ;
350
+ die(0, `signal-${signal}`);
351
+ });
352
+ }
353
+ }
354
+ main();