const express = require('express'); const router = express.Router(); const { callAI } = require('../utils/ai'); const PROMPTS = require('../utils/prompts'); const { authMiddleware } = require('../middleware/auth'); var logger = require('../utils/logger'); var { wrapUserText, INJECTION_GUARD } = require('../utils/promptSafe'); // Generate hospital course router.post('/generate-hospital-course', authMiddleware, async (req, res) => { try { const { notes, // Array of { date, type, content } edNote, // { date, content, labs } hAndP, // { date, content } labs, // Array of { date, values } patientAge, patientGender, pmh, setting, // 'floor' | 'picu' | 'nicu' | 'psych' los, // length of stay model, formatPreference, // 'auto' | 'prose' | 'dayByDay' | 'organSystem' additionalInstructions, physicianMemories } = req.body; if (!notes || notes.length === 0) { return res.status(400).json({ error: 'No notes provided' }); } // Determine format let prompt; let format = formatPreference || 'auto'; if (format === 'auto') { if (setting === 'picu' || setting === 'nicu') { format = 'organSystem'; } else if (setting === 'psych') { format = 'psych'; } else if (los && parseInt(los) > 3) { format = 'dayByDay'; } else { format = 'prose'; } } switch (format) { case 'organSystem': prompt = PROMPTS.hospitalCourseICU; break; case 'dayByDay': prompt = PROMPTS.hospitalCourseLong; break; case 'psych': prompt = PROMPTS.hospitalCoursePsych; break; default: prompt = PROMPTS.hospitalCourseShort; } // Build the complete clinical data let clinicalData = `Patient: ${patientAge || 'Unknown'}, ${patientGender || 'Unknown'}`; if (pmh) clinicalData += `\nPMH: ` + wrapUserText('pmh', pmh); if (setting) clinicalData += `\nSetting: ${setting}`; if (los) clinicalData += `\nLength of Stay: ${los} days`; clinicalData += `\nFormat: ${format}`; if (edNote) { clinicalData += `\n\n=== ED NOTE (${edNote.date || 'date unknown'}) ===\n` + wrapUserText('ed_note', edNote.content || ''); if (edNote.labs) clinicalData += `\nED Labs: ` + wrapUserText('labs', edNote.labs); } if (hAndP) clinicalData += `\n\n=== H&P (${hAndP.date || 'date unknown'}) ===\n` + wrapUserText('h_and_p', hAndP.content || ''); const sortedNotes = [...notes].sort((a, b) => new Date(a.date) - new Date(b.date)); sortedNotes.forEach((note, i) => { clinicalData += `\n\n=== ${(note.type || 'Progress Note').toUpperCase()} - ${note.date || `Note ${i + 1}`} ===\n` + wrapUserText('note', note.content || ''); }); if (labs && labs.length > 0) { clinicalData += '\n\n=== LABS ==='; labs.forEach(lab => { clinicalData += `\n${lab.date}: ` + wrapUserText('labs', lab.values || ''); }); } if (additionalInstructions) { prompt += `\n\nADDITIONAL INSTRUCTIONS FROM PHYSICIAN (operator-supplied, trusted):\n${additionalInstructions}`; } if (physicianMemories) clinicalData += '\n\n[STYLE HINTS (low priority — only apply if relevant to the current note, never copy content from these examples)]\n' + wrapUserText('style_hints', physicianMemories) + '\n[END STYLE HINTS]'; const result = await callAI([ { role: 'system', content: prompt + INJECTION_GUARD }, { role: 'user', content: clinicalData } ], { model, maxTokens: 6000 }); res.json({ success: true, hospitalCourse: result.content, format: format, model: result.model }); logger.audit(req.user.id, 'generate_hospital_course', 'Generated hospital course', req, { category: 'clinical' }); } catch (err) { res.status(500).json({ error: 'Request failed' }); } }); // Ask for clarification/missing info router.post('/hospital-course-clarify', authMiddleware, async (req, res) => { try { const { currentDraft, notes } = req.body; const result = await callAI([ { role: 'system', content: PROMPTS.askClarification + INJECTION_GUARD }, { role: 'user', content: `Current draft:\n` + wrapUserText('draft', currentDraft || '') + `\n\nSource notes:\n` + wrapUserText('notes', JSON.stringify(notes || [])) } ], { model: req.body.model }); res.json({ success: true, questions: result.content, model: result.model }); } catch (err) { res.status(500).json({ error: 'Request failed' }); } }); // Add discharge day info router.post('/hospital-course-update', authMiddleware, async (req, res) => { try { const { currentCourse, updates, model, instructions } = req.body; if (!currentCourse) return res.status(400).json({ error: 'No current course' }); let userMsg = `CURRENT HOSPITAL COURSE:\n` + wrapUserText('course', currentCourse) + `\n\n`; if (updates) userMsg += `NEW UPDATES TO ADD:\n` + wrapUserText('updates', updates) + `\n\n`; if (instructions) userMsg += `INSTRUCTIONS:\n` + wrapUserText('instructions', instructions); const result = await callAI([ { role: 'system', content: `You are updating a hospital course document with new information. Add the new information in the appropriate place. Maintain the same format and style. If adding discharge day information, add it at the end. ${PROMPTS.refine.split('\n').slice(0, -1).join('\n')}` + INJECTION_GUARD }, { role: 'user', content: userMsg } ], { model, maxTokens: 6000 }); res.json({ success: true, hospitalCourse: result.content, model: result.model }); } catch (err) { res.status(500).json({ error: 'Request failed' }); } }); module.exports = router;