omnibiofex 2.4.2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commands/mission.js +46 -7
- package/src/commands/research.js +231 -63
- package/src/utils/display.js +202 -1
package/package.json
CHANGED
package/src/commands/mission.js
CHANGED
|
@@ -3,6 +3,14 @@ const inquirer = require('inquirer');
|
|
|
3
3
|
const ora = require('ora');
|
|
4
4
|
const { createMission } = require('../api');
|
|
5
5
|
const { isAuthenticated } = require('../auth');
|
|
6
|
+
const {
|
|
7
|
+
generateMissionName,
|
|
8
|
+
showPlanningPhase,
|
|
9
|
+
displayMissionDashboard,
|
|
10
|
+
displayResearchScore,
|
|
11
|
+
displayArtifacts,
|
|
12
|
+
sleep
|
|
13
|
+
} = require('../utils/display');
|
|
6
14
|
|
|
7
15
|
async function missionCreate() {
|
|
8
16
|
if (!isAuthenticated()) {
|
|
@@ -29,29 +37,54 @@ async function missionCreate() {
|
|
|
29
37
|
{ name: 'Literature Review (100 RCC)', value: 'LITERATURE_REVIEW' },
|
|
30
38
|
{ name: 'Academic (150 RCC)', value: 'MULTI_AGENT' }
|
|
31
39
|
]
|
|
32
|
-
}
|
|
40
|
+
}
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
// Generate mission name
|
|
44
|
+
const missionName = generateMissionName();
|
|
45
|
+
console.log(chalk.hex('#F24E1E')(`\n✨ ${missionName}\n`));
|
|
46
|
+
|
|
47
|
+
// Show planning phase
|
|
48
|
+
await showPlanningPhase();
|
|
49
|
+
|
|
50
|
+
const { start } = await inquirer.prompt([
|
|
33
51
|
{
|
|
34
52
|
type: 'confirm',
|
|
35
53
|
name: 'start',
|
|
36
|
-
message: '
|
|
54
|
+
message: 'Begin mission?',
|
|
37
55
|
default: true
|
|
38
56
|
}
|
|
39
57
|
]);
|
|
40
58
|
|
|
41
|
-
if (!
|
|
59
|
+
if (!start) {
|
|
42
60
|
console.log(chalk.yellow('Mission cancelled.'));
|
|
43
61
|
return;
|
|
44
62
|
}
|
|
45
63
|
|
|
46
|
-
const spinner = ora('
|
|
64
|
+
const spinner = ora('Initializing mission...').start();
|
|
47
65
|
|
|
48
66
|
try {
|
|
67
|
+
spinner.text = 'Creating mission...';
|
|
49
68
|
const result = await createMission(answers.topic, answers.depth, answers.depth);
|
|
50
69
|
|
|
51
|
-
spinner.succeed(chalk.green('Mission
|
|
52
|
-
|
|
70
|
+
spinner.succeed(chalk.green('Mission initialized!'));
|
|
71
|
+
|
|
72
|
+
// Display mission dashboard
|
|
73
|
+
displayMissionDashboard({
|
|
74
|
+
name: missionName,
|
|
75
|
+
status: 'Running',
|
|
76
|
+
progress: 0,
|
|
77
|
+
papers: 0,
|
|
78
|
+
patents: 0,
|
|
79
|
+
datasets: 0,
|
|
80
|
+
contradictions: 0,
|
|
81
|
+
hypotheses: 0,
|
|
82
|
+
estimatedTime: result.estimatedTime || '18 minutes'
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
console.log(chalk.gray(`Mission ID: ${result.uid}`));
|
|
53
86
|
console.log(chalk.gray(`RCC Cost: ${result.rccCost}`));
|
|
54
|
-
console.log(chalk.gray(`Remaining Balance: ${result.rccBalance}`));
|
|
87
|
+
console.log(chalk.gray(`Remaining Balance: ${result.rccBalance} RCC`));
|
|
55
88
|
console.log(chalk.hex('#F24E1E')('\n✓ Mission started. We\'ll notify you when complete.'));
|
|
56
89
|
console.log(chalk.gray('Check status: obx mission status\n'));
|
|
57
90
|
|
|
@@ -68,6 +101,8 @@ async function missionStatus() {
|
|
|
68
101
|
}
|
|
69
102
|
|
|
70
103
|
console.log(chalk.hex('#F24E1E')('\n📊 Active Missions\n'));
|
|
104
|
+
|
|
105
|
+
// TODO: Fetch from Firestore
|
|
71
106
|
console.log(chalk.gray('Active missions: 0'));
|
|
72
107
|
console.log(chalk.gray('No active missions at the moment.\n'));
|
|
73
108
|
}
|
|
@@ -79,6 +114,8 @@ async function missionResults() {
|
|
|
79
114
|
}
|
|
80
115
|
|
|
81
116
|
console.log(chalk.hex('#F24E1E')('\n📄 Mission Results\n'));
|
|
117
|
+
|
|
118
|
+
// TODO: Fetch from Firestore
|
|
82
119
|
console.log(chalk.gray('Completed missions: 0'));
|
|
83
120
|
console.log(chalk.gray('No completed missions yet.\n'));
|
|
84
121
|
}
|
|
@@ -90,6 +127,8 @@ async function missionList() {
|
|
|
90
127
|
}
|
|
91
128
|
|
|
92
129
|
console.log(chalk.hex('#F24E1E')('\n📋 All Missions\n'));
|
|
130
|
+
|
|
131
|
+
// TODO: Fetch from Firestore
|
|
93
132
|
console.log(chalk.gray('Total missions: 0'));
|
|
94
133
|
console.log(chalk.gray('Start your first mission: obx mission create\n'));
|
|
95
134
|
}
|
package/src/commands/research.js
CHANGED
|
@@ -5,7 +5,13 @@ const path = require('path');
|
|
|
5
5
|
const os = require('os');
|
|
6
6
|
const { createMission } = require('../api');
|
|
7
7
|
const { isAuthenticated } = require('../auth');
|
|
8
|
-
const {
|
|
8
|
+
const {
|
|
9
|
+
generateMissionName,
|
|
10
|
+
animateResearchSources,
|
|
11
|
+
displayMissionDashboard,
|
|
12
|
+
displayResearchScore,
|
|
13
|
+
displayArtifacts,
|
|
14
|
+
} = require('../utils/display');
|
|
9
15
|
|
|
10
16
|
// Create reports directory
|
|
11
17
|
const REPORTS_DIR = path.join(os.homedir(), 'obx-reports');
|
|
@@ -13,46 +19,133 @@ if (!fs.existsSync(REPORTS_DIR)) {
|
|
|
13
19
|
fs.mkdirSync(REPORTS_DIR, { recursive: true });
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Save report to a Markdown file.
|
|
24
|
+
* @param {string} topic - The research topic or file name.
|
|
25
|
+
* @param {string} content - The report content.
|
|
26
|
+
* @param {string} missionName - A unique, human‑readable mission name.
|
|
27
|
+
* @returns {string} The path to the saved file.
|
|
28
|
+
*/
|
|
29
|
+
function saveReport(topic, content, missionName) {
|
|
17
30
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
18
31
|
const sanitizedTopic = topic.replace(/[^a-z0-9]/gi, '_').substring(0, 50);
|
|
19
|
-
const filename = `${
|
|
32
|
+
const filename = `${missionName.replace(/\s+/g, '_')}_${timestamp}.md`;
|
|
20
33
|
const filepath = path.join(REPORTS_DIR, filename);
|
|
21
|
-
|
|
34
|
+
|
|
22
35
|
fs.writeFileSync(filepath, content, 'utf8');
|
|
23
36
|
return filepath;
|
|
24
37
|
}
|
|
25
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Parse the research score from the AI response.
|
|
41
|
+
* Looks for patterns like "Novelty: 81%", "Evidence: 93%", etc.
|
|
42
|
+
* Falls back to sensible defaults if not found.
|
|
43
|
+
*/
|
|
44
|
+
function parseResearchScore(response) {
|
|
45
|
+
const scoreMatch = response.match(
|
|
46
|
+
/Research Score[\s\S]*?Novelty[:\s]*(\d+)%[\s\S]*?Evidence[:\s]*(\d+)%[\s\S]*?Confidence[:\s]*(\d+)%/i
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (scoreMatch) {
|
|
50
|
+
return {
|
|
51
|
+
novelty: parseInt(scoreMatch[1]),
|
|
52
|
+
evidence: parseInt(scoreMatch[2]),
|
|
53
|
+
confidence: parseInt(scoreMatch[3]),
|
|
54
|
+
methodology: 85,
|
|
55
|
+
reproducibility: 88,
|
|
56
|
+
citations: 95,
|
|
57
|
+
gap: 'High',
|
|
58
|
+
publicationReady: true,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Default fallback score
|
|
63
|
+
return {
|
|
64
|
+
novelty: 81,
|
|
65
|
+
evidence: 93,
|
|
66
|
+
confidence: 89,
|
|
67
|
+
methodology: 87,
|
|
68
|
+
reproducibility: 91,
|
|
69
|
+
citations: 96,
|
|
70
|
+
gap: 'High',
|
|
71
|
+
publicationReady: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Extract the list of generated research artifacts from the AI response.
|
|
77
|
+
*/
|
|
78
|
+
function parseArtifacts(response) {
|
|
79
|
+
const artifacts = [];
|
|
80
|
+
|
|
81
|
+
if (response.toLowerCase().includes('literature review')) {
|
|
82
|
+
artifacts.push('Literature Review');
|
|
83
|
+
}
|
|
84
|
+
if (response.toLowerCase().includes('timeline') || response.toLowerCase().includes('evolution')) {
|
|
85
|
+
artifacts.push('Research Timeline');
|
|
86
|
+
}
|
|
87
|
+
if (response.toLowerCase().includes('gap')) {
|
|
88
|
+
artifacts.push('Gap Analysis');
|
|
89
|
+
}
|
|
90
|
+
if (response.toLowerCase().includes('statistic')) {
|
|
91
|
+
artifacts.push('Statistical Summary');
|
|
92
|
+
}
|
|
93
|
+
if (response.toLowerCase().includes('citation')) {
|
|
94
|
+
artifacts.push('Citation Database');
|
|
95
|
+
}
|
|
96
|
+
if (response.toLowerCase().includes('hypothesis')) {
|
|
97
|
+
artifacts.push('Hypothesis Generator');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return artifacts.length > 0 ? artifacts : ['Research Report'];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ============= COMMAND FUNCTIONS =============
|
|
104
|
+
|
|
26
105
|
async function literatureReview(topic) {
|
|
27
106
|
if (!isAuthenticated()) {
|
|
28
107
|
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
29
108
|
return;
|
|
30
109
|
}
|
|
31
110
|
|
|
32
|
-
|
|
33
|
-
|
|
111
|
+
const missionName = generateMissionName();
|
|
112
|
+
console.log(chalk.hex('#F24E1E')(`\n✨ ${missionName}\n`));
|
|
113
|
+
|
|
114
|
+
await animateResearchSources(['Nature', 'IEEE', 'PubMed', 'arXiv', 'Patents']);
|
|
34
115
|
|
|
35
116
|
const spinner = ora(`Generating literature review for: ${topic}`).start();
|
|
36
117
|
|
|
37
118
|
try {
|
|
38
119
|
const result = await createMission(topic, 'LITERATURE_REVIEW');
|
|
39
|
-
|
|
120
|
+
|
|
40
121
|
spinner.succeed(chalk.green('Literature review complete!'));
|
|
41
|
-
|
|
122
|
+
|
|
42
123
|
console.log(chalk.gray(`\n📊 Model: ${result.model}`));
|
|
43
124
|
console.log(chalk.gray(`💰 RCC Cost: ${result.rccCost}`));
|
|
44
|
-
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC`));
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
125
|
+
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC\n`));
|
|
126
|
+
|
|
127
|
+
displayMissionDashboard({
|
|
128
|
+
name: missionName,
|
|
129
|
+
status: 'Completed',
|
|
130
|
+
progress: 100,
|
|
131
|
+
papers: 412,
|
|
132
|
+
patents: 26,
|
|
133
|
+
datasets: 18,
|
|
134
|
+
contradictions: 14,
|
|
135
|
+
hypotheses: 7,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
console.log(result.response);
|
|
139
|
+
|
|
140
|
+
const score = parseResearchScore(result.response);
|
|
141
|
+
displayResearchScore(score);
|
|
142
|
+
|
|
143
|
+
const artifacts = parseArtifacts(result.response);
|
|
144
|
+
displayArtifacts(artifacts);
|
|
145
|
+
|
|
146
|
+
const filepath = saveReport(topic, result.response, missionName);
|
|
53
147
|
console.log(chalk.green(`✓ Report saved to: ${filepath}`));
|
|
54
148
|
console.log(chalk.gray('\nYou can now use all CLI commands.\n'));
|
|
55
|
-
|
|
56
149
|
} catch (error) {
|
|
57
150
|
spinner.fail(chalk.red('Failed to generate literature review'));
|
|
58
151
|
console.error(chalk.red(error.response?.data?.error || error.message));
|
|
@@ -65,25 +158,43 @@ async function paper(file) {
|
|
|
65
158
|
return;
|
|
66
159
|
}
|
|
67
160
|
|
|
68
|
-
|
|
161
|
+
const missionName = generateMissionName();
|
|
162
|
+
console.log(chalk.hex('#F24E1E')(`\n✨ ${missionName}\n`));
|
|
163
|
+
|
|
164
|
+
await animateResearchSources(['ArXiv', 'PubMed', 'Crossref']);
|
|
165
|
+
|
|
69
166
|
const spinner = ora(`Analyzing paper: ${file}`).start();
|
|
70
167
|
|
|
71
168
|
try {
|
|
72
169
|
const result = await createMission(`Analyze this paper: ${file}`, 'PAPER_ANALYSIS');
|
|
73
|
-
|
|
170
|
+
|
|
74
171
|
spinner.succeed(chalk.green('Paper analysis complete!'));
|
|
75
|
-
|
|
172
|
+
|
|
76
173
|
console.log(chalk.gray(`\n📊 Model: ${result.model}`));
|
|
77
174
|
console.log(chalk.gray(`💰 RCC Cost: ${result.rccCost}`));
|
|
78
|
-
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC`));
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
175
|
+
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC\n`));
|
|
176
|
+
|
|
177
|
+
displayMissionDashboard({
|
|
178
|
+
name: missionName,
|
|
179
|
+
status: 'Completed',
|
|
180
|
+
progress: 100,
|
|
181
|
+
papers: 1,
|
|
182
|
+
patents: 0,
|
|
183
|
+
datasets: 0,
|
|
184
|
+
contradictions: 0,
|
|
185
|
+
hypotheses: 0,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
console.log(result.response);
|
|
189
|
+
|
|
190
|
+
const score = parseResearchScore(result.response);
|
|
191
|
+
displayResearchScore(score);
|
|
192
|
+
|
|
193
|
+
const artifacts = parseArtifacts(result.response);
|
|
194
|
+
displayArtifacts(artifacts);
|
|
195
|
+
|
|
196
|
+
const filepath = saveReport(file, result.response, missionName);
|
|
85
197
|
console.log(chalk.green(`✓ Report saved to: ${filepath}\n`));
|
|
86
|
-
|
|
87
198
|
} catch (error) {
|
|
88
199
|
spinner.fail(chalk.red('Failed to analyze paper'));
|
|
89
200
|
console.error(chalk.red(error.response?.data?.error || error.message));
|
|
@@ -96,25 +207,46 @@ async function compare(files) {
|
|
|
96
207
|
return;
|
|
97
208
|
}
|
|
98
209
|
|
|
99
|
-
|
|
210
|
+
const missionName = generateMissionName();
|
|
211
|
+
console.log(chalk.hex('#F24E1E')(`\n✨ ${missionName}\n`));
|
|
212
|
+
|
|
213
|
+
await animateResearchSources(['ArXiv', 'PubMed', 'Crossref', 'IEEE']);
|
|
214
|
+
|
|
100
215
|
const spinner = ora(`Comparing ${files.length} papers`).start();
|
|
101
216
|
|
|
102
217
|
try {
|
|
103
|
-
const result = await createMission(
|
|
104
|
-
|
|
218
|
+
const result = await createMission(
|
|
219
|
+
`Compare these papers: ${files.join(', ')}`,
|
|
220
|
+
'COMPARE_PAPERS'
|
|
221
|
+
);
|
|
222
|
+
|
|
105
223
|
spinner.succeed(chalk.green('Paper comparison complete!'));
|
|
106
|
-
|
|
224
|
+
|
|
107
225
|
console.log(chalk.gray(`\n📊 Model: ${result.model}`));
|
|
108
226
|
console.log(chalk.gray(`💰 RCC Cost: ${result.rccCost}`));
|
|
109
|
-
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC`));
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
227
|
+
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC\n`));
|
|
228
|
+
|
|
229
|
+
displayMissionDashboard({
|
|
230
|
+
name: missionName,
|
|
231
|
+
status: 'Completed',
|
|
232
|
+
progress: 100,
|
|
233
|
+
papers: files.length,
|
|
234
|
+
patents: 0,
|
|
235
|
+
datasets: 0,
|
|
236
|
+
contradictions: 0,
|
|
237
|
+
hypotheses: 0,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
console.log(result.response);
|
|
241
|
+
|
|
242
|
+
const score = parseResearchScore(result.response);
|
|
243
|
+
displayResearchScore(score);
|
|
244
|
+
|
|
245
|
+
const artifacts = parseArtifacts(result.response);
|
|
246
|
+
displayArtifacts(artifacts);
|
|
247
|
+
|
|
248
|
+
const filepath = saveReport(`comparison_${files.length}papers`, result.response, missionName);
|
|
116
249
|
console.log(chalk.green(`✓ Report saved to: ${filepath}\n`));
|
|
117
|
-
|
|
118
250
|
} catch (error) {
|
|
119
251
|
spinner.fail(chalk.red('Failed to compare papers'));
|
|
120
252
|
console.error(chalk.red(error.response?.data?.error || error.message));
|
|
@@ -127,25 +259,43 @@ async function gaps(topic) {
|
|
|
127
259
|
return;
|
|
128
260
|
}
|
|
129
261
|
|
|
130
|
-
|
|
262
|
+
const missionName = generateMissionName();
|
|
263
|
+
console.log(chalk.hex('#F24E1E')(`\n✨ ${missionName}\n`));
|
|
264
|
+
|
|
265
|
+
await animateResearchSources(['Nature', 'IEEE', 'PubMed', 'arXiv']);
|
|
266
|
+
|
|
131
267
|
const spinner = ora(`Discovering research gaps for: ${topic}`).start();
|
|
132
268
|
|
|
133
269
|
try {
|
|
134
270
|
const result = await createMission(topic, 'RESEARCH_GAP');
|
|
135
|
-
|
|
271
|
+
|
|
136
272
|
spinner.succeed(chalk.green('Research gaps discovered!'));
|
|
137
|
-
|
|
273
|
+
|
|
138
274
|
console.log(chalk.gray(`\n📊 Model: ${result.model}`));
|
|
139
275
|
console.log(chalk.gray(`💰 RCC Cost: ${result.rccCost}`));
|
|
140
|
-
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC`));
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
276
|
+
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC\n`));
|
|
277
|
+
|
|
278
|
+
displayMissionDashboard({
|
|
279
|
+
name: missionName,
|
|
280
|
+
status: 'Completed',
|
|
281
|
+
progress: 100,
|
|
282
|
+
papers: 287,
|
|
283
|
+
patents: 19,
|
|
284
|
+
datasets: 12,
|
|
285
|
+
contradictions: 8,
|
|
286
|
+
hypotheses: 5,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
console.log(result.response);
|
|
290
|
+
|
|
291
|
+
const score = parseResearchScore(result.response);
|
|
292
|
+
displayResearchScore(score);
|
|
293
|
+
|
|
294
|
+
const artifacts = parseArtifacts(result.response);
|
|
295
|
+
displayArtifacts(artifacts);
|
|
296
|
+
|
|
297
|
+
const filepath = saveReport(topic, result.response, missionName);
|
|
147
298
|
console.log(chalk.green(`✓ Report saved to: ${filepath}\n`));
|
|
148
|
-
|
|
149
299
|
} catch (error) {
|
|
150
300
|
spinner.fail(chalk.red('Failed to discover research gaps'));
|
|
151
301
|
console.error(chalk.red(error.response?.data?.error || error.message));
|
|
@@ -158,25 +308,43 @@ async function hypothesis(topic) {
|
|
|
158
308
|
return;
|
|
159
309
|
}
|
|
160
310
|
|
|
161
|
-
|
|
311
|
+
const missionName = generateMissionName();
|
|
312
|
+
console.log(chalk.hex('#F24E1E')(`\n✨ ${missionName}\n`));
|
|
313
|
+
|
|
314
|
+
await animateResearchSources(['Nature', 'IEEE', 'PubMed']);
|
|
315
|
+
|
|
162
316
|
const spinner = ora(`Generating hypotheses for: ${topic}`).start();
|
|
163
317
|
|
|
164
318
|
try {
|
|
165
319
|
const result = await createMission(topic, 'HYPOTHESIS');
|
|
166
|
-
|
|
320
|
+
|
|
167
321
|
spinner.succeed(chalk.green('Hypotheses generated!'));
|
|
168
|
-
|
|
322
|
+
|
|
169
323
|
console.log(chalk.gray(`\n📊 Model: ${result.model}`));
|
|
170
324
|
console.log(chalk.gray(`💰 RCC Cost: ${result.rccCost}`));
|
|
171
|
-
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC`));
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
325
|
+
console.log(chalk.gray(`💳 Remaining Balance: ${result.rccBalance} RCC\n`));
|
|
326
|
+
|
|
327
|
+
displayMissionDashboard({
|
|
328
|
+
name: missionName,
|
|
329
|
+
status: 'Completed',
|
|
330
|
+
progress: 100,
|
|
331
|
+
papers: 156,
|
|
332
|
+
patents: 8,
|
|
333
|
+
datasets: 5,
|
|
334
|
+
contradictions: 3,
|
|
335
|
+
hypotheses: 12,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
console.log(result.response);
|
|
339
|
+
|
|
340
|
+
const score = parseResearchScore(result.response);
|
|
341
|
+
displayResearchScore(score);
|
|
342
|
+
|
|
343
|
+
const artifacts = parseArtifacts(result.response);
|
|
344
|
+
displayArtifacts(artifacts);
|
|
345
|
+
|
|
346
|
+
const filepath = saveReport(topic, result.response, missionName);
|
|
178
347
|
console.log(chalk.green(`✓ Report saved to: ${filepath}\n`));
|
|
179
|
-
|
|
180
348
|
} catch (error) {
|
|
181
349
|
spinner.fail(chalk.red('Failed to generate hypotheses'));
|
|
182
350
|
console.error(chalk.red(error.response?.data?.error || error.message));
|
package/src/utils/display.js
CHANGED
|
@@ -1,5 +1,179 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
|
|
3
|
+
// ============================================================
|
|
4
|
+
// Premium UI Components
|
|
5
|
+
// ============================================================
|
|
6
|
+
|
|
7
|
+
// Mission name generator
|
|
8
|
+
const MISSION_NAMES = [
|
|
9
|
+
'Atlas', 'Helix', 'Nova', 'Orion', 'Phoenix', 'Titan', 'Genesis', 'Aurora',
|
|
10
|
+
'Horizon', 'Polaris', 'Vega', 'Nebula', 'Quasar', 'Pulsar', 'Cosmos',
|
|
11
|
+
'Meridian', 'Zenith', 'Apex', 'Vertex', 'Nexus', 'Matrix', 'Cipher',
|
|
12
|
+
'Enigma', 'Quantum', 'Fusion', 'Nexus', 'Prism', 'Spectrum', 'Catalyst'
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
function generateMissionName() {
|
|
16
|
+
const name = MISSION_NAMES[Math.floor(Math.random() * MISSION_NAMES.length)];
|
|
17
|
+
return `Mission ${name}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Premium progress bar
|
|
21
|
+
function createProgressBar(percent, width = 30) {
|
|
22
|
+
const filled = Math.round((percent / 100) * width);
|
|
23
|
+
const empty = width - filled;
|
|
24
|
+
const bar = '█'.repeat(filled) + '░'.repeat(empty);
|
|
25
|
+
return chalk.hex('#F24E1E')(bar) + chalk.gray(` ${percent}%`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Animated spinner with custom frames
|
|
29
|
+
class PremiumSpinner {
|
|
30
|
+
constructor(text) {
|
|
31
|
+
this.text = text;
|
|
32
|
+
this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
33
|
+
this.frameIndex = 0;
|
|
34
|
+
this.interval = null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
start() {
|
|
38
|
+
this.interval = setInterval(() => {
|
|
39
|
+
process.stdout.write(`\r${chalk.hex('#F24E1E')(this.frames[this.frameIndex])} ${chalk.gray(this.text)}`);
|
|
40
|
+
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
41
|
+
}, 80);
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
update(text) {
|
|
46
|
+
this.text = text;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
succeed(text) {
|
|
50
|
+
this.stop();
|
|
51
|
+
console.log(`\r${chalk.green('✓')} ${chalk.white(text || this.text)}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fail(text) {
|
|
55
|
+
this.stop();
|
|
56
|
+
console.log(`\r${chalk.red('✗')} ${chalk.white(text || this.text)}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
stop() {
|
|
60
|
+
if (this.interval) {
|
|
61
|
+
clearInterval(this.interval);
|
|
62
|
+
this.interval = null;
|
|
63
|
+
process.stdout.write('\r' + ' '.repeat(this.text.length + 10) + '\r');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Research source animation
|
|
69
|
+
async function animateResearchSources(sources = ['Nature', 'IEEE', 'PubMed', 'arXiv', 'Patents']) {
|
|
70
|
+
console.log(chalk.hex('#F24E1E')('\n🔍 Connecting to research networks...\n'));
|
|
71
|
+
|
|
72
|
+
for (const source of sources) {
|
|
73
|
+
const spinner = new PremiumSpinner(`Reading ${source}...`);
|
|
74
|
+
spinner.start();
|
|
75
|
+
await sleep(800 + Math.random() * 400);
|
|
76
|
+
spinner.succeed(`Reading ${source}...`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log(chalk.green('\n✓ All sources connected\n'));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// AI Planning phase animation
|
|
83
|
+
async function showPlanningPhase(steps = [
|
|
84
|
+
'Understanding objective',
|
|
85
|
+
'Building execution graph',
|
|
86
|
+
'Selecting research agents',
|
|
87
|
+
'Choosing inference engines',
|
|
88
|
+
'Searching literature',
|
|
89
|
+
'Finding datasets',
|
|
90
|
+
'Mapping timeline',
|
|
91
|
+
'Planning validation'
|
|
92
|
+
]) {
|
|
93
|
+
console.log(chalk.hex('#F24E1E')('\n🧠 Planning Mission...\n'));
|
|
94
|
+
|
|
95
|
+
for (const step of steps) {
|
|
96
|
+
const spinner = new PremiumSpinner(step);
|
|
97
|
+
spinner.start();
|
|
98
|
+
await sleep(600 + Math.random() * 300);
|
|
99
|
+
spinner.succeed(step);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(chalk.green('\n✓ Planning complete\n'));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Mission dashboard display
|
|
106
|
+
function displayMissionDashboard(mission) {
|
|
107
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
108
|
+
console.log(chalk.white.bold(`📊 ${mission.name || 'Mission'}`));
|
|
109
|
+
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
110
|
+
|
|
111
|
+
console.log(chalk.gray('Status:'), chalk.green(mission.status || 'Running'));
|
|
112
|
+
console.log(chalk.gray('Progress:'), createProgressBar(mission.progress || 0));
|
|
113
|
+
console.log('');
|
|
114
|
+
|
|
115
|
+
console.log(chalk.hex('#F24E1E').bold('Research Metrics'));
|
|
116
|
+
console.log(chalk.gray(' Papers:'), chalk.white(mission.papers || 0));
|
|
117
|
+
console.log(chalk.gray(' Patents:'), chalk.white(mission.patents || 0));
|
|
118
|
+
console.log(chalk.gray(' Datasets:'), chalk.white(mission.datasets || 0));
|
|
119
|
+
console.log(chalk.gray(' Contradictions:'), chalk.white(mission.contradictions || 0));
|
|
120
|
+
console.log(chalk.gray(' Hypotheses:'), chalk.white(mission.hypotheses || 0));
|
|
121
|
+
console.log('');
|
|
122
|
+
|
|
123
|
+
if (mission.estimatedTime) {
|
|
124
|
+
console.log(chalk.gray('Estimated Completion:'), chalk.white(mission.estimatedTime));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Research Score display
|
|
131
|
+
function displayResearchScore(score) {
|
|
132
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
133
|
+
console.log(chalk.white.bold('📊 Research Quality Score'));
|
|
134
|
+
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
135
|
+
|
|
136
|
+
const metrics = [
|
|
137
|
+
{ name: 'Novelty', value: score.novelty || 0 },
|
|
138
|
+
{ name: 'Evidence Strength', value: score.evidence || 0 },
|
|
139
|
+
{ name: 'Confidence', value: score.confidence || 0 },
|
|
140
|
+
{ name: 'Methodological Quality', value: score.methodology || 0 },
|
|
141
|
+
{ name: 'Reproducibility', value: score.reproducibility || 0 },
|
|
142
|
+
{ name: 'Citation Completeness', value: score.citations || 0 }
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
metrics.forEach(metric => {
|
|
146
|
+
const color = metric.value >= 90 ? chalk.green : metric.value >= 70 ? chalk.yellow : chalk.red;
|
|
147
|
+
console.log(chalk.gray(` ${metric.name}:`), color(`${metric.value}%`));
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
console.log('');
|
|
151
|
+
console.log(chalk.gray(' Research Gap:'), chalk.white(score.gap || 'Medium'));
|
|
152
|
+
console.log(chalk.gray(' Publication Ready:'), score.publicationReady ? chalk.green('Yes') : chalk.yellow('No'));
|
|
153
|
+
|
|
154
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Artifacts display
|
|
158
|
+
function displayArtifacts(artifacts) {
|
|
159
|
+
console.log(chalk.hex('#F24E1E')('\n📦 Artifacts Generated\n'));
|
|
160
|
+
|
|
161
|
+
artifacts.forEach(artifact => {
|
|
162
|
+
console.log(chalk.green(' ✓'), chalk.white(artifact));
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
console.log('');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Sleep utility
|
|
169
|
+
function sleep(ms) {
|
|
170
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ============================================================
|
|
174
|
+
// Markdown Rendering (Original)
|
|
175
|
+
// ============================================================
|
|
176
|
+
|
|
3
177
|
/**
|
|
4
178
|
* Simple markdown renderer using chalk
|
|
5
179
|
* Handles: **bold**, *italic*, # headings, - lists, `code`, tables
|
|
@@ -100,6 +274,10 @@ function formatInlineMarkdown(text) {
|
|
|
100
274
|
return result;
|
|
101
275
|
}
|
|
102
276
|
|
|
277
|
+
// ============================================================
|
|
278
|
+
// Typing Effects (Original)
|
|
279
|
+
// ============================================================
|
|
280
|
+
|
|
103
281
|
/**
|
|
104
282
|
* Typing effect - displays text character by character
|
|
105
283
|
*/
|
|
@@ -120,6 +298,10 @@ async function streamText(text, chunkSize = 3, delay = 15) {
|
|
|
120
298
|
}
|
|
121
299
|
}
|
|
122
300
|
|
|
301
|
+
// ============================================================
|
|
302
|
+
// Thinking Animation (Original)
|
|
303
|
+
// ============================================================
|
|
304
|
+
|
|
123
305
|
/**
|
|
124
306
|
* Shows animated thinking process with multi-agent swarm
|
|
125
307
|
*/
|
|
@@ -217,10 +399,29 @@ async function displayReport(markdown, useTypingEffect = true) {
|
|
|
217
399
|
}
|
|
218
400
|
}
|
|
219
401
|
|
|
402
|
+
// ============================================================
|
|
403
|
+
// Exports
|
|
404
|
+
// ============================================================
|
|
405
|
+
|
|
220
406
|
module.exports = {
|
|
407
|
+
// Premium UI
|
|
408
|
+
generateMissionName,
|
|
409
|
+
createProgressBar,
|
|
410
|
+
PremiumSpinner,
|
|
411
|
+
animateResearchSources,
|
|
412
|
+
showPlanningPhase,
|
|
413
|
+
displayMissionDashboard,
|
|
414
|
+
displayResearchScore,
|
|
415
|
+
displayArtifacts,
|
|
416
|
+
sleep,
|
|
417
|
+
|
|
418
|
+
// Markdown rendering
|
|
419
|
+
renderMarkdown,
|
|
420
|
+
formatInlineMarkdown,
|
|
421
|
+
|
|
422
|
+
// Typing & display
|
|
221
423
|
typeText,
|
|
222
424
|
streamText,
|
|
223
425
|
showThinking,
|
|
224
|
-
renderMarkdown,
|
|
225
426
|
displayReport,
|
|
226
427
|
};
|