natureco-cli 2.20.0 → 2.20.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "2.20.0",
3
+ "version": "2.20.2",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "main": "bin/natureco.js",
6
6
  "bin": {
@@ -141,7 +141,28 @@ function buildIndexPrompt(index) {
141
141
  return lines.join('\n');
142
142
  }
143
143
 
144
- // ── Streaming fetch ───────────────────────────────────────────────────────────
144
+ // ── Git helpers ───────────────────────────────────────────────────────────────
145
+ async function generateCommitMessage(diff, providerConfig) {
146
+ const body = {
147
+ model: providerConfig.model,
148
+ messages: [
149
+ { role: 'system', content: 'Sen bir git commit mesajı üreticisin. Conventional Commits formatında (feat/fix/refactor/chore vb.) kısa ve açıklayıcı bir commit mesajı yaz. Sadece mesajı yaz, başka hiçbir şey yazma.' },
150
+ { role: 'user', content: `Bu diff için commit mesajı üret:\n\n${diff}` },
151
+ ],
152
+ temperature: 0.3,
153
+ max_tokens: 100,
154
+ stream: false,
155
+ };
156
+ const res = await fetch(`${providerConfig.url}/chat/completions`, {
157
+ method: 'POST',
158
+ headers: { 'Authorization': `Bearer ${providerConfig.apiKey}`, 'Content-Type': 'application/json' },
159
+ body: JSON.stringify(body),
160
+ });
161
+ const data = await res.json();
162
+ return (data.choices?.[0]?.message?.content || 'chore: update files').trim().replace(/^["']|["']$/g, '');
163
+ }
164
+
165
+
145
166
  async function streamMessage(providerConfig, messages, tools) {
146
167
  const endpoint = `${providerConfig.url}/chat/completions`;
147
168
  const body = {
@@ -245,6 +266,10 @@ async function runToolCall(toolCall, stats) {
245
266
  stats.filesChanged++;
246
267
  stats.changedFiles.push(toolCall.input.path || '?');
247
268
  console.log(chalk.green(` ✓ ${toolCall.input.path} güncellendi`));
269
+ if (stats.changedFiles.length === 1) {
270
+ // İlk değişiklikte ipucu göster
271
+ console.log(chalk.gray(` 💡 git add . && /commit ile kaydet`));
272
+ }
248
273
  }
249
274
  if (toolCall.name === 'bash') stats.commandsRun++;
250
275
  stats.toolCallCount++;
@@ -426,6 +451,36 @@ ${indexPrompt}`;
426
451
  console.log();
427
452
  }
428
453
 
454
+ // ── Komut çalıştır + hata döngüsü ───────────────────────────────────────────
455
+ async function runAndFix(cmd) {
456
+ console.log(chalk.gray(`\n ▶ ${cmd} çalıştırılıyor...\n`));
457
+ try {
458
+ const output = execSync(cmd, {
459
+ cwd: process.cwd(), timeout: 30000, stdio: 'pipe',
460
+ }).toString();
461
+ console.log(chalk.green(' ✓ Başarılı:'));
462
+ console.log(chalk.gray(' ' + output.slice(0, 500).split('\n').join('\n ')));
463
+ console.log();
464
+ } catch (err) {
465
+ const errorOutput = (err.stderr?.toString() || err.stdout?.toString() || err.message || '').slice(0, 500);
466
+ console.log(chalk.red(' ✗ Hata:'));
467
+ console.log(chalk.gray(' ' + errorOutput.split('\n').join('\n ')));
468
+ console.log();
469
+
470
+ const { fix } = await inquirer.prompt([{
471
+ type: 'confirm', name: 'fix',
472
+ message: chalk.yellow(' Hatayı otomatik düzeltmemi ister misin?'),
473
+ default: true,
474
+ }]);
475
+
476
+ if (fix) {
477
+ const fixMessage = `Şu komut çalıştırıldı: ${cmd}\nHata oluştu:\n${errorOutput}\nBu hatayı analiz et ve düzelt.`;
478
+ console.log(chalk.cyan('\n Düzeltiliyor...\n'));
479
+ await handleMessage(fixMessage);
480
+ }
481
+ }
482
+ }
483
+
429
484
  // ── Mesaj gönder + tool loop ──────────────────────────────────────────────
430
485
  async function handleMessage(userMessage) {
431
486
  userMessage = userMessage.trim();
@@ -441,6 +496,10 @@ ${indexPrompt}`;
441
496
  ['/summary', 'Session özetini göster'],
442
497
  ['/done', 'Bitir ve özet göster'],
443
498
  ['/index', 'Projeyi yeniden indexle'],
499
+ ['/run <cmd>','Komutu çalıştır, hata varsa düzelt'],
500
+ ['/test', 'Testleri çalıştır, hata varsa düzelt'],
501
+ ['/git', 'Git durumu ve son commitler'],
502
+ ['/commit', 'Staged değişiklikleri AI ile commit et'],
444
503
  ['/help', 'Bu yardım'],
445
504
  ].forEach(([c, d]) => console.log(' ' + chalk.cyan(c.padEnd(12)) + chalk.gray(d)));
446
505
  console.log(chalk.gray(' Ctrl+C'.padEnd(14) + 'Çıkış'));
@@ -465,6 +524,63 @@ ${indexPrompt}`;
465
524
  );
466
525
  return;
467
526
  }
527
+ case 'run': {
528
+ const runCmd = userMessage.slice(4).trim() || 'node index.js';
529
+ await runAndFix(runCmd);
530
+ return;
531
+ }
532
+ case 'test': {
533
+ const testCmd = projectIndex.packageJson?.scripts?.test
534
+ ? 'npm test'
535
+ : projectIndex.type === 'python' ? 'python -m pytest' : null;
536
+ if (!testCmd) {
537
+ console.log(chalk.red(' Test komutu bulunamadı.\n'));
538
+ return;
539
+ }
540
+ await runAndFix(testCmd);
541
+ return;
542
+ }
543
+ case 'git': {
544
+ try {
545
+ const status = execSync('git status --short', { cwd: process.cwd(), stdio: 'pipe' }).toString().trim();
546
+ const log = execSync('git log --oneline -5', { cwd: process.cwd(), stdio: 'pipe' }).toString().trim();
547
+ console.log(chalk.yellow('\n Git Durumu:'));
548
+ console.log(status ? chalk.gray(' ' + status.split('\n').join('\n ')) : chalk.gray(' temiz'));
549
+ console.log(chalk.yellow('\n Son Commitler:'));
550
+ console.log(chalk.gray(' ' + log.split('\n').join('\n ')));
551
+ console.log();
552
+ } catch (e) {
553
+ console.log(chalk.red(' Git bulunamadı veya bu dizin bir git repo değil.\n'));
554
+ }
555
+ return;
556
+ }
557
+ case 'commit': {
558
+ try {
559
+ const diff = execSync('git diff --staged', { cwd: process.cwd(), stdio: 'pipe' }).toString();
560
+ if (!diff.trim()) {
561
+ console.log(chalk.red('\n Staged değişiklik yok.'));
562
+ console.log(chalk.gray(' Önce: git add .\n'));
563
+ return;
564
+ }
565
+ const sp = startSpinner('Commit mesajı üretiliyor...');
566
+ const commitMsg = await generateCommitMessage(diff.slice(0, 2000), providerConfig);
567
+ stopSpinner(sp, 'Commit mesajı hazır', true);
568
+ console.log(chalk.cyan(`\n Önerilen: ${chalk.white(commitMsg)}\n`));
569
+ const { ok } = await inquirer.prompt([{
570
+ type: 'confirm', name: 'ok',
571
+ message: ' Commit edilsin mi?', default: true,
572
+ }]);
573
+ if (ok) {
574
+ execSync(`git commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { cwd: process.cwd(), stdio: 'pipe' });
575
+ console.log(chalk.green(' ✓ Commit yapıldı!\n'));
576
+ } else {
577
+ console.log(chalk.gray(' İptal edildi.\n'));
578
+ }
579
+ } catch (e) {
580
+ console.log(chalk.red(` Git hatası: ${e.message}\n`));
581
+ }
582
+ return;
583
+ }
468
584
  default:
469
585
  console.log(chalk.red(`Bilinmeyen komut: /${cmd}\n`));
470
586
  return;