musubi-sdd 3.9.0 → 5.0.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 (51) hide show
  1. package/README.ja.md +25 -1
  2. package/README.md +30 -1
  3. package/package.json +1 -1
  4. package/src/agents/agent-loop.js +532 -0
  5. package/src/agents/agentic/code-generator.js +767 -0
  6. package/src/agents/agentic/code-reviewer.js +698 -0
  7. package/src/agents/agentic/index.js +43 -0
  8. package/src/agents/function-tool.js +432 -0
  9. package/src/agents/index.js +45 -0
  10. package/src/agents/schema-generator.js +514 -0
  11. package/src/analyzers/ast-extractor.js +863 -0
  12. package/src/analyzers/context-optimizer.js +674 -0
  13. package/src/analyzers/repository-map.js +685 -0
  14. package/src/integrations/index.js +7 -1
  15. package/src/integrations/mcp/index.js +175 -0
  16. package/src/integrations/mcp/mcp-context-provider.js +472 -0
  17. package/src/integrations/mcp/mcp-discovery.js +436 -0
  18. package/src/integrations/mcp/mcp-tool-registry.js +467 -0
  19. package/src/integrations/mcp-connector.js +818 -0
  20. package/src/integrations/tool-discovery.js +589 -0
  21. package/src/managers/index.js +7 -0
  22. package/src/managers/skill-tools.js +565 -0
  23. package/src/monitoring/quality-dashboard.js +483 -0
  24. package/src/orchestration/agent-skill-binding.js +655 -0
  25. package/src/orchestration/error-handler.js +827 -0
  26. package/src/orchestration/index.js +235 -1
  27. package/src/orchestration/mcp-tool-adapters.js +896 -0
  28. package/src/orchestration/reasoning/index.js +58 -0
  29. package/src/orchestration/reasoning/planning-engine.js +831 -0
  30. package/src/orchestration/reasoning/reasoning-engine.js +710 -0
  31. package/src/orchestration/reasoning/self-correction.js +751 -0
  32. package/src/orchestration/skill-executor.js +665 -0
  33. package/src/orchestration/skill-registry.js +650 -0
  34. package/src/orchestration/workflow-examples.js +1072 -0
  35. package/src/orchestration/workflow-executor.js +779 -0
  36. package/src/phase4-integration.js +248 -0
  37. package/src/phase5-integration.js +402 -0
  38. package/src/steering/steering-auto-update.js +572 -0
  39. package/src/steering/steering-validator.js +547 -0
  40. package/src/templates/agents/claude-code/CLAUDE.md +9 -0
  41. package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +26 -0
  42. package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +9 -0
  43. package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +34 -0
  44. package/src/templates/agents/codex/AGENTS.md +9 -0
  45. package/src/templates/agents/cursor/AGENTS.md +9 -0
  46. package/src/templates/agents/gemini-cli/GEMINI.md +9 -0
  47. package/src/templates/agents/github-copilot/AGENTS.md +9 -0
  48. package/src/templates/agents/qwen-code/QWEN.md +9 -0
  49. package/src/templates/agents/windsurf/AGENTS.md +9 -0
  50. package/src/templates/template-constraints.js +646 -0
  51. package/src/validators/advanced-validation.js +580 -0
