navada-edge-cli 2.2.2 → 2.4.0
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/lib/agent.js +68 -11
- package/lib/cli.js +4 -5
- package/package.json +1 -1
package/lib/agent.js
CHANGED
|
@@ -95,7 +95,52 @@ const localTools = {
|
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
// ---------------------------------------------------------------------------
|
|
98
|
-
//
|
|
98
|
+
// Free tier — proxied through NAVADA Edge Dashboard (key stays on ASUS)
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Dashboard proxy endpoints — tries Cloudflare tunnel first, then direct
|
|
101
|
+
// Users on Tailscale hit the direct IP; public users hit the tunnel
|
|
102
|
+
const FREE_TIER_ENDPOINTS = [
|
|
103
|
+
'http://100.88.118.128:7900/api/v1/chat', // Direct (fastest for Tailscale users)
|
|
104
|
+
'https://api.navada-edge-server.uk/api/v1/chat', // Cloudflare tunnel (public fallback)
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
async function callFreeTier(messages) {
|
|
108
|
+
// Try each endpoint (public first, then Tailscale)
|
|
109
|
+
for (const endpoint of FREE_TIER_ENDPOINTS) {
|
|
110
|
+
try {
|
|
111
|
+
const r = await navada.request(endpoint, {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
body: { messages },
|
|
114
|
+
timeout: 30000,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (r.status === 429) {
|
|
118
|
+
return {
|
|
119
|
+
content: `Free tier limit reached (30 requests/min).
|
|
120
|
+
|
|
121
|
+
To continue, add your own API key:
|
|
122
|
+
/login sk-ant-your-anthropic-key (full agent with tool use)
|
|
123
|
+
/login sk-your-openai-key (GPT-4o)
|
|
124
|
+
/init hfToken hf_your_token (Qwen Coder — FREE unlimited)
|
|
125
|
+
|
|
126
|
+
Or wait a minute and try again.`,
|
|
127
|
+
isRateLimit: true,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (r.status === 200) {
|
|
132
|
+
return { content: r.data?.choices?.[0]?.message?.content || '', isRateLimit: false };
|
|
133
|
+
}
|
|
134
|
+
} catch {
|
|
135
|
+
continue; // Try next endpoint
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
throw new Error('Free tier unavailable. Add your own key: /login <key>');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// Anthropic Claude API — conversational agent with tool use
|
|
99
144
|
// ---------------------------------------------------------------------------
|
|
100
145
|
async function chat(userMessage, conversationHistory = []) {
|
|
101
146
|
// Smart key detection — check all possible locations
|
|
@@ -110,8 +155,9 @@ async function chat(userMessage, conversationHistory = []) {
|
|
|
110
155
|
|| (apiKey && apiKey.startsWith('sk-ant') ? apiKey : '')
|
|
111
156
|
|| '';
|
|
112
157
|
|
|
158
|
+
// No personal key — use Grok free tier
|
|
113
159
|
if (!effectiveKey) {
|
|
114
|
-
return
|
|
160
|
+
return grokChat(userMessage, conversationHistory);
|
|
115
161
|
}
|
|
116
162
|
|
|
117
163
|
const tools = [
|
|
@@ -273,8 +319,21 @@ async function executeTool(name, input) {
|
|
|
273
319
|
}
|
|
274
320
|
}
|
|
275
321
|
|
|
322
|
+
async function grokChat(userMessage, conversationHistory = []) {
|
|
323
|
+
const messages = [
|
|
324
|
+
...conversationHistory.slice(-20).map(m => ({
|
|
325
|
+
role: m.role,
|
|
326
|
+
content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),
|
|
327
|
+
})),
|
|
328
|
+
{ role: 'user', content: userMessage },
|
|
329
|
+
];
|
|
330
|
+
|
|
331
|
+
const result = await callFreeTier(messages);
|
|
332
|
+
return result.content || 'No response from free tier. Try /login <key> for full agent.';
|
|
333
|
+
}
|
|
334
|
+
|
|
276
335
|
async function fallbackChat(msg) {
|
|
277
|
-
// Try MCP → Qwen → OpenAI →
|
|
336
|
+
// Try MCP → Qwen → OpenAI → Grok free tier
|
|
278
337
|
if (navada.config.mcp) {
|
|
279
338
|
try {
|
|
280
339
|
const r = await navada.mcp.call('chat', { message: msg });
|
|
@@ -290,14 +349,12 @@ async function fallbackChat(msg) {
|
|
|
290
349
|
if (navada.config.openaiKey) {
|
|
291
350
|
try { return await navada.ai.openai.chat(msg); } catch {}
|
|
292
351
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
/commands still work without a key — try /help`;
|
|
352
|
+
// Grok is always available as the free fallback
|
|
353
|
+
try {
|
|
354
|
+
const result = await callFreeTier([{ role: 'user', content: msg }]);
|
|
355
|
+
return result.content;
|
|
356
|
+
} catch {}
|
|
357
|
+
return `All providers failed. Check your internet connection or try again.`;
|
|
301
358
|
}
|
|
302
359
|
|
|
303
360
|
// ---------------------------------------------------------------------------
|
package/lib/cli.js
CHANGED
|
@@ -92,11 +92,10 @@ async function run(argv) {
|
|
|
92
92
|
// Interactive mode — always start. User can /setup if needed.
|
|
93
93
|
showWelcome();
|
|
94
94
|
|
|
95
|
-
//
|
|
96
|
-
const
|
|
97
|
-
if (!
|
|
98
|
-
console.log(ui.
|
|
99
|
-
console.log(ui.dim('You can still use /commands. Natural chat requires an API key.'));
|
|
95
|
+
// Show tier info
|
|
96
|
+
const hasPersonalKey = config.getApiKey() || config.get('anthropicKey') || process.env.ANTHROPIC_API_KEY;
|
|
97
|
+
if (!hasPersonalKey) {
|
|
98
|
+
console.log(ui.dim('Free tier active (Grok). /login <your-key> for full agent with tool use.'));
|
|
100
99
|
console.log('');
|
|
101
100
|
}
|
|
102
101
|
|
package/package.json
CHANGED