natureco-cli 5.6.14 → 5.6.16

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.6.14",
3
+ "version": "5.6.16",
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"
@@ -1,338 +1,338 @@
1
- const chalk = require('chalk');
2
- const fs = require('fs');
3
- const path = require('path');
4
- const os = require('os');
5
- const { loadMemory, saveMemory, clearMemory } = require('../utils/memory');
6
- const { getConfig } = require('../utils/config');
7
-
8
- const MEMORY_DIR = path.join(os.homedir(), '.natureco', 'memory');
9
-
10
- async function memoryCmd(args) {
11
- const [action, ...params] = (args || []);
12
-
13
- if (!action || action === 'status') return statusMemory();
14
- if (action === 'list') return listMemory();
15
- if (action === 'search') return searchMemory(params.join(' '));
16
- if (action === 'show') return showMemory(params[0]);
17
- if (action === 'clear') return clearMemoryCmd(params[0]);
18
- if (action === 'index') return indexMemory();
19
- if (action === 'export') return exportMemoryCmd(params[0], params[1]);
20
- if (action === 'import') return importMemoryCmd(params[0], params[1]);
21
- if (action === 'semantic') return semanticSearchCmd(params.join(' '));
22
- // Wiki pages
23
- if (action === 'wiki') return wikiCmd(params[0], params.slice(1));
24
- if (action === 'wiki-create') return wikiCreateCmd(params[0], params.slice(1).join(' '));
25
- if (action === 'wiki-list') return wikiListCmd();
26
- if (action === 'wiki-search') return wikiSearchCmd(params.join(' '));
27
-
28
- console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
29
- console.log(chalk.gray(' Kullanım: natureco memory [status|list|search|show|clear|index|export|import|semantic|wiki|wiki-create|wiki-list|wiki-search]\n'));
30
- process.exit(1);
31
- }
32
-
33
- function statusMemory() {
34
- const config = getConfig();
35
- const w = process.stdout.columns || 120;
36
- const line = chalk.gray('─'.repeat(w));
37
-
38
- console.log('');
39
- console.log(line);
40
- console.log(chalk.bold.cyan(' Hafıza Durumu'));
41
- console.log(line);
42
-
43
- if (!fs.existsSync(MEMORY_DIR)) {
44
- console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
45
- console.log(line);
46
- return;
47
- }
48
-
49
- const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
50
-
51
- if (files.length === 0) {
52
- console.log(chalk.gray('\n Kayıtlı hafıza yok.\n'));
53
- console.log(line);
54
- return;
55
- }
56
-
57
- let totalFacts = 0;
58
- const activeBotName = config.botName || '';
59
-
60
- console.log('');
61
- files.forEach(file => {
62
- const botId = file.replace('.json', '');
63
- try {
64
- const mem = loadMemory(botId);
65
- const factCount = (mem.facts || []).length;
66
- const prefCount = (mem.preferences || []).length;
67
- totalFacts += factCount;
68
- const isActive = activeBotName && (mem.botName === activeBotName);
69
- const bar = isActive ? chalk.cyan('▌') : chalk.gray('▌');
70
-
71
- console.log(bar + ' ' + chalk.bold.white(mem.botName || botId) + (isActive ? chalk.cyan(' ← aktif') : ''));
72
- console.log(bar + ' ' + chalk.gray('Kullanıcı : ') + chalk.white(mem.name || '—'));
73
- if (mem.nickname) {
74
- console.log(bar + ' ' + chalk.gray('Lakap : ') + chalk.white(mem.nickname));
75
- }
76
- console.log(bar + ' ' + chalk.gray('Bilgi : ') + chalk.white(`${factCount} kayıt`));
77
- console.log(bar + ' ' + chalk.gray('Tercihler : ') + chalk.white(`${prefCount} kayıt`));
78
- if (mem.lastSeen) {
79
- const d = new Date(mem.lastSeen);
80
- console.log(bar + ' ' + chalk.gray('Son görüş : ') + chalk.white(d.toLocaleDateString('tr-TR')));
81
- }
82
- console.log('');
83
- } catch {}
84
- });
85
-
86
- console.log(line);
87
- console.log(chalk.gray(` ${files.length} bot · ${totalFacts} toplam bilgi · natureco memory search <sorgu>`));
88
- console.log(line);
89
- console.log('');
90
- }
91
-
92
- function listMemory() {
93
- if (!fs.existsSync(MEMORY_DIR)) {
94
- console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
95
- return;
96
- }
97
-
98
- const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
99
- console.log(chalk.cyan.bold(`\n Hafıza Dosyaları (${files.length})\n`));
100
- files.forEach(f => {
101
- const botId = f.replace('.json', '');
102
- const mem = loadMemory(botId);
103
- console.log(chalk.white(` ${f}`));
104
- console.log(chalk.gray(` Bot: ${mem.botName || botId} · ${(mem.facts || []).length} bilgi`));
105
- });
106
- console.log('');
107
- }
108
-
109
- function searchMemory(query) {
110
- if (!query) {
111
- console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n'));
112
- console.log(chalk.gray(' Kullanım: natureco memory search <sorgu>\n'));
113
- process.exit(1);
114
- }
115
-
116
- if (!fs.existsSync(MEMORY_DIR)) {
117
- console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
118
- return;
119
- }
120
-
121
- const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
122
- const results = [];
123
-
124
- files.forEach(file => {
125
- const botId = file.replace('.json', '');
126
- const mem = loadMemory(botId);
127
- const q = query.toLowerCase();
128
-
129
- if (mem.name?.toLowerCase().includes(q)) {
130
- results.push({ bot: mem.botName || botId, field: 'İsim', value: mem.name });
131
- }
132
- if (mem.nickname?.toLowerCase().includes(q)) {
133
- results.push({ bot: mem.botName || botId, field: 'Lakap', value: mem.nickname });
134
- }
135
- (mem.facts || []).forEach(f => {
136
- const val = typeof f === 'string' ? f : f.value;
137
- if (val?.toLowerCase().includes(q)) {
138
- results.push({ bot: mem.botName || botId, field: 'Bilgi', value: val });
139
- }
140
- });
141
- });
142
-
143
- console.log(chalk.cyan.bold(`\n "${query}" için ${results.length} sonuç\n`));
144
- if (results.length === 0) {
145
- console.log(chalk.gray(' Sonuç bulunamadı.\n'));
146
- return;
147
- }
148
- results.forEach(r => {
149
- console.log(chalk.white(` [${r.bot}] `) + chalk.gray(`${r.field}: `) + chalk.white(r.value));
150
- });
151
- console.log('');
152
- }
153
-
154
- function showMemory(botId) {
155
- const config = getConfig();
156
- const id = botId || 'universal-provider';
157
- const mem = loadMemory(id);
158
-
159
- console.log('');
160
- console.log(chalk.gray(' ' + '─'.repeat(48)));
161
- console.log(chalk.cyan.bold(`\n Hafıza: ${mem.botName || id}\n`));
162
-
163
- if (mem.name) console.log(chalk.gray(' İsim : ') + chalk.white(mem.name));
164
- if (mem.nickname) console.log(chalk.gray(' Lakap : ') + chalk.white(mem.nickname));
165
- if (mem.botName) console.log(chalk.gray(' Bot adı : ') + chalk.cyan(mem.botName));
166
-
167
- const facts = mem.facts || [];
168
- if (facts.length > 0) {
169
- console.log(chalk.gray('\n Bilgiler:\n'));
170
- facts.forEach((f, i) => {
171
- const val = typeof f === 'string' ? f : f.value;
172
- const score = typeof f === 'object' ? f.score : 5;
173
- console.log(chalk.gray(` ${(i + 1).toString().padStart(2)}. `) + chalk.white(val) + chalk.gray(` (${score})`));
174
- });
175
- }
176
- console.log('');
177
- }
178
-
179
- function clearMemoryCmd(botId) {
180
- const id = botId || 'universal-provider';
181
- clearMemory(id);
182
- console.log(chalk.green(`\n ✓ Hafıza temizlendi: ${id}\n`));
183
- }
184
-
185
- function indexMemory() {
186
- if (!fs.existsSync(MEMORY_DIR)) {
187
- console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
188
- return;
189
- }
190
-
191
- const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
192
- let indexed = 0;
193
-
194
- files.forEach(file => {
195
- const botId = file.replace('.json', '');
196
- try {
197
- const mem = loadMemory(botId);
198
- // Bozuk fact'leri temizle
199
- if (Array.isArray(mem.facts)) {
200
- mem.facts = mem.facts.filter(f => {
201
- const val = typeof f === 'string' ? f : f?.value;
202
- return val && typeof val === 'string' && val.length > 0;
203
- });
204
- saveMemory(botId, mem);
205
- indexed++;
206
- }
207
- } catch {}
208
- });
209
-
210
- console.log(chalk.green(`\n ✓ ${indexed} hafıza dosyası yeniden indexlendi\n`));
211
- }
212
-
213
- // ── Export Memory ──────────────────────────────────────────────────────────────
214
- function exportMemoryCmd(botId, outputFile) {
215
- const id = botId || 'universal-provider';
216
- const mem = exportMemory(id);
217
- const filePath = outputFile || path.join(process.cwd(), `memory-${id}.json`);
218
- fs.writeFileSync(filePath, JSON.stringify(mem, null, 2));
219
- console.log(chalk.green(`\n ✓ Hafıza dışa aktarıldı: ${filePath}\n`));
220
- }
221
-
222
- // ── Import Memory ──────────────────────────────────────────────────────────────
223
- function importMemoryCmd(botId, sourceFile) {
224
- if (!sourceFile) {
225
- console.log(chalk.red('\n ❌ Kaynak dosya gerekli\n'));
226
- console.log(chalk.gray(' Kullanım: natureco memory import <botId> <dosya.json>\n'));
227
- return;
228
- }
229
- const resolvedPath = path.resolve(sourceFile.replace(/^~/, os.homedir()));
230
- if (!fs.existsSync(resolvedPath)) {
231
- console.log(chalk.red(`\n ❌ Dosya bulunamadı: ${resolvedPath}\n`));
232
- return;
233
- }
234
- try {
235
- const data = JSON.parse(fs.readFileSync(resolvedPath, 'utf-8'));
236
- importMemory(botId || 'universal-provider', data);
237
- console.log(chalk.green(`\n ✓ Hafıza içe aktarıldı: ${botId || 'universal-provider'}\n`));
238
- } catch (err) {
239
- console.log(chalk.red(`\n ❌ Hata: ${err.message}\n`));
240
- }
241
- }
242
-
243
- // ── Semantic Search ────────────────────────────────────────────────────────────
244
- function semanticSearchCmd(query) {
245
- if (!query) {
246
- console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n'));
247
- return;
248
- }
249
- const results = semanticSearchMemory(query, 10);
250
- console.log(chalk.cyan.bold(`\n Semantic: "${query}" → ${results.length} sonuç\n`));
251
- if (results.length === 0) {
252
- console.log(chalk.gray(' Sonuç bulunamadı.\n'));
253
- return;
254
- }
255
- results.forEach((r, i) => {
256
- const pct = Math.round(r.score * 100);
257
- const bar = chalk.green('█'.repeat(Math.floor(pct / 10))) + chalk.gray('░'.repeat(10 - Math.floor(pct / 10)));
258
- console.log(` ${chalk.white(`${i + 1}.`)} ${bar} ${chalk.white(r.value.slice(0, 70))}`);
259
- console.log(chalk.gray(` [${r.bot}] alaka: %${pct}`));
260
- });
261
- console.log('');
262
- }
263
-
264
- // ── Wiki Commands ──────────────────────────────────────────────────────────────
265
- function wikiCmd(action, params) {
266
- if (!action || action === 'list') return wikiListCmd();
267
- if (action === 'show') {
268
- const slug = params?.[0];
269
- if (!slug) { console.log(chalk.red('\n ❌ Sayfa adı gerekli\n')); return; }
270
- const page = getWikiPage(slug);
271
- if (!page) { console.log(chalk.yellow(`\n ⚠ Sayfa bulunamadı: ${slug}\n`)); return; }
272
- console.log(chalk.cyan.bold(`\n Wiki: ${page.slug}\n`));
273
- console.log(chalk.white(page.content));
274
- console.log(chalk.gray(`\n Son güncelleme: ${page.updatedAt}\n`));
275
- return;
276
- }
277
- if (action === 'create' || action === 'edit') {
278
- const slug = params?.[0];
279
- const content = params?.slice(1).join(' ');
280
- if (!slug || !content) {
281
- console.log(chalk.red('\n ❌ Kullanım: natureco memory wiki create <slug> <içerik>\n'));
282
- return;
283
- }
284
- saveWikiPage(slug, content);
285
- console.log(chalk.green(`\n ✓ Wiki sayfası kaydedildi: ${slug}\n`));
286
- return;
287
- }
288
- if (action === 'search') {
289
- const query = params?.join(' ');
290
- if (!query) { console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n')); return; }
291
- const results = searchWikiPages(query);
292
- console.log(chalk.cyan.bold(`\n Wiki: "${query}" → ${results.length} sonuç\n`));
293
- if (results.length === 0) { console.log(chalk.gray(' Sonuç bulunamadı.\n')); return; }
294
- results.forEach(p => {
295
- console.log(` ${chalk.white(p.slug)} ${chalk.gray('—')} ${chalk.gray((p.content || '').slice(0, 60))}`);
296
- });
297
- console.log('');
298
- return;
299
- }
300
- console.log(chalk.red(`\n ❌ Bilinmeyen wiki aksiyonu: ${action}\n`));
301
- }
302
-
303
- function wikiCreateCmd(slug, content) {
304
- if (!slug || !content) {
305
- console.log(chalk.red('\n ❌ Kullanım: natureco memory wiki-create <slug> <içerik>\n'));
306
- return;
307
- }
308
- saveWikiPage(slug, content);
309
- console.log(chalk.green(`\n ✓ Wiki sayfası oluşturuldu: ${slug}\n`));
310
- }
311
-
312
- function wikiListCmd() {
313
- const pages = listWikiPages();
314
- console.log(chalk.cyan.bold(`\n Wiki Sayfaları (${pages.length})\n`));
315
- if (pages.length === 0) {
316
- console.log(chalk.gray(' Henüz sayfa yok.\n'));
317
- console.log(chalk.gray(' Oluşturmak: ') + chalk.cyan('natureco memory wiki create <slug> <içerik>\n'));
318
- return;
319
- }
320
- pages.forEach(p => {
321
- const preview = (p.content || '').slice(0, 60).replace(/\n/g, ' ');
322
- console.log(` ${chalk.white(p.slug)} ${chalk.gray('—')} ${chalk.gray(preview)}`);
323
- console.log(chalk.gray(` ${p.updatedAt}\n`));
324
- });
325
- }
326
-
327
- function wikiSearchCmd(query) {
328
- if (!query) { console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n')); return; }
329
- const results = searchWikiPages(query);
330
- console.log(chalk.cyan.bold(`\n Wiki Ara: "${query}" → ${results.length} sonuç\n`));
331
- if (results.length === 0) { console.log(chalk.gray(' Sonuç bulunamadı.\n')); return; }
332
- results.forEach(p => {
333
- console.log(` ${chalk.white(p.slug)}`);
334
- console.log(chalk.gray(` ${(p.content || '').slice(0, 80)}\n`));
335
- });
336
- }
337
-
338
- module.exports = memoryCmd;
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+ const { loadMemory, saveMemory, clearMemory } = require('../utils/memory');
6
+ const { getConfig } = require('../utils/config');
7
+
8
+ const MEMORY_DIR = path.join(os.homedir(), '.natureco', 'memory');
9
+
10
+ async function memoryCmd(args) {
11
+ const [action, ...params] = (args || []);
12
+
13
+ if (!action || action === 'status') return statusMemory();
14
+ if (action === 'list') return listMemory();
15
+ if (action === 'search') return searchMemory(params.join(' '));
16
+ if (action === 'show') return showMemory(params[0]);
17
+ if (action === 'clear') return clearMemoryCmd(params[0]);
18
+ if (action === 'index') return indexMemory();
19
+ if (action === 'export') return exportMemoryCmd(params[0], params[1]);
20
+ if (action === 'import') return importMemoryCmd(params[0], params[1]);
21
+ if (action === 'semantic') return semanticSearchCmd(params.join(' '));
22
+ // Wiki pages
23
+ if (action === 'wiki') return wikiCmd(params[0], params.slice(1));
24
+ if (action === 'wiki-create') return wikiCreateCmd(params[0], params.slice(1).join(' '));
25
+ if (action === 'wiki-list') return wikiListCmd();
26
+ if (action === 'wiki-search') return wikiSearchCmd(params.join(' '));
27
+
28
+ console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
29
+ console.log(chalk.gray(' Kullanım: natureco memory [status|list|search|show|clear|index|export|import|semantic|wiki|wiki-create|wiki-list|wiki-search]\n'));
30
+ process.exit(1);
31
+ }
32
+
33
+ function statusMemory() {
34
+ const config = getConfig();
35
+ const w = process.stdout.columns || 120;
36
+ const line = chalk.gray('─'.repeat(w));
37
+
38
+ console.log('');
39
+ console.log(line);
40
+ console.log(chalk.bold.cyan(' Hafıza Durumu'));
41
+ console.log(line);
42
+
43
+ if (!fs.existsSync(MEMORY_DIR)) {
44
+ console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
45
+ console.log(line);
46
+ return;
47
+ }
48
+
49
+ const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
50
+
51
+ if (files.length === 0) {
52
+ console.log(chalk.gray('\n Kayıtlı hafıza yok.\n'));
53
+ console.log(line);
54
+ return;
55
+ }
56
+
57
+ let totalFacts = 0;
58
+ const activeBotName = config.botName || '';
59
+
60
+ console.log('');
61
+ files.forEach(file => {
62
+ const botId = file.replace('.json', '');
63
+ try {
64
+ const mem = loadMemory(botId);
65
+ const factCount = (mem.facts || []).length;
66
+ const prefCount = (mem.preferences || []).length;
67
+ totalFacts += factCount;
68
+ const isActive = activeBotName && (mem.botName === activeBotName);
69
+ const bar = isActive ? chalk.cyan('▌') : chalk.gray('▌');
70
+
71
+ console.log(bar + ' ' + chalk.bold.white(mem.botName || botId) + (isActive ? chalk.cyan(' ← aktif') : ''));
72
+ console.log(bar + ' ' + chalk.gray('Kullanıcı : ') + chalk.white(mem.name || '—'));
73
+ if (mem.nickname) {
74
+ console.log(bar + ' ' + chalk.gray('Lakap : ') + chalk.white(mem.nickname));
75
+ }
76
+ console.log(bar + ' ' + chalk.gray('Bilgi : ') + chalk.white(`${factCount} kayıt`));
77
+ console.log(bar + ' ' + chalk.gray('Tercihler : ') + chalk.white(`${prefCount} kayıt`));
78
+ if (mem.lastSeen) {
79
+ const d = new Date(mem.lastSeen);
80
+ console.log(bar + ' ' + chalk.gray('Son görüş : ') + chalk.white(d.toLocaleDateString('tr-TR')));
81
+ }
82
+ console.log('');
83
+ } catch {}
84
+ });
85
+
86
+ console.log(line);
87
+ console.log(chalk.gray(` ${files.length} bot · ${totalFacts} toplam bilgi · natureco memory search <sorgu>`));
88
+ console.log(line);
89
+ console.log('');
90
+ }
91
+
92
+ function listMemory() {
93
+ if (!fs.existsSync(MEMORY_DIR)) {
94
+ console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
95
+ return;
96
+ }
97
+
98
+ const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
99
+ console.log(chalk.cyan.bold(`\n Hafıza Dosyaları (${files.length})\n`));
100
+ files.forEach(f => {
101
+ const botId = f.replace('.json', '');
102
+ const mem = loadMemory(botId);
103
+ console.log(chalk.white(` ${f}`));
104
+ console.log(chalk.gray(` Bot: ${mem.botName || botId} · ${(mem.facts || []).length} bilgi`));
105
+ });
106
+ console.log('');
107
+ }
108
+
109
+ function searchMemory(query) {
110
+ if (!query) {
111
+ console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n'));
112
+ console.log(chalk.gray(' Kullanım: natureco memory search <sorgu>\n'));
113
+ process.exit(1);
114
+ }
115
+
116
+ if (!fs.existsSync(MEMORY_DIR)) {
117
+ console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
118
+ return;
119
+ }
120
+
121
+ const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
122
+ const results = [];
123
+
124
+ files.forEach(file => {
125
+ const botId = file.replace('.json', '');
126
+ const mem = loadMemory(botId);
127
+ const q = query.toLowerCase();
128
+
129
+ if (mem.name?.toLowerCase().includes(q)) {
130
+ results.push({ bot: mem.botName || botId, field: 'İsim', value: mem.name });
131
+ }
132
+ if (mem.nickname?.toLowerCase().includes(q)) {
133
+ results.push({ bot: mem.botName || botId, field: 'Lakap', value: mem.nickname });
134
+ }
135
+ (mem.facts || []).forEach(f => {
136
+ const val = typeof f === 'string' ? f : f.value;
137
+ if (val?.toLowerCase().includes(q)) {
138
+ results.push({ bot: mem.botName || botId, field: 'Bilgi', value: val });
139
+ }
140
+ });
141
+ });
142
+
143
+ console.log(chalk.cyan.bold(`\n "${query}" için ${results.length} sonuç\n`));
144
+ if (results.length === 0) {
145
+ console.log(chalk.gray(' Sonuç bulunamadı.\n'));
146
+ return;
147
+ }
148
+ results.forEach(r => {
149
+ console.log(chalk.white(` [${r.bot}] `) + chalk.gray(`${r.field}: `) + chalk.white(r.value));
150
+ });
151
+ console.log('');
152
+ }
153
+
154
+ function showMemory(botId) {
155
+ const config = getConfig();
156
+ const id = botId || 'universal-provider';
157
+ const mem = loadMemory(id);
158
+
159
+ console.log('');
160
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
161
+ console.log(chalk.cyan.bold(`\n Hafıza: ${mem.botName || id}\n`));
162
+
163
+ if (mem.name) console.log(chalk.gray(' İsim : ') + chalk.white(mem.name));
164
+ if (mem.nickname) console.log(chalk.gray(' Lakap : ') + chalk.white(mem.nickname));
165
+ if (mem.botName) console.log(chalk.gray(' Bot adı : ') + chalk.cyan(mem.botName));
166
+
167
+ const facts = mem.facts || [];
168
+ if (facts.length > 0) {
169
+ console.log(chalk.gray('\n Bilgiler:\n'));
170
+ facts.forEach((f, i) => {
171
+ const val = typeof f === 'string' ? f : f.value;
172
+ const score = typeof f === 'object' ? f.score : 5;
173
+ console.log(chalk.gray(` ${(i + 1).toString().padStart(2)}. `) + chalk.white(val) + chalk.gray(` (${score})`));
174
+ });
175
+ }
176
+ console.log('');
177
+ }
178
+
179
+ function clearMemoryCmd(botId) {
180
+ const id = botId || 'universal-provider';
181
+ clearMemory(id);
182
+ console.log(chalk.green(`\n ✓ Hafıza temizlendi: ${id}\n`));
183
+ }
184
+
185
+ function indexMemory() {
186
+ if (!fs.existsSync(MEMORY_DIR)) {
187
+ console.log(chalk.gray('\n Hafıza dizini bulunamadı.\n'));
188
+ return;
189
+ }
190
+
191
+ const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
192
+ let indexed = 0;
193
+
194
+ files.forEach(file => {
195
+ const botId = file.replace('.json', '');
196
+ try {
197
+ const mem = loadMemory(botId);
198
+ // Bozuk fact'leri temizle
199
+ if (Array.isArray(mem.facts)) {
200
+ mem.facts = mem.facts.filter(f => {
201
+ const val = typeof f === 'string' ? f : f?.value;
202
+ return val && typeof val === 'string' && val.length > 0;
203
+ });
204
+ saveMemory(botId, mem);
205
+ indexed++;
206
+ }
207
+ } catch {}
208
+ });
209
+
210
+ console.log(chalk.green(`\n ✓ ${indexed} hafıza dosyası yeniden indexlendi\n`));
211
+ }
212
+
213
+ // ── Export Memory ──────────────────────────────────────────────────────────────
214
+ function exportMemoryCmd(botId, outputFile) {
215
+ const id = botId || 'universal-provider';
216
+ const mem = exportMemory(id);
217
+ const filePath = outputFile || path.join(process.cwd(), `memory-${id}.json`);
218
+ fs.writeFileSync(filePath, JSON.stringify(mem, null, 2));
219
+ console.log(chalk.green(`\n ✓ Hafıza dışa aktarıldı: ${filePath}\n`));
220
+ }
221
+
222
+ // ── Import Memory ──────────────────────────────────────────────────────────────
223
+ function importMemoryCmd(botId, sourceFile) {
224
+ if (!sourceFile) {
225
+ console.log(chalk.red('\n ❌ Kaynak dosya gerekli\n'));
226
+ console.log(chalk.gray(' Kullanım: natureco memory import <botId> <dosya.json>\n'));
227
+ return;
228
+ }
229
+ const resolvedPath = path.resolve(sourceFile.replace(/^~/, os.homedir()));
230
+ if (!fs.existsSync(resolvedPath)) {
231
+ console.log(chalk.red(`\n ❌ Dosya bulunamadı: ${resolvedPath}\n`));
232
+ return;
233
+ }
234
+ try {
235
+ const data = JSON.parse(fs.readFileSync(resolvedPath, 'utf-8'));
236
+ importMemory(botId || 'universal-provider', data);
237
+ console.log(chalk.green(`\n ✓ Hafıza içe aktarıldı: ${botId || 'universal-provider'}\n`));
238
+ } catch (err) {
239
+ console.log(chalk.red(`\n ❌ Hata: ${err.message}\n`));
240
+ }
241
+ }
242
+
243
+ // ── Semantic Search ────────────────────────────────────────────────────────────
244
+ function semanticSearchCmd(query) {
245
+ if (!query) {
246
+ console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n'));
247
+ return;
248
+ }
249
+ const results = semanticSearchMemory(query, 10);
250
+ console.log(chalk.cyan.bold(`\n Semantic: "${query}" → ${results.length} sonuç\n`));
251
+ if (results.length === 0) {
252
+ console.log(chalk.gray(' Sonuç bulunamadı.\n'));
253
+ return;
254
+ }
255
+ results.forEach((r, i) => {
256
+ const pct = Math.round(r.score * 100);
257
+ const bar = chalk.green('█'.repeat(Math.floor(pct / 10))) + chalk.gray('░'.repeat(10 - Math.floor(pct / 10)));
258
+ console.log(` ${chalk.white(`${i + 1}.`)} ${bar} ${chalk.white(r.value.slice(0, 70))}`);
259
+ console.log(chalk.gray(` [${r.bot}] alaka: %${pct}`));
260
+ });
261
+ console.log('');
262
+ }
263
+
264
+ // ── Wiki Commands ──────────────────────────────────────────────────────────────
265
+ function wikiCmd(action, params) {
266
+ if (!action || action === 'list') return wikiListCmd();
267
+ if (action === 'show') {
268
+ const slug = params?.[0];
269
+ if (!slug) { console.log(chalk.red('\n ❌ Sayfa adı gerekli\n')); return; }
270
+ const page = getWikiPage(slug);
271
+ if (!page) { console.log(chalk.yellow(`\n ⚠ Sayfa bulunamadı: ${slug}\n`)); return; }
272
+ console.log(chalk.cyan.bold(`\n Wiki: ${page.slug}\n`));
273
+ console.log(chalk.white(page.content));
274
+ console.log(chalk.gray(`\n Son güncelleme: ${page.updatedAt}\n`));
275
+ return;
276
+ }
277
+ if (action === 'create' || action === 'edit') {
278
+ const slug = params?.[0];
279
+ const content = params?.slice(1).join(' ');
280
+ if (!slug || !content) {
281
+ console.log(chalk.red('\n ❌ Kullanım: natureco memory wiki create <slug> <içerik>\n'));
282
+ return;
283
+ }
284
+ saveWikiPage(slug, content);
285
+ console.log(chalk.green(`\n ✓ Wiki sayfası kaydedildi: ${slug}\n`));
286
+ return;
287
+ }
288
+ if (action === 'search') {
289
+ const query = params?.join(' ');
290
+ if (!query) { console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n')); return; }
291
+ const results = searchWikiPages(query);
292
+ console.log(chalk.cyan.bold(`\n Wiki: "${query}" → ${results.length} sonuç\n`));
293
+ if (results.length === 0) { console.log(chalk.gray(' Sonuç bulunamadı.\n')); return; }
294
+ results.forEach(p => {
295
+ console.log(` ${chalk.white(p.slug)} ${chalk.gray('—')} ${chalk.gray((p.content || '').slice(0, 60))}`);
296
+ });
297
+ console.log('');
298
+ return;
299
+ }
300
+ console.log(chalk.red(`\n ❌ Bilinmeyen wiki aksiyonu: ${action}\n`));
301
+ }
302
+
303
+ function wikiCreateCmd(slug, content) {
304
+ if (!slug || !content) {
305
+ console.log(chalk.red('\n ❌ Kullanım: natureco memory wiki-create <slug> <içerik>\n'));
306
+ return;
307
+ }
308
+ saveWikiPage(slug, content);
309
+ console.log(chalk.green(`\n ✓ Wiki sayfası oluşturuldu: ${slug}\n`));
310
+ }
311
+
312
+ function wikiListCmd() {
313
+ const pages = listWikiPages();
314
+ console.log(chalk.cyan.bold(`\n Wiki Sayfaları (${pages.length})\n`));
315
+ if (pages.length === 0) {
316
+ console.log(chalk.gray(' Henüz sayfa yok.\n'));
317
+ console.log(chalk.gray(' Oluşturmak: ') + chalk.cyan('natureco memory wiki create <slug> <içerik>\n'));
318
+ return;
319
+ }
320
+ pages.forEach(p => {
321
+ const preview = (p.content || '').slice(0, 60).replace(/\n/g, ' ');
322
+ console.log(` ${chalk.white(p.slug)} ${chalk.gray('—')} ${chalk.gray(preview)}`);
323
+ console.log(chalk.gray(` ${p.updatedAt}\n`));
324
+ });
325
+ }
326
+
327
+ function wikiSearchCmd(query) {
328
+ if (!query) { console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n')); return; }
329
+ const results = searchWikiPages(query);
330
+ console.log(chalk.cyan.bold(`\n Wiki Ara: "${query}" → ${results.length} sonuç\n`));
331
+ if (results.length === 0) { console.log(chalk.gray(' Sonuç bulunamadı.\n')); return; }
332
+ results.forEach(p => {
333
+ console.log(` ${chalk.white(p.slug)}`);
334
+ console.log(chalk.gray(` ${(p.content || '').slice(0, 80)}\n`));
335
+ });
336
+ }
337
+
338
+ module.exports = memoryCmd;
@@ -17,12 +17,34 @@ const path = require('path');
17
17
  const os = require('os');
18
18
  const inquirer = require('../utils/inquirer-wrapper');
19
19
  const chalk = require('chalk');
20
+ const { requireApproval, RISK } = require('../utils/dangerous');
20
21
 
21
22
  async function reset() {
22
23
  const args = process.argv.slice(3);
23
24
  const home = os.homedir();
24
25
  const baseDir = path.join(home, '.natureco');
25
26
 
27
+ // v5.6.16: Dangerous command approval
28
+ const isFullReset = args.includes('--all') || args.includes('--personal');
29
+ const risk = isFullReset ? RISK.CRITICAL : RISK.HIGH;
30
+ const reason = isFullReset
31
+ ? 'Tum kisisel veriler ve ayarlar silinecek (geri alinamaz)'
32
+ : 'Secili kapsamdaki veriler silinecek';
33
+
34
+ // --yes/-y bypass (eski davranis)
35
+ const skipApproval = args.includes('--yes') || args.includes('-y');
36
+
37
+ if (!skipApproval) {
38
+ const argsObj = {
39
+ flags: args.filter(a => a.startsWith('--') || a.startsWith('-'))
40
+ };
41
+ const approved = await requireApproval('natureco reset', argsObj, risk, reason);
42
+ if (!approved) {
43
+ console.log(chalk.gray('\nIptal edildi.\n'));
44
+ return;
45
+ }
46
+ }
47
+
26
48
  console.log(chalk.yellow('\n\u26a0 RESET - Tum veriler silinecek!\n'));
27
49
 
28
50
  const whatToReset = {
@@ -48,18 +70,7 @@ async function reset() {
48
70
  if (whatToReset.soul) console.log(' - soul/ (generic default doner)');
49
71
  if (whatToReset.personal) console.log(' - personal/');
50
72
 
51
- // Onay
52
- const ans = await inquirer.prompt([{
53
- type: 'confirm',
54
- name: 'confirm',
55
- message: 'Tum verileri silmek istediginize emin misiniz?',
56
- default: false,
57
- }]);
58
-
59
- if (!ans.confirm) {
60
- console.log(chalk.gray('\nIptal edildi.'));
61
- return;
62
- }
73
+
63
74
 
64
75
  // Sil
65
76
  if (whatToReset.config) {
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Dangerous Command Approval (v5.6.16)
3
+ *
4
+ * Hermes Agent'taki "Command required approval" mekanizmasinin
5
+ * NatureCo CLI versiyonu. Riskli komutlari calistirmadan once
6
+ * kullanici onayi alir.
7
+ *
8
+ * Kullanim:
9
+ * const { requireApproval, RISK } = require('../utils/dangerous');
10
+ * if (!await requireApproval('reset', { scope: 'full' }, RISK.CRITICAL)) return;
11
+ */
12
+
13
+ const inquirer = require('../utils/inquirer-wrapper');
14
+ const chalk = require('chalk');
15
+
16
+ const RISK = {
17
+ LOW: 'low', // Otomatik onay
18
+ MEDIUM: 'medium', // Basit onay mesaji
19
+ HIGH: 'high', // Acik onay gerekli
20
+ CRITICAL: 'critical', // Tam yazim onay gerekli
21
+ };
22
+
23
+ const RISK_LABELS = {
24
+ low: { color: 'gray', icon: '⚪', label: 'DUSUK RISK' },
25
+ medium: { color: 'yellow', icon: '🟡', label: 'ORTA RISK' },
26
+ high: { color: 'red', icon: '🔴', label: 'YUKSEK RISK' },
27
+ critical: { color: 'magenta', icon: '⛔', label: 'KRITIK - GERI ALINAMAZ' },
28
+ };
29
+
30
+ const RISK_RANK = { low: 0, medium: 1, high: 2, critical: 3 };
31
+
32
+ /**
33
+ * Komut calistirmadan once risk seviyesi goster, onay iste
34
+ * @param {string} command - komut adi ('reset', 'uninstall', 'memory clear', vs.)
35
+ * @param {object} args - komutun parametreleri
36
+ * @param {string} risk - RISK enum degeri
37
+ * @param {string} reason - neden tehlikeli
38
+ * @returns {Promise<boolean>} - onay verildi mi
39
+ */
40
+ async function requireApproval(command, args = {}, risk = RISK.HIGH, reason = '') {
41
+ // --force veya --yes flag kontrolu (CLI tarafinda eklenir)
42
+ if (process.env.NATURECO_FORCE === '1' || args.force || args.yes) {
43
+ return true;
44
+ }
45
+
46
+ const label = RISK_LABELS[risk] || RISK_LABELS.high;
47
+
48
+ console.log();
49
+ console.log(chalk[label.color](` ${label.icon} ${label.label}: ${command}`));
50
+ console.log(chalk.gray(' ' + '─'.repeat(60)));
51
+ console.log(chalk.white(` Komut: ${command}`));
52
+ if (Object.keys(args).length > 0) {
53
+ console.log(chalk.gray(` Argumanlar: ${JSON.stringify(args)}`));
54
+ }
55
+ if (reason) {
56
+ console.log(chalk[label.color](` Neden: ${reason}`));
57
+ }
58
+ console.log(chalk.gray(' ' + '─'.repeat(60)));
59
+
60
+ // Dusuk risk - otomatik onay, sadece mesaj goster
61
+ if (risk === RISK.LOW) {
62
+ console.log(chalk.gray(' Otomatik onaylandi (dusuk risk)'));
63
+ console.log();
64
+ return true;
65
+ }
66
+
67
+ // Kritik risk - tam yazim gerekli
68
+ if (risk === RISK.CRITICAL) {
69
+ console.log(chalk.red(' Bu islem geri alinamaz!'));
70
+ const { confirm } = await inquirer.prompt([{
71
+ type: 'input',
72
+ name: 'confirm',
73
+ message: chalk.red(' Devam etmek icin "EVET SIL" yazin (veya Enter ile iptal):'),
74
+ validate: (input) => input === 'EVET SIL' || input === ''
75
+ }]);
76
+ console.log();
77
+ return confirm === 'EVET SIL';
78
+ }
79
+
80
+ // Yuksek ve orta risk - basit onay
81
+ const promptType = risk === RISK.HIGH ? 'confirm' : 'confirm';
82
+ const { ok } = await inquirer.prompt([{
83
+ type: promptType,
84
+ name: 'ok',
85
+ message: chalk[label.color](` Bu komutu calistirmak istediginize emin misiniz?`),
86
+ default: false,
87
+ }]);
88
+ console.log();
89
+ return ok;
90
+ }
91
+
92
+ /**
93
+ * Komutun risk seviyesini goster, hizli onay al
94
+ * (sync versiyon, sadece mesaj gosterir)
95
+ */
96
+ function showRisk(command, args = {}, risk = RISK.MEDIUM, reason = '') {
97
+ const label = RISK_LABELS[risk] || RISK_LABELS.medium;
98
+ console.log();
99
+ console.log(chalk[label.color](` ${label.icon} ${label.label}: ${command}`));
100
+ if (reason) console.log(chalk.gray(` ${reason}`));
101
+ console.log();
102
+ }
103
+
104
+ module.exports = {
105
+ RISK,
106
+ RISK_LABELS,
107
+ RISK_RANK,
108
+ requireApproval,
109
+ showRisk,
110
+ };