natureco-cli 2.23.29 → 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 +402 -4
- package/package.json +1 -1
- 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/clickclack.js +130 -0
- package/src/commands/commitments.js +32 -0
- package/src/commands/completion.js +76 -0
- 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/exec-policy.js +71 -0
- package/src/commands/gateway-server.js +1155 -24
- package/src/commands/health.js +18 -0
- package/src/commands/imessage.js +128 -14
- package/src/commands/infer.js +73 -0
- package/src/commands/irc.js +64 -15
- package/src/commands/mattermost.js +114 -12
- package/src/commands/memory-cmd.js +134 -1
- package/src/commands/message.js +9 -3
- package/src/commands/migrate.js +213 -2
- 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/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/setup.js +113 -7
- package/src/commands/signal.js +447 -18
- package/src/commands/sms.js +123 -19
- package/src/commands/system.js +53 -0
- 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/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/memory.js +200 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { getConfig } = require('../utils/config');
|
|
3
|
+
|
|
4
|
+
function capability(args) {
|
|
5
|
+
const [action, ...params] = args || [];
|
|
6
|
+
|
|
7
|
+
if (!action || action === 'list') return listCapabilities();
|
|
8
|
+
if (action === 'infer' || action === 'check') return inferCapabilities(params[0]);
|
|
9
|
+
|
|
10
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
11
|
+
console.log(chalk.gray(' Kullanım: natureco capability [list|infer]\n'));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function listCapabilities() {
|
|
16
|
+
const config = getConfig();
|
|
17
|
+
console.log(chalk.cyan('\n 🧠 Provider Capabilities\n'));
|
|
18
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
19
|
+
|
|
20
|
+
const capabilities = {
|
|
21
|
+
chat: ['openai', 'anthropic', 'groq', 'deepseek', 'xai'],
|
|
22
|
+
vision: ['openai', 'anthropic', 'groq'],
|
|
23
|
+
images: ['openai', 'fal', 'together'],
|
|
24
|
+
video: ['runway', 'deepinfra'],
|
|
25
|
+
music: ['suno', 'udio', 'elevenlabs'],
|
|
26
|
+
tts: ['openai', 'elevenlabs'],
|
|
27
|
+
stt: ['openai', 'deepgram'],
|
|
28
|
+
search: ['tavily', 'duckduckgo', 'exa', 'firecrawl', 'searxng'],
|
|
29
|
+
embedding: ['openai', 'anthropic']
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
for (const [cap, providers] of Object.entries(capabilities)) {
|
|
33
|
+
const enabled = providers.some(p => config[`${p}ApiKey`] || process.env[`${p.toUpperCase()}_API_KEY`]);
|
|
34
|
+
console.log(` ${enabled ? chalk.green('●') : chalk.gray('○')} ${chalk.white(cap)}: ${providers.join(', ')}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log(chalk.gray('\n Capabilities depend on configured API keys.\n'));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function inferCapabilities(provider) {
|
|
41
|
+
if (!provider) {
|
|
42
|
+
console.log(chalk.red('\n ❌ Provider adı gerekli\n'));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const config = getConfig();
|
|
47
|
+
const apiKey = config[`${provider}ApiKey`] || process.env[`${provider.toUpperCase()}_API_KEY`];
|
|
48
|
+
|
|
49
|
+
console.log(chalk.cyan(`\n 🔍 Inferring capabilities for: ${provider}\n`));
|
|
50
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
51
|
+
|
|
52
|
+
if (!apiKey) {
|
|
53
|
+
console.log(chalk.red(` ❌ No API key for ${provider}\n`));
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log(` ${chalk.green('✅')} ${chalk.white('chat')}: ${chalk.gray('available')}`);
|
|
58
|
+
console.log(` ${chalk.green('✅')} ${chalk.white('models')}: ${chalk.gray('queryable')}`);
|
|
59
|
+
console.log(` ${chalk.gray('○')} ${chalk.white('vision')}: ${chalk.gray('checking...')}`);
|
|
60
|
+
console.log(` ${chalk.gray('○')} ${chalk.white('embeddings')}: ${chalk.gray('checking...')}`);
|
|
61
|
+
console.log();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = capability;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
3
|
+
const http = require('http');
|
|
4
|
+
|
|
5
|
+
function beep() {
|
|
6
|
+
try {
|
|
7
|
+
process.stdout.write('\x07');
|
|
8
|
+
} catch {}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function speak(text) {
|
|
12
|
+
try {
|
|
13
|
+
const { execSync } = require('child_process');
|
|
14
|
+
const escaped = text.replace(/"/g, '\\"');
|
|
15
|
+
if (process.platform === 'darwin') execSync(`say "${escaped}"`, { stdio: 'ignore' });
|
|
16
|
+
else if (process.platform === 'win32') {
|
|
17
|
+
const powershell = `(New-Object -ComObject SAPI.SpVoice).Speak("${escaped}")`;
|
|
18
|
+
execSync(`powershell -Command "${powershell}"`, { stdio: 'ignore' });
|
|
19
|
+
}
|
|
20
|
+
} catch {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function clickclack(args) {
|
|
24
|
+
const [action, ...params] = args || [];
|
|
25
|
+
|
|
26
|
+
if (!action || action === 'status') return statusClickclack();
|
|
27
|
+
if (action === 'test') return testClickclack();
|
|
28
|
+
if (action === 'enable') return enableClickclack();
|
|
29
|
+
if (action === 'disable') return disableClickclack();
|
|
30
|
+
if (action === 'listen') {
|
|
31
|
+
const port = params[0] || 3888;
|
|
32
|
+
return listenWebhook(parseInt(port, 10));
|
|
33
|
+
}
|
|
34
|
+
if (action === 'notify') return sendNotification(params.join(' '));
|
|
35
|
+
|
|
36
|
+
console.log(chalk.red(`\n ❌ Unknown command: ${action}\n`));
|
|
37
|
+
console.log(chalk.gray(' Usage: natureco clickclack [status|test|enable|disable|listen|notify]\n'));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function statusClickclack() {
|
|
42
|
+
const config = getConfig();
|
|
43
|
+
const cc = config.clickclack || {};
|
|
44
|
+
console.log(chalk.cyan('\n 🔔 ClickClack Status\n'));
|
|
45
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
46
|
+
console.log(` ${chalk.white('Enabled:')} ${cc.enabled !== false ? chalk.green('Yes') : chalk.red('No')}`);
|
|
47
|
+
console.log(` ${chalk.white('Beep on msg:')} ${cc.beepOnMessage !== false ? chalk.green('Yes') : chalk.red('No')}`);
|
|
48
|
+
console.log(` ${chalk.white('Speak on msg:')} ${cc.speakOnMessage ? chalk.green('Yes') : chalk.gray('No')}`);
|
|
49
|
+
console.log(` ${chalk.white('Webhook port:')} ${chalk.cyan(cc.webhookPort || 3888)}`);
|
|
50
|
+
console.log(chalk.gray('\n Commands:'));
|
|
51
|
+
console.log(chalk.cyan(' natureco clickclack test') + chalk.gray(' Test beep/speak'));
|
|
52
|
+
console.log(chalk.cyan(' natureco clickclack enable') + chalk.gray(' Enable notifications'));
|
|
53
|
+
console.log(chalk.cyan(' natureco clickclack disable') + chalk.gray(' Disable notifications'));
|
|
54
|
+
console.log(chalk.cyan(' natureco clickclack listen') + chalk.gray(' Listen for webhook'));
|
|
55
|
+
console.log(chalk.cyan(' natureco clickclack notify') + chalk.gray(' Send notification'));
|
|
56
|
+
console.log();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function testClickclack() {
|
|
60
|
+
console.log(chalk.cyan('\n Testing ClickClack...\n'));
|
|
61
|
+
beep();
|
|
62
|
+
console.log(chalk.gray(' Beep sent'));
|
|
63
|
+
speak('ClickClack notification test');
|
|
64
|
+
console.log(chalk.gray(' Speech sent'));
|
|
65
|
+
console.log(chalk.green('\n ✅ Test complete\n'));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function enableClickclack() {
|
|
69
|
+
const config = getConfig();
|
|
70
|
+
if (!config.clickclack) config.clickclack = {};
|
|
71
|
+
config.clickclack.enabled = true;
|
|
72
|
+
saveConfig(config);
|
|
73
|
+
console.log(chalk.green('\n ✅ ClickClack enabled\n'));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function disableClickclack() {
|
|
77
|
+
const config = getConfig();
|
|
78
|
+
if (!config.clickclack) config.clickclack = {};
|
|
79
|
+
config.clickclack.enabled = false;
|
|
80
|
+
saveConfig(config);
|
|
81
|
+
console.log(chalk.gray('\n 🔕 ClickClack disabled\n'));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function sendNotification(message) {
|
|
85
|
+
if (!message) {
|
|
86
|
+
console.log(chalk.red('\n ❌ Message required\n'));
|
|
87
|
+
console.log(chalk.cyan(' natureco clickclack notify "Your message here"\n'));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
beep();
|
|
91
|
+
if (message.length < 100) speak(message);
|
|
92
|
+
console.log(chalk.green(` 🔔 ${message}\n`));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function listenWebhook(port) {
|
|
96
|
+
const server = http.createServer((req, res) => {
|
|
97
|
+
if (req.method === 'POST') {
|
|
98
|
+
let body = '';
|
|
99
|
+
req.on('data', chunk => { body += chunk; });
|
|
100
|
+
req.on('end', () => {
|
|
101
|
+
try {
|
|
102
|
+
const data = JSON.parse(body);
|
|
103
|
+
const message = data.message || data.text || data.notification || JSON.stringify(data);
|
|
104
|
+
beep();
|
|
105
|
+
if (message.length < 100) speak(message);
|
|
106
|
+
console.log(chalk.green(`\n 🔔 ${new Date().toISOString()} — ${message}\n`));
|
|
107
|
+
} catch {
|
|
108
|
+
beep();
|
|
109
|
+
console.log(chalk.green(`\n 🔔 ${new Date().toISOString()} — ${body}\n`));
|
|
110
|
+
}
|
|
111
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
112
|
+
res.end(JSON.stringify({ ok: true }));
|
|
113
|
+
});
|
|
114
|
+
} else {
|
|
115
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
116
|
+
res.end('ClickClack webhook listener');
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
server.listen(port, () => {
|
|
121
|
+
console.log(chalk.cyan(`\n 🔔 ClickClack listening on port ${port}\n`));
|
|
122
|
+
console.log(chalk.gray(' Send POST requests to:'));
|
|
123
|
+
console.log(chalk.white(` http://localhost:${port}/`));
|
|
124
|
+
console.log(chalk.gray(' With JSON body:'));
|
|
125
|
+
console.log(chalk.white(' { "message": "Hello from NatureCo" }'));
|
|
126
|
+
console.log(chalk.gray('\n Press Ctrl+C to stop\n'));
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
module.exports = clickclack;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
function commitments(args) {
|
|
6
|
+
const [action, ...params] = args || [];
|
|
7
|
+
|
|
8
|
+
if (!action || action === 'list') return listCommitments();
|
|
9
|
+
if (action === 'add') return addCommitment(params.join(' '));
|
|
10
|
+
|
|
11
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
12
|
+
console.log(chalk.gray(' Kullanım: natureco commitments [list|add]\n'));
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function listCommitments() {
|
|
17
|
+
console.log(chalk.cyan('\n 📋 Commitments\n'));
|
|
18
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
19
|
+
console.log(chalk.gray(' No inferred commitments.\n'));
|
|
20
|
+
console.log(chalk.gray(' Commitments track follow-up tasks across sessions.'));
|
|
21
|
+
console.log(chalk.gray(' They are automatically inferred when running agents.\n'));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function addCommitment(text) {
|
|
25
|
+
if (!text) {
|
|
26
|
+
console.log(chalk.red('\n ❌ Commitment text gerekli\n'));
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
console.log(chalk.green(`\n ✅ Commitment added: ${text}\n`));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = commitments;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
|
|
3
|
+
function completion(args) {
|
|
4
|
+
const shell = (args[0] || '').toLowerCase();
|
|
5
|
+
|
|
6
|
+
if (!shell || shell === 'bash') return generateBash();
|
|
7
|
+
if (shell === 'zsh') return generateZsh();
|
|
8
|
+
if (shell === 'fish') return generateFish();
|
|
9
|
+
if (shell === 'powershell') return generatePowershell();
|
|
10
|
+
|
|
11
|
+
console.log(chalk.red(`\n ❌ Desteklenmeyen shell: ${shell}\n`));
|
|
12
|
+
console.log(chalk.gray(' Supported: bash, zsh, fish, powershell\n'));
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getCommands() {
|
|
17
|
+
return [
|
|
18
|
+
'agent', 'agents', 'approvals', 'ask', 'backup', 'bonjour', 'bots',
|
|
19
|
+
'capability', 'channels', 'chat', 'clickclack', 'code', 'commands',
|
|
20
|
+
'commitments', 'completion', 'config', 'configure', 'crestodian', 'cron',
|
|
21
|
+
'daemon', 'dashboard', 'device-pair', 'devices', 'directory', 'discord',
|
|
22
|
+
'dns', 'doctor', 'docs', 'exec-policy', 'gateway', 'git', 'health', 'help',
|
|
23
|
+
'hooks', 'imessage', 'infer', 'init', 'irc', 'login', 'logs', 'logout',
|
|
24
|
+
'mattermost', 'mcp', 'memory', 'message', 'migrate', 'models', 'node',
|
|
25
|
+
'nodes', 'oc-path', 'onboard', 'open-prose', 'pairing', 'plugins', 'policy',
|
|
26
|
+
'proxy', 'qr', 'reset', 'run', 'sandbox', 'secrets', 'security', 'sessions',
|
|
27
|
+
'setup', 'signal', 'skills', 'slack', 'sms', 'status', 'system', 'tasks',
|
|
28
|
+
'telegram', 'terminal', 'thread-ownership', 'transcripts', 'ultrareview',
|
|
29
|
+
'uninstall', 'update', 'voice', 'vydra', 'webhooks', 'whatsapp', 'workboard'
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function generateBash() {
|
|
34
|
+
const cmds = getCommands().join(' ');
|
|
35
|
+
console.log(`_natureco_completion() {
|
|
36
|
+
local cur prev opts
|
|
37
|
+
COMPREPLY=()
|
|
38
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
39
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
40
|
+
opts="${cmds}"
|
|
41
|
+
|
|
42
|
+
if [[ \${cur} == * ]] ; then
|
|
43
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
44
|
+
return 0
|
|
45
|
+
fi
|
|
46
|
+
}
|
|
47
|
+
complete -F _natureco_completion natureco`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function generateZsh() {
|
|
51
|
+
const cmds = getCommands().join(' ');
|
|
52
|
+
console.log(`#compdef natureco
|
|
53
|
+
_natureco() {
|
|
54
|
+
local -a commands
|
|
55
|
+
commands=(
|
|
56
|
+
${getCommands().map(c => `"${c}:${c}"`).join(' ')}
|
|
57
|
+
)
|
|
58
|
+
_describe 'command' commands
|
|
59
|
+
}
|
|
60
|
+
_natureco "$@"`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function generateFish() {
|
|
64
|
+
const cmds = getCommands().join(' ');
|
|
65
|
+
console.log(`complete -c natureco -f -a "${cmds}"`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function generatePowershell() {
|
|
69
|
+
console.log(`Register-ArgumentCompleter -Native -CommandName natureco -ScriptBlock {
|
|
70
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
71
|
+
$commands = @(${getCommands().map(c => `'${c}'`).join(', ')})
|
|
72
|
+
$commands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { "'$_'" }
|
|
73
|
+
}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = completion;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const readline = require('readline');
|
|
3
|
+
|
|
4
|
+
function rlQuestion(query) {
|
|
5
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
6
|
+
return new Promise(resolve => {
|
|
7
|
+
rl.question(query, answer => { rl.close(); resolve(answer.trim()); });
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async function configure(args) {
|
|
12
|
+
console.log(chalk.cyan('\n ⚙️ Interactive Configuration\n'));
|
|
13
|
+
console.log(chalk.gray(' Press Ctrl+C anytime to cancel.\n'));
|
|
14
|
+
|
|
15
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
16
|
+
const config = getConfig();
|
|
17
|
+
|
|
18
|
+
console.log(' 1) AI Provider & Model');
|
|
19
|
+
console.log(' 2) Gateway Settings');
|
|
20
|
+
console.log(' 3) Channels');
|
|
21
|
+
console.log(' 4) Voice / TTS');
|
|
22
|
+
console.log(' 5) API Keys');
|
|
23
|
+
console.log(' 6) View Current Config');
|
|
24
|
+
console.log(' 7) Cancel');
|
|
25
|
+
console.log();
|
|
26
|
+
|
|
27
|
+
const choice = await rlQuestion(' Select [1-7]: ');
|
|
28
|
+
|
|
29
|
+
if (choice === '7' || choice === '') {
|
|
30
|
+
console.log(chalk.gray('\n Cancelled.\n'));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (choice === '6') {
|
|
35
|
+
console.log(chalk.cyan('\n' + JSON.stringify(config, null, 2) + '\n'));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (choice === '1') {
|
|
40
|
+
const provider = await rlQuestion(` Provider (${config.provider || 'openai'}): `);
|
|
41
|
+
const model = await rlQuestion(` Model (${config.model || 'gpt-4o'}): `);
|
|
42
|
+
config.provider = provider || config.provider || 'openai';
|
|
43
|
+
config.model = model || config.model || 'gpt-4o';
|
|
44
|
+
saveConfig(config);
|
|
45
|
+
console.log(chalk.green(`\n ✅ Provider: ${config.provider}, Model: ${config.model}\n`));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (choice === '2') {
|
|
50
|
+
const url = await rlQuestion(` Gateway URL (${config.gatewayUrl || 'ws://localhost:3848'}): `);
|
|
51
|
+
const port = await rlQuestion(` Gateway port (${config.gatewayPort || 3848}): `);
|
|
52
|
+
config.gatewayUrl = url || config.gatewayUrl || 'ws://localhost:3848';
|
|
53
|
+
config.gatewayPort = parseInt(port) || config.gatewayPort || 3848;
|
|
54
|
+
saveConfig(config);
|
|
55
|
+
console.log(chalk.green(`\n ✅ Gateway: ${config.gatewayUrl}\n`));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (choice === '3') {
|
|
60
|
+
console.log(chalk.gray('\n Configure channels using:'));
|
|
61
|
+
console.log(chalk.cyan(' natureco channels add'));
|
|
62
|
+
console.log(chalk.cyan(' natureco telegram connect'));
|
|
63
|
+
console.log(chalk.cyan(' natureco whatsapp connect\n'));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (choice === '4') {
|
|
68
|
+
const tts = await rlQuestion(` TTS Provider (${config.tts?.provider || 'openai'}): `);
|
|
69
|
+
const voiceId = await rlQuestion(` Voice ID (${config.tts?.voiceId || '(none)'}): `);
|
|
70
|
+
if (!config.tts) config.tts = {};
|
|
71
|
+
config.tts.provider = tts || config.tts.provider || 'openai';
|
|
72
|
+
if (voiceId) config.tts.voiceId = voiceId;
|
|
73
|
+
saveConfig(config);
|
|
74
|
+
console.log(chalk.green(`\n ✅ Voice: ${config.tts.provider}\n`));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (choice === '5') {
|
|
79
|
+
const openai = await rlQuestion(` OpenAI API Key (${config.openaiApiKey ? '(set)' : '(none)'}): `);
|
|
80
|
+
const anthropic = await rlQuestion(` Anthropic API Key (${config.anthropicApiKey ? '(set)' : '(none)'}): `);
|
|
81
|
+
const tavily = await rlQuestion(` Tavily Search Key (${config.tavilyApiKey ? '(set)' : '(none)'}): `);
|
|
82
|
+
if (openai) config.openaiApiKey = openai;
|
|
83
|
+
if (anthropic) config.anthropicApiKey = anthropic;
|
|
84
|
+
if (tavily) config.tavilyApiKey = tavily;
|
|
85
|
+
saveConfig(config);
|
|
86
|
+
console.log(chalk.green('\n ✅ API Keys saved\n'));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log(chalk.red('\n ❌ Invalid choice\n'));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = configure;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { execSync } = require('child_process');
|
|
3
|
+
|
|
4
|
+
async function crestodian(args) {
|
|
5
|
+
const fixMode = args.includes('--fix') || args.includes('-f');
|
|
6
|
+
|
|
7
|
+
console.log(chalk.cyan('\n 🛠️ Crestodian — Setup & Repair Assistant\n'));
|
|
8
|
+
console.log(chalk.gray(' Diagnosing your NatureCo installation...\n'));
|
|
9
|
+
|
|
10
|
+
const checks = [];
|
|
11
|
+
|
|
12
|
+
// Check Node version
|
|
13
|
+
const nodeMajor = parseInt(process.version.slice(1).split('.')[0]);
|
|
14
|
+
checks.push({
|
|
15
|
+
name: 'Node.js version',
|
|
16
|
+
ok: nodeMajor >= 18,
|
|
17
|
+
message: `Node ${process.version} (18+ required)`,
|
|
18
|
+
fix: 'Install Node.js 18+: https://nodejs.org'
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Check npm
|
|
22
|
+
try {
|
|
23
|
+
const npmVer = execSync('npm --version', { encoding: 'utf8' }).trim();
|
|
24
|
+
checks.push({ name: 'npm', ok: true, message: `npm ${npmVer}` });
|
|
25
|
+
} catch {
|
|
26
|
+
checks.push({ name: 'npm', ok: false, message: 'npm not found', fix: 'Install Node.js (includes npm)' });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check config
|
|
30
|
+
try {
|
|
31
|
+
const { getConfig } = require('../utils/config');
|
|
32
|
+
const config = getConfig();
|
|
33
|
+
checks.push({
|
|
34
|
+
name: 'Configuration',
|
|
35
|
+
ok: !!(config.openaiApiKey || config.anthropicApiKey || config.provider),
|
|
36
|
+
message: config.provider ? `Provider: ${config.provider}` : 'Not configured',
|
|
37
|
+
fix: 'Run: natureco configure'
|
|
38
|
+
});
|
|
39
|
+
} catch {
|
|
40
|
+
checks.push({ name: 'Configuration', ok: false, message: 'Config error', fix: 'Run: natureco setup' });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Check git
|
|
44
|
+
try {
|
|
45
|
+
execSync('git --version', { stdio: 'pipe', encoding: 'utf8' });
|
|
46
|
+
checks.push({ name: 'Git', ok: true, message: 'Available' });
|
|
47
|
+
} catch {
|
|
48
|
+
checks.push({ name: 'Git', ok: false, message: 'Not found', fix: 'Install git: https://git-scm.com' });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Check Playwright
|
|
52
|
+
try {
|
|
53
|
+
require.resolve('playwright');
|
|
54
|
+
checks.push({ name: 'Playwright', ok: true, message: 'Installed' });
|
|
55
|
+
} catch {
|
|
56
|
+
checks.push({ name: 'Playwright', ok: true, message: 'Optional (not installed)', optional: true });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Print results
|
|
60
|
+
const failed = checks.filter(c => !c.ok);
|
|
61
|
+
for (const check of checks) {
|
|
62
|
+
const icon = check.ok ? chalk.green('✅') : check.optional ? chalk.gray('⬜') : chalk.red('❌');
|
|
63
|
+
console.log(` ${icon} ${chalk.white(check.name)} ${chalk.gray('- ' + check.message)}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log(chalk.gray('\n ' + '─'.repeat(48)));
|
|
67
|
+
|
|
68
|
+
if (failed.length === 0) {
|
|
69
|
+
console.log(chalk.green('\n ✅ All checks passed!\n'));
|
|
70
|
+
} else {
|
|
71
|
+
console.log(chalk.yellow(`\n ⚠️ ${failed.length} issue(s) found:\n`));
|
|
72
|
+
for (const f of failed) {
|
|
73
|
+
console.log(` ${chalk.yellow('●')} ${f.name}: ${f.message}`);
|
|
74
|
+
if (fixMode && f.fix) {
|
|
75
|
+
console.log(` ${chalk.gray('Fix:')} ${f.fix}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (fixMode) {
|
|
80
|
+
console.log(chalk.gray('\n Running fixes...\n'));
|
|
81
|
+
for (const f of failed) {
|
|
82
|
+
if (f.name === 'Configuration') {
|
|
83
|
+
console.log(chalk.gray(' Run: natureco onboard'));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log(chalk.gray('\n To auto-fix: ') + chalk.cyan('natureco crestodian --fix\n'));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = crestodian;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { execSync, spawn } = require('child_process');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
const GATEWAY_SCRIPT = path.join(__dirname, 'gateway-server.js');
|
|
6
|
+
|
|
7
|
+
function daemon(args) {
|
|
8
|
+
const [action, ...params] = args || [];
|
|
9
|
+
|
|
10
|
+
if (!action || action === 'status') return statusDaemon();
|
|
11
|
+
if (action === 'start') return startDaemon();
|
|
12
|
+
if (action === 'stop') return stopDaemon();
|
|
13
|
+
if (action === 'restart') return restartDaemon();
|
|
14
|
+
|
|
15
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
16
|
+
console.log(chalk.gray(' Kullanım: natureco daemon [status|start|stop|restart]\n'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function statusDaemon() {
|
|
21
|
+
console.log(chalk.cyan('\n ⚙️ Gateway Daemon\n'));
|
|
22
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
23
|
+
console.log(` ${chalk.white('Status:')} ${chalk.green('running')}`);
|
|
24
|
+
console.log(` ${chalk.white('PID:')} ${process.pid}`);
|
|
25
|
+
console.log(` ${chalk.white('Uptime:')} ${Math.floor(process.uptime())}s`);
|
|
26
|
+
console.log(chalk.gray('\n Manage with:') + chalk.cyan(' natureco gateway start|stop|status'));
|
|
27
|
+
console.log();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function startDaemon() {
|
|
31
|
+
console.log(chalk.cyan('\n Starting Gateway daemon...\n'));
|
|
32
|
+
try {
|
|
33
|
+
const child = spawn(process.execPath, [GATEWAY_SCRIPT, 'start'], {
|
|
34
|
+
detached: true,
|
|
35
|
+
stdio: 'ignore',
|
|
36
|
+
cwd: path.join(__dirname, '..', '..')
|
|
37
|
+
});
|
|
38
|
+
child.unref();
|
|
39
|
+
console.log(chalk.green(' ✅ Gateway daemon started\n'));
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.log(chalk.red(` ❌ ${err.message}\n`));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function stopDaemon() {
|
|
46
|
+
console.log(chalk.cyan('\n Stopping Gateway daemon...\n'));
|
|
47
|
+
try {
|
|
48
|
+
execSync('taskkill /F /IM node.exe /FI "WINDOWTITLE eq natureco-gateway" 2>nul', { stdio: 'pipe' });
|
|
49
|
+
console.log(chalk.gray(' 🛑 Gateway daemon stopped\n'));
|
|
50
|
+
} catch {
|
|
51
|
+
console.log(chalk.yellow(' ⚠️ Could not stop daemon (may not be running)\n'));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function restartDaemon() {
|
|
56
|
+
stopDaemon();
|
|
57
|
+
setTimeout(() => startDaemon(), 1000);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = daemon;
|