@cli4ai/chrome 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/c4ai.json +22 -0
- package/package.json +42 -0
- package/run.ts +86 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Chrome
|
|
2
|
+
|
|
3
|
+
Browser automation with your profile.
|
|
4
|
+
|
|
5
|
+
## Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
./start.sh # Launch Chrome (quit Chrome first)
|
|
9
|
+
./run.js connect # Connect puppeteer
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
./run.js navigate <url> [--new-tab]
|
|
16
|
+
./run.js eval "<js>"
|
|
17
|
+
./run.js screenshot [file] [--full-page]
|
|
18
|
+
./run.js cookies [domain]
|
|
19
|
+
```
|
package/c4ai.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "chrome",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Chrome browser automation (foundation for browser tools)",
|
|
5
|
+
"author": "cliforai",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"entry": "run.ts",
|
|
8
|
+
"runtime": "bun",
|
|
9
|
+
"keywords": ["chrome", "browser", "puppeteer", "automation"],
|
|
10
|
+
"commands": {
|
|
11
|
+
"connect": { "description": "Connect to Chrome", "args": [{ "name": "port", "description": "Default: 9222", "required": false }] },
|
|
12
|
+
"navigate": { "description": "Open URL", "args": [{ "name": "url", "required": true }] },
|
|
13
|
+
"eval": { "description": "Run JavaScript", "args": [{ "name": "script", "required": true }] },
|
|
14
|
+
"screenshot": { "description": "Capture viewport", "args": [{ "name": "output", "required": false }] },
|
|
15
|
+
"cookies": { "description": "Get cookies", "args": [{ "name": "domain", "required": false }] }
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"puppeteer": "^24.0.0",
|
|
19
|
+
"commander": "^14.0.0"
|
|
20
|
+
},
|
|
21
|
+
"mcp": { "enabled": true, "transport": "stdio" }
|
|
22
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cli4ai/chrome",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Chrome browser automation (foundation for browser tools)",
|
|
5
|
+
"author": "cliforai",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "run.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"chrome": "./run.ts"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"c4ai",
|
|
14
|
+
"cli",
|
|
15
|
+
"ai-tools",
|
|
16
|
+
"chrome",
|
|
17
|
+
"browser",
|
|
18
|
+
"puppeteer",
|
|
19
|
+
"automation"
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/cli4ai/packages",
|
|
24
|
+
"directory": "packages/chrome"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/cli4ai/packages/tree/main/packages/chrome",
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/cli4ai/packages/issues"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"run.ts",
|
|
32
|
+
"c4ai.json",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"test": "bun test"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/run.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import puppeteer from 'puppeteer';
|
|
3
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
4
|
+
import { join, resolve } from 'path';
|
|
5
|
+
import { cli, output, outputError, withErrorHandling } from '../lib/cli.ts';
|
|
6
|
+
|
|
7
|
+
const WS_FILE = join(import.meta.dir, '.ws-endpoint');
|
|
8
|
+
|
|
9
|
+
async function getPage(newTab = false) {
|
|
10
|
+
let ws: string;
|
|
11
|
+
try {
|
|
12
|
+
ws = readFileSync(WS_FILE, 'utf-8');
|
|
13
|
+
} catch {
|
|
14
|
+
outputError('NOT_FOUND', 'Not connected to Chrome', {
|
|
15
|
+
hint: 'Run: chrome connect'
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const browser = await puppeteer.connect({ browserWSEndpoint: ws });
|
|
20
|
+
const pages = await browser.pages();
|
|
21
|
+
const page = newTab ? await browser.newPage() : (pages[pages.length - 1] || await browser.newPage());
|
|
22
|
+
return { page, browser };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const program = cli('chrome', '1.0.0', 'Chrome browser automation');
|
|
26
|
+
|
|
27
|
+
program
|
|
28
|
+
.command('connect [port]')
|
|
29
|
+
.description('Connect to Chrome (default: 9222)')
|
|
30
|
+
.action(withErrorHandling(async (port = '9222') => {
|
|
31
|
+
const browser = await puppeteer.connect({ browserURL: `http://127.0.0.1:${port}` });
|
|
32
|
+
writeFileSync(WS_FILE, browser.wsEndpoint());
|
|
33
|
+
console.log(`Connected on port ${port}`);
|
|
34
|
+
browser.disconnect();
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
program
|
|
38
|
+
.command('navigate <url>')
|
|
39
|
+
.description('Open URL')
|
|
40
|
+
.option('--new-tab', 'Open in new tab')
|
|
41
|
+
.action(withErrorHandling(async (url: string, options: { newTab?: boolean }) => {
|
|
42
|
+
const { page, browser } = await getPage(options.newTab);
|
|
43
|
+
await page.goto(url, { waitUntil: 'networkidle2' });
|
|
44
|
+
console.log(await page.title());
|
|
45
|
+
if (options.newTab) await page.close();
|
|
46
|
+
browser.disconnect();
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
program
|
|
50
|
+
.command('eval <script>')
|
|
51
|
+
.description('Run JavaScript')
|
|
52
|
+
.action(withErrorHandling(async (script: string) => {
|
|
53
|
+
const { page, browser } = await getPage();
|
|
54
|
+
const result = await page.evaluate((code: string) => eval(code), script);
|
|
55
|
+
if (result !== undefined) output(result);
|
|
56
|
+
browser.disconnect();
|
|
57
|
+
}));
|
|
58
|
+
|
|
59
|
+
program
|
|
60
|
+
.command('screenshot [output]')
|
|
61
|
+
.description('Capture viewport')
|
|
62
|
+
.option('--full-page', 'Capture full page')
|
|
63
|
+
.action(withErrorHandling(async (outputFile = 'screenshot.png', options: { fullPage?: boolean }) => {
|
|
64
|
+
const { page, browser } = await getPage();
|
|
65
|
+
const outputPath = resolve(outputFile);
|
|
66
|
+
await page.screenshot({ path: outputPath, fullPage: options.fullPage });
|
|
67
|
+
console.log(`Saved: ${outputPath}`);
|
|
68
|
+
browser.disconnect();
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
program
|
|
72
|
+
.command('cookies [domain]')
|
|
73
|
+
.description('Get cookies')
|
|
74
|
+
.action(withErrorHandling(async (domain?: string) => {
|
|
75
|
+
const { page, browser } = await getPage();
|
|
76
|
+
const client = await page.createCDPSession();
|
|
77
|
+
const { cookies } = await client.send('Network.getAllCookies');
|
|
78
|
+
const filtered = domain && domain !== '--all'
|
|
79
|
+
? cookies.filter((c: { domain: string }) => c.domain.includes(domain))
|
|
80
|
+
: cookies;
|
|
81
|
+
output(filtered);
|
|
82
|
+
console.error(`\n${filtered.length} cookies`);
|
|
83
|
+
browser.disconnect();
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
program.parse();
|