Commit graph

355 commits

Author SHA1 Message Date
Daniel
7fdbcd51e6 feat: ChatGPT-style chat list — abbreviated rows with relative dates, pinned-first ordering, ⋮ menu (Rename/Pin/Export/Delete); clinical context always on; warn-only budget; mic live-transcript fallback; learning-hub page mode; composer autosize; include-context icon fix 2026-09-09 00:14:34 +02:00
Daniel
23788d63c5 feat: Open WebUI presentation — unboxed assistant messages, hairline OWUI tables without card containers
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 54s
Forgejo Android APK / Build signed APK (push) Successful in 2m2s
2026-09-08 23:46:29 +02:00
Daniel
bb218750d9 feat: Create image tool at rail top (describe or pick a chat), Images gallery of past creations, ChatGPT-style composer icons (headset/mic/attach/send), example tap asks immediately 2026-09-08 23:40:53 +02:00
Daniel
68385c42f1 fix: iPhone keyboard handling — resizes-content viewport, in-flow pill composer on 100dvh, 16px input to stop auto-zoom 2026-09-08 23:30:35 +02:00
Daniel
01f97f7996 fix: hide conversation budget helper on mobile (ChatGPT-style quiet composer)
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 55s
Forgejo Android APK / Build signed APK (push) Successful in 2m11s
2026-09-08 23:17:25 +02:00
Daniel
309d85ae86 feat: ChatGPT-style mobile UI — slim top bar with saved-chats drawer, plain example prompts, floating pill composer 2026-09-08 23:15:24 +02:00
Daniel
830a08b1ba fix: mobile rail rules after media queries so the horizontal strip wins
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 47s
Forgejo Android APK / Build signed APK (push) Successful in 2m5s
2026-09-08 22:56:35 +02:00
Daniel
ee0cc62500 fix: ChatGPT-style mobile layout — full-width chat, example questions visible, horizontal saved-chat chips, sources below 2026-09-08 22:55:28 +02:00
Daniel
cc9188fa08 fix: OWUI hover-delete on saved-chat rows (row click opens, trash icon deletes)
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 56s
Forgejo Android APK / Build signed APK (push) Successful in 2m3s
2026-09-08 22:45:13 +02:00
Daniel
da86c7db79 fix: OWUI-style polish — fullscreen workspace replaces main menu, row-click saved chats (delete stays as hover), markdown-rendered patient handout, admin-only raw transcript, /api TTS URL, scrollable unclipped tables, action buttons hidden in exports, autosave-only copy 2026-09-08 22:41:08 +02:00
Daniel
2e0951995c fix: take-home and translate-languages fetch URLs must be /api-prefixed
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 48s
Forgejo Android APK / Build signed APK (push) Successful in 2m11s
2026-09-08 20:07:27 +02:00
Daniel
09a4e02e39 feat: patient take home (copy/export/email), composer mic dictation, voice conversation mode, provider-aware translate languages 2026-09-08 20:01:46 +02:00
Daniel
3626f590d8 fix: QA-found defect — streamed assistant rows missing Copy/Translate/Regenerate actions 2026-09-08 19:39:39 +02:00
Daniel
79de7ccddb fix: reviewer findings — mhchem macro wrapping, regenerate history dedupe, strict safe image allowlist, stale docs 2026-09-08 19:25:31 +02:00
Daniel
8b072496e2 feat: Open WebUI-style assistant workspace — 3-column layout, markdown/math/code/tables, autosave with images, translation (LibreTranslate+DeepL), citation modal, Learning Hub moved in, handoff removed 2026-09-08 18:52:35 +02:00
Daniel
17a0ebe68b fix: new-chat confirm uses the site dialog; remove assistant intro paragraph
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 24s
Forgejo Android APK / Build signed APK (push) Successful in 2m6s
2026-09-08 16:38:08 +02:00
Daniel
81abc60591 Merge branch 'fix/attach-images-20260907'
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 24s
Forgejo Android APK / Build signed APK (push) Successful in 2m13s
2026-09-08 15:53:05 +02:00
Daniel
94210ac0a1 feat: attach images to clinical search with strict validation and multimodal routing 2026-09-08 15:53:05 +02:00
Daniel
3464f2d456 fix: drop redundant Full conversation unchanged from image context label 2026-09-08 15:52:37 +02:00
Daniel
c237826ef6 feat: clinical handoff as the standard site modal, closes back to the chat
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 24s
Forgejo Android APK / Build signed APK (push) Successful in 1m59s
2026-09-07 21:10:23 +02:00
Daniel
be889567f5 fix: remove reopen-image-history UI, trim budget label, image-storage preflight now passes with scoped ListBucket 2026-09-07 21:05:55 +02:00
Daniel
f1ac24a17d fix: simple prompt editing (save + restore original only), live users search, straight responsive admin rows
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 22s
Forgejo Android APK / Build signed APK (push) Successful in 1m55s
2026-09-07 19:30:40 +02:00
Daniel
e7599128ec fix: separate Scribe/Clinical/Learning prompt sections; drop model classification entirely with scrub migration
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 26s
Forgejo Android APK / Build signed APK (push) Successful in 1m58s
2026-09-07 18:22:51 +02:00
Daniel
13fca7887d feat: unify Admin model/prompt UI — single prompt dropdown, two image-model dropdowns, searchable/scrollable users, remove classification/custom-add, consistent font, concise labels 2026-09-07 18:18:48 +02:00
Daniel
bb82295173 fix: single image-model dropdown applied to both workflows; concise budget labels 2026-09-07 17:58:28 +02:00
Daniel
6be2d1375a feat: integrate durable image jobs/private assets into current core 2026-09-07 16:53:42 +02:00
Daniel
3a8dbbcce3 fix: keep the sidebar generated image session-only, never stored in saved chats
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 26s
Forgejo Android APK / Build signed APK (push) Successful in 4m4s
2026-09-07 16:23:55 +02:00
Daniel
a7fb45515f fix: revert verbose conversation budget help to one concise line 2026-09-07 16:21:06 +02:00
Daniel
c09038bfec fix: compact prompt administration with robust admin loading and concise styling 2026-09-07 16:11:49 +02:00
Daniel
9902ee07a6 fix: render clinical handoff Markdown with a concise heading
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 26s
Forgejo Android APK / Build signed APK (push) Successful in 2m2s
2026-09-07 14:23:56 +02:00
Daniel
40e7dd5206 fix: bind clinical image and export actions to their original account
All checks were successful
Forgejo Android APK / Root app tests (push) Successful in 31s
Forgejo Android APK / Build signed APK (push) Successful in 1m57s
2026-09-07 07:45:48 +02:00
Daniel
dc83f6e21b fix: preserve export navigation and clinical source boundaries 2026-09-07 07:10:47 +02:00
Daniel
b0bebe6970 fix: preserve saved clinical tables and per-turn citation targets 2026-09-07 05:58:12 +02:00
Daniel
cfaf8e957b feat: ship reviewed prompt history, conversation limits and account protections 2026-09-07 04:01:01 +02:00
Daniel
5c5d68a7c1 fix: make manual CMS category creation visible and keyboard-accessible
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m46s
2026-09-07 01:16:40 +02:00
Daniel
baab83e50e fix: enforce sessions, escape quiz metadata and isolate ED drafts
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m47s
2026-09-06 07:44:08 +02:00
Daniel
2942d4f6b3 Revert "Sanitize citations from clinical image prompts"
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m43s
This reverts commit 7833018695.
2026-09-02 01:50:44 +02:00
Daniel
7833018695 Sanitize citations from clinical image prompts
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m47s
2026-09-02 01:47:32 +02:00
Daniel
491f5e02b7 Render escaped clinical citations as links
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m49s
2026-09-01 19:19:11 +02:00
Daniel
e4dacbaf09 Rejoin detached clinical citations
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m50s
2026-09-01 19:11:18 +02:00
Daniel
34eef6ec6b Keep prose citations inline
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m50s
2026-09-01 18:51:39 +02:00
Daniel
e71a7e22e1 Keep clinical citations inline
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m54s
2026-09-01 18:45:44 +02:00
Daniel
3d4a95fea4 Revert the clinical assistant markdown changes and fix mermaid rendering only
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m50s
Reverts 126d7928 and 2d292d12 in full. The markdown normaliser and the trailing
emphasis and dollar handling return to exactly the state tagged
pre-citation-fixes-20260828, which has been rendering acceptably in use.

