omnibiofex 2.8.4 → 4.0.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.
@@ -1,110 +1,5 @@
1
1
  const chalk = require('chalk');
2
- const figlet = require('figlet');
3
2
 
4
- // Update the banner display
5
- function displayBanner(version) {
6
- console.log(
7
- chalk.hex('#F24E1E')(
8
- figlet.textSync('OmniBioFex X', { horizontalLayout: 'full' })
9
- )
10
- );
11
- console.log(chalk.gray(`The Autonomous Research Operating System v${version}\n`));
12
- console.log(chalk.hex('#F24E1E')('Create Research. Publish It. Earn From It.\n'));
13
- }
14
-
15
- // ==================== MISSION NAMES ====================
16
- const MISSION_NAMES = [
17
- 'Atlas', 'Helix', 'Nova', 'Orion', 'Phoenix', 'Titan', 'Genesis', 'Aurora',
18
- 'Horizon', 'Polaris', 'Vega', 'Nebula', 'Quasar', 'Pulsar', 'Cosmos',
19
- 'Meridian', 'Zenith', 'Apex', 'Vertex', 'Nexus', 'Matrix', 'Cipher',
20
- 'Enigma', 'Quantum', 'Fusion', 'Prism', 'Spectrum', 'Catalyst', 'Vortex',
21
- 'Eclipse', 'Zenon', 'Aether', 'Cipher', 'Odyssey', 'Paradox', 'Elysium'
22
- ];
23
-
24
- function generateMissionName() {
25
- const name = MISSION_NAMES[Math.floor(Math.random() * MISSION_NAMES.length)];
26
- return `Mission ${name}`;
27
- }
28
-
29
- // ==================== UTILITIES ====================
30
- function sleep(ms) {
31
- return new Promise(resolve => setTimeout(resolve, ms));
32
- }
33
-
34
- // ==================== TYPING ANIMATION ====================
35
- /**
36
- * Type text character by character (premium effect)
37
- * @param {string} text - Text to type
38
- * @param {number} speed - Delay per character (ms)
39
- * @param {string} color - Chalk color function
40
- */
41
- async function typeText(text, speed = 15, color = null) {
42
- for (let i = 0; i < text.length; i++) {
43
- const char = text[i];
44
- if (color) {
45
- process.stdout.write(color(char));
46
- } else {
47
- process.stdout.write(char);
48
- }
49
-
50
- // Variable speed for natural feel
51
- let delay = speed;
52
- if (char === '.' || char === '!' || char === '?') {
53
- delay = speed * 8; // Longer pause at punctuation
54
- } else if (char === ',') {
55
- delay = speed * 4;
56
- } else if (char === '\n') {
57
- delay = speed * 2;
58
- } else if (char === ' ') {
59
- delay = speed * 0.5;
60
- }
61
-
62
- await sleep(delay);
63
- }
64
- }
65
-
66
- /**
67
- * Stream text in chunks (faster than char-by-char)
68
- */
69
- async function streamText(text, chunkSize = 3, delay = 10) {
70
- for (let i = 0; i < text.length; i += chunkSize) {
71
- process.stdout.write(text.substring(i, i + chunkSize));
72
- await sleep(delay);
73
- }
74
- }
75
-
76
- /**
77
- * Type a complete line with automatic newline
78
- */
79
- async function typeLine(text, speed = 15, color = null) {
80
- await typeText(text, speed, color);
81
- process.stdout.write('\n');
82
- }
83
-
84
- // ==================== PROGRESS BAR ====================
85
- function createProgressBar(percent, width = 30) {
86
- const filled = Math.round((percent / 100) * width);
87
- const empty = width - filled;
88
- const bar = '█'.repeat(filled) + '░'.repeat(empty);
89
- return chalk.hex('#F24E1E')(bar) + chalk.gray(` ${percent}%`);
90
- }
91
-
92
- /**
93
- * Animate a progress bar from 0 to target
94
- */
95
- async function animateProgressBar(target, label = 'Progress', duration = 2000) {
96
- const steps = 20;
97
- const stepTime = duration / steps;
98
-
99
- for (let i = 0; i <= steps; i++) {
100
- const current = Math.round((target / steps) * i);
101
- process.stdout.write(`\r${chalk.gray(label + ':')} ${createProgressBar(current)}`);
102
- await sleep(stepTime);
103
- }
104
- process.stdout.write('\n');
105
- }
106
-
107
- // ==================== PREMIUM SPINNER ====================
108
3
  class PremiumSpinner {
109
4
  constructor(text) {
110
5
  this.text = text;
@@ -118,9 +13,7 @@ class PremiumSpinner {
118
13
  this.startTime = Date.now();
119
14
  this.interval = setInterval(() => {
120
15
  const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
121
- process.stdout.write(
122
- `\r${chalk.hex('#F24E1E')(this.frames[this.frameIndex])} ${this.text} ${chalk.gray(`[${elapsed}s]`)}`
123
- );
16
+ process.stdout.write(`\r${chalk.hex('#F24E1E')(this.frames[this.frameIndex])} ${this.text} ${chalk.gray(`[${elapsed}s]`)}`);
124
17
  this.frameIndex = (this.frameIndex + 1) % this.frames.length;
125
18
  }, 80);
126
19
  return this;
@@ -141,13 +34,8 @@ class PremiumSpinner {
141
34
  console.log(`\r${chalk.red('✗')} ${chalk.white(text || this.text)}`);
142
35
  }
143
36
 
144
- info(text) {
145
- this.stop();
146
- console.log(`\r${chalk.blue('ℹ')} ${chalk.white(text || this.text)}`);
147
- }
148
-
149
37
  clearLine() {
150
- process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
38
+ process.stdout.write('\r' + ' '.repeat(80) + '\r');
151
39
  }
152
40
 
153
41
  stop() {
@@ -159,757 +47,40 @@ class PremiumSpinner {
159
47
  }
160
48
  }
161
49
 
162
- // ==================== RESEARCH ANIMATIONS ====================
163
- async function animateResearchSources() {
164
- console.log(chalk.hex('#F24E1E')('\n🔍 Connecting to research networks...\n'));
165
-
166
- const sources = [
167
- { name: 'Nature', icon: '📗' },
168
- { name: 'IEEE Xplore', icon: '📘' },
169
- { name: 'PubMed', icon: '📙' },
170
- { name: 'arXiv', icon: '📕' },
171
- { name: 'Google Scholar', icon: '🎓' },
172
- { name: 'Patent Databases', icon: '📜' }
173
- ];
174
-
175
- for (const source of sources) {
176
- const spinner = new PremiumSpinner(`${source.icon} Reading ${source.name}...`);
177
- spinner.start();
178
- await sleep(400 + Math.random() * 400);
179
- spinner.succeed(`${source.icon} ${source.name} connected`);
180
- }
181
-
182
- console.log(chalk.green('\n✓ All sources connected\n'));
183
- }
184
-
185
- async function showPlanningPhase(topic) {
186
- console.log(chalk.hex('#F24E1E').bold('\n🧠 Planning Mission...\n'));
187
-
188
- const steps = [
189
- { text: `Understanding objective: "${topic}"`, delay: 600 },
190
- { text: 'Building execution graph', delay: 500 },
191
- { text: 'Selecting research agents (6 agents)', delay: 700 },
192
- { text: 'Choosing inference engines', delay: 400 },
193
- { text: 'Searching literature databases', delay: 600 },
194
- { text: 'Finding relevant datasets', delay: 500 },
195
- { text: 'Identifying patents', delay: 400 },
196
- { text: 'Mapping research timeline', delay: 600 },
197
- { text: 'Planning validation steps', delay: 500 },
198
- { text: 'Estimating completion time', delay: 300 }
199
- ];
200
-
201
- for (const step of steps) {
202
- const spinner = new PremiumSpinner(step.text);
203
- spinner.start();
204
- await sleep(step.delay);
205
- spinner.succeed(step.text);
206
- }
207
-
208
- console.log(chalk.green('\n✓ Planning complete\n'));
209
- }
210
-
211
- // ==================== RESEARCH SCORE ====================
212
- function generateResearchScore(response) {
213
- // Generate realistic scores based on response length/quality
214
- const length = (response || '').length;
215
- const base = Math.min(95, 75 + Math.floor(length / 100));
216
-
217
- return {
218
- novelty: base + Math.floor(Math.random() * 8) - 3,
219
- evidence: base + Math.floor(Math.random() * 6),
220
- confidence: base + Math.floor(Math.random() * 5) - 2,
221
- methodology: base + Math.floor(Math.random() * 7) - 3,
222
- reproducibility: base + Math.floor(Math.random() * 8) - 4,
223
- citations: Math.min(100, base + 5 + Math.floor(Math.random() * 5)),
224
- gap: ['Low', 'Medium', 'High'][Math.floor(Math.random() * 3)],
225
- publicationReady: base > 82
226
- };
227
- }
228
-
229
- async function displayResearchScore(score) {
230
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
231
- console.log(chalk.white.bold('📊 Research Quality Score'));
232
- console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
233
-
234
- const metrics = [
235
- { name: 'Novelty', value: score.novelty },
236
- { name: 'Evidence Strength', value: score.evidence },
237
- { name: 'Confidence', value: score.confidence },
238
- { name: 'Methodological Quality', value: score.methodology },
239
- { name: 'Reproducibility', value: score.reproducibility },
240
- { name: 'Citation Completeness', value: score.citations }
241
- ];
242
-
243
- for (const metric of metrics) {
244
- const color = metric.value >= 90 ? chalk.green : metric.value >= 75 ? chalk.yellow : chalk.red;
245
- const bar = '█'.repeat(Math.floor(metric.value / 5)) + '░'.repeat(20 - Math.floor(metric.value / 5));
246
- process.stdout.write(chalk.gray(` ${metric.name.padEnd(25)} `));
247
- await typeText(`${metric.value}%`, 30, color);
248
- process.stdout.write(` ${chalk.gray(bar)}\n`);
249
- await sleep(100);
250
- }
251
-
252
- console.log('');
253
- console.log(chalk.gray(' Research Gap: '), chalk.white.bold(score.gap));
254
- console.log(
255
- chalk.gray(' Publication Ready: '),
256
- score.publicationReady ? chalk.green.bold('Yes ✓') : chalk.yellow.bold('No')
257
- );
258
-
259
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
260
- }
261
-
262
- // ==================== ARTIFACTS ====================
263
- function generateArtifacts(taskType) {
264
- const base = [
265
- { icon: '📄', name: 'Research Report' },
266
- { icon: '📊', name: 'Statistical Summary' },
267
- { icon: '🔗', name: 'Citation Database' }
268
- ];
269
-
270
- const extras = {
271
- LITERATURE_REVIEW: [
272
- { icon: '📚', name: 'Literature Review' },
273
- { icon: '🗓️', name: 'Research Timeline' },
274
- { icon: '🔍', name: 'Gap Analysis' }
275
- ],
276
- RESEARCH_GAP: [
277
- { icon: '🔍', name: 'Gap Analysis' },
278
- { icon: '💡', name: 'Novel Opportunities' }
279
- ],
280
- HYPOTHESIS: [
281
- { icon: '💡', name: 'Hypotheses' },
282
- { icon: '🧪', name: 'Validation Protocols' }
283
- ]
284
- };
285
-
286
- return [...base, ...(extras[taskType] || [])];
287
- }
288
-
289
- async function displayArtifacts(artifacts) {
290
- console.log(chalk.hex('#F24E1E').bold('📦 Artifacts Generated\n'));
291
-
292
- for (const artifact of artifacts) {
293
- await sleep(100);
294
- console.log(` ${chalk.green('✓')} ${chalk.white(artifact.icon + ' ' + artifact.name)}`);
295
- }
296
-
297
- console.log('');
298
- }
299
-
300
- // ==================== MISSION DASHBOARD ====================
301
- async function displayMissionDashboard(mission) {
302
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
303
- console.log(chalk.white.bold(`✨ ${mission.name}`));
304
- console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
305
-
306
- console.log(chalk.gray('Status: '), chalk.yellow(mission.status || 'Running'));
307
- console.log(chalk.gray('Progress: '), createProgressBar(mission.progress || 0));
308
- console.log('');
309
-
310
- console.log(chalk.hex('#F24E1E').bold('Research Metrics'));
311
- const metrics = [
312
- { label: 'Papers', value: mission.papers || 0 },
313
- { label: 'Patents', value: mission.patents || 0 },
314
- { label: 'Datasets', value: mission.datasets || 0 },
315
- { label: 'Contradictions', value: mission.contradictions || 0 },
316
- { label: 'Hypotheses', value: mission.hypotheses || 0 }
317
- ];
318
-
319
- for (const m of metrics) {
320
- console.log(chalk.gray(` ${m.label.padEnd(15)}`), chalk.white(m.value));
321
- }
322
-
323
- if (mission.estimatedTime) {
324
- console.log('');
325
- console.log(chalk.gray('Est. Completion:'), chalk.white(mission.estimatedTime));
326
- }
327
-
328
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
329
- }
330
-
331
- // ==================== HELPERS FOR TABLE RENDERING ====================
332
- function formatTable(rows) {
333
- if (!rows || rows.length === 0) return '';
334
-
335
- // Calculate column widths
336
- const colWidths = [];
337
- rows.forEach(row => {
338
- row.forEach((cell, i) => {
339
- colWidths[i] = Math.max(colWidths[i] || 0, cell.length);
340
- });
341
- });
342
-
343
- // Format each row
344
- return rows.map((row, rowIndex) => {
345
- const isHeader = rowIndex === 0;
346
- const formatted = row.map((cell, i) => {
347
- const padded = cell.padEnd(colWidths[i]);
348
- return isHeader ? chalk.white.bold(padded) : chalk.gray(padded);
349
- }).join(' │ ');
350
-
351
- return chalk.gray('│ ') + formatted + chalk.gray(' │');
352
- }).join('\n');
353
- }
354
-
355
- function addVisualBreak() {
356
- console.log(chalk.gray('\n' + '·'.repeat(60) + '\n'));
357
- }
358
-
359
- // ==================== INLINE MARKDOWN PARSER ====================
360
-
361
- /**
362
- * Parse a line and return array of segments with formatting
363
- * Handles: **bold**, *italic*, `code`, and combinations
364
- */
365
- function parseInlineMarkdown(text) {
366
- const segments = [];
367
- let remaining = text;
368
-
369
- while (remaining.length > 0) {
370
- // Find the next markdown pattern
371
- const boldMatch = remaining.match(/\*\*(.+?)\*\*/);
372
- const italicMatch = remaining.match(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/);
373
- const codeMatch = remaining.match(/`([^`]+)`/);
374
-
375
- // Find earliest match
376
- let earliest = null;
377
- let earliestIndex = remaining.length;
378
-
379
- if (boldMatch && boldMatch.index < earliestIndex) {
380
- earliest = { type: 'bold', match: boldMatch, index: boldMatch.index };
381
- earliestIndex = boldMatch.index;
382
- }
383
- if (codeMatch && codeMatch.index < earliestIndex) {
384
- earliest = { type: 'code', match: codeMatch, index: codeMatch.index };
385
- earliestIndex = codeMatch.index;
386
- }
387
- if (italicMatch && italicMatch.index < earliestIndex) {
388
- earliest = { type: 'italic', match: italicMatch, index: italicMatch.index };
389
- earliestIndex = italicMatch.index;
390
- }
391
-
392
- if (!earliest) {
393
- // No more markdown, add remaining as plain text
394
- if (remaining.length > 0) {
395
- segments.push({ text: remaining, style: 'plain' });
396
- }
397
- break;
398
- }
399
-
400
- // Add text before the match
401
- if (earliestIndex > 0) {
402
- segments.push({
403
- text: remaining.substring(0, earliestIndex),
404
- style: 'plain'
405
- });
406
- }
407
-
408
- // Add the formatted segment
409
- segments.push({
410
- text: earliest.match[1],
411
- style: earliest.type
412
- });
413
-
414
- // Continue with remaining text
415
- remaining = remaining.substring(earliestIndex + earliest.match[0].length);
416
- }
417
-
418
- return segments;
419
- }
420
-
421
- /**
422
- * Type a line with inline markdown formatting (bold, italic, code)
423
- */
424
- async function typeFormattedLine(text, speed = 8) {
425
- const segments = parseInlineMarkdown(text);
426
-
427
- for (const segment of segments) {
428
- let colorFn = chalk.white;
429
-
430
- switch (segment.style) {
431
- case 'bold':
432
- colorFn = chalk.white.bold;
433
- break;
434
- case 'italic':
435
- colorFn = chalk.white.italic;
436
- break;
437
- case 'code':
438
- colorFn = chalk.bgBlack.cyan;
439
- break;
440
- case 'plain':
441
- default:
442
- colorFn = chalk.white;
443
- }
444
-
445
- await typeText(segment.text, speed, colorFn);
446
- }
447
-
448
- process.stdout.write('\n');
50
+ async function sleep(ms) {
51
+ return new Promise(resolve => setTimeout(resolve, ms));
449
52
  }
450
53
 
451
- /**
452
- * Type a line with inline markdown, but use gray color for plain text
453
- */
454
- async function typeFormattedLineGray(text, speed = 6) {
455
- const segments = parseInlineMarkdown(text);
456
-
457
- for (const segment of segments) {
458
- let colorFn = chalk.gray;
459
-
460
- switch (segment.style) {
461
- case 'bold':
462
- colorFn = chalk.white.bold;
463
- break;
464
- case 'italic':
465
- colorFn = chalk.white.italic;
466
- break;
467
- case 'code':
468
- colorFn = chalk.bgBlack.cyan;
469
- break;
470
- case 'plain':
471
- default:
472
- colorFn = chalk.gray;
473
- }
474
-
475
- await typeText(segment.text, speed, colorFn);
54
+ async function typeText(text, speed = 8) {
55
+ for (const char of text) {
56
+ process.stdout.write(char);
57
+ await sleep(speed);
476
58
  }
477
-
478
- process.stdout.write('\n');
479
59
  }
480
60
 
481
- // ==================== UPDATED AI RESPONSE RENDERER ====================
482
-
483
- async function typeAIResponse(response) {
484
- console.log(chalk.hex('#F24E1E').bold('\n📄 Research Report\n'));
485
- console.log(chalk.gray('═'.repeat(60)) + '\n');
486
-
487
- const lines = response.split('\n');
488
- let inTable = false;
489
-
490
- for (let i = 0; i < lines.length; i++) {
491
- const line = lines[i];
61
+ async function typeAIResponse(text) {
62
+ const lines = text.split('\n');
63
+ for (const line of lines) {
492
64
  const trimmed = line.trim();
493
-
494
- // Skip empty lines but add spacing
495
- if (trimmed === '') {
496
- if (!inTable) {
497
- console.log('');
498
- await sleep(80);
499
- }
500
- continue;
501
- }
502
-
503
- // Detect table rows (lines with |)
504
- if (trimmed.includes('|') && trimmed.startsWith('|')) {
505
- // Skip separator rows like |---|---| or | ---------- |
506
- if (trimmed.match(/^\|[\s\-:]+\|$/)) {
507
- continue;
508
- }
509
-
510
- if (!inTable) {
511
- inTable = true;
512
- console.log(chalk.gray('┌' + '─'.repeat(58) + '┐'));
513
- }
514
-
515
- // Parse table cells
516
- const cells = trimmed.split('|').filter(c => c.trim() !== '').map(c => c.trim());
517
-
518
- // Format table row with inline markdown support
519
- if (cells.length > 0) {
520
- const isHeader = i === 0 || (i > 0 && lines[i-1].trim() === '');
521
-
522
- process.stdout.write(chalk.gray('│ '));
523
-
524
- for (let j = 0; j < cells.length; j++) {
525
- const cell = cells[j];
526
- const padded = cell.padEnd(15);
527
-
528
- if (isHeader) {
529
- // Header cells - parse markdown and make bold
530
- const segments = parseInlineMarkdown(padded);
531
- for (const seg of segments) {
532
- process.stdout.write(chalk.white.bold(seg.text));
533
- }
534
- } else {
535
- // Regular cells - parse markdown
536
- const segments = parseInlineMarkdown(padded);
537
- for (const seg of segments) {
538
- let colorFn = chalk.gray;
539
- if (seg.style === 'bold') colorFn = chalk.white.bold;
540
- else if (seg.style === 'italic') colorFn = chalk.white.italic;
541
- else if (seg.style === 'code') colorFn = chalk.bgBlack.cyan;
542
- process.stdout.write(colorFn(seg.text));
543
- }
544
- }
545
-
546
- if (j < cells.length - 1) {
547
- process.stdout.write(chalk.gray(' │ '));
548
- }
549
- }
550
-
551
- console.log(chalk.gray(' │'));
552
- await sleep(50);
553
- }
554
-
555
- continue;
556
- } else if (inTable) {
557
- // End of table
558
- console.log(chalk.gray('└' + '─'.repeat(58) + '┐'));
559
- console.log('');
560
- inTable = false;
561
- await sleep(100);
562
- }
563
-
564
- // Headers (## or #)
565
- if (trimmed.startsWith('## ')) {
566
- const header = trimmed.substring(3);
567
- console.log('');
568
- process.stdout.write(chalk.hex('#F24E1E').bold('▸ '));
569
- await typeFormattedLine(header, 15);
570
- console.log(chalk.gray('─'.repeat(60)));
571
- await sleep(150);
572
- continue;
573
- }
574
-
65
+ if (trimmed === '') { console.log(''); continue; }
575
66
  if (trimmed.startsWith('# ')) {
576
- const header = trimmed.substring(2);
577
- console.log('');
578
- process.stdout.write(chalk.hex('#F24E1E').bold.underline(' '));
579
- await typeFormattedLine(header, 20);
580
- console.log('');
581
- await sleep(200);
582
- continue;
583
- }
584
-
585
- // Bullet points
586
- if (trimmed.startsWith('• ') || trimmed.startsWith('- ') || trimmed.startsWith('* ')) {
587
- const bullet = trimmed.substring(2);
588
- process.stdout.write(chalk.hex('#F24E1E')(' ▸ '));
589
- await typeFormattedLine(bullet, 8);
590
- await sleep(60);
591
- continue;
592
- }
593
-
594
- // Numbered lists
595
- const numberedMatch = trimmed.match(/^(\d+)\.\s+(.+)/);
596
- if (numberedMatch) {
597
- const num = numberedMatch[1];
598
- const text = numberedMatch[2];
599
- process.stdout.write(chalk.hex('#F24E1E')(` ${num}. `));
600
- await typeFormattedLine(text, 8);
601
- await sleep(60);
602
- continue;
603
- }
604
-
605
- // Regular paragraph (with inline markdown support)
606
- process.stdout.write(' ');
607
- await typeFormattedLineGray(trimmed, 6);
608
- await sleep(40);
609
- }
610
-
611
- // Close any open table
612
- if (inTable) {
613
- console.log(chalk.gray('└' + '─'.repeat(58) + '┐'));
614
- }
615
-
616
- console.log('\n' + chalk.gray('═'.repeat(60)) + '\n');
617
- }
618
-
619
- // ==================== RENDER MARKDOWN (existing) ====================
620
- function renderMarkdown(markdown) {
621
- // Simplified - most formatting happens in typeAIResponse
622
- return markdown;
623
- }
624
-
625
- async function displayReport(markdown, useTypingEffect = true) {
626
- if (useTypingEffect) {
627
- await typeAIResponse(markdown);
628
- } else {
629
- console.log(markdown);
630
- }
631
- }
632
-
633
- // ==================== SIMPLE THINKING ANIMATION ====================
634
- async function showThinking(taskType, topic) {
635
- console.log(chalk.hex('#F24E1E').bold(`\n🤖 Thinking about: ${topic}\n`));
636
-
637
- const thoughts = [
638
- 'Analyzing research landscape...',
639
- 'Identifying key methodologies...',
640
- 'Cross-referencing findings...',
641
- 'Synthesizing insights...',
642
- 'Preparing report...'
643
- ];
644
-
645
- for (const thought of thoughts) {
646
- const spinner = new PremiumSpinner(thought);
647
- spinner.start();
648
- await sleep(600 + Math.random() * 400);
649
- spinner.succeed(thought);
650
- }
651
- }
652
-
653
- // ==================== MISSION HEALTH SCORE ====================
654
-
655
- /**
656
- * Calculate comprehensive mission health metrics
657
- */
658
- function calculateMissionHealth(missionData) {
659
- const evidence = missionData.evidenceScore || 96;
660
- const novelty = missionData.noveltyScore || 81;
661
- const confidence = missionData.confidenceScore || 91;
662
- const methodology = missionData.methodologyScore || 89;
663
- const reproducibility = missionData.reproducibilityScore || 93;
664
- const citations = missionData.citationsScore || 98;
665
-
666
- // Calculate overall health (weighted average)
667
- const overall = Math.round(
668
- (evidence * 0.25) +
669
- (novelty * 0.15) +
670
- (confidence * 0.20) +
671
- (methodology * 0.15) +
672
- (reproducibility * 0.15) +
673
- (citations * 0.10)
674
- );
675
-
676
- // Calculate bias risk
677
- const biasRisk = overall >= 90 ? 'Low' : overall >= 75 ? 'Medium' : 'High';
678
-
679
- // Identify missing experiments based on gaps
680
- const missingExperiments = missionData.gapsCount || Math.floor(Math.random() * 3) + 1;
681
-
682
- // Publication readiness
683
- const publicationReady = overall >= 85 && evidence >= 90 && citations >= 95;
684
-
685
- return {
686
- overall,
687
- evidence,
688
- novelty,
689
- confidence,
690
- methodology,
691
- reproducibility,
692
- citations,
693
- biasRisk,
694
- missingExperiments,
695
- publicationReady
696
- };
697
- }
698
-
699
- /**
700
- * Display beautiful mission health score
701
- */
702
- async function displayMissionHealth(health, missionName = 'Mission') {
703
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
704
- console.log(chalk.white.bold(`🏥 ${missionName} - Health Score`));
705
- console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
706
-
707
- // Overall health with color coding
708
- const overallColor = health.overall >= 90 ? chalk.green :
709
- health.overall >= 75 ? chalk.yellow : chalk.red;
710
-
711
- console.log(chalk.gray(' Overall Health:'), overallColor.bold(`${health.overall}%`));
712
- console.log('');
713
-
714
- // Detailed metrics
715
- const metrics = [
716
- { name: 'Evidence Strength', value: health.evidence },
717
- { name: 'Novelty', value: health.novelty },
718
- { name: 'Confidence', value: health.confidence },
719
- { name: 'Methodological Quality', value: health.methodology },
720
- { name: 'Reproducibility', value: health.reproducibility },
721
- { name: 'Citation Completeness', value: health.citations }
722
- ];
723
-
724
- for (const metric of metrics) {
725
- const color = metric.value >= 90 ? chalk.green :
726
- metric.value >= 75 ? chalk.yellow : chalk.red;
727
- const bar = '█'.repeat(Math.floor(metric.value / 5)) + '░'.repeat(20 - Math.floor(metric.value / 5));
728
-
729
- process.stdout.write(chalk.gray(` ${metric.name.padEnd(25)} `));
730
- await typeText(`${metric.value}%`, 20, color);
731
- process.stdout.write(` ${chalk.gray(bar)}\n`);
732
- await sleep(80);
733
- }
734
-
735
- console.log('');
736
-
737
- // Risk assessment
738
- const biasColor = health.biasRisk === 'Low' ? chalk.green :
739
- health.biasRisk === 'Medium' ? chalk.yellow : chalk.red;
740
- console.log(chalk.gray(' Bias Risk:'), biasColor.bold(health.biasRisk));
741
-
742
- // Missing experiments
743
- if (health.missingExperiments > 0) {
744
- console.log(
745
- chalk.gray(' Missing Experiments:'),
746
- chalk.yellow.bold(`${health.missingExperiments}`)
747
- );
748
- } else {
749
- console.log(chalk.gray(' Missing Experiments:'), chalk.green.bold('None ✓'));
750
- }
751
-
752
- // Publication readiness
753
- console.log(
754
- chalk.gray(' Publication Ready:'),
755
- health.publicationReady ? chalk.green.bold('Yes ✓') : chalk.yellow.bold('Needs Review')
756
- );
757
-
758
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
759
- }
760
-
761
- // ==================== RESEARCH TIMELINE VISUALIZATION ====================
762
-
763
- /**
764
- * Display beautiful research timeline
765
- */
766
- async function displayTimeline(timeline, topic) {
767
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
768
- console.log(chalk.white.bold(`📅 Research Timeline: ${topic}`));
769
- console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
770
-
771
- if (!timeline || timeline.length === 0) {
772
- console.log(chalk.gray(' No timeline data available.\n'));
773
- return;
774
- }
775
-
776
- // Sort by year
777
- const sorted = [...timeline].sort((a, b) => a.year - b.year);
778
-
779
- for (let i = 0; i < sorted.length; i++) {
780
- const event = sorted[i];
781
- const isLast = i === sorted.length - 1;
782
- const isCurrent = event.isCurrentResearch;
783
-
784
- // Year
785
- process.stdout.write(chalk.hex('#F24E1E').bold(` ${event.year} `));
786
-
787
- // Connector line
788
- if (!isLast) {
789
- process.stdout.write(chalk.gray('──── '));
790
- } else {
791
- process.stdout.write(chalk.gray('──── '));
792
- }
793
-
794
- // Event title
795
- if (isCurrent) {
796
- await typeText(event.title, 10, chalk.green.bold);
797
- } else {
798
- await typeText(event.title, 10, chalk.white);
799
- }
800
-
801
- console.log('');
802
-
803
- // Description
804
- if (event.description) {
805
- console.log(chalk.gray(` ${event.description}`));
806
- }
807
-
808
- // Impact
809
- if (event.impact) {
810
- const impactColor = event.impact === 'High' ? chalk.red :
811
- event.impact === 'Medium' ? chalk.yellow : chalk.gray;
812
- console.log(chalk.gray(` Impact: `), impactColor(event.impact));
813
- }
814
-
815
- // Vertical connector
816
- if (!isLast) {
817
- console.log(chalk.gray(' │'));
67
+ console.log(chalk.hex('#F24E1E').bold(`\n${trimmed.substring(2)}`));
68
+ console.log(chalk.gray(''.repeat(60)));
69
+ } else if (trimmed.startsWith('## ')) {
70
+ console.log(chalk.white.bold(`\n▸ ${trimmed.substring(3)}`));
71
+ console.log(chalk.gray(''.repeat(60)));
72
+ } else if (trimmed.startsWith('### ')) {
73
+ console.log(chalk.white.bold(`\n ▸ ${trimmed.substring(4)}`));
74
+ } else if (trimmed.startsWith('- ') || trimmed.startsWith('* ')) {
75
+ console.log(chalk.white(` ▸ ${trimmed.substring(2)}`));
76
+ } else if (trimmed.match(/^\d+\./)) {
77
+ console.log(chalk.white(` ${trimmed}`));
78
+ } else if (trimmed.startsWith('|')) {
79
+ console.log(chalk.gray(` ${trimmed}`));
818
80
  } else {
819
- console.log('');
820
- console.log(chalk.green.bold(' ✨ Your research continues from here'));
821
- }
822
-
823
- console.log('');
824
- await sleep(150);
825
- }
826
-
827
- console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
828
- }
829
-
830
- // ==================== MORNING BRIEFING DISPLAY ====================
831
-
832
- /**
833
- * Display morning briefing
834
- */
835
- async function displayMorningBriefing(briefing) {
836
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
837
- console.log(chalk.white.bold('☀️ Good Morning, Researcher!'));
838
- console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
839
-
840
- console.log(chalk.gray(` ${briefing.date}\n`));
841
-
842
- if (briefing.updates && briefing.updates.length > 0) {
843
- console.log(chalk.white.bold(' 📊 Mission Updates:\n'));
844
-
845
- for (const update of briefing.updates) {
846
- const icon = update.type === 'paper' ? '📄' :
847
- update.type === 'patent' ? '📜' :
848
- update.type === 'citation' ? '🔗' :
849
- update.type === 'contradiction' ? '⚠️' : '📌';
850
-
851
- process.stdout.write(chalk.gray(` ${icon} `));
852
- await typeText(update.text, 8, chalk.white);
853
- console.log('');
854
- await sleep(100);
855
- }
856
- }
857
-
858
- if (briefing.missions && briefing.missions.length > 0) {
859
- console.log(chalk.white.bold('\n 🎯 Active Missions:\n'));
860
-
861
- for (const mission of briefing.missions) {
862
- const statusColor = mission.status === 'Running' ? chalk.yellow :
863
- mission.status === 'Complete' ? chalk.green : chalk.gray;
864
-
865
- console.log(chalk.gray(` ✨ ${mission.name}`));
866
- console.log(statusColor(` Status: ${mission.status}`));
867
- console.log(chalk.gray(` Progress: ${mission.progress}%`));
868
- console.log('');
869
- }
870
- }
871
-
872
- if (briefing.recommendations && briefing.recommendations.length > 0) {
873
- console.log(chalk.white.bold(' 💡 Recommendations:\n'));
874
-
875
- for (const rec of briefing.recommendations) {
876
- process.stdout.write(chalk.gray(' ▸ '));
877
- await typeText(rec, 8, chalk.white);
878
- console.log('');
879
- await sleep(80);
81
+ console.log(chalk.white(` ${trimmed}`));
880
82
  }
881
83
  }
882
-
883
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
884
84
  }
885
85
 
886
- module.exports = {
887
- generateMissionName,
888
- sleep,
889
- typeText,
890
- streamText,
891
- typeLine,
892
- createProgressBar,
893
- animateProgressBar,
894
- PremiumSpinner,
895
- animateResearchSources,
896
- showPlanningPhase,
897
- generateResearchScore,
898
- displayResearchScore,
899
- generateArtifacts,
900
- displayArtifacts,
901
- displayMissionDashboard,
902
- typeAIResponse,
903
- renderMarkdown,
904
- displayReport,
905
- showThinking,
906
- formatTable,
907
- addVisualBreak,
908
- // NEW EXPORTS
909
- calculateMissionHealth,
910
- displayMissionHealth,
911
- displayTimeline,
912
- displayMorningBriefing,
913
- // ADD BANNER
914
- displayBanner,
915
- };
86
+ module.exports = { PremiumSpinner, sleep, typeText, typeAIResponse };