tachibot-mcp 2.0.2

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 (214) hide show
  1. package/.env.example +260 -0
  2. package/CHANGELOG.md +54 -0
  3. package/CODE_OF_CONDUCT.md +56 -0
  4. package/CONTRIBUTING.md +54 -0
  5. package/Dockerfile +36 -0
  6. package/LICENSE +644 -0
  7. package/README.md +201 -0
  8. package/SECURITY.md +95 -0
  9. package/dist/personality/komaai-expressions.js +12 -0
  10. package/dist/profiles/balanced.json +33 -0
  11. package/dist/profiles/code_focus.json +33 -0
  12. package/dist/profiles/full.json +33 -0
  13. package/dist/profiles/minimal.json +33 -0
  14. package/dist/profiles/research_power.json +33 -0
  15. package/dist/scripts/build-profiles.js +46 -0
  16. package/dist/src/application/services/focus/FocusModeRegistry.js +46 -0
  17. package/dist/src/application/services/focus/FocusTool.service.js +109 -0
  18. package/dist/src/application/services/focus/ModeRegistry.js +46 -0
  19. package/dist/src/application/services/focus/modes/focus-deep.mode.js +27 -0
  20. package/dist/src/application/services/focus/modes/status.mode.js +50 -0
  21. package/dist/src/application/services/focus/modes/tachibot-status.mode.js +50 -0
  22. package/dist/src/collaborative-orchestrator.js +391 -0
  23. package/dist/src/config/model-constants.js +188 -0
  24. package/dist/src/config/model-defaults.js +57 -0
  25. package/dist/src/config/model-preferences.js +382 -0
  26. package/dist/src/config/timeout-config.js +130 -0
  27. package/dist/src/config.js +173 -0
  28. package/dist/src/domain/interfaces/IFocusMode.js +5 -0
  29. package/dist/src/domain/interfaces/IProvider.js +6 -0
  30. package/dist/src/domain/interfaces/ITool.js +5 -0
  31. package/dist/src/focus-deep.js +245 -0
  32. package/dist/src/infrastructure/ascii/art/robots.ascii.js +16 -0
  33. package/dist/src/mcp-client.js +90 -0
  34. package/dist/src/memory/index.js +17 -0
  35. package/dist/src/memory/memory-config.js +135 -0
  36. package/dist/src/memory/memory-interface.js +174 -0
  37. package/dist/src/memory/memory-manager.js +383 -0
  38. package/dist/src/memory/providers/devlog-provider.js +385 -0
  39. package/dist/src/memory/providers/hybrid-provider.js +399 -0
  40. package/dist/src/memory/providers/local-provider.js +388 -0
  41. package/dist/src/memory/providers/mem0-provider.js +337 -0
  42. package/dist/src/modes/architect.js +477 -0
  43. package/dist/src/modes/auditor.js +362 -0
  44. package/dist/src/modes/challenger.js +841 -0
  45. package/dist/src/modes/code-reviewer.js +382 -0
  46. package/dist/src/modes/commit-guardian.js +424 -0
  47. package/dist/src/modes/documentation-writer.js +572 -0
  48. package/dist/src/modes/scout.js +587 -0
  49. package/dist/src/modes/shared/helpers/challenger-helpers.js +454 -0
  50. package/dist/src/modes/shared/helpers/index.js +17 -0
  51. package/dist/src/modes/shared/helpers/scout-helpers.js +270 -0
  52. package/dist/src/modes/shared/helpers/verifier-helpers.js +332 -0
  53. package/dist/src/modes/test-architect.js +767 -0
  54. package/dist/src/modes/verifier.js +378 -0
  55. package/dist/src/monitoring/performance-monitor.js +435 -0
  56. package/dist/src/optimization/batch-executor.js +121 -0
  57. package/dist/src/optimization/context-pruner.js +196 -0
  58. package/dist/src/optimization/cost-monitor.js +338 -0
  59. package/dist/src/optimization/index.js +65 -0
  60. package/dist/src/optimization/model-router.js +264 -0
  61. package/dist/src/optimization/result-cache.js +114 -0
  62. package/dist/src/optimization/token-optimizer.js +257 -0
  63. package/dist/src/optimization/token-tracker.js +118 -0
  64. package/dist/src/orchestrator-instructions.js +128 -0
  65. package/dist/src/orchestrator-lite.js +139 -0
  66. package/dist/src/orchestrator.js +191 -0
  67. package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionEngine.js +1 -0
  68. package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionStrategy.js +5 -0
  69. package/dist/src/orchestrators/collaborative/interfaces/IVisualizationRenderer.js +1 -0
  70. package/dist/src/orchestrators/collaborative/registries/ModelProviderRegistry.js +95 -0
  71. package/dist/src/orchestrators/collaborative/registries/ToolAdapterRegistry.js +64 -0
  72. package/dist/src/orchestrators/collaborative/services/tool-execution/ToolExecutionService.js +502 -0
  73. package/dist/src/orchestrators/collaborative/services/visualization/VisualizationService.js +206 -0
  74. package/dist/src/orchestrators/collaborative/types/session-types.js +5 -0
  75. package/dist/src/profiles/balanced.js +37 -0
  76. package/dist/src/profiles/code_focus.js +37 -0
  77. package/dist/src/profiles/debug_intensive.js +59 -0
  78. package/dist/src/profiles/full.js +37 -0
  79. package/dist/src/profiles/minimal.js +37 -0
  80. package/dist/src/profiles/research_code.js +59 -0
  81. package/dist/src/profiles/research_power.js +37 -0
  82. package/dist/src/profiles/types.js +5 -0
  83. package/dist/src/profiles/workflow_builder.js +53 -0
  84. package/dist/src/prompt-engineer-lite.js +78 -0
  85. package/dist/src/prompt-engineer.js +399 -0
  86. package/dist/src/reasoning-chain.js +508 -0
  87. package/dist/src/sequential-thinking.js +291 -0
  88. package/dist/src/server-diagnostic.js +74 -0
  89. package/dist/src/server-raw.js +158 -0
  90. package/dist/src/server-simple.js +58 -0
  91. package/dist/src/server.js +514 -0
  92. package/dist/src/session/session-logger.js +617 -0
  93. package/dist/src/session/session-manager.js +571 -0
  94. package/dist/src/session/session-tools.js +400 -0
  95. package/dist/src/tools/advanced-modes.js +200 -0
  96. package/dist/src/tools/claude-integration.js +356 -0
  97. package/dist/src/tools/consolidated/ai-router.js +174 -0
  98. package/dist/src/tools/consolidated/ai-tool.js +48 -0
  99. package/dist/src/tools/consolidated/brainstorm-tool.js +87 -0
  100. package/dist/src/tools/consolidated/environment-detector.js +80 -0
  101. package/dist/src/tools/consolidated/index.js +50 -0
  102. package/dist/src/tools/consolidated/search-tool.js +110 -0
  103. package/dist/src/tools/consolidated/workflow-tool.js +238 -0
  104. package/dist/src/tools/gemini-tools.js +329 -0
  105. package/dist/src/tools/grok-enhanced.js +376 -0
  106. package/dist/src/tools/grok-tools.js +299 -0
  107. package/dist/src/tools/lmstudio-tools.js +223 -0
  108. package/dist/src/tools/openai-tools.js +498 -0
  109. package/dist/src/tools/openrouter-tools.js +317 -0
  110. package/dist/src/tools/optimized-wrapper.js +204 -0
  111. package/dist/src/tools/perplexity-tools.js +294 -0
  112. package/dist/src/tools/pingpong-tool.js +343 -0
  113. package/dist/src/tools/qwen-wrapper.js +74 -0
  114. package/dist/src/tools/tool-router.js +444 -0
  115. package/dist/src/tools/unified-ai-provider.js +260 -0
  116. package/dist/src/tools/workflow-runner.js +425 -0
  117. package/dist/src/tools/workflow-validator-tool.js +107 -0
  118. package/dist/src/types.js +23 -0
  119. package/dist/src/utils/input-validator.js +130 -0
  120. package/dist/src/utils/model-router.js +91 -0
  121. package/dist/src/utils/progress-stream.js +255 -0
  122. package/dist/src/utils/provider-router.js +88 -0
  123. package/dist/src/utils/smart-api-client.js +146 -0
  124. package/dist/src/utils/table-builder.js +218 -0
  125. package/dist/src/utils/timestamp-formatter.js +134 -0
  126. package/dist/src/utils/tool-compressor.js +257 -0
  127. package/dist/src/utils/tool-config.js +201 -0
  128. package/dist/src/validators/dependency-graph-validator.js +147 -0
  129. package/dist/src/validators/interpolation-validator.js +222 -0
  130. package/dist/src/validators/output-usage-validator.js +151 -0
  131. package/dist/src/validators/syntax-validator.js +102 -0
  132. package/dist/src/validators/tool-registry-validator.js +123 -0
  133. package/dist/src/validators/tool-types.js +97 -0
  134. package/dist/src/validators/types.js +8 -0
  135. package/dist/src/validators/workflow-validator.js +134 -0
  136. package/dist/src/visualizer-lite.js +42 -0
  137. package/dist/src/visualizer.js +179 -0
  138. package/dist/src/workflows/circuit-breaker.js +199 -0
  139. package/dist/src/workflows/custom-workflows.js +451 -0
  140. package/dist/src/workflows/engine/AutoSynthesizer.js +97 -0
  141. package/dist/src/workflows/engine/StepParameterResolver.js +74 -0
  142. package/dist/src/workflows/engine/VariableInterpolator.js +123 -0
  143. package/dist/src/workflows/engine/WorkflowDiscovery.js +125 -0
  144. package/dist/src/workflows/engine/WorkflowExecutionEngine.js +485 -0
  145. package/dist/src/workflows/engine/WorkflowExecutor.js +113 -0
  146. package/dist/src/workflows/engine/WorkflowFileManager.js +244 -0
  147. package/dist/src/workflows/engine/WorkflowHelpers.js +114 -0
  148. package/dist/src/workflows/engine/WorkflowOutputFormatter.js +83 -0
  149. package/dist/src/workflows/engine/events/WorkflowEventBus.js +132 -0
  150. package/dist/src/workflows/engine/events/interfaces/IEventBus.js +5 -0
  151. package/dist/src/workflows/engine/handlers/ErrorRecoveryHandler.js +162 -0
  152. package/dist/src/workflows/engine/handlers/PromptEnhancementHandler.js +115 -0
  153. package/dist/src/workflows/engine/handlers/SessionPersistenceHandler.js +167 -0
  154. package/dist/src/workflows/engine/handlers/StepExecutionHandler.js +231 -0
  155. package/dist/src/workflows/engine/handlers/ToolInvocationHandler.js +46 -0
  156. package/dist/src/workflows/engine/interfaces/IAutoSynthesizer.js +5 -0
  157. package/dist/src/workflows/engine/interfaces/IStepParameterResolver.js +5 -0
  158. package/dist/src/workflows/engine/interfaces/IVariableInterpolator.js +5 -0
  159. package/dist/src/workflows/engine/interfaces/IWorkflowDiscovery.js +4 -0
  160. package/dist/src/workflows/engine/interfaces/IWorkflowFileManager.js +5 -0
  161. package/dist/src/workflows/engine/interfaces/IWorkflowOutputFormatter.js +5 -0
  162. package/dist/src/workflows/engine/state/WorkflowStateMachine.js +194 -0
  163. package/dist/src/workflows/engine/state/interfaces/IStateMachine.js +17 -0
  164. package/dist/src/workflows/fallback-strategies.js +373 -0
  165. package/dist/src/workflows/message-queue.js +455 -0
  166. package/dist/src/workflows/model-router.js +189 -0
  167. package/dist/src/workflows/orchestrator-examples.js +174 -0
  168. package/dist/src/workflows/orchestrator-integration.js +200 -0
  169. package/dist/src/workflows/self-healing.js +524 -0
  170. package/dist/src/workflows/tool-mapper.js +407 -0
  171. package/dist/src/workflows/tool-orchestrator.js +796 -0
  172. package/dist/src/workflows/workflow-engine.js +573 -0
  173. package/dist/src/workflows/workflow-parser.js +283 -0
  174. package/dist/src/workflows/workflow-types.js +95 -0
  175. package/dist/src/workflows.js +568 -0
  176. package/dist/test-workflow-file-output.js +93 -0
  177. package/docs/API_KEYS.md +570 -0
  178. package/docs/CLAUDE_CODE_SETUP.md +181 -0
  179. package/docs/CLAUDE_DESKTOP_MANUAL.md +127 -0
  180. package/docs/CONFIGURATION.md +745 -0
  181. package/docs/FOCUS_MODES.md +240 -0
  182. package/docs/INSTALLATION_BOTH.md +145 -0
  183. package/docs/TERMS.md +352 -0
  184. package/docs/TOOLS_REFERENCE.md +1622 -0
  185. package/docs/TOOL_PARAMETERS.md +496 -0
  186. package/docs/TOOL_PROFILES.md +236 -0
  187. package/docs/WORKFLOWS.md +987 -0
  188. package/docs/WORKFLOW_OUTPUT.md +198 -0
  189. package/docs/WORKFLOW_PROGRESS_TRACKING.md +305 -0
  190. package/docs/workflows/design-brainstorm.md +335 -0
  191. package/package.json +97 -0
  192. package/profiles/balanced.json +37 -0
  193. package/profiles/code_focus.json +37 -0
  194. package/profiles/debug_intensive.json +34 -0
  195. package/profiles/full.json +37 -0
  196. package/profiles/minimal.json +37 -0
  197. package/profiles/research_power.json +37 -0
  198. package/profiles/workflow_builder.json +37 -0
  199. package/smithery.yaml +66 -0
  200. package/start.sh +8 -0
  201. package/tools.config.json +81 -0
  202. package/tsconfig.json +18 -0
  203. package/workflows/accessibility-code-audit.yaml +92 -0
  204. package/workflows/code-architecture-review.yaml +202 -0
  205. package/workflows/code-review.yaml +142 -0
  206. package/workflows/core/iterative-problem-solver.yaml +283 -0
  207. package/workflows/creative-brainstorm-yaml.yaml +215 -0
  208. package/workflows/pingpong.yaml +141 -0
  209. package/workflows/system/README.md +412 -0
  210. package/workflows/system/challenger.yaml +175 -0
  211. package/workflows/system/scout.yaml +164 -0
  212. package/workflows/system/verifier.yaml +133 -0
  213. package/workflows/ultra-creative-brainstorm.yaml +318 -0
  214. package/workflows/ux-research-flow.yaml +92 -0
