bb-browser 0.4.4 → 0.5.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 +116 -102
- package/README.zh-CN.md +114 -100
- package/dist/chunk-AHGAQEFO.js +110 -0
- package/dist/chunk-AHGAQEFO.js.map +1 -0
- package/dist/{chunk-H7M4J4CW.js → chunk-D4HDZEJT.js} +2 -18
- package/dist/chunk-D4HDZEJT.js.map +1 -0
- package/dist/chunk-DBJBHYC7.js +21 -0
- package/dist/chunk-DBJBHYC7.js.map +1 -0
- package/dist/cli.js +1751 -1499
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +2 -1
- package/dist/daemon.js.map +1 -1
- package/dist/jq-HHMLHEPA.js +9 -0
- package/dist/jq-HHMLHEPA.js.map +1 -0
- package/dist/mcp.js +5 -3
- package/dist/mcp.js.map +1 -1
- package/extension/background.js +80 -0
- package/extension/background.js.map +1 -1
- package/extension/dist/background.js +80 -0
- package/extension/dist/background.js.map +1 -1
- package/extension/dist/manifest.json +2 -2
- package/extension/manifest.json +2 -2
- package/package.json +1 -1
- package/dist/chunk-H7M4J4CW.js.map +0 -1
package/README.md
CHANGED
|
@@ -16,154 +16,168 @@
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
You're already logged into
|
|
19
|
+
You're already logged into Twitter, Reddit, YouTube, Zhihu, Bilibili, LinkedIn, GitHub — bb-browser lets AI agents **use that directly**.
|
|
20
20
|
|
|
21
|
+
```bash
|
|
22
|
+
bb-browser site twitter/search "AI agent" # search tweets
|
|
23
|
+
bb-browser site zhihu/hot # trending on Zhihu
|
|
24
|
+
bb-browser site arxiv/search "transformer" # search papers
|
|
25
|
+
bb-browser site eastmoney/stock "茅台" # real-time stock quote
|
|
26
|
+
bb-browser site boss/search "AI engineer" # search jobs
|
|
27
|
+
bb-browser site wikipedia/summary "Python" # Wikipedia summary
|
|
28
|
+
bb-browser site youtube/transcript VIDEO_ID # full transcript
|
|
29
|
+
bb-browser site stackoverflow/search "async" # search SO questions
|
|
21
30
|
```
|
|
22
|
-
AI Agent (Claude Code, Codex, etc.)
|
|
23
|
-
│ CLI commands
|
|
24
|
-
▼
|
|
25
|
-
bb-browser CLI ──HTTP──▶ Daemon ──SSE──▶ Chrome Extension
|
|
26
|
-
│
|
|
27
|
-
▼ chrome.debugger (CDP)
|
|
28
|
-
Your Real Browser
|
|
29
|
-
(logged-in sites, cookies, sessions)
|
|
30
|
-
```
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
**103 commands across 36 platforms.** All using your real browser's login state. [Full list →](https://github.com/epiral/bb-sites)
|
|
33
|
+
|
|
34
|
+
## The idea
|
|
35
|
+
|
|
36
|
+
The internet was built for browsers. AI agents have been trying to access it through APIs — but 99% of websites don't offer one.
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
bb-browser flips this: **instead of forcing websites to provide machine interfaces, let machines use the human interface directly.** The adapter runs `eval` inside your browser tab, calls `fetch()` with your cookies, or invokes the page's own webpack modules. The website thinks it's you. Because it **is** you.
|
|
35
39
|
|
|
36
40
|
| | Playwright / Selenium | Scraping libs | bb-browser |
|
|
37
41
|
|---|---|---|---|
|
|
38
42
|
| Browser | Headless, isolated | No browser | Your real Chrome |
|
|
39
43
|
| Login state | None, must re-login | Cookie extraction | Already there |
|
|
40
|
-
| Anti-bot | Detected easily | Cat-and-mouse
|
|
41
|
-
|
|
|
44
|
+
| Anti-bot | Detected easily | Cat-and-mouse | Invisible — it IS the user |
|
|
45
|
+
| Complex auth | Can't replicate | Reverse engineer | Page handles it itself |
|
|
42
46
|
|
|
43
|
-
##
|
|
47
|
+
## Quick Start
|
|
44
48
|
|
|
45
|
-
###
|
|
49
|
+
### Install
|
|
46
50
|
|
|
47
51
|
```bash
|
|
48
|
-
bb-browser
|
|
49
|
-
bb-browser snapshot -i # interactive elements only
|
|
50
|
-
bb-browser click @0 # click by ref
|
|
51
|
-
bb-browser fill @2 "hello" # fill input
|
|
52
|
-
bb-browser press Enter
|
|
53
|
-
bb-browser screenshot
|
|
52
|
+
npm install -g bb-browser
|
|
54
53
|
```
|
|
55
54
|
|
|
56
|
-
###
|
|
55
|
+
### Chrome Extension
|
|
56
|
+
|
|
57
|
+
1. Download from [Releases](https://github.com/epiral/bb-browser/releases/latest)
|
|
58
|
+
2. Unzip → `chrome://extensions/` → Developer Mode → Load unpacked
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
### Use
|
|
59
61
|
|
|
60
62
|
```bash
|
|
61
|
-
|
|
62
|
-
bb-browser
|
|
63
|
+
bb-browser site update # pull community adapters
|
|
64
|
+
bb-browser site recommend # see which adapters match your browsing habits
|
|
65
|
+
bb-browser site zhihu/hot # go
|
|
66
|
+
```
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
### MCP (Claude Code / Cursor)
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"bb-browser": {
|
|
74
|
+
"command": "npx",
|
|
75
|
+
"args": ["-y", "bb-browser", "--mcp"]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
66
79
|
```
|
|
67
80
|
|
|
68
|
-
|
|
81
|
+
## 36 platforms, 103 commands
|
|
82
|
+
|
|
83
|
+
Community-driven via [bb-sites](https://github.com/epiral/bb-sites). One JS file per command.
|
|
69
84
|
|
|
70
|
-
|
|
85
|
+
| Category | Platforms | Commands |
|
|
86
|
+
|----------|-----------|----------|
|
|
87
|
+
| **Search** | Google, Baidu, Bing, DuckDuckGo, Sogou WeChat | search |
|
|
88
|
+
| **Social** | Twitter/X, Reddit, Weibo, Xiaohongshu, Jike, LinkedIn, Hupu | search, feed, thread, user, notifications, hot |
|
|
89
|
+
| **News** | BBC, Reuters, 36kr, Toutiao, Eastmoney | headlines, search, newsflash, hot |
|
|
90
|
+
| **Dev** | GitHub, StackOverflow, HackerNews, CSDN, cnblogs, V2EX, Dev.to, npm, PyPI, arXiv | search, issues, repo, top, thread, package |
|
|
91
|
+
| **Video** | YouTube, Bilibili | search, video, transcript, popular, comments, feed |
|
|
92
|
+
| **Entertainment** | Douban, IMDb, Genius, Qidian | movie, search, top250 |
|
|
93
|
+
| **Finance** | Xueqiu, Eastmoney, Yahoo Finance | stock, hot stocks, feed, watchlist, search |
|
|
94
|
+
| **Jobs** | BOSS Zhipin, LinkedIn | search, detail, profile |
|
|
95
|
+
| **Knowledge** | Wikipedia, Zhihu, Open Library | search, summary, hot, question |
|
|
96
|
+
| **Shopping** | SMZDM | search deals |
|
|
97
|
+
| **Tools** | Youdao, GSMArena, Product Hunt, Ctrip | translate, phone specs, trending products |
|
|
98
|
+
|
|
99
|
+
## 10 minutes to add any website
|
|
71
100
|
|
|
72
101
|
```bash
|
|
73
|
-
bb-browser
|
|
74
|
-
# → Full request headers (including auth/signing), full response body
|
|
75
|
-
# → See exactly how a website's API works — then build an adapter for it
|
|
102
|
+
bb-browser guide # full tutorial
|
|
76
103
|
```
|
|
77
104
|
|
|
78
|
-
|
|
105
|
+
Tell your AI agent: *"turn XX website into a CLI"*. It reads the guide, reverse-engineers the API with `network --with-body`, writes the adapter, tests it, and submits a PR. All autonomously.
|
|
106
|
+
|
|
107
|
+
Three tiers of adapter complexity:
|
|
108
|
+
|
|
109
|
+
| Tier | Auth method | Example | Time |
|
|
110
|
+
|------|-------------|---------|------|
|
|
111
|
+
| **1** | Cookie (fetch directly) | Reddit, GitHub, V2EX | ~1 min |
|
|
112
|
+
| **2** | Bearer + CSRF token | Twitter, Zhihu | ~3 min |
|
|
113
|
+
| **3** | Webpack injection / Pinia store | Twitter search, Xiaohongshu | ~10 min |
|
|
114
|
+
|
|
115
|
+
We tested this: **20 AI agents ran in parallel, each independently reverse-engineered a website and produced a working adapter.** The marginal cost of adding a new website to the agent-accessible internet is approaching zero.
|
|
79
116
|
|
|
80
|
-
|
|
117
|
+
## What this means for AI agents
|
|
118
|
+
|
|
119
|
+
Without bb-browser, an AI agent's world is: **files + terminal + a few APIs with keys.**
|
|
120
|
+
|
|
121
|
+
With bb-browser: **files + terminal + the entire internet.**
|
|
122
|
+
|
|
123
|
+
An agent can now, in under a minute:
|
|
81
124
|
|
|
82
125
|
```bash
|
|
83
|
-
|
|
84
|
-
bb-browser site
|
|
85
|
-
bb-browser site twitter/
|
|
86
|
-
bb-browser site
|
|
87
|
-
bb-browser site
|
|
126
|
+
# Cross-platform research on any topic
|
|
127
|
+
bb-browser site arxiv/search "retrieval augmented generation"
|
|
128
|
+
bb-browser site twitter/search "RAG"
|
|
129
|
+
bb-browser site github search rag-framework
|
|
130
|
+
bb-browser site stackoverflow/search "RAG implementation"
|
|
131
|
+
bb-browser site zhihu/search "RAG"
|
|
132
|
+
bb-browser site 36kr/newsflash
|
|
88
133
|
```
|
|
89
134
|
|
|
90
|
-
|
|
135
|
+
Six platforms, six dimensions, structured JSON. Faster and broader than any human researcher.
|
|
91
136
|
|
|
92
|
-
##
|
|
137
|
+
## Also a full browser automation tool
|
|
93
138
|
|
|
94
139
|
```bash
|
|
95
|
-
|
|
140
|
+
bb-browser open https://example.com
|
|
141
|
+
bb-browser snapshot -i # accessibility tree
|
|
142
|
+
bb-browser click @3 # click element
|
|
143
|
+
bb-browser fill @5 "hello" # fill input
|
|
144
|
+
bb-browser eval "document.title" # run JS
|
|
145
|
+
bb-browser fetch URL --json # authenticated fetch
|
|
146
|
+
bb-browser network requests --with-body --json # capture traffic
|
|
147
|
+
bb-browser screenshot # take screenshot
|
|
96
148
|
```
|
|
97
149
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
1. `chrome://extensions/` → Enable Developer Mode
|
|
101
|
-
2. "Load unpacked" → select `node_modules/bb-browser/extension/`
|
|
102
|
-
3. Done.
|
|
150
|
+
All commands support `--json` output, `--jq <expr>` for inline filtering, and `--tab <id>` for concurrent multi-tab operations.
|
|
103
151
|
|
|
104
152
|
```bash
|
|
105
|
-
bb-browser
|
|
106
|
-
|
|
153
|
+
bb-browser site xueqiu/hot-stock 5 --jq '.items[] | {name, changePercent}'
|
|
154
|
+
# {"name":"云天化","changePercent":"2.08%"}
|
|
155
|
+
# {"name":"东芯股份","changePercent":"-7.60%"}
|
|
156
|
+
|
|
157
|
+
bb-browser site info xueqiu/stock # view adapter args, example, domain
|
|
107
158
|
```
|
|
108
159
|
|
|
109
|
-
##
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
| | `snapshot -i` | Interactive elements only |
|
|
118
|
-
| **Interact** | `click <ref>` | Click element |
|
|
119
|
-
| | `fill <ref> <text>` | Clear and fill |
|
|
120
|
-
| | `type <ref> <text>` | Append text |
|
|
121
|
-
| | `hover <ref>` | Hover |
|
|
122
|
-
| | `press <key>` | Keyboard (Enter, Tab, Control+a) |
|
|
123
|
-
| | `scroll <dir> [px]` | Scroll |
|
|
124
|
-
| | `check` / `uncheck <ref>` | Checkbox |
|
|
125
|
-
| | `select <ref> <val>` | Dropdown |
|
|
126
|
-
| **Data** | `get text <ref>` | Element text |
|
|
127
|
-
| | `get url` / `get title` | Page info |
|
|
128
|
-
| | `screenshot [path]` | Screenshot |
|
|
129
|
-
| | `eval "<js>"` | Run JavaScript |
|
|
130
|
-
| **Fetch** | `fetch <url> [--json]` | Authenticated HTTP fetch |
|
|
131
|
-
| **Site** | `site list` | List site adapters |
|
|
132
|
-
| | `site <name> [args]` | Run adapter |
|
|
133
|
-
| | `site update` | Update community adapters |
|
|
134
|
-
| **Network** | `network requests [filter]` | View requests |
|
|
135
|
-
| | `network requests --with-body` | Include headers & body |
|
|
136
|
-
| | `network route "<url>" --abort` | Block requests |
|
|
137
|
-
| | `network clear` | Clear records |
|
|
138
|
-
| **Tab** | `tab` | List tabs |
|
|
139
|
-
| | `tab new [url]` | New tab |
|
|
140
|
-
| | `tab <n>` | Switch tab |
|
|
141
|
-
| **Debug** | `console` / `errors` | Console & JS errors |
|
|
142
|
-
| | `trace start` / `trace stop` | Record user actions |
|
|
143
|
-
| **Daemon** | `daemon` / `stop` / `status` | Manage daemon |
|
|
144
|
-
|
|
145
|
-
All commands support `--json` for structured output and `--tab <id>` for multi-tab operations.
|
|
160
|
+
## Daemon configuration
|
|
161
|
+
|
|
162
|
+
The daemon binds to `localhost:19824` by default. You can customize the host with `--host`:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
bb-browser daemon --host 127.0.0.1 # IPv4 only (fix macOS IPv6 issues)
|
|
166
|
+
bb-browser daemon --host 0.0.0.0 # listen on all interfaces (for Tailscale / ZeroTier remote access)
|
|
167
|
+
```
|
|
146
168
|
|
|
147
169
|
## Architecture
|
|
148
170
|
|
|
149
171
|
```
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
│
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
└── extension/ # Built extension (npm publish)
|
|
172
|
+
AI Agent (Claude Code, Codex, Cursor, etc.)
|
|
173
|
+
│ CLI or MCP (stdio)
|
|
174
|
+
▼
|
|
175
|
+
bb-browser CLI ──HTTP──▶ Daemon ──SSE──▶ Chrome Extension
|
|
176
|
+
│
|
|
177
|
+
▼ chrome.debugger (CDP)
|
|
178
|
+
Your Real Browser
|
|
158
179
|
```
|
|
159
180
|
|
|
160
|
-
| Layer | Tech |
|
|
161
|
-
|-------|------|
|
|
162
|
-
| CLI | TypeScript, zero dependencies |
|
|
163
|
-
| Daemon | Node.js HTTP + SSE |
|
|
164
|
-
| Extension | Chrome MV3 + `chrome.debugger` API |
|
|
165
|
-
| Build | pnpm monorepo + Turborepo + tsup + Vite |
|
|
166
|
-
|
|
167
181
|
## License
|
|
168
182
|
|
|
169
183
|
[MIT](LICENSE)
|
package/README.zh-CN.md
CHANGED
|
@@ -16,154 +16,168 @@
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
你已经登录了微博、知乎、B站、小红书、Twitter、GitHub、LinkedIn — bb-browser 让 AI Agent **直接用你的登录态**。
|
|
20
20
|
|
|
21
|
+
```bash
|
|
22
|
+
bb-browser site twitter/search "AI agent" # 搜索推文
|
|
23
|
+
bb-browser site zhihu/hot # 知乎热榜
|
|
24
|
+
bb-browser site arxiv/search "transformer" # 搜论文
|
|
25
|
+
bb-browser site eastmoney/stock "茅台" # 实时股票行情
|
|
26
|
+
bb-browser site boss/search "AI 工程师" # 搜职位
|
|
27
|
+
bb-browser site wikipedia/summary "Python" # 维基百科摘要
|
|
28
|
+
bb-browser site youtube/transcript VIDEO_ID # YouTube 字幕全文
|
|
29
|
+
bb-browser site stackoverflow/search "async" # 搜 StackOverflow
|
|
21
30
|
```
|
|
22
|
-
AI Agent (Claude Code, Codex 等)
|
|
23
|
-
│ CLI 命令
|
|
24
|
-
▼
|
|
25
|
-
bb-browser CLI ──HTTP──▶ Daemon ──SSE──▶ Chrome 扩展
|
|
26
|
-
│
|
|
27
|
-
▼ chrome.debugger (CDP)
|
|
28
|
-
你的真实浏览器
|
|
29
|
-
(已登录的网站、Cookie、会话)
|
|
30
|
-
```
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
**36 个平台,103 个命令,全部用你真实浏览器的登录态。** [完整列表 →](https://github.com/epiral/bb-sites)
|
|
33
|
+
|
|
34
|
+
## 核心理念
|
|
35
|
+
|
|
36
|
+
互联网是为浏览器构建的。AI Agent 一直试图通过 API 访问它 — 但 99% 的网站不提供 API。
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
bb-browser 翻转了这个逻辑:**不是让网站适配机器,而是让机器使用人的界面。** adapter 在你的浏览器 tab 里跑 `eval`,用你的 Cookie 调 `fetch()`,或者直接调用页面的 webpack 模块。网站以为是你在操作。因为**就是你**。
|
|
35
39
|
|
|
36
40
|
| | Playwright / Selenium | 爬虫库 | bb-browser |
|
|
37
41
|
|---|---|---|---|
|
|
38
42
|
| 浏览器 | 无头、隔离环境 | 没有浏览器 | 你的真实 Chrome |
|
|
39
43
|
| 登录态 | 没有,要重新登录 | 偷 Cookie | 已经在了 |
|
|
40
44
|
| 反爬检测 | 容易被识别 | 猫鼠游戏 | 无法检测 — 它就是用户 |
|
|
41
|
-
|
|
|
45
|
+
| 复杂鉴权 | 无法复制 | 需要逆向 | 页面自己处理 |
|
|
42
46
|
|
|
43
|
-
##
|
|
47
|
+
## 快速开始
|
|
44
48
|
|
|
45
|
-
###
|
|
49
|
+
### 安装
|
|
46
50
|
|
|
47
51
|
```bash
|
|
48
|
-
bb-browser
|
|
49
|
-
bb-browser snapshot -i # 只看可交互元素
|
|
50
|
-
bb-browser click @0 # 按 ref 点击
|
|
51
|
-
bb-browser fill @2 "hello" # 填写输入框
|
|
52
|
-
bb-browser press Enter
|
|
53
|
-
bb-browser screenshot
|
|
52
|
+
npm install -g bb-browser
|
|
54
53
|
```
|
|
55
54
|
|
|
56
|
-
###
|
|
55
|
+
### Chrome 扩展
|
|
56
|
+
|
|
57
|
+
1. 从 [Releases](https://github.com/epiral/bb-browser/releases/latest) 下载 zip
|
|
58
|
+
2. 解压 → `chrome://extensions/` → 开发者模式 → 加载已解压的扩展程序
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
### 使用
|
|
59
61
|
|
|
60
62
|
```bash
|
|
61
|
-
|
|
62
|
-
bb-browser
|
|
63
|
+
bb-browser site update # 拉取社区适配器
|
|
64
|
+
bb-browser site recommend # 看看哪些和你的浏览习惯匹配
|
|
65
|
+
bb-browser site zhihu/hot # 开搞
|
|
66
|
+
```
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
### MCP 接入(Claude Code / Cursor)
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"bb-browser": {
|
|
74
|
+
"command": "npx",
|
|
75
|
+
"args": ["-y", "bb-browser", "--mcp"]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
66
79
|
```
|
|
67
80
|
|
|
68
|
-
|
|
81
|
+
## 36 个平台,103 个命令
|
|
69
82
|
|
|
70
|
-
|
|
83
|
+
社区驱动,通过 [bb-sites](https://github.com/epiral/bb-sites) 维护。每个命令一个 JS 文件。
|
|
84
|
+
|
|
85
|
+
| 类别 | 平台 | 命令 |
|
|
86
|
+
|------|------|------|
|
|
87
|
+
| **搜索引擎** | Google、百度、Bing、DuckDuckGo、搜狗微信 | search |
|
|
88
|
+
| **社交媒体** | Twitter/X、Reddit、微博、小红书、即刻、LinkedIn、虎扑 | search、feed、thread、user、notifications、hot |
|
|
89
|
+
| **新闻资讯** | BBC、Reuters、36氪、今日头条、东方财富 | headlines、search、newsflash、hot |
|
|
90
|
+
| **技术开发** | GitHub、StackOverflow、HackerNews、CSDN、博客园、V2EX、Dev.to、npm、PyPI、arXiv | search、issues、repo、top、thread、package |
|
|
91
|
+
| **视频平台** | YouTube、B站 | search、video、transcript、popular、comments、feed |
|
|
92
|
+
| **影音娱乐** | 豆瓣、IMDb、Genius、起点中文网 | movie、search、top250 |
|
|
93
|
+
| **财经股票** | 雪球、东方财富、Yahoo Finance | stock、hot-stock、feed、watchlist、search |
|
|
94
|
+
| **求职招聘** | BOSS直聘、LinkedIn | search、detail、profile |
|
|
95
|
+
| **知识百科** | Wikipedia、知乎、Open Library | search、summary、hot、question |
|
|
96
|
+
| **消费购物** | 什么值得买 | search |
|
|
97
|
+
| **实用工具** | 有道翻译、GSMArena、Product Hunt、携程 | translate、手机参数、热门产品 |
|
|
98
|
+
|
|
99
|
+
## 10 分钟,CLI 化任何网站
|
|
71
100
|
|
|
72
101
|
```bash
|
|
73
|
-
bb-browser
|
|
74
|
-
# → 完整的请求头(包括签名 header)、完整的响应体
|
|
75
|
-
# → 看清一个网站的 API 是怎么工作的 — 然后为它写 adapter
|
|
102
|
+
bb-browser guide # 完整教程
|
|
76
103
|
```
|
|
77
104
|
|
|
78
|
-
|
|
105
|
+
跟你的 AI Agent 说:*「帮我把 XX 网站 CLI 化」*。它会读 guide,用 `network --with-body` 抓包逆向,写 adapter,测试,然后提 PR 到社区仓库。全程自动。
|
|
106
|
+
|
|
107
|
+
三种 adapter 复杂度:
|
|
108
|
+
|
|
109
|
+
| 层级 | 认证方式 | 代表 | 耗时 |
|
|
110
|
+
|------|----------|------|------|
|
|
111
|
+
| **Tier 1** | Cookie(直接 fetch) | Reddit、GitHub、V2EX | ~1 分钟 |
|
|
112
|
+
| **Tier 2** | Bearer + CSRF token | Twitter、知乎 | ~3 分钟 |
|
|
113
|
+
| **Tier 3** | Webpack 注入 / Pinia store | Twitter 搜索、小红书 | ~10 分钟 |
|
|
114
|
+
|
|
115
|
+
实测:**20 个 AI Agent 并发运行,每个独立逆向一个网站并产出可用的 adapter。** 将一个新网站纳入 Agent 可访问范围的边际成本趋近于零。
|
|
79
116
|
|
|
80
|
-
|
|
117
|
+
## 对 AI Agent 意味着什么
|
|
118
|
+
|
|
119
|
+
没有 bb-browser,AI Agent 的世界是:**文件系统 + 终端 + 少数有 API key 的服务。**
|
|
120
|
+
|
|
121
|
+
有了 bb-browser:**文件系统 + 终端 + 整个互联网。**
|
|
122
|
+
|
|
123
|
+
一个 Agent 现在可以在一分钟内:
|
|
81
124
|
|
|
82
125
|
```bash
|
|
83
|
-
|
|
84
|
-
bb-browser site
|
|
85
|
-
bb-browser site twitter/
|
|
86
|
-
bb-browser site
|
|
87
|
-
bb-browser site
|
|
126
|
+
# 跨平台调研任何话题
|
|
127
|
+
bb-browser site arxiv/search "retrieval augmented generation"
|
|
128
|
+
bb-browser site twitter/search "RAG"
|
|
129
|
+
bb-browser site github search rag-framework
|
|
130
|
+
bb-browser site stackoverflow/search "RAG implementation"
|
|
131
|
+
bb-browser site zhihu/search "RAG"
|
|
132
|
+
bb-browser site 36kr/newsflash
|
|
88
133
|
```
|
|
89
134
|
|
|
90
|
-
|
|
135
|
+
六个平台,六个维度,结构化 JSON。比任何人类研究员都快、都广。
|
|
91
136
|
|
|
92
|
-
##
|
|
137
|
+
## 同时也是完整的浏览器自动化工具
|
|
93
138
|
|
|
94
139
|
```bash
|
|
95
|
-
|
|
140
|
+
bb-browser open https://example.com
|
|
141
|
+
bb-browser snapshot -i # 可访问性树
|
|
142
|
+
bb-browser click @3 # 点击元素
|
|
143
|
+
bb-browser fill @5 "hello" # 填写输入框
|
|
144
|
+
bb-browser eval "document.title" # 执行 JS
|
|
145
|
+
bb-browser fetch URL --json # 带登录态的 fetch
|
|
146
|
+
bb-browser network requests --with-body --json # 抓包
|
|
147
|
+
bb-browser screenshot # 截图
|
|
96
148
|
```
|
|
97
149
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
1. 打开 `chrome://extensions/` → 开启开发者模式
|
|
101
|
-
2. 点击「加载已解压的扩展程序」→ 选 `node_modules/bb-browser/extension/`
|
|
102
|
-
3. 完成。
|
|
150
|
+
所有命令支持 `--json` 输出、`--jq <expr>` 内联过滤、和 `--tab <id>` 多标签页并发操作。
|
|
103
151
|
|
|
104
152
|
```bash
|
|
105
|
-
bb-browser
|
|
106
|
-
|
|
153
|
+
bb-browser site xueqiu/hot-stock 5 --jq '.items[] | {name, changePercent}'
|
|
154
|
+
# {"name":"云天化","changePercent":"2.08%"}
|
|
155
|
+
# {"name":"东芯股份","changePercent":"-7.60%"}
|
|
156
|
+
|
|
157
|
+
bb-browser site info xueqiu/stock # 查看 adapter 参数、示例、域名
|
|
107
158
|
```
|
|
108
159
|
|
|
109
|
-
##
|
|
160
|
+
## Daemon 配置
|
|
110
161
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
| | `snapshot -i` | 只看可交互元素 |
|
|
118
|
-
| **交互** | `click <ref>` | 点击 |
|
|
119
|
-
| | `fill <ref> <text>` | 清空后填入 |
|
|
120
|
-
| | `type <ref> <text>` | 追加输入 |
|
|
121
|
-
| | `hover <ref>` | 悬停 |
|
|
122
|
-
| | `press <key>` | 按键(Enter, Tab, Control+a)|
|
|
123
|
-
| | `scroll <dir> [px]` | 滚动 |
|
|
124
|
-
| | `check` / `uncheck <ref>` | 复选框 |
|
|
125
|
-
| | `select <ref> <val>` | 下拉框 |
|
|
126
|
-
| **数据** | `get text <ref>` | 元素文本 |
|
|
127
|
-
| | `get url` / `get title` | 页面信息 |
|
|
128
|
-
| | `screenshot [path]` | 截图 |
|
|
129
|
-
| | `eval "<js>"` | 执行 JavaScript |
|
|
130
|
-
| **Fetch** | `fetch <url> [--json]` | 带登录态的 HTTP 请求 |
|
|
131
|
-
| **Site** | `site list` | 列出 adapter |
|
|
132
|
-
| | `site <name> [args]` | 运行 adapter |
|
|
133
|
-
| | `site update` | 更新社区 adapter |
|
|
134
|
-
| **网络** | `network requests [filter]` | 查看请求 |
|
|
135
|
-
| | `network requests --with-body` | 包含请求头和响应体 |
|
|
136
|
-
| | `network route "<url>" --abort` | 拦截请求 |
|
|
137
|
-
| | `network clear` | 清空记录 |
|
|
138
|
-
| **Tab** | `tab` | 列出标签页 |
|
|
139
|
-
| | `tab new [url]` | 新标签页 |
|
|
140
|
-
| | `tab <n>` | 切换标签页 |
|
|
141
|
-
| **调试** | `console` / `errors` | 控制台/JS 错误 |
|
|
142
|
-
| | `trace start` / `trace stop` | 录制用户操作 |
|
|
143
|
-
| **Daemon** | `daemon` / `stop` / `status` | 管理 daemon |
|
|
144
|
-
|
|
145
|
-
所有命令支持 `--json` 结构化输出和 `--tab <id>` 多标签页操作。
|
|
162
|
+
Daemon 默认绑定 `localhost:19824`,可通过 `--host` 自定义监听地址:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
bb-browser daemon --host 127.0.0.1 # 仅 IPv4(解决 macOS IPv6 问题)
|
|
166
|
+
bb-browser daemon --host 0.0.0.0 # 监听所有网卡(用于 Tailscale / ZeroTier 跨机器访问)
|
|
167
|
+
```
|
|
146
168
|
|
|
147
169
|
## 架构
|
|
148
170
|
|
|
149
171
|
```
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
│
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
└── extension/ # 构建好的扩展(npm 发布)
|
|
172
|
+
AI Agent (Claude Code, Codex, Cursor 等)
|
|
173
|
+
│ CLI 或 MCP (stdio)
|
|
174
|
+
▼
|
|
175
|
+
bb-browser CLI ──HTTP──▶ Daemon ──SSE──▶ Chrome 扩展
|
|
176
|
+
│
|
|
177
|
+
▼ chrome.debugger (CDP)
|
|
178
|
+
你的真实浏览器
|
|
158
179
|
```
|
|
159
180
|
|
|
160
|
-
| 层 | 技术栈 |
|
|
161
|
-
|----|--------|
|
|
162
|
-
| CLI | TypeScript,零依赖 |
|
|
163
|
-
| Daemon | Node.js HTTP + SSE |
|
|
164
|
-
| Extension | Chrome MV3 + `chrome.debugger` API |
|
|
165
|
-
| 构建 | pnpm monorepo + Turborepo + tsup + Vite |
|
|
166
|
-
|
|
167
181
|
## 许可证
|
|
168
182
|
|
|
169
183
|
[MIT](LICENSE)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// packages/cli/src/jq.ts
|
|
4
|
+
function splitTopLevel(input, separator) {
|
|
5
|
+
const parts = [];
|
|
6
|
+
let current = "";
|
|
7
|
+
let depth = 0;
|
|
8
|
+
let inString = false;
|
|
9
|
+
for (let i = 0; i < input.length; i++) {
|
|
10
|
+
const char = input[i];
|
|
11
|
+
const prev = input[i - 1];
|
|
12
|
+
if (char === '"' && prev !== "\\") inString = !inString;
|
|
13
|
+
if (!inString) {
|
|
14
|
+
if (char === "{" || char === "(" || char === "[") depth++;
|
|
15
|
+
if (char === "}" || char === ")" || char === "]") depth--;
|
|
16
|
+
if (depth === 0 && input.slice(i, i + separator.length) === separator) {
|
|
17
|
+
parts.push(current.trim());
|
|
18
|
+
current = "";
|
|
19
|
+
i += separator.length - 1;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
current += char;
|
|
24
|
+
}
|
|
25
|
+
if (current.trim()) parts.push(current.trim());
|
|
26
|
+
return parts;
|
|
27
|
+
}
|
|
28
|
+
function parseLiteral(value) {
|
|
29
|
+
const trimmed = value.trim();
|
|
30
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) return JSON.parse(trimmed);
|
|
31
|
+
if (trimmed === "true") return true;
|
|
32
|
+
if (trimmed === "false") return false;
|
|
33
|
+
if (trimmed === "null") return null;
|
|
34
|
+
return Number(trimmed);
|
|
35
|
+
}
|
|
36
|
+
function getField(value, field) {
|
|
37
|
+
return value !== null && typeof value === "object" ? value[field] : void 0;
|
|
38
|
+
}
|
|
39
|
+
function applySegment(inputs, expr) {
|
|
40
|
+
if (expr === ".") return inputs;
|
|
41
|
+
if (expr.startsWith("select(")) {
|
|
42
|
+
const match = expr.match(/^select\((.+?)\s*(==|>)\s*(.+)\)$/);
|
|
43
|
+
if (!match) throw new Error(`\u4E0D\u652F\u6301\u7684 jq \u8868\u8FBE\u5F0F: ${expr}`);
|
|
44
|
+
const [, leftExpr, op, rightExpr] = match;
|
|
45
|
+
const expected = parseLiteral(rightExpr);
|
|
46
|
+
return inputs.filter((item) => {
|
|
47
|
+
const left = applyExpression([item], leftExpr)[0];
|
|
48
|
+
return op === "==" ? left === expected : Number(left) > Number(expected);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (expr.startsWith("{") && expr.endsWith("}")) {
|
|
52
|
+
const body = expr.slice(1, -1).trim();
|
|
53
|
+
if (!body) return inputs.map(() => ({}));
|
|
54
|
+
const entries = splitTopLevel(body, ",");
|
|
55
|
+
return inputs.map((item) => {
|
|
56
|
+
const obj = {};
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
const colon = entry.indexOf(":");
|
|
59
|
+
if (colon === -1) {
|
|
60
|
+
const key = entry.trim().replace(/^\./, "");
|
|
61
|
+
obj[key] = applyExpression([item], `.${key}`)[0];
|
|
62
|
+
} else {
|
|
63
|
+
const key = entry.slice(0, colon).trim();
|
|
64
|
+
const valueExpr = entry.slice(colon + 1).trim();
|
|
65
|
+
obj[key] = applyExpression([item], valueExpr)[0];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return obj;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (!expr.startsWith(".")) throw new Error(`\u4E0D\u652F\u6301\u7684 jq \u8868\u8FBE\u5F0F: ${expr}`);
|
|
72
|
+
let current = inputs;
|
|
73
|
+
let remaining = expr.slice(1);
|
|
74
|
+
while (remaining.length > 0) {
|
|
75
|
+
if (remaining.startsWith("[]")) {
|
|
76
|
+
current = current.flatMap((item) => Array.isArray(item) ? item : []);
|
|
77
|
+
remaining = remaining.slice(2);
|
|
78
|
+
} else if (remaining.startsWith("[")) {
|
|
79
|
+
const match = remaining.match(/^\[(-?\d+)\]/);
|
|
80
|
+
if (!match) throw new Error(`\u4E0D\u652F\u6301\u7684 jq \u8868\u8FBE\u5F0F: .${remaining}`);
|
|
81
|
+
const index = Number(match[1]);
|
|
82
|
+
current = current.map((item) => {
|
|
83
|
+
if (!Array.isArray(item)) return void 0;
|
|
84
|
+
return item[index >= 0 ? index : item.length + index];
|
|
85
|
+
});
|
|
86
|
+
remaining = remaining.slice(match[0].length);
|
|
87
|
+
} else if (remaining.startsWith(".")) {
|
|
88
|
+
remaining = remaining.slice(1);
|
|
89
|
+
} else {
|
|
90
|
+
const match = remaining.match(/^([A-Za-z_][A-Za-z0-9_]*)/);
|
|
91
|
+
if (!match) throw new Error(`\u4E0D\u652F\u6301\u7684 jq \u8868\u8FBE\u5F0F: .${remaining}`);
|
|
92
|
+
const field = match[1];
|
|
93
|
+
current = current.map((item) => getField(item, field));
|
|
94
|
+
remaining = remaining.slice(field.length);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return current;
|
|
98
|
+
}
|
|
99
|
+
function applyExpression(inputs, expression) {
|
|
100
|
+
const segments = splitTopLevel(expression.trim(), "|");
|
|
101
|
+
return segments.reduce((current, segment) => applySegment(current, segment.trim()), inputs);
|
|
102
|
+
}
|
|
103
|
+
function applyJq(data, expression) {
|
|
104
|
+
return applyExpression([data], expression).filter((item) => item !== void 0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
applyJq
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=chunk-AHGAQEFO.js.map
|