natureco-cli 2.14.0 → 2.14.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "2.14.0",
3
+ "version": "2.14.1",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "main": "bin/natureco.js",
6
6
  "bin": {
@@ -83,11 +83,85 @@ async function chat(botName, options = {}) {
83
83
  }
84
84
  }
85
85
 
86
+ // Startup animation
87
+ console.clear();
88
+
89
+ // ASCII art rabbit
90
+ console.log('');
91
+ console.log(chalk.cyan(' (\\\_/)'));
92
+ console.log(chalk.cyan(' (•ᴥ•)'));
93
+ console.log(chalk.cyan(' />🌿'));
94
+ console.log('');
95
+
96
+ // Helper function for progress bar
97
+ function progressBar(percent, width = 20) {
98
+ const filled = Math.round(width * percent);
99
+ return chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(width - filled));
100
+ }
101
+
102
+ // Helper function to check gateway status
103
+ function checkGateway() {
104
+ try {
105
+ const fs2 = require('fs');
106
+ const gatewayPidFile = path.join(os.homedir(), '.natureco', 'gateway.pid');
107
+ if (fs2.existsSync(gatewayPidFile)) {
108
+ const pid = parseInt(fs2.readFileSync(gatewayPidFile, 'utf8'));
109
+ process.kill(pid, 0);
110
+ return true;
111
+ }
112
+ } catch {
113
+ return false;
114
+ }
115
+ return false;
116
+ }
117
+
118
+ // Startup steps with animation
119
+ const steps = [
120
+ { label: 'Memory', fn: () => loadMemory(bot.id) },
121
+ { label: 'Skills', fn: () => getSkillPrompts() },
122
+ { label: 'Gateway', fn: () => checkGateway() },
123
+ ];
124
+
125
+ // Execute steps with progress animation
126
+ const results = {};
127
+ for (let i = 0; i < steps.length; i++) {
128
+ const step = steps[i];
129
+ const percent = (i + 1) / steps.length;
130
+
131
+ process.stdout.write(`[${progressBar(percent)}] ${step.label}...`);
132
+
133
+ // Execute step
134
+ const result = step.fn();
135
+ results[step.label.toLowerCase()] = result;
136
+
137
+ // Show result
138
+ let info = '';
139
+ if (step.label === 'Memory' && result) {
140
+ const factCount = (result.facts || []).length;
141
+ info = factCount > 0 ? ` · ${factCount} facts` : '';
142
+ } else if (step.label === 'Skills' && result) {
143
+ const skillCount = getSkills().length;
144
+ info = skillCount > 0 ? ` · ${skillCount} skills` : '';
145
+ } else if (step.label === 'Gateway') {
146
+ info = result ? ' · running' : ' · offline';
147
+ }
148
+
149
+ process.stdout.write(`\r[${progressBar(percent)}] ${step.label} loaded${info}\n`);
150
+
151
+ // Wait 300ms
152
+ await new Promise(resolve => setTimeout(resolve, 300));
153
+ }
154
+
155
+ console.log('');
156
+
157
+ // Wait a bit before clearing
158
+ await new Promise(resolve => setTimeout(resolve, 500));
159
+
86
160
  // Chat başlat
87
161
  console.clear();
88
162
 
89
163
  // Get botName from memory
90
- const memory = loadMemory(bot.id);
164
+ const memory = results.memory || loadMemory(bot.id);
91
165
  const displayBotName = memory.botName || bot.name;
92
166
 
93
167
  // Get provider model (short name)
