natureco-cli 2.23.28 → 2.23.29

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/bin/natureco.js CHANGED
@@ -13,6 +13,12 @@ const init = require('../src/commands/init');
13
13
  const config = require('../src/commands/config');
14
14
  const ask = require('../src/commands/ask');
15
15
  const run = require('../src/commands/run');
16
+ const signal = require('../src/commands/signal');
17
+ const irc = require('../src/commands/irc');
18
+ const mattermost = require('../src/commands/mattermost');
19
+ const imessage = require('../src/commands/imessage');
20
+ const sms = require('../src/commands/sms');
21
+ const webhooks = require('../src/commands/webhooks');
16
22
 
17
23
  const program = new Command();
18
24
 
@@ -42,6 +48,12 @@ ${chalk.yellow('🔌 Entegrasyonlar')}
42
48
  ${chalk.cyan('whatsapp')} WhatsApp bağlantısı
43
49
  ${chalk.cyan('discord')} Discord bağlantısı
44
50
  ${chalk.cyan('slack')} Slack bağlantısı
51
+ ${chalk.cyan('signal')} Signal bağlantısı
52
+ ${chalk.cyan('irc')} IRC bağlantısı
53
+ ${chalk.cyan('mattermost')} Mattermost bağlantısı
54
+ ${chalk.cyan('imessage')} iMessage bağlantısı
55
+ ${chalk.cyan('sms')} SMS (Twilio) bağlantısı
56
+ ${chalk.cyan('webhooks')} Webhook yönetimi
45
57
  ${chalk.cyan('gateway')} WebSocket gateway
46
58
 
47
59
  ${chalk.yellow('🛠️ Geliştirici Araçları')}
@@ -123,7 +135,7 @@ program
123
135
 
124
136
  program
125
137
  .command('config <action> [key] [value...]')
126
- .description('Manage configuration (get|set|list)')
138
+ .description('Manage configuration (get|set|list|backups|restore)')
127
139
  .action((action, key, value) => config([action, key, ...(value || [])]));
128
140
 
129
141
  program
@@ -232,10 +244,10 @@ program
232
244
 
233
245
  program
234
246
  .command('tasks [action] [params...]')
235
- .description('Manage background tasks (list|show)')
247
+ .description('Manage background tasks (list|show|cancel|audit|maintenance|flow|summary)')
236
248
  .action((action, params) => {
237
249
  const tasksCmd = require('../src/commands/tasks');
238
- tasksCmd(action, ...(params || []));
250
+ tasksCmd([action, ...(params || [])]);
239
251
  });
240
252
 
241
253
  program
@@ -286,6 +298,54 @@ program
286
298
  telegramCmd(action, chatId);
287
299
  });
288
300
 
301
+ program
302
+ .command('signal <action>')
303
+ .description('Signal integration (connect|disconnect|status)')
304
+ .action((action) => {
305
+ const signalCmd = require('../src/commands/signal');
306
+ signalCmd(action);
307
+ });
308
+
309
+ program
310
+ .command('irc <action>')
311
+ .description('IRC integration (connect|disconnect|status)')
312
+ .action((action) => {
313
+ const ircCmd = require('../src/commands/irc');
314
+ ircCmd(action);
315
+ });
316
+
317
+ program
318
+ .command('mattermost <action>')
319
+ .description('Mattermost integration (connect|disconnect|status)')
320
+ .action((action) => {
321
+ const mattermostCmd = require('../src/commands/mattermost');
322
+ mattermostCmd(action);
323
+ });
324
+
325
+ program
326
+ .command('imessage <action>')
327
+ .description('iMessage integration (connect|disconnect|status)')
328
+ .action((action) => {
329
+ const imessageCmd = require('../src/commands/imessage');
330
+ imessageCmd(action);
331
+ });
332
+
333
+ program
334
+ .command('sms <action>')
335
+ .description('SMS/Twilio integration (connect|disconnect|status)')
336
+ .action((action) => {
337
+ const smsCmd = require('../src/commands/sms');
338
+ smsCmd(action);
339
+ });
340
+
341
+ program
342
+ .command('webhooks <action>')
343
+ .description('Webhook management (connect|disconnect|status|list)')
344
+ .action((action) => {
345
+ const webhooksCmd = require('../src/commands/webhooks');
346
+ webhooksCmd(action);
347
+ });
348
+
289
349
  program
