feat: implement Story 3.1 — chat panel UI with streaming AI responses
Add AI copilot chat panel to the diagram editor with streaming responses, chat history persistence, and markdown rendering. Includes copilot API route, diagram-aware system prompt, and schema with 15 passing tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
47
packages/api/src/modules/ai/copilot/router.ts
Normal file
47
packages/api/src/modules/ai/copilot/router.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Hono } from "hono";
|
||||
import * as z from "zod";
|
||||
|
||||
import { getCopilotHistory, streamCopilot } from "@turbostarter/ai/copilot/api";
|
||||
import { copilotMessageSchema } from "@turbostarter/ai/copilot/schema";
|
||||
|
||||
import { enforceAuth, deductCredits, rateLimiter, validate } from "../../../middleware";
|
||||
|
||||
import type { User } from "@turbostarter/auth";
|
||||
|
||||
const chatIdQuerySchema = z.object({
|
||||
chatId: z.string(),
|
||||
});
|
||||
|
||||
export const copilotRouter = new Hono<{
|
||||
Variables: {
|
||||
user: User;
|
||||
};
|
||||
}>()
|
||||
.get(
|
||||
"/messages",
|
||||
enforceAuth,
|
||||
validate("query", chatIdQuerySchema),
|
||||
async (c) => {
|
||||
const { chatId } = c.req.valid("query");
|
||||
const messages = await getCopilotHistory(chatId);
|
||||
return c.json(messages);
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/",
|
||||
enforceAuth,
|
||||
rateLimiter,
|
||||
validate("json", copilotMessageSchema),
|
||||
async (c) => {
|
||||
const input = c.req.valid("json");
|
||||
|
||||
// Deduct 1 credit per copilot message
|
||||
await deductCredits(1, "copilot")(c, async () => { /* noop */ });
|
||||
|
||||
return streamCopilot({
|
||||
...input,
|
||||
signal: c.req.raw.signal,
|
||||
userId: c.var.user.id,
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -5,6 +5,7 @@ import { getUserCredits } from "@turbostarter/ai/credits/server";
|
||||
import { enforceAuth } from "../../middleware";
|
||||
|
||||
import { chatRouter } from "./chat";
|
||||
import { copilotRouter } from "./copilot/router";
|
||||
import { imageRouter } from "./image";
|
||||
import { pdfRouter } from "./pdf";
|
||||
import { sttRouter } from "./stt";
|
||||
@@ -13,6 +14,7 @@ import { ttsRouter } from "./tts";
|
||||
export const aiRouter = new Hono()
|
||||
.use(enforceAuth)
|
||||
.route("/chat", chatRouter)
|
||||
.route("/copilot", copilotRouter)
|
||||
.route("/pdf", pdfRouter)
|
||||
.route("/image", imageRouter)
|
||||
.route("/tts", ttsRouter)
|
||||
|
||||
Reference in New Issue
Block a user