@vitest-agent/plugin 5.5.0 → 5.6.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.
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import "@effected/env";
2
2
  import { EnvironmentDetector, PlatformLiveError, PlatformOptions, PlatformServices, SettingsInput, StackFrameInput } from "@vitest-agent/engine";
3
- import { AgentPluginOptions, AgentReporterOptions, ConsoleMode, CoverageBaselines, CoverageInput, CoverageLevel, CoverageLevelName, CoverageLevelName as CoverageLevelName$1, CoverageReport, ResolvedReporterConfig, ResolvedThresholds, RunEvent, RunRetentionPolicy, Transport, VitestAgentReporterFactory, resolveCoverageInput, validateCoverageConfig } from "@vitest-agent/sdk";
3
+ import { AgentPluginOptions, AgentReporterOptions, ConsoleMode, CoverageBaselines, CoverageInput, CoverageLevel, CoverageLevelName, CoverageLevelName as CoverageLevelName$1, CoverageReport, ResolvedReporterConfig, ResolvedThresholds, RunEvent, RunRetentionPolicy, SuggestedActionRecord, Transport, VitestAgentReporterFactory, resolveCoverageInput, validateCoverageConfig } from "@vitest-agent/sdk";
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";
@@ -631,6 +631,17 @@ interface AgentReporterConstructorOptions extends AgentReporterOptions {
631
631
  * `run_tests` tool.
632
632
  */
633
633
  passWithNoTests?: boolean;
634
+ /**
635
+ * Run-level suggested actions the plugin resolved at config time — the
636
+ * `ConfigValidation` warnings and info entries, mapped onto
637
+ * `SuggestedActionRecord`s (issue #544). Forwarded verbatim onto
638
+ * `ReporterRenderInput.suggestedActions` for every render, so the
639
+ * `Actions:` trailer repeats them in watch mode. Absent when the config
640
+ * validated clean.
641
+ *
642
+ * @internal
643
+ */
644
+ suggestedActions?: ReadonlyArray<SuggestedActionRecord>;
634
645
  coverageThresholds?: ResolvedThresholds | Record<string, unknown>;
635
646
  coverageTargets?: ResolvedThresholds | Record<string, unknown>;
636
647
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest-agent/plugin",
3
- "version": "5.5.0",
3
+ "version": "5.6.0",
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": [
@@ -49,11 +49,11 @@
49
49
  "@effected/glob": "^0.14.0",
50
50
  "@effected/walker": "^0.19.0",
51
51
  "@effected/workspaces": "^0.38.0",
52
- "@vitest-agent/cli": "4.1.0",
53
- "@vitest-agent/engine": "1.2.0",
54
- "@vitest-agent/mcp": "5.2.10",
55
- "@vitest-agent/reporter": "5.0.9",
56
- "@vitest-agent/sdk": "7.1.0",
52
+ "@vitest-agent/cli": "4.1.1",
53
+ "@vitest-agent/engine": "2.0.0",
54
+ "@vitest-agent/mcp": "5.3.0",
55
+ "@vitest-agent/reporter": "6.0.0",
56
+ "@vitest-agent/sdk": "8.0.0",
57
57
  "effect": "^4.0.6",
58
58
  "magic-string": "^1.4.3"
59
59
  },
package/plugin.js CHANGED
@@ -6,6 +6,7 @@ import { assertFlatScope } from "./utils/report-writer.js";
6
6
  import { installStrayOutputCapture } from "./utils/stray-output-capture.js";
7
7
  import { AgentReporter } from "./reporter.js";
8
8
  import { buildModuleInfo } from "./utils/build-module-info.js";
9
+ import { publishConfigSuggestedActions, suggestedActionsFromValidation } from "./utils/config-suggested-actions.js";
9
10
  import { DefaultDiscoverStrategy } from "./utils/discover-strategy.js";
10
11
  import { discoverProjects } from "./utils/discover-projects.js";
