vite-plugin-aipanel 1.2.0-beta.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 (98) hide show
  1. package/README.md +72 -0
  2. package/es/client/vue-devtools-bridge.d.ts +58 -0
  3. package/es/client/vue-devtools-bridge.mjs +150 -0
  4. package/es/core/injector.d.ts +2 -0
  5. package/es/core/injector.mjs +15 -0
  6. package/es/core/mcp-chrome.d.ts +56 -0
  7. package/es/core/mcp-chrome.mjs +133 -0
  8. package/es/core/mcp-proxy.d.ts +23 -0
  9. package/es/core/mcp-proxy.mjs +212 -0
  10. package/es/core/mcp-tools.d.ts +15 -0
  11. package/es/core/mcp-tools.mjs +671 -0
  12. package/es/core/provider-loader.d.ts +19 -0
  13. package/es/core/provider-loader.mjs +30 -0
  14. package/es/core/proxy-server.d.ts +12 -0
  15. package/es/core/proxy-server.mjs +148 -0
  16. package/es/core/service.d.ts +39 -0
  17. package/es/core/service.mjs +267 -0
  18. package/es/endpoints/context.d.ts +3 -0
  19. package/es/endpoints/context.mjs +106 -0
  20. package/es/endpoints/index.d.ts +9 -0
  21. package/es/endpoints/index.mjs +30 -0
  22. package/es/endpoints/logs.d.ts +9 -0
  23. package/es/endpoints/logs.mjs +86 -0
  24. package/es/endpoints/mcp.d.ts +6 -0
  25. package/es/endpoints/mcp.mjs +610 -0
  26. package/es/endpoints/sessions.d.ts +3 -0
  27. package/es/endpoints/sessions.mjs +62 -0
  28. package/es/endpoints/sse.d.ts +3 -0
  29. package/es/endpoints/sse.mjs +44 -0
  30. package/es/endpoints/start.d.ts +3 -0
  31. package/es/endpoints/start.mjs +21 -0
  32. package/es/endpoints/types.d.ts +34 -0
  33. package/es/endpoints/types.mjs +0 -0
  34. package/es/endpoints/vue-devtools.d.ts +9 -0
  35. package/es/endpoints/vue-devtools.mjs +107 -0
  36. package/es/endpoints/warmup.d.ts +3 -0
  37. package/es/endpoints/warmup.mjs +42 -0
  38. package/es/endpoints/widget.d.ts +3 -0
  39. package/es/endpoints/widget.mjs +36 -0
  40. package/es/env.d.ts +1 -0
  41. package/es/index.d.ts +22 -0
  42. package/es/index.mjs +342 -0
  43. package/es/utils/format-bridge.d.ts +9 -0
  44. package/es/utils/format-bridge.mjs +80 -0
  45. package/es/utils/paths.d.ts +3 -0
  46. package/es/utils/paths.mjs +45 -0
  47. package/es/utils/system.d.ts +3 -0
  48. package/es/utils/system.mjs +76 -0
  49. package/lib/client/vue-devtools-bridge.cjs +150 -0
  50. package/lib/client/vue-devtools-bridge.d.ts +58 -0
  51. package/lib/client.css +2 -0
  52. package/lib/client.js +6950 -0
  53. package/lib/core/injector.cjs +34 -0
  54. package/lib/core/injector.d.ts +2 -0
  55. package/lib/core/mcp-chrome.cjs +161 -0
  56. package/lib/core/mcp-chrome.d.ts +56 -0
  57. package/lib/core/mcp-proxy.cjs +244 -0
  58. package/lib/core/mcp-proxy.d.ts +23 -0
  59. package/lib/core/mcp-tools.cjs +694 -0
  60. package/lib/core/mcp-tools.d.ts +15 -0
  61. package/lib/core/provider-loader.cjs +53 -0
  62. package/lib/core/provider-loader.d.ts +19 -0
  63. package/lib/core/proxy-server.cjs +181 -0
  64. package/lib/core/proxy-server.d.ts +12 -0
  65. package/lib/core/service.cjs +289 -0
  66. package/lib/core/service.d.ts +39 -0
  67. package/lib/endpoints/context.cjs +129 -0
  68. package/lib/endpoints/context.d.ts +3 -0
  69. package/lib/endpoints/index.cjs +58 -0
  70. package/lib/endpoints/index.d.ts +9 -0
  71. package/lib/endpoints/logs.cjs +107 -0
  72. package/lib/endpoints/logs.d.ts +9 -0
  73. package/lib/endpoints/mcp.cjs +624 -0
  74. package/lib/endpoints/mcp.d.ts +6 -0
  75. package/lib/endpoints/sessions.cjs +85 -0
  76. package/lib/endpoints/sessions.d.ts +3 -0
  77. package/lib/endpoints/sse.cjs +67 -0
  78. package/lib/endpoints/sse.d.ts +3 -0
  79. package/lib/endpoints/start.cjs +44 -0
  80. package/lib/endpoints/start.d.ts +3 -0
  81. package/lib/endpoints/types.cjs +15 -0
  82. package/lib/endpoints/types.d.ts +34 -0
  83. package/lib/endpoints/vue-devtools.cjs +132 -0
  84. package/lib/endpoints/vue-devtools.d.ts +9 -0
  85. package/lib/endpoints/warmup.cjs +65 -0
  86. package/lib/endpoints/warmup.d.ts +3 -0
  87. package/lib/endpoints/widget.cjs +69 -0
  88. package/lib/endpoints/widget.d.ts +3 -0
  89. package/lib/env.d.ts +1 -0
  90. package/lib/index.cjs +361 -0
  91. package/lib/index.d.ts +22 -0
  92. package/lib/utils/format-bridge.cjs +102 -0
  93. package/lib/utils/format-bridge.d.ts +9 -0
  94. package/lib/utils/paths.cjs +80 -0
  95. package/lib/utils/paths.d.ts +3 -0
  96. package/lib/utils/system.cjs +110 -0
  97. package/lib/utils/system.d.ts +3 -0
  98. package/package.json +68 -0
