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
package/src/commands/gateway.js
CHANGED
|
@@ -6,23 +6,11 @@ const packageJson = require('../../package.json');
|
|
|
6
6
|
const { getConfig, CONFIG_FILE } = require('../utils/config');
|
|
7
7
|
const { getSkills } = require('../utils/skills');
|
|
8
8
|
const { getMcpServers } = require('../utils/mcp');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
let makeWASocket, useMultiFileAuthState, fetchLatestBaileysVersion, Browsers;
|
|
9
|
+
const { loadBaileys } = require('../utils/baileys');
|
|
10
|
+
const { NatureCoError, GatewayError, handleError } = require('../utils/errors');
|
|
12
11
|
const pino = require('pino');
|
|
13
12
|
const logger = pino({ level: 'silent' });
|
|
14
13
|
|
|
15
|
-
// Lazy load Baileys
|
|
16
|
-
function loadBaileys() {
|
|
17
|
-
if (!makeWASocket) {
|
|
18
|
-
const baileys = require('@whiskeysockets/baileys');
|
|
19
|
-
makeWASocket = baileys.default;
|
|
20
|
-
useMultiFileAuthState = baileys.useMultiFileAuthState;
|
|
21
|
-
fetchLatestBaileysVersion = baileys.fetchLatestBaileysVersion;
|
|
22
|
-
Browsers = baileys.Browsers;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
14
|
async function gateway(action) {
|
|
27
15
|
if (action === 'start') {
|
|
28
16
|
return startGateway();
|
|
@@ -139,7 +127,7 @@ async function startGateway() {
|
|
|
139
127
|
|
|
140
128
|
async function startWhatsAppProvider(sessionDir, config) {
|
|
141
129
|
try {
|
|
142
|
-
loadBaileys();
|
|
130
|
+
const { makeWASocket, useMultiFileAuthState, fetchLatestBaileysVersion, Browsers } = loadBaileys();
|
|
143
131
|
|
|
144
132
|
const { state, saveCreds } = await useMultiFileAuthState(sessionDir);
|
|
145
133
|
const { version } = await fetchLatestBaileysVersion();
|
|
@@ -224,8 +212,9 @@ async function startWhatsAppProvider(sessionDir, config) {
|
|
|
224
212
|
await sock.sendMessage(msg.key.remoteJid, { text: reply.slice(0, 4000) });
|
|
225
213
|
console.log(chalk.cyan('[whatsapp]'), chalk.green(`!code tamamlandı (${result.iterations} iterasyon)`));
|
|
226
214
|
} catch (err) {
|
|
227
|
-
|
|
228
|
-
|
|
215
|
+
const msg = err instanceof NatureCoError ? err.message : err?.message ?? 'Unknown error';
|
|
216
|
+
console.log(chalk.red('[whatsapp/code]'), chalk.gray(`hata: ${msg}`));
|
|
217
|
+
await sock.sendMessage(msg.key.remoteJid, { text: `❌ Hata: ${msg}` });
|
|
229
218
|
}
|
|
230
219
|
continue;
|
|
231
220
|
}
|
|
@@ -235,14 +224,15 @@ async function startWhatsAppProvider(sessionDir, config) {
|
|
|
235
224
|
console.log(chalk.cyan('[whatsapp]'), chalk.gray('Sending reply...'));
|
|
236
225
|
|
|
237
226
|
const response = await sendMessage(config.apiKey, config.whatsappBotId, messageText, null, '');
|
|
238
|
-
const reply = response?.reply
|
|
227
|
+
const reply = response?.reply ?? response?.message ?? '';
|
|
239
228
|
|
|
240
229
|
if (reply) {
|
|
241
230
|
await sock.sendMessage(msg.key.remoteJid, { text: reply });
|
|
242
231
|
console.log(chalk.cyan('[whatsapp]'), chalk.green(`Reply sent (${reply.length} chars)`));
|
|
243
232
|
}
|
|
244
233
|
} catch (err) {
|
|
245
|
-
|
|
234
|
+
const msg = err instanceof NatureCoError ? err.message : err?.message ?? 'Unknown error';
|
|
235
|
+
console.log(chalk.red('[whatsapp]'), chalk.gray(`error: ${msg}`));
|
|
246
236
|
}
|
|
247
237
|
}
|
|
248
238
|
}
|
|
@@ -251,7 +241,8 @@ async function startWhatsAppProvider(sessionDir, config) {
|
|
|
251
241
|
sock.ev.on('creds.update', saveCreds);
|
|
252
242
|
|
|
253
243
|
} catch (err) {
|
|
254
|
-
|
|
244
|
+
const msg = err instanceof NatureCoError ? err.message : err?.message ?? 'Unknown error';
|
|
245
|
+
console.log(chalk.red('[whatsapp]'), chalk.gray(`failed to start: ${msg}`));
|
|
255
246
|
}
|
|
256
247
|
}
|
|
257
248
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
|
|
4
|
+
function health(args) {
|
|
5
|
+
console.log(chalk.cyan('\n 🏥 System Health\n'));
|
|
6
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
7
|
+
console.log(` ${chalk.white('Status:')} ${chalk.green('Healthy')}`);
|
|
8
|
+
console.log(` ${chalk.white('Node:')} ${process.version}`);
|
|
9
|
+
console.log(` ${chalk.white('Platform:')} ${process.platform} ${os.release()}`);
|
|
10
|
+
console.log(` ${chalk.white('Uptime:')} ${Math.floor(process.uptime())}s`);
|
|
11
|
+
console.log(` ${chalk.white('Memory:')} ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB / ${Math.round(process.memoryUsage().heapTotal / 1024 / 1024)}MB`);
|
|
12
|
+
console.log(` ${chalk.white('CPU:')} ${os.cpus()[0]?.model || 'unknown'}`);
|
|
13
|
+
console.log(` ${chalk.white('Load:')} ${os.loadavg()[0].toFixed(2)}`);
|
|
14
|
+
console.log(` ${chalk.white('Host:')} ${os.hostname()}`);
|
|
15
|
+
console.log();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = health;
|
package/src/commands/help.js
CHANGED
|
@@ -40,6 +40,12 @@ function help() {
|
|
|
40
40
|
printCmd('natureco whatsapp connect', 'WhatsApp QR kod ile bağla');
|
|
41
41
|
printCmd('natureco discord connect', 'Discord bot bağla');
|
|
42
42
|
printCmd('natureco slack connect', 'Slack workspace bağla');
|
|
43
|
+
printCmd('natureco signal connect', 'Signal REST API bağla');
|
|
44
|
+
printCmd('natureco irc connect', 'IRC sunucusuna bağlan');
|
|
45
|
+
printCmd('natureco mattermost connect', 'Mattermost bot bağla');
|
|
46
|
+
printCmd('natureco imessage connect', 'iMessage bridge bağla');
|
|
47
|
+
printCmd('natureco sms connect', 'Twilio SMS bağla');
|
|
48
|
+
printCmd('natureco webhooks connect', 'Webhook ekle');
|
|
43
49
|
|
|
44
50
|
// ── Gateway & Dashboard ──────────────────────────────────────
|
|
45
51
|
console.log(chalk.cyan.bold('\n Gateway & Dashboard\n'));
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('../utils/inquirer-wrapper');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
async function imessage(action) {
|
|
8
|
+
if (!action || action === 'connect') return connectImessage();
|
|
9
|
+
if (action === 'disconnect') return disconnectImessage();
|
|
10
|
+
if (action === 'status') return statusImessage();
|
|
11
|
+
if (action === 'probe') return probeImessage();
|
|
12
|
+
console.log(chalk.red('\n❌ Unknown action\n'));
|
|
13
|
+
console.log(chalk.gray('Available actions: connect, disconnect, status, probe\n'));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function connectImessage() {
|
|
18
|
+
const config = getConfig();
|
|
19
|
+
if (!config.providerUrl) {
|
|
20
|
+
console.log(chalk.red('\n❌ Setup yapılmamış. Önce "natureco setup" çalıştırın.\n'));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (process.platform !== 'darwin') {
|
|
25
|
+
console.log(chalk.red('\n❌ iMessage sadece macOS\'te çalışır.\n'));
|
|
26
|
+
console.log(chalk.gray('Mevcut platform:'), chalk.white(process.platform));
|
|
27
|
+
console.log(chalk.gray('Diğer platformlar için SMS (Twilio) kullanılabilir.\n'));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log(chalk.yellow('\n⏳ iMessage bağlantısı hazırlanıyor...\n'));
|
|
32
|
+
console.log(chalk.gray('Gereken: imsg bridge — https://github.com/mbilker/imsg\n'));
|
|
33
|
+
|
|
34
|
+
const defaults = {
|
|
35
|
+
cliPath: config.imessageCliPath || '',
|
|
36
|
+
service: config.imessageService || 'auto',
|
|
37
|
+
dbPath: config.imessageDbPath || '~/Library/Messages/chat.db',
|
|
38
|
+
dmPolicy: config.imessageDmPolicy || 'pairing',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const answers = await inquirer.prompt([
|
|
42
|
+
{ type: 'input', name: 'cliPath', message: 'imsg CLI yolu (boş = PATH):', default: defaults.cliPath },
|
|
43
|
+
{ type: 'input', name: 'dbPath', message: 'iMessage veritabanı yolu:', default: defaults.dbPath },
|
|
44
|
+
{ type: 'list', name: 'service', message: 'Servis:', default: defaults.service, choices: [
|
|
45
|
+
{ name: 'Auto-detect (önerilen)', value: 'auto' },
|
|
46
|
+
{ name: 'iMessage', value: 'imessage' },
|
|
47
|
+
{ name: 'SMS', value: 'sms' },
|
|
48
|
+
]},
|
|
49
|
+
{ type: 'list', name: 'dmPolicy', message: 'DM politikası:', default: defaults.dmPolicy, choices: [
|
|
50
|
+
{ name: 'Pairing (önerilen)', value: 'pairing' },
|
|
51
|
+
{ name: 'Allowlist', value: 'allowlist' },
|
|
52
|
+
{ name: 'Open', value: 'open' },
|
|
53
|
+
{ name: 'Disabled', value: 'disabled' },
|
|
54
|
+
]},
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
const botId = `imessage_${Date.now()}`;
|
|
58
|
+
config.imessageCliPath = answers.cliPath.trim() || '';
|
|
59
|
+
config.imessageDbPath = answers.dbPath.trim() || '~/Library/Messages/chat.db';
|
|
60
|
+
config.imessageService = answers.service;
|
|
61
|
+
config.imessageDmPolicy = answers.dmPolicy;
|
|
62
|
+
config.imessageBotId = botId;
|
|
63
|
+
saveConfig(config);
|
|
64
|
+
|
|
65
|
+
console.log(chalk.green('\n✅ iMessage bağlantısı kaydedildi!\n'));
|
|
66
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(botId));
|
|
67
|
+
if (config.imessageCliPath) console.log(chalk.cyan('CLI Yolu:'), chalk.white(config.imessageCliPath));
|
|
68
|
+
console.log(chalk.cyan('Servis:'), chalk.white(answers.service));
|
|
69
|
+
console.log(chalk.gray('\nGateway ile başlatmak için: natureco gateway start\n'));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function disconnectImessage() {
|
|
73
|
+
const config = getConfig();
|
|
74
|
+
if (!config.imessageBotId) {
|
|
75
|
+
console.log(chalk.gray('\n⚠️ No iMessage connection found\n'));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const { confirm } = await inquirer.prompt([
|
|
79
|
+
{ type: 'confirm', name: 'confirm', message: 'iMessage bağlantısını kaldırmak istediğinize emin misiniz?', default: false }
|
|
80
|
+
]);
|
|
81
|
+
if (!confirm) {
|
|
82
|
+
console.log(chalk.gray('\nCancelled\n'));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
delete config.imessageCliPath; delete config.imessageDbPath; delete config.imessageService;
|
|
86
|
+
delete config.imessageDmPolicy; delete config.imessageBotId;
|
|
87
|
+
saveConfig(config);
|
|
88
|
+
console.log(chalk.green('\n✅ iMessage disconnected\n'));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function statusImessage() {
|
|
92
|
+
const config = getConfig();
|
|
93
|
+
if (!config.imessageBotId) {
|
|
94
|
+
console.log(chalk.gray('\n⚠️ iMessage not connected\n'));
|
|
95
|
+
console.log(chalk.gray('Connect with: natureco imessage connect\n'));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
console.log(chalk.green('\n✅ iMessage connected\n'));
|
|
99
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(config.imessageBotId));
|
|
100
|
+
if (config.imessageCliPath) console.log(chalk.cyan('CLI Yolu:'), chalk.white(config.imessageCliPath));
|
|
101
|
+
console.log(chalk.cyan('Servis:'), chalk.white(config.imessageService || 'auto'));
|
|
102
|
+
|
|
103
|
+
if (process.platform === 'darwin') {
|
|
104
|
+
const imsgPath = findImsgBinary(config);
|
|
105
|
+
console.log(chalk.cyan('imsg binary:'), chalk.white(imsgPath || 'Bulunamadı'));
|
|
106
|
+
if (config.imessageDbPath) console.log(chalk.cyan('DB Yolu:'), chalk.white(config.imessageDbPath));
|
|
107
|
+
} else {
|
|
108
|
+
console.log(chalk.yellow('\n⚠️ iMessage sadece macOS\'te çalışır'));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.log(chalk.gray('\nDisconnect with: natureco imessage disconnect\n'));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function probeImessage() {
|
|
115
|
+
const config = getConfig();
|
|
116
|
+
if (!config.imessageBotId) {
|
|
117
|
+
console.log(chalk.red('\n❌ iMessage bağlantısı yapılmamış\n'));
|
|
118
|
+
console.log(chalk.gray('Önce: natureco imessage connect\n'));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (process.platform !== 'darwin') {
|
|
123
|
+
console.log(chalk.red('\n❌ iMessage sadece macOS\'te kullanılabilir.\n'));
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log(chalk.yellow('\n⏳ iMessage problanıyor...\n'));
|
|
128
|
+
|
|
129
|
+
const imsgPath = findImsgBinary(config);
|
|
130
|
+
if (!imsgPath) {
|
|
131
|
+
console.log(chalk.red('✗ imsg binary bulunamadı\n'));
|
|
132
|
+
console.log(chalk.gray('Kurulum: brew install mbilker/imsg/imsg'));
|
|
133
|
+
console.log(chalk.gray('Veya: https://github.com/mbilker/imsg\n'));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
console.log(chalk.green(`✓ imsg found: ${imsgPath}`));
|
|
137
|
+
|
|
138
|
+
// Check DB
|
|
139
|
+
const dbPath = (config.imessageDbPath || '~/Library/Messages/chat.db').replace(/^~/, require('os').homedir());
|
|
140
|
+
if (fs.existsSync(dbPath)) {
|
|
141
|
+
console.log(chalk.green(`✓ iMessage DB: ${dbPath}`));
|
|
142
|
+
} else {
|
|
143
|
+
console.log(chalk.yellow(`⚠️ iMessage DB bulunamadı: ${dbPath}`));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Try to send a test message (dry run)
|
|
147
|
+
try {
|
|
148
|
+
const result = execSync(`"${imsgPath}" --help 2>&1`, { encoding: 'utf-8', timeout: 5000 });
|
|
149
|
+
console.log(chalk.gray(`\nimsg version: ${result.split('\n')[0]}`));
|
|
150
|
+
} catch {
|
|
151
|
+
console.log(chalk.yellow('⚠️ imsg çalıştırılamadı'));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
console.log('');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function findImsgBinary(config) {
|
|
158
|
+
if (config.imessageCliPath && fs.existsSync(config.imessageCliPath)) {
|
|
159
|
+
return config.imessageCliPath;
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const which = execSync('which imsg 2>/dev/null || echo ""', { encoding: 'utf-8', timeout: 5000 });
|
|
163
|
+
const p = which.trim();
|
|
164
|
+
if (p && fs.existsSync(p)) return p;
|
|
165
|
+
} catch {}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
module.exports = imessage;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { getConfig } = require('../utils/config');
|
|
3
|
+
|
|
4
|
+
function infer(args) {
|
|
5
|
+
const [action, ...params] = args || [];
|
|
6
|
+
|
|
7
|
+
if (!action || action === 'models') return inferModels();
|
|
8
|
+
if (action === 'media') return inferMedia();
|
|
9
|
+
if (action === 'capabilities') return inferCapabilities();
|
|
10
|
+
|
|
11
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
12
|
+
console.log(chalk.gray(' Kullanım: natureco infer [models|media|capabilities]\n'));
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function inferModels() {
|
|
17
|
+
const config = getConfig();
|
|
18
|
+
console.log(chalk.cyan('\n 🔍 Inferring models...\n'));
|
|
19
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
20
|
+
|
|
21
|
+
const providers = ['openai', 'anthropic', 'groq', 'deepseek', 'xai'];
|
|
22
|
+
for (const p of providers) {
|
|
23
|
+
const key = config[`${p}ApiKey`] || process.env[`${p.toUpperCase()}_API_KEY`];
|
|
24
|
+
const status = key ? chalk.green('API key found') : chalk.gray('not configured');
|
|
25
|
+
console.log(` ${chalk.white(p)}: ${status}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log(chalk.gray('\n For full model listing: ') + chalk.cyan('natureco models list\n'));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function inferMedia() {
|
|
32
|
+
const config = getConfig();
|
|
33
|
+
console.log(chalk.cyan('\n 🔍 Inferring media capabilities...\n'));
|
|
34
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
35
|
+
|
|
36
|
+
const checks = [
|
|
37
|
+
{ name: 'Image Generation', key: 'openaiApiKey', provider: 'OpenAI / FAL / Together' },
|
|
38
|
+
{ name: 'Video Generation', key: 'runwayApiKey', provider: 'Runway / DeepInfra' },
|
|
39
|
+
{ name: 'Music Generation', key: 'sunoApiKey', provider: 'Suno / Udio / ElevenLabs' },
|
|
40
|
+
{ name: 'Speech-to-Text', key: 'openaiApiKey', provider: 'OpenAI Whisper / Deepgram' },
|
|
41
|
+
{ name: 'Text-to-Speech', key: 'elevenlabsApiKey', provider: 'ElevenLabs / OpenAI' },
|
|
42
|
+
{ name: 'Audio Understanding', key: 'openaiApiKey', provider: 'OpenAI / Deepgram' }
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
for (const c of checks) {
|
|
46
|
+
const key = config[c.key] || process.env[c.key.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase()];
|
|
47
|
+
const status = key ? chalk.green('available') : chalk.gray('not configured');
|
|
48
|
+
console.log(` ${chalk.white(c.name)}: ${status} ${chalk.gray(`(${c.provider})`)}`);
|
|
49
|
+
}
|
|
50
|
+
console.log();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function inferCapabilities() {
|
|
54
|
+
const config = getConfig();
|
|
55
|
+
console.log(chalk.cyan('\n 🔍 Provider capabilities...\n'));
|
|
56
|
+
|
|
57
|
+
const cap = [
|
|
58
|
+
{ name: 'Chat', needs: ['openaiApiKey', 'anthropicApiKey'] },
|
|
59
|
+
{ name: 'Vision', needs: ['openaiApiKey', 'anthropicApiKey'] },
|
|
60
|
+
{ name: 'Embeddings', needs: ['openaiApiKey'] },
|
|
61
|
+
{ name: 'Web Search', needs: ['tavilyApiKey'] },
|
|
62
|
+
{ name: 'Image Gen', needs: ['openaiApiKey', 'falApiKey'] },
|
|
63
|
+
{ name: 'TTS', needs: ['elevenlabsApiKey', 'openaiApiKey'] }
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
for (const c of cap) {
|
|
67
|
+
const ok = c.needs.some(k => config[k] || process.env[k.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase()]);
|
|
68
|
+
console.log(` ${ok ? chalk.green('●') : chalk.gray('○')} ${chalk.white(c.name)}`);
|
|
69
|
+
}
|
|
70
|
+
console.log();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = infer;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('../utils/inquirer-wrapper');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
|
|
5
|
+
async function irc(action) {
|
|
6
|
+
if (!action || action === 'connect') return connectIrc();
|
|
7
|
+
if (action === 'disconnect') return disconnectIrc();
|
|
8
|
+
if (action === 'status') return statusIrc();
|
|
9
|
+
console.log(chalk.red('\n❌ Unknown action\n'));
|
|
10
|
+
console.log(chalk.gray('Available actions: connect, disconnect, status\n'));
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function connectIrc() {
|
|
15
|
+
const config = getConfig();
|
|
16
|
+
if (!config.providerUrl) {
|
|
17
|
+
console.log(chalk.red('\n❌ Setup yapılmamış. Önce "natureco setup" çalıştırın.\n'));
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
console.log(chalk.yellow('\n⏳ IRC bağlantısı hazırlanıyor...\n'));
|
|
21
|
+
|
|
22
|
+
const defaults = {
|
|
23
|
+
host: config.ircHost || '',
|
|
24
|
+
port: config.ircPort || 6697,
|
|
25
|
+
tls: config.ircTls !== undefined ? config.ircTls : true,
|
|
26
|
+
nick: config.ircNick || '',
|
|
27
|
+
username: config.ircUsername || '',
|
|
28
|
+
realname: config.ircRealname || '',
|
|
29
|
+
password: config.ircPassword || '',
|
|
30
|
+
channels: config.ircChannels || [],
|
|
31
|
+
dmPolicy: config.ircDmPolicy || 'pairing',
|
|
32
|
+
nickservEnabled: config.ircNickservEnabled !== undefined ? config.ircNickservEnabled : true,
|
|
33
|
+
nickservPassword: config.ircNickservPassword || '',
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const answers = await inquirer.prompt([
|
|
37
|
+
{ type: 'input', name: 'host', message: 'IRC sunucusu:', default: defaults.host, validate: v => v.trim() ? true : 'Gerekli' },
|
|
38
|
+
{ type: 'input', name: 'port', message: 'Port:', default: String(defaults.port), validate: v => { const n = parseInt(v); return n > 0 && n < 65536 ? true : '1-65535 arası' } },
|
|
39
|
+
{ type: 'confirm', name: 'tls', message: 'TLS kullanılsın mı?', default: defaults.tls },
|
|
40
|
+
{ type: 'input', name: 'nick', message: 'Nick:', default: defaults.nick, validate: v => v.trim() ? true : 'Gerekli' },
|
|
41
|
+
{ type: 'input', name: 'username', message: 'Kullanıcı adı (opsiyonel):', default: defaults.username || defaults.nick },
|
|
42
|
+
{ type: 'input', name: 'realname', message: 'Gerçek ad (opsiyonel):', default: defaults.realname || 'NatureCo' },
|
|
43
|
+
{ type: 'password', name: 'password', message: 'Sunucu parolası (opsiyonel):' },
|
|
44
|
+
{ type: 'input', name: 'channels', message: 'Kanallar (virgülle ayırın):', default: defaults.channels.join(',') },
|
|
45
|
+
{ type: 'confirm', name: 'nickservEnabled', message: 'NickServ kullanılsın mı?', default: defaults.nickservEnabled },
|
|
46
|
+
{ type: 'password', name: 'nickservPassword', message: 'NickServ parolası (opsiyonel):' },
|
|
47
|
+
{ type: 'list', name: 'dmPolicy', message: 'DM politikası:', default: defaults.dmPolicy, choices: [
|
|
48
|
+
{ name: 'Pairing (önerilen)', value: 'pairing' },
|
|
49
|
+
{ name: 'Allowlist', value: 'allowlist' },
|
|
50
|
+
{ name: 'Open', value: 'open' },
|
|
51
|
+
{ name: 'Disabled', value: 'disabled' },
|
|
52
|
+
]},
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
const botId = `irc_${Date.now()}`;
|
|
56
|
+
config.ircHost = answers.host.trim();
|
|
57
|
+
config.ircPort = parseInt(answers.port);
|
|
58
|
+
config.ircTls = answers.tls;
|
|
59
|
+
config.ircNick = answers.nick.trim();
|
|
60
|
+
config.ircUsername = answers.username.trim() || answers.nick.trim();
|
|
61
|
+
config.ircRealname = answers.realname.trim() || 'NatureCo';
|
|
62
|
+
config.ircPassword = answers.password || '';
|
|
63
|
+
config.ircChannels = answers.channels ? answers.channels.split(',').map(c => c.trim()).filter(Boolean) : [];
|
|
64
|
+
config.ircNickservEnabled = answers.nickservEnabled;
|
|
65
|
+
config.ircNickservPassword = answers.nickservPassword || '';
|
|
66
|
+
config.ircDmPolicy = answers.dmPolicy;
|
|
67
|
+
config.ircBotId = botId;
|
|
68
|
+
saveConfig(config);
|
|
69
|
+
|
|
70
|
+
console.log(chalk.green('\n✅ IRC bağlantısı kaydedildi!\n'));
|
|
71
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(botId));
|
|
72
|
+
console.log(chalk.cyan('Sunucu:'), chalk.white(`${answers.host.trim()}:${answers.port}`));
|
|
73
|
+
console.log(chalk.cyan('Nick:'), chalk.white(answers.nick.trim()));
|
|
74
|
+
if (config.ircChannels.length) console.log(chalk.cyan('Kanallar:'), chalk.white(config.ircChannels.join(', ')));
|
|
75
|
+
console.log(chalk.gray('\nGateway ile başlatmak için: natureco gateway start\n'));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function disconnectIrc() {
|
|
79
|
+
const config = getConfig();
|
|
80
|
+
if (!config.ircBotId) {
|
|
81
|
+
console.log(chalk.gray('\n⚠️ No IRC connection found\n'));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const { confirm } = await inquirer.prompt([
|
|
85
|
+
{ type: 'confirm', name: 'confirm', message: 'IRC bağlantısını kaldırmak istediğinize emin misiniz?', default: false }
|
|
86
|
+
]);
|
|
87
|
+
if (!confirm) {
|
|
88
|
+
console.log(chalk.gray('\nCancelled\n'));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
delete config.ircHost; delete config.ircPort; delete config.ircTls; delete config.ircNick;
|
|
92
|
+
delete config.ircUsername; delete config.ircRealname; delete config.ircPassword;
|
|
93
|
+
delete config.ircChannels; delete config.ircNickservEnabled; delete config.ircNickservPassword;
|
|
94
|
+
delete config.ircDmPolicy; delete config.ircBotId;
|
|
95
|
+
saveConfig(config);
|
|
96
|
+
console.log(chalk.green('\n✅ IRC disconnected\n'));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function statusIrc() {
|
|
100
|
+
const config = getConfig();
|
|
101
|
+
if (!config.ircBotId) {
|
|
102
|
+
console.log(chalk.gray('\n⚠️ IRC not connected\n'));
|
|
103
|
+
console.log(chalk.gray('Connect with: natureco irc connect\n'));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
console.log(chalk.green('\n✅ IRC connected\n'));
|
|
107
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(config.ircBotId));
|
|
108
|
+
console.log(chalk.cyan('Sunucu:'), chalk.white(`${config.ircHost}:${config.ircPort}`));
|
|
109
|
+
console.log(chalk.cyan('TLS:'), chalk.white(config.ircTls ? 'Evet' : 'Hayır'));
|
|
110
|
+
console.log(chalk.cyan('Nick:'), chalk.white(config.ircNick));
|
|
111
|
+
console.log(chalk.cyan('Kullanıcı:'), chalk.white(config.ircUsername));
|
|
112
|
+
if (config.ircRealname) console.log(chalk.cyan('Realname:'), chalk.white(config.ircRealname));
|
|
113
|
+
if (config.ircChannels?.length) console.log(chalk.cyan('Kanallar:'), chalk.white(config.ircChannels.join(', ')));
|
|
114
|
+
console.log(chalk.cyan('NickServ:'), chalk.white(config.ircNickservEnabled ? 'Evet' : 'Hayır'));
|
|
115
|
+
console.log(chalk.cyan('DM Politikası:'), chalk.white(config.ircDmPolicy || 'pairing'));
|
|
116
|
+
console.log(chalk.gray('\nDisconnect with: natureco irc disconnect\n'));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = irc;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('../utils/inquirer-wrapper');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
|
|
5
|
+
async function mattermost(action) {
|
|
6
|
+
if (!action || action === 'connect') return connectMattermost();
|
|
7
|
+
if (action === 'disconnect') return disconnectMattermost();
|
|
8
|
+
if (action === 'status') return statusMattermost();
|
|
9
|
+
if (action === 'probe') return probeMattermost();
|
|
10
|
+
console.log(chalk.red('\n❌ Unknown action\n'));
|
|
11
|
+
console.log(chalk.gray('Available actions: connect, disconnect, status, probe\n'));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function connectMattermost() {
|
|
16
|
+
const config = getConfig();
|
|
17
|
+
if (!config.providerUrl) {
|
|
18
|
+
console.log(chalk.red('\n❌ Setup yapılmamış. Önce "natureco setup" çalıştırın.\n'));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
console.log(chalk.yellow('\n⏳ Mattermost bağlantısı hazırlanıyor...\n'));
|
|
22
|
+
console.log(chalk.gray('Mattermost bot token almak için:'));
|
|
23
|
+
console.log(chalk.gray('1. Mattermost > System Console > Bot Accounts'));
|
|
24
|
+
console.log(chalk.gray('2. Bot oluşturun veya mevcut botu kullanın'));
|
|
25
|
+
console.log(chalk.gray('3. Access Token oluşturun\n'));
|
|
26
|
+
|
|
27
|
+
const defaults = {
|
|
28
|
+
baseUrl: config.mattermostBaseUrl || '',
|
|
29
|
+
token: config.mattermostToken || '',
|
|
30
|
+
dmPolicy: config.mattermostDmPolicy || 'pairing',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const answers = await inquirer.prompt([
|
|
34
|
+
{ type: 'input', name: 'baseUrl', message: 'Mattermost sunucu URL:', default: defaults.baseUrl, validate: v => v.trim() ? true : 'Gerekli' },
|
|
35
|
+
{ type: 'input', name: 'token', message: 'Bot token:', default: defaults.token ? defaults.token.slice(0, 10) + '...' : '', validate: v => v.trim() ? true : 'Gerekli' },
|
|
36
|
+
{ type: 'confirm', name: 'enableSlash', message: 'Slash komutları kaydedilsin mi?', default: config.mattermostSlashEnabled !== false },
|
|
37
|
+
{ type: 'list', name: 'dmPolicy', message: 'DM politikası:', default: defaults.dmPolicy, choices: [
|
|
38
|
+
{ name: 'Pairing (önerilen)', value: 'pairing' },
|
|
39
|
+
{ name: 'Allowlist', value: 'allowlist' },
|
|
40
|
+
{ name: 'Open', value: 'open' },
|
|
41
|
+
{ name: 'Disabled', value: 'disabled' },
|
|
42
|
+
]},
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
const botId = `mattermost_${Date.now()}`;
|
|
46
|
+
config.mattermostBaseUrl = answers.baseUrl.trim().replace(/\/+$/, '');
|
|
47
|
+
config.mattermostToken = answers.token.trim();
|
|
48
|
+
config.mattermostSlashEnabled = answers.enableSlash;
|
|
49
|
+
config.mattermostDmPolicy = answers.dmPolicy;
|
|
50
|
+
config.mattermostBotId = botId;
|
|
51
|
+
saveConfig(config);
|
|
52
|
+
|
|
53
|
+
console.log(chalk.green('\n✅ Mattermost bağlantısı kaydedildi!\n'));
|
|
54
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(botId));
|
|
55
|
+
console.log(chalk.cyan('Sunucu:'), chalk.white(config.mattermostBaseUrl));
|
|
56
|
+
console.log(chalk.cyan('Token:'), chalk.white((answers.token || '').slice(0, 20) + '...'));
|
|
57
|
+
console.log(chalk.gray('\nGateway ile başlatmak için: natureco gateway start\n'));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function disconnectMattermost() {
|
|
61
|
+
const config = getConfig();
|
|
62
|
+
if (!config.mattermostBotId) {
|
|
63
|
+
console.log(chalk.gray('\n⚠️ No Mattermost connection found\n'));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const { confirm } = await inquirer.prompt([
|
|
67
|
+
{ type: 'confirm', name: 'confirm', message: 'Mattermost bağlantısını kaldırmak istediğinize emin misiniz?', default: false }
|
|
68
|
+
]);
|
|
69
|
+
if (!confirm) {
|
|
70
|
+
console.log(chalk.gray('\nCancelled\n'));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
delete config.mattermostBaseUrl; delete config.mattermostToken;
|
|
74
|
+
delete config.mattermostSlashEnabled; delete config.mattermostDmPolicy;
|
|
75
|
+
delete config.mattermostBotId;
|
|
76
|
+
saveConfig(config);
|
|
77
|
+
console.log(chalk.green('\n✅ Mattermost disconnected\n'));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function statusMattermost() {
|
|
81
|
+
const config = getConfig();
|
|
82
|
+
if (!config.mattermostBotId) {
|
|
83
|
+
console.log(chalk.gray('\n⚠️ Mattermost not connected\n'));
|
|
84
|
+
console.log(chalk.gray('Connect with: natureco mattermost connect\n'));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(chalk.green('\n✅ Mattermost connected\n'));
|
|
88
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(config.mattermostBotId));
|
|
89
|
+
console.log(chalk.cyan('Sunucu:'), chalk.white(config.mattermostBaseUrl));
|
|
90
|
+
console.log(chalk.cyan('Token:'), chalk.white((config.mattermostToken || '').slice(0, 20) + '...'));
|
|
91
|
+
console.log(chalk.cyan('Slash Komutları:'), chalk.white(config.mattermostSlashEnabled !== false ? 'Aktif' : 'Devre Dışı'));
|
|
92
|
+
console.log(chalk.cyan('DM Politikası:'), chalk.white(config.mattermostDmPolicy || 'pairing'));
|
|
93
|
+
|
|
94
|
+
// Optionally probe
|
|
95
|
+
if (config.mattermostBaseUrl && config.mattermostToken) {
|
|
96
|
+
console.log(chalk.gray('\nProbe için: natureco mattermost probe\n'));
|
|
97
|
+
}
|
|
98
|
+
console.log(chalk.gray('\nDisconnect with: natureco mattermost disconnect\n'));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function probeMattermost() {
|
|
102
|
+
const config = getConfig();
|
|
103
|
+
if (!config.mattermostBaseUrl || !config.mattermostToken) {
|
|
104
|
+
console.log(chalk.red('\n❌ Mattermost bağlantısı yapılmamış\n'));
|
|
105
|
+
console.log(chalk.gray('Önce: natureco mattermost connect\n'));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const baseUrl = config.mattermostBaseUrl.replace(/\/+$/, '');
|
|
110
|
+
const token = config.mattermostToken;
|
|
111
|
+
|
|
112
|
+
console.log(chalk.yellow(`\n⏳ Problanıyor: ${baseUrl}\n`));
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const res = await fetch(`${baseUrl}/api/v4/users/me`, {
|
|
116
|
+
headers: { 'Authorization': `Bearer ${token}` },
|
|
117
|
+
signal: AbortSignal.timeout(10000),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (!res.ok) {
|
|
121
|
+
console.log(chalk.red(`✗ API Hatası: HTTP ${res.status}`));
|
|
122
|
+
if (res.status === 401) console.log(chalk.gray(' Token geçersiz. Yeni bir bot token alın.'));
|
|
123
|
+
if (res.status === 403) console.log(chalk.gray(' Botun yetkisi yetersiz.'));
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const me = await res.json();
|
|
128
|
+
console.log(chalk.green('✓ API Bağlantısı Başarılı\n'));
|
|
129
|
+
console.log(chalk.cyan('Bot Kullanıcı ID:'), chalk.white(me.id));
|
|
130
|
+
console.log(chalk.cyan('Kullanıcı Adı:'), chalk.white(me.username));
|
|
131
|
+
console.log(chalk.cyan('E-posta:'), chalk.white(me.email));
|
|
132
|
+
console.log(chalk.cyan('Rol:'), chalk.white(me.roles));
|
|
133
|
+
|
|
134
|
+
// Check WebSocket
|
|
135
|
+
const wsUrl = baseUrl.replace(/^http/, 'ws') + '/api/v4/websocket';
|
|
136
|
+
console.log(chalk.gray(`\nWebSocket: ${wsUrl}`));
|
|
137
|
+
|
|
138
|
+
// Check slash commands
|
|
139
|
+
try {
|
|
140
|
+
const teamsRes = await fetch(`${baseUrl}/api/v4/users/me/teams`, {
|
|
141
|
+
headers: { 'Authorization': `Bearer ${token}` },
|
|
142
|
+
signal: AbortSignal.timeout(5000),
|
|
143
|
+
});
|
|
144
|
+
if (teamsRes.ok) {
|
|
145
|
+
const teams = await teamsRes.json();
|
|
146
|
+
console.log(chalk.gray(`\nTakımlar (${teams.length}):`));
|
|
147
|
+
for (const team of teams.slice(0, 5)) {
|
|
148
|
+
console.log(chalk.gray(` - ${team.display_name} (${team.name})`));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} catch {}
|
|
152
|
+
|
|
153
|
+
console.log('');
|
|
154
|
+
|
|
155
|
+
} catch (err) {
|
|
156
|
+
console.log(chalk.red(`\n✗ Probe hatası: ${err.message}\n`));
|
|
157
|
+
if (err.message.includes('ENOTFOUND') || err.message.includes('ECONNREFUSED')) {
|
|
158
|
+
console.log(chalk.gray('Sunucuya erişilemiyor. URL\'yi kontrol edin.\n'));
|
|
159
|
+
}
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = mattermost;
|