natureco-cli 2.13.16 → 2.13.18

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.16",
3
+ "version": "2.13.18",
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.16</div>
214
+ <div class="version-badge" id="version-badge">v2.13.18</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.16',
344
+ version: 'v2.13.18',
345
345
  bots: cfg.bots || [],
346
346
  telegramToken: cfg.telegramToken || null,
347
347
  whatsappConnected: cfg.whatsappConnected || false,
@@ -74,9 +74,12 @@ 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 nicknameMatch = userMd.match(/What to call them:\s*\*\*(.+?)\*\*/i);
77
78
 
78
79
  const memory = {
79
80
  name: nameMatch ? nameMatch[1].trim() : null,
81
+ nickname: nicknameMatch ? nicknameMatch[1].trim() : null,
82
+ botName: null, // Will be extracted from MEMORY.md
80
83
  facts: []
81
84
  };
82
85
 
@@ -85,6 +88,10 @@ async function migrate(options) {
85
88
  memory.name = memory.name.replace(/\*\*/g, '').trim();
86
89
  }
87
90
 
91
+ if (memory.nickname) {
92
+ memory.nickname = memory.nickname.replace(/\*\*/g, '').trim();
93
+ }
94
+
88
95
  if (timezoneMatch) {
89
96
  let timezone = timezoneMatch[1].trim().replace(/\*\*/g, '').trim();
90
97
  addUniqueFact(memory.facts, {
@@ -137,6 +144,25 @@ async function migrate(options) {
137
144
  try {
138
145
  const content = fs.readFileSync(file, 'utf8');
139
146
 
147
+ // Extract bot name from MEMORY.md (first file only)
148
+ if (!memory.botName && file === mainMemoryPath) {
149
+ // Try multiple patterns for bot name
150
+ const botNamePatterns = [
151
+ /[İI]sim:\s*([^\n]+)/, // İsim: İchigo
152
+ /Ben[,\s]+([A-ZÇĞİÖŞÜ][a-zçğıöşü]+)/, // Ben, İchigo
153
+ /Adım[,\s]+([A-ZÇĞİÖŞÜ][a-zçğıöşü]+)/, // Adım İchigo
154
+ /Ben\s+([A-ZÇĞİÖŞÜ][a-zçğıöşü]+)['']?[ıi]m/ // Ben İchigo'yum
155
+ ];
156
+
157
+ for (const pattern of botNamePatterns) {
158
+ const match = content.match(pattern);
159
+ if (match) {
160
+ memory.botName = match[1].trim().replace(/\*\*/g, '').trim();
161
+ break;
162
+ }
163
+ }
164
+ }
165
+
140
166
  // Extract meaningful lines (skip headers, empty lines, useless patterns)
141
167
  const lines = content.split('\n')
142
168
  .filter(l => l.trim() && !l.startsWith('#'))
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
 
@@ -24,6 +24,7 @@ function loadMemory(botId) {
24
24
  if (!fs.existsSync(filePath)) {
25
25
  return {
26
26
  name: '',
27
+ nickname: '',
27
28
  botName: '',
28
29
  preferences: [],
29
30
  facts: [],
@@ -38,6 +39,7 @@ function loadMemory(botId) {
38
39
  // Return with safe defaults for all fields
39
40
  const memory = {
40
41
  name: data.name || '',
42
+ nickname: data.nickname || '',
41
43
  botName: data.botName || '',
42
44
  preferences: data.preferences || [],
43
45
  facts: data.facts || [],
@@ -56,6 +58,7 @@ function loadMemory(botId) {
56
58
  } catch {
57
59
  return {
58
60
  name: '',
61
+ nickname: '',
59
62
  botName: '',
60
63
  preferences: [],
61
64
  facts: [],
@@ -83,6 +86,8 @@ function addMemoryEntry(botId, key, value) {
83
86
 
84
87
  if (key === 'name') {
85
88
  memory.name = value;
89
+ } else if (key === 'nickname') {
90
+ memory.nickname = value;
86
91
  } else if (key === 'botName') {
87
92
  memory.botName = value;
88
93
  } else if (key === 'preference') {
@@ -202,29 +207,35 @@ function getMemoryPrompt(botId) {
202
207
 
203
208
  // Safe defaults for all fields
204
209
  const name = memory.name || '';
210
+ const nickname = memory.nickname || '';
205
211
  const botName = memory.botName || '';
206
212
  const preferences = memory.preferences || [];
207
213
  const facts = memory.facts || [];
208
214
 
209
- if (!name && !botName && preferences.length === 0 && facts.length === 0) {
210
- return '';
211
- }
212
-
213
215
  const parts = [];
214
216
 
215
- // Add bot name if set
217
+ // Add bot name if set (MUST be before empty check)
216
218
  if (botName) {
217
219
  parts.push(`Your name is ${botName}.`);
218
220
  }
219
221
 
222
+ // Check if there's any content to add
223
+ if (!name && !nickname && !botName && preferences.length === 0 && facts.length === 0) {
224
+ return '';
225
+ }
226
+
220
227
  // Add user memory section
221
- if (name || preferences.length > 0 || facts.length > 0) {
228
+ if (name || nickname || preferences.length > 0 || facts.length > 0) {
222
229
  parts.push('## Kullanıcı Hafızası');
223
230
 
224
231
  if (name) {
225
232
  parts.push(`İsim: ${name}`);
226
233
  }
227
234
 
235
+ if (nickname) {
236
+ parts.push(`Lakap: ${nickname}`);
237
+ }
238
+
228
239
  if (preferences.length > 0) {
229
240
  const sorted = preferences.sort((a, b) => b.score - a.score);
230
241
  parts.push(`Tercihler: ${sorted.map(p => p.value).join(', ')}`);
@@ -235,8 +246,6 @@ function getMemoryPrompt(botId) {
235
246
  const sorted = facts.sort((a, b) => b.score - a.score);
236
247
  const topFacts = sorted.slice(0, 15);
237
248
 
238
- console.log('[MEMORY] Facts count:', facts.length, '→ showing:', topFacts.length);
239
-
240
249
  parts.push(`Bilgiler: ${topFacts.map(f => f.value).join(', ')}`);
241
250
 
242
251
  if (facts.length > 15) {
@@ -246,7 +255,6 @@ function getMemoryPrompt(botId) {
246
255
  }
247
256
 
248
257
  const prompt = parts.join('\n');
249
- console.log('[MEMORY] Prompt length:', prompt.length, 'chars, ~', Math.round(prompt.length / 4), 'tokens');
250
258
 
251
259
  return prompt;
252
260
  }