weixin-devtools-mcp 0.0.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.
@@ -0,0 +1,670 @@
1
+ /**
2
+ * 连接管理工具
3
+ * 负责微信开发者工具的连接和断开
4
+ */
5
+ import { z } from 'zod';
6
+ import { defineTool } from './ToolDefinition.js';
7
+ import { connectDevtools, connectDevtoolsEnhanced, DevToolsConnectionError } from '../tools.js';
8
+ /**
9
+ * 创建请求拦截器函数
10
+ * 从 network.ts 复制,用于自动启动网络监听
11
+ */
12
+ function createRequestInterceptor() {
13
+ return function (options) {
14
+ // @ts-ignore - wx is available in WeChat miniprogram environment
15
+ const wxObj = (typeof wx !== 'undefined' ? wx : null);
16
+ if (!wxObj) {
17
+ return this.origin(options);
18
+ }
19
+ if (!wxObj.__networkLogs) {
20
+ wxObj.__networkLogs = [];
21
+ }
22
+ const requestId = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
23
+ const startTime = Date.now();
24
+ const originalSuccess = options.success;
25
+ options.success = function (res) {
26
+ wxObj.__networkLogs.push({
27
+ id: requestId,
28
+ type: 'request',
29
+ url: options.url,
30
+ method: options.method || 'GET',
31
+ headers: options.header,
32
+ data: options.data,
33
+ statusCode: res.statusCode,
34
+ response: res.data,
35
+ duration: Date.now() - startTime,
36
+ timestamp: new Date().toISOString(),
37
+ success: true
38
+ });
39
+ if (originalSuccess)
40
+ originalSuccess(res);
41
+ };
42
+ const originalFail = options.fail;
43
+ options.fail = function (err) {
44
+ wxObj.__networkLogs.push({
45
+ id: requestId,
46
+ type: 'request',
47
+ url: options.url,
48
+ method: options.method || 'GET',
49
+ headers: options.header,
50
+ data: options.data,
51
+ error: err.errMsg || String(err),
52
+ duration: Date.now() - startTime,
53
+ timestamp: new Date().toISOString(),
54
+ success: false
55
+ });
56
+ if (originalFail)
57
+ originalFail(err);
58
+ };
59
+ return this.origin(options);
60
+ };
61
+ }
62
+ /**
63
+ * 创建 uploadFile 拦截器函数
64
+ */
65
+ function createUploadFileInterceptor() {
66
+ return function (options) {
67
+ // @ts-ignore - wx is available in WeChat miniprogram environment
68
+ const wxObj = (typeof wx !== 'undefined' ? wx : null);
69
+ if (!wxObj) {
70
+ return this.origin(options);
71
+ }
72
+ if (!wxObj.__networkLogs) {
73
+ wxObj.__networkLogs = [];
74
+ }
75
+ const requestId = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
76
+ const startTime = Date.now();
77
+ const originalSuccess = options.success;
78
+ options.success = function (res) {
79
+ wxObj.__networkLogs.push({
80
+ id: requestId,
81
+ type: 'uploadFile',
82
+ url: options.url,
83
+ headers: options.header,
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,
92
+ timestamp: new Date().toISOString(),
93
+ success: true
94
+ });
95
+ if (originalSuccess)
96
+ originalSuccess(res);
97
+ };
98
+ const originalFail = options.fail;
99
+ options.fail = function (err) {
100
+ wxObj.__networkLogs.push({
101
+ id: requestId,
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,
112
+ timestamp: new Date().toISOString(),
113
+ success: false
114
+ });
115
+ if (originalFail)
116
+ originalFail(err);
117
+ };
118
+ return this.origin(options);
119
+ };
120
+ }
121
+ /**
122
+ * 创建 downloadFile 拦截器函数
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);
130
+ }
131
+ if (!wxObj.__networkLogs) {
132
+ wxObj.__networkLogs = [];
133
+ }
134
+ const requestId = 'req_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
135
+ const startTime = Date.now();
136
+ const originalSuccess = options.success;
137
+ options.success = function (res) {
138
+ wxObj.__networkLogs.push({
139
+ id: requestId,
140
+ type: 'downloadFile',
141
+ url: options.url,
142
+ headers: options.header,
143
+ statusCode: res.statusCode,
144
+ response: {
145
+ tempFilePath: res.tempFilePath,
146
+ filePath: res.filePath
147
+ },
148
+ duration: Date.now() - startTime,
149
+ timestamp: new Date().toISOString(),
150
+ success: true
151
+ });
152
+ if (originalSuccess)
153
+ originalSuccess(res);
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
166
+ });
167
+ if (originalFail)
168
+ originalFail(err);
169
+ };
170
+ return this.origin(options);
171
+ };
172
+ }
173
+ /**
174
+ * 连接到微信开发者工具(传统版)
175
+ */
176
+ export const connectDevtoolsTool = defineTool({
177
+ name: 'connect_devtools',
178
+ description: '连接到微信开发者工具(传统模式,兼容性)',
179
+ schema: z.object({
180
+ projectPath: z.string().describe('小程序项目的绝对路径'),
181
+ cliPath: z.string().optional().describe('微信开发者工具CLI的绝对路径(可选,默认会自动查找)'),
182
+ port: z.number().optional().describe('WebSocket端口号(可选,默认自动分配)'),
183
+ }),
184
+ annotations: {
185
+ audience: ['developers'],
186
+ },
187
+ handler: async (request, response, context) => {
188
+ const { projectPath, cliPath, port } = request.params;
189
+ // 检查是否已有活跃连接
190
+ if (context.miniProgram) {
191
+ try {
192
+ // 验证连接是否仍然有效
193
+ const currentPage = await context.miniProgram.currentPage();
194
+ const pagePath = await currentPage.path;
195
+ // 连接有效,复用现有连接
196
+ response.appendResponseLine(`✅ 检测到已有活跃连接,复用现有连接`);
197
+ response.appendResponseLine(`项目路径: ${projectPath}`);
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}`);
391
+ }
392
+ catch (error) {
393
+ const errorMessage = error instanceof Error ? error.message : String(error);
394
+ response.appendResponseLine(`连接失败: ${errorMessage}`);
395
+ throw error;
396
+ }
397
+ },
398
+ });
399
+ /**
400
+ * 智能连接到微信开发者工具(增强版)
401
+ */
402
+ export const connectDevtoolsEnhancedTool = defineTool({
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
+ }),
417
+ annotations: {
418
+ audience: ['developers'],
419
+ },
420
+ handler: async (request, response, context) => {
421
+ const { projectPath, mode, cliPath, autoPort, autoAccount, timeout, fallbackMode, healthCheck, verbose } = request.params;
422
+ // 检查是否已有活跃连接
423
+ if (context.miniProgram) {
424
+ try {
425
+ // 验证连接是否仍然有效
426
+ const currentPage = await context.miniProgram.currentPage();
427
+ const pagePath = await currentPage.path;
428
+ // 连接有效,复用现有连接
429
+ response.appendResponseLine(`✅ 检测到已有活跃连接,复用现有连接`);
430
+ response.appendResponseLine(`项目路径: ${projectPath}`);
431
+ response.appendResponseLine(`当前页面: ${pagePath}`);
432
+ response.appendResponseLine(`说明: 跳过重新连接,使用已建立的连接`);
433
+ if (verbose) {
434
+ response.appendResponseLine(`提示: 如需强制重新连接,请先关闭微信开发者工具`);
435
+ }
436
+ return;
437
+ }
438
+ catch (error) {
439
+ // 连接已失效,清空并继续新建连接
440
+ if (verbose) {
441
+ response.appendResponseLine(`检测到已有连接但已失效,准备重新连接...`);
442
+ }
443
+ context.miniProgram = null;
444
+ context.currentPage = null;
445
+ }
446
+ }
447
+ try {
448
+ const options = {
449
+ projectPath,
450
+ mode,
451
+ cliPath,
452
+ autoPort,
453
+ autoAccount,
454
+ timeout,
455
+ fallbackMode,
456
+ healthCheck,
457
+ verbose
458
+ };
459
+ const result = await connectDevtoolsEnhanced(options);
460
+ // 更新上下文
461
+ context.miniProgram = result.miniProgram;
462
+ context.currentPage = result.currentPage;
463
+ context.elementMap.clear();
464
+ // 自动启动console监听
465
+ try {
466
+ // 清除之前的监听器(如果有的话)
467
+ context.miniProgram.removeAllListeners('console');
468
+ context.miniProgram.removeAllListeners('exception');
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;
642
+ }
643
+ },
644
+ });
645
+ /**
646
+ * 获取当前页面信息
647
+ */
648
+ export const getCurrentPageTool = defineTool({
649
+ name: 'get_current_page',
650
+ description: '获取当前页面信息并设置为活动页面',
651
+ schema: z.object({}),
652
+ annotations: {
653
+ audience: ['developers'],
654
+ },
655
+ handler: async (request, response, context) => {
656
+ if (!context.miniProgram) {
657
+ throw new Error('请先连接到微信开发者工具');
658
+ }
659
+ try {
660
+ context.currentPage = await context.miniProgram.currentPage();
661
+ const pagePath = await context.currentPage.path;
662
+ response.appendResponseLine(`当前页面: ${pagePath}`);
663
+ }
664
+ catch (error) {
665
+ const errorMessage = error instanceof Error ? error.message : String(error);
666
+ response.appendResponseLine(`获取当前页面失败: ${errorMessage}`);
667
+ throw error;
668
+ }
669
+ },
670
+ });