Commit Graph

11 Commits

Author SHA1 Message Date
Khalid Abdi fa2e499440 feat: live AI chat (thinking + inline Veil) and display/add actions
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>
2026-06-13 23:49:18 +03:00
Khalid Abdi ddf4b49d82 fix: chat works with any configured provider + surfaces errors
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>
2026-06-13 19:27:37 +03:00
Khalid Abdi 31d86bb5dd frontend: wire chat to the real agent + lab charts + import approval
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>
2026-06-13 18:44:20 +03:00
Khalid Abdi c6a1b98427 frontend: declutter chat input to a single model+effort picker
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>
2026-06-13 18:23:45 +03:00
Khalid Abdi ab2f10bffc i18n: convert settings, chat, patient records and notes; update docs
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>
2026-06-08 02:23:20 +03:00
Claude 1ecbd16404 Wire frontend to the backend: auth, organizations, real patient API
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>
2026-06-02 21:28:02 +03:00
Khalid Abdi dec150c77d Patients page, clinical Settings re-theme, Polar-style user footer
- 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>
2026-06-01 21:55:33 +03:00
Khalid Abdi 750622e0db Edit patient records + fix Add-patient dialog scrollbar
- 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>
2026-06-01 21:17:43 +03:00
Khalid Abdi da785ee51f Accept bare /<file#> command and remove page-level scrollbar
- 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>
2026-06-01 19:04:50 +03:00
Khalid Abdi 88a45cf19d Add /patient lookup with patient-info cards, clinical chat input
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>
2026-06-01 18:56:56 +03:00
Khalid Abdi 97bf9ed8cc Build temetro app: dark theme, clinical sidebar, AI chat, settings page
- Linear-inspired dark theme (app/globals.css), forced dark in layout
- Clinical sidebar (components/sidebar-02) with temetro brand
- AI chat UI (components/chat): Cursor-style input, UI-only mock replies
- Settings page (components/settings): Polar-style tabs/sections, UI only
- Route-group app shell: app/(app)/{layout,page,settings}
- shadcn (Base UI) + ai-elements component libraries
- CLAUDE.md: architecture notes + per-folder commit policy

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 20:25:19 +03:00