@goldensheepai/toknxr-cli 0.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.
- package/.env +21 -0
- package/.env.example +21 -0
- package/README.md +238 -0
- package/interactions.log +8 -0
- package/lib/ai-analytics.js +296 -0
- package/lib/auth.js +73 -0
- package/lib/cli.js +382 -0
- package/lib/code-analysis.js +304 -0
- package/lib/code-review.js +319 -0
- package/lib/config.js +7 -0
- package/lib/dashboard.js +363 -0
- package/lib/hallucination-detector.js +272 -0
- package/lib/policy.js +49 -0
- package/lib/pricing.js +20 -0
- package/lib/proxy.js +359 -0
- package/lib/sync.js +95 -0
- package/package.json +38 -0
- package/src/ai-analytics.ts +418 -0
- package/src/auth.ts +80 -0
- package/src/cli.ts +447 -0
- package/src/code-analysis.ts +365 -0
- package/src/config.ts +10 -0
- package/src/dashboard.tsx +391 -0
- package/src/hallucination-detector.ts +368 -0
- package/src/policy.ts +55 -0
- package/src/pricing.ts +21 -0
- package/src/proxy.ts +438 -0
- package/src/sync.ts +129 -0
- package/start.sh +56 -0
- package/test-analysis.mjs +77 -0
- package/test-coding.mjs +27 -0
- package/test-generate-sample-data.js +118 -0
- package/test-proxy.mjs +25 -0
- package/toknxr.config.json +63 -0
- package/toknxr.policy.json +18 -0
- package/tsconfig.json +19 -0
@@ -0,0 +1,319 @@
|
|
1
|
+
import fs from 'fs';
|
2
|
+
import path from 'path';
|
3
|
+
import chalk from 'chalk';
|
4
|
+
// Comprehensive code review rules for AI-generated code
|
5
|
+
export const DEFAULT_CODE_REVIEW_RULES = [
|
6
|
+
// Security Issues
|
7
|
+
{
|
8
|
+
id: 'SEC001',
|
9
|
+
name: 'Hardcoded Secrets',
|
10
|
+
description: 'Detects hardcoded API keys, passwords, or tokens',
|
11
|
+
severity: 'error',
|
12
|
+
category: 'security',
|
13
|
+
pattern: /(api[_-]?key|password|secret|token)\s*[=:]?\s*["'][^"']{8,}["']/gi,
|
14
|
+
message: 'Potential hardcoded secret detected',
|
15
|
+
suggestion: 'Use environment variables or secure secret management'
|
16
|
+
},
|
17
|
+
{
|
18
|
+
id: 'SEC002',
|
19
|
+
name: 'SQL Injection Risk',
|
20
|
+
description: 'Detects unsafe string concatenation in SQL queries',
|
21
|
+
severity: 'error',
|
22
|
+
category: 'security',
|
23
|
+
pattern: /(SELECT|INSERT|UPDATE|DELETE).*\+.*["'][^"']*["']/gi,
|
24
|
+
message: 'Potential SQL injection vulnerability',
|
25
|
+
suggestion: 'Use parameterized queries or prepared statements'
|
26
|
+
},
|
27
|
+
{
|
28
|
+
id: 'SEC003',
|
29
|
+
name: 'Insecure Random',
|
30
|
+
description: 'Detects use of Math.random() for security-sensitive operations',
|
31
|
+
severity: 'warning',
|
32
|
+
category: 'security',
|
33
|
+
pattern: /Math\.random\(\)/g,
|
34
|
+
message: 'Math.random() is not cryptographically secure',
|
35
|
+
suggestion: 'Use crypto.randomBytes() or crypto.getRandomValues() for security-sensitive operations'
|
36
|
+
},
|
37
|
+
// Performance Issues
|
38
|
+
{
|
39
|
+
id: 'PERF001',
|
40
|
+
name: 'Inefficient Loop',
|
41
|
+
description: 'Detects potential infinite or inefficient loops',
|
42
|
+
severity: 'warning',
|
43
|
+
category: 'performance',
|
44
|
+
pattern: /for\s*\(\s*let\s+\w+\s*=\s*0\s*;\s*\w+\s*<\s*\w+\.length\s*;\s*\w+\+\+\s*\)\s*{[^}]*\w+\[\w+\]/g,
|
45
|
+
message: 'Potential inefficient array iteration',
|
46
|
+
suggestion: 'Consider using modern array methods like forEach, map, or for...of'
|
47
|
+
},
|
48
|
+
{
|
49
|
+
id: 'PERF002',
|
50
|
+
name: 'Large DOM Manipulation',
|
51
|
+
description: 'Detects multiple DOM manipulations that could be batched',
|
52
|
+
severity: 'info',
|
53
|
+
category: 'performance',
|
54
|
+
pattern: /(document\.createElement|appendChild|innerHTML\s*=)[^;]+;[^;]*\1/gi,
|
55
|
+
message: 'Multiple DOM manipulations detected',
|
56
|
+
suggestion: 'Consider batching DOM operations or using DocumentFragment'
|
57
|
+
},
|
58
|
+
// Maintainability Issues
|
59
|
+
{
|
60
|
+
id: 'MAINT001',
|
61
|
+
name: 'Long Function',
|
62
|
+
description: 'Detects functions that are too long and should be broken up',
|
63
|
+
severity: 'warning',
|
64
|
+
category: 'maintainability',
|
65
|
+
pattern: /^(?:function|\w+\s*=>|\w+\s*\([^)]*\)\s*{[^}]*{[^}]*}[^}]*})/gm,
|
66
|
+
message: 'Function appears to be too long',
|
67
|
+
suggestion: 'Consider breaking this function into smaller, more focused functions'
|
68
|
+
},
|
69
|
+
{
|
70
|
+
id: 'MAINT002',
|
71
|
+
name: 'Missing Error Handling',
|
72
|
+
description: 'Detects operations that might throw errors without proper handling',
|
73
|
+
severity: 'warning',
|
74
|
+
category: 'maintainability',
|
75
|
+
pattern: /(fetch|axios|XMLHttpRequest)\s*\([^)]+\)\s*(?![^}]*catch|\.catch)/gi,
|
76
|
+
message: 'Async operation without error handling',
|
77
|
+
suggestion: 'Add try-catch blocks or .catch() handlers for async operations'
|
78
|
+
},
|
79
|
+
{
|
80
|
+
id: 'MAINT003',
|
81
|
+
name: 'Magic Numbers',
|
82
|
+
description: 'Detects hardcoded numeric values that should be constants',
|
83
|
+
severity: 'info',
|
84
|
+
category: 'maintainability',
|
85
|
+
pattern: /\b\d{2,}\b/g,
|
86
|
+
message: 'Magic number detected',
|
87
|
+
suggestion: 'Consider defining this as a named constant for better readability'
|
88
|
+
},
|
89
|
+
// Reliability Issues
|
90
|
+
{
|
91
|
+
id: 'REL001',
|
92
|
+
name: 'Unsafe Type Coercion',
|
93
|
+
description: 'Detects potentially unsafe type conversions',
|
94
|
+
severity: 'warning',
|
95
|
+
category: 'reliability',
|
96
|
+
pattern: /(==|!=)\s*null/gi,
|
97
|
+
message: 'Loose equality comparison with null',
|
98
|
+
suggestion: 'Use strict equality (===) or explicitly check for null/undefined'
|
99
|
+
},
|
100
|
+
{
|
101
|
+
id: 'REL002',
|
102
|
+
name: 'Resource Leaks',
|
103
|
+
description: 'Detects potential resource leaks',
|
104
|
+
severity: 'warning',
|
105
|
+
category: 'reliability',
|
106
|
+
pattern: /(addEventListener|setTimeout|setInterval)\s*\([^)]+\)\s*(?![^}]*removeEventListener|\.clear)/gi,
|
107
|
+
message: 'Event listener or timer without cleanup',
|
108
|
+
suggestion: 'Ensure proper cleanup of event listeners and timers'
|
109
|
+
}
|
110
|
+
];
|
111
|
+
export class CodeReviewer {
|
112
|
+
rules;
|
113
|
+
constructor(customRules = []) {
|
114
|
+
this.rules = [...DEFAULT_CODE_REVIEW_RULES, ...customRules];
|
115
|
+
}
|
116
|
+
async reviewFile(filePath) {
|
117
|
+
try {
|
118
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
119
|
+
const lines = content.split('\n');
|
120
|
+
const results = [];
|
121
|
+
let errors = 0;
|
122
|
+
let warnings = 0;
|
123
|
+
let info = 0;
|
124
|
+
lines.forEach((line, index) => {
|
125
|
+
this.rules.forEach(rule => {
|
126
|
+
const matches = line.match(rule.pattern);
|
127
|
+
if (matches) {
|
128
|
+
matches.forEach(match => {
|
129
|
+
const result = {
|
130
|
+
rule,
|
131
|
+
line: index + 1,
|
132
|
+
context: line.trim(),
|
133
|
+
severity: rule.severity,
|
134
|
+
message: rule.message,
|
135
|
+
suggestion: rule.suggestion
|
136
|
+
};
|
137
|
+
results.push(result);
|
138
|
+
switch (rule.severity) {
|
139
|
+
case 'error':
|
140
|
+
errors++;
|
141
|
+
break;
|
142
|
+
case 'warning':
|
143
|
+
warnings++;
|
144
|
+
break;
|
145
|
+
case 'info':
|
146
|
+
info++;
|
147
|
+
break;
|
148
|
+
}
|
149
|
+
});
|
150
|
+
}
|
151
|
+
});
|
152
|
+
});
|
153
|
+
const totalIssues = results.length;
|
154
|
+
const summary = this.generateSummary(totalIssues, errors, warnings, info);
|
155
|
+
const recommendations = this.generateRecommendations(results);
|
156
|
+
return {
|
157
|
+
filePath,
|
158
|
+
totalIssues,
|
159
|
+
errors,
|
160
|
+
warnings,
|
161
|
+
info,
|
162
|
+
results,
|
163
|
+
summary,
|
164
|
+
recommendations
|
165
|
+
};
|
166
|
+
}
|
167
|
+
catch (error) {
|
168
|
+
throw new Error(`Failed to review file ${filePath}: ${error}`);
|
169
|
+
}
|
170
|
+
}
|
171
|
+
async reviewDirectory(dirPath) {
|
172
|
+
const reports = [];
|
173
|
+
const files = this.getCodeFiles(dirPath);
|
174
|
+
for (const file of files) {
|
175
|
+
try {
|
176
|
+
const report = await this.reviewFile(file);
|
177
|
+
reports.push(report);
|
178
|
+
}
|
179
|
+
catch (error) {
|
180
|
+
console.warn(chalk.yellow(`Warning: Could not review file ${file}: ${error}`));
|
181
|
+
}
|
182
|
+
}
|
183
|
+
return reports;
|
184
|
+
}
|
185
|
+
getCodeFiles(dirPath) {
|
186
|
+
const files = [];
|
187
|
+
const extensions = ['.js', '.ts', '.jsx', '.tsx', '.py', '.java', '.cpp', '.c', '.cs'];
|
188
|
+
const scan = (currentPath) => {
|
189
|
+
const items = fs.readdirSync(currentPath);
|
190
|
+
for (const item of items) {
|
191
|
+
const fullPath = path.join(currentPath, item);
|
192
|
+
const stat = fs.statSync(fullPath);
|
193
|
+
if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
|
194
|
+
scan(fullPath);
|
195
|
+
}
|
196
|
+
else if (stat.isFile() && extensions.some(ext => item.endsWith(ext))) {
|
197
|
+
files.push(fullPath);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
};
|
201
|
+
scan(dirPath);
|
202
|
+
return files;
|
203
|
+
}
|
204
|
+
generateSummary(totalIssues, errors, warnings, info) {
|
205
|
+
if (totalIssues === 0) {
|
206
|
+
return 'โ
No issues found! The code looks good.';
|
207
|
+
}
|
208
|
+
let summary = `Found ${totalIssues} issue${totalIssues > 1 ? 's' : ''}: `;
|
209
|
+
const parts = [];
|
210
|
+
if (errors > 0)
|
211
|
+
parts.push(`${errors} error${errors > 1 ? 's' : ''}`);
|
212
|
+
if (warnings > 0)
|
213
|
+
parts.push(`${warnings} warning${warnings > 1 ? 's' : ''}`);
|
214
|
+
if (info > 0)
|
215
|
+
parts.push(`${info} info item${info > 1 ? 's' : ''}`);
|
216
|
+
summary += parts.join(', ');
|
217
|
+
if (errors > 0) {
|
218
|
+
summary += ' ๐ด Critical issues need immediate attention.';
|
219
|
+
}
|
220
|
+
else if (warnings > 0) {
|
221
|
+
summary += ' ๐ก Some issues should be addressed.';
|
222
|
+
}
|
223
|
+
else {
|
224
|
+
summary += ' โน๏ธ Minor improvements suggested.';
|
225
|
+
}
|
226
|
+
return summary;
|
227
|
+
}
|
228
|
+
generateRecommendations(results) {
|
229
|
+
const recommendations = [];
|
230
|
+
const categories = new Set(results.map(r => r.rule.category));
|
231
|
+
if (categories.has('security')) {
|
232
|
+
recommendations.push('๐ Review security issues first - they pose the highest risk');
|
233
|
+
}
|
234
|
+
if (categories.has('reliability')) {
|
235
|
+
recommendations.push('๐ก๏ธ Address reliability issues to prevent runtime errors');
|
236
|
+
}
|
237
|
+
if (categories.has('performance')) {
|
238
|
+
recommendations.push('โก Consider performance optimizations for better user experience');
|
239
|
+
}
|
240
|
+
if (categories.has('maintainability')) {
|
241
|
+
recommendations.push('๐งน Refactor maintainability issues for long-term code health');
|
242
|
+
}
|
243
|
+
if (recommendations.length === 0) {
|
244
|
+
recommendations.push('โจ Code quality looks good! Consider regular reviews to maintain standards');
|
245
|
+
}
|
246
|
+
return recommendations;
|
247
|
+
}
|
248
|
+
addCustomRule(rule) {
|
249
|
+
this.rules.push(rule);
|
250
|
+
}
|
251
|
+
getRules() {
|
252
|
+
return [...this.rules];
|
253
|
+
}
|
254
|
+
}
|
255
|
+
export function printReviewReport(report) {
|
256
|
+
console.log(chalk.bold.blue(`\n๐ Code Review Report for: ${path.basename(report.filePath)}`));
|
257
|
+
console.log(chalk.gray(`File: ${report.filePath}`));
|
258
|
+
console.log(chalk.cyan(report.summary));
|
259
|
+
console.log('');
|
260
|
+
if (report.results.length > 0) {
|
261
|
+
// Group by severity
|
262
|
+
const errors = report.results.filter(r => r.severity === 'error');
|
263
|
+
const warnings = report.results.filter(r => r.severity === 'warning');
|
264
|
+
const info = report.results.filter(r => r.severity === 'info');
|
265
|
+
if (errors.length > 0) {
|
266
|
+
console.log(chalk.red.bold('๐ด ERRORS:'));
|
267
|
+
errors.forEach(result => {
|
268
|
+
console.log(` ${chalk.red(`[${result.rule.id}]`)} Line ${result.line}: ${result.message}`);
|
269
|
+
if (result.suggestion) {
|
270
|
+
console.log(` ๐ก ${chalk.gray(result.suggestion)}`);
|
271
|
+
}
|
272
|
+
});
|
273
|
+
console.log('');
|
274
|
+
}
|
275
|
+
if (warnings.length > 0) {
|
276
|
+
console.log(chalk.yellow.bold('๐ก WARNINGS:'));
|
277
|
+
warnings.forEach(result => {
|
278
|
+
console.log(` ${chalk.yellow(`[${result.rule.id}]`)} Line ${result.line}: ${result.message}`);
|
279
|
+
if (result.suggestion) {
|
280
|
+
console.log(` ๐ก ${chalk.gray(result.suggestion)}`);
|
281
|
+
}
|
282
|
+
});
|
283
|
+
console.log('');
|
284
|
+
}
|
285
|
+
if (info.length > 0) {
|
286
|
+
console.log(chalk.blue.bold('โน๏ธ INFO:'));
|
287
|
+
info.forEach(result => {
|
288
|
+
console.log(` ${chalk.blue(`[${result.rule.id}]`)} Line ${result.line}: ${result.message}`);
|
289
|
+
if (result.suggestion) {
|
290
|
+
console.log(` ๐ก ${chalk.gray(result.suggestion)}`);
|
291
|
+
}
|
292
|
+
});
|
293
|
+
console.log('');
|
294
|
+
}
|
295
|
+
}
|
296
|
+
if (report.recommendations.length > 0) {
|
297
|
+
console.log(chalk.green.bold('๐ก RECOMMENDATIONS:'));
|
298
|
+
report.recommendations.forEach(rec => {
|
299
|
+
console.log(` ${rec}`);
|
300
|
+
});
|
301
|
+
console.log('');
|
302
|
+
}
|
303
|
+
console.log(chalk.gray(`Total: ${report.totalIssues} issues (${report.errors} errors, ${report.warnings} warnings, ${report.info} info)`));
|
304
|
+
}
|
305
|
+
export function printMultipleReports(reports) {
|
306
|
+
const totalIssues = reports.reduce((sum, r) => sum + r.totalIssues, 0);
|
307
|
+
const totalErrors = reports.reduce((sum, r) => sum + r.errors, 0);
|
308
|
+
const totalWarnings = reports.reduce((sum, r) => sum + r.warnings, 0);
|
309
|
+
const totalInfo = reports.reduce((sum, r) => sum + r.info, 0);
|
310
|
+
console.log(chalk.bold.blue(`\n๐ Code Review Summary`));
|
311
|
+
console.log(chalk.cyan(`Reviewed ${reports.length} files`));
|
312
|
+
console.log(chalk.gray(`Total Issues: ${totalIssues} (${totalErrors} errors, ${totalWarnings} warnings, ${totalInfo} info)`));
|
313
|
+
console.log('');
|
314
|
+
reports.forEach(report => {
|
315
|
+
if (report.totalIssues > 0) {
|
316
|
+
printReviewReport(report);
|
317
|
+
}
|
318
|
+
});
|
319
|
+
}
|
package/lib/config.js
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
import { createClient } from '@supabase/supabase-js';
|
2
|
+
export const supabaseUrl = process.env.SUPABASE_URL || 'https://pkdytotoptkknghtsomn.supabase.co';
|
3
|
+
export const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBrZHl0b3RvcHRra25naHRzb21uIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTk3MjI1OTgsImV4cCI6MjA3NTI5ODU5OH0.Y3RVJvx7w-eGD4Nv2aVv8jnkUKhmA2vpkBs7_rFzEoQ';
|
4
|
+
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
|
5
|
+
export const setAuthToken = (token) => {
|
6
|
+
supabase.auth.setSession({ access_token: token, refresh_token: '' });
|
7
|
+
};
|