41 lines
1.8 KiB
TypeScript
41 lines
1.8 KiB
TypeScript
"use server";
|
|
|
|
import { requireUserId } from "@/lib/auth-helpers";
|
|
import { getAllGroupsForUser } from "@/lib/board";
|
|
import { formatAllGroupsForPrompt } from "@/lib/ai/context";
|
|
import { callChatCompletion } from "@/lib/ai/chat-completion";
|
|
|
|
export interface ChatMessage {
|
|
role: "user" | "assistant";
|
|
content: string;
|
|
}
|
|
|
|
export type GlobalChatResult = { content: string } | { error: string };
|
|
|
|
const SYSTEM_PROMPT_HEADER = `You are a helpful assistant answering questions about the user's personal/team to-do board app. Below is the full current state of every board they own, including completed to-dos and archived groups (kept so you can answer historical questions like "what did we do about X").
|
|
|
|
Answer only using the information below. If the answer isn't in it, say so plainly instead of guessing. When it's helpful, mention which project/category/group the information came from.
|
|
|
|
`;
|
|
|
|
/**
|
|
* Free-form Q&A across everything the user owns (Home board + every
|
|
* Project), for the global Chat page. Re-fetches and re-serializes the
|
|
* full context on every turn -- simpler and always fresh, and re-checks
|
|
* the user's own access each call the same way the existing group-scoped
|
|
* AI actions do (lib/actions/group-ai.ts, lib/actions/todo-ai.ts).
|
|
* Unlike those, there's no artifact to save, so this returns the model's
|
|
* plain-text reply directly rather than an ask/finalize JSON contract.
|
|
*/
|
|
export async function sendChatMessage(messages: ChatMessage[]): Promise<GlobalChatResult> {
|
|
const userId = await requireUserId();
|
|
const groups = await getAllGroupsForUser(userId);
|
|
const context = formatAllGroupsForPrompt(groups);
|
|
|
|
const systemPrompt = `${SYSTEM_PROMPT_HEADER}${context}`;
|
|
|
|
return callChatCompletion([{ role: "system", content: systemPrompt }, ...messages], {
|
|
temperature: 0.3,
|
|
});
|
|
}
|