mirror of
https://github.com/temetro/temetro.git
synced 2026-07-26 11:58:14 +00:00
b29fdff1cb
Record a clinician↔patient visit (or paste a transcript) on the patient
sheet; the backend transcribes it (OpenAI Whisper / Gemini), de-identifies
the transcript + context through Veil, and drafts a structured SOAP note
the clinician reviews and edits before saving — the same write-approval
gate as the chat agent.
Backend: POST /api/scribe/{transcribe,draft,save} (routes/scribe.ts,
services/ai/transcribe.ts), veil.redactText() free-text redactor,
appendEncounter service, audio MIME types on attachments. Gated by
patient:write + the clinic AI policy (reception/disabled-AI excluded).
Frontend: ScribeDialog + lib/scribe.ts, "Record visit" on the patient
detail, gated by clinical access + AI availability. New `scribe` locale
namespace across all five languages. Bumps to v0.4.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
// Client for the ambient AI visit-scribe API. The dialog records (or accepts a
|
|
// pasted transcript of) a clinician↔patient visit, transcribes it, drafts a
|
|
// structured encounter note, and — after the clinician reviews it — appends the
|
|
// note to the patient record (the same write-approval gate as the chat agent).
|
|
|
|
import { apiFetch } from "@/lib/api-client";
|
|
import type { Encounter, Patient } from "@/lib/patients";
|
|
|
|
export type ScribeVeil = {
|
|
active: boolean;
|
|
level: string;
|
|
classes: string[];
|
|
provider: string;
|
|
};
|
|
|
|
// Turn a stored audio attachment into a raw transcript (server streams it to the
|
|
// user's OpenAI/Gemini speech provider). Audio does NOT pass through Veil.
|
|
export function transcribeRecording(
|
|
attachmentId: string,
|
|
): Promise<{ transcript: string }> {
|
|
return apiFetch<{ transcript: string }>("/api/scribe/transcribe", {
|
|
method: "POST",
|
|
body: JSON.stringify({ attachmentId }),
|
|
});
|
|
}
|
|
|
|
// Draft an encounter note from a transcript. The transcript + patient context
|
|
// are de-identified through Veil before any external call; the draft is never
|
|
// saved automatically.
|
|
export function draftNote(input: {
|
|
fileNumber: string;
|
|
transcript: string;
|
|
visitType?: string;
|
|
date?: string;
|
|
}): Promise<{ draft: Encounter; veil: ScribeVeil }> {
|
|
return apiFetch<{ draft: Encounter; veil: ScribeVeil }>("/api/scribe/draft", {
|
|
method: "POST",
|
|
body: JSON.stringify(input),
|
|
});
|
|
}
|
|
|
|
// The approval step: append the reviewed note to the patient record.
|
|
export function saveNote(
|
|
fileNumber: string,
|
|
encounter: Encounter,
|
|
): Promise<Patient> {
|
|
return apiFetch<Patient>("/api/scribe/save", {
|
|
method: "POST",
|
|
body: JSON.stringify({ fileNumber, encounter }),
|
|
});
|
|
}
|