290
350
  .command('message <action>')
291
351
  .description('Send messages directly (send)')
@@ -332,10 +392,12 @@ program
332
392
 
333
393
  program
334
394
  .command('models [action] [params...]')
335
- .description('Manage AI models (list|set|scan|aliases)')
395
+ .description('Manage AI models (list|set|scan|aliases|fallbacks)')
396
+ .allowUnknownOption()
336
397
  .action((action, params) => {
337
398
  const modelsCmd = require('../src/commands/models');
338
- modelsCmd([action, ...(params || [])]);
399
+ const allArgs = process.argv.slice(process.argv.indexOf('models') + 1);
400
+ modelsCmd(allArgs);
339
401
  });
340
402
 
341
403
  program
@@ -396,7 +458,7 @@ program
396
458
 
397
459
  program
398
460
  .command('plugins [action] [params...]')
399
- .description('Manage plugins (list|install|enable|disable|info|doctor)')
461
+ .description('Manage plugins (list|install|uninstall|enable|disable|info|update|search|doctor|registry)')
400
462
  .action((action, params) => {
401
463
  const pluginsCmd = require('../src/commands/plugins');
402
464
  pluginsCmd([action, ...(params || [])]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "2.23.28",
3
+ "version": "2.23.29",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "bin": {
6
6
  "natureco": "bin/natureco.js"
@@ -11,7 +11,10 @@
11
11
  "skills/"
12
12
  ],
13
13
  "scripts": {
14
- "test": "node bin/natureco.js help"
14
+ "test": "node bin/natureco.js help",
15
+ "test:unit": "vitest run",
16
+ "test:watch": "vitest watch",
17
+ "test:coverage": "vitest run --coverage"
15
18
  },
16
19
  "keywords": [
17
20
  "natureco",
@@ -27,17 +30,18 @@
27
30
  "@whiskeysockets/baileys": "^7.0.0-rc10",
28
31
  "chalk": "^4.1.2",
29
32
  "commander": "^11.1.0",
30
- "inquirer": "^13.4.3",
33
+ "json5": "^2.2.3",
31
34
  "node-cron": "^4.2.1",
32
35
  "node-telegram-bot-api": "^0.67.0",
33
- "ora": "^9.4.0",
34
36
  "pino": "^8.21.0",
35
37
  "qrcode-terminal": "^0.12.0",
36
38
  "semver": "^7.8.1",
37
39
  "ws": "^8.20.0"
38
40
  },
39
41
  "engines": {
40
- "node": ">=16.0.0"
42
+ "node": ">=18.0.0"
41
43
  },
42
- "//": "TODO: form-data güvenlik açığı — node-telegram-bot-api güncelleme gerektirir"
44
+ "devDependencies": {
45
+ "vitest": "^4.1.9"
46
+ }
43
47
  }
@@ -61,6 +61,66 @@ function listChannels() {
61
61
  });
62
62
  }
63
63
 
64
+ if (config.signalBotId) {
65
+ channels.push({
66
+ name: 'Signal',
67
+ icon: '🔒',
68
+ status: 'bağlı',
69
+ detail: `hesap: ${config.signalAccount || 'bağlı'}`,
70
+ chats: 0,
71
+ });
72
+ }
73
+
74
+ if (config.ircBotId) {
75
+ channels.push({
76
+ name: 'IRC',
77
+ icon: '💬',
78
+ status: 'bağlı',
79
+ detail: `${config.ircHost}:${config.ircPort} (${config.ircNick})`,
80
+ chats: 0,
81
+ });
82
+ }
83
+
84
+ if (config.mattermostBotId) {
85
+ channels.push({
86
+ name: 'Mattermost',
87
+ icon: '📢',
88
+ status: 'bağlı',
89
+ detail: `sunucu: ${config.mattermostBaseUrl || 'bağlı'}`,
90
+ chats: 0,
91
+ });
92
+ }
93
+
94
+ if (config.imessageBotId) {
95
+ channels.push({
96
+ name: 'iMessage',
97
+ icon: '💬',
98
+ status: 'bağlı',
99
+ detail: 'macOS bridge',
100
+ chats: 0,
101
+ });
102
+ }
103
+
104
+ if (config.smsBotId) {
105
+ channels.push({
106
+ name: 'SMS (Twilio)',
107
+ icon: '📨',
108
+ status: 'bağlı',
109
+ detail: `numara: ${config.smsFromNumber || 'bağlı'}`,
110
+ chats: 0,
111
+ });
112
+ }
113
+
114
+ if (config.webhooks && config.webhooks.length > 0) {
115
+ channels.push({
116
+ name: 'Webhooks',
117
+ icon: '🔗',
118
+ status: 'bağlı',
119
+ detail: `${config.webhooks.length} route`,
120
+ chats: 0,
121
+ });
122
+ }
123
+
64
124
  console.log('');
