@xiaou66/vite-plugin-vue-mcp-next 1.0.3 → 1.0.4

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/dist/index.d.cts CHANGED
@@ -370,10 +370,25 @@ interface PageTarget {
370
370
  readonly pathname: string;
371
371
  /** 页面标题,用于 AI 和用户在多个相似 URL 中识别目标页面。 */
372
372
  readonly title?: string;
373
+ /** 同标签页稳定身份,仅 runtime 目标提供,用于刷新或 HMR 重连时断开旧 pageId。 */
374
+ readonly runtimeClientId?: string;
373
375
  /** 对应的 Vite HTML 入口或 appendTo 入口,用于说明页面来自哪个开发入口。 */
374
376
  readonly entry?: string;
375
377
  /** 页面是否仍可调试,用于避免 MCP 对已断开的页面继续执行操作。 */
376
378
  readonly connected: boolean;
379
+ /** runtime 目标断开时间,仅用于保留短期历史并清理过期断开记录。 */
380
+ readonly disconnectedAt?: number;
381
+ }
382
+ /**
383
+ * 页面目标列表选项。
384
+ *
385
+ * 默认列表面向日常调试,只展示可操作页面;排查生命周期问题时可显式包含断开 runtime 记录。
386
+ */
387
+ interface PageTargetListOptions {
388
+ /** 是否包含已断开的 runtime 页面,默认隐藏以避免刷新历史干扰目标选择。 */
389
+ readonly includeDisconnected?: boolean;
390
+ /** 测试或批处理场景可传入固定时间,避免依赖真实时钟造成用例不稳定。 */
391
+ readonly now?: number;
377
392
  }
378
393
  /**
379
394
  * 页面 Console 和运行时异常的统一记录。
@@ -444,13 +459,13 @@ interface NetworkRecord {
444
459
  */
445
460
  interface PageTargetRegistry {
446
461
  /** 新增或更新页面目标,适合 runtime 重连和 CDP target 刷新场景。 */
447
- upsert(target: PageTarget): void;
462
+ upsert(target: PageTarget, now?: number): void;
448
463
  /** 获取单个页面目标,工具调用解析 pageId 时使用。 */
449
464
  get(pageId: string): PageTarget | undefined;
450
- /** 返回所有页面目标快照,避免调用方修改内部 Map。 */
451
- list(): PageTarget[];
452
- /** 标记页面断开,保留记录可以帮助用户理解刚才的页面为什么不可操作。 */
453
- disconnect(pageId: string): void;
465
+ /** 返回页面目标快照,默认隐藏已断开的 runtime 历史记录。 */
466
+ list(options?: PageTargetListOptions): PageTarget[];
467
+ /** 标记页面断开,保留短期记录可以帮助用户理解刚才的页面为什么不可操作。 */
468
+ disconnect(pageId: string, now?: number): void;
454
469
  }
455
470
  /**
456
471
  * 插件内部共享上下文。
package/dist/index.d.ts CHANGED
@@ -370,10 +370,25 @@ interface PageTarget {
370
370
  readonly pathname: string;
371
371
  /** 页面标题,用于 AI 和用户在多个相似 URL 中识别目标页面。 */
372
372
  readonly title?: string;
373
+ /** 同标签页稳定身份,仅 runtime 目标提供,用于刷新或 HMR 重连时断开旧 pageId。 */
374
+ readonly runtimeClientId?: string;
373
375
  /** 对应的 Vite HTML 入口或 appendTo 入口,用于说明页面来自哪个开发入口。 */
374
376
  readonly entry?: string;
375
377
  /** 页面是否仍可调试,用于避免 MCP 对已断开的页面继续执行操作。 */
376
378
  readonly connected: boolean;
379
+ /** runtime 目标断开时间,仅用于保留短期历史并清理过期断开记录。 */
380
+ readonly disconnectedAt?: number;
381
+ }
382
+ /**
383
+ * 页面目标列表选项。
384
+ *
385
+ * 默认列表面向日常调试,只展示可操作页面;排查生命周期问题时可显式包含断开 runtime 记录。
386
+ */
387
+ interface PageTargetListOptions {
388
+ /** 是否包含已断开的 runtime 页面,默认隐藏以避免刷新历史干扰目标选择。 */
389
+ readonly includeDisconnected?: boolean;
390
+ /** 测试或批处理场景可传入固定时间,避免依赖真实时钟造成用例不稳定。 */
391
+ readonly now?: number;
377
392
  }
378
393
  /**
379
394
  * 页面 Console 和运行时异常的统一记录。
@@ -444,13 +459,13 @@ interface NetworkRecord {
444
459
  */
445
460
  interface PageTargetRegistry {
446
461
  /** 新增或更新页面目标,适合 runtime 重连和 CDP target 刷新场景。 */
447
- upsert(target: PageTarget): void;
462
+ upsert(target: PageTarget, now?: number): void;
448
463
  /** 获取单个页面目标,工具调用解析 pageId 时使用。 */
449
464
  get(pageId: string): PageTarget | undefined;
450
- /** 返回所有页面目标快照,避免调用方修改内部 Map。 */
451
- list(): PageTarget[];
452
- /** 标记页面断开,保留记录可以帮助用户理解刚才的页面为什么不可操作。 */
453
- disconnect(pageId: string): void;
465
+ /** 返回页面目标快照,默认隐藏已断开的 runtime 历史记录。 */
466
+ list(options?: PageTargetListOptions): PageTarget[];
467
+ /** 标记页面断开,保留短期记录可以帮助用户理解刚才的页面为什么不可操作。 */
468
+ disconnect(pageId: string, now?: number): void;
454
469
  }
