diff --git a/app/api/grok-debug/route.ts b/app/api/grok-debug/route.ts deleted file mode 100644 index 7215a74..0000000 --- a/app/api/grok-debug/route.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server'; - -const CRAWL_SERVICE_URL = 'http://127.0.0.1:8000'; - -export async function POST(req: NextRequest) { - try { - const body = await req.json(); - const { message, history } = body; - - console.log(`[Grok Debug API] Incoming body:`, JSON.stringify(body, null, 2)); - - const proxyPayload = { - message, - history: history || [], - cookies: body.cookies || null, - user_agent: body.userAgent || null - }; - console.log(`[Grok Debug API] Proxy payload:`, JSON.stringify(proxyPayload, null, 2)); - - const response = await fetch(`${CRAWL_SERVICE_URL}/grok/chat`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(proxyPayload), - }); - - if (!response.ok) { - const errorText = await response.text(); - console.error(`[Grok Debug API] Service error: ${response.status} ${errorText}`); - try { - // Try to parse detailed JSON error from FastAPI - const errorJson = JSON.parse(errorText); - return NextResponse.json(errorJson, { status: response.status }); - } catch { - // Fallback to text - return NextResponse.json( - { error: `Service error: ${response.status} - ${errorText}` }, - { status: response.status } - ); - } - } - - const data = await response.json(); - return NextResponse.json(data); - - } catch (error: any) { - console.error('[Grok Debug API] Internal error:', error); - return NextResponse.json( - { error: error.message || 'Internal Server Error' }, - { status: 500 } - ); - } -} diff --git a/app/api/grok-image/route.ts b/app/api/grok-image/route.ts deleted file mode 100644 index ed2838a..0000000 --- a/app/api/grok-image/route.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server'; - -/** - * Grok Image Generation API - * Uses xLmiler/grok2api_python backend with OpenAI-compatible format - */ -export async function POST(req: NextRequest) { - try { - const body = await req.json(); - const { prompt, numImages = 1, grokApiUrl, apiKey, sso } = body; - - if (!prompt) { - return NextResponse.json({ error: "Prompt is required" }, { status: 400 }); - } - - if (!grokApiUrl) { - return NextResponse.json({ error: "Grok API URL not configured" }, { status: 400 }); - } - - console.log(`[Grok Image] Generating ${numImages} image(s) for: "${prompt.substring(0, 50)}..."`); - - // Call xLmiler backend using OpenAI-compatible format - const headers: Record = { - 'Content-Type': 'application/json', - }; - - if (apiKey) { - headers['Authorization'] = `Bearer ${apiKey}`; - } - - const response = await fetch(`${grokApiUrl}/v1/chat/completions`, { - method: 'POST', - headers, - body: JSON.stringify({ - model: 'grok-4-imageGen', - messages: [ - { - role: 'user', - content: prompt - } - ], - // The xLmiler backend handles image generation via chat completions - }) - }); - - if (!response.ok) { - const errorText = await response.text(); - console.error('[Grok Image] Error:', response.status, errorText); - return NextResponse.json( - { error: `Grok API Error: ${response.status} - ${errorText.substring(0, 200)}` }, - { status: response.status } - ); - } - - const data = await response.json(); - console.log('[Grok Image] Response:', JSON.stringify(data, null, 2).substring(0, 500)); - - // Extract image URLs from the response - // xLmiler returns images in the message content or as markdown images - const content = data.choices?.[0]?.message?.content || ''; - - // Parse image URLs from markdown format: ![...](url) or direct URLs - const imageUrls: string[] = []; - - // Match markdown image syntax - const mdImageRegex = /!\[.*?\]\((https?:\/\/[^\s)]+)\)/g; - let match; - while ((match = mdImageRegex.exec(content)) !== null) { - imageUrls.push(match[1]); - } - - // Also match direct URLs - const urlRegex = /https:\/\/[^\s"'<>]+\.(png|jpg|jpeg|webp|gif)/gi; - while ((match = urlRegex.exec(content)) !== null) { - if (!imageUrls.includes(match[0])) { - imageUrls.push(match[0]); - } - } - - // Return images in our standard format - const images = imageUrls.slice(0, numImages).map(url => ({ - url, - prompt, - model: 'grok-4-imageGen' - })); - - if (images.length === 0) { - // Return the raw content for debugging - return NextResponse.json({ - error: "No images found in response", - rawContent: content.substring(0, 500) - }, { status: 500 }); - } - - return NextResponse.json({ images }); - - } catch (error: any) { - console.error('[Grok Image] Error:', error); - return NextResponse.json( - { error: error.message || 'Generation failed' }, - { status: 500 } - ); - } -} diff --git a/app/api/meta-chat/route.ts b/app/api/meta-chat/route.ts deleted file mode 100644 index 50ac189..0000000 --- a/app/api/meta-chat/route.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server'; -import { MetaAIClient } from '@/lib/providers/meta-client'; - -/** - * Meta AI Chat API - * Uses MetaAIClient directly (GraphQL-based) for Llama 3 chat - * No external Crawl4AI service needed - */ -export async function POST(req: NextRequest) { - try { - const body = await req.json(); - const { message, history, metaCookies } = body; - - if (!message) { - return NextResponse.json({ error: "Message is required" }, { status: 400 }); - } - - if (!metaCookies) { - return NextResponse.json( - { error: "Meta AI cookies required. Configure in Settings." }, - { status: 401 } - ); - } - - console.log(`[Meta Chat] Message: "${message.substring(0, 50)}..."`); - - // Use MetaAIClient to send chat message - // The Meta AI API is primarily designed for image generation, - // but we can use it for text chat by not prefixing with "Imagine" - const client = new MetaAIClient({ cookies: metaCookies }); - - // For chat, we need to initialize session and send via GraphQL - // Since MetaAIClient.generate() adds "Imagine" prefix for images, - // we'll create a direct chat method or adapt the prompt - - // Send message directly - the response will contain text, not images - const chatPrompt = message; // Don't add "Imagine" prefix for chat - - try { - // Use the internal sendPrompt mechanism via generate - // But we'll extract the text response instead of images - const response = await sendMetaChatMessage(client, chatPrompt, metaCookies); - return NextResponse.json({ response }); - } catch (chatError: any) { - // If the direct approach fails, provide helpful error - throw new Error(chatError.message || "Failed to get response from Meta AI"); - } - - } catch (error: any) { - console.error('[Meta Chat] Error:', error); - - const msg = error.message || ""; - const isAuthError = msg.includes("401") || msg.includes("cookies") || - msg.includes("expired") || msg.includes("Login"); - - return NextResponse.json( - { error: error.message || 'Internal Server Error' }, - { status: isAuthError ? 401 : 500 } - ); - } -} - -/** - * Send a chat message to Meta AI and extract text response - */ -async function sendMetaChatMessage(client: MetaAIClient, message: string, cookies: string): Promise { - const META_AI_BASE = "https://www.meta.ai"; - const GRAPHQL_ENDPOINT = `${META_AI_BASE}/api/graphql/`; - - // Normalize cookies from JSON array to string format - const normalizedCookies = normalizeCookies(cookies); - - // First we need to get session tokens - const sessionResponse = await fetch(META_AI_BASE, { - headers: { - "Cookie": normalizedCookies, - "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", - } - }); - const html = await sessionResponse.text(); - - // Extract LSD token - const lsdMatch = html.match(/\"LSD\",\[\],\{\"token\":\"([^\"]+)\"/) || - html.match(/\"lsd\":\"([^\"]+)\"/) || - html.match(/name=\"lsd\" value=\"([^\"]+)\"/); - const lsd = lsdMatch?.[1] || ''; - - // Extract access token - const tokenMatch = html.match(/\"accessToken\":\"([^\"]+)\"/); - const accessToken = tokenMatch?.[1]; - - if (html.includes('login_form') || html.includes('login_page')) { - throw new Error("Meta AI: Cookies expired. Please update in Settings."); - } - - // Send chat message - const variables = { - message: { - text: message, - content_type: "TEXT" - }, - source: "PDT_CHAT_INPUT", - external_message_id: Math.random().toString(36).substring(2) + Date.now().toString(36) - }; - - const body = new URLSearchParams({ - fb_api_caller_class: "RelayModern", - fb_api_req_friendly_name: "useAbraSendMessageMutation", - variables: JSON.stringify(variables), - doc_id: "7783822248314888", - ...(lsd && { lsd }), - }); - - const response = await fetch(GRAPHQL_ENDPOINT, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - "Cookie": normalizedCookies, - "Origin": META_AI_BASE, - "Referer": `${META_AI_BASE}/`, - "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", - "Sec-Fetch-Site": "same-origin", - "Sec-Fetch-Mode": "cors", - "Sec-Fetch-Dest": "empty", - "Accept": "application/json", - "Accept-Language": "en-US,en;q=0.9", - ...(accessToken && { "Authorization": `OAuth ${accessToken}` }) - }, - body: body.toString() - }); - - // Get response text first - const responseText = await response.text(); - - // Check if response is HTML (error page) - if (responseText.trim().startsWith('<') || responseText.includes(' "foo=bar; ..." - */ -function normalizeCookies(cookies: string): string { - if (!cookies) return ''; - - try { - const trimmed = cookies.trim(); - // Check if it's JSON array - if (trimmed.startsWith('[')) { - const parsed = JSON.parse(trimmed); - if (Array.isArray(parsed)) { - return parsed - .map((c: any) => `${c.name}=${c.value}`) - .join('; '); - } - } - // Check if it's JSON object with multiple arrays (merged cookies) - if (trimmed.startsWith('{')) { - const parsed = JSON.parse(trimmed); - // If it's an object, iterate values - const entries = Object.entries(parsed) - .map(([k, v]) => `${k}=${v}`) - .join('; '); - return entries; - } - } catch (e) { - // Not JSON, assume it's already a string format - } - - return cookies; -}