@goldensheepai/toknxr-cli 0.3.0 ā 0.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.
- package/lib/cli.js +182 -23
- package/lib/commands/hallucination-commands.js +453 -0
- package/lib/enhanced-hallucination-detector.js +622 -0
- package/lib/execution-based-detector.js +538 -0
- package/lib/execution-sandbox.js +602 -0
- package/lib/hallucination-database-service.js +447 -0
- package/lib/hallucination-patterns.js +490 -0
- package/lib/types/database-types.js +5 -0
- package/lib/types/hallucination-types.js +74 -0
- package/lib/types/index.js +8 -0
- package/lib/ui.js +73 -6
- package/package.json +1 -1
- package/lib/auth.js +0 -73
- package/lib/cli.test.js +0 -49
- package/lib/code-review.js +0 -319
- package/lib/config.js +0 -7
- package/lib/sync.js +0 -117
@@ -0,0 +1,453 @@
|
|
1
|
+
/**
|
2
|
+
* CLI Commands for Enhanced Hallucination Detection
|
3
|
+
*/
|
4
|
+
import chalk from 'chalk';
|
5
|
+
import inquirer from 'inquirer';
|
6
|
+
import { createCodeHaluDetector } from '../enhanced-hallucination-detector.js';
|
7
|
+
import { detectAllPatterns, getPatternStatistics } from '../hallucination-patterns.js';
|
8
|
+
import { analyzeExecutionForHallucinations } from '../execution-based-detector.js';
|
9
|
+
/**
|
10
|
+
* Detailed hallucination analysis command
|
11
|
+
*/
|
12
|
+
export async function hallucinationsDetailedCommand(options) {
|
13
|
+
console.log(chalk.bold.blue('š§ Enhanced Hallucination Analysis (CodeHalu)'));
|
14
|
+
console.log(chalk.gray('ā'.repeat(60)));
|
15
|
+
let code;
|
16
|
+
let language = options.language || 'python';
|
17
|
+
// Get code input
|
18
|
+
if (options.file) {
|
19
|
+
try {
|
20
|
+
const fs = await import('fs');
|
21
|
+
code = fs.readFileSync(options.file, 'utf8');
|
22
|
+
console.log(chalk.green(`š Loaded code from: ${options.file}`));
|
23
|
+
}
|
24
|
+
catch (error) {
|
25
|
+
console.error(chalk.red(`ā Failed to read file: ${options.file}`));
|
26
|
+
return;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
else if (options.code) {
|
30
|
+
code = options.code;
|
31
|
+
}
|
32
|
+
else {
|
33
|
+
// Interactive code input
|
34
|
+
const { inputMethod } = await inquirer.prompt([
|
35
|
+
{
|
36
|
+
type: 'list',
|
37
|
+
name: 'inputMethod',
|
38
|
+
message: 'How would you like to provide the code?',
|
39
|
+
choices: [
|
40
|
+
{ name: 'š Enter code directly', value: 'direct' },
|
41
|
+
{ name: 'š Load from file', value: 'file' },
|
42
|
+
{ name: 'š Analyze from recent interactions', value: 'recent' },
|
43
|
+
],
|
44
|
+
},
|
45
|
+
]);
|
46
|
+
if (inputMethod === 'direct') {
|
47
|
+
const { inputCode } = await inquirer.prompt([
|
48
|
+
{
|
49
|
+
type: 'editor',
|
50
|
+
name: 'inputCode',
|
51
|
+
message: 'Enter the code to analyze:',
|
52
|
+
validate: (input) => input.trim().length > 0 || 'Code cannot be empty',
|
53
|
+
},
|
54
|
+
]);
|
55
|
+
code = inputCode;
|
56
|
+
}
|
57
|
+
else if (inputMethod === 'file') {
|
58
|
+
const { filePath } = await inquirer.prompt([
|
59
|
+
{
|
60
|
+
type: 'input',
|
61
|
+
name: 'filePath',
|
62
|
+
message: 'Enter the file path:',
|
63
|
+
validate: (input) => input.trim().length > 0 || 'File path cannot be empty',
|
64
|
+
},
|
65
|
+
]);
|
66
|
+
try {
|
67
|
+
const fs = await import('fs');
|
68
|
+
code = fs.readFileSync(filePath, 'utf8');
|
69
|
+
console.log(chalk.green(`š Loaded code from: ${filePath}`));
|
70
|
+
}
|
71
|
+
catch (error) {
|
72
|
+
console.error(chalk.red(`ā Failed to read file: ${filePath}`));
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
console.log(chalk.yellow('š Recent interactions analysis not yet implemented'));
|
78
|
+
return;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
// Language detection/confirmation
|
82
|
+
if (!options.language) {
|
83
|
+
const { detectedLanguage } = await inquirer.prompt([
|
84
|
+
{
|
85
|
+
type: 'list',
|
86
|
+
name: 'detectedLanguage',
|
87
|
+
message: 'Select the programming language:',
|
88
|
+
choices: [
|
89
|
+
{ name: 'š Python', value: 'python' },
|
90
|
+
{ name: 'š JavaScript', value: 'javascript' },
|
91
|
+
{ name: 'š· TypeScript', value: 'typescript' },
|
92
|
+
{ name: 'ā Java', value: 'java' },
|
93
|
+
{ name: 'š§ Other', value: 'other' },
|
94
|
+
],
|
95
|
+
default: 'python',
|
96
|
+
},
|
97
|
+
]);
|
98
|
+
language = detectedLanguage;
|
99
|
+
}
|
100
|
+
console.log(chalk.cyan(`\nš Analyzing ${language} code (${code.length} characters)...`));
|
101
|
+
try {
|
102
|
+
// Create detector with appropriate configuration
|
103
|
+
const detector = createCodeHaluDetector({
|
104
|
+
enableExecutionAnalysis: options.enableExecution !== false,
|
105
|
+
enableStaticAnalysis: true,
|
106
|
+
enablePatternMatching: true,
|
107
|
+
confidenceThreshold: 0.6,
|
108
|
+
maxExecutionTime: 10000,
|
109
|
+
});
|
110
|
+
// Perform analysis
|
111
|
+
const startTime = Date.now();
|
112
|
+
const result = await detector.detectHallucinations(code, language);
|
113
|
+
const analysisTime = Date.now() - startTime;
|
114
|
+
// Display results
|
115
|
+
console.log(chalk.bold('\nš Analysis Results'));
|
116
|
+
console.log(chalk.gray('ā'.repeat(40)));
|
117
|
+
// Overall metrics
|
118
|
+
const rateColor = result.overallHallucinationRate > 0.7 ? chalk.red :
|
119
|
+
result.overallHallucinationRate > 0.4 ? chalk.yellow : chalk.green;
|
120
|
+
console.log(`šÆ Overall Hallucination Rate: ${rateColor(`${(result.overallHallucinationRate * 100).toFixed(1)}%`)}`);
|
121
|
+
console.log(`ā±ļø Analysis Time: ${analysisTime}ms`);
|
122
|
+
console.log(`š¬ Detection Methods: ${result.analysisMetadata.detectionMethods.join(', ')}`);
|
123
|
+
console.log(`š Code Length: ${result.analysisMetadata.codeLength} characters`);
|
124
|
+
// Categories breakdown
|
125
|
+
if (result.categories.length > 0) {
|
126
|
+
console.log(chalk.bold('\nš·ļø Detected Issues by Category'));
|
127
|
+
console.log(chalk.gray('ā'.repeat(40)));
|
128
|
+
const categoryGroups = result.categories.reduce((groups, category) => {
|
129
|
+
if (!groups[category.type])
|
130
|
+
groups[category.type] = [];
|
131
|
+
groups[category.type].push(category);
|
132
|
+
return groups;
|
133
|
+
}, {});
|
134
|
+
Object.entries(categoryGroups).forEach(([type, categories]) => {
|
135
|
+
const typeIcon = {
|
136
|
+
mapping: 'šŗļø',
|
137
|
+
naming: 'š·ļø',
|
138
|
+
resource: 'ā”',
|
139
|
+
logic: 'š§ ',
|
140
|
+
}[type] || 'ā';
|
141
|
+
console.log(`\n${typeIcon} ${type.toUpperCase()} Issues (${categories.length}):`);
|
142
|
+
categories.forEach((category, index) => {
|
143
|
+
const severityColor = {
|
144
|
+
low: chalk.blue,
|
145
|
+
medium: chalk.yellow,
|
146
|
+
high: chalk.red,
|
147
|
+
critical: chalk.magenta,
|
148
|
+
}[category.severity];
|
149
|
+
console.log(` ${index + 1}. ${severityColor(category.severity.toUpperCase())} - ${category.description}`);
|
150
|
+
console.log(` Confidence: ${(category.confidence * 100).toFixed(1)}%`);
|
151
|
+
console.log(` Impact: ${category.businessImpact.estimatedDevTimeWasted.toFixed(1)}h dev time`);
|
152
|
+
if (category.lineNumbers && category.lineNumbers.length > 0) {
|
153
|
+
console.log(` Lines: ${category.lineNumbers.join(', ')}`);
|
154
|
+
}
|
155
|
+
if (category.suggestedFix) {
|
156
|
+
console.log(` Fix: ${chalk.cyan(category.suggestedFix)}`);
|
157
|
+
}
|
158
|
+
});
|
159
|
+
});
|
160
|
+
}
|
161
|
+
else {
|
162
|
+
console.log(chalk.green('\nā
No significant hallucinations detected!'));
|
163
|
+
}
|
164
|
+
// Execution results
|
165
|
+
if (result.executionResult) {
|
166
|
+
console.log(chalk.bold('\nā” Execution Analysis'));
|
167
|
+
console.log(chalk.gray('ā'.repeat(40)));
|
168
|
+
const execResult = result.executionResult;
|
169
|
+
console.log(`Status: ${execResult.success ? chalk.green('ā
Success') : chalk.red('ā Failed')}`);
|
170
|
+
console.log(`Memory Usage: ${execResult.resourceUsage.memoryMB.toFixed(2)}MB`);
|
171
|
+
console.log(`Execution Time: ${execResult.resourceUsage.executionTimeMs}ms`);
|
172
|
+
console.log(`Timed Out: ${execResult.timedOut ? chalk.red('Yes') : chalk.green('No')}`);
|
173
|
+
if (execResult.errors.length > 0) {
|
174
|
+
console.log(chalk.red('\nExecution Errors:'));
|
175
|
+
execResult.errors.forEach((error, index) => {
|
176
|
+
console.log(` ${index + 1}. ${error.type}: ${error.message}`);
|
177
|
+
});
|
178
|
+
}
|
179
|
+
if (execResult.output) {
|
180
|
+
console.log(chalk.blue('\nOutput:'));
|
181
|
+
console.log(chalk.gray(execResult.output.substring(0, 200) +
|
182
|
+
(execResult.output.length > 200 ? '...' : '')));
|
183
|
+
}
|
184
|
+
}
|
185
|
+
// Business impact
|
186
|
+
console.log(chalk.bold('\nš¼ Business Impact'));
|
187
|
+
console.log(chalk.gray('ā'.repeat(40)));
|
188
|
+
console.log(`Estimated Dev Time Wasted: ${chalk.yellow(`${result.businessImpact.estimatedDevTimeWasted.toFixed(1)} hours`)}`);
|
189
|
+
console.log(`Cost of Hallucinations: ${chalk.red(`$${result.businessImpact.costOfHallucinations.toFixed(2)}`)}`);
|
190
|
+
console.log(`Quality Impact: ${result.businessImpact.qualityImpact}/100`);
|
191
|
+
console.log(`Cost Multiplier: ${result.businessImpact.costMultiplier.toFixed(1)}x`);
|
192
|
+
// Recommendations
|
193
|
+
if (result.recommendations.length > 0) {
|
194
|
+
console.log(chalk.bold('\nš” Recommendations'));
|
195
|
+
console.log(chalk.gray('ā'.repeat(40)));
|
196
|
+
result.recommendations.forEach((rec, index) => {
|
197
|
+
const priorityColor = rec.priority === 'high' ? chalk.red :
|
198
|
+
rec.priority === 'medium' ? chalk.yellow : chalk.blue;
|
199
|
+
console.log(`\n${index + 1}. ${priorityColor(rec.priority.toUpperCase())} - ${rec.title}`);
|
200
|
+
console.log(` ${rec.description}`);
|
201
|
+
console.log(` Expected Impact: ${rec.expectedImpact}`);
|
202
|
+
console.log(` Estimated Time: ${rec.estimatedTimeToFix || 'Unknown'}`);
|
203
|
+
if (rec.actionItems.length > 0) {
|
204
|
+
console.log(` Action Items:`);
|
205
|
+
rec.actionItems.forEach(item => {
|
206
|
+
console.log(` ⢠${item}`);
|
207
|
+
});
|
208
|
+
}
|
209
|
+
});
|
210
|
+
}
|
211
|
+
// Pattern statistics (if available)
|
212
|
+
if (result.analysisMetadata.patternStats) {
|
213
|
+
const stats = result.analysisMetadata.patternStats;
|
214
|
+
console.log(chalk.bold('\nš Pattern Statistics'));
|
215
|
+
console.log(chalk.gray('ā'.repeat(40)));
|
216
|
+
console.log(`Total Patterns: ${stats.totalPatterns}`);
|
217
|
+
console.log(`Average Confidence: ${(stats.avgConfidence * 100).toFixed(1)}%`);
|
218
|
+
if (Object.keys(stats.byCategory).length > 0) {
|
219
|
+
console.log('By Category:');
|
220
|
+
Object.entries(stats.byCategory).forEach(([category, count]) => {
|
221
|
+
console.log(` ${category}: ${count}`);
|
222
|
+
});
|
223
|
+
}
|
224
|
+
if (Object.keys(stats.bySeverity).length > 0) {
|
225
|
+
console.log('By Severity:');
|
226
|
+
Object.entries(stats.bySeverity).forEach(([severity, count]) => {
|
227
|
+
console.log(` ${severity}: ${count}`);
|
228
|
+
});
|
229
|
+
}
|
230
|
+
}
|
231
|
+
// Export option
|
232
|
+
if (options.output) {
|
233
|
+
try {
|
234
|
+
const fs = await import('fs');
|
235
|
+
const exportData = {
|
236
|
+
timestamp: new Date().toISOString(),
|
237
|
+
code: code.substring(0, 1000) + (code.length > 1000 ? '...' : ''),
|
238
|
+
language,
|
239
|
+
analysisTime,
|
240
|
+
result,
|
241
|
+
};
|
242
|
+
fs.writeFileSync(options.output, JSON.stringify(exportData, null, 2));
|
243
|
+
console.log(chalk.green(`\nš¾ Results exported to: ${options.output}`));
|
244
|
+
}
|
245
|
+
catch (error) {
|
246
|
+
console.error(chalk.red(`ā Failed to export results: ${error}`));
|
247
|
+
}
|
248
|
+
}
|
249
|
+
// Interactive follow-up
|
250
|
+
console.log(chalk.blue('\nš What would you like to do next?'));
|
251
|
+
const { nextAction } = await inquirer.prompt([
|
252
|
+
{
|
253
|
+
type: 'list',
|
254
|
+
name: 'nextAction',
|
255
|
+
message: 'Choose an action:',
|
256
|
+
choices: [
|
257
|
+
{ name: 'š Analyze different code', value: 'analyze_new' },
|
258
|
+
{ name: 'š View pattern details', value: 'pattern_details' },
|
259
|
+
{ name: 'ā” Run execution analysis only', value: 'execution_only' },
|
260
|
+
{ name: 'š¾ Export detailed report', value: 'export' },
|
261
|
+
{ name: 'ā Exit', value: 'exit' },
|
262
|
+
],
|
263
|
+
},
|
264
|
+
]);
|
265
|
+
switch (nextAction) {
|
266
|
+
case 'analyze_new':
|
267
|
+
console.log(chalk.cyan('š Run the command again with new code'));
|
268
|
+
break;
|
269
|
+
case 'pattern_details':
|
270
|
+
await showPatternDetails(code);
|
271
|
+
break;
|
272
|
+
case 'execution_only':
|
273
|
+
await showExecutionAnalysis(code, language);
|
274
|
+
break;
|
275
|
+
case 'export':
|
276
|
+
await exportDetailedReport(result, code, language);
|
277
|
+
break;
|
278
|
+
case 'exit':
|
279
|
+
console.log(chalk.gray('š Analysis complete!'));
|
280
|
+
break;
|
281
|
+
}
|
282
|
+
}
|
283
|
+
catch (error) {
|
284
|
+
console.error(chalk.red('ā Analysis failed:'), error);
|
285
|
+
console.log(chalk.yellow('\nš” Troubleshooting tips:'));
|
286
|
+
console.log(' ⢠Check that the code is valid and complete');
|
287
|
+
console.log(' ⢠Ensure Python is installed for execution analysis');
|
288
|
+
console.log(' ⢠Try disabling execution analysis with --no-execution');
|
289
|
+
}
|
290
|
+
}
|
291
|
+
/**
|
292
|
+
* Code quality report command
|
293
|
+
*/
|
294
|
+
export async function codeQualityReportCommand(options) {
|
295
|
+
console.log(chalk.bold.blue('š Comprehensive Code Quality Report'));
|
296
|
+
console.log(chalk.gray('ā'.repeat(60)));
|
297
|
+
// This would integrate with the existing interaction log
|
298
|
+
const path = await import('path');
|
299
|
+
const fs = await import('fs');
|
300
|
+
const logFilePath = path.resolve(process.cwd(), 'interactions.log');
|
301
|
+
if (!fs.existsSync(logFilePath)) {
|
302
|
+
console.log(chalk.yellow('No interactions logged yet. Start tracking with: ') +
|
303
|
+
chalk.cyan('toknxr start'));
|
304
|
+
return;
|
305
|
+
}
|
306
|
+
console.log(chalk.cyan('š Generating comprehensive quality report...'));
|
307
|
+
// Load interactions and analyze for hallucinations
|
308
|
+
const fileContent = fs.readFileSync(logFilePath, 'utf8');
|
309
|
+
const lines = fileContent.trim().split('\\n');
|
310
|
+
let codingInteractions = 0;
|
311
|
+
let totalHallucinationRate = 0;
|
312
|
+
let criticalIssues = 0;
|
313
|
+
console.log(chalk.green(`ā
Analyzed ${lines.length} interactions`));
|
314
|
+
console.log(chalk.blue(`š Found ${codingInteractions} coding interactions`));
|
315
|
+
if (codingInteractions > 0) {
|
316
|
+
const avgHallucinationRate = totalHallucinationRate / codingInteractions;
|
317
|
+
console.log(chalk.yellow(`š§ Average Hallucination Rate: ${(avgHallucinationRate * 100).toFixed(1)}%`));
|
318
|
+
console.log(chalk.red(`ā ļø Critical Issues: ${criticalIssues}`));
|
319
|
+
}
|
320
|
+
// Generate report based on format
|
321
|
+
const format = options.format || 'json';
|
322
|
+
const outputPath = options.output || `code-quality-report.${format}`;
|
323
|
+
const report = {
|
324
|
+
timestamp: new Date().toISOString(),
|
325
|
+
summary: {
|
326
|
+
totalInteractions: lines.length,
|
327
|
+
codingInteractions,
|
328
|
+
avgHallucinationRate: codingInteractions > 0 ? totalHallucinationRate / codingInteractions : 0,
|
329
|
+
criticalIssues,
|
330
|
+
},
|
331
|
+
// Additional report data would be added here
|
332
|
+
};
|
333
|
+
try {
|
334
|
+
if (format === 'json') {
|
335
|
+
fs.writeFileSync(outputPath, JSON.stringify(report, null, 2));
|
336
|
+
}
|
337
|
+
else if (format === 'html') {
|
338
|
+
const htmlReport = generateHtmlReport(report);
|
339
|
+
fs.writeFileSync(outputPath, htmlReport);
|
340
|
+
}
|
341
|
+
else {
|
342
|
+
console.error(chalk.red(`ā Unsupported format: ${format}`));
|
343
|
+
return;
|
344
|
+
}
|
345
|
+
console.log(chalk.green(`ā
Report generated: ${outputPath}`));
|
346
|
+
}
|
347
|
+
catch (error) {
|
348
|
+
console.error(chalk.red('ā Failed to generate report:'), error);
|
349
|
+
}
|
350
|
+
}
|
351
|
+
/**
|
352
|
+
* Helper functions
|
353
|
+
*/
|
354
|
+
async function showPatternDetails(code) {
|
355
|
+
console.log(chalk.bold('\nš Pattern Detection Details'));
|
356
|
+
console.log(chalk.gray('ā'.repeat(40)));
|
357
|
+
const patterns = detectAllPatterns(code);
|
358
|
+
const stats = getPatternStatistics(patterns);
|
359
|
+
console.log(`Total Patterns Detected: ${stats.totalPatterns}`);
|
360
|
+
console.log(`Average Confidence: ${(stats.avgConfidence * 100).toFixed(1)}%`);
|
361
|
+
patterns.forEach((pattern, index) => {
|
362
|
+
console.log(`\n${index + 1}. ${pattern.pattern} (${pattern.category})`);
|
363
|
+
console.log(` Severity: ${pattern.severity}`);
|
364
|
+
console.log(` Confidence: ${(pattern.confidence * 100).toFixed(1)}%`);
|
365
|
+
console.log(` Lines: ${pattern.lineNumbers.join(', ')}`);
|
366
|
+
if (pattern.evidence.length > 0) {
|
367
|
+
console.log(` Evidence:`);
|
368
|
+
pattern.evidence.forEach(evidence => {
|
369
|
+
console.log(` ⢠${evidence.content}`);
|
370
|
+
});
|
371
|
+
}
|
372
|
+
});
|
373
|
+
}
|
374
|
+
async function showExecutionAnalysis(code, language) {
|
375
|
+
console.log(chalk.bold('\nā” Execution-Only Analysis'));
|
376
|
+
console.log(chalk.gray('ā'.repeat(40)));
|
377
|
+
try {
|
378
|
+
const analysis = await analyzeExecutionForHallucinations(code);
|
379
|
+
console.log(`Execution Success: ${analysis.executionResult.success ? 'ā
' : 'ā'}`);
|
380
|
+
console.log(`Memory Usage: ${analysis.executionResult.resourceUsage.memoryMB.toFixed(2)}MB`);
|
381
|
+
console.log(`Execution Time: ${analysis.executionResult.resourceUsage.executionTimeMs}ms`);
|
382
|
+
console.log(`\nResource Hallucinations: ${analysis.resourceHallucinations.length}`);
|
383
|
+
console.log(`Logic Hallucinations: ${analysis.logicHallucinations.length}`);
|
384
|
+
[...analysis.resourceHallucinations, ...analysis.logicHallucinations].forEach((category, index) => {
|
385
|
+
console.log(`\n${index + 1}. ${category.type}/${category.subtype}`);
|
386
|
+
console.log(` ${category.description}`);
|
387
|
+
console.log(` Severity: ${category.severity}`);
|
388
|
+
});
|
389
|
+
}
|
390
|
+
catch (error) {
|
391
|
+
console.error(chalk.red('ā Execution analysis failed:'), error);
|
392
|
+
}
|
393
|
+
}
|
394
|
+
async function exportDetailedReport(result, code, language) {
|
395
|
+
const { outputPath } = await inquirer.prompt([
|
396
|
+
{
|
397
|
+
type: 'input',
|
398
|
+
name: 'outputPath',
|
399
|
+
message: 'Enter output file path:',
|
400
|
+
default: `hallucination-report-${Date.now()}.json`,
|
401
|
+
},
|
402
|
+
]);
|
403
|
+
const report = {
|
404
|
+
timestamp: new Date().toISOString(),
|
405
|
+
metadata: {
|
406
|
+
codeLength: code.length,
|
407
|
+
language,
|
408
|
+
analysisVersion: '1.0.0',
|
409
|
+
},
|
410
|
+
code: code.substring(0, 2000) + (code.length > 2000 ? '...' : ''),
|
411
|
+
analysis: result,
|
412
|
+
};
|
413
|
+
try {
|
414
|
+
const fs = await import('fs');
|
415
|
+
fs.writeFileSync(outputPath, JSON.stringify(report, null, 2));
|
416
|
+
console.log(chalk.green(`ā
Detailed report exported to: ${outputPath}`));
|
417
|
+
}
|
418
|
+
catch (error) {
|
419
|
+
console.error(chalk.red('ā Export failed:'), error);
|
420
|
+
}
|
421
|
+
}
|
422
|
+
function generateHtmlReport(report) {
|
423
|
+
return `
|
424
|
+
<!DOCTYPE html>
|
425
|
+
<html>
|
426
|
+
<head>
|
427
|
+
<title>Code Quality Report</title>
|
428
|
+
<style>
|
429
|
+
body { font-family: Arial, sans-serif; margin: 20px; }
|
430
|
+
.header { background: #f0f0f0; padding: 20px; border-radius: 5px; }
|
431
|
+
.metric { margin: 10px 0; }
|
432
|
+
.critical { color: #d32f2f; }
|
433
|
+
.warning { color: #f57c00; }
|
434
|
+
.success { color: #388e3c; }
|
435
|
+
</style>
|
436
|
+
</head>
|
437
|
+
<body>
|
438
|
+
<div class="header">
|
439
|
+
<h1>Code Quality Report</h1>
|
440
|
+
<p>Generated: ${report.timestamp}</p>
|
441
|
+
</div>
|
442
|
+
|
443
|
+
<h2>Summary</h2>
|
444
|
+
<div class="metric">Total Interactions: ${report.summary.totalInteractions}</div>
|
445
|
+
<div class="metric">Coding Interactions: ${report.summary.codingInteractions}</div>
|
446
|
+
<div class="metric">Average Hallucination Rate: ${(report.summary.avgHallucinationRate * 100).toFixed(1)}%</div>
|
447
|
+
<div class="metric">Critical Issues: <span class="critical">${report.summary.criticalIssues}</span></div>
|
448
|
+
|
449
|
+
<!-- Additional report sections would be added here -->
|
450
|
+
</body>
|
451
|
+
</html>
|
452
|
+
`;
|
453
|
+
}
|