@everydaydevopsio/pilot 0.5.0 → 0.6.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 (280) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/CLAUDE.md +9 -9
  3. package/README.md +108 -53
  4. package/dist/browser/browser-manager.d.ts +60 -0
  5. package/dist/browser/browser-manager.d.ts.map +1 -0
  6. package/dist/browser/browser-manager.js +348 -0
  7. package/dist/browser/browser-manager.js.map +1 -0
  8. package/dist/browser/chrome-launcher.d.ts +30 -0
  9. package/dist/browser/chrome-launcher.d.ts.map +1 -0
  10. package/dist/browser/chrome-launcher.js +217 -0
  11. package/dist/browser/chrome-launcher.js.map +1 -0
  12. package/dist/browser/connection.d.ts +23 -0
  13. package/dist/browser/connection.d.ts.map +1 -0
  14. package/dist/browser/connection.js +53 -0
  15. package/dist/browser/connection.js.map +1 -0
  16. package/dist/browser/events.d.ts +9 -0
  17. package/dist/browser/events.d.ts.map +1 -0
  18. package/dist/browser/events.js +99 -0
  19. package/dist/browser/events.js.map +1 -0
  20. package/dist/browser/index.d.ts +4 -0
  21. package/dist/browser/index.d.ts.map +1 -0
  22. package/dist/browser/index.js +4 -0
  23. package/dist/browser/index.js.map +1 -0
  24. package/dist/browser/inspect/element-ref.d.ts +23 -0
  25. package/dist/browser/inspect/element-ref.d.ts.map +1 -0
  26. package/dist/browser/inspect/element-ref.js +52 -0
  27. package/dist/browser/inspect/element-ref.js.map +1 -0
  28. package/dist/browser/inspect/snapshot.d.ts +11 -0
  29. package/dist/browser/inspect/snapshot.d.ts.map +1 -0
  30. package/dist/browser/inspect/snapshot.js +282 -0
  31. package/dist/browser/inspect/snapshot.js.map +1 -0
  32. package/dist/browser/inspect/styles.d.ts +45 -0
  33. package/dist/browser/inspect/styles.d.ts.map +1 -0
  34. package/dist/browser/inspect/styles.js +190 -0
  35. package/dist/browser/inspect/styles.js.map +1 -0
  36. package/dist/browser/inspect/types.d.ts +35 -0
  37. package/dist/browser/inspect/types.d.ts.map +1 -0
  38. package/dist/browser/inspect/types.js +2 -0
  39. package/dist/browser/inspect/types.js.map +1 -0
  40. package/dist/browser/interaction/dialogs.d.ts +18 -0
  41. package/dist/browser/interaction/dialogs.d.ts.map +1 -0
  42. package/dist/browser/interaction/dialogs.js +35 -0
  43. package/dist/browser/interaction/dialogs.js.map +1 -0
  44. package/dist/browser/interaction/downloads.d.ts +23 -0
  45. package/dist/browser/interaction/downloads.d.ts.map +1 -0
  46. package/dist/browser/interaction/downloads.js +87 -0
  47. package/dist/browser/interaction/downloads.js.map +1 -0
  48. package/dist/browser/interaction/events.d.ts +17 -0
  49. package/dist/browser/interaction/events.d.ts.map +1 -0
  50. package/dist/browser/interaction/events.js +66 -0
  51. package/dist/browser/interaction/events.js.map +1 -0
  52. package/dist/browser/interaction/ref-resolver.d.ts +18 -0
  53. package/dist/browser/interaction/ref-resolver.d.ts.map +1 -0
  54. package/dist/browser/interaction/ref-resolver.js +32 -0
  55. package/dist/browser/interaction/ref-resolver.js.map +1 -0
  56. package/dist/browser/interaction/uploads.d.ts +4 -0
  57. package/dist/browser/interaction/uploads.d.ts.map +1 -0
  58. package/dist/browser/interaction/uploads.js +43 -0
  59. package/dist/browser/interaction/uploads.js.map +1 -0
  60. package/dist/browser/network/network-buffer.d.ts +19 -0
  61. package/dist/browser/network/network-buffer.d.ts.map +1 -0
  62. package/dist/browser/network/network-buffer.js +118 -0
  63. package/dist/browser/network/network-buffer.js.map +1 -0
  64. package/dist/browser/network/network-monitor.d.ts +8 -0
  65. package/dist/browser/network/network-monitor.d.ts.map +1 -0
  66. package/dist/browser/network/network-monitor.js +85 -0
  67. package/dist/browser/network/network-monitor.js.map +1 -0
  68. package/dist/browser/network/redaction.d.ts +3 -0
  69. package/dist/browser/network/redaction.d.ts.map +1 -0
  70. package/dist/browser/network/redaction.js +36 -0
  71. package/dist/browser/network/redaction.js.map +1 -0
  72. package/dist/browser/network/types.d.ts +45 -0
  73. package/dist/browser/network/types.d.ts.map +1 -0
  74. package/dist/browser/network/types.js +2 -0
  75. package/dist/browser/network/types.js.map +1 -0
  76. package/dist/browser/performance/analyze.d.ts +5 -0
  77. package/dist/browser/performance/analyze.d.ts.map +1 -0
  78. package/dist/browser/performance/analyze.js +230 -0
  79. package/dist/browser/performance/analyze.js.map +1 -0
  80. package/dist/browser/performance/trace.d.ts +10 -0
  81. package/dist/browser/performance/trace.d.ts.map +1 -0
  82. package/dist/browser/performance/trace.js +38 -0
  83. package/dist/browser/performance/trace.js.map +1 -0
  84. package/dist/browser/performance/types.d.ts +31 -0
  85. package/dist/browser/performance/types.d.ts.map +1 -0
  86. package/dist/browser/performance/types.js +2 -0
  87. package/dist/browser/performance/types.js.map +1 -0
  88. package/dist/browser/security/origins.d.ts +18 -0
  89. package/dist/browser/security/origins.d.ts.map +1 -0
  90. package/dist/browser/security/origins.js +84 -0
  91. package/dist/browser/security/origins.js.map +1 -0
  92. package/dist/browser/tabs.d.ts +15 -0
  93. package/dist/browser/tabs.d.ts.map +1 -0
  94. package/dist/browser/tabs.js +71 -0
  95. package/dist/browser/tabs.js.map +1 -0
  96. package/dist/browser/types.d.ts +31 -0
  97. package/dist/browser/types.d.ts.map +1 -0
  98. package/dist/browser/types.js +2 -0
  99. package/dist/browser/types.js.map +1 -0
  100. package/dist/browser.d.ts +2 -99
  101. package/dist/browser.d.ts.map +1 -1
  102. package/dist/browser.js +3 -653
  103. package/dist/browser.js.map +1 -1
  104. package/dist/commands/check.d.ts +17 -0
  105. package/dist/commands/check.d.ts.map +1 -0
  106. package/dist/commands/check.js +38 -0
  107. package/dist/commands/check.js.map +1 -0
  108. package/dist/commands/click.d.ts +3 -1
  109. package/dist/commands/click.d.ts.map +1 -1
  110. package/dist/commands/click.js +16 -4
  111. package/dist/commands/click.js.map +1 -1
  112. package/dist/commands/connect.d.ts +14 -0
  113. package/dist/commands/connect.d.ts.map +1 -0
  114. package/dist/commands/connect.js +19 -0
  115. package/dist/commands/connect.js.map +1 -0
  116. package/dist/commands/dialog.d.ts +19 -0
  117. package/dist/commands/dialog.d.ts.map +1 -0
  118. package/dist/commands/dialog.js +51 -0
  119. package/dist/commands/dialog.js.map +1 -0
  120. package/dist/commands/downloads.d.ts +30 -0
  121. package/dist/commands/downloads.d.ts.map +1 -0
  122. package/dist/commands/downloads.js +66 -0
  123. package/dist/commands/downloads.js.map +1 -0
  124. package/dist/commands/fill.d.ts +16 -0
  125. package/dist/commands/fill.d.ts.map +1 -0
  126. package/dist/commands/fill.js +15 -0
  127. package/dist/commands/fill.js.map +1 -0
  128. package/dist/commands/find.d.ts +14 -0
  129. package/dist/commands/find.d.ts.map +1 -0
  130. package/dist/commands/find.js +26 -0
  131. package/dist/commands/find.js.map +1 -0
  132. package/dist/commands/hover.d.ts +13 -0
  133. package/dist/commands/hover.d.ts.map +1 -0
  134. package/dist/commands/hover.js +24 -0
  135. package/dist/commands/hover.js.map +1 -0
  136. package/dist/commands/navigate.d.ts.map +1 -1
  137. package/dist/commands/navigate.js +13 -0
  138. package/dist/commands/navigate.js.map +1 -1
  139. package/dist/commands/network.d.ts +33 -0
  140. package/dist/commands/network.d.ts.map +1 -0
  141. package/dist/commands/network.js +84 -0
  142. package/dist/commands/network.js.map +1 -0
  143. package/dist/commands/performance.d.ts +12 -0
  144. package/dist/commands/performance.d.ts.map +1 -0
  145. package/dist/commands/performance.js +26 -0
  146. package/dist/commands/performance.js.map +1 -0
  147. package/dist/commands/press_key.d.ts +10 -0
  148. package/dist/commands/press_key.d.ts.map +1 -0
  149. package/dist/commands/press_key.js +103 -0
  150. package/dist/commands/press_key.js.map +1 -0
  151. package/dist/commands/scroll.d.ts +21 -0
  152. package/dist/commands/scroll.d.ts.map +1 -0
  153. package/dist/commands/scroll.js +54 -0
  154. package/dist/commands/scroll.js.map +1 -0
  155. package/dist/commands/select.d.ts +18 -0
  156. package/dist/commands/select.d.ts.map +1 -0
  157. package/dist/commands/select.js +53 -0
  158. package/dist/commands/select.js.map +1 -0
  159. package/dist/commands/snapshot.d.ts +9 -0
  160. package/dist/commands/snapshot.d.ts.map +1 -0
  161. package/dist/commands/snapshot.js +7 -0
  162. package/dist/commands/snapshot.js.map +1 -0
  163. package/dist/commands/styles.d.ts +13 -0
  164. package/dist/commands/styles.d.ts.map +1 -0
  165. package/dist/commands/styles.js +7 -0
  166. package/dist/commands/styles.js.map +1 -0
  167. package/dist/commands/type.d.ts +3 -1
  168. package/dist/commands/type.d.ts.map +1 -1
  169. package/dist/commands/type.js +11 -2
  170. package/dist/commands/type.js.map +1 -1
  171. package/dist/commands/upload.d.ts +12 -0
  172. package/dist/commands/upload.d.ts.map +1 -0
  173. package/dist/commands/upload.js +13 -0
  174. package/dist/commands/upload.js.map +1 -0
  175. package/dist/mcp/console-buffer.d.ts +9 -0
  176. package/dist/mcp/console-buffer.d.ts.map +1 -1
  177. package/dist/mcp/console-buffer.js.map +1 -1
  178. package/dist/mcp/server.d.ts +10 -0
  179. package/dist/mcp/server.d.ts.map +1 -1
  180. package/dist/mcp/server.js +63 -2
  181. package/dist/mcp/server.js.map +1 -1
  182. package/dist/mcp/tools/browser.d.ts.map +1 -1
  183. package/dist/mcp/tools/browser.js +99 -8
  184. package/dist/mcp/tools/browser.js.map +1 -1
  185. package/dist/mcp/tools/connect.d.ts +5 -0
  186. package/dist/mcp/tools/connect.d.ts.map +1 -0
  187. package/dist/mcp/tools/connect.js +48 -0
  188. package/dist/mcp/tools/connect.js.map +1 -0
  189. package/dist/mcp/tools/files.d.ts +4 -0
  190. package/dist/mcp/tools/files.d.ts.map +1 -0
  191. package/dist/mcp/tools/files.js +85 -0
  192. package/dist/mcp/tools/files.js.map +1 -0
  193. package/dist/mcp/tools/interaction.d.ts +4 -0
  194. package/dist/mcp/tools/interaction.d.ts.map +1 -0
  195. package/dist/mcp/tools/interaction.js +176 -0
  196. package/dist/mcp/tools/interaction.js.map +1 -0
  197. package/dist/mcp/tools/names.d.ts +1 -1
  198. package/dist/mcp/tools/names.d.ts.map +1 -1
  199. package/dist/mcp/tools/names.js +19 -1
  200. package/dist/mcp/tools/names.js.map +1 -1
  201. package/dist/mcp/tools/network.d.ts +4 -0
  202. package/dist/mcp/tools/network.d.ts.map +1 -0
  203. package/dist/mcp/tools/network.js +68 -0
  204. package/dist/mcp/tools/network.js.map +1 -0
  205. package/dist/mcp/tools/performance.d.ts +4 -0
  206. package/dist/mcp/tools/performance.d.ts.map +1 -0
  207. package/dist/mcp/tools/performance.js +26 -0
  208. package/dist/mcp/tools/performance.js.map +1 -0
  209. package/dist/mcp/tools/runtime.d.ts +4 -0
  210. package/dist/mcp/tools/runtime.d.ts.map +1 -0
  211. package/dist/mcp/tools/runtime.js +128 -0
  212. package/dist/mcp/tools/runtime.js.map +1 -0
  213. package/dist/mcp/tools/snapshot.d.ts +4 -0
  214. package/dist/mcp/tools/snapshot.d.ts.map +1 -0
  215. package/dist/mcp/tools/snapshot.js +42 -0
  216. package/dist/mcp/tools/snapshot.js.map +1 -0
  217. package/dist/mcp/tools/styles.d.ts +4 -0
  218. package/dist/mcp/tools/styles.d.ts.map +1 -0
  219. package/dist/mcp/tools/styles.js +27 -0
  220. package/dist/mcp/tools/styles.js.map +1 -0
  221. package/dist/util/config.d.ts.map +1 -1
  222. package/dist/util/config.js +3 -2
  223. package/dist/util/config.js.map +1 -1
  224. package/package.json +7 -3
  225. package/src/browser/browser-manager.ts +457 -0
  226. package/src/browser/chrome-launcher.ts +271 -0
  227. package/src/browser/connection.ts +84 -0
  228. package/src/browser/events.ts +121 -0
  229. package/src/browser/index.ts +20 -0
  230. package/src/browser/inspect/element-ref.ts +68 -0
  231. package/src/browser/inspect/snapshot.ts +348 -0
  232. package/src/browser/inspect/styles.ts +258 -0
  233. package/src/browser/inspect/types.ts +37 -0
  234. package/src/browser/interaction/dialogs.ts +54 -0
  235. package/src/browser/interaction/downloads.ts +116 -0
  236. package/src/browser/interaction/events.ts +79 -0
  237. package/src/browser/interaction/ref-resolver.ts +53 -0
  238. package/src/browser/interaction/uploads.ts +60 -0
  239. package/src/browser/network/network-buffer.ts +133 -0
  240. package/src/browser/network/network-monitor.ts +107 -0
  241. package/src/browser/network/redaction.ts +42 -0
  242. package/src/browser/network/types.ts +47 -0
  243. package/src/browser/performance/analyze.ts +298 -0
  244. package/src/browser/performance/trace.ts +60 -0
  245. package/src/browser/performance/types.ts +34 -0
  246. package/src/browser/security/origins.ts +102 -0
  247. package/src/browser/tabs.ts +110 -0
  248. package/src/browser/types.ts +31 -0
  249. package/src/browser.ts +22 -798
  250. package/src/commands/check.ts +59 -0
  251. package/src/commands/click.ts +18 -4
  252. package/src/commands/connect.ts +40 -0
  253. package/src/commands/dialog.ts +79 -0
  254. package/src/commands/downloads.ts +111 -0
  255. package/src/commands/fill.ts +34 -0
  256. package/src/commands/find.ts +52 -0
  257. package/src/commands/hover.ts +42 -0
  258. package/src/commands/navigate.ts +20 -0
  259. package/src/commands/network.ts +141 -0
  260. package/src/commands/performance.ts +51 -0
  261. package/src/commands/press_key.ts +134 -0
  262. package/src/commands/scroll.ts +79 -0
  263. package/src/commands/select.ts +78 -0
  264. package/src/commands/snapshot.ts +18 -0
  265. package/src/commands/styles.ts +24 -0
  266. package/src/commands/type.ts +12 -2
  267. package/src/commands/upload.ts +36 -0
  268. package/src/mcp/console-buffer.ts +10 -0
  269. package/src/mcp/server.ts +74 -2
  270. package/src/mcp/tools/browser.ts +113 -7
  271. package/src/mcp/tools/connect.ts +62 -0
  272. package/src/mcp/tools/files.ts +120 -0
  273. package/src/mcp/tools/interaction.ts +232 -0
  274. package/src/mcp/tools/names.ts +19 -1
  275. package/src/mcp/tools/network.ts +86 -0
  276. package/src/mcp/tools/performance.ts +40 -0
  277. package/src/mcp/tools/runtime.ts +164 -0
  278. package/src/mcp/tools/snapshot.ts +64 -0
  279. package/src/mcp/tools/styles.ts +41 -0
  280. package/src/util/config.ts +3 -2
