natureco-cli 2.23.28 β 2.23.30
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/README.md +94 -11
- package/bin/natureco.js +470 -10
- package/package.json +10 -6
- package/src/commands/admin-rpc.js +219 -0
- package/src/commands/agent.js +89 -0
- package/src/commands/approvals.js +53 -0
- package/src/commands/backup.js +124 -0
- package/src/commands/bonjour.js +167 -0
- package/src/commands/capability.js +64 -0
- package/src/commands/channels.js +94 -4
- package/src/commands/chat.js +11 -25
- package/src/commands/clickclack.js +130 -0
- package/src/commands/commitments.js +32 -0
- package/src/commands/completion.js +76 -0
- package/src/commands/config.js +111 -68
- package/src/commands/configure.js +93 -0
- package/src/commands/crestodian.js +92 -0
- package/src/commands/daemon.js +60 -0
- package/src/commands/device-pair.js +248 -0
- package/src/commands/devices.js +110 -0
- package/src/commands/directory.js +47 -0
- package/src/commands/dns.js +58 -0
- package/src/commands/docs.js +43 -0
- package/src/commands/doctor.js +121 -16
- package/src/commands/exec-policy.js +71 -0
- package/src/commands/gateway-server.js +1175 -30
- package/src/commands/gateway.js +11 -20
- package/src/commands/health.js +18 -0
- package/src/commands/help.js +6 -0
- package/src/commands/imessage.js +169 -0
- package/src/commands/infer.js +73 -0
- package/src/commands/irc.js +119 -0
- package/src/commands/mattermost.js +164 -0
- package/src/commands/memory-cmd.js +134 -1
- package/src/commands/message.js +30 -4
- package/src/commands/migrate.js +213 -2
- package/src/commands/models.js +584 -216
- package/src/commands/node.js +98 -0
- package/src/commands/nodes.js +106 -0
- package/src/commands/oc-path.js +200 -0
- package/src/commands/onboard.js +70 -0
- package/src/commands/open-prose.js +67 -0
- package/src/commands/plugins.js +415 -172
- package/src/commands/policy.js +176 -0
- package/src/commands/proxy.js +155 -0
- package/src/commands/qr.js +28 -0
- package/src/commands/sandbox.js +125 -0
- package/src/commands/secrets.js +118 -0
- package/src/commands/security.js +149 -1
- package/src/commands/setup.js +114 -10
- package/src/commands/signal.js +495 -0
- package/src/commands/skills.js +20 -29
- package/src/commands/sms.js +168 -0
- package/src/commands/system.js +53 -0
- package/src/commands/tasks.js +328 -79
- package/src/commands/terminal.js +21 -0
- package/src/commands/thread-ownership.js +157 -0
- package/src/commands/transcripts.js +72 -0
- package/src/commands/voice.js +82 -0
- package/src/commands/vydra.js +98 -0
- package/src/commands/webhooks.js +79 -0
- package/src/commands/whatsapp.js +7 -21
- package/src/commands/workboard.js +207 -0
- package/src/tools/audio_understanding.js +154 -0
- package/src/tools/bash.js +63 -29
- package/src/tools/browser.js +112 -0
- package/src/tools/canvas.js +104 -0
- package/src/tools/document_extract.js +84 -0
- package/src/tools/duckduckgo.js +54 -0
- package/src/tools/exa_search.js +66 -0
- package/src/tools/firecrawl.js +104 -0
- package/src/tools/image_generation.js +99 -0
- package/src/tools/llm_task.js +118 -0
- package/src/tools/media_understanding.js +128 -0
- package/src/tools/music_generation.js +113 -0
- package/src/tools/parallel_search.js +77 -0
- package/src/tools/phone_control.js +80 -0
- package/src/tools/phone_control_enhanced.js +184 -0
- package/src/tools/searxng.js +61 -0
- package/src/tools/speech_to_text.js +135 -0
- package/src/tools/text_to_speech.js +105 -0
- package/src/tools/thread_ownership.js +88 -0
- package/src/tools/video_generation.js +72 -0
- package/src/tools/web_readability.js +104 -0
- package/src/utils/api.js +3 -20
- package/src/utils/approvals.js +297 -0
- package/src/utils/background.js +223 -66
- package/src/utils/baileys.js +21 -0
- package/src/utils/config.js +141 -10
- package/src/utils/errors.js +148 -0
- package/src/utils/inquirer-wrapper.js +1 -2
- package/src/utils/memory.js +200 -0
- package/src/utils/path-utils.js +13 -13
- package/src/utils/plugin-registry.js +238 -0
- package/src/utils/secrets.js +177 -0
- package/src/utils/skills.js +10 -23
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
6
|
+
|
|
7
|
+
function policy(args) {
|
|
8
|
+
const [action, ...params] = (args || []);
|
|
9
|
+
|
|
10
|
+
if (!action || action === 'check') return checkPolicy();
|
|
11
|
+
if (action === 'set') return setPolicy(params[0], params.slice(1).join(' '));
|
|
12
|
+
if (action === 'list') return listPolicies();
|
|
13
|
+
if (action === 'remove') return removePolicy(params[0]);
|
|
14
|
+
|
|
15
|
+
console.log(chalk.red(`\n β Bilinmeyen komut: ${action}\n`));
|
|
16
|
+
console.log(chalk.gray(' KullanΔ±m: natureco policy [check|set|list|remove]\n'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const POLICY_CHECKS = [
|
|
21
|
+
{
|
|
22
|
+
id: 'node-version',
|
|
23
|
+
name: 'Node.js Versiyonu',
|
|
24
|
+
check: () => {
|
|
25
|
+
const v = process.version.slice(1).split('.')[0];
|
|
26
|
+
return parseInt(v) >= 18
|
|
27
|
+
? { status: 'pass', message: `Node.js ${process.version}` }
|
|
28
|
+
: { status: 'fail', message: `Node.js ${process.version} (18+ gerekli)`, fix: 'Node.js gΓΌncelleyin' };
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'config-exists',
|
|
33
|
+
name: 'Config DosyasΔ±',
|
|
34
|
+
check: () => {
|
|
35
|
+
const configFile = path.join(os.homedir(), '.natureco', 'config.json');
|
|
36
|
+
if (!fs.existsSync(configFile)) {
|
|
37
|
+
return { status: 'fail', message: 'config.json bulunamadΔ±', fix: 'natureco setup Γ§alΔ±ΕtΔ±rΔ±n' };
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
JSON.parse(fs.readFileSync(configFile, 'utf-8'));
|
|
41
|
+
return { status: 'pass', message: 'Config geΓ§erli JSON' };
|
|
42
|
+
} catch {
|
|
43
|
+
return { status: 'fail', message: 'Config bozuk JSON', fix: '~/.natureco/config.json dΓΌzeltin' };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'api-key',
|
|
49
|
+
name: 'API Key',
|
|
50
|
+
check: () => {
|
|
51
|
+
const config = getConfig();
|
|
52
|
+
if (config.providerApiKey || config.apiKey || process.env.GROQ_API_KEY) {
|
|
53
|
+
return { status: 'pass', message: 'API key mevcut' };
|
|
54
|
+
}
|
|
55
|
+
return { status: 'warn', message: 'API key eksik', fix: 'natureco login veya GROQ_API_KEY env' };
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 'provider-url',
|
|
60
|
+
name: 'Provider URL',
|
|
61
|
+
check: () => {
|
|
62
|
+
const config = getConfig();
|
|
63
|
+
if (config.providerUrl) {
|
|
64
|
+
return { status: 'pass', message: config.providerUrl };
|
|
65
|
+
}
|
|
66
|
+
return { status: 'warn', message: 'Provider ayarlanmamΔ±Ε', fix: 'natureco setup' };
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'git-config',
|
|
71
|
+
name: 'Git YapΔ±landΔ±rmasΔ±',
|
|
72
|
+
check: () => {
|
|
73
|
+
try {
|
|
74
|
+
const { execSync } = require('child_process');
|
|
75
|
+
const name = execSync('git config user.name', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
76
|
+
const email = execSync('git config user.email', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
77
|
+
if (name && email) return { status: 'pass', message: `${name} <${email}>` };
|
|
78
|
+
return { status: 'warn', message: 'Git user.name/email eksik', fix: 'git config --global user.name "AdΔ±nΔ±z"' };
|
|
79
|
+
} catch {
|
|
80
|
+
return { status: 'warn', message: 'Git repo deΔil', fix: 'git init' };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'disk-space',
|
|
86
|
+
name: 'Disk AlanΔ±',
|
|
87
|
+
check: () => {
|
|
88
|
+
try {
|
|
89
|
+
const drive = path.parse(os.homedir()).root.replace(':', '');
|
|
90
|
+
const { execSync } = require('child_process');
|
|
91
|
+
const output = execSync(`powershell -Command "Get-PSDrive -Name ${drive} | Select-Object -ExpandProperty Free"`, { encoding: 'utf-8' }).trim();
|
|
92
|
+
const free = parseInt(output);
|
|
93
|
+
if (isNaN(free)) return { status: 'pass', message: 'Kontrol edilemedi' };
|
|
94
|
+
const freeGB = free / 1e9;
|
|
95
|
+
if (freeGB < 0.5) return { status: 'fail', message: `Sadece ${freeGB.toFixed(1)}GB boΕ`, fix: 'Disk temizliΔi yapΔ±n' };
|
|
96
|
+
return { status: 'pass', message: `${freeGB.toFixed(1)}GB boΕ alan` };
|
|
97
|
+
} catch {
|
|
98
|
+
return { status: 'pass', message: 'Kontrol edilemedi' };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
function checkPolicy() {
|
|
105
|
+
console.log(chalk.cyan.bold('\n Workspace Uyumluluk PolitikasΔ±\n'));
|
|
106
|
+
console.log(chalk.gray(' ' + 'β'.repeat(48)));
|
|
107
|
+
|
|
108
|
+
let passed = 0;
|
|
109
|
+
let failed = 0;
|
|
110
|
+
let warnings = 0;
|
|
111
|
+
|
|
112
|
+
for (const check of POLICY_CHECKS) {
|
|
113
|
+
const result = check.check();
|
|
114
|
+
if (result.status === 'pass') {
|
|
115
|
+
console.log(` ${chalk.green('β')} ${check.name}: ${chalk.white(result.message)}`);
|
|
116
|
+
passed++;
|
|
117
|
+
} else if (result.status === 'fail') {
|
|
118
|
+
console.log(` ${chalk.red('β')} ${check.name}: ${chalk.white(result.message)}`);
|
|
119
|
+
console.log(chalk.gray(` DΓΌzeltme: ${result.fix}`));
|
|
120
|
+
failed++;
|
|
121
|
+
} else {
|
|
122
|
+
console.log(` ${chalk.yellow('β ')} ${check.name}: ${chalk.white(result.message)}`);
|
|
123
|
+
if (result.fix) console.log(chalk.gray(` Γneri: ${result.fix}`));
|
|
124
|
+
warnings++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log(chalk.gray(' ' + 'β'.repeat(48)));
|
|
129
|
+
console.log(chalk.gray(` GeΓ§ti: ${passed} | UyarΔ±: ${warnings} | Hata: ${failed}\n`));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function setPolicy(key, value) {
|
|
133
|
+
if (!key) {
|
|
134
|
+
console.log(chalk.red('\n β Politika adΔ± gerekli\n'));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const config = getConfig();
|
|
138
|
+
if (!config.policies) config.policies = {};
|
|
139
|
+
config.policies[key] = value;
|
|
140
|
+
saveConfig(config);
|
|
141
|
+
console.log(chalk.green(`\n β Politika ayarlandΔ±: ${key} = ${value}\n`));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function listPolicies() {
|
|
145
|
+
const config = getConfig();
|
|
146
|
+
const policies = config.policies || {};
|
|
147
|
+
|
|
148
|
+
if (Object.keys(policies).length === 0) {
|
|
149
|
+
console.log(chalk.gray('\n TanΔ±mlΔ± politika yok.\n'));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
console.log(chalk.cyan.bold('\n TanΔ±mlΔ± Politikalar\n'));
|
|
154
|
+
console.log(chalk.gray(' ' + 'β'.repeat(48)));
|
|
155
|
+
for (const [key, value] of Object.entries(policies)) {
|
|
156
|
+
console.log(` ${chalk.white(key)}: ${chalk.cyan(value)}`);
|
|
157
|
+
}
|
|
158
|
+
console.log('');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function removePolicy(key) {
|
|
162
|
+
if (!key) {
|
|
163
|
+
console.log(chalk.red('\n β Politika adΔ± gerekli\n'));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const config = getConfig();
|
|
167
|
+
if (config.policies?.[key]) {
|
|
168
|
+
delete config.policies[key];
|
|
169
|
+
saveConfig(config);
|
|
170
|
+
console.log(chalk.green(`\n β Politika silindi: ${key}\n`));
|
|
171
|
+
} else {
|
|
172
|
+
console.log(chalk.yellow(`\n β Politika bulunamadΔ±: ${key}\n`));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
module.exports = policy;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const http = require('http');
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const { URL } = require('url');
|
|
5
|
+
|
|
6
|
+
let proxyInstance = null;
|
|
7
|
+
let captured = [];
|
|
8
|
+
let forwardUrl = null;
|
|
9
|
+
|
|
10
|
+
function proxy(args) {
|
|
11
|
+
const [action, ...params] = args || [];
|
|
12
|
+
|
|
13
|
+
if (!action || action === 'status') return statusProxy();
|
|
14
|
+
if (action === 'start') return startProxy(params);
|
|
15
|
+
if (action === 'stop') return stopProxy();
|
|
16
|
+
if (action === 'capture') return showCapture();
|
|
17
|
+
if (action === 'clear') return clearCapture();
|
|
18
|
+
|
|
19
|
+
console.log(chalk.red(`\n β Bilinmeyen komut: ${action}\n`));
|
|
20
|
+
console.log(chalk.gray(' KullanΔ±m: natureco proxy [status|start|stop|capture|clear]\n'));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function statusProxy() {
|
|
25
|
+
console.log(chalk.cyan('\n π Debug Proxy\n'));
|
|
26
|
+
console.log(chalk.gray(' ' + 'β'.repeat(48)));
|
|
27
|
+
console.log(` ${chalk.white('Status:')} ${proxyInstance ? chalk.green('Running') : chalk.red('Stopped')}`);
|
|
28
|
+
if (proxyInstance) {
|
|
29
|
+
console.log(` ${chalk.white('Port:')} ${proxyInstance.port}`);
|
|
30
|
+
console.log(` ${chalk.white('Forward:')} ${forwardUrl ? chalk.cyan(forwardUrl) : chalk.gray('(none)')}`);
|
|
31
|
+
console.log(` ${chalk.white('Captured:')} ${captured.length} request(s)`);
|
|
32
|
+
}
|
|
33
|
+
console.log(chalk.gray('\n Examples:'));
|
|
34
|
+
console.log(chalk.gray(' ') + chalk.cyan('natureco proxy start'));
|
|
35
|
+
console.log(chalk.gray(' ') + chalk.cyan('natureco proxy start 9090'));
|
|
36
|
+
console.log(chalk.gray(' ') + chalk.cyan('natureco proxy start 8080 --forward http://localhost:3000'));
|
|
37
|
+
console.log(chalk.gray(' ') + chalk.cyan('natureco proxy capture'));
|
|
38
|
+
console.log(chalk.gray(' ') + chalk.cyan('natureco proxy clear'));
|
|
39
|
+
console.log(chalk.gray(' ') + chalk.cyan('natureco proxy stop'));
|
|
40
|
+
console.log();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function startProxy(params) {
|
|
44
|
+
if (proxyInstance) {
|
|
45
|
+
console.log(chalk.yellow('\n β οΈ Proxy already running\n'));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const port = parseInt(params[0], 10) || 8080;
|
|
50
|
+
const fwdIdx = params.indexOf('--forward');
|
|
51
|
+
if (fwdIdx !== -1 && params[fwdIdx + 1]) {
|
|
52
|
+
forwardUrl = params[fwdIdx + 1];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
captured = [];
|
|
56
|
+
|
|
57
|
+
const server = http.createServer((req, res) => {
|
|
58
|
+
const chunks = [];
|
|
59
|
+
req.on('data', chunk => chunks.push(chunk));
|
|
60
|
+
req.on('end', () => {
|
|
61
|
+
const body = Buffer.concat(chunks).toString();
|
|
62
|
+
const entry = {
|
|
63
|
+
id: captured.length + 1,
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
method: req.method,
|
|
66
|
+
url: req.url,
|
|
67
|
+
headers: req.headers,
|
|
68
|
+
body: body ? body.substring(0, 2000) : null
|
|
69
|
+
};
|
|
70
|
+
captured.push(entry);
|
|
71
|
+
if (captured.length > 200) captured.shift();
|
|
72
|
+
|
|
73
|
+
console.log(chalk.gray(` [${entry.id}] ${chalk.cyan(req.method)} ${req.url}`));
|
|
74
|
+
|
|
75
|
+
if (forwardUrl) {
|
|
76
|
+
try {
|
|
77
|
+
const target = new URL(req.url, forwardUrl);
|
|
78
|
+
const proxyReq = http.request({
|
|
79
|
+
hostname: target.hostname,
|
|
80
|
+
port: target.port || 80,
|
|
81
|
+
path: target.pathname + target.search,
|
|
82
|
+
method: req.method,
|
|
83
|
+
headers: { ...req.headers, host: target.host }
|
|
84
|
+
}, proxyRes => {
|
|
85
|
+
let proxyBody = '';
|
|
86
|
+
proxyRes.on('data', c => proxyBody += c);
|
|
87
|
+
proxyRes.on('end', () => {
|
|
88
|
+
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
89
|
+
res.end(proxyBody);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
proxyReq.on('error', () => {
|
|
93
|
+
res.writeHead(502);
|
|
94
|
+
res.end('Bad Gateway');
|
|
95
|
+
});
|
|
96
|
+
if (body) proxyReq.write(body);
|
|
97
|
+
proxyReq.end();
|
|
98
|
+
} catch {
|
|
99
|
+
res.writeHead(502);
|
|
100
|
+
res.end('Bad Gateway');
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
104
|
+
res.end(JSON.stringify({ ok: true, id: entry.id, captured: captured.length }));
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
proxyInstance = server;
|
|
110
|
+
proxyInstance.port = port;
|
|
111
|
+
server.listen(port, () => {
|
|
112
|
+
console.log(chalk.green(`\n π Debug proxy on http://localhost:${port}\n`));
|
|
113
|
+
if (forwardUrl) console.log(chalk.gray(` Forwarding to: ${forwardUrl}\n`));
|
|
114
|
+
console.log(chalk.gray(' Captured requests shown below. Press Ctrl+C to stop.\n'));
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function stopProxy() {
|
|
119
|
+
if (!proxyInstance) {
|
|
120
|
+
console.log(chalk.yellow('\n β οΈ Proxy not running\n'));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
proxyInstance.close(() => {
|
|
124
|
+
console.log(chalk.gray('\n π Proxy stopped\n'));
|
|
125
|
+
proxyInstance = null;
|
|
126
|
+
forwardUrl = null;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function showCapture() {
|
|
131
|
+
if (captured.length === 0) {
|
|
132
|
+
console.log(chalk.gray('\n No captured requests.\n'));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
console.log(chalk.cyan(`\n π Captured Requests (${captured.length})\n`));
|
|
137
|
+
console.log(chalk.gray(' ' + 'β'.repeat(64)));
|
|
138
|
+
|
|
139
|
+
for (const entry of captured.slice(-20)) {
|
|
140
|
+
const time = entry.timestamp.slice(11, 19);
|
|
141
|
+
console.log(` ${chalk.gray(`[${entry.id}]`)} ${chalk.cyan(entry.method)} ${chalk.white(entry.url)} ${chalk.gray(time)}`);
|
|
142
|
+
if (entry.body) {
|
|
143
|
+
const preview = entry.body.length > 200 ? entry.body.substring(0, 200) + 'β¦' : entry.body;
|
|
144
|
+
console.log(` ${chalk.gray(preview)}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
console.log();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function clearCapture() {
|
|
151
|
+
captured = [];
|
|
152
|
+
console.log(chalk.gray('\n ποΈ Captured requests cleared\n'));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
module.exports = proxy;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
function qr(args) {
|
|
5
|
+
const data = args.join(' ') || generatePairingData();
|
|
6
|
+
|
|
7
|
+
console.log(chalk.cyan('\n π± QR Pairing Code\n'));
|
|
8
|
+
console.log(chalk.gray(' ' + 'β'.repeat(48)));
|
|
9
|
+
|
|
10
|
+
const code = crypto.randomBytes(4).toString('hex').toUpperCase();
|
|
11
|
+
const expiresAt = new Date(Date.now() + 15 * 60 * 1000);
|
|
12
|
+
|
|
13
|
+
console.log(` ${chalk.white('Pairing Code:')} ${chalk.bold.yellow(code)}`);
|
|
14
|
+
console.log(` ${chalk.white('Expires:')} ${chalk.gray(expiresAt.toLocaleString())}`);
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(chalk.gray(' To pair a device, run on the device:'));
|
|
17
|
+
console.log(chalk.cyan(' natureco device-pair verify ') + chalk.yellow(code));
|
|
18
|
+
console.log();
|
|
19
|
+
console.log(chalk.gray(' Or scan with the NatureCo mobile app.'));
|
|
20
|
+
console.log();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function generatePairingData() {
|
|
24
|
+
const id = crypto.randomBytes(8).toString('hex');
|
|
25
|
+
return JSON.stringify({ id, timestamp: Date.now() });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = qr;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { execSync, spawn } = require('child_process');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
const SANDBOX_DIR = path.join(os.tmpdir(), 'natureco-sandboxes');
|
|
8
|
+
|
|
9
|
+
function sandbox(args) {
|
|
10
|
+
const [action, ...params] = args || [];
|
|
11
|
+
|
|
12
|
+
if (!action || action === 'list') return listSandboxes();
|
|
13
|
+
if (action === 'create') return createSandbox(params[0]);
|
|
14
|
+
if (action === 'destroy') return destroySandbox(params[0]);
|
|
15
|
+
if (action === 'exec') return execSandbox(params[0], params.slice(1).join(' '));
|
|
16
|
+
|
|
17
|
+
console.log(chalk.red(`\n β Bilinmeyen komut: ${action}\n`));
|
|
18
|
+
console.log(chalk.gray(' KullanΔ±m: natureco sandbox [list|create|destroy|exec]\n'));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getDirSandboxes() {
|
|
23
|
+
if (!fs.existsSync(SANDBOX_DIR)) return [];
|
|
24
|
+
return fs.readdirSync(SANDBOX_DIR).filter(name => {
|
|
25
|
+
const stat = fs.statSync(path.join(SANDBOX_DIR, name));
|
|
26
|
+
return stat.isDirectory();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function listSandboxes() {
|
|
31
|
+
console.log(chalk.cyan('\n π¦ Sandbox Containers\n'));
|
|
32
|
+
console.log(chalk.gray(' ' + 'β'.repeat(48)));
|
|
33
|
+
|
|
34
|
+
// Dir-based sandboxes
|
|
35
|
+
const dirSandboxes = getDirSandboxes();
|
|
36
|
+
if (dirSandboxes.length > 0) {
|
|
37
|
+
for (const name of dirSandboxes) {
|
|
38
|
+
const dir = path.join(SANDBOX_DIR, name);
|
|
39
|
+
const files = fs.readdirSync(dir).length;
|
|
40
|
+
const created = fs.statSync(dir).birthtime;
|
|
41
|
+
console.log(` ${chalk.green('β')} ${chalk.white(name)} ${chalk.gray(`(${files} file(s), ${created.toISOString().slice(0, 10)})`)}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Docker sandboxes
|
|
46
|
+
try {
|
|
47
|
+
const dockerOut = execSync('docker ps --filter "name=natureco-sandbox" --format "{{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}" 2>nul', { encoding: 'utf8', timeout: 5000, stdio: 'pipe' }).trim();
|
|
48
|
+
if (dockerOut) {
|
|
49
|
+
for (const line of dockerOut.split('\n')) {
|
|
50
|
+
const [id, image, status, name] = line.split('\t');
|
|
51
|
+
console.log(` ${chalk.blue('β')} ${chalk.white(name || id)} ${chalk.gray(`${image} β ${status}`)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch {}
|
|
55
|
+
|
|
56
|
+
if (dirSandboxes.length === 0) {
|
|
57
|
+
console.log(chalk.gray(' No sandboxes found.\n'));
|
|
58
|
+
console.log(chalk.gray(' Create one:') + chalk.cyan(' natureco sandbox create [name]\n'));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
console.log();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function createSandbox(name) {
|
|
65
|
+
const sandboxName = name || `sandbox-${Date.now()}`;
|
|
66
|
+
const dir = path.join(SANDBOX_DIR, sandboxName);
|
|
67
|
+
|
|
68
|
+
if (fs.existsSync(dir)) {
|
|
69
|
+
console.log(chalk.red(`\n β Sandbox '${sandboxName}' already exists\n`));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
74
|
+
fs.writeFileSync(path.join(dir, '.natureco-sandbox'), JSON.stringify({ created: new Date().toISOString(), name: sandboxName }));
|
|
75
|
+
|
|
76
|
+
console.log(chalk.green(`\n β
Sandbox created: ${sandboxName}\n`));
|
|
77
|
+
console.log(chalk.gray(` Directory: ${dir}\n`));
|
|
78
|
+
console.log(chalk.gray(' Usage:') + chalk.cyan(` natureco sandbox exec ${sandboxName} "node -e 'console.log(\\"hello\\")'"`) + '\n');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function destroySandbox(name) {
|
|
82
|
+
if (!name) {
|
|
83
|
+
console.log(chalk.red('\n β Sandbox name gerekli\n'));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const dir = path.join(SANDBOX_DIR, name);
|
|
88
|
+
if (fs.existsSync(dir)) {
|
|
89
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
90
|
+
console.log(chalk.gray(` ποΈ Dir sandbox destroyed: ${name}\n`));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
execSync(`docker rm -f ${name} 2>nul`, { stdio: 'pipe', timeout: 10000 });
|
|
95
|
+
console.log(chalk.gray(` ποΈ Docker sandbox destroyed: ${name}\n`));
|
|
96
|
+
} catch {}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function execSandbox(name, command) {
|
|
100
|
+
if (!name || !command) {
|
|
101
|
+
console.log(chalk.red('\n β Sandbox name ve command gerekli\n'));
|
|
102
|
+
console.log(chalk.gray(' KullanΔ±m: natureco sandbox exec <name> <command>\n'));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const dir = path.join(SANDBOX_DIR, name);
|
|
107
|
+
if (!fs.existsSync(dir)) {
|
|
108
|
+
console.log(chalk.red(`\n β Sandbox '${name}' not found\n`));
|
|
109
|
+
console.log(chalk.gray(' Create one:') + chalk.cyan(` natureco sandbox create ${name}`) + '\n');
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log(chalk.cyan(`\n π Executing in sandbox '${name}': ${command}\n`));
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const result = execSync(command, { cwd: dir, encoding: 'utf8', timeout: 30000, stdio: 'inherit' });
|
|
117
|
+
return result;
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (err.status !== undefined) process.exit(err.status);
|
|
120
|
+
console.log(chalk.red(` β ${err.message}\n`));
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = sandbox;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
3
|
+
|
|
4
|
+
function secrets(args) {
|
|
5
|
+
const [action, ...params] = args || [];
|
|
6
|
+
|
|
7
|
+
if (!action || action === 'list') return listSecrets();
|
|
8
|
+
if (action === 'set') return setSecret(params[0], params.slice(1).join(' '));
|
|
9
|
+
if (action === 'get') return getSecret(params[0]);
|
|
10
|
+
if (action === 'unset') return unsetSecret(params[0]);
|
|
11
|
+
if (action === 'audit') return auditSecrets();
|
|
12
|
+
|
|
13
|
+
console.log(chalk.red(`\n β Bilinmeyen komut: ${action}\n`));
|
|
14
|
+
console.log(chalk.gray(' KullanΔ±m: natureco secrets [list|set|get|unset|audit]\n'));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function listSecrets() {
|
|
19
|
+
const config = getConfig();
|
|
20
|
+
const secretKeys = Object.keys(config).filter(k =>
|
|
21
|
+
k.toLowerCase().includes('key') || k.toLowerCase().includes('token') || k.toLowerCase().includes('secret')
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
console.log(chalk.cyan('\n π Secrets\n'));
|
|
25
|
+
console.log(chalk.gray(' ' + 'β'.repeat(48)));
|
|
26
|
+
|
|
27
|
+
if (secretKeys.length === 0) {
|
|
28
|
+
console.log(chalk.gray(' No secrets stored.\n'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (const key of secretKeys.sort()) {
|
|
33
|
+
const val = config[key];
|
|
34
|
+
const masked = val ? val.substring(0, 6) + 'β¦' + val.slice(-4) : '(empty)';
|
|
35
|
+
console.log(` ${chalk.white(key)}: ${chalk.gray(masked)}`);
|
|
36
|
+
}
|
|
37
|
+
console.log();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function setSecret(key, value) {
|
|
41
|
+
if (!key || !value) {
|
|
42
|
+
console.log(chalk.red('\n β key ve value gerekli\n'));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const config = getConfig();
|
|
47
|
+
config[key] = value;
|
|
48
|
+
saveConfig(config);
|
|
49
|
+
console.log(chalk.green(`\n β
Secret set: ${key}\n`));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getSecret(key) {
|
|
53
|
+
if (!key) {
|
|
54
|
+
console.log(chalk.red('\n β key gerekli\n'));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const config = getConfig();
|
|
59
|
+
const value = config[key];
|
|
60
|
+
|
|
61
|
+
if (!value) {
|
|
62
|
+
console.log(chalk.yellow(`\n β οΈ Secret not found: ${key}\n`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log(chalk.cyan(`\n ${key}: ${chalk.white(value)}\n`));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function unsetSecret(key) {
|
|
70
|
+
if (!key) {
|
|
71
|
+
console.log(chalk.red('\n β key gerekli\n'));
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const config = getConfig();
|
|
76
|
+
delete config[key];
|
|
77
|
+
saveConfig(config);
|
|
78
|
+
console.log(chalk.gray(`\n ποΈ Secret removed: ${key}\n`));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function auditSecrets() {
|
|
82
|
+
const config = getConfig();
|
|
83
|
+
const secrets = Object.keys(config).filter(k =>
|
|
84
|
+
k.toLowerCase().includes('key') || k.toLowerCase().includes('token') || k.toLowerCase().includes('secret')
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const envKeys = ['OPENAI_API_KEY', 'ANTHROPIC_API_KEY', 'GROQ_API_KEY', 'TAVILY_API_KEY',
|
|
88
|
+
'ELEVENLABS_API_KEY', 'DEEPGRAM_API_KEY', 'FAL_KEY', 'TOGETHER_API_KEY',
|
|
89
|
+
'PUSHOVER_TOKEN', 'PUSHOVER_USER', 'NTFY_TOPIC', 'NTFY_SERVER',
|
|
90
|
+
'TWILIO_SID', 'TWILIO_TOKEN', 'TWILIO_FROM', 'SUNO_API_KEY', 'UDIO_API_KEY',
|
|
91
|
+
'VYDRA_API_KEY', 'SLACK_BOT_TOKEN', 'DISCORD_BOT_TOKEN', 'TELEGRAM_BOT_TOKEN',
|
|
92
|
+
'WHATSAPP_API_KEY'
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
console.log(chalk.cyan('\n π Secrets Audit\n'));
|
|
96
|
+
console.log(chalk.gray(' ' + 'β'.repeat(48)));
|
|
97
|
+
|
|
98
|
+
console.log(chalk.white('\n Config Secrets:'));
|
|
99
|
+
for (const key of secrets.sort()) {
|
|
100
|
+
const val = config[key];
|
|
101
|
+
const status = val ? chalk.green('set') : chalk.red('empty');
|
|
102
|
+
console.log(` ${chalk.gray('β')} ${key}: ${status}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log(chalk.white('\n Environment Variables:'));
|
|
106
|
+
let found = 0;
|
|
107
|
+
for (const envKey of envKeys) {
|
|
108
|
+
if (process.env[envKey]) {
|
|
109
|
+
console.log(` ${chalk.green('β')} ${envKey}: ${chalk.green('set')}`);
|
|
110
|
+
found++;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (found === 0) console.log(chalk.gray(' (none set in environment)'));
|
|
114
|
+
|
|
115
|
+
console.log(chalk.gray(`\n Total: ${secrets.length} config + ${found} env\n`));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = secrets;
|