@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
@@ -127,10 +127,29 @@ export interface BrowserSession {
127
127
  }
128
128
 
129
129
  export const INTERACTIVE_ROLES = new Set([
130
- 'button', 'link', 'textbox', 'combobox', 'listbox', 'checkbox', 'radio',
131
- 'slider', 'spinbutton', 'searchbox', 'option', 'menuitem', 'tab', 'switch',
132
- 'treeitem', 'menuitemcheckbox', 'menuitemradio', 'row', 'gridcell', 'cell',
133
- 'columnheader', 'rowheader', 'scrollbar',
130
+ 'button',
131
+ 'link',
132
+ 'textbox',
133
+ 'combobox',
134
+ 'listbox',
135
+ 'checkbox',
136
+ 'radio',
137
+ 'slider',
138
+ 'spinbutton',
139
+ 'searchbox',
140
+ 'option',
141
+ 'menuitem',
142
+ 'tab',
143
+ 'switch',
144
+ 'treeitem',
145
+ 'menuitemcheckbox',
146
+ 'menuitemradio',
147
+ 'row',
148
+ 'gridcell',
149
+ 'cell',
150
+ 'columnheader',
151
+ 'rowheader',
152
+ 'scrollbar',
134
153
  ]);
135
154
 
136
155
  export const CHROME_EXECUTABLES = [
@@ -1,5 +1,5 @@
1
- import type { CdpClient } from './cdp.js';
2
1
  import { evaluateJs } from './actions.js';
2
+ import type { CdpClient } from './cdp.js';
3
3
 
4
4
  export interface WebVitals {
5
5
  lcp?: number;
@@ -16,7 +16,7 @@ export interface WebVitals {
16
16
  export async function collectVitals(
17
17
  client: CdpClient,
18
18
  sessionId: string,
19
- waitMs = 2000
19
+ waitMs = 2000,
20
20
  ): Promise<WebVitals> {
21
21
  // Inject PerformanceObserver collectors and wait for data
22
22
  const script = `
@@ -97,26 +97,43 @@ export async function collectVitals(
97
97
 
98
98
  export function formatVitals(vitals: WebVitals): string {
99
99
  const lines: string[] = [];
100
- const ms = (v?: number) => v !== undefined ? `${Math.round(v)}ms` : 'n/a';
100
+ const ms = (v?: number) => (v !== undefined ? `${Math.round(v)}ms` : 'n/a');
101
101
  const score = (metric: string, v?: number): string => {
102
102
  if (v === undefined) return '';
103
- if (metric === 'lcp') return v < 2500 ? ' ✓ good' : v < 4000 ? ' ~ needs improvement' : ' ✗ poor';
104
- if (metric === 'fcp') return v < 1800 ? ' ✓ good' : v < 3000 ? ' ~ needs improvement' : ' ✗ poor';
105
- if (metric === 'cls') return v < 0.1 ? ' ✓ good' : v < 0.25 ? ' ~ needs improvement' : ' ✗ poor';
103
+ if (metric === 'lcp')
104
+ return v < 2500 ? ' ✓ good' : v < 4000 ? ' ~ needs improvement' : ' ✗ poor';
105
+ if (metric === 'fcp')
106
+ return v < 1800 ? ' ✓ good' : v < 3000 ? ' ~ needs improvement' : ' ✗ poor';
107
+ if (metric === 'cls')
108
+ return v < 0.1 ? ' ✓ good' : v < 0.25 ? ' ~ needs improvement' : ' ✗ poor';
106
109
  if (metric === 'inp') return v < 200 ? ' ✓ good' : v < 500 ? ' ~ needs improvement' : ' ✗ poor';
107
- if (metric === 'ttfb') return v < 800 ? ' ✓ good' : v < 1800 ? ' ~ needs improvement' : ' ✗ poor';
110
+ if (metric === 'ttfb')
111
+ return v < 800 ? ' ✓ good' : v < 1800 ? ' ~ needs improvement' : ' ✗ poor';
108
112
  return '';
109
113
  };
110
114
 
111
- if (vitals.lcp !== undefined) lines.push(` LCP (Largest Contentful Paint): ${ms(vitals.lcp)}${score('lcp', vitals.lcp)}`);
112
- if (vitals.fcp !== undefined) lines.push(` FCP (First Contentful Paint): ${ms(vitals.fcp)}${score('fcp', vitals.fcp)}`);
113
- if (vitals.cls !== undefined) lines.push(` CLS (Cumulative Layout Shift): ${vitals.cls?.toFixed(4)}${score('cls', vitals.cls)}`);
114
- if (vitals.inp !== undefined) lines.push(` INP (Interaction to Next Paint): ${ms(vitals.inp)}${score('inp', vitals.inp)}`);
115
- if (vitals.ttfb !== undefined) lines.push(` TTFB (Time to First Byte): ${ms(vitals.ttfb)}${score('ttfb', vitals.ttfb)}`);
116
- if (vitals.domInteractive !== undefined) lines.push(` DOM Interactive: ${ms(vitals.domInteractive)}`);
117
- if (vitals.domContentLoaded !== undefined) lines.push(` DOMContentLoaded: ${ms(vitals.domContentLoaded)}`);
118
- if (vitals.loadTime !== undefined) lines.push(` Load: ${ms(vitals.loadTime)}`);
119
- if (vitals.resources !== undefined) lines.push(` Resources loaded: ${vitals.resources}`);
115
+ if (vitals.lcp !== undefined)
116
+ lines.push(` LCP (Largest Contentful Paint): ${ms(vitals.lcp)}${score('lcp', vitals.lcp)}`);
117
+ if (vitals.fcp !== undefined)
118
+ lines.push(` FCP (First Contentful Paint): ${ms(vitals.fcp)}${score('fcp', vitals.fcp)}`);
119
+ if (vitals.cls !== undefined)
120
+ lines.push(
121
+ ` CLS (Cumulative Layout Shift): ${vitals.cls?.toFixed(4)}${score('cls', vitals.cls)}`,
122
+ );
123
+ if (vitals.inp !== undefined)
124
+ lines.push(` INP (Interaction to Next Paint): ${ms(vitals.inp)}${score('inp', vitals.inp)}`);
125
+ if (vitals.ttfb !== undefined)
126
+ lines.push(
127
+ ` TTFB (Time to First Byte): ${ms(vitals.ttfb)}${score('ttfb', vitals.ttfb)}`,
128
+ );
129
+ if (vitals.domInteractive !== undefined)
130
+ lines.push(` DOM Interactive: ${ms(vitals.domInteractive)}`);
131
+ if (vitals.domContentLoaded !== undefined)
132
+ lines.push(` DOMContentLoaded: ${ms(vitals.domContentLoaded)}`);
133
+ if (vitals.loadTime !== undefined)
134
+ lines.push(` Load: ${ms(vitals.loadTime)}`);
135
+ if (vitals.resources !== undefined)
136
+ lines.push(` Resources loaded: ${vitals.resources}`);
120
137
 
121
138
  return lines.join('\n');
122
139
  }
@@ -1,7 +1,7 @@
1
+ import { evaluateJs } from './actions.js';
2
+ import { getCurrentUrl } from './browser.js';
1
3
  import type { CdpClient } from './cdp.js';
2
4
  import type { WaitOptions } from './types.js';
3
- import { getCurrentUrl } from './browser.js';
4
- import { evaluateJs } from './actions.js';
5
5
 
6
6
  const DEFAULT_TIMEOUT = 30_000;
7
7
  const POLL_INTERVAL = 250;
@@ -9,7 +9,7 @@ const POLL_INTERVAL = 250;
9
9
  export async function waitFor(
10
10
  client: CdpClient,
11
11
  sessionId: string,
12
- options: WaitOptions
12
+ options: WaitOptions,
13
13
  ): Promise<void> {
14
14
  const timeout = options.timeout ?? DEFAULT_TIMEOUT;
15
15
  const deadline = Date.now() + timeout;
@@ -42,7 +42,7 @@ async function waitForLoad(
42
42
  client: CdpClient,
43
43
  sessionId: string,
44
44
  condition: string,
45
- timeout: number
45
+ timeout: number,
46
46
  ): Promise<void> {
47
47
  if (condition === 'networkidle') {
48
48
  await waitForNetworkIdle(client, sessionId, 500, timeout);
@@ -54,7 +54,10 @@ async function waitForLoad(
54
54
  let timedOut = false;
55
55
  let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
56
56
  const timeoutPromise = new Promise<void>((resolve) => {
57
- timeoutHandle = setTimeout(() => { timedOut = true; resolve(); }, timeout);
57
+ timeoutHandle = setTimeout(() => {
58
+ timedOut = true;
59
+ resolve();
60
+ }, timeout);
58
61
  });
59
62
  try {
60
63
  await Promise.race([eventPromise, timeoutPromise]);
@@ -69,7 +72,7 @@ async function waitForNetworkIdle(
69
72
  client: CdpClient,
70
73
  sessionId: string,
71
74
  idleMs: number,
72
- timeout: number
75
+ timeout: number,
73
76
  ): Promise<void> {
74
77
  return new Promise((resolve, reject) => {
75
78
  let pending = 0;
@@ -77,9 +80,15 @@ async function waitForNetworkIdle(
77
80
  let idleTimer: ReturnType<typeof setTimeout> | null = null;
78
81
 
79
82
  const cleanup = () => {
80
- if (idleTimer) { clearTimeout(idleTimer); idleTimer = null; }
83
+ if (idleTimer) {
84
+ clearTimeout(idleTimer);
85
+ idleTimer = null;
86
+ }
81
87
  clearTimeout(killTimer);
82
- offReq(); offResp(); offFail(); offCache();
88
+ offReq();
89
+ offResp();
90
+ offFail();
91
+ offCache();
83
92
  };
84
93
 
85
94
  const killTimer = setTimeout(() => {
@@ -87,31 +96,44 @@ async function waitForNetworkIdle(
87
96
  reject(new Error('Timeout waiting for networkidle'));
88
97
  }, timeout);
89
98
 
90
- const settle = () => { cleanup(); resolve(); };
99
+ const settle = () => {
100
+ cleanup();
101
+ resolve();
102
+ };
91
103
 
92
104
  const check = () => {
93
105
  if (pending === 0) {
94
106
  if (idleTimer) clearTimeout(idleTimer);
95
107
  idleTimer = setTimeout(settle, idleMs);
96
108
  } else {
97
- if (idleTimer) { clearTimeout(idleTimer); idleTimer = null; }
109
+ if (idleTimer) {
110
+ clearTimeout(idleTimer);
111
+ idleTimer = null;
112
+ }
98
113
  }
99
114
  };
100
115
 
101
116
  const offReq = client.on('Network.requestWillBeSent', (params, sid) => {
102
117
  if (sid !== sessionId) return;
103
118
  const id = params.requestId as string;
104
- if (!inflight.has(id)) { inflight.add(id); pending++; check(); }
119
+ if (!inflight.has(id)) {
120
+ inflight.add(id);
121
+ pending++;
122
+ check();
123
+ }
105
124
  });
106
125
 
107
126
  const decrement = (params: Record<string, unknown>, sid?: string) => {
108
127
  if (sid !== sessionId) return;
109
128
  const id = params.requestId as string;
110
- if (inflight.delete(id)) { pending = Math.max(0, pending - 1); check(); }
129
+ if (inflight.delete(id)) {
130
+ pending = Math.max(0, pending - 1);
131
+ check();
132
+ }
111
133
  };
112
134
 
113
- const offResp = client.on('Network.loadingFinished', decrement);
114
- const offFail = client.on('Network.loadingFailed', decrement);
135
+ const offResp = client.on('Network.loadingFinished', decrement);
136
+ const offFail = client.on('Network.loadingFailed', decrement);
115
137
  const offCache = client.on('Network.requestServedFromCache', decrement);
116
138
 
117
139
  check();
@@ -122,7 +144,7 @@ async function waitForUrl(
122
144
  client: CdpClient,
123
145
  sessionId: string,
124
146
  pattern: string,
125
- deadline: number
147
+ deadline: number,
126
148
  ): Promise<void> {
127
149
  const regex = globToRegex(pattern);
128
150
  while (Date.now() < deadline) {
@@ -137,10 +159,14 @@ async function waitForText(
137
159
  client: CdpClient,
138
160
  sessionId: string,
139
161
  text: string,
140
- deadline: number
162
+ deadline: number,
141
163
  ): Promise<void> {
142
164
  while (Date.now() < deadline) {
143
- const bodyText = await evaluateJs(client, sessionId, 'document.body?.innerText ?? ""') as string;
165
+ const bodyText = (await evaluateJs(
166
+ client,
167
+ sessionId,
168
+ 'document.body?.innerText ?? ""',
169
+ )) as string;
144
170
  if (bodyText.includes(text)) return;
145
171
  await sleep(POLL_INTERVAL);
146
172
  }
@@ -151,14 +177,14 @@ async function waitForSelector(
151
177
  client: CdpClient,
152
178
  sessionId: string,
153
179
  selector: string,
154
- deadline: number
180
+ deadline: number,
155
181
  ): Promise<void> {
156
182
  while (Date.now() < deadline) {
157
- const found = await evaluateJs(
183
+ const found = (await evaluateJs(
158
184
  client,
159
185
  sessionId,
160
- `!!document.querySelector(${JSON.stringify(selector)})`
161
- ) as boolean;
186
+ `!!document.querySelector(${JSON.stringify(selector)})`,
187
+ )) as boolean;
162
188
  if (found) return;
163
189
  await sleep(POLL_INTERVAL);
164
190
  }
package/src/cli/action.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  // src/commands/browse-action.ts
2
- import { Command } from 'commander';
3
- import { readdir, readFile, writeFile, mkdir } from 'node:fs/promises';
2
+
4
3
  import { existsSync } from 'node:fs';
4
+ import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
5
5
  import { join } from 'node:path';
6
- import { analyzePageForAction, type AnalyzerPage } from '../index.js';
6
+ import { Command } from 'commander';
7
7
  import type { ActionDef, StepDef } from '../index.js';
8
+ import { type AnalyzerPage, analyzePageForAction } from '../index.js';
8
9
 
9
10
  async function readAction(filePath: string): Promise<ActionDef> {
10
11
  return JSON.parse(await readFile(filePath, 'utf8')) as ActionDef;
@@ -34,7 +35,7 @@ const BUILTIN_ACTIONS: { id: string; platform: string; name: string }[] = [
34
35
  async function getCustomActions(): Promise<ActionDef[]> {
35
36
  const dir = join(process.cwd(), '.monomind', 'actions');
36
37
  if (!existsSync(dir)) return [];
37
- const files = (await readdir(dir)).filter(f => f.endsWith('.json'));
38
+ const files = (await readdir(dir)).filter((f) => f.endsWith('.json'));
38
39
  const results: ActionDef[] = [];
39
40
  for (const f of files) {
40
41
  try {
@@ -63,10 +64,16 @@ export function createActionCommand(): Command {
63
64
  try {
64
65
  // Dynamic import to avoid crashing if CDP is unavailable
65
66
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
- const mod = await (import('@monoes/monobrowse' as string) as Promise<any>).catch(() => null);
67
- const createBrowserPage = mod?.createBrowserPage as ((url: string) => Promise<AnalyzerPage>) | null;
67
+ const mod = await (import('@monoes/monobrowse' as string) as Promise<any>).catch(
68
+ () => null,
69
+ );
70
+ const createBrowserPage = mod?.createBrowserPage as
71
+ | ((url: string) => Promise<AnalyzerPage>)
72
+ | null;
68
73
  if (!createBrowserPage) {
69
- throw new Error('Browser CDP client not available. Ensure Chrome is running with --remote-debugging-port=9222');
74
+ throw new Error(
75
+ 'Browser CDP client not available. Ensure Chrome is running with --remote-debugging-port=9222',
76
+ );
70
77
  }
71
78
  const page = await createBrowserPage(opts.url);
72
79
  actionDef = await analyzePageForAction(page, opts.task);
@@ -98,10 +105,12 @@ export function createActionCommand(): Command {
98
105
  console.log(`Running action: ${actionId} with account: ${opts.account}`);
99
106
 
100
107
  const custom = await getCustomActions();
101
- const def = custom.find(a => a.id === actionId);
108
+ const def = custom.find((a) => a.id === actionId);
102
109
  if (!def) {
103
110
  console.error(`Action not found in custom actions: ${actionId}`);
104
- console.error('Built-in actions require adapter step definitions — use "action build" to create a custom action.');
111
+ console.error(
112
+ 'Built-in actions require adapter step definitions — use "action build" to create a custom action.',
113
+ );
105
114
  process.exit(1);
106
115
  }
107
116
 
@@ -126,8 +135,13 @@ export function createActionCommand(): Command {
126
135
  break;
127
136
  case 'find': {
128
137
  for (const sel of step.selectors) {
129
- const found = await findBySelector(client, sessionId, refs, interpolate(sel)).catch(() => null);
130
- if (found) { refs.set(step.as, found); break; }
138
+ const found = await findBySelector(client, sessionId, refs, interpolate(sel)).catch(
139
+ () => null,
140
+ );
141
+ if (found) {
142
+ refs.set(step.as, found);
143
+ break;
144
+ }
131
145
  }
132
146
  console.log(` find → ${step.as}`);
133
147
  break;
@@ -150,9 +164,12 @@ export function createActionCommand(): Command {
150
164
  if (step.condition === 'network_idle') {
151
165
  await waitFor(client, sessionId, { load: 'networkidle', timeout: step.timeout });
152
166
  } else if (step.condition === 'selector' && step.selector) {
153
- await waitFor(client, sessionId, { selector: step.selector, timeout: step.timeout });
167
+ await waitFor(client, sessionId, {
168
+ selector: step.selector,
169
+ timeout: step.timeout,
170
+ });
154
171
  } else if (step.condition === 'duration') {
155
- await new Promise(r => setTimeout(r, step.timeout ?? 1000));
172
+ await new Promise((r) => setTimeout(r, step.timeout ?? 1000));
156
173
  }
157
174
  console.log(` wait → ${step.condition}`);
158
175
  break;
@@ -160,8 +177,16 @@ export function createActionCommand(): Command {
160
177
  const ref = refs.get(step.target);
161
178
  if (!ref) throw new Error(`Element "${step.target}" not found`);
162
179
  const val = step.attribute
163
- ? await evaluateJs(client, sessionId, `document.querySelector('[data-ref="${ref.ref}"]')?.getAttribute('${step.attribute}')`)
164
- : await evaluateJs(client, sessionId, `document.querySelector('[data-ref="${ref.ref}"]')?.textContent`);
180
+ ? await evaluateJs(
181
+ client,
182
+ sessionId,
183
+ `document.querySelector('[data-ref="${ref.ref}"]')?.getAttribute('${step.attribute}')`,
184
+ )
185
+ : await evaluateJs(
186
+ client,
187
+ sessionId,
188
+ `document.querySelector('[data-ref="${ref.ref}"]')?.textContent`,
189
+ );
165
190
  console.log(` extract → ${step.as}: ${val}`);
166
191
  break;
167
192
  }
@@ -189,10 +214,10 @@ export function createActionCommand(): Command {
189
214
  .action(async (opts: { platform?: string }) => {
190
215
  const custom = await getCustomActions();
191
216
  const all = [
192
- ...BUILTIN_ACTIONS.map(a => ({ ...a, source: 'built-in' })),
193
- ...custom.map(a => ({ id: a.id, platform: a.platform, name: a.name, source: 'custom' })),
217
+ ...BUILTIN_ACTIONS.map((a) => ({ ...a, source: 'built-in' })),
218
+ ...custom.map((a) => ({ id: a.id, platform: a.platform, name: a.name, source: 'custom' })),
194
219
  ];
195
- const filtered = opts.platform ? all.filter(a => a.platform === opts.platform) : all;
220
+ const filtered = opts.platform ? all.filter((a) => a.platform === opts.platform) : all;
196
221
  if (filtered.length === 0) {
197
222
  console.log('No actions found.');
198
223
  return;
@@ -210,7 +235,7 @@ export function createActionCommand(): Command {
210
235
  .action(async (actionId: string) => {
211
236
  // Check custom actions first
212
237
  const dir = join(process.cwd(), '.monomind', 'actions');
213
- const fileName = actionId.replace(':', '-') + '.json';
238
+ const fileName = `${actionId.replace(':', '-')}.json`;
214
239
  const customPath = join(dir, fileName);
215
240
  if (existsSync(customPath)) {
216
241
  const def = await readAction(customPath);
@@ -218,9 +243,15 @@ export function createActionCommand(): Command {
218
243
  return;
219
244
  }
220
245
  // Check built-ins
221
- const builtin = BUILTIN_ACTIONS.find(a => a.id === actionId);
246
+ const builtin = BUILTIN_ACTIONS.find((a) => a.id === actionId);
222
247
  if (builtin) {
223
- console.log(JSON.stringify({ ...builtin, note: 'Built-in action — steps defined in browser/adapters/' }, null, 2));
248
+ console.log(
249
+ JSON.stringify(
250
+ { ...builtin, note: 'Built-in action — steps defined in browser/adapters/' },
251
+ null,
252
+ 2,
253
+ ),
254
+ );
224
255
  return;
225
256
  }
226
257
  console.error(`Action not found: ${actionId}`);