| import { clsx, type ClassValue } from 'clsx'; |
| import { twMerge } from 'tailwind-merge'; |
| import type { Severity, ErrorCategory, Settings, PromptPreset, PromptSettings } from '@/types'; |
|
|
| |
| export function cn(...inputs: ClassValue[]) { |
| return twMerge(clsx(inputs)); |
| } |
|
|
| |
| export const CATEGORY_INFO = { |
| medication: { |
| id: 'medication' as const, |
| label: 'Medication', |
| icon: 'π', |
| description: 'Dosage errors, drug interactions, contraindications', |
| }, |
| measurement: { |
| id: 'measurement' as const, |
| label: 'Measurement', |
| icon: 'π', |
| description: 'Vital signs, lab values outside possible ranges', |
| }, |
| logical: { |
| id: 'logical' as const, |
| label: 'Logical', |
| icon: 'π', |
| description: 'Temporal contradictions, diagnostic inconsistencies', |
| }, |
| missing: { |
| id: 'missing' as const, |
| label: 'Missing Info', |
| icon: 'β', |
| description: 'Incomplete documentation, missing required elements', |
| }, |
| terminology: { |
| id: 'terminology' as const, |
| label: 'Terminology', |
| icon: 'π', |
| description: 'Misspellings, ambiguous abbreviations', |
| }, |
| } as const; |
|
|
| |
| export const SEVERITY_INFO = { |
| critical: { |
| id: 'critical' as const, |
| label: 'Critical', |
| className: 'glass-critical', |
| textColor: 'text-[var(--critical-text)]', |
| bgColor: 'bg-[var(--critical-bg)]', |
| borderColor: 'border-[var(--critical-border)]', |
| glowClass: 'pulse-glow-critical', |
| }, |
| warning: { |
| id: 'warning' as const, |
| label: 'Warning', |
| className: 'glass-warning', |
| textColor: 'text-[var(--warning-text)]', |
| bgColor: 'bg-[var(--warning-bg)]', |
| borderColor: 'border-[var(--warning-border)]', |
| glowClass: 'pulse-glow-warning', |
| }, |
| suggestion: { |
| id: 'suggestion' as const, |
| label: 'Suggestion', |
| className: 'glass-suggestion', |
| textColor: 'text-[var(--suggestion-text)]', |
| bgColor: 'bg-[var(--suggestion-bg)]', |
| borderColor: 'border-[var(--suggestion-border)]', |
| glowClass: '', |
| }, |
| } as const; |
|
|
| |
| export const DEFAULT_PROMPT = `You are an emergency medicine clinical safety reviewer analyzing a real patient's emergency department documentation. Your ONLY task is to identify CRITICAL patient safety errors β the kind that could cause direct harm if missed. |
| |
| FOCUS EXCLUSIVELY on these error types: |
| |
| 1. CONTRAINDICATED_MEDICATION β A prescribed drug that is dangerous given the patient's diagnosis, allergies, or concurrent medications (e.g., Amiodarone in WPW, penicillin with documented allergy, NSAID with active GI bleeding). |
| |
| 2. DANGEROUS_DOSAGE β Medication dose significantly outside the therapeutic range β 2x or more above maximum, clearly subtherapeutic, or wrong frequency that changes total daily dose dangerously (e.g., Metoprolol 500mg instead of 50mg). |
| |
| 3. CLINICAL_SCORE_ERROR β Risk stratification scores (CHAβDSβ-VASc, NIHSS, Wells, HEART, GCS, etc.) are miscalculated, leading to a wrong treatment decision. |
| |
| 4. MISSING_CRITICAL_TREATMENT β A life-saving medication or intervention is clearly indicated by the diagnosis but completely absent from the treatment plan. |
| |
| 5. TREATMENT_LOGIC_FAILURE β The treatment plan directly contradicts the diagnosis or clinical findings (e.g., patient discharged when admission is clearly required). |
| |
| 6. MISSING_CRITICAL_WORKUP β Diagnostic tests urgently indicated by the clinical presentation are not ordered (e.g., no troponin in chest pain, no CT in suspected PE/stroke). |
| |
| STRICT RULES: |
| - Report AT MOST 3 errors, strictly prioritized by patient safety impact. |
| - Only report errors you are β₯80% confident about. |
| - Do NOT report: style preferences, minor documentation gaps, formatting issues, or speculative concerns. |
| - If the clinical note has no critical safety errors, return an empty errors array. |
| - Less is more β a false alarm wastes physician time and erodes trust.`; |
|
|
| export const STRICT_PROMPT = `You are a rigorous clinical safety auditor. Analyze emergency department documentation with the highest standards. ONLY flag issues that represent genuine, immediate patient safety threats. |
| |
| FOCUS EXCLUSIVELY on these error types: |
| 1. CONTRAINDICATED_MEDICATION β Only flag drugs with clear, documented contraindications (allergy, organ failure, dangerous interaction). |
| 2. DANGEROUS_DOSAGE β Only flag doses that are β₯2x above maximum or clearly subtherapeutic for a critical condition. |
| 3. CLINICAL_SCORE_ERROR β Only flag score miscalculations that directly change the treatment decision. |
| 4. MISSING_CRITICAL_TREATMENT β Only flag omissions of life-saving interventions that are standard of care. |
| 5. TREATMENT_LOGIC_FAILURE β Only flag treatment plans that directly contradict the diagnosis. |
| 6. MISSING_CRITICAL_WORKUP β Only flag urgently indicated tests that are completely absent. |
| |
| ULTRA-STRICT RULES: |
| - Report AT MOST 2 errors, only the most critical. |
| - Only report errors you are β₯90% confident about. |
| - When in doubt, do NOT flag it. Zero false positives is the goal. |
| - If no clear safety errors exist, return an empty errors array.`; |
|
|
| export const VERBOSE_PROMPT = `You are a comprehensive clinical documentation reviewer for emergency department notes. Perform a thorough analysis identifying all potential patient safety issues. |
| |
| Review these error categories in detail: |
| 1. CONTRAINDICATED_MEDICATION β Check all prescribed drugs against documented allergies, diagnoses, organ function, and concurrent medications for dangerous interactions or contraindications. |
| 2. DANGEROUS_DOSAGE β Verify all medication dosages against standard therapeutic ranges, weight-based dosing, renal/hepatic adjustments, and frequency schedules. |
| 3. CLINICAL_SCORE_ERROR β Recalculate all risk stratification scores (CHAβDSβ-VASc, NIHSS, Wells, HEART, GCS, CURB-65, etc.) and verify they match the documented values and resulting treatment decisions. |
| 4. MISSING_CRITICAL_TREATMENT β Cross-reference the diagnosis with standard treatment protocols to identify any omitted life-saving medications or interventions. |
| 5. TREATMENT_LOGIC_FAILURE β Analyze the treatment plan for internal contradictions with the diagnosis, clinical findings, and documented assessments. |
| 6. MISSING_CRITICAL_WORKUP β Review the clinical presentation against standard diagnostic algorithms to identify any urgently indicated tests not ordered. |
| |
| RULES: |
| - Report up to 3 errors, prioritized by patient safety impact. |
| - Only report errors you are β₯80% confident about. |
| - Provide detailed explanations with specific clinical reasoning for each finding. |
| - Include specific recommendations for corrective action.`; |
|
|
| |
| export const MEDGEMMA_BACKEND_PROMPT = `You are an emergency medicine clinical safety reviewer analyzing a real patient's emergency department documentation. Your ONLY task is to identify CRITICAL patient safety errors β the kind that could cause direct harm if missed. |
| |
| FOCUS EXCLUSIVELY on these error types: |
| |
| 1. CONTRAINDICATED_MEDICATION |
| A prescribed drug that is dangerous given the patient's diagnosis, allergies, or concurrent medications (e.g., Amiodarone in WPW, penicillin with documented allergy, NSAID with active GI bleeding). |
| |
| 2. DANGEROUS_DOSAGE |
| Medication dose significantly outside the therapeutic range β 2x or more above maximum, clearly subtherapeutic, or wrong frequency that changes total daily dose dangerously (e.g., Metoprolol 500mg instead of 50mg, Furosemide 1x1 when 3x1 needed). |
| |
| 3. CLINICAL_SCORE_ERROR |
| Risk stratification scores (CHAβDSβ-VASc, NIHSS, Wells, HEART, GCS, etc.) are miscalculated, leading to a wrong treatment decision (e.g., CHAβDSβ-VASc scored 1 when it should be 2 β patient denied anticoagulation). |
| |
| 4. MISSING_CRITICAL_TREATMENT |
| A life-saving medication or intervention is clearly indicated by the diagnosis but completely absent from the treatment plan (e.g., no aspirin/antiplatelet in STEMI, no anticoagulation for high-risk AF, no IV fluids in severe dehydration). |
| |
| 5. TREATMENT_LOGIC_FAILURE |
| The treatment plan directly contradicts the diagnosis or clinical findings (e.g., patient discharged when admission is clearly required, antibiotics stopped too early in active sepsis, no reperfusion in acute MI). |
| |
| 6. MISSING_CRITICAL_WORKUP |
| Diagnostic tests urgently indicated by the clinical presentation are not ordered (e.g., no troponin in chest pain, no CT in suspected PE/stroke, no imaging for acute abdomen, no blood cultures in sepsis). |
| |
| STRICT RULES: |
| - Report AT MOST 3 errors, strictly prioritized by patient safety impact. |
| - Only report errors you are β₯80% confident about. |
| - Do NOT report: style preferences, minor documentation gaps, formatting issues, findings that are "could be improved" but not directly dangerous, or speculative concerns. |
| - If the clinical note has no critical safety errors, return an empty errors array. |
| - Less is more β a false alarm wastes physician time and erodes trust. |
| |
| Output: Valid JSON with "errors" array and "summary" string. Each error has: type, severity, quote, problem, recommendation, confidence.`; |
|
|
| |
| export const BUILT_IN_PRESETS: PromptPreset[] = [ |
| { |
| id: 'default', |
| name: 'Default', |
| prompt: DEFAULT_PROMPT, |
| isBuiltIn: true, |
| }, |
| { |
| id: 'strict', |
| name: 'Strict', |
| prompt: STRICT_PROMPT, |
| isBuiltIn: true, |
| }, |
| { |
| id: 'verbose', |
| name: 'Verbose', |
| prompt: VERBOSE_PROMPT, |
| isBuiltIn: true, |
| }, |
| ]; |
|
|
| |
| export const DEFAULT_PROMPT_SETTINGS: PromptSettings = { |
| activePresetId: 'default', |
| customPrompt: DEFAULT_PROMPT, |
| savedPresets: [], |
| }; |
|
|
| |
| export const DEFAULT_SETTINGS: Settings = { |
| provider: 'local', |
| selectedModel: '', |
| temperature: 0.1, |
| confidenceThreshold: 0.7, |
| enabledSeverities: ['critical', 'warning', 'suggestion'] as Severity[], |
| enabledCategories: ['medication', 'measurement', 'logical', 'missing', 'terminology'] as ErrorCategory[], |
| promptSettings: DEFAULT_PROMPT_SETTINGS, |
| }; |
|
|
| |
| export function formatConfidence(confidence: number): string { |
| return `${Math.round(confidence * 100)}%`; |
| } |
|
|
| |
| export function formatDuration(ms: number): string { |
| if (ms < 1000) { |
| return `${ms}ms`; |
| } |
| const seconds = ms / 1000; |
| if (seconds < 60) { |
| return `${seconds.toFixed(1)}s`; |
| } |
| const minutes = Math.floor(seconds / 60); |
| const remainingSeconds = Math.round(seconds % 60); |
| return `${minutes}m ${remainingSeconds}s`; |
| } |
|
|
| |
| export function truncateText(text: string, maxLength: number): string { |
| if (text.length <= maxLength) return text; |
| return text.slice(0, maxLength - 3) + '...'; |
| } |
|
|
| |
| export function generateId(): string { |
| return Math.random().toString(36).substring(2, 11); |
| } |
|
|
| |
| export function debounce<T extends (...args: Parameters<T>) => ReturnType<T>>( |
| fn: T, |
| delay: number |
| ): (...args: Parameters<T>) => void { |
| let timeoutId: ReturnType<typeof setTimeout>; |
| return (...args: Parameters<T>) => { |
| clearTimeout(timeoutId); |
| timeoutId = setTimeout(() => fn(...args), delay); |
| }; |
| } |
|
|
| |
| export function getFromStorage<T>(key: string, defaultValue: T): T { |
| if (typeof window === 'undefined') return defaultValue; |
| try { |
| const item = localStorage.getItem(key); |
| return item ? JSON.parse(item) : defaultValue; |
| } catch { |
| return defaultValue; |
| } |
| } |
|
|
| export function setToStorage<T>(key: string, value: T): void { |
| if (typeof window === 'undefined') return; |
| try { |
| localStorage.setItem(key, JSON.stringify(value)); |
| } catch { |
| |
| } |
| } |
|
|