@@ -0,0 +1,767 @@
1
+ export class TestArchitect {
2
+ constructor() {
3
+ this.defaultModel = 'qwen3-coder-480b'; // Best for code generation
4
+ this.defaultMaxTokens = 4000;
5
+ this.defaultFramework = 'jest';
6
+ this.defaultTestTypes = ['unit', 'integration', 'e2e'];
7
+ }
8
+ async architectTests(code, options = {}) {
9
+ const model = options.model || this.defaultModel;
10
+ const framework = options.testFramework || this.defaultFramework;
11
+ const testTypes = options.testTypes || this.defaultTestTypes;
12
+ const coverage = options.coverage || 'thorough';
13
+ const generateMocks = options.generateMocks !== false; // default true
14
+ // Type assertions to help TypeScript understand these won't be undefined
15
+ const safeFramework = framework;
16
+ const safeTestTypes = testTypes;
17
+ const safeCoverage = coverage;
18
+ // Analyze code structure
19
+ const codeStructure = await this.analyzeCodeForTesting(code);
20
+ // Design test suite architecture
21
+ const testSuite = await this.designTestSuite(codeStructure, safeFramework, safeCoverage);
22
+ // Generate test files
23
+ const testFiles = await this.generateTestFiles(codeStructure, safeFramework, safeTestTypes);
24
+ // Generate edge cases
25
+ const edgeCases = await this.generateEdgeCases(codeStructure);
26
+ // Generate mocks if requested
27
+ const mockFiles = generateMocks ? await this.generateMockFiles(codeStructure, safeFramework) : [];
28
+ // Generate test configuration
29
+ const testConfig = await this.generateTestConfiguration(safeFramework, testSuite, safeCoverage);
30
+ // Create synthesis
31
+ const synthesis = this.synthesizeTestArchitecture(testSuite, testFiles, mockFiles, testConfig, edgeCases);
32
+ return {
33
+ testSuite,
34
+ testFiles,
35
+ mockFiles,
36
+ testConfig,
37
+ edgeCases,
38
+ synthesis
39
+ };
40
+ }
41
+ async analyzeCodeForTesting(code) {
42
+ const structure = {
43
+ functions: this.extractTestableFunction(code),
44
+ classes: this.extractTestableClasses(code),
45
+ exports: this.extractExports(code),
46
+ dependencies: this.extractDependencies(code),
47
+ asyncOperations: this.findAsyncOperations(code),
48
+ errorHandling: this.findErrorHandling(code),
49
+ complexity: this.assessTestingComplexity(code),
50
+ riskAreas: this.identifyRiskAreas(code)
51
+ };
52
+ return structure;
53
+ }
54
+ extractTestableFunction(code) {
55
+ const functions = [];
56
+ const functionPatterns = [
57
+ /(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)\s*(?::\s*([^{]+))?\s*\{/g,
58
+ /(?:const|let)\s+(\w+)\s*=\s*(?:async\s+)?\(([^)]*)\)\s*=>\s*/g
59
+ ];
60
+ functionPatterns.forEach(pattern => {
61
+ let match;
62
+ while ((match = pattern.exec(code)) !== null) {
63
+ const [, name, params] = match;
64
+ const funcBody = this.extractFunctionBody(code, match.index);
65
+ functions.push({
66
+ name,
67
+ parameters: this.parseParameters(params),
68
+ isAsync: match[0].includes('async'),
69
+ isExported: match[0].includes('export'),
70
+ complexity: this.calculateFunctionComplexity(funcBody),
71
+ hasErrorHandling: funcBody.includes('try') || funcBody.includes('catch'),
72
+ body: funcBody,
73
+ testPriority: this.calculateTestPriority(name, funcBody)
74
+ });
75
+ }
76
+ });
77
+ return functions;
78
+ }
79
+ extractFunctionBody(code, startIndex) {
80
+ let braceCount = 0;
81
+ let startBrace = -1;
82
+ for (let i = startIndex; i < code.length; i++) {
83
+ if (code[i] === '{') {
84
+ if (startBrace === -1)
85
+ startBrace = i;
86
+ braceCount++;
87
+ }
88
+ else if (code[i] === '}') {
89
+ braceCount--;
90
+ if (braceCount === 0) {
91
+ return code.substring(startBrace, i + 1);
92
+ }
93
+ }
94
+ }
95
+ return '';
96
+ }
97
+ calculateFunctionComplexity(body) {
98
+ const complexityIndicators = ['if', 'for', 'while', 'switch', 'try', '?'];
99
+ const count = complexityIndicators.reduce((sum, indicator) => sum + (body.split(indicator).length - 1), 0);
100
+ return count > 8 ? 'high' : count > 3 ? 'medium' : 'low';
101
+ }
102
+ calculateTestPriority(name, body) {
103
+ // Critical: Security, authentication, payment, data validation
104
+ const criticalKeywords = ['auth', 'login', 'password', 'validate', 'security', 'payment', 'encrypt'];
105
+ if (criticalKeywords.some(keyword => name.toLowerCase().includes(keyword))) {
106
+ return 'critical';
107
+ }
108
+ // High: Error handling, async operations, external APIs
109
+ if (body.includes('throw') || body.includes('await') || body.includes('fetch') || body.includes('axios')) {
110
+ return 'high';
111
+ }
112
+ // Medium: Business logic, calculations, transformations
113
+ if (name.includes('calculate') || name.includes('process') || name.includes('transform')) {
114
+ return 'medium';
115
+ }
116
+ return 'low';
117
+ }
118
+ extractTestableClasses(code) {
119
+ const classes = [];
120
+ const classPattern = /(?:export\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?\s*\{([^}]+)\}/g;
121
+ let match;
122
+ while ((match = classPattern.exec(code)) !== null) {
123
+ const [, name, extends_, body] = match;
124
+ const methods = this.extractClassMethods(body);
125
+ classes.push({
126
+ name,
127
+ extends: extends_,
128
+ methods,
129
+ isExported: match[0].includes('export'),
130
+ testPriority: methods.some((m) => m.testPriority === 'critical') ? 'critical' : 'high'
131
+ });
132
+ }
133
+ return classes;
134
+ }
135
+ extractClassMethods(body) {
136
+ const methods = [];
137
+ const methodPattern = /(async\s+)?(\w+)\s*\(([^)]*)\)\s*(?::\s*([^{]+))?\s*\{/g;
138
+ let match;
139
+ while ((match = methodPattern.exec(body)) !== null) {
140
+ const [, async, name, params, returnType] = match;
141
+ methods.push({
142
+ name,
143
+ isAsync: !!async,
144
+ parameters: this.parseParameters(params),
145
+ returnType,
146
+ testPriority: this.calculateTestPriority(name, body)
147
+ });
148
+ }
149
+ return methods;
150
+ }
151
+ extractExports(code) {
152
+ const exports = [];
153
+ const patterns = [
154
+ /export\s+(?:default\s+)?(?:class|function|const)\s+(\w+)/g,
155
+ /export\s*\{\s*([^}]+)\s*\}/g
156
+ ];
157
+ patterns.forEach(pattern => {
158
+ let match;
159
+ while ((match = pattern.exec(code)) !== null) {
160
+ if (match[1].includes(',')) {
161
+ // Handle multiple exports: export { a, b, c }
162
+ match[1].split(',').forEach(name => exports.push(name.trim()));
163
+ }
164
+ else {
165
+ exports.push(match[1]);
166
+ }
167
+ }
168
+ });
169
+ return exports;
170
+ }
171
+ extractDependencies(code) {
172
+ const dependencies = [];
173
+ const importPattern = /import\s+(?:\{([^}]+)\}|\*\s+as\s+(\w+)|(\w+))?\s+from\s+['"]([^'"]+)['"]/g;
174
+ let match;
175
+ while ((match = importPattern.exec(code)) !== null) {
176
+ const [, named, namespace, default_, module] = match;
177
+ dependencies.push({
178
+ module,
179
+ imports: named ? named.split(',').map(s => s.trim()) : namespace ? [namespace] : [default_],
180
+ type: this.categorizeImport(module)
181
+ });
182
+ }
183
+ return dependencies;
184
+ }
185
+ categorizeImport(module) {
186
+ if (module.startsWith('./') || module.startsWith('../'))
187
+ return 'internal';
188
+ if (['fs', 'path', 'http', 'crypto', 'util'].includes(module))
189
+ return 'builtin';
190
+ return 'external';
191
+ }
192
+ findAsyncOperations(code) {
193
+ const asyncOps = [];
194
+ const patterns = [
195
+ { pattern: /await\s+([^;\n]+)/g, type: 'await' },
196
+ { pattern: /\.then\s*\(/g, type: 'promise' },
197
+ { pattern: /new\s+Promise/g, type: 'promise-constructor' },
198
+ { pattern: /setTimeout|setInterval/g, type: 'timer' }
199
+ ];
200
+ patterns.forEach(({ pattern, type }) => {
201
+ let match;
202
+ while ((match = pattern.exec(code)) !== null) {
203
+ asyncOps.push({
204
+ type,
205
+ code: match[0],
206
+ line: this.getLineNumber(code, match.index)
207
+ });
208
+ }
209
+ });
210
+ return asyncOps;
211
+ }
212
+ findErrorHandling(code) {
213
+ const errorHandling = [];
214
+ const patterns = [
215
+ { pattern: /try\s*\{[^}]*\}\s*catch/g, type: 'try-catch' },
216
+ { pattern: /throw\s+new\s+Error/g, type: 'throw' },
217
+ { pattern: /\.catch\s*\(/g, type: 'promise-catch' }
218
+ ];
219
+ patterns.forEach(({ pattern, type }) => {
220
+ const matches = code.match(pattern) || [];
221
+ errorHandling.push({
222
+ type,
223
+ count: matches.length
224
+ });
225
+ });
226
+ return errorHandling;
227
+ }
228
+ identifyRiskAreas(code) {
229
+ const risks = [];
230
+ if (code.includes('eval('))
231
+ risks.push('Code injection risk (eval)');
232
+ if (code.includes('innerHTML'))
233
+ risks.push('XSS risk (innerHTML)');
234
+ if (code.includes('JSON.parse') && !code.includes('try'))
235
+ risks.push('JSON parsing without error handling');
236
+ if (code.includes('parseInt') && !code.includes('10'))
237
+ risks.push('parseInt without radix');
238
+ if (code.includes('== null') || code.includes('!= null'))
239
+ risks.push('Loose equality with null');
240
+ return risks;
241
+ }
242
+ getLineNumber(code, index) {
243
+ return code.substring(0, index).split('\n').length;
244
+ }
245
+ parseParameters(paramString) {
246
+ if (!paramString.trim())
247
+ return [];
248
+ return paramString.split(',').map(param => {
249
+ const trimmed = param.trim();
250
+ const [nameAndType] = trimmed.split('=');
251
+ const [name, type] = nameAndType.includes(':')
252
+ ? nameAndType.split(':').map(s => s.trim())
253
+ : [nameAndType.trim(), 'any'];
254
+ return { name, type: type || 'any' };
255
+ });
256
+ }
257
+ assessTestingComplexity(code) {
258
+ const lines = code.split('\n').length;
259
+ const functions = (code.match(/function|=>/g) || []).length;
260
+ const asyncOps = (code.match(/await|\.then/g) || []).length;
261
+ const complexity = lines + functions * 5 + asyncOps * 3;
262
+ return complexity > 300 ? 'high' : complexity > 100 ? 'medium' : 'low';
263
+ }
264
+ async designTestSuite(structure, framework, coverage) {
265
+ const totalFunctions = structure.functions.length;
266
+ const totalClasses = structure.classes.length;
267
+ const criticalItems = [...structure.functions, ...structure.classes]
268
+ .filter(item => item.testPriority === 'critical').length;
269
+ const testMultiplier = coverage === 'basic' ? 2 : coverage === 'thorough' ? 4 : 6;
270
+ const totalTests = (totalFunctions + totalClasses * 3) * testMultiplier + structure.edgeCases?.length || 0;
271
+ const testCategories = [
272
+ {
273
+ name: 'Unit Tests',
274
+ testCount: totalFunctions * testMultiplier,
275
+ priority: 'high',
276
+ description: 'Individual function and method testing'
277
+ },
278
+ {
279
+ name: 'Integration Tests',
280
+ testCount: Math.ceil(totalTests * 0.3),
281
+ priority: 'medium',
282
+ description: 'Component interaction testing'
283
+ },
284
+ {
285
+ name: 'Edge Cases',
286
+ testCount: structure.riskAreas.length * 2,
287
+ priority: 'high',
288
+ description: 'Boundary and error condition testing'
289
+ }
290
+ ];
291
+ if (criticalItems > 0) {
292
+ testCategories.push({
293
+ name: 'Security Tests',
294
+ testCount: criticalItems * 3,
295
+ priority: 'high',
296
+ description: 'Security and validation testing'
297
+ });
298
+ }
299
+ return {
300
+ name: `${framework.charAt(0).toUpperCase() + framework.slice(1)} Test Suite`,
301
+ description: `Comprehensive test suite with ${coverage} coverage`,
302
+ framework,
303
+ totalTests,
304
+ testCategories,
305
+ setupRequirements: this.generateSetupRequirements(structure, framework),
306
+ estimatedCoverage: coverage === 'basic' ? 70 : coverage === 'thorough' ? 85 : 95
307
+ };
308
+ }
309
+ generateSetupRequirements(structure, framework) {
310
+ const requirements = [
311
+ `Install ${framework} and related dependencies`,
312
+ 'Configure test scripts in package.json'
313
+ ];
314
+ if (structure.asyncOperations.length > 0) {
315
+ requirements.push('Setup async testing utilities');
316
+ }
317
+ if (structure.dependencies.some((d) => d.type === 'external')) {
318
+ requirements.push('Configure mocking for external dependencies');
319
+ }
320
+ if (structure.riskAreas.length > 0) {
321
+ requirements.push('Setup security testing tools');
322
+ }
323
+ return requirements;
324
+ }
325
+ async generateTestFiles(structure, framework, testTypes) {
326
+ const testFiles = [];
327
+ // Generate unit test files
328
+ if (testTypes.includes('unit')) {
329
+ structure.functions.forEach((func) => {
330
+ testFiles.push({
331
+ fileName: `${func.name}.test.${framework === 'jest' ? 'js' : 'ts'}`,
332
+ testType: 'unit',
333
+ tests: this.generateUnitTests(func, framework),
334
+ imports: this.generateTestImports(func, framework),
335
+ setup: this.generateTestSetup(func, framework),
336
+ teardown: this.generateTestTeardown(func, framework),
337
+ content: this.generateTestFileContent(func, framework, 'unit')
338
+ });
339
+ });
340
+ }
341
+ // Generate integration test files
342
+ if (testTypes.includes('integration')) {
343
+ const integrationFile = {
344
+ fileName: `integration.test.${framework === 'jest' ? 'js' : 'ts'}`,
345
+ testType: 'integration',
346
+ tests: this.generateIntegrationTests(structure, framework),
347
+ imports: [`import { ${structure.exports.join(', ')} } from '../src/index'`],
348
+ setup: 'beforeAll(() => { /* Setup test environment */ });',
349
+ teardown: 'afterAll(() => { /* Cleanup test environment */ });',
350
+ content: this.generateIntegrationTestContent(structure, framework)
351
+ };
352
+ testFiles.push(integrationFile);
353
+ }
354
+ // Generate E2E test files
355
+ if (testTypes.includes('e2e')) {
356
+ testFiles.push({
357
+ fileName: `e2e.test.${framework === 'playwright' ? 'ts' : 'js'}`,
358
+ testType: 'e2e',
359
+ tests: this.generateE2ETests(structure, framework),
360
+ imports: this.generateE2EImports(framework),
361
+ setup: 'beforeEach(() => { /* Setup browser */ });',
362
+ teardown: 'afterEach(() => { /* Cleanup browser */ });',
363
+ content: this.generateE2ETestContent(structure, framework)
364
+ });
365
+ }
366
+ return testFiles;
367
+ }
368
+ generateUnitTests(func, framework) {
369
+ const tests = [];
370
+ // Happy path test
371
+ tests.push({
372
+ name: `should ${func.name} successfully with valid input`,
373
+ description: `Test ${func.name} with expected input parameters`,
374
+ type: 'positive',
375
+ priority: func.testPriority,
376
+ code: this.generateHappyPathTest(func, framework),
377
+ assertions: [`expect(result).toBeDefined()`, `expect(result).not.toBeNull()`],
378
+ mocks: func.isAsync ? ['mockExternalService'] : undefined
379
+ });
380
+ // Error handling test
381
+ if (func.hasErrorHandling) {
382
+ tests.push({
383
+ name: `should handle errors in ${func.name}`,
384
+ description: `Test error handling in ${func.name}`,
385
+ type: 'negative',
386
+ priority: 'high',
387
+ code: this.generateErrorTest(func, framework),
388
+ assertions: [`expect(() => ${func.name}(invalidInput)).toThrow()`],
389
+ });
390
+ }
391
+ // Edge cases
392
+ if (func.parameters.length > 0) {
393
+ tests.push({
394
+ name: `should handle edge cases in ${func.name}`,
395
+ description: `Test boundary conditions for ${func.name}`,
396
+ type: 'edge',
397
+ priority: 'medium',
398
+ code: this.generateEdgeCaseTest(func, framework),
399
+ assertions: [`expect(result).toBeValid()`],
400
+ });
401
+ }
402
+ return tests;
403
+ }
404
+ generateHappyPathTest(func, framework) {
405
+ const params = func.parameters.map((p) => this.generateTestValue(p.type)).join(', ');
406
+ const asyncPrefix = func.isAsync ? 'await ' : '';
407
+ return `
408
+ test('should ${func.name} successfully with valid input', ${func.isAsync ? 'async ' : ''}() => {
409
+ ${func.isAsync ? '// Setup mocks if needed' : ''}
410
+ const result = ${asyncPrefix}${func.name}(${params});
411
+ expect(result).toBeDefined();
412
+ ${this.generateAdditionalAssertions(func)}
413
+ });`;
414
+ }
415
+ generateErrorTest(func, framework) {
416
+ return `
417
+ test('should handle errors in ${func.name}', ${func.isAsync ? 'async ' : ''}() => {
418
+ ${func.isAsync ? 'await expect(' : 'expect(() =>'}${func.name}(null)${func.isAsync ? ').rejects.toThrow()' : ').toThrow()'};
419
+ });`;
420
+ }
421
+ generateEdgeCaseTest(func, framework) {
422
+ const edgeParams = func.parameters.map((p) => this.generateEdgeValue(p.type)).join(', ');
423
+ return `
424
+ test('should handle edge cases in ${func.name}', ${func.isAsync ? 'async ' : ''}() => {
425
+ const result = ${func.isAsync ? 'await ' : ''}${func.name}(${edgeParams});
426
+ expect(result).toBeValid(); // Replace with appropriate assertion
427
+ });`;
428
+ }
429
+ generateTestValue(type) {
430
+ const typeMap = {
431
+ 'string': '"test"',
432
+ 'number': '42',
433
+ 'boolean': 'true',
434
+ 'object': '{}',
435
+ 'array': '[]',
436
+ 'undefined': 'undefined',
437
+ 'null': 'null'
438
+ };
439
+ return typeMap[type.toLowerCase()] || '{}';
440
+ }
441
+ generateEdgeValue(type) {
442
+ const edgeMap = {
443
+ 'string': '""', // empty string
444
+ 'number': '0',
445
+ 'boolean': 'false',
446
+ 'object': 'null',
447
+ 'array': '[]'
448
+ };
449
+ return edgeMap[type.toLowerCase()] || 'null';
450
+ }
451
+ generateAdditionalAssertions(func) {
452
+ if (func.name.toLowerCase().includes('calculate')) {
453
+ return 'expect(typeof result).toBe("number");';
454
+ }
455
+ if (func.name.toLowerCase().includes('validate')) {
456
+ return 'expect(typeof result).toBe("boolean");';
457
+ }
458
+ return '// Add specific assertions based on function behavior';
459
+ }
460
+ generateTestImports(func, framework) {
461
+ const imports = [`import { ${func.name} } from '../src/index'`];
462
+ if (framework === 'jest') {
463
+ imports.push("import { jest } from '@jest/globals'");
464
+ }
465
+ if (func.isAsync) {
466
+ imports.push("// Import mocking utilities if needed");
467
+ }
468
+ return imports;
469
+ }
470
+ generateTestSetup(func, framework) {
471
+ if (func.isAsync) {
472
+ return `beforeEach(() => {
473
+ // Setup mocks and test environment
474
+ jest.clearAllMocks();
475
+ });`;
476
+ }
477
+ return 'beforeEach(() => { /* Setup if needed */ });';
478
+ }
479
+ generateTestTeardown(func, framework) {
480
+ if (func.isAsync) {
481
+ return `afterEach(() => {
482
+ // Cleanup mocks and resources
483
+ jest.restoreAllMocks();
484
+ });`;
485
+ }
486
+ return 'afterEach(() => { /* Cleanup if needed */ });';
487
+ }
488
+ generateTestFileContent(func, framework, testType) {
489
+ const imports = this.generateTestImports(func, framework).join('\n');
490
+ const setup = this.generateTestSetup(func, framework);
491
+ const teardown = this.generateTestTeardown(func, framework);
492
+ const tests = this.generateUnitTests(func, framework);
493
+ return `${imports}
494
+
495
+ describe('${func.name}', () => {
496
+ ${setup}
497
+
498
+ ${teardown}
499
+
500
+ ${tests.map(test => test.code).join('\n ')}
501
+ });`;
502
+ }
503
+ generateIntegrationTests(structure, framework) {
504
+ const tests = [];
505
+ // Test component interactions
506
+ tests.push({
507
+ name: 'should integrate components correctly',
508
+ description: 'Test integration between multiple components',
509
+ type: 'positive',
510
+ priority: 'high',
511
+ code: this.generateComponentIntegrationTest(structure, framework),
512
+ assertions: ['expect(result).toBeDefined()']
513
+ });
514
+ return tests;
515
+ }
516
+ generateComponentIntegrationTest(structure, framework) {
517
+ const mainFunctions = structure.functions.slice(0, 2);
518
+ return `
519
+ test('should integrate components correctly', async () => {
520
+ // Test integration between ${mainFunctions.map((f) => f.name).join(' and ')}
521
+ ${mainFunctions.map((f) => `const ${f.name}Result = await ${f.name}(${this.generateTestValue('any')});`).join('\n ')}
522
+
523
+ // Assert integration works
524
+ ${mainFunctions.map((f) => `expect(${f.name}Result).toBeDefined();`).join('\n ')}
525
+ });`;
526
+ }
527
+ generateIntegrationTestContent(structure, framework) {
528
+ const tests = this.generateIntegrationTests(structure, framework);
529
+ return `import { ${structure.exports.join(', ')} } from '../src/index';
530
+
531
+ describe('Integration Tests', () => {
532
+ beforeAll(() => {
533
+ // Setup integration test environment
534
+ });
535
+
536
+ afterAll(() => {
537
+ // Cleanup integration test environment
538
+ });
539
+
540
+ ${tests.map(test => test.code).join('\n ')}
541
+ });`;
542
+ }
543
+ generateE2ETests(structure, framework) {
544
+ // Basic E2E test structure
545
+ return [{
546
+ name: 'should work end-to-end',
547
+ description: 'Complete user workflow test',
548
+ type: 'positive',
549
+ priority: 'medium',
550
+ code: this.generateE2ETestCode(structure, framework),
551
+ assertions: ['expect(page).toContainText("success")']
552
+ }];
553
+ }
554
+ generateE2ETestCode(structure, framework) {
555
+ if (framework === 'playwright') {
556
+ return `
557
+ test('should work end-to-end', async ({ page }) => {
558
+ await page.goto('/');
559
+ // Add E2E test steps here
560
+ await expect(page).toHaveTitle(/Expected Title/);
561
+ });`;
562
+ }
563
+ return `
564
+ test('should work end-to-end', async () => {
565
+ // E2E test implementation
566
+ expect(true).toBe(true); // Replace with actual test
567
+ });`;
568
+ }
569
+ generateE2EImports(framework) {
570
+ if (framework === 'playwright') {
571
+ return ["import { test, expect } from '@playwright/test'"];
572
+ }
573
+ return ["// Import E2E testing framework"];
574
+ }
575
+ generateE2ETestContent(structure, framework) {
576
+ const imports = this.generateE2EImports(framework).join('\n');
577
+ const tests = this.generateE2ETests(structure, framework);
578
+ return `${imports}
579
+
580
+ describe('E2E Tests', () => {
581
+ ${tests.map(test => test.code).join('\n ')}
582
+ });`;
583
+ }
584
+ async generateEdgeCases(structure) {
585
+ const edgeCases = [];
586
+ structure.functions.forEach((func) => {
587
+ func.parameters.forEach((param) => {
588
+ edgeCases.push({
589
+ scenario: `${func.name} with ${param.type} boundary values`,
590
+ input: this.generateBoundaryInput(param.type),
591
+ expectedOutput: 'Should handle gracefully',
592
+ description: `Test ${func.name} with edge case input for ${param.name}`,
593
+ severity: param.type === 'string' ? 'medium' : 'high',
594
+ testCode: this.generateEdgeCaseTestCode(func, param)
595
+ });
596
+ });
597
+ });
598
+ return edgeCases.slice(0, 10); // Limit to prevent overflow
599
+ }
600
+ generateBoundaryInput(type) {
601
+ const boundaries = {
602
+ 'string': ['', 'a'.repeat(1000), 'special chars: !@#$%^&*()'],
603
+ 'number': [0, -1, Number.MAX_VALUE, Number.MIN_VALUE, NaN, Infinity],
604
+ 'array': [[], new Array(1000).fill(0)],
605
+ 'object': [{}, null, undefined]
606
+ };
607
+ return boundaries[type.toLowerCase()] || null;
608
+ }
609
+ generateEdgeCaseTestCode(func, param) {
610
+ const boundaryValues = this.generateBoundaryInput(param.type);
611
+ return `
612
+ test('should handle ${param.name} boundary values', () => {
613
+ const boundaryValues = ${JSON.stringify(boundaryValues)};
614
+ boundaryValues.forEach(value => {
615
+ expect(() => ${func.name}(value)).not.toThrow();
616
+ });
617
+ });`;
618
+ }
619
+ async generateMockFiles(structure, framework) {
620
+ const mocks = [];
621
+ // Generate service mocks
622
+ const externalDeps = structure.dependencies.filter((d) => d.type === 'external');
623
+ externalDeps.forEach((dep) => {
624
+ mocks.push({
625
+ fileName: `__mocks__/${dep.module}.js`,
626
+ mockType: 'service',
627
+ content: this.generateServiceMock(dep, framework),
628
+ description: `Mock for ${dep.module} service`
629
+ });
630
+ });
631
+ // Generate API mocks
632
+ const asyncOps = structure.asyncOperations.filter((op) => op.type === 'await');
633
+ if (asyncOps.length > 0) {
634
+ mocks.push({
635
+ fileName: '__mocks__/api.js',
636
+ mockType: 'api',
637
+ content: this.generateApiMock(framework),
638
+ description: 'Mock for API calls'
639
+ });
640
+ }
641
+ return mocks;
642
+ }
643
+ generateServiceMock(dependency, framework) {
644
+ return `// Mock for ${dependency.module}
645
+ export default {
646
+ ${dependency.imports.map((imp) => `
647
+ ${imp}: jest.fn(() => Promise.resolve('mocked-${imp}'))`).join(',\n')}
648
+ };`;
649
+ }
650
+ generateApiMock(framework) {
651
+ return `// API Mock
652
+ export const mockApi = {
653
+ get: jest.fn(() => Promise.resolve({ data: 'mocked-data' })),
654
+ post: jest.fn(() => Promise.resolve({ data: 'created' })),
655
+ put: jest.fn(() => Promise.resolve({ data: 'updated' })),
656
+ delete: jest.fn(() => Promise.resolve({ data: 'deleted' }))
657
+ };`;
658
+ }
659
+ async generateTestConfiguration(framework, testSuite, coverage) {
660
+ const configs = {
661
+ jest: {
662
+ configFile: `module.exports = {
663
+ preset: 'ts-jest',
664
+ testEnvironment: 'node',
665
+ collectCoverage: true,
666
+ collectCoverageFrom: [
667
+ 'src/**/*.{ts,js}',
668
+ '!src/**/*.d.ts'
669
+ ],
670
+ coverageDirectory: 'coverage',
671
+ coverageReporters: ['text', 'lcov', 'html'],
672
+ testMatch: ['**/__tests__/**/*.(ts|js)', '**/*.(test|spec).(ts|js)'],
673
+ setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
674
+ };`,
675
+ scripts: {
676
+ 'test': 'jest',
677
+ 'test:watch': 'jest --watch',
678
+ 'test:coverage': 'jest --coverage'
679
+ },
680
+ dependencies: ['jest', '@types/jest', 'ts-jest']
681
+ },
682
+ vitest: {
683
+ configFile: `import { defineConfig } from 'vitest/config';
684
+
685
+ export default defineConfig({
686
+ test: {
687
+ globals: true,
688
+ environment: 'node',
689
+ coverage: {
690
+ provider: 'c8',
691
+ reporter: ['text', 'json', 'html']
692
+ }
693
+ }
694
+ });`,
695
+ scripts: {
696
+ 'test': 'vitest run',
697
+ 'test:watch': 'vitest',
698
+ 'test:coverage': 'vitest run --coverage'
699
+ },
700
+ dependencies: ['vitest', '@vitest/ui', 'c8']
701
+ }
702
+ };
703
+ const config = configs[framework] || configs.jest;
704
+ const coverageThreshold = coverage === 'basic' ? 70 : coverage === 'thorough' ? 85 : 95;
705
+ return {
706
+ framework,
707
+ configFile: config.configFile,
708
+ scripts: config.scripts,
709
+ dependencies: config.dependencies,
710
+ coverage: {
711
+ threshold: coverageThreshold,
712
+ reports: ['text', 'lcov', 'html'],
713
+ directories: ['src/'],
714
+ excludes: ['node_modules/', 'dist/', '*.d.ts']
715
+ }
716
+ };
717
+ }
718
+ synthesizeTestArchitecture(testSuite, testFiles, mockFiles, testConfig, edgeCases) {
719
+ let synthesis = `## Test Architecture Summary\n\n`;
720
+ // Test Suite Overview
721
+ synthesis += `**Test Suite: ${testSuite.name}**\n`;
722
+ synthesis += `- Framework: ${testSuite.framework}\n`;
723
+ synthesis += `- Total Tests: ${testSuite.totalTests}\n`;
724
+ synthesis += `- Estimated Coverage: ${testSuite.estimatedCoverage}%\n`;
725
+ synthesis += `- Test Categories: ${testSuite.testCategories.length}\n\n`;
726
+ // Test Categories
727
+ synthesis += `**Test Categories:**\n`;
728
+ testSuite.testCategories.forEach(category => {
729
+ synthesis += `- ${category.name}: ${category.testCount} tests (${category.priority} priority)\n`;
730
+ });
731
+ synthesis += '\n';
732
+ // Generated Files
733
+ synthesis += `**Generated Files:**\n`;
734
+ synthesis += `- Test Files: ${testFiles.length}\n`;
735
+ testFiles.forEach(file => {
736
+ synthesis += ` - ${file.fileName} (${file.testType}, ${file.tests.length} tests)\n`;
737
+ });
738
+ if (mockFiles.length > 0) {
739
+ synthesis += `- Mock Files: ${mockFiles.length}\n`;
740
+ mockFiles.forEach(mock => {
741
+ synthesis += ` - ${mock.fileName} (${mock.mockType})\n`;
742
+ });
743
+ }
744
+ synthesis += '\n';
745
+ // Edge Cases
746
+ const criticalEdgeCases = edgeCases.filter(e => e.severity === 'high').length;
747
+ if (criticalEdgeCases > 0) {
748
+ synthesis += `**Critical Edge Cases: ${criticalEdgeCases}**\n`;
749
+ edgeCases.filter(e => e.severity === 'high').slice(0, 3).forEach(edge => {
750
+ synthesis += `- ${edge.scenario}\n`;
751
+ });
752
+ synthesis += '\n';
753
+ }
754
+ // Setup Instructions
755
+ synthesis += `**Setup Instructions:**\n`;
756
+ testSuite.setupRequirements.forEach(req => {
757
+ synthesis += `1. ${req}\n`;
758
+ });
759
+ synthesis += `\n**Next Steps:**\n`;
760
+ synthesis += `1. Install dependencies: ${testConfig.dependencies.join(', ')}\n`;
761
+ synthesis += `2. Add test scripts to package.json\n`;
762
+ synthesis += `3. Create ${testConfig.framework} configuration file\n`;
763
+ synthesis += `4. Run tests to establish baseline\n`;
764
+ synthesis += `5. Integrate with CI/CD pipeline\n`;
765
+ return synthesis;
766
+ }
767
+ }