// server.js
import express from "express";
import cors from "cors";
import fetch from "node-fetch";
const app = express();
app.use(cors({ origin: [/\.tilda\.ws$/, /your-domain\.xyz$/, /localhost/], credentials: false }));
app.use(express.json({ limit: "1mb" }));
const OPENAI_API_KEY = process.env.OPENAI_API_KEY; // положите сюда ваш ключ
const ASSISTANT_ID = "asst_Hr3U1Uc6BlR7qZN1Bxxm8n0e"; // ваш ассистент
if (!OPENAI_API_KEY) {
console.error("❌ Missing OPENAI_API_KEY env");
process.exit(1);
}
const OAI = async (path, opts={}) => {
const res = await fetch(`https://api.openai.com/v1/${path}`, {
...opts,
headers: {
"Authorization": `Bearer ${OPENAI_API_KEY}`,
"Content-Type": "application/json",
...(opts.headers || {})
}
});
if (!res.ok) throw new Error(`OpenAI ${res.status}: ${await res.text()}`);
return res.json();
};
// POST /api/chat-assistant { messages:[{role:'user', content:'...'}] }
app.post("/api/chat-assistant", async (req, res) => {
try {
const msgs = Array.isArray(req.body?.messages) ? req.body.messages : [];
const userText = [...msgs].reverse().find(m => m.role === "user")?.content || "";
if (!userText) return res.status(400).json({ error: "No user message" });
// 1) новый тред
const thread = await OAI("threads", { method:"POST", body: JSON.stringify({}) });
// 2) сообщение пользователя
await OAI(`threads/${thread.id}/messages`, {
method:"POST",
body: JSON.stringify({ role:"user", content: userText })
});
// 3) запускаем ран ассистента
let run = await OAI(`threads/${thread.id}/runs`, {
method:"POST",
body: JSON.stringify({ assistant_id: ASSISTANT_ID })
});
// 4) ждём завершения
let tries = 0;
const wait = (ms)=>new Promise(r=>setTimeout(r,ms));
while (["queued","in_progress","requires_action","cancelling"].includes(run.status)) {
await wait(Math.min(2000 * Math.pow(1.3, tries++), 6000));
run = await OAI(`threads/${thread.id}/runs/${run.id}`, { method:"GET" });
if (tries > 40) throw new Error("Timeout waiting for run");
}
if (run.status !== "completed") throw new Error(`Run status: ${run.status}`);
// 5) читаем ответы ассистента
const list = await OAI(`threads/${thread.id}/messages?limit=10`, { method:"GET" });
const firstAssistant = (list.data || []).find(m => m.role === "assistant");
const blocks = firstAssistant?.content?.filter(c => c.type === "text") || [];
const reply = blocks.map(t => t.text?.value || "").join("\n").trim();
res.json({ reply: reply || "(пустой ответ ассистента)" });
} catch (err) {
console.error("chat-assistant error:", err);
res.status(500).json({ error: String(err.message || err) });
}
});
app.get("/api/health", (_, res) => res.json({ ok:true }));
const port = process.env.PORT || 3000;
app.listen(port, () => console.log("Server at http://localhost:"+port));