natureco-cli 2.12.0 → 2.12.1

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 CHANGED
@@ -97,6 +97,16 @@ program
97
97
  updateCmd();
98
98
  });
99
99
 
100
+ program
101
+ .command('migrate')
102
+ .description('Migrate from other CLI tools')
103
+ .option('--from <source>', 'Source CLI (openclaw)')
104
+ .option('--openclaw-dir <path>', 'OpenClaw directory path (default: ~/.openclaw)')
105
+ .action((options) => {
106
+ const migrateCmd = require('../src/commands/migrate');
107
+ migrateCmd(options);
108
+ });
109
+
100
110
  program
101
111
  .command('commands [action] [params...]')
102
112
  .description('Manage custom commands (list|create)')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "2.12.0",
3
+ "version": "2.12.1",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "main": "bin/natureco.js",
6
6
  "bin": {
@@ -211,7 +211,7 @@ body::before{
211
211
  <div class="header-bot-name" id="header-bot-name">Nature Bot</div>
212
212
  <div class="header-bot-model" id="header-bot-model">NatureCo</div>
213
213
  </div>
214
- <div class="version-badge" id="version-badge">v2.12.0</div>
214
+ <div class="version-badge" id="version-badge">v2.12.1</div>
215
215
  </div>
216
216
  <div class="messages" id="messages"></div>
217
217
  <div class="input-area">
@@ -341,7 +341,7 @@ function dashboard(action) {
341
341
  apiKey: cfg.apiKey,
342
342
  defaultBot: cfg.defaultBot,
343
343
  defaultBotId: cfg.defaultBotId,
344
- version: 'v2.12.0',
344
+ version: 'v2.12.1',
345
345
  bots: cfg.bots || [],
346
346
  telegramToken: cfg.telegramToken || null,
347
347
  whatsappConnected: cfg.whatsappConnected || false,
@@ -0,0 +1,223 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const os = require('os');
4
+ const chalk = require('chalk');
5
+ const { getConfig, setConfig } = require('../utils/config');
6
+
7
+ async function migrate(options) {
8
+ const from = options.from || 'openclaw';
9
+
10
+ if (from !== 'openclaw') {
11
+ console.log(chalk.red('\n❌ Sadece OpenClaw migration destekleniyor.\n'));
12
+ console.log(chalk.gray('Kullanım: natureco migrate --from openclaw\n'));
13
+ return;
14
+ }
15
+
16
+ console.log(chalk.yellow('\n⏳ OpenClaw → NatureCo migration başlıyor...\n'));
17
+
18
+ // OpenClaw directory
19
+ const openclawDir = options.openclawDir || path.join(os.homedir(), '.openclaw');
20
+
21
+ if (!fs.existsSync(openclawDir)) {
22
+ console.log(chalk.red(`❌ OpenClaw dizini bulunamadı: ${openclawDir}\n`));
23
+ console.log(chalk.gray('--openclaw-dir ile farklı bir dizin belirtin.\n'));
24
+ return;
25
+ }
26
+
27
+ console.log(chalk.cyan('OpenClaw dizini:'), chalk.white(openclawDir));
28
+ console.log('');
29
+
30
+ const report = {
31
+ memory: null,
32
+ crons: { total: 0, active: 0, inactive: 0 },
33
+ telegram: null,
34
+ whatsapp: false,
35
+ };
36
+
37
+ // 1. Memory migration
38
+ try {
39
+ const userMdPath = path.join(openclawDir, 'workspace', 'USER.md');
40
+
41
+ if (fs.existsSync(userMdPath)) {
42
+ const userMd = fs.readFileSync(userMdPath, 'utf8');
43
+
44
+ // Parse USER.md
45
+ const nameMatch = userMd.match(/Name:\s*(.+)/i);
46
+ const timezoneMatch = userMd.match(/Timezone:\s*(.+)/i);
47
+ const notesMatch = userMd.match(/Notes:\s*(.+)/i);
48
+
49
+ const memory = {
50
+ name: nameMatch ? nameMatch[1].trim() : null,
51
+ facts: []
52
+ };
53
+
54
+ if (timezoneMatch) {
55
+ memory.facts.push(`Timezone: ${timezoneMatch[1].trim()}`);
56
+ }
57
+
58
+ if (notesMatch) {
59
+ memory.facts.push(notesMatch[1].trim());
60
+ }
61
+
62
+ // Save to NatureCo memory
63
+ const memoryDir = path.join(os.homedir(), '.natureco', 'memory');
64
+ fs.mkdirSync(memoryDir, { recursive: true });
65
+
66
+ const memoryFile = path.join(memoryDir, 'universal-provider.json');
67
+ fs.writeFileSync(memoryFile, JSON.stringify(memory, null, 2));
68
+
69
+ report.memory = memory;
70
+ }
71
+ } catch (err) {
72
+ console.log(chalk.gray('⚠️ Memory migration atlandı:', err.message));
73
+ }
74
+
75
+ // 2. Cron jobs migration
76
+ try {
77
+ const cronJobsPath = path.join(openclawDir, 'cron', 'jobs.json');
78
+
79
+ if (fs.existsSync(cronJobsPath)) {
80
+ const openclawCrons = JSON.parse(fs.readFileSync(cronJobsPath, 'utf8'));
81
+
82
+ const naturecoCrons = [];
83
+
84
+ for (const job of openclawCrons) {
85
+ report.crons.total++;
86
+
87
+ if (!job.enabled) {
88
+ report.crons.inactive++;
89
+ continue;
90
+ }
91
+
92
+ report.crons.active++;
93
+
94
+ // Only migrate cron schedule (not interval)
95
+ if (job.schedule?.kind !== 'cron') {
96
+ continue;
97
+ }
98
+
99
+ // Determine action based on delivery channel
100
+ let action = 'whatsapp'; // default
101
+ if (job.delivery?.channel === 'telegram') {
102
+ action = 'telegram';
103
+ }
104
+
105
+ // Get prompt (first 200 chars)
106
+ let prompt = job.payload?.message || '';
107
+ if (prompt.length > 200) {
108
+ prompt = prompt.slice(0, 200) + '...';
109
+ }
110
+
111
+ naturecoCrons.push({
112
+ name: job.name || 'Unnamed Job',
113
+ schedule: job.schedule.expr,
114
+ action: action,
115
+ prompt: prompt,
116
+ });
117
+ }
118
+
119
+ // Save to NatureCo crons
120
+ const cronsFile = path.join(os.homedir(), '.natureco', 'crons.json');
121
+
122
+ // Merge with existing crons if any
123
+ let existingCrons = [];
124
+ if (fs.existsSync(cronsFile)) {
125
+ existingCrons = JSON.parse(fs.readFileSync(cronsFile, 'utf8'));
126
+ }
127
+
128
+ const mergedCrons = [...existingCrons, ...naturecoCrons];
129
+ fs.writeFileSync(cronsFile, JSON.stringify(mergedCrons, null, 2));
130
+ }
131
+ } catch (err) {
132
+ console.log(chalk.gray('⚠️ Cron migration atlandı:', err.message));
133
+ }
134
+
135
+ // 3. Telegram allowFrom migration
136
+ try {
137
+ const telegramAllowPath = path.join(openclawDir, 'credentials', 'telegram-default-allowFrom.json');
138
+
139
+ if (fs.existsSync(telegramAllowPath)) {
140
+ const allowFrom = JSON.parse(fs.readFileSync(telegramAllowPath, 'utf8'));
141
+
142
+ if (Array.isArray(allowFrom) && allowFrom.length > 0) {
143
+ // Save to NatureCo config
144
+ setConfig('telegramAllowedChats', allowFrom);
145
+ report.telegram = allowFrom;
146
+ }
147
+ }
148
+ } catch (err) {
149
+ console.log(chalk.gray('⚠️ Telegram allowFrom migration atlandı:', err.message));
150
+ }
151
+
152
+ // 4. WhatsApp session migration
153
+ try {
154
+ const whatsappSessionPath = path.join(openclawDir, 'credentials', 'whatsapp', 'default');
155
+
156
+ if (fs.existsSync(whatsappSessionPath)) {
157
+ const config = getConfig();
158
+ const botId = config.defaultBotId || 'whatsapp_default';
159
+
160
+ const naturecoSessionPath = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', `whatsapp_${botId}`);
161
+
162
+ // Copy directory recursively
163
+ fs.mkdirSync(naturecoSessionPath, { recursive: true });
164
+ copyDirRecursive(whatsappSessionPath, naturecoSessionPath);
165
+
166
+ report.whatsapp = true;
167
+ }
168
+ } catch (err) {
169
+ console.log(chalk.gray('⚠️ WhatsApp session migration atlandı:', err.message));
170
+ }
171
+
172
+ // Print migration report
173
+ console.log(chalk.green('✅ Migration tamamlandı!\n'));
174
+
175
+ if (report.memory) {
176
+ const facts = report.memory.facts.join(', ');
177
+ console.log(chalk.green('✅ Memory:'), chalk.white(`${report.memory.name || 'N/A'}${facts ? ', ' + facts : ''}`));
178
+ }
179
+
180
+ if (report.crons.total > 0) {
181
+ console.log(chalk.green('✅ Cron jobs:'), chalk.white(`${report.crons.total} job migrate edildi (${report.crons.active} aktif, ${report.crons.inactive} pasif)`));
182
+ }
183
+
184
+ if (report.telegram && report.telegram.length > 0) {
185
+ console.log(chalk.green('✅ Telegram allowFrom:'), chalk.white(report.telegram.join(', ')));
186
+ }
187
+
188
+ if (report.whatsapp) {
189
+ console.log(chalk.green('✅ WhatsApp session kopyalandı'));
190
+ }
191
+
192
+ console.log('');
193
+ console.log(chalk.yellow('⚠️ Manuel kurulum gerekli:'));
194
+ console.log(chalk.gray(' - Provider URL ve API key ayarlayın:'));
195
+ console.log(chalk.cyan(' natureco config set providerUrl https://api.groq.com/openai/v1'));
196
+ console.log(chalk.cyan(' natureco config set providerApiKey gsk_xxx'));
197
+ console.log(chalk.cyan(' natureco config set providerModel llama-3.1-8b-instant'));
198
+ console.log('');
199
+ }
200
+
201
+ /**
202
+ * Copy directory recursively
203
+ */
204
+ function copyDirRecursive(src, dest) {
205
+ if (!fs.existsSync(src)) return;
206
+
207
+ fs.mkdirSync(dest, { recursive: true });
208
+
209
+ const entries = fs.readdirSync(src, { withFileTypes: true });
210
+
211
+ for (const entry of entries) {
212
+ const srcPath = path.join(src, entry.name);
213
+ const destPath = path.join(dest, entry.name);
214
+
215
+ if (entry.isDirectory()) {
216
+ copyDirRecursive(srcPath, destPath);
217
+ } else {
218
+ fs.copyFileSync(srcPath, destPath);
219
+ }
220
+ }
221
+ }
222
+
223
+ module.exports = migrate;