@@ -0,0 +1,767 @@
1
+ /**
2
+ * @file code-generator.js
3
+ * @description Autonomous code generation engine for agentic coding
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { EventEmitter } = require('events');
10
+ const path = require('path');
11
+
12
+ /**
13
+ * Generation mode types
14
+ * @enum {string}
15
+ */
16
+ const GEN_MODE = {
17
+ CREATE: 'create',
18
+ MODIFY: 'modify',
19
+ EXTEND: 'extend',
20
+ REFACTOR: 'refactor'
21
+ };
22
+
23
+ /**
24
+ * Language types
25
+ * @enum {string}
26
+ */
27
+ const LANGUAGE = {
28
+ JAVASCRIPT: 'javascript',
29
+ TYPESCRIPT: 'typescript',
30
+ PYTHON: 'python',
31
+ JSON: 'json',
32
+ MARKDOWN: 'markdown',
33
+ YAML: 'yaml'
34
+ };
35
+
36
+ /**
37
+ * @typedef {Object} GenerationRequest
38
+ * @property {string} description - What to generate
39
+ * @property {string} [mode=GEN_MODE.CREATE] - Generation mode
40
+ * @property {string} [language] - Target language
41
+ * @property {string} [filePath] - Target file path
42
+ * @property {Object} [context] - Additional context
43
+ * @property {Object} [constraints] - Generation constraints
44
+ */
45
+
46
+ /**
47
+ * @typedef {Object} GenerationResult
48
+ * @property {string} id - Result identifier
49
+ * @property {boolean} success - Whether generation succeeded
50
+ * @property {string} code - Generated code
51
+ * @property {string} language - Code language
52
+ * @property {string} [filePath] - Target file path
53
+ * @property {Object} metadata - Generation metadata
54
+ * @property {string[]} [warnings] - Generation warnings
55
+ */
56
+
57
+ /**
58
+ * @typedef {Object} CodeGeneratorOptions
59
+ * @property {Object} [templates={}] - Code templates
60
+ * @property {boolean} [addComments=true] - Add documentation comments
61
+ * @property {boolean} [addTyping=true] - Add type annotations where applicable
62
+ * @property {string} [style='standard'] - Code style
63
+ * @property {number} [indentSize=2] - Indentation size
64
+ * @property {boolean} [useTabs=false] - Use tabs for indentation
65
+ */
66
+
67
+ /**
68
+ * Code templates for various patterns
69
+ */
70
+ const TEMPLATES = {
71
+ javascript: {
72
+ class: `/**
73
+ * @class {name}
74
+ * @description {description}
75
+ */
76
+ class {name} {
77
+ /**
78
+ * Create {name}
79
+ * @param {Object} options - Options
80
+ */
81
+ constructor(options = {}) {
82
+ {properties}
83
+ }
84
+
85
+ {methods}
86
+ }
87
+
88
+ module.exports = { {name} };`,
89
+
90
+ function: `/**
91
+ * {description}
92
+ * @param {params}
93
+ * @returns {returns}
94
+ */
95
+ function {name}({paramNames}) {
96
+ {body}
97
+ }`,
98
+
99
+ asyncFunction: `/**
100
+ * {description}
101
+ * @param {params}
102
+ * @returns {Promise<{returns}>}
103
+ */
104
+ async function {name}({paramNames}) {
105
+ {body}
106
+ }`,
107
+
108
+ module: `/**
109
+ * @file {filename}
110
+ * @description {description}
111
+ * @version 1.0.0
112
+ */
113
+
114
+ 'use strict';
115
+
116
+ {imports}
117
+
118
+ {body}
119
+
120
+ module.exports = {
121
+ {exports}
122
+ };`,
123
+
124
+ test: `/**
125
+ * @file {filename}
126
+ * @description Tests for {testSubject}
127
+ */
128
+
129
+ 'use strict';
130
+
131
+ const { {imports} } = require('{importPath}');
132
+
133
+ describe('{testSubject}', () => {
134
+ {beforeEach}
135
+
136
+ {testCases}
137
+ });`
138
+ },
139
+
140
+ typescript: {
141
+ interface: `/**
142
+ * {description}
143
+ */
144
+ export interface {name} {
145
+ {properties}
146
+ }`,
147
+
148
+ class: `/**
149
+ * @class {name}
150
+ * @description {description}
151
+ */
152
+ export class {name} {
153
+ {properties}
154
+
155
+ /**
156
+ * Create {name}
157
+ */
158
+ constructor({constructorParams}) {
159
+ {constructorBody}
160
+ }
161
+
162
+ {methods}
163
+ }`,
164
+
165
+ function: `/**
166
+ * {description}
167
+ * @param {params}
168
+ * @returns {returns}
169
+ */
170
+ export function {name}({paramNames}): {returnType} {
171
+ {body}
172
+ }`
173
+ },
174
+
175
+ python: {
176
+ class: `"""
177
+ {description}
178
+ """
179
+
180
+ class {name}:
181
+ """
182
+ {classDoc}
183
+ """
184
+
185
+ def __init__(self{initParams}):
186
+ """Initialize {name}."""
187
+ {initBody}
188
+
189
+ {methods}`,
190
+
191
+ function: `def {name}({paramNames}){returnType}:
192
+ """
193
+ {description}
194
+
195
+ Args:
196
+ {argDocs}
197
+
198
+ Returns:
199
+ {returnDoc}
200
+ """
201
+ {body}`,
202
+
203
+ asyncFunction: `async def {name}({paramNames}){returnType}:
204
+ """
205
+ {description}
206
+
207
+ Args:
208
+ {argDocs}
209
+
210
+ Returns:
211
+ {returnDoc}
212
+ """
213
+ {body}`
214
+ }
215
+ };
216
+
217
+ /**
218
+ * Code Generator class for autonomous code generation
219
+ * @extends EventEmitter
220
+ */
221
+ class CodeGenerator extends EventEmitter {
222
+ /**
223
+ * Create code generator
224
+ * @param {CodeGeneratorOptions} [options={}] - Generator options
225
+ */
226
+ constructor(options = {}) {
227
+ super();
228
+
229
+ this.templates = { ...TEMPLATES, ...(options.templates || {}) };
230
+ this.addComments = options.addComments ?? true;
231
+ this.addTyping = options.addTyping ?? true;
232
+ this.style = options.style || 'standard';
233
+ this.indentSize = options.indentSize ?? 2;
234
+ this.useTabs = options.useTabs ?? false;
235
+
236
+ // State
237
+ this.history = [];
238
+ this.generationCounter = 0;
239
+ }
240
+
241
+ /**
242
+ * Generate code from request
243
+ * @param {GenerationRequest} request - Generation request
244
+ * @returns {Promise<GenerationResult>}
245
+ */
246
+ async generate(request) {
247
+ const id = this.generateId();
248
+ const startTime = Date.now();
249
+
250
+ this.emit('generation:start', { id, request });
251
+
252
+ try {
253
+ // Determine language
254
+ const language = request.language || this.detectLanguage(request);
255
+
256
+ // Select generation strategy
257
+ let code;
258
+ switch (request.mode || GEN_MODE.CREATE) {
259
+ case GEN_MODE.CREATE:
260
+ code = await this.generateNew(request, language);
261
+ break;
262
+ case GEN_MODE.MODIFY:
263
+ code = await this.generateModification(request, language);
264
+ break;
265
+ case GEN_MODE.EXTEND:
266
+ code = await this.generateExtension(request, language);
267
+ break;
268
+ case GEN_MODE.REFACTOR:
269
+ code = await this.generateRefactoring(request, language);
270
+ break;
271
+ default:
272
+ code = await this.generateNew(request, language);
273
+ }
274
+
275
+ // Apply formatting
276
+ code = this.format(code, language);
277
+
278
+ const result = {
279
+ id,
280
+ success: true,
281
+ code,
282
+ language,
283
+ filePath: request.filePath,
284
+ metadata: {
285
+ mode: request.mode || GEN_MODE.CREATE,
286
+ duration: Date.now() - startTime,
287
+ linesOfCode: code.split('\n').length
288
+ },
289
+ warnings: []
290
+ };
291
+
292
+ // Store in history
293
+ this.history.push(result);
294
+
295
+ this.emit('generation:complete', { result });
296
+
297
+ return result;
298
+
299
+ } catch (error) {
300
+ const result = {
301
+ id,
302
+ success: false,
303
+ code: '',
304
+ language: request.language || 'unknown',
305
+ filePath: request.filePath,
306
+ metadata: {
307
+ mode: request.mode || GEN_MODE.CREATE,
308
+ duration: Date.now() - startTime,
309
+ error: error.message
310
+ },
311
+ warnings: [error.message]
312
+ };
313
+
314
+ this.emit('generation:error', { id, error: error.message });
315
+
316
+ return result;
317
+ }
318
+ }
319
+
320
+ /**
321
+ * Generate new code
322
+ * @private
323
+ */
324
+ async generateNew(request, language) {
325
+ const description = request.description.toLowerCase();
326
+
327
+ // Detect what to generate
328
+ if (description.includes('class')) {
329
+ return this.generateClass(request, language);
330
+ } else if (description.includes('function') || description.includes('method')) {
331
+ return this.generateFunction(request, language);
332
+ } else if (description.includes('interface') && language === LANGUAGE.TYPESCRIPT) {
333
+ return this.generateInterface(request, language);
334
+ } else if (description.includes('test')) {
335
+ return this.generateTest(request, language);
336
+ } else if (description.includes('module') || description.includes('file')) {
337
+ return this.generateModule(request, language);
338
+ } else {
339
+ // Default to function
340
+ return this.generateFunction(request, language);
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Generate modification code
346
+ * @private
347
+ */
348
+ async generateModification(request, language) {
349
+ const { context } = request;
350
+
351
+ if (!context || !context.existingCode) {
352
+ throw new Error('Modification requires existing code in context');
353
+ }
354
+
355
+ // Simple modification: add or update based on description
356
+ let modified = context.existingCode;
357
+
358
+ // Add comments if requested
359
+ if (this.addComments && request.description.includes('document')) {
360
+ modified = this.addDocumentation(modified, language);
361
+ }
362
+
363
+ return modified;
364
+ }
365
+
366
+ /**
367
+ * Generate extension code
368
+ * @private
369
+ */
370
+ async generateExtension(request, language) {
371
+ const { context } = request;
372
+
373
+ if (!context || !context.existingCode) {
374
+ throw new Error('Extension requires existing code in context');
375
+ }
376
+
377
+ const existing = context.existingCode;
378
+ const extension = await this.generateNew(request, language);
379
+
380
+ return `${existing}\n\n${extension}`;
381
+ }
382
+
383
+ /**
384
+ * Generate refactoring
385
+ * @private
386
+ */
387
+ async generateRefactoring(request, language) {
388
+ const { context } = request;
389
+
390
+ if (!context || !context.existingCode) {
391
+ throw new Error('Refactoring requires existing code in context');
392
+ }
393
+
394
+ // Simple refactoring: improve structure
395
+ let refactored = context.existingCode;
396
+
397
+ // Add proper indentation
398
+ refactored = this.format(refactored, language);
399
+
400
+ return refactored;
401
+ }
402
+
403
+ /**
404
+ * Generate a class
405
+ * @private
406
+ */
407
+ generateClass(request, language) {
408
+ const className = this.extractName(request.description, 'Class');
409
+ const template = this.templates[language]?.class || this.templates.javascript.class;
410
+
411
+ let code = template
412
+ .replace(/{name}/g, className)
413
+ .replace(/{description}/g, request.description)
414
+ .replace(/{properties}/g, this.generateProperties(request, language))
415
+ .replace(/{methods}/g, this.generateMethods(request, language));
416
+
417
+ if (language === LANGUAGE.TYPESCRIPT) {
418
+ code = code
419
+ .replace(/{constructorParams}/g, '')
420
+ .replace(/{constructorBody}/g, '');
421
+ }
422
+
423
+ return code;
424
+ }
425
+
426
+ /**
427
+ * Generate a function
428
+ * @private
429
+ */
430
+ generateFunction(request, language) {
431
+ const funcName = this.extractName(request.description, 'function');
432
+ const isAsync = request.description.toLowerCase().includes('async');
433
+
434
+ const templateKey = isAsync ? 'asyncFunction' : 'function';
435
+ const template = this.templates[language]?.[templateKey] || this.templates.javascript[templateKey];
436
+
437
+ const params = this.extractParams(request.description);
438
+
439
+ let code = template
440
+ .replace(/{name}/g, funcName)
441
+ .replace(/{description}/g, request.description)
442
+ .replace(/{params}/g, params.map(p => `@param {${p.type}} ${p.name}`).join('\n * '))
443
+ .replace(/{paramNames}/g, params.map(p => p.name).join(', '))
444
+ .replace(/{returns}/g, 'any')
445
+ .replace(/{returnType}/g, ': any')
446
+ .replace(/{body}/g, '// TODO: Implement')
447
+ .replace(/{argDocs}/g, params.map(p => `${p.name}: ${p.type}`).join('\n '))
448
+ .replace(/{returnDoc}/g, 'Result');
449
+
450
+ return code;
451
+ }
452
+
453
+ /**
454
+ * Generate an interface (TypeScript)
455
+ * @private
456
+ */
457
+ generateInterface(request, language) {
458
+ if (language !== LANGUAGE.TYPESCRIPT) {
459
+ throw new Error('Interfaces are only supported in TypeScript');
460
+ }
461
+
462
+ const interfaceName = this.extractName(request.description, 'Interface');
463
+ const template = this.templates.typescript.interface;
464
+
465
+ return template
466
+ .replace(/{name}/g, interfaceName)
467
+ .replace(/{description}/g, request.description)
468
+ .replace(/{properties}/g, ' // TODO: Add properties');
469
+ }
470
+
471
+ /**
472
+ * Generate test code
473
+ * @private
474
+ */
475
+ generateTest(request, language) {
476
+ const template = this.templates.javascript.test;
477
+ const testSubject = this.extractName(request.description, 'Subject');
478
+ const fileName = request.filePath ? path.basename(request.filePath) : 'test.test.js';
479
+
480
+ return template
481
+ .replace(/{filename}/g, fileName)
482
+ .replace(/{testSubject}/g, testSubject)
483
+ .replace(/{imports}/g, testSubject)
484
+ .replace(/{importPath}/g, `./${testSubject.toLowerCase()}`)
485
+ .replace(/{beforeEach}/g, `let instance;\n \n beforeEach(() => {\n instance = new ${testSubject}();\n });`)
486
+ .replace(/{testCases}/g, this.generateTestCases(testSubject));
487
+ }
488
+
489
+ /**
490
+ * Generate module code
491
+ * @private
492
+ */
493
+ generateModule(request, language) {
494
+ const template = this.templates.javascript.module;
495
+ const fileName = request.filePath ? path.basename(request.filePath) : 'module.js';
496
+
497
+ return template
498
+ .replace(/{filename}/g, fileName)
499
+ .replace(/{description}/g, request.description)
500
+ .replace(/{imports}/g, '')
501
+ .replace(/{body}/g, '// TODO: Implement module')
502
+ .replace(/{exports}/g, '');
503
+ }
504
+
505
+ /**
506
+ * Generate class properties
507
+ * @private
508
+ */
509
+ generateProperties(request, language) {
510
+ const constraints = request.constraints || {};
511
+ const props = constraints.properties || [];
512
+
513
+ if (props.length === 0) {
514
+ return 'this.options = options;';
515
+ }
516
+
517
+ return props.map(p => `this.${p} = options.${p};`).join('\n ');
518
+ }
519
+
520
+ /**
521
+ * Generate class methods
522
+ * @private
523
+ */
524
+ generateMethods(request, language) {
525
+ const constraints = request.constraints || {};
526
+ const methods = constraints.methods || [];
527
+
528
+ if (methods.length === 0) {
529
+ return `/**
530
+ * Main method
531
+ */
532
+ execute() {
533
+ // TODO: Implement
534
+ }`;
535
+ }
536
+
537
+ return methods.map(m => `/**
538
+ * ${m.description || m.name}
539
+ */
540
+ ${m.name}() {
541
+ // TODO: Implement
542
+ }`).join('\n \n ');
543
+ }
544
+
545
+ /**
546
+ * Generate test cases
547
+ * @private
548
+ */
549
+ generateTestCases(subject) {
550
+ return `describe('constructor', () => {
551
+ it('should create instance', () => {
552
+ expect(instance).toBeDefined();
553
+ });
554
+ });
555
+
556
+ describe('methods', () => {
557
+ it('should have required methods', () => {
558
+ // TODO: Add method tests
559
+ });
560
+ });`;
561
+ }
562
+
563
+ /**
564
+ * Extract name from description
565
+ * @private
566
+ */
567
+ extractName(description, defaultName) {
568
+ // Look for quoted names
569
+ const quotedMatch = description.match(/['"]([^'"]+)['"]/);
570
+ if (quotedMatch) return quotedMatch[1];
571
+
572
+ // Look for "called X" or "named X"
573
+ const namedMatch = description.match(/(?:called|named)\s+([a-zA-Z_][a-zA-Z0-9_]*)/i);
574
+ if (namedMatch) return namedMatch[1];
575
+
576
+ // Look for capitalized word after "a" or "an"
577
+ const articleMatch = description.match(/(?:a|an)\s+([A-Z][a-zA-Z0-9_]*)/);
578
+ if (articleMatch) return articleMatch[1];
579
+
580
+ return defaultName;
581
+ }
582
+
583
+ /**
584
+ * Extract parameters from description
585
+ * @private
586
+ */
587
+ extractParams(description) {
588
+ const params = [];
589
+
590
+ // Look for "with parameters X, Y, Z"
591
+ const paramMatch = description.match(/(?:with\s+)?param(?:eter)?s?\s+([^.]+)/i);
592
+ if (paramMatch) {
593
+ const paramList = paramMatch[1].split(/[,\s]+/).filter(p => p && !['and', 'or'].includes(p));
594
+ params.push(...paramList.map(name => ({ name, type: 'any' })));
595
+ }
596
+
597
+ // Look for "takes X and Y"
598
+ const takesMatch = description.match(/takes\s+([^.]+)/i);
599
+ if (takesMatch && params.length === 0) {
600
+ const paramList = takesMatch[1].split(/[,\s]+/).filter(p => p && !['and', 'or', 'a', 'an'].includes(p));
601
+ params.push(...paramList.map(name => ({ name, type: 'any' })));
602
+ }
603
+
604
+ return params;
605
+ }
606
+
607
+ /**
608
+ * Detect language from request
609
+ * @private
610
+ */
611
+ detectLanguage(request) {
612
+ if (request.filePath) {
613
+ const ext = path.extname(request.filePath);
614
+ const langMap = {
615
+ '.js': LANGUAGE.JAVASCRIPT,
616
+ '.ts': LANGUAGE.TYPESCRIPT,
617
+ '.py': LANGUAGE.PYTHON,
618
+ '.json': LANGUAGE.JSON,
619
+ '.md': LANGUAGE.MARKDOWN,
620
+ '.yaml': LANGUAGE.YAML,
621
+ '.yml': LANGUAGE.YAML
622
+ };
623
+ return langMap[ext] || LANGUAGE.JAVASCRIPT;
624
+ }
625
+
626
+ // Check description for language hints
627
+ const desc = request.description.toLowerCase();
628
+ if (desc.includes('typescript') || desc.includes('ts')) return LANGUAGE.TYPESCRIPT;
629
+ if (desc.includes('python') || desc.includes('py')) return LANGUAGE.PYTHON;
630
+
631
+ return LANGUAGE.JAVASCRIPT;
632
+ }
633
+
634
+ /**
635
+ * Format code
636
+ * @private
637
+ */
638
+ format(code, language) {
639
+ const indent = this.useTabs ? '\t' : ' '.repeat(this.indentSize);
640
+
641
+ // Normalize line endings
642
+ code = code.replace(/\r\n/g, '\n');
643
+
644
+ // Remove trailing whitespace
645
+ code = code.split('\n').map(line => line.trimEnd()).join('\n');
646
+
647
+ // Ensure single newline at end
648
+ code = code.trimEnd() + '\n';
649
+
650
+ return code;
651
+ }
652
+
653
+ /**
654
+ * Add documentation to code
655
+ * @private
656
+ */
657
+ addDocumentation(code, language) {
658
+ // Simple documentation addition
659
+ if (language === LANGUAGE.JAVASCRIPT || language === LANGUAGE.TYPESCRIPT) {
660
+ if (!code.startsWith('/**') && !code.startsWith('//')) {
661
+ code = '// Auto-documented code\n' + code;
662
+ }
663
+ } else if (language === LANGUAGE.PYTHON) {
664
+ if (!code.startsWith('"""') && !code.startsWith('#')) {
665
+ code = '# Auto-documented code\n' + code;
666
+ }
667
+ }
668
+
669
+ return code;
670
+ }
671
+
672
+ /**
673
+ * Generate unique ID
674
+ * @private
675
+ */
676
+ generateId() {
677
+ return `gen-${++this.generationCounter}-${Date.now().toString(36)}`;
678
+ }
679
+
680
+ /**
681
+ * Get generation history
682
+ * @param {number} [count] - Number of items to return
683
+ * @returns {GenerationResult[]}
684
+ */
685
+ getHistory(count) {
686
+ if (count) {
687
+ return this.history.slice(-count);
688
+ }
689
+ return [...this.history];
690
+ }
691
+
692
+ /**
693
+ * Clear history
694
+ */
695
+ clearHistory() {
696
+ this.history = [];
697
+ }
698
+
699
+ /**
700
+ * Get statistics
701
+ * @returns {Object}
702
+ */
703
+ getStats() {
704
+ const successful = this.history.filter(r => r.success).length;
705
+ const byLanguage = {};
706
+ const byMode = {};
707
+ let totalLines = 0;
708
+
709
+ for (const result of this.history) {
710
+ byLanguage[result.language] = (byLanguage[result.language] || 0) + 1;
711
+ byMode[result.metadata.mode] = (byMode[result.metadata.mode] || 0) + 1;
712
+ totalLines += result.metadata.linesOfCode || 0;
713
+ }
714
+
715
+ return {
716
+ totalGenerations: this.history.length,
717
+ successful,
718
+ failed: this.history.length - successful,
719
+ successRate: this.history.length > 0 ? successful / this.history.length : 0,
720
+ byLanguage,
721
+ byMode,
722
+ totalLinesGenerated: totalLines
723
+ };
724
+ }
725
+
726
+ /**
727
+ * Add custom template
728
+ * @param {string} language - Language
729
+ * @param {string} name - Template name
730
+ * @param {string} template - Template content
731
+ */
732
+ addTemplate(language, name, template) {
733
+ if (!this.templates[language]) {
734
+ this.templates[language] = {};
735
+ }
736
+ this.templates[language][name] = template;
737
+ }
738
+ }
739
+
740
+ /**
741
+ * Create code generator
742
+ * @param {CodeGeneratorOptions} [options={}] - Generator options
743
+ * @returns {CodeGenerator}
744
+ */
745
+ function createCodeGenerator(options = {}) {
746
+ return new CodeGenerator(options);
747
+ }
748
+
749
+ /**
750
+ * Generate code from description
751
+ * @param {string} description - What to generate
752
+ * @param {Object} [options={}] - Generation options
753
+ * @returns {Promise<GenerationResult>}
754
+ */
755
+ async function generateCode(description, options = {}) {
756
+ const generator = createCodeGenerator(options);
757
+ return generator.generate({ description, ...options });
758
+ }
759
+
760
+ module.exports = {
761
+ CodeGenerator,
762
+ createCodeGenerator,
763
+ generateCode,
764
+ GEN_MODE,
765
+ LANGUAGE,
766
+ TEMPLATES
767
+ };