@vitest-agent/plugin 5.6.2 → 6.0.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
@@ -4,6 +4,7 @@ import { AgentPluginOptions, AgentReporterOptions, ConsoleMode, CoverageBaseline
4
4
  import { Context, Effect, Layer, Option } from "effect";
5
5
  import { TestProjectInlineConfiguration, TestTagDefinition } from "vitest/config";
6
6
  import { ResolvedConfig, VitestPluginContext } from "vitest/node";
7
+ import { WalkerSyncOps, WalkerSyncOps as WalkerSyncOps$1 } from "@effected/walker";
7
8
  import { WorkspacesSyncOptions } from "@effected/workspaces/node-sync";
8
9
  import { SourceMap } from "magic-string";
9
10
  /**
@@ -29,83 +30,6 @@ export declare class Tag {
29
30
  */
30
31
  static make(name: string, options?: TagOptions): Tag;
31
32
  }
32
- /**
33
- * The filesystem operations the discovery walkers need, supplied by the
34
- * caller. Node's built-ins satisfy it directly via {@link nodeWalkerFs}, which
35
- * is what every production call site uses.
36
- *
37
- * The port exists because the walkers used to call `node:fs/promises` outright,
38
- * which made them untestable against anything but a real temporary directory —
39
- * a virtual filesystem cannot intercept a direct `node:fs` call. Every test in
40
- * this package that exercised discovery therefore had to build, populate and
41
- * tear down a real tmp tree.
42
- *
43
- * Deliberately NOT `fs.promises`-shaped: the walkers need exactly two
44
- * operations, and a wider surface would invite call sites to reach past the
45
- * port. It is also NOT shaped like `@effected/workspaces`'s `SyncFileSystem`
46
- * (which this package consumes separately, in `discover-projects.ts`) — that
47
- * port answers entry *names*, and the walkers need the entry *type* that
48
- * `readdir({ withFileTypes: true })` returns in the same syscall. Reading names
49
- * and then stat-ing each one is the syscall-doubling this module exists to
50
- * avoid; see {@link WalkerEntry}.
51
- *
52
- * @packageDocumentation
53
- */
54
- /**
55
- * One directory entry, carrying the name and type together.
56
- *
57
- * A structural subset of Node's `Dirent`, so a real `Dirent` satisfies it
58
- * verbatim and `readdir({ withFileTypes: true })` needs no adaptation.
59
- * @public
60
- */
61
- interface WalkerEntry {
62
- /** The entry's own name, not a path. */
63
- readonly name: string;
64
- /** Whether this entry is a regular file. */
65
- readonly isFile: () => boolean;
66
- /** Whether this entry is a directory. */
67
- readonly isDirectory: () => boolean;
68
- }
69
- /**
70
- * The filesystem operations the discovery walkers need.
71
- *
72
- * Both operations may reject; every walker absorbs a rejection as "this path
73
- * contributes nothing" rather than propagating it, matching the behavior the
74
- * `node:fs` calls had when they were inline.
75
- * @public
76
- */
77
- interface WalkerFileSystem {
78
- /**
79
- * The entries inside the directory at `dir`, with their types. May reject —
80
- * a rejection reads as an unreadable directory and skips it.
81
- */
82
- readonly readDirectory: (dir: string) => Promise<ReadonlyArray<WalkerEntry>>;
83
- /**
84
- * The type of the entry at `path`, or `null` when it does not exist or
85
- * cannot be read. Never rejects.
86
- */
87
- readonly statEntry: (path: string) => Promise<WalkerEntryStat | null>;
88
- }
89
- /**
90
- * What the walkers read off a `stat`: the entry's type, plus the modification
91
- * time the discovery cache's directory signature is built from.
92
- * @public
93
- */
94
- interface WalkerEntryStat {
95
- /** Whether the path holds a regular file. */
96
- readonly isFile: boolean;
97
- /** Whether the path holds a directory. */
98
- readonly isDirectory: boolean;
99
- /** Modification time in milliseconds since the epoch. */
100
- readonly mtimeMs: number;
101
- }
102
- /**
103
- * {@link WalkerFileSystem} over `node:fs/promises` — the binding every
104
- * production call site uses, and the default when a walker is called without
105
- * an explicit port.
106
- * @public
107
- */
108
- export declare const nodeWalkerFs: WalkerFileSystem;
109
33
  /**
110
34
  * Resolved metadata about a discovered test module.
111
35
  * @public
@@ -148,11 +72,12 @@ interface DiscoverInput {
148
72
  /** Parsed `package.json` contents, when available. */
