@vitest-agent/mcp 4.2.2 → 4.3.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/tools/trends.js CHANGED
@@ -1,5 +1,4 @@
1
- import { RenderText } from "../annotations.js";
2
- import { Effect, Option, Schema, SchemaGetter } from "effect";
1
+ import { Effect, Option, Schema } from "effect";
3
2
  import { DataReader } from "@vitest-agent/engine";
4
3
  import { Tool } from "effect/unstable/ai";
5
4
  import { TrendRecord } from "@vitest-agent/sdk";
@@ -24,71 +23,6 @@ const TestTrendsResult = Schema.Union([TrendsAvailable, TrendsAbsent]).annotate(
24
23
  title: "test_trends result",
25
24
  description: "Coverage trend record per project. Discriminate on `dataAvailable` to handle the cold-start case."
26
25
  });
27
- const SPARKLINE_CHARS = [
28
- "▁",
29
- "▂",
30
- "▃",
31
- "▄",
32
- "▅",
33
- "▆",
34
- "▇",
35
- "█"
36
- ];
37
- function toSparkline(values) {
38
- if (values.length === 0) return "";
39
- const min = Math.min(...values);
40
- const range = Math.max(...values) - min;
41
- return values.map((v) => {
42
- const index = range === 0 ? 4 : Math.round((v - min) / range * (SPARKLINE_CHARS.length - 1));
43
- return SPARKLINE_CHARS[index] ?? "▄";
44
- }).join("");
45
- }
46
- const directionIcon = (d) => d === "improving" ? "📈" : d === "regressing" ? "📉" : "➡️";
47
- const formatTestTrendsMarkdown = (data) => {
48
- if (data.dataAvailable === false) return `No trend data available for project \`${data.project}\`. Run tests multiple times to build trend history.`;
49
- const entries = data.trends.entries;
50
- const latest = entries[entries.length - 1];
51
- if (latest === void 0) return `No trend data available for project \`${data.project}\`.`;
52
- const lines = [`# Coverage Trends: ${data.project}`, ""];
53
- lines.push(`${directionIcon(latest.direction)} **Overall direction:** ${latest.direction} over ${entries.length} run${entries.length === 1 ? "" : "s"}`);
54
- lines.push("", "## Latest Coverage", "", "| Metric | Value | Δ |", "| --- | --- | --- |");
55
- const metrics = [
56
- "statements",
57
- "branches",
58
- "functions",
59
- "lines"
60
- ];
61
- for (const metric of metrics) {
62
- const value = latest.coverage[metric];
63
- const delta = latest.delta[metric];
64
- const deltaStr = delta > 0 ? `+${delta.toFixed(2)}%` : delta < 0 ? `${delta.toFixed(2)}%` : "—";
65
- const deltaIcon = delta > .1 ? "↑" : delta < -.1 ? "↓" : "";
66
- lines.push(`| ${metric} | ${value.toFixed(2)}% | ${deltaIcon} ${deltaStr} |`);
67
- }
68
- lines.push("");
69
- if (entries.length >= 2) {
70
- lines.push("## Trajectory", "");
71
- for (const metric of metrics) {
72
- const values = entries.map((e) => e.coverage[metric]);
73
- lines.push(`- **${metric}**: \`${toSparkline(values)}\``);
74
- }
75
- lines.push("");
76
- }
77
- const recentEntries = entries.slice(-10);
78
- if (recentEntries.length > 0) {
79
- lines.push("## Recent Runs", "", "| Date | Lines | Branches | Functions | Statements | Direction |", "| --- | --- | --- | --- | --- | --- |");
80
- for (const entry of recentEntries) {
81
- const date = new Date(entry.timestamp).toLocaleDateString();
82
- lines.push(`| ${date} | ${entry.coverage.lines.toFixed(1)}% | ${entry.coverage.branches.toFixed(1)}% | ${entry.coverage.functions.toFixed(1)}% | ${entry.coverage.statements.toFixed(1)}% | ${directionIcon(entry.direction)} |`);
83
- }
84
- lines.push("");
85
- }
86
- return lines.join("\n");
87
- };
88
- const TestTrendsAsMarkdown = TestTrendsResult.pipe(Schema.decodeTo(Schema.String, {
89
- decode: SchemaGetter.transform((data) => formatTestTrendsMarkdown(data)),
90
- encode: SchemaGetter.forbidden(() => "TestTrendsAsMarkdown is one-way: markdown cannot be parsed back to TestTrendsResult.")
91
- }));
92
26
  /**
93
27
  * The `test_trends` tool's parameters.
94
28
  *
@@ -121,11 +55,11 @@ const handleTestTrends = (input) => Effect.gen(function* () {
121
55
  * @public
122
56
  */