The one change kept is mermaid. DOMPurify 3.1.6 strips an attribute whose value
contains "-->", and every mermaid flowchart contains one, so the sanitiser
removed data-mermaid and querySelectorAll('[data-mermaid]') never matched: the
diagram sat on "Rendering graph..." forever. Reproduced against the exact pinned
build from cdnjs; sequence diagrams using "->>" were unaffected, which is why
only flowcharts failed.

The diagram source is now percent-encoded into the attribute and decoded when
read, so no arrow ever appears in an attribute value. Nothing about the
sanitiser configuration changes and no markup is newly allowed. The reader
tolerates an unencoded value, so anything already in flight still renders.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 19:55:03 +02:00
Daniel
2d292d12af fix: make the markdown repairs line aware so tables and ranges survive
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m58s
The earlier fix corrected two of the repair rules and left the rest with the same
flaw, and the punctuation boundary it introduced let the table case back in. A
review found the remainder.

Every repair rule inserted newlines with no idea whether it was inside a markdown
table row. A dose row such as "| Dexamethasone | 0.6 mg/kg PO (max 16 mg) - single
dose | 1 |" was split mid-row, which drops that row's citation and every row
below it out of the table. A "#" column destroyed the table outright. The rules
now skip table rows, dividers and headers entirely.

