@monoes/monobrowse 1.0.9 → 1.0.12

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 (221) hide show
  1. package/README.md +1 -1
  2. package/dist/src/__tests__/adapters.test.js +5 -2
  3. package/dist/src/__tests__/adapters.test.js.map +1 -1
  4. package/dist/src/__tests__/batch-eval-parsing.test.js +4 -2
  5. package/dist/src/__tests__/batch-eval-parsing.test.js.map +1 -1
  6. package/dist/src/__tests__/box-model.test.js +9 -5
  7. package/dist/src/__tests__/box-model.test.js.map +1 -1
  8. package/dist/src/__tests__/browser-launch.test.d.ts +10 -0
  9. package/dist/src/__tests__/browser-launch.test.d.ts.map +1 -1
  10. package/dist/src/__tests__/browser-launch.test.js +17 -10
  11. package/dist/src/__tests__/browser-launch.test.js.map +1 -1
  12. package/dist/src/__tests__/cdp-client.test.js +9 -3
  13. package/dist/src/__tests__/cdp-client.test.js.map +1 -1
  14. package/dist/src/__tests__/close-browser.test.d.ts +13 -0
  15. package/dist/src/__tests__/close-browser.test.d.ts.map +1 -1
  16. package/dist/src/__tests__/close-browser.test.js +40 -26
  17. package/dist/src/__tests__/close-browser.test.js.map +1 -1
  18. package/dist/src/__tests__/console-log.test.js +17 -6
  19. package/dist/src/__tests__/console-log.test.js.map +1 -1
  20. package/dist/src/__tests__/find.test.js +26 -6
  21. package/dist/src/__tests__/find.test.js.map +1 -1
  22. package/dist/src/__tests__/frame-command.test.js +9 -3
  23. package/dist/src/__tests__/frame-command.test.js.map +1 -1
  24. package/dist/src/__tests__/open-url-navigate-error.test.js +1 -3
  25. package/dist/src/__tests__/open-url-navigate-error.test.js.map +1 -1
  26. package/dist/src/__tests__/output.test.js +1 -1
  27. package/dist/src/__tests__/output.test.js.map +1 -1
  28. package/dist/src/__tests__/reap-idle-browser.test.d.ts +15 -0
  29. package/dist/src/__tests__/reap-idle-browser.test.d.ts.map +1 -0
  30. package/dist/src/__tests__/reap-idle-browser.test.js +238 -0
  31. package/dist/src/__tests__/reap-idle-browser.test.js.map +1 -0
  32. package/dist/src/__tests__/ref-cache.test.js +18 -10
  33. package/dist/src/__tests__/ref-cache.test.js.map +1 -1
  34. package/dist/src/__tests__/session-state.test.d.ts +8 -0
  35. package/dist/src/__tests__/session-state.test.d.ts.map +1 -1
  36. package/dist/src/__tests__/session-state.test.js +10 -10
  37. package/dist/src/__tests__/session-state.test.js.map +1 -1
  38. package/dist/src/__tests__/snapshot.test.js +45 -15
  39. package/dist/src/__tests__/snapshot.test.js.map +1 -1
  40. package/dist/src/__tests__/storage-eval.test.js +14 -6
  41. package/dist/src/__tests__/storage-eval.test.js.map +1 -1
  42. package/dist/src/__tests__/tabs.test.js +25 -9
  43. package/dist/src/__tests__/tabs.test.js.map +1 -1
  44. package/dist/src/browser/action-builder/analyzer.d.ts +1 -1
  45. package/dist/src/browser/action-builder/analyzer.d.ts.map +1 -1
  46. package/dist/src/browser/action-builder/analyzer.js +25 -9
  47. package/dist/src/browser/action-builder/analyzer.js.map +1 -1
  48. package/dist/src/browser/action-builder/types.d.ts.map +1 -1
  49. package/dist/src/browser/actions.d.ts +1 -1
  50. package/dist/src/browser/actions.d.ts.map +1 -1
  51. package/dist/src/browser/actions.js +16 -6
  52. package/dist/src/browser/actions.js.map +1 -1
  53. package/dist/src/browser/adapters/gemini.d.ts.map +1 -1
  54. package/dist/src/browser/adapters/gemini.js.map +1 -1
  55. package/dist/src/browser/adapters/google.d.ts.map +1 -1
  56. package/dist/src/browser/adapters/google.js.map +1 -1
  57. package/dist/src/browser/adapters/index.d.ts.map +1 -1
  58. package/dist/src/browser/adapters/index.js +3 -3
  59. package/dist/src/browser/adapters/index.js.map +1 -1
  60. package/dist/src/browser/adapters/instagram.d.ts.map +1 -1
  61. package/dist/src/browser/adapters/instagram.js.map +1 -1
  62. package/dist/src/browser/adapters/linkedin.d.ts.map +1 -1
  63. package/dist/src/browser/adapters/linkedin.js.map +1 -1
  64. package/dist/src/browser/adapters/microsoft.d.ts.map +1 -1
  65. package/dist/src/browser/adapters/microsoft.js.map +1 -1
  66. package/dist/src/browser/adapters/x.d.ts.map +1 -1
  67. package/dist/src/browser/adapters/x.js.map +1 -1
  68. package/dist/src/browser/browser.d.ts +30 -0
  69. package/dist/src/browser/browser.d.ts.map +1 -1
  70. package/dist/src/browser/browser.js +122 -15
  71. package/dist/src/browser/browser.js.map +1 -1
  72. package/dist/src/browser/cdp.d.ts.map +1 -1
  73. package/dist/src/browser/cdp.js +21 -8
  74. package/dist/src/browser/cdp.js.map +1 -1
  75. package/dist/src/browser/console-log.d.ts.map +1 -1
  76. package/dist/src/browser/console-log.js +2 -2
  77. package/dist/src/browser/console-log.js.map +1 -1
  78. package/dist/src/browser/dashboard/server.d.ts.map +1 -1
  79. package/dist/src/browser/dashboard/server.js +29 -19
  80. package/dist/src/browser/dashboard/server.js.map +1 -1
  81. package/dist/src/browser/dashboard/ui.html +153 -165
  82. package/dist/src/browser/dialog.d.ts.map +1 -1
  83. package/dist/src/browser/dialog.js +3 -1
  84. package/dist/src/browser/dialog.js.map +1 -1
  85. package/dist/src/browser/emulation.d.ts.map +1 -1
  86. package/dist/src/browser/emulation.js +21 -6
  87. package/dist/src/browser/emulation.js.map +1 -1
  88. package/dist/src/browser/find.d.ts +4 -4
  89. package/dist/src/browser/find.d.ts.map +1 -1
  90. package/dist/src/browser/find.js +14 -6
  91. package/dist/src/browser/find.js.map +1 -1
  92. package/dist/src/browser/har.d.ts.map +1 -1
  93. package/dist/src/browser/har.js +14 -7
  94. package/dist/src/browser/har.js.map +1 -1
  95. package/dist/src/browser/index.d.ts +16 -16
  96. package/dist/src/browser/index.d.ts.map +1 -1
  97. package/dist/src/browser/index.js +16 -16
  98. package/dist/src/browser/index.js.map +1 -1
  99. package/dist/src/browser/network.d.ts.map +1 -1
  100. package/dist/src/browser/network.js +14 -4
  101. package/dist/src/browser/network.js.map +1 -1
  102. package/dist/src/browser/pdf.d.ts.map +1 -1
  103. package/dist/src/browser/pdf.js +3 -3
  104. package/dist/src/browser/pdf.js.map +1 -1
  105. package/dist/src/browser/profiler.d.ts.map +1 -1
  106. package/dist/src/browser/profiler.js +10 -5
  107. package/dist/src/browser/profiler.js.map +1 -1
  108. package/dist/src/browser/record.d.ts +1 -1
  109. package/dist/src/browser/record.d.ts.map +1 -1
  110. package/dist/src/browser/record.js +18 -7
  111. package/dist/src/browser/record.js.map +1 -1
  112. package/dist/src/browser/ref-cache.d.ts.map +1 -1
  113. package/dist/src/browser/ref-cache.js +9 -4
  114. package/dist/src/browser/ref-cache.js.map +1 -1
  115. package/dist/src/browser/screenshot.d.ts.map +1 -1
  116. package/dist/src/browser/screenshot.js +11 -7
  117. package/dist/src/browser/screenshot.js.map +1 -1
  118. package/dist/src/browser/session.d.ts +1 -1
  119. package/dist/src/browser/session.d.ts.map +1 -1
  120. package/dist/src/browser/session.js +27 -8
  121. package/dist/src/browser/session.js.map +1 -1
  122. package/dist/src/browser/snapshot.d.ts +1 -1
  123. package/dist/src/browser/snapshot.d.ts.map +1 -1
  124. package/dist/src/browser/snapshot.js +8 -4
  125. package/dist/src/browser/snapshot.js.map +1 -1
  126. package/dist/src/browser/storage.d.ts.map +1 -1
  127. package/dist/src/browser/storage.js.map +1 -1
  128. package/dist/src/browser/tabs.d.ts.map +1 -1
  129. package/dist/src/browser/tabs.js +9 -3
  130. package/dist/src/browser/tabs.js.map +1 -1
  131. package/dist/src/browser/trace.d.ts.map +1 -1
  132. package/dist/src/browser/trace.js +3 -3
  133. package/dist/src/browser/trace.js.map +1 -1
  134. package/dist/src/browser/types.d.ts.map +1 -1
  135. package/dist/src/browser/types.js +23 -4
  136. package/dist/src/browser/types.js.map +1 -1
  137. package/dist/src/browser/vitals.d.ts.map +1 -1
  138. package/dist/src/browser/vitals.js +1 -1
  139. package/dist/src/browser/vitals.js.map +1 -1
  140. package/dist/src/browser/wait.d.ts.map +1 -1
  141. package/dist/src/browser/wait.js +11 -5
  142. package/dist/src/browser/wait.js.map +1 -1
  143. package/dist/src/cli/action.d.ts.map +1 -1
  144. package/dist/src/cli/action.js +14 -11
  145. package/dist/src/cli/action.js.map +1 -1
  146. package/dist/src/cli/commands.d.ts.map +1 -1
  147. package/dist/src/cli/commands.js +453 -159
  148. package/dist/src/cli/commands.js.map +1 -1
  149. package/dist/src/cli/output.js +5 -5
  150. package/dist/src/cli/output.js.map +1 -1
  151. package/dist/src/cli/platform.d.ts.map +1 -1
  152. package/dist/src/cli/platform.js +15 -11
  153. package/dist/src/cli/platform.js.map +1 -1
  154. package/dist/src/cli/types.d.ts +1 -1
  155. package/dist/src/cli/types.d.ts.map +1 -1
  156. package/dist/src/cli.js +21 -9
  157. package/dist/src/cli.js.map +1 -1
  158. package/dist/src/index.d.ts +2 -2
  159. package/dist/src/index.d.ts.map +1 -1
  160. package/dist/src/index.js +2 -2
  161. package/dist/src/index.js.map +1 -1
  162. package/dist/tsconfig.tsbuildinfo +1 -1
  163. package/package.json +2 -2
  164. package/src/__tests__/adapters.test.ts +15 -8
  165. package/src/__tests__/batch-eval-parsing.test.ts +4 -2
  166. package/src/__tests__/box-model.test.ts +9 -5
  167. package/src/__tests__/browser-launch.test.ts +26 -15
  168. package/src/__tests__/cdp-client.test.ts +25 -9
  169. package/src/__tests__/close-browser.test.ts +49 -26
  170. package/src/__tests__/console-log.test.ts +36 -13
  171. package/src/__tests__/find.test.ts +58 -20
  172. package/src/__tests__/frame-command.test.ts +12 -6
  173. package/src/__tests__/open-url-navigate-error.test.ts +2 -4
  174. package/src/__tests__/output.test.ts +1 -1
  175. package/src/__tests__/reap-idle-browser.test.ts +276 -0
  176. package/src/__tests__/ref-cache.test.ts +25 -12
  177. package/src/__tests__/session-state.test.ts +40 -28
  178. package/src/__tests__/snapshot.test.ts +61 -22
  179. package/src/__tests__/storage-eval.test.ts +30 -16
  180. package/src/__tests__/tabs.test.ts +26 -10
  181. package/src/browser/action-builder/analyzer.ts +39 -15
  182. package/src/browser/action-builder/types.ts +45 -8
  183. package/src/browser/actions.ts +288 -123
  184. package/src/browser/adapters/gemini.ts +7 -3
  185. package/src/browser/adapters/google.ts +5 -3
  186. package/src/browser/adapters/index.ts +5 -4
  187. package/src/browser/adapters/instagram.ts +4 -2
  188. package/src/browser/adapters/linkedin.ts +4 -2
  189. package/src/browser/adapters/microsoft.ts +9 -5
  190. package/src/browser/adapters/x.ts +7 -3
  191. package/src/browser/browser.ts +188 -42
  192. package/src/browser/cdp.ts +43 -11
  193. package/src/browser/console-log.ts +24 -7
  194. package/src/browser/dashboard/server.ts +44 -25
  195. package/src/browser/dashboard/ui.html +153 -165
  196. package/src/browser/dialog.ts +25 -8
  197. package/src/browser/emulation.ts +86 -36
  198. package/src/browser/find.ts +110 -47
  199. package/src/browser/har.ts +58 -26
  200. package/src/browser/index.ts +16 -16
  201. package/src/browser/network.ts +147 -46
  202. package/src/browser/pdf.ts +4 -4
  203. package/src/browser/profiler.ts +23 -10
  204. package/src/browser/record.ts +38 -19
  205. package/src/browser/ref-cache.ts +38 -17
  206. package/src/browser/screenshot.ts +58 -32
  207. package/src/browser/session.ts +51 -18
  208. package/src/browser/snapshot.ts +34 -20
  209. package/src/browser/storage.ts +73 -17
  210. package/src/browser/tabs.ts +29 -17
  211. package/src/browser/trace.ts +14 -10
  212. package/src/browser/types.ts +23 -4
  213. package/src/browser/vitals.ts +33 -16
  214. package/src/browser/wait.ts +47 -21
  215. package/src/cli/action.ts +52 -21
  216. package/src/cli/commands.ts +1093 -385
  217. package/src/cli/output.ts +5 -5
  218. package/src/cli/platform.ts +44 -23
  219. package/src/cli/types.ts +1 -1
  220. package/src/cli.ts +34 -18
  221. package/src/index.ts +2 -2
