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>
34 lines
1.5 KiB
TypeScript
34 lines
1.5 KiB
TypeScript
import type { Request } from "express";
|
|
|
|
/**
|
|
* Public HTTPS origin this request arrived on (e.g. https://broadwaydental.mydentalofficemanagement.com).
|
|
* Derived from the Host header rather than an env var so it's automatically correct
|
|
* per-office — each office's nginx forwards its own public hostname in Host,
|
|
* and Cloudflare/Let's Encrypt terminate TLS in front of it either way.
|
|
*
|
|
* Only valid for requests that actually arrived via the public tunnel (i.e. inside
|
|
* a Twilio webhook handler). For anything triggered from the staff browser — which
|
|
* reaches the backend over the LAN-only local-* hostname — use getTwilioPublicBaseUrl()
|
|
* instead, since Twilio can never reach that LAN hostname to fetch a callback URL.
|
|
*/
|
|
export function getPublicBaseUrl(req: Request): string {
|
|
return `https://${req.get("host")}`;
|
|
}
|
|
|
|
/**
|
|
* Fixed public origin Twilio must use to call back into this office's server
|
|
* (e.g. for outbound-call TwiML webhooks). Comes from CLOUDFLARE_HOST, the
|
|
* per-office env var already reserved for this — not derived from the
|
|
* triggering request, since that request may have arrived over the LAN-only
|
|
* hostname, which Twilio cannot reach.
|
|
*/
|
|
export function getTwilioPublicBaseUrl(): string {
|
|
const host = process.env.CLOUDFLARE_HOST?.trim();
|
|
if (!host) {
|
|
throw new Error(
|
|
"CLOUDFLARE_HOST is not set — required to build a Twilio-reachable callback URL. Set it in .env to this office's public tunnel hostname."
|
|
);
|
|
}
|
|
return `https://${host}`;
|
|
}
|