@syrin/cli 1.3.2 → 1.4.1

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 (150) hide show
  1. package/README.md +184 -152
  2. package/dist/cli/commands/config.d.ts +47 -0
  3. package/dist/cli/commands/config.js +360 -0
  4. package/dist/cli/commands/dev.d.ts +6 -0
  5. package/dist/cli/commands/dev.js +67 -15
  6. package/dist/cli/commands/doctor.js +49 -13
  7. package/dist/cli/commands/init.d.ts +2 -0
  8. package/dist/cli/commands/init.js +89 -18
  9. package/dist/cli/commands/status.d.ts +10 -0
  10. package/dist/cli/commands/status.js +162 -0
  11. package/dist/cli/index.js +211 -12
  12. package/dist/cli/prompts/init-prompt.d.ts +18 -0
  13. package/dist/cli/prompts/init-prompt.js +159 -99
  14. package/dist/cli/utils/command-error-handler.js +2 -5
  15. package/dist/config/env-checker.d.ts +12 -2
  16. package/dist/config/env-checker.js +88 -38
  17. package/dist/config/env-templates.d.ts +15 -0
  18. package/dist/config/env-templates.js +49 -0
  19. package/dist/config/generator.js +17 -0
  20. package/dist/config/global-loader.d.ts +50 -0
  21. package/dist/config/global-loader.js +244 -0
  22. package/dist/config/loader.d.ts +28 -0
  23. package/dist/config/loader.js +95 -9
  24. package/dist/config/merger.d.ts +37 -0
  25. package/dist/config/merger.js +68 -0
  26. package/dist/config/schema.d.ts +26 -1
  27. package/dist/config/schema.js +73 -8
  28. package/dist/config/types.d.ts +19 -0
  29. package/dist/config/types.js +26 -1
  30. package/dist/constants/messages.d.ts +7 -0
  31. package/dist/constants/messages.js +8 -0
  32. package/dist/constants/paths.d.ts +6 -0
  33. package/dist/constants/paths.js +10 -0
  34. package/dist/events/emitter.js +7 -7
  35. package/dist/index.js +0 -0
  36. package/dist/presentation/config-ui.d.ts +34 -0
  37. package/dist/presentation/config-ui.js +139 -0
  38. package/dist/presentation/doctor-ui.d.ts +11 -0
  39. package/dist/presentation/doctor-ui.js +52 -1
  40. package/dist/presentation/init-ui.d.ts +9 -0
  41. package/dist/presentation/init-ui.js +33 -0
  42. package/dist/runtime/analysis/analyser.js +2 -2
  43. package/dist/runtime/analysis/rules/warnings/w104-generic-description.d.ts +1 -1
  44. package/dist/runtime/analysis/rules/warnings/w104-generic-description.js +1 -1
  45. package/dist/runtime/dev/event-mapper.js +19 -3
  46. package/dist/runtime/dev/session.d.ts +4 -0
  47. package/dist/runtime/dev/session.js +52 -3
  48. package/dist/runtime/llm/ollama.js +4 -4
  49. package/dist/runtime/mcp/client/manager.js +3 -3
  50. package/dist/runtime/sandbox/executor.js +5 -5
  51. package/dist/runtime/test/orchestrator.js +4 -4
  52. package/dist/utils/editor.d.ts +37 -0
  53. package/dist/utils/editor.js +137 -0
  54. package/dist/utils/logger.d.ts +24 -6
  55. package/dist/utils/logger.js +51 -8
  56. package/package.json +23 -23
  57. package/dist/runtime/analysis/rules/errors/e001-missing-output-schema.d.ts +0 -22
  58. package/dist/runtime/analysis/rules/errors/e001-missing-output-schema.js +0 -30
  59. package/dist/runtime/analysis/rules/errors/e002-underspecified-input.d.ts +0 -24
  60. package/dist/runtime/analysis/rules/errors/e002-underspecified-input.js +0 -52
  61. package/dist/runtime/analysis/rules/errors/e003-type-mismatch.d.ts +0 -23
  62. package/dist/runtime/analysis/rules/errors/e003-type-mismatch.js +0 -73
  63. package/dist/runtime/analysis/rules/errors/e004-free-text-propagation.d.ts +0 -23
  64. package/dist/runtime/analysis/rules/errors/e004-free-text-propagation.js +0 -47
  65. package/dist/runtime/analysis/rules/errors/e005-tool-ambiguity.d.ts +0 -25
  66. package/dist/runtime/analysis/rules/errors/e005-tool-ambiguity.js +0 -73
  67. package/dist/runtime/analysis/rules/errors/e006-param-not-in-description.d.ts +0 -22
  68. package/dist/runtime/analysis/rules/errors/e006-param-not-in-description.js +0 -57
  69. package/dist/runtime/analysis/rules/errors/e007-output-not-guaranteed.d.ts +0 -23
  70. package/dist/runtime/analysis/rules/errors/e007-output-not-guaranteed.js +0 -56
  71. package/dist/runtime/analysis/rules/errors/e008-circular-dependency.d.ts +0 -22
  72. package/dist/runtime/analysis/rules/errors/e008-circular-dependency.js +0 -84
  73. package/dist/runtime/analysis/rules/errors/e009-implicit-user-input.d.ts +0 -23
  74. package/dist/runtime/analysis/rules/errors/e009-implicit-user-input.js +0 -89
  75. package/dist/runtime/analysis/rules/errors/e010-non-serializable.d.ts +0 -25
  76. package/dist/runtime/analysis/rules/errors/e010-non-serializable.js +0 -46
  77. package/dist/runtime/analysis/rules/errors/e011-missing-tool-description.d.ts +0 -24
  78. package/dist/runtime/analysis/rules/errors/e011-missing-tool-description.js +0 -33
  79. package/dist/runtime/analysis/rules/errors/e012-side-effect-detected.d.ts +0 -39
  80. package/dist/runtime/analysis/rules/errors/e012-side-effect-detected.js +0 -40
  81. package/dist/runtime/analysis/rules/errors/e013-non-deterministic-output.d.ts +0 -37
  82. package/dist/runtime/analysis/rules/errors/e013-non-deterministic-output.js +0 -34
  83. package/dist/runtime/analysis/rules/errors/e013-output-explosion.d.ts +0 -39
  84. package/dist/runtime/analysis/rules/errors/e013-output-explosion.js +0 -36
  85. package/dist/runtime/analysis/rules/errors/e014-hidden-dependency.d.ts +0 -42
  86. package/dist/runtime/analysis/rules/errors/e014-hidden-dependency.js +0 -46
  87. package/dist/runtime/analysis/rules/errors/e014-output-explosion.d.ts +0 -39
  88. package/dist/runtime/analysis/rules/errors/e014-output-explosion.js +0 -36
  89. package/dist/runtime/analysis/rules/errors/e015-hidden-dependency.d.ts +0 -42
  90. package/dist/runtime/analysis/rules/errors/e015-hidden-dependency.js +0 -46
  91. package/dist/runtime/analysis/rules/errors/e015-unbounded-execution.d.ts +0 -44
  92. package/dist/runtime/analysis/rules/errors/e015-unbounded-execution.js +0 -66
  93. package/dist/runtime/analysis/rules/errors/e016-output-validation-failed.d.ts +0 -43
  94. package/dist/runtime/analysis/rules/errors/e016-output-validation-failed.js +0 -42
  95. package/dist/runtime/analysis/rules/errors/e016-unbounded-execution.d.ts +0 -44
  96. package/dist/runtime/analysis/rules/errors/e016-unbounded-execution.js +0 -66
  97. package/dist/runtime/analysis/rules/errors/e017-input-validation-failed.d.ts +0 -57
  98. package/dist/runtime/analysis/rules/errors/e017-input-validation-failed.js +0 -80
  99. package/dist/runtime/analysis/rules/errors/e017-output-validation-failed.d.ts +0 -43
  100. package/dist/runtime/analysis/rules/errors/e017-output-validation-failed.js +0 -42
  101. package/dist/runtime/analysis/rules/errors/e018-input-validation-failed.d.ts +0 -57
  102. package/dist/runtime/analysis/rules/errors/e018-input-validation-failed.js +0 -80
  103. package/dist/runtime/analysis/rules/errors/e018-tool-execution-failed.d.ts +0 -38
  104. package/dist/runtime/analysis/rules/errors/e018-tool-execution-failed.js +0 -37
  105. package/dist/runtime/analysis/rules/errors/e019-tool-execution-failed.d.ts +0 -38
  106. package/dist/runtime/analysis/rules/errors/e019-tool-execution-failed.js +0 -37
  107. package/dist/runtime/analysis/rules/errors/e019-unexpected-test-result.d.ts +0 -65
  108. package/dist/runtime/analysis/rules/errors/e019-unexpected-test-result.js +0 -109
  109. package/dist/runtime/analysis/rules/errors/e020-unexpected-test-result.d.ts +0 -65
  110. package/dist/runtime/analysis/rules/errors/e020-unexpected-test-result.js +0 -109
  111. package/dist/runtime/analysis/rules/warnings/w001-implicit-dependency.d.ts +0 -22
  112. package/dist/runtime/analysis/rules/warnings/w001-implicit-dependency.js +0 -39
  113. package/dist/runtime/analysis/rules/warnings/w002-free-text-without-normalization.d.ts +0 -24
  114. package/dist/runtime/analysis/rules/warnings/w002-free-text-without-normalization.js +0 -40
  115. package/dist/runtime/analysis/rules/warnings/w003-missing-examples.d.ts +0 -22
  116. package/dist/runtime/analysis/rules/warnings/w003-missing-examples.js +0 -84
  117. package/dist/runtime/analysis/rules/warnings/w004-overloaded-responsibility.d.ts +0 -23
  118. package/dist/runtime/analysis/rules/warnings/w004-overloaded-responsibility.js +0 -96
  119. package/dist/runtime/analysis/rules/warnings/w005-generic-description.d.ts +0 -53
  120. package/dist/runtime/analysis/rules/warnings/w005-generic-description.js +0 -108
  121. package/dist/runtime/analysis/rules/warnings/w006-optional-as-required.d.ts +0 -22
  122. package/dist/runtime/analysis/rules/warnings/w006-optional-as-required.js +0 -44
  123. package/dist/runtime/analysis/rules/warnings/w007-broad-output-schema.d.ts +0 -23
  124. package/dist/runtime/analysis/rules/warnings/w007-broad-output-schema.js +0 -37
  125. package/dist/runtime/analysis/rules/warnings/w008-multiple-entry-points.d.ts +0 -22
  126. package/dist/runtime/analysis/rules/warnings/w008-multiple-entry-points.js +0 -97
  127. package/dist/runtime/analysis/rules/warnings/w009-hidden-side-effects.d.ts +0 -23
  128. package/dist/runtime/analysis/rules/warnings/w009-hidden-side-effects.js +0 -88
  129. package/dist/runtime/analysis/rules/warnings/w010-output-not-reusable.d.ts +0 -22
  130. package/dist/runtime/analysis/rules/warnings/w010-output-not-reusable.js +0 -81
  131. package/dist/runtime/analysis/rules/warnings/w021-weak-schema.d.ts +0 -40
  132. package/dist/runtime/analysis/rules/warnings/w021-weak-schema.js +0 -32
  133. package/dist/runtime/analysis/rules/warnings/w022-high-entropy-output.d.ts +0 -39
  134. package/dist/runtime/analysis/rules/warnings/w022-high-entropy-output.js +0 -36
  135. package/dist/runtime/analysis/rules/warnings/w023-unstable-defaults.d.ts +0 -38
  136. package/dist/runtime/analysis/rules/warnings/w023-unstable-defaults.js +0 -36
  137. package/dist/runtime/test/dependency-tracker.d.ts +0 -66
  138. package/dist/runtime/test/dependency-tracker.js +0 -80
  139. package/dist/runtime/test/formatters.d.ts +0 -18
  140. package/dist/runtime/test/formatters.js +0 -172
  141. package/dist/runtime/test/input-generator.d.ts +0 -33
  142. package/dist/runtime/test/input-generator.js +0 -498
  143. package/dist/runtime/test/mcp-root-detector.d.ts +0 -31
  144. package/dist/runtime/test/mcp-root-detector.js +0 -105
  145. package/dist/runtime/test/retry-tester.d.ts +0 -44
  146. package/dist/runtime/test/retry-tester.js +0 -103
  147. package/dist/runtime/test/synthetic-input-generator.d.ts +0 -11
  148. package/dist/runtime/test/synthetic-input-generator.js +0 -154
  149. package/dist/runtime/test/test-runner.d.ts +0 -28
  150. package/dist/runtime/test/test-runner.js +0 -55
