@pyrokine/mcp-chrome 1.1.0 → 1.3.0
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 +103 -53
- package/dist/anti-detection/behavior.d.ts +0 -8
- package/dist/anti-detection/behavior.d.ts.map +1 -1
- package/dist/anti-detection/behavior.js +0 -16
- package/dist/anti-detection/behavior.js.map +1 -1
- package/dist/cdp/client.d.ts +0 -2
- package/dist/cdp/client.d.ts.map +1 -1
- package/dist/cdp/client.js +30 -45
- package/dist/cdp/client.js.map +1 -1
- package/dist/cdp/launcher.d.ts +1 -8
- package/dist/cdp/launcher.d.ts.map +1 -1
- package/dist/cdp/launcher.js +4 -20
- package/dist/cdp/launcher.js.map +1 -1
- package/dist/core/auto-wait.d.ts +2 -2
- package/dist/core/auto-wait.d.ts.map +1 -1
- package/dist/core/auto-wait.js +1 -1
- package/dist/core/auto-wait.js.map +1 -1
- package/dist/core/errors.d.ts +10 -13
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +19 -25
- package/dist/core/errors.js.map +1 -1
- package/dist/core/locator.d.ts +6 -7
- package/dist/core/locator.d.ts.map +1 -1
- package/dist/core/locator.js +77 -31
- package/dist/core/locator.js.map +1 -1
- package/dist/core/retry.d.ts.map +1 -1
- package/dist/core/retry.js +1 -1
- package/dist/core/retry.js.map +1 -1
- package/dist/core/session.d.ts +32 -33
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +154 -114
- package/dist/core/session.js.map +1 -1
- package/dist/core/types.d.ts +4 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +6 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/unified-session.d.ts +54 -67
- package/dist/core/unified-session.d.ts.map +1 -1
- package/dist/core/unified-session.js +215 -181
- package/dist/core/unified-session.js.map +1 -1
- package/dist/extension/bridge.d.ts +0 -19
- package/dist/extension/bridge.d.ts.map +1 -1
- package/dist/extension/bridge.js +6 -52
- package/dist/extension/bridge.js.map +1 -1
- package/dist/extension/http-server.d.ts +13 -11
- package/dist/extension/http-server.d.ts.map +1 -1
- package/dist/extension/http-server.js +101 -95
- package/dist/extension/http-server.js.map +1 -1
- package/dist/index.js +11 -64
- package/dist/index.js.map +1 -1
- package/dist/tools/browse.d.ts +3 -80
- package/dist/tools/browse.d.ts.map +1 -1
- package/dist/tools/browse.js +135 -291
- package/dist/tools/browse.js.map +1 -1
- package/dist/tools/cookies.d.ts +3 -71
- package/dist/tools/cookies.d.ts.map +1 -1
- package/dist/tools/cookies.js +75 -157
- package/dist/tools/cookies.js.map +1 -1
- package/dist/tools/evaluate.d.ts +3 -52
- package/dist/tools/evaluate.d.ts.map +1 -1
- package/dist/tools/evaluate.js +35 -86
- package/dist/tools/evaluate.js.map +1 -1
- package/dist/tools/extract.d.ts +3 -226
- package/dist/tools/extract.d.ts.map +1 -1
- package/dist/tools/extract.js +98 -170
- package/dist/tools/extract.js.map +1 -1
- package/dist/tools/index.d.ts +9 -9
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +9 -9
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/input.d.ts +3 -258
- package/dist/tools/input.d.ts.map +1 -1
- package/dist/tools/input.js +56 -143
- package/dist/tools/input.js.map +1 -1
- package/dist/tools/logs.d.ts +3 -51
- package/dist/tools/logs.d.ts.map +1 -1
- package/dist/tools/logs.js +47 -108
- package/dist/tools/logs.js.map +1 -1
- package/dist/tools/manage.d.ts +3 -64
- package/dist/tools/manage.d.ts.map +1 -1
- package/dist/tools/manage.js +243 -373
- package/dist/tools/manage.js.map +1 -1
- package/dist/tools/schema.d.ts +16 -182
- package/dist/tools/schema.d.ts.map +1 -1
- package/dist/tools/schema.js +70 -159
- package/dist/tools/schema.js.map +1 -1
- package/dist/tools/wait.d.ts +3 -221
- package/dist/tools/wait.d.ts.map +1 -1
- package/dist/tools/wait.js +74 -145
- package/dist/tools/wait.js.map +1 -1
- package/package.json +1 -1
package/dist/tools/manage.js
CHANGED
|
@@ -13,434 +13,261 @@
|
|
|
13
13
|
* - cdp: 发送任意 CDP 命令(高级)
|
|
14
14
|
*/
|
|
15
15
|
import { z } from 'zod';
|
|
16
|
-
import { devices, formatErrorResponse, getSession, getUnifiedSession } from '../core/index.js';
|
|
17
|
-
/**
|
|
18
|
-
* manage 工具定义
|
|
19
|
-
*/
|
|
20
|
-
export const manageToolDefinition = {
|
|
21
|
-
name: 'manage',
|
|
22
|
-
description: '页面与环境管理:新建页面、关闭页面、缓存、视口、UA、设备模拟',
|
|
23
|
-
inputSchema: {
|
|
24
|
-
type: 'object',
|
|
25
|
-
properties: {
|
|
26
|
-
action: {
|
|
27
|
-
type: 'string',
|
|
28
|
-
enum: [
|
|
29
|
-
'newPage',
|
|
30
|
-
'closePage',
|
|
31
|
-
'clearCache',
|
|
32
|
-
'viewport',
|
|
33
|
-
'userAgent',
|
|
34
|
-
'emulate',
|
|
35
|
-
'inputMode',
|
|
36
|
-
'stealth',
|
|
37
|
-
'cdp',
|
|
38
|
-
],
|
|
39
|
-
description: '管理操作',
|
|
40
|
-
},
|
|
41
|
-
inputMode: {
|
|
42
|
-
type: 'string',
|
|
43
|
-
enum: ['stealth', 'precise'],
|
|
44
|
-
description: '输入模式(inputMode)。precise=debugger API(默认,可绕过 CSP 但显示调试提示);stealth=JS 事件模拟(不触发调试提示但受 CSP 限制,适用于反检测场景)',
|
|
45
|
-
},
|
|
46
|
-
cdpMethod: {
|
|
47
|
-
type: 'string',
|
|
48
|
-
description: 'CDP 方法名(cdp),如 Runtime.evaluate、Page.captureScreenshot',
|
|
49
|
-
},
|
|
50
|
-
cdpParams: {
|
|
51
|
-
type: 'object',
|
|
52
|
-
description: 'CDP 方法参数(cdp)',
|
|
53
|
-
},
|
|
54
|
-
targetId: {
|
|
55
|
-
type: 'string',
|
|
56
|
-
description: '目标页面 ID(closePage)',
|
|
57
|
-
},
|
|
58
|
-
cacheType: {
|
|
59
|
-
type: 'string',
|
|
60
|
-
enum: ['all', 'cookies', 'storage', 'cache'],
|
|
61
|
-
description: '清除类型(clearCache)',
|
|
62
|
-
},
|
|
63
|
-
width: {
|
|
64
|
-
type: 'number',
|
|
65
|
-
description: '视口宽度(viewport)',
|
|
66
|
-
},
|
|
67
|
-
height: {
|
|
68
|
-
type: 'number',
|
|
69
|
-
description: '视口高度(viewport)',
|
|
70
|
-
},
|
|
71
|
-
userAgent: {
|
|
72
|
-
type: 'string',
|
|
73
|
-
description: 'User-Agent 字符串(userAgent)',
|
|
74
|
-
},
|
|
75
|
-
device: {
|
|
76
|
-
type: 'string',
|
|
77
|
-
description: '设备名称(emulate),如 iPhone 13, iPad Pro',
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
required: ['action'],
|
|
81
|
-
},
|
|
82
|
-
};
|
|
16
|
+
import { devices, formatErrorResponse, formatResponse, getSession, getUnifiedSession } from '../core/index.js';
|
|
83
17
|
/**
|
|
84
18
|
* manage 参数 schema
|
|
85
19
|
*/
|
|
86
20
|
const manageSchema = z.object({
|
|
87
21
|
action: z.enum([
|
|
88
|
-
'newPage',
|
|
89
|
-
'
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
width: z.number().optional(),
|
|
101
|
-
height: z.number().optional(),
|
|
102
|
-
userAgent: z.string().optional(),
|
|
103
|
-
device: z.string().optional(),
|
|
104
|
-
inputMode: z.enum(['stealth', 'precise']).optional(),
|
|
105
|
-
cdpMethod: z.string().optional(),
|
|
106
|
-
cdpParams: z.record(z.unknown()).optional(),
|
|
22
|
+
'newPage', 'closePage', 'clearCache', 'viewport',
|
|
23
|
+
'userAgent', 'emulate', 'inputMode', 'stealth', 'cdp',
|
|
24
|
+
]).describe('管理操作'),
|
|
25
|
+
inputMode: z.enum(['stealth', 'precise']).optional().describe('输入模式(inputMode)。precise=debugger API(默认,可绕过 CSP 但显示调试提示);stealth=JS 事件模拟(不触发调试提示但受 CSP 限制,适用于反检测场景)'),
|
|
26
|
+
cdpMethod: z.string().optional().describe('CDP 方法名(cdp),如 Runtime.evaluate、Page.captureScreenshot'),
|
|
27
|
+
cdpParams: z.record(z.unknown()).optional().describe('CDP 方法参数(cdp)'),
|
|
28
|
+
targetId: z.string().optional().describe('目标页面 ID(closePage)'),
|
|
29
|
+
cacheType: z.enum(['all', 'cookies', 'storage', 'cache']).optional().describe('清除类型(clearCache)'),
|
|
30
|
+
width: z.number().optional().describe('视口宽度(viewport)'),
|
|
31
|
+
height: z.number().optional().describe('视口高度(viewport)'),
|
|
32
|
+
userAgent: z.string().optional().describe('User-Agent 字符串(userAgent)'),
|
|
33
|
+
device: z.string().optional().describe('设备名称(emulate),如 iPhone 13, iPad Pro'),
|
|
107
34
|
});
|
|
108
35
|
/**
|
|
109
36
|
* manage 工具处理器
|
|
110
37
|
*/
|
|
111
|
-
|
|
38
|
+
async function handleManage(args) {
|
|
112
39
|
try {
|
|
113
|
-
const args = manageSchema.parse(params);
|
|
114
40
|
const unifiedSession = getUnifiedSession();
|
|
115
41
|
const mode = unifiedSession.getMode();
|
|
116
42
|
switch (args.action) {
|
|
117
43
|
case 'newPage': {
|
|
118
44
|
const target = await unifiedSession.newPage();
|
|
119
|
-
return {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
action: 'newPage',
|
|
126
|
-
target,
|
|
127
|
-
mode,
|
|
128
|
-
}),
|
|
129
|
-
},
|
|
130
|
-
],
|
|
131
|
-
};
|
|
45
|
+
return formatResponse({
|
|
46
|
+
success: true,
|
|
47
|
+
action: 'newPage',
|
|
48
|
+
target,
|
|
49
|
+
mode,
|
|
50
|
+
});
|
|
132
51
|
}
|
|
133
52
|
case 'closePage': {
|
|
134
53
|
await unifiedSession.closePage(args.targetId);
|
|
135
|
-
return {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
action: 'closePage',
|
|
142
|
-
targetId: args.targetId ?? 'current',
|
|
143
|
-
mode,
|
|
144
|
-
}),
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
};
|
|
54
|
+
return formatResponse({
|
|
55
|
+
success: true,
|
|
56
|
+
action: 'closePage',
|
|
57
|
+
targetId: args.targetId ?? 'current',
|
|
58
|
+
mode,
|
|
59
|
+
});
|
|
148
60
|
}
|
|
149
61
|
case 'clearCache': {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
62
|
+
return await unifiedSession.withTabId(undefined, async () => {
|
|
63
|
+
const cacheType = (args.cacheType ?? 'all');
|
|
64
|
+
if (mode === 'extension') {
|
|
65
|
+
// Extension 模式:只支持 cookies 清除
|
|
66
|
+
if (cacheType === 'all' || cacheType === 'cookies') {
|
|
67
|
+
await unifiedSession.clearCookies();
|
|
68
|
+
}
|
|
69
|
+
if (cacheType === 'storage' || cacheType === 'cache') {
|
|
70
|
+
return formatResponse({
|
|
71
|
+
success: true,
|
|
72
|
+
action: 'clearCache',
|
|
73
|
+
cacheType,
|
|
74
|
+
mode,
|
|
75
|
+
warning: 'Extension 模式仅支持清除 cookies,storage 和 cache 需要 CDP 模式',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const session = getSession();
|
|
81
|
+
await session.clearCache(cacheType);
|
|
155
82
|
}
|
|
156
|
-
|
|
83
|
+
return formatResponse({
|
|
84
|
+
success: true,
|
|
85
|
+
action: 'clearCache',
|
|
86
|
+
cacheType,
|
|
87
|
+
mode,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
case 'viewport': {
|
|
92
|
+
return await unifiedSession.withTabId(undefined, async () => {
|
|
93
|
+
if (args.width === undefined || args.height === undefined) {
|
|
157
94
|
return {
|
|
158
95
|
content: [
|
|
159
96
|
{
|
|
160
97
|
type: 'text',
|
|
161
98
|
text: JSON.stringify({
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
warning: 'Extension 模式仅支持清除 cookies,storage 和 cache 需要 CDP 模式',
|
|
99
|
+
error: {
|
|
100
|
+
code: 'INVALID_ARGUMENT',
|
|
101
|
+
message: '设置视口需要 width 和 height 参数',
|
|
102
|
+
},
|
|
167
103
|
}),
|
|
168
104
|
},
|
|
169
105
|
],
|
|
106
|
+
isError: true,
|
|
170
107
|
};
|
|
171
108
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
case 'viewport': {
|
|
192
|
-
if (args.width === undefined || args.height === undefined) {
|
|
193
|
-
return {
|
|
194
|
-
content: [
|
|
195
|
-
{
|
|
196
|
-
type: 'text',
|
|
197
|
-
text: JSON.stringify({
|
|
198
|
-
error: {
|
|
199
|
-
code: 'INVALID_ARGUMENT',
|
|
200
|
-
message: '设置视口需要 width 和 height 参数',
|
|
201
|
-
},
|
|
202
|
-
}),
|
|
203
|
-
},
|
|
204
|
-
],
|
|
205
|
-
isError: true,
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
if (mode === 'extension') {
|
|
209
|
-
// Extension 模式:使用 debugger API 设置视口
|
|
210
|
-
await unifiedSession.sendCdpCommand('Emulation.setDeviceMetricsOverride', {
|
|
109
|
+
if (mode === 'extension') {
|
|
110
|
+
// Extension 模式:使用 debugger API 设置视口
|
|
111
|
+
await unifiedSession.sendCdpCommand('Emulation.setDeviceMetricsOverride', {
|
|
112
|
+
width: args.width,
|
|
113
|
+
height: args.height,
|
|
114
|
+
deviceScaleFactor: 1,
|
|
115
|
+
mobile: false,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const session = getSession();
|
|
120
|
+
await session.setViewport(args.width, args.height);
|
|
121
|
+
}
|
|
122
|
+
// 触发 resize 事件(Emulation API 不会自动触发)
|
|
123
|
+
await unifiedSession.evaluate('window.dispatchEvent(new Event("resize"))');
|
|
124
|
+
return formatResponse({
|
|
125
|
+
success: true,
|
|
126
|
+
action: 'viewport',
|
|
211
127
|
width: args.width,
|
|
212
128
|
height: args.height,
|
|
213
|
-
|
|
214
|
-
mobile: false,
|
|
129
|
+
mode,
|
|
215
130
|
});
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
const session = getSession();
|
|
219
|
-
await session.setViewport(args.width, args.height);
|
|
220
|
-
}
|
|
221
|
-
return {
|
|
222
|
-
content: [
|
|
223
|
-
{
|
|
224
|
-
type: 'text',
|
|
225
|
-
text: JSON.stringify({
|
|
226
|
-
success: true,
|
|
227
|
-
action: 'viewport',
|
|
228
|
-
width: args.width,
|
|
229
|
-
height: args.height,
|
|
230
|
-
mode,
|
|
231
|
-
}),
|
|
232
|
-
},
|
|
233
|
-
],
|
|
234
|
-
};
|
|
131
|
+
});
|
|
235
132
|
}
|
|
236
133
|
case 'userAgent': {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
134
|
+
return await unifiedSession.withTabId(undefined, async () => {
|
|
135
|
+
if (!args.userAgent) {
|
|
136
|
+
return {
|
|
137
|
+
content: [
|
|
138
|
+
{
|
|
139
|
+
type: 'text',
|
|
140
|
+
text: JSON.stringify({
|
|
141
|
+
error: {
|
|
142
|
+
code: 'INVALID_ARGUMENT',
|
|
143
|
+
message: '设置 User-Agent 需要 userAgent 参数',
|
|
144
|
+
},
|
|
145
|
+
}),
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
isError: true,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (mode === 'extension') {
|
|
152
|
+
// Extension 模式:使用 debugger API 设置 UA
|
|
153
|
+
await unifiedSession.sendCdpCommand('Emulation.setUserAgentOverride', {
|
|
154
|
+
userAgent: args.userAgent,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
const session = getSession();
|
|
159
|
+
await session.setUserAgent(args.userAgent);
|
|
160
|
+
}
|
|
161
|
+
return formatResponse({
|
|
162
|
+
success: true,
|
|
163
|
+
action: 'userAgent',
|
|
256
164
|
userAgent: args.userAgent,
|
|
165
|
+
mode,
|
|
257
166
|
});
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
const session = getSession();
|
|
261
|
-
await session.setUserAgent(args.userAgent);
|
|
262
|
-
}
|
|
263
|
-
return {
|
|
264
|
-
content: [
|
|
265
|
-
{
|
|
266
|
-
type: 'text',
|
|
267
|
-
text: JSON.stringify({
|
|
268
|
-
success: true,
|
|
269
|
-
action: 'userAgent',
|
|
270
|
-
userAgent: args.userAgent,
|
|
271
|
-
mode,
|
|
272
|
-
}),
|
|
273
|
-
},
|
|
274
|
-
],
|
|
275
|
-
};
|
|
167
|
+
});
|
|
276
168
|
}
|
|
277
169
|
case 'inputMode': {
|
|
278
170
|
if (!args.inputMode) {
|
|
279
171
|
// 返回当前模式
|
|
280
|
-
return {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
stealth: 'JS 事件模拟,不触发调试提示,但受 CSP 限制(evaluate 可能失败)',
|
|
291
|
-
precise: 'debugger API,可绕过 CSP,但显示"扩展程序正在调试此浏览器"',
|
|
292
|
-
},
|
|
293
|
-
}),
|
|
294
|
-
},
|
|
295
|
-
],
|
|
296
|
-
};
|
|
172
|
+
return formatResponse({
|
|
173
|
+
success: true,
|
|
174
|
+
action: 'inputMode',
|
|
175
|
+
currentMode: unifiedSession.getInputMode(),
|
|
176
|
+
availableModes: ['stealth', 'precise'],
|
|
177
|
+
description: {
|
|
178
|
+
stealth: 'JS 事件模拟,不触发调试提示,但受 CSP 限制(evaluate 可能失败)',
|
|
179
|
+
precise: 'debugger API,可绕过 CSP,但显示"扩展程序正在调试此浏览器"',
|
|
180
|
+
},
|
|
181
|
+
});
|
|
297
182
|
}
|
|
298
183
|
unifiedSession.setInputMode(args.inputMode);
|
|
299
|
-
return {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
action: 'inputMode',
|
|
306
|
-
inputMode: args.inputMode,
|
|
307
|
-
mode,
|
|
308
|
-
}),
|
|
309
|
-
},
|
|
310
|
-
],
|
|
311
|
-
};
|
|
184
|
+
return formatResponse({
|
|
185
|
+
success: true,
|
|
186
|
+
action: 'inputMode',
|
|
187
|
+
inputMode: args.inputMode,
|
|
188
|
+
mode,
|
|
189
|
+
});
|
|
312
190
|
}
|
|
313
191
|
case 'emulate': {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
192
|
+
return await unifiedSession.withTabId(undefined, async () => {
|
|
193
|
+
if (!args.device) {
|
|
194
|
+
// 列出可用设备
|
|
195
|
+
return formatResponse({
|
|
196
|
+
success: true,
|
|
197
|
+
action: 'emulate',
|
|
198
|
+
availableDevices: Object.keys(devices),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
const device = devices[args.device];
|
|
202
|
+
if (!device) {
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: 'text',
|
|
207
|
+
text: JSON.stringify({
|
|
208
|
+
error: {
|
|
209
|
+
code: 'INVALID_ARGUMENT',
|
|
210
|
+
message: `未知设备: ${args.device}`,
|
|
211
|
+
suggestion: `可用设备: ${Object.keys(devices)
|
|
212
|
+
.join(', ')}`,
|
|
213
|
+
},
|
|
214
|
+
}),
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
isError: true,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
if (mode === 'extension') {
|
|
221
|
+
// Extension 模式:使用 debugger API
|
|
222
|
+
await unifiedSession.sendCdpCommand('Emulation.setDeviceMetricsOverride', {
|
|
223
|
+
width: device.viewport.width,
|
|
224
|
+
height: device.viewport.height,
|
|
225
|
+
deviceScaleFactor: device.viewport.deviceScaleFactor || 1,
|
|
226
|
+
mobile: device.viewport.isMobile || false,
|
|
227
|
+
});
|
|
228
|
+
await unifiedSession.sendCdpCommand('Emulation.setUserAgentOverride', {
|
|
229
|
+
userAgent: device.userAgent,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const session = getSession();
|
|
234
|
+
await session.setViewport(device.viewport.width, device.viewport.height);
|
|
235
|
+
await session.setUserAgent(device.userAgent);
|
|
236
|
+
}
|
|
237
|
+
// 触发 resize 事件(Emulation API 不会自动触发)
|
|
238
|
+
await unifiedSession.evaluate('window.dispatchEvent(new Event("resize"))');
|
|
239
|
+
return formatResponse({
|
|
240
|
+
success: true,
|
|
241
|
+
action: 'emulate',
|
|
242
|
+
device: args.device,
|
|
243
|
+
viewport: device.viewport,
|
|
244
|
+
mode,
|
|
357
245
|
});
|
|
358
|
-
}
|
|
359
|
-
else {
|
|
360
|
-
const session = getSession();
|
|
361
|
-
await session.setViewport(device.viewport.width, device.viewport.height);
|
|
362
|
-
await session.setUserAgent(device.userAgent);
|
|
363
|
-
}
|
|
364
|
-
return {
|
|
365
|
-
content: [
|
|
366
|
-
{
|
|
367
|
-
type: 'text',
|
|
368
|
-
text: JSON.stringify({
|
|
369
|
-
success: true,
|
|
370
|
-
action: 'emulate',
|
|
371
|
-
device: args.device,
|
|
372
|
-
viewport: device.viewport,
|
|
373
|
-
mode,
|
|
374
|
-
}),
|
|
375
|
-
},
|
|
376
|
-
],
|
|
377
|
-
};
|
|
246
|
+
});
|
|
378
247
|
}
|
|
379
248
|
case 'stealth': {
|
|
380
|
-
await unifiedSession.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
note: '已注入反检测脚本',
|
|
390
|
-
}),
|
|
391
|
-
},
|
|
392
|
-
],
|
|
393
|
-
};
|
|
249
|
+
return await unifiedSession.withTabId(undefined, async () => {
|
|
250
|
+
await unifiedSession.injectStealth();
|
|
251
|
+
return formatResponse({
|
|
252
|
+
success: true,
|
|
253
|
+
action: 'stealth',
|
|
254
|
+
mode,
|
|
255
|
+
note: '已注入反检测脚本',
|
|
256
|
+
});
|
|
257
|
+
});
|
|
394
258
|
}
|
|
395
259
|
case 'cdp': {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
content: [
|
|
399
|
-
{
|
|
400
|
-
type: 'text',
|
|
401
|
-
text: JSON.stringify({
|
|
402
|
-
error: {
|
|
403
|
-
code: 'INVALID_ARGUMENT',
|
|
404
|
-
message: '缺少 cdpMethod 参数',
|
|
405
|
-
suggestion: '请指定 CDP 方法名,如 Runtime.evaluate、Page.captureScreenshot',
|
|
406
|
-
},
|
|
407
|
-
}),
|
|
408
|
-
},
|
|
409
|
-
],
|
|
410
|
-
isError: true,
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
try {
|
|
414
|
-
const result = await unifiedSession.sendCdpCommand(args.cdpMethod, args.cdpParams);
|
|
415
|
-
return {
|
|
416
|
-
content: [
|
|
417
|
-
{
|
|
418
|
-
type: 'text',
|
|
419
|
-
text: JSON.stringify({
|
|
420
|
-
success: true,
|
|
421
|
-
action: 'cdp',
|
|
422
|
-
method: args.cdpMethod,
|
|
423
|
-
result,
|
|
424
|
-
mode,
|
|
425
|
-
}, null, 2),
|
|
426
|
-
},
|
|
427
|
-
],
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
catch (error) {
|
|
431
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
432
|
-
// Extension 模式下某些 CDP 域不支持
|
|
433
|
-
if (mode === 'extension' && (errorMessage.includes('not supported') || errorMessage.includes('not found'))) {
|
|
434
|
-
const domain = args.cdpMethod.split('.')[0];
|
|
260
|
+
return await unifiedSession.withTabId(undefined, async () => {
|
|
261
|
+
if (!args.cdpMethod) {
|
|
435
262
|
return {
|
|
436
263
|
content: [
|
|
437
264
|
{
|
|
438
265
|
type: 'text',
|
|
439
266
|
text: JSON.stringify({
|
|
440
267
|
error: {
|
|
441
|
-
code: '
|
|
442
|
-
message:
|
|
443
|
-
suggestion: '
|
|
268
|
+
code: 'INVALID_ARGUMENT',
|
|
269
|
+
message: '缺少 cdpMethod 参数',
|
|
270
|
+
suggestion: '请指定 CDP 方法名,如 Runtime.evaluate、Page.captureScreenshot',
|
|
444
271
|
},
|
|
445
272
|
}),
|
|
446
273
|
},
|
|
@@ -448,8 +275,42 @@ export async function handleManage(params) {
|
|
|
448
275
|
isError: true,
|
|
449
276
|
};
|
|
450
277
|
}
|
|
451
|
-
|
|
452
|
-
|
|
278
|
+
try {
|
|
279
|
+
const result = await unifiedSession.sendCdpCommand(args.cdpMethod, args.cdpParams);
|
|
280
|
+
return formatResponse({
|
|
281
|
+
success: true,
|
|
282
|
+
action: 'cdp',
|
|
283
|
+
method: args.cdpMethod,
|
|
284
|
+
result,
|
|
285
|
+
mode,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
290
|
+
// Extension 模式下某些 CDP 域不支持
|
|
291
|
+
if (mode ===
|
|
292
|
+
'extension' &&
|
|
293
|
+
(errorMessage.includes('not supported') || errorMessage.includes('not found'))) {
|
|
294
|
+
const domain = args.cdpMethod.split('.')[0];
|
|
295
|
+
return {
|
|
296
|
+
content: [
|
|
297
|
+
{
|
|
298
|
+
type: 'text',
|
|
299
|
+
text: JSON.stringify({
|
|
300
|
+
error: {
|
|
301
|
+
code: 'CDP_DOMAIN_NOT_SUPPORTED',
|
|
302
|
+
message: `Extension 模式不支持 ${domain} 域`,
|
|
303
|
+
suggestion: 'Extension 模式可用域:Page、Runtime、Emulation、DOM、Input、Network。如需完整 CDP 支持,请使用 CDP 模式(browse action="launch")',
|
|
304
|
+
},
|
|
305
|
+
}),
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
isError: true,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return formatErrorResponse(error);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
453
314
|
}
|
|
454
315
|
default:
|
|
455
316
|
return {
|
|
@@ -472,4 +333,13 @@ export async function handleManage(params) {
|
|
|
472
333
|
return formatErrorResponse(error);
|
|
473
334
|
}
|
|
474
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* 注册 manage 工具
|
|
338
|
+
*/
|
|
339
|
+
export function registerManageTool(server) {
|
|
340
|
+
server.registerTool('manage', {
|
|
341
|
+
description: '页面与环境管理:新建页面、关闭页面、缓存、视口、UA、设备模拟',
|
|
342
|
+
inputSchema: manageSchema,
|
|
343
|
+
}, (args) => handleManage(args));
|
|
344
|
+
}
|
|
475
345
|
//# sourceMappingURL=manage.js.map
|