⚡ NVIDIA CYBER AI

/gi, ""); } // 渲染Markdown工具 function renderMd(text){ try{ return safeHtml(marked.parse(text)); }catch(e){ return text; } } function appendMsg(role, text) { const wrap = document.createElement("div"); wrap.className = "msg " + role; const bubble = document.createElement("div"); bubble.className = "bubble"; if(role === "user"){ bubble.textContent = text; }else{ bubble.innerHTML = renderMd(text); } wrap.appendChild(bubble); chatEl.appendChild(wrap); chatEl.scrollTop = chatEl.scrollHeight; return bubble; } function clearChat() { chatEl.innerHTML = ""; messages = []; inputEl.value = ""; } async function send() { const text = inputEl.value.trim(); if (!text) return; sendBtn.disabled = true; sendBtn.classList.add("loading"); const useStream = document.getElementById("stream").checked; const model = document.getElementById("model").value; messages.push({ role: "user", content: text }); appendMsg("user", text); inputEl.value = ""; try { const res = await fetch("/api/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model, messages: [...messages], stream: useStream, }), }); if (!res.ok) { const err = await res.json().catch(() => ({ error: "服务异常" })); appendMsg("assistant", "❌ " + (err.error || "请求失败,状态码:" + res.status)); return; } if (useStream) { const reader = res.body.getReader(); const decoder = new TextDecoder("utf-8"); let buffer = ""; const aiBubble = appendMsg("assistant", "▌"); let fullText = ""; while (true) { const { value, done } = await reader.read(); if (done) { aiBubble.innerHTML = renderMd(fullText); break; } buffer += decoder.decode(value, { stream: true }); // 修复关键:改为单斜杠换行分割 const lines = buffer.split(" "); buffer = lines.pop(); for (const line of lines) { const trimLine = line.trim(); if (!trimLine.startsWith("data:")) continue; const dataStr = trimLine.replace("data:", "").trim(); if (dataStr === "[DONE]") continue; try { const chunk = JSON.parse(dataStr); const delta = chunk.choices?.[0]?.delta?.content || ""; fullText += delta; aiBubble.innerHTML = renderMd(fullText + "▌"); } catch (e) {} } } messages.push({ role: "assistant", content: fullText }); } else { const data = await res.json(); const reply = data.choices?.[0]?.message?.content || "无返回内容"; appendMsg("assistant", reply); messages.push({ role: "assistant", content: reply }); } } catch (err) { appendMsg("assistant", "❌ 网络请求失败:" + err.message); } finally { sendBtn.disabled = false; sendBtn.classList.remove("loading"); } }