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,383 @@
|
|
|
1
|
+
const inquirer = require('inquirer');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const cron = require('node-cron');
|
|
4
|
+
const { getApiKey } = require('../utils/config');
|
|
5
|
+
const { getBots, sendMessage } = require('../utils/api');
|
|
6
|
+
const {
|
|
7
|
+
loadCronJobs,
|
|
8
|
+
addCronJob,
|
|
9
|
+
removeCronJob,
|
|
10
|
+
updateCronJob,
|
|
11
|
+
getCronJob,
|
|
12
|
+
parseCronSchedule,
|
|
13
|
+
validateCronExpression,
|
|
14
|
+
logCronOutput,
|
|
15
|
+
getCronLog,
|
|
16
|
+
} = require('../utils/cron');
|
|
17
|
+
|
|
18
|
+
async function cronCommand(action, ...args) {
|
|
19
|
+
if (!action || action === 'list') {
|
|
20
|
+
return listCronJobs();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (action === 'add') {
|
|
24
|
+
return addCronJobInteractive();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (action === 'remove') {
|
|
28
|
+
const id = args[0];
|
|
29
|
+
if (!id) {
|
|
30
|
+
console.log(chalk.red('\n❌ Job ID required\n'));
|
|
31
|
+
console.log(chalk.gray('Usage: natureco cron remove <id>\n'));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
return removeCronJobCommand(id);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (action === 'run') {
|
|
38
|
+
const id = args[0];
|
|
39
|
+
if (!id) {
|
|
40
|
+
console.log(chalk.red('\n❌ Job ID required\n'));
|
|
41
|
+
console.log(chalk.gray('Usage: natureco cron run <id>\n'));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
return runCronJobNow(id);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (action === 'enable') {
|
|
48
|
+
const id = args[0];
|
|
49
|
+
if (!id) {
|
|
50
|
+
console.log(chalk.red('\n❌ Job ID required\n'));
|
|
51
|
+
console.log(chalk.gray('Usage: natureco cron enable <id>\n'));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
return toggleCronJob(id, true);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (action === 'disable') {
|
|
58
|
+
const id = args[0];
|
|
59
|
+
if (!id) {
|
|
60
|
+
console.log(chalk.red('\n❌ Job ID required\n'));
|
|
61
|
+
console.log(chalk.gray('Usage: natureco cron disable <id>\n'));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
return toggleCronJob(id, false);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (action === 'start') {
|
|
68
|
+
return startCronDaemon();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (action === 'logs') {
|
|
72
|
+
const id = args[0];
|
|
73
|
+
if (!id) {
|
|
74
|
+
console.log(chalk.red('\n❌ Job ID required\n'));
|
|
75
|
+
console.log(chalk.gray('Usage: natureco cron logs <id>\n'));
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
return showCronLogs(id);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log(chalk.red(`\n❌ Unknown action: ${action}\n`));
|
|
82
|
+
console.log(chalk.gray('Available actions: list, add, remove, run, enable, disable, start, logs\n'));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function listCronJobs() {
|
|
87
|
+
const jobs = loadCronJobs();
|
|
88
|
+
|
|
89
|
+
if (jobs.length === 0) {
|
|
90
|
+
console.log(chalk.gray('\nNo cron jobs found.\n'));
|
|
91
|
+
console.log(chalk.gray('Create one with: natureco cron add\n'));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(chalk.yellow('\nCron Jobs:\n'));
|
|
96
|
+
|
|
97
|
+
jobs.forEach(job => {
|
|
98
|
+
const status = job.enabled ? chalk.green('✓ enabled') : chalk.gray('✗ disabled');
|
|
99
|
+
console.log(` ${chalk.cyan(job.id)} ${status}`);
|
|
100
|
+
console.log(chalk.white(` ${job.name}`));
|
|
101
|
+
console.log(chalk.gray(` Bot: ${job.botName} | Schedule: ${job.schedule}`));
|
|
102
|
+
console.log(chalk.gray(` Output: ${job.outputType === 'file' ? 'log file' : 'terminal'}`));
|
|
103
|
+
console.log('');
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function addCronJobInteractive() {
|
|
108
|
+
const apiKey = getApiKey();
|
|
109
|
+
|
|
110
|
+
if (!apiKey) {
|
|
111
|
+
console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let botList;
|
|
116
|
+
try {
|
|
117
|
+
botList = await getBots(apiKey);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!botList || !botList.bots || botList.bots.length === 0) {
|
|
124
|
+
console.log(chalk.gray('No bots found. Create one at https://developers.natureco.me\n'));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
process.stdin.resume();
|
|
129
|
+
|
|
130
|
+
const answers = await inquirer.prompt([
|
|
131
|
+
{
|
|
132
|
+
type: 'input',
|
|
133
|
+
name: 'name',
|
|
134
|
+
message: 'Job name:',
|
|
135
|
+
validate: (val) => val.trim() !== '' || 'Name cannot be empty',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: 'input',
|
|
139
|
+
name: 'message',
|
|
140
|
+
message: 'Message to send to bot:',
|
|
141
|
+
validate: (val) => val.trim() !== '' || 'Message cannot be empty',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
type: 'list',
|
|
145
|
+
name: 'botId',
|
|
146
|
+
message: 'Select bot:',
|
|
147
|
+
choices: botList.bots.map(b => ({ name: b.name, value: b.id })),
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'list',
|
|
151
|
+
name: 'scheduleType',
|
|
152
|
+
message: 'Schedule type:',
|
|
153
|
+
choices: [
|
|
154
|
+
{ name: 'Daily at specific time', value: 'daily' },
|
|
155
|
+
{ name: 'Every X hours', value: 'hours' },
|
|
156
|
+
{ name: 'Custom cron expression', value: 'custom' },
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
let schedule;
|
|
162
|
+
|
|
163
|
+
if (answers.scheduleType === 'daily') {
|
|
164
|
+
const timeAnswer = await inquirer.prompt([
|
|
165
|
+
{
|
|
166
|
+
type: 'input',
|
|
167
|
+
name: 'time',
|
|
168
|
+
message: 'Time (HH:MM):',
|
|
169
|
+
default: '09:00',
|
|
170
|
+
validate: (val) => {
|
|
171
|
+
const match = val.match(/^(\d{1,2}):(\d{2})$/);
|
|
172
|
+
if (!match) return 'Invalid time format. Use HH:MM';
|
|
173
|
+
const hour = parseInt(match[1]);
|
|
174
|
+
const minute = parseInt(match[2]);
|
|
175
|
+
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
|
|
176
|
+
return 'Invalid time';
|
|
177
|
+
}
|
|
178
|
+
return true;
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
]);
|
|
182
|
+
schedule = `daily at ${timeAnswer.time}`;
|
|
183
|
+
} else if (answers.scheduleType === 'hours') {
|
|
184
|
+
const hoursAnswer = await inquirer.prompt([
|
|
185
|
+
{
|
|
186
|
+
type: 'input',
|
|
187
|
+
name: 'hours',
|
|
188
|
+
message: 'Every X hours:',
|
|
189
|
+
default: '1',
|
|
190
|
+
validate: (val) => {
|
|
191
|
+
const num = parseInt(val);
|
|
192
|
+
if (isNaN(num) || num < 1 || num > 24) {
|
|
193
|
+
return 'Enter a number between 1 and 24';
|
|
194
|
+
}
|
|
195
|
+
return true;
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
schedule = `every ${hoursAnswer.hours} hours`;
|
|
200
|
+
} else {
|
|
201
|
+
const cronAnswer = await inquirer.prompt([
|
|
202
|
+
{
|
|
203
|
+
type: 'input',
|
|
204
|
+
name: 'cron',
|
|
205
|
+
message: 'Cron expression:',
|
|
206
|
+
default: '0 9 * * *',
|
|
207
|
+
validate: (val) => {
|
|
208
|
+
const parsed = parseCronSchedule(val);
|
|
209
|
+
if (!validateCronExpression(parsed)) {
|
|
210
|
+
return 'Invalid cron expression';
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
]);
|
|
216
|
+
schedule = cronAnswer.cron;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const outputAnswer = await inquirer.prompt([
|
|
220
|
+
{
|
|
221
|
+
type: 'list',
|
|
222
|
+
name: 'outputType',
|
|
223
|
+
message: 'Output destination:',
|
|
224
|
+
choices: [
|
|
225
|
+
{ name: 'Save to log file', value: 'file' },
|
|
226
|
+
{ name: 'Print to terminal', value: 'terminal' },
|
|
227
|
+
],
|
|
228
|
+
default: 'file',
|
|
229
|
+
},
|
|
230
|
+
]);
|
|
231
|
+
|
|
232
|
+
const bot = botList.bots.find(b => b.id === answers.botId);
|
|
233
|
+
|
|
234
|
+
const job = addCronJob({
|
|
235
|
+
name: answers.name,
|
|
236
|
+
message: answers.message,
|
|
237
|
+
botId: answers.botId,
|
|
238
|
+
botName: bot.name,
|
|
239
|
+
schedule,
|
|
240
|
+
outputType: outputAnswer.outputType,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
console.log(chalk.green(`\n✅ Cron job created: ${job.id}\n`));
|
|
244
|
+
console.log(chalk.gray('Start the cron daemon with: natureco cron start\n'));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function removeCronJobCommand(id) {
|
|
248
|
+
const removed = removeCronJob(id);
|
|
249
|
+
if (removed) {
|
|
250
|
+
console.log(chalk.green(`\n✅ Cron job removed: ${id}\n`));
|
|
251
|
+
} else {
|
|
252
|
+
console.log(chalk.red(`\n❌ Cron job not found: ${id}\n`));
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async function runCronJobNow(id) {
|
|
258
|
+
const job = getCronJob(id);
|
|
259
|
+
if (!job) {
|
|
260
|
+
console.log(chalk.red(`\n❌ Cron job not found: ${id}\n`));
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const apiKey = getApiKey();
|
|
265
|
+
if (!apiKey) {
|
|
266
|
+
console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
console.log(chalk.yellow(`\n⏳ Running job: ${job.name}...\n`));
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const response = await sendMessage(apiKey, job.botId, job.message, null, '');
|
|
274
|
+
const reply = response.reply || response.message || 'No response';
|
|
275
|
+
|
|
276
|
+
const output = `Job: ${job.name}\nBot: ${job.botName}\nMessage: ${job.message}\nReply: ${reply}`;
|
|
277
|
+
|
|
278
|
+
if (job.outputType === 'file') {
|
|
279
|
+
logCronOutput(job.id, output);
|
|
280
|
+
console.log(chalk.green('✅ Job completed. Output saved to log file.\n'));
|
|
281
|
+
} else {
|
|
282
|
+
console.log(chalk.green('✅ Job completed:\n'));
|
|
283
|
+
console.log(chalk.white(reply));
|
|
284
|
+
console.log('');
|
|
285
|
+
}
|
|
286
|
+
} catch (err) {
|
|
287
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function toggleCronJob(id, enabled) {
|
|
293
|
+
const updated = updateCronJob(id, { enabled });
|
|
294
|
+
if (updated) {
|
|
295
|
+
const status = enabled ? 'enabled' : 'disabled';
|
|
296
|
+
console.log(chalk.green(`\n✅ Cron job ${status}: ${id}\n`));
|
|
297
|
+
} else {
|
|
298
|
+
console.log(chalk.red(`\n❌ Cron job not found: ${id}\n`));
|
|
299
|
+
process.exit(1);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function startCronDaemon() {
|
|
304
|
+
const apiKey = getApiKey();
|
|
305
|
+
if (!apiKey) {
|
|
306
|
+
console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
|
|
307
|
+
process.exit(1);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
console.log(chalk.green('🚀 Cron daemon started\n'));
|
|
311
|
+
console.log(chalk.gray('Press Ctrl+C to stop\n'));
|
|
312
|
+
|
|
313
|
+
const jobs = loadCronJobs();
|
|
314
|
+
const tasks = [];
|
|
315
|
+
|
|
316
|
+
jobs.forEach(job => {
|
|
317
|
+
if (!job.enabled) return;
|
|
318
|
+
|
|
319
|
+
const cronExpression = parseCronSchedule(job.schedule);
|
|
320
|
+
|
|
321
|
+
if (!validateCronExpression(cronExpression)) {
|
|
322
|
+
console.log(chalk.red(`❌ Invalid cron expression for job ${job.id}: ${job.schedule}`));
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const task = cron.schedule(cronExpression, async () => {
|
|
327
|
+
console.log(chalk.yellow(`⏳ Running job: ${job.name}`));
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
const response = await sendMessage(apiKey, job.botId, job.message, null, '');
|
|
331
|
+
const reply = response.reply || response.message || 'No response';
|
|
332
|
+
|
|
333
|
+
const output = `Job: ${job.name}\nBot: ${job.botName}\nMessage: ${job.message}\nReply: ${reply}`;
|
|
334
|
+
|
|
335
|
+
if (job.outputType === 'file') {
|
|
336
|
+
logCronOutput(job.id, output);
|
|
337
|
+
console.log(chalk.green(`✅ Job completed: ${job.name} (saved to log)`));
|
|
338
|
+
} else {
|
|
339
|
+
console.log(chalk.green(`✅ Job completed: ${job.name}`));
|
|
340
|
+
console.log(chalk.white(reply));
|
|
341
|
+
}
|
|
342
|
+
} catch (err) {
|
|
343
|
+
console.log(chalk.red(`❌ Job failed: ${job.name} - ${err.message}`));
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
tasks.push(task);
|
|
348
|
+
console.log(chalk.cyan(`✓ Scheduled: ${job.name} (${job.schedule})`));
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
if (tasks.length === 0) {
|
|
352
|
+
console.log(chalk.gray('No enabled jobs found.\n'));
|
|
353
|
+
process.exit(0);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
console.log('');
|
|
357
|
+
|
|
358
|
+
// Keep process alive
|
|
359
|
+
process.on('SIGINT', () => {
|
|
360
|
+
console.log(chalk.gray('\n\n👋 Stopping cron daemon...\n'));
|
|
361
|
+
tasks.forEach(task => task.stop());
|
|
362
|
+
process.exit(0);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function showCronLogs(id) {
|
|
367
|
+
const job = getCronJob(id);
|
|
368
|
+
if (!job) {
|
|
369
|
+
console.log(chalk.red(`\n❌ Cron job not found: ${id}\n`));
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const logs = getCronLog(id);
|
|
374
|
+
if (!logs) {
|
|
375
|
+
console.log(chalk.gray(`\nNo logs found for job: ${job.name}\n`));
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
console.log(chalk.yellow(`\nLogs for job: ${job.name}\n`));
|
|
380
|
+
console.log(logs);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
module.exports = cronCommand;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const { getApiKey } = require('../utils/config');
|
|
5
|
+
const { getBots, sendMessage } = require('../utils/api');
|
|
6
|
+
|
|
7
|
+
async function git(action, ...args) {
|
|
8
|
+
if (!action) {
|
|
9
|
+
console.log(chalk.red('\n❌ Action required\n'));
|
|
10
|
+
console.log(chalk.gray('Available actions: review, commit, pr, explain\n'));
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (action === 'review') {
|
|
15
|
+
return gitReview();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (action === 'commit') {
|
|
19
|
+
return gitCommit();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (action === 'pr') {
|
|
23
|
+
return gitPR();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (action === 'explain') {
|
|
27
|
+
return gitExplain();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log(chalk.red(`\n❌ Unknown action: ${action}\n`));
|
|
31
|
+
console.log(chalk.gray('Available actions: review, commit, pr, explain\n'));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function gitReview() {
|
|
36
|
+
let diff;
|
|
37
|
+
try {
|
|
38
|
+
diff = execSync('git diff --staged', { encoding: 'utf-8' });
|
|
39
|
+
} catch (err) {
|
|
40
|
+
console.log(chalk.red('\n❌ Git error. Make sure you are in a git repository.\n'));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!diff || diff.trim() === '') {
|
|
45
|
+
console.log(chalk.gray('\nNo staged changes to review.\n'));
|
|
46
|
+
console.log(chalk.gray('Stage changes with: git add <files>\n'));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const { apiKey, bot } = await getDefaultBot();
|
|
51
|
+
|
|
52
|
+
const prompt = `Bu değişiklikleri incele, sorunları ve iyileştirme önerilerini listele:\n\n${diff}`;
|
|
53
|
+
|
|
54
|
+
console.log(chalk.yellow('\n⏳ Reviewing changes...\n'));
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const response = await sendMessage(apiKey, bot.id, prompt, null, '');
|
|
58
|
+
const reply = response.reply || response.message || 'No response';
|
|
59
|
+
|
|
60
|
+
console.log(chalk.green('Code Review:\n'));
|
|
61
|
+
console.log(chalk.white(reply));
|
|
62
|
+
console.log('');
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function gitCommit() {
|
|
70
|
+
let diff;
|
|
71
|
+
try {
|
|
72
|
+
diff = execSync('git diff --staged', { encoding: 'utf-8' });
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.log(chalk.red('\n❌ Git error. Make sure you are in a git repository.\n'));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!diff || diff.trim() === '') {
|
|
79
|
+
console.log(chalk.gray('\nNo staged changes to commit.\n'));
|
|
80
|
+
console.log(chalk.gray('Stage changes with: git add <files>\n'));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const { apiKey, bot } = await getDefaultBot();
|
|
85
|
+
|
|
86
|
+
const prompt = `Bu değişiklikler için conventional commit formatında kısa ve açıklayıcı bir commit mesajı yaz (sadece mesajı yaz, açıklama yapma):\n\n${diff}`;
|
|
87
|
+
|
|
88
|
+
console.log(chalk.yellow('\n⏳ Generating commit message...\n'));
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const response = await sendMessage(apiKey, bot.id, prompt, null, '');
|
|
92
|
+
let commitMessage = response.reply || response.message || 'Update';
|
|
93
|
+
|
|
94
|
+
// Clean up the message
|
|
95
|
+
commitMessage = commitMessage.trim().replace(/^["']|["']$/g, '');
|
|
96
|
+
|
|
97
|
+
console.log(chalk.green('Suggested commit message:\n'));
|
|
98
|
+
console.log(chalk.white(commitMessage));
|
|
99
|
+
console.log('');
|
|
100
|
+
|
|
101
|
+
process.stdin.resume();
|
|
102
|
+
|
|
103
|
+
const answer = await inquirer.prompt([
|
|
104
|
+
{
|
|
105
|
+
type: 'confirm',
|
|
106
|
+
name: 'confirm',
|
|
107
|
+
message: 'Use this commit message?',
|
|
108
|
+
default: true,
|
|
109
|
+
},
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
if (answer.confirm) {
|
|
113
|
+
try {
|
|
114
|
+
execSync(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { stdio: 'inherit' });
|
|
115
|
+
console.log(chalk.green('\n✅ Committed successfully\n'));
|
|
116
|
+
} catch (err) {
|
|
117
|
+
console.log(chalk.red('\n❌ Commit failed\n'));
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
console.log(chalk.gray('\nCommit cancelled\n'));
|
|
122
|
+
}
|
|
123
|
+
} catch (err) {
|
|
124
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function gitPR() {
|
|
130
|
+
let diff;
|
|
131
|
+
try {
|
|
132
|
+
diff = execSync('git diff main...HEAD', { encoding: 'utf-8' });
|
|
133
|
+
} catch (err) {
|
|
134
|
+
try {
|
|
135
|
+
diff = execSync('git diff master...HEAD', { encoding: 'utf-8' });
|
|
136
|
+
} catch {
|
|
137
|
+
console.log(chalk.red('\n❌ Git error. Make sure you are in a git repository with a main/master branch.\n'));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!diff || diff.trim() === '') {
|
|
143
|
+
console.log(chalk.gray('\nNo changes to create PR description for.\n'));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const { apiKey, bot } = await getDefaultBot();
|
|
148
|
+
|
|
149
|
+
const prompt = `Bu değişiklikler için bir Pull Request açıklaması yaz. Başlık ve detaylı açıklama içersin:\n\n${diff}`;
|
|
150
|
+
|
|
151
|
+
console.log(chalk.yellow('\n⏳ Generating PR description...\n'));
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
const response = await sendMessage(apiKey, bot.id, prompt, null, '');
|
|
155
|
+
const prDescription = response.reply || response.message || 'No description';
|
|
156
|
+
|
|
157
|
+
console.log(chalk.green('PR Description:\n'));
|
|
158
|
+
console.log(chalk.white(prDescription));
|
|
159
|
+
console.log('');
|
|
160
|
+
} catch (err) {
|
|
161
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function gitExplain() {
|
|
167
|
+
let log;
|
|
168
|
+
try {
|
|
169
|
+
log = execSync('git log -1 --pretty=format:"%H%n%an%n%ad%n%s%n%b" HEAD', { encoding: 'utf-8' });
|
|
170
|
+
} catch (err) {
|
|
171
|
+
console.log(chalk.red('\n❌ Git error. Make sure you are in a git repository.\n'));
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let diff;
|
|
176
|
+
try {
|
|
177
|
+
diff = execSync('git show HEAD', { encoding: 'utf-8' });
|
|
178
|
+
} catch (err) {
|
|
179
|
+
console.log(chalk.red('\n❌ Could not get commit diff\n'));
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const { apiKey, bot } = await getDefaultBot();
|
|
184
|
+
|
|
185
|
+
const prompt = `Bu commit'i açıkla:\n\nCommit Info:\n${log}\n\nChanges:\n${diff}`;
|
|
186
|
+
|
|
187
|
+
console.log(chalk.yellow('\n⏳ Explaining commit...\n'));
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
const response = await sendMessage(apiKey, bot.id, prompt, null, '');
|
|
191
|
+
const explanation = response.reply || response.message || 'No explanation';
|
|
192
|
+
|
|
193
|
+
console.log(chalk.green('Commit Explanation:\n'));
|
|
194
|
+
console.log(chalk.white(explanation));
|
|
195
|
+
console.log('');
|
|
196
|
+
} catch (err) {
|
|
197
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function getDefaultBot() {
|
|
203
|
+
const apiKey = getApiKey();
|
|
204
|
+
|
|
205
|
+
if (!apiKey) {
|
|
206
|
+
console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let botList;
|
|
211
|
+
try {
|
|
212
|
+
botList = await getBots(apiKey);
|
|
213
|
+
} catch (err) {
|
|
214
|
+
console.log(chalk.red(`\n❌ Error: ${err.message}\n`));
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!botList || !botList.bots || botList.bots.length === 0) {
|
|
219
|
+
console.log(chalk.gray('No bots found. Create one at https://developers.natureco.me\n'));
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Use first bot as default
|
|
224
|
+
const bot = botList.bots[0];
|
|
225
|
+
|
|
226
|
+
return { apiKey, bot };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
module.exports = git;
|
package/src/commands/help.js
CHANGED
|
@@ -14,11 +14,18 @@ function help() {
|
|
|
14
14
|
{ cmd: 'natureco logout', desc: 'Logout and remove credentials' },
|
|
15
15
|
{ cmd: 'natureco bots', desc: 'List your AI bots' },
|
|
16
16
|
{ cmd: 'natureco chat <bot-name>', desc: 'Start chat with a bot' },
|
|
17
|
+
{ cmd: 'natureco chat <bot> --resume', desc: 'Resume latest session' },
|
|
17
18
|
{ cmd: 'natureco ask "<question>"', desc: 'Ask a single question' },
|
|
18
19
|
{ cmd: 'natureco run <script.md>', desc: 'Run a markdown script' },
|
|
19
20
|
{ cmd: 'natureco init', desc: 'Initialize project' },
|
|
20
21
|
{ cmd: 'natureco skills [action]', desc: 'Manage skills' },
|
|
21
22
|
{ cmd: 'natureco mcp [action]', desc: 'Manage MCP servers' },
|
|
23
|
+
{ cmd: 'natureco commands [action]', desc: 'Manage custom commands' },
|
|
24
|
+
{ cmd: 'natureco cron [action]', desc: 'Manage cron jobs' },
|
|
25
|
+
{ cmd: 'natureco hooks [action]', desc: 'Manage hooks' },
|
|
26
|
+
{ cmd: 'natureco sessions [action]', desc: 'Manage chat sessions' },
|
|
27
|
+
{ cmd: 'natureco git <action>', desc: 'Git integration' },
|
|
28
|
+
{ cmd: 'natureco tasks [action]', desc: 'Manage background tasks' },
|
|
22
29
|
{ cmd: 'natureco config <action>', desc: 'Manage configuration' },
|
|
23
30
|
{ cmd: 'natureco update', desc: 'Check for updates' },
|
|
24
31
|
{ cmd: 'natureco help', desc: 'Show this help message' },
|
|
@@ -33,19 +40,36 @@ function help() {
|
|
|
33
40
|
console.log(chalk.gray(' $ natureco login'));
|
|
34
41
|
console.log(chalk.gray(' $ natureco init'));
|
|
35
42
|
console.log(chalk.gray(' $ natureco bots'));
|
|
43
|
+
console.log(chalk.gray(' $ natureco chat "Nature Bot V3"'));
|
|
44
|
+
console.log(chalk.gray(' $ natureco chat "Bot" --resume'));
|
|
36
45
|
console.log(chalk.gray(' $ natureco ask "bu haftaki görevlerimi listele"'));
|
|
37
46
|
console.log(chalk.gray(' $ natureco run script.md'));
|
|
38
|
-
console.log(chalk.gray(' $ natureco skills'));
|
|
39
|
-
console.log(chalk.gray(' $ natureco skills install
|
|
40
|
-
console.log(chalk.gray(' $ natureco
|
|
47
|
+
console.log(chalk.gray(' $ natureco skills install github'));
|
|
48
|
+
console.log(chalk.gray(' $ natureco skills install clawhub:github'));
|
|
49
|
+
console.log(chalk.gray(' $ natureco commands create review'));
|
|
50
|
+
console.log(chalk.gray(' $ natureco cron add'));
|
|
51
|
+
console.log(chalk.gray(' $ natureco cron start'));
|
|
52
|
+
console.log(chalk.gray(' $ natureco hooks create pre-message'));
|
|
53
|
+
console.log(chalk.gray(' $ natureco sessions list'));
|
|
54
|
+
console.log(chalk.gray(' $ natureco git review'));
|
|
55
|
+
console.log(chalk.gray(' $ natureco git commit'));
|
|
56
|
+
console.log(chalk.gray(' $ natureco tasks list'));
|
|
41
57
|
console.log(chalk.gray(' $ natureco mcp add'));
|
|
42
|
-
console.log(chalk.gray(' $ natureco chat "Nature Bot V3"'));
|
|
43
58
|
console.log(chalk.gray(' $ natureco config list'));
|
|
44
59
|
console.log(chalk.gray(' $ natureco update'));
|
|
45
60
|
console.log(chalk.gray(' $ natureco logout\n'));
|
|
46
61
|
|
|
47
62
|
console.log(chalk.cyan.bold('Chat Commands:\n'));
|
|
48
63
|
console.log(chalk.gray(' Type your message and press Enter'));
|
|
64
|
+
console.log(chalk.gray(' /clear - Clear screen'));
|
|
65
|
+
console.log(chalk.gray(' /bot [name] - Switch bot'));
|
|
66
|
+
console.log(chalk.gray(' /skills - Show active skills'));
|
|
67
|
+
console.log(chalk.gray(' /memory - Show memory'));
|
|
68
|
+
console.log(chalk.gray(' /memory clear - Clear memory'));
|
|
69
|
+
console.log(chalk.gray(' /commands - List custom commands'));
|
|
70
|
+
console.log(chalk.gray(' /<command-name> - Use custom command'));
|
|
71
|
+
console.log(chalk.gray(' /help - Show chat help'));
|
|
72
|
+
console.log(chalk.gray(' Ctrl+B - Move task to background'));
|
|
49
73
|
console.log(chalk.gray(' Type "exit" or "quit" to leave chat\n'));
|
|
50
74
|
|
|
51
75
|
console.log(chalk.cyan.bold('Get API Key:\n'));
|