@yuaone/tools 0.1.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.
Files changed (87) hide show
  1. package/LICENSE +663 -0
  2. package/README.md +15 -0
  3. package/dist/__tests__/file-edit.test.d.ts +8 -0
  4. package/dist/__tests__/file-edit.test.d.ts.map +1 -0
  5. package/dist/__tests__/file-edit.test.js +125 -0
  6. package/dist/__tests__/file-edit.test.js.map +1 -0
  7. package/dist/__tests__/registry.test.d.ts +7 -0
  8. package/dist/__tests__/registry.test.d.ts.map +1 -0
  9. package/dist/__tests__/registry.test.js +83 -0
  10. package/dist/__tests__/registry.test.js.map +1 -0
  11. package/dist/__tests__/validators.test.d.ts +8 -0
  12. package/dist/__tests__/validators.test.d.ts.map +1 -0
  13. package/dist/__tests__/validators.test.js +189 -0
  14. package/dist/__tests__/validators.test.js.map +1 -0
  15. package/dist/base-tool.d.ts +45 -0
  16. package/dist/base-tool.d.ts.map +1 -0
  17. package/dist/base-tool.js +87 -0
  18. package/dist/base-tool.js.map +1 -0
  19. package/dist/browser-tool.d.ts +39 -0
  20. package/dist/browser-tool.d.ts.map +1 -0
  21. package/dist/browser-tool.js +518 -0
  22. package/dist/browser-tool.js.map +1 -0
  23. package/dist/code-search.d.ts +42 -0
  24. package/dist/code-search.d.ts.map +1 -0
  25. package/dist/code-search.js +298 -0
  26. package/dist/code-search.js.map +1 -0
  27. package/dist/design-tools.d.ts +70 -0
  28. package/dist/design-tools.d.ts.map +1 -0
  29. package/dist/design-tools.js +471 -0
  30. package/dist/design-tools.js.map +1 -0
  31. package/dist/dev-server-manager.d.ts +32 -0
  32. package/dist/dev-server-manager.d.ts.map +1 -0
  33. package/dist/dev-server-manager.js +183 -0
  34. package/dist/dev-server-manager.js.map +1 -0
  35. package/dist/file-edit.d.ts +19 -0
  36. package/dist/file-edit.d.ts.map +1 -0
  37. package/dist/file-edit.js +217 -0
  38. package/dist/file-edit.js.map +1 -0
  39. package/dist/file-read.d.ts +19 -0
  40. package/dist/file-read.d.ts.map +1 -0
  41. package/dist/file-read.js +142 -0
  42. package/dist/file-read.js.map +1 -0
  43. package/dist/file-write.d.ts +18 -0
  44. package/dist/file-write.d.ts.map +1 -0
  45. package/dist/file-write.js +139 -0
  46. package/dist/file-write.js.map +1 -0
  47. package/dist/git-ops.d.ts +25 -0
  48. package/dist/git-ops.d.ts.map +1 -0
  49. package/dist/git-ops.js +219 -0
  50. package/dist/git-ops.js.map +1 -0
  51. package/dist/glob.d.ts +18 -0
  52. package/dist/glob.d.ts.map +1 -0
  53. package/dist/glob.js +91 -0
  54. package/dist/glob.js.map +1 -0
  55. package/dist/grep.d.ts +19 -0
  56. package/dist/grep.d.ts.map +1 -0
  57. package/dist/grep.js +177 -0
  58. package/dist/grep.js.map +1 -0
  59. package/dist/index.d.ts +27 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +29 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/security-scan.d.ts +62 -0
  64. package/dist/security-scan.d.ts.map +1 -0
  65. package/dist/security-scan.js +445 -0
  66. package/dist/security-scan.js.map +1 -0
  67. package/dist/shell-exec.d.ts +20 -0
  68. package/dist/shell-exec.d.ts.map +1 -0
  69. package/dist/shell-exec.js +206 -0
  70. package/dist/shell-exec.js.map +1 -0
  71. package/dist/test-run.d.ts +51 -0
  72. package/dist/test-run.d.ts.map +1 -0
  73. package/dist/test-run.js +359 -0
  74. package/dist/test-run.js.map +1 -0
  75. package/dist/tool-registry.d.ts +70 -0
  76. package/dist/tool-registry.d.ts.map +1 -0
  77. package/dist/tool-registry.js +181 -0
  78. package/dist/tool-registry.js.map +1 -0
  79. package/dist/types.d.ts +137 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +8 -0
  82. package/dist/types.js.map +1 -0
  83. package/dist/validators.d.ts +57 -0
  84. package/dist/validators.d.ts.map +1 -0
  85. package/dist/validators.js +218 -0
  86. package/dist/validators.js.map +1 -0
  87. package/package.json +42 -0
