@sleepinsummer/agent-browser-cli 0.3.1-beta.1 → 0.3.1-beta.2

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 CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  所有重要变更都会记录在这里。日期使用北京时间自然日。
4
4
 
5
+ ## v0.3.1-beta.2 - 2026-05-17
6
+
7
+ ### 新增
8
+
9
+ - 新增多浏览器 / 多 Chrome Profile 会话隔离:扩展上报 `browser_id`、`profile_id`,daemon 内部使用 `session_key = browser_id:profile_id:tab_id` 路由。
10
+ - CLI 主要浏览器命令新增 `--browser` 和 `--profile`,支持按浏览器实例和 Profile 过滤/定位 tab。
11
+ - `tabs` 输出新增 `browser_id`、`profile_id`、`profile_label`、`tab_id`、`session_key`。
12
+ - `open` 新增 `--window`,支持新开独立 Chrome 窗口。
13
+ - `open` 新增 `--focus`,只有显式传入时才请求聚焦窗口。
14
+ - `open --window --group-title/--session` 支持对新窗口首个 tab 创建 Chrome tab group。
15
+
16
+ ### 调整
17
+
18
+ - `open` 返回结构改为以新打开目标为主:`opened_tab_id`、`opened_session_key`、`window_id`、`window`、`group`。旧执行通道移入 `metadata.executor`,避免 AI 误用旧 tab。
19
+ - daemon 在默认 session 失效时会回退到当前 active session,避免重启后卡在旧 `session_key`。
20
+ - `snapshot`、`@e` 缓存、调试缓存、截图/PDF、network/console 等路径统一按 `session_key` 隔离。
21
+ - skill 文档补充多 Profile、多浏览器、`open --window`、`--focus` 和 `opened_tab_id` 使用说明。
22
+
23
+ ### 验证
24
+
25
+ - 已覆盖真实 Chrome 场景:多 Profile 字段上报、`tabs --profile`、`exec/scan/snapshot/click/screenshot/save-pdf/network/console --profile --tab`、`open` tab/window/background/focus/group/session 组合、关闭测试 tab。
26
+ - 已执行 `cargo fmt --check`、`cargo check`、`cargo build`、`cargo test`、`node --check`、`npm pack --dry-run`。
27
+
5
28
  ## v0.3.1-beta.1 - 2026-05-16
6
29
 
7
30
  ### 新增
@@ -16,7 +39,7 @@
16
39
  - 新增 `save-pdf`:支持纸张、横向、缩放、打印背景、默认文件名清理和 50MB 上限。
17
40
  - 新增 `network` 调试命令:`start`、`list`、`detail`、`clear`、`stop`。
18
41
  - 新增 `console` 调试命令:`start`、`list`、`clear`、`stop`。
19
- - `open 新增 `--session` 和 `--group-title`,支持 Chrome 原生 tab group。
42
+ - `open` 新增 `--session` 和 `--group-title`,支持 Chrome 原生 tab group。
20
43
  - 新增 `close --tab <tabId>`,通过扩展原生 `chrome.tabs.remove` 关闭标签页。
21
44
  - Chrome 扩展新增 bot 图标,显示名改为 `Agent Browser CLI Bridge`。
22
45
  - daemon 退出时清理 daemon 缓存,并通知扩展清理 network/console 调试缓存。
@@ -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
- ws.send(JSON.stringify({
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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleepinsummer/agent-browser-cli",
3
- "version": "0.3.1-beta.1",
3
+ "version": "0.3.1-beta.2",
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-beta.1",
28
- "@sleepinsummer/agent-browser-cli-darwin-x64": "0.3.1-beta.1",
29
- "@sleepinsummer/agent-browser-cli-linux-x64": "0.3.1-beta.1",
30
- "@sleepinsummer/agent-browser-cli-linux-arm64": "0.3.1-beta.1",
31
- "@sleepinsummer/agent-browser-cli-win32-x64": "0.3.1-beta.1"
27
+ "@sleepinsummer/agent-browser-cli-darwin-arm64": "0.3.1-beta.2",
28
+ "@sleepinsummer/agent-browser-cli-darwin-x64": "0.3.1-beta.2",
29
+ "@sleepinsummer/agent-browser-cli-linux-x64": "0.3.1-beta.2",
30
+ "@sleepinsummer/agent-browser-cli-linux-arm64": "0.3.1-beta.2",
31
+ "@sleepinsummer/agent-browser-cli-win32-x64": "0.3.1-beta.2"
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>`;`@e` 只在当前 daemon、当前 tab、最近一次 `snapshot` 内有效。`@e` 只接受 `@e1` 这种带 `@` 的格式。
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 原生标签组。分组只是整理浏览器标签,失败不影响开 tab 主流程。
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 close --tab <tabId> --group-title "任务A"
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`。