natureco-cli 2.7.1 → 2.8.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
@@ -193,6 +193,24 @@ program
193
193
  telegramCmd(action);
194
194
  });
195
195
 
196
+ program
197
+ .command('message <action>')
198
+ .description('Send messages directly (send)')
199
+ .option('--target <target>', 'Target phone number or chat ID')
200
+ .option('--message <message>', 'Message to send')
201
+ .option('--channel <channel>', 'Channel: whatsapp or telegram (default: whatsapp)')
202
+ .action((action, options) => {
203
+ if (action === 'send') {
204
+ const messageCmd = require('../src/commands/message');
205
+ const args = process.argv.slice(3); // Get all args after 'message send'
206
+ messageCmd(args);
207
+ } else {
208
+ console.log(chalk.red('\n❌ Unknown action\n'));
209
+ console.log(chalk.gray('Available actions: send\n'));
210
+ process.exit(1);
211
+ }
212
+ });
213
+
196
214
  program
197
215
  .command('dashboard [action]')
198
216
  .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.7.1",
3
+ "version": "2.8.1",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "main": "bin/natureco.js",
6
6
  "bin": {
@@ -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.7.1</div>
214
+ <div class="version-badge" id="version-badge">v2.8.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.7.1',
344
+ version: 'v2.8.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.7.1...', 'green');
131
+ log('gateway', 'Starting NatureCo Gateway v2.8.1...', 'green');
132
132
 
133
133
  // Load config
134
134
  const { getConfig } = require('../utils/config');
@@ -139,6 +139,10 @@ async function runGatewayWorker() {
139
139
  process.exit(1);
140
140
  }
141
141
 
142
+ // Store provider instances globally for HTTP endpoint
143
+ global.whatsappSock = null;
144
+ global.telegramBot = null;
145
+
142
146
  // Start WhatsApp if configured
143
147
  if (config.whatsappConnected && config.whatsappBotId) {
144
148
  const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
@@ -162,6 +166,9 @@ async function runGatewayWorker() {
162
166
  log('telegram', 'not configured, skipping', 'gray');
163
167
  }
164
168
 
169
+ // Start HTTP server for message sending
170
+ startHttpServer();
171
+
165
172
  // Health check every 60 seconds
166
173
  setInterval(() => {
167
174
  log('gateway', 'health check: OK', 'gray');
@@ -236,6 +243,9 @@ async function startWhatsAppProvider(sessionDir, config) {
236
243
  log('whatsapp', `Connected successfully`, 'green');
237
244
  log('whatsapp', `Listening for inbound messages.`, 'cyan');
238
245
  log('whatsapp', `Phone: +${phone}`, 'gray');
246
+
247
+ // Store socket globally for HTTP endpoint
248
+ global.whatsappSock = sock;
239
249
  }
240
250
  });
241
251
 
@@ -446,11 +456,111 @@ async function startTelegramProvider(config) {
446
456
  log('telegram', `Polling error: ${error.message}`, 'red');
447
457
  });
448
458
 
459
+ // Store bot globally for HTTP endpoint
460
+ global.telegramBot = bot;
461
+
449
462
  } catch (err) {
450
463
  log('telegram', `Failed to start: ${err.message}`, 'red');
451
464
  }
452
465
  }
453
466
 
