superbrain-server 1.0.48 → 1.0.50

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/superbrain.js CHANGED
@@ -1,204 +1,204 @@
1
- #!/usr/bin/env node
2
- const fs = require('fs');
3
- const path = require('path');
4
- const os = require('os');
5
- const { spawnSync, spawn } = require('child_process');
6
-
7
- const pkgMeta = require('../package.json');
8
- const TARGET_DIR = path.join(os.homedir(), '.superbrain-server');
9
- const PAYLOAD_DIR = path.join(__dirname, '../payload');
10
-
11
- // Files that should NEVER be overwritten during an unpack/upgrade if they already exist in the target
12
- const PROTECTED_FILES = [
13
- 'superbrain.db',
14
- 'superbrain.db-shm',
15
- 'superbrain.db-wal',
16
- 'token.txt',
17
- '.env',
18
- '.api_keys',
19
- 'localtunnel.log',
20
- 'localtunnel_enabled.txt',
21
- '.setup_done',
22
- 'config/instagram_session.json',
23
- 'config/.api_keys',
24
- 'config/localtunnel_enabled.txt',
25
- 'config/localtunnel.log'
26
- ];
27
-
28
- function log(msg) {
29
- console.log(`\x1b[36m✨ [SuperBrain CLI]\x1b[0m ${msg}`);
30
- }
31
-
32
- function warn(msg) {
33
- console.log(`\x1b[33m⚠️ [SuperBrain CLI]\x1b[0m ${msg}`);
34
- }
35
-
36
- function errorOut(msg) {
37
- console.log(`\x1b[31m❌ [SuperBrain CLI]\x1b[0m ${msg}`);
38
- process.exit(1);
39
- }
40
-
41
- function parsePythonVersion(rawText) {
42
- const match = (rawText || '').match(/Python\s+(\d+)\.(\d+)\.(\d+)/i);
43
- if (!match) return null;
44
- return {
45
- major: Number(match[1]),
46
- minor: Number(match[2]),
47
- patch: Number(match[3]),
48
- };
49
- }
50
-
51
- function isSupportedPython(version) {
52
- if (!version) return false;
53
- if (version.major > 3) return true;
54
- return version.major === 3 && version.minor >= 10;
55
- }
56
-
57
- // Check if Python binaries are accessible
58
- function getPythonCommand() {
59
- const candidates = os.platform() === 'win32'
60
- ? [
61
- { cmd: 'py', args: ['-3', '--version'], execPrefix: ['-3'] },
62
- { cmd: 'python', args: ['--version'], execPrefix: [] },
63
- { cmd: 'python3', args: ['--version'], execPrefix: [] },
64
- ]
65
- : [
66
- { cmd: 'python3', args: ['--version'], execPrefix: [] },
67
- { cmd: 'python', args: ['--version'], execPrefix: [] },
68
- ];
69
-
70
- for (const candidate of candidates) {
71
- try {
72
- const res = spawnSync(candidate.cmd, candidate.args, { encoding: 'utf-8', timeout: 5000 });
73
- const combinedOutput = `${res.stdout || ''}\n${res.stderr || ''}`.trim();
74
- const version = parsePythonVersion(combinedOutput);
75
-
76
- if (res.status === 0 && isSupportedPython(version)) {
77
- return {
78
- command: candidate.cmd,
79
- execPrefix: candidate.execPrefix,
80
- version,
81
- };
82
- }
83
- } catch (e) {
84
- // Command missing
85
- }
86
- }
87
- return null;
88
- }
89
-
90
- function safeUnpack() {
91
- if (!fs.existsSync(TARGET_DIR)) {
92
- fs.mkdirSync(TARGET_DIR, { recursive: true });
93
- }
94
-
95
- log(`Unpacking server core to ${TARGET_DIR} ...`);
96
-
97
- // Recursively copy files from payload
98
- function copyRecursive(src, dest) {
99
- const stat = fs.statSync(src);
100
- if (stat.isDirectory()) {
101
- if (!fs.existsSync(dest)) fs.mkdirSync(dest);
102
- for (const child of fs.readdirSync(src)) {
103
- copyRecursive(path.join(src, child), path.join(dest, child));
104
- }
105
- } else {
106
- // It's a file
107
- const relativePath = path.relative(TARGET_DIR, dest).replace(/\\/g, '/');
108
- const isProtected = PROTECTED_FILES.includes(relativePath);
109
-
110
- if (isProtected && fs.existsSync(dest)) {
111
- // Skip overwriting user's database or tokens
112
- return;
113
- }
114
- fs.copyFileSync(src, dest);
115
- }
116
- }
117
-
118
- if (!fs.existsSync(PAYLOAD_DIR)) {
119
- errorOut("Payload directory missing inside npm package!");
120
- }
121
-
122
- copyRecursive(PAYLOAD_DIR, TARGET_DIR);
123
-
124
- // Write out version explicitly
125
- fs.writeFileSync(path.join(TARGET_DIR, 'VERSION'), pkgMeta.version, 'utf-8');
126
- log(`Extraction complete (v${pkgMeta.version}). Data persisted cleanly.`);
127
- }
128
-
129
- function checkUpgrades() {
130
- const versionFile = path.join(TARGET_DIR, 'VERSION');
131
- let currentVersion = '0.0.0';
132
- if (fs.existsSync(versionFile)) {
133
- currentVersion = fs.readFileSync(versionFile, 'utf-8').trim();
134
- }
135
-
136
- if (currentVersion !== pkgMeta.version) {
137
- log(`Version mismatch detected (Local: ${currentVersion} -> NPM: ${pkgMeta.version}). Auto-upgrading...`);
138
- safeUnpack();
139
- }
140
- }
141
-
142
- // ─────────────────────────────────────────────────────────────────────────────
143
- // EXECUTOR
144
- // ─────────────────────────────────────────────────────────────────────────────
145
-
146
- // 1. Python check
147
- const pythonInfo = getPythonCommand();
148
- if (!pythonInfo) {
149
- errorOut('Could not find Python >= 3.10 on this system. Please install Python 3.10+ to run SuperBrain.');
150
- }
151
-
152
- // 2. Safe unpack/upgrade
153
- checkUpgrades();
154
-
155
- // 3. Command Routing logic
156
- const userArgs = process.argv.slice(2);
157
- let targetScript = 'start.py';
158
- let finalArgs = userArgs;
159
-
160
- if (userArgs.length > 0) {
161
- const cmd = userArgs[0].toLowerCase();
162
- if (cmd === 'reset') {
163
- targetScript = 'reset.py';
164
- finalArgs = userArgs.slice(1); // remove 'reset' from arguments passed to python
165
- } else if (cmd === '-h' || cmd === '--help') {
166
- console.log(`
167
- SuperBrain Server Wrapper (v${pkgMeta.version})
168
-
169
- Usage:
170
- superbrain-server -> Starts the backend engine
171
- superbrain-server reset -> Open Reset Menu
172
- superbrain-server reset --all -> Force complete wipe
173
- superbrain-server status -> Show QR Code and Server Info
174
- superbrain-server ngrok -> Configure Ngrok tunnel
175
- `);
176
- process.exit(0);
177
- } else if (cmd === 'status' || cmd === 'update') {
178
- targetScript = 'start.py';
179
- finalArgs = ['--status'];
180
- } else if (cmd === 'ngrok') {
181
- targetScript = 'start.py';
182
- finalArgs = ['--ngrok'];
183
- }
184
- }
185
-
186
- // 4. Execution
187
- log(`Spinning up Python Engine via ${targetScript} (Python ${pythonInfo.version.major}.${pythonInfo.version.minor}.${pythonInfo.version.patch})...`);
188
- const child = spawn(pythonInfo.command, [...pythonInfo.execPrefix, targetScript, ...finalArgs], {
189
- cwd: TARGET_DIR,
190
- stdio: 'inherit'
191
- });
192
-
193
- // 5. Zombie Protection
194
- function handleShutdown(signal) {
195
- warn(`Received ${signal}. Shutting down Python engine...`);
196
- child.kill('SIGINT');
197
- }
198
-
199
- process.on('SIGINT', () => handleShutdown('SIGINT'));
200
- process.on('SIGTERM', () => handleShutdown('SIGTERM'));
201
-
202
- child.on('close', (code) => {
203
- process.exit(code || 0);
204
- });
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+ const { spawnSync, spawn } = require('child_process');
6
+
7
+ const pkgMeta = require('../package.json');
8
+ const TARGET_DIR = path.join(os.homedir(), '.superbrain-server');
9
+ const PAYLOAD_DIR = path.join(__dirname, '../payload');
10
+
11
+ // Files that should NEVER be overwritten during an unpack/upgrade if they already exist in the target
12
+ const PROTECTED_FILES = [
13
+ 'superbrain.db',
14
+ 'superbrain.db-shm',
15
+ 'superbrain.db-wal',
16
+ 'token.txt',
17
+ '.env',
18
+ '.api_keys',
19
+ 'localtunnel.log',
20
+ 'localtunnel_enabled.txt',
21
+ '.setup_done',
22
+ 'config/instagram_session.json',
23
+ 'config/.api_keys',
24
+ 'config/localtunnel_enabled.txt',
25
+ 'config/localtunnel.log'
26
+ ];
27
+
28
+ function log(msg) {
29
+ console.log(`\x1b[36m✨ [SuperBrain CLI]\x1b[0m ${msg}`);
30
+ }
31
+
32
+ function warn(msg) {
33
+ console.log(`\x1b[33m⚠️ [SuperBrain CLI]\x1b[0m ${msg}`);
34
+ }
35
+
36
+ function errorOut(msg) {
37
+ console.log(`\x1b[31m❌ [SuperBrain CLI]\x1b[0m ${msg}`);
38
+ process.exit(1);
39
+ }
40
+
41
+ function parsePythonVersion(rawText) {
42
+ const match = (rawText || '').match(/Python\s+(\d+)\.(\d+)\.(\d+)/i);
43
+ if (!match) return null;
44
+ return {
45
+ major: Number(match[1]),
46
+ minor: Number(match[2]),
47
+ patch: Number(match[3]),
48
+ };
49
+ }
50
+
51
+ function isSupportedPython(version) {
52
+ if (!version) return false;
53
+ if (version.major > 3) return true;
54
+ return version.major === 3 && version.minor >= 10;
55
+ }
56
+
57
+ // Check if Python binaries are accessible
58
+ function getPythonCommand() {
59
+ const candidates = os.platform() === 'win32'
60
+ ? [
61
+ { cmd: 'py', args: ['-3', '--version'], execPrefix: ['-3'] },
62
+ { cmd: 'python', args: ['--version'], execPrefix: [] },
63
+ { cmd: 'python3', args: ['--version'], execPrefix: [] },
64
+ ]
65
+ : [
66
+ { cmd: 'python3', args: ['--version'], execPrefix: [] },
67
+ { cmd: 'python', args: ['--version'], execPrefix: [] },
68
+ ];
69
+
70
+ for (const candidate of candidates) {
71
+ try {
72
+ const res = spawnSync(candidate.cmd, candidate.args, { encoding: 'utf-8', timeout: 5000 });
73
+ const combinedOutput = `${res.stdout || ''}\n${res.stderr || ''}`.trim();
74
+ const version = parsePythonVersion(combinedOutput);
75
+
76
+ if (res.status === 0 && isSupportedPython(version)) {
77
+ return {
78
+ command: candidate.cmd,
79
+ execPrefix: candidate.execPrefix,
80
+ version,
81
+ };
82
+ }
83
+ } catch (e) {
84
+ // Command missing
85
+ }
86
+ }
87
+ return null;
88
+ }
89
+
90
+ function safeUnpack() {
91
+ if (!fs.existsSync(TARGET_DIR)) {
92
+ fs.mkdirSync(TARGET_DIR, { recursive: true });
93
+ }
94
+
95
+ log(`Unpacking server core to ${TARGET_DIR} ...`);
96
+
97
+ // Recursively copy files from payload
98
+ function copyRecursive(src, dest) {
99
+ const stat = fs.statSync(src);
100
+ if (stat.isDirectory()) {
101
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest);
102
+ for (const child of fs.readdirSync(src)) {
103
+ copyRecursive(path.join(src, child), path.join(dest, child));
104
+ }
105
+ } else {
106
+ // It's a file
107
+ const relativePath = path.relative(TARGET_DIR, dest).replace(/\\/g, '/');
108
+ const isProtected = PROTECTED_FILES.includes(relativePath);
109
+
110
+ if (isProtected && fs.existsSync(dest)) {
111
+ // Skip overwriting user's database or tokens
112
+ return;
113
+ }
114
+ fs.copyFileSync(src, dest);
115
+ }
116
+ }
117
+
118
+ if (!fs.existsSync(PAYLOAD_DIR)) {
119
+ errorOut("Payload directory missing inside npm package!");
120
+ }
121
+
122
+ copyRecursive(PAYLOAD_DIR, TARGET_DIR);
123
+
124
+ // Write out version explicitly
125
+ fs.writeFileSync(path.join(TARGET_DIR, 'VERSION'), pkgMeta.version, 'utf-8');
126
+ log(`Extraction complete (v${pkgMeta.version}). Data persisted cleanly.`);
127
+ }
128
+
129
+ function checkUpgrades() {
130
+ const versionFile = path.join(TARGET_DIR, 'VERSION');
131
+ let currentVersion = '0.0.0';
132
+ if (fs.existsSync(versionFile)) {
133
+ currentVersion = fs.readFileSync(versionFile, 'utf-8').trim();
134
+ }
135
+
136
+ if (currentVersion !== pkgMeta.version) {
137
+ log(`Version mismatch detected (Local: ${currentVersion} -> NPM: ${pkgMeta.version}). Auto-upgrading...`);
138
+ safeUnpack();
139
+ }
140
+ }
141
+
142
+ // ─────────────────────────────────────────────────────────────────────────────
143
+ // EXECUTOR
144
+ // ─────────────────────────────────────────────────────────────────────────────
145
+
146
+ // 1. Python check
147
+ const pythonInfo = getPythonCommand();
148
+ if (!pythonInfo) {
149
+ errorOut('Could not find Python >= 3.10 on this system. Please install Python 3.10+ to run SuperBrain.');
150
+ }
151
+
152
+ // 2. Safe unpack/upgrade
153
+ checkUpgrades();
154
+
155
+ // 3. Command Routing logic
156
+ const userArgs = process.argv.slice(2);
157
+ let targetScript = 'start.py';
158
+ let finalArgs = userArgs;
159
+
160
+ if (userArgs.length > 0) {
161
+ const cmd = userArgs[0].toLowerCase();
162
+ if (cmd === 'reset') {
163
+ targetScript = 'reset.py';
164
+ finalArgs = userArgs.slice(1); // remove 'reset' from arguments passed to python
165
+ } else if (cmd === '-h' || cmd === '--help') {
166
+ console.log(`
167
+ SuperBrain Server Wrapper (v${pkgMeta.version})
168
+
169
+ Usage:
170
+ superbrain-server -> Starts the backend engine
171
+ superbrain-server reset -> Open Reset Menu
172
+ superbrain-server reset --all -> Force complete wipe
173
+ superbrain-server status -> Show QR Code and Server Info
174
+ superbrain-server ngrok -> Configure Ngrok tunnel
175
+ `);
176
+ process.exit(0);
177
+ } else if (cmd === 'status' || cmd === 'update') {
178
+ targetScript = 'start.py';
179
+ finalArgs = ['--status'];
180
+ } else if (cmd === 'ngrok') {
181
+ targetScript = 'start.py';
182
+ finalArgs = ['--ngrok'];
183
+ }
184
+ }
185
+
186
+ // 4. Execution
187
+ log(`Spinning up Python Engine via ${targetScript} (Python ${pythonInfo.version.major}.${pythonInfo.version.minor}.${pythonInfo.version.patch})...`);
188
+ const child = spawn(pythonInfo.command, [...pythonInfo.execPrefix, targetScript, ...finalArgs], {
189
+ cwd: TARGET_DIR,
190
+ stdio: 'inherit'
191
+ });
192
+
193
+ // 5. Zombie Protection
194
+ function handleShutdown(signal) {
195
+ warn(`Received ${signal}. Shutting down Python engine...`);
196
+ child.kill('SIGINT');
197
+ }
198
+
199
+ process.on('SIGINT', () => handleShutdown('SIGINT'));
200
+ process.on('SIGTERM', () => handleShutdown('SIGTERM'));
201
+
202
+ child.on('close', (code) => {
203
+ process.exit(code || 0);
204
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superbrain-server",
3
- "version": "1.0.48",
3
+ "version": "1.0.50",
4
4
  "description": "1-Line Auto-Installer and Server Execution wrapper for SuperBrain",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -1,58 +1,58 @@
1
- # ────────────────────────────────────────────────────────────────────────────────
2
- # SuperBrain Environment Configuration Template
3
- # ────────────────────────────────────────────────────────────────────────────────
4
- # Copy this file to .env and fill in your actual values
5
- # NEVER commit .env file to version control
6
- # ────────────────────────────────────────────────────────────────────────────────
7
-
8
- # ──── Application Settings ────
9
- ENVIRONMENT=production
10
- DEBUG=false
11
- LOG_LEVEL=INFO
12
-
13
- # ──── Server Configuration ────
14
- HOST=0.0.0.0
15
- PORT=5000
16
- WORKERS=4
17
- API_PORT=5000
18
-
19
- # ──── Database Configuration ────
20
- DATABASE_PATH=superbrain.db
21
- DATABASE_TIMEOUT=30
22
-
23
- # ──── AI Provider API Keys ────
24
- # Get these from the respective provider accounts
25
- GROQ_API_KEY=
26
- GEMINI_API_KEY=
27
- OPENROUTER_API_KEY=
28
-
29
- # ──── Whisper Configuration ────
30
- # Options: tiny, base, small, medium, large
31
- WHISPER_MODEL=base
32
- WHISPER_USE_CLOUD=true
33
-
34
- # ──── Instagram Credentials ────
35
- # Use a bot account or app-specific credentials, NOT your personal account
36
- INSTAGRAM_USERNAME=
37
- INSTAGRAM_PASSWORD=
38
-
39
- # ──── File Upload Configuration ────
40
- MAX_UPLOAD_SIZE=52428800
41
- UPLOAD_DIR=static/uploads
42
- TEMP_DIR=temp
43
-
44
- # ──── Request Timeout Settings ────
45
- REQUEST_TIMEOUT=60
46
- ANALYSIS_TIMEOUT=120
47
- MAX_RETRIES=3
48
- RETRY_DELAY=5
49
-
50
- # ──── Feature Flags ────
51
- ENABLE_METRICS=true
52
- ENABLE_HEALTH_CHECK=true
53
- ENABLE_API_DOCS=false
54
-
55
- # ────────────────────────────────────────────────────────────────────────────────
56
- # NOTE: Update only the values you need
57
- # Leave blank if optional or use defaults
58
- # ────────────────────────────────────────────────────────────────────────────────
1
+ # ────────────────────────────────────────────────────────────────────────────────
2
+ # SuperBrain Environment Configuration Template
3
+ # ────────────────────────────────────────────────────────────────────────────────
4
+ # Copy this file to .env and fill in your actual values
5
+ # NEVER commit .env file to version control
6
+ # ────────────────────────────────────────────────────────────────────────────────
7
+
8
+ # ──── Application Settings ────
9
+ ENVIRONMENT=production
10
+ DEBUG=false
11
+ LOG_LEVEL=INFO
12
+
13
+ # ──── Server Configuration ────
14
+ HOST=0.0.0.0
15
+ PORT=5000
16
+ WORKERS=4
17
+ API_PORT=5000
18
+
19
+ # ──── Database Configuration ────
20
+ DATABASE_PATH=superbrain.db
21
+ DATABASE_TIMEOUT=30
22
+
23
+ # ──── AI Provider API Keys ────
24
+ # Get these from the respective provider accounts
25
+ GROQ_API_KEY=
26
+ GEMINI_API_KEY=
27
+ OPENROUTER_API_KEY=
28
+
29
+ # ──── Whisper Configuration ────
30
+ # Options: tiny, base, small, medium, large
31
+ WHISPER_MODEL=base
32
+ WHISPER_USE_CLOUD=true
33
+
34
+ # ──── Instagram Credentials ────
35
+ # Use a bot account or app-specific credentials, NOT your personal account
36
+ INSTAGRAM_USERNAME=
37
+ INSTAGRAM_PASSWORD=
38
+
39
+ # ──── File Upload Configuration ────
40
+ MAX_UPLOAD_SIZE=52428800
41
+ UPLOAD_DIR=static/uploads
42
+ TEMP_DIR=temp
43
+
44
+ # ──── Request Timeout Settings ────
45
+ REQUEST_TIMEOUT=60
46
+ ANALYSIS_TIMEOUT=120
47
+ MAX_RETRIES=3
48
+ RETRY_DELAY=5
49
+
50
+ # ──── Feature Flags ────
51
+ ENABLE_METRICS=true
52
+ ENABLE_HEALTH_CHECK=true
53
+ ENABLE_API_DOCS=false
54
+
55
+ # ────────────────────────────────────────────────────────────────────────────────
56
+ # NOTE: Update only the values you need
57
+ # Leave blank if optional or use defaults
58
+ # ────────────────────────────────────────────────────────────────────────────────