natureco-cli 1.0.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.
@@ -0,0 +1,222 @@
1
+ const chalk = require('chalk');
2
+ const boxen = require('boxen');
3
+ const inquirer = require('inquirer');
4
+ const fs = require('fs');
5
+ const { saveConfig, CONFIG_DIR, CONFIG_FILE } = require('../utils/config');
6
+ const { getBots } = require('../utils/api');
7
+
8
+ async function setup() {
9
+ // Kurulum ekranı
10
+ const welcomeBox = boxen(
11
+ chalk.green.bold('🌿 NatureCo Terminal\n') +
12
+ chalk.green.bold(' İlk Kurulum\n'),
13
+ {
14
+ padding: 1,
15
+ margin: 1,
16
+ borderStyle: 'round',
17
+ borderColor: 'green',
18
+ align: 'center',
19
+ }
20
+ );
21
+
22
+ console.clear();
23
+ console.log(welcomeBox);
24
+ console.log(chalk.yellow('Hoş geldiniz! NatureCo CLI\'yi ilk kez'));
25
+ console.log(chalk.yellow('kullanıyorsunuz.\n'));
26
+
27
+ // Klasör oluştur
28
+ console.log(chalk.cyan('✦ ~/.natureco/ klasörü oluşturuluyor...'));
29
+ if (!fs.existsSync(CONFIG_DIR)) {
30
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
31
+ }
32
+ console.log(chalk.green(' ✓ Klasör oluşturuldu\n'));
33
+
34
+ console.log(chalk.cyan('✦ Varsayılan ayarlar yükleniyor...'));
35
+ console.log(chalk.green(' ✓ Ayarlar hazır\n'));
36
+
37
+ // API key sor
38
+ process.stdin.resume();
39
+ const { apiKey } = await inquirer.prompt([
40
+ {
41
+ type: 'input',
42
+ name: 'apiKey',
43
+ message: 'API key girin:',
44
+ validate: async (input) => {
45
+ if (!input || input.trim().length === 0) {
46
+ return 'API key gerekli';
47
+ }
48
+
49
+ const trimmed = input.trim();
50
+ if (!trimmed.startsWith('nc_') && !trimmed.startsWith('nco_')) {
51
+ return 'API key nc_ veya nco_ ile başlamalı';
52
+ }
53
+
54
+ // API key'i validate et
55
+ console.log(chalk.yellow('\n ⏳ API key doğrulanıyor...'));
56
+ try {
57
+ const response = await fetch('https://api.natureco.me/api/v1/bots', {
58
+ headers: {
59
+ 'Authorization': `Bearer ${trimmed}`,
60
+ 'Content-Type': 'application/json',
61
+ },
62
+ });
63
+
64
+ if (!response.ok) {
65
+ return 'Geçersiz API key';
66
+ }
67
+
68
+ const data = await response.json();
69
+ if (!data.bots || data.bots.length === 0) {
70
+ return 'Bu API key ile bot bulunamadı';
71
+ }
72
+
73
+ console.log(chalk.green(' ✓ API key doğrulandı\n'));
74
+ return true;
75
+ } catch (err) {
76
+ return `API hatası: ${err.message}`;
77
+ }
78
+ },
79
+ },
80
+ ]);
81
+
82
+ const trimmedApiKey = apiKey.trim();
83
+
84
+ // Botları çek
85
+ console.log(chalk.yellow('⏳ Botlar yükleniyor...\n'));
86
+ let botList;
87
+ try {
88
+ botList = await getBots(trimmedApiKey);
89
+ } catch (err) {
90
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
91
+ process.exit(1);
92
+ }
93
+
94
+ if (!botList || !botList.bots || botList.bots.length === 0) {
95
+ console.log(chalk.red('❌ Bot bulunamadı.\n'));
96
+ process.exit(1);
97
+ }
98
+
99
+ // Bot seç
100
+ process.stdin.resume();
101
+ const { selectedBotId } = await inquirer.prompt([
102
+ {
103
+ type: 'list',
104
+ name: 'selectedBotId',
105
+ message: 'Varsayılan bot seçin:',
106
+ choices: botList.bots.map(b => ({
107
+ name: b.name,
108
+ value: b.id,
109
+ })),
110
+ },
111
+ ]);
112
+
113
+ const selectedBot = botList.bots.find(b => b.id === selectedBotId);
114
+
115
+ // Telegram bağlantısı
116
+ process.stdin.resume();
117
+ const { connectTelegram } = await inquirer.prompt([
118
+ {
119
+ type: 'confirm',
120
+ name: 'connectTelegram',
121
+ message: 'Telegram bağlamak ister misiniz?',
122
+ default: false,
123
+ },
124
+ ]);
125
+
126
+ let telegramConnected = false;
127
+ let telegramSkipped = false;
128
+
129
+ if (connectTelegram) {
130
+ process.stdin.resume();
131
+ const { telegramToken } = await inquirer.prompt([
132
+ {
133
+ type: 'input',
134
+ name: 'telegramToken',
135
+ message: 'Telegram Bot Token girin (BotFather\'dan alınır):',
136
+ validate: (input) => {
137
+ if (!input || input.trim().length === 0) {
138
+ return 'Token gerekli';
139
+ }
140
+ return true;
141
+ },
142
+ },
143
+ ]);
144
+
145
+ process.stdin.resume();
146
+ const { telegramUserId } = await inquirer.prompt([
147
+ {
148
+ type: 'input',
149
+ name: 'telegramUserId',
150
+ message: 'Telegram kullanıcı ID\'niz nedir? (t.me/userinfobot ile öğrenebilirsiniz):',
151
+ validate: (val) => val.trim() !== '' || 'Kullanıcı ID boş olamaz',
152
+ },
153
+ ]);
154
+
155
+ console.log(chalk.yellow('\n⏳ Telegram bağlanıyor...\n'));
156
+
157
+ try {
158
+ const response = await fetch('https://api.natureco.me/api/agent/telegram/connect', {
159
+ method: 'POST',
160
+ headers: {
161
+ 'Authorization': `Bearer ${trimmedApiKey}`,
162
+ 'Content-Type': 'application/json',
163
+ },
164
+ body: JSON.stringify({
165
+ agent_id: selectedBotId,
166
+ telegram_bot_token: telegramToken.trim(),
167
+ telegram_user_id: telegramUserId.trim(),
168
+ }),
169
+ });
170
+
171
+ if (response.ok) {
172
+ console.log(chalk.green('✅ Telegram bağlandı\n'));
173
+ telegramConnected = true;
174
+
175
+ // Config'e telegramUserId ekle
176
+ config.telegramUserId = telegramUserId.trim();
177
+ } else {
178
+ const errorText = await response.text();
179
+ console.log(chalk.red(`❌ Telegram bağlanamadı: ${errorText}\n`));
180
+ }
181
+ } catch (err) {
182
+ console.log(chalk.red(`❌ Telegram bağlanamadı: ${err.message}\n`));
183
+ }
184
+ } else {
185
+ telegramSkipped = true;
186
+ }
187
+
188
+ // Config kaydet
189
+ const config = {
190
+ apiKey: trimmedApiKey,
191
+ defaultBot: selectedBot.name,
192
+ defaultBotId: selectedBot.id,
193
+ skills: {
194
+ enabled: true,
195
+ list: [],
196
+ },
197
+ mcpServers: {},
198
+ setupCompleted: true,
199
+ setupDate: new Date().toISOString(),
200
+ };
201
+
202
+ saveConfig(config);
203
+
204
+ // Kurulum tamamlandı
205
+ console.log(chalk.green.bold('✅ Kurulum tamamlandı!\n'));
206
+ console.log(chalk.cyan('Aktif bot:'), chalk.white(selectedBot.name));
207
+
208
+ if (telegramConnected) {
209
+ console.log(chalk.cyan('Telegram:'), chalk.green('✅ Bağlı'));
210
+ } else if (telegramSkipped) {
211
+ console.log(chalk.cyan('Telegram:'), chalk.gray('⏭ Atlandı'));
212
+ } else {
213
+ console.log(chalk.cyan('Telegram:'), chalk.red('❌ Bağlanamadı'));
214
+ }
215
+
216
+ console.log(chalk.cyan('Config:'), chalk.white(CONFIG_FILE));
217
+ console.log('');
218
+ console.log(chalk.yellow('Başlamak için:'), chalk.cyan('natureco chat'));
219
+ console.log('');
220
+ }
221
+
222
+ module.exports = setup;
@@ -0,0 +1,161 @@
1
+ const chalk = require('chalk');
2
+ const inquirer = require('inquirer');
3
+ const { getSkills, installSkill, removeSkill, updateAllSkills, createSkillTemplate } = require('../utils/skills');
4
+
5
+ async function skills(args) {
6
+ const [action, ...params] = args;
7
+
8
+ if (!action || action === 'list') {
9
+ await listSkills();
10
+ return;
11
+ }
12
+
13
+ if (action === 'install') {
14
+ const slug = params[0];
15
+ if (!slug) {
16
+ console.log(chalk.red('\n❌ Kullanım: natureco skills install <slug>\n'));
17
+ process.exit(1);
18
+ }
19
+ await installSkillCommand(slug);
20
+ return;
21
+ }
22
+
23
+ if (action === 'remove') {
24
+ const slug = params[0];
25
+ if (!slug) {
26
+ console.log(chalk.red('\n❌ Kullanım: natureco skills remove <slug>\n'));
27
+ process.exit(1);
28
+ }
29
+ await removeSkillCommand(slug);
30
+ return;
31
+ }
32
+
33
+ if (action === 'update') {
34
+ const flag = params[0];
35
+ if (flag === '--all') {
36
+ await updateAllSkillsCommand();
37
+ } else {
38
+ console.log(chalk.red('\n❌ Kullanım: natureco skills update --all\n'));
39
+ process.exit(1);
40
+ }
41
+ return;
42
+ }
43
+
44
+ if (action === 'create') {
45
+ const name = params[0];
46
+ if (!name) {
47
+ console.log(chalk.red('\n❌ Kullanım: natureco skills create <ad>\n'));
48
+ process.exit(1);
49
+ }
50
+ await createSkillCommand(name);
51
+ return;
52
+ }
53
+
54
+ console.log(chalk.red(`\n❌ Geçersiz action: ${action}\n`));
55
+ console.log(chalk.gray('Kullanım: natureco skills [list|install|remove|update|create]\n'));
56
+ process.exit(1);
57
+ }
58
+
59
+ async function listSkills() {
60
+ console.log(chalk.green.bold('\n╭─ Yüklü Skill\'ler ─╮\n'));
61
+
62
+ const allSkills = getSkills();
63
+
64
+ if (allSkills.length === 0) {
65
+ console.log(chalk.gray('Hiç skill yüklü değil.\n'));
66
+ console.log(chalk.yellow('Skill yüklemek için:'), chalk.white('natureco skills install <slug>\n'));
67
+ return;
68
+ }
69
+
70
+ allSkills.forEach((skill, index) => {
71
+ const sourceLabel = skill.source === 'builtin' ? chalk.blue('[Yerleşik]') :
72
+ skill.source === 'user' ? chalk.cyan('[Kişisel]') :
73
+ chalk.magenta('[Proje]');
74
+
75
+ console.log(chalk.white(`${index + 1}. ${skill.name}`) + ' ' + sourceLabel);
76
+ console.log(chalk.gray(` ${skill.description}`));
77
+
78
+ if (skill.metadata?.requires?.bins) {
79
+ console.log(chalk.gray(` Gerekli: ${skill.metadata.requires.bins.join(', ')}`));
80
+ }
81
+
82
+ if (skill.metadata?.os) {
83
+ console.log(chalk.gray(` Platform: ${skill.metadata.os.join(', ')}`));
84
+ }
85
+
86
+ console.log('');
87
+ });
88
+
89
+ console.log(chalk.green('╰────────────────────╯\n'));
90
+ console.log(chalk.gray(`Toplam: ${allSkills.length} skill\n`));
91
+ }
92
+
93
+ async function installSkillCommand(slug) {
94
+ console.log(chalk.yellow(`\n⏳ "${slug}" skill'i yükleniyor...\n`));
95
+
96
+ try {
97
+ await installSkill(slug);
98
+ console.log(chalk.green(`✅ "${slug}" başarıyla yüklendi!\n`));
99
+ } catch (err) {
100
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
101
+ process.exit(1);
102
+ }
103
+ }
104
+
105
+ async function removeSkillCommand(slug) {
106
+ const { confirm } = await inquirer.prompt([
107
+ {
108
+ type: 'confirm',
109
+ name: 'confirm',
110
+ message: `"${slug}" skill'ini silmek istediğinizden emin misiniz?`,
111
+ default: false,
112
+ },
113
+ ]);
114
+
115
+ if (!confirm) {
116
+ console.log(chalk.gray('\nİptal edildi.\n'));
117
+ return;
118
+ }
119
+
120
+ try {
121
+ removeSkill(slug);
122
+ console.log(chalk.green(`\n✅ "${slug}" silindi.\n`));
123
+ } catch (err) {
124
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
125
+ process.exit(1);
126
+ }
127
+ }
128
+
129
+ async function updateAllSkillsCommand() {
130
+ console.log(chalk.yellow('\n⏳ Tüm skill\'ler güncelleniyor...\n'));
131
+
132
+ try {
133
+ const updated = await updateAllSkills();
134
+ if (updated.length === 0) {
135
+ console.log(chalk.gray('Güncellenecek skill bulunamadı.\n'));
136
+ } else {
137
+ console.log(chalk.green(`✅ ${updated.length} skill güncellendi:\n`));
138
+ updated.forEach(s => console.log(chalk.cyan(` - ${s}`)));
139
+ console.log('');
140
+ }
141
+ } catch (err) {
142
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
143
+ process.exit(1);
144
+ }
145
+ }
146
+
147
+ async function createSkillCommand(name) {
148
+ console.log(chalk.yellow(`\n⏳ "${name}" skill şablonu oluşturuluyor...\n`));
149
+
150
+ try {
151
+ const skillPath = createSkillTemplate(name);
152
+ console.log(chalk.green(`✅ Skill şablonu oluşturuldu:\n`));
153
+ console.log(chalk.cyan(` ${skillPath}\n`));
154
+ console.log(chalk.gray('SKILL.md dosyasını düzenleyerek skill\'i özelleştirin.\n'));
155
+ } catch (err) {
156
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
157
+ process.exit(1);
158
+ }
159
+ }
160
+
161
+ module.exports = skills;
@@ -0,0 +1,61 @@
1
+ const chalk = require('chalk');
2
+ const { execSync } = require('child_process');
3
+ const packageJson = require('../../package.json');
4
+
5
+ async function update() {
6
+ const currentVersion = packageJson.version;
7
+
8
+ console.log(chalk.yellow('\n⏳ Güncelleme kontrol ediliyor...\n'));
9
+
10
+ try {
11
+ // npm'den en son versiyonu al
12
+ const latestVersion = execSync('npm view natureco-cli version', {
13
+ encoding: 'utf8',
14
+ stdio: ['pipe', 'pipe', 'ignore'],
15
+ }).trim();
16
+
17
+ console.log(chalk.cyan('Mevcut versiyon:'), chalk.white(currentVersion));
18
+ console.log(chalk.cyan('En son versiyon:'), chalk.white(latestVersion));
19
+ console.log('');
20
+
21
+ if (currentVersion === latestVersion) {
22
+ console.log(chalk.green('✅ NatureCo CLI güncel!\n'));
23
+ return;
24
+ }
25
+
26
+ // Versiyon karşılaştırması
27
+ const isNewer = compareVersions(latestVersion, currentVersion) > 0;
28
+
29
+ if (isNewer) {
30
+ console.log(chalk.yellow('🔔 Yeni versiyon mevcut!\n'));
31
+ console.log(chalk.gray('Güncellemek için:\n'));
32
+ console.log(chalk.cyan(' npm install -g natureco-cli@latest\n'));
33
+ console.log(chalk.gray('veya\n'));
34
+ console.log(chalk.cyan(' npm update -g natureco-cli\n'));
35
+ } else {
36
+ console.log(chalk.green('✅ NatureCo CLI güncel!\n'));
37
+ }
38
+ } catch (err) {
39
+ // npm view başarısız olursa (paket henüz yayınlanmamış)
40
+ console.log(chalk.gray('Güncelleme kontrolü yapılamadı.\n'));
41
+ console.log(chalk.gray('Paket henüz npm\'de yayınlanmamış olabilir.\n'));
42
+ }
43
+ }
44
+
45
+ // Versiyon karşılaştırma (semver)
46
+ function compareVersions(v1, v2) {
47
+ const parts1 = v1.split('.').map(Number);
48
+ const parts2 = v2.split('.').map(Number);
49
+
50
+ for (let i = 0; i < 3; i++) {
51
+ const p1 = parts1[i] || 0;
52
+ const p2 = parts2[i] || 0;
53
+
54
+ if (p1 > p2) return 1;
55
+ if (p1 < p2) return -1;
56
+ }
57
+
58
+ return 0;
59
+ }
60
+
61
+ module.exports = update;
@@ -0,0 +1,28 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const AGENTS_FILE = path.join(process.cwd(), '.natureco', 'AGENTS.md');
5
+
6
+ // Read AGENTS.md content
7
+ function getAgentsPrompt() {
8
+ if (!fs.existsSync(AGENTS_FILE)) {
9
+ return '';
10
+ }
11
+
12
+ try {
13
+ const content = fs.readFileSync(AGENTS_FILE, 'utf8');
14
+ return content.trim();
15
+ } catch {
16
+ return '';
17
+ }
18
+ }
19
+
20
+ // Check if AGENTS.md exists
21
+ function hasAgentsFile() {
22
+ return fs.existsSync(AGENTS_FILE);
23
+ }
24
+
25
+ module.exports = {
26
+ getAgentsPrompt,
27
+ hasAgentsFile,
28
+ };
@@ -0,0 +1,64 @@
1
+ const API_BASE = 'https://api.natureco.me';
2
+
3
+ async function request(endpoint, options = {}) {
4
+ const url = `${API_BASE}${endpoint}`;
5
+ const response = await fetch(url, {
6
+ ...options,
7
+ headers: {
8
+ 'Content-Type': 'application/json',
9
+ ...options.headers,
10
+ },
11
+ });
12
+
13
+ if (!response.ok) {
14
+ const text = await response.text();
15
+ throw new Error(`API Error: ${response.status} - ${text}`);
16
+ }
17
+
18
+ return response.json();
19
+ }
20
+
21
+ async function getBots(apiKey) {
22
+ return request('/api/v1/bots', {
23
+ headers: { Authorization: `Bearer ${apiKey}` },
24
+ });
25
+ }
26
+
27
+ async function sendMessage(apiKey, botId, message, conversationId = null, skillPrompts = '') {
28
+ const body = {
29
+ agent_id: botId,
30
+ message,
31
+ conversation_id: conversationId,
32
+ platform: 'cli',
33
+ user_id: 'cli-user'
34
+ };
35
+
36
+ // Skill prompts varsa system_prompt olarak ekle
37
+ if (skillPrompts && skillPrompts.trim().length > 0) {
38
+ body.system_prompt = skillPrompts;
39
+ }
40
+
41
+ return request('/api/agent/chat', {
42
+ method: 'POST',
43
+ headers: {
44
+ Authorization: `Bearer ${apiKey}`,
45
+ 'X-User-ID': 'cli-user'
46
+ },
47
+ body: JSON.stringify(body),
48
+ });
49
+ }
50
+
51
+ async function validateApiKey(apiKey) {
52
+ try {
53
+ const result = await getBots(apiKey);
54
+ return true;
55
+ } catch (err) {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ module.exports = {
61
+ getBots,
62
+ sendMessage,
63
+ validateApiKey,
64
+ };
@@ -0,0 +1,81 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const os = require('os');
4
+
5
+ const CONFIG_DIR = path.join(os.homedir(), '.natureco');
6
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
7
+
8
+ function ensureConfigDir() {
9
+ if (!fs.existsSync(CONFIG_DIR)) {
10
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
11
+ }
12
+ }
13
+
14
+ function saveConfig(data) {
15
+ ensureConfigDir();
16
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8');
17
+ }
18
+
19
+ function loadConfig() {
20
+ if (!fs.existsSync(CONFIG_FILE)) {
21
+ return null;
22
+ }
23
+ try {
24
+ const content = fs.readFileSync(CONFIG_FILE, 'utf8');
25
+ return JSON.parse(content);
26
+ } catch (err) {
27
+ return null;
28
+ }
29
+ }
30
+
31
+ function deleteConfig() {
32
+ if (fs.existsSync(CONFIG_FILE)) {
33
+ fs.unlinkSync(CONFIG_FILE);
34
+ }
35
+ }
36
+
37
+ function getApiKey() {
38
+ const config = loadConfig();
39
+ return config?.apiKey || null;
40
+ }
41
+
42
+ function saveApiKey(apiKey) {
43
+ const config = loadConfig() || {};
44
+ config.apiKey = apiKey;
45
+ saveConfig(config);
46
+ }
47
+
48
+ function getConfig() {
49
+ return loadConfig() || {};
50
+ }
51
+
52
+ function getAllConfig() {
53
+ return loadConfig() || {};
54
+ }
55
+
56
+ function setConfigValue(key, value) {
57
+ const config = loadConfig() || {};
58
+ const keys = key.split('.');
59
+ let current = config;
60
+ for (let i = 0; i < keys.length - 1; i++) {
61
+ if (!current[keys[i]]) {
62
+ current[keys[i]] = {};
63
+ }
64
+ current = current[keys[i]];
65
+ }
66
+ current[keys[keys.length - 1]] = value;
67
+ saveConfig(config);
68
+ }
69
+
70
+ module.exports = {
71
+ saveConfig,
72
+ loadConfig,
73
+ deleteConfig,
74
+ getApiKey,
75
+ saveApiKey,
76
+ getConfig,
77
+ getAllConfig,
78
+ setConfigValue,
79
+ CONFIG_FILE,
80
+ CONFIG_DIR,
81
+ };
@@ -0,0 +1,87 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { CONFIG_DIR } = require('./config');
4
+
5
+ const HISTORY_DIR = path.join(CONFIG_DIR, 'history');
6
+
7
+ // Ensure history directory exists
8
+ function ensureHistoryDir() {
9
+ if (!fs.existsSync(HISTORY_DIR)) {
10
+ fs.mkdirSync(HISTORY_DIR, { recursive: true });
11
+ }
12
+ }
13
+
14
+ // Get history file path for a bot
15
+ function getHistoryFilePath(botId) {
16
+ ensureHistoryDir();
17
+ return path.join(HISTORY_DIR, `${botId}.json`);
18
+ }
19
+
20
+ // Load conversation history for a bot
21
+ function loadHistory(botId) {
22
+ const filePath = getHistoryFilePath(botId);
23
+
24
+ if (!fs.existsSync(filePath)) {
25
+ return [];
26
+ }
27
+
28
+ try {
29
+ const content = fs.readFileSync(filePath, 'utf8');
30
+ return JSON.parse(content);
31
+ } catch {
32
+ return [];
33
+ }
34
+ }
35
+
36
+ // Save conversation history for a bot
37
+ function saveHistory(botId, history) {
38
+ const filePath = getHistoryFilePath(botId);
39
+
40
+ try {
41
+ fs.writeFileSync(filePath, JSON.stringify(history, null, 2), 'utf8');
42
+ } catch (err) {
43
+ // Silently fail - history is not critical
44
+ }
45
+ }
46
+
47
+ // Add message to history
48
+ function addToHistory(botId, userMessage, botReply, conversationId = null) {
49
+ const history = loadHistory(botId);
50
+
51
+ history.push({
52
+ timestamp: new Date().toISOString(),
53
+ user: userMessage,
54
+ bot: botReply,
55
+ conversationId,
56
+ });
57
+
58
+ // Keep only last 100 messages
59
+ if (history.length > 100) {
60
+ history.shift();
61
+ }
62
+
63
+ saveHistory(botId, history);
64
+ }
65
+
66
+ // Get command history (only user messages)
67
+ function getCommandHistory(botId) {
68
+ const history = loadHistory(botId);
69
+ return history.map(h => h.user);
70
+ }
71
+
72
+ // Clear history for a bot
73
+ function clearHistory(botId) {
74
+ const filePath = getHistoryFilePath(botId);
75
+
76
+ if (fs.existsSync(filePath)) {
77
+ fs.unlinkSync(filePath);
78
+ }
79
+ }
80
+
81
+ module.exports = {
82
+ loadHistory,
83
+ saveHistory,
84
+ addToHistory,
85
+ getCommandHistory,
86
+ clearHistory,
87
+ };