Twilio now handles only the in-browser dial pad (Access Token + browser-Device
outbound TwiML); Telnyx takes over SMS, inbound voicemail, the AI voice
conversation loop, and staff-triggered outbound calls via TeXML. Adds
TelnyxSettings model, Communication.provider discriminator, new comms/routes
modules, and a real Telnyx Settings page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Add remainingBenefit and thirdPartyInsurance columns to Patient; extract both
from the MassHealth accumulator/member-detail pages during the eligibility
check and surface them in the eligibility table
- Add an updated-date display and a toggle to suppress the post-check PDF
viewer popup (default off) on the insurance eligibility page
- Rename CMSP-prefixed PDF filenames and UI copy to MH, since CMSP and MH now
share the same worker
- Fold CMSP into MassHealth/MH across patient/claim insurance-type dropdowns
and the chatbot's eligibility routing, since they're the same insurance
- Remove auto-download of saved eligibility PDFs; downloading is now manual
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Only block appointment creation on explicit INACTIVE status, since
scrapes for some plan types (e.g. MassHealth Child Medicaid) can land
on UNKNOWN without actually finding an ineligible record.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a new recall conversation flow (recall-graph.ts) triggered from the
Patient Connection "AI Call" button: offers an existing patient a routine
exam & cleaning, classifies their yes/no reply, then books directly onto
the schedule (Column A, 30-minute slots, real conflict checking against
office hours and existing appointments) instead of only capturing a
preference for staff to follow up on.
Also adds a "Voice call" label in the message thread to distinguish call
transcripts from SMS, and updates the Call Templates settings UI with an
editable recall greeting.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds an "AI Call" option alongside Call/SMS/Chat that places an outbound
call where Lisa converses live with the patient via Twilio speech
gather + TTS, using the same conversational AI as chat. Includes a
separate, user-editable Call Template (Settings > AI Chat/Call Settings)
so the call greeting can be customized independently of SMS templates.
Also fixes the outbound-call webhook URL to always use the fixed public
Twilio hostname (CLOUDFLARE_HOST) instead of deriving it from the
triggering request, since staff-browser requests arrive over the
LAN-only hostname, which Twilio can never reach.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces fragile whole-screen text matching with a screenshot-diff step that
finds each dialog's actual pixel bounds, then restricts every subsequent AI
locate/click to that cropped region — eliminating false matches from text
elsewhere on screen (title bars, side panels). Adds column-boundary and
row-height detection so the patient row and Exam procedure click positions
are computed geometrically instead of relying on repeated fuzzy AI guesses
for visually similar neighbors. Also adds per-run screenshot/debug-crop
backups and a structured run.log for diagnosing failed runs, plus a
cmd:move primitive on the Windows agent for pre-click confirmation crops.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a Windows-side agent (screenshot/click/type over HTTP) plus backend
services to locate UI elements via vision and drive an existing-patient
appointment flow in Open Dental, wired into the Copy/Type Agent page and
socket progress updates.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Chatbot: submitting with only a screenshot attached (no text) now triggers the same
"AI Detect & Check Eligibility" flow as the Copy Agent page
- detect-eligibility-info now also extracts the visible insurance payer name and picks
Tufts SCO auto-check when both Sun Life and DentaQuest are detected, else MassHealth
- Chatbot-attached files are now handed off to both claim and preauth forms unconditionally,
not just claims
- TuftsSCO preauth Selenium worker: verify-and-retry the Tooth field (typing was silently
getting reset by duplicate-procedure-code warning banners), add a final re-verification
pass across all rows, fix acknowledgement-checkbox targeting/verification, and verify
the "Next step" click actually advances the wizard instead of trusting a blind click
- Member ID and DOB in the AI chat "patient found" confirmation card are now
editable inputs, and edits are persisted back to the patient record before
proceeding so corrections don't revert to stale values.
- Fix auto-lookup-by-member-ID effect on the insurance status page clobbering
a hand-edited DOB with the stale DB value during chatbot prefill.
- CMSP (under-14) eligibility flow was missing the appointment-creation hook
that the adult MassHealth flow already had, so under-14 patients never got
scheduled after a chatbot-initiated "eligibility & appointment" request.
- For already-known patients, the chatbot was creating the appointment before
running the eligibility check instead of after; now eligibility is always
checked first and the appointment created only afterward, and only when the
resulting patient status is ACTIVE.
- AI claim queue now uses previously saved AppointmentProcedure data (with a derived insurance site key) when an appointment has no notes but has saved procedures, instead of skipping with "No notes on this appointment"
- selenium-claim route now reads saved AppointmentFile attachments from disk when they weren't re-uploaded in the browser, so images/PDFs already attached via "Select Procedures" reach the MassHealth submission
Adds From/To date pickers and CCA PA / United PA / Tufts PA / All recent PA
buttons above the Upload claim documents section; button logic is stubbed
for now.
Adds an "AI Detect & Check Eligibility" action to the Copy Agent page that
sends captured screenshots to Claude to extract Member ID/DOB, then opens
the chatbot's eligibility confirm step pre-filled with the result.
- POST /api/ai/detect-eligibility-info: Claude vision extraction of
Member ID/DOB from uploaded screenshots.
- POST /api/patients/create-temp: auto-creates a placeholder "PID-<id>"
patient (matched by insuranceId+dob) when no patient is selected, so
screenshots can be saved immediately; the real eligibility check later
rewrites the patient's name and Cloud Storage folder automatically via
the existing createOrUpdatePatientByInsuranceId matching logic.
- Chatbot: Member ID/DOB on the confirm card are now editable (MM/DD/YYYY),
with edits synced back to the patient record before the check runs.
- Fixed a useEffect ordering bug on the insurance-status page that could
silently clear a chatbot-prefilled Member ID/DOB before the auto-trigger
effect ran, preventing the eligibility check from ever starting.
- Added a local-disk-only screenshot backup (apps/Backend/uploads/
screenshot-backups/) for debugging, not exposed anywhere in the UI.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Staff can now capture their screen via the browser's Screen Capture
API, crop the result, name the file, and save it directly to a
selected patient's Cloud Storage attachments folder.
Missed these five Number(...) coercions when widening PDF ids to support the
"cloud:<id>" format — member details/history/accumulator panels in the MH and
CMSP multi-PDF viewers were fed NaN, which usePdfBlob treats as falsy and
never fetches. Only the first panel (eligibility) used the already-fixed
pdfFileId field, so it worked while the rest silently stayed blank.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New saves go into the patient's Cloud Storage folder under category subfolders
(Eligibility/Claims/PreAuth/Claim Status/Attachments) via a new
storage.savePdfToCloudStorage helper, instead of the legacy PdfGroup/PdfFile
Postgres blob tables. Old records and their read paths are left untouched for
backward compatibility; PDF list/content/delete endpoints and viewers now
transparently handle both legacy numeric ids and new "cloud:<id>" ids.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Renames the sidebar entry to "AI Copy/Type Agent" with Copy Agent, Type
Agent, and Settings sub-pages. Settings shows the server's LAN IP
address (via a new /api/ai/network-info endpoint) since it changes
depending on which office the app is running in.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Vite resolves .tsx before .jsx (per extensions order in vite.config.ts),
so .jsx files were never loaded at runtime. Switching to TSX-only source.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
selenium-settings-card.jsx didn't exist and settings-page.jsx was missing
the import and case "selenium" handler, so the Selenium settings section
was invisible on other PCs running the .jsx files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a new Settings → Advanced → Selenium Settings page where the office
name (paymentGroupId) used in United/DentalHub portal dropdowns can be
configured without touching code. Previously hardcoded as "Summit Dental
Care"; now injected from DB into the three United workers at job dispatch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Redesign lab management tab with patient search table and action buttons
- Add react-barcode integration: generates CODE128 barcode from patient name with print and download support
- Add Dental Education page and sidebar entry between Cloud Storage and AI Input Agent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
handleClaimSubmit advanced the chatbot batch claim queue right after creating
the DB claim record, before the Selenium job even ran. This caused only the
last patient in a multi-patient claim batch to get its PDF saved to
Documents — earlier patients' job tracking got overwritten by the next
patient's submission before their PDF download could complete.
Also make advanceChatbotClaimQueue() report whether it navigated to another
queued patient, and skip the auto PDF preview popup in that case so it only
opens for the last/standalone claim.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add multi_claim intent so AI correctly handles "claim X for patient A and Y for patient B"
instead of applying all procedures to all patients (batch_claim)
- Each patient carries their own matchedCodes in the queue
- Fix batch claim PDF race condition: chatbot queue no longer advances in closeClaim(),
instead advances after selenium PDF is downloaded (matching column claim behavior)
- Align United SCO eligibility worker with claim worker: only fill subscriber ID + DOB,
use treatmentLocation by ID instead of arrow-wrapper click
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add "recement" example to LLM classifier so it spreads across multiple
teeth (recement #5, #3 → two D2920 entries). Add "today" to the AI
column claim message so the LLM sets appointmentDate instead of asking
"Which service date?"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add "comp" as alias for composite in CDT lookup. Update classifier
prompt with explicit examples for "claim comp #8 ml for lisa today"
and dental surface letter definitions (M/D/L/F/B/O/V/I) so the LLM
correctly treats #tooth+surfaces as composite fillings, not insurance.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a toggle behind the Go button on the Payments page to automatically run the MH batch payment check on a user-selected day of week and hour. Default is off.
- Schema: added autoMhCheckEnabled, autoMhCheckDayOfWeek, autoMhCheckHour to User model
- Backend: new mhBatchPaymentService (shared logic), GET/PUT /auto-mh-check-setting routes, hourly cron job that fires on matching day+hour
- Frontend: toggle + day select (Mon–Sun) + time select (hourly) that persist immediately to DB
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PDF import now marks payments as PAID when MassHealth patient's
mhPaidAmount >= totalBilled (no patient balance)
- Newly created patients from MH vouchers get insuranceProvider = 'MassHealth'
- Existing patients with blank insuranceProvider get it filled on import
- Fix: update patient name from PDF if existing record has empty name
- Various frontend/selenium/route updates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace hardcoded 8 PM / 9 PM backup schedules with user-selectable
hour dropdowns. Adds autoBackupHour and usbBackupHour fields to User
model. Cron jobs now check every hour against the configured time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- appointments-page: save full queue from current patient on confirm so that
cancelling the claim form resumes at the same patient instead of skipping it
- claims-page: advance ai_claim_queue only after successful submission (CCA,
MH selenium PDF download, or direct non-draft submit) via new advanceAiClaimQueue()
- cdt-lookup: fix extractToothSurface regex to allow space between # and digit
(e.g. "# 32") so tooth number is correctly captured
- cdt-lookup: silently skip bare tooth-number tokens ("# 32", "#32") that the
LLM may emit as standalone items, preventing false "unrecognized procedure" errors
- internal-chat-graph: add explicit rule that a CDT code followed by # NN
(e.g. "D7210 # 32") must stay as one entry and not spread to other procedures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add batch_eligibility_by_name intent so "check Mary and Sinthia" resolves multiple names
- Add "Check All & Appointment Today" button to batch eligibility UI — creates appointment for each patient after their eligibility check completes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add batch_eligibility, batch_claim, and batch_check_and_claim intents
to AI classifier so multiple patients can be processed one by one
- Add queue processing on insurance-status and claims pages to auto-start
the next patient after each check/claim completes
- Make patient schema firstName, lastName, phone optional so patients can
be created with just member ID + DOB from eligibility checks
- Cancel buttons now preserve chat history instead of clearing it
- Patient-found card shows Check Eligibility, Eligibility & Appointment
Today, and Cancel buttons
- Claim service date asks user to pick between latest appointment and
today when they differ
- Login page subtitle styled with animated gradient
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The chatbot-extracted DOB was stored in chatbot_claim_codes but never
forwarded to chatbot_claim_prefill, leaving the claim form DOB empty
when the patient DB record lacked it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add public /api/greeting endpoint that generates a daily AI greeting (cached per day)
- Replace static hero text with dynamic AI greeting (ChatGPT/Claude style)
- Add Stripe-style animated gradient blobs with 14 daily-rotating color palettes
- Use Plus Jakarta Sans font and Sparkles icon for modern AI look
- Update subtitle to "Driven by multiple AI agents"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claims no longer auto-create a schedule appointment when submitted — appointmentId is now optional.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add preauth intent to AI chatbot (classifier, workflow, frontend UI card)
- Auto-prefill preauth form with CDT codes, service date, and mapped prices
- Auto-trigger preauth Selenium handler by insurance siteKey (MH/Tufts/CCA/UnitedDH)
- Default tentative service date to today+3 for preauth (user didn't pick a date)
- Fix #number always means tooth number, distributes to all procedures in comma list
- Fix bare "post"/"pos" → D2954 (was matching D2955 via keyword scorer)
- UnitedDH pre-auth: fill procedure date with Ctrl+A to overwrite prefilled value
- UnitedDH pre-auth: select Location "Summit Dental Care" in step1 (same as billing entity)
- UnitedDH pre-auth: remove page refresh in step9 to preserve pre-auth number
- UnitedDH pre-auth: wait for table rows before extracting pre-auth number
- UnitedDH pre-auth/claim: explicit wait for Submit button after file upload (no sleep)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- claims-page: after auto-submit closes the form, automatically navigate
back to /appointments when an AI claim queue is pending resume, eliminating
the manual navigation delay between appointments
- internal-chat-workflow: warn and block claim when D1120 (child prophy) is
requested for a patient aged 14+ — recommend D1110 (adult prophy) instead,
and advise manual claim if user insists on D1120
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- parseSrpCode: recognize "D4341 UL" / "4341 LR" etc., store quadrant in quad field
- matchOne: auto-prefix D for 4-digit inputs like "0120" → D0120
- LLM prompt: keep SRP code and quadrant together as one procedureName entry
- CdtMatch / CdtResult: add quad field, thread through matchedCodes action data
- claim-form.tsx: include quad in chatbot_claim_prefill type and spread to service line
- selenium_claimSubmitWorker.py: pass quad to fill_service_line, select quadrant
dropdown by index (UR=1, UL=2, LL=3, LR=4) matching MassHealth form structure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Claim file uploads (chatbot or manual) now save to both the Cloud
Storage patient folder and the Documents page via new
POST /api/claims/upload-to-cloud endpoint
- MH submit flow now calls uploadAttachmentsToLocalFolder (same as
DDMA/United/Tufts) so chatbot-attached X-rays are persisted
- Removed old /upload-attachments disk route and attachmentDiskStorage
multer config; deleted uploads/patients/ folder
- uploadAttachmentsToLocalFolder now points to /upload-to-cloud and
sends patientId so the backend can create the patient folder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UI-only stub — logic to be defined. Mirrors the existing Claim for
Column section with its own column checkboxes and loading state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove auto-appending of "Appointment with [staff name]" to notes on
save, and preserve existing notes when dragging an appointment to a
new slot.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add "Eligibility & Appointment" button to chatbot eligibility-id-ready card
- For known patients: creates today's appointment immediately, then opens eligibility page
- For unknown patients: navigates to eligibility page; after Selenium creates the patient,
auto-creates appointment via tryAppointmentFromChatbot on the insurance-status page
- Update MH Eligibility & Appointment button to create a today's schedule slot instead of
navigating to the appointments page; shows PDF preview on completion
- createAppointmentToday falls back from Column A to Column B when Column A is full;
returns column label in response so UI can display it
- Set AI-scheduled appointment duration to 15 minutes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PC2 can now automatically pull and restore a fresh copy of PC1's database
on a daily schedule. Config and API key are stored in local JSON files so
they survive database restores.
- New networkSyncConfigService: file-based config (network-backup-key.json,
network-sync-config.json) that persists through DB restores
- New networkSyncService: streams live pg_dump from source PC over HTTP and
pipes into psql, then reconnects Prisma and applies missing migrations
- 6 new endpoints: get/regenerate API key, serve backup stream (key-auth
only), get/save sync config, trigger immediate sync
- Hourly cron job that fires only when current hour matches configured syncHour
- NetworkBackupManager component: shows this machine's key (show/copy/regen)
and receiver config (enable toggle, hour picker 0-23, source URL + key,
Save + Sync Now, last sync status)
- README setup guide for both PCs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Chatbot: add paperclip button to attach X-ray/PDF files to claim submissions;
files flow through chatbotFileStore into claim-form uploadedFiles for Selenium
- CDT lookup: auto-select D3310/D3320/D3330 by tooth number for RCT; strip #NN
from procedure names before alias lookup so "1 pa, #3" → D0220 tooth 3;
add "1 pa" alias for D0220; expand multi-PA notation via AI prompt rule
- AI classifier: add navigate_eligibility intent ("check mh" → /insurance-status);
fix duplicate intent entry; add RCT and multi-PA prompt rules
- Check+claim flow: pass serviceDate through check_and_claim_ready actionData;
tryClaimFromChatbot skips PDF preview and navigates straight to claims with
memberId fallback lookup; wired into all provider onPdfReady callbacks
- Claims table: add Service Date column between Patient Name and Submission Date
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
step2: wait for patient list //tbody//tr then 3s stabilize; wait for patient
name link to be element_to_be_clickable before reading href; wait for Create
claim button to be element_to_be_clickable (visible+enabled) then 3s for React
to finish re-rendering.
step3: re-find Create claim button fresh each attempt (avoids stale element
from React re-render); try selenium click → js events → js.click() in sequence;
verify URL changed before declaring success.
step4: open tooth dropdown via JS focus (avoids element-not-interactable on
click); select the matching tooth number option directly from 1-32 listbox
instead of typing characters.
step7: find Submit claim button with individual XPaths to avoid NoneType crash.
claims-page: use wouter setLocation for URL param cleanup so internal search
state stays in sync.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>