everything-dev 0.3.2 → 1.3.2

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 (308) hide show
  1. package/README.md +64 -0
  2. package/cli.js +10 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  4. package/dist/api-contract.cjs +172 -0
  5. package/dist/api-contract.cjs.map +1 -0
  6. package/dist/api-contract.mjs +171 -0
  7. package/dist/api-contract.mjs.map +1 -0
  8. package/dist/api.cjs +124 -0
  9. package/dist/api.cjs.map +1 -0
  10. package/dist/api.d.cts +36 -0
  11. package/dist/api.d.cts.map +1 -0
  12. package/dist/api.d.mts +36 -0
  13. package/dist/api.d.mts.map +1 -0
  14. package/dist/api.mjs +119 -0
  15. package/dist/api.mjs.map +1 -0
  16. package/dist/app.cjs +156 -0
  17. package/dist/app.cjs.map +1 -0
  18. package/dist/app.mjs +153 -0
  19. package/dist/app.mjs.map +1 -0
  20. package/dist/cli/catalog.cjs +30 -0
  21. package/dist/cli/catalog.cjs.map +1 -0
  22. package/dist/cli/catalog.mjs +29 -0
  23. package/dist/cli/catalog.mjs.map +1 -0
  24. package/dist/cli/help.cjs +16 -0
  25. package/dist/cli/help.cjs.map +1 -0
  26. package/dist/cli/help.mjs +16 -0
  27. package/dist/cli/help.mjs.map +1 -0
  28. package/dist/cli/init.cjs +317 -0
  29. package/dist/cli/init.cjs.map +1 -0
  30. package/dist/cli/init.d.cts +36 -0
  31. package/dist/cli/init.d.cts.map +1 -0
  32. package/dist/cli/init.d.mts +36 -0
  33. package/dist/cli/init.d.mts.map +1 -0
  34. package/dist/cli/init.mjs +309 -0
  35. package/dist/cli/init.mjs.map +1 -0
  36. package/dist/cli/parse.cjs +96 -0
  37. package/dist/cli/parse.cjs.map +1 -0
  38. package/dist/cli/parse.mjs +95 -0
  39. package/dist/cli/parse.mjs.map +1 -0
  40. package/dist/cli/prompts.cjs +42 -0
  41. package/dist/cli/prompts.cjs.map +1 -0
  42. package/dist/cli/prompts.mjs +41 -0
  43. package/dist/cli/prompts.mjs.map +1 -0
  44. package/dist/cli.cjs +167 -0
  45. package/dist/cli.cjs.map +1 -0
  46. package/dist/cli.d.cts +1 -0
  47. package/dist/cli.d.mts +1 -0
  48. package/dist/cli.mjs +166 -0
  49. package/dist/cli.mjs.map +1 -0
  50. package/dist/components/dev-view.cjs +307 -0
  51. package/dist/components/dev-view.cjs.map +1 -0
  52. package/dist/components/dev-view.mjs +306 -0
  53. package/dist/components/dev-view.mjs.map +1 -0
  54. package/dist/components/streaming-view.cjs +146 -0
  55. package/dist/components/streaming-view.cjs.map +1 -0
  56. package/dist/components/streaming-view.mjs +144 -0
  57. package/dist/components/streaming-view.mjs.map +1 -0
  58. package/dist/config.cjs +280 -0
  59. package/dist/config.cjs.map +1 -0
  60. package/dist/config.d.cts +35 -0
  61. package/dist/config.d.cts.map +1 -0
  62. package/dist/config.d.mts +35 -0
  63. package/dist/config.d.mts.map +1 -0
  64. package/dist/config.mjs +266 -0
  65. package/dist/config.mjs.map +1 -0
  66. package/dist/contract.cjs +209 -0
  67. package/dist/contract.cjs.map +1 -0
  68. package/dist/contract.d.cts +490 -0
  69. package/dist/contract.d.cts.map +1 -0
  70. package/dist/contract.d.mts +490 -0
  71. package/dist/contract.d.mts.map +1 -0
  72. package/dist/contract.meta.cjs +104 -0
  73. package/dist/contract.meta.cjs.map +1 -0
  74. package/dist/contract.meta.d.cts +141 -0
  75. package/dist/contract.meta.d.cts.map +1 -0
  76. package/dist/contract.meta.d.mts +141 -0
  77. package/dist/contract.meta.d.mts.map +1 -0
  78. package/dist/contract.meta.mjs +102 -0
  79. package/dist/contract.meta.mjs.map +1 -0
  80. package/dist/contract.mjs +186 -0
  81. package/dist/contract.mjs.map +1 -0
  82. package/dist/dev-logs.cjs +53 -0
  83. package/dist/dev-logs.cjs.map +1 -0
  84. package/dist/dev-logs.mjs +51 -0
  85. package/dist/dev-logs.mjs.map +1 -0
  86. package/dist/dev-session.cjs +195 -0
  87. package/dist/dev-session.cjs.map +1 -0
  88. package/dist/dev-session.mjs +194 -0
  89. package/dist/dev-session.mjs.map +1 -0
  90. package/dist/fastkv.cjs +89 -0
  91. package/dist/fastkv.cjs.map +1 -0
  92. package/dist/fastkv.d.cts +11 -0
  93. package/dist/fastkv.d.cts.map +1 -0
  94. package/dist/fastkv.d.mts +11 -0
  95. package/dist/fastkv.d.mts.map +1 -0
  96. package/dist/fastkv.mjs +82 -0
  97. package/dist/fastkv.mjs.map +1 -0
  98. package/dist/federation.server.cjs +27 -0
  99. package/dist/federation.server.cjs.map +1 -0
  100. package/dist/federation.server.mjs +27 -0
  101. package/dist/federation.server.mjs.map +1 -0
  102. package/dist/host.cjs +367 -0
  103. package/dist/host.cjs.map +1 -0
  104. package/dist/host.d.cts +22 -0
  105. package/dist/host.d.cts.map +1 -0
  106. package/dist/host.d.mts +22 -0
  107. package/dist/host.d.mts.map +1 -0
  108. package/dist/host.mjs +364 -0
  109. package/dist/host.mjs.map +1 -0
  110. package/dist/index.cjs +122 -0
  111. package/dist/index.d.cts +7 -0
  112. package/dist/index.d.mts +7 -0
  113. package/dist/index.mjs +9 -0
  114. package/dist/integrity.cjs +39 -0
  115. package/dist/integrity.cjs.map +1 -0
  116. package/dist/integrity.d.cts +7 -0
  117. package/dist/integrity.d.cts.map +1 -0
  118. package/dist/integrity.d.mts +7 -0
  119. package/dist/integrity.d.mts.map +1 -0
  120. package/dist/integrity.mjs +35 -0
  121. package/dist/integrity.mjs.map +1 -0
  122. package/dist/mf.cjs +77 -0
  123. package/dist/mf.cjs.map +1 -0
  124. package/dist/mf.d.cts +19 -0
  125. package/dist/mf.d.cts.map +1 -0
  126. package/dist/mf.d.mts +19 -0
  127. package/dist/mf.d.mts.map +1 -0
  128. package/dist/mf.mjs +71 -0
  129. package/dist/mf.mjs.map +1 -0
  130. package/dist/near-cli.cjs +196 -0
  131. package/dist/near-cli.cjs.map +1 -0
  132. package/dist/near-cli.mjs +193 -0
  133. package/dist/near-cli.mjs.map +1 -0
  134. package/dist/network.cjs +9 -0
  135. package/dist/network.cjs.map +1 -0
  136. package/dist/network.mjs +8 -0
  137. package/dist/network.mjs.map +1 -0
  138. package/dist/orchestrator.cjs +441 -0
  139. package/dist/orchestrator.cjs.map +1 -0
  140. package/dist/orchestrator.d.cts +40 -0
  141. package/dist/orchestrator.d.cts.map +1 -0
  142. package/dist/orchestrator.d.mts +40 -0
  143. package/dist/orchestrator.d.mts.map +1 -0
  144. package/dist/orchestrator.mjs +436 -0
  145. package/dist/orchestrator.mjs.map +1 -0
  146. package/dist/plugin.cjs +825 -0
  147. package/dist/plugin.cjs.map +1 -0
  148. package/dist/plugin.d.cts +347 -0
  149. package/dist/plugin.d.cts.map +1 -0
  150. package/dist/plugin.d.mts +348 -0
  151. package/dist/plugin.d.mts.map +1 -0
  152. package/dist/plugin.mjs +822 -0
  153. package/dist/plugin.mjs.map +1 -0
  154. package/dist/process-registry.cjs +120 -0
  155. package/dist/process-registry.cjs.map +1 -0
  156. package/dist/process-registry.d.cts +25 -0
  157. package/dist/process-registry.d.cts.map +1 -0
  158. package/dist/process-registry.d.mts +25 -0
  159. package/dist/process-registry.d.mts.map +1 -0
  160. package/dist/process-registry.mjs +119 -0
  161. package/dist/process-registry.mjs.map +1 -0
  162. package/dist/sdk.cjs +61 -0
  163. package/dist/sdk.d.cts +5 -0
  164. package/dist/sdk.d.mts +5 -0
  165. package/dist/sdk.mjs +6 -0
  166. package/dist/shared.cjs +143 -0
  167. package/dist/shared.cjs.map +1 -0
  168. package/dist/shared.d.cts +33 -0
  169. package/dist/shared.d.cts.map +1 -0
  170. package/dist/shared.d.mts +33 -0
  171. package/dist/shared.d.mts.map +1 -0
  172. package/dist/shared.mjs +140 -0
  173. package/dist/shared.mjs.map +1 -0
  174. package/dist/types.cjs +160 -0
  175. package/dist/types.cjs.map +1 -0
  176. package/dist/types.d.cts +269 -0
  177. package/dist/types.d.cts.map +1 -0
  178. package/dist/types.d.mts +269 -0
  179. package/dist/types.d.mts.map +1 -0
  180. package/dist/types.mjs +144 -0
  181. package/dist/types.mjs.map +1 -0
  182. package/dist/ui/head.cjs +67 -0
  183. package/dist/ui/head.cjs.map +1 -0
  184. package/dist/ui/head.d.cts +19 -0
  185. package/dist/ui/head.d.cts.map +1 -0
  186. package/dist/ui/head.d.mts +19 -0
  187. package/dist/ui/head.d.mts.map +1 -0
  188. package/dist/ui/head.mjs +61 -0
  189. package/dist/ui/head.mjs.map +1 -0
  190. package/dist/ui/index.cjs +32 -0
  191. package/dist/ui/index.d.cts +7 -0
  192. package/dist/ui/index.d.mts +7 -0
  193. package/dist/ui/index.mjs +6 -0
  194. package/dist/ui/metadata.cjs +106 -0
  195. package/dist/ui/metadata.cjs.map +1 -0
  196. package/dist/ui/metadata.d.cts +35 -0
  197. package/dist/ui/metadata.d.cts.map +1 -0
  198. package/dist/ui/metadata.d.mts +35 -0
  199. package/dist/ui/metadata.d.mts.map +1 -0
  200. package/dist/ui/metadata.mjs +100 -0
  201. package/dist/ui/metadata.mjs.map +1 -0
  202. package/dist/ui/router.cjs +56 -0
  203. package/dist/ui/router.cjs.map +1 -0
  204. package/dist/ui/router.d.cts +11 -0
  205. package/dist/ui/router.d.cts.map +1 -0
  206. package/dist/ui/router.d.mts +11 -0
  207. package/dist/ui/router.d.mts.map +1 -0
  208. package/dist/ui/router.mjs +51 -0
  209. package/dist/ui/router.mjs.map +1 -0
  210. package/dist/ui/runtime.cjs +65 -0
  211. package/dist/ui/runtime.cjs.map +1 -0
  212. package/dist/ui/runtime.d.cts +29 -0
  213. package/dist/ui/runtime.d.cts.map +1 -0
  214. package/dist/ui/runtime.d.mts +29 -0
  215. package/dist/ui/runtime.d.mts.map +1 -0
  216. package/dist/ui/runtime.mjs +53 -0
  217. package/dist/ui/runtime.mjs.map +1 -0
  218. package/dist/ui/types.cjs +0 -0
  219. package/dist/ui/types.d.cts +52 -0
  220. package/dist/ui/types.d.cts.map +1 -0
  221. package/dist/ui/types.d.mts +52 -0
  222. package/dist/ui/types.d.mts.map +1 -0
  223. package/dist/ui/types.mjs +1 -0
  224. package/dist/utils/banner.cjs +24 -0
  225. package/dist/utils/banner.cjs.map +1 -0
  226. package/dist/utils/banner.mjs +23 -0
  227. package/dist/utils/banner.mjs.map +1 -0
  228. package/dist/utils/linkify.cjs +15 -0
  229. package/dist/utils/linkify.cjs.map +1 -0
  230. package/dist/utils/linkify.mjs +14 -0
  231. package/dist/utils/linkify.mjs.map +1 -0
  232. package/dist/utils/run.cjs +40 -0
  233. package/dist/utils/run.cjs.map +1 -0
  234. package/dist/utils/run.mjs +39 -0
  235. package/dist/utils/run.mjs.map +1 -0
  236. package/dist/utils/theme.cjs +44 -0
  237. package/dist/utils/theme.cjs.map +1 -0
  238. package/dist/utils/theme.mjs +37 -0
  239. package/dist/utils/theme.mjs.map +1 -0
  240. package/package.json +269 -80
  241. package/src/api-contract.ts +309 -0
  242. package/src/api.ts +181 -0
  243. package/src/app.ts +346 -0
  244. package/src/cli/catalog.ts +49 -0
  245. package/src/cli/help.ts +13 -0
  246. package/src/cli/init.ts +415 -0
  247. package/src/cli/parse.ts +130 -0
  248. package/src/cli/prompts.ts +64 -0
  249. package/src/cli.ts +203 -1507
  250. package/src/components/dev-view.tsx +104 -41
  251. package/src/components/streaming-view.ts +89 -22
  252. package/src/config.ts +462 -532
  253. package/src/contract.meta.ts +96 -0
  254. package/src/contract.ts +164 -561
  255. package/src/dev-logs.ts +85 -0
  256. package/src/dev-session.ts +318 -0
  257. package/src/fastkv.ts +153 -0
  258. package/src/federation.server.ts +43 -0
  259. package/src/host.ts +526 -0
  260. package/src/index.ts +6 -3
  261. package/src/integrity.ts +54 -0
  262. package/src/mf.ts +105 -0
  263. package/src/near-cli.ts +284 -0
  264. package/src/network.ts +3 -0
  265. package/src/orchestrator.ts +648 -0
  266. package/src/plugin.ts +1116 -2303
  267. package/src/process-registry.ts +154 -0
  268. package/src/scripts/sync-api-contract.ts +24 -0
  269. package/src/sdk.ts +14 -0
  270. package/src/shared.ts +206 -0
  271. package/src/types.ts +152 -206
  272. package/src/ui/head.ts +34 -27
  273. package/src/ui/index.ts +3 -3
  274. package/src/ui/metadata.ts +95 -0
  275. package/src/ui/router.ts +22 -6
  276. package/src/ui/runtime.ts +55 -6
  277. package/src/ui/types.ts +24 -11
  278. package/src/utils/banner.ts +10 -6
  279. package/src/utils/run.ts +26 -27
  280. package/src/utils/theme.ts +3 -66
  281. package/src/components/monitor-view.tsx +0 -475
  282. package/src/components/status-view.tsx +0 -173
  283. package/src/lib/env.ts +0 -109
  284. package/src/lib/near-cli.ts +0 -289
  285. package/src/lib/nova.ts +0 -266
  286. package/src/lib/orchestrator.ts +0 -276
  287. package/src/lib/process-registry.ts +0 -166
  288. package/src/lib/process.ts +0 -549
  289. package/src/lib/resource-monitor/assertions.ts +0 -234
  290. package/src/lib/resource-monitor/command.ts +0 -283
  291. package/src/lib/resource-monitor/diff.ts +0 -157
  292. package/src/lib/resource-monitor/errors.ts +0 -127
  293. package/src/lib/resource-monitor/index.ts +0 -305
  294. package/src/lib/resource-monitor/platform/darwin.ts +0 -306
  295. package/src/lib/resource-monitor/platform/index.ts +0 -35
  296. package/src/lib/resource-monitor/platform/linux.ts +0 -332
  297. package/src/lib/resource-monitor/platform/windows.ts +0 -298
  298. package/src/lib/resource-monitor/snapshot.ts +0 -217
  299. package/src/lib/resource-monitor/types.ts +0 -74
  300. package/src/lib/session-recorder/errors.ts +0 -102
  301. package/src/lib/session-recorder/flows/login.ts +0 -210
  302. package/src/lib/session-recorder/index.ts +0 -361
  303. package/src/lib/session-recorder/playwright.ts +0 -257
  304. package/src/lib/session-recorder/report.ts +0 -353
  305. package/src/lib/session-recorder/server.ts +0 -267
  306. package/src/lib/session-recorder/types.ts +0 -115
  307. package/src/lib/sync.ts +0 -1
  308. package/src/ui/files.ts +0 -134
