sam-coder-cli 1.0.48 → 1.0.49

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.
Files changed (2) hide show
  1. package/bin/agi-animation.js +393 -140
  2. package/package.json +3 -2
@@ -9,6 +9,7 @@ const ANSI = {
9
9
  showCursor: '\x1B[?25h',
10
10
  moveTo: (x, y) => `\x1B[${y};${x}H`,
11
11
  clearLine: '\x1B[2K',
12
+ clearScreen: '\x1B[2J\x1B[0;0H',
12
13
  reset: '\x1B[0m',
13
14
  bold: '\x1B[1m',
14
15
  dim: '\x1B[2m',
@@ -16,7 +17,9 @@ const ANSI = {
16
17
  underline: '\x1B[4m',
17
18
  blink: '\x1B[5m',
18
19
  reverse: '\x1B[7m',
19
- strikethrough: '\x1B[9m'
20
+ strikethrough: '\x1B[9m',
21
+ saveCursor: '\x1B[s',
22
+ restoreCursor: '\x1B[u'
20
23
  };
21
24
 
22
25
  // Music/Sound generation using system beeps and terminal bells
@@ -25,17 +28,30 @@ class SoundGenerator {
25
28
  this.isWindows = os.platform() === 'win32';
26
29
  this.isMac = os.platform() === 'darwin';
27
30
  this.isLinux = os.platform() === 'linux';
31
+ this.soundEnabled = true;
28
32
  }
29
33
 
30
34
  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');
35
+ if (!this.soundEnabled) return;
36
+
37
+ try {
38
+ return new Promise((resolve) => {
39
+ if (this.isWindows) {
40
+ exec(`powershell -c "[console]::beep(${frequency},${duration})"`, { stdio: 'ignore' }, () => resolve());
41
+ } else if (this.isMac) {
42
+ exec(`osascript -e 'beep'`, { stdio: 'ignore' }, () => resolve());
43
+ } else if (this.isLinux) {
44
+ exec(`beep -f ${frequency} -l ${duration} 2>/dev/null || echo -e '\\a'`, { stdio: 'ignore' }, () => resolve());
45
+ } else {
46
+ process.stdout.write('\x07');
47
+ resolve();
48
+ }
49
+ // Fallback timeout
50
+ setTimeout(resolve, duration + 50);
51
+ });
52
+ } catch (error) {
53
+ // Silently fail for sound issues
54
+ this.soundEnabled = false;
39
55
  }
40
56
  }
41
57
 
@@ -83,22 +99,42 @@ function sleep(ms) {
83
99
  }
84
100
 
85
101
  function clearScreen() {
86
- process.stdout.write(ANSI.clear);
102
+ // Use more reliable screen clearing
103
+ process.stdout.write(ANSI.clearScreen);
87
104
  }
88
105
 