467
+ function startHttpServer() {
468
+ const http = require('http');
469
+
470
+ const server = http.createServer(async (req, res) => {
471
+ // CORS headers
472
+ res.setHeader('Access-Control-Allow-Origin', '*');
473
+ res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
474
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
475
+
476
+ if (req.method === 'OPTIONS') {
477
+ res.writeHead(200);
478
+ res.end();
479
+ return;
480
+ }
481
+
482
+ if (req.method === 'POST' && req.url === '/send') {
483
+ let body = '';
484
+
485
+ req.on('data', chunk => {
486
+ body += chunk.toString();
487
+ });
488
+
489
+ req.on('end', async () => {
490
+ try {
491
+ const { channel, target, message } = JSON.parse(body);
492
+
493
+ if (!channel || !target || !message) {
494
+ res.writeHead(400, { 'Content-Type': 'application/json' });
495
+ res.end(JSON.stringify({ error: 'Missing required fields: channel, target, message' }));
496
+ return;
497
+ }
498
+
499
+ if (channel === 'whatsapp') {
500
+ if (!global.whatsappSock) {
501
+ res.writeHead(503, { 'Content-Type': 'application/json' });
502
+ res.end(JSON.stringify({ error: 'WhatsApp not connected' }));
503
+ return;
504
+ }
505
+
506
+ const normalizedTarget = target.replace(/[^\d]/g, '');
507
+ const jid = `${normalizedTarget}@s.whatsapp.net`;
508
+
509
+ await global.whatsappSock.sendMessage(jid, { text: message });
510
+
511
+ log('http', `WhatsApp message sent to ${target}`, 'green');
512
+
513
+ res.writeHead(200, { 'Content-Type': 'application/json' });
514
+ res.end(JSON.stringify({ success: true, channel: 'whatsapp', target }));
515
+
516
+ } else if (channel === 'telegram') {
517
+ if (!global.telegramBot) {
518
+ res.writeHead(503, { 'Content-Type': 'application/json' });
519
+ res.end(JSON.stringify({ error: 'Telegram not connected' }));
520
+ return;
521
+ }
522
+
523
+ const chatId = target.trim();
524
+ if (!/^-?\d+$/.test(chatId)) {
525
+ res.writeHead(400, { 'Content-Type': 'application/json' });
526
+ res.end(JSON.stringify({ error: 'Invalid Telegram chat ID' }));
527
+ return;
528
+ }
529
+
530
+ await global.telegramBot.sendMessage(chatId, message);
531
+
532
+ log('http', `Telegram message sent to ${target}`, 'green');
533
+
534
+ res.writeHead(200, { 'Content-Type': 'application/json' });
535
+ res.end(JSON.stringify({ success: true, channel: 'telegram', target }));
536
+
537
+ } else {
538
+ res.writeHead(400, { 'Content-Type': 'application/json' });
539
+ res.end(JSON.stringify({ error: 'Invalid channel. Use "whatsapp" or "telegram"' }));
540
+ }
541
+
542
+ } catch (err) {
543
+ log('http', `Error: ${err.message}`, 'red');
544
+ res.writeHead(500, { 'Content-Type': 'application/json' });
545
+ res.end(JSON.stringify({ error: err.message }));
546
+ }
547
+ });
548
+
549
+ } else {
550
+ res.writeHead(404, { 'Content-Type': 'application/json' });
551
+ res.end(JSON.stringify({ error: 'Not found' }));
552
+ }
553
+ });
554
+
555
+ server.listen(3847, '127.0.0.1', () => {
556
+ log('http', 'HTTP server listening on http://127.0.0.1:3847', 'green');
557
+ });
558
+
559
+ server.on('error', (err) => {
560
+ log('http', `Server error: ${err.message}`, 'red');
561
+ });
562
+ }
563
+
454
564
  function stopGateway() {
455
565
  if (!fs.existsSync(PID_FILE)) {
456
566
  console.log(chalk.gray('\n⚠️ Gateway not running\n'));
@@ -0,0 +1,114 @@
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+ const { getConfig } = require('../utils/config');
6
+
7
+ const PID_FILE = path.join(os.homedir(), '.natureco', 'gateway.pid');
8
+ const GATEWAY_HTTP_URL = 'http://127.0.0.1:3847/send';
9
+
10
+ async function message(args) {
11
+ // Parse arguments
12
+ const targetIndex = args.indexOf('--target');
13
+ const messageIndex = args.indexOf('--message');
14
+ const channelIndex = args.indexOf('--channel');
15
+
16
+ if (targetIndex === -1 || messageIndex === -1) {
17
+ console.log(chalk.red('\n❌ Eksik parametre\n'));
18
+ console.log(chalk.gray('Kullanım:'));
19
+ console.log(chalk.cyan(' natureco message send --target <target> --message <msg> --channel [whatsapp|telegram]'));
20
+ console.log(chalk.gray('\nÖrnekler:'));
21
+ console.log(chalk.cyan(' natureco message send --target +905422842631 --message "Test" --channel whatsapp'));
22
+ console.log(chalk.cyan(' natureco message send --target 6139455189 --message "Test" --channel telegram\n'));
23
+ process.exit(1);
24
+ }
25
+
26
+ const target = args[targetIndex + 1];
27
+ const messageText = args[messageIndex + 1];
28
+ const channel = channelIndex !== -1 ? args[channelIndex + 1] : 'whatsapp';
29
+
30
+ if (!target || !messageText) {
31
+ console.log(chalk.red('\n❌ Target veya message boş olamaz\n'));
32
+ process.exit(1);
33
+ }
34
+
35
+ if (!['whatsapp', 'telegram'].includes(channel)) {
36
+ console.log(chalk.red('\n❌ Geçersiz kanal. Sadece "whatsapp" veya "telegram" kullanılabilir\n'));
37
+ process.exit(1);
38
+ }
39
+
40
+ // Check if gateway is running
41
+ if (!fs.existsSync(PID_FILE)) {
42
+ console.log(chalk.red('\n❌ Gateway çalışmıyor\n'));
43
+ console.log(chalk.yellow('Önce gateway\'i başlatın:'), chalk.cyan('natureco gateway start\n'));
44
+ process.exit(1);
45
+ }
46
+
47
+ try {
48
+ const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim());
49
+ process.kill(pid, 0); // Check if process exists
50
+ } catch {
51
+ console.log(chalk.red('\n❌ Gateway çalışmıyor (stale PID)\n'));
52
+ console.log(chalk.yellow('Önce gateway\'i başlatın:'), chalk.cyan('natureco gateway start\n'));
53
+ process.exit(1);
54
+ }
55
+
56
+ const config = getConfig();
57
+
58
+ // Validate channel configuration
59
+ if (channel === 'whatsapp' && (!config.whatsappConnected || !config.whatsappBotId)) {
60
+ console.log(chalk.red('\n❌ WhatsApp bağlı değil\n'));
61
+ console.log(chalk.yellow('Önce WhatsApp\'ı bağlayın:'), chalk.cyan('natureco whatsapp connect\n'));
62
+ process.exit(1);
63
+ }
64
+
65
+ if (channel === 'telegram' && (!config.telegramToken || !config.telegramBotId)) {
66
+ console.log(chalk.red('\n❌ Telegram bağlı değil\n'));
67
+ console.log(chalk.yellow('Önce Telegram\'ı bağlayın:'), chalk.cyan('natureco telegram connect\n'));
68
+ process.exit(1);
69
+ }
70
+
71
+ // Send message via HTTP endpoint
72
+ await sendMessageViaHttp(channel, target, messageText);
73
+ }
74
+
75
+ async function sendMessageViaHttp(channel, target, messageText) {
76
+ console.log(chalk.yellow(`\n⏳ ${channel === 'whatsapp' ? 'WhatsApp' : 'Telegram'} mesajı gönderiliyor...\n`));
77
+
78
+ try {
79
+ const response = await fetch(GATEWAY_HTTP_URL, {
80
+ method: 'POST',
81
+ headers: { 'Content-Type': 'application/json' },
82
+ body: JSON.stringify({ channel, target, message: messageText })
83
+ });
84
+
85
+ const data = await response.json();
86
+
87
+ if (!response.ok) {
88
+ throw new Error(data.error || `HTTP ${response.status}`);
89
+ }
90
+
91
+ console.log(chalk.green('✅ Mesaj gönderildi!\n'));
92
+ console.log(chalk.cyan('Kanal:'), chalk.white(channel));
93
+ console.log(chalk.cyan('Hedef:'), chalk.white(target));
94
+ console.log(chalk.cyan('Mesaj:'), chalk.white(messageText));
95
+ console.log('');
96
+
97
+ process.exit(0);
98
+
99
+ } catch (err) {
100
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
101
+
102
+ if (err.message.includes('ECONNREFUSED')) {
103
+ console.log(chalk.yellow('⚠️ Gateway HTTP sunucusuna bağlanılamadı'));
104
+ console.log(chalk.gray('Gateway\'i yeniden başlatın: natureco gateway stop && natureco gateway start\n'));
105
+ } else if (err.message.includes('not connected')) {
106
+ console.log(chalk.yellow(`⚠️ ${channel === 'whatsapp' ? 'WhatsApp' : 'Telegram'} bağlı değil`));
107
+ console.log(chalk.gray(`Bağlantıyı kontrol edin: natureco ${channel} status\n`));
108
+ }
109
+
110
+ process.exit(1);
111
+ }
112
+ }
113
+
114
+ module.exports = message;
package/src/utils/api.js CHANGED
@@ -1,4 +1,4 @@
1
- // NatureCo CLI v2.7.1 - Universal LLM Provider Support
1
+ // NatureCo CLI v2.8.0 - 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');