149
73
  readonly packageJson?: PackageJson;
150
74
  /**
151
- * Filesystem port the walkers read through. Defaults to `node:fs` when
152
- * omitted, which is what every production call site does; tests inject a
153
- * virtual volume instead of building a real temporary directory.
75
+ * Sync filesystem the walkers read through (`@effected/walker`'s
76
+ * `WalkerSyncOps`). Defaults to its `nodeWalkerSyncOps` when omitted, which
77
+ * is what every production call site does; tests inject a virtual volume
78
+ * instead of building a real temporary directory.
154
79
  */
155
- readonly fs?: WalkerFileSystem;
80
+ readonly fs?: WalkerSyncOps$1;
156
81
  }
157
82
  /**
158
83
  * Context object passed to a `ClassifyFn`.
@@ -249,10 +174,12 @@ interface DiscoverProjectsOptions {
249
174
  readonly path: string;
250
175
  }>;
251
176
  /**
252
- * Filesystem port the test-file and signature walks read through. Defaults
253
- * to `node:fs`; tests inject a virtual volume instead of a real tmp tree.
177
+ * Sync filesystem the test-file and signature walks read through
178
+ * (`@effected/walker`'s `WalkerSyncOps`). Defaults to its
179
+ * `nodeWalkerSyncOps`; tests inject a virtual volume instead of a real tmp
180
+ * tree.
254
181
  */
255
- readonly fs?: WalkerFileSystem;
182
+ readonly fs?: WalkerSyncOps$1;
256
183
  /**
257
184
  * Sync operations `@effected/workspaces` resolves the workspace root and
258
185
  * package list through. Defaults to its `nodeSyncOps` binding.
@@ -532,26 +459,35 @@ export declare namespace AgentPlugin {
532
459
  configure?: ProjectConfigureMap;
533
460
  }): DiscoverBuilder;
534
461
  /**
535
- * Run a shell command, suppressing all output unless the command fails.
536
- * Designed for use in Vitest `globalSetup` files to run build steps or
537
- * other preparatory scripts without polluting agent stdout.
462
+ * Run a build step once, suppressing all output unless it fails. Designed
463
+ * for Vitest `globalSetup` files to run build steps or other preparatory
464
+ * scripts without polluting agent stdout.
538
465
  *
539
- * Concurrent invocations of the same command from the same workspace
540
- * (e.g. two `vitest` runs started in one checkout at once) serialize
541
- * through a file-based advisory lock (issue #191): the first caller
542
- * runs the command; a concurrent caller blocks until the lock frees,
543
- * then skips its own run when the winner's build is still fresh
544
- * (`DEFAULT_BUILT_RECENTLY_MS`) rather than repeating it.
466
+ * A string `command` runs through the platform shell (`/bin/sh -c`, or
467
+ * `cmd.exe /d /s /c` on Windows), as `execSync` ran it; an argv array runs
468
+ * the executable directly, with no shell. Output is captured to temporary
469
+ * files, so a chatty build never trips a buffer limit; the trailing 1 MiB
470
+ * of each stream is kept for the failure.
545
471
  *
546
- * Serialization is best-effort by design: a waiter that is still
547
- * blocked after `DEFAULT_LOCK_WAIT_TIMEOUT_MS` gives up and runs the
548
- * command anyway, unserialized, rather than hanging the caller's test
549
- * run forever. See `utils/run-script-lock.ts` for that escape valve
550
- * and for the two-tier (pid probe, then age) stale-takeover rule.
472
+ * Concurrent invocations of the same command from the same directory (two
473
+ * `vitest` runs started in one checkout at once) serialize through
474
+ * `@effected/commands`' `RunOnce` file lock, keyed by the working directory
475
+ * the command runs in plus the command (issue #191): the first
476
+ * caller runs the command, and a concurrent caller that waited on it skips
477
+ * its own run once that owner succeeds. A previous, sequential run is never
478
+ * trusted, so an edit followed by a re-run always rebuilds, unless
479
+ * `VITEST_AGENT_RUNSCRIPT_BUILT_RECENTLY_MS` opts into trusting a marker
480
+ * that young.
481
+ *
482
+ * Serialization is best-effort by design: a waiter still blocked after the
483
+ * wait timeout (10 minutes), or a caller that cannot create the lock at
484
+ * all, runs the command unserialized rather than hanging or failing.
485
+ * `VITEST_AGENT_RUNSCRIPT_LOCK_STALE_MS`, `_LOCK_WAIT_TIMEOUT_MS` and
486
+ * `_LOCK_POLL_MS` tune the protocol's timings.
551
487
  *
552
488
  * On failure the captured stderr and stdout are written to their respective
553
- * streams before rethrowing, so the error is still visible to humans and
554
- * surfaced in CI logs.
489
+ * streams before the `CommandFailedError` is thrown, so the error is still
490
+ * visible to humans and surfaced in CI logs.
555
491
  *
556
492
  * ```ts
557
493
  * // vitest.setup.ts
@@ -561,7 +497,7 @@ export declare namespace AgentPlugin {
561
497
  * }
562
498
  * ```
563
499
  */
