natureco-cli 2.19.1 → 2.20.0

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.
@@ -1,119 +1,183 @@
1
1
  const chalk = require('chalk');
2
2
  const { listSessions, loadSession } = require('../utils/sessions');
3
- const { getApiKey } = require('../utils/config');
3
+ const { getApiKey, getConfig } = require('../utils/config');
4
4
  const { getBots } = require('../utils/api');
5
5
 
6
6
  async function sessions(action, ...args) {
7
- if (!action || action === 'list') {
8
- return listSessionsCommand();
9
- }
10
-
7
+ if (!action || action === 'list') return listSessionsCommand();
11
8
  if (action === 'show') {
12
9
  const sessionId = args[0];
13
10
  if (!sessionId) {
14
- console.log(chalk.red('\n❌ Session ID required\n'));
15
- console.log(chalk.gray('Usage: natureco sessions show <id>\n'));
11
+ console.log(chalk.red('\n ❌ Session ID gerekli\n'));
12
+ console.log(chalk.gray(' Kullanım: natureco sessions show <id>\n'));
16
13
  process.exit(1);
17
14
  }
18
15
  return showSession(sessionId);
19
16
  }
20
-
21
- console.log(chalk.red(`\n❌ Unknown action: ${action}\n`));
22
- console.log(chalk.gray('Available actions: list, show\n'));
17
+ console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
18
+ console.log(chalk.gray(' Kullanım: natureco sessions [list|show]\n'));
23
19
  process.exit(1);
24
20
  }
25
21
 
