veryfront 0.1.209 → 0.1.210
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/esm/cli/mcp/advanced-tools.d.ts.map +1 -1
- package/esm/cli/mcp/advanced-tools.js +2 -0
- package/esm/cli/mcp/standalone.d.ts.map +1 -1
- package/esm/cli/mcp/standalone.js +32 -0
- package/esm/cli/mcp/tools/run-tests-tool.d.ts +25 -0
- package/esm/cli/mcp/tools/run-tests-tool.d.ts.map +1 -0
- package/esm/cli/mcp/tools/run-tests-tool.js +80 -0
- package/esm/deno.js +1 -1
- package/esm/src/agent/data-stream.d.ts.map +1 -1
- package/esm/src/agent/data-stream.js +18 -0
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/cli/mcp/advanced-tools.ts +2 -0
- package/src/cli/mcp/standalone.ts +33 -0
- package/src/cli/mcp/tools/run-tests-tool.ts +101 -0
- package/src/deno.js +1 -1
- package/src/src/agent/data-stream.ts +23 -0
- package/src/src/utils/version-constant.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-tools.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/advanced-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"advanced-tools.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/advanced-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA6B1C,eAAO,MAAM,aAAa,EAAE,OAAO,EAuBlC,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { vfCreateProject, vfListExamples, vfListIntegrations, vfListTemplates, vfListUsecases, } from "./tools/catalog-tools.js";
|
|
2
2
|
import { vfGetDebugContext, vfGetFlywheelStatus, vfHotReload, vfPreviewRoute, vfTriggerHmr, vfWaitForReady, } from "./tools/dev-tools.js";
|
|
3
3
|
import { vfGetComponentTree, vfGetProjectContext, vfListLocalProjects, vfListRoutes, } from "./tools/project-tools.js";
|
|
4
|
+
import { vfRunTests } from "./tools/run-tests-tool.js";
|
|
4
5
|
import { vfGetConventions, vfScaffold } from "./tools/scaffold-tools.js";
|
|
5
6
|
import { vfGetSkillReference, vfGetSkills } from "./tools/skill-tools.js";
|
|
6
7
|
import { cicdTools } from "./tools/cicd-tools.js";
|
|
@@ -27,4 +28,5 @@ export const advancedTools = [
|
|
|
27
28
|
vfTriggerHmr,
|
|
28
29
|
vfWaitForReady,
|
|
29
30
|
vfGetFlywheelStatus,
|
|
31
|
+
vfRunTests,
|
|
30
32
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standalone.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/standalone.ts"],"names":[],"mappings":"AAsCA,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAA4B;gBAEnC,MAAM,GAAE,mBAAwB;IAM5C,KAAK,IAAI,IAAI;IAWb,IAAI,IAAI,IAAI;YAME,aAAa;IAW3B,OAAO,CAAC,cAAc;YAgCR,eAAe;IAqB7B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;YAyBb,mBAAmB;IA6CjC,OAAO,CAAC,iBAAiB;YAkBX,gBAAgB;IAwB9B,OAAO,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"standalone.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/standalone.ts"],"names":[],"mappings":"AAsCA,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAA4B;gBAEnC,MAAM,GAAE,mBAAwB;IAM5C,KAAK,IAAI,IAAI;IAWb,IAAI,IAAI,IAAI;YAME,aAAa;IAW3B,OAAO,CAAC,cAAc;YAgCR,eAAe;IAqB7B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;YAyBb,mBAAmB;IA6CjC,OAAO,CAAC,iBAAiB;YAkBX,gBAAgB;IAwB9B,OAAO,CAAC,WAAW;IAiMnB,OAAO,CAAC,mBAAmB;CA0F5B;AAED,wBAAgB,yBAAyB,CAAC,MAAM,GAAE,mBAAwB,GAAG,mBAAmB,CAI/F"}
|
|
@@ -350,6 +350,38 @@ export class StandaloneMCPServer {
|
|
|
350
350
|
}
|
|
351
351
|
},
|
|
352
352
|
},
|
|
353
|
+
{
|
|
354
|
+
name: "vf_run_tests",
|
|
355
|
+
description: "Run the project's test suite and get structured pass/fail results. " +
|
|
356
|
+
"Returns a summary with total, passed, failed, skipped counts and failure details " +
|
|
357
|
+
"including file path, test name, error message, and line number. " +
|
|
358
|
+
"Do not use for lint checks — use vf_run_lint instead.",
|
|
359
|
+
inputSchema: {
|
|
360
|
+
type: "object",
|
|
361
|
+
properties: {
|
|
362
|
+
filter: {
|
|
363
|
+
type: "string",
|
|
364
|
+
description: "Filter tests by name pattern",
|
|
365
|
+
},
|
|
366
|
+
parallel: {
|
|
367
|
+
type: "boolean",
|
|
368
|
+
description: "Run tests in parallel",
|
|
369
|
+
},
|
|
370
|
+
timeout: {
|
|
371
|
+
type: "number",
|
|
372
|
+
description: "Maximum time to wait for test completion in milliseconds (default: 300000)",
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
async execute(args) {
|
|
377
|
+
const { executeTests } = await import("./tools/run-tests-tool.js");
|
|
378
|
+
return executeTests({
|
|
379
|
+
filter: args.filter,
|
|
380
|
+
parallel: args.parallel,
|
|
381
|
+
timeout: args.timeout,
|
|
382
|
+
});
|
|
383
|
+
},
|
|
384
|
+
},
|
|
353
385
|
...this.createContext7Tools(),
|
|
354
386
|
];
|
|
355
387
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { MCPTool } from "../../../src/mcp/index.js";
|
|
3
|
+
import { type TestResult } from "../../commands/test/command.js";
|
|
4
|
+
declare const runTestsInput: z.ZodObject<{
|
|
5
|
+
filter: z.ZodOptional<z.ZodString>;
|
|
6
|
+
parallel: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
7
|
+
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
type RunTestsInput = z.infer<typeof runTestsInput>;
|
|
10
|
+
/** Build the deno test command args from input options. */
|
|
11
|
+
export declare function buildTestArgs(input: {
|
|
12
|
+
filter?: string;
|
|
13
|
+
parallel?: boolean;
|
|
14
|
+
}): string[];
|
|
15
|
+
/** Env vars required for deterministic test runs. */
|
|
16
|
+
export declare const TEST_ENV: Record<string, string>;
|
|
17
|
+
/** Spawn deno test and return structured results. Exported for standalone reuse. */
|
|
18
|
+
export declare function executeTests(input: {
|
|
19
|
+
filter?: string;
|
|
20
|
+
parallel?: boolean;
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}): Promise<TestResult>;
|
|
23
|
+
export declare const vfRunTests: MCPTool<RunTestsInput, TestResult>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=run-tests-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-tests-tool.d.ts","sourceRoot":"","sources":["../../../../src/cli/mcp/tools/run-tests-tool.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAElF,QAAA,MAAM,aAAa;;;;iBAUjB,CAAC;AAEH,KAAK,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEnD,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,EAAE,CAUtF;AAED,qDAAqD;AACrD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM3C,CAAC;AAEF,oFAAoF;AACpF,wBAAsB,YAAY,CAChC,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,OAAO,CAAC,UAAU,CAAC,CA8BrB;AAED,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,aAAa,EAAE,UAAU,CAgBzD,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: vf_run_tests
|
|
3
|
+
*
|
|
4
|
+
* Runs the project test suite via subprocess and returns structured results.
|
|
5
|
+
* Reuses parseTestOutput from the CLI test command.
|
|
6
|
+
*/
|
|
7
|
+
import * as dntShim from "../../../_dnt.shims.js";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { parseTestOutput } from "../../commands/test/command.js";
|
|
10
|
+
const runTestsInput = z.object({
|
|
11
|
+
filter: z.string().optional().describe("Filter tests by name pattern. Example: 'router' to run only tests matching 'router'."),
|
|
12
|
+
parallel: z.boolean().optional().default(false).describe("Run tests in parallel. Defaults to false."),
|
|
13
|
+
timeout: z.number().optional().default(300000).describe("Maximum time to wait for test completion in milliseconds. Defaults to 300000 (5 minutes)."),
|
|
14
|
+
});
|
|
15
|
+
/** Build the deno test command args from input options. */
|
|
16
|
+
export function buildTestArgs(input) {
|
|
17
|
+
return [
|
|
18
|
+
"test",
|
|
19
|
+
"--no-check",
|
|
20
|
+
"--allow-all",
|
|
21
|
+
"--unstable-worker-options",
|
|
22
|
+
"--unstable-net",
|
|
23
|
+
...(input.parallel ? ["--parallel"] : []),
|
|
24
|
+
...(input.filter ? [`--filter=${input.filter}`] : []),
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
/** Env vars required for deterministic test runs. */
|
|
28
|
+
export const TEST_ENV = {
|
|
29
|
+
VF_DISABLE_LRU_INTERVAL: "1",
|
|
30
|
+
SSR_TRANSFORM_PER_PROJECT_LIMIT: "0",
|
|
31
|
+
REVALIDATION_PER_PROJECT_LIMIT: "0",
|
|
32
|
+
NODE_ENV: "production",
|
|
33
|
+
LOG_FORMAT: "text",
|
|
34
|
+
};
|
|
35
|
+
/** Spawn deno test and return structured results. Exported for standalone reuse. */
|
|
36
|
+
export async function executeTests(input) {
|
|
37
|
+
const cmd = new dntShim.Deno.Command("deno", {
|
|
38
|
+
args: buildTestArgs(input),
|
|
39
|
+
stdout: "piped",
|
|
40
|
+
stderr: "piped",
|
|
41
|
+
env: TEST_ENV,
|
|
42
|
+
});
|
|
43
|
+
const child = cmd.spawn();
|
|
44
|
+
const timeoutMs = input.timeout ?? 300000;
|
|
45
|
+
const result = await Promise.race([
|
|
46
|
+
child.output(),
|
|
47
|
+
new Promise((_, reject) => {
|
|
48
|
+
const timer = dntShim.setTimeout(() => {
|
|
49
|
+
try {
|
|
50
|
+
child.kill();
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Process may have already exited
|
|
54
|
+
}
|
|
55
|
+
reject(new Error(`Test execution timed out after ${timeoutMs}ms`));
|
|
56
|
+
}, timeoutMs);
|
|
57
|
+
// Don't prevent process exit while waiting
|
|
58
|
+
dntShim.Deno.unrefTimer(timer);
|
|
59
|
+
}),
|
|
60
|
+
]);
|
|
61
|
+
const stdout = new TextDecoder().decode(result.stdout);
|
|
62
|
+
const stderr = new TextDecoder().decode(result.stderr);
|
|
63
|
+
return parseTestOutput(stdout + "\n" + stderr, result.code);
|
|
64
|
+
}
|
|
65
|
+
export const vfRunTests = {
|
|
66
|
+
name: "vf_run_tests",
|
|
67
|
+
title: "Run Tests",
|
|
68
|
+
annotations: {
|
|
69
|
+
readOnlyHint: false,
|
|
70
|
+
destructiveHint: false,
|
|
71
|
+
idempotentHint: true,
|
|
72
|
+
openWorldHint: false,
|
|
73
|
+
},
|
|
74
|
+
description: "Use this when you need to run the project's test suite and get structured pass/fail results. " +
|
|
75
|
+
"Returns a summary with total, passed, failed, skipped counts and failure details including " +
|
|
76
|
+
"file path, test name, error message, and line number. " +
|
|
77
|
+
"Do not use for lint checks — use vf_run_lint instead.",
|
|
78
|
+
inputSchema: runTestsInput,
|
|
79
|
+
execute: (input) => executeTests(input),
|
|
80
|
+
};
|
package/esm/deno.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-stream.d.ts","sourceRoot":"","sources":["../../../src/src/agent/data-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAMzE,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAmB1E;AAED,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"data-stream.d.ts","sourceRoot":"","sources":["../../../src/src/agent/data-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAMzE,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAmB1E;AAED,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAoCvF;AAED,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CActF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiB5E;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG;IACvD,MAAM,EAAE,sBAAsB,EAAE,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB,CAoBA;AAED,wBAAuB,sBAAsB,CAC3C,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GACjC,cAAc,CAAC,sBAAsB,CAAC,CAkCxC"}
|
|
@@ -27,6 +27,24 @@ export function mergeToolInputDelta(currentArguments, nextDelta) {
|
|
|
27
27
|
return `{${normalizedDelta}`;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
if (nextDelta.length === 0) {
|
|
31
|
+
return currentArguments;
|
|
32
|
+
}
|
|
33
|
+
if (currentArguments.length === 0) {
|
|
34
|
+
return nextDelta;
|
|
35
|
+
}
|
|
36
|
+
if (nextDelta === currentArguments || currentArguments.includes(nextDelta)) {
|
|
37
|
+
return currentArguments;
|
|
38
|
+
}
|
|
39
|
+
if (nextDelta.startsWith(currentArguments)) {
|
|
40
|
+
return nextDelta;
|
|
41
|
+
}
|
|
42
|
+
const maxOverlap = Math.min(currentArguments.length, nextDelta.length);
|
|
43
|
+
for (let overlap = maxOverlap; overlap > 0; overlap--) {
|
|
44
|
+
if (currentArguments.endsWith(nextDelta.slice(0, overlap))) {
|
|
45
|
+
return currentArguments + nextDelta.slice(overlap);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
30
48
|
return currentArguments + nextDelta;
|
|
31
49
|
}
|
|
32
50
|
export function mergeToolCallInput(currentArguments, nextInput) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.210";
|
|
2
2
|
//# sourceMappingURL=version-constant.d.ts.map
|
package/package.json
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
vfListLocalProjects,
|
|
22
22
|
vfListRoutes,
|
|
23
23
|
} from "./tools/project-tools.js";
|
|
24
|
+
import { vfRunTests } from "./tools/run-tests-tool.js";
|
|
24
25
|
import { vfGetConventions, vfScaffold } from "./tools/scaffold-tools.js";
|
|
25
26
|
import { vfGetSkillReference, vfGetSkills } from "./tools/skill-tools.js";
|
|
26
27
|
import { cicdTools } from "./tools/cicd-tools.js";
|
|
@@ -48,4 +49,5 @@ export const advancedTools: MCPTool[] = [
|
|
|
48
49
|
vfTriggerHmr,
|
|
49
50
|
vfWaitForReady,
|
|
50
51
|
vfGetFlywheelStatus,
|
|
52
|
+
vfRunTests,
|
|
51
53
|
];
|
|
@@ -411,6 +411,39 @@ export class StandaloneMCPServer {
|
|
|
411
411
|
}
|
|
412
412
|
},
|
|
413
413
|
},
|
|
414
|
+
{
|
|
415
|
+
name: "vf_run_tests",
|
|
416
|
+
description: "Run the project's test suite and get structured pass/fail results. " +
|
|
417
|
+
"Returns a summary with total, passed, failed, skipped counts and failure details " +
|
|
418
|
+
"including file path, test name, error message, and line number. " +
|
|
419
|
+
"Do not use for lint checks — use vf_run_lint instead.",
|
|
420
|
+
inputSchema: {
|
|
421
|
+
type: "object",
|
|
422
|
+
properties: {
|
|
423
|
+
filter: {
|
|
424
|
+
type: "string",
|
|
425
|
+
description: "Filter tests by name pattern",
|
|
426
|
+
},
|
|
427
|
+
parallel: {
|
|
428
|
+
type: "boolean",
|
|
429
|
+
description: "Run tests in parallel",
|
|
430
|
+
},
|
|
431
|
+
timeout: {
|
|
432
|
+
type: "number",
|
|
433
|
+
description:
|
|
434
|
+
"Maximum time to wait for test completion in milliseconds (default: 300000)",
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
async execute(args) {
|
|
439
|
+
const { executeTests } = await import("./tools/run-tests-tool.js");
|
|
440
|
+
return executeTests({
|
|
441
|
+
filter: args.filter as string | undefined,
|
|
442
|
+
parallel: args.parallel as boolean | undefined,
|
|
443
|
+
timeout: args.timeout as number | undefined,
|
|
444
|
+
});
|
|
445
|
+
},
|
|
446
|
+
},
|
|
414
447
|
...this.createContext7Tools(),
|
|
415
448
|
];
|
|
416
449
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: vf_run_tests
|
|
3
|
+
*
|
|
4
|
+
* Runs the project test suite via subprocess and returns structured results.
|
|
5
|
+
* Reuses parseTestOutput from the CLI test command.
|
|
6
|
+
*/
|
|
7
|
+
import * as dntShim from "../../../_dnt.shims.js";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import type { MCPTool } from "../../../src/mcp/index.js";
|
|
12
|
+
import { parseTestOutput, type TestResult } from "../../commands/test/command.js";
|
|
13
|
+
|
|
14
|
+
const runTestsInput = z.object({
|
|
15
|
+
filter: z.string().optional().describe(
|
|
16
|
+
"Filter tests by name pattern. Example: 'router' to run only tests matching 'router'.",
|
|
17
|
+
),
|
|
18
|
+
parallel: z.boolean().optional().default(false).describe(
|
|
19
|
+
"Run tests in parallel. Defaults to false.",
|
|
20
|
+
),
|
|
21
|
+
timeout: z.number().optional().default(300000).describe(
|
|
22
|
+
"Maximum time to wait for test completion in milliseconds. Defaults to 300000 (5 minutes).",
|
|
23
|
+
),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
type RunTestsInput = z.infer<typeof runTestsInput>;
|
|
27
|
+
|
|
28
|
+
/** Build the deno test command args from input options. */
|
|
29
|
+
export function buildTestArgs(input: { filter?: string; parallel?: boolean }): string[] {
|
|
30
|
+
return [
|
|
31
|
+
"test",
|
|
32
|
+
"--no-check",
|
|
33
|
+
"--allow-all",
|
|
34
|
+
"--unstable-worker-options",
|
|
35
|
+
"--unstable-net",
|
|
36
|
+
...(input.parallel ? ["--parallel"] : []),
|
|
37
|
+
...(input.filter ? [`--filter=${input.filter}`] : []),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Env vars required for deterministic test runs. */
|
|
42
|
+
export const TEST_ENV: Record<string, string> = {
|
|
43
|
+
VF_DISABLE_LRU_INTERVAL: "1",
|
|
44
|
+
SSR_TRANSFORM_PER_PROJECT_LIMIT: "0",
|
|
45
|
+
REVALIDATION_PER_PROJECT_LIMIT: "0",
|
|
46
|
+
NODE_ENV: "production",
|
|
47
|
+
LOG_FORMAT: "text",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Spawn deno test and return structured results. Exported for standalone reuse. */
|
|
51
|
+
export async function executeTests(
|
|
52
|
+
input: { filter?: string; parallel?: boolean; timeout?: number },
|
|
53
|
+
): Promise<TestResult> {
|
|
54
|
+
const cmd = new dntShim.Deno.Command("deno", {
|
|
55
|
+
args: buildTestArgs(input),
|
|
56
|
+
stdout: "piped",
|
|
57
|
+
stderr: "piped",
|
|
58
|
+
env: TEST_ENV,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const child = cmd.spawn();
|
|
62
|
+
const timeoutMs = input.timeout ?? 300000;
|
|
63
|
+
|
|
64
|
+
const result = await Promise.race([
|
|
65
|
+
child.output(),
|
|
66
|
+
new Promise<never>((_, reject) => {
|
|
67
|
+
const timer = dntShim.setTimeout(() => {
|
|
68
|
+
try {
|
|
69
|
+
child.kill();
|
|
70
|
+
} catch {
|
|
71
|
+
// Process may have already exited
|
|
72
|
+
}
|
|
73
|
+
reject(new Error(`Test execution timed out after ${timeoutMs}ms`));
|
|
74
|
+
}, timeoutMs);
|
|
75
|
+
// Don't prevent process exit while waiting
|
|
76
|
+
dntShim.Deno.unrefTimer(timer);
|
|
77
|
+
}),
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
const stdout = new TextDecoder().decode(result.stdout);
|
|
81
|
+
const stderr = new TextDecoder().decode(result.stderr);
|
|
82
|
+
return parseTestOutput(stdout + "\n" + stderr, result.code);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const vfRunTests: MCPTool<RunTestsInput, TestResult> = {
|
|
86
|
+
name: "vf_run_tests",
|
|
87
|
+
title: "Run Tests",
|
|
88
|
+
annotations: {
|
|
89
|
+
readOnlyHint: false,
|
|
90
|
+
destructiveHint: false,
|
|
91
|
+
idempotentHint: true,
|
|
92
|
+
openWorldHint: false,
|
|
93
|
+
},
|
|
94
|
+
description:
|
|
95
|
+
"Use this when you need to run the project's test suite and get structured pass/fail results. " +
|
|
96
|
+
"Returns a summary with total, passed, failed, skipped counts and failure details including " +
|
|
97
|
+
"file path, test name, error message, and line number. " +
|
|
98
|
+
"Do not use for lint checks — use vf_run_lint instead.",
|
|
99
|
+
inputSchema: runTestsInput,
|
|
100
|
+
execute: (input) => executeTests(input),
|
|
101
|
+
};
|
package/src/deno.js
CHANGED
|
@@ -37,6 +37,29 @@ export function mergeToolInputDelta(currentArguments: string, nextDelta: string)
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
if (nextDelta.length === 0) {
|
|
41
|
+
return currentArguments;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (currentArguments.length === 0) {
|
|
45
|
+
return nextDelta;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (nextDelta === currentArguments || currentArguments.includes(nextDelta)) {
|
|
49
|
+
return currentArguments;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (nextDelta.startsWith(currentArguments)) {
|
|
53
|
+
return nextDelta;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const maxOverlap = Math.min(currentArguments.length, nextDelta.length);
|
|
57
|
+
for (let overlap = maxOverlap; overlap > 0; overlap--) {
|
|
58
|
+
if (currentArguments.endsWith(nextDelta.slice(0, overlap))) {
|
|
59
|
+
return currentArguments + nextDelta.slice(overlap);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
40
63
|
return currentArguments + nextDelta;
|
|
41
64
|
}
|
|
42
65
|
|