import { OpenRouterClient } from "../../lib/openrouter"; import { TradingGraph } from "../../agents/tradingGraph"; import { db } from "../../lib/db.server"; export async function action({ request }: { request: Request }) { console.log("[analyze] Request received:", request.method, request.url); const body = await request.json(); console.log("[analyze] Request body:", JSON.stringify(body)); const ticker = body.ticker?.toUpperCase(); const date = body.date || new Date().toISOString().split("T")[0]; if (!ticker) { console.log("[analyze] Error: ticker missing"); return Response.json({ error: "ticker is required" }, { status: 400 }); } const apiKey = process.env.OPENROUTER_API_KEY; console.log("[analyze] API key configured:", !!apiKey, apiKey?.substring(0, 10) + "..."); if (!apiKey || apiKey === "your_openrouter_api_key_here") { console.log("[analyze] Using mock mode"); const mockDecision = { action: "hold" as const, confidence: 0.75, reasoning: `${ticker} analysis - Mock mode: positive momentum detected with neutral technical signals`, agentSignals: [ { agent: "fundamentals" as const, signal: "bullish" as const, confidence: 0.7, reasoning: "Strong fundamentals with positive earnings outlook", timestamp: new Date().toISOString(), }, { agent: "technical" as const, signal: "neutral" as const, confidence: 0.6, reasoning: "Mixed technical indicators", timestamp: new Date().toISOString(), }, ], debateRounds: [ { bullishView: "Bullish case supported by fundamentals and momentum", bearishView: "Bearish case from mixed technical signals", researcher: "bullish" as const, }, ], }; console.log("[analyze] Returning mock decision"); return Response.json(mockDecision); } const client = new OpenRouterClient(apiKey); const graph = new TradingGraph(client); const input = { financialData: `Financial data for ${ticker} as of ${date}`, technicalData: { prices: [100, 102, 101, 103, 105], sma: 102, ema: 103, rsi: 55, macd: 0.5, }, sentimentData: { headlines: [`${ticker} showing positive momentum`], source: "news" as const, }, }; try { console.log("[analyze] Running trading graph..."); if (body.background) { // Run in background: start async propagation and return 202 immediately (async () => { try { const decision = await graph.propagate(ticker, input); console.log("[analyze] Background decision received:", JSON.stringify(decision)); // persist last decision to DB await db.stock.upsert({ where: { ticker }, create: { ticker, lastDecision: decision.action as string, lastExplanation: (decision as any).reasoning || null, lastExecutionPlan: decision.executionPlan ? JSON.stringify(decision.executionPlan) : null, }, update: { lastDecision: decision.action as string, lastExplanation: (decision as any).reasoning || null, lastExecutionPlan: decision.executionPlan ? JSON.stringify(decision.executionPlan) : null, }, }); console.log("[analyze] Background decision saved to DB for", ticker); } catch (bgErr) { console.error("[analyze] Background error:", bgErr); } })(); return Response.json({ status: "queued" }, { status: 202 }); } const decision = await graph.propagate(ticker, input); console.log("[analyze] Decision received:", JSON.stringify(decision)); return Response.json(decision); } catch (error) { const message = error instanceof Error ? error.message : "Unknown error"; console.error("[analyze] Error:", error); return Response.json({ error: message }, { status: 500 }); } }