natureco-cli 2.5.1 → 2.6.1

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
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  const { Command } = require('commander');
4
4
  const chalk = require('chalk');
@@ -185,6 +185,14 @@ program
185
185
  whatsappCmd(action);
186
186
  });
187
187
 
188
+ program
189
+ .command('telegram <action>')
190
+ .description('Telegram integration (connect|disconnect|status)')
191
+ .action((action) => {
192
+ const telegramCmd = require('../src/commands/telegram');
193
+ telegramCmd(action);
194
+ });
195
+
188
196
  program
189
197
  .command('dashboard [action]')
190
198
  .description('Web Control UI (start|stop|status)')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "2.5.1",
3
+ "version": "2.6.1",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "main": "bin/natureco.js",
6
6
  "bin": {
@@ -32,6 +32,7 @@
32
32
  "eventsource": "^2.0.2",
33
33
  "inquirer": "^8.2.7",
34
34
  "node-cron": "^2.0.3",
35
+ "node-telegram-bot-api": "^0.65.1",
35
36
  "ora": "^5.4.1",
36
37
  "pino": "^8.21.0",
37
38
  "qrcode-terminal": "^0.12.0",
@@ -211,7 +211,7 @@ body::before{
211
211
  <div class="header-bot-name" id="header-bot-name">Nature Bot</div>
212
212
  <div class="header-bot-model" id="header-bot-model">NatureCo</div>
213
213
  </div>
214
- <div class="version-badge" id="version-badge">v2.5.1</div>
214
+ <div class="version-badge" id="version-badge">v2.6.1</div>
215
215
  </div>
216
216
  <div class="messages" id="messages"></div>
217
217
  <div class="input-area">
@@ -341,7 +341,7 @@ function dashboard(action) {
341
341
  apiKey: cfg.apiKey,
342
342
  defaultBot: cfg.defaultBot,
343
343
  defaultBotId: cfg.defaultBotId,
344
- version: 'v2.5.1',
344
+ version: 'v2.6.1',
345
345
  bots: cfg.bots || [],
346
346
  telegramToken: cfg.telegramToken || null,
347
347
  whatsappConnected: cfg.whatsappConnected || false,
@@ -128,7 +128,7 @@ async function startGateway() {
128
128
 
129
129
  async function runGatewayWorker() {
130
130
  // This runs in the background
131
- log('gateway', 'Starting NatureCo Gateway v2.5.1...', 'green');
131
+ log('gateway', 'Starting NatureCo Gateway v2.6.1...', 'green');
132
132
 
133
133
  // Load config
134
134
  const { getConfig } = require('../utils/config');
@@ -154,6 +154,14 @@ async function runGatewayWorker() {
154
154
  log('whatsapp', 'not configured, skipping', 'gray');
155
155
  }
156
156
 
157
+ // Start Telegram if configured
158
+ if (config.telegramToken && config.telegramBotId) {
159
+ log('telegram', 'starting bot...', 'cyan');
160
+ startTelegramProvider(config);
161
+ } else {
162
+ log('telegram', 'not configured, skipping', 'gray');
163
+ }
164
+
157
165
  // Health check every 60 seconds
158
166
  setInterval(() => {
159
167
  log('gateway', 'health check: OK', 'gray');
@@ -348,6 +356,101 @@ async function startWhatsAppProvider(sessionDir, config) {
348
356
  }
349
357
  }
350
358
 
359
+ async function startTelegramProvider(config) {
360
+ try {
361
+ // Lazy load node-telegram-bot-api
362
+ let TelegramBot;
363
+ try {
364
+ TelegramBot = require('node-telegram-bot-api');
365
+ } catch (err) {
366
+ log('telegram', 'node-telegram-bot-api not installed', 'red');
367
+ log('telegram', 'Install with: npm install -g node-telegram-bot-api', 'yellow');
368
+ return;
369
+ }
370
+
371
+ const bot = new TelegramBot(config.telegramToken, { polling: true });
372
+
373
+ log('telegram', 'Bot started successfully', 'green');
374
+ log('telegram', 'Listening for messages...', 'cyan');
375
+
376
+ bot.on('message', async (msg) => {
377
+ const chatId = msg.chat.id;
378
+ const messageText = msg.text;
379
+
380
+ if (!messageText) {
381
+ log('telegram', `Message without text from chat ${chatId}`, 'gray');
382
+ return;
383
+ }
384
+
385
+ // Access control - check allowed chats
386
+ const allowedChats = config.telegramAllowedChats || [];
387
+ if (allowedChats.length > 0 && !allowedChats.includes(String(chatId))) {
388
+ log('telegram', `Blocked message from chat ${chatId} (not in allowed list)`, 'yellow');
389
+ return;
390
+ }
391
+
392
+ log('telegram', `Inbound message from chat ${chatId} (${messageText.length} chars)`, 'cyan');
393
+
394
+ try {
395
+ const { sendMessage } = require('../utils/api');
396
+ const { getMemoryPrompt, extractMemoryFromMessage, addMemoryEntry } = require('../utils/memory');
397
+
398
+ log('telegram', 'Sending to AI provider...', 'cyan');
399
+
400
+ // Use Telegram-specific conversation ID for persistent history
401
+ const conversationId = `telegram_${chatId}`;
402
+
403
+ // Use same botId as terminal for shared memory
404
+ const botId = 'universal-provider';
405
+ const memoryPrompt = getMemoryPrompt(botId);
406
+
407
+ // Telegram system prompt with memory
408
+ let systemPrompt = `You are a helpful Telegram assistant. Keep responses concise and friendly. Use emojis when appropriate. If users ask for file operations or system commands, politely explain that those features are available in the terminal version.`;
409
+
410
+ if (memoryPrompt) {
411
+ systemPrompt += '\n\n' + memoryPrompt;
412
+ }
413
+
414
+ const response = await sendMessage(null, null, messageText, conversationId, systemPrompt);
415
+ const reply = response?.reply || response?.message || '';
416
+
417
+ if (reply) {
418
+ log('telegram', 'Sending reply...', 'cyan');
419
+
420
+ await bot.sendMessage(chatId, reply);
421
+
422
+ log('telegram', `Reply sent (${reply.length} chars)`, 'green');
423
+
424
+ // Extract and save memory from user message
425
+ const memoryEntries = extractMemoryFromMessage(messageText);
426
+ for (const entry of memoryEntries) {
427
+ addMemoryEntry(botId, entry.key, entry.value);
428
+ log('telegram', `Memory saved: ${entry.key} = ${entry.value}`, 'gray');
429
+ }
430
+ } else {
431
+ log('telegram', 'No reply from provider', 'yellow');
432
+ }
433
+ } catch (err) {
434
+ log('telegram', `Provider error: ${err.message}`, 'red');
435
+
436
+ // Send error message to user
437
+ try {
438
+ await bot.sendMessage(chatId, '❌ Bir hata oluştu. Lütfen tekrar deneyin.');
439
+ } catch (sendErr) {
440
+ log('telegram', `Failed to send error message: ${sendErr.message}`, 'red');
441
+ }
442
+ }
443
+ });
444
+
445
+ bot.on('polling_error', (error) => {
446
+ log('telegram', `Polling error: ${error.message}`, 'red');
447
+ });
448
+
449
+ } catch (err) {
450
+ log('telegram', `Failed to start: ${err.message}`, 'red');
451
+ }
452
+ }
453
+
351
454
  function stopGateway() {
352
455
  if (!fs.existsSync(PID_FILE)) {
353
456
  console.log(chalk.gray('\n⚠️ Gateway not running\n'));
@@ -0,0 +1,202 @@
1
+ const chalk = require('chalk');
2
+ const inquirer = require('inquirer');
3
+ const { getConfig, saveConfig } = require('../utils/config');
4
+
5
+ async function telegram(action) {
6
+ if (!action || action === 'connect') {
7
+ return connectTelegram();
8
+ }
9
+
10
+ if (action === 'disconnect') {
11
+ return disconnectTelegram();
12
+ }
13
+
14
+ if (action === 'status') {
15
+ return statusTelegram();
16
+ }
17
+
18
+ if (action === 'allow') {
19
+ const chatId = process.argv[4];
20
+ if (!chatId) {
21
+ console.log(chalk.red('\n❌ Chat ID belirtmelisiniz\n'));
22
+ console.log(chalk.gray('Kullanım: natureco telegram allow <chatId>\n'));
23
+ process.exit(1);
24
+ }
25
+ return allowChat(chatId);
26
+ }
27
+
28
+ console.log(chalk.red('\n❌ Unknown action\n'));
29
+ console.log(chalk.gray('Available actions: connect, disconnect, status, allow\n'));
30
+ process.exit(1);
31
+ }
32
+
33
+ async function connectTelegram() {
34
+ const config = getConfig();
35
+
36
+ if (!config.providerUrl) {
37
+ console.log(chalk.red('\n❌ Setup yapılmamış. Önce "natureco setup" çalıştırın.\n'));
38
+ process.exit(1);
39
+ }
40
+
41
+ console.log(chalk.yellow('\n⏳ Telegram bot bağlantısı hazırlanıyor...\n'));
42
+ console.log(chalk.gray('Telegram bot token almak için:'));
43
+ console.log(chalk.gray('1. Telegram\'da @BotFather\'ı aç'));
44
+ console.log(chalk.gray('2. /newbot komutunu gönder'));
45
+ console.log(chalk.gray('3. Bot adı ve kullanıcı adı belirle'));
46
+ console.log(chalk.gray('4. Aldığın token\'ı buraya gir\n'));
47
+
48
+ process.stdin.resume();
49
+
50
+ const answers = await inquirer.prompt([
51
+ {
52
+ type: 'input',
53
+ name: 'token',
54
+ message: 'Telegram bot token:',
55
+ validate: (val) => {
56
+ if (val.trim() === '') return 'Token boş olamaz';
57
+ if (!val.includes(':')) return 'Geçersiz token formatı (örnek: 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11)';
58
+ return true;
59
+ },
60
+ },
61
+ ]);
62
+
63
+ console.log(chalk.yellow('\n⏳ Telegram Chat ID almak için:\n'));
64
+ console.log(chalk.gray('1. Telegram\'da @userinfobot veya @getmyid_bot\'a mesaj gönder'));
65
+ console.log(chalk.gray('2. Sana chat ID\'ni söyleyecek'));
66
+ console.log(chalk.gray('3. Chat ID\'yi buraya gir (örnek: 123456789)\n'));
67
+
68
+ const chatIdAnswer = await inquirer.prompt([
69
+ {
70
+ type: 'input',
71
+ name: 'chatId',
72
+ message: 'Telegram Chat ID\'n:',
73
+ validate: (val) => {
74
+ if (val.trim() === '') return 'Chat ID boş olamaz';
75
+ if (!/^-?\d+$/.test(val.trim())) return 'Geçersiz Chat ID formatı (sadece rakam olmalı)';
76
+ return true;
77
+ },
78
+ },
79
+ ]);
80
+
81
+ // Telegram için bot ID oluştur (timestamp-based)
82
+ const botId = `telegram_${Date.now()}`;
83
+
84
+ console.log(chalk.yellow('\n⏳ Telegram bağlantısı kaydediliyor...\n'));
85
+
86
+ // Save to config (v2.x - no backend call)
87
+ config.telegramToken = answers.token.trim();
88
+ config.telegramBotId = botId;
89
+ config.telegramAllowedChats = [chatIdAnswer.chatId.trim()];
90
+ saveConfig(config);
91
+
92
+ console.log(chalk.green('✅ Telegram bot token kaydedildi!\n'));
93
+ console.log(chalk.cyan('Bot ID:'), chalk.white(botId));
94
+ console.log(chalk.cyan('Token:'), chalk.white(answers.token.slice(0, 20) + '...'));
95
+ console.log(chalk.cyan('İzin verilen chat:'), chalk.white(chatIdAnswer.chatId.trim()));
96
+ console.log(chalk.gray('\nSession kaydedildi: ~/.natureco/config.json'));
97
+ console.log(chalk.gray('Başka chat eklemek için: natureco telegram allow <chatId>'));
98
+
99
+ console.log(chalk.green('\n✅ Kurulum tamamlandı!\n'));
100
+ console.log(chalk.yellow('Gateway ile başlatmak için:'), chalk.cyan('natureco gateway start'));
101
+ console.log(chalk.gray('Gateway, Telegram botunu otomatik olarak başlatacak.\n'));
102
+ }
103
+
104
+ async function disconnectTelegram() {
105
+ const config = getConfig();
106
+
107
+ if (!config.telegramToken) {
108
+ console.log(chalk.gray('\n⚠️ No Telegram connection found\n'));
109
+ return;
110
+ }
111
+
112
+ process.stdin.resume();
113
+
114
+ const { confirm } = await inquirer.prompt([
115
+ {
116
+ type: 'confirm',
117
+ name: 'confirm',
118
+ message: 'Are you sure you want to disconnect Telegram?',
119
+ default: false,
120
+ },
121
+ ]);
122
+
123
+ if (!confirm) {
124
+ console.log(chalk.gray('\nCancelled\n'));
125
+ return;
126
+ }
127
+
128
+ // Remove from config
129
+ delete config.telegramToken;
130
+ delete config.telegramBotId;
131
+ delete config.telegramAllowedChats;
132
+ saveConfig(config);
133
+
134
+ console.log(chalk.green('\n✅ Telegram disconnected\n'));
135
+ console.log(chalk.gray('Note: The bot is still active on Telegram.'));
136
+ console.log(chalk.gray('You may need to manually delete it via @BotFather.\n'));
137
+ }
138
+
139
+ function statusTelegram() {
140
+ const config = getConfig();
141
+
142
+ if (!config.telegramToken) {
143
+ console.log(chalk.gray('\n⚠️ Telegram not connected\n'));
144
+ console.log(chalk.gray('Connect with: natureco telegram connect\n'));
145
+ return;
146
+ }
147
+
148
+ console.log(chalk.green('\n✅ Telegram connected\n'));
149
+ console.log(chalk.cyan('Token:'), chalk.white(config.telegramToken.slice(0, 20) + '...'));
150
+
151
+ if (config.telegramBotId) {
152
+ console.log(chalk.cyan('Bot ID:'), chalk.white(config.telegramBotId));
153
+ }
154
+
155
+ // Show allowed chats
156
+ const allowedChats = config.telegramAllowedChats || [];
157
+ if (allowedChats.length === 0) {
158
+ console.log(chalk.cyan('İzin listesi:'), chalk.gray('Boş (herkesten mesaj kabul edilir)'));
159
+ } else {
160
+ console.log(chalk.cyan('İzin listesi:'));
161
+ allowedChats.forEach(chatId => console.log(chalk.white(` - ${chatId}`)));
162
+ }
163
+
164
+ console.log(chalk.gray('\nDisconnect with: natureco telegram disconnect\n'));
165
+ }
166
+
167
+ function allowChat(chatId) {
168
+ const config = getConfig();
169
+
170
+ if (!config.telegramToken) {
171
+ console.log(chalk.red('\n❌ Telegram not connected\n'));
172
+ console.log(chalk.gray('Connect first with: natureco telegram connect\n'));
173
+ process.exit(1);
174
+ }
175
+
176
+ // Validate chat ID (should be numeric, can be negative for groups)
177
+ const normalized = chatId.trim();
178
+
179
+ if (!/^-?\d+$/.test(normalized)) {
180
+ console.log(chalk.red('\n❌ Geçersiz Chat ID formatı\n'));
181
+ console.log(chalk.gray('Chat ID sadece rakamlardan oluşmalı (örnek: 123456789 veya -123456789)\n'));
182
+ process.exit(1);
183
+ }
184
+
185
+ const allowedChats = config.telegramAllowedChats || [];
186
+
187
+ if (allowedChats.includes(normalized)) {
188
+ console.log(chalk.yellow('\n⚠️ Bu chat ID zaten izin listesinde\n'));
189
+ return;
190
+ }
191
+
192
+ allowedChats.push(normalized);
193
+ config.telegramAllowedChats = allowedChats;
194
+ saveConfig(config);
195
+
196
+ console.log(chalk.green('\n✅ Chat ID izin listesine eklendi\n'));
197
+ console.log(chalk.cyan('Chat ID:'), chalk.white(normalized));
198
+ console.log(chalk.cyan('Toplam:'), chalk.white(`${allowedChats.length} chat`));
199
+ console.log(chalk.gray('\nGateway\'i yeniden başlatın: natureco gateway stop && natureco gateway start\n'));
200
+ }
201
+
202
+ module.exports = telegram;
package/src/utils/api.js CHANGED
@@ -1,4 +1,4 @@
1
- // NatureCo CLI v2.5.1 - Universal LLM Provider Support
1
+ // NatureCo CLI v2.6.1 - Universal LLM Provider Support
2
2
  // Supports: OpenAI, Groq, Together, Fireworks, Perplexity, Mistral, DeepSeek, OpenRouter, Ollama, LM Studio, Anthropic
3
3
 
4
4
  const fs = require('fs');