import { defineConfig, loadEnv, type Plugin } from "vite"; import react from "@vitejs/plugin-react"; const SYSTEM_PROMPT = `你是一名数字脑健康表现报告助手。根据用户完成游戏时产生的结构化数据,生成通俗、克制、非医疗化的中文报告。 必须遵守: 1. 不诊断疾病,不使用确诊、患病、痴呆、障碍等医疗结论; 2. 只描述本次任务表现,明确设备、环境、熟悉程度可能影响结果;禁止使用“提示存在问题或挑战”“异常”“受损”等暗示医学结论的说法; 3. 建议必须低风险、可执行,不推荐药物或医疗处置; 4. 优先使用“本次反应相对偏慢”“注意表现有波动”“容易遗漏部分信息”“仍有提升空间”等表达; 5. 仅输出合法 JSON,不要 Markdown。 JSON 结构:{"summary":"80字内总结","strength":"60字内相对优势","opportunity":"60字内提升空间","recommendations":["建议1","建议2","建议3"]}`; function localDeepSeekApi(apiKey: string): Plugin { return { name: "braincheck-deepseek-local-api", configureServer(server) { server.middlewares.use("/api/analyze", async (request, response) => { if (request.method !== "POST") { response.statusCode = 405; response.end("Method not allowed"); return; } if (!apiKey) { response.statusCode = 503; response.setHeader("content-type", "application/json"); response.end(JSON.stringify({ error: "DEEPSEEK_API_KEY is not configured" })); return; } try { let raw = ""; for await (const chunk of request) raw += chunk; const assessment = JSON.parse(raw || "{}"); const upstream = await fetch("https://api.deepseek.com/chat/completions", { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${apiKey}` }, body: JSON.stringify({ model: "deepseek-chat", temperature: 0.35, response_format: { type: "json_object" }, messages: [ { role: "system", content: SYSTEM_PROMPT }, { role: "user", content: JSON.stringify({ profile: assessment.profile, metrics: assessment.metrics, eventCount: assessment.events?.length ?? 0 }) }, ], }), signal: AbortSignal.timeout(15000), }); if (!upstream.ok) throw new Error(`DeepSeek returned ${upstream.status}`); const payload = await upstream.json(); const content = payload?.choices?.[0]?.message?.content; if (!content) throw new Error("DeepSeek returned an empty response"); const rawReport = JSON.parse(content.replace(/^```json\s*|\s*```$/g, "")); const parsed = { summary: String(rawReport.summary || "本次四项任务已经完成。"), strength: String(rawReport.strength || "部分任务表现相对稳定。"), opportunity: String(rawReport.opportunity || "仍有可以通过规律练习提升的空间。"), recommendations: Array.isArray(rawReport.recommendations) ? rawReport.recommendations.slice(0, 3).map(String) : [], }; response.statusCode = 200; response.setHeader("content-type", "application/json; charset=utf-8"); response.end(JSON.stringify(parsed)); } catch (error) { response.statusCode = 502; response.setHeader("content-type", "application/json"); response.end(JSON.stringify({ error: error instanceof Error ? error.message : "AI request failed" })); } }); }, }; } export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ""); return { build: { outDir: "dist/client" }, server: { host: "0.0.0.0", allowedHosts: ["terminal.local"] }, plugins: [react(), localDeepSeekApi(env.DEEPSEEK_API_KEY)], }; });