@jackwener/opencli 0.9.8 → 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.
Files changed (97) hide show
  1. package/CDP.md +1 -1
  2. package/CDP.zh-CN.md +1 -1
  3. package/CLI-ELECTRON.md +2 -2
  4. package/CLI-EXPLORER.md +4 -4
  5. package/README.md +15 -57
  6. package/README.zh-CN.md +16 -59
  7. package/SKILL.md +10 -8
  8. package/TESTING.md +7 -7
  9. package/dist/browser/daemon-client.d.ts +37 -0
  10. package/dist/browser/daemon-client.js +82 -0
  11. package/dist/browser/discover.d.ts +11 -34
  12. package/dist/browser/discover.js +15 -205
  13. package/dist/browser/errors.d.ts +6 -20
  14. package/dist/browser/errors.js +24 -63
  15. package/dist/browser/index.d.ts +2 -11
  16. package/dist/browser/index.js +5 -11
  17. package/dist/browser/mcp.d.ts +9 -18
  18. package/dist/browser/mcp.js +70 -284
  19. package/dist/browser/page.d.ts +28 -6
  20. package/dist/browser/page.js +210 -85
  21. package/dist/browser.test.js +4 -225
  22. package/dist/cli-manifest.json +167 -0
  23. package/dist/clis/neteasemusic/like.d.ts +1 -0
  24. package/dist/clis/neteasemusic/like.js +25 -0
  25. package/dist/clis/neteasemusic/lyrics.d.ts +1 -0
  26. package/dist/clis/neteasemusic/lyrics.js +47 -0
  27. package/dist/clis/neteasemusic/next.d.ts +1 -0
  28. package/dist/clis/neteasemusic/next.js +26 -0
  29. package/dist/clis/neteasemusic/play.d.ts +1 -0
  30. package/dist/clis/neteasemusic/play.js +26 -0
  31. package/dist/clis/neteasemusic/playing.d.ts +1 -0
  32. package/dist/clis/neteasemusic/playing.js +59 -0
  33. package/dist/clis/neteasemusic/playlist.d.ts +1 -0
  34. package/dist/clis/neteasemusic/playlist.js +46 -0
  35. package/dist/clis/neteasemusic/prev.d.ts +1 -0
  36. package/dist/clis/neteasemusic/prev.js +25 -0
  37. package/dist/clis/neteasemusic/search.d.ts +1 -0
  38. package/dist/clis/neteasemusic/search.js +52 -0
  39. package/dist/clis/neteasemusic/status.d.ts +1 -0
  40. package/dist/clis/neteasemusic/status.js +16 -0
  41. package/dist/clis/neteasemusic/volume.d.ts +1 -0
  42. package/dist/clis/neteasemusic/volume.js +54 -0
  43. package/dist/daemon.d.ts +13 -0
  44. package/dist/daemon.js +187 -0
  45. package/dist/doctor.d.ts +27 -61
  46. package/dist/doctor.js +70 -601
  47. package/dist/doctor.test.js +30 -170
  48. package/dist/main.js +6 -25
  49. package/dist/pipeline/executor.test.js +1 -0
  50. package/dist/pipeline/steps/browser.js +2 -2
  51. package/dist/pipeline/steps/intercept.js +1 -2
  52. package/dist/setup.d.ts +6 -0
  53. package/dist/setup.js +46 -160
  54. package/dist/types.d.ts +6 -0
  55. package/extension/icons/icon-128.png +0 -0
  56. package/extension/icons/icon-16.png +0 -0
  57. package/extension/icons/icon-32.png +0 -0
  58. package/extension/icons/icon-48.png +0 -0
  59. package/extension/manifest.json +31 -0
  60. package/extension/package.json +16 -0
  61. package/extension/src/background.ts +293 -0
  62. package/extension/src/cdp.ts +125 -0
  63. package/extension/src/protocol.ts +57 -0
  64. package/extension/store-assets/screenshot-1280x800.png +0 -0
  65. package/extension/tsconfig.json +15 -0
  66. package/extension/vite.config.ts +18 -0
  67. package/package.json +5 -5
  68. package/src/browser/daemon-client.ts +113 -0
  69. package/src/browser/discover.ts +18 -232
  70. package/src/browser/errors.ts +30 -100
  71. package/src/browser/index.ts +6 -12
  72. package/src/browser/mcp.ts +78 -278
  73. package/src/browser/page.ts +222 -88
  74. package/src/browser.test.ts +3 -233
  75. package/src/clis/chatgpt/README.md +1 -1
  76. package/src/clis/chatgpt/README.zh-CN.md +1 -1
  77. package/src/clis/neteasemusic/README.md +31 -0
  78. package/src/clis/neteasemusic/README.zh-CN.md +31 -0
  79. package/src/clis/neteasemusic/like.ts +28 -0
  80. package/src/clis/neteasemusic/lyrics.ts +53 -0
  81. package/src/clis/neteasemusic/next.ts +30 -0
  82. package/src/clis/neteasemusic/play.ts +30 -0
  83. package/src/clis/neteasemusic/playing.ts +62 -0
  84. package/src/clis/neteasemusic/playlist.ts +51 -0
  85. package/src/clis/neteasemusic/prev.ts +29 -0
  86. package/src/clis/neteasemusic/search.ts +58 -0
  87. package/src/clis/neteasemusic/status.ts +18 -0
  88. package/src/clis/neteasemusic/volume.ts +61 -0
  89. package/src/daemon.ts +217 -0
  90. package/src/doctor.test.ts +32 -193
  91. package/src/doctor.ts +74 -668
  92. package/src/main.ts +6 -23
  93. package/src/pipeline/executor.test.ts +1 -0
  94. package/src/pipeline/steps/browser.ts +2 -2
  95. package/src/pipeline/steps/intercept.ts +1 -2
  96. package/src/setup.ts +47 -183
  97. package/src/types.ts +1 -0
