natureco-cli 1.0.14 → 1.0.16

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.
@@ -0,0 +1,159 @@
1
+ const chalk = require('chalk');
2
+ const inquirer = require('inquirer');
3
+ const { getApiKey, getConfig, saveConfig } = require('../utils/config');
4
+ const { getBots } = require('../utils/api');
5
+
6
+ async function discord(action) {
7
+ if (!action || action === 'connect') {
8
+ return connectDiscord();
9
+ }
10
+
11
+ if (action === 'disconnect') {
12
+ return disconnectDiscord();
13
+ }
14
+
15
+ if (action === 'status') {
16
+ return statusDiscord();
17
+ }
18
+
19
+ console.log(chalk.red('\n❌ Unknown action\n'));
20
+ console.log(chalk.gray('Available actions: connect, disconnect, status\n'));
21
+ process.exit(1);
22
+ }
23
+
24
+ async function connectDiscord() {
25
+ const apiKey = getApiKey();
26
+
27
+ if (!apiKey) {
28
+ console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
29
+ process.exit(1);
30
+ }
31
+
32
+ const config = getConfig();
33
+
34
+ console.log(chalk.yellow('\n⏳ Loading bots...\n'));
35
+
36
+ let botList;
37
+ try {
38
+ botList = await getBots(apiKey);
39
+ } catch (err) {
40
+ console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
41
+ process.exit(1);
42
+ }
43
+
44
+ if (!botList || !botList.bots || botList.bots.length === 0) {
45
+ console.log(chalk.gray('No bots found. Create one at https://developers.natureco.me\n'));
46
+ process.exit(1);
47
+ }
48
+
49
+ process.stdin.resume();
50
+
51
+ const answers = await inquirer.prompt([
52
+ {
53
+ type: 'list',
54
+ name: 'botId',
55
+ message: 'Select bot to connect:',
56
+ choices: botList.bots.map(b => ({ name: b.name, value: b.id })),
57
+ },
58
+ {
59
+ type: 'input',
60
+ name: 'token',
61
+ message: 'Discord bot token:',
62
+ validate: (val) => val.trim() !== '' || 'Token cannot be empty',
63
+ },
64
+ ]);
65
+
66
+ const selectedBot = botList.bots.find(b => b.id === answers.botId);
67
+
68
+ console.log(chalk.yellow('\n⏳ Connecting to Discord...\n'));
69
+
70
+ try {
71
+ const response = await fetch('https://api.natureco.me/api/agent/discord/connect', {
72
+ method: 'POST',
73
+ headers: {
74
+ 'Content-Type': 'application/json',
75
+ 'Authorization': `Bearer ${apiKey}`,
76
+ },
77
+ body: JSON.stringify({
78
+ agent_id: answers.botId,
79
+ discord_bot_token: answers.token.trim(),
80
+ }),
81
+ });
82
+
83
+ if (!response.ok) {
84
+ const error = await response.text();
85
+ throw new Error(error);
86
+ }
87
+
88
+ const data = await response.json();
89
+
90
+ console.log(chalk.green('✅ Discord connected successfully!\n'));
91
+ console.log(chalk.cyan('Bot:'), chalk.white(selectedBot.name));
92
+ console.log(chalk.cyan('Discord Bot:'), chalk.white(data.bot_username || 'Unknown'));
93
+ console.log(chalk.gray('\nYour bot is now active on Discord.'));
94
+ console.log(chalk.gray('Users can interact with /sor command.\n'));
95
+
96
+ // Save to config
97
+ config.discordToken = answers.token.trim();
98
+ config.discordBotId = answers.botId;
99
+ saveConfig(config);
100
+ } catch (err) {
101
+ console.log(chalk.red(`\n❌ Connection failed: ${err.message}\n`));
102
+ process.exit(1);
103
+ }
104
+ }
105
+
106
+ async function disconnectDiscord() {
107
+ const config = getConfig();
108
+
109
+ if (!config.discordToken) {
110
+ console.log(chalk.gray('\n⚠️ No Discord connection found\n'));
111
+ return;
112
+ }
113
+
114
+ process.stdin.resume();
115
+
116
+ const { confirm } = await inquirer.prompt([
117
+ {
118
+ type: 'confirm',
119
+ name: 'confirm',
120
+ message: 'Are you sure you want to disconnect Discord?',
121
+ default: false,
122
+ },
123
+ ]);
124
+
125
+ if (!confirm) {
126
+ console.log(chalk.gray('\nCancelled\n'));
127
+ return;
128
+ }
129
+
130
+ // Remove from config
131
+ delete config.discordToken;
132
+ delete config.discordBotId;
133
+ saveConfig(config);
134
+
135
+ console.log(chalk.green('\n✅ Discord disconnected\n'));
136
+ console.log(chalk.gray('Note: The bot is still registered on Discord.'));
137
+ console.log(chalk.gray('You may need to manually remove it from Discord Developer Portal.\n'));
138
+ }
139
+
140
+ function statusDiscord() {
141
+ const config = getConfig();
142
+
143
+ if (!config.discordToken) {
144
+ console.log(chalk.gray('\n⚠️ Discord not connected\n'));
145
+ console.log(chalk.gray('Connect with: natureco discord connect\n'));
146
+ return;
147
+ }
148
+
149
+ console.log(chalk.green('\n✅ Discord connected\n'));
150
+ console.log(chalk.cyan('Token:'), chalk.white(config.discordToken.slice(0, 20) + '...'));
151
+
152
+ if (config.discordBotId) {
153
+ console.log(chalk.cyan('Bot ID:'), chalk.white(config.discordBotId));
154
+ }
155
+
156
+ console.log(chalk.gray('\nDisconnect with: natureco discord disconnect\n'));
157
+ }
158
+
159
+ module.exports = discord;
@@ -0,0 +1,362 @@
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const net = require('net');
5
+ const { getConfig, saveConfig, CONFIG_FILE, CONFIG_DIR } = require('../utils/config');
6
+ const { getBots } = require('../utils/api');
7
+ const { getSkills } = require('../utils/skills');
8
+
9
+ async function doctor(options) {
10
+ const shouldFix = options && (options.includes('--fix') || options.includes('-f'));
11
+
12
+ console.log(chalk.cyan.bold('\n🔍 NatureCo CLI Sistem Kontrolü\n'));
13
+
14
+ const results = [];
15
+ let passed = 0;
16
+ let total = 0;
17
+ let criticalPassed = 0;
18
+ let criticalTotal = 0;
19
+
20
+ // 1. Node.js versiyon kontrolü
21
+ total++;
22
+ criticalTotal++;
23
+ const nodeVersion = process.version;
24
+ const nodeMajor = parseInt(nodeVersion.slice(1).split('.')[0]);
25
+ if (nodeMajor >= 18) {
26
+ console.log(chalk.green('✅ Node.js versiyonu:'), chalk.white(nodeVersion));
27
+ passed++;
28
+ criticalPassed++;
29
+ results.push({ status: 'ok', message: 'Node.js 18+' });
30
+ } else {
31
+ console.log(chalk.red('❌ Node.js versiyonu:'), chalk.white(nodeVersion), chalk.gray('(18+ gerekli)'));
32
+ results.push({ status: 'error', message: 'Node.js 18+ gerekli', fix: 'Node.js güncelleyin: https://nodejs.org' });
33
+ }
34
+
35
+ // 2. Config dosyası kontrolü
36
+ total++;
37
+ criticalTotal++;
38
+ let config = null;
39
+ if (fs.existsSync(CONFIG_FILE)) {
40
+ try {
41
+ const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
42
+ config = JSON.parse(data);
43
+ console.log(chalk.green('✅ Config dosyası:'), chalk.white(CONFIG_FILE));
44
+ passed++;
45
+ criticalPassed++;
46
+ results.push({ status: 'ok', message: 'Config dosyası geçerli' });
47
+ } catch (err) {
48
+ console.log(chalk.red('❌ Config dosyası:'), chalk.white('Bozuk JSON'));
49
+ results.push({ status: 'error', message: 'Config dosyası bozuk', fix: 'Config yeniden oluşturulacak' });
50
+
51
+ if (shouldFix) {
52
+ console.log(chalk.yellow(' 🔧 Config yeniden oluşturuluyor...'));
53
+ config = { setupCompleted: false, skills: { enabled: true, list: [] }, mcpServers: {} };
54
+ saveConfig(config);
55
+ console.log(chalk.green(' ✓ Config oluşturuldu'));
56
+ }
57
+ }
58
+ } else {
59
+ console.log(chalk.yellow('⚠️ Config dosyası:'), chalk.white('Bulunamadı'));
60
+ results.push({ status: 'warning', message: 'Config dosyası yok', fix: 'Config oluşturulacak' });
61
+
62
+ if (shouldFix) {
63
+ console.log(chalk.yellow(' 🔧 Config oluşturuluyor...'));
64
+ if (!fs.existsSync(CONFIG_DIR)) {
65
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
66
+ }
67
+ config = { setupCompleted: false, skills: { enabled: true, list: [] }, mcpServers: {} };
68
+ saveConfig(config);
69
+ console.log(chalk.green(' ✓ Config oluşturuldu'));
70
+ }
71
+ }
72
+
73
+ // 3. API key kontrolü
74
+ total++;
75
+ criticalTotal++;
76
+ let apiKeyValid = false;
77
+ if (config && config.apiKey) {
78
+ try {
79
+ const response = await fetch('https://api.natureco.me/api/v1/bots', {
80
+ headers: { 'Authorization': `Bearer ${config.apiKey}` },
81
+ });
82
+
83
+ if (response.ok) {
84
+ console.log(chalk.green('✅ API key:'), chalk.white(config.apiKey.slice(0, 8) + '...'));
85
+ passed++;
86
+ criticalPassed++;
87
+ apiKeyValid = true;
88
+ results.push({ status: 'ok', message: 'API key geçerli' });
89
+ } else {
90
+ console.log(chalk.red('❌ API key:'), chalk.white('Geçersiz'));
91
+ results.push({ status: 'error', message: 'API key geçersiz', fix: 'Setup çalıştırılacak' });
92
+ }
93
+ } catch (err) {
94
+ console.log(chalk.red('❌ API key:'), chalk.white('Test edilemedi'));
95
+ results.push({ status: 'error', message: 'API key test edilemedi' });
96
+ }
97
+ } else {
98
+ console.log(chalk.yellow('⚠️ API key:'), chalk.white('Kayıtlı değil'));
99
+ results.push({ status: 'warning', message: 'API key yok', fix: 'Setup çalıştırılacak' });
100
+ }
101
+
102
+ if (shouldFix && !apiKeyValid) {
103
+ console.log(chalk.yellow(' 🔧 Setup başlatılıyor...'));
104
+ console.log(chalk.gray(' Lütfen setup\'ı manuel çalıştırın: natureco setup'));
105
+ }
106
+
107
+ // 4. Varsayılan bot kontrolü
108
+ total++;
109
+ if (config && config.defaultBot && config.defaultBotId) {
110
+ console.log(chalk.green('✅ Varsayılan bot:'), chalk.white(config.defaultBot));
111
+ passed++;
112
+ results.push({ status: 'ok', message: 'Varsayılan bot ayarlanmış' });
113
+ } else {
114
+ console.log(chalk.yellow('⚠️ Varsayılan bot:'), chalk.white('Ayarlanmamış'));
115
+ results.push({ status: 'warning', message: 'Varsayılan bot yok', fix: 'Setup ile ayarlanabilir' });
116
+ }
117
+
118
+ // 5. Skills kontrolü
119
+ total++;
120
+ try {
121
+ const skills = getSkills();
122
+ const skillCount = skills.length;
123
+
124
+ if (skillCount > 0) {
125
+ console.log(chalk.green('✅ Skills:'), chalk.white(`${skillCount} yüklü`));
126
+ passed++;
127
+ results.push({ status: 'ok', message: `${skillCount} skill yüklü` });
128
+ } else {
129
+ console.log(chalk.yellow('⚠️ Skills:'), chalk.white('Yüklü skill yok'));
130
+ results.push({ status: 'warning', message: 'Skill yok', fix: 'Yerleşik skill\'ler yüklenebilir' });
131
+ }
132
+ } catch (err) {
133
+ console.log(chalk.yellow('⚠️ Skills:'), chalk.white('Kontrol edilemedi'));
134
+ results.push({ status: 'warning', message: 'Skills kontrol edilemedi' });
135
+ }
136
+
137
+ // 6. MCP sunucuları kontrolü
138
+ total++;
139
+ const mcpCount = config && config.mcpServers ? Object.keys(config.mcpServers).length : 0;
140
+ if (mcpCount > 0) {
141
+ console.log(chalk.green('✅ MCP sunucuları:'), chalk.white(`${mcpCount} kayıtlı`));
142
+ passed++;
143
+ results.push({ status: 'ok', message: `${mcpCount} MCP sunucusu` });
144
+ } else {
145
+ console.log(chalk.yellow('⚠️ MCP sunucuları:'), chalk.white('Kayıtlı sunucu yok'));
146
+ results.push({ status: 'warning', message: 'MCP sunucusu yok' });
147
+ }
148
+
149
+ // 7. Hafıza kontrolü
150
+ total++;
151
+ const memoryDir = path.join(CONFIG_DIR, 'memory');
152
+ let memoryActive = false;
153
+
154
+ if (fs.existsSync(memoryDir)) {
155
+ try {
156
+ const files = fs.readdirSync(memoryDir);
157
+ const memoryFiles = files.filter(f => f.endsWith('.json'));
158
+ if (memoryFiles.length > 0) {
159
+ memoryActive = true;
160
+ console.log(chalk.green('✅ Hafıza:'), chalk.white(`Aktif (${memoryFiles.length} dosya)`));
161
+ passed++;
162
+ results.push({ status: 'ok', message: `Hafıza aktif (${memoryFiles.length} dosya)` });
163
+ } else {
164
+ console.log(chalk.yellow('⚠️ Hafıza:'), chalk.white('Klasör var, dosya yok'));
165
+ results.push({ status: 'warning', message: 'Hafıza dosyası yok' });
166
+ }
167
+ } catch (err) {
168
+ console.log(chalk.yellow('⚠️ Hafıza:'), chalk.white('Kontrol edilemedi'));
169
+ results.push({ status: 'warning', message: 'Hafıza kontrol edilemedi' });
170
+ }
171
+ } else {
172
+ console.log(chalk.yellow('⚠️ Hafıza:'), chalk.white('Pasif'));
173
+ results.push({ status: 'warning', message: 'Hafıza pasif' });
174
+ }
175
+
176
+ // 8. Telegram kontrolü (opsiyonel)
177
+ if (config && config.telegramToken) {
178
+ console.log(chalk.green('✅ Telegram:'), chalk.white('Bağlı'));
179
+ results.push({ status: 'ok', message: 'Telegram bağlı', optional: true });
180
+ } else {
181
+ console.log(chalk.gray('⚪ Telegram:'), chalk.white('Bağlı değil'));
182
+ results.push({ status: 'info', message: 'Telegram bağlı değil', optional: true });
183
+ }
184
+
185
+ // 9. Discord kontrolü (opsiyonel)
186
+ if (config && config.discordToken) {
187
+ console.log(chalk.green('✅ Discord:'), chalk.white('Bağlı'));
188
+ results.push({ status: 'ok', message: 'Discord bağlı', optional: true });
189
+ } else {
190
+ console.log(chalk.gray('⚪ Discord:'), chalk.white('Bağlı değil'));
191
+ results.push({ status: 'info', message: 'Discord bağlı değil', optional: true });
192
+ }
193
+
194
+ // 10. Slack kontrolü (opsiyonel)
195
+ if (config && config.slackToken) {
196
+ console.log(chalk.green('✅ Slack:'), chalk.white('Bağlı'));
197
+ results.push({ status: 'ok', message: 'Slack bağlı', optional: true });
198
+ } else {
199
+ console.log(chalk.gray('⚪ Slack:'), chalk.white('Bağlı değil'));
200
+ results.push({ status: 'info', message: 'Slack bağlı değil', optional: true });
201
+ }
202
+
203
+ // 11. WhatsApp kontrolü (opsiyonel)
204
+ if (config && config.whatsappConnected) {
205
+ console.log(chalk.green('✅ WhatsApp:'), chalk.white('Bağlı'));
206
+ results.push({ status: 'ok', message: 'WhatsApp bağlı', optional: true });
207
+ } else {
208
+ console.log(chalk.gray('⚪ WhatsApp:'), chalk.white('Bağlı değil'));
209
+ results.push({ status: 'info', message: 'WhatsApp bağlı değil', optional: true });
210
+ }
211
+
212
+ // 12. Dashboard kontrolü (opsiyonel)
213
+ const dashboardRunning = await checkPort(3848);
214
+ if (dashboardRunning) {
215
+ console.log(chalk.green('✅ Dashboard:'), chalk.white('Çalışıyor (port 3848)'));
216
+ results.push({ status: 'ok', message: 'Dashboard çalışıyor', optional: true });
217
+ } else {
218
+ console.log(chalk.gray('⚪ Dashboard:'), chalk.white('Çalışmıyor'));
219
+ results.push({ status: 'info', message: 'Dashboard çalışmıyor', fix: 'natureco dashboard start', optional: true });
220
+
221
+ if (shouldFix) {
222
+ console.log(chalk.yellow(' 🔧 Dashboard başlatılıyor...'));
223
+ console.log(chalk.gray(' Lütfen manuel başlatın: natureco dashboard start'));
224
+ }
225
+ }
226
+
227
+ // 13. Gateway kontrolü (opsiyonel)
228
+ const gatewayRunning = await checkPort(3847);
229
+ if (gatewayRunning) {
230
+ console.log(chalk.green('✅ Gateway:'), chalk.white('Çalışıyor (port 3847)'));
231
+ results.push({ status: 'ok', message: 'Gateway çalışıyor', optional: true });
232
+ } else {
233
+ console.log(chalk.gray('⚪ Gateway:'), chalk.white('Çalışmıyor'));
234
+ results.push({ status: 'info', message: 'Gateway çalışmıyor', fix: 'natureco gateway start', optional: true });
235
+ }
236
+
237
+ // 14. Internet bağlantısı kontrolü
238
+ total++;
239
+ criticalTotal++;
240
+ try {
241
+ const response = await fetch('https://api.natureco.me/health', {
242
+ method: 'GET',
243
+ signal: AbortSignal.timeout(5000),
244
+ });
245
+
246
+ if (response.ok || response.status === 404) {
247
+ console.log(chalk.green('✅ Internet:'), chalk.white('api.natureco.me erişilebilir'));
248
+ passed++;
249
+ criticalPassed++;
250
+ results.push({ status: 'ok', message: 'API erişilebilir' });
251
+ } else {
252
+ console.log(chalk.yellow('⚠️ Internet:'), chalk.white('API yanıt vermiyor'));
253
+ results.push({ status: 'warning', message: 'API yanıt vermiyor' });
254
+ }
255
+ } catch (err) {
256
+ console.log(chalk.red('❌ Internet:'), chalk.white('api.natureco.me erişilemiyor'));
257
+ results.push({ status: 'error', message: 'API erişilemiyor' });
258
+ }
259
+
260
+ // 15. Güncelleme kontrolü
261
+ total++;
262
+ try {
263
+ const packageJson = require('../../package.json');
264
+ const currentVersion = packageJson.version;
265
+
266
+ const response = await fetch('https://registry.npmjs.org/natureco-cli/latest', {
267
+ signal: AbortSignal.timeout(5000),
268
+ });
269
+
270
+ if (response.ok) {
271
+ const data = await response.json();
272
+ const latestVersion = data.version;
273
+
274
+ if (currentVersion === latestVersion) {
275
+ console.log(chalk.green('✅ Versiyon:'), chalk.white(`${currentVersion} (güncel)`));
276
+ passed++;
277
+ results.push({ status: 'ok', message: 'Versiyon güncel' });
278
+ } else {
279
+ console.log(chalk.yellow('⚠️ Versiyon:'), chalk.white(`${currentVersion} → ${latestVersion} mevcut`));
280
+ results.push({ status: 'warning', message: 'Yeni versiyon mevcut', fix: 'npm install -g natureco-cli@latest' });
281
+
282
+ if (shouldFix) {
283
+ console.log(chalk.yellow(' 🔧 Güncelleme başlatılıyor...'));
284
+ console.log(chalk.gray(' Lütfen manuel güncelleyin: npm install -g natureco-cli@latest'));
285
+ }
286
+ }
287
+ } else {
288
+ console.log(chalk.gray('⚪ Versiyon:'), chalk.white('Kontrol edilemedi'));
289
+ results.push({ status: 'info', message: 'Versiyon kontrol edilemedi' });
290
+ }
291
+ } catch (err) {
292
+ console.log(chalk.gray('⚪ Versiyon:'), chalk.white('Kontrol edilemedi'));
293
+ results.push({ status: 'info', message: 'Versiyon kontrol edilemedi' });
294
+ }
295
+
296
+ // Özet
297
+ console.log(chalk.cyan('\n────────────────────────────────'));
298
+
299
+ // Kritik kontroller için durum
300
+ const criticalPercentage = criticalTotal > 0 ? Math.round((criticalPassed / criticalTotal) * 100) : 100;
301
+ let statusColor = chalk.green;
302
+ let statusText = 'Mükemmel';
303
+
304
+ if (criticalPercentage < 75) {
305
+ statusColor = chalk.red;
306
+ statusText = 'Kritik';
307
+ } else if (criticalPercentage < 100) {
308
+ statusColor = chalk.yellow;
309
+ statusText = 'Dikkat';
310
+ } else if (passed < total) {
311
+ statusColor = chalk.cyan;
312
+ statusText = 'İyi';
313
+ }
314
+
315
+ console.log(statusColor.bold(`Sistem Durumu: ${statusText}`));
316
+ console.log(chalk.white(`${passed}/${total} kontrol geçti`));
317
+ console.log(chalk.gray(`Kritik: ${criticalPassed}/${criticalTotal}`));
318
+
319
+ // Sorunlar
320
+ const errors = results.filter(r => r.status === 'error');
321
+ const warnings = results.filter(r => r.status === 'warning');
322
+
323
+ if (errors.length > 0) {
324
+ console.log(chalk.red(`\n❌ ${errors.length} hata bulundu`));
325
+ }
326
+
327
+ if (warnings.length > 0) {
328
+ console.log(chalk.yellow(`⚠️ ${warnings.length} uyarı bulundu`));
329
+ }
330
+
331
+ if (!shouldFix && (errors.length > 0 || warnings.length > 0)) {
332
+ console.log(chalk.gray('\nOtomatik onarım için: natureco doctor --fix'));
333
+ }
334
+
335
+ console.log(chalk.cyan('────────────────────────────────\n'));
336
+ }
337
+
338
+ function checkPort(port) {
339
+ return new Promise((resolve) => {
340
+ const socket = new net.Socket();
341
+
342
+ socket.setTimeout(1000);
343
+
344
+ socket.on('connect', () => {
345
+ socket.destroy();
346
+ resolve(true);
347
+ });
348
+
349
+ socket.on('timeout', () => {
350
+ socket.destroy();
351
+ resolve(false);
352
+ });
353
+
354
+ socket.on('error', () => {
355
+ resolve(false);
356
+ });
357
+
358
+ socket.connect(port, '127.0.0.1');
359
+ });
360
+ }
361
+
362
+ module.exports = doctor;