89
- function centerText(text, width = process.stdout.columns || 80) {
106
+ function getTerminalSize() {
107
+ return {
108
+ width: process.stdout.columns || 80,
109
+ height: process.stdout.rows || 24
110
+ };
111
+ }
112
+
113
+ function centerText(text, width = getTerminalSize().width) {
114
+ if (!text) return '';
90
115
  const lines = text.split('\n');
91
116
  return lines.map(line => {
92
- const padding = Math.max(0, Math.floor((width - line.length) / 2));
117
+ // Strip ANSI codes to calculate actual text length
118
+ const cleanLine = line.replace(/\x1b\[[0-9;]*m/g, '');
119
+ const padding = Math.max(0, Math.floor((width - cleanLine.length) / 2));
93
120
  return ' '.repeat(padding) + line;
94
121
  }).join('\n');
95
122
  }
96
123
 
124
+ function safeWrite(content) {
125
+ try {
126
+ process.stdout.write(content);
127
+ } catch (error) {
128
+ // Fallback for terminal issues
129
+ console.log(content);
130
+ }
131
+ }
132
+
97
133
  // Frame interpolation system
98
134
  class FrameInterpolator {
99
135
  constructor() {
100
- this.fps = 25;
101
- this.frameDuration = 1000 / this.fps; // 40ms per frame
136
+ this.fps = 30;
137
+ this.frameDuration = 1000 / this.fps; // ~33ms per frame for smoother animation
102
138
  }
103
139
 
104
140
  // Interpolate between two ASCII art frames
@@ -211,66 +247,96 @@ class FrameInterpolator {
211
247
 
212
248
  const interpolator = new FrameInterpolator();
213
249
 
214
- // Animation sequence with 25 FPS
250
+ // Animation sequence with 30 FPS
215
251
  async function runAGIAnimation() {
252
+ const { width, height } = getTerminalSize();
216
253
  process.stdout.write(ANSI.hideCursor);
217
254
 
218
255
  try {
219
256
  const startTime = Date.now();
220
257
  let frameCount = 0;
258
+ const frameTime = interpolator.frameDuration;
221
259
 
222
- // Start with ambient sound
223
- sound.playStartupSound();
260
+ // Start with ambient sound (non-blocking)
261
+ sound.playStartupSound().catch(() => {}); // Ignore sound errors
224
262
 
225
- // PHASE 1: The Void (1 second - 25 frames)
263
+ // PHASE 1: The Void (1 second - 30 frames)
226
264
  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`);
265
+ for (let i = 0; i < 30; i++) {
266
+ const dotCount = (i % 4) + 1;
267
+ const dots = ''.repeat(dotCount) + ' '.repeat(4 - dotCount);
268
+ const frame = '\n'.repeat(Math.floor(height / 2) - 2) +
269
+ centerText(dots) +
270
+ '\n'.repeat(Math.floor(height / 2) - 2);
271
+ voidFrames.push(frame);
231
272
  }
232
273
 
233
274
  for (const frame of voidFrames) {
234
275
  clearScreen();
235
- console.log(chalk.gray(frame));
236
- await sleep(40);
276
+ safeWrite(chalk.dim.gray(frame));
277
+ await sleep(frameTime);
237
278
  frameCount++;
238
279
  }
239
280
 
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);
281
+ // PHASE 2: Spark Formation (1 second - 30 frames)
282
+ const sparkFrames = [];
283
+ for (let i = 0; i < 30; i++) {
284
+ const progress = i / 29;
285
+ const intensity = Math.sin(progress * Math.PI * 2) * 0.5 + 0.5;
286
+
287
+ let sparkPattern;
288
+ if (progress < 0.3) {
289
+ sparkPattern = '·';
290
+ } else if (progress < 0.6) {
291
+ sparkPattern = ` ·\n ·•·\n ·`;
292
+ } else {
293
+ const core = intensity > 0.7 ? '█' : '●';
294
+ sparkPattern = ` · · ·\n· ·${core}· ·\n · · ·`;
295
+ }
296
+
297
+ const frame = '\n'.repeat(Math.floor(height / 2) - 3) +
298
+ centerText(sparkPattern) +
299
+ '\n'.repeat(Math.floor(height / 2) - 3);
300
+ sparkFrames.push(frame);
301
+ }
252
302
 
253
303
  for (const frame of sparkFrames) {
254
304
  clearScreen();
255
- console.log(chalk.white(centerText(frame)));
256
- await sleep(40);
305
+ safeWrite(chalk.white.bright(frame));
306
+ await sleep(frameTime);
257
307
  frameCount++;
258
308
  }
259
309
 
260
- // PHASE 3: Quantum Expansion (1.5 seconds - 37 frames)
310
+ // PHASE 3: Quantum Expansion (1.5 seconds - 45 frames)
261
311
  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';
312
+ const quantumChars = ['◆', '◇', '▪', '▫', '●', '○', '◊', '◉'];
313
+
314
+ for (let i = 0; i < 45; i++) {
315
+ const progress = i / 44;
316
+ const phase = progress * Math.PI * 4;
317
+ const baseSize = 2 + progress * 4;
318
+ const pulseSize = baseSize + Math.sin(phase * 2) * 1.5;
319
+
320
+ let frame = '\n'.repeat(Math.floor(height / 2) - Math.floor(pulseSize) - 2);
266
321
 
267
- for (let y = -size; y <= size; y++) {
322
+ for (let y = -Math.floor(pulseSize); y <= Math.floor(pulseSize); y++) {
268
323
  let line = '';
269
- for (let x = -size * 2; x <= size * 2; x++) {
324
+ for (let x = -Math.floor(pulseSize * 1.5); x <= Math.floor(pulseSize * 1.5); x++) {
270
325
  const dist = Math.sqrt(x * x + y * y);
271
- if (dist < size) {
272
- const chars = ['◆', '◇', '▪', '▫', '●', '○'];
273
- line += chars[Math.floor(Math.random() * chars.length)];
326
+ const normalizedDist = dist / pulseSize;
327
+
328
+ if (normalizedDist <= 1) {
329
+ // Use consistent pattern based on position and time
330
+ const charIndex = (Math.floor(x + y + i * 0.5)) % quantumChars.length;
331
+ const char = quantumChars[Math.abs(charIndex)];
332
+
333
+ // Add wave effect
334
+ const wave = Math.sin(dist * 0.5 + phase) * 0.5 + 0.5;
335
+ if (wave > 0.3) {
336
+ line += char;
337
+ } else {
338
+ line += '·';
339
+ }
274
340
  } else {
275
341
  line += ' ';
276
342
  }
@@ -281,45 +347,81 @@ async function runAGIAnimation() {
281
347
  quantumFrames.push(frame);
282
348
  }
283
349
 
284
- for (const frame of quantumFrames) {
350
+ for (let i = 0; i < quantumFrames.length; i++) {
285
351
  clearScreen();
286
- const colors = [chalk.blue, chalk.cyan, chalk.magenta];
287
- console.log(colors[frameCount % colors.length](frame));
288
- await sleep(40);
352
+ const colorCycle = i / 15; // Slower color cycling
353
+ let color;
354
+ if (colorCycle < 1) {
355
+ color = chalk.blue;
356
+ } else if (colorCycle < 2) {
357
+ color = chalk.cyan;
358
+ } else {
359
+ color = chalk.magenta;
360
+ }
361
+
362
+ safeWrite(color(quantumFrames[i]));
363
+ await sleep(frameTime);
289
364
  frameCount++;
290
365
  }
291
366
 
292
- // PHASE 4: Neural Network Formation (1.5 seconds - 37 frames)
367
+ // PHASE 4: Neural Network Formation (1.5 seconds - 45 frames)
293
368
  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;
369
+ const nodes = 6;
370
+ const layers = 4;
371
+
372
+ // Play glitch sound (non-blocking)
373
+ sound.playGlitchSound().catch(() => {});
374
+
375
+ for (let i = 0; i < 45; i++) {
376
+ const progress = i / 44;
377
+ let frame = '\n'.repeat(Math.floor(height / 2) - layers * 2);
300
378
 
301
379
  for (let layer = 0; layer < layers; layer++) {
302
380
  let line = '';
381
+ const layerProgress = Math.max(0, (progress - layer * 0.2) * 2);
382
+
303
383
  for (let node = 0; node < nodes; node++) {
304
- if (Math.random() < progress) {
305
- line += layer % 2 === 0 ? '◯' : '◉';
384
+ const nodeProgress = Math.max(0, (layerProgress - node * 0.1) * 3);
385
+
386
+ if (nodeProgress > 0.5) {
387
+ // Animate node activation
388
+ const activation = Math.sin(i * 0.3 + layer + node) * 0.5 + 0.5;
389
+ if (activation > 0.7) {
390
+ line += chalk.cyan.bright('◉');
391
+ } else if (activation > 0.3) {
392
+ line += chalk.cyan('◯');
393
+ } else {
394
+ line += chalk.dim('○');
395
+ }
306
396
  } else {
307
397
  line += '·';
308
398
  }
309
- if (node < nodes - 1) line += '━━━';
399
+
400
+ if (node < nodes - 1) {
401
+ // Animate connections
402
+ const connProgress = Math.max(0, (layerProgress - (node + 0.5) * 0.1) * 3);
403
+ if (connProgress > 0.5) {
404
+ const pulse = Math.sin(i * 0.4 + layer + node) > 0;
405
+ line += pulse ? chalk.cyan('━━') : chalk.dim('──');
406
+ } else {
407
+ line += ' ';
408
+ }
409
+ }
310
410
  }
311
411
  frame += centerText(line) + '\n';
312
412
 
313
413
  if (layer < layers - 1) {
314
- // Connection lines
414
+ // Vertical connection lines
315
415
  let connLine = '';
316
416
  for (let node = 0; node < nodes; node++) {
317
- if (Math.random() < progress) {
318
- connLine += node % 2 === 0 ? '┃' : '│';
417
+ const nodeProgress = Math.max(0, (layerProgress - node * 0.1) * 3);
418
+ if (nodeProgress > 0.5) {
419
+ const pulse = Math.sin(i * 0.2 + layer + node) > 0;
420
+ connLine += pulse ? chalk.cyan('┃') : chalk.dim('│');
319
421
  } else {
320
422
  connLine += ' ';
321
423
  }
322
- if (node < nodes - 1) connLine += ' ';
424
+ if (node < nodes - 1) connLine += ' ';
323
425
  }
324
426
  frame += centerText(connLine) + '\n';
325
427
  }
@@ -328,31 +430,46 @@ async function runAGIAnimation() {
328
430
  neuralFrames.push(frame);
329
431
  }
330
432
 
331
- // Play glitch sound
332
- sound.playGlitchSound();
333
-
334
433
  for (const frame of neuralFrames) {
335
434
  clearScreen();
336
- console.log(chalk.cyan(frame));
337
- await sleep(40);
435
+ safeWrite(frame);
436
+ await sleep(frameTime);
338
437
  frameCount++;
339
438
  }
340
439
 
341
- // PHASE 5: Data Stream (1 second - 25 frames)
440
+ // PHASE 5: Data Stream (1 second - 30 frames)
342
441
  const dataFrames = [];
343
- for (let i = 0; i < 25; i++) {
344
- let frame = '\n\n';
345
- const height = 10;
442
+ const streamHeight = Math.min(12, Math.floor(height * 0.4));
443
+ const streamWidth = Math.min(60, Math.floor(width * 0.7));
444
+
445
+ for (let i = 0; i < 30; i++) {
446
+ let frame = '\n'.repeat(Math.floor((height - streamHeight) / 2));
346
447
 
347
- for (let y = 0; y < height; y++) {
448
+ for (let y = 0; y < streamHeight; y++) {
348
449
  let line = '';
349
- const width = 40;
350
450
 
351
- for (let x = 0; x < width; x++) {
352
- if ((x + i) % 8 < 4) {
353
- line += Math.random() > 0.5 ? '1' : '0';
451
+ for (let x = 0; x < streamWidth; x++) {
452
+ // Create flowing data pattern
453
+ const wave1 = Math.sin((x + i * 2) * 0.1) * 0.5 + 0.5;
454
+ const wave2 = Math.cos((y + i * 1.5) * 0.15) * 0.5 + 0.5;
455
+ const combined = wave1 * wave2;
456
+
457
+ if (combined > 0.7) {
458
+ // Binary data
459
+ const bit = ((x + y + i) % 7) < 3 ? '1' : '0';
460
+ line += chalk.green.bright(bit);
461
+ } else if (combined > 0.4) {
462
+ // Block characters
463
+ const blocks = ['█', '▓', '▒', '░'];
464
+ const blockIndex = ((x + y + i) % blocks.length);
465
+ line += chalk.green(blocks[blockIndex]);
466
+ } else if (combined > 0.2) {
467
+ // Hexadecimal
468
+ const hex = '0123456789ABCDEF';
469
+ const hexChar = hex[((x * 7 + y * 3 + i) % hex.length)];
470
+ line += chalk.green.dim(hexChar);
354
471
  } else {
355
- line += Math.random() > 0.5 ? '█' : '░';
472
+ line += ' ';
356
473
  }
357
474
  }
358
475
 
@@ -364,126 +481,260 @@ async function runAGIAnimation() {
364
481
 
365
482
  for (const frame of dataFrames) {
366
483
  clearScreen();
367
- console.log(chalk.green(frame));
368
- await sleep(40);
484
+ safeWrite(frame);
485
+ await sleep(frameTime);
369
486
  frameCount++;
370
487
  }
371
488
 
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;
489
+ // PHASE 6: Loading Bar (1 second - 30 frames)
490
+ for (let i = 0; i < 30; i++) {
491
+ const progress = i / 29;
492
+ const barWidth = 38;
376
493
  const filled = Math.floor(barWidth * progress);
377
- const bar = '█'.repeat(filled) + '░'.repeat(barWidth - filled);
494
+ const remaining = barWidth - filled;
495
+
496
+ // Animated loading bar with gradient effect
497
+ let bar = '';
498
+ for (let j = 0; j < filled; j++) {
499
+ const intensity = (j / filled) * 0.7 + 0.3;
500
+ if (intensity > 0.8) {
501
+ bar += chalk.cyan.bright('█');
502
+ } else if (intensity > 0.5) {
503
+ bar += chalk.cyan('█');
504
+ } else {
505
+ bar += chalk.cyan.dim('█');
506
+ }
507
+ }
508
+
509
+ // Add loading cursor
510
+ if (remaining > 0 && i < 29) {
511
+ const cursor = ['▌', '▐'][i % 2];
512
+ bar += chalk.cyan.bright(cursor);
513
+ bar += chalk.gray('░').repeat(remaining - 1);
514
+ } else {
515
+ bar += chalk.gray('░').repeat(remaining);
516
+ }
517
+
378
518
  const percent = Math.floor(progress * 100);
379
519
 
380
- clearScreen();
381
- console.log(chalk.cyan(centerText(`
382
- ╔══════════════════════════════════════════╗
383
- ║ INITIALIZING SAM-CODER ║
384
- ╠══════════════════════════════════════════╣
520
+ const loadingBox = `
521
+ ╔════════════════════════════════════════════╗
522
+ ║ INITIALIZING SAM-CODER ║
523
+ ╠════════════════════════════════════════════╣
385
524
  ║ ${bar} ║
386
- ${percent.toString().padStart(3)}% Complete
387
- ╚══════════════════════════════════════════╝
388
- `)));
525
+ ${percent.toString().padStart(3)}% Complete
526
+ ╚════════════════════════════════════════════╝`;
527
+
528
+ clearScreen();
529
+ safeWrite(chalk.cyan(centerText(loadingBox)));
389
530
 
390
- if (i % 5 === 0) {
391
- sound.playBeep(200 + i * 20, 50);
531
+ if (i % 6 === 0) {
532
+ sound.playBeep(200 + i * 15, 40).catch(() => {});
392
533
  }
393
534
 
394
- await sleep(40);
535
+ await sleep(frameTime);
395
536
  frameCount++;
396
537
  }
397
538
 
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);
539
+ // PHASE 7: Matrix Rain (1 second - 30 frames)
540
+ const matrixChars = '01SAMCODERサムコーダー※◆◇▪▫●○';
541
+ const drops = Array(width).fill(0).map(() => ({
542
+ y: Math.random() * height,
543
+ speed: 0.5 + Math.random() * 1.5,
544
+ chars: Array(15).fill(0).map(() => matrixChars[Math.floor(Math.random() * matrixChars.length)])
545
+ }));
402
546
 
403
- for (let frame = 0; frame < 25; frame++) {
547
+ for (let frame = 0; frame < 30; frame++) {
404
548
  clearScreen();
405
549
 
550
+ // Build frame buffer for better performance
551
+ const frameBuffer = Array(height).fill(0).map(() => Array(width).fill(' '));
552
+
553
+ for (let x = 0; x < width; x++) {
554
+ const drop = drops[x];
555
+
556
+ for (let i = 0; i < 15; i++) {
557
+ const y = Math.floor(drop.y - i);
558
+ if (y >= 0 && y < height) {
559
+ const brightness = Math.max(0, 1 - i / 10);
560
+ const char = drop.chars[i % drop.chars.length];
561
+
562
+ // Store character with brightness info
563
+ frameBuffer[y][x] = { char, brightness };
564
+ }
565
+ }
566
+ }
567
+
568
+ // Render frame buffer
406
569
  for (let y = 0; y < height; y++) {
407
570
  let line = '';
408
571
  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);
572
+ const cell = frameBuffer[y][x];
573
+ if (typeof cell === 'object') {
574
+ if (cell.brightness > 0.8) {
575
+ line += chalk.greenBright(cell.char);
576
+ } else if (cell.brightness > 0.5) {
577
+ line += chalk.green(cell.char);
578
+ } else if (cell.brightness > 0.2) {
579
+ line += chalk.green.dim(cell.char);
418
580
  } else {
419
- line += chalk.gray(char);
581
+ line += chalk.gray(cell.char);
420
582
  }
421
583
  } else {
422
584
  line += ' ';
423
585
  }
424
586
  }
425
- console.log(line);
587
+ safeWrite(line + '\n');
426
588
  }
427
589
 
428
590
  // Update drops
429
591
  for (let i = 0; i < width; i++) {
430
- if (Math.random() > 0.95) drops[i] = 0;
431
- drops[i] += 0.5;
592
+ drops[i].y += drops[i].speed;
593
+ if (drops[i].y > height + 15 || Math.random() > 0.98) {
594
+ drops[i].y = -5;
595
+ drops[i].speed = 0.5 + Math.random() * 1.5;
596
+ // Refresh character set occasionally
597
+ if (Math.random() > 0.7) {
598
+ drops[i].chars = Array(15).fill(0).map(() => matrixChars[Math.floor(Math.random() * matrixChars.length)]);
599
+ }
600
+ }
432
601
  }
433
602
 
434
- await sleep(40);
603
+ await sleep(frameTime);
435
604
  frameCount++;
436
605
  }
437
606
 
438
- // PHASE 8: Final Reveal Build-up (1 second - 25 frames)
607
+ // PHASE 8: Final Reveal Build-up (1 second - 30 frames)
439
608
  const finalText = `
440
609
  ███████╗ █████╗ ███╗ ███╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗
441
610
  ██╔════╝██╔══██╗████╗ ████║ ██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗
442
611
  ███████╗███████║██╔████╔██║█████╗██║ ██║ ██║██║ ██║█████╗ ██████╔╝
443
612
  ╚════██║██╔══██║██║╚██╔╝██║╚════╝██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗
444
613
  ███████║██║ ██║██║ ╚═╝ ██║ ╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║
445
- ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝
446
- `;
614
+ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝`;
447
615
 
448
- const buildFrames = interpolator.expandFrames('█', finalText, 25);
616
+ // Play awakening sound (non-blocking)
617
+ sound.playAwakeningSound().catch(() => {});
618
+
619
+ // Create smoother reveal animation
620
+ const revealFrames = [];
621
+ const lines = finalText.trim().split('\n');
622
+ const maxWidth = Math.max(...lines.map(line => line.length));
623
+ const centerY = Math.floor((height - lines.length) / 2);
449
624
 
450
- // Play awakening sound
451
- sound.playAwakeningSound();
625
+ for (let frame = 0; frame < 30; frame++) {
626
+ const progress = frame / 29;
627
+ let revealFrame = '\n'.repeat(Math.max(0, centerY));
628
+
629
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
630
+ const line = lines[lineIndex];
631
+ const lineProgress = Math.max(0, Math.min(1, (progress - lineIndex * 0.1) * 2));
632
+ const revealWidth = Math.floor(line.length * lineProgress);
633
+
634
+ let revealedLine = '';
635
+ for (let charIndex = 0; charIndex < line.length; charIndex++) {
636
+ if (charIndex < revealWidth) {
637
+ // Add slight randomness to reveal
638
+ if (Math.random() < 0.95 || frame > 25) {
639
+ revealedLine += line[charIndex];
640
+ } else {
641
+ revealedLine += Math.random() > 0.5 ? '▓' : '▒';
642
+ }
643
+ } else {
644
+ revealedLine += ' ';
645
+ }
646
+ }
647
+
648
+ revealFrame += centerText(revealedLine) + '\n';
649
+ }
650
+
651
+ revealFrames.push(revealFrame);
652
+ }
452
653
 
453
- for (const frame of buildFrames) {
654
+ for (const frame of revealFrames) {
454
655
  clearScreen();
455
- console.log(chalk.cyanBright(centerText(frame)));
456
- await sleep(40);
656
+ safeWrite(chalk.cyanBright(frame));
657
+ await sleep(frameTime);
457
658
  frameCount++;
458
659
  }
459
660
 
460
- // PHASE 9: Final Blinking (1.5 seconds - 37 frames)
461
- for (let i = 0; i < 37; i++) {
661
+ // PHASE 9: Final Blinking (1.5 seconds - 45 frames)
662
+ const blinkFrames = 45;
663
+ for (let i = 0; i < blinkFrames; i++) {
462
664
  clearScreen();
463
665
 
464
- // Blink between red and bright red
465
- const isOn = i % 6 < 3;
466
- const color = isOn ? chalk.redBright.bold : chalk.red;
666
+ // More sophisticated blinking pattern
667
+ const blinkCycle = i % 8;
668
+ let color;
669
+
670
+ if (blinkCycle < 2) {
671
+ color = chalk.redBright.bold;
672
+ } else if (blinkCycle < 4) {
673
+ color = chalk.red.bold;
674
+ } else if (blinkCycle < 6) {
675
+ color = chalk.red;
676
+ } else {
677
+ color = chalk.red.dim;
678
+ }
467
679
 
468
- console.log(color(centerText(finalText)));
680
+ // Add subtle glow effect
681
+ const glowIntensity = Math.sin(i * 0.3) * 0.3 + 0.7;
682
+ let finalFrame = '\n'.repeat(Math.max(0, centerY));
469
683
 
470
- // Add subtitle on last few frames
684
+ for (const line of lines) {
685
+ if (glowIntensity > 0.8) {
686
+ finalFrame += centerText(line) + '\n';
687
+ } else {
688
+ // Slightly dim some characters for glow effect
689
+ let glowLine = '';
690
+ for (let j = 0; j < line.length; j++) {
691
+ if (Math.random() < glowIntensity) {
692
+ glowLine += line[j];
693
+ } else {
694
+ glowLine += line[j] === '█' ? '▓' : line[j];
695
+ }
696
+ }
697
+ finalFrame += centerText(glowLine) + '\n';
698
+ }
699
+ }
700
+
701
+ safeWrite(color(finalFrame));
702
+
703
+ // Add subtitle with typewriter effect
471
704
  if (i > 25) {
472
- console.log(chalk.gray(centerText('\n\n[ ARTIFICIAL GENERAL INTELLIGENCE ONLINE ]')));
705
+ const subtitle = '[ ARTIFICIAL GENERAL INTELLIGENCE ONLINE ]';
706
+ const typeProgress = Math.min(subtitle.length, Math.floor((i - 25) * 2.5));
707
+ const typedSubtitle = subtitle.substring(0, typeProgress);
708
+ const cursor = (i % 4 < 2) ? '_' : ' ';
709
+
710
+ safeWrite(chalk.gray(centerText(`\n\n${typedSubtitle}${cursor}`)));
473
711
  }
474
712
 
475
- await sleep(40);
713
+ await sleep(frameTime);
476
714
  frameCount++;
477
715
  }
478
716
 
479
- // Final hold
717
+ // Final hold with status
480
718
  clearScreen();
481
- console.log(chalk.redBright.bold(centerText(finalText)));
482
- console.log(chalk.gray(centerText('\n\n[ SYSTEM READY ]')));
719
+ let finalDisplay = '\n'.repeat(Math.max(0, centerY));
720
+ for (const line of lines) {
721
+ finalDisplay += centerText(line) + '\n';
722
+ }
723
+
724
+ safeWrite(chalk.redBright.bold(finalDisplay));
725
+ safeWrite(chalk.gray(centerText('\n\n[ SYSTEM READY ]')));
726
+ safeWrite(chalk.dim(centerText('\n\nPress any key to continue...')));
727
+
483
728
  await sleep(500);
484
729
 
485
730
  const totalTime = Date.now() - startTime;
486
- console.log(chalk.gray(`\n\nAnimation completed: ${frameCount} frames in ${totalTime}ms (${Math.round(frameCount / (totalTime / 1000))} FPS)`));
731
+ const actualFPS = Math.round(frameCount / (totalTime / 1000));
732
+
733
+ // Performance stats (optional, can be hidden)
734
+ if (process.env.DEBUG_ANIMATION) {
735
+ console.log(chalk.gray(`\n\nAnimation completed: ${frameCount} frames in ${totalTime}ms (${actualFPS} FPS)`));
736
+ }
737
+
487
738
  await sleep(1000);
488
739
 
489
740
  } finally {
@@ -499,5 +750,7 @@ module.exports = {
499
750
  sleep,
500
751
  clearScreen,
501
752
  centerText,
753
+ getTerminalSize,
754
+ safeWrite,
502
755
  FrameInterpolator
503
756
  };
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "sam-coder-cli",
3
- "version": "1.0.48",
3
+ "version": "1.0.49",
4
4
  "description": "SAM-CODER: An animated command-line AI assistant with agency capabilities.",
5
5
  "main": "bin/agi-cli.js",
6
6
  "bin": {
7
- "sam-coder": "bin/agi-cli.js"
7
+ "sam-coder": "bin/agi-cli.js",
8
+ "agi-cli": "bin/agi-cli.js"
8
9
  },
9
10
  "scripts": {
10
11
  "start": "node ./bin/agi-cli.js"