natureco-cli 2.23.29 → 2.23.30
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/README.md +94 -11
- package/bin/natureco.js +402 -4
- package/package.json +1 -1
- package/src/commands/admin-rpc.js +219 -0
- package/src/commands/agent.js +89 -0
- package/src/commands/approvals.js +53 -0
- package/src/commands/backup.js +124 -0
- package/src/commands/bonjour.js +167 -0
- package/src/commands/capability.js +64 -0
- package/src/commands/clickclack.js +130 -0
- package/src/commands/commitments.js +32 -0
- package/src/commands/completion.js +76 -0
- package/src/commands/configure.js +93 -0
- package/src/commands/crestodian.js +92 -0
- package/src/commands/daemon.js +60 -0
- package/src/commands/device-pair.js +248 -0
- package/src/commands/devices.js +110 -0
- package/src/commands/directory.js +47 -0
- package/src/commands/dns.js +58 -0
- package/src/commands/docs.js +43 -0
- package/src/commands/exec-policy.js +71 -0
- package/src/commands/gateway-server.js +1155 -24
- package/src/commands/health.js +18 -0
- package/src/commands/imessage.js +128 -14
- package/src/commands/infer.js +73 -0
- package/src/commands/irc.js +64 -15
- package/src/commands/mattermost.js +114 -12
- package/src/commands/memory-cmd.js +134 -1
- package/src/commands/message.js +9 -3
- package/src/commands/migrate.js +213 -2
- package/src/commands/node.js +98 -0
- package/src/commands/nodes.js +106 -0
- package/src/commands/oc-path.js +200 -0
- package/src/commands/onboard.js +70 -0
- package/src/commands/open-prose.js +67 -0
- package/src/commands/policy.js +176 -0
- package/src/commands/proxy.js +155 -0
- package/src/commands/qr.js +28 -0
- package/src/commands/sandbox.js +125 -0
- package/src/commands/secrets.js +118 -0
- package/src/commands/setup.js +113 -7
- package/src/commands/signal.js +447 -18
- package/src/commands/sms.js +123 -19
- package/src/commands/system.js +53 -0
- package/src/commands/terminal.js +21 -0
- package/src/commands/thread-ownership.js +157 -0
- package/src/commands/transcripts.js +72 -0
- package/src/commands/voice.js +82 -0
- package/src/commands/vydra.js +98 -0
- package/src/commands/workboard.js +207 -0
- package/src/tools/audio_understanding.js +154 -0
- package/src/tools/browser.js +112 -0
- package/src/tools/canvas.js +104 -0
- package/src/tools/document_extract.js +84 -0
- package/src/tools/duckduckgo.js +54 -0
- package/src/tools/exa_search.js +66 -0
- package/src/tools/firecrawl.js +104 -0
- package/src/tools/image_generation.js +99 -0
- package/src/tools/llm_task.js +118 -0
- package/src/tools/media_understanding.js +128 -0
- package/src/tools/music_generation.js +113 -0
- package/src/tools/parallel_search.js +77 -0
- package/src/tools/phone_control.js +80 -0
- package/src/tools/phone_control_enhanced.js +184 -0
- package/src/tools/searxng.js +61 -0
- package/src/tools/speech_to_text.js +135 -0
- package/src/tools/text_to_speech.js +105 -0
- package/src/tools/thread_ownership.js +88 -0
- package/src/tools/video_generation.js +72 -0
- package/src/tools/web_readability.js +104 -0
- package/src/utils/memory.js +200 -0
|
@@ -16,9 +16,17 @@ async function memoryCmd(args) {
|
|
|
16
16
|
if (action === 'show') return showMemory(params[0]);
|
|
17
17
|
if (action === 'clear') return clearMemoryCmd(params[0]);
|
|
18
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(' '));
|
|
19
27
|
|
|
20
28
|
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
21
|
-
console.log(chalk.gray(' Kullanım: natureco memory [status|list|search|show|clear|index]\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'));
|
|
22
30
|
process.exit(1);
|
|
23
31
|
}
|
|
24
32
|
|
|
@@ -202,4 +210,129 @@ function indexMemory() {
|
|
|
202
210
|
console.log(chalk.green(`\n ✓ ${indexed} hafıza dosyası yeniden indexlendi\n`));
|
|
203
211
|
}
|
|
204
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
|
+
|
|
205
338
|
module.exports = memoryCmd;
|
package/src/commands/message.js
CHANGED
|
@@ -33,8 +33,8 @@ async function message(args) {
|
|
|
33
33
|
process.exit(1);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
if (!['whatsapp', 'telegram', 'signal', 'irc', 'sms'].includes(channel)) {
|
|
37
|
-
console.log(chalk.red('\n❌ Geçersiz kanal. Kullanılabilir: whatsapp, telegram, signal, irc, sms\n'));
|
|
36
|
+
if (!['whatsapp', 'telegram', 'signal', 'irc', 'sms', 'mattermost'].includes(channel)) {
|
|
37
|
+
console.log(chalk.red('\n❌ Geçersiz kanal. Kullanılabilir: whatsapp, telegram, signal, irc, sms, mattermost\n'));
|
|
38
38
|
process.exit(1);
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -87,12 +87,18 @@ async function message(args) {
|
|
|
87
87
|
process.exit(1);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
if (channel === 'mattermost' && (!config.mattermostBotId || !config.mattermostToken)) {
|
|
91
|
+
console.log(chalk.red('\n❌ Mattermost bağlı değil\n'));
|
|
92
|
+
console.log(chalk.yellow('Önce Mattermost\'u bağlayın:'), chalk.cyan('natureco mattermost connect\n'));
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
|
|
90
96
|
// Send message via HTTP endpoint
|
|
91
97
|
await sendMessageViaHttp(channel, target, messageText);
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
async function sendMessageViaHttp(channel, target, messageText) {
|
|
95
|
-
const channelNames = { whatsapp: 'WhatsApp', telegram: 'Telegram', signal: 'Signal', irc: 'IRC', sms: 'SMS' };
|
|
101
|
+
const channelNames = { whatsapp: 'WhatsApp', telegram: 'Telegram', signal: 'Signal', irc: 'IRC', sms: 'SMS', mattermost: 'Mattermost' };
|
|
96
102
|
console.log(chalk.yellow(`\n⏳ ${channelNames[channel] || channel} mesajı gönderiliyor...\n`));
|
|
97
103
|
|
|
98
104
|
try {
|
package/src/commands/migrate.js
CHANGED
|
@@ -35,9 +35,17 @@ function addUniqueFact(facts, newFact) {
|
|
|
35
35
|
async function migrate(options) {
|
|
36
36
|
const from = options.from || 'openclaw';
|
|
37
37
|
|
|
38
|
+
if (from === 'claude-code' || from === 'claude') {
|
|
39
|
+
return migrateClaudeCode();
|
|
40
|
+
}
|
|
41
|
+
if (from === 'hermes') {
|
|
42
|
+
return migrateHermes();
|
|
43
|
+
}
|
|
38
44
|
if (from !== 'openclaw') {
|
|
39
|
-
console.log(chalk.red('\n❌
|
|
40
|
-
console.log(chalk.gray('Kullanım: natureco migrate --from openclaw
|
|
45
|
+
console.log(chalk.red('\n❌ Desteklenen kaynaklar: openclaw, claude-code, hermes\n'));
|
|
46
|
+
console.log(chalk.gray('Kullanım: natureco migrate --from openclaw'));
|
|
47
|
+
console.log(chalk.gray(' natureco migrate --from claude-code'));
|
|
48
|
+
console.log(chalk.gray(' natureco migrate --from hermes\n'));
|
|
41
49
|
return;
|
|
42
50
|
}
|
|
43
51
|
|
|
@@ -623,4 +631,207 @@ function copyDirRecursive(src, dest) {
|
|
|
623
631
|
}
|
|
624
632
|
}
|
|
625
633
|
|
|
634
|
+
// ── Claude Code Migration ──────────────────────────────────────────────────────
|
|
635
|
+
async function migrateClaudeCode() {
|
|
636
|
+
console.log(chalk.yellow('\n⏳ Claude Code → NatureCo migration başlıyor...\n'));
|
|
637
|
+
|
|
638
|
+
const claudeDir = path.join(os.homedir(), '.claude');
|
|
639
|
+
const claudeSettings = path.join(claudeDir, 'settings.json');
|
|
640
|
+
const claudeProjects = path.join(os.homedir(), '.claude', 'projects');
|
|
641
|
+
|
|
642
|
+
if (!fs.existsSync(claudeSettings)) {
|
|
643
|
+
console.log(chalk.yellow('⚠ Claude Code settings bulunamadı: ~/.claude/settings.json\n'));
|
|
644
|
+
} else {
|
|
645
|
+
try {
|
|
646
|
+
const settings = JSON.parse(fs.readFileSync(claudeSettings, 'utf-8'));
|
|
647
|
+
console.log(chalk.gray(' Claude Code ayarları bulundu.\n'));
|
|
648
|
+
|
|
649
|
+
// Migrate allowed tools
|
|
650
|
+
if (settings.allowList?.length > 0) {
|
|
651
|
+
const config = getConfig();
|
|
652
|
+
if (!config.policies) config.policies = {};
|
|
653
|
+
config.policies.claudeAllowedTools = settings.allowList;
|
|
654
|
+
setConfigValue('policies', config.policies);
|
|
655
|
+
console.log(chalk.green(` ✅ ${settings.allowList.length} izinli araç migrate edildi`));
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Migrate permissions
|
|
659
|
+
if (settings.permissions) {
|
|
660
|
+
const config = getConfig();
|
|
661
|
+
config.claudePermissions = settings.permissions;
|
|
662
|
+
setConfigValue('claudePermissions', settings.permissions);
|
|
663
|
+
console.log(chalk.green(' ✅ Claude izinleri migrate edildi'));
|
|
664
|
+
}
|
|
665
|
+
} catch (err) {
|
|
666
|
+
console.log(chalk.red(` ❌ Claude settings okuma hatası: ${err.message}`));
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// Migrate Claude projects
|
|
671
|
+
if (fs.existsSync(claudeProjects)) {
|
|
672
|
+
try {
|
|
673
|
+
const projects = fs.readdirSync(claudeProjects).filter(f => {
|
|
674
|
+
const p = path.join(claudeProjects, f);
|
|
675
|
+
return fs.statSync(p).isDirectory() && !f.startsWith('.');
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
if (projects.length > 0) {
|
|
679
|
+
console.log(chalk.gray(`\n Claude projeleri bulundu: ${projects.length}\n`));
|
|
680
|
+
const projectsDir = path.join(os.homedir(), '.natureco', 'claude-projects');
|
|
681
|
+
fs.mkdirSync(projectsDir, { recursive: true });
|
|
682
|
+
|
|
683
|
+
for (const project of projects) {
|
|
684
|
+
const src = path.join(claudeProjects, project);
|
|
685
|
+
const dst = path.join(projectsDir, project);
|
|
686
|
+
if (!fs.existsSync(dst)) {
|
|
687
|
+
fs.cpSync(src, dst, { recursive: true });
|
|
688
|
+
console.log(chalk.green(` ✅ Proje kopyalandı: ${project}`));
|
|
689
|
+
} else {
|
|
690
|
+
console.log(chalk.yellow(` ⚠ Proje zaten var, atlandı: ${project}`));
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
} catch (err) {
|
|
695
|
+
console.log(chalk.yellow(` ⚠ Proje migrasyonu atlandı: ${err.message}`));
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Migrate MEMORY.md if exists
|
|
700
|
+
const memoryFile = path.join(claudeDir, '..', 'workspace', 'MEMORY.md');
|
|
701
|
+
if (fs.existsSync(memoryFile)) {
|
|
702
|
+
try {
|
|
703
|
+
const content = fs.readFileSync(memoryFile, 'utf-8');
|
|
704
|
+
const memory = {
|
|
705
|
+
name: '',
|
|
706
|
+
nickname: '',
|
|
707
|
+
botName: '',
|
|
708
|
+
facts: [{ value: 'Migrated from Claude Code', score: 5, updatedAt: new Date().toISOString() }],
|
|
709
|
+
preferences: []
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
const lines = content.split('\n');
|
|
713
|
+
for (const line of lines) {
|
|
714
|
+
if (line.toLowerCase().includes('name:')) {
|
|
715
|
+
memory.name = line.split(':')[1]?.trim() || '';
|
|
716
|
+
}
|
|
717
|
+
if (line.toLowerCase().includes('preference:') || line.toLowerCase().includes('favorite:')) {
|
|
718
|
+
memory.preferences.push({ value: line.split(':')[1]?.trim() || '', score: 5, updatedAt: new Date().toISOString() });
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const memoryDir = path.join(os.homedir(), '.natureco', 'memory');
|
|
723
|
+
fs.mkdirSync(memoryDir, { recursive: true });
|
|
724
|
+
fs.writeFileSync(path.join(memoryDir, 'universal-provider.json'), JSON.stringify(memory, null, 2));
|
|
725
|
+
console.log(chalk.green(' ✅ Claude MEMORY.md migrate edildi'));
|
|
726
|
+
} catch (err) {
|
|
727
|
+
console.log(chalk.yellow(` ⚠ Memory migrasyonu atlandı: ${err.message}`));
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
console.log(chalk.green('\n✅ Claude Code migration tamamlandı!\n'));
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// ── Hermes Migration ──────────────────────────────────────────────────────────
|
|
735
|
+
async function migrateHermes() {
|
|
736
|
+
console.log(chalk.yellow('\n⏳ Hermes → NatureCo migration başlıyor...\n'));
|
|
737
|
+
|
|
738
|
+
const hermesDir = path.join(os.homedir(), '.hermes');
|
|
739
|
+
const hermesConfig = path.join(hermesDir, 'config.json');
|
|
740
|
+
const hermesSessions = path.join(hermesDir, 'sessions');
|
|
741
|
+
|
|
742
|
+
if (!fs.existsSync(hermesDir)) {
|
|
743
|
+
console.log(chalk.yellow('⚠ Hermes dizini bulunamadı: ~/.hermes\n'));
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
let migrated = { config: false, sessions: 0, memory: false };
|
|
748
|
+
|
|
749
|
+
// Migrate config
|
|
750
|
+
if (fs.existsSync(hermesConfig)) {
|
|
751
|
+
try {
|
|
752
|
+
const config = JSON.parse(fs.readFileSync(hermesConfig, 'utf-8'));
|
|
753
|
+
|
|
754
|
+
const ncConfig = getConfig();
|
|
755
|
+
if (config.provider) ncConfig.providerUrl = config.provider;
|
|
756
|
+
if (config.model) ncConfig.providerModel = config.model;
|
|
757
|
+
if (config.apiKey) ncConfig.providerApiKey = config.apiKey;
|
|
758
|
+
if (config.systemPrompt) ncConfig.systemPrompt = config.systemPrompt;
|
|
759
|
+
if (config.temperature !== undefined) ncConfig.temperature = config.temperature;
|
|
760
|
+
|
|
761
|
+
setConfigValue('providerUrl', ncConfig.providerUrl);
|
|
762
|
+
setConfigValue('providerModel', ncConfig.providerModel);
|
|
763
|
+
if (config.apiKey) setConfigValue('providerApiKey', ncConfig.providerApiKey);
|
|
764
|
+
if (config.systemPrompt) setConfigValue('systemPrompt', ncConfig.systemPrompt);
|
|
765
|
+
if (config.temperature !== undefined) setConfigValue('temperature', ncConfig.temperature);
|
|
766
|
+
|
|
767
|
+
migrated.config = true;
|
|
768
|
+
console.log(chalk.green(' ✅ Hermes config migrate edildi'));
|
|
769
|
+
} catch (err) {
|
|
770
|
+
console.log(chalk.red(` ❌ Config okuma hatası: ${err.message}`));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// Migrate sessions
|
|
775
|
+
if (fs.existsSync(hermesSessions)) {
|
|
776
|
+
try {
|
|
777
|
+
const sessions = fs.readdirSync(hermesSessions).filter(f => f.endsWith('.json'));
|
|
778
|
+
const ncSessionsDir = path.join(os.homedir(), '.natureco', 'sessions');
|
|
779
|
+
fs.mkdirSync(ncSessionsDir, { recursive: true });
|
|
780
|
+
|
|
781
|
+
for (const session of sessions) {
|
|
782
|
+
const src = path.join(hermesSessions, session);
|
|
783
|
+
const dst = path.join(ncSessionsDir, `hermes-${session}`);
|
|
784
|
+
if (!fs.existsSync(dst)) {
|
|
785
|
+
fs.copyFileSync(src, dst);
|
|
786
|
+
migrated.sessions++;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
if (migrated.sessions > 0) {
|
|
791
|
+
console.log(chalk.green(` ✅ ${migrated.sessions} Hermes oturumu migrate edildi`));
|
|
792
|
+
}
|
|
793
|
+
} catch (err) {
|
|
794
|
+
console.log(chalk.yellow(` ⚠ Session migrasyonu atlandı: ${err.message}`));
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// Migrate memory
|
|
799
|
+
const hermesMemory = path.join(hermesDir, 'memory.json');
|
|
800
|
+
if (fs.existsSync(hermesMemory)) {
|
|
801
|
+
try {
|
|
802
|
+
const memData = JSON.parse(fs.readFileSync(hermesMemory, 'utf-8'));
|
|
803
|
+
const ncMemoryDir = path.join(os.homedir(), '.natureco', 'memory');
|
|
804
|
+
fs.mkdirSync(ncMemoryDir, { recursive: true });
|
|
805
|
+
|
|
806
|
+
const ncMem = {
|
|
807
|
+
name: memData.userName || '',
|
|
808
|
+
nickname: '',
|
|
809
|
+
botName: 'Hermes',
|
|
810
|
+
facts: [],
|
|
811
|
+
preferences: []
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
if (memData.userInfo) {
|
|
815
|
+
ncMem.facts.push({ value: memData.userInfo, score: 6, updatedAt: new Date().toISOString() });
|
|
816
|
+
}
|
|
817
|
+
if (memData.context) {
|
|
818
|
+
ncMem.facts.push({ value: memData.context, score: 5, updatedAt: new Date().toISOString() });
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
fs.writeFileSync(path.join(ncMemoryDir, 'hermes-migrated.json'), JSON.stringify(ncMem, null, 2));
|
|
822
|
+
migrated.memory = true;
|
|
823
|
+
console.log(chalk.green(' ✅ Hermes hafızası migrate edildi'));
|
|
824
|
+
} catch (err) {
|
|
825
|
+
console.log(chalk.yellow(` ⚠ Memory migrasyonu atlandı: ${err.message}`));
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (!migrated.config && migrated.sessions === 0 && !migrated.memory) {
|
|
830
|
+
console.log(chalk.yellow(' ⚠ Hiçbir veri migrate edilemedi.\n'));
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
console.log(chalk.green('\n✅ Hermes migration tamamlandı!\n'));
|
|
835
|
+
}
|
|
836
|
+
|
|
626
837
|
module.exports = migrate;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const http = require('http');
|
|
4
|
+
|
|
5
|
+
let nodeServer = null;
|
|
6
|
+
|
|
7
|
+
function nodeCmd(args) {
|
|
8
|
+
const [action, ...params] = args || [];
|
|
9
|
+
|
|
10
|
+
if (!action || action === 'status') return statusNode();
|
|
11
|
+
if (action === 'start') return startNode(params[0]);
|
|
12
|
+
if (action === 'stop') return stopNode();
|
|
13
|
+
if (action === 'info') return infoNode();
|
|
14
|
+
|
|
15
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
16
|
+
console.log(chalk.gray(' Kullanım: natureco node [status|start|stop|info]\n'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function statusNode() {
|
|
21
|
+
console.log(chalk.cyan('\n 🖥️ Node Host\n'));
|
|
22
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
23
|
+
console.log(` ${chalk.white('Status:')} ${nodeServer ? chalk.green('Running on port ' + nodeServer.port) : chalk.gray('idle')}`);
|
|
24
|
+
console.log(` ${chalk.white('Host:')} ${os.hostname()}`);
|
|
25
|
+
console.log(` ${chalk.white('Platform:')} ${process.platform}`);
|
|
26
|
+
console.log(` ${chalk.white('Memory:')} ${Math.round(os.freemem() / 1024 / 1024)}MB free`);
|
|
27
|
+
console.log(` ${chalk.white('CPU:')} ${os.cpus()[0]?.model || 'unknown'}`);
|
|
28
|
+
console.log(chalk.gray('\n Start: ') + chalk.cyan('natureco node start [port]'));
|
|
29
|
+
console.log(chalk.gray(' Info: ') + chalk.cyan('natureco node info'));
|
|
30
|
+
console.log();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function startNode(portStr) {
|
|
34
|
+
if (nodeServer) {
|
|
35
|
+
console.log(chalk.yellow('\n ⚠️ Node host already running\n'));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const port = parseInt(portStr, 10) || 0;
|
|
40
|
+
const server = http.createServer((req, res) => {
|
|
41
|
+
if (req.url === '/health' || req.url === '/') {
|
|
42
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
43
|
+
res.end(JSON.stringify({
|
|
44
|
+
status: 'ok',
|
|
45
|
+
hostname: os.hostname(),
|
|
46
|
+
platform: process.platform,
|
|
47
|
+
node: process.version,
|
|
48
|
+
uptime: Math.floor(process.uptime()),
|
|
49
|
+
memory: { free: os.freemem(), total: os.totalmem() },
|
|
50
|
+
cpus: os.cpus().length,
|
|
51
|
+
loadavg: os.loadavg()
|
|
52
|
+
}));
|
|
53
|
+
} else {
|
|
54
|
+
res.writeHead(404);
|
|
55
|
+
res.end('Not Found');
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
server.listen(port, () => {
|
|
60
|
+
nodeServer = server;
|
|
61
|
+
nodeServer.port = server.address().port;
|
|
62
|
+
console.log(chalk.green(`\n ✅ Node host running on http://localhost:${nodeServer.port}\n`));
|
|
63
|
+
console.log(chalk.gray(` Health endpoint: http://localhost:${nodeServer.port}/health\n`));
|
|
64
|
+
console.log(chalk.gray(' Press Ctrl+C to stop.\n'));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function stopNode() {
|
|
69
|
+
if (!nodeServer) {
|
|
70
|
+
console.log(chalk.yellow('\n ⚠️ Node host not running\n'));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
nodeServer.close(() => {
|
|
74
|
+
console.log(chalk.gray('\n 🛑 Node host stopped\n'));
|
|
75
|
+
nodeServer = null;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function infoNode() {
|
|
80
|
+
console.log(chalk.cyan('\n 🖥️ Node Info\n'));
|
|
81
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
82
|
+
console.log(` ${chalk.white('Node:')} ${process.version}`);
|
|
83
|
+
console.log(` ${chalk.white('Platform:')} ${process.platform} ${os.release()}`);
|
|
84
|
+
console.log(` ${chalk.white('Arch:')} ${process.arch}`);
|
|
85
|
+
console.log(` ${chalk.white('Hostname:')} ${os.hostname()}`);
|
|
86
|
+
console.log(` ${chalk.white('CPUs:')} ${os.cpus().length}`);
|
|
87
|
+
for (let i = 0; i < Math.min(os.cpus().length, 4); i++) {
|
|
88
|
+
console.log(` ${chalk.gray(`${i}: ${os.cpus()[i].model}`)}`);
|
|
89
|
+
}
|
|
90
|
+
if (os.cpus().length > 4) console.log(` ${chalk.gray(`… and ${os.cpus().length - 4} more`)}`);
|
|
91
|
+
console.log(` ${chalk.white('Memory:')} ${Math.round(os.totalmem() / 1024 / 1024 / 1024)}GB total, ${Math.round(os.freemem() / 1024 / 1024)}MB free`);
|
|
92
|
+
console.log(` ${chalk.white('Load:')} ${os.loadavg().map(l => l.toFixed(2)).join(', ')}`);
|
|
93
|
+
console.log(` ${chalk.white('Uptime:')} ${Math.floor(os.uptime() / 3600)}h ${Math.floor((os.uptime() % 3600) / 60)}m`);
|
|
94
|
+
console.log(` ${chalk.white('Interfaces:')} ${Object.keys(os.networkInterfaces()).filter(k => k !== 'lo').join(', ') || 'none'}`);
|
|
95
|
+
console.log();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = nodeCmd;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
|
|
5
|
+
function nodes(args) {
|
|
6
|
+
const [action, ...params] = args || [];
|
|
7
|
+
|
|
8
|
+
if (!action || action === 'list') return listNodes();
|
|
9
|
+
if (action === 'pair') return pairNode(params[0]);
|
|
10
|
+
if (action === 'approve') return approveNode(params[0]);
|
|
11
|
+
if (action === 'reject') return rejectNode(params[0]);
|
|
12
|
+
if (action === 'remove') return removeNode(params[0]);
|
|
13
|
+
if (action === 'rename') return renameNode(params[0], params.slice(1).join(' '));
|
|
14
|
+
|
|
15
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
16
|
+
console.log(chalk.gray(' Kullanım: natureco nodes [list|pair|approve|reject|remove|rename]\n'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function listNodes() {
|
|
21
|
+
const config = getConfig();
|
|
22
|
+
const nodes = config.pairedNodes || [];
|
|
23
|
+
|
|
24
|
+
console.log(chalk.cyan('\n 🖥️ Paired Nodes\n'));
|
|
25
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
26
|
+
|
|
27
|
+
if (nodes.length === 0) {
|
|
28
|
+
console.log(chalk.gray(' No paired nodes.\n'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (const n of nodes) {
|
|
33
|
+
console.log(` ${chalk.green('●')} ${chalk.white(n.name || n.id)}`);
|
|
34
|
+
console.log(` ${chalk.gray('ID:')} ${n.id}`);
|
|
35
|
+
console.log(` ${chalk.gray('URL:')} ${n.url || 'local'}`);
|
|
36
|
+
console.log(` ${chalk.gray('Key:')} ${n.key ? n.key.substring(0, 8) + '…' : 'none'}`);
|
|
37
|
+
}
|
|
38
|
+
console.log();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function pairNode(url) {
|
|
42
|
+
if (!url) {
|
|
43
|
+
console.log(chalk.red('\n ❌ Node URL gerekli\n'));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const config = getConfig();
|
|
48
|
+
if (!config.pairedNodes) config.pairedNodes = [];
|
|
49
|
+
|
|
50
|
+
const id = `node_${crypto.randomBytes(8).toString('hex')}`;
|
|
51
|
+
const key = crypto.randomBytes(16).toString('hex');
|
|
52
|
+
|
|
53
|
+
config.pairedNodes.push({ id, url, key, name: url, pairedAt: new Date().toISOString() });
|
|
54
|
+
saveConfig(config);
|
|
55
|
+
|
|
56
|
+
console.log(chalk.green(`\n ✅ Node paired: ${url}\n`));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function approveNode(id) {
|
|
60
|
+
console.log(chalk.green(`\n ✅ Node approved: ${id}\n`));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function rejectNode(id) {
|
|
64
|
+
console.log(chalk.gray(`\n ❌ Node rejected: ${id}\n`));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function removeNode(id) {
|
|
68
|
+
if (!id) {
|
|
69
|
+
console.log(chalk.red('\n ❌ Node ID gerekli\n'));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const config = getConfig();
|
|
74
|
+
const nodes = config.pairedNodes || [];
|
|
75
|
+
const idx = nodes.findIndex(n => n.id === id);
|
|
76
|
+
|
|
77
|
+
if (idx === -1) {
|
|
78
|
+
console.log(chalk.red(`\n ❌ Node bulunamadı: ${id}\n`));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
nodes.splice(idx, 1);
|
|
83
|
+
config.pairedNodes = nodes;
|
|
84
|
+
saveConfig(config);
|
|
85
|
+
console.log(chalk.gray(`\n 🗑️ Node removed: ${id}\n`));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function renameNode(id, name) {
|
|
89
|
+
if (!id || !name) {
|
|
90
|
+
console.log(chalk.red('\n ❌ Node ID ve name gerekli\n'));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const config = getConfig();
|
|
95
|
+
const node = (config.pairedNodes || []).find(n => n.id === id);
|
|
96
|
+
if (!node) {
|
|
97
|
+
console.log(chalk.red(`\n ❌ Node bulunamadı: ${id}\n`));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
node.name = name;
|
|
102
|
+
saveConfig(config);
|
|
103
|
+
console.log(chalk.green(`\n ✅ Node renamed: ${name}\n`));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = nodes;
|