eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
196 lines (195 loc) • 11.1 kB
TypeScript
import type { SessionAuthContext } from "#channel/types.js";
import type { SessionContext } from "#public/definitions/callback-context.js";
import type { ChannelSessionOps } from "#public/definitions/defineChannel.js";
import type { HandleMessageStreamEvent } from "#protocol/message.js";
import { type TwilioApiOptions, type TwilioApiResponse, type TwilioCredentials } from "#public/channels/twilio/api.js";
import { type TwilioTextMessage, type TwilioVoiceCall, type TwilioVoiceTranscription } from "#public/channels/twilio/inbound.js";
import { type TwilioAuthToken, type TwilioWebhookUrl } from "#public/channels/twilio/verify.js";
import { type Channel } from "#public/definitions/defineChannel.js";
type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
type: T;
}> extends {
data: infer D;
} ? D : undefined;
/** Pre-dispatch Twilio context passed to the inbound text, voice, and voice-transcription hooks. */
export interface TwilioContext {
readonly twilio: TwilioHandle;
}
/** Channel-owned Twilio context returned by `context()`. */
export interface TwilioChannelContext extends TwilioContext {
state: TwilioChannelState;
}
/** Event-handler Twilio context, including session operations. */
export interface TwilioEventContext extends TwilioChannelContext, ChannelSessionOps {
}
/** JSON-serializable state for the phone-number conversation. */
export interface TwilioChannelState {
/** Caller / sender phone number. */
from: string | null;
/** Twilio number or sender that received the latest session-starting webhook. */
to: string | null;
/** Most recent inbound SMS SID when this session was started by text. */
lastMessageSid?: string | null;
/** Most recent inbound Call SID when this session was started by voice. */
lastCallSid?: string | null;
}
/** Per-session instrumentation snapshot for Twilio runtime telemetry. Reports the active phone-number pair and the most recent message and call SIDs. */
export interface TwilioInstrumentationMetadata extends Record<string, unknown> {
readonly from: string | null;
readonly lastCallSid: string | null;
readonly lastMessageSid: string | null;
readonly to: string | null;
}
/** Twilio channel credentials. `authToken` also verifies inbound webhook signatures. */
export interface TwilioChannelCredentials extends TwilioCredentials {
readonly authToken?: TwilioAuthToken;
}
/** Target accepted by `receive(twilio, { target })` for proactive phone-number sessions. */
export interface TwilioReceiveTarget {
readonly phoneNumber: string;
/** Twilio sender included in the phone-pair continuation token. */
readonly from?: string;
}
/** Result of an inbound Twilio text or transcription hook. Return `null` (or `undefined`) to drop the webhook without dispatching; otherwise supply the session `auth` context. */
export type TwilioInboundResult = {
auth: SessionAuthContext | null;
} | null;
/** Sync or async {@link TwilioInboundResult}. */
export type TwilioInboundResultOrPromise = TwilioInboundResult | Promise<TwilioInboundResult>;
/** Phone-number allow list for inbound Twilio webhook triggers. `"*"` allows every sender. */
export type TwilioAllowFrom = string | readonly string[] | (() => string | readonly string[] | Promise<string | readonly string[]>);
/**
* Result of an inbound Twilio voice hook. Return `null` to reject the call.
* Any result other than `null` accepts the call and can override the answering TwiML.
*/
export interface TwilioVoiceResult {
/** Prompt spoken before Twilio starts speech recognition. */
readonly prompt?: string;
/** BCP 47 language used for speech recognition and the nested `<Say>` prompt. */
readonly language?: string;
/** Twilio `<Say voice>` used for the prompt, e.g. `Polly.Joanna-Neural`. */
readonly voice?: string;
/** Twilio `<Gather speechModel>` used for speech recognition. */
readonly speechModel?: string;
/** Twilio `<Gather timeout>` in seconds. */
readonly timeoutSeconds?: number;
/** Twilio `<Gather speechTimeout>`, such as `"auto"` or a second count string. */
readonly speechTimeout?: string;
/** Twilio `<Gather hints>` for expected words or phrases. */
readonly hints?: string | readonly string[];
/** Twilio `<Gather profanityFilter>` toggle. */
readonly profanityFilter?: boolean;
}
/** Sync or async {@link TwilioVoiceResult}. */
export type TwilioVoiceResultOrPromise = TwilioVoiceResult | null | undefined | Promise<TwilioVoiceResult | null | undefined>;
type TwilioEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: TwilioEventContext, ctx: SessionContext) => void | Promise<void>;
type TwilioSessionFailedHandler = (data: EventData<"session.failed">, channel: TwilioEventContext) => void | Promise<void>;
/** Event handlers supported by `twilioChannel({ events })`. */
export interface TwilioChannelEvents {
readonly "turn.started"?: TwilioEventHandler<"turn.started">;
readonly "actions.requested"?: TwilioEventHandler<"actions.requested">;
readonly "action.result"?: TwilioEventHandler<"action.result">;
readonly "message.completed"?: TwilioEventHandler<"message.completed">;
readonly "message.appended"?: TwilioEventHandler<"message.appended">;
readonly "input.requested"?: TwilioEventHandler<"input.requested">;
readonly "turn.failed"?: TwilioEventHandler<"turn.failed">;
readonly "turn.completed"?: TwilioEventHandler<"turn.completed">;
readonly "session.failed"?: TwilioSessionFailedHandler;
readonly "session.completed"?: TwilioEventHandler<"session.completed">;
readonly "session.waiting"?: TwilioEventHandler<"session.waiting">;
readonly "authorization.required"?: TwilioEventHandler<"authorization.required">;
readonly "authorization.completed"?: TwilioEventHandler<"authorization.completed">;
}
/** SMS/Messaging defaults for Twilio outbound replies. */
export interface TwilioMessagingConfig {
/** Sender phone number. Defaults to the inbound `To` number when available. */
readonly from?: string;
/** Messaging Service SID. Used instead of `from` when supplied. */
readonly messagingServiceSid?: string;
/** Optional Twilio status callback URL for outbound messages. */
readonly statusCallbackUrl?: string;
}
/** Voice webhook defaults for accepting calls and gathering speech. */
export interface TwilioVoiceConfig {
/** Prompt spoken when a caller reaches the voice route. */
readonly prompt?: string;
/** Twilio `<Say voice>` used for the prompt, e.g. `Polly.Joanna-Neural`. */
readonly voice?: string;
/** Spoken acknowledgement after a transcription webhook is accepted. */
readonly acknowledgement?: string;
/** BCP 47 language used for speech recognition and the nested `<Say>` prompt. */
readonly language?: string;
/** Twilio `<Gather speechModel>` used for speech recognition. */
readonly speechModel?: string;
/** Twilio `<Gather timeout>` in seconds. */
readonly timeoutSeconds?: number;
/** Twilio `<Gather speechTimeout>`, such as `"auto"` or a second count string. */
readonly speechTimeout?: string;
/** Twilio `<Gather hints>` for expected words or phrases. */
readonly hints?: string | readonly string[];
/** Twilio `<Gather profanityFilter>` toggle. */
readonly profanityFilter?: boolean;
}
/** Configuration for {@link twilioChannel}. */
export interface TwilioChannelConfig {
readonly credentials?: TwilioChannelCredentials;
/**
* Base route for Twilio webhooks. Defaults to `/eve/v1/twilio` and
* mounts `/messages`, `/voice`, and `/voice/transcription` below it.
*/
readonly route?: string;
/**
* Public URL Twilio used for signing. Set this when proxies or local
* tunnels make `request.url` differ from the configured webhook URL.
*/
readonly webhookUrl?: TwilioWebhookUrl;
/** Public base URL used to render absolute voice `<Gather action>` URLs. */
readonly publicBaseUrl?: string | ((request: Request) => string | Promise<string>);
/**
* Exact caller/sender numbers allowed to reach inbound hooks, or `"*"` to
* allow every verified Twilio sender. Resolvers run on each inbound webhook.
*/
readonly allowFrom: TwilioAllowFrom;
readonly messaging?: TwilioMessagingConfig;
readonly voice?: TwilioVoiceConfig;
readonly api?: Omit<TwilioApiOptions, "credentials">;
/** Inbound text hook. Defaults to phone-number auth and dispatch. */
onText?(ctx: TwilioContext, message: TwilioTextMessage): TwilioInboundResultOrPromise;
/** Inbound voice hook. Return `null` to reject the call before gathering speech. */
onVoice?(ctx: TwilioContext, call: TwilioVoiceCall): TwilioVoiceResultOrPromise;
/** Inbound voice transcription hook. Defaults to phone-number auth and dispatch. */
onVoiceTranscription?(ctx: TwilioContext, transcription: TwilioVoiceTranscription): TwilioInboundResultOrPromise;
readonly events?: TwilioChannelEvents;
}
/** Low-level Twilio handle exposed to hooks and event handlers. */
export interface TwilioHandle {
/** Caller / sender phone number bound to this conversation. */
readonly from: string;
/** Twilio receiver / sender number for replies, when known. */
readonly to: string | undefined;
/** Most recent call SID, when the session started from a voice transcription. */
readonly callSid: string | undefined;
/** Raw Twilio REST API escape hatch. `path` is appended to the API base URL (default `https://api.twilio.com`). `body` fields are POSTed as form-encoded parameters. */
request(path: string, body: Readonly<Record<string, string | number | boolean | undefined | null>>): Promise<TwilioApiResponse>;
/** Sends a text message to this conversation's phone number by default. */
sendMessage(message: string, options?: TwilioSendMessageOptions): Promise<TwilioApiResponse>;
/** Updates a live call with replacement TwiML. */
updateCall(callSid: string, twiml: string): Promise<TwilioApiResponse>;
}
/** Per-call overrides for {@link TwilioHandle.sendMessage}. */
export interface TwilioSendMessageOptions {
/** Recipient phone number. Defaults to the conversation's `from` number. */
readonly to?: string;
/** Sender phone number. Defaults to `messaging.from`, falling back to the inbound `To` number. */
readonly from?: string;
/** Messaging Service SID. Defaults to `messaging.messagingServiceSid`. */
readonly messagingServiceSid?: string;
/** Twilio status callback URL. Defaults to `messaging.statusCallbackUrl`. */
readonly statusCallbackUrl?: string;
}
/** Concrete return type of {@link twilioChannel}. */
export interface TwilioChannel extends Channel<TwilioChannelState, TwilioReceiveTarget, TwilioInstrumentationMetadata> {
}
/** Twilio channel factory for SMS and speech-transcribed inbound calls. */
export declare function twilioChannel(config: TwilioChannelConfig): TwilioChannel;
export {};