natureco-cli 2.11.2 → 2.11.4

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.11.2",
3
+ "version": "2.11.4",
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.11.2</div>
214
+ <div class="version-badge" id="version-badge">v2.11.4</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.11.2',
344
+ version: 'v2.11.4',
345
345
  bots: cfg.bots || [],
346
346
  telegramToken: cfg.telegramToken || null,
347
347
  whatsappConnected: cfg.whatsappConnected || false,
@@ -138,7 +138,7 @@ async function startGateway() {
138
138
 
139
139
  async function runGatewayWorker() {
140
140
  // This runs in the background
141
- log('gateway', 'Starting NatureCo Gateway v2.11.2...', 'green');
141
+ log('gateway', 'Starting NatureCo Gateway v2.11.3...', 'green');
142
142
 
143
143
  // Load config
144
144
  const { getConfig } = require('../utils/config');
package/src/utils/api.js CHANGED
@@ -136,35 +136,67 @@ function getMcpTools() {
136
136
  return allTools;
137
137
  }
138
138
 
139
+ /**
140
+ * Normalize MCP tool schema for AI consumption
141
+ * Adds hints to number/integer parameters to prevent string conversion
142
+ */
143
+ function normalizeMcpToolSchema(tool) {
144
+ const schema = tool.inputSchema || tool.input_schema || {};
145
+
146
+ // Ensure properties exist
147
+ if (!schema.properties) return tool;
148
+
149
+ // Clone schema to avoid mutating original
150
+ const normalizedSchema = JSON.parse(JSON.stringify(schema));
151
+
152
+ // Groq sometimes sends strings for number params
153
+ // Add coercion hint to description
154
+ for (const [key, prop] of Object.entries(normalizedSchema.properties)) {
155
+ if (prop.type === 'number' || prop.type === 'integer') {
156
+ prop.description = (prop.description || '') + ' (must be a number, not a string)';
157
+ }
158
+ }
159
+
160
+ return { ...tool, inputSchema: normalizedSchema };
161
+ }
162
+
139
163
  /**
140
164
  * Coerce MCP tool parameters to match schema types
141
165
  */
142
166
  function coerceMcpParams(tool, params) {
143
- const schema = tool.inputSchema?.properties || tool.input_schema?.properties || {};
167
+ // GitHub MCP uses inputSchema, others may use input_schema
168
+ // Try all possible schema locations
169
+ const schema = tool.inputSchema?.properties ||
170
+ tool.input_schema?.properties ||
171
+ tool.parameters?.properties || // fallback
172
+ {};
173
+
174
+ // Debug: Show which schema format was found
175
+ console.log('[DEBUG] COERCE TOOL:', tool.name);
176
+ console.log('[DEBUG] COERCE SCHEMA SOURCE:',
177
+ tool.inputSchema?.properties ? 'inputSchema.properties' :
178
+ tool.input_schema?.properties ? 'input_schema.properties' :
179
+ tool.parameters?.properties ? 'parameters.properties' : 'NONE');
180
+ console.log('[DEBUG] COERCE SCHEMA:', JSON.stringify(schema).slice(0, 200));
181
+
144
182
  const coerced = { ...params };
145
183
 
146
184
  for (const [key, def] of Object.entries(schema)) {
147
185
  if (coerced[key] === undefined || coerced[key] === null) continue;
148
186
 
149
- // Coerce number
150
- if (def.type === 'number' && typeof coerced[key] === 'string') {
187
+ // Coerce number or integer
188
+ if ((def.type === 'number' || def.type === 'integer') && typeof coerced[key] === 'string') {
151
189
  const num = Number(coerced[key]);
152
190
  if (!isNaN(num)) {
153
191
  coerced[key] = num;
192
+ console.log('[DEBUG] COERCED', key, 'from string to number:', coerced[key]);
154
193
  }
155
194
  }
156
195
 
157
196
  // Coerce boolean
158
197
  if (def.type === 'boolean' && typeof coerced[key] === 'string') {
159
198
  coerced[key] = coerced[key] === 'true' || coerced[key] === '1';
160
- }
161
-
162
- // Coerce integer
163
- if (def.type === 'integer' && typeof coerced[key] === 'string') {
164
- const num = parseInt(coerced[key], 10);
165
- if (!isNaN(num)) {
166
- coerced[key] = num;
167
- }
199
+ console.log('[DEBUG] COERCED', key, 'from string to boolean:', coerced[key]);
168
200
  }
169
201
  }
170
202
 
@@ -328,8 +360,11 @@ function formatToolsForOpenAI() {
328
360
  const localTools = getToolDefinitions();
329
361
  const mcpTools = getMcpTools();
330
362
 
331
- // Combine local and MCP tools
332
- const allTools = [...localTools, ...mcpTools];
363
+ // Normalize MCP tools before combining
364
+ const normalizedMcpTools = mcpTools.map(tool => normalizeMcpToolSchema(tool));
365
+
366
+ // Combine local and normalized MCP tools
367
+ const allTools = [...localTools, ...normalizedMcpTools];
333
368
 
334
369
  return allTools.map(tool => ({
335
370
  type: 'function',
@@ -348,8 +383,11 @@ function formatToolsForAnthropic() {
348
383
  const localTools = getToolDefinitions();
349
384
  const mcpTools = getMcpTools();
350
385
 
351
- // Combine local and MCP tools
352
- const allTools = [...localTools, ...mcpTools];
386
+ // Normalize MCP tools before combining
387
+ const normalizedMcpTools = mcpTools.map(tool => normalizeMcpToolSchema(tool));
388
+
389
+ // Combine local and normalized MCP tools
390
+ const allTools = [...localTools, ...normalizedMcpTools];
353
391
 
354
392
  return allTools.map(tool => ({
355
393
  name: tool.name,
@@ -655,6 +693,10 @@ ENCODING: Tool results are base64 encoded with prefix [BASE64_ENCODED_RESULT]:.
655
693
  NEVER show the base64 string to the user. Decode it internally and present the data in a human-readable format.
656
694
  The encoding is for security - you must decode and interpret the results before responding.
657
695
 
696
+ CRITICAL: For MCP tools, ALWAYS send number/integer parameters as numbers (not strings).
697
+ Example: per_page must be 3 (not "3"), issue_number must be 5 (not "5"), limit must be 10 (not "10").
698
+ When you see a parameter with type "number" or "integer", convert string values to actual numbers before calling the tool.
699
+
658
700
  TOOL SELECTION GUIDE:
659
701
  - read_file: Use for .txt, .md, .json, .log, .csv files
660
702
  - bash with "cat file | head -100": Use for .sh, .py, .js, .ts, .env, config files, or any file with special characters