natureco-cli 2.20.1 → 2.21.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "2.20.1",
3
+ "version": "2.21.0",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "main": "bin/natureco.js",
6
6
  "bin": {
@@ -141,6 +141,48 @@ function buildIndexPrompt(index) {
141
141
  return lines.join('\n');
142
142
  }
143
143
 
144
+ // ── Proje hafızası ────────────────────────────────────────────────────────────
145
+ function getProjectMemoryPath() {
146
+ return path.join(process.cwd(), '.natureco', 'project.md');
147
+ }
148
+
149
+ function loadProjectMemory() {
150
+ try {
151
+ const p = getProjectMemoryPath();
152
+ if (fs.existsSync(p)) return fs.readFileSync(p, 'utf8');
153
+ } catch {}
154
+ return null;
155
+ }
156
+
157
+ async function generateSummary(messages, providerConfig) {
158
+ const recent = messages.filter(m => m.role !== 'system').slice(-12);
159
+ if (!recent.length) return 'Bu session boş geçti.';
160
+ const prompt = `Bu kod session'ını 3-5 madde halinde Türkçe özetle. Ne yapıldı, hangi dosyalar değiştirildi, hangi sorunlar çözüldü:\n${JSON.stringify(recent).slice(0, 3000)}`;
161
+ try {
162
+ const res = await fetch(`${providerConfig.url}/chat/completions`, {
163
+ method: 'POST',
164
+ headers: { 'Authorization': `Bearer ${providerConfig.apiKey}`, 'Content-Type': 'application/json' },
165
+ body: JSON.stringify({ model: providerConfig.model, messages: [{ role: 'user', content: prompt }], max_tokens: 400, stream: false }),
166
+ });
167
+ const data = await res.json();
168
+ return data.choices?.[0]?.message?.content || 'Özet oluşturulamadı.';
169
+ } catch {
170
+ return 'Özet oluşturulamadı.';
171
+ }
172
+ }
173
+
174
+ async function saveProjectMemory(messages, providerConfig) {
175
+ const sp = startSpinner('Proje hafızası güncelleniyor...');
176
+ const summary = await generateSummary(messages, providerConfig);
177
+ stopSpinner(sp, 'Proje hafızası güncellendi', true);
178
+ const memPath = getProjectMemoryPath();
179
+ const dir = path.dirname(memPath);
180
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
181
+ const existing = fs.existsSync(memPath) ? fs.readFileSync(memPath, 'utf8') : '# Proje Hafızası\n';
182
+ const entry = `\n## ${new Date().toLocaleDateString('tr-TR')} — ${new Date().toLocaleTimeString('tr-TR', { hour: '2-digit', minute: '2-digit' })}\n${summary}\n`;
183
+ fs.writeFileSync(memPath, existing + entry);
184
+ }
185
+
144
186
  // ── Git helpers ───────────────────────────────────────────────────────────────
145
187
  async function generateCommitMessage(diff, providerConfig) {
146
188
  const body = {
@@ -378,6 +420,12 @@ ${indexPrompt}`;
378
420
  if (agentsPrompt) systemPrompt += `\n\n## Project Instructions\n${agentsPrompt}`;
379
421
  if (memoryPrompt) systemPrompt += '\n\n' + memoryPrompt;
380
422
 
423
+ // ── Proje hafızası ────────────────────────────────────────────────────────
424
+ const projectMemory = loadProjectMemory();
425
+ if (projectMemory) {
426
+ systemPrompt += `\n\n## Proje Geçmişi (.natureco/project.md)\n${projectMemory.slice(0, 2000)}`;
427
+ }
428
+
381
429
  // Hedef dosya varsa context'e ekle
382
430
  if (targetFile) {
383
431
  try {
@@ -428,6 +476,7 @@ ${indexPrompt}`;
428
476
  console.log(centerText(chalk.gray(`🌿 ${projectIndex.gitBranch} · ${changes} değişiklik`)));
429
477
  }
430
478
  if (targetFile) console.log(centerText(chalk.gray(`📄 ${targetFile}`)));
479
+ if (projectMemory) console.log(centerText(chalk.gray(`📋 Proje hafızası yüklendi`)));
431
480
  console.log(centerText(chalk.gray(`${shortModel} · /help · Ctrl+C çıkış`)));
432
481
  console.log(sep());
433
482
  console.log();
@@ -451,6 +500,36 @@ ${indexPrompt}`;
451
500
  console.log();
452
501
  }
453
502
 
503
+ // ── Komut çalıştır + hata döngüsü ───────────────────────────────────────────
504
+ async function runAndFix(cmd) {
505
+ console.log(chalk.gray(`\n ▶ ${cmd} çalıştırılıyor...\n`));
506
+ try {
507
+ const output = execSync(cmd, {
508
+ cwd: process.cwd(), timeout: 30000, stdio: 'pipe',
509
+ }).toString();
510
+ console.log(chalk.green(' ✓ Başarılı:'));
511
+ console.log(chalk.gray(' ' + output.slice(0, 500).split('\n').join('\n ')));
512
+ console.log();
513
+ } catch (err) {
514
+ const errorOutput = (err.stderr?.toString() || err.stdout?.toString() || err.message || '').slice(0, 500);
515
+ console.log(chalk.red(' ✗ Hata:'));
516
+ console.log(chalk.gray(' ' + errorOutput.split('\n').join('\n ')));
517
+ console.log();
518
+
519
+ const { fix } = await inquirer.prompt([{
520
+ type: 'confirm', name: 'fix',
521
+ message: chalk.yellow(' Hatayı otomatik düzeltmemi ister misin?'),
522
+ default: true,
523
+ }]);
524
+
525
+ if (fix) {
526
+ const fixMessage = `Şu komut çalıştırıldı: ${cmd}\nHata oluştu:\n${errorOutput}\nBu hatayı analiz et ve düzelt.`;
527
+ console.log(chalk.cyan('\n Düzeltiliyor...\n'));
528
+ await handleMessage(fixMessage);
529
+ }
530
+ }
531
+ }
532
+
454
533
  // ── Mesaj gönder + tool loop ──────────────────────────────────────────────
455
534
  async function handleMessage(userMessage) {
456
535
  userMessage = userMessage.trim();
@@ -463,9 +542,12 @@ ${indexPrompt}`;
463
542
  console.log(chalk.yellow('Code Agent Komutları:'));
464
543
  [
465
544
  ['/clear', 'Ekranı temizle'],
466
- ['/summary', 'Session özetini göster'],
545
+ ['/summary', 'Session özetini göster ve kaydet'],
546
+ ['/memory', 'Proje hafızasını göster'],
467
547
  ['/done', 'Bitir ve özet göster'],
468
548
  ['/index', 'Projeyi yeniden indexle'],
549
+ ['/run <cmd>','Komutu çalıştır, hata varsa düzelt'],
550
+ ['/test', 'Testleri çalıştır, hata varsa düzelt'],
469
551
  ['/git', 'Git durumu ve son commitler'],
470
552
  ['/commit', 'Staged değişiklikleri AI ile commit et'],
471
553
  ['/help', 'Bu yardım'],
@@ -477,10 +559,25 @@ ${indexPrompt}`;
477
559
  console.clear();
478
560
  return;
479
561
  case 'summary':
480
- case 'done':
562
+ case 'done': {
563
+ const sum = await generateSummary(conversationMessages, providerConfig);
564
+ console.log(chalk.yellow('\n 📝 Session Özeti:'));
565
+ console.log(chalk.white(' ' + sum.split('\n').join('\n ')));
566
+ console.log();
481
567
  showSummary();
482
568
  if (cmd === 'done') process.exit(0);
483
569
  return;
570
+ }
571
+ case 'memory': {
572
+ const mem = loadProjectMemory();
573
+ if (mem) {
574
+ console.log(chalk.yellow('\n 📋 Proje Hafızası:'));
575
+ console.log(chalk.gray(' ' + mem.slice(0, 1500).split('\n').join('\n ')));
576
+ } else {
577
+ console.log(chalk.gray('\n Henüz proje hafızası yok. /done ile kaydet.\n'));
578
+ }
579
+ return;
580
+ }
484
581
  case 'index': {
485
582
  const sp = startSpinner('Proje yeniden indexleniyor...');
486
583
  const newIndex = await indexProject(process.cwd());
@@ -492,6 +589,22 @@ ${indexPrompt}`;
492
589
  );
493
590
  return;
494
591
  }
592
+ case 'run': {
593
+ const runCmd = userMessage.slice(4).trim() || 'node index.js';
594
+ await runAndFix(runCmd);
595
+ return;
596
+ }
597
+ case 'test': {
598
+ const testCmd = projectIndex.packageJson?.scripts?.test
599
+ ? 'npm test'
600
+ : projectIndex.type === 'python' ? 'python -m pytest' : null;
601
+ if (!testCmd) {
602
+ console.log(chalk.red(' Test komutu bulunamadı.\n'));
603
+ return;
604
+ }
605
+ await runAndFix(testCmd);
606
+ return;
607
+ }
495
608
  case 'git': {
496
609
  try {
497
610
  const status = execSync('git status --short', { cwd: process.cwd(), stdio: 'pipe' }).toString().trim();
@@ -616,8 +729,18 @@ ${indexPrompt}`;
616
729
  // ── Input loop ───────────────────────────────────────────────────────────────
617
730
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
618
731
 
619
- process.on('SIGINT', () => {
732
+ process.on('SIGINT', async () => {
620
733
  rl.close();
734
+ if (conversationMessages.length > 2) {
735
+ try {
736
+ const { save } = await inquirer.prompt([{
737
+ type: 'confirm', name: 'save',
738
+ message: chalk.yellow(" Bu session'ı proje hafızasına kaydet?"),
739
+ default: true,
740
+ }]);
741
+ if (save) await saveProjectMemory(conversationMessages, providerConfig);
742
+ } catch {}
743
+ }
621
744
  showSummary();
622
745
  console.log(chalk.gray('👋 Goodbye!\n'));
623
746
  process.exit(0);