fastbrowser_cli 1.0.9 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/fastbrowser_cli/fastbrowser_cli.js +190 -146
- package/dist/fastbrowser_cli/fastbrowser_cli.js.map +1 -1
- package/package.json +7 -1
- package/skills/fastbrowser/SKILL.md +36 -0
- package/src/fastbrowser_cli/fastbrowser_cli.ts +209 -157
- package/tmp/.claude/.claude/settings.local.json +0 -7
- package/tmp/.claude/settings.local.json +0 -7
- /package/tmp/{.claude → dotclaude}/skills/fastbrowser/SKILL.md +0 -0
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@ Control a live Chrome browser from the command line: navigate, click, fill forms
|
|
|
5
5
|
A lighter alternative to Chrome DevTools MCP or Puppeteer, designed for AI agents and shell workflows. A persistent HTTP daemon keeps an MCP connection to the browser alive so each command incurs minimal latency.
|
|
6
6
|
|
|
7
7
|
- rely on [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp) for robust browser control
|
|
8
|
+
- rely on [a11y_parse](https://github.com/jeromeetienne/skillmd_collection/tree/main/packages/a11y_parse) for accessibility tree parsing and querying.
|
|
9
|
+
Especially a CSS-like selector syntax optimized for the accessibility tree.
|
|
8
10
|
- expose a curated, efficient toolset optimized for AI agent use cases
|
|
9
11
|
- minimize the required round-trips and boilerplate to perform common tasks
|
|
10
12
|
- minimize the output size, thus reducing LLM input size and parsing complexity.
|
|
@@ -32,7 +34,7 @@ npm install -g fastbrowser_cli
|
|
|
32
34
|
Or install just the SKILL.md into an agent folder so an AI agent can use it:
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
|
-
npx fastbrowser_cli
|
|
37
|
+
npx fastbrowser_cli install <skill-folder>
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
This copies `SKILL.md` to `<skill-folder>/skills/fastbrowser/SKILL.md`.
|
|
@@ -64,6 +66,7 @@ npx fastbrowser_cli click -s 'link[name="More information..."]'
|
|
|
64
66
|
| `click` | Click an element by accessibility selector | `-s, --selector` |
|
|
65
67
|
| `fill_form` | Fill a form field by accessibility selector | `-s, --selector`, `--value` |
|
|
66
68
|
| `press_keys` | Press a comma-separated key sequence | `--keys` |
|
|
69
|
+
| `install [skill-folder]` | Install SKILL.md into `<skill-folder>/skills/fastbrowser` (default: `.`) | — |
|
|
67
70
|
| `server start` | Start the HTTP daemon | — |
|
|
68
71
|
| `server status` | Report daemon running/stopped | — |
|
|
69
72
|
| `server stop` | Stop the HTTP daemon | — |
|
|
@@ -4,138 +4,186 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
// node imports
|
|
8
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
-
// npm imports
|
|
11
9
|
const commander_1 = require("commander");
|
|
12
|
-
|
|
10
|
+
const string_argv_1 = __importDefault(require("string-argv"));
|
|
13
11
|
const http_client_js_1 = require("./libs/http-client.js");
|
|
14
12
|
const server_manager_js_1 = require("./libs/server-manager.js");
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
function getAutostartFromCmd(cmd) {
|
|
20
|
-
const globalOpts = cmd.optsWithGlobals();
|
|
21
|
-
return globalOpts.autostart !== false;
|
|
13
|
+
class SilentExitError extends Error {
|
|
14
|
+
constructor() {
|
|
15
|
+
super('silent-exit');
|
|
16
|
+
}
|
|
22
17
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
19
|
+
class MainHelper {
|
|
20
|
+
static getServerFromCmd(cmd) {
|
|
21
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
22
|
+
return http_client_js_1.HttpClient.getServerUrl(globalOpts.server);
|
|
23
|
+
}
|
|
24
|
+
static getAutostartFromCmd(cmd) {
|
|
25
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
26
|
+
return globalOpts.autostart !== false;
|
|
27
|
+
}
|
|
28
|
+
static async runTool(cmd, routeName, body) {
|
|
29
|
+
const server = MainHelper.getServerFromCmd(cmd);
|
|
30
|
+
if (MainHelper.getAutostartFromCmd(cmd) === true) {
|
|
27
31
|
await server_manager_js_1.ServerManager.ensureRunning(server);
|
|
28
32
|
}
|
|
29
33
|
const response = await http_client_js_1.HttpClient.postTool(server, routeName, body);
|
|
30
34
|
http_client_js_1.HttpClient.printResponse(response);
|
|
31
35
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
let parsed;
|
|
46
|
-
try {
|
|
47
|
-
parsed = JSON.parse(opts.selectorsJson);
|
|
36
|
+
static buildQuerySelectorsBody(opts) {
|
|
37
|
+
if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = JSON.parse(opts.selectorsJson);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
throw new Error(`--selectors-json is not valid JSON: ${err.message}`);
|
|
44
|
+
}
|
|
45
|
+
if (Array.isArray(parsed) === false) {
|
|
46
|
+
throw new Error('--selectors-json must be a JSON array');
|
|
47
|
+
}
|
|
48
|
+
return { selectors: parsed };
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
const selectorList = opts.selector ?? [];
|
|
51
|
+
if (selectorList.length === 0) {
|
|
52
|
+
throw new Error('At least one --selector or --selectors-json is required');
|
|
51
53
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
const limit = opts.limit === undefined ? 0 : Number.parseInt(opts.limit, 10);
|
|
55
|
+
if (Number.isNaN(limit) === true) {
|
|
56
|
+
throw new Error(`Invalid --limit: ${opts.limit}`);
|
|
54
57
|
}
|
|
55
|
-
|
|
58
|
+
const withAncestors = opts.withAncestors !== false;
|
|
59
|
+
const selectors = selectorList.map((selector) => ({
|
|
60
|
+
selector,
|
|
61
|
+
limit,
|
|
62
|
+
withAncestors,
|
|
63
|
+
}));
|
|
64
|
+
return { selectors };
|
|
56
65
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
static buildQuerySelectorFirstBody(opts) {
|
|
67
|
+
if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
|
|
68
|
+
let parsed;
|
|
69
|
+
try {
|
|
70
|
+
parsed = JSON.parse(opts.selectorsJson);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
throw new Error(`--selectors-json is not valid JSON: ${err.message}`);
|
|
74
|
+
}
|
|
75
|
+
if (Array.isArray(parsed) === false) {
|
|
76
|
+
throw new Error('--selectors-json must be a JSON array');
|
|
77
|
+
}
|
|
78
|
+
return { selectors: parsed };
|
|
79
|
+
}
|
|
80
|
+
const selectorList = opts.selector ?? [];
|
|
81
|
+
if (selectorList.length === 0) {
|
|
82
|
+
throw new Error('At least one --selector or --selectors-json is required');
|
|
83
|
+
}
|
|
84
|
+
const withAncestors = opts.withAncestors !== false;
|
|
85
|
+
const selectors = selectorList.map((selector) => ({
|
|
86
|
+
selector,
|
|
87
|
+
withAncestors,
|
|
88
|
+
}));
|
|
89
|
+
return { selectors };
|
|
64
90
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
withAncestors,
|
|
70
|
-
}));
|
|
71
|
-
return { selectors };
|
|
72
|
-
}
|
|
73
|
-
function buildQuerySelectorFirstBody(opts) {
|
|
74
|
-
if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
|
|
75
|
-
let parsed;
|
|
91
|
+
static async runInstall(skillFolder) {
|
|
92
|
+
const sourceSkillMd = node_path_1.default.resolve(__dirname, '../../skills/fastbrowser/SKILL.md');
|
|
93
|
+
const targetDir = node_path_1.default.resolve(skillFolder, 'skills', 'fastbrowser');
|
|
94
|
+
const targetSkillMd = node_path_1.default.join(targetDir, 'SKILL.md');
|
|
76
95
|
try {
|
|
77
|
-
|
|
96
|
+
await node_fs_1.default.promises.mkdir(targetDir, { recursive: true });
|
|
97
|
+
await node_fs_1.default.promises.copyFile(sourceSkillMd, targetSkillMd);
|
|
98
|
+
console.log(`Installed fastbrowser SKILL.md at ${targetSkillMd}`);
|
|
78
99
|
}
|
|
79
100
|
catch (err) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
throw new Error('--selectors-json must be a JSON array');
|
|
101
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
102
|
+
console.error(`fastbrowser-cli error: ${message}`);
|
|
103
|
+
process.exit(1);
|
|
84
104
|
}
|
|
85
|
-
return { selectors: parsed };
|
|
86
105
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
106
|
+
static async readBatchSource(file, inlineScript) {
|
|
107
|
+
if (inlineScript !== undefined && inlineScript !== '') {
|
|
108
|
+
return inlineScript;
|
|
109
|
+
}
|
|
110
|
+
if (file !== undefined && file !== '') {
|
|
111
|
+
return await node_fs_1.default.promises.readFile(file, 'utf-8');
|
|
112
|
+
}
|
|
113
|
+
if (process.stdin.isTTY === true) {
|
|
114
|
+
throw new Error('batch: no input. Provide a file path, --script, or pipe commands on stdin.');
|
|
115
|
+
}
|
|
116
|
+
return await MainHelper.readStdinToString();
|
|
90
117
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
99
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
100
|
-
//
|
|
101
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
102
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
103
|
-
async function runInstall(skillFolder) {
|
|
104
|
-
const sourceSkillMd = node_path_1.default.resolve(__dirname, '../../skills/fastbrowser/SKILL.md');
|
|
105
|
-
const targetDir = node_path_1.default.resolve(skillFolder, 'skills', 'fastbrowser');
|
|
106
|
-
const targetSkillMd = node_path_1.default.join(targetDir, 'SKILL.md');
|
|
107
|
-
try {
|
|
108
|
-
await node_fs_1.default.promises.mkdir(targetDir, { recursive: true });
|
|
109
|
-
await node_fs_1.default.promises.copyFile(sourceSkillMd, targetSkillMd);
|
|
110
|
-
console.log(`Installed fastbrowser SKILL.md at ${targetSkillMd}`);
|
|
118
|
+
static async readStdinToString() {
|
|
119
|
+
const chunks = [];
|
|
120
|
+
return await new Promise((resolve, reject) => {
|
|
121
|
+
process.stdin.on('data', (chunk) => chunks.push(chunk));
|
|
122
|
+
process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
|
|
123
|
+
process.stdin.on('error', (err) => reject(err));
|
|
124
|
+
});
|
|
111
125
|
}
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
126
|
+
static async runBatch(program, source, stopOnError, batchCmd) {
|
|
127
|
+
const globalOpts = batchCmd.optsWithGlobals();
|
|
128
|
+
const globalFlags = [];
|
|
129
|
+
if (globalOpts.server !== undefined) {
|
|
130
|
+
globalFlags.push('--server', globalOpts.server);
|
|
131
|
+
}
|
|
132
|
+
if (globalOpts.autostart === false) {
|
|
133
|
+
globalFlags.push('--no-autostart');
|
|
134
|
+
}
|
|
135
|
+
const lines = source.split('\n');
|
|
136
|
+
let ok = 0;
|
|
137
|
+
let failed = 0;
|
|
138
|
+
for (const rawLine of lines) {
|
|
139
|
+
const line = rawLine.trim();
|
|
140
|
+
if (line === '' || line.startsWith('#') === true)
|
|
141
|
+
continue;
|
|
142
|
+
const argv = (0, string_argv_1.default)(line);
|
|
143
|
+
if (argv.length === 0)
|
|
144
|
+
continue;
|
|
145
|
+
console.log(`> ${line}`);
|
|
146
|
+
try {
|
|
147
|
+
await program.parseAsync([...globalFlags, ...argv], { from: 'user' });
|
|
148
|
+
ok += 1;
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
failed += 1;
|
|
152
|
+
if (err instanceof SilentExitError === false && err instanceof commander_1.CommanderError === false) {
|
|
153
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
154
|
+
console.error(`fastbrowser-cli error: ${message}`);
|
|
155
|
+
}
|
|
156
|
+
if (stopOnError === true) {
|
|
157
|
+
throw new SilentExitError();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (stopOnError === false) {
|
|
162
|
+
console.log(`batch: ${ok} ok, ${failed} failed`);
|
|
163
|
+
}
|
|
164
|
+
if (failed > 0) {
|
|
165
|
+
throw new SilentExitError();
|
|
166
|
+
}
|
|
116
167
|
}
|
|
117
168
|
}
|
|
118
169
|
///////////////////////////////////////////////////////////////////////////////
|
|
119
170
|
///////////////////////////////////////////////////////////////////////////////
|
|
120
|
-
//
|
|
171
|
+
//
|
|
121
172
|
///////////////////////////////////////////////////////////////////////////////
|
|
122
173
|
///////////////////////////////////////////////////////////////////////////////
|
|
123
174
|
async function main() {
|
|
124
|
-
const installIdx = process.argv.indexOf('--install');
|
|
125
|
-
if (installIdx !== -1) {
|
|
126
|
-
const next = process.argv[installIdx + 1];
|
|
127
|
-
const skillFolder = (next !== undefined && next.startsWith('-') === false) ? next : '.';
|
|
128
|
-
await runInstall(skillFolder);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
175
|
const program = new commander_1.Command();
|
|
132
176
|
program
|
|
133
177
|
.name('fastbrowser-cli')
|
|
134
178
|
.description('CLI client for fastbrowser')
|
|
135
179
|
.option('--server <url>', 'fastbrowser-httpd URL (default: env FASTBROWSER_SERVER or http://localhost:8787)')
|
|
136
180
|
.option('--autostart', 'Auto-start the server before a command if it is not running', true)
|
|
137
|
-
.option('--no-autostart', 'Do not auto-start the server before a command')
|
|
138
|
-
|
|
181
|
+
.option('--no-autostart', 'Do not auto-start the server before a command');
|
|
182
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
183
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
184
|
+
//
|
|
185
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
186
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
139
187
|
const serverCmd = program
|
|
140
188
|
.command('server')
|
|
141
189
|
.description('Manage the fastbrowser HTTP server');
|
|
@@ -143,52 +191,43 @@ async function main() {
|
|
|
143
191
|
.command('start')
|
|
144
192
|
.description('Start the fastbrowser HTTP server as a detached daemon')
|
|
145
193
|
.action(async (_opts, cmd) => {
|
|
146
|
-
const server = getServerFromCmd(cmd);
|
|
147
|
-
|
|
148
|
-
await server_manager_js_1.ServerManager.start(server);
|
|
149
|
-
}
|
|
150
|
-
catch (err) {
|
|
151
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
152
|
-
console.error(`fastbrowser-cli error: ${message}`);
|
|
153
|
-
process.exit(1);
|
|
154
|
-
}
|
|
194
|
+
const server = MainHelper.getServerFromCmd(cmd);
|
|
195
|
+
await server_manager_js_1.ServerManager.start(server);
|
|
155
196
|
});
|
|
156
197
|
serverCmd
|
|
157
198
|
.command('stop')
|
|
158
199
|
.description('Stop the fastbrowser HTTP server')
|
|
159
200
|
.action(async (_opts, cmd) => {
|
|
160
|
-
const server = getServerFromCmd(cmd);
|
|
161
|
-
|
|
162
|
-
await server_manager_js_1.ServerManager.stop(server);
|
|
163
|
-
}
|
|
164
|
-
catch (err) {
|
|
165
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
166
|
-
console.error(`fastbrowser-cli error: ${message}`);
|
|
167
|
-
process.exit(1);
|
|
168
|
-
}
|
|
201
|
+
const server = MainHelper.getServerFromCmd(cmd);
|
|
202
|
+
await server_manager_js_1.ServerManager.stop(server);
|
|
169
203
|
});
|
|
170
204
|
serverCmd
|
|
171
205
|
.command('status')
|
|
172
206
|
.description('Report whether the fastbrowser HTTP server is running')
|
|
173
207
|
.action(async (_opts, cmd) => {
|
|
174
|
-
const server = getServerFromCmd(cmd);
|
|
208
|
+
const server = MainHelper.getServerFromCmd(cmd);
|
|
175
209
|
const state = await server_manager_js_1.ServerManager.status(server);
|
|
176
210
|
console.log(`fastbrowser server at ${server}: ${state}`);
|
|
177
211
|
if (state === 'stopped')
|
|
178
|
-
|
|
212
|
+
throw new SilentExitError();
|
|
179
213
|
});
|
|
214
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
215
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
216
|
+
//
|
|
217
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
218
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
180
219
|
program
|
|
181
220
|
.command('list_pages')
|
|
182
221
|
.description('List all open browser pages')
|
|
183
222
|
.action(async (_opts, cmd) => {
|
|
184
|
-
await runTool(cmd, 'list_pages', {});
|
|
223
|
+
await MainHelper.runTool(cmd, 'list_pages', {});
|
|
185
224
|
});
|
|
186
225
|
program
|
|
187
226
|
.command('new_page')
|
|
188
227
|
.description('Open a new browser page')
|
|
189
228
|
.requiredOption('--url <url>', 'URL to open')
|
|
190
229
|
.action(async (opts, cmd) => {
|
|
191
|
-
await runTool(cmd, 'new_page', { url: opts.url });
|
|
230
|
+
await MainHelper.runTool(cmd, 'new_page', { url: opts.url });
|
|
192
231
|
});
|
|
193
232
|
program
|
|
194
233
|
.command('close_page')
|
|
@@ -197,32 +236,31 @@ async function main() {
|
|
|
197
236
|
.action(async (opts, cmd) => {
|
|
198
237
|
const pageId = Number.parseInt(opts.pageId, 10);
|
|
199
238
|
if (Number.isNaN(pageId) === true) {
|
|
200
|
-
|
|
201
|
-
process.exit(1);
|
|
239
|
+
throw new Error(`Invalid --page-id: ${opts.pageId}`);
|
|
202
240
|
}
|
|
203
|
-
await runTool(cmd, 'close_page', { pageId });
|
|
241
|
+
await MainHelper.runTool(cmd, 'close_page', { pageId });
|
|
204
242
|
});
|
|
205
243
|
program
|
|
206
244
|
.command('navigate_page')
|
|
207
245
|
.description('Navigate the current page to a URL')
|
|
208
246
|
.requiredOption('--url <url>', 'URL to navigate to')
|
|
209
247
|
.action(async (opts, cmd) => {
|
|
210
|
-
await runTool(cmd, 'navigate_page', { url: opts.url });
|
|
248
|
+
await MainHelper.runTool(cmd, 'navigate_page', { url: opts.url });
|
|
211
249
|
});
|
|
212
250
|
program
|
|
213
251
|
.command('click')
|
|
214
252
|
.description('Click an element by its accessibility selector')
|
|
215
253
|
.requiredOption('-s, --selector <selector>', 'Accessibility selector (e.g. "#1_3" or \'button[name="Submit"]\')')
|
|
216
254
|
.action(async (opts, cmd) => {
|
|
217
|
-
await runTool(cmd, 'click', { selector: opts.selector });
|
|
255
|
+
await MainHelper.runTool(cmd, 'click', { selector: opts.selector });
|
|
218
256
|
});
|
|
219
257
|
program
|
|
220
258
|
.command('fill_form')
|
|
221
259
|
.description('Fill a form field by its accessibility selector')
|
|
222
260
|
.requiredOption('-s, --selector <selector>', 'Accessibility selector (e.g. "#1_3" or \'textbox[name="Email"]\')')
|
|
223
|
-
.requiredOption('--value <value>', 'Value to fill')
|
|
261
|
+
.requiredOption('-v, --value <value>', 'Value to fill')
|
|
224
262
|
.action(async (opts, cmd) => {
|
|
225
|
-
await runTool(cmd, 'fill_form', {
|
|
263
|
+
await MainHelper.runTool(cmd, 'fill_form', {
|
|
226
264
|
elements: [{ selector: opts.selector, value: opts.value }],
|
|
227
265
|
});
|
|
228
266
|
});
|
|
@@ -238,15 +276,8 @@ async function main() {
|
|
|
238
276
|
.option('--no-with-ancestors', 'Exclude ancestor nodes')
|
|
239
277
|
.option('--selectors-json <json>', 'JSON array of {selector,limit,withAncestors} for per-selector control')
|
|
240
278
|
.action(async (opts, cmd) => {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
body = buildQuerySelectorsBody(opts);
|
|
244
|
-
}
|
|
245
|
-
catch (err) {
|
|
246
|
-
console.error(`fastbrowser-cli error: ${err.message}`);
|
|
247
|
-
process.exit(1);
|
|
248
|
-
}
|
|
249
|
-
await runTool(cmd, 'query_selectors_all', body);
|
|
279
|
+
const body = MainHelper.buildQuerySelectorsBody(opts);
|
|
280
|
+
await MainHelper.runTool(cmd, 'query_selectors_all', body);
|
|
250
281
|
});
|
|
251
282
|
program
|
|
252
283
|
.command('query_selectors')
|
|
@@ -259,30 +290,43 @@ async function main() {
|
|
|
259
290
|
.option('--no-with-ancestors', 'Exclude ancestor nodes')
|
|
260
291
|
.option('--selectors-json <json>', 'JSON array of {selector,withAncestors} for per-selector control')
|
|
261
292
|
.action(async (opts, cmd) => {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
body = buildQuerySelectorFirstBody(opts);
|
|
265
|
-
}
|
|
266
|
-
catch (err) {
|
|
267
|
-
console.error(`fastbrowser-cli error: ${err.message}`);
|
|
268
|
-
process.exit(1);
|
|
269
|
-
}
|
|
270
|
-
await runTool(cmd, 'query_selectors', body);
|
|
293
|
+
const body = MainHelper.buildQuerySelectorFirstBody(opts);
|
|
294
|
+
await MainHelper.runTool(cmd, 'query_selectors', body);
|
|
271
295
|
});
|
|
272
296
|
program
|
|
273
297
|
.command('take_snapshot')
|
|
274
298
|
.description('Take an accessibility-tree snapshot of the current page')
|
|
275
299
|
.action(async (_opts, cmd) => {
|
|
276
|
-
await runTool(cmd, 'take_snapshot', {});
|
|
300
|
+
await MainHelper.runTool(cmd, 'take_snapshot', {});
|
|
277
301
|
});
|
|
278
302
|
program
|
|
279
303
|
.command('press_keys')
|
|
280
304
|
.description('Press a sequence of keys')
|
|
281
305
|
.requiredOption('--keys <keys>', "Comma-separated keys. E.g. 'Hello, Tab, Enter'")
|
|
282
306
|
.action(async (opts, cmd) => {
|
|
283
|
-
await runTool(cmd, 'press_keys', { keys: opts.keys });
|
|
307
|
+
await MainHelper.runTool(cmd, 'press_keys', { keys: opts.keys });
|
|
308
|
+
});
|
|
309
|
+
program
|
|
310
|
+
.command('install [skill-folder]')
|
|
311
|
+
.description('Install SKILL.md into <skill-folder>/skills/fastbrowser (default: .)')
|
|
312
|
+
.action(async (skillFolder) => {
|
|
313
|
+
await MainHelper.runInstall(skillFolder ?? '.');
|
|
314
|
+
});
|
|
315
|
+
program
|
|
316
|
+
.command('batch [file]')
|
|
317
|
+
.description('Run multiple commands from a file, piped stdin, or an inline --script string (one command per line, # comments allowed)')
|
|
318
|
+
.option('--script <script>', 'Inline multi-line script (overrides [file] and stdin)')
|
|
319
|
+
.option('--no-stop-on-error', 'Continue running subsequent lines after a failure (default: stop on first error)')
|
|
320
|
+
.action(async (file, opts, cmd) => {
|
|
321
|
+
const source = await MainHelper.readBatchSource(file, opts.script);
|
|
322
|
+
await MainHelper.runBatch(program, source, opts.stopOnError !== false, cmd);
|
|
284
323
|
});
|
|
285
|
-
|
|
324
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
325
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
326
|
+
//
|
|
327
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
328
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
329
|
+
await program.parseAsync();
|
|
286
330
|
}
|
|
287
331
|
void main();
|
|
288
332
|
//# sourceMappingURL=fastbrowser_cli.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fastbrowser_cli.js","sourceRoot":"","sources":["../../src/fastbrowser_cli/fastbrowser_cli.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fastbrowser_cli.js","sourceRoot":"","sources":["../../src/fastbrowser_cli/fastbrowser_cli.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastbrowser_cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/fastbrowser_cli/fastbrowser_cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -19,12 +19,18 @@
|
|
|
19
19
|
"keywords": [],
|
|
20
20
|
"author": "",
|
|
21
21
|
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/jeromeetienne/skillmd_collecetion.git"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/jeromeetienne/skillmd_collection/packages/fastbrowser_cli#readme",
|
|
22
27
|
"type": "commonjs",
|
|
23
28
|
"dependencies": {
|
|
24
29
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
25
30
|
"a11y_parse": "^1.0.1",
|
|
26
31
|
"commander": "^12.1.0",
|
|
27
32
|
"express": "^4.21.2",
|
|
33
|
+
"string-argv": "^0.3.2",
|
|
28
34
|
"typescript": "^6.0.3",
|
|
29
35
|
"zod": "^4.3.6",
|
|
30
36
|
"zod-from-json-schema": "^0.5.2"
|
|
@@ -190,6 +190,41 @@ npx fastbrowser_cli press_keys --keys "Tab, Tab, Enter"
|
|
|
190
190
|
npx fastbrowser_cli press_keys --keys "Hello, Tab, Enter"
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
+
## Batch Execution
|
|
194
|
+
|
|
195
|
+
Run several commands from one invocation — each line is parsed and executed like a standalone command, reusing the persistent HTTP server session.
|
|
196
|
+
|
|
197
|
+
Syntax rules:
|
|
198
|
+
- One command per line, same syntax as the standalone CLI (e.g. `click -s '...'`)
|
|
199
|
+
- Shell-style quoting (single and double quotes)
|
|
200
|
+
- Blank lines are ignored
|
|
201
|
+
- Lines starting with `#` are comments
|
|
202
|
+
|
|
203
|
+
By default, the batch stops at the first failing line (shell `set -e` semantics). Pass `--no-stop-on-error` to log failures and continue; the process still exits non-zero at the end if any line failed.
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# From a file
|
|
207
|
+
npx fastbrowser_cli batch ./demo.fbs
|
|
208
|
+
|
|
209
|
+
# Piped on stdin
|
|
210
|
+
cat demo.fbs | npx fastbrowser_cli batch
|
|
211
|
+
|
|
212
|
+
# Inline script
|
|
213
|
+
npx fastbrowser_cli batch --script $'press_keys --keys "Enter"\nclick -s \'button[name^="Tout effacer"]\''
|
|
214
|
+
|
|
215
|
+
# Continue through failures
|
|
216
|
+
npx fastbrowser_cli batch --no-stop-on-error ./demo.fbs
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Example `demo.fbs`:
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
# open a page and interact
|
|
223
|
+
new_page --url https://example.com
|
|
224
|
+
fill_form -s 'textbox[name="Email"]' --value 'hello@example.com'
|
|
225
|
+
press_keys --keys "Tab, Enter"
|
|
226
|
+
```
|
|
227
|
+
|
|
193
228
|
## Command Reference
|
|
194
229
|
|
|
195
230
|
| Command | Purpose | Required flags |
|
|
@@ -204,6 +239,7 @@ npx fastbrowser_cli press_keys --keys "Hello, Tab, Enter"
|
|
|
204
239
|
| `click` | Click an element by accessibility selector | `--selector` / `-s` |
|
|
205
240
|
| `fill_form` | Fill a form field by accessibility selector | `--selector` / `-s`, `--value` |
|
|
206
241
|
| `press_keys` | Press a comma-separated key sequence | `--keys` |
|
|
242
|
+
| `batch` | Run multiple commands from a file, piped stdin, or `--script` inline | one of: `<file>`, `--script`, or piped stdin |
|
|
207
243
|
| `server start` | Start the HTTP server daemon | — |
|
|
208
244
|
| `server status` | Report server running/stopped | — |
|
|
209
245
|
| `server stop` | Stop the HTTP server | — |
|
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// node imports
|
|
4
3
|
import fs from 'node:fs';
|
|
5
4
|
import path from 'node:path';
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
import
|
|
6
|
+
import { Command, CommanderError } from 'commander';
|
|
7
|
+
import stringArgv from 'string-argv';
|
|
9
8
|
|
|
10
|
-
// local imports
|
|
11
9
|
import { HttpClient } from './libs/http-client.js';
|
|
12
10
|
import { ServerManager } from './libs/server-manager.js';
|
|
13
11
|
import type { QuerySelectorInput, QuerySelectorFirstInput, QuerySelectorsAllRequest, QuerySelectorRequest } from '../fastbrowser_httpd/libs/tool-schemas.js';
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
17
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
18
|
-
//
|
|
19
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
20
13
|
///////////////////////////////////////////////////////////////////////////////
|
|
21
14
|
|
|
22
15
|
type GlobalOpts = {
|
|
@@ -24,151 +17,206 @@ type GlobalOpts = {
|
|
|
24
17
|
autostart?: boolean;
|
|
25
18
|
};
|
|
26
19
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
class SilentExitError extends Error {
|
|
21
|
+
constructor() {
|
|
22
|
+
super('silent-exit');
|
|
23
|
+
}
|
|
30
24
|
}
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
const globalOpts = cmd.optsWithGlobals<GlobalOpts>();
|
|
34
|
-
return globalOpts.autostart !== false;
|
|
35
|
-
}
|
|
26
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
36
27
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
class MainHelper {
|
|
29
|
+
static getServerFromCmd(cmd: Command): string {
|
|
30
|
+
const globalOpts = cmd.optsWithGlobals<GlobalOpts>();
|
|
31
|
+
return HttpClient.getServerUrl(globalOpts.server);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static getAutostartFromCmd(cmd: Command): boolean {
|
|
35
|
+
const globalOpts = cmd.optsWithGlobals<GlobalOpts>();
|
|
36
|
+
return globalOpts.autostart !== false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static async runTool(cmd: Command, routeName: string, body: unknown): Promise<void> {
|
|
40
|
+
const server = MainHelper.getServerFromCmd(cmd);
|
|
41
|
+
if (MainHelper.getAutostartFromCmd(cmd) === true) {
|
|
41
42
|
await ServerManager.ensureRunning(server);
|
|
42
43
|
}
|
|
43
44
|
const response = await HttpClient.postTool(server, routeName, body);
|
|
44
45
|
HttpClient.printResponse(response);
|
|
45
|
-
} catch (err) {
|
|
46
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
47
|
-
console.error(`fastbrowser-cli error: ${message}`);
|
|
48
|
-
process.exit(1);
|
|
49
46
|
}
|
|
50
|
-
}
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
static buildQuerySelectorsBody(opts: {
|
|
49
|
+
selector?: string[];
|
|
50
|
+
limit?: string;
|
|
51
|
+
withAncestors?: boolean;
|
|
52
|
+
selectorsJson?: string;
|
|
53
|
+
}): QuerySelectorsAllRequest {
|
|
54
|
+
if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
|
|
55
|
+
let parsed: unknown;
|
|
56
|
+
try {
|
|
57
|
+
parsed = JSON.parse(opts.selectorsJson);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
throw new Error(`--selectors-json is not valid JSON: ${(err as Error).message}`);
|
|
60
|
+
}
|
|
61
|
+
if (Array.isArray(parsed) === false) {
|
|
62
|
+
throw new Error('--selectors-json must be a JSON array');
|
|
63
|
+
}
|
|
64
|
+
return { selectors: parsed as QuerySelectorInput[] };
|
|
65
|
+
}
|
|
57
66
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
withAncestors?: boolean;
|
|
62
|
-
selectorsJson?: string;
|
|
63
|
-
}): QuerySelectorsAllRequest {
|
|
64
|
-
if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
|
|
65
|
-
let parsed: unknown;
|
|
66
|
-
try {
|
|
67
|
-
parsed = JSON.parse(opts.selectorsJson);
|
|
68
|
-
} catch (err) {
|
|
69
|
-
throw new Error(`--selectors-json is not valid JSON: ${(err as Error).message}`);
|
|
67
|
+
const selectorList = opts.selector ?? [];
|
|
68
|
+
if (selectorList.length === 0) {
|
|
69
|
+
throw new Error('At least one --selector or --selectors-json is required');
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
|
|
72
|
+
const limit = opts.limit === undefined ? 0 : Number.parseInt(opts.limit, 10);
|
|
73
|
+
if (Number.isNaN(limit) === true) {
|
|
74
|
+
throw new Error(`Invalid --limit: ${opts.limit}`);
|
|
73
75
|
}
|
|
74
|
-
|
|
76
|
+
const withAncestors = opts.withAncestors !== false;
|
|
77
|
+
|
|
78
|
+
const selectors: QuerySelectorInput[] = selectorList.map((selector) => ({
|
|
79
|
+
selector,
|
|
80
|
+
limit,
|
|
81
|
+
withAncestors,
|
|
82
|
+
}));
|
|
83
|
+
return { selectors };
|
|
75
84
|
}
|
|
76
85
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
static buildQuerySelectorFirstBody(opts: {
|
|
87
|
+
selector?: string[];
|
|
88
|
+
withAncestors?: boolean;
|
|
89
|
+
selectorsJson?: string;
|
|
90
|
+
}): QuerySelectorRequest {
|
|
91
|
+
if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
|
|
92
|
+
let parsed: unknown;
|
|
93
|
+
try {
|
|
94
|
+
parsed = JSON.parse(opts.selectorsJson);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
throw new Error(`--selectors-json is not valid JSON: ${(err as Error).message}`);
|
|
97
|
+
}
|
|
98
|
+
if (Array.isArray(parsed) === false) {
|
|
99
|
+
throw new Error('--selectors-json must be a JSON array');
|
|
100
|
+
}
|
|
101
|
+
return { selectors: parsed as QuerySelectorFirstInput[] };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const selectorList = opts.selector ?? [];
|
|
105
|
+
if (selectorList.length === 0) {
|
|
106
|
+
throw new Error('At least one --selector or --selectors-json is required');
|
|
107
|
+
}
|
|
81
108
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
109
|
+
const withAncestors = opts.withAncestors !== false;
|
|
110
|
+
|
|
111
|
+
const selectors: QuerySelectorFirstInput[] = selectorList.map((selector) => ({
|
|
112
|
+
selector,
|
|
113
|
+
withAncestors,
|
|
114
|
+
}));
|
|
115
|
+
return { selectors };
|
|
85
116
|
}
|
|
86
|
-
const withAncestors = opts.withAncestors !== false;
|
|
87
|
-
|
|
88
|
-
const selectors: QuerySelectorInput[] = selectorList.map((selector) => ({
|
|
89
|
-
selector,
|
|
90
|
-
limit,
|
|
91
|
-
withAncestors,
|
|
92
|
-
}));
|
|
93
|
-
return { selectors };
|
|
94
|
-
}
|
|
95
117
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}): QuerySelectorRequest {
|
|
101
|
-
if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
|
|
102
|
-
let parsed: unknown;
|
|
118
|
+
static async runInstall(skillFolder: string): Promise<void> {
|
|
119
|
+
const sourceSkillMd = path.resolve(__dirname, '../../skills/fastbrowser/SKILL.md');
|
|
120
|
+
const targetDir = path.resolve(skillFolder, 'skills', 'fastbrowser');
|
|
121
|
+
const targetSkillMd = path.join(targetDir, 'SKILL.md');
|
|
103
122
|
try {
|
|
104
|
-
|
|
123
|
+
await fs.promises.mkdir(targetDir, { recursive: true });
|
|
124
|
+
await fs.promises.copyFile(sourceSkillMd, targetSkillMd);
|
|
125
|
+
console.log(`Installed fastbrowser SKILL.md at ${targetSkillMd}`);
|
|
105
126
|
} catch (err) {
|
|
106
|
-
|
|
127
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
128
|
+
console.error(`fastbrowser-cli error: ${message}`);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static async readBatchSource(file: string | undefined, inlineScript: string | undefined): Promise<string> {
|
|
134
|
+
if (inlineScript !== undefined && inlineScript !== '') {
|
|
135
|
+
return inlineScript;
|
|
136
|
+
}
|
|
137
|
+
if (file !== undefined && file !== '') {
|
|
138
|
+
return await fs.promises.readFile(file, 'utf-8');
|
|
107
139
|
}
|
|
108
|
-
if (
|
|
109
|
-
throw new Error('
|
|
140
|
+
if (process.stdin.isTTY === true) {
|
|
141
|
+
throw new Error('batch: no input. Provide a file path, --script, or pipe commands on stdin.');
|
|
110
142
|
}
|
|
111
|
-
return
|
|
143
|
+
return await MainHelper.readStdinToString();
|
|
112
144
|
}
|
|
113
145
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
146
|
+
static async readStdinToString(): Promise<string> {
|
|
147
|
+
const chunks: Buffer[] = [];
|
|
148
|
+
return await new Promise((resolve, reject) => {
|
|
149
|
+
process.stdin.on('data', (chunk) => chunks.push(chunk as Buffer));
|
|
150
|
+
process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
|
|
151
|
+
process.stdin.on('error', (err) => reject(err));
|
|
152
|
+
});
|
|
117
153
|
}
|
|
118
154
|
|
|
119
|
-
|
|
155
|
+
static async runBatch(program: Command, source: string, stopOnError: boolean, batchCmd: Command): Promise<void> {
|
|
156
|
+
const globalOpts = batchCmd.optsWithGlobals<GlobalOpts>();
|
|
157
|
+
const globalFlags: string[] = [];
|
|
158
|
+
if (globalOpts.server !== undefined) {
|
|
159
|
+
globalFlags.push('--server', globalOpts.server);
|
|
160
|
+
}
|
|
161
|
+
if (globalOpts.autostart === false) {
|
|
162
|
+
globalFlags.push('--no-autostart');
|
|
163
|
+
}
|
|
120
164
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
165
|
+
const lines = source.split('\n');
|
|
166
|
+
let ok = 0;
|
|
167
|
+
let failed = 0;
|
|
168
|
+
for (const rawLine of lines) {
|
|
169
|
+
const line = rawLine.trim();
|
|
170
|
+
if (line === '' || line.startsWith('#') === true) continue;
|
|
127
171
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
//
|
|
131
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
132
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
172
|
+
const argv = stringArgv(line);
|
|
173
|
+
if (argv.length === 0) continue;
|
|
133
174
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
175
|
+
console.log(`> ${line}`);
|
|
176
|
+
try {
|
|
177
|
+
await program.parseAsync([...globalFlags, ...argv], { from: 'user' });
|
|
178
|
+
ok += 1;
|
|
179
|
+
} catch (err) {
|
|
180
|
+
failed += 1;
|
|
181
|
+
if (err instanceof SilentExitError === false && err instanceof CommanderError === false) {
|
|
182
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
183
|
+
console.error(`fastbrowser-cli error: ${message}`);
|
|
184
|
+
}
|
|
185
|
+
if (stopOnError === true) {
|
|
186
|
+
throw new SilentExitError();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (stopOnError === false) {
|
|
192
|
+
console.log(`batch: ${ok} ok, ${failed} failed`);
|
|
193
|
+
}
|
|
194
|
+
if (failed > 0) {
|
|
195
|
+
throw new SilentExitError();
|
|
196
|
+
}
|
|
146
197
|
}
|
|
147
198
|
}
|
|
148
199
|
|
|
149
200
|
///////////////////////////////////////////////////////////////////////////////
|
|
150
201
|
///////////////////////////////////////////////////////////////////////////////
|
|
151
|
-
//
|
|
202
|
+
//
|
|
152
203
|
///////////////////////////////////////////////////////////////////////////////
|
|
153
204
|
///////////////////////////////////////////////////////////////////////////////
|
|
154
205
|
|
|
155
206
|
async function main(): Promise<void> {
|
|
156
|
-
const installIdx = process.argv.indexOf('--install');
|
|
157
|
-
if (installIdx !== -1) {
|
|
158
|
-
const next = process.argv[installIdx + 1];
|
|
159
|
-
const skillFolder = (next !== undefined && next.startsWith('-') === false) ? next : '.';
|
|
160
|
-
await runInstall(skillFolder);
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
207
|
const program = new Command();
|
|
165
208
|
program
|
|
166
209
|
.name('fastbrowser-cli')
|
|
167
210
|
.description('CLI client for fastbrowser')
|
|
168
211
|
.option('--server <url>', 'fastbrowser-httpd URL (default: env FASTBROWSER_SERVER or http://localhost:8787)')
|
|
169
212
|
.option('--autostart', 'Auto-start the server before a command if it is not running', true)
|
|
170
|
-
.option('--no-autostart', 'Do not auto-start the server before a command')
|
|
171
|
-
|
|
213
|
+
.option('--no-autostart', 'Do not auto-start the server before a command');
|
|
214
|
+
|
|
215
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
216
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
217
|
+
//
|
|
218
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
219
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
172
220
|
|
|
173
221
|
const serverCmd = program
|
|
174
222
|
.command('server')
|
|
@@ -178,45 +226,39 @@ async function main(): Promise<void> {
|
|
|
178
226
|
.command('start')
|
|
179
227
|
.description('Start the fastbrowser HTTP server as a detached daemon')
|
|
180
228
|
.action(async (_opts, cmd: Command) => {
|
|
181
|
-
const server = getServerFromCmd(cmd);
|
|
182
|
-
|
|
183
|
-
await ServerManager.start(server);
|
|
184
|
-
} catch (err) {
|
|
185
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
186
|
-
console.error(`fastbrowser-cli error: ${message}`);
|
|
187
|
-
process.exit(1);
|
|
188
|
-
}
|
|
229
|
+
const server = MainHelper.getServerFromCmd(cmd);
|
|
230
|
+
await ServerManager.start(server);
|
|
189
231
|
});
|
|
190
232
|
|
|
191
233
|
serverCmd
|
|
192
234
|
.command('stop')
|
|
193
235
|
.description('Stop the fastbrowser HTTP server')
|
|
194
236
|
.action(async (_opts, cmd: Command) => {
|
|
195
|
-
const server = getServerFromCmd(cmd);
|
|
196
|
-
|
|
197
|
-
await ServerManager.stop(server);
|
|
198
|
-
} catch (err) {
|
|
199
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
200
|
-
console.error(`fastbrowser-cli error: ${message}`);
|
|
201
|
-
process.exit(1);
|
|
202
|
-
}
|
|
237
|
+
const server = MainHelper.getServerFromCmd(cmd);
|
|
238
|
+
await ServerManager.stop(server);
|
|
203
239
|
});
|
|
204
240
|
|
|
205
241
|
serverCmd
|
|
206
242
|
.command('status')
|
|
207
243
|
.description('Report whether the fastbrowser HTTP server is running')
|
|
208
244
|
.action(async (_opts, cmd: Command) => {
|
|
209
|
-
const server = getServerFromCmd(cmd);
|
|
245
|
+
const server = MainHelper.getServerFromCmd(cmd);
|
|
210
246
|
const state = await ServerManager.status(server);
|
|
211
247
|
console.log(`fastbrowser server at ${server}: ${state}`);
|
|
212
|
-
if (state === 'stopped')
|
|
248
|
+
if (state === 'stopped') throw new SilentExitError();
|
|
213
249
|
});
|
|
214
250
|
|
|
251
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
252
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
253
|
+
//
|
|
254
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
255
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
256
|
+
|
|
215
257
|
program
|
|
216
258
|
.command('list_pages')
|
|
217
259
|
.description('List all open browser pages')
|
|
218
260
|
.action(async (_opts, cmd: Command) => {
|
|
219
|
-
await runTool(cmd, 'list_pages', {});
|
|
261
|
+
await MainHelper.runTool(cmd, 'list_pages', {});
|
|
220
262
|
});
|
|
221
263
|
|
|
222
264
|
program
|
|
@@ -224,7 +266,7 @@ async function main(): Promise<void> {
|
|
|
224
266
|
.description('Open a new browser page')
|
|
225
267
|
.requiredOption('--url <url>', 'URL to open')
|
|
226
268
|
.action(async (opts: { url: string }, cmd: Command) => {
|
|
227
|
-
await runTool(cmd, 'new_page', { url: opts.url });
|
|
269
|
+
await MainHelper.runTool(cmd, 'new_page', { url: opts.url });
|
|
228
270
|
});
|
|
229
271
|
|
|
230
272
|
program
|
|
@@ -234,10 +276,9 @@ async function main(): Promise<void> {
|
|
|
234
276
|
.action(async (opts: { pageId: string }, cmd: Command) => {
|
|
235
277
|
const pageId = Number.parseInt(opts.pageId, 10);
|
|
236
278
|
if (Number.isNaN(pageId) === true) {
|
|
237
|
-
|
|
238
|
-
process.exit(1);
|
|
279
|
+
throw new Error(`Invalid --page-id: ${opts.pageId}`);
|
|
239
280
|
}
|
|
240
|
-
await runTool(cmd, 'close_page', { pageId });
|
|
281
|
+
await MainHelper.runTool(cmd, 'close_page', { pageId });
|
|
241
282
|
});
|
|
242
283
|
|
|
243
284
|
program
|
|
@@ -245,7 +286,7 @@ async function main(): Promise<void> {
|
|
|
245
286
|
.description('Navigate the current page to a URL')
|
|
246
287
|
.requiredOption('--url <url>', 'URL to navigate to')
|
|
247
288
|
.action(async (opts: { url: string }, cmd: Command) => {
|
|
248
|
-
await runTool(cmd, 'navigate_page', { url: opts.url });
|
|
289
|
+
await MainHelper.runTool(cmd, 'navigate_page', { url: opts.url });
|
|
249
290
|
});
|
|
250
291
|
|
|
251
292
|
program
|
|
@@ -253,16 +294,16 @@ async function main(): Promise<void> {
|
|
|
253
294
|
.description('Click an element by its accessibility selector')
|
|
254
295
|
.requiredOption('-s, --selector <selector>', 'Accessibility selector (e.g. "#1_3" or \'button[name="Submit"]\')')
|
|
255
296
|
.action(async (opts: { selector: string }, cmd: Command) => {
|
|
256
|
-
await runTool(cmd, 'click', { selector: opts.selector });
|
|
297
|
+
await MainHelper.runTool(cmd, 'click', { selector: opts.selector });
|
|
257
298
|
});
|
|
258
299
|
|
|
259
300
|
program
|
|
260
301
|
.command('fill_form')
|
|
261
302
|
.description('Fill a form field by its accessibility selector')
|
|
262
303
|
.requiredOption('-s, --selector <selector>', 'Accessibility selector (e.g. "#1_3" or \'textbox[name="Email"]\')')
|
|
263
|
-
.requiredOption('--value <value>', 'Value to fill')
|
|
304
|
+
.requiredOption('-v, --value <value>', 'Value to fill')
|
|
264
305
|
.action(async (opts: { selector: string; value: string }, cmd: Command) => {
|
|
265
|
-
await runTool(cmd, 'fill_form', {
|
|
306
|
+
await MainHelper.runTool(cmd, 'fill_form', {
|
|
266
307
|
elements: [{ selector: opts.selector, value: opts.value }],
|
|
267
308
|
});
|
|
268
309
|
});
|
|
@@ -284,14 +325,8 @@ async function main(): Promise<void> {
|
|
|
284
325
|
withAncestors?: boolean;
|
|
285
326
|
selectorsJson?: string;
|
|
286
327
|
}, cmd: Command) => {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
body = buildQuerySelectorsBody(opts);
|
|
290
|
-
} catch (err) {
|
|
291
|
-
console.error(`fastbrowser-cli error: ${(err as Error).message}`);
|
|
292
|
-
process.exit(1);
|
|
293
|
-
}
|
|
294
|
-
await runTool(cmd, 'query_selectors_all', body);
|
|
328
|
+
const body = MainHelper.buildQuerySelectorsBody(opts);
|
|
329
|
+
await MainHelper.runTool(cmd, 'query_selectors_all', body);
|
|
295
330
|
});
|
|
296
331
|
|
|
297
332
|
program
|
|
@@ -309,21 +344,15 @@ async function main(): Promise<void> {
|
|
|
309
344
|
withAncestors?: boolean;
|
|
310
345
|
selectorsJson?: string;
|
|
311
346
|
}, cmd: Command) => {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
body = buildQuerySelectorFirstBody(opts);
|
|
315
|
-
} catch (err) {
|
|
316
|
-
console.error(`fastbrowser-cli error: ${(err as Error).message}`);
|
|
317
|
-
process.exit(1);
|
|
318
|
-
}
|
|
319
|
-
await runTool(cmd, 'query_selectors', body);
|
|
347
|
+
const body = MainHelper.buildQuerySelectorFirstBody(opts);
|
|
348
|
+
await MainHelper.runTool(cmd, 'query_selectors', body);
|
|
320
349
|
});
|
|
321
350
|
|
|
322
351
|
program
|
|
323
352
|
.command('take_snapshot')
|
|
324
353
|
.description('Take an accessibility-tree snapshot of the current page')
|
|
325
354
|
.action(async (_opts, cmd: Command) => {
|
|
326
|
-
await runTool(cmd, 'take_snapshot', {});
|
|
355
|
+
await MainHelper.runTool(cmd, 'take_snapshot', {});
|
|
327
356
|
});
|
|
328
357
|
|
|
329
358
|
program
|
|
@@ -331,10 +360,33 @@ async function main(): Promise<void> {
|
|
|
331
360
|
.description('Press a sequence of keys')
|
|
332
361
|
.requiredOption('--keys <keys>', "Comma-separated keys. E.g. 'Hello, Tab, Enter'")
|
|
333
362
|
.action(async (opts: { keys: string }, cmd: Command) => {
|
|
334
|
-
await runTool(cmd, 'press_keys', { keys: opts.keys });
|
|
363
|
+
await MainHelper.runTool(cmd, 'press_keys', { keys: opts.keys });
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
program
|
|
367
|
+
.command('install [skill-folder]')
|
|
368
|
+
.description('Install SKILL.md into <skill-folder>/skills/fastbrowser (default: .)')
|
|
369
|
+
.action(async (skillFolder: string | undefined) => {
|
|
370
|
+
await MainHelper.runInstall(skillFolder ?? '.');
|
|
335
371
|
});
|
|
336
372
|
|
|
337
|
-
|
|
373
|
+
program
|
|
374
|
+
.command('batch [file]')
|
|
375
|
+
.description('Run multiple commands from a file, piped stdin, or an inline --script string (one command per line, # comments allowed)')
|
|
376
|
+
.option('--script <script>', 'Inline multi-line script (overrides [file] and stdin)')
|
|
377
|
+
.option('--no-stop-on-error', 'Continue running subsequent lines after a failure (default: stop on first error)')
|
|
378
|
+
.action(async (file: string | undefined, opts: { script?: string; stopOnError: boolean }, cmd: Command) => {
|
|
379
|
+
const source = await MainHelper.readBatchSource(file, opts.script);
|
|
380
|
+
await MainHelper.runBatch(program, source, opts.stopOnError !== false, cmd);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
384
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
385
|
+
//
|
|
386
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
387
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
388
|
+
|
|
389
|
+
await program.parseAsync();
|
|
338
390
|
}
|
|
339
391
|
|
|
340
392
|
void main();
|
|
File without changes
|