imperium-crawl 2.3.1 → 2.4.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 +69 -11
- package/dist/cli-explore.d.ts +30 -0
- package/dist/cli-explore.d.ts.map +1 -0
- package/dist/cli-explore.js +427 -0
- package/dist/cli-explore.js.map +1 -0
- package/dist/cli-recorder.d.ts +44 -0
- package/dist/cli-recorder.d.ts.map +1 -0
- package/dist/cli-recorder.js +67 -0
- package/dist/cli-recorder.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +28 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/knowledge/index.d.ts +1 -0
- package/dist/knowledge/index.d.ts.map +1 -1
- package/dist/knowledge/index.js +1 -0
- package/dist/knowledge/index.js.map +1 -1
- package/dist/knowledge/record-browser.d.ts +17 -0
- package/dist/knowledge/record-browser.d.ts.map +1 -0
- package/dist/knowledge/record-browser.js +29 -0
- package/dist/knowledge/record-browser.js.map +1 -0
- package/dist/llm/retry.d.ts +4 -2
- package/dist/llm/retry.d.ts.map +1 -1
- package/dist/llm/retry.js +15 -4
- package/dist/llm/retry.js.map +1 -1
- package/dist/sessions/index.d.ts +1 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +1 -1
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/manager.d.ts +20 -0
- package/dist/sessions/manager.d.ts.map +1 -1
- package/dist/sessions/manager.js +57 -0
- package/dist/sessions/manager.js.map +1 -1
- package/dist/sessions/types.d.ts +2 -0
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/skills/chain.d.ts +61 -0
- package/dist/skills/chain.d.ts.map +1 -0
- package/dist/skills/chain.js +182 -0
- package/dist/skills/chain.js.map +1 -0
- package/dist/skills/conditions.d.ts +14 -0
- package/dist/skills/conditions.d.ts.map +1 -0
- package/dist/skills/conditions.js +208 -0
- package/dist/skills/conditions.js.map +1 -0
- package/dist/skills/manager.d.ts +47 -2
- package/dist/skills/manager.d.ts.map +1 -1
- package/dist/skills/manager.js.map +1 -1
- package/dist/skills/parameters.d.ts +49 -0
- package/dist/skills/parameters.d.ts.map +1 -0
- package/dist/skills/parameters.js +157 -0
- package/dist/skills/parameters.js.map +1 -0
- package/dist/stealth/index.d.ts +1 -0
- package/dist/stealth/index.d.ts.map +1 -1
- package/dist/stealth/index.js +61 -13
- package/dist/stealth/index.js.map +1 -1
- package/dist/tools/action-executor.d.ts +64 -0
- package/dist/tools/action-executor.d.ts.map +1 -0
- package/dist/tools/action-executor.js +365 -0
- package/dist/tools/action-executor.js.map +1 -0
- package/dist/tools/batch-scrape.d.ts +2 -2
- package/dist/tools/crawl.d.ts +2 -2
- package/dist/tools/create-skill.d.ts +2 -2
- package/dist/tools/discover-apis.d.ts +1 -1
- package/dist/tools/discover-apis.d.ts.map +1 -1
- package/dist/tools/discover-apis.js +3 -0
- package/dist/tools/discover-apis.js.map +1 -1
- package/dist/tools/download.d.ts +4 -4
- package/dist/tools/download.d.ts.map +1 -1
- package/dist/tools/download.js +3 -0
- package/dist/tools/download.js.map +1 -1
- package/dist/tools/extract.d.ts +1 -1
- package/dist/tools/image-search.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/instagram.d.ts +2 -2
- package/dist/tools/interact.d.ts +72 -44
- package/dist/tools/interact.d.ts.map +1 -1
- package/dist/tools/interact.js +33 -299
- package/dist/tools/interact.js.map +1 -1
- package/dist/tools/knowledge.d.ts +24 -0
- package/dist/tools/knowledge.d.ts.map +1 -0
- package/dist/tools/knowledge.js +99 -0
- package/dist/tools/knowledge.js.map +1 -0
- package/dist/tools/list-skills.js +1 -1
- package/dist/tools/list-skills.js.map +1 -1
- package/dist/tools/manifest.d.ts.map +1 -1
- package/dist/tools/manifest.js +5 -0
- package/dist/tools/manifest.js.map +1 -1
- package/dist/tools/monitor-websocket.d.ts +1 -1
- package/dist/tools/news-search.d.ts +1 -1
- package/dist/tools/query-api.d.ts +6 -6
- package/dist/tools/readability.d.ts +2 -2
- package/dist/tools/reddit.d.ts +4 -4
- package/dist/tools/run-skill.d.ts +14 -4
- package/dist/tools/run-skill.d.ts.map +1 -1
- package/dist/tools/run-skill.js +73 -0
- package/dist/tools/run-skill.js.map +1 -1
- package/dist/tools/scrape.d.ts +9 -6
- package/dist/tools/scrape.d.ts.map +1 -1
- package/dist/tools/scrape.js +2 -0
- package/dist/tools/scrape.js.map +1 -1
- package/dist/tools/screenshot.d.ts.map +1 -1
- package/dist/tools/screenshot.js +6 -0
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/search.d.ts +1 -1
- package/dist/tools/snapshot.d.ts +5 -5
- package/dist/tools/snapshot.d.ts.map +1 -1
- package/dist/tools/snapshot.js +3 -0
- package/dist/tools/snapshot.js.map +1 -1
- package/dist/tools/video-search.d.ts +1 -1
- package/dist/tools/youtube.d.ts +2 -2
- package/dist/utils/fetcher.d.ts.map +1 -1
- package/dist/utils/fetcher.js +33 -0
- package/dist/utils/fetcher.js.map +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
**The most powerful open-source CLI tool for web scraping, crawling, and data extraction.**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
29 tools. Zero API keys required. One `npx` command.
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/imperium-crawl)
|
|
10
10
|
[](./LICENSE)
|
|
11
|
-
[]()
|
|
12
12
|
[](https://www.npmjs.com/package/imperium-crawl)
|
|
13
13
|
|
|
14
14
|
</div>
|
|
@@ -31,7 +31,7 @@ npx -y imperium-crawl scrape --url https://example.com
|
|
|
31
31
|
npm install -g imperium-crawl
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
> That's it.
|
|
34
|
+
> That's it. 23 of 29 tools work with zero API keys. Add optional keys later to unlock search, AI extraction, and CAPTCHA solving.
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
@@ -107,7 +107,7 @@ Scraping 4 URLs (concurrency: 3)...
|
|
|
107
107
|
## Why imperium-crawl?
|
|
108
108
|
|
|
109
109
|
🔓 **Zero API Keys Required**
|
|
110
|
-
|
|
110
|
+
23 of 29 tools work out of the box. No accounts, no tokens, no credit cards. Just `npx` and go.
|
|
111
111
|
|
|
112
112
|
🛡️ **3-Level Auto-Escalating Stealth**
|
|
113
113
|
Headers → TLS fingerprinting → headless browser + CAPTCHA solving. Automatically escalates until it gets through.
|
|
@@ -115,7 +115,7 @@ Headers → TLS fingerprinting → headless browser + CAPTCHA solving. Automatic
|
|
|
115
115
|
🧠 **Self-Improving**
|
|
116
116
|
Adaptive learning engine remembers what works per domain. Second visit is 3x faster. The more you use it, the smarter it gets.
|
|
117
117
|
|
|
118
|
-
🧰 **
|
|
118
|
+
🧰 **29 Tools, 2 Modes**
|
|
119
119
|
CLI tool or interactive TUI. Scraping, crawling, search, extraction, API discovery, WebSocket monitoring, browser automation, batch processing.
|
|
120
120
|
|
|
121
121
|
📜 **14 Built-in Recipes**
|
|
@@ -131,7 +131,7 @@ Teach it once, run forever. Auto-detect patterns on any page, save as reusable s
|
|
|
131
131
|
| Feature | **imperium-crawl** | Firecrawl | Crawl4AI | Browserbase | Puppeteer |
|
|
132
132
|
|---------|:------------------:|:---------:|:--------:|:-----------:|:---------:|
|
|
133
133
|
| Price | **Free forever** | $19+/month | Free | $0.01/min | Free |
|
|
134
|
-
| Total tools | **
|
|
134
|
+
| Total tools | **29** | 5 | 2 | 4 | N/A |
|
|
135
135
|
| Stealth levels | **3 (auto-escalate)** | Cloud-based | 1 | Cloud-based | None |
|
|
136
136
|
| Anti-bot detection | **7 systems** | Partial | Partial | Partial | None |
|
|
137
137
|
| TLS fingerprinting | **JA3/JA4** | No | No | No | No |
|
|
@@ -224,7 +224,7 @@ Second visit to cloudflare.com:
|
|
|
224
224
|
|
|
225
225
|
---
|
|
226
226
|
|
|
227
|
-
## All
|
|
227
|
+
## All 29 Tools
|
|
228
228
|
|
|
229
229
|
### 📄 Scraping (no API key needed)
|
|
230
230
|
|
|
@@ -272,7 +272,7 @@ Second visit to cloudflare.com:
|
|
|
272
272
|
|
|
273
273
|
| Tool | What It Does |
|
|
274
274
|
|------|-------------|
|
|
275
|
-
| **interact** | Browser automation with
|
|
275
|
+
| **interact** | Browser automation with 19 action types (click, type, scroll, wait, screenshot, evaluate, select, hover, press, navigate, drag, upload, storage, cookies, pdf, auth_login, refresh). Ref targeting via ARIA snapshot, session encryption, action policy, domain filter, network interception, device emulation. |
|
|
276
276
|
| **snapshot** | ARIA-based page snapshot with interactive element refs. Use refs in interact for precise targeting. Annotated screenshots. |
|
|
277
277
|
|
|
278
278
|
### 📱 Social Media (no API key needed)
|
|
@@ -299,6 +299,12 @@ Second visit to cloudflare.com:
|
|
|
299
299
|
| **job_status** | Full results for a specific batch job including per-URL outcomes. |
|
|
300
300
|
| **delete_job** | Clean up completed or failed batch jobs. |
|
|
301
301
|
|
|
302
|
+
### 🧠 Knowledge Engine (no API key needed)
|
|
303
|
+
|
|
304
|
+
| Tool | What It Does |
|
|
305
|
+
|------|-------------|
|
|
306
|
+
| **knowledge** | Dump adaptive knowledge engine stats — per-domain success rates, optimal stealth levels, anti-bot detection history, rate limits. Use to debug scraping issues and understand problematic domains. |
|
|
307
|
+
|
|
302
308
|
---
|
|
303
309
|
|
|
304
310
|
## Setup
|
|
@@ -366,6 +372,26 @@ imperium-crawl tui
|
|
|
366
372
|
|
|
367
373
|
Interactive slash-command terminal with parameter prompts, table rendering, markdown display, and session state. Use `/save` to export results and `/again` to re-run the last command.
|
|
368
374
|
|
|
375
|
+
### Explore REPL
|
|
376
|
+
|
|
377
|
+
Interactively explore a site in a headed browser, then save the session as a reusable skill:
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
imperium-crawl explore https://example.com
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
```
|
|
384
|
+
> navigate https://example.com/login
|
|
385
|
+
> type "#email" "user@example.com"
|
|
386
|
+
> type "#password" "{{env:MY_PASSWORD}}"
|
|
387
|
+
> click "#submit"
|
|
388
|
+
> snapshot
|
|
389
|
+
> save-skill my-login
|
|
390
|
+
✅ Saved skill: my-login (4 actions, 1 parameter detected)
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Commands: `navigate`, `click`, `type`, `select`, `hover`, `press`, `scroll`, `wait`, `screenshot`, `snapshot`, `evaluate`, `save-skill`, `history`, `undo`, `status`, `help`, `exit`
|
|
394
|
+
|
|
369
395
|
---
|
|
370
396
|
|
|
371
397
|
## Skills & Recipes
|
|
@@ -389,6 +415,37 @@ run_skill({ name: "tc-ai-news" })
|
|
|
389
415
|
|
|
390
416
|
Skills are saved in `~/.imperium-crawl/skills/` as JSON files — human-readable, editable, portable.
|
|
391
417
|
|
|
418
|
+
### Skill Parameters
|
|
419
|
+
|
|
420
|
+
Use template variables in skills — resolved at run time:
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
# In skill JSON actions:
|
|
424
|
+
{ "value": "{{input:query}}" } # passed via --params or prompted
|
|
425
|
+
{ "value": "{{env:SITE_PASSWORD}}" } # from environment variable
|
|
426
|
+
{ "value": "{{computed:date_today}}" } # auto-computed (date_today, timestamp, random_string, year, month, day)
|
|
427
|
+
|
|
428
|
+
# Run with params:
|
|
429
|
+
imperium-crawl run-skill my-search --params '{"query": "machine learning"}'
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Skill Chains
|
|
433
|
+
|
|
434
|
+
Chain skills together — output of one step becomes input to the next:
|
|
435
|
+
|
|
436
|
+
```json
|
|
437
|
+
{
|
|
438
|
+
"type": "chain",
|
|
439
|
+
"name": "search-and-extract",
|
|
440
|
+
"steps": [
|
|
441
|
+
{ "skill": "search-results", "output": "search" },
|
|
442
|
+
{ "skill": "extract-details", "input": { "url": "$search.results[0].url" }, "output": "details" }
|
|
443
|
+
]
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
Variable syntax: `$step_name.field.nested[0]` — simple dot-path access, no eval.
|
|
448
|
+
|
|
392
449
|
### Built-in Recipes
|
|
393
450
|
|
|
394
451
|
| Recipe | What It Does |
|
|
@@ -435,7 +492,7 @@ Turn any website into an API. No documentation needed.
|
|
|
435
492
|
|
|
436
493
|
## AI Agent Guide
|
|
437
494
|
|
|
438
|
-
imperium-crawl ships with [`SKILL/`](./SKILL/) — a structured guide that teaches AI agents how to use all
|
|
495
|
+
imperium-crawl ships with [`SKILL/`](./SKILL/) — a structured guide that teaches AI agents how to use all 29 tools effectively. Includes proven workflows, decision trees, error recovery, and advanced patterns.
|
|
439
496
|
|
|
440
497
|
### Two Ways to Connect
|
|
441
498
|
|
|
@@ -496,13 +553,14 @@ Every tool tested against production websites with real anti-bot defenses:
|
|
|
496
553
|
| 📋 **list_jobs** | — | Batch jobs with status and progress |
|
|
497
554
|
| 📊 **job_status** | Batch job | Full per-URL results with timing |
|
|
498
555
|
| 🗑️ **delete_job** | Completed job | Cleaned up job data from disk |
|
|
556
|
+
| 🧠 **knowledge** | Local knowledge file | Per-domain stats: stealth levels, success rates, anti-bot systems detected |
|
|
499
557
|
| 🎬 **youtube** | "web scraping tutorial" | Search results, video details, comments, transcripts — no API key |
|
|
500
558
|
| 💬 **reddit** | r/webscraping | Subreddit posts, comments, search — public JSON API |
|
|
501
559
|
| 📸 **instagram** | @nike profile | Profile details, engagement rate, recent posts — internal API |
|
|
502
560
|
| 📥 **download** | YouTube video, web page images | Auto-detect URL type, download media files — images, video, og:image |
|
|
503
561
|
| 📡 **rss** | Hacker News RSS | Parsed feed items with title, link, date, author, categories |
|
|
504
562
|
|
|
505
|
-
> **
|
|
563
|
+
> **29/29 tools. 34 hidden APIs on Airbnb. Live BTC feed. Zero API keys for scraping.**
|
|
506
564
|
|
|
507
565
|
---
|
|
508
566
|
|
|
@@ -535,7 +593,7 @@ cd imperium-crawl
|
|
|
535
593
|
npm install
|
|
536
594
|
npm run build
|
|
537
595
|
npm run dev # Watch mode (rebuild on changes)
|
|
538
|
-
npm test #
|
|
596
|
+
npm test # 546 tests
|
|
539
597
|
npm start # Start CLI (shows help or TUI)
|
|
540
598
|
```
|
|
541
599
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explore REPL — interactive browser session with live Playwright.
|
|
3
|
+
*
|
|
4
|
+
* Usage: imperium-crawl explore <url>
|
|
5
|
+
*
|
|
6
|
+
* Opens a headed (visible) browser window and gives the user a readline REPL
|
|
7
|
+
* to execute actions interactively. Every successful action is recorded.
|
|
8
|
+
* At any point, run `save-skill <name>` to export the session as a reusable skill.
|
|
9
|
+
*
|
|
10
|
+
* Commands:
|
|
11
|
+
* navigate <url> Navigate to URL
|
|
12
|
+
* click <selector> Click element
|
|
13
|
+
* type <selector> <text> Fill input field
|
|
14
|
+
* select <selector> <value> Select option
|
|
15
|
+
* wait [ms] Wait N ms (default 1000)
|
|
16
|
+
* screenshot [file] Save screenshot
|
|
17
|
+
* snapshot Show ARIA tree + refs
|
|
18
|
+
* evaluate <script> Run JS in page
|
|
19
|
+
* scroll [up|down] [px] Scroll page
|
|
20
|
+
* hover <selector> Hover element
|
|
21
|
+
* press <key> Press keyboard key
|
|
22
|
+
* save-skill <name> Export recording as skill JSON
|
|
23
|
+
* status Show URL, action count
|
|
24
|
+
* history List recorded actions
|
|
25
|
+
* undo Remove last action
|
|
26
|
+
* help Show command list
|
|
27
|
+
* exit / quit Close browser and exit
|
|
28
|
+
*/
|
|
29
|
+
export declare function runExplore(startUrl: string, sessionId?: string): Promise<void>;
|
|
30
|
+
//# sourceMappingURL=cli-explore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-explore.d.ts","sourceRoot":"","sources":["../src/cli-explore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAgGH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6RpF"}
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explore REPL — interactive browser session with live Playwright.
|
|
3
|
+
*
|
|
4
|
+
* Usage: imperium-crawl explore <url>
|
|
5
|
+
*
|
|
6
|
+
* Opens a headed (visible) browser window and gives the user a readline REPL
|
|
7
|
+
* to execute actions interactively. Every successful action is recorded.
|
|
8
|
+
* At any point, run `save-skill <name>` to export the session as a reusable skill.
|
|
9
|
+
*
|
|
10
|
+
* Commands:
|
|
11
|
+
* navigate <url> Navigate to URL
|
|
12
|
+
* click <selector> Click element
|
|
13
|
+
* type <selector> <text> Fill input field
|
|
14
|
+
* select <selector> <value> Select option
|
|
15
|
+
* wait [ms] Wait N ms (default 1000)
|
|
16
|
+
* screenshot [file] Save screenshot
|
|
17
|
+
* snapshot Show ARIA tree + refs
|
|
18
|
+
* evaluate <script> Run JS in page
|
|
19
|
+
* scroll [up|down] [px] Scroll page
|
|
20
|
+
* hover <selector> Hover element
|
|
21
|
+
* press <key> Press keyboard key
|
|
22
|
+
* save-skill <name> Export recording as skill JSON
|
|
23
|
+
* status Show URL, action count
|
|
24
|
+
* history List recorded actions
|
|
25
|
+
* undo Remove last action
|
|
26
|
+
* help Show command list
|
|
27
|
+
* exit / quit Close browser and exit
|
|
28
|
+
*/
|
|
29
|
+
import readline from "node:readline";
|
|
30
|
+
import fs from "node:fs/promises";
|
|
31
|
+
import { ActionRecorder } from "./cli-recorder.js";
|
|
32
|
+
import { executeAction } from "./tools/action-executor.js";
|
|
33
|
+
import { getSessionManager } from "./sessions/index.js";
|
|
34
|
+
import { save as saveSkill } from "./skills/manager.js";
|
|
35
|
+
import { getEnhancedSnapshot } from "./snapshot/index.js";
|
|
36
|
+
import { getSnapshotStore } from "./snapshot/index.js";
|
|
37
|
+
import { normalizeUrl } from "./utils/url.js";
|
|
38
|
+
const EXPLORE_TIMEOUT = 30_000;
|
|
39
|
+
// ── ANSI helpers ──
|
|
40
|
+
const C = {
|
|
41
|
+
reset: "\x1b[0m",
|
|
42
|
+
bold: "\x1b[1m",
|
|
43
|
+
dim: "\x1b[2m",
|
|
44
|
+
green: "\x1b[32m",
|
|
45
|
+
red: "\x1b[31m",
|
|
46
|
+
yellow: "\x1b[33m",
|
|
47
|
+
cyan: "\x1b[36m",
|
|
48
|
+
blue: "\x1b[34m",
|
|
49
|
+
magenta: "\x1b[35m",
|
|
50
|
+
};
|
|
51
|
+
function ok(msg) { process.stdout.write(`${C.green}✓${C.reset} ${msg}\n`); }
|
|
52
|
+
function err(msg) { process.stdout.write(`${C.red}✗${C.reset} ${msg}\n`); }
|
|
53
|
+
function info(msg) { process.stdout.write(`${C.cyan}›${C.reset} ${msg}\n`); }
|
|
54
|
+
function dim(msg) { process.stdout.write(`${C.dim}${msg}${C.reset}\n`); }
|
|
55
|
+
// ── Help text ──
|
|
56
|
+
const HELP_TEXT = `
|
|
57
|
+
${C.bold}Explore REPL Commands${C.reset}
|
|
58
|
+
${C.dim}────────────────────────────────────────────────────${C.reset}
|
|
59
|
+
${C.cyan}navigate${C.reset} <url> Navigate to a URL
|
|
60
|
+
${C.cyan}click${C.reset} <selector> Click element (CSS selector or @ref)
|
|
61
|
+
${C.cyan}type${C.reset} <selector> <text> Fill input field
|
|
62
|
+
${C.cyan}select${C.reset} <selector> <value> Select dropdown option
|
|
63
|
+
${C.cyan}hover${C.reset} <selector> Hover over element
|
|
64
|
+
${C.cyan}press${C.reset} <key> Press keyboard key (Enter, Tab, Escape…)
|
|
65
|
+
${C.cyan}scroll${C.reset} [up|down] [px] Scroll page (default: down 500px)
|
|
66
|
+
${C.cyan}wait${C.reset} [ms] Wait N milliseconds (default: 1000)
|
|
67
|
+
${C.cyan}evaluate${C.reset} <js> Run JavaScript in page context
|
|
68
|
+
${C.cyan}screenshot${C.reset} [filename.png] Take screenshot
|
|
69
|
+
${C.cyan}snapshot${C.reset} Show ARIA tree with element refs
|
|
70
|
+
${C.dim}────────────────────────────────────────────────────${C.reset}
|
|
71
|
+
${C.yellow}save-skill${C.reset} <name> Export session as reusable skill
|
|
72
|
+
${C.yellow}history${C.reset} List recorded actions
|
|
73
|
+
${C.yellow}undo${C.reset} Remove last action from recording
|
|
74
|
+
${C.yellow}status${C.reset} Show current URL and action count
|
|
75
|
+
${C.yellow}help${C.reset} Show this help
|
|
76
|
+
${C.yellow}exit${C.reset} / ${C.yellow}quit${C.reset} Close browser and exit
|
|
77
|
+
${C.dim}────────────────────────────────────────────────────${C.reset}
|
|
78
|
+
`;
|
|
79
|
+
// ── Tokenizer ──
|
|
80
|
+
/** Split command line respecting quoted strings */
|
|
81
|
+
function tokenize(line) {
|
|
82
|
+
const tokens = [];
|
|
83
|
+
let current = "";
|
|
84
|
+
let inQuote = false;
|
|
85
|
+
let quoteChar = "";
|
|
86
|
+
for (let i = 0; i < line.length; i++) {
|
|
87
|
+
const ch = line[i];
|
|
88
|
+
if (inQuote) {
|
|
89
|
+
if (ch === quoteChar) {
|
|
90
|
+
inQuote = false;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
current += ch;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if (ch === '"' || ch === "'") {
|
|
97
|
+
inQuote = true;
|
|
98
|
+
quoteChar = ch;
|
|
99
|
+
}
|
|
100
|
+
else if (ch === " " || ch === "\t") {
|
|
101
|
+
if (current) {
|
|
102
|
+
tokens.push(current);
|
|
103
|
+
current = "";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
current += ch;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (current)
|
|
111
|
+
tokens.push(current);
|
|
112
|
+
return tokens;
|
|
113
|
+
}
|
|
114
|
+
// ── Session ID for snapshot refs ──
|
|
115
|
+
const EXPLORE_SESSION_ID = `explore-${Date.now()}`;
|
|
116
|
+
// ── Main REPL ──
|
|
117
|
+
export async function runExplore(startUrl, sessionId) {
|
|
118
|
+
const { isPlaywrightAvailable } = await import("./stealth/browser.js");
|
|
119
|
+
if (!(await isPlaywrightAvailable())) {
|
|
120
|
+
err("rebrowser-playwright is required for explore mode.");
|
|
121
|
+
err("Install with: npm i rebrowser-playwright");
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
const url = normalizeUrl(startUrl);
|
|
125
|
+
info(`Opening browser → ${C.cyan}${url}${C.reset}`);
|
|
126
|
+
info("Type ${C.bold}help${C.reset} for available commands\n");
|
|
127
|
+
// Launch headed browser
|
|
128
|
+
const { chromium } = await import("rebrowser-playwright");
|
|
129
|
+
const { STEALTH_ARGS } = await import("./constants.js");
|
|
130
|
+
const { timeZone, locale } = Intl.DateTimeFormat().resolvedOptions();
|
|
131
|
+
const browser = await chromium.launch({
|
|
132
|
+
headless: false,
|
|
133
|
+
args: STEALTH_ARGS,
|
|
134
|
+
});
|
|
135
|
+
const context = await browser.newContext({ timezoneId: timeZone, locale });
|
|
136
|
+
// Restore session cookies if session_id given
|
|
137
|
+
if (sessionId) {
|
|
138
|
+
const session = await getSessionManager().load(sessionId);
|
|
139
|
+
if (session?.cookies.length) {
|
|
140
|
+
await context.addCookies(session.cookies);
|
|
141
|
+
info(`Restored session: ${C.yellow}${sessionId}${C.reset}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const page = await context.newPage();
|
|
145
|
+
// Navigate to starting URL
|
|
146
|
+
try {
|
|
147
|
+
await page.goto(url, { waitUntil: "load", timeout: EXPLORE_TIMEOUT });
|
|
148
|
+
ok(`Navigated to ${page.url()}`);
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
err(`Navigation failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
152
|
+
}
|
|
153
|
+
const recorder = new ActionRecorder(url);
|
|
154
|
+
const screenshots = [];
|
|
155
|
+
// ── Readline REPL ──
|
|
156
|
+
const rl = readline.createInterface({
|
|
157
|
+
input: process.stdin,
|
|
158
|
+
output: process.stdout,
|
|
159
|
+
prompt: `${C.magenta}explore${C.reset}${C.dim}›${C.reset} `,
|
|
160
|
+
terminal: true,
|
|
161
|
+
});
|
|
162
|
+
rl.prompt();
|
|
163
|
+
const cleanup = async () => {
|
|
164
|
+
// Save session cookies if session_id given
|
|
165
|
+
if (sessionId) {
|
|
166
|
+
try {
|
|
167
|
+
const cookies = await context.cookies();
|
|
168
|
+
const stored = cookies.map((c) => ({
|
|
169
|
+
name: c.name, value: c.value, domain: c.domain, path: c.path,
|
|
170
|
+
expires: c.expires, httpOnly: c.httpOnly, secure: c.secure,
|
|
171
|
+
sameSite: c.sameSite,
|
|
172
|
+
}));
|
|
173
|
+
await getSessionManager().save(sessionId, stored, page.url());
|
|
174
|
+
ok(`Session saved: ${sessionId}`);
|
|
175
|
+
}
|
|
176
|
+
catch { /* non-critical */ }
|
|
177
|
+
}
|
|
178
|
+
await browser.close().catch(() => { });
|
|
179
|
+
rl.close();
|
|
180
|
+
};
|
|
181
|
+
process.on("SIGINT", async () => { await cleanup(); process.exit(0); });
|
|
182
|
+
rl.on("line", async (rawLine) => {
|
|
183
|
+
rl.pause();
|
|
184
|
+
const line = rawLine.trim();
|
|
185
|
+
if (!line) {
|
|
186
|
+
rl.resume();
|
|
187
|
+
rl.prompt();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const tokens = tokenize(line);
|
|
191
|
+
const cmd = tokens[0]?.toLowerCase() ?? "";
|
|
192
|
+
const args = tokens.slice(1);
|
|
193
|
+
try {
|
|
194
|
+
switch (cmd) {
|
|
195
|
+
case "navigate": {
|
|
196
|
+
if (!args[0]) {
|
|
197
|
+
err("Usage: navigate <url>");
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
const navUrl = args[0].startsWith("http") ? args[0] : `https://${args[0]}`;
|
|
201
|
+
await page.goto(navUrl, { waitUntil: "load", timeout: EXPLORE_TIMEOUT });
|
|
202
|
+
ok(`Navigated to ${page.url()}`);
|
|
203
|
+
recorder.record({ type: "navigate", url: navUrl }, line, page.url());
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
case "click": {
|
|
207
|
+
if (!args[0]) {
|
|
208
|
+
err("Usage: click <selector>");
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
const action = { type: "click", selector: args[0] };
|
|
212
|
+
const result = await executeAction(page, action, screenshots, EXPLORE_TIMEOUT, EXPLORE_SESSION_ID);
|
|
213
|
+
if (result.success) {
|
|
214
|
+
ok(`Clicked: ${args[0]}`);
|
|
215
|
+
recorder.record(action, line, page.url());
|
|
216
|
+
}
|
|
217
|
+
else
|
|
218
|
+
err(result.error ?? "Click failed");
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
case "type": {
|
|
222
|
+
if (!args[0] || !args[1]) {
|
|
223
|
+
err("Usage: type <selector> <text>");
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
const text = args.slice(1).join(" ");
|
|
227
|
+
const action = { type: "type", selector: args[0], text };
|
|
228
|
+
const result = await executeAction(page, action, screenshots, EXPLORE_TIMEOUT, EXPLORE_SESSION_ID);
|
|
229
|
+
if (result.success) {
|
|
230
|
+
ok(`Typed into: ${args[0]}`);
|
|
231
|
+
recorder.record(action, line, page.url());
|
|
232
|
+
}
|
|
233
|
+
else
|
|
234
|
+
err(result.error ?? "Type failed");
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case "select": {
|
|
238
|
+
if (!args[0] || !args[1]) {
|
|
239
|
+
err("Usage: select <selector> <value>");
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
const action = { type: "select", selector: args[0], value: args[1] };
|
|
243
|
+
const result = await executeAction(page, action, screenshots, EXPLORE_TIMEOUT, EXPLORE_SESSION_ID);
|
|
244
|
+
if (result.success) {
|
|
245
|
+
ok(`Selected: ${args[1]} in ${args[0]}`);
|
|
246
|
+
recorder.record(action, line, page.url());
|
|
247
|
+
}
|
|
248
|
+
else
|
|
249
|
+
err(result.error ?? "Select failed");
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
case "hover": {
|
|
253
|
+
if (!args[0]) {
|
|
254
|
+
err("Usage: hover <selector>");
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
const action = { type: "hover", selector: args[0] };
|
|
258
|
+
const result = await executeAction(page, action, screenshots, EXPLORE_TIMEOUT, EXPLORE_SESSION_ID);
|
|
259
|
+
if (result.success) {
|
|
260
|
+
ok(`Hovered: ${args[0]}`);
|
|
261
|
+
recorder.record(action, line, page.url());
|
|
262
|
+
}
|
|
263
|
+
else
|
|
264
|
+
err(result.error ?? "Hover failed");
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case "press": {
|
|
268
|
+
if (!args[0]) {
|
|
269
|
+
err("Usage: press <key> (e.g. Enter, Tab, Escape)");
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
const action = { type: "press", key: args[0] };
|
|
273
|
+
const result = await executeAction(page, action, screenshots, EXPLORE_TIMEOUT, EXPLORE_SESSION_ID);
|
|
274
|
+
if (result.success) {
|
|
275
|
+
ok(`Pressed: ${args[0]}`);
|
|
276
|
+
recorder.record(action, line, page.url());
|
|
277
|
+
}
|
|
278
|
+
else
|
|
279
|
+
err(result.error ?? "Press failed");
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
case "scroll": {
|
|
283
|
+
const direction = args[0]?.toLowerCase() ?? "down";
|
|
284
|
+
const px = parseInt(args[1] ?? "500", 10);
|
|
285
|
+
const y = direction === "up" ? -px : px;
|
|
286
|
+
const action = { type: "scroll", y };
|
|
287
|
+
const result = await executeAction(page, action, screenshots, EXPLORE_TIMEOUT, EXPLORE_SESSION_ID);
|
|
288
|
+
if (result.success) {
|
|
289
|
+
ok(`Scrolled ${direction} ${Math.abs(y)}px`);
|
|
290
|
+
recorder.record(action, line, page.url());
|
|
291
|
+
}
|
|
292
|
+
else
|
|
293
|
+
err(result.error ?? "Scroll failed");
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
case "wait": {
|
|
297
|
+
const ms = parseInt(args[0] ?? "1000", 10);
|
|
298
|
+
const action = { type: "wait", duration: ms };
|
|
299
|
+
await executeAction(page, action, screenshots, EXPLORE_TIMEOUT + ms, EXPLORE_SESSION_ID);
|
|
300
|
+
ok(`Waited ${ms}ms`);
|
|
301
|
+
recorder.record(action, line, page.url());
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case "screenshot": {
|
|
305
|
+
const filename = args[0] ?? `screenshot-${Date.now()}.png`;
|
|
306
|
+
const buf = await page.screenshot({ fullPage: false });
|
|
307
|
+
await fs.writeFile(filename, buf);
|
|
308
|
+
ok(`Screenshot saved: ${filename}`);
|
|
309
|
+
recorder.record({ type: "screenshot" }, line, page.url());
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
case "snapshot": {
|
|
313
|
+
info("Taking ARIA snapshot...");
|
|
314
|
+
try {
|
|
315
|
+
const snapshot = await getEnhancedSnapshot(page, { interactive: true, compact: true });
|
|
316
|
+
getSnapshotStore().save(EXPLORE_SESSION_ID, snapshot.refs, page.url());
|
|
317
|
+
process.stdout.write("\n" + snapshot.tree + "\n\n");
|
|
318
|
+
info(`${C.dim}${Object.keys(snapshot.refs).length} refs available. Use @ref in commands.${C.reset}`);
|
|
319
|
+
}
|
|
320
|
+
catch (e) {
|
|
321
|
+
err(`Snapshot failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
322
|
+
}
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
case "evaluate": {
|
|
326
|
+
if (!args[0]) {
|
|
327
|
+
err("Usage: evaluate <script>");
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
const script = args.join(" ");
|
|
331
|
+
const action = { type: "evaluate", script };
|
|
332
|
+
const result = await executeAction(page, action, screenshots, EXPLORE_TIMEOUT, EXPLORE_SESSION_ID);
|
|
333
|
+
if (result.success) {
|
|
334
|
+
ok("Evaluated:");
|
|
335
|
+
process.stdout.write(JSON.stringify(result.result, null, 2) + "\n");
|
|
336
|
+
recorder.record(action, line, page.url());
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
err(result.error ?? "Evaluate failed");
|
|
340
|
+
}
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
case "save-skill": {
|
|
344
|
+
if (!args[0]) {
|
|
345
|
+
err("Usage: save-skill <name>");
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
const skillName = args[0];
|
|
349
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(skillName)) {
|
|
350
|
+
err("Skill name may only contain letters, numbers, hyphens, and underscores");
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
if (recorder.count === 0) {
|
|
354
|
+
err("No actions recorded yet. Perform some actions first.");
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
// Auto-detect parameters
|
|
358
|
+
const detectedParams = recorder.detectParameters();
|
|
359
|
+
const paramCount = Object.keys(detectedParams).length;
|
|
360
|
+
const description = `Recorded skill from ${new URL(url).hostname} — ${recorder.count} actions`;
|
|
361
|
+
const config = recorder.toSkillConfig(skillName, description, sessionId, detectedParams);
|
|
362
|
+
await saveSkill(skillName, config);
|
|
363
|
+
ok(`Saved skill: ${C.yellow}${skillName}${C.reset} (${recorder.count} actions${paramCount > 0 ? `, ${paramCount} params detected` : ""})`);
|
|
364
|
+
info(`Run with: ${C.cyan}imperium-crawl run-skill ${skillName}${C.reset}`);
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
case "history": {
|
|
368
|
+
const h = recorder.getHistory();
|
|
369
|
+
if (h.length === 0) {
|
|
370
|
+
info("No actions recorded yet.");
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
process.stdout.write(`\n${C.bold}Recorded actions (${h.length}):${C.reset}\n`);
|
|
374
|
+
h.forEach((r, i) => {
|
|
375
|
+
dim(` ${String(i + 1).padStart(2)}. ${r.rawCommand}`);
|
|
376
|
+
});
|
|
377
|
+
process.stdout.write("\n");
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
case "undo": {
|
|
381
|
+
const undone = recorder.undo();
|
|
382
|
+
if (undone) {
|
|
383
|
+
ok(`Removed: ${undone.rawCommand}`);
|
|
384
|
+
info(`${recorder.count} actions remaining`);
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
info("Nothing to undo");
|
|
388
|
+
}
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
case "status": {
|
|
392
|
+
process.stdout.write(`\n`);
|
|
393
|
+
info(`URL: ${C.cyan}${page.url()}${C.reset}`);
|
|
394
|
+
info(`Actions: ${C.yellow}${recorder.count}${C.reset} recorded`);
|
|
395
|
+
if (sessionId)
|
|
396
|
+
info(`Session: ${C.yellow}${sessionId}${C.reset}`);
|
|
397
|
+
process.stdout.write(`\n`);
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
case "help": {
|
|
401
|
+
process.stdout.write(HELP_TEXT);
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
case "exit":
|
|
405
|
+
case "quit": {
|
|
406
|
+
info("Closing browser...");
|
|
407
|
+
await cleanup();
|
|
408
|
+
process.exit(0);
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
default: {
|
|
412
|
+
err(`Unknown command: ${cmd}. Type ${C.bold}help${C.reset} for available commands.`);
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch (e) {
|
|
418
|
+
err(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
419
|
+
}
|
|
420
|
+
rl.resume();
|
|
421
|
+
rl.prompt();
|
|
422
|
+
});
|
|
423
|
+
rl.on("close", async () => {
|
|
424
|
+
await cleanup();
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
//# sourceMappingURL=cli-explore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-explore.js","sourceRoot":"","sources":["../src/cli-explore.ts"],"names":[],"mappings":"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"}
|