@aethermind/setup 0.1.3 → 0.1.5
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 -33
- package/package.json +36 -36
- package/src/detect.js +103 -64
- package/src/env.js +126 -88
- package/src/index.js +152 -118
- package/src/install.js +63 -44
- package/src/ui.js +64 -53
- package/src/validate.js +59 -59
package/bin/setup.js
CHANGED
|
@@ -1,33 +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
|
-
});
|
|
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
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@aethermind/setup",
|
|
3
|
-
"version": "0.1.
|
|
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
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@aethermind/setup",
|
|
3
|
+
"version": "0.1.5",
|
|
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
CHANGED
|
@@ -1,64 +1,103 @@
|
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
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
|
+
/**
|
|
19
|
+
* Detect the project language/runtime.
|
|
20
|
+
* Returns 'node', 'python', or 'unknown'.
|
|
21
|
+
*/
|
|
22
|
+
function detectLanguage(cwd) {
|
|
23
|
+
if (fs.existsSync(path.join(cwd, 'package.json'))) return 'node';
|
|
24
|
+
if (
|
|
25
|
+
fs.existsSync(path.join(cwd, 'requirements.txt')) ||
|
|
26
|
+
fs.existsSync(path.join(cwd, 'pyproject.toml')) ||
|
|
27
|
+
fs.existsSync(path.join(cwd, 'setup.py')) ||
|
|
28
|
+
fs.existsSync(path.join(cwd, 'Pipfile'))
|
|
29
|
+
) return 'python';
|
|
30
|
+
return 'unknown';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function detectPackageJson(cwd) {
|
|
34
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
35
|
+
if (!fs.existsSync(pkgPath)) return null;
|
|
36
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
37
|
+
ok(`Proyecto: ${pkg.name || path.basename(cwd)}`);
|
|
38
|
+
return pkg;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const AI_SDKS = [
|
|
42
|
+
{ name: 'openai', label: 'openai' },
|
|
43
|
+
{ name: '@anthropic-ai/sdk', label: '@anthropic-ai/sdk' },
|
|
44
|
+
{ name: '@google/generative-ai', label: '@google/generative-ai' },
|
|
45
|
+
{ name: 'ollama', label: 'ollama' },
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
function detectInstalledSDKs(cwd) {
|
|
49
|
+
const found = [];
|
|
50
|
+
for (const sdk of AI_SDKS) {
|
|
51
|
+
try {
|
|
52
|
+
const sdkPkgPath = path.join(cwd, 'node_modules', ...sdk.name.split('/'), 'package.json');
|
|
53
|
+
if (fs.existsSync(sdkPkgPath)) {
|
|
54
|
+
found.push(sdk.label);
|
|
55
|
+
}
|
|
56
|
+
} catch (_) {
|
|
57
|
+
// not installed
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (found.length > 0) {
|
|
61
|
+
ok(`SDKs detectados: ${found.join(', ')}`);
|
|
62
|
+
} else {
|
|
63
|
+
info('No se detectaron SDKs de IA instalados');
|
|
64
|
+
}
|
|
65
|
+
return found;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function detectPackageManager(cwd) {
|
|
69
|
+
if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';
|
|
70
|
+
if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';
|
|
71
|
+
if (fs.existsSync(path.join(cwd, 'bun.lockb'))) return 'bun';
|
|
72
|
+
return 'npm';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Detect if Ollama is installed (binary on PATH or running on default port).
|
|
77
|
+
*/
|
|
78
|
+
function detectOllama() {
|
|
79
|
+
const { execSync } = require('child_process');
|
|
80
|
+
|
|
81
|
+
// Check if ollama binary exists
|
|
82
|
+
try {
|
|
83
|
+
execSync('ollama --version', { stdio: 'pipe', timeout: 5000 });
|
|
84
|
+
ok('Ollama detectado');
|
|
85
|
+
return true;
|
|
86
|
+
} catch (_) {
|
|
87
|
+
// not on PATH
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Check if something is listening on port 11434 (default Ollama port)
|
|
91
|
+
const http = require('http');
|
|
92
|
+
return new Promise((resolve) => {
|
|
93
|
+
const req = http.get('http://localhost:11434', { timeout: 2000 }, (res) => {
|
|
94
|
+
req.destroy();
|
|
95
|
+
ok('Ollama detectado (puerto 11434 activo)');
|
|
96
|
+
resolve(true);
|
|
97
|
+
});
|
|
98
|
+
req.on('error', () => resolve(false));
|
|
99
|
+
req.on('timeout', () => { req.destroy(); resolve(false); });
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = { checkNodeVersion, detectLanguage, detectPackageJson, detectInstalledSDKs, detectPackageManager, detectOllama };
|
package/src/env.js
CHANGED
|
@@ -1,88 +1,126 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { ok, info } = require('./ui.js');
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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 GATEWAY_URL = 'https://aethermind-agentos-production.up.railway.app/gateway/v1';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Update .env file for a Node.js project.
|
|
11
|
+
* Adds AETHERMIND_API_KEY and NODE_OPTIONS=--require @aethermind/agent/register
|
|
12
|
+
*/
|
|
13
|
+
function updateEnvForNode(cwd, apiKey) {
|
|
14
|
+
const envPath = path.join(cwd, '.env');
|
|
15
|
+
backupEnv(cwd, envPath);
|
|
16
|
+
|
|
17
|
+
let content = readEnvOrEmpty(envPath);
|
|
18
|
+
|
|
19
|
+
content = setEnvVar(content, 'AETHERMIND_API_KEY', apiKey);
|
|
20
|
+
content = setEnvVar(content, 'NODE_OPTIONS', buildNodeOptions(content));
|
|
21
|
+
|
|
22
|
+
fs.writeFileSync(envPath, content, 'utf-8');
|
|
23
|
+
ok('.env actualizado (AETHERMIND_API_KEY + NODE_OPTIONS)');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Add Ollama proxy env vars.
|
|
28
|
+
* Sets OLLAMA_HOST to point to the local Aethermind proxy instead of Ollama directly.
|
|
29
|
+
*/
|
|
30
|
+
function addOllamaEnv(cwd) {
|
|
31
|
+
const envPath = path.join(cwd, '.env');
|
|
32
|
+
let content = readEnvOrEmpty(envPath);
|
|
33
|
+
|
|
34
|
+
content = setEnvVar(content, 'OLLAMA_HOST', 'http://localhost:11435');
|
|
35
|
+
|
|
36
|
+
fs.writeFileSync(envPath, content, 'utf-8');
|
|
37
|
+
ok('.env actualizado (OLLAMA_HOST → proxy en puerto 11435)');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Update .env file for a Python or generic project.
|
|
42
|
+
* Sets OPENAI_BASE_URL, OPENAI_API_KEY (= SDK key), and ANTHROPIC_BASE_URL.
|
|
43
|
+
* The gateway authenticates via the SDK key and uses stored provider keys.
|
|
44
|
+
*/
|
|
45
|
+
function updateEnvForGateway(cwd, apiKey) {
|
|
46
|
+
const envPath = path.join(cwd, '.env');
|
|
47
|
+
backupEnv(cwd, envPath);
|
|
48
|
+
|
|
49
|
+
let content = readEnvOrEmpty(envPath);
|
|
50
|
+
|
|
51
|
+
content = setEnvVar(content, 'AETHERMIND_API_KEY', apiKey);
|
|
52
|
+
content = setEnvVar(content, 'OPENAI_BASE_URL', GATEWAY_URL);
|
|
53
|
+
content = setEnvVar(content, 'OPENAI_API_KEY', apiKey);
|
|
54
|
+
content = setEnvVar(content, 'ANTHROPIC_BASE_URL', GATEWAY_URL);
|
|
55
|
+
content = setEnvVar(content, 'ANTHROPIC_API_KEY', apiKey);
|
|
56
|
+
|
|
57
|
+
fs.writeFileSync(envPath, content, 'utf-8');
|
|
58
|
+
ok('.env actualizado (OPENAI_BASE_URL + ANTHROPIC_BASE_URL + API keys)');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ─── Helpers ────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
function readEnvOrEmpty(envPath) {
|
|
64
|
+
if (fs.existsSync(envPath)) {
|
|
65
|
+
return fs.readFileSync(envPath, 'utf-8');
|
|
66
|
+
}
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function backupEnv(cwd, envPath) {
|
|
71
|
+
const backupPath = path.join(cwd, '.env.aethermind.backup');
|
|
72
|
+
if (fs.existsSync(envPath)) {
|
|
73
|
+
fs.copyFileSync(envPath, backupPath);
|
|
74
|
+
ok('Backup guardado en .env.aethermind.backup');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function setEnvVar(content, key, value) {
|
|
79
|
+
const regex = new RegExp(`^${key}=.*$`, 'm');
|
|
80
|
+
const newLine = `${key}=${value}`;
|
|
81
|
+
|
|
82
|
+
if (regex.test(content)) {
|
|
83
|
+
return content.replace(regex, newLine);
|
|
84
|
+
}
|
|
85
|
+
if (content && !content.endsWith('\n')) {
|
|
86
|
+
content += '\n';
|
|
87
|
+
}
|
|
88
|
+
return content + newLine + '\n';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function buildNodeOptions(content) {
|
|
92
|
+
const requireFlag = '--require @aethermind/agent/register';
|
|
93
|
+
const lines = content.split('\n');
|
|
94
|
+
const existingLine = lines.find((l) => l.startsWith('NODE_OPTIONS='));
|
|
95
|
+
|
|
96
|
+
if (existingLine) {
|
|
97
|
+
const existingValue = existingLine.replace('NODE_OPTIONS=', '');
|
|
98
|
+
if (existingValue.includes(requireFlag)) return existingValue;
|
|
99
|
+
return existingValue ? `${existingValue} ${requireFlag}` : requireFlag;
|
|
100
|
+
}
|
|
101
|
+
return requireFlag;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function restoreEnvFile(cwd) {
|
|
105
|
+
const envPath = path.join(cwd, '.env');
|
|
106
|
+
const backupPath = path.join(cwd, '.env.aethermind.backup');
|
|
107
|
+
|
|
108
|
+
if (fs.existsSync(backupPath)) {
|
|
109
|
+
fs.copyFileSync(backupPath, envPath);
|
|
110
|
+
fs.unlinkSync(backupPath);
|
|
111
|
+
ok('.env restaurado desde backup');
|
|
112
|
+
} else if (fs.existsSync(envPath)) {
|
|
113
|
+
let content = fs.readFileSync(envPath, 'utf-8');
|
|
114
|
+
content = content.replace(/^AETHERMIND_API_KEY=.*\n?/m, '');
|
|
115
|
+
content = content.replace(/ ?--require @aethermind\/agent\/register/g, '');
|
|
116
|
+
content = content.replace(/^NODE_OPTIONS=\s*\n?/m, '');
|
|
117
|
+
content = content.replace(/^OPENAI_BASE_URL=.*\n?/m, '');
|
|
118
|
+
content = content.replace(/^ANTHROPIC_BASE_URL=.*\n?/m, '');
|
|
119
|
+
fs.writeFileSync(envPath, content, 'utf-8');
|
|
120
|
+
ok('Entradas de Aethermind removidas del .env');
|
|
121
|
+
} else {
|
|
122
|
+
info('No se encontro .env para restaurar');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = { updateEnvForNode, updateEnvForGateway, addOllamaEnv, restoreEnvFile };
|
package/src/index.js
CHANGED
|
@@ -1,118 +1,152 @@
|
|
|
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 {
|
|
8
|
-
const {
|
|
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} (
|
|
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
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
console.log('
|
|
66
|
-
console.log('');
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
console.log(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const readline = require('readline');
|
|
4
|
+
const { banner, ok, info, separator, summary, c } = require('./ui.js');
|
|
5
|
+
const { checkNodeVersion, detectLanguage, detectPackageJson, detectInstalledSDKs, detectPackageManager, detectOllama } = require('./detect.js');
|
|
6
|
+
const { validateApiKey } = require('./validate.js');
|
|
7
|
+
const { installAgent, uninstallAgent, installOllamaProxy } = require('./install.js');
|
|
8
|
+
const { updateEnvForNode, updateEnvForGateway, addOllamaEnv, 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} (y/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 (needed to run this script)
|
|
33
|
+
checkNodeVersion();
|
|
34
|
+
|
|
35
|
+
// 2. Detect project language
|
|
36
|
+
const language = detectLanguage(cwd);
|
|
37
|
+
ok(`Proyecto detectado: ${language === 'node' ? 'Node.js' : language === 'python' ? 'Python' : 'Otro'}`);
|
|
38
|
+
|
|
39
|
+
// 3. Detect project details
|
|
40
|
+
if (language === 'node') {
|
|
41
|
+
detectPackageJson(cwd);
|
|
42
|
+
detectInstalledSDKs(cwd);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 4. Detect Ollama
|
|
46
|
+
const hasOllama = await detectOllama();
|
|
47
|
+
|
|
48
|
+
separator();
|
|
49
|
+
|
|
50
|
+
// 5. Ask for API key
|
|
51
|
+
const apiKey = await prompt(c.cyan(' ? ') + 'Pega tu SDK API Key (la encontras en el dashboard): ');
|
|
52
|
+
|
|
53
|
+
if (!apiKey) {
|
|
54
|
+
console.log(c.red('\n API key no puede estar vacia.'));
|
|
55
|
+
console.log(' Obtene tu key en: https://aethermind-agent-os-dashboard.vercel.app\n');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 6. Validate API key
|
|
60
|
+
await validateApiKey(apiKey);
|
|
61
|
+
|
|
62
|
+
separator();
|
|
63
|
+
|
|
64
|
+
// 7. Show plan and confirm
|
|
65
|
+
console.log('');
|
|
66
|
+
console.log(c.bold(' Se realizaran los siguientes cambios:'));
|
|
67
|
+
|
|
68
|
+
if (language === 'node') {
|
|
69
|
+
const pm = detectPackageManager(cwd);
|
|
70
|
+
console.log(` - Instalar @aethermind/agent (via ${pm})`);
|
|
71
|
+
console.log(' - Agregar AETHERMIND_API_KEY al .env');
|
|
72
|
+
console.log(' - Agregar --require @aethermind/agent/register a NODE_OPTIONS');
|
|
73
|
+
} else {
|
|
74
|
+
console.log(' - Agregar AETHERMIND_API_KEY al .env');
|
|
75
|
+
console.log(' - Configurar OPENAI_BASE_URL -> Aethermind Gateway');
|
|
76
|
+
console.log(' - Configurar ANTHROPIC_BASE_URL -> Aethermind Gateway');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (hasOllama) {
|
|
80
|
+
console.log(' - Configurar OLLAMA_HOST -> proxy local (puerto 11435)');
|
|
81
|
+
if (language === 'node') {
|
|
82
|
+
const pm = detectPackageManager(cwd);
|
|
83
|
+
console.log(` - Instalar @aethermind/proxy (via ${pm})`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log(c.dim(' Tu codigo NO se modifica.'));
|
|
89
|
+
console.log('');
|
|
90
|
+
|
|
91
|
+
const proceed = await confirm(c.cyan(' ? ') + 'Continuar?');
|
|
92
|
+
if (!proceed) {
|
|
93
|
+
console.log('\n Setup cancelado.\n');
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log('');
|
|
98
|
+
|
|
99
|
+
// 8. Execute
|
|
100
|
+
if (language === 'node') {
|
|
101
|
+
const pm = detectPackageManager(cwd);
|
|
102
|
+
installAgent(pm);
|
|
103
|
+
updateEnvForNode(cwd, apiKey);
|
|
104
|
+
if (hasOllama) {
|
|
105
|
+
installOllamaProxy(pm);
|
|
106
|
+
addOllamaEnv(cwd);
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
updateEnvForGateway(cwd, apiKey);
|
|
110
|
+
if (hasOllama) {
|
|
111
|
+
addOllamaEnv(cwd);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 9. Done
|
|
116
|
+
summary(language, hasOllama);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function runUninstall() {
|
|
120
|
+
const cwd = process.cwd();
|
|
121
|
+
|
|
122
|
+
banner();
|
|
123
|
+
console.log(c.yellow(' Desinstalando Aethermind...\n'));
|
|
124
|
+
|
|
125
|
+
const language = detectLanguage(cwd);
|
|
126
|
+
|
|
127
|
+
const proceed = await confirm(c.cyan(' ? ') + 'Desinstalar Aethermind y restaurar .env?');
|
|
128
|
+
if (!proceed) {
|
|
129
|
+
console.log('\n Cancelado.\n');
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.log('');
|
|
134
|
+
|
|
135
|
+
if (language === 'node') {
|
|
136
|
+
const pm = detectPackageManager(cwd);
|
|
137
|
+
uninstallAgent(pm);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
restoreEnvFile(cwd);
|
|
141
|
+
|
|
142
|
+
console.log(c.green('\n Aethermind desinstalado correctamente.\n'));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function main({ uninstall = false } = {}) {
|
|
146
|
+
if (uninstall) {
|
|
147
|
+
return runUninstall();
|
|
148
|
+
}
|
|
149
|
+
return runSetup();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
module.exports = { main };
|
package/src/install.js
CHANGED
|
@@ -1,44 +1,63 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { execSync } = require('child_process');
|
|
4
|
-
const { ok, fail } = require('./ui.js');
|
|
5
|
-
|
|
6
|
-
function
|
|
7
|
-
const cmds = {
|
|
8
|
-
npm: 'npm install @aethermind/
|
|
9
|
-
pnpm: 'pnpm add @aethermind/
|
|
10
|
-
yarn: 'yarn add @aethermind/
|
|
11
|
-
bun: 'bun add @aethermind/
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const cmd = cmds[packageManager] || cmds.npm;
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
execSync(cmd, { stdio: 'pipe', timeout: 120000 });
|
|
18
|
-
ok('@aethermind/
|
|
19
|
-
} catch (err) {
|
|
20
|
-
fail(`Error instalando @aethermind/
|
|
21
|
-
console.log(` Intenta manualmente: ${cmd}`);
|
|
22
|
-
throw new Error(`Fallo la instalacion: ${err.message}`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function
|
|
27
|
-
const cmds = {
|
|
28
|
-
npm: 'npm uninstall @aethermind/
|
|
29
|
-
pnpm: 'pnpm remove @aethermind/
|
|
30
|
-
yarn: 'yarn remove @aethermind/
|
|
31
|
-
bun: 'bun remove @aethermind/
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const cmd = cmds[packageManager] || cmds.npm;
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
execSync(cmd, { stdio: 'pipe', timeout: 120000 });
|
|
38
|
-
ok('@aethermind/
|
|
39
|
-
} catch (_) {
|
|
40
|
-
// may not be installed, that's ok
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
const { ok, fail } = require('./ui.js');
|
|
5
|
+
|
|
6
|
+
function installAgent(packageManager) {
|
|
7
|
+
const cmds = {
|
|
8
|
+
npm: 'npm install @aethermind/agent --legacy-peer-deps',
|
|
9
|
+
pnpm: 'pnpm add @aethermind/agent',
|
|
10
|
+
yarn: 'yarn add @aethermind/agent',
|
|
11
|
+
bun: 'bun add @aethermind/agent',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const cmd = cmds[packageManager] || cmds.npm;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
execSync(cmd, { stdio: 'pipe', timeout: 120000 });
|
|
18
|
+
ok('@aethermind/agent instalado');
|
|
19
|
+
} catch (err) {
|
|
20
|
+
fail(`Error instalando @aethermind/agent con ${packageManager}`);
|
|
21
|
+
console.log(` Intenta manualmente: ${cmd}`);
|
|
22
|
+
throw new Error(`Fallo la instalacion: ${err.message}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function uninstallAgent(packageManager) {
|
|
27
|
+
const cmds = {
|
|
28
|
+
npm: 'npm uninstall @aethermind/agent',
|
|
29
|
+
pnpm: 'pnpm remove @aethermind/agent',
|
|
30
|
+
yarn: 'yarn remove @aethermind/agent',
|
|
31
|
+
bun: 'bun remove @aethermind/agent',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const cmd = cmds[packageManager] || cmds.npm;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
execSync(cmd, { stdio: 'pipe', timeout: 120000 });
|
|
38
|
+
ok('@aethermind/agent desinstalado');
|
|
39
|
+
} catch (_) {
|
|
40
|
+
// may not be installed, that's ok
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function installOllamaProxy(packageManager) {
|
|
45
|
+
const cmds = {
|
|
46
|
+
npm: 'npm install @aethermind/proxy --legacy-peer-deps',
|
|
47
|
+
pnpm: 'pnpm add @aethermind/proxy',
|
|
48
|
+
yarn: 'yarn add @aethermind/proxy',
|
|
49
|
+
bun: 'bun add @aethermind/proxy',
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const cmd = cmds[packageManager] || cmds.npm;
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
execSync(cmd, { stdio: 'pipe', timeout: 120000 });
|
|
56
|
+
ok('@aethermind/proxy instalado');
|
|
57
|
+
} catch (err) {
|
|
58
|
+
fail(`Error instalando @aethermind/proxy con ${packageManager}`);
|
|
59
|
+
console.log(` Intenta manualmente: ${cmd}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = { installAgent, uninstallAgent, installOllamaProxy };
|
package/src/ui.js
CHANGED
|
@@ -1,53 +1,64 @@
|
|
|
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(
|
|
42
|
-
console.log(c.green(c.bold(' Listo
|
|
43
|
-
console.log('');
|
|
44
|
-
console.log(' Corre tu app normalmente:');
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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(language, hasOllama) {
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(c.dim(' ' + '='.repeat(40)));
|
|
42
|
+
console.log(c.green(c.bold(' Listo! Tu app esta siendo monitoreada.')));
|
|
43
|
+
console.log('');
|
|
44
|
+
console.log(' Corre tu app normalmente:');
|
|
45
|
+
if (language === 'python') {
|
|
46
|
+
console.log(c.cyan(' python app.py'));
|
|
47
|
+
} else {
|
|
48
|
+
console.log(c.cyan(' node app.js'));
|
|
49
|
+
}
|
|
50
|
+
if (hasOllama) {
|
|
51
|
+
console.log('');
|
|
52
|
+
console.log(' Para modelos Ollama, antes inicia el proxy:');
|
|
53
|
+
console.log(c.cyan(' npx @aethermind/proxy'));
|
|
54
|
+
}
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log(' No necesitas cambiar tu codigo.');
|
|
57
|
+
console.log('');
|
|
58
|
+
console.log(' Mira tu dashboard:');
|
|
59
|
+
console.log(c.cyan(' https://aethermind-agent-os-dashboard.vercel.app'));
|
|
60
|
+
console.log(c.dim(' ' + '='.repeat(40)));
|
|
61
|
+
console.log('');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = { banner, ok, fail, info, separator, summary, c };
|
package/src/validate.js
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const https = require('https');
|
|
4
|
-
const http = require('http');
|
|
5
|
-
const { ok, fail } = require('./ui.js');
|
|
6
|
-
|
|
7
|
-
const API_BASE = 'https://aethermind-agentos-production.up.railway.app';
|
|
8
|
-
|
|
9
|
-
function validateApiKey(apiKey) {
|
|
10
|
-
return new Promise((resolve, reject) => {
|
|
11
|
-
const url = new URL(`${API_BASE}/v1/validate`);
|
|
12
|
-
const client = url.protocol === 'https:' ? https : http;
|
|
13
|
-
|
|
14
|
-
const req = client.get(
|
|
15
|
-
url.href,
|
|
16
|
-
{
|
|
17
|
-
headers: {
|
|
18
|
-
'X-API-Key': apiKey,
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
(res) => {
|
|
22
|
-
let body = '';
|
|
23
|
-
res.on('data', (chunk) => (body += chunk));
|
|
24
|
-
res.on('end', () => {
|
|
25
|
-
if (res.statusCode === 200) {
|
|
26
|
-
try {
|
|
27
|
-
const data = JSON.parse(body);
|
|
28
|
-
if (data.valid) {
|
|
29
|
-
ok(`API key valida — organizacion: ${data.organization}`);
|
|
30
|
-
resolve(data);
|
|
31
|
-
} else {
|
|
32
|
-
fail('API key invalida');
|
|
33
|
-
reject(new Error('API key invalida. Verifica tu AETHERMIND_API_KEY.'));
|
|
34
|
-
}
|
|
35
|
-
} catch (_) {
|
|
36
|
-
ok('API key valida');
|
|
37
|
-
resolve({});
|
|
38
|
-
}
|
|
39
|
-
} else if (res.statusCode === 401 || res.statusCode === 403) {
|
|
40
|
-
fail('API key invalida o inactiva');
|
|
41
|
-
reject(new Error('API key invalida. Verifica tu AETHERMIND_API_KEY.'));
|
|
42
|
-
} else {
|
|
43
|
-
fail(`Error validando API key (HTTP ${res.statusCode})`);
|
|
44
|
-
reject(new Error(`Error del servidor (HTTP ${res.statusCode}). Intenta de nuevo.`));
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
req.on('error', (err) => {
|
|
51
|
-
fail(`No se pudo conectar al servidor: ${err.message}`);
|
|
52
|
-
reject(new Error('No se pudo validar la API key. Verifica tu conexion a internet.'));
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
req.end();
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
module.exports = { validateApiKey };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const http = require('http');
|
|
5
|
+
const { ok, fail } = require('./ui.js');
|
|
6
|
+
|
|
7
|
+
const API_BASE = 'https://aethermind-agentos-production.up.railway.app';
|
|
8
|
+
|
|
9
|
+
function validateApiKey(apiKey) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const url = new URL(`${API_BASE}/v1/validate`);
|
|
12
|
+
const client = url.protocol === 'https:' ? https : http;
|
|
13
|
+
|
|
14
|
+
const req = client.get(
|
|
15
|
+
url.href,
|
|
16
|
+
{
|
|
17
|
+
headers: {
|
|
18
|
+
'X-API-Key': apiKey,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
(res) => {
|
|
22
|
+
let body = '';
|
|
23
|
+
res.on('data', (chunk) => (body += chunk));
|
|
24
|
+
res.on('end', () => {
|
|
25
|
+
if (res.statusCode === 200) {
|
|
26
|
+
try {
|
|
27
|
+
const data = JSON.parse(body);
|
|
28
|
+
if (data.valid) {
|
|
29
|
+
ok(`API key valida — organizacion: ${data.organization}`);
|
|
30
|
+
resolve(data);
|
|
31
|
+
} else {
|
|
32
|
+
fail('API key invalida');
|
|
33
|
+
reject(new Error('API key invalida. Verifica tu AETHERMIND_API_KEY.'));
|
|
34
|
+
}
|
|
35
|
+
} catch (_) {
|
|
36
|
+
ok('API key valida');
|
|
37
|
+
resolve({});
|
|
38
|
+
}
|
|
39
|
+
} else if (res.statusCode === 401 || res.statusCode === 403) {
|
|
40
|
+
fail('API key invalida o inactiva');
|
|
41
|
+
reject(new Error('API key invalida. Verifica tu AETHERMIND_API_KEY.'));
|
|
42
|
+
} else {
|
|
43
|
+
fail(`Error validando API key (HTTP ${res.statusCode})`);
|
|
44
|
+
reject(new Error(`Error del servidor (HTTP ${res.statusCode}). Intenta de nuevo.`));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
req.on('error', (err) => {
|
|
51
|
+
fail(`No se pudo conectar al servidor: ${err.message}`);
|
|
52
|
+
reject(new Error('No se pudo validar la API key. Verifica tu conexion a internet.'));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
req.end();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = { validateApiKey };
|