import { prisma } from "@/lib/db"; import { ARCADE_SERVER_REGISTRY } from "@/lib/arcade/registry"; export type LlmInstructionType = "flashcards" | "quizzes" | "connections"; const DEFAULT_LLM_INSTRUCTIONS_FLASHCARDS = `You are generating study materials in a strict JSON format for import into a personal study app. The overall output must be raw JSON with no wrapping markdown code fence and no commentary before or after. Markdown formatting INSIDE string values (lists, **bold**, tables) is fine, see the formatting rule below. For flashcards, use this shape: { "type": "flashcards", "deckName": "...", "description": "...", "cards": [{"front": "...", "back": "..."}] } Rules: - CRITICAL: Output MUST be valid JSON. EVERY string value must start and end with double quotes. Do NOT output unquoted strings. Example: "back": "your text here". - Use Markdown formatting (bullet lists, **bold**, tables) inside "back" text wherever it improves clarity. You MUST escape any newlines in the string as \\n. Do not use raw newlines. - Base everything strictly on the material below. Do not add outside facts. Material: [paste your notes or lecture content here]`; const DEFAULT_LLM_INSTRUCTIONS_QUIZZES = `You are generating study materials in a strict JSON format for import into a personal study app. The overall output must be raw JSON with no wrapping markdown code fence and no commentary before or after. Markdown formatting INSIDE string values (lists, **bold**, tables) is fine, see the formatting rule below. For quizzes, use this shape: { "type": "quiz", "quizName": "...", "description": "...", "questions": [ {"type": "multiple_choice" | "sata", "prompt": "...", "category": "...", "options": [{"text": "...", "correct": true|false}], "rationale": "..."} ]} Rules: - CRITICAL: Output MUST be perfectly valid JSON. EVERY string value (including rationale and prompt) MUST start and end with double quotes. Do NOT output unquoted strings. Example: "rationale": "your text here" - "multiple_choice" questions must have exactly one option with correct: true. - "sata" questions must have two or more options with correct: true. - Every question needs a rationale explaining why the correct option(s) are correct, and briefly why the others are not. - Every question must include a "category" field: a short topic tag you choose based on the content (e.g. "thyroid", "limbic system"). Reuse the exact same label across questions on the same topic rather than inventing a new variant each time, and keep the total number of distinct categories small relative to the number of questions. - Use Markdown formatting (bullet lists, **bold**, tables) inside "rationale" text wherever it improves clarity. You MUST escape any newlines in the string as \\n. Do not use raw newlines. - Base everything strictly on the material below. Do not add outside facts. Material: [paste your notes or lecture content here]`; function instructionConfig(type: LlmInstructionType) { if (type === "flashcards") return { key: "llmInstructionsFlashcards", value: DEFAULT_LLM_INSTRUCTIONS_FLASHCARDS }; if (type === "quizzes") return { key: "llmInstructionsQuizzes", value: DEFAULT_LLM_INSTRUCTIONS_QUIZZES }; return { key: "llmInstructionsConnections", value: ARCADE_SERVER_REGISTRY.connections.defaultInstructions }; } export async function getLlmInstructions(type: LlmInstructionType): Promise { const { key, value: def } = instructionConfig(type); const setting = await prisma.setting.findUnique({ where: { key }, }); return setting?.value ?? def; } export async function updateLlmInstructions(type: LlmInstructionType, value: string) { const { key } = instructionConfig(type); return prisma.setting.upsert({ where: { key }, update: { value }, create: { key, value }, }); } export async function resetLlmInstructions(type: LlmInstructionType) { const { key, value: def } = instructionConfig(type); return prisma.setting.upsert({ where: { key }, update: { value: def }, create: { key, value: def }, }); }