@sleepinsummer/agent-browser-cli 0.2.4 → 0.2.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/AI_INSTALL.md CHANGED
@@ -7,11 +7,12 @@
7
7
 
8
8
  要求:
9
9
  1. 优先使用 npm 安装:npm install -g @sleepinsummer/agent-browser-cli。
10
- 2. 指导我在 Chrome 中加载 assets/tmwd_cdp_bridge 解压扩展。
11
- 3. 如果之前已经加载过扩展,必须在 chrome://extensions 里重新加载 `assets/tmwd_cdp_bridge`,确保最新 `config.js` `background.js` 生效。
12
- 4. skills/agent-browser-cli/SKILL.md 安装到当前 AI 可识别的 skills 目录。
13
- 5. 执行 agent-browser-cli tabs、open status 验证可用。
14
- 6. 如果 npm 平台包暂不支持当前系统,再回退到源码构建:cargo build --release。
10
+ 2. 先询问我希望把 Chrome 扩展解压到哪个本地目录。
11
+ 3. GitHub 最新 Release 下载 `chrome-extensions.zip`,解压到我指定的目录,并指导我在 Chrome 中加载解压后的 `tmwd_cdp_bridge` 扩展目录。
12
+ 4. 如果之前已经加载过扩展,必须在 chrome://extensions 里重新加载该扩展,确保最新 `config.js`、`content.js` `background.js` 生效。
13
+ 5. skills/agent-browser-cli/SKILL.md 安装到当前 AI 可识别的 skills 目录。
14
+ 6. 执行 agent-browser-cli tabs、open status 验证可用。
15
+ 7. 如果 npm 平台包暂不支持当前系统,再回退到源码构建:cargo build --release。
15
16
  ```
16
17
 
17
18
  ## 1. 安装 CLI
@@ -29,9 +30,20 @@ agent-browser-cli --help
29
30
  @sleepinsummer/agent-browser-cli
30
31
  @sleepinsummer/agent-browser-cli-darwin-arm64
31
32
  @sleepinsummer/agent-browser-cli-darwin-x64
33
+ @sleepinsummer/agent-browser-cli-linux-x64
32
34
  @sleepinsummer/agent-browser-cli-win32-x64
33
35
  ```
34
36
 
37
+ Linux 使用前请确认本机 Chrome / Chromium 支持安装扩展。
38
+
39
+ 如果在 WSL 中使用,当前版本依赖 WSL 访问宿主机 `localhost` 上的 Chrome 桥接服务。建议环境:
40
+
41
+ ```text
42
+ WSL 2.0.0+
43
+ Windows 11 22H2+
44
+ .wslconfig 中启用 networkingMode=mirrored
45
+ ```
46
+
35
47
  如果当前平台包暂未发布或安装失败,使用源码构建:
36
48
 
37
49
  ```bash
@@ -43,11 +55,26 @@ cargo build --release
43
55
 
44
56
  ## 2. 加载 Chrome 扩展
45
57
 
46
- 如果使用 npm 安装,需要先下载或克隆仓库,用于加载扩展和安装 skill:
58
+ 先询问用户希望把扩展解压到哪个本地目录,例如:
59
+
60
+ ```text
61
+ 请告诉我 Chrome 扩展希望解压到哪个目录,例如 ~/agent-browser-cli-extension。
62
+ ```
63
+
64
+ 然后下载最新 Release 中的 `chrome-extensions.zip` 并解压到该目录。zip 解压后内部目录仍是 `tmwd_cdp_bridge`:
47
65
 
48
66
  ```bash