564
- function runScript(command: string): void;
500
+ function runScript(command: string | readonly [string, ...string[]]): void;
565
501
  }
566
502
  /**
567
503
  * Constructor argument shape for {@link AgentReporter}.
@@ -731,6 +667,12 @@ export declare class AgentReporter {
731
667
  * (issue #576).
732
668
  */
733
669
  private rendered;
670
+ /**
671
+ * `performance.now()` at this run's `onTestRunStart`, for the run's
672
+ * execution time (issue #544). `undefined` when `onTestRunStart` never
673
+ * fired (tests invoking `onTestRunEnd` directly).
674
+ */
675
+ private runStartedAt;
734
676
  /**
735
677
  * Stored Vitest instance from {@link AgentReporter.onInit | onInit}.
736
678
  *
@@ -1307,27 +1249,30 @@ export declare function classifyByDirectory(dirMap: Record<string, ReadonlyArray
1307
1249
  */
1308
1250
  export declare function combineClassifiers(...fns: ReadonlyArray<ClassifyFn>): ClassifyFn;
1309
1251
  /**
1310
- * Async file walker that returns matched absolute paths.
1252
+ * File walker that returns matched absolute paths.
1311
1253
  *
1312
- * Walks `dir` recursively via `node:fs/promises`. Skips `node_modules`, `.git`,
1313
- * and `dist` directories, and does not descend past a nested `package.json`
1314
- * boundary (any directory other than `dir` itself that has its own
1315
- * `package.json` is treated as an independent unit — its files belong to a
1316
- * separate discovery pass, not this one). The package-boundary rule applies
1254
+ * Expands each pattern under `dir` with `@effected/walker`'s `descendSync`
1255
+ * over `ops` (default: `nodeWalkerSyncOps`). Skips `node_modules`, `.git`, and
1256
+ * `dist` directories, follows symlinked directories (a link loop is cut by
1257
+ * the walker's cycle guard), and does not descend past a nested
1258
+ * `package.json` boundary (any directory other than `dir` itself that has its
1259
+ * own `package.json` is treated as an independent unit — its files belong to
1260
+ * a separate discovery pass, not this one). The package-boundary rule applies
1317
1261
  * to every supplied pattern, not just an unanchored `**\/` one — an anchored
1318
1262
  * pattern like `"src/**\/*.test.ts"` will not match a test file under a
1319
1263
  * nested package.json even though the pattern itself never reaches past
1320
- * `src/`, because the boundary check runs once per directory, independent of
1321
- * which pattern is being matched. Matches files against the supplied glob
1322
- * patterns relative to `dir` (e.g. `"src/**\/*.test.ts"`).
1264
+ * `src/`. Matches files against the supplied glob patterns relative to `dir`
1265
+ * (e.g. `"src/**\/*.test.ts"`); a pattern that fails to compile matches
1266
+ * nothing.
1323
1267
  *
1324
1268
  * Returns an empty array if `dir` does not exist or no files match.
1325
1269
  * @param dir - Absolute path to the directory to walk
1326
1270
  * @param patterns - Glob patterns to match against (relative to `dir`)
1327
- * @returns Absolute paths of matched test files
1271
+ * @param ops - The sync filesystem the walk reads through
1272
+ * @returns Absolute paths of matched test files, each pattern's matches sorted, deduplicated across patterns
1328
1273
  * @public
1329
1274
  */