65
125
  console.log(chalk.gray(' ' + '─'.repeat(48)));
66
126
  console.log(chalk.cyan.bold('\n Kanallar\n'));
@@ -71,7 +131,13 @@ function listChannels() {
71
131
  console.log(chalk.cyan(' natureco telegram connect'));
72
132
  console.log(chalk.cyan(' natureco whatsapp connect'));
73
133
  console.log(chalk.cyan(' natureco discord connect'));
74
- console.log(chalk.cyan(' natureco slack connect\n'));
134
+ console.log(chalk.cyan(' natureco slack connect'));
135
+ console.log(chalk.cyan(' natureco signal connect'));
136
+ console.log(chalk.cyan(' natureco irc connect'));
137
+ console.log(chalk.cyan(' natureco mattermost connect'));
138
+ console.log(chalk.cyan(' natureco imessage connect'));
139
+ console.log(chalk.cyan(' natureco sms connect'));
140
+ console.log(chalk.cyan(' natureco webhooks connect\n'));
75
141
  return;
76
142
  }
77
143
 
@@ -98,6 +164,12 @@ function statusChannels() {
98
164
  { name: 'WhatsApp', ok: !!config.whatsappConnected },
99
165
  { name: 'Discord', ok: !!config.discordToken },
100
166
  { name: 'Slack', ok: !!config.slackToken },
167
+ { name: 'Signal', ok: !!config.signalBotId },
168
+ { name: 'IRC', ok: !!config.ircBotId },
169
+ { name: 'Mattermost', ok: !!config.mattermostBotId },
170
+ { name: 'iMessage', ok: !!config.imessageBotId },
171
+ { name: 'SMS', ok: !!config.smsBotId },
172
+ { name: 'Webhooks', ok: !!(config.webhooks && config.webhooks.length > 0) },
101
173
  ];
102
174
 