49
- git clone https://github.com/sleepinginsummer/agent-browser-cli.git
50
- cd agent-browser-cli
67
+ EXT_PARENT="$HOME/agent-browser-cli-extension"
68
+ mkdir -p "$EXT_PARENT"
69
+ ZIP_URL="$(curl -fsSL https://api.github.com/repos/sleepinginsummer/agent-browser-cli/releases/latest | grep -o '"browser_download_url": "[^"]*chrome-extensions.zip"' | head -n 1 | cut -d '"' -f 4)"
70
+ curl -fL "$ZIP_URL" -o "$EXT_PARENT/chrome-extensions.zip"
71
+ unzip -o "$EXT_PARENT/chrome-extensions.zip" -d "$EXT_PARENT"
72
+ ```
73
+
74
+ 解压后扩展目录应为:
75
+
76
+ ```text
77
+ $EXT_PARENT/tmwd_cdp_bridge
51
78
  ```
52
79
 
53
80
  在 Chrome 打开:
@@ -59,10 +86,10 @@ chrome://extensions
59
86
  开启“开发者模式”,加载已解压扩展目录:
60
87
 
61
88
  ```text
62
- assets/tmwd_cdp_bridge
89
+ $EXT_PARENT/tmwd_cdp_bridge
63
90
  ```
64
91
 
65
- 如果之前已经安装过旧版 GenericAgent 的 `tmwd_cdp_bridge` 扩展,可以继续使用同协议旧扩展;但建议加载当前仓库的 `assets/tmwd_cdp_bridge` 并点击“重新加载”。
92
+ 如果之前已经安装过旧版 GenericAgent 的 `tmwd_cdp_bridge` 扩展,可以继续使用同协议旧扩展;但建议加载最新 Release 解压出来的 `tmwd_cdp_bridge` 并点击“重新加载”。
66
93
 
67
94
  当前扩展配置应包含:
68
95
 
@@ -123,4 +150,3 @@ agent-browser-cli exec --tab <tabId> 'return document.title'
123
150
  ```text
124
151
  skills/agent-browser-cli/SKILL.md
125
152
  ```
126
-
package/README.md CHANGED
@@ -9,8 +9,8 @@
9
9
  <p>
10
10
  <a href="https://github.com/sleepinginsummer/agent-browser-cli"><img src="https://img.shields.io/badge/CLI-agentbrowsercli-2ea44f" alt="CLI agentbrowsercli"></a>
11
11
  <a href="https://github.com/sleepinginsummer/agent-browser-cli/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-green" alt="License MIT"></a>
12
- <a href="https://github.com/sleepinginsummer/agent-browser-cli"><img src="https://img.shields.io/badge/sys-win%2Fmac-0078D6?labelColor=0078D6&color=C0C0C0" alt="sys win/mac"></a>
13
- <a href="https://github.com/sleepinginsummer/agent-browser-cli/releases"><img src="https://img.shields.io/badge/release-v0.2.3-blue" alt="release v0.2.3"></a>
12
+ <a href="https://github.com/sleepinginsummer/agent-browser-cli"><img src="https://img.shields.io/badge/sys-win%2Fmac%2Flinux-0078D6?labelColor=0078D6&color=C0C0C0" alt="sys win/mac/linux"></a>
13
+ <a href="https://github.com/sleepinginsummer/agent-browser-cli/releases"><img src="https://img.shields.io/badge/release-v0.2.7-blue" alt="release v0.2.7"></a>
14
14
  <a href="https://github.com/sleepinginsummer/agent-browser-cli/pulls"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen" alt="PRs welcome"></a>
15
15
  </p>
16
16
 
@@ -26,9 +26,11 @@
26
26
 
27
27
  ## 项目信息
28
28
 
29
- - 当前版本:`0.2.3`
30
- - 支持平台:sys win/mac
31
- - 浏览器:Chrome / Chromium,需加载 `assets/tmwd_cdp_bridge`
29
+ - 当前版本:`0.2.7`
30
+ - 支持平台:Windows(包括 WSL)/ Mac / Linux
31
+ - 浏览器:Chrome,需加载拓展 `assets/tmwd_cdp_bridge`
32
+ - Linux 支持前提:本机 Chrome / Chromium 需要支持安装扩展
33
+ - WSL 支持前提:需使用 `WSL 2.0.0+`,并建议在 Windows `11 22H2+` 下启用 `networkingMode=mirrored`,以便 WSL 连接宿主机 `localhost` 上的 Chrome 桥接服务
32
34
 
33
35
  ## 致谢
34
36
 
@@ -110,7 +112,9 @@ cargo build --release
110
112
 
111
113
  ## Chrome 扩展
112
114
 
113
- 加载扩展目录:
115
+ 推荐从 [最新 Release](https://github.com/sleepinginsummer/agent-browser-cli/releases/latest) 下载 `chrome-extensions.zip`,下载后解压,Chrome 打开 `chrome://extensions`,开启“开发者模式”,点击“加载已解压的扩展程序”,选择解压后的 `tmwd_cdp_bridge` 目录。
116
+
117
+ 本地源码构建时,也可以直接加载扩展目录:
114
118
 
115
119
  ```text
116
120
  assets/tmwd_cdp_bridge
@@ -118,6 +122,8 @@ assets/tmwd_cdp_bridge
118
122
 
119
123
  Chrome 需要至少打开一个正常网页标签页,不要只停留在 `about:blank` 或 `chrome://` 页面。
120
124
 
125
+ 扩展连接后会在页面右侧显示 Chrome 插件提示角标。角标支持拖动位置,鼠标悬浮时展开;10 秒无命令后自动隐藏,也可以点击 `本次隐藏` 手动隐藏,本次服务连接周期内不再显示,约 300 秒服务断开并下次重连后恢复。
126
+
121
127
  ## 快速自检
122
128
 
123
129
  ```bash
@@ -195,6 +201,7 @@ rm -rf ~/.agents/skills/agent-browser-cli
195
201
  ## 友情链接
196
202
 
197
203
  - [LINUX DO - 新的理想型社区](https://linux.do/)
204
+ - [GenericAgent--复旦团队研发|仅仅~3K行代码 Self-Evolving Agent](https://github.com/lsdefine/GenericAgent/tree/main)
198
205
 
199
206
  ## 许可证
200
207
 
package/README_EN.md CHANGED
@@ -9,8 +9,8 @@ Browser perception · Page control · Chrome session reuse · CDP · Conditional
9
9
  <p>
10
10
  <a href="https://github.com/sleepinginsummer/agent-browser-cli"><img src="https://img.shields.io/badge/CLI-agentbrowsercli-2ea44f" alt="CLI agentbrowsercli"></a>
11
11
  <a href="https://github.com/sleepinginsummer/agent-browser-cli/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-green" alt="License MIT"></a>
12
- <a href="https://github.com/sleepinginsummer/agent-browser-cli"><img src="https://img.shields.io/badge/sys-win%2Fmac-0078D6?labelColor=0078D6&color=C0C0C0" alt="sys win/mac"></a>
13
- <a href="https://github.com/sleepinginsummer/agent-browser-cli/releases"><img src="https://img.shields.io/badge/release-v0.2.3-blue" alt="release v0.2.3"></a>
12
+ <a href="https://github.com/sleepinginsummer/agent-browser-cli"><img src="https://img.shields.io/badge/sys-win%2Fmac%2Flinux-0078D6?labelColor=0078D6&color=C0C0C0" alt="sys win/mac/linux"></a>
13
+ <a href="https://github.com/sleepinginsummer/agent-browser-cli/releases"><img src="https://img.shields.io/badge/release-v0.2.7-blue" alt="release v0.2.7"></a>
14
14
  <a href="https://github.com/sleepinginsummer/agent-browser-cli/pulls"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen" alt="PRs welcome"></a>
15
15
  </p>
16
16
 
@@ -26,9 +26,11 @@ This project is not Selenium or Playwright. It is better suited for helping agen
26
26
 
27
27
  ## Project Info
28
28
 
29
- - Current version: `0.2.3`
30
- - Supported platforms: sys win/mac
31
- - Browser: Chrome / Chromium, with `assets/tmwd_cdp_bridge` loaded
29
+ - Current version: `0.2.7`
30
+ - Supported platforms: Windows (including WSL) / Mac / Linux
31
+ - Browser: Chrome, with the `assets/tmwd_cdp_bridge` extension loaded
32
+ - Linux prerequisite: the local Chrome / Chromium build must support loading extensions
33
+ - WSL prerequisite: use `WSL 2.0.0+`, and preferably enable `networkingMode=mirrored` on Windows `11 22H2+` so WSL can reach the host Chrome bridge service on `localhost`
32
34
 
33
35
  ## Acknowledgements
34
36
 
@@ -110,7 +112,9 @@ cargo build --release
110
112
 
111
113
  ## Chrome Extension
112
114
 
113
- Load this extension directory:
115
+ Recommended: download `chrome-extensions.zip` from the [latest Release](https://github.com/sleepinginsummer/agent-browser-cli/releases/latest), extract it, open `chrome://extensions` in Chrome, enable `Developer mode`, click `Load unpacked`, and select the extracted `tmwd_cdp_bridge` directory.
116
+
117
+ When building from local source, you can also load this extension directory directly:
114
118
 
115
119
  ```text
116
120
  assets/tmwd_cdp_bridge
@@ -118,6 +122,8 @@ assets/tmwd_cdp_bridge
118
122
 
119
123
  Chrome needs at least one normal web page tab open. Do not leave it only on `about:blank` or `chrome://` pages.
120
124
 
125
+ After the extension is connected, a Chrome extension tip badge appears on the right side of the page. The badge position is draggable and expands on hover. It auto-hides after 10 seconds without commands, and you can also click `Hide for this session` to hide it manually. Manual hiding lasts for the current service connection cycle and resets after the service disconnects after about 300 seconds and reconnects.
126
+
121
127
  ## Quick Check
122
128
 
123
129
  ```bash
@@ -195,6 +201,7 @@ Finally, remove the `TMWD CDP Bridge` extension from Chrome's extension manageme
195
201
  ## Friendly Links
196
202
 
197
203
  - [LINUX DO - A New Ideal Community](https://linux.do/)
204
+ - [GenericAgent--复旦团队研发|仅仅~3K行代码 Self-Evolving Agent](https://github.com/lsdefine/GenericAgent/tree/main)
198
205
 
199
206
  ## License
200
207
 
@@ -15,8 +15,11 @@ chrome.runtime.onInstalled.addListener(() => {
15
15
  });
16
16
  });
17
17
 
18
+ let lastCommandAt = 0;
19
+
18
20
  async function handleExtMessage(msg, sender) {
19
21
  if (msg.cmd === 'status') return handleStatus();
22
+ lastCommandAt = Date.now();
20
23
  if (msg.cmd === 'cookies') return await handleCookies(msg, sender);
21
24
  if (msg.cmd === 'cdp') return await handleCDP(msg, sender);
22
25
  if (msg.cmd === 'batch') return await handleBatch(msg, sender);
@@ -75,7 +78,8 @@ function handleStatus() {
75
78
  ok: true,
76
79
  data: {
77
80
  wsConnected: !!ws && ws.readyState === WebSocket.OPEN,
78
- wsUrl: WS_URL
81
+ wsUrl: WS_URL,
82
+ lastCommandAt
79
83
  }
80
84
  };
81
85
  }
@@ -173,6 +177,20 @@ async function handleCDP(msg, sender) {
173
177
  // Filter out chrome:// and other internal tabs that can't be scripted
174
178
  const isScriptable = url => url && /^https?:/.test(url);
175
179
 
180
+ async function injectContentScriptsIntoExistingTabs() {
181
+ const tabs = (await chrome.tabs.query({})).filter(t => isScriptable(t.url));
182
+ for (const tab of tabs) {
183
+ try {
184
+ await chrome.scripting.executeScript({
185
+ target: { tabId: tab.id, allFrames: true },
186
+ files: ['config.js', 'content.js']
187
+ });
188
+ } catch (e) {
189
+ console.log('[TMWD-WS] Inject content script failed:', tab.id, e.message);
190
+ }
191
+ }
192
+ }
193
+
176
194
  // --- Shared page/CDP script builder core ---
177
195
  function buildExecScript(code, errorHandler) {
178
196
  return `(async () => {
@@ -380,6 +398,7 @@ function connectWS() {
380
398
  try {
381
399
  const data = JSON.parse(event.data);
382
400
  if (data.id && data.code) {
401
+ lastCommandAt = Date.now();
383
402
  let code = data.code;
384
403
  // If code is a JSON string representing an object, parse it
385
404
  if (typeof code === 'string') {
@@ -417,8 +436,15 @@ function connectWS() {
417
436
 
418
437
  // Initial connect + wake-up hooks
419
438
  connectWS();
420
- chrome.runtime.onStartup.addListener(() => connectWS());
421
- chrome.runtime.onInstalled.addListener(() => connectWS());
439
+ injectContentScriptsIntoExistingTabs();
440
+ chrome.runtime.onStartup.addListener(() => {
441
+ connectWS();
442
+ injectContentScriptsIntoExistingTabs();
443
+ });
444
+ chrome.runtime.onInstalled.addListener(() => {
445
+ connectWS();
446
+ injectContentScriptsIntoExistingTabs();
447
+ });
422
448
 
423
449
  // Sync tab list on changes
424
450
  async function sendTabsUpdate() {
@@ -1,27 +1,63 @@
1
1
  ;(function(){ if (/streamlit/i.test(document.title)) return;
2
+ if (window.__agentBrowserCliCleanup) window.__agentBrowserCliCleanup();
3
+ if (window.__agentBrowserCliObserverCleanup) window.__agentBrowserCliObserverCleanup();
4
+ document.querySelectorAll('#agent-browser-cli-ind,#agent-browser-cli-style').forEach(e => e.remove());
2
5
 
3
6
  // Remove meta CSP tags
4
7
  document.querySelectorAll('meta[http-equiv="Content-Security-Policy"]').forEach(e => e.remove());
5
8
 
6
9
  /**
7
- * Render a bottom-right badge that reflects the real bridge connection status.
10
+ * Render a right-side floating badge that reflects the real bridge connection status.
8
11
  */
9
12
  (function(){
10
13
  if(window.self!==window.top)return;
14
+ const s=document.createElement('style');
15
+ s.id='agent-browser-cli-style';
16
+ s.textContent='#agent-browser-cli-ind{position:fixed;top:40%;right:0;display:flex;align-items:center;gap:10px;width:218px;height:36px;box-sizing:border-box;padding:0 8px 0 9px;color:white;border-radius:18px 0 0 18px;font-size:11px;font-weight:bold;line-height:36px;z-index:99999;cursor:grab;box-shadow:0 4px 12px rgba(0,0,0,0.22);background:#4CAF50;opacity:.72;overflow:visible;white-space:nowrap;user-select:none;transform:translateX(190px);transition:transform .18s ease,opacity .18s ease;}#agent-browser-cli-ind::after{content:"";position:absolute;inset:0;border-radius:18px 0 0 18px;background:#4CAF50;z-index:-1;}#agent-browser-cli-dot{flex:0 0 auto;width:10px;height:10px;border-radius:999px;background:white;}#agent-browser-cli-label{flex:0 0 auto;max-width:150px;overflow:hidden;}#agent-browser-cli-ind[data-expanded="1"]{opacity:.92;transform:translateX(0);}#agent-browser-cli-ind[data-dragging="1"]{cursor:grabbing;transition:none;}#agent-browser-cli-close{position:relative;flex:0 0 auto;width:20px;height:20px;border-radius:999px;line-height:18px;text-align:center;font-size:15px;font-weight:bold;background:#1f7a33;color:white;opacity:0;pointer-events:none;cursor:pointer;}#agent-browser-cli-ind[data-expanded="1"] #agent-browser-cli-close{opacity:1;pointer-events:auto;}#agent-browser-cli-close:hover{background:#145523;}#agent-browser-cli-close::after{content:"本次隐藏";position:absolute;right:0;bottom:28px;padding:4px 7px;border-radius:4px;background:#1f2937;color:white;font-size:12px;font-weight:500;line-height:16px;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .12s ease,transform .12s ease;}#agent-browser-cli-close:hover::after{opacity:1;transform:translateY(0);}';
17
+ (document.head||document.documentElement).appendChild(s);
11
18
  const d=document.createElement('div');
12
19
  d.id='agent-browser-cli-ind';
13
- d.style.cssText='position:fixed;bottom:8px;right:8px;color:white;padding:4px 7px;border-radius:4px;font-size:11px;font-weight:bold;z-index:99999;cursor:pointer;box-shadow:0 2px 4px rgba(0,0,0,0.2);opacity:0.5;';
20
+ const dot=document.createElement('span');
21
+ dot.id='agent-browser-cli-dot';
22
+ const label=document.createElement('span');
23
+ label.id='agent-browser-cli-label';
24
+ label.textContent='agent_browser_cli: 已连接';
25
+ const close=document.createElement('span');
26
+ close.id='agent-browser-cli-close';
27
+ close.textContent='×';
28
+ d.appendChild(dot);
29
+ d.appendChild(label);
30
+ d.appendChild(close);
31
+ let collapseTimer = null;
32
+ let dragging = false;
33
+ let moved = false;
34
+ let dragOffsetY = 0;
35
+ let dismissed = false;
36
+ let wasConnected = false;
37
+ let lastSeenCommandAt = 0;
38
+ let lastTop = Math.round(window.innerHeight * 0.4);
39
+ d.style.top = lastTop + 'px';
14
40
  /**
15
41
  * Show the badge only when the bridge is really connected.
16
42
  */
17
- function setBadgeState(connected, detail) {
18
- // Hide the indicator completely when offline to avoid persistent page noise.
19
- d.style.display = connected ? 'block' : 'none';
20
- d.innerText = 'agent_browser_cli: 已连接';
21
- d.style.background = '#4CAF50';
43
+ function setBadgeState(connected, detail, lastCommandAt) {
44
+ // 手动关闭只在当前连接周期生效;断开后下次重新连接会再次显示。
45
+ if (connected && !wasConnected) dismissed = false;
46
+ wasConnected = connected;
47
+ const commandAt = Number(lastCommandAt) || 0;
48
+ if (commandAt > lastSeenCommandAt) lastSeenCommandAt = commandAt;
49
+ const activeRecently = lastSeenCommandAt > 0 && Date.now() - lastSeenCommandAt <= 10000;
50
+ d.style.display = connected && !dismissed && activeRecently ? 'flex' : 'none';
51
+ label.textContent = 'agent_browser_cli: 已连接';
22
52
  d.dataset.connected = connected ? '1' : '0';
23
53
  d.dataset.detail = detail || '';
24
54
  }
55
+ function setExpanded(expanded) {
56
+ d.dataset.expanded = expanded ? '1' : '0';
57
+ }
58
+ function clampTop(top) {
59
+ return Math.max(8, Math.min(window.innerHeight - d.offsetHeight - 8, top));
60
+ }
25
61
  /**
26
62
  * Poll background status and update the badge visibility.
27
63
  */
@@ -29,26 +65,70 @@ document.querySelectorAll('meta[http-equiv="Content-Security-Policy"]').forEach(
29
65
  try {
30
66
  const resp = await chrome.runtime.sendMessage({ cmd: 'status' });
31
67
  const connected = !!resp?.ok && !!resp?.data?.wsConnected;
32
- setBadgeState(connected, resp?.data?.wsUrl || '');
68
+ setBadgeState(connected, resp?.data?.wsUrl || '', resp?.data?.lastCommandAt);
33
69
  } catch (e) {
34
- setBadgeState(false, e.message || '');
70
+ setBadgeState(false, e.message || '', 0);
35
71
  }
36
72
  }
37
- d.addEventListener('click',()=>alert((d.dataset.connected === '1' ? '会话活跃' : '会话未连接') + '\nURL: ' + location.href + (d.dataset.detail ? '\nBridge: ' + d.dataset.detail : '')));
73
+ d.addEventListener('mouseenter', () => {
74
+ if (collapseTimer) clearTimeout(collapseTimer);
75
+ setExpanded(true);
76
+ });
77
+ d.addEventListener('mouseleave', () => {
78
+ if (collapseTimer) clearTimeout(collapseTimer);
79
+ setExpanded(false);
80
+ });
81
+ d.addEventListener('pointerdown', (e) => {
82
+ dragging = true;
83
+ moved = false;
84
+ dragOffsetY = e.clientY - d.getBoundingClientRect().top;
85
+ d.dataset.dragging = '1';
86
+ d.setPointerCapture(e.pointerId);
87
+ });
88
+ d.addEventListener('pointermove', (e) => {
89
+ if (!dragging) return;
90
+ const nextTop = clampTop(e.clientY - dragOffsetY);
91
+ if (Math.abs(nextTop - lastTop) > 2) moved = true;
92
+ lastTop = nextTop;
93
+ d.style.top = lastTop + 'px';
94
+ });
95
+ d.addEventListener('pointerup', (e) => {
96
+ dragging = false;
97
+ d.dataset.dragging = '0';
98
+ try { d.releasePointerCapture(e.pointerId); } catch (_) {}
99
+ });
100
+ close.addEventListener('pointerdown', (e) => { e.stopPropagation(); });
101
+ close.addEventListener('click', (e) => {
102
+ e.stopPropagation();
103
+ dismissed = true;
104
+ setExpanded(false);
105
+ d.style.display = 'none';
106
+ });
107
+ window.addEventListener('resize', () => {
108
+ lastTop = clampTop(lastTop);
109
+ d.style.top = lastTop + 'px';
110
+ });
38
111
  (document.body||document.documentElement).appendChild(d);
39
112
  setBadgeState(false, '');
40
113
  refreshBadgeState();
41
- setInterval(refreshBadgeState, 3000);
114
+ const refreshTimer = setInterval(refreshBadgeState, 3000);
115
+ window.__agentBrowserCliCleanup = () => {
116
+ clearInterval(refreshTimer);
117
+ d.remove();
118
+ s.remove();
119
+ };
42
120
  })();
43
121
 
44
- new MutationObserver(muts => {
122
+ const agentBrowserCliObserver = new MutationObserver(muts => {
45
123
  for (const m of muts) for (const n of m.addedNodes) {
46
124
  if (n.id === TID || (n.querySelector && n.querySelector('#' + TID))) {
47
125
  const el = n.id === TID ? n : n.querySelector('#' + TID);
48
126
  handle(el);
49
127
  }
50
128
  }
51
- }).observe(document.documentElement, { childList: true, subtree: true });
129
+ });
130
+ agentBrowserCliObserver.observe(document.documentElement, { childList: true, subtree: true });
131
+ window.__agentBrowserCliObserverCleanup = () => agentBrowserCliObserver.disconnect();
52
132
 
53
133
  /**
54
134
  * Consume page-side bridge requests and forward them to the extension background worker.
@@ -10,6 +10,7 @@ function platformPackageName() {
10
10
  if (platform === "darwin" && arch === "arm64") return "@sleepinsummer/agent-browser-cli-darwin-arm64";
11
11
  if (platform === "darwin" && arch === "x64") return "@sleepinsummer/agent-browser-cli-darwin-x64";
12
12
  if (platform === "linux" && arch === "x64") return "@sleepinsummer/agent-browser-cli-linux-x64";
13
+ if (platform === "linux" && arch === "arm64") return "@sleepinsummer/agent-browser-cli-linux-arm64";
13
14
  if (platform === "win32" && arch === "x64") return "@sleepinsummer/agent-browser-cli-win32-x64";
14
15
  throw new Error(`Unsupported platform: ${platform}-${arch}`);
15
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleepinsummer/agent-browser-cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.7",
4
4
  "description": "Agent-oriented browser sensing and control CLI backed by a native Rust daemon.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -21,10 +21,11 @@
21
21
  "postinstall": "node npm/postinstall.js"
22
22
  },
23
23
  "optionalDependencies": {
24
- "@sleepinsummer/agent-browser-cli-darwin-arm64": "0.2.4",
25
- "@sleepinsummer/agent-browser-cli-darwin-x64": "0.2.4",
26
- "@sleepinsummer/agent-browser-cli-linux-x64": "0.2.4",
27
- "@sleepinsummer/agent-browser-cli-win32-x64": "0.2.4"
24
+ "@sleepinsummer/agent-browser-cli-darwin-arm64": "0.2.7",
25
+ "@sleepinsummer/agent-browser-cli-darwin-x64": "0.2.7",
26
+ "@sleepinsummer/agent-browser-cli-linux-x64": "0.2.7",
27
+ "@sleepinsummer/agent-browser-cli-linux-arm64": "0.2.7",
28
+ "@sleepinsummer/agent-browser-cli-win32-x64": "0.2.7"
28
29
  },
29
30
  "engines": {
30
31
  "node": ">=18"