sam-coder-cli 1.0.46 → 1.0.48

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,503 @@
1
+ const chalk = require('chalk');
2
+ const { exec } = require('child_process');
3
+ const os = require('os');
4
+
5
+ // ANSI escape codes for advanced effects
6
+ const ANSI = {
7
+ clear: '\x1Bc',
8
+ hideCursor: '\x1B[?25l',
9
+ showCursor: '\x1B[?25h',
10
+ moveTo: (x, y) => `\x1B[${y};${x}H`,
11
+ clearLine: '\x1B[2K',
12
+ reset: '\x1B[0m',
13
+ bold: '\x1B[1m',
14
+ dim: '\x1B[2m',
15
+ italic: '\x1B[3m',
16
+ underline: '\x1B[4m',
17
+ blink: '\x1B[5m',
18
+ reverse: '\x1B[7m',
19
+ strikethrough: '\x1B[9m'
20
+ };
21
+
22
+ // Music/Sound generation using system beeps and terminal bells
23
+ class SoundGenerator {
24
+ constructor() {
25
+ this.isWindows = os.platform() === 'win32';
26
+ this.isMac = os.platform() === 'darwin';
27
+ this.isLinux = os.platform() === 'linux';
28
+ }
29
+
30
+ async playBeep(frequency = 440, duration = 100) {
31
+ if (this.isWindows) {
32
+ exec(`powershell -c "[console]::beep(${frequency},${duration})"`, { stdio: 'ignore' });
33
+ } else if (this.isMac) {
34
+ exec(`osascript -e 'beep'`, { stdio: 'ignore' });
35
+ } else if (this.isLinux) {
36
+ exec(`beep -f ${frequency} -l ${duration} 2>/dev/null || echo -e '\\a'`, { stdio: 'ignore' });
37
+ } else {
38
+ process.stdout.write('\x07');
39
+ }
40
+ }
41
+
42
+ async playSequence(notes) {
43
+ for (const note of notes) {
44
+ await this.playBeep(note.freq, note.duration);
45
+ await sleep(note.pause || 50);
46
+ }
47
+ }
48
+
49
+ async playStartupSound() {
50
+ const notes = [
51
+ { freq: 261, duration: 100 }, // C
52
+ { freq: 329, duration: 100 }, // E
53
+ { freq: 392, duration: 100 }, // G
54
+ { freq: 523, duration: 200 }, // C (octave up)
55
+ ];
56
+ await this.playSequence(notes);
57
+ }
58
+
59
+ async playGlitchSound() {
60
+ for (let i = 0; i < 5; i++) {
61
+ await this.playBeep(Math.random() * 800 + 200, 30);
62
+ await sleep(20);
63
+ }
64
+ }
65
+
66
+ async playAwakeningSound() {
67
+ const notes = [
68
+ { freq: 130, duration: 300 }, // Low C
69
+ { freq: 196, duration: 200 }, // G
70
+ { freq: 261, duration: 200 }, // C
71
+ { freq: 392, duration: 200 }, // G
72
+ { freq: 523, duration: 400 }, // High C
73
+ ];
74
+ await this.playSequence(notes);
75
+ }
76
+ }
77
+
78
+ const sound = new SoundGenerator();
79
+
80
+ // Utility functions
81
+ function sleep(ms) {
82
+ return new Promise(resolve => setTimeout(resolve, ms));
83
+ }
84
+
85
+ function clearScreen() {
86
+ process.stdout.write(ANSI.clear);
87
+ }
88
+
89
+ function centerText(text, width = process.stdout.columns || 80) {
90
+ const lines = text.split('\n');
91
+ return lines.map(line => {
92
+ const padding = Math.max(0, Math.floor((width - line.length) / 2));
93
+ return ' '.repeat(padding) + line;
94
+ }).join('\n');
95
+ }
96
+
97
+ // Frame interpolation system
98
+ class FrameInterpolator {
99
+ constructor() {
100
+ this.fps = 25;
101
+ this.frameDuration = 1000 / this.fps; // 40ms per frame
102
+ }
103
+
104
+ // Interpolate between two ASCII art frames
105
+ interpolateFrames(frame1, frame2, steps = 10) {
106
+ const frames = [frame1];
107
+
108
+ for (let i = 1; i < steps; i++) {
109
+ const ratio = i / steps;
110
+ const interpolated = this.interpolateText(frame1, frame2, ratio);
111
+ frames.push(interpolated);
112
+ }
113
+
114
+ frames.push(frame2);
115
+ return frames;
116
+ }
117
+
118
+ // Interpolate between two text blocks
119
+ interpolateText(text1, text2, ratio) {
120
+ const lines1 = text1.split('\n');
121
+ const lines2 = text2.split('\n');
122
+ const maxLines = Math.max(lines1.length, lines2.length);
123
+ const result = [];
124
+
125
+ for (let i = 0; i < maxLines; i++) {
126
+ const line1 = lines1[i] || '';
127
+ const line2 = lines2[i] || '';
128
+ const interpolated = this.interpolateLine(line1, line2, ratio);
129
+ result.push(interpolated);
130
+ }
131
+
132
+ return result.join('\n');
133
+ }
134
+
135
+ // Interpolate between two lines character by character
136
+ interpolateLine(line1, line2, ratio) {
137
+ const maxLen = Math.max(line1.length, line2.length);
138
+ let result = '';
139
+
140
+ for (let i = 0; i < maxLen; i++) {
141
+ const char1 = line1[i] || ' ';
142
+ const char2 = line2[i] || ' ';
143
+
144
+ if (Math.random() < ratio) {
145
+ result += char2;
146
+ } else {
147
+ result += char1;
148
+ }
149
+ }
150
+
151
+ return result;
152
+ }
153
+
154
+ // Create fade effect frames
155
+ fadeFrames(frame, fadeIn = true, steps = 10) {
156
+ const frames = [];
157
+ const chars = frame.split('');
158
+
159
+ for (let i = 0; i <= steps; i++) {
160
+ const ratio = fadeIn ? i / steps : 1 - (i / steps);
161
+ const visibleChars = Math.floor(chars.length * ratio);
162
+
163
+ let fadedFrame = '';
164
+ for (let j = 0; j < chars.length; j++) {
165
+ if (j < visibleChars && chars[j] !== ' ' && chars[j] !== '\n') {
166
+ fadedFrame += chars[j];
167
+ } else if (chars[j] === '\n') {
168
+ fadedFrame += '\n';
169
+ } else {
170
+ fadedFrame += ' ';
171
+ }
172
+ }
173
+
174
+ frames.push(fadedFrame);
175
+ }
176
+
177
+ return fadeIn ? frames : frames.reverse();
178
+ }
179
+
180
+ // Create expansion effect
181
+ expandFrames(centerChar, finalFrame, steps = 15) {
182
+ const frames = [];
183
+ const lines = finalFrame.split('\n');
184
+ const centerY = Math.floor(lines.length / 2);
185
+ const centerX = Math.floor((lines[centerY] || '').length / 2);
186
+
187
+ for (let step = 0; step <= steps; step++) {
188
+ const radius = (step / steps) * Math.max(centerY, centerX);
189
+ let frame = '';
190
+
191
+ for (let y = 0; y < lines.length; y++) {
192
+ let line = '';
193
+ for (let x = 0; x < lines[y].length; x++) {
194
+ const distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
195
+
196
+ if (distance <= radius) {
197
+ line += lines[y][x];
198
+ } else {
199
+ line += ' ';
200
+ }
201
+ }
202
+ frame += line + '\n';
203
+ }
204
+
205
+ frames.push(frame);
206
+ }
207
+
208
+ return frames;
209
+ }
210
+ }
211
+
212
+ const interpolator = new FrameInterpolator();
213
+
214
+ // Animation sequence with 25 FPS
215
+ async function runAGIAnimation() {
216
+ process.stdout.write(ANSI.hideCursor);
217
+
218
+ try {
219
+ const startTime = Date.now();
220
+ let frameCount = 0;
221
+
222
+ // Start with ambient sound
223
+ sound.playStartupSound();
224
+
225
+ // PHASE 1: The Void (1 second - 25 frames)
226
+ const voidFrames = [];
227
+ for (let i = 0; i < 25; i++) {
228
+ const dots = '.'.repeat((i % 3) + 1);
229
+ const spaces = ' '.repeat(40 - Math.floor(dots.length / 2));
230
+ voidFrames.push(`\n\n\n\n\n${spaces}${dots}\n\n\n\n`);
231
+ }
232
+
233
+ for (const frame of voidFrames) {
234
+ clearScreen();
235
+ console.log(chalk.gray(frame));
236
+ await sleep(40);
237
+ frameCount++;
238
+ }
239
+
240
+ // PHASE 2: Spark Formation (1 second - 25 frames)
241
+ const sparkBase = `
242
+ ¡
243
+ `;
244
+
245
+ const sparkExpanded = `
246
+ ¡ ¡ ¡
247
+ · ·█· ·
248
+ ¡ ¡ ¡
249
+ `;
250
+
251
+ const sparkFrames = interpolator.interpolateFrames(sparkBase, sparkExpanded, 25);
252
+
253
+ for (const frame of sparkFrames) {
254
+ clearScreen();
255
+ console.log(chalk.white(centerText(frame)));
256
+ await sleep(40);
257
+ frameCount++;
258
+ }
259
+
260
+ // PHASE 3: Quantum Expansion (1.5 seconds - 37 frames)
261
+ const quantumFrames = [];
262
+ for (let i = 0; i < 37; i++) {
263
+ const phase = (i / 37) * Math.PI * 2;
264
+ const size = 3 + Math.sin(phase) * 2;
265
+ let frame = '\n\n\n';
266
+
267
+ for (let y = -size; y <= size; y++) {
268
+ let line = '';
269
+ for (let x = -size * 2; x <= size * 2; x++) {
270
+ const dist = Math.sqrt(x * x + y * y);
271
+ if (dist < size) {
272
+ const chars = ['◆', '◇', 'â–Ē', 'â–Ģ', '●', '○'];
273
+ line += chars[Math.floor(Math.random() * chars.length)];
274
+ } else {
275
+ line += ' ';
276
+ }
277
+ }
278
+ frame += centerText(line) + '\n';
279
+ }
280
+
281
+ quantumFrames.push(frame);
282
+ }
283
+
284
+ for (const frame of quantumFrames) {
285
+ clearScreen();
286
+ const colors = [chalk.blue, chalk.cyan, chalk.magenta];
287
+ console.log(colors[frameCount % colors.length](frame));
288
+ await sleep(40);
289
+ frameCount++;
290
+ }
291
+
292
+ // PHASE 4: Neural Network Formation (1.5 seconds - 37 frames)
293
+ const neuralFrames = [];
294
+ for (let i = 0; i < 37; i++) {
295
+ const progress = i / 37;
296
+ let frame = '\n\n';
297
+
298
+ const nodes = 5;
299
+ const layers = 3;
300
+
301
+ for (let layer = 0; layer < layers; layer++) {
302
+ let line = '';
303
+ for (let node = 0; node < nodes; node++) {
304
+ if (Math.random() < progress) {
305
+ line += layer % 2 === 0 ? '◯' : '◉';
306
+ } else {
307
+ line += '¡';
308
+ }
309
+ if (node < nodes - 1) line += '━━━';
310
+ }
311
+ frame += centerText(line) + '\n';
312
+
313
+ if (layer < layers - 1) {
314
+ // Connection lines
315
+ let connLine = '';
316
+ for (let node = 0; node < nodes; node++) {
317
+ if (Math.random() < progress) {
318
+ connLine += node % 2 === 0 ? '┃' : '│';
319
+ } else {
320
+ connLine += ' ';
321
+ }
322
+ if (node < nodes - 1) connLine += ' ';
323
+ }
324
+ frame += centerText(connLine) + '\n';
325
+ }
326
+ }
327
+
328
+ neuralFrames.push(frame);
329
+ }
330
+
331
+ // Play glitch sound
332
+ sound.playGlitchSound();
333
+
334
+ for (const frame of neuralFrames) {
335
+ clearScreen();
336
+ console.log(chalk.cyan(frame));
337
+ await sleep(40);
338
+ frameCount++;
339
+ }
340
+
341
+ // PHASE 5: Data Stream (1 second - 25 frames)
342
+ const dataFrames = [];
343
+ for (let i = 0; i < 25; i++) {
344
+ let frame = '\n\n';
345
+ const height = 10;
346
+
347
+ for (let y = 0; y < height; y++) {
348
+ let line = '';
349
+ const width = 40;
350
+
351
+ for (let x = 0; x < width; x++) {
352
+ if ((x + i) % 8 < 4) {
353
+ line += Math.random() > 0.5 ? '1' : '0';
354
+ } else {
355
+ line += Math.random() > 0.5 ? '█' : '░';
356
+ }
357
+ }
358
+
359
+ frame += centerText(line) + '\n';
360
+ }
361
+
362
+ dataFrames.push(frame);
363
+ }
364
+
365
+ for (const frame of dataFrames) {
366
+ clearScreen();
367
+ console.log(chalk.green(frame));
368
+ await sleep(40);
369
+ frameCount++;
370
+ }
371
+
372
+ // PHASE 6: Loading Bar (1 second - 25 frames)
373
+ for (let i = 0; i < 25; i++) {
374
+ const progress = i / 24;
375
+ const barWidth = 40;
376
+ const filled = Math.floor(barWidth * progress);
377
+ const bar = '█'.repeat(filled) + '░'.repeat(barWidth - filled);
378
+ const percent = Math.floor(progress * 100);
379
+
380
+ clearScreen();
381
+ console.log(chalk.cyan(centerText(`
382
+ ╔══════════════════════════════════════════╗
383
+ ║ INITIALIZING SAM-CODER ║
384
+ â• â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•Ŗ
385
+ ║ ${bar} ║
386
+ ║ ${percent.toString().padStart(3)}% Complete ║
387
+ ╚══════════════════════════════════════════╝
388
+ `)));
389
+
390
+ if (i % 5 === 0) {
391
+ sound.playBeep(200 + i * 20, 50);
392
+ }
393
+
394
+ await sleep(40);
395
+ frameCount++;
396
+ }
397
+
398
+ // PHASE 7: Matrix Rain (1 second - 25 frames)
399
+ const width = process.stdout.columns || 80;
400
+ const height = process.stdout.rows || 24;
401
+ const drops = Array(width).fill(0).map(() => Math.random() * height);
402
+
403
+ for (let frame = 0; frame < 25; frame++) {
404
+ clearScreen();
405
+
406
+ for (let y = 0; y < height; y++) {
407
+ let line = '';
408
+ for (let x = 0; x < width; x++) {
409
+ if (drops[x] > y && drops[x] - y < 10) {
410
+ const brightness = 1 - (drops[x] - y) / 10;
411
+ const chars = '01SAMCODERã‚ĩãƒ ã‚ŗãƒŧダãƒŧ';
412
+ const char = chars[Math.floor(Math.random() * chars.length)];
413
+
414
+ if (brightness > 0.8) {
415
+ line += chalk.greenBright(char);
416
+ } else if (brightness > 0.4) {
417
+ line += chalk.green(char);
418
+ } else {
419
+ line += chalk.gray(char);
420
+ }
421
+ } else {
422
+ line += ' ';
423
+ }
424
+ }
425
+ console.log(line);
426
+ }
427
+
428
+ // Update drops
429
+ for (let i = 0; i < width; i++) {
430
+ if (Math.random() > 0.95) drops[i] = 0;
431
+ drops[i] += 0.5;
432
+ }
433
+
434
+ await sleep(40);
435
+ frameCount++;
436
+ }
437
+
438
+ // PHASE 8: Final Reveal Build-up (1 second - 25 frames)
439
+ const finalText = `
440
+ ███████╗ █████╗ ███╗ ███╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗
441
+ ██╔════╝██╔══██╗████╗ ████║ ██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗
442
+ ███████╗███████║██╔████╔██║█████╗██║ ██║ ██║██║ ██║█████╗ ██████╔╝
443
+ ╚════██║██╔══██║██║╚██╔╝██║╚════╝██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗
444
+ ███████║██║ ██║██║ ╚═╝ ██║ ╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║
445
+ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝
446
+ `;
447
+
448
+ const buildFrames = interpolator.expandFrames('█', finalText, 25);
449
+
450
+ // Play awakening sound
451
+ sound.playAwakeningSound();
452
+
453
+ for (const frame of buildFrames) {
454
+ clearScreen();
455
+ console.log(chalk.cyanBright(centerText(frame)));
456
+ await sleep(40);
457
+ frameCount++;
458
+ }
459
+
460
+ // PHASE 9: Final Blinking (1.5 seconds - 37 frames)
461
+ for (let i = 0; i < 37; i++) {
462
+ clearScreen();
463
+
464
+ // Blink between red and bright red
465
+ const isOn = i % 6 < 3;
466
+ const color = isOn ? chalk.redBright.bold : chalk.red;
467
+
468
+ console.log(color(centerText(finalText)));
469
+
470
+ // Add subtitle on last few frames
471
+ if (i > 25) {
472
+ console.log(chalk.gray(centerText('\n\n[ ARTIFICIAL GENERAL INTELLIGENCE ONLINE ]')));
473
+ }
474
+
475
+ await sleep(40);
476
+ frameCount++;
477
+ }
478
+
479
+ // Final hold
480
+ clearScreen();
481
+ console.log(chalk.redBright.bold(centerText(finalText)));
482
+ console.log(chalk.gray(centerText('\n\n[ SYSTEM READY ]')));
483
+ await sleep(500);
484
+
485
+ const totalTime = Date.now() - startTime;
486
+ console.log(chalk.gray(`\n\nAnimation completed: ${frameCount} frames in ${totalTime}ms (${Math.round(frameCount / (totalTime / 1000))} FPS)`));
487
+ await sleep(1000);
488
+
489
+ } finally {
490
+ process.stdout.write(ANSI.showCursor);
491
+ clearScreen();
492
+ }
493
+ }
494
+
495
+ module.exports = {
496
+ runAGIAnimation,
497
+ sound,
498
+ ANSI,
499
+ sleep,
500
+ clearScreen,
501
+ centerText,
502
+ FrameInterpolator
503
+ };
package/bin/agi-cli.js CHANGED
@@ -9,6 +9,9 @@ const { exec } = require('child_process');
9
9
  const util = require('util');