@@ -0,0 +1,34 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var injector_exports = {};
19
+ __export(injector_exports, {
20
+ injectWidget: () => injectWidget
21
+ });
22
+ module.exports = __toCommonJS(injector_exports);
23
+ var import_core = require("@aipanel/core");
24
+ function injectWidget(options) {
25
+ const configBase64 = Buffer.from(JSON.stringify(options)).toString("base64");
26
+ const scriptTag = `<script type="module" src="${import_core.WIDGET_SCRIPT_PATH}" ${import_core.CONFIG_DATA_ATTR}="${configBase64}"></script>`;
27
+ const styleTag = `<link rel="stylesheet" href="${import_core.WIDGET_STYLE_PATH}" />`;
28
+ return `${styleTag}
29
+ ${scriptTag}`;
30
+ }
31
+ // Annotate the CommonJS export names for ESM import in node:
32
+ 0 && (module.exports = {
33
+ injectWidget
34
+ });
@@ -0,0 +1,2 @@
1
+ import type { WidgetOptions } from "@aipanel/core";
2
+ export declare function injectWidget(options: WidgetOptions): string;
@@ -0,0 +1,161 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var mcp_chrome_exports = {};
19
+ __export(mcp_chrome_exports, {
20
+ extractEvalValue: () => extractEvalValue,
21
+ getProjectOrigins: () => getProjectOrigins,
22
+ isProjectPage: () => isProjectPage,
23
+ parseListPages: () => parseListPages,
24
+ resolveChromePageId: () => resolveChromePageId,
25
+ validatePageId: () => validatePageId
26
+ });
27
+ module.exports = __toCommonJS(mcp_chrome_exports);
28
+ var import_node = require("@aipanel/core/node");
29
+ const log = (0, import_node.createLogger)("McpChrome");
30
+ function getProjectOrigins(server) {
31
+ const local = server.resolvedUrls?.local ?? [];
32
+ const network = server.resolvedUrls?.network ?? [];
33
+ const origins = [...new Set([...local, ...network].map((u) => new URL(u).origin))];
34
+ log.debug("project origins", { origins });
35
+ return origins;
36
+ }
37
+ function isProjectPage(url, origins) {
38
+ return origins.some((origin) => url.startsWith(origin));
39
+ }
40
+ function parseListPages(text) {
41
+ const pages = [];
42
+ for (const line of text.split("\n")) {
43
+ const match = line.match(/^(\d+):\s*(.+?)\s*\((\S+)\)/);
44
+ if (match) {
45
+ pages.push({
46
+ pageId: parseInt(match[1], 10),
47
+ title: match[2].replace(/\s*\.{3}$/, "").trim(),
48
+ url: match[3],
49
+ selected: /\[selected\]/i.test(line)
50
+ });
51
+ }
52
+ }
53
+ return pages;
54
+ }
55
+ function extractEvalValue(text) {
56
+ if (!text) return void 0;
57
+ const marker = "```json\n";
58
+ const startIdx = text.indexOf(marker);
59
+ if (startIdx < 0) return text.trim();
60
+ const contentStart = startIdx + marker.length;
61
+ const endIdx = text.indexOf("\n```", contentStart);
62
+ const jsonStr = endIdx < 0 ? text.substring(contentStart) : text.substring(contentStart, endIdx);
63
+ try {
64
+ return JSON.parse(jsonStr.trim());
65
+ } catch {
66
+ return jsonStr.trim();
67
+ }
68
+ }
69
+ async function validatePageId(mcp, pageId, projectOrigins) {
70
+ const listResult = await mcp.callChromeDevTool("list_pages", {});
71
+ if (listResult?.error || !listResult?.result) {
72
+ return {
73
+ valid: false,
74
+ error: listResult?.error?.message ?? "\u65E0\u6CD5\u83B7\u53D6 Chrome \u9875\u9762\u5217\u8868\uFF0C\u8BF7\u786E\u8BA4 Chrome DevTools \u5DF2\u8FDE\u63A5",
75
+ projectPages: []
76
+ };
77
+ }
78
+ const text = listResult?.result?.content?.[0]?.text;
79
+ const allPages = text ? parseListPages(text) : [];
80
+ const projectPages = allPages.filter((p) => isProjectPage(p.url, projectOrigins));
81
+ const isValid = projectPages.some((p) => p.pageId === pageId);
82
+ if (!isValid) {
83
+ return {
84
+ valid: false,
85
+ error: `pageId ${pageId} \u65E0\u6548\u6216\u975E\u9879\u76EE\u9875\u9762\uFF0C\u8BF7\u83B7\u53D6\u6709\u6548\u9875\u9762 ID`,
86
+ projectPages
87
+ };
88
+ }
89
+ return { valid: true, projectPages };
90
+ }
91
+ async function resolveChromePageId(mcp, url, title, projectOrigins, sessionId, pages, chromeSelectedPageId) {
92
+ if (!mcp || !mcp.isRunning) {
93
+ const reason = !mcp ? "MCP \u6A21\u5757\u672A\u521D\u59CB\u5316" : "Chrome DevTools MCP \u8FDB\u7A0B\u672A\u542F\u52A8";
94
+ log.debug(`resolveChromePageId: ${reason}`);
95
+ return { ok: false, error: reason };
96
+ }
97
+ if (!url) {
98
+ return { ok: false, error: "\u9875\u9762 URL \u4E3A\u7A7A\uFF0C\u5C1A\u672A\u6536\u5230\u4E0A\u4E0B\u6587\u4FE1\u606F" };
99
+ }
100
+ try {
101
+ if (!pages) {
102
+ const listResult = await mcp.callChromeDevTool("list_pages", {});
103
+ const text = listResult?.result?.content?.[0]?.text;
104
+ if (!text) {
105
+ return { ok: false, error: "\u65E0\u6CD5\u83B7\u53D6 Chrome \u9875\u9762\u5217\u8868\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u6253\u5F00\u76EE\u6807\u9875\u9762" };
106
+ }
107
+ const allPages = parseListPages(text);
108
+ chromeSelectedPageId = allPages.find((p) => p.selected)?.pageId;
109
+ pages = allPages.filter((p) => isProjectPage(p.url, projectOrigins));
110
+ }
111
+ log.debug("resolveChromePageId: list_pages result", {
112
+ pages: pages.map((p) => ({ id: p.pageId, url: p.url, title: p.title.substring(0, 40) })),
113
+ target: { url, title }
114
+ });
115
+ if (sessionId) {
116
+ let matchedPageId = null;
117
+ for (const page of pages) {
118
+ await mcp.callChromeDevTool("select_page", { pageId: page.pageId, bringToFront: false });
119
+ const evalResult = await mcp.callChromeDevTool("evaluate_script", {
120
+ function: "() => sessionStorage.getItem('_aipanel_pk')"
121
+ });
122
+ const rawText = evalResult?.result?.content?.[0]?.text;
123
+ const extracted = extractEvalValue(rawText);
124
+ if (extracted === sessionId) {
125
+ matchedPageId = page.pageId;
126
+ break;
127
+ }
128
+ }
129
+ if (chromeSelectedPageId != null && chromeSelectedPageId !== matchedPageId) {
130
+ await mcp.callChromeDevTool("select_page", {
131
+ pageId: chromeSelectedPageId,
132
+ bringToFront: false
133
+ });
134
+ }
135
+ if (matchedPageId != null) {
136
+ return { ok: true, pageId: matchedPageId };
137
+ }
138
+ return {
139
+ ok: false,
140
+ error: `\u672A\u80FD\u901A\u8FC7\u4F1A\u8BDD\u6807\u8BC6\u627E\u5230\u76EE\u6807\u9875\u9762\uFF0C\u8BF7\u786E\u8BA4\u76EE\u6807\u9875\u9762\u5DF2\u6253\u5F00`
141
+ };
142
+ }
143
+ return {
144
+ ok: false,
145
+ error: `\u4E0A\u4E0B\u6587\u7F3A\u5C11\u4F1A\u8BDD\u6807\u8BC6\uFF08_aipanel_pk\uFF09\uFF0C\u65E0\u6CD5\u5B9A\u4F4D\u9875\u9762\uFF0C\u8BF7\u5237\u65B0\u76EE\u6807\u9875\u9762\u540E\u91CD\u8BD5`
146
+ };
147
+ } catch (err) {
148
+ const msg = `MCP \u8C03\u7528\u5931\u8D25: ${err.message}`;
149
+ log.debug("Failed to resolve pageId via MCP", { error: err.message });
150
+ return { ok: false, error: msg };
151
+ }
152
+ }
153
+ // Annotate the CommonJS export names for ESM import in node:
154
+ 0 && (module.exports = {
155
+ extractEvalValue,
156
+ getProjectOrigins,
157
+ isProjectPage,
158
+ parseListPages,
159
+ resolveChromePageId,
160
+ validatePageId
161
+ });
@@ -0,0 +1,56 @@
1
+ /**
2
+ * MCP Chrome 页面相关工具
3
+ *
4
+ * 专注于 Chrome DevTools 页面匹配与解析逻辑
5
+ */
6
+ import type { ViteDevServer } from "vite";
7
+ import type { McpProxy } from "./mcp-proxy";
8
+ /** 从 Vite 服务器解析的所有 URL 中提取项目 origin 列表 */
9
+ export declare function getProjectOrigins(server: ViteDevServer): string[];
10
+ /** 判断页面 URL 是否属于项目的某个 origin */
11
+ export declare function isProjectPage(url: string, origins: string[]): boolean;
12
+ export interface PageInfo {
13
+ pageId: number;
14
+ url: string;
15
+ title: string;
16
+ /** Chrome DevTools 当前选中的页面 */
17
+ selected: boolean;
18
+ }
19
+ /** 解析 list_pages 返回的文本。格式:"56: Title (URL) [selected]" */
20
+ export declare function parseListPages(text: string): PageInfo[];
21
+ /** 从 evaluate_script 返回的格式化文本中提取 JSON 值 */
22
+ export declare function extractEvalValue(text: string | undefined): string | undefined;
23
+ type PageIdResult = {
24
+ ok: true;
25
+ pageId: number;
26
+ } | {
27
+ ok: false;
28
+ error: string;
29
+ };
30
+ /**
31
+ * 校验 pageId 是否属于项目页面
32
+ *
33
+ * 调用 list_pages → 过滤项目页面 → 检查 pageId 是否在范围内。
34
+ * 供 MCP 代理层和 Vue DevTools 端点共用。
35
+ */
36
+ export declare function validatePageId(mcp: McpProxy, pageId: number, projectOrigins: string[]): Promise<{
37
+ valid: true;
38
+ projectPages: PageInfo[];
39
+ } | {
40
+ valid: false;
41
+ error: string;
42
+ projectPages: PageInfo[];
43
+ }>;
44
+ /**
45
+ * 通过 MCP 解析当前页面对应的 Chrome DevTools pageId
46
+ *
47
+ * 策略:
48
+ * 1. list_pages → 解析每行的 "pageId: title (URL)" 格式
49
+ * 2. 仅用 sessionId(_aipanel_pk)匹配,跨导航可靠;不做 URL 降级匹配
50
+ *
51
+ * 失败时返回具体原因,由调用方透传给 Agent。
52
+ */
53
+ export declare function resolveChromePageId(mcp: McpProxy | undefined, url: string, title: string, projectOrigins: string[], sessionId?: string, pages?: PageInfo[],
54
+ /** Chrome 当前选中的 pageId(调用方传入,避免过滤后丢失非项目页面信息) */
55
+ chromeSelectedPageId?: number): Promise<PageIdResult>;
56
+ export {};
@@ -0,0 +1,244 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __typeError = (msg) => {
8
+ throw TypeError(msg);
9
+ };
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
33
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
34
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
35
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
36
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
37
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
38
+ var __privateWrapper = (obj, member, setter, getter) => ({
39
+ set _(value) {
40
+ __privateSet(obj, member, value, setter);
41
+ },
42
+ get _() {
43
+ return __privateGet(obj, member, getter);
44
+ }
45
+ });
46
+ var mcp_proxy_exports = {};
47
+ __export(mcp_proxy_exports, {
48
+ McpProxy: () => McpProxy
49
+ });
50
+ module.exports = __toCommonJS(mcp_proxy_exports);
51
+ var import_node_child_process = require("node:child_process");
52
+ var import_node_readline = require("node:readline");
53
+ var import_node_crypto = __toESM(require("node:crypto"));
54
+ var import_node_path = __toESM(require("node:path"));
55
+ var import_node = require("@aipanel/core/node");
56
+ var _proc, _rl, _messageId, _internalIdBase, _pending, _args, _startPromise, _idleTimer, _idleTimeout, _McpProxy_instances, doStart_fn, resetIdleTimer_fn;
57
+ const log = (0, import_node.createLogger)("McpProxy");
58
+ function resolveChromeDevToolsMcpBin() {
59
+ const pluginDir = (0, import_node.resolvePackageDir)("vite-plugin-aipanel");
60
+ const require2 = (0, import_node.createPackageRequire)(pluginDir);
61
+ const pkgJsonPath = require2.resolve("chrome-devtools-mcp/package.json");
62
+ const pkgDir = import_node_path.default.dirname(pkgJsonPath);
63
+ const { bin } = require2(pkgJsonPath);
64
+ const binEntry = typeof bin === "string" ? bin : Object.values(bin)[0];
65
+ return import_node_path.default.resolve(pkgDir, binEntry);
66
+ }
67
+ class McpProxy {
68
+ constructor(options = {}) {
69
+ __privateAdd(this, _McpProxy_instances);
70
+ __privateAdd(this, _proc, null);
71
+ __privateAdd(this, _rl, null);
72
+ __privateAdd(this, _messageId, 0);
73
+ /** 内部调用使用的高位 ID 起始值,避免与客户端 ID 冲突 */
74
+ __privateAdd(this, _internalIdBase, 1e6);
75
+ __privateAdd(this, _pending, /* @__PURE__ */ new Map());
76
+ __privateAdd(this, _args);
77
+ __privateAdd(this, _startPromise, null);
78
+ __privateAdd(this, _idleTimer, null);
79
+ __privateAdd(this, _idleTimeout);
80
+ __publicField(this, "sessionId");
81
+ __privateSet(this, _args, options.args ?? [
82
+ "--auto-connect",
83
+ "--no-usage-statistics",
84
+ "--no-performance-crux"
85
+ ]);
86
+ __privateSet(this, _idleTimeout, options.idleTimeout ?? 0);
87
+ this.sessionId = import_node_crypto.default.randomUUID();
88
+ }
89
+ get isRunning() {
90
+ return __privateGet(this, _proc) !== null && !__privateGet(this, _proc).killed;
91
+ }
92
+ async start() {
93
+ if (this.isRunning) return;
94
+ if (__privateGet(this, _startPromise)) return __privateGet(this, _startPromise);
95
+ __privateSet(this, _startPromise, __privateMethod(this, _McpProxy_instances, doStart_fn).call(this));
96
+ return __privateGet(this, _startPromise);
97
+ }
98
+ /** 转发原始 JSON-RPC 请求,保留客户端 ID */
99
+ async forward(rawRequest) {
100
+ await this.start();
101
+ if (!__privateGet(this, _proc) || !__privateGet(this, _proc).stdin) {
102
+ throw new Error("MCP process not available");
103
+ }
104
+ __privateMethod(this, _McpProxy_instances, resetIdleTimer_fn).call(this);
105
+ let msg;
106
+ try {
107
+ msg = JSON.parse(rawRequest);
108
+ } catch {
109
+ throw new Error("Invalid JSON-RPC request");
110
+ }
111
+ return new Promise((resolve) => {
112
+ const id = msg.id;
113
+ if (id !== void 0) {
114
+ __privateGet(this, _pending).set(id, (raw) => resolve(JSON.stringify(raw)));
115
+ } else {
116
+ __privateGet(this, _proc).stdin.write(rawRequest + "\n");
117
+ resolve("");
118
+ return;
119
+ }
120
+ __privateGet(this, _proc).stdin.write(rawRequest + "\n");
121
+ });
122
+ }
123
+ /** 调用 MCP 工具 */
124
+ async call(method, params = {}) {
125
+ await this.start();
126
+ if (!__privateGet(this, _proc) || !__privateGet(this, _proc).stdin) {
127
+ throw new Error("MCP process not available");
128
+ }
129
+ __privateMethod(this, _McpProxy_instances, resetIdleTimer_fn).call(this);
130
+ const id = __privateGet(this, _internalIdBase) + ++__privateWrapper(this, _messageId)._;
131
+ return new Promise((resolve) => {
132
+ __privateGet(this, _pending).set(id, resolve);
133
+ const request = JSON.stringify({ jsonrpc: "2.0", id, method, params });
134
+ __privateGet(this, _proc).stdin.write(request + "\n");
135
+ });
136
+ }
137
+ /** 直接调用 chrome-devtools-mcp 底层工具(内部使用) */
138
+ async callChromeDevTool(name, args = {}) {
139
+ return this.call("tools/call", { name, arguments: args });
140
+ }
141
+ /** 验证 MCP 是否可用 + 预热 CDP 连接 */
142
+ async verify() {
143
+ try {
144
+ await this.callChromeDevTool("list_pages", {});
145
+ return { ok: true };
146
+ } catch (e) {
147
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
148
+ }
149
+ }
150
+ stop() {
151
+ if (__privateGet(this, _idleTimer)) clearTimeout(__privateGet(this, _idleTimer));
152
+ const err = new Error("MCP server shutting down");
153
+ for (const resolve of __privateGet(this, _pending).values()) {
154
+ resolve({ error: { code: -32e3, message: err.message } });
155
+ }
156
+ __privateGet(this, _pending).clear();
157
+ if (__privateGet(this, _rl)) {
158
+ __privateGet(this, _rl).close();
159
+ __privateSet(this, _rl, null);
160
+ }
161
+ if (__privateGet(this, _proc) && !__privateGet(this, _proc).killed) {
162
+ __privateGet(this, _proc).kill();
163
+ __privateSet(this, _proc, null);
164
+ }
165
+ __privateSet(this, _startPromise, null);
166
+ }
167
+ }
168
+ _proc = new WeakMap();
169
+ _rl = new WeakMap();
170
+ _messageId = new WeakMap();
171
+ _internalIdBase = new WeakMap();
172
+ _pending = new WeakMap();
173
+ _args = new WeakMap();
174
+ _startPromise = new WeakMap();
175
+ _idleTimer = new WeakMap();
176
+ _idleTimeout = new WeakMap();
177
+ _McpProxy_instances = new WeakSet();
178
+ doStart_fn = async function() {
179
+ log.debug("Starting MCP process", { args: __privateGet(this, _args) });
180
+ try {
181
+ const binPath = resolveChromeDevToolsMcpBin();
182
+ __privateSet(this, _proc, (0, import_node_child_process.spawn)(process.execPath, [binPath, ...__privateGet(this, _args)], {
183
+ stdio: ["pipe", "pipe", "pipe"]
184
+ }));
185
+ log.debug("Using local chrome-devtools-mcp");
186
+ } catch {
187
+ throw new Error(
188
+ "Cannot find chrome-devtools-mcp. Please ensure it is installed: npm install chrome-devtools-mcp"
189
+ );
190
+ }
191
+ __privateSet(this, _rl, (0, import_node_readline.createInterface)({ input: __privateGet(this, _proc).stdout }));
192
+ __privateGet(this, _rl).on("line", (line) => {
193
+ try {
194
+ const msg = JSON.parse(line);
195
+ log.debug("MCP stdout", {
196
+ id: msg.id,
197
+ method: msg.method,
198
+ hasResult: !!msg.result,
199
+ hasError: !!msg.error
200
+ });
201
+ if (msg.id !== void 0 && __privateGet(this, _pending).has(msg.id)) {
202
+ const resolve = __privateGet(this, _pending).get(msg.id);
203
+ __privateGet(this, _pending).delete(msg.id);
204
+ log.debug("MCP pending resolved", { id: msg.id });
205
+ resolve(msg);
206
+ }
207
+ } catch {
208
+ }
209
+ });
210
+ __privateGet(this, _proc).stderr?.on("data", (d) => {
211
+ const text = d.toString().trim();
212
+ if (!text || /No handler registered for issue code \w+/i.test(text)) return;
213
+ log.debug("[MCP stderr]", { text: text.substring(0, 200) });
214
+ });
215
+ __privateGet(this, _proc).on("close", (code) => {
216
+ log.debug("MCP process closed", { code });
217
+ for (const resolve of __privateGet(this, _pending).values()) {
218
+ resolve({ error: { code: -32e3, message: `MCP process exited with code ${code}` } });
219
+ }
220
+ __privateGet(this, _pending).clear();
221
+ __privateSet(this, _proc, null);
222
+ __privateSet(this, _rl, null);
223
+ __privateSet(this, _startPromise, null);
224
+ });
225
+ await this.call("initialize", {
226
+ protocolVersion: "2024-11-05",
227
+ capabilities: {},
228
+ clientInfo: { name: "vite-plugin-aipanel", version: "1.0.0" }
229
+ });
230
+ log.debug("MCP proxy ready");
231
+ __privateSet(this, _startPromise, null);
232
+ };
233
+ resetIdleTimer_fn = function() {
234
+ if (__privateGet(this, _idleTimeout) <= 0) return;
235
+ if (__privateGet(this, _idleTimer)) clearTimeout(__privateGet(this, _idleTimer));
236
+ __privateSet(this, _idleTimer, setTimeout(() => {
237
+ log.debug("MCP process idle timeout, stopping");
238
+ this.stop();
239
+ }, __privateGet(this, _idleTimeout)));
240
+ };
241
+ // Annotate the CommonJS export names for ESM import in node:
242
+ 0 && (module.exports = {
243
+ McpProxy
244
+ });
@@ -0,0 +1,23 @@
1
+ export interface McpProxyOptions {
2
+ args?: string[];
3
+ idleTimeout?: number;
4
+ }
5
+ export declare class McpProxy {
6
+ #private;
7
+ readonly sessionId: string;
8
+ constructor(options?: McpProxyOptions);
9
+ get isRunning(): boolean;
10
+ start(): Promise<void>;
11
+ /** 转发原始 JSON-RPC 请求,保留客户端 ID */
12
+ forward(rawRequest: string): Promise<string>;
13
+ /** 调用 MCP 工具 */
14
+ call(method: string, params?: Record<string, unknown>): Promise<unknown>;
15
+ /** 直接调用 chrome-devtools-mcp 底层工具(内部使用) */
16
+ callChromeDevTool(name: string, args?: Record<string, unknown>): Promise<unknown>;
17
+ /** 验证 MCP 是否可用 + 预热 CDP 连接 */
18
+ verify(): Promise<{
19
+ ok: boolean;
20
+ error?: string;
21
+ }>;
22
+ stop(): void;
23
+ }