From fd6b2cc28e84adfd271326b8857a04b44ee099b5 Mon Sep 17 00:00:00 2001 From: Kurdistan Tech Ministry Date: Sun, 28 Jun 2026 11:16:24 -0700 Subject: [PATCH] feat(bot): Groq as primary AI provider, Claude fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Telegram assistant now answers via Groq (free) first and falls back to Claude when ANTHROPIC has credit. Keys come from env (GROQ_API_KEY / ANTHROPIC_API_KEY) — no secrets in source. Wallet/p2p logic untouched. --- package.json | 2 +- src/version.json | 6 +- supabase/functions/telegram-bot/index.ts | 74 +++++++++++++++++------- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 62d4d71..6649ee6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pezkuwi-telegram-miniapp", - "version": "1.0.235", + "version": "1.0.236", "type": "module", "description": "Pezkuwichain Telegram Mini App - Forum, Announcements, Rewards", "author": "Pezkuwichain Team", diff --git a/src/version.json b/src/version.json index 02890ed..681b084 100644 --- a/src/version.json +++ b/src/version.json @@ -1,5 +1,5 @@ { - "version": "1.0.233", - "buildTime": "2026-06-13T04:42:17.513Z", - "buildNumber": 1781325737513 + "version": "1.0.236", + "buildTime": "2026-06-28T18:16:24.919Z", + "buildNumber": 1782670584920 } diff --git a/supabase/functions/telegram-bot/index.ts b/supabase/functions/telegram-bot/index.ts index 02ec3e2..9f85203 100644 --- a/supabase/functions/telegram-bot/index.ts +++ b/supabase/functions/telegram-bot/index.ts @@ -26,6 +26,8 @@ const MINI_APP_URLS: Record = { }; const ANTHROPIC_API_KEY = Deno.env.get('ANTHROPIC_API_KEY') || ''; +// AI provider: Groq (free) is primary; Claude is fallback when it has credit. +const GROQ_API_KEY = Deno.env.get('GROQ_API_KEY') || ''; function getBotId(req: Request): string { const url = new URL(req.url); @@ -234,24 +236,59 @@ async function handleAIChat(token: string, chatId: number, userMessage: string, }); try { - const response = await fetch('https://api.anthropic.com/v1/messages', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'x-api-key': ANTHROPIC_API_KEY, - 'anthropic-version': '2023-06-01', - }, - body: JSON.stringify({ - model: 'claude-sonnet-4-20250514', - max_tokens: 1024, - system: CLAUDE_SYSTEM_PROMPT, - messages: [{ role: 'user', content: userMessage }], - }), - }); + // Primary provider: Groq (free). Fallback: Claude when it has credit. + let aiReply: string | null = null; - if (!response.ok) { - const errorText = await response.text(); - console.error('[AI] Claude API error:', response.status, errorText); + if (GROQ_API_KEY) { + try { + const gr = await fetch('https://api.groq.com/openai/v1/chat/completions', { + method: 'POST', + headers: { Authorization: 'Bearer ' + GROQ_API_KEY, 'Content-Type': 'application/json' }, + body: JSON.stringify({ + model: 'llama-3.3-70b-versatile', + temperature: 0.3, + max_tokens: 900, + messages: [ + { role: 'system', content: CLAUDE_SYSTEM_PROMPT }, + { role: 'user', content: userMessage }, + ], + }), + }); + if (gr.ok) { + const gd = await gr.json(); + aiReply = gd.choices?.[0]?.message?.content || null; + } else { + console.error('[AI] Groq error:', gr.status, await gr.text()); + } + } catch (e) { + console.error('[AI] Groq exception:', e); + } + } + + if (!aiReply && ANTHROPIC_API_KEY) { + const response = await fetch('https://api.anthropic.com/v1/messages', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': ANTHROPIC_API_KEY, + 'anthropic-version': '2023-06-01', + }, + body: JSON.stringify({ + model: 'claude-sonnet-4-20250514', + max_tokens: 1024, + system: CLAUDE_SYSTEM_PROMPT, + messages: [{ role: 'user', content: userMessage }], + }), + }); + if (response.ok) { + const result = await response.json(); + aiReply = result.content?.[0]?.text || null; + } else { + console.error('[AI] Claude API error:', response.status, await response.text()); + } + } + + if (!aiReply) { await sendTelegramRequest(token, 'sendMessage', { chat_id: chatId, text: 'Sorry, I could not process your question right now. Please try again.', @@ -259,9 +296,6 @@ async function handleAIChat(token: string, chatId: number, userMessage: string, return; } - const result = await response.json(); - const aiReply = result.content?.[0]?.text || 'No response generated.'; - // Telegram message limit is 4096 chars if (aiReply.length <= 4096) { await sendTelegramRequest(token, 'sendMessage', {