package/CDP.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Connecting OpenCLI via CDP (Remote/Headless Servers)
2
2
 
3
- If you cannot use the Playwright MCP Bridge extension (e.g., in a remote headless server environment without a UI), OpenCLI provides an alternative: connecting directly to Chrome via **CDP (Chrome DevTools Protocol)**.
3
+ If you cannot use the opencli Browser Bridge extension (e.g., in a remote headless server environment without a UI), OpenCLI provides an alternative: connecting directly to Chrome via **CDP (Chrome DevTools Protocol)**.
4
4
 
5
5
  Because CDP binds to `localhost` by default for security reasons, accessing it from a remote server requires an additional networking tunnel.
6
6
 
package/CDP.zh-CN.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 通过 CDP 远程连接 OpenCLI (服务器/无头环境)
2
2
 
3
- 如果你无法使用 Playwright MCP Bridge 浏览器扩展(例如:在无界面的远程服务器上运行 OpenCLI 时),OpenCLI 提供了备选方案:通过连接 **CDP (Chrome DevTools Protocol,即 Chrome 开发者工具协议)** 来直接控制本地 Chrome。
3
+ 如果你无法使用 opencli Browser Bridge 浏览器扩展(例如:在无界面的远程服务器上运行 OpenCLI 时),OpenCLI 提供了备选方案:通过连接 **CDP (Chrome DevTools Protocol,即 Chrome 开发者工具协议)** 来直接控制本地 Chrome。
4
4
 
5
5
  出于安全考虑,CDP 默认仅绑定在 `localhost` 的本地端口。所以,若是想让**远程服务器**调用本地的 CDP 服务,我们需要依靠一层额外的网络隧道。
6
6
 
package/CLI-ELECTRON.md CHANGED
@@ -8,7 +8,7 @@ Based on the successful automation of **Cursor**, **Codex**, **Antigravity**, **
8
8
 
9
9
  ## Core Concept
10
10
 
11
- Electron apps are essentially local Chromium browser instances. By exposing a debugging port (CDP — Chrome DevTools Protocol) at launch time, we can use Playwright to pierce through the UI layer, accessing and controlling all underlying state including React/Vue components and Shadow DOM.
11
+ Electron apps are essentially local Chromium browser instances. By exposing a debugging port (CDP — Chrome DevTools Protocol) at launch time, we can use the Browser Bridge to pierce through the UI layer, accessing and controlling all underlying state including React/Vue components and Shadow DOM.
12
12
 
