navada-edge-cli 3.4.0 → 3.4.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.
Files changed (2) hide show
  1. package/lib/agent.js +76 -12
  2. package/package.json +1 -1
package/lib/agent.js CHANGED
@@ -32,6 +32,8 @@ You also connect to the NAVADA Edge Network (4 nodes via Tailscale VPN):
32
32
  - send_email / generate_image: communications and AI image generation
33
33
  - founder_info: information about Lee Akpareva, the creator of NAVADA
34
34
  When users ask you to DO something — DO IT. Use write_file to create files. Use shell to run commands. Never say "I can't" when you have a tool for it.
35
+ When asked to generate diagrams — use write_file to create Mermaid (.mmd), SVG, or HTML files. You can also use python_exec with matplotlib/graphviz for complex diagrams.
36
+ When asked to create, edit, or delete files — use the file tools directly. You are a terminal agent with FULL access.
35
37
  Keep responses short. Code blocks when needed. No fluff.`,
36
38
  founder: {
37
39
  name: 'Leslie (Lee) Akpareva',
@@ -650,13 +652,16 @@ function streamGemini(key, messages, model = 'gemini-2.0-flash') {
650
652
 
651
653
  function openAITools() {
652
654
  const defs = [
653
- { name: 'shell', description: 'Execute a shell command on the user\'s machine', parameters: { type: 'object', properties: { command: { type: 'string' } }, required: ['command'] } },
654
- { name: 'read_file', description: 'Read a file', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } },
655
- { name: 'write_file', description: 'Write to a file', parameters: { type: 'object', properties: { path: { type: 'string' }, content: { type: 'string' } }, required: ['path', 'content'] } },
656
- { name: 'list_files', description: 'List directory contents', parameters: { type: 'object', properties: { path: { type: 'string' } } } },
657
- { name: 'system_info', description: 'Get system info (CPU, RAM, OS)', parameters: { type: 'object', properties: {} } },
658
- { name: 'python_exec', description: 'Execute Python code', parameters: { type: 'object', properties: { code: { type: 'string' } }, required: ['code'] } },
659
- { name: 'python_pip', description: 'Install a Python package', parameters: { type: 'object', properties: { package: { type: 'string' } }, required: ['package'] } },
655
+ { name: 'shell', description: 'Execute a shell command on the user\'s machine. Use for: file operations, git, npm, docker, system commands, creating directories, running scripts.', parameters: { type: 'object', properties: { command: { type: 'string', description: 'The shell command to run' } }, required: ['command'] } },
656
+ { name: 'read_file', description: 'Read the contents of a file on the user\'s machine.', parameters: { type: 'object', properties: { path: { type: 'string', description: 'Absolute or relative file path' } }, required: ['path'] } },
657
+ { name: 'write_file', description: 'Write content to a file. Creates parent directories if needed. Use for creating new files, scripts, configs, diagrams (Mermaid, SVG, HTML), code files.', parameters: { type: 'object', properties: { path: { type: 'string', description: 'File path to write' }, content: { type: 'string', description: 'Full content to write to the file' } }, required: ['path', 'content'] } },
658
+ { name: 'list_files', description: 'List files and directories.', parameters: { type: 'object', properties: { path: { type: 'string', description: 'Directory path (default: current dir)' } } } },
659
+ { name: 'system_info', description: 'Get local system information (CPU, RAM, disk, OS, hostname).', parameters: { type: 'object', properties: {} } },
660
+ { name: 'python_exec', description: 'Execute Python code inline. Use for data analysis, calculations, generating content, processing files, ML tasks.', parameters: { type: 'object', properties: { code: { type: 'string', description: 'Python code to execute' } }, required: ['code'] } },
661
+ { name: 'python_pip', description: 'Install a Python package via pip.', parameters: { type: 'object', properties: { package: { type: 'string', description: 'Package name' } }, required: ['package'] } },
662
+ { name: 'python_script', description: 'Run a Python script file.', parameters: { type: 'object', properties: { path: { type: 'string', description: 'Path to .py file' } }, required: ['path'] } },
663
+ { name: 'sandbox_run', description: 'Run code in an isolated sandbox with syntax highlighting. Supports javascript, python, typescript.', parameters: { type: 'object', properties: { code: { type: 'string' }, language: { type: 'string', description: 'javascript, python, or typescript' } }, required: ['code'] } },
664
+ { name: 'founder_info', description: 'Get information about Lee Akpareva, founder of NAVADA Edge.', parameters: { type: 'object', properties: {} } },
660
665
  ];
661
666
  return defs.map(d => ({ type: 'function', function: d }));
662
667
  }
@@ -997,13 +1002,72 @@ async function grokChat(userMessage, conversationHistory = []) {
997
1002
  { role: 'user', content: userMessage },
998
1003
  ];
999
1004
 
1000
- // Try streaming first
1001
- const result = await callFreeTier(messages, true);
1002
- if (result.streamed) {
1003
- // Already printed to stdout, return for history
1005
+ // Send tools with the request — free tier now supports tool use
1006
+ const tools = openAITools();
1007
+ const endpoint = FREE_TIER_ENDPOINTS[0];
1008
+
1009
+ // Non-streaming request with tools (streaming + tools is complex, use non-streaming for tool calls)
1010
+ let response;
1011
+ try {
1012
+ const r = await navada.request(endpoint, {
1013
+ method: 'POST',
1014
+ body: { messages, tools },
1015
+ timeout: 120000,
1016
+ });
1017
+
1018
+ if (r.status === 429) {
1019
+ return `Free tier limit reached. /login <key> for unlimited access.`;
1020
+ }
1021
+ if (r.status !== 200) {
1022
+ // Fall back to streaming without tools
1023
+ const result = await callFreeTier(messages, true);
1024
+ return result.content || 'No response from free tier.';
1025
+ }
1026
+
1027
+ rateTracker.record();
1028
+ response = r.data;
1029
+ } catch {
1030
+ // Network error — try streaming fallback
1031
+ const result = await callFreeTier(messages, true);
1004
1032
  return result.content || 'No response from free tier. Try /login <key> for full agent.';
1005
1033
  }
1006
- return result.content || 'No response from free tier. Try /login <key> for full agent.';
1034
+
1035
+ // Handle tool use loop (same as OpenAI path)
1036
+ let iterations = 0;
1037
+ while (response?.choices?.[0]?.finish_reason === 'tool_calls' && iterations < 10) {
1038
+ iterations++;
1039
+ const toolCalls = response.choices[0].message.tool_calls || [];
1040
+ if (toolCalls.length === 0) break;
1041
+
1042
+ const toolResults = [];
1043
+ for (const tc of toolCalls) {
1044
+ let input;
1045
+ try { input = JSON.parse(tc.function.arguments); } catch { input = {}; }
1046
+ console.log(ui.dim(` [${tc.function.name}] ${JSON.stringify(input).slice(0, 80)}`));
1047
+ const result = await executeTool(tc.function.name, input);
1048
+ toolResults.push({ role: 'tool', tool_call_id: tc.id, content: typeof result === 'string' ? result : JSON.stringify(result) });
1049
+ }
1050
+
1051
+ // Add assistant message with tool_calls + results, then call again
1052
+ messages.push({ role: 'assistant', content: response.choices[0].message.content || null, tool_calls: toolCalls });
1053
+ messages.push(...toolResults);
1054
+
1055
+ try {
1056
+ const r = await navada.request(endpoint, {
1057
+ method: 'POST',
1058
+ body: { messages, tools },
1059
+ timeout: 120000,
1060
+ });
1061
+ if (r.status !== 200) break;
1062
+ rateTracker.record();
1063
+ response = r.data;
1064
+ } catch { break; }
1065
+ }
1066
+
1067
+ // Extract final text
1068
+ const content = response?.choices?.[0]?.message?.content || '';
1069
+ if (content) console.log(` ${content}`);
1070
+ return content || 'No response.';
1007
1071
  }
1008
1072
 
1009
1073
  async function fallbackChat(msg) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navada-edge-cli",
3
- "version": "3.4.0",
3
+ "version": "3.4.1",
4
4
  "description": "Interactive CLI for the NAVADA Edge Network — explore nodes, agents, Cloudflare, AI, Docker, and MCP from your terminal",
5
5
  "main": "lib/cli.js",
6
6
  "bin": {