natureco-cli 2.16.4 → 2.17.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 +64 -0
- package/package.json +1 -1
- package/src/commands/bots.js +17 -16
- package/src/commands/channels.js +177 -0
- package/src/commands/dashboard.js +2 -2
- package/src/commands/doctor.js +1 -0
- package/src/commands/git.js +9 -12
- package/src/commands/help.js +12 -5
- package/src/commands/logs.js +99 -0
- package/src/commands/memory-cmd.js +190 -0
- package/src/commands/models.js +216 -0
- package/src/commands/reset.js +94 -0
- package/src/commands/security.js +142 -0
- package/src/commands/skills.js +15 -19
- package/src/commands/status.js +84 -0
- package/src/commands/ultrareview.js +15 -4
package/bin/natureco.js
CHANGED
|
@@ -244,6 +244,70 @@ program
|
|
|
244
244
|
doctorCmd(args);
|
|
245
245
|
});
|
|
246
246
|
|
|
247
|
+
program
|
|
248
|
+
.command('channels [action] [params...]')
|
|
249
|
+
.description('Manage connected channels (list|status|remove|logs)')
|
|
250
|
+
.action((action, params) => {
|
|
251
|
+
const channelsCmd = require('../src/commands/channels');
|
|
252
|
+
channelsCmd([action, ...(params || [])]);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
program
|
|
256
|
+
.command('models [action] [params...]')
|
|
257
|
+
.description('Manage AI models (list|set|scan|aliases)')
|
|
258
|
+
.action((action, params) => {
|
|
259
|
+
const modelsCmd = require('../src/commands/models');
|
|
260
|
+
modelsCmd([action, ...(params || [])]);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
program
|
|
264
|
+
.command('memory [action] [params...]')
|
|
265
|
+
.description('Manage memory (status|list|search|show|clear|index)')
|
|
266
|
+
.action((action, params) => {
|
|
267
|
+
const memoryCmd = require('../src/commands/memory-cmd');
|
|
268
|
+
memoryCmd([action, ...(params || [])]);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
program
|
|
272
|
+
.command('logs')
|
|
273
|
+
.description('View and follow gateway logs')
|
|
274
|
+
.option('--follow, -f', 'Follow logs in real-time')
|
|
275
|
+
.option('--json', 'JSON output')
|
|
276
|
+
.option('--plain', 'Plain text output')
|
|
277
|
+
.option('--limit <n>', 'Number of lines to show', '50')
|
|
278
|
+
.action(() => {
|
|
279
|
+
const logsCmd = require('../src/commands/logs');
|
|
280
|
+
logsCmd(process.argv.slice(3));
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
program
|
|
284
|
+
.command('status')
|
|
285
|
+
.description('Show overall system status')
|
|
286
|
+
.action(() => {
|
|
287
|
+
const statusCmd = require('../src/commands/status');
|
|
288
|
+
statusCmd();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
program
|
|
292
|
+
.command('reset')
|
|
293
|
+
.description('Reset local config/state')
|
|
294
|
+
.option('--scope <scope>', 'Scope: config|memory|sessions|full', 'config')
|
|
295
|
+
.option('--yes, -y', 'Skip confirmation')
|
|
296
|
+
.action(() => {
|
|
297
|
+
const resetCmd = require('../src/commands/reset');
|
|
298
|
+
resetCmd(process.argv.slice(3));
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
program
|
|
302
|
+
.command('security [action]')
|
|
303
|
+
.description('Security audit (audit)')
|
|
304
|
+
.option('--fix', 'Auto-fix issues')
|
|
305
|
+
.option('--json', 'JSON output')
|
|
306
|
+
.action((action) => {
|
|
307
|
+
const securityCmd = require('../src/commands/security');
|
|
308
|
+
securityCmd(process.argv.slice(3));
|
|
309
|
+
});
|
|
310
|
+
|
|
247
311
|
program
|
|
248
312
|
.command('help')
|
|
249
313
|
.description('Show help information')
|
package/package.json
CHANGED
package/src/commands/bots.js
CHANGED
|
@@ -3,37 +3,38 @@ const { getApiKey } = require('../utils/config');
|
|
|
3
3
|
const { getBots } = require('../utils/api');
|
|
4
4
|
|
|
5
5
|
async function bots() {
|
|
6
|
-
const
|
|
6
|
+
const { getConfig } = require('../utils/config');
|
|
7
|
+
const config = getConfig();
|
|
8
|
+
const apiKey = getApiKey() || config.providerApiKey || '';
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
console.log(chalk.yellow('\n⏳ Fetching your bots...\n'));
|
|
10
|
+
console.log(chalk.gray('\n Botlar yükleniyor...\n'));
|
|
14
11
|
|
|
15
12
|
try {
|
|
16
13
|
const botList = await getBots(apiKey);
|
|
17
14
|
|
|
18
15
|
if (!botList || !botList.bots || botList.bots.length === 0) {
|
|
19
|
-
console.log(chalk.gray('
|
|
16
|
+
console.log(chalk.gray(' Bot bulunamadı.'));
|
|
17
|
+
console.log(chalk.gray(' Oluşturmak için: ') + chalk.cyan('developers.natureco.me\n'));
|
|
20
18
|
return;
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
console.log(chalk.
|
|
21
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
22
|
+
console.log(chalk.cyan.bold('\n Botlarım\n'));
|
|
24
23
|
|
|
25
24
|
botList.bots.forEach((bot, index) => {
|
|
26
|
-
|
|
27
|
-
console.log(chalk.
|
|
28
|
-
console.log(chalk.gray(`
|
|
29
|
-
console.log(chalk.gray(`
|
|
25
|
+
const active = config.botName === bot.name ? chalk.green(' ← aktif') : '';
|
|
26
|
+
console.log(chalk.white(` ${index + 1}. ${bot.name}`) + active);
|
|
27
|
+
console.log(chalk.gray(` ID : ${bot.id}`));
|
|
28
|
+
console.log(chalk.gray(` Provider: ${bot.ai_provider || 'groq'}`));
|
|
29
|
+
if (bot.model) console.log(chalk.gray(` Model : ${bot.model}`));
|
|
30
30
|
console.log('');
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
console.log(chalk.
|
|
34
|
-
console.log(chalk.gray(`
|
|
33
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
34
|
+
console.log(chalk.gray(` Toplam: ${botList.bots.length} bot`));
|
|
35
|
+
console.log(chalk.gray(' Chat başlatmak için: ') + chalk.cyan('natureco chat\n'));
|
|
35
36
|
} catch (err) {
|
|
36
|
-
console.log(chalk.red(`\n❌
|
|
37
|
+
console.log(chalk.red(`\n ❌ Hata: ${err.message}\n`));
|
|
37
38
|
process.exit(1);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
async function channels(args) {
|
|
8
|
+
const [action, ...params] = (args || []);
|
|
9
|
+
|
|
10
|
+
if (!action || action === 'list') return listChannels();
|
|
11
|
+
if (action === 'status') return statusChannels();
|
|
12
|
+
if (action === 'remove') return removeChannel(params[0]);
|
|
13
|
+
if (action === 'logs') return channelLogs(params[0]);
|
|
14
|
+
|
|
15
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
16
|
+
console.log(chalk.gray(' Kullanım: natureco channels [list|status|remove|logs]\n'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function listChannels() {
|
|
21
|
+
const config = getConfig();
|
|
22
|
+
const channels = [];
|
|
23
|
+
|
|
24
|
+
if (config.telegramToken) {
|
|
25
|
+
channels.push({
|
|
26
|
+
name: 'Telegram',
|
|
27
|
+
icon: '✈',
|
|
28
|
+
status: 'bağlı',
|
|
29
|
+
detail: `token: ${config.telegramToken.slice(0, 12)}...`,
|
|
30
|
+
chats: (config.telegramAllowedChats || []).length,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (config.whatsappConnected) {
|
|
35
|
+
channels.push({
|
|
36
|
+
name: 'WhatsApp',
|
|
37
|
+
icon: '📱',
|
|
38
|
+
status: 'bağlı',
|
|
39
|
+
detail: config.whatsappPhone ? `+${config.whatsappPhone.split(':')[0]}` : 'bağlı',
|
|
40
|
+
chats: (config.whatsappAllowedNumbers || []).length,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (config.discordToken) {
|
|
45
|
+
channels.push({
|
|
46
|
+
name: 'Discord',
|
|
47
|
+
icon: '🎮',
|
|
48
|
+
status: 'bağlı',
|
|
49
|
+
detail: `token: ${config.discordToken.slice(0, 12)}...`,
|
|
50
|
+
chats: 0,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (config.slackToken) {
|
|
55
|
+
channels.push({
|
|
56
|
+
name: 'Slack',
|
|
57
|
+
icon: '💼',
|
|
58
|
+
status: 'bağlı',
|
|
59
|
+
detail: `token: ${config.slackToken.slice(0, 12)}...`,
|
|
60
|
+
chats: 0,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
66
|
+
console.log(chalk.cyan.bold('\n Kanallar\n'));
|
|
67
|
+
|
|
68
|
+
if (channels.length === 0) {
|
|
69
|
+
console.log(chalk.gray(' Bağlı kanal yok.\n'));
|
|
70
|
+
console.log(chalk.gray(' Bağlamak için:'));
|
|
71
|
+
console.log(chalk.cyan(' natureco telegram connect'));
|
|
72
|
+
console.log(chalk.cyan(' natureco whatsapp connect'));
|
|
73
|
+
console.log(chalk.cyan(' natureco discord connect'));
|
|
74
|
+
console.log(chalk.cyan(' natureco slack connect\n'));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
channels.forEach(ch => {
|
|
79
|
+
console.log(chalk.white(` ${ch.icon} ${ch.name}`) + chalk.green(' ✓ ' + ch.status));
|
|
80
|
+
console.log(chalk.gray(` ${ch.detail}`));
|
|
81
|
+
if (ch.chats > 0) console.log(chalk.gray(` İzin listesi: ${ch.chats} kayıt`));
|
|
82
|
+
console.log('');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
86
|
+
console.log(chalk.gray(` Toplam: ${channels.length} kanal bağlı`));
|
|
87
|
+
console.log(chalk.gray(' Kaldırmak için: ') + chalk.cyan('natureco channels remove <kanal>\n'));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function statusChannels() {
|
|
91
|
+
const config = getConfig();
|
|
92
|
+
console.log('');
|
|
93
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
94
|
+
console.log(chalk.cyan.bold('\n Kanal Durumu\n'));
|
|
95
|
+
|
|
96
|
+
const checks = [
|
|
97
|
+
{ name: 'Telegram', ok: !!config.telegramToken },
|
|
98
|
+
{ name: 'WhatsApp', ok: !!config.whatsappConnected },
|
|
99
|
+
{ name: 'Discord', ok: !!config.discordToken },
|
|
100
|
+
{ name: 'Slack', ok: !!config.slackToken },
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
checks.forEach(ch => {
|
|
104
|
+
const icon = ch.ok ? chalk.green('✓') : chalk.gray('○');
|
|
105
|
+
const label = ch.ok ? chalk.white(ch.name) : chalk.gray(ch.name);
|
|
106
|
+
const status = ch.ok ? chalk.green('bağlı') : chalk.gray('bağlı değil');
|
|
107
|
+
console.log(` ${icon} ${label.padEnd(12)} ${status}`);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const connected = checks.filter(c => c.ok).length;
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
113
|
+
console.log(chalk.gray(` ${connected}/4 kanal aktif\n`));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function removeChannel(channel) {
|
|
117
|
+
if (!channel) {
|
|
118
|
+
console.log(chalk.red('\n ❌ Kanal adı gerekli\n'));
|
|
119
|
+
console.log(chalk.gray(' Kullanım: natureco channels remove <telegram|whatsapp|discord|slack>\n'));
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const config = getConfig();
|
|
124
|
+
const ch = channel.toLowerCase();
|
|
125
|
+
|
|
126
|
+
if (ch === 'telegram') {
|
|
127
|
+
delete config.telegramToken;
|
|
128
|
+
delete config.telegramBotId;
|
|
129
|
+
delete config.telegramAllowedChats;
|
|
130
|
+
} else if (ch === 'whatsapp') {
|
|
131
|
+
// Session dosyalarını sil
|
|
132
|
+
if (config.whatsappBotId) {
|
|
133
|
+
const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
|
|
134
|
+
if (fs.existsSync(sessionDir)) {
|
|
135
|
+
fs.rmSync(sessionDir, { recursive: true, force: true });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
delete config.whatsappConnected;
|
|
139
|
+
delete config.whatsappBotId;
|
|
140
|
+
delete config.whatsappPhone;
|
|
141
|
+
delete config.whatsappAllowedNumbers;
|
|
142
|
+
} else if (ch === 'discord') {
|
|
143
|
+
delete config.discordToken;
|
|
144
|
+
delete config.discordBotId;
|
|
145
|
+
} else if (ch === 'slack') {
|
|
146
|
+
delete config.slackToken;
|
|
147
|
+
delete config.slackBotId;
|
|
148
|
+
} else {
|
|
149
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen kanal: ${channel}\n`));
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
saveConfig(config);
|
|
154
|
+
console.log(chalk.green(`\n ✓ ${channel} kaldırıldı\n`));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function channelLogs(channel) {
|
|
158
|
+
const logFile = path.join(os.homedir(), '.natureco', 'gateway.log');
|
|
159
|
+
if (!fs.existsSync(logFile)) {
|
|
160
|
+
console.log(chalk.gray('\n Log dosyası bulunamadı.\n'));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const lines = fs.readFileSync(logFile, 'utf-8').split('\n').filter(l => l.trim());
|
|
165
|
+
const filtered = channel
|
|
166
|
+
? lines.filter(l => l.toLowerCase().includes(channel.toLowerCase()))
|
|
167
|
+
: lines;
|
|
168
|
+
|
|
169
|
+
const last = filtered.slice(-20);
|
|
170
|
+
console.log('');
|
|
171
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
172
|
+
console.log(chalk.cyan.bold(`\n Kanal Logları${channel ? ` (${channel})` : ''}\n`));
|
|
173
|
+
last.forEach(l => console.log(chalk.gray(' ' + l)));
|
|
174
|
+
console.log('');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
module.exports = channels;
|
|
@@ -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.
|
|
214
|
+
<div class="version-badge" id="version-badge">v2.17.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.
|
|
344
|
+
version: 'v2.17.1',
|
|
345
345
|
bots: cfg.bots || [],
|
|
346
346
|
telegramToken: cfg.telegramToken || null,
|
|
347
347
|
whatsappConnected: cfg.whatsappConnected || false,
|
package/src/commands/doctor.js
CHANGED
package/src/commands/git.js
CHANGED
|
@@ -200,13 +200,10 @@ async function gitExplain() {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
async function getDefaultBot() {
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
process.exit(1);
|
|
208
|
-
}
|
|
209
|
-
|
|
203
|
+
const { getConfig } = require('../utils/config');
|
|
204
|
+
const config = getConfig();
|
|
205
|
+
const apiKey = getApiKey() || config.providerApiKey || '';
|
|
206
|
+
|
|
210
207
|
let botList;
|
|
211
208
|
try {
|
|
212
209
|
botList = await getBots(apiKey);
|
|
@@ -214,15 +211,15 @@ async function getDefaultBot() {
|
|
|
214
211
|
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
215
212
|
process.exit(1);
|
|
216
213
|
}
|
|
217
|
-
|
|
214
|
+
|
|
218
215
|
if (!botList || !botList.bots || botList.bots.length === 0) {
|
|
219
216
|
console.log(chalk.gray('No bots found. Create one at https://developers.natureco.me\n'));
|
|
220
217
|
process.exit(1);
|
|
221
218
|
}
|
|
222
|
-
|
|
223
|
-
//
|
|
224
|
-
const bot = botList.bots[0];
|
|
225
|
-
|
|
219
|
+
|
|
220
|
+
// Config'deki botName ile eşleştir, yoksa ilk botu kullan
|
|
221
|
+
const bot = botList.bots.find(b => b.name === config.botName) || botList.bots[0];
|
|
222
|
+
|
|
226
223
|
return { apiKey, bot };
|
|
227
224
|
}
|
|
228
225
|
|
package/src/commands/help.js
CHANGED
|
@@ -72,11 +72,18 @@ function help() {
|
|
|
72
72
|
|
|
73
73
|
// ── Diğer ────────────────────────────────────────────────────
|
|
74
74
|
console.log(chalk.cyan.bold('\n Diğer\n'));
|
|
75
|
-
printCmd('natureco
|
|
76
|
-
printCmd('natureco
|
|
77
|
-
printCmd('natureco
|
|
78
|
-
printCmd('natureco
|
|
79
|
-
printCmd('natureco
|
|
75
|
+
printCmd('natureco channels [action]', 'Kanal yönetimi (list|status|remove|logs)');
|
|
76
|
+
printCmd('natureco models [action]', 'Model yönetimi (list|set|scan|aliases)');
|
|
77
|
+
printCmd('natureco memory [action]', 'Hafıza yönetimi (status|list|search|show|clear)');
|
|
78
|
+
printCmd('natureco logs', 'Gateway loglarını göster (--follow ile canlı)');
|
|
79
|
+
printCmd('natureco status', 'Genel sistem durumu');
|
|
80
|
+
printCmd('natureco security audit', 'Güvenlik denetimi (--fix ile otomatik düzelt)');
|
|
81
|
+
printCmd('natureco reset', 'Config sıfırla (--scope config|memory|sessions|full)');
|
|
82
|
+
printCmd('natureco sessions list', 'Geçmiş oturumları listele');
|
|
83
|
+
printCmd('natureco tasks list', 'Arka plan görevlerini listele');
|
|
84
|
+
printCmd('natureco config list', 'Tüm ayarları göster');
|
|
85
|
+
printCmd('natureco config set <k> <v>', 'Ayar değiştir');
|
|
86
|
+
printCmd('natureco init', 'Proje klasörü oluştur (.natureco/)');
|
|
80
87
|
|
|
81
88
|
// ── Chat içi komutlar ────────────────────────────────────────
|
|
82
89
|
console.log(chalk.cyan.bold('\n Chat İçi Komutlar\n'));
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
const LOG_FILE = path.join(os.homedir(), '.natureco', 'gateway.log');
|
|
7
|
+
|
|
8
|
+
async function logs(args) {
|
|
9
|
+
const follow = args.includes('--follow') || args.includes('-f');
|
|
10
|
+
const json = args.includes('--json');
|
|
11
|
+
const plain = args.includes('--plain');
|
|
12
|
+
const limitIdx = args.indexOf('--limit');
|
|
13
|
+
const limit = limitIdx !== -1 && args[limitIdx + 1]
|
|
14
|
+
? parseInt(args[limitIdx + 1]) || 50
|
|
15
|
+
: (args.find(a => a.startsWith('--limit='))
|
|
16
|
+
? parseInt(args.find(a => a.startsWith('--limit=')).split('=')[1]) || 50
|
|
17
|
+
: 50);
|
|
18
|
+
|
|
19
|
+
if (!fs.existsSync(LOG_FILE)) {
|
|
20
|
+
if (!json) console.log(chalk.gray('\n Log dosyası bulunamadı: ' + LOG_FILE + '\n'));
|
|
21
|
+
else console.log(JSON.stringify({ error: 'Log file not found' }));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const printLines = (lines) => {
|
|
26
|
+
const last = lines.slice(-limit);
|
|
27
|
+
if (json) {
|
|
28
|
+
console.log(JSON.stringify({ lines: last }));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!plain) {
|
|
32
|
+
console.log('');
|
|
33
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
34
|
+
console.log(chalk.cyan.bold(`\n Gateway Logları (son ${limit})\n`));
|
|
35
|
+
}
|
|
36
|
+
last.forEach(line => {
|
|
37
|
+
if (!line.trim()) return;
|
|
38
|
+
if (plain) {
|
|
39
|
+
console.log(line);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Renklendirme
|
|
43
|
+
if (line.includes('[error]') || line.includes('ERROR') || line.includes('❌')) {
|
|
44
|
+
console.log(chalk.red(' ' + line));
|
|
45
|
+
} else if (line.includes('[warn]') || line.includes('WARN') || line.includes('⚠')) {
|
|
46
|
+
console.log(chalk.yellow(' ' + line));
|
|
47
|
+
} else if (line.includes('[whatsapp]') || line.includes('[telegram]') || line.includes('[discord]')) {
|
|
48
|
+
console.log(chalk.cyan(' ' + line));
|
|
49
|
+
} else {
|
|
50
|
+
console.log(chalk.gray(' ' + line));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
if (!plain) console.log('');
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const content = fs.readFileSync(LOG_FILE, 'utf-8');
|
|
57
|
+
const lines = content.split('\n').filter(l => l.trim());
|
|
58
|
+
printLines(lines);
|
|
59
|
+
|
|
60
|
+
if (follow) {
|
|
61
|
+
if (!plain) console.log(chalk.gray(' Canlı takip modunda... (Ctrl+C ile çık)\n'));
|
|
62
|
+
let lastSize = fs.statSync(LOG_FILE).size;
|
|
63
|
+
|
|
64
|
+
const watcher = setInterval(() => {
|
|
65
|
+
try {
|
|
66
|
+
const stat = fs.statSync(LOG_FILE);
|
|
67
|
+
if (stat.size > lastSize) {
|
|
68
|
+
const fd = fs.openSync(LOG_FILE, 'r');
|
|
69
|
+
const buf = Buffer.alloc(stat.size - lastSize);
|
|
70
|
+
fs.readSync(fd, buf, 0, buf.length, lastSize);
|
|
71
|
+
fs.closeSync(fd);
|
|
72
|
+
const newLines = buf.toString('utf-8').split('\n').filter(l => l.trim());
|
|
73
|
+
newLines.forEach(line => {
|
|
74
|
+
if (!line.trim()) return;
|
|
75
|
+
if (plain) { console.log(line); return; }
|
|
76
|
+
if (line.includes('[error]') || line.includes('ERROR')) {
|
|
77
|
+
console.log(chalk.red(' ' + line));
|
|
78
|
+
} else if (line.includes('[warn]') || line.includes('WARN')) {
|
|
79
|
+
console.log(chalk.yellow(' ' + line));
|
|
80
|
+
} else if (line.includes('[whatsapp]') || line.includes('[telegram]')) {
|
|
81
|
+
console.log(chalk.cyan(' ' + line));
|
|
82
|
+
} else {
|
|
83
|
+
console.log(chalk.gray(' ' + line));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
lastSize = stat.size;
|
|
87
|
+
}
|
|
88
|
+
} catch {}
|
|
89
|
+
}, 500);
|
|
90
|
+
|
|
91
|
+
process.on('SIGINT', () => {
|
|
92
|
+
clearInterval(watcher);
|
|
93
|
+
console.log(chalk.gray('\n Takip durduruldu.\n'));
|
|
94
|
+
process.exit(0);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = logs;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const { loadMemory, saveMemory, clearMemory } = require('../utils/memory');
|
|
6
|
+
const { getConfig } = require('../utils/config');
|
|
7
|
+
|
|
8
|
+
const MEMORY_DIR = path.join(os.homedir(), '.natureco', 'memory');
|
|
9
|
+
|
|
10
|
+
async function memoryCmd(args) {
|
|
11
|
+
const [action, ...params] = (args || []);
|
|
12
|
+
|
|
13
|
+
if (!action || action === 'status') return statusMemory();
|
|
14
|
+
if (action === 'list') return listMemory();
|
|
15
|
+
if (action === 'search') return searchMemory(params.join(' '));
|
|
16
|
+
if (action === 'show') return showMemory(params[0]);
|
|
17
|
+
if (action === 'clear') return clearMemoryCmd(params[0]);
|
|
18
|
+
if (action === 'index') return indexMemory();
|
|
19
|
+
|
|
20
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
21
|
+
console.log(chalk.gray(' Kullanım: natureco memory [status|list|search|show|clear|index]\n'));
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function statusMemory() {
|
|
26
|
+
const config = getConfig();
|
|
27
|
+
|
|
28
|
+
console.log('');
|
|
29
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
30
|
+
console.log(chalk.cyan.bold('\n Hafıza Durumu\n'));
|
|
31
|
+
|
|
32
|
+
if (!fs.existsSync(MEMORY_DIR)) {
|
|
33
|
+
console.log(chalk.gray(' Hafıza dizini bulunamadı.\n'));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
|
|
38
|
+
|
|
39
|
+
if (files.length === 0) {
|
|
40
|
+
console.log(chalk.gray(' Kayıtlı hafıza yok.\n'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let totalFacts = 0;
|
|
45
|
+
files.forEach(file => {
|
|
46
|
+
const botId = file.replace('.json', '');
|
|
47
|
+
try {
|
|
48
|
+
const mem = loadMemory(botId);
|
|
49
|
+
const factCount = (mem.facts || []).length;
|
|
50
|
+
totalFacts += factCount;
|
|
51
|
+
const active = config.botName && (mem.botName === config.botName) ? chalk.green(' ← aktif') : '';
|
|
52
|
+
console.log(chalk.white(` ${mem.botName || botId}`) + active);
|
|
53
|
+
if (mem.name) console.log(chalk.gray(` Kullanıcı : ${mem.name}`));
|
|
54
|
+
if (mem.nickname) console.log(chalk.gray(` Lakap : ${mem.nickname}`));
|
|
55
|
+
console.log(chalk.gray(` Bilgi : ${factCount} kayıt`));
|
|
56
|
+
if (mem.lastSeen) {
|
|
57
|
+
const d = new Date(mem.lastSeen);
|
|
58
|
+
console.log(chalk.gray(` Son görüş : ${d.toLocaleDateString('tr-TR')}`));
|
|
59
|
+
}
|
|
60
|
+
console.log('');
|
|
61
|
+
} catch {}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
65
|
+
console.log(chalk.gray(` ${files.length} bot · ${totalFacts} toplam bilgi`));
|
|
66
|
+
console.log(chalk.gray(' Aramak için: ') + chalk.cyan('natureco memory search <sorgu>\n'));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function listMemory() {
|
|
70
|
+
if (!fs.existsSync(MEMORY_DIR)) {
|
|
71
|
+
console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
|
|
76
|
+
console.log(chalk.cyan.bold(`\n Hafıza Dosyaları (${files.length})\n`));
|
|
77
|
+
files.forEach(f => {
|
|
78
|
+
const botId = f.replace('.json', '');
|
|
79
|
+
const mem = loadMemory(botId);
|
|
80
|
+
console.log(chalk.white(` ${f}`));
|
|
81
|
+
console.log(chalk.gray(` Bot: ${mem.botName || botId} · ${(mem.facts || []).length} bilgi`));
|
|
82
|
+
});
|
|
83
|
+
console.log('');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function searchMemory(query) {
|
|
87
|
+
if (!query) {
|
|
88
|
+
console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n'));
|
|
89
|
+
console.log(chalk.gray(' Kullanım: natureco memory search <sorgu>\n'));
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!fs.existsSync(MEMORY_DIR)) {
|
|
94
|
+
console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
|
|
99
|
+
const results = [];
|
|
100
|
+
|
|
101
|
+
files.forEach(file => {
|
|
102
|
+
const botId = file.replace('.json', '');
|
|
103
|
+
const mem = loadMemory(botId);
|
|
104
|
+
const q = query.toLowerCase();
|
|
105
|
+
|
|
106
|
+
if (mem.name?.toLowerCase().includes(q)) {
|
|
107
|
+
results.push({ bot: mem.botName || botId, field: 'İsim', value: mem.name });
|
|
108
|
+
}
|
|
109
|
+
if (mem.nickname?.toLowerCase().includes(q)) {
|
|
110
|
+
results.push({ bot: mem.botName || botId, field: 'Lakap', value: mem.nickname });
|
|
111
|
+
}
|
|
112
|
+
(mem.facts || []).forEach(f => {
|
|
113
|
+
const val = typeof f === 'string' ? f : f.value;
|
|
114
|
+
if (val?.toLowerCase().includes(q)) {
|
|
115
|
+
results.push({ bot: mem.botName || botId, field: 'Bilgi', value: val });
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
console.log(chalk.cyan.bold(`\n "${query}" için ${results.length} sonuç\n`));
|
|
121
|
+
if (results.length === 0) {
|
|
122
|
+
console.log(chalk.gray(' Sonuç bulunamadı.\n'));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
results.forEach(r => {
|
|
126
|
+
console.log(chalk.white(` [${r.bot}] `) + chalk.gray(`${r.field}: `) + chalk.white(r.value));
|
|
127
|
+
});
|
|
128
|
+
console.log('');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function showMemory(botId) {
|
|
132
|
+
const config = getConfig();
|
|
133
|
+
const id = botId || 'universal-provider';
|
|
134
|
+
const mem = loadMemory(id);
|
|
135
|
+
|
|
136
|
+
console.log('');
|
|
137
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
138
|
+
console.log(chalk.cyan.bold(`\n Hafıza: ${mem.botName || id}\n`));
|
|
139
|
+
|
|
140
|
+
if (mem.name) console.log(chalk.gray(' İsim : ') + chalk.white(mem.name));
|
|
141
|
+
if (mem.nickname) console.log(chalk.gray(' Lakap : ') + chalk.white(mem.nickname));
|
|
142
|
+
if (mem.botName) console.log(chalk.gray(' Bot adı : ') + chalk.cyan(mem.botName));
|
|
143
|
+
|
|
144
|
+
const facts = mem.facts || [];
|
|
145
|
+
if (facts.length > 0) {
|
|
146
|
+
console.log(chalk.gray('\n Bilgiler:\n'));
|
|
147
|
+
facts.forEach((f, i) => {
|
|
148
|
+
const val = typeof f === 'string' ? f : f.value;
|
|
149
|
+
const score = typeof f === 'object' ? f.score : 5;
|
|
150
|
+
console.log(chalk.gray(` ${(i + 1).toString().padStart(2)}. `) + chalk.white(val) + chalk.gray(` (${score})`));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
console.log('');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function clearMemoryCmd(botId) {
|
|
157
|
+
const id = botId || 'universal-provider';
|
|
158
|
+
clearMemory(id);
|
|
159
|
+
console.log(chalk.green(`\n ✓ Hafıza temizlendi: ${id}\n`));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function indexMemory() {
|
|
163
|
+
if (!fs.existsSync(MEMORY_DIR)) {
|
|
164
|
+
console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
|
|
169
|
+
let indexed = 0;
|
|
170
|
+
|
|
171
|
+
files.forEach(file => {
|
|
172
|
+
const botId = file.replace('.json', '');
|
|
173
|
+
try {
|
|
174
|
+
const mem = loadMemory(botId);
|
|
175
|
+
// Bozuk fact'leri temizle
|
|
176
|
+
if (Array.isArray(mem.facts)) {
|
|
177
|
+
mem.facts = mem.facts.filter(f => {
|
|
178
|
+
const val = typeof f === 'string' ? f : f?.value;
|
|
179
|
+
return val && typeof val === 'string' && val.length > 0;
|
|
180
|
+
});
|
|
181
|
+
saveMemory(botId, mem);
|
|
182
|
+
indexed++;
|
|
183
|
+
}
|
|
184
|
+
} catch {}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
console.log(chalk.green(`\n ✓ ${indexed} hafıza dosyası yeniden indexlendi\n`));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = memoryCmd;
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
|
|
5
|
+
const PROVIDER_MODELS = {
|
|
6
|
+
'api.groq.com': [
|
|
7
|
+
{ id: 'llama-3.3-70b-versatile', label: 'Llama 3.3 70B Versatile (önerilen)' },
|
|
8
|
+
{ id: 'llama-3.1-8b-instant', label: 'Llama 3.1 8B Instant (hızlı)' },
|
|
9
|
+
{ id: 'llama-3.1-70b-versatile', label: 'Llama 3.1 70B Versatile' },
|
|
10
|
+
{ id: 'mixtral-8x7b-32768', label: 'Mixtral 8x7B' },
|
|
11
|
+
{ id: 'gemma2-9b-it', label: 'Gemma 2 9B' },
|
|
12
|
+
],
|
|
13
|
+
'api.openai.com': [
|
|
14
|
+
{ id: 'gpt-4o', label: 'GPT-4o (önerilen)' },
|
|
15
|
+
{ id: 'gpt-4o-mini', label: 'GPT-4o Mini (hızlı)' },
|
|
16
|
+
{ id: 'gpt-4-turbo', label: 'GPT-4 Turbo' },
|
|
17
|
+
{ id: 'gpt-3.5-turbo',label: 'GPT-3.5 Turbo (ucuz)' },
|
|
18
|
+
],
|
|
19
|
+
'api.anthropic.com': [
|
|
20
|
+
{ id: 'claude-opus-4-7', label: 'Claude Opus 4.7 (en güçlü)' },
|
|
21
|
+
{ id: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6 (önerilen)' },
|
|
22
|
+
{ id: 'claude-haiku-4-5-20251001',label: 'Claude Haiku 4.5 (hızlı)' },
|
|
23
|
+
],
|
|
24
|
+
'api.together.xyz': [
|
|
25
|
+
{ id: 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo', label: 'Llama 3.1 70B Turbo' },
|
|
26
|
+
{ id: 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo', label: 'Llama 3.1 8B Turbo' },
|
|
27
|
+
{ id: 'mistralai/Mixtral-8x7B-Instruct-v0.1', label: 'Mixtral 8x7B' },
|
|
28
|
+
],
|
|
29
|
+
'natureco.me': [
|
|
30
|
+
{ id: 'natureco-default', label: 'NatureCo Default (otomatik)' },
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
async function models(args) {
|
|
35
|
+
const [action, ...params] = (args || []);
|
|
36
|
+
|
|
37
|
+
if (!action || action === 'list' || action === 'status') return listModels();
|
|
38
|
+
if (action === 'set') return setModel(params[0]);
|
|
39
|
+
if (action === 'scan') return scanModels();
|
|
40
|
+
if (action === 'aliases') return manageAliases(params);
|
|
41
|
+
|
|
42
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
43
|
+
console.log(chalk.gray(' Kullanım: natureco models [list|set|scan|aliases]\n'));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function listModels() {
|
|
48
|
+
const config = getConfig();
|
|
49
|
+
const providerUrl = config.providerUrl || '';
|
|
50
|
+
const currentModel = config.providerModel || 'bilinmiyor';
|
|
51
|
+
|
|
52
|
+
// Provider'a göre model listesi bul
|
|
53
|
+
let modelList = [];
|
|
54
|
+
for (const [domain, list] of Object.entries(PROVIDER_MODELS)) {
|
|
55
|
+
if (providerUrl.includes(domain)) {
|
|
56
|
+
modelList = list;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const providerHost = providerUrl.replace('https://', '').split('/')[0] || 'yapılandırılmamış';
|
|
62
|
+
|
|
63
|
+
console.log('');
|
|
64
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
65
|
+
console.log(chalk.cyan.bold('\n Model Yapılandırması\n'));
|
|
66
|
+
console.log(chalk.gray(' Provider : ') + chalk.white(providerHost));
|
|
67
|
+
console.log(chalk.gray(' Aktif : ') + chalk.cyan(currentModel));
|
|
68
|
+
|
|
69
|
+
if (config.modelAliases && Object.keys(config.modelAliases).length > 0) {
|
|
70
|
+
console.log(chalk.gray(' Takma ad : ') + chalk.white(
|
|
71
|
+
Object.entries(config.modelAliases).map(([k, v]) => `${k}→${v}`).join(', ')
|
|
72
|
+
));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (modelList.length > 0) {
|
|
76
|
+
console.log(chalk.cyan.bold('\n Mevcut Modeller\n'));
|
|
77
|
+
modelList.forEach(m => {
|
|
78
|
+
const active = m.id === currentModel ? chalk.green(' ← aktif') : '';
|
|
79
|
+
console.log(chalk.white(` ${m.id}`) + active);
|
|
80
|
+
console.log(chalk.gray(` ${m.label}`));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
86
|
+
console.log(chalk.gray(' Değiştirmek için: ') + chalk.cyan('natureco models set <model-id>'));
|
|
87
|
+
console.log(chalk.gray(' Taramak için: ') + chalk.cyan('natureco models scan\n'));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function setModel(modelId) {
|
|
91
|
+
const config = getConfig();
|
|
92
|
+
const providerUrl = config.providerUrl || '';
|
|
93
|
+
|
|
94
|
+
if (!modelId) {
|
|
95
|
+
// İnteraktif seçim
|
|
96
|
+
let modelList = [];
|
|
97
|
+
for (const [domain, list] of Object.entries(PROVIDER_MODELS)) {
|
|
98
|
+
if (providerUrl.includes(domain)) {
|
|
99
|
+
modelList = list;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (modelList.length === 0) {
|
|
105
|
+
const { customModel } = await inquirer.prompt([{
|
|
106
|
+
type: 'input',
|
|
107
|
+
name: 'customModel',
|
|
108
|
+
message: ' Model ID girin:',
|
|
109
|
+
validate: v => v.trim() ? true : 'Model ID gerekli',
|
|
110
|
+
}]);
|
|
111
|
+
modelId = customModel.trim();
|
|
112
|
+
} else {
|
|
113
|
+
const { selected } = await inquirer.prompt([{
|
|
114
|
+
type: 'list',
|
|
115
|
+
name: 'selected',
|
|
116
|
+
message: ' Model seç:',
|
|
117
|
+
choices: modelList.map(m => ({ name: m.label, value: m.id })),
|
|
118
|
+
}]);
|
|
119
|
+
modelId = selected;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
config.providerModel = modelId;
|
|
124
|
+
saveConfig(config);
|
|
125
|
+
|
|
126
|
+
console.log(chalk.green(`\n ✓ Model güncellendi: ${modelId}\n`));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function scanModels() {
|
|
130
|
+
const config = getConfig();
|
|
131
|
+
const providerUrl = config.providerUrl || '';
|
|
132
|
+
|
|
133
|
+
console.log(chalk.gray('\n Modeller taranıyor...\n'));
|
|
134
|
+
|
|
135
|
+
// OpenRouter ücretsiz modelleri
|
|
136
|
+
if (providerUrl.includes('openrouter')) {
|
|
137
|
+
try {
|
|
138
|
+
const res = await fetch('https://openrouter.ai/api/v1/models', {
|
|
139
|
+
headers: { 'Authorization': `Bearer ${config.providerApiKey}` }
|
|
140
|
+
});
|
|
141
|
+
if (res.ok) {
|
|
142
|
+
const data = await res.json();
|
|
143
|
+
const free = (data.data || []).filter(m => m.pricing?.prompt === '0');
|
|
144
|
+
console.log(chalk.cyan.bold(` OpenRouter Ücretsiz Modeller (${free.length})\n`));
|
|
145
|
+
free.slice(0, 15).forEach(m => {
|
|
146
|
+
console.log(chalk.white(` ${m.id}`));
|
|
147
|
+
console.log(chalk.gray(` ${(m.description || '').slice(0, 60)}`));
|
|
148
|
+
});
|
|
149
|
+
console.log('');
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
} catch {}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Provider'a göre bilinen modelleri göster
|
|
156
|
+
let modelList = [];
|
|
157
|
+
for (const [domain, list] of Object.entries(PROVIDER_MODELS)) {
|
|
158
|
+
if (providerUrl.includes(domain)) {
|
|
159
|
+
modelList = list;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (modelList.length > 0) {
|
|
165
|
+
console.log(chalk.cyan.bold(` Bilinen Modeller\n`));
|
|
166
|
+
modelList.forEach(m => {
|
|
167
|
+
console.log(chalk.white(` ${m.id}`));
|
|
168
|
+
console.log(chalk.gray(` ${m.label}`));
|
|
169
|
+
});
|
|
170
|
+
} else {
|
|
171
|
+
console.log(chalk.gray(' Bu provider için model listesi bilinmiyor.'));
|
|
172
|
+
console.log(chalk.gray(' Manuel ayarlamak için: ') + chalk.cyan('natureco models set <model-id>\n'));
|
|
173
|
+
}
|
|
174
|
+
console.log('');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function manageAliases(params) {
|
|
178
|
+
const config = getConfig();
|
|
179
|
+
const aliases = config.modelAliases || {};
|
|
180
|
+
|
|
181
|
+
if (params.length === 0) {
|
|
182
|
+
// Listele
|
|
183
|
+
console.log(chalk.cyan.bold('\n Model Takma Adları\n'));
|
|
184
|
+
if (Object.keys(aliases).length === 0) {
|
|
185
|
+
console.log(chalk.gray(' Takma ad yok.\n'));
|
|
186
|
+
console.log(chalk.gray(' Eklemek için: ') + chalk.cyan('natureco models aliases <takma-ad> <model-id>\n'));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
Object.entries(aliases).forEach(([alias, model]) => {
|
|
190
|
+
console.log(chalk.white(` ${alias.padEnd(15)} → `) + chalk.cyan(model));
|
|
191
|
+
});
|
|
192
|
+
console.log('');
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (params.length === 2) {
|
|
197
|
+
const [alias, modelId] = params;
|
|
198
|
+
aliases[alias] = modelId;
|
|
199
|
+
config.modelAliases = aliases;
|
|
200
|
+
saveConfig(config);
|
|
201
|
+
console.log(chalk.green(`\n ✓ Takma ad eklendi: ${alias} → ${modelId}\n`));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (params.length === 1 && aliases[params[0]]) {
|
|
206
|
+
delete aliases[params[0]];
|
|
207
|
+
config.modelAliases = aliases;
|
|
208
|
+
saveConfig(config);
|
|
209
|
+
console.log(chalk.green(`\n ✓ Takma ad silindi: ${params[0]}\n`));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
console.log(chalk.gray('\n Kullanım: natureco models aliases [<takma-ad> <model-id>]\n'));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = models;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const { CONFIG_DIR, CONFIG_FILE } = require('../utils/config');
|
|
7
|
+
|
|
8
|
+
async function reset(args) {
|
|
9
|
+
const scope = args?.find(a => a.startsWith('--scope='))?.split('=')[1]
|
|
10
|
+
|| (args?.includes('--scope') ? args[args.indexOf('--scope') + 1] : null)
|
|
11
|
+
|| 'config';
|
|
12
|
+
const yes = args?.includes('--yes') || args?.includes('-y');
|
|
13
|
+
|
|
14
|
+
console.log('');
|
|
15
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
16
|
+
console.log(chalk.yellow.bold('\n NatureCo CLI — Sıfırlama\n'));
|
|
17
|
+
|
|
18
|
+
const scopeDescriptions = {
|
|
19
|
+
config: 'Sadece config dosyasını sıfırla (~/.natureco/config.json)',
|
|
20
|
+
memory: 'Tüm hafıza dosyalarını sil (~/.natureco/memory/)',
|
|
21
|
+
sessions: 'Tüm session dosyalarını sil (~/.natureco/sessions/)',
|
|
22
|
+
full: 'Her şeyi sil (~/.natureco/ klasörü tamamen)',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
console.log(chalk.gray(` Kapsam: `) + chalk.white(scope));
|
|
26
|
+
console.log(chalk.gray(` İşlem: `) + chalk.yellow(scopeDescriptions[scope] || scopeDescriptions.config));
|
|
27
|
+
console.log('');
|
|
28
|
+
|
|
29
|
+
if (!yes) {
|
|
30
|
+
const { confirm } = await inquirer.prompt([{
|
|
31
|
+
type: 'confirm',
|
|
32
|
+
name: 'confirm',
|
|
33
|
+
message: ' Devam etmek istediğinizden emin misiniz?',
|
|
34
|
+
default: false,
|
|
35
|
+
}]);
|
|
36
|
+
if (!confirm) {
|
|
37
|
+
console.log(chalk.gray('\n İptal edildi.\n'));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (scope === 'config' || scope === 'full') {
|
|
43
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
44
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
45
|
+
console.log(chalk.green(' ✓ Config dosyası silindi'));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (scope === 'memory' || scope === 'full') {
|
|
50
|
+
const memDir = path.join(CONFIG_DIR, 'memory');
|
|
51
|
+
if (fs.existsSync(memDir)) {
|
|
52
|
+
fs.rmSync(memDir, { recursive: true, force: true });
|
|
53
|
+
console.log(chalk.green(' ✓ Hafıza dosyaları silindi'));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (scope === 'sessions' || scope === 'full') {
|
|
58
|
+
const sessDir = path.join(CONFIG_DIR, 'sessions');
|
|
59
|
+
if (fs.existsSync(sessDir)) {
|
|
60
|
+
fs.rmSync(sessDir, { recursive: true, force: true });
|
|
61
|
+
console.log(chalk.green(' ✓ Session dosyaları silindi'));
|
|
62
|
+
}
|
|
63
|
+
const convDir = path.join(CONFIG_DIR, 'conversations');
|
|
64
|
+
if (fs.existsSync(convDir)) {
|
|
65
|
+
fs.rmSync(convDir, { recursive: true, force: true });
|
|
66
|
+
console.log(chalk.green(' ✓ Konuşma geçmişi silindi'));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (scope === 'full') {
|
|
71
|
+
// WhatsApp sessions
|
|
72
|
+
const waDir = path.join(CONFIG_DIR, 'whatsapp-sessions');
|
|
73
|
+
if (fs.existsSync(waDir)) {
|
|
74
|
+
fs.rmSync(waDir, { recursive: true, force: true });
|
|
75
|
+
console.log(chalk.green(' ✓ WhatsApp session\'ları silindi'));
|
|
76
|
+
}
|
|
77
|
+
// Skills
|
|
78
|
+
const skillsDir = path.join(CONFIG_DIR, 'skills');
|
|
79
|
+
if (fs.existsSync(skillsDir)) {
|
|
80
|
+
fs.rmSync(skillsDir, { recursive: true, force: true });
|
|
81
|
+
console.log(chalk.green(' ✓ Skill\'ler silindi'));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log('');
|
|
86
|
+
console.log(chalk.green(' ✓ Sıfırlama tamamlandı!'));
|
|
87
|
+
if (scope === 'config' || scope === 'full') {
|
|
88
|
+
console.log(chalk.gray('\n Yeniden kurulum için: ') + chalk.cyan('natureco setup\n'));
|
|
89
|
+
} else {
|
|
90
|
+
console.log('');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = reset;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const { getConfig, CONFIG_FILE, CONFIG_DIR } = require('../utils/config');
|
|
6
|
+
|
|
7
|
+
async function security(args) {
|
|
8
|
+
const [action, ...params] = (args || []);
|
|
9
|
+
|
|
10
|
+
if (!action || action === 'audit') return audit(args);
|
|
11
|
+
|
|
12
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
13
|
+
console.log(chalk.gray(' Kullanım: natureco security [audit]\n'));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function audit(args) {
|
|
18
|
+
const fix = args.includes('--fix');
|
|
19
|
+
const json = args.includes('--json');
|
|
20
|
+
|
|
21
|
+
const issues = [];
|
|
22
|
+
const warnings = [];
|
|
23
|
+
const ok = [];
|
|
24
|
+
|
|
25
|
+
// 1. Config dosyası izinleri
|
|
26
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
27
|
+
try {
|
|
28
|
+
const stat = fs.statSync(CONFIG_FILE);
|
|
29
|
+
const mode = (stat.mode & 0o777).toString(8);
|
|
30
|
+
if (process.platform !== 'win32' && mode !== '600' && mode !== '644') {
|
|
31
|
+
issues.push({
|
|
32
|
+
id: 'config-permissions',
|
|
33
|
+
msg: `Config dosyası izinleri geniş: ${mode} (önerilen: 600)`,
|
|
34
|
+
fix: () => fs.chmodSync(CONFIG_FILE, 0o600),
|
|
35
|
+
});
|
|
36
|
+
} else {
|
|
37
|
+
ok.push('Config dosyası izinleri');
|
|
38
|
+
}
|
|
39
|
+
} catch {}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 2. API key formatı
|
|
43
|
+
const config = getConfig();
|
|
44
|
+
if (config.providerApiKey) {
|
|
45
|
+
if (config.providerApiKey.length < 10) {
|
|
46
|
+
issues.push({ id: 'weak-api-key', msg: 'API key çok kısa görünüyor' });
|
|
47
|
+
} else {
|
|
48
|
+
ok.push('API key formatı');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 3. Debug mode
|
|
53
|
+
if (config.debug === true) {
|
|
54
|
+
warnings.push({ id: 'debug-mode', msg: 'Debug modu açık — API key\'ler loglara yazılabilir' });
|
|
55
|
+
} else {
|
|
56
|
+
ok.push('Debug modu kapalı');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 4. WhatsApp session dosyaları
|
|
60
|
+
const waDir = path.join(CONFIG_DIR, 'whatsapp-sessions');
|
|
61
|
+
if (fs.existsSync(waDir)) {
|
|
62
|
+
const sessions = fs.readdirSync(waDir);
|
|
63
|
+
if (sessions.length > 3) {
|
|
64
|
+
warnings.push({ id: 'old-wa-sessions', msg: `${sessions.length} WhatsApp session var — eskiler temizlenebilir` });
|
|
65
|
+
} else {
|
|
66
|
+
ok.push('WhatsApp session sayısı');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 5. Gateway log boyutu
|
|
71
|
+
const logFile = path.join(CONFIG_DIR, 'gateway.log');
|
|
72
|
+
if (fs.existsSync(logFile)) {
|
|
73
|
+
const stat = fs.statSync(logFile);
|
|
74
|
+
const sizeMB = stat.size / (1024 * 1024);
|
|
75
|
+
if (sizeMB > 50) {
|
|
76
|
+
warnings.push({ id: 'large-log', msg: `Gateway log dosyası büyük: ${sizeMB.toFixed(1)}MB` });
|
|
77
|
+
} else {
|
|
78
|
+
ok.push('Gateway log boyutu');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 6. Eski conversation dosyaları
|
|
83
|
+
const convDir = path.join(CONFIG_DIR, 'conversations');
|
|
84
|
+
if (fs.existsSync(convDir)) {
|
|
85
|
+
const convFiles = fs.readdirSync(convDir).filter(f => f.endsWith('.json'));
|
|
86
|
+
if (convFiles.length > 20) {
|
|
87
|
+
warnings.push({ id: 'old-conversations', msg: `${convFiles.length} konuşma dosyası var — eskiler temizlenebilir` });
|
|
88
|
+
} else {
|
|
89
|
+
ok.push('Konuşma dosyası sayısı');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (json) {
|
|
94
|
+
console.log(JSON.stringify({ ok, warnings: warnings.map(w => w.msg), issues: issues.map(i => i.msg) }, null, 2));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
100
|
+
console.log(chalk.cyan.bold('\n Güvenlik Denetimi\n'));
|
|
101
|
+
|
|
102
|
+
ok.forEach(msg => console.log(chalk.green(' ✓ ') + chalk.gray(msg)));
|
|
103
|
+
|
|
104
|
+
if (warnings.length > 0) {
|
|
105
|
+
console.log('');
|
|
106
|
+
warnings.forEach(w => console.log(chalk.yellow(' ⚠ ') + chalk.yellow(w.msg)));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (issues.length > 0) {
|
|
110
|
+
console.log('');
|
|
111
|
+
issues.forEach(i => console.log(chalk.red(' ❌ ') + chalk.red(i.msg)));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log('');
|
|
115
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
116
|
+
|
|
117
|
+
if (issues.length === 0 && warnings.length === 0) {
|
|
118
|
+
console.log(chalk.green(' ✓ Güvenlik sorunu bulunamadı\n'));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log(chalk.gray(` ${ok.length} geçti · ${warnings.length} uyarı · ${issues.length} sorun`));
|
|
123
|
+
|
|
124
|
+
if (fix && issues.length > 0) {
|
|
125
|
+
console.log('');
|
|
126
|
+
issues.forEach(i => {
|
|
127
|
+
if (i.fix) {
|
|
128
|
+
try {
|
|
129
|
+
i.fix();
|
|
130
|
+
console.log(chalk.green(` ✓ Düzeltildi: ${i.id}`));
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.log(chalk.red(` ❌ Düzeltilemedi: ${i.id} — ${e.message}`));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
} else if (issues.length > 0) {
|
|
137
|
+
console.log(chalk.gray('\n Otomatik düzeltmek için: ') + chalk.cyan('natureco security audit --fix'));
|
|
138
|
+
}
|
|
139
|
+
console.log('');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
module.exports = security;
|
package/src/commands/skills.js
CHANGED
|
@@ -68,37 +68,33 @@ async function skills(args) {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
async function listSkills() {
|
|
71
|
-
console.log(chalk.green.bold('\n╭─ Yüklü Skill\'ler ─╮\n'));
|
|
72
|
-
|
|
73
71
|
const allSkills = getSkills();
|
|
74
72
|
|
|
73
|
+
console.log(chalk.gray('\n ' + '─'.repeat(48)));
|
|
74
|
+
console.log(chalk.cyan.bold('\n Yüklü Skill\'ler\n'));
|
|
75
|
+
|
|
75
76
|
if (allSkills.length === 0) {
|
|
76
|
-
console.log(chalk.gray('Hiç skill yüklü değil.\n'));
|
|
77
|
-
console.log(chalk.
|
|
77
|
+
console.log(chalk.gray(' Hiç skill yüklü değil.\n'));
|
|
78
|
+
console.log(chalk.gray(' Yüklemek için: ') + chalk.cyan('natureco skills install <slug>'));
|
|
79
|
+
console.log(chalk.gray(' Gözatmak için: ') + chalk.cyan('natureco skills browse\n'));
|
|
78
80
|
return;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
allSkills.forEach((skill, index) => {
|
|
82
|
-
const sourceLabel = skill.source === 'builtin' ? chalk.blue('[
|
|
83
|
-
skill.source === 'user' ? chalk.cyan('[
|
|
84
|
-
chalk.magenta('[
|
|
85
|
-
|
|
86
|
-
console.log(chalk.
|
|
87
|
-
console.log(chalk.gray(` ${skill.description}`));
|
|
88
|
-
|
|
84
|
+
const sourceLabel = skill.source === 'builtin' ? chalk.blue('[yerleşik]') :
|
|
85
|
+
skill.source === 'user' ? chalk.cyan('[kişisel]') :
|
|
86
|
+
chalk.magenta('[proje]');
|
|
87
|
+
console.log(chalk.white(` ${index + 1}. ${skill.name} `) + sourceLabel);
|
|
88
|
+
console.log(chalk.gray(` ${skill.description}`));
|
|
89
89
|
if (skill.metadata?.requires?.bins) {
|
|
90
|
-
console.log(chalk.gray(`
|
|
90
|
+
console.log(chalk.gray(` Gerekli: ${skill.metadata.requires.bins.join(', ')}`));
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
if (skill.metadata?.os) {
|
|
94
|
-
console.log(chalk.gray(` Platform: ${skill.metadata.os.join(', ')}`));
|
|
95
|
-
}
|
|
96
|
-
|
|
97
92
|
console.log('');
|
|
98
93
|
});
|
|
99
94
|
|
|
100
|
-
console.log(chalk.
|
|
101
|
-
console.log(chalk.gray(`Toplam: ${allSkills.length} skill
|
|
95
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
96
|
+
console.log(chalk.gray(` Toplam: ${allSkills.length} skill`));
|
|
97
|
+
console.log(chalk.gray(' Kaldırmak için: ') + chalk.cyan('natureco skills remove <slug>\n'));
|
|
102
98
|
}
|
|
103
99
|
|
|
104
100
|
async function installSkillCommand(slug) {
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
const { getSkills } = require('../utils/skills');
|
|
7
|
+
|
|
8
|
+
async function status() {
|
|
9
|
+
const config = getConfig();
|
|
10
|
+
const version = require('../../package.json').version;
|
|
11
|
+
|
|
12
|
+
console.log('');
|
|
13
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
14
|
+
console.log(chalk.cyan.bold('\n NatureCo CLI — Durum\n'));
|
|
15
|
+
|
|
16
|
+
// Provider
|
|
17
|
+
const providerHost = config.providerUrl
|
|
18
|
+
? config.providerUrl.replace('https://', '').split('/')[0]
|
|
19
|
+
: null;
|
|
20
|
+
|
|
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));
|
|
30
|
+
|
|
31
|
+
// Gateway durumu
|
|
32
|
+
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
|
+
const dashPid = path.join(os.homedir(), '.natureco', 'dashboard.pid');
|
|
38
|
+
const dashRunning = fs.existsSync(dashPid);
|
|
39
|
+
console.log(chalk.gray(' Dashboard : ') + (dashRunning ? chalk.green('çalışıyor (localhost:3848)') : chalk.gray('durdurulmuş')));
|
|
40
|
+
|
|
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')));
|
|
48
|
+
|
|
49
|
+
// Skills
|
|
50
|
+
const skills = getSkills();
|
|
51
|
+
console.log(chalk.gray(' Skills : ') + chalk.white(`${skills.length} yüklü`));
|
|
52
|
+
|
|
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`));
|
|
57
|
+
|
|
58
|
+
// Son session
|
|
59
|
+
const sessDir = path.join(os.homedir(), '.natureco', 'sessions');
|
|
60
|
+
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
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Son loglar
|
|
68
|
+
const logFile = path.join(os.homedir(), '.natureco', 'gateway.log');
|
|
69
|
+
if (fs.existsSync(logFile)) {
|
|
70
|
+
const lines = fs.readFileSync(logFile, 'utf-8').split('\n').filter(l => l.trim());
|
|
71
|
+
const last = lines.slice(-3);
|
|
72
|
+
if (last.length > 0) {
|
|
73
|
+
console.log(chalk.gray('\n Son Loglar:\n'));
|
|
74
|
+
last.forEach(l => console.log(chalk.gray(' ' + l)));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
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'));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = status;
|
|
@@ -16,13 +16,24 @@ async function ultrareview(filePath) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const config = getConfig();
|
|
19
|
-
const defaultBotId = config.defaultBotId;
|
|
19
|
+
const defaultBotId = config.defaultBotId || config.botName || 'universal-provider';
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
// getBots ile gerçek bot ID'yi al
|
|
22
|
+
const apiKey = getApiKey();
|
|
23
|
+
if (!apiKey && !config.providerApiKey) {
|
|
24
|
+
console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
|
|
23
25
|
process.exit(1);
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
let botId = defaultBotId;
|
|
29
|
+
try {
|
|
30
|
+
const botList = await getBots(apiKey || config.providerApiKey);
|
|
31
|
+
if (botList?.bots?.length > 0) {
|
|
32
|
+
const matched = botList.bots.find(b => b.name === config.botName) || botList.bots[0];
|
|
33
|
+
botId = matched.id;
|
|
34
|
+
}
|
|
35
|
+
} catch { /* fallback to defaultBotId */ }
|
|
36
|
+
|
|
26
37
|
let code;
|
|
27
38
|
let filename;
|
|
28
39
|
|
|
@@ -99,7 +110,7 @@ ${code}
|
|
|
99
110
|
\`\`\``;
|
|
100
111
|
|
|
101
112
|
try {
|
|
102
|
-
const response = await sendMessage(apiKey,
|
|
113
|
+
const response = await sendMessage(apiKey || config.providerApiKey, botId, prompt, null, '');
|
|
103
114
|
const review = response.reply || response.message || 'No response';
|
|
104
115
|
|
|
105
116
|
console.log(chalk.green('\n📊 Ultra Review:\n'));
|