Make the chat feel alive and let the agent act on the clinic — safely.
UX (frontend):
- Stream `data-step` parts from each tool into an inline Chain-of-Thought
trace, plus a "Thinking…" shimmer while a request is in flight (works even
on the non-streamed external+Veil path).
- Replace the modal Veil consent Dialog with an inline, once-per-session
"Veil" confirmation above the input (with a "Use local model" option).
- Render new list + action-preview cards; chat-input now uses COSS tokens.
Agent (backend):
- Add display tools (listAppointments / listTasks / listPrescriptions) and
propose tools (proposeAppointment / proposeTask / proposePrescription) that
validate as a dry run and stream an approval card — nothing is written until
the clinician approves, via the existing RBAC-gated create endpoints.
- previewImport now also covers single-patient add + migration.
- System prompt: display + add only, never edit/delete or alter the schema;
stronger migration guidance. ToolContext carries the viewer for task scoping.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The chat defaulted to a Claude model, so a user who saved only a Gemini key got
a silent failure (backend derived Anthropic, found no key, errored — and the UI
showed nothing).
- Backend: resolveModel now falls back to whichever provider actually has a key
(preferring the configured one), so a Gemini key just works regardless of the
picked model. Clear 400 if no provider is configured at all.
- Frontend: the chat seeds its model/effort from the saved AI config, and now
surfaces request failures as both a persistent alert banner and a toast —
never silent.
- Settings: switching provider auto-selects that provider's default model.
- Refreshed the model catalog to current ids (Gemini 2.5 Pro/Flash + 2.0 Flash;
dropped the retired gemini-1.5-pro); per-provider default model updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the mock chat with the live backend agent:
- chat-panel uses @ai-sdk/react useChat against /api/chat (credentials included),
passing the selected model + effort per send. The `/patient <file#>` fast-path
is kept as an instant client-side shortcut.
- Renders the agent's streamed data parts: patientCard → record cards
(PatientResult), labCard → new LabChartCard (visx area chart with a high/low
flag badge in the top-right corner + recent values), importPreview →
ImportPreviewCard (the human approval gate: review counts/issues, then commit
via POST /api/ai/import — nothing is written until approved).
- Veil consent: a one-time dialog before the first send to a cloud model,
explaining that identifiers are de-identified before leaving the clinic.
- Attached text files (csv/json/txt…) now include their content in the message
so the agent can parse an export for import.
Shared chat message/data-part types in lib/ai-chat.ts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the five clinical context selects (access, response mode, specialty,
facility, time range) with one model picker styled like the reference design:
a primary model list with descriptions, an Effort submenu, and a "More models"
submenu. Move the Add-patient pill up into the toolbar and drop the now-empty
bottom context-selector card so the input is a single clean rounded surface.
Model/effort selection is lifted to ChatPanel so it can travel with each send
(wired to the backend agent in a later phase). Adds a shared model catalog
(lib/ai-models.ts) reused by the picker, Settings, and the chat wiring.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Finish the i18n pass: settings panels (profile/care-team/signing), the
chat heading + input, the patient cards / detail / create-edit form, and
the notes page + rich-text editor are all keyed in en/translation.json.
All 526 static t() keys resolve. Document the new backend resources +
Socket.io realtime (backend README/CLAUDE) and the i18n coverage
(frontend CLAUDE).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Connects the UI-only app to the new backend over Better Auth + a small
patient API client, replacing the in-memory fixture and placeholder identity.
- Better Auth React client (lib/auth-client.ts) + shared access-control
roles; API client (lib/api-client.ts) sending credentials cross-origin.
- Designed (auth) route group: login, signup, verify-email, forgot/reset
password, clinic onboarding, and accept-invite.
- proxy.ts (this Next's renamed middleware) optimistic redirect + an
authoritative client AppAuthGuard requiring a session and active clinic.
- Real identity in nav-user (useSession + sign out); the unused team
switcher repurposed as an organization (clinic) switcher; Care-team
settings tab manages members and invitations.
- lib/patients.ts now calls the org-scoped API (types unchanged); patients
table and create/edit dialog updated for async create/update.
- next.config: standalone output + Dockerfile for containerized runs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Patients: new /patients directory table (name, MRN, age·sex, status,
last seen, allergies) with search + Add patient; clicking a row opens
the record in the chat via /?patient=<#>. chat-panel reads that search
param (Suspense-wrapped) and runs the lookup once on arrival. Sidebar
"Patients" now links to /patients; lib/patients gains listPatients().
- Settings: re-themed to clinical tabs (Profile · Records · Signing ·
Care team · Developers) — clinician profile, patient notifications,
patient-owned-storage/signed-records features, and a Signing key panel.
Same layout/components, only content changed.
- Sidebar footer: Polar-style NavUser (avatar + name + chevron) opening a
menu upward — Settings · Docs & GitHub · Theme · Log out. Collapsed
("locked"): avatar only, name on hover (tooltip), menu opens to the
right. Placeholder identity (no auth yet).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Generalize add-patient-dialog → shared PatientFormDialog (create | edit).
Edit mode prefills from the patient; both modes now cover all sections
with add/remove rows: identity, vitals, allergies, meds, problems, labs,
visits. Save writes to the store (addPatient overwrites by file #).
- Fix the dialog scrollbar: fixed header + footer (Save/Cancel pinned),
only the field body scrolls, scrollbar hidden (no-scrollbar).
- patient-cards: "Edit record" button on the Summary card opens the editor
(stopPropagation so it doesn't open the detail dialog); PatientResult
holds the editor state and exposes onPatientUpdated.
- chat-panel: onPatientUpdated replaces the message's patient in place, so
saved edits update the on-screen cards (no duplicate message, no requery).
- chat-input: Add pill now uses PatientFormDialog mode="create".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- chat-panel.tsx: `/10293` now triggers a lookup, not just `/patient 10293`
(regex accepts an optional `patient` keyword; matches digits only so
`/help` etc. still fall through to the normal reply).
- app/layout.tsx: make <body> a fixed h-dvh, overflow-hidden shell so the
page no longer shows its own scrollbar; each route's SidebarInset already
scrolls internally (chat = overflow-hidden, settings = overflow-y-auto).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Type `/patient <fileNumber>` to pull up a patient: a skeleton card set
appears, then fills in with summary, allergies & alerts, medications &
problems, and vitals/labs/visits — composed from existing Card/Badge/
Avatar/Separator/Skeleton primitives (no new design).
- lib/patients.ts: typed mock fixture + async getPatient() (swap point
for a real API later).
- components/chat/patient-cards.tsx: PatientResult (loading/ready/
not-found).
- chat-panel.tsx: discriminated-union message model, strict /patient
parse, async lookup with update-by-id, clinical heading.
- chat-input.tsx: relabel leftover coding-assistant controls to clinical
copy + clinical icons; layout/styling unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>