@@ -33,7 +33,10 @@ function errorsFor(sessionId: string): PageError[] {
33
33
  export function setupConsoleCapture(client: CdpClient, sessionId: string): void {
34
34
  // Remove stale listeners from any prior connection on this sessionId
35
35
  const prevOffs = _consoleListeners.get(sessionId);
36
- if (prevOffs) { for (const off of prevOffs) off(); _consoleListeners.delete(sessionId); }
36
+ if (prevOffs) {
37
+ for (const off of prevOffs) off();
38
+ _consoleListeners.delete(sessionId);
39
+ }
37
40
 
38
41
  _consoleMessages.set(sessionId, []);
39
42
  _pageErrors.set(sessionId, []);
@@ -52,7 +55,12 @@ export function setupConsoleCapture(client: CdpClient, sessionId: string): void
52
55
 
53
56
  const off2 = client.on('Log.entryAdded', (params, sid) => {
54
57
  if (sid !== sessionId) return;
55
- const entry = params.entry as { level?: string; text?: string; url?: string; lineNumber?: number };
58
+ const entry = params.entry as {
59
+ level?: string;
60
+ text?: string;
61
+ url?: string;
62
+ lineNumber?: number;
63
+ };
56
64
  // CDP uses 'warning' but ConsoleMessage type uses 'warn'
57
65
  const rawLevel = entry.level === 'warning' ? 'warn' : entry.level;
58
66
  messagesFor(sessionId).push({
@@ -92,29 +100,38 @@ export async function enableConsoleCapture(client: CdpClient, sessionId: string)
92
100
  }
93
101
 
94
102
  export function getConsoleMessages(sessionId?: string): ConsoleMessage[] {
95
- if (sessionId) return [...(messagesFor(sessionId))];
103
+ if (sessionId) return [...messagesFor(sessionId)];
96
104
  // Fallback: return all messages across all sessions (legacy callers)
97
105
  return [..._consoleMessages.values()].flat();
98
106
  }
99
107
 
100
108
  export function clearConsoleMessages(sessionId?: string): void {
101
- if (sessionId) { _consoleMessages.set(sessionId, []); return; }
109
+ if (sessionId) {
110
+ _consoleMessages.set(sessionId, []);
111
+ return;
112
+ }
102
113
  _consoleMessages.clear();
103
114
  }
104
115
 
105
116
  export function getPageErrors(sessionId?: string): PageError[] {
106
- if (sessionId) return [...(errorsFor(sessionId))];
117
+ if (sessionId) return [...errorsFor(sessionId)];
107
118
  return [..._pageErrors.values()].flat();
108
119
  }
109
120
 
110
121
  export function clearPageErrors(sessionId?: string): void {
111
- if (sessionId) { _pageErrors.set(sessionId, []); return; }
122
+ if (sessionId) {
123
+ _pageErrors.set(sessionId, []);
124
+ return;
125
+ }
112
126
  _pageErrors.clear();
113
127
  }
114
128
 
115
129
  export function teardownConsoleCapture(sessionId: string): void {
116
130
  const offs = _consoleListeners.get(sessionId);
117
- if (offs) { for (const off of offs) off(); _consoleListeners.delete(sessionId); }
131
+ if (offs) {
132
+ for (const off of offs) off();
133
+ _consoleListeners.delete(sessionId);
134
+ }
118
135
  _consoleMessages.delete(sessionId);
119
136
  _pageErrors.delete(sessionId);
120
137
  }
@@ -1,11 +1,11 @@
1
- import { createServer, IncomingMessage, ServerResponse } from 'node:http';
2
- import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';
3
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
4
- import { join, dirname } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
- import { homedir } from 'node:os';
7
- import { createRequire } from 'node:module';
8
1
  import { randomBytes } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
4
+ import { createServer, type IncomingMessage } from 'node:http';
5
+ import { createRequire } from 'node:module';
6
+ import { homedir } from 'node:os';
7
+ import { dirname, join } from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
9
 
10
10
  export interface StepEvent {
11
11
  type: string;
@@ -23,10 +23,12 @@ export interface RunRecord {
23
23
 
24
24
  const RUNS_FILE = join(homedir(), '.monomind', 'browse-runs.json');
25
25
 
26
- function readBody(req: IncomingMessage): Promise<string> {
26
+ function _readBody(req: IncomingMessage): Promise<string> {
27
27
  return new Promise((resolve, reject) => {
28
28
  let body = '';
29
- req.on('data', (chunk: Buffer) => { body += chunk.toString(); });
29
+ req.on('data', (chunk: Buffer) => {
30
+ body += chunk.toString();
31
+ });
30
32
  req.on('end', () => resolve(body));
31
33
  req.on('error', reject);
32
34
  });
@@ -36,13 +38,15 @@ async function loadPersistedRuns(): Promise<RunRecord[]> {
36
38
  if (!existsSync(RUNS_FILE)) return [];
37
39
  try {
38
40
  return JSON.parse(await readFile(RUNS_FILE, 'utf-8')) as RunRecord[];
39
- } catch { return []; }
41
+ } catch {
42
+ return [];
43
+ }
40
44
  }
41
45
 
42
46
  const _require = createRequire(import.meta.url);
43
47
 
44
48
  const __dirname = dirname(fileURLToPath(import.meta.url));
45
- const DEFAULT_PORT = parseInt(process.env['MONOBROWSE_DASHBOARD_PORT'] ?? '4242', 10);
49
+ const DEFAULT_PORT = parseInt(process.env.MONOBROWSE_DASHBOARD_PORT ?? '4242', 10);
46
50
  const MAX_RUN_HISTORY = 50;
47
51
 
48
52
  export interface DashboardServer {
@@ -67,7 +71,9 @@ export function startDashboard(port = DEFAULT_PORT): DashboardServer {
67
71
  try {
68
72
  const authFileDir = join(homedir(), '.monomind');
69
73
  mkdirSync(authFileDir, { recursive: true });
70
- writeFileSync(join(authFileDir, 'monobrowse-dashboard-token'), dashboardAuthValue, { mode: 0o600 });
74
+ writeFileSync(join(authFileDir, 'monobrowse-dashboard-token'), dashboardAuthValue, {
75
+ mode: 0o600,
76
+ });
71
77
  } catch {
72
78
  // best-effort: if we can't persist the token, mutating routes still
73
79
  // enforce it in-memory — trusted callers just won't be able to read it.
@@ -114,8 +120,8 @@ export function startDashboard(port = DEFAULT_PORT): DashboardServer {
114
120
 
115
121
  if (url === '/runs' && req.method === 'GET') {
116
122
  const persisted = await loadPersistedRuns().catch(() => [] as RunRecord[]);
117
- const seen = new Set(runHistory.map(r => r.id));
118
- const merged = [...runHistory, ...persisted.filter(r => !seen.has(r.id))]
123
+ const seen = new Set(runHistory.map((r) => r.id));
124
+ const merged = [...runHistory, ...persisted.filter((r) => !seen.has(r.id))]
119
125
  .sort((a, b) => b.startedAt - a.startedAt)
120
126
  .slice(0, MAX_RUN_HISTORY);
121
127
  res.writeHead(200, { 'Content-Type': 'application/json' });
@@ -130,7 +136,8 @@ export function startDashboard(port = DEFAULT_PORT): DashboardServer {
130
136
  // every non-GET/HEAD route; GET/SSE reads stay open on the loopback baseline.
131
137
  if (url.startsWith('/stop/') && req.method === 'POST') {
132
138
  const parsedAuth = new URL(url, 'http://localhost');
133
- const suppliedAuth = req.headers['x-monobrowse-token'] || parsedAuth.searchParams.get('token') || '';
139
+ const suppliedAuth =
140
+ req.headers['x-monobrowse-token'] || parsedAuth.searchParams.get('token') || '';
134
141
  if (suppliedAuth !== dashboardAuthValue) {
135
142
  res.writeHead(401, { 'Content-Type': 'application/json' });
136
143
  res.end(JSON.stringify({ error: 'Unauthorized: missing or invalid auth token' }));
@@ -144,18 +151,26 @@ export function startDashboard(port = DEFAULT_PORT): DashboardServer {
144
151
  }
145
152
 
146
153
  const parsed = new URL(url, 'http://localhost');
147
- if (parsed.pathname === '/events' && (req.method === 'GET' || req.method === 'HEAD') && !WebSocketServer) {
154
+ if (
155
+ parsed.pathname === '/events' &&
156
+ (req.method === 'GET' || req.method === 'HEAD') &&
157
+ !WebSocketServer
158
+ ) {
148
159
  // SSE fallback when ws not available
149
160
  const subscribedDir = parsed.searchParams.get('dir') ?? null;
150
161
  res.writeHead(200, {
151
162
  'Content-Type': 'text/event-stream',
152
163
  'Cache-Control': 'no-cache',
153
- 'Connection': 'keep-alive',
164
+ Connection: 'keep-alive',
154
165
  });
155
166
  res.write(`data: ${JSON.stringify({ type: 'connected' })}\n\n`);
156
167
  clientDirs.set(res, subscribedDir);
157
168
  const heartbeat = setInterval(() => {
158
- try { res.write(': keep-alive\n\n'); } catch { clearInterval(heartbeat); }
169
+ try {
170
+ res.write(': keep-alive\n\n');
171
+ } catch {
172
+ clearInterval(heartbeat);
173
+ }
159
174
  }, 30_000);
160
175
  req.on('close', () => {
161
176
  clearInterval(heartbeat);
@@ -176,8 +191,8 @@ export function startDashboard(port = DEFAULT_PORT): DashboardServer {
176
191
  const subscribedDir = upgradeParsed.searchParams.get('dir') ?? null;
177
192
  clientDirs.set(ws, subscribedDir);
178
193
  const persisted = await loadPersistedRuns().catch(() => [] as RunRecord[]);
179
- const seen = new Set(runHistory.map(r => r.id));
180
- const merged = [...runHistory, ...persisted.filter(r => !seen.has(r.id))]
194
+ const seen = new Set(runHistory.map((r) => r.id));
195
+ const merged = [...runHistory, ...persisted.filter((r) => !seen.has(r.id))]
181
196
  .sort((a, b) => b.startedAt - a.startedAt)
182
197
  .slice(0, MAX_RUN_HISTORY);
183
198
  ws.send(JSON.stringify({ type: 'history', runs: merged }));
@@ -205,7 +220,11 @@ export function startDashboard(port = DEFAULT_PORT): DashboardServer {
205
220
  function broadcast(event: StepEvent): void {
206
221
  const msg = JSON.stringify(event);
207
222
  for (const [client, subscribedDir] of clientDirs) {
208
- if (subscribedDir !== null && event.projectDir !== undefined && subscribedDir !== event.projectDir) {
223
+ if (
224
+ subscribedDir !== null &&
225
+ event.projectDir !== undefined &&
226
+ subscribedDir !== event.projectDir
227
+ ) {
209
228
  continue;
210
229
  }
211
230
  try {
@@ -221,7 +240,7 @@ export function startDashboard(port = DEFAULT_PORT): DashboardServer {
221
240
  }
222
241
 
223
242
  function addRunRecord(record: RunRecord): void {
224
- const idx = runHistory.findIndex(r => r.id === record.id);
243
+ const idx = runHistory.findIndex((r) => r.id === record.id);
225
244
  if (idx >= 0) {
226
245
  runHistory[idx] = record;
227
246
  } else {
@@ -229,9 +248,9 @@ export function startDashboard(port = DEFAULT_PORT): DashboardServer {
229
248
  if (runHistory.length > MAX_RUN_HISTORY) runHistory.pop();
230
249
  }
231
250
  const dir = join(homedir(), '.monomind');
232
- mkdir(dir, { recursive: true }).then(() =>
233
- writeFile(RUNS_FILE, JSON.stringify(runHistory, null, 2))
234
- ).catch(() => {});
251
+ mkdir(dir, { recursive: true })
252
+ .then(() => writeFile(RUNS_FILE, JSON.stringify(runHistory, null, 2)))
253
+ .catch(() => {});
235
254
  }
236
255
 
237
256
  function isStopRequested(runId: string): boolean {