103
175
  checks.forEach(ch => {
@@ -110,13 +182,13 @@ function statusChannels() {
110
182
  const connected = checks.filter(c => c.ok).length;
111
183
  console.log('');
112
184
  console.log(chalk.gray(' ' + '─'.repeat(48)));
113
- console.log(chalk.gray(` ${connected}/4 kanal aktif\n`));
185
+ console.log(chalk.gray(` ${connected}/${checks.length} kanal aktif\n`));
114
186
  }
115
187
 
116
188
  function removeChannel(channel) {
117
189
  if (!channel) {
118
190
  console.log(chalk.red('\n ❌ Kanal adı gerekli\n'));
119
- console.log(chalk.gray(' Kullanım: natureco channels remove <telegram|whatsapp|discord|slack>\n'));
191
+ console.log(chalk.gray(' Kullanım: natureco channels remove <telegram|whatsapp|discord|slack|signal|irc|mattermost|imessage|sms|webhooks>\n'));
120
192
  process.exit(1);
121
193
  }
122
194
 
@@ -128,7 +200,6 @@ function removeChannel(channel) {
128
200
  delete config.telegramBotId;
129
201
  delete config.telegramAllowedChats;
130
202
  } else if (ch === 'whatsapp') {
131
- // Session dosyalarını sil
132
203
  if (config.whatsappBotId) {
133
204
  const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
134
205
  if (fs.existsSync(sessionDir)) {
@@ -145,6 +216,25 @@ function removeChannel(channel) {
145
216
  } else if (ch === 'slack') {
146
217
  delete config.slackToken;
147
218
  delete config.slackBotId;
219
+ } else if (ch === 'signal') {
220
+ delete config.signalHttpUrl;
221
+ delete config.signalAccount;
222
+ delete config.signalDmPolicy;
223
+ delete config.signalBotId;
224
+ } else if (ch === 'irc') {
225
+ delete config.ircHost; delete config.ircPort; delete config.ircTls;
226
+ delete config.ircNick; delete config.ircUsername; delete config.ircPassword;
227
+ delete config.ircChannels; delete config.ircDmPolicy; delete config.ircBotId;
228
+ } else if (ch === 'mattermost') {
229
+ delete config.mattermostBaseUrl; delete config.mattermostToken;
230
+ delete config.mattermostDmPolicy; delete config.mattermostBotId;
231
+ } else if (ch === 'imessage') {
232
+ delete config.imessageCliPath; delete config.imessageDmPolicy; delete config.imessageBotId;
233
+ } else if (ch === 'sms') {
234
+ delete config.smsAccountSid; delete config.smsAuthToken; delete config.smsFromNumber;
235
+ delete config.smsPublicWebhookUrl; delete config.smsDmPolicy; delete config.smsBotId;
236
+ } else if (ch === 'webhooks') {
237
+ delete config.webhooks; delete config.webhookEnabled;
148
238
  } else {
149
239
  console.log(chalk.red(`\n ❌ Bilinmeyen kanal: ${channel}\n`));
150
240
  process.exit(1);
@@ -13,8 +13,8 @@ const { getMemoryPrompt, extractMemoryFromMessage, loadMemory, clearMemory, addM
13
13
  const { getCommands, getCommandContent } = require('../utils/commands');
14
14
  const { runHooks } = require('../utils/hooks');
15
15
  const { createSession, loadSession, getLatestSession, addMessageToSession, loadLastSession, listSessions, saveSession } = require('../utils/sessions');
16
- const { getToolDefinitions, executeToolCalls, getSessionStats, resetSessionStats } = require('../utils/tool-runner');
17
- const { extractToolCalls } = require('../utils/tool-adapter');
16
+ const { NatureCoError, ApiError, handleError } = require('../utils/errors');
17
+ const { getToolDefinitions, getSessionStats, resetSessionStats } = require('../utils/tool-runner');
18
18
 
19
19
  // ── ASCII Logo ────────────────────────────────────────────────────────────────
20
20
  const ASCII_LOGO = [
@@ -80,10 +80,9 @@ async function chat(botName, options = {}) {
80
80
  // ── Bot seçimi ──────────────────────────────────────────────────────────────
81
81
  let botList;
82
82
  try {
83
- botList = await getBots(apiKey || config.providerApiKey || '');
83
+ botList = await getBots(apiKey ?? config.providerApiKey ?? '');
84
84
  } catch (err) {
85
- console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
86
- process.exit(1);
85
+ handleError(err, { prefix: '❌ Error', exit: true });
87
86
  }
88
87
 
89
88
  if (!botList?.bots?.length) {
@@ -311,7 +310,7 @@ async function chat(botName, options = {}) {
311
310
  console.log();
312
311
  addToHistory(bot.id, userMessage, reply, conversationId);
313
312
  addMessageToSession(bot.id, session.id, userMessage, reply);
314
- } catch (e) { stopLoading(); console.log(chalk.red(`Error: ${e.message}`)); console.log(); }
313
+ } catch (e) { stopLoading(); handleError(e, { prefix: 'Error', exit: false }); console.log(); }
315
314
  } else {
316
315
  console.log(chalk.red(`Bilinmeyen komut: /${cmd}`));
317
316
  console.log();
@@ -336,27 +335,12 @@ async function chat(botName, options = {}) {
336
335
 
337
336
  try {
338
337
  const toolDefinitions = getToolDefinitions();
339
- let response = await _sendMessage(apiKey || config.providerApiKey, bot.id, userMessage, conversationId, systemPrompt, toolDefinitions, options);
338
+ let response = await _sendMessage(apiKey ?? config.providerApiKey, bot.id, userMessage, conversationId, systemPrompt, toolDefinitions, options);
340
339
  stopLoading();
341
340
 
342
- if (response.conversation_id) conversationId = response.conversation_id;
343
-
344
- // Tool loop — api.js zaten tool loop yapıyor, bu loop çalışmamalı
345
- let iter = 0;
346
- while (iter < 5) {
347
- const toolCalls = extractToolCalls(response);
348
- if (!toolCalls?.length) break;
349
- console.log(chalk.yellow(`🔧 ${toolCalls.length} tool çalıştırılıyor...`));
350
- const toolResults = await executeToolCalls(toolCalls);
351
- const toolMsg = toolResults.map(tr => `Tool: ${tr.name}\nResult: ${tr.result.success ? (tr.result.output || '') : tr.result.error}`).join('\n\n');
352
- startLoading();
353
- response = await _sendMessage(apiKey || config.providerApiKey, bot.id, toolMsg, conversationId, systemPrompt, toolDefinitions, options);
354
- stopLoading();
355
- if (response.conversation_id) conversationId = response.conversation_id;
356
- iter++;
357
- }
341
+ if (response?.conversation_id) conversationId = response.conversation_id;
358
342
 
359
- let botReply = response.reply || response.message || 'No response';
343
+ let botReply = response?.reply ?? response?.message ?? 'No response';
360
344
  botReply = await runHooks('post-message', botReply, { botId: bot.id, botName: bot.name });
361
345
 
362
346
  console.log(chalk.cyan(`${displayBotName} `) + botReply);
@@ -370,7 +354,9 @@ async function chat(botName, options = {}) {
370
354
 
371
355
  } catch (err) {
372
356
  stopLoading();
373
- const errMsg = err.message.split('"message":"')[1]?.split('"')[0] || err.message;
357
+ const errMsg = err instanceof NatureCoError
358
+ ? err.message
359
+ : (err?.message?.split('"message":"')[1]?.split('"')[0] ?? err?.message ?? 'Unknown error');
374
360
  console.log(chalk.red(`Error: ${errMsg}`));
375
361
  console.log();
376
362
  }
@@ -1,68 +1,111 @@
1
- const chalk = require('chalk');
2
- const { getConfig, setConfigValue, getAllConfig } = require('../utils/config');
3
-
4
- function config(args) {
5
- const [action, key, ...valueParts] = args;
6
-
7
- if (!action) {
8
- console.log(chalk.red('\n❌ Kullanım: natureco config <get|set|list> [key] [value]\n'));
9
- process.exit(1);
10
- }
11
-
12
- if (action === 'list') {
13
- const cfg = getAllConfig();
14
- console.log(chalk.green.bold('\n╭─ Config ─╮\n'));
15
- console.log(JSON.stringify(cfg, null, 2));
16
- console.log('');
17
- return;
18
- }
19
-
20
- if (action === 'get') {
21
- if (!key) {
22
- console.log(chalk.red('\n❌ Key belirtilmedi.\n'));
23
- process.exit(1);
24
- }
25
- const cfg = getConfig();
26
- const keys = key.split('.');
27
- let value = cfg;
28
- for (const k of keys) {
29
- value = value?.[k];
30
- }
31
- if (value === undefined) {
32
- console.log(chalk.gray(`\n${key}: (tanımlı değil)\n`));
33
- } else {
34
- console.log(chalk.cyan(`\n${key}:`), chalk.white(JSON.stringify(value, null, 2)));
35
- console.log('');
36
- }
37
- return;
38
- }
39
-
40
- if (action === 'set') {
41
- if (!key) {
42
- console.log(chalk.red('\n❌ Key belirtilmedi.\n'));
43
- process.exit(1);
44
- }
45
- if (valueParts.length === 0) {
46
- console.log(chalk.red('\n❌ Value belirtilmedi.\n'));
47
- process.exit(1);
48
- }
49
- const value = valueParts.join(' ');
50
-
51
- // JSON parse dene
52
- let parsedValue = value;
53
- try {
54
- parsedValue = JSON.parse(value);
55
- } catch {
56
- // String olarak kalsın
57
- }
58
-
59
- setConfigValue(key, parsedValue);
60
- console.log(chalk.green(`\n✅ ${key} = ${JSON.stringify(parsedValue)}\n`));
61
- return;
62
- }
63
-
64
- console.log(chalk.red(`\n Geçersiz action: ${action}\n`));
65
- process.exit(1);
66
- }
67
-
68
- module.exports = config;
1
+ const chalk = require('chalk');
2
+ const path = require('path');
3
+ const { getConfig, setConfigValue, getAllConfig, listBackups, restoreConfig, CONFIG_BACKUP_DIR } = require('../utils/config');
4
+
5
+ function config(args) {
6
+ const [action, key, ...valueParts] = args;
7
+
8
+ if (!action) {
9
+ console.log(chalk.red('\n❌ Kullanım: natureco config <get|set|list|backups|restore> [key] [value]\n'));
10
+ process.exit(1);
11
+ }
12
+
13
+ if (action === 'list') {
14
+ const cfg = getAllConfig();
15
+ console.log(chalk.green.bold('\n╭─ Config ─╮\n'));
16
+ console.log(JSON.stringify(cfg, null, 2));
17
+ console.log('');
18
+ return;
19
+ }
20
+
21
+ if (action === 'get') {
22
+ if (!key) {
23
+ console.log(chalk.red('\n❌ Key belirtilmedi.\n'));
24
+ process.exit(1);
25
+ }
26
+ const cfg = getConfig();
27
+ const keys = key.split('.');
28
+ let value = cfg;
29
+ for (const k of keys) {
30
+ value = value?.[k];
31
+ }
32
+ if (value === undefined) {
33
+ console.log(chalk.gray(`\n${key}: (tanımlı değil)\n`));
34
+ } else {
35
+ console.log(chalk.cyan(`\n${key}:`), chalk.white(JSON.stringify(value, null, 2)));
36
+ console.log('');
37
+ }
38
+ return;
39
+ }
40
+
41
+ if (action === 'set') {
42
+ if (!key) {
43
+ console.log(chalk.red('\n❌ Key belirtilmedi.\n'));
44
+ process.exit(1);
45
+ }
46
+ if (valueParts.length === 0) {
47
+ console.log(chalk.red('\n❌ Value belirtilmedi.\n'));
48
+ process.exit(1);
49
+ }
50
+ const value = valueParts.join(' ');
51
+
52
+ let parsedValue = value;
53
+ try {
54
+ parsedValue = JSON.parse(value);
55
+ } catch {}
56
+
57
+ setConfigValue(key, parsedValue);
58
+ console.log(chalk.green(`\n✅ ${key} = ${JSON.stringify(parsedValue)}\n`));
59
+ return;
60
+ }
61
+
62
+ if (action === 'backups' || action === 'backup') {
63
+ const backups = listBackups();
64
+ console.log(chalk.cyan.bold('\n Config Yedekleri\n'));
65
+ if (backups.length === 0) {
66
+ console.log(chalk.gray(' Henüz yedek alınmamış.\n'));
67
+ return;
68
+ }
69
+ backups.forEach((f, i) => {
70
+ const ts = f.replace(/^config-|\.json$/g, '').replace(/T/, ' ').replace(/-/g, ':').replace(/:[^:]*$/, '');
71
+ console.log(chalk.white(` ${i + 1}. ${ts}`));
72
+ console.log(chalk.gray(` ${path.join(CONFIG_BACKUP_DIR, f)}`));
73
+ });
74
+ console.log(chalk.gray(`\n Geri yüklemek için: natureco config restore <dosya-adı>`));
75
+ console.log(chalk.gray(` Örnek: natureco config restore ${backups[0] || 'config-....json'}\n`));
76
+ return;
77
+ }
78
+
79
+ if (action === 'restore') {
80
+ const backupId = key;
81
+ if (!backupId) {
82
+ const backups = listBackups();
83
+ if (backups.length === 0) {
84
+ console.log(chalk.red('\n❌ Geri yüklenecek yedek bulunamadı.\n'));
85
+ process.exit(1);
86
+ }
87
+ console.log(chalk.cyan.bold('\n Geri Yükleme\n'));
88
+ console.log(chalk.gray(' En son yedek: ') + chalk.white(backups[0]));
89
+ console.log('');
90
+ console.log(chalk.gray(' Kullanım: ') + chalk.cyan(`natureco config restore ${backups[0]}`));
91
+ console.log(chalk.gray(' Yedekleri listelemek için: ') + chalk.cyan('natureco config backups\n'));
92
+ return;
93
+ }
94
+
95
+ try {
96
+ const result = restoreConfig(backupId);
97
+ console.log(chalk.green(`\n✅ Config geri yüklendi: ${result.timestamp}\n`));
98
+ console.log(chalk.gray(` Kaynak: ${result.path}\n`));
99
+ } catch (err) {
100
+ console.log(chalk.red(`\n❌ Geri yükleme başarısız: ${err.message}\n`));
101
+ process.exit(1);
102
+ }
103
+ return;
104
+ }
105
+
106
+ console.log(chalk.red(`\n❌ Geçersiz action: ${action}\n`));
107
+ console.log(chalk.gray(' Kullanım: natureco config <get|set|list|backups|restore> [key] [value]\n'));
108
+ process.exit(1);
109
+ }
110
+
111
+ module.exports = config;