1330
- export declare function findTestFiles(dir: string, patterns: ReadonlyArray<string>, fs?: WalkerFileSystem): Promise<ReadonlyArray<string>>;
1275
+ export declare function findTestFiles(dir: string, patterns: ReadonlyArray<string>, ops?: WalkerSyncOps$1): Promise<ReadonlyArray<string>>;
1331
1276
  /**
1332
1277
  * Options passed to `CoverageAnalyzer.process` and `CoverageAnalyzer.processScoped`.
1333
1278
  *
@@ -1598,5 +1543,5 @@ export declare const COVERAGE_AUTOUPDATE: Readonly<{
1598
1543
  strict: (next: number, previous: number) => number;
1599
1544
  lenient: (next: number, previous: number) => number;
1600
1545
  }>;
1601
- export { type AddProjectInput, type AgentPluginConstructorOptions, type AgentReporterConstructorOptions, type ClassifyContext, type ClassifyFn, type CoverageInput, CoverageLevel, type CoverageLevelName, type CoverageLevelPreset, type CoverageOptions, type DiscoverBuilder, type DiscoverInput, type PackageJson as DiscoverPackageJson, type DiscoverProjectsOptions, type DiscoverProjectsResult, type DiscoverResult, type DiscoverStrategyCreateOptions, type DiscoverStrategyExtendOptions, type InjectTagsResult, type ModuleInfo, type ProjectConfigureMap, type ProjectTestOverrides, type TagOptions, type ValidationError, type ValidationInfo, type ValidationInput, type ValidationResult, type ValidationWarning, type VitestErrorLike, type VitestStackFrameLike, type VitestThresholdsInput, type WalkerEntry, type WalkerEntryStat, type WalkerFileSystem, resolveCoverageInput, validateCoverageConfig };
1546
+ export { type AddProjectInput, type AgentPluginConstructorOptions, type AgentReporterConstructorOptions, type ClassifyContext, type ClassifyFn, type CoverageInput, CoverageLevel, type CoverageLevelName, type CoverageLevelPreset, type CoverageOptions, type DiscoverBuilder, type DiscoverInput, type PackageJson as DiscoverPackageJson, type DiscoverProjectsOptions, type DiscoverProjectsResult, type DiscoverResult, type DiscoverStrategyCreateOptions, type DiscoverStrategyExtendOptions, type InjectTagsResult, type ModuleInfo, type ProjectConfigureMap, type ProjectTestOverrides, type TagOptions, type ValidationError, type ValidationInfo, type ValidationInput, type ValidationResult, type ValidationWarning, type VitestErrorLike, type VitestStackFrameLike, type VitestThresholdsInput, type WalkerSyncOps, resolveCoverageInput, validateCoverageConfig };
1602
1547
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -9,7 +9,6 @@ import { captureSettings, hashSettings } from "./utils/capture-settings.js";
9
9
  import { processFailure } from "./utils/process-failure.js";
10
10
  import { ConfigurationError } from "./utils/configuration-error.js";
11
11
  import { AgentReporter } from "./reporter.js";
12
- import { nodeWalkerFs } from "./utils/walker-fs.js";
13
12
  import { findTestFiles } from "./utils/find-test-files.js";
14
13
  import { Tag } from "./utils/tag.js";
15
14
  import { DefaultDiscoverStrategy, DiscoverStrategy } from "./utils/discover-strategy.js";
@@ -30,4 +29,4 @@ const COVERAGE_LEVELS_PER_FILE = AgentPlugin.COVERAGE_LEVELS_PER_FILE;
30
29
  /** Auto-update tolerance functions for `coverage.thresholds.autoUpdate`. Mirrors `AgentPlugin.COVERAGE_AUTOUPDATE`. @public */
