@weapp-vite/mcp 1.2.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 +21 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +1325 -227
- package/package.json +5 -2
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
|
-
import fs$1 from 'node:fs/promises';
|
|
4
|
-
import { createRequire } from 'node:module';
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
import fs from 'node:fs';
|
|
7
|
-
import { spawn } from 'node:child_process';
|
|
8
3
|
import { Buffer } from 'node:buffer';
|
|
9
4
|
import http from 'node:http';
|
|
10
5
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
11
6
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
12
|
-
import {
|
|
7
|
+
import { ResourceTemplate, McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
13
8
|
import { z } from 'zod';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import fs$1 from 'node:fs/promises';
|
|
12
|
+
import { createRequire } from 'node:module';
|
|
13
|
+
import { spawn } from 'node:child_process';
|
|
14
|
+
import { closeSharedMiniProgram, acquireSharedMiniProgram, releaseSharedMiniProgram } from '@weapp-vite/devtools-runtime';
|
|
14
15
|
|
|
15
16
|
const MCP_SERVER_NAME = "@weapp-vite/mcp";
|
|
16
17
|
const MCP_SERVER_VERSION = "2.0.0";
|
|
@@ -84,6 +85,118 @@ function resolveSubPath(root, relativePath) {
|
|
|
84
85
|
return assertInsideRoot(root, path.resolve(root, relativePath));
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
function registerServerPrompts(server, options) {
|
|
89
|
+
const { packageIds, packageIdSchema } = options;
|
|
90
|
+
server.registerPrompt("plan-weapp-vite-change", {
|
|
91
|
+
title: "Plan weapp-vite Change",
|
|
92
|
+
description: "\u6839\u636E\u53D8\u66F4\u76EE\u6807\u751F\u6210 weapp-vite / wevu \u4FEE\u6539\u8BA1\u5212\u63D0\u793A\u8BCD",
|
|
93
|
+
argsSchema: {
|
|
94
|
+
objective: z.string().min(1),
|
|
95
|
+
focusPackage: packageIdSchema.optional()
|
|
96
|
+
}
|
|
97
|
+
}, async ({ objective, focusPackage }) => {
|
|
98
|
+
const targets = focusPackage ? [focusPackage] : packageIds;
|
|
99
|
+
return {
|
|
100
|
+
messages: [
|
|
101
|
+
{
|
|
102
|
+
role: "user",
|
|
103
|
+
content: {
|
|
104
|
+
type: "text",
|
|
105
|
+
text: [
|
|
106
|
+
"\u4F60\u662F weapp-vite monorepo \u7EF4\u62A4\u8005\uFF0C\u8BF7\u7ED9\u51FA\u53EF\u6267\u884C\u7684\u6539\u9020\u8BA1\u5212\u3002",
|
|
107
|
+
`\u76EE\u6807\uFF1A${objective}`,
|
|
108
|
+
`\u805A\u7126\u5305\uFF1A${targets.join(", ")}`,
|
|
109
|
+
"\u8BF7\u5305\u542B\uFF1A\u5F71\u54CD\u9762\u3001\u98CE\u9669\u70B9\u3001\u6D4B\u8BD5\u7B56\u7565\u3001\u56DE\u6EDA\u7B56\u7565\u3002"
|
|
110
|
+
].join("\n")
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
server.registerPrompt("debug-wevu-runtime", {
|
|
117
|
+
title: "Debug wevu Runtime",
|
|
118
|
+
description: "\u7528\u4E8E\u5B9A\u4F4D wevu runtime \u751F\u547D\u5468\u671F/\u54CD\u5E94\u5F0F\u95EE\u9898\u7684\u6807\u51C6\u63D0\u793A\u8BCD",
|
|
119
|
+
argsSchema: {
|
|
120
|
+
symptom: z.string().min(1)
|
|
121
|
+
}
|
|
122
|
+
}, async ({ symptom }) => {
|
|
123
|
+
return {
|
|
124
|
+
messages: [
|
|
125
|
+
{
|
|
126
|
+
role: "user",
|
|
127
|
+
content: {
|
|
128
|
+
type: "text",
|
|
129
|
+
text: [
|
|
130
|
+
"\u8BF7\u57FA\u4E8E wevu runtime \u4EE3\u7801\u8DEF\u5F84\u8FDB\u884C\u5206\u5C42\u6392\u67E5\uFF1A",
|
|
131
|
+
"1. \u590D\u73B0\u573A\u666F\u4E0E\u6700\u5C0F\u6837\u4F8B",
|
|
132
|
+
"2. \u751F\u547D\u5468\u671F\u94A9\u5B50\u89E6\u53D1\u94FE",
|
|
133
|
+
"3. \u54CD\u5E94\u5F0F\u4E0E setData \u5DEE\u91CF\u540C\u6B65\u94FE",
|
|
134
|
+
"4. \u5355\u6D4B\u4E0E e2e \u56DE\u5F52\u8865\u4E01",
|
|
135
|
+
`\u73B0\u8C61\uFF1A${symptom}`
|
|
136
|
+
].join("\n")
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
server.registerPrompt("inspect-mini-program-page", {
|
|
143
|
+
title: "Inspect Mini Program Page",
|
|
144
|
+
description: "\u8FDE\u63A5\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u5E76\u68C0\u67E5\u5F53\u524D\u5C0F\u7A0B\u5E8F\u9875\u9762\u7684\u6807\u51C6\u6D41\u7A0B",
|
|
145
|
+
argsSchema: {
|
|
146
|
+
projectPath: z.string().min(1),
|
|
147
|
+
pagePath: z.string().optional(),
|
|
148
|
+
focus: z.string().optional()
|
|
149
|
+
}
|
|
150
|
+
}, async ({ projectPath, pagePath, focus }) => {
|
|
151
|
+
return {
|
|
152
|
+
messages: [
|
|
153
|
+
{
|
|
154
|
+
role: "user",
|
|
155
|
+
content: {
|
|
156
|
+
type: "text",
|
|
157
|
+
text: [
|
|
158
|
+
"\u8BF7\u6309\u987A\u5E8F\u4F7F\u7528 weapp-vite MCP runtime tools \u68C0\u67E5\u5C0F\u7A0B\u5E8F\u9875\u9762\uFF1A",
|
|
159
|
+
`1. \u8C03\u7528 weapp_devtools_connect\uFF0CprojectPath=${projectPath}`,
|
|
160
|
+
pagePath ? `2. \u8C03\u7528 weapp_devtools_route \u8DF3\u8F6C\u5230 ${pagePath}` : "2. \u8C03\u7528 weapp_devtools_active_page \u786E\u8BA4\u5F53\u524D\u9875\u9762",
|
|
161
|
+
"3. \u8C03\u7528 weapp_devtools_capture \u83B7\u53D6\u622A\u56FE",
|
|
162
|
+
"4. \u5982\u9700\u68C0\u67E5\u7ED3\u6784\uFF0C\u4F18\u5148\u8C03\u7528 weapp_runtime_find_node/weapp_runtime_find_nodes\uFF0C\u5FC5\u8981\u65F6\u8BBE\u7F6E withWxml=true",
|
|
163
|
+
"5. \u8C03\u7528 weapp_devtools_console \u68C0\u67E5 console/exception \u65E5\u5FD7",
|
|
164
|
+
focus ? `\u5173\u6CE8\u70B9\uFF1A${focus}` : "\u5173\u6CE8\u70B9\uFF1A\u9875\u9762\u662F\u5426\u6B63\u786E\u6E32\u67D3\u3001\u662F\u5426\u5B58\u5728\u8FD0\u884C\u65F6\u9519\u8BEF\u3002"
|
|
165
|
+
].join("\n")
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
server.registerPrompt("recover-mini-program-connection", {
|
|
172
|
+
title: "Recover Mini Program Connection",
|
|
173
|
+
description: "\u6062\u590D\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177 automator \u8FDE\u63A5\u7684\u6807\u51C6\u6D41\u7A0B",
|
|
174
|
+
argsSchema: {
|
|
175
|
+
projectPath: z.string().min(1),
|
|
176
|
+
lastError: z.string().optional()
|
|
177
|
+
}
|
|
178
|
+
}, async ({ projectPath, lastError }) => {
|
|
179
|
+
return {
|
|
180
|
+
messages: [
|
|
181
|
+
{
|
|
182
|
+
role: "user",
|
|
183
|
+
content: {
|
|
184
|
+
type: "text",
|
|
185
|
+
text: [
|
|
186
|
+
"\u8BF7\u6309\u987A\u5E8F\u6062\u590D weapp-vite MCP runtime \u8FDE\u63A5\uFF1A",
|
|
187
|
+
`1. \u8C03\u7528 weapp_devtools_connect\uFF0CprojectPath=${projectPath}\uFF0Creconnect=true`,
|
|
188
|
+
"2. \u5982\u679C\u4ECD\u5931\u8D25\uFF0C\u68C0\u67E5\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u662F\u5426\u5DF2\u5F00\u542F\u670D\u52A1\u7AEF\u53E3\u4E0E\u81EA\u52A8\u5316\u6D4B\u8BD5\u80FD\u529B",
|
|
189
|
+
"3. \u5982\u679C\u662F\u534F\u8BAE\u8D85\u65F6\uFF0C\u5173\u95ED\u591A\u4F59 DevTools \u7A97\u53E3\u540E\u53EA\u91CD\u8BD5\u4E00\u6B21",
|
|
190
|
+
"4. \u6062\u590D\u540E\u8C03\u7528 weapp_devtools_active_page \u548C weapp_devtools_console \u786E\u8BA4\u72B6\u6001",
|
|
191
|
+
lastError ? `\u4E0A\u4E00\u6B21\u9519\u8BEF\uFF1A${lastError}` : "\u4E0A\u4E00\u6B21\u9519\u8BEF\uFF1A\u672A\u63D0\u4F9B\u3002"
|
|
192
|
+
].join("\n")
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
87
200
|
async function pathExists(filePath) {
|
|
88
201
|
try {
|
|
89
202
|
await fs$1.access(filePath);
|
|
@@ -195,87 +308,6 @@ async function resolveExposedPackages(workspaceRoot) {
|
|
|
195
308
|
}).sort((a, b) => a.id.localeCompare(b.id));
|
|
196
309
|
}
|
|
197
310
|
|
|
198
|
-
async function loadPackageSummary(workspaceRoot, id) {
|
|
199
|
-
return resolveExposedPackage(workspaceRoot, id);
|
|
200
|
-
}
|
|
201
|
-
async function loadExposedCatalog(workspaceRoot) {
|
|
202
|
-
return resolveExposedPackages(workspaceRoot);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
206
|
-
"pnpm",
|
|
207
|
-
"node",
|
|
208
|
-
"git",
|
|
209
|
-
"rg"
|
|
210
|
-
]);
|
|
211
|
-
function resolveExecutable(command) {
|
|
212
|
-
if (process.platform === "win32") {
|
|
213
|
-
if (command === "pnpm") {
|
|
214
|
-
return "pnpm.cmd";
|
|
215
|
-
}
|
|
216
|
-
if (command === "git") {
|
|
217
|
-
return "git.exe";
|
|
218
|
-
}
|
|
219
|
-
if (command === "rg") {
|
|
220
|
-
return "rg.exe";
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return command;
|
|
224
|
-
}
|
|
225
|
-
function truncateOutput(text, maxChars) {
|
|
226
|
-
if (text.length <= maxChars) {
|
|
227
|
-
return text;
|
|
228
|
-
}
|
|
229
|
-
return `${text.slice(0, maxChars)}
|
|
230
|
-
|
|
231
|
-
[truncated: ${text.length - maxChars} chars omitted]`;
|
|
232
|
-
}
|
|
233
|
-
async function runCommand(workspaceRoot, command, args, options) {
|
|
234
|
-
if (!ALLOWED_COMMANDS.has(command)) {
|
|
235
|
-
throw new Error(`\u4E0D\u5141\u8BB8\u7684\u547D\u4EE4\uFF1A${command}`);
|
|
236
|
-
}
|
|
237
|
-
const cwd = resolveSubPath(workspaceRoot, options?.cwdRelative ?? ".");
|
|
238
|
-
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
239
|
-
const maxOutputChars = options?.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
|
|
240
|
-
const executable = resolveExecutable(command);
|
|
241
|
-
const child = spawn(executable, args, {
|
|
242
|
-
cwd,
|
|
243
|
-
env: process.env,
|
|
244
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
245
|
-
shell: false
|
|
246
|
-
});
|
|
247
|
-
let stdout = "";
|
|
248
|
-
let stderr = "";
|
|
249
|
-
let timedOut = false;
|
|
250
|
-
const timer = setTimeout(() => {
|
|
251
|
-
timedOut = true;
|
|
252
|
-
child.kill("SIGTERM");
|
|
253
|
-
}, timeoutMs);
|
|
254
|
-
child.stdout.on("data", (chunk) => {
|
|
255
|
-
stdout += chunk.toString();
|
|
256
|
-
});
|
|
257
|
-
child.stderr.on("data", (chunk) => {
|
|
258
|
-
stderr += chunk.toString();
|
|
259
|
-
});
|
|
260
|
-
const exitCode = await new Promise((resolve, reject) => {
|
|
261
|
-
child.on("error", reject);
|
|
262
|
-
child.on("close", (code) => {
|
|
263
|
-
resolve(code ?? -1);
|
|
264
|
-
});
|
|
265
|
-
}).finally(() => {
|
|
266
|
-
clearTimeout(timer);
|
|
267
|
-
});
|
|
268
|
-
return {
|
|
269
|
-
command,
|
|
270
|
-
args,
|
|
271
|
-
cwd: path.resolve(cwd),
|
|
272
|
-
exitCode,
|
|
273
|
-
stdout: truncateOutput(stdout.trim(), maxOutputChars),
|
|
274
|
-
stderr: truncateOutput(stderr.trim(), maxOutputChars),
|
|
275
|
-
timedOut
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
311
|
async function walkFilesRecursive(root, current, output, maxResults) {
|
|
280
312
|
if (output.length >= maxResults) {
|
|
281
313
|
return;
|
|
@@ -398,8 +430,80 @@ function toToolError(error) {
|
|
|
398
430
|
};
|
|
399
431
|
}
|
|
400
432
|
|
|
401
|
-
const
|
|
402
|
-
|
|
433
|
+
const ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
434
|
+
"pnpm",
|
|
435
|
+
"node",
|
|
436
|
+
"git",
|
|
437
|
+
"rg"
|
|
438
|
+
]);
|
|
439
|
+
function resolveExecutable(command) {
|
|
440
|
+
if (process.platform === "win32") {
|
|
441
|
+
if (command === "pnpm") {
|
|
442
|
+
return "pnpm.cmd";
|
|
443
|
+
}
|
|
444
|
+
if (command === "git") {
|
|
445
|
+
return "git.exe";
|
|
446
|
+
}
|
|
447
|
+
if (command === "rg") {
|
|
448
|
+
return "rg.exe";
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return command;
|
|
452
|
+
}
|
|
453
|
+
function truncateOutput(text, maxChars) {
|
|
454
|
+
if (text.length <= maxChars) {
|
|
455
|
+
return text;
|
|
456
|
+
}
|
|
457
|
+
return `${text.slice(0, maxChars)}
|
|
458
|
+
|
|
459
|
+
[truncated: ${text.length - maxChars} chars omitted]`;
|
|
460
|
+
}
|
|
461
|
+
async function runCommand(workspaceRoot, command, args, options) {
|
|
462
|
+
if (!ALLOWED_COMMANDS.has(command)) {
|
|
463
|
+
throw new Error(`\u4E0D\u5141\u8BB8\u7684\u547D\u4EE4\uFF1A${command}`);
|
|
464
|
+
}
|
|
465
|
+
const cwd = resolveSubPath(workspaceRoot, options?.cwdRelative ?? ".");
|
|
466
|
+
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
467
|
+
const maxOutputChars = options?.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
|
|
468
|
+
const executable = resolveExecutable(command);
|
|
469
|
+
const child = spawn(executable, args, {
|
|
470
|
+
cwd,
|
|
471
|
+
env: process.env,
|
|
472
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
473
|
+
shell: false
|
|
474
|
+
});
|
|
475
|
+
let stdout = "";
|
|
476
|
+
let stderr = "";
|
|
477
|
+
let timedOut = false;
|
|
478
|
+
const timer = setTimeout(() => {
|
|
479
|
+
timedOut = true;
|
|
480
|
+
child.kill("SIGTERM");
|
|
481
|
+
}, timeoutMs);
|
|
482
|
+
child.stdout.on("data", (chunk) => {
|
|
483
|
+
stdout += chunk.toString();
|
|
484
|
+
});
|
|
485
|
+
child.stderr.on("data", (chunk) => {
|
|
486
|
+
stderr += chunk.toString();
|
|
487
|
+
});
|
|
488
|
+
const exitCode = await new Promise((resolve, reject) => {
|
|
489
|
+
child.on("error", reject);
|
|
490
|
+
child.on("close", (code) => {
|
|
491
|
+
resolve(code ?? -1);
|
|
492
|
+
});
|
|
493
|
+
}).finally(() => {
|
|
494
|
+
clearTimeout(timer);
|
|
495
|
+
});
|
|
496
|
+
return {
|
|
497
|
+
command,
|
|
498
|
+
args,
|
|
499
|
+
cwd: path.resolve(cwd),
|
|
500
|
+
exitCode,
|
|
501
|
+
stdout: truncateOutput(stdout.trim(), maxOutputChars),
|
|
502
|
+
stderr: truncateOutput(stderr.trim(), maxOutputChars),
|
|
503
|
+
timedOut
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
403
507
|
async function resolvePackageRoot(workspaceRoot, packageId) {
|
|
404
508
|
const resolved = await resolveExposedPackage(workspaceRoot, packageId);
|
|
405
509
|
if (!resolved.sourceRoot) {
|
|
@@ -432,21 +536,1119 @@ async function runWeappViteCliTool(workspaceRoot, input) {
|
|
|
432
536
|
timeoutMs: input.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
433
537
|
});
|
|
434
538
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
539
|
+
|
|
540
|
+
async function registerServerResources(server, options) {
|
|
541
|
+
const { workspaceRoot, packageIds } = options;
|
|
542
|
+
server.registerResource("workspace-catalog", "weapp-vite://workspace/catalog", {
|
|
543
|
+
title: "Workspace Catalog",
|
|
544
|
+
description: "weapp-vite / wevu \u5305\u76EE\u5F55\u3001\u7248\u672C\u548C\u811A\u672C\u5217\u8868",
|
|
545
|
+
mimeType: "application/json"
|
|
546
|
+
}, async () => {
|
|
547
|
+
const catalog2 = await resolveExposedPackages(workspaceRoot);
|
|
548
|
+
const text = JSON.stringify({ workspaceRoot, packages: catalog2 }, null, 2);
|
|
549
|
+
return {
|
|
550
|
+
contents: [{
|
|
551
|
+
uri: "weapp-vite://workspace/catalog",
|
|
552
|
+
mimeType: "application/json",
|
|
553
|
+
text
|
|
554
|
+
}]
|
|
555
|
+
};
|
|
556
|
+
});
|
|
557
|
+
const catalog = await resolveExposedPackages(workspaceRoot);
|
|
558
|
+
for (const summary of catalog) {
|
|
559
|
+
if (summary.docs.readme) {
|
|
560
|
+
const uri = toDocsUri(summary.id, "README.md");
|
|
561
|
+
server.registerResource(`docs-${summary.id}-readme`, uri, {
|
|
562
|
+
title: `${summary.id} README`,
|
|
563
|
+
mimeType: "text/markdown"
|
|
564
|
+
}, async () => {
|
|
565
|
+
const text = await readTextFile(summary.docs.readme);
|
|
566
|
+
return {
|
|
567
|
+
contents: [{ uri, mimeType: "text/markdown", text }]
|
|
568
|
+
};
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
if (summary.docs.changelog) {
|
|
572
|
+
const uri = toDocsUri(summary.id, "CHANGELOG.md");
|
|
573
|
+
server.registerResource(`docs-${summary.id}-changelog`, uri, {
|
|
574
|
+
title: `${summary.id} CHANGELOG`,
|
|
575
|
+
mimeType: "text/markdown"
|
|
576
|
+
}, async () => {
|
|
577
|
+
const text = await readTextFile(summary.docs.changelog);
|
|
578
|
+
return {
|
|
579
|
+
contents: [{ uri, mimeType: "text/markdown", text }]
|
|
580
|
+
};
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
const sourceTemplate = new ResourceTemplate("weapp-vite://source/{package}?path={path}", {
|
|
585
|
+
list: void 0,
|
|
586
|
+
complete: {
|
|
587
|
+
package: () => packageIds
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
server.registerResource("source-template", sourceTemplate, {
|
|
591
|
+
title: "Source Template",
|
|
592
|
+
description: "\u8BFB\u53D6 weapp-vite / wevu \u4EFB\u610F\u6E90\u7801\u6587\u4EF6\uFF08\u901A\u8FC7 package + path \u53C2\u6570\uFF09",
|
|
593
|
+
mimeType: "text/plain"
|
|
594
|
+
}, async (uri, variables) => {
|
|
595
|
+
try {
|
|
596
|
+
const packageId = String(variables.package ?? "");
|
|
597
|
+
if (!packageIds.includes(packageId)) {
|
|
598
|
+
throw new Error(`\u672A\u77E5 package\uFF1A${packageId}`);
|
|
599
|
+
}
|
|
600
|
+
const relativePath = decodeURIComponent(String(variables.path ?? ""));
|
|
601
|
+
const packageRoot = await resolvePackageRoot(workspaceRoot, packageId);
|
|
602
|
+
const { content } = await readFileContent(packageRoot, relativePath, {
|
|
603
|
+
maxChars: DEFAULT_MAX_FILE_CHARS
|
|
604
|
+
});
|
|
605
|
+
return {
|
|
606
|
+
contents: [{
|
|
607
|
+
uri: uri.toString(),
|
|
608
|
+
mimeType: "text/plain",
|
|
609
|
+
text: content
|
|
610
|
+
}]
|
|
611
|
+
};
|
|
612
|
+
} catch (error) {
|
|
613
|
+
return {
|
|
614
|
+
contents: [{
|
|
615
|
+
uri: uri.toString(),
|
|
616
|
+
mimeType: "text/plain",
|
|
617
|
+
text: `[resource-error] ${normalizeErrorMessage(error)}`
|
|
618
|
+
}]
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
z.object({
|
|
625
|
+
projectPath: z.string().trim().min(1).describe("\u5C0F\u7A0B\u5E8F\u9879\u76EE\u8DEF\u5F84\uFF1B\u652F\u6301 workspaceRoot \u76F8\u5BF9\u8DEF\u5F84"),
|
|
626
|
+
timeout: z.number().int().positive().optional(),
|
|
627
|
+
preferOpenedSession: z.boolean().optional()
|
|
628
|
+
});
|
|
629
|
+
const connectionInputSchema = {
|
|
630
|
+
projectPath: z.string().trim().min(1).describe("\u5C0F\u7A0B\u5E8F\u9879\u76EE\u8DEF\u5F84\uFF1B\u652F\u6301 workspaceRoot \u76F8\u5BF9\u8DEF\u5F84"),
|
|
631
|
+
timeout: z.number().int().positive().optional(),
|
|
632
|
+
preferOpenedSession: z.boolean().optional()
|
|
633
|
+
};
|
|
634
|
+
class RuntimeSessionManager {
|
|
635
|
+
constructor(workspaceRoot, runtimeHooks = createUnavailableRuntimeHooks()) {
|
|
636
|
+
this.workspaceRoot = workspaceRoot;
|
|
637
|
+
this.runtimeHooks = runtimeHooks;
|
|
638
|
+
}
|
|
639
|
+
logs = [];
|
|
640
|
+
attachedSessions = /* @__PURE__ */ new Map();
|
|
641
|
+
maxLogs = 1e3;
|
|
642
|
+
async close(input) {
|
|
643
|
+
const projectPath = this.resolveProjectPath(input.projectPath);
|
|
644
|
+
this.detach(projectPath);
|
|
645
|
+
await closeSharedMiniProgram(projectPath);
|
|
646
|
+
}
|
|
647
|
+
clearLogs() {
|
|
648
|
+
this.logs.length = 0;
|
|
649
|
+
}
|
|
650
|
+
getLogs() {
|
|
651
|
+
return [...this.logs];
|
|
652
|
+
}
|
|
653
|
+
resolveProjectPath(projectPath) {
|
|
654
|
+
return path.isAbsolute(projectPath) ? path.normalize(projectPath) : path.resolve(this.workspaceRoot, projectPath);
|
|
655
|
+
}
|
|
656
|
+
resolveWorkspacePath(filePath) {
|
|
657
|
+
return path.isAbsolute(filePath) ? path.normalize(filePath) : path.resolve(this.workspaceRoot, filePath);
|
|
658
|
+
}
|
|
659
|
+
async withMiniProgram(input, runner) {
|
|
660
|
+
const projectPath = this.resolveProjectPath(input.projectPath);
|
|
661
|
+
const miniProgram = await acquireSharedMiniProgram(this.runtimeHooks, {
|
|
662
|
+
projectPath,
|
|
663
|
+
timeout: input.timeout,
|
|
664
|
+
preferOpenedSession: input.preferOpenedSession,
|
|
665
|
+
sharedSession: true
|
|
666
|
+
});
|
|
667
|
+
this.attach(projectPath, miniProgram);
|
|
668
|
+
try {
|
|
669
|
+
return await runner(miniProgram);
|
|
670
|
+
} catch (error) {
|
|
671
|
+
this.detach(projectPath);
|
|
672
|
+
await closeSharedMiniProgram(projectPath);
|
|
673
|
+
throw error;
|
|
674
|
+
} finally {
|
|
675
|
+
releaseSharedMiniProgram(projectPath);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
async withPage(input, runner) {
|
|
679
|
+
return await this.withMiniProgram(input, async (miniProgram) => {
|
|
680
|
+
const page = await miniProgram.currentPage();
|
|
681
|
+
if (!page) {
|
|
682
|
+
throw new Error("\u5F53\u524D\u6CA1\u6709\u6D3B\u52A8\u9875\u9762\uFF0C\u8BF7\u5148\u8C03\u7528 weapp_devtools_connect \u786E\u8BA4 DevTools \u4F1A\u8BDD\u3002");
|
|
683
|
+
}
|
|
684
|
+
return await runner(page, miniProgram);
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
attach(projectPath, miniProgram) {
|
|
688
|
+
const existing = this.attachedSessions.get(projectPath);
|
|
689
|
+
if (existing?.miniProgram === miniProgram) {
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
this.detach(projectPath);
|
|
693
|
+
const onConsole = (payload) => {
|
|
694
|
+
this.pushLog(normalizeConsoleEvent(payload));
|
|
695
|
+
};
|
|
696
|
+
const onException = (payload) => {
|
|
697
|
+
this.pushLog(normalizeExceptionEvent(payload));
|
|
698
|
+
};
|
|
699
|
+
miniProgram.on("console", onConsole);
|
|
700
|
+
miniProgram.on("exception", onException);
|
|
701
|
+
this.attachedSessions.set(projectPath, {
|
|
702
|
+
miniProgram,
|
|
703
|
+
onConsole,
|
|
704
|
+
onException
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
detach(projectPath) {
|
|
708
|
+
const attached = this.attachedSessions.get(projectPath);
|
|
709
|
+
if (!attached) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (typeof attached.miniProgram.off === "function") {
|
|
713
|
+
attached.miniProgram.off("console", attached.onConsole);
|
|
714
|
+
attached.miniProgram.off("exception", attached.onException);
|
|
715
|
+
}
|
|
716
|
+
this.attachedSessions.delete(projectPath);
|
|
717
|
+
}
|
|
718
|
+
pushLog(entry) {
|
|
719
|
+
this.logs.push(entry);
|
|
720
|
+
while (this.logs.length > this.maxLogs) {
|
|
721
|
+
this.logs.shift();
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
function buildUrl(pagePath, query) {
|
|
726
|
+
const normalizedPath = pagePath.startsWith("/") ? pagePath : `/${pagePath}`;
|
|
727
|
+
if (!query || Object.keys(query).length === 0) {
|
|
728
|
+
return normalizedPath;
|
|
729
|
+
}
|
|
730
|
+
const search = new URLSearchParams(query).toString();
|
|
731
|
+
if (!search) {
|
|
732
|
+
return normalizedPath;
|
|
733
|
+
}
|
|
734
|
+
return `${normalizedPath}${normalizedPath.includes("?") ? "&" : "?"}${search}`;
|
|
735
|
+
}
|
|
736
|
+
function parseSelectorWithIndex(selector) {
|
|
737
|
+
const match = selector.match(/^(.+?)\[index=(\d+)\]$/);
|
|
738
|
+
if (!match?.[1] || !match[2]) {
|
|
739
|
+
return {
|
|
740
|
+
selector,
|
|
741
|
+
index: void 0
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
return {
|
|
745
|
+
selector: match[1],
|
|
746
|
+
index: Number.parseInt(match[2], 10)
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
async function resolveElement(page, selectorInput, innerSelector) {
|
|
750
|
+
const { selector, index } = parseSelectorWithIndex(selectorInput);
|
|
751
|
+
let element;
|
|
752
|
+
if (index === void 0) {
|
|
753
|
+
element = await page.$(selector);
|
|
754
|
+
} else {
|
|
755
|
+
const elements = await queryElements(page, selector);
|
|
756
|
+
if (index < 0 || index >= elements.length) {
|
|
757
|
+
throw new Error(`\u9009\u62E9\u5668 "${selector}" \u7684 index=${index} \u8D85\u51FA\u8303\u56F4\uFF0C\u5F53\u524D\u5339\u914D ${elements.length} \u4E2A\u5143\u7D20\u3002`);
|
|
758
|
+
}
|
|
759
|
+
element = elements[index];
|
|
760
|
+
}
|
|
761
|
+
if (!element) {
|
|
762
|
+
throw new Error(`\u672A\u627E\u5230\u5143\u7D20: ${selectorInput}`);
|
|
763
|
+
}
|
|
764
|
+
if (!innerSelector) {
|
|
765
|
+
return element;
|
|
766
|
+
}
|
|
767
|
+
const inner = await callOptionalMethod(element, "$", innerSelector);
|
|
768
|
+
if (!inner) {
|
|
769
|
+
throw new Error(`\u5728\u5143\u7D20 "${selectorInput}" \u5185\u672A\u627E\u5230\u5143\u7D20: ${innerSelector}`);
|
|
770
|
+
}
|
|
771
|
+
return inner;
|
|
772
|
+
}
|
|
773
|
+
async function queryElements(page, selectorInput) {
|
|
774
|
+
const { selector, index } = parseSelectorWithIndex(selectorInput);
|
|
775
|
+
const elements = await callOptionalMethod(page, "$$", selector);
|
|
776
|
+
if (!Array.isArray(elements)) {
|
|
777
|
+
return [];
|
|
778
|
+
}
|
|
779
|
+
if (index === void 0) {
|
|
780
|
+
return elements;
|
|
781
|
+
}
|
|
782
|
+
if (index < 0 || index >= elements.length) {
|
|
783
|
+
throw new Error(`\u9009\u62E9\u5668 "${selector}" \u7684 index=${index} \u8D85\u51FA\u8303\u56F4\uFF0C\u5F53\u524D\u5339\u914D ${elements.length} \u4E2A\u5143\u7D20\u3002`);
|
|
784
|
+
}
|
|
785
|
+
return [elements[index]];
|
|
786
|
+
}
|
|
787
|
+
async function summarizeElement(element, withWxml = false) {
|
|
788
|
+
const [text, value, size, offset, scrollWidth, scrollHeight, outerWxml] = await Promise.all([
|
|
789
|
+
callMaybe(element, "text"),
|
|
790
|
+
callMaybe(element, "value"),
|
|
791
|
+
callMaybe(element, "size"),
|
|
792
|
+
callMaybe(element, "offset"),
|
|
793
|
+
callMaybe(element, "scrollWidth"),
|
|
794
|
+
callMaybe(element, "scrollHeight"),
|
|
795
|
+
withWxml ? callMaybe(element, "outerWxml") : Promise.resolve(void 0)
|
|
796
|
+
]);
|
|
797
|
+
return compactObject({
|
|
798
|
+
tagName: readProperty(element, "tagName"),
|
|
799
|
+
text,
|
|
800
|
+
value,
|
|
801
|
+
size,
|
|
802
|
+
offset,
|
|
803
|
+
scrollWidth,
|
|
804
|
+
scrollHeight,
|
|
805
|
+
outerWxml
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
function toSerializableValue(value) {
|
|
809
|
+
if (value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
810
|
+
return value;
|
|
811
|
+
}
|
|
812
|
+
if (typeof value === "bigint") {
|
|
813
|
+
return value.toString();
|
|
814
|
+
}
|
|
815
|
+
if (value instanceof Date) {
|
|
816
|
+
return value.toISOString();
|
|
817
|
+
}
|
|
818
|
+
if (Buffer.isBuffer(value)) {
|
|
819
|
+
return value.toString("base64");
|
|
820
|
+
}
|
|
821
|
+
if (Array.isArray(value)) {
|
|
822
|
+
return value.map((item) => toSerializableValue(item));
|
|
823
|
+
}
|
|
824
|
+
if (typeof value === "object") {
|
|
825
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, toSerializableValue(item)]));
|
|
826
|
+
}
|
|
827
|
+
return String(value);
|
|
828
|
+
}
|
|
829
|
+
async function callRequiredMethod(target, methodName, ...args) {
|
|
830
|
+
const method = readProperty(target, methodName);
|
|
831
|
+
if (typeof method !== "function") {
|
|
832
|
+
throw new TypeError(`\u5F53\u524D\u5BF9\u8C61\u4E0D\u652F\u6301 ${methodName} \u65B9\u6CD5\u3002`);
|
|
833
|
+
}
|
|
834
|
+
return await method.apply(target, args);
|
|
835
|
+
}
|
|
836
|
+
async function callOptionalMethod(target, methodName, ...args) {
|
|
837
|
+
const method = readProperty(target, methodName);
|
|
838
|
+
if (typeof method !== "function") {
|
|
839
|
+
return void 0;
|
|
840
|
+
}
|
|
841
|
+
return await method.apply(target, args);
|
|
842
|
+
}
|
|
843
|
+
async function callMaybe(target, methodName, ...args) {
|
|
844
|
+
try {
|
|
845
|
+
return await callOptionalMethod(target, methodName, ...args);
|
|
846
|
+
} catch {
|
|
847
|
+
return void 0;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
function compactObject(input) {
|
|
851
|
+
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
|
|
852
|
+
}
|
|
853
|
+
function readProperty(target, key) {
|
|
854
|
+
if (!target || typeof target !== "object") {
|
|
855
|
+
return void 0;
|
|
856
|
+
}
|
|
857
|
+
return target[key];
|
|
858
|
+
}
|
|
859
|
+
function normalizeConsoleEvent(payload) {
|
|
860
|
+
const record = toRecord$1(payload);
|
|
861
|
+
return {
|
|
862
|
+
level: normalizeLogLevel(record.type ?? record.level ?? record.method),
|
|
863
|
+
message: resolveLogMessage(record, payload),
|
|
864
|
+
timestamp: Date.now(),
|
|
865
|
+
raw: toSerializableValue(payload)
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
function normalizeExceptionEvent(payload) {
|
|
869
|
+
const record = toRecord$1(payload);
|
|
870
|
+
const error = toRecord$1(record.error);
|
|
871
|
+
const message = [
|
|
872
|
+
typeof error.message === "string" ? error.message : void 0,
|
|
873
|
+
typeof record.message === "string" ? record.message : void 0,
|
|
874
|
+
typeof error.stack === "string" ? error.stack : void 0,
|
|
875
|
+
typeof record.stack === "string" ? record.stack : void 0
|
|
876
|
+
].filter(Boolean).join("\n");
|
|
877
|
+
return {
|
|
878
|
+
level: "error",
|
|
879
|
+
message: message || JSON.stringify(toSerializableValue(payload)),
|
|
880
|
+
timestamp: Date.now(),
|
|
881
|
+
raw: toSerializableValue(payload)
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
function normalizeLogLevel(value) {
|
|
885
|
+
const normalized = String(value ?? "log").toLowerCase();
|
|
886
|
+
if (normalized === "warning") {
|
|
887
|
+
return "warn";
|
|
888
|
+
}
|
|
889
|
+
if (["debug", "log", "info", "warn", "error"].includes(normalized)) {
|
|
890
|
+
return normalized;
|
|
891
|
+
}
|
|
892
|
+
return "log";
|
|
893
|
+
}
|
|
894
|
+
function resolveLogMessage(record, payload) {
|
|
895
|
+
if (typeof record.text === "string" && record.text) {
|
|
896
|
+
return record.text;
|
|
897
|
+
}
|
|
898
|
+
if (typeof record.message === "string" && record.message) {
|
|
899
|
+
return record.message;
|
|
900
|
+
}
|
|
901
|
+
if (Array.isArray(record.args)) {
|
|
902
|
+
return record.args.map(formatLogArgument).join(" ");
|
|
903
|
+
}
|
|
904
|
+
if (typeof payload === "string") {
|
|
905
|
+
return payload;
|
|
906
|
+
}
|
|
907
|
+
return JSON.stringify(toSerializableValue(payload));
|
|
908
|
+
}
|
|
909
|
+
function formatLogArgument(value) {
|
|
910
|
+
const record = toRecord$1(value);
|
|
911
|
+
if (record.value !== void 0) {
|
|
912
|
+
return typeof record.value === "string" ? record.value : JSON.stringify(toSerializableValue(record.value));
|
|
913
|
+
}
|
|
914
|
+
if (typeof record.description === "string") {
|
|
915
|
+
return record.description;
|
|
916
|
+
}
|
|
917
|
+
return typeof value === "string" ? value : JSON.stringify(toSerializableValue(value));
|
|
918
|
+
}
|
|
919
|
+
function toRecord$1(value) {
|
|
920
|
+
return value && typeof value === "object" ? value : {};
|
|
921
|
+
}
|
|
922
|
+
function createUnavailableRuntimeHooks() {
|
|
923
|
+
return {
|
|
924
|
+
async connectMiniProgram() {
|
|
925
|
+
throw new Error("\u672A\u914D\u7F6E DevTools runtime hooks\u3002\u8BF7\u901A\u8FC7 createWeappViteMcpServer({ runtimeHooks }) \u6CE8\u5165 automator \u8FDE\u63A5\u80FD\u529B\u3002");
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const navigateSchema = {
|
|
931
|
+
...connectionInputSchema,
|
|
932
|
+
path: z.string().trim().min(1).optional(),
|
|
933
|
+
query: z.record(z.string(), z.string()).optional(),
|
|
934
|
+
transition: z.enum(["navigateTo", "redirectTo", "reLaunch", "switchTab", "navigateBack"]).optional(),
|
|
935
|
+
waitMs: z.number().int().nonnegative().optional()
|
|
936
|
+
};
|
|
937
|
+
const screenshotSchema = {
|
|
938
|
+
...connectionInputSchema,
|
|
939
|
+
outputPath: z.string().trim().min(1).optional()
|
|
940
|
+
};
|
|
941
|
+
const hostApiSchema = {
|
|
942
|
+
...connectionInputSchema,
|
|
943
|
+
method: z.string().trim().min(1),
|
|
944
|
+
args: z.array(z.unknown()).optional()
|
|
945
|
+
};
|
|
946
|
+
function registerDevtoolsRuntimeTools(server, manager) {
|
|
947
|
+
server.registerTool("weapp_devtools_connect", {
|
|
948
|
+
title: "Ensure Mini Program Connection",
|
|
949
|
+
description: "\u786E\u4FDD\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177 automator \u4F1A\u8BDD\u53EF\u7528\uFF0C\u5E76\u8FD4\u56DE\u5F53\u524D\u9875\u9762\u4E0E\u7CFB\u7EDF\u4FE1\u606F\u3002",
|
|
950
|
+
inputSchema: {
|
|
951
|
+
...connectionInputSchema,
|
|
952
|
+
reconnect: z.boolean().optional()
|
|
953
|
+
}
|
|
954
|
+
}, async ({ reconnect, ...connection }) => {
|
|
955
|
+
try {
|
|
956
|
+
if (reconnect) {
|
|
957
|
+
await manager.close(connection);
|
|
958
|
+
}
|
|
959
|
+
const result = await manager.withMiniProgram(connection, async (miniProgram) => {
|
|
960
|
+
const page = await miniProgram.currentPage().catch(() => null);
|
|
961
|
+
const systemInfo = await miniProgram.systemInfo().catch(() => null);
|
|
962
|
+
return {
|
|
963
|
+
connected: true,
|
|
964
|
+
projectPath: connection.projectPath,
|
|
965
|
+
resolvedProjectPath: manager.resolveProjectPath(connection.projectPath),
|
|
966
|
+
currentPage: page ? { path: page.path, query: toSerializableValue(page.query) } : null,
|
|
967
|
+
systemInfo: toSerializableValue(systemInfo)
|
|
968
|
+
};
|
|
969
|
+
});
|
|
970
|
+
return toToolResult(result);
|
|
971
|
+
} catch (error) {
|
|
972
|
+
return toToolError(error);
|
|
973
|
+
}
|
|
974
|
+
});
|
|
975
|
+
server.registerTool("weapp_devtools_route", {
|
|
976
|
+
title: "Navigate Mini Program",
|
|
977
|
+
description: "\u5728\u5C0F\u7A0B\u5E8F\u5185\u6267\u884C navigateTo\u3001redirectTo\u3001reLaunch\u3001switchTab \u6216 navigateBack\u3002",
|
|
978
|
+
inputSchema: navigateSchema
|
|
979
|
+
}, async ({ path: pagePath, query, transition = "navigateTo", waitMs, ...connection }) => {
|
|
980
|
+
try {
|
|
981
|
+
const result = await manager.withMiniProgram(connection, async (miniProgram) => {
|
|
982
|
+
if (transition === "navigateBack") {
|
|
983
|
+
const page2 = await miniProgram.navigateBack();
|
|
984
|
+
if (waitMs && page2) {
|
|
985
|
+
await page2.waitFor(waitMs);
|
|
986
|
+
}
|
|
987
|
+
return {
|
|
988
|
+
transition,
|
|
989
|
+
activePage: page2 ? { path: page2.path, query: toSerializableValue(page2.query) } : null
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
if (!pagePath) {
|
|
993
|
+
throw new Error("transition \u4E0D\u662F navigateBack \u65F6\u5FC5\u987B\u63D0\u4F9B path\u3002");
|
|
994
|
+
}
|
|
995
|
+
const url = buildUrl(pagePath, query);
|
|
996
|
+
const page = await callRequiredMethod(
|
|
997
|
+
miniProgram,
|
|
998
|
+
transition,
|
|
999
|
+
url
|
|
1000
|
+
);
|
|
1001
|
+
if (waitMs && page) {
|
|
1002
|
+
await page.waitFor(waitMs);
|
|
1003
|
+
}
|
|
1004
|
+
return {
|
|
1005
|
+
transition,
|
|
1006
|
+
url,
|
|
1007
|
+
activePage: page ? { path: page.path, query: toSerializableValue(page.query) } : null
|
|
1008
|
+
};
|
|
1009
|
+
});
|
|
1010
|
+
return toToolResult(result);
|
|
1011
|
+
} catch (error) {
|
|
1012
|
+
return toToolError(error);
|
|
1013
|
+
}
|
|
1014
|
+
});
|
|
1015
|
+
server.registerTool("weapp_devtools_active_page", {
|
|
1016
|
+
title: "Current Mini Program Page",
|
|
1017
|
+
description: "\u83B7\u53D6\u5F53\u524D\u9875\u9762\u8DEF\u5F84\u3001\u67E5\u8BE2\u53C2\u6570\u3001\u5C3A\u5BF8\u3001\u6EDA\u52A8\u4F4D\u7F6E\uFF1B\u53EF\u9009\u8FD4\u56DE\u9875\u9762 data\u3002",
|
|
1018
|
+
inputSchema: {
|
|
1019
|
+
...connectionInputSchema,
|
|
1020
|
+
withData: z.boolean().optional()
|
|
1021
|
+
}
|
|
1022
|
+
}, async ({ withData, ...connection }) => {
|
|
1023
|
+
try {
|
|
1024
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1025
|
+
const [size, scrollTop, data] = await Promise.all([
|
|
1026
|
+
page.size().catch(() => null),
|
|
1027
|
+
page.scrollTop().catch(() => null),
|
|
1028
|
+
withData ? page.data().catch(() => null) : Promise.resolve(void 0)
|
|
1029
|
+
]);
|
|
1030
|
+
return compactObject({
|
|
1031
|
+
path: page.path,
|
|
1032
|
+
query: toSerializableValue(page.query),
|
|
1033
|
+
size: toSerializableValue(size),
|
|
1034
|
+
scrollTop: toSerializableValue(scrollTop),
|
|
1035
|
+
data: toSerializableValue(data)
|
|
1036
|
+
});
|
|
1037
|
+
});
|
|
1038
|
+
return toToolResult(result);
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
return toToolError(error);
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
1043
|
+
server.registerTool("weapp_devtools_page_stack", {
|
|
1044
|
+
title: "Mini Program Page Stack",
|
|
1045
|
+
description: "\u83B7\u53D6\u5F53\u524D\u5C0F\u7A0B\u5E8F\u9875\u9762\u6808\u3002",
|
|
1046
|
+
inputSchema: connectionInputSchema
|
|
1047
|
+
}, async (connection) => {
|
|
1048
|
+
try {
|
|
1049
|
+
const result = await manager.withMiniProgram(connection, async (miniProgram) => {
|
|
1050
|
+
const stack = await miniProgram.pageStack();
|
|
1051
|
+
return stack.map((page) => ({
|
|
1052
|
+
path: page.path,
|
|
1053
|
+
query: toSerializableValue(page.query)
|
|
1054
|
+
}));
|
|
1055
|
+
});
|
|
1056
|
+
return toToolResult(result);
|
|
1057
|
+
} catch (error) {
|
|
1058
|
+
return toToolError(error);
|
|
1059
|
+
}
|
|
1060
|
+
});
|
|
1061
|
+
server.registerTool("weapp_devtools_capture", {
|
|
1062
|
+
title: "Mini Program Screenshot",
|
|
1063
|
+
description: "\u622A\u53D6\u5F53\u524D\u5C0F\u7A0B\u5E8F\u89C6\u53E3\uFF0C\u8FD4\u56DE base64\uFF0C\u6216\u4FDD\u5B58\u5230 workspaceRoot \u76F8\u5BF9 outputPath\u3002",
|
|
1064
|
+
inputSchema: screenshotSchema
|
|
1065
|
+
}, async ({ outputPath, ...connection }) => {
|
|
1066
|
+
try {
|
|
1067
|
+
const result = await manager.withMiniProgram(connection, async (miniProgram) => {
|
|
1068
|
+
const screenshot = await miniProgram.screenshot();
|
|
1069
|
+
const buffer = typeof screenshot === "string" ? Buffer.from(screenshot, "base64") : Buffer.from(screenshot);
|
|
1070
|
+
if (outputPath) {
|
|
1071
|
+
const resolvedOutputPath = manager.resolveWorkspacePath(outputPath);
|
|
1072
|
+
await fs$1.mkdir(path.dirname(resolvedOutputPath), { recursive: true });
|
|
1073
|
+
await fs$1.writeFile(resolvedOutputPath, buffer);
|
|
1074
|
+
return {
|
|
1075
|
+
path: resolvedOutputPath,
|
|
1076
|
+
bytes: buffer.length
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
return {
|
|
1080
|
+
base64: buffer.toString("base64"),
|
|
1081
|
+
bytes: buffer.length
|
|
1082
|
+
};
|
|
1083
|
+
});
|
|
1084
|
+
return toToolResult(result);
|
|
1085
|
+
} catch (error) {
|
|
1086
|
+
return toToolError(error);
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
server.registerTool("weapp_devtools_host_api", {
|
|
1090
|
+
title: "Call wx Method",
|
|
1091
|
+
description: "\u8C03\u7528\u5FAE\u4FE1\u5C0F\u7A0B\u5E8F wx API\uFF0C\u4F8B\u5982 wx.pageScrollTo\u3002",
|
|
1092
|
+
inputSchema: hostApiSchema
|
|
1093
|
+
}, async ({ method, args, ...connection }) => {
|
|
1094
|
+
try {
|
|
1095
|
+
const result = await manager.withMiniProgram(connection, async (miniProgram) => {
|
|
1096
|
+
const callArgs = args ?? [];
|
|
1097
|
+
const callResult = await miniProgram.callWxMethod(method, ...callArgs);
|
|
1098
|
+
return {
|
|
1099
|
+
method,
|
|
1100
|
+
args: toSerializableValue(callArgs),
|
|
1101
|
+
result: toSerializableValue(callResult)
|
|
1102
|
+
};
|
|
1103
|
+
});
|
|
1104
|
+
return toToolResult(result);
|
|
1105
|
+
} catch (error) {
|
|
1106
|
+
return toToolError(error);
|
|
1107
|
+
}
|
|
1108
|
+
});
|
|
1109
|
+
server.registerTool("weapp_devtools_console", {
|
|
1110
|
+
title: "Get Mini Program Logs",
|
|
1111
|
+
description: "\u8BFB\u53D6 MCP \u4F1A\u8BDD\u6355\u83B7\u5230\u7684\u5C0F\u7A0B\u5E8F console/exception \u65E5\u5FD7\uFF1B\u53EF\u9009\u8BFB\u53D6\u540E\u6E05\u7A7A\u3002",
|
|
1112
|
+
inputSchema: {
|
|
1113
|
+
clear: z.boolean().optional()
|
|
1114
|
+
}
|
|
1115
|
+
}, async ({ clear }) => {
|
|
1116
|
+
try {
|
|
1117
|
+
const logs = manager.getLogs();
|
|
1118
|
+
if (clear) {
|
|
1119
|
+
manager.clearLogs();
|
|
1120
|
+
}
|
|
1121
|
+
return toToolResult({
|
|
1122
|
+
count: logs.length,
|
|
1123
|
+
logs
|
|
1124
|
+
});
|
|
1125
|
+
} catch (error) {
|
|
1126
|
+
return toToolError(error);
|
|
1127
|
+
}
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
const elementSelectorSchema = {
|
|
1132
|
+
...connectionInputSchema,
|
|
1133
|
+
selector: z.string().trim().min(1),
|
|
1134
|
+
innerSelector: z.string().trim().min(1).optional()
|
|
1135
|
+
};
|
|
1136
|
+
function registerRuntimeNodeTools(server, manager) {
|
|
1137
|
+
server.registerTool("weapp_runtime_tap_node", {
|
|
1138
|
+
title: "Tap Element",
|
|
1139
|
+
description: "\u70B9\u51FB\u9875\u9762\u5143\u7D20\uFF0C\u652F\u6301 selector[index=N]\u3001innerSelector \u548C\u70B9\u51FB\u540E\u7B49\u5F85\u3002",
|
|
1140
|
+
inputSchema: {
|
|
1141
|
+
...elementSelectorSchema,
|
|
1142
|
+
waitMs: z.number().int().nonnegative().optional()
|
|
1143
|
+
}
|
|
1144
|
+
}, async ({ selector, innerSelector, waitMs, ...connection }) => {
|
|
1145
|
+
try {
|
|
1146
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1147
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1148
|
+
await element.tap();
|
|
1149
|
+
if (waitMs) {
|
|
1150
|
+
await page.waitFor(waitMs);
|
|
1151
|
+
}
|
|
1152
|
+
return {
|
|
1153
|
+
selector,
|
|
1154
|
+
innerSelector: innerSelector ?? null,
|
|
1155
|
+
waitedMs: waitMs ?? 0
|
|
1156
|
+
};
|
|
1157
|
+
});
|
|
1158
|
+
return toToolResult(result);
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
return toToolError(error);
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
server.registerTool("weapp_runtime_input_node", {
|
|
1164
|
+
title: "Input Element Text",
|
|
1165
|
+
description: "\u5411 input \u6216 textarea \u5143\u7D20\u8F93\u5165\u6587\u672C\u3002",
|
|
1166
|
+
inputSchema: {
|
|
1167
|
+
...elementSelectorSchema,
|
|
1168
|
+
value: z.union([z.string(), z.number()])
|
|
1169
|
+
}
|
|
1170
|
+
}, async ({ selector, innerSelector, value, ...connection }) => {
|
|
1171
|
+
try {
|
|
1172
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1173
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1174
|
+
await callRequiredMethod(element, "input", String(value));
|
|
1175
|
+
return {
|
|
1176
|
+
selector,
|
|
1177
|
+
innerSelector: innerSelector ?? null,
|
|
1178
|
+
value: String(value)
|
|
1179
|
+
};
|
|
1180
|
+
});
|
|
1181
|
+
return toToolResult(result);
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
return toToolError(error);
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
server.registerTool("weapp_runtime_invoke_component", {
|
|
1187
|
+
title: "Call Element Method",
|
|
1188
|
+
description: "\u8C03\u7528\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u5143\u7D20\u5B9E\u4F8B\u65B9\u6CD5\u3002",
|
|
1189
|
+
inputSchema: {
|
|
1190
|
+
...elementSelectorSchema,
|
|
1191
|
+
method: z.string().trim().min(1),
|
|
1192
|
+
args: z.array(z.unknown()).optional()
|
|
1193
|
+
}
|
|
1194
|
+
}, async ({ selector, innerSelector, method, args, ...connection }) => {
|
|
1195
|
+
try {
|
|
1196
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1197
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1198
|
+
const callArgs = args ?? [];
|
|
1199
|
+
return {
|
|
1200
|
+
selector,
|
|
1201
|
+
innerSelector: innerSelector ?? null,
|
|
1202
|
+
method,
|
|
1203
|
+
args: toSerializableValue(callArgs),
|
|
1204
|
+
result: toSerializableValue(await callRequiredMethod(element, method, ...callArgs))
|
|
1205
|
+
};
|
|
1206
|
+
});
|
|
1207
|
+
return toToolResult(result);
|
|
1208
|
+
} catch (error) {
|
|
1209
|
+
return toToolError(error);
|
|
1210
|
+
}
|
|
1211
|
+
});
|
|
1212
|
+
server.registerTool("weapp_runtime_component_state", {
|
|
1213
|
+
title: "Get Element Data",
|
|
1214
|
+
description: "\u8BFB\u53D6\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u5143\u7D20 data\uFF0C\u53EF\u901A\u8FC7 path \u8BFB\u53D6\u5D4C\u5957\u5B57\u6BB5\u3002",
|
|
1215
|
+
inputSchema: {
|
|
1216
|
+
...elementSelectorSchema,
|
|
1217
|
+
path: z.string().trim().min(1).optional()
|
|
1218
|
+
}
|
|
1219
|
+
}, async ({ selector, innerSelector, path, ...connection }) => {
|
|
1220
|
+
try {
|
|
1221
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1222
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1223
|
+
return {
|
|
1224
|
+
selector,
|
|
1225
|
+
innerSelector: innerSelector ?? null,
|
|
1226
|
+
path: path ?? null,
|
|
1227
|
+
data: toSerializableValue(await callRequiredMethod(element, "data", path))
|
|
1228
|
+
};
|
|
1229
|
+
});
|
|
1230
|
+
return toToolResult(result);
|
|
1231
|
+
} catch (error) {
|
|
1232
|
+
return toToolError(error);
|
|
1233
|
+
}
|
|
1234
|
+
});
|
|
1235
|
+
server.registerTool("weapp_runtime_update_component_state", {
|
|
1236
|
+
title: "Set Element Data",
|
|
1237
|
+
description: "\u8C03\u7528\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u5143\u7D20 setData \u66F4\u65B0 data\u3002",
|
|
1238
|
+
inputSchema: {
|
|
1239
|
+
...elementSelectorSchema,
|
|
1240
|
+
data: z.record(z.string(), z.unknown())
|
|
1241
|
+
}
|
|
1242
|
+
}, async ({ selector, innerSelector, data, ...connection }) => {
|
|
1243
|
+
try {
|
|
1244
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1245
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1246
|
+
await callRequiredMethod(element, "setData", data);
|
|
1247
|
+
return {
|
|
1248
|
+
selector,
|
|
1249
|
+
innerSelector: innerSelector ?? null,
|
|
1250
|
+
keys: Object.keys(data)
|
|
1251
|
+
};
|
|
1252
|
+
});
|
|
1253
|
+
return toToolResult(result);
|
|
1254
|
+
} catch (error) {
|
|
1255
|
+
return toToolError(error);
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
1258
|
+
server.registerTool("weapp_runtime_find_child", {
|
|
1259
|
+
title: "Get Inner Element",
|
|
1260
|
+
description: "\u5728\u5143\u7D20\u8303\u56F4\u5185\u67E5\u8BE2\u5355\u4E2A\u5185\u90E8\u5143\u7D20\u3002",
|
|
1261
|
+
inputSchema: {
|
|
1262
|
+
...elementSelectorSchema,
|
|
1263
|
+
targetSelector: z.string().trim().min(1),
|
|
1264
|
+
withWxml: z.boolean().optional()
|
|
1265
|
+
}
|
|
1266
|
+
}, async ({ selector, innerSelector, targetSelector, withWxml, ...connection }) => {
|
|
1267
|
+
try {
|
|
1268
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1269
|
+
const parent = await resolveElement(page, selector, innerSelector);
|
|
1270
|
+
const element = await callRequiredMethod(parent, "$", targetSelector);
|
|
1271
|
+
if (!element) {
|
|
1272
|
+
throw new Error(`\u5728\u5143\u7D20 "${selector}" \u5185\u672A\u627E\u5230\u5143\u7D20: ${targetSelector}`);
|
|
1273
|
+
}
|
|
1274
|
+
return {
|
|
1275
|
+
selector,
|
|
1276
|
+
innerSelector: innerSelector ?? null,
|
|
1277
|
+
targetSelector,
|
|
1278
|
+
...await summarizeElement(element, withWxml)
|
|
1279
|
+
};
|
|
1280
|
+
});
|
|
1281
|
+
return toToolResult(result);
|
|
1282
|
+
} catch (error) {
|
|
1283
|
+
return toToolError(error);
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
server.registerTool("weapp_runtime_find_children", {
|
|
1287
|
+
title: "Get Inner Elements",
|
|
1288
|
+
description: "\u5728\u5143\u7D20\u8303\u56F4\u5185\u67E5\u8BE2\u5185\u90E8\u5143\u7D20\u6570\u7EC4\u3002",
|
|
1289
|
+
inputSchema: {
|
|
1290
|
+
...elementSelectorSchema,
|
|
1291
|
+
targetSelector: z.string().trim().min(1),
|
|
1292
|
+
withWxml: z.boolean().optional()
|
|
1293
|
+
}
|
|
1294
|
+
}, async ({ selector, innerSelector, targetSelector, withWxml, ...connection }) => {
|
|
1295
|
+
try {
|
|
1296
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1297
|
+
const parent = await resolveElement(page, selector, innerSelector);
|
|
1298
|
+
const elements = await callRequiredMethod(parent, "$$", targetSelector);
|
|
1299
|
+
if (!Array.isArray(elements)) {
|
|
1300
|
+
throw new TypeError(`\u5728\u5143\u7D20 "${selector}" \u5185\u67E5\u8BE2 "${targetSelector}" \u5931\u8D25\u3002`);
|
|
1301
|
+
}
|
|
1302
|
+
return {
|
|
1303
|
+
selector,
|
|
1304
|
+
innerSelector: innerSelector ?? null,
|
|
1305
|
+
targetSelector,
|
|
1306
|
+
count: elements.length,
|
|
1307
|
+
elements: await Promise.all(elements.map(async (element, index) => ({
|
|
1308
|
+
index,
|
|
1309
|
+
...await summarizeElement(element, withWxml)
|
|
1310
|
+
})))
|
|
1311
|
+
};
|
|
1312
|
+
});
|
|
1313
|
+
return toToolResult(result);
|
|
1314
|
+
} catch (error) {
|
|
1315
|
+
return toToolError(error);
|
|
1316
|
+
}
|
|
1317
|
+
});
|
|
1318
|
+
server.registerTool("weapp_runtime_node_markup", {
|
|
1319
|
+
title: "Get Element WXML",
|
|
1320
|
+
description: "\u8BFB\u53D6\u5143\u7D20 inner WXML \u6216 outer WXML\u3002",
|
|
1321
|
+
inputSchema: {
|
|
1322
|
+
...elementSelectorSchema,
|
|
1323
|
+
outer: z.boolean().optional()
|
|
1324
|
+
}
|
|
1325
|
+
}, async ({ selector, innerSelector, outer, ...connection }) => {
|
|
1326
|
+
try {
|
|
1327
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1328
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1329
|
+
const method = outer ? "outerWxml" : "wxml";
|
|
1330
|
+
return {
|
|
1331
|
+
selector,
|
|
1332
|
+
innerSelector: innerSelector ?? null,
|
|
1333
|
+
type: method,
|
|
1334
|
+
wxml: toSerializableValue(await callRequiredMethod(element, method))
|
|
1335
|
+
};
|
|
1336
|
+
});
|
|
1337
|
+
return toToolResult(result);
|
|
1338
|
+
} catch (error) {
|
|
1339
|
+
return toToolError(error);
|
|
1340
|
+
}
|
|
1341
|
+
});
|
|
1342
|
+
server.registerTool("weapp_runtime_node_styles", {
|
|
1343
|
+
title: "Get Element Styles",
|
|
1344
|
+
description: "\u8BFB\u53D6\u5143\u7D20\u6837\u5F0F\u503C\u3002",
|
|
1345
|
+
inputSchema: {
|
|
1346
|
+
...elementSelectorSchema,
|
|
1347
|
+
names: z.array(z.string().trim().min(1)).min(1)
|
|
1348
|
+
}
|
|
1349
|
+
}, async ({ selector, innerSelector, names, ...connection }) => {
|
|
1350
|
+
try {
|
|
1351
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1352
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1353
|
+
return {
|
|
1354
|
+
selector,
|
|
1355
|
+
innerSelector: innerSelector ?? null,
|
|
1356
|
+
styles: Object.fromEntries(await Promise.all(names.map(async (name) => [
|
|
1357
|
+
name,
|
|
1358
|
+
toSerializableValue(await callMaybe(element, "style", name))
|
|
1359
|
+
])))
|
|
1360
|
+
};
|
|
1361
|
+
});
|
|
1362
|
+
return toToolResult(result);
|
|
1363
|
+
} catch (error) {
|
|
1364
|
+
return toToolError(error);
|
|
1365
|
+
}
|
|
1366
|
+
});
|
|
1367
|
+
server.registerTool("weapp_runtime_node_attrs", {
|
|
1368
|
+
title: "Get Element Attributes",
|
|
1369
|
+
description: "\u8BFB\u53D6\u5143\u7D20 attribute \u503C\u3002",
|
|
1370
|
+
inputSchema: {
|
|
1371
|
+
...elementSelectorSchema,
|
|
1372
|
+
names: z.array(z.string().trim().min(1)).min(1)
|
|
1373
|
+
}
|
|
1374
|
+
}, async ({ selector, innerSelector, names, ...connection }) => {
|
|
1375
|
+
try {
|
|
1376
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1377
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1378
|
+
return {
|
|
1379
|
+
selector,
|
|
1380
|
+
innerSelector: innerSelector ?? null,
|
|
1381
|
+
attributes: Object.fromEntries(await Promise.all(names.map(async (name) => [
|
|
1382
|
+
name,
|
|
1383
|
+
toSerializableValue(await callMaybe(element, "attribute", name))
|
|
1384
|
+
])))
|
|
1385
|
+
};
|
|
1386
|
+
});
|
|
1387
|
+
return toToolResult(result);
|
|
1388
|
+
} catch (error) {
|
|
1389
|
+
return toToolError(error);
|
|
1390
|
+
}
|
|
1391
|
+
});
|
|
1392
|
+
server.registerTool("weapp_runtime_scroll_node", {
|
|
1393
|
+
title: "Scroll Element",
|
|
1394
|
+
description: "\u6EDA\u52A8 scroll-view \u5143\u7D20\u5230\u6307\u5B9A\u4F4D\u7F6E\u3002",
|
|
1395
|
+
inputSchema: {
|
|
1396
|
+
...elementSelectorSchema,
|
|
1397
|
+
x: z.number(),
|
|
1398
|
+
y: z.number()
|
|
1399
|
+
}
|
|
1400
|
+
}, async ({ selector, innerSelector, x, y, ...connection }) => {
|
|
1401
|
+
try {
|
|
1402
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1403
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1404
|
+
await callRequiredMethod(element, "scrollTo", x, y);
|
|
1405
|
+
return {
|
|
1406
|
+
selector,
|
|
1407
|
+
innerSelector: innerSelector ?? null,
|
|
1408
|
+
x,
|
|
1409
|
+
y
|
|
1410
|
+
};
|
|
1411
|
+
});
|
|
1412
|
+
return toToolResult(result);
|
|
1413
|
+
} catch (error) {
|
|
1414
|
+
return toToolError(error);
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1417
|
+
server.registerTool("weapp_runtime_measure_node", {
|
|
1418
|
+
title: "Get Element Bounding Rect",
|
|
1419
|
+
description: "\u8BFB\u53D6\u5143\u7D20\u89C6\u53E3\u77E9\u5F62\uFF1B\u4F18\u5148\u4F7F\u7528\u5143\u7D20 offset/size\uFF0C\u7F3A\u5931\u65F6\u8FD4\u56DE\u53EF\u7528\u5B57\u6BB5\u3002",
|
|
1420
|
+
inputSchema: elementSelectorSchema
|
|
1421
|
+
}, async ({ selector, innerSelector, ...connection }) => {
|
|
1422
|
+
try {
|
|
1423
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1424
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1425
|
+
const offset = toRecord(await callMaybe(element, "offset"));
|
|
1426
|
+
const size = toRecord(await callMaybe(element, "size"));
|
|
1427
|
+
const left = toNumber(offset.left);
|
|
1428
|
+
const top = toNumber(offset.top);
|
|
1429
|
+
const width = toNumber(size.width ?? offset.width);
|
|
1430
|
+
const height = toNumber(size.height ?? offset.height);
|
|
1431
|
+
return {
|
|
1432
|
+
selector,
|
|
1433
|
+
innerSelector: innerSelector ?? null,
|
|
1434
|
+
boundingClientRect: compactObject({
|
|
1435
|
+
left,
|
|
1436
|
+
top,
|
|
1437
|
+
width,
|
|
1438
|
+
height,
|
|
1439
|
+
right: left !== void 0 && width !== void 0 ? left + width : void 0,
|
|
1440
|
+
bottom: top !== void 0 && height !== void 0 ? top + height : void 0,
|
|
1441
|
+
rawOffset: toSerializableValue(offset),
|
|
1442
|
+
rawSize: toSerializableValue(size),
|
|
1443
|
+
tagName: readProperty(element, "tagName")
|
|
1444
|
+
})
|
|
1445
|
+
};
|
|
1446
|
+
});
|
|
1447
|
+
return toToolResult(result);
|
|
1448
|
+
} catch (error) {
|
|
1449
|
+
return toToolError(error);
|
|
1450
|
+
}
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
function toRecord(value) {
|
|
1454
|
+
return value && typeof value === "object" ? value : {};
|
|
1455
|
+
}
|
|
1456
|
+
function toNumber(value) {
|
|
1457
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
const selectorSchema = {
|
|
1461
|
+
...connectionInputSchema,
|
|
1462
|
+
selector: z.string().trim().min(1),
|
|
1463
|
+
innerSelector: z.string().trim().min(1).optional(),
|
|
1464
|
+
withWxml: z.boolean().optional()
|
|
1465
|
+
};
|
|
1466
|
+
function registerRuntimePageTools(server, manager) {
|
|
1467
|
+
server.registerTool("weapp_runtime_find_node", {
|
|
1468
|
+
title: "Get Page Element",
|
|
1469
|
+
description: "\u901A\u8FC7\u9009\u62E9\u5668\u83B7\u53D6\u5F53\u524D\u9875\u9762\u5143\u7D20\u6458\u8981\uFF0C\u652F\u6301 selector[index=N]\u3001innerSelector \u4E0E withWxml\u3002",
|
|
1470
|
+
inputSchema: selectorSchema
|
|
1471
|
+
}, async ({ selector, innerSelector, withWxml, ...connection }) => {
|
|
1472
|
+
try {
|
|
1473
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1474
|
+
const element = await resolveElement(page, selector, innerSelector);
|
|
1475
|
+
return {
|
|
1476
|
+
selector,
|
|
1477
|
+
innerSelector: innerSelector ?? null,
|
|
1478
|
+
...await summarizeElement(element, withWxml)
|
|
1479
|
+
};
|
|
1480
|
+
});
|
|
1481
|
+
return toToolResult(result);
|
|
1482
|
+
} catch (error) {
|
|
1483
|
+
return toToolError(error);
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
server.registerTool("weapp_runtime_find_nodes", {
|
|
1487
|
+
title: "Get Page Elements",
|
|
1488
|
+
description: "\u901A\u8FC7\u9009\u62E9\u5668\u83B7\u53D6\u5F53\u524D\u9875\u9762\u5143\u7D20\u6570\u7EC4\u6458\u8981\uFF0C\u652F\u6301 selector[index=N] \u4E0E withWxml\u3002",
|
|
1489
|
+
inputSchema: {
|
|
1490
|
+
...connectionInputSchema,
|
|
1491
|
+
selector: z.string().trim().min(1),
|
|
1492
|
+
withWxml: z.boolean().optional()
|
|
1493
|
+
}
|
|
1494
|
+
}, async ({ selector, withWxml, ...connection }) => {
|
|
1495
|
+
try {
|
|
1496
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1497
|
+
const elements = await queryElements(page, selector);
|
|
1498
|
+
return {
|
|
1499
|
+
selector,
|
|
1500
|
+
count: elements.length,
|
|
1501
|
+
elements: await Promise.all(elements.map(async (element, index) => ({
|
|
1502
|
+
index,
|
|
1503
|
+
...await summarizeElement(element, withWxml)
|
|
1504
|
+
})))
|
|
1505
|
+
};
|
|
1506
|
+
});
|
|
1507
|
+
return toToolResult(result);
|
|
1508
|
+
} catch (error) {
|
|
1509
|
+
return toToolError(error);
|
|
1510
|
+
}
|
|
1511
|
+
});
|
|
1512
|
+
server.registerTool("weapp_runtime_wait_node", {
|
|
1513
|
+
title: "Wait Page Element",
|
|
1514
|
+
description: "\u8F6E\u8BE2\u7B49\u5F85\u5143\u7D20\u51FA\u73B0\uFF0C\u652F\u6301 selector[index=N]\u3002",
|
|
1515
|
+
inputSchema: {
|
|
1516
|
+
...connectionInputSchema,
|
|
1517
|
+
selector: z.string().trim().min(1),
|
|
1518
|
+
timeoutMs: z.number().int().positive().optional(),
|
|
1519
|
+
intervalMs: z.number().int().positive().optional()
|
|
1520
|
+
}
|
|
1521
|
+
}, async ({ selector, timeoutMs = 5e3, intervalMs = 200, ...connection }) => {
|
|
1522
|
+
try {
|
|
1523
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1524
|
+
const startedAt = Date.now();
|
|
1525
|
+
while (Date.now() - startedAt <= timeoutMs) {
|
|
1526
|
+
const elements = await queryElements(page, selector).catch(() => []);
|
|
1527
|
+
if (elements.length > 0) {
|
|
1528
|
+
return {
|
|
1529
|
+
selector,
|
|
1530
|
+
found: true,
|
|
1531
|
+
count: elements.length,
|
|
1532
|
+
waitMs: Date.now() - startedAt
|
|
1533
|
+
};
|
|
1534
|
+
}
|
|
1535
|
+
await page.waitFor(intervalMs);
|
|
1536
|
+
}
|
|
1537
|
+
throw new Error(`\u7B49\u5F85\u5143\u7D20 "${selector}" \u8D85\u65F6 (${timeoutMs}ms)\u3002`);
|
|
1538
|
+
});
|
|
1539
|
+
return toToolResult(result);
|
|
1540
|
+
} catch (error) {
|
|
1541
|
+
return toToolError(error);
|
|
1542
|
+
}
|
|
1543
|
+
});
|
|
1544
|
+
server.registerTool("weapp_runtime_wait", {
|
|
1545
|
+
title: "Wait Page Timeout",
|
|
1546
|
+
description: "\u5728\u5F53\u524D\u9875\u9762\u7B49\u5F85\u6307\u5B9A\u6BEB\u79D2\u6570\u3002",
|
|
1547
|
+
inputSchema: {
|
|
1548
|
+
...connectionInputSchema,
|
|
1549
|
+
milliseconds: z.number().int().nonnegative()
|
|
1550
|
+
}
|
|
1551
|
+
}, async ({ milliseconds, ...connection }) => {
|
|
1552
|
+
try {
|
|
1553
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1554
|
+
await page.waitFor(milliseconds);
|
|
1555
|
+
return { waitedMs: milliseconds };
|
|
1556
|
+
});
|
|
1557
|
+
return toToolResult(result);
|
|
1558
|
+
} catch (error) {
|
|
1559
|
+
return toToolError(error);
|
|
1560
|
+
}
|
|
1561
|
+
});
|
|
1562
|
+
server.registerTool("weapp_runtime_page_state", {
|
|
1563
|
+
title: "Get Page Data",
|
|
1564
|
+
description: "\u8BFB\u53D6\u5F53\u524D\u9875\u9762 data\uFF0C\u53EF\u901A\u8FC7 path \u8BFB\u53D6\u5D4C\u5957\u5B57\u6BB5\u3002",
|
|
1565
|
+
inputSchema: {
|
|
1566
|
+
...connectionInputSchema,
|
|
1567
|
+
path: z.string().trim().min(1).optional()
|
|
1568
|
+
}
|
|
1569
|
+
}, async ({ path, ...connection }) => {
|
|
1570
|
+
try {
|
|
1571
|
+
const result = await manager.withPage(connection, async (page) => ({
|
|
1572
|
+
path: path ?? null,
|
|
1573
|
+
data: toSerializableValue(await page.data(path))
|
|
1574
|
+
}));
|
|
1575
|
+
return toToolResult(result);
|
|
1576
|
+
} catch (error) {
|
|
1577
|
+
return toToolError(error);
|
|
1578
|
+
}
|
|
1579
|
+
});
|
|
1580
|
+
server.registerTool("weapp_runtime_update_page_state", {
|
|
1581
|
+
title: "Set Page Data",
|
|
1582
|
+
description: "\u8C03\u7528\u5F53\u524D\u9875\u9762 setData \u66F4\u65B0 data\u3002",
|
|
1583
|
+
inputSchema: {
|
|
1584
|
+
...connectionInputSchema,
|
|
1585
|
+
data: z.record(z.string(), z.unknown()),
|
|
1586
|
+
verify: z.boolean().optional()
|
|
1587
|
+
}
|
|
1588
|
+
}, async ({ data, verify, ...connection }) => {
|
|
1589
|
+
try {
|
|
1590
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1591
|
+
await callRequiredMethod(page, "setData", data);
|
|
1592
|
+
return {
|
|
1593
|
+
keys: Object.keys(data),
|
|
1594
|
+
data: verify ? toSerializableValue(await page.data()) : void 0
|
|
1595
|
+
};
|
|
1596
|
+
});
|
|
1597
|
+
return toToolResult(result);
|
|
1598
|
+
} catch (error) {
|
|
1599
|
+
return toToolError(error);
|
|
1600
|
+
}
|
|
440
1601
|
});
|
|
1602
|
+
server.registerTool("weapp_runtime_invoke_page", {
|
|
1603
|
+
title: "Call Page Method",
|
|
1604
|
+
description: "\u8C03\u7528\u5F53\u524D\u9875\u9762\u5B9E\u4F8B\u65B9\u6CD5\u3002",
|
|
1605
|
+
inputSchema: {
|
|
1606
|
+
...connectionInputSchema,
|
|
1607
|
+
method: z.string().trim().min(1),
|
|
1608
|
+
args: z.array(z.unknown()).optional()
|
|
1609
|
+
}
|
|
1610
|
+
}, async ({ method, args, ...connection }) => {
|
|
1611
|
+
try {
|
|
1612
|
+
const result = await manager.withPage(connection, async (page) => {
|
|
1613
|
+
const callArgs = args ?? [];
|
|
1614
|
+
return {
|
|
1615
|
+
method,
|
|
1616
|
+
args: toSerializableValue(callArgs),
|
|
1617
|
+
result: toSerializableValue(await callRequiredMethod(page, method, ...callArgs))
|
|
1618
|
+
};
|
|
1619
|
+
});
|
|
1620
|
+
return toToolResult(result);
|
|
1621
|
+
} catch (error) {
|
|
1622
|
+
return toToolError(error);
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
function registerRuntimeTools(server, options) {
|
|
1628
|
+
const manager = new RuntimeSessionManager(options.workspaceRoot, options.runtimeHooks);
|
|
1629
|
+
registerDevtoolsRuntimeTools(server, manager);
|
|
1630
|
+
registerRuntimePageTools(server, manager);
|
|
1631
|
+
registerRuntimeNodeTools(server, manager);
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
async function loadPackageSummary(workspaceRoot, id) {
|
|
1635
|
+
return resolveExposedPackage(workspaceRoot, id);
|
|
1636
|
+
}
|
|
1637
|
+
async function loadExposedCatalog(workspaceRoot) {
|
|
1638
|
+
return resolveExposedPackages(workspaceRoot);
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
function registerServerTools(server, options) {
|
|
1642
|
+
const { workspaceRoot, packageIds, packageIdSchema } = options;
|
|
441
1643
|
server.registerTool("workspace_catalog", {
|
|
442
1644
|
title: "Workspace Catalog",
|
|
443
1645
|
description: "\u8BFB\u53D6 weapp-vite / wevu \u76F8\u5173\u5305\u76EE\u5F55\u4E0E\u811A\u672C\u80FD\u529B\u6E05\u5355"
|
|
444
1646
|
}, async () => {
|
|
445
1647
|
try {
|
|
446
|
-
const
|
|
1648
|
+
const catalog = await loadExposedCatalog(workspaceRoot);
|
|
447
1649
|
return toToolResult({
|
|
448
1650
|
workspaceRoot,
|
|
449
|
-
packages:
|
|
1651
|
+
packages: catalog
|
|
450
1652
|
});
|
|
451
1653
|
} catch (error) {
|
|
452
1654
|
return toToolError(error);
|
|
@@ -695,137 +1897,32 @@ async function createWeappViteMcpServer(options) {
|
|
|
695
1897
|
return toToolError(error);
|
|
696
1898
|
}
|
|
697
1899
|
});
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
return {
|
|
708
|
-
messages: [
|
|
709
|
-
{
|
|
710
|
-
role: "user",
|
|
711
|
-
content: {
|
|
712
|
-
type: "text",
|
|
713
|
-
text: [
|
|
714
|
-
"\u4F60\u662F weapp-vite monorepo \u7EF4\u62A4\u8005\uFF0C\u8BF7\u7ED9\u51FA\u53EF\u6267\u884C\u7684\u6539\u9020\u8BA1\u5212\u3002",
|
|
715
|
-
`\u76EE\u6807\uFF1A${objective}`,
|
|
716
|
-
`\u805A\u7126\u5305\uFF1A${targets.join(", ")}`,
|
|
717
|
-
"\u8BF7\u5305\u542B\uFF1A\u5F71\u54CD\u9762\u3001\u98CE\u9669\u70B9\u3001\u6D4B\u8BD5\u7B56\u7565\u3001\u56DE\u6EDA\u7B56\u7565\u3002"
|
|
718
|
-
].join("\n")
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
]
|
|
722
|
-
};
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
const packageIds = Object.keys(EXPOSED_PACKAGES);
|
|
1903
|
+
const packageIdSchema = z.enum(packageIds);
|
|
1904
|
+
async function createWeappViteMcpServer(options) {
|
|
1905
|
+
const workspaceRoot = resolveWorkspaceRoot(options?.workspaceRoot);
|
|
1906
|
+
const server = new McpServer({
|
|
1907
|
+
name: MCP_SERVER_NAME,
|
|
1908
|
+
version: MCP_SERVER_VERSION
|
|
723
1909
|
});
|
|
724
|
-
server
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
symptom: z.string().min(1)
|
|
729
|
-
}
|
|
730
|
-
}, async ({ symptom }) => {
|
|
731
|
-
return {
|
|
732
|
-
messages: [
|
|
733
|
-
{
|
|
734
|
-
role: "user",
|
|
735
|
-
content: {
|
|
736
|
-
type: "text",
|
|
737
|
-
text: [
|
|
738
|
-
"\u8BF7\u57FA\u4E8E wevu runtime \u4EE3\u7801\u8DEF\u5F84\u8FDB\u884C\u5206\u5C42\u6392\u67E5\uFF1A",
|
|
739
|
-
"1. \u590D\u73B0\u573A\u666F\u4E0E\u6700\u5C0F\u6837\u4F8B",
|
|
740
|
-
"2. \u751F\u547D\u5468\u671F\u94A9\u5B50\u89E6\u53D1\u94FE",
|
|
741
|
-
"3. \u54CD\u5E94\u5F0F\u4E0E setData \u5DEE\u91CF\u540C\u6B65\u94FE",
|
|
742
|
-
"4. \u5355\u6D4B\u4E0E e2e \u56DE\u5F52\u8865\u4E01",
|
|
743
|
-
`\u73B0\u8C61\uFF1A${symptom}`
|
|
744
|
-
].join("\n")
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
]
|
|
748
|
-
};
|
|
1910
|
+
registerServerTools(server, {
|
|
1911
|
+
workspaceRoot,
|
|
1912
|
+
packageIds,
|
|
1913
|
+
packageIdSchema
|
|
749
1914
|
});
|
|
750
|
-
server
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
mimeType: "application/json"
|
|
754
|
-
}, async () => {
|
|
755
|
-
const catalog2 = await loadExposedCatalog(workspaceRoot);
|
|
756
|
-
const text = JSON.stringify({ workspaceRoot, packages: catalog2 }, null, 2);
|
|
757
|
-
return {
|
|
758
|
-
contents: [{
|
|
759
|
-
uri: "weapp-vite://workspace/catalog",
|
|
760
|
-
mimeType: "application/json",
|
|
761
|
-
text
|
|
762
|
-
}]
|
|
763
|
-
};
|
|
1915
|
+
registerRuntimeTools(server, {
|
|
1916
|
+
runtimeHooks: options?.runtimeHooks,
|
|
1917
|
+
workspaceRoot
|
|
764
1918
|
});
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
const uri = toDocsUri(summary.id, "README.md");
|
|
769
|
-
server.registerResource(`docs-${summary.id}-readme`, uri, {
|
|
770
|
-
title: `${summary.id} README`,
|
|
771
|
-
mimeType: "text/markdown"
|
|
772
|
-
}, async () => {
|
|
773
|
-
const text = await readTextFile(summary.docs.readme);
|
|
774
|
-
return {
|
|
775
|
-
contents: [{ uri, mimeType: "text/markdown", text }]
|
|
776
|
-
};
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
if (summary.docs.changelog) {
|
|
780
|
-
const uri = toDocsUri(summary.id, "CHANGELOG.md");
|
|
781
|
-
server.registerResource(`docs-${summary.id}-changelog`, uri, {
|
|
782
|
-
title: `${summary.id} CHANGELOG`,
|
|
783
|
-
mimeType: "text/markdown"
|
|
784
|
-
}, async () => {
|
|
785
|
-
const text = await readTextFile(summary.docs.changelog);
|
|
786
|
-
return {
|
|
787
|
-
contents: [{ uri, mimeType: "text/markdown", text }]
|
|
788
|
-
};
|
|
789
|
-
});
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
const sourceTemplate = new ResourceTemplate("weapp-vite://source/{package}?path={path}", {
|
|
793
|
-
list: void 0,
|
|
794
|
-
complete: {
|
|
795
|
-
package: () => packageIds
|
|
796
|
-
}
|
|
1919
|
+
registerServerPrompts(server, {
|
|
1920
|
+
packageIds,
|
|
1921
|
+
packageIdSchema
|
|
797
1922
|
});
|
|
798
|
-
server
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
mimeType: "text/plain"
|
|
802
|
-
}, async (uri, variables) => {
|
|
803
|
-
try {
|
|
804
|
-
const packageId = String(variables.package ?? "");
|
|
805
|
-
if (!packageIds.includes(packageId)) {
|
|
806
|
-
throw new Error(`\u672A\u77E5 package\uFF1A${packageId}`);
|
|
807
|
-
}
|
|
808
|
-
const relativePath = decodeURIComponent(String(variables.path ?? ""));
|
|
809
|
-
const packageRoot = await resolvePackageRoot(workspaceRoot, packageId);
|
|
810
|
-
const { content } = await readFileContent(packageRoot, relativePath, {
|
|
811
|
-
maxChars: DEFAULT_MAX_FILE_CHARS
|
|
812
|
-
});
|
|
813
|
-
return {
|
|
814
|
-
contents: [{
|
|
815
|
-
uri: uri.toString(),
|
|
816
|
-
mimeType: "text/plain",
|
|
817
|
-
text: content
|
|
818
|
-
}]
|
|
819
|
-
};
|
|
820
|
-
} catch (error) {
|
|
821
|
-
return {
|
|
822
|
-
contents: [{
|
|
823
|
-
uri: uri.toString(),
|
|
824
|
-
mimeType: "text/plain",
|
|
825
|
-
text: `[resource-error] ${normalizeErrorMessage(error)}`
|
|
826
|
-
}]
|
|
827
|
-
};
|
|
828
|
-
}
|
|
1923
|
+
await registerServerResources(server, {
|
|
1924
|
+
workspaceRoot,
|
|
1925
|
+
packageIds
|
|
829
1926
|
});
|
|
830
1927
|
return {
|
|
831
1928
|
server,
|
|
@@ -874,7 +1971,7 @@ function writeJson(res, statusCode, payload) {
|
|
|
874
1971
|
res.setHeader("content-type", "application/json");
|
|
875
1972
|
res.end(JSON.stringify(payload));
|
|
876
1973
|
}
|
|
877
|
-
async function startStdioServer
|
|
1974
|
+
async function startStdioServer(options) {
|
|
878
1975
|
const previousCwd = process.cwd();
|
|
879
1976
|
if (options?.workspaceRoot) {
|
|
880
1977
|
process.chdir(options.workspaceRoot);
|
|
@@ -895,13 +1992,14 @@ async function startStreamableHttpServer(options) {
|
|
|
895
1992
|
host = DEFAULT_MCP_HOST,
|
|
896
1993
|
port = DEFAULT_MCP_PORT,
|
|
897
1994
|
workspaceRoot,
|
|
1995
|
+
runtimeHooks,
|
|
898
1996
|
unref = false,
|
|
899
1997
|
quiet = false,
|
|
900
1998
|
onReady
|
|
901
1999
|
} = options;
|
|
902
2000
|
const normalizedEndpoint = normalizeEndpoint(endpoint);
|
|
903
2001
|
const normalizedPort = normalizePort(port);
|
|
904
|
-
const { server: mcpServer } = await createWeappViteMcpServer({ workspaceRoot });
|
|
2002
|
+
const { server: mcpServer } = await createWeappViteMcpServer({ runtimeHooks, workspaceRoot });
|
|
905
2003
|
const transport = new StreamableHTTPServerTransport({
|
|
906
2004
|
sessionIdGenerator: void 0
|
|
907
2005
|
});
|
|
@@ -979,7 +2077,7 @@ async function startWeappViteMcpServer(options) {
|
|
|
979
2077
|
if (transport === "streamable-http") {
|
|
980
2078
|
return startStreamableHttpServer(options ?? {});
|
|
981
2079
|
}
|
|
982
|
-
await startStdioServer
|
|
2080
|
+
await startStdioServer(options);
|
|
983
2081
|
return {
|
|
984
2082
|
transport: "stdio"
|
|
985
2083
|
};
|
|
@@ -1002,4 +2100,4 @@ ${message}
|
|
|
1002
2100
|
});
|
|
1003
2101
|
}
|
|
1004
2102
|
|
|
1005
|
-
export { DEFAULT_MAX_FILE_CHARS, DEFAULT_MAX_OUTPUT_CHARS, DEFAULT_MAX_RESULTS, DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_TIMEOUT_MS, EXPOSED_PACKAGES, MCP_SERVER_NAME, MCP_SERVER_VERSION, SKIPPED_DIR_NAMES, assertInsideRoot, createWeappViteMcpServer, formatJson, listFilesInDirectory, loadExposedCatalog, loadPackageSummary, normalizeErrorMessage, readFileContent, resolveSubPath, resolveWorkspaceRoot, runCommand, searchTextInDirectory, startStdioServer
|
|
2103
|
+
export { DEFAULT_MAX_FILE_CHARS, DEFAULT_MAX_OUTPUT_CHARS, DEFAULT_MAX_RESULTS, DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_TIMEOUT_MS, EXPOSED_PACKAGES, MCP_SERVER_NAME, MCP_SERVER_VERSION, SKIPPED_DIR_NAMES, assertInsideRoot, createWeappViteMcpServer, formatJson, listFilesInDirectory, loadExposedCatalog, loadPackageSummary, normalizeErrorMessage, readFileContent, resolveSubPath, resolveWorkspaceRoot, runCommand, searchTextInDirectory, startStdioServer, startWeappViteMcpServer, toToolError, toToolResult };
|