omnibiofex 2.8.5 → 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.
- package/bin/obx +30 -158
- package/package.json +13 -28
- package/src/auth.js +181 -381
- package/src/commands/account.js +35 -88
- package/src/commands/data.js +40 -114
- package/src/commands/debug.js +28 -25
- package/src/commands/earnings.js +31 -86
- package/src/commands/mission.js +194 -98
- package/src/commands/morning.js +39 -107
- package/src/commands/open.js +26 -36
- package/src/commands/publish.js +81 -126
- package/src/commands/research.js +148 -281
- package/src/commands/timeline.js +15 -54
- package/src/firebase.js +4 -14
- package/src/user.js +94 -0
- package/src/utils/display.js +27 -856
- package/src/api.js +0 -72
- package/src/config.js +0 -16
package/src/commands/mission.js
CHANGED
|
@@ -1,147 +1,243 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const inquirer = require('inquirer');
|
|
3
|
-
const {
|
|
4
|
-
const {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
const { getAuthToken, isAuthenticated } = require('../auth');
|
|
4
|
+
const { PremiumSpinner, sleep, typeAIResponse } = require('../utils/display');
|
|
5
|
+
|
|
6
|
+
const BACKEND_URL = 'https://obxvisionassistant-yyedhmslhq-uc.a.run.app';
|
|
7
|
+
const GET_USER_DATA_URL = 'https://getuserdata-yyedhmslhq-uc.a.run.app';
|
|
8
|
+
|
|
9
|
+
const RCC_COSTS = {
|
|
10
|
+
QUICK_RESEARCH: 10,
|
|
11
|
+
DEEP_RESEARCH: 50,
|
|
12
|
+
LITERATURE_REVIEW: 100,
|
|
13
|
+
MULTI_AGENT: 150
|
|
14
|
+
};
|
|
15
|
+
|
|
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
|
+
];
|
|
21
|
+
|
|
22
|
+
function generateMissionName() {
|
|
23
|
+
return `Mission ${MISSION_NAMES[Math.floor(Math.random() * MISSION_NAMES.length)]}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ✅ Helper: Fetch user data from backend
|
|
27
|
+
async function fetchUserData(token) {
|
|
28
|
+
const response = await fetch(GET_USER_DATA_URL, {
|
|
29
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const err = await response.json().catch(() => ({ error: `HTTP ${response.status}` }));
|
|
33
|
+
throw new Error(err.error || `Backend returned ${response.status}`);
|
|
34
|
+
}
|
|
35
|
+
return await response.json();
|
|
36
|
+
}
|
|
13
37
|
|
|
14
38
|
async function missionCreate() {
|
|
15
39
|
if (!isAuthenticated()) {
|
|
16
40
|
console.error(chalk.red('✗ Not authenticated. Please run: obx login'));
|
|
41
|
+
process.exit(1);
|
|
17
42
|
return;
|
|
18
43
|
}
|
|
19
44
|
|
|
20
|
-
console.log(chalk.hex('#F24E1E')
|
|
45
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
46
|
+
console.log(chalk.white.bold('🎯 CREATE RESEARCH MISSION'));
|
|
47
|
+
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
21
48
|
|
|
22
49
|
const answers = await inquirer.prompt([
|
|
50
|
+
{ type: 'input', name: 'topic', message: 'Research topic:', validate: (i) => i.length > 0 || 'Required' },
|
|
23
51
|
{
|
|
24
|
-
type: '
|
|
25
|
-
name: 'topic',
|
|
26
|
-
message: 'Research topic:',
|
|
27
|
-
validate: (input) => input.length > 0 || 'Topic is required'
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
type: 'list',
|
|
31
|
-
name: 'depth',
|
|
32
|
-
message: 'Research depth:',
|
|
52
|
+
type: 'list', name: 'depth', message: 'Research depth:',
|
|
33
53
|
choices: [
|
|
34
|
-
{ name: 'Quick (10 RCC)', value: 'QUICK_RESEARCH' },
|
|
35
|
-
{ name: 'Deep (50 RCC)', value: 'DEEP_RESEARCH' },
|
|
54
|
+
{ name: 'Quick Research (10 RCC)', value: 'QUICK_RESEARCH' },
|
|
55
|
+
{ name: 'Deep Research (50 RCC)', value: 'DEEP_RESEARCH' },
|
|
36
56
|
{ name: 'Literature Review (100 RCC)', value: 'LITERATURE_REVIEW' },
|
|
37
57
|
{ name: 'Academic (150 RCC)', value: 'MULTI_AGENT' }
|
|
38
58
|
]
|
|
39
59
|
}
|
|
40
60
|
]);
|
|
41
61
|
|
|
62
|
+
const cost = RCC_COSTS[answers.depth] || 10;
|
|
42
63
|
const missionName = generateMissionName();
|
|
43
64
|
|
|
44
|
-
console.log(chalk.hex('#F24E1E')(
|
|
45
|
-
console.log(chalk.white.bold(`✨ ${missionName}`));
|
|
46
|
-
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════'));
|
|
47
|
-
console.log(chalk.gray(`Topic: ${answers.topic}`));
|
|
48
|
-
console.log(chalk.gray(`Depth: ${answers.depth}\n`));
|
|
65
|
+
console.log(chalk.hex('#F24E1E')(`\n✨ ${missionName}`));
|
|
49
66
|
|
|
50
|
-
|
|
51
|
-
|
|
67
|
+
const steps = [
|
|
68
|
+
'🧠 Planning Mission...', '✓ Understanding objective', '✓ Building execution graph',
|
|
69
|
+
'✓ Selecting research agents', '✓ Choosing inference engines', '✓ Searching literature',
|
|
70
|
+
'✓ Finding datasets', '✓ Mapping timeline', '✓ Planning validation'
|
|
71
|
+
];
|
|
52
72
|
|
|
53
|
-
const
|
|
54
|
-
{
|
|
55
|
-
type: 'confirm',
|
|
56
|
-
name: 'start',
|
|
57
|
-
message: 'Begin mission?',
|
|
58
|
-
default: true
|
|
59
|
-
}
|
|
60
|
-
]);
|
|
73
|
+
for (const step of steps) { console.log(chalk.white(step)); await sleep(300); }
|
|
61
74
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
75
|
+
const { start } = await inquirer.prompt([{
|
|
76
|
+
type: 'confirm', name: 'start', message: 'Begin mission?', default: true
|
|
77
|
+
}]);
|
|
78
|
+
|
|
79
|
+
if (!start) { console.log(chalk.yellow('Mission cancelled.')); process.exit(0); return; }
|
|
66
80
|
|
|
67
|
-
const spinner = new PremiumSpinner('
|
|
81
|
+
const spinner = new PremiumSpinner('Creating mission');
|
|
68
82
|
spinner.start();
|
|
69
83
|
|
|
70
84
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
const token = await getAuthToken();
|
|
86
|
+
spinner.update('Calling AI backend');
|
|
73
87
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
status: 'Running',
|
|
79
|
-
progress: 0,
|
|
80
|
-
papers: 0,
|
|
81
|
-
patents: 0,
|
|
82
|
-
datasets: 0,
|
|
83
|
-
contradictions: 0,
|
|
84
|
-
hypotheses: 0,
|
|
85
|
-
estimatedTime: result.estimatedTime || '18 minutes'
|
|
88
|
+
const response = await fetch(BACKEND_URL, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
|
|
91
|
+
body: JSON.stringify({ taskType: answers.depth, message: answers.topic, model: 'deep' })
|
|
86
92
|
});
|
|
93
|
+
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
const errorData = await response.json().catch(() => ({ error: `HTTP ${response.status}` }));
|
|
96
|
+
throw new Error(errorData.error || `Backend returned ${response.status}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const data = await response.json();
|
|
100
|
+
spinner.succeed('✓ Mission completed');
|
|
101
|
+
|
|
102
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
103
|
+
console.log(chalk.white.bold(`📊 ${missionName} - Completed`));
|
|
104
|
+
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
105
|
+
|
|
106
|
+
console.log(chalk.white(` 📌 Topic: ${chalk.hex('#F24E1E')(answers.topic)}`));
|
|
107
|
+
console.log(chalk.white(` ⛽ RCC Cost: ${chalk.green(cost + ' RCC')}`));
|
|
108
|
+
console.log(chalk.white(` 🤖 Model: ${chalk.gray(data.model || 'Deep Reasoning Engine™')}`));
|
|
109
|
+
console.log(chalk.white(` 💳 Balance: ${chalk.gray((data.rccBalance || 0).toLocaleString()) + ' RCC'}`));
|
|
110
|
+
|
|
111
|
+
console.log(chalk.white.bold('\n\n📄 Research Report'));
|
|
112
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
113
|
+
await typeAIResponse(data.response || 'Report not available.');
|
|
114
|
+
|
|
115
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
116
|
+
console.log(chalk.white.bold('📦 ARTIFACTS GENERATED'));
|
|
117
|
+
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
87
118
|
|
|
88
|
-
console.log(chalk.
|
|
89
|
-
console.log(chalk.
|
|
90
|
-
console.log(chalk.
|
|
91
|
-
console.log(chalk.
|
|
92
|
-
console.log(chalk.
|
|
93
|
-
|
|
119
|
+
console.log(chalk.green(' ✓ Literature Review'));
|
|
120
|
+
console.log(chalk.green(' ✓ Research Timeline'));
|
|
121
|
+
console.log(chalk.green(' ✓ Gap Analysis'));
|
|
122
|
+
console.log(chalk.green(' ✓ Citation Database'));
|
|
123
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
|
|
124
|
+
console.log(chalk.gray('Next steps: obx publish | obx earnings | obx mission status\n'));
|
|
125
|
+
process.exit(0);
|
|
126
|
+
|
|
94
127
|
} catch (error) {
|
|
95
128
|
spinner.fail('Failed to create mission');
|
|
96
|
-
console.error(chalk.red(error.
|
|
129
|
+
console.error(chalk.red(error.message));
|
|
130
|
+
process.exit(1);
|
|
97
131
|
}
|
|
98
132
|
}
|
|
99
133
|
|
|
100
134
|
async function missionStatus() {
|
|
101
|
-
if (!isAuthenticated()) {
|
|
102
|
-
console.error(chalk.red('✗ Not authenticated. Please run: obx login'));
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
console.log(chalk.hex('#F24E1E').bold('\n📊 Active Missions\n'));
|
|
107
|
-
|
|
108
|
-
// Simulate a mission for demo
|
|
109
|
-
await displayMissionDashboard({
|
|
110
|
-
name: 'Mission Atlas',
|
|
111
|
-
status: 'Running',
|
|
112
|
-
progress: 52,
|
|
113
|
-
papers: 243,
|
|
114
|
-
patents: 12,
|
|
115
|
-
datasets: 8,
|
|
116
|
-
contradictions: 5,
|
|
117
|
-
hypotheses: 3,
|
|
118
|
-
estimatedTime: '11 minutes'
|
|
119
|
-
});
|
|
135
|
+
if (!isAuthenticated()) { console.error(chalk.red('✗ Not authenticated')); process.exit(1); return; }
|
|
120
136
|
|
|
121
|
-
console.log(chalk.
|
|
137
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
138
|
+
console.log(chalk.white.bold('📊 ACTIVE MISSIONS'));
|
|
139
|
+
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
140
|
+
|
|
141
|
+
const spinner = new PremiumSpinner('Fetching missions');
|
|
142
|
+
spinner.start();
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
const token = await getAuthToken();
|
|
146
|
+
const userData = await fetchUserData(token);
|
|
147
|
+
spinner.succeed('Missions loaded');
|
|
148
|
+
|
|
149
|
+
const active = userData.missions.filter(m => m.status === 'running' || m.status === 'pending');
|
|
150
|
+
|
|
151
|
+
if (active.length === 0) {
|
|
152
|
+
console.log(chalk.yellow(' No active missions.\n'));
|
|
153
|
+
console.log(chalk.gray(' Create one with: obx mission create\n'));
|
|
154
|
+
} else {
|
|
155
|
+
active.forEach((m, i) => {
|
|
156
|
+
console.log(chalk.white(`\n ${i + 1}. ${chalk.hex('#F24E1E')(m.missionName || m.id)}`));
|
|
157
|
+
console.log(chalk.white(` Topic: ${(m.message || '').substring(0, 50)}`));
|
|
158
|
+
console.log(chalk.yellow(` Status: ${m.status}`));
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
process.exit(0);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
spinner.fail('Failed');
|
|
164
|
+
console.error(chalk.red(error.message));
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
122
167
|
}
|
|
123
168
|
|
|
124
169
|
async function missionResults() {
|
|
125
|
-
if (!isAuthenticated()) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
170
|
+
if (!isAuthenticated()) { console.error(chalk.red('✗ Not authenticated')); process.exit(1); return; }
|
|
171
|
+
|
|
172
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
173
|
+
console.log(chalk.white.bold('📄 COMPLETED MISSIONS'));
|
|
174
|
+
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
175
|
+
|
|
176
|
+
const spinner = new PremiumSpinner('Fetching missions');
|
|
177
|
+
spinner.start();
|
|
129
178
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
179
|
+
try {
|
|
180
|
+
const token = await getAuthToken();
|
|
181
|
+
const userData = await fetchUserData(token);
|
|
182
|
+
spinner.succeed('Missions loaded');
|
|
183
|
+
|
|
184
|
+
const completed = userData.missions.filter(m => m.status === 'completed');
|
|
185
|
+
|
|
186
|
+
if (completed.length === 0) {
|
|
187
|
+
console.log(chalk.yellow(' No completed missions.\n'));
|
|
188
|
+
} else {
|
|
189
|
+
completed.forEach((m, i) => {
|
|
190
|
+
const pub = m.isPublished ? chalk.green('✓ Published') : chalk.gray('○ Unpublished');
|
|
191
|
+
console.log(chalk.white(`\n ${i + 1}. ${chalk.hex('#F24E1E')(m.missionName || m.id)} ${pub}`));
|
|
192
|
+
console.log(chalk.white(` Topic: ${(m.message || '').substring(0, 50)}`));
|
|
193
|
+
console.log(chalk.gray(` Cost: ${m.rccCost || 0} RCC`));
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
process.exit(0);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
spinner.fail('Failed');
|
|
199
|
+
console.error(chalk.red(error.message));
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
135
202
|
}
|
|
136
203
|
|
|
137
204
|
async function missionList() {
|
|
138
|
-
if (!isAuthenticated()) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
205
|
+
if (!isAuthenticated()) { console.error(chalk.red('✗ Not authenticated')); process.exit(1); return; }
|
|
206
|
+
|
|
207
|
+
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
208
|
+
console.log(chalk.white.bold('📋 ALL MISSIONS'));
|
|
209
|
+
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
142
210
|
|
|
143
|
-
|
|
144
|
-
|
|
211
|
+
const spinner = new PremiumSpinner('Fetching missions');
|
|
212
|
+
spinner.start();
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
const token = await getAuthToken();
|
|
216
|
+
const userData = await fetchUserData(token);
|
|
217
|
+
spinner.succeed('Missions loaded');
|
|
218
|
+
|
|
219
|
+
const missions = userData.missions;
|
|
220
|
+
|
|
221
|
+
if (missions.length === 0) {
|
|
222
|
+
console.log(chalk.yellow(' No missions yet.\n'));
|
|
223
|
+
console.log(chalk.gray(' Create one with: obx mission create\n'));
|
|
224
|
+
} else {
|
|
225
|
+
console.log(chalk.white(` 📊 Total: ${userData.stats.totalMissions} missions`));
|
|
226
|
+
console.log(chalk.green(` ✅ Completed: ${userData.stats.completed}`));
|
|
227
|
+
console.log(chalk.yellow(` ⏳ Active: ${userData.stats.active}`));
|
|
228
|
+
console.log(chalk.hex('#F24E1E')(` 📤 Published: ${userData.stats.published}\n`));
|
|
229
|
+
|
|
230
|
+
missions.forEach((m, i) => {
|
|
231
|
+
const c = m.status === 'completed' ? chalk.green : m.status === 'running' ? chalk.yellow : chalk.gray;
|
|
232
|
+
console.log(chalk.white(` ${i + 1}. ${chalk.hex('#F24E1E')(m.missionName || m.id)} ${c(`(${m.status})`)}`));
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
process.exit(0);
|
|
236
|
+
} catch (error) {
|
|
237
|
+
spinner.fail('Failed');
|
|
238
|
+
console.error(chalk.red(error.message));
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
145
241
|
}
|
|
146
242
|
|
|
147
243
|
module.exports = { missionCreate, missionStatus, missionResults, missionList };
|
package/src/commands/morning.js
CHANGED
|
@@ -1,150 +1,82 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
-
const {
|
|
3
|
-
const {
|
|
4
|
-
const { PremiumSpinner, sleep } = require('../utils/display');
|
|
5
|
-
const { collection, query, where, orderBy, limit, getDocs } = require('firebase/firestore');
|
|
2
|
+
const { getAuthToken, isAuthenticated } = require('../auth');
|
|
3
|
+
const { PremiumSpinner } = require('../utils/display');
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
if (!isAuthenticated()) {
|
|
9
|
-
console.error(chalk.red('✗ Not authenticated. Please run: obx login'));
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
5
|
+
const GET_USER_DATA_URL = 'https://getuserdata-yyedhmslhq-uc.a.run.app';
|
|
12
6
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (!uid) {
|
|
17
|
-
console.error(chalk.red('✗ Could not extract user ID from token.'));
|
|
18
|
-
console.error(chalk.gray('Please run: obx login'));
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
7
|
+
async function morning() {
|
|
8
|
+
if (!isAuthenticated()) { console.error(chalk.red('✗ Not authenticated')); process.exit(1); return; }
|
|
21
9
|
|
|
22
|
-
const spinner = new PremiumSpinner('☀️ Fetching
|
|
10
|
+
const spinner = new PremiumSpinner('☀️ Fetching daily briefing');
|
|
23
11
|
spinner.start();
|
|
24
12
|
|
|
25
13
|
try {
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
const yesterdayStart = new Date(todayStart);
|
|
30
|
-
yesterdayStart.setDate(yesterdayStart.getDate() - 1);
|
|
31
|
-
|
|
32
|
-
// Fetch active missions
|
|
33
|
-
const activeQuery = query(
|
|
34
|
-
collection(db, 'missions'),
|
|
35
|
-
where('uid', '==', uid),
|
|
36
|
-
where('status', 'in', ['running', 'pending'])
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const activeSnapshot = await getDocs(activeQuery);
|
|
40
|
-
const activeMissions = [];
|
|
41
|
-
activeSnapshot.forEach(doc => {
|
|
42
|
-
activeMissions.push({ id: doc.id, ...doc.data() });
|
|
14
|
+
const token = await getAuthToken();
|
|
15
|
+
const response = await fetch(GET_USER_DATA_URL, {
|
|
16
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
43
17
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const sevenDaysAgo = new Date();
|
|
47
|
-
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
|
|
18
|
+
if (!response.ok) throw new Error(`Backend error: ${response.status}`);
|
|
19
|
+
const userData = await response.json();
|
|
48
20
|
|
|
49
|
-
const recentQuery = query(
|
|
50
|
-
collection(db, 'missions'),
|
|
51
|
-
where('uid', '==', uid),
|
|
52
|
-
where('status', '==', 'completed'),
|
|
53
|
-
orderBy('createdAt', 'desc'),
|
|
54
|
-
limit(10)
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
const recentSnapshot = await getDocs(recentQuery);
|
|
58
|
-
const recentMissions = [];
|
|
59
|
-
recentSnapshot.forEach(doc => {
|
|
60
|
-
recentMissions.push({ id: doc.id, ...doc.data() });
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Fetch published missions for earnings
|
|
64
|
-
const publishedQuery = query(
|
|
65
|
-
collection(db, 'missions'),
|
|
66
|
-
where('uid', '==', uid),
|
|
67
|
-
where('isPublished', '==', true)
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
const publishedSnapshot = await getDocs(publishedQuery);
|
|
71
|
-
const publishedMissions = [];
|
|
72
|
-
publishedSnapshot.forEach(doc => {
|
|
73
|
-
publishedMissions.push({ id: doc.id, ...doc.data() });
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const totalViews = publishedMissions.reduce((sum, m) => sum + (m.views || 0), 0);
|
|
77
|
-
const totalEarnings = publishedMissions.reduce((sum, m) => sum + (m.earnings || 0), 0);
|
|
78
|
-
|
|
79
21
|
spinner.succeed('Daily briefing loaded');
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
weekday: 'long',
|
|
84
|
-
year: 'numeric',
|
|
85
|
-
month: 'long',
|
|
86
|
-
day: 'numeric'
|
|
22
|
+
|
|
23
|
+
const today = new Date().toLocaleDateString('en-US', {
|
|
24
|
+
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
|
|
87
25
|
});
|
|
26
|
+
|
|
27
|
+
const active = userData.missions.filter(m => m.status === 'running' || m.status === 'pending');
|
|
28
|
+
const recent = userData.missions.filter(m => m.status === 'completed').slice(0, 5);
|
|
29
|
+
const published = userData.missions.filter(m => m.isPublished === true);
|
|
88
30
|
|
|
89
31
|
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
90
32
|
console.log(chalk.white.bold('☀️ GOOD MORNING, RESEARCHER!'));
|
|
91
33
|
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
92
|
-
|
|
93
|
-
console.log(chalk.gray(`
|
|
94
|
-
console.log(chalk.gray(` 📅 ${chalk.white(dateString)}`));
|
|
34
|
+
console.log(chalk.gray(` 👤 ${chalk.white(userData.user.name || userData.user.email)}`));
|
|
35
|
+
console.log(chalk.gray(` 📅 ${chalk.white(today)}`));
|
|
95
36
|
|
|
96
|
-
|
|
97
|
-
if (activeMissions.length > 0) {
|
|
37
|
+
if (active.length > 0) {
|
|
98
38
|
console.log(chalk.white.bold('\n\n🎯 ACTIVE MISSIONS'));
|
|
99
39
|
console.log(chalk.gray('─'.repeat(60)));
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
console.log(chalk.white(`\n ✨ ${chalk.hex('#F24E1E')(m.id)}`));
|
|
104
|
-
console.log(chalk.white(` Topic: ${topic}`));
|
|
40
|
+
active.forEach(m => {
|
|
41
|
+
console.log(chalk.white(`\n ✨ ${chalk.hex('#F24E1E')(m.missionName || m.id)}`));
|
|
42
|
+
console.log(chalk.white(` Topic: ${(m.message || '').substring(0, 50)}`));
|
|
105
43
|
console.log(chalk.yellow(` Status: ${m.status}`));
|
|
106
44
|
});
|
|
107
45
|
}
|
|
108
46
|
|
|
109
|
-
|
|
110
|
-
if (recentMissions.length > 0) {
|
|
47
|
+
if (recent.length > 0) {
|
|
111
48
|
console.log(chalk.white.bold('\n\n✅ RECENTLY COMPLETED'));
|
|
112
49
|
console.log(chalk.gray('─'.repeat(60)));
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const date = m.createdAt?.toDate?.().toLocaleDateString() || 'N/A';
|
|
117
|
-
console.log(chalk.white(`\n ${i + 1}. ${topic}`));
|
|
50
|
+
recent.forEach((m, i) => {
|
|
51
|
+
const date = m.createdAt ? new Date(m.createdAt).toLocaleDateString() : 'N/A';
|
|
52
|
+
console.log(chalk.white(`\n ${i + 1}. ${(m.message || '').substring(0, 50)}`));
|
|
118
53
|
console.log(chalk.gray(` Completed: ${date}`));
|
|
119
54
|
});
|
|
120
55
|
}
|
|
121
56
|
|
|
122
|
-
|
|
123
|
-
if (publishedMissions.length > 0) {
|
|
57
|
+
if (published.length > 0) {
|
|
124
58
|
console.log(chalk.white.bold('\n\n💰 EARNINGS SUMMARY'));
|
|
125
59
|
console.log(chalk.gray('─'.repeat(60)));
|
|
126
|
-
|
|
127
|
-
console.log(chalk.white(
|
|
128
|
-
console.log(chalk.white(`
|
|
129
|
-
console.log(chalk.white(` 💰 Total Earnings: ${chalk.green('₹' + totalEarnings.toLocaleString())}`));
|
|
60
|
+
console.log(chalk.white(`\n 📤 Published: ${chalk.green(published.length)}`));
|
|
61
|
+
console.log(chalk.white(` 👁 Views: ${chalk.green(userData.stats.totalViews.toLocaleString())}`));
|
|
62
|
+
console.log(chalk.white(` 💰 Earnings: ${chalk.green('₹' + userData.stats.totalEarnings.toLocaleString())}`));
|
|
130
63
|
}
|
|
131
64
|
|
|
132
|
-
// Recommendations
|
|
133
65
|
console.log(chalk.white.bold('\n\n💡 RECOMMENDATIONS'));
|
|
134
66
|
console.log(chalk.gray('─'.repeat(60)));
|
|
135
|
-
|
|
136
|
-
console.log(chalk.white('
|
|
137
|
-
console.log(chalk.white(' ▸
|
|
138
|
-
console.log(chalk.white(' ▸
|
|
139
|
-
console.log(chalk.white(' ▸ Generate new research with "obx mission create"'));
|
|
67
|
+
console.log(chalk.white('\n ▸ Check missions: "obx mission status"'));
|
|
68
|
+
console.log(chalk.white(' ▸ Publish research: "obx publish"'));
|
|
69
|
+
console.log(chalk.white(' ▸ View earnings: "obx earnings"'));
|
|
70
|
+
console.log(chalk.white(' ▸ New research: "obx mission create"'));
|
|
140
71
|
|
|
141
72
|
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
142
73
|
console.log(chalk.gray('Free • No RCC cost'));
|
|
143
74
|
console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
|
|
144
|
-
|
|
75
|
+
process.exit(0);
|
|
145
76
|
} catch (error) {
|
|
146
|
-
spinner.fail('Failed to fetch
|
|
77
|
+
spinner.fail('Failed to fetch briefing');
|
|
147
78
|
console.error(chalk.red(error.message));
|
|
79
|
+
process.exit(1);
|
|
148
80
|
}
|
|
149
81
|
}
|
|
150
82
|
|
package/src/commands/open.js
CHANGED
|
@@ -2,48 +2,36 @@ const chalk = require('chalk');
|
|
|
2
2
|
const open = require('open');
|
|
3
3
|
const inquirer = require('inquirer');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
'home': { url: 'https://x.omnibiofex.cloud/', name: 'Home Page' }
|
|
16
|
-
};
|
|
5
|
+
const pages = {
|
|
6
|
+
'dashboard': { url: 'https://x.omnibiofex.cloud/dash', name: 'Web Dashboard' },
|
|
7
|
+
'earn': { url: 'https://x.omnibiofex.cloud/earn', name: 'How to Earn' },
|
|
8
|
+
'pricing': { url: 'https://x.omnibiofex.cloud/pricing', name: 'Pricing Plans' },
|
|
9
|
+
'agents': { url: 'https://x.omnibiofex.cloud/agents', name: 'AI Agents' },
|
|
10
|
+
'how-it-works': { url: 'https://x.omnibiofex.cloud/how-it-works', name: 'How It Works' },
|
|
11
|
+
'commands': { url: 'https://x.omnibiofex.cloud/commands', name: 'Commands Reference' },
|
|
12
|
+
'cli-guide': { url: 'https://x.omnibiofex.cloud/cli-guide', name: 'CLI Guide' },
|
|
13
|
+
'home': { url: 'https://x.omnibiofex.cloud/', name: 'Home Page' }
|
|
14
|
+
};
|
|
17
15
|
|
|
16
|
+
async function openPage(page) {
|
|
18
17
|
if (!page) {
|
|
19
|
-
const { selectedPage } = await inquirer.prompt([
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
name: '
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{ name: '💳 Pricing Plans', value: 'pricing' },
|
|
29
|
-
{ name: '🤖 AI Agents', value: 'agents' },
|
|
30
|
-
{ name: '📖 How It Works', value: 'how-it-works' },
|
|
31
|
-
{ name: '⌨️ Commands Reference', value: 'commands' },
|
|
32
|
-
{ name: '📘 CLI Guide', value: 'cli-guide' }
|
|
33
|
-
]
|
|
34
|
-
}
|
|
35
|
-
]);
|
|
18
|
+
const { selectedPage } = await inquirer.prompt([{
|
|
19
|
+
type: 'list', name: 'selectedPage', message: 'Which page?',
|
|
20
|
+
choices: [
|
|
21
|
+
{ name: '🏠 Home', value: 'home' }, { name: '📊 Dashboard', value: 'dashboard' },
|
|
22
|
+
{ name: '💰 Earn', value: 'earn' }, { name: '💳 Pricing', value: 'pricing' },
|
|
23
|
+
{ name: '🤖 Agents', value: 'agents' }, { name: '📖 How It Works', value: 'how-it-works' },
|
|
24
|
+
{ name: '⌨️ Commands', value: 'commands' }, { name: '📘 CLI Guide', value: 'cli-guide' }
|
|
25
|
+
]
|
|
26
|
+
}]);
|
|
36
27
|
page = selectedPage;
|
|
37
28
|
}
|
|
38
29
|
|
|
39
30
|
const pageInfo = pages[page];
|
|
40
|
-
|
|
41
31
|
if (!pageInfo) {
|
|
42
32
|
console.error(chalk.red(`✗ Unknown page: ${page}`));
|
|
43
|
-
console.log(chalk.gray('\nAvailable pages
|
|
44
|
-
|
|
45
|
-
console.log(chalk.gray(` • ${key}`));
|
|
46
|
-
});
|
|
33
|
+
console.log(chalk.gray('\nAvailable: ' + Object.keys(pages).join(', ') + '\n'));
|
|
34
|
+
process.exit(1);
|
|
47
35
|
return;
|
|
48
36
|
}
|
|
49
37
|
|
|
@@ -52,10 +40,12 @@ async function openPage(page) {
|
|
|
52
40
|
|
|
53
41
|
try {
|
|
54
42
|
await open(pageInfo.url);
|
|
55
|
-
console.log(chalk.green(`✓ Opened ${pageInfo.name}
|
|
43
|
+
console.log(chalk.green(`✓ Opened ${pageInfo.name}\n`));
|
|
44
|
+
process.exit(0);
|
|
56
45
|
} catch (error) {
|
|
57
46
|
console.error(chalk.red('✗ Failed to open browser'));
|
|
58
|
-
console.log(chalk.gray(`\
|
|
47
|
+
console.log(chalk.gray(`\nVisit: ${pageInfo.url}\n`));
|
|
48
|
+
process.exit(1);
|
|
59
49
|
}
|
|
60
50
|
}
|
|
61
51
|
|