@@ -96,10 +170,63 @@ async function chat(botName, options = {}) {
96
170
  const providerModel = config.providerModel || 'unknown';
97
171
  const shortModel = providerModel.split('/').pop().split('-').slice(0, 2).join('-'); // e.g., "llama-3.1" from "llama-3.1-8b-instant"
98
172
 
99
- // Minimal header with separator
100
- const separator = '─'.repeat(40);
173
+ // Get terminal width
174
+ const terminalWidth = process.stdout.columns || 80;
175
+ const separator = '─'.repeat(terminalWidth);
176
+
177
+ // Full UI header
178
+ console.log(chalk.gray(separator));
179
+
180
+ // Line 1: NatureCo · botName · model · timezone
181
+ const timezone = memory.facts?.find(f => {
182
+ const val = typeof f === 'string' ? f : f.value;
183
+ return val?.includes('Timezone:');
184
+ });
185
+ const tzStr = timezone ? (typeof timezone === 'string' ? timezone : timezone.value).replace('Timezone:', '').trim() : '';
186
+ const line1 = chalk.white.bold('NatureCo') +
187
+ chalk.gray(' · ') +
188
+ chalk.cyan(displayBotName) +
189
+ chalk.gray(' · ') +
190
+ chalk.gray(shortModel) +
191
+ (tzStr ? chalk.gray(' · ') + chalk.gray(tzStr) : '');
192
+ console.log(line1);
193
+
194
+ console.log(chalk.gray(separator));
195
+
196
+ // Line 2: Session · Commands · Ctrl+C
197
+ const line2 = chalk.gray('Session') +
198
+ chalk.gray(' · ') +
199
+ chalk.gray('Commands: /clear /bot /skills /memory /help') +
200
+ chalk.gray(' · ') +
201
+ chalk.gray('Ctrl+C to exit');
202
+ console.log(line2);
203
+
101
204
  console.log(chalk.gray(separator));
102
- console.log(chalk.white('NatureCo') + chalk.gray(' · ') + chalk.cyan(displayBotName) + chalk.gray(' · ') + chalk.gray(shortModel));
205
+
206
+ // Line 3: Memory info · Skills · Crons
207
+ const userName = memory.name || '';
208
+ const factCount = (memory.facts || []).length;
209
+ const skillCount = getSkills().length;
210
+
211
+ // Get cron count
212
+ let cronCount = 0;
213
+ try {
214
+ const fs2 = require('fs');
215
+ const cronsFile = path.join(os.homedir(), '.natureco', 'crons.json');
216
+ if (fs2.existsSync(cronsFile)) {
217
+ const crons = JSON.parse(fs2.readFileSync(cronsFile, 'utf8'));
218
+ cronCount = crons.filter(c => c.enabled).length;
219
+ }
220
+ } catch {}
221
+
222
+ const memoryInfo = userName ? `Memory: ${userName}` : 'Memory';
223
+ const line3 = chalk.gray(memoryInfo + (factCount > 0 ? ` · ${factCount} facts` : '')) +
224
+ chalk.gray(' ') +
225
+ chalk.gray(`Skills: ${skillCount}`) +
226
+ chalk.gray(' ') +
227
+ chalk.gray(`Crons: ${cronCount} active`);
228
+ console.log(line3);
229
+
103
230
  console.log(chalk.gray(separator));
104
231
  console.log('');
105
232
 
@@ -142,11 +269,8 @@ async function chat(botName, options = {}) {
142
269
  } else {
143
270
  // Create new session
144
271
  session = createSession(bot.id, bot.name);
145
- console.log(chalk.gray(`Session: ${session.id}\n`));
146
272
  }
147
273
 
148
- console.log(chalk.gray('Commands: /clear /bot /skills /memory /help · Ctrl+C to exit\n'));
149
-
150
274
  // Run on-start hooks
151
275
  await runHooks('on-start', null, { botId: bot.id, botName: bot.name });
152
276
 
@@ -244,12 +368,13 @@ async function chat(botName, options = {}) {
244
368
  switch (command.toLowerCase()) {
245
369
  case 'clear':
246
370
  console.clear();
247
- const separator2 = '─'.repeat(40);
371
+ const terminalWidth2 = process.stdout.columns || 80;
372
+ const separator2 = '─'.repeat(terminalWidth2);
373
+
248
374
  console.log(chalk.gray(separator2));
249
- console.log(chalk.white('NatureCo') + chalk.gray(' · ') + chalk.cyan(displayBotName) + chalk.gray(' · ') + chalk.gray(shortModel));
375
+ console.log(chalk.white.bold('NatureCo') + chalk.gray(' · ') + chalk.cyan(displayBotName) + chalk.gray(' · ') + chalk.gray(shortModel));
250
376
  console.log(chalk.gray(separator2));
251
377
  console.log('');
252
- console.log(chalk.gray('Commands: /clear /bot /skills /memory /help\n'));
253
378
  rl.prompt();
254
379
  return;
255
380
 
@@ -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.14.0</div>
214
+ <div class="version-badge" id="version-badge">v2.14.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.14.0',
344
+ version: 'v2.14.1',
345
345
  bots: cfg.bots || [],
346
346
  telegramToken: cfg.telegramToken || null,
347
347
  whatsappConnected: cfg.whatsappConnected || false,