11
12
  import { ensureGithubActionsReporter } from "./utils/ensure-github-reporter.js";
@@ -216,11 +217,15 @@ function AgentPlugin(options = {}, _layer) {
216
217
  ctx.defineCacheKeyGenerator(makeTagCacheKeyGenerator(classifyForCache));
217
218
  log("registered fsModuleCache tag cache-key generator");
218
219
  }
219
- const { env, executor } = await Effect.runPromise(Effect.gen(function* () {
220
- const env = yield* (yield* EnvironmentDetector).detect();
220
+ const { env, executor, inGithubActions } = await Effect.runPromise(Effect.gen(function* () {
221
+ const detector = yield* EnvironmentDetector;
222
+ const env = yield* detector.detect();
223
+ const executor = yield* (yield* ExecutorResolver).resolve(env);
224
+ const ci = yield* detector.ci;
221
225
  return {
222
226
  env,
223
- executor: yield* (yield* ExecutorResolver).resolve(env)
227
+ executor,
228
+ inGithubActions: Option.contains(ci, "github-actions")
224
229
  };
225
230
  }).pipe(Effect.provide(Layer.merge(layer, ExecutorResolverLive))));
226
231
  const reportOption = options.report;
@@ -254,17 +259,19 @@ function AgentPlugin(options = {}, _layer) {
254
259
  stderr: process.stderr
255
260
  });
256
261
  }
257
- if (env === "ci-github" && consoleMode !== "silent") {
262
+ const githubActions = inGithubActions && consoleMode !== "silent";
263
+ if (githubActions) {
258
264
  log("normalizing the github-actions reporter entry");
259
265
  const withGithubActions = ensureGithubActionsReporter(vitest.config.reporters);
260
266
  vitest.config.reporters = withGithubActions;
261
267
  }
262
- const githubActions = env === "ci-github" && consoleMode !== "silent";
263
268
  log("githubActions (auto):", githubActions);
264
269
  const validation = await Effect.runPromise(Effect.provide(Effect.flatMap(ConfigValidation, (cv) => cv.validate({
265
270
  vitestConfig: vitest.config,
266
271
  pluginOptions: options
267
272
  })), ConfigValidationLive));
273
+ const configSuggestedActions = suggestedActionsFromValidation(validation);
274
+ publishConfigSuggestedActions(vitest, configSuggestedActions);
268
275
  for (const w of validation.warnings) reportOnce(`[vitest-agent:plugin] warning ${w.code}: ${w.message}` + (w.remediation ? `\n ${w.remediation}` : "") + "\n");
269
276
  for (const i of validation.info) reportOnce(`[vitest-agent:plugin] info ${i.code}: ${i.message}\n`);
270
277
  if (validation.errors.length > 0) {
@@ -328,6 +335,7 @@ function AgentPlugin(options = {}, _layer) {
328
335
  ...reportScope !== void 0 && { reportScope },
329
336
  transport,
330
337
  ...passWithNoTests !== void 0 ? { passWithNoTests } : {},
338
+ ...configSuggestedActions.length > 0 ? { suggestedActions: configSuggestedActions } : {},
331
339
  ...options.reporter !== void 0 && { reporter: options.reporter },
332
340
  ...options.onRunEvent !== void 0 ? { onRunEvent: options.onRunEvent } : {}
333
341
  });
package/reporter.js CHANGED
@@ -495,7 +495,8 @@ var AgentReporter = class {
495
495
  coverageMode: options.coverageMode ?? "full",
496
496
  persist: options.persist ?? true,
497
497
  transport: options.transport ?? { kind: "local" },
498
- ...options.passWithNoTests !== void 0 ? { passWithNoTests: options.passWithNoTests } : {}
498
+ ...options.passWithNoTests !== void 0 ? { passWithNoTests: options.passWithNoTests } : {},
499
+ ...options.suggestedActions !== void 0 && options.suggestedActions.length > 0 ? { suggestedActions: options.suggestedActions } : {}
499
500
  };
500
501
  this.options = resolvedTargets ? {
501
502
  ...base,
@@ -1343,7 +1344,8 @@ var AgentReporter = class {
1343
1344
  const reporters = preBuiltReporters ?? normalizeReporters(opts.reporter(kit));
1344
1345
  const renderInput = {
1345
1346
  reports: withStrayOutput(reports, strayOutput),
1346
- classifications: /* @__PURE__ */ new Map()
1347
+ classifications: /* @__PURE__ */ new Map(),
1348
+ ...opts.suggestedActions !== void 0 && { suggestedActions: opts.suggestedActions }
1347
1349
  };
1348
1350
  const allOutputs = reporters.flatMap((r) => r.render(renderInput, kit));
1349
1351
  for (const output of allOutputs) routeRenderedOutput(output, {
@@ -1448,7 +1450,8 @@ var AgentReporter = class {
1448
1450
  gitCommitSha: process.env.GITHUB_SHA ?? null,
1449
1451
  hostSource: hostProbe.source,
1450
1452
  hostValue: hostProbe.value,
1451
- hostMetadata: hostProbe.metadata
1453
+ hostMetadata: hostProbe.metadata,
1454
+ strayOutput: strayOutput ?? null
1452
1455
  });
1453
1456
  for (const mod of projectModules) {
1454
1457
  const fileId = yield* store.ensureFile(mod.relativeModuleId);
@@ -1852,6 +1855,7 @@ var AgentReporter = class {
1852
1855
  const renderInput = {
1853
1856
  reports: withStrayOutput(reports, strayOutput),
1854
1857
  classifications,
1858
+ ...opts.suggestedActions !== void 0 && { suggestedActions: opts.suggestedActions },
1855
1859
  ...trendSummary !== void 0 && { trendSummary }
1856
1860
  };
1857
1861
  const allOutputs = reporters.flatMap((r) => r.render(renderInput, kit));
@@ -1,38 +1,33 @@
1
- import { osc8 } from "@vitest-agent/sdk";
2
-
3
1
  // src/utils/build-reporter-kit.ts
4
2
  const buildReporterKit = (input) => {
5
3
  const consoleOutput = input.consoleMode === "silent" ? "silent" : "failures";
6
4
  const githubSummary = input.githubActions;
7
5
  const githubSummaryFile = process.env.GITHUB_STEP_SUMMARY;
8
- const config = {
9
- executor: input.executor,
10
- consoleMode: input.consoleMode,
11
- mcp: input.mcp,
12
- consoleOutput,
13
- omitPassingTests: true,
14
- coverageConsoleLimit: 10,
15
- includeBareZero: false,
16
- githubActions: input.githubActions,
17
- githubSummary,
18
- detail: input.detail,
19
- noColor: input.noColor,
20
- coverageMode: input.coverageMode,
21
- persist: input.persist,
22
- transport: input.transport,
23
- ...input.dbPath !== void 0 && { dbPath: input.dbPath },
24
- ...input.projectFilter !== void 0 && { projectFilter: input.projectFilter },
25
- ...githubSummaryFile !== void 0 && { githubSummaryFile },
26
- ...input.runCommand !== void 0 && { runCommand: input.runCommand },
27
- ...input.coverageThresholds !== void 0 && { coverageThresholds: input.coverageThresholds },
28
- ...input.coverageTargets !== void 0 && { coverageTargets: input.coverageTargets },
29
- ...input.passWithNoTests !== void 0 && { passWithNoTests: input.passWithNoTests }
30
- };
31
- const osc8Enabled = !input.noColor && (input.env === "terminal" || input.env === "agent-shell");
32
6
  return {
33
- config,
7
+ config: {
8
+ executor: input.executor,
9
+ consoleMode: input.consoleMode,
10
+ mcp: input.mcp,
11
+ consoleOutput,
12
+ omitPassingTests: true,
13
+ coverageConsoleLimit: 10,
14
+ includeBareZero: false,
15
+ githubActions: input.githubActions,
16
+ githubSummary,
17
+ detail: input.detail,
18
+ noColor: input.noColor,
19
+ coverageMode: input.coverageMode,
20
+ persist: input.persist,
21
+ transport: input.transport,
22
+ ...input.dbPath !== void 0 && { dbPath: input.dbPath },
23
+ ...input.projectFilter !== void 0 && { projectFilter: input.projectFilter },
24
+ ...githubSummaryFile !== void 0 && { githubSummaryFile },
25
+ ...input.runCommand !== void 0 && { runCommand: input.runCommand },
26
+ ...input.coverageThresholds !== void 0 && { coverageThresholds: input.coverageThresholds },
27
+ ...input.coverageTargets !== void 0 && { coverageTargets: input.coverageTargets },
28
+ ...input.passWithNoTests !== void 0 && { passWithNoTests: input.passWithNoTests }
29
+ },
34
30
  stdEnv: input.env,
35
- stdOsc8: (url, label) => osc8(url, label, { enabled: osc8Enabled }),
36
31
  ...input.runEvents !== void 0 && { runEvents: input.runEvents }
37
32
  };
38
33
  };
@@ -0,0 +1,42 @@
1
+ // src/utils/config-suggested-actions.ts
2
+ /**
3
+ * The `Symbol.for` key under which `configureVitest` publishes the run's
4
+ * config-derived suggested actions on the Vitest instance. `Symbol.for`
5
+ * resolves to the identical symbol across module copies in one process, so
6
+ * the MCP `run_tests` tool reads the same slot off the Vitest instance it
7
+ * created (mirrors the discovery last-scan slot).
8
+ *
9
+ * @internal
10
+ */
11
+ const CONFIG_SUGGESTED_ACTIONS_SYMBOL = Symbol.for("vitest-agent:config-suggested-actions");
12
+ /**
13
+ * Map a `ValidationResult`'s warnings and info entries onto suggested
14
+ * actions, in the order the validator produced them. A warning becomes a
15
+ * `warn` action and an info entry an `info` action; the title names the
16
+ * rule code, the detail carries the message followed by the remediation
17
+ * when the rule has one. No `targetTool` — there is no MCP tool that edits
18
+ * the Vitest config.
19
+ *
20
+ * @internal
21
+ */
22
+ const suggestedActionsFromValidation = (result) => [...result.warnings.map((w) => ({
23
+ severity: "warn",
24
+ title: `Coverage config: ${w.code}`,
25
+ detail: w.remediation !== void 0 ? `${w.message} ${w.remediation}` : w.message
26
+ })), ...result.info.map((i) => ({
27
+ severity: "info",
28
+ title: `Coverage config: ${i.code}`,
29
+ detail: i.message
30
+ }))];
31
+ /**
32
+ * Publish the run's config-derived suggested actions on the Vitest instance
33
+ * for readers in the same process (the MCP `run_tests` tool). An empty list
34
+ * clears the slot so a watch-mode rerun after a config fix reports nothing.
35
+ *
36
+ * @internal
37
+ */
38
+ const publishConfigSuggestedActions = (vitest, actions) => {
39
+ vitest[CONFIG_SUGGESTED_ACTIONS_SYMBOL] = actions.length > 0 ? actions : void 0;
40
+ };
41
+
42
+ export { CONFIG_SUGGESTED_ACTIONS_SYMBOL, publishConfigSuggestedActions, suggestedActionsFromValidation };
package/version.js CHANGED
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @public
10
10
  */
11
- const CURRENT_PLUGIN_VERSION = "5.5.0";
11
+ const CURRENT_PLUGIN_VERSION = "5.6.0";
12
12
 
13
13
  export { CURRENT_PLUGIN_VERSION };