omnibiofex 2.4.1
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/LICENSE +21 -0
- package/README.md +168 -0
- package/bin/obx +40 -0
- package/package.json +60 -0
- package/src/api.js +67 -0
- package/src/auth.js +260 -0
- package/src/commands/account.js +47 -0
- package/src/commands/data.js +59 -0
- package/src/commands/mission.js +97 -0
- package/src/commands/research.js +101 -0
- package/src/config.js +13 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OmniBioFex
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# OmniBioFex X CLI
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**The Autonomous Research Terminal**
|
|
6
|
+
|
|
7
|
+
Execute AI-powered research missions from your terminal. Stop chatting. Start delegating.
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/omnibiofex)
|
|
10
|
+
[](https://nodejs.org)
|
|
11
|
+
[](https://opensource.org/licenses/MIT)
|
|
12
|
+
[](https://www.npmjs.com/package/omnibiofex)
|
|
13
|
+
|
|
14
|
+
[Website](https://x.omnibiofex.cloud) ⢠[Dashboard](https://x.omnibiofex.cloud/dash) ⢠[Documentation](https://x.omnibiofex.cloud/cli-guide)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## ⨠Features
|
|
21
|
+
|
|
22
|
+
- šÆ **Autonomous Missions** - Assign research, get structured reports
|
|
23
|
+
- š¤ **Multi-Agent Swarm** - 6 specialized AI agents collaborate in real-time
|
|
24
|
+
- š¾ **Persistent Memory** - Projects remember everything, even months later
|
|
25
|
+
- š **Secure Auth** - Passwordless Magic Link authentication
|
|
26
|
+
- ā” **Smart Routing** - Automatically routes to optimal AI engine
|
|
27
|
+
- š **Evidence-Backed** - Every conclusion includes sources and confidence scores
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## š Installation
|
|
32
|
+
|
|
33
|
+
### Quick Install (Recommended)
|
|
34
|
+
|
|
35
|
+
**macOS / Linux:**
|
|
36
|
+
curl -fsSL https://x.omnibiofex.cloud/install | sh
|
|
37
|
+
**Windows (PowerShell):**
|
|
38
|
+
irm https://x.omnibiofex.cloud/install.ps1 | iex
|
|
39
|
+
**Via npm**
|
|
40
|
+
npm install -g omnibiofex
|
|
41
|
+
**Verify Installation**
|
|
42
|
+
obx version
|
|
43
|
+
š Authentication
|
|
44
|
+
OmniBioFex X uses secure, passwordless Magic Link authentication.
|
|
45
|
+
bash
|
|
46
|
+
obx login
|
|
47
|
+
Flow:
|
|
48
|
+
Enter your email in the terminal
|
|
49
|
+
Check your inbox for the magic link
|
|
50
|
+
Click the link ā Automatically authenticated
|
|
51
|
+
You're ready to research!
|
|
52
|
+
New users get 2,500 free Research Compute Credits (RCC)! š
|
|
53
|
+
š Command Reference
|
|
54
|
+
Mission Commands
|
|
55
|
+
Command
|
|
56
|
+
Description
|
|
57
|
+
Cost
|
|
58
|
+
obx mission create
|
|
59
|
+
Start new autonomous research mission
|
|
60
|
+
Varies
|
|
61
|
+
obx mission status
|
|
62
|
+
Check active missions
|
|
63
|
+
Free
|
|
64
|
+
obx mission results
|
|
65
|
+
View completed mission reports
|
|
66
|
+
Free
|
|
67
|
+
obx mission list
|
|
68
|
+
List all missions (active + completed)
|
|
69
|
+
Free
|
|
70
|
+
Research Commands
|
|
71
|
+
Command
|
|
72
|
+
Description
|
|
73
|
+
Cost
|
|
74
|
+
obx literature <topic>
|
|
75
|
+
Generate comprehensive literature review
|
|
76
|
+
100 RCC
|
|
77
|
+
obx paper <file.pdf>
|
|
78
|
+
Analyze a research paper
|
|
79
|
+
40 RCC
|
|
80
|
+
obx compare <files...>
|
|
81
|
+
Compare multiple papers
|
|
82
|
+
80 RCC
|
|
83
|
+
obx gaps <topic>
|
|
84
|
+
Discover research gaps
|
|
85
|
+
120 RCC
|
|
86
|
+
obx hypothesis <topic>
|
|
87
|
+
Generate research hypotheses
|
|
88
|
+
100 RCC
|
|
89
|
+
Data Commands
|
|
90
|
+
Command
|
|
91
|
+
Description
|
|
92
|
+
Cost
|
|
93
|
+
obx dataset <file.csv>
|
|
94
|
+
Analyze dataset
|
|
95
|
+
40-150 RCC
|
|
96
|
+
obx code [directory]
|
|
97
|
+
Review code repository
|
|
98
|
+
40-300 RCC
|
|
99
|
+
obx medical <file.dcm>
|
|
100
|
+
Analyze medical imaging
|
|
101
|
+
30-120 RCC
|
|
102
|
+
Account Commands
|
|
103
|
+
Command
|
|
104
|
+
Description
|
|
105
|
+
obx credits
|
|
106
|
+
Check your RCC balance
|
|
107
|
+
obx usage
|
|
108
|
+
View usage statistics
|
|
109
|
+
obx buy
|
|
110
|
+
Open browser to purchase credits
|
|
111
|
+
obx login
|
|
112
|
+
Authenticate with your account
|
|
113
|
+
obx logout
|
|
114
|
+
Sign out
|
|
115
|
+
obx version
|
|
116
|
+
Show CLI version
|
|
117
|
+
š° Pricing
|
|
118
|
+
Research Compute Credits (RCC) - Pay only for what you use. No subscriptions. No hidden fees.
|
|
119
|
+
Pack
|
|
120
|
+
Credits
|
|
121
|
+
Price
|
|
122
|
+
Effective Rate
|
|
123
|
+
Starter
|
|
124
|
+
1,000
|
|
125
|
+
ā¹99
|
|
126
|
+
ā¹99/1K
|
|
127
|
+
Explorer
|
|
128
|
+
5,000
|
|
129
|
+
ā¹449
|
|
130
|
+
ā¹89.8/1K
|
|
131
|
+
Researcher
|
|
132
|
+
10,000
|
|
133
|
+
ā¹849
|
|
134
|
+
ā¹84.9/1K
|
|
135
|
+
Professional ā
|
|
136
|
+
25,000
|
|
137
|
+
ā¹1,999
|
|
138
|
+
ā¹80/1K
|
|
139
|
+
Advanced
|
|
140
|
+
50,000
|
|
141
|
+
ā¹3,799
|
|
142
|
+
ā¹76/1K
|
|
143
|
+
Laboratory
|
|
144
|
+
100,000
|
|
145
|
+
ā¹6,999
|
|
146
|
+
ā¹70/1K
|
|
147
|
+
Enterprise
|
|
148
|
+
500,000
|
|
149
|
+
ā¹29,999
|
|
150
|
+
ā¹60/1K
|
|
151
|
+
š New users get 2,500 free RCC on signup!
|
|
152
|
+
Purchase credits via:
|
|
153
|
+
Web Dashboard: https://x.omnibiofex.cloud/dash
|
|
154
|
+
CLI: obx buy
|
|
155
|
+
šÆ Example Workflow
|
|
156
|
+
bash
|
|
157
|
+
123456789101112131415161718192021222324
|
|
158
|
+
š Resources
|
|
159
|
+
Website: https://x.omnibiofex.cloud
|
|
160
|
+
Dashboard: https://x.omnibiofex.cloud/dash
|
|
161
|
+
CLI Guide: https://x.omnibiofex.cloud/cli-guide
|
|
162
|
+
Pricing: https://x.omnibiofex.cloud/pricing
|
|
163
|
+
Vision: https://x.omnibiofex.cloud/vision
|
|
164
|
+
Architecture: https://x.omnibiofex.cloud/architecture
|
|
165
|
+
|
|
166
|
+
š License
|
|
167
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
168
|
+
Made with ā¤ļø by OmniBioFex
|
package/bin/obx
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { program } = require('commander');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const figlet = require('figlet');
|
|
5
|
+
const { login, logout } = require('../src/auth');
|
|
6
|
+
const { missionCreate, missionStatus, missionResults, missionList } = require('../src/commands/mission');
|
|
7
|
+
const { literatureReview, gaps, hypothesis } = require('../src/commands/research');
|
|
8
|
+
const { credits, usage, buy } = require('../src/commands/account');
|
|
9
|
+
|
|
10
|
+
console.log(chalk.hex('#F24E1E')(figlet.textSync('OmniBioFex X', { horizontalLayout: 'full' })));
|
|
11
|
+
console.log(chalk.gray('The Autonomous Research Terminal v2.4.1\n'));
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.command('login').description('Authenticate').action(login);
|
|
15
|
+
program
|
|
16
|
+
.command('logout').description('Sign out').action(logout);
|
|
17
|
+
program
|
|
18
|
+
.command('mission <action>').description('create | status | results | list')
|
|
19
|
+
.action(async (action) => {
|
|
20
|
+
const actions = { create: missionCreate, status: missionStatus, results: missionResults, list: missionList };
|
|
21
|
+
if (actions[action]) await actions[action]();
|
|
22
|
+
else console.error(chalk.red('Unknown action'));
|
|
23
|
+
});
|
|
24
|
+
program
|
|
25
|
+
.command('literature <topic>').description('Generate literature review').action(literatureReview);
|
|
26
|
+
program
|
|
27
|
+
.command('gaps <topic>').description('Discover research gaps').action(gaps);
|
|
28
|
+
program
|
|
29
|
+
.command('hypothesis <topic>').description('Generate hypotheses').action(hypothesis);
|
|
30
|
+
program
|
|
31
|
+
.command('credits').description('Check RCC balance').action(credits);
|
|
32
|
+
program
|
|
33
|
+
.command('usage').description('View usage').action(usage);
|
|
34
|
+
program
|
|
35
|
+
.command('buy').description('Purchase credits').action(buy);
|
|
36
|
+
program
|
|
37
|
+
.command('version').description('Show version').action(() => console.log(chalk.hex('#F24E1E')('OmniBioFex X v2.4.1')));
|
|
38
|
+
|
|
39
|
+
program.parse(process.argv);
|
|
40
|
+
if (!process.argv.slice(2).length) program.outputHelp();
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "omnibiofex",
|
|
3
|
+
"version": "2.4.1",
|
|
4
|
+
"description": "OmniBioFex X - The Autonomous Research Terminal for AI-powered research missions",
|
|
5
|
+
"main": "bin/obx",
|
|
6
|
+
"bin": {
|
|
7
|
+
"obx": "bin/obx"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/obx",
|
|
11
|
+
"test": "echo \"No tests yet\" && exit 0"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"ai",
|
|
15
|
+
"research",
|
|
16
|
+
"terminal",
|
|
17
|
+
"cli",
|
|
18
|
+
"autonomous",
|
|
19
|
+
"omnibiofex",
|
|
20
|
+
"academic",
|
|
21
|
+
"scientific",
|
|
22
|
+
"literature-review",
|
|
23
|
+
"research-agent",
|
|
24
|
+
"multi-agent"
|
|
25
|
+
],
|
|
26
|
+
"author": {
|
|
27
|
+
"name": "OmniBioFex",
|
|
28
|
+
"email": "omnibiofexcloud@gmail.com",
|
|
29
|
+
"url": "https://x.omnibiofex.cloud"
|
|
30
|
+
},
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"homepage": "https://x.omnibiofex.cloud",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/omnibiofex/omnibiofex-cli.git"
|
|
36
|
+
},
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/omnibiofex/omnibiofex-cli/issues"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=14.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"firebase": "^10.7.1",
|
|
45
|
+
"axios": "^1.6.2",
|
|
46
|
+
"chalk": "^4.1.2",
|
|
47
|
+
"commander": "^11.1.0",
|
|
48
|
+
"inquirer": "^8.2.6",
|
|
49
|
+
"open": "^8.4.2",
|
|
50
|
+
"ora": "^5.4.1",
|
|
51
|
+
"figlet": "^1.7.0",
|
|
52
|
+
"conf": "^10.2.0"
|
|
53
|
+
},
|
|
54
|
+
"files": [
|
|
55
|
+
"bin/",
|
|
56
|
+
"src/",
|
|
57
|
+
"README.md",
|
|
58
|
+
"LICENSE"
|
|
59
|
+
]
|
|
60
|
+
}
|
package/src/api.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const config = require('./config');
|
|
4
|
+
const { getAuthToken } = require('./auth');
|
|
5
|
+
|
|
6
|
+
const apiClient = axios.create({
|
|
7
|
+
timeout: 540000, // 9 minutes
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// Add auth header to all requests
|
|
11
|
+
apiClient.interceptors.request.use((requestConfig) => {
|
|
12
|
+
const token = getAuthToken();
|
|
13
|
+
requestConfig.headers.Authorization = `Bearer ${token}`;
|
|
14
|
+
return requestConfig;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Handle errors
|
|
18
|
+
apiClient.interceptors.response.use(
|
|
19
|
+
(response) => response,
|
|
20
|
+
(error) => {
|
|
21
|
+
if (error.response?.status === 401) {
|
|
22
|
+
console.error(chalk.red('Authentication expired. Please run: obx login'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
return Promise.reject(error);
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
async function createMission(topic, taskType) {
|
|
30
|
+
const response = await apiClient.post(config.get('apiUrl'), {
|
|
31
|
+
message: topic,
|
|
32
|
+
taskType: taskType,
|
|
33
|
+
conversationHistory: []
|
|
34
|
+
});
|
|
35
|
+
return response.data;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function analyzeFile(filePath, taskType) {
|
|
39
|
+
const fs = require('fs');
|
|
40
|
+
const fileBuffer = fs.readFileSync(filePath);
|
|
41
|
+
const base64Data = fileBuffer.toString('base64');
|
|
42
|
+
|
|
43
|
+
const response = await apiClient.post(config.get('apiUrl'), {
|
|
44
|
+
message: `Analyze this file: ${filePath}`,
|
|
45
|
+
taskType: taskType,
|
|
46
|
+
images: [`data:application/pdf;base64,${base64Data}`],
|
|
47
|
+
conversationHistory: []
|
|
48
|
+
});
|
|
49
|
+
return response.data;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// š„ FIXED: Actually call the backend endpoint
|
|
53
|
+
async function getUserCredits() {
|
|
54
|
+
try {
|
|
55
|
+
const response = await apiClient.get('https://getusercredits-yyedhmslhq-uc.a.run.app');
|
|
56
|
+
return {
|
|
57
|
+
balance: response.data.tokens || 0,
|
|
58
|
+
used: 0, // You can track this later
|
|
59
|
+
total: response.data.tokens || 0
|
|
60
|
+
};
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(chalk.red('Error fetching credits:'), error.message);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = { createMission, analyzeFile, getUserCredits };
|
package/src/auth.js
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const { URL } = require('url');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const inquirer = require('inquirer');
|
|
5
|
+
const { initializeApp } = require('firebase/app');
|
|
6
|
+
const { getAuth, sendSignInLinkToEmail } = require('firebase/auth');
|
|
7
|
+
const config = require('./config');
|
|
8
|
+
|
|
9
|
+
const firebaseConfig = {
|
|
10
|
+
apiKey: "AIzaSyDlgXId4pLlYqm-MDuhfz3dLH24KBRHkw8",
|
|
11
|
+
authDomain: "omnibiofex-x.firebaseapp.com",
|
|
12
|
+
projectId: "omnibiofex-x",
|
|
13
|
+
storageBucket: "omnibiofex-x.firebasestorage.app",
|
|
14
|
+
messagingSenderId: "292246591666",
|
|
15
|
+
appId: "1:292246591666:web:a182851585e4b0f79511ab",
|
|
16
|
+
measurementId: "G-RLQH7BDNHB"
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const app = initializeApp(firebaseConfig);
|
|
20
|
+
const auth = getAuth(app);
|
|
21
|
+
|
|
22
|
+
const LOCAL_PORT = 8765;
|
|
23
|
+
const CALLBACK_PATH = '/auth/callback';
|
|
24
|
+
|
|
25
|
+
async function login() {
|
|
26
|
+
console.log(chalk.hex('#F24E1E')('\nš OmniBioFex X Authentication\n'));
|
|
27
|
+
|
|
28
|
+
if (isAuthenticated()) {
|
|
29
|
+
const { confirm } = await inquirer.prompt([{
|
|
30
|
+
type: 'confirm',
|
|
31
|
+
name: 'confirm',
|
|
32
|
+
message: 'You are already logged in. Login again?',
|
|
33
|
+
default: false
|
|
34
|
+
}]);
|
|
35
|
+
if (!confirm) {
|
|
36
|
+
console.log(chalk.gray('Login cancelled.'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const { email } = await inquirer.prompt([{
|
|
42
|
+
type: 'input',
|
|
43
|
+
name: 'email',
|
|
44
|
+
message: 'Enter your email:',
|
|
45
|
+
validate: (input) => {
|
|
46
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
47
|
+
return emailRegex.test(input) || 'Please enter a valid email';
|
|
48
|
+
}
|
|
49
|
+
}]);
|
|
50
|
+
|
|
51
|
+
console.log(chalk.gray('\nš§ Sending magic link...'));
|
|
52
|
+
|
|
53
|
+
let server = null;
|
|
54
|
+
let spinner = null;
|
|
55
|
+
let timeout = null;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
server = startLocalServer();
|
|
59
|
+
|
|
60
|
+
const actionCodeSettings = {
|
|
61
|
+
url: `https://x.omnibiofex.cloud/auth?cli=true`,
|
|
62
|
+
handleCodeInApp: true
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
await sendSignInLinkToEmail(auth, email, actionCodeSettings);
|
|
66
|
+
|
|
67
|
+
config.set('pendingEmail', email);
|
|
68
|
+
config.set('pendingLogin', true);
|
|
69
|
+
|
|
70
|
+
console.log(chalk.green(`\nā Magic link sent to ${email}`));
|
|
71
|
+
console.log(chalk.gray('\nš¬ Check your inbox and click the link to complete login.'));
|
|
72
|
+
console.log(chalk.gray('ā³ Waiting for authentication... (press Ctrl+C to cancel)\n'));
|
|
73
|
+
|
|
74
|
+
const frames = ['ā ', 'ā ', 'ā ¹', 'ā ø', 'ā ¼', 'ā “', 'ā ¦', 'ā §', 'ā ', 'ā '];
|
|
75
|
+
let i = 0;
|
|
76
|
+
spinner = setInterval(() => {
|
|
77
|
+
process.stdout.write(`\r${chalk.hex('#F24E1E')(frames[i])} ${chalk.gray('Waiting for magic link click...')}`);
|
|
78
|
+
i = (i + 1) % frames.length;
|
|
79
|
+
}, 80);
|
|
80
|
+
|
|
81
|
+
timeout = setTimeout(() => {
|
|
82
|
+
cleanup();
|
|
83
|
+
console.log(chalk.red('\n\nā Authentication timed out. Please try again.'));
|
|
84
|
+
config.delete('pendingLogin');
|
|
85
|
+
config.delete('pendingEmail');
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}, 5 * 60 * 1000);
|
|
88
|
+
|
|
89
|
+
const token = await waitForAuth();
|
|
90
|
+
|
|
91
|
+
cleanup();
|
|
92
|
+
|
|
93
|
+
if (token) {
|
|
94
|
+
config.set('authToken', token);
|
|
95
|
+
config.set('userEmail', email);
|
|
96
|
+
config.delete('pendingLogin');
|
|
97
|
+
config.delete('pendingEmail');
|
|
98
|
+
|
|
99
|
+
console.log(chalk.green('\n\nā Successfully authenticated!'));
|
|
100
|
+
console.log(chalk.hex('#F24E1E')(`\nš Welcome to OmniBioFex X, ${email}!`));
|
|
101
|
+
console.log(chalk.gray('You can now use all CLI commands.\n'));
|
|
102
|
+
|
|
103
|
+
// š„ THE FIX: Exit the process cleanly
|
|
104
|
+
process.exit(0);
|
|
105
|
+
} else {
|
|
106
|
+
throw new Error('No token received');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
} catch (error) {
|
|
110
|
+
cleanup();
|
|
111
|
+
console.error(chalk.red(`\nā Authentication failed: ${error.message}`));
|
|
112
|
+
config.delete('pendingLogin');
|
|
113
|
+
config.delete('pendingEmail');
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function cleanup() {
|
|
118
|
+
if (spinner) {
|
|
119
|
+
clearInterval(spinner);
|
|
120
|
+
spinner = null;
|
|
121
|
+
process.stdout.write('\n');
|
|
122
|
+
}
|
|
123
|
+
if (timeout) {
|
|
124
|
+
clearTimeout(timeout);
|
|
125
|
+
timeout = null;
|
|
126
|
+
}
|
|
127
|
+
if (server) {
|
|
128
|
+
server.close();
|
|
129
|
+
server = null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function startLocalServer() {
|
|
135
|
+
const server = http.createServer((req, res) => {
|
|
136
|
+
const url = new URL(req.url, `http://localhost:${LOCAL_PORT}`);
|
|
137
|
+
|
|
138
|
+
// Ignore favicon requests
|
|
139
|
+
if (url.pathname === '/favicon.ico') {
|
|
140
|
+
res.writeHead(204);
|
|
141
|
+
res.end();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
console.log('Local server received request:', req.url);
|
|
146
|
+
|
|
147
|
+
if (url.pathname === CALLBACK_PATH) {
|
|
148
|
+
const token = url.searchParams.get('token');
|
|
149
|
+
const error = url.searchParams.get('error');
|
|
150
|
+
|
|
151
|
+
if (token) {
|
|
152
|
+
console.log('ā Received auth token from browser');
|
|
153
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
154
|
+
res.end(`
|
|
155
|
+
<!DOCTYPE html>
|
|
156
|
+
<html>
|
|
157
|
+
<head>
|
|
158
|
+
<title>OmniBioFex X - Authentication Successful</title>
|
|
159
|
+
<style>
|
|
160
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
161
|
+
background: #F4F4F0; color: #0F0F0F; display: flex; align-items: center;
|
|
162
|
+
justify-content: center; min-height: 100vh; margin: 0;
|
|
163
|
+
background-image: radial-gradient(#E0E0DB 1px, transparent 1px);
|
|
164
|
+
background-size: 40px 40px; }
|
|
165
|
+
.card { background: white; border: 1px solid #E0E0DB; padding: 48px;
|
|
166
|
+
max-width: 500px; text-align: center; }
|
|
167
|
+
.check { width: 64px; height: 64px; border-radius: 50%; background: #10b981;
|
|
168
|
+
color: white; font-size: 32px; display: flex; align-items: center;
|
|
169
|
+
justify-content: center; margin: 0 auto 24px; }
|
|
170
|
+
h1 { margin: 0 0 12px; font-size: 24px; }
|
|
171
|
+
p { color: #737373; margin: 0 0 24px; }
|
|
172
|
+
.close { color: #F24E1E; font-size: 14px; font-family: monospace; }
|
|
173
|
+
</style>
|
|
174
|
+
</head>
|
|
175
|
+
<body>
|
|
176
|
+
<div class="card">
|
|
177
|
+
<div class="check">ā</div>
|
|
178
|
+
<h1>Authentication Successful!</h1>
|
|
179
|
+
<p>You can close this window and return to your terminal.</p>
|
|
180
|
+
<div class="close">You may close this tab now.</div>
|
|
181
|
+
</div>
|
|
182
|
+
</body>
|
|
183
|
+
</html>
|
|
184
|
+
`);
|
|
185
|
+
|
|
186
|
+
global._authToken = token;
|
|
187
|
+
} else {
|
|
188
|
+
console.error('ā No token received, error:', error);
|
|
189
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
190
|
+
res.end(`
|
|
191
|
+
<!DOCTYPE html>
|
|
192
|
+
<html>
|
|
193
|
+
<head>
|
|
194
|
+
<title>Authentication Failed</title>
|
|
195
|
+
<style>
|
|
196
|
+
body { font-family: sans-serif; background: #F4F4F0; display: flex;
|
|
197
|
+
align-items: center; justify-content: center; min-height: 100vh; margin: 0; }
|
|
198
|
+
.card { background: white; padding: 48px; text-align: center; border: 1px solid #E0E0DB; }
|
|
199
|
+
h1 { color: #F24E1E; }
|
|
200
|
+
</style>
|
|
201
|
+
</head>
|
|
202
|
+
<body>
|
|
203
|
+
<div class="card">
|
|
204
|
+
<h1>Authentication Failed</h1>
|
|
205
|
+
<p>${error || 'Unknown error'}</p>
|
|
206
|
+
<p>Please close this window and try again in your terminal.</p>
|
|
207
|
+
</div>
|
|
208
|
+
</body>
|
|
209
|
+
</html>
|
|
210
|
+
`);
|
|
211
|
+
global._authToken = null;
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
res.writeHead(404);
|
|
215
|
+
res.end('Not found');
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
server.listen(LOCAL_PORT, () => {
|
|
220
|
+
console.log(`Local auth server listening on port ${LOCAL_PORT}`);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
return server;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function waitForAuth() {
|
|
227
|
+
return new Promise((resolve) => {
|
|
228
|
+
const checkInterval = setInterval(() => {
|
|
229
|
+
if (global._authToken !== undefined) {
|
|
230
|
+
clearInterval(checkInterval);
|
|
231
|
+
const token = global._authToken;
|
|
232
|
+
delete global._authToken;
|
|
233
|
+
resolve(token);
|
|
234
|
+
}
|
|
235
|
+
}, 500);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function logout() {
|
|
240
|
+
config.delete('authToken');
|
|
241
|
+
config.delete('userId');
|
|
242
|
+
config.delete('userEmail');
|
|
243
|
+
console.log(chalk.green('ā Logged out successfully'));
|
|
244
|
+
process.exit(0);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function isAuthenticated() {
|
|
248
|
+
return config.get('authToken') !== null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function getAuthToken() {
|
|
252
|
+
const token = config.get('authToken');
|
|
253
|
+
if (!token) {
|
|
254
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
return token;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
module.exports = { login, logout, isAuthenticated, getAuthToken };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const open = require('open');
|
|
3
|
+
const { isAuthenticated } = require('../auth');
|
|
4
|
+
const { getUserCredits } = require('../api');
|
|
5
|
+
const config = require('../config');
|
|
6
|
+
|
|
7
|
+
async function credits() {
|
|
8
|
+
if (!isAuthenticated()) {
|
|
9
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
console.log(chalk.hex('#F24E1E')('\nš° Research Compute Credits\n'));
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const data = await getUserCredits();
|
|
17
|
+
console.log(chalk.white(`Current Balance: ${chalk.hex('#F24E1E')(data.balance.toLocaleString())} RCC`));
|
|
18
|
+
console.log(chalk.gray(`Used: ${data.used.toLocaleString()} RCC`));
|
|
19
|
+
console.log(chalk.gray(`Total: ${data.total.toLocaleString()} RCC\n`));
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error(chalk.red('Failed to fetch credits'));
|
|
22
|
+
console.error(chalk.gray('Error details:', error.message));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function usage() {
|
|
27
|
+
if (!isAuthenticated()) {
|
|
28
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log(chalk.hex('#F24E1E')('\nš Usage Statistics\n'));
|
|
33
|
+
console.log(chalk.gray('Total missions: 0'));
|
|
34
|
+
console.log(chalk.gray('Total RCC spent: 0'));
|
|
35
|
+
console.log(chalk.gray('Active missions: 0\n'));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function buy() {
|
|
39
|
+
console.log(chalk.hex('#F24E1E')('\nš³ Purchase Research Credits\n'));
|
|
40
|
+
console.log(chalk.gray('Opening browser to dashboard...\n'));
|
|
41
|
+
|
|
42
|
+
await open(config.get('dashboardUrl'));
|
|
43
|
+
|
|
44
|
+
console.log(chalk.gray('ā Browser opened. Complete purchase in the dashboard.\n'));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = { credits, usage, buy };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const { isAuthenticated } = require('../auth');
|
|
4
|
+
|
|
5
|
+
async function dataset(file) {
|
|
6
|
+
if (!isAuthenticated()) {
|
|
7
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const spinner = ora(`Analyzing dataset: ${file}`).start();
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
spinner.succeed(chalk.green('Dataset analysis complete!'));
|
|
15
|
+
console.log(chalk.gray('\nā Analysis generated successfully.\n'));
|
|
16
|
+
|
|
17
|
+
} catch (error) {
|
|
18
|
+
spinner.fail(chalk.red('Failed to analyze dataset'));
|
|
19
|
+
console.error(chalk.red(error.message));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function code(directory) {
|
|
24
|
+
if (!isAuthenticated()) {
|
|
25
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const spinner = ora(`Reviewing code in: ${directory}`).start();
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
spinner.succeed(chalk.green('Code review complete!'));
|
|
33
|
+
console.log(chalk.gray('\nā Review generated successfully.\n'));
|
|
34
|
+
|
|
35
|
+
} catch (error) {
|
|
36
|
+
spinner.fail(chalk.red('Failed to review code'));
|
|
37
|
+
console.error(chalk.red(error.message));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function medical(file) {
|
|
42
|
+
if (!isAuthenticated()) {
|
|
43
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const spinner = ora(`Analyzing medical imaging: ${file}`).start();
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
spinner.succeed(chalk.green('Medical analysis complete!'));
|
|
51
|
+
console.log(chalk.gray('\nā Analysis generated successfully.\n'));
|
|
52
|
+
|
|
53
|
+
} catch (error) {
|
|
54
|
+
spinner.fail(chalk.red('Failed to analyze medical imaging'));
|
|
55
|
+
console.error(chalk.red(error.message));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = { dataset, code, medical };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const ora = require('ora');
|
|
4
|
+
const { createMission } = require('../api');
|
|
5
|
+
const { isAuthenticated } = require('../auth');
|
|
6
|
+
|
|
7
|
+
async function missionCreate() {
|
|
8
|
+
if (!isAuthenticated()) {
|
|
9
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
console.log(chalk.hex('#F24E1E')('\nšÆ Create New Research Mission\n'));
|
|
14
|
+
|
|
15
|
+
const answers = await inquirer.prompt([
|
|
16
|
+
{
|
|
17
|
+
type: 'input',
|
|
18
|
+
name: 'topic',
|
|
19
|
+
message: 'Research topic:',
|
|
20
|
+
validate: (input) => input.length > 0 || 'Topic is required'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
type: 'list',
|
|
24
|
+
name: 'depth',
|
|
25
|
+
message: 'Research depth:',
|
|
26
|
+
choices: [
|
|
27
|
+
{ name: 'Quick (10 RCC)', value: 'QUICK_RESEARCH' },
|
|
28
|
+
{ name: 'Deep (50 RCC)', value: 'DEEP_RESEARCH' },
|
|
29
|
+
{ name: 'Literature Review (100 RCC)', value: 'LITERATURE_REVIEW' },
|
|
30
|
+
{ name: 'Academic (150 RCC)', value: 'MULTI_AGENT' }
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: 'confirm',
|
|
35
|
+
name: 'start',
|
|
36
|
+
message: 'Start mission?',
|
|
37
|
+
default: true
|
|
38
|
+
}
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
if (!answers.start) {
|
|
42
|
+
console.log(chalk.yellow('Mission cancelled.'));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const spinner = ora('Creating mission...').start();
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const result = await createMission(answers.topic, answers.depth, answers.depth);
|
|
50
|
+
|
|
51
|
+
spinner.succeed(chalk.green('Mission created successfully!'));
|
|
52
|
+
console.log(chalk.gray(`\nMission ID: ${result.uid}`));
|
|
53
|
+
console.log(chalk.gray(`RCC Cost: ${result.rccCost}`));
|
|
54
|
+
console.log(chalk.gray(`Remaining Balance: ${result.rccBalance}`));
|
|
55
|
+
console.log(chalk.hex('#F24E1E')('\nā Mission started. We\'ll notify you when complete.'));
|
|
56
|
+
console.log(chalk.gray('Check status: obx mission status\n'));
|
|
57
|
+
|
|
58
|
+
} catch (error) {
|
|
59
|
+
spinner.fail(chalk.red('Failed to create mission'));
|
|
60
|
+
console.error(chalk.red(error.response?.data?.error || error.message));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function missionStatus() {
|
|
65
|
+
if (!isAuthenticated()) {
|
|
66
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log(chalk.hex('#F24E1E')('\nš Active Missions\n'));
|
|
71
|
+
console.log(chalk.gray('Active missions: 0'));
|
|
72
|
+
console.log(chalk.gray('No active missions at the moment.\n'));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function missionResults() {
|
|
76
|
+
if (!isAuthenticated()) {
|
|
77
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log(chalk.hex('#F24E1E')('\nš Mission Results\n'));
|
|
82
|
+
console.log(chalk.gray('Completed missions: 0'));
|
|
83
|
+
console.log(chalk.gray('No completed missions yet.\n'));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function missionList() {
|
|
87
|
+
if (!isAuthenticated()) {
|
|
88
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log(chalk.hex('#F24E1E')('\nš All Missions\n'));
|
|
93
|
+
console.log(chalk.gray('Total missions: 0'));
|
|
94
|
+
console.log(chalk.gray('Start your first mission: obx mission create\n'));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = { missionCreate, missionStatus, missionResults, missionList };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const { createMission } = require('../api');
|
|
4
|
+
const { isAuthenticated } = require('../auth');
|
|
5
|
+
|
|
6
|
+
async function literatureReview(topic) {
|
|
7
|
+
if (!isAuthenticated()) {
|
|
8
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const spinner = ora(`Generating literature review for: ${topic}`).start();
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const result = await createMission(topic, 'Academic', 'LITERATURE_REVIEW');
|
|
16
|
+
|
|
17
|
+
spinner.succeed(chalk.green('Literature review complete!'));
|
|
18
|
+
console.log(chalk.gray(`\nRCC Cost: ${result.rccCost}`));
|
|
19
|
+
console.log(chalk.gray(`Remaining Balance: ${result.rccBalance}`));
|
|
20
|
+
console.log(chalk.hex('#F24E1E')('\nā Report generated successfully.\n'));
|
|
21
|
+
|
|
22
|
+
} catch (error) {
|
|
23
|
+
spinner.fail(chalk.red('Failed to generate literature review'));
|
|
24
|
+
console.error(chalk.red(error.response?.data?.error || error.message));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function paper(file) {
|
|
29
|
+
if (!isAuthenticated()) {
|
|
30
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const spinner = ora(`Analyzing paper: ${file}`).start();
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
// Would need file upload implementation
|
|
38
|
+
spinner.succeed(chalk.green('Paper analysis complete!'));
|
|
39
|
+
console.log(chalk.gray('\nā Analysis generated successfully.\n'));
|
|
40
|
+
|
|
41
|
+
} catch (error) {
|
|
42
|
+
spinner.fail(chalk.red('Failed to analyze paper'));
|
|
43
|
+
console.error(chalk.red(error.message));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function compare(files) {
|
|
48
|
+
if (!isAuthenticated()) {
|
|
49
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log(chalk.hex('#F24E1E')(`\nš Comparing ${files.length} papers\n`));
|
|
54
|
+
console.log(chalk.gray('Comparison complete!\n'));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function gaps(topic) {
|
|
58
|
+
if (!isAuthenticated()) {
|
|
59
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const spinner = ora(`Discovering research gaps for: ${topic}`).start();
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const result = await createMission(topic, 'Academic', 'RESEARCH_GAP');
|
|
67
|
+
|
|
68
|
+
spinner.succeed(chalk.green('Research gaps discovered!'));
|
|
69
|
+
console.log(chalk.gray(`\nRCC Cost: ${result.rccCost}`));
|
|
70
|
+
console.log(chalk.gray(`Remaining Balance: ${result.rccBalance}`));
|
|
71
|
+
console.log(chalk.hex('#F24E1E')('\nā Gap analysis complete.\n'));
|
|
72
|
+
|
|
73
|
+
} catch (error) {
|
|
74
|
+
spinner.fail(chalk.red('Failed to discover research gaps'));
|
|
75
|
+
console.error(chalk.red(error.response?.data?.error || error.message));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function hypothesis(topic) {
|
|
80
|
+
if (!isAuthenticated()) {
|
|
81
|
+
console.error(chalk.red('Not authenticated. Please run: obx login'));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const spinner = ora(`Generating hypotheses for: ${topic}`).start();
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const result = await createMission(topic, 'Academic', 'HYPOTHESIS');
|
|
89
|
+
|
|
90
|
+
spinner.succeed(chalk.green('Hypotheses generated!'));
|
|
91
|
+
console.log(chalk.gray(`\nRCC Cost: ${result.rccCost}`));
|
|
92
|
+
console.log(chalk.gray(`Remaining Balance: ${result.rccBalance}`));
|
|
93
|
+
console.log(chalk.hex('#F24E1E')('\nā Hypothesis generation complete.\n'));
|
|
94
|
+
|
|
95
|
+
} catch (error) {
|
|
96
|
+
spinner.fail(chalk.red('Failed to generate hypotheses'));
|
|
97
|
+
console.error(chalk.red(error.response?.data?.error || error.message));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = { literatureReview, paper, compare, gaps, hypothesis };
|
package/src/config.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const Conf = require('conf');
|
|
2
|
+
|
|
3
|
+
const config = new Conf({
|
|
4
|
+
projectName: 'omnibiofex',
|
|
5
|
+
defaults: {
|
|
6
|
+
apiUrl: 'https://obxvisionassistant-yyedhmslhq-uc.a.run.app',
|
|
7
|
+
dashboardUrl: 'https://x.omnibiofex.cloud/dash',
|
|
8
|
+
authToken: null,
|
|
9
|
+
userId: null,
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
module.exports = config;
|