weixin-devtools-mcp 0.0.1 → 0.1.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/LICENSE +21 -0
- package/README.md +127 -128
- package/build/MiniProgramContext.d.ts +317 -0
- package/build/MiniProgramContext.d.ts.map +1 -0
- package/build/MiniProgramContext.js +696 -0
- package/build/MiniProgramContext.js.map +1 -0
- package/build/collectors/Collector.d.ts +127 -0
- package/build/collectors/Collector.d.ts.map +1 -0
- package/build/collectors/Collector.js +252 -0
- package/build/collectors/Collector.js.map +1 -0
- package/build/collectors/ConsoleCollector.d.ts +104 -0
- package/build/collectors/ConsoleCollector.d.ts.map +1 -0
- package/build/collectors/ConsoleCollector.js +157 -0
- package/build/collectors/ConsoleCollector.js.map +1 -0
- package/build/collectors/NetworkCollector.d.ts +167 -0
- package/build/collectors/NetworkCollector.d.ts.map +1 -0
- package/build/collectors/NetworkCollector.js +265 -0
- package/build/collectors/NetworkCollector.js.map +1 -0
- package/build/collectors/index.d.ts +13 -0
- package/build/collectors/index.d.ts.map +1 -0
- package/build/collectors/index.js +17 -0
- package/build/collectors/index.js.map +1 -0
- package/build/config/tool-profile.d.ts +30 -0
- package/build/config/tool-profile.d.ts.map +1 -0
- package/build/config/tool-profile.js +138 -0
- package/build/config/tool-profile.js.map +1 -0
- package/build/connection/adapters.d.ts +3 -0
- package/build/connection/adapters.d.ts.map +1 -0
- package/build/connection/adapters.js +134 -0
- package/build/connection/adapters.js.map +1 -0
- package/build/connection/errors.d.ts +34 -0
- package/build/connection/errors.d.ts.map +1 -0
- package/build/connection/errors.js +101 -0
- package/build/connection/errors.js.map +1 -0
- package/build/connection/health-probe.d.ts +4 -0
- package/build/connection/health-probe.d.ts.map +1 -0
- package/build/connection/health-probe.js +60 -0
- package/build/connection/health-probe.js.map +1 -0
- package/build/connection/index.d.ts +6 -0
- package/build/connection/index.d.ts.map +1 -0
- package/build/connection/index.js +6 -0
- package/build/connection/index.js.map +1 -0
- package/build/connection/manager.d.ts +19 -0
- package/build/connection/manager.d.ts.map +1 -0
- package/build/connection/manager.js +227 -0
- package/build/connection/manager.js.map +1 -0
- package/build/connection/resolver.d.ts +3 -0
- package/build/connection/resolver.d.ts.map +1 -0
- package/build/connection/resolver.js +99 -0
- package/build/connection/resolver.js.map +1 -0
- package/build/connection/types.d.ts +95 -0
- package/build/connection/types.d.ts.map +1 -0
- package/build/connection/types.js +16 -0
- package/build/connection/types.js.map +1 -0
- package/build/core/assertion.d.ts +22 -0
- package/build/core/assertion.d.ts.map +1 -0
- package/build/core/assertion.js +318 -0
- package/build/core/assertion.js.map +1 -0
- package/build/core/connection.d.ts +37 -0
- package/build/core/connection.d.ts.map +1 -0
- package/build/core/connection.js +745 -0
- package/build/core/connection.js.map +1 -0
- package/build/core/index.d.ts +13 -0
- package/build/core/index.d.ts.map +1 -0
- package/build/core/index.js +19 -0
- package/build/core/index.js.map +1 -0
- package/build/core/interaction.d.ts +22 -0
- package/build/core/interaction.d.ts.map +1 -0
- package/build/core/interaction.js +185 -0
- package/build/core/interaction.js.map +1 -0
- package/build/core/navigation.d.ts +26 -0
- package/build/core/navigation.d.ts.map +1 -0
- package/build/core/navigation.js +210 -0
- package/build/core/navigation.js.map +1 -0
- package/build/core/query.d.ts +14 -0
- package/build/core/query.d.ts.map +1 -0
- package/build/core/query.js +191 -0
- package/build/core/query.js.map +1 -0
- package/build/core/screenshot.d.ts +10 -0
- package/build/core/screenshot.d.ts.map +1 -0
- package/build/core/screenshot.js +93 -0
- package/build/core/screenshot.js.map +1 -0
- package/build/core/snapshot.d.ts +17 -0
- package/build/core/snapshot.d.ts.map +1 -0
- package/build/core/snapshot.js +225 -0
- package/build/core/snapshot.js.map +1 -0
- package/build/core/types.d.ts +250 -0
- package/build/core/types.d.ts.map +1 -0
- package/build/core/types.js +6 -0
- package/build/core/types.js.map +1 -0
- package/build/formatters/consoleFormatter.d.ts +50 -0
- package/build/formatters/consoleFormatter.d.ts.map +1 -0
- package/build/formatters/consoleFormatter.js +116 -0
- package/build/formatters/consoleFormatter.js.map +1 -0
- package/build/formatters/snapshotFormatter.d.ts +41 -0
- package/build/formatters/snapshotFormatter.d.ts.map +1 -0
- package/build/formatters/snapshotFormatter.js +156 -0
- package/build/formatters/snapshotFormatter.js.map +1 -0
- package/build/index.d.ts +11 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +45 -9
- package/build/index.js.map +1 -0
- package/build/server.d.ts +7 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +88 -32
- package/build/server.js.map +1 -0
- package/build/tools/ToolDefinition.d.ts +265 -0
- package/build/tools/ToolDefinition.d.ts.map +1 -0
- package/build/tools/ToolDefinition.js +16 -7
- package/build/tools/ToolDefinition.js.map +1 -0
- package/build/tools/assert.d.ts +17 -0
- package/build/tools/assert.d.ts.map +1 -0
- package/build/tools/assert.js +63 -103
- package/build/tools/assert.js.map +1 -0
- package/build/tools/connection.d.ts +13 -0
- package/build/tools/connection.d.ts.map +1 -0
- package/build/tools/connection.js +338 -611
- package/build/tools/connection.js.map +1 -0
- package/build/tools/console.d.ts +20 -0
- package/build/tools/console.d.ts.map +1 -0
- package/build/tools/console.js +162 -152
- package/build/tools/console.js.map +1 -0
- package/build/tools/diagnose.d.ts +22 -0
- package/build/tools/diagnose.d.ts.map +1 -0
- package/build/tools/diagnose.js +406 -13
- package/build/tools/diagnose.js.map +1 -0
- package/build/tools/index.d.ts +6 -0
- package/build/tools/index.d.ts.map +1 -0
- package/build/tools/index.js +3 -77
- package/build/tools/index.js.map +1 -0
- package/build/tools/input.d.ts +21 -0
- package/build/tools/input.d.ts.map +1 -0
- package/build/tools/input.js +73 -139
- package/build/tools/input.js.map +1 -0
- package/build/tools/navigate.d.ts +21 -0
- package/build/tools/navigate.d.ts.map +1 -0
- package/build/tools/navigate.js +63 -126
- package/build/tools/navigate.js.map +1 -0
- package/build/tools/network.d.ts +21 -0
- package/build/tools/network.d.ts.map +1 -0
- package/build/tools/network.js +214 -1044
- package/build/tools/network.js.map +1 -0
- package/build/tools/page.d.ts +13 -0
- package/build/tools/page.d.ts.map +1 -0
- package/build/tools/page.js +6 -3
- package/build/tools/page.js.map +1 -0
- package/build/tools/screenshot.d.ts +9 -0
- package/build/tools/screenshot.d.ts.map +1 -0
- package/build/tools/screenshot.js +3 -1
- package/build/tools/screenshot.js.map +1 -0
- package/build/tools/script.d.ts +6 -0
- package/build/tools/script.d.ts.map +1 -0
- package/build/tools/script.js +92 -0
- package/build/tools/script.js.map +1 -0
- package/build/tools/snapshot.d.ts +9 -0
- package/build/tools/snapshot.d.ts.map +1 -0
- package/build/tools/snapshot.js +78 -12
- package/build/tools/snapshot.js.map +1 -0
- package/build/tools/tools.d.ts +15 -0
- package/build/tools/tools.d.ts.map +1 -0
- package/build/tools/tools.js +63 -0
- package/build/tools/tools.js.map +1 -0
- package/build/tools.d.ts +431 -0
- package/build/tools.d.ts.map +1 -0
- package/build/tools.js +258 -118
- package/build/tools.js.map +1 -0
- package/build/types/errors.d.ts +189 -0
- package/build/types/errors.d.ts.map +1 -0
- package/build/types/errors.js +257 -0
- package/build/types/errors.js.map +1 -0
- package/build/utils/error.d.ts +6 -0
- package/build/utils/error.d.ts.map +1 -0
- package/build/utils/error.js +11 -0
- package/build/utils/error.js.map +1 -0
- package/build/utils/idGenerator.d.ts +21 -0
- package/build/utils/idGenerator.d.ts.map +1 -0
- package/build/utils/idGenerator.js +23 -0
- package/build/utils/idGenerator.js.map +1 -0
- package/build/version.d.ts +7 -0
- package/build/version.d.ts.map +1 -0
- package/build/version.js +10 -0
- package/build/version.js.map +1 -0
- package/package.json +31 -9
|
@@ -1,644 +1,369 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 连接管理工具
|
|
3
|
-
*
|
|
3
|
+
* 提供 connect / reconnect / disconnect / status 能力
|
|
4
4
|
*/
|
|
5
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment -- wx 运行时对象在 evaluate 上下文中动态注入,需保持现有注释抑制。 */
|
|
5
6
|
import { z } from 'zod';
|
|
6
|
-
import { defineTool } from './ToolDefinition.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
originalFail(err);
|
|
58
|
-
};
|
|
59
|
-
return this.origin(options);
|
|
7
|
+
import { defineTool, ToolCategory } from './ToolDefinition.js';
|
|
8
|
+
const strategyEnum = z.enum(['auto', 'launch', 'connect', 'wsEndpoint', 'browserUrl', 'discover']);
|
|
9
|
+
const connectSchema = z.object({
|
|
10
|
+
strategy: strategyEnum.optional().default('auto')
|
|
11
|
+
.describe('连接策略: auto/launch/connect/wsEndpoint/browserUrl/discover'),
|
|
12
|
+
projectPath: z.string().optional().describe('小程序项目的绝对路径'),
|
|
13
|
+
cliPath: z.string().optional().describe('微信开发者工具 CLI 绝对路径(可选)'),
|
|
14
|
+
autoPort: z.number().optional().describe('自动化监听端口(可选)'),
|
|
15
|
+
browserUrl: z.string().optional().describe('已运行实例的 HTTP 调试地址,如 http://127.0.0.1:9222'),
|
|
16
|
+
wsEndpoint: z.string().optional().describe('已运行实例的 WS 地址,如 ws://127.0.0.1:9420'),
|
|
17
|
+
wsHeaders: z.record(z.string()).optional().describe('WS 自定义请求头'),
|
|
18
|
+
timeoutMs: z.number().optional().default(45000).describe('连接超时时间(毫秒)'),
|
|
19
|
+
fallback: z.array(strategyEnum).optional().describe('连接失败时的回退策略序列'),
|
|
20
|
+
healthCheck: z.boolean().optional().default(true).describe('是否执行连接健康检查'),
|
|
21
|
+
autoDiscover: z.boolean().optional().default(true).describe('auto 策略下是否优先尝试自动发现端点'),
|
|
22
|
+
verbose: z.boolean().optional().default(false).describe('是否输出详细日志'),
|
|
23
|
+
autoAudits: z.boolean().optional().describe('launch/connect 策略下是否启用体验评分'),
|
|
24
|
+
});
|
|
25
|
+
const reconnectSchema = z.object({
|
|
26
|
+
strategy: strategyEnum.optional().describe('可选,覆盖上次连接策略'),
|
|
27
|
+
projectPath: z.string().optional().describe('可选,覆盖上次项目路径'),
|
|
28
|
+
cliPath: z.string().optional(),
|
|
29
|
+
autoPort: z.number().optional(),
|
|
30
|
+
browserUrl: z.string().optional(),
|
|
31
|
+
wsEndpoint: z.string().optional(),
|
|
32
|
+
wsHeaders: z.record(z.string()).optional(),
|
|
33
|
+
timeoutMs: z.number().optional(),
|
|
34
|
+
fallback: z.array(strategyEnum).optional(),
|
|
35
|
+
healthCheck: z.boolean().optional(),
|
|
36
|
+
autoDiscover: z.boolean().optional(),
|
|
37
|
+
verbose: z.boolean().optional(),
|
|
38
|
+
autoAudits: z.boolean().optional(),
|
|
39
|
+
});
|
|
40
|
+
const statusSchema = z.object({
|
|
41
|
+
refreshHealth: z.boolean().optional().default(true).describe('是否刷新健康检查状态'),
|
|
42
|
+
});
|
|
43
|
+
function toConnectionRequest(params) {
|
|
44
|
+
return {
|
|
45
|
+
strategy: params.strategy,
|
|
46
|
+
projectPath: params.projectPath,
|
|
47
|
+
cliPath: params.cliPath,
|
|
48
|
+
autoPort: params.autoPort,
|
|
49
|
+
browserUrl: params.browserUrl,
|
|
50
|
+
wsEndpoint: params.wsEndpoint,
|
|
51
|
+
wsHeaders: params.wsHeaders,
|
|
52
|
+
timeoutMs: params.timeoutMs,
|
|
53
|
+
fallback: params.fallback,
|
|
54
|
+
healthCheck: params.healthCheck,
|
|
55
|
+
autoDiscover: params.autoDiscover,
|
|
56
|
+
verbose: params.verbose,
|
|
57
|
+
autoAudits: params.autoAudits,
|
|
60
58
|
};
|
|
61
59
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
data: {
|
|
85
|
-
filePath: options.filePath,
|
|
86
|
-
name: options.name,
|
|
87
|
-
formData: options.formData
|
|
88
|
-
},
|
|
89
|
-
statusCode: res.statusCode,
|
|
90
|
-
response: res.data,
|
|
91
|
-
duration: Date.now() - startTime,
|
|
60
|
+
function formatHealthSummary(health) {
|
|
61
|
+
if (!health) {
|
|
62
|
+
return 'unknown';
|
|
63
|
+
}
|
|
64
|
+
return `${health.level} (${health.checks.length} checks)`;
|
|
65
|
+
}
|
|
66
|
+
function updateConsoleStorage(context, updater) {
|
|
67
|
+
const storage = context.consoleStorage;
|
|
68
|
+
updater(storage);
|
|
69
|
+
context.consoleStorage = storage;
|
|
70
|
+
}
|
|
71
|
+
function updateNetworkStorage(context, updater) {
|
|
72
|
+
const storage = context.networkStorage;
|
|
73
|
+
updater(storage);
|
|
74
|
+
context.networkStorage = storage;
|
|
75
|
+
}
|
|
76
|
+
async function startAutomaticMonitoring(miniProgram, context, response) {
|
|
77
|
+
try {
|
|
78
|
+
const consoleHandler = (msg) => {
|
|
79
|
+
const consoleMessage = {
|
|
80
|
+
type: msg.type || 'log',
|
|
81
|
+
args: msg.args || [],
|
|
92
82
|
timestamp: new Date().toISOString(),
|
|
93
|
-
|
|
83
|
+
source: 'miniprogram',
|
|
84
|
+
};
|
|
85
|
+
updateConsoleStorage(context, storage => {
|
|
86
|
+
const currentSession = storage.navigations[0];
|
|
87
|
+
if (!currentSession) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (storage.idGenerator) {
|
|
91
|
+
consoleMessage.msgid = storage.idGenerator();
|
|
92
|
+
if (consoleMessage.msgid !== undefined) {
|
|
93
|
+
storage.messageIdMap.set(consoleMessage.msgid, consoleMessage);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
currentSession.messages.push(consoleMessage);
|
|
94
97
|
});
|
|
95
|
-
if (originalSuccess)
|
|
96
|
-
originalSuccess(res);
|
|
97
98
|
};
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
type: 'uploadFile',
|
|
103
|
-
url: options.url,
|
|
104
|
-
headers: options.header,
|
|
105
|
-
data: {
|
|
106
|
-
filePath: options.filePath,
|
|
107
|
-
name: options.name,
|
|
108
|
-
formData: options.formData
|
|
109
|
-
},
|
|
110
|
-
error: err.errMsg || String(err),
|
|
111
|
-
duration: Date.now() - startTime,
|
|
99
|
+
const exceptionHandler = (err) => {
|
|
100
|
+
const exceptionMessage = {
|
|
101
|
+
message: err.message || 'Unknown exception',
|
|
102
|
+
stack: err.stack,
|
|
112
103
|
timestamp: new Date().toISOString(),
|
|
113
|
-
|
|
104
|
+
source: 'miniprogram',
|
|
105
|
+
};
|
|
106
|
+
updateConsoleStorage(context, storage => {
|
|
107
|
+
const currentSession = storage.navigations[0];
|
|
108
|
+
if (!currentSession) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (storage.idGenerator) {
|
|
112
|
+
exceptionMessage.msgid = storage.idGenerator();
|
|
113
|
+
if (exceptionMessage.msgid !== undefined) {
|
|
114
|
+
storage.messageIdMap.set(exceptionMessage.msgid, exceptionMessage);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
currentSession.exceptions.push(exceptionMessage);
|
|
114
118
|
});
|
|
115
|
-
if (originalFail)
|
|
116
|
-
originalFail(err);
|
|
117
119
|
};
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
*/
|
|
124
|
-
function createDownloadFileInterceptor() {
|
|
125
|
-
return function (options) {
|
|
126
|
-
// @ts-ignore - wx is available in WeChat miniprogram environment
|
|
127
|
-
const wxObj = (typeof wx !== 'undefined' ? wx : null);
|
|
128
|
-
if (!wxObj) {
|
|
129
|
-
return this.origin(options);
|
|
120
|
+
if (typeof context.bindConsoleAndExceptionListeners === 'function') {
|
|
121
|
+
context.bindConsoleAndExceptionListeners({
|
|
122
|
+
consoleHandler,
|
|
123
|
+
exceptionHandler,
|
|
124
|
+
});
|
|
130
125
|
}
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
else {
|
|
127
|
+
miniProgram.off('console', consoleHandler);
|
|
128
|
+
miniProgram.off('exception', exceptionHandler);
|
|
129
|
+
miniProgram.on('console', consoleHandler);
|
|
130
|
+
miniProgram.on('exception', exceptionHandler);
|
|
133
131
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
132
|
+
updateConsoleStorage(context, storage => {
|
|
133
|
+
storage.isMonitoring = true;
|
|
134
|
+
storage.startTime = new Date().toISOString();
|
|
135
|
+
});
|
|
136
|
+
response.appendResponseLine('Console监听已自动启动');
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
response.appendResponseLine(`警告: Console监听启动失败 - ${error instanceof Error ? error.message : String(error)}`);
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
if (!context.networkStorage.isMonitoring) {
|
|
143
|
+
await miniProgram.evaluate(function () {
|
|
144
|
+
// @ts-ignore
|
|
145
|
+
if (typeof wx === 'undefined' || wx.__networkInterceptorsInstalled)
|
|
146
|
+
return;
|
|
147
|
+
// @ts-ignore
|
|
148
|
+
wx.__networkLogs = wx.__networkLogs || [];
|
|
149
|
+
// @ts-ignore
|
|
150
|
+
wx.__networkLogsLimit = 1000;
|
|
151
|
+
// @ts-ignore
|
|
152
|
+
wx.__networkInterceptorsDisabled = false;
|
|
153
|
+
// @ts-ignore
|
|
154
|
+
wx.__pushNetworkLog = function (log) {
|
|
155
|
+
// @ts-ignore
|
|
156
|
+
if (wx.__networkInterceptorsDisabled)
|
|
157
|
+
return;
|
|
158
|
+
// @ts-ignore
|
|
159
|
+
wx.__networkLogs.push(log);
|
|
160
|
+
// @ts-ignore
|
|
161
|
+
while (wx.__networkLogs.length > wx.__networkLogsLimit) {
|
|
162
|
+
// @ts-ignore
|
|
163
|
+
wx.__networkLogs.shift();
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
// @ts-ignore
|
|
167
|
+
const _originalRequest = wx.request;
|
|
168
|
+
// @ts-ignore
|
|
169
|
+
const _originalUploadFile = wx.uploadFile;
|
|
170
|
+
// @ts-ignore
|
|
171
|
+
const _originalDownloadFile = wx.downloadFile;
|
|
172
|
+
// @ts-ignore
|
|
173
|
+
delete wx.request;
|
|
174
|
+
// @ts-ignore
|
|
175
|
+
Object.defineProperty(wx, 'request', {
|
|
176
|
+
configurable: true,
|
|
177
|
+
value: function (options) {
|
|
178
|
+
// @ts-ignore
|
|
179
|
+
if (wx.__networkInterceptorsDisabled)
|
|
180
|
+
return _originalRequest.call(this, options);
|
|
181
|
+
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
182
|
+
const start = Date.now();
|
|
183
|
+
const origSuccess = options.success;
|
|
184
|
+
const origFail = options.fail;
|
|
185
|
+
options.success = function (res) {
|
|
186
|
+
// @ts-ignore
|
|
187
|
+
wx.__pushNetworkLog({ id, type: 'request', url: options.url, method: options.method || 'GET',
|
|
188
|
+
headers: options.header, data: options.data, statusCode: res.statusCode,
|
|
189
|
+
response: res.data, duration: Date.now() - start, timestamp: new Date().toISOString(), success: true });
|
|
190
|
+
if (origSuccess)
|
|
191
|
+
origSuccess.call(this, res);
|
|
192
|
+
};
|
|
193
|
+
options.fail = function (err) {
|
|
194
|
+
// @ts-ignore
|
|
195
|
+
wx.__pushNetworkLog({ id, type: 'request', url: options.url, method: options.method || 'GET',
|
|
196
|
+
headers: options.header, data: options.data, error: err.errMsg || String(err),
|
|
197
|
+
duration: Date.now() - start, timestamp: new Date().toISOString(), success: false });
|
|
198
|
+
if (origFail)
|
|
199
|
+
origFail.call(this, err);
|
|
200
|
+
};
|
|
201
|
+
return _originalRequest.call(this, options);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
// @ts-ignore
|
|
205
|
+
delete wx.uploadFile;
|
|
206
|
+
// @ts-ignore
|
|
207
|
+
Object.defineProperty(wx, 'uploadFile', {
|
|
208
|
+
configurable: true,
|
|
209
|
+
value: function (options) {
|
|
210
|
+
// @ts-ignore
|
|
211
|
+
if (wx.__networkInterceptorsDisabled)
|
|
212
|
+
return _originalUploadFile.call(this, options);
|
|
213
|
+
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
214
|
+
const start = Date.now();
|
|
215
|
+
const origSuccess = options.success;
|
|
216
|
+
const origFail = options.fail;
|
|
217
|
+
options.success = function (res) {
|
|
218
|
+
// @ts-ignore
|
|
219
|
+
wx.__pushNetworkLog({ id, type: 'uploadFile', url: options.url, headers: options.header,
|
|
220
|
+
data: { filePath: options.filePath, name: options.name, formData: options.formData },
|
|
221
|
+
statusCode: res.statusCode, response: res.data, duration: Date.now() - start,
|
|
222
|
+
timestamp: new Date().toISOString(), success: true });
|
|
223
|
+
if (origSuccess)
|
|
224
|
+
origSuccess.call(this, res);
|
|
225
|
+
};
|
|
226
|
+
options.fail = function (err) {
|
|
227
|
+
// @ts-ignore
|
|
228
|
+
wx.__pushNetworkLog({ id, type: 'uploadFile', url: options.url, headers: options.header,
|
|
229
|
+
data: { filePath: options.filePath, name: options.name, formData: options.formData },
|
|
230
|
+
error: err.errMsg || String(err), duration: Date.now() - start,
|
|
231
|
+
timestamp: new Date().toISOString(), success: false });
|
|
232
|
+
if (origFail)
|
|
233
|
+
origFail.call(this, err);
|
|
234
|
+
};
|
|
235
|
+
return _originalUploadFile.call(this, options);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
// @ts-ignore
|
|
239
|
+
delete wx.downloadFile;
|
|
240
|
+
// @ts-ignore
|
|
241
|
+
Object.defineProperty(wx, 'downloadFile', {
|
|
242
|
+
configurable: true,
|
|
243
|
+
value: function (options) {
|
|
244
|
+
// @ts-ignore
|
|
245
|
+
if (wx.__networkInterceptorsDisabled)
|
|
246
|
+
return _originalDownloadFile.call(this, options);
|
|
247
|
+
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
248
|
+
const start = Date.now();
|
|
249
|
+
const origSuccess = options.success;
|
|
250
|
+
const origFail = options.fail;
|
|
251
|
+
options.success = function (res) {
|
|
252
|
+
// @ts-ignore
|
|
253
|
+
wx.__pushNetworkLog({ id, type: 'downloadFile', url: options.url, headers: options.header,
|
|
254
|
+
statusCode: res.statusCode, response: { tempFilePath: res.tempFilePath, filePath: res.filePath },
|
|
255
|
+
duration: Date.now() - start, timestamp: new Date().toISOString(), success: true });
|
|
256
|
+
if (origSuccess)
|
|
257
|
+
origSuccess.call(this, res);
|
|
258
|
+
};
|
|
259
|
+
options.fail = function (err) {
|
|
260
|
+
// @ts-ignore
|
|
261
|
+
wx.__pushNetworkLog({ id, type: 'downloadFile', url: options.url, headers: options.header,
|
|
262
|
+
error: err.errMsg || String(err), duration: Date.now() - start,
|
|
263
|
+
timestamp: new Date().toISOString(), success: false });
|
|
264
|
+
if (origFail)
|
|
265
|
+
origFail.call(this, err);
|
|
266
|
+
};
|
|
267
|
+
return _originalDownloadFile.call(this, options);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
// @ts-ignore
|
|
271
|
+
wx.__networkInterceptorsInstalled = true;
|
|
151
272
|
});
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const originalFail = options.fail;
|
|
156
|
-
options.fail = function (err) {
|
|
157
|
-
wxObj.__networkLogs.push({
|
|
158
|
-
id: requestId,
|
|
159
|
-
type: 'downloadFile',
|
|
160
|
-
url: options.url,
|
|
161
|
-
headers: options.header,
|
|
162
|
-
error: err.errMsg || String(err),
|
|
163
|
-
duration: Date.now() - startTime,
|
|
164
|
-
timestamp: new Date().toISOString(),
|
|
165
|
-
success: false
|
|
273
|
+
updateNetworkStorage(context, storage => {
|
|
274
|
+
storage.isMonitoring = true;
|
|
275
|
+
storage.startTime = new Date().toISOString();
|
|
166
276
|
});
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
277
|
+
}
|
|
278
|
+
response.appendResponseLine('网络监听已自动启动(增强型拦截)');
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
response.appendResponseLine(`警告: 网络监听启动失败 - ${error instanceof Error ? error.message : String(error)}`);
|
|
282
|
+
}
|
|
172
283
|
}
|
|
173
|
-
/**
|
|
174
|
-
* 连接到微信开发者工具(传统版)
|
|
175
|
-
*/
|
|
176
284
|
export const connectDevtoolsTool = defineTool({
|
|
177
285
|
name: 'connect_devtools',
|
|
178
|
-
description: '
|
|
179
|
-
schema:
|
|
180
|
-
projectPath: z.string().describe('小程序项目的绝对路径'),
|
|
181
|
-
cliPath: z.string().optional().describe('微信开发者工具CLI的绝对路径(可选,默认会自动查找)'),
|
|
182
|
-
port: z.number().optional().describe('WebSocket端口号(可选,默认自动分配)'),
|
|
183
|
-
}),
|
|
286
|
+
description: '连接微信开发者工具,支持多入口策略和自动回退',
|
|
287
|
+
schema: connectSchema,
|
|
184
288
|
annotations: {
|
|
289
|
+
category: ToolCategory.CORE,
|
|
185
290
|
audience: ['developers'],
|
|
186
291
|
},
|
|
187
292
|
handler: async (request, response, context) => {
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
response.appendResponseLine(`当前页面: ${pagePath}`);
|
|
199
|
-
response.appendResponseLine(`说明: 跳过重新连接,使用已建立的连接`);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
catch (error) {
|
|
203
|
-
// 连接已失效,清空并继续新建连接
|
|
204
|
-
context.miniProgram = null;
|
|
205
|
-
context.currentPage = null;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
try {
|
|
209
|
-
const options = { projectPath };
|
|
210
|
-
if (cliPath)
|
|
211
|
-
options.cliPath = cliPath;
|
|
212
|
-
if (port)
|
|
213
|
-
options.port = port;
|
|
214
|
-
const result = await connectDevtools(options);
|
|
215
|
-
// 更新上下文
|
|
216
|
-
context.miniProgram = result.miniProgram;
|
|
217
|
-
context.currentPage = result.currentPage;
|
|
218
|
-
context.elementMap.clear();
|
|
219
|
-
// 自动启动console监听
|
|
220
|
-
try {
|
|
221
|
-
// 清除之前的监听器(如果有的话)
|
|
222
|
-
context.miniProgram.removeAllListeners('console');
|
|
223
|
-
context.miniProgram.removeAllListeners('exception');
|
|
224
|
-
// 启动console监听
|
|
225
|
-
context.consoleStorage.isMonitoring = true;
|
|
226
|
-
context.consoleStorage.startTime = new Date().toISOString();
|
|
227
|
-
context.miniProgram.on('console', (msg) => {
|
|
228
|
-
const consoleMessage = {
|
|
229
|
-
type: msg.type || 'log',
|
|
230
|
-
args: msg.args || [],
|
|
231
|
-
timestamp: new Date().toISOString(),
|
|
232
|
-
source: 'miniprogram'
|
|
233
|
-
};
|
|
234
|
-
context.consoleStorage.consoleMessages.push(consoleMessage);
|
|
235
|
-
console.log(`[Console ${msg.type}]:`, msg.args);
|
|
236
|
-
});
|
|
237
|
-
context.miniProgram.on('exception', (err) => {
|
|
238
|
-
const exceptionMessage = {
|
|
239
|
-
message: err.message || String(err),
|
|
240
|
-
stack: err.stack,
|
|
241
|
-
timestamp: new Date().toISOString(),
|
|
242
|
-
source: 'miniprogram'
|
|
243
|
-
};
|
|
244
|
-
context.consoleStorage.exceptionMessages.push(exceptionMessage);
|
|
245
|
-
console.log(`[Exception]:`, err.message, err.stack);
|
|
246
|
-
});
|
|
247
|
-
response.appendResponseLine(`Console监听已自动启动`);
|
|
248
|
-
}
|
|
249
|
-
catch (consoleError) {
|
|
250
|
-
response.appendResponseLine(`警告: Console监听启动失败 - ${consoleError instanceof Error ? consoleError.message : String(consoleError)}`);
|
|
251
|
-
}
|
|
252
|
-
// 自动启动网络监听(使用evaluate()方式绕过框架限制)
|
|
253
|
-
try {
|
|
254
|
-
if (!context.networkStorage.isMonitoring) {
|
|
255
|
-
// 使用与network.ts相同的evaluate()注入方式,增加Mpx框架支持
|
|
256
|
-
await context.miniProgram.evaluate(function () {
|
|
257
|
-
// @ts-ignore
|
|
258
|
-
if (typeof wx === 'undefined' || wx.__networkInterceptorsInstalled) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
// @ts-ignore
|
|
262
|
-
wx.__networkLogs = wx.__networkLogs || [];
|
|
263
|
-
// Mpx 拦截器已在 tools.ts 的 connectDevtools() 中统一注入
|
|
264
|
-
// 此处仅保留 wx.request 回退拦截器(用于非 Mpx 框架或直接调用 wx API 的场景)
|
|
265
|
-
// 保存原始方法(通过getter获取)
|
|
266
|
-
// @ts-ignore
|
|
267
|
-
const _originalRequest = wx.request;
|
|
268
|
-
// @ts-ignore
|
|
269
|
-
const _originalUploadFile = wx.uploadFile;
|
|
270
|
-
// @ts-ignore
|
|
271
|
-
const _originalDownloadFile = wx.downloadFile;
|
|
272
|
-
// 拦截wx.request - 先删除getter
|
|
273
|
-
// @ts-ignore
|
|
274
|
-
delete wx.request;
|
|
275
|
-
// @ts-ignore
|
|
276
|
-
Object.defineProperty(wx, 'request', {
|
|
277
|
-
configurable: true,
|
|
278
|
-
value: function (options) {
|
|
279
|
-
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
280
|
-
const start = Date.now();
|
|
281
|
-
const origSuccess = options.success;
|
|
282
|
-
const origFail = options.fail;
|
|
283
|
-
options.success = function (res) {
|
|
284
|
-
// @ts-ignore
|
|
285
|
-
wx.__networkLogs.push({
|
|
286
|
-
id, type: 'request', url: options.url, method: options.method || 'GET',
|
|
287
|
-
headers: options.header, data: options.data, statusCode: res.statusCode,
|
|
288
|
-
response: res.data, duration: Date.now() - start,
|
|
289
|
-
timestamp: new Date().toISOString(), success: true
|
|
290
|
-
});
|
|
291
|
-
if (origSuccess)
|
|
292
|
-
origSuccess.call(this, res);
|
|
293
|
-
};
|
|
294
|
-
options.fail = function (err) {
|
|
295
|
-
// @ts-ignore
|
|
296
|
-
wx.__networkLogs.push({
|
|
297
|
-
id, type: 'request', url: options.url, method: options.method || 'GET',
|
|
298
|
-
headers: options.header, data: options.data, error: err.errMsg || String(err),
|
|
299
|
-
duration: Date.now() - start, timestamp: new Date().toISOString(), success: false
|
|
300
|
-
});
|
|
301
|
-
if (origFail)
|
|
302
|
-
origFail.call(this, err);
|
|
303
|
-
};
|
|
304
|
-
return _originalRequest.call(this, options);
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
// 拦截wx.uploadFile - 先删除getter
|
|
308
|
-
// @ts-ignore
|
|
309
|
-
delete wx.uploadFile;
|
|
310
|
-
// @ts-ignore
|
|
311
|
-
Object.defineProperty(wx, 'uploadFile', {
|
|
312
|
-
configurable: true,
|
|
313
|
-
value: function (options) {
|
|
314
|
-
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
315
|
-
const start = Date.now();
|
|
316
|
-
const origSuccess = options.success;
|
|
317
|
-
const origFail = options.fail;
|
|
318
|
-
options.success = function (res) {
|
|
319
|
-
// @ts-ignore
|
|
320
|
-
wx.__networkLogs.push({
|
|
321
|
-
id, type: 'uploadFile', url: options.url, headers: options.header,
|
|
322
|
-
data: { filePath: options.filePath, name: options.name, formData: options.formData },
|
|
323
|
-
statusCode: res.statusCode, response: res.data, duration: Date.now() - start,
|
|
324
|
-
timestamp: new Date().toISOString(), success: true
|
|
325
|
-
});
|
|
326
|
-
if (origSuccess)
|
|
327
|
-
origSuccess.call(this, res);
|
|
328
|
-
};
|
|
329
|
-
options.fail = function (err) {
|
|
330
|
-
// @ts-ignore
|
|
331
|
-
wx.__networkLogs.push({
|
|
332
|
-
id, type: 'uploadFile', url: options.url, headers: options.header,
|
|
333
|
-
data: { filePath: options.filePath, name: options.name, formData: options.formData },
|
|
334
|
-
error: err.errMsg || String(err), duration: Date.now() - start,
|
|
335
|
-
timestamp: new Date().toISOString(), success: false
|
|
336
|
-
});
|
|
337
|
-
if (origFail)
|
|
338
|
-
origFail.call(this, err);
|
|
339
|
-
};
|
|
340
|
-
return _originalUploadFile.call(this, options);
|
|
341
|
-
}
|
|
342
|
-
});
|
|
343
|
-
// 拦截wx.downloadFile - 先删除getter
|
|
344
|
-
// @ts-ignore
|
|
345
|
-
delete wx.downloadFile;
|
|
346
|
-
// @ts-ignore
|
|
347
|
-
Object.defineProperty(wx, 'downloadFile', {
|
|
348
|
-
configurable: true,
|
|
349
|
-
value: function (options) {
|
|
350
|
-
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
351
|
-
const start = Date.now();
|
|
352
|
-
const origSuccess = options.success;
|
|
353
|
-
const origFail = options.fail;
|
|
354
|
-
options.success = function (res) {
|
|
355
|
-
// @ts-ignore
|
|
356
|
-
wx.__networkLogs.push({
|
|
357
|
-
id, type: 'downloadFile', url: options.url, headers: options.header,
|
|
358
|
-
statusCode: res.statusCode, response: { tempFilePath: res.tempFilePath, filePath: res.filePath },
|
|
359
|
-
duration: Date.now() - start, timestamp: new Date().toISOString(), success: true
|
|
360
|
-
});
|
|
361
|
-
if (origSuccess)
|
|
362
|
-
origSuccess.call(this, res);
|
|
363
|
-
};
|
|
364
|
-
options.fail = function (err) {
|
|
365
|
-
// @ts-ignore
|
|
366
|
-
wx.__networkLogs.push({
|
|
367
|
-
id, type: 'downloadFile', url: options.url, headers: options.header,
|
|
368
|
-
error: err.errMsg || String(err), duration: Date.now() - start,
|
|
369
|
-
timestamp: new Date().toISOString(), success: false
|
|
370
|
-
});
|
|
371
|
-
if (origFail)
|
|
372
|
-
origFail.call(this, err);
|
|
373
|
-
};
|
|
374
|
-
return _originalDownloadFile.call(this, options);
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
// @ts-ignore
|
|
378
|
-
wx.__networkInterceptorsInstalled = true;
|
|
379
|
-
});
|
|
380
|
-
context.networkStorage.isMonitoring = true;
|
|
381
|
-
context.networkStorage.startTime = new Date().toISOString();
|
|
382
|
-
}
|
|
383
|
-
response.appendResponseLine(`网络监听已自动启动(增强型拦截)`);
|
|
384
|
-
}
|
|
385
|
-
catch (networkError) {
|
|
386
|
-
response.appendResponseLine(`警告: 网络监听启动失败 - ${networkError instanceof Error ? networkError.message : String(networkError)}`);
|
|
387
|
-
}
|
|
388
|
-
response.appendResponseLine(`成功连接到微信开发者工具 (传统模式)`);
|
|
389
|
-
response.appendResponseLine(`项目路径: ${projectPath}`);
|
|
390
|
-
response.appendResponseLine(`当前页面: ${result.pagePath}`);
|
|
293
|
+
const result = await context.connectDevtools(toConnectionRequest(request.params));
|
|
294
|
+
await startAutomaticMonitoring(result.miniProgram, context, response);
|
|
295
|
+
response.appendResponseLine('✅ 连接成功');
|
|
296
|
+
response.appendResponseLine(`连接ID: ${result.connectionId}`);
|
|
297
|
+
response.appendResponseLine(`策略: ${result.strategyUsed}`);
|
|
298
|
+
response.appendResponseLine(`连接状态: ${result.status}`);
|
|
299
|
+
response.appendResponseLine(`健康检查: ${formatHealthSummary(result.health)}`);
|
|
300
|
+
response.appendResponseLine(`当前页面: ${result.pagePath}`);
|
|
301
|
+
if (result.endpoint) {
|
|
302
|
+
response.appendResponseLine(`端点: ${result.endpoint}`);
|
|
391
303
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
response.appendResponseLine(
|
|
395
|
-
throw error;
|
|
304
|
+
response.appendResponseLine(`耗时: total=${result.timing.totalMs}ms, connect=${result.timing.connectMs}ms, health=${result.timing.healthMs}ms`);
|
|
305
|
+
if (result.warnings.length > 0) {
|
|
306
|
+
response.appendResponseLine(`回退告警: ${result.warnings.join(' | ')}`);
|
|
396
307
|
}
|
|
397
308
|
},
|
|
398
309
|
});
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
name: 'connect_devtools_enhanced',
|
|
404
|
-
description: '智能连接到微信开发者工具,支持多种模式和自动回退(推荐)',
|
|
405
|
-
schema: z.object({
|
|
406
|
-
projectPath: z.string().describe('小程序项目的绝对路径'),
|
|
407
|
-
mode: z.enum(['auto', 'launch', 'connect']).optional().default('auto')
|
|
408
|
-
.describe('连接模式: auto(智能), launch(传统), connect(两阶段)'),
|
|
409
|
-
cliPath: z.string().optional().describe('微信开发者工具CLI的绝对路径(可选)'),
|
|
410
|
-
autoPort: z.number().optional().describe('自动化监听端口(可选,默认自动检测)'),
|
|
411
|
-
autoAccount: z.string().optional().describe('指定用户openid(--auto-account)'),
|
|
412
|
-
timeout: z.number().optional().default(45000).describe('连接超时时间(毫秒)'),
|
|
413
|
-
fallbackMode: z.boolean().optional().default(true).describe('允许模式回退'),
|
|
414
|
-
healthCheck: z.boolean().optional().default(true).describe('执行健康检查'),
|
|
415
|
-
verbose: z.boolean().optional().default(false).describe('详细日志输出'),
|
|
416
|
-
}),
|
|
310
|
+
export const reconnectDevtoolsTool = defineTool({
|
|
311
|
+
name: 'reconnect_devtools',
|
|
312
|
+
description: '重新连接微信开发者工具,可复用上一次连接参数',
|
|
313
|
+
schema: reconnectSchema,
|
|
417
314
|
annotations: {
|
|
315
|
+
category: ToolCategory.CORE,
|
|
418
316
|
audience: ['developers'],
|
|
419
317
|
},
|
|
420
318
|
handler: async (request, response, context) => {
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
// 启动console监听
|
|
470
|
-
context.consoleStorage.isMonitoring = true;
|
|
471
|
-
context.consoleStorage.startTime = new Date().toISOString();
|
|
472
|
-
context.miniProgram.on('console', (msg) => {
|
|
473
|
-
const consoleMessage = {
|
|
474
|
-
type: msg.type || 'log',
|
|
475
|
-
args: msg.args || [],
|
|
476
|
-
timestamp: new Date().toISOString(),
|
|
477
|
-
source: 'miniprogram'
|
|
478
|
-
};
|
|
479
|
-
context.consoleStorage.consoleMessages.push(consoleMessage);
|
|
480
|
-
console.log(`[Console ${msg.type}]:`, msg.args);
|
|
481
|
-
});
|
|
482
|
-
context.miniProgram.on('exception', (err) => {
|
|
483
|
-
const exceptionMessage = {
|
|
484
|
-
message: err.message || String(err),
|
|
485
|
-
stack: err.stack,
|
|
486
|
-
timestamp: new Date().toISOString(),
|
|
487
|
-
source: 'miniprogram'
|
|
488
|
-
};
|
|
489
|
-
context.consoleStorage.exceptionMessages.push(exceptionMessage);
|
|
490
|
-
console.log(`[Exception]:`, err.message, err.stack);
|
|
491
|
-
});
|
|
492
|
-
response.appendResponseLine(`Console监听已自动启动`);
|
|
493
|
-
}
|
|
494
|
-
catch (consoleError) {
|
|
495
|
-
response.appendResponseLine(`警告: Console监听启动失败 - ${consoleError instanceof Error ? consoleError.message : String(consoleError)}`);
|
|
496
|
-
}
|
|
497
|
-
// 自动启动网络监听(使用evaluate()方式绕过框架限制)
|
|
498
|
-
try {
|
|
499
|
-
if (!context.networkStorage.isMonitoring) {
|
|
500
|
-
// 使用evaluate()注入拦截器(与第一个工具相同的逻辑)
|
|
501
|
-
await context.miniProgram.evaluate(function () {
|
|
502
|
-
// @ts-ignore
|
|
503
|
-
if (typeof wx === 'undefined' || wx.__networkInterceptorsInstalled)
|
|
504
|
-
return;
|
|
505
|
-
// @ts-ignore
|
|
506
|
-
wx.__networkLogs = wx.__networkLogs || [];
|
|
507
|
-
// Mpx 拦截器已在 tools.ts 的 connectDevtools() 中统一注入
|
|
508
|
-
// 此处仅保留 wx.request 回退拦截器(用于非 Mpx 框架或直接调用 wx API 的场景)
|
|
509
|
-
// @ts-ignore - 保存原始方法(通过getter获取)
|
|
510
|
-
const _originalRequest = wx.request;
|
|
511
|
-
// @ts-ignore
|
|
512
|
-
const _originalUploadFile = wx.uploadFile;
|
|
513
|
-
// @ts-ignore
|
|
514
|
-
const _originalDownloadFile = wx.downloadFile;
|
|
515
|
-
// @ts-ignore - 先删除getter
|
|
516
|
-
delete wx.request;
|
|
517
|
-
// @ts-ignore
|
|
518
|
-
Object.defineProperty(wx, 'request', {
|
|
519
|
-
configurable: true,
|
|
520
|
-
value: function (options) {
|
|
521
|
-
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
522
|
-
const start = Date.now();
|
|
523
|
-
const origSuccess = options.success;
|
|
524
|
-
const origFail = options.fail;
|
|
525
|
-
options.success = function (res) {
|
|
526
|
-
// @ts-ignore
|
|
527
|
-
wx.__networkLogs.push({ id, type: 'request', url: options.url, method: options.method || 'GET',
|
|
528
|
-
headers: options.header, data: options.data, statusCode: res.statusCode,
|
|
529
|
-
response: res.data, duration: Date.now() - start, timestamp: new Date().toISOString(), success: true });
|
|
530
|
-
if (origSuccess)
|
|
531
|
-
origSuccess.call(this, res);
|
|
532
|
-
};
|
|
533
|
-
options.fail = function (err) {
|
|
534
|
-
// @ts-ignore
|
|
535
|
-
wx.__networkLogs.push({ id, type: 'request', url: options.url, method: options.method || 'GET',
|
|
536
|
-
headers: options.header, data: options.data, error: err.errMsg || String(err),
|
|
537
|
-
duration: Date.now() - start, timestamp: new Date().toISOString(), success: false });
|
|
538
|
-
if (origFail)
|
|
539
|
-
origFail.call(this, err);
|
|
540
|
-
};
|
|
541
|
-
return _originalRequest.call(this, options);
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
// @ts-ignore - 先删除getter
|
|
545
|
-
delete wx.uploadFile;
|
|
546
|
-
// @ts-ignore
|
|
547
|
-
Object.defineProperty(wx, 'uploadFile', {
|
|
548
|
-
configurable: true,
|
|
549
|
-
value: function (options) {
|
|
550
|
-
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
551
|
-
const start = Date.now();
|
|
552
|
-
const origSuccess = options.success;
|
|
553
|
-
const origFail = options.fail;
|
|
554
|
-
options.success = function (res) {
|
|
555
|
-
// @ts-ignore
|
|
556
|
-
wx.__networkLogs.push({ id, type: 'uploadFile', url: options.url, headers: options.header,
|
|
557
|
-
data: { filePath: options.filePath, name: options.name, formData: options.formData },
|
|
558
|
-
statusCode: res.statusCode, response: res.data, duration: Date.now() - start,
|
|
559
|
-
timestamp: new Date().toISOString(), success: true });
|
|
560
|
-
if (origSuccess)
|
|
561
|
-
origSuccess.call(this, res);
|
|
562
|
-
};
|
|
563
|
-
options.fail = function (err) {
|
|
564
|
-
// @ts-ignore
|
|
565
|
-
wx.__networkLogs.push({ id, type: 'uploadFile', url: options.url, headers: options.header,
|
|
566
|
-
data: { filePath: options.filePath, name: options.name, formData: options.formData },
|
|
567
|
-
error: err.errMsg || String(err), duration: Date.now() - start,
|
|
568
|
-
timestamp: new Date().toISOString(), success: false });
|
|
569
|
-
if (origFail)
|
|
570
|
-
origFail.call(this, err);
|
|
571
|
-
};
|
|
572
|
-
return _originalUploadFile.call(this, options);
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
// @ts-ignore - 先删除getter
|
|
576
|
-
delete wx.downloadFile;
|
|
577
|
-
// @ts-ignore
|
|
578
|
-
Object.defineProperty(wx, 'downloadFile', {
|
|
579
|
-
configurable: true,
|
|
580
|
-
value: function (options) {
|
|
581
|
-
const id = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
|
|
582
|
-
const start = Date.now();
|
|
583
|
-
const origSuccess = options.success;
|
|
584
|
-
const origFail = options.fail;
|
|
585
|
-
options.success = function (res) {
|
|
586
|
-
// @ts-ignore
|
|
587
|
-
wx.__networkLogs.push({ id, type: 'downloadFile', url: options.url, headers: options.header,
|
|
588
|
-
statusCode: res.statusCode, response: { tempFilePath: res.tempFilePath, filePath: res.filePath },
|
|
589
|
-
duration: Date.now() - start, timestamp: new Date().toISOString(), success: true });
|
|
590
|
-
if (origSuccess)
|
|
591
|
-
origSuccess.call(this, res);
|
|
592
|
-
};
|
|
593
|
-
options.fail = function (err) {
|
|
594
|
-
// @ts-ignore
|
|
595
|
-
wx.__networkLogs.push({ id, type: 'downloadFile', url: options.url, headers: options.header,
|
|
596
|
-
error: err.errMsg || String(err), duration: Date.now() - start,
|
|
597
|
-
timestamp: new Date().toISOString(), success: false });
|
|
598
|
-
if (origFail)
|
|
599
|
-
origFail.call(this, err);
|
|
600
|
-
};
|
|
601
|
-
return _originalDownloadFile.call(this, options);
|
|
602
|
-
}
|
|
603
|
-
});
|
|
604
|
-
// @ts-ignore
|
|
605
|
-
wx.__networkInterceptorsInstalled = true;
|
|
606
|
-
});
|
|
607
|
-
context.networkStorage.isMonitoring = true;
|
|
608
|
-
context.networkStorage.startTime = new Date().toISOString();
|
|
609
|
-
}
|
|
610
|
-
response.appendResponseLine(`网络监听已自动启动(增强型拦截)`);
|
|
611
|
-
}
|
|
612
|
-
catch (networkError) {
|
|
613
|
-
response.appendResponseLine(`警告: 网络监听启动失败 - ${networkError instanceof Error ? networkError.message : String(networkError)}`);
|
|
614
|
-
}
|
|
615
|
-
// 根据结果显示详细信息
|
|
616
|
-
response.appendResponseLine(`✅ 智能连接成功`);
|
|
617
|
-
response.appendResponseLine(`项目路径: ${projectPath}`);
|
|
618
|
-
response.appendResponseLine(`当前页面: ${result.pagePath}`);
|
|
619
|
-
response.appendResponseLine(`连接模式: ${result.connectionMode}`);
|
|
620
|
-
response.appendResponseLine(`启动耗时: ${result.startupTime}ms`);
|
|
621
|
-
response.appendResponseLine(`健康状态: ${result.healthStatus}`);
|
|
622
|
-
if (result.processInfo) {
|
|
623
|
-
response.appendResponseLine(`进程信息: PID=${result.processInfo.pid}, Port=${result.processInfo.port}`);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
catch (error) {
|
|
627
|
-
// 处理增强错误信息
|
|
628
|
-
if (error instanceof DevToolsConnectionError) {
|
|
629
|
-
response.appendResponseLine(`❗ ${error.phase}阶段失败: ${error.message}`);
|
|
630
|
-
if (error.originalError) {
|
|
631
|
-
response.appendResponseLine(`原始错误: ${error.originalError.message}`);
|
|
632
|
-
}
|
|
633
|
-
if (error.details && verbose) {
|
|
634
|
-
response.appendResponseLine(`详细信息: ${JSON.stringify(error.details, null, 2)}`);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
else {
|
|
638
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
639
|
-
response.appendResponseLine(`连接失败: ${errorMessage}`);
|
|
640
|
-
}
|
|
641
|
-
throw error;
|
|
319
|
+
const params = toConnectionRequest(request.params);
|
|
320
|
+
const hasOverride = Object.values(params).some(value => value !== undefined);
|
|
321
|
+
const result = hasOverride
|
|
322
|
+
? await context.reconnectDevtools(params)
|
|
323
|
+
: await context.reconnectDevtools();
|
|
324
|
+
await startAutomaticMonitoring(result.miniProgram, context, response);
|
|
325
|
+
response.appendResponseLine('✅ 重连成功');
|
|
326
|
+
response.appendResponseLine(`连接ID: ${result.connectionId}`);
|
|
327
|
+
response.appendResponseLine(`策略: ${result.strategyUsed}`);
|
|
328
|
+
response.appendResponseLine(`连接状态: ${result.status}`);
|
|
329
|
+
response.appendResponseLine(`健康检查: ${formatHealthSummary(result.health)}`);
|
|
330
|
+
response.appendResponseLine(`当前页面: ${result.pagePath}`);
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
export const disconnectDevtoolsTool = defineTool({
|
|
334
|
+
name: 'disconnect_devtools',
|
|
335
|
+
description: '断开与微信开发者工具的连接并清理上下文状态',
|
|
336
|
+
schema: z.object({}),
|
|
337
|
+
annotations: {
|
|
338
|
+
category: ToolCategory.CORE,
|
|
339
|
+
audience: ['developers'],
|
|
340
|
+
},
|
|
341
|
+
handler: async (_request, response, context) => {
|
|
342
|
+
const status = await context.disconnectDevtools();
|
|
343
|
+
response.appendResponseLine('✅ 已断开连接');
|
|
344
|
+
response.appendResponseLine(`当前状态: ${status.state}`);
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
export const getConnectionStatusTool = defineTool({
|
|
348
|
+
name: 'get_connection_status',
|
|
349
|
+
description: '获取当前连接状态(可选刷新健康检查)',
|
|
350
|
+
schema: statusSchema,
|
|
351
|
+
annotations: {
|
|
352
|
+
category: ToolCategory.CORE,
|
|
353
|
+
audience: ['developers'],
|
|
354
|
+
},
|
|
355
|
+
handler: async (request, response, context) => {
|
|
356
|
+
const params = request.params;
|
|
357
|
+
const status = await context.getConnectionStatus({
|
|
358
|
+
refreshHealth: params.refreshHealth,
|
|
359
|
+
});
|
|
360
|
+
response.appendResponseLine(`连接状态: ${status.state}`);
|
|
361
|
+
response.appendResponseLine(`已连接: ${status.connected ? '是' : '否'}`);
|
|
362
|
+
response.appendResponseLine(`策略: ${status.strategyUsed ?? 'N/A'}`);
|
|
363
|
+
response.appendResponseLine(`页面: ${status.pagePath ?? 'N/A'}`);
|
|
364
|
+
response.appendResponseLine(`健康检查: ${formatHealthSummary(status.health)}`);
|
|
365
|
+
if (status.lastError) {
|
|
366
|
+
response.appendResponseLine(`最近错误: [${status.lastError.code}] ${status.lastError.message}`);
|
|
642
367
|
}
|
|
643
368
|
},
|
|
644
369
|
});
|
|
@@ -650,9 +375,10 @@ export const getCurrentPageTool = defineTool({
|
|
|
650
375
|
description: '获取当前页面信息并设置为活动页面',
|
|
651
376
|
schema: z.object({}),
|
|
652
377
|
annotations: {
|
|
378
|
+
category: ToolCategory.CORE,
|
|
653
379
|
audience: ['developers'],
|
|
654
380
|
},
|
|
655
|
-
handler: async (
|
|
381
|
+
handler: async (_request, response, context) => {
|
|
656
382
|
if (!context.miniProgram) {
|
|
657
383
|
throw new Error('请先连接到微信开发者工具');
|
|
658
384
|
}
|
|
@@ -668,3 +394,4 @@ export const getCurrentPageTool = defineTool({
|
|
|
668
394
|
}
|
|
669
395
|
},
|
|
670
396
|
});
|
|
397
|
+
//# sourceMappingURL=connection.js.map
|