@vitest-agent/mcp 2.1.1 → 2.1.2

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/index.d.ts CHANGED
@@ -533,6 +533,7 @@ declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
533
533
  readonly failed: number;
534
534
  readonly skipped: number;
535
535
  readonly duration: number;
536
+ readonly modules?: number | undefined;
536
537
  };
537
538
  readonly failed: readonly {
538
539
  readonly file: string;
package/index.js CHANGED
@@ -12,7 +12,7 @@ import { parseSessionEnvExports, recoverSessionContextFromSessionEnv } from "./s
12
12
  *
13
13
  * @public
14
14
  */
15
- const CURRENT_MCP_VERSION = "2.1.1";
15
+ const CURRENT_MCP_VERSION = "2.1.2";
16
16
 
17
17
  //#endregion
18
18
  export { CURRENT_MCP_VERSION, McpLive, appRouter, buildMcpServer, createCallerFactory, createCurrentSessionIdRef, createSessionContextRef, parseSessionEnvExports, recoverSessionContextFromSessionEnv, startMcpServer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest-agent/mcp",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "private": false,
5
5
  "description": "Model Context Protocol server for vitest-agent. Exposes 53 tools for agent access to test data, TDD lifecycle, and session management.",
6
6
  "keywords": [
@@ -42,7 +42,7 @@
42
42
  "@effect/sql-sqlite-node": "4.0.0-beta.107",
43
43
  "@modelcontextprotocol/sdk": "^1.30.0",
44
44
  "@trpc/server": "^11.18.0",
45
- "@vitest-agent/sdk": "2.0.16",
45
+ "@vitest-agent/sdk": "2.1.0",
46
46
  "effect": "4.0.0-beta.107",
47
47
  "zod": "^4.4.3"
48
48
  },
@@ -1,7 +1,10 @@
1
1
  import { publicProcedure } from "../context.js";
2
- import { AgentReport, DataReader, DataStore, buildAgentReport, buildConsoleLeaks, collectConsoleLeakEntries } from "@vitest-agent/sdk";
2
+ import { AgentReport, DataReader, DataStore, buildAgentReport, buildConsoleLeaks, coerceErrorField, collectConsoleLeakEntries } from "@vitest-agent/sdk";
3
3
  import { Effect, Schema, SchemaGetter } from "effect";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
+ import { mkdtempSync, rmSync } from "node:fs";
6
+ import { tmpdir } from "node:os";
7
+ import { join } from "node:path";
5
8
  import { Writable } from "node:stream";
6
9
 
7
10
  //#region src/tools/run-tests.ts
@@ -84,6 +87,27 @@ function readDiscoveryLastScannedAt() {
84
87
  const value = globalThis[DISCOVERY_LAST_SCAN_SYMBOL];
85
88
  return typeof value === "string" ? value : void 0;
86
89
  }
90
+ /**
91
+ * Per-invocation coverage temp directory. Vitest's v8 provider `rm -rf`s the
92
+ * shared `coverage/` reports directory at run start (`clean: true` default),
93
+ * so two concurrent runs in one checkout destroy each other's `.tmp` files
94
+ * (ENOENT coverage-N.json — issues #159/#191/#194). Each MCP run gets its own
95
+ * directory; coverage persistence is unaffected because the analyzer consumes
96
+ * the in-memory CoverageMap, never the disk artifacts. Consequence: final
97
+ * coverage artifacts (html/lcov) from MCP-driven runs land in the throwaway
98
+ * dir instead of `./coverage` — acceptable because MCP consumers read
99
+ * coverage from SQLite (`CoverageAnalyzer` consumes the in-memory map via
100
+ * `onCoverage`), not from disk artifacts.
101
+ *
102
+ * @internal exported for tests
103
+ */
104
+ const makeCoverageDirOverride = () => {
105
+ const dir = mkdtempSync(join(tmpdir(), "vitest-agent-cov-"));
106
+ return {
107
+ dir,
108
+ coverage: { reportsDirectory: dir }
109
+ };
110
+ };
87
111
  const stdoutSinkStorage = new AsyncLocalStorage();
88
112
  const stderrSinkStorage = new AsyncLocalStorage();
89
113
  let _stdioPatched = false;
@@ -305,10 +329,13 @@ const runTests = publicProcedure.input(Schema.toStandardSchemaV1(Schema.Struct({
305
329
  } });
306
330
  const { createVitest } = await import("vitest/node");
307
331
  let vitest;
332
+ let covOverride;
308
333
  try {
334
+ covOverride = makeCoverageDirOverride();
309
335
  vitest = await createVitest("test", {
310
336
  root: ctx.cwd,
311
337
  run: true,
338
+ coverage: covOverride.coverage,
312
339
  ...project ? { project } : {},
313
340
  ...resolvedExpression !== null ? { tagsFilter: [resolvedExpression] } : {},
314
341
  ...input.passWithNoTests !== void 0 ? { passWithNoTests: input.passWithNoTests } : {}
@@ -334,8 +361,8 @@ const runTests = publicProcedure.input(Schema.toStandardSchemaV1(Schema.Struct({
334
361
  resolvedExpression
335
362
  }
336
363
  };
337
- const reason = unhandledErrors.length > 0 || result.testModules.some((m) => m.state() === "failed") ? "failed" : "passed";
338
- const baseReport = buildAgentReport(testModules, unhandledErrors, reason, { omitPassingTests: true });
364
+ const preliminaryReason = unhandledErrors.length > 0 || result.testModules.some((m) => m.state() === "failed") ? "failed" : "passed";
365
+ const baseReport = buildAgentReport(testModules, unhandledErrors, preliminaryReason, { omitPassingTests: true });
339
366
  const leaks = buildConsoleLeaks(collectConsoleLeakEntries(localVitest.state.getFiles()));
340
367
  const report = leaks !== void 0 ? {
341
368
  ...baseReport,
@@ -369,19 +396,34 @@ const runTests = publicProcedure.input(Schema.toStandardSchemaV1(Schema.Struct({
369
396
  discoveryLastScannedAt: readDiscoveryLastScannedAt() ?? null
370
397
  };
371
398
  } catch (err) {
372
- if (err instanceof Error && err.message === "VITEST_TIMEOUT") return {
373
- kind: "timeout",
374
- timeoutSeconds: input.timeout ?? 120
375
- };
399
+ let message;
400
+ try {
401
+ if (err instanceof Error && err.message === "VITEST_TIMEOUT") return {
402
+ kind: "timeout",
403
+ timeoutSeconds: input.timeout ?? 120
404
+ };
405
+ message = err instanceof Error ? err.message : String(err);
406
+ } catch {
407
+ message = coerceErrorField(err, "message") ?? "<unserializable error>";
408
+ }
376
409
  return {
377
410
  kind: "error",
378
- message: err instanceof Error ? err.message : String(err)
411
+ message
379
412
  };
380
413
  } finally {
381
- await vitest?.close();
382
- nullStream.destroy();
414
+ try {
415
+ await vitest?.close();
416
+ } finally {
417
+ nullStream.destroy();
418
+ if (covOverride !== void 0) try {
419
+ rmSync(covOverride.dir, {
420
+ recursive: true,
421
+ force: true
422
+ });
423
+ } catch {}
424
+ }
383
425
  }
384
426
  }));
385
427
 
386
428
  //#endregion
387
- export { RunTestsAsMarkdown, RunTestsResult, coerceErrors, composeTagExpression, formatNoMatchMarkdown, formatReportMarkdown, formatRunTestsMarkdown, readDiscoveryLastScannedAt, runTests, sanitizeTestArgs, withStdioCaptured };
429
+ export { RunTestsAsMarkdown, RunTestsResult, coerceErrors, composeTagExpression, formatNoMatchMarkdown, formatReportMarkdown, formatRunTestsMarkdown, makeCoverageDirOverride, readDiscoveryLastScannedAt, runTests, sanitizeTestArgs, withStdioCaptured };