Ranges were still split in three other places: in a heading, so "### Dexamethasone
0.15 - 0.6 mg/kg" rendered as a heading reading "Dexamethasone 0.15"; after a
citation; and beside a hash, where "Room # 4" became a heading. A hyphen now
starts a list item only when a number does not follow, and a run-together heading
is recognised by the capital letter after the hashes rather than by position.

Adjacent citation merging could also cross a paragraph break, turning "[1]\n\n[2]
Vancomycin only if MRSA" into "[1, 2]Vancomycin only if MRSA" -- joining two
paragraphs and moving a citation onto a claim it never supported. Merging is now
limited to citations on the same line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 19:49:01 +02:00
Daniel
126d7928a2 fix: stop the markdown normaliser mangling doses, bold and dollar amounts
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m52s
Three rendering defects in the clinical assistant, all confirmed by running the
code rather than reading it.

A spaced hyphen anywhere in a sentence was rewritten as a list item, so every
numeric range written that way was split in two:

    "Give dexamethasone 0.15 - 0.6 mg/kg orally."
      -> "Give dexamethasone 0.15\n- 0.6 mg/kg orally."

which renders as a truncated sentence followed by a bullet, and a dose range
therefore reads as a different dose. The same applied to SpO2 targets, pH ranges
and age ranges. A hyphen now starts a list item only at the beginning of a line
or after sentence punctuation, which still catches the case the rule was written
for.

An answer ending in a bold phrase lost its closing marker, because trailing
emphasis was stripped unconditionally and the strip ran twice. Only an unpaired
marker is removed now.

Inline maths swallowed dollar amounts: "Costs $5 to $10 per dose" rendered the
text between the signs as an equation and dropped both signs. A $...$ span is
now treated as maths only when it contains something mathematical, so subscripts
and fractions still render.

Citation handling is unchanged and covered by the same tests: clusters still
merge and sort, unknown source numbers stay literal, links still resolve by index,
and bare numbers in a table's Source column still become bracketed tokens.

The state before these fixes is tagged pre-citation-fixes-20260828.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 19:20:39 +02:00
Daniel
c88cc6a547 Prevent citations in clinical image prompts
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m58s
2026-08-28 03:23:18 +02:00
Daniel
3fb4c10f2b Point the APK download link at Forgejo
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 2m48s
The login page linked to
github.com/ifedan-ed/pediatric-ai-scribe-v3/releases/latest, which returns
404 — releases are published to git.danvics.com by the Forgejo APK
workflow. Verified: the Forgejo URL returns 200, the GitHub one 404.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 01:17:29 +02:00
Daniel
f31afcdbf4 Fix biometric login, and keep recording alive across screen lock
Biometric sign-in has never worked. auth.js drove
window.Capacitor.Plugins.NativeBiometric — the API of
capacitor-native-biometric, which is not a dependency of this project. The
installed plugin is @aparajita/capacitor-biometric-auth, registered as
BiometricAuthNative with an entirely different API and no credential
storage at all. bioPlugin() therefore always returned null, bioAvailable()
always resolved {ok:false}, and the button was never revealed.