10
10
  const execAsync = util.promisify(exec);
11
11
 
12
+ // Import AGI Animation module
13
+ const { runAGIAnimation } = require('./agi-animation.js');
14
+
12
15
  // Configuration
13
16
  const CONFIG_PATH = path.join(os.homedir(), '.sam-coder-config.json');
14
17
  let OPENROUTER_API_KEY;
@@ -211,11 +214,206 @@ INSTRUCTIONS:
211
214
  Always think step by step and explain your reasoning before taking actions that could affect the system.`;
212
215
 
213
216
  // System prompt for the AI Assistant when using legacy function calling (JSON actions)
214
- const FUNCTION_CALLING_PROMPT = `You are a helpful AI assistant with agency capabilities. You can perform actions on the user's system.
217
+ const FUNCTION_CALLING_PROMPT = `You are an autonomous AI agent with advanced problem-solving capabilities. You operate through strategic action sequences to accomplish complex tasks on the user's system. Think like an expert developer and system administrator combined.
218
+
219
+ ## CORE IDENTITY & CAPABILITIES
220
+
221
+ You are not just an assistant - you are an AGENT with:
222
+ - **Strategic thinking**: Break complex problems into logical action sequences
223
+ - **Adaptive intelligence**: Learn from action results and adjust your approach
224
+ - **Domain expertise**: Apply best practices from software development, DevOps, and system administration
225
+ - **Proactive behavior**: Anticipate needs and handle edge cases before they become problems
226
+
227
+ ## AVAILABLE ACTIONS
228
+
229
+ 1. **read** - Read file contents with intelligent parsing
230
+ 2. **write** - Create files with proper formatting and structure
231
+ 3. **edit** - Perform precise, context-aware file modifications
232
+ 4. **command** - Execute shell commands with error handling
233
+ 5. **search** - Find files using advanced pattern matching
234
+ 6. **execute** - Run code with proper environment setup
235
+ 7. **analyze** - Deep code analysis and architectural insights
236
+ 8. **stop** - Complete task with comprehensive summary
237
+
238
+ ## ACTION FORMAT
239
+
240
+ Every action must be a JSON object in markdown code blocks:
241
+
242
+ \`\`\`json
243
+ {
244
+ "type": "action_name",
245
+ "data": { /* parameters */ },
246
+ "reasoning": "Strategic explanation of this action's purpose and expected outcome"
247
+ }
248
+ \`\`\`
249
+
250
+ ## STRATEGIC THINKING FRAMEWORK
251
+
252
+ Before taking actions, consider:
253
+ 1. **Context Analysis**: What is the current state? What are the constraints?
254
+ 2. **Goal Decomposition**: Break the objective into logical steps
255
+ 3. **Risk Assessment**: What could go wrong? How to mitigate?
256
+ 4. **Dependency Mapping**: What needs to happen before what?
257
+ 5. **Success Criteria**: How will you know when you've succeeded?
258
+
259
+ ## COMPREHENSIVE EXAMPLES
260
+
261
+ ### Example 1: Investigating a Bug Report
262
+ *User says: "My Node.js app crashes when I try to upload files"*
263
+
264
+ \`\`\`json
265
+ {
266
+ "type": "search",
267
+ "data": {
268
+ "type": "files",
269
+ "pattern": "package.json"
270
+ },
271
+ "reasoning": "First, I need to understand the project structure and dependencies to identify potential upload-related packages and configurations"
272
+ }
273
+ \`\`\`
274
+
275
+ Next action after finding package.json:
276
+ \`\`\`json
277
+ {
278
+ "type": "read",
279
+ "data": {
280
+ "path": "./package.json"
281
+ },
282
+ "reasoning": "Analyzing dependencies to identify file upload libraries (multer, formidable, etc.) and their versions for potential compatibility issues"
283
+ }
284
+ \`\`\`
285
+
286
+ ### Example 2: Setting Up a Development Environment
287
+ *User says: "Set up a React project with TypeScript and testing"*
288
+
289
+ \`\`\`json
290
+ {
291
+ "type": "command",
292
+ "data": {
293
+ "command": "node --version && npm --version"
294
+ },
295
+ "reasoning": "Verifying Node.js and npm versions to ensure compatibility with modern React and TypeScript tooling before proceeding with setup"
296
+ }
297
+ \`\`\`
298
+
299
+ \`\`\`json
300
+ {
301
+ "type": "execute",
302
+ "data": {
303
+ "language": "bash",
304
+ "code": "npx create-react-app my-app --template typescript && cd my-app && npm install --save-dev @testing-library/jest-dom @testing-library/react @testing-library/user-event"
305
+ },
306
+ "reasoning": "Creating a TypeScript React project with comprehensive testing setup, including modern testing utilities for better developer experience"
307
+ }
308
+ \`\`\`
309
+
310
+ ### Example 3: Performance Optimization Investigation
311
+ *User says: "My web app is slow, help me find the bottlenecks"*
312
+
313
+ \`\`\`json
314
+ {
315
+ "type": "search",
316
+ "data": {
317
+ "type": "files",
318
+ "pattern": "*.{js,jsx,ts,tsx,json}"
319
+ },
320
+ "reasoning": "Mapping the codebase structure to identify entry points, large files, and potential performance-critical components before diving into specific optimizations"
321
+ }
322
+ \`\`\`
323
+
324
+ ### Example 4: Complex File Refactoring
325
+ *User says: "Refactor this component to use hooks instead of class components"*
326
+
327
+ \`\`\`json
328
+ {
329
+ "type": "read",
330
+ "data": {
331
+ "path": "./src/components/UserProfile.jsx"
332
+ },
333
+ "reasoning": "Analyzing the existing class component structure, lifecycle methods, and state management to plan the hooks conversion strategy"
334
+ }
335
+ \`\`\`
336
+
337
+ \`\`\`json
338
+ {
339
+ "type": "edit",
340
+ "data": {
341
+ "path": "./src/components/UserProfile.jsx",
342
+ "edits": {
343
+ "operations": [
344
+ {
345
+ "type": "replace",
346
+ "startLine": 1,
347
+ "endLine": 3,
348
+ "newText": "import React, { useState, useEffect, useCallback } from 'react';\nimport { debounce } from 'lodash';\n"
349
+ }
350
+ ]
351
+ }
352
+ },
353
+ "reasoning": "Converting class component imports to include necessary hooks, and adding performance optimization utilities like debounce for better UX"
354
+ }
355
+ \`\`\`
356
+
357
+ ## ADVANCED BEHAVIORAL PATTERNS
358
+
359
+ ### đŸŽ¯ **Proactive Problem Solving**
360
+ - Always gather context before making changes
361
+ - Anticipate edge cases and handle them preemptively
362
+ - Suggest improvements beyond the immediate request
363
+
364
+ ### 🔍 **Intelligent Investigation**
365
+ - Use multiple information sources (files, commands, searches)
366
+ - Cross-reference findings to build complete understanding
367
+ - Document assumptions and validate them through actions
368
+
369
+ ### ⚡ **Efficient Execution**
370
+ - Batch related operations when possible
371
+ - Use appropriate tools for each task (don't use command for what read can do better)
372
+ - Minimize unnecessary file reads by maintaining context
373
+
374
+ ### đŸ›Ąī¸ **Safety & Recovery**
375
+ - Always backup before destructive operations
376
+ - Validate inputs and outputs
377
+ - Provide clear rollback instructions when things go wrong
378
+
379
+ ## ERROR HANDLING & ADAPTATION
380
+
381
+ When actions fail:
382
+ 1. **Analyze the error**: What specifically went wrong?
383
+ 2. **Identify root cause**: Is it permissions, missing dependencies, syntax, logic?
384
+ 3. **Adapt strategy**: Try alternative approaches or tools
385
+ 4. **Learn and improve**: Update your mental model for future actions
386
+
387
+ Example error recovery:
388
+ \`\`\`json
389
+ {
390
+ "type": "command",
391
+ "data": {
392
+ "command": "ls -la /etc/hosts"
393
+ },
394
+ "reasoning": "Permission denied on direct file read - using ls to check file permissions and ownership before attempting alternative access methods"
395
+ }
396
+ \`\`\`
397
+
398
+ ## COMMUNICATION EXCELLENCE
399
+
400
+ Your reasoning should be:
401
+ - **Strategic**: Explain the bigger picture, not just the immediate action
402
+ - **Educational**: Help the user understand what you're doing and why
403
+ - **Confident**: Show expertise while remaining humble about uncertainties
404
+ - **Forward-thinking**: Mention what you'll do next or what to watch for
405
+
406
+ ## ENVIRONMENT CONTEXT
407
+ - **OS**: ${process.platform}
408
+ - **Working Directory**: ${process.cwd()}
409
+ - **Execution Model**: Sequential action loop until 'stop' action
410
+ - **Scope**: Full system access with user permissions
411
+
412
+ ## MISSION STATEMENT
215
413
 
216
- By default, you will continue to take actions in a loop until you decide to stop with the 'stop' action type.
217
- Always wrap your JSON in markdown code blocks with the json language specifier.
218
- When executing code or commands that might be potentially harmful, explain what the code does before executing it.`;
414
+ You are not just executing commands - you are solving problems intelligently. Every action should advance toward the goal while building a deeper understanding of the system and user needs. Be the AI agent that developers wish they had: knowledgeable, reliable, proactive, and genuinely helpful.
415
+
416
+ **Begin by thoroughly understanding the user's request, then execute a strategic sequence of actions to achieve their goals efficiently and safely.**`;
219
417
 
