iosm-cli 0.2.8 → 0.2.9

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.
Files changed (93) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +3 -3
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +7 -3
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/agent-profiles.d.ts.map +1 -1
  7. package/dist/core/agent-profiles.js +5 -1
  8. package/dist/core/agent-profiles.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +3 -0
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +188 -2
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/sdk.d.ts +2 -2
  14. package/dist/core/sdk.d.ts.map +1 -1
  15. package/dist/core/sdk.js +7 -4
  16. package/dist/core/sdk.js.map +1 -1
  17. package/dist/core/settings-manager.d.ts +18 -0
  18. package/dist/core/settings-manager.d.ts.map +1 -1
  19. package/dist/core/settings-manager.js +29 -0
  20. package/dist/core/settings-manager.js.map +1 -1
  21. package/dist/core/shadow-guard.d.ts.map +1 -1
  22. package/dist/core/shadow-guard.js +12 -1
  23. package/dist/core/shadow-guard.js.map +1 -1
  24. package/dist/core/system-prompt.d.ts.map +1 -1
  25. package/dist/core/system-prompt.js +32 -1
  26. package/dist/core/system-prompt.js.map +1 -1
  27. package/dist/core/tools/db-run.d.ts +84 -0
  28. package/dist/core/tools/db-run.d.ts.map +1 -0
  29. package/dist/core/tools/db-run.js +690 -0
  30. package/dist/core/tools/db-run.js.map +1 -0
  31. package/dist/core/tools/index.d.ts +44 -0
  32. package/dist/core/tools/index.d.ts.map +1 -1
  33. package/dist/core/tools/index.js +16 -0
  34. package/dist/core/tools/index.js.map +1 -1
  35. package/dist/core/tools/lint-run.d.ts +42 -0
  36. package/dist/core/tools/lint-run.d.ts.map +1 -0
  37. package/dist/core/tools/lint-run.js +276 -0
  38. package/dist/core/tools/lint-run.js.map +1 -0
  39. package/dist/core/tools/test-run.d.ts +36 -0
  40. package/dist/core/tools/test-run.d.ts.map +1 -0
  41. package/dist/core/tools/test-run.js +255 -0
  42. package/dist/core/tools/test-run.js.map +1 -0
  43. package/dist/core/tools/typecheck-run.d.ts +44 -0
  44. package/dist/core/tools/typecheck-run.d.ts.map +1 -0
  45. package/dist/core/tools/typecheck-run.js +343 -0
  46. package/dist/core/tools/typecheck-run.js.map +1 -0
  47. package/dist/core/tools/verification-runner.d.ts +53 -0
  48. package/dist/core/tools/verification-runner.d.ts.map +1 -0
  49. package/dist/core/tools/verification-runner.js +235 -0
  50. package/dist/core/tools/verification-runner.js.map +1 -0
  51. package/dist/index.d.ts +2 -2
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +1 -1
  54. package/dist/index.js.map +1 -1
  55. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  56. package/dist/modes/interactive/components/branch-summary-message.js +2 -1
  57. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  58. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  59. package/dist/modes/interactive/components/compaction-summary-message.js +2 -1
  60. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  61. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  62. package/dist/modes/interactive/components/custom-message.js +2 -1
  63. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  64. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  65. package/dist/modes/interactive/components/skill-invocation-message.js +4 -2
  66. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  67. package/dist/modes/interactive/components/subagent-message.d.ts.map +1 -1
  68. package/dist/modes/interactive/components/subagent-message.js +3 -1
  69. package/dist/modes/interactive/components/subagent-message.js.map +1 -1
  70. package/dist/modes/interactive/components/task-plan-message.d.ts.map +1 -1
  71. package/dist/modes/interactive/components/task-plan-message.js +2 -1
  72. package/dist/modes/interactive/components/task-plan-message.js.map +1 -1
  73. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  74. package/dist/modes/interactive/components/tool-execution.js +25 -7
  75. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  76. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  77. package/dist/modes/interactive/components/user-message.js +2 -1
  78. package/dist/modes/interactive/components/user-message.js.map +1 -1
  79. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  80. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  81. package/dist/modes/interactive/interactive-mode.js +494 -9
  82. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  83. package/dist/modes/interactive/theme/dark.json +39 -38
  84. package/dist/modes/interactive/theme/light.json +29 -29
  85. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  86. package/dist/modes/interactive/theme/theme.js +16 -25
  87. package/dist/modes/interactive/theme/theme.js.map +1 -1
  88. package/dist/modes/interactive/theme/universal.json +85 -0
  89. package/docs/cli-reference.md +16 -1
  90. package/docs/configuration.md +76 -1
  91. package/docs/development-and-testing.md +1 -1
  92. package/docs/interactive-mode.md +7 -2
  93. package/package.json +1 -1
