{"repo": "alexb-os/modo-parcial", "files": {"src/lib/ai/deepseek.ts": {"21ab2df442fcdfffdcb7b15c100c3ed653d8cc12": {"t": 1785745570.6435492, "n": 2009, "h": "c1ce7140169fdae6", "c": "export type ChatMessage = {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n};\n\nexport type DeepSeekOptions = {\n json?: boolean;\n temperature?: number;\n maxTokens?: number;\n timeoutMs?: number;\n};\n\nconst DEEPSEEK_URL = \"https://api.deepseek.com/chat/completions\";\nconst MODEL = \"deepseek-chat\";\n\nexport function isDeepSeekConfigured(): boolean {\n return Boolean(process.env.DEEPSEEK_API_KEY);\n}\n\n/**\n * Llama a la API de DeepSeek (compatible con el formato OpenAI Chat Completions).\n * Lanza si no hay API key o si la respuesta no es exitosa, para que el route handler\n * pueda caer al motor deterministico (`buildRescuePlan`).\n */\nexport async function callDeepSeek(\n messages: ChatMessage[],\n options: DeepSeekOptions = {},\n): Promise {\n const apiKey = process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n throw new Error(\"DEEPSEEK_API_KEY no configurada\");\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 12_000);\n\n try {\n const response = await fetch(DEEPSEEK_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: MODEL,\n messages,\n temperature: options.temperature ?? 0.4,\n max_tokens: options.maxTokens ?? 900,\n ...(options.json ? { response_format: { type: \"json_object\" } } : {}),\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const detail = await response.text().catch(() => \"\");\n throw new Error(`DeepSeek HTTP ${response.status}: ${detail.slice(0, 200)}`);\n }\n\n const data = (await response.json()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n throw new Error(\"DeepSeek devolvio una respuesta vacia\");\n }\n return content;\n } finally {\n clearTimeout(timeout);\n }\n}\n"}, "05185a057761b806877d3b2fcc14d627bc14098d": {"t": 1785754347.889657, "n": 2009, "h": "c1ce7140169fdae6", "c": "export type ChatMessage = {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n};\n\nexport type DeepSeekOptions = {\n json?: boolean;\n temperature?: number;\n maxTokens?: number;\n timeoutMs?: number;\n};\n\nconst DEEPSEEK_URL = \"https://api.deepseek.com/chat/completions\";\nconst MODEL = \"deepseek-chat\";\n\nexport function isDeepSeekConfigured(): boolean {\n return Boolean(process.env.DEEPSEEK_API_KEY);\n}\n\n/**\n * Llama a la API de DeepSeek (compatible con el formato OpenAI Chat Completions).\n * Lanza si no hay API key o si la respuesta no es exitosa, para que el route handler\n * pueda caer al motor deterministico (`buildRescuePlan`).\n */\nexport async function callDeepSeek(\n messages: ChatMessage[],\n options: DeepSeekOptions = {},\n): Promise {\n const apiKey = process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n throw new Error(\"DEEPSEEK_API_KEY no configurada\");\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 12_000);\n\n try {\n const response = await fetch(DEEPSEEK_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: MODEL,\n messages,\n temperature: options.temperature ?? 0.4,\n max_tokens: options.maxTokens ?? 900,\n ...(options.json ? { response_format: { type: \"json_object\" } } : {}),\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const detail = await response.text().catch(() => \"\");\n throw new Error(`DeepSeek HTTP ${response.status}: ${detail.slice(0, 200)}`);\n }\n\n const data = (await response.json()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n throw new Error(\"DeepSeek devolvio una respuesta vacia\");\n }\n return content;\n } finally {\n clearTimeout(timeout);\n }\n}\n"}}}}