weapp-vite 7.4.0 → 7.5.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.
Files changed (92) hide show
  1. package/README.md +51 -1
  2. package/bin/bootstrap.js +14 -1
  3. package/dist/adapters-CcHrsYaj.mjs +1 -0
  4. package/dist/analyze-ZJUvEdaY.mjs +248 -0
  5. package/dist/auto-import-components/resolvers.mjs +1 -2
  6. package/dist/auto-import-presets/wevu-router.mjs +1 -2
  7. package/dist/auto-import-presets/wevu.mjs +1 -2
  8. package/dist/auto-routes.mjs +2 -1
  9. package/dist/budget-BD7VqLCl.d.mts +178 -0
  10. package/dist/chunkStrategy-DRA5WpB-.mjs +1436 -0
  11. package/dist/cli-acceptance.d.mts +1 -0
  12. package/dist/cli-acceptance.mjs +21 -0
  13. package/dist/cli.mjs +1420 -1554
  14. package/dist/compatibility.mjs +1 -2
  15. package/dist/{config-Dbvj5yK7.d.mts → config-V0L-IAJf.d.mts} +87 -30
  16. package/dist/config.d.mts +2 -2
  17. package/dist/config.mjs +1 -1
  18. package/dist/{constants-WOsG3Eqd.mjs → constants-DEZdcsMn.mjs} +1 -1
  19. package/dist/{createContext-UOEgeYnA.mjs → createCompilerContextInstance-DJH_P_nZ.mjs} +31278 -32148
  20. package/dist/createContext-BqYzHhY9.mjs +12 -0
  21. package/dist/dashboard/analyze.d.mts +48 -0
  22. package/dist/dashboard/analyze.mjs +1 -0
  23. package/dist/dashboard/vite.d.mts +1 -1
  24. package/dist/dashboard-DvqF3Key.mjs +1842 -0
  25. package/dist/dashboard.d.mts +3 -2
  26. package/dist/dashboard.mjs +1 -2
  27. package/dist/dashboardViteBridge-Dy3nAD4m.mjs +299 -0
  28. package/dist/dev-fR5GiJRO.mjs +63 -0
  29. package/dist/devProvider-BGBkw28J.mjs +1050 -0
  30. package/dist/docs/README.md +51 -1
  31. package/dist/docs/ai-workflows.md +4 -0
  32. package/dist/docs/doctor.md +38 -0
  33. package/dist/docs/getting-started.md +3 -1
  34. package/dist/docs/index.md +3 -1
  35. package/dist/docs/mcp.md +94 -1
  36. package/dist/docs/testing.md +29 -2
  37. package/dist/docs/troubleshooting.md +8 -0
  38. package/dist/docs/uni-app-component-libraries.md +8 -7
  39. package/dist/docs/upload.md +40 -3
  40. package/dist/docs/vite-plugin.md +171 -0
  41. package/dist/docs/vue-sfc.md +19 -0
  42. package/dist/docs/weapp-config.md +54 -0
  43. package/dist/docs/wevu-authoring.md +10 -0
  44. package/dist/doctor-worker.d.mts +1 -0
  45. package/dist/doctor-worker.mjs +59 -0
  46. package/dist/doctor.d.mts +144 -0
  47. package/dist/doctor.mjs +848 -0
  48. package/dist/eslint.mjs +1 -2
  49. package/dist/file-DRb4eWqw.mjs +1 -0
  50. package/dist/{file-giE9UMZa.mjs → file-sC3jD7Fh.mjs} +15 -9
  51. package/dist/files-BqxFIPRp.mjs +45 -0
  52. package/dist/getInstance-DiGSzBNI.mjs +28 -0
  53. package/dist/getInstance-SiE6WZRh.mjs +1 -0
  54. package/dist/index-C9HjUX5c.d.mts +741 -0
  55. package/dist/index.d.mts +10 -8
  56. package/dist/index.mjs +3 -2
  57. package/dist/json.d.mts +1 -1
  58. package/dist/json.mjs +1 -2
  59. package/dist/lifecycle-BROTlwSL.mjs +320 -0
  60. package/dist/loadConfig-C3BQhz7F.mjs +59 -0
  61. package/dist/loadConfig-VGtBF4qm.mjs +1 -0
  62. package/dist/logger-DGn5iEVN.mjs +1 -0
  63. package/dist/{mcp-BG6TliEg.mjs → mcp-Cj8Maqo6.mjs} +16 -7
  64. package/dist/mcp-D3Yh24Cj.mjs +529 -0
  65. package/dist/mcp.d.mts +6 -3
  66. package/dist/mcp.mjs +1 -2
  67. package/dist/package-7swhyLmf.mjs +91 -0
  68. package/dist/path-doV773b7.mjs +103 -0
  69. package/dist/{platform-DTWs5QRi.mjs → platform-CnkySBKz.mjs} +1 -1
  70. package/dist/processCleanup-B6KA30Zc.mjs +77 -0
  71. package/dist/protocol-vg8HGJ4n.mjs +138 -0
  72. package/dist/{resolvers-icNxkpcy.mjs → resolvers-Dod-euqX.mjs} +4 -1
  73. package/dist/resolvers.mjs +1 -2
  74. package/dist/runtime.mjs +1 -2
  75. package/dist/session-PskhD-nZ.mjs +390 -0
  76. package/dist/test.d.mts +1 -0
  77. package/dist/test.mjs +201 -44
  78. package/dist/types.d.mts +2 -2
  79. package/dist/{upload-D0RcEWrq.mjs → upload-D4msblBf.mjs} +174 -15
  80. package/dist/upload-worker.mjs +136 -3
  81. package/dist/utils-CJSCgEj6.mjs +1094 -0
  82. package/dist/vite.d.mts +9 -0
  83. package/dist/vite.mjs +270 -0
  84. package/dist/volar.d.mts +2 -2
  85. package/dist/web-apis.mjs +1 -2
  86. package/package.json +67 -41
  87. package/dist/adapters-BwnMMIZR.mjs +0 -2
  88. package/dist/dashboard-BzaVesmQ.mjs +0 -558
  89. package/dist/file-D19nbDoN.mjs +0 -2
  90. package/dist/getInstance-CYF1vl5l.mjs +0 -2
  91. package/dist/index-DbqVupg0.d.mts +0 -246
  92. package/dist/logger-mt4mSTqV.mjs +0 -2
