@syrin/cli 1.3.1 → 1.4.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 (150) hide show
  1. package/README.md +36 -0
  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 +4 -4
  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,498 +0,0 @@
1
- /**
2
- * Synthetic input generator.
3
- * Generates test inputs from JSON Schema definitions.
4
- */
5
- /**
6
- * Generate test inputs from a JSON Schema.
7
- * Includes both predictable patterns and agent-like unpredictable variations.
8
- * @param schema - JSON Schema definition
9
- * @returns Array of generated input objects
10
- */
11
- export function generateInputsFromSchema(schema) {
12
- const inputs = [];
13
- // 1. Predictable patterns (for correctness testing)
14
- // Generate minimal valid input (only required fields)
15
- inputs.push(generateMinimalInput(schema));
16
- // Generate input with defaults (optional fields with default values)
17
- inputs.push(generateWithDefaults(schema));
18
- // Generate edge cases
19
- inputs.push(...generateEdgeCases(schema));
20
- // 2. Agent-like unpredictable patterns (for agent safety testing)
21
- // Generate random variations (agent-like inputs)
22
- inputs.push(...generateAgentLikeInputs(schema));
23
- // Generate invalid-but-close inputs (type coercion attempts)
24
- inputs.push(...generateInvalidButCloseInputs(schema));
25
- // Generate extreme values (very long strings, very large numbers)
26
- inputs.push(...generateExtremeValueInputs(schema));
27
- // Remove duplicates (by JSON string comparison)
28
- const uniqueInputs = removeDuplicates(inputs);
29
- return uniqueInputs;
30
- }
31
- /**
32
- * Type guard for JSONSchemaField.
33
- */
34
- function isJSONSchemaField(obj) {
35
- return (typeof obj === 'object' &&
36
- obj !== null &&
37
- ('type' in obj || 'properties' in obj || 'items' in obj || '$ref' in obj));
38
- }
39
- /**
40
- * Generate minimal input (only required fields).
41
- */
42
- function generateMinimalInput(schema) {
43
- const input = {};
44
- if (!isJSONSchemaField(schema)) {
45
- return input;
46
- }
47
- const properties = schema.properties;
48
- const required = schema.required;
49
- if (!properties) {
50
- return input;
51
- }
52
- // Only include required fields
53
- if (required) {
54
- for (const fieldName of required) {
55
- const fieldSchema = properties[fieldName];
56
- if (fieldSchema) {
57
- input[fieldName] = generateValue(fieldSchema);
58
- }
59
- }
60
- }
61
- return input;
62
- }
63
- /**
64
- * Generate input with default values.
65
- */
66
- function generateWithDefaults(schema) {
67
- const minimal = generateMinimalInput(schema);
68
- if (!isJSONSchemaField(schema)) {
69
- return minimal;
70
- }
71
- const properties = schema.properties;
72
- if (!properties) {
73
- return minimal;
74
- }
75
- // Add optional fields with defaults if they exist
76
- for (const [fieldName, fieldSchema] of Object.entries(properties)) {
77
- if (!(fieldName in minimal)) {
78
- if (isJSONSchemaField(fieldSchema) && 'default' in fieldSchema) {
79
- minimal[fieldName] = fieldSchema.default;
80
- }
81
- }
82
- }
83
- return minimal;
84
- }
85
- /**
86
- * Generate edge case inputs.
87
- */
88
- function generateEdgeCases(schema) {
89
- const cases = [];
90
- if (!isJSONSchemaField(schema)) {
91
- return cases;
92
- }
93
- const properties = schema.properties;
94
- const required = schema.required;
95
- if (!properties) {
96
- return cases;
97
- }
98
- // Generate edge cases for each field
99
- for (const [fieldName, fieldSchema] of Object.entries(properties)) {
100
- const isRequired = required?.includes(fieldName) ?? false;
101
- // Generate edge case: empty string (if field is string)
102
- if (isStringType(fieldSchema)) {
103
- const edgeCase = {};
104
- if (isRequired) {
105
- edgeCase[fieldName] = '';
106
- cases.push(edgeCase);
107
- }
108
- }
109
- // Generate edge case: null (if nullable)
110
- if (isNullable(fieldSchema)) {
111
- const edgeCase = {};
112
- if (isRequired) {
113
- edgeCase[fieldName] = null;
114
- cases.push(edgeCase);
115
- }
116
- }
117
- // Generate edge case: empty array (if field is array)
118
- if (isArrayType(fieldSchema)) {
119
- const edgeCase = {};
120
- if (isRequired) {
121
- edgeCase[fieldName] = [];
122
- cases.push(edgeCase);
123
- }
124
- }
125
- }
126
- return cases;
127
- }
128
- /**
129
- * Generate a value from a field schema.
130
- */
131
- function generateValue(schema) {
132
- if (!isJSONSchemaField(schema)) {
133
- return null;
134
- }
135
- // Check for enum
136
- if (Array.isArray(schema.enum) && schema.enum.length > 0) {
137
- return schema.enum[0];
138
- }
139
- // Check for default value
140
- if ('default' in schema) {
141
- return schema.default;
142
- }
143
- // Generate based on type
144
- const type = schema.type;
145
- if (Array.isArray(type)) {
146
- // Use first non-null type
147
- const firstType = type.find(t => t !== 'null') || type[0];
148
- if (firstType) {
149
- return generateValueByType(firstType, schema);
150
- }
151
- }
152
- if (typeof type === 'string') {
153
- return generateValueByType(type, schema);
154
- }
155
- // If no type specified, try to infer from other properties
156
- if (isJSONSchemaField(schema)) {
157
- if (schema.properties) {
158
- return {};
159
- }
160
- if (schema.items) {
161
- return [];
162
- }
163
- }
164
- return null;
165
- }
166
- /**
167
- * Generate value by type.
168
- */
169
- function generateValueByType(type, schema) {
170
- switch (type) {
171
- case 'string':
172
- if (typeof schema === 'object' &&
173
- schema !== null &&
174
- 'pattern' in schema) {
175
- // For patterns, return a simple string (pattern matching is complex)
176
- return 'test_string';
177
- }
178
- return 'test_string';
179
- case 'number':
180
- case 'integer':
181
- if (schema.minimum !== undefined) {
182
- return schema.minimum;
183
- }
184
- if (schema.maximum !== undefined) {
185
- return schema.maximum;
186
- }
187
- return 0;
188
- case 'boolean':
189
- return false;
190
- case 'array':
191
- return [];
192
- case 'object':
193
- return {};
194
- case 'null':
195
- return null;
196
- default:
197
- return null;
198
- }
199
- }
200
- /**
201
- * Check if schema is string type.
202
- */
203
- function isStringType(schema) {
204
- if (!isJSONSchemaField(schema)) {
205
- return false;
206
- }
207
- const type = schema.type;
208
- if (typeof type === 'string') {
209
- return type === 'string';
210
- }
211
- if (Array.isArray(type)) {
212
- return type.includes('string');
213
- }
214
- return false;
215
- }
216
- /**
217
- * Check if schema is array type.
218
- */
219
- function isArrayType(schema) {
220
- if (!isJSONSchemaField(schema)) {
221
- return false;
222
- }
223
- const type = schema.type;
224
- if (typeof type === 'string') {
225
- return type === 'array';
226
- }
227
- if (Array.isArray(type)) {
228
- return type.includes('array');
229
- }
230
- return false;
231
- }
232
- /**
233
- * Check if schema is nullable.
234
- */
235
- function isNullable(schema) {
236
- if (!isJSONSchemaField(schema)) {
237
- return false;
238
- }
239
- if (schema.nullable === true) {
240
- return true;
241
- }
242
- const type = schema.type;
243
- if (Array.isArray(type)) {
244
- return type.includes('null');
245
- }
246
- return false;
247
- }
248
- /**
249
- * Generate agent-like unpredictable inputs (random variations).
250
- * Simulates how agents might generate inputs.
251
- */
252
- function generateAgentLikeInputs(schema) {
253
- const inputs = [];
254
- if (!isJSONSchemaField(schema)) {
255
- return inputs;
256
- }
257
- const properties = schema.properties;
258
- const required = schema.required;
259
- if (!properties) {
260
- return inputs;
261
- }
262
- // Generate 3 random variations with random values
263
- const numVariations = 3;
264
- for (let i = 0; i < numVariations; i++) {
265
- const input = {};
266
- // Include all required fields with random values
267
- if (required) {
268
- for (const fieldName of required) {
269
- const fieldSchema = properties[fieldName];
270
- if (fieldSchema) {
271
- input[fieldName] = generateRandomValue(fieldSchema);
272
- }
273
- }
274
- }
275
- // Randomly include some optional fields (agent-like behavior)
276
- for (const [fieldName, fieldSchema] of Object.entries(properties)) {
277
- if (!required?.includes(fieldName) && Math.random() > 0.5) {
278
- input[fieldName] = generateRandomValue(fieldSchema);
279
- }
280
- }
281
- if (Object.keys(input).length > 0) {
282
- inputs.push(input);
283
- }
284
- }
285
- return inputs;
286
- }
287
- /**
288
- * Generate invalid-but-close inputs (type coercion attempts).
289
- * Simulates agents trying to pass slightly wrong types.
290
- */
291
- function generateInvalidButCloseInputs(schema) {
292
- const inputs = [];
293
- if (!isJSONSchemaField(schema)) {
294
- return inputs;
295
- }
296
- const properties = schema.properties;
297
- const required = schema.required;
298
- if (!properties) {
299
- return inputs;
300
- }
301
- // For each required string field, try passing a number (agent might do type coercion)
302
- if (required) {
303
- for (const fieldName of required) {
304
- const fieldSchema = properties[fieldName];
305
- if (isStringType(fieldSchema)) {
306
- const input = {};
307
- // Try number instead of string (common agent mistake)
308
- input[fieldName] = Math.floor(Math.random() * 1000);
309
- // Fill other required fields with valid values
310
- for (const otherField of required) {
311
- if (otherField !== fieldName) {
312
- const prop = properties[otherField];
313
- if (!prop) {
314
- throw new Error(`Malformed schema: required field "${otherField}" not found in properties`);
315
- }
316
- input[otherField] = generateValue(prop);
317
- }
318
- }
319
- inputs.push(input);
320
- }
321
- // Try null for required non-nullable fields
322
- if (!isNullable(fieldSchema)) {
323
- const input = {};
324
- input[fieldName] = null;
325
- for (const otherField of required) {
326
- if (otherField !== fieldName) {
327
- const prop = properties[otherField];
328
- if (!prop) {
329
- throw new Error(`Malformed schema: required field "${otherField}" not found in properties`);
330
- }
331
- input[otherField] = generateValue(prop);
332
- }
333
- }
334
- inputs.push(input);
335
- }
336
- }
337
- }
338
- return inputs;
339
- }
340
- /**
341
- * Generate extreme value inputs (very long strings, very large numbers).
342
- * Tests tools against agent-generated extreme inputs.
343
- */
344
- function generateExtremeValueInputs(schema) {
345
- const inputs = [];
346
- if (!isJSONSchemaField(schema)) {
347
- return inputs;
348
- }
349
- const properties = schema.properties;
350
- const required = schema.required;
351
- if (!properties) {
352
- return inputs;
353
- }
354
- // Generate extreme string (1000+ characters)
355
- if (required) {
356
- for (const fieldName of required) {
357
- const fieldSchema = properties[fieldName];
358
- if (isStringType(fieldSchema)) {
359
- const input = {};
360
- // Very long string (agent might paste large text)
361
- input[fieldName] =
362
- 'A'.repeat(1000) + ' very long string that agents might generate';
363
- for (const otherField of required) {
364
- if (otherField !== fieldName) {
365
- const prop = properties[otherField];
366
- if (!prop) {
367
- throw new Error(`Malformed schema: required field "${otherField}" not found in properties`);
368
- }
369
- input[otherField] = generateValue(prop);
370
- }
371
- }
372
- inputs.push(input);
373
- }
374
- // Very large number
375
- if (isNumberType(fieldSchema)) {
376
- const input = {};
377
- input[fieldName] = Number.MAX_SAFE_INTEGER;
378
- for (const otherField of required) {
379
- if (otherField !== fieldName) {
380
- const prop = properties[otherField];
381
- if (!prop) {
382
- throw new Error(`Malformed schema: required field "${otherField}" not found in properties`);
383
- }
384
- input[otherField] = generateValue(prop);
385
- }
386
- }
387
- inputs.push(input);
388
- // Very small number
389
- const input2 = {};
390
- input2[fieldName] = Number.MIN_SAFE_INTEGER;
391
- for (const otherField of required) {
392
- if (otherField !== fieldName) {
393
- const prop = properties[otherField];
394
- if (!prop) {
395
- throw new Error(`Malformed schema: required field "${otherField}" not found in properties`);
396
- }
397
- input2[otherField] = generateValue(prop);
398
- }
399
- }
400
- inputs.push(input2);
401
- }
402
- }
403
- }
404
- return inputs;
405
- }
406
- /**
407
- * Generate a random value from a field schema (for agent-like inputs).
408
- */
409
- function generateRandomValue(schema) {
410
- if (!isJSONSchemaField(schema)) {
411
- return null;
412
- }
413
- // Check for enum - pick random enum value
414
- if (Array.isArray(schema.enum) && schema.enum.length > 0) {
415
- return schema.enum[Math.floor(Math.random() * schema.enum.length)];
416
- }
417
- // Generate based on type with randomness
418
- const type = schema.type;
419
- if (typeof type === 'string') {
420
- return generateRandomValueByType(type, schema);
421
- }
422
- if (Array.isArray(type)) {
423
- const firstType = type.find(t => t !== 'null') || type[0];
424
- if (firstType) {
425
- return generateRandomValueByType(firstType, schema);
426
- }
427
- }
428
- return null;
429
- }
430
- /**
431
- * Generate random value by type.
432
- */
433
- function generateRandomValueByType(type, schema) {
434
- switch (type) {
435
- case 'string': {
436
- // Random string with various patterns (agent-like)
437
- const patterns = [
438
- `random_${Math.random().toString(36).substring(7)}`,
439
- `Test String ${Date.now()}`,
440
- `Mixed123String${Math.floor(Math.random() * 100)}`,
441
- `special-chars-!@#$%^&*()`,
442
- `unicode-测试-☀️🌧️`,
443
- ];
444
- return patterns[Math.floor(Math.random() * patterns.length)];
445
- }
446
- case 'number':
447
- case 'integer': {
448
- const min = schema.minimum ?? -1000;
449
- const max = schema.maximum ?? 1000;
450
- return Math.floor(Math.random() * (max - min + 1)) + min;
451
- }
452
- case 'boolean':
453
- return Math.random() > 0.5;
454
- case 'array': {
455
- // Random array with 0-5 elements
456
- const length = Math.floor(Math.random() * 6);
457
- return Array.from({ length }, () => generateRandomValue(schema.items || {}));
458
- }
459
- case 'object':
460
- return {};
461
- case 'null':
462
- return null;
463
- default:
464
- return null;
465
- }
466
- }
467
- /**
468
- * Check if schema is number type.
469
- */
470
- function isNumberType(schema) {
471
- if (!isJSONSchemaField(schema)) {
472
- return false;
473
- }
474
- const type = schema.type;
475
- if (typeof type === 'string') {
476
- return type === 'number' || type === 'integer';
477
- }
478
- if (Array.isArray(type)) {
479
- return type.includes('number') || type.includes('integer');
480
- }
481
- return false;
482
- }
483
- /**
484
- * Remove duplicate inputs.
485
- */
486
- function removeDuplicates(inputs) {
487
- const seen = new Set();
488
- const unique = [];
489
- for (const input of inputs) {
490
- const key = JSON.stringify(input, Object.keys(input).sort());
491
- if (!seen.has(key)) {
492
- seen.add(key);
493
- unique.push(input);
494
- }
495
- }
496
- return unique;
497
- }
498
- //# sourceMappingURL=input-generator.js.map
@@ -1,31 +0,0 @@
1
- /**
2
- * MCP root detection utility.
3
- * Detects the MCP server root directory using priority: CLI flag > config > auto-detect.
4
- */
5
- /**
6
- * Options for MCP root detection.
7
- */
8
- export interface MCPRootDetectionOptions {
9
- /** Explicit MCP root from CLI flag */
10
- cliMCPRoot?: string;
11
- /** MCP root from config file */
12
- configMCPRoot?: string;
13
- /** Current working directory (defaults to process.cwd()) */
14
- cwd?: string;
15
- }
16
- /**
17
- * Detect MCP root directory using priority order.
18
- * Priority: CLI flag > Config > Auto-detect > Current working directory
19
- *
20
- * @param options - Detection options
21
- * @returns Resolved MCP root directory (absolute path)
22
- */
23
- export declare function detectMCPRoot(options?: MCPRootDetectionOptions): string;
24
- /**
25
- * Resolve tools directory path relative to MCP root.
26
- * @param mcpRoot - MCP root directory
27
- * @param toolsDir - Tools directory name (default: "tools")
28
- * @returns Absolute path to tools directory
29
- */
30
- export declare function resolveToolsDir(mcpRoot: string, toolsDir?: string): string;
31
- //# sourceMappingURL=mcp-root-detector.d.ts.map
@@ -1,105 +0,0 @@
1
- /**
2
- * MCP root detection utility.
3
- * Detects the MCP server root directory using priority: CLI flag > config > auto-detect.
4
- */
5
- import * as fs from 'fs';
6
- import * as path from 'path';
7
- /**
8
- * Auto-detect MCP root by looking for common indicators.
9
- * @param startDir - Directory to start searching from
10
- * @returns Detected MCP root, or null if not found
11
- */
12
- function autoDetectMCPRoot(startDir) {
13
- let currentDir = path.resolve(startDir);
14
- // Look up the directory tree for indicators
15
- while (currentDir !== path.dirname(currentDir)) {
16
- // Check for tools directory
17
- const toolsDir = path.join(currentDir, 'tools');
18
- try {
19
- if (fs.existsSync(toolsDir) && fs.statSync(toolsDir).isDirectory()) {
20
- return currentDir;
21
- }
22
- }
23
- catch (_error) {
24
- // If fs.existsSync or fs.statSync throws, treat as not present
25
- // Continue searching
26
- }
27
- // Check for common MCP server files
28
- const serverFiles = [
29
- 'server.py',
30
- 'server.ts',
31
- 'server.js',
32
- 'package.json',
33
- 'requirements.txt',
34
- ];
35
- for (const file of serverFiles) {
36
- const filePath = path.join(currentDir, file);
37
- try {
38
- if (fs.existsSync(filePath)) {
39
- // Server file found - return currentDir (tools directory check already handled above)
40
- return currentDir;
41
- }
42
- }
43
- catch (_error) {
44
- // Ignore errors and continue
45
- }
46
- }
47
- // Move up one directory
48
- currentDir = path.dirname(currentDir);
49
- }
50
- return null;
51
- }
52
- /**
53
- * Validate MCP root path and throw descriptive errors if invalid.
54
- */
55
- function validateMCPRootPath(sourcePath, resolvedPath, source) {
56
- if (!fs.existsSync(resolvedPath)) {
57
- const prefix = source === 'CLI flag' ? '' : 'from config ';
58
- throw new Error(`MCP root directory ${prefix}not found: ${sourcePath} (resolved to: ${resolvedPath})`);
59
- }
60
- // Ensure it's a directory, not a file
61
- const stats = fs.statSync(resolvedPath);
62
- if (!stats.isDirectory()) {
63
- const prefix = source === 'CLI flag' ? '' : 'from config ';
64
- throw new Error(`MCP root path ${prefix}is not a directory: ${sourcePath} (resolved to: ${resolvedPath})`);
65
- }
66
- }
67
- /**
68
- * Detect MCP root directory using priority order.
69
- * Priority: CLI flag > Config > Auto-detect > Current working directory
70
- *
71
- * @param options - Detection options
72
- * @returns Resolved MCP root directory (absolute path)
73
- */
74
- export function detectMCPRoot(options = {}) {
75
- const cwd = options.cwd || process.cwd();
76
- // Priority 1: CLI flag (explicit)
77
- if (options.cliMCPRoot) {
78
- const resolved = path.resolve(cwd, options.cliMCPRoot);
79
- validateMCPRootPath(options.cliMCPRoot, resolved, 'from CLI flag');
80
- return resolved;
81
- }
82
- // Priority 2: Config file
83
- if (options.configMCPRoot) {
84
- const resolved = path.resolve(cwd, options.configMCPRoot);
85
- validateMCPRootPath(options.configMCPRoot, resolved, 'from config');
86
- return resolved;
87
- }
88
- // Priority 3: Auto-detect
89
- const autoDetected = autoDetectMCPRoot(cwd);
90
- if (autoDetected) {
91
- return autoDetected;
92
- }
93
- // Priority 4: Default to current working directory
94
- return path.resolve(cwd);
95
- }
96
- /**
97
- * Resolve tools directory path relative to MCP root.
98
- * @param mcpRoot - MCP root directory
99
- * @param toolsDir - Tools directory name (default: "tools")
100
- * @returns Absolute path to tools directory
101
- */
102
- export function resolveToolsDir(mcpRoot, toolsDir = 'tools') {
103
- return path.resolve(mcpRoot, toolsDir);
104
- }
105
- //# sourceMappingURL=mcp-root-detector.js.map
@@ -1,44 +0,0 @@
1
- /**
2
- * Retry scenario tester.
3
- * Tests tools against agent retry patterns (retry on failure, timeout, error).
4
- */
5
- import type { SandboxExecutor, ToolExecutionResult } from '../../runtime/sandbox/index.js';
6
- /**
7
- * Retry test configuration.
8
- */
9
- export interface RetryTestConfig {
10
- /** Maximum number of retries to test (default: 3) */
11
- maxRetries?: number;
12
- /** Retry delay in milliseconds (default: 100) */
13
- retryDelayMs?: number;
14
- /** Test retry on failure (default: true) */
15
- testRetryOnFailure?: boolean;
16
- /** Test retry on timeout (default: true) */
17
- testRetryOnTimeout?: boolean;
18
- /** Test retry on connection error (default: true) */
19
- testRetryOnConnectionError?: boolean;
20
- }
21
- /**
22
- * Retry test result.
23
- */
24
- export interface RetryTestResult {
25
- /** Input tested */
26
- testInput: Record<string, unknown>;
27
- /** Retry attempts made */
28
- attempts: number;
29
- /** Whether tool eventually succeeded after retries */
30
- eventuallySucceeded: boolean;
31
- /** Results from all retry attempts */
32
- results: ToolExecutionResult[];
33
- /** Issues detected */
34
- issues: string[];
35
- }
36
- /**
37
- * Test tool retry behavior.
38
- * Simulates agent retry patterns to ensure tools handle retries gracefully.
39
- *
40
- * Note: Idempotency (output consistency across retries) is checked separately
41
- * This tester focuses on retry reliability.
42
- */
43
- export declare function testRetryBehavior(executor: SandboxExecutor, toolName: string, testInput: Record<string, unknown>, config?: RetryTestConfig, toolTimeoutMs?: number): Promise<RetryTestResult>;
44
- //# sourceMappingURL=retry-tester.d.ts.map