@optima-chat/browser-cli 0.5.5 → 0.5.7
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/.claude/skills/browser/SKILL.md +17 -27
- package/dist/index.js +21 -37
- package/package.json +1 -1
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: browser
|
|
3
|
-
description: "Browser automation
|
|
4
|
-
version: "1.
|
|
3
|
+
description: "Browser automation — controls real browsers (Chrome, ZiNiao/紫鸟) via browser-cli. MUST USE when user mentions: 紫鸟, ZiNiao, 反指纹浏览器, 店铺浏览器, TikTok Shop 后台操作, 多店铺管理, or needs to operate any logged-in platform. Also use for opening websites, filling forms, posting content, testing websites. Do NOT use for simple web scraping (use WebFetch)."
|
|
4
|
+
version: "1.1.0"
|
|
5
5
|
owner_repo: Optima-Chat/optima-browser-use
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# 浏览器自动化 Skill
|
|
9
9
|
|
|
10
|
+
**重要:本 Skill 可以直接控制紫鸟浏览器和 Chrome。当用户提到紫鸟、店铺、TikTok Shop 后台时,按下方"紫鸟浏览器"章节操作。**
|
|
11
|
+
|
|
10
12
|
## 使用场景
|
|
11
13
|
|
|
12
|
-
-
|
|
14
|
+
- 用户提到紫鸟浏览器、ZiNiao、反指纹浏览器、多店铺管理
|
|
15
|
+
- 用户要求操作 TikTok Shop 卖家后台、领星 ERP 等需要登录态的平台
|
|
16
|
+
- 用户要求打开网站或访问某个 URL
|
|
13
17
|
- 用户要求登录平台、填写表单或发布内容
|
|
14
|
-
- 用户需要测试网站功能
|
|
15
18
|
- 用户需要操作没有 API 的第三方平台
|
|
16
|
-
- 用户要求自动化浏览器交互
|
|
17
19
|
|
|
18
20
|
**不适用场景:**
|
|
19
21
|
- 简单网页抓取 → 使用 WebFetch
|
|
20
|
-
- 已有专用 skill 的任务(如 scout、tiktok、instagram、shein 等)
|
|
21
22
|
|
|
22
23
|
## 脚本优先原则
|
|
23
24
|
|
|
@@ -29,17 +30,13 @@ owner_repo: Optima-Chat/optima-browser-use
|
|
|
29
30
|
|
|
30
31
|
脚本执行零 token 消耗,比手动操作快 10 倍以上。
|
|
31
32
|
|
|
32
|
-
##
|
|
33
|
+
## 前提条件:Desktop 桌面应用
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
**Browser Skill 需要用户安装 Optima Browser Operator 桌面应用。** 所有浏览器操作都通过 Desktop app 控制用户本地的 Chrome 或紫鸟浏览器。
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|------|----------|------|
|
|
38
|
-
| **Desktop + 紫鸟** | 用户安装了 Desktop app 且配置了紫鸟 | 通过紫鸟反指纹浏览器操作,保留多店铺登录态 |
|
|
39
|
-
| **Desktop + Chrome** | 用户安装了 Desktop app | 通过用户本地 Chrome 操作 |
|
|
40
|
-
| **Cloud** | 无 Desktop app | 后端 headless Chromium,无登录态 |
|
|
37
|
+
如果 `browser-cli launch` 返回 `desktop_not_connected` 错误,提示用户:
|
|
41
38
|
|
|
42
|
-
|
|
39
|
+
> "需要安装 Optima Browser Operator 桌面应用才能使用浏览器功能。下载地址: https://github.com/Optima-Chat/optima-browser-use/releases"
|
|
43
40
|
|
|
44
41
|
### 紫鸟浏览器(跨境电商多店铺管理)
|
|
45
42
|
|
|
@@ -66,7 +63,7 @@ browser-cli launch --connector ziniao --ziniao-profile 27774259938707 --url http
|
|
|
66
63
|
**重要**:
|
|
67
64
|
- 用户说"迪士尼店铺"、"林总店铺"等 → 先 `ziniao profiles` 查列表,按名称模糊匹配找到 profile_id
|
|
68
65
|
- 用户说"打开紫鸟"但没指定店铺 → 先列出 profiles 让用户选
|
|
69
|
-
- 紫鸟需要 Desktop app
|
|
66
|
+
- 紫鸟需要 Desktop app 在线(紫鸟 WebDriver 会按需自动启动)
|
|
70
67
|
|
|
71
68
|
## 命令
|
|
72
69
|
|
|
@@ -224,22 +221,16 @@ browser-cli close
|
|
|
224
221
|
/mnt/efs/{userId}/images/... → 自动转换 ✓
|
|
225
222
|
```
|
|
226
223
|
|
|
227
|
-
##
|
|
228
|
-
|
|
229
|
-
当用户要求操作需要登录的平台(TikTok Shop、小红书、Instagram 等),需要用户的真实浏览器(有登录态)。
|
|
224
|
+
## Desktop 桌面应用未连接时
|
|
230
225
|
|
|
231
|
-
|
|
226
|
+
如果 `browser-cli launch` 返回错误,提示用户安装 Desktop app:
|
|
232
227
|
|
|
233
|
-
1.
|
|
228
|
+
1. 下载安装(Mac .dmg / Windows .exe):https://github.com/Optima-Chat/optima-browser-use/releases
|
|
234
229
|
2. 首次启动自动打开浏览器登录授权
|
|
235
|
-
3.
|
|
230
|
+
3. 授权后自动连接
|
|
236
231
|
|
|
237
232
|
**跨境电商用户(多店铺)**:推荐安装紫鸟浏览器 + Desktop app,可以按店铺 profile 分别操作,每个店铺独立登录态。
|
|
238
233
|
|
|
239
|
-
**备选方案:Chrome 扩展**
|
|
240
|
-
|
|
241
|
-
安装 Optima Browser Operator Chrome 扩展,直接用 Chrome 已登录的账号操作。
|
|
242
|
-
|
|
243
234
|
## 注意事项
|
|
244
235
|
|
|
245
236
|
- **脚本优先**:每次操作前先 `browser-cli scripts`,有脚本就用脚本
|
|
@@ -247,6 +238,5 @@ browser-cli close
|
|
|
247
238
|
- **避免不必要的截图**:截图消耗 token,日常导航用 DOM 输出即可
|
|
248
239
|
- **5 分钟超时**:无操作 5 分钟后会话自动关闭
|
|
249
240
|
- **务必关闭**:操作完成后运行 `browser-cli close` 释放资源
|
|
250
|
-
- **login_required 处理**:如果 runscript 返回 `login_required`
|
|
241
|
+
- **login_required 处理**:如果 runscript 返回 `login_required` 错误,说明该平台未登录。让用户在自己的浏览器里手动登录该平台,然后重新 `runscript`
|
|
251
242
|
- **Fallback 后更新脚本**:如果脚本频繁失败,重新生成并 submit-script 覆盖
|
|
252
|
-
- **Extension 模式**:标记了 `REQUIRES_USER_SESSION=True` 的脚本会自动使用用户的真实 Chrome(通过 Optima Browser Operator 扩展),未标记的脚本走 Chromium。这由后端自动判断,无需手动指定
|
package/dist/index.js
CHANGED
|
@@ -196,53 +196,38 @@ var BrowserAPI = class {
|
|
|
196
196
|
async getStatus(sessionId) {
|
|
197
197
|
return request(`/api/sessions/${sessionId}/status`);
|
|
198
198
|
}
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
/** Execute an action then fetch DOM state separately.
|
|
200
|
+
* Decoupled to prevent EventBus overflow on remote CDP tunnels. */
|
|
201
|
+
async actThenState(sessionId, path, body, timeout) {
|
|
202
|
+
await request(`/api/sessions/${sessionId}/${path}`, {
|
|
201
203
|
method: "POST",
|
|
202
|
-
body: JSON.stringify(
|
|
204
|
+
body: JSON.stringify(body)
|
|
203
205
|
});
|
|
206
|
+
return this.getState(sessionId);
|
|
207
|
+
}
|
|
208
|
+
async navigate(sessionId, url) {
|
|
209
|
+
return this.actThenState(sessionId, "navigate", { url });
|
|
204
210
|
}
|
|
205
211
|
async back(sessionId) {
|
|
206
|
-
return
|
|
207
|
-
method: "POST",
|
|
208
|
-
body: JSON.stringify({})
|
|
209
|
-
});
|
|
212
|
+
return this.actThenState(sessionId, "back", {});
|
|
210
213
|
}
|
|
211
214
|
async refresh(sessionId) {
|
|
212
|
-
return
|
|
213
|
-
method: "POST",
|
|
214
|
-
body: JSON.stringify({})
|
|
215
|
-
});
|
|
215
|
+
return this.actThenState(sessionId, "refresh", {});
|
|
216
216
|
}
|
|
217
217
|
async click(sessionId, index) {
|
|
218
|
-
return
|
|
219
|
-
method: "POST",
|
|
220
|
-
body: JSON.stringify({ index })
|
|
221
|
-
});
|
|
218
|
+
return this.actThenState(sessionId, "click", { index });
|
|
222
219
|
}
|
|
223
220
|
async input(sessionId, index, text, clear = true) {
|
|
224
|
-
return
|
|
225
|
-
method: "POST",
|
|
226
|
-
body: JSON.stringify({ index, text, clear })
|
|
227
|
-
});
|
|
221
|
+
return this.actThenState(sessionId, "input", { index, text, clear });
|
|
228
222
|
}
|
|
229
223
|
async scroll(sessionId, down, pages = 1) {
|
|
230
|
-
return
|
|
231
|
-
method: "POST",
|
|
232
|
-
body: JSON.stringify({ down, pages })
|
|
233
|
-
});
|
|
224
|
+
return this.actThenState(sessionId, "scroll", { down, pages });
|
|
234
225
|
}
|
|
235
226
|
async keys(sessionId, keys) {
|
|
236
|
-
return
|
|
237
|
-
method: "POST",
|
|
238
|
-
body: JSON.stringify({ keys })
|
|
239
|
-
});
|
|
227
|
+
return this.actThenState(sessionId, "keys", { keys });
|
|
240
228
|
}
|
|
241
229
|
async select(sessionId, index, text) {
|
|
242
|
-
return
|
|
243
|
-
method: "POST",
|
|
244
|
-
body: JSON.stringify({ index, text })
|
|
245
|
-
});
|
|
230
|
+
return this.actThenState(sessionId, "select", { index, text });
|
|
246
231
|
}
|
|
247
232
|
async getState(sessionId) {
|
|
248
233
|
return request(`/api/sessions/${sessionId}/state`);
|
|
@@ -266,22 +251,21 @@ var BrowserAPI = class {
|
|
|
266
251
|
return request(`/api/sessions/${sessionId}/tabs`);
|
|
267
252
|
}
|
|
268
253
|
async switchTab(sessionId, tabId) {
|
|
269
|
-
return
|
|
270
|
-
method: "POST",
|
|
271
|
-
body: JSON.stringify({ tab_id: tabId })
|
|
272
|
-
});
|
|
254
|
+
return this.actThenState(sessionId, "switch", { tab_id: tabId });
|
|
273
255
|
}
|
|
274
256
|
async closeTab(sessionId, tabId) {
|
|
275
|
-
|
|
257
|
+
await request(
|
|
276
258
|
`/api/sessions/${sessionId}/tabs/${tabId}`,
|
|
277
259
|
{ method: "DELETE" }
|
|
278
260
|
);
|
|
261
|
+
return this.getState(sessionId);
|
|
279
262
|
}
|
|
280
263
|
async uploadFiles(sessionId, index, filePaths) {
|
|
281
|
-
|
|
264
|
+
await request(`/api/sessions/${sessionId}/upload`, {
|
|
282
265
|
method: "POST",
|
|
283
266
|
body: JSON.stringify({ index, file_paths: filePaths })
|
|
284
267
|
});
|
|
268
|
+
return this.getState(sessionId);
|
|
285
269
|
}
|
|
286
270
|
// Script methods
|
|
287
271
|
async submitScript(name, code) {
|