@sleepinsummer/agent-browser-cli 0.3.1-beta.1 → 0.3.1
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/CHANGELOG.md +17 -7
- package/assets/tmwd_cdp_bridge/background.js +37 -6
- package/assets/tmwd_cdp_bridge/icons/bot-128.png +0 -0
- package/assets/tmwd_cdp_bridge/icons/bot-16.png +0 -0
- package/assets/tmwd_cdp_bridge/icons/bot-32.png +0 -0
- package/assets/tmwd_cdp_bridge/icons/bot-48.png +0 -0
- package/package.json +6 -6
- package/skills/agent-browser-cli/SKILL.md +12 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
所有重要变更都会记录在这里。日期使用北京时间自然日。
|
|
4
4
|
|
|
5
|
-
## v0.3.1
|
|
5
|
+
## v0.3.1 - 2026-05-17
|
|
6
6
|
|
|
7
7
|
### 新增
|
|
8
8
|
|
|
@@ -11,27 +11,37 @@
|
|
|
11
11
|
- 新增 `install-skill`:支持 `--dry-run` 和 `--yes`,用于安装/更新 Agent skill。
|
|
12
12
|
- 增强 `status`:新增 `healthy`、`summary`、`message`,保留旧字段。
|
|
13
13
|
- 新增 `snapshot`:基于 Chrome Accessibility Tree 生成 `@e` 操作引用,支持 `--offset`、`--limit`、`--details`、`--tab`。
|
|
14
|
-
- 新增高层操作命令:`click`、`fill`、`send-keys`、`mouse-click`。
|
|
14
|
+
- 新增高层操作命令:`click`、`fill`、`send-keys`、`mouse-click`,支持 `--monitor`、`--wait-js`、`--wait-timeout`。
|
|
15
15
|
- 新增 `screenshot`:支持视口截图、全页截图、元素截图、PNG/JPEG、默认落盘目录。
|
|
16
16
|
- 新增 `save-pdf`:支持纸张、横向、缩放、打印背景、默认文件名清理和 50MB 上限。
|
|
17
17
|
- 新增 `network` 调试命令:`start`、`list`、`detail`、`clear`、`stop`。
|
|
18
18
|
- 新增 `console` 调试命令:`start`、`list`、`clear`、`stop`。
|
|
19
|
-
-
|
|
19
|
+
- 新增多浏览器 / 多 Chrome Profile 会话隔离:扩展上报 `browser_id`、`profile_id`、`profile_label`,daemon 内部使用 `session_key = browser_id:profile_id:tab_id` 路由。
|
|
20
|
+
- CLI 主要浏览器命令新增 `--browser` 和 `--profile`,支持按浏览器实例和 Profile 过滤/定位 tab。
|
|
21
|
+
- `tabs` 输出新增 `browser_id`、`profile_id`、`profile_label`、`tab_id`、`session_key`。
|
|
22
|
+
- `open` 新增 `--session` 和 `--group-title`,支持 Chrome 原生 tab group。
|
|
23
|
+
- `open` 新增 `--window`,支持新开独立 Chrome 窗口。
|
|
24
|
+
- `open` 新增 `--focus`,只有显式传入时才请求聚焦窗口。
|
|
25
|
+
- `open --window --group-title/--session` 支持对新窗口首个 tab 创建 Chrome tab group。
|
|
20
26
|
- 新增 `close --tab <tabId>`,通过扩展原生 `chrome.tabs.remove` 关闭标签页。
|
|
21
|
-
- Chrome
|
|
22
|
-
- daemon 退出时清理 daemon 缓存,并通知扩展清理 network/console 调试缓存。
|
|
27
|
+
- Chrome 扩展新增图标,显示名改为 `Agent Browser CLI Bridge`。
|
|
23
28
|
|
|
24
29
|
### 调整
|
|
25
30
|
|
|
31
|
+
- `open` 返回结构改为以新打开目标为主:`opened_tab_id`、`opened_session_key`、`window_id`、`window`、`group`。旧执行通道移入 `metadata.executor`,避免 AI 误用旧 tab。
|
|
32
|
+
- daemon 在默认 session 失效时会回退到当前 active session,避免重启后卡在旧 `session_key`。
|
|
33
|
+
- `snapshot`、`@e` 缓存、调试缓存、截图/PDF、network/console 等路径统一按 `session_key` 隔离。
|
|
26
34
|
- daemon stdout/stderr 日志固定写入用户目录,不再落到当前目录或 npm 包目录。
|
|
27
35
|
- npm wrapper 设置 `AGENT_BROWSER_CLI_PACKAGE_DIR`,方便全局安装后定位内置 skill。
|
|
28
36
|
- `network stop` / `console stop` 会停止监听并清理对应缓存。
|
|
29
|
-
-
|
|
37
|
+
- daemon 退出时清理 daemon 缓存,并通知扩展清理 network/console 调试缓存。
|
|
38
|
+
- skill 文档重写为 Agent 操作 SOP,明确 `scan`、`snapshot`、`exec/CDP` 的职责边界,并补充多 Profile、多浏览器、`open --window`、`--focus` 和 `opened_tab_id` 使用说明。
|
|
30
39
|
|
|
31
40
|
### 验证
|
|
32
41
|
|
|
33
42
|
- 已覆盖真实 Chrome 场景:百度搜索、页面扫描、DOM 定位、输入/点击、截图、PDF、network/console 监听、缓存清理、tab group、关闭测试 tab。
|
|
34
|
-
-
|
|
43
|
+
- 已覆盖多 Profile 字段上报、`tabs --profile`、`tabs --browser --profile`、`exec/scan/snapshot/click/fill/send-keys/mouse-click/screenshot/save-pdf/network/console --profile --tab`、`open` tab/window/background/focus/group/session 组合。
|
|
44
|
+
- 已执行 `cargo fmt --check`、`cargo check`、`cargo build`、`cargo test`、`node --check`、`npm pack --dry-run`。
|
|
35
45
|
|
|
36
46
|
## v0.2.10-extension - 2026-05-15
|
|
37
47
|
|
|
@@ -19,6 +19,25 @@ let lastCommandAt = 0;
|
|
|
19
19
|
const DEFAULT_WS_PORT = 18765;
|
|
20
20
|
const CLI_API_PORT = 18767;
|
|
21
21
|
let wsPort = DEFAULT_WS_PORT;
|
|
22
|
+
const browserId = `browser-${crypto.randomUUID()}`;
|
|
23
|
+
let profileId = null;
|
|
24
|
+
let profileLabel = null;
|
|
25
|
+
|
|
26
|
+
async function loadClientIdentity() {
|
|
27
|
+
const data = await chrome.storage.local.get({ profileId: null, profileLabel: null });
|
|
28
|
+
profileId = data.profileId || `profile-${crypto.randomUUID()}`;
|
|
29
|
+
profileLabel = data.profileLabel || null;
|
|
30
|
+
if (!data.profileId) await chrome.storage.local.set({ profileId });
|
|
31
|
+
return { browserId, profileId, profileLabel };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function withClientIdentity(payload) {
|
|
35
|
+
return Object.assign({
|
|
36
|
+
browser_id: browserId,
|
|
37
|
+
profile_id: profileId || 'profile-pending',
|
|
38
|
+
profile_label: profileLabel || undefined
|
|
39
|
+
}, payload);
|
|
40
|
+
}
|
|
22
41
|
|
|
23
42
|
async function handleExtMessage(msg, sender) {
|
|
24
43
|
if (msg.cmd === 'status') return handleStatus();
|
|
@@ -96,7 +115,10 @@ function handleStatus() {
|
|
|
96
115
|
wsConnected: !!ws && ws.readyState === WebSocket.OPEN,
|
|
97
116
|
wsUrl: getWsUrl(),
|
|
98
117
|
wsPort,
|
|
99
|
-
lastCommandAt
|
|
118
|
+
lastCommandAt,
|
|
119
|
+
browserId,
|
|
120
|
+
profileId,
|
|
121
|
+
profileLabel
|
|
100
122
|
}
|
|
101
123
|
};
|
|
102
124
|
}
|
|
@@ -479,11 +501,18 @@ async function handleOpenTab(msg) {
|
|
|
479
501
|
try {
|
|
480
502
|
const url = normalizeOpenUrl(msg.url);
|
|
481
503
|
const active = msg.active !== false;
|
|
504
|
+
if (msg.window === true) {
|
|
505
|
+
// window 模式默认不聚焦,避免新窗口打断用户当前工作区。
|
|
506
|
+
const win = await chrome.windows.create({ url, focused: msg.allowFocus === true });
|
|
507
|
+
const tab = Array.isArray(win.tabs) && win.tabs.length ? win.tabs[0] : null;
|
|
508
|
+
const group = tab?.id ? await groupTabIfRequested(tab.id, msg.groupTitle) : { ok: false, skipped: true, reason: 'window created without tab info' };
|
|
509
|
+
return { ok: true, data: { id: tab?.id, url: tab?.url || url, title: tab?.title || '', active: !!tab?.active, windowId: win.id, window: true, group } };
|
|
510
|
+
}
|
|
482
511
|
const tab = await chrome.tabs.create({ url, active });
|
|
483
512
|
const group = await groupTabIfRequested(tab.id, msg.groupTitle);
|
|
484
513
|
// 默认创建/激活标签页但不聚焦浏览器窗口,避免打断当前工作区。
|
|
485
514
|
if (active && msg.allowFocus === true && tab.windowId) await chrome.windows.update(tab.windowId, { focused: true });
|
|
486
|
-
return { ok: true, data: { id: tab.id, url: tab.url || url, title: tab.title || '', active: tab.active, windowId: tab.windowId, group } };
|
|
515
|
+
return { ok: true, data: { id: tab.id, url: tab.url || url, title: tab.title || '', active: tab.active, windowId: tab.windowId, window: false, group } };
|
|
487
516
|
} catch (e) {
|
|
488
517
|
return { ok: false, error: e.message };
|
|
489
518
|
}
|
|
@@ -818,11 +847,12 @@ async function connectWS() {
|
|
|
818
847
|
ws.onopen = async () => {
|
|
819
848
|
console.log('[TMWD-WS] Connected!');
|
|
820
849
|
scheduleKeepalive(); // Keep SW alive while connected
|
|
850
|
+
await loadClientIdentity();
|
|
821
851
|
const tabs = (await chrome.tabs.query({})).filter(t => isScriptable(t.url));
|
|
822
|
-
ws.send(JSON.stringify({
|
|
852
|
+
ws.send(JSON.stringify(withClientIdentity({
|
|
823
853
|
type: 'ext_ready',
|
|
824
854
|
tabs: tabs.map(t => ({ id: t.id, url: t.url, title: t.title }))
|
|
825
|
-
}));
|
|
855
|
+
})));
|
|
826
856
|
console.log('[TMWD-WS] Sent ext_ready with', tabs.length, 'tabs');
|
|
827
857
|
};
|
|
828
858
|
ws.onmessage = async (event) => {
|
|
@@ -891,10 +921,11 @@ chrome.runtime.onInstalled.addListener(() => {
|
|
|
891
921
|
async function sendTabsUpdate() {
|
|
892
922
|
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
893
923
|
const tabs = (await chrome.tabs.query({})).filter(t => isScriptable(t.url) && !/streamlit/i.test(t.title));
|
|
894
|
-
|
|
924
|
+
await loadClientIdentity();
|
|
925
|
+
ws.send(JSON.stringify(withClientIdentity({
|
|
895
926
|
type: 'tabs_update',
|
|
896
927
|
tabs: tabs.map(t => ({ id: t.id, url: t.url, title: t.title }))
|
|
897
|
-
}));
|
|
928
|
+
})));
|
|
898
929
|
}
|
|
899
930
|
chrome.tabs.onUpdated.addListener((_, changeInfo) => {
|
|
900
931
|
if (changeInfo.status === 'complete') sendTabsUpdate();
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleepinsummer/agent-browser-cli",
|
|
3
|
-
"version": "0.3.1
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Agent-oriented browser sensing and control CLI backed by a native Rust daemon.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"postinstall": "node npm/postinstall.js"
|
|
25
25
|
},
|
|
26
26
|
"optionalDependencies": {
|
|
27
|
-
"@sleepinsummer/agent-browser-cli-darwin-arm64": "0.3.1
|
|
28
|
-
"@sleepinsummer/agent-browser-cli-darwin-x64": "0.3.1
|
|
29
|
-
"@sleepinsummer/agent-browser-cli-linux-x64": "0.3.1
|
|
30
|
-
"@sleepinsummer/agent-browser-cli-linux-arm64": "0.3.1
|
|
31
|
-
"@sleepinsummer/agent-browser-cli-win32-x64": "0.3.1
|
|
27
|
+
"@sleepinsummer/agent-browser-cli-darwin-arm64": "0.3.1",
|
|
28
|
+
"@sleepinsummer/agent-browser-cli-darwin-x64": "0.3.1",
|
|
29
|
+
"@sleepinsummer/agent-browser-cli-linux-x64": "0.3.1",
|
|
30
|
+
"@sleepinsummer/agent-browser-cli-linux-arm64": "0.3.1",
|
|
31
|
+
"@sleepinsummer/agent-browser-cli-win32-x64": "0.3.1"
|
|
32
32
|
},
|
|
33
33
|
"engines": {
|
|
34
34
|
"node": ">=18"
|
|
@@ -43,8 +43,13 @@ agent-browser-cli status
|
|
|
43
43
|
agent-browser-cli doctor
|
|
44
44
|
agent-browser-cli logs --tail 100
|
|
45
45
|
agent-browser-cli tabs
|
|
46
|
+
agent-browser-cli tabs --profile work
|
|
46
47
|
agent-browser-cli scan --tabs-only
|
|
47
|
-
agent-browser-cli scan --tab <tabId> --text-only
|
|
48
|
+
agent-browser-cli scan --profile work --tab <tabId> --text-only
|
|
49
|
+
agent-browser-cli open --profile work https://example.com
|
|
50
|
+
agent-browser-cli open --window https://example.com
|
|
51
|
+
agent-browser-cli open --window --focus https://example.com
|
|
52
|
+
# open 返回后继续操作新页面时,优先使用 result.opened_tab_id / result.opened_session_key
|
|
48
53
|
agent-browser-cli open https://example.com
|
|
49
54
|
agent-browser-cli close --tab <tabId>
|
|
50
55
|
agent-browser-cli exec --tab <tabId> 'return document.title'
|
|
@@ -76,7 +81,7 @@ agent-browser-cli send-keys --target '@e2' 'Enter'
|
|
|
76
81
|
agent-browser-cli mouse-click '@e3'
|
|
77
82
|
```
|
|
78
83
|
|
|
79
|
-
所有高层操作都支持 `--tab <tabId
|
|
84
|
+
所有高层操作都支持 `--tab <tabId>`,多 Chrome Profile / 多浏览器实例时还支持 `--profile <profile_id-or-label>` 和 `--browser <browser_id>`。`tabs` 输出会包含 `browser_id`、`profile_id`、`profile_label`、`tab_id`、`session_key`。只传 `--tab` 且存在歧义时,必须补 `--profile` 或 `--browser`,不要猜。`@e` 只在当前 daemon、当前 session_key、最近一次 `snapshot` 内有效。`@e` 只接受 `@e1` 这种带 `@` 的格式。
|
|
80
85
|
|
|
81
86
|
慢页面要把等待和监控分开:
|
|
82
87
|
|
|
@@ -139,12 +144,14 @@ agent-browser-cli console stop --tab <tabId>
|
|
|
139
144
|
|
|
140
145
|
## 标签分组
|
|
141
146
|
|
|
142
|
-
多任务开新标签时可以用 session 或 group-title 把标签放入 Chrome
|
|
147
|
+
多任务开新标签时可以用 session 或 group-title 把标签放入 Chrome 原生标签组。需要独立窗口时用 `open --window`;默认不聚焦,需要抢焦点时显式加 `--focus`;`--window --group-title` / `--window --session` 会把新窗口里的首个 tab 加入对应 tab group。分组只是整理浏览器标签,失败不影响开 tab 主流程。
|
|
143
148
|
|
|
144
149
|
```bash
|
|
145
150
|
agent-browser-cli open https://example.com --session research
|
|
146
|
-
agent-browser-cli open https://example.com
|
|
147
|
-
agent-browser-cli
|
|
151
|
+
agent-browser-cli open https://example.com --group-title "任务A"
|
|
152
|
+
agent-browser-cli open --window https://example.com
|
|
153
|
+
agent-browser-cli open --window --focus https://example.com
|
|
154
|
+
agent-browser-cli open --profile work https://example.com
|
|
148
155
|
```
|
|
149
156
|
|
|
150
157
|
`--session` 和 `--group-title` 都会作为标签组标题;两者同时传时优先使用 `--group-title`。
|