31
30
  const COVERAGE_AUTOUPDATE = AgentPlugin.COVERAGE_AUTOUPDATE;
32
31
 
33
- export { AgentPlugin, AgentReporter, CONSOLE_REPORTERS, COVERAGE_AUTOUPDATE, COVERAGE_LEVELS, COVERAGE_LEVELS_PER_FILE, CURRENT_PLUGIN_VERSION, ConfigValidation, ConfigValidationLive, ConfigValidationTest, ConfigurationError, CoverageAnalyzer, CoverageAnalyzerLive, CoverageAnalyzerTest, CoverageLevel, DefaultDiscoverStrategy, DiscoverStrategy, ReporterLive, Tag, applyProjectOverrides, captureEnvVars, captureSettings, classifyByDirectory, classifyByFilename, combineClassifiers, discoverProjects, findTestFiles, hashSettings, nodeWalkerFs, processFailure, resolveCoverageInput, resolveThresholds, stripConsoleReporters, validateCoverageConfig };
32
+ export { AgentPlugin, AgentReporter, CONSOLE_REPORTERS, COVERAGE_AUTOUPDATE, COVERAGE_LEVELS, COVERAGE_LEVELS_PER_FILE, CURRENT_PLUGIN_VERSION, ConfigValidation, ConfigValidationLive, ConfigValidationTest, ConfigurationError, CoverageAnalyzer, CoverageAnalyzerLive, CoverageAnalyzerTest, CoverageLevel, DefaultDiscoverStrategy, DiscoverStrategy, ReporterLive, Tag, applyProjectOverrides, captureEnvVars, captureSettings, classifyByDirectory, classifyByFilename, combineClassifiers, discoverProjects, findTestFiles, hashSettings, processFailure, resolveCoverageInput, resolveThresholds, stripConsoleReporters, validateCoverageConfig };
@@ -1,7 +1,7 @@
1
1
  import { CoverageAnalyzer } from "../services/CoverageAnalyzer.js";
2
2
  import { toPosixPath } from "../utils/to-posix-path.js";
3
3
  import { relative } from "node:path";
4
- import { compressLines } from "@vitest-agent/sdk";
4
+ import { Fmt } from "@effected/cli";
5
5
  import { Effect, Layer, Option, Result } from "effect";
6
6
  import { GlobPattern } from "@effected/glob";
7
7
 
