@aethermind/setup 0.1.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/setup.js +33 -0
- package/package.json +36 -0
- package/src/detect.js +63 -0
- package/src/env.js +88 -0
- package/src/index.js +118 -0
- package/src/install.js +44 -0
- package/src/ui.js +53 -0
- package/src/validate.js +51 -0
package/bin/setup.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { main } = require('../src/index.js');
|
|
7
|
+
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
|
|
10
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
11
|
+
console.log(`
|
|
12
|
+
Usage: npx @aethermind/setup [options]
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--uninstall Revert all changes made by setup
|
|
16
|
+
--help, -h Show this help message
|
|
17
|
+
--version, -v Show version
|
|
18
|
+
`);
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
23
|
+
const pkg = require('../package.json');
|
|
24
|
+
console.log(pkg.version);
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const uninstall = args.includes('--uninstall');
|
|
29
|
+
|
|
30
|
+
main({ uninstall }).catch((err) => {
|
|
31
|
+
console.error('\n\x1b[31mError:\x1b[0m', err.message || err);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aethermind/setup",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI setup tool for Aethermind AgentOS — configures your project with one command",
|
|
5
|
+
"bin": {
|
|
6
|
+
"aethermind-setup": "./bin/setup.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "node bin/setup.js --help"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"aethermind",
|
|
17
|
+
"setup",
|
|
18
|
+
"cli",
|
|
19
|
+
"ai",
|
|
20
|
+
"monitoring",
|
|
21
|
+
"telemetry"
|
|
22
|
+
],
|
|
23
|
+
"author": "Aethermind Team",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/gonzacba17/Aethermind-AgentOS.git",
|
|
28
|
+
"directory": "packages/setup"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=16.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/detect.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { ok, fail, info } = require('./ui.js');
|
|
6
|
+
|
|
7
|
+
function checkNodeVersion() {
|
|
8
|
+
const version = process.versions.node;
|
|
9
|
+
const major = parseInt(version.split('.')[0], 10);
|
|
10
|
+
if (major < 16) {
|
|
11
|
+
fail(`Node.js v${version} detectado - se requiere >= 16`);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
ok(`Node.js v${version} detectado`);
|
|
15
|
+
return version;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function detectPackageJson(cwd) {
|
|
19
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
20
|
+
if (!fs.existsSync(pkgPath)) {
|
|
21
|
+
fail('No se encontro package.json en el directorio actual');
|
|
22
|
+
console.log(' Ejecuta este comando desde la raiz de tu proyecto.');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
26
|
+
ok(`Proyecto: ${pkg.name || path.basename(cwd)} (package.json encontrado)`);
|
|
27
|
+
return pkg;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const AI_SDKS = [
|
|
31
|
+
{ name: 'openai', label: 'openai' },
|
|
32
|
+
{ name: '@anthropic-ai/sdk', label: '@anthropic-ai/sdk' },
|
|
33
|
+
{ name: '@google/generative-ai', label: '@google/generative-ai' },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
function detectInstalledSDKs(cwd) {
|
|
37
|
+
const found = [];
|
|
38
|
+
for (const sdk of AI_SDKS) {
|
|
39
|
+
try {
|
|
40
|
+
const sdkPkgPath = path.join(cwd, 'node_modules', ...sdk.name.split('/'), 'package.json');
|
|
41
|
+
if (fs.existsSync(sdkPkgPath)) {
|
|
42
|
+
found.push(sdk.label);
|
|
43
|
+
}
|
|
44
|
+
} catch (_) {
|
|
45
|
+
// not installed
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (found.length > 0) {
|
|
49
|
+
ok(`SDKs detectados: ${found.join(', ')}`);
|
|
50
|
+
} else {
|
|
51
|
+
info('No se detectaron SDKs de IA instalados (openai, anthropic, gemini)');
|
|
52
|
+
}
|
|
53
|
+
return found;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function detectPackageManager(cwd) {
|
|
57
|
+
if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';
|
|
58
|
+
if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';
|
|
59
|
+
if (fs.existsSync(path.join(cwd, 'bun.lockb'))) return 'bun';
|
|
60
|
+
return 'npm';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = { checkNodeVersion, detectPackageJson, detectInstalledSDKs, detectPackageManager };
|
package/src/env.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { ok, info } = require('./ui.js');
|
|
6
|
+
|
|
7
|
+
const ENV_KEYS = {
|
|
8
|
+
AETHERMIND_API_KEY: null,
|
|
9
|
+
NODE_OPTIONS: '--require @aethermind/providers/register',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function updateEnvFile(cwd, apiKey) {
|
|
13
|
+
const envPath = path.join(cwd, '.env');
|
|
14
|
+
const backupPath = path.join(cwd, '.env.aethermind.backup');
|
|
15
|
+
let existing = '';
|
|
16
|
+
|
|
17
|
+
// Backup existing .env
|
|
18
|
+
if (fs.existsSync(envPath)) {
|
|
19
|
+
existing = fs.readFileSync(envPath, 'utf-8');
|
|
20
|
+
fs.copyFileSync(envPath, backupPath);
|
|
21
|
+
ok('Backup guardado en .env.aethermind.backup');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const lines = existing ? existing.split('\n') : [];
|
|
25
|
+
const updates = {
|
|
26
|
+
AETHERMIND_API_KEY: apiKey,
|
|
27
|
+
NODE_OPTIONS: buildNodeOptions(lines),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
let content = existing;
|
|
31
|
+
|
|
32
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
33
|
+
const regex = new RegExp(`^${key}=.*$`, 'm');
|
|
34
|
+
const newLine = `${key}=${value}`;
|
|
35
|
+
|
|
36
|
+
if (regex.test(content)) {
|
|
37
|
+
content = content.replace(regex, newLine);
|
|
38
|
+
} else {
|
|
39
|
+
if (content && !content.endsWith('\n')) {
|
|
40
|
+
content += '\n';
|
|
41
|
+
}
|
|
42
|
+
content += newLine + '\n';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fs.writeFileSync(envPath, content, 'utf-8');
|
|
47
|
+
ok('.env actualizado');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function buildNodeOptions(lines) {
|
|
51
|
+
const requireFlag = '--require @aethermind/providers/register';
|
|
52
|
+
const existingLine = lines.find((l) => l.startsWith('NODE_OPTIONS='));
|
|
53
|
+
|
|
54
|
+
if (existingLine) {
|
|
55
|
+
const existingValue = existingLine.replace('NODE_OPTIONS=', '');
|
|
56
|
+
if (existingValue.includes(requireFlag)) {
|
|
57
|
+
return existingValue;
|
|
58
|
+
}
|
|
59
|
+
return existingValue ? `${existingValue} ${requireFlag}` : requireFlag;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return requireFlag;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function restoreEnvFile(cwd) {
|
|
66
|
+
const envPath = path.join(cwd, '.env');
|
|
67
|
+
const backupPath = path.join(cwd, '.env.aethermind.backup');
|
|
68
|
+
|
|
69
|
+
if (fs.existsSync(backupPath)) {
|
|
70
|
+
fs.copyFileSync(backupPath, envPath);
|
|
71
|
+
fs.unlinkSync(backupPath);
|
|
72
|
+
ok('.env restaurado desde backup');
|
|
73
|
+
} else if (fs.existsSync(envPath)) {
|
|
74
|
+
// Remove our additions from .env
|
|
75
|
+
let content = fs.readFileSync(envPath, 'utf-8');
|
|
76
|
+
content = content.replace(/^AETHERMIND_API_KEY=.*\n?/m, '');
|
|
77
|
+
// Remove our require from NODE_OPTIONS
|
|
78
|
+
content = content.replace(/ ?--require @aethermind\/providers\/register/g, '');
|
|
79
|
+
// Remove empty NODE_OPTIONS line
|
|
80
|
+
content = content.replace(/^NODE_OPTIONS=\s*\n?/m, '');
|
|
81
|
+
fs.writeFileSync(envPath, content, 'utf-8');
|
|
82
|
+
ok('Entradas de Aethermind removidas del .env');
|
|
83
|
+
} else {
|
|
84
|
+
info('No se encontro .env para restaurar');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { updateEnvFile, restoreEnvFile };
|
package/src/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const readline = require('readline');
|
|
4
|
+
const { banner, ok, info, separator, summary, c } = require('./ui.js');
|
|
5
|
+
const { checkNodeVersion, detectPackageJson, detectInstalledSDKs, detectPackageManager } = require('./detect.js');
|
|
6
|
+
const { validateApiKey } = require('./validate.js');
|
|
7
|
+
const { installProviders, uninstallProviders } = require('./install.js');
|
|
8
|
+
const { updateEnvFile, restoreEnvFile } = require('./env.js');
|
|
9
|
+
|
|
10
|
+
function prompt(question) {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
const rl = readline.createInterface({
|
|
13
|
+
input: process.stdin,
|
|
14
|
+
output: process.stdout,
|
|
15
|
+
});
|
|
16
|
+
rl.question(question, (answer) => {
|
|
17
|
+
rl.close();
|
|
18
|
+
resolve(answer.trim());
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function confirm(question) {
|
|
24
|
+
return prompt(`${question} (s/n): `).then((a) => a.toLowerCase() === 's' || a.toLowerCase() === 'y');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function runSetup() {
|
|
28
|
+
const cwd = process.cwd();
|
|
29
|
+
|
|
30
|
+
banner();
|
|
31
|
+
|
|
32
|
+
// 1. Check Node version
|
|
33
|
+
checkNodeVersion();
|
|
34
|
+
|
|
35
|
+
// 2. Detect package.json
|
|
36
|
+
const pkg = detectPackageJson(cwd);
|
|
37
|
+
|
|
38
|
+
// 3. Detect installed SDKs
|
|
39
|
+
const sdks = detectInstalledSDKs(cwd);
|
|
40
|
+
|
|
41
|
+
// 4. Detect package manager
|
|
42
|
+
const pm = detectPackageManager(cwd);
|
|
43
|
+
|
|
44
|
+
separator();
|
|
45
|
+
|
|
46
|
+
// 5. Ask for API key
|
|
47
|
+
const apiKey = await prompt(c.cyan(' ? ') + 'Ingresa tu AETHERMIND_API_KEY: ');
|
|
48
|
+
|
|
49
|
+
if (!apiKey) {
|
|
50
|
+
console.log(c.red('\n API key no puede estar vacia.'));
|
|
51
|
+
console.log(' Obtene tu key en: https://aethermind-agent-os-dashboard.vercel.app/settings\n');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 6. Validate API key
|
|
56
|
+
await validateApiKey(apiKey);
|
|
57
|
+
|
|
58
|
+
separator();
|
|
59
|
+
|
|
60
|
+
// 7. Show what will be modified and confirm
|
|
61
|
+
console.log('');
|
|
62
|
+
console.log(c.bold(' Se realizaran los siguientes cambios:'));
|
|
63
|
+
console.log(` - Instalar @aethermind/providers (via ${pm})`);
|
|
64
|
+
console.log(' - Agregar AETHERMIND_API_KEY al .env');
|
|
65
|
+
console.log(' - Agregar --require @aethermind/providers/register a NODE_OPTIONS');
|
|
66
|
+
console.log('');
|
|
67
|
+
|
|
68
|
+
const proceed = await confirm(c.cyan(' ? ') + 'Continuar?');
|
|
69
|
+
if (!proceed) {
|
|
70
|
+
console.log('\n Setup cancelado.\n');
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log('');
|
|
75
|
+
|
|
76
|
+
// 8. Install @aethermind/providers
|
|
77
|
+
installProviders(pm);
|
|
78
|
+
|
|
79
|
+
// 9. Update .env
|
|
80
|
+
updateEnvFile(cwd, apiKey);
|
|
81
|
+
|
|
82
|
+
// 10. Show summary
|
|
83
|
+
summary();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function runUninstall() {
|
|
87
|
+
const cwd = process.cwd();
|
|
88
|
+
|
|
89
|
+
banner();
|
|
90
|
+
console.log(c.yellow(' Desinstalando Aethermind AgentOS...\n'));
|
|
91
|
+
|
|
92
|
+
const pm = detectPackageManager(cwd);
|
|
93
|
+
|
|
94
|
+
const proceed = await confirm(c.cyan(' ? ') + 'Desinstalar @aethermind/providers y restaurar .env?');
|
|
95
|
+
if (!proceed) {
|
|
96
|
+
console.log('\n Cancelado.\n');
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log('');
|
|
101
|
+
|
|
102
|
+
// Uninstall package
|
|
103
|
+
uninstallProviders(pm);
|
|
104
|
+
|
|
105
|
+
// Restore .env
|
|
106
|
+
restoreEnvFile(cwd);
|
|
107
|
+
|
|
108
|
+
console.log(c.green('\n Aethermind AgentOS desinstalado correctamente.\n'));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function main({ uninstall = false } = {}) {
|
|
112
|
+
if (uninstall) {
|
|
113
|
+
return runUninstall();
|
|
114
|
+
}
|
|
115
|
+
return runSetup();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = { main };
|
package/src/install.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
const { ok, fail } = require('./ui.js');
|
|
5
|
+
|
|
6
|
+
function installProviders(packageManager) {
|
|
7
|
+
const cmds = {
|
|
8
|
+
npm: 'npm install @aethermind/providers',
|
|
9
|
+
pnpm: 'pnpm add @aethermind/providers',
|
|
10
|
+
yarn: 'yarn add @aethermind/providers',
|
|
11
|
+
bun: 'bun add @aethermind/providers',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const cmd = cmds[packageManager] || cmds.npm;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
execSync(cmd, { stdio: 'pipe', timeout: 120000 });
|
|
18
|
+
ok('@aethermind/providers instalado');
|
|
19
|
+
} catch (err) {
|
|
20
|
+
fail(`Error instalando @aethermind/providers con ${packageManager}`);
|
|
21
|
+
console.log(` Intenta manualmente: ${cmd}`);
|
|
22
|
+
throw new Error(`Fallo la instalacion: ${err.message}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function uninstallProviders(packageManager) {
|
|
27
|
+
const cmds = {
|
|
28
|
+
npm: 'npm uninstall @aethermind/providers',
|
|
29
|
+
pnpm: 'pnpm remove @aethermind/providers',
|
|
30
|
+
yarn: 'yarn remove @aethermind/providers',
|
|
31
|
+
bun: 'bun remove @aethermind/providers',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const cmd = cmds[packageManager] || cmds.npm;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
execSync(cmd, { stdio: 'pipe', timeout: 120000 });
|
|
38
|
+
ok('@aethermind/providers desinstalado');
|
|
39
|
+
} catch (_) {
|
|
40
|
+
// may not be installed, that's ok
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { installProviders, uninstallProviders };
|
package/src/ui.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const isColorSupported = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
4
|
+
|
|
5
|
+
const c = {
|
|
6
|
+
green: (s) => isColorSupported ? `\x1b[32m${s}\x1b[0m` : s,
|
|
7
|
+
red: (s) => isColorSupported ? `\x1b[31m${s}\x1b[0m` : s,
|
|
8
|
+
yellow: (s) => isColorSupported ? `\x1b[33m${s}\x1b[0m` : s,
|
|
9
|
+
cyan: (s) => isColorSupported ? `\x1b[36m${s}\x1b[0m` : s,
|
|
10
|
+
bold: (s) => isColorSupported ? `\x1b[1m${s}\x1b[0m` : s,
|
|
11
|
+
dim: (s) => isColorSupported ? `\x1b[2m${s}\x1b[0m` : s,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function banner() {
|
|
15
|
+
console.log('');
|
|
16
|
+
console.log(c.cyan('+---------------------------------+'));
|
|
17
|
+
console.log(c.cyan('|') + c.bold(' Aethermind AgentOS Setup ') + c.cyan('|'));
|
|
18
|
+
console.log(c.cyan('+---------------------------------+'));
|
|
19
|
+
console.log('');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function ok(msg) {
|
|
23
|
+
console.log(c.green(' OK ') + msg);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function fail(msg) {
|
|
27
|
+
console.log(c.red(' X ') + msg);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function info(msg) {
|
|
31
|
+
console.log(c.yellow(' ! ') + msg);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function separator() {
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log(c.dim(' ' + '-'.repeat(35)));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function summary() {
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(c.dim(' ' + '='.repeat(35)));
|
|
42
|
+
console.log(c.green(c.bold(' Listo. Tu app esta siendo monitoreada.')));
|
|
43
|
+
console.log('');
|
|
44
|
+
console.log(' Corre tu app normalmente:');
|
|
45
|
+
console.log(c.cyan(' node index.js'));
|
|
46
|
+
console.log('');
|
|
47
|
+
console.log(' Mira tu dashboard:');
|
|
48
|
+
console.log(c.cyan(' https://aethermind-agent-os-dashboard.vercel.app'));
|
|
49
|
+
console.log(c.dim(' ' + '='.repeat(35)));
|
|
50
|
+
console.log('');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = { banner, ok, fail, info, separator, summary, c };
|
package/src/validate.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const http = require('http');
|
|
5
|
+
const { ok, fail } = require('./ui.js');
|
|
6
|
+
|
|
7
|
+
function validateApiKey(apiKey) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
const url = new URL('https://aethermind-agent-os.vercel.app/api/client/me');
|
|
10
|
+
const client = url.protocol === 'https:' ? https : http;
|
|
11
|
+
|
|
12
|
+
const req = client.get(
|
|
13
|
+
url.href,
|
|
14
|
+
{
|
|
15
|
+
headers: {
|
|
16
|
+
Authorization: `Bearer ${apiKey}`,
|
|
17
|
+
'Content-Type': 'application/json',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
(res) => {
|
|
21
|
+
let body = '';
|
|
22
|
+
res.on('data', (chunk) => (body += chunk));
|
|
23
|
+
res.on('end', () => {
|
|
24
|
+
if (res.statusCode === 200) {
|
|
25
|
+
try {
|
|
26
|
+
const data = JSON.parse(body);
|
|
27
|
+
const email = data.email || data.user?.email || 'usuario verificado';
|
|
28
|
+
ok(`API key valida — conectado como ${email}`);
|
|
29
|
+
resolve(data);
|
|
30
|
+
} catch (_) {
|
|
31
|
+
ok('API key valida');
|
|
32
|
+
resolve({});
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
fail(`API key invalida (HTTP ${res.statusCode})`);
|
|
36
|
+
reject(new Error(`API key invalida. Verifica tu AETHERMIND_API_KEY.`));
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
req.on('error', (err) => {
|
|
43
|
+
fail(`No se pudo conectar al servidor: ${err.message}`);
|
|
44
|
+
reject(new Error('No se pudo validar la API key. Verifica tu conexion a internet.'));
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
req.end();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = { validateApiKey };
|