chrxmaticc-copilot 1.0.3

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/src/chat.js ADDED
@@ -0,0 +1,480 @@
1
+ // Chrxmaticc Copilot v1.0.0
2
+ // Single-User Chat Engine — All Features + Secrets
3
+ // Dual AI + TTS + Voice + Spotify + Plugins + Memory
4
+ // Author: Chrxmee-Midnightt
5
+
6
+ var readline = require('readline');
7
+ var chalk = require('chalk');
8
+ var PERSONALITY = require('./personality');
9
+ var pollinations = require('./apis/pollinations');
10
+ var groq = require('./apis/groq');
11
+ var tts = require('./tts');
12
+ var pluginEngine = require('./plugin-engine');
13
+ var memory = require('./memory');
14
+
15
+ var conversationHistory = [];
16
+ var currentProvider = 'pollinations';
17
+ var groqRateLimited = false;
18
+ var rateLimitResetTime = 0;
19
+ var ttsEnabled = true;
20
+ var clipboardWatcherActive = false;
21
+
22
+ function pickRandom(arr) {
23
+ return arr[Math.floor(Math.random() * arr.length)];
24
+ }
25
+
26
+ function getOfflineResponse(input) {
27
+ var lower = input.toLowerCase();
28
+ var topics = PERSONALITY.topics;
29
+ var responses = PERSONALITY.offline;
30
+
31
+ for (var category in topics) {
32
+ for (var i = 0; i < topics[category].length; i++) {
33
+ if (lower.indexOf(topics[category][i]) !== -1) {
34
+ if (responses[category]) return pickRandom(responses[category]);
35
+ }
36
+ }
37
+ }
38
+
39
+ if (lower.indexOf('hello') !== -1 || lower.indexOf('hey') !== -1 || lower.indexOf('hi') !== -1 || lower.indexOf('yo') !== -1) {
40
+ return pickRandom(responses.greeting);
41
+ }
42
+ if (lower.indexOf('help') !== -1) {
43
+ return 'Commands: /voice, /speak, /run, /roll, /8ball, /save, /clear, /provider, /clipboard, /complete, /review, /song, /playlist, /spotify, /plugins, /memory, /sys, /crypto, /weather, /translate, /qr, /passwd, /github, /define, /search, /remind, /exit. Secret commands: /easter, /midnight, /vault, /ping, /credits';
44
+ }
45
+ if (lower.indexOf('who are you') !== -1) {
46
+ return pickRandom(responses.whoami);
47
+ }
48
+ if (lower.indexOf('exit') !== -1 || lower.indexOf('quit') !== -1 || lower.indexOf('bye') !== -1) {
49
+ return { text: pickRandom(PERSONALITY.goodbyes), exit: true };
50
+ }
51
+
52
+ return pickRandom(responses.fallback);
53
+ }
54
+
55
+ async function askAI(userInput) {
56
+ if (groqRateLimited && Date.now() > rateLimitResetTime) groqRateLimited = false;
57
+
58
+ var result = await pollinations.ask(userInput, conversationHistory, PERSONALITY.systemPrompt);
59
+ if (result.success) { currentProvider = 'pollinations'; return result; }
60
+
61
+ if (!groqRateLimited) {
62
+ result = await groq.ask(userInput, conversationHistory, PERSONALITY.systemPrompt);
63
+ if (result.success) { currentProvider = 'groq'; return result; }
64
+ if (result.error === 'rate_limited') { groqRateLimited = true; rateLimitResetTime = Date.now() + 60000; }
65
+ }
66
+
67
+ result = await pollinations.ask(userInput, conversationHistory, PERSONALITY.systemPrompt);
68
+ if (result.success) { currentProvider = 'pollinations'; return result; }
69
+
70
+ return { success: false, error: 'all providers down', provider: 'offline' };
71
+ }
72
+
73
+ async function getResponse(input) {
74
+ var aiResult = await askAI(input);
75
+ if (aiResult.success) return { text: aiResult.text, provider: aiResult.provider };
76
+ return { text: getOfflineResponse(input), provider: 'offline' };
77
+ }
78
+
79
+ function typeText(text, callback) {
80
+ var chars = text.split('');
81
+ var i = 0;
82
+ function type() {
83
+ if (i < chars.length) {
84
+ process.stdout.write(chars[i]);
85
+ i = i + 1;
86
+ setTimeout(type, PERSONALITY.typingSpeedMin + Math.random() * (PERSONALITY.typingSpeedMax - PERSONALITY.typingSpeedMin));
87
+ } else {
88
+ console.log('');
89
+ console.log('');
90
+ if (callback) callback();
91
+ }
92
+ }
93
+ type();
94
+ }
95
+
96
+ // ──────────────────────────────────────────────
97
+ // SECRET COMMANDS
98
+ // ──────────────────────────────────────────────
99
+
100
+ var SECRETS = {
101
+ '/easter': function() {
102
+ var eggs = [
103
+ chalk.yellow('🥚 Easter egg found.'),
104
+ chalk.cyan('🥚 Another one.'),
105
+ chalk.magenta('🥚 You are persistent.'),
106
+ chalk.green('🥚 Four.'),
107
+ chalk.red('🥚 Five. The vault opens.'),
108
+ chalk.yellow('🥚 Six.'),
109
+ chalk.cyan('🥚 Seven.'),
110
+ chalk.magenta('🥚 Eight.'),
111
+ chalk.green('🥚 Nine.'),
112
+ chalk.red('🥚 Ten. All eggs collected.')
113
+ ];
114
+ var count = Math.floor(Math.random() * eggs.length);
115
+ return eggs[count];
116
+ },
117
+
118
+ '/midnight': function() {
119
+ return chalk.red('🌑 Midnight mode activated. The vault is wet. The neon beeps.');
120
+ },
121
+
122
+ '/vault': function() {
123
+ var msgs = [
124
+ 'The vault door is chrome. Wet. Reflecting neon.',
125
+ 'Inside: 26 shaders. 13 in 2D. 13 in 3D. Protected by the copilot.',
126
+ 'The C4 beeps. It never explodes. Eternal tension.'
127
+ ];
128
+ return chalk.red('🔐 ') + pickRandom(msgs);
129
+ },
130
+
131
+ '/ping': function() {
132
+ return 'pong | latency: ' + Math.floor(Math.random() * 50) + 'ms | provider: ' + currentProvider + ' | memory: ' + conversationHistory.length + ' msgs';
133
+ },
134
+
135
+ '/credits': function() {
136
+ return chalk.magenta('Chrxmaticc Copilot v1.0.0 — Chrxmee-Midnightt');
137
+ },
138
+
139
+ '/matrix': function() {
140
+ var chars = '01';
141
+ var lines = [];
142
+ for (var i = 0; i < 5; i++) {
143
+ var line = '';
144
+ for (var j = 0; j < 40; j++) line = line + chars[Math.floor(Math.random() * 2)] + ' ';
145
+ lines.push(chalk.green(line));
146
+ }
147
+ return lines.join('\n') + '\n\n' + chalk.white('Just a terminal AI.');
148
+ }
149
+ };
150
+
151
+ // ──────────────────────────────────────────────
152
+ // UTILITY COMMANDS
153
+ // ──────────────────────────────────────────────
154
+
155
+ async function handleUtilityCommand(trimmed) {
156
+ var lower = trimmed.toLowerCase();
157
+
158
+ // System monitor
159
+ if (lower === '/sys') {
160
+ var os = require('os');
161
+ var totalMem = (os.totalmem() / 1024 / 1024 / 1024).toFixed(1);
162
+ var freeMem = (os.freemem() / 1024 / 1024 / 1024).toFixed(1);
163
+ var cpuCount = os.cpus().length;
164
+ var uptime = Math.floor(os.uptime() / 3600);
165
+ return 'CPU: ' + cpuCount + ' cores | RAM: ' + freeMem + 'GB free / ' + totalMem + 'GB total | Uptime: ' + uptime + 'h';
166
+ }
167
+
168
+ // Password generator
169
+ if (lower.indexOf('/passwd') === 0) {
170
+ var len = parseInt(trimmed.replace('/passwd', '').trim()) || 16;
171
+ var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()';
172
+ var pass = '';
173
+ for (var i = 0; i < len; i++) pass = pass + chars[Math.floor(Math.random() * chars.length)];
174
+ return '🔑 ' + pass;
175
+ }
176
+
177
+ // QR code
178
+ if (lower.indexOf('/qr') === 0) {
179
+ var text = trimmed.replace('/qr', '').trim() || 'chrxmaticc';
180
+ var qr = '';
181
+ for (var y = 0; y < 21; y++) {
182
+ for (var x = 0; x < 21; x++) {
183
+ qr = qr + (Math.random() > 0.5 ? '██' : ' ');
184
+ }
185
+ qr = qr + '\n';
186
+ }
187
+ return '📱 QR for: ' + text + '\n' + chalk.white(qr) + '\n(Install qrcode-terminal for real QR)';
188
+ }
189
+
190
+ // Color preview
191
+ if (lower.indexOf('/color') === 0) {
192
+ var hex = trimmed.replace('/color', '').trim().replace('#', '') || 'ff00ff';
193
+ return chalk.hex('#' + hex)('██████████') + ' #' + hex;
194
+ }
195
+
196
+ return null;
197
+ }
198
+
199
+ // ──────────────────────────────────────────────
200
+ // MAIN COMMAND HANDLER
201
+ // ──────────────────────────────────────────────
202
+
203
+ async function handleCommand(trimmed, text, rl) {
204
+ var lower = trimmed.toLowerCase();
205
+ var cmdName = lower.split(' ')[0];
206
+
207
+ // Secret commands
208
+ if (SECRETS[cmdName]) {
209
+ var result = SECRETS[cmdName]();
210
+ return typeof result === 'function' ? result() : result;
211
+ }
212
+
213
+ // Utility commands
214
+ var utilResult = await handleUtilityCommand(trimmed);
215
+ if (utilResult) return utilResult;
216
+
217
+ // Voice
218
+ if (lower === '/voice' || lower === '/v') {
219
+ var voice = require('./voice');
220
+ voice.voiceChat(rl, function() { rl.prompt(); });
221
+ return chalk.magenta('🎤 Listening...');
222
+ }
223
+
224
+ // TTS
225
+ if (lower.indexOf('/speak') === 0) {
226
+ var speakText = trimmed.replace('/speak', '').trim() || text;
227
+ if (ttsEnabled) {
228
+ tts.speak(speakText, 'en', function(err) {
229
+ if (err) console.log(' ' + chalk.red('TTS Error: ' + err.message));
230
+ });
231
+ return '🗣️ ' + speakText;
232
+ }
233
+ return chalk.gray('TTS muted. /unmute');
234
+ }
235
+
236
+ if (lower === '/mute') { ttsEnabled = false; return chalk.yellow('🔇 TTS muted.'); }
237
+ if (lower === '/unmute') { ttsEnabled = true; return chalk.green('🔊 TTS unmuted.'); }
238
+
239
+ // Run command
240
+ if (lower.indexOf('/run') === 0) {
241
+ var cmd = trimmed.replace('/run', '').trim();
242
+ if (!cmd) return chalk.yellow('Usage: /run <command>');
243
+ try {
244
+ var execSync = require('child_process').execSync;
245
+ var output = execSync(cmd, { encoding: 'utf8', timeout: 10000, maxBuffer: 1024 * 500 });
246
+ return chalk.green('$ ' + cmd + '\n') + output.slice(0, 1000);
247
+ } catch (e) {
248
+ return chalk.red('$ ' + cmd + '\nError: ') + e.message;
249
+ }
250
+ }
251
+
252
+ // Save
253
+ if (lower === '/save') {
254
+ var fs = require('fs');
255
+ var log = '';
256
+ for (var i = 0; i < conversationHistory.length; i++) {
257
+ log = log + conversationHistory[i].role + ': ' + conversationHistory[i].content + '\n';
258
+ }
259
+ fs.writeFileSync('chrxmaticc-chat.log', log);
260
+ memory.storeConversation('local-user', conversationHistory);
261
+ return chalk.green('💾 Saved.');
262
+ }
263
+
264
+ // Clear
265
+ if (lower === '/clear') { conversationHistory = []; return chalk.yellow('🧹 Cleared.'); }
266
+
267
+ // Provider
268
+ if (lower === '/provider') {
269
+ return chalk.gray('Provider: ' + currentProvider + ' | TTS: ' + (ttsEnabled ? 'on' : 'off') + ' | Memory: ' + conversationHistory.length);
270
+ }
271
+
272
+ // Roll dice
273
+ if (lower.indexOf('/roll') === 0) {
274
+ var dice = lower.replace('/roll', '').trim() || '1d6';
275
+ var parts = dice.split('d');
276
+ var count = parseInt(parts[0]) || 1;
277
+ var sides = parseInt(parts[1]) || 6;
278
+ var results = [];
279
+ for (var i = 0; i < count; i++) results.push(Math.floor(Math.random() * sides) + 1);
280
+ var total = results.reduce(function(a, b) { return a + b; }, 0);
281
+ return chalk.yellow('🎲 ' + dice + ': ') + results.join(', ') + chalk.green(' = ' + total);
282
+ }
283
+
284
+ // 8-ball
285
+ if (lower.indexOf('/8ball') === 0) {
286
+ var ball = ['Yes.', 'No.', 'Maybe.', 'Ask again.', 'Definitely.', 'Doubtful.'];
287
+ return chalk.magenta('🎱 ') + pickRandom(ball);
288
+ }
289
+
290
+ // Clipboard
291
+ if (lower === '/clipboard on') {
292
+ var cw = require('./extensions/clipboard-watcher');
293
+ cw.startWatcher();
294
+ clipboardWatcherActive = true;
295
+ return chalk.green('📋 Clipboard watcher active.');
296
+ }
297
+ if (lower === '/clipboard off') { clipboardWatcherActive = false; return chalk.yellow('📋 Stopped.'); }
298
+
299
+ // Terminal complete
300
+ if (lower.indexOf('/complete') === 0) {
301
+ var partial = trimmed.replace('/complete', '').trim();
302
+ if (!partial) return chalk.yellow('Usage: /complete <partial command>');
303
+ var th = require('./extensions/terminal-hook');
304
+ var suggestion = await th.suggestCommand(partial);
305
+ return chalk.cyan('💡 ') + suggestion;
306
+ }
307
+
308
+ // Code review
309
+ if (lower.indexOf('/review') === 0) {
310
+ var code = trimmed.replace('/review', '').trim();
311
+ if (!code) return chalk.yellow('Usage: /review <code>');
312
+ var cr = require('./extensions/code-review');
313
+ var result = await cr.reviewCode(code);
314
+ return chalk.green('🔍 Review:\n') + result.review;
315
+ }
316
+
317
+ // Spotify
318
+ if (lower.indexOf('/spotify') === 0) {
319
+ var spotify = require('./extensions/spotify');
320
+ var result = await spotify.handleCommand(trimmed, 'local-user');
321
+ return chalk.green('🎵 ') + result.text;
322
+ }
323
+
324
+ // Song analysis
325
+ if (lower.indexOf('/song') === 0) {
326
+ var track = trimmed.replace('/song', '').trim();
327
+ if (!track) return chalk.yellow('Usage: /song <track> - <artist>');
328
+ var sp = require('./extensions/spotify');
329
+ var parts = track.split(' - ');
330
+ var analysis = await sp.analyzeTrack(parts[0], parts[1] || '');
331
+ return chalk.green('🎵 ') + analysis;
332
+ }
333
+
334
+ // Playlist
335
+ if (lower.indexOf('/playlist') === 0) {
336
+ var mood = trimmed.replace('/playlist', '').trim() || 'chill';
337
+ var sp = require('./extensions/spotify');
338
+ var playlist = await sp.createPlaylistPrompt(mood);
339
+ return chalk.green('🎧 Playlist:\n') + playlist;
340
+ }
341
+
342
+ // Similar songs
343
+ if (lower.indexOf('/similar') === 0) {
344
+ var track = trimmed.replace('/similar', '').trim();
345
+ if (!track) return chalk.yellow('Usage: /similar <track> - <artist>');
346
+ var sp = require('./extensions/spotify');
347
+ var parts = track.split(' - ');
348
+ var similar = await sp.suggestSimilar(parts[0], parts[1] || '');
349
+ return chalk.green('🎧 Similar:\n') + similar;
350
+ }
351
+
352
+ // Plugin commands
353
+ if (pluginEngine.isPluginCommand(trimmed)) {
354
+ var plugin = pluginEngine.getPluginFromCommand(trimmed);
355
+ if (plugin) {
356
+ var args = trimmed.replace('/' + plugin.name, '').trim();
357
+ var context = { userId: 'local-user', conversationHistory: conversationHistory, currentProvider: currentProvider, getResponse: getResponse };
358
+ var pluginResult = await pluginEngine.runPlugin(plugin.name, args, context);
359
+ return chalk.cyan('🔌 ') + pluginResult;
360
+ }
361
+ }
362
+
363
+ // Plugin management
364
+ if (lower === '/plugins') {
365
+ var all = pluginEngine.getAllPlugins();
366
+ if (all.length === 0) return chalk.gray('No plugins. Drop .js files in ' + pluginEngine.getPluginDir());
367
+ var list = '🔌 Plugins:\n';
368
+ all.forEach(function(p) { list = list + ' ' + chalk.cyan('/' + p.name) + ' — ' + p.description + '\n'; });
369
+ return list;
370
+ }
371
+ if (lower === '/plugins reload') { var count = pluginEngine.reload(); return chalk.green('🔌 Reloaded. ' + count + ' active.'); }
372
+
373
+ // Memory
374
+ if (lower === '/memory') {
375
+ var mem = memory.getStats('local-user');
376
+ return chalk.gray('Memory: ' + mem.conversations + ' conversations, ' + mem.facts + ' facts');
377
+ }
378
+ if (lower === '/memory recall') {
379
+ var recalled = memory.recall('local-user', trimmed.replace('/memory recall', '').trim());
380
+ return chalk.yellow('🧠 ') + (recalled || 'Nothing found.');
381
+ }
382
+
383
+ // Exit
384
+ if (lower === '/exit' || lower === '/quit') {
385
+ return { text: pickRandom(PERSONALITY.goodbyes), exit: true };
386
+ }
387
+
388
+ return null;
389
+ }
390
+
391
+ // ──────────────────────────────────────────────
392
+ // CHAT LOOP
393
+ // ──────────────────────────────────────────────
394
+
395
+ function chat() {
396
+ memory.init();
397
+ pluginEngine.init();
398
+
399
+ var rl = readline.createInterface({
400
+ input: process.stdin,
401
+ output: process.stdout,
402
+ prompt: chalk.cyan('you > ')
403
+ });
404
+
405
+ console.log('');
406
+ console.log(' ' + chalk.magenta('╔══════════════════════════════════════╗'));
407
+ console.log(' ' + chalk.magenta('║ 🧠 ' + PERSONALITY.name + ' v' + PERSONALITY.version + ' ║'));
408
+ console.log(' ' + chalk.magenta('║ ' + PERSONALITY.tagline + ' ║'));
409
+ console.log(' ' + chalk.magenta('╚══════════════════════════════════════╝'));
410
+ console.log('');
411
+ console.log(' ' + chalk.green('●') + ' AI: Pollinations + Groq');
412
+ console.log(' ' + chalk.magenta('●') + ' Voice: /voice | TTS: /speak');
413
+ console.log(' ' + chalk.cyan('●') + ' Spotify: /spotify login');
414
+ console.log(' ' + chalk.yellow('●') + ' Tools: /run, /review, /sys, /passwd');
415
+ var pluginCount = pluginEngine.getAllPlugins().length;
416
+ if (pluginCount > 0) console.log(' ' + chalk.green('●') + ' Plugins: ' + pluginCount + ' loaded');
417
+ console.log(' ' + chalk.gray('Type /help for all commands'));
418
+ console.log('');
419
+
420
+ var greeting = pickRandom(PERSONALITY.greetings);
421
+ process.stdout.write(' ' + chalk.magenta('chrxmaticc > '));
422
+ typeText(greeting, function() { rl.prompt(); });
423
+
424
+ rl.on('line', async function(input) {
425
+ var trimmed = input.trim();
426
+ if (!trimmed) {
427
+ process.stdout.write(' ' + chalk.magenta('chrxmaticc > '));
428
+ typeText(pickRandom(PERSONALITY.emptyInput), function() { rl.prompt(); });
429
+ return;
430
+ }
431
+
432
+ var response = await getResponse(trimmed);
433
+ var text = typeof response === 'string' ? response : response.text;
434
+ var exit = typeof response === 'object' && response.exit;
435
+ var provider = response.provider || 'offline';
436
+
437
+ var commandResult = await handleCommand(trimmed, text, rl);
438
+ if (commandResult) {
439
+ if (typeof commandResult === 'object' && commandResult.exit) {
440
+ text = commandResult.text;
441
+ exit = true;
442
+ } else {
443
+ text = commandResult;
444
+ provider = 'system';
445
+ }
446
+ }
447
+
448
+ if (provider !== 'system') {
449
+ conversationHistory.push({ role: 'user', content: trimmed });
450
+ conversationHistory.push({ role: 'assistant', content: text });
451
+ memory.storeMessage('local-user', 'user', trimmed, provider);
452
+ memory.storeMessage('local-user', 'assistant', text, provider);
453
+ }
454
+
455
+ if (conversationHistory.length > PERSONALITY.maxHistory) {
456
+ conversationHistory = conversationHistory.slice(-PERSONALITY.maxHistory);
457
+ }
458
+
459
+ var providerBadge = '';
460
+ if (provider === 'pollinations') providerBadge = chalk.green(' [Pollinations]');
461
+ else if (provider === 'groq') providerBadge = chalk.cyan(' [Groq]');
462
+ else if (provider === 'offline') providerBadge = chalk.yellow(' [Offline]');
463
+ else if (provider === 'system') providerBadge = chalk.magenta(' [System]');
464
+
465
+ process.stdout.write(' ' + chalk.magenta('chrxmaticc > '));
466
+ typeText(text + providerBadge, function() {
467
+ if (exit) {
468
+ console.log(' ' + chalk.gray(PERSONALITY.name + ' offline.'));
469
+ console.log('');
470
+ rl.close();
471
+ return;
472
+ }
473
+ rl.prompt();
474
+ });
475
+ });
476
+
477
+ rl.on('close', function() { process.exit(0); });
478
+ }
479
+
480
+ module.exports = { chat: chat, getResponse: getResponse };
@@ -0,0 +1,66 @@
1
+ var chalk = require('chalk');
2
+ // Chrxmaticc Copilot — Clipboard Watcher
3
+ // Watches clipboard for errors, auto-suggests fixes
4
+ // Author: Chrxmee-Midnightt
5
+
6
+ var chat = require('../chat');
7
+ var chalk = require('chalk');
8
+ var lastClip = '';
9
+
10
+ function startWatcher(intervalMs) {
11
+ intervalMs = intervalMs || 3000;
12
+
13
+ console.log('');
14
+ console.log(' ' + chalk.magenta('📋 Clipboard Watcher started'));
15
+ console.log(' ' + chalk.gray('Copy an error message and I\'ll suggest a fix'));
16
+ console.log('');
17
+
18
+ setInterval(function() {
19
+ var clipboardy;
20
+ try {
21
+ clipboardy = require('clipboardy');
22
+ } catch (e) {
23
+ console.log(' ' + chalk.gray('Install clipboardy: npm install clipboardy'));
24
+ return;
25
+ }
26
+
27
+ try {
28
+ var currentClip = clipboardy.readSync();
29
+
30
+ if (currentClip && currentClip !== lastClip && currentClip.length > 10) {
31
+ lastClip = currentClip;
32
+
33
+ if (isError(currentClip)) {
34
+ console.log(' ' + chalk.red('✗ Error detected in clipboard!'));
35
+ console.log(' ' + chalk.gray('Analyzing...'));
36
+
37
+ chat.getResponse('I copied this error. What does it mean and how do I fix it? Give me a direct answer.\n\n' + currentClip.slice(0, 1000))
38
+ .then(function(response) {
39
+ var text = typeof response === 'string' ? response : response.text;
40
+ console.log(' ' + chalk.magenta('chrxmaticc > ') + text);
41
+ console.log('');
42
+ });
43
+ }
44
+ }
45
+ } catch (e) {}
46
+ }, intervalMs);
47
+ }
48
+
49
+ function isError(text) {
50
+ var errorPatterns = [
51
+ 'error', 'Error', 'ERROR',
52
+ 'TypeError', 'ReferenceError', 'SyntaxError',
53
+ 'cannot find', 'is not defined', 'is not a function',
54
+ 'failed to', 'unable to', 'permission denied',
55
+ 'ENOENT', 'EACCES', 'ECONNREFUSED',
56
+ 'fatal', 'traceback', 'stack trace',
57
+ 'undefined is not', 'null is not'
58
+ ];
59
+
60
+ for (var i = 0; i < errorPatterns.length; i++) {
61
+ if (text.indexOf(errorPatterns[i]) !== -1) return true;
62
+ }
63
+ return false;
64
+ }
65
+
66
+ module.exports = { startWatcher: startWatcher };
@@ -0,0 +1,63 @@
1
+ var chalk = require('chalk');
2
+ // Chrxmaticc Copilot — Code Review Bot
3
+ // Reviews GitHub PRs with AI suggestions
4
+ // Author: Chrxmee-Midnightt
5
+
6
+ var chat = require('../chat');
7
+ var chalk = require('chalk');
8
+
9
+ var reviewCache = {};
10
+
11
+ async function reviewCode(code, language) {
12
+ language = language || 'javascript';
13
+
14
+ var prompt = 'Review this ' + language + ' code. Find bugs, suggest improvements, and check for best practices. Be direct and concise.\n\n```' + language + '\n' + code.slice(0, 3000) + '\n```';
15
+
16
+ var response = await chat.getResponse(prompt);
17
+ var text = typeof response === 'string' ? response : response.text;
18
+
19
+ return {
20
+ review: text,
21
+ timestamp: Date.now()
22
+ };
23
+ }
24
+
25
+ async function reviewPR(prTitle, prDescription, files) {
26
+ var prompt = 'Review this pull request:\nTitle: ' + prTitle + '\nDescription: ' + prDescription + '\n\nFiles changed:\n';
27
+
28
+ for (var i = 0; i < files.length; i++) {
29
+ prompt = prompt + '\n### ' + files[i].filename + '\n```\n' + files[i].patch.slice(0, 1500) + '\n```\n';
30
+ }
31
+
32
+ prompt = prompt + '\nGive me a summary, any bugs found, and suggestions.';
33
+
34
+ var response = await chat.getResponse(prompt);
35
+ var text = typeof response === 'string' ? response : response.text;
36
+
37
+ return {
38
+ review: text,
39
+ filesReviewed: files.length,
40
+ timestamp: Date.now()
41
+ };
42
+ }
43
+
44
+ function watchGitHubPRs(webhookUrl) {
45
+ console.log('');
46
+ console.log(' ' + chalk.magenta('🔍 Code Review Bot active'));
47
+ console.log(' ' + chalk.gray('Send PRs to review. Results cached for 1 hour.'));
48
+ console.log('');
49
+ }
50
+
51
+ function getReviewFromCache(key) {
52
+ if (reviewCache[key] && Date.now() - reviewCache[key].timestamp < 3600000) {
53
+ return reviewCache[key].review;
54
+ }
55
+ return null;
56
+ }
57
+
58
+ module.exports = {
59
+ reviewCode: reviewCode,
60
+ reviewPR: reviewPR,
61
+ watchGitHubPRs: watchGitHubPRs,
62
+ getReviewFromCache: getReviewFromCache
63
+ };