26
22
  async function listSessionsCommand() {
27
23
  const apiKey = getApiKey();
28
-
24
+ const w = process.stdout.columns || 120;
25
+ const line = chalk.gray('─'.repeat(w));
26
+
29
27
  if (!apiKey) {
30
- console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
28
+ console.log(chalk.red('\n Giriş yapılmamış. natureco login\n'));
31
29
  process.exit(1);
32
30
  }
33
-
31
+
34
32
  let botList;
35
33
  try {
36
34
  botList = await getBots(apiKey);
37
35
  } catch (err) {
38
- console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
36
+ console.log(chalk.red(`\n Hata: ${err.message}\n`));
39
37
  process.exit(1);
40
38
  }
41
-
42
- if (!botList || !botList.bots || botList.bots.length === 0) {
43
- console.log(chalk.gray('No bots found.\n'));
39
+
40
+ if (!botList?.bots?.length) {
41
+ console.log(chalk.gray('\n Bot bulunamadı.\n'));
44
42
  return;
45
43
  }
46
-
47
- console.log(chalk.yellow('\nChat Sessions:\n'));
48
-
49
- let foundAny = false;
50
-
44
+
45
+ // Tüm session'ları topla
46
+ const allSessions = [];
51
47
  botList.bots.forEach(bot => {
52
- const sessions = listSessions(bot.id);
53
- if (sessions.length > 0) {
54
- foundAny = true;
55
- console.log(chalk.cyan(` ${bot.name}:`));
56
- sessions.forEach(session => {
57
- const date = new Date(session.createdAt).toLocaleString();
58
- const messageCount = session.messages.length;
59
- console.log(` ${chalk.white(session.id)} - ${chalk.gray(date)} - ${chalk.gray(messageCount + ' messages')}`);
48
+ const list = listSessions(bot.id);
49
+ list.forEach(s => {
50
+ allSessions.push({
51
+ ...s,
52
+ botName: bot.name,
53
+ messageCount: (s.messages || []).length,
54
+ lastMessage: s.messages?.slice(-1)[0]?.user || '',
60
55
  });
61
- console.log('');
62
- }
56
+ });
63
57
  });
64
-
65
- if (!foundAny) {
66
- console.log(chalk.gray(' No sessions found.\n'));
58
+
59
+ // 0 mesajlıları filtrele
60
+ const active = allSessions.filter(s => s.messageCount > 0);
61
+
62
+ console.log('');
63
+ console.log(line);
64
+ const title = chalk.bold.cyan(' Oturumlar');
65
+ const count = chalk.gray(`${active.length} aktif `);
66
+ const pad = w - 12 - String(active.length).length - 8;
67
+ console.log(title + ' '.repeat(Math.max(1, pad)) + count);
68
+ console.log(line);
69
+
70
+ if (active.length === 0) {
71
+ console.log(chalk.gray('\n Henüz oturum yok.\n'));
72
+ console.log(line);
73
+ return;
67
74
  }
75
+
76
+ // Grupla
77
+ const now = Date.now();
78
+ const todayStr = new Date().toDateString();
79
+ const groups = { 'Bugün': [], 'Bu Hafta': [], 'Daha Önce': [] };
80
+
81
+ active.forEach(s => {
82
+ const d = new Date(s.createdAt);
83
+ if (d.toDateString() === todayStr) groups['Bugün'].push(s);
84
+ else if (now - d < 7 * 24 * 60 * 60 * 1000) groups['Bu Hafta'].push(s);
85
+ else groups['Daha Önce'].push(s);
86
+ });
87
+
88
+ // Kolon genişlikleri
89
+ const dateW = 17;
90
+ const botW = 14;
91
+ const previewW = Math.max(20, w - dateW - botW - 18 - 10);
92
+
93
+ Object.entries(groups).forEach(([label, items]) => {
94
+ if (!items.length) return;
95
+
96
+ console.log('');
97
+ console.log(chalk.yellow(` ${label}`));
98
+ console.log(chalk.gray(' ' +
99
+ 'Tarih/Saat'.padEnd(dateW) +
100
+ 'Bot'.padEnd(botW) +
101
+ 'Son Mesaj'.padEnd(previewW) +
102
+ 'Mesaj'.padStart(6) +
103
+ ' ID'
104
+ ));
105
+ console.log(chalk.gray(' ' + '·'.repeat(w - 4)));
106
+
107
+ items.forEach(s => {
108
+ const d = new Date(s.createdAt);
109
+ const time = d.toLocaleString('tr-TR', {
110
+ day: '2-digit', month: '2-digit',
111
+ hour: '2-digit', minute: '2-digit',
112
+ });
113
+ const bot = (s.botName || '—').slice(0, botW - 2).padEnd(botW);
114
+ const preview = (s.lastMessage || '—').slice(0, previewW - 2).padEnd(previewW);
115
+ const msgs = String(s.messageCount).padStart(5);
116
+ const id = chalk.gray(s.id.slice(-8));
117
+
118
+ console.log(
119
+ chalk.gray(' ' + time.padEnd(dateW)) +
120
+ chalk.cyan(bot) +
121
+ chalk.white(preview) +
122
+ chalk.gray(msgs) +
123
+ ' ' + id
124
+ );
125
+ });
126
+ });
127
+
128
+ console.log('');
129
+ console.log(line);
130
+ console.log(chalk.gray(` ${active.length} aktif oturum · natureco sessions show <id>`));
131
+ console.log(line);
132
+ console.log('');
68
133
  }
69
134
 
70
135
  async function showSession(sessionId) {
71
136
  const apiKey = getApiKey();
72
-
137
+ const w = process.stdout.columns || 120;
138
+ const line = chalk.gray('─'.repeat(w));
139
+
73
140
  if (!apiKey) {
74
- console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
141
+ console.log(chalk.red('\n Giriş yapılmamış. natureco login\n'));
75
142
  process.exit(1);
76
143
  }
77
-
144
+
78
145
  let botList;
79
146
  try {
80
147
  botList = await getBots(apiKey);
81
148
  } catch (err) {
82
- console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
149
+ console.log(chalk.red(`\n Hata: ${err.message}\n`));
83
150
  process.exit(1);
84
151
  }
85
-
86
- if (!botList || !botList.bots || botList.bots.length === 0) {
87
- console.log(chalk.gray('No bots found.\n'));
88
- return;
89
- }
90
-
91
- // Find session across all bots
152
+
92
153
  let session = null;
93
154
  let botName = null;
94
-
95
- for (const bot of botList.bots) {
155
+ for (const bot of (botList?.bots || [])) {
96
156
  session = loadSession(bot.id, sessionId);
97
- if (session) {
98
- botName = bot.name;
99
- break;
100
- }
157
+ if (session) { botName = bot.name; break; }
101
158
  }
102
-
159
+
103
160
  if (!session) {
104
- console.log(chalk.red(`\n❌ Session not found: ${sessionId}\n`));
161
+ console.log(chalk.red(`\n Oturum bulunamadı: ${sessionId}\n`));
105
162
  process.exit(1);
106
163
  }
107
-
108
- console.log(chalk.yellow(`\nSession: ${session.id}\n`));
109
- console.log(chalk.gray(`Bot: ${botName}`));
110
- console.log(chalk.gray(`Created: ${new Date(session.createdAt).toLocaleString()}`));
111
- console.log(chalk.gray(`Messages: ${session.messages.length}\n`));
112
-
164
+
165
+ console.log('');
166
+ console.log(line);
167
+ console.log(chalk.bold.cyan(` Oturum: ${session.id.slice(-8)}`));
168
+ console.log(chalk.gray(` Bot: ${botName} · ${new Date(session.createdAt).toLocaleString('tr-TR')} · ${session.messages.length} mesaj`));
169
+ console.log(line);
170
+ console.log('');
171
+
113
172
  session.messages.forEach((msg, i) => {
114
- console.log(chalk.cyan(`[${i + 1}] siz › ${msg.user}`));
115
- console.log(chalk.green(` bot ${msg.bot}\n`));
173
+ const num = chalk.gray(` ${String(i + 1).padStart(2)}.`);
174
+ console.log(num + ' ' + chalk.white('You ') + msg.user);
175
+ console.log(' ' + chalk.cyan('Bot ') + msg.bot);
176
+ console.log('');
116
177
  });
178
+
179
+ console.log(line);
180
+ console.log('');
117
181
  }
118
182
 
119
183
  module.exports = sessions;
@@ -8,77 +8,120 @@ const { getSkills } = require('../utils/skills');
8
8
  async function status() {
9
9
  const config = getConfig();
10
10
  const version = require('../../package.json').version;
11
+ const w = process.stdout.columns || 120;
12
+ const line = chalk.gray('─'.repeat(w));
11
13
 
14
+ // ── Header ────────────────────────────────────────────────────────────────
12
15
  console.log('');
13
- console.log(chalk.gray(' ' + '─'.repeat(48)));
14
- console.log(chalk.cyan.bold('\n NatureCo CLI — Durum\n'));
16
+ console.log(line);
17
+ const title = chalk.bold.cyan(' NatureCo CLI') + chalk.gray(' — Durum Raporu');
18
+ const ver = chalk.gray(`v${version} `);
19
+ const pad = w - 16 - version.length - 3;
20
+ console.log(title + ' '.repeat(Math.max(1, pad)) + ver);
21
+ console.log(line);
15
22
 
16
- // Provider
23
+ // ── Provider & Bot ────────────────────────────────────────────────────────
17
24
  const providerHost = config.providerUrl
18
25
  ? config.providerUrl.replace('https://', '').split('/')[0]
19
26
  : null;
27
+ const model = config.providerModel
28
+ ? config.providerModel.split('/').pop().split('-').slice(0, 3).join('-')
29
+ : 'bilinmiyor';
20
30
 
21
- console.log(chalk.gray(' Versiyon : ') + chalk.white(`v${version}`));
22
- if (providerHost) {
23
- console.log(chalk.gray(' Provider : ') + chalk.white(providerHost));
24
- console.log(chalk.gray(' Model : ') + chalk.white(config.providerModel || 'bilinmiyor'));
25
- } else {
26
- console.log(chalk.gray(' Provider : ') + chalk.yellow('yapılandırılmamış'));
27
- }
28
- if (config.botName) console.log(chalk.gray(' Bot : ') + chalk.cyan(config.botName));
29
- if (config.userName) console.log(chalk.gray(' Kullanıcı : ') + chalk.white(config.userName));
31
+ console.log('');
32
+ row('Provider ', providerHost ? chalk.white(providerHost) : chalk.yellow('yapılandırılmamış'),
33
+ 'Bot ', config.botName ? chalk.cyan(config.botName) : chalk.gray('—'), w);
34
+ row('Model ', chalk.white(model),
35
+ 'Kullanıcı', config.userName ? chalk.white(config.userName) : chalk.gray('—'), w);
30
36
 
31
- // Gateway durumu
37
+ // ── Servisler ─────────────────────────────────────────────────────────────
32
38
  const pidFile = path.join(os.homedir(), '.natureco', 'gateway.pid');
33
- const gatewayRunning = fs.existsSync(pidFile);
34
- console.log(chalk.gray(' Gateway : ') + (gatewayRunning ? chalk.green('çalışıyor') : chalk.gray('durdurulmuş')));
35
-
36
- // Dashboard
37
39
  const dashPid = path.join(os.homedir(), '.natureco', 'dashboard.pid');
40
+ const gatewayRunning = fs.existsSync(pidFile);
38
41
  const dashRunning = fs.existsSync(dashPid);
39
- console.log(chalk.gray(' Dashboard : ') + (dashRunning ? chalk.green('çalışıyor (localhost:3848)') : chalk.gray('durdurulmuş')));
40
42
 
41
- // Kanallar
42
- const channels = [];
43
- if (config.telegramToken) channels.push('Telegram');
44
- if (config.whatsappConnected) channels.push('WhatsApp');
45
- if (config.discordToken) channels.push('Discord');
46
- if (config.slackToken) channels.push('Slack');
47
- console.log(chalk.gray(' Kanallar : ') + (channels.length > 0 ? chalk.white(channels.join(', ')) : chalk.gray('yok')));
43
+ row('Gateway ', gatewayRunning ? chalk.green('● çalışıyor') : chalk.gray('○ durdurulmuş'),
44
+ 'Dashboard', dashRunning ? chalk.green('● localhost:3848') : chalk.gray('○ durdurulmuş'), w);
48
45
 
49
- // Skills
50
- const skills = getSkills();
51
- console.log(chalk.gray(' Skills : ') + chalk.white(`${skills.length} yüklü`));
46
+ // ── Entegrasyonlar ────────────────────────────────────────────────────────
47
+ const tg = config.telegramToken ? chalk.green('● bağlı') : chalk.gray('○ —');
48
+ const wa = config.whatsappConnected ? chalk.green(' bağlı') : chalk.gray('○ —');
49
+ const dc = config.discordToken ? chalk.green('● bağlı') : chalk.gray('○ —');
50
+ const sl = config.slackToken ? chalk.green('● bağlı') : chalk.gray('○ —');
52
51
 
53
- // Memory
54
- const memDir = path.join(os.homedir(), '.natureco', 'memory');
55
- const memFiles = fs.existsSync(memDir) ? fs.readdirSync(memDir).filter(f => f.endsWith('.json')).length : 0;
56
- console.log(chalk.gray(' Hafıza : ') + chalk.white(`${memFiles} bot`));
52
+ console.log('');
53
+ console.log(chalk.gray(' ' + ''.repeat(w - 2)));
54
+ console.log(chalk.gray(' Entegrasyonlar'));
55
+ console.log('');
56
+ row('Telegram ', tg, 'Discord ', dc, w);
57
+ row('WhatsApp ', wa, 'Slack ', sl, w);
57
58
 
58
- // Son session
59
+ // ── Kaynaklar ─────────────────────────────────────────────────────────────
60
+ const skills = getSkills();
61
+ const memDir = path.join(os.homedir(), '.natureco', 'memory');
62
+ const memFiles = fs.existsSync(memDir)
63
+ ? fs.readdirSync(memDir).filter(f => f.endsWith('.json')).length : 0;
59
64
  const sessDir = path.join(os.homedir(), '.natureco', 'sessions');
65
+ let sessCount = 0;
60
66
  if (fs.existsSync(sessDir)) {
61
- const sessions = fs.readdirSync(sessDir).filter(f => f.endsWith('.json'));
62
- if (sessions.length > 0) {
63
- console.log(chalk.gray(' Sessions : ') + chalk.white(`${sessions.length} kayıtlı`));
64
- }
67
+ sessCount = fs.readdirSync(sessDir).filter(f => f.endsWith('.json')).length;
65
68
  }
66
69
 
67
- // Son loglar
70
+ console.log('');
71
+ console.log(chalk.gray(' ' + '─'.repeat(w - 2)));
72
+ console.log(chalk.gray(' Kaynaklar'));
73
+ console.log('');
74
+ row('Skills ', chalk.white(`${skills.length} yüklü`),
75
+ 'Hafıza ', chalk.white(`${memFiles} bot`), w);
76
+ row('Sessions ', chalk.white(`${sessCount} kayıtlı`),
77
+ 'Versiyon ', chalk.white(`v${version}`), w);
78
+
79
+ // ── Son Loglar ────────────────────────────────────────────────────────────
68
80
  const logFile = path.join(os.homedir(), '.natureco', 'gateway.log');
69
81
  if (fs.existsSync(logFile)) {
70
82
  const lines = fs.readFileSync(logFile, 'utf-8').split('\n').filter(l => l.trim());
71
83
  const last = lines.slice(-3);
72
84
  if (last.length > 0) {
73
- console.log(chalk.gray('\n Son Loglar:\n'));
74
- last.forEach(l => console.log(chalk.gray(' ' + l)));
85
+ console.log('');
86
+ console.log(chalk.gray(' ' + '─'.repeat(w - 2)));
87
+ console.log(chalk.gray(' Son Aktivite'));
88
+ console.log('');
89
+ last.forEach(l => {
90
+ const trimmed = l.slice(0, w - 4);
91
+ console.log(chalk.gray(' ') + chalk.gray(trimmed));
92
+ });
75
93
  }
76
94
  }
77
95
 
96
+ // ── Footer ────────────────────────────────────────────────────────────────
78
97
  console.log('');
79
- console.log(chalk.gray(' ' + '─'.repeat(48)));
80
- console.log(chalk.gray(' Detaylı kontrol: ') + chalk.cyan('natureco doctor'));
81
- console.log(chalk.gray(' Kanal durumu : ') + chalk.cyan('natureco channels status\n'));
98
+ console.log(line);
99
+ console.log(
100
+ chalk.gray(' natureco doctor') +
101
+ chalk.gray(' · ') +
102
+ chalk.gray('natureco chat') +
103
+ chalk.gray(' · ') +
104
+ chalk.gray('natureco code') +
105
+ chalk.gray(' · ') +
106
+ chalk.gray('natureco channels status')
107
+ );
108
+ console.log(line);
109
+ console.log('');
110
+ }
111
+
112
+ // ── İki kolon satır yardımcısı ─────────────────────────────────────────────
113
+ function row(label1, val1, label2, val2, w) {
114
+ const col = Math.floor(w / 2);
115
+ const left = chalk.gray(' ' + label1) + val1;
116
+ const right = chalk.gray(label2) + val2;
117
+ // ANSI kodlarını sayma — sabit padding kullan
118
+ const leftPlain = (' ' + label1).length + stripAnsi(String(val1)).length;
119
+ const pad = Math.max(1, col - leftPlain);
120
+ console.log(left + ' '.repeat(pad) + right);
121
+ }
122
+
123
+ function stripAnsi(str) {
124
+ return str.replace(/\x1B\[[0-9;]*m/g, '');
82
125
  }
83
126
 
84
127
  module.exports = status;