@vitest-agent/plugin 5.0.4 → 5.1.1

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
@@ -3,8 +3,8 @@ import { AgentPluginOptions, AgentReporterOptions, ConsoleMode, CoverageBaseline
3
3
  import { Context, Effect, Layer, Option } from "effect";
4
4
  import { TestProjectInlineConfiguration, TestTagDefinition } from "vitest/config";
5
5
  import { ResolvedConfig, VitestPluginContext } from "vitest/node";
6
- import { SourceMap } from "magic-string";
7
6
  import { WorkspacesSyncOptions } from "@effected/workspaces/node-sync";
7
+ import { SourceMap } from "magic-string";
8
8
  import { MigrationError } from "effect/sql/Migrator";
9
9
  import { SqlError } from "effect/sql/SqlError";
10
10
  //#region src/utils/tag.d.ts
@@ -236,6 +236,50 @@ export declare class DefaultDiscoverStrategy extends DiscoverStrategy {
236
236
  extend(options: DiscoverStrategyExtendOptions): DiscoverStrategy;
237
237
  }
238
238
  //#endregion
239
+ //#region src/utils/discover-projects.d.ts
240
+ /**
241
+ * The resolved output of `discoverProjects` — projects and tag definitions ready for `defineConfig`.
242
+ * @public
243
+ */
244
+ interface DiscoverProjectsResult {
245
+ readonly projects: TestProjectInlineConfiguration[] | undefined;
246
+ readonly tags: TestTagDefinition[];
247
+ }
248
+ /**
249
+ * Options for `discoverProjects`.
250
+ * @public
251
+ */
252
+ interface DiscoverProjectsOptions {
253
+ readonly strategy?: DiscoverStrategy;
254
+ readonly cwd?: string;
255
+ readonly additionalEntries?: ReadonlyArray<{
256
+ readonly name: string;
257
+ readonly path: string;
258
+ }>;
259
+ /**
260
+ * Filesystem port the test-file and signature walks read through. Defaults
261
+ * to `node:fs`; tests inject a virtual volume instead of a real tmp tree.
262
+ */
263
+ readonly fs?: WalkerFileSystem;
264
+ /**
265
+ * Sync operations `@effected/workspaces` resolves the workspace root and
266
+ * package list through. Defaults to its `nodeSyncOps` binding.
267
+ */
268
+ readonly syncOps?: WorkspacesSyncOptions;
269
+ /**
270
+ * Optional traversal depth override for workspace package enumeration.
271
+ * Forwarded to `@effected/workspaces`' `getWorkspacePackagesSync`.
272
+ */
273
+ readonly maxDepth?: number;
274
+ }
275
+ /**
276
+ * Scan all workspace packages and additional entries through the active strategy and return projects + tags.
277
+ * @param options - Optional strategy, working directory, and extra project entries
278
+ * @returns Resolved projects and tag definitions
279
+ * @public
280
+ */
281
+ export declare function discoverProjects(options?: DiscoverProjectsOptions): Promise<DiscoverProjectsResult>;
282
+ //#endregion
239
283
  //#region src/utils/inject-tags.d.ts
240
284
  /**
241
285
  * Return value of the Vite `transform` hook — the rewritten source code and its source map.
@@ -1118,50 +1162,6 @@ export declare class ConfigurationError extends Error {
1118
1162
  readonly name = "ConfigurationError";
1119
1163
  }
1120
1164
  //#endregion
1121
- //#region src/utils/discover-projects.d.ts
1122
- /**
1123
- * The resolved output of `discoverProjects` — projects and tag definitions ready for `defineConfig`.
1124
- * @public
1125
- */
1126
- interface DiscoverProjectsResult {
1127
- readonly projects: TestProjectInlineConfiguration[] | undefined;
1128
- readonly tags: TestTagDefinition[];
1129
- }
1130
- /**
1131
- * Options for `discoverProjects`.
1132
- * @public
1133
- */
1134
- interface DiscoverProjectsOptions {
1135
- readonly strategy?: DiscoverStrategy;
1136
- readonly cwd?: string;
1137
- readonly additionalEntries?: ReadonlyArray<{
1138
- readonly name: string;
1139
- readonly path: string;
1140
- }>;
1141
- /**
1142
- * Filesystem port the test-file and signature walks read through. Defaults
1143
- * to `node:fs`; tests inject a virtual volume instead of a real tmp tree.
1144
- */
1145
- readonly fs?: WalkerFileSystem;
1146
- /**
1147
- * Sync operations `@effected/workspaces` resolves the workspace root and
1148
- * package list through. Defaults to its `nodeSyncOps` binding.
1149
- */
1150
- readonly syncOps?: WorkspacesSyncOptions;
1151
- /**
1152
- * Optional traversal depth override for workspace package enumeration.
1153
- * Forwarded to `@effected/workspaces`' `getWorkspacePackagesSync`.
1154
- */
1155
- readonly maxDepth?: number;
1156
- }
1157
- /**
1158
- * Scan all workspace packages and additional entries through the active strategy and return projects + tags.
1159
- * @param options - Optional strategy, working directory, and extra project entries
1160
- * @returns Resolved projects and tag definitions
1161
- * @public
1162
- */
1163
- export declare function discoverProjects(options?: DiscoverProjectsOptions): Promise<DiscoverProjectsResult>;
1164
- //#endregion
1165
1165
  //#region src/utils/classify-helpers.d.ts
1166
1166
  /**
1167
1167
  * Creates a ClassifyFn that maps filename suffix patterns to tag arrays.
@@ -1433,9 +1433,17 @@ interface VitestErrorLike {
1433
1433
  * Returns `null` for the signature when no usable top frame is found
1434
1434
  * (error has no stack, or every frame is in framework code). Frames may
1435
1435
  * still be populated even when the signature is null.
1436
+ *
1437
+ * @param error - The Vitest error to process.
1438
+ * @param options - Optional overrides. `readSource` reads the top frame's
1439
+ * source file as UTF-8 text for function-boundary detection; it defaults to
1440
+ * `node:fs`'s `readFileSync`, and a throw is treated as an unreadable file
1441
+ * (the signature falls back to the raw-line bucket).
1436
1442
  * @public
1437
1443
  */
1438
- export declare const processFailure: (error: VitestErrorLike) => {
1444
+ export declare const processFailure: (error: VitestErrorLike, options?: {
1445
+ readonly readSource?: (path: string) => string;
1446
+ }) => {
1439
1447
  frames: ReadonlyArray<StackFrameInput>;
1440
1448
  signatureHash: string | null;
1441
1449
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest-agent/plugin",
3
- "version": "5.0.4",
3
+ "version": "5.1.1",
4
4
  "private": false,
5
5
  "description": "Vitest plugin for the vitest-agent ecosystem: owns persistence, classification, baselines, trends, and dispatches rendering to a configurable reporter.",
6
6
  "keywords": [
@@ -46,9 +46,9 @@
46
46
  "@effect/platform-node": "4.0.0-rc.118",
47
47
  "@effected/glob": "^0.9.0",
48
48
  "@effected/workspaces": "^0.30.2",
49
- "@vitest-agent/cli": "3.2.4",
50
- "@vitest-agent/engine": "0.2.11",
51
- "@vitest-agent/mcp": "5.1.2",
49
+ "@vitest-agent/cli": "3.2.6",
50
+ "@vitest-agent/engine": "0.3.1",
51
+ "@vitest-agent/mcp": "5.1.4",
52
52
  "@vitest-agent/reporter": "3.1.3",
53
53
  "@vitest-agent/sdk": "5.1.3",
54
54
  "effect": "4.0.0-rc.118",
package/plugin.js CHANGED
@@ -357,6 +357,11 @@ const buildPreset = (thresholdsLevel, targetsLevel, perFile) => Object.freeze({
357
357
  * `strategy` is provided AND `additionalEntries` is empty. Any `.addProject()`
358
358
  * chain or explicit strategy bypasses the cache.
359
359
  *
360
+ * Every option — including the `fs` / `syncOps` filesystem ports that
361
+ * `AgentPlugin.discover` never sets — is forwarded unchanged to
362
+ * `discoverProjects`, so tests can drive the builder over a virtual volume.
363
+ * Exported for tests only; not part of the package barrel.
364
+ *
360
365
  * @internal
361
366
  */
362
367
  function makeDiscoverBuilder(options) {
@@ -446,4 +451,4 @@ function makeDiscoverBuilder(options) {
446
451
  })(AgentPlugin || (AgentPlugin = {}));
447
452
 
448
453
  //#endregion
449
- export { AgentPlugin, CURRENT_PLUGIN_VERSION, resolveConsoleMode };
454
+ export { AgentPlugin, CURRENT_PLUGIN_VERSION, makeDiscoverBuilder, resolveConsoleMode };
@@ -3,12 +3,16 @@ import { existsSync, readFileSync } from "node:fs";
3
3
  import { basename, dirname, relative } from "node:path";
4
4
 
5
5
  //#region src/utils/build-module-info.ts
6
+ const nodeBuildModuleInfoFs = {
7
+ exists: (path) => existsSync(path),
8
+ readFile: (path) => readFileSync(path, "utf8")
9
+ };
6
10
  const NOT_FOUND = {
7
11
  packageName: "",
8
12
  packagePath: ""
9
13
  };
10
14
  const cache = /* @__PURE__ */ new Map();
11
- const resolvePackageInfo = (filePath) => {
15
+ const resolvePackageInfo = (filePath, fs) => {
12
16
  let dir = dirname(filePath);
13
17
  const visited = [];
14
18
  while (true) {
@@ -19,8 +23,8 @@ const resolvePackageInfo = (filePath) => {
19
23
  }
20
24
  visited.push(dir);
21
25
  const pkgJsonPath = `${dir}/package.json`;
22
- if (existsSync(pkgJsonPath)) try {
23
- const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf8"));
26
+ if (fs.exists(pkgJsonPath)) try {
27
+ const pkg = JSON.parse(fs.readFile(pkgJsonPath));
24
28
  const result = {
25
29
  packageName: typeof pkg.name === "string" ? pkg.name : "",
26
30
  packagePath: dir
@@ -44,11 +48,17 @@ const resolvePackageInfo = (filePath) => {
44
48
  *
45
49
  * Query strings (Vite virtual module suffixes like `?v=1234`) are stripped
46
50
  * before the walk so the cache key is always a clean filesystem path.
51
+ *
52
+ * @param filePath - Module id, optionally carrying a Vite query suffix.
53
+ * @param fs - Filesystem the `package.json` walk reads through. Defaults to
54
+ * `node:fs`; tests pass a virtual volume. The cache is shared across ports
55
+ * and keyed only by directory, so a test injecting a volume should use
56
+ * roots no other caller walks, or call {@link clearBuildModuleInfoCache}.
47
57
  */
48
- const buildModuleInfo = (filePath) => {
58
+ const buildModuleInfo = (filePath, fs = nodeBuildModuleInfoFs) => {
49
59
  const queryIndex = filePath.indexOf("?");
50
60
  const cleanId = queryIndex === -1 ? filePath : filePath.slice(0, queryIndex);
51
- const { packageName, packagePath } = resolvePackageInfo(cleanId);
61
+ const { packageName, packagePath } = resolvePackageInfo(cleanId, fs);
52
62
  return {
53
63
  path: cleanId,
54
64
  relativePath: toPosixPath(relative(process.cwd(), cleanId)),
@@ -22,9 +22,10 @@ const parseFramesFromStackString = (stack) => {
22
22
  }
23
23
  return frames;
24
24
  };
25
- const readSourceSafe = (filePath) => {
25
+ const readSourceNode = (filePath) => readFileSync(filePath, "utf-8");
26
+ const readSourceSafe = (filePath, readSource) => {
26
27
  try {
27
- return readFileSync(filePath, "utf-8");
28
+ return readSource(filePath);
28
29
  } catch {
29
30
  return null;
30
31
  }
@@ -36,9 +37,15 @@ const readSourceSafe = (filePath) => {
36
37
  * Returns `null` for the signature when no usable top frame is found
37
38
  * (error has no stack, or every frame is in framework code). Frames may
38
39
  * still be populated even when the signature is null.
40
+ *
41
+ * @param error - The Vitest error to process.
42
+ * @param options - Optional overrides. `readSource` reads the top frame's
43
+ * source file as UTF-8 text for function-boundary detection; it defaults to
44
+ * `node:fs`'s `readFileSync`, and a throw is treated as an unreadable file
45
+ * (the signature falls back to the raw-line bucket).
39
46
  * @public
40
47
  */
41
- const processFailure = (error) => {
48
+ const processFailure = (error, options) => {
42
49
  const rawFrames = error.stacks !== void 0 && error.stacks.length > 0 ? error.stacks.map((f, ordinal) => ({
43
50
  ordinal,
44
51
  method: f.method ?? null,
@@ -52,7 +59,7 @@ const processFailure = (error) => {
52
59
  let topFunctionName = null;
53
60
  if (topFrame !== void 0) {
54
61
  const lineForBoundary = topFrame.line;
55
- const source = readSourceSafe(topFrame.filePath);
62
+ const source = readSourceSafe(topFrame.filePath, options?.readSource ?? readSourceNode);
56
63
  const boundary = source !== null ? findFunctionBoundary(source, lineForBoundary) : null;
57
64
  if (boundary !== null) {
58
65
  topBoundaryLine = boundary.line;
package/version.js CHANGED
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @public
10
10
  */
11
- const CURRENT_PLUGIN_VERSION = "5.0.4";
11
+ const CURRENT_PLUGIN_VERSION = "5.1.1";
12
12
 
13
13
  //#endregion
14
14
  export { CURRENT_PLUGIN_VERSION };