natureco-cli 1.0.1 → 1.0.5
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 +52 -1
- package/package.json +5 -5
- package/src/commands/chat.js +211 -9
- package/src/commands/commands.js +74 -0
- package/src/commands/cron.js +383 -0
- package/src/commands/git.js +229 -0
- package/src/commands/help.js +28 -4
- package/src/commands/hooks.js +87 -0
- package/src/commands/sessions.js +119 -0
- package/src/commands/setup.js +150 -134
- package/src/commands/skills.js +85 -1
- package/src/commands/tasks.js +79 -0
- package/src/utils/api.js +9 -0
- package/src/utils/background.js +66 -0
- package/src/utils/commands.js +77 -0
- package/src/utils/cron.js +126 -0
- package/src/utils/hooks.js +154 -0
- package/src/utils/memory.js +160 -0
- package/src/utils/sessions.js +109 -0
- package/src/utils/skills.js +41 -5
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const inquirer = require('inquirer');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const { getAllHooks, createHook } = require('../utils/hooks');
|
|
4
|
+
|
|
5
|
+
async function hooks(action, ...args) {
|
|
6
|
+
if (!action || action === 'list') {
|
|
7
|
+
return listHooks();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (action === 'create') {
|
|
11
|
+
const type = args[0];
|
|
12
|
+
if (!type) {
|
|
13
|
+
console.log(chalk.red('\n❌ Hook type required\n'));
|
|
14
|
+
console.log(chalk.gray('Available types: pre-message, post-message, on-start, on-exit\n'));
|
|
15
|
+
console.log(chalk.gray('Usage: natureco hooks create <type>\n'));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
return createHookInteractive(type);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.log(chalk.red(`\n❌ Unknown action: ${action}\n`));
|
|
22
|
+
console.log(chalk.gray('Available actions: list, create\n'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function listHooks() {
|
|
27
|
+
const hooks = getAllHooks();
|
|
28
|
+
|
|
29
|
+
if (hooks.length === 0) {
|
|
30
|
+
console.log(chalk.gray('\nNo hooks found.\n'));
|
|
31
|
+
console.log(chalk.gray('Create one with: natureco hooks create <type>\n'));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log(chalk.yellow('\nHooks:\n'));
|
|
36
|
+
|
|
37
|
+
const grouped = {};
|
|
38
|
+
hooks.forEach(hook => {
|
|
39
|
+
if (!grouped[hook.type]) grouped[hook.type] = [];
|
|
40
|
+
grouped[hook.type].push(hook);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
Object.keys(grouped).forEach(type => {
|
|
44
|
+
console.log(chalk.cyan(` ${type}:`));
|
|
45
|
+
grouped[type].forEach(hook => {
|
|
46
|
+
const sourceLabel = hook.source === 'user' ? chalk.blue('[global]') : chalk.green('[project]');
|
|
47
|
+
console.log(` ${sourceLabel} ${chalk.white(hook.name)}`);
|
|
48
|
+
});
|
|
49
|
+
console.log('');
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function createHookInteractive(type) {
|
|
54
|
+
const validTypes = ['pre-message', 'post-message', 'on-start', 'on-exit'];
|
|
55
|
+
|
|
56
|
+
if (!validTypes.includes(type)) {
|
|
57
|
+
console.log(chalk.red(`\n❌ Invalid hook type: ${type}\n`));
|
|
58
|
+
console.log(chalk.gray('Available types: pre-message, post-message, on-start, on-exit\n'));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
process.stdin.resume();
|
|
63
|
+
|
|
64
|
+
const answers = await inquirer.prompt([
|
|
65
|
+
{
|
|
66
|
+
type: 'list',
|
|
67
|
+
name: 'scope',
|
|
68
|
+
message: 'Hook scope:',
|
|
69
|
+
choices: [
|
|
70
|
+
{ name: 'Project (only this project)', value: 'project' },
|
|
71
|
+
{ name: 'Global (all projects)', value: 'user' },
|
|
72
|
+
],
|
|
73
|
+
default: 'project',
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const filePath = createHook(type, answers.scope);
|
|
79
|
+
console.log(chalk.green(`\n✅ Hook created: ${filePath}\n`));
|
|
80
|
+
console.log(chalk.gray('Edit the file to customize the hook behavior.\n'));
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = hooks;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { listSessions, loadSession } = require('../utils/sessions');
|
|
3
|
+
const { getApiKey } = require('../utils/config');
|
|
4
|
+
const { getBots } = require('../utils/api');
|
|
5
|
+
|
|
6
|
+
async function sessions(action, ...args) {
|
|
7
|
+
if (!action || action === 'list') {
|
|
8
|
+
return listSessionsCommand();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (action === 'show') {
|
|
12
|
+
const sessionId = args[0];
|
|
13
|
+
if (!sessionId) {
|
|
14
|
+
console.log(chalk.red('\n❌ Session ID required\n'));
|
|
15
|
+
console.log(chalk.gray('Usage: natureco sessions show <id>\n'));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
return showSession(sessionId);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.log(chalk.red(`\n❌ Unknown action: ${action}\n`));
|
|
22
|
+
console.log(chalk.gray('Available actions: list, show\n'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function listSessionsCommand() {
|
|
27
|
+
const apiKey = getApiKey();
|
|
28
|
+
|
|
29
|
+
if (!apiKey) {
|
|
30
|
+
console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let botList;
|
|
35
|
+
try {
|
|
36
|
+
botList = await getBots(apiKey);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!botList || !botList.bots || botList.bots.length === 0) {
|
|
43
|
+
console.log(chalk.gray('No bots found.\n'));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(chalk.yellow('\nChat Sessions:\n'));
|
|
48
|
+
|
|
49
|
+
let foundAny = false;
|
|
50
|
+
|
|
51
|
+
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')}`);
|
|
60
|
+
});
|
|
61
|
+
console.log('');
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (!foundAny) {
|
|
66
|
+
console.log(chalk.gray(' No sessions found.\n'));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function showSession(sessionId) {
|
|
71
|
+
const apiKey = getApiKey();
|
|
72
|
+
|
|
73
|
+
if (!apiKey) {
|
|
74
|
+
console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let botList;
|
|
79
|
+
try {
|
|
80
|
+
botList = await getBots(apiKey);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
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
|
|
92
|
+
let session = null;
|
|
93
|
+
let botName = null;
|
|
94
|
+
|
|
95
|
+
for (const bot of botList.bots) {
|
|
96
|
+
session = loadSession(bot.id, sessionId);
|
|
97
|
+
if (session) {
|
|
98
|
+
botName = bot.name;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!session) {
|
|
104
|
+
console.log(chalk.red(`\n❌ Session not found: ${sessionId}\n`));
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
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
|
+
|
|
113
|
+
session.messages.forEach((msg, i) => {
|
|
114
|
+
console.log(chalk.cyan(`[${i + 1}] siz › ${msg.user}`));
|
|
115
|
+
console.log(chalk.green(` bot › ${msg.bot}\n`));
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = sessions;
|
package/src/commands/setup.js
CHANGED
|
@@ -34,183 +34,199 @@ async function setup() {
|
|
|
34
34
|
console.log(chalk.cyan('✦ Varsayılan ayarlar yükleniyor...'));
|
|
35
35
|
console.log(chalk.green(' ✓ Ayarlar hazır\n'));
|
|
36
36
|
|
|
37
|
-
//
|
|
37
|
+
// AI sağlayıcı seç
|
|
38
38
|
process.stdin.resume();
|
|
39
|
-
const {
|
|
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([
|
|
39
|
+
const { aiProvider } = await inquirer.prompt([
|
|
102
40
|
{
|
|
103
41
|
type: 'list',
|
|
104
|
-
name: '
|
|
105
|
-
message: '
|
|
106
|
-
choices:
|
|
107
|
-
name:
|
|
108
|
-
value:
|
|
109
|
-
|
|
42
|
+
name: 'aiProvider',
|
|
43
|
+
message: 'AI sağlayıcı seçin:',
|
|
44
|
+
choices: [
|
|
45
|
+
{ name: 'NatureCo (önerilen)', value: 'natureco' },
|
|
46
|
+
{ name: 'OpenAI', value: 'openai' },
|
|
47
|
+
{ name: 'Anthropic Claude', value: 'anthropic' },
|
|
48
|
+
{ name: 'Groq', value: 'groq' },
|
|
49
|
+
{ name: 'Google Gemini', value: 'gemini' },
|
|
50
|
+
],
|
|
51
|
+
default: 'natureco',
|
|
110
52
|
},
|
|
111
53
|
]);
|
|
112
54
|
|
|
113
|
-
|
|
55
|
+
let aiApiKey = null;
|
|
56
|
+
let naturecoApiKey = null;
|
|
114
57
|
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
name: '
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
124
|
-
]);
|
|
58
|
+
// NatureCo dışı sağlayıcı seçildiyse key sor
|
|
59
|
+
if (aiProvider !== 'natureco') {
|
|
60
|
+
const providerInfo = {
|
|
61
|
+
openai: { name: 'OpenAI', prefix: 'sk-', example: 'sk-...' },
|
|
62
|
+
anthropic: { name: 'Anthropic', prefix: 'sk-ant-', example: 'sk-ant-...' },
|
|
63
|
+
groq: { name: 'Groq', prefix: 'gsk_', example: 'gsk_...' },
|
|
64
|
+
gemini: { name: 'Google Gemini', prefix: 'AIza', example: 'AIza...' },
|
|
65
|
+
};
|
|
125
66
|
|
|
126
|
-
|
|
127
|
-
let telegramSkipped = false;
|
|
67
|
+
const info = providerInfo[aiProvider];
|
|
128
68
|
|
|
129
|
-
if (connectTelegram) {
|
|
130
69
|
process.stdin.resume();
|
|
131
|
-
const {
|
|
70
|
+
const { customApiKey } = await inquirer.prompt([
|
|
132
71
|
{
|
|
133
72
|
type: 'input',
|
|
134
|
-
name: '
|
|
135
|
-
message:
|
|
73
|
+
name: 'customApiKey',
|
|
74
|
+
message: `${info.name} API key girin (${info.example}):`,
|
|
136
75
|
validate: (input) => {
|
|
137
76
|
if (!input || input.trim().length === 0) {
|
|
138
|
-
return '
|
|
77
|
+
return 'API key gerekli';
|
|
78
|
+
}
|
|
79
|
+
if (!input.trim().startsWith(info.prefix)) {
|
|
80
|
+
return `API key ${info.prefix} ile başlamalı`;
|
|
139
81
|
}
|
|
140
82
|
return true;
|
|
141
83
|
},
|
|
142
84
|
},
|
|
143
85
|
]);
|
|
144
86
|
|
|
87
|
+
aiApiKey = customApiKey.trim();
|
|
88
|
+
|
|
89
|
+
// NatureCo API key de sor (opsiyonel)
|
|
90
|
+
process.stdin.resume();
|
|
91
|
+
const { wantNaturecoKey } = await inquirer.prompt([
|
|
92
|
+
{
|
|
93
|
+
type: 'confirm',
|
|
94
|
+
name: 'wantNaturecoKey',
|
|
95
|
+
message: 'NatureCo API key de girmek ister misiniz? (Bot yönetimi için)',
|
|
96
|
+
default: false,
|
|
97
|
+
},
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
if (wantNaturecoKey) {
|
|
101
|
+
process.stdin.resume();
|
|
102
|
+
const { ncKey } = await inquirer.prompt([
|
|
103
|
+
{
|
|
104
|
+
type: 'input',
|
|
105
|
+
name: 'ncKey',
|
|
106
|
+
message: 'NatureCo API key:',
|
|
107
|
+
validate: (input) => {
|
|
108
|
+
const trimmed = input.trim();
|
|
109
|
+
if (trimmed.length === 0) return true; // Opsiyonel
|
|
110
|
+
if (!trimmed.startsWith('nc_') && !trimmed.startsWith('nco_')) {
|
|
111
|
+
return 'API key nc_ veya nco_ ile başlamalı';
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
]);
|
|
117
|
+
if (ncKey.trim().length > 0) {
|
|
118
|
+
naturecoApiKey = ncKey.trim();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
// NatureCo seçildiyse normal akış
|
|
145
123
|
process.stdin.resume();
|
|
146
|
-
const {
|
|
124
|
+
const { apiKey } = await inquirer.prompt([
|
|
147
125
|
{
|
|
148
126
|
type: 'input',
|
|
149
|
-
name: '
|
|
150
|
-
message: '
|
|
151
|
-
validate: (
|
|
127
|
+
name: 'apiKey',
|
|
128
|
+
message: 'NatureCo API key girin:',
|
|
129
|
+
validate: async (input) => {
|
|
130
|
+
if (!input || input.trim().length === 0) {
|
|
131
|
+
return 'API key gerekli';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const trimmed = input.trim();
|
|
135
|
+
if (!trimmed.startsWith('nc_') && !trimmed.startsWith('nco_')) {
|
|
136
|
+
return 'API key nc_ veya nco_ ile başlamalı';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log(chalk.yellow('\n ⏳ API key doğrulanıyor...'));
|
|
140
|
+
try {
|
|
141
|
+
const response = await fetch('https://api.natureco.me/api/v1/bots', {
|
|
142
|
+
headers: {
|
|
143
|
+
'Authorization': `Bearer ${trimmed}`,
|
|
144
|
+
'Content-Type': 'application/json',
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (!response.ok) {
|
|
149
|
+
return 'Geçersiz API key';
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const data = await response.json();
|
|
153
|
+
if (!data.bots || data.bots.length === 0) {
|
|
154
|
+
return 'Bu API key ile bot bulunamadı';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
console.log(chalk.green(' ✓ API key doğrulandı\n'));
|
|
158
|
+
return true;
|
|
159
|
+
} catch (err) {
|
|
160
|
+
return `API hatası: ${err.message}`;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
152
163
|
},
|
|
153
164
|
]);
|
|
154
165
|
|
|
155
|
-
|
|
166
|
+
naturecoApiKey = apiKey.trim();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Bot seçimi (sadece NatureCo key varsa)
|
|
170
|
+
let selectedBot = null;
|
|
171
|
+
let selectedBotId = null;
|
|
156
172
|
|
|
173
|
+
if (naturecoApiKey) {
|
|
174
|
+
console.log(chalk.yellow('⏳ Botlar yükleniyor...\n'));
|
|
157
175
|
try {
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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`));
|
|
176
|
+
const botList = await getBots(naturecoApiKey);
|
|
177
|
+
|
|
178
|
+
if (botList && botList.bots && botList.bots.length > 0) {
|
|
179
|
+
process.stdin.resume();
|
|
180
|
+
const { botId } = await inquirer.prompt([
|
|
181
|
+
{
|
|
182
|
+
type: 'list',
|
|
183
|
+
name: 'botId',
|
|
184
|
+
message: 'Varsayılan bot seçin:',
|
|
185
|
+
choices: botList.bots.map(b => ({ name: b.name, value: b.id })),
|
|
186
|
+
},
|
|
187
|
+
]);
|
|
188
|
+
|
|
189
|
+
selectedBotId = botId;
|
|
190
|
+
selectedBot = botList.bots.find(b => b.id === botId);
|
|
180
191
|
}
|
|
181
192
|
} catch (err) {
|
|
182
|
-
console.log(chalk.
|
|
193
|
+
console.log(chalk.yellow(`⚠️ Bot listesi alınamadı: ${err.message}\n`));
|
|
183
194
|
}
|
|
184
|
-
} else {
|
|
185
|
-
telegramSkipped = true;
|
|
186
195
|
}
|
|
187
196
|
|
|
188
197
|
// Config kaydet
|
|
189
198
|
const config = {
|
|
190
|
-
apiKey: trimmedApiKey,
|
|
191
|
-
defaultBot: selectedBot.name,
|
|
192
|
-
defaultBotId: selectedBot.id,
|
|
193
|
-
skills: {
|
|
194
|
-
enabled: true,
|
|
195
|
-
list: [],
|
|
196
|
-
},
|
|
197
|
-
mcpServers: {},
|
|
198
199
|
setupCompleted: true,
|
|
199
200
|
setupDate: new Date().toISOString(),
|
|
201
|
+
skills: { enabled: true, list: [] },
|
|
202
|
+
mcpServers: {},
|
|
200
203
|
};
|
|
201
204
|
|
|
205
|
+
if (aiProvider !== 'natureco') {
|
|
206
|
+
config.aiProvider = aiProvider;
|
|
207
|
+
config.aiApiKey = aiApiKey;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (naturecoApiKey) {
|
|
211
|
+
config.apiKey = naturecoApiKey;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (selectedBot) {
|
|
215
|
+
config.defaultBot = selectedBot.name;
|
|
216
|
+
config.defaultBotId = selectedBotId;
|
|
217
|
+
}
|
|
218
|
+
|
|
202
219
|
saveConfig(config);
|
|
203
220
|
|
|
204
221
|
// Kurulum tamamlandı
|
|
205
|
-
console.log(chalk.green.bold('✅ Kurulum tamamlandı!\n'));
|
|
206
|
-
console.log(chalk.cyan('Aktif bot:'), chalk.white(selectedBot.name));
|
|
222
|
+
console.log(chalk.green.bold('\n✅ Kurulum tamamlandı!\n'));
|
|
207
223
|
|
|
208
|
-
if (
|
|
209
|
-
console.log(chalk.cyan('
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
console.log(chalk.cyan('
|
|
224
|
+
if (aiProvider !== 'natureco') {
|
|
225
|
+
console.log(chalk.cyan('AI Sağlayıcı:'), chalk.white(aiProvider));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (selectedBot) {
|
|
229
|
+
console.log(chalk.cyan('Varsayılan Bot:'), chalk.white(selectedBot.name));
|
|
214
230
|
}
|
|
215
231
|
|
|
216
232
|
console.log(chalk.cyan('Config:'), chalk.white(CONFIG_FILE));
|
package/src/commands/skills.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const inquirer = require('inquirer');
|
|
3
|
-
const { getSkills, installSkill, removeSkill, updateAllSkills, createSkillTemplate } = require('../utils/skills');
|
|
3
|
+
const { getSkills, installSkill, removeSkill, updateAllSkills, createSkillTemplate, getPopularSkills } = require('../utils/skills');
|
|
4
4
|
|
|
5
5
|
async function skills(args) {
|
|
6
6
|
const [action, ...params] = args;
|
|
@@ -51,6 +51,17 @@ async function skills(args) {
|
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
if (action === 'search') {
|
|
55
|
+
const query = params.join(' ');
|
|
56
|
+
await searchSkillsCommand(query);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (action === 'browse') {
|
|
61
|
+
await browseSkillsCommand();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
54
65
|
console.log(chalk.red(`\n❌ Geçersiz action: ${action}\n`));
|
|
55
66
|
console.log(chalk.gray('Kullanım: natureco skills [list|install|remove|update|create]\n'));
|
|
56
67
|
process.exit(1);
|
|
@@ -158,4 +169,77 @@ async function createSkillCommand(name) {
|
|
|
158
169
|
}
|
|
159
170
|
}
|
|
160
171
|
|
|
172
|
+
async function searchSkillsCommand(query) {
|
|
173
|
+
const popularSkills = getPopularSkills();
|
|
174
|
+
|
|
175
|
+
if (!query || query.trim().length === 0) {
|
|
176
|
+
console.log(chalk.yellow('\nPopüler Skill\'ler:\n'));
|
|
177
|
+
popularSkills.forEach(skill => {
|
|
178
|
+
console.log(chalk.cyan(` ${skill.name.padEnd(15)}`), chalk.gray(skill.description));
|
|
179
|
+
});
|
|
180
|
+
console.log('');
|
|
181
|
+
console.log(chalk.gray('Kurmak için: '), chalk.cyan('natureco skills install <slug>'));
|
|
182
|
+
console.log(chalk.gray('Örnek: '), chalk.cyan('natureco skills install github'));
|
|
183
|
+
console.log(chalk.gray('ClawHub: '), chalk.cyan('natureco skills install clawhub:github'));
|
|
184
|
+
console.log('');
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Search in popular skills
|
|
189
|
+
const results = popularSkills.filter(skill =>
|
|
190
|
+
skill.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
191
|
+
skill.description.toLowerCase().includes(query.toLowerCase()) ||
|
|
192
|
+
skill.slug.toLowerCase().includes(query.toLowerCase())
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
if (results.length === 0) {
|
|
196
|
+
console.log(chalk.yellow(`\n"${query}" için sonuç bulunamadı.\n`));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
console.log(chalk.yellow(`\n"${query}" için ${results.length} sonuç:\n`));
|
|
201
|
+
results.forEach(skill => {
|
|
202
|
+
console.log(chalk.cyan(` ${skill.name.padEnd(15)}`), chalk.gray(skill.description));
|
|
203
|
+
console.log(chalk.gray(` Kurmak için: natureco skills install ${skill.slug}`));
|
|
204
|
+
});
|
|
205
|
+
console.log('');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function browseSkillsCommand() {
|
|
209
|
+
const popularSkills = getPopularSkills();
|
|
210
|
+
|
|
211
|
+
console.log(chalk.green.bold('\n╭─ Popüler Skill\'ler ─╮\n'));
|
|
212
|
+
|
|
213
|
+
process.stdin.resume();
|
|
214
|
+
const { selectedSkills } = await inquirer.prompt([
|
|
215
|
+
{
|
|
216
|
+
type: 'checkbox',
|
|
217
|
+
name: 'selectedSkills',
|
|
218
|
+
message: 'Kurmak istediğiniz skill\'leri seçin:',
|
|
219
|
+
choices: popularSkills.map(skill => ({
|
|
220
|
+
name: `${skill.name} - ${skill.description}`,
|
|
221
|
+
value: skill.slug,
|
|
222
|
+
})),
|
|
223
|
+
},
|
|
224
|
+
]);
|
|
225
|
+
|
|
226
|
+
if (selectedSkills.length === 0) {
|
|
227
|
+
console.log(chalk.gray('\nHiçbir skill seçilmedi.\n'));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
console.log(chalk.yellow(`\n⏳ ${selectedSkills.length} skill kuruluyor...\n`));
|
|
232
|
+
|
|
233
|
+
for (const slug of selectedSkills) {
|
|
234
|
+
try {
|
|
235
|
+
await installSkill(slug);
|
|
236
|
+
console.log(chalk.green(`✅ ${slug} kuruldu`));
|
|
237
|
+
} catch (err) {
|
|
238
|
+
console.log(chalk.red(`❌ ${slug} kurulamadı: ${err.message}`));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log(chalk.green('\n✅ Kurulum tamamlandı!\n'));
|
|
243
|
+
}
|
|
244
|
+
|
|
161
245
|
module.exports = skills;
|