@@ -0,0 +1,134 @@
1
+ import type { Client } from 'chrome-remote-interface';
2
+
3
+ /**
4
+ * Map of named keys to CDP key event properties.
5
+ */
6
+ const KEY_MAP: Record<
7
+ string,
8
+ { key: string; code: string; keyCode?: number; text?: string }
9
+ > = {
10
+ enter: { key: 'Enter', code: 'Enter', keyCode: 13, text: '\r' },
11
+ tab: { key: 'Tab', code: 'Tab', keyCode: 9 },
12
+ escape: { key: 'Escape', code: 'Escape', keyCode: 27 },
13
+ backspace: { key: 'Backspace', code: 'Backspace', keyCode: 8 },
14
+ delete: { key: 'Delete', code: 'Delete', keyCode: 46 },
15
+ space: { key: ' ', code: 'Space', keyCode: 32, text: ' ' },
16
+ arrowup: { key: 'ArrowUp', code: 'ArrowUp', keyCode: 38 },
17
+ arrowdown: { key: 'ArrowDown', code: 'ArrowDown', keyCode: 40 },
18
+ arrowleft: { key: 'ArrowLeft', code: 'ArrowLeft', keyCode: 37 },
19
+ arrowright: { key: 'ArrowRight', code: 'ArrowRight', keyCode: 39 },
20
+ home: { key: 'Home', code: 'Home', keyCode: 36 },
21
+ end: { key: 'End', code: 'End', keyCode: 35 },
22
+ pageup: { key: 'PageUp', code: 'PageUp', keyCode: 33 },
23
+ pagedown: { key: 'PageDown', code: 'PageDown', keyCode: 34 },
24
+ f1: { key: 'F1', code: 'F1', keyCode: 112 },
25
+ f2: { key: 'F2', code: 'F2', keyCode: 113 },
26
+ f3: { key: 'F3', code: 'F3', keyCode: 114 },
27
+ f4: { key: 'F4', code: 'F4', keyCode: 115 },
28
+ f5: { key: 'F5', code: 'F5', keyCode: 116 },
29
+ f6: { key: 'F6', code: 'F6', keyCode: 117 },
30
+ f7: { key: 'F7', code: 'F7', keyCode: 118 },
31
+ f8: { key: 'F8', code: 'F8', keyCode: 119 },
32
+ f9: { key: 'F9', code: 'F9', keyCode: 120 },
33
+ f10: { key: 'F10', code: 'F10', keyCode: 121 },
34
+ f11: { key: 'F11', code: 'F11', keyCode: 122 },
35
+ f12: { key: 'F12', code: 'F12', keyCode: 123 }
36
+ };
37
+
38
+ // CDP modifier bit flags
39
+ const MODIFIER_FLAGS: Record<string, number> = {
40
+ alt: 1,
41
+ control: 2,
42
+ ctrl: 2,
43
+ meta: 4,
44
+ cmd: 4,
45
+ command: 4,
46
+ shift: 8
47
+ };
48
+
49
+ export interface PressKeyParams {
50
+ key: string;
51
+ }
52
+
53
+ export interface PressKeyResult {
54
+ key: string;
55
+ modifiers: string[];
56
+ }
57
+
58
+ /**
59
+ * Parse a key string like "Control+a", "Meta+Shift+Enter", or "Tab".
60
+ */
61
+ function parseKeyCombo(input: string): {
62
+ modifiers: number;
63
+ modifierNames: string[];
64
+ keyInfo: { key: string; code: string; keyCode?: number; text?: string };
65
+ } {
66
+ const parts = input.split('+');
67
+ let modifiers = 0;
68
+ const modifierNames: string[] = [];
69
+
70
+ // Last part is the actual key, everything before is a modifier
71
+ const keyPart = parts.pop()!;
72
+
73
+ for (const mod of parts) {
74
+ const flag = MODIFIER_FLAGS[mod.toLowerCase()];
75
+ if (flag) {
76
+ modifiers |= flag;
77
+ modifierNames.push(mod);
78
+ }
79
+ }
80
+
81
+ // Look up the key in our map
82
+ const mapped = KEY_MAP[keyPart.toLowerCase()];
83
+ if (mapped) {
84
+ return { modifiers, modifierNames, keyInfo: mapped };
85
+ }
86
+
87
+ // Single character key
88
+ if (keyPart.length === 1) {
89
+ const charCode = keyPart.charCodeAt(0);
90
+ return {
91
+ modifiers,
92
+ modifierNames,
93
+ keyInfo: {
94
+ key: keyPart,
95
+ code: `Key${keyPart.toUpperCase()}`,
96
+ keyCode: charCode,
97
+ text: modifiers === 0 ? keyPart : undefined
98
+ }
99
+ };
100
+ }
101
+
102
+ // Unknown named key — pass through
103
+ return {
104
+ modifiers,
105
+ modifierNames,
106
+ keyInfo: { key: keyPart, code: keyPart }
107
+ };
108
+ }
109
+
110
+ export async function executePressKey(
111
+ client: Client,
112
+ params: PressKeyParams
113
+ ): Promise<PressKeyResult> {
114
+ const { modifiers, modifierNames, keyInfo } = parseKeyCombo(params.key);
115
+
116
+ await client.Input.dispatchKeyEvent({
117
+ type: 'keyDown',
118
+ key: keyInfo.key,
119
+ code: keyInfo.code,
120
+ windowsVirtualKeyCode: keyInfo.keyCode,
121
+ modifiers,
122
+ ...(keyInfo.text && { text: keyInfo.text })
123
+ });
124
+
125
+ await client.Input.dispatchKeyEvent({
126
+ type: 'keyUp',
127
+ key: keyInfo.key,
128
+ code: keyInfo.code,
129
+ windowsVirtualKeyCode: keyInfo.keyCode,
130
+ modifiers
131
+ });
132
+
133
+ return { key: keyInfo.key, modifiers: modifierNames };
134
+ }
@@ -0,0 +1,79 @@
1
+ import type { Client } from 'chrome-remote-interface';
2
+ import type { ElementRefMap } from '../browser/inspect/element-ref.js';
3
+
4
+ export interface ScrollParams {
5
+ ref?: string;
6
+ x?: number;
7
+ y?: number;
8
+ direction?: 'up' | 'down' | 'left' | 'right';
9
+ amount?: number;
10
+ }
11
+
12
+ export interface ScrollResult {
13
+ scrollX: number;
14
+ scrollY: number;
15
+ }
16
+
17
+ /**
18
+ * Scroll the page or an element.
19
+ * - If ref is given, scrolls the element into view.
20
+ * - If direction/amount is given, scrolls the page.
21
+ * - If x/y is given, scrolls the page to absolute coordinates.
22
+ */
23
+ export async function executeScroll(
24
+ client: Client,
25
+ refMap: ElementRefMap,
26
+ params: ScrollParams
27
+ ): Promise<ScrollResult> {
28
+ if (params.ref) {
29
+ // Scroll element into view
30
+ const backendNodeId = refMap.resolve(params.ref);
31
+ await client.DOM.scrollIntoViewIfNeeded({ backendNodeId });
32
+
33
+ const { result } = await client.Runtime.evaluate({
34
+ expression: `JSON.stringify({ scrollX: window.scrollX, scrollY: window.scrollY })`,
35
+ returnByValue: true
36
+ });
37
+ const pos = JSON.parse(String(result.value));
38
+ return { scrollX: pos.scrollX, scrollY: pos.scrollY };
39
+ }
40
+
41
+ if (params.direction) {
42
+ const amount = params.amount ?? 300;
43
+ const deltaX =
44
+ params.direction === 'left'
45
+ ? -amount
46
+ : params.direction === 'right'
47
+ ? amount
48
+ : 0;
49
+ const deltaY =
50
+ params.direction === 'up'
51
+ ? -amount
52
+ : params.direction === 'down'
53
+ ? amount
54
+ : 0;
55
+
56
+ await client.Input.dispatchMouseEvent({
57
+ type: 'mouseWheel',
58
+ x: 0,
59
+ y: 0,
60
+ deltaX,
61
+ deltaY
62
+ });
63
+
64
+ // Small delay for scroll to take effect
65
+ await new Promise((r) => setTimeout(r, 100));
66
+ } else if (params.x !== undefined || params.y !== undefined) {
67
+ await client.Runtime.evaluate({
68
+ expression: `window.scrollTo(${params.x ?? 0}, ${params.y ?? 0})`,
69
+ awaitPromise: false
70
+ });
71
+ }
72
+
73
+ const { result } = await client.Runtime.evaluate({
74
+ expression: `JSON.stringify({ scrollX: window.scrollX, scrollY: window.scrollY })`,
75
+ returnByValue: true
76
+ });
77
+ const pos = JSON.parse(String(result.value));
78
+ return { scrollX: pos.scrollX, scrollY: pos.scrollY };
79
+ }
@@ -0,0 +1,78 @@
1
+ import type { Client } from 'chrome-remote-interface';
2
+ import type { ElementRefMap } from '../browser/inspect/element-ref.js';
3
+ import { resolveRef, focusRef } from '../browser/interaction/ref-resolver.js';
4
+
5
+ export interface SelectParams {
6
+ ref: string;
7
+ value?: string;
8
+ label?: string;
9
+ index?: number;
10
+ }
11
+
12
+ export interface SelectResult {
13
+ ref: string;
14
+ selectedValue: string;
15
+ selectedLabel: string;
16
+ }
17
+
18
+ /**
19
+ * Select an option in a <select> element by value, label, or index.
20
+ */
21
+ export async function executeSelect(
22
+ client: Client,
23
+ refMap: ElementRefMap,
24
+ params: SelectParams
25
+ ): Promise<SelectResult> {
26
+ const resolved = await resolveRef(client, refMap, params.ref);
27
+
28
+ await focusRef(client, resolved.backendNodeId);
29
+
30
+ const { result, exceptionDetails } = await client.Runtime.callFunctionOn({
31
+ objectId: resolved.objectId,
32
+ functionDeclaration: `function(byValue, byLabel, byIndex) {
33
+ if (this.tagName.toLowerCase() !== 'select') {
34
+ throw new Error('Element is not a <select>');
35
+ }
36
+ var found = false;
37
+ for (var i = 0; i < this.options.length; i++) {
38
+ var opt = this.options[i];
39
+ if (byValue !== null && opt.value === byValue) {
40
+ this.selectedIndex = i; found = true; break;
41
+ }
42
+ if (byLabel !== null && opt.textContent.trim() === byLabel) {
43
+ this.selectedIndex = i; found = true; break;
44
+ }
45
+ if (byIndex !== null && i === byIndex) {
46
+ this.selectedIndex = i; found = true; break;
47
+ }
48
+ }
49
+ if (!found) throw new Error('Option not found');
50
+ this.dispatchEvent(new Event('input', { bubbles: true }));
51
+ this.dispatchEvent(new Event('change', { bubbles: true }));
52
+ var sel = this.options[this.selectedIndex];
53
+ return { value: sel.value, label: sel.textContent.trim() };
54
+ }`,
55
+ arguments: [
56
+ { value: params.value ?? null },
57
+ { value: params.label ?? null },
58
+ { value: params.index ?? null }
59
+ ],
60
+ returnByValue: true,
61
+ awaitPromise: false
62
+ });
63
+
64
+ if (exceptionDetails) {
65
+ throw new Error(
66
+ exceptionDetails.exception?.description ??
67
+ exceptionDetails.text ??
68
+ 'Failed to select option'
69
+ );
70
+ }
71
+
72
+ const selected = result.value as { value: string; label: string };
73
+ return {
74
+ ref: params.ref,
75
+ selectedValue: selected.value,
76
+ selectedLabel: selected.label
77
+ };
78
+ }
@@ -0,0 +1,18 @@
1
+ import type { Client } from 'chrome-remote-interface';
2
+ import type { ElementRefMap } from '../browser/inspect/element-ref.js';
3
+ import { buildSnapshot, formatSnapshot } from '../browser/inspect/snapshot.js';
4
+ import type { SnapshotResult } from '../browser/inspect/types.js';
5
+
6
+ export interface SnapshotCommandResult {
7
+ text: string;
8
+ snapshot: SnapshotResult;
9
+ }
10
+
11
+ export async function executeSnapshot(
12
+ client: Client,
13
+ refMap: ElementRefMap
14
+ ): Promise<SnapshotCommandResult> {
15
+ const snapshot = await buildSnapshot(client, refMap);
16
+ const text = formatSnapshot(snapshot);
17
+ return { text, snapshot };
18
+ }
@@ -0,0 +1,24 @@
1
+ import type { Client } from 'chrome-remote-interface';
2
+ import type { ElementRefMap } from '../browser/inspect/element-ref.js';
3
+ import { getStyles, formatStyles } from '../browser/inspect/styles.js';
4
+ import type { StylesResult } from '../browser/inspect/styles.js';
5
+
6
+ export interface StylesParams {
7
+ ref: string;
8
+ properties?: string[];
9
+ }
10
+
11
+ export interface StylesCommandResult {
12
+ text: string;
13
+ styles: StylesResult;
14
+ }
15
+
16
+ export async function executeStyles(
17
+ client: Client,
18
+ refMap: ElementRefMap,
19
+ params: StylesParams
20
+ ): Promise<StylesCommandResult> {
21
+ const styles = await getStyles(client, refMap, params.ref, params.properties);
22
+ const text = formatStyles(styles);
23
+ return { text, styles };
24
+ }
@@ -1,8 +1,11 @@
1
1
  import { z } from 'zod';