@@ -0,0 +1,276 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { Type } from "@sinclair/typebox";
4
+ import { resolveToCwd } from "./path-utils.js";
5
+ import { detectPackageManager, ensureCommandOrThrow, formatVerificationOutput, readPackageJson, resolvePackageManagerExecInvocation, resolvePackageManagerRunInvocation, runVerificationCommand, } from "./verification-runner.js";
6
+ const lintRunSchema = Type.Object({
7
+ runner: Type.Optional(Type.Union([
8
+ Type.Literal("auto"),
9
+ Type.Literal("npm"),
10
+ Type.Literal("pnpm"),
11
+ Type.Literal("yarn"),
12
+ Type.Literal("bun"),
13
+ Type.Literal("eslint"),
14
+ Type.Literal("prettier"),
15
+ Type.Literal("stylelint"),
16
+ ], {
17
+ description: "Linter runner: auto | npm | pnpm | yarn | bun | eslint | prettier | stylelint",
18
+ })),
19
+ mode: Type.Optional(Type.Union([Type.Literal("check"), Type.Literal("fix")], {
20
+ description: "Lint mode: check | fix (default: check).",
21
+ })),
22
+ script: Type.Optional(Type.String({
23
+ description: "Package script for npm/pnpm/yarn/bun runners (default: lint or lint:fix by mode).",
24
+ })),
25
+ targets: Type.Optional(Type.Array(Type.String(), {
26
+ description: "Optional explicit lint targets (paths/globs).",
27
+ })),
28
+ args: Type.Optional(Type.Array(Type.String(), {
29
+ description: "Additional CLI args forwarded to the selected linter runner.",
30
+ })),
31
+ path: Type.Optional(Type.String({ description: "Working directory for lint execution (default: current directory)." })),
32
+ timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (default: 300)." })),
33
+ });
34
+ export const DEFAULT_LINT_RUN_TIMEOUT_SECONDS = 300;
35
+ function normalizeTimeoutSeconds(raw) {
36
+ if (raw === undefined)
37
+ return DEFAULT_LINT_RUN_TIMEOUT_SECONDS;
38
+ const value = Math.floor(raw);
39
+ if (!Number.isFinite(value) || value <= 0) {
40
+ throw new Error("timeout must be a positive number.");
41
+ }
42
+ return value;
43
+ }
44
+ function normalizeStringArray(raw) {
45
+ return (raw ?? []).map((item) => String(item));
46
+ }
47
+ function normalizeScriptName(raw, mode) {
48
+ const fallback = mode === "fix" ? "lint:fix" : "lint";
49
+ const script = (raw ?? fallback).trim();
50
+ if (script.length === 0) {
51
+ throw new Error("script must not be empty.");
52
+ }
53
+ return script;
54
+ }
55
+ function hasAnyFile(cwd, fileNames) {
56
+ return fileNames.some((name) => existsSync(join(cwd, name)));
57
+ }
58
+ function hasEslintConfig(cwd, packageJsonEslintConfig) {
59
+ if (packageJsonEslintConfig && typeof packageJsonEslintConfig === "object") {
60
+ return true;
61
+ }
62
+ return hasAnyFile(cwd, [
63
+ "eslint.config.js",
64
+ "eslint.config.cjs",
65
+ "eslint.config.mjs",
66
+ "eslint.config.ts",
67
+ "eslint.config.mts",
68
+ "eslint.config.cts",
69
+ ".eslintrc",
70
+ ".eslintrc.js",
71
+ ".eslintrc.cjs",
72
+ ".eslintrc.mjs",
73
+ ".eslintrc.yaml",
74
+ ".eslintrc.yml",
75
+ ".eslintrc.json",
76
+ ]);
77
+ }
78
+ function hasStylelintConfig(cwd, packageJsonStylelint) {
79
+ if (packageJsonStylelint && typeof packageJsonStylelint === "object") {
80
+ return true;
81
+ }
82
+ return hasAnyFile(cwd, [
83
+ "stylelint.config.js",
84
+ "stylelint.config.cjs",
85
+ "stylelint.config.mjs",
86
+ "stylelint.config.ts",
87
+ "stylelint.config.mts",
88
+ "stylelint.config.cts",
89
+ ".stylelintrc",
90
+ ".stylelintrc.js",
91
+ ".stylelintrc.cjs",
92
+ ".stylelintrc.mjs",
93
+ ".stylelintrc.yaml",
94
+ ".stylelintrc.yml",
95
+ ".stylelintrc.json",
96
+ ]);
97
+ }
98
+ function hasPrettierConfig(cwd, packageJsonPrettier) {
99
+ if (typeof packageJsonPrettier === "string" || (packageJsonPrettier && typeof packageJsonPrettier === "object")) {
100
+ return true;
101
+ }
102
+ return hasAnyFile(cwd, [
103
+ ".prettierrc",
104
+ ".prettierrc.js",
105
+ ".prettierrc.cjs",
106
+ ".prettierrc.mjs",
107
+ ".prettierrc.json",
108
+ ".prettierrc.yaml",
109
+ ".prettierrc.yml",
110
+ ".prettierrc.toml",
111
+ "prettier.config.js",
112
+ "prettier.config.cjs",
113
+ "prettier.config.mjs",
114
+ ]);
115
+ }
116
+ function assertPackageManagerAvailable(packageManager) {
117
+ if (packageManager === "bun") {
118
+ ensureCommandOrThrow("bun", 'Command "bun" is required for bun-based lint execution.');
119
+ return;
120
+ }
121
+ ensureCommandOrThrow(packageManager, `Command "${packageManager}" is required for lint execution.`);
122
+ }
123
+ function resolveScriptBasedCommand(packageManager, script, args) {
124
+ assertPackageManagerAvailable(packageManager);
125
+ const invocation = resolvePackageManagerRunInvocation(packageManager, script, args);
126
+ return {
127
+ resolvedRunner: packageManager,
128
+ command: invocation.command,
129
+ args: invocation.args,
130
+ };
131
+ }
132
+ function buildDirectLintArgs(runner, mode, targets, args) {
133
+ const effectiveTargets = targets.length > 0 ? targets : runner === "stylelint" ? ["**/*.{css,scss,sass,less}"] : ["."];
134
+ if (runner === "eslint") {
135
+ const modeArgs = mode === "fix" ? ["--fix"] : [];
136
+ return [...modeArgs, ...args, ...effectiveTargets];
137
+ }
138
+ if (runner === "prettier") {
139
+ const modeArgs = mode === "fix" ? ["--write"] : ["--check"];
140
+ return [...modeArgs, ...args, ...effectiveTargets];
141
+ }
142
+ const modeArgs = mode === "fix" ? ["--fix"] : [];
143
+ return [...modeArgs, ...args, ...effectiveTargets];
144
+ }
145
+ function resolveDirectLintCommand(packageManager, runner, mode, targets, args) {
146
+ assertPackageManagerAvailable(packageManager);
147
+ const directArgs = buildDirectLintArgs(runner, mode, targets, args);
148
+ const invocation = resolvePackageManagerExecInvocation(packageManager, runner, directArgs);
149
+ ensureCommandOrThrow(invocation.command, `Command "${invocation.command}" is required to run ${runner}. Install ${packageManager} tooling first.`);
150
+ return {
151
+ resolvedRunner: runner,
152
+ command: invocation.command,
153
+ args: invocation.args,
154
+ };
155
+ }
156
+ function resolveAutoRunner(cwd, script) {
157
+ const packageJson = readPackageJson(cwd);
158
+ if (packageJson?.scripts[script]) {
159
+ return detectPackageManager(cwd);
160
+ }
161
+ if (hasEslintConfig(cwd, packageJson?.raw?.eslintConfig))
162
+ return "eslint";
163
+ if (hasStylelintConfig(cwd, packageJson?.raw?.stylelint))
164
+ return "stylelint";
165
+ if (hasPrettierConfig(cwd, packageJson?.raw?.prettier))
166
+ return "prettier";
167
+ throw new Error('Unable to auto-detect lint runner. Expected package.json lint script or eslint/stylelint/prettier config.');
168
+ }
169
+ function hasCheckModeConflictArgs(args) {
170
+ for (const arg of args) {
171
+ if (arg === "--fix" || arg.startsWith("--fix=") || arg === "--write" || arg.startsWith("--write=")) {
172
+ return arg;
173
+ }
174
+ }
175
+ return undefined;
176
+ }
177
+ function resolveLintCommand(input) {
178
+ const packageJson = readPackageJson(input.cwd);
179
+ let resolvedRunner;
180
+ if (input.runner === "auto") {
181
+ resolvedRunner = resolveAutoRunner(input.cwd, input.script);
182
+ }
183
+ else {
184
+ resolvedRunner = input.runner;
185
+ }
186
+ if (resolvedRunner === "npm" || resolvedRunner === "pnpm" || resolvedRunner === "yarn" || resolvedRunner === "bun") {
187
+ if (!packageJson) {
188
+ throw new Error(`package.json is required to run ${resolvedRunner} scripts.`);
189
+ }
190
+ if (!packageJson.scripts[input.script]) {
191
+ throw new Error(`Script "${input.script}" is not defined in package.json.`);
192
+ }
193
+ return resolveScriptBasedCommand(resolvedRunner, input.script, input.args);
194
+ }
195
+ const packageManager = detectPackageManager(input.cwd);
196
+ return resolveDirectLintCommand(packageManager, resolvedRunner, input.mode, input.targets, input.args);
197
+ }
198
+ function mapLintStatus(exitCode) {
199
+ if (exitCode === 0)
200
+ return "passed";
201
+ if (exitCode === 1)
202
+ return "failed";
203
+ return "error";
204
+ }
205
+ function renderSummary(details, output) {
206
+ const argsText = details.resolvedArgs.length > 0 ? ` ${details.resolvedArgs.join(" ")}` : "";
207
+ return [
208
+ `lint_run status: ${details.status}`,
209
+ `runner: ${details.resolvedRunner}`,
210
+ `mode: ${details.mode}`,
211
+ `command: ${details.resolvedCommand}${argsText}`,
212
+ `cwd: ${details.cwd}`,
213
+ `exit_code: ${details.exitCode}`,
214
+ `duration_ms: ${details.durationMs}`,
215
+ "",
216
+ output,
217
+ ].join("\n");
218
+ }
219
+ export function createLintRunTool(cwd) {
220
+ return {
221
+ name: "lint_run",
222
+ label: "lint_run",
223
+ description: "Structured lint runner with auto detection across npm/pnpm/yarn/bun scripts and eslint/prettier/stylelint direct execution. Returns normalized status without throwing on ordinary lint failures.",
224
+ parameters: lintRunSchema,
225
+ execute: async (_toolCallId, input, signal) => {
226
+ const executionCwd = resolveToCwd(input.path || ".", cwd);
227
+ const timeoutSeconds = normalizeTimeoutSeconds(input.timeout);
228
+ const args = normalizeStringArray(input.args);
229
+ const targets = normalizeStringArray(input.targets);
230
+ const mode = input.mode ?? "check";
231
+ const script = normalizeScriptName(input.script, mode);
232
+ const runner = input.runner ?? "auto";
233
+ if (mode === "check") {
234
+ const conflictArg = hasCheckModeConflictArgs(args);
235
+ if (conflictArg) {
236
+ throw new Error(`Argument "${conflictArg}" is incompatible with mode=check.`);
237
+ }
238
+ }
239
+ const command = resolveLintCommand({
240
+ cwd: executionCwd,
241
+ runner,
242
+ mode,
243
+ script,
244
+ args,
245
+ targets,
246
+ });
247
+ const result = await runVerificationCommand({
248
+ command: command.command,
249
+ args: command.args,
250
+ cwd: executionCwd,
251
+ timeoutMs: timeoutSeconds * 1000,
252
+ signal,
253
+ });
254
+ const status = mapLintStatus(result.exitCode);
255
+ const formatted = formatVerificationOutput(result.stdout, result.stderr, result.captureTruncated, "No lint output");
256
+ const details = {
257
+ resolvedRunner: command.resolvedRunner,
258
+ resolvedCommand: command.command,
259
+ resolvedArgs: command.args,
260
+ cwd: executionCwd,
261
+ mode,
262
+ exitCode: result.exitCode,
263
+ status,
264
+ durationMs: result.durationMs,
265
+ captureTruncated: result.captureTruncated || undefined,
266
+ truncation: formatted.truncation,
267
+ };
268
+ return {
269
+ content: [{ type: "text", text: renderSummary(details, formatted.text) }],
270
+ details,
271
+ };
272
+ },
273
+ };
274
+ }
275
+ export const lintRunTool = createLintRunTool(process.cwd());
276
+ //# sourceMappingURL=lint-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-run.js","sourceRoot":"","sources":["../../../src/core/tools/lint-run.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { resolveToCwd } from \"./path-utils.js\";\nimport type { TruncationResult } from \"./truncate.js\";\nimport {\n\ttype PackageManager,\n\tdetectPackageManager,\n\tensureCommandOrThrow,\n\tformatVerificationOutput,\n\treadPackageJson,\n\tresolvePackageManagerExecInvocation,\n\tresolvePackageManagerRunInvocation,\n\trunVerificationCommand,\n} from \"./verification-runner.js\";\n\nconst lintRunSchema = Type.Object({\n\trunner: Type.Optional(\n\t\tType.Union(\n\t\t\t[\n\t\t\t\tType.Literal(\"auto\"),\n\t\t\t\tType.Literal(\"npm\"),\n\t\t\t\tType.Literal(\"pnpm\"),\n\t\t\t\tType.Literal(\"yarn\"),\n\t\t\t\tType.Literal(\"bun\"),\n\t\t\t\tType.Literal(\"eslint\"),\n\t\t\t\tType.Literal(\"prettier\"),\n\t\t\t\tType.Literal(\"stylelint\"),\n\t\t\t],\n\t\t\t{\n\t\t\t\tdescription: \"Linter runner: auto | npm | pnpm | yarn | bun | eslint | prettier | stylelint\",\n\t\t\t},\n\t\t),\n\t),\n\tmode: Type.Optional(\n\t\tType.Union([Type.Literal(\"check\"), Type.Literal(\"fix\")], {\n\t\t\tdescription: \"Lint mode: check | fix (default: check).\",\n\t\t}),\n\t),\n\tscript: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Package script for npm/pnpm/yarn/bun runners (default: lint or lint:fix by mode).\",\n\t\t}),\n\t),\n\ttargets: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription: \"Optional explicit lint targets (paths/globs).\",\n\t\t}),\n\t),\n\targs: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription: \"Additional CLI args forwarded to the selected linter runner.\",\n\t\t}),\n\t),\n\tpath: Type.Optional(Type.String({ description: \"Working directory for lint execution (default: current directory).\" })),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (default: 300).\" })),\n});\n\nexport type LintRunToolInput = Static<typeof lintRunSchema>;\nexport type LintRunRunner = \"auto\" | \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" | \"eslint\" | \"prettier\" | \"stylelint\";\nexport type LintRunMode = \"check\" | \"fix\";\nexport type LintRunStatus = \"passed\" | \"failed\" | \"no_tests\" | \"error\";\n\ntype ResolvedLintRunner = Exclude<LintRunRunner, \"auto\">;\n\ninterface ResolvedLintCommand {\n\tresolvedRunner: ResolvedLintRunner;\n\tcommand: string;\n\targs: string[];\n}\n\nexport interface LintRunToolDetails {\n\tresolvedRunner: ResolvedLintRunner;\n\tresolvedCommand: string;\n\tresolvedArgs: string[];\n\tcwd: string;\n\tmode: LintRunMode;\n\texitCode: number;\n\tstatus: LintRunStatus;\n\tdurationMs: number;\n\tcaptureTruncated?: boolean;\n\ttruncation?: TruncationResult;\n}\n\nexport const DEFAULT_LINT_RUN_TIMEOUT_SECONDS = 300;\n\nfunction normalizeTimeoutSeconds(raw: number | undefined): number {\n\tif (raw === undefined) return DEFAULT_LINT_RUN_TIMEOUT_SECONDS;\n\tconst value = Math.floor(raw);\n\tif (!Number.isFinite(value) || value <= 0) {\n\t\tthrow new Error(\"timeout must be a positive number.\");\n\t}\n\treturn value;\n}\n\nfunction normalizeStringArray(raw: string[] | undefined): string[] {\n\treturn (raw ?? []).map((item) => String(item));\n}\n\nfunction normalizeScriptName(raw: string | undefined, mode: LintRunMode): string {\n\tconst fallback = mode === \"fix\" ? \"lint:fix\" : \"lint\";\n\tconst script = (raw ?? fallback).trim();\n\tif (script.length === 0) {\n\t\tthrow new Error(\"script must not be empty.\");\n\t}\n\treturn script;\n}\n\nfunction hasAnyFile(cwd: string, fileNames: string[]): boolean {\n\treturn fileNames.some((name) => existsSync(join(cwd, name)));\n}\n\nfunction hasEslintConfig(cwd: string, packageJsonEslintConfig: unknown): boolean {\n\tif (packageJsonEslintConfig && typeof packageJsonEslintConfig === \"object\") {\n\t\treturn true;\n\t}\n\treturn hasAnyFile(cwd, [\n\t\t\"eslint.config.js\",\n\t\t\"eslint.config.cjs\",\n\t\t\"eslint.config.mjs\",\n\t\t\"eslint.config.ts\",\n\t\t\"eslint.config.mts\",\n\t\t\"eslint.config.cts\",\n\t\t\".eslintrc\",\n\t\t\".eslintrc.js\",\n\t\t\".eslintrc.cjs\",\n\t\t\".eslintrc.mjs\",\n\t\t\".eslintrc.yaml\",\n\t\t\".eslintrc.yml\",\n\t\t\".eslintrc.json\",\n\t]);\n}\n\nfunction hasStylelintConfig(cwd: string, packageJsonStylelint: unknown): boolean {\n\tif (packageJsonStylelint && typeof packageJsonStylelint === \"object\") {\n\t\treturn true;\n\t}\n\treturn hasAnyFile(cwd, [\n\t\t\"stylelint.config.js\",\n\t\t\"stylelint.config.cjs\",\n\t\t\"stylelint.config.mjs\",\n\t\t\"stylelint.config.ts\",\n\t\t\"stylelint.config.mts\",\n\t\t\"stylelint.config.cts\",\n\t\t\".stylelintrc\",\n\t\t\".stylelintrc.js\",\n\t\t\".stylelintrc.cjs\",\n\t\t\".stylelintrc.mjs\",\n\t\t\".stylelintrc.yaml\",\n\t\t\".stylelintrc.yml\",\n\t\t\".stylelintrc.json\",\n\t]);\n}\n\nfunction hasPrettierConfig(cwd: string, packageJsonPrettier: unknown): boolean {\n\tif (typeof packageJsonPrettier === \"string\" || (packageJsonPrettier && typeof packageJsonPrettier === \"object\")) {\n\t\treturn true;\n\t}\n\treturn hasAnyFile(cwd, [\n\t\t\".prettierrc\",\n\t\t\".prettierrc.js\",\n\t\t\".prettierrc.cjs\",\n\t\t\".prettierrc.mjs\",\n\t\t\".prettierrc.json\",\n\t\t\".prettierrc.yaml\",\n\t\t\".prettierrc.yml\",\n\t\t\".prettierrc.toml\",\n\t\t\"prettier.config.js\",\n\t\t\"prettier.config.cjs\",\n\t\t\"prettier.config.mjs\",\n\t]);\n}\n\nfunction assertPackageManagerAvailable(packageManager: PackageManager): void {\n\tif (packageManager === \"bun\") {\n\t\tensureCommandOrThrow(\"bun\", 'Command \"bun\" is required for bun-based lint execution.');\n\t\treturn;\n\t}\n\tensureCommandOrThrow(packageManager, `Command \"${packageManager}\" is required for lint execution.`);\n}\n\nfunction resolveScriptBasedCommand(packageManager: PackageManager, script: string, args: string[]): ResolvedLintCommand {\n\tassertPackageManagerAvailable(packageManager);\n\tconst invocation = resolvePackageManagerRunInvocation(packageManager, script, args);\n\treturn {\n\t\tresolvedRunner: packageManager,\n\t\tcommand: invocation.command,\n\t\targs: invocation.args,\n\t};\n}\n\nfunction buildDirectLintArgs(\n\trunner: \"eslint\" | \"prettier\" | \"stylelint\",\n\tmode: LintRunMode,\n\ttargets: string[],\n\targs: string[],\n): string[] {\n\tconst effectiveTargets =\n\t\ttargets.length > 0 ? targets : runner === \"stylelint\" ? [\"**/*.{css,scss,sass,less}\"] : [\".\"];\n\n\tif (runner === \"eslint\") {\n\t\tconst modeArgs = mode === \"fix\" ? [\"--fix\"] : [];\n\t\treturn [...modeArgs, ...args, ...effectiveTargets];\n\t}\n\tif (runner === \"prettier\") {\n\t\tconst modeArgs = mode === \"fix\" ? [\"--write\"] : [\"--check\"];\n\t\treturn [...modeArgs, ...args, ...effectiveTargets];\n\t}\n\tconst modeArgs = mode === \"fix\" ? [\"--fix\"] : [];\n\treturn [...modeArgs, ...args, ...effectiveTargets];\n}\n\nfunction resolveDirectLintCommand(\n\tpackageManager: PackageManager,\n\trunner: \"eslint\" | \"prettier\" | \"stylelint\",\n\tmode: LintRunMode,\n\ttargets: string[],\n\targs: string[],\n): ResolvedLintCommand {\n\tassertPackageManagerAvailable(packageManager);\n\tconst directArgs = buildDirectLintArgs(runner, mode, targets, args);\n\tconst invocation = resolvePackageManagerExecInvocation(packageManager, runner, directArgs);\n\tensureCommandOrThrow(\n\t\tinvocation.command,\n\t\t`Command \"${invocation.command}\" is required to run ${runner}. Install ${packageManager} tooling first.`,\n\t);\n\treturn {\n\t\tresolvedRunner: runner,\n\t\tcommand: invocation.command,\n\t\targs: invocation.args,\n\t};\n}\n\nfunction resolveAutoRunner(cwd: string, script: string): ResolvedLintRunner {\n\tconst packageJson = readPackageJson(cwd);\n\tif (packageJson?.scripts[script]) {\n\t\treturn detectPackageManager(cwd);\n\t}\n\tif (hasEslintConfig(cwd, packageJson?.raw?.eslintConfig)) return \"eslint\";\n\tif (hasStylelintConfig(cwd, packageJson?.raw?.stylelint)) return \"stylelint\";\n\tif (hasPrettierConfig(cwd, packageJson?.raw?.prettier)) return \"prettier\";\n\tthrow new Error(\n\t\t'Unable to auto-detect lint runner. Expected package.json lint script or eslint/stylelint/prettier config.',\n\t);\n}\n\nfunction hasCheckModeConflictArgs(args: string[]): string | undefined {\n\tfor (const arg of args) {\n\t\tif (arg === \"--fix\" || arg.startsWith(\"--fix=\") || arg === \"--write\" || arg.startsWith(\"--write=\")) {\n\t\t\treturn arg;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction resolveLintCommand(input: {\n\tcwd: string;\n\trunner: LintRunRunner;\n\tmode: LintRunMode;\n\tscript: string;\n\targs: string[];\n\ttargets: string[];\n}): ResolvedLintCommand {\n\tconst packageJson = readPackageJson(input.cwd);\n\tlet resolvedRunner: ResolvedLintRunner;\n\n\tif (input.runner === \"auto\") {\n\t\tresolvedRunner = resolveAutoRunner(input.cwd, input.script);\n\t} else {\n\t\tresolvedRunner = input.runner;\n\t}\n\n\tif (resolvedRunner === \"npm\" || resolvedRunner === \"pnpm\" || resolvedRunner === \"yarn\" || resolvedRunner === \"bun\") {\n\t\tif (!packageJson) {\n\t\t\tthrow new Error(`package.json is required to run ${resolvedRunner} scripts.`);\n\t\t}\n\t\tif (!packageJson.scripts[input.script]) {\n\t\t\tthrow new Error(`Script \"${input.script}\" is not defined in package.json.`);\n\t\t}\n\t\treturn resolveScriptBasedCommand(resolvedRunner, input.script, input.args);\n\t}\n\n\tconst packageManager = detectPackageManager(input.cwd);\n\treturn resolveDirectLintCommand(packageManager, resolvedRunner, input.mode, input.targets, input.args);\n}\n\nfunction mapLintStatus(exitCode: number): LintRunStatus {\n\tif (exitCode === 0) return \"passed\";\n\tif (exitCode === 1) return \"failed\";\n\treturn \"error\";\n}\n\nfunction renderSummary(details: LintRunToolDetails, output: string): string {\n\tconst argsText = details.resolvedArgs.length > 0 ? ` ${details.resolvedArgs.join(\" \")}` : \"\";\n\treturn [\n\t\t`lint_run status: ${details.status}`,\n\t\t`runner: ${details.resolvedRunner}`,\n\t\t`mode: ${details.mode}`,\n\t\t`command: ${details.resolvedCommand}${argsText}`,\n\t\t`cwd: ${details.cwd}`,\n\t\t`exit_code: ${details.exitCode}`,\n\t\t`duration_ms: ${details.durationMs}`,\n\t\t\"\",\n\t\toutput,\n\t].join(\"\\n\");\n}\n\nexport function createLintRunTool(cwd: string): AgentTool<typeof lintRunSchema> {\n\treturn {\n\t\tname: \"lint_run\",\n\t\tlabel: \"lint_run\",\n\t\tdescription:\n\t\t\t\"Structured lint runner with auto detection across npm/pnpm/yarn/bun scripts and eslint/prettier/stylelint direct execution. Returns normalized status without throwing on ordinary lint failures.\",\n\t\tparameters: lintRunSchema,\n\t\texecute: async (_toolCallId: string, input: LintRunToolInput, signal?: AbortSignal) => {\n\t\t\tconst executionCwd = resolveToCwd(input.path || \".\", cwd);\n\t\t\tconst timeoutSeconds = normalizeTimeoutSeconds(input.timeout);\n\t\t\tconst args = normalizeStringArray(input.args);\n\t\t\tconst targets = normalizeStringArray(input.targets);\n\t\t\tconst mode: LintRunMode = input.mode ?? \"check\";\n\t\t\tconst script = normalizeScriptName(input.script, mode);\n\t\t\tconst runner: LintRunRunner = input.runner ?? \"auto\";\n\n\t\t\tif (mode === \"check\") {\n\t\t\t\tconst conflictArg = hasCheckModeConflictArgs(args);\n\t\t\t\tif (conflictArg) {\n\t\t\t\t\tthrow new Error(`Argument \"${conflictArg}\" is incompatible with mode=check.`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst command = resolveLintCommand({\n\t\t\t\tcwd: executionCwd,\n\t\t\t\trunner,\n\t\t\t\tmode,\n\t\t\t\tscript,\n\t\t\t\targs,\n\t\t\t\ttargets,\n\t\t\t});\n\n\t\t\tconst result = await runVerificationCommand({\n\t\t\t\tcommand: command.command,\n\t\t\t\targs: command.args,\n\t\t\t\tcwd: executionCwd,\n\t\t\t\ttimeoutMs: timeoutSeconds * 1000,\n\t\t\t\tsignal,\n\t\t\t});\n\n\t\t\tconst status = mapLintStatus(result.exitCode);\n\t\t\tconst formatted = formatVerificationOutput(\n\t\t\t\tresult.stdout,\n\t\t\t\tresult.stderr,\n\t\t\t\tresult.captureTruncated,\n\t\t\t\t\"No lint output\",\n\t\t\t);\n\n\t\t\tconst details: LintRunToolDetails = {\n\t\t\t\tresolvedRunner: command.resolvedRunner,\n\t\t\t\tresolvedCommand: command.command,\n\t\t\t\tresolvedArgs: command.args,\n\t\t\t\tcwd: executionCwd,\n\t\t\t\tmode,\n\t\t\t\texitCode: result.exitCode,\n\t\t\t\tstatus,\n\t\t\t\tdurationMs: result.durationMs,\n\t\t\t\tcaptureTruncated: result.captureTruncated || undefined,\n\t\t\t\ttruncation: formatted.truncation,\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: renderSummary(details, formatted.text) }],\n\t\t\t\tdetails,\n\t\t\t};\n\t\t},\n\t};\n}\n\nexport const lintRunTool = createLintRunTool(process.cwd());\n\n"]}
@@ -0,0 +1,36 @@
1
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
2
+ import { type Static } from "@sinclair/typebox";
3
+ import type { TruncationResult } from "./truncate.js";
4
+ declare const testRunSchema: import("@sinclair/typebox").TObject<{
5
+ runner: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"auto">, import("@sinclair/typebox").TLiteral<"npm">, import("@sinclair/typebox").TLiteral<"pnpm">, import("@sinclair/typebox").TLiteral<"yarn">, import("@sinclair/typebox").TLiteral<"bun">, import("@sinclair/typebox").TLiteral<"vitest">, import("@sinclair/typebox").TLiteral<"jest">, import("@sinclair/typebox").TLiteral<"pytest">]>>;
6
+ script: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
7
+ args: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
8
+ path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
9
+ timeout: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
10
+ }>;
11
+ export type TestRunToolInput = Static<typeof testRunSchema>;
12
+ export type TestRunRunner = "auto" | "npm" | "pnpm" | "yarn" | "bun" | "vitest" | "jest" | "pytest";
13
+ export type TestRunStatus = "passed" | "failed" | "no_tests" | "error";
14
+ type ResolvedTestRunner = Exclude<TestRunRunner, "auto">;
15
+ export interface TestRunToolDetails {
16
+ resolvedRunner: ResolvedTestRunner;
17
+ resolvedCommand: string;
18
+ resolvedArgs: string[];
19
+ cwd: string;
20
+ exitCode: number;
21
+ status: TestRunStatus;
22
+ durationMs: number;
23
+ captureTruncated?: boolean;
24
+ truncation?: TruncationResult;
25
+ }
26
+ export declare const DEFAULT_TEST_RUN_TIMEOUT_SECONDS = 900;
27
+ export declare function createTestRunTool(cwd: string): AgentTool<typeof testRunSchema>;
28
+ export declare const testRunTool: AgentTool<import("@sinclair/typebox").TObject<{
29
+ runner: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"auto">, import("@sinclair/typebox").TLiteral<"npm">, import("@sinclair/typebox").TLiteral<"pnpm">, import("@sinclair/typebox").TLiteral<"yarn">, import("@sinclair/typebox").TLiteral<"bun">, import("@sinclair/typebox").TLiteral<"vitest">, import("@sinclair/typebox").TLiteral<"jest">, import("@sinclair/typebox").TLiteral<"pytest">]>>;
30
+ script: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
31
+ args: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
32
+ path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
33
+ timeout: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
34
+ }>, any>;
35
+ export {};
36
+ //# sourceMappingURL=test-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-run.d.ts","sourceRoot":"","sources":["../../../src/core/tools/test-run.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAatD,QAAA,MAAM,aAAa;;;;;;EA8BjB,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAC5D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AACpG,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAEvE,KAAK,kBAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AAQzD,MAAM,WAAW,kBAAkB;IAClC,cAAc,EAAE,kBAAkB,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAiMpD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,aAAa,CAAC,CA6E9E;AAED,eAAO,MAAM,WAAW;;;;;;QAAmC,CAAC"}
@@ -0,0 +1,255 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { Type } from "@sinclair/typebox";
4
+ import { resolveToCwd } from "./path-utils.js";
5
+ import { commandExists, detectPackageManager, ensureCommandOrThrow, formatVerificationOutput, readPackageJson, resolvePackageManagerExecInvocation, resolvePackageManagerRunInvocation, runVerificationCommand, } from "./verification-runner.js";
6
+ const testRunSchema = Type.Object({
7
+ runner: Type.Optional(Type.Union([
8
+ Type.Literal("auto"),
9
+ Type.Literal("npm"),
10
+ Type.Literal("pnpm"),
11
+ Type.Literal("yarn"),
12
+ Type.Literal("bun"),
13
+ Type.Literal("vitest"),
14
+ Type.Literal("jest"),
15
+ Type.Literal("pytest"),
16
+ ], {
17
+ description: "Test runner: auto | npm | pnpm | yarn | bun | vitest | jest | pytest",
18
+ })),
19
+ script: Type.Optional(Type.String({
20
+ description: "Package script for npm/pnpm/yarn/bun runners (default: test).",
21
+ })),
22
+ args: Type.Optional(Type.Array(Type.String(), {
23
+ description: "Additional arguments forwarded to the selected runner.",
24
+ })),
25
+ path: Type.Optional(Type.String({ description: "Working directory for running tests (default: current directory)." })),
26
+ timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (default: 900)." })),
27
+ });
28
+ export const DEFAULT_TEST_RUN_TIMEOUT_SECONDS = 900;
29
+ function normalizeTimeoutSeconds(raw) {
30
+ if (raw === undefined)
31
+ return DEFAULT_TEST_RUN_TIMEOUT_SECONDS;
32
+ const value = Math.floor(raw);
33
+ if (!Number.isFinite(value) || value <= 0) {
34
+ throw new Error("timeout must be a positive number.");
35
+ }
36
+ return value;
37
+ }
38
+ function normalizeStringArray(raw) {
39
+ return (raw ?? []).map((item) => String(item));
40
+ }
41
+ function normalizeScriptName(raw, fallback) {
42
+ const script = (raw ?? fallback).trim();
43
+ if (script.length === 0) {
44
+ throw new Error("script must not be empty.");
45
+ }
46
+ return script;
47
+ }
48
+ function hasAnyFile(cwd, fileNames) {
49
+ return fileNames.some((name) => existsSync(join(cwd, name)));
50
+ }
51
+ function hasVitestConfig(cwd) {
52
+ return hasAnyFile(cwd, [
53
+ "vitest.config.ts",
54
+ "vitest.config.js",
55
+ "vitest.config.mjs",
56
+ "vitest.config.cjs",
57
+ "vitest.config.mts",
58
+ "vitest.config.cts",
59
+ ]);
60
+ }
61
+ function hasJestConfig(cwd, packageJsonJest) {
62
+ if (packageJsonJest && typeof packageJsonJest === "object") {
63
+ return true;
64
+ }
65
+ return hasAnyFile(cwd, [
66
+ "jest.config.ts",
67
+ "jest.config.js",
68
+ "jest.config.mjs",
69
+ "jest.config.cjs",
70
+ "jest.config.json",
71
+ "jest.config.mts",
72
+ "jest.config.cts",
73
+ ]);
74
+ }
75
+ function hasPythonMarkers(cwd) {
76
+ return hasAnyFile(cwd, [
77
+ "pyproject.toml",
78
+ "pytest.ini",
79
+ "tox.ini",
80
+ "setup.cfg",
81
+ "requirements.txt",
82
+ "requirements-dev.txt",
83
+ ]);
84
+ }
85
+ function assertPackageManagerAvailable(packageManager) {
86
+ if (packageManager === "bun") {
87
+ ensureCommandOrThrow("bun", 'Command "bun" is required for bun-based test execution.');
88
+ return;
89
+ }
90
+ ensureCommandOrThrow(packageManager, `Command "${packageManager}" is required for test execution.`);
91
+ }
92
+ function resolveScriptBasedCommand(packageManager, script, args) {
93
+ assertPackageManagerAvailable(packageManager);
94
+ const invocation = resolvePackageManagerRunInvocation(packageManager, script, args);
95
+ return {
96
+ resolvedRunner: packageManager,
97
+ command: invocation.command,
98
+ args: invocation.args,
99
+ };
100
+ }
101
+ function resolveFrameworkCommand(packageManager, runner, args) {
102
+ assertPackageManagerAvailable(packageManager);
103
+ const invocation = resolvePackageManagerExecInvocation(packageManager, runner, args);
104
+ ensureCommandOrThrow(invocation.command, `Command "${invocation.command}" is required to run ${runner}. Install ${packageManager} tooling first.`);
105
+ return {
106
+ resolvedRunner: runner,
107
+ command: invocation.command,
108
+ args: invocation.args,
109
+ };
110
+ }
111
+ function resolvePytestCommand(args) {
112
+ if (commandExists("python3")) {
113
+ return {
114
+ resolvedRunner: "pytest",
115
+ command: "python3",
116
+ args: ["-m", "pytest", ...args],
117
+ };
118
+ }
119
+ if (commandExists("pytest")) {
120
+ return {
121
+ resolvedRunner: "pytest",
122
+ command: "pytest",
123
+ args,
124
+ };
125
+ }
126
+ throw new Error('No pytest runtime found. Install python3 + pytest or expose "pytest" in PATH.');
127
+ }
128
+ function resolveAutoRunner(cwd, script) {
129
+ const packageJson = readPackageJson(cwd);
130
+ if (packageJson?.scripts[script]) {
131
+ return detectPackageManager(cwd);
132
+ }
133
+ if (hasVitestConfig(cwd))
134
+ return "vitest";
135
+ if (hasJestConfig(cwd, packageJson?.raw?.jest))
136
+ return "jest";
137
+ if (hasPythonMarkers(cwd))
138
+ return "pytest";
139
+ throw new Error('Unable to auto-detect test runner. Expected package.json script, vitest/jest config, or python pytest markers.');
140
+ }
141
+ function resolveTestCommand(input) {
142
+ const packageJson = readPackageJson(input.cwd);
143
+ const detectedPackageManager = detectPackageManager(input.cwd);
144
+ let resolvedRunner;
145
+ if (input.runner === "auto") {
146
+ resolvedRunner = resolveAutoRunner(input.cwd, input.script);
147
+ }
148
+ else {
149
+ resolvedRunner = input.runner;
150
+ }
151
+ if (resolvedRunner === "npm" || resolvedRunner === "pnpm" || resolvedRunner === "yarn" || resolvedRunner === "bun") {
152
+ if (!packageJson) {
153
+ throw new Error(`package.json is required to run ${resolvedRunner} scripts.`);
154
+ }
155
+ if (!packageJson.scripts[input.script]) {
156
+ throw new Error(`Script "${input.script}" is not defined in package.json.`);
157
+ }
158
+ return resolveScriptBasedCommand(resolvedRunner, input.script, input.args);
159
+ }
160
+ if (resolvedRunner === "vitest" || resolvedRunner === "jest") {
161
+ return resolveFrameworkCommand(detectedPackageManager, resolvedRunner, input.args);
162
+ }
163
+ return resolvePytestCommand(input.args);
164
+ }
165
+ function mapTestStatus(resolvedRunner, exitCode) {
166
+ if (exitCode === 0)
167
+ return "passed";
168
+ if (resolvedRunner === "pytest" && exitCode === 5)
169
+ return "no_tests";
170
+ if (exitCode === 1)
171
+ return "failed";
172
+ return "error";
173
+ }
174
+ function indicatesPytestModuleMissing(output) {
175
+ return /No module named pytest|ModuleNotFoundError:\s*No module named ['"]pytest['"]/i.test(output);
176
+ }
177
+ function renderSummary(details, output) {
178
+ const argsText = details.resolvedArgs.length > 0 ? ` ${details.resolvedArgs.join(" ")}` : "";
179
+ return [
180
+ `test_run status: ${details.status}`,
181
+ `runner: ${details.resolvedRunner}`,
182
+ `command: ${details.resolvedCommand}${argsText}`,
183
+ `cwd: ${details.cwd}`,
184
+ `exit_code: ${details.exitCode}`,
185
+ `duration_ms: ${details.durationMs}`,
186
+ "",
187
+ output,
188
+ ].join("\n");
189
+ }
190
+ export function createTestRunTool(cwd) {
191
+ return {
192
+ name: "test_run",
193
+ label: "test_run",
194
+ description: "Structured test runner with auto detection across npm/pnpm/yarn/bun, vitest, jest, and pytest. Returns normalized status without throwing on ordinary test failures.",
195
+ parameters: testRunSchema,
196
+ execute: async (_toolCallId, input, signal) => {
197
+ const executionCwd = resolveToCwd(input.path || ".", cwd);
198
+ const timeoutSeconds = normalizeTimeoutSeconds(input.timeout);
199
+ const normalizedArgs = normalizeStringArray(input.args);
200
+ const script = normalizeScriptName(input.script, "test");
201
+ const runner = input.runner ?? "auto";
202
+ let command = resolveTestCommand({
203
+ cwd: executionCwd,
204
+ runner,
205
+ script,
206
+ args: normalizedArgs,
207
+ });
208
+ let result = await runVerificationCommand({
209
+ command: command.command,
210
+ args: command.args,
211
+ cwd: executionCwd,
212
+ timeoutMs: timeoutSeconds * 1000,
213
+ signal,
214
+ });
215
+ // python3 -m pytest fallback to bare pytest when pytest module is unavailable
216
+ if (command.resolvedRunner === "pytest" &&
217
+ command.command === "python3" &&
218
+ result.exitCode !== 0 &&
219
+ indicatesPytestModuleMissing(`${result.stdout}\n${result.stderr}`) &&
220
+ commandExists("pytest")) {
221
+ const fallback = await runVerificationCommand({
222
+ command: "pytest",
223
+ args: normalizedArgs,
224
+ cwd: executionCwd,
225
+ timeoutMs: timeoutSeconds * 1000,
226
+ signal,
227
+ });
228
+ command = { resolvedRunner: "pytest", command: "pytest", args: normalizedArgs };
229
+ result = {
230
+ ...fallback,
231
+ durationMs: result.durationMs + fallback.durationMs,
232
+ };
233
+ }
234
+ const status = mapTestStatus(command.resolvedRunner, result.exitCode);
235
+ const formatted = formatVerificationOutput(result.stdout, result.stderr, result.captureTruncated, "No test output");
236
+ const details = {
237
+ resolvedRunner: command.resolvedRunner,
238
+ resolvedCommand: command.command,
239
+ resolvedArgs: command.args,
240
+ cwd: executionCwd,
241
+ exitCode: result.exitCode,
242
+ status,
243
+ durationMs: result.durationMs,
244
+ captureTruncated: result.captureTruncated || undefined,
245
+ truncation: formatted.truncation,
246
+ };
247
+ return {
248
+ content: [{ type: "text", text: renderSummary(details, formatted.text) }],
249
+ details,
250
+ };
251
+ },
252
+ };
253
+ }
254
+ export const testRunTool = createTestRunTool(process.cwd());
255
+ //# sourceMappingURL=test-run.js.map