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,135 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const inquirer = require('inquirer');
4
+ const chalk = require('chalk');
5
+ const { getApiKey } = require('../utils/config');
6
+ const { getBots } = require('../utils/api');
7
+
8
+ async function init() {
9
+ console.log(chalk.green.bold('\n╭─ NatureCo Proje Başlatma ─╮\n'));
10
+
11
+ const apiKey = getApiKey();
12
+ if (!apiKey) {
13
+ console.log(chalk.red('❌ Giriş yapılmadı. Önce "natureco login" çalıştırın.\n'));
14
+ process.exit(1);
15
+ }
16
+
17
+ // Mevcut klasörde .natureco var mı kontrol et
18
+ const projectDir = path.join(process.cwd(), '.natureco');
19
+ if (fs.existsSync(projectDir)) {
20
+ console.log(chalk.yellow('⚠️ Bu klasörde zaten .natureco/ mevcut.\n'));
21
+ const { overwrite } = await inquirer.prompt([
22
+ {
23
+ type: 'confirm',
24
+ name: 'overwrite',
25
+ message: 'Üzerine yazmak ister misiniz?',
26
+ default: false,
27
+ },
28
+ ]);
29
+ if (!overwrite) {
30
+ console.log(chalk.gray('İptal edildi.\n'));
31
+ process.exit(0);
32
+ }
33
+ }
34
+
35
+ // Botları çek
36
+ console.log(chalk.yellow('⏳ Botlar yükleniyor...\n'));
37
+ let botList;
38
+ try {
39
+ botList = await getBots(apiKey);
40
+ } catch (err) {
41
+ console.log(chalk.red(`❌ Hata: ${err.message}\n`));
42
+ process.exit(1);
43
+ }
44
+
45
+ if (!botList || !botList.bots || botList.bots.length === 0) {
46
+ console.log(chalk.gray('Bot bulunamadı. Önce https://developers.natureco.me adresinden bot oluşturun.\n'));
47
+ process.exit(1);
48
+ }
49
+
50
+ // Varsayılan bot seç
51
+ const { defaultBot } = await inquirer.prompt([
52
+ {
53
+ type: 'list',
54
+ name: 'defaultBot',
55
+ message: 'Varsayılan bot:',
56
+ choices: botList.bots.map(b => ({ name: b.name, value: b.id })),
57
+ },
58
+ ]);
59
+
60
+ const selectedBot = botList.bots.find(b => b.id === defaultBot);
61
+
62
+ // Skill'ler
63
+ const { skills } = await inquirer.prompt([
64
+ {
65
+ type: 'checkbox',
66
+ name: 'skills',
67
+ message: 'Hangi skill\'ler eklensin?',
68
+ choices: [
69
+ { name: 'code-review (Kod inceleme)', value: 'code-review', checked: true },
70
+ { name: 'summarize (Özetleme)', value: 'summarize', checked: true },
71
+ { name: 'translate (Çeviri)', value: 'translate', checked: false },
72
+ ],
73
+ },
74
+ ]);
75
+
76
+ // .natureco klasörünü oluştur
77
+ if (!fs.existsSync(projectDir)) {
78
+ fs.mkdirSync(projectDir, { recursive: true });
79
+ }
80
+
81
+ // config.json
82
+ const config = {
83
+ defaultBot: selectedBot.name,
84
+ defaultBotId: selectedBot.id,
85
+ skills: {
86
+ enabled: true,
87
+ list: skills,
88
+ },
89
+ createdAt: new Date().toISOString(),
90
+ };
91
+ fs.writeFileSync(
92
+ path.join(projectDir, 'config.json'),
93
+ JSON.stringify(config, null, 2),
94
+ 'utf8'
95
+ );
96
+
97
+ // AGENTS.md
98
+ const agentsMd = `# ${selectedBot.name} Talimatları
99
+
100
+ Bu dosya projeye özel bot talimatlarını içerir.
101
+ Chat başladığında bu içerik sistem promptuna eklenir.
102
+
103
+ ## Proje Hakkında
104
+
105
+ [Projenizi tanımlayın]
106
+
107
+ ## Bot Görevleri
108
+
109
+ - [Görev 1]
110
+ - [Görev 2]
111
+
112
+ ## Kurallar
113
+
114
+ - [Kural 1]
115
+ - [Kural 2]
116
+ `;
117
+ fs.writeFileSync(path.join(projectDir, 'AGENTS.md'), agentsMd, 'utf8');
118
+
119
+ // skills klasörü
120
+ const skillsDir = path.join(projectDir, 'skills');
121
+ if (!fs.existsSync(skillsDir)) {
122
+ fs.mkdirSync(skillsDir, { recursive: true });
123
+ }
124
+
125
+ console.log(chalk.green('\n✅ Proje başlatıldı!\n'));
126
+ console.log(chalk.cyan('Oluşturulan dosyalar:'));
127
+ console.log(chalk.gray(` .natureco/config.json`));
128
+ console.log(chalk.gray(` .natureco/AGENTS.md`));
129
+ console.log(chalk.gray(` .natureco/skills/`));
130
+ console.log('');
131
+ console.log(chalk.yellow('Sonraki adım:'), chalk.white(`natureco chat "${selectedBot.name}"`));
132
+ console.log('');
133
+ }
134
+
135
+ module.exports = init;
@@ -0,0 +1,45 @@
1
+ const inquirer = require('inquirer');
2
+ const chalk = require('chalk');
3
+ const { saveApiKey } = require('../utils/config');
4
+ const { validateApiKey } = require('../utils/api');
5
+
6
+ async function login() {
7
+ console.log(chalk.green.bold('\n╭─ NatureCo Login ─╮'));
8
+ console.log(chalk.green('│ Enter your API key │'));
9
+ console.log(chalk.green('╰───────────────────╯\n'));
10
+
11
+ const answers = await inquirer.prompt([
12
+ {
13
+ type: 'password',
14
+ name: 'apiKey',
15
+ message: 'API Key:',
16
+ mask: '*',
17
+ validate: (input) => {
18
+ if (!input || input.trim().length === 0) {
19
+ return 'API key cannot be empty';
20
+ }
21
+ if (!input.startsWith('nco_') && !input.startsWith('nc_')) {
22
+ return 'API key must start with "nco_" or "nc_"';
23
+ }
24
+ return true;
25
+ },
26
+ },
27
+ ]);
28
+
29
+ const apiKey = answers.apiKey.trim();
30
+
31
+ console.log(chalk.yellow('\n⏳ Validating API key...'));
32
+
33
+ const isValid = await validateApiKey(apiKey);
34
+
35
+ if (!isValid) {
36
+ console.log(chalk.red('❌ Invalid API key. Please check and try again.\n'));
37
+ process.exit(1);
38
+ }
39
+
40
+ saveApiKey(apiKey);
41
+ console.log(chalk.green('✅ Login successful! API key saved.\n'));
42
+ console.log(chalk.gray(`Stored in: ~/.natureco/config.json\n`));
43
+ }
44
+
45
+ module.exports = login;
@@ -0,0 +1,13 @@
1
+ const chalk = require('chalk');
2
+ const { deleteConfig, CONFIG_FILE } = require('../utils/config');
3
+
4
+ function logout() {
5
+ console.log(chalk.yellow('\n⏳ Logging out...'));
6
+
7
+ deleteConfig();
8
+
9
+ console.log(chalk.green('✅ Logged out successfully.\n'));
10
+ console.log(chalk.gray(`Removed: ${CONFIG_FILE}\n`));
11
+ }
12
+
13
+ module.exports = logout;
@@ -0,0 +1,275 @@
1
+ const chalk = require('chalk');
2
+ const inquirer = require('inquirer');
3
+ const {
4
+ getMcpServers,
5
+ addMcpServer,
6
+ removeMcpServer,
7
+ testMcpServer,
8
+ toggleMcpServer,
9
+ getMcpTemplates,
10
+ updateMcpServer,
11
+ } = require('../utils/mcp');
12
+
13
+ async function mcp(args) {
14
+ const [action, ...params] = args;
15
+
16
+ if (!action || action === 'list') {
17
+ return listMcpServers();
18
+ }
19
+
20
+ switch (action) {
21
+ case 'add':
22
+ return await addMcpServerInteractive(params);
23
+ case 'remove':
24
+ return removeMcpServerCommand(params);
25
+ case 'test':
26
+ return testMcpServerCommand(params);
27
+ case 'enable':
28
+ return toggleMcpServerCommand(params, true);
29
+ case 'disable':
30
+ return toggleMcpServerCommand(params, false);
31
+ case 'templates':
32
+ return listTemplates();
33
+ default:
34
+ console.log(chalk.red(`\n❌ Bilinmeyen komut: ${action}\n`));
35
+ console.log(chalk.gray('Kullanım: natureco mcp <list|add|remove|test|enable|disable|templates>\n'));
36
+ process.exit(1);
37
+ }
38
+ }
39
+
40
+ function listMcpServers() {
41
+ const servers = getMcpServers();
42
+ const serverNames = Object.keys(servers);
43
+
44
+ if (serverNames.length === 0) {
45
+ console.log(chalk.gray('\nMCP sunucu yok.\n'));
46
+ console.log(chalk.yellow('Eklemek için: ') + chalk.cyan('natureco mcp add\n'));
47
+ return;
48
+ }
49
+
50
+ console.log(chalk.green.bold('\n╭─ MCP Sunucular ─╮\n'));
51
+
52
+ serverNames.forEach(name => {
53
+ const server = servers[name];
54
+ const status = server.disabled ? chalk.red('✗ Devre dışı') : chalk.green('✓ Aktif');
55
+
56
+ console.log(chalk.cyan(` ${name}`));
57
+ console.log(chalk.gray(` Durum: ${status}`));
58
+ console.log(chalk.gray(` Komut: ${server.command} ${server.args?.join(' ') || ''}`));
59
+
60
+ if (server.env && Object.keys(server.env).length > 0) {
61
+ console.log(chalk.gray(` Env: ${Object.keys(server.env).join(', ')}`));
62
+ }
63
+
64
+ console.log('');
65
+ });
66
+
67
+ console.log(chalk.gray('Komutlar:'));
68
+ console.log(chalk.gray(' natureco mcp add - Yeni sunucu ekle'));
69
+ console.log(chalk.gray(' natureco mcp remove - Sunucu kaldır'));
70
+ console.log(chalk.gray(' natureco mcp test - Bağlantı test et'));
71
+ console.log(chalk.gray(' natureco mcp templates - Hazır şablonları göster\n'));
72
+ }
73
+
74
+ function listTemplates() {
75
+ const templates = getMcpTemplates();
76
+
77
+ console.log(chalk.green.bold('\n╭─ MCP Şablonlar ─╮\n'));
78
+
79
+ Object.entries(templates).forEach(([key, template]) => {
80
+ console.log(chalk.cyan(` ${template.name}`));
81
+ console.log(chalk.gray(` ${template.description}`));
82
+ console.log(chalk.gray(` Komut: ${template.command} ${template.args.join(' ')}`));
83
+
84
+ if (template.env && Object.keys(template.env).length > 0) {
85
+ const envVars = Object.entries(template.env)
86
+ .map(([k, v]) => `${k}=${v}`)
87
+ .join(', ');
88
+ console.log(chalk.gray(` Env: ${envVars}`));
89
+ }
90
+
91
+ console.log('');
92
+ });
93
+
94
+ console.log(chalk.yellow('Eklemek için: ') + chalk.cyan('natureco mcp add\n'));
95
+ }
96
+
97
+ async function addMcpServerInteractive(params) {
98
+ const templates = getMcpTemplates();
99
+ const templateNames = Object.keys(templates);
100
+
101
+ // Sunucu adı
102
+ let serverName;
103
+ if (params[0]) {
104
+ serverName = params[0];
105
+ } else {
106
+ const { name } = await inquirer.prompt([
107
+ {
108
+ type: 'input',
109
+ name: 'name',
110
+ message: 'Sunucu adı:',
111
+ validate: (input) => {
112
+ if (!input || input.trim().length === 0) {
113
+ return 'Sunucu adı gerekli';
114
+ }
115
+ const servers = getMcpServers();
116
+ if (servers[input]) {
117
+ return 'Bu isimde sunucu zaten mevcut';
118
+ }
119
+ return true;
120
+ },
121
+ },
122
+ ]);
123
+ serverName = name;
124
+ }
125
+
126
+ // Şablon seç
127
+ const { useTemplate } = await inquirer.prompt([
128
+ {
129
+ type: 'confirm',
130
+ name: 'useTemplate',
131
+ message: 'Hazır şablon kullanmak ister misiniz?',
132
+ default: true,
133
+ },
134
+ ]);
135
+
136
+ if (useTemplate) {
137
+ const { template } = await inquirer.prompt([
138
+ {
139
+ type: 'list',
140
+ name: 'template',
141
+ message: 'Şablon seçin:',
142
+ choices: templateNames.map(key => ({
143
+ name: `${templates[key].name} - ${templates[key].description}`,
144
+ value: key,
145
+ })),
146
+ },
147
+ ]);
148
+
149
+ const selectedTemplate = templates[template];
150
+
151
+ // Environment variables
152
+ const envVars = {};
153
+ if (selectedTemplate.env && Object.keys(selectedTemplate.env).length > 0) {
154
+ console.log(chalk.yellow('\nEnvironment variable\'ları ayarlayın:\n'));
155
+
156
+ for (const [key, defaultValue] of Object.entries(selectedTemplate.env)) {
157
+ const { value } = await inquirer.prompt([
158
+ {
159
+ type: 'input',
160
+ name: 'value',
161
+ message: `${key}:`,
162
+ default: defaultValue,
163
+ },
164
+ ]);
165
+ envVars[key] = value;
166
+ }
167
+ }
168
+
169
+ try {
170
+ addMcpServer(serverName, template);
171
+
172
+ // Update env vars if provided
173
+ if (Object.keys(envVars).length > 0) {
174
+ updateMcpServer(serverName, { env: envVars });
175
+ }
176
+
177
+ console.log(chalk.green(`\n✅ MCP sunucu eklendi: ${serverName}\n`));
178
+ console.log(chalk.gray('Test etmek için: ') + chalk.cyan(`natureco mcp test ${serverName}\n`));
179
+ } catch (err) {
180
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
181
+ process.exit(1);
182
+ }
183
+ } else {
184
+ // Custom config
185
+ const { command } = await inquirer.prompt([
186
+ {
187
+ type: 'input',
188
+ name: 'command',
189
+ message: 'Komut:',
190
+ default: 'npx',
191
+ },
192
+ ]);
193
+
194
+ const { args } = await inquirer.prompt([
195
+ {
196
+ type: 'input',
197
+ name: 'args',
198
+ message: 'Argümanlar (boşlukla ayırın):',
199
+ },
200
+ ]);
201
+
202
+ const customConfig = {
203
+ command,
204
+ args: args.split(' ').filter(a => a.length > 0),
205
+ env: {},
206
+ };
207
+
208
+ try {
209
+ addMcpServer(serverName, null, customConfig);
210
+ console.log(chalk.green(`\n✅ MCP sunucu eklendi: ${serverName}\n`));
211
+ } catch (err) {
212
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
213
+ process.exit(1);
214
+ }
215
+ }
216
+ }
217
+
218
+ function removeMcpServerCommand(params) {
219
+ if (params.length === 0) {
220
+ console.log(chalk.red('\n❌ Sunucu adı gerekli\n'));
221
+ console.log(chalk.gray('Kullanım: natureco mcp remove <sunucu-adı>\n'));
222
+ process.exit(1);
223
+ }
224
+
225
+ const serverName = params[0];
226
+
227
+ try {
228
+ removeMcpServer(serverName);
229
+ console.log(chalk.green(`\n✅ MCP sunucu kaldırıldı: ${serverName}\n`));
230
+ } catch (err) {
231
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
232
+ process.exit(1);
233
+ }
234
+ }
235
+
236
+ function testMcpServerCommand(params) {
237
+ if (params.length === 0) {
238
+ console.log(chalk.red('\n❌ Sunucu adı gerekli\n'));
239
+ console.log(chalk.gray('Kullanım: natureco mcp test <sunucu-adı>\n'));
240
+ process.exit(1);
241
+ }
242
+
243
+ const serverName = params[0];
244
+
245
+ console.log(chalk.yellow(`\n⏳ Test ediliyor: ${serverName}...\n`));
246
+
247
+ try {
248
+ testMcpServer(serverName);
249
+ console.log(chalk.green(`✅ Bağlantı başarılı: ${serverName}\n`));
250
+ } catch (err) {
251
+ console.log(chalk.red(`❌ Bağlantı başarısız: ${err.message}\n`));
252
+ process.exit(1);
253
+ }
254
+ }
255
+
256
+ function toggleMcpServerCommand(params, enabled) {
257
+ if (params.length === 0) {
258
+ console.log(chalk.red('\n❌ Sunucu adı gerekli\n'));
259
+ console.log(chalk.gray(`Kullanım: natureco mcp ${enabled ? 'enable' : 'disable'} <sunucu-adı>\n`));
260
+ process.exit(1);
261
+ }
262
+
263
+ const serverName = params[0];
264
+
265
+ try {
266
+ toggleMcpServer(serverName, enabled);
267
+ const status = enabled ? 'aktif' : 'devre dışı';
268
+ console.log(chalk.green(`\n✅ MCP sunucu ${status}: ${serverName}\n`));
269
+ } catch (err) {
270
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
271
+ process.exit(1);
272
+ }
273
+ }
274
+
275
+ module.exports = mcp;
@@ -0,0 +1,69 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { getApiKey, getConfig } = require('../utils/config');
5
+ const { sendMessage } = require('../utils/api');
6
+ const { getSkillPrompts } = require('../utils/skills');
7
+
8
+ async function run(scriptPath) {
9
+ const apiKey = getApiKey();
10
+
11
+ if (!apiKey) {
12
+ console.log(chalk.red('\n❌ Giriş yapılmamış. Önce "natureco login" çalıştırın.\n'));
13
+ process.exit(1);
14
+ }
15
+
16
+ const config = getConfig();
17
+ const defaultBotId = config.defaultBotId;
18
+
19
+ if (!defaultBotId) {
20
+ console.log(chalk.red('\n❌ Varsayılan bot ayarlanmamış. "natureco config set defaultBotId <bot-id>" ile ayarlayın.\n'));
21
+ process.exit(1);
22
+ }
23
+
24
+ // Script dosyasını oku
25
+ const fullPath = path.resolve(scriptPath);
26
+
27
+ if (!fs.existsSync(fullPath)) {
28
+ console.log(chalk.red(`\n❌ Dosya bulunamadı: ${scriptPath}\n`));
29
+ process.exit(1);
30
+ }
31
+
32
+ const scriptContent = fs.readFileSync(fullPath, 'utf8');
33
+
34
+ if (!scriptContent || scriptContent.trim().length === 0) {
35
+ console.log(chalk.red('\n❌ Script dosyası boş.\n'));
36
+ process.exit(1);
37
+ }
38
+
39
+ // Skill prompts'ları yükle
40
+ const skillPrompts = getSkillPrompts();
41
+
42
+ console.log(chalk.yellow(`\n⏳ Script çalıştırılıyor: ${path.basename(scriptPath)}\n`));
43
+
44
+ // Loading animasyonu
45
+ const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
46
+ let i = 0;
47
+ process.stdout.write(chalk.yellow('⏳ '));
48
+ const loadingInterval = setInterval(() => {
49
+ process.stdout.write(`\r${chalk.yellow('⏳')} ${chalk.yellow(frames[i])}`);
50
+ i = (i + 1) % frames.length;
51
+ }, 80);
52
+
53
+ try {
54
+ const response = await sendMessage(apiKey, defaultBotId, scriptContent, null, skillPrompts);
55
+
56
+ clearInterval(loadingInterval);
57
+ process.stdout.write('\r');
58
+
59
+ const botReply = response.reply || response.message || 'Yanıt alınamadı';
60
+ console.log(chalk.green(`\n${botReply}\n`));
61
+ } catch (err) {
62
+ clearInterval(loadingInterval);
63
+ process.stdout.write('\r');
64
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
65
+ process.exit(1);
66
+ }
67
+ }
68
+
69
+ module.exports = run;