123
57
  const testTrendsTool = Tool.make("test_trends", {
124
- description: "Use when you want to see whether a project's coverage is trending up or down over time. Returns markdown in content[] and a typed JSON object in structuredContent ({ dataAvailable, project, trends? }).",
58
+ description: "Use when you want to see whether a project's coverage is trending up or down over time. Returns a typed JSON object in structuredContent ({ dataAvailable, project, trends? }).",
125
59
  parameters: TestTrendsInput,
126
60
  success: TestTrendsResult,
127
61
  dependencies: [DataReader]
128
- }).annotate(Tool.Title, "Test trends").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.OpenWorld, false).annotate(Tool.Idempotent, true).annotate(RenderText, (encoded) => formatTestTrendsMarkdown(encoded));
62
+ }).annotate(Tool.Title, "Test trends").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.OpenWorld, false).annotate(Tool.Idempotent, true);
129
63
 
130
64
  //#endregion
131
- export { TestTrendsInput, TestTrendsResult, formatTestTrendsMarkdown, handleTestTrends, testTrendsTool };
65
+ export { TestTrendsInput, TestTrendsResult, handleTestTrends, testTrendsTool };
@@ -1,4 +1,3 @@
1
- import { RenderText } from "../annotations.js";
2
1
  import { Effect, Schema } from "effect";
3
2
  import { DataReader, formatTriageEffect } from "@vitest-agent/engine";
4
3
  import { Tool } from "effect/unstable/ai";
@@ -45,17 +44,16 @@ const handleTriageBrief = (input) => Effect.gen(function* () {
45
44
  };
46
45
  });
47
46
  /**
48
- * The Effect-native `triage_brief` tool. The text channel is the
49
- * pre-rendered `markdown` field itself.
47
+ * The Effect-native `triage_brief` tool.
50
48
  *
51
49
  * @public
52
50
  */
53
51
  const triageBriefTool = Tool.make("triage_brief", {
54
- description: "Use when you need to orient on the current test landscape: failing tests, flaky tests, open TDD sessions, and suggested next actions. Returns markdown in content[] and a typed envelope in structuredContent ({ hasContent, markdown }).",
52
+ description: "Use when you need to orient on the current test landscape: failing tests, flaky tests, open TDD sessions, and suggested next actions. Returns a typed envelope in structuredContent ({ hasContent, markdown }).",
55
53
  parameters: TriageBriefInput,
56
54
  success: TriageBriefResult,
57
55
  dependencies: [DataReader]
58
- }).annotate(Tool.Title, "Triage brief").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.OpenWorld, false).annotate(Tool.Idempotent, true).annotate(RenderText, (encoded) => encoded.markdown);
56
+ }).annotate(Tool.Title, "Triage brief").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.OpenWorld, false).annotate(Tool.Idempotent, true);
59
57
 
60
58
  //#endregion
61
59
  export { TriageBriefInput, TriageBriefResult, handleTriageBrief, triageBriefTool };
@@ -1,5 +1,4 @@
1
- import { RenderText } from "../annotations.js";
2
- import { Effect, Schema, SchemaGetter } from "effect";
1
+ import { Effect, Schema } from "effect";
3
2
  import { DataReader } from "@vitest-agent/engine";
4
3
  import { Tool } from "effect/unstable/ai";
5
4
 
@@ -28,16 +27,6 @@ const TurnSearchResult = Schema.Struct({
28
27
  title: "turn_search result",
29
28
  description: "Turn-log search results across all sessions, optionally filtered by session, time, type."
30
29
  });
