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 +1 -1
- package/src/commands/code.js +126 -3
package/package.json
CHANGED
package/src/commands/code.js
CHANGED
|
@@ -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);
|