import { Router } from "express"; import { getSession, addMessage } from "../services/sessionStore.js"; import { trackUsage, getUsageSummary, formatCost, getSessionUsage } from "../services/usageTracker.js"; import { getCloudflareAccountId, getCloudflareApiToken } from "../services/providerConfig.js"; import { getCloudflareModel } from "../services/ChatCloudflare.js"; import { buildLangChainMessages, aiMessageToClaudeResponse } from "../services/langchainModels.js"; const router = Router(); router.post("/*path", async (req, res) => { const requestStart = Date.now(); console.log(`[Cloudflare API] ========== REQUEST START ==========`); const accountId = getCloudflareAccountId(); const apiToken = getCloudflareApiToken(); if (!accountId) { console.error(`[Cloudflare API] ERROR: Account ID not configured`); return res.status(500).json({ error: "Cloudflare account ID not configured" }); } if (!apiToken) { console.error(`[Cloudflare API] ERROR: API token not configured`); return res.status(500).json({ error: "Cloudflare API token not configured" }); } const { sessionId, model: modelId, system: systemPrompt, messages } = req.body; console.log(`[Cloudflare API] Session ID: ${sessionId || 'none'}`); console.log(`[Cloudflare API] Model: ${modelId}`); console.log(`[Cloudflare API] Messages count: ${messages?.length || 0}`); try { // Get LangChain-compatible Cloudflare model with tools bound const model = getCloudflareModel(modelId); // Build messages with entity context and history const langChainMessages = buildLangChainMessages( sessionId, messages, systemPrompt ); console.log(`[Cloudflare API] Sending request via LangChain ChatCloudflare...`); const fetchStart = Date.now(); // Invoke model const response = await model.invoke(langChainMessages); const fetchDuration = Date.now() - fetchStart; console.log(`[Cloudflare API] Response received in ${fetchDuration}ms`); // Convert to Claude API format for client compatibility const data = aiMessageToClaudeResponse(response, modelId); console.log(`[Cloudflare API] Response converted. Stop reason: ${data.stop_reason}, content blocks: ${data.content?.length || 0}`); // Track and log token usage if (data.usage) { const userMessage = messages?.[messages.length - 1]; const inputText = typeof userMessage?.content === 'string' ? userMessage.content : null; const outputText = data.content ?.filter(c => c.type === 'text') .map(c => c.text) .join('\n') || null; const toolCalls = data.content ?.filter(c => c.type === 'tool_use') .map(c => ({ name: c.name, input: c.input })) || []; const usageRecord = trackUsage(sessionId, modelId, data.usage, { inputText, outputText, toolCalls }); console.log(`[Cloudflare API] REQUEST USAGE: ${getUsageSummary(usageRecord)}`); if (sessionId) { const sessionStats = getSessionUsage(sessionId); if (sessionStats) { console.log(`[Cloudflare API] SESSION TOTALS (${sessionStats.requestCount} requests):`); console.log(`[Cloudflare API] Total input: ${sessionStats.totalInputTokens} tokens`); console.log(`[Cloudflare API] Total output: ${sessionStats.totalOutputTokens} tokens`); console.log(`[Cloudflare API] Total cost: ${formatCost(sessionStats.totalCost)}`); } } } // Store messages to session if (sessionId && data.content) { const session = getSession(sessionId); if (session) { const userMessage = messages?.[messages.length - 1]; if (userMessage && userMessage.role === 'user' && typeof userMessage.content === 'string') { addMessage(sessionId, { role: 'user', content: userMessage.content }); console.log(`[Cloudflare API] Stored user message to session`); } const assistantContent = data.content .filter(c => c.type === 'text') .map(c => c.text) .join('\n'); if (assistantContent) { addMessage(sessionId, { role: 'assistant', content: assistantContent }); console.log(`[Cloudflare API] Stored assistant response to session (${assistantContent.length} chars)`); } } } const totalDuration = Date.now() - requestStart; console.log(`[Cloudflare API] ========== REQUEST COMPLETE (${totalDuration}ms) ==========`); res.json(data); } catch (error) { const totalDuration = Date.now() - requestStart; console.error(`[Cloudflare API] ========== REQUEST FAILED (${totalDuration}ms) ==========`); console.error(`[Cloudflare API] Error:`, error); console.error(`[Cloudflare API] Error message:`, error.message); res.status(500).json({ error: "Failed to call Cloudflare API", details: error.message }); } }); export default router;