@@ -1,298 +0,0 @@
1
- import { Effect, Layer } from "effect";
2
- import { execShellSafe, powershellSafe } from "../command";
3
- import type {
4
- MemoryInfo,
5
- PlatformOperations,
6
- PortInfo,
7
- ProcessInfo,
8
- } from "../types";
9
- import { PlatformService } from "../types";
10
-
11
- const getPortInfo = (
12
- ports: number[]
13
- ): Effect.Effect<Record<number, PortInfo>, never> =>
14
- Effect.gen(function* () {
15
- yield* Effect.logInfo(`[windows] Checking ${ports.length} ports`);
16
-
17
- const result: Record<number, PortInfo> = {};
18
- for (const port of ports) {
19
- result[port] = { port, pid: null, command: null, state: "FREE" };
20
- }
21
-
22
- if (ports.length === 0) return result;
23
-
24
- const output = yield* execShellSafe("netstat -ano -p TCP");
25
- if (!output) {
26
- yield* Effect.logDebug(
27
- "[windows] No netstat output, all ports appear free"
28
- );
29
- return result;
30
- }
31
-
32
- const lines = output.split("\n").filter(Boolean);
33
- yield* Effect.logDebug(`[windows] Parsing ${lines.length} netstat lines`);
34
-
35
- for (const line of lines) {
36
- if (!line.includes("LISTENING")) continue;
37
-
38
- const parts = line.trim().split(/\s+/);
39
- if (parts.length < 5) continue;
40
-
41
- const localAddr = parts[1];
42
- const portMatch = localAddr.match(/:(\d+)$/);
43
- if (!portMatch) continue;
44
-
45
- const port = parseInt(portMatch[1], 10);
46
- if (!ports.includes(port)) continue;
47
-
48
- const pid = parseInt(parts[4], 10);
49
-
50
- let command: string | null = null;
51
- if (pid) {
52
- const cmdOutput = yield* execShellSafe(
53
- `wmic process where ProcessId=${pid} get Name /format:list`
54
- );
55
- const nameMatch = cmdOutput.match(/Name=(.+)/);
56
- command = nameMatch ? nameMatch[1].trim() : null;
57
- }
58
-
59
- result[port] = {
60
- port,
61
- pid,
62
- command,
63
- state: "LISTEN",
64
- };
65
-
66
- yield* Effect.logDebug(
67
- `[windows] Port :${port} bound to PID ${pid} (${command})`
68
- );
69
- }
70
-
71
- const boundCount = Object.values(result).filter(
72
- (p) => p.state === "LISTEN"
73
- ).length;
74
- yield* Effect.logInfo(
75
- `[windows] Found ${boundCount}/${ports.length} ports in use`
76
- );
77
-
78
- return result;
79
- });
80
-
81
- const getProcessTree = (
82
- rootPids: number[]
83
- ): Effect.Effect<ProcessInfo[], never> =>
84
- Effect.gen(function* () {
85
- yield* Effect.logInfo(
86
- `[windows] Building process tree for ${rootPids.length} root PIDs`
87
- );
88
-
89
- const processes: ProcessInfo[] = [];
90
- const visited = new Set<number>();
91
-
92
- const getProcess = (
93
- pid: number
94
- ): Effect.Effect<ProcessInfo | null, never> =>
95
- Effect.gen(function* () {
96
- if (visited.has(pid)) return null;
97
- visited.add(pid);
98
-
99
- const output = yield* execShellSafe(
100
- `wmic process where ProcessId=${pid} get ProcessId,ParentProcessId,WorkingSetSize,Name,CommandLine /format:csv`
101
- );
102
- const lines = output
103
- .split("\n")
104
- .filter((l) => l.trim() && !l.startsWith("Node"));
105
- if (lines.length === 0) return null;
106
-
107
- const parts = lines[0].split(",");
108
- if (parts.length < 5) return null;
109
-
110
- const cmdLine = parts[1] || "";
111
- const name = parts[2] || "";
112
- const ppid = parseInt(parts[3], 10);
113
- const procId = parseInt(parts[4], 10);
114
- const rss = parseInt(parts[5], 10) || 0;
115
-
116
- yield* Effect.logDebug(
117
- `[windows] Process ${pid}: ${name} (RSS: ${(rss / 1024).toFixed(0)}KB)`
118
- );
119
-
120
- return {
121
- pid: procId,
122
- ppid,
123
- command: name,
124
- args: cmdLine.split(/\s+/).slice(1),
125
- rss,
126
- children: [],
127
- };
128
- });
129
-
130
- const getChildren = (pid: number): Effect.Effect<number[], never> =>
131
- Effect.gen(function* () {
132
- const output = yield* execShellSafe(
133
- `wmic process where ParentProcessId=${pid} get ProcessId /format:list`
134
- );
135
- const matches = output.match(/ProcessId=(\d+)/g);
136
- if (!matches) return [];
137
-
138
- const children = matches.map((m) =>
139
- parseInt(m.replace("ProcessId=", ""), 10)
140
- );
141
-
142
- if (children.length > 0) {
143
- yield* Effect.logDebug(
144
- `[windows] PID ${pid} has ${children.length} children: ${children.join(", ")}`
145
- );
146
- }
147
-
148
- return children;
149
- });
150
-
151
- const traverse = (pid: number): Effect.Effect<void, never> =>
152
- Effect.gen(function* () {
153
- const proc = yield* getProcess(pid);
154
- if (!proc) return;
155
-
156
- const children = yield* getChildren(pid);
157
- proc.children = children;
158
- processes.push(proc);
159
-
160
- for (const child of children) {
161
- yield* traverse(child);
162
- }
163
- });
164
-
165
- for (const pid of rootPids) {
166
- yield* traverse(pid);
167
- }
168
-
169
- yield* Effect.logInfo(
170
- `[windows] Process tree contains ${processes.length} processes`
171
- );
172
-
173
- return processes;
174
- });
175
-
176
- const getMemoryInfo = (): Effect.Effect<MemoryInfo, never> =>
177
- Effect.gen(function* () {
178
- yield* Effect.logDebug("[windows] Getting memory info");
179
-
180
- const script = `
181
- $os = Get-CimInstance Win32_OperatingSystem
182
- $total = $os.TotalVisibleMemorySize * 1024
183
- $free = $os.FreePhysicalMemory * 1024
184
- Write-Output "$total,$free"
185
- `;
186
- const output = yield* powershellSafe(script);
187
-
188
- if (!output) {
189
- yield* Effect.logWarning("[windows] Could not get memory info");
190
- return { total: 0, used: 0, free: 0, processRss: 0 };
191
- }
192
-
193
- const [totalStr, freeStr] = output.split(",");
194
- const total = parseInt(totalStr, 10) || 0;
195
- const free = parseInt(freeStr, 10) || 0;
196
-
197
- const totalMB = (total / 1024 / 1024).toFixed(0);
198
- const usedMB = ((total - free) / 1024 / 1024).toFixed(0);
199
- yield* Effect.logDebug(
200
- `[windows] Memory: ${usedMB}MB used / ${totalMB}MB total`
201
- );
202
-
203
- return {
204
- total,
205
- used: total - free,
206
- free,
207
- processRss: 0,
208
- };
209
- });
210
-
211
- const getAllProcesses = (): Effect.Effect<ProcessInfo[], never> =>
212
- Effect.gen(function* () {
213
- yield* Effect.logDebug("[windows] Getting all processes");
214
-
215
- const processes: ProcessInfo[] = [];
216
-
217
- const output = yield* execShellSafe(
218
- "wmic process get ProcessId,ParentProcessId,WorkingSetSize,Name /format:csv"
219
- );
220
- const lines = output
221
- .split("\n")
222
- .filter((l) => l.trim() && !l.startsWith("Node"));
223
-
224
- for (const line of lines) {
225
- const parts = line.split(",");
226
- if (parts.length < 4) continue;
227
-
228
- const name = parts[1] || "";
229
- const ppid = parseInt(parts[2], 10);
230
- const pid = parseInt(parts[3], 10);
231
- const rss = parseInt(parts[4], 10) || 0;
232
-
233
- if (isNaN(pid)) continue;
234
-
235
- processes.push({
236
- pid,
237
- ppid: isNaN(ppid) ? 0 : ppid,
238
- command: name,
239
- args: [],
240
- rss,
241
- children: [],
242
- });
243
- }
244
-
245
- yield* Effect.logDebug(
246
- `[windows] Found ${processes.length} total processes`
247
- );
248
-
249
- return processes;
250
- });
251
-
252
- const findChildProcesses = (pid: number): Effect.Effect<number[], never> =>
253
- Effect.gen(function* () {
254
- yield* Effect.logDebug(`[windows] Finding all children of PID ${pid}`);
255
-
256
- const children: number[] = [];
257
- const visited = new Set<number>();
258
-
259
- const recurse = (parentPid: number): Effect.Effect<void, never> =>
260
- Effect.gen(function* () {
261
- if (visited.has(parentPid)) return;
262
- visited.add(parentPid);
263
-
264
- const output = yield* execShellSafe(
265
- `wmic process where ParentProcessId=${parentPid} get ProcessId /format:list`
266
- );
267
- const matches = output.match(/ProcessId=(\d+)/g);
268
- if (!matches) return;
269
-
270
- for (const match of matches) {
271
- const childPid = parseInt(match.replace("ProcessId=", ""), 10);
272
- if (!isNaN(childPid)) {
273
- children.push(childPid);
274
- yield* recurse(childPid);
275
- }
276
- }
277
- });
278
-
279
- yield* recurse(pid);
280
-
281
- if (children.length > 0) {
282
- yield* Effect.logDebug(
283
- `[windows] PID ${pid} has ${children.length} descendants`
284
- );
285
- }
286
-
287
- return children;
288
- });
289
-
290
- const windowsOperations: PlatformOperations = {
291
- getPortInfo,
292
- getProcessTree,
293
- getMemoryInfo,
294
- getAllProcesses,
295
- findChildProcesses,
296
- };
297
-
298
- export const WindowsLayer = Layer.succeed(PlatformService, windowsOperations);
@@ -1,217 +0,0 @@
1
- import { Effect } from "effect";
2
- import { loadConfig } from "../../config";
3
- import { PlatformService, withPlatform } from "./platform";
4
- import type { MonitorConfig, ProcessInfo, Snapshot } from "./types";
5
-
6
- export const getPortsToMonitor = (
7
- config?: MonitorConfig,
8
- ): Effect.Effect<number[]> =>
9
- Effect.gen(function* () {
10
- if (config?.ports && config.ports.length > 0) {
11
- yield* Effect.logDebug(
12
- `Using configured ports: ${config.ports.join(", ")}`,
13
- );
14
- return config.ports;
15
- }
16
-
17
- // Load config and get ports from runtime config
18
- const result = yield* Effect.tryPromise({
19
- try: () => loadConfig({ path: config?.configPath }),
20
- catch: () => new Error("Config not found"),
21
- }).pipe(Effect.catchAll(() => Effect.succeed(null)));
22
-
23
- if (result?.runtime) {
24
- const ports = [
25
- result.runtime.hostUrl,
26
- result.runtime.ui.url,
27
- result.runtime.api.url,
28
- ]
29
- .map((url) => {
30
- try {
31
- return parseInt(new URL(url).port || "0");
32
- } catch {
33
- return 0;
34
- }
35
- })
36
- .filter((p) => p > 0);
37
- return ports;
38
- }
39
-
40
- return [3000, 3002, 3014];
41
- });
42
-
43
- export const getConfigPathSafe = (
44
- config?: MonitorConfig,
45
- ): Effect.Effect<string | null> =>
46
- Effect.tryPromise({
47
- try: async () => {
48
- const result = await loadConfig({ path: config?.configPath });
49
- return result?.source.path ?? null;
50
- },
51
- catch: () => new Error("Config not found"),
52
- }).pipe(Effect.catchAll(() => Effect.succeed(null)));
53
-
54
- export const createSnapshot = (
55
- config?: MonitorConfig,
56
- ): Effect.Effect<Snapshot, never, PlatformService> =>
57
- Effect.gen(function* () {
58
- yield* Effect.logInfo("Creating system snapshot");
59
-
60
- const platform = yield* PlatformService;
61
- const ports = yield* getPortsToMonitor(config);
62
- const configPath = yield* getConfigPathSafe(config);
63
-
64
- yield* Effect.logDebug(`Monitoring ports: ${ports.join(", ")}`);
65
-
66
- const portInfo = yield* platform.getPortInfo(ports);
67
- const boundPorts = Object.values(portInfo).filter(
68
- (p) => p.state !== "FREE",
69
- );
70
-
71
- yield* Effect.logInfo(`Found ${boundPorts.length} bound ports`);
72
-
73
- const rootPids = boundPorts
74
- .map((p) => p.pid)
75
- .filter((pid): pid is number => pid !== null);
76
-
77
- const processes =
78
- rootPids.length > 0 ? yield* platform.getProcessTree(rootPids) : [];
79
-
80
- yield* Effect.logInfo(`Tracked ${processes.length} processes in tree`);
81
-
82
- const memory = yield* platform.getMemoryInfo();
83
-
84
- const totalRss = processes.reduce((sum, p) => sum + p.rss, 0);
85
- memory.processRss = totalRss;
86
-
87
- yield* Effect.logDebug(
88
- `Total process RSS: ${(totalRss / 1024 / 1024).toFixed(1)}MB`,
89
- );
90
-
91
- const snapshot: Snapshot = {
92
- timestamp: Date.now(),
93
- configPath,
94
- ports: portInfo,
95
- processes,
96
- memory,
97
- platform: process.platform,
98
- };
99
-
100
- yield* Effect.logInfo(
101
- `Snapshot created at ${new Date(snapshot.timestamp).toISOString()}`,
102
- );
103
-
104
- return snapshot;
105
- });
106
-
107
- export const createSnapshotWithPlatform = (
108
- config?: MonitorConfig,
109
- ): Effect.Effect<Snapshot> => withPlatform(createSnapshot(config));
110
-
111
- export const findProcessesByPattern = (
112
- patterns: string[],
113
- ): Effect.Effect<ProcessInfo[], never, PlatformService> =>
114
- Effect.gen(function* () {
115
- yield* Effect.logDebug(
116
- `Finding processes matching: ${patterns.join(", ")}`,
117
- );
118
-
119
- const platform = yield* PlatformService;
120
- const allProcesses = yield* platform.getAllProcesses();
121
-
122
- const matched = allProcesses.filter((proc) =>
123
- patterns.some((pattern) =>
124
- proc.command.toLowerCase().includes(pattern.toLowerCase()),
125
- ),
126
- );
127
-
128
- yield* Effect.logInfo(
129
- `Found ${matched.length} processes matching patterns`,
130
- );
131
-
132
- return matched;
133
- });
134
-
135
- export const findBosProcesses = (): Effect.Effect<
136
- ProcessInfo[],
137
- never,
138
- PlatformService
139
- > => {
140
- const patterns = ["bun", "rspack", "rsbuild", "esbuild", "webpack", "node"];
141
- return findProcessesByPattern(patterns);
142
- };
143
-
144
- export const isProcessAliveSync = (pid: number): boolean => {
145
- try {
146
- process.kill(pid, 0);
147
- return true;
148
- } catch {
149
- return false;
150
- }
151
- };
152
-
153
- export const isProcessAlive = (pid: number): Effect.Effect<boolean> =>
154
- Effect.sync(() => isProcessAliveSync(pid));
155
-
156
- export const waitForProcessDeath = (
157
- pid: number,
158
- timeoutMs = 5000,
159
- ): Effect.Effect<boolean> =>
160
- Effect.gen(function* () {
161
- yield* Effect.logDebug(
162
- `Waiting for PID ${pid} to die (timeout: ${timeoutMs}ms)`,
163
- );
164
- const start = Date.now();
165
-
166
- while (Date.now() - start < timeoutMs) {
167
- const alive = yield* isProcessAlive(pid);
168
- if (!alive) {
169
- yield* Effect.logDebug(`PID ${pid} is dead`);
170
- return true;
171
- }
172
- yield* Effect.sleep("100 millis");
173
- }
174
-
175
- const finalAlive = yield* isProcessAlive(pid);
176
- if (finalAlive) {
177
- yield* Effect.logWarning(`PID ${pid} still alive after ${timeoutMs}ms`);
178
- }
179
- return !finalAlive;
180
- });
181
-
182
- export const waitForPortFree = (
183
- port: number,
184
- timeoutMs = 5000,
185
- ): Effect.Effect<boolean, never, PlatformService> =>
186
- Effect.gen(function* () {
187
- yield* Effect.logDebug(
188
- `Waiting for port :${port} to be free (timeout: ${timeoutMs}ms)`,
189
- );
190
- const platform = yield* PlatformService;
191
- const start = Date.now();
192
-
193
- while (Date.now() - start < timeoutMs) {
194
- const portInfo = yield* platform.getPortInfo([port]);
195
- if (portInfo[port].state === "FREE") {
196
- yield* Effect.logDebug(`Port :${port} is now free`);
197
- return true;
198
- }
199
- yield* Effect.sleep("100 millis");
200
- }
201
-
202
- const finalPortInfo = yield* platform.getPortInfo([port]);
203
- const isFree = finalPortInfo[port].state === "FREE";
204
-
205
- if (!isFree) {
206
- yield* Effect.logWarning(
207
- `Port :${port} still bound after ${timeoutMs}ms`,
208
- );
209
- }
210
-
211
- return isFree;
212
- });
213
-
214
- export const waitForPortFreeWithPlatform = (
215
- port: number,
216
- timeoutMs = 5000,
217
- ): Effect.Effect<boolean> => withPlatform(waitForPortFree(port, timeoutMs));
@@ -1,74 +0,0 @@
1
- import { Context, Effect } from "effect";
2
-
3
- export interface PortInfo {
4
- port: number;
5
- pid: number | null;
6
- command: string | null;
7
- state: "LISTEN" | "ESTABLISHED" | "TIME_WAIT" | "FREE";
8
- name?: string;
9
- }
10
-
11
- export interface ProcessInfo {
12
- pid: number;
13
- ppid: number;
14
- command: string;
15
- args: string[];
16
- rss: number;
17
- children: number[];
18
- startTime?: number;
19
- }
20
-
21
- export interface MemoryInfo {
22
- total: number;
23
- used: number;
24
- free: number;
25
- processRss: number;
26
- }
27
-
28
- export interface Snapshot {
29
- timestamp: number;
30
- configPath: string | null;
31
- ports: Record<number, PortInfo>;
32
- processes: ProcessInfo[];
33
- memory: MemoryInfo;
34
- platform: NodeJS.Platform;
35
- }
36
-
37
- export interface SnapshotDiff {
38
- from: Snapshot;
39
- to: Snapshot;
40
- orphanedProcesses: ProcessInfo[];
41
- stillBoundPorts: PortInfo[];
42
- freedPorts: number[];
43
- memoryDeltaBytes: number;
44
- newProcesses: ProcessInfo[];
45
- killedProcesses: ProcessInfo[];
46
- }
47
-
48
- export interface MonitorConfig {
49
- ports?: number[];
50
- processPatterns?: string[];
51
- refreshInterval?: number;
52
- configPath?: string;
53
- }
54
-
55
- export interface PlatformOperations {
56
- readonly getPortInfo: (
57
- ports: number[]
58
- ) => Effect.Effect<Record<number, PortInfo>, never>;
59
-
60
- readonly getProcessTree: (
61
- rootPids: number[]
62
- ) => Effect.Effect<ProcessInfo[], never>;
63
-
64
- readonly getMemoryInfo: () => Effect.Effect<MemoryInfo, never>;
65
-
66
- readonly getAllProcesses: () => Effect.Effect<ProcessInfo[], never>;
67
-
68
- readonly findChildProcesses: (pid: number) => Effect.Effect<number[], never>;
69
- }
70
-
71
- export class PlatformService extends Context.Tag("PlatformService")<
72
- PlatformService,
73
- PlatformOperations
74
- >() {}
@@ -1,102 +0,0 @@
1
- import { Data } from "effect";
2
-
3
- export class SessionTimeout extends Data.TaggedError("SessionTimeout")<{
4
- readonly timeoutMs: number;
5
- readonly elapsedMs: number;
6
- }> {
7
- get message() {
8
- return `Session timed out after ${this.elapsedMs}ms (limit: ${this.timeoutMs}ms)`;
9
- }
10
- }
11
-
12
- export class BrowserLaunchFailed extends Data.TaggedError("BrowserLaunchFailed")<{
13
- readonly reason: string;
14
- readonly headless: boolean;
15
- }> {
16
- get message() {
17
- return `Failed to launch browser (headless: ${this.headless}): ${this.reason}`;
18
- }
19
- }
20
-
21
- export class ServerStartFailed extends Data.TaggedError("ServerStartFailed")<{
22
- readonly server: string;
23
- readonly port: number;
24
- readonly reason: string;
25
- }> {
26
- get message() {
27
- return `Failed to start ${this.server} on port ${this.port}: ${this.reason}`;
28
- }
29
- }
30
-
31
- export class ServerNotReady extends Data.TaggedError("ServerNotReady")<{
32
- readonly servers: string[];
33
- readonly timeoutMs: number;
34
- }> {
35
- get message() {
36
- return `Servers not ready after ${this.timeoutMs}ms: ${this.servers.join(", ")}`;
37
- }
38
- }
39
-
40
- export class FlowExecutionFailed extends Data.TaggedError("FlowExecutionFailed")<{
41
- readonly flowName: string;
42
- readonly step: string;
43
- readonly reason: string;
44
- }> {
45
- get message() {
46
- return `Flow "${this.flowName}" failed at step "${this.step}": ${this.reason}`;
47
- }
48
- }
49
-
50
- export class SnapshotFailed extends Data.TaggedError("SnapshotFailed")<{
51
- readonly reason: string;
52
- }> {
53
- get message() {
54
- return `Failed to capture snapshot: ${this.reason}`;
55
- }
56
- }
57
-
58
- export class ExportFailed extends Data.TaggedError("ExportFailed")<{
59
- readonly path: string;
60
- readonly reason: string;
61
- }> {
62
- get message() {
63
- return `Failed to export session to ${this.path}: ${this.reason}`;
64
- }
65
- }
66
-
67
- export class BrowserMetricsFailed extends Data.TaggedError("BrowserMetricsFailed")<{
68
- readonly reason: string;
69
- }> {
70
- get message() {
71
- return `Failed to collect browser metrics: ${this.reason}`;
72
- }
73
- }
74
-
75
- export class PopupNotDetected extends Data.TaggedError("PopupNotDetected")<{
76
- readonly timeoutMs: number;
77
- }> {
78
- get message() {
79
- return `Popup window not detected within ${this.timeoutMs}ms`;
80
- }
81
- }
82
-
83
- export class AuthenticationFailed extends Data.TaggedError("AuthenticationFailed")<{
84
- readonly step: string;
85
- readonly reason: string;
86
- }> {
87
- get message() {
88
- return `Authentication failed at "${this.step}": ${this.reason}`;
89
- }
90
- }
91
-
92
- export type SessionRecorderError =
93
- | SessionTimeout
94
- | BrowserLaunchFailed
95
- | ServerStartFailed
96
- | ServerNotReady
97
- | FlowExecutionFailed
98
- | SnapshotFailed
99
- | ExportFailed
100
- | BrowserMetricsFailed
101
- | PopupNotDetected
102
- | AuthenticationFailed;