2
2
  import type { Client } from 'chrome-remote-interface';
3
+ import type { ElementRefMap } from '../browser/inspect/element-ref.js';
4
+ import { resolveRef, focusRef } from '../browser/interaction/ref-resolver.js';
3
5
 
4
6
  export const TypeParamsSchema = z.object({
5
7
  text: z.string(),
8
+ ref: z.string().optional(),
6
9
  selector: z.string().optional(),
7
10
  clearFirst: z.boolean().default(false),
8
11
  delayMs: z.number().int().min(0).default(0)
@@ -30,9 +33,16 @@ async function focusSelector(client: Client, selector: string): Promise<void> {
30
33
 
31
34
  export async function executeType(
32
35
  client: Client,
33
- params: TypeParams
36
+ params: TypeParams,
37
+ refMap?: ElementRefMap
34
38
  ): Promise<TypeResult> {
35
- if (params.selector) {
39
+ if (params.ref) {
40
+ if (!refMap) {
41
+ throw new Error('Element ref map is required when using ref parameter');
42
+ }
43
+ const resolved = await resolveRef(client, refMap, params.ref);
44
+ await focusRef(client, resolved.backendNodeId);
45
+ } else if (params.selector) {
36
46
  await focusSelector(client, params.selector);
37
47
  }
38
48
 
@@ -0,0 +1,36 @@
1
+ import type { Client } from 'chrome-remote-interface';
2
+ import type { ElementRefMap } from '../browser/inspect/element-ref.js';
3
+ import {
4
+ validateUploadFiles,
5
+ uploadFiles
6
+ } from '../browser/interaction/uploads.js';
7
+
8
+ export interface UploadParams {
9
+ ref: string;
10
+ files: string[];
11
+ }
12
+
13
+ export interface UploadResult {
14
+ ref: string;
15
+ files: string[];
16
+ }
17
+
18
+ export async function executeUpload(
19
+ client: Client,
20
+ refMap: ElementRefMap,
21
+ params: UploadParams
22
+ ): Promise<UploadResult> {
23
+ if (params.files.length === 0) {
24
+ throw new Error('At least one file is required');
25
+ }
26
+
27
+ const backendNodeId = refMap.resolve(params.ref);
28
+
29
+ // Validate files before uploading
30
+ validateUploadFiles(params.files);
31
+
32
+ // Upload to the file input element
33
+ await uploadFiles(client, backendNodeId, params.files);
34
+
35
+ return { ref: params.ref, files: params.files };
36
+ }
@@ -1,11 +1,21 @@
1
1
  export type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug';
2
2
 
3
+ export interface StackFrame {
4
+ url: string;
5
+ functionName: string;
6
+ lineNumber: number;
7
+ columnNumber: number;
8
+ }
9
+
3
10
  export interface ConsoleMessage {
4
11
  level: ConsoleLevel;
5
12
  text: string;
6
13
  url: string;
7
14
  lineNumber: number;
15
+ columnNumber?: number;
8
16
  timestamp: number;
17
+ stackFrames?: StackFrame[];
18
+ isException?: boolean;
9
19
  }
10
20
 
11
21
  export interface ConsoleFilter {
package/src/mcp/server.ts CHANGED
@@ -1,9 +1,29 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { BrowserManager } from '../browser.js';
3
+ import { ElementRefMap } from '../browser/inspect/element-ref.js';
4
+ import { resetCssState } from '../browser/inspect/styles.js';
5
+ import { DialogQueue } from '../browser/interaction/dialogs.js';
6
+ import { attachDialogHandler } from '../browser/interaction/dialogs.js';
7
+ import {
8
+ DownloadTracker,
9
+ enableDownloads,
10
+ attachDownloadHandler
11
+ } from '../browser/interaction/downloads.js';
12
+ import { NetworkBuffer } from '../browser/network/network-buffer.js';
13
+ import { attachNetworkMonitor } from '../browser/network/network-monitor.js';
3
14
  import { loadConfig } from '../util/config.js';
4
15
  import { ConsoleBuffer, type ConsoleMessage } from './console-buffer.js';
5
16
  import { registerBrowserTools } from './tools/browser.js';
6
17
  import { registerErrorTools } from './tools/errors.js';
18
+ import { registerSnapshotTools } from './tools/snapshot.js';
19
+ import { registerInteractionTools } from './tools/interaction.js';
20
+ import { registerNetworkTools } from './tools/network.js';
21
+ import { registerRuntimeTools } from './tools/runtime.js';
22
+ import { registerStylesTools } from './tools/styles.js';
23
+ import { registerFilesTools } from './tools/files.js';
24
+ import { createTraceState } from '../browser/performance/trace.js';
25
+ import { registerPerformanceTools } from './tools/performance.js';
26
+ import { registerConnectTools } from './tools/connect.js';
7
27
 
8
28
  export interface McpConfig {
9
29
  bufferSize: number;
@@ -14,6 +34,11 @@ export interface McpConfig {
14
34
  export interface BrowserContext {
15
35
  manager: BrowserManager | null;
16
36
  consoleBuffer: ConsoleBuffer;
37
+ elementRefMap: ElementRefMap;
38
+ networkBuffer: NetworkBuffer;
39
+ dialogQueue: DialogQueue;
40
+ downloadTracker: DownloadTracker;
41
+ traceState: ReturnType<typeof createTraceState>;
17
42
  baseConfig: McpConfig;
18
43
  }
19
44
 
@@ -27,18 +52,57 @@ export async function createMcpServer(config: McpConfig): Promise<{
27
52
  });
28
53
 
29
54
  const consoleBuffer = new ConsoleBuffer(config.bufferSize);
55
+ const elementRefMap = new ElementRefMap();
56
+ const networkBuffer = new NetworkBuffer();
57
+ const dialogQueue = new DialogQueue();
58
+ const downloadTracker = new DownloadTracker();
59
+ const traceState = createTraceState();
30
60
 
31
61
  const context: BrowserContext = {
32
62
  manager: null,
33
63
  consoleBuffer,
64
+ elementRefMap,
65
+ networkBuffer,
66
+ dialogQueue,
67
+ downloadTracker,
68
+ traceState,
34
69
  baseConfig: config
35
70
  };
36
71
 
37
- function attachConsoleBuffer(manager: BrowserManager): void {
72
+ function attachEventHandlers(manager: BrowserManager): void {
73
+ let monitoredClient: unknown = null;
74
+
75
+ function ensureMonitors(): void {
76
+ const client = manager.getClient();
77
+ if (client && client !== monitoredClient) {
78
+ attachNetworkMonitor(client, networkBuffer);
79
+ attachDialogHandler(client, dialogQueue);
80
+ attachDownloadHandler(client, downloadTracker);
81
+ void enableDownloads(client).catch(() => {
82
+ // Download behavior setup may fail in some environments
83
+ });
84
+ monitoredClient = client;
85
+ }
86
+ }
87
+
38
88
  manager.setEventCallback((event, data) => {
39
89
  if (event === 'console_message') {
40
90
  consoleBuffer.push(data as ConsoleMessage);
41
91
  }
92
+ if (event === 'page_navigated') {
93
+ elementRefMap.invalidate();
94
+ }
95
+ if (event === 'browser_connected') {
96
+ ensureMonitors();
97
+ }
98
+ if (event === 'browser_disconnected') {
99
+ monitoredClient = null;
100
+ resetCssState();
101
+ dialogQueue.clear();
102
+ downloadTracker.clear();
103
+ }
104
+ // Reattach after tab switch (new client, no connect event)
105
+ ensureMonitors();
42
106
  });
43
107
  }
44
108
 
@@ -48,12 +112,20 @@ export async function createMcpServer(config: McpConfig): Promise<{
48
112
  cdpHost: config.cdpHost
49
113
  });
50
114
  const manager = new BrowserManager(browserConfig);
51
- attachConsoleBuffer(manager);
115
+ attachEventHandlers(manager);
52
116
  return manager;
53
117
  }
54
118
 
55
119
  registerBrowserTools(server, context, makeBrowserManager);
56
120
  registerErrorTools(server, consoleBuffer);
121
+ registerSnapshotTools(server, context);
122
+ registerInteractionTools(server, context);
123
+ registerNetworkTools(server, context);
124
+ registerRuntimeTools(server, consoleBuffer);
125
+ registerStylesTools(server, context);
126
+ registerFilesTools(server, context);
127
+ registerPerformanceTools(server, context);
128
+ registerConnectTools(server, context, makeBrowserManager);
57
129
 
58
130
  return {
59
131
  server,