@@ -1,103 +0,0 @@
1
- /**
2
- * Retry scenario tester.
3
- * Tests tools against agent retry patterns (retry on failure, timeout, error).
4
- */
5
- import { ToolExecutionErrorType } from '../../runtime/sandbox/index.js';
6
- /**
7
- * Get error type from an unknown error object.
8
- * @param error - Error object (may be ToolExecutionError or unknown)
9
- * @returns ToolExecutionErrorType if error has errorType, undefined otherwise
10
- */
11
- function getErrorType(error) {
12
- if (error && typeof error === 'object' && 'errorType' in error) {
13
- return error.errorType;
14
- }
15
- return undefined;
16
- }
17
- /**
18
- * Test tool retry behavior.
19
- * Simulates agent retry patterns to ensure tools handle retries gracefully.
20
- *
21
- * Note: Idempotency (output consistency across retries) is checked separately
22
- * This tester focuses on retry reliability.
23
- */
24
- export async function testRetryBehavior(executor, toolName, testInput, config = {}, toolTimeoutMs) {
25
- const maxRetries = config.maxRetries ?? 3;
26
- const retryDelayMs = config.retryDelayMs ?? 100;
27
- const testRetryOnFailure = config.testRetryOnFailure ?? true;
28
- const testRetryOnTimeout = config.testRetryOnTimeout ?? true;
29
- const testRetryOnConnectionError = config.testRetryOnConnectionError ?? true;
30
- const results = [];
31
- const issues = [];
32
- let eventuallySucceeded = false;
33
- // Run initial execution
34
- let executionResults = await executor.executeTool(toolName, [testInput], toolTimeoutMs);
35
- let lastResult = executionResults[0];
36
- if (lastResult) {
37
- results.push(lastResult);
38
- }
39
- // If first attempt succeeded, test retry behavior
40
- if (lastResult && lastResult.success) {
41
- eventuallySucceeded = true;
42
- // Retry to check reliability
43
- for (let attempt = 1; attempt < maxRetries; attempt++) {
44
- await new Promise(resolve => setTimeout(resolve, retryDelayMs));
45
- executionResults = await executor.executeTool(toolName, [testInput], toolTimeoutMs);
46
- const retryResult = executionResults[0];
47
- if (retryResult) {
48
- results.push(retryResult);
49
- // Check reliability (retry shouldn't fail if first attempt succeeded)
50
- if (!retryResult.success) {
51
- issues.push(`Retry ${attempt + 1} failed (was successful on first attempt) - tool may be unreliable under retry scenarios`);
52
- }
53
- // Note: We don't report idempotency issues here as tools can be idempotent by design
54
- }
55
- }
56
- }
57
- else if (lastResult && !lastResult.success) {
58
- // First attempt failed - test retry on failure
59
- if (testRetryOnFailure) {
60
- const errorType = getErrorType(lastResult.error);
61
- const shouldRetry = errorType === ToolExecutionErrorType.EXECUTION_ERROR ||
62
- errorType === ToolExecutionErrorType.UNKNOWN;
63
- if (shouldRetry) {
64
- // Retry on failure
65
- for (let attempt = 1; attempt < maxRetries; attempt++) {
66
- await new Promise(resolve => setTimeout(resolve, retryDelayMs));
67
- executionResults = await executor.executeTool(toolName, [testInput], toolTimeoutMs);
68
- const retryResult = executionResults[0];
69
- if (retryResult) {
70
- results.push(retryResult);
71
- if (retryResult.success) {
72
- eventuallySucceeded = true;
73
- issues.push(`Tool recovered after ${attempt + 1} retry attempts (initially failed)`);
74
- break;
75
- }
76
- }
77
- }
78
- if (!eventuallySucceeded) {
79
- issues.push(`Tool failed consistently after ${maxRetries} retry attempts`);
80
- }
81
- }
82
- }
83
- // Test retry on timeout
84
- if (testRetryOnTimeout && lastResult.timedOut === true) {
85
- issues.push(`Tool timed out - agents may retry, causing delays`);
86
- }
87
- // Test retry on connection error
88
- if (testRetryOnConnectionError && !lastResult.success) {
89
- const errorType = getErrorType(lastResult.error);
90
- if (errorType === ToolExecutionErrorType.CONNECTION_ERROR) {
91
- issues.push(`Connection error detected - agents may retry, causing delays`);
92
- }
93
- }
94
- }
95
- return {
96
- testInput,
97
- attempts: results.length,
98
- eventuallySucceeded,
99
- results,
100
- issues,
101
- };
102
- }
103
- //# sourceMappingURL=retry-tester.js.map
@@ -1,11 +0,0 @@
1
- /**
2
- * Generate system-level synthetic test inputs from tool input schema.
3
- * These inputs test edge cases, type validations, and boundary conditions.
4
- */
5
- /**
6
- * Generate synthetic test inputs from a JSON schema.
7
- * @param schema - Input schema (JSON Schema format)
8
- * @returns Array of synthetic test inputs
9
- */
10
- export declare function generateSyntheticInputs(schema: unknown): Array<Record<string, unknown>>;
11
- //# sourceMappingURL=synthetic-input-generator.d.ts.map
@@ -1,154 +0,0 @@
1
- /**
2
- * Generate system-level synthetic test inputs from tool input schema.
3
- * These inputs test edge cases, type validations, and boundary conditions.
4
- */
5
- /**
6
- * Generate synthetic test inputs from a JSON schema.
7
- * @param schema - Input schema (JSON Schema format)
8
- * @returns Array of synthetic test inputs
9
- */
10
- export function generateSyntheticInputs(schema) {
11
- const inputs = [];
12
- if (!schema || typeof schema !== 'object') {
13
- return inputs;
14
- }
15
- const jsonSchema = schema;
16
- // Handle object schemas with properties
17
- if (jsonSchema.type === 'object' && jsonSchema.properties) {
18
- const properties = jsonSchema.properties;
19
- const required = jsonSchema.required || [];
20
- // Generate edge case inputs for each property
21
- for (const [propName, propSchema] of Object.entries(properties)) {
22
- const prop = propSchema;
23
- const propType = Array.isArray(prop.type) ? prop.type[0] : prop.type;
24
- // Generate edge case values based on property type
25
- const edgeCases = generateEdgeCasesForProperty(propName, prop, propType);
26
- for (const edgeCase of edgeCases) {
27
- inputs.push(edgeCase);
28
- }
29
- }
30
- // Generate input with all required fields (minimal valid input)
31
- if (required.length > 0) {
32
- const minimalInput = {};
33
- for (const reqField of required) {
34
- const propSchema = properties[reqField];
35
- const propType = Array.isArray(propSchema?.type)
36
- ? propSchema.type[0]
37
- : propSchema?.type;
38
- minimalInput[reqField] = getDefaultValue(propType);
39
- }
40
- inputs.push(minimalInput);
41
- }
42
- }
43
- // Remove duplicates
44
- return removeDuplicateInputs(inputs);
45
- }
46
- /**
47
- * Generate edge case values for a specific property.
48
- */
49
- function generateEdgeCasesForProperty(propName, propSchema, propType) {
50
- const edgeCases = [];
51
- if (propSchema.enum) {
52
- // For enums, test each enum value
53
- for (const enumValue of propSchema.enum) {
54
- edgeCases.push({ [propName]: enumValue });
55
- }
56
- }
57
- else {
58
- switch (propType) {
59
- case 'string':
60
- edgeCases.push({ [propName]: '' }, // Empty string
61
- { [propName]: 'test' }, // Normal string
62
- ...(propSchema.minLength !== undefined ? [] : [
63
- { [propName]: 'a'.repeat(100) }, // Long string
64
- ]));
65
- break;
66
- case 'number':
67
- case 'integer':
68
- edgeCases.push({ [propName]: 0 }, { [propName]: 1 }, { [propName]: -1 }, ...(propSchema.minimum !== undefined ? [] : [
69
- { [propName]: Number.MAX_SAFE_INTEGER },
70
- ]), ...(propSchema.maximum !== undefined ? [] : [
71
- { [propName]: Number.MIN_SAFE_INTEGER },
72
- ]));
73
- break;
74
- case 'boolean':
75
- edgeCases.push({ [propName]: true }, { [propName]: false });
76
- break;
77
- case 'array':
78
- edgeCases.push({ [propName]: [] }, // Empty array
79
- { [propName]: [1, 2, 3] } // Array with values
80
- );
81
- break;
82
- case 'object':
83
- edgeCases.push({ [propName]: {} }, // Empty object
84
- { [propName]: { key: 'value' } } // Object with values
85
- );
86
- break;
87
- default:
88
- // For unknown types, generate a basic test value
89
- edgeCases.push({ [propName]: null });
90
- break;
91
- }
92
- }
93
- return edgeCases;
94
- }
95
- /**
96
- * Get a default value for a property type.
97
- */
98
- function getDefaultValue(propType) {
99
- switch (propType) {
100
- case 'string':
101
- return 'test';
102
- case 'number':
103
- case 'integer':
104
- return 0;
105
- case 'boolean':
106
- return false;
107
- case 'array':
108
- return [];
109
- case 'object':
110
- return {};
111
- default:
112
- return null;
113
- }
114
- }
115
- /**
116
- * Remove duplicate inputs by normalizing and comparing JSON representation.
117
- */
118
- function removeDuplicateInputs(inputs) {
119
- const seen = new Set();
120
- const unique = [];
121
- for (const input of inputs) {
122
- const normalized = deepSortObject(input);
123
- const key = JSON.stringify(normalized);
124
- if (!seen.has(key)) {
125
- seen.add(key);
126
- unique.push(input);
127
- }
128
- }
129
- return unique;
130
- }
131
- /**
132
- * Recursively sort object keys for deterministic comparison.
133
- */
134
- function deepSortObject(obj) {
135
- if (obj === null || obj === undefined) {
136
- return obj;
137
- }
138
- if (Array.isArray(obj)) {
139
- return obj.map(item => deepSortObject(item));
140
- }
141
- if (typeof obj === 'object') {
142
- const sorted = {};
143
- const keys = Object.keys(obj).sort();
144
- for (const key of keys) {
145
- const value = obj[key];
146
- if (value !== undefined) {
147
- sorted[key] = deepSortObject(value);
148
- }
149
- }
150
- return sorted;
151
- }
152
- return obj;
153
- }
154
- //# sourceMappingURL=synthetic-input-generator.js.map
@@ -1,28 +0,0 @@
1
- /**
2
- * Test input runner.
3
- * Executes tools with contract-defined test inputs.
4
- */
5
- import type { ToolContract } from './contract-types.js';
6
- import type { SandboxExecutor, ToolExecutionResult } from '../../runtime/sandbox/index.js';
7
- /**
8
- * Test execution result with metadata.
9
- */
10
- export type TestExecutionResult = ToolExecutionResult & {
11
- /** Test case name */
12
- testName: string;
13
- /** Test input used */
14
- testInput: Record<string, unknown>;
15
- /** Test expectation */
16
- expectation?: import('./contract-types.js').TestExpectation;
17
- /** Expected output schema name (optional, for tests expecting different output schema) */
18
- expectedOutputSchema?: string;
19
- };
20
- /**
21
- * Run contract-defined test cases.
22
- * @param executor - Sandbox executor
23
- * @param contract - Tool contract
24
- * @param determinismRuns - Number of runs for deterministic tests (default: 1)
25
- * @returns Array of test execution results
26
- */
27
- export declare function runContractTests(executor: SandboxExecutor, contract: ToolContract, toolTimeoutMs?: number): Promise<TestExecutionResult[]>;
28
- //# sourceMappingURL=test-runner.d.ts.map
@@ -1,55 +0,0 @@
1
- /**
2
- * Test input runner.
3
- * Executes tools with contract-defined test inputs.
4
- */
5
- /**
6
- * Run contract-defined test cases.
7
- * @param executor - Sandbox executor
8
- * @param contract - Tool contract
9
- * @param determinismRuns - Number of runs for deterministic tests (default: 1)
10
- * @returns Array of test execution results
11
- */
12
- export async function runContractTests(executor, contract, toolTimeoutMs) {
13
- if (!contract.tests || contract.tests.length === 0) {
14
- return [];
15
- }
16
- const results = [];
17
- for (const test of contract.tests) {
18
- // Set environment variables if specified
19
- const originalEnv = { ...process.env };
20
- if (test.env) {
21
- for (const [key, value] of Object.entries(test.env)) {
22
- process.env[key] = value;
23
- }
24
- }
25
- try {
26
- // Execute tool with test input (run once)
27
- const executionResults = await executor.executeTool(contract.tool, [test.input], toolTimeoutMs);
28
- // Map to test execution results
29
- for (const result of executionResults) {
30
- results.push({
31
- ...result,
32
- testName: test.name,
33
- testInput: test.input,
34
- expectation: test.expect,
35
- });
36
- }
37
- }
38
- finally {
39
- // Restore environment properly (avoid reassigning process.env which breaks Node's proxy)
40
- // Remove any keys that were added
41
- const currentKeys = Object.keys(process.env);
42
- for (const key of currentKeys) {
43
- if (!(key in originalEnv)) {
44
- delete process.env[key];
45
- }
46
- }
47
- // Restore any keys that were changed
48
- for (const [key, value] of Object.entries(originalEnv)) {
49
- process.env[key] = value;
50
- }
51
- }
52
- }
53
- return results;
54
- }
55
- //# sourceMappingURL=test-runner.js.map