@dyyz1993/agent-browser 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +907 -0
- package/bin/agent-browser-darwin-arm64 +0 -0
- package/bin/agent-browser.js +120 -0
- package/dist/__tests__/e2e/utils/test-helpers.d.ts +5 -0
- package/dist/__tests__/e2e/utils/test-helpers.d.ts.map +1 -0
- package/dist/__tests__/e2e/utils/test-helpers.js +22 -0
- package/dist/__tests__/e2e/utils/test-helpers.js.map +1 -0
- package/dist/__tests__/test-iframe.d.ts +2 -0
- package/dist/__tests__/test-iframe.d.ts.map +1 -0
- package/dist/__tests__/test-iframe.js +52 -0
- package/dist/__tests__/test-iframe.js.map +1 -0
- package/dist/__tests__/utils/parseCli.d.ts +20 -0
- package/dist/__tests__/utils/parseCli.d.ts.map +1 -0
- package/dist/__tests__/utils/parseCli.js +1086 -0
- package/dist/__tests__/utils/parseCli.js.map +1 -0
- package/dist/actions.d.ts +50 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +2164 -0
- package/dist/actions.js.map +1 -0
- package/dist/browser.d.ts +556 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +2599 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli/commands.d.ts +8 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +1038 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/connection.d.ts +50 -0
- package/dist/cli/connection.d.ts.map +1 -0
- package/dist/cli/connection.js +595 -0
- package/dist/cli/connection.js.map +1 -0
- package/dist/cli/flags.d.ts +36 -0
- package/dist/cli/flags.d.ts.map +1 -0
- package/dist/cli/flags.js +206 -0
- package/dist/cli/flags.js.map +1 -0
- package/dist/cli/help.d.ts +4 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +1024 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/output.d.ts +14 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +456 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli-new.d.ts +3 -0
- package/dist/cli-new.d.ts.map +1 -0
- package/dist/cli-new.js +308 -0
- package/dist/cli-new.js.map +1 -0
- package/dist/cli-old.d.ts +3 -0
- package/dist/cli-old.d.ts.map +1 -0
- package/dist/cli-old.js +1101 -0
- package/dist/cli-old.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +403 -0
- package/dist/cli.js.map +1 -0
- package/dist/content-detection.d.ts +18 -0
- package/dist/content-detection.d.ts.map +1 -0
- package/dist/content-detection.js +68 -0
- package/dist/content-detection.js.map +1 -0
- package/dist/daemon.d.ts +55 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +426 -0
- package/dist/daemon.js.map +1 -0
- package/dist/diff.d.ts +42 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +166 -0
- package/dist/diff.js.map +1 -0
- package/dist/human-mouse.d.ts +31 -0
- package/dist/human-mouse.d.ts.map +1 -0
- package/dist/human-mouse.js +184 -0
- package/dist/human-mouse.js.map +1 -0
- package/dist/ios-actions.d.ts +11 -0
- package/dist/ios-actions.d.ts.map +1 -0
- package/dist/ios-actions.js +228 -0
- package/dist/ios-actions.js.map +1 -0
- package/dist/ios-manager.d.ts +266 -0
- package/dist/ios-manager.d.ts.map +1 -0
- package/dist/ios-manager.js +1076 -0
- package/dist/ios-manager.js.map +1 -0
- package/dist/message-bridge.d.ts +10 -0
- package/dist/message-bridge.d.ts.map +1 -0
- package/dist/message-bridge.js +60 -0
- package/dist/message-bridge.js.map +1 -0
- package/dist/protocol.d.ts +26 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +912 -0
- package/dist/protocol.js.map +1 -0
- package/dist/recorder/binding.d.ts +24 -0
- package/dist/recorder/binding.d.ts.map +1 -0
- package/dist/recorder/binding.js +215 -0
- package/dist/recorder/binding.js.map +1 -0
- package/dist/recorder/index.d.ts +4 -0
- package/dist/recorder/index.d.ts.map +1 -0
- package/dist/recorder/index.js +4 -0
- package/dist/recorder/index.js.map +1 -0
- package/dist/recorder/inject.js +1913 -0
- package/dist/recorder/recorder.d.ts +19 -0
- package/dist/recorder/recorder.d.ts.map +1 -0
- package/dist/recorder/recorder.js +101 -0
- package/dist/recorder/recorder.js.map +1 -0
- package/dist/recorder/store.d.ts +22 -0
- package/dist/recorder/store.d.ts.map +1 -0
- package/dist/recorder/store.js +150 -0
- package/dist/recorder/store.js.map +1 -0
- package/dist/recorder/types.d.ts +73 -0
- package/dist/recorder/types.d.ts.map +1 -0
- package/dist/recorder/types.js +5 -0
- package/dist/recorder/types.js.map +1 -0
- package/dist/snapshot.d.ts +81 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +1348 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/stream-server-standalone.d.ts +38 -0
- package/dist/stream-server-standalone.d.ts.map +1 -0
- package/dist/stream-server-standalone.js +494 -0
- package/dist/stream-server-standalone.js.map +1 -0
- package/dist/stream-server.d.ts +214 -0
- package/dist/stream-server.d.ts.map +1 -0
- package/dist/stream-server.js +811 -0
- package/dist/stream-server.js.map +1 -0
- package/dist/types.d.ts +914 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/viewer-html.d.ts +2 -0
- package/dist/viewer-html.d.ts.map +1 -0
- package/dist/viewer-html.js +185 -0
- package/dist/viewer-html.js.map +1 -0
- package/dist/viewer-script.d.ts +47 -0
- package/dist/viewer-script.d.ts.map +1 -0
- package/dist/viewer-script.js +586 -0
- package/dist/viewer-script.js.map +1 -0
- package/package.json +86 -0
- package/scripts/build-all-platforms.sh +68 -0
- package/scripts/check-version-sync.js +39 -0
- package/scripts/check_goods_container.js +35 -0
- package/scripts/check_page_content.js +36 -0
- package/scripts/click_applause_rate.js +30 -0
- package/scripts/copy-native.js +36 -0
- package/scripts/copy-recorder.js +21 -0
- package/scripts/e2e-test-recorder.ts +584 -0
- package/scripts/explore_jd_page.js +31 -0
- package/scripts/extract_all_jd_data.js +80 -0
- package/scripts/extract_jd_product_detail.js +62 -0
- package/scripts/extract_jd_products_correct_links.js +78 -0
- package/scripts/extract_jd_products_final.js +80 -0
- package/scripts/extract_jd_reviews.js +48 -0
- package/scripts/extract_jd_seafood_final.js +78 -0
- package/scripts/extract_multiple_products.js +77 -0
- package/scripts/extract_products_no_scroll.js +68 -0
- package/scripts/extract_products_simple.js +68 -0
- package/scripts/find_applause_rate.js +26 -0
- package/scripts/find_jd_links.js +28 -0
- package/scripts/find_main_content.js +20 -0
- package/scripts/find_product_cards.js +38 -0
- package/scripts/find_root_content.js +26 -0
- package/scripts/find_unique_products.js +55 -0
- package/scripts/get_jd_product_detail.js +16 -0
- package/scripts/get_jd_products.js +23 -0
- package/scripts/get_jd_seafood_products.js +44 -0
- package/scripts/get_product_details_from_images.js +54 -0
- package/scripts/postinstall.js +235 -0
- package/scripts/scroll_and_get_products.js +47 -0
- package/scripts/scroll_deep_and_find.js +45 -0
- package/scripts/sync-version.js +69 -0
- package/scripts/verify-baidu-enter.ts +116 -0
- package/skills/agent-browser/SKILL.md +310 -0
- package/skills/agent-browser/references/authentication.md +198 -0
- package/skills/agent-browser/references/commands.md +471 -0
- package/skills/agent-browser/references/data-extraction.md +377 -0
- package/skills/agent-browser/references/proxy-support.md +188 -0
- package/skills/agent-browser/references/session-management.md +197 -0
- package/skills/agent-browser/references/snapshot-refs.md +379 -0
- package/skills/agent-browser/references/video-recording.md +173 -0
- package/skills/agent-browser/templates/api-interception.sh +53 -0
- package/skills/agent-browser/templates/authenticated-session.sh +97 -0
- package/skills/agent-browser/templates/capture-workflow.sh +69 -0
- package/skills/agent-browser/templates/data-extraction.sh +210 -0
- package/skills/agent-browser/templates/form-automation.sh +62 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +356 -0
- package/skills/skill-creator/references/output-patterns.md +82 -0
- package/skills/skill-creator/references/workflows.md +28 -0
- package/skills/skill-creator/scripts/init_skill.py +303 -0
- package/skills/skill-creator/scripts/package_skill.py +113 -0
- package/skills/skill-creator/scripts/quick_validate.py +95 -0
|
@@ -0,0 +1,1086 @@
|
|
|
1
|
+
export class CliError extends Error {
|
|
2
|
+
usage;
|
|
3
|
+
constructor(message, usage) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.usage = usage;
|
|
6
|
+
this.name = 'CliError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function error(message, usage) {
|
|
10
|
+
throw new CliError(message, usage);
|
|
11
|
+
}
|
|
12
|
+
export function parseInFrame(args) {
|
|
13
|
+
let inFrame;
|
|
14
|
+
const remaining = [];
|
|
15
|
+
for (let i = 0; i < args.length; i++) {
|
|
16
|
+
if (args[i] === '--in-frame') {
|
|
17
|
+
inFrame = args[i + 1];
|
|
18
|
+
i++;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
remaining.push(args[i]);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { inFrame, remaining };
|
|
25
|
+
}
|
|
26
|
+
export function parseDiff(args) {
|
|
27
|
+
const diffIdx = args.indexOf('--diff');
|
|
28
|
+
if (diffIdx === -1) {
|
|
29
|
+
return { remaining: args };
|
|
30
|
+
}
|
|
31
|
+
const remaining = [...args];
|
|
32
|
+
remaining.splice(diffIdx, 1);
|
|
33
|
+
const nextArg = remaining[diffIdx];
|
|
34
|
+
if (nextArg === 'full') {
|
|
35
|
+
remaining.splice(diffIdx, 1);
|
|
36
|
+
return { diffScope: 'full', remaining };
|
|
37
|
+
}
|
|
38
|
+
if (nextArg && /^\d+$/.test(nextArg)) {
|
|
39
|
+
remaining.splice(diffIdx, 1);
|
|
40
|
+
return { diffScope: parseInt(nextArg, 10), remaining };
|
|
41
|
+
}
|
|
42
|
+
if (nextArg && !nextArg.startsWith('-') && !nextArg.startsWith('@')) {
|
|
43
|
+
remaining.splice(diffIdx, 1);
|
|
44
|
+
return { diffScope: nextArg, remaining };
|
|
45
|
+
}
|
|
46
|
+
return { diffScope: 3, remaining };
|
|
47
|
+
}
|
|
48
|
+
export function genId() {
|
|
49
|
+
return `n${Date.now() % 1000000}`;
|
|
50
|
+
}
|
|
51
|
+
export function parseCliArgs(args) {
|
|
52
|
+
if (args.length === 0) {
|
|
53
|
+
error('No command provided', 'agent-browser <command> [args...]');
|
|
54
|
+
}
|
|
55
|
+
const cmd = args[0];
|
|
56
|
+
const rest = args.slice(1);
|
|
57
|
+
const id = genId();
|
|
58
|
+
switch (cmd) {
|
|
59
|
+
case 'open':
|
|
60
|
+
case 'goto':
|
|
61
|
+
case 'navigate': {
|
|
62
|
+
const url = rest[0];
|
|
63
|
+
if (!url)
|
|
64
|
+
error('Missing URL', 'agent-browser open <url>');
|
|
65
|
+
const urlLower = url.toLowerCase();
|
|
66
|
+
const formattedUrl = urlLower.startsWith('http://') ||
|
|
67
|
+
urlLower.startsWith('https://') ||
|
|
68
|
+
urlLower.startsWith('about:') ||
|
|
69
|
+
urlLower.startsWith('data:') ||
|
|
70
|
+
urlLower.startsWith('file:')
|
|
71
|
+
? url
|
|
72
|
+
: `https://${url}`;
|
|
73
|
+
return { id, action: 'navigate', url: formattedUrl };
|
|
74
|
+
}
|
|
75
|
+
case 'back':
|
|
76
|
+
return { id, action: 'back' };
|
|
77
|
+
case 'forward':
|
|
78
|
+
return { id, action: 'forward' };
|
|
79
|
+
case 'reload':
|
|
80
|
+
return { id, action: 'reload' };
|
|
81
|
+
case 'click': {
|
|
82
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
83
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
84
|
+
const selector = remaining[0];
|
|
85
|
+
if (!selector)
|
|
86
|
+
error('Missing selector', 'agent-browser click <selector> [--diff [scope]] [--in-frame <path>]');
|
|
87
|
+
const cmd = { id, action: 'click', selector, inFrame };
|
|
88
|
+
if (diffScope !== undefined)
|
|
89
|
+
cmd.diffScope = diffScope;
|
|
90
|
+
return cmd;
|
|
91
|
+
}
|
|
92
|
+
case 'dblclick': {
|
|
93
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
94
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
95
|
+
const selector = remaining[0];
|
|
96
|
+
if (!selector)
|
|
97
|
+
error('Missing selector', 'agent-browser dblclick <selector> [--diff [scope]] [--in-frame <path>]');
|
|
98
|
+
const cmd = { id, action: 'dblclick', selector, inFrame };
|
|
99
|
+
if (diffScope !== undefined)
|
|
100
|
+
cmd.diffScope = diffScope;
|
|
101
|
+
return cmd;
|
|
102
|
+
}
|
|
103
|
+
case 'fill': {
|
|
104
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
105
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
106
|
+
const selector = remaining[0];
|
|
107
|
+
const value = remaining.slice(1).join(' ');
|
|
108
|
+
if (!selector || !value)
|
|
109
|
+
error('Missing selector or value', 'agent-browser fill <selector> <text> [--diff [scope]] [--in-frame <path>]');
|
|
110
|
+
const cmd = { id, action: 'fill', selector, value, inFrame };
|
|
111
|
+
if (diffScope !== undefined)
|
|
112
|
+
cmd.diffScope = diffScope;
|
|
113
|
+
return cmd;
|
|
114
|
+
}
|
|
115
|
+
case 'type': {
|
|
116
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
117
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
118
|
+
const selector = remaining[0];
|
|
119
|
+
const text = remaining.slice(1).join(' ');
|
|
120
|
+
if (!selector || !text)
|
|
121
|
+
error('Missing selector or text', 'agent-browser type <selector> <text> [--diff [scope]] [--in-frame <path>]');
|
|
122
|
+
const cmd = { id, action: 'type', selector, text, inFrame };
|
|
123
|
+
if (diffScope !== undefined)
|
|
124
|
+
cmd.diffScope = diffScope;
|
|
125
|
+
return cmd;
|
|
126
|
+
}
|
|
127
|
+
case 'hover': {
|
|
128
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
129
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
130
|
+
const selector = remaining[0];
|
|
131
|
+
if (!selector)
|
|
132
|
+
error('Missing selector', 'agent-browser hover <selector> [--diff [scope]] [--in-frame <path>]');
|
|
133
|
+
const cmd = { id, action: 'hover', selector, inFrame };
|
|
134
|
+
if (diffScope !== undefined)
|
|
135
|
+
cmd.diffScope = diffScope;
|
|
136
|
+
return cmd;
|
|
137
|
+
}
|
|
138
|
+
case 'focus': {
|
|
139
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
140
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
141
|
+
const selector = remaining[0];
|
|
142
|
+
if (!selector)
|
|
143
|
+
error('Missing selector', 'agent-browser focus <selector> [--diff [scope]] [--in-frame <path>]');
|
|
144
|
+
const cmd = { id, action: 'focus', selector, inFrame };
|
|
145
|
+
if (diffScope !== undefined)
|
|
146
|
+
cmd.diffScope = diffScope;
|
|
147
|
+
return cmd;
|
|
148
|
+
}
|
|
149
|
+
case 'check': {
|
|
150
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
151
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
152
|
+
const selector = remaining[0];
|
|
153
|
+
if (!selector)
|
|
154
|
+
error('Missing selector', 'agent-browser check <selector> [--diff [scope]] [--in-frame <path>]');
|
|
155
|
+
const cmd = { id, action: 'check', selector, inFrame };
|
|
156
|
+
if (diffScope !== undefined)
|
|
157
|
+
cmd.diffScope = diffScope;
|
|
158
|
+
return cmd;
|
|
159
|
+
}
|
|
160
|
+
case 'uncheck': {
|
|
161
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
162
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
163
|
+
const selector = remaining[0];
|
|
164
|
+
if (!selector)
|
|
165
|
+
error('Missing selector', 'agent-browser uncheck <selector> [--diff [scope]] [--in-frame <path>]');
|
|
166
|
+
const cmd = { id, action: 'uncheck', selector, inFrame };
|
|
167
|
+
if (diffScope !== undefined)
|
|
168
|
+
cmd.diffScope = diffScope;
|
|
169
|
+
return cmd;
|
|
170
|
+
}
|
|
171
|
+
case 'select': {
|
|
172
|
+
const { inFrame, remaining: r1 } = parseInFrame(rest);
|
|
173
|
+
const { diffScope, remaining } = parseDiff(r1);
|
|
174
|
+
const selector = remaining[0];
|
|
175
|
+
const values = remaining.slice(1);
|
|
176
|
+
if (!selector)
|
|
177
|
+
error('Missing selector', 'agent-browser select <selector> <value...> [--diff [scope]] [--in-frame <path>]');
|
|
178
|
+
if (values.length === 0)
|
|
179
|
+
error('Missing values', 'agent-browser select <selector> <value...> [--diff [scope]] [--in-frame <path>]');
|
|
180
|
+
const cmd = {
|
|
181
|
+
id,
|
|
182
|
+
action: 'select',
|
|
183
|
+
selector,
|
|
184
|
+
values: values.length === 1 ? values[0] : values,
|
|
185
|
+
inFrame,
|
|
186
|
+
};
|
|
187
|
+
if (diffScope !== undefined)
|
|
188
|
+
cmd.diffScope = diffScope;
|
|
189
|
+
return cmd;
|
|
190
|
+
}
|
|
191
|
+
case 'drag': {
|
|
192
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
193
|
+
const source = remaining[0];
|
|
194
|
+
const target = remaining[1];
|
|
195
|
+
if (!source)
|
|
196
|
+
error('Missing source selector', 'agent-browser drag <source> <target> [--in-frame <path>]');
|
|
197
|
+
if (!target)
|
|
198
|
+
error('Missing target selector', 'agent-browser drag <source> <target> [--in-frame <path>]');
|
|
199
|
+
return { id, action: 'drag', source, target, inFrame };
|
|
200
|
+
}
|
|
201
|
+
case 'upload': {
|
|
202
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
203
|
+
const selector = remaining[0];
|
|
204
|
+
const files = remaining.slice(1);
|
|
205
|
+
if (!selector)
|
|
206
|
+
error('Missing selector', 'agent-browser upload <selector> <files...> [--in-frame <path>]');
|
|
207
|
+
if (files.length === 0)
|
|
208
|
+
error('Missing files', 'agent-browser upload <selector> <files...> [--in-frame <path>]');
|
|
209
|
+
return { id, action: 'upload', selector, files, inFrame };
|
|
210
|
+
}
|
|
211
|
+
case 'download': {
|
|
212
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
213
|
+
const selector = remaining[0];
|
|
214
|
+
const path = remaining[1];
|
|
215
|
+
if (!selector)
|
|
216
|
+
error('Missing selector', 'agent-browser download <selector> <path> [--in-frame <path>]');
|
|
217
|
+
if (!path)
|
|
218
|
+
error('Missing path', 'agent-browser download <selector> <path> [--in-frame <path>]');
|
|
219
|
+
return { id, action: 'download', selector, path, inFrame };
|
|
220
|
+
}
|
|
221
|
+
case 'press':
|
|
222
|
+
case 'key': {
|
|
223
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
224
|
+
const key = remaining[0];
|
|
225
|
+
if (!key)
|
|
226
|
+
error('Missing key', 'agent-browser press <key> [--in-frame <path>]');
|
|
227
|
+
return { id, action: 'press', key, inFrame };
|
|
228
|
+
}
|
|
229
|
+
case 'keydown': {
|
|
230
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
231
|
+
const key = remaining[0];
|
|
232
|
+
if (!key)
|
|
233
|
+
error('Missing key', 'agent-browser keydown <key> [--in-frame <path>]');
|
|
234
|
+
return { id, action: 'keydown', key, inFrame };
|
|
235
|
+
}
|
|
236
|
+
case 'keyup': {
|
|
237
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
238
|
+
const key = remaining[0];
|
|
239
|
+
if (!key)
|
|
240
|
+
error('Missing key', 'agent-browser keyup <key> [--in-frame <path>]');
|
|
241
|
+
return { id, action: 'keyup', key, inFrame };
|
|
242
|
+
}
|
|
243
|
+
case 'scroll': {
|
|
244
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
245
|
+
const direction = remaining[0] || 'down';
|
|
246
|
+
const amount = remaining[1] ? parseInt(remaining[1], 10) : 300;
|
|
247
|
+
return { id, action: 'scroll', direction, amount, inFrame };
|
|
248
|
+
}
|
|
249
|
+
case 'scrollintoview':
|
|
250
|
+
case 'scrollinto': {
|
|
251
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
252
|
+
const selector = remaining[0];
|
|
253
|
+
if (!selector)
|
|
254
|
+
error('Missing selector', 'agent-browser scrollintoview <selector> [--in-frame <path>]');
|
|
255
|
+
return { id, action: 'scrollintoview', selector, inFrame };
|
|
256
|
+
}
|
|
257
|
+
case 'wait': {
|
|
258
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
259
|
+
if (remaining.includes('--url') || remaining.includes('-u')) {
|
|
260
|
+
const urlIdx = remaining.includes('--url')
|
|
261
|
+
? remaining.indexOf('--url')
|
|
262
|
+
: remaining.indexOf('-u');
|
|
263
|
+
const url = remaining[urlIdx + 1];
|
|
264
|
+
if (!url)
|
|
265
|
+
error('Missing URL pattern', 'agent-browser wait --url <pattern> [--in-frame <path>]');
|
|
266
|
+
return { id, action: 'waitforurl', url, inFrame };
|
|
267
|
+
}
|
|
268
|
+
if (remaining.includes('--load') || remaining.includes('-l')) {
|
|
269
|
+
const loadIdx = remaining.includes('--load')
|
|
270
|
+
? remaining.indexOf('--load')
|
|
271
|
+
: remaining.indexOf('-l');
|
|
272
|
+
const state = remaining[loadIdx + 1];
|
|
273
|
+
if (!state)
|
|
274
|
+
error('Missing load state', 'agent-browser wait --load <state> [--in-frame <path>]');
|
|
275
|
+
return { id, action: 'waitforloadstate', state, inFrame };
|
|
276
|
+
}
|
|
277
|
+
if (remaining.includes('--fn') || remaining.includes('-f')) {
|
|
278
|
+
const fnIdx = remaining.includes('--fn')
|
|
279
|
+
? remaining.indexOf('--fn')
|
|
280
|
+
: remaining.indexOf('-f');
|
|
281
|
+
const expression = remaining[fnIdx + 1];
|
|
282
|
+
if (!expression)
|
|
283
|
+
error('Missing expression', 'agent-browser wait --fn <expression> [--in-frame <path>]');
|
|
284
|
+
return { id, action: 'waitforfunction', expression, inFrame };
|
|
285
|
+
}
|
|
286
|
+
if (remaining.includes('--text') || remaining.includes('-t')) {
|
|
287
|
+
const textIdx = remaining.includes('--text')
|
|
288
|
+
? remaining.indexOf('--text')
|
|
289
|
+
: remaining.indexOf('-t');
|
|
290
|
+
const text = remaining[textIdx + 1];
|
|
291
|
+
if (!text)
|
|
292
|
+
error('Missing text', 'agent-browser wait --text <text> [--in-frame <path>]');
|
|
293
|
+
return { id, action: 'wait', selector: `text=${text}`, inFrame };
|
|
294
|
+
}
|
|
295
|
+
if (remaining.includes('--download') || remaining.includes('-d')) {
|
|
296
|
+
const cmd = { id, action: 'waitfordownload', inFrame };
|
|
297
|
+
const dlIdx = remaining.includes('--download')
|
|
298
|
+
? remaining.indexOf('--download')
|
|
299
|
+
: remaining.indexOf('-d');
|
|
300
|
+
if (remaining[dlIdx + 1] && !remaining[dlIdx + 1].startsWith('--'))
|
|
301
|
+
cmd.path = remaining[dlIdx + 1];
|
|
302
|
+
const timeoutIdx = remaining.indexOf('--timeout');
|
|
303
|
+
if (timeoutIdx !== -1 && remaining[timeoutIdx + 1])
|
|
304
|
+
cmd.timeout = parseInt(remaining[timeoutIdx + 1], 10);
|
|
305
|
+
return cmd;
|
|
306
|
+
}
|
|
307
|
+
if (remaining[0]) {
|
|
308
|
+
const timeout = parseInt(remaining[0], 10);
|
|
309
|
+
if (!isNaN(timeout))
|
|
310
|
+
return { id, action: 'wait', timeout, inFrame };
|
|
311
|
+
return { id, action: 'wait', selector: remaining[0], inFrame };
|
|
312
|
+
}
|
|
313
|
+
error('Missing arguments', 'agent-browser wait <selector|ms|--url|--load|--fn|--text|--download> [--in-frame <path>]');
|
|
314
|
+
}
|
|
315
|
+
case 'screenshot': {
|
|
316
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
317
|
+
const fullPage = remaining.includes('--full') || remaining.includes('-f');
|
|
318
|
+
const filtered = remaining.filter((r) => r !== '--full' && r !== '-f');
|
|
319
|
+
let selector;
|
|
320
|
+
let path;
|
|
321
|
+
if (filtered.length === 2) {
|
|
322
|
+
selector = filtered[0];
|
|
323
|
+
path = filtered[1];
|
|
324
|
+
}
|
|
325
|
+
else if (filtered.length === 1) {
|
|
326
|
+
const arg = filtered[0];
|
|
327
|
+
const isPath = arg.includes('/') ||
|
|
328
|
+
arg.endsWith('.png') ||
|
|
329
|
+
arg.endsWith('.jpg') ||
|
|
330
|
+
arg.endsWith('.jpeg') ||
|
|
331
|
+
arg.endsWith('.webp');
|
|
332
|
+
if (isPath)
|
|
333
|
+
path = arg;
|
|
334
|
+
else
|
|
335
|
+
selector = arg;
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
id,
|
|
339
|
+
action: 'screenshot',
|
|
340
|
+
selector,
|
|
341
|
+
path,
|
|
342
|
+
fullPage: fullPage ? true : undefined,
|
|
343
|
+
inFrame,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
case 'pdf': {
|
|
347
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
348
|
+
const path = remaining[0];
|
|
349
|
+
if (!path)
|
|
350
|
+
error('Missing path', 'agent-browser pdf <path> [--in-frame <path>]');
|
|
351
|
+
return { id, action: 'pdf', path, inFrame };
|
|
352
|
+
}
|
|
353
|
+
case 'snapshot': {
|
|
354
|
+
const command = { id, action: 'snapshot' };
|
|
355
|
+
for (let i = 0; i < rest.length; i++) {
|
|
356
|
+
switch (rest[i]) {
|
|
357
|
+
case '-i':
|
|
358
|
+
case '--interactive':
|
|
359
|
+
command.interactive = true;
|
|
360
|
+
break;
|
|
361
|
+
case '-c':
|
|
362
|
+
case '--compact':
|
|
363
|
+
command.compact = true;
|
|
364
|
+
break;
|
|
365
|
+
case '-C':
|
|
366
|
+
case '--cursor':
|
|
367
|
+
command.cursor = true;
|
|
368
|
+
break;
|
|
369
|
+
case '-d':
|
|
370
|
+
case '--depth':
|
|
371
|
+
if (rest[i + 1]) {
|
|
372
|
+
command.maxDepth = parseInt(rest[i + 1], 10);
|
|
373
|
+
i++;
|
|
374
|
+
}
|
|
375
|
+
break;
|
|
376
|
+
case '-s':
|
|
377
|
+
case '--selector':
|
|
378
|
+
if (rest[i + 1]) {
|
|
379
|
+
command.selector = rest[i + 1];
|
|
380
|
+
i++;
|
|
381
|
+
}
|
|
382
|
+
break;
|
|
383
|
+
case '--in-frame':
|
|
384
|
+
if (rest[i + 1]) {
|
|
385
|
+
command.inFrame = rest[i + 1];
|
|
386
|
+
i++;
|
|
387
|
+
}
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return command;
|
|
392
|
+
}
|
|
393
|
+
case 'eval': {
|
|
394
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
395
|
+
let script;
|
|
396
|
+
let file;
|
|
397
|
+
if (remaining.includes('--file')) {
|
|
398
|
+
const fileIdx = remaining.indexOf('--file');
|
|
399
|
+
file = remaining[fileIdx + 1];
|
|
400
|
+
if (!file)
|
|
401
|
+
error('Missing file path', 'agent-browser eval --file <path> [--in-frame <path>]');
|
|
402
|
+
}
|
|
403
|
+
else if (remaining.includes('-f') && !remaining.includes('--fn')) {
|
|
404
|
+
const fIdx = remaining.indexOf('-f');
|
|
405
|
+
if (fIdx + 1 < remaining.length && !remaining[fIdx + 1].startsWith('-')) {
|
|
406
|
+
file = remaining[fIdx + 1];
|
|
407
|
+
}
|
|
408
|
+
if (!file)
|
|
409
|
+
error('Missing file path', 'agent-browser eval -f <path> [--in-frame <path>]');
|
|
410
|
+
}
|
|
411
|
+
else if (remaining.includes('--stdin')) {
|
|
412
|
+
const fd = process.stdin.fd;
|
|
413
|
+
const buffer = Buffer.allocUnsafe(1024);
|
|
414
|
+
const chunks = [];
|
|
415
|
+
let bytesRead;
|
|
416
|
+
const fs = require('fs');
|
|
417
|
+
while ((bytesRead = fs.readSync(fd, buffer, 0, buffer.length)) > 0) {
|
|
418
|
+
chunks.push(Buffer.from(buffer.subarray(0, bytesRead)));
|
|
419
|
+
}
|
|
420
|
+
script = Buffer.concat(chunks).toString('utf8');
|
|
421
|
+
}
|
|
422
|
+
else if (remaining.includes('-b') || remaining.includes('--base64')) {
|
|
423
|
+
const bIdx = remaining.includes('-b')
|
|
424
|
+
? remaining.indexOf('-b')
|
|
425
|
+
: remaining.indexOf('--base64');
|
|
426
|
+
const encoded = remaining[bIdx + 1];
|
|
427
|
+
if (!encoded)
|
|
428
|
+
error('Missing base64 script', 'agent-browser eval -b <base64-script> [--in-frame <path>]');
|
|
429
|
+
try {
|
|
430
|
+
script = Buffer.from(encoded, 'base64').toString('utf8');
|
|
431
|
+
}
|
|
432
|
+
catch {
|
|
433
|
+
error('Invalid base64', 'agent-browser eval -b <base64-script> [--in-frame <path>]');
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
script = remaining.join(' ');
|
|
438
|
+
if (!script)
|
|
439
|
+
error('Missing script', 'agent-browser eval <script> [--in-frame <path>]');
|
|
440
|
+
}
|
|
441
|
+
return { id, action: 'evaluate', script, file, inFrame };
|
|
442
|
+
}
|
|
443
|
+
case 'close':
|
|
444
|
+
case 'quit':
|
|
445
|
+
case 'exit':
|
|
446
|
+
return { id, action: 'close' };
|
|
447
|
+
case 'get': {
|
|
448
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
449
|
+
const subcmd = remaining[0];
|
|
450
|
+
if (!subcmd)
|
|
451
|
+
error('Missing subcommand', 'agent-browser get <text|html|value|attr|url|title|count|box|styles> [args...] [--in-frame <path>]');
|
|
452
|
+
switch (subcmd) {
|
|
453
|
+
case 'text': {
|
|
454
|
+
const selector = remaining[1];
|
|
455
|
+
if (!selector)
|
|
456
|
+
error('Missing selector', 'agent-browser get text <selector> [--in-frame <path>]');
|
|
457
|
+
return { id, action: 'gettext', selector, inFrame };
|
|
458
|
+
}
|
|
459
|
+
case 'html': {
|
|
460
|
+
const selector = remaining[1];
|
|
461
|
+
if (!selector)
|
|
462
|
+
error('Missing selector', 'agent-browser get html <selector> [--in-frame <path>]');
|
|
463
|
+
return { id, action: 'innerhtml', selector, inFrame };
|
|
464
|
+
}
|
|
465
|
+
case 'value': {
|
|
466
|
+
const selector = remaining[1];
|
|
467
|
+
if (!selector)
|
|
468
|
+
error('Missing selector', 'agent-browser get value <selector> [--in-frame <path>]');
|
|
469
|
+
return { id, action: 'inputvalue', selector, inFrame };
|
|
470
|
+
}
|
|
471
|
+
case 'attr': {
|
|
472
|
+
const selector = remaining[1];
|
|
473
|
+
const attribute = remaining[2];
|
|
474
|
+
if (!selector)
|
|
475
|
+
error('Missing selector', 'agent-browser get attr <selector> <attribute> [--in-frame <path>]');
|
|
476
|
+
if (!attribute)
|
|
477
|
+
error('Missing attribute', 'agent-browser get attr <selector> <attribute> [--in-frame <path>]');
|
|
478
|
+
return { id, action: 'getattribute', selector, attribute, inFrame };
|
|
479
|
+
}
|
|
480
|
+
case 'url':
|
|
481
|
+
return { id, action: 'url', inFrame };
|
|
482
|
+
case 'title':
|
|
483
|
+
return { id, action: 'title', inFrame };
|
|
484
|
+
case 'count': {
|
|
485
|
+
const selector = remaining[1];
|
|
486
|
+
if (!selector)
|
|
487
|
+
error('Missing selector', 'agent-browser get count <selector> [--in-frame <path>]');
|
|
488
|
+
return { id, action: 'count', selector, inFrame };
|
|
489
|
+
}
|
|
490
|
+
case 'box': {
|
|
491
|
+
const selector = remaining[1];
|
|
492
|
+
if (!selector)
|
|
493
|
+
error('Missing selector', 'agent-browser get box <selector> [--in-frame <path>]');
|
|
494
|
+
return { id, action: 'boundingbox', selector, inFrame };
|
|
495
|
+
}
|
|
496
|
+
case 'styles': {
|
|
497
|
+
const selector = remaining[1];
|
|
498
|
+
if (!selector)
|
|
499
|
+
error('Missing selector', 'agent-browser get styles <selector> [--in-frame <path>]');
|
|
500
|
+
return { id, action: 'styles', selector, inFrame };
|
|
501
|
+
}
|
|
502
|
+
default:
|
|
503
|
+
error(`Unknown get subcommand: ${subcmd}`, 'agent-browser get <text|html|value|attr|url|title|count|box|styles> [args...] [--in-frame <path>]');
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
case 'is': {
|
|
507
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
508
|
+
const subcmd = remaining[0];
|
|
509
|
+
if (!subcmd)
|
|
510
|
+
error('Missing subcommand', 'agent-browser is <visible|enabled|checked> <selector> [--in-frame <path>]');
|
|
511
|
+
const selector = remaining[1];
|
|
512
|
+
if (!selector)
|
|
513
|
+
error('Missing selector', `agent-browser is ${subcmd} <selector> [--in-frame <path>]`);
|
|
514
|
+
switch (subcmd) {
|
|
515
|
+
case 'visible':
|
|
516
|
+
return { id, action: 'isvisible', selector, inFrame };
|
|
517
|
+
case 'enabled':
|
|
518
|
+
return { id, action: 'isenabled', selector, inFrame };
|
|
519
|
+
case 'checked':
|
|
520
|
+
return { id, action: 'ischecked', selector, inFrame };
|
|
521
|
+
default:
|
|
522
|
+
error(`Unknown is subcommand: ${subcmd}`, 'agent-browser is <visible|enabled|checked> <selector> [--in-frame <path>]');
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
case 'find': {
|
|
526
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
527
|
+
const locator = remaining[0];
|
|
528
|
+
if (!locator)
|
|
529
|
+
error('Missing locator type', 'agent-browser find <locator> <value> [action] [text] [--in-frame <path>]');
|
|
530
|
+
const nameIdx = remaining.indexOf('--name');
|
|
531
|
+
const name = nameIdx !== -1 ? remaining[nameIdx + 1] : undefined;
|
|
532
|
+
const exact = remaining.includes('--exact');
|
|
533
|
+
switch (locator) {
|
|
534
|
+
case 'role': {
|
|
535
|
+
const role = remaining[1];
|
|
536
|
+
if (!role)
|
|
537
|
+
error('Missing role', 'agent-browser find role <role> [action] [--name <name>] [--exact] [--in-frame <path>]');
|
|
538
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
539
|
+
const valueIdx = remaining.findIndex((r, i) => i > 2 && !r.startsWith('--'));
|
|
540
|
+
const value = valueIdx !== -1
|
|
541
|
+
? remaining
|
|
542
|
+
.slice(valueIdx)
|
|
543
|
+
.filter((a) => !a.startsWith('--'))
|
|
544
|
+
.join(' ')
|
|
545
|
+
: undefined;
|
|
546
|
+
const cmd = { id, action: 'getbyrole', role, subaction, name, exact, inFrame };
|
|
547
|
+
if (value)
|
|
548
|
+
cmd.value = value;
|
|
549
|
+
return cmd;
|
|
550
|
+
}
|
|
551
|
+
case 'text': {
|
|
552
|
+
const text = remaining[1];
|
|
553
|
+
if (!text)
|
|
554
|
+
error('Missing text', 'agent-browser find text <text> [action] [--exact] [--in-frame <path>]');
|
|
555
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
556
|
+
return { id, action: 'getbytext', text, subaction, exact, inFrame };
|
|
557
|
+
}
|
|
558
|
+
case 'label': {
|
|
559
|
+
const label = remaining[1];
|
|
560
|
+
if (!label)
|
|
561
|
+
error('Missing label', 'agent-browser find label <label> [action] [text] [--exact] [--in-frame <path>]');
|
|
562
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
563
|
+
const value = remaining
|
|
564
|
+
.slice(3)
|
|
565
|
+
.filter((a) => !a.startsWith('--'))
|
|
566
|
+
.join(' ');
|
|
567
|
+
const cmd = { id, action: 'getbylabel', label, subaction, exact, inFrame };
|
|
568
|
+
if (value)
|
|
569
|
+
cmd.value = value;
|
|
570
|
+
return cmd;
|
|
571
|
+
}
|
|
572
|
+
case 'placeholder': {
|
|
573
|
+
const placeholder = remaining[1];
|
|
574
|
+
if (!placeholder)
|
|
575
|
+
error('Missing placeholder', 'agent-browser find placeholder <text> [action] [text] [--exact] [--in-frame <path>]');
|
|
576
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
577
|
+
const value = remaining
|
|
578
|
+
.slice(3)
|
|
579
|
+
.filter((a) => !a.startsWith('--'))
|
|
580
|
+
.join(' ');
|
|
581
|
+
const cmd = {
|
|
582
|
+
id,
|
|
583
|
+
action: 'getbyplaceholder',
|
|
584
|
+
placeholder,
|
|
585
|
+
subaction,
|
|
586
|
+
exact,
|
|
587
|
+
inFrame,
|
|
588
|
+
};
|
|
589
|
+
if (value)
|
|
590
|
+
cmd.value = value;
|
|
591
|
+
return cmd;
|
|
592
|
+
}
|
|
593
|
+
case 'alt': {
|
|
594
|
+
const text = remaining[1];
|
|
595
|
+
if (!text)
|
|
596
|
+
error('Missing alt text', 'agent-browser find alt <text> [action] [--exact] [--in-frame <path>]');
|
|
597
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
598
|
+
return { id, action: 'getbyalttext', text, subaction, exact, inFrame };
|
|
599
|
+
}
|
|
600
|
+
case 'title': {
|
|
601
|
+
const text = remaining[1];
|
|
602
|
+
if (!text)
|
|
603
|
+
error('Missing title text', 'agent-browser find title <text> [action] [--exact] [--in-frame <path>]');
|
|
604
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
605
|
+
return { id, action: 'getbytitle', text, subaction, exact, inFrame };
|
|
606
|
+
}
|
|
607
|
+
case 'testid': {
|
|
608
|
+
const testId = remaining[1];
|
|
609
|
+
if (!testId)
|
|
610
|
+
error('Missing testid', 'agent-browser find testid <id> [action] [text] [--in-frame <path>]');
|
|
611
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
612
|
+
const value = remaining.slice(3).join(' ');
|
|
613
|
+
const cmd = { id, action: 'getbytestid', testId, subaction, inFrame };
|
|
614
|
+
if (value)
|
|
615
|
+
cmd.value = value;
|
|
616
|
+
return cmd;
|
|
617
|
+
}
|
|
618
|
+
case 'first': {
|
|
619
|
+
const selector = remaining[1];
|
|
620
|
+
if (!selector)
|
|
621
|
+
error('Missing selector', 'agent-browser find first <selector> [action] [text] [--in-frame <path>]');
|
|
622
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
623
|
+
const value = remaining.slice(3).join(' ');
|
|
624
|
+
const cmd = { id, action: 'nth', selector, index: 0, subaction, inFrame };
|
|
625
|
+
if (value)
|
|
626
|
+
cmd.value = value;
|
|
627
|
+
return cmd;
|
|
628
|
+
}
|
|
629
|
+
case 'last': {
|
|
630
|
+
const selector = remaining[1];
|
|
631
|
+
if (!selector)
|
|
632
|
+
error('Missing selector', 'agent-browser find last <selector> [action] [text] [--in-frame <path>]');
|
|
633
|
+
const subaction = remaining[2] && !remaining[2].startsWith('--') ? remaining[2] : 'click';
|
|
634
|
+
const value = remaining.slice(3).join(' ');
|
|
635
|
+
const cmd = { id, action: 'nth', selector, index: -1, subaction, inFrame };
|
|
636
|
+
if (value)
|
|
637
|
+
cmd.value = value;
|
|
638
|
+
return cmd;
|
|
639
|
+
}
|
|
640
|
+
case 'nth': {
|
|
641
|
+
const idxStr = remaining[1];
|
|
642
|
+
if (!idxStr)
|
|
643
|
+
error('Missing index', 'agent-browser find nth <index> <selector> [action] [text] [--in-frame <path>]');
|
|
644
|
+
const idx = parseInt(idxStr, 10);
|
|
645
|
+
if (isNaN(idx))
|
|
646
|
+
error('Invalid index', 'agent-browser find nth <index> <selector> [action] [text] [--in-frame <path>]');
|
|
647
|
+
const selector = remaining[2];
|
|
648
|
+
if (!selector)
|
|
649
|
+
error('Missing selector', 'agent-browser find nth <index> <selector> [action] [text] [--in-frame <path>]');
|
|
650
|
+
const subaction = remaining[3] && !remaining[3].startsWith('--') ? remaining[3] : 'click';
|
|
651
|
+
const value = remaining.slice(4).join(' ');
|
|
652
|
+
const cmd = { id, action: 'nth', selector, index: idx, subaction, inFrame };
|
|
653
|
+
if (value)
|
|
654
|
+
cmd.value = value;
|
|
655
|
+
return cmd;
|
|
656
|
+
}
|
|
657
|
+
default:
|
|
658
|
+
error(`Unknown find locator: ${locator}`, 'agent-browser find <role|text|label|placeholder|alt|title|testid|first|last|nth> ... [--in-frame <path>]');
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
case 'mouse': {
|
|
662
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
663
|
+
const subcmd = remaining[0];
|
|
664
|
+
if (!subcmd)
|
|
665
|
+
error('Missing subcommand', 'agent-browser mouse <move|down|up|wheel|wander> [args...] [--in-frame <path>]');
|
|
666
|
+
switch (subcmd) {
|
|
667
|
+
case 'move': {
|
|
668
|
+
const x = remaining[1] ? parseInt(remaining[1], 10) : NaN;
|
|
669
|
+
const y = remaining[2] ? parseInt(remaining[2], 10) : NaN;
|
|
670
|
+
if (isNaN(x) || isNaN(y))
|
|
671
|
+
error('Missing or invalid coordinates', 'agent-browser mouse move <x> <y> [--in-frame <path>]');
|
|
672
|
+
return { id, action: 'mousemove', x, y, inFrame };
|
|
673
|
+
}
|
|
674
|
+
case 'down':
|
|
675
|
+
return { id, action: 'mousedown', button: remaining[1] || 'left', inFrame };
|
|
676
|
+
case 'up':
|
|
677
|
+
return { id, action: 'mouseup', button: remaining[1] || 'left', inFrame };
|
|
678
|
+
case 'wheel': {
|
|
679
|
+
const deltaY = remaining[1] ? parseInt(remaining[1], 10) : 100;
|
|
680
|
+
const deltaX = remaining[2] ? parseInt(remaining[2], 10) : 0;
|
|
681
|
+
return { id, action: 'wheel', deltaX, deltaY, inFrame };
|
|
682
|
+
}
|
|
683
|
+
case 'wander': {
|
|
684
|
+
const duration = remaining[1] ? parseInt(remaining[1], 10) : 2000;
|
|
685
|
+
return { id, action: 'wander', duration, inFrame };
|
|
686
|
+
}
|
|
687
|
+
case 'trajectory': {
|
|
688
|
+
// Format: mouse trajectory "x:y:delay;x:y:delay;..."
|
|
689
|
+
const data = remaining[1] || '';
|
|
690
|
+
return { id, action: 'mousetrajectory', data, inFrame };
|
|
691
|
+
}
|
|
692
|
+
default:
|
|
693
|
+
error(`Unknown mouse subcommand: ${subcmd}`, 'agent-browser mouse <move|down|up|wheel|wander|trajectory> [args...] [--in-frame <path>]');
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
case 'set': {
|
|
697
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
698
|
+
const subcmd = remaining[0];
|
|
699
|
+
if (!subcmd)
|
|
700
|
+
error('Missing subcommand', 'agent-browser set <viewport|device|geo|offline|headers|credentials|media> ... [--in-frame <path>]');
|
|
701
|
+
switch (subcmd) {
|
|
702
|
+
case 'viewport': {
|
|
703
|
+
const width = remaining[1] ? parseInt(remaining[1], 10) : NaN;
|
|
704
|
+
const height = remaining[2] ? parseInt(remaining[2], 10) : NaN;
|
|
705
|
+
if (isNaN(width) || isNaN(height))
|
|
706
|
+
error('Missing or invalid dimensions', 'agent-browser set viewport <width> <height> [--in-frame <path>]');
|
|
707
|
+
return { id, action: 'viewport', width, height, inFrame };
|
|
708
|
+
}
|
|
709
|
+
case 'device': {
|
|
710
|
+
const device = remaining[1];
|
|
711
|
+
if (!device)
|
|
712
|
+
error('Missing device name', 'agent-browser set device <name> [--in-frame <path>]');
|
|
713
|
+
return { id, action: 'device', device, inFrame };
|
|
714
|
+
}
|
|
715
|
+
case 'geo':
|
|
716
|
+
case 'geolocation': {
|
|
717
|
+
const latitude = remaining[1] ? parseFloat(remaining[1]) : NaN;
|
|
718
|
+
const longitude = remaining[2] ? parseFloat(remaining[2]) : NaN;
|
|
719
|
+
if (isNaN(latitude) || isNaN(longitude))
|
|
720
|
+
error('Missing or invalid coordinates', 'agent-browser set geo <latitude> <longitude> [--in-frame <path>]');
|
|
721
|
+
return { id, action: 'geolocation', latitude, longitude, inFrame };
|
|
722
|
+
}
|
|
723
|
+
case 'offline': {
|
|
724
|
+
const off = remaining[1] !== 'off' && remaining[1] !== 'false';
|
|
725
|
+
return { id, action: 'offline', offline: off, inFrame };
|
|
726
|
+
}
|
|
727
|
+
case 'headers': {
|
|
728
|
+
const json = remaining[1];
|
|
729
|
+
if (!json)
|
|
730
|
+
error('Missing headers JSON', 'agent-browser set headers <json> [--in-frame <path>]');
|
|
731
|
+
try {
|
|
732
|
+
const headers = JSON.parse(json);
|
|
733
|
+
return { id, action: 'headers', headers, inFrame };
|
|
734
|
+
}
|
|
735
|
+
catch {
|
|
736
|
+
error('Invalid JSON', 'agent-browser set headers <json> [--in-frame <path>]');
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
case 'credentials':
|
|
740
|
+
case 'auth': {
|
|
741
|
+
const username = remaining[1];
|
|
742
|
+
const password = remaining[2];
|
|
743
|
+
if (!username || !password)
|
|
744
|
+
error('Missing credentials', 'agent-browser set credentials <username> <password> [--in-frame <path>]');
|
|
745
|
+
return { id, action: 'credentials', username, password, inFrame };
|
|
746
|
+
}
|
|
747
|
+
case 'media': {
|
|
748
|
+
const color = remaining.includes('dark')
|
|
749
|
+
? 'dark'
|
|
750
|
+
: remaining.includes('light')
|
|
751
|
+
? 'light'
|
|
752
|
+
: 'no-preference';
|
|
753
|
+
const reduced = remaining.includes('reduced-motion') ? 'reduce' : 'no-preference';
|
|
754
|
+
return {
|
|
755
|
+
id,
|
|
756
|
+
action: 'emulatemedia',
|
|
757
|
+
colorScheme: color,
|
|
758
|
+
reducedMotion: reduced,
|
|
759
|
+
inFrame,
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
default:
|
|
763
|
+
error(`Unknown set subcommand: ${subcmd}`, 'agent-browser set <viewport|device|geo|offline|headers|credentials|media> ... [--in-frame <path>]');
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
case 'network': {
|
|
767
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
768
|
+
const subcmd = remaining[0];
|
|
769
|
+
if (!subcmd)
|
|
770
|
+
error('Missing subcommand', 'agent-browser network <route|unroute|requests> ... [--in-frame <path>]');
|
|
771
|
+
switch (subcmd) {
|
|
772
|
+
case 'route': {
|
|
773
|
+
const url = remaining[1];
|
|
774
|
+
if (!url)
|
|
775
|
+
error('Missing URL pattern', 'agent-browser network route <url> [--abort] [--body <json>] [--in-frame <path>]');
|
|
776
|
+
const abort = remaining.includes('--abort');
|
|
777
|
+
const bodyIdx = remaining.indexOf('--body');
|
|
778
|
+
const body = bodyIdx !== -1 ? remaining[bodyIdx + 1] : undefined;
|
|
779
|
+
return { id, action: 'route', url, abort, body, inFrame };
|
|
780
|
+
}
|
|
781
|
+
case 'unroute':
|
|
782
|
+
return { id, action: 'unroute', url: remaining[1], inFrame };
|
|
783
|
+
case 'requests': {
|
|
784
|
+
const clear = remaining.includes('--clear');
|
|
785
|
+
const filterIdx = remaining.indexOf('--filter');
|
|
786
|
+
const filter = filterIdx !== -1 ? remaining[filterIdx + 1] : undefined;
|
|
787
|
+
return { id, action: 'requests', clear, filter, inFrame };
|
|
788
|
+
}
|
|
789
|
+
default:
|
|
790
|
+
error(`Unknown network subcommand: ${subcmd}`, 'agent-browser network <route|unroute|requests> ... [--in-frame <path>]');
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
case 'storage': {
|
|
794
|
+
const type = rest[0];
|
|
795
|
+
if (!type || (type !== 'local' && type !== 'session'))
|
|
796
|
+
error('Missing storage type', 'agent-browser storage <local|session> [key] [value]');
|
|
797
|
+
const subcmd = rest[1];
|
|
798
|
+
if (!subcmd)
|
|
799
|
+
return { id, action: 'storage_get', type };
|
|
800
|
+
if (subcmd === 'set') {
|
|
801
|
+
const key = rest[2];
|
|
802
|
+
const value = rest[3];
|
|
803
|
+
if (!key || !value)
|
|
804
|
+
error('Missing key or value', 'agent-browser storage <local|session> set <key> <value>');
|
|
805
|
+
return { id, action: 'storage_set', type, key, value };
|
|
806
|
+
}
|
|
807
|
+
if (subcmd === 'clear')
|
|
808
|
+
return { id, action: 'storage_clear', type };
|
|
809
|
+
return { id, action: 'storage_get', type, key: subcmd };
|
|
810
|
+
}
|
|
811
|
+
case 'cookies': {
|
|
812
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
813
|
+
const subcmd = remaining[0] || 'get';
|
|
814
|
+
switch (subcmd) {
|
|
815
|
+
case 'set': {
|
|
816
|
+
const name = remaining[1];
|
|
817
|
+
const value = remaining[2];
|
|
818
|
+
if (!name || !value)
|
|
819
|
+
error('Missing name or value', 'agent-browser cookies set <name> <value> [options] [--in-frame <path>]');
|
|
820
|
+
const cookie = { name, value };
|
|
821
|
+
for (let i = 3; i < remaining.length; i++) {
|
|
822
|
+
switch (remaining[i]) {
|
|
823
|
+
case '--url':
|
|
824
|
+
cookie.url = remaining[++i];
|
|
825
|
+
break;
|
|
826
|
+
case '--domain':
|
|
827
|
+
cookie.domain = remaining[++i];
|
|
828
|
+
break;
|
|
829
|
+
case '--path':
|
|
830
|
+
cookie.path = remaining[++i];
|
|
831
|
+
break;
|
|
832
|
+
case '--httpOnly':
|
|
833
|
+
cookie.httpOnly = true;
|
|
834
|
+
break;
|
|
835
|
+
case '--secure':
|
|
836
|
+
cookie.secure = true;
|
|
837
|
+
break;
|
|
838
|
+
case '--sameSite':
|
|
839
|
+
cookie.sameSite = remaining[++i];
|
|
840
|
+
break;
|
|
841
|
+
case '--expires':
|
|
842
|
+
cookie.expires = parseInt(remaining[++i], 10);
|
|
843
|
+
break;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
return { id, action: 'cookies_set', cookies: [cookie], inFrame };
|
|
847
|
+
}
|
|
848
|
+
case 'clear':
|
|
849
|
+
return { id, action: 'cookies_clear', inFrame };
|
|
850
|
+
default:
|
|
851
|
+
return {
|
|
852
|
+
id,
|
|
853
|
+
action: 'cookies_get',
|
|
854
|
+
urls: subcmd !== 'get' ? [subcmd, ...remaining.slice(1)] : undefined,
|
|
855
|
+
inFrame,
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
case 'tab': {
|
|
860
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
861
|
+
const subcmd = remaining[0];
|
|
862
|
+
if (!subcmd || subcmd === 'list')
|
|
863
|
+
return { id, action: 'tab_list', inFrame };
|
|
864
|
+
if (subcmd === 'new') {
|
|
865
|
+
const cmd = { id, action: 'tab_new', inFrame };
|
|
866
|
+
if (remaining[1])
|
|
867
|
+
cmd.url = remaining[1];
|
|
868
|
+
return cmd;
|
|
869
|
+
}
|
|
870
|
+
if (subcmd === 'close') {
|
|
871
|
+
const cmd = { id, action: 'tab_close', inFrame };
|
|
872
|
+
if (remaining[1])
|
|
873
|
+
cmd.index = parseInt(remaining[1], 10);
|
|
874
|
+
return cmd;
|
|
875
|
+
}
|
|
876
|
+
const index = parseInt(subcmd, 10);
|
|
877
|
+
if (!isNaN(index))
|
|
878
|
+
return { id, action: 'tab_switch', index, inFrame };
|
|
879
|
+
error('Unknown tab command', 'agent-browser tab <list|new|close|index> [--in-frame <path>]');
|
|
880
|
+
}
|
|
881
|
+
case 'window': {
|
|
882
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
883
|
+
if (remaining[0] === 'new')
|
|
884
|
+
return { id, action: 'window_new', inFrame };
|
|
885
|
+
error('Unknown window command', 'agent-browser window new [--in-frame <path>]');
|
|
886
|
+
}
|
|
887
|
+
case 'frame': {
|
|
888
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
889
|
+
if (remaining[0] === 'main')
|
|
890
|
+
return { id, action: 'mainframe', inFrame };
|
|
891
|
+
let urlOpt;
|
|
892
|
+
let nameOpt;
|
|
893
|
+
let selectorOpt;
|
|
894
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
895
|
+
if (remaining[i] === '--url') {
|
|
896
|
+
urlOpt = remaining[i + 1];
|
|
897
|
+
i++;
|
|
898
|
+
}
|
|
899
|
+
else if (remaining[i] === '--name') {
|
|
900
|
+
nameOpt = remaining[i + 1];
|
|
901
|
+
i++;
|
|
902
|
+
}
|
|
903
|
+
else if (!remaining[i].startsWith('--') && !selectorOpt) {
|
|
904
|
+
selectorOpt = remaining[i];
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
if (urlOpt)
|
|
908
|
+
return { id, action: 'frame', url: urlOpt, inFrame };
|
|
909
|
+
if (nameOpt)
|
|
910
|
+
return { id, action: 'frame', name: nameOpt, inFrame };
|
|
911
|
+
if (selectorOpt)
|
|
912
|
+
return { id, action: 'frame', selector: selectorOpt, inFrame };
|
|
913
|
+
error('Missing selector', 'agent-browser frame <selector|main> [--url <url>] [--name <name>] [--in-frame <path>]');
|
|
914
|
+
}
|
|
915
|
+
case 'dialog': {
|
|
916
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
917
|
+
const subcmd = remaining[0];
|
|
918
|
+
if (!subcmd)
|
|
919
|
+
error('Missing subcommand', 'agent-browser dialog <accept|dismiss> [text] [--in-frame <path>]');
|
|
920
|
+
if (subcmd === 'accept') {
|
|
921
|
+
const cmd = { id, action: 'dialog', response: 'accept', inFrame };
|
|
922
|
+
if (remaining[1])
|
|
923
|
+
cmd.promptText = remaining[1];
|
|
924
|
+
return cmd;
|
|
925
|
+
}
|
|
926
|
+
if (subcmd === 'dismiss')
|
|
927
|
+
return { id, action: 'dialog', response: 'dismiss', inFrame };
|
|
928
|
+
error('Unknown dialog command', 'agent-browser dialog <accept|dismiss> [text] [--in-frame <path>]');
|
|
929
|
+
}
|
|
930
|
+
case 'trace': {
|
|
931
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
932
|
+
const subcmd = remaining[0];
|
|
933
|
+
if (!subcmd)
|
|
934
|
+
error('Missing subcommand', 'agent-browser trace <start|stop> [path] [--in-frame <path>]');
|
|
935
|
+
if (subcmd === 'start')
|
|
936
|
+
return { id, action: 'trace_start', inFrame };
|
|
937
|
+
if (subcmd === 'stop') {
|
|
938
|
+
const path = remaining[1];
|
|
939
|
+
if (!path)
|
|
940
|
+
error('Missing path', 'agent-browser trace stop <path> [--in-frame <path>]');
|
|
941
|
+
return { id, action: 'trace_stop', path, inFrame };
|
|
942
|
+
}
|
|
943
|
+
error('Unknown trace command', 'agent-browser trace <start|stop> [path] [--in-frame <path>]');
|
|
944
|
+
}
|
|
945
|
+
case 'record': {
|
|
946
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
947
|
+
const subcmd = remaining[0];
|
|
948
|
+
if (!subcmd)
|
|
949
|
+
error('Missing subcommand', 'agent-browser record <start|stop|restart> [path] [url] [--in-frame <path>]');
|
|
950
|
+
if (subcmd === 'start') {
|
|
951
|
+
const path = remaining[1];
|
|
952
|
+
if (!path)
|
|
953
|
+
error('Missing path', 'agent-browser record start <output.webm> [url] [--in-frame <path>]');
|
|
954
|
+
const cmd = { id, action: 'recording_start', path, inFrame };
|
|
955
|
+
if (remaining[2])
|
|
956
|
+
cmd.url = remaining[2].startsWith('http') ? remaining[2] : `https://${remaining[2]}`;
|
|
957
|
+
return cmd;
|
|
958
|
+
}
|
|
959
|
+
if (subcmd === 'stop')
|
|
960
|
+
return { id, action: 'recording_stop', inFrame };
|
|
961
|
+
if (subcmd === 'restart') {
|
|
962
|
+
const path = remaining[1];
|
|
963
|
+
if (!path)
|
|
964
|
+
error('Missing path', 'agent-browser record restart <output.webm> [url] [--in-frame <path>]');
|
|
965
|
+
const cmd = { id, action: 'recording_restart', path, inFrame };
|
|
966
|
+
if (remaining[2])
|
|
967
|
+
cmd.url = remaining[2].startsWith('http') ? remaining[2] : `https://${remaining[2]}`;
|
|
968
|
+
return cmd;
|
|
969
|
+
}
|
|
970
|
+
error('Unknown record command', 'agent-browser record <start|stop|restart> [path] [url] [--in-frame <path>]');
|
|
971
|
+
}
|
|
972
|
+
case 'recorder': {
|
|
973
|
+
const subcmd = rest[0];
|
|
974
|
+
const remaining = rest.slice(1);
|
|
975
|
+
if (!subcmd)
|
|
976
|
+
error('Missing subcommand', 'agent-browser recorder <start|stop|status> [--output file]');
|
|
977
|
+
if (subcmd === 'start') {
|
|
978
|
+
const url = remaining[0];
|
|
979
|
+
const cmd = { id, action: 'recorder_start' };
|
|
980
|
+
if (url)
|
|
981
|
+
cmd.url = url.startsWith('http') ? url : `https://${url}`;
|
|
982
|
+
return cmd;
|
|
983
|
+
}
|
|
984
|
+
if (subcmd === 'stop') {
|
|
985
|
+
let output;
|
|
986
|
+
const outputIdx = remaining.indexOf('--output');
|
|
987
|
+
if (outputIdx !== -1) {
|
|
988
|
+
output = remaining[outputIdx + 1];
|
|
989
|
+
}
|
|
990
|
+
const cmd = { id, action: 'recorder_stop', output };
|
|
991
|
+
return cmd;
|
|
992
|
+
}
|
|
993
|
+
if (subcmd === 'status') {
|
|
994
|
+
return { id, action: 'recorder_status' };
|
|
995
|
+
}
|
|
996
|
+
if (subcmd === 'replay') {
|
|
997
|
+
const path = remaining[0];
|
|
998
|
+
const cmd = { id, action: 'recorder_replay' };
|
|
999
|
+
if (path)
|
|
1000
|
+
cmd.path = path;
|
|
1001
|
+
return cmd;
|
|
1002
|
+
}
|
|
1003
|
+
error('Unknown recorder command', 'agent-browser recorder <start|stop|status|replay> [--output file] [path]');
|
|
1004
|
+
}
|
|
1005
|
+
case 'console': {
|
|
1006
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
1007
|
+
return { id, action: 'console', clear: remaining.includes('--clear'), inFrame };
|
|
1008
|
+
}
|
|
1009
|
+
case 'errors': {
|
|
1010
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
1011
|
+
return { id, action: 'errors', clear: remaining.includes('--clear'), inFrame };
|
|
1012
|
+
}
|
|
1013
|
+
case 'highlight': {
|
|
1014
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
1015
|
+
const selector = remaining[0];
|
|
1016
|
+
if (!selector)
|
|
1017
|
+
error('Missing selector', 'agent-browser highlight <selector> [--in-frame <path>]');
|
|
1018
|
+
return { id, action: 'highlight', selector, inFrame };
|
|
1019
|
+
}
|
|
1020
|
+
case 'state': {
|
|
1021
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
1022
|
+
const subcmd = remaining[0];
|
|
1023
|
+
if (!subcmd)
|
|
1024
|
+
error('Missing subcommand', 'agent-browser state <save|load> <path> [--in-frame <path>]');
|
|
1025
|
+
const path = remaining[1];
|
|
1026
|
+
if (!path)
|
|
1027
|
+
error('Missing path', `agent-browser state ${subcmd} <path> [--in-frame <path>]`);
|
|
1028
|
+
if (subcmd === 'save')
|
|
1029
|
+
return { id, action: 'state_save', path, inFrame };
|
|
1030
|
+
if (subcmd === 'load')
|
|
1031
|
+
return { id, action: 'state_load', path, inFrame };
|
|
1032
|
+
error('Unknown state command', 'agent-browser state <save|load> <path> [--in-frame <path>]');
|
|
1033
|
+
}
|
|
1034
|
+
case 'connect': {
|
|
1035
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
1036
|
+
const endpoint = remaining[0];
|
|
1037
|
+
if (!endpoint)
|
|
1038
|
+
error('Missing endpoint', 'agent-browser connect <port|url> [--in-frame <path>]');
|
|
1039
|
+
if (endpoint.startsWith('ws://') ||
|
|
1040
|
+
endpoint.startsWith('wss://') ||
|
|
1041
|
+
endpoint.startsWith('http://') ||
|
|
1042
|
+
endpoint.startsWith('https://')) {
|
|
1043
|
+
return { id, action: 'launch', cdpUrl: endpoint, inFrame };
|
|
1044
|
+
}
|
|
1045
|
+
const port = parseInt(endpoint, 10);
|
|
1046
|
+
if (isNaN(port))
|
|
1047
|
+
error('Invalid port or URL', 'agent-browser connect <port|url> [--in-frame <path>]');
|
|
1048
|
+
if (port <= 0)
|
|
1049
|
+
error('Port must be greater than 0', 'agent-browser connect <port|url> [--in-frame <path>]');
|
|
1050
|
+
if (port > 65535)
|
|
1051
|
+
error('Port out of range (1-65535)', 'agent-browser connect <port|url> [--in-frame <path>]');
|
|
1052
|
+
return { id, action: 'launch', cdpPort: port, inFrame };
|
|
1053
|
+
}
|
|
1054
|
+
case 'tap': {
|
|
1055
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
1056
|
+
const selector = remaining[0];
|
|
1057
|
+
if (!selector)
|
|
1058
|
+
error('Missing selector', 'agent-browser tap <selector> [--in-frame <path>]');
|
|
1059
|
+
return { id, action: 'tap', selector, inFrame };
|
|
1060
|
+
}
|
|
1061
|
+
case 'swipe': {
|
|
1062
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
1063
|
+
const direction = remaining[0];
|
|
1064
|
+
if (!direction || !['up', 'down', 'left', 'right'].includes(direction))
|
|
1065
|
+
error('Invalid direction', 'agent-browser swipe <up|down|left|right> [distance] [--in-frame <path>]');
|
|
1066
|
+
const cmd = { id, action: 'swipe', direction, inFrame };
|
|
1067
|
+
if (remaining[1])
|
|
1068
|
+
cmd.distance = parseInt(remaining[1], 10);
|
|
1069
|
+
return cmd;
|
|
1070
|
+
}
|
|
1071
|
+
case 'device': {
|
|
1072
|
+
const { inFrame, remaining } = parseInFrame(rest);
|
|
1073
|
+
const subcmd = remaining[0];
|
|
1074
|
+
if (!subcmd || subcmd === 'list')
|
|
1075
|
+
return { id, action: 'device_list', inFrame };
|
|
1076
|
+
error('Unknown device command', 'agent-browser device [list] [--in-frame <path>]');
|
|
1077
|
+
}
|
|
1078
|
+
case 'config': {
|
|
1079
|
+
const json = rest.includes('--json');
|
|
1080
|
+
return { id, action: 'config', json };
|
|
1081
|
+
}
|
|
1082
|
+
default:
|
|
1083
|
+
error(`Unknown command: ${cmd}`);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
//# sourceMappingURL=parseCli.js.map
|