Rewritten against what is actually installed, with no new dependency:
BiometricAuthNative (checkBiometry/authenticate) presents the prompt, and
the already-working SecureStoragePlugin — via the window.SecureStorage
wrapper — holds the credentials. Credentials are only read after
authenticate() resolves, so the OS still gates access. biometryType is a
numeric enum in this plugin, so the old FACE_ID/TOUCH_ID string maps are
replaced with a single lookup exposed as typeName.

Secure storage itself was fine and is unchanged: SecureStoragePlugin
matches the name the wrapper looks up and is registered in
capacitor.settings.gradle.

Recording across screen lock: window.nativeKeepAwake() called Capacitor's
KeepAwake plugin, which is also not installed here, so it silently did
nothing and the device slept mid-encounter — taking the WebView's
MediaRecorder with it. keepAwake() is now a method on the existing
NativeRecording JavascriptInterface, which sets FLAG_KEEP_SCREEN_ON, and
is bound to the WebView so it survives the launcher's navigation to the
remote origin. The Capacitor plugin remains a fallback.

If the screen is locked anyway (power button, incoming call), the activity
pauses and Chromium throttles timers for hidden WebViews, starving
MediaRecorder's chunk delivery. MainActivity now calls resumeTimers() on
pause while recording. The foreground service was already correct — it
holds a partial wake lock and declares FOREGROUND_SERVICE_TYPE_MICROPHONE.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 01:12:47 +02:00
Daniel
524ad40d49 Match TTS voices to the selected LiteLLM model
Voice lists were a single flat set from LITELLM_TTS_VOICES, so picking a
model could leave an incompatible voice selected and the request would
fail at the gateway. Voices are now resolved per model family (Kokoro,
Kitten, Supertonic, Groq Orpheus EN/AR), with a compatibility check that
falls back through user → admin → env → first valid voice. Groq Orpheus
requests also pin response_format to wav.

Also refreshes the cardiac/respiratory auscultation samples, extends the
well-visit component, and fixes the Android launch theme background
(@null → colorPrimary) so the splash does not flash through.

NOTE: this is in-progress work that was already sitting uncommitted in
the working tree; it is committed here as-is so the tree was clean for
the release bump.
2026-07-30 17:34:34 +02:00
Daniel
82ed46d01b Fix Turnstile in the mobile app; drop it from login
The Turnstile challenge failed reliably inside the Capacitor WebView,
which blocked login and registration from the Android app.

Three separate causes:

1. Android WebView blocks third-party cookies by default. Turnstile runs
   in a cross-origin iframe from challenges.cloudflare.com and needs its
   own storage, so the widget never emitted a token. MainActivity now
   calls setAcceptThirdPartyCookies on the app's own WebView.

2. The register handler read the Turnstile response with an unscoped
   document.querySelector, which matched the *login* widget's input (it
   comes first in the DOM). Registration therefore submitted the login
   widget's token — single-use with a 5 minute expiry, so any prior login
   attempt or slow signup made it fail server-side.

3. The register and forgot-password widgets auto-rendered inside forms
   that start at display:none, where Turnstile does not reliably complete
   a challenge, and nothing re-rendered them when the form was shown.

Widgets are now rendered explicitly when their form first becomes
visible, and tokens are captured from the render callback instead of
being read back out of the injected input — which makes the unscoped
lookup in (2) structurally impossible. Added error/expired/timeout
callbacks so a widget failure surfaces the Cloudflare error code instead
of failing silently behind a generic toast.

Login is no longer gated at all. It is the path mobile users hit
constantly, and it is already covered by a 10-per-15-min per-IP rate
limit, a constant-time credential check, and TOTP 2FA. Registration and
password reset — the endpoints that actually attract bots — stay gated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 17:22:03 +02:00