NEON / backend /src /index.ts
picklefried706's picture
Upload folder using huggingface_hub
40a9423 verified
import Fastify from "fastify";
import cors from "@fastify/cors";
import { z } from "zod";
import { handleChat } from "./ai/engine.js";
import { ChatRequest } from "./types.js";
const server = Fastify({
logger: true
});
await server.register(cors, {
origin: true,
credentials: true
});
server.get("/health", async () => ({ status: "ok" }));
server.post("/api/chat", async (request, reply) => {
const body = request.body as ChatRequest;
const schema = z.object({
sessionId: z.string().min(1),
message: z.string().min(1),
mode: z.enum(["auto", "search", "no-search"]).optional()
});
const parsed = schema.safeParse(body);
if (!parsed.success) {
reply.status(400);
return { error: parsed.error.flatten() };
}
const chunks: string[] = [];
await handleChat(parsed.data, {
onStatus: () => {},
onToken: (token) => chunks.push(token),
onDone: () => {},
onError: () => {}
});
return { message: chunks.join("") };
});
server.get("/api/chat/stream", async (request, reply) => {
const query = request.query as Record<string, string>;
const schema = z.object({
sessionId: z.string().min(1),
message: z.string().min(1),
mode: z.enum(["auto", "search", "no-search"]).optional()
});
const parsed = schema.safeParse(query);
if (!parsed.success) {
reply.status(400);
return reply.send({ error: parsed.error.flatten() });
}
reply.raw.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
"X-Accel-Buffering": "no"
});
reply.raw.flushHeaders?.();
const writeEvent = (event: string, data: string) => {
reply.raw.write(`event: ${event}\n`);
reply.raw.write(`data: ${data}\n\n`);
};
const requestPayload: ChatRequest = {
sessionId: parsed.data.sessionId,
message: parsed.data.message,
mode: parsed.data.mode
};
let closed = false;
request.raw.on("close", () => {
closed = true;
});
await handleChat(requestPayload, {
onStatus: (message) => !closed && writeEvent("status", JSON.stringify({ message })),
onToken: (token) => !closed && writeEvent("delta", JSON.stringify({ token })),
onDone: () => !closed && writeEvent("done", JSON.stringify({ ok: true })),
onError: (message) => !closed && writeEvent("error", JSON.stringify({ message }))
});
reply.raw.end();
});
const port = Number(process.env.PORT ?? 8080);
server.listen({ port, host: "0.0.0.0" }).catch((err) => {
server.log.error(err);
process.exit(1);
});