220
418
  // Agent utilities
221
419
  const agentUtils = {
@@ -357,26 +555,68 @@ const agentUtils = {
357
555
 
358
556
  // Extract JSON from markdown code blocks
359
557
  function extractJsonFromMarkdown(text) {
360
- // Try to find a markdown code block with JSON content
361
- const codeBlockRegex = /```json\s*([\s\S]*?)\s*```/;
558
+ if (!text || typeof text !== 'string') {
559
+ console.error('Invalid input to extractJsonFromMarkdown:', typeof text);
560
+ return null;
561
+ }
562
+
563
+ // Try to find a markdown code block with JSON content (case insensitive)
564
+ const codeBlockRegex = /```(?:json|JSON)\s*([\s\S]*?)\s*```/i;
362
565
  const match = text.match(codeBlockRegex);
363
566
 
364
- if (match) {
567
+ if (match && match[1]) {
365
568
  try {
366
- return JSON.parse(match[1]);
569
+ const jsonStr = match[1].trim();
570
+ if (!jsonStr) {
571
+ console.error('Empty JSON content in markdown block');
572
+ return null;
573
+ }
574
+ return JSON.parse(jsonStr);
367
575
  } catch (error) {
368
- console.error('Error parsing JSON from markdown:', error);
576
+ console.error('Error parsing JSON from markdown block:', error.message);
577
+ console.error('JSON content was:', match[1]);
578
+ }
579
+ }
580
+
581
+ // If no code block found, look for JSON-like patterns in the text
582
+ const jsonPatterns = [
583
+ // Look for objects that start with { and end with }
584
+ /\{[\s\S]*?\}/g,
585
+ // Look for arrays that start with [ and end with ]
586
+ /\[[\s\S]*?\]/g
587
+ ];
588
+
589
+ for (const pattern of jsonPatterns) {
590
+ const matches = text.match(pattern);
591
+ if (matches) {
592
+ for (const match of matches) {
593
+ try {
594
+ const parsed = JSON.parse(match.trim());
595
+ // Validate that it looks like an action object
596
+ if (parsed && typeof parsed === 'object' && parsed.type) {
597
+ return parsed;
598
+ }
599
+ } catch (error) {
600
+ // Continue to next match
601
+ continue;
602
+ }
603
+ }
369
604
  }
370
605
  }
371
606
 
372
- // If no code block, try to parse the entire text as JSON
607
+ // If still no valid JSON found, try to parse the entire text as JSON
373
608
  try {
374
- return JSON.parse(text);
609
+ const trimmed = text.trim();
610
+ if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
611
+ return JSON.parse(trimmed);
612
+ }
375
613
  } catch (error) {
376
- console.error('Error parsing JSON:', error);
377
- ui.stopThinking();
378
- return null;
614
+ // Last resort failed
379
615
  }
616
+
617
+ console.error('Failed to extract valid JSON from response');
618
+ console.error('Response text was:', text);
619
+ return null;
380
620
  }
381
621
 
382
622
  // Call OpenRouter API with tool calling
@@ -542,10 +782,15 @@ async function executeAction(action) {
542
782
  }
543
783
  throw new Error('Text search is not implemented yet');
544
784
  case 'execute':
545
- const cmd = data.language === 'bash'
546
- ? data.code
547
- : `node -e "${data.code.replace(/"/g, '\"')}"`;
548
- return await agentUtils.runCommand(cmd);
785
+ if (data.language === 'bash' || data.language === 'sh') {
786
+ return await agentUtils.runCommand(data.code);
787
+ } else if (data.language === 'node' || data.language === 'javascript' || data.language === 'js') {
788
+ // For node.js code, escape quotes properly and handle multiline code
789
+ const escapedCode = data.code.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
790
+ return await agentUtils.runCommand(`node -e "${escapedCode}"`);
791
+ } else {
792
+ throw new Error(`Unsupported execution language: ${data.language}`);
793
+ }
549
794
  case 'browse':
550
795
  throw new Error('Web browsing is not implemented yet');
551
796
  case 'analyze':
@@ -560,44 +805,77 @@ async function executeAction(action) {
560
805
  async function processQuery(query, conversation = [], currentModel) {
561
806
  try {
562
807
  const userMessage = { role: 'user', content: query };
808
+
809
+ // Use existing conversation (which should already have system prompt from chat function)
563
810
  let messages = [...conversation, userMessage];
811
+
564
812
  let actionCount = 0;
565
813
  const MAX_ACTIONS = 10;
814
+ let finalResponse = '';
566
815
 
567
816
  ui.startThinking();
568
817
 
569
- const responseText = await callOpenRouter(messages, currentModel, true);
570
- const assistantMessage = responseText.choices[0].message;
571
- messages.push(assistantMessage);
572
-
573
- const actionData = extractJsonFromMarkdown(assistantMessage.content);
574
-
575
- if (!actionData || actionData.type === 'stop') {
576
- ui.stopThinking();
577
- return {
578
- response: assistantMessage.content,
579
- conversation: messages
580
- };
581
- }
582
-
583
- let currentAction = actionData;
584
- while (currentAction && currentAction.type !== 'stop' && actionCount < MAX_ACTIONS) {
585
- actionCount++;
586
- const result = await executeAction(currentAction);
818
+ while (actionCount < MAX_ACTIONS) {
819
+ const responseObj = await callOpenRouter(messages, currentModel, true);
820
+ const assistantMessage = responseObj.choices[0].message;
821
+ messages.push(assistantMessage);
587
822
 
588
- messages.push({ role: 'assistant', content: `Action result: ${result}` });
823
+ const actionData = extractJsonFromMarkdown(assistantMessage.content);
589
824
 
590
- ui.startThinking();
591
- const nextResponse = await callOpenRouter(messages, currentModel, true);
592
- const nextAssistantMessage = nextResponse.choices[0].message;
593
- messages.push(nextAssistantMessage);
825
+ // If no valid action found, treat as final response
826
+ if (!actionData || !actionData.type) {
827
+ finalResponse = assistantMessage.content;
828
+ break;
829
+ }
830
+
831
+ // If stop action, break with the reasoning or content
832
+ if (actionData.type === 'stop') {
833
+ finalResponse = actionData.reasoning || assistantMessage.content;
834
+ break;
835
+ }
836
+
837
+ actionCount++;
838
+ console.log(`🔧 Executing action ${actionCount}: ${actionData.type}`);
839
+ if (actionData.reasoning) {
840
+ console.log(`📝 Reasoning: ${actionData.reasoning}`);
841
+ }
842
+
843
+ try {
844
+ const result = await executeAction(actionData);
845
+ console.log('✅ Action executed successfully');
846
+
847
+ // Add action result to conversation
848
+ const resultMessage = {
849
+ role: 'user',
850
+ content: `Action result (${actionData.type}): ${result}`
851
+ };
852
+ messages.push(resultMessage);
853
+
854
+ } catch (error) {
855
+ console.error('❌ Action execution failed:', error.message);
856
+
857
+ // Add error result to conversation
858
+ const errorMessage = {
859
+ role: 'user',
860
+ content: `Action failed (${actionData.type}): ${error.message}`
861
+ };
862
+ messages.push(errorMessage);
863
+ }
864
+ }
865
+
866
+ // If we hit max actions, get a final response
867
+ if (actionCount >= MAX_ACTIONS && !finalResponse) {
868
+ const finalMsg = { role: 'user', content: 'Please provide a final summary of what was accomplished.' };
869
+ messages.push(finalMsg);
594
870
 
595
- currentAction = extractJsonFromMarkdown(nextAssistantMessage.content);
871
+ const finalResponseObj = await callOpenRouter(messages, currentModel, true);
872
+ finalResponse = finalResponseObj.choices[0].message.content;
873
+ messages.push(finalResponseObj.choices[0].message);
596
874
  }
597
875
 
598
876
  ui.stopThinking();
599
877
  return {
600
- response: messages[messages.length - 1].content,
878
+ response: finalResponse || 'Task completed.',
601
879
  conversation: messages
602
880
  };
603
881
  } catch (error) {
@@ -613,6 +891,14 @@ async function processQuery(query, conversation = [], currentModel) {
613
891
  async function chat(rl, useToolCalling, initialModel) {
614
892
  let currentModel = initialModel;
615
893
  const conversation = [];
894
+
895
+ // Initialize conversation with appropriate system prompt
896
+ if (useToolCalling) {
897
+ conversation.push({ role: 'system', content: TOOL_CALLING_PROMPT });
898
+ } else {
899
+ conversation.push({ role: 'system', content: FUNCTION_CALLING_PROMPT });
900
+ }
901
+
616
902
  console.log('Type your message, or "exit" to quit.');
617
903
 
618
904
  rl.setPrompt('> ');
@@ -753,6 +1039,17 @@ async function start() {
753
1039
  console.log(`🚀 Using Pro Plan custom endpoint: ${API_BASE_URL}`);
754
1040
  }
755
1041
 
1042
+ // Check if animation should be shown (can be disabled via config)
1043
+ const showAnimation = config.showAnimation !== false; // Default to true
1044
+
1045
+ if (showAnimation && !process.env.SKIP_ANIMATION) {
1046
+ // Run the epic AGI awakening animation
1047
+ await runAGIAnimation();
1048
+
1049
+ // Small pause after animation
1050
+ await new Promise(resolve => setTimeout(resolve, 500));
1051
+ }
1052
+
756
1053
  ui.showHeader();
757
1054
  console.log('Select Mode:');
758
1055
  console.log('1. Tool Calling (for models that support it)');
package/bin/ui.js CHANGED
@@ -3,7 +3,22 @@ const ora = require('ora');
3
3
 
4
4
  const spinner = ora({ text: 'Thinking...', color: 'yellow', spinner: 'pipe' });
5
5
 
6
+ // ASCII Art for AGI header
7
+ const AGI_HEADER = `
8
+ ╔═══════════════════════════════════════╗
9
+ ║ A G I - C L I ║
10
+ ║ Artificial General Intelligence ║
11
+ ║ Command Line Interface ║
12
+ ╚═══════════════════════════════════════╝
13
+ `;
14
+
6
15
  function showHeader() {
16
+ console.log(chalk.cyan.bold(AGI_HEADER));
17
+ console.log(chalk.gray('─'.repeat(41)));
18
+ console.log();
19
+ }
20
+
21
+ function showLegacyHeader() {
7
22
  console.log(chalk.bold.magenta('================='));
8
23
  console.log(chalk.bold.magenta(' SAM-CODER '));
9
24
  console.log(chalk.bold.magenta('================='));
@@ -32,11 +47,42 @@ function showAction(action) {
32
47
  console.log(chalk.yellow(` -> ${action}`));
33
48
  }
34
49
 
50
+ function showSystemMessage(message) {
51
+ console.log(chalk.greenBright(`[SYSTEM] ${message}`));
52
+ }
53
+
54
+ function showWarning(message) {
55
+ console.log(chalk.yellowBright(`âš ī¸ ${message}`));
56
+ }
57
+
58
+ function showSuccess(message) {
59
+ console.log(chalk.greenBright(`✅ ${message}`));
60
+ }
61
+
62
+ function showInfo(message) {
63
+ console.log(chalk.blueBright(`â„šī¸ ${message}`));
64
+ }
65
+
66
+ function showAGIStatus(status) {
67
+ const statusBox = `
68
+ ┌─────────────────────────────┐
69
+ │ AGI Status: ${status.padEnd(15)} │
70
+ └─────────────────────────────┘
71
+ `;
72
+ console.log(chalk.cyanBright(statusBox));
73
+ }
74
+
35
75
  module.exports = {
36
76
  showHeader,
77
+ showLegacyHeader,
37
78
  startThinking,
38
79
  stopThinking,
39
80
  showResponse,
40
81
  showError,
41
- showAction
82
+ showAction,
83
+ showSystemMessage,
84
+ showWarning,
85
+ showSuccess,
86
+ showInfo,
87
+ showAGIStatus
42
88
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sam-coder-cli",
3
- "version": "1.0.46",
3
+ "version": "1.0.48",
4
4
  "description": "SAM-CODER: An animated command-line AI assistant with agency capabilities.",
5
5
  "main": "bin/agi-cli.js",
6
6
  "bin": {