natureco-cli 2.13.15 → 2.13.17

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.13.15",
3
+ "version": "2.13.17",
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.13.15</div>
214
+ <div class="version-badge" id="version-badge">v2.13.17</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.13.15',
344
+ version: 'v2.13.17',
345
345
  bots: cfg.bots || [],
346
346
  telegramToken: cfg.telegramToken || null,
347
347
  whatsappConnected: cfg.whatsappConnected || false,
@@ -74,9 +74,11 @@ async function migrate(options) {
74
74
  const nameMatch = userMd.match(/Name:\s*(.+)/i);
75
75
  const timezoneMatch = userMd.match(/Timezone:\s*(.+)/i);
76
76
  const notesMatch = userMd.match(/Notes:\s*(.+)/i);
77
+ const botNameMatch = userMd.match(/What to call them:\s*\*\*(.+?)\*\*/i);
77
78
 
78
79
  const memory = {
79
80
  name: nameMatch ? nameMatch[1].trim() : null,
81
+ botName: botNameMatch ? botNameMatch[1].trim() : null,
80
82
  facts: []
81
83
  };
82
84
 
@@ -85,6 +87,10 @@ async function migrate(options) {
85
87
  memory.name = memory.name.replace(/\*\*/g, '').trim();
86
88
  }
87
89
 
90
+ if (memory.botName) {
91
+ memory.botName = memory.botName.replace(/\*\*/g, '').trim();
92
+ }
93
+
88
94
  if (timezoneMatch) {
89
95
  let timezone = timezoneMatch[1].trim().replace(/\*\*/g, '').trim();
90
96
  addUniqueFact(memory.facts, {
package/src/utils/api.js CHANGED
@@ -207,14 +207,6 @@ function coerceMcpParams(tool, params) {
207
207
  tool.parameters?.properties || // fallback
208
208
  {};
209
209
 
210
- // Debug: Show which schema format was found
211
- console.log('[DEBUG] COERCE TOOL:', tool.name);
212
- console.log('[DEBUG] COERCE SCHEMA SOURCE:',
213
- tool.inputSchema?.properties ? 'inputSchema.properties' :
214
- tool.input_schema?.properties ? 'input_schema.properties' :
215
- tool.parameters?.properties ? 'parameters.properties' : 'NONE');
216
- console.log('[DEBUG] COERCE SCHEMA:', JSON.stringify(schema).slice(0, 200));
217
-
218
210
  const coerced = { ...params };
219
211
 
220
212
  for (const [key, def] of Object.entries(schema)) {
@@ -225,14 +217,12 @@ function coerceMcpParams(tool, params) {
225
217
  const num = Number(coerced[key]);
226
218
  if (!isNaN(num)) {
227
219
  coerced[key] = num;
228
- console.log('[DEBUG] COERCED', key, 'from string to number:', coerced[key]);
229
220
  }
230
221
  }
231
222
 
232
223
  // Coerce boolean
233
224
  if (def.type === 'boolean' && typeof coerced[key] === 'string') {
234
225
  coerced[key] = coerced[key] === 'true' || coerced[key] === '1';
235
- console.log('[DEBUG] COERCED', key, 'from string to boolean:', coerced[key]);
236
226
  }
237
227
  }
238
228
 
@@ -243,8 +233,6 @@ function coerceMcpParams(tool, params) {
243
233
  * Execute MCP tool call
244
234
  */
245
235
  async function executeMcpTool(toolName, toolArgs) {
246
- console.log('[DEBUG] EXECUTING MCP TOOL:', toolName, 'Args:', JSON.stringify(toolArgs).slice(0, 100));
247
-
248
236
  // Find which server has this tool
249
237
  for (const [serverName, { client, tools }] of Object.entries(mcpClients)) {
250
238
  const tool = tools.find(t => t.name === toolName);
@@ -255,12 +243,9 @@ async function executeMcpTool(toolName, toolArgs) {
255
243
  try {
256
244
  // Coerce parameters to match schema types
257
245
  const coercedArgs = coerceMcpParams(tool, toolArgs);
258
- console.log('[DEBUG] MCP COERCED ARGS:', JSON.stringify(coercedArgs).slice(0, 100));
259
246
 
260
247
  const result = await client.callTool(toolName, coercedArgs);
261
248
 
262
- console.log('[DEBUG] MCP RAW RESULT:', JSON.stringify(result).slice(0, 200));
263
-
264
249
  // MCP returns { content: [{ type: 'text', text: '...' }] }
265
250
  if (result.content && result.content.length > 0) {
266
251
  // Extract all text content and join with newlines
@@ -274,10 +259,8 @@ async function executeMcpTool(toolName, toolArgs) {
274
259
  // Truncate MCP result to max 1500 characters
275
260
  if (output.length > 1500) {
276
261
  output = output.slice(0, 1500) + '... (truncated)';
277
- console.log('[DEBUG] MCP OUTPUT TRUNCATED from', textContents.join('\n').length, 'to 1500 chars');
278
262
  }
279
263
 
280
- console.log('[DEBUG] MCP FORMATTED OUTPUT:', output.slice(0, 100));
281
264
  return {
282
265
  success: true,
283
266
  output: output
@@ -291,17 +274,14 @@ async function executeMcpTool(toolName, toolArgs) {
291
274
  // Truncate fallback output too
292
275
  if (fallbackOutput.length > 1500) {
293
276
  fallbackOutput = fallbackOutput.slice(0, 1500) + '... (truncated)';
294
- console.log('[DEBUG] MCP FALLBACK OUTPUT TRUNCATED');
295
277
  }
296
278
 
297
- console.log('[DEBUG] MCP FALLBACK OUTPUT:', fallbackOutput.slice(0, 100));
298
279
  return {
299
280
  success: true,
300
281
  output: fallbackOutput
301
282
  };
302
283
 
303
284
  } catch (err) {
304
- console.log('[DEBUG] MCP ERROR:', err.message);
305
285
  return {
306
286
  success: false,
307
287
  error: `MCP tool error: ${err.message}`
@@ -310,7 +290,6 @@ async function executeMcpTool(toolName, toolArgs) {
310
290
  }
311
291
  }
312
292
 
313
- console.log('[DEBUG] MCP TOOL NOT FOUND:', toolName);
314
293
  return {
315
294
  success: false,
316
295
  error: `MCP tool not found: ${toolName}`
@@ -449,10 +428,6 @@ async function sendMessageOpenAICompatible(providerConfig, messages, tools) {
449
428
  };
450
429
 
451
430
  const bodyStr = JSON.stringify(requestBody);
452
- console.log('[API] Request size:', bodyStr.length, 'chars, ~', Math.round(bodyStr.length / 4), 'tokens');
453
- console.log('[API] Messages count:', messages.length);
454
- console.log('[API] Tools count:', tools?.length || 0);
455
- console.log('[API] System prompt length:', messages[0]?.content?.length || 0);
456
431
 
457
432
  const response = await fetch(endpoint, {
458
433
  method: 'POST',
@@ -529,16 +504,6 @@ async function sendMessageAnthropic(providerConfig, messages, tools) {
529
504
  * Send message with tool support (universal)
530
505
  */
531
506
  async function sendMessageToProvider(apiKey, message, conversationId = null, systemPrompt = null) {
532
- // DEBUG: Write system prompt to file for inspection
533
- try {
534
- const debugPath = path.join(os.homedir(), '.natureco', 'debug-system-prompt.txt');
535
- fs.writeFileSync(debugPath, systemPrompt || 'EMPTY');
536
- console.log('[DEBUG] System prompt written to ~/.natureco/debug-system-prompt.txt');
537
- console.log('[DEBUG] System prompt length:', (systemPrompt || '').length, 'chars');
538
- } catch (err) {
539
- // Silently fail if can't write debug file
540
- }
541
-
542
507
  const providerConfig = getProviderConfig();
543
508
 
544
509
  if (!providerConfig) {
@@ -617,13 +582,10 @@ async function sendMessageToProvider(apiKey, message, conversationId = null, sys
617
582
  const mcpTools = getMcpTools();
618
583
  const isMcpTool = mcpTools.find(t => t.name === toolCall.name);
619
584
 
620
- console.log('[DEBUG] Tool call:', toolCall.name, 'Is MCP?', !!isMcpTool);
621
-
622
585
  if (isMcpTool) {
623
586
  // Execute MCP tool
624
587
  debugLog(`[MCP] Executing tool: ${toolCall.name}`);
625
588
  const result = await executeMcpTool(toolCall.name, toolCall.input);
626
- console.log('[DEBUG] MCP result:', JSON.stringify(result).slice(0, 200));
627
589
  toolResults.push({
628
590
  id: toolCall.id,
629
591
  name: toolCall.name,
@@ -633,20 +595,15 @@ async function sendMessageToProvider(apiKey, message, conversationId = null, sys
633
595
  // Execute local tool
634
596
  debugLog(`[Local] Executing tool: ${toolCall.name}`);
635
597
  const localResults = await executeToolCalls([toolCall]);
636
- console.log('[DEBUG] Local result:', JSON.stringify(localResults[0]).slice(0, 200));
637
598
  toolResults.push(...localResults);
638
599
  }
639
600
  }
640
601
 
641
602
  // Add tool results to messages (base64 encoded for safety)
642
603
  for (const result of toolResults) {
643
- console.log('[ENCODE]', result.name, 'Result type:', typeof result.result);
644
-
645
604
  // Encode tool result (works for both MCP and local tools)
646
605
  const encodedContent = encodeToolResult(result.result);
647
606
 
648
- console.log('[ENCODE]', result.name, 'Encoded preview:', encodedContent.slice(0, 50));
649
-
650
607
  messages.push({
651
608
  role: 'tool',
652
609
  tool_call_id: result.id,
@@ -818,12 +775,6 @@ TOOL SELECTION GUIDE:
818
775
  }
819
776
  }
820
777
 
821
- // Log system prompt components
822
- console.log('[API] Base system prompt:', baseSystemPrompt.length, 'chars');
823
- console.log('[API] MCP prompt:', mcpPrompt.length, 'chars');
824
- console.log('[API] Skills prompt:', skillsPrompt.length, 'chars');
825
- console.log('[API] Total system prompt:', systemPrompt.length, 'chars, ~', Math.round(systemPrompt.length / 4), 'tokens');
826
-
827
778
  return sendMessageToProvider(apiKey, message, conversationId, systemPrompt);
828
779
  }
829
780
 
@@ -206,17 +206,18 @@ function getMemoryPrompt(botId) {
206
206
  const preferences = memory.preferences || [];
207
207
  const facts = memory.facts || [];
208
208
 
209
- if (!name && !botName && preferences.length === 0 && facts.length === 0) {
210
- return '';
211
- }
212
-
213
209
  const parts = [];
214
210
 
215
- // Add bot name if set
211
+ // Add bot name if set (MUST be before empty check)
216
212
  if (botName) {
217
213
  parts.push(`Your name is ${botName}.`);
218
214
  }
219
215
 
216
+ // Check if there's any content to add
217
+ if (!name && !botName && preferences.length === 0 && facts.length === 0) {
218
+ return '';
219
+ }
220
+
220
221
  // Add user memory section
221
222
  if (name || preferences.length > 0 || facts.length > 0) {
222
223
  parts.push('## Kullanıcı Hafızası');
@@ -235,8 +236,6 @@ function getMemoryPrompt(botId) {
235
236
  const sorted = facts.sort((a, b) => b.score - a.score);
236
237
  const topFacts = sorted.slice(0, 15);
237
238
 
238
- console.log('[MEMORY] Facts count:', facts.length, '→ showing:', topFacts.length);
239
-
240
239
  parts.push(`Bilgiler: ${topFacts.map(f => f.value).join(', ')}`);
241
240
 
242
241
  if (facts.length > 15) {
@@ -246,7 +245,6 @@ function getMemoryPrompt(botId) {
246
245
  }
247
246
 
248
247
  const prompt = parts.join('\n');
249
- console.log('[MEMORY] Prompt length:', prompt.length, 'chars, ~', Math.round(prompt.length / 4), 'tokens');
250
248
 
251
249
  return prompt;
252
250
  }
@@ -295,19 +295,24 @@ function getPopularSkills() {
295
295
  // Get skill prompt injection content
296
296
  function getSkillPrompts() {
297
297
  const skills = getSkills();
298
+
299
+ if (skills.length === 0) {
300
+ return '';
301
+ }
302
+
298
303
  const prompts = [];
299
304
 
300
305
  for (const skill of skills) {
301
- const skillFile = path.join(skill.path, 'SKILL.md');
302
- if (fs.existsSync(skillFile)) {
303
- const content = fs.readFileSync(skillFile, 'utf8');
304
- // Remove frontmatter
305
- const withoutFrontmatter = content.replace(/^---\n[\s\S]*?\n---\n/, '');
306
- prompts.push(`\n## Skill: ${skill.name}\n${withoutFrontmatter}`);
307
- }
306
+ // Only add skill name and short description (not full SKILL.md content)
307
+ const desc = skill.description ? skill.description.slice(0, 100) : '';
308
+ prompts.push(`- ${skill.name}: ${desc}`);
308
309
  }
309
310
 
310
- return prompts.join('\n\n');
311
+ // Limit to first 10 skills
312
+ const skillsList = prompts.slice(0, 10).join('\n');
313
+ const moreCount = skills.length > 10 ? ` (${skills.length - 10} more)` : '';
314
+
315
+ return `\n\nInstalled skills (${skills.length})${moreCount}:\n${skillsList}\nUse /skills for details.`;
311
316
  }
312
317
 
313
318
  module.exports = {