natureco-cli 2.23.29 → 2.23.31
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 +495 -94
- package/package.json +1 -1
- package/src/commands/acp.js +39 -0
- package/src/commands/admin-rpc.js +302 -0
- package/src/commands/agent.js +280 -0
- package/src/commands/agents.js +114 -30
- package/src/commands/approvals.js +214 -0
- package/src/commands/backup.js +124 -0
- package/src/commands/bonjour.js +167 -0
- package/src/commands/browser.js +815 -0
- package/src/commands/capability.js +237 -0
- package/src/commands/channels.js +422 -267
- package/src/commands/chat.js +5 -8
- package/src/commands/clawbot.js +19 -0
- package/src/commands/clickclack.js +130 -0
- package/src/commands/code.js +3 -2
- package/src/commands/commitments.js +148 -0
- package/src/commands/completion.js +84 -0
- package/src/commands/config.js +219 -30
- package/src/commands/configure.js +110 -0
- package/src/commands/crestodian.js +92 -0
- package/src/commands/cron.js +239 -19
- package/src/commands/daemon.js +90 -0
- package/src/commands/dashboard.js +47 -374
- package/src/commands/device-pair.js +248 -0
- package/src/commands/devices.js +137 -0
- package/src/commands/directory.js +179 -0
- package/src/commands/dns.js +196 -0
- package/src/commands/docs.js +136 -0
- package/src/commands/doctor.js +143 -492
- package/src/commands/exec-policy.js +80 -0
- package/src/commands/gateway-server.js +1155 -24
- package/src/commands/gateway.js +492 -249
- package/src/commands/health.js +148 -0
- package/src/commands/help.js +24 -25
- package/src/commands/hooks.js +141 -87
- package/src/commands/imessage.js +128 -14
- package/src/commands/infer.js +1474 -0
- package/src/commands/irc.js +64 -15
- package/src/commands/logs.js +122 -99
- package/src/commands/mattermost.js +114 -12
- package/src/commands/mcp.js +121 -309
- package/src/commands/memory-cmd.js +134 -1
- package/src/commands/memory.js +128 -0
- package/src/commands/message.js +720 -134
- package/src/commands/migrate.js +213 -2
- package/src/commands/models.js +39 -1
- package/src/commands/node.js +98 -0
- package/src/commands/nodes.js +362 -0
- package/src/commands/oc-path.js +200 -0
- package/src/commands/onboard.js +129 -0
- package/src/commands/open-prose.js +67 -0
- package/src/commands/pairing.js +108 -107
- package/src/commands/path.js +206 -0
- package/src/commands/plugins.js +35 -1
- package/src/commands/policy.js +176 -0
- package/src/commands/proxy.js +306 -0
- package/src/commands/qr.js +70 -0
- package/src/commands/reset.js +101 -94
- package/src/commands/sandbox.js +125 -0
- package/src/commands/secrets.js +201 -0
- package/src/commands/sessions.js +110 -51
- package/src/commands/setup.js +102 -543
- package/src/commands/signal.js +447 -18
- package/src/commands/skills.js +67 -1
- package/src/commands/sms.js +123 -19
- package/src/commands/status.js +101 -127
- package/src/commands/system.js +53 -0
- package/src/commands/tasks.js +208 -100
- package/src/commands/terminal.js +139 -0
- package/src/commands/thread-ownership.js +157 -0
- package/src/commands/transcripts.js +95 -0
- package/src/commands/tui.js +41 -0
- package/src/commands/uninstall.js +73 -92
- package/src/commands/update.js +146 -91
- package/src/commands/voice.js +82 -0
- package/src/commands/vydra.js +98 -0
- package/src/commands/webhooks.js +58 -66
- package/src/commands/wiki.js +783 -0
- package/src/commands/workboard.js +207 -0
- package/src/tools/audio_understanding.js +154 -0
- 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/agents-md.js +85 -0
- package/src/utils/api.js +39 -40
- package/src/utils/format.js +144 -0
- package/src/utils/headless.js +2 -1
- package/src/utils/memory.js +200 -0
- package/src/utils/parallel-tools.js +106 -0
- package/src/utils/sub-agent.js +148 -0
- package/src/utils/token-budget.js +304 -0
- package/src/utils/tool-runner.js +7 -5
- package/src/utils/web-fetch.js +107 -0
package/src/commands/reset.js
CHANGED
|
@@ -1,94 +1,101 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const readline = require('readline');
|
|
6
|
+
|
|
7
|
+
const BASE_DIR = path.join(os.homedir(), '.natureco');
|
|
8
|
+
const CONFIG_FILE = path.join(BASE_DIR, 'config.json');
|
|
9
|
+
const WORKSPACE_DIR = path.join(BASE_DIR, 'workspace');
|
|
10
|
+
|
|
11
|
+
function rlQuestion(query) {
|
|
12
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
13
|
+
return new Promise(resolve => {
|
|
14
|
+
rl.question(query, answer => { rl.close(); resolve(answer.trim().toLowerCase()); });
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function reset(params) {
|
|
19
|
+
try {
|
|
20
|
+
const [action] = params || [];
|
|
21
|
+
|
|
22
|
+
if (!action || action === 'list') return cmdList();
|
|
23
|
+
if (action === 'config') return await cmdConfig();
|
|
24
|
+
if (action === 'workspace') return await cmdWorkspace();
|
|
25
|
+
if (action === 'all') return await cmdAll();
|
|
26
|
+
|
|
27
|
+
console.log(chalk.red(`\n Unknown reset action: ${action}\n`));
|
|
28
|
+
console.log(chalk.gray(' Usage: natureco reset [config|workspace|all|list]\n'));
|
|
29
|
+
} catch (err) {
|
|
30
|
+
console.log(chalk.red(`\n Reset error: ${err.message}\n`));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function cmdList() {
|
|
35
|
+
console.log(chalk.cyan('\n Reset — What Would Be Removed\n'));
|
|
36
|
+
|
|
37
|
+
if (fs.existsSync(CONFIG_FILE)) console.log(chalk.gray(' • ') + chalk.white('Config file') + chalk.gray(' (' + CONFIG_FILE + ')'));
|
|
38
|
+
else console.log(chalk.gray(' • Config file — ') + chalk.gray('not found'));
|
|
39
|
+
|
|
40
|
+
if (fs.existsSync(WORKSPACE_DIR)) console.log(chalk.gray(' • ') + chalk.white('Workspace directory') + chalk.gray(' (' + WORKSPACE_DIR + ')'));
|
|
41
|
+
else console.log(chalk.gray(' • Workspace directory — ') + chalk.gray('not found'));
|
|
42
|
+
|
|
43
|
+
if (fs.existsSync(BASE_DIR)) {
|
|
44
|
+
const entries = fs.readdirSync(BASE_DIR);
|
|
45
|
+
console.log(chalk.gray(' • ') + chalk.white('~/.natureco/') + chalk.gray(' (' + entries.length + ' entries)'));
|
|
46
|
+
} else {
|
|
47
|
+
console.log(chalk.gray(' • ~/.natureco/ — ') + chalk.gray('not found'));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
console.log('');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function cmdConfig() {
|
|
54
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
55
|
+
console.log(chalk.yellow('\n No config file to remove.\n'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const answer = await rlQuestion(chalk.yellow(' Remove config file? [y/N]: '));
|
|
60
|
+
if (answer !== 'y' && answer !== 'yes') {
|
|
61
|
+
console.log(chalk.gray('\n Cancelled.\n'));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
66
|
+
console.log(chalk.green('\n Config file removed.\n'));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function cmdWorkspace() {
|
|
70
|
+
if (!fs.existsSync(WORKSPACE_DIR)) {
|
|
71
|
+
console.log(chalk.yellow('\n No workspace directory to remove.\n'));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const answer = await rlQuestion(chalk.yellow(' Remove workspace directory? [y/N]: '));
|
|
76
|
+
if (answer !== 'y' && answer !== 'yes') {
|
|
77
|
+
console.log(chalk.gray('\n Cancelled.\n'));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fs.rmSync(WORKSPACE_DIR, { recursive: true, force: true });
|
|
82
|
+
console.log(chalk.green('\n Workspace directory removed.\n'));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function cmdAll() {
|
|
86
|
+
if (!fs.existsSync(BASE_DIR)) {
|
|
87
|
+
console.log(chalk.yellow('\n Nothing to remove — ~/.natureco does not exist.\n'));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const answer = await rlQuestion(chalk.red(' Remove ALL NatureCo state (~/.natureco)? [y/N]: '));
|
|
92
|
+
if (answer !== 'y' && answer !== 'yes') {
|
|
93
|
+
console.log(chalk.gray('\n Cancelled.\n'));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fs.rmSync(BASE_DIR, { recursive: true, force: true });
|
|
98
|
+
console.log(chalk.green('\n All NatureCo state removed.\n'));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = reset;
|
|
@@ -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,201 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const F = require('../utils/format');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
|
|
5
|
+
function secrets(args) {
|
|
6
|
+
const [action, ...params] = args || [];
|
|
7
|
+
|
|
8
|
+
if (!action || action === 'list') return listSecrets();
|
|
9
|
+
if (action === 'set') return setSecret(params[0], params.slice(1).join(' '));
|
|
10
|
+
if (action === 'get') return getSecret(params[0]);
|
|
11
|
+
if (action === 'unset') return unsetSecret(params[0]);
|
|
12
|
+
if (action === 'audit') return auditSecrets();
|
|
13
|
+
if (action === 'reload') return reloadSecrets();
|
|
14
|
+
if (action === 'configure') return configureProvider(params[0]);
|
|
15
|
+
if (action === 'apply') return applySecrets();
|
|
16
|
+
|
|
17
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
18
|
+
console.log(chalk.gray(' Kullanım: natureco secrets [list|set|get|unset|audit|reload|configure|apply]\n'));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function listSecrets() {
|
|
23
|
+
const config = getConfig();
|
|
24
|
+
const secretKeys = Object.keys(config).filter(k =>
|
|
25
|
+
k.toLowerCase().includes('key') || k.toLowerCase().includes('token') || k.toLowerCase().includes('secret')
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
F.header('Secrets');
|
|
29
|
+
|
|
30
|
+
if (secretKeys.length === 0) {
|
|
31
|
+
F.info('No secrets stored.');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const rows = secretKeys.sort().map(key => {
|
|
36
|
+
const val = config[key];
|
|
37
|
+
const masked = val ? val.substring(0, 6) + '…' + val.slice(-4) : '(empty)';
|
|
38
|
+
return [key, masked, '-'];
|
|
39
|
+
});
|
|
40
|
+
F.table(['Name', 'Masked', 'Updated'], rows);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function setSecret(key, value) {
|
|
44
|
+
if (!key || !value) {
|
|
45
|
+
console.log(chalk.red('\n ❌ key ve value gerekli\n'));
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const config = getConfig();
|
|
50
|
+
config[key] = value;
|
|
51
|
+
saveConfig(config);
|
|
52
|
+
F.success(`Secret set: ${key}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function getSecret(key) {
|
|
56
|
+
if (!key) {
|
|
57
|
+
console.log(chalk.red('\n ❌ key gerekli\n'));
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const config = getConfig();
|
|
62
|
+
const value = config[key];
|
|
63
|
+
|
|
64
|
+
if (!value) {
|
|
65
|
+
F.warning(`Secret not found: ${key}`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
F.kv(key, value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function unsetSecret(key) {
|
|
73
|
+
if (!key) {
|
|
74
|
+
console.log(chalk.red('\n ❌ key gerekli\n'));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const config = getConfig();
|
|
79
|
+
delete config[key];
|
|
80
|
+
saveConfig(config);
|
|
81
|
+
F.success(`Secret removed: ${key}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function auditSecrets() {
|
|
85
|
+
const config = getConfig();
|
|
86
|
+
const secrets = Object.keys(config).filter(k =>
|
|
87
|
+
k.toLowerCase().includes('key') || k.toLowerCase().includes('token') || k.toLowerCase().includes('secret')
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const envKeys = ['OPENAI_API_KEY', 'ANTHROPIC_API_KEY', 'GROQ_API_KEY', 'TAVILY_API_KEY',
|
|
91
|
+
'ELEVENLABS_API_KEY', 'DEEPGRAM_API_KEY', 'FAL_KEY', 'TOGETHER_API_KEY',
|
|
92
|
+
'PUSHOVER_TOKEN', 'PUSHOVER_USER', 'NTFY_TOPIC', 'NTFY_SERVER',
|
|
93
|
+
'TWILIO_SID', 'TWILIO_TOKEN', 'TWILIO_FROM', 'SUNO_API_KEY', 'UDIO_API_KEY',
|
|
94
|
+
'VYDRA_API_KEY', 'SLACK_BOT_TOKEN', 'DISCORD_BOT_TOKEN', 'TELEGRAM_BOT_TOKEN',
|
|
95
|
+
'WHATSAPP_API_KEY'
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
F.header('Secrets Audit');
|
|
99
|
+
|
|
100
|
+
const rows = [];
|
|
101
|
+
for (const key of secrets.sort()) {
|
|
102
|
+
const val = config[key];
|
|
103
|
+
rows.push([key, 'config', val ? 'set' : 'empty']);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let found = 0;
|
|
107
|
+
for (const envKey of envKeys) {
|
|
108
|
+
if (process.env[envKey]) {
|
|
109
|
+
rows.push([envKey, 'env', 'set']);
|
|
110
|
+
found++;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
F.table(['Key', 'Type', 'Status'], rows);
|
|
115
|
+
|
|
116
|
+
if (found === 0) F.info('(none set in environment)');
|
|
117
|
+
|
|
118
|
+
F.meta(`Total: ${secrets.length} config + ${found} env`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function reloadSecrets() {
|
|
122
|
+
const config = getConfig();
|
|
123
|
+
const envMappings = {
|
|
124
|
+
OPENAI_API_KEY: 'openaiApiKey',
|
|
125
|
+
ANTHROPIC_API_KEY: 'anthropicApiKey',
|
|
126
|
+
GROQ_API_KEY: 'groqApiKey',
|
|
127
|
+
TAVILY_API_KEY: 'tavilyApiKey',
|
|
128
|
+
ELEVENLABS_API_KEY: 'elevenlabsApiKey',
|
|
129
|
+
DEEPGRAM_API_KEY: 'deepgramApiKey',
|
|
130
|
+
FAL_KEY: 'falKey',
|
|
131
|
+
TOGETHER_API_KEY: 'togetherApiKey',
|
|
132
|
+
TELEGRAM_BOT_TOKEN: 'telegramToken',
|
|
133
|
+
DISCORD_BOT_TOKEN: 'discordToken',
|
|
134
|
+
SLACK_BOT_TOKEN: 'slackToken',
|
|
135
|
+
};
|
|
136
|
+
let count = 0;
|
|
137
|
+
for (const [envVar, configKey] of Object.entries(envMappings)) {
|
|
138
|
+
if (process.env[envVar] && !config[configKey]) {
|
|
139
|
+
config[configKey] = process.env[envVar];
|
|
140
|
+
count++;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (count > 0) {
|
|
144
|
+
saveConfig(config);
|
|
145
|
+
F.success(`${count} secrets loaded from environment`);
|
|
146
|
+
} else {
|
|
147
|
+
F.warning('No new secrets found in environment');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function configureProvider(provider) {
|
|
152
|
+
if (!provider) {
|
|
153
|
+
console.log(chalk.red('\n ❌ Provider name required\n'));
|
|
154
|
+
console.log(chalk.gray(' Available: openai, anthropic, groq, together, deepseek, mistral, perplexity, elevenlabs, deepgram, fal\n'));
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const instructions = {
|
|
159
|
+
openai: { key: 'openaiApiKey', env: 'OPENAI_API_KEY', url: 'https://platform.openai.com/api-keys' },
|
|
160
|
+
anthropic: { key: 'anthropicApiKey', env: 'ANTHROPIC_API_KEY', url: 'https://console.anthropic.com/keys' },
|
|
161
|
+
groq: { key: 'groqApiKey', env: 'GROQ_API_KEY', url: 'https://console.groq.com/keys' },
|
|
162
|
+
together: { key: 'togetherApiKey', env: 'TOGETHER_API_KEY', url: 'https://together.ai/settings/api-keys' },
|
|
163
|
+
deepseek: { key: 'deepseekApiKey', env: 'DEEPSEEK_API_KEY', url: 'https://platform.deepseek.com/api-keys' },
|
|
164
|
+
mistral: { key: 'mistralApiKey', env: 'MISTRAL_API_KEY', url: 'https://console.mistral.ai/api-keys' },
|
|
165
|
+
perplexity: { key: 'perplexityApiKey', env: 'PERPLEXITY_API_KEY', url: 'https://www.perplexity.ai/settings/api' },
|
|
166
|
+
elevenlabs: { key: 'elevenlabsApiKey', env: 'ELEVENLABS_API_KEY', url: 'https://elevenlabs.io/app/settings/api-keys' },
|
|
167
|
+
deepgram: { key: 'deepgramApiKey', env: 'DEEPGRAM_API_KEY', url: 'https://console.deepgram.com/keys' },
|
|
168
|
+
fal: { key: 'falKey', env: 'FAL_KEY', url: 'https://fal.ai/dashboard/keys' },
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const info = instructions[provider.toLowerCase()];
|
|
172
|
+
|
|
173
|
+
if (!info) {
|
|
174
|
+
console.log(chalk.red(`\n ❌ Unknown provider: ${provider}\n`));
|
|
175
|
+
console.log(chalk.gray(' Available: openai, anthropic, groq, together, deepseek, mistral, perplexity, elevenlabs, deepgram, fal\n'));
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
F.section(`Configure ${provider}`);
|
|
180
|
+
|
|
181
|
+
F.list([
|
|
182
|
+
{ label: 'Config key', value: info.key },
|
|
183
|
+
{ label: 'Env var', value: info.env },
|
|
184
|
+
{ label: 'Get key', value: info.url },
|
|
185
|
+
]);
|
|
186
|
+
|
|
187
|
+
F.info(`Set it: natureco secrets set ${info.key} <your-key>`);
|
|
188
|
+
F.info(`Or set env: $env:${info.env}="your-key"`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function applySecrets() {
|
|
192
|
+
F.header('Apply Secrets');
|
|
193
|
+
F.info('Secrets are stored locally in config.json');
|
|
194
|
+
F.info('To make them available to running processes:');
|
|
195
|
+
F.list([
|
|
196
|
+
'Set environment variables and restart',
|
|
197
|
+
'Or use: natureco secrets reload',
|
|
198
|
+
]);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
module.exports = secrets;
|