natureco-cli 5.45.1 → 5.46.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/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/src/commands/repl.js +10 -0
- package/src/tools/memory_tree.js +40 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to NatureCo CLI will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [5.46.0] - 2026-07-08 — "MEMORY: otomatik hijyen — yazma-anı dedup/çelişki uyarısı + oturum-sonu ipucu"
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Otomatik hafıza hijyeni (lint artık yalnız manuel değil).** `natureco memory lint` güçlüydü ama çoğu kullanıcı hiç çalıştırmaz; hafıza sessizce yinelenen/çelişen kayıtlarla bozulurdu. İki gürültüsüz otomatik katman eklendi:
|
|
9
|
+
- **Yazma-anı (`memory_tree append`, ajanın her kaydında).** Yeni yaprak aynı dala eklenirken mevcut yapraklarla Jaccard benzerliğine bakılır (Urðr lint mantığı, LLM'siz): **(a)** çok-benzer (≥%85) → **tekrar EKLENMEZ** (`deduped:true` + not; bloat önlenir, veri kaybı yok çünkü zaten var); **(b)** aynı konu farklı değer (%50–85) → eklenir **ama** sonuca `warning` düşülür (çelişki; hangi değerin doğru olduğuna karar veremeyiz, veriyi kaybetmeyiz → ajan/kullanıcı uzlaştırır, gerekirse `memory_tree remove`). Uyarı `buildFeedback` üzerinden ajana ulaşır (E2E doğrulandı).
|
|
10
|
+
- **Oturum-sonu ipucu.** `natureco chat` kapanışında hafızada olası yinelenen/çelişen kayıt varsa tek satır hatırlatma: `💡 Hafızada N olası yinelenen/çelişen kayıt — "natureco memory lint" ile gözden geçir.` Sadece bulgu varsa yazılır; hata asla oturumu bozmaz.
|
|
11
|
+
- 4 yeni regresyon testi (dedup atlama + tek kopya, çelişki uyarısı + ikisi de saklanır, alakasız temiz, tool-düzeyi Türkçe recall). **600 test yeşil** (597 + 3 skip).
|
|
12
|
+
|
|
13
|
+
### Notes
|
|
14
|
+
- Duplicate eşiği bilinçli olarak yüksek (%85) — yalnızca neredeyse-birebir kayıtlar atlanır; "sunucu ip 10.0.0.5" → "10.0.0.9" gibi gerçek güncellemeler çelişki sayılır (atlanmaz, uyarılır), böylece meşru bir değişiklik asla kaybolmaz.
|
|
15
|
+
|
|
5
16
|
## [5.45.1] - 2026-07-08 — "FIX: Türkçe İ/i recall hatası — büyük-harfli her Türkçe kelime sessizce kaçıyordu"
|
|
6
17
|
|
|
7
18
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natureco-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.46.0",
|
|
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"
|
package/src/commands/repl.js
CHANGED
|
@@ -1243,6 +1243,16 @@ async function startRepl(args) {
|
|
|
1243
1243
|
console.log(chalk.gray(` 🎯 ${persistResult.preferencesAdded} yeni tercih kaydedildi`));
|
|
1244
1244
|
}
|
|
1245
1245
|
|
|
1246
|
+
// v5.46: oturum-sonu hafıza-sağlığı ipucu (gürültüsüz). Yinelenen/çelişen kayıt varsa
|
|
1247
|
+
// tek satır hatırlat — kullanıcı çoğu zaman "natureco memory lint"i hiç çalıştırmaz,
|
|
1248
|
+
// hafıza sessizce bozulur. Sadece bulgu varsa yazılır; hata asla oturumu bozmaz.
|
|
1249
|
+
try {
|
|
1250
|
+
const { lintUser } = require('../utils/memory-lint');
|
|
1251
|
+
const { flatFindings, treeFindings } = lintUser(cfg.userName);
|
|
1252
|
+
const n = (flatFindings.length + treeFindings.length);
|
|
1253
|
+
if (n > 0) console.log(chalk.gray(` 💡 Hafızada ${n} olası yinelenen/çelişen kayıt — "natureco memory lint" ile gözden geçir.`));
|
|
1254
|
+
} catch {}
|
|
1255
|
+
|
|
1246
1256
|
const sessId = saveSession(messages, {
|
|
1247
1257
|
provider: providerUrl, model, user: cfg.userName,
|
|
1248
1258
|
bot: memory.botName, factCount: memory.facts?.length || 0,
|
package/src/tools/memory_tree.js
CHANGED
|
@@ -18,6 +18,7 @@ const fs = require('fs');
|
|
|
18
18
|
const path = require('path');
|
|
19
19
|
const os = require('os');
|
|
20
20
|
const { foldTr } = require('../utils/tr-text');
|
|
21
|
+
const { tokens, jaccard } = require('../utils/memory-lint');
|
|
21
22
|
|
|
22
23
|
const ROOTS = [
|
|
23
24
|
{ id: '1-kisisel', title: 'Kişisel & Tercihler', branches: ['Kimlik', 'Tercihler', 'İletişim Kalıpları'] },
|
|
@@ -138,13 +139,45 @@ function remove(username, root, query) {
|
|
|
138
139
|
return { success: true, removed, root: r.id };
|
|
139
140
|
}
|
|
140
141
|
|
|
142
|
+
// Belirli bir daldaki mevcut yaprakları döndür (yazma-anı hijyen kontrolü için). Türkçe-güvenli dal eşleşmesi.
|
|
143
|
+
function leavesInBranch(txt, branchName) {
|
|
144
|
+
const target = foldTr(branchName).trim();
|
|
145
|
+
const out = [];
|
|
146
|
+
let cur = null;
|
|
147
|
+
for (const line of txt.split('\n')) {
|
|
148
|
+
const h = line.match(/^##\s+(.+?)\s*$/);
|
|
149
|
+
if (h) { cur = foldTr(h[1]).trim(); continue; }
|
|
150
|
+
if (cur === target && /^\s*-\s+\S/.test(line)) out.push(line.trim().replace(/^-\s*/, ''));
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
|
|
141
155
|
function append(username, root, branch, content) {
|
|
142
156
|
ensureTree(username);
|
|
143
157
|
const r = resolveRoot(root);
|
|
144
158
|
const p = rootPath(username, r.id);
|
|
145
159
|
const br = String(branch || 'Genel').trim();
|
|
146
|
-
const
|
|
160
|
+
const cleaned = String(content).replace(/\s+/g, ' ').trim();
|
|
161
|
+
const leaf = '- ' + cleaned;
|
|
147
162
|
let txt = fs.readFileSync(p, 'utf8');
|
|
163
|
+
|
|
164
|
+
// v5.46: yazma-anı hijyen (Urðr lint mantığı, LLM'siz). Aynı dala eklenen yaprağı mevcutlarla
|
|
165
|
+
// Jaccard ile karşılaştır: (a) çok-benzer (≥0.85) → TEKRAR EKLEME (bloat önle, veri kaybı yok
|
|
166
|
+
// çünkü zaten var); (b) aynı konu farklı değer (0.5–0.85) → EKLE ama UYAR (çelişki; hangi
|
|
167
|
+
// değerin doğru olduğuna karar veremeyiz, veriyi kaybetmeyiz → ajan/kullanıcı uzlaştırır).
|
|
168
|
+
let best = { sim: 0, leaf: null };
|
|
169
|
+
try {
|
|
170
|
+
const nt = tokens(cleaned);
|
|
171
|
+
for (const ex of leavesInBranch(txt, br)) {
|
|
172
|
+
const s = jaccard(nt, tokens(ex));
|
|
173
|
+
if (s > best.sim) best = { sim: s, leaf: ex };
|
|
174
|
+
}
|
|
175
|
+
} catch {}
|
|
176
|
+
if (best.sim >= 0.85) {
|
|
177
|
+
return { success: true, deduped: true, root: r.id, branch: br,
|
|
178
|
+
note: `Zaten çok benzer bir kayıt var (%${Math.round(best.sim * 100)}: "${best.leaf}") — tekrar eklenmedi.` };
|
|
179
|
+
}
|
|
180
|
+
|
|
148
181
|
const bRe = new RegExp(`^##[ \\t]+${br.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[ \\t]*$`, 'mi');
|
|
149
182
|
const m = txt.match(bRe);
|
|
150
183
|
if (m) {
|
|
@@ -154,7 +187,11 @@ function append(username, root, branch, content) {
|
|
|
154
187
|
txt = txt.trimEnd() + `\n\n## ${br}\n${leaf}\n`;
|
|
155
188
|
}
|
|
156
189
|
fs.writeFileSync(p, txt, 'utf8');
|
|
157
|
-
|
|
190
|
+
const result = { success: true, root: r.id, branch: br, saved: leaf };
|
|
191
|
+
if (best.sim >= 0.5) {
|
|
192
|
+
result.warning = `Aynı konuda farklı bir kayıt var (%${Math.round(best.sim * 100)}): "${best.leaf}". İkisi de saklandı; doğru olan kalsın, gerekirse memory_tree remove ile eskisini sil.`;
|
|
193
|
+
}
|
|
194
|
+
return result;
|
|
158
195
|
}
|
|
159
196
|
|
|
160
197
|
module.exports = {
|
|
@@ -188,5 +225,5 @@ module.exports = {
|
|
|
188
225
|
return { success: false, error: 'bilinmeyen action: ' + p.action + ' (index|read|search|append|remove)' };
|
|
189
226
|
} catch (e) { return { success: false, error: e.message }; }
|
|
190
227
|
},
|
|
191
|
-
_internal: { ensureTree, buildIndex, buildDigest, readRoot, search, append, getPending, remove, treeDir, rootPath, ROOTS },
|
|
228
|
+
_internal: { ensureTree, buildIndex, buildDigest, readRoot, search, append, getPending, remove, leavesInBranch, treeDir, rootPath, ROOTS },
|
|
192
229
|
};
|