@everydaydevopsio/pilot 0.5.2 → 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.
- package/CHANGELOG.md +64 -0
- package/CLAUDE.md +7 -7
- package/README.md +108 -53
- package/dist/browser/browser-manager.d.ts +60 -0
- package/dist/browser/browser-manager.d.ts.map +1 -0
- package/dist/browser/browser-manager.js +348 -0
- package/dist/browser/browser-manager.js.map +1 -0
- package/dist/browser/chrome-launcher.d.ts +30 -0
- package/dist/browser/chrome-launcher.d.ts.map +1 -0
- package/dist/browser/chrome-launcher.js +217 -0
- package/dist/browser/chrome-launcher.js.map +1 -0
- package/dist/browser/connection.d.ts +23 -0
- package/dist/browser/connection.d.ts.map +1 -0
- package/dist/browser/connection.js +53 -0
- package/dist/browser/connection.js.map +1 -0
- package/dist/browser/events.d.ts +9 -0
- package/dist/browser/events.d.ts.map +1 -0
- package/dist/browser/events.js +99 -0
- package/dist/browser/events.js.map +1 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/inspect/element-ref.d.ts +23 -0
- package/dist/browser/inspect/element-ref.d.ts.map +1 -0
- package/dist/browser/inspect/element-ref.js +52 -0
- package/dist/browser/inspect/element-ref.js.map +1 -0
- package/dist/browser/inspect/snapshot.d.ts +11 -0
- package/dist/browser/inspect/snapshot.d.ts.map +1 -0
- package/dist/browser/inspect/snapshot.js +282 -0
- package/dist/browser/inspect/snapshot.js.map +1 -0
- package/dist/browser/inspect/styles.d.ts +45 -0
- package/dist/browser/inspect/styles.d.ts.map +1 -0
- package/dist/browser/inspect/styles.js +190 -0
- package/dist/browser/inspect/styles.js.map +1 -0
- package/dist/browser/inspect/types.d.ts +35 -0
- package/dist/browser/inspect/types.d.ts.map +1 -0
- package/dist/browser/inspect/types.js +2 -0
- package/dist/browser/inspect/types.js.map +1 -0
- package/dist/browser/interaction/dialogs.d.ts +18 -0
- package/dist/browser/interaction/dialogs.d.ts.map +1 -0
- package/dist/browser/interaction/dialogs.js +35 -0
- package/dist/browser/interaction/dialogs.js.map +1 -0
- package/dist/browser/interaction/downloads.d.ts +23 -0
- package/dist/browser/interaction/downloads.d.ts.map +1 -0
- package/dist/browser/interaction/downloads.js +87 -0
- package/dist/browser/interaction/downloads.js.map +1 -0
- package/dist/browser/interaction/events.d.ts +17 -0
- package/dist/browser/interaction/events.d.ts.map +1 -0
- package/dist/browser/interaction/events.js +66 -0
- package/dist/browser/interaction/events.js.map +1 -0
- package/dist/browser/interaction/ref-resolver.d.ts +18 -0
- package/dist/browser/interaction/ref-resolver.d.ts.map +1 -0
- package/dist/browser/interaction/ref-resolver.js +32 -0
- package/dist/browser/interaction/ref-resolver.js.map +1 -0
- package/dist/browser/interaction/uploads.d.ts +4 -0
- package/dist/browser/interaction/uploads.d.ts.map +1 -0
- package/dist/browser/interaction/uploads.js +43 -0
- package/dist/browser/interaction/uploads.js.map +1 -0
- package/dist/browser/network/network-buffer.d.ts +19 -0
- package/dist/browser/network/network-buffer.d.ts.map +1 -0
- package/dist/browser/network/network-buffer.js +118 -0
- package/dist/browser/network/network-buffer.js.map +1 -0
- package/dist/browser/network/network-monitor.d.ts +8 -0
- package/dist/browser/network/network-monitor.d.ts.map +1 -0
- package/dist/browser/network/network-monitor.js +85 -0
- package/dist/browser/network/network-monitor.js.map +1 -0
- package/dist/browser/network/redaction.d.ts +3 -0
- package/dist/browser/network/redaction.d.ts.map +1 -0
- package/dist/browser/network/redaction.js +36 -0
- package/dist/browser/network/redaction.js.map +1 -0
- package/dist/browser/network/types.d.ts +45 -0
- package/dist/browser/network/types.d.ts.map +1 -0
- package/dist/browser/network/types.js +2 -0
- package/dist/browser/network/types.js.map +1 -0
- package/dist/browser/performance/analyze.d.ts +5 -0
- package/dist/browser/performance/analyze.d.ts.map +1 -0
- package/dist/browser/performance/analyze.js +230 -0
- package/dist/browser/performance/analyze.js.map +1 -0
- package/dist/browser/performance/trace.d.ts +10 -0
- package/dist/browser/performance/trace.d.ts.map +1 -0
- package/dist/browser/performance/trace.js +38 -0
- package/dist/browser/performance/trace.js.map +1 -0
- package/dist/browser/performance/types.d.ts +31 -0
- package/dist/browser/performance/types.d.ts.map +1 -0
- package/dist/browser/performance/types.js +2 -0
- package/dist/browser/performance/types.js.map +1 -0
- package/dist/browser/security/origins.d.ts +18 -0
- package/dist/browser/security/origins.d.ts.map +1 -0
- package/dist/browser/security/origins.js +84 -0
- package/dist/browser/security/origins.js.map +1 -0
- package/dist/browser/tabs.d.ts +15 -0
- package/dist/browser/tabs.d.ts.map +1 -0
- package/dist/browser/tabs.js +71 -0
- package/dist/browser/tabs.js.map +1 -0
- package/dist/browser/types.d.ts +31 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/browser.d.ts +2 -99
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +3 -653
- package/dist/browser.js.map +1 -1
- package/dist/commands/check.d.ts +17 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +38 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/click.d.ts +3 -1
- package/dist/commands/click.d.ts.map +1 -1
- package/dist/commands/click.js +16 -4
- package/dist/commands/click.js.map +1 -1
- package/dist/commands/connect.d.ts +14 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +19 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/dialog.d.ts +19 -0
- package/dist/commands/dialog.d.ts.map +1 -0
- package/dist/commands/dialog.js +51 -0
- package/dist/commands/dialog.js.map +1 -0
- package/dist/commands/downloads.d.ts +30 -0
- package/dist/commands/downloads.d.ts.map +1 -0
- package/dist/commands/downloads.js +66 -0
- package/dist/commands/downloads.js.map +1 -0
- package/dist/commands/fill.d.ts +16 -0
- package/dist/commands/fill.d.ts.map +1 -0
- package/dist/commands/fill.js +15 -0
- package/dist/commands/fill.js.map +1 -0
- package/dist/commands/find.d.ts +14 -0
- package/dist/commands/find.d.ts.map +1 -0
- package/dist/commands/find.js +26 -0
- package/dist/commands/find.js.map +1 -0
- package/dist/commands/hover.d.ts +13 -0
- package/dist/commands/hover.d.ts.map +1 -0
- package/dist/commands/hover.js +24 -0
- package/dist/commands/hover.js.map +1 -0
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +13 -0
- package/dist/commands/navigate.js.map +1 -1
- package/dist/commands/network.d.ts +33 -0
- package/dist/commands/network.d.ts.map +1 -0
- package/dist/commands/network.js +84 -0
- package/dist/commands/network.js.map +1 -0
- package/dist/commands/performance.d.ts +12 -0
- package/dist/commands/performance.d.ts.map +1 -0
- package/dist/commands/performance.js +26 -0
- package/dist/commands/performance.js.map +1 -0
- package/dist/commands/press_key.d.ts +10 -0
- package/dist/commands/press_key.d.ts.map +1 -0
- package/dist/commands/press_key.js +103 -0
- package/dist/commands/press_key.js.map +1 -0
- package/dist/commands/scroll.d.ts +21 -0
- package/dist/commands/scroll.d.ts.map +1 -0
- package/dist/commands/scroll.js +54 -0
- package/dist/commands/scroll.js.map +1 -0
- package/dist/commands/select.d.ts +18 -0
- package/dist/commands/select.d.ts.map +1 -0
- package/dist/commands/select.js +53 -0
- package/dist/commands/select.js.map +1 -0
- package/dist/commands/snapshot.d.ts +9 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +7 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/styles.d.ts +13 -0
- package/dist/commands/styles.d.ts.map +1 -0
- package/dist/commands/styles.js +7 -0
- package/dist/commands/styles.js.map +1 -0
- package/dist/commands/type.d.ts +3 -1
- package/dist/commands/type.d.ts.map +1 -1
- package/dist/commands/type.js +11 -2
- package/dist/commands/type.js.map +1 -1
- package/dist/commands/upload.d.ts +12 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +13 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/mcp/console-buffer.d.ts +9 -0
- package/dist/mcp/console-buffer.d.ts.map +1 -1
- package/dist/mcp/console-buffer.js.map +1 -1
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +63 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/browser.d.ts.map +1 -1
- package/dist/mcp/tools/browser.js +99 -8
- package/dist/mcp/tools/browser.js.map +1 -1
- package/dist/mcp/tools/connect.d.ts +5 -0
- package/dist/mcp/tools/connect.d.ts.map +1 -0
- package/dist/mcp/tools/connect.js +48 -0
- package/dist/mcp/tools/connect.js.map +1 -0
- package/dist/mcp/tools/files.d.ts +4 -0
- package/dist/mcp/tools/files.d.ts.map +1 -0
- package/dist/mcp/tools/files.js +85 -0
- package/dist/mcp/tools/files.js.map +1 -0
- package/dist/mcp/tools/interaction.d.ts +4 -0
- package/dist/mcp/tools/interaction.d.ts.map +1 -0
- package/dist/mcp/tools/interaction.js +176 -0
- package/dist/mcp/tools/interaction.js.map +1 -0
- package/dist/mcp/tools/names.d.ts +1 -1
- package/dist/mcp/tools/names.d.ts.map +1 -1
- package/dist/mcp/tools/names.js +19 -1
- package/dist/mcp/tools/names.js.map +1 -1
- package/dist/mcp/tools/network.d.ts +4 -0
- package/dist/mcp/tools/network.d.ts.map +1 -0
- package/dist/mcp/tools/network.js +68 -0
- package/dist/mcp/tools/network.js.map +1 -0
- package/dist/mcp/tools/performance.d.ts +4 -0
- package/dist/mcp/tools/performance.d.ts.map +1 -0
- package/dist/mcp/tools/performance.js +26 -0
- package/dist/mcp/tools/performance.js.map +1 -0
- package/dist/mcp/tools/runtime.d.ts +4 -0
- package/dist/mcp/tools/runtime.d.ts.map +1 -0
- package/dist/mcp/tools/runtime.js +128 -0
- package/dist/mcp/tools/runtime.js.map +1 -0
- package/dist/mcp/tools/snapshot.d.ts +4 -0
- package/dist/mcp/tools/snapshot.d.ts.map +1 -0
- package/dist/mcp/tools/snapshot.js +42 -0
- package/dist/mcp/tools/snapshot.js.map +1 -0
- package/dist/mcp/tools/styles.d.ts +4 -0
- package/dist/mcp/tools/styles.d.ts.map +1 -0
- package/dist/mcp/tools/styles.js +27 -0
- package/dist/mcp/tools/styles.js.map +1 -0
- package/dist/util/config.d.ts.map +1 -1
- package/dist/util/config.js +3 -2
- package/dist/util/config.js.map +1 -1
- package/package.json +3 -3
- package/src/browser/browser-manager.ts +457 -0
- package/src/browser/chrome-launcher.ts +271 -0
- package/src/browser/connection.ts +84 -0
- package/src/browser/events.ts +121 -0
- package/src/browser/index.ts +20 -0
- package/src/browser/inspect/element-ref.ts +68 -0
- package/src/browser/inspect/snapshot.ts +348 -0
- package/src/browser/inspect/styles.ts +258 -0
- package/src/browser/inspect/types.ts +37 -0
- package/src/browser/interaction/dialogs.ts +54 -0
- package/src/browser/interaction/downloads.ts +116 -0
- package/src/browser/interaction/events.ts +79 -0
- package/src/browser/interaction/ref-resolver.ts +53 -0
- package/src/browser/interaction/uploads.ts +60 -0
- package/src/browser/network/network-buffer.ts +133 -0
- package/src/browser/network/network-monitor.ts +107 -0
- package/src/browser/network/redaction.ts +42 -0
- package/src/browser/network/types.ts +47 -0
- package/src/browser/performance/analyze.ts +298 -0
- package/src/browser/performance/trace.ts +60 -0
- package/src/browser/performance/types.ts +34 -0
- package/src/browser/security/origins.ts +102 -0
- package/src/browser/tabs.ts +110 -0
- package/src/browser/types.ts +31 -0
- package/src/browser.ts +22 -798
- package/src/commands/check.ts +59 -0
- package/src/commands/click.ts +18 -4
- package/src/commands/connect.ts +40 -0
- package/src/commands/dialog.ts +79 -0
- package/src/commands/downloads.ts +111 -0
- package/src/commands/fill.ts +34 -0
- package/src/commands/find.ts +52 -0
- package/src/commands/hover.ts +42 -0
- package/src/commands/navigate.ts +20 -0
- package/src/commands/network.ts +141 -0
- package/src/commands/performance.ts +51 -0
- package/src/commands/press_key.ts +134 -0
- package/src/commands/scroll.ts +79 -0
- package/src/commands/select.ts +78 -0
- package/src/commands/snapshot.ts +18 -0
- package/src/commands/styles.ts +24 -0
- package/src/commands/type.ts +12 -2
- package/src/commands/upload.ts +36 -0
- package/src/mcp/console-buffer.ts +10 -0
- package/src/mcp/server.ts +74 -2
- package/src/mcp/tools/browser.ts +113 -7
- package/src/mcp/tools/connect.ts +62 -0
- package/src/mcp/tools/files.ts +120 -0
- package/src/mcp/tools/interaction.ts +232 -0
- package/src/mcp/tools/names.ts +19 -1
- package/src/mcp/tools/network.ts +86 -0
- package/src/mcp/tools/performance.ts +40 -0
- package/src/mcp/tools/runtime.ts +164 -0
- package/src/mcp/tools/snapshot.ts +64 -0
- package/src/mcp/tools/styles.ts +41 -0
- 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
|
+
}
|
package/src/commands/type.ts
CHANGED
|
@@ -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.
|
|
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
|
|
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
|
-
|
|
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,
|