natureco-cli 5.4.7 → 5.4.9

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": "5.4.7",
3
+ "version": "5.4.9",
4
4
  "description": "OpenClaw'dan daha güvenli, daha hızlı, daha ucuz AI agent CLI. Multi-agent, self-evolving skills, audit log, maliyet optimizasyonu ve NatureCo platform-native.",
5
5
  "bin": {
6
6
  "natureco": "bin/natureco.js"
@@ -24,7 +24,7 @@ const chalk = require('chalk');
24
24
  const tui = require('../utils/tui');
25
25
  const { loadToolDefinitions, toOpenAIFormat, executeTool } = require('../utils/tools');
26
26
 
27
- // v5.4.6: Model adi sizintisini engelle
27
+ // v5.4.6: Model adi sizintisini engelle — global'e ata, callback'lerden erisebilir olsun
28
28
  const MODEL_NAMES_TO_HIDE = ['MiniMax-M2.5', 'MiniMaxM2.5', 'minimaxm25', 'Claude-3', 'GPT-4', 'ChatGPT'];
29
29
  function fixModelNameLeak(text, botName) {
30
30
  if (!text) return text;
@@ -38,6 +38,7 @@ function fixModelNameLeak(text, botName) {
38
38
  fixed = fixed.replace(/I am\s+Claude[^.,!?\n]*/gi, 'I am İchigo');
39
39
  return fixed;
40
40
  }
41
+ global.fixModelNameLeak = fixModelNameLeak;
41
42
 
42
43
  // v4.8.0: Tool definitions — başlangıçta bir kez yükle (performans)
43
44
  let _toolDefs = null;
@@ -463,8 +464,20 @@ async function startRepl(args) {
463
464
  // Memory yükle
464
465
  let memory = loadMemory(cfg.userName);
465
466
 
466
- // v5.4.6: Memory'de botName yoksa otomatik İchigo set et
467
+ // v5.4.7: Memory'de botName yoksa otomatik İchigo set et VE kaydet
467
468
  if (!memory.botName) memory.botName = 'İchigo';
469
+ // BotName'i memory'ye persist et (her oturumda ayni kalsin)
470
+ try {
471
+ const fs = require('fs');
472
+ const memFile = path.join(os.homedir(), '.natureco', 'memory', ((cfg.userName || 'default').toLowerCase()) + '.json');
473
+ if (fs.existsSync(memFile)) {
474
+ const memData = JSON.parse(fs.readFileSync(memFile, 'utf8'));
475
+ if (!memData.botName || memData.botName !== memory.botName) {
476
+ memData.botName = memory.botName;
477
+ fs.writeFileSync(memFile, JSON.stringify(memData, null, 2), 'utf8');
478
+ }
479
+ }
480
+ } catch (e) {} // Sessizce devam et, kritik degil
468
481
  // v5.4.5: SOUL.md'yi yukle ve kisiligi system prompt'a enjekte et
469
482
  const { loadSoul, summarizeSoul } = require("../tools/soul");
470
483
  const soulContent = loadSoul();
@@ -552,6 +565,9 @@ async function startRepl(args) {
552
565
  }
553
566
  console.log(tui.C.muted(' Komutlar: ') + tui.C.yellow('/help') + tui.C.muted(' · ') + tui.C.yellow('/memory') + tui.C.muted(' · ') + tui.C.yellow('/sessions') + tui.C.muted(' · ') + tui.C.yellow('/exit'));
554
567
  console.log('');
568
+ // v5.4.7: Hard-coded kimlik — model once bunu okusun
569
+ console.log(tui.C.brand(' 👋 Ben ' + (memory.botName || 'İchigo') + ', ' + (userName || 'kanka') + '. Sen nasilsin?'));
570
+ console.log('');
555
571
 
556
572
  let totalInputTokens = 0;
557
573
  let totalOutputTokens = 0;
@@ -712,6 +728,17 @@ async function startRepl(args) {
712
728
  // User mesajı
713
729
  messages.push({ role: 'user', content: line });
714
730
 
731
+ // v5.4.9: Hard-coded fallback — "sen kimsin?" gibi sorular icin model cevabindan once prefix
732
+ const trimmed = (line || '').toLowerCase();
733
+ const isIdentityQuestion = /(sen\s+kim|adin\s+ne|kendini\s+tan|kendin\s+tanit|kimsin|ne\s+adindasin)/.test(trimmed);
734
+ if (isIdentityQuestion) {
735
+ // Hard-coded "Ben İchigo" — model cevap verse bile onemli degil, bu gorunur
736
+ process.stdout.write(tui.styled('\n AI ', { color: tui.PALETTE.secondary, bold: true }));
737
+ process.stdout.write('Ben İchigo, NatureCo CLI\'nin Türkçe yapay zeka asistanıyım. ');
738
+ // Modelin devam etmesini beklemiyoruz, normal akis devam etsin
739
+ console.log('\n');
740
+ }
741
+
715
742
  // AI cevabı
716
743
  process.stdout.write(tui.styled('\n AI ', { color: tui.PALETTE.secondary, bold: true }));
717
744
  try {
@@ -721,11 +748,31 @@ async function startRepl(args) {
721
748
  providerApiKey,
722
749
  apiMessages,
723
750
  model,
724
- // Text chunk callback — v5.4.6: post-process ile model adı sızıntısını engelle
751
+ // Text chunk callback — v5.4.9: streaming buffer + fix
752
+ // Streaming'de cümleler chunk'lar arasinda bolunur ("Ben " + "NatureCo " + "CLI").
753
+ // Buffer biriktir, cumle tamamlaninca (. ! ? veya newline) fix uygula.
725
754
  (chunk) => {
726
755
  try {
727
- const fixedChunk = fixModelNameLeak(chunk, botName);
728
- process.stdout.write(fixedChunk);
756
+ let c = String(chunk || '');
757
+ // Eger fixBuffer global'de yoksa olustur
758
+ if (!global._fixBuffer) global._fixBuffer = '';
759
+ global._fixBuffer += c;
760
+
761
+ // Son karakterle karar ver
762
+ const lastChar = global._fixBuffer.slice(-1);
763
+ // Noktalama veya newline varsa, buffer'i isle ve temizle
764
+ if (/[.!?\n]/.test(lastChar)) {
765
+ let toProcess = global._fixBuffer;
766
+ global._fixBuffer = '';
767
+ // Tum model adlarini İchigo ile degistir
768
+ toProcess = toProcess.replace(/MiniMax[\s\-\w\.]*/g, 'İchigo');
769
+ toProcess = toProcess.replace(/Claude[\s\-\w\.]*/g, 'İchigo');
770
+ toProcess = toProcess.replace(/GPT[\s\-\w\.]*/g, 'İchigo');
771
+ toProcess = toProcess.replace(/ChatGPT/g, 'İchigo');
772
+ toProcess = toProcess.replace(/Ben\s+(?:MiniMax|Claude|GPT|NatureCo\s+CLI|bir\s+AI)[^\n.!?]*/gi, 'Ben İchigo');
773
+ process.stdout.write(toProcess);
774
+ }
775
+ // Noktalama yoksa, sadece bekle (sonraki chunk'ta tamamlanir)
729
776
  } catch (e) {
730
777
  process.stdout.write(chunk);
731
778
  }
@@ -58,16 +58,54 @@ function decayFacts(memory) {
58
58
  return memory;
59
59
  }
60
60
 
61
+
62
+ /**
63
+ * v5.4.9: Memory yazma sonrasi verification — geri oku ve gercekten yazildigini dogrula
64
+ * Self-validation mekanizmasi: tool cagirip "success" demesine ragmen dosya bos olabilir
65
+ */
66
+ function verifyMemoryWrite(username, expectedFact, expectedBotName) {
67
+ try {
68
+ const memFile = getMemoryFile(username);
69
+ if (!fs.existsSync(memFile)) {
70
+ return { success: false, error: "Memory dosyasi olusturulamadi: " + memFile };
71
+ }
72
+ const mem = JSON.parse(fs.readFileSync(memFile, "utf8"));
73
+
74
+ // Fact verification
75
+ if (expectedFact) {
76
+ const found = (mem.facts || []).some(f => f.value === expectedFact);
77
+ if (!found) {
78
+ return { success: false, error: "Fact memory'de bulunamadi: " + expectedFact };
79
+ }
80
+ }
81
+
82
+ // BotName verification
83
+ if (expectedBotName && mem.botName !== expectedBotName) {
84
+ return { success: false, error: "BotName guncellenmedi: " + mem.botName };
85
+ }
86
+
87
+ return { success: true, message: "Memory dogrulandi" };
88
+ } catch (e) {
89
+ return { success: false, error: e.message };
90
+ }
91
+ }
92
+
93
+
61
94
  function addMemory({ username, fact, score = 5, category = "general", botName, nickname, name }) {
62
- if (!username) return { success: false, error: "username gerekli" };
95
+ // Username yoksa ve 'name' parametresi varsa, onu username olarak kullan
96
+ // (Parton'un "patron" diye hitap etmesi durumu icin)
97
+ const effectiveUsername = username || (name && name.toLowerCase()) || 'default';
98
+ if (!effectiveUsername || effectiveUsername === 'default') {
99
+ // Hicbir username yok, default.json'a yaz
100
+ }
63
101
 
64
- let memory = loadMemory(username);
102
+ let memory = loadMemory(effectiveUsername);
65
103
  memory = decayFacts(memory);
66
104
 
67
- // identity updates (botName, nickname, name)
105
+ // identity updates (botName, nickname, name) — name sadece memory.name, username degil
68
106
  if (botName) memory.botName = botName;
69
107
  if (nickname !== undefined) memory.nickname = nickname;
70
- if (name) memory.name = name;
108
+ if (name) memory.name = name; // Bu memory.name (kullanici gercek adi), username degil
71
109
 
72
110
  if (fact) {
73
111
  // duplicate kontrol
@@ -87,12 +125,23 @@ function addMemory({ username, fact, score = 5, category = "general", botName, n
87
125
  }
88
126
 
89
127
  if (!memory.preferences) memory.preferences = [];
90
- memory = saveMemory(username, memory);
128
+ memory = saveMemory(effectiveUsername, memory);
129
+
130
+ // v5.4.9: Verification - geri oku ve dogrula
131
+ const verifyResult = verifyMemoryWrite(effectiveUsername, fact, botName);
132
+ if (!verifyResult.success) {
133
+ return {
134
+ success: false,
135
+ error: "Memory yazildi ama dogrulanamadi: " + verifyResult.error,
136
+ username: effectiveUsername,
137
+ };
138
+ }
91
139
 
92
140
  return {
93
141
  success: true,
94
- message: "Memory guncellendi",
95
- username,
142
+ message: "Memory guncellendi ve dogrulandi",
143
+ username: effectiveUsername,
144
+ verified: true,
96
145
  totalFacts: memory.facts.length,
97
146
  facts: memory.facts.map(f => ({ value: f.value, score: f.score, category: f.category })),
98
147
  botName: memory.botName,