natureco-cli 5.6.16 → 5.6.18
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/bin/natureco.js +1085 -1084
- package/package.json +1 -1
- package/src/commands/memory-cmd.js +73 -3
- package/src/commands/uninstall.js +7 -2
- package/src/utils/memory-store.js +185 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natureco-cli",
|
|
3
|
-
"version": "5.6.
|
|
3
|
+
"version": "5.6.18",
|
|
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"
|
|
@@ -2,6 +2,7 @@ const chalk = require('chalk');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
|
+
const memoryStore = require('../utils/memory-store');
|
|
5
6
|
const { loadMemory, saveMemory, clearMemory } = require('../utils/memory');
|
|
6
7
|
const { getConfig } = require('../utils/config');
|
|
7
8
|
|
|
@@ -213,7 +214,7 @@ function indexMemory() {
|
|
|
213
214
|
// ── Export Memory ──────────────────────────────────────────────────────────────
|
|
214
215
|
function exportMemoryCmd(botId, outputFile) {
|
|
215
216
|
const id = botId || 'universal-provider';
|
|
216
|
-
const mem =
|
|
217
|
+
const mem = memoryStore.loadMemory(id);
|
|
217
218
|
const filePath = outputFile || path.join(process.cwd(), `memory-${id}.json`);
|
|
218
219
|
fs.writeFileSync(filePath, JSON.stringify(mem, null, 2));
|
|
219
220
|
console.log(chalk.green(`\n ✓ Hafıza dışa aktarıldı: ${filePath}\n`));
|
|
@@ -233,8 +234,11 @@ function importMemoryCmd(botId, sourceFile) {
|
|
|
233
234
|
}
|
|
234
235
|
try {
|
|
235
236
|
const data = JSON.parse(fs.readFileSync(resolvedPath, 'utf-8'));
|
|
236
|
-
|
|
237
|
-
|
|
237
|
+
// v5.6.16: memoryStore.saveMemory kullan
|
|
238
|
+
const importId = botId || 'universal-provider';
|
|
239
|
+
memoryStore.saveMemory(importId, data);
|
|
240
|
+
console.log(chalk.green(`\n ✓ Hafıza içe aktarıldı: ${importId}\n`));
|
|
241
|
+
console.log(chalk.green(`\n ✓ Hafıza içe aktarıldı: ${id}\n`));
|
|
238
242
|
} catch (err) {
|
|
239
243
|
console.log(chalk.red(`\n ❌ Hata: ${err.message}\n`));
|
|
240
244
|
}
|
|
@@ -335,4 +339,70 @@ function wikiSearchCmd(query) {
|
|
|
335
339
|
});
|
|
336
340
|
}
|
|
337
341
|
|
|
342
|
+
// ── Wiki Page Functions (v5.6.16 inline) ─────────────────────────────
|
|
343
|
+
function listWikiPages() {
|
|
344
|
+
const WIKI_DIR = path.join(os.homedir(), '.natureco', 'wiki');
|
|
345
|
+
if (!fs.existsSync(WIKI_DIR)) {
|
|
346
|
+
console.log(chalk.gray('\n Wiki bos.\n'));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const files = fs.readdirSync(WIKI_DIR).filter(f => f.endsWith('.md'));
|
|
350
|
+
console.log(chalk.cyan(`\n Wiki Sayfalari (${files.length}):\n`));
|
|
351
|
+
files.forEach(f => console.log(` ${chalk.white(f.replace('.md',''))}`));
|
|
352
|
+
console.log();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function getWikiPage(slug) {
|
|
356
|
+
if (!slug) return;
|
|
357
|
+
const WIKI_DIR = path.join(os.homedir(), '.natureco', 'wiki');
|
|
358
|
+
const filePath = path.join(WIKI_DIR, `${slug}.md`);
|
|
359
|
+
if (!fs.existsSync(filePath)) {
|
|
360
|
+
console.log(chalk.red(`\n ❌ Wiki sayfasi bulunamadi: ${slug}\n`));
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
console.log(chalk.cyan(`\n ${slug}\n`));
|
|
364
|
+
console.log(chalk.gray(' ' + '─'.repeat(60)));
|
|
365
|
+
console.log(fs.readFileSync(filePath, 'utf-8'));
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function saveWikiPage(slug, content) {
|
|
369
|
+
if (!slug) return;
|
|
370
|
+
const WIKI_DIR = path.join(os.homedir(), '.natureco', 'wiki');
|
|
371
|
+
if (!fs.existsSync(WIKI_DIR)) fs.mkdirSync(WIKI_DIR, { recursive: true });
|
|
372
|
+
const filePath = path.join(WIKI_DIR, `${slug}.md`);
|
|
373
|
+
fs.writeFileSync(filePath, content);
|
|
374
|
+
console.log(chalk.green(`\n ✓ Wiki sayfasi kaydedildi: ${slug}\n`));
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function searchWikiPages(query) {
|
|
378
|
+
if (!query) return [];
|
|
379
|
+
const WIKI_DIR = path.join(os.homedir(), '.natureco', 'wiki');
|
|
380
|
+
if (!fs.existsSync(WIKI_DIR)) return [];
|
|
381
|
+
const lower = query.toLowerCase();
|
|
382
|
+
return fs.readdirSync(WIKI_DIR)
|
|
383
|
+
.filter(f => f.endsWith('.md'))
|
|
384
|
+
.map(f => ({
|
|
385
|
+
slug: f.replace('.md', ''),
|
|
386
|
+
content: fs.readFileSync(path.join(WIKI_DIR, f), 'utf-8'),
|
|
387
|
+
}))
|
|
388
|
+
.filter(p => p.content.toLowerCase().includes(lower));
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// ── Semantic Search (v5.6.16 inline - basit keyword-based) ───────────
|
|
392
|
+
function semanticSearchMemory(query, botId) {
|
|
393
|
+
const id = botId || 'universal-provider';
|
|
394
|
+
const mem = memoryStore.loadMemory(id);
|
|
395
|
+
if (!query) return [];
|
|
396
|
+
const lower = query.toLowerCase();
|
|
397
|
+
const results = [];
|
|
398
|
+
// facts icinde ara
|
|
399
|
+
(mem.facts || []).forEach(f => {
|
|
400
|
+
const text = (typeof f === 'string' ? f : f.value) || '';
|
|
401
|
+
if (text.toLowerCase().includes(lower)) {
|
|
402
|
+
results.push({ type: 'fact', value: text, score: f.score || 5 });
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
return results;
|
|
406
|
+
}
|
|
407
|
+
|
|
338
408
|
module.exports = memoryCmd;
|
|
@@ -4,6 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const { execSync } = require('child_process');
|
|
6
6
|
const readline = require('readline');
|
|
7
|
+
const { requireApproval, RISK } = require('../utils/dangerous');
|
|
7
8
|
|
|
8
9
|
const BASE_DIR = path.join(os.homedir(), '.natureco');
|
|
9
10
|
|
|
@@ -46,12 +47,16 @@ function cmdDryRun() {
|
|
|
46
47
|
async function cmdRun() {
|
|
47
48
|
console.log(chalk.cyan('\n Uninstall NatureCo\n'));
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
// v5.6.16: Dangerous approval (CRITICAL)
|
|
51
|
+
const approved = await requireApproval('natureco uninstall', {}, RISK.CRITICAL,
|
|
52
|
+
'NatureCo CLI ve tum kisisel veriler silinecek (geri alinamaz)');
|
|
53
|
+
if (!approved) {
|
|
51
54
|
console.log(chalk.gray('\n Cancelled.\n'));
|
|
52
55
|
return;
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
// Eski onay mekanizmasini kaldirdik, dangerous approval yeterli
|
|
59
|
+
|
|
55
60
|
if (fs.existsSync(BASE_DIR)) {
|
|
56
61
|
console.log(chalk.gray(' Removing ~/.natureco/...'));
|
|
57
62
|
fs.rmSync(BASE_DIR, { recursive: true, force: true });
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memory_write - Memory'ye fact/kayit yaz (v5.1.1)
|
|
3
|
+
*
|
|
4
|
+
* REPL'in extractMemoryFromMessage ozelligini tool olarak expose eder.
|
|
5
|
+
* Parton'un vizyonu: "Benim asistanim, her seyimi hatirlayacak"
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const os = require("os");
|
|
11
|
+
|
|
12
|
+
const MEMORY_DIR = path.join(os.homedir(), ".natureco", "memory");
|
|
13
|
+
|
|
14
|
+
function getMemoryFile(username) {
|
|
15
|
+
const name = (username || "default").toLowerCase();
|
|
16
|
+
return path.join(MEMORY_DIR, `${name}.json`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function loadMemory(username) {
|
|
20
|
+
const file = getMemoryFile(username);
|
|
21
|
+
try {
|
|
22
|
+
if (!fs.existsSync(file)) {
|
|
23
|
+
return { name: username || "User", nickname: null, botName: null, facts: [], preferences: [] };
|
|
24
|
+
}
|
|
25
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
26
|
+
} catch {
|
|
27
|
+
return { name: username || "User", nickname: null, botName: null, facts: [], preferences: [] };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function saveMemory(username, memory) {
|
|
32
|
+
if (!fs.existsSync(MEMORY_DIR)) fs.mkdirSync(MEMORY_DIR, { recursive: true });
|
|
33
|
+
memory.lastUpdated = new Date().toISOString();
|
|
34
|
+
fs.writeFileSync(getMemoryFile(username), JSON.stringify(memory, null, 2), "utf8");
|
|
35
|
+
return memory;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Score azalt (eski fact'ler zamanla unutuluyor)
|
|
40
|
+
*/
|
|
41
|
+
function decayFacts(memory) {
|
|
42
|
+
if (!memory.facts) return memory;
|
|
43
|
+
const now = Date.now();
|
|
44
|
+
memory.facts = memory.facts.map(f => {
|
|
45
|
+
if (!f.score) f.score = 5;
|
|
46
|
+
// 1 haftadan eski -1, 1 aydan eski -3
|
|
47
|
+
const ageMs = now - new Date(f.updatedAt || f.createdAt || now).getTime();
|
|
48
|
+
const ageDays = ageMs / (1000 * 60 * 60 * 24);
|
|
49
|
+
if (ageDays > 30) f.score = Math.max(0, f.score - 3);
|
|
50
|
+
else if (ageDays > 7) f.score = Math.max(0, f.score - 1);
|
|
51
|
+
return f;
|
|
52
|
+
});
|
|
53
|
+
// score 0 olanlari sil
|
|
54
|
+
memory.facts = memory.facts.filter(f => (f.score || 0) > 0);
|
|
55
|
+
// max 15 fact tut
|
|
56
|
+
memory.facts.sort((a, b) => (b.score || 0) - (a.score || 0));
|
|
57
|
+
memory.facts = memory.facts.slice(0, 15);
|
|
58
|
+
return memory;
|
|
59
|
+
}
|
|
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
|
+
|
|
94
|
+
function addMemory({ username, fact, score = 5, category = "general", botName, nickname, name }) {
|
|
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
|
+
}
|
|
101
|
+
|
|
102
|
+
let memory = loadMemory(effectiveUsername);
|
|
103
|
+
memory = decayFacts(memory);
|
|
104
|
+
|
|
105
|
+
// identity updates (botName, nickname, name) — name sadece memory.name, username degil
|
|
106
|
+
if (botName) memory.botName = botName;
|
|
107
|
+
if (nickname !== undefined) memory.nickname = nickname;
|
|
108
|
+
if (name) memory.name = name; // Bu memory.name (kullanici gercek adi), username degil
|
|
109
|
+
|
|
110
|
+
if (fact) {
|
|
111
|
+
// duplicate kontrol
|
|
112
|
+
const existing = memory.facts.find(f => (f.value || f).toLowerCase() === fact.toLowerCase());
|
|
113
|
+
if (existing) {
|
|
114
|
+
existing.score = Math.min(10, (existing.score || 5) + 2);
|
|
115
|
+
existing.updatedAt = new Date().toISOString();
|
|
116
|
+
} else {
|
|
117
|
+
memory.facts.push({
|
|
118
|
+
value: fact,
|
|
119
|
+
score,
|
|
120
|
+
category,
|
|
121
|
+
updatedAt: new Date().toISOString(),
|
|
122
|
+
createdAt: new Date().toISOString(),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!memory.preferences) memory.preferences = [];
|
|
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
|
+
}
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
success: true,
|
|
142
|
+
message: "Memory guncellendi ve dogrulandi",
|
|
143
|
+
username: effectiveUsername,
|
|
144
|
+
verified: true,
|
|
145
|
+
totalFacts: memory.facts.length,
|
|
146
|
+
facts: memory.facts.map(f => ({ value: f.value, score: f.score, category: f.category })),
|
|
147
|
+
botName: memory.botName,
|
|
148
|
+
nickname: memory.nickname,
|
|
149
|
+
name: memory.name,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function clearMemory({ username }) {
|
|
154
|
+
if (!username) return { success: false, error: "username gerekli" };
|
|
155
|
+
const file = getMemoryFile(username);
|
|
156
|
+
if (fs.existsSync(file)) fs.unlinkSync(file);
|
|
157
|
+
return { success: true, message: `Memory temizlendi: ${username}` };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function showMemory({ username }) {
|
|
161
|
+
if (!username) return { success: false, error: "username gerekli" };
|
|
162
|
+
const memory = loadMemory(username);
|
|
163
|
+
return {
|
|
164
|
+
success: true,
|
|
165
|
+
username,
|
|
166
|
+
name: memory.name,
|
|
167
|
+
nickname: memory.nickname,
|
|
168
|
+
botName: memory.botName,
|
|
169
|
+
totalFacts: (memory.facts || []).length,
|
|
170
|
+
facts: memory.facts || [],
|
|
171
|
+
preferences: memory.preferences || [],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
module.exports = {
|
|
177
|
+
getMemoryFile,
|
|
178
|
+
loadMemory,
|
|
179
|
+
saveMemory,
|
|
180
|
+
decayFacts,
|
|
181
|
+
verifyMemoryWrite,
|
|
182
|
+
addMemory,
|
|
183
|
+
clearMemory,
|
|
184
|
+
showMemory,
|
|
185
|
+
};
|