web-fetcher-mcp 1.0.14 → 1.0.16
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/README.md +108 -1
- package/dist/tools/list-tabs.d.ts.map +1 -1
- package/dist/tools/list-tabs.js.map +1 -1
- package/dist/tools/tab-manager.d.ts.map +1 -1
- package/dist/tools/tab-manager.js +5 -2
- package/dist/tools/tab-manager.js.map +1 -1
- package/dist/utils/browser.d.ts.map +1 -1
- package/dist/utils/browser.js +18 -3
- package/dist/utils/browser.js.map +1 -1
- package/dist/utils/tabs.d.ts +11 -2
- package/dist/utils/tabs.d.ts.map +1 -1
- package/dist/utils/tabs.js +156 -4
- package/dist/utils/tabs.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -199,7 +199,114 @@ npm install -g web-fetcher-mcp
|
|
|
199
199
|
|
|
200
200
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
201
201
|
|------|------|------|--------|------|
|
|
202
|
-
|
|
|
202
|
+
| url | string | 否 | 'current' | 网页 URL,使用 'current' 则操作当前已打开的页面 |
|
|
203
|
+
| selector | string | 是 | - | CSS 选择器,支持标准 CSS 选择器和 Playwright 文本选择器 |
|
|
204
|
+
| waitForNavigation | boolean | 否 | false | 点击后是否等待页面导航完成 |
|
|
205
|
+
| navigationTimeout | number | 否 | 10000 | 等待导航的超时时间(毫秒) |
|
|
206
|
+
| useExistingPage | boolean | 否 | true | 是否使用已存在的页面 |
|
|
207
|
+
|
|
208
|
+
#### 选择器使用技巧(重要!)
|
|
209
|
+
|
|
210
|
+
**1. 避免使用 `:has-text()`,用 `text=` 代替**
|
|
211
|
+
|
|
212
|
+
| 选择器 | 行为 | 风险 |
|
|
213
|
+
|--------|------|------|
|
|
214
|
+
| `:has-text("组件")` | 匹配**任意包含该文本的祖先元素** | 可能匹配到 `<html>`、`<body>` 等根元素,导致点击失效 |
|
|
215
|
+
| `text=组件` | 匹配**文本内容精确等于**"组件"的最窄元素 | 安全性高,命中意图元素 |
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
// ❌ 错误:可能点到 <html> 根元素
|
|
219
|
+
{ "selector": ":has-text(\"组件\")" }
|
|
220
|
+
|
|
221
|
+
// ✅ 正确:精确匹配文本
|
|
222
|
+
{ "selector": "text=组件" }
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**2. SPA 页面导航用 `a[href="..."]` 更可靠**
|
|
226
|
+
|
|
227
|
+
在 Vue Router、React Router 等 SPA 页面中,`text=文本` 触发的点击事件可能无法被路由框架正确拦截,导致导航失败。推荐使用**带具体 href 的属性选择器**:
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
// ❌ 点击了但 SPA 路由可能不响应
|
|
231
|
+
{ "selector": "text=组件" }
|
|
232
|
+
|
|
233
|
+
// ✅ 精准命中带路由能力的 <a> 标签,浏览器原生行为 + 路由框架双重保障
|
|
234
|
+
{ "selector": "a[href='/zh-CN/os-theme/components/modal']" }
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
> **原理**:SPA 的路由框架通常在 `<a>` 标签上绑定点击拦截。`text=` 可能命中 `<a>` 的父元素,事件传播路径不完整,导致路由不切换。`a[href="..."]` 直接命中 `<a>` 自身,事件必然被路由框架捕获。
|
|
238
|
+
|
|
239
|
+
**3. 导航点击记得加 `waitForNavigation`**
|
|
240
|
+
|
|
241
|
+
点击后如果期望页面跳转,建议设置 `waitForNavigation: true`:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"selector": "a[href='/target-page']",
|
|
246
|
+
"waitForNavigation": true,
|
|
247
|
+
"navigationTimeout": 10000
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 页面导航策略
|
|
254
|
+
|
|
255
|
+
MCP 提供了两套操作方式,使用时需要注意它们的区别:
|
|
256
|
+
|
|
257
|
+
### fetch-web-page(刷新式导航)
|
|
258
|
+
|
|
259
|
+
每次调用都会**重新加载页面**,适合首次访问或需要最新内容的场景。
|
|
260
|
+
|
|
261
|
+
- 每次请求都是全新的页面加载
|
|
262
|
+
- 之前的页面状态(滚动位置、表单输入、展开的菜单等)会丢失
|
|
263
|
+
- 首次访问 TAPD 等需要登录的页面时,推荐使用 `loginMode: "manual"`
|
|
264
|
+
|
|
265
|
+
### useExistingPage 工具(保持页面状态)
|
|
266
|
+
|
|
267
|
+
`get-page-info`、`click-element`、`scroll-page` 等工具支持 `useExistingPage: true`,**不会刷新页面**,保留当前页面的所有状态。
|
|
268
|
+
|
|
269
|
+
- 点击导航后,页面状态保持,如侧边栏展开状态、登录态等
|
|
270
|
+
- 适合多步交互操作:点击 → 获取内容 → 再点击 → 再获取
|
|
271
|
+
- `url: "current"` + `useExistingPage: true` 是标准组合
|
|
272
|
+
|
|
273
|
+
### 典型流程
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
1. fetch-web-page(url) → 首次加载页面(刷新)
|
|
277
|
+
2. click-element(selector) → 点击导航(不刷新,保持状态)
|
|
278
|
+
3. get-page-info(useExistingPage) → 获取导航后的内容(不刷新)
|
|
279
|
+
4. click-element(another) → 继续交互(不刷新)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
// 步骤 1:首次加载
|
|
284
|
+
{ "name": "fetch-web-page", "arguments": { "url": "https://example.com" } }
|
|
285
|
+
|
|
286
|
+
// 步骤 2:点击导航链接(不刷新)
|
|
287
|
+
{ "name": "click-element", "arguments": {
|
|
288
|
+
"url": "current",
|
|
289
|
+
"selector": "a[href='/page2']",
|
|
290
|
+
"waitForNavigation": true,
|
|
291
|
+
"useExistingPage": true
|
|
292
|
+
} }
|
|
293
|
+
|
|
294
|
+
// 步骤 3:获取导航后的页面内容(不刷新)
|
|
295
|
+
{ "name": "get-page-info", "arguments": {
|
|
296
|
+
"url": "current",
|
|
297
|
+
"useExistingPage": true,
|
|
298
|
+
"includeText": true
|
|
299
|
+
} }
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 常见踩坑
|
|
303
|
+
|
|
304
|
+
| 问题 | 原因 | 解决 |
|
|
305
|
+
|------|------|------|
|
|
306
|
+
| 点击导航后 `get-page-info` 内容没变 | 没加 `waitForNavigation: true` | 点击时设 `waitForNavigation: true` |
|
|
307
|
+
| `scroll-page` + `navigate-history` 并行执行报 Session closed | 导航进行中操作 DOM 冲突 | 顺序执行,导航完成后才能做其他操作 |
|
|
308
|
+
| `type-input` + `pressEnter: true` 报 context destroyed | 回车触发表单提交,页面跳转 | 确认不需要跳转时将 `pressEnter` 设为 `false` |
|
|
309
|
+
| `:has-text("X")` 点到了 `<html>` 根元素 | `:has-text()` 匹配任意包含该文本的祖先 | 改用 `text=X` 精确匹配 |
|
|
203
310
|
|
|
204
311
|
---
|
|
205
312
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-tabs.d.ts","sourceRoot":"","sources":["../../src/tools/list-tabs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"list-tabs.d.ts","sourceRoot":"","sources":["../../src/tools/list-tabs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAInD;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,CAsBxD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-tabs.js","sourceRoot":"","sources":["../../src/tools/list-tabs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"list-tabs.js","sourceRoot":"","sources":["../../src/tools/list-tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,IAAI,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEnE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,CAAC;QACH,MAAM,iBAAiB,GAAG,MAAM,UAAU,EAAE,CAAC;QAC7C,MAAM,EAAE,OAAO,EAAE,GAAG,iBAAiB,CAAC;QAEtC,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,IAAI,CAAC;QAE3D,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI;YACJ,WAAW;YACX,SAAS,EAAE,IAAI,CAAC,MAAM;SACvB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,CAAC,OAAO,IAAI,WAAW;YACnC,IAAI,EAAE,EAAE;YACR,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-manager.d.ts","sourceRoot":"","sources":["../../src/tools/tab-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIpE;;GAEG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"tab-manager.d.ts","sourceRoot":"","sources":["../../src/tools/tab-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIpE;;GAEG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAOvE;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAcrE"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { getBrowser } from '../utils/browser.js';
|
|
1
2
|
import { switchTab as switchTabInManager, closeTab as closeTabInManager, getActiveTabId } from '../utils/tabs.js';
|
|
2
3
|
/**
|
|
3
4
|
* 切换到指定标签页
|
|
4
5
|
*/
|
|
5
6
|
export async function switchTab(tabId) {
|
|
6
7
|
try {
|
|
7
|
-
|
|
8
|
+
const { browser } = await getBrowser();
|
|
9
|
+
return await switchTabInManager(tabId, browser);
|
|
8
10
|
}
|
|
9
11
|
catch (error) {
|
|
10
12
|
return { success: false, error: error.message };
|
|
@@ -15,7 +17,8 @@ export async function switchTab(tabId) {
|
|
|
15
17
|
*/
|
|
16
18
|
export async function closeTab(tabId) {
|
|
17
19
|
try {
|
|
18
|
-
const
|
|
20
|
+
const { browser } = await getBrowser();
|
|
21
|
+
const result = await closeTabInManager(tabId, browser);
|
|
19
22
|
if (result.success) {
|
|
20
23
|
return {
|
|
21
24
|
...result,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-manager.js","sourceRoot":"","sources":["../../src/tools/tab-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tab-manager.js","sourceRoot":"","sources":["../../src/tools/tab-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,SAAS,IAAI,kBAAkB,EAAE,QAAQ,IAAI,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa;IAC3C,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC;QACvC,OAAO,MAAM,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAClD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAa;IAC1C,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACvD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO;gBACL,GAAG,MAAM;gBACT,cAAc,EAAE,cAAc,EAAE;aACjC,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAClD,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/utils/browser.ts"],"names":[],"mappings":"AAAA,OAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/utils/browser.ts"],"names":[],"mappings":"AAAA,OAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAmBtD,wBAAsB,UAAU,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAkE7D;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,OAAO,EAC3B,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,OAAO,EAC3B,OAAO,CAAC,EAAE;IACR,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACA,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAExC;AAGD,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,QAAQ,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB1H"}
|
package/dist/utils/browser.js
CHANGED
|
@@ -2,7 +2,7 @@ import puppeteer from 'puppeteer';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { CHROME_PATH, DEBUGGING_PORT, USER_DATA_DIR, DATA_DIR } from './config.js';
|
|
4
4
|
import { setupBrowserConsoleCollector } from './console-logger.js';
|
|
5
|
-
import { getOrCreateTab, cleanupClosedTabs } from './tabs.js';
|
|
5
|
+
import { getOrCreateTab, cleanupClosedTabs, clearAllTabs } from './tabs.js';
|
|
6
6
|
// 确保数据目录存在
|
|
7
7
|
function ensureDataDir() {
|
|
8
8
|
if (!fs.existsSync(DATA_DIR)) {
|
|
@@ -12,12 +12,22 @@ function ensureDataDir() {
|
|
|
12
12
|
fs.mkdirSync(USER_DATA_DIR, { recursive: true });
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
// 浏览器实例缓存(避免每次工具调用都启动/连接新实例)
|
|
16
|
+
let cachedBrowser = null;
|
|
17
|
+
let cachedUseExisting = false;
|
|
15
18
|
// 连接到已有 Chrome 实例或启动新实例
|
|
16
19
|
export async function getBrowser() {
|
|
17
20
|
ensureDataDir();
|
|
18
21
|
// 先清理已关闭的标签页
|
|
19
22
|
cleanupClosedTabs();
|
|
20
|
-
//
|
|
23
|
+
// 如果已有缓存的浏览器实例且未断开,直接复用
|
|
24
|
+
if (cachedBrowser && cachedBrowser.isConnected()) {
|
|
25
|
+
console.error('复用缓存的浏览器实例');
|
|
26
|
+
return { browser: cachedBrowser, useExistingBrowser: cachedUseExisting };
|
|
27
|
+
}
|
|
28
|
+
// 🔧 缓存失效或不存在,需要新建连接。先清空旧标签页映射(旧 Page 对象已失效)
|
|
29
|
+
clearAllTabs();
|
|
30
|
+
// 优先尝试连接已有的 Chrome 实例(用户手动启动的)
|
|
21
31
|
try {
|
|
22
32
|
console.error('尝试连接到已有的 Chrome 实例 (端口 9222)...');
|
|
23
33
|
const browser = await puppeteer.connect({
|
|
@@ -27,6 +37,8 @@ export async function getBrowser() {
|
|
|
27
37
|
console.error('成功连接到已有的 Chrome 实例!');
|
|
28
38
|
// 设置全局日志收集器
|
|
29
39
|
setupBrowserConsoleCollector(browser);
|
|
40
|
+
cachedBrowser = browser;
|
|
41
|
+
cachedUseExisting = true;
|
|
30
42
|
return { browser, useExistingBrowser: true };
|
|
31
43
|
}
|
|
32
44
|
catch (connectError) {
|
|
@@ -52,12 +64,15 @@ export async function getBrowser() {
|
|
|
52
64
|
'--safebrowsing-disable-auto-update',
|
|
53
65
|
'--disable-infobars',
|
|
54
66
|
'--disable-notifications',
|
|
55
|
-
'--disable-popup-blocking'
|
|
67
|
+
'--disable-popup-blocking',
|
|
68
|
+
`--remote-debugging-port=${DEBUGGING_PORT}`
|
|
56
69
|
]
|
|
57
70
|
});
|
|
58
71
|
console.error('已启动独立的 Chrome 实例');
|
|
59
72
|
// 设置全局日志收集器
|
|
60
73
|
setupBrowserConsoleCollector(browser);
|
|
74
|
+
cachedBrowser = browser;
|
|
75
|
+
cachedUseExisting = false;
|
|
61
76
|
return { browser, useExistingBrowser: false };
|
|
62
77
|
}
|
|
63
78
|
catch (launchError) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/utils/browser.ts"],"names":[],"mappings":"AAAA,OAAO,SAA4B,MAAM,WAAW,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,EAAyB,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/utils/browser.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/tabs.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ export interface TabInfo {
|
|
|
5
5
|
title: string;
|
|
6
6
|
isActive: boolean;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* 同步浏览器真实页面到 tabMap(处理 MCP 重启后 tabMap 丢失的情况)
|
|
10
|
+
* 使用 URL 匹配保持 tabId 稳定(不依赖 Page 对象引用,引用在重连后会失效)
|
|
11
|
+
*/
|
|
12
|
+
export declare function syncBrowserPages(browser: Browser): Promise<void>;
|
|
8
13
|
/**
|
|
9
14
|
* 获取或创建指定标签页
|
|
10
15
|
* @param browser 浏览器实例
|
|
@@ -35,7 +40,7 @@ export declare function listTabs(browser: Browser): Promise<TabInfo[]>;
|
|
|
35
40
|
/**
|
|
36
41
|
* 切换到指定标签页
|
|
37
42
|
*/
|
|
38
|
-
export declare function switchTab(tabId: string): Promise<{
|
|
43
|
+
export declare function switchTab(tabId: string, browser?: Browser): Promise<{
|
|
39
44
|
success: boolean;
|
|
40
45
|
error?: string;
|
|
41
46
|
tabInfo?: TabInfo;
|
|
@@ -43,7 +48,7 @@ export declare function switchTab(tabId: string): Promise<{
|
|
|
43
48
|
/**
|
|
44
49
|
* 关闭指定标签页
|
|
45
50
|
*/
|
|
46
|
-
export declare function closeTab(tabId: string): Promise<{
|
|
51
|
+
export declare function closeTab(tabId: string, browser?: Browser): Promise<{
|
|
47
52
|
success: boolean;
|
|
48
53
|
error?: string;
|
|
49
54
|
closedTabId?: string;
|
|
@@ -52,4 +57,8 @@ export declare function closeTab(tabId: string): Promise<{
|
|
|
52
57
|
* 清理已关闭的标签页(从 map 中移除)
|
|
53
58
|
*/
|
|
54
59
|
export declare function cleanupClosedTabs(): void;
|
|
60
|
+
/**
|
|
61
|
+
* 清空所有标签页映射(浏览器重连时需要,因为旧 Page 对象已失效)
|
|
62
|
+
*/
|
|
63
|
+
export declare function clearAllTabs(): void;
|
|
55
64
|
//# sourceMappingURL=tabs.d.ts.map
|
package/dist/utils/tabs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/utils/tabs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI1C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CACnB;AAmBD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,OAAO,EAC3B,OAAO,CAAC,EAAE;IACR,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACA,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/utils/tabs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI1C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CACnB;AAmBD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA2GtE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,OAAO,EAC3B,OAAO,CAAC,EAAE;IACR,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACA,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAuFxC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE9D;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAE9C;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CA0BnE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAkClI;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BpI;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAMxC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAInC"}
|
package/dist/utils/tabs.js
CHANGED
|
@@ -12,6 +12,118 @@ function generateTabId() {
|
|
|
12
12
|
tabIdCounter++;
|
|
13
13
|
return `tab_${tabIdCounter}`;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* 同步浏览器真实页面到 tabMap(处理 MCP 重启后 tabMap 丢失的情况)
|
|
17
|
+
* 使用 URL 匹配保持 tabId 稳定(不依赖 Page 对象引用,引用在重连后会失效)
|
|
18
|
+
*/
|
|
19
|
+
export async function syncBrowserPages(browser) {
|
|
20
|
+
const allPages = await browser.pages();
|
|
21
|
+
// 建立当前浏览器中真实页面的 URL 集合(排除 about:blank 等)
|
|
22
|
+
const aliveUrls = new Set();
|
|
23
|
+
const alivePages = new Map(); // URL → Page
|
|
24
|
+
for (const page of allPages) {
|
|
25
|
+
try {
|
|
26
|
+
const url = page.url();
|
|
27
|
+
if (!url
|
|
28
|
+
|| url === 'about:blank'
|
|
29
|
+
|| url.startsWith('devtools://')
|
|
30
|
+
|| url.startsWith('chrome://')
|
|
31
|
+
|| url.startsWith('chrome-extension://'))
|
|
32
|
+
continue;
|
|
33
|
+
aliveUrls.add(url);
|
|
34
|
+
// 如果相同 URL 有多个页面,只保留第一个
|
|
35
|
+
if (!alivePages.has(url)) {
|
|
36
|
+
alivePages.set(url, page);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// 重复页面,关闭它
|
|
40
|
+
try {
|
|
41
|
+
await page.close();
|
|
42
|
+
}
|
|
43
|
+
catch (e) { /* ignore */ }
|
|
44
|
+
console.error(`清理重复页面: ${url}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (e) { /* 忽略无法访问的页面 */ }
|
|
48
|
+
}
|
|
49
|
+
// 建立当前 tabMap 中 URL → tabId 的反向映射
|
|
50
|
+
const existingUrlToTabId = new Map();
|
|
51
|
+
for (const [tabId, page] of tabMap.entries()) {
|
|
52
|
+
try {
|
|
53
|
+
const url = page.url();
|
|
54
|
+
if (url && url !== 'about:blank') {
|
|
55
|
+
existingUrlToTabId.set(url, tabId);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (e) { /* 旧 Page 可能失效 */ }
|
|
59
|
+
}
|
|
60
|
+
// 更新 tabMap:保留已有的 tabId,新增或移除页面
|
|
61
|
+
const newTabMap = new Map();
|
|
62
|
+
for (const [url, page] of alivePages) {
|
|
63
|
+
const existingTabId = existingUrlToTabId.get(url);
|
|
64
|
+
if (existingTabId) {
|
|
65
|
+
// 复用已有 tabId,更新 Page 引用
|
|
66
|
+
newTabMap.set(existingTabId, page);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// 新页面,生成新 tabId
|
|
70
|
+
const newTabId = generateTabId();
|
|
71
|
+
newTabMap.set(newTabId, page);
|
|
72
|
+
setupConsoleCollector(page);
|
|
73
|
+
console.error(`发现新标签页: ${newTabId} (${url})`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// 清理不再存在的旧页面
|
|
77
|
+
for (const [tabId, page] of tabMap.entries()) {
|
|
78
|
+
if (!newTabMap.has(tabId)) {
|
|
79
|
+
try {
|
|
80
|
+
if (!page.isClosed())
|
|
81
|
+
await page.close();
|
|
82
|
+
}
|
|
83
|
+
catch (e) { /* ignore */ }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// 替换 tabMap
|
|
87
|
+
tabMap.clear();
|
|
88
|
+
for (const [tabId, page] of newTabMap) {
|
|
89
|
+
tabMap.set(tabId, page);
|
|
90
|
+
// 同步 Page 引用到旧条目(用于 getOrCreateTab 中已持有的引用)
|
|
91
|
+
try {
|
|
92
|
+
const url = page.url();
|
|
93
|
+
if (url) {
|
|
94
|
+
const oldPage = existingUrlToTabId.has(url) ? tabMap.get(existingUrlToTabId.get(url)) : null;
|
|
95
|
+
// Page 引用已在 newTabMap 中同步,无需额外操作
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (e) { /* ignore */ }
|
|
99
|
+
}
|
|
100
|
+
// 检测活跃标签页
|
|
101
|
+
if (tabMap.size > 0) {
|
|
102
|
+
let detectedActive = null;
|
|
103
|
+
for (const [tabId, page] of tabMap.entries()) {
|
|
104
|
+
try {
|
|
105
|
+
const visible = await page.evaluate(() => {
|
|
106
|
+
return document.visibilityState === 'visible';
|
|
107
|
+
});
|
|
108
|
+
if (visible) {
|
|
109
|
+
detectedActive = tabId;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (e) { /* ignore */ }
|
|
114
|
+
}
|
|
115
|
+
if (detectedActive) {
|
|
116
|
+
activeTabId = detectedActive;
|
|
117
|
+
}
|
|
118
|
+
else if (!activeTabId || !tabMap.has(activeTabId)) {
|
|
119
|
+
// 回退:取第一个作为活跃
|
|
120
|
+
for (const [tabId] of tabMap.entries()) {
|
|
121
|
+
activeTabId = tabId;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
15
127
|
/**
|
|
16
128
|
* 获取或创建指定标签页
|
|
17
129
|
* @param browser 浏览器实例
|
|
@@ -21,8 +133,10 @@ function generateTabId() {
|
|
|
21
133
|
*/
|
|
22
134
|
export async function getOrCreateTab(browser, useExistingBrowser, options) {
|
|
23
135
|
const { tabId: targetTabId, url, createNew } = options || {};
|
|
24
|
-
// 如果指定了 tabId
|
|
136
|
+
// 如果指定了 tabId 且不要求新建,先同步浏览器页面再查找
|
|
25
137
|
if (targetTabId && !createNew) {
|
|
138
|
+
// 从浏览器同步页面到 tabMap(解决 MCP 重启后 tabMap 丢失的问题)
|
|
139
|
+
await syncBrowserPages(browser);
|
|
26
140
|
const existingPage = tabMap.get(targetTabId);
|
|
27
141
|
if (existingPage && !existingPage.isClosed()) {
|
|
28
142
|
// 设置为当前活跃标签
|
|
@@ -42,6 +156,26 @@ export async function getOrCreateTab(browser, useExistingBrowser, options) {
|
|
|
42
156
|
tabMap.delete(targetTabId);
|
|
43
157
|
console.error(`标签页 ${targetTabId} 已关闭或不存在`);
|
|
44
158
|
}
|
|
159
|
+
// 🔧 无 tabId 且 url='current':复用浏览器的活跃标签页,不新建空白页
|
|
160
|
+
if (!targetTabId && url === 'current' && !createNew) {
|
|
161
|
+
await syncBrowserPages(browser);
|
|
162
|
+
// 优先使用检测到的活跃标签页
|
|
163
|
+
if (activeTabId) {
|
|
164
|
+
const activePage = tabMap.get(activeTabId);
|
|
165
|
+
if (activePage && !activePage.isClosed()) {
|
|
166
|
+
console.error(`复用活跃标签页: ${activeTabId}`);
|
|
167
|
+
return { page: activePage, tabId: activeTabId };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// 没有活跃标签页,取第一个可用的
|
|
171
|
+
for (const [tabId, page] of tabMap.entries()) {
|
|
172
|
+
if (!page.isClosed()) {
|
|
173
|
+
activeTabId = tabId;
|
|
174
|
+
console.error(`复用第一个可用标签页: ${tabId}`);
|
|
175
|
+
return { page, tabId };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
45
179
|
// 创建新标签页
|
|
46
180
|
let newPage;
|
|
47
181
|
if (useExistingBrowser) {
|
|
@@ -85,8 +219,10 @@ export function getActiveTabId() {
|
|
|
85
219
|
* 获取所有标签页列表
|
|
86
220
|
*/
|
|
87
221
|
export async function listTabs(browser) {
|
|
88
|
-
|
|
222
|
+
// 先同步浏览器真实页面到 tabMap(处理 MCP 重启后 tabMap 丢失的情况)
|
|
223
|
+
await syncBrowserPages(browser);
|
|
89
224
|
const tabs = [];
|
|
225
|
+
// 列出所有标签页
|
|
90
226
|
for (const [tabId, page] of tabMap.entries()) {
|
|
91
227
|
if (!page.isClosed()) {
|
|
92
228
|
try {
|
|
@@ -111,7 +247,11 @@ export async function listTabs(browser) {
|
|
|
111
247
|
/**
|
|
112
248
|
* 切换到指定标签页
|
|
113
249
|
*/
|
|
114
|
-
export async function switchTab(tabId) {
|
|
250
|
+
export async function switchTab(tabId, browser) {
|
|
251
|
+
// 从浏览器同步页面到 tabMap(解决 MCP 重启后 tabMap 丢失的问题)
|
|
252
|
+
if (browser) {
|
|
253
|
+
await syncBrowserPages(browser);
|
|
254
|
+
}
|
|
115
255
|
const page = tabMap.get(tabId);
|
|
116
256
|
if (!page) {
|
|
117
257
|
return { success: false, error: `标签页 ${tabId} 不存在` };
|
|
@@ -141,7 +281,11 @@ export async function switchTab(tabId) {
|
|
|
141
281
|
/**
|
|
142
282
|
* 关闭指定标签页
|
|
143
283
|
*/
|
|
144
|
-
export async function closeTab(tabId) {
|
|
284
|
+
export async function closeTab(tabId, browser) {
|
|
285
|
+
// 从浏览器同步页面到 tabMap(解决 MCP 重启后 tabMap 丢失的问题)
|
|
286
|
+
if (browser) {
|
|
287
|
+
await syncBrowserPages(browser);
|
|
288
|
+
}
|
|
145
289
|
const page = tabMap.get(tabId);
|
|
146
290
|
if (!page) {
|
|
147
291
|
return { success: false, error: `标签页 ${tabId} 不存在` };
|
|
@@ -170,4 +314,12 @@ export function cleanupClosedTabs() {
|
|
|
170
314
|
}
|
|
171
315
|
}
|
|
172
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* 清空所有标签页映射(浏览器重连时需要,因为旧 Page 对象已失效)
|
|
319
|
+
*/
|
|
320
|
+
export function clearAllTabs() {
|
|
321
|
+
tabMap.clear();
|
|
322
|
+
activeTabId = null;
|
|
323
|
+
console.error('已清空所有标签页映射(浏览器重连)');
|
|
324
|
+
}
|
|
173
325
|
//# sourceMappingURL=tabs.js.map
|
package/dist/utils/tabs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../src/utils/tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAU5D,8BAA8B;AAC9B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAgB,CAAC;AAEvC,cAAc;AACd,IAAI,WAAW,GAAkB,IAAI,CAAC;AAEtC,aAAa;AACb,IAAI,YAAY,GAAG,CAAC,CAAC;AAErB;;GAEG;AACH,SAAS,aAAa;IACpB,YAAY,EAAE,CAAC;IACf,OAAO,OAAO,YAAY,EAAE,CAAC;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,kBAA2B,EAC3B,OAIC;IAED,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IAE7D,
|
|
1
|
+
{"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../src/utils/tabs.ts"],"names":[],"mappings":"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"}
|