import express from 'express'; import cors from 'cors'; const app = express(); const PORT = process.env.PROXY_PORT || 5374; const DEBUG = process.env.REACT_APP_DEBUG_MODE === 'true'; function debugLog(...args) { if (DEBUG) console.log(...args); } app.use(cors()); // Increase payload limit to 10MB (default is 100kb) app.use(express.json({ limit: '10mb' })); // Proxy endpoint for Claude API app.post('/api/claude', async (req, res) => { try { const { messages, apiKey, model, maxTokens } = req.body; debugLog('=== Proxy received request ==='); debugLog('Model:', model); debugLog('Max tokens:', maxTokens); debugLog('Messages count:', messages?.length); const requestBody = { model: model, max_tokens: maxTokens, messages: messages, ...(req.body.tools && { tools: req.body.tools }) }; debugLog('Request body:', JSON.stringify(requestBody, null, 2)); const response = await fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey, 'anthropic-version': '2023-06-01' }, body: JSON.stringify(requestBody) }); debugLog('Claude API response status:', response.status); if (!response.ok) { const error = await response.text(); console.error('Claude API error:', error); return res.status(response.status).json({ error }); } const data = await response.json(); debugLog('Claude API success, response content length:', data.content?.[0]?.text?.length); debugLog('Token usage:', data.usage); res.json(data); } catch (error) { console.error('Proxy error:', error); res.status(500).json({ error: error.message }); } }); // Proxy endpoint for scraping web pages (avoids CORS issues) app.get('/api/scrape', async (req, res) => { try { const { url } = req.query; if (!url) { return res.status(400).json({ error: 'Missing url query parameter' }); } debugLog('=== Scrape proxy request ==='); debugLog('URL:', url); const response = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', } }); if (!response.ok) { console.error('Scrape failed:', response.status, response.statusText); return res.status(response.status).json({ error: `Failed to fetch: ${response.status} ${response.statusText}` }); } const html = await response.text(); debugLog('Scraped HTML length:', html.length); res.type('text/html').send(html); } catch (error) { console.error('Scrape proxy error:', error); res.status(500).json({ error: error.message }); } }); app.listen(PORT, () => { console.log(`Proxy server running on http://localhost:${PORT}`); });