code-simplifier 1.0.0 → 1.2.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.
@@ -0,0 +1,757 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * AI-Powered Knowledge Base
5
+ * Automatically extracts and manages best practices from code analysis
6
+ * Provides intelligent Q&A and learning materials
7
+ */
8
+
9
+ const fs = require('fs-extra')
10
+ const path = require('path')
11
+ const chalk = require('chalk')
12
+ const { OpenAI } = require('openai')
13
+ const Anthropic = require('@anthropic-ai/sdk')
14
+
15
+ /**
16
+ * AI Knowledge Base - Manages best practices, patterns, and learning materials
17
+ */
18
+ class AIKnowledgeBase {
19
+ constructor(config = {}) {
20
+ this.config = {
21
+ dataDir: config.dataDir || path.join(process.cwd(), 'knowledge-base'),
22
+ casesFile: config.casesFile || 'cases.json',
23
+ patternsFile: config.patternsFile || 'patterns.json',
24
+ minCasesPerWeek: config.minCasesPerWeek || 10,
25
+ maxIterations: config.maxIterations || 50,
26
+ openaiApiKey: config.openaiApiKey || process.env.OPENAI_API_KEY,
27
+ anthropicApiKey: config.anthropicApiKey || process.env.ANTHROPIC_API_KEY,
28
+ ...config
29
+ }
30
+
31
+ this.cases = []
32
+ this.patterns = {}
33
+ this.statistics = {
34
+ totalCases: 0,
35
+ weeklyCases: 0,
36
+ tagAccuracy: 0,
37
+ lastUpdated: null
38
+ }
39
+
40
+ this.openai = this.config.openaiApiKey ? new OpenAI({ apiKey: this.config.openaiApiKey }) : null
41
+ this.anthropic = this.config.anthropicApiKey ? new Anthropic({ apiKey: this.config.anthropicApiKey }) : null
42
+
43
+ this.knowledgeDir = path.join(this.config.dataDir, 'knowledge')
44
+ this.examplesDir = path.join(this.config.dataDir, 'examples')
45
+ }
46
+
47
+ /**
48
+ * Initialize the knowledge base
49
+ */
50
+ async initialize() {
51
+ await fs.ensureDir(this.knowledgeDir)
52
+ await fs.ensureDir(this.examplesDir)
53
+ await this.loadKnowledgeBase()
54
+ }
55
+
56
+ /**
57
+ * Load knowledge base from files
58
+ */
59
+ async loadKnowledgeBase() {
60
+ try {
61
+ const casesPath = path.join(this.config.dataDir, this.config.casesFile)
62
+ const patternsPath = path.join(this.config.dataDir, this.config.patternsFile)
63
+
64
+ if (await fs.pathExists(casesPath)) {
65
+ this.cases = await fs.readJson(casesPath)
66
+ }
67
+
68
+ if (await fs.pathExists(patternsPath)) {
69
+ this.patterns = await fs.readJson(patternsPath)
70
+ }
71
+
72
+ this.updateStatistics()
73
+ } catch (error) {
74
+ console.error(chalk.red('Error loading knowledge base:'), error.message)
75
+ this.cases = []
76
+ this.patterns = {}
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Save knowledge base to files
82
+ */
83
+ async saveKnowledgeBase() {
84
+ try {
85
+ await fs.ensureDir(this.config.dataDir)
86
+ const casesPath = path.join(this.config.dataDir, this.config.casesFile)
87
+ const patternsPath = path.join(this.config.dataDir, this.config.patternsFile)
88
+
89
+ await fs.writeJson(casesPath, this.cases, { spaces: 2 })
90
+ await fs.writeJson(patternsPath, this.patterns, { spaces: 2 })
91
+
92
+ this.statistics.lastUpdated = new Date().toISOString()
93
+ } catch (error) {
94
+ console.error(chalk.red('Error saving knowledge base:'), error.message)
95
+ // Don't throw, just log the error
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Extract best practices from code analysis results
101
+ */
102
+ async extractBestPractices(analysisResult, metadata = {}) {
103
+ console.log(chalk.blue('Extracting best practices from analysis...'))
104
+
105
+ const cases = []
106
+
107
+ for (const fileResult of analysisResult.files || []) {
108
+ const issues = fileResult.issues || []
109
+
110
+ for (const issue of issues) {
111
+ if (issue.severity === 'error' || issue.severity === 'warning') {
112
+ const bestPractice = await this.generateBestPractice(issue, fileResult, metadata)
113
+ if (bestPractice) {
114
+ cases.push(bestPractice)
115
+ }
116
+ }
117
+ }
118
+ }
119
+
120
+ // Smart classification and tagging
121
+ for (const caseItem of cases) {
122
+ await this.classifyAndTagCase(caseItem)
123
+ }
124
+
125
+ // Add to knowledge base
126
+ this.cases.push(...cases)
127
+
128
+ // Ensure we meet weekly quota
129
+ await this.ensureWeeklyQuota()
130
+
131
+ await this.saveKnowledgeBase()
132
+
133
+ return {
134
+ extracted: cases.length,
135
+ totalCases: this.cases.length,
136
+ weeklyCases: this.statistics.weeklyCases
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Generate best practice from an issue
142
+ */
143
+ async generateBestPractice(issue, fileResult, metadata) {
144
+ const prompt = `
145
+ Based on the following code issue, generate a comprehensive best practice case:
146
+
147
+ Issue: ${issue.type}
148
+ Description: ${issue.description}
149
+ File: ${fileResult.filePath}
150
+ Language: ${fileResult.language}
151
+ Severity: ${issue.severity}
152
+ Location: Line ${issue.line}
153
+
154
+ Code Context:
155
+ ${issue.codeSnippet || 'No code snippet available'}
156
+
157
+ Generate a best practice case in JSON format with:
158
+ 1. title: Clear, descriptive title
159
+ 2. problem: Detailed explanation of the problem
160
+ 3. whyItMatters: Why this issue is important
161
+ 4. solution: Step-by-step solution
162
+ 5. codeExample: Working code example
163
+ 6. tags: Relevant tags (3-5 tags)
164
+ 7. category: Main category
165
+ 8. language: Programming language
166
+ 9. difficulty: beginner/intermediate/advanced
167
+ 10. relatedPatterns: Array of related patterns
168
+ 11. preventionTips: Tips to prevent this issue
169
+
170
+ Return only valid JSON.
171
+ `
172
+
173
+ try {
174
+ const response = await this.generateWithAI(prompt)
175
+ const parsed = JSON.parse(response)
176
+
177
+ return {
178
+ id: this.generateCaseId(),
179
+ timestamp: new Date().toISOString(),
180
+ source: 'ai-analysis',
181
+ sourceFile: fileResult.filePath,
182
+ ...parsed,
183
+ metadata: {
184
+ originalIssue: issue,
185
+ fileLanguage: fileResult.language,
186
+ analysisMetadata: metadata
187
+ }
188
+ }
189
+ } catch (error) {
190
+ console.warn(chalk.yellow('Could not generate AI case, using template:'), error.message)
191
+ return this.createTemplateCase(issue, fileResult)
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Create a template case when AI is not available
197
+ */
198
+ createTemplateCase(issue, fileResult) {
199
+ return {
200
+ id: this.generateCaseId(),
201
+ timestamp: new Date().toISOString(),
202
+ source: 'template',
203
+ sourceFile: fileResult.filePath,
204
+ title: `${issue.type}: ${issue.description}`,
205
+ problem: issue.description,
206
+ whyItMatters: `This ${issue.severity} issue affects code quality and maintainability.`,
207
+ solution: this.getDefaultSolution(issue.type),
208
+ codeExample: issue.codeSnippet || '// Example code needed',
209
+ tags: this.extractTagsFromIssue(issue),
210
+ category: this.getCategoryFromIssue(issue),
211
+ language: fileResult.language || 'unknown',
212
+ difficulty: 'intermediate',
213
+ relatedPatterns: [],
214
+ preventionTips: ['Follow coding standards', 'Regular code reviews', 'Use linters'],
215
+ metadata: {
216
+ originalIssue: issue,
217
+ fileLanguage: fileResult.language
218
+ }
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Classify and tag a case intelligently
224
+ */
225
+ async classifyAndTagCase(caseItem) {
226
+ const prompt = `
227
+ Analyze this best practice case and provide smart classification:
228
+
229
+ Title: ${caseItem.title}
230
+ Problem: ${caseItem.problem}
231
+ Solution: ${caseItem.solution}
232
+
233
+ Provide enhanced tags (3-5 additional tags) and category refinements.
234
+ Focus on: design patterns, anti-patterns, best practices, language-specific idioms.
235
+
236
+ Return JSON with:
237
+ {
238
+ "enhancedTags": ["tag1", "tag2", "tag3"],
239
+ "confidence": 0.95,
240
+ "patternTypes": ["pattern1", "pattern2"]
241
+ }
242
+ `
243
+
244
+ try {
245
+ const response = await this.generateWithAI(prompt)
246
+ const parsed = JSON.parse(response)
247
+
248
+ caseItem.tags = [...new Set([...caseItem.tags, ...parsed.enhancedTags])]
249
+ caseItem.patternTypes = parsed.patternTypes
250
+ caseItem.classificationConfidence = parsed.confidence
251
+ } catch (error) {
252
+ console.warn(chalk.yellow('Classification failed, using defaults'))
253
+ caseItem.classificationConfidence = 0.7
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Generate learning materials and examples
259
+ */
260
+ async generateLearningMaterials(caseId) {
261
+ const caseItem = this.cases.find(c => c.id === caseId)
262
+ if (!caseItem) {
263
+ throw new Error(`Case ${caseId} not found`)
264
+ }
265
+
266
+ const materials = {
267
+ caseId,
268
+ generatedAt: new Date().toISOString(),
269
+ sections: []
270
+ }
271
+
272
+ // Generate different types of learning materials
273
+ materials.sections.push({
274
+ type: 'explanation',
275
+ title: 'Understanding the Problem',
276
+ content: await this.generateExplanation(caseItem)
277
+ })
278
+
279
+ materials.sections.push({
280
+ type: 'example',
281
+ title: 'Code Example',
282
+ content: await this.generateDetailedExample(caseItem)
283
+ })
284
+
285
+ materials.sections.push({
286
+ type: 'exercise',
287
+ title: 'Practice Exercise',
288
+ content: await this.generateExercise(caseItem)
289
+ })
290
+
291
+ materials.sections.push({
292
+ type: 'related',
293
+ title: 'Related Concepts',
294
+ content: await this.findRelatedConcepts(caseItem)
295
+ })
296
+
297
+ // Save materials
298
+ const materialsPath = path.join(this.knowledgeDir, `${caseId}-materials.md`)
299
+ await fs.writeFile(materialsPath, this.formatMaterialsAsMarkdown(materials))
300
+
301
+ return materials
302
+ }
303
+
304
+ /**
305
+ * Answer questions using natural language
306
+ */
307
+ async query(question, options = {}) {
308
+ console.log(chalk.blue(`Processing query: "${question}"`))
309
+
310
+ const prompt = `
311
+ Knowledge Base Query: ${question}
312
+
313
+ Available Cases: ${this.cases.length}
314
+ Categories: ${Object.keys(this.patterns).join(', ')}
315
+
316
+ Search through the knowledge base and provide a comprehensive answer.
317
+ Include:
318
+ 1. Direct answer to the question
319
+ 2. Relevant cases/examples
320
+ 3. Best practices
321
+ 4. Code snippets when applicable
322
+ 5. Related recommendations
323
+
324
+ Format as a helpful, informative response.
325
+ `
326
+
327
+ try {
328
+ const response = await this.generateWithAI(prompt)
329
+
330
+ // Also perform keyword search
331
+ const keywordResults = this.performKeywordSearch(question)
332
+
333
+ return {
334
+ question,
335
+ answer: response,
336
+ relevantCases: keywordResults.cases,
337
+ confidence: keywordResults.confidence,
338
+ timestamp: new Date().toISOString()
339
+ }
340
+ } catch (error) {
341
+ console.warn(chalk.yellow('AI query failed, using keyword search'))
342
+ return this.performKeywordSearch(question)
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Perform keyword-based search
348
+ */
349
+ performKeywordSearch(query) {
350
+ const keywords = query.toLowerCase().split(/\s+/)
351
+ const scoredCases = []
352
+
353
+ for (const caseItem of this.cases) {
354
+ let score = 0
355
+ const searchableText = [
356
+ caseItem.title,
357
+ caseItem.problem,
358
+ caseItem.solution,
359
+ ...(caseItem.tags || [])
360
+ ].join(' ').toLowerCase()
361
+
362
+ for (const keyword of keywords) {
363
+ if (searchableText.includes(keyword)) {
364
+ score += 1
365
+ }
366
+ }
367
+
368
+ if (score > 0) {
369
+ scoredCases.push({
370
+ ...caseItem,
371
+ relevanceScore: score / keywords.length
372
+ })
373
+ }
374
+ }
375
+
376
+ scoredCases.sort((a, b) => b.relevanceScore - a.relevanceScore)
377
+
378
+ return {
379
+ cases: scoredCases.slice(0, 10),
380
+ confidence: scoredCases.length > 0 ? Math.min(scoredCases[0].relevanceScore, 1.0) : 0.0
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Provide related case recommendations
386
+ */
387
+ async getRecommendations(caseId, limit = 5) {
388
+ const caseItem = this.cases.find(c => c.id === caseId)
389
+ if (!caseItem) {
390
+ return []
391
+ }
392
+
393
+ const recommendations = []
394
+
395
+ for (const otherCase of this.cases) {
396
+ if (otherCase.id === caseId) continue
397
+
398
+ let similarity = 0
399
+
400
+ // Check tag overlap
401
+ const commonTags = (caseItem.tags || []).filter(tag =>
402
+ (otherCase.tags || []).includes(tag)
403
+ )
404
+ similarity += commonTags.length * 0.3
405
+
406
+ // Check category match
407
+ if (caseItem.category === otherCase.category) {
408
+ similarity += 0.4
409
+ }
410
+
411
+ // Check language match
412
+ if (caseItem.language === otherCase.language) {
413
+ similarity += 0.2
414
+ }
415
+
416
+ // Check pattern type match
417
+ const commonPatterns = (caseItem.patternTypes || []).filter(pattern =>
418
+ (otherCase.patternTypes || []).includes(pattern)
419
+ )
420
+ similarity += commonPatterns.length * 0.1
421
+
422
+ if (similarity > 0) {
423
+ recommendations.push({
424
+ ...otherCase,
425
+ similarityScore: similarity,
426
+ commonTags,
427
+ commonPatterns
428
+ })
429
+ }
430
+ }
431
+
432
+ recommendations.sort((a, b) => b.similarityScore - a.similarityScore)
433
+
434
+ return recommendations.slice(0, limit)
435
+ }
436
+
437
+ /**
438
+ * Ensure minimum weekly case quota
439
+ */
440
+ async ensureWeeklyQuota() {
441
+ const oneWeekAgo = new Date()
442
+ oneWeekAgo.setDate(oneWeekAgo.getDate() - 7)
443
+
444
+ const recentCases = this.cases.filter(c =>
445
+ new Date(c.timestamp) > oneWeekAgo
446
+ )
447
+
448
+ this.statistics.weeklyCases = recentCases.length
449
+
450
+ if (recentCases.length < this.config.minCasesPerWeek) {
451
+ console.log(chalk.yellow(`Weekly quota not met. Extracting ${this.config.minCasesPerWeek - recentCases.length} more cases...`))
452
+
453
+ // This would typically trigger additional analysis or extraction
454
+ // For now, we'll mark it in statistics
455
+ this.statistics.quotaStatus = 'needs-attention'
456
+ } else {
457
+ this.statistics.quotaStatus = 'met'
458
+ }
459
+ }
460
+
461
+ /**
462
+ * Update statistics
463
+ */
464
+ updateStatistics() {
465
+ this.statistics.totalCases = this.cases.length
466
+
467
+ const oneWeekAgo = new Date()
468
+ oneWeekAgo.setDate(oneWeekAgo.getDate() - 7)
469
+
470
+ const recentCases = this.cases.filter(c =>
471
+ new Date(c.timestamp) > oneWeekAgo
472
+ )
473
+
474
+ this.statistics.weeklyCases = recentCases.length
475
+
476
+ // Calculate tag accuracy (mock implementation)
477
+ const classifiedCases = this.cases.filter(c => c.classificationConfidence)
478
+ if (classifiedCases.length > 0) {
479
+ const avgConfidence = classifiedCases.reduce((sum, c) =>
480
+ sum + (c.classificationConfidence || 0), 0
481
+ ) / classifiedCases.length
482
+ this.statistics.tagAccuracy = avgConfidence * 100
483
+ }
484
+ }
485
+
486
+ /**
487
+ * Generate with AI (OpenAI or Anthropic)
488
+ */
489
+ async generateWithAI(prompt) {
490
+ // Try OpenAI first
491
+ if (this.openai) {
492
+ try {
493
+ const response = await this.openai.chat.completions.create({
494
+ model: 'gpt-4',
495
+ messages: [{ role: 'user', content: prompt }],
496
+ temperature: 0.7,
497
+ max_tokens: 2000
498
+ })
499
+ return response.choices[0].message.content
500
+ } catch (error) {
501
+ console.warn(chalk.yellow('OpenAI failed, trying Anthropic...'))
502
+ }
503
+ }
504
+
505
+ // Try Anthropic
506
+ if (this.anthropic) {
507
+ try {
508
+ const response = await this.anthropic.messages.create({
509
+ model: 'claude-3-5-sonnet-20241022',
510
+ max_tokens: 2000,
511
+ messages: [{ role: 'user', content: prompt }]
512
+ })
513
+ return response.content[0].text
514
+ } catch (error) {
515
+ console.warn(chalk.yellow('Anthropic failed, using mock mode'))
516
+ }
517
+ }
518
+
519
+ // Mock mode
520
+ return this.generateMockResponse(prompt)
521
+ }
522
+
523
+ /**
524
+ * Generate mock response for testing
525
+ */
526
+ generateMockResponse(prompt) {
527
+ if (prompt.includes('best practice case')) {
528
+ return JSON.stringify({
529
+ title: 'Code Quality Best Practice',
530
+ problem: 'This is a mock problem description',
531
+ whyItMatters: 'Quality matters for maintainability',
532
+ solution: 'Follow best practices and coding standards',
533
+ codeExample: '// Example code here',
534
+ tags: ['best-practice', 'quality'],
535
+ category: 'best-practices',
536
+ language: 'javascript',
537
+ difficulty: 'intermediate',
538
+ relatedPatterns: ['clean-code'],
539
+ preventionTips: ['Use linters', 'Code reviews']
540
+ })
541
+ }
542
+
543
+ if (prompt.includes('enhanced tags')) {
544
+ return JSON.stringify({
545
+ enhancedTags: ['refactoring', 'clean-code'],
546
+ confidence: 0.85,
547
+ patternTypes: ['extract-method', 'rename-variable']
548
+ })
549
+ }
550
+
551
+ return 'This is a mock AI response for testing purposes.'
552
+ }
553
+
554
+ /**
555
+ * Generate explanation for learning materials
556
+ */
557
+ async generateExplanation(caseItem) {
558
+ return `
559
+ ## Understanding ${caseItem.title}
560
+
561
+ ### The Problem
562
+ ${caseItem.problem}
563
+
564
+ ### Why It Matters
565
+ ${caseItem.whyItMatters}
566
+
567
+ ### Impact
568
+ - Affects code maintainability
569
+ - Increases technical debt
570
+ - Makes debugging harder
571
+ - Reduces team productivity
572
+
573
+ ### Best Practices
574
+ ${caseItem.preventionTips.map(tip => `- ${tip}`).join('\n')}
575
+ `.trim()
576
+ }
577
+
578
+ /**
579
+ * Generate detailed example
580
+ */
581
+ async generateDetailedExample(caseItem) {
582
+ return `
583
+ ## Code Example (${caseItem.language})
584
+
585
+ ### Bad Example
586
+ \`\`\`${caseItem.language}
587
+ ${caseItem.codeExample}
588
+ \`\`\`
589
+
590
+ ### Good Example
591
+ \`\`\`${caseItem.language}
592
+ // Refactored code following best practices
593
+ // This demonstrates the solution
594
+ `.trim()
595
+ }
596
+
597
+ /**
598
+ * Generate practice exercise
599
+ */
600
+ async generateExercise(caseItem) {
601
+ return `
602
+ ## Practice Exercise
603
+
604
+ ### Task
605
+ Refactor the following code to address the ${caseItem.title} issue.
606
+
607
+ ### Hints
608
+ - Consider the single responsibility principle
609
+ - Follow naming conventions
610
+ - Keep functions small and focused
611
+
612
+ ### Expected Outcome
613
+ - Improved code quality
614
+ - Better maintainability
615
+ - Clearer intent
616
+ `.trim()
617
+ }
618
+
619
+ /**
620
+ * Find related concepts
621
+ */
622
+ async findRelatedConcepts(caseItem) {
623
+ const related = await this.getRecommendations(caseItem.id, 3)
624
+ return related.map(r => `
625
+ - **${r.title}** (${(r.similarityScore * 100).toFixed(0)}% similar)
626
+ ${r.problem.substring(0, 100)}...
627
+ `).join('\n')
628
+ }
629
+
630
+ /**
631
+ * Format materials as Markdown
632
+ */
633
+ formatMaterialsAsMarkdown(materials) {
634
+ return `# Learning Materials: ${materials.caseId}
635
+
636
+ Generated: ${materials.generatedAt}
637
+
638
+ ${materials.sections.map(section => `
639
+ ## ${section.title}
640
+
641
+ ${section.content}
642
+ `).join('\n')}
643
+ `
644
+ }
645
+
646
+ /**
647
+ * Generate case ID
648
+ */
649
+ generateCaseId() {
650
+ return `KB-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
651
+ }
652
+
653
+ /**
654
+ * Get default solution for issue type
655
+ */
656
+ getDefaultSolution(issueType) {
657
+ const solutions = {
658
+ 'longFunction': 'Extract smaller functions with single responsibilities',
659
+ 'badVariableNames': 'Use descriptive names that explain purpose',
660
+ 'highComplexity': 'Simplify logic and reduce decision points',
661
+ 'duplicateCode': 'Extract to a shared function or constant',
662
+ 'magicNumbers': 'Replace with named constants',
663
+ 'nestedConditionals': 'Use early returns and polymorphism'
664
+ }
665
+ return solutions[issueType] || 'Review and improve code structure'
666
+ }
667
+
668
+ /**
669
+ * Extract tags from issue
670
+ */
671
+ extractTagsFromIssue(issue) {
672
+ const tags = [issue.type, issue.severity]
673
+ if (issue.category) tags.push(issue.category)
674
+ return tags
675
+ }
676
+
677
+ /**
678
+ * Get category from issue
679
+ */
680
+ getCategoryFromIssue(issue) {
681
+ return issue.category || 'general'
682
+ }
683
+
684
+ /**
685
+ * Get statistics
686
+ */
687
+ getStatistics() {
688
+ this.updateStatistics()
689
+ return this.statistics
690
+ }
691
+
692
+ /**
693
+ * Export knowledge base
694
+ */
695
+ async export(format = 'json') {
696
+ const exportData = {
697
+ cases: this.cases,
698
+ patterns: this.patterns,
699
+ statistics: this.getStatistics(),
700
+ exportedAt: new Date().toISOString()
701
+ }
702
+
703
+ if (format === 'json') {
704
+ return JSON.stringify(exportData, null, 2)
705
+ }
706
+
707
+ if (format === 'markdown') {
708
+ return this.exportAsMarkdown(exportData)
709
+ }
710
+
711
+ throw new Error(`Unsupported export format: ${format}`)
712
+ }
713
+
714
+ /**
715
+ * Export as Markdown
716
+ */
717
+ exportAsMarkdown(data) {
718
+ let markdown = `# Knowledge Base Export
719
+
720
+ Generated: ${data.exportedAt}
721
+ Total Cases: ${data.statistics.totalCases}
722
+ Weekly Cases: ${data.statistics.weeklyCases}
723
+
724
+ ## Cases
725
+
726
+ `
727
+
728
+ for (const caseItem of data.cases) {
729
+ markdown += `
730
+ ### ${caseItem.title}
731
+
732
+ **Category:** ${caseItem.category}
733
+ **Language:** ${caseItem.language}
734
+ **Difficulty:** ${caseItem.difficulty}
735
+ **Tags:** ${caseItem.tags.join(', ')}
736
+
737
+ #### Problem
738
+ ${caseItem.problem}
739
+
740
+ #### Solution
741
+ ${caseItem.solution}
742
+
743
+ #### Code Example
744
+ \`\`\`${caseItem.language}
745
+ ${caseItem.codeExample}
746
+ \`\`\`
747
+
748
+ ---
749
+
750
+ `
751
+ }
752
+
753
+ return markdown
754
+ }
755
+ }
756
+
757
+ module.exports = AIKnowledgeBase