@@ -0,0 +1,529 @@
1
+ import { r as logger_default } from "./logger-DGn5iEVN.mjs";
2
+ import { c as startWeappViteMcpServer, s as resolveWeappMcpConfig } from "./mcp-Cj8Maqo6.mjs";
3
+ import process from "node:process";
4
+ import path from "pathe";
5
+ import path$1 from "node:path";
6
+ import { fs } from "@weapp-core/shared/fs";
7
+ import { writeFile } from "node:fs/promises";
8
+ import os from "node:os";
9
+ import { runWithSuspendedSharedInput } from "weapp-ide-cli";
10
+ import { createInterface } from "node:readline/promises";
11
+ import { clearTimeout, setTimeout as setTimeout$1 } from "node:timers";
12
+ //#region src/cli/commands/accept.ts
13
+ function registerAcceptCommand(cli) {
14
+ cli.command("accept [root]", "run deterministic mini-program acceptance without a model").option("--init", "create acceptance configuration without overwriting").option("--inspect", "inspect acceptance prerequisites without executing project code").option("--report <jobId>", "read a saved report and check source freshness").option("--acceptance-config <file>", "select an acceptance JSON configuration").option("--trust", "authorize the reviewed configuration for this invocation").option("--json", "write protocol data only to stdout").action(async (root = ".", options) => {
15
+ try {
16
+ const directory = path$1.resolve(root);
17
+ const { defaultVerification, detectProject, safePath } = await import("@weapp-vite/acceptance");
18
+ if (options.init) {
19
+ const target = await safePath(directory, options.acceptanceConfig ?? "weapp-acceptance.config.json");
20
+ const config = {
21
+ version: 1,
22
+ verification: defaultVerification(await detectProject(directory)),
23
+ acceptance: {
24
+ requiredChecks: ["build", "devtools"],
25
+ scenarios: [],
26
+ timeoutMs: 6e5
27
+ }
28
+ };
29
+ await writeFile(target, `${JSON.stringify(config, null, 2)}\n`, { flag: "wx" });
30
+ process.stdout.write(`${JSON.stringify({
31
+ created: target,
32
+ modelRequired: false
33
+ })}\n`);
34
+ return;
35
+ }
36
+ const { createRuntimeAcceptanceService } = await import("@weapp-vite/mcp");
37
+ const { connectMiniProgram, prepareAcceptanceProject, resolveAutomatorSessionOptions } = await import("weapp-ide-cli");
38
+ const service = await createRuntimeAcceptanceService(directory, {
39
+ trust: Boolean(options.trust && !options.inspect && !options.report),
40
+ configFile: options.acceptanceConfig
41
+ }, {
42
+ connectMiniProgram,
43
+ resolveSessionOptions: resolveAutomatorSessionOptions,
44
+ prepareProject: prepareAcceptanceProject
45
+ });
46
+ let jobId;
47
+ let cancelRequested = false;
48
+ const cancel = () => {
49
+ cancelRequested = true;
50
+ if (jobId) service.cancel(jobId);
51
+ };
52
+ process.once("SIGINT", cancel);
53
+ try {
54
+ let result;
55
+ if (options.inspect) result = await service.inspect();
56
+ else if (options.report) result = await service.report(options.report);
57
+ else {
58
+ let report = await service.start();
59
+ jobId = report.jobId;
60
+ if (cancelRequested) await service.cancel(jobId);
61
+ while (report.status === "running") {
62
+ await new Promise((resolve) => setTimeout(resolve, 100));
63
+ report = await service.report(jobId);
64
+ }
65
+ result = report;
66
+ }
67
+ process.stdout.write(`${JSON.stringify(result, null, options.json ? void 0 : 2)}\n`);
68
+ if ("passed" in result && (!result.passed || result.snapshot.stale)) process.exitCode = 1;
69
+ } finally {
70
+ process.off("SIGINT", cancel);
71
+ await service.close();
72
+ }
73
+ } catch (error) {
74
+ const message = error instanceof Error ? error.message : String(error);
75
+ if (options.json) process.stdout.write(`${JSON.stringify({
76
+ status: "failed",
77
+ passed: false,
78
+ reason: message
79
+ })}\n`);
80
+ else process.stderr.write(`${message}\n`);
81
+ process.exitCode = 1;
82
+ }
83
+ });
84
+ }
85
+ //#endregion
86
+ //#region src/cli/options.ts
87
+ function filterDuplicateOptions(options) {
88
+ for (const [key, value] of Object.entries(options)) if (Array.isArray(value)) options[key] = value[value.length - 1];
89
+ }
90
+ function resolveConfigFile(options) {
91
+ if (typeof options.config === "string") return options.config;
92
+ if (typeof options.c === "string") return options.c;
93
+ }
94
+ function convertBase(value) {
95
+ if (value === 0) return "";
96
+ return value;
97
+ }
98
+ function coerceBooleanOption(value) {
99
+ if (value === void 0) return;
100
+ if (typeof value === "boolean") return value;
101
+ if (typeof value === "string") {
102
+ const normalized = value.trim().toLowerCase();
103
+ if (normalized === "") return true;
104
+ if (normalized === "false" || normalized === "0" || normalized === "off" || normalized === "no") return false;
105
+ if (normalized === "true" || normalized === "1" || normalized === "on" || normalized === "yes") return true;
106
+ return true;
107
+ }
108
+ if (typeof value === "number") return value !== 0;
109
+ return Boolean(value);
110
+ }
111
+ function parseDashboardUiHost(value) {
112
+ if (value === void 0 || value === "standalone" || value === "hub") return value;
113
+ throw new Error(`不支持的 --ui-host 值:${String(value)}(仅支持 standalone 或 hub)`);
114
+ }
115
+ function isUiEnabled(options) {
116
+ return Boolean(options.ui || options.analyze || options.uiHost !== void 0);
117
+ }
118
+ //#endregion
119
+ //#region src/cli/mcpClient/shared.ts
120
+ const CODEX_BLOCK_PREFIX = "# >>> weapp-vite mcp ";
121
+ const CODEX_BLOCK_SUFFIX = " >>>";
122
+ const CODEX_BLOCK_END_PREFIX = "# <<< weapp-vite mcp ";
123
+ const CODEX_BLOCK_END_SUFFIX = " <<<";
124
+ const DEFAULT_HTTP_TIMEOUT_MS = 1500;
125
+ const WORKSPACE_FOLDER_TOKEN = "${workspaceFolder}";
126
+ const REG_CodexUrl = /^\s*url\s*=\s*"([^"]+)"/m;
127
+ const REG_CodexCommand = /^\s*command\s*=\s*"([^"]+)"/m;
128
+ const REG_CodexArgs = /^\s*args\s*=\s*\[([^\]]*)\]/m;
129
+ const REG_FirstTomlString = /"([^"]+)"/;
130
+ function resolveTargetWorkspaceRoot(target) {
131
+ if (target.client === "cursor") return path.dirname(path.dirname(target.configPath));
132
+ if (target.client === "claude-code") return path.dirname(target.configPath);
133
+ return process.cwd();
134
+ }
135
+ function escapeRegExp(value) {
136
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
137
+ }
138
+ function renderTomlString(value) {
139
+ return JSON.stringify(value);
140
+ }
141
+ function sanitizeServerNameSegment(value) {
142
+ return value.trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-{2,}/g, "-").replace(/^-|-$/g, "");
143
+ }
144
+ function resolveServerName(workspaceRoot) {
145
+ return `weapp-vite-${sanitizeServerNameSegment(path.basename(workspaceRoot)) || "project"}`;
146
+ }
147
+ function resolveNodeBinCommand() {
148
+ return process.execPath || "node";
149
+ }
150
+ function resolveProjectCliBin(workspaceRoot) {
151
+ return path.join(workspaceRoot, "node_modules", "weapp-vite", "bin", "weapp-vite.js");
152
+ }
153
+ function renderCommandArgs(args) {
154
+ return args.map(renderTomlString).join(", ");
155
+ }
156
+ function renderCodexBlock(serverName, entry) {
157
+ const startMarker = `${CODEX_BLOCK_PREFIX}${serverName}${CODEX_BLOCK_SUFFIX}`;
158
+ const endMarker = `${CODEX_BLOCK_END_PREFIX}${serverName}${CODEX_BLOCK_END_SUFFIX}`;
159
+ if (entry.url) return `${startMarker}
160
+ [mcp_servers.${serverName}]
161
+ url = ${renderTomlString(entry.url)}
162
+ ${endMarker}
163
+ `;
164
+ return `${startMarker}
165
+ [mcp_servers.${serverName}]
166
+ command = ${renderTomlString(entry.command ?? resolveNodeBinCommand())}
167
+ args = [${renderCommandArgs(entry.args ?? [])}]
168
+ ${endMarker}
169
+ `;
170
+ }
171
+ function renderJsonPreview(serverName, entry) {
172
+ return `${JSON.stringify({ mcpServers: { [serverName]: entry } }, null, 2)}
173
+ `;
174
+ }
175
+ function resolveCommandEntry(client, workspaceRoot) {
176
+ const binPath = resolveProjectCliBin(workspaceRoot);
177
+ if (client === "cursor") return {
178
+ command: "node",
179
+ args: [
180
+ `${WORKSPACE_FOLDER_TOKEN}/node_modules/weapp-vite/bin/weapp-vite.js`,
181
+ "mcp",
182
+ "--workspace-root",
183
+ WORKSPACE_FOLDER_TOKEN
184
+ ]
185
+ };
186
+ return {
187
+ command: resolveNodeBinCommand(),
188
+ args: [
189
+ binPath,
190
+ "mcp",
191
+ "--workspace-root",
192
+ workspaceRoot
193
+ ]
194
+ };
195
+ }
196
+ function resolveHttpEntry(client, url) {
197
+ if (client === "claude-code") return {
198
+ type: "http",
199
+ url
200
+ };
201
+ return { url };
202
+ }
203
+ function resolveConfigEntry(client, transport, workspaceRoot, url) {
204
+ return transport === "http" ? resolveHttpEntry(client, url ?? "") : resolveCommandEntry(client, workspaceRoot);
205
+ }
206
+ function resolveCodexBlockPattern(serverName) {
207
+ const startMarker = `${CODEX_BLOCK_PREFIX}${serverName}${CODEX_BLOCK_SUFFIX}`;
208
+ const endMarker = `${CODEX_BLOCK_END_PREFIX}${serverName}${CODEX_BLOCK_END_SUFFIX}`;
209
+ return new RegExp(`${escapeRegExp(startMarker)}[\\s\\S]*?${escapeRegExp(endMarker)}\\n?`, "g");
210
+ }
211
+ function upsertCodexManagedBlock(content, serverName, block) {
212
+ const withoutExisting = content.trimEnd().replace(resolveCodexBlockPattern(serverName), "").trimEnd();
213
+ if (!withoutExisting) return block;
214
+ return `${withoutExisting}\n\n${block}`;
215
+ }
216
+ function parseJsonConfig(content, configPath) {
217
+ if (!content.trim()) return {};
218
+ try {
219
+ return JSON.parse(content);
220
+ } catch (error) {
221
+ const message = error instanceof Error ? error.message : String(error);
222
+ throw new Error(`无法解析 MCP 配置文件 ${configPath}:${message}`);
223
+ }
224
+ }
225
+ function resolveTarget(client, workspaceRoot) {
226
+ const serverName = resolveServerName(workspaceRoot);
227
+ if (client === "codex") return {
228
+ client,
229
+ configPath: path.join(os.homedir(), ".codex", "config.toml"),
230
+ displayName: "Codex",
231
+ serverName
232
+ };
233
+ if (client === "claude-code") return {
234
+ client,
235
+ configPath: path.join(workspaceRoot, ".mcp.json"),
236
+ displayName: "Claude Code",
237
+ serverName
238
+ };
239
+ return {
240
+ client,
241
+ configPath: path.join(workspaceRoot, ".cursor", "mcp.json"),
242
+ displayName: "Cursor",
243
+ serverName
244
+ };
245
+ }
246
+ //#endregion
247
+ //#region src/cli/mcpClient/inspect.ts
248
+ async function probeHttpEndpoint(url) {
249
+ const controller = new AbortController();
250
+ const timer = setTimeout$1(() => {
251
+ controller.abort();
252
+ }, DEFAULT_HTTP_TIMEOUT_MS);
253
+ try {
254
+ return (await fetch(url, {
255
+ method: "GET",
256
+ signal: controller.signal
257
+ })).status > 0;
258
+ } catch {
259
+ return false;
260
+ } finally {
261
+ clearTimeout(timer);
262
+ controller.abort();
263
+ }
264
+ }
265
+ async function inspectJsonConfig(target) {
266
+ if (!await fs.pathExists(target.configPath)) return {
267
+ configExists: false,
268
+ configPath: target.configPath,
269
+ displayName: target.displayName,
270
+ issues: [`未找到配置文件:${target.configPath}`],
271
+ serverName: target.serverName
272
+ };
273
+ const entry = parseJsonConfig(await fs.readFile(target.configPath, "utf8"), target.configPath).mcpServers?.[target.serverName];
274
+ if (!entry) return {
275
+ configExists: true,
276
+ configPath: target.configPath,
277
+ displayName: target.displayName,
278
+ issues: [`配置文件中未找到服务器 ${target.serverName}`],
279
+ serverName: target.serverName
280
+ };
281
+ const transport = entry.url ? "http" : "command";
282
+ const issues = [];
283
+ let httpReachable;
284
+ if (transport === "command") {
285
+ const normalizedBin = (entry.args?.[0])?.replaceAll(WORKSPACE_FOLDER_TOKEN, resolveTargetWorkspaceRoot(target));
286
+ if (!normalizedBin || !await fs.pathExists(normalizedBin)) issues.push(`未找到本地 CLI 入口:${normalizedBin ?? "缺少 args[0]"}`);
287
+ } else if (entry.url) {
288
+ httpReachable = await probeHttpEndpoint(entry.url);
289
+ if (!httpReachable) issues.push(`HTTP MCP 地址不可达:${entry.url}`);
290
+ }
291
+ return {
292
+ configExists: true,
293
+ configPath: target.configPath,
294
+ displayName: target.displayName,
295
+ httpReachable,
296
+ issues,
297
+ serverName: target.serverName,
298
+ transport
299
+ };
300
+ }
301
+ async function inspectCodexConfig(target) {
302
+ if (!await fs.pathExists(target.configPath)) return {
303
+ configExists: false,
304
+ configPath: target.configPath,
305
+ displayName: target.displayName,
306
+ issues: [`未找到配置文件:${target.configPath}`],
307
+ serverName: target.serverName
308
+ };
309
+ const blockMatch = (await fs.readFile(target.configPath, "utf8")).match(resolveCodexBlockPattern(target.serverName));
310
+ if (!blockMatch?.[0]) return {
311
+ configExists: true,
312
+ configPath: target.configPath,
313
+ displayName: target.displayName,
314
+ issues: [`未找到 weapp-vite 生成的 Codex 配置区块:${target.serverName}`],
315
+ serverName: target.serverName
316
+ };
317
+ const block = blockMatch[0];
318
+ const issues = [];
319
+ const urlMatch = block.match(REG_CodexUrl);
320
+ const commandMatch = block.match(REG_CodexCommand);
321
+ const argsMatch = block.match(REG_CodexArgs);
322
+ if (urlMatch?.[1]) {
323
+ const reachable = await probeHttpEndpoint(urlMatch[1]);
324
+ if (!reachable) issues.push(`HTTP MCP 地址不可达:${urlMatch[1]}`);
325
+ return {
326
+ configExists: true,
327
+ configPath: target.configPath,
328
+ displayName: target.displayName,
329
+ httpReachable: reachable,
330
+ issues,
331
+ serverName: target.serverName,
332
+ transport: "http"
333
+ };
334
+ }
335
+ const binPath = (argsMatch?.[1]?.match(REG_FirstTomlString))?.[1];
336
+ if (!commandMatch?.[1]) issues.push("Codex 配置区块缺少 command 字段");
337
+ if (!binPath || !await fs.pathExists(binPath)) issues.push(`未找到本地 CLI 入口:${binPath ?? "缺少 args[0]"}`);
338
+ return {
339
+ configExists: true,
340
+ configPath: target.configPath,
341
+ displayName: target.displayName,
342
+ issues,
343
+ serverName: target.serverName,
344
+ transport: "command"
345
+ };
346
+ }
347
+ async function inspectMcpClientConfig(options) {
348
+ const target = resolveTarget(options.client, path.resolve(options.workspaceRoot));
349
+ if (target.client === "codex") return await inspectCodexConfig(target);
350
+ return await inspectJsonConfig(target);
351
+ }
352
+ //#endregion
353
+ //#region src/cli/mcpClient/plan.ts
354
+ function resolveSupportedMcpClient(input) {
355
+ if (input === "codex" || input === "claude-code" || input === "cursor") return input;
356
+ throw new Error(`不支持的 MCP 客户端:${input}。当前仅支持 codex、claude-code、cursor。`);
357
+ }
358
+ function buildMcpClientConfigPlan(options) {
359
+ const workspaceRoot = path.resolve(options.workspaceRoot);
360
+ const target = resolveTarget(options.client, workspaceRoot);
361
+ const entry = resolveConfigEntry(options.client, options.transport, workspaceRoot, options.url);
362
+ if (options.transport === "http" && !entry.url) throw new Error("HTTP 模式缺少 MCP 服务地址,请使用 --url 指定或在当前项目中检测到可用地址。");
363
+ return {
364
+ entry,
365
+ preview: target.client === "codex" ? renderCodexBlock(target.serverName, entry) : renderJsonPreview(target.serverName, entry),
366
+ target,
367
+ transport: options.transport
368
+ };
369
+ }
370
+ function formatMcpQuickStart(options) {
371
+ const suffix = options.transport === "http" && options.httpUrl ? ` --transport http --url ${options.httpUrl}` : "";
372
+ return [
373
+ "在 AI 工具中接入 weapp-vite MCP:",
374
+ ` - Codex: wv mcp init codex${suffix}`,
375
+ ` - Claude Code: wv mcp init claude-code${suffix}`,
376
+ ` - Cursor: wv mcp init cursor${suffix}`
377
+ ];
378
+ }
379
+ //#endregion
380
+ //#region src/cli/mcpClient/index.ts
381
+ async function writeMcpClientConfig(plan) {
382
+ await fs.ensureDir(path.dirname(plan.target.configPath));
383
+ const existing = await fs.readFile(plan.target.configPath, "utf8").catch(() => "");
384
+ if (plan.target.client === "codex") {
385
+ const nextContent = upsertCodexManagedBlock(existing, plan.target.serverName, plan.preview);
386
+ await fs.writeFile(plan.target.configPath, nextContent, "utf8");
387
+ return;
388
+ }
389
+ const parsed = parseJsonConfig(existing, plan.target.configPath);
390
+ const nextConfig = {
391
+ ...parsed,
392
+ mcpServers: {
393
+ ...parsed.mcpServers ?? {},
394
+ [plan.target.serverName]: plan.entry
395
+ }
396
+ };
397
+ await fs.writeFile(plan.target.configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
398
+ }
399
+ //#endregion
400
+ //#region src/cli/commands/mcp.ts
401
+ function resolvePort(port) {
402
+ if (typeof port === "number" && Number.isInteger(port)) return port;
403
+ if (typeof port === "string" && port.trim()) {
404
+ const parsed = Number.parseInt(port, 10);
405
+ if (Number.isInteger(parsed)) return parsed;
406
+ }
407
+ }
408
+ async function resolveHttpUrl(options) {
409
+ if (options.url?.trim()) return options.url.trim();
410
+ const workspaceRoot = options.workspaceRoot ? path.resolve(options.workspaceRoot) : process.cwd();
411
+ const originalCwd = process.cwd();
412
+ try {
413
+ if (workspaceRoot !== originalCwd) process.chdir(workspaceRoot);
414
+ const configFile = resolveConfigFile(options);
415
+ const { loadConfig } = await import("./loadConfig-VGtBF4qm.mjs");
416
+ const loaded = await loadConfig(configFile);
417
+ const resolved = resolveWeappMcpConfig(loaded?.config?.weapp?.mcp);
418
+ return `http://${resolved.host}:${resolved.port}${resolved.endpoint}`;
419
+ } catch {
420
+ const resolved = resolveWeappMcpConfig(void 0);
421
+ return `http://${resolved.host}:${resolved.port}${resolved.endpoint}`;
422
+ } finally {
423
+ if (process.cwd() !== originalCwd) process.chdir(originalCwd);
424
+ }
425
+ }
426
+ async function confirmWrite() {
427
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
428
+ return await runWithSuspendedSharedInput(async () => {
429
+ const rl = createInterface({
430
+ input: process.stdin,
431
+ output: process.stdout
432
+ });
433
+ try {
434
+ const normalized = (await rl.question("是否写入配置文件?(Y/n) ")).trim().toLowerCase();
435
+ return normalized === "" || normalized === "y" || normalized === "yes";
436
+ } finally {
437
+ rl.close();
438
+ }
439
+ });
440
+ }
441
+ function resolveClientTransport(transport) {
442
+ return transport === "http" ? "http" : "command";
443
+ }
444
+ async function handlePrint(clientName, options, write = false) {
445
+ const client = resolveSupportedMcpClient(clientName);
446
+ const workspaceRoot = options.workspaceRoot ?? process.cwd();
447
+ const transport = resolveClientTransport(options.transport);
448
+ const plan = buildMcpClientConfigPlan({
449
+ client,
450
+ transport,
451
+ url: transport === "http" ? await resolveHttpUrl(options) : void 0,
452
+ workspaceRoot
453
+ });
454
+ logger_default.info(`${plan.target.displayName} 配置文件:${plan.target.configPath}`);
455
+ logger_default.info(`服务器名称:${plan.target.serverName}`);
456
+ process.stdout.write(`${plan.preview}\n`);
457
+ if (!write) return;
458
+ if (options.yes || await confirmWrite()) {
459
+ await writeMcpClientConfig(plan);
460
+ logger_default.success(`已写入 ${plan.target.displayName} MCP 配置。`);
461
+ logger_default.info(`请重启 ${plan.target.displayName},然后执行:wv mcp doctor ${client}`);
462
+ return;
463
+ }
464
+ logger_default.info("已取消写入。");
465
+ }
466
+ async function handleDoctor(clientName, options) {
467
+ const result = await inspectMcpClientConfig({
468
+ client: resolveSupportedMcpClient(clientName),
469
+ workspaceRoot: options.workspaceRoot ?? process.cwd()
470
+ });
471
+ logger_default.info(`${result.displayName} 配置文件:${result.configPath}`);
472
+ logger_default.info(`服务器名称:${result.serverName}`);
473
+ if (!result.configExists || result.issues.length > 0) {
474
+ for (const issue of result.issues) logger_default.warn(issue);
475
+ throw new Error("MCP 客户端配置检查未通过。");
476
+ }
477
+ if (result.transport) logger_default.info(`传输模式:${result.transport}`);
478
+ if (result.httpReachable !== void 0) logger_default.info(`HTTP 服务可达:${result.httpReachable ? "是" : "否"}`);
479
+ logger_default.success("MCP 客户端配置检查通过。");
480
+ }
481
+ async function handleServer(options) {
482
+ const resolvedTransport = options.transport === "http" ? "streamable-http" : options.transport === "command" ? void 0 : options.transport;
483
+ const handle = await startWeappViteMcpServer({
484
+ endpoint: options.endpoint,
485
+ host: options.host,
486
+ port: resolvePort(options.port),
487
+ restEndpoint: options.rest === false ? false : options.restEndpoint,
488
+ transport: resolvedTransport,
489
+ unref: options.unref,
490
+ workspaceRoot: options.workspaceRoot
491
+ });
492
+ const shutdown = async () => {
493
+ process.off("SIGINT", shutdown);
494
+ process.off("SIGTERM", shutdown);
495
+ process.stdin.off("end", shutdown);
496
+ await handle.close?.();
497
+ };
498
+ process.once("SIGINT", shutdown);
499
+ process.once("SIGTERM", shutdown);
500
+ if (resolvedTransport !== "streamable-http") process.stdin.once("end", shutdown);
501
+ for (const line of formatMcpQuickStart({
502
+ httpUrl: resolvedTransport === "streamable-http" ? `http://${options.host ?? "127.0.0.1"}:${resolvePort(options.port) ?? 3088}${options.endpoint ?? "/mcp"}` : void 0,
503
+ transport: resolvedTransport === "streamable-http" ? "http" : "command"
504
+ })) logger_default.info(line);
505
+ }
506
+ function registerMcpCommand(cli) {
507
+ cli.command("mcp [...args]", "start weapp-vite MCP server or manage MCP client onboarding").option("--transport <type>", "[string] stdio | streamable-http | command | http", { default: "stdio" }).option("--host <host>", "[string] streamable-http host").option("--port <port>", "[number] streamable-http port").option("--endpoint <path>", "[string] streamable-http endpoint path").option("--rest-endpoint <path>", "[string] streamable-http REST runtime endpoint path").option("--no-rest", "[boolean] disable streamable-http REST runtime endpoints").option("--unref", "[boolean] unref HTTP server to not block process exit").option("--url <url>", "[string] explicit HTTP MCP url").option("--workspace-root <path>", "[string] workspace root path, defaults to cwd").option("-y, --yes", "[boolean] write config without prompt").action(async (args, options) => {
508
+ const [subcommand, client] = args;
509
+ if (subcommand === "init") {
510
+ if (!client) throw new Error("缺少客户端名称,请使用:wv mcp init <codex|claude-code|cursor>");
511
+ await handlePrint(client, options, true);
512
+ return;
513
+ }
514
+ if (subcommand === "print") {
515
+ if (!client) throw new Error("缺少客户端名称,请使用:wv mcp print <codex|claude-code|cursor>");
516
+ await handlePrint(client, options, false);
517
+ return;
518
+ }
519
+ if (subcommand === "doctor") {
520
+ if (!client) throw new Error("缺少客户端名称,请使用:wv mcp doctor <codex|claude-code|cursor>");
521
+ await handleDoctor(client, options);
522
+ return;
523
+ }
524
+ if (subcommand) throw new Error(`未知的 mcp 子命令:${subcommand}`);
525
+ await handleServer(options);
526
+ });
527
+ }
528
+ //#endregion
529
+ export { filterDuplicateOptions as a, resolveConfigFile as c, convertBase as i, registerAcceptCommand as l, formatMcpQuickStart as n, isUiEnabled as o, coerceBooleanOption as r, parseDashboardUiHost as s, registerMcpCommand as t };
package/dist/mcp.d.mts CHANGED
@@ -1,6 +1,9 @@
1
- import { Wt as WeappMcpConfig } from "./config-Dbvj5yK7.mjs";
2
- import { CreateServerOptions, DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_RUNTIME_REST_ENDPOINT, McpServerHandle, StartMcpServerOptions, createWeappViteMcpServer } from "@weapp-vite/mcp";
1
+ import { Wt as WeappMcpConfig } from "./config-V0L-IAJf.mjs";
2
+ import { DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_RUNTIME_REST_ENDPOINT } from "@weapp-core/constants";
3
+ import { CreateServerOptions, McpServerHandle, StartMcpServerOptions, createWeappViteMcpServer as createWeappViteMcpServer$1 } from "@weapp-vite/mcp";
3
4
  //#region src/mcp.d.ts
5
+ /** 创建服务时才加载 MCP 运行时;配置解析与公开常量保持同步。 */
6
+ export declare function createWeappViteMcpServer(options?: CreateServerOptions): ReturnType<typeof createWeappViteMcpServer$1>;
4
7
  export interface ResolvedWeappMcpConfig {
5
8
  agentName?: string;
6
9
  enabled: boolean;
@@ -22,4 +25,4 @@ export declare function resolveProjectMcpPort(projectRoot?: string): number;
22
25
  export declare function resolveWeappMcpConfig(config?: boolean | WeappMcpConfig, options?: ResolveWeappMcpConfigOptions): ResolvedWeappMcpConfig;
23
26
  export declare function startWeappViteMcpServer(options?: WeappViteMcpServerOptions): Promise<WeappViteMcpServerHandle>;
24
27
  //#endregion
25
- export { type CreateServerOptions, DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_RUNTIME_REST_ENDPOINT, createWeappViteMcpServer };
28
+ export { type CreateServerOptions, DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_RUNTIME_REST_ENDPOINT };
package/dist/mcp.mjs CHANGED
@@ -1,2 +1 @@
1
- import { a as createWeappViteMcpServer, c as startWeappViteMcpServer, i as DEFAULT_RUNTIME_REST_ENDPOINT, n as DEFAULT_MCP_HOST, o as resolveProjectMcpPort, r as DEFAULT_MCP_PORT, s as resolveWeappMcpConfig, t as DEFAULT_MCP_ENDPOINT } from "./mcp-BG6TliEg.mjs";
2
- export { DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_RUNTIME_REST_ENDPOINT, createWeappViteMcpServer, resolveProjectMcpPort, resolveWeappMcpConfig, startWeappViteMcpServer };
1
+ export { t as DEFAULT_MCP_ENDPOINT, n as DEFAULT_MCP_HOST, r as DEFAULT_MCP_PORT, i as DEFAULT_RUNTIME_REST_ENDPOINT, a as createWeappViteMcpServer, o as resolveProjectMcpPort, s as resolveWeappMcpConfig, c as startWeappViteMcpServer } from "./mcp-Cj8Maqo6.mjs";
@@ -0,0 +1,91 @@
1
+ import { t as isPathInside } from "./path-doV773b7.mjs";
2
+ import "./utils-CJSCgEj6.mjs";
3
+ import { i as SHARED_CHUNK_VIRTUAL_PREFIX } from "./chunkStrategy-DRA5WpB-.mjs";
4
+ import { posix } from "pathe";
5
+ //#region src/analyze/subpackages/classifier.ts
6
+ const VIRTUAL_MODULE_INDICATOR = "\0";
7
+ const VIRTUAL_PREFIX = `${SHARED_CHUNK_VIRTUAL_PREFIX}/`;
8
+ function classifyModuleSourceKind(options) {
9
+ if (options.isNodeModule) return "node_modules";
10
+ if (options.inSrc) return "src";
11
+ if (options.inPlugin) return "plugin";
12
+ return "workspace";
13
+ }
14
+ function resolvePluginAssetAbsolute(normalizedFileName, pluginRoot) {
15
+ if (!pluginRoot) return;
16
+ if (posix.isAbsolute(normalizedFileName)) return isPathInside(pluginRoot, normalizedFileName) ? normalizedFileName : void 0;
17
+ const pluginBase = posix.basename(pluginRoot);
18
+ if (normalizedFileName !== pluginBase && !normalizedFileName.startsWith(`${pluginBase}/`)) return;
19
+ const relative = normalizedFileName === pluginBase ? "" : normalizedFileName.slice(pluginBase.length + 1);
20
+ const absolute = posix.resolve(pluginRoot, relative);
21
+ return isPathInside(pluginRoot, absolute) ? absolute : void 0;
22
+ }
23
+ function resolveSubPackageRoot(fileName, context) {
24
+ const normalized = posix.normalize(fileName);
25
+ return Array.from(context.subPackageRoots).filter(Boolean).sort((left, right) => right.length - left.length).find((root) => normalized === root || normalized.startsWith(`${root}/`));
26
+ }
27
+ function classifyPackage(fileName, origin, context) {
28
+ if (fileName.startsWith(VIRTUAL_PREFIX)) {
29
+ const combination = fileName.slice(VIRTUAL_PREFIX.length).split("/")[0] || "shared";
30
+ return {
31
+ id: `virtual:${combination}`,
32
+ label: `共享虚拟包 ${combination}`,
33
+ type: "virtual"
34
+ };
35
+ }
36
+ const rootCandidate = resolveSubPackageRoot(fileName, context);
37
+ if (rootCandidate) {
38
+ const isIndependent = context.independentRoots.has(rootCandidate);
39
+ return {
40
+ id: rootCandidate,
41
+ label: `${isIndependent ? "独立分包" : "分包"} ${rootCandidate}`,
42
+ type: isIndependent || origin === "independent" ? "independent" : "subPackage"
43
+ };
44
+ }
45
+ return {
46
+ id: "__main__",
47
+ label: "主包",
48
+ type: "main"
49
+ };
50
+ }
51
+ function normalizeModuleId(id) {
52
+ if (!id || id.includes(VIRTUAL_MODULE_INDICATOR)) return;
53
+ if (!posix.isAbsolute(id)) return;
54
+ return posix.normalize(id);
55
+ }
56
+ function resolveModuleSourceType(absoluteId, ctx) {
57
+ const { configService } = ctx;
58
+ const isNodeModule = absoluteId.includes("/node_modules/") || absoluteId.includes("\\node_modules\\");
59
+ const pluginRoot = configService.absolutePluginRoot;
60
+ const srcRoot = configService.absoluteSrcRoot;
61
+ const sourceType = classifyModuleSourceKind({
62
+ isNodeModule,
63
+ inSrc: isPathInside(srcRoot, absoluteId),
64
+ inPlugin: pluginRoot ? isPathInside(pluginRoot, absoluteId) : false
65
+ });
66
+ return {
67
+ source: configService.relativeAbsoluteSrcRoot(absoluteId),
68
+ sourceType
69
+ };
70
+ }
71
+ function resolveAssetSource(fileName, ctx) {
72
+ const { configService } = ctx;
73
+ const normalized = posix.normalize(fileName);
74
+ const srcCandidate = posix.isAbsolute(normalized) ? normalized : posix.resolve(configService.absoluteSrcRoot, normalized);
75
+ if (isPathInside(configService.absoluteSrcRoot, srcCandidate)) return {
76
+ absolute: srcCandidate,
77
+ source: configService.relativeAbsoluteSrcRoot(srcCandidate),
78
+ sourceType: "src"
79
+ };
80
+ const pluginAbsolute = resolvePluginAssetAbsolute(normalized, configService.absolutePluginRoot);
81
+ if (pluginAbsolute) return {
82
+ absolute: pluginAbsolute,
83
+ source: configService.relativeAbsoluteSrcRoot(pluginAbsolute),
84
+ sourceType: "plugin"
85
+ };
86
+ }
87
+ //#endregion
88
+ //#region package.json
89
+ var version = "7.5.0";
90
+ //#endregion
91
+ export { resolveModuleSourceType as a, resolveAssetSource as i, classifyPackage as n, normalizeModuleId as r, version as t };