feat(twilio): add Answering Machine Detection (AMD) support via telephony config (#443)

* feat(twilio): add Answering Machine Detection (AMD) support via telephony config

Closes #339

* chore: regenerate OpenAPI spec to fix drift-check

The openapi.json snapshot had drifted from the FastAPI app definition
because main gained new organization endpoints (billing, credits,
context) after this branch was created. Regenerate it with
'python -m scripts.dump_docs_openapi' to bring it back in sync.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add provider-level AMD hooks

* fix: handle db error while persisting amd result

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Sabiha Khan <sabihak89@gmail.com>
Co-authored-by: Sabiha Khan <87858386+chewwbaka@users.noreply.github.com>
This commit is contained in:
nuthalapativarun 2026-06-25 02:15:13 -07:00 committed by GitHub
parent 29c5be298c
commit d675fd1fda
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 380 additions and 66 deletions

View file

@ -5892,6 +5892,12 @@ export type TwilioConfigurationRequest = {
* List of Twilio phone numbers
*/
from_numbers?: Array<string>;
/**
* Amd Enabled
*
* Detect whether outbound calls are answered by a person or machine. Twilio may bill AMD as an additional per-call feature.
*/
amd_enabled?: boolean;
};
/**
@ -5916,6 +5922,10 @@ export type TwilioConfigurationResponse = {
* From Numbers
*/
from_numbers: Array<string>;
/**
* Amd Enabled
*/
amd_enabled?: boolean;
};
/**

View file

@ -47,7 +47,8 @@ interface ConfigFormDialogProps {
onSaved: () => void;
}
type FieldValues = Record<string, string | number | undefined>;
type FieldValue = string | number | boolean | undefined;
type FieldValues = Record<string, FieldValue>;
export function ConfigFormDialog({
open,
@ -104,7 +105,7 @@ export function ConfigFormDialog({
if (!isEdit) setValues({});
}, [providerName, isEdit]);
const updateField = (fieldName: string, value: string | number) => {
const updateField = (fieldName: string, value: FieldValue) => {
setValues((prev) => ({ ...prev, [fieldName]: value }));
};
@ -292,8 +293,8 @@ export function ConfigFormDialog({
interface FieldInputProps {
field: TelephonyProviderMetadata["fields"][number];
value: string | number | undefined;
onChange: (v: string | number) => void;
value: FieldValue;
onChange: (v: FieldValue) => void;
isEdit: boolean;
}
@ -335,6 +336,15 @@ function FieldInput({ field, value, onChange, isEdit }: FieldInputProps) {
/>
);
}
if (field.type === "boolean") {
return (
<Switch
id={`cfg-field-${field.name}`}
checked={Boolean(value)}
onCheckedChange={onChange}
/>
);
}
return (
<Input
id={`cfg-field-${field.name}`}