455
470
  /**
456
471
  * 插件内部共享上下文。
package/dist/index.js CHANGED
@@ -194,24 +194,64 @@ function createRingBuffer(capacity) {
194
194
  }
195
195
 
196
196
  // src/context.ts
197
+ var MINUTE_MS = 60 * 1e3;
198
+ var DISCONNECTED_RUNTIME_TARGET_RETENTION_MS = 5 * MINUTE_MS;
199
+ function shouldPruneDisconnectedRuntimeTarget(target, now) {
200
+ return target.source === "runtime" && !target.connected && typeof target.disconnectedAt === "number" && now - target.disconnectedAt > DISCONNECTED_RUNTIME_TARGET_RETENTION_MS;
201
+ }
202
+ function pruneDisconnectedRuntimeTargets(targets, now) {
203
+ for (const [pageId, target] of targets) {
204
+ if (shouldPruneDisconnectedRuntimeTarget(target, now)) {
205
+ targets.delete(pageId);
206
+ }
207
+ }
208
+ }
209
+ function markTargetDisconnected(target, now) {
210
+ return {
211
+ ...target,
212
+ connected: false,
213
+ disconnectedAt: target.disconnectedAt ?? now
214
+ };
215
+ }
216
+ function shouldListPageTarget(target, options) {
217
+ return options.includeDisconnected === true || target.source !== "runtime" || target.connected;
218
+ }
219
+ function disconnectPreviousRuntimeClientTarget(targets, target, now) {
220
+ if (target.source !== "runtime" || !target.runtimeClientId) {
221
+ return;
222
+ }
223
+ for (const [pageId, currentTarget] of targets) {
224
+ if (pageId === target.pageId || currentTarget.source !== "runtime" || currentTarget.runtimeClientId !== target.runtimeClientId || !currentTarget.connected) {
225
+ continue;
226
+ }
227
+ targets.set(pageId, markTargetDisconnected(currentTarget, now));
228
+ }
229
+ }
197
230
  function createPageTargetRegistry() {
198
231
  const targets = /* @__PURE__ */ new Map();
199
232
  return {
200
- upsert(target) {
233
+ upsert(target, now = Date.now()) {
234
+ pruneDisconnectedRuntimeTargets(targets, now);
235
+ disconnectPreviousRuntimeClientTarget(targets, target, now);
201
236
  targets.set(target.pageId, target);
202
237
  },
203
238
  get(pageId) {
204
239
  return targets.get(pageId);
205
240
  },
206
- list() {
207
- return [...targets.values()];
241
+ list(options = {}) {
242
+ const now = options.now ?? Date.now();
243
+ pruneDisconnectedRuntimeTargets(targets, now);
244
+ return [...targets.values()].filter(
245
+ (target) => shouldListPageTarget(target, options)
246
+ );
208
247
  },
209
- disconnect(pageId) {
248
+ disconnect(pageId, now = Date.now()) {
249
+ pruneDisconnectedRuntimeTargets(targets, now);
210
250
  const target = targets.get(pageId);
211
251
  if (!target) {
212
252
  return;
213
253
  }
214
- targets.set(pageId, { ...target, connected: false });
254
+ targets.set(pageId, markTargetDisconnected(target, now));
215
255
  }
216
256
  };
217
257
  }
@@ -664,9 +704,12 @@ function registerPageTools(server, ctx, vite) {
664
704
  server.registerTool(
665
705
  MCP_TOOL_NAMES.listPages,
666
706
  {
667
- description: "List Vite page entries and connected runtime/CDP targets."
707
+ description: "List Vite page entries and connected runtime/CDP targets.",
708
+ inputSchema: {
709
+ includeDisconnected: z5.boolean().optional()
710
+ }
668
711
  },
669
- async () => {
712
+ async (input) => {
670
713
  const cdpResult = await listCdpPageTargets(ctx);
671
714
  for (const target of cdpResult.pages) {
672
715
  ctx.pages.upsert(target);
@@ -674,7 +717,9 @@ function registerPageTools(server, ctx, vite) {
674
717
  }
675
718
  return createToolResponse({
676
719
  entries: discoverHtmlEntries(vite),
677
- pages: ctx.pages.list(),
720
+ pages: ctx.pages.list({
721
+ includeDisconnected: input.includeDisconnected
722
+ }),
678
723
  cdpError: cdpResult.error
679
724
  });
680
725
  }
@@ -2298,7 +2343,7 @@ function isRuntimePageTarget(payload) {
2298
2343
  return false;
2299
2344
  }
2300
2345
  const target = payload;
2301
- return target.source === "runtime" && typeof target.pageId === "string" && typeof target.url === "string" && typeof target.pathname === "string" && typeof target.connected === "boolean";
2346
+ return target.source === "runtime" && typeof target.pageId === "string" && typeof target.url === "string" && typeof target.pathname === "string" && typeof target.connected === "boolean" && (target.runtimeClientId === void 0 || typeof target.runtimeClientId === "string");
2302
2347
  }
2303
2348
  function isConsoleRecord(payload) {
2304
2349
  if (!payload || typeof payload !== "object") {