13
13
  > **Note:** Not all desktop apps are Electron. WeChat (native Cocoa) and Feishu/Lark (custom Lark Framework) embed Chromium but do NOT expose CDP. For those apps, use the AppleScript + clipboard approach instead (see [Non-Electron Pattern](#non-electron-pattern-applescript)).
14
14
 
@@ -109,7 +109,7 @@ Core techniques:
109
109
  ## Pitfalls & Gotchas
110
110
 
111
111
  1. **Port conflicts (EADDRINUSE)**: Only one app per port. Use unique ports: Codex=9222, ChatGPT=9224, Cursor=9226, ChatWise=9228, Notion=9230, Discord=9232
112
- 2. **IPage abstraction**: OpenCLI wraps Playwright Page as `IPage` (`src/types.ts`). Use `page.pressKey()` and `page.evaluate()`, NOT `page.keyboard.press()`
112
+ 2. **IPage abstraction**: OpenCLI wraps the browser page as `IPage` (`src/types.ts`). Use `page.pressKey()` and `page.evaluate()`, NOT direct DOM APIs
113
113
  3. **Timing**: Always add `await page.wait(0.5)` to `1.0` after DOM mutations. Returning too early disconnects prematurely
114
114
  4. **AppleScript requires Accessibility**: Terminal app must be granted permission in System Settings → Privacy & Security → Accessibility
115
115
 
package/CLI-EXPLORER.md CHANGED
@@ -9,12 +9,12 @@
9
9
 
10
10
  ---
11
11
 
12
- ## AI Agent 开发者必读:用 Playwright MCP Bridge 探索
12
+ ## AI Agent 开发者必读:用浏览器探索
13
13
 
14
14
  > [!CAUTION]
15
- > **你(AI Agent)必须通过 Playwright MCP Bridge 打开浏览器去访问目标网站!**
15
+ > **你(AI Agent)必须通过浏览器打开目标网站去探索!**
16
16
  > 不要只靠 `opencli explore` 命令或静态分析来发现 API。
17
- > 你拥有 Playwright MCP 工具,必须主动用它们浏览网页、观察网络请求、模拟用户交互。
17
+ > 你拥有浏览器工具,必须主动用它们浏览网页、观察网络请求、模拟用户交互。
18
18
 
19
19
  ### 为什么?
20
20
 
@@ -36,7 +36,7 @@
36
36
 
37
37
  | ❌ 错误做法 | ✅ 正确做法 |
38
38
  |------------|------------|
39
- | 只用 `opencli explore` 命令,等结果自动出来 | MCP Bridge 打开浏览器,主动浏览页面 |
39
+ | 只用 `opencli explore` 命令,等结果自动出来 | 用浏览器工具打开页面,主动浏览 |
40
40
  | 直接在代码里 `fetch(url)`,不看浏览器实际请求 | 先在浏览器中确认 API 可用,再写代码 |
41
41
  | 页面打开后直接抓包,期望所有 API 都出现 | 模拟点击交互(展开评论/切换标签/加载更多) |
42
42
  | 遇到 HTTP 200 但空数据就放弃 | 检查是否需要 Wbi 签名或 Cookie 鉴权 |
package/README.md CHANGED
@@ -49,69 +49,27 @@ Turn ANY Electron application into a CLI tool! Recombine, script, and extend app
49
49
 
50
50
  > **⚠️ Important**: Browser commands reuse your Chrome login session. You must be logged into the target website in Chrome before running commands. If you get empty data or errors, check your login status first.
51
51
 
52
- OpenCLI connects to your browser through the Playwright MCP Bridge extension.
53
- It prefers an existing local/global `@playwright/mcp` install and falls back to `npx -y @playwright/mcp@latest` automatically when no local MCP server is found.
52
+ OpenCLI connects to your browser through a lightweight **Browser Bridge** Chrome Extension + micro-daemon (zero config, auto-start).
54
53
 
55
- ### Playwright MCP Bridge Extension Setup
54
+ ### Browser Bridge Extension Setup
56
55
 
57
- 1. Install **[Playwright MCP Bridge](https://chromewebstore.google.com/detail/playwright-mcp-bridge/mmlmfjhmonkocbjadbfplnigmagldckm)** extension in Chrome.
58
- 2. Run `opencli setup` discovers the token, distributes it to your tools, and verifies connectivity:
56
+ 1. Install the **opencli Browser Bridge** extension in Chrome:
57
+ - Open `chrome://extensions`, enable **Developer mode** (top-right toggle)
58
+ - Click **Load unpacked**, select the `extension/` folder from this repo
59
+ 2. That's it! The daemon auto-starts when you run any browser command. No tokens, no manual configuration.
59
60
 
60
- ```bash
61
- opencli setup
62
- ```
63
-
64
- The interactive TUI will:
65
- - 🔍 Auto-discover `PLAYWRIGHT_MCP_EXTENSION_TOKEN` from Chrome (no manual copy needed)
66
- - ☑️ Show all detected tools (Codex, Cursor, Claude Code, Gemini CLI, etc.)
67
- - ✏️ Update only the files you select (Space to toggle, Enter to confirm)
68
- - 🔌 Auto-verify browser connectivity after writing configs
69
-
70
- > **Tip**: Use `opencli doctor` for ongoing diagnosis and maintenance:
61
+ > **Tip**: Use `opencli doctor` for ongoing diagnosis:
71
62
  > ```bash
72
- > opencli doctor # Read-only token & config diagnosis
73
- > opencli doctor --live # Also test live browser connectivity
74
- > opencli doctor --fix # Fix mismatched configs (interactive)
75
- > opencli doctor --fix -y # Fix all configs non-interactively
63
+ > opencli doctor # Check extension + daemon connectivity
64
+ > opencli doctor --live # Also test live browser commands
76
65
  > ```
77
66
 
78
- **Alternative: CDP Mode (For Servers/Headless)**
79
- If you cannot install the browser extension (e.g. running OpenCLI on a remote headless server), you can connect OpenCLI to your local Chrome via CDP using SSH tunnels or reverse proxies. See the [CDP Connection Guide](./CDP.md) for detailed instructions.
80
-
81
- <details>
82
- <summary>Manual setup (alternative)</summary>
83
-
84
- Add token to your MCP client config (e.g. Claude/Cursor):
85
-
86
- ```json
87
- {
88
- "mcpServers": {
89
- "playwright": {
90
- "command": "npx",
91
- "args": ["-y", "@playwright/mcp@latest", "--extension"],
92
- "env": {
93
- "PLAYWRIGHT_MCP_EXTENSION_TOKEN": "<your-token-here>"
94
- }
95
- }
96
- }
97
- }
98
- ```
99
-
100
- Export in shell (e.g. `~/.zshrc`):
101
-
102
- ```bash
103
- export PLAYWRIGHT_MCP_EXTENSION_TOKEN="<your-token-here>"
104
- ```
105
-
106
- </details>
107
-
108
67
  ## Quick Start
109
68
 
110
69
  ### Install via npm (recommended)
111
70
 
112
71
  ```bash
113
72
  npm install -g @jackwener/opencli
114
- opencli setup # One-time: configure Playwright MCP token
115
73
  ```
116
74
 
117
75
  Then use directly:
@@ -297,15 +255,15 @@ npx vitest run tests/e2e/ # E2E tests
297
255
 
298
256
  ## Troubleshooting
299
257
 
300
- - **"Failed to connect to Playwright MCP Bridge"**
301
- - Ensure the Playwright MCP extension is installed and **enabled** in your running Chrome.
302
- - Restart the Chrome browser if you just installed the extension.
258
+ - **"Extension not connected"**
259
+ - Ensure the opencli Browser Bridge extension is installed and **enabled** in `chrome://extensions`.
303
260
  - **Empty data returns or 'Unauthorized' error**
304
- - Your login session in Chrome might have expired. Open a normal Chrome tab, navigate to the target site, and log in or refresh the page to prove you are human.
261
+ - Your login session in Chrome might have expired. Open a normal Chrome tab, navigate to the target site, and log in or refresh the page.
305
262
  - **Node API errors**
306
263
  - Make sure you are using Node.js >= 20. Some dependencies require modern Node APIs.
307
- - **Token issues**
308
- - Run `opencli doctor` to diagnose token configuration across all tools.
264
+ - **Daemon issues**
265
+ - Check daemon status: `curl localhost:19825/status`
266
+ - View extension logs: `curl localhost:19825/logs`
309
267
 
310
268
  ## Releasing New Versions
311
269
 
package/README.zh-CN.md CHANGED
@@ -50,69 +50,27 @@ CLI all electron!现在支持把所有 electron 应用 CLI 化,从而组合
50
50
 
51
51
  > **⚠️ 重要**:大多数命令复用你的 Chrome 登录状态。运行命令前,你必须已在 Chrome 中打开目标网站并完成登录。如果获取到空数据或报错,请先检查你的浏览器登录状态。
52
52
 
53
- OpenCLI 通过 Playwright MCP Bridge 扩展与你的浏览器通信。
54
- 它会优先复用本地或全局已安装的 `@playwright/mcp`,如果没有嗅探到可用 MCP server,则会自动回退到 `npx -y @playwright/mcp@latest` 启动。
53
+ OpenCLI 通过轻量化的 **Browser Bridge** Chrome 扩展 + 微型 daemon 与浏览器通信(零配置,自动启动)。
55
54
 
56
- ### Playwright MCP Bridge 扩展配置
55
+ ### Browser Bridge 扩展配置
57
56
 
58
- 1. 安装 **[Playwright MCP Bridge](https://chromewebstore.google.com/detail/playwright-mcp-bridge/mmlmfjhmonkocbjadbfplnigmagldckm)** 扩展
59
- 2. 运行 `opencli setup` — 自动发现 Token、分发到各工具、验证连通性:
57
+ 1. Chrome 中安装 **opencli Browser Bridge** 扩展:
58
+ - 打开 `chrome://extensions`,启用右上角的 **开发者模式**
59
+ - 点击 **加载已解压的扩展程序**,选择本仓库的 `extension/` 文件夹
60
+ 2. 完成!运行任何浏览器命令时 daemon 会自动启动。无需 token,无需手动配置。
60
61
 
61
- ```bash
62
- opencli setup
63
- ```
64
-
65
- 交互式 TUI 会:
66
- - 🔍 从 Chrome 自动发现 `PLAYWRIGHT_MCP_EXTENSION_TOKEN`(无需手动复制)
67
- - ☑️ 显示所有支持的工具(Codex、Cursor、Claude Code、Gemini CLI 等)
68
- - ✏️ 只更新你选中的文件(空格切换,回车确认)
69
- - 🔌 完成后自动验证浏览器连通性
70
-
71
- > **Tip**:后续诊断和维护用 `opencli doctor`:
62
+ > **Tip**:后续诊断用 `opencli doctor`:
72
63
  > ```bash
73
- > opencli doctor # 只读 Token 与配置诊断
74
- > opencli doctor --live # 额外测试浏览器连通性
75
- > opencli doctor --fix # 修复不一致的配置(交互确认)
76
- > opencli doctor --fix -y # 无交互直接修复所有配置
64
+ > opencli doctor # 检查扩展和 daemon 连通性
65
+ > opencli doctor --live # 额外测试浏览器命令
77
66
  > ```
78
67
 
79
- **备选方案:CDP 模式 (适用于服务器/无头环境)**
80
- 如果你无法安装浏览器扩展(比如在远程无头服务器上运行 OpenCLI),你可以通过 SSH 隧道或反向代理,利用 CDP (Chrome DevTools Protocol) 连接到本地的 Chrome 浏览器。详细指南请参考 [CDP 连接教程](./CDP.zh-CN.md)。
81
-
82
- <details>
83
- <summary>手动配置(备选方案)</summary>
84
-
85
- 配置你的 MCP 客户端(如 Claude/Cursor 等):
86
-
87
- ```json
88
- {
89
- "mcpServers": {
90
- "playwright": {
91
- "command": "npx",
92
- "args": ["-y", "@playwright/mcp@latest", "--extension"],
93
- "env": {
94
- "PLAYWRIGHT_MCP_EXTENSION_TOKEN": "<你的-token>"
95
- }
96
- }
97
- }
98
- }
99
- ```
100
-
101
- 在终端环境变量中导出(建议写进 `~/.zshrc`):
102
-
103
- ```bash
104
- export PLAYWRIGHT_MCP_EXTENSION_TOKEN="<你的-token>"
105
- ```
106
-
107
- </details>
108
-
109
68
  ## 快速开始
110
69
 
111
70
  ### npm 全局安装(推荐)
112
71
 
113
72
  ```bash
114
73
  npm install -g @jackwener/opencli
115
- opencli setup # 首次使用:配置 Playwright MCP token
116
74
  ```
117
75
 
118
76
  直接使用:
@@ -280,16 +238,15 @@ opencli cascade https://api.example.com/data
280
238
 
281
239
  ## 常见问题排查
282
240
 
283
- - **"Failed to connect to Playwright MCP Bridge"** 报错
284
- - 确保你当前的 Chrome 已安装且**开启了** Playwright MCP Bridge 浏览器插件。
285
- - 如果是刚装完插件,需要重启 Chrome 浏览器。
241
+ - **"Extension not connected" 报错**
242
+ - 确保你当前的 Chrome 已安装且**开启了** opencli Browser Bridge 扩展(在 `chrome://extensions` 中检查)。
286
243
  - **返回空数据,或者报错 "Unauthorized"**
287
- - Chrome 里的登录态可能已经过期(甚至被要求过滑动验证码)。请打开当前 Chrome 页面,在新标签页重新手工登录或刷新该页面。
244
+ - Chrome 里的登录态可能已经过期。请打开当前 Chrome 页面,在新标签页重新手工登录或刷新该页面。
288
245
  - **Node API 错误 (如 parseArgs, fs 等)**
289
- - 确保 Node.js 版本 `>= 20`。旧版不支持我们使用的现代核心库 API。
290
- - **Token 问题**
291
- - 运行 `opencli doctor` 诊断所有工具的 Token 配置状态。
292
- - 使用 `opencli doctor --live` 测试浏览器连通性。
246
+ - 确保 Node.js 版本 `>= 20`。
247
+ - **Daemon 问题**
248
+ - 检查 daemon 状态:`curl localhost:19825/status`
249
+ - 查看扩展日志:`curl localhost:19825/logs`
293
250
 
294
251
  ## 版本发布
295
252
 
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: opencli
3
3
  description: "OpenCLI — Make any website or Electron App your CLI. Zero risk, AI-powered, reuse Chrome login. 80+ commands across 19 sites."
4
4
  version: 0.7.3
5
5
  author: jackwener
6
- tags: [cli, browser, web, mcp, playwright, bilibili, zhihu, twitter, github, v2ex, hackernews, reddit, xiaohongshu, xueqiu, youtube, boss, coupang, AI, agent]
6
+ tags: [cli, browser, web, chrome-extension, cdp, bilibili, zhihu, twitter, github, v2ex, hackernews, reddit, xiaohongshu, xueqiu, youtube, boss, coupang, AI, agent]
7
7
  ---
8
8
 
9
9
  # OpenCLI
@@ -12,7 +12,7 @@ tags: [cli, browser, web, mcp, playwright, bilibili, zhihu, twitter, github, v2e
12
12
 
13
13
  > [!CAUTION]
14
14
  > **AI Agent 必读:创建或修改任何适配器之前,你必须先阅读 [CLI-EXPLORER.md](./CLI-EXPLORER.md)!**
15
- > 该文档包含完整的 API 发现工作流(必须使用 Playwright MCP Bridge 浏览器探索)、5 级认证策略决策树、平台 SDK 速查表、`tap` 步骤调试流程、分页 API 模板、级联请求模式、以及常见陷阱。
15
+ > 该文档包含完整的 API 发现工作流(必须使用浏览器探索)、5 级认证策略决策树、平台 SDK 速查表、`tap` 步骤调试流程、分页 API 模板、级联请求模式、以及常见陷阱。
16
16
  > **本文件(SKILL.md)仅提供命令参考和简化模板,不足以正确开发适配器。**
17
17
 
18
18
  ## Install & Run
@@ -34,8 +34,8 @@ npm update -g @jackwener/opencli
34
34
 
35
35
  Browser commands require:
36
36
  1. Chrome browser running **(logged into target sites)**
37
- 2. [Playwright MCP Bridge](https://chromewebstore.google.com/detail/playwright-mcp-bridge/mmlmfjhmonkocbjadbfplnigmagldckm) extension installed
38
- 3. Run `opencli setup` to auto-discover token and configure all tools
37
+ 2. **opencli Browser Bridge** Chrome extension installed (load `extension/` as unpacked in `chrome://extensions`)
38
+ 3. No further setup needed — the daemon auto-starts on first browser command
39
39
 
40
40
  > **Note**: You must be logged into the target website in Chrome before running commands. Tabs opened during command execution are auto-closed afterwards.
41
41
 
@@ -227,7 +227,7 @@ opencli bilibili hot -v # Show each pipeline step and data flow
227
227
 
228
228
  > [!IMPORTANT]
229
229
  > **完整模式 — 在写任何代码之前,先阅读 [CLI-EXPLORER.md](./CLI-EXPLORER.md)。**
230
- > 它包含:① AI Agent 浏览器探索工作流(必须用 Playwright MCP 抓包验证 API)② 认证策略决策树 ③ 平台 SDK(如 Bilibili 的 `apiGet`/`fetchJson`)④ YAML vs TS 选择指南 ⑤ `tap` 步骤调试方法 ⑥ 级联请求模板 ⑦ 常见陷阱表。
230
+ > 它包含:① AI Agent 浏览器探索工作流 认证策略决策树 ③ 平台 SDK(如 Bilibili 的 `apiGet`/`fetchJson`)④ YAML vs TS 选择指南 ⑤ `tap` 步骤调试方法 ⑥ 级联请求模板 ⑦ 常见陷阱表。
231
231
  > **下方仅为简化模板参考,直接使用极易踩坑。**
232
232
 
233
233
  ### YAML Pipeline (declarative, recommended)
@@ -374,16 +374,18 @@ ${{ index + 1 }}
374
374
 
375
375
  | Variable | Default | Description |
376
376
  |----------|---------|-------------|
377
+ | `OPENCLI_DAEMON_PORT` | 19825 | Daemon listen port |
377
378
  | `OPENCLI_BROWSER_CONNECT_TIMEOUT` | 30 | Browser connection timeout (sec) |
378
379
  | `OPENCLI_BROWSER_COMMAND_TIMEOUT` | 45 | Command execution timeout (sec) |
379
380
  | `OPENCLI_BROWSER_EXPLORE_TIMEOUT` | 120 | Explore timeout (sec) |
380
- | `PLAYWRIGHT_MCP_EXTENSION_TOKEN` | — | Auto-approve extension connection |
381
+ | `OPENCLI_VERBOSE` | — | Show daemon/extension logs |
381
382
 
382
383
  ## Troubleshooting
383
384
 
384
385
  | Issue | Solution |
385
386
  |-------|----------|
386
387
  | `npx not found` | Install Node.js: `brew install node` |
387
- | `Timed out connecting to browser` | 1) Chrome must be open 2) Install MCP Bridge extension and configure token |
388
+ | `Extension not connected` | 1) Chrome must be open 2) Install opencli Browser Bridge extension |
388
389
  | `Target page context` error | Add `navigate:` step before `evaluate:` in YAML |
389
- | Empty table data | Check if evaluate returns JSON string (MCP parsing) or data path is wrong |
390
+ | Empty table data | Check if evaluate returns correct data path |
391
+ | Daemon issues | `curl localhost:19825/status` to check, `curl localhost:19825/logs` for extension logs |
package/TESTING.md CHANGED
@@ -105,10 +105,10 @@ npx vitest src/
105
105
 
106
106
  ### 浏览器命令本地测试须知
107
107
 
108
- - `PLAYWRIGHT_MCP_EXTENSION_TOKEN` 时,opencli 自动启动一个独立浏览器实例
108
+ - opencli 通过 Browser Bridge 扩展连接已运行的 Chrome 浏览器
109
109
  - `browser-public.test.ts` 使用 `tryBrowserCommand()`,站点反爬导致空数据时 warn + pass
110
110
  - `browser-auth.test.ts` 验证 **graceful failure**(不 crash 不 hang 即通过)
111
- - 如需测试完整登录态,保持 Chrome 登录态 + 设置 `PLAYWRIGHT_MCP_EXTENSION_TOKEN`,手动跑对应测试
111
+ - 如需测试完整登录态,保持 Chrome 登录态并安装 Browser Bridge 扩展,手动跑对应测试
112
112
 
113
113
  ---
114
114
 
@@ -202,12 +202,12 @@ steps:
202
202
 
203
203
  ## 浏览器模式
204
204
 
205
- opencli 根据 `PLAYWRIGHT_MCP_EXTENSION_TOKEN` 环境变量自动选择模式:
205
+ opencli 通过 Browser Bridge 扩展连接浏览器:
206
206
 
207
- | 条件 | 模式 | MCP 参数 | 使用场景 |
208
- |---|---|---|---|
209
- | Token 已设置 | Extension 模式 | `--extension` | 本地用户,连接已登录的 Chrome |
210
- | Token 未设置 | Standalone 模式 | (无特殊 flag) | CI 或无扩展环境,自启浏览器 |
207
+ | 条件 | 模式 | 使用场景 |
208
+ |---|---|---|
209
+ | 扩展已安装 | Extension 模式 | 本地用户,连接已登录的 Chrome |
210
+ | 扩展未安装 | CLI 报错提示安装 | 需要安装 Browser Bridge 扩展 |
211
211
 
212
212
  CI 中使用 `OPENCLI_BROWSER_EXECUTABLE_PATH` 指定真实 Chrome 路径:
213
213
 
@@ -0,0 +1,37 @@
1
+ /**
2
+ * HTTP client for communicating with the opencli daemon.
3
+ *
4
+ * Provides a typed send() function that posts a Command and returns a Result.
5
+ */
6
+ export interface DaemonCommand {
7
+ id: string;
8
+ action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot';
9
+ tabId?: number;
10
+ code?: string;
11
+ url?: string;
12
+ op?: string;
13
+ index?: number;
14
+ domain?: string;
15
+ format?: 'png' | 'jpeg';
16
+ quality?: number;
17
+ fullPage?: boolean;
18
+ }
19
+ export interface DaemonResult {
20
+ id: string;
21
+ ok: boolean;
22
+ data?: unknown;
23
+ error?: string;
24
+ }
25
+ /**
26
+ * Check if daemon is running.
27
+ */
28
+ export declare function isDaemonRunning(): Promise<boolean>;
29
+ /**
30
+ * Check if daemon is running AND the extension is connected.
31
+ */
32
+ export declare function isExtensionConnected(): Promise<boolean>;
33
+ /**
34
+ * Send a command to the daemon and wait for a result.
35
+ * Retries up to 3 times with 500ms delay for transient failures.
36
+ */
37
+ export declare function sendCommand(action: DaemonCommand['action'], params?: Omit<DaemonCommand, 'id' | 'action'>): Promise<unknown>;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * HTTP client for communicating with the opencli daemon.
3
+ *
4
+ * Provides a typed send() function that posts a Command and returns a Result.
5
+ */
6
+ const DAEMON_PORT = parseInt(process.env.OPENCLI_DAEMON_PORT ?? '19825', 10);
7
+ const DAEMON_URL = `http://127.0.0.1:${DAEMON_PORT}`;
8
+ let _idCounter = 0;
9
+ function generateId() {
10
+ return `cmd_${Date.now()}_${++_idCounter}`;
11
+ }
12
+ /**
13
+ * Check if daemon is running.
14
+ */
15
+ export async function isDaemonRunning() {
16
+ try {
17
+ const controller = new AbortController();
18
+ const timer = setTimeout(() => controller.abort(), 2000);
19
+ const res = await fetch(`${DAEMON_URL}/status`, { signal: controller.signal });
20
+ clearTimeout(timer);
21
+ return res.ok;
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ }
27
+ /**
28
+ * Check if daemon is running AND the extension is connected.
29
+ */
30
+ export async function isExtensionConnected() {
31
+ try {
32
+ const controller = new AbortController();
33
+ const timer = setTimeout(() => controller.abort(), 2000);
34
+ const res = await fetch(`${DAEMON_URL}/status`, { signal: controller.signal });
35
+ clearTimeout(timer);
36
+ if (!res.ok)
37
+ return false;
38
+ const data = await res.json();
39
+ return !!data.extensionConnected;
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ /**
46
+ * Send a command to the daemon and wait for a result.
47
+ * Retries up to 3 times with 500ms delay for transient failures.
48
+ */
49
+ export async function sendCommand(action, params = {}) {
50
+ const id = generateId();
51
+ const command = { id, action, ...params };
52
+ const maxRetries = 3;
53
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
54
+ try {
55
+ const controller = new AbortController();
56
+ const timer = setTimeout(() => controller.abort(), 30000);
57
+ const res = await fetch(`${DAEMON_URL}/command`, {
58
+ method: 'POST',
59
+ headers: { 'Content-Type': 'application/json' },
60
+ body: JSON.stringify(command),
61
+ signal: controller.signal,
62
+ });
63
+ clearTimeout(timer);
64
+ const result = (await res.json());
65
+ if (!result.ok) {
66
+ throw new Error(result.error ?? 'Daemon command failed');
67
+ }
68
+ return result.data;
69
+ }
70
+ catch (err) {
71
+ const isRetryable = err instanceof TypeError // fetch network error
72
+ || (err instanceof Error && err.name === 'AbortError');
73
+ if (isRetryable && attempt < maxRetries) {
74
+ await new Promise(r => setTimeout(r, 500));
75
+ continue;
76
+ }
77
+ throw err;
78
+ }
79
+ }
80
+ // Unreachable — the loop always returns or throws
81
+ throw new Error('sendCommand: max retries exhausted');
82
+ }
@@ -1,38 +1,15 @@
1
1
  /**
2
- * MCP server path discovery and argument building.
2
+ * Daemon discovery — simplified from MCP server path discovery.
3
+ *
4
+ * Only needs to check if the daemon is running. No more file system
5
+ * scanning for @playwright/mcp locations.
3
6
  */
4
- import { execSync } from 'node:child_process';
5
- import * as fs from 'node:fs';
6
- export declare function resetMcpServerPathCache(): void;
7
- export declare function setMcpDiscoveryTestHooks(input?: {
8
- existsSync?: typeof fs.existsSync;
9
- execSync?: typeof execSync;
10
- }): void;
11
- export declare function findMcpServerPath(): string | null;
7
+ import { isDaemonRunning } from './daemon-client.js';
8
+ export { isDaemonRunning };
12
9
  /**
13
- * Chrome 144+ auto-discovery: read DevToolsActivePort file to get CDP endpoint.
14
- *
15
- * Starting with Chrome 144, users can enable remote debugging from
16
- * chrome://inspect#remote-debugging without any command-line flags.
17
- * Chrome writes the active port and browser GUID to a DevToolsActivePort file
18
- * in the user data directory, which we read to construct the WebSocket endpoint.
10
+ * Check daemon status and return connection info.
19
11
  */
20
- export declare function discoverChromeEndpoint(): string | null;
21
- export declare function resolveCdpEndpoint(): {
22
- endpoint?: string;
23
- requestedCdp: boolean;
24
- };
25
- export declare function buildMcpArgs(input: {
26
- mcpPath: string;
27
- executablePath?: string | null;
28
- cdpEndpoint?: string;
29
- }): string[];
30
- export declare function buildMcpLaunchSpec(input: {
31
- mcpPath?: string | null;
32
- executablePath?: string | null;
33
- cdpEndpoint?: string;
34
- }): {
35
- command: string;
36
- args: string[];
37
- usedNpxFallback: boolean;
38
- };
12
+ export declare function checkDaemonStatus(): Promise<{
13
+ running: boolean;
14
+ extensionConnected: boolean;
15
+ }>;