31
- const formatTurnSearchMarkdown = (data) => {
32
- if (data.turns.length === 0) return "No turns matched.";
33
- const lines = ["# Turns", ""];
34
- for (const t of data.turns) lines.push(`- session=${t.sessionId} turn=${t.turnNo} type=${t.type} at=${t.occurredAt}`);
35
- return lines.join("\n");
36
- };
37
- const TurnSearchAsMarkdown = TurnSearchResult.pipe(Schema.decodeTo(Schema.String, {
38
- decode: SchemaGetter.transform((data) => formatTurnSearchMarkdown(data)),
39
- encode: SchemaGetter.forbidden(() => "TurnSearchAsMarkdown is one-way: markdown cannot be parsed back to TurnSearchResult.")
40
- }));
41
30
  /**
42
31
  * The `turn_search` tool's parameters.
43
32
  *
@@ -80,11 +69,11 @@ const handleTurnSearch = (input) => Effect.gen(function* () {
80
69
  * @public
81
70
  */
82
71
  const turnSearchTool = Tool.make("turn_search", {
83
- description: "Use when you need to find past turns across sessions by type, time, or session. Returns markdown in content[] and a typed JSON object in structuredContent ({ count, turns[] }).",
72
+ description: "Use when you need to find past turns across sessions by type, time, or session. Returns a typed JSON object in structuredContent ({ count, turns[] }).",
84
73
  parameters: TurnSearchInput,
85
74
  success: TurnSearchResult,
86
75
  dependencies: [DataReader]
87
- }).annotate(Tool.Title, "Turn search").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.OpenWorld, false).annotate(Tool.Idempotent, true).annotate(RenderText, (encoded) => formatTurnSearchMarkdown(encoded));
76
+ }).annotate(Tool.Title, "Turn search").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.OpenWorld, false).annotate(Tool.Idempotent, true);
88
77
 
89
78
  //#endregion
90
- export { TurnSearchInput, TurnSearchResult, formatTurnSearchMarkdown, handleTurnSearch, turnSearchTool };
79
+ export { TurnSearchInput, TurnSearchResult, handleTurnSearch, turnSearchTool };
@@ -1,4 +1,3 @@
1
- import { RenderText } from "../annotations.js";
2
1
  import { Effect, Schema } from "effect";
3
2
  import { DataReader, formatWrapupEffect } from "@vitest-agent/engine";
4
3
  import { Tool } from "effect/unstable/ai";
@@ -65,17 +64,16 @@ const handleWrapupPrompt = (input) => Effect.gen(function* () {
65
64
  };
66
65
  });
67
66
  /**
68
- * The Effect-native `wrapup_prompt` tool. The text channel is the
69
- * pre-rendered `markdown` field itself.
67
+ * The Effect-native `wrapup_prompt` tool.
70
68
  *
71
69
  * @public
72
70
  */
73
71
  const wrapupPromptTool = Tool.make("wrapup_prompt", {
74
- description: "Use when a session is ending and you need a tailored wrap-up prompt (Stop / SessionEnd / PreCompact / TDD handoff / UserPromptSubmit nudge variants). Returns markdown in content[] and a typed envelope in structuredContent ({ hasContent, kind, markdown }).",
72
+ description: "Use when a session is ending and you need a tailored wrap-up prompt (Stop / SessionEnd / PreCompact / TDD handoff / UserPromptSubmit nudge variants). Returns a typed envelope in structuredContent ({ hasContent, kind, markdown }).",
75
73
  parameters: WrapupPromptInput,
76
74
  success: WrapupPromptResult,
77
75
  dependencies: [DataReader]
78
- }).annotate(Tool.Title, "Wrap-up prompt").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.OpenWorld, false).annotate(Tool.Idempotent, true).annotate(RenderText, (encoded) => encoded.markdown);
76
+ }).annotate(Tool.Title, "Wrap-up prompt").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.OpenWorld, false).annotate(Tool.Idempotent, true);
79
77
 
80
78
  //#endregion
81
79
  export { WrapupPromptInput, WrapupPromptResult, handleWrapupPrompt, wrapupPromptTool };
package/version.js CHANGED
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * @public
9
9
  */
10
- const CURRENT_MCP_VERSION = "4.2.2";
10
+ const CURRENT_MCP_VERSION = "4.3.0";
11
11
 
12
12
  //#endregion
13
13
  export { CURRENT_MCP_VERSION };