@@ -0,0 +1,206 @@
1
+ /**
2
+ * @yuaone/tools — shell_exec tool
3
+ *
4
+ * Executes a command using execFile (no shell interpretation).
5
+ * - executable + args[] pattern (not a string command)
6
+ * - Shell metacharacter validation
7
+ * - Blocked commands (rm -rf /, sudo, chmod 777, etc.)
8
+ * - 30-second default timeout
9
+ * - stdout/stderr separate return
10
+ */
11
+ import { execFile } from 'node:child_process';
12
+ import { BaseTool } from './base-tool.js';
13
+ import { validateNoShellMeta, validateCommand, validatePath } from './validators.js';
14
+ const DEFAULT_TIMEOUT = 30_000;
15
+ const MAX_STDOUT = 100_000; // 100KB
16
+ const MAX_STDERR = 50_000; // 50KB
17
+ export class ShellExecTool extends BaseTool {
18
+ name = 'shell_exec';
19
+ description = 'Execute a command with explicit executable and args (no shell interpretation). ' +
20
+ 'Use for build tools, test runners, linters, etc.';
21
+ riskLevel = 'critical';
22
+ parameters = {
23
+ executable: {
24
+ type: 'string',
25
+ description: 'Executable name or path (e.g., "npx", "tsc", "node")',
26
+ required: true,
27
+ },
28
+ args: {
29
+ type: 'array',
30
+ description: 'Argument array (passed directly, no shell interpretation)',
31
+ required: true,
32
+ items: { type: 'string', description: 'A single argument' },
33
+ },
34
+ cwd: {
35
+ type: 'string',
36
+ description: 'Working directory (relative to project root, default: project root)',
37
+ required: false,
38
+ },
39
+ timeout: {
40
+ type: 'number',
41
+ description: 'Timeout in milliseconds (default: 30000)',
42
+ required: false,
43
+ default: DEFAULT_TIMEOUT,
44
+ },
45
+ env: {
46
+ type: 'object',
47
+ description: 'Additional environment variables',
48
+ required: false,
49
+ },
50
+ };
51
+ async execute(args, workDir, abortSignal) {
52
+ const toolCallId = args._toolCallId ?? '';
53
+ const executable = args.executable;
54
+ const execArgs = args.args;
55
+ const cwd = args.cwd;
56
+ const timeout = args.timeout ?? DEFAULT_TIMEOUT;
57
+ const env = args.env;
58
+ if (!executable) {
59
+ return this.fail(toolCallId, 'Missing required parameter: executable');
60
+ }
61
+ if (!execArgs || !Array.isArray(execArgs)) {
62
+ return this.fail(toolCallId, 'Missing required parameter: args (must be an array)');
63
+ }
64
+ // Block shell binaries and command wrappers that can bypass tool validation
65
+ const SHELL_BINARIES = new Set(['bash', 'sh', 'zsh', 'dash', 'csh', 'ksh', 'fish']);
66
+ const COMMAND_WRAPPERS = new Set([
67
+ 'env', 'xargs', 'nohup', 'strace', 'ltrace', 'gdb',
68
+ 'script', 'expect', 'unbuffer', 'setsid', 'timeout',
69
+ ]);
70
+ const execBase = executable.split('/').pop() ?? executable;
71
+ if (SHELL_BINARIES.has(execBase)) {
72
+ return this.fail(toolCallId, `Shell binary "${execBase}" cannot be executed directly. ` +
73
+ 'Use specific tool commands instead (e.g., "node", "pnpm", "git").');
74
+ }
75
+ if (COMMAND_WRAPPERS.has(execBase)) {
76
+ return this.fail(toolCallId, `Command wrapper "${execBase}" is blocked — it can be used to bypass security controls. ` +
77
+ 'Execute the target command directly instead.');
78
+ }
79
+ // Validate no shell metacharacters
80
+ try {
81
+ validateNoShellMeta(executable, execArgs);
82
+ }
83
+ catch (err) {
84
+ return this.fail(toolCallId, err.message);
85
+ }
86
+ // Validate command is not blocked
87
+ try {
88
+ validateCommand(executable, execArgs);
89
+ }
90
+ catch (err) {
91
+ return this.fail(toolCallId, err.message);
92
+ }
93
+ // Resolve cwd
94
+ let resolvedCwd = workDir;
95
+ if (cwd) {
96
+ try {
97
+ resolvedCwd = validatePath(cwd, workDir);
98
+ }
99
+ catch (err) {
100
+ return this.fail(toolCallId, err.message);
101
+ }
102
+ }
103
+ // Execute
104
+ const startTime = Date.now();
105
+ try {
106
+ const result = await new Promise((resolve) => {
107
+ // Check if already aborted before starting
108
+ if (abortSignal?.aborted) {
109
+ resolve({ stdout: '', stderr: '', exitCode: 1, timedOut: false });
110
+ return;
111
+ }
112
+ const child = execFile(executable, execArgs, {
113
+ cwd: resolvedCwd,
114
+ timeout,
115
+ maxBuffer: MAX_STDOUT + MAX_STDERR,
116
+ env: env ? { ...process.env, ...sanitizeEnv(env) } : process.env,
117
+ }, (error, stdout, stderr) => {
118
+ const execError = error;
119
+ let exitCode;
120
+ if (execError && typeof execError.code === 'number') {
121
+ exitCode = execError.code;
122
+ }
123
+ else if (execError && 'status' in execError && typeof execError.status === 'number') {
124
+ exitCode = execError.status;
125
+ }
126
+ else {
127
+ exitCode = execError ? 1 : 0;
128
+ }
129
+ const timedOut = execError !== null && 'killed' in (execError ?? {}) && execError?.killed === true;
130
+ resolve({
131
+ stdout: truncateStr(String(stdout ?? ''), MAX_STDOUT),
132
+ stderr: truncateStr(String(stderr ?? ''), MAX_STDERR),
133
+ exitCode: typeof exitCode === 'number' ? exitCode : 1,
134
+ timedOut,
135
+ });
136
+ });
137
+ // Wire AbortSignal to kill the child process
138
+ if (abortSignal) {
139
+ const onAbort = () => {
140
+ child.kill('SIGTERM');
141
+ // If SIGTERM doesn't work, escalate to SIGKILL after 3s
142
+ setTimeout(() => {
143
+ if (!child.killed) {
144
+ child.kill('SIGKILL');
145
+ }
146
+ }, 3000).unref();
147
+ };
148
+ abortSignal.addEventListener('abort', onAbort, { once: true });
149
+ // Clean up listener when child exits
150
+ child.on('exit', () => {
151
+ abortSignal.removeEventListener('abort', onAbort);
152
+ });
153
+ }
154
+ });
155
+ const durationMs = Date.now() - startTime;
156
+ let output = '';
157
+ if (result.stdout) {
158
+ output += `[stdout]\n${result.stdout}\n`;
159
+ }
160
+ if (result.stderr) {
161
+ output += `[stderr]\n${result.stderr}\n`;
162
+ }
163
+ if (result.timedOut) {
164
+ output += `\n[TIMED OUT after ${timeout}ms]`;
165
+ }
166
+ output += `\n[exit code: ${result.exitCode}] [duration: ${durationMs}ms]`;
167
+ return {
168
+ tool_call_id: toolCallId,
169
+ name: this.name,
170
+ success: result.exitCode === 0 && !result.timedOut,
171
+ output: this.truncateOutput(output),
172
+ durationMs,
173
+ };
174
+ }
175
+ catch (err) {
176
+ const durationMs = Date.now() - startTime;
177
+ return this.fail(toolCallId, `Execution failed: ${err.message} [duration: ${durationMs}ms]`);
178
+ }
179
+ }
180
+ }
181
+ /**
182
+ * Strip dangerous environment variables that could enable arbitrary code execution.
183
+ * Blocks PATH override, dynamic linker injection, and interpreter hooks.
184
+ */
185
+ const BLOCKED_ENV_VARS = new Set([
186
+ 'PATH', 'LD_PRELOAD', 'LD_LIBRARY_PATH', 'DYLD_INSERT_LIBRARIES',
187
+ 'DYLD_LIBRARY_PATH', 'NODE_OPTIONS', 'PYTHONPATH', 'PYTHONSTARTUP',
188
+ 'PERL5OPT', 'PERL5LIB', 'RUBYOPT', 'RUBYLIB',
189
+ 'SHELL', 'BASH_ENV', 'ENV', 'CDPATH',
190
+ 'IFS', 'SHELLOPTS', 'BASHOPTS',
191
+ ]);
192
+ function sanitizeEnv(env) {
193
+ const safe = {};
194
+ for (const [key, value] of Object.entries(env)) {
195
+ if (!BLOCKED_ENV_VARS.has(key.toUpperCase())) {
196
+ safe[key] = value;
197
+ }
198
+ }
199
+ return safe;
200
+ }
201
+ function truncateStr(s, max) {
202
+ if (s.length <= max)
203
+ return s;
204
+ return s.slice(-max) + `\n... (truncated, showing last ${max} chars)`;
205
+ }
206
+ //# sourceMappingURL=shell-exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-exec.js","sourceRoot":"","sources":["../src/shell-exec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @yuaone/tools — test_run tool
3
+ *
4
+ * Test framework auto-detection + execution.
5
+ *
6
+ * Detection order:
7
+ * 1. package.json scripts.test
8
+ * 2. jest.config / vitest.config / pytest.ini config files
9
+ * 3. Error if no framework detected
10
+ *
11
+ * Supports: Jest (--json), Vitest (--reporter=json), Pytest (--tb=short)
12
+ *
13
+ * riskLevel: 'medium' (tests execute code)
14
+ */
15
+ import type { ParameterDef, RiskLevel, ToolResult } from './types.js';
16
+ import { BaseTool } from './base-tool.js';
17
+ export declare class TestRunTool extends BaseTool {
18
+ readonly name = "test_run";
19
+ readonly description: string;
20
+ readonly riskLevel: RiskLevel;
21
+ readonly parameters: Record<string, ParameterDef>;
22
+ execute(args: Record<string, unknown>, workDir: string): Promise<ToolResult>;
23
+ /**
24
+ * Detect test framework from project configuration.
25
+ */
26
+ private detectFramework;
27
+ /**
28
+ * Build the executable and args for the detected framework.
29
+ */
30
+ private buildCommand;
31
+ /**
32
+ * Execute the test command using execFile (no shell injection).
33
+ */
34
+ private runTest;
35
+ /**
36
+ * Parse test output into structured results.
37
+ */
38
+ private parseResults;
39
+ private parseJestResults;
40
+ private parseVitestResults;
41
+ private parsePytestResults;
42
+ /**
43
+ * Fallback parser for raw text output when JSON parsing fails.
44
+ */
45
+ private parseRawOutput;
46
+ /**
47
+ * Format the output for the agent.
48
+ */
49
+ private formatOutput;
50
+ }
51
+ //# sourceMappingURL=test-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-run.d.ts","sourceRoot":"","sources":["../src/test-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgB1C,qBAAa,WAAY,SAAQ,QAAQ;IACvC,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,WAAW,SAEsD;IAC1E,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAY;IAEzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAmB/C;IAEI,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA4DlF;;OAEG;YACW,eAAe;IAgD7B;;OAEG;IACH,OAAO,CAAC,YAAY;IA8BpB;;OAEG;IACH,OAAO,CAAC,OAAO;IA4Bf;;OAEG;IACH,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,gBAAgB;IAkDxB,OAAO,CAAC,kBAAkB;IAiD1B,OAAO,CAAC,kBAAkB;IA4B1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,YAAY;CAkCrB"}
@@ -0,0 +1,359 @@
1
+ /**
2
+ * @yuaone/tools — test_run tool
3
+ *
4
+ * Test framework auto-detection + execution.
5
+ *
6
+ * Detection order:
7
+ * 1. package.json scripts.test
8
+ * 2. jest.config / vitest.config / pytest.ini config files
9
+ * 3. Error if no framework detected
10
+ *
11
+ * Supports: Jest (--json), Vitest (--reporter=json), Pytest (--tb=short)
12
+ *
13
+ * riskLevel: 'medium' (tests execute code)
14
+ */
15
+ import { execFile } from 'node:child_process';
16
+ import { readFile, access } from 'node:fs/promises';
17
+ import { join } from 'node:path';
18
+ import { BaseTool } from './base-tool.js';
19
+ const DEFAULT_TIMEOUT = 60_000; // 60s
20
+ const MAX_OUTPUT = 100_000; // 100KB
21
+ export class TestRunTool extends BaseTool {
22
+ name = 'test_run';
23
+ description = 'Run tests with auto-detected framework (Jest, Vitest, Pytest). ' +
24
+ 'Returns structured results with pass/fail counts and failure details.';
25
+ riskLevel = 'medium';
26
+ parameters = {
27
+ testPath: {
28
+ type: 'string',
29
+ description: 'Specific test file or directory to run (relative to project root)',
30
+ required: false,
31
+ },
32
+ framework: {
33
+ type: 'string',
34
+ description: 'Test framework to use (default: auto-detect)',
35
+ required: false,
36
+ enum: ['jest', 'vitest', 'pytest', 'auto'],
37
+ default: 'auto',
38
+ },
39
+ coverage: {
40
+ type: 'boolean',
41
+ description: 'Include coverage report',
42
+ required: false,
43
+ default: false,
44
+ },
45
+ };
46
+ async execute(args, workDir) {
47
+ const toolCallId = args._toolCallId ?? '';
48
+ const testPath = args.testPath;
49
+ const requestedFramework = args.framework ?? 'auto';
50
+ const coverage = args.coverage ?? false;
51
+ // Validate testPath if provided
52
+ if (testPath) {
53
+ try {
54
+ this.validatePath(testPath, workDir);
55
+ }
56
+ catch (err) {
57
+ return this.fail(toolCallId, err.message);
58
+ }
59
+ }
60
+ // Detect framework
61
+ let framework;
62
+ if (requestedFramework === 'auto') {
63
+ const detected = await this.detectFramework(workDir);
64
+ if (!detected) {
65
+ return this.fail(toolCallId, 'Could not detect test framework. No test script in package.json and no config files found (jest.config, vitest.config, pytest.ini).');
66
+ }
67
+ framework = detected;
68
+ }
69
+ else {
70
+ framework = requestedFramework;
71
+ }
72
+ // Build command
73
+ const { executable, cmdArgs } = this.buildCommand(framework, testPath, coverage);
74
+ // Execute
75
+ const startTime = Date.now();
76
+ try {
77
+ const result = await this.runTest(executable, cmdArgs, workDir, DEFAULT_TIMEOUT);
78
+ const durationMs = Date.now() - startTime;
79
+ // Parse results
80
+ const summary = this.parseResults(framework, result.stdout, result.stderr);
81
+ const output = this.formatOutput(framework, summary, durationMs, result.exitCode);
82
+ return {
83
+ tool_call_id: toolCallId,
84
+ name: this.name,
85
+ success: summary.failed === 0 && result.exitCode === 0,
86
+ output: this.truncateOutput(output),
87
+ durationMs,
88
+ };
89
+ }
90
+ catch (err) {
91
+ const durationMs = Date.now() - startTime;
92
+ return this.fail(toolCallId, `Test execution failed: ${err.message} [duration: ${durationMs}ms]`);
93
+ }
94
+ }
95
+ /**
96
+ * Detect test framework from project configuration.
97
+ */
98
+ async detectFramework(workDir) {
99
+ // 1. Check package.json scripts.test
100
+ try {
101
+ const pkgPath = join(workDir, 'package.json');
102
+ const pkgContent = await readFile(pkgPath, 'utf-8');
103
+ const pkg = JSON.parse(pkgContent);
104
+ const scripts = pkg.scripts;
105
+ if (scripts?.test) {
106
+ const testScript = scripts.test;
107
+ if (testScript.includes('vitest'))
108
+ return 'vitest';
109
+ if (testScript.includes('jest'))
110
+ return 'jest';
111
+ if (testScript.includes('pytest'))
112
+ return 'pytest';
113
+ }
114
+ }
115
+ catch {
116
+ // No package.json or invalid — continue checking config files
117
+ }
118
+ // 2. Check config files
119
+ const configChecks = [
120
+ { files: ['vitest.config.ts', 'vitest.config.js', 'vitest.config.mts'], framework: 'vitest' },
121
+ { files: ['jest.config.ts', 'jest.config.js', 'jest.config.cjs', 'jest.config.mjs'], framework: 'jest' },
122
+ { files: ['pytest.ini', 'pyproject.toml', 'setup.cfg'], framework: 'pytest' },
123
+ ];
124
+ for (const check of configChecks) {
125
+ for (const file of check.files) {
126
+ try {
127
+ await access(join(workDir, file));
128
+ // For pyproject.toml, verify it has pytest config
129
+ if (file === 'pyproject.toml') {
130
+ const content = await readFile(join(workDir, file), 'utf-8');
131
+ if (!content.includes('[tool.pytest') && !content.includes('pytest'))
132
+ continue;
133
+ }
134
+ if (file === 'setup.cfg') {
135
+ const content = await readFile(join(workDir, file), 'utf-8');
136
+ if (!content.includes('[tool:pytest]'))
137
+ continue;
138
+ }
139
+ return check.framework;
140
+ }
141
+ catch {
142
+ // File doesn't exist — continue
143
+ }
144
+ }
145
+ }
146
+ return null;
147
+ }
148
+ /**
149
+ * Build the executable and args for the detected framework.
150
+ */
151
+ buildCommand(framework, testPath, coverage) {
152
+ switch (framework) {
153
+ case 'jest': {
154
+ const cmdArgs = ['--json', '--no-coverage'];
155
+ if (coverage) {
156
+ cmdArgs[1] = '--coverage';
157
+ cmdArgs.push('--coverageReporters=json-summary');
158
+ }
159
+ if (testPath)
160
+ cmdArgs.push(testPath);
161
+ return { executable: 'npx', cmdArgs: ['jest', ...cmdArgs] };
162
+ }
163
+ case 'vitest': {
164
+ const cmdArgs = ['--reporter=json', '--run'];
165
+ if (coverage)
166
+ cmdArgs.push('--coverage');
167
+ if (testPath)
168
+ cmdArgs.push(testPath);
169
+ return { executable: 'npx', cmdArgs: ['vitest', ...cmdArgs] };
170
+ }
171
+ case 'pytest': {
172
+ const cmdArgs = ['--tb=short', '-q'];
173
+ if (coverage)
174
+ cmdArgs.push('--cov', '--cov-report=term');
175
+ if (testPath)
176
+ cmdArgs.push(testPath);
177
+ return { executable: 'python3', cmdArgs: ['-m', 'pytest', ...cmdArgs] };
178
+ }
179
+ }
180
+ }
181
+ /**
182
+ * Execute the test command using execFile (no shell injection).
183
+ */
184
+ runTest(executable, args, cwd, timeout) {
185
+ return new Promise((resolve) => {
186
+ execFile(executable, args, {
187
+ cwd,
188
+ timeout,
189
+ maxBuffer: MAX_OUTPUT * 2,
190
+ env: { ...process.env, FORCE_COLOR: '0', CI: 'true' },
191
+ }, (error, stdout, stderr) => {
192
+ const exitCode = error && typeof error.code === 'number' ? error.code : (error ? 1 : 0);
193
+ resolve({
194
+ stdout: String(stdout ?? ''),
195
+ stderr: String(stderr ?? ''),
196
+ exitCode,
197
+ });
198
+ });
199
+ });
200
+ }
201
+ /**
202
+ * Parse test output into structured results.
203
+ */
204
+ parseResults(framework, stdout, stderr) {
205
+ switch (framework) {
206
+ case 'jest':
207
+ return this.parseJestResults(stdout, stderr);
208
+ case 'vitest':
209
+ return this.parseVitestResults(stdout, stderr);
210
+ case 'pytest':
211
+ return this.parsePytestResults(stdout, stderr);
212
+ }
213
+ }
214
+ parseJestResults(stdout, stderr) {
215
+ // Jest --json outputs JSON to stdout
216
+ try {
217
+ // Find JSON in output (Jest may prepend non-JSON text)
218
+ const jsonStart = stdout.indexOf('{');
219
+ if (jsonStart >= 0) {
220
+ const json = JSON.parse(stdout.slice(jsonStart));
221
+ const failedTests = [];
222
+ if (json.testResults) {
223
+ for (const suite of json.testResults) {
224
+ if (suite.testResults) {
225
+ for (const test of suite.testResults) {
226
+ if (test.status === 'failed' && test.failureMessages) {
227
+ failedTests.push({
228
+ name: test.title ?? 'unknown',
229
+ error: test.failureMessages.join('\n').slice(0, 500),
230
+ });
231
+ }
232
+ }
233
+ }
234
+ }
235
+ }
236
+ return {
237
+ passed: json.numPassedTests ?? 0,
238
+ failed: json.numFailedTests ?? 0,
239
+ skipped: json.numPendingTests ?? 0,
240
+ failedTests,
241
+ stdout: stdout + stderr,
242
+ };
243
+ }
244
+ }
245
+ catch {
246
+ // JSON parse failed — fall through to raw output
247
+ }
248
+ return this.parseRawOutput(stdout, stderr);
249
+ }
250
+ parseVitestResults(stdout, stderr) {
251
+ // Vitest --reporter=json outputs JSON to stdout
252
+ try {
253
+ const jsonStart = stdout.indexOf('{');
254
+ if (jsonStart >= 0) {
255
+ const json = JSON.parse(stdout.slice(jsonStart));
256
+ const failedTests = [];
257
+ if (json.testResults) {
258
+ for (const suite of json.testResults) {
259
+ if (suite.assertionResults) {
260
+ for (const test of suite.assertionResults) {
261
+ if (test.status === 'failed' && test.failureMessages) {
262
+ failedTests.push({
263
+ name: test.title ?? 'unknown',
264
+ error: test.failureMessages.join('\n').slice(0, 500),
265
+ });
266
+ }
267
+ }
268
+ }
269
+ }
270
+ }
271
+ return {
272
+ passed: json.numPassedTests ?? 0,
273
+ failed: json.numFailedTests ?? 0,
274
+ skipped: json.numPendingTests ?? 0,
275
+ failedTests,
276
+ stdout: stdout + stderr,
277
+ };
278
+ }
279
+ }
280
+ catch {
281
+ // Fall through
282
+ }
283
+ return this.parseRawOutput(stdout, stderr);
284
+ }
285
+ parsePytestResults(stdout, stderr) {
286
+ const combined = stdout + stderr;
287
+ const failedTests = [];
288
+ // Parse pytest summary line: "X passed, Y failed, Z skipped"
289
+ let passed = 0;
290
+ let failed = 0;
291
+ let skipped = 0;
292
+ const summaryMatch = combined.match(/(\d+)\s+passed/);
293
+ if (summaryMatch)
294
+ passed = parseInt(summaryMatch[1], 10);
295
+ const failedMatch = combined.match(/(\d+)\s+failed/);
296
+ if (failedMatch)
297
+ failed = parseInt(failedMatch[1], 10);
298
+ const skippedMatch = combined.match(/(\d+)\s+skipped/);
299
+ if (skippedMatch)
300
+ skipped = parseInt(skippedMatch[1], 10);
301
+ // Extract FAILED test names
302
+ const failedPattern = /FAILED\s+(\S+)/g;
303
+ let match;
304
+ while ((match = failedPattern.exec(combined)) !== null) {
305
+ failedTests.push({ name: match[1], error: '' });
306
+ }
307
+ return { passed, failed, skipped, failedTests, stdout: combined };
308
+ }
309
+ /**
310
+ * Fallback parser for raw text output when JSON parsing fails.
311
+ */
312
+ parseRawOutput(stdout, stderr) {
313
+ const combined = stdout + stderr;
314
+ let passed = 0;
315
+ let failed = 0;
316
+ let skipped = 0;
317
+ // Try to extract numbers from common patterns
318
+ const passMatch = combined.match(/(\d+)\s+(?:pass(?:ed|ing)?|✓)/i);
319
+ if (passMatch)
320
+ passed = parseInt(passMatch[1], 10);
321
+ const failMatch = combined.match(/(\d+)\s+(?:fail(?:ed|ing|ure)?|✗|✕)/i);
322
+ if (failMatch)
323
+ failed = parseInt(failMatch[1], 10);
324
+ const skipMatch = combined.match(/(\d+)\s+(?:skip(?:ped)?|pending|todo)/i);
325
+ if (skipMatch)
326
+ skipped = parseInt(skipMatch[1], 10);
327
+ return { passed, failed, skipped, failedTests: [], stdout: combined };
328
+ }
329
+ /**
330
+ * Format the output for the agent.
331
+ */
332
+ formatOutput(framework, summary, durationMs, exitCode) {
333
+ const lines = [];
334
+ lines.push(`[Test Results — ${framework}]`);
335
+ lines.push(`Passed: ${summary.passed} | Failed: ${summary.failed} | Skipped: ${summary.skipped}`);
336
+ if (summary.coverage !== undefined) {
337
+ lines.push(`Coverage: ${summary.coverage}%`);
338
+ }
339
+ lines.push(`Duration: ${durationMs}ms | Exit code: ${exitCode}`);
340
+ if (summary.failedTests.length > 0) {
341
+ lines.push('');
342
+ lines.push('[Failed Tests]');
343
+ for (const t of summary.failedTests.slice(0, 20)) {
344
+ lines.push(` ✗ ${t.name}`);
345
+ if (t.error) {
346
+ lines.push(` ${t.error.split('\n')[0]}`);
347
+ }
348
+ }
349
+ if (summary.failedTests.length > 20) {
350
+ lines.push(` ... and ${summary.failedTests.length - 20} more`);
351
+ }
352
+ }
353
+ lines.push('');
354
+ lines.push('[Raw Output]');
355
+ lines.push(summary.stdout.slice(0, MAX_OUTPUT));
356
+ return lines.join('\n');
357
+ }
358
+ }
359
+ //# sourceMappingURL=test-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-run.js","sourceRoot":"","sources":["../src/test-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,MAAM;AACtC,MAAM,UAAU,GAAG,OAAO,CAAC,CAAK,QAAQ;AAaxC,MAAM,OAAO,WAAY,SAAQ,QAAQ;IAC9B,IAAI,GAAG,UAAU,CAAC;IAClB,WAAW,GAClB,iEAAiE;QACjE,uEAAuE,CAAC;IACjE,SAAS,GAAc,QAAQ,CAAC;IAEhC,UAAU,GAAiC;QAClD,QAAQ,EAAE;YACR,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,mEAAmE;YAChF,QAAQ,EAAE,KAAK;SAChB;QACD,SAAS,EAAE;YACT,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,8CAA8C;YAC3D,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC;YAC1C,OAAO,EAAE,MAAM;SAChB;QACD,QAAQ,EAAE;YACR,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,yBAAyB;YACtC,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,KAAK;SACf;KACF,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,IAA6B,EAAE,OAAe;QAC1D,MAAM,UAAU,GAAI,IAAI,CAAC,WAAsB,IAAI,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAA8B,CAAC;QACrD,MAAM,kBAAkB,GAAI,IAAI,CAAC,SAAoB,IAAI,MAAM,CAAC;QAChE,MAAM,QAAQ,GAAI,IAAI,CAAC,QAAoB,IAAI,KAAK,CAAC;QAErD,gCAAgC;QAChC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,IAAI,SAAoB,CAAC;QACzB,IAAI,kBAAkB,KAAK,MAAM,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACrD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,IAAI,CAAC,IAAI,CACd,UAAU,EACV,qIAAqI,CACtI,CAAC;YACJ,CAAC;YACD,SAAS,GAAG,QAAQ,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,kBAA+B,CAAC;QAC9C,CAAC;QAED,gBAAgB;QAChB,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEjF,UAAU;QACV,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;YACjF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAE1C,gBAAgB;YAChB,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAE3E,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YAElF,OAAO;gBACL,YAAY,EAAE,UAAU;gBACxB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;gBACtD,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;gBACnC,UAAU;aACX,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC1C,OAAO,IAAI,CAAC,IAAI,CACd,UAAU,EACV,0BAA2B,GAAa,CAAC,OAAO,eAAe,UAAU,KAAK,CAC/E,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,eAAe,CAAC,OAAe;QAC3C,qCAAqC;QACrC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;YAC9C,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAA4B,CAAC;YAC9D,MAAM,OAAO,GAAG,GAAG,CAAC,OAA6C,CAAC;YAElE,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;gBAClB,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;gBAChC,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBAAE,OAAO,QAAQ,CAAC;gBACnD,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,OAAO,MAAM,CAAC;gBAC/C,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBAAE,OAAO,QAAQ,CAAC;YACrD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;QAChE,CAAC;QAED,wBAAwB;QACxB,MAAM,YAAY,GAAqD;YACrE,EAAE,KAAK,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE;YAC7F,EAAE,KAAK,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE;YACxG,EAAE,KAAK,EAAE,CAAC,YAAY,EAAE,gBAAgB,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE;SAC9E,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;YACjC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC/B,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;oBAClC,kDAAkD;oBAClD,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;wBAC9B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;wBAC7D,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;4BAAE,SAAS;oBACjF,CAAC;oBACD,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;wBACzB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;wBAC7D,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;4BAAE,SAAS;oBACnD,CAAC;oBACD,OAAO,KAAK,CAAC,SAAS,CAAC;gBACzB,CAAC;gBAAC,MAAM,CAAC;oBACP,gCAAgC;gBAClC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACK,YAAY,CAClB,SAAoB,EACpB,QAAiB,EACjB,QAAkB;QAElB,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;gBAC5C,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;oBAC1B,OAAO,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;gBACnD,CAAC;gBACD,IAAI,QAAQ;oBAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACrC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;YAC9D,CAAC;YACD,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,OAAO,GAAG,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;gBAC7C,IAAI,QAAQ;oBAAE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBACzC,IAAI,QAAQ;oBAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACrC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;YAChE,CAAC;YACD,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,OAAO,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gBACrC,IAAI,QAAQ;oBAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;gBACzD,IAAI,QAAQ;oBAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACrC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;YAC1E,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,OAAO,CACb,UAAkB,EAClB,IAAc,EACd,GAAW,EACX,OAAe;QAEf,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,QAAQ,CACN,UAAU,EACV,IAAI,EACJ;gBACE,GAAG;gBACH,OAAO;gBACP,SAAS,EAAE,UAAU,GAAG,CAAC;gBACzB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE;aACtD,EACD,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACxB,MAAM,QAAQ,GAAG,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxF,OAAO,CAAC;oBACN,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;oBAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;oBAC5B,QAAQ;iBACT,CAAC,CAAC;YACL,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,SAAoB,EAAE,MAAc,EAAE,MAAc;QACvE,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC/C,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,MAAc,EAAE,MAAc;QACrD,qCAAqC;QACrC,IAAI,CAAC;YACH,uDAAuD;YACvD,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBACnB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAW9C,CAAC;gBAEF,MAAM,WAAW,GAA2C,EAAE,CAAC;gBAC/D,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;wBACrC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;4BACtB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;gCACrC,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;oCACrD,WAAW,CAAC,IAAI,CAAC;wCACf,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS;wCAC7B,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;qCACrD,CAAC,CAAC;gCACL,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,OAAO;oBACL,MAAM,EAAE,IAAI,CAAC,cAAc,IAAI,CAAC;oBAChC,MAAM,EAAE,IAAI,CAAC,cAAc,IAAI,CAAC;oBAChC,OAAO,EAAE,IAAI,CAAC,eAAe,IAAI,CAAC;oBAClC,WAAW;oBACX,MAAM,EAAE,MAAM,GAAG,MAAM;iBACxB,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;QAED,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAEO,kBAAkB,CAAC,MAAc,EAAE,MAAc;QACvD,gDAAgD;QAChD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBACnB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAW9C,CAAC;gBAEF,MAAM,WAAW,GAA2C,EAAE,CAAC;gBAC/D,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;wBACrC,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;4BAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;gCAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;oCACrD,WAAW,CAAC,IAAI,CAAC;wCACf,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS;wCAC7B,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;qCACrD,CAAC,CAAC;gCACL,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,OAAO;oBACL,MAAM,EAAE,IAAI,CAAC,cAAc,IAAI,CAAC;oBAChC,MAAM,EAAE,IAAI,CAAC,cAAc,IAAI,CAAC;oBAChC,OAAO,EAAE,IAAI,CAAC,eAAe,IAAI,CAAC;oBAClC,WAAW;oBACX,MAAM,EAAE,MAAM,GAAG,MAAM;iBACxB,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;QAED,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAEO,kBAAkB,CAAC,MAAc,EAAE,MAAc;QACvD,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;QACjC,MAAM,WAAW,GAA2C,EAAE,CAAC;QAE/D,6DAA6D;QAC7D,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACtD,IAAI,YAAY;YAAE,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEzD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACrD,IAAI,WAAW;YAAE,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEvD,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACvD,IAAI,YAAY;YAAE,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAE1D,4BAA4B;QAC5B,MAAM,aAAa,GAAG,iBAAiB,CAAC;QACxC,IAAI,KAAK,CAAC;QACV,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACvD,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACpE,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,MAAc,EAAE,MAAc;QACnD,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;QACjC,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,8CAA8C;QAC9C,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACnE,IAAI,SAAS;YAAE,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEnD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACzE,IAAI,SAAS;YAAE,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEnD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC3E,IAAI,SAAS;YAAE,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACxE,CAAC;IAED;;OAEG;IACK,YAAY,CAClB,SAAiB,EACjB,OAAoB,EACpB,UAAkB,EAClB,QAAgB;QAEhB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,mBAAmB,SAAS,GAAG,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,MAAM,cAAc,OAAO,CAAC,MAAM,eAAe,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAClG,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,aAAa,UAAU,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QAEjE,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBACjD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC5B,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;oBACZ,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;YACD,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBACpC,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;QAEhD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF"}