@@ -253,7 +253,7 @@ function processCoverageInternal(coverageMap, options, testedFiles) {
253
253
  if (scoped && !testedFileSet?.has(toPosixPath(filePath))) continue;
254
254
  const isBelowThreshold = isBelowMetricThresholds(fileStats, resolveEffectivePerFileThresholds(matchPath, options.thresholds) ?? resolveEffectiveThresholds(matchPath, options.thresholds));
255
255
  if (isBareZero || isBelowThreshold) {
256
- const uncoveredLines = compressLines(fileCoverage.getUncoveredLines());
256
+ const uncoveredLines = Fmt.ranges(fileCoverage.getUncoveredLines());
257
257
  lowCoverage.push({
258
258
  file: filePath,
259
259
  summary: fileStats,
@@ -263,7 +263,7 @@ function processCoverageInternal(coverageMap, options, testedFiles) {
263
263
  }
264
264
  if (options.targets) {
265
265
  if (isBelowMetricThresholds(fileStats, resolveEffectivePerFileThresholds(matchPath, options.targets) ?? resolveEffectiveThresholds(matchPath, options.targets))) {
266
- const uncoveredLines = compressLines(fileCoverage.getUncoveredLines());
266
+ const uncoveredLines = Fmt.ranges(fileCoverage.getUncoveredLines());
267
267
  belowTarget.push({
268
268
  file: filePath,
269
269
  summary: fileStats,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest-agent/plugin",
3
- "version": "5.6.2",
3
+ "version": "6.0.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": [
@@ -44,24 +44,33 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@effect/platform-node": "^4.0.6",
47
- "@effected/cli": "^0.22.2",
48
- "@effected/env": "^0.5.0",
49
- "@effected/glob": "^0.14.0",
50
- "@effected/walker": "^0.20.1",
51
- "@effected/workspaces": "^0.39.0",
52
- "@vitest-agent/cli": "4.1.3",
53
- "@vitest-agent/engine": "2.1.0",
54
- "@vitest-agent/mcp": "5.4.0",
55
- "@vitest-agent/reporter": "6.0.2",
56
- "@vitest-agent/sdk": "8.0.0",
47
+ "@effected/cli": "^0.23.0",
48
+ "@effected/commands": "^0.17.0",
49
+ "@effected/env": "^0.6.0",
50
+ "@effected/glob": "^0.15.0",
51
+ "@effected/walker": "^0.21.0",
52
+ "@effected/workspaces": "^0.39.1",
53
+ "@vitest-agent/cli": "4.1.4",
54
+ "@vitest-agent/engine": "3.0.0",
55
+ "@vitest-agent/mcp": "6.0.0",
56
+ "@vitest-agent/reporter": "6.1.0",
57
+ "@vitest-agent/sdk": "9.0.0",
57
58
  "effect": "^4.0.6",
58
- "magic-string": "^1.4.3"
59
+ "magic-string": "^1.4.4"
59
60
  },
60
61
  "peerDependencies": {
61
62
  "@vitest/coverage-istanbul": "^5.0.0",
62
63
  "@vitest/coverage-v8": "^5.0.0",
63
64
  "vitest": "^5.0.0"
64
65
  },
66
+ "peerDependenciesMeta": {
67
+ "@vitest/coverage-istanbul": {
68
+ "optional": true
69
+ },
70
+ "@vitest/coverage-v8": {
71
+ "optional": true
72
+ }
73
+ },
65
74
  "engines": {
66
75
  "node": ">=24.11.0"
67
76
  }
package/plugin.js CHANGED
@@ -14,20 +14,21 @@ import { injectTags } from "./utils/inject-tags.js";
14
14
  import { isBenignViteSourceMapWarning } from "./utils/is-benign-vite-source-map-warning.js";
15
15
  import { resolveCoverageDirIsolation } from "./utils/resolve-coverage-dir-isolation.js";
16
16
  import { PERSIST_ENV_VAR, resolvePersistence } from "./utils/resolve-persistence.js";
17
- import { DEFAULT_BUILT_RECENTLY_MS, DEFAULT_LOCK_STALE_MS, DEFAULT_LOCK_WAIT_TIMEOUT_MS, acquireRunScriptLock, markRunScriptDone, parseLockTimingOverride, releaseRunScriptLock } from "./utils/run-script-lock.js";
17
+ import { runScriptOptions, shellCommand } from "./utils/run-script-lock.js";
18
18
  import { stripConsoleReporters } from "./utils/strip-console-reporters.js";
19
19
  import { makeTagCacheKeyGenerator } from "./utils/tag-cache-key.js";
20
20
  import { readVitestVersion, vitestPeerVersionMismatchMessage } from "./utils/vitest-peer-version-mismatch-error.js";
21
21
  import { CURRENT_PLUGIN_VERSION } from "./version.js";
22
- import { execSync } from "node:child_process";
23
22
  import { mkdtempSync, rmSync } from "node:fs";
24
23
  import { tmpdir } from "node:os";
25
24
  import { join } from "node:path";
26
25
  import { CliLog } from "@effected/cli";
26
+ import { RunOnce } from "@effected/commands";
27
+ import { nodeRunOnceHost } from "@effected/commands/node-sync";
27
28
  import { Audience, EnvOverride } from "@effected/env";
28
- import { EnvironmentDetector, EnvironmentDetectorLive, ExecutorResolver, ExecutorResolverLive, LoggerLive, resolveLogLevel } from "@vitest-agent/engine";
29
- import { AgentConsoleMode, CiConsoleMode, CoverageLevel, HumanConsoleMode, SRC_DIR, TEST_DIR, formatFatalError, isTestFileName } from "@vitest-agent/sdk";
30
- import { Effect, Layer, Option } from "effect";
29
+ import { EnvironmentDetector, EnvironmentDetectorLive, ExecutorResolver, ExecutorResolverLive, LoggerLive, formatFatalError, resolveLogLevel } from "@vitest-agent/engine";
30
+ import { AgentConsoleMode, CiConsoleMode, CoverageLevel, HumanConsoleMode, SRC_DIR, TEST_DIR, isTestFileName } from "@vitest-agent/sdk";
31
+ import { Effect, Layer, Option, Result } from "effect";
31
32
 
32
33
  // src/plugin.ts
33
34
  /**
@@ -439,38 +440,14 @@ function makeDiscoverBuilder(options) {
439
440
  });
440
441
  }
441
442
  _AgentPlugin.discover = discover;
442
- /**
443
- * Parses a `VITEST_AGENT_RUNSCRIPT_*` override env var, falling back to
444
- * `fallback` for anything that is not a whole positive integer at or above
445
- * `minimum`. Test-support: lets the concurrency e2e suite use short timeouts
446
- * instead of the production-sized defaults — but a typo there (`"200ms"`,
447
- * `"-1"`, `"0"`) must degrade to the default rather than to an
448
- * instantly-stale lock or a busy-spinning waiter.
449
- */
450
- function readRunScriptLockEnvOverride(name, fallback, minimum = 1) {
451
- return parseLockTimingOverride(process.env[name], fallback, minimum);
452
- }
453
443
  function runScript(command) {
454
- const lock = acquireRunScriptLock({
455
- cwd: process.cwd(),
456
- command,
457
- staleMs: readRunScriptLockEnvOverride("VITEST_AGENT_RUNSCRIPT_LOCK_STALE_MS", DEFAULT_LOCK_STALE_MS),
458
- waitTimeoutMs: readRunScriptLockEnvOverride("VITEST_AGENT_RUNSCRIPT_LOCK_WAIT_TIMEOUT_MS", DEFAULT_LOCK_WAIT_TIMEOUT_MS),
459
- pollMs: readRunScriptLockEnvOverride("VITEST_AGENT_RUNSCRIPT_LOCK_POLL_MS", 200, 10),
460
- builtRecentlyMs: readRunScriptLockEnvOverride("VITEST_AGENT_RUNSCRIPT_BUILT_RECENTLY_MS", DEFAULT_BUILT_RECENTLY_MS)
461
- });
462
- if (lock.recentlyBuilt) return;
463
- try {
464
- execSync(command, { stdio: "pipe" });
465
- markRunScriptDone(lock);
466
- } catch (error) {
467
- const execError = error;
468
- if (execError.stderr?.length) process.stderr.write(execError.stderr);
469
- if (execError.stdout?.length) process.stdout.write(execError.stdout);
470
- throw error;
471
- } finally {
472
- releaseRunScriptLock(lock);
473
- }
444
+ const run = typeof command === "string" ? shellCommand(command, process.platform, process.env) : { argv: command };
445
+ const outcome = RunOnce.commandSync(runScriptOptions(command, process.cwd(), process.env), nodeRunOnceHost, run);
446
+ if (Result.isSuccess(outcome)) return;
447
+ const failure = outcome.failure;
448
+ if (failure.stderr !== void 0 && failure.stderr.length > 0) process.stderr.write(failure.stderr);
449
+ if (failure.stdout !== void 0 && failure.stdout.length > 0) process.stdout.write(failure.stdout);
450
+ throw failure;
474
451
  }
475
452
  _AgentPlugin.runScript = runScript;
476
453
  })(AgentPlugin || (AgentPlugin = {}));