feat: add internal AI chat assistant and AI Input Agent page

- Add Gemini-powered internal staff chatbot (free-text input in the
  upper-right bot panel): type "check MARIA GONZALES" to search patient
  and pre-fill eligibility, or "open claims" to navigate directly
- Add /api/ai/internal-chat endpoint with LangGraph + Google Gemini
  classifier (intent: check_eligibility, find_patient, navigate_*)
- Add Users AI Chat settings section in Settings > Advanced > AI Chat
  to configure a custom system prompt for the internal assistant
- Store internal chat system prompt in existing twilioSettings JSON
  blob (no DB migration needed)
- Add AI Input Agent sidebar entry and placeholder page describing
  planned keyboard-automation typing into Open Dental / Eaglesoft

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ff
2026-06-02 00:44:05 -04:00
co-authored by Claude Sonnet 4.6
parent 3ac185b0ec
commit be90966f6e
8 changed files with 707 additions and 101 deletions
@@ -0,0 +1,137 @@
import { Bot, Keyboard, FileCheck, CreditCard, Shield, Zap, ArrowRight } from "lucide-react";
import { Card, CardContent } from "@/components/ui/card";
const SOFTWARE_TARGETS = [
{ name: "Open Dental", color: "bg-blue-100 text-blue-700 border-blue-200" },
{ name: "Eaglesoft", color: "bg-emerald-100 text-emerald-700 border-emerald-200" },
{ name: "Dentrix", color: "bg-violet-100 text-violet-700 border-violet-200" },
{ name: "Curve Dental", color: "bg-orange-100 text-orange-700 border-orange-200" },
];
const CAPABILITIES = [
{
icon: <Shield className="h-5 w-5 text-teal-600" />,
title: "Eligibility Results",
description:
"Automatically type insurance eligibility information — coverage status, plan details, deductibles, and co-pays — directly into the patient chart in your dental software.",
},
{
icon: <FileCheck className="h-5 w-5 text-blue-600" />,
title: "Claim Information",
description:
"Transfer claim numbers, claim status updates, and denial reasons from the insurance portal results into your claims module without manual re-entry.",
},
{
icon: <CreditCard className="h-5 w-5 text-indigo-600" />,
title: "Insurance Payments",
description:
"Post ERA / EOB payment details — amounts, adjustments, patient responsibility — directly into your payment ledger by typing them into the active software window.",
},
];
export default function AiInputAgentPage() {
return (
<div className="max-w-3xl mx-auto px-4 py-10 space-y-10">
{/* Hero */}
<div className="text-center space-y-3">
<div className="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-violet-100 mb-2">
<Bot className="h-8 w-8 text-violet-600" />
</div>
<h1 className="text-3xl font-bold tracking-tight">AI Input Agent</h1>
<p className="text-muted-foreground text-base max-w-xl mx-auto">
An AI-powered agent that reads data from this app and types it directly into your
current dental management software — no copy-paste, no manual re-entry.
</p>
<span className="inline-block bg-amber-100 text-amber-700 text-xs font-semibold px-3 py-1 rounded-full border border-amber-200">
Coming Soon
</span>
</div>
{/* How it works */}
<Card>
<CardContent className="py-6 space-y-4">
<div className="flex items-center gap-2">
<Keyboard className="h-5 w-5 text-violet-500" />
<h2 className="text-base font-semibold">How it works</h2>
</div>
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-3 text-sm">
{[
"Retrieve data in this app\n(eligibility, claim, payment)",
"Agent identifies the active\nfield in your dental software",
"Types the value directly\nvia keyboard automation",
].map((step, i) => (
<div key={i} className="flex items-center gap-3 flex-1">
<div className="flex-shrink-0 w-7 h-7 rounded-full bg-violet-100 text-violet-700 text-xs font-bold flex items-center justify-center">
{i + 1}
</div>
<p className="whitespace-pre-line text-muted-foreground leading-snug">{step}</p>
{i < 2 && <ArrowRight className="h-4 w-4 text-muted-foreground/40 hidden sm:block flex-shrink-0" />}
</div>
))}
</div>
<p className="text-xs text-muted-foreground pt-1 border-t">
The agent runs as a lightweight local process on your workstation. It receives
instructions from this app and uses keyboard automation to type data into whatever
window is currently focused in your dental software — no clipboard involved.
</p>
</CardContent>
</Card>
{/* What it will type */}
<div className="space-y-3">
<h2 className="text-base font-semibold">What it will type</h2>
<div className="grid gap-4 sm:grid-cols-3">
{CAPABILITIES.map((cap) => (
<Card key={cap.title}>
<CardContent className="py-5 space-y-2">
<div className="flex items-center gap-2">
{cap.icon}
<span className="text-sm font-medium">{cap.title}</span>
</div>
<p className="text-xs text-muted-foreground leading-relaxed">
{cap.description}
</p>
</CardContent>
</Card>
))}
</div>
</div>
{/* Supported software */}
<div className="space-y-3">
<h2 className="text-base font-semibold">Planned software support</h2>
<div className="flex flex-wrap gap-2">
{SOFTWARE_TARGETS.map((s) => (
<span
key={s.name}
className={`text-sm font-medium px-3 py-1.5 rounded-lg border ${s.color}`}
>
{s.name}
</span>
))}
</div>
<p className="text-xs text-muted-foreground">
Each software has its own field layout. The agent will include pre-built templates
for common workflows in each platform.
</p>
</div>
{/* Why */}
<Card className="border-violet-200 bg-violet-50/50">
<CardContent className="py-5 flex items-start gap-3">
<Zap className="h-5 w-5 text-violet-500 mt-0.5 flex-shrink-0" />
<div className="space-y-1">
<p className="text-sm font-medium text-violet-900">Why this matters</p>
<p className="text-sm text-violet-700 leading-relaxed">
Staff currently check eligibility or look up a claim here, then manually retype
every value into Open Dental or Eaglesoft. This agent eliminates that step entirely —
one click sends the data straight into the right field.
</p>
</div>
</CardContent>
</Card>
</div>
);
}