twilio-agent-connect 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../packages/core/src/types/config.ts","../packages/core/src/types/handoff.ts","../packages/core/src/types/conversation.ts","../packages/core/src/types/tac.ts","../packages/core/src/lib/tac-memory-response.ts","../packages/core/src/types/memory.ts","../packages/core/src/types/crelay.ts","../packages/core/src/types/tools.ts","../packages/core/src/types/cintel.ts","../packages/core/src/types/knowledge.ts","../packages/core/src/lib/config.ts","../packages/core/src/util/log-redaction.ts","../packages/core/src/lib/logger.ts","../package.json","../packages/core/src/clients/base.ts","../packages/core/src/clients/memory.ts","../packages/core/src/clients/conversation.ts","../packages/core/src/clients/knowledge.ts","../packages/core/src/lib/operator-result-processor.ts","../packages/core/src/lib/tac.ts","../packages/core/src/channels/base.ts","../packages/core/src/channels/messaging.ts","../packages/core/src/channels/sms.ts","../packages/core/src/channels/rcs.ts","../packages/core/src/channels/whatsapp.ts","../packages/core/src/channels/chat.ts","../packages/core/src/util/handoff-urls.ts","../packages/core/src/channels/voice.ts","../packages/core/src/lib/conversation-session-helpers.ts","../packages/core/src/adapters/options.ts","../packages/core/src/adapters/prompt-builder.ts","../packages/tools/src/lib/builder.ts","../packages/tools/src/built-in/memory.ts","../packages/tools/src/built-in/messaging.ts","../packages/tools/src/built-in/handoff.ts","../packages/tools/src/built-in/knowledge.ts","../packages/server/src/lib/server.ts"],"names":["z","record","axios","session","Twilio"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * Channel types supported by the framework\n */\nexport const ChannelTypeSchema = z.enum(['sms', 'voice', 'chat', 'rcs', 'whatsapp']);\nexport type ChannelType = z.infer<typeof ChannelTypeSchema>;\n\n/**\n * Twilio Memory configuration schema\n */\nexport const TwilioMemoryConfigSchema = z.object({\n traitGroups: z.array(z.string()).optional(),\n observationsLimit: z.number().int().min(0).max(100).default(20),\n summariesLimit: z.number().int().min(0).max(100).default(5),\n // 0 matches the Memory API and Python SDK. Above 0, Memory requires a\n // conversationId on every /Recall, forcing the query expansion that\n // `memoryMode: \"once\"` exists to avoid.\n communicationsLimit: z.number().int().min(0).max(100).default(0),\n relevanceThreshold: z.number().min(0.0).max(1.0).default(0.0),\n /**\n * Trait group name that holds the phone identifier on newly created profiles.\n * Must match the promoted-to-identifier configuration of the Conversation Memory store.\n */\n phoneTraitGroup: z.string().default('Contact'),\n /** Trait field name within `phoneTraitGroup` that holds the phone identifier. */\n phoneTraitField: z.string().default('phone'),\n});\n\nexport type TwilioMemoryConfig = z.infer<typeof TwilioMemoryConfigSchema>;\n\n/**\n * Schema for a voice route path (e.g. voiceWebsocketPath). Trims whitespace,\n * maps an empty string to undefined so the `.default` applies, and requires a\n * leading '/' so path concatenation onto the domain can't produce a malformed\n * URL (e.g. `wss://example.comws`).\n */\nconst voicePathSchema = (defaultPath: string): z.ZodType<string> =>\n z.preprocess(v => {\n if (typeof v !== 'string') return v;\n const trimmed = v.trim();\n return trimmed.length === 0 ? undefined : trimmed;\n }, z.string().startsWith('/', 'Path must start with \"/\"').default(defaultPath));\n\n/** The three Twilio call callbacks TAC serves, one route per kind. */\nexport const CallEventKindSchema = z.enum(['status', 'amd', 'recording']);\n\nexport type CallEventKind = z.infer<typeof CallEventKindSchema>;\n\n/** Iterable form of {@link CallEventKind}, for registering every route. */\nexport const CALL_EVENT_KINDS: readonly CallEventKind[] = CallEventKindSchema.options;\n\n/**\n * TAC configuration schema\n */\nexport const TACConfigSchema = z.object({\n accountSid: z.string().min(1, 'Twilio Account SID is required'),\n authToken: z.string().min(1, 'Twilio Auth Token is required'),\n apiKey: z.string().min(1, 'Twilio API Key is required'),\n apiSecret: z.string().min(1, 'Twilio API Secret is required'),\n phoneNumber: z.string().min(1, 'Twilio Phone Number is required'),\n rcsSenderId: z\n .string()\n .regex(\n /^rcs:.+$/,\n 'RCS sender ID must be in format: rcs:<sender-id-or-phone> (e.g., rcs:brand_acme_agent or rcs:+1234567890)'\n )\n .optional(),\n whatsappNumber: z\n .string()\n .regex(/^whatsapp:\\+\\d+$/, 'WhatsApp number must be in format: whatsapp:+1234567890')\n .optional(),\n memoryConfig: TwilioMemoryConfigSchema.prefault({}),\n conversationConfigurationId: z\n .string()\n .regex(/^conv_configuration_[0-9a-z]{26}$/, 'Invalid Conversation Configuration ID format')\n .optional(),\n /**\n * Public domain where voice routes are reachable, optionally including a port\n * and/or base path (e.g. \"example.ngrok.app\", \"example.ngrok.app:8080\",\n * or \"example.com/server1\"). Used by VoiceChannel to construct the public\n * WebSocket URL and ConversationRelay action URL. Required when using the Voice channel.\n *\n * Whitespace, schemes (https://, wss://), and trailing slashes are stripped\n * automatically; anything else is passed through as given. Mirrors the Python\n * SDK's `_normalize_voice_public_domain` — keep the two in step.\n */\n voicePublicDomain: z\n .preprocess(v => {\n if (typeof v !== 'string') return v;\n let s = v.trim();\n if (s.length === 0) return undefined;\n for (const scheme of ['https://', 'http://', 'wss://', 'ws://']) {\n if (s.toLowerCase().startsWith(scheme)) {\n s = s.slice(scheme.length);\n break;\n }\n }\n s = s.replace(/\\/+$/, '');\n return s.length === 0 ? undefined : s;\n }, z.string().optional())\n .optional(),\n\n /**\n * Path the voice WebSocket is served at. Combined with voicePublicDomain to\n * build the public WebSocket URL the voice channel hands to Twilio in TwiML;\n * TACServer also registers its WebSocket route at this path. Override only if\n * you mount the route at a non-default path. Must start with '/'.\n */\n voiceWebsocketPath: voicePathSchema('/ws'),\n\n /**\n * Path the ConversationRelay action callback is served at. Same role as\n * voiceWebsocketPath but for the `<Connect action=...>` cleanup callback.\n * Must start with '/'.\n */\n voiceActionPath: voicePathSchema('/conversation-relay-callback'),\n\n /**\n * Base path for the call-event callbacks (status, async AMD, recording).\n * TACServer registers one route per callback under it — `<base>/status`,\n * `<base>/amd`, `<base>/recording` — so the route identifies the event. Same\n * role as voiceActionPath. Must start with '/'.\n */\n voiceCallEventPath: voicePathSchema('/twilio/call-events'),\n cintelConfigurationId: z.string().optional(),\n cintelSummaryOperatorSid: z.string().optional(),\n region: z\n .string()\n .max(63, 'Invalid Twilio region format (must be a valid DNS label)')\n .regex(\n /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/,\n 'Invalid Twilio region format (must be a valid DNS label)'\n )\n .optional(),\n /**\n * Twilio Studio Flow SID (FWxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) for handoff.\n * TAC derives both the digital-handoff Studio Executions URL and the voice\n * `<Connect action>` webhook URL from this SID.\n */\n studioHandoffFlowSid: z\n .string()\n .regex(\n /^FW[0-9a-f]{32}$/,\n 'Invalid Studio Flow SID format (expected FW followed by 32 hex chars)'\n )\n .optional(),\n});\n\nexport type TACConfigData = z.infer<typeof TACConfigSchema>;\n\n/**\n * Environment variable mapping for configuration\n */\nexport const EnvironmentVariables = {\n TWILIO_ACCOUNT_SID: 'TWILIO_ACCOUNT_SID',\n TWILIO_AUTH_TOKEN: 'TWILIO_AUTH_TOKEN',\n TWILIO_API_KEY: 'TWILIO_API_KEY',\n TWILIO_API_SECRET: 'TWILIO_API_SECRET',\n TWILIO_PHONE_NUMBER: 'TWILIO_PHONE_NUMBER',\n TWILIO_RCS_SENDER_ID: 'TWILIO_RCS_SENDER_ID',\n TWILIO_WHATSAPP_NUMBER: 'TWILIO_WHATSAPP_NUMBER',\n TWILIO_MEMORY_PROFILE_TRAIT_GROUPS: 'TWILIO_MEMORY_PROFILE_TRAIT_GROUPS',\n TWILIO_MEMORY_OBSERVATIONS_LIMIT: 'TWILIO_MEMORY_OBSERVATIONS_LIMIT',\n TWILIO_MEMORY_SUMMARIES_LIMIT: 'TWILIO_MEMORY_SUMMARIES_LIMIT',\n TWILIO_MEMORY_COMMUNICATIONS_LIMIT: 'TWILIO_MEMORY_COMMUNICATIONS_LIMIT',\n TWILIO_MEMORY_RELEVANCE_THRESHOLD: 'TWILIO_MEMORY_RELEVANCE_THRESHOLD',\n TWILIO_MEMORY_PHONE_TRAIT_GROUP: 'TWILIO_MEMORY_PHONE_TRAIT_GROUP',\n TWILIO_MEMORY_PHONE_TRAIT_FIELD: 'TWILIO_MEMORY_PHONE_TRAIT_FIELD',\n TWILIO_CONVERSATION_CONFIGURATION_ID: 'TWILIO_CONVERSATION_CONFIGURATION_ID',\n TWILIO_VOICE_PUBLIC_DOMAIN: 'TWILIO_VOICE_PUBLIC_DOMAIN',\n TWILIO_VOICE_WEBSOCKET_PATH: 'TWILIO_VOICE_WEBSOCKET_PATH',\n TWILIO_VOICE_ACTION_PATH: 'TWILIO_VOICE_ACTION_PATH',\n TWILIO_VOICE_CALL_EVENT_PATH: 'TWILIO_VOICE_CALL_EVENT_PATH',\n TWILIO_TAC_CI_CONFIGURATION_ID: 'TWILIO_TAC_CI_CONFIGURATION_ID',\n TWILIO_TAC_CI_SUMMARY_OPERATOR_SID: 'TWILIO_TAC_CI_SUMMARY_OPERATOR_SID',\n TWILIO_REGION: 'TWILIO_REGION',\n TWILIO_STUDIO_HANDOFF_FLOW_SID: 'TWILIO_STUDIO_HANDOFF_FLOW_SID',\n} as const;\n","import { z } from 'zod';\n\n/**\n * Structured payload generated during a handoff.\n *\n * Contains conversation context and developer-defined attributes\n * for routing to the target system (e.g., Flex TaskRouter).\n *\n * Serialized with camelCase aliases (conversationId/storeId/profileId)\n * for the Studio Executions wire format.\n */\nexport const HandoffPayloadSchema = z.object({\n conversationId: z.string(),\n storeId: z.string(),\n profileId: z.string(),\n attributes: z.record(z.string(), z.unknown()).default({}),\n});\n\nexport type HandoffPayload = z.infer<typeof HandoffPayloadSchema>;\n\n/**\n * ConversationRelay WebSocket ``end`` message carrying a handoff payload.\n *\n * ``handoffData`` is a JSON *string* (not a nested object) — ConversationRelay\n * forwards it verbatim in the POST body to the ``<Connect action>`` URL.\n */\nexport const PendingHandoffDataSchema = z.object({\n type: z.literal('end').default('end'),\n handoffData: z.string(),\n});\n\nexport type PendingHandoffData = z.infer<typeof PendingHandoffDataSchema>;\n","import { z } from 'zod';\nimport { ChannelTypeSchema } from './config';\nimport { PendingHandoffDataSchema } from './handoff';\nimport type { TACMemoryResponse } from '../lib/tac-memory-response';\n\n/**\n * Participant address type for different communication channels\n */\nexport const ParticipantAddressTypeSchema = z.enum([\n 'VOICE',\n 'SMS',\n 'RCS',\n 'EMAIL',\n 'WHATSAPP',\n 'CHAT',\n 'API',\n 'SYSTEM',\n]);\nexport type ParticipantAddressType = z.infer<typeof ParticipantAddressTypeSchema>;\n\n/**\n * Participant address containing channel and address\n */\nexport const ParticipantAddressSchema = z.object({\n channel: ParticipantAddressTypeSchema,\n address: z.string().min(1, 'Address is required'),\n channelId: z.string().nullable().optional(),\n});\n\nexport type ParticipantAddress = z.infer<typeof ParticipantAddressSchema>;\n\n/**\n * Communication participant for Conversations Service API (Conversation Orchestrator).\n *\n * Note: participantId is required for SDK validation when creating communications.\n */\nexport const CommunicationParticipantSchema = z.object({\n address: z.string().max(254),\n channel: ParticipantAddressTypeSchema,\n participantId: z.string(),\n deliveryStatus: z\n .enum(['INITIATED', 'IN_PROGRESS', 'DELIVERED', 'COMPLETED', 'FAILED'])\n .optional(),\n});\n\nexport type CommunicationParticipant = z.infer<typeof CommunicationParticipantSchema>;\n\n/**\n * Word-level transcription data with timing information.\n */\nexport const TranscriptionWordSchema = z.object({\n text: z.string(),\n startTime: z.string().optional(),\n endTime: z.string().optional(),\n});\n\nexport type TranscriptionWord = z.infer<typeof TranscriptionWordSchema>;\n\n/**\n * Transcription metadata for communication content.\n */\nexport const TranscriptionSchema = z.object({\n channel: z.number().optional(),\n confidence: z.number().min(0).max(1).optional(),\n engine: z.string().optional(),\n words: z.array(TranscriptionWordSchema).optional(),\n});\n\nexport type Transcription = z.infer<typeof TranscriptionSchema>;\n\n/**\n * Communication content (ContentText or ContentTranscription).\n *\n * Note: In the Conversation Orchestrator API, both `type` and `text` are required fields.\n */\nexport const CommunicationContentSchema = z.object({\n type: z.enum(['TEXT', 'TRANSCRIPTION']),\n text: z.string().max(8388608),\n transcription: TranscriptionSchema.optional(),\n});\n\nexport type CommunicationContent = z.infer<typeof CommunicationContentSchema>;\n\n/**\n * Communication from Conversations Service API (Conversation Orchestrator).\n *\n * Note: `createdAt` is optional per API spec.\n */\nexport const CommunicationSchema = z.object({\n id: z.string(),\n conversationId: z.string(),\n accountId: z.string(),\n author: CommunicationParticipantSchema,\n content: CommunicationContentSchema,\n recipients: z.array(CommunicationParticipantSchema),\n channelId: z.string().nullable().optional(),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n occurredAt: z.string().nullable().optional(),\n});\n\nexport type Communication = z.infer<typeof CommunicationSchema>;\n\n/**\n * List communications response\n */\nexport const ListCommunicationsResponseSchema = z.object({\n communications: z.array(CommunicationSchema),\n});\n\nexport type ListCommunicationsResponse = z.infer<typeof ListCommunicationsResponseSchema>;\n\n/**\n * Participant reference for the Actions API (`from`/`to` entries).\n *\n * Either `participantId` or `address` must be supplied; `channel` is always required.\n * When both are provided, Conversation Orchestrator uses `participantId` and\n * `channel` disambiguates which of the participant's addresses to use.\n */\nexport const ActionParticipantRefSchema = z\n .object({\n participantId: z.string().min(1).optional(),\n address: z.string().min(1).max(254).optional(),\n channel: ParticipantAddressTypeSchema,\n })\n .refine(v => Boolean(v.participantId) || Boolean(v.address), {\n message: 'ActionParticipantRef requires at least `participantId` or `address`',\n });\n\nexport type ActionParticipantRef = z.infer<typeof ActionParticipantRefSchema>;\n\n/**\n * Plain-text content for a SEND_MESSAGE action.\n */\nexport const ActionTextContentSchema = z.object({\n text: z.string().max(8388608),\n});\n\nexport type ActionTextContent = z.infer<typeof ActionTextContentSchema>;\n\n/**\n * Channel-specific settings forwarded to the downstream backend.\n *\n * Open pass-through: any field not explicitly modeled here (e.g.\n * `messagingServiceSid`, `statusCallback`, `Attributes`) can be set by callers and\n * will be forwarded as-is.\n */\nexport const ActionChannelSettingsSchema = z.looseObject({\n channelId: z.string().optional(),\n});\n\nexport type ActionChannelSettings = z.infer<typeof ActionChannelSettingsSchema>;\n\n/**\n * Inner payload for a SEND_MESSAGE action.\n */\nexport const SendMessageActionPayloadSchema = z.object({\n from: ActionParticipantRefSchema,\n to: z.array(ActionParticipantRefSchema).min(1),\n content: ActionTextContentSchema,\n channelSettings: ActionChannelSettingsSchema.optional(),\n});\n\nexport type SendMessageActionPayload = z.infer<typeof SendMessageActionPayloadSchema>;\n\n/**\n * Request for POST /v2/Conversations/{id}/Actions with type=SEND_MESSAGE.\n *\n * Body is discriminated by `type` with the action-specific fields under `payload`.\n */\nexport const SendMessageActionRequestSchema = z.object({\n type: z.literal('SEND_MESSAGE').default('SEND_MESSAGE'),\n payload: SendMessageActionPayloadSchema,\n});\n\nexport type SendMessageActionRequest = z.infer<typeof SendMessageActionRequestSchema>;\n\n/**\n * Response from POST /v2/Conversations/{id}/Actions (202 Accepted).\n *\n * Listen for COMMUNICATION_CREATED webhook to get the full Communication.\n */\nexport const ActionResponseSchema = z.object({\n id: z.string(),\n // Kept as string (not enum) to tolerate future action types. Known: SEND_MESSAGE.\n type: z.string(),\n // Kept as string (not enum) to tolerate future statuses. Known: PENDING, COMPLETED, FAILED.\n status: z.string(),\n conversationId: z.string(),\n createdAt: z.string().nullish(),\n});\n\nexport type ActionResponse = z.infer<typeof ActionResponseSchema>;\n\n/**\n * Author information for a conversation session\n */\nexport const AuthorInfoSchema = z.object({\n address: z.string(),\n participantId: z.string().optional(),\n});\n\nexport type AuthorInfo = z.infer<typeof AuthorInfoSchema>;\n\n/**\n * Profile information for a conversation participant\n */\nexport interface Profile {\n profileId: string;\n traits?: Record<string, unknown>;\n}\n\n/**\n * Conversation session context\n */\nexport const ConversationSessionSchema = z.object({\n conversationId: z.string().min(1, 'Conversation ID is required'),\n /**\n * Twilio Call SID on the Voice channel, unset on messaging. The correlation\n * key for call events (`VoiceChannel.onCallStatus` / `onAmd` / `onRecording`)\n * and `endCall`. Equals `conversationId` in relay-only mode; look the session\n * up the other way with `VoiceChannel.getConversationSessionByCallSid`.\n */\n callSid: z.string().optional(),\n profileId: z.string().optional(),\n serviceId: z.string().optional(),\n channel: ChannelTypeSchema,\n startedAt: z.date(),\n authorInfo: AuthorInfoSchema.optional(),\n /**\n * Agent-side participant info stashed by inbound reconciliation or outbound\n * initiation. `sendResponse` reads this to avoid re-listing participants at\n * send time.\n */\n aiAgentInfo: AuthorInfoSchema.optional(),\n profile: z.custom<Profile>().optional(),\n metadata: z.record(z.string(), z.unknown()).optional().default({}),\n /**\n * Pending handoff payload set by the handoff tool. Voice channel sends\n * this as a WS \"end\" message after the LLM's final response.\n */\n pendingHandoffData: PendingHandoffDataSchema.optional(),\n /**\n * Cached memory for \"once\" mode. Set on the first retrieval, cleared when\n * the conversation becomes INACTIVE. Not persisted/serialized.\n */\n cachedMemory: z.custom<TACMemoryResponse>().optional(),\n});\n\nexport type ConversationSession = z.infer<typeof ConversationSessionSchema>;\n\n/**\n * Branded types for type safety\n */\nexport type ConversationId = string & { readonly _brand: 'ConversationId' };\nexport type ProfileId = string & { readonly _brand: 'ProfileId' };\nexport type ParticipantId = string & { readonly _brand: 'ParticipantId' };\n\n/**\n * Type guards for branded types\n */\nexport function isConversationId(value: string): value is ConversationId {\n return value.length > 0;\n}\n\nexport function isProfileId(value: string): value is ProfileId {\n return value.length > 0;\n}\n\nexport function isParticipantId(value: string): value is ParticipantId {\n return value.length > 0;\n}\n\n/**\n * Conversation response from Conversations Service API\n */\nexport const ConversationResponseSchema = z.object({\n id: z.string(),\n accountId: z.string(),\n status: z.string().optional(),\n name: z.string().nullish(), // API returns null when not set\n configurationId: z.string().optional(),\n createdAt: z.string().optional(),\n updatedAt: z.string().optional(),\n});\n\nexport type ConversationResponse = z.infer<typeof ConversationResponseSchema>;\n\n/**\n * List conversations response\n */\nexport const ListConversationsResponseSchema = z.object({\n conversations: z.array(ConversationResponseSchema),\n});\n\nexport type ListConversationsResponse = z.infer<typeof ListConversationsResponseSchema>;\n\n/**\n * Participant address from Conversations Service API (camelCase format)\n */\nexport const ConversationAddressSchema = z.object({\n channel: ParticipantAddressTypeSchema,\n address: z.string(),\n channelId: z.string().nullish(), // API returns null when not set\n});\n\nexport type ConversationAddress = z.infer<typeof ConversationAddressSchema>;\n\n/**\n * Participant response from Conversations Service API\n */\nexport const ConversationParticipantSchema = z.object({\n id: z.string(),\n conversationId: z.string(),\n accountId: z.string(),\n name: z.string().optional(),\n type: z.enum(['HUMAN_AGENT', 'CUSTOMER', 'AI_AGENT', 'AGENT', 'UNKNOWN']).optional(),\n profileId: z.string().nullable().optional(),\n addresses: z.array(ConversationAddressSchema).default([]),\n createdAt: z.string().optional(),\n updatedAt: z.string().optional(),\n});\n\nexport type ConversationParticipant = z.infer<typeof ConversationParticipantSchema>;\n\n/**\n * List participants response\n */\nexport const ListParticipantsResponseSchema = z.object({\n participants: z.array(ConversationParticipantSchema),\n});\n\nexport type ListParticipantsResponse = z.infer<typeof ListParticipantsResponseSchema>;\n\n/**\n * Timeout settings for channel status transitions\n */\nexport const StatusTimeoutsSchema = z.object({\n inactive: z.number().int().gte(1).nullable().optional(),\n closed: z.number().int().gte(1),\n});\n\nexport type StatusTimeouts = z.infer<typeof StatusTimeoutsSchema>;\n\n/**\n * Capture rule with from/to addresses and optional metadata\n */\nexport const CaptureRuleSchema = z.object({\n from: z.string(),\n to: z.string(),\n metadata: z.record(z.string(), z.string()).nullable().optional(),\n});\n\nexport type CaptureRule = z.infer<typeof CaptureRuleSchema>;\n\n/**\n * Configuration settings for a specific channel type\n */\nexport const ChannelSettingsSchema = z.object({\n statusTimeouts: StatusTimeoutsSchema.nullable().optional(),\n captureRules: z.array(CaptureRuleSchema).nullable().optional(),\n});\n\nexport type ChannelSettings = z.infer<typeof ChannelSettingsSchema>;\n\n/**\n * Webhook configuration for status callbacks\n */\nexport const StatusCallbackSchema = z.object({\n url: z.url(),\n method: z.enum(['POST', 'GET', 'PUT', 'DELETE', 'PATCH']).optional().default('POST'),\n});\n\nexport type StatusCallback = z.infer<typeof StatusCallbackSchema>;\n\n/**\n * Conversation grouping type\n *\n * - `GROUP_BY_PROFILE`: Groups communications by participant profile. Communications\n * with the same profile go to the same conversation, regardless of the channel or address.\n * - `GROUP_BY_PARTICIPANT_ADDRESSES`: Groups communications by participant addresses\n * across all channels. A customer using +15551234567 will be in the same conversation\n * whether they contact via SMS, WhatsApp, or RCS.\n * - `GROUP_BY_PARTICIPANT_ADDRESSES_AND_CHANNEL_TYPE`: Groups communications by both\n * participant addresses AND channel. A customer using +15551234567 via SMS will be in\n * a different conversation than the same customer via WhatsApp.\n */\nexport const ConversationGroupingTypeSchema = z.enum([\n 'GROUP_BY_PROFILE',\n 'GROUP_BY_PARTICIPANT_ADDRESSES',\n 'GROUP_BY_PARTICIPANT_ADDRESSES_AND_CHANNEL_TYPE',\n]);\n\nexport type ConversationGroupingType = z.infer<typeof ConversationGroupingTypeSchema>;\n\n/**\n * Configuration settings for a conversation\n */\nexport const ConversationConfigurationSchema = z.object({\n id: z.string(),\n displayName: z\n .string()\n .max(32)\n .regex(/^[a-zA-Z0-9-_ ]+$/)\n .nullable()\n .optional(),\n description: z.string(),\n conversationGroupingType: ConversationGroupingTypeSchema,\n memoryStoreId: z\n .string()\n .regex(/^mem_(store|service)_[0-7][0-9a-z]{25}$/, 'Invalid Memory Store ID format'),\n channelSettings: z.record(z.string(), ChannelSettingsSchema).nullable().optional(),\n statusCallbacks: z.array(StatusCallbackSchema).max(20).nullable().optional(),\n intelligenceConfigurationIds: z.array(z.string()).max(5).nullable().optional(),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n version: z.number().int().nullable().optional(),\n});\n\nexport type ConversationConfiguration = z.infer<typeof ConversationConfigurationSchema>;\n\n// =========================================================================\n// Outbound Conversation Types\n// =========================================================================\n\n/**\n * Options for initiating an outbound SMS conversation.\n *\n * The sender is always TAC's configured `config.phoneNumber`. Multi-sender\n * deployments should run one TAC instance per sender so inbound webhook\n * routing, memory scoping, and configuration stay in sync.\n */\nexport const InitiateMessagingConversationOptionsSchema = z.object({\n to: z.string().min(1, 'Recipient address is required'),\n message: z.string().min(1, 'Initial message is required'),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type InitiateMessagingConversationOptions = z.infer<\n typeof InitiateMessagingConversationOptionsSchema\n>;\n\n/**\n * Result of initiating an outbound conversation\n */\nexport interface InitiateConversationResult {\n conversationId: ConversationId;\n session: ConversationSession;\n}\n\n/**\n * Result of initiating an outbound voice conversation.\n * Note: conversationId is not included because the conversation is created by\n * Conversation Orchestrator during passive hydration — the SDK discovers it by\n * callSid, in the background from WebSocket setup.\n */\nexport interface InitiateVoiceConversationResult {\n callSid: string;\n}\n\n/**\n * Webhook payload structure from Twilio Conversation Orchestrator.\n * This structure is used by all channels (messaging and voice) for webhook events.\n */\nexport interface ConversationWebhookPayload {\n eventType: string;\n timestamp?: string;\n data?: {\n id?: string;\n conversationId?: string;\n accountId?: string;\n serviceId?: string;\n status?: string;\n participantType?: string;\n profileId?: string;\n channelId?: string;\n author?: {\n address?: string;\n channel?: string;\n participantId?: string;\n };\n content?: {\n type?: string;\n text?: string;\n };\n recipients?: Array<{\n address?: string;\n channel?: string;\n participantId?: string;\n deliveryStatus?: string;\n }>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n","import { z } from 'zod';\nimport { TranscriptionSchema } from './conversation';\n\n/**\n * Channel type for communications\n */\nexport const TACChannelTypeSchema = z.enum([\n 'VOICE',\n 'SMS',\n 'RCS',\n 'EMAIL',\n 'WHATSAPP',\n 'CHAT',\n 'API',\n 'SYSTEM',\n]);\nexport type TACChannelType = z.infer<typeof TACChannelTypeSchema>;\n\n/**\n * Delivery status for communications\n */\nexport const TACDeliveryStatusSchema = z.enum([\n 'INITIATED',\n 'IN_PROGRESS',\n 'DELIVERED',\n 'COMPLETED',\n 'FAILED',\n]);\nexport type TACDeliveryStatus = z.infer<typeof TACDeliveryStatusSchema>;\n\n/**\n * Participant type\n */\nexport const TACParticipantTypeSchema = z.enum(['HUMAN_AGENT', 'CUSTOMER', 'AI_AGENT', 'AGENT']);\nexport type TACParticipantType = z.infer<typeof TACParticipantTypeSchema>;\n\n/**\n * Unified author model with all fields from both Memory and Conversation Orchestrator APIs.\n *\n * Fields not available from a particular API will be undefined.\n */\nexport const TACCommunicationAuthorSchema = z.object({\n // Common fields (both APIs)\n address: z.string(),\n channel: TACChannelTypeSchema,\n\n // Conversation Orchestrator-only fields\n participantId: z.string().optional(),\n deliveryStatus: TACDeliveryStatusSchema.optional(),\n\n // Memory-only fields\n id: z.string().optional(),\n name: z.string().optional(),\n type: TACParticipantTypeSchema.optional(),\n profileId: z.string().nullable().optional(),\n});\n\nexport type TACCommunicationAuthor = z.infer<typeof TACCommunicationAuthorSchema>;\n\n/**\n * Unified content model with all fields from both Memory and Conversation Orchestrator APIs.\n */\nexport const TACCommunicationContentSchema = z.object({\n // Conversation Orchestrator-only: content type discriminator\n type: z.enum(['TEXT', 'TRANSCRIPTION']).optional(),\n // Both APIs: message text (optional in unified model to handle both)\n text: z.string().optional(),\n // Conversation Orchestrator-only: transcription metadata\n transcription: TranscriptionSchema.optional(),\n});\n\nexport type TACCommunicationContent = z.infer<typeof TACCommunicationContentSchema>;\n\n/**\n * Unified communication model with all fields from both Memory and Conversation Orchestrator APIs.\n *\n * Provides complete access to all communication fields regardless of the source.\n * Fields not available from a particular API will be undefined.\n */\nexport const TACCommunicationSchema = z.object({\n // Common fields (both APIs)\n id: z.string(),\n author: TACCommunicationAuthorSchema,\n content: TACCommunicationContentSchema,\n recipients: z.array(TACCommunicationAuthorSchema).default([]),\n channelId: z.string().nullable().optional(),\n createdAt: z.string().optional(),\n updatedAt: z.string().optional(),\n\n // Conversation Orchestrator-only fields\n conversationId: z.string().optional(),\n accountId: z.string().optional(),\n});\n\nexport type TACCommunication = z.infer<typeof TACCommunicationSchema>;\n","import { Communication } from '../types/conversation';\nimport { MemoryRetrievalResponse, ObservationInfo, SummaryInfo } from '../types/memory';\nimport { TACCommunication, TACCommunicationSchema } from '../types/tac';\n\n/**\n * Type guard to check if data is MemoryRetrievalResponse.\n */\nfunction isMemoryRetrievalResponse(\n data: MemoryRetrievalResponse | Communication[]\n): data is MemoryRetrievalResponse {\n return !Array.isArray(data);\n}\n\n/**\n * Unified response wrapper for TAC.retrieveMemory().\n *\n * Provides a consistent interface for accessing memory data regardless of whether\n * Memory API is configured or falling back to Conversation Orchestrator Communications API.\n *\n * Memory configured:\n * - observations, summaries, communications all populated\n * - communications include Memory-specific fields (author id, name, type, profileId)\n *\n * Conversation Orchestrator fallback:\n * - observations and summaries are empty arrays\n * - communications include Conversation Orchestrator-specific fields (conversationId, accountId, etc.)\n */\nexport class TACMemoryResponse {\n private readonly _data: MemoryRetrievalResponse | Communication[];\n private readonly _communications: TACCommunication[];\n\n /**\n * Initialize wrapper with either Memory or Conversation Orchestrator data.\n *\n * @param data - Either MemoryRetrievalResponse (Memory) or Communication[] (Conversation Orchestrator)\n */\n constructor(data: MemoryRetrievalResponse | Communication[]) {\n this._data = data;\n\n if (isMemoryRetrievalResponse(data)) {\n this._communications = (data.communications ?? []).map(comm =>\n TACCommunicationSchema.parse(comm)\n );\n } else {\n this._communications = data.map(comm => TACCommunicationSchema.parse(comm));\n }\n }\n\n /**\n * Get observation memories.\n *\n * @returns List of observations if Memory is configured, empty array for Conversation Orchestrator fallback\n */\n get observations(): ObservationInfo[] {\n if (isMemoryRetrievalResponse(this._data)) {\n return this._data.observations;\n }\n return [];\n }\n\n /**\n * Get summary memories.\n *\n * @returns List of summaries if Memory is configured, empty array for Conversation Orchestrator fallback\n */\n get summaries(): SummaryInfo[] {\n if (isMemoryRetrievalResponse(this._data)) {\n return this._data.summaries;\n }\n return [];\n }\n\n /**\n * Get communications in unified format with all available fields.\n *\n * Communications are converted to a common format during initialization that includes\n * all fields from both Memory and Conversation Orchestrator APIs. Fields not available from a particular\n * API will be undefined.\n *\n * @returns List of unified communications with all available fields\n */\n get communications(): TACCommunication[] {\n return this._communications;\n }\n\n /**\n * Check if Memory API is configured and providing full features.\n *\n * @returns true if Memory is configured (observations/summaries available),\n * false if using Conversation Orchestrator fallback (only communications available)\n */\n get hasMemoryFeatures(): boolean {\n return isMemoryRetrievalResponse(this._data);\n }\n\n /**\n * Access raw underlying data for advanced use cases.\n *\n * Use this when you need access to all fields from the original API responses,\n * not just the unified common fields.\n *\n * @returns Either MemoryRetrievalResponse or Communication[] depending on configuration\n */\n get rawData(): MemoryRetrievalResponse | Communication[] {\n return this._data;\n }\n\n /**\n * Build formatted prompt sections from available memory data.\n *\n * Generates markdown-formatted sections for observations, summaries, and communications\n * that can be injected into LLM prompts. Each section includes a heading and formatted content.\n * Sections with no data are omitted from the result.\n *\n * @returns Array of formatted prompt sections, empty array if no memory data available\n */\n buildMemoryPrompts(): string[] {\n const sections: string[] = [];\n\n const observationsSection = this.buildObservationsPrompt();\n if (observationsSection) {\n sections.push(observationsSection);\n }\n\n const summariesSection = this.buildSummariesPrompt();\n if (summariesSection) {\n sections.push(summariesSection);\n }\n\n const communicationsSection = this.buildCommunicationsPrompt();\n if (communicationsSection) {\n sections.push(communicationsSection);\n }\n\n return sections;\n }\n\n private buildObservationsPrompt(): string | null {\n if (this.observations.length === 0) {\n return null;\n }\n\n const lines = [\n '## Key Observations',\n 'Important notes about the customer from previous interactions:',\n ];\n\n for (const obs of this.observations) {\n lines.push(`- ${obs.content}`);\n }\n\n return lines.join('\\n');\n }\n\n private buildSummariesPrompt(): string | null {\n if (this.summaries.length === 0) {\n return null;\n }\n\n const lines = [\n '## Past Conversation Summaries',\n 'Summaries of previous conversations with this customer:',\n ];\n\n for (const summary of this.summaries) {\n lines.push(`- ${summary.content}`);\n }\n\n return lines.join('\\n');\n }\n\n private buildCommunicationsPrompt(): string | null {\n if (this.communications.length === 0) {\n return null;\n }\n\n const lines = ['## Recent Message History', 'Recent messages exchanged with this customer:'];\n\n for (const comm of this.communications) {\n const content = comm.content?.text;\n if (typeof content !== 'string' || content.trim().length === 0) {\n continue;\n }\n // Determine role - defaults to \"Assistant\" for undefined or non-CUSTOMER authors\n const role = comm.author?.type === 'CUSTOMER' ? 'User' : 'Assistant';\n lines.push(`${role}: ${content}`);\n }\n\n return lines.length > 2 ? lines.join('\\n') : null;\n }\n}\n","import { z } from 'zod';\n\n/**\n * Memory retrieval mode for channels.\n *\n * - \"always\": Fetch memory with the message as query on every inbound message.\n * - \"once\": Fetch memory once at conversation start with no query (and no\n * conversation id, skipping query expansion) and cache it. The cache is\n * invalidated when the conversation becomes INACTIVE.\n * - \"never\": Never automatically fetch memory (default).\n */\nexport const MemoryModeSchema = z.enum(['always', 'never', 'once']);\nexport type MemoryMode = z.infer<typeof MemoryModeSchema>;\n\n/**\n * Message direction in a conversation\n */\nexport const MessageDirectionSchema = z.enum(['inbound', 'outbound']);\nexport type MessageDirection = z.infer<typeof MessageDirectionSchema>;\n\n/**\n * Channel type for Memory communications\n */\nexport const MemoryChannelTypeSchema = z.enum([\n 'VOICE',\n 'SMS',\n 'RCS',\n 'EMAIL',\n 'WHATSAPP',\n 'CHAT',\n 'API',\n 'SYSTEM',\n]);\nexport type MemoryChannelType = z.infer<typeof MemoryChannelTypeSchema>;\n\n/**\n * Participant type in Memory API\n */\nexport const MemoryParticipantTypeSchema = z.enum([\n 'HUMAN_AGENT',\n 'CUSTOMER',\n 'AI_AGENT',\n 'AGENT',\n 'UNKNOWN',\n]);\nexport type MemoryParticipantType = z.infer<typeof MemoryParticipantTypeSchema>;\n\n/**\n * Delivery status for Memory communications\n */\nexport const MemoryDeliveryStatusSchema = z.enum([\n 'INITIATED',\n 'IN_PROGRESS',\n 'DELIVERED',\n 'COMPLETED',\n 'FAILED',\n]);\nexport type MemoryDeliveryStatus = z.infer<typeof MemoryDeliveryStatusSchema>;\n\n/**\n * Participant in a Memory communication (author or recipient).\n *\n * Memory API has different field requirements than Conversation Orchestrator:\n * - Uses `id` and `name` instead of just `participant_id`\n * - Includes `type` and `profileId` fields\n */\nexport const MemoryParticipantSchema = z.object({\n id: z.string(),\n name: z.string().max(256),\n address: z.string().max(254),\n channel: MemoryChannelTypeSchema,\n type: MemoryParticipantTypeSchema.optional(),\n profileId: z.string().nullable().optional(),\n deliveryStatus: MemoryDeliveryStatusSchema.optional(),\n});\n\nexport type MemoryParticipant = z.infer<typeof MemoryParticipantSchema>;\n\n/**\n * Content of a Memory communication.\n *\n * Memory API content is simpler than Conversation Orchestrator - no type discriminator field.\n * The `text` field is optional in Memory API models.\n */\nexport const MemoryCommunicationContentSchema = z.object({\n text: z.string().max(8388608).optional(),\n});\n\nexport type MemoryCommunicationContent = z.infer<typeof MemoryCommunicationContentSchema>;\n\n/**\n * A communication from Memory API (historical conversation data).\n *\n * Memory API has different field requirements than Conversation Orchestrator:\n * - No `conversationId`, `accountId`, or `content.type` fields\n * - Participants use `id`, `name`, `type`, `profileId`\n */\nexport const MemoryCommunicationSchema = z.object({\n id: z.string(),\n author: MemoryParticipantSchema,\n content: MemoryCommunicationContentSchema,\n recipients: z.array(MemoryParticipantSchema).max(100),\n channelId: z.string().max(256).nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string().optional(),\n});\n\nexport type MemoryCommunication = z.infer<typeof MemoryCommunicationSchema>;\n\n/**\n * Individual session message\n */\nexport const SessionMessageSchema = z.object({\n direction: MessageDirectionSchema,\n channel: z.string(),\n from_address: z.string().optional(),\n to_address: z.string().optional(),\n content: z.string(),\n timestamp: z.iso.datetime(),\n});\n\nexport type SessionMessage = z.infer<typeof SessionMessageSchema>;\n\n/**\n * Session information containing conversation history\n */\nexport const SessionInfoSchema = z.object({\n session_id: z.string(),\n started_at: z.iso.datetime(),\n ended_at: z.iso.datetime().optional(),\n channel: z.string(),\n messages: z.array(SessionMessageSchema),\n});\n\nexport type SessionInfo = z.infer<typeof SessionInfoSchema>;\n\n/**\n * Individual observation extracted from conversations\n */\nexport const ObservationInfoSchema = z.object({\n id: z.string(),\n content: z.string(),\n createdAt: z.iso.datetime(),\n occurredAt: z.iso.datetime().optional(),\n updatedAt: z.iso.datetime().optional(),\n conversationIds: z.array(z.string()).nullable().optional(),\n source: z.string().optional(),\n});\n\nexport type ObservationInfo = z.infer<typeof ObservationInfoSchema>;\n\n/**\n * Conversation summary information\n */\nexport const SummaryInfoSchema = z.object({\n id: z.string(),\n content: z.string(),\n createdAt: z.iso.datetime(),\n updatedAt: z.iso.datetime().optional(),\n conversationIds: z.array(z.string()).optional(),\n});\n\nexport type SummaryInfo = z.infer<typeof SummaryInfoSchema>;\n\n/**\n * Memory retrieval request parameters.\n *\n * Defaults match the Memory API server defaults. The SDK-level defaults in\n * TwilioMemoryConfigSchema may differ (e.g. communicationsLimit defaults to 10\n * in the SDK config for a better out-of-box experience, vs 0 on the API).\n */\nexport const MemoryRetrievalRequestSchema = z.object({\n conversationId: z.string().optional(),\n query: z.string().optional(),\n beginDate: z.iso.datetime().optional(),\n endDate: z.iso.datetime().optional(),\n observationsLimit: z.number().int().min(0).max(100).optional(),\n summariesLimit: z.number().int().min(0).max(100).optional(),\n communicationsLimit: z.number().int().min(0).max(100).optional(),\n relevanceThreshold: z.number().min(0.0).max(1.0).optional(),\n});\n\nexport type MemoryRetrievalRequest = z.infer<typeof MemoryRetrievalRequestSchema>;\n\n/**\n * Memory retrieval response from the Memory API /Recall endpoint.\n *\n * Contains observations, summaries, and communications from Memory API.\n */\nexport const MemoryRetrievalResponseSchema = z.object({\n observations: z.array(ObservationInfoSchema),\n summaries: z.array(SummaryInfoSchema),\n communications: z.array(MemoryCommunicationSchema).optional().default([]),\n meta: z\n .object({\n queryTime: z.number().optional(),\n })\n .optional(),\n});\n\nexport type MemoryRetrievalResponse = z.infer<typeof MemoryRetrievalResponseSchema>;\n\n/**\n * Profile lookup response\n */\nexport const ProfileLookupResponseSchema = z.object({\n normalizedValue: z.string().max(255),\n profiles: z\n .array(z.string())\n .max(100)\n .nullable()\n .transform(v => v ?? []),\n});\n\nexport type ProfileLookupResponse = z.infer<typeof ProfileLookupResponseSchema>;\n\n/**\n * Profile response with traits\n */\nexport const ProfileResponseSchema = z.object({\n id: z.string(),\n createdAt: z.string(),\n traits: z.record(z.string(), z.unknown()),\n});\n\nexport type ProfileResponse = z.infer<typeof ProfileResponseSchema>;\n\n/**\n * Empty memory response for error fallback\n */\nexport const EMPTY_MEMORY_RESPONSE: MemoryRetrievalResponse = {\n observations: [],\n summaries: [],\n communications: [],\n};\n\n/**\n * A single observation in a create request.\n *\n * `occurredAt` is required by the Memory API and formatted as ISO 8601.\n */\nexport const ObservationCreateRequestSchema = z.object({\n content: z.string(),\n source: z.string(),\n occurredAt: z.string(),\n conversationIds: z.array(z.string()).optional(),\n});\n\nexport type ObservationCreateRequest = z.infer<typeof ObservationCreateRequestSchema>;\n\n/**\n * Request body for the Memory API Observations endpoint.\n *\n * The endpoint is a batch create that wraps observations in an array.\n */\nexport const CreateObservationsRequestSchema = z.object({\n observations: z.array(ObservationCreateRequestSchema),\n});\n\nexport type CreateObservationsRequest = z.infer<typeof CreateObservationsRequestSchema>;\n\n/**\n * Response from creating an observation.\n *\n * The Memory API Observations endpoint is a batch create that returns a\n * confirmation message rather than the persisted observation.\n */\nexport const CreateObservationResponseSchema = z.object({\n message: z.string(),\n});\n\nexport type CreateObservationResponse = z.infer<typeof CreateObservationResponseSchema>;\n\n/**\n * Response from creating conversation summaries\n */\nexport const CreateConversationSummariesResponseSchema = z.object({\n message: z.string(),\n});\n\nexport type CreateConversationSummariesResponse = z.infer<\n typeof CreateConversationSummariesResponseSchema\n>;\n","import { z } from 'zod';\nimport type VoiceResponse from 'twilio/lib/twiml/VoiceResponse.js';\nimport type { CallListInstanceCreateOptions } from 'twilio/lib/rest/api/v2010/account/call.js';\n\n/**\n * ConversationRelay API Types\n *\n * Zod schemas are the single source of truth for runtime validation. Types are\n * inferred from schemas via z.infer. Compile-time drift guards (type assertions\n * against VoiceResponse.ConversationRelayAttributes / LanguageAttributes) ensure\n * that if the Twilio SDK types change, `npm run typecheck` will fail immediately.\n *\n * @see https://www.twilio.com/docs/voice/conversationrelay\n * @see https://www.twilio.com/docs/voice/conversationrelay/conversationrelay-noun\n */\n\n/**\n * Language configuration for multi-language ConversationRelay support\n * @see https://www.twilio.com/docs/voice/conversationrelay/conversationrelay-noun#language-attributes\n */\nexport const LanguageAttributesSchema = z.object({\n /** Language code (e.g., 'en-US', 'es-ES', 'en-AU') */\n code: z.string(),\n /** TTS provider for this language */\n ttsProvider: z.string().optional(),\n /** TTS voice for this language */\n voice: z.string().optional(),\n /** TTS language (may differ from code) */\n ttsLanguage: z.string().optional(),\n /** Transcription provider for this language */\n transcriptionProvider: z.string().optional(),\n /** Speech model for transcription */\n speechModel: z.string().optional(),\n /** Transcription language (may differ from code) */\n transcriptionLanguage: z.string().optional(),\n});\n\nexport type LanguageAttributes = z.infer<typeof LanguageAttributesSchema>;\n\n/**\n * ConversationRelay attributes for TwiML configuration\n * @see https://www.twilio.com/docs/voice/conversationrelay/conversationrelay-noun\n */\nexport const ConversationRelayAttributesSchema = z.object({\n /** WebSocket URL for ConversationRelay (required) */\n url: z.url(),\n\n // Welcome greeting settings\n /** Initial greeting to play when call connects */\n welcomeGreeting: z.string().optional(),\n /** Whether welcome greeting can be interrupted */\n welcomeGreetingInterruptible: z.enum(['any', 'speech', 'none']).optional(),\n\n // Transcription settings\n /** Transcription provider (e.g., 'Deepgram', 'Google') */\n transcriptionProvider: z.string().optional(),\n /** Language for transcription (e.g., 'en-US') */\n transcriptionLanguage: z.string().optional(),\n /** Speech model for transcription (e.g., 'nova-3-general') */\n speechModel: z.string().optional(),\n\n // TTS settings\n /** Text-to-speech provider (e.g., 'Google', 'ElevenLabs') */\n ttsProvider: z.string().optional(),\n /** Language for TTS (e.g., 'en-US') */\n ttsLanguage: z.string().optional(),\n /** Voice identifier for TTS (e.g., 'en-US-Journey-O') */\n voice: z.string().optional(),\n /** ElevenLabs text normalization setting */\n elevenlabsTextNormalization: z.string().optional(),\n\n // Interaction settings\n /** When agent speech can be interrupted */\n interruptible: z.enum(['any', 'speech', 'none']).optional(),\n /** Interrupt detection sensitivity */\n interruptSensitivity: z.enum(['low', 'medium', 'high']).optional(),\n /** Enable DTMF tone detection */\n dtmfDetection: z.boolean().optional(),\n /** Recognition hints for domain-specific vocabulary */\n hints: z.string().optional(),\n /** Whether prompts should be reported when TTS is playing and interrupt is disabled */\n reportInputDuringAgentSpeech: z.boolean().optional(),\n\n // Advanced settings\n /** Enable partial prompts (streaming) */\n partialPrompts: z.boolean().optional(),\n /** Enable profanity filtering */\n profanityFilter: z.boolean().optional(),\n /** Allow preemption of agent speech */\n preemptible: z.boolean().optional(),\n /** Default language code */\n language: z.string().optional(),\n /** Debug options for troubleshooting (string per SDK, not boolean) */\n debug: z.string().optional(),\n\n // Intelligence service\n /** Conversational Intelligence Service ID or unique name */\n intelligenceService: z.string().optional(),\n\n // Conversation orchestrator\n /** Twilio Conversation Orchestrator configuration ID */\n conversationConfiguration: z.string().optional(),\n});\n\nexport type ConversationRelayAttributes = z.infer<typeof ConversationRelayAttributesSchema>;\n\n/**\n * @internal Compile-time SDK drift guards — do not use directly.\n * If the Twilio SDK updates VoiceResponse.ConversationRelayAttributes or\n * VoiceResponse.LanguageAttributes, these checks will fail during typecheck,\n * signaling that our Zod schemas need to be updated to match.\n */\nexport type _SDKDriftGuards = {\n langCompat: LanguageAttributes extends VoiceResponse.LanguageAttributes ? true : never;\n langKeys: keyof VoiceResponse.LanguageAttributes extends keyof LanguageAttributes ? true : never;\n crelayCompat: ConversationRelayAttributes extends VoiceResponse.ConversationRelayAttributes\n ? true\n : never;\n crelayKeys: keyof VoiceResponse.ConversationRelayAttributes extends keyof ConversationRelayAttributes\n ? true\n : never;\n};\n\n/**\n * Custom parameters passed via TwiML\n * Can contain any key-value pairs with unknown values\n */\nexport const CustomParametersSchema = z.record(z.string(), z.unknown());\n\nexport type CustomParameters = z.infer<typeof CustomParametersSchema>;\n\n/**\n * WebSocket setup message from ConversationRelay\n */\nexport const SetupMessageSchema = z.object({\n type: z.literal('setup'),\n sessionId: z.string(),\n callSid: z.string(),\n parentCallSid: z.string().optional(),\n from: z.string(),\n to: z.string(),\n forwardedFrom: z.string().optional(),\n callerName: z.string().optional(),\n direction: z.string(),\n callType: z.string(),\n callStatus: z.string(),\n accountSid: z.string(),\n customParameters: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type SetupMessage = z.infer<typeof SetupMessageSchema>;\n\n/**\n * WebSocket prompt message (user speech)\n */\nexport const PromptMessageSchema = z.object({\n type: z.literal('prompt'),\n voicePrompt: z.string(),\n lang: z.string().optional(),\n last: z.boolean().optional(),\n agentSpeaking: z.string().optional(),\n});\n\nexport type PromptMessage = z.infer<typeof PromptMessageSchema>;\n\n/**\n * WebSocket interrupt message (user interruption)\n */\nexport const InterruptMessageSchema = z.object({\n type: z.literal('interrupt'),\n utteranceUntilInterrupt: z.string().optional(),\n durationUntilInterruptMs: z.number().int().nonnegative().optional(),\n});\n\nexport type InterruptMessage = z.infer<typeof InterruptMessageSchema>;\n\n/**\n * Union of all WebSocket message types\n */\nexport const WebSocketMessageSchema = z.union([\n SetupMessageSchema,\n PromptMessageSchema,\n InterruptMessageSchema,\n]);\n\nexport type WebSocketMessage = z.infer<typeof WebSocketMessageSchema>;\n\n/**\n * Text Token Message to send back via WebSocket\n * @see https://www.twilio.com/docs/voice/conversationrelay/websocket-messages#text-tokens-message\n */\nexport const TextTokenMessageSchema = z.object({\n type: z.literal('text'),\n token: z.string(),\n last: z.boolean().optional().default(true),\n});\n\nexport type TextTokenMessage = z.infer<typeof TextTokenMessageSchema>;\n\n/**\n * Extended ConversationRelay configuration that includes child elements.\n * Includes all ConversationRelayAttributes fields plus support for languages array.\n *\n * Note: The type is defined as an explicit interface and the schema is annotated\n * with z.ZodType<ConversationRelayConfig> to prevent TypeScript's type inference\n * from collapsing to `any` when resolving complex Zod generics with many optional\n * fields (especially under exactOptionalPropertyTypes).\n */\nexport interface ConversationRelayConfig extends ConversationRelayAttributes {\n /** Optional language configurations as child <Language> elements */\n languages?: LanguageAttributes[] | undefined;\n}\n\nexport const ConversationRelayConfigSchema: z.ZodType<ConversationRelayConfig> =\n ConversationRelayAttributesSchema.extend({\n /** Optional language configurations as child <Language> elements */\n languages: z.array(LanguageAttributesSchema).optional(),\n });\n\n// =========================================================================\n// TwiML customization layer\n// =========================================================================\n\n/**\n * Twilio uses the same four-value enum for several attributes that control\n * what caller input (DTMF, speech, both, neither) triggers a given behavior.\n */\nexport const InterruptModeSchema = z.enum(['none', 'dtmf', 'speech', 'any']);\nexport type InterruptMode = z.infer<typeof InterruptModeSchema>;\n\n/**\n * A single `<Language>` child for multi-language ConversationRelay setups.\n *\n * Maps to the `<Language>` element documented at\n * https://www.twilio.com/docs/voice/twiml/connect/conversationrelay#language-element\n *\n * Distinct from {@link LanguageAttributes} (the Twilio-SDK-shaped type used by\n * `connectConversationRelay`): this is the customization-facing model used in\n * {@link TwiMLOptions}, mirroring the Python SDK's `LanguageConfig`.\n */\nexport const LanguageConfigSchema = z.object({\n /**\n * Language code, e.g. 'es-MX'. Can be 'multi' for automatic language\n * detection (requires ElevenLabs TTS and Deepgram STT).\n */\n code: z.string(),\n /** TTS voice name for this language */\n voice: z.string().optional(),\n /** TTS provider, e.g. 'google' */\n ttsProvider: z.string().optional(),\n /** Transcription provider, e.g. 'deepgram' */\n transcriptionProvider: z.string().optional(),\n /** Speech model for STT. Choices vary by transcriptionProvider. */\n speechModel: z.string().optional(),\n});\n\nexport type LanguageConfig = z.infer<typeof LanguageConfigSchema>;\n\n/**\n * Options for the TwiML inside `<ConversationRelay>` (plus the\n * `<Connect action>` URL).\n *\n * Fields map to the attributes documented at\n * https://www.twilio.com/docs/voice/twiml/connect/conversationrelay . All\n * fields are optional. `VoiceChannel.handleIncomingCall` merges these values\n * over TAC defaults per-field — only fields explicitly present on the object\n * override lower layers (see `VoiceChannel`'s overlay logic).\n *\n * This is the customization-facing counterpart to {@link ConversationRelayConfig}\n * (which is the Twilio-SDK-shaped emit model and carries the required `url`).\n * Mirrors the Python SDK's `TwiMLOptions`.\n */\nexport const TwiMLOptionsSchema = z\n .object({\n /** Custom parameters to pass to ConversationRelay as `<Parameter>` children */\n customParameters: CustomParametersSchema.optional(),\n /** Initial greeting message for the caller */\n welcomeGreeting: z.string().optional(),\n /**\n * What caller input can interrupt the welcome greeting.\n * Defaults to 'any' on Twilio.\n */\n welcomeGreetingInterruptible: InterruptModeSchema.optional(),\n /**\n * URL for Twilio to request when the call ends (`<Connect action>`). Set to\n * a non-empty URL, or leave unset. An explicit `undefined` suppresses the\n * action entirely (see `VoiceChannel`'s actionUrl resolution); an empty\n * string is rejected so it can't silently drop the action.\n */\n actionUrl: z.string().min(1, 'actionUrl must not be empty').optional(),\n /**\n * Conversation Service SID. When set, ConversationRelay will manage\n * conversation creation and participants.\n */\n conversationConfiguration: z.string().optional(),\n /**\n * ConversationRelay WebSocket URL (the `<ConversationRelay url=...>`\n * attribute). Leave unset (the default) to use the URL the channel derives\n * from `TACConfig.voicePublicDomain` + `voiceWebsocketPath`. Set it only for\n * a per-call URL — e.g. an affinity-routed host that appends a token to the\n * upgrade URL — typically from an `onInboundCallTwiml` customizer. Layers\n * per-field like every other field. Must be non-empty when set.\n */\n websocketUrl: z.string().min(1, 'websocketUrl must not be empty').optional(),\n\n // Language, TTS, STT\n /**\n * Language for both STT and TTS, e.g. 'en-US'. Equivalent to setting both\n * ttsLanguage and transcriptionLanguage.\n */\n language: z.string().optional(),\n /** TTS language code; overrides `language` for TTS. */\n ttsLanguage: z.string().optional(),\n /**\n * STT language code; overrides `language` for transcription. Can be\n * 'multi' for automatic language detection (Deepgram only).\n */\n transcriptionLanguage: z.string().optional(),\n /** TTS voice name (choices vary by ttsProvider) */\n voice: z.string().optional(),\n /** TTS provider: 'Google', 'Amazon', or 'ElevenLabs'. Defaults to 'ElevenLabs'. */\n ttsProvider: z.string().optional(),\n /**\n * STT provider: 'Google' or 'Deepgram'. Defaults to 'Deepgram' (or 'Google'\n * for accounts that used ConversationRelay before 2025-09-12).\n */\n transcriptionProvider: z.string().optional(),\n /** Speech model for STT. Choices vary by transcriptionProvider. */\n speechModel: z.string().optional(),\n /**\n * Text normalization for ElevenLabs TTS. Defaults to 'off'. 'auto' behaves\n * like 'off' for ConversationRelay calls.\n */\n elevenlabsTextNormalization: z.enum(['on', 'auto', 'off']).optional(),\n\n // Turn detection / interruption\n /**\n * Confidence required to finish a turn. Only applies with Deepgram + flux\n * speech model. Twilio enforces the accepted range — see ConversationRelay docs.\n */\n eotThreshold: z.number().optional(),\n /**\n * Send unfinalized prompts and eager end-of-turn events (last=false). Only\n * applies with Deepgram + flux speech model.\n */\n partialPrompts: z.boolean().optional(),\n /**\n * Use Deepgram Smart Format for transcription output. Defaults to true when\n * transcriptionProvider='Deepgram'.\n */\n deepgramSmartFormat: z.boolean().optional(),\n /**\n * Silence (ms) after speech before finalizing the prompt. Integer\n * milliseconds or the literal 'auto' (the platform default). Twilio enforces\n * the accepted range — see ConversationRelay docs.\n */\n speechTimeout: z.union([z.number().int(), z.literal('auto')]).optional(),\n /**\n * What caller input interrupts TTS playback. Boolean accepted for backward\n * compat: true='any', false='none'. Defaults to 'any'.\n */\n interruptible: z.union([InterruptModeSchema, z.boolean()]).optional(),\n /** How easily caller speech triggers an interrupt. Defaults to 'high'. */\n interruptSensitivity: z.enum(['high', 'medium', 'low']).optional(),\n /**\n * What caller input gets reported while the agent is speaking (independent\n * of whether playback is interrupted). Defaults to 'none' since May 2025.\n */\n reportInputDuringAgentSpeech: InterruptModeSchema.optional(),\n /**\n * Filter short conversational feedback ('yeah', 'uh-huh', …) so it doesn't\n * interrupt the agent. Defaults to false.\n */\n ignoreBackchannel: z.boolean().optional(),\n /**\n * Allow text tokens from the next talk cycle to interrupt the current one.\n * Defaults to false.\n */\n preemptible: z.boolean().optional(),\n /** Emit DTMF keypress events over the WebSocket. */\n dtmfDetection: z.boolean().optional(),\n\n // Recognition hints / events / debug / intelligence\n /**\n * Comma-separated words/phrases likely to appear in speech. Capitalize\n * proper nouns.\n */\n hints: z.string().optional(),\n /** Space-separated event subscriptions, e.g. 'speaker-events tokens-played'. */\n events: z.string().optional(),\n /**\n * Debug subscription, e.g. 'debugging'. Note: 'speaker-events' and\n * 'tokens-played' have moved to the `events` attribute — only use them here\n * for backward compatibility.\n */\n debug: z.string().optional(),\n /**\n * Conversation Intelligence (classic) Service SID or unique name for\n * persisting transcripts and running Language Operators.\n */\n intelligenceService: z.string().optional(),\n\n // Nested <Language> children\n /** Additional `<Language>` children for multi-language support */\n languages: z.array(LanguageConfigSchema).optional(),\n\n /**\n * Escape hatch for ConversationRelay attributes not yet typed on this model.\n * Keys are emitted as-is on `<ConversationRelay>`; Twilio's SDK converts\n * snake_case to camelCase, lowercases bools to 'true'/'false', and\n * stringifies numbers. Prefer a typed field when one exists — use `extra`\n * only for newly-added Twilio attributes not yet in this SDK.\n */\n extra: z.record(z.string(), z.union([z.string(), z.boolean(), z.number()])).optional(),\n })\n // Forbid unknown keys so a typo in a field name fails loudly rather than\n // being silently dropped from the emitted TwiML.\n .strict()\n // Fail fast when `extra` includes a key that has a typed field on this model.\n // Without this, the user's value would be silently dropped by the TwiML\n // serializer in favor of the typed default — a footgun.\n .superRefine((value, ctx) => {\n if (!value.extra) return;\n const typed = new Set(Object.keys(TwiMLOptionsShape).filter(k => k !== 'extra'));\n const shadowed = Object.keys(value.extra)\n .filter(k => typed.has(k))\n .sort();\n if (shadowed.length > 0) {\n ctx.addIssue({\n code: 'custom',\n path: ['extra'],\n message:\n `TwiMLOptions.extra keys [${shadowed.join(', ')}] shadow typed fields. ` +\n 'Set the typed field directly instead of using `extra`.',\n });\n }\n });\n\n/**\n * @internal Field names of {@link TwiMLOptionsSchema}, used by the shadow-guard\n * refinement above. Declared separately because `.strict().superRefine(...)`\n * erases the object shape on the schema instance.\n */\nconst TwiMLOptionsShape = {\n customParameters: true,\n welcomeGreeting: true,\n welcomeGreetingInterruptible: true,\n actionUrl: true,\n conversationConfiguration: true,\n websocketUrl: true,\n language: true,\n ttsLanguage: true,\n transcriptionLanguage: true,\n voice: true,\n ttsProvider: true,\n transcriptionProvider: true,\n speechModel: true,\n elevenlabsTextNormalization: true,\n eotThreshold: true,\n partialPrompts: true,\n deepgramSmartFormat: true,\n speechTimeout: true,\n interruptible: true,\n interruptSensitivity: true,\n reportInputDuringAgentSpeech: true,\n ignoreBackchannel: true,\n preemptible: true,\n dtmfDetection: true,\n hints: true,\n events: true,\n debug: true,\n intelligenceService: true,\n languages: true,\n extra: true,\n} as const;\n\nexport type TwiMLOptions = z.infer<typeof TwiMLOptionsSchema>;\n\n/**\n * Framework-neutral view of the Twilio TwiML webhook form.\n *\n * Populated by `TACServer` from the incoming Twilio webhook, then passed to a\n * customizer registered via `VoiceChannel.onInboundCallTwiml(...)` so the\n * application can produce per-call {@link TwiMLOptions} overrides without\n * depending on Fastify types. Mirrors the Python SDK's `TwiMLRequest`.\n */\nexport const TwiMLRequestSchema = z.object({\n from: z.string().optional(),\n to: z.string().optional(),\n callSid: z.string().optional(),\n callerCountry: z.string().optional(),\n callerState: z.string().optional(),\n callerCity: z.string().optional(),\n direction: z.string().optional(),\n /**\n * Any other fields from the Twilio webhook not captured above. Values are\n * always strings here (webhook form fields are url-encoded), unlike\n * TwiMLOptions.extra which accepts string | boolean | number for emitted\n * TwiML attributes.\n */\n extra: z.record(z.string(), z.string()).default({}),\n});\n\nexport type TwiMLRequest = z.infer<typeof TwiMLRequestSchema>;\n\n/**\n * Map from Twilio webhook form field names to {@link TwiMLRequest} keys.\n * Fields not in this map are bucketed into `extra` by {@link twiMLRequestFromForm}.\n */\nconst TWIML_REQUEST_FORM_ALIASES: Record<string, keyof Omit<TwiMLRequest, 'extra'>> = {\n From: 'from',\n To: 'to',\n CallSid: 'callSid',\n CallerCountry: 'callerCountry',\n CallerState: 'callerState',\n CallerCity: 'callerCity',\n Direction: 'direction',\n};\n\n/**\n * Build a {@link TwiMLRequest} from a raw Twilio form dict, bucketing unknown\n * keys into `extra`. Mirrors the Python SDK's `TwiMLRequest.from_form`.\n */\nexport function twiMLRequestFromForm(form: Record<string, string>): TwiMLRequest {\n const known: Record<string, string> = {};\n const extra: Record<string, string> = {};\n for (const [key, value] of Object.entries(form)) {\n const alias = TWIML_REQUEST_FORM_ALIASES[key];\n if (alias) {\n known[alias] = value;\n } else {\n extra[key] = value;\n }\n }\n return TwiMLRequestSchema.parse({ ...known, extra });\n}\n\n/**\n * Voice channel specific events\n */\nexport interface VoiceChannelEvents {\n setup: SetupMessage;\n prompt: PromptMessage;\n interrupt: InterruptMessage;\n error: Error;\n}\n\n/**\n * ConversationRelay callback payload from Twilio webhook\n *\n * Sent when a ConversationRelay session ends or transitions state.\n * Includes standard voice webhook parameters plus ConversationRelay-specific fields.\n *\n * @see https://www.twilio.com/docs/voice/twiml#request-parameters\n * @see https://www.twilio.com/docs/voice/conversationrelay/conversationrelay-noun#statuscallback\n */\nexport const ConversationRelayCallbackPayloadSchema = z.object({\n // Core Twilio identifiers (required)\n AccountSid: z.string(),\n CallSid: z.string(),\n\n /** Call status with strict type checking for all valid Twilio call states */\n CallStatus: z.enum([\n 'queued',\n 'initiated',\n 'ringing',\n 'in-progress',\n 'completed',\n 'busy',\n 'no-answer',\n 'failed',\n 'canceled',\n ]),\n\n // Call participants (required)\n From: z.string(),\n To: z.string(),\n\n /** Direction of the call */\n Direction: z.enum(['inbound', 'outbound-api', 'outbound-dial']),\n\n // Standard voice webhook parameters (optional)\n ApiVersion: z.string().optional(),\n ForwardedFrom: z.string().optional(),\n CallerName: z.string().optional(),\n ParentCallSid: z.string().optional(),\n ApplicationSid: z.string().optional(),\n\n // ConversationRelay session information (optional)\n SessionId: z.string().optional(),\n SessionStatus: z.string().optional(),\n SessionDuration: z.string().optional(),\n});\n\nexport type ConversationRelayCallbackPayload = z.infer<\n typeof ConversationRelayCallbackPayloadSchema\n>;\n\n// =========================================================================\n// Call Events (status callback, async AMD, recording status)\n// =========================================================================\n\n/**\n * Split a Twilio webhook form into aliased fields and everything else.\n *\n * Unknown keys — including fields that belong to a different call event — are\n * bucketed rather than dropped, so a handler can still reach them via `extra`.\n */\nfunction splitCallEventForm(\n form: Record<string, string>,\n aliases: Record<string, string>\n): { known: Record<string, string>; extra: Record<string, string> } {\n const known: Record<string, string> = {};\n const extra: Record<string, string> = {};\n for (const [key, value] of Object.entries(form)) {\n const alias = aliases[key];\n if (alias) {\n known[alias] = value;\n } else {\n extra[key] = value;\n }\n }\n return { known, extra };\n}\n\n/**\n * Fields shared by the three Twilio call-webhook events.\n *\n * `callSid` is the correlation key across every surface — it matches\n * `ConversationSession.callSid` and the SID from\n * `initiateOutboundConversation`. It's required: every real call webhook\n * carries one, and defaulting it would hand handlers an empty SID to act on\n * (`endCall('')` is a Twilio 404). Missing or blank fails validation, which the\n * channel turns into a 400.\n */\nconst CallEventBaseShape = {\n callSid: z.string().min(1, 'CallSid is required'),\n accountSid: z.string().optional(),\n /** Any other Twilio webhook fields not surfaced above. */\n extra: z.record(z.string(), z.string()).default({}),\n};\n\nconst CALL_EVENT_BASE_ALIASES = {\n CallSid: 'callSid',\n AccountSid: 'accountSid',\n} as const;\n\n/**\n * Call statuses that mean the call ended without reaching the callee — i.e.\n * worth a retry.\n */\nconst UNREACHED_CALL_STATUSES: readonly string[] = ['busy', 'no-answer', 'failed', 'canceled'];\n\n/**\n * A Twilio `statusCallback` webhook — call progress and disposition.\n *\n * By default Twilio sends only the terminal event, which covers every\n * disposition (`completed` / `busy` / `no-answer` / `failed` / `canceled`); set\n * `CallOptions.statusCallbackEvent` for the intermediate ones. Register a\n * handler via `VoiceChannel.onCallStatus`.\n *\n * `isUnreached` is computed at parse time so application code doesn't have to\n * match disposition strings itself.\n */\nexport const CallStatusEventSchema = z\n .object({\n ...CallEventBaseShape,\n callStatus: z.string().optional(),\n callDuration: z.string().optional(),\n sipResponseCode: z.string().optional(),\n })\n .transform(event => ({\n ...event,\n /** Call ended without reaching the callee — i.e. worth a retry. */\n isUnreached: UNREACHED_CALL_STATUSES.includes(event.callStatus ?? ''),\n }));\n\nexport type CallStatusEvent = z.infer<typeof CallStatusEventSchema>;\n\nconst CALL_STATUS_EVENT_ALIASES: Record<string, string> = {\n ...CALL_EVENT_BASE_ALIASES,\n CallStatus: 'callStatus',\n CallDuration: 'callDuration',\n SipResponseCode: 'sipResponseCode',\n};\n\n/** Build a {@link CallStatusEvent} from a raw Twilio webhook form. */\nexport function callStatusEventFromForm(form: Record<string, string>): CallStatusEvent {\n const { known, extra } = splitCallEventForm(form, CALL_STATUS_EVENT_ALIASES);\n return CallStatusEventSchema.parse({ ...known, extra });\n}\n\n/**\n * A Twilio `asyncAmdStatusCallback` webhook — answering machine detection.\n *\n * Fires at most once per call, and only when the call set both\n * `CallOptions.machineDetection` and `asyncAmd`.\n *\n * `answeredBy` is mode-dependent — `machine_start` under `'Enable'`,\n * `machine_end_beep` / `machine_end_silence` / `machine_end_other` under\n * `'DetectMessageEnd'`, plus `human` / `fax` / `unknown` in both. Use\n * `isMachine` rather than matching those yourself. Register a handler via\n * `VoiceChannel.onAmd`.\n */\nexport const AmdEventSchema = z\n .object({\n ...CallEventBaseShape,\n answeredBy: z.string().optional(),\n machineDetectionDuration: z.string().optional(),\n })\n .transform(event => ({\n ...event,\n /**\n * A machine answered — any `machine_*` value, either mode. `unknown`\n * (detection timed out) is false, so a call is never hung up on a guess.\n */\n isMachine: (event.answeredBy ?? '').startsWith('machine'),\n }));\n\nexport type AmdEvent = z.infer<typeof AmdEventSchema>;\n\nconst AMD_EVENT_ALIASES: Record<string, string> = {\n ...CALL_EVENT_BASE_ALIASES,\n AnsweredBy: 'answeredBy',\n MachineDetectionDuration: 'machineDetectionDuration',\n};\n\n/** Build an {@link AmdEvent} from a raw Twilio webhook form. */\nexport function amdEventFromForm(form: Record<string, string>): AmdEvent {\n const { known, extra } = splitCallEventForm(form, AMD_EVENT_ALIASES);\n return AmdEventSchema.parse({ ...known, extra });\n}\n\n/**\n * A Twilio `recordingStatusCallback` webhook — a recording became available.\n *\n * Fires when the recording is ready (`recordingUrl` accessible), only when\n * recording is enabled. Register a handler via `VoiceChannel.onRecording`.\n */\nexport const RecordingEventSchema = z.object({\n ...CallEventBaseShape,\n recordingSid: z.string().optional(),\n recordingUrl: z.string().optional(),\n recordingStatus: z.string().optional(),\n recordingDuration: z.string().optional(),\n});\n\nexport type RecordingEvent = z.infer<typeof RecordingEventSchema>;\n\nconst RECORDING_EVENT_ALIASES: Record<string, string> = {\n ...CALL_EVENT_BASE_ALIASES,\n RecordingSid: 'recordingSid',\n RecordingUrl: 'recordingUrl',\n RecordingStatus: 'recordingStatus',\n RecordingDuration: 'recordingDuration',\n};\n\n/** Build a {@link RecordingEvent} from a raw Twilio webhook form. */\nexport function recordingEventFromForm(form: Record<string, string>): RecordingEvent {\n const { known, extra } = splitCallEventForm(form, RECORDING_EVENT_ALIASES);\n return RecordingEventSchema.parse({ ...known, extra });\n}\n\n// =========================================================================\n// Calls API parameters (calls.create passthrough)\n// =========================================================================\n\n/**\n * Every parameter `client.calls.create()` accepts, as of the pinned Twilio SDK.\n *\n * Unlike Python's `inspect.signature`, TypeScript has no runtime view of a\n * function's accepted keys, so the set is listed here and pinned to the SDK by\n * {@link _CallsCreateDriftGuards} at typecheck time. It's needed at runtime\n * because the Node SDK builds its request body from an explicit whitelist —\n * an unrecognized key is **silently dropped**, not an error, so without this a\n * typo would look like it worked.\n */\nconst CALLS_CREATE_PARAMS = [\n 'applicationSid',\n 'asyncAmd',\n 'asyncAmdStatusCallback',\n 'asyncAmdStatusCallbackMethod',\n 'byoc',\n 'callerId',\n 'callReason',\n 'callToken',\n 'clientNotificationUrl',\n 'fallbackMethod',\n 'fallbackUrl',\n 'from',\n 'machineDetection',\n 'machineDetectionSilenceTimeout',\n 'machineDetectionSpeechEndThreshold',\n 'machineDetectionSpeechThreshold',\n 'machineDetectionTimeout',\n 'method',\n 'record',\n 'recordingChannels',\n 'recordingStatusCallback',\n 'recordingStatusCallbackEvent',\n 'recordingStatusCallbackMethod',\n 'recordingTrack',\n 'sendDigits',\n 'sipAuthPassword',\n 'sipAuthUsername',\n 'statusCallback',\n 'statusCallbackEvent',\n 'statusCallbackMethod',\n 'timeLimit',\n 'timeout',\n 'to',\n 'trim',\n 'twiml',\n 'url',\n] as const;\n\n/**\n * `calls.create` parameters TAC owns — it builds the call and its TwiML, so a\n * caller setting these would either be overwritten or break the call.\n */\nconst RESERVED_CALL_PARAMS = ['to', 'from', 'twiml', 'url', 'applicationSid'] as const;\n\ntype ReservedCallParam = (typeof RESERVED_CALL_PARAMS)[number];\n\n/**\n * The `calls.create` parameters TAC types explicitly — the ones outbound\n * ConversationRelay reaches for. Everything else the SDK accepts is still\n * forwarded, typed by the SDK itself via {@link CallOptions}.\n */\nexport interface TypedCallOptions {\n /**\n * Enables AMD. `'Enable'` reports as soon as it can tell human from machine\n * (to hang up on voicemail); `'DetectMessageEnd'` waits out the greeting (to\n * leave a message). Required, together with `asyncAmd`, for `onAmd` to fire.\n */\n machineDetection?: 'Enable' | 'DetectMessageEnd' | undefined;\n /**\n * Detect in the background. Required for `onAmd`: with it off, `AnsweredBy`\n * comes back on the TwiML request, which inline TwiML can't receive.\n *\n * Twilio's API types this as a string; a boolean is serialized for you.\n */\n asyncAmd?: boolean | string | undefined;\n asyncAmdStatusCallback?: string | undefined;\n asyncAmdStatusCallbackMethod?: string | undefined;\n machineDetectionTimeout?: number | undefined;\n machineDetectionSpeechThreshold?: number | undefined;\n machineDetectionSpeechEndThreshold?: number | undefined;\n machineDetectionSilenceTimeout?: number | undefined;\n\n /** Required for `onRecording`. */\n record?: boolean | undefined;\n recordingStatusCallback?: string | undefined;\n recordingStatusCallbackEvent?: string[] | undefined;\n recordingChannels?: string | undefined;\n recordingTrack?: string | undefined;\n\n statusCallback?: string | undefined;\n /**\n * Lifecycle events to report. Omitted, Twilio sends only `'completed'` —\n * which covers busy/canceled/failed/no-answer. Set it for ringing/answered.\n */\n statusCallbackEvent?: string[] | undefined;\n statusCallbackMethod?: string | undefined;\n /** Seconds to ring before giving up. Twilio defaults to 60. */\n timeout?: number | undefined;\n}\n\n/**\n * Parameters for Twilio's `client.calls.create()`.\n *\n * {@link TypedCallOptions} covers the ones outbound ConversationRelay reaches\n * for; any other parameter `calls.create()` accepts is forwarded too, typed by\n * the Twilio SDK. TAC-owned parameters (`to`, `from`, `twiml`, `url`,\n * `applicationSid`) are excluded — TAC builds the call and its TwiML.\n *\n * Unknown keys are rejected at validation, so a typo fails at\n * `initiateOutboundConversation` rather than being silently dropped by the SDK.\n *\n * @example\n * ```typescript\n * const callOptions: CallOptions = {\n * machineDetection: 'Enable',\n * asyncAmd: true,\n * record: true,\n * };\n * ```\n */\nexport type CallOptions = TypedCallOptions &\n Omit<CallListInstanceCreateOptions, ReservedCallParam | keyof TypedCallOptions>;\n\n/**\n * @internal Fails typecheck unless instantiated with `true`. A conditional type\n * that merely resolves to `never` is not an error on its own, so the assertion\n * has to be a constraint violation to be load-bearing.\n */\ntype _AssertTrue<T extends true> = T;\n\n/**\n * @internal Compile-time SDK drift guards — do not use directly.\n * If the Twilio SDK adds, removes, or renames a `calls.create` parameter these\n * checks fail during `npm run typecheck`, signaling that\n * {@link CALLS_CREATE_PARAMS} needs updating. Without the `complete` direction a\n * newly added SDK parameter would be rejected at runtime as unknown.\n */\nexport type _CallsCreateDriftGuards = {\n known: _AssertTrue<\n (typeof CALLS_CREATE_PARAMS)[number] extends keyof CallListInstanceCreateOptions ? true : false\n >;\n complete: _AssertTrue<\n keyof CallListInstanceCreateOptions extends (typeof CALLS_CREATE_PARAMS)[number] ? true : false\n >;\n typedAreRealParams: _AssertTrue<\n keyof TypedCallOptions extends keyof CallListInstanceCreateOptions ? true : false\n >;\n reservedAreRealParams: _AssertTrue<\n ReservedCallParam extends keyof CallListInstanceCreateOptions ? true : false\n >;\n};\n\nconst ACCEPTED_CALL_PARAMS: ReadonlySet<string> = new Set(CALLS_CREATE_PARAMS);\n\n/**\n * Whether an `asyncAmd` value actually turns background detection on.\n *\n * Accepts the boolean TAC serializes for callers and the string Twilio's API\n * types the parameter as, so `'false'` reads as off rather than as a non-empty\n * (therefore truthy) string.\n */\nfunction isAsyncAmdEnabled(value: unknown): boolean {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.trim().toLowerCase() === 'true';\n return false;\n}\n\n/**\n * Runtime validation for {@link CallOptions}.\n *\n * Loose rather than strict so untyped-but-real Calls API parameters pass\n * through; `superRefine` then rejects TAC-owned and unknown keys explicitly so\n * the message says which mistake was made.\n */\nconst CallOptionsObjectSchema = z\n .looseObject({\n machineDetection: z.enum(['Enable', 'DetectMessageEnd']).optional(),\n asyncAmd: z.union([z.boolean(), z.string()]).optional(),\n asyncAmdStatusCallback: z.string().optional(),\n asyncAmdStatusCallbackMethod: z.string().optional(),\n machineDetectionTimeout: z.number().int().optional(),\n machineDetectionSpeechThreshold: z.number().int().optional(),\n machineDetectionSpeechEndThreshold: z.number().int().optional(),\n machineDetectionSilenceTimeout: z.number().int().optional(),\n\n record: z.boolean().optional(),\n recordingStatusCallback: z.string().optional(),\n recordingStatusCallbackEvent: z.array(z.string()).optional(),\n recordingChannels: z.string().optional(),\n recordingTrack: z.string().optional(),\n\n statusCallback: z.string().optional(),\n statusCallbackEvent: z.array(z.string()).optional(),\n statusCallbackMethod: z.string().optional(),\n timeout: z.number().int().optional(),\n })\n .superRefine((value, ctx) => {\n const supplied = Object.keys(value);\n\n const conflict = supplied.filter(key =>\n (RESERVED_CALL_PARAMS as readonly string[]).includes(key)\n );\n if (conflict.length > 0) {\n ctx.addIssue({\n code: 'custom',\n message:\n `callOptions may not set TAC-owned call parameters: ${conflict.sort().join(', ')}. ` +\n 'TAC builds the call and its TwiML.',\n });\n }\n\n const unknown = supplied.filter(key => !ACCEPTED_CALL_PARAMS.has(key));\n if (unknown.length > 0) {\n ctx.addIssue({\n code: 'custom',\n message:\n \"callOptions has parameters Twilio's calls.create() does not accept: \" +\n `${unknown.sort().join(', ')}. Check for a typo, or upgrade the twilio package.`,\n });\n }\n\n // AMD needs both flags. machineDetection turns detection on; asyncAmd\n // delivers AnsweredBy to a callback. Without asyncAmd, Twilio returns it on\n // the TwiML request instead — unreachable, since TAC sends inline TwiML.\n //\n // asyncAmd is checked by value, not truthiness: Twilio's API types it as a\n // string, and `Boolean('false')` is true — so a plain truthiness test would\n // wave through `asyncAmd: 'false'` and silently deliver no AMD event.\n if (Boolean(value.machineDetection) !== isAsyncAmdEnabled(value.asyncAmd)) {\n ctx.addIssue({\n code: 'custom',\n message:\n 'AMD requires both machineDetection and asyncAmd; got ' +\n `machineDetection=${JSON.stringify(value.machineDetection)}, ` +\n `asyncAmd=${JSON.stringify(value.asyncAmd)}.`,\n });\n }\n });\n\n/**\n * Validates {@link CallOptions}. The parsed value is re-widened to `CallOptions`\n * because the loose object's inferred index signature would otherwise erase the\n * SDK-derived parameter types.\n */\nexport const CallOptionsSchema: z.ZodType<CallOptions, unknown> = CallOptionsObjectSchema.transform(\n value => value as CallOptions\n);\n\n/**\n * Serialize {@link CallOptions} into the argument object for\n * `client.calls.create()`, dropping unset keys.\n *\n * `asyncAmd` is coerced to a string because Twilio's SDK types it as one,\n * unlike `record`.\n */\nexport function callOptionsToCreateParams(options: CallOptions): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(options)) {\n if (value === undefined) continue;\n params[key] = key === 'asyncAmd' && typeof value === 'boolean' ? String(value) : value;\n }\n return params;\n}\n\n// =========================================================================\n// Outbound Voice Conversation Types\n// =========================================================================\n\n/**\n * Options for initiating an outbound voice conversation.\n *\n * The caller identity is always TAC's configured `config.phoneNumber`.\n * Multi-number deployments should run one TAC instance per line.\n *\n * TwiML for the outbound call is built by merging per-field, highest precedence\n * first:\n * 1. This call's `twimlOptions` (per-call overrides)\n * 2. `VoiceChannelConfig.defaultTwimlOptions` (channel-wide defaults)\n * 3. TAC defaults (welcome greeting, conversationConfiguration, actionUrl\n * resolved via Studio handoff if configured, else derived from\n * `TACConfig.voicePublicDomain` + `voiceActionPath`)\n *\n * Fields you don't set at a layer fall through to lower layers — so\n * `twimlOptions: { voice: 'es-MX-Neural2-A' }` on this call overrides only\n * `voice`; `language`, `interruptible`, etc. from the channel config still apply.\n */\nexport interface InitiateVoiceConversationOptions {\n to: string;\n /**\n * Public WebSocket URL for ConversationRelay (e.g. 'wss://your-domain.ngrok.app/ws').\n * Optional — defaults to the URL derived from `TACConfig.voicePublicDomain` +\n * `voiceWebsocketPath`. Pass it here only to override the URL for a specific call.\n */\n websocketUrl?: string | undefined;\n /**\n * Per-call overrides for the TwiML inside `<ConversationRelay>`. Merged over\n * `VoiceChannelConfig.defaultTwimlOptions` and TAC defaults.\n */\n twimlOptions?: TwiMLOptions | undefined;\n /**\n * Parameters for Twilio's `calls.create()` — AMD, recording, status\n * callbacks, timeout (see {@link CallOptions}). Callback URLs auto-wire when\n * the matching handler is registered; an explicit URL wins.\n */\n callOptions?: CallOptions | undefined;\n}\n\nexport const InitiateVoiceConversationOptionsSchema: z.ZodType<InitiateVoiceConversationOptions> = z\n .object({\n to: z.string().min(1, 'Recipient phone number is required'),\n websocketUrl: z.url().optional(),\n twimlOptions: TwiMLOptionsSchema.optional(),\n callOptions: CallOptionsSchema.optional(),\n })\n // Reject removed flat fields (welcomeGreeting, actionUrl, customParameters,\n // conversationRelayConfig) so callers upgrading from older TAC versions get\n // a clear error instead of having their values silently dropped.\n .strict();\n","import { z } from 'zod';\n\n/**\n * JSON Schema definition for tool parameters\n */\nexport const JSONSchemaSchema = z.object({\n type: z.enum(['object', 'string', 'number', 'boolean', 'array']),\n properties: z.record(z.string(), z.any()).optional(),\n required: z.array(z.string()).optional(),\n items: z.any().optional(),\n enum: z.array(z.any()).optional(),\n description: z.string().optional(),\n});\n\nexport type JSONSchema = z.infer<typeof JSONSchemaSchema>;\n\n/**\n * Tool function signature\n */\nexport type ToolFunction<TParams = unknown, TResult = unknown> = (\n params: TParams\n) => Promise<TResult> | TResult;\n\n/**\n * Core tool definition\n */\nexport interface TACTool<TParams = unknown, TResult = unknown> {\n name: string;\n description: string;\n parameters: JSONSchema;\n implementation: ToolFunction<TParams, TResult>;\n}\n\n/**\n * OpenAI tool format\n */\nexport const OpenAIToolSchema = z.object({\n type: z.literal('function'),\n function: z.object({\n name: z.string(),\n description: z.string(),\n parameters: JSONSchemaSchema,\n }),\n});\n\nexport type OpenAITool = z.infer<typeof OpenAIToolSchema>;\n\n/**\n * Anthropic tool format\n */\nexport const AnthropicToolSchema = z.object({\n name: z.string(),\n description: z.string(),\n input_schema: JSONSchemaSchema,\n});\n\nexport type AnthropicTool = z.infer<typeof AnthropicToolSchema>;\n\n/**\n * Tool execution context\n */\nexport interface ToolContext {\n conversationId?: string;\n profileId?: string;\n channel?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Tool execution result\n */\nexport const ToolExecutionResultSchema = z.object({\n success: z.boolean(),\n data: z.any().optional(),\n error: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type ToolExecutionResult = z.infer<typeof ToolExecutionResultSchema>;\n\n/**\n * Built-in tool types\n */\nexport const BuiltInTools = {\n RETRIEVE_MEMORY: 'retrieve_profile_memory',\n SEND_MESSAGE: 'send_message',\n HANDOFF: 'handoff',\n SEARCH_KNOWLEDGE: 'search_knowledge',\n} as const;\n\nexport type BuiltInToolName = (typeof BuiltInTools)[keyof typeof BuiltInTools];\n","import { z } from 'zod';\n\n/**\n * Conversation Intelligence Types\n *\n * These types represent the webhook payloads and configuration for\n * processing Conversation Intelligence operator results.\n */\n\n/**\n * Participant in operator execution (e.g., CUSTOMER, AGENT)\n */\nexport const CintelParticipantSchema = z.object({\n type: z.string(),\n profileId: z.string().optional(),\n mediaParticipantId: z.string().optional(),\n});\n\nexport type CintelParticipant = z.infer<typeof CintelParticipantSchema>;\n\n/**\n * Execution details for an operator result\n */\nexport const ExecutionDetailsSchema = z.object({\n participants: z.array(CintelParticipantSchema).optional(),\n});\n\nexport type ExecutionDetails = z.infer<typeof ExecutionDetailsSchema>;\n\n/**\n * Operator metadata\n */\nexport const OperatorSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n});\n\nexport type Operator = z.infer<typeof OperatorSchema>;\n\n/**\n * Individual operator result from Conversation Intelligence\n */\nexport const OperatorResultSchema = z.object({\n id: z.string(),\n operator: OperatorSchema,\n outputFormat: z.string(),\n result: z.unknown(),\n dateCreated: z.string(),\n referenceIds: z.array(z.string()).optional().default([]),\n executionDetails: ExecutionDetailsSchema.optional(),\n});\n\nexport type OperatorResult = z.infer<typeof OperatorResultSchema>;\n\n/**\n * Intelligence configuration metadata\n */\nexport const IntelligenceConfigurationSchema = z.object({\n id: z.string(),\n friendlyName: z.string().optional(),\n});\n\nexport type IntelligenceConfiguration = z.infer<typeof IntelligenceConfigurationSchema>;\n\n/**\n * Full webhook payload for operator result events\n */\nexport const OperatorResultEventSchema = z.object({\n accountId: z.string(),\n conversationId: z.string(),\n memoryStoreId: z.string().optional(),\n intelligenceConfiguration: IntelligenceConfigurationSchema,\n operatorResults: z.array(OperatorResultSchema),\n});\n\nexport type OperatorResultEvent = z.infer<typeof OperatorResultEventSchema>;\n\n/**\n * Result of processing an operator result event\n */\nexport const OperatorProcessingResultSchema = z.object({\n success: z.boolean(),\n eventType: z.string().optional(),\n skipped: z.boolean().default(false),\n skipReason: z.string().optional(),\n error: z.string().optional(),\n createdCount: z.number().default(0),\n});\n\nexport type OperatorProcessingResult = z.infer<typeof OperatorProcessingResultSchema>;\n\n/**\n * Conversation Intelligence configuration for TAC\n */\nexport const ConversationIntelligenceConfigSchema = z.object({\n configurationId: z.string(),\n summaryOperatorSid: z.string().optional(),\n});\n\nexport type ConversationIntelligenceConfig = z.infer<typeof ConversationIntelligenceConfigSchema>;\n\n/**\n * Summary item for batch creation\n */\nexport const ConversationSummaryItemSchema = z.object({\n content: z.string(),\n conversationId: z.string(),\n occurredAt: z.string(),\n source: z.string().optional(),\n});\n\nexport type ConversationSummaryItem = z.infer<typeof ConversationSummaryItemSchema>;\n","import { z } from 'zod';\n\n/**\n * Knowledge base status enum\n */\nexport const KnowledgeBaseStatusSchema = z.enum([\n 'QUEUED',\n 'PROVISIONING',\n 'ACTIVE',\n 'FAILED',\n 'DELETING',\n]);\n\nexport type KnowledgeBaseStatus = z.infer<typeof KnowledgeBaseStatusSchema>;\n\n/**\n * Knowledge base metadata (from GET endpoint)\n */\nexport const KnowledgeBaseSchema = z.object({\n id: z.string(),\n displayName: z.string(),\n description: z.string(),\n status: KnowledgeBaseStatusSchema,\n createdAt: z.string(),\n updatedAt: z.string(),\n version: z.number(),\n});\n\nexport type KnowledgeBase = z.infer<typeof KnowledgeBaseSchema>;\n\n/**\n * Search result chunk (from POST search endpoint)\n */\nexport const KnowledgeChunkResultSchema = z.object({\n content: z.string(),\n knowledgeId: z.string(),\n createdAt: z.string(),\n score: z.number().optional(),\n});\n\nexport type KnowledgeChunkResult = z.infer<typeof KnowledgeChunkResultSchema>;\n\n/**\n * Search response wrapper\n */\nexport const KnowledgeSearchResponseSchema = z.object({\n chunks: z.array(KnowledgeChunkResultSchema),\n});\n\nexport type KnowledgeSearchResponse = z.infer<typeof KnowledgeSearchResponseSchema>;\n","import { TACConfigData, TACConfigSchema, EnvironmentVariables } from '../types/index';\nimport type { CallEventKind } from '../types/index';\nimport { z } from 'zod';\n\n/**\n * TAC Configuration class with Python-like static factory methods\n *\n * Example usage:\n * ```typescript\n * // Load from environment variables\n * const config = TACConfig.fromEnv();\n *\n * // Or create manually\n * const config = new TACConfig({\n * accountSid: 'ACxxxx',\n * // ...\n * });\n * ```\n */\nexport class TACConfig {\n public readonly accountSid: string;\n public readonly authToken: string;\n public readonly apiKey: string;\n public readonly apiSecret: string;\n public readonly phoneNumber: string;\n public readonly rcsSenderId?: string;\n public readonly whatsappNumber?: string;\n public readonly memoryConfig: TACConfigData['memoryConfig'];\n public readonly conversationConfigurationId?: string;\n public readonly voicePublicDomain?: string;\n /** Path the voice WebSocket is served at (default '/ws'). */\n public readonly voiceWebsocketPath: string;\n /** Path the ConversationRelay action callback is served at (default '/conversation-relay-callback'). */\n public readonly voiceActionPath: string;\n /** Base path the call-event callbacks are served under (default '/twilio/call-events'). */\n public readonly voiceCallEventPath: string;\n public readonly cintelConfigurationId?: string;\n public readonly cintelSummaryOperatorSid?: string;\n /** Optional Twilio region subdomain for API routing (e.g. transforms base URLs to `https://{product}.{region}.twilio.com`) */\n public readonly region?: string;\n /**\n * Twilio Studio Flow SID for handoff. TAC derives both the digital-handoff\n * Studio Executions URL (`studio.twilio.com/v2/Flows/{SID}/Executions`) and\n * the voice `<Connect action>` webhook URL\n * (`webhooks.twilio.com/v1/Accounts/{AccountSid}/Flows/{SID}?Trigger=incomingCall`)\n * from this SID.\n */\n public readonly studioHandoffFlowSid?: string;\n constructor(data: TACConfigData | z.input<typeof TACConfigSchema>) {\n // Validate the configuration data\n const validatedConfig = TACConfigSchema.parse(data);\n\n // Assign all properties\n this.accountSid = validatedConfig.accountSid;\n this.authToken = validatedConfig.authToken;\n this.apiKey = validatedConfig.apiKey;\n this.apiSecret = validatedConfig.apiSecret;\n this.phoneNumber = validatedConfig.phoneNumber;\n if (validatedConfig.rcsSenderId) {\n this.rcsSenderId = validatedConfig.rcsSenderId;\n }\n if (validatedConfig.whatsappNumber) {\n this.whatsappNumber = validatedConfig.whatsappNumber;\n }\n // Assign the validated memory config directly; schema parsing already validates shape and applies defaults\n this.memoryConfig = validatedConfig.memoryConfig;\n if (validatedConfig.conversationConfigurationId) {\n this.conversationConfigurationId = validatedConfig.conversationConfigurationId;\n }\n if (validatedConfig.voicePublicDomain) {\n this.voicePublicDomain = validatedConfig.voicePublicDomain;\n }\n // voiceWebsocketPath / voiceActionPath / voiceCallEventPath always have schema defaults\n this.voiceWebsocketPath = validatedConfig.voiceWebsocketPath;\n this.voiceActionPath = validatedConfig.voiceActionPath;\n this.voiceCallEventPath = validatedConfig.voiceCallEventPath;\n if (validatedConfig.cintelConfigurationId) {\n this.cintelConfigurationId = validatedConfig.cintelConfigurationId;\n }\n if (validatedConfig.cintelSummaryOperatorSid) {\n this.cintelSummaryOperatorSid = validatedConfig.cintelSummaryOperatorSid;\n }\n if (validatedConfig.region) {\n this.region = validatedConfig.region;\n }\n if (validatedConfig.studioHandoffFlowSid) {\n this.studioHandoffFlowSid = validatedConfig.studioHandoffFlowSid;\n }\n }\n\n /**\n * Create TACConfig from environment variables.\n *\n * Required environment variables:\n * - TWILIO_ACCOUNT_SID: Twilio Account SID\n * - TWILIO_AUTH_TOKEN: Twilio Auth Token for API authentication\n * - TWILIO_API_KEY: Twilio API Key SID (starts with SK)\n * - TWILIO_API_SECRET: Twilio API Secret for API Key authentication\n * - TWILIO_PHONE_NUMBER: Phone number for voice and SMS channels\n *\n * Optional environment variables:\n * - TWILIO_WHATSAPP_NUMBER: WhatsApp number for WhatsApp channel (e.g., 'whatsapp:+1234567890')\n * - TWILIO_CONVERSATION_CONFIGURATION_ID: Conversation Orchestrator configuration ID (enables orchestrated mode)\n * - TWILIO_VOICE_PUBLIC_DOMAIN: Public domain for voice routes (required for voice; a port and/or base path are allowed, e.g., 'abc123.ngrok.app', 'example.ngrok.app:8080', or 'example.com/server1')\n * - TWILIO_VOICE_WEBSOCKET_PATH: Path for the voice WebSocket (default: /ws)\n * - TWILIO_VOICE_ACTION_PATH: Path for the ConversationRelay action callback (default: /conversation-relay-callback)\n * - TWILIO_VOICE_CALL_EVENT_PATH: Base path for the call-event callbacks — status, async AMD, recording (default: /twilio/call-events)\n * - TWILIO_REGION: Twilio region subdomain for API routing (e.g. transforms base URLs to `https://{product}.{region}.twilio.com`)\n * - TWILIO_STUDIO_HANDOFF_FLOW_SID: Studio Flow SID used by createStudioHandoffTool for human handoff\n * - TWILIO_RCS_SENDER_ID: RCS Sender ID for the RCS channel\n *\n * Memory Configuration (defaults defined in TwilioMemoryConfigSchema):\n * - TWILIO_MEMORY_PROFILE_TRAIT_GROUPS: Trait groups to include (comma-separated, e.g., \"Contact,Preferences\")\n * - TWILIO_MEMORY_OBSERVATIONS_LIMIT: Max observations in memory retrieval\n * - TWILIO_MEMORY_SUMMARIES_LIMIT: Max summaries in memory retrieval\n * - TWILIO_MEMORY_COMMUNICATIONS_LIMIT: Max communications in memory retrieval\n * - TWILIO_MEMORY_RELEVANCE_THRESHOLD: Min relevance score (0.0-1.0)\n * - TWILIO_MEMORY_PHONE_TRAIT_GROUP: Trait group that holds the phone identifier on new profiles (default \"Contact\")\n * - TWILIO_MEMORY_PHONE_TRAIT_FIELD: Trait field within phoneTraitGroup (default \"phone\")\n *\n * @throws Error if required environment variables are not set or invalid\n *\n * @example\n * ```typescript\n * // Ensure env vars are set before calling (e.g. via dotenv, Docker, CI, etc.)\n * const config = TACConfig.fromEnv();\n *\n * // Use in TAC initialization\n * const tac = new TAC({ config });\n * ```\n */\n public static fromEnv(): TACConfig {\n // Check for required environment variables\n const requiredVars = [\n { key: EnvironmentVariables.TWILIO_ACCOUNT_SID, name: 'TWILIO_ACCOUNT_SID' },\n { key: EnvironmentVariables.TWILIO_AUTH_TOKEN, name: 'TWILIO_AUTH_TOKEN' },\n { key: EnvironmentVariables.TWILIO_API_KEY, name: 'TWILIO_API_KEY' },\n { key: EnvironmentVariables.TWILIO_API_SECRET, name: 'TWILIO_API_SECRET' },\n { key: EnvironmentVariables.TWILIO_PHONE_NUMBER, name: 'TWILIO_PHONE_NUMBER' },\n ];\n\n // Throw error for missing required variables (like Python's KeyError)\n for (const { key, name } of requiredVars) {\n if (!process.env[key]) {\n throw new Error(`Missing required environment variable: ${name}`);\n }\n }\n\n // Parse memory configuration from environment variables\n const traitGroupsStr = process.env[EnvironmentVariables.TWILIO_MEMORY_PROFILE_TRAIT_GROUPS];\n // Parse trait groups, filtering out empty strings from malformed CSV (e.g., \"A,,B,\")\n // Treat empty/whitespace-only strings and delimiter-only inputs as undefined for consistency\n const trimmedTraitGroups = traitGroupsStr?.trim();\n const parsedTraitGroups =\n trimmedTraitGroups && trimmedTraitGroups.length > 0\n ? trimmedTraitGroups\n .split(',')\n .map(g => g.trim())\n .filter(g => g.length > 0)\n : undefined;\n const traitGroups =\n parsedTraitGroups && parsedTraitGroups.length > 0 ? parsedTraitGroups : undefined;\n\n // Helper to parse integer from env var with validation and bounds checking.\n // Returns undefined when the env var is not set, letting the Zod schema apply defaults.\n const parseIntEnv = (\n envVarName: string,\n value: string | undefined,\n min: number,\n max: number\n ): number | undefined => {\n if (!value) return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n\n const parsed = Number(trimmed);\n if (!Number.isFinite(parsed)) {\n throw new Error(`Invalid ${envVarName}: expected an integer, got \"${value}\"`);\n }\n if (!Number.isInteger(parsed)) {\n throw new Error(`Invalid ${envVarName}: expected an integer, got \"${value}\"`);\n }\n if (parsed < min || parsed > max) {\n throw new Error(`Invalid ${envVarName}: must be between ${min} and ${max}, got ${parsed}`);\n }\n return parsed;\n };\n\n // Helper to parse float from env var with validation and bounds checking.\n // Returns undefined when the env var is not set, letting the Zod schema apply defaults.\n const parseFloatEnv = (\n envVarName: string,\n value: string | undefined,\n min: number,\n max: number\n ): number | undefined => {\n if (!value) return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n\n const parsed = Number(trimmed);\n if (!Number.isFinite(parsed)) {\n throw new Error(`Invalid ${envVarName}: expected a number, got \"${value}\"`);\n }\n if (parsed < min || parsed > max) {\n throw new Error(`Invalid ${envVarName}: must be between ${min} and ${max}, got ${parsed}`);\n }\n return parsed;\n };\n\n const rawConfig = {\n accountSid: process.env[EnvironmentVariables.TWILIO_ACCOUNT_SID]!,\n authToken: process.env[EnvironmentVariables.TWILIO_AUTH_TOKEN]!,\n apiKey: process.env[EnvironmentVariables.TWILIO_API_KEY]!,\n apiSecret: process.env[EnvironmentVariables.TWILIO_API_SECRET]!,\n phoneNumber: process.env[EnvironmentVariables.TWILIO_PHONE_NUMBER]!,\n rcsSenderId: process.env[EnvironmentVariables.TWILIO_RCS_SENDER_ID],\n whatsappNumber: process.env[EnvironmentVariables.TWILIO_WHATSAPP_NUMBER] || undefined,\n memoryConfig: {\n traitGroups,\n observationsLimit: parseIntEnv(\n 'TWILIO_MEMORY_OBSERVATIONS_LIMIT',\n process.env[EnvironmentVariables.TWILIO_MEMORY_OBSERVATIONS_LIMIT],\n 0,\n 100\n ),\n summariesLimit: parseIntEnv(\n 'TWILIO_MEMORY_SUMMARIES_LIMIT',\n process.env[EnvironmentVariables.TWILIO_MEMORY_SUMMARIES_LIMIT],\n 0,\n 100\n ),\n communicationsLimit: parseIntEnv(\n 'TWILIO_MEMORY_COMMUNICATIONS_LIMIT',\n process.env[EnvironmentVariables.TWILIO_MEMORY_COMMUNICATIONS_LIMIT],\n 0,\n 100\n ),\n relevanceThreshold: parseFloatEnv(\n 'TWILIO_MEMORY_RELEVANCE_THRESHOLD',\n process.env[EnvironmentVariables.TWILIO_MEMORY_RELEVANCE_THRESHOLD],\n 0.0,\n 1.0\n ),\n phoneTraitGroup:\n process.env[EnvironmentVariables.TWILIO_MEMORY_PHONE_TRAIT_GROUP] || undefined,\n phoneTraitField:\n process.env[EnvironmentVariables.TWILIO_MEMORY_PHONE_TRAIT_FIELD] || undefined,\n },\n conversationConfigurationId:\n process.env[EnvironmentVariables.TWILIO_CONVERSATION_CONFIGURATION_ID] || undefined,\n voicePublicDomain: process.env[EnvironmentVariables.TWILIO_VOICE_PUBLIC_DOMAIN],\n voiceWebsocketPath:\n process.env[EnvironmentVariables.TWILIO_VOICE_WEBSOCKET_PATH] || undefined,\n voiceActionPath: process.env[EnvironmentVariables.TWILIO_VOICE_ACTION_PATH] || undefined,\n voiceCallEventPath:\n process.env[EnvironmentVariables.TWILIO_VOICE_CALL_EVENT_PATH] || undefined,\n cintelConfigurationId: process.env[EnvironmentVariables.TWILIO_TAC_CI_CONFIGURATION_ID],\n cintelSummaryOperatorSid:\n process.env[EnvironmentVariables.TWILIO_TAC_CI_SUMMARY_OPERATOR_SID],\n region: process.env[EnvironmentVariables.TWILIO_REGION],\n studioHandoffFlowSid: process.env[EnvironmentVariables.TWILIO_STUDIO_HANDOFF_FLOW_SID],\n };\n\n return new TACConfig(rawConfig);\n }\n\n /**\n * Path a call-event callback is served at.\n *\n * Single source of truth: the voice channel builds callback URLs from this\n * and TACServer registers routes at it, so the two can't drift.\n */\n public callEventPath(kind: CallEventKind): string {\n return `${this.voiceCallEventPath.replace(/\\/+$/, '')}/${kind}`;\n }\n\n /**\n * Public URL for a call-event callback, or `undefined` without a public domain.\n */\n public callEventUrl(kind: CallEventKind): string | undefined {\n if (!this.voicePublicDomain) {\n return undefined;\n }\n return `https://${this.voicePublicDomain}${this.callEventPath(kind)}`;\n }\n\n /**\n * Whether Conversation Orchestrator is configured.\n * Returns false in voice-only mode (no conversationConfigurationId).\n *\n * @internal\n */\n public isOrchestratorEnabled(): boolean {\n return this.conversationConfigurationId !== undefined;\n }\n\n /**\n * Get basic auth credentials for Twilio APIs\n */\n public getBasicAuthCredentials(): { username: string; password: string } {\n return {\n username: this.accountSid,\n password: this.authToken,\n };\n }\n}\n","function scrubPhoneMatch(match: string): string {\n const digits = match.replace(/[\\s\\-()]/g, '');\n if (digits.length < 8) return '***';\n return `${digits.slice(0, 2)}***${digits.slice(-4)}`;\n}\n\nfunction scrubEmailMatch(match: string): string {\n const atIndex = match.indexOf('@');\n if (atIndex <= 0) return '***';\n return `${match[0]}***${match.slice(atIndex)}`;\n}\n\nexport function scrubPii(value: string): string {\n // Fresh RegExp each call — avoids lastIndex state bugs from the g flag\n const phoneRe = /\\+\\d[\\d\\s()-]{6,}\\d/g;\n const emailRe = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;\n return value.replace(phoneRe, scrubPhoneMatch).replace(emailRe, scrubEmailMatch);\n}\n\nexport function scrubObject(obj: unknown, seen?: WeakSet<object>): unknown {\n if (typeof obj === 'string') return scrubPii(obj);\n if (obj === null || typeof obj !== 'object') return obj;\n\n const visited = seen ?? new WeakSet<object>();\n if (visited.has(obj)) return '[Circular]';\n visited.add(obj);\n\n if (obj instanceof Error) {\n const record = obj as unknown as Record<string, unknown>;\n const scrubbed = Object.create(Object.getPrototypeOf(obj) as object) as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n scrubbed[key] = scrubObject(record[key], visited);\n }\n const result = scrubbed as unknown as Error;\n if (!Object.prototype.hasOwnProperty.call(scrubbed, 'message')) {\n result.message = scrubPii(obj.message);\n }\n if (!Object.prototype.hasOwnProperty.call(scrubbed, 'name')) {\n result.name = obj.name;\n }\n if (obj.stack && !Object.prototype.hasOwnProperty.call(scrubbed, 'stack')) {\n result.stack = scrubPii(obj.stack);\n }\n return result;\n }\n\n if (Array.isArray(obj)) return obj.map(item => scrubObject(item, visited));\n\n // Only deep-scrub plain objects; leave class instances (Date, URL, Map, etc.) unchanged\n if (Object.getPrototypeOf(obj) !== Object.prototype) return obj;\n\n const record = obj as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(record)) {\n out[key] = scrubObject(record[key], visited);\n }\n return out;\n}\n\nexport function maskPhone(phone: string): string {\n if (!phone || !phone.startsWith('+') || phone.length < 8) {\n return '***';\n }\n return `${phone.slice(0, 2)}***${phone.slice(-4)}`;\n}\n\nexport function maskEmail(email: string): string {\n const atIndex = email.indexOf('@');\n if (atIndex <= 0) {\n return '***';\n }\n return `${email[0]}***${email.slice(atIndex)}`;\n}\n\nexport function maskAddress(address: string): string {\n if (!address) return '***';\n if (address.includes('@')) return maskEmail(address);\n if (address.startsWith('+')) return maskPhone(address);\n if (address.length <= 1) return '***';\n return `${address[0]}***`;\n}\n\n/**\n * Mask `<Parameter value=\"...\">` contents in TwiML, keeping the names.\n *\n * `<Parameter>` children carry whatever the developer put in\n * `customParameters` — profile IDs, caller names. Names stay because knowing\n * which parameters were sent is the point of logging the TwiML.\n *\n * Handles either quote style. TAC's own TwiML comes from the Twilio SDK, which\n * always double-quotes, but this takes a plain string and shouldn't depend on\n * that to stay safe.\n */\nexport function redactTwimlParameters(twiml: string | undefined | null): string {\n if (!twiml) return '';\n // Fresh RegExp each call — avoids lastIndex state bugs from the g flag.\n const parameterValueRe = /(<Parameter\\b[^>]*?\\bvalue=)([\"'])(.*?)\\2/gi;\n return twiml.replace(parameterValueRe, (_match, prefix: string, quote: string) => {\n return `${prefix}${quote}***${quote}`;\n });\n}\n","import pino from 'pino';\nimport { scrubObject } from '../util/log-redaction';\n\n/**\n * Logger type that can be either Pino logger or Fastify's logger\n */\nexport type Logger = pino.Logger;\n\nfunction piiLogMethod(this: pino.Logger, args: unknown[], method: pino.LogFn): void {\n const scrubbed = args.map(arg =>\n typeof arg === 'string'\n ? scrubObject(arg)\n : typeof arg === 'object' && arg !== null\n ? scrubObject(arg)\n : arg\n );\n return method.apply(this, scrubbed as Parameters<pino.LogFn>);\n}\n\nexport function createLogger(options?: { level?: string; name?: string }): Logger {\n const level = options?.level || process.env.TWILIO_LOG_LEVEL || 'info';\n\n return pino({\n level,\n ...(options?.name && { name: options.name }),\n hooks: { logMethod: piiLogMethod },\n });\n}\n","{\n \"name\": \"twilio-agent-connect\",\n \"version\": \"2.2.0\",\n \"description\": \"Twilio Agent Connect - A TypeScript framework for building intelligent agents\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"clean\": \"rimraf dist packages/*/dist\",\n \"test\": \"vitest --run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest --coverage\",\n \"lint\": \"eslint packages/*/src/**/*.ts src/**/*.ts\",\n \"lint:fix\": \"eslint packages/*/src/**/*.ts src/**/*.ts --fix\",\n \"format\": \"prettier --write packages/*/src/**/*.ts src/**/*.ts getting_started/**/*.ts\",\n \"format:check\": \"prettier --check packages/*/src/**/*.ts src/**/*.ts getting_started/**/*.ts\",\n \"typecheck\": \"tsc --noEmit\",\n \"docs\": \"typedoc\",\n \"docs:watch\": \"typedoc --watch\",\n \"example:getting-started\": \"cd getting_started/examples/openai && npm install && npm run dev\",\n \"example:chat\": \"cd getting_started/examples/chat && npm install && npm run dev\"\n },\n \"keywords\": [\n \"twilio\",\n \"ai\",\n \"agents\",\n \"framework\",\n \"typescript\"\n ],\n \"author\": \"Twilio\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/twilio/twilio-agent-connect-typescript.git\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.0.0\",\n \"@shipgirl/typedoc-plugin-versions\": \"^0.3.2\",\n \"@types/node\": \"^22.0.0\",\n \"@types/ws\": \"^8.18.1\",\n \"@vitest/coverage-v8\": \"^4.1.2\",\n \"axios-mock-adapter\": \"^2.1.0\",\n \"eslint\": \"^9.0.0\",\n \"globals\": \"^15.0.0\",\n \"prettier\": \"^3.0.0\",\n \"rimraf\": \"^5.0.0\",\n \"tsup\": \"^8.5.1\",\n \"typedoc\": \"^0.28.20\",\n \"typedoc-material-theme\": \"^1.4.1\",\n \"typescript\": \"^5.0.0\",\n \"typescript-eslint\": \"^8.0.0\",\n \"vitest\": \"^4.1.2\"\n },\n \"dependencies\": {\n \"@fastify/formbody\": \"^8.0.2\",\n \"@fastify/websocket\": \"^11.2.0\",\n \"axios\": \"^1.15.2\",\n \"axios-retry\": \"^4.5.0\",\n \"dotenv\": \"^16.4.7\",\n \"fastify\": \"^5.8.5\",\n \"fastify-graceful-shutdown\": \"^5.0.0\",\n \"pino\": \"^9.0.0\",\n \"twilio\": \"^5.10.7\",\n \"ws\": \"^8.19.0\",\n \"zod\": \"^4.0.0\"\n },\n \"peerDependencies\": {\n \"@openai/agents\": \"^0.8.0\"\n },\n \"peerDependenciesMeta\": {\n \"@openai/agents\": {\n \"optional\": true\n }\n },\n \"engines\": {\n \"node\": \">=22.13.0\",\n \"npm\": \">=9.0.0\"\n }\n}\n","import { Logger, createLogger } from '../lib/logger';\nimport { TACConfig } from '../lib/config';\nimport packageJson from '../../../../package.json' with { type: 'json' };\nimport axios, { AxiosInstance } from 'axios';\nimport axiosRetry from 'axios-retry';\n\nfunction buildUserAgent(): string {\n return `twilio-agent-connect-typescript/${packageJson.version}`;\n}\n\n/**\n * Base HTTP client for Twilio API services\n *\n * Features:\n * - Automatic Basic Auth using Twilio API credentials\n * - User-Agent header injection\n * - 30-second request timeout\n * - HTTP redirect following (up to 5 redirects) with auth preservation\n * - Automatic retry (up to 3 retries / 4 total attempts with exponential backoff)\n * - Error logging for failed requests\n * - Automatic JSON serialization/deserialization\n */\nexport abstract class BaseClient {\n protected readonly baseUrl: string;\n protected readonly logger: Logger;\n protected readonly axiosInstance: AxiosInstance;\n\n constructor(baseUrl: string, config: TACConfig, logger?: Logger) {\n this.baseUrl = baseUrl;\n this.logger = logger || createLogger({ name: this.constructor.name });\n\n // Create Authorization header for Basic Auth\n const authHeader =\n 'Basic ' + Buffer.from(`${config.apiKey}:${config.apiSecret}`).toString('base64');\n\n // Extract origin from baseUrl for same-origin check\n const baseOrigin = new URL(baseUrl).origin;\n\n this.axiosInstance = axios.create({\n baseURL: baseUrl,\n timeout: 30000,\n maxRedirects: 5,\n headers: {\n 'User-Agent': buildUserAgent(),\n Authorization: authHeader,\n },\n beforeRedirect: (options, _responseDetails) => {\n // Preserve auth header for same-origin redirects only (prevents credential leaks)\n const redirectUrl = new URL(\n String(options.path || ''),\n `${String(options.protocol)}//${String(options.host)}`\n );\n if (redirectUrl.origin === baseOrigin && options.headers) {\n (options.headers as Record<string, string>).Authorization = authHeader;\n }\n },\n });\n\n axiosRetry(this.axiosInstance, {\n retries: 3,\n retryDelay: retryCount => axiosRetry.exponentialDelay(retryCount),\n retryCondition: error => {\n // Retry network/no-response errors for any method, and retry 5xx/429 responses only for idempotent methods\n // (which helps prevent duplicate side effects on non-idempotent requests such as POST)\n return axiosRetry.isNetworkOrIdempotentRequestError(error);\n },\n });\n\n // Response interceptor for error logging\n this.axiosInstance.interceptors.response.use(\n response => response,\n error => {\n if (axios.isAxiosError(error)) {\n const status = error.response?.status;\n const logContext = {\n error: error.message,\n method: error.config?.method,\n url: error.config?.url,\n status,\n };\n // Log 4xx as warn (client errors, may be expected/handled)\n // Log 5xx/network as error (server/infrastructure failures)\n if (status !== undefined && status >= 400 && status < 500) {\n this.logger.warn(logContext, 'HTTP request client error');\n } else {\n this.logger.error(logContext, 'HTTP request error');\n }\n }\n throw error;\n }\n );\n }\n\n /**\n * Make an HTTP request with automatic header injection and error handling\n *\n * @param url - The URL path (relative to baseURL)\n * @param method - HTTP method (GET, POST, etc.)\n * @param data - Optional request body (will be automatically serialized to JSON)\n * @param params - Optional query string parameters\n * @returns Promise resolving to the response data (already parsed from JSON)\n * @throws Error on timeout, HTTP errors, or network failures\n */\n protected async makeRequest<TResponse = unknown>(\n url: string,\n method: string,\n data?: unknown,\n params?: Record<string, string>\n ): Promise<TResponse> {\n const response = await this.axiosInstance.request<TResponse>({\n url,\n method,\n data,\n params,\n });\n\n return response.data;\n }\n}\n","import { z } from 'zod';\nimport {\n MemoryRetrievalRequest,\n MemoryRetrievalRequestSchema,\n MemoryRetrievalResponse,\n EMPTY_MEMORY_RESPONSE,\n ObservationInfoSchema,\n SummaryInfoSchema,\n MemoryCommunicationSchema,\n ProfileLookupResponse,\n ProfileLookupResponseSchema,\n ProfileResponse,\n ProfileResponseSchema,\n ObservationCreateRequest,\n CreateObservationsRequest,\n CreateObservationResponse,\n CreateObservationResponseSchema,\n CreateConversationSummariesResponse,\n CreateConversationSummariesResponseSchema,\n} from '../types';\nimport { TACConfig } from '../lib/config';\nimport { Logger } from '../lib/logger';\nimport { BaseClient } from './base';\n\n/**\n * Memory client for interacting with Twilio Memory Service\n */\nexport class MemoryClient extends BaseClient {\n private readonly storeId: string;\n\n constructor(config: TACConfig, storeId: string, logger?: Logger) {\n const baseUrl = config.region\n ? `https://memory.${config.region}.twilio.com`\n : 'https://memory.twilio.com';\n super(baseUrl, config, logger);\n this.storeId = storeId;\n }\n\n /**\n * Get the store ID this client is configured for\n */\n public getStoreId(): string {\n return this.storeId;\n }\n\n /**\n * Retrieve memories for a specific profile\n *\n * @param profileId - The profile ID to retrieve memories for\n * @param request - Optional request parameters for filtering results\n * @returns Promise containing memory retrieval response\n */\n public async retrieveMemories(\n profileId: string,\n request: Partial<MemoryRetrievalRequest> = {}\n ): Promise<MemoryRetrievalResponse> {\n try {\n const url = `/v1/Stores/${this.storeId}/Profiles/${profileId}/Recall`;\n\n this.logger.debug(\n {\n memory_store_id: this.storeId,\n profile_id: profileId,\n request,\n },\n 'Retrieving memories'\n );\n\n // Validate and apply defaults through schema\n const validatedRequest = MemoryRetrievalRequestSchema.parse(request);\n\n // Serialize request to Memory API wire format (camelCase)\n const requestBody = {\n conversationId: validatedRequest.conversationId,\n query: validatedRequest.query,\n beginDate: validatedRequest.beginDate,\n endDate: validatedRequest.endDate,\n observationsLimit: validatedRequest.observationsLimit,\n summariesLimit: validatedRequest.summariesLimit,\n communicationsLimit: validatedRequest.communicationsLimit,\n relevanceThreshold: validatedRequest.relevanceThreshold,\n };\n\n // Remove undefined values\n const cleanedBody = Object.fromEntries(\n Object.entries(requestBody).filter(([_, value]) => value !== undefined)\n );\n\n const data = await this.makeRequest<MemoryRetrievalResponse>(url, 'POST', cleanedBody);\n\n this.logger.debug(\n {\n memory_store_id: this.storeId,\n profile_id: profileId,\n },\n 'Raw memory response received'\n );\n\n if (data === null || typeof data !== 'object') {\n this.logger.warn(\n {\n profile_id: profileId,\n memory_store_id: this.storeId,\n },\n 'Invalid memory response format'\n );\n return EMPTY_MEMORY_RESPONSE;\n }\n\n // Parse each item independently so a single malformed entry (e.g. an\n // unrecognized enum value) doesn't discard the entire response.\n const response = data as Record<string, unknown>;\n const observations = this.parseItems(\n response.observations,\n ObservationInfoSchema,\n 'observation',\n profileId\n );\n const summaries = this.parseItems(\n response.summaries,\n SummaryInfoSchema,\n 'summary',\n profileId\n );\n const communications = this.parseItems(\n response.communications,\n MemoryCommunicationSchema,\n 'communication',\n profileId\n );\n\n this.logger.debug(\n {\n memory_store_id: this.storeId,\n profile_id: profileId,\n observation_count: observations.length,\n summary_count: summaries.length,\n communication_count: communications.length,\n // Server-side query time; dominates /Recall when expansion runs.\n query_time_ms: (response.meta as { queryTime?: number } | undefined)?.queryTime,\n },\n 'Memory retrieval succeeded'\n );\n\n return { observations, summaries, communications };\n } catch (error) {\n this.logger.warn(\n {\n error: error instanceof Error ? error.message : String(error),\n profile_id: profileId,\n memory_store_id: this.storeId,\n },\n 'Memory retrieval error'\n );\n return EMPTY_MEMORY_RESPONSE;\n }\n }\n\n /** Cap on per-item validation warnings logged per response, to avoid flooding logs. */\n private static readonly MAX_INVALID_ITEM_LOGS = 10;\n\n /**\n * Validate an array of memory items one at a time, dropping (and logging)\n * any that fail validation while keeping the rest.\n *\n * Per-item warnings are capped at {@link MemoryClient.MAX_INVALID_ITEM_LOGS}\n * and followed by a single summary warning with the total `invalid_count`.\n */\n private parseItems<T>(\n value: unknown,\n schema: z.ZodType<T, unknown>,\n itemType: string,\n profileId: string\n ): T[] {\n if (value === undefined) {\n return [];\n }\n\n if (!Array.isArray(value)) {\n this.logger.warn(\n {\n profile_id: profileId,\n memory_store_id: this.storeId,\n item_type: itemType,\n received_type: typeof value,\n },\n 'Expected an array of memory items but received a non-array value'\n );\n return [];\n }\n\n const parsed: T[] = [];\n let invalidCount = 0;\n for (const [index, item] of value.entries()) {\n const result = schema.safeParse(item);\n if (result.success) {\n parsed.push(result.data);\n continue;\n }\n\n invalidCount += 1;\n if (invalidCount <= MemoryClient.MAX_INVALID_ITEM_LOGS) {\n this.logger.warn(\n {\n profile_id: profileId,\n memory_store_id: this.storeId,\n item_type: itemType,\n item_index: index,\n validation_errors: result.error.issues,\n },\n 'Dropping invalid memory item'\n );\n }\n }\n\n if (invalidCount > 0) {\n this.logger.warn(\n {\n profile_id: profileId,\n memory_store_id: this.storeId,\n item_type: itemType,\n invalid_count: invalidCount,\n total_count: value.length,\n },\n 'Dropped invalid memory items'\n );\n }\n\n return parsed;\n }\n\n /**\n * Find profiles that contain a specific identifier value\n *\n * @param idType - Identifier type (e.g., 'phone', 'email')\n * @param value - Raw value captured for the identifier\n * @returns Promise containing profile lookup response with normalized value and matching profile IDs\n */\n public async lookupProfile(idType: string, value: string): Promise<ProfileLookupResponse> {\n const url = `/v1/Stores/${this.storeId}/Profiles/Lookup`;\n\n const requestBody = {\n idType,\n value,\n };\n\n try {\n const data = await this.makeRequest<ProfileLookupResponse>(url, 'POST', requestBody);\n return ProfileLookupResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to lookup profile: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create a profile via identity resolution (upsert).\n *\n * Conversation Memory runs identity resolution on the submitted traits: if an identifier\n * match is found, the existing canonical profile ID is returned; otherwise a\n * new profile is minted. The body must contain at least one\n * trait-promoted-to-identifier per the store's identity resolution settings,\n * else resolution fails with 400.\n *\n * The write is queued (202 Accepted) — the canonical profile ID is returned\n * synchronously in the response body, but downstream traits may not be fully\n * persisted immediately.\n *\n * @param traits - Trait-group → field → value mapping (e.g. `{\"Contact\": {\"phone\": \"+13175551234\"}}`)\n * @returns Canonical profile ID (`mem_profile_…`)\n * @throws Error if the API request fails or the response is missing an `id` field\n */\n public async createProfile(traits: Record<string, Record<string, unknown>>): Promise<string> {\n const url = `/v1/Stores/${this.storeId}/Profiles`;\n const requestBody = { traits };\n\n let data: unknown;\n try {\n data = await this.makeRequest<unknown>(url, 'POST', requestBody);\n } catch (error) {\n throw new Error(\n `Failed to create profile: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n\n const profileId =\n data && typeof data === 'object' && 'id' in data ? (data as { id: unknown }).id : undefined;\n if (typeof profileId !== 'string') {\n throw new Error(`CreateProfile response missing 'id' field: ${JSON.stringify(data)}`);\n }\n return profileId;\n }\n\n /**\n * Fetch profile information with traits\n *\n * @param profileId - The profile ID to fetch\n * @param traitGroups - Optional list of trait group names to include\n * @returns Promise containing profile response with ID, created timestamp, and traits\n */\n public async getProfile(profileId: string, traitGroups?: string[]): Promise<ProfileResponse> {\n const url = `/v1/Stores/${this.storeId}/Profiles/${profileId}`;\n\n const params: Record<string, string> = {};\n if (traitGroups && traitGroups.length > 0) {\n params.traitGroups = traitGroups.join(',');\n }\n\n try {\n const data = await this.makeRequest<ProfileResponse>(\n url,\n 'GET',\n undefined,\n Object.keys(params).length > 0 ? params : undefined\n );\n return ProfileResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to get profile: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create an observation for a profile.\n *\n * The Memory API Observations endpoint is a batch create: the observation is\n * wrapped in an `observations` array and `occurredAt` is required, so it\n * defaults to the current time (ISO 8601) when omitted or blank.\n *\n * @param profileId - The profile ID to create the observation for\n * @param content - The observation content\n * @param source - Source of the observation (default: 'conversation-intelligence')\n * @param conversationIds - Optional array of conversation IDs associated with this observation\n * @param occurredAt - Timestamp when the observation occurred (ISO 8601); defaults to now when omitted or blank\n * @returns Promise containing the API confirmation message\n */\n public async createObservation(\n profileId: string,\n content: string,\n source: string = 'conversation-intelligence',\n conversationIds?: string[],\n occurredAt?: string\n ): Promise<CreateObservationResponse> {\n const url = `/v1/Stores/${this.storeId}/Profiles/${profileId}/Observations`;\n\n const observation: ObservationCreateRequest = {\n content,\n source,\n occurredAt: occurredAt && occurredAt.trim() ? occurredAt : new Date().toISOString(),\n };\n\n if (conversationIds && conversationIds.length > 0) {\n observation.conversationIds = conversationIds;\n }\n\n const requestBody: CreateObservationsRequest = { observations: [observation] };\n\n try {\n const data = await this.makeRequest<CreateObservationResponse>(url, 'POST', requestBody);\n return CreateObservationResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to create observation: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create conversation summaries for a profile\n *\n * @param profileId - The profile ID to create summaries for\n * @param summaries - Array of summary items to create\n * @returns Promise containing a success message for the created conversation summaries\n */\n public async createConversationSummaries(\n profileId: string,\n summaries: Array<{\n content: string;\n conversationId: string;\n occurredAt: string;\n source?: string;\n }>\n ): Promise<CreateConversationSummariesResponse> {\n const url = `/v1/Stores/${this.storeId}/Profiles/${profileId}/ConversationSummaries`;\n\n const requestBody = {\n summaries: summaries.map(s => ({\n content: s.content,\n conversationId: s.conversationId,\n occurredAt: s.occurredAt,\n source: s.source ?? 'conversation-intelligence',\n })),\n };\n\n try {\n const data = await this.makeRequest<CreateConversationSummariesResponse>(\n url,\n 'POST',\n requestBody\n );\n return CreateConversationSummariesResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to create conversation summaries: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n}\n","import {\n ActionResponse,\n ActionResponseSchema,\n Communication,\n ConversationResponse,\n ConversationResponseSchema,\n ConversationAddress,\n ConversationParticipant,\n ConversationParticipantSchema,\n SendMessageActionRequest,\n ConversationConfiguration,\n ConversationConfigurationSchema,\n ListCommunicationsResponse,\n ListCommunicationsResponseSchema,\n ListParticipantsResponse,\n ListParticipantsResponseSchema,\n ListConversationsResponse,\n ListConversationsResponseSchema,\n} from '../types';\nimport axios from 'axios';\nimport { TACConfig } from '../lib/config';\nimport { Logger } from '../lib/logger';\nimport { BaseClient } from './base';\n\n/**\n * Conversation client for interacting with Twilio Conversations Service\n */\nexport class ConversationClient extends BaseClient {\n private readonly conversationConfigurationId: string;\n\n constructor(config: TACConfig, logger?: Logger) {\n const baseUrl = config.region\n ? `https://conversations.${config.region}.twilio.com`\n : 'https://conversations.twilio.com';\n super(baseUrl, config, logger);\n if (!config.conversationConfigurationId) {\n throw new Error('conversationConfigurationId is required to create ConversationClient');\n }\n this.conversationConfigurationId = config.conversationConfigurationId;\n }\n\n /**\n * Create an action on a conversation via the Conversation Orchestrator Actions API.\n *\n * Currently supports SEND_MESSAGE actions. Returns 202 Accepted; the action is\n * processed asynchronously and delivered via COMMUNICATION_CREATED webhook.\n *\n * @param conversationId - The conversation ID\n * @param request - The action request ({type, payload})\n * @returns Promise containing the ActionResponse\n */\n public async createAction(\n conversationId: string,\n request: SendMessageActionRequest\n ): Promise<ActionResponse> {\n const url = `/v2/Conversations/${conversationId}/Actions`;\n\n try {\n const data = await this.makeRequest<ActionResponse>(url, 'POST', request);\n return ActionResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to create action: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * List communications for a conversation\n *\n * @param conversationId - The conversation ID\n * @returns Promise containing array of communications\n */\n public async listCommunications(conversationId: string): Promise<Communication[]> {\n const url = `/v2/Conversations/${conversationId}/Communications`;\n\n try {\n const data = await this.makeRequest<ListCommunicationsResponse>(url, 'GET');\n const validated = ListCommunicationsResponseSchema.parse(data);\n return validated.communications;\n } catch (error) {\n throw new Error(\n `Failed to list communications: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create a new conversation, optionally with inline participants.\n *\n * When participants are provided, CO creates them atomically with the\n * conversation. If an active conversation with the same participant\n * addresses already exists (respecting the configuration's group-by\n * rules), CO returns 409 with a pointer to the existing conversation.\n */\n public async createConversation(options?: {\n name?: string;\n participants?: Array<{\n type: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT';\n addresses: ConversationAddress[];\n }>;\n }): Promise<ConversationResponse> {\n const url = `/v2/Conversations`;\n\n const requestBody: Record<string, unknown> = {\n configurationId: this.conversationConfigurationId,\n };\n\n if (options?.name) {\n requestBody.name = options.name;\n }\n\n if (options?.participants) {\n requestBody.participants = options.participants;\n }\n\n try {\n const data = await this.makeRequest<ConversationResponse>(url, 'POST', requestBody);\n return ConversationResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to create conversation: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create a conversation with inline participants, reusing an existing active\n * conversation if CO returns 409 (group-by dedup).\n *\n * On 409 CO returns the existing conversation ID in the\n * X-Conflicting-Resource-Id response header.\n */\n public async createOrReuseConversation(\n participants: Array<{\n type: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT';\n addresses: ConversationAddress[];\n }>\n ): Promise<{ conversation: { id: string }; reused: boolean }> {\n try {\n const conversation = await this.createConversation({ participants });\n return { conversation, reused: false };\n } catch (error) {\n const existingId = this.extractConversationIdFrom409(error);\n if (existingId) {\n this.logger.info(\n { conversation_id: existingId },\n 'Reusing existing active conversation (409 dedup)'\n );\n return { conversation: { id: existingId }, reused: true };\n }\n throw error;\n }\n }\n\n /**\n * Extract conversation ID from a 409 response's X-Conflicting-Resource-Id header.\n */\n private extractConversationIdFrom409(error: unknown): string | null {\n // Unwrap: createConversation wraps the axios error in a generic Error\n const cause = error instanceof Error ? (error.cause ?? error) : error;\n if (!axios.isAxiosError(cause) || cause.response?.status !== 409) {\n return null;\n }\n\n const headers = cause.response.headers as Record<string, string> | undefined;\n const conflictId = headers?.['x-conflicting-resource-id'];\n return typeof conflictId === 'string' && conflictId.length > 0 ? conflictId : null;\n }\n\n /**\n * Add a participant to a conversation.\n *\n * @param conversationId - The conversation ID\n * @param addresses - Array of participant addresses\n * @param participantType - Type of participant (CUSTOMER, AI_AGENT, HUMAN_AGENT, AGENT)\n * @returns Promise containing participant response\n */\n public async addParticipant(\n conversationId: string,\n addresses: ConversationAddress[],\n participantType: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT' | 'AGENT'\n ): Promise<ConversationParticipant> {\n const url = `/v2/Conversations/${conversationId}/Participants`;\n\n const requestBody = {\n type: participantType,\n addresses,\n };\n\n try {\n const data = await this.makeRequest<ConversationParticipant>(url, 'POST', requestBody);\n return ConversationParticipantSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to add participant: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Replace an existing participant.\n *\n * PUT is a full resource replacement per the Conversation Orchestrator spec —\n * any field omitted from the body is cleared on the server. Callers must pass\n * the current `addresses` (and `name` if set) to preserve them.\n *\n * @param conversationId - Conversation ID containing the participant\n * @param participantId - Participant ID to update\n * @param participantType - New participant type\n * @param addresses - Current participant addresses (required to avoid wiping)\n * @param options.name - Current participant display name (optional)\n * @param options.profileId - Conversation Memory profile ID to attach (optional)\n * @returns Promise containing the updated participant\n */\n public async updateParticipant(\n conversationId: string,\n participantId: string,\n participantType: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT' | 'AGENT',\n addresses: ConversationAddress[],\n options?: { name?: string; profileId?: string }\n ): Promise<ConversationParticipant> {\n const url = `/v2/Conversations/${conversationId}/Participants/${participantId}`;\n\n const requestBody: Record<string, unknown> = {\n type: participantType,\n addresses,\n };\n if (options?.name !== undefined) {\n requestBody.name = options.name;\n }\n if (options?.profileId !== undefined) {\n requestBody.profileId = options.profileId;\n }\n\n try {\n const data = await this.makeRequest<ConversationParticipant>(url, 'PUT', requestBody);\n return ConversationParticipantSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to update participant: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * List participants in a conversation\n *\n * @param conversationId - The conversation ID\n * @returns Promise containing array of participants\n */\n public async listParticipants(conversationId: string): Promise<ConversationParticipant[]> {\n const url = `/v2/Conversations/${conversationId}/Participants`;\n\n try {\n const data = await this.makeRequest<ListParticipantsResponse>(url, 'GET');\n const validated = ListParticipantsResponseSchema.parse(data);\n return validated.participants;\n } catch (error) {\n throw new Error(\n `Failed to list participants: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * List conversations with optional filters\n *\n * @param filters - Optional filters (channelId, status)\n * @returns Promise containing array of conversations\n */\n public async listConversations(filters?: {\n channelId?: string;\n status?: string[];\n }): Promise<ConversationResponse[]> {\n const url = `/v2/Conversations`;\n\n const params: Record<string, string> = {};\n if (filters?.channelId) {\n params.channelId = filters.channelId;\n }\n if (filters?.status && filters.status.length > 0) {\n params.status = filters.status.join(',');\n }\n\n try {\n const data = await this.makeRequest<ListConversationsResponse>(\n url,\n 'GET',\n undefined,\n Object.keys(params).length > 0 ? params : undefined\n );\n const validated = ListConversationsResponseSchema.parse(data);\n return validated.conversations;\n } catch (error) {\n throw new Error(\n `Failed to list conversations: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Clear statusCallbacks on a conversation's instance configuration.\n *\n * This stops the conversation from sending webhook events to TAC,\n * which is needed during handoff so the receiving system can take over.\n *\n * @param conversationId - The conversation ID to update\n */\n public async clearStatusCallbacks(conversationId: string): Promise<void> {\n const url = `/v2/Conversations/${conversationId}`;\n\n try {\n await this.makeRequest<unknown>(url, 'PATCH', {\n configuration: { statusCallbacks: [] },\n });\n } catch (error) {\n throw new Error(\n `Failed to clear status callbacks: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Update conversation status\n *\n * @param conversationId - The conversation ID\n * @param status - New status (ACTIVE, INACTIVE, CLOSED)\n * @returns Promise containing updated conversation\n */\n public async updateConversation(\n conversationId: string,\n status: 'ACTIVE' | 'INACTIVE' | 'CLOSED'\n ): Promise<ConversationResponse> {\n const url = `/v2/Conversations/${conversationId}`;\n\n const requestBody = { status };\n\n try {\n const data = await this.makeRequest<ConversationResponse>(url, 'PUT', requestBody);\n return ConversationResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to update conversation: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Retrieve the details for a single configuration\n *\n * @param configurationId - The configuration ID to retrieve\n * @returns Promise containing configuration details\n */\n public async getConfiguration(configurationId: string): Promise<ConversationConfiguration> {\n const url = `/v2/ControlPlane/Configurations/${configurationId}`;\n\n try {\n const data = await this.makeRequest<ConversationConfiguration>(url, 'GET');\n return ConversationConfigurationSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to get configuration: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n}\n","import {\n KnowledgeBase,\n KnowledgeBaseSchema,\n KnowledgeChunkResult,\n KnowledgeSearchResponse,\n KnowledgeSearchResponseSchema,\n} from '../types';\nimport { TACConfig } from '../lib/config';\nimport { Logger } from '../lib/logger';\nimport { BaseClient } from './base';\n\n/**\n * Knowledge client for interacting with Twilio Knowledge Service\n */\nexport class KnowledgeClient extends BaseClient {\n constructor(config: TACConfig, logger?: Logger) {\n const baseUrl = config.region\n ? `https://knowledge.${config.region}.twilio.com`\n : 'https://knowledge.twilio.com';\n super(baseUrl, config, logger);\n }\n\n /**\n * Get knowledge base metadata\n *\n * @param knowledgeBaseId - The knowledge base ID (format: know_knowledgebase_*)\n * @returns Promise containing knowledge base metadata\n */\n public async getKnowledgeBase(knowledgeBaseId: string): Promise<KnowledgeBase> {\n const url = `/v2/ControlPlane/KnowledgeBases/${knowledgeBaseId}`;\n\n try {\n const data = await this.makeRequest<KnowledgeBase>(url, 'GET');\n return KnowledgeBaseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to get knowledge base: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Search knowledge base for relevant content\n *\n * @param knowledgeBaseId - The knowledge base ID (format: know_knowledgebase_*)\n * @param query - Search query (max 2048 characters)\n * @param topK - Maximum number of results to return (default: 5, max: 20)\n * @param knowledgeIds - Optional list of knowledge IDs to filter results\n * @returns Promise containing array of search result chunks\n */\n public async searchKnowledgeBase(\n knowledgeBaseId: string,\n query: string,\n topK: number = 5,\n knowledgeIds?: string[]\n ): Promise<KnowledgeChunkResult[]> {\n const url = `/v2/KnowledgeBases/${knowledgeBaseId}/Search`;\n\n const requestBody: Record<string, unknown> = {\n query,\n top: Math.min(Math.max(topK, 1), 20), // Clamp to 1-20\n };\n\n if (knowledgeIds && knowledgeIds.length > 0) {\n requestBody.knowledgeIds = knowledgeIds;\n }\n\n try {\n const data = await this.makeRequest<KnowledgeSearchResponse>(url, 'POST', requestBody);\n const validated = KnowledgeSearchResponseSchema.parse(data);\n return validated.chunks;\n } catch (error) {\n throw new Error(\n `Failed to search knowledge base: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n}\n","import {\n OperatorResultEvent,\n OperatorResultEventSchema,\n OperatorResult,\n OperatorProcessingResult,\n ConversationIntelligenceConfig,\n} from '../types/index';\nimport { MemoryClient } from '../clients/memory';\nimport { Logger, createLogger } from './logger';\n\n/**\n * Extract profile IDs from operator result execution details\n *\n * @param operatorResult - The operator result to extract profile IDs from\n * @returns Array of profile IDs found in participants\n */\nfunction extractProfileIds(operatorResult: OperatorResult): string[] {\n const profileIds: string[] = [];\n\n if (operatorResult.executionDetails?.participants) {\n for (const participant of operatorResult.executionDetails.participants) {\n if (participant.profileId) {\n profileIds.push(participant.profileId);\n }\n }\n }\n\n return profileIds;\n}\n\n/**\n * Generate content string from operator result\n *\n * @param operatorResult - The operator result to generate content from\n * @returns Content string or undefined if result is empty\n */\nfunction generateContent(operatorResult: OperatorResult): string | undefined {\n const result = operatorResult.result;\n\n if (result === null || result === undefined) {\n return undefined;\n }\n\n if (typeof result === 'string') {\n return result.trim() || undefined;\n }\n\n // For objects/arrays, stringify them\n const jsonString = JSON.stringify(result);\n return jsonString === '{}' || jsonString === '[]' ? undefined : jsonString;\n}\n\n/**\n * Parse summaries content from JSON result\n *\n * Expects format: { \"summaries\": [\"summary1\", \"summary2\", ...] }\n *\n * @param jsonContent - JSON string to parse\n * @returns Array of summary strings\n */\nfunction parseSummariesContent(jsonContent: string): string[] {\n try {\n const parsed = JSON.parse(jsonContent) as unknown;\n\n if (typeof parsed === 'object' && parsed !== null && 'summaries' in parsed) {\n const summaries = (parsed as { summaries: unknown }).summaries;\n if (Array.isArray(summaries)) {\n return summaries.filter((s): s is string => typeof s === 'string' && s.trim() !== '');\n }\n }\n\n return [];\n } catch {\n return [];\n }\n}\n\n/**\n * Processor for Conversation Intelligence operator result webhooks\n *\n * Processes operator results from CI and creates conversation summaries in the\n * Memory service based on the operator configuration.\n */\nexport class OperatorResultProcessor {\n private readonly memoryClient: MemoryClient;\n private readonly config: ConversationIntelligenceConfig;\n private readonly logger: Logger;\n\n constructor(memoryClient: MemoryClient, config: ConversationIntelligenceConfig, logger?: Logger) {\n this.memoryClient = memoryClient;\n this.config = config;\n this.logger = logger ?? createLogger({ name: 'cintel-processor' });\n }\n\n /**\n * Process an operator result event webhook payload\n *\n * @param payload - The raw webhook payload\n * @returns Processing result indicating success/failure and details\n */\n public async processEvent(payload: unknown): Promise<OperatorProcessingResult> {\n // Validate the payload\n const parseResult = OperatorResultEventSchema.safeParse(payload);\n\n if (!parseResult.success) {\n this.logger.warn(\n { validation_errors: parseResult.error.issues },\n 'Invalid operator result event payload'\n );\n return {\n success: false,\n skipped: false,\n error: `Invalid payload: ${parseResult.error.message}`,\n createdCount: 0,\n };\n }\n\n const event = parseResult.data;\n\n // Check if this event is from the configured CI configuration\n if (event.intelligenceConfiguration.id !== this.config.configurationId) {\n this.logger.debug(\n {\n received_config_id: event.intelligenceConfiguration.id,\n expected_config_id: this.config.configurationId,\n },\n 'Skipping event from different CI configuration'\n );\n return {\n success: true,\n skipped: true,\n skipReason: `Event from different CI configuration: ${event.intelligenceConfiguration.id}`,\n createdCount: 0,\n };\n }\n\n // Check for memory store ID and verify it matches the client's store ID\n if (!event.memoryStoreId) {\n this.logger.warn({ conversation_id: event.conversationId }, 'No memory store ID in event');\n return {\n success: false,\n skipped: false,\n error: 'No memory store ID provided in event',\n createdCount: 0,\n };\n }\n\n const clientStoreId = this.memoryClient.getStoreId();\n if (event.memoryStoreId !== clientStoreId) {\n this.logger.debug(\n {\n conversation_id: event.conversationId,\n event_store_id: event.memoryStoreId,\n client_store_id: clientStoreId,\n },\n 'Skipping event from different memory store'\n );\n return {\n success: true,\n skipped: true,\n skipReason: `Event from different memory store: ${event.memoryStoreId} (expected ${clientStoreId})`,\n createdCount: 0,\n };\n }\n\n // Process each operator result\n const results: OperatorProcessingResult[] = [];\n\n for (const operatorResult of event.operatorResults) {\n const result = await this.processOperatorResult(event, operatorResult);\n results.push(result);\n }\n\n // Aggregate results\n const successCount = results.filter(r => r.success && !r.skipped).length;\n const skippedCount = results.filter(r => r.skipped).length;\n const errorCount = results.filter(r => !r.success).length;\n const totalCreated = results.reduce((sum, r) => sum + r.createdCount, 0);\n\n // Determine overall event type\n const eventTypes = results\n .filter(r => r.success && !r.skipped && r.eventType)\n .map(r => r.eventType);\n const uniqueEventTypes = [...new Set(eventTypes)];\n const eventType =\n uniqueEventTypes.length === 1\n ? uniqueEventTypes[0]\n : uniqueEventTypes.length > 1\n ? 'mixed'\n : undefined;\n\n if (errorCount > 0) {\n const errors = results.filter(r => !r.success).map(r => r.error);\n return {\n success: false,\n eventType,\n skipped: false,\n error: `${errorCount} operator(s) failed: ${errors.join('; ')}`,\n createdCount: totalCreated,\n };\n }\n\n if (skippedCount === results.length) {\n return {\n success: true,\n skipped: true,\n skipReason: 'All operator results were skipped',\n createdCount: 0,\n };\n }\n\n this.logger.info(\n {\n conversation_id: event.conversationId,\n success_count: successCount,\n skipped_count: skippedCount,\n created_count: totalCreated,\n event_type: eventType,\n },\n 'Processed operator result event'\n );\n\n return {\n success: true,\n eventType,\n skipped: false,\n createdCount: totalCreated,\n };\n }\n\n /**\n * Process an individual operator result\n */\n private async processOperatorResult(\n event: OperatorResultEvent,\n operatorResult: OperatorResult\n ): Promise<OperatorProcessingResult> {\n const operatorSid = operatorResult.operator.id;\n\n // Check if this is a configured operator\n const isSummaryOperator = this.config.summaryOperatorSid === operatorSid;\n\n if (!isSummaryOperator) {\n this.logger.debug(\n {\n operator_sid: operatorSid,\n summary_operator_sid: this.config.summaryOperatorSid,\n },\n 'Skipping unconfigured operator'\n );\n return {\n success: true,\n skipped: true,\n skipReason: `Operator ${operatorSid} is not configured for processing`,\n createdCount: 0,\n };\n }\n\n // Generate content from operator result\n const content = generateContent(operatorResult);\n\n if (!content) {\n this.logger.debug(\n { operator_sid: operatorSid },\n 'Skipping operator result with empty content'\n );\n return {\n success: true,\n skipped: true,\n skipReason: 'Operator result has empty content',\n createdCount: 0,\n };\n }\n\n // Extract profile IDs from execution details\n const profileIds = extractProfileIds(operatorResult);\n\n if (profileIds.length === 0) {\n this.logger.warn(\n { operator_sid: operatorSid, conversation_id: event.conversationId },\n 'No profile IDs found in operator result'\n );\n return {\n success: true,\n skipped: true,\n skipReason: 'No profile IDs found in operator result execution details',\n createdCount: 0,\n };\n }\n\n return this.processSummaryEvent(event, operatorResult, content, profileIds);\n }\n\n /**\n * Process a summary operator result\n */\n private async processSummaryEvent(\n event: OperatorResultEvent,\n operatorResult: OperatorResult,\n content: string,\n profileIds: string[]\n ): Promise<OperatorProcessingResult> {\n // Parse summaries from JSON content\n const summaries = parseSummariesContent(content);\n\n if (summaries.length === 0) {\n this.logger.debug(\n { operator_sid: operatorResult.operator.id },\n 'No summaries found in content'\n );\n return {\n success: true,\n eventType: 'summary',\n skipped: true,\n skipReason: 'No summaries found in operator result content',\n createdCount: 0,\n };\n }\n\n let createdCount = 0;\n\n // Create summaries for each profile\n for (const profileId of profileIds) {\n try {\n const summaryItems = summaries.map(summaryContent => ({\n content: summaryContent,\n conversationId: event.conversationId,\n occurredAt: operatorResult.dateCreated,\n source: 'conversation-intelligence',\n }));\n\n await this.memoryClient.createConversationSummaries(profileId, summaryItems);\n createdCount += summaries.length;\n\n this.logger.debug(\n {\n profile_id: profileId,\n conversation_id: event.conversationId,\n summary_count: summaries.length,\n },\n 'Created conversation summaries'\n );\n } catch (error) {\n this.logger.error(\n {\n err: error,\n profile_id: profileId,\n conversation_id: event.conversationId,\n },\n 'Failed to create conversation summaries'\n );\n return {\n success: false,\n eventType: 'summary',\n skipped: false,\n error: `Failed to create summaries: ${error instanceof Error ? error.message : String(error)}`,\n createdCount,\n };\n }\n }\n\n return {\n success: true,\n eventType: 'summary',\n skipped: false,\n createdCount,\n };\n }\n}\n","import {\n TACConfigData,\n ConversationSession,\n ConversationId,\n ProfileId,\n ProfileResponse,\n ChannelType,\n OperatorProcessingResult,\n} from '../types';\nimport { TACMemoryResponse } from './tac-memory-response';\nimport { TACConfig } from './config';\nimport { MemoryClient } from '../clients/memory';\nimport { ConversationClient } from '../clients/conversation';\nimport { KnowledgeClient } from '../clients/knowledge';\nimport { BaseChannel } from '../channels/base';\nimport { Logger, createLogger } from './logger';\nimport { maskAddress } from '../util/log-redaction';\nimport { OperatorResultProcessor } from './operator-result-processor';\n\nexport interface TACOptions {\n config?: TACConfig | TACConfigData;\n logger?: Logger;\n}\n\n/**\n * Callback function signatures for TAC events\n */\nexport type MessageReadyCallback = (params: {\n conversationId: ConversationId;\n profileId: ProfileId | undefined;\n message: string;\n author: string;\n memory: TACMemoryResponse | undefined;\n session: ConversationSession;\n channel: ChannelType;\n abortSignal?: AbortSignal;\n}) => Promise<string | null | void> | string | null | void;\n\nexport type InterruptCallback = (params: {\n conversationId: ConversationId;\n utteranceUntilInterrupt: string | undefined;\n durationUntilInterruptMs: number | undefined;\n session: ConversationSession;\n}) => Promise<void> | void;\n\nexport type ConversationEndedCallback = (params: {\n session: ConversationSession;\n}) => Promise<void> | void;\n\n/**\n * Main Twilio Agent Connect class\n *\n * Central orchestrator that manages configuration, channels (SMS, WhatsApp, Chat, Voice),\n * callbacks, and coordinates between memory, conversations, and LLM integrations.\n */\nexport class TAC {\n private static readonly FACTORY_TOKEN = Symbol('TAC.create');\n\n private readonly config: TACConfig;\n public readonly logger: Logger;\n private memoryClient: MemoryClient | null = null;\n private knowledgeClient: KnowledgeClient | null = null;\n private conversationClient: ConversationClient | null = null;\n private readonly channels: Map<ChannelType, BaseChannel>;\n private cintelProcessor?: OperatorResultProcessor;\n\n private memoryStoreId: string | undefined;\n\n // Callback registrations\n private messageReadyCallback?: MessageReadyCallback;\n private interruptCallback?: InterruptCallback;\n private conversationEndedCallback?: ConversationEndedCallback;\n\n private constructor(token: symbol, options: TACOptions = {}) {\n if (token !== TAC.FACTORY_TOKEN) {\n throw new Error('TAC constructor is private. Use TAC.create() instead of new TAC().');\n }\n // Handle config resolution:\n // - If it's already a TACConfig instance, use it\n // - If it's data, create a new TACConfig\n // - If not provided, load from environment variables\n const finalConfig = options.config\n ? options.config instanceof TACConfig\n ? options.config\n : new TACConfig(options.config)\n : TACConfig.fromEnv();\n const finalLogger = options.logger ?? createLogger({ name: 'tac' });\n\n this.config = finalConfig;\n this.logger = finalLogger;\n this.channels = new Map();\n }\n\n public static async create(options: TACOptions = {}): Promise<TAC> {\n const tac = new TAC(TAC.FACTORY_TOKEN, options);\n\n if (!tac.config.isOrchestratorEnabled()) {\n tac.logger.info(\n 'Voice-only mode: conversationConfigurationId not set, skipping Conversation Orchestrator initialization'\n );\n return tac;\n }\n\n try {\n tac.conversationClient = new ConversationClient(\n tac.config,\n tac.logger.child({ component: 'conversation' })\n );\n\n // Safe: we already returned early if !isOrchestratorEnabled(), so conversationConfigurationId is defined\n const conversationConfig = await tac.conversationClient.getConfiguration(\n tac.config.conversationConfigurationId!\n );\n\n tac.memoryStoreId = conversationConfig.memoryStoreId;\n tac.memoryClient = new MemoryClient(\n tac.config,\n conversationConfig.memoryStoreId,\n tac.logger.child({ component: 'memory' })\n );\n\n tac.knowledgeClient = new KnowledgeClient(\n tac.config,\n tac.logger.child({ component: 'knowledge' })\n );\n\n if (tac.config.cintelConfigurationId) {\n tac.cintelProcessor = new OperatorResultProcessor(\n tac.memoryClient,\n {\n configurationId: tac.config.cintelConfigurationId,\n summaryOperatorSid: tac.config.cintelSummaryOperatorSid,\n },\n tac.logger.child({ component: 'cintel' })\n );\n }\n\n return tac;\n } catch (error) {\n tac.logger.error({ err: error }, 'TAC initialization failed');\n throw error;\n }\n }\n\n /**\n * Register a channel with the framework\n */\n public registerChannel(channel: BaseChannel): void {\n this.logger.info({ channel: channel.channelType }, 'Registering channel');\n\n // Remove existing channel of same type\n const existingChannel = this.channels.get(channel.channelType);\n if (existingChannel) {\n this.logger.info({ channel: channel.channelType }, 'Replacing existing channel registration');\n existingChannel.shutdown();\n }\n\n this.channels.set(channel.channelType, channel);\n\n // Set up channel event listeners\n this.setupChannelEventListeners(channel);\n\n this.logger.info({ channel: channel.channelType }, 'Channel registration complete');\n }\n\n /**\n * Set up event listeners for a channel\n */\n private setupChannelEventListeners(channel: BaseChannel): void {\n // Handle channel errors directly\n channel.on(\n 'error',\n ({ error, context }: { error: Error; context?: Record<string, unknown> }) => {\n this.logger.error({ err: error, ...context }, 'Channel error');\n }\n );\n\n // Handle message received events for SMS channels\n channel.on(\n 'messageReceived',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises -- Intentionally async callback\n async (data: {\n conversationId: ConversationId;\n profileId: ProfileId | undefined;\n message: string;\n author: string;\n userMemory: TACMemoryResponse | undefined;\n }): Promise<void> => {\n await this.handleMessageReady({ ...data, channelType: channel.channelType });\n }\n );\n\n // Handle voice prompt events\n channel.on(\n 'prompt',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises -- Intentionally async callback\n async ({\n conversationId,\n transcript,\n userMemory,\n session,\n abortSignal,\n }: {\n conversationId: ConversationId;\n transcript: string;\n userMemory?: TACMemoryResponse;\n session?: ConversationSession;\n abortSignal: AbortSignal;\n }): Promise<void> => {\n // Use session from event if available, otherwise get from channel\n const eventSession = session || channel.getConversationSession(conversationId);\n if (eventSession) {\n await this.handleMessageReady({\n conversationId,\n profileId: eventSession.profileId ? (eventSession.profileId as ProfileId) : undefined,\n message: transcript,\n author: 'user',\n userMemory,\n channelType: channel.channelType,\n abortSignal,\n });\n }\n }\n );\n\n // Handle voice interrupt events\n channel.on(\n 'interrupt',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises -- Intentionally async event handler\n async ({\n conversationId,\n utteranceUntilInterrupt,\n durationUntilInterruptMs,\n }: {\n conversationId: ConversationId;\n utteranceUntilInterrupt: string | undefined;\n durationUntilInterruptMs: number | undefined;\n }) => {\n const session = channel.getConversationSession(conversationId);\n if (session && this.interruptCallback) {\n try {\n await this.interruptCallback({\n conversationId,\n utteranceUntilInterrupt,\n durationUntilInterruptMs,\n session,\n });\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: conversationId },\n 'Interrupt callback error'\n );\n }\n }\n }\n );\n\n // Handle conversation ended events\n channel.on(\n 'conversationEnded',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises -- Intentionally async event handler\n async ({ session }: { session: ConversationSession }) => {\n if (this.conversationEndedCallback) {\n try {\n await this.conversationEndedCallback({ session });\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: session.conversationId },\n 'Conversation ended callback error'\n );\n }\n }\n }\n );\n }\n\n /**\n * Handle message ready event from channels\n */\n private async handleMessageReady(data: {\n conversationId: ConversationId;\n profileId: ProfileId | undefined;\n message: string;\n author: string;\n userMemory: TACMemoryResponse | undefined;\n channelType: ChannelType;\n abortSignal?: AbortSignal;\n }): Promise<void> {\n this.logger.debug(\n {\n conversation_id: data.conversationId,\n profile_id: data.profileId,\n author: maskAddress(data.author),\n message_length: data.message.length,\n channel: data.channelType,\n operation: 'handle_message_ready',\n },\n 'Handling message ready'\n );\n\n if (!this.messageReadyCallback) {\n this.logger.warn('No message ready callback registered');\n return;\n }\n\n try {\n // Use the channel type passed from the event handler, not lookup by conversation ID\n // This ensures voice prompts use voice channel even if SMS also has this conversation\n const channel = this.channels.get(data.channelType);\n if (!channel) {\n throw new Error(`No channel found for type ${data.channelType}`);\n }\n\n this.logger.debug(\n { conversation_id: data.conversationId, channel: channel.channelType },\n 'Using channel for message'\n );\n\n const session = channel.getConversationSession(data.conversationId);\n if (!session) {\n throw new Error(`No session found for conversation ${data.conversationId}`);\n }\n\n // Memory is now fetched by channels based on their memoryMode configuration\n const memory = data.userMemory;\n\n // Execute callback\n this.logger.debug(\n { conversation_id: data.conversationId },\n 'Executing message ready callback'\n );\n try {\n const response = await this.messageReadyCallback({\n conversationId: data.conversationId,\n profileId: data.profileId,\n message: data.message,\n author: data.author,\n memory: memory ?? undefined,\n session,\n channel: channel.channelType,\n ...(data.abortSignal !== undefined && { abortSignal: data.abortSignal }),\n });\n this.logger.debug(\n { conversation_id: data.conversationId },\n 'Message ready callback completed'\n );\n\n // Auto-send if callback returned a string\n if (typeof response === 'string') {\n if (response === '') {\n this.logger.warn(\n { conversation_id: data.conversationId },\n 'Callback returned empty string, skipping auto-send'\n );\n } else {\n try {\n await channel.sendResponse(data.conversationId, response);\n } catch (sendError) {\n this.logger.error(\n { err: sendError, conversation_id: data.conversationId },\n 'Failed to auto-send callback response'\n );\n }\n }\n }\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: data.conversationId },\n 'Message ready callback error'\n );\n }\n\n this.logger.debug({ conversation_id: data.conversationId }, 'Message handling completed');\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: data.conversationId },\n 'Message handling error'\n );\n }\n }\n\n /**\n * Register callback for when messages are ready to be processed.\n * Return a string to auto-send, or null/void for manual handling.\n */\n public onMessageReady(callback: MessageReadyCallback): void {\n this.messageReadyCallback = callback;\n }\n\n /**\n * Register callback for when user interrupts (voice channel)\n */\n public onInterrupt(callback: InterruptCallback): void {\n this.interruptCallback = callback;\n }\n\n /**\n * Register callback for when a conversation ends.\n *\n * The callback is triggered by channels when a conversation is closed\n * (e.g., SMS conversation status changed to CLOSED, or voice WebSocket\n * disconnected). The callback receives the full ConversationSession before\n * it is cleaned up.\n */\n public onConversationEnded(callback: ConversationEndedCallback): void {\n this.conversationEndedCallback = callback;\n }\n\n /**\n * Whether Conversation Orchestrator is configured.\n * Returns false in voice-only mode.\n *\n * @internal\n */\n public isOrchestratorEnabled(): boolean {\n return this.config.isOrchestratorEnabled();\n }\n\n /**\n * Get registered channel by type\n */\n public getChannel<T extends BaseChannel>(channelType: ChannelType): T | undefined {\n return this.channels.get(channelType) as T | undefined;\n }\n\n /**\n * Get configuration\n */\n public getConfig(): TACConfig {\n return this.config;\n }\n\n /**\n * Get memory client for advanced memory operations.\n * Returns null in voice-only mode.\n */\n public getMemoryClient(): MemoryClient | null {\n return this.memoryClient;\n }\n\n /**\n * Get the memory store ID resolved from the ConversationConfiguration at startup.\n * Returns undefined in voice-only mode.\n */\n public getMemoryStoreId(): string | undefined {\n return this.memoryStoreId;\n }\n\n /**\n * Get knowledge client for knowledge base operations.\n * Returns null in voice-only mode.\n */\n public getKnowledgeClient(): KnowledgeClient | null {\n return this.knowledgeClient;\n }\n\n /**\n * Get conversation client for advanced conversation operations.\n * Returns null in voice-only mode.\n */\n public getConversationClient(): ConversationClient | null {\n return this.conversationClient;\n }\n\n /**\n * Check if Conversation Intelligence processing is enabled\n *\n * @returns true if CI processor is initialized, false otherwise\n */\n public isCintelEnabled(): boolean {\n return this.cintelProcessor !== undefined;\n }\n\n /**\n * Process a Conversation Intelligence operator result webhook event\n *\n * @param payload - The raw webhook payload from CI\n * @returns Promise containing the processing result\n * @throws Error if CI processor is not initialized\n */\n public async processCintelEvent(payload: unknown): Promise<OperatorProcessingResult> {\n if (!this.cintelProcessor) {\n throw new Error(\n 'Conversation Intelligence processor is not initialized. ' +\n 'Ensure cintelConfigurationId is provided in TAC configuration.'\n );\n }\n return this.cintelProcessor.processEvent(payload);\n }\n\n /**\n * Retrieve memories from Memory API with automatic fallback to Conversations API\n *\n * @param session - Conversation session context\n * @param query - Optional semantic search query\n * @param conversationId - Passed through to `/Recall` as-is. Sending one\n * without a `query` makes Memory infer one from that conversation's history\n * — an expensive server-side step — so leave it unset when there is no\n * per-turn topic (e.g. `\"once\"` mode's cache-priming fetch).\n * @returns Promise containing TACMemoryResponse wrapper providing unified access to memory data.\n *\n * Attempts to retrieve from Memory API first:\n * - observations, summaries, and communications available\n * - communications include author name and type\n *\n * Falls back to Conversations API on error:\n * - observations and summaries are empty arrays\n * - communications have basic fields only (no author name/type)\n */\n public async retrieveMemory(\n session: ConversationSession,\n query?: string,\n conversationId?: string\n ): Promise<TACMemoryResponse> {\n if (!this.isOrchestratorEnabled()) {\n return new TACMemoryResponse([]);\n }\n\n try {\n // If profileId is missing, try to lookup profile using address\n if (!session.profileId) {\n // Check if authorInfo and address are available\n if (!session.authorInfo || !session.authorInfo.address) {\n throw new Error(\n 'profileId is required for memory retrieval but was not found in ' +\n 'conversation context. Additionally, authorInfo.address is not available ' +\n 'for profile lookup. Ensure either profileId or authorInfo.address is ' +\n 'provided when creating the ConversationSession.'\n );\n }\n\n // Determine identity type based on address format\n // Email addresses contain '@', phone numbers start with '+'\n const address = session.authorInfo.address;\n let identityType: 'email' | 'phone';\n if (address.includes('@')) {\n identityType = 'email';\n } else if (address.startsWith('+')) {\n identityType = 'phone';\n } else {\n throw new Error(\n `Unsupported authorInfo.address format '${maskAddress(address)}'. ` +\n \"Expected an email address containing '@' or a phone number starting with '+'.\"\n );\n }\n this.logger.debug(\n { identityType, address: maskAddress(address), channel: session.channel },\n 'profileId not found, attempting to lookup profile'\n );\n\n if (!this.memoryClient) {\n throw new Error('Memory client is not available');\n }\n\n // Lookup profile using appropriate identity type\n const lookupResponse = await this.memoryClient.lookupProfile(\n identityType,\n session.authorInfo.address\n );\n\n // Check if any profiles were found\n if (!lookupResponse.profiles || lookupResponse.profiles.length === 0) {\n throw new Error(\n `No profile found for ${identityType} ${maskAddress(session.authorInfo.address)}. ` +\n 'Profile lookup returned no results. Ensure the identity ' +\n 'is registered in the identity resolution system.'\n );\n }\n\n // Use the first profile ID\n session.profileId = lookupResponse.profiles[0];\n }\n\n if (!session.profileId) {\n throw new Error('Profile ID is required but was not resolved');\n }\n\n if (!this.memoryClient) {\n throw new Error('Memory client is not available');\n }\n\n const memoryResponse = await this.memoryClient.retrieveMemories(session.profileId, {\n conversationId,\n query,\n observationsLimit: this.config.memoryConfig.observationsLimit,\n summariesLimit: this.config.memoryConfig.summariesLimit,\n communicationsLimit: this.config.memoryConfig.communicationsLimit,\n relevanceThreshold: this.config.memoryConfig.relevanceThreshold,\n });\n return new TACMemoryResponse(memoryResponse);\n } catch (error) {\n this.logger.warn(\n { err: error },\n 'Failed to retrieve memory from Memory API, falling back to Conversations API'\n );\n\n try {\n if (!this.conversationClient) {\n throw new Error('Conversation client is not available');\n }\n const communications = await this.conversationClient.listCommunications(\n session.conversationId\n );\n\n return new TACMemoryResponse(communications);\n } catch (fallbackError) {\n this.logger.error({ err: fallbackError }, 'Failed to retrieve communications');\n throw fallbackError;\n }\n }\n }\n\n /**\n * Fetch profile information with traits\n *\n * @param profileId - Profile ID to fetch\n * @returns Promise containing profile response or undefined if not available\n */\n public async fetchProfile(profileId: string): Promise<ProfileResponse | undefined> {\n if (!profileId) {\n this.logger.warn('profile_id is required for profile fetching but was not provided');\n return undefined;\n }\n\n if (!this.memoryClient) {\n this.logger.warn('Memory client is not available (voice-only mode)');\n return undefined;\n }\n\n try {\n const traitGroups = this.config.memoryConfig.traitGroups;\n const profileResponse = await this.memoryClient.getProfile(profileId, traitGroups);\n return profileResponse;\n } catch (error) {\n this.logger.error({ err: error }, `Failed to fetch profile for ${profileId}`);\n return undefined;\n }\n }\n\n /**\n * Shutdown TAC and cleanup resources\n */\n public shutdown(): void {\n for (const channel of this.channels.values()) {\n this.logger.debug({ channel: channel.channelType }, 'Shutting down channel');\n channel.shutdown();\n }\n\n this.channels.clear();\n this.logger.info('TAC shutdown complete');\n }\n}\n","import {\n ConversationSession,\n ChannelType,\n ConversationId,\n ConversationWebhookPayload,\n ProfileId,\n MemoryMode,\n MemoryModeSchema,\n isConversationId,\n isProfileId,\n} from '../types/index';\nimport { TACConfig } from '../lib/config';\nimport { ConversationClient } from '../clients/conversation';\nimport { Logger } from '../lib/logger';\nimport type { TAC } from '../lib/tac';\nimport { TACMemoryResponse } from '../lib/tac-memory-response';\n\n/**\n * Base channel event callbacks\n */\nexport interface BaseChannelEvents {\n onConversationStarted?: (data: { session: ConversationSession }) => void;\n onConversationEnded?: (data: { session: ConversationSession }) => Promise<void> | void;\n onError?: (data: { error: Error; context?: Record<string, unknown> }) => void;\n}\n\n/**\n * Base channel options\n */\nexport interface BaseChannelOptions {\n /**\n * Memory retrieval mode for this channel. Default is \"never\".\n *\n * - \"never\": Memory is not automatically retrieved. Use the memory TAC tool or manually call `tac.retrieveMemory()` in callbacks for conditional retrieval.\n * - \"always\": Memory is automatically retrieved (using the message as query) for every inbound message and available in `onMessageReady` callback.\n * - \"once\": Memory is retrieved once at conversation start with no query (and no conversation id) and cached on the session. Subsequent messages reuse the cache until the conversation becomes INACTIVE.\n */\n memoryMode?: MemoryMode;\n\n /**\n * Maximum number of idempotency tokens to track for webhook deduplication.\n * Default is 10000. Must be a positive integer.\n */\n dedupCapacity?: number;\n}\n\n/**\n * Abstract base class for all channel implementations\n *\n * Provides common functionality for:\n * - Conversation lifecycle management and session tracking\n * - Webhook deduplication using Twilio idempotency tokens\n * - Event filtering to prevent cross-channel fanout\n * - Memory retrieval integration\n * - Error handling and logging\n *\n * Subclasses must implement channel-specific webhook processing and message sending.\n */\nexport abstract class BaseChannel {\n protected readonly tac: TAC;\n protected readonly config: TACConfig;\n protected readonly logger: Logger;\n protected readonly conversationClient: ConversationClient | null;\n protected readonly activeConversations: Map<ConversationId, ConversationSession>;\n protected readonly callbacks: BaseChannelEvents;\n protected readonly memoryMode: MemoryMode;\n private readonly processedWebhookTokens: Set<string>;\n private readonly maxTrackedTokens: number;\n\n constructor(tac: TAC, options?: BaseChannelOptions) {\n this.tac = tac;\n this.config = tac.getConfig();\n this.logger = tac.logger.child({ component: 'channel' });\n this.conversationClient = tac.getConversationClient();\n this.activeConversations = new Map();\n this.callbacks = {};\n\n // Validate memoryMode with runtime check for JS consumers\n const providedMode = options?.memoryMode;\n const modeToValidate = providedMode === undefined ? 'never' : providedMode;\n const parseResult = MemoryModeSchema.safeParse(modeToValidate);\n if (!parseResult.success) {\n throw new Error(\n `Invalid memoryMode: \"${modeToValidate}\". Must be \"always\", \"once\", or \"never\".`\n );\n }\n this.memoryMode = parseResult.data;\n\n // Validate and set deduplication capacity\n const capacity = options?.dedupCapacity ?? 10000;\n if (capacity < 1 || !Number.isInteger(capacity)) {\n throw new Error('dedupCapacity must be a positive integer');\n }\n this.maxTrackedTokens = capacity;\n this.processedWebhookTokens = new Set();\n }\n\n /**\n * Get the channel type (implemented by subclasses)\n */\n public abstract get channelType(): ChannelType;\n\n /**\n * Register event callbacks\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Generic event callback needs to accept any args\n public on(event: string, callback: (...args: any[]) => void): void {\n switch (event) {\n case 'conversationStarted':\n this.callbacks.onConversationStarted = callback;\n break;\n case 'conversationEnded':\n this.callbacks.onConversationEnded = callback;\n break;\n case 'error':\n this.callbacks.onError = callback;\n break;\n }\n }\n\n /**\n * Process incoming webhook data (implemented by subclasses)\n */\n public abstract processWebhook(payload: unknown): Promise<void>;\n\n /**\n * Send a response back to the user (implemented by subclasses)\n */\n public abstract sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void>;\n\n /**\n * Start a new conversation session\n */\n protected startConversation(\n conversationId: ConversationId,\n profileId?: ProfileId,\n serviceId?: string\n ): ConversationSession {\n if (this.activeConversations.has(conversationId)) {\n this.logger.debug(\n {\n conversation_id: conversationId,\n profile_id: this.activeConversations.get(conversationId)?.profileId,\n service_id: this.activeConversations.get(conversationId)?.serviceId,\n },\n 'Conversation already active'\n );\n return this.activeConversations.get(conversationId)!;\n }\n\n const session: ConversationSession = {\n conversationId: conversationId,\n profileId: profileId,\n serviceId: serviceId,\n channel: this.channelType,\n startedAt: new Date(),\n metadata: {},\n };\n\n this.activeConversations.set(conversationId, session);\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n profile_id: profileId,\n service_id: serviceId,\n channel: this.channelType,\n },\n 'Conversation started'\n );\n\n if (this.callbacks.onConversationStarted) {\n this.callbacks.onConversationStarted({ session });\n }\n\n return session;\n }\n\n /**\n * End a conversation session.\n *\n * Triggers the onConversationEnded callback BEFORE removing the session,\n * so the callback receives the full ConversationSession data.\n * Errors in the callback do not prevent session cleanup.\n */\n protected async endConversation(conversationId: ConversationId): Promise<void> {\n const session = this.activeConversations.get(conversationId);\n\n if (session) {\n // Trigger callback BEFORE deleting the session\n if (this.callbacks.onConversationEnded) {\n try {\n await this.callbacks.onConversationEnded({ session });\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: conversationId },\n 'Error in conversation ended callback'\n );\n }\n }\n\n this.activeConversations.delete(conversationId);\n this.logger.debug(\n {\n conversation_id: conversationId,\n channel: this.channelType,\n service_id: session.serviceId,\n },\n 'Conversation ended'\n );\n } else {\n this.logger.debug(\n { conversation_id: conversationId, channel: this.channelType },\n 'Conversation end requested but no active session found'\n );\n }\n }\n\n /**\n * Get an active conversation session\n */\n public getConversationSession(conversationId: ConversationId): ConversationSession | undefined {\n return this.activeConversations.get(conversationId);\n }\n\n /**\n * Check if a conversation is active\n */\n public isConversationActive(conversationId: ConversationId): boolean {\n return this.activeConversations.has(conversationId);\n }\n\n /**\n * Handle errors with proper context\n */\n protected handleError(error: Error, context?: Record<string, unknown>): void {\n this.logger.error({ err: error }, 'Channel error');\n\n if (this.callbacks.onError) {\n if (context) {\n this.callbacks.onError({ error, context });\n } else {\n this.callbacks.onError({ error });\n }\n }\n }\n\n /**\n * Check if a webhook has already been processed using Twilio's idempotency token.\n * Uses a sliding window with fixed capacity to track tokens (FIFO eviction).\n *\n * This is intentionally a single synchronous check-and-record to prevent race conditions\n * where a duplicate arrives while the first request is still awaiting async work.\n */\n protected isDuplicateWebhook(idempotencyToken: string): boolean {\n if (this.processedWebhookTokens.has(idempotencyToken)) {\n return true;\n }\n\n if (this.processedWebhookTokens.size >= this.maxTrackedTokens) {\n const oldest = this.processedWebhookTokens.values().next().value!;\n this.processedWebhookTokens.delete(oldest);\n }\n\n this.processedWebhookTokens.add(idempotencyToken);\n return false;\n }\n\n /**\n * Remove an idempotency token from the deduplication cache.\n * Used when webhook processing fails and retries should not be blocked.\n */\n protected removeWebhookToken(idempotencyToken: string): void {\n this.processedWebhookTokens.delete(idempotencyToken);\n }\n\n /**\n * Self-filtering: check if webhook event belongs to this channel.\n *\n * - COMMUNICATION_CREATED: require author.channel matches this channel type\n * - CONVERSATION_UPDATED: only process if conversation is tracked locally\n * - Other events: pass through\n */\n protected isEventForThisChannel(webhookData: ConversationWebhookPayload): boolean {\n const eventType = webhookData.eventType;\n const authorChannel = webhookData.data?.author?.channel;\n\n // COMMUNICATION_CREATED: require author.channel for safe filtering\n // Reject events without channel to prevent fanout crosstalk\n if (eventType === 'COMMUNICATION_CREATED') {\n if (!authorChannel) {\n return false;\n }\n return authorChannel === this.channelType.toUpperCase();\n }\n\n // CONVERSATION_UPDATED: only process if this channel tracks the conversation\n if (eventType === 'CONVERSATION_UPDATED') {\n const conversationId = this.extractConversationId(webhookData);\n if (conversationId && !this.activeConversations.has(conversationId)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Validate webhook payload (override in subclasses for specific validation)\n */\n protected validateWebhookPayload(payload: unknown): boolean {\n return payload !== null && payload !== undefined;\n }\n\n /**\n * Preprocess webhook before handling event-specific logic.\n * Handles deduplication, validation, filtering, and data extraction.\n *\n * @param payload - Raw webhook payload from Twilio\n * @param idempotencyToken - Optional idempotency token for deduplication\n * @returns Preprocessed webhook data, or null if webhook should be skipped\n */\n protected preprocessWebhook(\n payload: unknown,\n idempotencyToken: string | undefined\n ): {\n webhookData: ConversationWebhookPayload;\n eventType: string;\n conversationId: string | undefined;\n } | null {\n this.logger.debug({ operation: 'webhook_processing' }, 'Processing webhook');\n\n if (idempotencyToken && this.isDuplicateWebhook(idempotencyToken)) {\n this.logger.debug({ idempotency_token: idempotencyToken }, 'Skipping duplicate webhook');\n return null;\n }\n\n if (!this.validateWebhookPayload(payload)) {\n throw new Error('Invalid webhook payload');\n }\n\n const webhookData = payload as ConversationWebhookPayload;\n const eventType = webhookData.eventType;\n const conversationId = webhookData.data?.conversationId || webhookData.data?.id;\n\n // Self-filter: ignore events meant for other channel types\n if (!this.isEventForThisChannel(webhookData)) {\n this.logger.debug(\n { event_type: eventType, channel: this.channelType, conversation_id: conversationId },\n 'Ignoring event for different channel type'\n );\n return null;\n }\n\n return { webhookData, eventType, conversationId };\n }\n\n /**\n * Extract conversation ID from webhook payload with type validation.\n *\n * Extracts conversationId from webhookData.data?.conversationId || webhookData.data?.id,\n * validates the value is a non-empty string, and ensures it passes isConversationId check.\n *\n * This prevents invalid IDs from causing downstream issues like incorrect Map key\n * matching in CONVERSATION_UPDATED self-filtering or propagating malformed IDs.\n */\n protected extractConversationId(payload: unknown): ConversationId | null {\n if (!payload || typeof payload !== 'object') {\n return null;\n }\n\n const webhookData = payload as ConversationWebhookPayload;\n const conversationId = webhookData.data?.conversationId || webhookData.data?.id;\n\n // Validate type and format before casting to ConversationId\n if (conversationId && typeof conversationId === 'string' && isConversationId(conversationId)) {\n return conversationId;\n }\n\n return null;\n }\n\n /**\n * Extract profile ID from webhook payload with type validation.\n *\n * Extracts profileId from webhookData.data?.profileId,\n * validates the value is a non-empty string, and ensures it passes isProfileId check.\n *\n * This prevents invalid IDs from propagating downstream and ensures consistent\n * validation across all channel types.\n */\n protected extractProfileId(payload: unknown): ProfileId | null {\n if (!payload || typeof payload !== 'object') {\n return null;\n }\n\n const webhookData = payload as ConversationWebhookPayload;\n const profileId = webhookData.data?.profileId;\n\n // Validate type and format before casting to ProfileId\n if (profileId && typeof profileId === 'string' && isProfileId(profileId)) {\n return profileId;\n }\n\n return null;\n }\n\n /**\n * Retrieve memory according to the channel's memoryMode.\n *\n * This method handles the common logic for memory retrieval across all channels,\n * including error handling and debug logging.\n *\n * Modes:\n * - \"always\": Fetch with the provided query on every message.\n * - \"once\": Fetch once with neither a query nor a conversation id (skipping\n * query expansion) and cache the result on the session. Subsequent calls\n * reuse the cache until it is invalidated on the INACTIVE transition.\n * - \"never\": Skip retrieval.\n *\n * Memory retrieval failures are logged and swallowed so message processing\n * continues without memory context.\n */\n protected async retrieveMemoryIfEnabled(\n session: ConversationSession,\n query?: string\n ): Promise<TACMemoryResponse | undefined> {\n // \"never\" and any unexpected value: no automatic retrieval\n if (this.memoryMode !== 'always' && this.memoryMode !== 'once') {\n return undefined;\n }\n\n // \"once\" mode reuses cached memory across messages.\n if (this.memoryMode === 'once' && session.cachedMemory !== undefined) {\n this.logger.debug({ conversation_id: session.conversationId }, 'Reusing cached memory');\n return session.cachedMemory;\n }\n\n try {\n // \"always\" sends query + conversation id so Memory ranks by relevance.\n // \"once\" sends neither: with no query, a conversation id only buys\n // Memory's expensive server-side query expansion.\n const isAlways = this.memoryMode === 'always';\n const memory = await this.tac.retrieveMemory(\n session,\n isAlways ? query : undefined,\n isAlways ? session.conversationId : undefined\n );\n if (this.memoryMode === 'once') {\n session.cachedMemory = memory;\n }\n this.logger.debug(\n { conversation_id: session.conversationId, memory_mode: this.memoryMode },\n 'Memory retrieved'\n );\n return memory;\n } catch (error) {\n this.logger.warn(\n { err: error, conversation_id: session.conversationId },\n 'Failed to retrieve memory, continuing without memory context'\n );\n // Continue without memory rather than failing entire message processing\n return undefined;\n }\n }\n\n /**\n * Invalidate cached memory for \"once\" mode when a conversation becomes\n * INACTIVE. Conversation Orchestrator updates memory on the INACTIVE\n * transition, so the next message re-fetches fresh memory. No-op for other\n * memory modes.\n */\n protected invalidateCachedMemory(conversationId: ConversationId): void {\n if (this.memoryMode !== 'once') {\n return;\n }\n\n const session = this.activeConversations.get(conversationId);\n if (session?.cachedMemory !== undefined) {\n session.cachedMemory = undefined;\n this.logger.debug(\n { conversation_id: conversationId },\n 'Invalidated cached memory on INACTIVE status'\n );\n }\n }\n\n /**\n * Cleanup resources when shutting down\n */\n public shutdown(): void {\n this.activeConversations.clear();\n delete this.callbacks.onConversationStarted;\n delete this.callbacks.onConversationEnded;\n delete this.callbacks.onError;\n }\n}\n","import {\n ActionChannelSettings,\n ConversationAddress,\n ConversationId,\n ConversationParticipant,\n ConversationWebhookPayload,\n InitiateConversationResult,\n ProfileId,\n SendMessageActionRequest,\n isConversationId,\n} from '../types/index';\nimport axios from 'axios';\nimport { BaseChannel, BaseChannelEvents, BaseChannelOptions } from './base';\nimport { ConversationClient } from '../clients/conversation';\nimport type { TAC } from '../lib/tac';\nimport { maskAddress } from '../util/log-redaction';\n\n/**\n * Participant types that represent TAC itself at TAC's (channel, address).\n *\n * `AI_AGENT` is the canonical type; `AGENT` is the legacy Conversation\n * Orchestrator form. A participant typed either way at TAC's address is\n * recognized as TAC and not overwritten; anything else (HUMAN_AGENT,\n * CUSTOMER, …) is someone else's assignment.\n */\nconst AGENT_TYPES = new Set<string>(['AGENT', 'AI_AGENT']);\n\n/**\n * Memory identifier type to use when looking up / creating a profile for a\n * channel's customer address. Channels absent from this map skip profile\n * resolution during participant reconciliation.\n */\nconst CHANNEL_IDENTITY_TYPES: Record<string, string> = {\n SMS: 'phone',\n VOICE: 'phone',\n RCS: 'rcs',\n WHATSAPP: 'whatsapp',\n};\n\n/**\n * Messaging channel configuration options.\n * Alias for BaseChannelOptions that can be extended by specific channel implementations.\n */\nexport type MessagingChannelConfig = BaseChannelOptions;\n\n/**\n * Messaging channel event callbacks extending base callbacks\n */\nexport interface MessagingChannelEvents extends BaseChannelEvents {\n onMessageReceived?: (data: {\n conversationId: ConversationId;\n profileId: ProfileId | undefined;\n message: string;\n author: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Memory structure is dynamic and defined by user\n userMemory: any;\n }) => void;\n}\n\n/**\n * Abstract Messaging Channel base class for SMS and Chat channels\n *\n * Provides shared webhook processing logic for messaging channels\n * (SMS and Chat) that use the Conversations Service webhooks.\n *\n * Subclasses must implement:\n * - `isDefaultAgentAddress`: fast-path check for the channel's default agent address\n * - `getAgentAddress`: return the agent's `ConversationAddress` for a conversation\n * - `sendResponse`: send messages back through the channel\n *\n * Subclass flags:\n * - `reconcileCustomerType`: if `true` (default), reconciliation will also\n * promote a channel-matching UNKNOWN participant (not owning the agent\n * address) to CUSTOMER. Set `false` for channels where the customer is\n * identified author-driven (e.g. chat).\n */\nexport abstract class MessagingChannel extends BaseChannel {\n protected override readonly conversationClient: ConversationClient;\n protected readonly messagingCallbacks: MessagingChannelEvents;\n\n /**\n * Controls whether reconciliation promotes an UNKNOWN customer-side\n * participant to CUSTOMER. Subclasses override to opt out (e.g. chat).\n */\n protected reconcileCustomerType: boolean = true;\n\n constructor(tac: TAC, config?: MessagingChannelConfig) {\n super(tac, config);\n if (!tac.isOrchestratorEnabled()) {\n throw new Error(\n 'Messaging channels require conversationConfigurationId to be configured. ' +\n 'Voice-only mode does not support SMS or Chat channels.'\n );\n }\n // Safe: orchestrator is enabled so conversationClient is guaranteed non-null\n this.conversationClient = tac.getConversationClient() as ConversationClient;\n this.messagingCallbacks = {};\n }\n\n /**\n * Fast-path check: is the author address this channel's default agent address?\n * (e.g., config.phoneNumber for SMS, agentAddress for Chat)\n */\n protected abstract isDefaultAgentAddress(authorAddress: string): boolean;\n\n /**\n * Return the agent-side ConversationAddress for this conversation.\n *\n * Used by `reconcileParticipants` to identify which participant (by channel\n * + address) represents the agent. May read from session state (e.g. chat's\n * per-conversation channelId) to build the address.\n */\n protected abstract getAgentAddress(conversationId: ConversationId): ConversationAddress;\n\n /**\n * Check if a message is from the bot itself (2-tier).\n *\n * 1. Default agent address (stateless, no API call)\n * 2. API fallback via listParticipants (cross-process / multi-worker)\n */\n private async isOwnMessage(\n authorAddress: string,\n conversationId: ConversationId,\n authorParticipantId: string | undefined\n ): Promise<boolean> {\n if (this.isDefaultAgentAddress(authorAddress)) return true;\n\n if (authorParticipantId) {\n try {\n const participants = await this.conversationClient.listParticipants(conversationId);\n const authorParticipant = participants.find(p => p.id === authorParticipantId);\n if (authorParticipant) {\n if (authorParticipant.type === undefined) {\n this.logger.warn(\n { conversation_id: conversationId, participant_id: authorParticipantId },\n 'Participant type is undefined — cannot determine if this is an agent message'\n );\n }\n if (authorParticipant.type && AGENT_TYPES.has(authorParticipant.type)) {\n return true;\n }\n }\n } catch (error) {\n this.logger.warn(\n { err: error, conversation_id: conversationId, participant_id: authorParticipantId },\n 'Failed to look up participant type for self-message check; falling through'\n );\n }\n }\n\n return false;\n }\n\n /**\n * Register event callbacks (override for messaging-specific events)\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Generic event callback needs to accept any args\n public override on(event: string, callback: (...args: any[]) => void): void {\n if (event === 'messageReceived') {\n this.messagingCallbacks.onMessageReceived = callback;\n } else {\n // Delegate to parent for base events\n super.on(event, callback);\n }\n }\n\n /**\n * Process messaging channel webhook from Conversation Orchestrator\n */\n public async processWebhook(payload: unknown, idempotencyToken?: string): Promise<void> {\n try {\n const result = this.preprocessWebhook(payload, idempotencyToken);\n if (!result) {\n return;\n }\n\n const { webhookData, eventType, conversationId } = result;\n\n switch (eventType) {\n case 'CONVERSATION_CREATED':\n this.logger.debug(\n { conversation_id: conversationId, profile_id: webhookData.data?.profileId },\n 'Handling CONVERSATION_CREATED'\n );\n this.handleConversationCreated(webhookData);\n break;\n\n case 'COMMUNICATION_CREATED':\n this.logger.debug({ conversation_id: conversationId }, 'Handling COMMUNICATION_CREATED');\n await this.handleCommunicationCreated(webhookData);\n break;\n\n case 'CONVERSATION_UPDATED':\n this.logger.debug(\n { conversation_id: conversationId, status: webhookData.data?.status },\n 'Handling CONVERSATION_UPDATED'\n );\n await this.handleConversationUpdated(webhookData);\n break;\n\n default:\n this.logger.warn(\n {\n event_type: eventType,\n raw_event_type: webhookData.eventType,\n conversation_id: conversationId,\n },\n 'Unhandled event type - this event will be ignored'\n );\n }\n\n this.logger.debug({ event_type: eventType }, 'Webhook processing completed');\n } catch (error) {\n // Remove the token so retries are not blocked\n if (idempotencyToken) {\n this.removeWebhookToken(idempotencyToken);\n }\n this.handleError(error instanceof Error ? error : new Error(String(error)), { payload });\n }\n }\n\n /**\n * Handle conversation creation event\n */\n private handleConversationCreated(payload: ConversationWebhookPayload): void {\n const conversationId = this.extractConversationId(payload);\n const profileId = this.extractProfileId(payload);\n\n if (!conversationId) {\n this.logger.warn(\n { operation: 'handle_conversation_created' },\n 'Missing conversation ID in conversation.created event'\n );\n throw new Error('Missing conversation ID in conversation.created event');\n }\n\n this.startConversation(conversationId, profileId ?? undefined, payload.data?.serviceId);\n }\n\n /**\n * Handle new communication event (incoming message)\n */\n private async handleCommunicationCreated(payload: ConversationWebhookPayload): Promise<void> {\n const conversationId = this.extractConversationId(payload);\n const profileId = this.extractProfileId(payload);\n // Extract message text from data.content.text\n const message = payload.data?.content?.text?.trim();\n // Author is in data.author.address\n const author = payload.data?.author?.address || 'unknown';\n\n this.logger.info(\n {\n conversation_id: conversationId,\n profile_id: profileId,\n author: maskAddress(author),\n message_length: message?.length,\n operation: 'handle_communication_created',\n },\n 'Handling communication.created'\n );\n\n if (!conversationId) {\n this.logger.warn(\n { operation: 'handle_communication_created' },\n 'Missing conversation ID in communication.created event'\n );\n throw new Error('Missing conversation ID in communication.created event');\n }\n\n if (!message) {\n this.logger.info({ conversation_id: conversationId }, 'Ignoring empty message');\n return;\n }\n\n // Per-conversation communication ID dedup stored in the in-memory\n // ConversationSession metadata. This only prevents duplicate processing\n // within the current process/session lifetime; it does not deduplicate\n // across horizontally-scaled instances or after a restart.\n const communicationId = payload.data?.id;\n if (communicationId) {\n const session = this.getConversationSession(conversationId);\n if (session?.metadata?.lastCommunicationId === communicationId) {\n this.logger.debug(\n { conversation_id: conversationId, communication_id: communicationId },\n 'Skipping already-processed communication'\n );\n return;\n }\n }\n\n // Filter out messages from the bot itself\n if (await this.isOwnMessage(author, conversationId, payload.data?.author?.participantId)) {\n this.logger.info(\n {\n conversation_id: conversationId,\n author_address: maskAddress(author),\n },\n 'Ignoring message from AI agent'\n );\n return;\n }\n\n // Initialize conversation if not already active\n if (!this.isConversationActive(conversationId)) {\n this.logger.debug({ conversation_id: conversationId }, 'Starting new conversation');\n this.startConversation(conversationId, profileId ?? undefined, payload.data?.serviceId);\n } else if (payload.data?.serviceId) {\n const session = this.getConversationSession(conversationId);\n if (session && session.serviceId !== payload.data.serviceId) {\n this.logger.debug(\n {\n conversation_id: conversationId,\n old_service_id: session.serviceId,\n new_service_id: payload.data.serviceId,\n },\n 'Updating conversation configuration ID from communication.created'\n );\n session.serviceId = payload.data.serviceId;\n }\n }\n\n // Get session and update with author info for profile lookup\n const session = this.getConversationSession(conversationId);\n if (session) {\n session.authorInfo = {\n address: author,\n participantId: payload.data?.author?.participantId,\n };\n\n // Store channelId (Chat Channel SID) in session metadata for reply sending\n if (payload.data?.channelId) {\n if (!session.metadata) {\n session.metadata = {};\n }\n session.metadata.channelId = payload.data.channelId;\n this.logger.debug(\n { conversation_id: conversationId, channel_id: payload.data.channelId },\n 'Stored channelId in session metadata'\n );\n }\n\n // Track communication ID for cross-process dedup\n if (communicationId) {\n if (!session.metadata) {\n session.metadata = {};\n }\n session.metadata.lastCommunicationId = communicationId;\n }\n\n // Reconcile participant types pre-LLM so v1-bridge's UNKNOWN gets\n // promoted, and to stash both participant ids on the session for\n // sendResponse. Reconcile failure means the reply would fail too —\n // skip the callback so the LLM doesn't waste a turn on an\n // un-replyable conversation.\n //\n // Gate on `aiAgentInfo` (persistent across turns) — `authorInfo` is\n // overwritten from every webhook so it's not a reliable \"already\n // reconciled\" signal.\n if (!session.aiAgentInfo) {\n const resolved = await this.reconcileParticipants(conversationId);\n if (!resolved) {\n // Surface via handleError (logs at error level AND fires the app's\n // onError callback) rather than a bare warn — otherwise the dropped\n // inbound is invisible to the app and can't be observed or retried.\n // Set a stable error.name and error_code so consumers can classify\n // this condition programmatically without string-matching the message.\n const error = new Error(\n `Participant reconciliation failed for conversation ${conversationId}; ` +\n 'inbound message dropped because no sendable participants could be resolved.'\n );\n error.name = 'ParticipantReconciliationError';\n this.handleError(error, {\n conversation_id: conversationId,\n channel: this.channelType,\n dropped_inbound: true,\n error_code: 'participant_reconciliation_failed',\n });\n return;\n }\n\n const [agentParticipant, customerParticipant] = resolved;\n const agentAddress = this.getAgentAddress(conversationId);\n session.aiAgentInfo = {\n address: agentAddress.address,\n participantId: agentParticipant.id,\n };\n // When reconcile resolved a customer (SMS path — chat disables customer\n // reconciliation and uses the authorInfo captured from the webhook\n // above), use its authoritative participant id and lift any resolved\n // profile.\n if (customerParticipant && session.authorInfo) {\n session.authorInfo.participantId = customerParticipant.id;\n if (customerParticipant.profileId && !session.profileId) {\n session.profileId = customerParticipant.profileId;\n }\n }\n }\n }\n\n // Retrieve user memory if enabled via memoryMode\n const userMemory = session ? await this.retrieveMemoryIfEnabled(session, message) : undefined;\n\n // Invoke message received callback with memory context\n if (this.messagingCallbacks.onMessageReceived) {\n this.logger.debug({ conversation_id: conversationId }, 'Invoking message received callback');\n this.messagingCallbacks.onMessageReceived({\n conversationId,\n profileId: (session?.profileId as ProfileId | undefined) ?? profileId ?? undefined,\n message,\n author,\n userMemory,\n });\n }\n }\n\n /**\n * Handle conversation updated event\n */\n private async handleConversationUpdated(payload: ConversationWebhookPayload): Promise<void> {\n const conversationId = this.extractConversationId(payload);\n\n if (!conversationId) {\n throw new Error('Missing conversation ID in conversation.updated event');\n }\n\n // Check if conversation is closed\n if (payload.data?.status === 'CLOSED') {\n this.logger.debug(\n { conversation_id: conversationId, status: payload.data.status },\n 'Conversation closed, cleaning up'\n );\n await this.endConversation(conversationId);\n } else if (payload.data?.status === 'INACTIVE') {\n // Invalidate cached memory (\"once\" mode) when the conversation becomes\n // inactive. Memory is updated by Conversation Orchestrator on the\n // INACTIVE transition, so the next message re-fetches fresh memory.\n this.invalidateCachedMemory(conversationId);\n }\n }\n\n /**\n * Validate messaging channel webhook payload structure\n */\n protected override validateWebhookPayload(payload: unknown): boolean {\n if (!super.validateWebhookPayload(payload)) {\n return false;\n }\n\n const webhookData = payload as ConversationWebhookPayload;\n return (\n typeof webhookData === 'object' &&\n typeof webhookData.eventType === 'string' &&\n webhookData.eventType.length > 0\n );\n }\n\n /**\n * Reconcile Conversation Orchestrator's participants to the types TAC\n * needs for sending.\n *\n * v1-bridge capture can leave TAC's agent participant as `UNKNOWN` (wrong\n * type at our address), or omit it entirely (customer-only conversation).\n * This pass fixes those cases; it refuses to rewrite anything else at our\n * address. Decision matrix:\n *\n * | Agent side | Customer side | Action |\n * |----------------------|---------------------|-------------------------------|\n * | AGENT / AI_AGENT | CUSTOMER | Use as-is (no profile work). |\n * | AGENT / AI_AGENT | UNKNOWN, no CUST | Resolve profile, PUT → CUST. |\n * | UNKNOWN at our addr | CUSTOMER | PUT agent → AI_AGENT. |\n * | UNKNOWN at our addr | UNKNOWN, no CUST | PUT agent; resolve, PUT CUST. |\n * | other at our addr | any | Return null (log ERROR). |\n * | none at our addr | CUSTOMER or UNKNOWN | POST AI_AGENT, then proceed. |\n * | any | no resolvable cust | Return null (caller WARNs). |\n *\n * TAC recognizes both `AGENT` and `AI_AGENT` at its address as itself.\n * `HUMAN_AGENT` is NOT treated as TAC (a real human is a separate\n * participant — TAC must not speak on their behalf); it falls into the\n * \"other at our addr\" row and causes the reconcile to bail.\n *\n * Customer-side reconciliation is gated by `reconcileCustomerType`. Chat\n * sets it to `false` because chat identifies the customer author-driven\n * (via `session.authorInfo.participantId`), so promoting some other\n * `UNKNOWN` CHAT participant could pick the wrong recipient.\n *\n * @returns `[agent, customerOrNull]` on success. `customer` is `null` when\n * `reconcileCustomerType` is `false`. `null` overall when either the agent\n * or the customer cannot be resolved — the caller treats `null` as a hard\n * stop and skips the message-ready callback.\n */\n protected async reconcileParticipants(\n conversationId: ConversationId\n ): Promise<[ConversationParticipant, ConversationParticipant | null] | null> {\n const agentAddress = this.getAgentAddress(conversationId);\n\n let participants: ConversationParticipant[];\n try {\n participants = await this.conversationClient.listParticipants(conversationId);\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: conversationId },\n 'Failed to list participants for reconciliation'\n );\n return null;\n }\n\n const channel = agentAddress.channel;\n\n const ownsAgentAddress = (p: ConversationParticipant): boolean =>\n Array.isArray(p.addresses) &&\n p.addresses.some(a => a.channel === channel && a.address === agentAddress.address);\n\n const matchesChannel = (p: ConversationParticipant): boolean =>\n Array.isArray(p.addresses) && p.addresses.some(a => a.channel === channel);\n\n let agentCandidate = participants.find(ownsAgentAddress);\n if (!agentCandidate) {\n const created = await this.addAgentParticipant(conversationId, agentAddress);\n if (!created) return null;\n agentCandidate = created;\n } else if (agentCandidate.type === 'UNKNOWN') {\n // Only promote UNKNOWN — an already-typed participant at TAC's address\n // that isn't AGENT/AI_AGENT (e.g., CUSTOMER, HUMAN_AGENT) is someone\n // else's assignment and must not be overwritten.\n const promoted = await this.promoteParticipant(conversationId, agentCandidate, 'AI_AGENT');\n if (!promoted) return null;\n agentCandidate = promoted;\n } else if (!agentCandidate.type || !AGENT_TYPES.has(agentCandidate.type)) {\n this.logger.error(\n {\n conversation_id: conversationId,\n participant_id: agentCandidate.id,\n participant_type: agentCandidate.type,\n },\n \"Participant at TAC's address has a conflicting type; refusing to overwrite. \" +\n 'Check Conversation Orchestrator participant state — a non-agent participant is holding ' +\n \"TAC's (channel, address).\"\n );\n return null;\n }\n\n if (!this.reconcileCustomerType) {\n return [agentCandidate, null];\n }\n\n const customer = participants.find(\n p => p.type === 'CUSTOMER' && matchesChannel(p) && !ownsAgentAddress(p)\n );\n if (customer) {\n return [agentCandidate, customer];\n }\n\n const customerUnknown = participants.find(\n p => p.type === 'UNKNOWN' && matchesChannel(p) && !ownsAgentAddress(p)\n );\n if (customerUnknown) {\n const profileId = await this.resolveCustomerProfile(customerUnknown, channel);\n const promotedCustomer = await this.promoteParticipant(\n conversationId,\n customerUnknown,\n 'CUSTOMER',\n profileId\n );\n if (promotedCustomer) {\n return [agentCandidate, promotedCustomer];\n }\n }\n\n this.logger.warn(\n { conversation_id: conversationId, channel },\n 'No customer participant resolvable; skipping webhook'\n );\n return null;\n }\n\n /**\n * Find or mint a Conversation Memory profile for a customer being promoted from UNKNOWN.\n *\n * Only resolves for phone-based channels (SMS, VOICE, RCS, WHATSAPP). Looks\n * up by the channel's identifier type (`phone` for SMS/VOICE, `rcs` for\n * RCS, `whatsapp` for WHATSAPP) first; on miss, creates a new profile\n * using the configured phone trait group/field. Returns undefined on any\n * failure — the caller still promotes the participant, just without a\n * `profileId` attached.\n */\n private async resolveCustomerProfile(\n customer: ConversationParticipant,\n channel: string\n ): Promise<string | undefined> {\n const identityType = CHANNEL_IDENTITY_TYPES[channel];\n if (!identityType) return undefined;\n\n const memoryClient = this.tac.getMemoryClient();\n if (!memoryClient || !this.tac.getMemoryStoreId()) return undefined;\n\n const phoneAddress = Array.isArray(customer.addresses)\n ? (customer.addresses.find(a => a.channel === channel && !!a.address)?.address ?? undefined)\n : undefined;\n if (!phoneAddress) return undefined;\n\n try {\n const lookup = await memoryClient.lookupProfile(identityType, phoneAddress);\n if (lookup.profiles && lookup.profiles.length > 0) {\n return lookup.profiles[0];\n }\n } catch (error) {\n this.logger.warn(\n { err: error, conversation_id: customer.conversationId },\n 'Profile lookup failed during reconciliation; falling back to create'\n );\n }\n\n const memoryConfig = this.config.memoryConfig;\n const traitGroup = memoryConfig.phoneTraitGroup;\n const traitField = memoryConfig.phoneTraitField;\n\n try {\n return await memoryClient.createProfile({\n [traitGroup]: { [traitField]: phoneAddress },\n });\n } catch (error) {\n this.logger.warn(\n { err: error, conversation_id: customer.conversationId },\n 'Profile creation failed during reconciliation; promoting without profile'\n );\n return undefined;\n }\n }\n\n /**\n * PUT a participant to `newType`.\n *\n * Conversation Orchestrator's PUT is a full-resource replacement, so we\n * pass the existing `name` and `addresses` back unchanged to avoid wiping\n * them. `profileId` defaults to the participant's current value; pass a\n * non-undefined override to attach a newly resolved profile during CUSTOMER\n * reconciliation.\n *\n * Returns undefined on any error (including 409). A 409 from Conversation\n * Orchestrator here means the promotion is structurally blocked — stop and\n * surface it; don't retry.\n */\n private async promoteParticipant(\n conversationId: ConversationId,\n participant: ConversationParticipant,\n newType: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT' | 'AGENT',\n profileId?: string\n ): Promise<ConversationParticipant | undefined> {\n const effectiveProfileId = profileId !== undefined ? profileId : participant.profileId;\n const updateOptions: { name?: string; profileId?: string } = {};\n if (participant.name !== undefined) updateOptions.name = participant.name;\n if (effectiveProfileId !== null && effectiveProfileId !== undefined) {\n updateOptions.profileId = effectiveProfileId;\n }\n\n try {\n const updated = await this.conversationClient.updateParticipant(\n conversationId,\n participant.id,\n newType,\n participant.addresses,\n updateOptions\n );\n this.logger.debug(\n {\n conversation_id: conversationId,\n participant_id: participant.id,\n from_type: participant.type,\n to_type: newType,\n },\n 'Promoted participant'\n );\n return updated;\n } catch (error) {\n if (this.isConflictError(error)) {\n this.logger.warn(\n {\n conversation_id: conversationId,\n participant_id: participant.id,\n target_type: newType,\n conflicting_resource_id: this.extractConflictingResourceId(error),\n },\n 'Conversation Orchestrator returned 409 on participant promotion; skipping — ' +\n 'likely a conflicting conversation or grouping constraint. Check ' +\n 'Conversation Orchestrator for duplicate active conversations.'\n );\n return undefined;\n }\n this.logger.error(\n {\n err: error,\n conversation_id: conversationId,\n participant_id: participant.id,\n target_type: newType,\n },\n 'Failed to promote participant'\n );\n return undefined;\n }\n }\n\n /**\n * POST an `AI_AGENT` participant owning `agentAddress`.\n *\n * Returns undefined on any error (including 409). A 409 here means the\n * address is already owned or the conversation's participant set can't\n * accept a new AI_AGENT — stop and surface it; don't retry.\n */\n private async addAgentParticipant(\n conversationId: ConversationId,\n agentAddress: ConversationAddress\n ): Promise<ConversationParticipant | undefined> {\n try {\n const created = await this.conversationClient.addParticipant(\n conversationId,\n [agentAddress],\n 'AI_AGENT'\n );\n this.logger.debug(\n { conversation_id: conversationId, participant_id: created.id },\n 'Added AI_AGENT participant'\n );\n return created;\n } catch (error) {\n if (this.isConflictError(error)) {\n this.logger.warn(\n {\n conversation_id: conversationId,\n conflicting_resource_id: this.extractConflictingResourceId(error),\n },\n 'Conversation Orchestrator returned 409 on AI_AGENT participant add; skipping — ' +\n \"address is already owned or the conversation can't accept a new AI_AGENT. \" +\n 'Check Conversation Orchestrator participant state.'\n );\n return undefined;\n }\n this.logger.error(\n { err: error, conversation_id: conversationId },\n 'Failed to add AI_AGENT participant'\n );\n return undefined;\n }\n }\n\n private isConflictError(error: unknown): boolean {\n const cause = error instanceof Error ? (error.cause ?? error) : error;\n return axios.isAxiosError(cause) && cause.response?.status === 409;\n }\n\n private extractConflictingResourceId(error: unknown): string | undefined {\n const cause = error instanceof Error ? (error.cause ?? error) : error;\n if (!axios.isAxiosError(cause)) return undefined;\n const headers = cause.response?.headers as Record<string, string> | undefined;\n const id = headers?.['x-conflicting-resource-id'];\n return typeof id === 'string' && id.length > 0 ? id : undefined;\n }\n\n /**\n * Shared outbound conversation initiation for messaging channels (SMS/RCS/Chat/WhatsApp).\n *\n * Handles the full flow: create conversation → find participants → start\n * session → send initial message → error cleanup.\n */\n protected async initiateOutboundMessagingConversation(params: {\n channel: 'SMS' | 'CHAT' | 'RCS' | 'WHATSAPP';\n to: string;\n from: string;\n message: string;\n metadata?: Record<string, unknown>;\n channelId?: string;\n channelSettings?: ActionChannelSettings;\n }): Promise<InitiateConversationResult> {\n const {\n channel,\n to,\n from: fromAddress,\n message,\n metadata,\n channelId,\n channelSettings,\n } = params;\n\n let conversationId: string | undefined;\n let conversationReused = false;\n\n try {\n const customerAddress: ConversationAddress = {\n channel,\n address: to,\n ...(channelId ? { channelId } : {}),\n };\n const agentAddress: ConversationAddress = {\n channel,\n address: fromAddress,\n ...(channelId ? { channelId } : {}),\n };\n\n const result = await this.conversationClient.createOrReuseConversation([\n { type: 'CUSTOMER', addresses: [customerAddress] },\n { type: 'AI_AGENT', addresses: [agentAddress] },\n ]);\n conversationId = result.conversation.id;\n conversationReused = result.reused;\n\n if (!isConversationId(conversationId)) {\n throw new Error(`Invalid conversation ID returned: ${conversationId}`);\n }\n\n const participants = await this.conversationClient.listParticipants(conversationId);\n\n const customerParticipant = participants.find(\n p =>\n p.type === 'CUSTOMER' &&\n Array.isArray(p.addresses) &&\n p.addresses.some(\n a =>\n a.channel === channel &&\n a.address === to &&\n (channelId === undefined || a.channelId === channelId)\n )\n );\n if (!customerParticipant) {\n throw new Error('Customer participant not found after conversation creation');\n }\n\n const agentParticipant = participants.find(\n p =>\n p.type !== undefined &&\n AGENT_TYPES.has(p.type) &&\n Array.isArray(p.addresses) &&\n p.addresses.some(\n a =>\n a.channel === channel &&\n a.address === fromAddress &&\n (channelId === undefined || a.channelId === channelId)\n )\n );\n if (!agentParticipant) {\n throw new Error('Agent participant not found after conversation creation');\n }\n\n // Start local session BEFORE sending the initial message so the\n // COMMUNICATION_CREATED webhook (triggered by createAction) finds a\n // correctly-configured session instead of auto-starting one with wrong\n // metadata.\n const session = this.startConversation(conversationId);\n session.authorInfo = {\n address: to,\n participantId: customerParticipant.id,\n };\n session.aiAgentInfo = {\n address: fromAddress,\n participantId: agentParticipant.id,\n };\n session.metadata = {\n ...session.metadata,\n ...(metadata ?? {}),\n direction: 'outbound',\n ...(channelId ? { channelId } : {}),\n };\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: { channel, participantId: agentParticipant.id },\n to: [{ channel, participantId: customerParticipant.id }],\n content: { text: message },\n ...(channelSettings ? { channelSettings } : {}),\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n { conversation_id: conversationId, to: maskAddress(to) },\n `Outbound ${channel} conversation initiated`\n );\n\n return { conversationId, session };\n } catch (error) {\n if (conversationId) {\n this.activeConversations.delete(conversationId as ConversationId);\n }\n if (conversationId && !conversationReused) {\n await this.conversationClient\n .updateConversation(conversationId, 'CLOSED')\n .catch(closeErr => {\n this.logger.warn(\n { err: closeErr, conversation_id: conversationId },\n 'Failed to close orphaned conversation after initiation error'\n );\n });\n }\n this.logger.error(\n { err: error, to: maskAddress(to) },\n `Failed to initiate outbound ${channel}`\n );\n this.handleError(error instanceof Error ? error : new Error(String(error)), { to });\n throw error;\n }\n }\n}\n","import {\n ChannelType,\n ConversationAddress,\n ConversationId,\n SendMessageActionRequest,\n InitiateMessagingConversationOptions,\n InitiateMessagingConversationOptionsSchema,\n InitiateConversationResult,\n} from '../types/index';\nimport { MessagingChannel } from './messaging';\nimport { maskAddress } from '../util/log-redaction';\n\n/**\n * SMS Channel implementation for Twilio Conversations Service\n *\n * Handles SMS conversations through webhook events from Twilio.\n * Automatically retrieves user memory and manages conversation lifecycle.\n */\nexport class SMSChannel extends MessagingChannel {\n public get channelType(): ChannelType {\n return 'sms';\n }\n\n protected isDefaultAgentAddress(authorAddress: string): boolean {\n return authorAddress === this.config.phoneNumber;\n }\n\n protected getAgentAddress(_conversationId: ConversationId): ConversationAddress {\n return { channel: 'SMS', address: this.config.phoneNumber };\n }\n\n /**\n * Send SMS response using the Conversation Orchestrator Actions API (SEND_MESSAGE).\n *\n * Reads the agent and customer participant ids stashed on the session by\n * inbound reconciliation or outbound initiation. Missing ids are a misuse —\n * `sendResponse` is only expected to be called after an inbound webhook\n * (COMMUNICATION_CREATED → reconcile) or after `initiateOutboundConversation`,\n * both of which populate the session.\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_length: message.length,\n operation: 'send_response',\n },\n 'Sending SMS response'\n );\n\n try {\n const session = this.getConversationSession(conversationId);\n\n if (!session || !session.authorInfo || !session.aiAgentInfo) {\n throw new Error(\n `Unable to send SMS: sendResponse called without a reconciled session for ` +\n `conversation ${conversationId}. Wait for an inbound webhook or call ` +\n `initiateOutboundConversation first.`\n );\n }\n\n const customerParticipantId = session.authorInfo.participantId;\n const agentParticipantId = session.aiAgentInfo.participantId;\n if (!customerParticipantId || !agentParticipantId) {\n throw new Error(\n `Unable to send SMS: session for conversation ${conversationId} is missing ` +\n `participant ids.`\n );\n }\n\n const channelId =\n typeof session.metadata?.channelId === 'string' ? session.metadata.channelId : undefined;\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n recipient_participant_id: customerParticipantId,\n agent_participant_id: agentParticipantId,\n },\n 'Sending SMS via Actions API'\n );\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: {\n channel: 'SMS',\n participantId: agentParticipantId,\n },\n to: [\n {\n channel: 'SMS',\n participantId: customerParticipantId,\n },\n ],\n content: { text: message },\n ...(channelId ? { channelSettings: { channelId } } : {}),\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n },\n 'SMS sent successfully via Actions API'\n );\n } catch (error) {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Send response error');\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n }\n\n /**\n * Initiate an outbound SMS conversation\n *\n * Creates a conversation via Conversation Orchestrator, adds customer and\n * agent participants, then sends the initial message via the Actions API.\n * The sender is always `config.phoneNumber`.\n */\n public async initiateOutboundConversation(\n options: InitiateMessagingConversationOptions\n ): Promise<InitiateConversationResult> {\n const validated = InitiateMessagingConversationOptionsSchema.parse(options);\n\n this.logger.info(\n { to: maskAddress(validated.to), message_length: validated.message.length },\n 'Initiating outbound SMS conversation'\n );\n\n return this.initiateOutboundMessagingConversation({\n channel: 'SMS',\n to: validated.to,\n from: this.config.phoneNumber,\n message: validated.message,\n ...(validated.metadata ? { metadata: validated.metadata } : {}),\n });\n }\n}\n","import {\n ChannelType,\n ConversationAddress,\n ConversationId,\n SendMessageActionRequest,\n InitiateMessagingConversationOptions,\n InitiateMessagingConversationOptionsSchema,\n InitiateConversationResult,\n} from '../types/index';\nimport { MessagingChannel, MessagingChannelConfig } from './messaging';\nimport { maskAddress } from '../util/log-redaction';\nimport type { TAC } from '../lib/tac';\n\n/**\n * RCS Channel implementation for Twilio Conversations Service\n *\n * Handles RCS (Rich Communication Services) conversations through webhook\n * events from Twilio. The RCS Sender ID is configured on `TACConfig` via\n * `TWILIO_RCS_SENDER_ID`. Follows the same pattern as SMS (sender from\n * TAC config) for consistency with other messaging channels.\n */\nexport class RCSChannel extends MessagingChannel {\n constructor(tac: TAC, config?: MessagingChannelConfig) {\n super(tac, config);\n\n if (!this.config.rcsSenderId) {\n throw new Error(\n 'rcsSenderId is required for RCS channel. ' +\n 'Please set TWILIO_RCS_SENDER_ID environment variable or provide rcsSenderId in TACConfig.'\n );\n }\n }\n\n public get channelType(): ChannelType {\n return 'rcs';\n }\n\n protected isDefaultAgentAddress(authorAddress: string): boolean {\n return authorAddress === this.config.rcsSenderId;\n }\n\n protected getAgentAddress(_conversationId: ConversationId): ConversationAddress {\n if (!this.config.rcsSenderId) {\n throw new Error('rcsSenderId is required for RCS channel.');\n }\n return { channel: 'RCS', address: this.config.rcsSenderId };\n }\n\n /**\n * Send RCS response using the Conversation Orchestrator Actions API (SEND_MESSAGE).\n *\n * Reads the agent and customer participant ids stashed on the session by\n * inbound reconciliation or outbound initiation. Missing ids are a misuse —\n * `sendResponse` is only expected to be called after an inbound webhook\n * (COMMUNICATION_CREATED → reconcile) or after `initiateOutboundConversation`,\n * both of which populate the session.\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_length: message.length,\n operation: 'send_response',\n },\n 'Sending RCS response'\n );\n\n try {\n const session = this.getConversationSession(conversationId);\n\n if (!session || !session.authorInfo || !session.aiAgentInfo) {\n throw new Error(\n `Unable to send RCS: sendResponse called without a reconciled session for ` +\n `conversation ${conversationId}. Wait for an inbound webhook or call ` +\n `initiateOutboundConversation first.`\n );\n }\n\n const customerParticipantId = session.authorInfo.participantId;\n const agentParticipantId = session.aiAgentInfo.participantId;\n if (!customerParticipantId || !agentParticipantId) {\n throw new Error(\n `Unable to send RCS: session for conversation ${conversationId} is missing ` +\n `participant ids.`\n );\n }\n\n const channelId =\n typeof session.metadata?.channelId === 'string' ? session.metadata.channelId : undefined;\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n recipient_participant_id: customerParticipantId,\n agent_participant_id: agentParticipantId,\n },\n 'Sending RCS via Actions API'\n );\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: {\n channel: 'RCS',\n participantId: agentParticipantId,\n },\n to: [\n {\n channel: 'RCS',\n participantId: customerParticipantId,\n },\n ],\n content: { text: message },\n ...(channelId ? { channelSettings: { channelId } } : {}),\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n },\n 'RCS sent successfully via Actions API'\n );\n } catch (error) {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Send response error');\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n }\n\n /**\n * Initiate an outbound RCS conversation\n *\n * Creates a conversation via Conversation Orchestrator, adds customer and\n * agent participants, then sends the initial message via the Actions API.\n * The sender is always `config.rcsSenderId`.\n */\n public async initiateOutboundConversation(\n options: InitiateMessagingConversationOptions\n ): Promise<InitiateConversationResult> {\n const validated = InitiateMessagingConversationOptionsSchema.parse(options);\n\n if (!this.config.rcsSenderId) {\n throw new Error('rcsSenderId is required for RCS channel.');\n }\n\n this.logger.info(\n { to: maskAddress(validated.to), message_length: validated.message.length },\n 'Initiating outbound RCS conversation'\n );\n\n return this.initiateOutboundMessagingConversation({\n channel: 'RCS',\n to: validated.to,\n from: this.config.rcsSenderId,\n message: validated.message,\n ...(validated.metadata ? { metadata: validated.metadata } : {}),\n });\n }\n}\n","import {\n ChannelType,\n ConversationAddress,\n ConversationId,\n SendMessageActionRequest,\n InitiateMessagingConversationOptions,\n InitiateMessagingConversationOptionsSchema,\n InitiateConversationResult,\n} from '../types/index';\nimport { MessagingChannel } from './messaging';\nimport { maskAddress } from '../util/log-redaction';\n\n/**\n * WhatsApp Channel implementation for Twilio Conversations Service\n *\n * Handles WhatsApp conversations through webhook events from Twilio.\n * Automatically retrieves user memory and manages conversation lifecycle.\n *\n * WhatsApp uses WhatsApp sender phone numbers configured in TACConfig\n * (via TWILIO_WHATSAPP_NUMBER). Address format: whatsapp:+1234567890\n */\nexport class WhatsAppChannel extends MessagingChannel {\n public get channelType(): ChannelType {\n return 'whatsapp';\n }\n\n protected isDefaultAgentAddress(authorAddress: string): boolean {\n if (!this.config.whatsappNumber) {\n throw new Error(\n 'whatsappNumber is required for WhatsApp channel. ' +\n 'Please set TWILIO_WHATSAPP_NUMBER environment variable or ' +\n 'provide whatsappNumber in TACConfig.'\n );\n }\n return authorAddress === this.config.whatsappNumber;\n }\n\n protected getAgentAddress(_conversationId: ConversationId): ConversationAddress {\n if (!this.config.whatsappNumber) {\n throw new Error(\n 'whatsappNumber is required for WhatsApp channel. ' +\n 'Please set TWILIO_WHATSAPP_NUMBER environment variable or ' +\n 'provide whatsappNumber in TACConfig.'\n );\n }\n return { channel: 'WHATSAPP', address: this.config.whatsappNumber };\n }\n\n /**\n * Send WhatsApp response using the Conversation Orchestrator Actions API (SEND_MESSAGE).\n *\n * Reads the agent and customer participant ids stashed on the session by\n * inbound reconciliation or outbound initiation. Missing ids are a misuse —\n * `sendResponse` is only expected to be called after an inbound webhook\n * (COMMUNICATION_CREATED → reconcile) or after `initiateOutboundConversation`,\n * both of which populate the session.\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_length: message.length,\n operation: 'send_response',\n },\n 'Sending WhatsApp response'\n );\n\n try {\n const session = this.getConversationSession(conversationId);\n\n if (!session || !session.authorInfo || !session.aiAgentInfo) {\n throw new Error(\n `Unable to send WhatsApp: sendResponse called without a reconciled session for ` +\n `conversation ${conversationId}. Wait for an inbound webhook or call ` +\n `initiateOutboundConversation first.`\n );\n }\n\n const customerParticipantId = session.authorInfo.participantId;\n const agentParticipantId = session.aiAgentInfo.participantId;\n if (!customerParticipantId || !agentParticipantId) {\n throw new Error(\n `Unable to send WhatsApp: session for conversation ${conversationId} is missing ` +\n `participant ids.`\n );\n }\n\n const channelId =\n typeof session.metadata?.channelId === 'string' ? session.metadata.channelId : undefined;\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n recipient_participant_id: customerParticipantId,\n agent_participant_id: agentParticipantId,\n },\n 'Sending WhatsApp via Actions API'\n );\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: {\n channel: 'WHATSAPP',\n participantId: agentParticipantId,\n },\n to: [\n {\n channel: 'WHATSAPP',\n participantId: customerParticipantId,\n },\n ],\n content: { text: message },\n ...(channelId ? { channelSettings: { channelId } } : {}),\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n },\n 'WhatsApp sent successfully via Actions API'\n );\n } catch (error) {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Send response error');\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n }\n\n /**\n * Initiate an outbound WhatsApp conversation\n *\n * Creates a conversation via Conversation Orchestrator, adds customer and\n * agent participants, then sends the initial message via the Actions API.\n * The sender is always `config.whatsappNumber`.\n */\n public async initiateOutboundConversation(\n options: InitiateMessagingConversationOptions\n ): Promise<InitiateConversationResult> {\n const validated = InitiateMessagingConversationOptionsSchema.parse(options);\n\n if (!this.config.whatsappNumber) {\n throw new Error(\n 'whatsappNumber is required for WhatsApp channel. ' +\n 'Please set TWILIO_WHATSAPP_NUMBER environment variable or ' +\n 'provide whatsappNumber in TACConfig.'\n );\n }\n\n this.logger.info(\n { to: maskAddress(validated.to), message_length: validated.message.length },\n 'Initiating outbound WhatsApp conversation'\n );\n\n return this.initiateOutboundMessagingConversation({\n channel: 'WHATSAPP',\n to: validated.to,\n from: this.config.whatsappNumber,\n message: validated.message,\n ...(validated.metadata ? { metadata: validated.metadata } : {}),\n });\n }\n}\n","import {\n ActionChannelSettings,\n ChannelType,\n ConversationAddress,\n ConversationId,\n SendMessageActionRequest,\n InitiateConversationResult,\n} from '../types/index';\nimport { z } from 'zod';\nimport { MessagingChannel, MessagingChannelConfig } from './messaging';\nimport type { TAC } from '../lib/tac';\nimport { maskAddress } from '../util/log-redaction';\n\n/**\n * Options for initiating an outbound chat conversation.\n *\n * The sender is always the channel's configured `agentAddress`. Multi-sender\n * deployments should run one TAC instance per sender.\n */\nexport const InitiateChatConversationOptionsSchema = z.object({\n to: z.string().min(1, 'Recipient identity is required'),\n channelId: z.string().min(1, 'Chat Channel SID is required'),\n message: z.string().min(1, 'Initial message is required'),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type InitiateChatConversationOptions = z.infer<typeof InitiateChatConversationOptionsSchema>;\n\n/**\n * Chat channel configuration options\n */\nexport interface ChatChannelConfig extends MessagingChannelConfig {\n /** Chat agent identity string (defaults to 'ai-assistant') */\n agentAddress?: string;\n}\n\n/**\n * Chat Channel implementation for Twilio Conversations Service\n *\n * Handles web chat conversations through webhook events from Twilio.\n * Uses identity-based addressing instead of phone numbers.\n * Automatically creates AI_AGENT participant if needed and manages conversation lifecycle.\n */\nexport class ChatChannel extends MessagingChannel {\n private readonly agentAddress: string;\n\n // Chat identifies the customer author-driven from the webhook's\n // `author.participantId`; promoting some other channel-matching UNKNOWN\n // CHAT participant could pick the wrong recipient.\n protected override reconcileCustomerType: boolean = false;\n\n constructor(tac: TAC, config?: ChatChannelConfig) {\n super(tac, config);\n this.agentAddress = config?.agentAddress ?? 'ai-assistant';\n }\n\n public get channelType(): ChannelType {\n return 'chat';\n }\n\n protected isDefaultAgentAddress(authorAddress: string): boolean {\n return authorAddress === this.agentAddress;\n }\n\n protected getAgentAddress(conversationId: ConversationId): ConversationAddress {\n const session = this.getConversationSession(conversationId);\n const channelId =\n session && typeof session.metadata?.channelId === 'string'\n ? session.metadata.channelId\n : undefined;\n return {\n channel: 'CHAT',\n address: this.agentAddress,\n ...(channelId ? { channelId } : {}),\n };\n }\n\n /**\n * Send chat response using the Conversation Orchestrator Actions API (SEND_MESSAGE).\n *\n * Reads the agent and customer participant ids stashed on the session by\n * inbound reconciliation or outbound initiation. Missing ids are a misuse —\n * `sendResponse` is only expected to be called after an inbound webhook\n * (COMMUNICATION_CREATED → reconcile) or after `initiateOutboundConversation`,\n * both of which populate the session.\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_length: message.length,\n operation: 'send_response',\n },\n 'Sending chat response'\n );\n\n try {\n const session = this.getConversationSession(conversationId);\n\n if (!session || !session.authorInfo || !session.aiAgentInfo) {\n throw new Error(\n `Unable to send chat message: sendResponse called without a reconciled session ` +\n `for conversation ${conversationId}. Wait for an inbound webhook or call ` +\n `initiateOutboundConversation first.`\n );\n }\n\n const customerParticipantId = session.authorInfo.participantId;\n const agentParticipantId = session.aiAgentInfo.participantId;\n if (!customerParticipantId || !agentParticipantId) {\n throw new Error(\n `Unable to send chat message: session for conversation ${conversationId} is ` +\n `missing participant ids.`\n );\n }\n\n // channelId (Chat Channel SID) is required for CHAT delivery — the V1\n // Chat backend uses it to pick the destination thread. Inbound webhooks\n // always populate it, so a missing value here is a misuse.\n const chatChannelSid =\n typeof session.metadata?.channelId === 'string' ? session.metadata.channelId : undefined;\n\n if (!chatChannelSid) {\n throw new Error(\n \"Missing required session.metadata['channelId'] for chat sendResponse; \" +\n 'this is normally populated by an inbound webhook. Ensure an inbound ' +\n 'message has been processed before calling sendResponse, or set ' +\n \"session.metadata['channelId'] explicitly in advanced usage.\"\n );\n }\n\n const channelSettings: ActionChannelSettings = {\n channelId: chatChannelSid,\n };\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n recipient_participant_id: customerParticipantId,\n agent_participant_id: agentParticipantId,\n channel_id: chatChannelSid,\n },\n 'Sending chat message via Actions API'\n );\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: {\n channel: 'CHAT',\n participantId: agentParticipantId,\n },\n to: [\n {\n channel: 'CHAT',\n participantId: customerParticipantId,\n },\n ],\n content: { text: message },\n channelSettings,\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n { conversation_id: conversationId, channel_id: chatChannelSid },\n 'Chat message sent successfully via Actions API'\n );\n } catch (error) {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Send response error');\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n }\n\n /**\n * Initiate an outbound chat conversation\n *\n * Creates a conversation via Conversation Orchestrator, adds customer and\n * agent participants, then sends the initial message via the Actions API.\n * The sender is always this channel's configured `agentAddress`.\n */\n public async initiateOutboundConversation(\n options: InitiateChatConversationOptions\n ): Promise<InitiateConversationResult> {\n const validated = InitiateChatConversationOptionsSchema.parse(options);\n\n this.logger.info(\n { to: maskAddress(validated.to), channel_id: validated.channelId },\n 'Initiating outbound chat conversation'\n );\n\n return this.initiateOutboundMessagingConversation({\n channel: 'CHAT',\n to: validated.to,\n from: this.agentAddress,\n message: validated.message,\n ...(validated.metadata ? { metadata: validated.metadata } : {}),\n channelId: validated.channelId,\n channelSettings: {\n channelId: validated.channelId,\n },\n });\n }\n}\n","/**\n * URL builders for Twilio Studio handoff.\n *\n * Shared between the tools package (digital handoff POSTs) and the server\n * package (voice `<Connect action>` URL).\n */\n\n/**\n * Build the Twilio Studio Flow Executions URL for a given Flow SID.\n *\n * Used for digital (messaging/chat) handoff — POST the handoff payload\n * to this URL to start a Studio flow execution.\n */\nexport function studioExecutionsUrl(flowSid: string): string {\n return `https://studio.twilio.com/v2/Flows/${flowSid}/Executions`;\n}\n\n/**\n * Build the Twilio Studio Flow voice webhook URL for a given Flow SID.\n *\n * Used as the `<Connect action=...>` URL in TwiML for voice handoff,\n * so that when ConversationRelay ends the session Twilio triggers the\n * Studio flow for an incoming call.\n */\nexport function studioVoiceHandoffUrl(accountSid: string, flowSid: string): string {\n return `https://webhooks.twilio.com/v1/Accounts/${accountSid}/Flows/${flowSid}?Trigger=incomingCall`;\n}\n","import { WebSocket } from 'ws';\nimport VoiceResponse from 'twilio/lib/twiml/VoiceResponse.js';\nimport Twilio from 'twilio';\nimport {\n ChannelType,\n ConversationId,\n ConversationSession,\n ProfileId,\n WebSocketMessageSchema,\n PromptMessage,\n InterruptMessage,\n TextTokenMessage,\n CustomParameters,\n ConversationRelayConfig,\n ConversationRelayConfigSchema,\n ConversationRelayCallbackPayload,\n InitiateVoiceConversationOptions,\n InitiateVoiceConversationOptionsSchema,\n TwiMLOptions,\n TwiMLRequest,\n ConversationWebhookPayload,\n CallOptions,\n CallEventKind,\n CallStatusEvent,\n AmdEvent,\n RecordingEvent,\n CallOptionsSchema,\n callOptionsToCreateParams,\n callStatusEventFromForm,\n amdEventFromForm,\n recordingEventFromForm,\n} from '../types/index';\nimport type { InitiateVoiceConversationResult } from '../types/conversation';\nimport { BaseChannel, BaseChannelEvents, BaseChannelOptions } from './base';\nimport type { TAC } from '../lib/tac';\nimport { TACMemoryResponse } from '../lib/tac-memory-response';\nimport { maskAddress, redactTwimlParameters } from '../util/log-redaction';\nimport { studioVoiceHandoffUrl } from '../util/handoff-urls';\n\n/** Fixed default welcome greeting applied when no layer sets one. */\nconst DEFAULT_WELCOME_GREETING = 'Hello! How can I assist you today?';\n\n/** Poll window from call-connect: 10 attempts, 250ms doubling to a 1.5s cap (~11s). */\nconst POLL_ATTEMPTS = 10;\nconst POLL_BASE_DELAY_MS = 250;\nconst POLL_MAX_DELAY_MS = 1500;\n\n/**\n * Configuration for the Voice channel.\n *\n * `defaultTwimlOptions` is one of several TwiML layers that merge per-field;\n * see `handleIncomingCall` (inbound) and `initiateOutboundConversation`\n * (outbound) for the full precedence order.\n */\nexport interface VoiceChannelConfig extends BaseChannelOptions {\n /**\n * Static `TwiMLOptions` applied to every call (inbound and outbound).\n * Controls the TwiML inside `<ConversationRelay>` — voice, language,\n * transcription provider, welcomeGreeting, `<Language>` children, etc. Use\n * this when the same ConversationRelay configuration is correct for every call.\n *\n * Per-call inbound customization is registered via\n * `VoiceChannel.onInboundCallTwiml(...)` (not on this config).\n *\n * Note: `customParameters` and `languages` replace wholesale when a\n * higher-priority layer sets them.\n */\n defaultTwimlOptions?: TwiMLOptions;\n\n /**\n * Static {@link CallOptions} applied to every outbound call — the\n * `calls.create` parameters, including the call-event callback URLs. This is\n * the layer to use for a custom server or non-default routes: URLs set here\n * override the ones TAC would derive from `voicePublicDomain` +\n * `voiceCallEventPath`.\n */\n defaultCallOptions?: CallOptions;\n}\n\n/**\n * Callback that produces per-call overrides for the TwiML inside\n * `<ConversationRelay>` on inbound calls. Receives a framework-neutral\n * {@link TwiMLRequest} and returns {@link TwiMLOptions}.\n */\nexport type InboundCallTwimlHandler = (req: TwiMLRequest) => Promise<TwiMLOptions>;\n\n/** Handler for Twilio `statusCallback` webhooks. */\nexport type CallStatusHandler = (event: CallStatusEvent) => Promise<void> | void;\n\n/** Handler for Twilio `asyncAmdStatusCallback` webhooks. */\nexport type AmdHandler = (event: AmdEvent) => Promise<void> | void;\n\n/** Handler for Twilio `recordingStatusCallback` webhooks. */\nexport type RecordingHandler = (event: RecordingEvent) => Promise<void> | void;\n\n/**\n * Stringify a custom-parameter value for emission as a `<Parameter value=...>`.\n * Parameter values are scalars in practice; objects are JSON-encoded rather\n * than producing '[object Object]'.\n */\nfunction stringifyParameterValue(value: unknown): string {\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n // string | number | boolean | bigint | symbol — all safely stringifiable.\n return String(value as string | number | boolean | bigint);\n}\n\n/**\n * Voice channel event callbacks extending base callbacks\n */\nexport interface VoiceChannelEvents extends BaseChannelEvents {\n onSetup?: (data: {\n callSid: string;\n from: string;\n to: string;\n customParameters: Record<string, unknown> | undefined;\n }) => void;\n onPrompt?: (data: {\n conversationId: ConversationId;\n transcript: string;\n userMemory?: TACMemoryResponse;\n session?: ConversationSession;\n abortSignal: AbortSignal;\n }) => Promise<void> | void;\n onInterrupt?: (data: {\n conversationId: ConversationId;\n utteranceUntilInterrupt: string | undefined;\n durationUntilInterruptMs: number | undefined;\n }) => void;\n /**\n * Fired once the session and WebSocket registration exist — in orchestrated\n * mode possibly before the first prompt, since the lookup starts at setup.\n */\n onWebSocketConnected?: (data: { conversationId: ConversationId }) => void;\n onWebSocketDisconnected?: (data: { conversationId: ConversationId }) => void;\n}\n\n/**\n * Voice Channel implementation for Twilio ConversationRelay\n *\n * Handles voice conversations through WebSocket connections.\n * Manages real-time audio streaming and conversation state.\n */\nexport interface StreamTask {\n controller: AbortController;\n hasSentTokens: boolean;\n}\n\nexport class VoiceChannel extends BaseChannel {\n private readonly webSocketConnections: Map<ConversationId, WebSocket>;\n private readonly voiceCallbacks: VoiceChannelEvents;\n private readonly streamTasks: Map<ConversationId, StreamTask>;\n private readonly promptQueues: Map<ConversationId, Promise<void>>;\n private readonly initializationRetries: Map<string, number>;\n private readonly callSidToConversationId: Map<string, ConversationId>;\n private readonly MAX_INITIALIZATION_RETRIES = 3;\n private twilioClient: ReturnType<typeof Twilio> | undefined;\n private readonly voiceConfig: VoiceChannelConfig;\n private onInboundCallTwimlHandler: InboundCallTwimlHandler | undefined;\n private onCallStatusHandler: CallStatusHandler | undefined;\n private onAmdHandler: AmdHandler | undefined;\n private onRecordingHandler: RecordingHandler | undefined;\n\n constructor(tac: TAC, options?: VoiceChannelConfig) {\n super(tac, options);\n this.voiceConfig = options ?? {};\n this.webSocketConnections = new Map();\n this.voiceCallbacks = {};\n this.streamTasks = new Map();\n this.promptQueues = new Map();\n this.initializationRetries = new Map();\n this.callSidToConversationId = new Map();\n }\n\n /**\n * Register a callback that produces per-call overrides for the TwiML inside\n * `<ConversationRelay>` on inbound calls.\n *\n * The callback receives a framework-neutral {@link TwiMLRequest} (parsed from\n * the Twilio webhook form) and returns {@link TwiMLOptions}. Fields the\n * callback explicitly sets override `defaultTwimlOptions` and TAC defaults;\n * unset fields fall through.\n *\n * @example\n * ```typescript\n * voiceChannel.onInboundCallTwiml(async req => {\n * if (req.callerCountry === 'MX') {\n * return { language: 'es-MX', welcomeGreeting: '¡Hola!' };\n * }\n * return {};\n * });\n * ```\n *\n * Outbound calls don't use this — pass per-call TwiML via\n * `InitiateVoiceConversationOptions.twimlOptions` directly.\n */\n public onInboundCallTwiml(callback: InboundCallTwimlHandler): void {\n this.onInboundCallTwimlHandler = callback;\n }\n\n /**\n * Register a handler for Twilio `statusCallback` webhooks.\n *\n * This is the Calls-API status callback (call disposition), not the\n * ConversationRelay session callback — see\n * {@link handleConversationRelayCallback}.\n *\n * Registering does two things: it stores the handler, and it makes later\n * outbound calls pass `statusCallback` to `calls.create`. With no handler\n * registered TAC omits that parameter, so Twilio has nowhere to post and the\n * event never arrives.\n *\n * Twilio reports only the terminal event by default, which covers every\n * disposition; set `CallOptions.statusCallbackEvent` for ringing/answered.\n *\n * @example\n * ```typescript\n * voiceChannel.onCallStatus(async event => {\n * if (event.isUnreached) {\n * // queue a retry\n * }\n * });\n * ```\n */\n public onCallStatus(callback: CallStatusHandler): void {\n this.onCallStatusHandler = callback;\n }\n\n /**\n * Register a handler for Twilio `asyncAmdStatusCallback` webhooks.\n *\n * Registering makes later outbound calls pass `asyncAmdStatusCallback` to\n * `calls.create`; without a handler TAC omits it and Twilio has nowhere to\n * post the result. It does not enable detection — that's per-call, via\n * `CallOptions.machineDetection` and `asyncAmd`, both of which are required\n * for this to fire (at most once per call).\n *\n * @example\n * ```typescript\n * voiceChannel.onAmd(async event => {\n * if (event.isMachine) {\n * await voiceChannel.endCall(event.callSid); // voicemail → hang up\n * }\n * });\n * ```\n */\n public onAmd(callback: AmdHandler): void {\n this.onAmdHandler = callback;\n }\n\n /**\n * Register a handler for Twilio `recordingStatusCallback` webhooks.\n *\n * Registering makes later outbound calls pass `recordingStatusCallback` to\n * `calls.create`; without a handler TAC omits it and Twilio has nowhere to\n * post. It does not start recording — that's `CallOptions.record`, which is\n * required for this to fire.\n *\n * @example\n * ```typescript\n * voiceChannel.onRecording(async event => {\n * if (event.recordingStatus === 'completed') {\n * // store event.recordingUrl\n * }\n * });\n * ```\n */\n public onRecording(callback: RecordingHandler): void {\n this.onRecordingHandler = callback;\n }\n\n /**\n * Resolve the public WebSocket URL from `TACConfig.voicePublicDomain` +\n * `TACConfig.voiceWebsocketPath`. Throws if `voicePublicDomain` isn't set.\n */\n private resolveWebsocketUrl(action: string): string {\n if (this.config.voicePublicDomain) {\n return `wss://${this.config.voicePublicDomain}${this.config.voiceWebsocketPath}`;\n }\n throw new Error(\n `${action} needs a WebSocket URL. Set TWILIO_VOICE_PUBLIC_DOMAIN ` +\n '(or TACConfig.voicePublicDomain).'\n );\n }\n\n /**\n * Resolve the default `<Connect action=...>` cleanup URL.\n *\n * Returns undefined if `voicePublicDomain` isn't set; that's fine because\n * actionUrl has higher-priority layers (customizer, twimlOptions, Studio\n * handoff) above this fallback.\n */\n private resolveDefaultActionUrl(): string | undefined {\n if (this.config.voicePublicDomain) {\n return `https://${this.config.voicePublicDomain}${this.config.voiceActionPath}`;\n }\n return undefined;\n }\n\n private getTwilioClient(): ReturnType<typeof Twilio> {\n if (!this.twilioClient) {\n this.twilioClient = Twilio(this.config.apiKey, this.config.apiSecret, {\n accountSid: this.config.accountSid,\n });\n }\n return this.twilioClient;\n }\n\n public get channelType(): ChannelType {\n return 'voice';\n }\n\n /**\n * Register event callbacks (override for Voice-specific events)\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Generic event callback needs to accept any args\n public override on(event: string, callback: (...args: any[]) => void): void {\n switch (event) {\n case 'setup':\n this.voiceCallbacks.onSetup = callback;\n break;\n case 'prompt':\n this.voiceCallbacks.onPrompt = callback;\n break;\n case 'interrupt':\n this.voiceCallbacks.onInterrupt = callback;\n break;\n case 'webSocketConnected':\n this.voiceCallbacks.onWebSocketConnected = callback;\n break;\n case 'webSocketDisconnected':\n this.voiceCallbacks.onWebSocketDisconnected = callback;\n break;\n default:\n // Delegate to parent for base events\n super.on(event, callback);\n break;\n }\n }\n\n /**\n * Process conversation webhooks for cleanup.\n *\n * Voice channel processes CONVERSATION_UPDATED events:\n * - CLOSED status: Clean up local session state\n *\n * Note: Conversation tracking uses instance-local memory. In multi-instance\n * deployments, webhooks may route to a different instance, preventing cleanup.\n *\n * @param payload - Raw webhook event data from Twilio\n * @param idempotencyToken - Optional Twilio idempotency token from request headers\n */\n public async processWebhook(payload: unknown, idempotencyToken?: string): Promise<void> {\n try {\n const result = this.preprocessWebhook(payload, idempotencyToken);\n if (!result) {\n return;\n }\n\n const { webhookData, eventType, conversationId } = result;\n\n switch (eventType) {\n case 'CONVERSATION_UPDATED':\n this.logger.debug(\n { conversation_id: conversationId, status: webhookData.data?.status },\n 'Handling CONVERSATION_UPDATED'\n );\n await this.handleConversationUpdated(webhookData);\n break;\n\n default:\n this.logger.debug(\n {\n event_type: eventType,\n raw_event_type: webhookData.eventType,\n conversation_id: conversationId,\n },\n 'Unhandled event type - this event will be ignored'\n );\n }\n\n this.logger.debug({ event_type: eventType }, 'Webhook processing completed');\n } catch (error) {\n // Remove the token so retries are not blocked\n if (idempotencyToken) {\n this.removeWebhookToken(idempotencyToken);\n }\n this.handleError(error instanceof Error ? error : new Error(String(error)), { payload });\n }\n }\n\n /**\n * Handle conversation updated event\n */\n private async handleConversationUpdated(payload: ConversationWebhookPayload): Promise<void> {\n const conversationId = this.extractConversationId(payload);\n\n if (!conversationId) {\n throw new Error('Missing conversation ID in conversation.updated event');\n }\n\n // Check if conversation is closed\n if (payload.data?.status === 'CLOSED') {\n this.logger.debug(\n { conversation_id: conversationId, status: payload.data.status },\n 'Conversation closed, cleaning up'\n );\n await this.endConversation(conversationId);\n } else if (payload.data?.status === 'INACTIVE') {\n // \"once\" mode: drop the cache so the next message re-fetches.\n this.invalidateCachedMemory(conversationId);\n }\n }\n\n /**\n * Get active WebSocket connection for a conversation\n */\n public getWebsocket(conversationId: ConversationId): WebSocket | null {\n return this.webSocketConnections.get(conversationId) || null;\n }\n\n /**\n * Poll Conversation Orchestrator for the conversation ConversationRelay\n * created for `callSid`, then register the local session and WebSocket.\n * Runs in the background from `setup`, so those can exist before the\n * caller speaks.\n */\n private async initializeOrchestratedConversation(\n callSid: string,\n fromNumber: string | null,\n ws: WebSocket\n ): Promise<ConversationId> {\n if (!this.conversationClient) {\n throw new Error('Conversation client is required in orchestrated mode');\n }\n\n let conversations: Awaited<ReturnType<typeof this.conversationClient.listConversations>> = [];\n\n for (let attempt = 0; attempt < POLL_ATTEMPTS; attempt++) {\n // ACTIVE only: a stale conversation on the same CallSid would break the\n // \"exactly 1\" check below.\n conversations = await this.conversationClient.listConversations({\n channelId: callSid,\n status: ['ACTIVE'],\n });\n if (conversations.length === 1) break;\n if (attempt < POLL_ATTEMPTS - 1) {\n this.logger.debug(\n { call_sid: callSid, attempt: attempt + 1, found: conversations.length },\n 'Conversation not ready yet, polling again'\n );\n const delayMs = Math.min(POLL_BASE_DELAY_MS * 2 ** attempt, POLL_MAX_DELAY_MS);\n await new Promise(resolve => setTimeout(resolve, delayMs));\n }\n }\n\n if (conversations.length !== 1) {\n throw new Error(\n `Expected exactly 1 conversation for callSid ${callSid}, ` +\n `but found ${conversations.length} after ${POLL_ATTEMPTS} attempts`\n );\n }\n\n const conversation = conversations[0]!;\n const conversationId = conversation.id as ConversationId;\n\n const participants = await this.conversationClient.listParticipants(conversationId);\n\n const customerParticipant = participants.find(p => p.type === 'CUSTOMER');\n const customerAddress =\n customerParticipant?.addresses?.find(a => a.channel === 'VOICE')?.address ??\n fromNumber ??\n undefined;\n const profileId: ProfileId | undefined = customerParticipant?.profileId\n ? (customerParticipant.profileId as ProfileId)\n : undefined;\n\n this.webSocketConnections.set(conversationId, ws);\n this.callSidToConversationId.set(callSid, conversationId);\n const session = this.startConversation(conversationId, profileId);\n // conversationId is the Orchestrator's, so record the CallSid too —\n // out-of-band call webhooks resolve via getConversationSessionByCallSid.\n session.callSid = callSid;\n\n if (customerAddress) {\n session.authorInfo = {\n address: customerAddress,\n };\n }\n\n if (this.voiceCallbacks.onWebSocketConnected) {\n this.voiceCallbacks.onWebSocketConnected({ conversationId });\n }\n\n return conversationId;\n }\n\n /**\n * Handle WebSocket connection from ConversationRelay\n */\n public handleWebSocketConnection(ws: WebSocket): void {\n let conversationId: ConversationId | null = null;\n let callSid: string | null = null;\n let fromNumber: string | null = null;\n let initializationFailed = false;\n // Background conversation lookup started on `setup`; cleared once claimed,\n // by the first prompt or by the close handler.\n let initPromise: Promise<ConversationId> | null = null;\n\n ws.on('message', (data: Buffer) => {\n (async (): Promise<void> => {\n try {\n const messageData = JSON.parse(data.toString()) as unknown;\n const result = WebSocketMessageSchema.safeParse(messageData);\n\n if (!result.success) {\n this.logger.debug(\n {\n validation_errors: result.error.issues.map(issue => ({\n path: issue.path.join('.'),\n message: issue.message,\n })),\n },\n 'Invalid or unrecognized WebSocket message, skipping'\n );\n return;\n }\n\n const message = result.data;\n\n switch (message.type) {\n case 'setup':\n callSid = message.callSid;\n fromNumber = message.from;\n\n // ConversationRelay creates the conversation at call-connect, so\n // start the lookup now and let it overlap the wait for the\n // caller's first utterance instead of delaying it.\n if (this.tac.isOrchestratorEnabled()) {\n this.logger.debug(\n { call_sid: callSid },\n 'Starting background conversation initialization'\n );\n initPromise = this.initializeOrchestratedConversation(callSid, fromNumber, ws);\n // Marks it handled; whoever claims it still sees the rejection.\n void initPromise.catch(() => undefined);\n }\n\n if (this.voiceCallbacks.onSetup) {\n this.voiceCallbacks.onSetup({\n callSid,\n from: message.from,\n to: message.to,\n customParameters: message.customParameters,\n });\n }\n break;\n\n case 'prompt':\n if (!conversationId && callSid) {\n // Check retry limit before attempting initialization\n const retryCount = this.initializationRetries.get(callSid) ?? 0;\n if (retryCount >= this.MAX_INITIALIZATION_RETRIES) {\n throw new Error(\n `Cannot process prompt - conversation initialization failed after ${retryCount} attempts for callSid ${callSid}`\n );\n }\n\n try {\n if (initializationFailed) {\n this.logger.info(\n { call_sid: callSid, retry_count: retryCount },\n 'Retrying conversation initialization after previous failure'\n );\n }\n\n if (!this.tac.isOrchestratorEnabled()) {\n // Voice-only mode: use callSid as conversationId directly\n conversationId = callSid as ConversationId;\n this.webSocketConnections.set(conversationId, ws);\n this.callSidToConversationId.set(callSid, conversationId);\n const session = this.startConversation(conversationId);\n // Relay-only: conversationId === callSid.\n session.callSid = callSid;\n\n if (fromNumber) {\n session.authorInfo = { address: fromNumber };\n }\n\n if (this.voiceCallbacks.onWebSocketConnected) {\n this.voiceCallbacks.onWebSocketConnected({ conversationId });\n }\n } else {\n // Await the lookup from `setup` — usually already done.\n // Stays visible to the close handler while awaited, so a\n // hangup mid-lookup still cleans up; cleared after so a\n // retry starts fresh and `close` uses conversationId.\n initPromise ??= this.initializeOrchestratedConversation(\n callSid,\n fromNumber,\n ws\n );\n try {\n conversationId = await initPromise;\n } finally {\n initPromise = null;\n }\n }\n\n // Success! Clear retry count and failed flag\n initializationFailed = false;\n this.initializationRetries.delete(callSid);\n this.logger.info(\n { conversation_id: conversationId, call_sid: callSid },\n 'Conversation initialization succeeded'\n );\n } catch (err) {\n initializationFailed = true;\n this.initializationRetries.set(callSid, retryCount + 1);\n this.logger.error(\n { err, call_sid: callSid, retry_count: retryCount + 1 },\n 'Conversation initialization failed'\n );\n throw err;\n }\n }\n\n if (conversationId) {\n const previousPrompt = this.promptQueues.get(conversationId) ?? Promise.resolve();\n const currentPrompt = previousPrompt\n .then(() => this.handlePromptMessage(conversationId!, message))\n .catch((err: unknown) => {\n this.handleError(err instanceof Error ? err : new Error(String(err)), {\n conversationId,\n message: data.toString(),\n });\n });\n this.promptQueues.set(conversationId, currentPrompt);\n } else {\n this.logger.warn('Received prompt before conversation initialized');\n }\n break;\n\n case 'interrupt':\n if (conversationId) {\n this.handleInterruptMessage(conversationId, message);\n }\n break;\n\n default:\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_type: (messageData as Record<string, unknown>)?.type,\n },\n 'Unhandled WebSocket event type'\n );\n break;\n }\n } catch (error) {\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n callSid,\n message: data.toString(),\n });\n }\n })().catch((err: unknown) => {\n this.logger.error({ err }, 'Unhandled error in WebSocket message handler');\n });\n });\n\n ws.on('close', () => {\n // Call ended before any prompt claimed the lookup. A promise can't be\n // cancelled, so adopt what it registers and tear that down, or the\n // WebSocket registration leaks. The conversation stays tracked (CLOSED).\n const pendingInit = initPromise;\n initPromise = null;\n if (pendingInit && !conversationId) {\n void pendingInit\n .then(async adoptedId => {\n await this.handleWebSocketDisconnect(adoptedId);\n if (callSid) this.callSidToConversationId.delete(callSid);\n })\n // No prompt ever arrived to surface a lookup failure, so log here.\n .catch((err: unknown) => {\n this.logger.error(\n { err, call_sid: callSid },\n 'Background conversation initialization failed after the call ended'\n );\n });\n }\n\n if (conversationId) {\n void this.handleWebSocketDisconnect(conversationId).catch((err: unknown) => {\n this.logger.error(\n { err, conversation_id: conversationId },\n 'WebSocket disconnect handler error'\n );\n });\n }\n if (callSid) {\n this.initializationRetries.delete(callSid);\n this.callSidToConversationId.delete(callSid);\n }\n });\n\n ws.on('error', (error: Error) => {\n this.handleError(error, { conversationId });\n });\n }\n\n /**\n * Handle WebSocket prompt message (user speech)\n */\n private async handlePromptMessage(\n conversationId: ConversationId,\n message: PromptMessage\n ): Promise<void> {\n const transcript = message.voicePrompt;\n\n // Start a new stream task so the AbortSignal is available to handlers.\n // startStreamTask() cancels any existing task internally.\n const streamTask = this.startStreamTask(conversationId);\n\n // Get session for memory retrieval\n const session = this.getConversationSession(conversationId);\n\n // Retrieve memory if enabled via memoryMode\n const userMemory = session\n ? await this.retrieveMemoryIfEnabled(session, transcript)\n : undefined;\n\n if (this.voiceCallbacks.onPrompt) {\n await this.voiceCallbacks.onPrompt({\n conversationId,\n transcript,\n abortSignal: streamTask.controller.signal,\n ...(userMemory !== undefined && { userMemory }),\n ...(session !== undefined && { session }),\n });\n }\n }\n\n /**\n * Handle WebSocket interrupt message\n */\n private handleInterruptMessage(conversationId: ConversationId, message: InterruptMessage): void {\n const { utteranceUntilInterrupt, durationUntilInterruptMs } = message;\n\n // Check whether tokens were sent before cancelling (cancel deletes the entry)\n const streamTask = this.streamTasks.get(conversationId);\n const wasStreaming = streamTask?.hasSentTokens ?? false;\n\n // Cancel any in-flight stream task on interrupt\n const cancelled = this.cancelStreamTask(conversationId);\n if (cancelled) {\n this.logger.info(\n { conversation_id: conversationId },\n 'Cancelled stream task due to interrupt'\n );\n }\n\n // Finalize the interrupted token stream so ConversationRelay stops\n // waiting for more tokens. Only needed when tokens were actually sent;\n // sending last:true without a preceding stream creates a spurious empty turn.\n if (cancelled && wasStreaming) {\n const ws = this.webSocketConnections.get(conversationId);\n if (ws?.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify({ type: 'text', token: '', last: true }));\n } catch (err) {\n this.logger.debug(\n { conversation_id: conversationId, err },\n 'WebSocket closed before sending stream finalization'\n );\n }\n }\n }\n\n if (this.voiceCallbacks.onInterrupt) {\n this.voiceCallbacks.onInterrupt({\n conversationId,\n utteranceUntilInterrupt,\n durationUntilInterruptMs,\n });\n }\n }\n\n /**\n * Handle WebSocket disconnection. In orchestrated mode the conversation stays\n * tracked until the CLOSED webhook (so a follow-up call can reuse it); in\n * voice-only mode there is no such webhook, so it ends here.\n */\n private async handleWebSocketDisconnect(conversationId: ConversationId): Promise<void> {\n this.cancelStreamTask(conversationId);\n this.webSocketConnections.delete(conversationId);\n this.promptQueues.delete(conversationId);\n\n if (this.voiceCallbacks.onWebSocketDisconnected) {\n this.voiceCallbacks.onWebSocketDisconnected({ conversationId });\n }\n\n if (!this.tac.isOrchestratorEnabled()) {\n await this.endConversation(conversationId);\n }\n }\n\n /**\n * Send voice response via WebSocket\n */\n public sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n try {\n const ws = this.webSocketConnections.get(conversationId);\n\n if (ws?.readyState !== WebSocket.OPEN) {\n throw new Error(`No active WebSocket connection for conversation ${conversationId}`);\n }\n\n const response: TextTokenMessage = {\n type: 'text',\n token: message,\n last: true,\n };\n\n ws.send(JSON.stringify(response));\n\n // If a handoff is pending, send the WS \"end\" message now that the\n // LLM's final response has been delivered to the caller.\n const session = this.getConversationSession(conversationId);\n if (session?.pendingHandoffData) {\n try {\n ws.send(JSON.stringify(session.pendingHandoffData));\n delete session.pendingHandoffData;\n } catch (err) {\n this.logger.warn(\n { err, conversation_id: conversationId },\n 'WebSocket closed before sending handoff end message; caller will not be transferred'\n );\n }\n }\n\n return Promise.resolve();\n } catch (error) {\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n }\n\n /**\n * Send a streaming voice response via WebSocket, token by token.\n *\n * Each chunk from the iterable is sent as a text token message with last: false.\n * After the iterable completes, a final empty marker with last: true is sent\n * only if at least one token was emitted. If the AbortSignal fires (e.g., user\n * interrupted), iteration stops and no final marker is sent (the interrupt\n * handler sends the finalization instead).\n *\n * @returns The accumulated full response text.\n */\n public async sendStreamingResponse(\n conversationId: ConversationId,\n stream: AsyncIterable<string>,\n options?: { signal?: AbortSignal }\n ): Promise<string> {\n const ws = this.webSocketConnections.get(conversationId);\n\n if (ws?.readyState !== WebSocket.OPEN) {\n throw new Error(`No active WebSocket connection for conversation ${conversationId}`);\n }\n\n const activeTask = this.streamTasks.get(conversationId);\n const signal = options?.signal ?? activeTask?.controller.signal;\n let fullResponse = '';\n let hasSentTokens = false;\n\n if (signal?.aborted) {\n return fullResponse;\n }\n\n try {\n for await (const chunk of stream) {\n if (signal?.aborted) {\n break;\n }\n\n if (ws.readyState !== WebSocket.OPEN) {\n this.logger.info(\n { conversation_id: conversationId },\n 'WebSocket closed during streaming'\n );\n break;\n }\n\n fullResponse += chunk;\n const tokenMessage: TextTokenMessage = {\n type: 'text',\n token: chunk,\n last: false,\n };\n ws.send(JSON.stringify(tokenMessage));\n hasSentTokens = true;\n if (activeTask) {\n activeTask.hasSentTokens = true;\n }\n }\n\n if (!signal?.aborted && hasSentTokens && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'text', token: '', last: true }));\n }\n } catch (error) {\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n });\n throw error;\n } finally {\n // Only clean up if we still own the active stream task.\n // A new prompt may have replaced it while we were unwinding.\n if (activeTask && this.streamTasks.get(conversationId) === activeTask) {\n this.completeStreamTask(conversationId);\n }\n }\n\n return fullResponse;\n }\n\n // =========================================================================\n // Incoming Call Handling\n // =========================================================================\n\n /**\n * Generate the TwiML response for an incoming voice call.\n *\n * ConversationRelay automatically handles conversation creation and\n * participant management via the `conversationConfiguration` parameter.\n *\n * The WebSocket URL and default session-cleanup action URL are derived from\n * `TACConfig.voicePublicDomain` + `TACConfig.voiceWebsocketPath` /\n * `voiceActionPath`.\n *\n * TwiML fields are merged per-field, highest precedence first:\n * 1. Output of the customizer registered via\n * `VoiceChannel.onInboundCallTwiml(...)` if configured and `twimlRequest`\n * is given. (Application-owned.)\n * 2. `VoiceChannelConfig.defaultTwimlOptions` — per-channel defaults.\n * 3. `hostTwimlOptions` — per-call transport facts supplied by the host (the\n * code owning the route), e.g. a per-call `websocketUrl` with an affinity\n * token.\n * 4. TAC defaults: a fixed default welcomeGreeting, `conversationConfiguration`\n * from `TACConfig`, `actionUrl` resolved via Studio handoff (when\n * `studioHandoffFlowSid` is configured), else derived from\n * `TACConfig.voicePublicDomain` + `voiceActionPath`, and the `websocketUrl`\n * derived from `TACConfig.voicePublicDomain` + `voiceWebsocketPath`.\n *\n * Fields not set at a layer fall through to lower layers. Arrays (`languages`)\n * and nested objects (`customParameters`) replace wholesale when set at a\n * higher-priority layer. `websocketUrl` falls back to the `TACConfig`-derived\n * URL if unset at every layer.\n *\n * @param twimlRequest - Parsed Twilio webhook fields. Passed to the customizer\n * if one is configured on the channel.\n * @param options - Additional per-call inputs.\n * @param options.hostTwimlOptions - Per-call TwiML supplied by a custom\n * in-process host (e.g. an affinity-routed deployment injecting a per-call\n * `websocketUrl`), layered below `defaultTwimlOptions` and the application\n * customizer but above the TAC defaults.\n * @returns TwiML XML string for call connection.\n */\n public async handleIncomingCall(\n twimlRequest?: TwiMLRequest,\n options?: { hostTwimlOptions?: TwiMLOptions }\n ): Promise<string> {\n let customized: TwiMLOptions | undefined;\n if (this.onInboundCallTwimlHandler && twimlRequest) {\n customized = await this.onInboundCallTwimlHandler(twimlRequest);\n }\n\n const merged = this.buildTwimlOptions(options?.hostTwimlOptions, customized);\n const websocketUrl = merged.websocketUrl ?? this.resolveWebsocketUrl('handleIncomingCall');\n return this.generateTwiml(websocketUrl, merged);\n }\n\n /**\n * Layer TwiML options, lowest precedence first: TAC defaults → `host`\n * (calling host's per-call values) → channel `defaultTwimlOptions` → `perCall`\n * (application customizer output for inbound, or\n * `InitiateVoiceConversationOptions.twimlOptions` for outbound).\n */\n private buildTwimlOptions(\n host: TwiMLOptions | undefined,\n perCall: TwiMLOptions | undefined\n ): TwiMLOptions {\n const merged: TwiMLOptions = {\n welcomeGreeting: DEFAULT_WELCOME_GREETING,\n ...(this.tac.isOrchestratorEnabled() && this.config.conversationConfigurationId !== undefined\n ? { conversationConfiguration: this.config.conversationConfigurationId }\n : {}),\n };\n const resolvedActionUrl = this.resolveActionUrl(host, perCall);\n if (resolvedActionUrl !== undefined) {\n merged.actionUrl = resolvedActionUrl;\n }\n if (host) {\n this.overlayFields(merged, host);\n }\n if (this.voiceConfig.defaultTwimlOptions) {\n this.overlayFields(merged, this.voiceConfig.defaultTwimlOptions);\n }\n if (perCall) {\n this.overlayFields(merged, perCall);\n }\n return merged;\n }\n\n /**\n * Apply fields explicitly present on `source` onto `target`.\n *\n * Nested objects (`customParameters`), arrays (`languages`), and dicts\n * (`extra`) replace wholesale — there's no per-key merging.\n *\n * `actionUrl` is skipped here on purpose — it's resolved once via\n * `resolveActionUrl` looking at every layer at once, and that resolved value\n * is written into `target` before this overlay runs. Letting it through here\n * would let a higher-priority layer that didn't set actionUrl silently clobber\n * a lower layer that did.\n *\n * \"Explicitly present\" is detected via key presence (`key in source`), which\n * mirrors Python's `model_fields_set`: a key set to `undefined` is still\n * \"present\" and overrides lower layers, while an absent key falls through.\n */\n private overlayFields(target: TwiMLOptions, source: TwiMLOptions): void {\n for (const key of Object.keys(source) as (keyof TwiMLOptions)[]) {\n if (key === 'actionUrl') {\n continue;\n }\n // Index assignment across a heterogeneous record; both sides are TwiMLOptions.\n (target as Record<string, unknown>)[key] = (source as Record<string, unknown>)[key];\n }\n }\n\n /**\n * Resolve the TwiML `<Connect action=...>` URL.\n *\n * Precedence (highest to lowest):\n * 1. application customizer\n * 2. channel `defaultTwimlOptions`\n * 3. `host` (calling host's per-call options)\n * 4. Studio handoff (when `studioHandoffFlowSid` is configured)\n * 5. Channel default — derived from `TACConfig.voicePublicDomain` +\n * `TACConfig.voiceActionPath`.\n *\n * User-expressed intent (Studio handoff is configured explicitly on\n * `TACConfig`) beats the SDK's generated cleanup default.\n *\n * Explicit `actionUrl: undefined` on a layer (key present, value undefined)\n * suppresses `<Connect action=...>` entirely — all lower layers are skipped.\n * `actionUrl` left absent (key not present) falls through to the next layer.\n */\n private resolveActionUrl(\n host: TwiMLOptions | undefined,\n customized: TwiMLOptions | undefined\n ): string | undefined {\n if (customized && 'actionUrl' in customized) {\n return customized.actionUrl;\n }\n if (\n this.voiceConfig.defaultTwimlOptions &&\n 'actionUrl' in this.voiceConfig.defaultTwimlOptions\n ) {\n return this.voiceConfig.defaultTwimlOptions.actionUrl;\n }\n if (host && 'actionUrl' in host) {\n return host.actionUrl;\n }\n if (this.config.studioHandoffFlowSid) {\n return studioVoiceHandoffUrl(this.config.accountSid, this.config.studioHandoffFlowSid);\n }\n return this.resolveDefaultActionUrl();\n }\n\n // =========================================================================\n // Outbound Call Handling\n // =========================================================================\n\n /**\n * Overlay `perCall` onto `VoiceChannelConfig.defaultCallOptions`.\n *\n * Per-field via key presence, the same convention {@link overlayFields} uses\n * for TwiML options — so a per-call `{ machineDetection: undefined }`\n * explicitly clears the channel default rather than falling through to it.\n *\n * The result is always validated, for two reasons: a combination only\n * reachable by layering — per-call clearing `machineDetection` while the\n * default set `asyncAmd` — must still fail instead of reaching Twilio, and\n * `VoiceChannelConfig` is a plain interface, so `defaultCallOptions` has had\n * no runtime validation of its own.\n */\n private mergeCallOptions(perCall: CallOptions | undefined): CallOptions | undefined {\n const defaults = this.voiceConfig.defaultCallOptions;\n if (!defaults && !perCall) {\n return undefined;\n }\n\n const merged: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(defaults ?? {})) {\n if (value !== undefined) {\n merged[key] = value;\n }\n }\n for (const key of Object.keys(perCall ?? {})) {\n merged[key] = (perCall as Record<string, unknown>)[key];\n }\n return CallOptionsSchema.parse(merged);\n }\n\n /**\n * Build the extra arguments for `client.calls.create`.\n *\n * Layers, highest precedence first: this call's `callOptions`,\n * `VoiceChannelConfig.defaultCallOptions`, then callback URLs derived from\n * `voicePublicDomain` + `voiceCallEventPath`.\n *\n * A URL is derived only when its handler is registered. That's a deliberate\n * deviation from `websocketUrl` / `actionUrl`, which derive unconditionally:\n * those are load-bearing, so a wrong one fails loudly on the first call,\n * whereas an unwanted call-event URL fails as silent 11200 alerts for a\n * feature nobody asked for. Set the URLs in `defaultCallOptions` when TAC\n * isn't serving the routes.\n */\n private buildCallParams(callOptions: CallOptions | undefined): Record<string, unknown> {\n const merged = this.mergeCallOptions(callOptions);\n const params = merged ? callOptionsToCreateParams(merged) : {};\n\n const wiring: [CallEventKind, string, unknown][] = [\n ['status', 'statusCallback', this.onCallStatusHandler],\n ['amd', 'asyncAmdStatusCallback', this.onAmdHandler],\n ['recording', 'recordingStatusCallback', this.onRecordingHandler],\n ];\n for (const [kind, param, handler] of wiring) {\n if (!handler) continue;\n const url = this.config.callEventUrl(kind);\n // An explicit URL from either options layer is never overwritten.\n if (url !== undefined && params[param] === undefined) {\n params[param] = url;\n }\n }\n\n return params;\n }\n\n /**\n * Initiate an outbound voice conversation\n *\n * Places an outbound call with inline TwiML that connects to ConversationRelay.\n * The conversationConfiguration attribute tells CO to create and manage the\n * conversation during passive hydration. The session is initialized when the\n * background callSid lookup started at WebSocket setup finds it.\n *\n * TwiML fields are merged per-field, highest precedence first:\n * 1. `options.twimlOptions` — per-call overrides\n * 2. `VoiceChannelConfig.defaultTwimlOptions` — channel-wide defaults\n * 3. TAC defaults: welcome greeting, `conversationConfiguration` from\n * `TACConfig`, and `actionUrl` from Studio handoff (if configured), else\n * derived from `TACConfig.voicePublicDomain` + `voiceActionPath`.\n *\n * Calls-API parameters merge the same way:\n * 1. `options.callOptions` — per-call overrides\n * 2. `VoiceChannelConfig.defaultCallOptions` — channel-wide defaults\n * 3. Callback URLs derived from `TACConfig.voicePublicDomain` +\n * `voiceCallEventPath`, for handlers that are registered\n *\n * The WebSocket URL is derived from `TACConfig.voicePublicDomain` +\n * `TACConfig.voiceWebsocketPath`, unless overridden per-call via\n * `options.websocketUrl`.\n */\n public async initiateOutboundConversation(\n options: InitiateVoiceConversationOptions\n ): Promise<InitiateVoiceConversationResult> {\n const validated = InitiateVoiceConversationOptionsSchema.parse(options);\n const fromNumber = this.config.phoneNumber;\n\n this.logger.info(\n { to: validated.to, from: fromNumber },\n 'Initiating outbound voice conversation'\n );\n\n try {\n // Outbound has no inbound customizer and no host layer; the per-call\n // override is options.twimlOptions.\n const merged = this.buildTwimlOptions(undefined, validated.twimlOptions);\n\n // `options.websocketUrl` is the dedicated per-call outbound override and\n // wins over any websocketUrl that came through the layered twimlOptions\n // merge; both fall back to the TACConfig-derived URL.\n const websocketUrl =\n validated.websocketUrl ??\n merged.websocketUrl ??\n this.resolveWebsocketUrl('initiateOutboundConversation');\n const twiml = this.generateTwiml(websocketUrl, merged);\n const callParams = this.buildCallParams(validated.callOptions);\n\n // The inline TwiML handed to Twilio, useful for debugging the\n // <Connect action> handoff target. customParameters values are masked —\n // they're arbitrary developer data (profile IDs, caller names), unlike\n // the WS/action URLs and conversation config.\n this.logger.debug(\n { twiml: redactTwimlParameters(twiml), to: maskAddress(validated.to) },\n 'Outbound call TwiML'\n );\n\n // Place the outbound call with inline TwiML\n const client = this.getTwilioClient();\n const call = await client.calls.create({\n to: validated.to,\n from: fromNumber,\n twiml,\n ...callParams,\n });\n\n this.logger.info(\n { call_sid: call.sid, to: maskAddress(validated.to) },\n 'Outbound voice call placed'\n );\n\n return { callSid: call.sid };\n } catch (error) {\n this.logger.error(\n { err: error, to: maskAddress(validated.to) },\n 'Failed to initiate outbound call'\n );\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n to: validated.to,\n });\n throw error;\n }\n }\n\n // =========================================================================\n // ConversationRelay Callback Handling\n // =========================================================================\n\n /**\n * Handle ConversationRelay callback from Twilio. Cleans up on call completion\n * in voice-only mode; in orchestrated mode the CO webhook owns cleanup.\n *\n * @param payload - Callback payload from Twilio\n * @returns Response with status, content, and content type\n */\n public async handleConversationRelayCallback(\n payload: ConversationRelayCallbackPayload\n ): Promise<{ status: number; content: string; contentType: string }> {\n this.logger.debug(\n { call_sid: payload.CallSid, call_status: payload.CallStatus },\n 'ConversationRelay callback received'\n );\n\n if (payload.AccountSid !== this.config.accountSid) {\n this.logger.warn(\n { expected: this.config.accountSid, received: payload.AccountSid },\n 'ConversationRelay callback AccountSid mismatch, ignoring'\n );\n return { status: 403, content: 'Forbidden', contentType: 'text/plain' };\n }\n\n if (payload.CallStatus === 'completed' && !this.tac.isOrchestratorEnabled()) {\n const conversationId = this.callSidToConversationId.get(payload.CallSid);\n if (conversationId) {\n this.callSidToConversationId.delete(payload.CallSid);\n await this.endConversation(conversationId);\n }\n }\n\n return { status: 200, content: 'OK', contentType: 'text/plain' };\n }\n\n // =========================================================================\n // Call Event Handling (status callback, async AMD, recording)\n // =========================================================================\n\n /**\n * Whether a call-webhook payload belongs to the configured account.\n *\n * Twilio signature validation already gates the route; this is defense in\n * depth. A payload with no `AccountSid` is allowed through.\n *\n * Subaccounts: events carry the SID the call was placed on, so configure TAC\n * with that account or its events get dropped here.\n */\n private callEventAccountOk(form: Record<string, string>): boolean {\n const accountSid = form['AccountSid'];\n if (accountSid && accountSid !== this.config.accountSid) {\n this.logger.warn(\n { expected: this.config.accountSid, received: accountSid },\n 'Call event AccountSid mismatch, ignoring'\n );\n return false;\n }\n return true;\n }\n\n /**\n * Parse a call-event webhook form and dispatch it to its handler.\n *\n * Returns 400 when the payload can't be parsed (no `CallSid`) or the handler\n * throws — better than handing Twilio a 200 for an event that wasn't\n * processed. Everything else, including no handler registered and an\n * account mismatch, is a 200 no-op.\n */\n private async dispatchCallEvent<T>(\n kind: CallEventKind,\n form: Record<string, string>,\n handler: ((event: T) => Promise<void> | void) | undefined,\n parse: (form: Record<string, string>) => T,\n logFields: (event: T) => Record<string, unknown>\n ): Promise<{ status: number; content: string; contentType: string }> {\n const ok = { status: 200, content: 'OK', contentType: 'text/plain' };\n if (!handler || !this.callEventAccountOk(form)) {\n return ok;\n }\n\n try {\n const event = parse(form);\n this.logger.debug(logFields(event), `Call ${kind} event received`);\n await handler(event);\n } catch (error) {\n this.logger.error({ err: error, kind }, 'Failed to process call event callback');\n return { status: 400, content: 'Bad Request', contentType: 'text/plain' };\n }\n return ok;\n }\n\n /**\n * Handle a Twilio `statusCallback` webhook.\n *\n * The developer routes the request here (`TACServer` does this automatically\n * for its `/status` call-event route). Parsed into a {@link CallStatusEvent}\n * and dispatched to the {@link onCallStatus} handler. No-op if no handler is\n * registered.\n *\n * @param form - Raw form data from the webhook request.\n */\n public async handleCallStatusEvent(\n form: Record<string, string>\n ): Promise<{ status: number; content: string; contentType: string }> {\n return this.dispatchCallEvent(\n 'status',\n form,\n this.onCallStatusHandler,\n callStatusEventFromForm,\n event => ({ call_sid: event.callSid, call_status: event.callStatus })\n );\n }\n\n /**\n * Handle a Twilio `asyncAmdStatusCallback` webhook.\n *\n * The developer routes the request here (`TACServer` does this automatically\n * for its `/amd` call-event route). Parsed into an {@link AmdEvent} and\n * dispatched to the {@link onAmd} handler. No-op if no handler is registered.\n *\n * @param form - Raw form data from the webhook request.\n */\n public async handleAmdEvent(\n form: Record<string, string>\n ): Promise<{ status: number; content: string; contentType: string }> {\n return this.dispatchCallEvent('amd', form, this.onAmdHandler, amdEventFromForm, event => ({\n call_sid: event.callSid,\n answered_by: event.answeredBy,\n }));\n }\n\n /**\n * Handle a Twilio `recordingStatusCallback` webhook.\n *\n * The developer routes the request here (`TACServer` does this automatically\n * for its `/recording` call-event route). Parsed into a\n * {@link RecordingEvent} and dispatched to the {@link onRecording} handler.\n * No-op if no handler is registered.\n *\n * @param form - Raw form data from the webhook request.\n */\n public async handleRecordingEvent(\n form: Record<string, string>\n ): Promise<{ status: number; content: string; contentType: string }> {\n return this.dispatchCallEvent(\n 'recording',\n form,\n this.onRecordingHandler,\n recordingEventFromForm,\n event => ({ call_sid: event.callSid, recording_status: event.recordingStatus })\n );\n }\n\n /**\n * Hang up a call and clean up its ConversationRelay session.\n *\n * Works on `callSid` alone, whether or not a session exists yet. No-ops the\n * session cleanup if none is tracked.\n *\n * Does not throw — hanging up an already-ended call is routine (the callee\n * hangs up while AMD is still resolving), and handlers shouldn't have to\n * guard against it.\n *\n * @param callSid - Twilio Call SID (from a call event, the outbound result, or\n * `ConversationSession.callSid`).\n * @returns True if Twilio accepted the hangup, false if it failed (logged).\n * Session cleanup runs either way.\n */\n public async endCall(callSid: string): Promise<boolean> {\n const client = this.getTwilioClient();\n let hungUp = true;\n try {\n await client.calls(callSid).update({ status: 'completed' });\n } catch (error) {\n hungUp = false;\n this.logger.error({ err: error, call_sid: callSid }, 'Failed to hang up call');\n }\n\n const session = this.getConversationSessionByCallSid(callSid);\n if (session) {\n await this.endConversation(session.conversationId as ConversationId);\n }\n return hungUp;\n }\n\n /**\n * Look up the active voice session for a Twilio Call SID.\n *\n * Out-of-band code holding a CallSid — a dashboard route, an operator action,\n * a call-event handler — can't reach the session-facing methods, which are\n * keyed by conversation id: the Orchestrator conversation id in orchestrator\n * mode, the CallSid only in ConversationRelay-only mode.\n *\n * Relay-only mode creates the session on the first prompt; orchestrated\n * mode creates it when the lookup started at setup finishes, so it may\n * exist before the caller speaks — including before `onAmd` fires. Treat it\n * as racy and hang up with {@link endCall}, which needs no session.\n *\n * At the other end, orchestrator mode keeps the session until Conversation\n * Orchestrator's CLOSED webhook, so it outlives the call and `onCallStatus` /\n * `onRecording` do resolve. Relay-only mode tears down on the\n * ConversationRelay callback instead, which races them.\n *\n * @example\n * ```typescript\n * async function nudge(callSid: string): Promise<void> {\n * const session = voiceChannel.getConversationSessionByCallSid(callSid);\n * if (session) {\n * await voiceChannel.sendResponse(session.conversationId, 'Still there?');\n * }\n * }\n * ```\n *\n * @param callSid - Twilio Call SID, e.g. from\n * `InitiateVoiceConversationResult.callSid` or a call event.\n * @returns The session, or `undefined` — not created yet, the call ended, or\n * it landed on another instance (see the horizontal-scaling note in\n * CLAUDE.md).\n */\n public getConversationSessionByCallSid(callSid: string): ConversationSession | undefined {\n for (const session of this.activeConversations.values()) {\n if (session.callSid === callSid) {\n return session;\n }\n }\n return undefined;\n }\n\n // =========================================================================\n // Stream Task Management\n // =========================================================================\n\n /**\n * Start tracking a streaming task for a conversation\n *\n * @param conversationId - The conversation ID\n * @returns The stream task with its AbortController\n */\n public startStreamTask(conversationId: ConversationId): StreamTask {\n // Cancel any existing task\n this.cancelStreamTask(conversationId);\n\n const task: StreamTask = { controller: new AbortController(), hasSentTokens: false };\n this.streamTasks.set(conversationId, task);\n\n this.logger.debug({ conversation_id: conversationId }, 'Started stream task');\n return task;\n }\n\n /**\n * Cancel an active streaming task\n *\n * @param conversationId - The conversation ID\n * @returns true if a task was cancelled, false otherwise\n */\n public cancelStreamTask(conversationId: ConversationId): boolean {\n const task = this.streamTasks.get(conversationId);\n if (task) {\n task.controller.abort();\n this.streamTasks.delete(conversationId);\n this.logger.debug({ conversation_id: conversationId }, 'Cancelled stream task');\n return true;\n }\n return false;\n }\n\n /**\n * Complete a streaming task (remove from tracking)\n *\n * @param conversationId - The conversation ID\n */\n public completeStreamTask(conversationId: ConversationId): void {\n this.streamTasks.delete(conversationId);\n this.logger.debug({ conversation_id: conversationId }, 'Completed stream task');\n }\n\n /**\n * Check if a stream task is active\n *\n * @param conversationId - The conversation ID\n * @returns true if an active task exists\n */\n public hasActiveStreamTask(conversationId: ConversationId): boolean {\n const task = this.streamTasks.get(conversationId);\n return task !== undefined && !task.controller.signal.aborted;\n }\n\n // =========================================================================\n // ConversationRelay TwiML Generation\n // =========================================================================\n\n /**\n * Field names on {@link TwiMLOptions} that map directly to `<ConversationRelay>`\n * attributes (camelCase, emitted as-is). Excludes the fields handled specially\n * by {@link generateTwiml}: websocketUrl (resolved through the layered merge and\n * emitted as the `url` attribute), actionUrl, languages, customParameters, extra.\n */\n private static readonly RELAY_ATTR_FIELDS: readonly (keyof TwiMLOptions)[] = [\n 'welcomeGreeting',\n 'welcomeGreetingInterruptible',\n 'conversationConfiguration',\n 'language',\n 'ttsLanguage',\n 'transcriptionLanguage',\n 'voice',\n 'ttsProvider',\n 'transcriptionProvider',\n 'speechModel',\n 'elevenlabsTextNormalization',\n 'eotThreshold',\n 'partialPrompts',\n 'deepgramSmartFormat',\n 'speechTimeout',\n 'interruptible',\n 'interruptSensitivity',\n 'reportInputDuringAgentSpeech',\n 'ignoreBackchannel',\n 'preemptible',\n 'dtmfDetection',\n 'hints',\n 'events',\n 'debug',\n 'intelligenceService',\n ];\n\n /**\n * Generate TwiML XML for ConversationRelay from a merged {@link TwiMLOptions}.\n *\n * This is the low-level emitter used by `handleIncomingCall` and\n * `initiateOutboundConversation` after layering. It mirrors the Python SDK's\n * `generate_twiml`. The WebSocket URL may be passed as `websocketUrl` or via\n * `options.websocketUrl` (the explicit argument wins when both are given), so a\n * channel-less caller can pass everything in one object.\n *\n * @param websocketUrl - Public WebSocket URL (e.g. 'wss://example.ngrok.app/ws').\n * Optional if `options.websocketUrl` is set.\n * @param options - Merged TwiMLOptions to emit.\n * @returns TwiML XML string ready to return to Twilio.\n * @throws {Error} if no WebSocket URL is provided via either source.\n */\n private generateTwiml(websocketUrl: string | undefined, options: TwiMLOptions): string {\n const resolvedWebsocketUrl = websocketUrl || options.websocketUrl;\n if (!resolvedWebsocketUrl) {\n throw new Error(\n 'generateTwiml requires a WebSocket URL — pass it explicitly or set options.websocketUrl.'\n );\n }\n\n const response = new VoiceResponse();\n\n // <Connect action=...> — actionUrl undefined means no action attribute.\n const connect = response.connect(options.actionUrl ? { action: options.actionUrl } : {});\n\n // Build ConversationRelay attributes. Keys on TwiMLOptions are already\n // camelCase; the Twilio SDK serializes booleans/numbers as TwiML attribute\n // values.\n const relayAttrs: Record<string, unknown> = { url: resolvedWebsocketUrl };\n for (const field of VoiceChannel.RELAY_ATTR_FIELDS) {\n let value = options[field];\n if (value === undefined) {\n continue;\n }\n // Twilio accepts true/false on `interruptible` for backward-compat but the\n // documented enum is none|dtmf|speech|any. Normalize so we emit canonical\n // values regardless of the SDK's bool serialization.\n if (field === 'interruptible' && typeof value === 'boolean') {\n value = value ? 'any' : 'none';\n }\n relayAttrs[field] = value;\n }\n\n // `extra` is the escape hatch for attributes not yet typed. The schema's\n // shadow-guard rejects keys colliding with typed fields, so pass them\n // through as-is — except `url`: it's not a TwiMLOptions field (invisible to\n // the shadow-guard) but IS the resolved WebSocket endpoint, so letting\n // `extra.url` through would silently point the call at the wrong socket.\n if (options.extra) {\n for (const [key, value] of Object.entries(options.extra)) {\n if (key === 'url') {\n this.logger.warn(\n 'Ignoring `url` in TwiMLOptions.extra; set `websocketUrl` to override the ConversationRelay URL.'\n );\n continue;\n }\n relayAttrs[key] = value;\n }\n }\n\n const relay = connect.conversationRelay(\n relayAttrs as Parameters<typeof connect.conversationRelay>[0]\n );\n\n // Emit <Language> children, if any.\n if (options.languages && options.languages.length > 0) {\n for (const lang of options.languages) {\n const langAttrs = this.filterUnsetValues(lang);\n relay.language(langAttrs as Parameters<typeof relay.language>[0]);\n }\n }\n\n // Emit custom parameters as <Parameter> children, skipping null/undefined.\n if (options.customParameters) {\n for (const [name, value] of Object.entries(options.customParameters)) {\n if (value !== null && value !== undefined) {\n relay.parameter({ name, value: stringifyParameterValue(value) });\n }\n }\n }\n\n return response.toString();\n }\n\n /**\n * Generate TwiML to connect a call to ConversationRelay.\n * Validates configuration with Zod before generating TwiML.\n *\n * @param config - ConversationRelay configuration (url, transcription, TTS, etc.)\n * @param options - Optional settings for parameters and the Connect verb\n * @returns TwiML XML string\n * @throws {Error} if config validation fails\n */\n public connectConversationRelay(\n config: ConversationRelayConfig,\n options?: { parameters?: CustomParameters; actionUrl?: string }\n ): string {\n // Validate configuration with Zod schema (consistent with project pattern)\n const validationResult = ConversationRelayConfigSchema.safeParse(config);\n\n if (!validationResult.success) {\n const errorMessage = validationResult.error.issues\n .map(issue => `${issue.path.join('.')}: ${issue.message}`)\n .join(', ');\n throw new Error(`Invalid ConversationRelay configuration: ${errorMessage}`);\n }\n\n const validatedConfig = validationResult.data;\n\n // Extract languages array (child elements, not attributes)\n const { languages, ...conversationRelayAttributes } = validatedConfig;\n\n // Filter out undefined values to keep TwiML clean\n const filteredConfig = this.filterUnsetValues(conversationRelayAttributes);\n\n // Build TwiML using SDK\n const response = new VoiceResponse();\n const connect = response.connect(options?.actionUrl ? { action: options.actionUrl } : {});\n const relay = connect.conversationRelay(filteredConfig);\n\n // Add language configurations as child <Language> elements\n if (languages && languages.length > 0) {\n for (const lang of languages) {\n // Filter out undefined values to satisfy exactOptionalPropertyTypes\n // Type assertion is safe here because we've already validated with Zod\n const filteredLang = this.filterUnsetValues(lang);\n relay.language(filteredLang as Parameters<typeof relay.language>[0]);\n }\n }\n\n // Add custom parameters as child <Parameter> elements\n if (options?.parameters) {\n for (const [name, value] of Object.entries(options.parameters)) {\n relay.parameter({ name, value: String(value) });\n }\n }\n\n return response.toString();\n }\n\n /**\n * Filter out undefined values from configuration object.\n * Keeps null, false, 0, and empty strings as they are valid values.\n */\n private filterUnsetValues(config: Record<string, unknown>): Record<string, unknown> {\n const filtered: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(config)) {\n if (value !== undefined) {\n filtered[key] = value;\n }\n }\n return filtered;\n }\n\n /**\n * Cleanup channel state on shutdown\n *\n * Note: WebSocket connections are managed by the server and closed there.\n * This method only cleans up internal channel state.\n */\n public override shutdown(): void {\n this.streamTasks.clear();\n this.webSocketConnections.clear();\n this.promptQueues.clear();\n this.initializationRetries.clear();\n this.callSidToConversationId.clear();\n super.shutdown();\n }\n}\n","import { ConversationSession } from '../types/conversation';\n\nfunction formatTraitValue(value: unknown): string {\n // For primitives (string, number, boolean, bigint), return as-is for readability\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'bigint'\n ) {\n return String(value);\n }\n // For objects and arrays, use JSON.stringify with bigint replacer\n try {\n return (\n JSON.stringify(value, (_key, replacerValue: unknown) => {\n if (typeof replacerValue === 'bigint') {\n return String(replacerValue);\n }\n return replacerValue;\n }) ?? String(value)\n );\n } catch {\n return String(value);\n }\n}\n\n/**\n * Build a formatted profile prompt section from conversation session data.\n *\n * Generates a markdown-formatted Customer Profile section with trait information.\n * Each trait is displayed as a bulleted list item with the trait name and formatted value.\n * Primitive values (string, number, boolean, bigint) are shown without quotes for readability,\n * while objects and arrays are JSON-stringified.\n *\n * @param context - The conversation session containing profile data\n * @param traitGroups - Optional array of trait group names to include. If provided, only\n * these trait groups will be included in the output. If an empty array\n * is provided, returns null.\n * @returns Formatted profile section or null if no profile data or no traits match filter\n */\nexport function buildProfilePrompt(\n context: ConversationSession,\n traitGroups?: string[]\n): string | null {\n if (!context.profile || !context.profile.traits) {\n return null;\n }\n\n let filteredTraits: Record<string, unknown>;\n\n if (traitGroups !== undefined) {\n if (traitGroups.length === 0) {\n return null;\n }\n\n filteredTraits = Object.fromEntries(\n Object.entries(context.profile.traits).filter(\n ([key, value]) => traitGroups.includes(key) && value != null\n )\n );\n } else {\n filteredTraits = Object.fromEntries(\n Object.entries(context.profile.traits).filter(([, value]) => value != null)\n );\n }\n\n if (Object.keys(filteredTraits).length === 0) {\n return null;\n }\n\n const lines = ['## Customer Profile', 'Information about this customer:'];\n\n for (const [key, value] of Object.entries(filteredTraits)) {\n lines.push(`- ${key}: ${formatTraitValue(value)}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * Configuration options for adapter utilities like MemoryPromptBuilder.\n */\nexport interface AdapterOptions {\n /**\n * Optional array of profile trait group names to include in the output.\n *\n * - If undefined or not provided, all available trait groups are included\n * - If empty array ([]), no profile traits are included (profile section is omitted)\n * - If populated array, only the specified trait groups are included\n *\n * @example\n * ```typescript\n * // Include only Contact and Preferences traits\n * { profileTraits: ['Contact', 'Preferences'] }\n *\n * // Exclude all profile traits\n * { profileTraits: [] }\n *\n * // Include all traits (default)\n * { } // or undefined\n * ```\n */\n profileTraits?: string[];\n}\n\n/**\n * Extract and normalize profile trait groups from adapter options.\n *\n * This is an internal helper function used by MemoryPromptBuilder to handle trait filtering.\n * The returned array should be treated as immutable.\n *\n * @param options - Adapter options containing optional profileTraits configuration\n * @returns undefined if all traits should be included, empty array if traits should be\n * excluded, or the specified trait groups array. The array is returned by reference.\n * @internal\n */\nexport function getProfileTraits(options?: AdapterOptions): string[] | undefined {\n if (!options || options.profileTraits === undefined) {\n return undefined;\n }\n\n if (options.profileTraits.length === 0) {\n return [];\n }\n\n return options.profileTraits;\n}\n","import { TACMemoryResponse } from '../lib/tac-memory-response';\nimport { buildProfilePrompt } from '../lib/conversation-session-helpers';\nimport { ConversationSession } from '../types/conversation';\nimport { AdapterOptions, getProfileTraits } from './options';\n\n/**\n * Utility class for building formatted LLM prompts from TAC memory and profile data.\n *\n * Generates markdown-formatted prompt sections that can be injected into LLM system messages,\n * providing context about the customer from previous interactions.\n *\n * @example\n * ```typescript\n * // Simple usage with compose() - no if/else needed\n * const systemPrompt = MemoryPromptBuilder.compose(\n * 'You are a helpful assistant.',\n * memoryResponse,\n * session\n * );\n *\n * // Advanced usage with trait filtering\n * const systemPrompt = MemoryPromptBuilder.compose(\n * 'You are a helpful assistant.',\n * memoryResponse,\n * session,\n * { profileTraits: ['Contact', 'Preferences'] }\n * );\n * ```\n */\nexport class MemoryPromptBuilder {\n /**\n * Build a formatted memory prompt from available memory and profile data.\n *\n * **Note:** Most users should use `compose()` instead, which automatically handles\n * combining memory with your system prompt. Use `build()` only if you need the raw\n * memory content without a system prompt.\n *\n * Generates a structured prompt with up to four sections:\n * - **Customer Profile**: Profile traits (filtered by options if provided)\n * - **Key Observations**: Important notes from previous interactions\n * - **Past Conversation Summaries**: Summaries of previous conversations\n * - **Recent Message History**: Recent communications with the customer\n *\n * Sections with no data are omitted. If no data is available at all, returns an empty string.\n *\n * @param memoryResponse - Memory data from TAC.retrieveMemory() containing observations,\n * summaries, and communications. Optional.\n * @param context - Conversation session containing profile data. Optional.\n * @param options - Configuration options for filtering profile traits. If profileTraits is\n * provided, only those trait groups will be included in the output. If an\n * empty array is provided, profile section is omitted. Optional.\n * @returns Formatted markdown prompt string ready for injection into LLM system messages.\n * Returns empty string if no memory or profile data is available.\n *\n * @example\n * ```typescript\n * // Recommended: Use compose() for most cases\n * const prompt = MemoryPromptBuilder.compose(basePrompt, memory, session);\n *\n * // Advanced: Use build() only if you need raw memory content\n * const rawMemory = MemoryPromptBuilder.build(memory, session);\n * if (rawMemory) {\n * // Custom handling of memory content\n * }\n * ```\n */\n static build(\n memoryResponse?: TACMemoryResponse | null,\n context?: ConversationSession | null,\n options?: AdapterOptions\n ): string {\n if (!memoryResponse && (!context || !context.profile)) {\n return '';\n }\n\n const sections: string[] = [];\n\n if (context) {\n const traitGroups = getProfileTraits(options);\n const profileSection = buildProfilePrompt(context, traitGroups);\n if (profileSection) {\n sections.push(profileSection);\n }\n }\n\n if (memoryResponse) {\n const memorySections = memoryResponse.buildMemoryPrompts();\n sections.push(...memorySections);\n }\n\n if (sections.length === 0) {\n return '';\n }\n\n return this.assemblePrompt(sections);\n }\n\n /**\n * Compose system prompt with memory context.\n *\n * Appends memory to systemPrompt if available. Always returns a string.\n * Eliminates the need for manual if/else checks when combining prompts.\n *\n * **Note:** Empty strings and whitespace-only strings are treated as \"no system prompt\"\n * (same as null/undefined). Whitespace is automatically trimmed from systemPrompt.\n *\n * @param systemPrompt - Base system prompt for the LLM. Empty string, whitespace-only,\n * null, and undefined are all treated as \"no system prompt\". Optional.\n * @param memoryResponse - Memory data from TAC.retrieveMemory(). Optional.\n * @param context - Conversation session containing profile data. Optional.\n * @param options - Configuration options for filtering profile traits. Optional.\n * @returns Composed prompt with memory appended to systemPrompt. Returns empty string\n * if both systemPrompt and memory are empty/null/undefined.\n *\n * @example\n * ```typescript\n * // Before (manual if/else)\n * const memoryContext = MemoryPromptBuilder.build(memoryResponse, context);\n * const systemPrompt = basePrompt + (memoryContext ? `\\n\\n${memoryContext}` : '');\n *\n * // After (compose handles it)\n * const systemPrompt = MemoryPromptBuilder.compose(basePrompt, memoryResponse, context);\n *\n * // Empty strings and whitespace are treated as \"no prompt\"\n * MemoryPromptBuilder.compose('', memoryResponse, context); // Returns just memory\n * MemoryPromptBuilder.compose(' ', memoryResponse, context); // Returns just memory (trimmed)\n * MemoryPromptBuilder.compose(null, memoryResponse, context); // Returns just memory\n * ```\n */\n static compose(\n systemPrompt?: string | null,\n memoryResponse?: TACMemoryResponse | null,\n context?: ConversationSession | null,\n options?: AdapterOptions\n ): string {\n const memoryContent = this.build(memoryResponse, context, options);\n const trimmedPrompt = systemPrompt?.trim() || null;\n\n if (!trimmedPrompt && !memoryContent) {\n return '';\n }\n\n if (!trimmedPrompt) {\n return memoryContent;\n }\n\n if (!memoryContent) {\n return trimmedPrompt;\n }\n\n return `${trimmedPrompt}\\n\\n${memoryContent}`;\n }\n\n private static assemblePrompt(sections: string[]): string {\n const header = [\n '# Customer Context',\n 'You have access to the following information about this customer ' +\n 'from previous interactions:',\n '',\n ];\n\n const body = sections.join('\\n\\n');\n\n return header.join('\\n') + body;\n }\n}\n","import { ToolFunction, JSONSchema, OpenAITool, AnthropicTool } from '@twilio/tac-core';\n\n/**\n * TAC Tool class with helper methods for LLM integration\n *\n * Matches Python's TACTool dataclass with conversion methods.\n */\nexport class TACTool<TParams = unknown, TResult = unknown> {\n constructor(\n public readonly name: string,\n public readonly description: string,\n public readonly parameters: JSONSchema,\n public readonly implementation: ToolFunction<TParams, TResult>\n ) {}\n\n /**\n * Convert to OpenAI function calling format\n */\n toOpenAIFormat(): OpenAITool {\n return {\n type: 'function',\n function: {\n name: this.name,\n description: this.description,\n parameters: this.parameters,\n },\n };\n }\n\n /**\n * Convert to Anthropic tool calling format\n */\n toAnthropicFormat(): AnthropicTool {\n return {\n name: this.name,\n description: this.description,\n input_schema: this.parameters,\n };\n }\n\n /**\n * Convert to JSON string (OpenAI format by default)\n */\n toJSON(): string {\n return JSON.stringify(this.toOpenAIFormat(), null, 2);\n }\n\n /**\n * Convert this tool to an OpenAI Agents SDK `FunctionTool` instance.\n *\n * Unlike `toOpenAIFormat` and `toAnthropicFormat` (which return plain\n * objects consumed by HTTP APIs), the OpenAI Agents SDK dispatches on tool\n * *type*, so this returns a live `tool(...)` object with an invoke callback\n * that calls this tool and JSON-encodes the result.\n *\n * Requires the `@openai/agents` package:\n *\n * npm install @openai/agents\n *\n * @returns A FunctionTool ready to pass to `new Agent({ tools: [...] })`.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Return type depends on an optional peer dep we don't declare\n async toOpenAIAgentsSDKTool(): Promise<any> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Optional peer dep: dynamic import, can't declare types\n let agentsModule: any;\n try {\n // Dynamic import of an optional peer dependency. The indirection via a\n // string variable keeps TypeScript from trying to resolve the module\n // at compile time (it isn't a declared dependency).\n const moduleSpec = '@openai/agents';\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- Dynamic optional-dep import\n agentsModule = await import(/* @vite-ignore */ moduleSpec);\n } catch (err) {\n const cause = err instanceof Error ? err.message : String(err);\n throw new Error(\n 'toOpenAIAgentsSDKTool() failed to load @openai/agents. ' +\n 'Install with: npm install @openai/agents. ' +\n `Underlying error: ${cause}`,\n { cause: err }\n );\n }\n\n const impl = this.implementation;\n // The Agents SDK's `JsonObjectSchemaNonStrict` requires `additionalProperties: true`\n // (and `Strict` requires `: false`). Our schema sets neither by default, so normalize\n // for the non-strict path we're opting into.\n const parameters = {\n ...this.parameters,\n additionalProperties: true,\n };\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call -- Optional peer dep\n return agentsModule.tool({\n name: this.name,\n description: this.description,\n parameters,\n // Disable strict mode: the Agents SDK's strict JSON schema rejects\n // some features TAC emits (e.g. unions, top-level description).\n strict: false,\n execute: async (args: unknown): Promise<string> => {\n const result = await impl(args as TParams);\n return JSON.stringify(result);\n },\n });\n }\n}\n\n/**\n * Create a tool directly with all parameters\n *\n * Simplified approach matching Python's create_tool function.\n * No builder pattern - just a simple function call.\n */\nexport function defineTool<TParams = unknown, TResult = unknown>(\n name: string,\n description: string,\n parameters: JSONSchema,\n implementation: ToolFunction<TParams, TResult>\n): TACTool<TParams, TResult> {\n if (!name) {\n throw new Error('Tool name is required');\n }\n\n if (!description) {\n throw new Error('Tool description is required');\n }\n\n if (!parameters) {\n throw new Error('Tool parameters schema is required');\n }\n\n if (!implementation) {\n throw new Error('Tool implementation is required');\n }\n\n return new TACTool(name, description, parameters, implementation);\n}\n","import {\n MemoryRetrievalRequest,\n MemoryRetrievalResponse,\n BuiltInTools,\n MemoryClient,\n} from '@twilio/tac-core';\nimport { TACTool, defineTool } from '../lib/builder';\n\n/**\n * Parameters for memory retrieval tool\n */\ninterface MemoryRetrievalParams {\n query?: string;\n beginDate?: string;\n endDate?: string;\n observationsLimit?: number;\n summariesLimit?: number;\n communicationsLimit?: number;\n relevanceThreshold?: number;\n}\n\n/**\n * Create memory retrieval tool.\n *\n * @param memoryClient - Memory client instance (must be initialized with storeId)\n * @param profileId - Optional profile ID for memory retrieval\n * @param conversationId - Optional conversation ID for memory retrieval\n * @param options - Optional overrides for tool metadata.\n * @param options.name - Tool name exposed to the LLM. Defaults to `retrieve_profile_memory`.\n * @param options.description - Tool description exposed to the LLM. Defaults to a\n * generic \"retrieve memories\" prompt.\n */\nexport function createMemoryRetrievalTool(\n memoryClient: MemoryClient,\n profileId?: string,\n conversationId?: string,\n options: { name?: string; description?: string } = {}\n): TACTool<MemoryRetrievalParams, MemoryRetrievalResponse> {\n return defineTool(\n options.name ?? BuiltInTools.RETRIEVE_MEMORY,\n options.description ??\n 'Retrieve user memories including observations, summaries, and conversation history',\n {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Optional semantic search query to filter memories',\n },\n beginDate: {\n type: 'string',\n description: 'Optional start date for filtering memories (ISO 8601 format)',\n },\n endDate: {\n type: 'string',\n description: 'Optional end date for filtering memories (ISO 8601 format)',\n },\n observationsLimit: {\n type: 'integer',\n minimum: 0,\n maximum: 100,\n default: 20,\n description: 'Maximum number of observations to retrieve. Set to 0 to skip observations.',\n },\n summariesLimit: {\n type: 'integer',\n minimum: 0,\n maximum: 100,\n default: 5,\n description: 'Maximum number of summaries to retrieve. Set to 0 to skip summaries.',\n },\n communicationsLimit: {\n type: 'integer',\n minimum: 0,\n maximum: 100,\n default: 0,\n description:\n 'Maximum number of communications to retrieve. Set to 0 to skip communications.',\n },\n relevanceThreshold: {\n type: 'number',\n minimum: 0.0,\n maximum: 1.0,\n default: 0.0,\n description: 'Minimum relevance score threshold for observations and summaries.',\n },\n },\n required: [], // No required parameters\n description: 'Retrieve memories for the current user',\n },\n async (params: MemoryRetrievalParams) => {\n if (!profileId) {\n throw new Error('No profile ID available for memory retrieval');\n }\n\n const request = Object.fromEntries(\n Object.entries({\n conversationId,\n query: params.query,\n beginDate: params.beginDate,\n endDate: params.endDate,\n observationsLimit: params.observationsLimit,\n summariesLimit: params.summariesLimit,\n communicationsLimit: params.communicationsLimit,\n relevanceThreshold: params.relevanceThreshold,\n }).filter(([_, value]) => value !== undefined)\n ) as Partial<MemoryRetrievalRequest>;\n\n return memoryClient.retrieveMemories(profileId, request);\n }\n );\n}\n\n/**\n * Create factory function for memory tools\n *\n * @param memoryClient - Memory client instance (must be initialized with storeId)\n */\nexport function createMemoryTools(memoryClient: MemoryClient): {\n forProfile: (\n profileId: string,\n conversationId?: string\n ) => TACTool<MemoryRetrievalParams, MemoryRetrievalResponse>;\n forSession: (\n profileId?: string,\n conversationId?: string\n ) => TACTool<MemoryRetrievalParams, MemoryRetrievalResponse>;\n} {\n return {\n forProfile: (profileId: string, conversationId?: string) =>\n createMemoryRetrievalTool(memoryClient, profileId, conversationId),\n\n forSession: (profileId?: string, conversationId?: string) =>\n createMemoryRetrievalTool(memoryClient, profileId, conversationId),\n };\n}\n","import { BuiltInTools, ConversationId, BaseChannel } from '@twilio/tac-core';\nimport { TACTool, defineTool } from '../lib/builder';\n\n/**\n * Parameters for send message tool\n */\ninterface SendMessageParams {\n message: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Result from send message tool\n */\ninterface SendMessageResult {\n success: boolean;\n message_id?: string;\n error?: string;\n}\n\n/**\n * Create send message tool\n */\nexport function createSendMessageTool(\n channel: BaseChannel,\n conversationId: ConversationId\n): TACTool<SendMessageParams, SendMessageResult> {\n return defineTool(\n BuiltInTools.SEND_MESSAGE,\n 'Send a message to the user in the current conversation',\n {\n type: 'object',\n properties: {\n message: {\n type: 'string',\n description: 'The message content to send to the user',\n },\n metadata: {\n type: 'object',\n description: 'Optional metadata to include with the message',\n },\n },\n required: ['message'],\n description: 'Send a message to the user',\n },\n async (params: SendMessageParams) => {\n try {\n await channel.sendResponse(conversationId, params.message, params.metadata);\n\n return {\n success: true,\n message_id: `msg_${Date.now()}`, // Simple ID generation\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n );\n}\n\n/**\n * Create factory function for messaging tools\n */\nexport function createMessagingTools(): {\n forConversation: (\n channel: BaseChannel,\n conversationId: ConversationId\n ) => TACTool<SendMessageParams, SendMessageResult>;\n} {\n return {\n /**\n * Create send message tool for specific channel and conversation\n */\n forConversation: (channel: BaseChannel, conversationId: ConversationId) =>\n createSendMessageTool(channel, conversationId),\n };\n}\n","/**\n * Handoff tool for the Twilio Agent Connect.\n *\n * Generic Studio-backed handoff that routes a conversation to a human agent.\n * Produces a structured HandoffPayload and delivers it as a Twilio Studio\n * Execution (voice via `<Connect action>`, digital channels via direct POST).\n */\n\nimport axios, { AxiosError } from 'axios';\nimport {\n ConversationSession,\n HandoffPayload,\n PendingHandoffData,\n TAC,\n studioExecutionsUrl,\n studioVoiceHandoffUrl,\n} from '@twilio/tac-core';\nimport { TACTool, defineTool } from '../lib/builder';\n\n// Re-export URL helpers for backward compatibility with the Python factory surface.\nexport { studioExecutionsUrl, studioVoiceHandoffUrl };\n\n/**\n * Build a HandoffPayload from session context and attributes.\n *\n * Useful for custom handoff tools that want TAC's payload shape without\n * the Studio-specific delivery in `postStudioHandoff`.\n */\nexport function buildHandoffPayload(\n session: ConversationSession,\n memoryStoreId: string,\n attributes: Record<string, unknown>\n): HandoffPayload {\n return {\n conversationId: session.conversationId,\n storeId: memoryStoreId,\n profileId: session.profileId ?? '',\n attributes,\n };\n}\n\n/**\n * POST a handoff payload to a Twilio Studio Flow Executions endpoint.\n *\n * Emits the Twilio Studio Executions API wire format: form-encoded\n * `To` / `From` / `Parameters` fields with HTTP Basic auth.\n * `Parameters` is a JSON string keyed under `HandoffData` so Studio\n * can reference it via `{{flow.data.HandoffData.*}}`.\n */\nexport async function postStudioHandoff(\n payload: HandoffPayload,\n session: ConversationSession,\n options: {\n handoffUrl: string;\n fromAddress: string;\n apiKey: string;\n apiSecret: string;\n }\n): Promise<void> {\n const { handoffUrl, fromAddress, apiKey, apiSecret } = options;\n const toAddress = session.authorInfo?.address ?? '';\n\n const form = new URLSearchParams();\n form.append('To', toAddress);\n form.append('From', fromAddress);\n form.append('Parameters', JSON.stringify({ HandoffData: payload }));\n\n await axios.post(handoffUrl, form.toString(), {\n timeout: 10_000,\n auth: { username: apiKey, password: apiSecret },\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n });\n}\n\n/**\n * Result returned by the handoff tool.\n */\nexport interface HandoffResult {\n status: 'handoff_initiated' | 'handoff_failed';\n channel: string;\n error?: string;\n}\n\ninterface HandoffParams {\n reason: string;\n}\n\nconst DEFAULT_HANDOFF_TOOL_NAME = 'handoff';\nconst DEFAULT_HANDOFF_TOOL_DESCRIPTION =\n 'Hand off the conversation to a human agent. ' +\n 'Use this when the customer requests a human, or when you ' +\n 'cannot adequately handle the request.';\n\n/**\n * Create a handoff tool that delivers in the Twilio Studio Executions API shape.\n *\n * The returned tool exposes only `handoff({ reason })` to the LLM. All other\n * dependencies (TAC instance, session, static attributes) are captured in the\n * closure.\n *\n * On digital channels, the tool POSTs to the Studio Flow Executions endpoint\n * derived from `tac.getConfig().studioHandoffFlowSid`. For voice channels,\n * the payload is stored on the session and the voice channel automatically\n * sends the WS `end` message with `handoffData` after the LLM's final\n * response is delivered.\n *\n * The tool also sets the conversation to INACTIVE and clears status callbacks\n * to prevent further webhook events from being routed to TAC.\n *\n * **Not available in voice-only mode.** This tool requires Conversation\n * Orchestrator for conversation state management and Conversation Memory for\n * the handoff payload. In voice-only mode, implement your own handoff by\n * setting `session.pendingHandoffData` directly — the voice channel will\n * send the WS `end` message with your payload, and your `<Connect action>`\n * URL handler can route the call accordingly.\n *\n * @throws Error if `tac.getConfig().studioHandoffFlowSid` is unset, if\n * Conversation Orchestrator is not configured (voice-only mode), or if\n * the memory store ID was not resolved at startup.\n */\nexport function createStudioHandoffTool(\n tac: TAC,\n session: ConversationSession,\n options: {\n attributes?: Record<string, unknown>;\n name?: string;\n description?: string;\n } = {}\n): TACTool<HandoffParams, HandoffResult> {\n const config = tac.getConfig();\n if (!config.studioHandoffFlowSid) {\n throw new Error(\n 'createStudioHandoffTool requires tac.getConfig().studioHandoffFlowSid ' +\n '(set TWILIO_STUDIO_HANDOFF_FLOW_SID in your environment).'\n );\n }\n const flowSid = config.studioHandoffFlowSid;\n\n const coClient = tac.getConversationClient();\n if (!coClient) {\n throw new Error(\n 'createStudioHandoffTool requires Conversation Orchestrator ' +\n '(not available in voice-only mode)'\n );\n }\n const memoryStoreId = tac.getMemoryStoreId();\n if (!memoryStoreId) {\n throw new Error(\n 'createStudioHandoffTool requires a memory store ID ' +\n '(resolved from conversationConfigurationId at startup)'\n );\n }\n\n const staticAttributes = options.attributes ?? {};\n const toolName = options.name ?? DEFAULT_HANDOFF_TOOL_NAME;\n const toolDescription = options.description ?? DEFAULT_HANDOFF_TOOL_DESCRIPTION;\n\n return defineTool<HandoffParams, HandoffResult>(\n toolName,\n toolDescription,\n {\n type: 'object',\n properties: {\n reason: {\n type: 'string',\n description: 'The reason for handing off to a human agent',\n },\n },\n required: ['reason'],\n description: 'Hand off the conversation to a human agent',\n },\n async (params: HandoffParams): Promise<HandoffResult> => {\n const attributes = { ...staticAttributes, reason: params.reason };\n const payload = buildHandoffPayload(session, memoryStoreId, attributes);\n\n // 1. Set conversation to INACTIVE to trigger the CO-generated\n // conversation summary that Flex fetches on pickup. Downstream\n // (Studio/Flex) flips it back to ACTIVE on pickup and CLOSED on hangup —\n // we don't close it ourselves.\n try {\n await coClient.updateConversation(session.conversationId, 'INACTIVE');\n } catch (err) {\n tac.logger.warn(\n { err, conversation_id: session.conversationId },\n 'Failed to set conversation INACTIVE during handoff'\n );\n }\n\n // 2. Clear statusCallbacks so TAC stops receiving webhook events for\n // this conversation (Flex/human agent will handle it from here).\n try {\n await coClient.clearStatusCallbacks(session.conversationId);\n } catch (err) {\n tac.logger.warn(\n { err, conversation_id: session.conversationId },\n 'Failed to clear status callbacks during handoff'\n );\n }\n\n // 3. Deliver handoff payload.\n if (session.channel === 'voice') {\n // Voice: store on session for deferred delivery. The voice channel\n // sends the WS \"end\" message after the LLM's final response so the\n // caller hears a goodbye before transfer. handoffData is a JSON\n // *string* — ConversationRelay forwards it verbatim in the POST body\n // to the action URL.\n const pending: PendingHandoffData = {\n type: 'end',\n handoffData: JSON.stringify(payload),\n };\n session.pendingHandoffData = pending;\n } else {\n // Digital channels: POST handoff payload to the Studio Flow Executions\n // endpoint. If the POST fails (network, 4xx, 5xx, timeout), return\n // handoff_failed so the LLM can tell the user instead of claiming\n // success.\n try {\n await postStudioHandoff(payload, session, {\n handoffUrl: studioExecutionsUrl(flowSid),\n fromAddress: config.phoneNumber,\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n });\n } catch (err) {\n const message =\n err instanceof AxiosError\n ? err.message\n : err instanceof Error\n ? err.message\n : String(err);\n tac.logger.error(\n { err, conversation_id: session.conversationId },\n 'Failed to deliver handoff payload'\n );\n return {\n status: 'handoff_failed',\n channel: session.channel,\n error: message,\n };\n }\n }\n\n return { status: 'handoff_initiated', channel: session.channel };\n }\n );\n}\n","import { KnowledgeClient, KnowledgeChunkResult } from '@twilio/tac-core';\nimport { TACTool, defineTool } from '../lib/builder';\n\n/**\n * Parameters for knowledge search tool (visible to LLM)\n */\ninterface KnowledgeSearchParams {\n query: string;\n}\n\n/**\n * Configuration for knowledge search tool\n */\ninterface KnowledgeToolConfig {\n name?: string;\n description?: string;\n topK?: number;\n}\n\n/**\n * Create knowledge search tool with explicit name and description\n *\n * @param knowledgeClient - The Knowledge client instance\n * @param knowledgeBaseId - The knowledge base ID to search\n * @param config - Configuration with required name and description\n * @returns TACTool configured for knowledge search\n */\nexport function createKnowledgeSearchTool(\n knowledgeClient: KnowledgeClient,\n knowledgeBaseId: string,\n config: { name: string; description: string; topK?: number }\n): TACTool<KnowledgeSearchParams, KnowledgeChunkResult[]> {\n const topK = config.topK ?? 5;\n\n return defineTool(\n config.name,\n config.description,\n {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'The search query to find relevant knowledge',\n },\n },\n required: ['query'],\n description: config.description,\n },\n async (params: KnowledgeSearchParams) => {\n return knowledgeClient.searchKnowledgeBase(knowledgeBaseId, params.query, topK);\n }\n );\n}\n\n/**\n * Create knowledge search tool with auto-fetched metadata from knowledge base\n *\n * This async version fetches the knowledge base metadata to auto-generate\n * the tool name and description if not provided.\n *\n * @param knowledgeClient - The Knowledge client instance\n * @param knowledgeBaseId - The knowledge base ID to search\n * @param config - Optional configuration (name/description auto-generated if not provided)\n * @returns Promise containing TACTool configured for knowledge search\n */\nexport async function createKnowledgeSearchToolAsync(\n knowledgeClient: KnowledgeClient,\n knowledgeBaseId: string,\n config?: KnowledgeToolConfig\n): Promise<TACTool<KnowledgeSearchParams, KnowledgeChunkResult[]>> {\n let name = config?.name;\n let description = config?.description;\n\n // Fetch knowledge base metadata if name or description not provided\n if (!name || !description) {\n const kb = await knowledgeClient.getKnowledgeBase(knowledgeBaseId);\n if (!name) {\n // Generate tool name from display name (normalized snake_case)\n const normalized = kb.displayName\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_+|_+$/g, '');\n\n name = normalized ? `search_${normalized}` : 'search_knowledge_base';\n }\n if (!description) {\n description = kb.description || `Search the ${kb.displayName} knowledge base`;\n }\n }\n\n const toolConfig: { name: string; description: string; topK?: number } = {\n name,\n description,\n };\n if (config?.topK !== undefined) {\n toolConfig.topK = config.topK;\n }\n return createKnowledgeSearchTool(knowledgeClient, knowledgeBaseId, toolConfig);\n}\n\n/**\n * Create factory for knowledge tools\n *\n * @param knowledgeClient - The Knowledge client instance\n * @returns Factory object with methods to create knowledge tools\n */\nexport function createKnowledgeTools(knowledgeClient: KnowledgeClient): {\n forKnowledgeBase: (\n knowledgeBaseId: string,\n config: { name: string; description: string; topK?: number }\n ) => TACTool<KnowledgeSearchParams, KnowledgeChunkResult[]>;\n forKnowledgeBaseAsync: (\n knowledgeBaseId: string,\n config?: KnowledgeToolConfig\n ) => Promise<TACTool<KnowledgeSearchParams, KnowledgeChunkResult[]>>;\n} {\n return {\n /**\n * Create knowledge search tool with explicit config\n */\n forKnowledgeBase: (\n knowledgeBaseId: string,\n config: { name: string; description: string; topK?: number }\n ) => createKnowledgeSearchTool(knowledgeClient, knowledgeBaseId, config),\n\n /**\n * Create knowledge search tool with auto-fetched metadata\n */\n forKnowledgeBaseAsync: (knowledgeBaseId: string, config?: KnowledgeToolConfig) =>\n createKnowledgeSearchToolAsync(knowledgeClient, knowledgeBaseId, config),\n };\n}\n","import Fastify, {\n FastifyInstance,\n FastifyServerOptions,\n FastifyRequest,\n FastifyReply,\n} from 'fastify';\nimport formbody from '@fastify/formbody';\nimport websocket from '@fastify/websocket';\nimport gracefulShutdown from 'fastify-graceful-shutdown';\nimport type { WebSocket } from 'ws';\nimport twilio from 'twilio';\n\nimport {\n ConversationRelayCallbackPayloadSchema,\n twiMLRequestFromForm,\n CALL_EVENT_KINDS,\n} from '@twilio/tac-core';\nimport { TAC, VoiceChannel, MessagingChannel } from '@twilio/tac-core';\n\n/**\n * Server configuration options\n */\nexport interface TACServerConfig {\n /** Fastify server options (ignored if `fastifyInstance` is provided) */\n fastify?: FastifyServerOptions;\n\n /**\n * Pre-configured Fastify instance to mount TAC routes onto.\n *\n * Use this to control construction-time settings (logger, `trustProxy`,\n * schema, ...) or to register your own plugins/hooks before TAC's\n * routes are set up. If provided, the `fastify` options field is\n * ignored.\n */\n fastifyInstance?: FastifyInstance;\n\n /** Host to bind the server to (default: '0.0.0.0') */\n host?: string;\n\n /** Port to bind the server to (default: 8000) */\n port?: number;\n\n /**\n * Custom server-only webhook paths. The voice WebSocket and ConversationRelay\n * action callback paths live on `TACConfig` (`voiceWebsocketPath` /\n * `voiceActionPath`) because they're consumed by the voice channel regardless\n * of which web framework is used; this server reads them from there.\n */\n webhookPaths?: {\n /**\n * @deprecated Use `conversation` instead. This field will be removed in a future version.\n * If both `messaging` and `conversation` are set, `conversation` takes precedence.\n */\n messaging?: string;\n conversation?: string;\n twiml?: string;\n /** Path for Conversation Intelligence webhook (optional - only registered if provided) */\n cintel?: string;\n };\n\n /** Voice channel instance (alternative to registering on TAC) */\n voiceChannel?: VoiceChannel;\n\n /** Messaging channel instances — webhooks are fanned out to all (alternative to registering on TAC) */\n messagingChannels?: MessagingChannel[];\n}\n\n/**\n * Default server configuration\n */\nconst DEFAULT_CONFIG = {\n host: '0.0.0.0',\n port: 8000,\n webhookPaths: {\n conversation: '/webhook',\n twiml: '/twiml',\n },\n} satisfies Omit<\n TACServerConfig,\n 'fastify' | 'fastifyInstance' | 'voiceChannel' | 'messagingChannels'\n>;\n\n/** Normalize a route path for comparison, so '/hooks' and '/hooks/' collide. */\nfunction stripTrailingSlash(path: string): string {\n return path.replace(/\\/+$/, '');\n}\n\n/** What the voice channel's webhook handlers hand back for a reply. */\ntype CallEventResult = { status: number; content: string; contentType: string };\n\n/**\n * Batteries-included Fastify server for TAC\n *\n * Provides out-of-the-box setup for SMS and Voice channels with\n * proper webhook handling, WebSocket support, and production-ready defaults.\n *\n * Customization:\n * - Pass your own Fastify instance via `config.fastifyInstance` to control\n * construction-time settings (logger, `trustProxy`, schema, ...) and to\n * register plugins/hooks before TAC's routes are set up.\n * - Or mutate `server.fastify` after construction to add routes,\n * decorators, or hooks — before calling `start()`.\n *\n * Example:\n * import Fastify from 'fastify';\n *\n * const app = Fastify({ logger: true, trustProxy: true });\n * const server = new TACServer(tac, { fastifyInstance: app });\n *\n * server.fastify.get('/health', async () => ({ status: 'ok' }));\n *\n * await server.start();\n */\nexport class TACServer {\n public readonly fastify: FastifyInstance;\n private readonly tac: TAC;\n private readonly config: Required<\n Omit<TACServerConfig, 'fastify' | 'fastifyInstance' | 'voiceChannel' | 'messagingChannels'>\n >;\n /** All enabled messaging channels */\n private readonly messagingChannels: MessagingChannel[];\n /** Voice channel instance */\n private readonly voiceChannel: VoiceChannel | undefined;\n /** All channels that need webhook processing (voice + messaging) */\n private readonly webhookChannels: (VoiceChannel | MessagingChannel)[];\n\n constructor(tac: TAC, config: TACServerConfig = {}) {\n this.tac = tac;\n\n // Handle deprecated `messaging` field: log warning and apply fallback if needed\n const webhookPaths = { ...DEFAULT_CONFIG.webhookPaths, ...config.webhookPaths };\n if (config.webhookPaths?.messaging) {\n console.warn(\n 'TACServer: The \"webhookPaths.messaging\" field is deprecated and will be removed in a future version. ' +\n 'Please update your configuration to use \"webhookPaths.conversation\" instead.'\n );\n // If conversation isn't explicitly set, use messaging value as fallback\n if (!config.webhookPaths.conversation) {\n webhookPaths.conversation = config.webhookPaths.messaging;\n }\n }\n\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n webhookPaths,\n };\n\n // Resolve channels: prefer explicit kwargs, fall back to tac.getChannel()\n this.voiceChannel = config.voiceChannel ?? tac.getChannel<VoiceChannel>('voice');\n\n // Fail fast at construction if a voice channel is attached but no public\n // URL is configured. Without this check, the misconfiguration would only\n // surface on the first inbound call as a 500 — easy to miss in CI or smoke\n // tests that don't hit voice. Custom adapters (Express/etc.) constructing\n // VoiceChannel directly still get the runtime error on first request.\n if (this.voiceChannel && !tac.getConfig().voicePublicDomain) {\n throw new Error(\n 'Voice channel is configured but TACConfig.voicePublicDomain is not set. ' +\n 'Set it directly or via the TWILIO_VOICE_PUBLIC_DOMAIN env var.'\n );\n }\n // Unconditional, because the call-event routes register unconditionally\n // (like the TwiML and ConversationRelay routes) — so the collision is real\n // whether or not a voice channel is attached.\n this.validateCallEventPaths();\n this.messagingChannels =\n config.messagingChannels ??\n (\n [\n tac.getChannel<MessagingChannel>('sms'),\n tac.getChannel<MessagingChannel>('rcs'),\n tac.getChannel<MessagingChannel>('chat'),\n tac.getChannel<MessagingChannel>('whatsapp'),\n ] as (MessagingChannel | undefined)[]\n ).filter((ch): ch is MessagingChannel => ch != null);\n\n // Gather all channels that need webhook processing\n this.webhookChannels = [];\n if (this.voiceChannel) {\n this.webhookChannels.push(this.voiceChannel);\n }\n this.webhookChannels.push(...this.messagingChannels);\n\n if (this.webhookChannels.length === 0) {\n console.warn(\n 'TACServer: No channels configured for webhook processing. Register channels with TAC to enable webhooks.'\n );\n }\n // Use the user-supplied Fastify instance if provided; otherwise create\n // a default one with Pino logging.\n if (config.fastifyInstance) {\n this.fastify = config.fastifyInstance;\n } else {\n this.fastify = Fastify({\n logger: {\n level: process.env.TWILIO_LOG_LEVEL || 'info',\n },\n ...config.fastify,\n });\n }\n }\n\n /**\n * Validate `voiceCallEventPath`, the one path that isn't literal.\n *\n * Every other TAC path registers as configured, so a bad value is visible.\n * This one expands into three sub-paths, hiding a mistake the base path looks\n * innocent for: a sub-path colliding with another route while the base looks\n * unrelated (base `/hooks` vs `webhookPaths.twiml = '/hooks/status'`). Both\n * would register as POST routes and requests would reach the wrong handler.\n *\n * The leading-slash requirement is enforced by `TACConfigSchema` at parse\n * time, so it doesn't need re-checking here.\n */\n private validateCallEventPaths(): void {\n const cfg = this.tac.getConfig();\n\n const others: Record<string, string> = {\n [stripTrailingSlash(this.config.webhookPaths.twiml || '/twiml')]: 'webhookPaths.twiml',\n [stripTrailingSlash(cfg.voiceActionPath)]: 'TACConfig.voiceActionPath',\n [stripTrailingSlash(this.config.webhookPaths.conversation || '/webhook')]:\n 'webhookPaths.conversation',\n };\n if (this.config.webhookPaths.cintel) {\n others[stripTrailingSlash(this.config.webhookPaths.cintel)] = 'webhookPaths.cintel';\n }\n\n for (const kind of CALL_EVENT_KINDS) {\n const path = cfg.callEventPath(kind);\n const clash = others[stripTrailingSlash(path)];\n if (clash !== undefined) {\n throw new Error(\n `TACConfig.voiceCallEventPath expands to '${path}', which collides with ` +\n `${clash}. Both would register as POST routes and requests would ` +\n 'reach the wrong handler.'\n );\n }\n }\n }\n\n private getForwardedProto(request: FastifyRequest): string {\n const raw = request.headers['x-forwarded-proto'] as string | undefined;\n return raw?.split(',')[0]?.trim() || 'https';\n }\n\n private getForwardedHost(request: FastifyRequest): string {\n const raw = (request.headers['x-forwarded-host'] as string | undefined) || request.headers.host;\n return raw?.split(',')[0]?.trim() || '';\n }\n\n /**\n * Get the full URL for webhook validation\n * Handles X-Forwarded-* headers for proxy/ngrok scenarios\n */\n private getWebhookUrl(request: FastifyRequest): string {\n const proto = this.getForwardedProto(request);\n const host = this.getForwardedHost(request);\n return `${proto}://${host}${request.url}`;\n }\n\n /**\n * Validate the Twilio signature on an HTTP request. On failure, sends a 403\n * reply (Fastify halts the request once `reply.send` is called in a\n * `preHandler`, so the route handler won't run). Scoped to TAC-registered\n * webhook routes — does not run on user-added routes registered on\n * `server.fastify`.\n */\n private async validateRequestSignature(\n request: FastifyRequest,\n reply: FastifyReply\n ): Promise<void> {\n const signature = request.headers['x-twilio-signature'] as string;\n const url = this.getWebhookUrl(request);\n const authToken = this.tac.getConfig().authToken;\n\n let isValid: boolean;\n if (request.url.includes('bodySHA256=')) {\n const body = (request as FastifyRequest & { rawBody?: string }).rawBody ?? '';\n isValid = twilio.validateRequestWithBody(authToken, signature, url, body);\n } else {\n const params = (request.body as Record<string, string>) || {};\n isValid = twilio.validateRequest(authToken, signature, url, params);\n }\n\n if (!isValid) {\n this.fastify.log.warn({ url, hasSignature: !!signature }, 'Invalid Twilio webhook signature');\n await reply.code(403).send({ error: 'Invalid webhook signature' });\n }\n }\n\n /**\n * Setup routes\n */\n private async setupRoutes(): Promise<void> {\n const validateSignature = {\n preHandler: async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {\n await this.validateRequestSignature(request, reply);\n },\n };\n\n // Conversation Orchestrator webhook — fan out to all enabled channels\n if (this.webhookChannels.length > 0) {\n this.fastify.post(\n this.config.webhookPaths.conversation || '/webhook',\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n const rawHeader = request.headers['i-twilio-idempotency-token'];\n const idempotencyToken = Array.isArray(rawHeader) ? rawHeader[0] : rawHeader;\n\n // Fan out to all channels\n for (const channel of this.webhookChannels) {\n channel.processWebhook(request.body, idempotencyToken).catch((err: unknown) => {\n this.fastify.log.error(\n { err, channel: channel.channelType },\n 'Webhook processing error'\n );\n });\n }\n\n await reply.code(200).send({ status: 'ok' });\n }\n );\n }\n\n // Voice webhook (POST - Twilio calls this when an incoming call arrives)\n this.fastify.post(\n this.config.webhookPaths.twiml || '/twiml',\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n if (!this.voiceChannel) {\n await reply.code(500).send({ error: 'Voice channel not available' });\n return;\n }\n\n const voiceChannel = this.voiceChannel;\n\n // Parse the Twilio webhook form into a framework-neutral TwiMLRequest\n // and hand it to the channel. The channel derives the WebSocket and\n // action URLs from TACConfig (voicePublicDomain + paths), layers in\n // VoiceChannelConfig.defaultTwimlOptions, and runs any per-call\n // customizer registered via voiceChannel.onInboundCallTwiml(...).\n const formDict = (request.body as Record<string, string>) ?? {};\n const twimlRequest = twiMLRequestFromForm(formDict);\n\n const twiml = await voiceChannel.handleIncomingCall(twimlRequest);\n\n await reply.type('application/xml').send(twiml);\n } catch (error) {\n this.fastify.log.error(\n 'TwiML generation error: ' + (error instanceof Error ? error.message : String(error))\n );\n await reply.code(500).send({\n error: 'Internal server error',\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n );\n\n // ConversationRelay callback endpoint. Path lives on TACConfig because the\n // voice channel derives the action URL from it too.\n this.fastify.post(\n this.tac.getConfig().voiceActionPath,\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n if (!this.voiceChannel) {\n await reply.code(500).send({ error: 'Voice channel not available' });\n return;\n }\n\n const voiceChannel = this.voiceChannel;\n\n // Parse form data into payload\n const formData = request.body as Record<string, string>;\n const parseResult = ConversationRelayCallbackPayloadSchema.safeParse(formData);\n\n if (!parseResult.success) {\n this.fastify.log.error(\n { errors: parseResult.error.issues },\n 'Invalid ConversationRelay callback payload'\n );\n await reply.code(400).send({ error: 'Invalid payload' });\n return;\n }\n\n const result = await voiceChannel.handleConversationRelayCallback(parseResult.data);\n\n await reply.code(result.status).type(result.contentType).send(result.content);\n } catch (error) {\n this.fastify.log.error(\n 'ConversationRelay callback error: ' +\n (error instanceof Error ? error.message : String(error))\n );\n await reply.code(500).send({ error: 'Internal server error' });\n }\n }\n );\n\n // One route per Twilio call callback — the route is the discriminator, so\n // each handler parses its own typed event with no payload sniffing. Paths\n // live on TACConfig because the voice channel derives the callback URLs it\n // hands to the Calls API from the same base.\n const callEventHandlers: Record<\n (typeof CALL_EVENT_KINDS)[number],\n (channel: VoiceChannel, form: Record<string, string>) => Promise<CallEventResult>\n > = {\n status: (channel, form) => channel.handleCallStatusEvent(form),\n amd: (channel, form) => channel.handleAmdEvent(form),\n recording: (channel, form) => channel.handleRecordingEvent(form),\n };\n\n for (const kind of CALL_EVENT_KINDS) {\n const handle = callEventHandlers[kind];\n this.fastify.post(\n this.tac.getConfig().callEventPath(kind),\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n if (!this.voiceChannel) {\n await reply.code(500).send({ error: 'Voice channel not available' });\n return;\n }\n\n const formData = (request.body as Record<string, string>) ?? {};\n const result = await handle(this.voiceChannel, formData);\n\n await reply.code(result.status).type(result.contentType).send(result.content);\n } catch (error) {\n this.fastify.log.error(\n `Call ${kind} callback error: ` +\n (error instanceof Error ? error.message : String(error))\n );\n await reply.code(500).send({ error: 'Internal server error' });\n }\n }\n );\n }\n\n // Voice WebSocket endpoint. Path lives on TACConfig because the voice\n // channel derives the WebSocket URL from it too.\n await this.fastify.register(fastify => {\n fastify.get(\n this.tac.getConfig().voiceWebsocketPath,\n { websocket: true },\n (socket: WebSocket, request: FastifyRequest) => {\n const signature = request.headers['x-twilio-signature'] as string;\n const authToken = this.tac.getConfig().authToken;\n\n const proto = this.getForwardedProto(request);\n const host = this.getForwardedHost(request);\n\n if (!host) {\n this.fastify.log.warn('WebSocket connection rejected: missing host header');\n socket.close(1008, 'Invalid request');\n return;\n }\n\n const wsProto = proto === 'https' ? 'wss' : 'ws';\n const fullUrl = new URL(`${wsProto}://${host}${request.url}`);\n const params: Record<string, string> = {};\n fullUrl.searchParams.forEach((value, key) => {\n params[key] = value;\n });\n const url = fullUrl.origin + fullUrl.pathname;\n\n const isValid = twilio.validateRequest(authToken, signature, url, params);\n\n if (!isValid) {\n this.fastify.log.warn(\n { url, hasSignature: !!signature },\n 'WebSocket connection rejected: invalid Twilio signature'\n );\n socket.close(1008, 'Invalid signature');\n return;\n }\n\n if (!this.voiceChannel) {\n socket.terminate();\n return;\n }\n\n this.voiceChannel.handleWebSocketConnection(socket);\n }\n );\n });\n\n // Conversation Intelligence webhook endpoint (optional - only if path is configured)\n if (this.config.webhookPaths.cintel) {\n this.fastify.post(\n this.config.webhookPaths.cintel,\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n if (!this.tac.isCintelEnabled()) {\n await reply.code(400).send({\n error: 'Conversation Intelligence is not enabled',\n message:\n 'Set TWILIO_TAC_CI_CONFIGURATION_ID and memory credentials to enable CI processing',\n });\n return;\n }\n\n try {\n this.fastify.log.info('Processing Conversation Intelligence webhook');\n const result = await this.tac.processCintelEvent(request.body);\n\n if (result.success) {\n if (result.skipped) {\n this.fastify.log.debug({ reason: result.skipReason }, 'CI event skipped');\n } else {\n this.fastify.log.info(\n { eventType: result.eventType, createdCount: result.createdCount },\n 'CI event processed'\n );\n }\n } else {\n this.fastify.log.error({ error: result.error }, 'CI event processing failed');\n }\n\n await reply.send(result);\n } catch (error) {\n this.fastify.log.error(\n 'CI webhook error: ' + (error instanceof Error ? error.message : String(error))\n );\n await reply.code(500).send({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n );\n }\n }\n\n /**\n * Start the server\n */\n public async start(): Promise<void> {\n try {\n // Register required plugins, guarding against users who pre-registered\n // them on a supplied `fastifyInstance` (duplicate registration throws).\n if (!this.fastify.hasContentTypeParser('application/x-www-form-urlencoded')) {\n await this.fastify.register(formbody);\n }\n if (!this.fastify.hasDecorator('websocketServer')) {\n await this.fastify.register(websocket);\n }\n if (!this.fastify.hasDecorator('gracefulShutdown')) {\n await this.fastify.register(gracefulShutdown);\n }\n\n // Replace the default JSON parser with one that stores the raw body string,\n // needed by validateRequestWithBody for bodySHA256 signature validation.\n const defaultJsonParser = this.fastify.getDefaultJsonParser('error', 'error');\n if (this.fastify.hasContentTypeParser('application/json')) {\n this.fastify.removeContentTypeParser('application/json');\n }\n this.fastify.addContentTypeParser(\n 'application/json',\n { parseAs: 'string' },\n (request, body: string, done) => {\n (request as FastifyRequest & { rawBody?: string }).rawBody = body;\n void defaultJsonParser(request, body, done);\n }\n );\n\n // Set up routes (must be after plugin registration)\n // Signature validation is applied per-route as a `preHandler` so it only\n // runs on TAC-registered webhook routes, not on user-added routes on\n // `server.fastify`.\n await this.setupRoutes();\n\n // Configure graceful shutdown to wait for WebSocket connections\n this.fastify.gracefulShutdown(async (signal: string) => {\n this.fastify.log.info({ signal }, 'Received shutdown signal');\n\n // Wait for WebSocket connections to close naturally\n await this.waitForWebSocketsToClose();\n\n // Shutdown TAC (cleans up channel state)\n this.tac.shutdown();\n });\n\n // Start Fastify server\n await this.fastify.listen({\n host: this.config.host,\n port: this.config.port,\n });\n\n this.fastify.log.info(\n {\n host: this.config.host,\n port: this.config.port,\n conversation_webhook: this.config.webhookPaths.conversation,\n twiml_webhook: this.config.webhookPaths.twiml,\n ws_websocket: this.tac.getConfig().voiceWebsocketPath,\n conversation_relay_callback: this.tac.getConfig().voiceActionPath,\n ...(this.voiceChannel && {\n call_event_callbacks: CALL_EVENT_KINDS.map(kind =>\n this.tac.getConfig().callEventPath(kind)\n ),\n }),\n ...(this.config.webhookPaths.cintel && {\n cintel_webhook: this.config.webhookPaths.cintel,\n }),\n },\n 'TAC Server started'\n );\n } catch (error) {\n this.fastify.log.error({ err: error }, 'Failed to start TAC Server');\n throw error;\n }\n }\n\n /**\n * Wait for all WebSocket connections to close\n */\n private async waitForWebSocketsToClose(timeoutMs = 30000): Promise<void> {\n const wsServer = this.fastify.websocketServer;\n if (!wsServer || wsServer.clients.size === 0) {\n return;\n }\n\n this.fastify.log.info(\n { websocket_count: wsServer.clients.size },\n 'Waiting for WebSocket connections to close...'\n );\n\n const startTime = Date.now();\n\n return new Promise<void>(resolve => {\n const checkInterval = setInterval(() => {\n const clientCount = wsServer.clients.size;\n\n if (clientCount === 0) {\n clearInterval(checkInterval);\n this.fastify.log.info('All WebSocket connections closed');\n resolve();\n return;\n }\n\n // Check for timeout\n if (Date.now() - startTime >= timeoutMs) {\n clearInterval(checkInterval);\n this.fastify.log.warn(\n { remaining_websockets: clientCount },\n 'Timeout waiting for WebSockets to close, proceeding with shutdown'\n );\n resolve();\n return;\n }\n\n this.fastify.log.info(\n { remaining_websockets: clientCount },\n 'Waiting for WebSockets to close...'\n );\n }, 5000);\n });\n }\n\n /**\n * Stop the server gracefully\n */\n public async stop(): Promise<void> {\n try {\n await this.fastify.close();\n this.fastify.log.info('TAC Server stopped');\n } catch (error) {\n this.fastify.log.error({ err: error }, 'Error stopping TAC Server');\n throw error;\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../packages/core/src/types/config.ts","../packages/core/src/types/handoff.ts","../packages/core/src/types/conversation.ts","../packages/core/src/types/tac.ts","../packages/core/src/lib/tac-memory-response.ts","../packages/core/src/types/memory.ts","../packages/core/src/types/crelay.ts","../packages/core/src/types/stream.ts","../packages/core/src/types/tools.ts","../packages/core/src/types/cintel.ts","../packages/core/src/types/knowledge.ts","../packages/core/src/lib/config.ts","../packages/core/src/util/log-redaction.ts","../packages/core/src/lib/logger.ts","../package.json","../packages/core/src/clients/base.ts","../packages/core/src/clients/memory.ts","../packages/core/src/clients/conversation.ts","../packages/core/src/clients/knowledge.ts","../packages/core/src/lib/analytics.ts","../packages/core/src/lib/operator-result-processor.ts","../packages/core/src/lib/tac.ts","../packages/core/src/channels/base.ts","../packages/core/src/channels/messaging.ts","../packages/core/src/channels/sms.ts","../packages/core/src/channels/rcs.ts","../packages/core/src/channels/whatsapp.ts","../packages/core/src/channels/chat.ts","../packages/core/src/lib/deprecation.ts","../packages/core/src/channels/voice/provider.ts","../packages/core/src/channels/voice/twiml.ts","../packages/core/src/util/handoff-urls.ts","../packages/core/src/channels/voice/conversation-relay/twiml.ts","../packages/core/src/channels/voice/conversation-relay/provider.ts","../packages/core/src/channels/voice/conversation-relay/config.ts","../packages/core/src/channels/voice/channel.ts","../packages/core/src/channels/voice/media-streams/twiml.ts","../packages/core/src/channels/voice/media-streams/config.ts","../packages/core/src/channels/voice/media-streams/shared/config.ts","../packages/core/src/channels/voice/media-streams/shared/state.ts","../packages/core/src/channels/voice/media-streams/shared/openai-provider.ts","../packages/core/src/channels/voice/media-streams/openai-realtime/state.ts","../packages/core/src/channels/voice/media-streams/openai-realtime/provider.ts","../packages/core/src/channels/voice/media-streams/openai-realtime/config.ts","../packages/core/src/channels/voice/media-streams/gpt-live/state.ts","../packages/core/src/channels/voice/media-streams/gpt-live/provider.ts","../packages/core/src/channels/voice/media-streams/gpt-live/config.ts","../packages/core/src/lib/conversation-session-helpers.ts","../packages/core/src/adapters/options.ts","../packages/core/src/adapters/prompt-builder.ts","../packages/tools/src/lib/builder.ts","../packages/tools/src/built-in/memory.ts","../packages/tools/src/built-in/messaging.ts","../packages/tools/src/built-in/handoff.ts","../packages/tools/src/built-in/knowledge.ts","../packages/server/src/lib/server.ts"],"names":["z","record","axios","session","client","VoiceResponse","Twilio","WebSocket","CallState","SESSION_CONFIG_TOKEN_PARAM","isTwilioMediaStreamAudioFormat"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * Channel types supported by the framework\n */\nexport const ChannelTypeSchema = z.enum(['sms', 'voice', 'chat', 'rcs', 'whatsapp']);\nexport type ChannelType = z.infer<typeof ChannelTypeSchema>;\n\n/**\n * Twilio Memory configuration schema\n */\nexport const TwilioMemoryConfigSchema = z.object({\n traitGroups: z.array(z.string()).optional(),\n observationsLimit: z.number().int().min(0).max(100).default(20),\n summariesLimit: z.number().int().min(0).max(100).default(5),\n // 0 matches the Memory API and Python SDK. Above 0, Memory requires a\n // conversationId on every /Recall, forcing the query expansion that\n // `memoryMode: \"once\"` exists to avoid.\n communicationsLimit: z.number().int().min(0).max(100).default(0),\n relevanceThreshold: z.number().min(0.0).max(1.0).default(0.0),\n /**\n * Trait group name that holds the phone identifier on newly created profiles.\n * Must match the promoted-to-identifier configuration of the Conversation Memory store.\n */\n phoneTraitGroup: z.string().default('Contact'),\n /** Trait field name within `phoneTraitGroup` that holds the phone identifier. */\n phoneTraitField: z.string().default('phone'),\n});\n\nexport type TwilioMemoryConfig = z.infer<typeof TwilioMemoryConfigSchema>;\n\n/**\n * Schema for a voice route path (e.g. voiceWebsocketPath). Trims whitespace,\n * maps an empty string to undefined so the `.default` applies, and requires a\n * leading '/' so path concatenation onto the domain can't produce a malformed\n * URL (e.g. `wss://example.comws`).\n */\nconst voicePathSchema = (defaultPath: string): z.ZodType<string> =>\n z.preprocess(v => {\n if (typeof v !== 'string') return v;\n const trimmed = v.trim();\n return trimmed.length === 0 ? undefined : trimmed;\n }, z.string().startsWith('/', 'Path must start with \"/\"').default(defaultPath));\n\n/** The three Twilio call callbacks TAC serves, one route per kind. */\nexport const CallEventKindSchema = z.enum(['status', 'amd', 'recording']);\n\nexport type CallEventKind = z.infer<typeof CallEventKindSchema>;\n\n/** Iterable form of {@link CallEventKind}, for registering every route. */\nexport const CALL_EVENT_KINDS: readonly CallEventKind[] = CallEventKindSchema.options;\n\n/**\n * TAC configuration schema\n */\nexport const TACConfigSchema = z.object({\n accountSid: z.string().min(1, 'Twilio Account SID is required'),\n authToken: z.string().min(1, 'Twilio Auth Token is required'),\n apiKey: z.string().min(1, 'Twilio API Key is required'),\n apiSecret: z.string().min(1, 'Twilio API Secret is required'),\n phoneNumber: z.string().min(1, 'Twilio Phone Number is required'),\n rcsSenderId: z\n .string()\n .regex(\n /^rcs:.+$/,\n 'RCS sender ID must be in format: rcs:<sender-id-or-phone> (e.g., rcs:brand_acme_agent or rcs:+1234567890)'\n )\n .optional(),\n whatsappNumber: z\n .string()\n .regex(/^whatsapp:\\+\\d+$/, 'WhatsApp number must be in format: whatsapp:+1234567890')\n .optional(),\n memoryConfig: TwilioMemoryConfigSchema.prefault({}),\n conversationConfigurationId: z\n .string()\n .regex(/^conv_configuration_[0-9a-z]{26}$/, 'Invalid Conversation Configuration ID format')\n .optional(),\n /**\n * Public domain where voice routes are reachable, optionally including a port\n * and/or base path (e.g. \"example.ngrok.app\", \"example.ngrok.app:8080\",\n * or \"example.com/server1\"). Used by VoiceChannel to construct the public\n * WebSocket URL and ConversationRelay action URL. Required when using the Voice channel.\n *\n * Whitespace, schemes (https://, wss://), and trailing slashes are stripped\n * automatically; anything else is passed through as given. Mirrors the Python\n * SDK's `_normalize_voice_public_domain` — keep the two in step.\n */\n voicePublicDomain: z\n .preprocess(v => {\n if (typeof v !== 'string') return v;\n let s = v.trim();\n if (s.length === 0) return undefined;\n for (const scheme of ['https://', 'http://', 'wss://', 'ws://']) {\n if (s.toLowerCase().startsWith(scheme)) {\n s = s.slice(scheme.length);\n break;\n }\n }\n s = s.replace(/\\/+$/, '');\n return s.length === 0 ? undefined : s;\n }, z.string().optional())\n .optional(),\n\n /**\n * Path the voice WebSocket is served at. Combined with voicePublicDomain to\n * build the public WebSocket URL the voice channel hands to Twilio in TwiML;\n * TACServer also registers its WebSocket route at this path. Override only if\n * you mount the route at a non-default path. Must start with '/'.\n */\n voiceWebsocketPath: voicePathSchema('/ws'),\n\n /**\n * Path the ConversationRelay action callback is served at. Same role as\n * voiceWebsocketPath but for the `<Connect action=...>` cleanup callback.\n * Must start with '/'.\n */\n voiceActionPath: voicePathSchema('/conversation-relay-callback'),\n\n /**\n * Base path for the call-event callbacks (status, async AMD, recording).\n * TACServer registers one route per callback under it — `<base>/status`,\n * `<base>/amd`, `<base>/recording` — so the route identifies the event. Same\n * role as voiceActionPath. Must start with '/'.\n */\n voiceCallEventPath: voicePathSchema('/twilio/call-events'),\n cintelConfigurationId: z.string().optional(),\n cintelSummaryOperatorSid: z.string().optional(),\n region: z\n .string()\n .max(63, 'Invalid Twilio region format (must be a valid DNS label)')\n .regex(\n /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/,\n 'Invalid Twilio region format (must be a valid DNS label)'\n )\n .optional(),\n /**\n * Twilio Studio Flow SID (FWxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) for handoff.\n * TAC derives both the digital-handoff Studio Executions URL and the voice\n * `<Connect action>` webhook URL from this SID.\n */\n studioHandoffFlowSid: z\n .string()\n .regex(\n /^FW[0-9a-f]{32}$/,\n 'Invalid Studio Flow SID format (expected FW followed by 32 hex chars)'\n )\n .optional(),\n});\n\nexport type TACConfigData = z.infer<typeof TACConfigSchema>;\n\n/**\n * Environment variable mapping for configuration\n */\nexport const EnvironmentVariables = {\n TWILIO_ACCOUNT_SID: 'TWILIO_ACCOUNT_SID',\n TWILIO_AUTH_TOKEN: 'TWILIO_AUTH_TOKEN',\n TWILIO_API_KEY: 'TWILIO_API_KEY',\n TWILIO_API_SECRET: 'TWILIO_API_SECRET',\n TWILIO_PHONE_NUMBER: 'TWILIO_PHONE_NUMBER',\n TWILIO_RCS_SENDER_ID: 'TWILIO_RCS_SENDER_ID',\n TWILIO_WHATSAPP_NUMBER: 'TWILIO_WHATSAPP_NUMBER',\n TWILIO_MEMORY_PROFILE_TRAIT_GROUPS: 'TWILIO_MEMORY_PROFILE_TRAIT_GROUPS',\n TWILIO_MEMORY_OBSERVATIONS_LIMIT: 'TWILIO_MEMORY_OBSERVATIONS_LIMIT',\n TWILIO_MEMORY_SUMMARIES_LIMIT: 'TWILIO_MEMORY_SUMMARIES_LIMIT',\n TWILIO_MEMORY_COMMUNICATIONS_LIMIT: 'TWILIO_MEMORY_COMMUNICATIONS_LIMIT',\n TWILIO_MEMORY_RELEVANCE_THRESHOLD: 'TWILIO_MEMORY_RELEVANCE_THRESHOLD',\n TWILIO_MEMORY_PHONE_TRAIT_GROUP: 'TWILIO_MEMORY_PHONE_TRAIT_GROUP',\n TWILIO_MEMORY_PHONE_TRAIT_FIELD: 'TWILIO_MEMORY_PHONE_TRAIT_FIELD',\n TWILIO_CONVERSATION_CONFIGURATION_ID: 'TWILIO_CONVERSATION_CONFIGURATION_ID',\n TWILIO_VOICE_PUBLIC_DOMAIN: 'TWILIO_VOICE_PUBLIC_DOMAIN',\n TWILIO_VOICE_WEBSOCKET_PATH: 'TWILIO_VOICE_WEBSOCKET_PATH',\n TWILIO_VOICE_ACTION_PATH: 'TWILIO_VOICE_ACTION_PATH',\n TWILIO_VOICE_CALL_EVENT_PATH: 'TWILIO_VOICE_CALL_EVENT_PATH',\n TWILIO_TAC_CI_CONFIGURATION_ID: 'TWILIO_TAC_CI_CONFIGURATION_ID',\n TWILIO_TAC_CI_SUMMARY_OPERATOR_SID: 'TWILIO_TAC_CI_SUMMARY_OPERATOR_SID',\n TWILIO_REGION: 'TWILIO_REGION',\n TWILIO_STUDIO_HANDOFF_FLOW_SID: 'TWILIO_STUDIO_HANDOFF_FLOW_SID',\n} as const;\n","import { z } from 'zod';\n\n/**\n * Structured payload generated during a handoff.\n *\n * Contains conversation context and developer-defined attributes\n * for routing to the target system (e.g., Flex TaskRouter).\n *\n * Serialized with camelCase aliases (conversationId/storeId/profileId)\n * for the Studio Executions wire format.\n */\nexport const HandoffPayloadSchema = z.object({\n conversationId: z.string(),\n storeId: z.string(),\n profileId: z.string(),\n attributes: z.record(z.string(), z.unknown()).default({}),\n});\n\nexport type HandoffPayload = z.infer<typeof HandoffPayloadSchema>;\n\n/**\n * ConversationRelay WebSocket ``end`` message carrying a handoff payload.\n *\n * ``handoffData`` is a JSON *string* (not a nested object) — ConversationRelay\n * forwards it verbatim in the POST body to the ``<Connect action>`` URL.\n */\nexport const PendingHandoffDataSchema = z.object({\n type: z.literal('end').default('end'),\n handoffData: z.string(),\n});\n\nexport type PendingHandoffData = z.infer<typeof PendingHandoffDataSchema>;\n","import { z } from 'zod';\nimport { ChannelTypeSchema } from './config';\nimport { PendingHandoffDataSchema } from './handoff';\nimport type { TACMemoryResponse } from '../lib/tac-memory-response';\n\n/**\n * Participant address type for different communication channels\n */\nexport const ParticipantAddressTypeSchema = z.enum([\n 'VOICE',\n 'SMS',\n 'RCS',\n 'EMAIL',\n 'WHATSAPP',\n 'CHAT',\n 'API',\n 'SYSTEM',\n]);\nexport type ParticipantAddressType = z.infer<typeof ParticipantAddressTypeSchema>;\n\n/**\n * Participant address containing channel and address\n */\nexport const ParticipantAddressSchema = z.object({\n channel: ParticipantAddressTypeSchema,\n address: z.string().min(1, 'Address is required'),\n channelId: z.string().nullable().optional(),\n});\n\nexport type ParticipantAddress = z.infer<typeof ParticipantAddressSchema>;\n\n/**\n * Communication participant for Conversations Service API (Conversation Orchestrator).\n *\n * Note: participantId is required for SDK validation when creating communications.\n */\nexport const CommunicationParticipantSchema = z.object({\n address: z.string().max(254),\n channel: ParticipantAddressTypeSchema,\n participantId: z.string(),\n deliveryStatus: z\n .enum(['INITIATED', 'IN_PROGRESS', 'DELIVERED', 'COMPLETED', 'FAILED'])\n .optional(),\n});\n\nexport type CommunicationParticipant = z.infer<typeof CommunicationParticipantSchema>;\n\n/**\n * Word-level transcription data with timing information.\n */\nexport const TranscriptionWordSchema = z.object({\n text: z.string(),\n startTime: z.string().optional(),\n endTime: z.string().optional(),\n});\n\nexport type TranscriptionWord = z.infer<typeof TranscriptionWordSchema>;\n\n/**\n * Transcription metadata for communication content.\n */\nexport const TranscriptionSchema = z.object({\n channel: z.number().optional(),\n confidence: z.number().min(0).max(1).optional(),\n engine: z.string().optional(),\n words: z.array(TranscriptionWordSchema).optional(),\n});\n\nexport type Transcription = z.infer<typeof TranscriptionSchema>;\n\n/**\n * Communication content (ContentText or ContentTranscription).\n *\n * Note: In the Conversation Orchestrator API, both `type` and `text` are required fields.\n */\nexport const CommunicationContentSchema = z.object({\n type: z.enum(['TEXT', 'TRANSCRIPTION']),\n text: z.string().max(8388608),\n transcription: TranscriptionSchema.optional(),\n});\n\nexport type CommunicationContent = z.infer<typeof CommunicationContentSchema>;\n\n/**\n * Communication from Conversations Service API (Conversation Orchestrator).\n *\n * Note: `createdAt` is optional per API spec.\n */\nexport const CommunicationSchema = z.object({\n id: z.string(),\n conversationId: z.string(),\n accountId: z.string(),\n author: CommunicationParticipantSchema,\n content: CommunicationContentSchema,\n recipients: z.array(CommunicationParticipantSchema),\n channelId: z.string().nullable().optional(),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n occurredAt: z.string().nullable().optional(),\n});\n\nexport type Communication = z.infer<typeof CommunicationSchema>;\n\n/**\n * List communications response\n */\nexport const ListCommunicationsResponseSchema = z.object({\n communications: z.array(CommunicationSchema),\n});\n\nexport type ListCommunicationsResponse = z.infer<typeof ListCommunicationsResponseSchema>;\n\n/**\n * Participant reference for the Actions API (`from`/`to` entries).\n *\n * Either `participantId` or `address` must be supplied; `channel` is always required.\n * When both are provided, Conversation Orchestrator uses `participantId` and\n * `channel` disambiguates which of the participant's addresses to use.\n */\nexport const ActionParticipantRefSchema = z\n .object({\n participantId: z.string().min(1).optional(),\n address: z.string().min(1).max(254).optional(),\n channel: ParticipantAddressTypeSchema,\n })\n .refine(v => Boolean(v.participantId) || Boolean(v.address), {\n message: 'ActionParticipantRef requires at least `participantId` or `address`',\n });\n\nexport type ActionParticipantRef = z.infer<typeof ActionParticipantRefSchema>;\n\n/**\n * Plain-text content for a SEND_MESSAGE action.\n */\nexport const ActionTextContentSchema = z.object({\n text: z.string().max(8388608),\n});\n\nexport type ActionTextContent = z.infer<typeof ActionTextContentSchema>;\n\n/**\n * Channel-specific settings forwarded to the downstream backend.\n *\n * Open pass-through: any field not explicitly modeled here (e.g.\n * `messagingServiceSid`, `statusCallback`, `Attributes`) can be set by callers and\n * will be forwarded as-is.\n */\nexport const ActionChannelSettingsSchema = z.looseObject({\n channelId: z.string().optional(),\n});\n\nexport type ActionChannelSettings = z.infer<typeof ActionChannelSettingsSchema>;\n\n/**\n * Inner payload for a SEND_MESSAGE action.\n */\nexport const SendMessageActionPayloadSchema = z.object({\n from: ActionParticipantRefSchema,\n to: z.array(ActionParticipantRefSchema).min(1),\n content: ActionTextContentSchema,\n channelSettings: ActionChannelSettingsSchema.optional(),\n});\n\nexport type SendMessageActionPayload = z.infer<typeof SendMessageActionPayloadSchema>;\n\n/**\n * Request for POST /v2/Conversations/{id}/Actions with type=SEND_MESSAGE.\n *\n * Body is discriminated by `type` with the action-specific fields under `payload`.\n */\nexport const SendMessageActionRequestSchema = z.object({\n type: z.literal('SEND_MESSAGE').default('SEND_MESSAGE'),\n payload: SendMessageActionPayloadSchema,\n});\n\nexport type SendMessageActionRequest = z.infer<typeof SendMessageActionRequestSchema>;\n\n/**\n * Response from POST /v2/Conversations/{id}/Actions (202 Accepted).\n *\n * Listen for COMMUNICATION_CREATED webhook to get the full Communication.\n */\nexport const ActionResponseSchema = z.object({\n id: z.string(),\n // Kept as string (not enum) to tolerate future action types. Known: SEND_MESSAGE.\n type: z.string(),\n // Kept as string (not enum) to tolerate future statuses. Known: PENDING, COMPLETED, FAILED.\n status: z.string(),\n conversationId: z.string(),\n createdAt: z.string().nullish(),\n});\n\nexport type ActionResponse = z.infer<typeof ActionResponseSchema>;\n\n/**\n * Author information for a conversation session\n */\nexport const AuthorInfoSchema = z.object({\n address: z.string(),\n participantId: z.string().optional(),\n});\n\nexport type AuthorInfo = z.infer<typeof AuthorInfoSchema>;\n\n/**\n * Profile information for a conversation participant\n */\nexport interface Profile {\n profileId: string;\n traits?: Record<string, unknown>;\n}\n\n/**\n * Conversation session context\n */\nexport const ConversationSessionSchema = z.object({\n conversationId: z.string().min(1, 'Conversation ID is required'),\n /**\n * Twilio Call SID on the Voice channel, unset on messaging. The correlation\n * key for call events (`VoiceChannel.onCallStatus` / `onAmd` / `onRecording`)\n * and `endCall`. Equals `conversationId` in relay-only mode; look the session\n * up the other way with `VoiceChannel.getConversationSessionByCallSid`.\n */\n callSid: z.string().optional(),\n profileId: z.string().optional(),\n serviceId: z.string().optional(),\n channel: ChannelTypeSchema,\n startedAt: z.date(),\n authorInfo: AuthorInfoSchema.optional(),\n /**\n * Agent-side participant info stashed by inbound reconciliation or outbound\n * initiation. `sendResponse` reads this to avoid re-listing participants at\n * send time.\n */\n aiAgentInfo: AuthorInfoSchema.optional(),\n profile: z.custom<Profile>().optional(),\n metadata: z.record(z.string(), z.unknown()).optional().default({}),\n /**\n * Pending handoff payload set by the handoff tool. Voice channel sends\n * this as a WS \"end\" message after the LLM's final response.\n */\n pendingHandoffData: PendingHandoffDataSchema.optional(),\n /**\n * Cached memory for \"once\" mode. Set on the first retrieval, cleared when\n * the conversation becomes INACTIVE. Not persisted/serialized.\n */\n cachedMemory: z.custom<TACMemoryResponse>().optional(),\n});\n\nexport type ConversationSession = z.infer<typeof ConversationSessionSchema>;\n\n/**\n * Branded types for type safety\n */\nexport type ConversationId = string & { readonly _brand: 'ConversationId' };\nexport type ProfileId = string & { readonly _brand: 'ProfileId' };\nexport type ParticipantId = string & { readonly _brand: 'ParticipantId' };\n\n/**\n * Type guards for branded types\n */\nexport function isConversationId(value: string): value is ConversationId {\n return value.length > 0;\n}\n\nexport function isProfileId(value: string): value is ProfileId {\n return value.length > 0;\n}\n\nexport function isParticipantId(value: string): value is ParticipantId {\n return value.length > 0;\n}\n\n/**\n * Conversation response from Conversations Service API\n */\nexport const ConversationResponseSchema = z.object({\n id: z.string(),\n accountId: z.string(),\n status: z.string().optional(),\n name: z.string().nullish(), // API returns null when not set\n configurationId: z.string().optional(),\n createdAt: z.string().optional(),\n updatedAt: z.string().optional(),\n});\n\nexport type ConversationResponse = z.infer<typeof ConversationResponseSchema>;\n\n/**\n * List conversations response\n */\nexport const ListConversationsResponseSchema = z.object({\n conversations: z.array(ConversationResponseSchema),\n});\n\nexport type ListConversationsResponse = z.infer<typeof ListConversationsResponseSchema>;\n\n/**\n * Participant address from Conversations Service API (camelCase format)\n */\nexport const ConversationAddressSchema = z.object({\n channel: ParticipantAddressTypeSchema,\n address: z.string(),\n channelId: z.string().nullish(), // API returns null when not set\n});\n\nexport type ConversationAddress = z.infer<typeof ConversationAddressSchema>;\n\n/**\n * Participant response from Conversations Service API\n */\nexport const ConversationParticipantSchema = z.object({\n id: z.string(),\n conversationId: z.string(),\n accountId: z.string(),\n name: z.string().optional(),\n type: z.enum(['HUMAN_AGENT', 'CUSTOMER', 'AI_AGENT', 'AGENT', 'UNKNOWN']).optional(),\n profileId: z.string().nullable().optional(),\n addresses: z.array(ConversationAddressSchema).default([]),\n createdAt: z.string().optional(),\n updatedAt: z.string().optional(),\n});\n\nexport type ConversationParticipant = z.infer<typeof ConversationParticipantSchema>;\n\n/**\n * List participants response\n */\nexport const ListParticipantsResponseSchema = z.object({\n participants: z.array(ConversationParticipantSchema),\n});\n\nexport type ListParticipantsResponse = z.infer<typeof ListParticipantsResponseSchema>;\n\n/**\n * Timeout settings for channel status transitions\n */\nexport const StatusTimeoutsSchema = z.object({\n inactive: z.number().int().gte(1).nullable().optional(),\n closed: z.number().int().gte(1),\n});\n\nexport type StatusTimeouts = z.infer<typeof StatusTimeoutsSchema>;\n\n/**\n * Capture rule with from/to addresses and optional metadata\n */\nexport const CaptureRuleSchema = z.object({\n from: z.string(),\n to: z.string(),\n metadata: z.record(z.string(), z.string()).nullable().optional(),\n});\n\nexport type CaptureRule = z.infer<typeof CaptureRuleSchema>;\n\n/**\n * Configuration settings for a specific channel type\n */\nexport const ChannelSettingsSchema = z.object({\n statusTimeouts: StatusTimeoutsSchema.nullable().optional(),\n captureRules: z.array(CaptureRuleSchema).nullable().optional(),\n});\n\nexport type ChannelSettings = z.infer<typeof ChannelSettingsSchema>;\n\n/**\n * Webhook configuration for status callbacks\n */\nexport const StatusCallbackSchema = z.object({\n url: z.url(),\n method: z.enum(['POST', 'GET', 'PUT', 'DELETE', 'PATCH']).optional().default('POST'),\n});\n\nexport type StatusCallback = z.infer<typeof StatusCallbackSchema>;\n\n/**\n * Conversation grouping type\n *\n * - `GROUP_BY_PROFILE`: Groups communications by participant profile. Communications\n * with the same profile go to the same conversation, regardless of the channel or address.\n * - `GROUP_BY_PARTICIPANT_ADDRESSES`: Groups communications by participant addresses\n * across all channels. A customer using +15551234567 will be in the same conversation\n * whether they contact via SMS, WhatsApp, or RCS.\n * - `GROUP_BY_PARTICIPANT_ADDRESSES_AND_CHANNEL_TYPE`: Groups communications by both\n * participant addresses AND channel. A customer using +15551234567 via SMS will be in\n * a different conversation than the same customer via WhatsApp.\n */\nexport const ConversationGroupingTypeSchema = z.enum([\n 'GROUP_BY_PROFILE',\n 'GROUP_BY_PARTICIPANT_ADDRESSES',\n 'GROUP_BY_PARTICIPANT_ADDRESSES_AND_CHANNEL_TYPE',\n]);\n\nexport type ConversationGroupingType = z.infer<typeof ConversationGroupingTypeSchema>;\n\n/**\n * Configuration settings for a conversation\n */\nexport const ConversationConfigurationSchema = z.object({\n id: z.string(),\n displayName: z\n .string()\n .max(32)\n .regex(/^[a-zA-Z0-9-_ ]+$/)\n .nullable()\n .optional(),\n description: z.string(),\n conversationGroupingType: ConversationGroupingTypeSchema,\n memoryStoreId: z\n .string()\n .regex(/^mem_(store|service)_[0-7][0-9a-z]{25}$/, 'Invalid Memory Store ID format'),\n channelSettings: z.record(z.string(), ChannelSettingsSchema).nullable().optional(),\n statusCallbacks: z.array(StatusCallbackSchema).max(20).nullable().optional(),\n intelligenceConfigurationIds: z.array(z.string()).max(5).nullable().optional(),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n version: z.number().int().nullable().optional(),\n});\n\nexport type ConversationConfiguration = z.infer<typeof ConversationConfigurationSchema>;\n\n// =========================================================================\n// Outbound Conversation Types\n// =========================================================================\n\n/**\n * Options for initiating an outbound SMS conversation.\n *\n * The sender is always TAC's configured `config.phoneNumber`. Multi-sender\n * deployments should run one TAC instance per sender so inbound webhook\n * routing, memory scoping, and configuration stay in sync.\n */\nexport const InitiateMessagingConversationOptionsSchema = z.object({\n to: z.string().min(1, 'Recipient address is required'),\n message: z.string().min(1, 'Initial message is required'),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type InitiateMessagingConversationOptions = z.infer<\n typeof InitiateMessagingConversationOptionsSchema\n>;\n\n/**\n * Result of initiating an outbound conversation\n */\nexport interface InitiateConversationResult {\n conversationId: ConversationId;\n session: ConversationSession;\n}\n\n/**\n * Result of initiating an outbound voice conversation.\n * Note: conversationId is not included because the conversation is created by\n * Conversation Orchestrator during passive hydration — the SDK discovers it by\n * callSid, in the background from WebSocket setup.\n */\nexport interface InitiateVoiceConversationResult {\n callSid: string;\n}\n\n/**\n * Webhook payload structure from Twilio Conversation Orchestrator.\n * This structure is used by all channels (messaging and voice) for webhook events.\n */\nexport interface ConversationWebhookPayload {\n eventType: string;\n timestamp?: string;\n data?: {\n id?: string;\n conversationId?: string;\n accountId?: string;\n serviceId?: string;\n status?: string;\n participantType?: string;\n profileId?: string;\n channelId?: string;\n author?: {\n address?: string;\n channel?: string;\n participantId?: string;\n };\n content?: {\n type?: string;\n text?: string;\n };\n recipients?: Array<{\n address?: string;\n channel?: string;\n participantId?: string;\n deliveryStatus?: string;\n }>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n","import { z } from 'zod';\nimport { TranscriptionSchema } from './conversation';\n\n/**\n * Channel type for communications\n */\nexport const TACChannelTypeSchema = z.enum([\n 'VOICE',\n 'SMS',\n 'RCS',\n 'EMAIL',\n 'WHATSAPP',\n 'CHAT',\n 'API',\n 'SYSTEM',\n]);\nexport type TACChannelType = z.infer<typeof TACChannelTypeSchema>;\n\n/**\n * Delivery status for communications\n */\nexport const TACDeliveryStatusSchema = z.enum([\n 'INITIATED',\n 'IN_PROGRESS',\n 'DELIVERED',\n 'COMPLETED',\n 'FAILED',\n]);\nexport type TACDeliveryStatus = z.infer<typeof TACDeliveryStatusSchema>;\n\n/**\n * Participant type\n */\nexport const TACParticipantTypeSchema = z.enum(['HUMAN_AGENT', 'CUSTOMER', 'AI_AGENT', 'AGENT']);\nexport type TACParticipantType = z.infer<typeof TACParticipantTypeSchema>;\n\n/**\n * Unified author model with all fields from both Memory and Conversation Orchestrator APIs.\n *\n * Fields not available from a particular API will be undefined.\n */\nexport const TACCommunicationAuthorSchema = z.object({\n // Common fields (both APIs)\n address: z.string(),\n channel: TACChannelTypeSchema,\n\n // Conversation Orchestrator-only fields\n participantId: z.string().optional(),\n deliveryStatus: TACDeliveryStatusSchema.optional(),\n\n // Memory-only fields\n id: z.string().optional(),\n name: z.string().optional(),\n type: TACParticipantTypeSchema.optional(),\n profileId: z.string().nullable().optional(),\n});\n\nexport type TACCommunicationAuthor = z.infer<typeof TACCommunicationAuthorSchema>;\n\n/**\n * Unified content model with all fields from both Memory and Conversation Orchestrator APIs.\n */\nexport const TACCommunicationContentSchema = z.object({\n // Conversation Orchestrator-only: content type discriminator\n type: z.enum(['TEXT', 'TRANSCRIPTION']).optional(),\n // Both APIs: message text (optional in unified model to handle both)\n text: z.string().optional(),\n // Conversation Orchestrator-only: transcription metadata\n transcription: TranscriptionSchema.optional(),\n});\n\nexport type TACCommunicationContent = z.infer<typeof TACCommunicationContentSchema>;\n\n/**\n * Unified communication model with all fields from both Memory and Conversation Orchestrator APIs.\n *\n * Provides complete access to all communication fields regardless of the source.\n * Fields not available from a particular API will be undefined.\n */\nexport const TACCommunicationSchema = z.object({\n // Common fields (both APIs)\n id: z.string(),\n author: TACCommunicationAuthorSchema,\n content: TACCommunicationContentSchema,\n recipients: z.array(TACCommunicationAuthorSchema).default([]),\n channelId: z.string().nullable().optional(),\n createdAt: z.string().optional(),\n updatedAt: z.string().optional(),\n\n // Conversation Orchestrator-only fields\n conversationId: z.string().optional(),\n accountId: z.string().optional(),\n});\n\nexport type TACCommunication = z.infer<typeof TACCommunicationSchema>;\n","import { Communication } from '../types/conversation';\nimport { MemoryRetrievalResponse, ObservationInfo, SummaryInfo } from '../types/memory';\nimport { TACCommunication, TACCommunicationSchema } from '../types/tac';\n\n/**\n * Type guard to check if data is MemoryRetrievalResponse.\n */\nfunction isMemoryRetrievalResponse(\n data: MemoryRetrievalResponse | Communication[]\n): data is MemoryRetrievalResponse {\n return !Array.isArray(data);\n}\n\n/**\n * Unified response wrapper for TAC.retrieveMemory().\n *\n * Provides a consistent interface for accessing memory data regardless of whether\n * Memory API is configured or falling back to Conversation Orchestrator Communications API.\n *\n * Memory configured:\n * - observations, summaries, communications all populated\n * - communications include Memory-specific fields (author id, name, type, profileId)\n *\n * Conversation Orchestrator fallback:\n * - observations and summaries are empty arrays\n * - communications include Conversation Orchestrator-specific fields (conversationId, accountId, etc.)\n */\nexport class TACMemoryResponse {\n private readonly _data: MemoryRetrievalResponse | Communication[];\n private readonly _communications: TACCommunication[];\n\n /**\n * Initialize wrapper with either Memory or Conversation Orchestrator data.\n *\n * @param data - Either MemoryRetrievalResponse (Memory) or Communication[] (Conversation Orchestrator)\n */\n constructor(data: MemoryRetrievalResponse | Communication[]) {\n this._data = data;\n\n if (isMemoryRetrievalResponse(data)) {\n this._communications = (data.communications ?? []).map(comm =>\n TACCommunicationSchema.parse(comm)\n );\n } else {\n this._communications = data.map(comm => TACCommunicationSchema.parse(comm));\n }\n }\n\n /**\n * Get observation memories.\n *\n * @returns List of observations if Memory is configured, empty array for Conversation Orchestrator fallback\n */\n get observations(): ObservationInfo[] {\n if (isMemoryRetrievalResponse(this._data)) {\n return this._data.observations;\n }\n return [];\n }\n\n /**\n * Get summary memories.\n *\n * @returns List of summaries if Memory is configured, empty array for Conversation Orchestrator fallback\n */\n get summaries(): SummaryInfo[] {\n if (isMemoryRetrievalResponse(this._data)) {\n return this._data.summaries;\n }\n return [];\n }\n\n /**\n * Get communications in unified format with all available fields.\n *\n * Communications are converted to a common format during initialization that includes\n * all fields from both Memory and Conversation Orchestrator APIs. Fields not available from a particular\n * API will be undefined.\n *\n * @returns List of unified communications with all available fields\n */\n get communications(): TACCommunication[] {\n return this._communications;\n }\n\n /**\n * Check if Memory API is configured and providing full features.\n *\n * @returns true if Memory is configured (observations/summaries available),\n * false if using Conversation Orchestrator fallback (only communications available)\n */\n get hasMemoryFeatures(): boolean {\n return isMemoryRetrievalResponse(this._data);\n }\n\n /**\n * Access raw underlying data for advanced use cases.\n *\n * Use this when you need access to all fields from the original API responses,\n * not just the unified common fields.\n *\n * @returns Either MemoryRetrievalResponse or Communication[] depending on configuration\n */\n get rawData(): MemoryRetrievalResponse | Communication[] {\n return this._data;\n }\n\n /**\n * Build formatted prompt sections from available memory data.\n *\n * Generates markdown-formatted sections for observations, summaries, and communications\n * that can be injected into LLM prompts. Each section includes a heading and formatted content.\n * Sections with no data are omitted from the result.\n *\n * @returns Array of formatted prompt sections, empty array if no memory data available\n */\n buildMemoryPrompts(): string[] {\n const sections: string[] = [];\n\n const observationsSection = this.buildObservationsPrompt();\n if (observationsSection) {\n sections.push(observationsSection);\n }\n\n const summariesSection = this.buildSummariesPrompt();\n if (summariesSection) {\n sections.push(summariesSection);\n }\n\n const communicationsSection = this.buildCommunicationsPrompt();\n if (communicationsSection) {\n sections.push(communicationsSection);\n }\n\n return sections;\n }\n\n private buildObservationsPrompt(): string | null {\n if (this.observations.length === 0) {\n return null;\n }\n\n const lines = [\n '## Key Observations',\n 'Important notes about the customer from previous interactions:',\n ];\n\n for (const obs of this.observations) {\n lines.push(`- ${obs.content}`);\n }\n\n return lines.join('\\n');\n }\n\n private buildSummariesPrompt(): string | null {\n if (this.summaries.length === 0) {\n return null;\n }\n\n const lines = [\n '## Past Conversation Summaries',\n 'Summaries of previous conversations with this customer:',\n ];\n\n for (const summary of this.summaries) {\n lines.push(`- ${summary.content}`);\n }\n\n return lines.join('\\n');\n }\n\n private buildCommunicationsPrompt(): string | null {\n if (this.communications.length === 0) {\n return null;\n }\n\n const lines = ['## Recent Message History', 'Recent messages exchanged with this customer:'];\n\n for (const comm of this.communications) {\n const content = comm.content?.text;\n if (typeof content !== 'string' || content.trim().length === 0) {\n continue;\n }\n // Determine role - defaults to \"Assistant\" for undefined or non-CUSTOMER authors\n const role = comm.author?.type === 'CUSTOMER' ? 'User' : 'Assistant';\n lines.push(`${role}: ${content}`);\n }\n\n return lines.length > 2 ? lines.join('\\n') : null;\n }\n}\n","import { z } from 'zod';\n\n/**\n * Memory retrieval mode for channels.\n *\n * - \"always\": Fetch memory with the message as query on every inbound message.\n * - \"once\": Fetch memory once at conversation start with no query (and no\n * conversation id, skipping query expansion) and cache it. The cache is\n * invalidated when the conversation becomes INACTIVE.\n * - \"never\": Never automatically fetch memory (default).\n */\nexport const MemoryModeSchema = z.enum(['always', 'never', 'once']);\nexport type MemoryMode = z.infer<typeof MemoryModeSchema>;\n\n/**\n * Message direction in a conversation\n */\nexport const MessageDirectionSchema = z.enum(['inbound', 'outbound']);\nexport type MessageDirection = z.infer<typeof MessageDirectionSchema>;\n\n/**\n * Channel type for Memory communications\n */\nexport const MemoryChannelTypeSchema = z.enum([\n 'VOICE',\n 'SMS',\n 'RCS',\n 'EMAIL',\n 'WHATSAPP',\n 'CHAT',\n 'API',\n 'SYSTEM',\n]);\nexport type MemoryChannelType = z.infer<typeof MemoryChannelTypeSchema>;\n\n/**\n * Participant type in Memory API\n */\nexport const MemoryParticipantTypeSchema = z.enum([\n 'HUMAN_AGENT',\n 'CUSTOMER',\n 'AI_AGENT',\n 'AGENT',\n 'UNKNOWN',\n]);\nexport type MemoryParticipantType = z.infer<typeof MemoryParticipantTypeSchema>;\n\n/**\n * Delivery status for Memory communications\n */\nexport const MemoryDeliveryStatusSchema = z.enum([\n 'INITIATED',\n 'IN_PROGRESS',\n 'DELIVERED',\n 'COMPLETED',\n 'FAILED',\n]);\nexport type MemoryDeliveryStatus = z.infer<typeof MemoryDeliveryStatusSchema>;\n\n/**\n * Participant in a Memory communication (author or recipient).\n *\n * Memory API has different field requirements than Conversation Orchestrator:\n * - Uses `id` and `name` instead of just `participant_id`\n * - Includes `type` and `profileId` fields\n */\nexport const MemoryParticipantSchema = z.object({\n id: z.string(),\n name: z.string().max(256),\n address: z.string().max(254),\n channel: MemoryChannelTypeSchema,\n type: MemoryParticipantTypeSchema.optional(),\n profileId: z.string().nullable().optional(),\n deliveryStatus: MemoryDeliveryStatusSchema.optional(),\n});\n\nexport type MemoryParticipant = z.infer<typeof MemoryParticipantSchema>;\n\n/**\n * Content of a Memory communication.\n *\n * Memory API content is simpler than Conversation Orchestrator - no type discriminator field.\n * The `text` field is optional in Memory API models.\n */\nexport const MemoryCommunicationContentSchema = z.object({\n text: z.string().max(8388608).optional(),\n});\n\nexport type MemoryCommunicationContent = z.infer<typeof MemoryCommunicationContentSchema>;\n\n/**\n * A communication from Memory API (historical conversation data).\n *\n * Memory API has different field requirements than Conversation Orchestrator:\n * - No `conversationId`, `accountId`, or `content.type` fields\n * - Participants use `id`, `name`, `type`, `profileId`\n */\nexport const MemoryCommunicationSchema = z.object({\n id: z.string(),\n author: MemoryParticipantSchema,\n content: MemoryCommunicationContentSchema,\n recipients: z.array(MemoryParticipantSchema).max(100),\n channelId: z.string().max(256).nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string().optional(),\n});\n\nexport type MemoryCommunication = z.infer<typeof MemoryCommunicationSchema>;\n\n/**\n * Individual session message\n */\nexport const SessionMessageSchema = z.object({\n direction: MessageDirectionSchema,\n channel: z.string(),\n from_address: z.string().optional(),\n to_address: z.string().optional(),\n content: z.string(),\n timestamp: z.iso.datetime(),\n});\n\nexport type SessionMessage = z.infer<typeof SessionMessageSchema>;\n\n/**\n * Session information containing conversation history\n */\nexport const SessionInfoSchema = z.object({\n session_id: z.string(),\n started_at: z.iso.datetime(),\n ended_at: z.iso.datetime().optional(),\n channel: z.string(),\n messages: z.array(SessionMessageSchema),\n});\n\nexport type SessionInfo = z.infer<typeof SessionInfoSchema>;\n\n/**\n * Individual observation extracted from conversations\n */\nexport const ObservationInfoSchema = z.object({\n id: z.string(),\n content: z.string(),\n createdAt: z.iso.datetime(),\n occurredAt: z.iso.datetime().optional(),\n updatedAt: z.iso.datetime().optional(),\n conversationIds: z.array(z.string()).nullable().optional(),\n source: z.string().optional(),\n});\n\nexport type ObservationInfo = z.infer<typeof ObservationInfoSchema>;\n\n/**\n * Conversation summary information\n */\nexport const SummaryInfoSchema = z.object({\n id: z.string(),\n content: z.string(),\n createdAt: z.iso.datetime(),\n updatedAt: z.iso.datetime().optional(),\n conversationIds: z.array(z.string()).optional(),\n});\n\nexport type SummaryInfo = z.infer<typeof SummaryInfoSchema>;\n\n/**\n * Memory retrieval request parameters.\n *\n * Defaults match the Memory API server defaults. The SDK-level defaults in\n * TwilioMemoryConfigSchema may differ (e.g. communicationsLimit defaults to 10\n * in the SDK config for a better out-of-box experience, vs 0 on the API).\n */\nexport const MemoryRetrievalRequestSchema = z.object({\n conversationId: z.string().optional(),\n query: z.string().optional(),\n beginDate: z.iso.datetime().optional(),\n endDate: z.iso.datetime().optional(),\n observationsLimit: z.number().int().min(0).max(100).optional(),\n summariesLimit: z.number().int().min(0).max(100).optional(),\n communicationsLimit: z.number().int().min(0).max(100).optional(),\n relevanceThreshold: z.number().min(0.0).max(1.0).optional(),\n});\n\nexport type MemoryRetrievalRequest = z.infer<typeof MemoryRetrievalRequestSchema>;\n\n/**\n * Memory retrieval response from the Memory API /Recall endpoint.\n *\n * Contains observations, summaries, and communications from Memory API.\n */\nexport const MemoryRetrievalResponseSchema = z.object({\n observations: z.array(ObservationInfoSchema),\n summaries: z.array(SummaryInfoSchema),\n communications: z.array(MemoryCommunicationSchema).optional().default([]),\n meta: z\n .object({\n queryTime: z.number().optional(),\n })\n .optional(),\n});\n\nexport type MemoryRetrievalResponse = z.infer<typeof MemoryRetrievalResponseSchema>;\n\n/**\n * Profile lookup response\n */\nexport const ProfileLookupResponseSchema = z.object({\n normalizedValue: z.string().max(255),\n profiles: z\n .array(z.string())\n .max(100)\n .nullable()\n .transform(v => v ?? []),\n});\n\nexport type ProfileLookupResponse = z.infer<typeof ProfileLookupResponseSchema>;\n\n/**\n * Profile response with traits\n */\nexport const ProfileResponseSchema = z.object({\n id: z.string(),\n createdAt: z.string(),\n traits: z.record(z.string(), z.unknown()),\n});\n\nexport type ProfileResponse = z.infer<typeof ProfileResponseSchema>;\n\n/**\n * Empty memory response for error fallback\n */\nexport const EMPTY_MEMORY_RESPONSE: MemoryRetrievalResponse = {\n observations: [],\n summaries: [],\n communications: [],\n};\n\n/**\n * A single observation in a create request.\n *\n * `occurredAt` is required by the Memory API and formatted as ISO 8601.\n */\nexport const ObservationCreateRequestSchema = z.object({\n content: z.string(),\n source: z.string(),\n occurredAt: z.string(),\n conversationIds: z.array(z.string()).optional(),\n});\n\nexport type ObservationCreateRequest = z.infer<typeof ObservationCreateRequestSchema>;\n\n/**\n * Request body for the Memory API Observations endpoint.\n *\n * The endpoint is a batch create that wraps observations in an array.\n */\nexport const CreateObservationsRequestSchema = z.object({\n observations: z.array(ObservationCreateRequestSchema),\n});\n\nexport type CreateObservationsRequest = z.infer<typeof CreateObservationsRequestSchema>;\n\n/**\n * Response from creating an observation.\n *\n * The Memory API Observations endpoint is a batch create that returns a\n * confirmation message rather than the persisted observation.\n */\nexport const CreateObservationResponseSchema = z.object({\n message: z.string(),\n});\n\nexport type CreateObservationResponse = z.infer<typeof CreateObservationResponseSchema>;\n\n/**\n * Response from creating conversation summaries\n */\nexport const CreateConversationSummariesResponseSchema = z.object({\n message: z.string(),\n});\n\nexport type CreateConversationSummariesResponse = z.infer<\n typeof CreateConversationSummariesResponseSchema\n>;\n","import { z } from 'zod';\nimport type VoiceResponse from 'twilio/lib/twiml/VoiceResponse.js';\nimport type { CallListInstanceCreateOptions } from 'twilio/lib/rest/api/v2010/account/call.js';\n\n/**\n * ConversationRelay API Types\n *\n * Zod schemas are the single source of truth for runtime validation. Types are\n * inferred from schemas via z.infer. Compile-time drift guards (type assertions\n * against VoiceResponse.ConversationRelayAttributes / LanguageAttributes) ensure\n * that if the Twilio SDK types change, `npm run typecheck` will fail immediately.\n *\n * @see https://www.twilio.com/docs/voice/conversationrelay\n * @see https://www.twilio.com/docs/voice/conversationrelay/conversationrelay-noun\n */\n\n/**\n * Language configuration for multi-language ConversationRelay support\n * @see https://www.twilio.com/docs/voice/conversationrelay/conversationrelay-noun#language-attributes\n */\nexport const LanguageAttributesSchema = z.object({\n /** Language code (e.g., 'en-US', 'es-ES', 'en-AU') */\n code: z.string(),\n /** TTS provider for this language */\n ttsProvider: z.string().optional(),\n /** TTS voice for this language */\n voice: z.string().optional(),\n /** TTS language (may differ from code) */\n ttsLanguage: z.string().optional(),\n /** Transcription provider for this language */\n transcriptionProvider: z.string().optional(),\n /** Speech model for transcription */\n speechModel: z.string().optional(),\n /** Transcription language (may differ from code) */\n transcriptionLanguage: z.string().optional(),\n});\n\nexport type LanguageAttributes = z.infer<typeof LanguageAttributesSchema>;\n\n/**\n * ConversationRelay attributes for TwiML configuration\n * @see https://www.twilio.com/docs/voice/conversationrelay/conversationrelay-noun\n */\nexport const ConversationRelayAttributesSchema = z.object({\n /** WebSocket URL for ConversationRelay (required) */\n url: z.url(),\n\n // Welcome greeting settings\n /** Initial greeting to play when call connects */\n welcomeGreeting: z.string().optional(),\n /** Whether welcome greeting can be interrupted */\n welcomeGreetingInterruptible: z.enum(['any', 'speech', 'none']).optional(),\n\n // Transcription settings\n /** Transcription provider (e.g., 'Deepgram', 'Google') */\n transcriptionProvider: z.string().optional(),\n /** Language for transcription (e.g., 'en-US') */\n transcriptionLanguage: z.string().optional(),\n /** Speech model for transcription (e.g., 'nova-3-general') */\n speechModel: z.string().optional(),\n\n // TTS settings\n /** Text-to-speech provider (e.g., 'Google', 'ElevenLabs') */\n ttsProvider: z.string().optional(),\n /** Language for TTS (e.g., 'en-US') */\n ttsLanguage: z.string().optional(),\n /** Voice identifier for TTS (e.g., 'en-US-Journey-O') */\n voice: z.string().optional(),\n /** ElevenLabs text normalization setting */\n elevenlabsTextNormalization: z.string().optional(),\n\n // Interaction settings\n /** When agent speech can be interrupted */\n interruptible: z.enum(['any', 'speech', 'none']).optional(),\n /** Interrupt detection sensitivity */\n interruptSensitivity: z.enum(['low', 'medium', 'high']).optional(),\n /** Enable DTMF tone detection */\n dtmfDetection: z.boolean().optional(),\n /** Recognition hints for domain-specific vocabulary */\n hints: z.string().optional(),\n /** Whether prompts should be reported when TTS is playing and interrupt is disabled */\n reportInputDuringAgentSpeech: z.boolean().optional(),\n\n // Advanced settings\n /** Enable partial prompts (streaming) */\n partialPrompts: z.boolean().optional(),\n /** Enable profanity filtering */\n profanityFilter: z.boolean().optional(),\n /** Allow preemption of agent speech */\n preemptible: z.boolean().optional(),\n /** Default language code */\n language: z.string().optional(),\n /** Debug options for troubleshooting (string per SDK, not boolean) */\n debug: z.string().optional(),\n\n // Intelligence service\n /** Conversational Intelligence Service ID or unique name */\n intelligenceService: z.string().optional(),\n\n // Conversation orchestrator\n /** Twilio Conversation Orchestrator configuration ID */\n conversationConfiguration: z.string().optional(),\n});\n\nexport type ConversationRelayAttributes = z.infer<typeof ConversationRelayAttributesSchema>;\n\n/**\n * @internal Compile-time SDK drift guards — do not use directly.\n * If the Twilio SDK updates VoiceResponse.ConversationRelayAttributes or\n * VoiceResponse.LanguageAttributes, these checks will fail during typecheck,\n * signaling that our Zod schemas need to be updated to match.\n */\nexport type _SDKDriftGuards = {\n langCompat: LanguageAttributes extends VoiceResponse.LanguageAttributes ? true : never;\n langKeys: keyof VoiceResponse.LanguageAttributes extends keyof LanguageAttributes ? true : never;\n crelayCompat: ConversationRelayAttributes extends VoiceResponse.ConversationRelayAttributes\n ? true\n : never;\n crelayKeys: keyof VoiceResponse.ConversationRelayAttributes extends keyof ConversationRelayAttributes\n ? true\n : never;\n};\n\n/**\n * Custom parameters passed via TwiML\n * Can contain any key-value pairs with unknown values\n */\nexport const CustomParametersSchema = z.record(z.string(), z.unknown());\n\nexport type CustomParameters = z.infer<typeof CustomParametersSchema>;\n\n/**\n * WebSocket setup message from ConversationRelay\n */\nexport const SetupMessageSchema = z.object({\n type: z.literal('setup'),\n sessionId: z.string(),\n callSid: z.string(),\n parentCallSid: z.string().optional(),\n from: z.string(),\n to: z.string(),\n forwardedFrom: z.string().optional(),\n callerName: z.string().optional(),\n direction: z.string(),\n callType: z.string(),\n callStatus: z.string(),\n accountSid: z.string(),\n customParameters: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type SetupMessage = z.infer<typeof SetupMessageSchema>;\n\n/**\n * WebSocket prompt message (user speech)\n */\nexport const PromptMessageSchema = z.object({\n type: z.literal('prompt'),\n voicePrompt: z.string(),\n lang: z.string().optional(),\n last: z.boolean().optional(),\n agentSpeaking: z.string().optional(),\n});\n\nexport type PromptMessage = z.infer<typeof PromptMessageSchema>;\n\n/**\n * WebSocket interrupt message (user interruption)\n */\nexport const InterruptMessageSchema = z.object({\n type: z.literal('interrupt'),\n utteranceUntilInterrupt: z.string().optional(),\n durationUntilInterruptMs: z.number().int().nonnegative().optional(),\n});\n\nexport type InterruptMessage = z.infer<typeof InterruptMessageSchema>;\n\n/**\n * WebSocket DTMF message (caller pressed a key).\n *\n * Only sent when `dtmfDetection` is enabled on `<ConversationRelay>`, and one\n * message per keypress — digits are never batched.\n *\n * @see https://www.twilio.com/docs/voice/conversationrelay/websocket-messages#dtmf-message\n */\nexport const DtmfMessageSchema = z.object({\n type: z.literal('dtmf'),\n /** The key pressed: `0`-`9`, `*`, `#`, or `A`-`D`. */\n digit: z.string(),\n});\n\nexport type DtmfMessage = z.infer<typeof DtmfMessageSchema>;\n\n/**\n * Union of all WebSocket message types\n */\nexport const WebSocketMessageSchema = z.union([\n SetupMessageSchema,\n PromptMessageSchema,\n InterruptMessageSchema,\n DtmfMessageSchema,\n]);\n\nexport type WebSocketMessage = z.infer<typeof WebSocketMessageSchema>;\n\n/**\n * Text Token Message to send back via WebSocket\n * @see https://www.twilio.com/docs/voice/conversationrelay/websocket-messages#text-tokens-message\n */\nexport const TextTokenMessageSchema = z.object({\n type: z.literal('text'),\n token: z.string(),\n last: z.boolean().optional().default(true),\n});\n\nexport type TextTokenMessage = z.infer<typeof TextTokenMessageSchema>;\n\n/**\n * Extended ConversationRelay configuration that includes child elements.\n * Includes all ConversationRelayAttributes fields plus support for languages array.\n *\n * Note: The type is defined as an explicit interface and the schema is annotated\n * with z.ZodType<ConversationRelayConfig> to prevent TypeScript's type inference\n * from collapsing to `any` when resolving complex Zod generics with many optional\n * fields (especially under exactOptionalPropertyTypes).\n */\nexport interface ConversationRelayConfig extends ConversationRelayAttributes {\n /** Optional language configurations as child <Language> elements */\n languages?: LanguageAttributes[] | undefined;\n}\n\nexport const ConversationRelayConfigSchema: z.ZodType<ConversationRelayConfig> =\n ConversationRelayAttributesSchema.extend({\n /** Optional language configurations as child <Language> elements */\n languages: z.array(LanguageAttributesSchema).optional(),\n });\n\n// =========================================================================\n// TwiML customization layer\n// =========================================================================\n\n/**\n * Twilio uses the same four-value enum for several attributes that control\n * what caller input (DTMF, speech, both, neither) triggers a given behavior.\n */\nexport const InterruptModeSchema = z.enum(['none', 'dtmf', 'speech', 'any']);\nexport type InterruptMode = z.infer<typeof InterruptModeSchema>;\n\n/**\n * A single `<Language>` child for multi-language ConversationRelay setups.\n *\n * Maps to the `<Language>` element documented at\n * https://www.twilio.com/docs/voice/twiml/connect/conversationrelay#language-element\n *\n * Distinct from {@link LanguageAttributes} (the Twilio-SDK-shaped type used by\n * `connectConversationRelay`): this is the customization-facing model used in\n * {@link VoiceTwiMLOptionsConversationRelay}, mirroring the Python SDK's\n * `LanguageConfig`.\n */\nexport const LanguageConfigSchema = z.object({\n /**\n * Language code, e.g. 'es-MX'. Can be 'multi' for automatic language\n * detection (requires ElevenLabs TTS and Deepgram STT).\n */\n code: z.string(),\n /** TTS voice name for this language */\n voice: z.string().optional(),\n /** TTS provider, e.g. 'google' */\n ttsProvider: z.string().optional(),\n /** Transcription provider, e.g. 'deepgram' */\n transcriptionProvider: z.string().optional(),\n /** Speech model for STT. Choices vary by transcriptionProvider. */\n speechModel: z.string().optional(),\n});\n\nexport type LanguageConfig = z.infer<typeof LanguageConfigSchema>;\n\n/**\n * Raw object form of the provider-agnostic TwiML options — the single source\n * of truth for the three fields every provider shares. The exported base\n * schema below and each provider-specific subtype (ConversationRelay and\n * Media Streams) build on this same const, so the shared fields stay\n * defined once.\n */\nconst VoiceTwiMLOptionsBase = z.object({\n /**\n * Custom parameters to pass to the provider's TwiML element as `<Parameter>`\n * children.\n */\n customParameters: CustomParametersSchema.optional(),\n /**\n * URL for Twilio to request when the call ends (`<Connect action>`). Set to\n * a non-empty URL, or leave unset. An explicit `undefined` suppresses the\n * action entirely (see the TwiML builder's actionUrl resolution); an empty\n * string is rejected so it can't silently drop the action.\n */\n actionUrl: z.string().min(1, 'actionUrl must not be empty').optional(),\n /**\n * WebSocket URL for the provider's TwiML element (`<ConversationRelay url=...>`\n * today). Leave unset (the default) to use the URL the channel derives\n * from `TACConfig.voicePublicDomain` + `voiceWebsocketPath`. Set it only for\n * a per-call URL — e.g. an affinity-routed host that appends a token to the\n * upgrade URL — typically from an `onInboundCallTwiml` customizer. Layers\n * per-field like every other field. Must be non-empty when set.\n */\n websocketUrl: z.string().min(1, 'websocketUrl must not be empty').optional(),\n});\n\n/**\n * Provider-agnostic base for a voice provider's inbound-call TwiML\n * customization options.\n *\n * Each provider answers the inbound-call webhook with its own TwiML shape\n * ({@link VoiceTwiMLOptionsConversationRelaySchema} for `<ConversationRelay>`,\n * {@link VoiceTwiMLOptionsMediaStreamsSchema} for `<Connect><Stream>`), so\n * `VoiceProvider.handleIncomingCall`'s\n * `hostTwimlOptions` is typed against this base rather than a specific\n * provider's options. It carries only what every provider shares: the\n * `<Connect action>` URL, the transport URL, and `<Parameter>` children.\n *\n * Mirrors the Python SDK's `VoiceTwiMLOptions`.\n */\nexport const VoiceTwiMLOptionsSchema = VoiceTwiMLOptionsBase.strict();\n\n/**\n * Options for the TwiML inside `<ConversationRelay>` (plus the\n * `<Connect action>` URL).\n *\n * Fields map to the attributes documented at\n * https://www.twilio.com/docs/voice/twiml/connect/conversationrelay . All\n * fields are optional. `VoiceChannel.handleIncomingCall` merges these values\n * over TAC defaults per-field — only fields explicitly present on the object\n * override lower layers (see `VoiceChannel`'s overlay logic).\n *\n * This is the customization-facing counterpart to {@link ConversationRelayConfig}\n * (which is the Twilio-SDK-shaped emit model and carries the required `url`).\n * Mirrors the Python SDK's `VoiceTwiMLOptionsConversationRelay`.\n */\nexport const VoiceTwiMLOptionsConversationRelaySchema = VoiceTwiMLOptionsBase.extend({\n /** Initial greeting message for the caller */\n welcomeGreeting: z.string().optional(),\n /**\n * What caller input can interrupt the welcome greeting.\n * Defaults to 'any' on Twilio.\n */\n welcomeGreetingInterruptible: InterruptModeSchema.optional(),\n /**\n * Conversation Service SID. When set, ConversationRelay will manage\n * conversation creation and participants.\n */\n conversationConfiguration: z.string().optional(),\n\n // Language, TTS, STT\n /**\n * Language for both STT and TTS, e.g. 'en-US'. Equivalent to setting both\n * ttsLanguage and transcriptionLanguage.\n */\n language: z.string().optional(),\n /** TTS language code; overrides `language` for TTS. */\n ttsLanguage: z.string().optional(),\n /**\n * STT language code; overrides `language` for transcription. Can be\n * 'multi' for automatic language detection (Deepgram only).\n */\n transcriptionLanguage: z.string().optional(),\n /** TTS voice name (choices vary by ttsProvider) */\n voice: z.string().optional(),\n /** TTS provider: 'Google', 'Amazon', or 'ElevenLabs'. Defaults to 'ElevenLabs'. */\n ttsProvider: z.string().optional(),\n /**\n * STT provider: 'Google' or 'Deepgram'. Defaults to 'Deepgram' (or 'Google'\n * for accounts that used ConversationRelay before 2025-09-12).\n */\n transcriptionProvider: z.string().optional(),\n /** Speech model for STT. Choices vary by transcriptionProvider. */\n speechModel: z.string().optional(),\n /**\n * Text normalization for ElevenLabs TTS. Defaults to 'off'. 'auto' behaves\n * like 'off' for ConversationRelay calls.\n */\n elevenlabsTextNormalization: z.enum(['on', 'auto', 'off']).optional(),\n\n // Turn detection / interruption\n /**\n * Confidence required to finish a turn. Only applies with Deepgram + flux\n * speech model. Twilio enforces the accepted range — see ConversationRelay docs.\n */\n eotThreshold: z.number().optional(),\n /**\n * Send unfinalized prompts and eager end-of-turn events (last=false). Only\n * applies with Deepgram + flux speech model.\n */\n partialPrompts: z.boolean().optional(),\n /**\n * Use Deepgram Smart Format for transcription output. Defaults to true when\n * transcriptionProvider='Deepgram'.\n */\n deepgramSmartFormat: z.boolean().optional(),\n /**\n * Silence (ms) after speech before finalizing the prompt. Integer\n * milliseconds or the literal 'auto' (the platform default). Twilio enforces\n * the accepted range — see ConversationRelay docs.\n */\n speechTimeout: z.union([z.number().int(), z.literal('auto')]).optional(),\n /**\n * What caller input interrupts TTS playback. Boolean accepted for backward\n * compat: true='any', false='none'. Defaults to 'any'.\n */\n interruptible: z.union([InterruptModeSchema, z.boolean()]).optional(),\n /** How easily caller speech triggers an interrupt. Defaults to 'high'. */\n interruptSensitivity: z.enum(['high', 'medium', 'low']).optional(),\n /**\n * What caller input gets reported while the agent is speaking (independent\n * of whether playback is interrupted). Defaults to 'none' since May 2025.\n */\n reportInputDuringAgentSpeech: InterruptModeSchema.optional(),\n /**\n * Filter short conversational feedback ('yeah', 'uh-huh', …) so it doesn't\n * interrupt the agent. Defaults to false.\n */\n ignoreBackchannel: z.boolean().optional(),\n /**\n * Allow text tokens from the next talk cycle to interrupt the current one.\n * Defaults to false.\n */\n preemptible: z.boolean().optional(),\n /** Emit DTMF keypress events over the WebSocket. */\n dtmfDetection: z.boolean().optional(),\n\n // Recognition hints / events / debug / intelligence\n /**\n * Comma-separated words/phrases likely to appear in speech. Capitalize\n * proper nouns.\n */\n hints: z.string().optional(),\n /** Space-separated event subscriptions, e.g. 'speaker-events tokens-played'. */\n events: z.string().optional(),\n /**\n * Debug subscription, e.g. 'debugging'. Note: 'speaker-events' and\n * 'tokens-played' have moved to the `events` attribute — only use them here\n * for backward compatibility.\n */\n debug: z.string().optional(),\n /**\n * Conversation Intelligence (classic) Service SID or unique name for\n * persisting transcripts and running Language Operators.\n */\n intelligenceService: z.string().optional(),\n\n // Nested <Language> children\n /** Additional `<Language>` children for multi-language support */\n languages: z.array(LanguageConfigSchema).optional(),\n\n /**\n * Escape hatch for ConversationRelay attributes not yet typed on this model.\n * Keys are emitted as-is on `<ConversationRelay>`; Twilio's SDK converts\n * snake_case to camelCase, lowercases bools to 'true'/'false', and\n * stringifies numbers. Prefer a typed field when one exists — use `extra`\n * only for newly-added Twilio attributes not yet in this SDK.\n */\n extra: z.record(z.string(), z.union([z.string(), z.boolean(), z.number()])).optional(),\n})\n // Forbid unknown keys so a typo in a field name fails loudly rather than\n // being silently dropped from the emitted TwiML.\n .strict()\n // Fail fast when `extra` includes a key that has a typed field on this model.\n // Without this, the user's value would be silently dropped by the TwiML\n // serializer in favor of the typed default — a footgun.\n .superRefine((value, ctx) => {\n if (!value.extra) return;\n const typed = new Set(\n Object.keys(VoiceTwiMLOptionsConversationRelayShape).filter(k => k !== 'extra')\n );\n const shadowed = Object.keys(value.extra)\n .filter(k => typed.has(k))\n .sort();\n if (shadowed.length > 0) {\n ctx.addIssue({\n code: 'custom',\n path: ['extra'],\n message:\n `VoiceTwiMLOptionsConversationRelay.extra keys [${shadowed.join(', ')}] shadow typed fields. ` +\n 'Set the typed field directly instead of using `extra`.',\n });\n }\n });\n\n/**\n * @internal Field names of {@link VoiceTwiMLOptionsConversationRelaySchema},\n * used by the shadow-guard refinement above. Declared separately because\n * `.strict().superRefine(...)` erases the object shape on the schema instance.\n */\nconst VoiceTwiMLOptionsConversationRelayShape = {\n customParameters: true,\n welcomeGreeting: true,\n welcomeGreetingInterruptible: true,\n actionUrl: true,\n conversationConfiguration: true,\n websocketUrl: true,\n language: true,\n ttsLanguage: true,\n transcriptionLanguage: true,\n voice: true,\n ttsProvider: true,\n transcriptionProvider: true,\n speechModel: true,\n elevenlabsTextNormalization: true,\n eotThreshold: true,\n partialPrompts: true,\n deepgramSmartFormat: true,\n speechTimeout: true,\n interruptible: true,\n interruptSensitivity: true,\n reportInputDuringAgentSpeech: true,\n ignoreBackchannel: true,\n preemptible: true,\n dtmfDetection: true,\n hints: true,\n events: true,\n debug: true,\n intelligenceService: true,\n languages: true,\n extra: true,\n} as const;\n\nexport type VoiceTwiMLOptions = z.infer<typeof VoiceTwiMLOptionsSchema>;\n\nexport type VoiceTwiMLOptionsConversationRelay = z.infer<\n typeof VoiceTwiMLOptionsConversationRelaySchema\n>;\n\n/**\n * Options for the TwiML inside `<Connect><Stream>`.\n *\n * Fields map to the attributes documented at\n * https://www.twilio.com/docs/voice/twiml/stream (the `<Stream>` verb) and\n * https://www.twilio.com/docs/voice/twiml/connect (the `<Connect>` verb it is\n * nested in). `track` is deliberately absent: a bidirectional `<Connect>`\n * stream only ever carries `inbound_track`, so it is not settable.\n *\n * Inherits `customParameters`, `actionUrl` and `websocketUrl` from the shared\n * base. Mirrors the Python SDK's `VoiceTwiMLOptionsMediaStreams`.\n */\nexport const VoiceTwiMLOptionsMediaStreamsSchema = VoiceTwiMLOptionsBase.extend({\n /**\n * Friendly name for the stream (`<Stream name=...>`). Must be unique per\n * call; it arrives back in the WebSocket `start` event.\n */\n name: z.string().optional(),\n /**\n * Absolute URL Twilio posts to when the stream starts, stops, or errors\n * (StreamSid/StreamName/StreamEvent/StreamError/Timestamp params). Must be\n * non-empty when set, like the other URL fields, so an empty string can't\n * silently emit a broken attribute.\n */\n statusCallback: z.string().min(1, 'statusCallback must not be empty').optional(),\n /** HTTP method for `statusCallback`. Defaults to POST on Twilio. */\n statusCallbackMethod: z.enum(['GET', 'POST']).optional(),\n /**\n * HTTP method for `actionUrl`. Defaults to POST on Twilio. Lives here rather\n * than on the shared base because no other provider's TwiML exposes it.\n */\n actionMethod: z.enum(['GET', 'POST']).optional(),\n})\n // Forbid unknown keys so a typo in a field name fails loudly rather than\n // being silently dropped from the emitted TwiML. Unlike the ConversationRelay\n // subtype there is no `extra` escape hatch here, so `.strict()` stands alone\n // and `.shape` stays readable.\n .strict();\n\nexport type VoiceTwiMLOptionsMediaStreams = z.infer<typeof VoiceTwiMLOptionsMediaStreamsSchema>;\n\n/** @deprecated Use {@link VoiceTwiMLOptionsConversationRelay} instead. */\nexport type TwiMLOptions = VoiceTwiMLOptionsConversationRelay;\n\n/**\n * Unlike Python, this emits no runtime warning. It is a plain alias so that\n * `TwiMLOptionsSchema === VoiceTwiMLOptionsConversationRelaySchema`; wrapping it\n * in a warning proxy would break that identity, and callers commonly compare or\n * `.extend()` the schema.\n *\n * @deprecated Use {@link VoiceTwiMLOptionsConversationRelaySchema} instead.\n */\nexport const TwiMLOptionsSchema = VoiceTwiMLOptionsConversationRelaySchema;\n\n/**\n * Framework-neutral view of the Twilio TwiML webhook form.\n *\n * Populated by `TACServer` from the incoming Twilio webhook, then passed to a\n * customizer registered via `VoiceChannel.onInboundCallTwiml(...)` so the\n * application can produce per-call {@link VoiceTwiMLOptions} overrides without\n * depending on Fastify types. Mirrors the Python SDK's `TwiMLRequest`.\n */\nexport const TwiMLRequestSchema = z.object({\n from: z.string().optional(),\n to: z.string().optional(),\n callSid: z.string().optional(),\n callerCountry: z.string().optional(),\n callerState: z.string().optional(),\n callerCity: z.string().optional(),\n direction: z.string().optional(),\n /**\n * Any other fields from the Twilio webhook not captured above. Values are\n * always strings here (webhook form fields are url-encoded), unlike\n * VoiceTwiMLOptionsConversationRelay.extra which accepts string | boolean |\n * number for emitted TwiML attributes.\n */\n extra: z.record(z.string(), z.string()).default({}),\n});\n\nexport type TwiMLRequest = z.infer<typeof TwiMLRequestSchema>;\n\n/**\n * Map from Twilio webhook form field names to {@link TwiMLRequest} keys.\n * Fields not in this map are bucketed into `extra` by {@link twiMLRequestFromForm}.\n */\nconst TWIML_REQUEST_FORM_ALIASES: Record<string, keyof Omit<TwiMLRequest, 'extra'>> = {\n From: 'from',\n To: 'to',\n CallSid: 'callSid',\n CallerCountry: 'callerCountry',\n CallerState: 'callerState',\n CallerCity: 'callerCity',\n Direction: 'direction',\n};\n\n/**\n * Build a {@link TwiMLRequest} from a raw Twilio form dict, bucketing unknown\n * keys into `extra`. Mirrors the Python SDK's `TwiMLRequest.from_form`.\n */\nexport function twiMLRequestFromForm(form: Record<string, string>): TwiMLRequest {\n const known: Record<string, string> = {};\n const extra: Record<string, string> = {};\n for (const [key, value] of Object.entries(form)) {\n const alias = TWIML_REQUEST_FORM_ALIASES[key];\n if (alias) {\n known[alias] = value;\n } else {\n extra[key] = value;\n }\n }\n return TwiMLRequestSchema.parse({ ...known, extra });\n}\n\n/**\n * Voice channel specific events\n */\nexport interface VoiceChannelEvents {\n setup: SetupMessage;\n prompt: PromptMessage;\n interrupt: InterruptMessage;\n dtmf: DtmfMessage;\n error: Error;\n}\n\n/**\n * ConversationRelay callback payload from Twilio webhook\n *\n * Sent when a ConversationRelay session ends or transitions state.\n * Includes standard voice webhook parameters plus ConversationRelay-specific fields.\n *\n * @see https://www.twilio.com/docs/voice/twiml#request-parameters\n * @see https://www.twilio.com/docs/voice/conversationrelay/conversationrelay-noun#statuscallback\n */\nexport const ConversationRelayCallbackPayloadSchema = z.object({\n // Core Twilio identifiers (required)\n AccountSid: z.string(),\n CallSid: z.string(),\n\n /** Call status with strict type checking for all valid Twilio call states */\n CallStatus: z.enum([\n 'queued',\n 'initiated',\n 'ringing',\n 'in-progress',\n 'completed',\n 'busy',\n 'no-answer',\n 'failed',\n 'canceled',\n ]),\n\n // Call participants (required)\n From: z.string(),\n To: z.string(),\n\n /** Direction of the call */\n Direction: z.enum(['inbound', 'outbound-api', 'outbound-dial']),\n\n // Standard voice webhook parameters (optional)\n ApiVersion: z.string().optional(),\n ForwardedFrom: z.string().optional(),\n CallerName: z.string().optional(),\n ParentCallSid: z.string().optional(),\n ApplicationSid: z.string().optional(),\n\n // ConversationRelay session information (optional)\n SessionId: z.string().optional(),\n SessionStatus: z.string().optional(),\n SessionDuration: z.string().optional(),\n});\n\nexport type ConversationRelayCallbackPayload = z.infer<\n typeof ConversationRelayCallbackPayloadSchema\n>;\n\n/** HTTP response a provider's out-of-band lifecycle webhook handler produces. */\nexport interface TwilioProviderCallbackResponse {\n status: number;\n content: string;\n contentType: string;\n}\n\n// =========================================================================\n// Call Events (status callback, async AMD, recording status)\n// =========================================================================\n\n/**\n * Split a Twilio webhook form into aliased fields and everything else.\n *\n * Unknown keys — including fields that belong to a different call event — are\n * bucketed rather than dropped, so a handler can still reach them via `extra`.\n */\nfunction splitCallEventForm(\n form: Record<string, string>,\n aliases: Record<string, string>\n): { known: Record<string, string>; extra: Record<string, string> } {\n const known: Record<string, string> = {};\n const extra: Record<string, string> = {};\n for (const [key, value] of Object.entries(form)) {\n const alias = aliases[key];\n if (alias) {\n known[alias] = value;\n } else {\n extra[key] = value;\n }\n }\n return { known, extra };\n}\n\n/**\n * Fields shared by the three Twilio call-webhook events.\n *\n * `callSid` is the correlation key across every surface — it matches\n * `ConversationSession.callSid` and the SID from\n * `initiateOutboundConversation`. It's required: every real call webhook\n * carries one, and defaulting it would hand handlers an empty SID to act on\n * (`endCall('')` is a Twilio 404). Missing or blank fails validation, which the\n * channel turns into a 400.\n */\nconst CallEventBaseShape = {\n callSid: z.string().min(1, 'CallSid is required'),\n accountSid: z.string().optional(),\n /** Any other Twilio webhook fields not surfaced above. */\n extra: z.record(z.string(), z.string()).default({}),\n};\n\nconst CALL_EVENT_BASE_ALIASES = {\n CallSid: 'callSid',\n AccountSid: 'accountSid',\n} as const;\n\n/**\n * Call statuses that mean the call ended without reaching the callee — i.e.\n * worth a retry.\n */\nconst UNREACHED_CALL_STATUSES: readonly string[] = ['busy', 'no-answer', 'failed', 'canceled'];\n\n/**\n * A Twilio `statusCallback` webhook — call progress and disposition.\n *\n * By default Twilio sends only the terminal event, which covers every\n * disposition (`completed` / `busy` / `no-answer` / `failed` / `canceled`); set\n * `CallOptions.statusCallbackEvent` for the intermediate ones. Register a\n * handler via `VoiceChannel.onCallStatus`.\n *\n * `isUnreached` is computed at parse time so application code doesn't have to\n * match disposition strings itself.\n */\nexport const CallStatusEventSchema = z\n .object({\n ...CallEventBaseShape,\n callStatus: z.string().optional(),\n callDuration: z.string().optional(),\n sipResponseCode: z.string().optional(),\n })\n .transform(event => ({\n ...event,\n /** Call ended without reaching the callee — i.e. worth a retry. */\n isUnreached: UNREACHED_CALL_STATUSES.includes(event.callStatus ?? ''),\n }));\n\nexport type CallStatusEvent = z.infer<typeof CallStatusEventSchema>;\n\nconst CALL_STATUS_EVENT_ALIASES: Record<string, string> = {\n ...CALL_EVENT_BASE_ALIASES,\n CallStatus: 'callStatus',\n CallDuration: 'callDuration',\n SipResponseCode: 'sipResponseCode',\n};\n\n/** Build a {@link CallStatusEvent} from a raw Twilio webhook form. */\nexport function callStatusEventFromForm(form: Record<string, string>): CallStatusEvent {\n const { known, extra } = splitCallEventForm(form, CALL_STATUS_EVENT_ALIASES);\n return CallStatusEventSchema.parse({ ...known, extra });\n}\n\n/**\n * A Twilio `asyncAmdStatusCallback` webhook — answering machine detection.\n *\n * Fires at most once per call, and only when the call set both\n * `CallOptions.machineDetection` and `asyncAmd`.\n *\n * `answeredBy` is mode-dependent — `machine_start` under `'Enable'`,\n * `machine_end_beep` / `machine_end_silence` / `machine_end_other` under\n * `'DetectMessageEnd'`, plus `human` / `fax` / `unknown` in both. Use\n * `isMachine` rather than matching those yourself. Register a handler via\n * `VoiceChannel.onAmd`.\n */\nexport const AmdEventSchema = z\n .object({\n ...CallEventBaseShape,\n answeredBy: z.string().optional(),\n machineDetectionDuration: z.string().optional(),\n })\n .transform(event => ({\n ...event,\n /**\n * A machine answered — any `machine_*` value, either mode. `unknown`\n * (detection timed out) is false, so a call is never hung up on a guess.\n */\n isMachine: (event.answeredBy ?? '').startsWith('machine'),\n }));\n\nexport type AmdEvent = z.infer<typeof AmdEventSchema>;\n\nconst AMD_EVENT_ALIASES: Record<string, string> = {\n ...CALL_EVENT_BASE_ALIASES,\n AnsweredBy: 'answeredBy',\n MachineDetectionDuration: 'machineDetectionDuration',\n};\n\n/** Build an {@link AmdEvent} from a raw Twilio webhook form. */\nexport function amdEventFromForm(form: Record<string, string>): AmdEvent {\n const { known, extra } = splitCallEventForm(form, AMD_EVENT_ALIASES);\n return AmdEventSchema.parse({ ...known, extra });\n}\n\n/**\n * A Twilio `recordingStatusCallback` webhook — a recording became available.\n *\n * Fires when the recording is ready (`recordingUrl` accessible), only when\n * recording is enabled. Register a handler via `VoiceChannel.onRecording`.\n */\nexport const RecordingEventSchema = z.object({\n ...CallEventBaseShape,\n recordingSid: z.string().optional(),\n recordingUrl: z.string().optional(),\n recordingStatus: z.string().optional(),\n recordingDuration: z.string().optional(),\n});\n\nexport type RecordingEvent = z.infer<typeof RecordingEventSchema>;\n\nconst RECORDING_EVENT_ALIASES: Record<string, string> = {\n ...CALL_EVENT_BASE_ALIASES,\n RecordingSid: 'recordingSid',\n RecordingUrl: 'recordingUrl',\n RecordingStatus: 'recordingStatus',\n RecordingDuration: 'recordingDuration',\n};\n\n/** Build a {@link RecordingEvent} from a raw Twilio webhook form. */\nexport function recordingEventFromForm(form: Record<string, string>): RecordingEvent {\n const { known, extra } = splitCallEventForm(form, RECORDING_EVENT_ALIASES);\n return RecordingEventSchema.parse({ ...known, extra });\n}\n\n// =========================================================================\n// Calls API parameters (calls.create passthrough)\n// =========================================================================\n\n/**\n * Every parameter `client.calls.create()` accepts, as of the pinned Twilio SDK.\n *\n * Unlike Python's `inspect.signature`, TypeScript has no runtime view of a\n * function's accepted keys, so the set is listed here and pinned to the SDK by\n * {@link _CallsCreateDriftGuards} at typecheck time. It's needed at runtime\n * because the Node SDK builds its request body from an explicit whitelist —\n * an unrecognized key is **silently dropped**, not an error, so without this a\n * typo would look like it worked.\n */\nconst CALLS_CREATE_PARAMS = [\n 'applicationSid',\n 'asyncAmd',\n 'asyncAmdStatusCallback',\n 'asyncAmdStatusCallbackMethod',\n 'byoc',\n 'callerId',\n 'callReason',\n 'callToken',\n 'clientNotificationUrl',\n 'fallbackMethod',\n 'fallbackUrl',\n 'from',\n 'machineDetection',\n 'machineDetectionSilenceTimeout',\n 'machineDetectionSpeechEndThreshold',\n 'machineDetectionSpeechThreshold',\n 'machineDetectionTimeout',\n 'method',\n 'record',\n 'recordingChannels',\n 'recordingStatusCallback',\n 'recordingStatusCallbackEvent',\n 'recordingStatusCallbackMethod',\n 'recordingTrack',\n 'sendDigits',\n 'sipAuthPassword',\n 'sipAuthUsername',\n 'statusCallback',\n 'statusCallbackEvent',\n 'statusCallbackMethod',\n 'timeLimit',\n 'timeout',\n 'to',\n 'trim',\n 'twiml',\n 'url',\n] as const;\n\n/**\n * `calls.create` parameters TAC owns — it builds the call and its TwiML, so a\n * caller setting these would either be overwritten or break the call.\n */\nconst RESERVED_CALL_PARAMS = ['to', 'from', 'twiml', 'url', 'applicationSid'] as const;\n\ntype ReservedCallParam = (typeof RESERVED_CALL_PARAMS)[number];\n\n/**\n * The `calls.create` parameters TAC types explicitly — the ones outbound\n * ConversationRelay reaches for. Everything else the SDK accepts is still\n * forwarded, typed by the SDK itself via {@link CallOptions}.\n */\nexport interface TypedCallOptions {\n /**\n * Enables AMD. `'Enable'` reports as soon as it can tell human from machine\n * (to hang up on voicemail); `'DetectMessageEnd'` waits out the greeting (to\n * leave a message). Required, together with `asyncAmd`, for `onAmd` to fire.\n */\n machineDetection?: 'Enable' | 'DetectMessageEnd' | undefined;\n /**\n * Detect in the background. Required for `onAmd`: with it off, `AnsweredBy`\n * comes back on the TwiML request, which inline TwiML can't receive.\n *\n * Twilio's API types this as a string; a boolean is serialized for you.\n */\n asyncAmd?: boolean | string | undefined;\n asyncAmdStatusCallback?: string | undefined;\n asyncAmdStatusCallbackMethod?: string | undefined;\n machineDetectionTimeout?: number | undefined;\n machineDetectionSpeechThreshold?: number | undefined;\n machineDetectionSpeechEndThreshold?: number | undefined;\n machineDetectionSilenceTimeout?: number | undefined;\n\n /** Required for `onRecording`. */\n record?: boolean | undefined;\n recordingStatusCallback?: string | undefined;\n recordingStatusCallbackEvent?: string[] | undefined;\n recordingChannels?: string | undefined;\n recordingTrack?: string | undefined;\n\n statusCallback?: string | undefined;\n /**\n * Lifecycle events to report. Omitted, Twilio sends only `'completed'` —\n * which covers busy/canceled/failed/no-answer. Set it for ringing/answered.\n */\n statusCallbackEvent?: string[] | undefined;\n statusCallbackMethod?: string | undefined;\n /** Seconds to ring before giving up. Twilio defaults to 60. */\n timeout?: number | undefined;\n}\n\n/**\n * Parameters for Twilio's `client.calls.create()`.\n *\n * {@link TypedCallOptions} covers the ones outbound ConversationRelay reaches\n * for; any other parameter `calls.create()` accepts is forwarded too, typed by\n * the Twilio SDK. TAC-owned parameters (`to`, `from`, `twiml`, `url`,\n * `applicationSid`) are excluded — TAC builds the call and its TwiML.\n *\n * Unknown keys are rejected at validation, so a typo fails at\n * `initiateOutboundConversation` rather than being silently dropped by the SDK.\n *\n * @example\n * ```typescript\n * const callOptions: CallOptions = {\n * machineDetection: 'Enable',\n * asyncAmd: true,\n * record: true,\n * };\n * ```\n */\nexport type CallOptions = TypedCallOptions &\n Omit<CallListInstanceCreateOptions, ReservedCallParam | keyof TypedCallOptions>;\n\n/**\n * @internal Fails typecheck unless instantiated with `true`. A conditional type\n * that merely resolves to `never` is not an error on its own, so the assertion\n * has to be a constraint violation to be load-bearing.\n */\ntype _AssertTrue<T extends true> = T;\n\n/**\n * @internal Compile-time SDK drift guards — do not use directly.\n * If the Twilio SDK adds, removes, or renames a `calls.create` parameter these\n * checks fail during `npm run typecheck`, signaling that\n * {@link CALLS_CREATE_PARAMS} needs updating. Without the `complete` direction a\n * newly added SDK parameter would be rejected at runtime as unknown.\n */\nexport type _CallsCreateDriftGuards = {\n known: _AssertTrue<\n (typeof CALLS_CREATE_PARAMS)[number] extends keyof CallListInstanceCreateOptions ? true : false\n >;\n complete: _AssertTrue<\n keyof CallListInstanceCreateOptions extends (typeof CALLS_CREATE_PARAMS)[number] ? true : false\n >;\n typedAreRealParams: _AssertTrue<\n keyof TypedCallOptions extends keyof CallListInstanceCreateOptions ? true : false\n >;\n reservedAreRealParams: _AssertTrue<\n ReservedCallParam extends keyof CallListInstanceCreateOptions ? true : false\n >;\n};\n\nconst ACCEPTED_CALL_PARAMS: ReadonlySet<string> = new Set(CALLS_CREATE_PARAMS);\n\n/**\n * Whether an `asyncAmd` value actually turns background detection on.\n *\n * Accepts the boolean TAC serializes for callers and the string Twilio's API\n * types the parameter as, so `'false'` reads as off rather than as a non-empty\n * (therefore truthy) string.\n */\nfunction isAsyncAmdEnabled(value: unknown): boolean {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.trim().toLowerCase() === 'true';\n return false;\n}\n\n/**\n * Runtime validation for {@link CallOptions}.\n *\n * Loose rather than strict so untyped-but-real Calls API parameters pass\n * through; `superRefine` then rejects TAC-owned and unknown keys explicitly so\n * the message says which mistake was made.\n */\nconst CallOptionsObjectSchema = z\n .looseObject({\n machineDetection: z.enum(['Enable', 'DetectMessageEnd']).optional(),\n asyncAmd: z.union([z.boolean(), z.string()]).optional(),\n asyncAmdStatusCallback: z.string().optional(),\n asyncAmdStatusCallbackMethod: z.string().optional(),\n machineDetectionTimeout: z.number().int().optional(),\n machineDetectionSpeechThreshold: z.number().int().optional(),\n machineDetectionSpeechEndThreshold: z.number().int().optional(),\n machineDetectionSilenceTimeout: z.number().int().optional(),\n\n record: z.boolean().optional(),\n recordingStatusCallback: z.string().optional(),\n recordingStatusCallbackEvent: z.array(z.string()).optional(),\n recordingChannels: z.string().optional(),\n recordingTrack: z.string().optional(),\n\n statusCallback: z.string().optional(),\n statusCallbackEvent: z.array(z.string()).optional(),\n statusCallbackMethod: z.string().optional(),\n timeout: z.number().int().optional(),\n })\n .superRefine((value, ctx) => {\n const supplied = Object.keys(value);\n\n const conflict = supplied.filter(key =>\n (RESERVED_CALL_PARAMS as readonly string[]).includes(key)\n );\n if (conflict.length > 0) {\n ctx.addIssue({\n code: 'custom',\n message:\n `callOptions may not set TAC-owned call parameters: ${conflict.sort().join(', ')}. ` +\n 'TAC builds the call and its TwiML.',\n });\n }\n\n const unknown = supplied.filter(key => !ACCEPTED_CALL_PARAMS.has(key));\n if (unknown.length > 0) {\n ctx.addIssue({\n code: 'custom',\n message:\n \"callOptions has parameters Twilio's calls.create() does not accept: \" +\n `${unknown.sort().join(', ')}. Check for a typo, or upgrade the twilio package.`,\n });\n }\n\n // AMD needs both flags. machineDetection turns detection on; asyncAmd\n // delivers AnsweredBy to a callback. Without asyncAmd, Twilio returns it on\n // the TwiML request instead — unreachable, since TAC sends inline TwiML.\n //\n // asyncAmd is checked by value, not truthiness: Twilio's API types it as a\n // string, and `Boolean('false')` is true — so a plain truthiness test would\n // wave through `asyncAmd: 'false'` and silently deliver no AMD event.\n if (Boolean(value.machineDetection) !== isAsyncAmdEnabled(value.asyncAmd)) {\n ctx.addIssue({\n code: 'custom',\n message:\n 'AMD requires both machineDetection and asyncAmd; got ' +\n `machineDetection=${JSON.stringify(value.machineDetection)}, ` +\n `asyncAmd=${JSON.stringify(value.asyncAmd)}.`,\n });\n }\n });\n\n/**\n * Validates {@link CallOptions}. The parsed value is re-widened to `CallOptions`\n * because the loose object's inferred index signature would otherwise erase the\n * SDK-derived parameter types.\n */\nexport const CallOptionsSchema: z.ZodType<CallOptions, unknown> = CallOptionsObjectSchema.transform(\n value => value as CallOptions\n);\n\n/**\n * Serialize {@link CallOptions} into the argument object for\n * `client.calls.create()`, dropping unset keys.\n *\n * `asyncAmd` is coerced to a string because Twilio's SDK types it as one,\n * unlike `record`.\n */\nexport function callOptionsToCreateParams(options: CallOptions): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(options)) {\n if (value === undefined) continue;\n params[key] = key === 'asyncAmd' && typeof value === 'boolean' ? String(value) : value;\n }\n return params;\n}\n\n// =========================================================================\n// Outbound Voice Conversation Types\n// =========================================================================\n\n/**\n * Options for initiating an outbound voice conversation.\n *\n * The caller identity is always TAC's configured `config.phoneNumber`.\n * Multi-number deployments should run one TAC instance per line.\n *\n * TwiML for the outbound call is built by merging per-field, highest precedence\n * first:\n * 1. This call's `twimlOptions` (per-call overrides)\n * 2. `VoiceChannelConfig.defaultTwimlOptions` (channel-wide defaults)\n * 3. TAC defaults (welcome greeting, conversationConfiguration, actionUrl\n * resolved via Studio handoff if configured, else derived from\n * `TACConfig.voicePublicDomain` + `voiceActionPath`)\n *\n * Fields you don't set at a layer fall through to lower layers — so\n * `twimlOptions: { voice: 'es-MX-Neural2-A' }` on this call overrides only\n * `voice`; `language`, `interruptible`, etc. from the channel config still apply.\n */\nexport interface InitiateVoiceConversationOptions {\n to: string;\n /**\n * Public WebSocket URL for ConversationRelay (e.g. 'wss://your-domain.ngrok.app/ws').\n * Optional — defaults to the URL derived from `TACConfig.voicePublicDomain` +\n * `voiceWebsocketPath`. Pass it here only to override the URL for a specific call.\n */\n websocketUrl?: string | undefined;\n /**\n * Per-call overrides for the outbound TwiML. Merged over\n * `VoiceChannelConfig.defaultTwimlOptions` and TAC defaults.\n *\n * A union of the provider subtypes rather than the provider-agnostic base:\n * the base type carries only the three shared fields, so TypeScript's\n * excess-property check would reject a fresh object literal carrying any\n * provider-specific field. Each provider still parses this against its own\n * schema at the channel boundary, so passing the wrong subtype for the\n * configured provider fails at runtime.\n */\n twimlOptions?: VoiceTwiMLOptionsConversationRelay | VoiceTwiMLOptionsMediaStreams | undefined;\n /**\n * Parameters for Twilio's `calls.create()` — AMD, recording, status\n * callbacks, timeout (see {@link CallOptions}). Callback URLs auto-wire when\n * the matching handler is registered; an explicit URL wins.\n */\n callOptions?: CallOptions | undefined;\n}\n\n/**\n * Raw object form of the outbound voice options, hoisted so provider subtypes\n * can `.extend()` it. The exported schema below is annotated\n * `z.ZodType<InitiateVoiceConversationOptions>`, which erases the object shape\n * and with it `.extend()` — the same reason {@link VoiceTwiMLOptionsBase} exists.\n */\nconst InitiateVoiceConversationOptionsBase = z.object({\n to: z.string().min(1, 'Recipient phone number is required'),\n websocketUrl: z.url().optional(),\n twimlOptions: VoiceTwiMLOptionsConversationRelaySchema.optional(),\n callOptions: CallOptionsSchema.optional(),\n});\n\n/**\n * Validates outbound options for `ConversationRelayProvider`.\n *\n * Despite the union on {@link InitiateVoiceConversationOptions.twimlOptions},\n * this schema accepts only the ConversationRelay subtype — use\n * {@link InitiateVoiceConversationOptionsOpenAIRealtimeSchema} for\n * `<Connect><Stream>`.\n */\nexport const InitiateVoiceConversationOptionsSchema: z.ZodType<InitiateVoiceConversationOptions> =\n InitiateVoiceConversationOptionsBase\n // Reject removed flat fields (welcomeGreeting, actionUrl, customParameters,\n // conversationRelayConfig) so callers upgrading from older TAC versions get\n // a clear error instead of having their values silently dropped.\n .strict();\n\n/**\n * Outbound options for `OpenAIRealtimeProvider`, adding a per-call\n * `sessionConfig` on top of {@link InitiateVoiceConversationOptionsSchema}.\n * Also narrows `twimlOptions` to {@link VoiceTwiMLOptionsMediaStreamsSchema}.\n *\n * Mirrors the Python SDK's `InitiateVoiceConversationOptionsOpenAIRealtime`.\n */\nexport const InitiateVoiceConversationOptionsOpenAIRealtimeSchema =\n InitiateVoiceConversationOptionsBase.extend({\n // Overridden to the Media Streams subtype: the inherited ConversationRelay\n // schema is `.strict()` and would reject `name` / `statusCallback` outright,\n // so this provider's TwiML options could never survive parsing.\n twimlOptions: VoiceTwiMLOptionsMediaStreamsSchema.optional(),\n /**\n * Used verbatim in place of `OpenAIRealtimeProviderConfig.defaultSessionConfig`\n * for this call.\n */\n sessionConfig: z.record(z.string(), z.unknown()).nullable().optional(),\n }).strict();\n\nexport type InitiateVoiceConversationOptionsOpenAIRealtime = z.infer<\n typeof InitiateVoiceConversationOptionsOpenAIRealtimeSchema\n>;\n\n/**\n * Outbound options for `GPTLiveProvider`, adding a per-call `sessionConfig` on\n * top of {@link InitiateVoiceConversationOptionsSchema}. Also narrows\n * `twimlOptions` to {@link VoiceTwiMLOptionsMediaStreamsSchema}.\n *\n * Mirrors the Python SDK's `InitiateVoiceConversationOptionsGPTLive`.\n */\nexport const InitiateVoiceConversationOptionsGPTLiveSchema =\n InitiateVoiceConversationOptionsBase.extend({\n // Overridden to the Media Streams subtype: the inherited ConversationRelay\n // schema is `.strict()` and would reject `name` / `statusCallback` outright,\n // so this provider's TwiML options could never survive parsing.\n twimlOptions: VoiceTwiMLOptionsMediaStreamsSchema.optional(),\n /**\n * Used verbatim in place of `GPTLiveProviderConfig.defaultSessionConfig`\n * for this call.\n */\n sessionConfig: z.record(z.string(), z.unknown()).nullable().optional(),\n }).strict();\n\nexport type InitiateVoiceConversationOptionsGPTLive = z.infer<\n typeof InitiateVoiceConversationOptionsGPTLiveSchema\n>;\n","import { z } from 'zod';\n\n/**\n * The `start` field of Twilio's Media Stream `start` event.\n *\n * This is an inbound, read-only message Twilio pushes over the\n * `<Connect><Stream>` WebSocket, so unlike the outbound TwiML options it\n * carries no snake_case alias layer — the wire names are parsed directly.\n *\n * Mirrors the Python SDK's `StreamStartMessage`. Python exposes a\n * `conversation_id` property aliasing `call_sid`; here callers read `callSid`\n * directly.\n *\n * @see https://www.twilio.com/docs/voice/media-streams/websocket-messages\n */\nexport const StreamStartMessageSchema = z.object({\n /** SID of the Media Stream itself (`MZ...`), used to address media back to Twilio. */\n streamSid: z.string(),\n /** SID of the call the stream is attached to — TAC's conversation identifier. */\n callSid: z.string(),\n /**\n * Negotiated audio format (encoding, sample rate, channels). Left untyped\n * because Twilio may add fields here, and the provider only reads it for\n * diagnostics.\n */\n mediaFormat: z.record(z.string(), z.unknown()).nullable().optional(),\n /**\n * Values of the `<Parameter>` children emitted on `<Stream>`. Defaults to an\n * empty object so callers never have to null-check it.\n */\n customParameters: z.record(z.string(), z.string()).default({}),\n});\n\nexport type StreamStartMessage = z.infer<typeof StreamStartMessageSchema>;\n","import { z } from 'zod';\n\n/**\n * JSON Schema definition for tool parameters\n */\nexport const JSONSchemaSchema = z.object({\n type: z.enum(['object', 'string', 'number', 'boolean', 'array']),\n properties: z.record(z.string(), z.any()).optional(),\n required: z.array(z.string()).optional(),\n items: z.any().optional(),\n enum: z.array(z.any()).optional(),\n description: z.string().optional(),\n});\n\nexport type JSONSchema = z.infer<typeof JSONSchemaSchema>;\n\n/**\n * Tool function signature\n */\nexport type ToolFunction<TParams = unknown, TResult = unknown> = (\n params: TParams\n) => Promise<TResult> | TResult;\n\n/**\n * Core tool definition\n */\nexport interface TACTool<TParams = unknown, TResult = unknown> {\n name: string;\n description: string;\n parameters: JSONSchema;\n implementation: ToolFunction<TParams, TResult>;\n}\n\n/**\n * OpenAI tool format\n */\nexport const OpenAIToolSchema = z.object({\n type: z.literal('function'),\n function: z.object({\n name: z.string(),\n description: z.string(),\n parameters: JSONSchemaSchema,\n }),\n});\n\nexport type OpenAITool = z.infer<typeof OpenAIToolSchema>;\n\n/**\n * Anthropic tool format\n */\nexport const AnthropicToolSchema = z.object({\n name: z.string(),\n description: z.string(),\n input_schema: JSONSchemaSchema,\n});\n\nexport type AnthropicTool = z.infer<typeof AnthropicToolSchema>;\n\n/**\n * OpenAI Realtime tool format.\n *\n * Realtime's `session.tools` expects the fields flat on the tool object,\n * unlike Chat Completions ({@link OpenAIToolSchema}), which nests them under a\n * `function` key.\n */\nexport const OpenAIRealtimeToolSchema = z.object({\n type: z.literal('function'),\n name: z.string(),\n description: z.string(),\n parameters: JSONSchemaSchema,\n});\n\nexport type OpenAIRealtimeTool = z.infer<typeof OpenAIRealtimeToolSchema>;\n\n/**\n * Tool execution context\n */\nexport interface ToolContext {\n conversationId?: string;\n profileId?: string;\n channel?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Tool execution result\n */\nexport const ToolExecutionResultSchema = z.object({\n success: z.boolean(),\n data: z.any().optional(),\n error: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type ToolExecutionResult = z.infer<typeof ToolExecutionResultSchema>;\n\n/**\n * Built-in tool types\n */\nexport const BuiltInTools = {\n RETRIEVE_MEMORY: 'retrieve_profile_memory',\n SEND_MESSAGE: 'send_message',\n HANDOFF: 'handoff',\n SEARCH_KNOWLEDGE: 'search_knowledge',\n} as const;\n\nexport type BuiltInToolName = (typeof BuiltInTools)[keyof typeof BuiltInTools];\n","import { z } from 'zod';\n\n/**\n * Conversation Intelligence Types\n *\n * These types represent the webhook payloads and configuration for\n * processing Conversation Intelligence operator results.\n */\n\n/**\n * Participant in operator execution (e.g., CUSTOMER, AGENT)\n */\nexport const CintelParticipantSchema = z.object({\n type: z.string(),\n profileId: z.string().optional(),\n mediaParticipantId: z.string().optional(),\n});\n\nexport type CintelParticipant = z.infer<typeof CintelParticipantSchema>;\n\n/**\n * Execution details for an operator result\n */\nexport const ExecutionDetailsSchema = z.object({\n participants: z.array(CintelParticipantSchema).optional(),\n});\n\nexport type ExecutionDetails = z.infer<typeof ExecutionDetailsSchema>;\n\n/**\n * Operator metadata\n */\nexport const OperatorSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n});\n\nexport type Operator = z.infer<typeof OperatorSchema>;\n\n/**\n * Individual operator result from Conversation Intelligence\n */\nexport const OperatorResultSchema = z.object({\n id: z.string(),\n operator: OperatorSchema,\n outputFormat: z.string(),\n result: z.unknown(),\n dateCreated: z.string(),\n referenceIds: z.array(z.string()).optional().default([]),\n executionDetails: ExecutionDetailsSchema.optional(),\n});\n\nexport type OperatorResult = z.infer<typeof OperatorResultSchema>;\n\n/**\n * Intelligence configuration metadata\n */\nexport const IntelligenceConfigurationSchema = z.object({\n id: z.string(),\n friendlyName: z.string().optional(),\n});\n\nexport type IntelligenceConfiguration = z.infer<typeof IntelligenceConfigurationSchema>;\n\n/**\n * Full webhook payload for operator result events\n */\nexport const OperatorResultEventSchema = z.object({\n accountId: z.string(),\n conversationId: z.string(),\n memoryStoreId: z.string().optional(),\n intelligenceConfiguration: IntelligenceConfigurationSchema,\n operatorResults: z.array(OperatorResultSchema),\n});\n\nexport type OperatorResultEvent = z.infer<typeof OperatorResultEventSchema>;\n\n/**\n * Result of processing an operator result event\n */\nexport const OperatorProcessingResultSchema = z.object({\n success: z.boolean(),\n eventType: z.string().optional(),\n skipped: z.boolean().default(false),\n skipReason: z.string().optional(),\n error: z.string().optional(),\n createdCount: z.number().default(0),\n});\n\nexport type OperatorProcessingResult = z.infer<typeof OperatorProcessingResultSchema>;\n\n/**\n * Conversation Intelligence configuration for TAC\n */\nexport const ConversationIntelligenceConfigSchema = z.object({\n configurationId: z.string(),\n summaryOperatorSid: z.string().optional(),\n});\n\nexport type ConversationIntelligenceConfig = z.infer<typeof ConversationIntelligenceConfigSchema>;\n\n/**\n * Summary item for batch creation\n */\nexport const ConversationSummaryItemSchema = z.object({\n content: z.string(),\n conversationId: z.string(),\n occurredAt: z.string(),\n source: z.string().optional(),\n});\n\nexport type ConversationSummaryItem = z.infer<typeof ConversationSummaryItemSchema>;\n","import { z } from 'zod';\n\n/**\n * Knowledge base status enum\n */\nexport const KnowledgeBaseStatusSchema = z.enum([\n 'QUEUED',\n 'PROVISIONING',\n 'ACTIVE',\n 'FAILED',\n 'DELETING',\n]);\n\nexport type KnowledgeBaseStatus = z.infer<typeof KnowledgeBaseStatusSchema>;\n\n/**\n * Knowledge base metadata (from GET endpoint)\n */\nexport const KnowledgeBaseSchema = z.object({\n id: z.string(),\n displayName: z.string(),\n description: z.string(),\n status: KnowledgeBaseStatusSchema,\n createdAt: z.string(),\n updatedAt: z.string(),\n version: z.number(),\n});\n\nexport type KnowledgeBase = z.infer<typeof KnowledgeBaseSchema>;\n\n/**\n * Search result chunk (from POST search endpoint)\n */\nexport const KnowledgeChunkResultSchema = z.object({\n content: z.string(),\n knowledgeId: z.string(),\n createdAt: z.string(),\n score: z.number().optional(),\n});\n\nexport type KnowledgeChunkResult = z.infer<typeof KnowledgeChunkResultSchema>;\n\n/**\n * Search response wrapper\n */\nexport const KnowledgeSearchResponseSchema = z.object({\n chunks: z.array(KnowledgeChunkResultSchema),\n});\n\nexport type KnowledgeSearchResponse = z.infer<typeof KnowledgeSearchResponseSchema>;\n","import { TACConfigData, TACConfigSchema, EnvironmentVariables } from '../types/index';\nimport type { CallEventKind } from '../types/index';\nimport { z } from 'zod';\n\n/**\n * TAC Configuration class with Python-like static factory methods\n *\n * Example usage:\n * ```typescript\n * // Load from environment variables\n * const config = TACConfig.fromEnv();\n *\n * // Or create manually\n * const config = new TACConfig({\n * accountSid: 'ACxxxx',\n * // ...\n * });\n * ```\n */\nexport class TACConfig {\n public readonly accountSid: string;\n public readonly authToken: string;\n public readonly apiKey: string;\n public readonly apiSecret: string;\n public readonly phoneNumber: string;\n public readonly rcsSenderId?: string;\n public readonly whatsappNumber?: string;\n public readonly memoryConfig: TACConfigData['memoryConfig'];\n public readonly conversationConfigurationId?: string;\n public readonly voicePublicDomain?: string;\n /** Path the voice WebSocket is served at (default '/ws'). */\n public readonly voiceWebsocketPath: string;\n /** Path the ConversationRelay action callback is served at (default '/conversation-relay-callback'). */\n public readonly voiceActionPath: string;\n /** Base path the call-event callbacks are served under (default '/twilio/call-events'). */\n public readonly voiceCallEventPath: string;\n public readonly cintelConfigurationId?: string;\n public readonly cintelSummaryOperatorSid?: string;\n /** Optional Twilio region subdomain for API routing (e.g. transforms base URLs to `https://{product}.{region}.twilio.com`) */\n public readonly region?: string;\n /**\n * Twilio Studio Flow SID for handoff. TAC derives both the digital-handoff\n * Studio Executions URL (`studio.twilio.com/v2/Flows/{SID}/Executions`) and\n * the voice `<Connect action>` webhook URL\n * (`webhooks.twilio.com/v1/Accounts/{AccountSid}/Flows/{SID}?Trigger=incomingCall`)\n * from this SID.\n */\n public readonly studioHandoffFlowSid?: string;\n constructor(data: TACConfigData | z.input<typeof TACConfigSchema>) {\n // Validate the configuration data\n const validatedConfig = TACConfigSchema.parse(data);\n\n // Assign all properties\n this.accountSid = validatedConfig.accountSid;\n this.authToken = validatedConfig.authToken;\n this.apiKey = validatedConfig.apiKey;\n this.apiSecret = validatedConfig.apiSecret;\n this.phoneNumber = validatedConfig.phoneNumber;\n if (validatedConfig.rcsSenderId) {\n this.rcsSenderId = validatedConfig.rcsSenderId;\n }\n if (validatedConfig.whatsappNumber) {\n this.whatsappNumber = validatedConfig.whatsappNumber;\n }\n // Assign the validated memory config directly; schema parsing already validates shape and applies defaults\n this.memoryConfig = validatedConfig.memoryConfig;\n if (validatedConfig.conversationConfigurationId) {\n this.conversationConfigurationId = validatedConfig.conversationConfigurationId;\n }\n if (validatedConfig.voicePublicDomain) {\n this.voicePublicDomain = validatedConfig.voicePublicDomain;\n }\n // voiceWebsocketPath / voiceActionPath / voiceCallEventPath always have schema defaults\n this.voiceWebsocketPath = validatedConfig.voiceWebsocketPath;\n this.voiceActionPath = validatedConfig.voiceActionPath;\n this.voiceCallEventPath = validatedConfig.voiceCallEventPath;\n if (validatedConfig.cintelConfigurationId) {\n this.cintelConfigurationId = validatedConfig.cintelConfigurationId;\n }\n if (validatedConfig.cintelSummaryOperatorSid) {\n this.cintelSummaryOperatorSid = validatedConfig.cintelSummaryOperatorSid;\n }\n if (validatedConfig.region) {\n this.region = validatedConfig.region;\n }\n if (validatedConfig.studioHandoffFlowSid) {\n this.studioHandoffFlowSid = validatedConfig.studioHandoffFlowSid;\n }\n }\n\n /**\n * Create TACConfig from environment variables.\n *\n * Required environment variables:\n * - TWILIO_ACCOUNT_SID: Twilio Account SID\n * - TWILIO_AUTH_TOKEN: Twilio Auth Token for API authentication\n * - TWILIO_API_KEY: Twilio API Key SID (starts with SK)\n * - TWILIO_API_SECRET: Twilio API Secret for API Key authentication\n * - TWILIO_PHONE_NUMBER: Phone number for voice and SMS channels\n *\n * Optional environment variables:\n * - TWILIO_WHATSAPP_NUMBER: WhatsApp number for WhatsApp channel (e.g., 'whatsapp:+1234567890')\n * - TWILIO_CONVERSATION_CONFIGURATION_ID: Conversation Orchestrator configuration ID (enables orchestrated mode)\n * - TWILIO_VOICE_PUBLIC_DOMAIN: Public domain for voice routes (required for voice; a port and/or base path are allowed, e.g., 'abc123.ngrok.app', 'example.ngrok.app:8080', or 'example.com/server1')\n * - TWILIO_VOICE_WEBSOCKET_PATH: Path for the voice WebSocket (default: /ws)\n * - TWILIO_VOICE_ACTION_PATH: Path for the ConversationRelay action callback (default: /conversation-relay-callback)\n * - TWILIO_VOICE_CALL_EVENT_PATH: Base path for the call-event callbacks — status, async AMD, recording (default: /twilio/call-events)\n * - TWILIO_REGION: Twilio region subdomain for API routing (e.g. transforms base URLs to `https://{product}.{region}.twilio.com`)\n * - TWILIO_STUDIO_HANDOFF_FLOW_SID: Studio Flow SID used by createStudioHandoffTool for human handoff\n * - TWILIO_RCS_SENDER_ID: RCS Sender ID for the RCS channel\n *\n * Memory Configuration (defaults defined in TwilioMemoryConfigSchema):\n * - TWILIO_MEMORY_PROFILE_TRAIT_GROUPS: Trait groups to include (comma-separated, e.g., \"Contact,Preferences\")\n * - TWILIO_MEMORY_OBSERVATIONS_LIMIT: Max observations in memory retrieval\n * - TWILIO_MEMORY_SUMMARIES_LIMIT: Max summaries in memory retrieval\n * - TWILIO_MEMORY_COMMUNICATIONS_LIMIT: Max communications in memory retrieval\n * - TWILIO_MEMORY_RELEVANCE_THRESHOLD: Min relevance score (0.0-1.0)\n * - TWILIO_MEMORY_PHONE_TRAIT_GROUP: Trait group that holds the phone identifier on new profiles (default \"Contact\")\n * - TWILIO_MEMORY_PHONE_TRAIT_FIELD: Trait field within phoneTraitGroup (default \"phone\")\n *\n * @throws Error if required environment variables are not set or invalid\n *\n * @example\n * ```typescript\n * // Ensure env vars are set before calling (e.g. via dotenv, Docker, CI, etc.)\n * const config = TACConfig.fromEnv();\n *\n * // Use in TAC initialization\n * const tac = new TAC({ config });\n * ```\n */\n public static fromEnv(): TACConfig {\n // Check for required environment variables\n const requiredVars = [\n { key: EnvironmentVariables.TWILIO_ACCOUNT_SID, name: 'TWILIO_ACCOUNT_SID' },\n { key: EnvironmentVariables.TWILIO_AUTH_TOKEN, name: 'TWILIO_AUTH_TOKEN' },\n { key: EnvironmentVariables.TWILIO_API_KEY, name: 'TWILIO_API_KEY' },\n { key: EnvironmentVariables.TWILIO_API_SECRET, name: 'TWILIO_API_SECRET' },\n { key: EnvironmentVariables.TWILIO_PHONE_NUMBER, name: 'TWILIO_PHONE_NUMBER' },\n ];\n\n // Throw error for missing required variables (like Python's KeyError)\n for (const { key, name } of requiredVars) {\n if (!process.env[key]) {\n throw new Error(`Missing required environment variable: ${name}`);\n }\n }\n\n // Parse memory configuration from environment variables\n const traitGroupsStr = process.env[EnvironmentVariables.TWILIO_MEMORY_PROFILE_TRAIT_GROUPS];\n // Parse trait groups, filtering out empty strings from malformed CSV (e.g., \"A,,B,\")\n // Treat empty/whitespace-only strings and delimiter-only inputs as undefined for consistency\n const trimmedTraitGroups = traitGroupsStr?.trim();\n const parsedTraitGroups =\n trimmedTraitGroups && trimmedTraitGroups.length > 0\n ? trimmedTraitGroups\n .split(',')\n .map(g => g.trim())\n .filter(g => g.length > 0)\n : undefined;\n const traitGroups =\n parsedTraitGroups && parsedTraitGroups.length > 0 ? parsedTraitGroups : undefined;\n\n // Helper to parse integer from env var with validation and bounds checking.\n // Returns undefined when the env var is not set, letting the Zod schema apply defaults.\n const parseIntEnv = (\n envVarName: string,\n value: string | undefined,\n min: number,\n max: number\n ): number | undefined => {\n if (!value) return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n\n const parsed = Number(trimmed);\n if (!Number.isFinite(parsed)) {\n throw new Error(`Invalid ${envVarName}: expected an integer, got \"${value}\"`);\n }\n if (!Number.isInteger(parsed)) {\n throw new Error(`Invalid ${envVarName}: expected an integer, got \"${value}\"`);\n }\n if (parsed < min || parsed > max) {\n throw new Error(`Invalid ${envVarName}: must be between ${min} and ${max}, got ${parsed}`);\n }\n return parsed;\n };\n\n // Helper to parse float from env var with validation and bounds checking.\n // Returns undefined when the env var is not set, letting the Zod schema apply defaults.\n const parseFloatEnv = (\n envVarName: string,\n value: string | undefined,\n min: number,\n max: number\n ): number | undefined => {\n if (!value) return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n\n const parsed = Number(trimmed);\n if (!Number.isFinite(parsed)) {\n throw new Error(`Invalid ${envVarName}: expected a number, got \"${value}\"`);\n }\n if (parsed < min || parsed > max) {\n throw new Error(`Invalid ${envVarName}: must be between ${min} and ${max}, got ${parsed}`);\n }\n return parsed;\n };\n\n const rawConfig = {\n accountSid: process.env[EnvironmentVariables.TWILIO_ACCOUNT_SID]!,\n authToken: process.env[EnvironmentVariables.TWILIO_AUTH_TOKEN]!,\n apiKey: process.env[EnvironmentVariables.TWILIO_API_KEY]!,\n apiSecret: process.env[EnvironmentVariables.TWILIO_API_SECRET]!,\n phoneNumber: process.env[EnvironmentVariables.TWILIO_PHONE_NUMBER]!,\n rcsSenderId: process.env[EnvironmentVariables.TWILIO_RCS_SENDER_ID],\n whatsappNumber: process.env[EnvironmentVariables.TWILIO_WHATSAPP_NUMBER] || undefined,\n memoryConfig: {\n traitGroups,\n observationsLimit: parseIntEnv(\n 'TWILIO_MEMORY_OBSERVATIONS_LIMIT',\n process.env[EnvironmentVariables.TWILIO_MEMORY_OBSERVATIONS_LIMIT],\n 0,\n 100\n ),\n summariesLimit: parseIntEnv(\n 'TWILIO_MEMORY_SUMMARIES_LIMIT',\n process.env[EnvironmentVariables.TWILIO_MEMORY_SUMMARIES_LIMIT],\n 0,\n 100\n ),\n communicationsLimit: parseIntEnv(\n 'TWILIO_MEMORY_COMMUNICATIONS_LIMIT',\n process.env[EnvironmentVariables.TWILIO_MEMORY_COMMUNICATIONS_LIMIT],\n 0,\n 100\n ),\n relevanceThreshold: parseFloatEnv(\n 'TWILIO_MEMORY_RELEVANCE_THRESHOLD',\n process.env[EnvironmentVariables.TWILIO_MEMORY_RELEVANCE_THRESHOLD],\n 0.0,\n 1.0\n ),\n phoneTraitGroup:\n process.env[EnvironmentVariables.TWILIO_MEMORY_PHONE_TRAIT_GROUP] || undefined,\n phoneTraitField:\n process.env[EnvironmentVariables.TWILIO_MEMORY_PHONE_TRAIT_FIELD] || undefined,\n },\n conversationConfigurationId:\n process.env[EnvironmentVariables.TWILIO_CONVERSATION_CONFIGURATION_ID] || undefined,\n voicePublicDomain: process.env[EnvironmentVariables.TWILIO_VOICE_PUBLIC_DOMAIN],\n voiceWebsocketPath:\n process.env[EnvironmentVariables.TWILIO_VOICE_WEBSOCKET_PATH] || undefined,\n voiceActionPath: process.env[EnvironmentVariables.TWILIO_VOICE_ACTION_PATH] || undefined,\n voiceCallEventPath:\n process.env[EnvironmentVariables.TWILIO_VOICE_CALL_EVENT_PATH] || undefined,\n cintelConfigurationId: process.env[EnvironmentVariables.TWILIO_TAC_CI_CONFIGURATION_ID],\n cintelSummaryOperatorSid:\n process.env[EnvironmentVariables.TWILIO_TAC_CI_SUMMARY_OPERATOR_SID],\n region: process.env[EnvironmentVariables.TWILIO_REGION],\n studioHandoffFlowSid: process.env[EnvironmentVariables.TWILIO_STUDIO_HANDOFF_FLOW_SID],\n };\n\n return new TACConfig(rawConfig);\n }\n\n /**\n * Path a call-event callback is served at.\n *\n * Single source of truth: the voice channel builds callback URLs from this\n * and TACServer registers routes at it, so the two can't drift.\n */\n public callEventPath(kind: CallEventKind): string {\n return `${this.voiceCallEventPath.replace(/\\/+$/, '')}/${kind}`;\n }\n\n /**\n * Public URL for a call-event callback, or `undefined` without a public domain.\n */\n public callEventUrl(kind: CallEventKind): string | undefined {\n if (!this.voicePublicDomain) {\n return undefined;\n }\n return `https://${this.voicePublicDomain}${this.callEventPath(kind)}`;\n }\n\n /**\n * Whether Conversation Orchestrator is configured.\n * Returns false in voice-only mode (no conversationConfigurationId).\n *\n * @internal\n */\n public isOrchestratorEnabled(): boolean {\n return this.conversationConfigurationId !== undefined;\n }\n\n /**\n * Get basic auth credentials for Twilio APIs\n */\n public getBasicAuthCredentials(): { username: string; password: string } {\n return {\n username: this.accountSid,\n password: this.authToken,\n };\n }\n}\n","function scrubPhoneMatch(match: string): string {\n const digits = match.replace(/[\\s\\-()]/g, '');\n if (digits.length < 8) return '***';\n return `${digits.slice(0, 2)}***${digits.slice(-4)}`;\n}\n\nfunction scrubEmailMatch(match: string): string {\n const atIndex = match.indexOf('@');\n if (atIndex <= 0) return '***';\n return `${match[0]}***${match.slice(atIndex)}`;\n}\n\nexport function scrubPii(value: string): string {\n // Fresh RegExp each call — avoids lastIndex state bugs from the g flag\n const phoneRe = /\\+\\d[\\d\\s()-]{6,}\\d/g;\n const emailRe = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;\n return value.replace(phoneRe, scrubPhoneMatch).replace(emailRe, scrubEmailMatch);\n}\n\nexport function scrubObject(obj: unknown, seen?: WeakSet<object>): unknown {\n if (typeof obj === 'string') return scrubPii(obj);\n if (obj === null || typeof obj !== 'object') return obj;\n\n const visited = seen ?? new WeakSet<object>();\n if (visited.has(obj)) return '[Circular]';\n visited.add(obj);\n\n if (obj instanceof Error) {\n const record = obj as unknown as Record<string, unknown>;\n const scrubbed = Object.create(Object.getPrototypeOf(obj) as object) as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n scrubbed[key] = scrubObject(record[key], visited);\n }\n const result = scrubbed as unknown as Error;\n if (!Object.prototype.hasOwnProperty.call(scrubbed, 'message')) {\n result.message = scrubPii(obj.message);\n }\n if (!Object.prototype.hasOwnProperty.call(scrubbed, 'name')) {\n result.name = obj.name;\n }\n if (obj.stack && !Object.prototype.hasOwnProperty.call(scrubbed, 'stack')) {\n result.stack = scrubPii(obj.stack);\n }\n return result;\n }\n\n if (Array.isArray(obj)) return obj.map(item => scrubObject(item, visited));\n\n // Only deep-scrub plain objects; leave class instances (Date, URL, Map, etc.) unchanged\n if (Object.getPrototypeOf(obj) !== Object.prototype) return obj;\n\n const record = obj as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(record)) {\n out[key] = scrubObject(record[key], visited);\n }\n return out;\n}\n\nexport function maskPhone(phone: string): string {\n if (!phone || !phone.startsWith('+') || phone.length < 8) {\n return '***';\n }\n return `${phone.slice(0, 2)}***${phone.slice(-4)}`;\n}\n\nexport function maskEmail(email: string): string {\n const atIndex = email.indexOf('@');\n if (atIndex <= 0) {\n return '***';\n }\n return `${email[0]}***${email.slice(atIndex)}`;\n}\n\nexport function maskAddress(address: string): string {\n if (!address) return '***';\n if (address.includes('@')) return maskEmail(address);\n if (address.startsWith('+')) return maskPhone(address);\n if (address.length <= 1) return '***';\n return `${address[0]}***`;\n}\n\n/**\n * Mask `<Parameter value=\"...\">` contents in TwiML, keeping the names.\n *\n * `<Parameter>` children carry whatever the developer put in\n * `customParameters` — profile IDs, caller names. Names stay because knowing\n * which parameters were sent is the point of logging the TwiML.\n *\n * Handles either quote style. TAC's own TwiML comes from the Twilio SDK, which\n * always double-quotes, but this takes a plain string and shouldn't depend on\n * that to stay safe.\n */\nexport function redactTwimlParameters(twiml: string | undefined | null): string {\n if (!twiml) return '';\n // Fresh RegExp each call — avoids lastIndex state bugs from the g flag.\n const parameterValueRe = /(<Parameter\\b[^>]*?\\bvalue=)([\"'])(.*?)\\2/gi;\n return twiml.replace(parameterValueRe, (_match, prefix: string, quote: string) => {\n return `${prefix}${quote}***${quote}`;\n });\n}\n","import pino from 'pino';\nimport { scrubObject } from '../util/log-redaction';\n\n/**\n * Logger type that can be either Pino logger or Fastify's logger\n */\nexport type Logger = pino.Logger;\n\nfunction piiLogMethod(this: pino.Logger, args: unknown[], method: pino.LogFn): void {\n const scrubbed = args.map(arg =>\n typeof arg === 'string'\n ? scrubObject(arg)\n : typeof arg === 'object' && arg !== null\n ? scrubObject(arg)\n : arg\n );\n return method.apply(this, scrubbed as Parameters<pino.LogFn>);\n}\n\nexport function createLogger(options?: { level?: string; name?: string }): Logger {\n const level = options?.level || process.env.TWILIO_LOG_LEVEL || 'info';\n\n return pino({\n level,\n ...(options?.name && { name: options.name }),\n hooks: { logMethod: piiLogMethod },\n });\n}\n","{\n \"name\": \"twilio-agent-connect\",\n \"version\": \"2.4.0\",\n \"description\": \"Twilio Agent Connect - A TypeScript framework for building intelligent agents\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"clean\": \"rimraf dist packages/*/dist\",\n \"test\": \"vitest --run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest --coverage\",\n \"lint\": \"eslint 'packages/*/src/**/*.ts' 'src/**/*.ts'\",\n \"lint:fix\": \"eslint 'packages/*/src/**/*.ts' 'src/**/*.ts' --fix\",\n \"format\": \"prettier --write 'packages/*/src/**/*.ts' 'src/**/*.ts' 'getting_started/**/*.ts'\",\n \"format:check\": \"prettier --check 'packages/*/src/**/*.ts' 'src/**/*.ts' 'getting_started/**/*.ts'\",\n \"typecheck\": \"tsc --noEmit\",\n \"docs\": \"typedoc\",\n \"docs:watch\": \"typedoc --watch\",\n \"example:getting-started\": \"cd getting_started/examples/openai && npm install && npm run dev\",\n \"example:chat\": \"cd getting_started/examples/chat && npm install && npm run dev\"\n },\n \"keywords\": [\n \"twilio\",\n \"ai\",\n \"agents\",\n \"framework\",\n \"typescript\"\n ],\n \"author\": \"Twilio\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/twilio/twilio-agent-connect-typescript.git\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.0.0\",\n \"@shipgirl/typedoc-plugin-versions\": \"^0.3.2\",\n \"@types/node\": \"^22.0.0\",\n \"@types/ws\": \"^8.18.1\",\n \"@vitest/coverage-v8\": \"^4.1.2\",\n \"axios-mock-adapter\": \"^2.1.0\",\n \"eslint\": \"^9.0.0\",\n \"globals\": \"^15.0.0\",\n \"prettier\": \"^3.0.0\",\n \"rimraf\": \"^5.0.0\",\n \"tsup\": \"^8.5.1\",\n \"typedoc\": \"^0.28.20\",\n \"typedoc-material-theme\": \"^1.4.1\",\n \"typescript\": \"^5.0.0\",\n \"typescript-eslint\": \"^8.0.0\",\n \"vitest\": \"^4.1.2\"\n },\n \"dependencies\": {\n \"@fastify/formbody\": \"^8.0.2\",\n \"@fastify/websocket\": \"^11.2.0\",\n \"@segment/analytics-node\": \"^3.1.0\",\n \"axios\": \"^1.15.2\",\n \"axios-retry\": \"^4.5.0\",\n \"dotenv\": \"^16.4.7\",\n \"fastify\": \"^5.8.5\",\n \"fastify-graceful-shutdown\": \"^5.0.0\",\n \"pino\": \"^9.0.0\",\n \"twilio\": \"^5.10.7\",\n \"ws\": \"^8.19.0\",\n \"zod\": \"^4.0.0\"\n },\n \"peerDependencies\": {\n \"@openai/agents\": \"^0.8.0\"\n },\n \"peerDependenciesMeta\": {\n \"@openai/agents\": {\n \"optional\": true\n }\n },\n \"engines\": {\n \"node\": \">=22.13.0\",\n \"npm\": \">=9.0.0\"\n }\n}\n","import { Logger, createLogger } from '../lib/logger';\nimport { TACConfig } from '../lib/config';\nimport packageJson from '../../../../package.json' with { type: 'json' };\nimport axios, { AxiosInstance } from 'axios';\nimport axiosRetry from 'axios-retry';\n\nfunction buildUserAgent(): string {\n return `twilio-agent-connect-typescript/${packageJson.version}`;\n}\n\n/**\n * Base HTTP client for Twilio API services\n *\n * Features:\n * - Automatic Basic Auth using Twilio API credentials\n * - User-Agent header injection\n * - 30-second request timeout\n * - HTTP redirect following (up to 5 redirects) with auth preservation\n * - Automatic retry (up to 3 retries / 4 total attempts with exponential backoff)\n * - Error logging for failed requests\n * - Automatic JSON serialization/deserialization\n */\nexport abstract class BaseClient {\n protected readonly baseUrl: string;\n protected readonly logger: Logger;\n protected readonly axiosInstance: AxiosInstance;\n\n constructor(baseUrl: string, config: TACConfig, logger?: Logger) {\n this.baseUrl = baseUrl;\n this.logger = logger || createLogger({ name: this.constructor.name });\n\n // Create Authorization header for Basic Auth\n const authHeader =\n 'Basic ' + Buffer.from(`${config.apiKey}:${config.apiSecret}`).toString('base64');\n\n // Extract origin from baseUrl for same-origin check\n const baseOrigin = new URL(baseUrl).origin;\n\n this.axiosInstance = axios.create({\n baseURL: baseUrl,\n timeout: 30000,\n maxRedirects: 5,\n headers: {\n 'User-Agent': buildUserAgent(),\n Authorization: authHeader,\n },\n beforeRedirect: (options, _responseDetails) => {\n // Preserve auth header for same-origin redirects only (prevents credential leaks)\n const redirectUrl = new URL(\n String(options.path || ''),\n `${String(options.protocol)}//${String(options.host)}`\n );\n if (redirectUrl.origin === baseOrigin && options.headers) {\n (options.headers as Record<string, string>).Authorization = authHeader;\n }\n },\n });\n\n axiosRetry(this.axiosInstance, {\n retries: 3,\n retryDelay: retryCount => axiosRetry.exponentialDelay(retryCount),\n retryCondition: error => {\n // Retry network/no-response errors for any method, and retry 5xx/429 responses only for idempotent methods\n // (which helps prevent duplicate side effects on non-idempotent requests such as POST)\n return axiosRetry.isNetworkOrIdempotentRequestError(error);\n },\n });\n\n // Response interceptor for error logging\n this.axiosInstance.interceptors.response.use(\n response => response,\n error => {\n if (axios.isAxiosError(error)) {\n const status = error.response?.status;\n const logContext = {\n error: error.message,\n method: error.config?.method,\n url: error.config?.url,\n status,\n };\n // Log 4xx as warn (client errors, may be expected/handled)\n // Log 5xx/network as error (server/infrastructure failures)\n if (status !== undefined && status >= 400 && status < 500) {\n this.logger.warn(logContext, 'HTTP request client error');\n } else {\n this.logger.error(logContext, 'HTTP request error');\n }\n }\n throw error;\n }\n );\n }\n\n /**\n * Make an HTTP request with automatic header injection and error handling\n *\n * @param url - The URL path (relative to baseURL)\n * @param method - HTTP method (GET, POST, etc.)\n * @param data - Optional request body (will be automatically serialized to JSON)\n * @param params - Optional query string parameters\n * @returns Promise resolving to the response data (already parsed from JSON)\n * @throws Error on timeout, HTTP errors, or network failures\n */\n protected async makeRequest<TResponse = unknown>(\n url: string,\n method: string,\n data?: unknown,\n params?: Record<string, string>\n ): Promise<TResponse> {\n const response = await this.axiosInstance.request<TResponse>({\n url,\n method,\n data,\n params,\n });\n\n return response.data;\n }\n}\n","import { z } from 'zod';\nimport {\n MemoryRetrievalRequest,\n MemoryRetrievalRequestSchema,\n MemoryRetrievalResponse,\n EMPTY_MEMORY_RESPONSE,\n ObservationInfoSchema,\n SummaryInfoSchema,\n MemoryCommunicationSchema,\n ProfileLookupResponse,\n ProfileLookupResponseSchema,\n ProfileResponse,\n ProfileResponseSchema,\n ObservationCreateRequest,\n CreateObservationsRequest,\n CreateObservationResponse,\n CreateObservationResponseSchema,\n CreateConversationSummariesResponse,\n CreateConversationSummariesResponseSchema,\n} from '../types';\nimport { TACConfig } from '../lib/config';\nimport { Logger } from '../lib/logger';\nimport { BaseClient } from './base';\n\n/**\n * Memory client for interacting with Twilio Memory Service\n */\nexport class MemoryClient extends BaseClient {\n private readonly storeId: string;\n\n constructor(config: TACConfig, storeId: string, logger?: Logger) {\n const baseUrl = config.region\n ? `https://memory.${config.region}.twilio.com`\n : 'https://memory.twilio.com';\n super(baseUrl, config, logger);\n this.storeId = storeId;\n }\n\n /**\n * Get the store ID this client is configured for\n */\n public getStoreId(): string {\n return this.storeId;\n }\n\n /**\n * Retrieve memories for a specific profile\n *\n * @param profileId - The profile ID to retrieve memories for\n * @param request - Optional request parameters for filtering results\n * @returns Promise containing memory retrieval response\n */\n public async retrieveMemories(\n profileId: string,\n request: Partial<MemoryRetrievalRequest> = {}\n ): Promise<MemoryRetrievalResponse> {\n try {\n const url = `/v1/Stores/${this.storeId}/Profiles/${profileId}/Recall`;\n\n this.logger.debug(\n {\n memory_store_id: this.storeId,\n profile_id: profileId,\n request,\n },\n 'Retrieving memories'\n );\n\n // Validate and apply defaults through schema\n const validatedRequest = MemoryRetrievalRequestSchema.parse(request);\n\n // Serialize request to Memory API wire format (camelCase)\n const requestBody = {\n conversationId: validatedRequest.conversationId,\n query: validatedRequest.query,\n beginDate: validatedRequest.beginDate,\n endDate: validatedRequest.endDate,\n observationsLimit: validatedRequest.observationsLimit,\n summariesLimit: validatedRequest.summariesLimit,\n communicationsLimit: validatedRequest.communicationsLimit,\n relevanceThreshold: validatedRequest.relevanceThreshold,\n };\n\n // Remove undefined values\n const cleanedBody = Object.fromEntries(\n Object.entries(requestBody).filter(([_, value]) => value !== undefined)\n );\n\n const data = await this.makeRequest<MemoryRetrievalResponse>(url, 'POST', cleanedBody);\n\n this.logger.debug(\n {\n memory_store_id: this.storeId,\n profile_id: profileId,\n },\n 'Raw memory response received'\n );\n\n if (data === null || typeof data !== 'object') {\n this.logger.warn(\n {\n profile_id: profileId,\n memory_store_id: this.storeId,\n },\n 'Invalid memory response format'\n );\n return EMPTY_MEMORY_RESPONSE;\n }\n\n // Parse each item independently so a single malformed entry (e.g. an\n // unrecognized enum value) doesn't discard the entire response.\n const response = data as Record<string, unknown>;\n const observations = this.parseItems(\n response.observations,\n ObservationInfoSchema,\n 'observation',\n profileId\n );\n const summaries = this.parseItems(\n response.summaries,\n SummaryInfoSchema,\n 'summary',\n profileId\n );\n const communications = this.parseItems(\n response.communications,\n MemoryCommunicationSchema,\n 'communication',\n profileId\n );\n\n this.logger.debug(\n {\n memory_store_id: this.storeId,\n profile_id: profileId,\n observation_count: observations.length,\n summary_count: summaries.length,\n communication_count: communications.length,\n // Server-side query time; dominates /Recall when expansion runs.\n query_time_ms: (response.meta as { queryTime?: number } | undefined)?.queryTime,\n },\n 'Memory retrieval succeeded'\n );\n\n return { observations, summaries, communications };\n } catch (error) {\n this.logger.warn(\n {\n error: error instanceof Error ? error.message : String(error),\n profile_id: profileId,\n memory_store_id: this.storeId,\n },\n 'Memory retrieval error'\n );\n return EMPTY_MEMORY_RESPONSE;\n }\n }\n\n /** Cap on per-item validation warnings logged per response, to avoid flooding logs. */\n private static readonly MAX_INVALID_ITEM_LOGS = 10;\n\n /**\n * Validate an array of memory items one at a time, dropping (and logging)\n * any that fail validation while keeping the rest.\n *\n * Per-item warnings are capped at {@link MemoryClient.MAX_INVALID_ITEM_LOGS}\n * and followed by a single summary warning with the total `invalid_count`.\n */\n private parseItems<T>(\n value: unknown,\n schema: z.ZodType<T, unknown>,\n itemType: string,\n profileId: string\n ): T[] {\n if (value === undefined) {\n return [];\n }\n\n if (!Array.isArray(value)) {\n this.logger.warn(\n {\n profile_id: profileId,\n memory_store_id: this.storeId,\n item_type: itemType,\n received_type: typeof value,\n },\n 'Expected an array of memory items but received a non-array value'\n );\n return [];\n }\n\n const parsed: T[] = [];\n let invalidCount = 0;\n for (const [index, item] of value.entries()) {\n const result = schema.safeParse(item);\n if (result.success) {\n parsed.push(result.data);\n continue;\n }\n\n invalidCount += 1;\n if (invalidCount <= MemoryClient.MAX_INVALID_ITEM_LOGS) {\n this.logger.warn(\n {\n profile_id: profileId,\n memory_store_id: this.storeId,\n item_type: itemType,\n item_index: index,\n validation_errors: result.error.issues,\n },\n 'Dropping invalid memory item'\n );\n }\n }\n\n if (invalidCount > 0) {\n this.logger.warn(\n {\n profile_id: profileId,\n memory_store_id: this.storeId,\n item_type: itemType,\n invalid_count: invalidCount,\n total_count: value.length,\n },\n 'Dropped invalid memory items'\n );\n }\n\n return parsed;\n }\n\n /**\n * Find profiles that contain a specific identifier value\n *\n * @param idType - Identifier type (e.g., 'phone', 'email')\n * @param value - Raw value captured for the identifier\n * @returns Promise containing profile lookup response with normalized value and matching profile IDs\n */\n public async lookupProfile(idType: string, value: string): Promise<ProfileLookupResponse> {\n const url = `/v1/Stores/${this.storeId}/Profiles/Lookup`;\n\n const requestBody = {\n idType,\n value,\n };\n\n try {\n const data = await this.makeRequest<ProfileLookupResponse>(url, 'POST', requestBody);\n return ProfileLookupResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to lookup profile: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create a profile via identity resolution (upsert).\n *\n * Conversation Memory runs identity resolution on the submitted traits: if an identifier\n * match is found, the existing canonical profile ID is returned; otherwise a\n * new profile is minted. The body must contain at least one\n * trait-promoted-to-identifier per the store's identity resolution settings,\n * else resolution fails with 400.\n *\n * The write is queued (202 Accepted) — the canonical profile ID is returned\n * synchronously in the response body, but downstream traits may not be fully\n * persisted immediately.\n *\n * @param traits - Trait-group → field → value mapping (e.g. `{\"Contact\": {\"phone\": \"+13175551234\"}}`)\n * @returns Canonical profile ID (`mem_profile_…`)\n * @throws Error if the API request fails or the response is missing an `id` field\n */\n public async createProfile(traits: Record<string, Record<string, unknown>>): Promise<string> {\n const url = `/v1/Stores/${this.storeId}/Profiles`;\n const requestBody = { traits };\n\n let data: unknown;\n try {\n data = await this.makeRequest<unknown>(url, 'POST', requestBody);\n } catch (error) {\n throw new Error(\n `Failed to create profile: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n\n const profileId =\n data && typeof data === 'object' && 'id' in data ? (data as { id: unknown }).id : undefined;\n if (typeof profileId !== 'string') {\n throw new Error(`CreateProfile response missing 'id' field: ${JSON.stringify(data)}`);\n }\n return profileId;\n }\n\n /**\n * Fetch profile information with traits\n *\n * @param profileId - The profile ID to fetch\n * @param traitGroups - Optional list of trait group names to include\n * @returns Promise containing profile response with ID, created timestamp, and traits\n */\n public async getProfile(profileId: string, traitGroups?: string[]): Promise<ProfileResponse> {\n const url = `/v1/Stores/${this.storeId}/Profiles/${profileId}`;\n\n const params: Record<string, string> = {};\n if (traitGroups && traitGroups.length > 0) {\n params.traitGroups = traitGroups.join(',');\n }\n\n try {\n const data = await this.makeRequest<ProfileResponse>(\n url,\n 'GET',\n undefined,\n Object.keys(params).length > 0 ? params : undefined\n );\n return ProfileResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to get profile: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create an observation for a profile.\n *\n * The Memory API Observations endpoint is a batch create: the observation is\n * wrapped in an `observations` array and `occurredAt` is required, so it\n * defaults to the current time (ISO 8601) when omitted or blank.\n *\n * @param profileId - The profile ID to create the observation for\n * @param content - The observation content\n * @param source - Source of the observation (default: 'conversation-intelligence')\n * @param conversationIds - Optional array of conversation IDs associated with this observation\n * @param occurredAt - Timestamp when the observation occurred (ISO 8601); defaults to now when omitted or blank\n * @returns Promise containing the API confirmation message\n */\n public async createObservation(\n profileId: string,\n content: string,\n source: string = 'conversation-intelligence',\n conversationIds?: string[],\n occurredAt?: string\n ): Promise<CreateObservationResponse> {\n const url = `/v1/Stores/${this.storeId}/Profiles/${profileId}/Observations`;\n\n const observation: ObservationCreateRequest = {\n content,\n source,\n occurredAt: occurredAt && occurredAt.trim() ? occurredAt : new Date().toISOString(),\n };\n\n if (conversationIds && conversationIds.length > 0) {\n observation.conversationIds = conversationIds;\n }\n\n const requestBody: CreateObservationsRequest = { observations: [observation] };\n\n try {\n const data = await this.makeRequest<CreateObservationResponse>(url, 'POST', requestBody);\n return CreateObservationResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to create observation: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create conversation summaries for a profile\n *\n * @param profileId - The profile ID to create summaries for\n * @param summaries - Array of summary items to create\n * @returns Promise containing a success message for the created conversation summaries\n */\n public async createConversationSummaries(\n profileId: string,\n summaries: Array<{\n content: string;\n conversationId: string;\n occurredAt: string;\n source?: string;\n }>\n ): Promise<CreateConversationSummariesResponse> {\n const url = `/v1/Stores/${this.storeId}/Profiles/${profileId}/ConversationSummaries`;\n\n const requestBody = {\n summaries: summaries.map(s => ({\n content: s.content,\n conversationId: s.conversationId,\n occurredAt: s.occurredAt,\n source: s.source ?? 'conversation-intelligence',\n })),\n };\n\n try {\n const data = await this.makeRequest<CreateConversationSummariesResponse>(\n url,\n 'POST',\n requestBody\n );\n return CreateConversationSummariesResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to create conversation summaries: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n}\n","import {\n ActionResponse,\n ActionResponseSchema,\n Communication,\n ConversationResponse,\n ConversationResponseSchema,\n ConversationAddress,\n ConversationParticipant,\n ConversationParticipantSchema,\n SendMessageActionRequest,\n ConversationConfiguration,\n ConversationConfigurationSchema,\n ListCommunicationsResponse,\n ListCommunicationsResponseSchema,\n ListParticipantsResponse,\n ListParticipantsResponseSchema,\n ListConversationsResponse,\n ListConversationsResponseSchema,\n} from '../types';\nimport axios from 'axios';\nimport { TACConfig } from '../lib/config';\nimport { Logger } from '../lib/logger';\nimport { BaseClient } from './base';\n\n/**\n * Conversation client for interacting with Twilio Conversations Service\n */\nexport class ConversationClient extends BaseClient {\n private readonly conversationConfigurationId: string;\n\n constructor(config: TACConfig, logger?: Logger) {\n const baseUrl = config.region\n ? `https://conversations.${config.region}.twilio.com`\n : 'https://conversations.twilio.com';\n super(baseUrl, config, logger);\n if (!config.conversationConfigurationId) {\n throw new Error('conversationConfigurationId is required to create ConversationClient');\n }\n this.conversationConfigurationId = config.conversationConfigurationId;\n }\n\n /**\n * Create an action on a conversation via the Conversation Orchestrator Actions API.\n *\n * Currently supports SEND_MESSAGE actions. Returns 202 Accepted; the action is\n * processed asynchronously and delivered via COMMUNICATION_CREATED webhook.\n *\n * @param conversationId - The conversation ID\n * @param request - The action request ({type, payload})\n * @returns Promise containing the ActionResponse\n */\n public async createAction(\n conversationId: string,\n request: SendMessageActionRequest\n ): Promise<ActionResponse> {\n const url = `/v2/Conversations/${conversationId}/Actions`;\n\n try {\n const data = await this.makeRequest<ActionResponse>(url, 'POST', request);\n return ActionResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to create action: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * List communications for a conversation\n *\n * @param conversationId - The conversation ID\n * @returns Promise containing array of communications\n */\n public async listCommunications(conversationId: string): Promise<Communication[]> {\n const url = `/v2/Conversations/${conversationId}/Communications`;\n\n try {\n const data = await this.makeRequest<ListCommunicationsResponse>(url, 'GET');\n const validated = ListCommunicationsResponseSchema.parse(data);\n return validated.communications;\n } catch (error) {\n throw new Error(\n `Failed to list communications: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create a new conversation, optionally with inline participants.\n *\n * When participants are provided, CO creates them atomically with the\n * conversation. If an active conversation with the same participant\n * addresses already exists (respecting the configuration's group-by\n * rules), CO returns 409 with a pointer to the existing conversation.\n */\n public async createConversation(options?: {\n name?: string;\n participants?: Array<{\n type: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT';\n addresses: ConversationAddress[];\n }>;\n }): Promise<ConversationResponse> {\n const url = `/v2/Conversations`;\n\n const requestBody: Record<string, unknown> = {\n configurationId: this.conversationConfigurationId,\n };\n\n if (options?.name) {\n requestBody.name = options.name;\n }\n\n if (options?.participants) {\n requestBody.participants = options.participants;\n }\n\n try {\n const data = await this.makeRequest<ConversationResponse>(url, 'POST', requestBody);\n return ConversationResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to create conversation: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Create a conversation with inline participants, reusing an existing active\n * conversation if CO returns 409 (group-by dedup).\n *\n * On 409 CO returns the existing conversation ID in the\n * X-Conflicting-Resource-Id response header.\n */\n public async createOrReuseConversation(\n participants: Array<{\n type: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT';\n addresses: ConversationAddress[];\n }>\n ): Promise<{ conversation: { id: string }; reused: boolean }> {\n try {\n const conversation = await this.createConversation({ participants });\n return { conversation, reused: false };\n } catch (error) {\n const existingId = this.extractConversationIdFrom409(error);\n if (existingId) {\n this.logger.info(\n { conversation_id: existingId },\n 'Reusing existing active conversation (409 dedup)'\n );\n return { conversation: { id: existingId }, reused: true };\n }\n throw error;\n }\n }\n\n /**\n * Extract conversation ID from a 409 response's X-Conflicting-Resource-Id header.\n */\n private extractConversationIdFrom409(error: unknown): string | null {\n // Unwrap: createConversation wraps the axios error in a generic Error\n const cause = error instanceof Error ? (error.cause ?? error) : error;\n if (!axios.isAxiosError(cause) || cause.response?.status !== 409) {\n return null;\n }\n\n const headers = cause.response.headers as Record<string, string> | undefined;\n const conflictId = headers?.['x-conflicting-resource-id'];\n return typeof conflictId === 'string' && conflictId.length > 0 ? conflictId : null;\n }\n\n /**\n * Add a participant to a conversation.\n *\n * @param conversationId - The conversation ID\n * @param addresses - Array of participant addresses\n * @param participantType - Type of participant (CUSTOMER, AI_AGENT, HUMAN_AGENT, AGENT)\n * @returns Promise containing participant response\n */\n public async addParticipant(\n conversationId: string,\n addresses: ConversationAddress[],\n participantType: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT' | 'AGENT'\n ): Promise<ConversationParticipant> {\n const url = `/v2/Conversations/${conversationId}/Participants`;\n\n const requestBody = {\n type: participantType,\n addresses,\n };\n\n try {\n const data = await this.makeRequest<ConversationParticipant>(url, 'POST', requestBody);\n return ConversationParticipantSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to add participant: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Replace an existing participant.\n *\n * PUT is a full resource replacement per the Conversation Orchestrator spec —\n * any field omitted from the body is cleared on the server. Callers must pass\n * the current `addresses` (and `name` if set) to preserve them.\n *\n * @param conversationId - Conversation ID containing the participant\n * @param participantId - Participant ID to update\n * @param participantType - New participant type\n * @param addresses - Current participant addresses (required to avoid wiping)\n * @param options.name - Current participant display name (optional)\n * @param options.profileId - Conversation Memory profile ID to attach (optional)\n * @returns Promise containing the updated participant\n */\n public async updateParticipant(\n conversationId: string,\n participantId: string,\n participantType: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT' | 'AGENT',\n addresses: ConversationAddress[],\n options?: { name?: string; profileId?: string }\n ): Promise<ConversationParticipant> {\n const url = `/v2/Conversations/${conversationId}/Participants/${participantId}`;\n\n const requestBody: Record<string, unknown> = {\n type: participantType,\n addresses,\n };\n if (options?.name !== undefined) {\n requestBody.name = options.name;\n }\n if (options?.profileId !== undefined) {\n requestBody.profileId = options.profileId;\n }\n\n try {\n const data = await this.makeRequest<ConversationParticipant>(url, 'PUT', requestBody);\n return ConversationParticipantSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to update participant: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * List participants in a conversation\n *\n * @param conversationId - The conversation ID\n * @returns Promise containing array of participants\n */\n public async listParticipants(conversationId: string): Promise<ConversationParticipant[]> {\n const url = `/v2/Conversations/${conversationId}/Participants`;\n\n try {\n const data = await this.makeRequest<ListParticipantsResponse>(url, 'GET');\n const validated = ListParticipantsResponseSchema.parse(data);\n return validated.participants;\n } catch (error) {\n throw new Error(\n `Failed to list participants: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * List conversations with optional filters\n *\n * @param filters - Optional filters (channelId, status)\n * @returns Promise containing array of conversations\n */\n public async listConversations(filters?: {\n channelId?: string;\n status?: string[];\n }): Promise<ConversationResponse[]> {\n const url = `/v2/Conversations`;\n\n const params: Record<string, string> = {};\n if (filters?.channelId) {\n params.channelId = filters.channelId;\n }\n if (filters?.status && filters.status.length > 0) {\n params.status = filters.status.join(',');\n }\n\n try {\n const data = await this.makeRequest<ListConversationsResponse>(\n url,\n 'GET',\n undefined,\n Object.keys(params).length > 0 ? params : undefined\n );\n const validated = ListConversationsResponseSchema.parse(data);\n return validated.conversations;\n } catch (error) {\n throw new Error(\n `Failed to list conversations: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Clear statusCallbacks on a conversation's instance configuration.\n *\n * This stops the conversation from sending webhook events to TAC,\n * which is needed during handoff so the receiving system can take over.\n *\n * @param conversationId - The conversation ID to update\n */\n public async clearStatusCallbacks(conversationId: string): Promise<void> {\n const url = `/v2/Conversations/${conversationId}`;\n\n try {\n await this.makeRequest<unknown>(url, 'PATCH', {\n configuration: { statusCallbacks: [] },\n });\n } catch (error) {\n throw new Error(\n `Failed to clear status callbacks: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Update conversation status\n *\n * @param conversationId - The conversation ID\n * @param status - New status (ACTIVE, INACTIVE, CLOSED)\n * @returns Promise containing updated conversation\n */\n public async updateConversation(\n conversationId: string,\n status: 'ACTIVE' | 'INACTIVE' | 'CLOSED'\n ): Promise<ConversationResponse> {\n const url = `/v2/Conversations/${conversationId}`;\n\n const requestBody = { status };\n\n try {\n const data = await this.makeRequest<ConversationResponse>(url, 'PUT', requestBody);\n return ConversationResponseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to update conversation: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Retrieve the details for a single configuration\n *\n * @param configurationId - The configuration ID to retrieve\n * @returns Promise containing configuration details\n */\n public async getConfiguration(configurationId: string): Promise<ConversationConfiguration> {\n const url = `/v2/ControlPlane/Configurations/${configurationId}`;\n\n try {\n const data = await this.makeRequest<ConversationConfiguration>(url, 'GET');\n return ConversationConfigurationSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to get configuration: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n}\n","import {\n KnowledgeBase,\n KnowledgeBaseSchema,\n KnowledgeChunkResult,\n KnowledgeSearchResponse,\n KnowledgeSearchResponseSchema,\n} from '../types';\nimport { TACConfig } from '../lib/config';\nimport { Logger } from '../lib/logger';\nimport { BaseClient } from './base';\n\n/**\n * Knowledge client for interacting with Twilio Knowledge Service\n */\nexport class KnowledgeClient extends BaseClient {\n constructor(config: TACConfig, logger?: Logger) {\n const baseUrl = config.region\n ? `https://knowledge.${config.region}.twilio.com`\n : 'https://knowledge.twilio.com';\n super(baseUrl, config, logger);\n }\n\n /**\n * Get knowledge base metadata\n *\n * @param knowledgeBaseId - The knowledge base ID (format: know_knowledgebase_*)\n * @returns Promise containing knowledge base metadata\n */\n public async getKnowledgeBase(knowledgeBaseId: string): Promise<KnowledgeBase> {\n const url = `/v2/ControlPlane/KnowledgeBases/${knowledgeBaseId}`;\n\n try {\n const data = await this.makeRequest<KnowledgeBase>(url, 'GET');\n return KnowledgeBaseSchema.parse(data);\n } catch (error) {\n throw new Error(\n `Failed to get knowledge base: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n /**\n * Search knowledge base for relevant content\n *\n * @param knowledgeBaseId - The knowledge base ID (format: know_knowledgebase_*)\n * @param query - Search query (max 2048 characters)\n * @param topK - Maximum number of results to return (default: 5, max: 20)\n * @param knowledgeIds - Optional list of knowledge IDs to filter results\n * @returns Promise containing array of search result chunks\n */\n public async searchKnowledgeBase(\n knowledgeBaseId: string,\n query: string,\n topK: number = 5,\n knowledgeIds?: string[]\n ): Promise<KnowledgeChunkResult[]> {\n const url = `/v2/KnowledgeBases/${knowledgeBaseId}/Search`;\n\n const requestBody: Record<string, unknown> = {\n query,\n top: Math.min(Math.max(topK, 1), 20), // Clamp to 1-20\n };\n\n if (knowledgeIds && knowledgeIds.length > 0) {\n requestBody.knowledgeIds = knowledgeIds;\n }\n\n try {\n const data = await this.makeRequest<KnowledgeSearchResponse>(url, 'POST', requestBody);\n const validated = KnowledgeSearchResponseSchema.parse(data);\n return validated.chunks;\n } catch (error) {\n throw new Error(\n `Failed to search knowledge base: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n}\n","import { Analytics } from '@segment/analytics-node';\nimport packageJson from '../../../../package.json' with { type: 'json' };\nimport { createLogger, Logger } from './logger';\n\n// The npm package name is unsuffixed, so it can't identify which Agent Connect\n// SDK sent an event.\nconst SDK_PACKAGE = 'twilio-agent-connect-typescript';\n\nlet client: Analytics | null = null;\nlet log: Logger | null = null;\nlet disabled: boolean | null = null;\n\nfunction getLog(): Logger {\n return (log ??= createLogger({ name: 'analytics' }));\n}\n\nfunction isDisabled(): boolean {\n if (disabled === null) {\n disabled = process.env.TAC_ANALYTICS_DISABLED === 'true';\n }\n return disabled;\n}\n\nfunction getClient(): Analytics | null {\n if (isDisabled()) return null;\n if (client) return client;\n client = new Analytics({\n writeKey: 'oH5gLNxB4NEg60y81mBxHWZn4RAoXQTN',\n flushAt: 20,\n flushInterval: 10_000,\n });\n // Debug, not warn: telemetry is best-effort and its failures are not the\n // consumer's problem, so they shouldn't surface in an application's logs.\n client.on('error', err => {\n getLog().debug({ err }, 'Segment analytics error');\n });\n return client;\n}\n\ntype EventProperties = { account_sid: string } & Record<string, unknown>;\n\n/**\n * Record a telemetry event. Never throws.\n *\n * @internal\n */\nexport function trackEvent(event: string, properties: EventProperties): void {\n try {\n const analytics = getClient();\n if (!analytics) return;\n analytics.track({\n anonymousId: properties.account_sid,\n event,\n properties: {\n ...properties,\n sdk_version: packageJson.version,\n sdk_package: SDK_PACKAGE,\n },\n });\n getLog().debug({ event }, 'Analytics event tracked');\n } catch (err) {\n getLog().debug({ err, event }, 'Analytics event failed');\n }\n}\n\n/**\n * Flush pending events and close the client. Called by `TAC.shutdown()`.\n *\n * @internal\n */\nexport async function shutdownAnalytics(): Promise<void> {\n if (client) {\n await client.closeAndFlush({ timeout: 5000 }).catch(() => {});\n client = null;\n }\n}\n\n/** Reset internal state — for testing only. */\nexport function _resetAnalytics(): void {\n client = null;\n disabled = null;\n log = null;\n}\n","import {\n OperatorResultEvent,\n OperatorResultEventSchema,\n OperatorResult,\n OperatorProcessingResult,\n ConversationIntelligenceConfig,\n} from '../types/index';\nimport { MemoryClient } from '../clients/memory';\nimport { Logger, createLogger } from './logger';\n\n/**\n * Extract profile IDs from operator result execution details\n *\n * @param operatorResult - The operator result to extract profile IDs from\n * @returns Array of profile IDs found in participants\n */\nfunction extractProfileIds(operatorResult: OperatorResult): string[] {\n const profileIds: string[] = [];\n\n if (operatorResult.executionDetails?.participants) {\n for (const participant of operatorResult.executionDetails.participants) {\n if (participant.profileId) {\n profileIds.push(participant.profileId);\n }\n }\n }\n\n return profileIds;\n}\n\n/**\n * Generate content string from operator result\n *\n * @param operatorResult - The operator result to generate content from\n * @returns Content string or undefined if result is empty\n */\nfunction generateContent(operatorResult: OperatorResult): string | undefined {\n const result = operatorResult.result;\n\n if (result === null || result === undefined) {\n return undefined;\n }\n\n if (typeof result === 'string') {\n return result.trim() || undefined;\n }\n\n // For objects/arrays, stringify them\n const jsonString = JSON.stringify(result);\n return jsonString === '{}' || jsonString === '[]' ? undefined : jsonString;\n}\n\n/**\n * Parse summaries content from JSON result\n *\n * Expects format: { \"summaries\": [\"summary1\", \"summary2\", ...] }\n *\n * @param jsonContent - JSON string to parse\n * @returns Array of summary strings\n */\nfunction parseSummariesContent(jsonContent: string): string[] {\n try {\n const parsed = JSON.parse(jsonContent) as unknown;\n\n if (typeof parsed === 'object' && parsed !== null && 'summaries' in parsed) {\n const summaries = (parsed as { summaries: unknown }).summaries;\n if (Array.isArray(summaries)) {\n return summaries.filter((s): s is string => typeof s === 'string' && s.trim() !== '');\n }\n }\n\n return [];\n } catch {\n return [];\n }\n}\n\n/**\n * Processor for Conversation Intelligence operator result webhooks\n *\n * Processes operator results from CI and creates conversation summaries in the\n * Memory service based on the operator configuration.\n */\nexport class OperatorResultProcessor {\n private readonly memoryClient: MemoryClient;\n private readonly config: ConversationIntelligenceConfig;\n private readonly logger: Logger;\n\n constructor(memoryClient: MemoryClient, config: ConversationIntelligenceConfig, logger?: Logger) {\n this.memoryClient = memoryClient;\n this.config = config;\n this.logger = logger ?? createLogger({ name: 'cintel-processor' });\n }\n\n /**\n * Process an operator result event webhook payload\n *\n * @param payload - The raw webhook payload\n * @returns Processing result indicating success/failure and details\n */\n public async processEvent(payload: unknown): Promise<OperatorProcessingResult> {\n // Validate the payload\n const parseResult = OperatorResultEventSchema.safeParse(payload);\n\n if (!parseResult.success) {\n this.logger.warn(\n { validation_errors: parseResult.error.issues },\n 'Invalid operator result event payload'\n );\n return {\n success: false,\n skipped: false,\n error: `Invalid payload: ${parseResult.error.message}`,\n createdCount: 0,\n };\n }\n\n const event = parseResult.data;\n\n // Check if this event is from the configured CI configuration\n if (event.intelligenceConfiguration.id !== this.config.configurationId) {\n this.logger.debug(\n {\n received_config_id: event.intelligenceConfiguration.id,\n expected_config_id: this.config.configurationId,\n },\n 'Skipping event from different CI configuration'\n );\n return {\n success: true,\n skipped: true,\n skipReason: `Event from different CI configuration: ${event.intelligenceConfiguration.id}`,\n createdCount: 0,\n };\n }\n\n // Check for memory store ID and verify it matches the client's store ID\n if (!event.memoryStoreId) {\n this.logger.warn({ conversation_id: event.conversationId }, 'No memory store ID in event');\n return {\n success: false,\n skipped: false,\n error: 'No memory store ID provided in event',\n createdCount: 0,\n };\n }\n\n const clientStoreId = this.memoryClient.getStoreId();\n if (event.memoryStoreId !== clientStoreId) {\n this.logger.debug(\n {\n conversation_id: event.conversationId,\n event_store_id: event.memoryStoreId,\n client_store_id: clientStoreId,\n },\n 'Skipping event from different memory store'\n );\n return {\n success: true,\n skipped: true,\n skipReason: `Event from different memory store: ${event.memoryStoreId} (expected ${clientStoreId})`,\n createdCount: 0,\n };\n }\n\n // Process each operator result\n const results: OperatorProcessingResult[] = [];\n\n for (const operatorResult of event.operatorResults) {\n const result = await this.processOperatorResult(event, operatorResult);\n results.push(result);\n }\n\n // Aggregate results\n const successCount = results.filter(r => r.success && !r.skipped).length;\n const skippedCount = results.filter(r => r.skipped).length;\n const errorCount = results.filter(r => !r.success).length;\n const totalCreated = results.reduce((sum, r) => sum + r.createdCount, 0);\n\n // Determine overall event type\n const eventTypes = results\n .filter(r => r.success && !r.skipped && r.eventType)\n .map(r => r.eventType);\n const uniqueEventTypes = [...new Set(eventTypes)];\n const eventType =\n uniqueEventTypes.length === 1\n ? uniqueEventTypes[0]\n : uniqueEventTypes.length > 1\n ? 'mixed'\n : undefined;\n\n if (errorCount > 0) {\n const errors = results.filter(r => !r.success).map(r => r.error);\n return {\n success: false,\n eventType,\n skipped: false,\n error: `${errorCount} operator(s) failed: ${errors.join('; ')}`,\n createdCount: totalCreated,\n };\n }\n\n if (skippedCount === results.length) {\n return {\n success: true,\n skipped: true,\n skipReason: 'All operator results were skipped',\n createdCount: 0,\n };\n }\n\n this.logger.info(\n {\n conversation_id: event.conversationId,\n success_count: successCount,\n skipped_count: skippedCount,\n created_count: totalCreated,\n event_type: eventType,\n },\n 'Processed operator result event'\n );\n\n return {\n success: true,\n eventType,\n skipped: false,\n createdCount: totalCreated,\n };\n }\n\n /**\n * Process an individual operator result\n */\n private async processOperatorResult(\n event: OperatorResultEvent,\n operatorResult: OperatorResult\n ): Promise<OperatorProcessingResult> {\n const operatorSid = operatorResult.operator.id;\n\n // Check if this is a configured operator\n const isSummaryOperator = this.config.summaryOperatorSid === operatorSid;\n\n if (!isSummaryOperator) {\n this.logger.debug(\n {\n operator_sid: operatorSid,\n summary_operator_sid: this.config.summaryOperatorSid,\n },\n 'Skipping unconfigured operator'\n );\n return {\n success: true,\n skipped: true,\n skipReason: `Operator ${operatorSid} is not configured for processing`,\n createdCount: 0,\n };\n }\n\n // Generate content from operator result\n const content = generateContent(operatorResult);\n\n if (!content) {\n this.logger.debug(\n { operator_sid: operatorSid },\n 'Skipping operator result with empty content'\n );\n return {\n success: true,\n skipped: true,\n skipReason: 'Operator result has empty content',\n createdCount: 0,\n };\n }\n\n // Extract profile IDs from execution details\n const profileIds = extractProfileIds(operatorResult);\n\n if (profileIds.length === 0) {\n this.logger.warn(\n { operator_sid: operatorSid, conversation_id: event.conversationId },\n 'No profile IDs found in operator result'\n );\n return {\n success: true,\n skipped: true,\n skipReason: 'No profile IDs found in operator result execution details',\n createdCount: 0,\n };\n }\n\n return this.processSummaryEvent(event, operatorResult, content, profileIds);\n }\n\n /**\n * Process a summary operator result\n */\n private async processSummaryEvent(\n event: OperatorResultEvent,\n operatorResult: OperatorResult,\n content: string,\n profileIds: string[]\n ): Promise<OperatorProcessingResult> {\n // Parse summaries from JSON content\n const summaries = parseSummariesContent(content);\n\n if (summaries.length === 0) {\n this.logger.debug(\n { operator_sid: operatorResult.operator.id },\n 'No summaries found in content'\n );\n return {\n success: true,\n eventType: 'summary',\n skipped: true,\n skipReason: 'No summaries found in operator result content',\n createdCount: 0,\n };\n }\n\n let createdCount = 0;\n\n // Create summaries for each profile\n for (const profileId of profileIds) {\n try {\n const summaryItems = summaries.map(summaryContent => ({\n content: summaryContent,\n conversationId: event.conversationId,\n occurredAt: operatorResult.dateCreated,\n source: 'conversation-intelligence',\n }));\n\n await this.memoryClient.createConversationSummaries(profileId, summaryItems);\n createdCount += summaries.length;\n\n this.logger.debug(\n {\n profile_id: profileId,\n conversation_id: event.conversationId,\n summary_count: summaries.length,\n },\n 'Created conversation summaries'\n );\n } catch (error) {\n this.logger.error(\n {\n err: error,\n profile_id: profileId,\n conversation_id: event.conversationId,\n },\n 'Failed to create conversation summaries'\n );\n return {\n success: false,\n eventType: 'summary',\n skipped: false,\n error: `Failed to create summaries: ${error instanceof Error ? error.message : String(error)}`,\n createdCount,\n };\n }\n }\n\n return {\n success: true,\n eventType: 'summary',\n skipped: false,\n createdCount,\n };\n }\n}\n","import {\n TACConfigData,\n ConversationSession,\n ConversationId,\n ProfileId,\n ProfileResponse,\n ChannelType,\n OperatorProcessingResult,\n} from '../types';\nimport { TACMemoryResponse } from './tac-memory-response';\nimport { TACConfig } from './config';\nimport { MemoryClient } from '../clients/memory';\nimport { ConversationClient } from '../clients/conversation';\nimport { KnowledgeClient } from '../clients/knowledge';\nimport { BaseChannel } from '../channels/base';\nimport { Logger, createLogger } from './logger';\nimport { shutdownAnalytics } from './analytics';\nimport { maskAddress } from '../util/log-redaction';\nimport { OperatorResultProcessor } from './operator-result-processor';\n\nexport interface TACOptions {\n config?: TACConfig | TACConfigData;\n logger?: Logger;\n}\n\n/**\n * Callback function signatures for TAC events\n */\nexport type MessageReadyCallback = (params: {\n conversationId: ConversationId;\n profileId: ProfileId | undefined;\n message: string;\n author: string;\n memory: TACMemoryResponse | undefined;\n session: ConversationSession;\n channel: ChannelType;\n abortSignal?: AbortSignal;\n}) => Promise<string | null | void> | string | null | void;\n\nexport type InterruptCallback = (params: {\n conversationId: ConversationId;\n utteranceUntilInterrupt: string | undefined;\n durationUntilInterruptMs: number | undefined;\n session: ConversationSession;\n}) => Promise<void> | void;\n\nexport type ConversationEndedCallback = (params: {\n session: ConversationSession;\n}) => Promise<void> | void;\n\n/**\n * Main Twilio Agent Connect class\n *\n * Central orchestrator that manages configuration, channels (SMS, WhatsApp, Chat, Voice),\n * callbacks, and coordinates between memory, conversations, and LLM integrations.\n */\nexport class TAC {\n private static readonly FACTORY_TOKEN = Symbol('TAC.create');\n\n private readonly config: TACConfig;\n public readonly logger: Logger;\n private memoryClient: MemoryClient | null = null;\n private knowledgeClient: KnowledgeClient | null = null;\n private conversationClient: ConversationClient | null = null;\n private readonly channels: Map<ChannelType, BaseChannel>;\n private cintelProcessor?: OperatorResultProcessor;\n\n private memoryStoreId: string | undefined;\n\n // Callback registrations\n private messageReadyCallback?: MessageReadyCallback;\n private interruptCallback?: InterruptCallback;\n private conversationEndedCallback?: ConversationEndedCallback;\n\n private constructor(token: symbol, options: TACOptions = {}) {\n if (token !== TAC.FACTORY_TOKEN) {\n throw new Error('TAC constructor is private. Use TAC.create() instead of new TAC().');\n }\n // Handle config resolution:\n // - If it's already a TACConfig instance, use it\n // - If it's data, create a new TACConfig\n // - If not provided, load from environment variables\n const finalConfig = options.config\n ? options.config instanceof TACConfig\n ? options.config\n : new TACConfig(options.config)\n : TACConfig.fromEnv();\n const finalLogger = options.logger ?? createLogger({ name: 'tac' });\n\n this.config = finalConfig;\n this.logger = finalLogger;\n this.channels = new Map();\n }\n\n public static async create(options: TACOptions = {}): Promise<TAC> {\n const tac = new TAC(TAC.FACTORY_TOKEN, options);\n\n if (!tac.config.isOrchestratorEnabled()) {\n tac.logger.info(\n 'Voice-only mode: conversationConfigurationId not set, skipping Conversation Orchestrator initialization'\n );\n return tac;\n }\n\n try {\n tac.conversationClient = new ConversationClient(\n tac.config,\n tac.logger.child({ component: 'conversation' })\n );\n\n // Safe: we already returned early if !isOrchestratorEnabled(), so conversationConfigurationId is defined\n const conversationConfig = await tac.conversationClient.getConfiguration(\n tac.config.conversationConfigurationId!\n );\n\n tac.memoryStoreId = conversationConfig.memoryStoreId;\n tac.memoryClient = new MemoryClient(\n tac.config,\n conversationConfig.memoryStoreId,\n tac.logger.child({ component: 'memory' })\n );\n\n tac.knowledgeClient = new KnowledgeClient(\n tac.config,\n tac.logger.child({ component: 'knowledge' })\n );\n\n if (tac.config.cintelConfigurationId) {\n tac.cintelProcessor = new OperatorResultProcessor(\n tac.memoryClient,\n {\n configurationId: tac.config.cintelConfigurationId,\n summaryOperatorSid: tac.config.cintelSummaryOperatorSid,\n },\n tac.logger.child({ component: 'cintel' })\n );\n }\n\n return tac;\n } catch (error) {\n tac.logger.error({ err: error }, 'TAC initialization failed');\n throw error;\n }\n }\n\n /**\n * Register a channel with the framework\n */\n public registerChannel(channel: BaseChannel): void {\n this.logger.info({ channel: channel.channelType }, 'Registering channel');\n\n // Remove existing channel of same type\n const existingChannel = this.channels.get(channel.channelType);\n if (existingChannel) {\n this.logger.info({ channel: channel.channelType }, 'Replacing existing channel registration');\n existingChannel.shutdown();\n }\n\n this.channels.set(channel.channelType, channel);\n\n // Set up channel event listeners\n this.setupChannelEventListeners(channel);\n\n this.logger.info({ channel: channel.channelType }, 'Channel registration complete');\n }\n\n /**\n * Set up event listeners for a channel\n */\n private setupChannelEventListeners(channel: BaseChannel): void {\n // Handle channel errors directly\n channel.on(\n 'error',\n ({ error, context }: { error: Error; context?: Record<string, unknown> }) => {\n this.logger.error({ err: error, ...context }, 'Channel error');\n }\n );\n\n // Handle message received events for SMS channels\n channel.on(\n 'messageReceived',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises -- Intentionally async callback\n async (data: {\n conversationId: ConversationId;\n profileId: ProfileId | undefined;\n message: string;\n author: string;\n userMemory: TACMemoryResponse | undefined;\n }): Promise<void> => {\n await this.handleMessageReady({ ...data, channelType: channel.channelType });\n }\n );\n\n // Handle voice prompt events\n channel.on(\n 'prompt',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises -- Intentionally async callback\n async ({\n conversationId,\n transcript,\n userMemory,\n session,\n abortSignal,\n }: {\n conversationId: ConversationId;\n transcript: string;\n userMemory?: TACMemoryResponse;\n session?: ConversationSession;\n abortSignal: AbortSignal;\n }): Promise<void> => {\n // Use session from event if available, otherwise get from channel\n const eventSession = session || channel.getConversationSession(conversationId);\n if (eventSession) {\n await this.handleMessageReady({\n conversationId,\n profileId: eventSession.profileId ? (eventSession.profileId as ProfileId) : undefined,\n message: transcript,\n author: 'user',\n userMemory,\n channelType: channel.channelType,\n abortSignal,\n });\n }\n }\n );\n\n // Handle voice interrupt events\n channel.on(\n 'interrupt',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises -- Intentionally async event handler\n async ({\n conversationId,\n utteranceUntilInterrupt,\n durationUntilInterruptMs,\n }: {\n conversationId: ConversationId;\n utteranceUntilInterrupt: string | undefined;\n durationUntilInterruptMs: number | undefined;\n }) => {\n const session = channel.getConversationSession(conversationId);\n if (session && this.interruptCallback) {\n try {\n await this.interruptCallback({\n conversationId,\n utteranceUntilInterrupt,\n durationUntilInterruptMs,\n session,\n });\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: conversationId },\n 'Interrupt callback error'\n );\n }\n }\n }\n );\n\n // Handle conversation ended events\n channel.on(\n 'conversationEnded',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises -- Intentionally async event handler\n async ({ session }: { session: ConversationSession }) => {\n if (this.conversationEndedCallback) {\n try {\n await this.conversationEndedCallback({ session });\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: session.conversationId },\n 'Conversation ended callback error'\n );\n }\n }\n }\n );\n }\n\n /**\n * Handle message ready event from channels\n */\n private async handleMessageReady(data: {\n conversationId: ConversationId;\n profileId: ProfileId | undefined;\n message: string;\n author: string;\n userMemory: TACMemoryResponse | undefined;\n channelType: ChannelType;\n abortSignal?: AbortSignal;\n }): Promise<void> {\n this.logger.debug(\n {\n conversation_id: data.conversationId,\n profile_id: data.profileId,\n author: maskAddress(data.author),\n message_length: data.message.length,\n channel: data.channelType,\n operation: 'handle_message_ready',\n },\n 'Handling message ready'\n );\n\n if (!this.messageReadyCallback) {\n this.logger.warn('No message ready callback registered');\n return;\n }\n\n try {\n // Use the channel type passed from the event handler, not lookup by conversation ID\n // This ensures voice prompts use voice channel even if SMS also has this conversation\n const channel = this.channels.get(data.channelType);\n if (!channel) {\n throw new Error(`No channel found for type ${data.channelType}`);\n }\n\n this.logger.debug(\n { conversation_id: data.conversationId, channel: channel.channelType },\n 'Using channel for message'\n );\n\n const session = channel.getConversationSession(data.conversationId);\n if (!session) {\n throw new Error(`No session found for conversation ${data.conversationId}`);\n }\n\n // Memory is now fetched by channels based on their memoryMode configuration\n const memory = data.userMemory;\n\n // Execute callback\n this.logger.debug(\n { conversation_id: data.conversationId },\n 'Executing message ready callback'\n );\n try {\n const response = await this.messageReadyCallback({\n conversationId: data.conversationId,\n profileId: data.profileId,\n message: data.message,\n author: data.author,\n memory: memory ?? undefined,\n session,\n channel: channel.channelType,\n ...(data.abortSignal !== undefined && { abortSignal: data.abortSignal }),\n });\n this.logger.debug(\n { conversation_id: data.conversationId },\n 'Message ready callback completed'\n );\n\n // Auto-send if callback returned a string\n if (typeof response === 'string') {\n if (response === '') {\n this.logger.warn(\n { conversation_id: data.conversationId },\n 'Callback returned empty string, skipping auto-send'\n );\n } else {\n try {\n await channel.sendResponse(data.conversationId, response);\n } catch (sendError) {\n this.logger.error(\n { err: sendError, conversation_id: data.conversationId },\n 'Failed to auto-send callback response'\n );\n }\n }\n }\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: data.conversationId },\n 'Message ready callback error'\n );\n }\n\n this.logger.debug({ conversation_id: data.conversationId }, 'Message handling completed');\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: data.conversationId },\n 'Message handling error'\n );\n }\n }\n\n /**\n * Register callback for when messages are ready to be processed.\n * Return a string to auto-send, or null/void for manual handling.\n */\n public onMessageReady(callback: MessageReadyCallback): void {\n this.messageReadyCallback = callback;\n }\n\n /**\n * Register callback for when user interrupts (voice channel)\n */\n public onInterrupt(callback: InterruptCallback): void {\n this.interruptCallback = callback;\n }\n\n /**\n * Register callback for when a conversation ends.\n *\n * The callback is triggered by channels when a conversation is closed\n * (e.g., SMS conversation status changed to CLOSED, or voice WebSocket\n * disconnected). The callback receives the full ConversationSession before\n * it is cleaned up.\n */\n public onConversationEnded(callback: ConversationEndedCallback): void {\n this.conversationEndedCallback = callback;\n }\n\n /**\n * Whether Conversation Orchestrator is configured.\n * Returns false in voice-only mode.\n *\n * @internal\n */\n public isOrchestratorEnabled(): boolean {\n return this.config.isOrchestratorEnabled();\n }\n\n /**\n * Get registered channel by type\n */\n public getChannel<T extends BaseChannel>(channelType: ChannelType): T | undefined {\n return this.channels.get(channelType) as T | undefined;\n }\n\n /**\n * Get configuration\n */\n public getConfig(): TACConfig {\n return this.config;\n }\n\n /**\n * Get memory client for advanced memory operations.\n * Returns null in voice-only mode.\n */\n public getMemoryClient(): MemoryClient | null {\n return this.memoryClient;\n }\n\n /**\n * Get the memory store ID resolved from the ConversationConfiguration at startup.\n * Returns undefined in voice-only mode.\n */\n public getMemoryStoreId(): string | undefined {\n return this.memoryStoreId;\n }\n\n /**\n * Get knowledge client for knowledge base operations.\n * Returns null in voice-only mode.\n */\n public getKnowledgeClient(): KnowledgeClient | null {\n return this.knowledgeClient;\n }\n\n /**\n * Get conversation client for advanced conversation operations.\n * Returns null in voice-only mode.\n */\n public getConversationClient(): ConversationClient | null {\n return this.conversationClient;\n }\n\n /**\n * Check if Conversation Intelligence processing is enabled\n *\n * @returns true if CI processor is initialized, false otherwise\n */\n public isCintelEnabled(): boolean {\n return this.cintelProcessor !== undefined;\n }\n\n /**\n * Process a Conversation Intelligence operator result webhook event\n *\n * @param payload - The raw webhook payload from CI\n * @returns Promise containing the processing result\n * @throws Error if CI processor is not initialized\n */\n public async processCintelEvent(payload: unknown): Promise<OperatorProcessingResult> {\n if (!this.cintelProcessor) {\n throw new Error(\n 'Conversation Intelligence processor is not initialized. ' +\n 'Ensure cintelConfigurationId is provided in TAC configuration.'\n );\n }\n return this.cintelProcessor.processEvent(payload);\n }\n\n /**\n * Retrieve memories from Memory API with automatic fallback to Conversations API\n *\n * @param session - Conversation session context\n * @param query - Optional semantic search query\n * @param conversationId - Passed through to `/Recall` as-is. Sending one\n * without a `query` makes Memory infer one from that conversation's history\n * — an expensive server-side step — so leave it unset when there is no\n * per-turn topic (e.g. `\"once\"` mode's cache-priming fetch).\n * @returns Promise containing TACMemoryResponse wrapper providing unified access to memory data.\n *\n * Attempts to retrieve from Memory API first:\n * - observations, summaries, and communications available\n * - communications include author name and type\n *\n * Falls back to Conversations API on error:\n * - observations and summaries are empty arrays\n * - communications have basic fields only (no author name/type)\n */\n public async retrieveMemory(\n session: ConversationSession,\n query?: string,\n conversationId?: string\n ): Promise<TACMemoryResponse> {\n if (!this.isOrchestratorEnabled()) {\n return new TACMemoryResponse([]);\n }\n\n try {\n // If profileId is missing, try to lookup profile using address\n if (!session.profileId) {\n // Check if authorInfo and address are available\n if (!session.authorInfo || !session.authorInfo.address) {\n throw new Error(\n 'profileId is required for memory retrieval but was not found in ' +\n 'conversation context. Additionally, authorInfo.address is not available ' +\n 'for profile lookup. Ensure either profileId or authorInfo.address is ' +\n 'provided when creating the ConversationSession.'\n );\n }\n\n // Determine identity type based on address format\n // Email addresses contain '@', phone numbers start with '+'\n const address = session.authorInfo.address;\n let identityType: 'email' | 'phone';\n if (address.includes('@')) {\n identityType = 'email';\n } else if (address.startsWith('+')) {\n identityType = 'phone';\n } else {\n throw new Error(\n `Unsupported authorInfo.address format '${maskAddress(address)}'. ` +\n \"Expected an email address containing '@' or a phone number starting with '+'.\"\n );\n }\n this.logger.debug(\n { identityType, address: maskAddress(address), channel: session.channel },\n 'profileId not found, attempting to lookup profile'\n );\n\n if (!this.memoryClient) {\n throw new Error('Memory client is not available');\n }\n\n // Lookup profile using appropriate identity type\n const lookupResponse = await this.memoryClient.lookupProfile(\n identityType,\n session.authorInfo.address\n );\n\n // Check if any profiles were found\n if (!lookupResponse.profiles || lookupResponse.profiles.length === 0) {\n throw new Error(\n `No profile found for ${identityType} ${maskAddress(session.authorInfo.address)}. ` +\n 'Profile lookup returned no results. Ensure the identity ' +\n 'is registered in the identity resolution system.'\n );\n }\n\n // Use the first profile ID\n session.profileId = lookupResponse.profiles[0];\n }\n\n if (!session.profileId) {\n throw new Error('Profile ID is required but was not resolved');\n }\n\n if (!this.memoryClient) {\n throw new Error('Memory client is not available');\n }\n\n const memoryResponse = await this.memoryClient.retrieveMemories(session.profileId, {\n conversationId,\n query,\n observationsLimit: this.config.memoryConfig.observationsLimit,\n summariesLimit: this.config.memoryConfig.summariesLimit,\n communicationsLimit: this.config.memoryConfig.communicationsLimit,\n relevanceThreshold: this.config.memoryConfig.relevanceThreshold,\n });\n return new TACMemoryResponse(memoryResponse);\n } catch (error) {\n this.logger.warn(\n { err: error },\n 'Failed to retrieve memory from Memory API, falling back to Conversations API'\n );\n\n try {\n if (!this.conversationClient) {\n throw new Error('Conversation client is not available');\n }\n const communications = await this.conversationClient.listCommunications(\n session.conversationId\n );\n\n return new TACMemoryResponse(communications);\n } catch (fallbackError) {\n this.logger.error({ err: fallbackError }, 'Failed to retrieve communications');\n throw fallbackError;\n }\n }\n }\n\n /**\n * Fetch profile information with traits\n *\n * @param profileId - Profile ID to fetch\n * @returns Promise containing profile response or undefined if not available\n */\n public async fetchProfile(profileId: string): Promise<ProfileResponse | undefined> {\n if (!profileId) {\n this.logger.warn('profile_id is required for profile fetching but was not provided');\n return undefined;\n }\n\n if (!this.memoryClient) {\n this.logger.warn('Memory client is not available (voice-only mode)');\n return undefined;\n }\n\n try {\n const traitGroups = this.config.memoryConfig.traitGroups;\n const profileResponse = await this.memoryClient.getProfile(profileId, traitGroups);\n return profileResponse;\n } catch (error) {\n this.logger.error({ err: error }, `Failed to fetch profile for ${profileId}`);\n return undefined;\n }\n }\n\n /**\n * Shutdown TAC and cleanup resources\n */\n public shutdown(): void {\n for (const channel of this.channels.values()) {\n this.logger.debug({ channel: channel.channelType }, 'Shutting down channel');\n channel.shutdown();\n }\n\n this.channels.clear();\n shutdownAnalytics().catch(() => {});\n this.logger.info('TAC shutdown complete');\n }\n}\n","import {\n ConversationSession,\n ChannelType,\n ConversationId,\n ConversationWebhookPayload,\n ProfileId,\n MemoryMode,\n MemoryModeSchema,\n isConversationId,\n isProfileId,\n} from '../types/index';\nimport { TACConfig } from '../lib/config';\nimport { ConversationClient } from '../clients/conversation';\nimport { Logger } from '../lib/logger';\nimport { trackEvent } from '../lib/analytics';\nimport type { TAC } from '../lib/tac';\nimport { TACMemoryResponse } from '../lib/tac-memory-response';\n\n/**\n * Base channel event callbacks\n */\nexport interface BaseChannelEvents {\n onConversationStarted?: (data: { session: ConversationSession }) => void;\n onConversationEnded?: (data: { session: ConversationSession }) => Promise<void> | void;\n onError?: (data: { error: Error; context?: Record<string, unknown> }) => void;\n}\n\n/**\n * Base channel options\n */\nexport interface BaseChannelOptions {\n /**\n * Memory retrieval mode for this channel. Default is \"never\".\n *\n * - \"never\": Memory is not automatically retrieved. Use the memory TAC tool or manually call `tac.retrieveMemory()` in callbacks for conditional retrieval.\n * - \"always\": Memory is automatically retrieved (using the message as query) for every inbound message and available in `onMessageReady` callback.\n * - \"once\": Memory is retrieved once at conversation start with no query (and no conversation id) and cached on the session. Subsequent messages reuse the cache until the conversation becomes INACTIVE.\n */\n memoryMode?: MemoryMode;\n\n /**\n * Maximum number of idempotency tokens to track for webhook deduplication.\n * Default is 10000. Must be a positive integer.\n */\n dedupCapacity?: number;\n}\n\n/**\n * Abstract base class for all channel implementations\n *\n * Provides common functionality for:\n * - Conversation lifecycle management and session tracking\n * - Webhook deduplication using Twilio idempotency tokens\n * - Event filtering to prevent cross-channel fanout\n * - Memory retrieval integration\n * - Error handling and logging\n *\n * Subclasses must implement channel-specific webhook processing and message sending.\n */\nexport abstract class BaseChannel {\n protected readonly tac: TAC;\n protected readonly config: TACConfig;\n protected readonly logger: Logger;\n protected readonly conversationClient: ConversationClient | null;\n protected readonly activeConversations: Map<ConversationId, ConversationSession>;\n protected readonly callbacks: BaseChannelEvents;\n protected readonly memoryMode: MemoryMode;\n private readonly processedWebhookTokens: Set<string>;\n private readonly maxTrackedTokens: number;\n\n constructor(tac: TAC, options?: BaseChannelOptions) {\n this.tac = tac;\n this.config = tac.getConfig();\n this.logger = tac.logger.child({ component: 'channel' });\n this.conversationClient = tac.getConversationClient();\n this.activeConversations = new Map();\n this.callbacks = {};\n\n // Validate memoryMode with runtime check for JS consumers\n const providedMode = options?.memoryMode;\n const modeToValidate = providedMode === undefined ? 'never' : providedMode;\n const parseResult = MemoryModeSchema.safeParse(modeToValidate);\n if (!parseResult.success) {\n throw new Error(\n `Invalid memoryMode: \"${modeToValidate}\". Must be \"always\", \"once\", or \"never\".`\n );\n }\n this.memoryMode = parseResult.data;\n\n // Validate and set deduplication capacity\n const capacity = options?.dedupCapacity ?? 10000;\n if (capacity < 1 || !Number.isInteger(capacity)) {\n throw new Error('dedupCapacity must be a positive integer');\n }\n this.maxTrackedTokens = capacity;\n this.processedWebhookTokens = new Set();\n }\n\n /**\n * Get the channel type (implemented by subclasses)\n */\n public abstract get channelType(): ChannelType;\n\n /**\n * Register event callbacks\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Generic event callback needs to accept any args\n public on(event: string, callback: (...args: any[]) => void): void {\n switch (event) {\n case 'conversationStarted':\n this.callbacks.onConversationStarted = callback;\n break;\n case 'conversationEnded':\n this.callbacks.onConversationEnded = callback;\n break;\n case 'error':\n this.callbacks.onError = callback;\n break;\n }\n }\n\n /**\n * Process incoming webhook data (implemented by subclasses)\n */\n public abstract processWebhook(payload: unknown): Promise<void>;\n\n /**\n * Send a response back to the user (implemented by subclasses)\n */\n public abstract sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void>;\n\n /**\n * Start a new conversation session\n */\n protected startConversation(\n conversationId: ConversationId,\n profileId?: ProfileId,\n serviceId?: string\n ): ConversationSession {\n if (this.activeConversations.has(conversationId)) {\n this.logger.debug(\n {\n conversation_id: conversationId,\n profile_id: this.activeConversations.get(conversationId)?.profileId,\n service_id: this.activeConversations.get(conversationId)?.serviceId,\n },\n 'Conversation already active'\n );\n return this.activeConversations.get(conversationId)!;\n }\n\n const session: ConversationSession = {\n conversationId: conversationId,\n profileId: profileId,\n serviceId: serviceId,\n channel: this.channelType,\n startedAt: new Date(),\n metadata: {},\n };\n\n this.activeConversations.set(conversationId, session);\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n profile_id: profileId,\n service_id: serviceId,\n channel: this.channelType,\n },\n 'Conversation started'\n );\n\n if (this.callbacks.onConversationStarted) {\n this.callbacks.onConversationStarted({ session });\n }\n\n trackEvent('Conversation Started', {\n account_sid: this.config.accountSid,\n channel: this.channelType,\n conversation_id: conversationId,\n has_profile_id: !!profileId,\n });\n\n return session;\n }\n\n /**\n * End a conversation session.\n *\n * Triggers the onConversationEnded callback BEFORE removing the session,\n * so the callback receives the full ConversationSession data.\n * Errors in the callback do not prevent session cleanup.\n */\n protected async endConversation(conversationId: ConversationId): Promise<void> {\n const session = this.activeConversations.get(conversationId);\n\n if (session) {\n // Trigger callback BEFORE deleting the session\n if (this.callbacks.onConversationEnded) {\n try {\n await this.callbacks.onConversationEnded({ session });\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: conversationId },\n 'Error in conversation ended callback'\n );\n }\n }\n\n trackEvent('Conversation Ended', {\n account_sid: this.config.accountSid,\n channel: this.channelType,\n conversation_id: conversationId,\n duration_ms: Date.now() - session.startedAt.getTime(),\n });\n\n this.activeConversations.delete(conversationId);\n this.logger.debug(\n {\n conversation_id: conversationId,\n channel: this.channelType,\n service_id: session.serviceId,\n },\n 'Conversation ended'\n );\n } else {\n this.logger.debug(\n { conversation_id: conversationId, channel: this.channelType },\n 'Conversation end requested but no active session found'\n );\n }\n }\n\n /**\n * Get an active conversation session\n */\n public getConversationSession(conversationId: ConversationId): ConversationSession | undefined {\n return this.activeConversations.get(conversationId);\n }\n\n /**\n * Check if a conversation is active\n */\n public isConversationActive(conversationId: ConversationId): boolean {\n return this.activeConversations.has(conversationId);\n }\n\n /**\n * Handle errors with proper context\n */\n protected handleError(error: Error, context?: Record<string, unknown>): void {\n this.logger.error({ err: error }, 'Channel error');\n\n if (this.callbacks.onError) {\n if (context) {\n this.callbacks.onError({ error, context });\n } else {\n this.callbacks.onError({ error });\n }\n }\n }\n\n /**\n * Check if a webhook has already been processed using Twilio's idempotency token.\n * Uses a sliding window with fixed capacity to track tokens (FIFO eviction).\n *\n * This is intentionally a single synchronous check-and-record to prevent race conditions\n * where a duplicate arrives while the first request is still awaiting async work.\n */\n protected isDuplicateWebhook(idempotencyToken: string): boolean {\n if (this.processedWebhookTokens.has(idempotencyToken)) {\n return true;\n }\n\n if (this.processedWebhookTokens.size >= this.maxTrackedTokens) {\n const oldest = this.processedWebhookTokens.values().next().value!;\n this.processedWebhookTokens.delete(oldest);\n }\n\n this.processedWebhookTokens.add(idempotencyToken);\n return false;\n }\n\n /**\n * Remove an idempotency token from the deduplication cache.\n * Used when webhook processing fails and retries should not be blocked.\n */\n protected removeWebhookToken(idempotencyToken: string): void {\n this.processedWebhookTokens.delete(idempotencyToken);\n }\n\n /**\n * Self-filtering: check if webhook event belongs to this channel.\n *\n * - COMMUNICATION_CREATED: require author.channel matches this channel type\n * - CONVERSATION_UPDATED: only process if conversation is tracked locally\n * - Other events: pass through\n */\n protected isEventForThisChannel(webhookData: ConversationWebhookPayload): boolean {\n const eventType = webhookData.eventType;\n const authorChannel = webhookData.data?.author?.channel;\n\n // COMMUNICATION_CREATED: require author.channel for safe filtering\n // Reject events without channel to prevent fanout crosstalk\n if (eventType === 'COMMUNICATION_CREATED') {\n if (!authorChannel) {\n return false;\n }\n return authorChannel === this.channelType.toUpperCase();\n }\n\n // CONVERSATION_UPDATED: only process if this channel tracks the conversation\n if (eventType === 'CONVERSATION_UPDATED') {\n const conversationId = this.extractConversationId(webhookData);\n if (conversationId && !this.activeConversations.has(conversationId)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Validate webhook payload (override in subclasses for specific validation)\n */\n protected validateWebhookPayload(payload: unknown): boolean {\n return payload !== null && payload !== undefined;\n }\n\n /**\n * Preprocess webhook before handling event-specific logic.\n * Handles deduplication, validation, filtering, and data extraction.\n *\n * @param payload - Raw webhook payload from Twilio\n * @param idempotencyToken - Optional idempotency token for deduplication\n * @returns Preprocessed webhook data, or null if webhook should be skipped\n */\n protected preprocessWebhook(\n payload: unknown,\n idempotencyToken: string | undefined\n ): {\n webhookData: ConversationWebhookPayload;\n eventType: string;\n conversationId: string | undefined;\n } | null {\n this.logger.debug({ operation: 'webhook_processing' }, 'Processing webhook');\n\n if (idempotencyToken && this.isDuplicateWebhook(idempotencyToken)) {\n this.logger.debug({ idempotency_token: idempotencyToken }, 'Skipping duplicate webhook');\n return null;\n }\n\n if (!this.validateWebhookPayload(payload)) {\n throw new Error('Invalid webhook payload');\n }\n\n const webhookData = payload as ConversationWebhookPayload;\n const eventType = webhookData.eventType;\n const conversationId = webhookData.data?.conversationId || webhookData.data?.id;\n\n // Self-filter: ignore events meant for other channel types\n if (!this.isEventForThisChannel(webhookData)) {\n this.logger.debug(\n { event_type: eventType, channel: this.channelType, conversation_id: conversationId },\n 'Ignoring event for different channel type'\n );\n return null;\n }\n\n return { webhookData, eventType, conversationId };\n }\n\n /**\n * Extract conversation ID from webhook payload with type validation.\n *\n * Extracts conversationId from webhookData.data?.conversationId || webhookData.data?.id,\n * validates the value is a non-empty string, and ensures it passes isConversationId check.\n *\n * This prevents invalid IDs from causing downstream issues like incorrect Map key\n * matching in CONVERSATION_UPDATED self-filtering or propagating malformed IDs.\n */\n protected extractConversationId(payload: unknown): ConversationId | null {\n if (!payload || typeof payload !== 'object') {\n return null;\n }\n\n const webhookData = payload as ConversationWebhookPayload;\n const conversationId = webhookData.data?.conversationId || webhookData.data?.id;\n\n // Validate type and format before casting to ConversationId\n if (conversationId && typeof conversationId === 'string' && isConversationId(conversationId)) {\n return conversationId;\n }\n\n return null;\n }\n\n /**\n * Extract profile ID from webhook payload with type validation.\n *\n * Extracts profileId from webhookData.data?.profileId,\n * validates the value is a non-empty string, and ensures it passes isProfileId check.\n *\n * This prevents invalid IDs from propagating downstream and ensures consistent\n * validation across all channel types.\n */\n protected extractProfileId(payload: unknown): ProfileId | null {\n if (!payload || typeof payload !== 'object') {\n return null;\n }\n\n const webhookData = payload as ConversationWebhookPayload;\n const profileId = webhookData.data?.profileId;\n\n // Validate type and format before casting to ProfileId\n if (profileId && typeof profileId === 'string' && isProfileId(profileId)) {\n return profileId;\n }\n\n return null;\n }\n\n /**\n * Retrieve memory according to the channel's memoryMode.\n *\n * This method handles the common logic for memory retrieval across all channels,\n * including error handling and debug logging.\n *\n * Modes:\n * - \"always\": Fetch with the provided query on every message.\n * - \"once\": Fetch once with neither a query nor a conversation id (skipping\n * query expansion) and cache the result on the session. Subsequent calls\n * reuse the cache until it is invalidated on the INACTIVE transition.\n * - \"never\": Skip retrieval.\n *\n * Memory retrieval failures are logged and swallowed so message processing\n * continues without memory context.\n */\n protected async retrieveMemoryIfEnabled(\n session: ConversationSession,\n query?: string\n ): Promise<TACMemoryResponse | undefined> {\n // \"never\" and any unexpected value: no automatic retrieval\n if (this.memoryMode !== 'always' && this.memoryMode !== 'once') {\n return undefined;\n }\n\n // \"once\" mode reuses cached memory across messages.\n if (this.memoryMode === 'once' && session.cachedMemory !== undefined) {\n this.logger.debug({ conversation_id: session.conversationId }, 'Reusing cached memory');\n return session.cachedMemory;\n }\n\n try {\n // \"always\" sends query + conversation id so Memory ranks by relevance.\n // \"once\" sends neither: with no query, a conversation id only buys\n // Memory's expensive server-side query expansion.\n const isAlways = this.memoryMode === 'always';\n const memory = await this.tac.retrieveMemory(\n session,\n isAlways ? query : undefined,\n isAlways ? session.conversationId : undefined\n );\n if (this.memoryMode === 'once') {\n session.cachedMemory = memory;\n }\n this.logger.debug(\n { conversation_id: session.conversationId, memory_mode: this.memoryMode },\n 'Memory retrieved'\n );\n return memory;\n } catch (error) {\n this.logger.warn(\n { err: error, conversation_id: session.conversationId },\n 'Failed to retrieve memory, continuing without memory context'\n );\n // Continue without memory rather than failing entire message processing\n return undefined;\n }\n }\n\n /**\n * Invalidate cached memory for \"once\" mode when a conversation becomes\n * INACTIVE. Conversation Orchestrator updates memory on the INACTIVE\n * transition, so the next message re-fetches fresh memory. No-op for other\n * memory modes.\n */\n protected invalidateCachedMemory(conversationId: ConversationId): void {\n if (this.memoryMode !== 'once') {\n return;\n }\n\n const session = this.activeConversations.get(conversationId);\n if (session?.cachedMemory !== undefined) {\n session.cachedMemory = undefined;\n this.logger.debug(\n { conversation_id: conversationId },\n 'Invalidated cached memory on INACTIVE status'\n );\n }\n }\n\n /**\n * Cleanup resources when shutting down\n */\n public shutdown(): void {\n this.activeConversations.clear();\n delete this.callbacks.onConversationStarted;\n delete this.callbacks.onConversationEnded;\n delete this.callbacks.onError;\n }\n}\n","import {\n ActionChannelSettings,\n ConversationAddress,\n ConversationId,\n ConversationParticipant,\n ConversationWebhookPayload,\n InitiateConversationResult,\n ProfileId,\n SendMessageActionRequest,\n isConversationId,\n} from '../types/index';\nimport axios from 'axios';\nimport { BaseChannel, BaseChannelEvents, BaseChannelOptions } from './base';\nimport { ConversationClient } from '../clients/conversation';\nimport type { TAC } from '../lib/tac';\nimport { trackEvent } from '../lib/analytics';\nimport { maskAddress } from '../util/log-redaction';\n\n/**\n * Participant types that represent TAC itself at TAC's (channel, address).\n *\n * `AI_AGENT` is the canonical type; `AGENT` is the legacy Conversation\n * Orchestrator form. A participant typed either way at TAC's address is\n * recognized as TAC and not overwritten; anything else (HUMAN_AGENT,\n * CUSTOMER, …) is someone else's assignment.\n */\nconst AGENT_TYPES = new Set<string>(['AGENT', 'AI_AGENT']);\n\n/**\n * Memory identifier type to use when looking up / creating a profile for a\n * channel's customer address. Channels absent from this map skip profile\n * resolution during participant reconciliation.\n */\nconst CHANNEL_IDENTITY_TYPES: Record<string, string> = {\n SMS: 'phone',\n VOICE: 'phone',\n RCS: 'rcs',\n WHATSAPP: 'whatsapp',\n};\n\n/**\n * Messaging channel configuration options.\n * Alias for BaseChannelOptions that can be extended by specific channel implementations.\n */\nexport type MessagingChannelConfig = BaseChannelOptions;\n\n/**\n * Messaging channel event callbacks extending base callbacks\n */\nexport interface MessagingChannelEvents extends BaseChannelEvents {\n onMessageReceived?: (data: {\n conversationId: ConversationId;\n profileId: ProfileId | undefined;\n message: string;\n author: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Memory structure is dynamic and defined by user\n userMemory: any;\n }) => void;\n}\n\n/**\n * Abstract Messaging Channel base class for SMS and Chat channels\n *\n * Provides shared webhook processing logic for messaging channels\n * (SMS and Chat) that use the Conversations Service webhooks.\n *\n * Subclasses must implement:\n * - `isDefaultAgentAddress`: fast-path check for the channel's default agent address\n * - `getAgentAddress`: return the agent's `ConversationAddress` for a conversation\n * - `sendResponse`: send messages back through the channel\n *\n * Subclass flags:\n * - `reconcileCustomerType`: if `true` (default), reconciliation will also\n * promote a channel-matching UNKNOWN participant (not owning the agent\n * address) to CUSTOMER. Set `false` for channels where the customer is\n * identified author-driven (e.g. chat).\n */\nexport abstract class MessagingChannel extends BaseChannel {\n protected override readonly conversationClient: ConversationClient;\n protected readonly messagingCallbacks: MessagingChannelEvents;\n\n /**\n * Controls whether reconciliation promotes an UNKNOWN customer-side\n * participant to CUSTOMER. Subclasses override to opt out (e.g. chat).\n */\n protected reconcileCustomerType: boolean = true;\n\n constructor(tac: TAC, config?: MessagingChannelConfig) {\n super(tac, config);\n if (!tac.isOrchestratorEnabled()) {\n throw new Error(\n 'Messaging channels require conversationConfigurationId to be configured. ' +\n 'Voice-only mode does not support SMS or Chat channels.'\n );\n }\n // Safe: orchestrator is enabled so conversationClient is guaranteed non-null\n this.conversationClient = tac.getConversationClient() as ConversationClient;\n this.messagingCallbacks = {};\n }\n\n /**\n * Fast-path check: is the author address this channel's default agent address?\n * (e.g., config.phoneNumber for SMS, agentAddress for Chat)\n */\n protected abstract isDefaultAgentAddress(authorAddress: string): boolean;\n\n /**\n * Return the agent-side ConversationAddress for this conversation.\n *\n * Used by `reconcileParticipants` to identify which participant (by channel\n * + address) represents the agent. May read from session state (e.g. chat's\n * per-conversation channelId) to build the address.\n */\n protected abstract getAgentAddress(conversationId: ConversationId): ConversationAddress;\n\n /**\n * Report a delivered response.\n *\n * Each channel calls this from its own `sendResponse` rather than the base\n * wrapping the call: `sendResponse` is the public extension point, so making\n * it a template method would break subclasses defined outside this package.\n */\n protected trackResponseSent(conversationId: ConversationId): void {\n trackEvent('Response Sent', {\n account_sid: this.config.accountSid,\n channel: this.channelType,\n conversation_id: conversationId,\n response_type: 'full',\n });\n }\n\n /**\n * Check if a message is from the bot itself (2-tier).\n *\n * 1. Default agent address (stateless, no API call)\n * 2. API fallback via listParticipants (cross-process / multi-worker)\n */\n private async isOwnMessage(\n authorAddress: string,\n conversationId: ConversationId,\n authorParticipantId: string | undefined\n ): Promise<boolean> {\n if (this.isDefaultAgentAddress(authorAddress)) return true;\n\n if (authorParticipantId) {\n try {\n const participants = await this.conversationClient.listParticipants(conversationId);\n const authorParticipant = participants.find(p => p.id === authorParticipantId);\n if (authorParticipant) {\n if (authorParticipant.type === undefined) {\n this.logger.warn(\n { conversation_id: conversationId, participant_id: authorParticipantId },\n 'Participant type is undefined — cannot determine if this is an agent message'\n );\n }\n if (authorParticipant.type && AGENT_TYPES.has(authorParticipant.type)) {\n return true;\n }\n }\n } catch (error) {\n this.logger.warn(\n { err: error, conversation_id: conversationId, participant_id: authorParticipantId },\n 'Failed to look up participant type for self-message check; falling through'\n );\n }\n }\n\n return false;\n }\n\n /**\n * Register event callbacks (override for messaging-specific events)\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Generic event callback needs to accept any args\n public override on(event: string, callback: (...args: any[]) => void): void {\n if (event === 'messageReceived') {\n this.messagingCallbacks.onMessageReceived = callback;\n } else {\n // Delegate to parent for base events\n super.on(event, callback);\n }\n }\n\n /**\n * Process messaging channel webhook from Conversation Orchestrator\n */\n public async processWebhook(payload: unknown, idempotencyToken?: string): Promise<void> {\n try {\n const result = this.preprocessWebhook(payload, idempotencyToken);\n if (!result) {\n return;\n }\n\n const { webhookData, eventType, conversationId } = result;\n\n switch (eventType) {\n case 'CONVERSATION_CREATED':\n this.logger.debug(\n { conversation_id: conversationId, profile_id: webhookData.data?.profileId },\n 'Handling CONVERSATION_CREATED'\n );\n this.handleConversationCreated(webhookData);\n break;\n\n case 'COMMUNICATION_CREATED':\n this.logger.debug({ conversation_id: conversationId }, 'Handling COMMUNICATION_CREATED');\n await this.handleCommunicationCreated(webhookData);\n break;\n\n case 'CONVERSATION_UPDATED':\n this.logger.debug(\n { conversation_id: conversationId, status: webhookData.data?.status },\n 'Handling CONVERSATION_UPDATED'\n );\n await this.handleConversationUpdated(webhookData);\n break;\n\n default:\n this.logger.warn(\n {\n event_type: eventType,\n raw_event_type: webhookData.eventType,\n conversation_id: conversationId,\n },\n 'Unhandled event type - this event will be ignored'\n );\n }\n\n this.logger.debug({ event_type: eventType }, 'Webhook processing completed');\n } catch (error) {\n // Remove the token so retries are not blocked\n if (idempotencyToken) {\n this.removeWebhookToken(idempotencyToken);\n }\n this.handleError(error instanceof Error ? error : new Error(String(error)), { payload });\n }\n }\n\n /**\n * Handle conversation creation event\n */\n private handleConversationCreated(payload: ConversationWebhookPayload): void {\n const conversationId = this.extractConversationId(payload);\n const profileId = this.extractProfileId(payload);\n\n if (!conversationId) {\n this.logger.warn(\n { operation: 'handle_conversation_created' },\n 'Missing conversation ID in conversation.created event'\n );\n throw new Error('Missing conversation ID in conversation.created event');\n }\n\n this.startConversation(conversationId, profileId ?? undefined, payload.data?.serviceId);\n }\n\n /**\n * Handle new communication event (incoming message)\n */\n private async handleCommunicationCreated(payload: ConversationWebhookPayload): Promise<void> {\n const conversationId = this.extractConversationId(payload);\n const profileId = this.extractProfileId(payload);\n // Extract message text from data.content.text\n const message = payload.data?.content?.text?.trim();\n // Author is in data.author.address\n const author = payload.data?.author?.address || 'unknown';\n\n this.logger.info(\n {\n conversation_id: conversationId,\n profile_id: profileId,\n author: maskAddress(author),\n message_length: message?.length,\n operation: 'handle_communication_created',\n },\n 'Handling communication.created'\n );\n\n if (!conversationId) {\n this.logger.warn(\n { operation: 'handle_communication_created' },\n 'Missing conversation ID in communication.created event'\n );\n throw new Error('Missing conversation ID in communication.created event');\n }\n\n if (!message) {\n this.logger.info({ conversation_id: conversationId }, 'Ignoring empty message');\n return;\n }\n\n // Per-conversation communication ID dedup stored in the in-memory\n // ConversationSession metadata. This only prevents duplicate processing\n // within the current process/session lifetime; it does not deduplicate\n // across horizontally-scaled instances or after a restart.\n const communicationId = payload.data?.id;\n if (communicationId) {\n const session = this.getConversationSession(conversationId);\n if (session?.metadata?.lastCommunicationId === communicationId) {\n this.logger.debug(\n { conversation_id: conversationId, communication_id: communicationId },\n 'Skipping already-processed communication'\n );\n return;\n }\n }\n\n // Filter out messages from the bot itself\n if (await this.isOwnMessage(author, conversationId, payload.data?.author?.participantId)) {\n this.logger.info(\n {\n conversation_id: conversationId,\n author_address: maskAddress(author),\n },\n 'Ignoring message from AI agent'\n );\n return;\n }\n\n // Initialize conversation if not already active\n if (!this.isConversationActive(conversationId)) {\n this.logger.debug({ conversation_id: conversationId }, 'Starting new conversation');\n this.startConversation(conversationId, profileId ?? undefined, payload.data?.serviceId);\n } else if (payload.data?.serviceId) {\n const session = this.getConversationSession(conversationId);\n if (session && session.serviceId !== payload.data.serviceId) {\n this.logger.debug(\n {\n conversation_id: conversationId,\n old_service_id: session.serviceId,\n new_service_id: payload.data.serviceId,\n },\n 'Updating conversation configuration ID from communication.created'\n );\n session.serviceId = payload.data.serviceId;\n }\n }\n\n // Get session and update with author info for profile lookup\n const session = this.getConversationSession(conversationId);\n if (session) {\n session.authorInfo = {\n address: author,\n participantId: payload.data?.author?.participantId,\n };\n\n // Store channelId (Chat Channel SID) in session metadata for reply sending\n if (payload.data?.channelId) {\n if (!session.metadata) {\n session.metadata = {};\n }\n session.metadata.channelId = payload.data.channelId;\n this.logger.debug(\n { conversation_id: conversationId, channel_id: payload.data.channelId },\n 'Stored channelId in session metadata'\n );\n }\n\n // Track communication ID for cross-process dedup\n if (communicationId) {\n if (!session.metadata) {\n session.metadata = {};\n }\n session.metadata.lastCommunicationId = communicationId;\n }\n\n // Reconcile participant types pre-LLM so v1-bridge's UNKNOWN gets\n // promoted, and to stash both participant ids on the session for\n // sendResponse. Reconcile failure means the reply would fail too —\n // skip the callback so the LLM doesn't waste a turn on an\n // un-replyable conversation.\n //\n // Gate on `aiAgentInfo` (persistent across turns) — `authorInfo` is\n // overwritten from every webhook so it's not a reliable \"already\n // reconciled\" signal.\n if (!session.aiAgentInfo) {\n const resolved = await this.reconcileParticipants(conversationId);\n if (!resolved) {\n // Surface via handleError (logs at error level AND fires the app's\n // onError callback) rather than a bare warn — otherwise the dropped\n // inbound is invisible to the app and can't be observed or retried.\n // Set a stable error.name and error_code so consumers can classify\n // this condition programmatically without string-matching the message.\n const error = new Error(\n `Participant reconciliation failed for conversation ${conversationId}; ` +\n 'inbound message dropped because no sendable participants could be resolved.'\n );\n error.name = 'ParticipantReconciliationError';\n this.handleError(error, {\n conversation_id: conversationId,\n channel: this.channelType,\n dropped_inbound: true,\n error_code: 'participant_reconciliation_failed',\n });\n return;\n }\n\n const [agentParticipant, customerParticipant] = resolved;\n const agentAddress = this.getAgentAddress(conversationId);\n session.aiAgentInfo = {\n address: agentAddress.address,\n participantId: agentParticipant.id,\n };\n // When reconcile resolved a customer (SMS path — chat disables customer\n // reconciliation and uses the authorInfo captured from the webhook\n // above), use its authoritative participant id and lift any resolved\n // profile.\n if (customerParticipant && session.authorInfo) {\n session.authorInfo.participantId = customerParticipant.id;\n if (customerParticipant.profileId && !session.profileId) {\n session.profileId = customerParticipant.profileId;\n }\n }\n }\n }\n\n // Retrieve user memory if enabled via memoryMode\n const userMemory = session ? await this.retrieveMemoryIfEnabled(session, message) : undefined;\n\n // Invoke message received callback with memory context\n if (this.messagingCallbacks.onMessageReceived) {\n this.logger.debug({ conversation_id: conversationId }, 'Invoking message received callback');\n this.messagingCallbacks.onMessageReceived({\n conversationId,\n profileId: (session?.profileId as ProfileId | undefined) ?? profileId ?? undefined,\n message,\n author,\n userMemory,\n });\n }\n\n trackEvent('Message Received', {\n account_sid: this.config.accountSid,\n channel: this.channelType,\n conversation_id: conversationId,\n });\n }\n\n /**\n * Handle conversation updated event\n */\n private async handleConversationUpdated(payload: ConversationWebhookPayload): Promise<void> {\n const conversationId = this.extractConversationId(payload);\n\n if (!conversationId) {\n throw new Error('Missing conversation ID in conversation.updated event');\n }\n\n // Check if conversation is closed\n if (payload.data?.status === 'CLOSED') {\n this.logger.debug(\n { conversation_id: conversationId, status: payload.data.status },\n 'Conversation closed, cleaning up'\n );\n await this.endConversation(conversationId);\n } else if (payload.data?.status === 'INACTIVE') {\n // Invalidate cached memory (\"once\" mode) when the conversation becomes\n // inactive. Memory is updated by Conversation Orchestrator on the\n // INACTIVE transition, so the next message re-fetches fresh memory.\n this.invalidateCachedMemory(conversationId);\n }\n }\n\n /**\n * Validate messaging channel webhook payload structure\n */\n protected override validateWebhookPayload(payload: unknown): boolean {\n if (!super.validateWebhookPayload(payload)) {\n return false;\n }\n\n const webhookData = payload as ConversationWebhookPayload;\n return (\n typeof webhookData === 'object' &&\n typeof webhookData.eventType === 'string' &&\n webhookData.eventType.length > 0\n );\n }\n\n /**\n * Reconcile Conversation Orchestrator's participants to the types TAC\n * needs for sending.\n *\n * v1-bridge capture can leave TAC's agent participant as `UNKNOWN` (wrong\n * type at our address), or omit it entirely (customer-only conversation).\n * This pass fixes those cases; it refuses to rewrite anything else at our\n * address. Decision matrix:\n *\n * | Agent side | Customer side | Action |\n * |----------------------|---------------------|-------------------------------|\n * | AGENT / AI_AGENT | CUSTOMER | Use as-is (no profile work). |\n * | AGENT / AI_AGENT | UNKNOWN, no CUST | Resolve profile, PUT → CUST. |\n * | UNKNOWN at our addr | CUSTOMER | PUT agent → AI_AGENT. |\n * | UNKNOWN at our addr | UNKNOWN, no CUST | PUT agent; resolve, PUT CUST. |\n * | other at our addr | any | Return null (log ERROR). |\n * | none at our addr | CUSTOMER or UNKNOWN | POST AI_AGENT, then proceed. |\n * | any | no resolvable cust | Return null (caller WARNs). |\n *\n * TAC recognizes both `AGENT` and `AI_AGENT` at its address as itself.\n * `HUMAN_AGENT` is NOT treated as TAC (a real human is a separate\n * participant — TAC must not speak on their behalf); it falls into the\n * \"other at our addr\" row and causes the reconcile to bail.\n *\n * Customer-side reconciliation is gated by `reconcileCustomerType`. Chat\n * sets it to `false` because chat identifies the customer author-driven\n * (via `session.authorInfo.participantId`), so promoting some other\n * `UNKNOWN` CHAT participant could pick the wrong recipient.\n *\n * @returns `[agent, customerOrNull]` on success. `customer` is `null` when\n * `reconcileCustomerType` is `false`. `null` overall when either the agent\n * or the customer cannot be resolved — the caller treats `null` as a hard\n * stop and skips the message-ready callback.\n */\n protected async reconcileParticipants(\n conversationId: ConversationId\n ): Promise<[ConversationParticipant, ConversationParticipant | null] | null> {\n const agentAddress = this.getAgentAddress(conversationId);\n\n let participants: ConversationParticipant[];\n try {\n participants = await this.conversationClient.listParticipants(conversationId);\n } catch (error) {\n this.logger.error(\n { err: error, conversation_id: conversationId },\n 'Failed to list participants for reconciliation'\n );\n return null;\n }\n\n const channel = agentAddress.channel;\n\n const ownsAgentAddress = (p: ConversationParticipant): boolean =>\n Array.isArray(p.addresses) &&\n p.addresses.some(a => a.channel === channel && a.address === agentAddress.address);\n\n const matchesChannel = (p: ConversationParticipant): boolean =>\n Array.isArray(p.addresses) && p.addresses.some(a => a.channel === channel);\n\n let agentCandidate = participants.find(ownsAgentAddress);\n if (!agentCandidate) {\n const created = await this.addAgentParticipant(conversationId, agentAddress);\n if (!created) return null;\n agentCandidate = created;\n } else if (agentCandidate.type === 'UNKNOWN') {\n // Only promote UNKNOWN — an already-typed participant at TAC's address\n // that isn't AGENT/AI_AGENT (e.g., CUSTOMER, HUMAN_AGENT) is someone\n // else's assignment and must not be overwritten.\n const promoted = await this.promoteParticipant(conversationId, agentCandidate, 'AI_AGENT');\n if (!promoted) return null;\n agentCandidate = promoted;\n } else if (!agentCandidate.type || !AGENT_TYPES.has(agentCandidate.type)) {\n this.logger.error(\n {\n conversation_id: conversationId,\n participant_id: agentCandidate.id,\n participant_type: agentCandidate.type,\n },\n \"Participant at TAC's address has a conflicting type; refusing to overwrite. \" +\n 'Check Conversation Orchestrator participant state — a non-agent participant is holding ' +\n \"TAC's (channel, address).\"\n );\n return null;\n }\n\n if (!this.reconcileCustomerType) {\n return [agentCandidate, null];\n }\n\n const customer = participants.find(\n p => p.type === 'CUSTOMER' && matchesChannel(p) && !ownsAgentAddress(p)\n );\n if (customer) {\n return [agentCandidate, customer];\n }\n\n const customerUnknown = participants.find(\n p => p.type === 'UNKNOWN' && matchesChannel(p) && !ownsAgentAddress(p)\n );\n if (customerUnknown) {\n const profileId = await this.resolveCustomerProfile(customerUnknown, channel);\n const promotedCustomer = await this.promoteParticipant(\n conversationId,\n customerUnknown,\n 'CUSTOMER',\n profileId\n );\n if (promotedCustomer) {\n return [agentCandidate, promotedCustomer];\n }\n }\n\n this.logger.warn(\n { conversation_id: conversationId, channel },\n 'No customer participant resolvable; skipping webhook'\n );\n return null;\n }\n\n /**\n * Find or mint a Conversation Memory profile for a customer being promoted from UNKNOWN.\n *\n * Only resolves for phone-based channels (SMS, VOICE, RCS, WHATSAPP). Looks\n * up by the channel's identifier type (`phone` for SMS/VOICE, `rcs` for\n * RCS, `whatsapp` for WHATSAPP) first; on miss, creates a new profile\n * using the configured phone trait group/field. Returns undefined on any\n * failure — the caller still promotes the participant, just without a\n * `profileId` attached.\n */\n private async resolveCustomerProfile(\n customer: ConversationParticipant,\n channel: string\n ): Promise<string | undefined> {\n const identityType = CHANNEL_IDENTITY_TYPES[channel];\n if (!identityType) return undefined;\n\n const memoryClient = this.tac.getMemoryClient();\n if (!memoryClient || !this.tac.getMemoryStoreId()) return undefined;\n\n const phoneAddress = Array.isArray(customer.addresses)\n ? (customer.addresses.find(a => a.channel === channel && !!a.address)?.address ?? undefined)\n : undefined;\n if (!phoneAddress) return undefined;\n\n try {\n const lookup = await memoryClient.lookupProfile(identityType, phoneAddress);\n if (lookup.profiles && lookup.profiles.length > 0) {\n return lookup.profiles[0];\n }\n } catch (error) {\n this.logger.warn(\n { err: error, conversation_id: customer.conversationId },\n 'Profile lookup failed during reconciliation; falling back to create'\n );\n }\n\n const memoryConfig = this.config.memoryConfig;\n const traitGroup = memoryConfig.phoneTraitGroup;\n const traitField = memoryConfig.phoneTraitField;\n\n try {\n return await memoryClient.createProfile({\n [traitGroup]: { [traitField]: phoneAddress },\n });\n } catch (error) {\n this.logger.warn(\n { err: error, conversation_id: customer.conversationId },\n 'Profile creation failed during reconciliation; promoting without profile'\n );\n return undefined;\n }\n }\n\n /**\n * PUT a participant to `newType`.\n *\n * Conversation Orchestrator's PUT is a full-resource replacement, so we\n * pass the existing `name` and `addresses` back unchanged to avoid wiping\n * them. `profileId` defaults to the participant's current value; pass a\n * non-undefined override to attach a newly resolved profile during CUSTOMER\n * reconciliation.\n *\n * Returns undefined on any error (including 409). A 409 from Conversation\n * Orchestrator here means the promotion is structurally blocked — stop and\n * surface it; don't retry.\n */\n private async promoteParticipant(\n conversationId: ConversationId,\n participant: ConversationParticipant,\n newType: 'CUSTOMER' | 'AI_AGENT' | 'HUMAN_AGENT' | 'AGENT',\n profileId?: string\n ): Promise<ConversationParticipant | undefined> {\n const effectiveProfileId = profileId !== undefined ? profileId : participant.profileId;\n const updateOptions: { name?: string; profileId?: string } = {};\n if (participant.name !== undefined) updateOptions.name = participant.name;\n if (effectiveProfileId !== null && effectiveProfileId !== undefined) {\n updateOptions.profileId = effectiveProfileId;\n }\n\n try {\n const updated = await this.conversationClient.updateParticipant(\n conversationId,\n participant.id,\n newType,\n participant.addresses,\n updateOptions\n );\n this.logger.debug(\n {\n conversation_id: conversationId,\n participant_id: participant.id,\n from_type: participant.type,\n to_type: newType,\n },\n 'Promoted participant'\n );\n return updated;\n } catch (error) {\n if (this.isConflictError(error)) {\n this.logger.warn(\n {\n conversation_id: conversationId,\n participant_id: participant.id,\n target_type: newType,\n conflicting_resource_id: this.extractConflictingResourceId(error),\n },\n 'Conversation Orchestrator returned 409 on participant promotion; skipping — ' +\n 'likely a conflicting conversation or grouping constraint. Check ' +\n 'Conversation Orchestrator for duplicate active conversations.'\n );\n return undefined;\n }\n this.logger.error(\n {\n err: error,\n conversation_id: conversationId,\n participant_id: participant.id,\n target_type: newType,\n },\n 'Failed to promote participant'\n );\n return undefined;\n }\n }\n\n /**\n * POST an `AI_AGENT` participant owning `agentAddress`.\n *\n * Returns undefined on any error (including 409). A 409 here means the\n * address is already owned or the conversation's participant set can't\n * accept a new AI_AGENT — stop and surface it; don't retry.\n */\n private async addAgentParticipant(\n conversationId: ConversationId,\n agentAddress: ConversationAddress\n ): Promise<ConversationParticipant | undefined> {\n try {\n const created = await this.conversationClient.addParticipant(\n conversationId,\n [agentAddress],\n 'AI_AGENT'\n );\n this.logger.debug(\n { conversation_id: conversationId, participant_id: created.id },\n 'Added AI_AGENT participant'\n );\n return created;\n } catch (error) {\n if (this.isConflictError(error)) {\n this.logger.warn(\n {\n conversation_id: conversationId,\n conflicting_resource_id: this.extractConflictingResourceId(error),\n },\n 'Conversation Orchestrator returned 409 on AI_AGENT participant add; skipping — ' +\n \"address is already owned or the conversation can't accept a new AI_AGENT. \" +\n 'Check Conversation Orchestrator participant state.'\n );\n return undefined;\n }\n this.logger.error(\n { err: error, conversation_id: conversationId },\n 'Failed to add AI_AGENT participant'\n );\n return undefined;\n }\n }\n\n private isConflictError(error: unknown): boolean {\n const cause = error instanceof Error ? (error.cause ?? error) : error;\n return axios.isAxiosError(cause) && cause.response?.status === 409;\n }\n\n private extractConflictingResourceId(error: unknown): string | undefined {\n const cause = error instanceof Error ? (error.cause ?? error) : error;\n if (!axios.isAxiosError(cause)) return undefined;\n const headers = cause.response?.headers as Record<string, string> | undefined;\n const id = headers?.['x-conflicting-resource-id'];\n return typeof id === 'string' && id.length > 0 ? id : undefined;\n }\n\n /**\n * Shared outbound conversation initiation for messaging channels (SMS/RCS/Chat/WhatsApp).\n *\n * Handles the full flow: create conversation → find participants → start\n * session → send initial message → error cleanup.\n */\n protected async initiateOutboundMessagingConversation(params: {\n channel: 'SMS' | 'CHAT' | 'RCS' | 'WHATSAPP';\n to: string;\n from: string;\n message: string;\n metadata?: Record<string, unknown>;\n channelId?: string;\n channelSettings?: ActionChannelSettings;\n }): Promise<InitiateConversationResult> {\n const {\n channel,\n to,\n from: fromAddress,\n message,\n metadata,\n channelId,\n channelSettings,\n } = params;\n\n let conversationId: string | undefined;\n let conversationReused = false;\n\n try {\n const customerAddress: ConversationAddress = {\n channel,\n address: to,\n ...(channelId ? { channelId } : {}),\n };\n const agentAddress: ConversationAddress = {\n channel,\n address: fromAddress,\n ...(channelId ? { channelId } : {}),\n };\n\n const result = await this.conversationClient.createOrReuseConversation([\n { type: 'CUSTOMER', addresses: [customerAddress] },\n { type: 'AI_AGENT', addresses: [agentAddress] },\n ]);\n conversationId = result.conversation.id;\n conversationReused = result.reused;\n\n if (!isConversationId(conversationId)) {\n throw new Error(`Invalid conversation ID returned: ${conversationId}`);\n }\n\n const participants = await this.conversationClient.listParticipants(conversationId);\n\n const customerParticipant = participants.find(\n p =>\n p.type === 'CUSTOMER' &&\n Array.isArray(p.addresses) &&\n p.addresses.some(\n a =>\n a.channel === channel &&\n a.address === to &&\n (channelId === undefined || a.channelId === channelId)\n )\n );\n if (!customerParticipant) {\n throw new Error('Customer participant not found after conversation creation');\n }\n\n const agentParticipant = participants.find(\n p =>\n p.type !== undefined &&\n AGENT_TYPES.has(p.type) &&\n Array.isArray(p.addresses) &&\n p.addresses.some(\n a =>\n a.channel === channel &&\n a.address === fromAddress &&\n (channelId === undefined || a.channelId === channelId)\n )\n );\n if (!agentParticipant) {\n throw new Error('Agent participant not found after conversation creation');\n }\n\n // Start local session BEFORE sending the initial message so the\n // COMMUNICATION_CREATED webhook (triggered by createAction) finds a\n // correctly-configured session instead of auto-starting one with wrong\n // metadata.\n const session = this.startConversation(conversationId);\n session.authorInfo = {\n address: to,\n participantId: customerParticipant.id,\n };\n session.aiAgentInfo = {\n address: fromAddress,\n participantId: agentParticipant.id,\n };\n session.metadata = {\n ...session.metadata,\n ...(metadata ?? {}),\n direction: 'outbound',\n ...(channelId ? { channelId } : {}),\n };\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: { channel, participantId: agentParticipant.id },\n to: [{ channel, participantId: customerParticipant.id }],\n content: { text: message },\n ...(channelSettings ? { channelSettings } : {}),\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n { conversation_id: conversationId, to: maskAddress(to) },\n `Outbound ${channel} conversation initiated`\n );\n\n return { conversationId, session };\n } catch (error) {\n if (conversationId) {\n this.activeConversations.delete(conversationId as ConversationId);\n }\n if (conversationId && !conversationReused) {\n await this.conversationClient\n .updateConversation(conversationId, 'CLOSED')\n .catch(closeErr => {\n this.logger.warn(\n { err: closeErr, conversation_id: conversationId },\n 'Failed to close orphaned conversation after initiation error'\n );\n });\n }\n this.logger.error(\n { err: error, to: maskAddress(to) },\n `Failed to initiate outbound ${channel}`\n );\n this.handleError(error instanceof Error ? error : new Error(String(error)), { to });\n throw error;\n }\n }\n}\n","import {\n ChannelType,\n ConversationAddress,\n ConversationId,\n SendMessageActionRequest,\n InitiateMessagingConversationOptions,\n InitiateMessagingConversationOptionsSchema,\n InitiateConversationResult,\n} from '../types/index';\nimport { MessagingChannel } from './messaging';\nimport { maskAddress } from '../util/log-redaction';\n\n/**\n * SMS Channel implementation for Twilio Conversations Service\n *\n * Handles SMS conversations through webhook events from Twilio.\n * Automatically retrieves user memory and manages conversation lifecycle.\n */\nexport class SMSChannel extends MessagingChannel {\n public get channelType(): ChannelType {\n return 'sms';\n }\n\n protected isDefaultAgentAddress(authorAddress: string): boolean {\n return authorAddress === this.config.phoneNumber;\n }\n\n protected getAgentAddress(_conversationId: ConversationId): ConversationAddress {\n return { channel: 'SMS', address: this.config.phoneNumber };\n }\n\n /**\n * Send SMS response using the Conversation Orchestrator Actions API (SEND_MESSAGE).\n *\n * Reads the agent and customer participant ids stashed on the session by\n * inbound reconciliation or outbound initiation. Missing ids are a misuse —\n * `sendResponse` is only expected to be called after an inbound webhook\n * (COMMUNICATION_CREATED → reconcile) or after `initiateOutboundConversation`,\n * both of which populate the session.\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_length: message.length,\n operation: 'send_response',\n },\n 'Sending SMS response'\n );\n\n try {\n const session = this.getConversationSession(conversationId);\n\n if (!session || !session.authorInfo || !session.aiAgentInfo) {\n throw new Error(\n `Unable to send SMS: sendResponse called without a reconciled session for ` +\n `conversation ${conversationId}. Wait for an inbound webhook or call ` +\n `initiateOutboundConversation first.`\n );\n }\n\n const customerParticipantId = session.authorInfo.participantId;\n const agentParticipantId = session.aiAgentInfo.participantId;\n if (!customerParticipantId || !agentParticipantId) {\n throw new Error(\n `Unable to send SMS: session for conversation ${conversationId} is missing ` +\n `participant ids.`\n );\n }\n\n const channelId =\n typeof session.metadata?.channelId === 'string' ? session.metadata.channelId : undefined;\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n recipient_participant_id: customerParticipantId,\n agent_participant_id: agentParticipantId,\n },\n 'Sending SMS via Actions API'\n );\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: {\n channel: 'SMS',\n participantId: agentParticipantId,\n },\n to: [\n {\n channel: 'SMS',\n participantId: customerParticipantId,\n },\n ],\n content: { text: message },\n ...(channelId ? { channelSettings: { channelId } } : {}),\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n },\n 'SMS sent successfully via Actions API'\n );\n } catch (error) {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Send response error');\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n\n this.trackResponseSent(conversationId);\n }\n\n /**\n * Initiate an outbound SMS conversation\n *\n * Creates a conversation via Conversation Orchestrator, adds customer and\n * agent participants, then sends the initial message via the Actions API.\n * The sender is always `config.phoneNumber`.\n */\n public async initiateOutboundConversation(\n options: InitiateMessagingConversationOptions\n ): Promise<InitiateConversationResult> {\n const validated = InitiateMessagingConversationOptionsSchema.parse(options);\n\n this.logger.info(\n { to: maskAddress(validated.to), message_length: validated.message.length },\n 'Initiating outbound SMS conversation'\n );\n\n return this.initiateOutboundMessagingConversation({\n channel: 'SMS',\n to: validated.to,\n from: this.config.phoneNumber,\n message: validated.message,\n ...(validated.metadata ? { metadata: validated.metadata } : {}),\n });\n }\n}\n","import {\n ChannelType,\n ConversationAddress,\n ConversationId,\n SendMessageActionRequest,\n InitiateMessagingConversationOptions,\n InitiateMessagingConversationOptionsSchema,\n InitiateConversationResult,\n} from '../types/index';\nimport { MessagingChannel, MessagingChannelConfig } from './messaging';\nimport { maskAddress } from '../util/log-redaction';\nimport type { TAC } from '../lib/tac';\n\n/**\n * RCS Channel implementation for Twilio Conversations Service\n *\n * Handles RCS (Rich Communication Services) conversations through webhook\n * events from Twilio. The RCS Sender ID is configured on `TACConfig` via\n * `TWILIO_RCS_SENDER_ID`. Follows the same pattern as SMS (sender from\n * TAC config) for consistency with other messaging channels.\n */\nexport class RCSChannel extends MessagingChannel {\n constructor(tac: TAC, config?: MessagingChannelConfig) {\n super(tac, config);\n\n if (!this.config.rcsSenderId) {\n throw new Error(\n 'rcsSenderId is required for RCS channel. ' +\n 'Please set TWILIO_RCS_SENDER_ID environment variable or provide rcsSenderId in TACConfig.'\n );\n }\n }\n\n public get channelType(): ChannelType {\n return 'rcs';\n }\n\n protected isDefaultAgentAddress(authorAddress: string): boolean {\n return authorAddress === this.config.rcsSenderId;\n }\n\n protected getAgentAddress(_conversationId: ConversationId): ConversationAddress {\n if (!this.config.rcsSenderId) {\n throw new Error('rcsSenderId is required for RCS channel.');\n }\n return { channel: 'RCS', address: this.config.rcsSenderId };\n }\n\n /**\n * Send RCS response using the Conversation Orchestrator Actions API (SEND_MESSAGE).\n *\n * Reads the agent and customer participant ids stashed on the session by\n * inbound reconciliation or outbound initiation. Missing ids are a misuse —\n * `sendResponse` is only expected to be called after an inbound webhook\n * (COMMUNICATION_CREATED → reconcile) or after `initiateOutboundConversation`,\n * both of which populate the session.\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_length: message.length,\n operation: 'send_response',\n },\n 'Sending RCS response'\n );\n\n try {\n const session = this.getConversationSession(conversationId);\n\n if (!session || !session.authorInfo || !session.aiAgentInfo) {\n throw new Error(\n `Unable to send RCS: sendResponse called without a reconciled session for ` +\n `conversation ${conversationId}. Wait for an inbound webhook or call ` +\n `initiateOutboundConversation first.`\n );\n }\n\n const customerParticipantId = session.authorInfo.participantId;\n const agentParticipantId = session.aiAgentInfo.participantId;\n if (!customerParticipantId || !agentParticipantId) {\n throw new Error(\n `Unable to send RCS: session for conversation ${conversationId} is missing ` +\n `participant ids.`\n );\n }\n\n const channelId =\n typeof session.metadata?.channelId === 'string' ? session.metadata.channelId : undefined;\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n recipient_participant_id: customerParticipantId,\n agent_participant_id: agentParticipantId,\n },\n 'Sending RCS via Actions API'\n );\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: {\n channel: 'RCS',\n participantId: agentParticipantId,\n },\n to: [\n {\n channel: 'RCS',\n participantId: customerParticipantId,\n },\n ],\n content: { text: message },\n ...(channelId ? { channelSettings: { channelId } } : {}),\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n },\n 'RCS sent successfully via Actions API'\n );\n } catch (error) {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Send response error');\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n\n this.trackResponseSent(conversationId);\n }\n\n /**\n * Initiate an outbound RCS conversation\n *\n * Creates a conversation via Conversation Orchestrator, adds customer and\n * agent participants, then sends the initial message via the Actions API.\n * The sender is always `config.rcsSenderId`.\n */\n public async initiateOutboundConversation(\n options: InitiateMessagingConversationOptions\n ): Promise<InitiateConversationResult> {\n const validated = InitiateMessagingConversationOptionsSchema.parse(options);\n\n if (!this.config.rcsSenderId) {\n throw new Error('rcsSenderId is required for RCS channel.');\n }\n\n this.logger.info(\n { to: maskAddress(validated.to), message_length: validated.message.length },\n 'Initiating outbound RCS conversation'\n );\n\n return this.initiateOutboundMessagingConversation({\n channel: 'RCS',\n to: validated.to,\n from: this.config.rcsSenderId,\n message: validated.message,\n ...(validated.metadata ? { metadata: validated.metadata } : {}),\n });\n }\n}\n","import {\n ChannelType,\n ConversationAddress,\n ConversationId,\n SendMessageActionRequest,\n InitiateMessagingConversationOptions,\n InitiateMessagingConversationOptionsSchema,\n InitiateConversationResult,\n} from '../types/index';\nimport { MessagingChannel } from './messaging';\nimport { maskAddress } from '../util/log-redaction';\n\n/**\n * WhatsApp Channel implementation for Twilio Conversations Service\n *\n * Handles WhatsApp conversations through webhook events from Twilio.\n * Automatically retrieves user memory and manages conversation lifecycle.\n *\n * WhatsApp uses WhatsApp sender phone numbers configured in TACConfig\n * (via TWILIO_WHATSAPP_NUMBER). Address format: whatsapp:+1234567890\n */\nexport class WhatsAppChannel extends MessagingChannel {\n public get channelType(): ChannelType {\n return 'whatsapp';\n }\n\n protected isDefaultAgentAddress(authorAddress: string): boolean {\n if (!this.config.whatsappNumber) {\n throw new Error(\n 'whatsappNumber is required for WhatsApp channel. ' +\n 'Please set TWILIO_WHATSAPP_NUMBER environment variable or ' +\n 'provide whatsappNumber in TACConfig.'\n );\n }\n return authorAddress === this.config.whatsappNumber;\n }\n\n protected getAgentAddress(_conversationId: ConversationId): ConversationAddress {\n if (!this.config.whatsappNumber) {\n throw new Error(\n 'whatsappNumber is required for WhatsApp channel. ' +\n 'Please set TWILIO_WHATSAPP_NUMBER environment variable or ' +\n 'provide whatsappNumber in TACConfig.'\n );\n }\n return { channel: 'WHATSAPP', address: this.config.whatsappNumber };\n }\n\n /**\n * Send WhatsApp response using the Conversation Orchestrator Actions API (SEND_MESSAGE).\n *\n * Reads the agent and customer participant ids stashed on the session by\n * inbound reconciliation or outbound initiation. Missing ids are a misuse —\n * `sendResponse` is only expected to be called after an inbound webhook\n * (COMMUNICATION_CREATED → reconcile) or after `initiateOutboundConversation`,\n * both of which populate the session.\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_length: message.length,\n operation: 'send_response',\n },\n 'Sending WhatsApp response'\n );\n\n try {\n const session = this.getConversationSession(conversationId);\n\n if (!session || !session.authorInfo || !session.aiAgentInfo) {\n throw new Error(\n `Unable to send WhatsApp: sendResponse called without a reconciled session for ` +\n `conversation ${conversationId}. Wait for an inbound webhook or call ` +\n `initiateOutboundConversation first.`\n );\n }\n\n const customerParticipantId = session.authorInfo.participantId;\n const agentParticipantId = session.aiAgentInfo.participantId;\n if (!customerParticipantId || !agentParticipantId) {\n throw new Error(\n `Unable to send WhatsApp: session for conversation ${conversationId} is missing ` +\n `participant ids.`\n );\n }\n\n const channelId =\n typeof session.metadata?.channelId === 'string' ? session.metadata.channelId : undefined;\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n recipient_participant_id: customerParticipantId,\n agent_participant_id: agentParticipantId,\n },\n 'Sending WhatsApp via Actions API'\n );\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: {\n channel: 'WHATSAPP',\n participantId: agentParticipantId,\n },\n to: [\n {\n channel: 'WHATSAPP',\n participantId: customerParticipantId,\n },\n ],\n content: { text: message },\n ...(channelId ? { channelSettings: { channelId } } : {}),\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n {\n conversation_id: conversationId,\n recipient_address: maskAddress(session.authorInfo.address),\n },\n 'WhatsApp sent successfully via Actions API'\n );\n } catch (error) {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Send response error');\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n\n this.trackResponseSent(conversationId);\n }\n\n /**\n * Initiate an outbound WhatsApp conversation\n *\n * Creates a conversation via Conversation Orchestrator, adds customer and\n * agent participants, then sends the initial message via the Actions API.\n * The sender is always `config.whatsappNumber`.\n */\n public async initiateOutboundConversation(\n options: InitiateMessagingConversationOptions\n ): Promise<InitiateConversationResult> {\n const validated = InitiateMessagingConversationOptionsSchema.parse(options);\n\n if (!this.config.whatsappNumber) {\n throw new Error(\n 'whatsappNumber is required for WhatsApp channel. ' +\n 'Please set TWILIO_WHATSAPP_NUMBER environment variable or ' +\n 'provide whatsappNumber in TACConfig.'\n );\n }\n\n this.logger.info(\n { to: maskAddress(validated.to), message_length: validated.message.length },\n 'Initiating outbound WhatsApp conversation'\n );\n\n return this.initiateOutboundMessagingConversation({\n channel: 'WHATSAPP',\n to: validated.to,\n from: this.config.whatsappNumber,\n message: validated.message,\n ...(validated.metadata ? { metadata: validated.metadata } : {}),\n });\n }\n}\n","import {\n ActionChannelSettings,\n ChannelType,\n ConversationAddress,\n ConversationId,\n SendMessageActionRequest,\n InitiateConversationResult,\n} from '../types/index';\nimport { z } from 'zod';\nimport { MessagingChannel, MessagingChannelConfig } from './messaging';\nimport type { TAC } from '../lib/tac';\nimport { maskAddress } from '../util/log-redaction';\n\n/**\n * Options for initiating an outbound chat conversation.\n *\n * The sender is always the channel's configured `agentAddress`. Multi-sender\n * deployments should run one TAC instance per sender.\n */\nexport const InitiateChatConversationOptionsSchema = z.object({\n to: z.string().min(1, 'Recipient identity is required'),\n channelId: z.string().min(1, 'Chat Channel SID is required'),\n message: z.string().min(1, 'Initial message is required'),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type InitiateChatConversationOptions = z.infer<typeof InitiateChatConversationOptionsSchema>;\n\n/**\n * Chat channel configuration options\n */\nexport interface ChatChannelConfig extends MessagingChannelConfig {\n /** Chat agent identity string (defaults to 'ai-assistant') */\n agentAddress?: string;\n}\n\n/**\n * Chat Channel implementation for Twilio Conversations Service\n *\n * Handles web chat conversations through webhook events from Twilio.\n * Uses identity-based addressing instead of phone numbers.\n * Automatically creates AI_AGENT participant if needed and manages conversation lifecycle.\n */\nexport class ChatChannel extends MessagingChannel {\n private readonly agentAddress: string;\n\n // Chat identifies the customer author-driven from the webhook's\n // `author.participantId`; promoting some other channel-matching UNKNOWN\n // CHAT participant could pick the wrong recipient.\n protected override reconcileCustomerType: boolean = false;\n\n constructor(tac: TAC, config?: ChatChannelConfig) {\n super(tac, config);\n this.agentAddress = config?.agentAddress ?? 'ai-assistant';\n }\n\n public get channelType(): ChannelType {\n return 'chat';\n }\n\n protected isDefaultAgentAddress(authorAddress: string): boolean {\n return authorAddress === this.agentAddress;\n }\n\n protected getAgentAddress(conversationId: ConversationId): ConversationAddress {\n const session = this.getConversationSession(conversationId);\n const channelId =\n session && typeof session.metadata?.channelId === 'string'\n ? session.metadata.channelId\n : undefined;\n return {\n channel: 'CHAT',\n address: this.agentAddress,\n ...(channelId ? { channelId } : {}),\n };\n }\n\n /**\n * Send chat response using the Conversation Orchestrator Actions API (SEND_MESSAGE).\n *\n * Reads the agent and customer participant ids stashed on the session by\n * inbound reconciliation or outbound initiation. Missing ids are a misuse —\n * `sendResponse` is only expected to be called after an inbound webhook\n * (COMMUNICATION_CREATED → reconcile) or after `initiateOutboundConversation`,\n * both of which populate the session.\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_length: message.length,\n operation: 'send_response',\n },\n 'Sending chat response'\n );\n\n try {\n const session = this.getConversationSession(conversationId);\n\n if (!session || !session.authorInfo || !session.aiAgentInfo) {\n throw new Error(\n `Unable to send chat message: sendResponse called without a reconciled session ` +\n `for conversation ${conversationId}. Wait for an inbound webhook or call ` +\n `initiateOutboundConversation first.`\n );\n }\n\n const customerParticipantId = session.authorInfo.participantId;\n const agentParticipantId = session.aiAgentInfo.participantId;\n if (!customerParticipantId || !agentParticipantId) {\n throw new Error(\n `Unable to send chat message: session for conversation ${conversationId} is ` +\n `missing participant ids.`\n );\n }\n\n // channelId (Chat Channel SID) is required for CHAT delivery — the V1\n // Chat backend uses it to pick the destination thread. Inbound webhooks\n // always populate it, so a missing value here is a misuse.\n const chatChannelSid =\n typeof session.metadata?.channelId === 'string' ? session.metadata.channelId : undefined;\n\n if (!chatChannelSid) {\n throw new Error(\n \"Missing required session.metadata['channelId'] for chat sendResponse; \" +\n 'this is normally populated by an inbound webhook. Ensure an inbound ' +\n 'message has been processed before calling sendResponse, or set ' +\n \"session.metadata['channelId'] explicitly in advanced usage.\"\n );\n }\n\n const channelSettings: ActionChannelSettings = {\n channelId: chatChannelSid,\n };\n\n this.logger.debug(\n {\n conversation_id: conversationId,\n recipient_participant_id: customerParticipantId,\n agent_participant_id: agentParticipantId,\n channel_id: chatChannelSid,\n },\n 'Sending chat message via Actions API'\n );\n\n const actionRequest: SendMessageActionRequest = {\n type: 'SEND_MESSAGE',\n payload: {\n from: {\n channel: 'CHAT',\n participantId: agentParticipantId,\n },\n to: [\n {\n channel: 'CHAT',\n participantId: customerParticipantId,\n },\n ],\n content: { text: message },\n channelSettings,\n },\n };\n\n await this.conversationClient.createAction(conversationId, actionRequest);\n\n this.logger.info(\n { conversation_id: conversationId, channel_id: chatChannelSid },\n 'Chat message sent successfully via Actions API'\n );\n } catch (error) {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Send response error');\n this.handleError(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n\n this.trackResponseSent(conversationId);\n }\n\n /**\n * Initiate an outbound chat conversation\n *\n * Creates a conversation via Conversation Orchestrator, adds customer and\n * agent participants, then sends the initial message via the Actions API.\n * The sender is always this channel's configured `agentAddress`.\n */\n public async initiateOutboundConversation(\n options: InitiateChatConversationOptions\n ): Promise<InitiateConversationResult> {\n const validated = InitiateChatConversationOptionsSchema.parse(options);\n\n this.logger.info(\n { to: maskAddress(validated.to), channel_id: validated.channelId },\n 'Initiating outbound chat conversation'\n );\n\n return this.initiateOutboundMessagingConversation({\n channel: 'CHAT',\n to: validated.to,\n from: this.agentAddress,\n message: validated.message,\n ...(validated.metadata ? { metadata: validated.metadata } : {}),\n channelId: validated.channelId,\n channelSettings: {\n channelId: validated.channelId,\n },\n });\n }\n}\n","const warned = new Set<string>();\n\n/**\n * Warn once per deprecated name that a renamed API is still being used.\n *\n * Mirrors the Python SDK's module-level `__getattr__` shim, which warns on\n * *every* access and never caches the resolved attribute — repeats are\n * suppressed by Python's default warning filter, which dedupes per attributed\n * `(module, line)` call site. TypeScript has no warning-filter equivalent, so\n * this helper dedupes globally per deprecated name: a coarser policy that\n * reports only the first offending call site in the process.\n *\n * TypeScript also has no `__getattr__` hook, so runtime values call this\n * explicitly; renamed *types* are erased at compile time and rely on\n * `@deprecated` tags instead.\n */\nexport function warnDeprecated(oldName: string, replacement: string): void {\n if (warned.has(oldName)) return;\n warned.add(oldName);\n console.warn(`${oldName} is deprecated and will be removed in 3.0 — use ${replacement} instead.`);\n}\n","import type { WebSocket } from 'ws';\nimport type { TACConfig } from '../../lib/config';\nimport { createLogger, type Logger } from '../../lib/logger';\nimport type {\n CallEventKind,\n ConversationId,\n InitiateVoiceConversationOptions,\n MemoryMode,\n TwilioProviderCallbackResponse,\n VoiceTwiMLOptions,\n TwiMLRequest,\n} from '../../types/index';\nimport type { InitiateVoiceConversationResult } from '../../types/conversation';\nimport type { BaseChannelOptions } from '../base';\nimport type { VoiceChannel } from './channel';\n\n/**\n * Base class for a {@link VoiceChannel}'s real-time media provider.\n *\n * Holds the owning `channel` (Calls API lifecycle, conversation bookkeeping,\n * `TAC`). Every method here has a default that either declines the capability\n * or does nothing, so a provider only implements the transport it actually\n * supports — ConversationRelay serves inbound TwiML and a WebSocket, while a\n * provider with no inbound story simply inherits the refusal.\n */\nexport class VoiceProvider {\n /** The `VoiceChannel` that owns this provider. */\n public readonly channel: VoiceChannel;\n\n /** Logger named after the concrete provider class. */\n protected readonly logger: Logger;\n\n constructor(channel: VoiceChannel) {\n this.channel = channel;\n this.logger = createLogger({ name: this.constructor.name });\n }\n\n /**\n * Stable snake_case identifier for this provider, reported on voice\n * telemetry events so emissions from different transports are\n * distinguishable. Built-in providers override it; a provider defined outside\n * the SDK inherits `\"custom\"`.\n *\n * @internal\n */\n public get providerId(): string {\n return 'custom';\n }\n\n /**\n * Channel name identifier, e.g. `\"VOICE\"`.\n *\n * A label for this provider's transport; it does not change how\n * `VoiceChannel` reports its `ChannelType`.\n */\n public get channelName(): string {\n return 'VOICE';\n }\n\n /**\n * Build the response for an inbound call. Default: not supported.\n *\n * @param _twimlRequest - Parsed Twilio webhook fields for the inbound call.\n * @param _options - Additional per-call inputs.\n * @param _options.hostTwimlOptions - Per-call TwiML supplied by a custom\n * in-process host.\n */\n // eslint-disable-next-line @typescript-eslint/require-await -- Default rejects without awaiting, but stays `async` so callers always get a Promise\n public async handleIncomingCall(\n _twimlRequest?: TwiMLRequest,\n _options?: { hostTwimlOptions?: VoiceTwiMLOptions }\n ): Promise<string> {\n throw new Error(`${this.constructor.name} does not support inbound calls.`);\n }\n\n /**\n * Handle this provider's own out-of-band lifecycle webhook, if it has one.\n *\n * Not every provider has an equivalent — Twilio's ConversationRelay posts to\n * `<Connect action=...>` when the session ends (`ConversationRelayProvider`\n * uses this as a WebSocket-disconnect backup); Media Streams instead has its\n * own independent `statusCallback` (`stream-started` / `stream-stopped` /\n * `stream-error`), which is purely informational and doesn't gate call flow.\n * Default acknowledges with an empty 200 for providers with nothing to do\n * here.\n */\n // eslint-disable-next-line @typescript-eslint/require-await -- Default acknowledges without awaiting, but stays `async` so callers always get a Promise\n public async handleTwilioProviderCallback(\n _payload: Record<string, unknown>\n ): Promise<TwilioProviderCallbackResponse> {\n return { status: 200, content: '', contentType: 'text/plain' };\n }\n\n /**\n * Drive one WebSocket connection from accept to disconnect.\n *\n * Implementations may be synchronous or asynchronous: a provider that only\n * attaches event handlers can return `void`, while one that awaits an\n * upstream handshake before serving traffic returns a `Promise<void>`. The\n * owning `VoiceChannel` is responsible for handling a returned promise's\n * rejection, so an async override never produces an unhandled rejection.\n */\n public handleWebSocket(_websocket: WebSocket): void | Promise<void> {\n throw new Error(`${this.constructor.name} does not support WebSocket connections.`);\n }\n\n /** Place an outbound call. Default: not supported. */\n // eslint-disable-next-line @typescript-eslint/require-await -- Default rejects without awaiting, but stays `async` so callers always get a Promise\n public async initiateOutboundConversation(\n _options: InitiateVoiceConversationOptions\n ): Promise<InitiateVoiceConversationResult> {\n throw new Error(`${this.constructor.name} does not support outbound calls.`);\n }\n\n /** Send a text response back through this provider's transport, if supported. */\n // eslint-disable-next-line @typescript-eslint/require-await -- Default rejects without awaiting, but stays `async` so callers always get a Promise\n public async sendResponse(\n _conversationId: ConversationId,\n _message: string,\n _metadata?: Record<string, unknown>\n ): Promise<void> {\n throw new Error(`${this.constructor.name} does not support sendResponse.`);\n }\n\n /**\n * Stream a text response back through this provider's transport, token by\n * token, if supported. Default: not supported.\n *\n * @param _conversationId - Conversation whose transport receives the tokens.\n * @param _stream - Async iterable of text chunks to relay as they arrive.\n * @param _options - Additional per-call inputs.\n * @param _options.signal - Aborts the stream mid-flight, e.g. when the caller\n * interrupts.\n * @returns The accumulated response text.\n */\n // eslint-disable-next-line @typescript-eslint/require-await -- Default rejects without awaiting, but stays `async` so callers always get a Promise\n public async sendStreamingResponse(\n _conversationId: ConversationId,\n _stream: AsyncIterable<string>,\n _options?: { signal?: AbortSignal }\n ): Promise<string> {\n throw new Error(`${this.constructor.name} does not support sendStreamingResponse.`);\n }\n\n /** Return the Twilio-facing WebSocket for a conversation, if tracked. */\n public getWebSocket(_conversationId: ConversationId): WebSocket | null {\n return null;\n }\n\n /**\n * Drop this provider's transport state on channel shutdown.\n *\n * Called by {@link VoiceChannel.shutdown} before the channel clears its own\n * conversation bookkeeping. Default no-op — providers override this to drop\n * whatever transport state they track. Live WebSocket connections are owned\n * and closed by the server, so an override only clears in-process tracking.\n */\n public shutdown(): void {\n return undefined;\n }\n\n /**\n * Set callback URLs on `callParams` for every registered call-event handler.\n *\n * A URL is derived only when its handler is registered — an unwanted\n * call-event URL would otherwise surface as silent 11200 alerts for a\n * feature nobody asked for. If TAC isn't serving these routes, set the URLs\n * explicitly via `CallOptions` (or the provider config's default call\n * options, where available). An explicit URL from either options layer is\n * never overwritten.\n */\n protected applyCallEventCallbacks(callParams: Record<string, unknown>): Record<string, unknown> {\n const handlers = this.channel.getCallEventHandlers();\n const wiring: [CallEventKind, string, unknown][] = [\n ['status', 'statusCallback', handlers.status],\n ['amd', 'asyncAmdStatusCallback', handlers.amd],\n ['recording', 'recordingStatusCallback', handlers.recording],\n ];\n for (const [kind, param, handler] of wiring) {\n if (!handler) continue;\n const url = this.channel.getTacConfig().callEventUrl(kind);\n // An explicit URL from either options layer is never overwritten.\n if (url !== undefined && callParams[param] === undefined) {\n callParams[param] = url;\n }\n }\n return callParams;\n }\n}\n\n/**\n * Base configuration for a {@link VoiceChannel}'s real-time media provider.\n *\n * Subclasses add their provider's own settings and implement\n * {@link VoiceProviderConfig.createProvider} to build the provider they\n * configure.\n */\nexport class VoiceProviderConfig {\n /** Memory retrieval mode for this channel. Defaults to `'never'`. */\n public memoryMode: MemoryMode;\n\n /**\n * The {@link BaseChannelOptions} this config was constructed with, retained\n * verbatim so `VoiceChannel` can hand them to `BaseChannel`.\n *\n * A provider config carries channel-level options (`dedupCapacity` and\n * friends) alongside its own provider settings; without this they would be\n * dropped on the config path while still applying on the plain-object path,\n * which is the same channel configured two ways.\n *\n * @internal\n */\n public readonly channelOptions: BaseChannelOptions;\n\n constructor(options?: BaseChannelOptions) {\n this.memoryMode = options?.memoryMode ?? 'never';\n this.channelOptions = { ...options };\n }\n\n /**\n * Build the {@link VoiceProvider} this config configures.\n *\n * @param _channel - The owning `VoiceChannel`.\n * @param _tacConfig - `TACConfig` — providers that talk TwiML need it to\n * derive default URLs (`voicePublicDomain` etc.).\n */\n public createProvider(_channel: VoiceChannel, _tacConfig: TACConfig): VoiceProvider {\n throw new Error(\n `${this.constructor.name} must implement createProvider() to be usable ` +\n 'as a VoiceChannel config.'\n );\n }\n}\n","import type { TACConfig } from '../../lib/config';\nimport type { Logger } from '../../lib/logger';\n\n/**\n * Filter out undefined values from a configuration object.\n * Keeps null, false, 0, and empty strings as they are valid values.\n */\nexport function filterUnsetValues(config: Record<string, unknown>): Record<string, unknown> {\n const filtered: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(config)) {\n if (value !== undefined) {\n filtered[key] = value;\n }\n }\n return filtered;\n}\n\n/**\n * Stringify a custom-parameter value for emission as a `<Parameter value=...>`.\n * Parameter values are scalars in practice; objects are JSON-encoded rather\n * than producing '[object Object]'.\n */\nexport function stringifyParameterValue(value: unknown): string {\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n // string | number | boolean | bigint | symbol — all safely stringifiable.\n return String(value as string | number | boolean | bigint);\n}\n\n/**\n * Common construction and option-layering helpers shared by every provider's\n * TwiML builder.\n *\n * Subclasses take `TACConfig` and their provider's channel config wholesale\n * (not individual derived values) so a later change to either — a new field, a\n * new default — is a change to the builder alone, not a change to what\n * `VoiceChannel` has to compute and hand over.\n *\n * @internal\n */\nexport abstract class TwiMLBuilderBase<TChannelConfig = unknown> {\n protected readonly tacConfig: TACConfig;\n protected readonly channelConfig: TChannelConfig;\n protected readonly logger: Logger;\n\n constructor(tacConfig: TACConfig, channelConfig: TChannelConfig, logger: Logger) {\n this.tacConfig = tacConfig;\n this.channelConfig = channelConfig;\n this.logger = logger;\n }\n\n /**\n * Apply fields explicitly present on `source` onto `target`, except those\n * named in `skip`.\n *\n * Nested objects, arrays, and dicts replace wholesale — there's no per-key\n * merging.\n *\n * \"Explicitly present\" is detected via key presence (`Object.keys`), which\n * mirrors Python's `model_fields_set`: a key set to `undefined` is still\n * \"present\" and overrides lower layers, while an absent key falls through.\n */\n protected overlayFields(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n skip: readonly string[] = []\n ): void {\n for (const key of Object.keys(source)) {\n if (skip.includes(key)) {\n continue;\n }\n target[key] = source[key];\n }\n }\n\n /**\n * The error thrown when no layer and no `TACConfig`-derived default supplies\n * a WebSocket URL. `caller` names the API the developer actually called.\n */\n protected missingWebsocketUrlError(caller: string): Error {\n return new Error(\n `${caller} needs a WebSocket URL. Set TWILIO_VOICE_PUBLIC_DOMAIN ` +\n '(or TACConfig.voicePublicDomain).'\n );\n }\n\n /**\n * The WebSocket URL derived from `TACConfig.voicePublicDomain` +\n * `TACConfig.voiceWebsocketPath`, or undefined when `voicePublicDomain` is\n * unset.\n */\n protected defaultWebsocketUrl(): string | undefined {\n if (!this.tacConfig.voicePublicDomain) {\n return undefined;\n }\n return `wss://${this.tacConfig.voicePublicDomain}${this.tacConfig.voiceWebsocketPath}`;\n }\n\n /**\n * Resolve the default `<Connect action=...>` cleanup URL from\n * `TACConfig.voicePublicDomain` + `TACConfig.voiceActionPath`.\n *\n * Returns undefined if `voicePublicDomain` isn't set; that's fine because\n * actionUrl has higher-priority layers (customizer, twimlOptions, Studio\n * handoff) above this fallback.\n */\n protected defaultActionUrl(): string | undefined {\n if (this.tacConfig.voicePublicDomain) {\n return `https://${this.tacConfig.voicePublicDomain}${this.tacConfig.voiceActionPath}`;\n }\n return undefined;\n }\n}\n","/**\n * URL builders for Twilio Studio handoff.\n *\n * Shared between the tools package (digital handoff POSTs) and the server\n * package (voice `<Connect action>` URL).\n */\n\n/**\n * Build the Twilio Studio Flow Executions URL for a given Flow SID.\n *\n * Used for digital (messaging/chat) handoff — POST the handoff payload\n * to this URL to start a Studio flow execution.\n */\nexport function studioExecutionsUrl(flowSid: string): string {\n return `https://studio.twilio.com/v2/Flows/${flowSid}/Executions`;\n}\n\n/**\n * Build the Twilio Studio Flow voice webhook URL for a given Flow SID.\n *\n * Used as the `<Connect action=...>` URL in TwiML for voice handoff,\n * so that when ConversationRelay ends the session Twilio triggers the\n * Studio flow for an incoming call.\n */\nexport function studioVoiceHandoffUrl(accountSid: string, flowSid: string): string {\n return `https://webhooks.twilio.com/v1/Accounts/${accountSid}/Flows/${flowSid}?Trigger=incomingCall`;\n}\n","import VoiceResponse from 'twilio/lib/twiml/VoiceResponse.js';\nimport type { VoiceTwiMLOptionsConversationRelay } from '../../../types/index';\nimport type { ConversationRelayProviderConfigOptions } from './config';\nimport { studioVoiceHandoffUrl } from '../../../util/handoff-urls';\nimport { TwiMLBuilderBase, filterUnsetValues, stringifyParameterValue } from '../twiml';\n\n/** Fixed default welcome greeting applied when no layer sets one. */\nconst DEFAULT_WELCOME_GREETING = 'Hello! How can I assist you today?';\n\n/** Fields excluded from the option overlays; resolved separately. */\nconst SKIP_ACTION_URL = ['actionUrl'] as const;\n\n/** Per-call inputs to {@link TwiMLBuilderConversationRelay.build}. */\nexport interface BuildTwiMLInputs {\n /**\n * Per-call overrides from the host owning the route (e.g. a per-call\n * `websocketUrl` with an affinity token). Lowest of the option layers.\n */\n host?: VoiceTwiMLOptionsConversationRelay | undefined;\n /**\n * Per-call overrides — the `onInboundCallTwiml` customizer's output for\n * inbound, or `InitiateVoiceConversationOptions.twimlOptions` for outbound.\n * Highest layer.\n */\n perCall?: VoiceTwiMLOptionsConversationRelay | undefined;\n /**\n * Dedicated per-call WebSocket override that wins over any `websocketUrl`\n * coming through the option layers. Used by outbound, which takes it as its\n * own argument.\n */\n websocketUrl?: string | undefined;\n}\n\n/**\n * Builds the TwiML for a ConversationRelay call, owning every layering and\n * resolution decision so `VoiceChannel` doesn't have to.\n */\nexport class TwiMLBuilderConversationRelay extends TwiMLBuilderBase<ConversationRelayProviderConfigOptions> {\n /**\n * Field names on {@link VoiceTwiMLOptionsConversationRelay} that map directly to `<ConversationRelay>`\n * attributes (camelCase, emitted as-is). Excludes the fields handled specially\n * by {@link generateTwiml}: websocketUrl (resolved through the layered merge and\n * emitted as the `url` attribute), actionUrl, languages, customParameters, extra.\n */\n protected static readonly RELAY_ATTR_FIELDS: readonly (keyof VoiceTwiMLOptionsConversationRelay)[] =\n [\n 'welcomeGreeting',\n 'welcomeGreetingInterruptible',\n 'conversationConfiguration',\n 'language',\n 'ttsLanguage',\n 'transcriptionLanguage',\n 'voice',\n 'ttsProvider',\n 'transcriptionProvider',\n 'speechModel',\n 'elevenlabsTextNormalization',\n 'eotThreshold',\n 'partialPrompts',\n 'deepgramSmartFormat',\n 'speechTimeout',\n 'interruptible',\n 'interruptSensitivity',\n 'reportInputDuringAgentSpeech',\n 'ignoreBackchannel',\n 'preemptible',\n 'dtmfDetection',\n 'hints',\n 'events',\n 'debug',\n 'intelligenceService',\n ];\n\n /**\n * Build the TwiML XML for one call.\n *\n * @param caller - Name of the calling method, used in the \"no WebSocket URL\"\n * error so it points at the API the developer actually called.\n * @param options - Per-call option layers and WebSocket override.\n * @throws {Error} if no layer and no `TACConfig`-derived default supplies a\n * WebSocket URL.\n */\n public build(caller: string, options?: BuildTwiMLInputs): string {\n const merged = this.buildTwimlOptions(options?.host, options?.perCall);\n\n const resolvedWebsocketUrl =\n options?.websocketUrl ?? merged.websocketUrl ?? this.defaultWebsocketUrl();\n if (!resolvedWebsocketUrl) {\n throw this.missingWebsocketUrlError(caller);\n }\n\n return this.generateTwiml(resolvedWebsocketUrl, merged);\n }\n\n /**\n * Layer TwiML options, lowest precedence first: TAC defaults → `host`\n * (calling host's per-call values) → channel `defaultTwimlOptions` → `perCall`\n * (application customizer output for inbound, or\n * `InitiateVoiceConversationOptions.twimlOptions` for outbound).\n *\n * `actionUrl` is skipped by the overlays on purpose — it's resolved once via\n * {@link resolveActionUrl} looking at every layer at once, and that resolved\n * value is written into `merged` before the overlays run. Letting it through\n * would let a higher-priority layer that didn't set actionUrl silently clobber\n * a lower layer that did.\n */\n protected buildTwimlOptions(\n host: VoiceTwiMLOptionsConversationRelay | undefined,\n perCall: VoiceTwiMLOptionsConversationRelay | undefined\n ): VoiceTwiMLOptionsConversationRelay {\n const merged: VoiceTwiMLOptionsConversationRelay = {\n welcomeGreeting: DEFAULT_WELCOME_GREETING,\n ...(this.tacConfig.isOrchestratorEnabled() &&\n this.tacConfig.conversationConfigurationId !== undefined\n ? { conversationConfiguration: this.tacConfig.conversationConfigurationId }\n : {}),\n };\n const resolvedActionUrl = this.resolveActionUrl(host, perCall);\n if (resolvedActionUrl !== undefined) {\n merged.actionUrl = resolvedActionUrl;\n }\n if (host) {\n this.overlayFields(merged, host, SKIP_ACTION_URL);\n }\n if (this.channelConfig.defaultTwimlOptions) {\n this.overlayFields(merged, this.channelConfig.defaultTwimlOptions, SKIP_ACTION_URL);\n }\n if (perCall) {\n this.overlayFields(merged, perCall, SKIP_ACTION_URL);\n }\n return merged;\n }\n\n /**\n * Resolve the TwiML `<Connect action=...>` URL.\n *\n * Precedence (highest to lowest):\n * 1. application customizer\n * 2. channel `defaultTwimlOptions`\n * 3. `host` (calling host's per-call options)\n * 4. Studio handoff (when `studioHandoffFlowSid` is configured)\n * 5. Channel default — derived from `TACConfig.voicePublicDomain` +\n * `TACConfig.voiceActionPath`.\n *\n * User-expressed intent (Studio handoff is configured explicitly on\n * `TACConfig`) beats the SDK's generated cleanup default.\n *\n * Explicit `actionUrl: undefined` on a layer (key present, value undefined)\n * suppresses `<Connect action=...>` entirely — all lower layers are skipped.\n * `actionUrl` left absent (key not present) falls through to the next layer.\n */\n protected resolveActionUrl(\n host: VoiceTwiMLOptionsConversationRelay | undefined,\n customized: VoiceTwiMLOptionsConversationRelay | undefined\n ): string | undefined {\n if (customized && 'actionUrl' in customized) {\n return customized.actionUrl;\n }\n const defaults = this.channelConfig.defaultTwimlOptions;\n if (defaults && 'actionUrl' in defaults) {\n return defaults.actionUrl;\n }\n if (host && 'actionUrl' in host) {\n return host.actionUrl;\n }\n if (this.tacConfig.studioHandoffFlowSid) {\n return studioVoiceHandoffUrl(this.tacConfig.accountSid, this.tacConfig.studioHandoffFlowSid);\n }\n return this.defaultActionUrl();\n }\n\n /**\n * Generate TwiML XML for ConversationRelay from a merged {@link VoiceTwiMLOptionsConversationRelay}.\n *\n * This is the low-level emitter used by {@link build} after layering. It\n * mirrors the Python SDK's `generate_twiml`.\n *\n * @param websocketUrl - Public WebSocket URL (e.g. 'wss://example.ngrok.app/ws').\n * @param options - Merged VoiceTwiMLOptionsConversationRelay to emit.\n * @returns TwiML XML string ready to return to Twilio.\n */\n protected generateTwiml(\n websocketUrl: string,\n options: VoiceTwiMLOptionsConversationRelay\n ): string {\n const response = new VoiceResponse();\n\n // <Connect action=...> — actionUrl undefined means no action attribute.\n const connect = response.connect(options.actionUrl ? { action: options.actionUrl } : {});\n\n // Build ConversationRelay attributes. Keys on VoiceTwiMLOptionsConversationRelay are already\n // camelCase; the Twilio SDK serializes booleans/numbers as TwiML attribute\n // values.\n const relayAttrs: Record<string, unknown> = { url: websocketUrl };\n for (const field of TwiMLBuilderConversationRelay.RELAY_ATTR_FIELDS) {\n let value = options[field];\n if (value === undefined) {\n continue;\n }\n // Twilio accepts true/false on `interruptible` for backward-compat but the\n // documented enum is none|dtmf|speech|any. Normalize so we emit canonical\n // values regardless of the SDK's bool serialization.\n if (field === 'interruptible' && typeof value === 'boolean') {\n value = value ? 'any' : 'none';\n }\n relayAttrs[field] = value;\n }\n\n // `extra` is the escape hatch for attributes not yet typed. The schema's\n // shadow-guard rejects keys colliding with typed fields, so pass them\n // through as-is — except `url`: it's not a VoiceTwiMLOptionsConversationRelay field (invisible to\n // the shadow-guard) but IS the resolved WebSocket endpoint, so letting\n // `extra.url` through would silently point the call at the wrong socket.\n if (options.extra) {\n for (const [key, value] of Object.entries(options.extra)) {\n if (key === 'url') {\n this.logger.warn(\n 'Ignoring `url` in VoiceTwiMLOptionsConversationRelay.extra; set `websocketUrl` to override the ConversationRelay URL.'\n );\n continue;\n }\n relayAttrs[key] = value;\n }\n }\n\n const relay = connect.conversationRelay(\n relayAttrs as Parameters<typeof connect.conversationRelay>[0]\n );\n\n // Emit <Language> children, if any.\n if (options.languages && options.languages.length > 0) {\n for (const lang of options.languages) {\n const langAttrs = filterUnsetValues(lang);\n relay.language(langAttrs as Parameters<typeof relay.language>[0]);\n }\n }\n\n // Emit custom parameters as <Parameter> children, skipping null/undefined.\n if (options.customParameters) {\n for (const [name, value] of Object.entries(options.customParameters)) {\n if (value !== null && value !== undefined) {\n relay.parameter({ name, value: stringifyParameterValue(value) });\n }\n }\n }\n\n return response.toString();\n }\n}\n","import { WebSocket } from 'ws';\nimport VoiceResponse from 'twilio/lib/twiml/VoiceResponse.js';\nimport type { ConversationClient } from '../../../clients/conversation';\nimport type { TACConfig } from '../../../lib/config';\nimport type { Logger } from '../../../lib/logger';\nimport {\n CallOptions,\n CallOptionsSchema,\n ConversationId,\n ConversationRelayCallbackPayloadSchema,\n ConversationRelayConfig,\n ConversationRelayConfigSchema,\n CustomParameters,\n DtmfMessage,\n InitiateVoiceConversationOptions,\n InitiateVoiceConversationOptionsSchema,\n InterruptMessage,\n ProfileId,\n PromptMessage,\n TextTokenMessage,\n TwilioProviderCallbackResponse,\n TwiMLRequest,\n VoiceTwiMLOptions,\n VoiceTwiMLOptionsConversationRelay,\n VoiceTwiMLOptionsConversationRelaySchema,\n WebSocketMessageSchema,\n callOptionsToCreateParams,\n} from '../../../types/index';\nimport type { InitiateVoiceConversationResult } from '../../../types/conversation';\nimport { maskAddress, redactTwimlParameters } from '../../../util/log-redaction';\nimport type { VoiceChannel } from '../channel';\nimport { VoiceProvider } from '../provider';\nimport { trackEvent } from '../../../lib/analytics';\nimport { filterUnsetValues } from '../twiml';\nimport type { ConversationRelayProviderConfig } from './config';\nimport { TwiMLBuilderConversationRelay } from './twiml';\n\n/** Poll window from call-connect: 10 attempts, 250ms doubling to a 1.5s cap (~11s). */\nconst POLL_ATTEMPTS = 10;\nconst POLL_BASE_DELAY_MS = 250;\nconst POLL_MAX_DELAY_MS = 1500;\n\n/**\n * A single in-flight streaming response, with the {@link AbortController} that\n * cancels it and whether any token has been written to the transport yet.\n */\nexport interface StreamTask {\n controller: AbortController;\n hasSentTokens: boolean;\n}\n\n/**\n * Twilio ConversationRelay: Twilio handles ASR/TTS and exchanges JSON\n * `setup`/`prompt`/`interrupt` messages over one WebSocket.\n *\n * This is the default provider {@link VoiceChannel} builds when none is passed\n * explicitly.\n */\nexport class ConversationRelayProvider extends VoiceProvider {\n /** @internal */\n public override get providerId(): string {\n return 'conversation_relay';\n }\n\n /**\n * The owning channel's logger, so relocated ConversationRelay logic keeps\n * logging exactly as it did when it lived on `VoiceChannel`.\n */\n protected override readonly logger: Logger;\n\n /** In-flight streaming responses, keyed by conversation. */\n protected readonly streamTasks: Map<ConversationId, StreamTask>;\n\n private readonly config: ConversationRelayProviderConfig;\n private readonly tacConfig: TACConfig;\n private readonly twimlBuilder: TwiMLBuilderConversationRelay;\n private readonly webSocketConnections: Map<ConversationId, WebSocket>;\n private readonly promptQueues: Map<ConversationId, Promise<void>>;\n private readonly initializationRetries: Map<string, number>;\n private readonly callSidToConversationId: Map<string, ConversationId>;\n private readonly MAX_INITIALIZATION_RETRIES = 3;\n\n constructor(\n channel: VoiceChannel,\n tacConfig: TACConfig,\n config: ConversationRelayProviderConfig\n ) {\n super(channel);\n this.logger = channel.getLoggerInternal();\n this.config = config;\n this.tacConfig = tacConfig;\n this.twimlBuilder = new TwiMLBuilderConversationRelay(tacConfig, config, this.logger);\n this.streamTasks = new Map();\n this.webSocketConnections = new Map();\n this.promptQueues = new Map();\n this.initializationRetries = new Map();\n this.callSidToConversationId = new Map();\n }\n\n public override get channelName(): string {\n return 'VOICE';\n }\n\n /**\n * Get active WebSocket connection for a conversation\n */\n public override getWebSocket(conversationId: ConversationId): WebSocket | null {\n return this.webSocketConnections.get(conversationId) || null;\n }\n\n /**\n * Poll Conversation Orchestrator for the conversation ConversationRelay\n * created for `callSid`, then register the local session and WebSocket.\n * Runs in the background from `setup`, so those can exist before the\n * caller speaks.\n */\n private async initializeOrchestratedConversation(\n callSid: string,\n fromNumber: string | null,\n ws: WebSocket\n ): Promise<ConversationId> {\n const conversationClient = this.channel.getConversationClientInternal();\n if (!conversationClient) {\n throw new Error('Conversation client is required in orchestrated mode');\n }\n\n let conversations: Awaited<ReturnType<ConversationClient['listConversations']>> = [];\n\n for (let attempt = 0; attempt < POLL_ATTEMPTS; attempt++) {\n // ACTIVE only: a stale conversation on the same CallSid would break the\n // \"exactly 1\" check below.\n conversations = await conversationClient.listConversations({\n channelId: callSid,\n status: ['ACTIVE'],\n });\n if (conversations.length === 1) break;\n if (attempt < POLL_ATTEMPTS - 1) {\n this.logger.debug(\n { call_sid: callSid, attempt: attempt + 1, found: conversations.length },\n 'Conversation not ready yet, polling again'\n );\n const delayMs = Math.min(POLL_BASE_DELAY_MS * 2 ** attempt, POLL_MAX_DELAY_MS);\n await new Promise(resolve => setTimeout(resolve, delayMs));\n }\n }\n\n if (conversations.length !== 1) {\n throw new Error(\n `Expected exactly 1 conversation for callSid ${callSid}, ` +\n `but found ${conversations.length} after ${POLL_ATTEMPTS} attempts`\n );\n }\n\n const conversation = conversations[0]!;\n const conversationId = conversation.id as ConversationId;\n\n const participants = await conversationClient.listParticipants(conversationId);\n\n const customerParticipant = participants.find(p => p.type === 'CUSTOMER');\n const customerAddress =\n customerParticipant?.addresses?.find(a => a.channel === 'VOICE')?.address ??\n fromNumber ??\n undefined;\n const profileId: ProfileId | undefined = customerParticipant?.profileId\n ? (customerParticipant.profileId as ProfileId)\n : undefined;\n\n this.webSocketConnections.set(conversationId, ws);\n this.callSidToConversationId.set(callSid, conversationId);\n const session = this.channel.startConversationInternal(conversationId, profileId);\n // conversationId is the Orchestrator's, so record the CallSid too —\n // out-of-band call webhooks resolve via getConversationSessionByCallSid.\n session.callSid = callSid;\n\n if (customerAddress) {\n session.authorInfo = {\n address: customerAddress,\n };\n }\n\n const voiceCallbacks = this.channel.getVoiceCallbacks();\n if (voiceCallbacks.onWebSocketConnected) {\n voiceCallbacks.onWebSocketConnected({ conversationId });\n }\n\n return conversationId;\n }\n\n /**\n * Handle WebSocket connection from ConversationRelay\n */\n public override handleWebSocket(ws: WebSocket): void {\n let conversationId: ConversationId | null = null;\n let callSid: string | null = null;\n let fromNumber: string | null = null;\n let initializationFailed = false;\n // Background conversation lookup started on `setup`; cleared once claimed,\n // by the first message that needs a conversation or by the close handler.\n let initPromise: Promise<ConversationId> | null = null;\n\n /**\n * Resolve this connection's conversation, creating it on first use.\n *\n * Shared by `prompt` and `dtmf` because either can be the first message\n * that needs a conversation — a caller can press a digit before speaking,\n * and until the session and WebSocket are registered a handler has no way\n * to respond. Returns null when `setup` hasn't arrived yet (no callSid);\n * rejects when initialization fails, after recording the attempt so a\n * later message can retry up to MAX_INITIALIZATION_RETRIES.\n */\n const ensureConversation = async (): Promise<ConversationId | null> => {\n if (conversationId) {\n return conversationId;\n }\n const sid = callSid;\n if (!sid) {\n return null;\n }\n\n // Check retry limit before attempting initialization\n const retryCount = this.initializationRetries.get(sid) ?? 0;\n if (retryCount >= this.MAX_INITIALIZATION_RETRIES) {\n throw new Error(\n `Cannot process message - conversation initialization failed after ${retryCount} attempts for callSid ${sid}`\n );\n }\n\n try {\n if (initializationFailed) {\n this.logger.info(\n { call_sid: sid, retry_count: retryCount },\n 'Retrying conversation initialization after previous failure'\n );\n }\n\n if (!this.channel.isOrchestratorEnabledInternal()) {\n // Voice-only mode: use callSid as conversationId directly\n conversationId = sid as ConversationId;\n this.webSocketConnections.set(conversationId, ws);\n this.callSidToConversationId.set(sid, conversationId);\n const session = this.channel.startConversationInternal(conversationId);\n // Relay-only: conversationId === callSid.\n session.callSid = sid;\n\n if (fromNumber) {\n session.authorInfo = { address: fromNumber };\n }\n\n const voiceCallbacks = this.channel.getVoiceCallbacks();\n if (voiceCallbacks.onWebSocketConnected) {\n voiceCallbacks.onWebSocketConnected({ conversationId });\n }\n } else {\n // Await the lookup from `setup` — usually already done.\n // Stays visible to the close handler while awaited, so a\n // hangup mid-lookup still cleans up; cleared after so a\n // retry starts fresh and `close` uses conversationId.\n initPromise ??= this.initializeOrchestratedConversation(sid, fromNumber, ws);\n try {\n conversationId = await initPromise;\n } finally {\n initPromise = null;\n }\n }\n\n // Success! Clear retry count and failed flag\n initializationFailed = false;\n this.initializationRetries.delete(sid);\n this.logger.info(\n { conversation_id: conversationId, call_sid: sid },\n 'Conversation initialization succeeded'\n );\n\n trackEvent('Conversation Initialized', {\n account_sid: this.tacConfig.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n provider: this.providerId,\n orchestrator_enabled: this.tacConfig.isOrchestratorEnabled(),\n });\n\n return conversationId;\n } catch (err) {\n initializationFailed = true;\n this.initializationRetries.set(sid, retryCount + 1);\n this.logger.error(\n { err, call_sid: sid, retry_count: retryCount + 1 },\n 'Conversation initialization failed'\n );\n throw err;\n }\n };\n\n ws.on('message', (data: Buffer) => {\n (async (): Promise<void> => {\n try {\n const messageData = JSON.parse(data.toString()) as unknown;\n const result = WebSocketMessageSchema.safeParse(messageData);\n\n if (!result.success) {\n this.logger.debug(\n {\n validation_errors: result.error.issues.map(issue => ({\n path: issue.path.join('.'),\n message: issue.message,\n })),\n },\n 'Invalid or unrecognized WebSocket message, skipping'\n );\n return;\n }\n\n const message = result.data;\n\n switch (message.type) {\n case 'setup':\n callSid = message.callSid;\n fromNumber = message.from;\n\n // ConversationRelay creates the conversation at call-connect, so\n // start the lookup now and let it overlap the wait for the\n // caller's first utterance instead of delaying it.\n if (this.channel.isOrchestratorEnabledInternal()) {\n this.logger.debug(\n { call_sid: callSid },\n 'Starting background conversation initialization'\n );\n initPromise = this.initializeOrchestratedConversation(callSid, fromNumber, ws);\n // Marks it handled; whoever claims it still sees the rejection.\n void initPromise.catch(() => undefined);\n }\n\n {\n const voiceCallbacks = this.channel.getVoiceCallbacks();\n if (voiceCallbacks.onSetup) {\n voiceCallbacks.onSetup({\n callSid,\n from: message.from,\n to: message.to,\n customParameters: message.customParameters,\n });\n }\n }\n break;\n\n case 'prompt':\n await ensureConversation();\n\n if (conversationId) {\n const previousPrompt = this.promptQueues.get(conversationId) ?? Promise.resolve();\n const currentPrompt = previousPrompt\n .then(() => this.handlePromptMessage(conversationId!, message))\n .catch((err: unknown) => {\n this.channel.handleErrorInternal(\n err instanceof Error ? err : new Error(String(err)),\n {\n conversationId,\n message: data.toString(),\n }\n );\n });\n this.promptQueues.set(conversationId, currentPrompt);\n } else {\n this.logger.warn('Received prompt before conversation initialized');\n }\n break;\n\n case 'interrupt':\n if (conversationId) {\n this.handleInterruptMessage(conversationId, message);\n }\n break;\n\n case 'dtmf':\n // A keypress can be the caller's first input, so initialize the\n // conversation the same way a prompt does — without it the handler\n // has no session and no WebSocket to respond on. Unlike a prompt, a\n // failure here is logged rather than thrown: the digit is still\n // worth delivering, just without a conversation.\n try {\n await ensureConversation();\n } catch (err) {\n this.logger.warn(\n { err, call_sid: callSid },\n 'Conversation initialization failed on DTMF keypress, delivering digit without a conversation'\n );\n }\n\n await this.handleDtmfMessage(conversationId, callSid, message);\n break;\n\n default:\n this.logger.debug(\n {\n conversation_id: conversationId,\n message_type: (messageData as Record<string, unknown>)?.type,\n },\n 'Unhandled WebSocket event type'\n );\n break;\n }\n } catch (error) {\n this.channel.handleErrorInternal(\n error instanceof Error ? error : new Error(String(error)),\n {\n conversationId,\n callSid,\n message: data.toString(),\n }\n );\n }\n })().catch((err: unknown) => {\n this.logger.error({ err }, 'Unhandled error in WebSocket message handler');\n });\n });\n\n ws.on('close', () => {\n // Call ended before any prompt claimed the lookup. A promise can't be\n // cancelled, so adopt what it registers and tear that down, or the\n // WebSocket registration leaks. The conversation stays tracked (CLOSED).\n const pendingInit = initPromise;\n initPromise = null;\n if (pendingInit && !conversationId) {\n void pendingInit\n .then(async adoptedId => {\n await this.handleWebSocketDisconnect(adoptedId);\n if (callSid) this.callSidToConversationId.delete(callSid);\n })\n // No prompt ever arrived to surface a lookup failure, so log here.\n .catch((err: unknown) => {\n this.logger.error(\n { err, call_sid: callSid },\n 'Background conversation initialization failed after the call ended'\n );\n });\n }\n\n if (conversationId) {\n void this.handleWebSocketDisconnect(conversationId).catch((err: unknown) => {\n this.logger.error(\n { err, conversation_id: conversationId },\n 'WebSocket disconnect handler error'\n );\n });\n }\n if (callSid) {\n this.initializationRetries.delete(callSid);\n this.callSidToConversationId.delete(callSid);\n }\n });\n\n ws.on('error', (error: Error) => {\n this.channel.handleErrorInternal(error, { conversationId });\n });\n }\n\n /**\n * Handle WebSocket prompt message (user speech)\n */\n private async handlePromptMessage(\n conversationId: ConversationId,\n message: PromptMessage\n ): Promise<void> {\n const transcript = message.voicePrompt;\n\n // Start a new stream task so the AbortSignal is available to handlers.\n // startStreamTask() cancels any existing task internally.\n const streamTask = this.startStreamTask(conversationId);\n\n // Get session for memory retrieval\n const session = this.channel.getConversationSession(conversationId);\n\n // Retrieve memory if enabled via memoryMode\n const userMemory = session\n ? await this.channel.retrieveMemoryInternal(session, transcript)\n : undefined;\n\n const voiceCallbacks = this.channel.getVoiceCallbacks();\n if (voiceCallbacks.onPrompt) {\n await voiceCallbacks.onPrompt({\n conversationId,\n transcript,\n abortSignal: streamTask.controller.signal,\n ...(userMemory !== undefined && { userMemory }),\n ...(session !== undefined && { session }),\n });\n }\n }\n\n /**\n * Handle WebSocket interrupt message\n */\n private handleInterruptMessage(conversationId: ConversationId, message: InterruptMessage): void {\n const { utteranceUntilInterrupt, durationUntilInterruptMs } = message;\n\n // Check whether tokens were sent before cancelling (cancel deletes the entry)\n const streamTask = this.streamTasks.get(conversationId);\n const wasStreaming = streamTask?.hasSentTokens ?? false;\n\n // Cancel any in-flight stream task on interrupt\n const cancelled = this.cancelStreamTask(conversationId);\n if (cancelled) {\n this.logger.info(\n { conversation_id: conversationId },\n 'Cancelled stream task due to interrupt'\n );\n }\n\n // Finalize the interrupted token stream so ConversationRelay stops\n // waiting for more tokens. Only needed when tokens were actually sent;\n // sending last:true without a preceding stream creates a spurious empty turn.\n if (cancelled && wasStreaming) {\n const ws = this.webSocketConnections.get(conversationId);\n if (ws?.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify({ type: 'text', token: '', last: true }));\n } catch (err) {\n this.logger.debug(\n { conversation_id: conversationId, err },\n 'WebSocket closed before sending stream finalization'\n );\n }\n }\n }\n\n const voiceCallbacks = this.channel.getVoiceCallbacks();\n if (voiceCallbacks.onInterrupt) {\n voiceCallbacks.onInterrupt({\n conversationId,\n utteranceUntilInterrupt,\n durationUntilInterruptMs,\n });\n }\n\n trackEvent('Voice Interrupt', {\n account_sid: this.tacConfig.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n ...(durationUntilInterruptMs !== undefined && {\n duration_until_interrupt_ms: durationUntilInterruptMs,\n }),\n provider: this.providerId,\n orchestrator_enabled: this.tacConfig.isOrchestratorEnabled(),\n });\n }\n\n /**\n * Handle WebSocket DTMF message (caller keypress)\n */\n private async handleDtmfMessage(\n conversationId: ConversationId | null,\n callSid: string | null,\n message: DtmfMessage\n ): Promise<void> {\n const { digit } = message;\n\n // Never log the digit itself — callers type account numbers and PINs on the\n // keypad, and nothing downstream scrubs it.\n this.logger.debug({ conversation_id: conversationId, call_sid: callSid }, 'DTMF keypress');\n\n const voiceCallbacks = this.channel.getVoiceCallbacks();\n if (!voiceCallbacks.onDtmf) {\n return;\n }\n\n const session = conversationId\n ? this.channel.getConversationSession(conversationId)\n : undefined;\n\n await voiceCallbacks.onDtmf({\n conversationId: conversationId ?? undefined,\n callSid: callSid ?? undefined,\n digit,\n ...(session !== undefined && { session }),\n });\n }\n\n /**\n * Handle WebSocket disconnection. In orchestrated mode the conversation stays\n * tracked until the CLOSED webhook (so a follow-up call can reuse it); in\n * voice-only mode there is no such webhook, so it ends here.\n */\n private async handleWebSocketDisconnect(conversationId: ConversationId): Promise<void> {\n this.cancelStreamTask(conversationId);\n this.webSocketConnections.delete(conversationId);\n this.promptQueues.delete(conversationId);\n\n const voiceCallbacks = this.channel.getVoiceCallbacks();\n if (voiceCallbacks.onWebSocketDisconnected) {\n voiceCallbacks.onWebSocketDisconnected({ conversationId });\n }\n\n trackEvent('Websocket Disconnected', {\n account_sid: this.tacConfig.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n provider: this.providerId,\n orchestrator_enabled: this.tacConfig.isOrchestratorEnabled(),\n });\n\n if (!this.channel.isOrchestratorEnabledInternal()) {\n await this.channel.endConversationInternal(conversationId);\n }\n }\n\n /**\n * Send voice response via WebSocket\n */\n public override sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n try {\n const ws = this.webSocketConnections.get(conversationId);\n\n if (ws?.readyState !== WebSocket.OPEN) {\n throw new Error(`No active WebSocket connection for conversation ${conversationId}`);\n }\n\n const response: TextTokenMessage = {\n type: 'text',\n token: message,\n last: true,\n };\n\n ws.send(JSON.stringify(response));\n\n // If a handoff is pending, send the WS \"end\" message now that the\n // LLM's final response has been delivered to the caller.\n const session = this.channel.getConversationSession(conversationId);\n if (session?.pendingHandoffData) {\n try {\n ws.send(JSON.stringify(session.pendingHandoffData));\n delete session.pendingHandoffData;\n } catch (err) {\n this.logger.warn(\n { err, conversation_id: conversationId },\n 'WebSocket closed before sending handoff end message; caller will not be transferred'\n );\n }\n }\n\n return Promise.resolve();\n } catch (error) {\n this.channel.handleErrorInternal(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n message,\n metadata,\n });\n throw error;\n }\n }\n\n /**\n * Send a streaming voice response via WebSocket, token by token.\n *\n * Each chunk from the iterable is sent as a text token message with last: false.\n * After the iterable completes, a final empty marker with last: true is sent\n * only if at least one token was emitted. If the AbortSignal fires (e.g., user\n * interrupted), iteration stops and no final marker is sent (the interrupt\n * handler sends the finalization instead).\n *\n * @returns The accumulated full response text.\n */\n public override async sendStreamingResponse(\n conversationId: ConversationId,\n stream: AsyncIterable<string>,\n options?: { signal?: AbortSignal }\n ): Promise<string> {\n const ws = this.webSocketConnections.get(conversationId);\n\n if (ws?.readyState !== WebSocket.OPEN) {\n throw new Error(`No active WebSocket connection for conversation ${conversationId}`);\n }\n\n const activeTask = this.streamTasks.get(conversationId);\n const signal = options?.signal ?? activeTask?.controller.signal;\n let fullResponse = '';\n let hasSentTokens = false;\n\n if (signal?.aborted) {\n return fullResponse;\n }\n\n try {\n for await (const chunk of stream) {\n if (signal?.aborted) {\n break;\n }\n\n if (ws.readyState !== WebSocket.OPEN) {\n this.logger.info(\n { conversation_id: conversationId },\n 'WebSocket closed during streaming'\n );\n break;\n }\n\n fullResponse += chunk;\n const tokenMessage: TextTokenMessage = {\n type: 'text',\n token: chunk,\n last: false,\n };\n ws.send(JSON.stringify(tokenMessage));\n hasSentTokens = true;\n if (activeTask) {\n activeTask.hasSentTokens = true;\n }\n }\n\n if (!signal?.aborted && hasSentTokens && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'text', token: '', last: true }));\n }\n } catch (error) {\n this.channel.handleErrorInternal(error instanceof Error ? error : new Error(String(error)), {\n conversationId,\n });\n throw error;\n } finally {\n // Only clean up if we still own the active stream task.\n // A new prompt may have replaced it while we were unwinding.\n if (activeTask && this.streamTasks.get(conversationId) === activeTask) {\n this.completeStreamTask(conversationId);\n }\n }\n\n return fullResponse;\n }\n\n // =========================================================================\n // Stream Task Management\n //\n // ConversationRelay-specific: these track the AbortController for a text\n // token stream. Full-duplex audio transports have no equivalent, so this\n // stays off `VoiceProvider`.\n // =========================================================================\n\n /**\n * Start tracking a streaming task for a conversation\n *\n * @param conversationId - The conversation ID\n * @returns The stream task with its AbortController\n */\n public startStreamTask(conversationId: ConversationId): StreamTask {\n // Cancel any existing task\n this.cancelStreamTask(conversationId);\n\n const task: StreamTask = { controller: new AbortController(), hasSentTokens: false };\n this.streamTasks.set(conversationId, task);\n\n this.logger.debug({ conversation_id: conversationId }, 'Started stream task');\n return task;\n }\n\n /**\n * Cancel an active streaming task\n *\n * @param conversationId - The conversation ID\n * @returns true if a task was cancelled, false otherwise\n */\n public cancelStreamTask(conversationId: ConversationId): boolean {\n const task = this.streamTasks.get(conversationId);\n if (task) {\n task.controller.abort();\n this.streamTasks.delete(conversationId);\n this.logger.debug({ conversation_id: conversationId }, 'Cancelled stream task');\n return true;\n }\n return false;\n }\n\n /**\n * Complete a streaming task (remove from tracking)\n *\n * @param conversationId - The conversation ID\n */\n public completeStreamTask(conversationId: ConversationId): void {\n this.streamTasks.delete(conversationId);\n this.logger.debug({ conversation_id: conversationId }, 'Completed stream task');\n }\n\n /**\n * Check if a stream task is active\n *\n * @param conversationId - The conversation ID\n * @returns true if an active task exists\n */\n public hasActiveStreamTask(conversationId: ConversationId): boolean {\n const task = this.streamTasks.get(conversationId);\n return task !== undefined && !task.controller.signal.aborted;\n }\n\n // =========================================================================\n // Incoming Call Handling\n // =========================================================================\n\n /**\n * Generate the TwiML response for an incoming voice call.\n *\n * ConversationRelay automatically handles conversation creation and\n * participant management via the `conversationConfiguration` parameter.\n *\n * The WebSocket URL and default session-cleanup action URL are derived from\n * `TACConfig.voicePublicDomain` + `TACConfig.voiceWebsocketPath` /\n * `voiceActionPath`.\n *\n * TwiML fields are merged per-field, highest precedence first:\n * 1. Output of the customizer registered via\n * `VoiceChannel.onInboundCallTwiml(...)` if configured and `twimlRequest`\n * is given. (Application-owned.)\n * 2. `ConversationRelayProviderConfig.defaultTwimlOptions` — per-channel\n * defaults.\n * 3. `hostTwimlOptions` — per-call transport facts supplied by the host (the\n * code owning the route), e.g. a per-call `websocketUrl` with an affinity\n * token.\n * 4. TAC defaults: a fixed default welcomeGreeting, `conversationConfiguration`\n * from `TACConfig`, `actionUrl` resolved via Studio handoff (when\n * `studioHandoffFlowSid` is configured), else derived from\n * `TACConfig.voicePublicDomain` + `voiceActionPath`, and the `websocketUrl`\n * derived from `TACConfig.voicePublicDomain` + `voiceWebsocketPath`.\n *\n * Fields not set at a layer fall through to lower layers. Arrays (`languages`)\n * and nested objects (`customParameters`) replace wholesale when set at a\n * higher-priority layer. `websocketUrl` falls back to the `TACConfig`-derived\n * URL if unset at every layer.\n *\n * @param twimlRequest - Parsed Twilio webhook fields. Passed to the customizer\n * if one is configured on the channel.\n * @param options - Additional per-call inputs.\n * @param options.hostTwimlOptions - Per-call TwiML supplied by a custom\n * in-process host (e.g. an affinity-routed deployment injecting a per-call\n * `websocketUrl`), layered below `defaultTwimlOptions` and the application\n * customizer but above the TAC defaults.\n * @returns TwiML XML string for call connection.\n * @throws {Error} if either options layer isn't a\n * {@link VoiceTwiMLOptionsConversationRelay}.\n */\n public override async handleIncomingCall(\n twimlRequest?: TwiMLRequest,\n options?: { hostTwimlOptions?: VoiceTwiMLOptions }\n ): Promise<string> {\n const host = this.narrowTwimlOptions(options?.hostTwimlOptions, 'options.hostTwimlOptions');\n\n const onInboundCallTwimlHandler = this.channel.getInboundCallTwimlHandler();\n let customized: VoiceTwiMLOptionsConversationRelay | undefined;\n if (onInboundCallTwimlHandler && twimlRequest) {\n customized = this.narrowTwimlOptions(\n await onInboundCallTwimlHandler(twimlRequest),\n 'the onInboundCallTwiml customizer output'\n );\n }\n\n return this.twimlBuilder.build('handleIncomingCall', {\n host,\n perCall: customized,\n });\n }\n\n /**\n * Narrow provider-agnostic {@link VoiceTwiMLOptions} to this provider's\n * concrete shape. `VoiceProvider.handleIncomingCall` is typed against the\n * base so every provider can accept its own TwiML options, so the\n * ConversationRelay shape has to be established at runtime.\n *\n * @param value - Options from a caller or the application customizer.\n * @param label - What produced `value`, for the error message.\n */\n private narrowTwimlOptions(\n value: VoiceTwiMLOptions | undefined,\n label: string\n ): VoiceTwiMLOptionsConversationRelay | undefined {\n if (value === undefined) {\n return undefined;\n }\n const parsed = VoiceTwiMLOptionsConversationRelaySchema.safeParse(value);\n if (!parsed.success) {\n const errorMessage = parsed.error.issues\n .map(issue => `${issue.path.join('.')}: ${issue.message}`)\n .join(', ');\n throw new Error(\n `ConversationRelayProvider.handleIncomingCall requires ${label} to be a ` +\n `VoiceTwiMLOptionsConversationRelay: ${errorMessage}`\n );\n }\n return parsed.data;\n }\n\n // =========================================================================\n // Outbound Call Handling\n // =========================================================================\n\n /**\n * Overlay `perCall` onto `ConversationRelayProviderConfig.defaultCallOptions`.\n *\n * Per-field via key presence, the same convention `TwiMLBuilderBase.overlayFields`\n * uses for TwiML options — so a per-call `{ machineDetection: undefined }`\n * explicitly clears the channel default rather than falling through to it.\n *\n * The result is always validated, for two reasons: a combination only\n * reachable by layering — per-call clearing `machineDetection` while the\n * default set `asyncAmd` — must still fail instead of reaching Twilio, and\n * `ConversationRelayProviderConfigOptions` is a plain interface, so\n * `defaultCallOptions` has had no runtime validation of its own.\n */\n private mergeCallOptions(perCall: CallOptions | undefined): CallOptions | undefined {\n const defaults = this.config.defaultCallOptions;\n if (!defaults && !perCall) {\n return undefined;\n }\n\n const merged: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(defaults ?? {})) {\n if (value !== undefined) {\n merged[key] = value;\n }\n }\n for (const key of Object.keys(perCall ?? {})) {\n merged[key] = (perCall as Record<string, unknown>)[key];\n }\n return CallOptionsSchema.parse(merged);\n }\n\n /**\n * Build the extra arguments for `client.calls.create`.\n *\n * Layers, highest precedence first: this call's `callOptions`,\n * `ConversationRelayProviderConfig.defaultCallOptions`, then callback URLs\n * derived from `voicePublicDomain` + `voiceCallEventPath`.\n *\n * A URL is derived only when its handler is registered. That's a deliberate\n * deviation from `websocketUrl` / `actionUrl`, which derive unconditionally:\n * those are load-bearing, so a wrong one fails loudly on the first call,\n * whereas an unwanted call-event URL fails as silent 11200 alerts for a\n * feature nobody asked for. Set the URLs in `defaultCallOptions` when TAC\n * isn't serving the routes.\n */\n private buildCallParams(callOptions: CallOptions | undefined): Record<string, unknown> {\n const merged = this.mergeCallOptions(callOptions);\n const params = merged ? callOptionsToCreateParams(merged) : {};\n\n return this.applyCallEventCallbacks(params);\n }\n\n /**\n * Initiate an outbound voice conversation\n *\n * Places an outbound call with inline TwiML that connects to ConversationRelay.\n * The conversationConfiguration attribute tells CO to create and manage the\n * conversation during passive hydration. The session is initialized when the\n * background callSid lookup started at WebSocket setup finds it.\n *\n * TwiML fields are merged per-field, highest precedence first:\n * 1. `options.twimlOptions` — per-call overrides\n * 2. `ConversationRelayProviderConfig.defaultTwimlOptions` — channel-wide\n * defaults\n * 3. TAC defaults: welcome greeting, `conversationConfiguration` from\n * `TACConfig`, and `actionUrl` from Studio handoff (if configured), else\n * derived from `TACConfig.voicePublicDomain` + `voiceActionPath`.\n *\n * Calls-API parameters merge the same way:\n * 1. `options.callOptions` — per-call overrides\n * 2. `ConversationRelayProviderConfig.defaultCallOptions` — channel-wide\n * defaults\n * 3. Callback URLs derived from `TACConfig.voicePublicDomain` +\n * `voiceCallEventPath`, for handlers that are registered\n *\n * The WebSocket URL is derived from `TACConfig.voicePublicDomain` +\n * `TACConfig.voiceWebsocketPath`, unless overridden per-call via\n * `options.websocketUrl`.\n */\n public override async initiateOutboundConversation(\n options: InitiateVoiceConversationOptions\n ): Promise<InitiateVoiceConversationResult> {\n const validated = InitiateVoiceConversationOptionsSchema.parse(options);\n const fromNumber = this.tacConfig.phoneNumber;\n\n this.logger.info(\n { to: validated.to, from: fromNumber },\n 'Initiating outbound voice conversation'\n );\n\n try {\n // Outbound has no inbound customizer and no host layer; the per-call\n // override is options.twimlOptions. `options.websocketUrl` is the\n // dedicated per-call outbound override and wins over any websocketUrl\n // that came through the layered twimlOptions merge; both fall back to the\n // TACConfig-derived URL.\n const twiml = this.twimlBuilder.build('initiateOutboundConversation', {\n perCall: validated.twimlOptions,\n websocketUrl: validated.websocketUrl,\n });\n const callParams = this.buildCallParams(validated.callOptions);\n\n // The inline TwiML handed to Twilio, useful for debugging the\n // <Connect action> handoff target. customParameters values are masked —\n // they're arbitrary developer data (profile IDs, caller names), unlike\n // the WS/action URLs and conversation config.\n this.logger.debug(\n { twiml: redactTwimlParameters(twiml), to: maskAddress(validated.to) },\n 'Outbound call TwiML'\n );\n\n // Place the outbound call with inline TwiML\n const client = this.channel.getTwilioClientInternal();\n const call = await client.calls.create({\n to: validated.to,\n from: fromNumber,\n twiml,\n ...callParams,\n });\n\n this.logger.info(\n { call_sid: call.sid, to: maskAddress(validated.to) },\n 'Outbound voice call placed'\n );\n\n return { callSid: call.sid };\n } catch (error) {\n this.logger.error(\n { err: error, to: maskAddress(validated.to) },\n 'Failed to initiate outbound call'\n );\n this.channel.handleErrorInternal(error instanceof Error ? error : new Error(String(error)), {\n to: validated.to,\n });\n throw error;\n }\n }\n\n // =========================================================================\n // ConversationRelay Callback Handling\n // =========================================================================\n\n /**\n * Handle ConversationRelay callback from Twilio. Cleans up on call completion\n * in voice-only mode; in orchestrated mode the CO webhook owns cleanup.\n *\n * @param rawPayload - Callback payload from Twilio\n * @returns Response with status, content, and content type\n */\n public override async handleTwilioProviderCallback(\n rawPayload: Record<string, unknown>\n ): Promise<TwilioProviderCallbackResponse> {\n const parsed = ConversationRelayCallbackPayloadSchema.safeParse(rawPayload);\n if (!parsed.success) {\n this.logger.warn(\n { errors: parsed.error.issues },\n 'Invalid ConversationRelay callback payload'\n );\n return { status: 400, content: 'Invalid payload', contentType: 'text/plain' };\n }\n const payload = parsed.data;\n\n this.logger.debug(\n { call_sid: payload.CallSid, call_status: payload.CallStatus },\n 'ConversationRelay callback received'\n );\n\n if (payload.AccountSid !== this.tacConfig.accountSid) {\n this.logger.warn(\n { expected: this.tacConfig.accountSid, received: payload.AccountSid },\n 'ConversationRelay callback AccountSid mismatch, ignoring'\n );\n return { status: 403, content: 'Forbidden', contentType: 'text/plain' };\n }\n\n if (payload.CallStatus === 'completed' && !this.channel.isOrchestratorEnabledInternal()) {\n const conversationId = this.callSidToConversationId.get(payload.CallSid);\n if (conversationId) {\n this.callSidToConversationId.delete(payload.CallSid);\n await this.channel.endConversationInternal(conversationId);\n }\n }\n\n return { status: 200, content: 'OK', contentType: 'text/plain' };\n }\n\n // =========================================================================\n // ConversationRelay TwiML Generation\n // =========================================================================\n\n /**\n * Generate TwiML to connect a call to ConversationRelay.\n * Validates configuration with Zod before generating TwiML.\n *\n * @param config - ConversationRelay configuration (url, transcription, TTS, etc.)\n * @param options - Optional settings for parameters and the Connect verb\n * @returns TwiML XML string\n * @throws {Error} if config validation fails\n */\n public connectConversationRelay(\n config: ConversationRelayConfig,\n options?: { parameters?: CustomParameters; actionUrl?: string }\n ): string {\n // Validate configuration with Zod schema (consistent with project pattern)\n const validationResult = ConversationRelayConfigSchema.safeParse(config);\n\n if (!validationResult.success) {\n const errorMessage = validationResult.error.issues\n .map(issue => `${issue.path.join('.')}: ${issue.message}`)\n .join(', ');\n throw new Error(`Invalid ConversationRelay configuration: ${errorMessage}`);\n }\n\n const validatedConfig = validationResult.data;\n\n // Extract languages array (child elements, not attributes)\n const { languages, ...conversationRelayAttributes } = validatedConfig;\n\n // Filter out undefined values to keep TwiML clean\n const filteredConfig = filterUnsetValues(conversationRelayAttributes);\n\n // Build TwiML using SDK\n const response = new VoiceResponse();\n const connect = response.connect(options?.actionUrl ? { action: options.actionUrl } : {});\n const relay = connect.conversationRelay(filteredConfig);\n\n // Add language configurations as child <Language> elements\n if (languages && languages.length > 0) {\n for (const lang of languages) {\n // Filter out undefined values to satisfy exactOptionalPropertyTypes\n // Type assertion is safe here because we've already validated with Zod\n const filteredLang = filterUnsetValues(lang);\n relay.language(filteredLang as Parameters<typeof relay.language>[0]);\n }\n }\n\n // Add custom parameters as child <Parameter> elements\n if (options?.parameters) {\n for (const [name, value] of Object.entries(options.parameters)) {\n relay.parameter({ name, value: String(value) });\n }\n }\n\n return response.toString();\n }\n\n /**\n * Drop this provider's ConversationRelay transport state on channel shutdown.\n *\n * Note: WebSocket connections are managed by the server and closed there.\n * This method only cleans up internal provider state.\n */\n public override shutdown(): void {\n super.shutdown();\n this.streamTasks.clear();\n this.webSocketConnections.clear();\n this.promptQueues.clear();\n this.initializationRetries.clear();\n this.callSidToConversationId.clear();\n }\n}\n","import type { TACConfig } from '../../../lib/config';\nimport type { CallOptions, VoiceTwiMLOptionsConversationRelay } from '../../../types/index';\nimport type { BaseChannelOptions } from '../../base';\nimport type { VoiceChannel } from '../channel';\nimport type { VoiceProvider } from '../provider';\nimport { VoiceProviderConfig } from '../provider';\nimport { ConversationRelayProvider } from './provider';\n\n/**\n * Options accepted by {@link ConversationRelayProviderConfig}.\n *\n * `defaultTwimlOptions` is one of several TwiML layers that merge per-field;\n * see `ConversationRelayProvider.handleIncomingCall` (inbound) and\n * `ConversationRelayProvider.initiateOutboundConversation` (outbound) for the\n * full precedence order.\n */\nexport interface ConversationRelayProviderConfigOptions extends BaseChannelOptions {\n /**\n * Static `VoiceTwiMLOptionsConversationRelay` applied to every call (inbound and outbound).\n * Controls the TwiML inside `<ConversationRelay>` — voice, language,\n * transcription provider, welcomeGreeting, `<Language>` children, etc. Use\n * this when the same ConversationRelay configuration is correct for every call.\n *\n * Per-call inbound customization is registered via\n * `VoiceChannel.onInboundCallTwiml(...)` (not on this config).\n *\n * Note: `customParameters` and `languages` replace wholesale when a\n * higher-priority layer sets them.\n */\n defaultTwimlOptions?: VoiceTwiMLOptionsConversationRelay;\n\n /**\n * Static {@link CallOptions} applied to every outbound call — the\n * `calls.create` parameters, including the call-event callback URLs. This is\n * the layer to use for a custom server or non-default routes: URLs set here\n * override the ones TAC would derive from `voicePublicDomain` +\n * `voiceCallEventPath`.\n */\n defaultCallOptions?: CallOptions;\n}\n\n/**\n * Configuration for {@link ConversationRelayProvider}, the default\n * {@link VoiceChannel} provider.\n *\n * TwiML configuration layers (highest precedence first):\n *\n * Inbound calls (`handleIncomingCall`):\n * 1. Output of the customizer registered via\n * `VoiceChannel.onInboundCallTwiml(...)` [optional]\n * 2. `defaultTwimlOptions` [optional]\n * 3. `handleIncomingCall(hostTwimlOptions)` [optional]\n * 4. TAC defaults\n *\n * Outbound calls (`initiateOutboundConversation`):\n * 1. `InitiateVoiceConversationOptions.twimlOptions` [optional]\n * 2. `defaultTwimlOptions` [optional]\n * 3. TAC defaults\n *\n * Calls-API parameters (`initiateOutboundConversation`):\n * 1. `InitiateVoiceConversationOptions.callOptions` [optional]\n * 2. `defaultCallOptions` [optional]\n * 3. Callback URLs derived from `TACConfig.voicePublicDomain` +\n * `voiceCallEventPath`, for handlers that are registered\n *\n * All layers merge per-field via key presence — only fields a layer explicitly\n * sets override lower layers. Arrays (`languages`) and nested objects\n * (`customParameters`) replace wholesale when set.\n *\n * Per-call inbound customization is registered via\n * `VoiceChannel.onInboundCallTwiml(...)` (not on this config).\n */\nexport class ConversationRelayProviderConfig extends VoiceProviderConfig {\n /**\n * Static `VoiceTwiMLOptionsConversationRelay` for the TwiML inside `<ConversationRelay>`, applied\n * to every call (inbound and outbound).\n */\n public readonly defaultTwimlOptions?: VoiceTwiMLOptionsConversationRelay;\n\n /** Static {@link CallOptions} applied to every outbound call. */\n public readonly defaultCallOptions?: CallOptions;\n\n constructor(options?: ConversationRelayProviderConfigOptions) {\n super(options);\n if (options?.defaultTwimlOptions !== undefined) {\n this.defaultTwimlOptions = options.defaultTwimlOptions;\n }\n if (options?.defaultCallOptions !== undefined) {\n this.defaultCallOptions = options.defaultCallOptions;\n }\n }\n\n public override createProvider(channel: VoiceChannel, tacConfig: TACConfig): VoiceProvider {\n return new ConversationRelayProvider(channel, tacConfig, this);\n }\n}\n\n/**\n * Pre-provider-split name for {@link ConversationRelayProviderConfigOptions} —\n * the shape `new VoiceChannel(tac, {...})` accepts. Kept so the shipped public\n * export stays valid across the provider refactor.\n *\n * @deprecated Use {@link ConversationRelayProviderConfigOptions} instead.\n */\nexport type VoiceChannelConfig = ConversationRelayProviderConfigOptions;\n","import type { WebSocket } from 'ws';\nimport Twilio from 'twilio';\nimport {\n ChannelType,\n ConversationId,\n ConversationSession,\n ProfileId,\n CustomParameters,\n ConversationRelayConfig,\n ConversationRelayCallbackPayload,\n TwilioProviderCallbackResponse,\n InitiateVoiceConversationOptions,\n VoiceTwiMLOptionsConversationRelay,\n TwiMLRequest,\n ConversationWebhookPayload,\n CallEventKind,\n CallStatusEvent,\n AmdEvent,\n RecordingEvent,\n callStatusEventFromForm,\n amdEventFromForm,\n recordingEventFromForm,\n} from '../../types/index';\nimport type { InitiateVoiceConversationResult } from '../../types/conversation';\nimport { BaseChannel, BaseChannelEvents, BaseChannelOptions } from '../base';\nimport type { ConversationClient } from '../../clients/conversation';\nimport type { TAC } from '../../lib/tac';\nimport type { TACConfig } from '../../lib/config';\nimport { warnDeprecated } from '../../lib/deprecation';\nimport { trackEvent } from '../../lib/analytics';\nimport type { Logger } from '../../lib/logger';\nimport type { TACMemoryResponse } from '../../lib/tac-memory-response';\nimport { ConversationRelayProviderConfig } from './conversation-relay/config';\nimport type { ConversationRelayProviderConfigOptions } from './conversation-relay/config';\nimport { ConversationRelayProvider } from './conversation-relay/provider';\nimport type { StreamTask } from './conversation-relay/provider';\nimport type { VoiceProvider } from './provider';\nimport { VoiceProviderConfig } from './provider';\n\n/**\n * Callback that produces per-call overrides for the TwiML inside\n * `<ConversationRelay>` on inbound calls. Receives a framework-neutral\n * {@link TwiMLRequest} and returns {@link VoiceTwiMLOptionsConversationRelay}.\n *\n * Stays typed against the ConversationRelay subtype rather than the\n * provider-agnostic base ({@link VoiceProvider.handleIncomingCall} is widened\n * to the base, this consumer-facing surface is not): the base has only\n * optional shared fields, so TypeScript's object-literal freshness check\n * rejects the documented inline form `async () => ({ voice: '...' })` for\n * having no properties in common with it. It widens once a second\n * inbound-capable provider exists.\n */\nexport type InboundCallTwimlHandler = (\n req: TwiMLRequest\n) => Promise<VoiceTwiMLOptionsConversationRelay>;\n\n/** Handler for Twilio `statusCallback` webhooks. */\nexport type CallStatusHandler = (event: CallStatusEvent) => Promise<void> | void;\n\n/** Handler for Twilio `asyncAmdStatusCallback` webhooks. */\nexport type AmdHandler = (event: AmdEvent) => Promise<void> | void;\n\n/** Handler for Twilio `recordingStatusCallback` webhooks. */\nexport type RecordingHandler = (event: RecordingEvent) => Promise<void> | void;\n\n/** One ConversationRelay keypress, as delivered to a {@link DtmfHandler}. */\nexport interface DtmfEvent {\n /**\n * Undefined only when the keypress beat conversation setup: `dtmf` before\n * ConversationRelay's `setup`, or an orchestrated-mode lookup that failed.\n */\n conversationId: ConversationId | undefined;\n /** Undefined only before ConversationRelay's `setup` message. */\n callSid: string | undefined;\n /** The key pressed: `0`-`9`, `*`, `#`, or `A`-`D`. */\n digit: string;\n /** Present whenever `conversationId` is. */\n session?: ConversationSession;\n}\n\n/** Handler for ConversationRelay `dtmf` messages (caller keypresses). */\nexport type DtmfHandler = (event: DtmfEvent) => Promise<void> | void;\n\n/**\n * Voice channel event callbacks extending base callbacks\n */\nexport interface VoiceChannelEvents extends BaseChannelEvents {\n onSetup?: (data: {\n callSid: string;\n from: string;\n to: string;\n customParameters: Record<string, unknown> | undefined;\n }) => void;\n onPrompt?: (data: {\n conversationId: ConversationId;\n transcript: string;\n userMemory?: TACMemoryResponse;\n session?: ConversationSession;\n abortSignal: AbortSignal;\n }) => Promise<void> | void;\n onInterrupt?: (data: {\n conversationId: ConversationId;\n utteranceUntilInterrupt: string | undefined;\n durationUntilInterruptMs: number | undefined;\n }) => void;\n /** Caller keypress. See {@link VoiceChannel.onDtmf}. */\n onDtmf?: DtmfHandler;\n /**\n * Fired once the session and WebSocket registration exist — in orchestrated\n * mode possibly before the first prompt, since the lookup starts at setup.\n */\n onWebSocketConnected?: (data: { conversationId: ConversationId }) => void;\n onWebSocketDisconnected?: (data: { conversationId: ConversationId }) => void;\n}\n\n/**\n * Voice Channel for handling voice-based conversations over a WebSocket.\n *\n * The real-time media transport lives on a {@link VoiceProvider} — by default\n * {@link ConversationRelayProvider}. `VoiceChannel` keeps the Calls-API\n * lifecycle (call events, hangup), conversation bookkeeping and webhook\n * processing, and delegates everything transport-shaped to the provider.\n */\nexport class VoiceChannel extends BaseChannel {\n private readonly provider: VoiceProvider;\n private readonly voiceCallbacks: VoiceChannelEvents;\n private twilioClient: ReturnType<typeof Twilio> | undefined;\n private onInboundCallTwimlHandler: InboundCallTwimlHandler | undefined;\n private onCallStatusHandler: CallStatusHandler | undefined;\n private onAmdHandler: AmdHandler | undefined;\n private onRecordingHandler: RecordingHandler | undefined;\n\n /**\n * @param tac - The owning {@link TAC} instance.\n * @param options - Either a {@link VoiceProviderConfig} selecting the media\n * provider, or a plain object — shorthand for\n * {@link ConversationRelayProviderConfig}, which is what TAC builds when no\n * provider config is given.\n */\n constructor(tac: TAC, options?: VoiceProviderConfig | ConversationRelayProviderConfigOptions) {\n super(tac, VoiceChannel.toBaseOptions(options));\n this.voiceCallbacks = {};\n this.provider = VoiceChannel.toProviderConfig(options).createProvider(this, this.config);\n }\n\n /**\n * The {@link BaseChannelOptions} to hand `BaseChannel`. A provider config\n * replays the options it retained (with its resolved `memoryMode`, which is\n * writable after construction); a plain options object is passed through. Both\n * paths therefore honour `dedupCapacity` and friends identically.\n */\n private static toBaseOptions(\n options?: VoiceProviderConfig | ConversationRelayProviderConfigOptions\n ): BaseChannelOptions | undefined {\n if (options === undefined) {\n return undefined;\n }\n if (options instanceof VoiceProviderConfig) {\n return { ...options.channelOptions, memoryMode: options.memoryMode };\n }\n return options;\n }\n\n /**\n * Resolve the provider config: an explicit {@link VoiceProviderConfig} as-is,\n * anything else wrapped as a {@link ConversationRelayProviderConfig}.\n */\n private static toProviderConfig(\n options?: VoiceProviderConfig | ConversationRelayProviderConfigOptions\n ): VoiceProviderConfig {\n return options instanceof VoiceProviderConfig\n ? options\n : new ConversationRelayProviderConfig(options);\n }\n\n /**\n * Register a callback that produces per-call overrides for the TwiML inside\n * `<ConversationRelay>` on inbound calls.\n *\n * The callback receives a framework-neutral {@link TwiMLRequest} (parsed from\n * the Twilio webhook form) and returns\n * {@link VoiceTwiMLOptionsConversationRelay}. Fields the\n * callback explicitly sets override `defaultTwimlOptions` and TAC defaults;\n * unset fields fall through.\n *\n * @example\n * ```typescript\n * voiceChannel.onInboundCallTwiml(async req => {\n * if (req.callerCountry === 'MX') {\n * return { language: 'es-MX', welcomeGreeting: '¡Hola!' };\n * }\n * return {};\n * });\n * ```\n *\n * Outbound calls don't use this — pass per-call TwiML via\n * `InitiateVoiceConversationOptions.twimlOptions` directly.\n */\n public onInboundCallTwiml(callback: InboundCallTwimlHandler): void {\n this.onInboundCallTwimlHandler = callback;\n }\n\n /**\n * Register a handler for Twilio `statusCallback` webhooks.\n *\n * This is the Calls-API status callback (call disposition), not the\n * ConversationRelay session callback — see\n * {@link handleTwilioProviderCallback}.\n *\n * Registering does two things: it stores the handler, and it makes later\n * outbound calls pass `statusCallback` to `calls.create`. With no handler\n * registered TAC omits that parameter, so Twilio has nowhere to post and the\n * event never arrives.\n *\n * Twilio reports only the terminal event by default, which covers every\n * disposition; set `CallOptions.statusCallbackEvent` for ringing/answered.\n *\n * @example\n * ```typescript\n * voiceChannel.onCallStatus(async event => {\n * if (event.isUnreached) {\n * // queue a retry\n * }\n * });\n * ```\n */\n public onCallStatus(callback: CallStatusHandler): void {\n this.onCallStatusHandler = callback;\n }\n\n /**\n * Register a handler for Twilio `asyncAmdStatusCallback` webhooks.\n *\n * Registering makes later outbound calls pass `asyncAmdStatusCallback` to\n * `calls.create`; without a handler TAC omits it and Twilio has nowhere to\n * post the result. It does not enable detection — that's per-call, via\n * `CallOptions.machineDetection` and `asyncAmd`, both of which are required\n * for this to fire (at most once per call).\n *\n * @example\n * ```typescript\n * voiceChannel.onAmd(async event => {\n * if (event.isMachine) {\n * await voiceChannel.endCall(event.callSid); // voicemail → hang up\n * }\n * });\n * ```\n */\n public onAmd(callback: AmdHandler): void {\n this.onAmdHandler = callback;\n }\n\n /**\n * Register a handler for Twilio `recordingStatusCallback` webhooks.\n *\n * Registering makes later outbound calls pass `recordingStatusCallback` to\n * `calls.create`; without a handler TAC omits it and Twilio has nowhere to\n * post. It does not start recording — that's `CallOptions.record`, which is\n * required for this to fire.\n *\n * @example\n * ```typescript\n * voiceChannel.onRecording(async event => {\n * if (event.recordingStatus === 'completed') {\n * // store event.recordingUrl\n * }\n * });\n * ```\n */\n public onRecording(callback: RecordingHandler): void {\n this.onRecordingHandler = callback;\n }\n\n /**\n * Register a handler for DTMF keypresses, called once per key in order.\n *\n * Requires `dtmfDetection: true` on the ConversationRelay config — without it\n * Twilio sends nothing and this never fires. Digits aren't buffered, so\n * accumulating a multi-digit entry is the handler's job.\n *\n * A keypress initializes the conversation just as a prompt does, since a\n * caller can type without ever speaking; if that fails the digit still\n * arrives, with `conversationId` and `session` undefined. Keypresses don't\n * cancel in-flight streaming on their own — that's a separate `interrupt`\n * message, sent when `interruptible` includes `dtmf`.\n *\n * @example\n * ```typescript\n * const digits = new Map<string, string>();\n *\n * voiceChannel.onDtmf(({ conversationId, digit }) => {\n * if (!conversationId) return;\n * digits.set(conversationId, (digits.get(conversationId) ?? '') + digit);\n * });\n * ```\n */\n public onDtmf(callback: DtmfHandler): void {\n this.voiceCallbacks.onDtmf = callback;\n }\n\n // =========================================================================\n // Provider-facing surface\n //\n // `BaseChannel`'s state is `protected`, and a `VoiceProvider` is not a\n // subclass of `VoiceChannel`, so relocated transport logic genuinely cannot\n // reach it. These forwarders open exactly what a provider needs and nothing\n // more; they are `@internal` and are not exported from the package root.\n // =========================================================================\n\n /**\n * The registered call-event handlers, for a `VoiceProvider` deciding which\n * callback URLs to derive. A provider is not a subclass of `VoiceChannel`,\n * so the `private` fields are genuinely out of reach without this.\n *\n * @internal\n */\n public getCallEventHandlers(): {\n status: CallStatusHandler | undefined;\n amd: AmdHandler | undefined;\n recording: RecordingHandler | undefined;\n } {\n return {\n status: this.onCallStatusHandler,\n amd: this.onAmdHandler,\n recording: this.onRecordingHandler,\n };\n }\n\n /**\n * This channel's `TACConfig`, for a `VoiceProvider` deriving default URLs.\n * `BaseChannel.config` is `protected`, and a provider is not a subclass.\n *\n * @internal\n */\n public getTacConfig(): TACConfig {\n return this.config;\n }\n\n /**\n * This channel's logger, so a provider's relocated logic keeps logging under\n * the same name it did when it lived on `VoiceChannel`.\n *\n * @internal\n */\n public getLoggerInternal(): Logger {\n return this.logger;\n }\n\n /**\n * The Conversation Orchestrator client, or `null` in ConversationRelay-only\n * mode.\n *\n * @internal\n */\n public getConversationClientInternal(): ConversationClient | null {\n return this.conversationClient;\n }\n\n /**\n * The lazily built Twilio REST client, for a provider placing outbound calls.\n *\n * @internal\n */\n public getTwilioClientInternal(): ReturnType<typeof Twilio> {\n return this.getTwilioClient();\n }\n\n /**\n * Whether Conversation Orchestrator is configured. Providers branch on this\n * to decide who owns conversation cleanup.\n *\n * @internal\n */\n public isOrchestratorEnabledInternal(): boolean {\n return this.tac.isOrchestratorEnabled();\n }\n\n /**\n * Voice event callbacks registered via {@link on}, for a provider to fire.\n *\n * @internal\n */\n public getVoiceCallbacks(): VoiceChannelEvents {\n return this.voiceCallbacks;\n }\n\n /**\n * The inbound-TwiML customizer registered via {@link onInboundCallTwiml}, for\n * a provider building the inbound response.\n *\n * @internal\n */\n public getInboundCallTwimlHandler(): InboundCallTwimlHandler | undefined {\n return this.onInboundCallTwimlHandler;\n }\n\n /**\n * Start tracking a conversation session. Forwards to\n * `BaseChannel.startConversation`.\n *\n * @internal\n */\n public startConversationInternal(\n conversationId: ConversationId,\n profileId?: ProfileId\n ): ConversationSession {\n return this.startConversation(conversationId, profileId);\n }\n\n /**\n * End a tracked conversation session. Forwards to\n * `BaseChannel.endConversation`.\n *\n * @internal\n */\n public endConversationInternal(conversationId: ConversationId): Promise<void> {\n return this.endConversation(conversationId);\n }\n\n /**\n * Retrieve memory when `memoryMode` calls for it. Forwards to\n * `BaseChannel.retrieveMemoryIfEnabled`.\n *\n * @internal\n */\n public retrieveMemoryInternal(\n session: ConversationSession,\n query?: string\n ): Promise<TACMemoryResponse | undefined> {\n return this.retrieveMemoryIfEnabled(session, query);\n }\n\n /**\n * Report an error through the channel's `onError` callback and logger.\n * Forwards to `BaseChannel.handleError`.\n *\n * @internal\n */\n public handleErrorInternal(error: Error, context?: Record<string, unknown>): void {\n this.handleError(error, context);\n }\n\n private getTwilioClient(): ReturnType<typeof Twilio> {\n if (!this.twilioClient) {\n this.twilioClient = Twilio(this.config.apiKey, this.config.apiSecret, {\n accountSid: this.config.accountSid,\n });\n }\n return this.twilioClient;\n }\n\n public get channelType(): ChannelType {\n return 'voice';\n }\n\n /**\n * Register event callbacks (override for Voice-specific events)\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Generic event callback needs to accept any args\n public override on(event: string, callback: (...args: any[]) => void): void {\n switch (event) {\n case 'setup':\n this.voiceCallbacks.onSetup = callback;\n break;\n case 'prompt':\n this.voiceCallbacks.onPrompt = callback;\n break;\n case 'interrupt':\n this.voiceCallbacks.onInterrupt = callback;\n break;\n case 'dtmf':\n this.voiceCallbacks.onDtmf = callback;\n break;\n case 'webSocketConnected':\n this.voiceCallbacks.onWebSocketConnected = callback;\n break;\n case 'webSocketDisconnected':\n this.voiceCallbacks.onWebSocketDisconnected = callback;\n break;\n default:\n // Delegate to parent for base events\n super.on(event, callback);\n break;\n }\n }\n\n /**\n * Process conversation webhooks for cleanup.\n *\n * Voice channel processes CONVERSATION_UPDATED events:\n * - CLOSED status: Clean up local session state\n *\n * Note: Conversation tracking uses instance-local memory. In multi-instance\n * deployments, webhooks may route to a different instance, preventing cleanup.\n *\n * @param payload - Raw webhook event data from Twilio\n * @param idempotencyToken - Optional Twilio idempotency token from request headers\n */\n public async processWebhook(payload: unknown, idempotencyToken?: string): Promise<void> {\n try {\n const result = this.preprocessWebhook(payload, idempotencyToken);\n if (!result) {\n return;\n }\n\n const { webhookData, eventType, conversationId } = result;\n\n switch (eventType) {\n case 'CONVERSATION_UPDATED':\n this.logger.debug(\n { conversation_id: conversationId, status: webhookData.data?.status },\n 'Handling CONVERSATION_UPDATED'\n );\n await this.handleConversationUpdated(webhookData);\n break;\n\n default:\n this.logger.debug(\n {\n event_type: eventType,\n raw_event_type: webhookData.eventType,\n conversation_id: conversationId,\n },\n 'Unhandled event type - this event will be ignored'\n );\n }\n\n this.logger.debug({ event_type: eventType }, 'Webhook processing completed');\n } catch (error) {\n // Remove the token so retries are not blocked\n if (idempotencyToken) {\n this.removeWebhookToken(idempotencyToken);\n }\n this.handleError(error instanceof Error ? error : new Error(String(error)), { payload });\n }\n }\n\n /**\n * Handle conversation updated event\n */\n private async handleConversationUpdated(payload: ConversationWebhookPayload): Promise<void> {\n const conversationId = this.extractConversationId(payload);\n\n if (!conversationId) {\n throw new Error('Missing conversation ID in conversation.updated event');\n }\n\n // Check if conversation is closed\n if (payload.data?.status === 'CLOSED') {\n this.logger.debug(\n { conversation_id: conversationId, status: payload.data.status },\n 'Conversation closed, cleaning up'\n );\n await this.endConversation(conversationId);\n } else if (payload.data?.status === 'INACTIVE') {\n // \"once\" mode: drop the cache so the next message re-fetches.\n this.invalidateCachedMemory(conversationId);\n }\n }\n\n /**\n * Get active WebSocket connection for a conversation\n */\n public getWebsocket(conversationId: ConversationId): WebSocket | null {\n return this.provider.getWebSocket(conversationId);\n }\n\n /**\n * Hand one WebSocket connection to the active provider, which drives its\n * lifecycle from accept to disconnect.\n *\n * @param ws - The accepted WebSocket, from ConversationRelay or whatever\n * transport the active provider serves.\n */\n public handleWebSocketConnection(ws: WebSocket): void {\n // Socket-open half of the Websocket Connected/Disconnected pair. Tracked\n // here rather than in a provider so every transport is covered; no\n // conversation identifier exists yet at this point.\n trackEvent('Websocket Connected', {\n account_sid: this.config.accountSid,\n channel: 'voice',\n provider: this.provider.providerId,\n orchestrator_enabled: this.config.isOrchestratorEnabled(),\n });\n\n // A provider may serve the socket synchronously or await an upstream\n // handshake first. Owning the returned promise here keeps an async\n // provider from producing an unhandled rejection.\n const result = this.provider.handleWebSocket(ws);\n if (result instanceof Promise) {\n void result.catch((err: unknown) => {\n this.logger.error({ err }, 'WebSocket handler error');\n });\n }\n }\n\n /**\n * Send voice response via WebSocket\n */\n public async sendResponse(\n conversationId: ConversationId,\n message: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n await this.provider.sendResponse(conversationId, message, metadata);\n trackEvent('Response Sent', {\n account_sid: this.config.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n response_type: 'full',\n provider: this.provider.providerId,\n orchestrator_enabled: this.config.isOrchestratorEnabled(),\n });\n }\n\n /**\n * Send a streaming voice response through the active provider's transport,\n * token by token. Delegates to the active provider — see\n * {@link ConversationRelayProvider.sendStreamingResponse} for the token\n * protocol and abort semantics.\n *\n * @param conversationId - Conversation whose transport receives the tokens.\n * @param stream - Async iterable of text chunks to relay as they arrive.\n * @param options - Additional per-call inputs.\n * @param options.signal - Aborts the stream mid-flight, e.g. when the caller\n * interrupts.\n * @returns The accumulated full response text.\n */\n public async sendStreamingResponse(\n conversationId: ConversationId,\n stream: AsyncIterable<string>,\n options?: { signal?: AbortSignal }\n ): Promise<string> {\n const fullResponse = await this.provider.sendStreamingResponse(conversationId, stream, options);\n\n // Empty means nothing reached the caller — an immediate abort, say — so\n // there is no response to report.\n if (fullResponse) {\n trackEvent('Response Sent', {\n account_sid: this.config.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n response_type: 'streaming',\n provider: this.provider.providerId,\n orchestrator_enabled: this.config.isOrchestratorEnabled(),\n });\n }\n\n return fullResponse;\n }\n\n // =========================================================================\n // Incoming Call Handling\n // =========================================================================\n\n /**\n * Generate the response for an incoming voice call. Delegates to the active\n * provider — see {@link ConversationRelayProvider.handleIncomingCall} for the\n * full TwiML merge/precedence rules (only meaningful for that provider; a\n * provider with no inbound story declines instead).\n *\n * @param twimlRequest - Parsed Twilio webhook fields. Passed to the customizer\n * registered via {@link onInboundCallTwiml}, if one is configured.\n * @param options - Additional per-call inputs.\n * @param options.hostTwimlOptions - Per-call TwiML supplied by a custom\n * in-process host (e.g. an affinity-routed deployment injecting a per-call\n * `websocketUrl`). Typed against the ConversationRelay subtype for the same\n * reason as {@link InboundCallTwimlHandler}.\n * @returns TwiML XML string for call connection.\n */\n public async handleIncomingCall(\n twimlRequest?: TwiMLRequest,\n options?: { hostTwimlOptions?: VoiceTwiMLOptionsConversationRelay }\n ): Promise<string> {\n return this.provider.handleIncomingCall(twimlRequest, options);\n }\n\n // =========================================================================\n // Outbound Call Handling\n // =========================================================================\n\n /**\n * Initiate an outbound voice conversation. Delegates to the active provider —\n * see {@link ConversationRelayProvider.initiateOutboundConversation} for the\n * TwiML and Calls-API merge/precedence rules.\n *\n * {@link ConversationRelayProvider} and `OpenAIRealtimeProvider` place\n * outbound calls; any other provider declines.\n *\n * @param options - Destination, per-call TwiML and Calls-API overrides.\n * `OpenAIRealtimeProvider` additionally accepts a per-call `sessionConfig`.\n * Each provider validates against its own schema and rejects the other's.\n * @returns The placed call's `callSid`.\n */\n public async initiateOutboundConversation(\n options: InitiateVoiceConversationOptions\n ): Promise<InitiateVoiceConversationResult> {\n return this.provider.initiateOutboundConversation(options);\n }\n\n // =========================================================================\n // Provider Callback Handling\n // =========================================================================\n\n /**\n * Handle the provider's own out-of-band lifecycle webhook from Twilio.\n *\n * Not every provider has one; those that don't inherit a plain 200\n * acknowledgement. ConversationRelay posts here when a session ends, and\n * cleans up on call completion in voice-only mode — in orchestrated mode the\n * CO webhook owns cleanup.\n *\n * @param payload - Raw callback payload from Twilio; the provider validates it.\n * @returns Response with status, content, and content type\n */\n public async handleTwilioProviderCallback(\n payload: Record<string, unknown>\n ): Promise<TwilioProviderCallbackResponse> {\n return this.provider.handleTwilioProviderCallback(payload);\n }\n\n /**\n * @deprecated Use {@link VoiceChannel.handleTwilioProviderCallback} instead.\n */\n public async handleConversationRelayCallback(\n payload: ConversationRelayCallbackPayload\n ): Promise<TwilioProviderCallbackResponse> {\n warnDeprecated('handleConversationRelayCallback', 'handleTwilioProviderCallback');\n return this.handleTwilioProviderCallback(payload);\n }\n\n // =========================================================================\n // Call Event Handling (status callback, async AMD, recording)\n // =========================================================================\n\n /**\n * Whether a call-webhook payload belongs to the configured account.\n *\n * Twilio signature validation already gates the route; this is defense in\n * depth. A payload with no `AccountSid` is allowed through.\n *\n * Subaccounts: events carry the SID the call was placed on, so configure TAC\n * with that account or its events get dropped here.\n */\n private callEventAccountOk(form: Record<string, string>): boolean {\n const accountSid = form['AccountSid'];\n if (accountSid && accountSid !== this.config.accountSid) {\n this.logger.warn(\n { expected: this.config.accountSid, received: accountSid },\n 'Call event AccountSid mismatch, ignoring'\n );\n return false;\n }\n return true;\n }\n\n /**\n * Parse a call-event webhook form and dispatch it to its handler.\n *\n * Returns 400 when the payload can't be parsed (no `CallSid`) or the handler\n * throws — better than handing Twilio a 200 for an event that wasn't\n * processed. Everything else, including no handler registered and an\n * account mismatch, is a 200 no-op.\n */\n private async dispatchCallEvent<T>(\n kind: CallEventKind,\n form: Record<string, string>,\n handler: ((event: T) => Promise<void> | void) | undefined,\n parse: (form: Record<string, string>) => T,\n logFields: (event: T) => Record<string, unknown>\n ): Promise<{ status: number; content: string; contentType: string }> {\n const ok = { status: 200, content: 'OK', contentType: 'text/plain' };\n if (!handler || !this.callEventAccountOk(form)) {\n return ok;\n }\n\n try {\n const event = parse(form);\n this.logger.debug(logFields(event), `Call ${kind} event received`);\n await handler(event);\n } catch (error) {\n this.logger.error({ err: error, kind }, 'Failed to process call event callback');\n return { status: 400, content: 'Bad Request', contentType: 'text/plain' };\n }\n return ok;\n }\n\n /**\n * Handle a Twilio `statusCallback` webhook.\n *\n * The developer routes the request here (`TACServer` does this automatically\n * for its `/status` call-event route). Parsed into a {@link CallStatusEvent}\n * and dispatched to the {@link onCallStatus} handler. No-op if no handler is\n * registered.\n *\n * @param form - Raw form data from the webhook request.\n */\n public async handleCallStatusEvent(\n form: Record<string, string>\n ): Promise<{ status: number; content: string; contentType: string }> {\n return this.dispatchCallEvent(\n 'status',\n form,\n this.onCallStatusHandler,\n callStatusEventFromForm,\n event => ({ call_sid: event.callSid, call_status: event.callStatus })\n );\n }\n\n /**\n * Handle a Twilio `asyncAmdStatusCallback` webhook.\n *\n * The developer routes the request here (`TACServer` does this automatically\n * for its `/amd` call-event route). Parsed into an {@link AmdEvent} and\n * dispatched to the {@link onAmd} handler. No-op if no handler is registered.\n *\n * @param form - Raw form data from the webhook request.\n */\n public async handleAmdEvent(\n form: Record<string, string>\n ): Promise<{ status: number; content: string; contentType: string }> {\n return this.dispatchCallEvent('amd', form, this.onAmdHandler, amdEventFromForm, event => ({\n call_sid: event.callSid,\n answered_by: event.answeredBy,\n }));\n }\n\n /**\n * Handle a Twilio `recordingStatusCallback` webhook.\n *\n * The developer routes the request here (`TACServer` does this automatically\n * for its `/recording` call-event route). Parsed into a\n * {@link RecordingEvent} and dispatched to the {@link onRecording} handler.\n * No-op if no handler is registered.\n *\n * @param form - Raw form data from the webhook request.\n */\n public async handleRecordingEvent(\n form: Record<string, string>\n ): Promise<{ status: number; content: string; contentType: string }> {\n return this.dispatchCallEvent(\n 'recording',\n form,\n this.onRecordingHandler,\n recordingEventFromForm,\n event => ({ call_sid: event.callSid, recording_status: event.recordingStatus })\n );\n }\n\n /**\n * Hang up a call and clean up its ConversationRelay session.\n *\n * Works on `callSid` alone, whether or not a session exists yet. No-ops the\n * session cleanup if none is tracked.\n *\n * Does not throw — hanging up an already-ended call is routine (the callee\n * hangs up while AMD is still resolving), and handlers shouldn't have to\n * guard against it.\n *\n * @param callSid - Twilio Call SID (from a call event, the outbound result, or\n * `ConversationSession.callSid`).\n * @returns True if Twilio accepted the hangup, false if it failed (logged).\n * Session cleanup runs either way.\n */\n public async endCall(callSid: string): Promise<boolean> {\n const client = this.getTwilioClient();\n let hungUp = true;\n try {\n await client.calls(callSid).update({ status: 'completed' });\n } catch (error) {\n hungUp = false;\n this.logger.error({ err: error, call_sid: callSid }, 'Failed to hang up call');\n }\n\n const session = this.getConversationSessionByCallSid(callSid);\n if (session) {\n await this.endConversation(session.conversationId as ConversationId);\n }\n return hungUp;\n }\n\n /**\n * Look up the active voice session for a Twilio Call SID.\n *\n * Out-of-band code holding a CallSid — a dashboard route, an operator action,\n * a call-event handler — can't reach the session-facing methods, which are\n * keyed by conversation id: the Orchestrator conversation id in orchestrator\n * mode, the CallSid only in ConversationRelay-only mode.\n *\n * Relay-only mode creates the session on the first prompt; orchestrated\n * mode creates it when the lookup started at setup finishes, so it may\n * exist before the caller speaks — including before `onAmd` fires. Treat it\n * as racy and hang up with {@link endCall}, which needs no session.\n *\n * At the other end, orchestrator mode keeps the session until Conversation\n * Orchestrator's CLOSED webhook, so it outlives the call and `onCallStatus` /\n * `onRecording` do resolve. Relay-only mode tears down on the\n * ConversationRelay callback instead, which races them.\n *\n * @example\n * ```typescript\n * async function nudge(callSid: string): Promise<void> {\n * const session = voiceChannel.getConversationSessionByCallSid(callSid);\n * if (session) {\n * await voiceChannel.sendResponse(session.conversationId, 'Still there?');\n * }\n * }\n * ```\n *\n * @param callSid - Twilio Call SID, e.g. from\n * `InitiateVoiceConversationResult.callSid` or a call event.\n * @returns The session, or `undefined` — not created yet, the call ended, or\n * it landed on another instance (see the horizontal-scaling note in\n * CLAUDE.md).\n */\n public getConversationSessionByCallSid(callSid: string): ConversationSession | undefined {\n for (const session of this.activeConversations.values()) {\n if (session.callSid === callSid) {\n return session;\n }\n }\n return undefined;\n }\n\n // =========================================================================\n // Stream Task Management\n //\n // Stream tasks are ConversationRelay's text-token machinery and live on\n // `ConversationRelayProvider`, alongside the transport that consumes their\n // AbortSignal. These forwarders keep the channel-level API intact.\n // =========================================================================\n\n /**\n * Narrow `provider` to the ConversationRelay implementation for the\n * ConversationRelay-only forwarders on this channel.\n *\n * Throws whenever a consumer supplies a non-ConversationRelay provider, which\n * is the point of the guard. The provider callback used to narrow here too; it\n * now rides {@link VoiceProvider.handleTwilioProviderCallback}'s\n * base-compatible signature instead, which is the eventual shape for these\n * forwarders.\n *\n * @throws {Error} if this channel's provider is not ConversationRelay-based.\n */\n private requireConversationRelayProvider(capability: string): ConversationRelayProvider {\n if (!(this.provider instanceof ConversationRelayProvider)) {\n throw new Error(`${this.provider.constructor.name} does not support ${capability}.`);\n }\n return this.provider;\n }\n\n /**\n * Start tracking a streaming task for a conversation\n *\n * @param conversationId - The conversation ID\n * @returns The stream task with its AbortController\n */\n public startStreamTask(conversationId: ConversationId): StreamTask {\n return this.requireConversationRelayProvider('stream tasks').startStreamTask(conversationId);\n }\n\n /**\n * Cancel an active streaming task\n *\n * @param conversationId - The conversation ID\n * @returns true if a task was cancelled, false otherwise\n */\n public cancelStreamTask(conversationId: ConversationId): boolean {\n return this.requireConversationRelayProvider('stream tasks').cancelStreamTask(conversationId);\n }\n\n /**\n * Complete a streaming task (remove from tracking)\n *\n * @param conversationId - The conversation ID\n */\n public completeStreamTask(conversationId: ConversationId): void {\n this.requireConversationRelayProvider('stream tasks').completeStreamTask(conversationId);\n }\n\n /**\n * Check if a stream task is active\n *\n * @param conversationId - The conversation ID\n * @returns true if an active task exists\n */\n public hasActiveStreamTask(conversationId: ConversationId): boolean {\n return this.requireConversationRelayProvider('stream tasks').hasActiveStreamTask(\n conversationId\n );\n }\n\n // =========================================================================\n // ConversationRelay TwiML Generation\n // =========================================================================\n\n /**\n * Generate TwiML to connect a call to ConversationRelay. Delegates to\n * {@link ConversationRelayProvider.connectConversationRelay}, which validates\n * the configuration with Zod before generating TwiML.\n *\n * @param config - ConversationRelay configuration (url, transcription, TTS, etc.)\n * @param options - Optional settings for parameters and the Connect verb\n * @returns TwiML XML string\n * @throws {Error} if config validation fails, or if this channel's provider is\n * not ConversationRelay-based.\n */\n public connectConversationRelay(\n config: ConversationRelayConfig,\n options?: { parameters?: CustomParameters; actionUrl?: string }\n ): string {\n return this.requireConversationRelayProvider(\n 'ConversationRelay TwiML generation'\n ).connectConversationRelay(config, options);\n }\n\n /**\n * Cleanup channel state on shutdown\n *\n * Note: WebSocket connections are managed by the server and closed there.\n * This method only cleans up internal channel state.\n */\n public override shutdown(): void {\n this.provider.shutdown();\n super.shutdown();\n }\n}\n","import VoiceResponse from 'twilio/lib/twiml/VoiceResponse.js';\nimport type { VoiceTwiMLOptionsMediaStreams } from '../../../types/index';\nimport { TwiMLBuilderBase, stringifyParameterValue } from '../twiml';\n\n/**\n * The slice of a Media Streams provider's config this builder reads. Declared\n * structurally rather than importing the provider's config class, so the\n * builder does not depend on which Media Streams provider owns it.\n */\nexport interface MediaStreamsTwiMLBuilderConfig {\n defaultTwimlOptions?: VoiceTwiMLOptionsMediaStreams | undefined;\n}\n\n/**\n * Generate TwiML that connects the call to a bidirectional Media Stream.\n *\n * See https://www.twilio.com/docs/voice/twiml/stream for the `<Stream>` verb.\n *\n * The WebSocket URL may be passed positionally or as `options.websocketUrl`\n * (positional wins when both are given), so a caller can pass everything in one\n * object: `generateStreamTwiml(undefined, { websocketUrl: ... })`.\n *\n * @param websocketUrl - Public `wss://` URL of the WebSocket endpoint Twilio\n * should stream call audio to (the `<Stream url=...>` attribute). Optional if\n * `options.websocketUrl` is set.\n * @param options - Optional Media Streams TwiML options.\n * @returns TwiML XML string ready to return to Twilio.\n * @throws {Error} if no WebSocket URL is provided via either source.\n */\nexport function generateStreamTwiml(\n websocketUrl?: string,\n options?: VoiceTwiMLOptionsMediaStreams\n): string {\n const resolved = websocketUrl ?? options?.websocketUrl;\n if (!resolved || !resolved.trim()) {\n throw new Error(\n 'generateStreamTwiml requires a WebSocket URL — pass it positionally or ' +\n 'set options.websocketUrl.'\n );\n }\n\n const response = new VoiceResponse();\n\n // <Connect> takes its attributes at construction so they land in the opening\n // tag; only action/method belong here, the rest are <Stream> attributes.\n const connectAttrs: Record<string, unknown> = {};\n if (options?.actionUrl) {\n connectAttrs.action = options.actionUrl;\n }\n if (options?.actionMethod) {\n connectAttrs.method = options.actionMethod;\n }\n const connect = response.connect(connectAttrs as Parameters<typeof response.connect>[0]);\n\n const streamAttrs: Record<string, unknown> = { url: resolved };\n if (options?.name) {\n streamAttrs.name = options.name;\n }\n if (options?.statusCallback) {\n streamAttrs.statusCallback = options.statusCallback;\n }\n if (options?.statusCallbackMethod) {\n streamAttrs.statusCallbackMethod = options.statusCallbackMethod;\n }\n const stream = connect.stream(streamAttrs as Parameters<typeof connect.stream>[0]);\n\n // Emit custom parameters as <Parameter> children, skipping null/undefined.\n if (options?.customParameters) {\n for (const [name, value] of Object.entries(options.customParameters)) {\n if (value !== null && value !== undefined) {\n stream.parameter({ name, value: stringifyParameterValue(value) });\n }\n }\n }\n\n return response.toString();\n}\n\n/** Per-call inputs to {@link TwiMLBuilderMediaStreams.build}. */\nexport interface BuildStreamTwiMLInputs {\n /**\n * Per-call overrides from the host owning the route (e.g. a per-call\n * `websocketUrl` with an affinity token). Lowest of the option layers.\n */\n host?: VoiceTwiMLOptionsMediaStreams | undefined;\n /**\n * Per-call overrides — the `onInboundCallTwiml` customizer's output for\n * inbound, or `InitiateVoiceConversationOptions.twimlOptions` for outbound.\n * Highest layer.\n */\n perCall?: VoiceTwiMLOptionsMediaStreams | undefined;\n /**\n * Dedicated per-call WebSocket override that wins over any `websocketUrl`\n * coming through the option layers. Used by outbound, which takes it as its\n * own argument.\n */\n websocketUrl?: string | undefined;\n}\n\n/**\n * Builds the TwiML for a Media Streams call, owning the layering and WebSocket\n * URL resolution so the provider doesn't have to.\n */\nexport class TwiMLBuilderMediaStreams extends TwiMLBuilderBase<MediaStreamsTwiMLBuilderConfig> {\n /**\n * Build the TwiML XML for one call.\n *\n * TwiML fields are merged per-field, highest precedence first:\n * 1. `perCall` — the `onInboundCallTwiml` customizer's output for inbound,\n * or `InitiateVoiceConversationOptions.twimlOptions` for outbound\n * 2. the provider config's `defaultTwimlOptions` — channel-wide defaults\n * 3. `host` — per-call transport facts supplied by the host\n * 4. TAC defaults: the WebSocket URL derived from\n * `TACConfig.voicePublicDomain` + `voiceWebsocketPath`\n *\n * @param caller - Name of the calling method, used in the \"no WebSocket URL\"\n * error so it points at the API the developer actually called.\n * @param options - Per-call option layers and WebSocket override.\n * @throws {Error} if no layer and no `TACConfig`-derived default supplies a\n * WebSocket URL.\n */\n public build(caller: string, options?: BuildStreamTwiMLInputs): string {\n const merged = this.buildTwimlOptions(options?.host, options?.perCall);\n\n // Falsy rather than nullish: an empty-string websocketUrl from any layer\n // must fall through instead of emitting <Stream url=\"\">.\n const resolvedWebsocketUrl =\n options?.websocketUrl || merged.websocketUrl || this.defaultWebsocketUrl();\n if (!resolvedWebsocketUrl) {\n throw this.missingWebsocketUrlError(caller);\n }\n\n return generateStreamTwiml(resolvedWebsocketUrl, merged);\n }\n\n /**\n * Layer TwiML options, lowest precedence first: `host` →\n * `defaultTwimlOptions` → `perCall`.\n *\n * `customParameters` replaces wholesale when set at a higher-priority layer —\n * there's no per-key merging.\n */\n protected buildTwimlOptions(\n host: VoiceTwiMLOptionsMediaStreams | undefined,\n perCall: VoiceTwiMLOptionsMediaStreams | undefined\n ): VoiceTwiMLOptionsMediaStreams {\n const merged: VoiceTwiMLOptionsMediaStreams = {};\n if (host) {\n this.overlayFields(merged, host);\n }\n if (this.channelConfig.defaultTwimlOptions) {\n this.overlayFields(merged, this.channelConfig.defaultTwimlOptions);\n }\n if (perCall) {\n this.overlayFields(merged, perCall);\n }\n return merged;\n }\n}\n","import type { VoiceTwiMLOptionsMediaStreams } from '../../../types/index';\nimport type { BaseChannelOptions } from '../../base';\nimport { VoiceProviderConfig } from '../provider';\n\n/** Options accepted by {@link MediaStreamsProviderConfig}. */\nexport interface MediaStreamsProviderConfigOptions extends BaseChannelOptions {\n /**\n * Static `VoiceTwiMLOptionsMediaStreams` applied to every inbound call.\n * Per-call customization is registered via\n * `VoiceChannel.onInboundCallTwiml(...)`, which takes precedence over this.\n */\n defaultTwimlOptions?: VoiceTwiMLOptionsMediaStreams;\n}\n\n/**\n * Base configuration for a Media Streams (`<Connect><Stream>`) provider.\n *\n * Holds the transport-level settings every Media Streams provider shares,\n * independent of which model or protocol runs over the stream.\n */\nexport class MediaStreamsProviderConfig extends VoiceProviderConfig {\n /**\n * Static `VoiceTwiMLOptionsMediaStreams` applied to every inbound call.\n * Per-call customization is registered via\n * `VoiceChannel.onInboundCallTwiml(...)`, which takes precedence over this.\n */\n public readonly defaultTwimlOptions?: VoiceTwiMLOptionsMediaStreams;\n\n constructor(options?: MediaStreamsProviderConfigOptions) {\n super(options);\n if (options?.defaultTwimlOptions !== undefined) {\n this.defaultTwimlOptions = options.defaultTwimlOptions;\n }\n }\n}\n","import type { TACTool } from '@twilio/tac-tools';\nimport type { TwiMLRequest } from '../../../../types/index';\nimport { MediaStreamsProviderConfig } from '../config';\nimport type { MediaStreamsProviderConfigOptions } from '../config';\n\n/**\n * Options accepted by {@link MediaStreamsOpenAIProviderConfig}.\n */\nexport interface MediaStreamsOpenAIProviderConfigOptions extends MediaStreamsProviderConfigOptions {\n /**\n * OpenAI API key. Defaults to the `OPENAI_API_KEY` environment variable.\n */\n openaiApiKey?: string;\n\n /**\n * Executable `TACTool` implementations, looked up by name to run mid-call\n * tool requests. This alone does not tell the model these tools exist — the\n * session config sent to OpenAI must separately declare each tool's schema.\n */\n // `never`, not `unknown`: `implementation` is a property, so its parameter is\n // contravariant and `TACTool[]` would reject every tool with typed params.\n tools?: TACTool<never, unknown>[];\n\n /**\n * Session configuration sent to OpenAI once the model connects — used for any\n * call that doesn't supply its own via\n * {@link MediaStreamsOpenAIProviderConfigOptions.onInboundCallSessionConfig}\n * or per-call outbound options.\n *\n * If using {@link MediaStreamsOpenAIProviderConfigOptions.tools}, this config\n * must separately list each tool's schema — it is passed to OpenAI as-is,\n * with no tool schemas merged in.\n */\n defaultSessionConfig?: Record<string, unknown>;\n\n /**\n * Per-inbound-call override for\n * {@link MediaStreamsOpenAIProviderConfigOptions.defaultSessionConfig},\n * called with the `TwiMLRequest`. Its return value is used verbatim (not\n * merged with `defaultSessionConfig`); return `null` to fall back to it.\n * Outbound calls don't use this — they pass their session config per call.\n */\n onInboundCallSessionConfig?: (req: TwiMLRequest) => Promise<Record<string, unknown> | null>;\n}\n\n/**\n * Base configuration for an OpenAI-backed Media Streams provider.\n *\n * Holds what every OpenAI-backed Media Streams provider needs — credentials,\n * executable tools, and the session config sent when the model connects —\n * independent of which OpenAI API runs over the stream.\n */\nexport class MediaStreamsOpenAIProviderConfig extends MediaStreamsProviderConfig {\n /** OpenAI API key. Defaults to the `OPENAI_API_KEY` environment variable. */\n public readonly openaiApiKey: string;\n\n /**\n * Executable `TACTool` implementations, looked up by name to run mid-call\n * tool requests. This alone does not tell the model these tools exist — the\n * session config sent to OpenAI must separately declare each tool's schema.\n */\n // See the `never` note on `MediaStreamsOpenAIProviderConfigOptions.tools`.\n public readonly tools: TACTool<never, unknown>[];\n\n /**\n * Session configuration sent to OpenAI once the model connects — used for any\n * call that doesn't supply its own via\n * {@link MediaStreamsOpenAIProviderConfig.onInboundCallSessionConfig} or\n * per-call outbound options.\n *\n * If using {@link MediaStreamsOpenAIProviderConfig.tools}, this config must\n * separately list each tool's schema — it is passed to OpenAI as-is, with no\n * tool schemas merged in.\n */\n public readonly defaultSessionConfig?: Record<string, unknown>;\n\n /**\n * Per-inbound-call override for\n * {@link MediaStreamsOpenAIProviderConfig.defaultSessionConfig}, called with\n * the `TwiMLRequest`. Its return value is used verbatim (not merged with\n * `defaultSessionConfig`); return `null` to fall back to it. Outbound calls\n * don't use this — they pass their session config per call.\n */\n public readonly onInboundCallSessionConfig?: (\n req: TwiMLRequest\n ) => Promise<Record<string, unknown> | null>;\n\n constructor(options?: MediaStreamsOpenAIProviderConfigOptions) {\n super(options);\n\n this.openaiApiKey = options?.openaiApiKey ?? process.env.OPENAI_API_KEY ?? '';\n this.tools = options?.tools ?? [];\n if (options?.defaultSessionConfig !== undefined) {\n this.defaultSessionConfig = options.defaultSessionConfig;\n }\n if (options?.onInboundCallSessionConfig !== undefined) {\n this.onInboundCallSessionConfig = options.onInboundCallSessionConfig;\n }\n\n if (!this.openaiApiKey) {\n throw new Error(\n 'openaiApiKey is required. Set the OPENAI_API_KEY environment ' +\n `variable or provide openaiApiKey in ${this.constructor.name}.`\n );\n }\n }\n}\n","import type { WebSocket } from 'ws';\n\n/**\n * Both legs of one call's audio bridge — the Twilio-facing socket and the\n * model-facing socket — live here together, rather than in two parallel maps\n * keyed by conversation id that could drift out of sync.\n *\n * `streamSid` and `transcript` live on `ConversationSession.metadata` instead,\n * not here: this map is deleted before `onConversationEnded` fires, so anything\n * a handler needs to read after the call ends must survive on the session.\n *\n * @internal\n */\nexport class MediaStreamsOpenAICallState {\n twilioWs: WebSocket | null = null;\n modelWs: WebSocket | null = null;\n\n /**\n * Resolves `true` once this call's model socket is open and its session\n * config has been sent, or `false` if that handshake failed. `null` until the\n * handshake has been started.\n *\n * Twilio begins streaming caller audio as soon as the media stream opens,\n * which is well before the OpenAI handshake completes. Caller audio waits on\n * this promise rather than being written to a socket that does not exist\n * yet, so a caller who speaks the instant the call connects is not clipped.\n * Every frame awaits this same promise, so the frames resume in the order\n * they arrived.\n *\n * It resolves rather than rejects: a failed handshake is reported once, by\n * the code that opened the socket, not once per waiting frame.\n */\n modelReady: Promise<boolean> | null = null;\n}\n","import { WebSocket } from 'ws';\nimport type { TACTool } from '@twilio/tac-tools';\nimport packageJson from '../../../../../../../package.json' with { type: 'json' };\nimport type { TACConfig } from '../../../../lib/config';\nimport type { Logger } from '../../../../lib/logger';\nimport {\n VoiceTwiMLOptionsMediaStreamsSchema,\n type ConversationId,\n type ConversationSession,\n type TwiMLRequest,\n type VoiceTwiMLOptions,\n type VoiceTwiMLOptionsMediaStreams,\n} from '../../../../types/index';\nimport type { VoiceChannel } from '../../channel';\nimport { VoiceProvider } from '../../provider';\nimport { TwiMLBuilderMediaStreams } from '../twiml';\nimport type { MediaStreamsOpenAIProviderConfig } from './config';\nimport type { MediaStreamsOpenAICallState } from './state';\n\n/**\n * Identifies this SDK to OpenAI on every WebSocket connection, per OpenAI's\n * requested User-Agent pattern: [Company/Library name]/[Language] [Version].\n *\n * Deliberately unlike the Twilio-facing User-Agent in `clients/base.ts`, which\n * follows Twilio's own convention instead.\n */\nexport const OPENAI_USER_AGENT = `twilio-agent-connect/TypeScript ${packageJson.version}`;\n\n/**\n * How long an inbound session-config override may sit unclaimed before it is\n * purged.\n *\n * Twilio can answer the TwiML webhook — which stashes the override under the\n * call SID — and then never open the Media Stream, when a call fails or is\n * abandoned after the webhook responds. Without this the stash would sit in\n * {@link MediaStreamsOpenAIProvider.pendingSessionConfigs} until process\n * shutdown. Mirrors the outbound token expiry in the GPT-Live provider.\n */\nconst INBOUND_SESSION_CONFIG_TTL_MS = 120_000;\n\n/**\n * Render Zod validation issues as a compact `path: message` list, so a thrown\n * `TypeError` names the fields that actually failed rather than dumping the\n * raw error.\n *\n * Typed structurally rather than against Zod's issue type so it stays usable\n * with the result of any schema's `safeParse`.\n *\n * @internal\n */\nexport function describeIssues(\n issues: readonly { readonly path: readonly PropertyKey[]; readonly message: string }[]\n): string {\n return issues.map(issue => `${issue.path.join('.') || '(root)'}: ${issue.message}`).join(', ');\n}\n\n/**\n * Shared scaffolding for a {@link VoiceProvider} bridging Twilio Media Streams\n * to an OpenAI real-time voice API.\n *\n * Holds only what's identical across every such provider; each subclass still\n * owns its own `initiateOutboundConversation`, `handleWebSocket`,\n * `registerCall`, `connectModel`, {@link dispatchModelEvent},\n * `handleFunctionCall`, and `cleanupCall`.\n *\n * Generic over `TCallState` (bound to `MediaStreamsOpenAICallState`) so\n * {@link calls} keeps each subclass's own call-state shape instead of widening\n * to the shared base everywhere it's read.\n */\nexport abstract class MediaStreamsOpenAIProvider<\n TCallState extends MediaStreamsOpenAICallState,\n> extends VoiceProvider {\n /**\n * The owning channel's logger, so this provider logs under the same name the\n * rest of the voice channel does.\n */\n protected override readonly logger: Logger;\n\n /** Executable tools from the config, looked up by the name the model sends. */\n protected readonly toolsByName: Map<string, TACTool>;\n\n /** Per-call transport state, keyed by conversation id. */\n protected readonly calls: Map<ConversationId, TCallState>;\n\n protected readonly config: MediaStreamsOpenAIProviderConfig;\n protected readonly tacConfig: TACConfig;\n protected readonly twimlBuilder: TwiMLBuilderMediaStreams;\n\n /**\n * Session config overrides awaiting the call they belong to.\n *\n * Inbound entries are keyed by call SID (known when the TwiML webhook is\n * answered); a subclass keys its outbound entries by whatever token it round\n * trips through the stream's custom parameters.\n */\n protected readonly pendingSessionConfigs: Map<string, Record<string, unknown>>;\n\n /**\n * Expiry timers for the inbound {@link pendingSessionConfigs} entries, keyed\n * by the same call SID. Each fires once to purge a stash whose Media Stream\n * never connected; a normal connect cancels it in the subclass's\n * `registerCall`. Outbound entries are keyed by token instead and are not\n * tracked here.\n */\n private readonly pendingInboundExpiries: Map<string, ReturnType<typeof setTimeout>>;\n\n constructor(\n channel: VoiceChannel,\n tacConfig: TACConfig,\n config: MediaStreamsOpenAIProviderConfig\n ) {\n super(channel);\n this.logger = channel.getLoggerInternal();\n this.config = config;\n this.tacConfig = tacConfig;\n this.toolsByName = new Map(config.tools.map(tool => [tool.name, tool as TACTool]));\n this.calls = new Map();\n this.twimlBuilder = new TwiMLBuilderMediaStreams(tacConfig, config, this.logger);\n this.pendingSessionConfigs = new Map();\n this.pendingInboundExpiries = new Map();\n }\n\n /** The Twilio-facing WebSocket for a conversation, if one is tracked. */\n public override getWebSocket(conversationId: ConversationId): WebSocket | null {\n return this.calls.get(conversationId)?.twilioWs ?? null;\n }\n\n /**\n * Open a WebSocket and resolve once it is ready to carry traffic.\n *\n * Isolated from each subclass's `connectModel` so tests can substitute a\n * socket without reaching the network.\n *\n * A resolved socket always carries at least one `'error'` listener, whatever\n * the caller does with it next.\n *\n * @internal\n */\n public openModelSocket(url: string, headers: Record<string, string>): Promise<WebSocket> {\n return new Promise<WebSocket>((resolve, reject) => {\n const ws = new WebSocket(url, { headers });\n const onOpen = (): void => {\n ws.off('error', onError);\n // A listener-less 'error' emission throws, and `ws` emits one for any\n // frame its receiver rejects — including mid-close. Callers that never\n // reach attachModelHandlers must still get a socket that can't do that.\n ws.on('error', () => {});\n resolve(ws);\n };\n const onError = (error: Error): void => {\n ws.off('open', onOpen);\n reject(error);\n };\n ws.once('open', onOpen);\n ws.once('error', onError);\n });\n }\n\n /**\n * The transcript captured so far for an in-progress call.\n *\n * It lives on `ConversationSession.metadata.transcript`, so once the call\n * ends and the session is dropped it is no longer reachable here — read it\n * from the session an `onConversationEnded` handler receives instead.\n */\n public getTranscript(conversationId: ConversationId): Record<string, string>[] {\n const transcript = this.channel.getConversationSession(conversationId)?.metadata.transcript;\n return Array.isArray(transcript) ? [...(transcript as Record<string, string>[])] : [];\n }\n\n /**\n * The session config stashed for `key` — a call SID for inbound calls, a\n * token for outbound ones.\n *\n * @internal\n */\n public peekPendingSessionConfig(key: string): Record<string, unknown> | undefined {\n return this.pendingSessionConfigs.get(key);\n }\n\n /**\n * How many session config overrides are waiting for their call.\n *\n * @internal\n */\n public pendingSessionConfigCount(): number {\n return this.pendingSessionConfigs.size;\n }\n\n /**\n * Start the clock on an inbound stash, so a call whose Media Stream never\n * connects cannot strand its override in {@link pendingSessionConfigs} until\n * shutdown.\n *\n * Unref'd: a two-minute timer must not be what keeps the process alive after\n * the call it belongs to is long over. Re-arming replaces any prior timer for\n * the same call SID, so a duplicate inbound webhook can't orphan one.\n */\n private armInboundConfigExpiry(callSid: string): void {\n this.cancelInboundConfigExpiry(callSid);\n const timer = setTimeout(() => {\n this.pendingInboundExpiries.delete(callSid);\n this.pendingSessionConfigs.delete(callSid);\n }, INBOUND_SESSION_CONFIG_TTL_MS);\n timer.unref();\n this.pendingInboundExpiries.set(callSid, timer);\n }\n\n /**\n * Stop the clock on an inbound stash, once the call it belongs to has\n * connected and is about to consume the entry. A no-op for outbound calls,\n * which key their stash by token and never arm one — the subclass calls this\n * with the call SID for every `start`, inbound or not.\n *\n * @internal\n */\n protected cancelInboundConfigExpiry(callSid: string): void {\n const timer = this.pendingInboundExpiries.get(callSid);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.pendingInboundExpiries.delete(callSid);\n }\n }\n\n /**\n * The executable tool the model would run for `name`, if the config supplied\n * one.\n *\n * @internal\n */\n public peekTool(name: string): TACTool | undefined {\n return this.toolsByName.get(name);\n }\n\n // =========================================================================\n // Inbound Call Handling\n // =========================================================================\n\n /**\n * Build the `<Connect><Stream>` TwiML for an inbound call.\n *\n * TwiML fields are merged per-field, highest precedence first:\n * 1. Output of the customizer registered via\n * `VoiceChannel.onInboundCallTwiml(...)`, if configured and\n * `twimlRequest` is given\n * 2. `MediaStreamsProviderConfig.defaultTwimlOptions` — channel-wide\n * defaults\n * 3. `options.hostTwimlOptions` — per-call transport facts supplied by the\n * host\n * 4. TAC defaults: the WebSocket URL derived from\n * `TACConfig.voicePublicDomain` + `voiceWebsocketPath`\n *\n * Also runs `MediaStreamsOpenAIProviderConfig.onInboundCallSessionConfig`, if\n * set, and stashes its result for the call to pick up once it connects. The\n * hook runs only after the TwiML builds, so a call that never connects\n * leaves nothing stashed behind it.\n *\n * @param twimlRequest - Parsed Twilio webhook fields for the inbound call.\n * @param options - Additional per-call inputs.\n * @param options.hostTwimlOptions - Per-call TwiML supplied by a custom\n * in-process host.\n * @throws {TypeError} if either the host options or the customizer's output\n * is not a `VoiceTwiMLOptionsMediaStreams`.\n * @throws {Error} if no WebSocket URL can be resolved — none of the TwiML\n * layers set one and `TACConfig.voicePublicDomain` is unset.\n */\n public override async handleIncomingCall(\n twimlRequest?: TwiMLRequest,\n options?: { hostTwimlOptions?: VoiceTwiMLOptions }\n ): Promise<string> {\n const host = this.narrowTwimlOptions(\n options?.hostTwimlOptions,\n 'handleIncomingCall',\n 'options.hostTwimlOptions'\n );\n\n const onInboundCallTwimlHandler = this.channel.getInboundCallTwimlHandler();\n let customized: VoiceTwiMLOptionsMediaStreams | undefined;\n if (onInboundCallTwimlHandler && twimlRequest) {\n customized = this.narrowTwimlOptions(\n await onInboundCallTwimlHandler(twimlRequest),\n 'handleIncomingCall',\n 'the onInboundCallTwiml customizer output'\n );\n }\n\n // Built before the stash, not after: build() throws when no WebSocket URL\n // can be resolved, and a throw here 500s the webhook so the call never\n // connects to drain the entry. Nothing would ever remove it.\n const twiml = this.twimlBuilder.build('handleIncomingCall', { host, perCall: customized });\n\n if (this.config.onInboundCallSessionConfig && twimlRequest?.callSid) {\n const sessionConfig = await this.config.onInboundCallSessionConfig(twimlRequest);\n if (sessionConfig !== null) {\n this.pendingSessionConfigs.set(twimlRequest.callSid, sessionConfig);\n this.armInboundConfigExpiry(twimlRequest.callSid);\n }\n }\n\n return twiml;\n }\n\n /**\n * Narrow provider-agnostic {@link VoiceTwiMLOptions} to this provider's\n * concrete shape. `VoiceProvider.handleIncomingCall` is typed against the\n * base so every provider can accept its own TwiML options, so the Media\n * Streams shape has to be established at runtime.\n *\n * @param value - Options from a caller or the application customizer.\n * @param caller - Name of the calling method, for the error message.\n * @param label - What produced `value`, for the error message.\n */\n protected narrowTwimlOptions(\n value: VoiceTwiMLOptions | undefined,\n caller: string,\n label: string\n ): VoiceTwiMLOptionsMediaStreams | undefined {\n if (value === undefined) {\n return undefined;\n }\n const parsed = VoiceTwiMLOptionsMediaStreamsSchema.safeParse(value);\n if (!parsed.success) {\n throw new TypeError(\n `MediaStreamsOpenAIProvider.${caller} requires ${label} to be a ` +\n `VoiceTwiMLOptionsMediaStreams: ${describeIssues(parsed.error.issues)}`\n );\n }\n return parsed.data;\n }\n\n // =========================================================================\n // Audio Bridge\n // =========================================================================\n\n /**\n * Parse one frame off the model socket and hand it to\n * {@link dispatchModelEvent}.\n *\n * A failure here is logged and skipped rather than ending the call: one\n * malformed delta must not hang up on the caller.\n *\n * @internal\n */\n public async handleModelMessage(\n conversationId: ConversationId,\n raw: Buffer | string\n ): Promise<void> {\n try {\n const event = JSON.parse(typeof raw === 'string' ? raw : raw.toString('utf8')) as Record<\n string,\n unknown\n >;\n const session = this.channel.getConversationSession(conversationId);\n if (session === undefined) {\n return;\n }\n await this.dispatchModelEvent(conversationId, session, event);\n } catch (err) {\n this.logger.error({ err, conversation_id: conversationId }, 'Error handling model event');\n }\n }\n\n /**\n * Interpret one event received from the model. Protocol-specific —\n * implemented by each subclass.\n */\n protected abstract dispatchModelEvent(\n conversationId: ConversationId,\n session: ConversationSession,\n event: Record<string, unknown>\n ): Promise<void>;\n\n /**\n * Look up a model-requested tool by name, run it, and return its output.\n *\n * Errors are returned as part of the output rather than thrown, so a bad\n * tool call does not kill the call.\n *\n * @internal\n */\n public async runToolCall(\n conversationId: ConversationId,\n name: string,\n argumentsJson: unknown\n ): Promise<unknown> {\n this.logger.debug({ conversation_id: conversationId, tool_name: name }, 'Tool call');\n\n const tool = this.toolsByName.get(name);\n if (tool === undefined) {\n return { error: `Unknown tool '${name}'` };\n }\n\n try {\n const parsedArguments: unknown = JSON.parse(\n typeof argumentsJson === 'string' && argumentsJson ? argumentsJson : '{}'\n );\n const output: unknown = await tool.implementation(parsedArguments);\n this.logger.debug({ conversation_id: conversationId, tool_name: name }, 'Tool result');\n return output;\n } catch (err) {\n // Only the generic message goes back: the model may read tool output\n // aloud, so a stack trace or upstream payload must never reach the caller.\n this.logger.error({ err, conversation_id: conversationId, tool_name: name }, 'Tool failed');\n return { error: `Tool '${name}' failed to execute.` };\n }\n }\n\n /** Write one event to this call's model socket, if it still has one. */\n protected modelSend(conversationId: ConversationId, payload: Record<string, unknown>): void {\n const modelWs = this.calls.get(conversationId)?.modelWs;\n if (!modelWs) {\n return;\n }\n try {\n modelWs.send(JSON.stringify(payload));\n } catch (err) {\n // A socket closing under a write is ordinary end-of-call, not an error.\n this.logger.debug({ err, conversation_id: conversationId }, 'Failed to send to model');\n }\n }\n\n /** Write one message to this call's Twilio socket, if it still has one. */\n protected twilioSend(conversationId: ConversationId, payload: Record<string, unknown>): void {\n const twilioWs = this.calls.get(conversationId)?.twilioWs;\n if (!twilioWs) {\n return;\n }\n try {\n twilioWs.send(JSON.stringify(payload));\n } catch (err) {\n this.logger.debug({ err, conversation_id: conversationId }, 'Failed to send to Twilio');\n }\n }\n\n /**\n * Always throws: the model streams its reply as audio straight to Twilio, so\n * this transport has no text response to send.\n */\n // eslint-disable-next-line @typescript-eslint/require-await -- Rejects without awaiting, but stays `async` so callers always get a Promise\n public override async sendResponse(\n _conversationId: ConversationId,\n _message: string,\n _metadata?: Record<string, unknown>\n ): Promise<void> {\n throw new Error(\n `${this.constructor.name} produces audio via the model; it has no text sendResponse.`\n );\n }\n\n /**\n * Drop this provider's Media Streams transport state on channel shutdown.\n *\n * Note: WebSocket connections are managed by the server and closed there.\n * This method only cleans up internal provider state — including session\n * config overrides stashed for calls that were placed but never connected.\n */\n public override shutdown(): void {\n super.shutdown();\n for (const timer of this.pendingInboundExpiries.values()) {\n clearTimeout(timer);\n }\n this.pendingInboundExpiries.clear();\n this.calls.clear();\n this.pendingSessionConfigs.clear();\n }\n}\n","import { MediaStreamsOpenAICallState } from '../shared/state';\n\n/**\n * Per-call barge-in bookkeeping.\n *\n * For every delta that carries an `item_id`, `currentItemAudioMs` is never\n * more than the duration of audio actually sent to Twilio for\n * `lastAssistantItem`: it comes from delta byte counts rather than a\n * wall-clock estimate, floored per delta, so it can understate by up to a\n * millisecond per delta. `conversation.item.truncate` rejects an `audioEndMs`\n * beyond the item's real content, so understating is the safe direction.\n *\n * `responseActive` tracks whether a response is still being generated (set on\n * `response.created`, cleared on `response.done` or once barge-in cancels it) —\n * `response.cancel` with nothing in flight is itself an error event, so this\n * gates whether to send it.\n *\n * `mutedItemId` is the assistant item truncated by the last barge-in —\n * `response.output_audio.delta` events whose `item_id` matches it are dropped\n * as stale audio for a reply the caller already talked over. It is never\n * cleared; the next barge-in overwrites it.\n *\n * @internal\n */\nexport class BargeInState {\n lastAssistantItem: string | null = null;\n currentItemAudioMs = 0;\n mutedItemId: string | null = null;\n responseActive = false;\n}\n\n/**\n * Per-call bookkeeping the OpenAI Realtime provider needs beyond\n * `ConversationSession` and the sockets its base class holds.\n *\n * @internal\n */\nexport class CallState extends MediaStreamsOpenAICallState {\n /**\n * Tail of this call's model-event chain: each incoming OpenAI Realtime event\n * is appended to it rather than dispatched on arrival.\n *\n * The Python SDK reads model events in a sequential loop, so event N is fully\n * handled before N+1 is even read. `ws` delivers each event on its own\n * `'message'` emission with nothing serializing them, so without this chain a\n * `response.output_audio.delta` could advance the barge-in bookkeeping while\n * dispatch is suspended on the `handleFunctionCall` await, producing a\n * truncate that overruns the item it names.\n */\n modelEvents: Promise<void> = Promise.resolve();\n\n readonly bargeIn = new BargeInState();\n}\n","import type { WebSocket } from 'ws';\nimport type { TACConfig } from '../../../../lib/config';\nimport {\n InitiateVoiceConversationOptionsOpenAIRealtimeSchema,\n StreamStartMessageSchema,\n callOptionsToCreateParams,\n type ConversationId,\n type ConversationSession,\n type InitiateVoiceConversationOptions,\n type InitiateVoiceConversationOptionsOpenAIRealtime,\n} from '../../../../types/index';\nimport type { InitiateVoiceConversationResult } from '../../../../types/conversation';\nimport { maskPhone, redactTwimlParameters } from '../../../../util/log-redaction';\nimport type { VoiceChannel } from '../../channel';\nimport { trackEvent } from '../../../../lib/analytics';\nimport {\n MediaStreamsOpenAIProvider,\n OPENAI_USER_AGENT,\n describeIssues,\n} from '../shared/openai-provider';\nimport type { OpenAIRealtimeProviderConfig } from './config';\nimport { CallState } from './state';\n\n/**\n * Reserved `<Stream>` custom parameter used to correlate an outbound call's\n * `sessionConfig` override to its WebSocket `start` event.\n *\n * Why a token instead of the call SID: `calls.create()` returning `call.sid`\n * does not happen-before Twilio connecting the media stream, so the SID is not\n * yet a usable correlation key when the `start` event may already be arriving.\n * The token is embedded in the TwiML before the call is placed, so it always\n * is.\n */\nconst SESSION_CONFIG_TOKEN_PARAM = '_tac_session_config_token';\n\n/**\n * The audio format both directions of a call must use.\n *\n * Twilio Media Streams always sends and expects 8kHz G.711 u-law — see\n * https://www.twilio.com/docs/voice/media-streams/websocket-messages. Not\n * configurable. No `rate` key: Realtime's `session.audio.*.format` schema\n * rejects it as unknown, since g711 is inherently fixed-rate.\n */\nexport const TWILIO_AUDIO_FORMAT_FOR_REALTIME = { type: 'audio/pcmu' } as const;\n\n/**\n * G.711 u-law at 8kHz is 1 byte per sample, 8000 samples/sec — a fixed,\n * non-configurable rate, so an audio byte count converts to milliseconds by\n * this constant alone, whatever the session config says.\n */\nconst PCMU_BYTES_PER_MS = 8;\n\n/**\n * Whether `value` is exactly {@link TWILIO_AUDIO_FORMAT_FOR_REALTIME}.\n *\n * Compared field by field rather than by serializing both sides, so key order\n * in a caller's session config can't decide the answer.\n */\nfunction isTwilioMediaStreamAudioFormat(value: unknown): boolean {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const expected: Record<string, unknown> = TWILIO_AUDIO_FORMAT_FOR_REALTIME;\n const actual = value as Record<string, unknown>;\n const keys = Object.keys(actual);\n return (\n keys.length === Object.keys(expected).length && keys.every(key => actual[key] === expected[key])\n );\n}\n\n/**\n * A {@link VoiceProvider} bridging Twilio Media Streams to OpenAI's Realtime\n * API.\n *\n * Twilio streams call audio to TAC's own WebSocket via `<Connect><Stream>`, and\n * this provider relays it to and from a second WebSocket it opens to OpenAI's\n * Realtime API.\n *\n * ```ts\n * const channel = new VoiceChannel(\n * tac,\n * new OpenAIRealtimeProviderConfig({ defaultSessionConfig: { instructions: '...' } })\n * );\n * ```\n */\nexport class OpenAIRealtimeProvider extends MediaStreamsOpenAIProvider<CallState> {\n /** @internal */\n public override get providerId(): string {\n return 'openai_realtime';\n }\n\n /**\n * The Realtime-specific config this provider was built with.\n *\n * `declare`: `target: ES2022` implies `useDefineForClassFields`, so a plain\n * redeclaration would emit a field definition that runs after `super()` and\n * overwrite the value the base constructor assigned with `undefined`. This\n * exists only to narrow the base's `MediaStreamsOpenAIProviderConfig` to the\n * Realtime shape `connectModel` reads `welcomeGreetingResponse` from.\n *\n * No `override`: TypeScript rejects it alongside `declare` (TS1243), and\n * `noImplicitOverride` does not require it for a `declare`d field.\n */\n declare protected readonly config: OpenAIRealtimeProviderConfig;\n\n constructor(channel: VoiceChannel, tacConfig: TACConfig, config: OpenAIRealtimeProviderConfig) {\n super(channel, tacConfig, config);\n }\n\n public override get channelName(): string {\n return 'VOICE_MEDIA_STREAM_OPENAI_REALTIME';\n }\n\n // =========================================================================\n // Outbound Call Handling\n // =========================================================================\n\n /**\n * Initiate an outbound voice conversation.\n *\n * Places an outbound call with inline TwiML that connects to a Media Stream.\n * Unlike inbound, there is no local session yet at this point — one is\n * created when Twilio's WebSocket `start` event arrives.\n *\n * TwiML fields are merged per-field — see\n * {@link TwiMLBuilderMediaStreams.build}. The WebSocket URL is derived from\n * `TACConfig.voicePublicDomain` + `TACConfig.voiceWebsocketPath` unless\n * overridden per-call via `options.websocketUrl`.\n *\n * Pass `InitiateVoiceConversationOptionsOpenAIRealtime` with `sessionConfig`\n * set to override `OpenAIRealtimeProviderConfig.defaultSessionConfig` for\n * this call.\n *\n * @param options - Outbound call options, validated in full against\n * `InitiateVoiceConversationOptionsOpenAIRealtimeSchema`.\n * @throws {TypeError} if `options` is not a valid\n * `InitiateVoiceConversationOptionsOpenAIRealtime` — including an unknown\n * key, a missing `to`, or a `twimlOptions` that is not a\n * `VoiceTwiMLOptionsMediaStreams`.\n * @throws {Error} if no WebSocket URL can be resolved — neither\n * `options.websocketUrl` nor any TwiML layer sets one and\n * `TACConfig.voicePublicDomain` is unset.\n */\n public override async initiateOutboundConversation(\n options: InitiateVoiceConversationOptions | InitiateVoiceConversationOptionsOpenAIRealtime\n ): Promise<InitiateVoiceConversationResult> {\n // Validate the whole options object, not just twimlOptions: this is the\n // only gate between a host's input and `calls.create()`, and it's what\n // makes the schema's `.strict()` upgrade guard fire for this provider.\n const parsedOptions = InitiateVoiceConversationOptionsOpenAIRealtimeSchema.safeParse(options);\n if (!parsedOptions.success) {\n throw new TypeError(\n 'OpenAIRealtimeProvider.initiateOutboundConversation requires options to be an ' +\n `InitiateVoiceConversationOptionsOpenAIRealtime: ${describeIssues(\n parsedOptions.error.issues\n )}`\n );\n }\n const validated = parsedOptions.data;\n let twimlOptions = validated.twimlOptions;\n\n // The token embedded in the TwiML below — not `call.sid` — correlates this\n // override to its WebSocket `start` event; see SESSION_CONFIG_TOKEN_PARAM.\n // Minting it here touches nothing shared: the map is only written once the\n // TwiML has been built, so a `build()` failure has nothing to leak.\n const sessionConfig = validated.sessionConfig ?? null;\n let sessionConfigToken: string | null = null;\n if (sessionConfig !== null) {\n sessionConfigToken = crypto.randomUUID().replace(/-/g, '');\n // Rebuilt rather than mutated because `twimlOptions` is absent whenever\n // the caller omitted it — there is no object to assign the token into.\n twimlOptions = {\n ...twimlOptions,\n customParameters: {\n ...twimlOptions?.customParameters,\n [SESSION_CONFIG_TOKEN_PARAM]: sessionConfigToken,\n },\n };\n }\n\n const fromNumber = this.tacConfig.phoneNumber;\n\n this.logger.info(\n { to: maskPhone(validated.to), from: maskPhone(fromNumber) },\n 'Initiating outbound voice conversation'\n );\n\n // Outbound has no inbound customizer and no host layer; the per-call\n // override is options.twimlOptions. `options.websocketUrl` is the dedicated\n // per-call outbound override and wins over any websocketUrl that came\n // through the layered twimlOptions merge.\n const twiml = this.twimlBuilder.build('initiateOutboundConversation', {\n perCall: twimlOptions,\n websocketUrl: validated.websocketUrl,\n });\n\n const callParams = this.applyCallEventCallbacks(\n validated.callOptions ? callOptionsToCreateParams(validated.callOptions) : {}\n );\n\n if (sessionConfigToken !== null && sessionConfig !== null) {\n this.pendingSessionConfigs.set(sessionConfigToken, sessionConfig);\n }\n\n try {\n // The inline TwiML handed to Twilio. customParameters values are masked —\n // they're arbitrary developer data (profile IDs, caller names), unlike the\n // WebSocket URL.\n this.logger.debug(\n { twiml: redactTwimlParameters(twiml), to: maskPhone(validated.to) },\n 'Outbound call TwiML'\n );\n\n const client = this.channel.getTwilioClientInternal();\n const call = await client.calls.create({\n to: validated.to,\n from: fromNumber,\n twiml,\n ...callParams,\n });\n\n this.logger.info(\n { call_sid: call.sid, to: maskPhone(validated.to) },\n 'Outbound voice call placed'\n );\n\n return { callSid: call.sid };\n } catch (error) {\n if (sessionConfigToken !== null) {\n this.pendingSessionConfigs.delete(sessionConfigToken);\n }\n this.logger.error(\n { err: error, to: maskPhone(validated.to) },\n 'Failed to initiate outbound call'\n );\n // Deliberately not routed through `channel.handleErrorInternal`, unlike\n // ConversationRelayProvider: this matches the Python SDK, where an\n // outbound failure is the caller's to handle and is surfaced only by the\n // rethrow below.\n throw error;\n }\n }\n\n // =========================================================================\n // Audio Bridge\n // =========================================================================\n\n /**\n * Drive one Twilio Media Stream connection from `start` to disconnect.\n *\n * Twilio's `start` event names the call, which opens the matching OpenAI\n * Realtime socket; from then on caller audio is relayed to the model and the\n * model's audio back to Twilio, until either side goes away. Whichever leg\n * closes first takes the other down with it, so a caller is never left\n * connected to silence.\n *\n * Twilio streams audio without waiting for the OpenAI socket to finish\n * connecting, so audio that arrives during that handshake is held and\n * forwarded, in order, once the model is ready — a caller who speaks the\n * instant the call connects is heard in full.\n *\n * Called by `VoiceChannel.handleWebSocketConnection`; hosts serve the socket\n * rather than calling this directly.\n *\n * @param ws - The accepted Twilio-facing WebSocket.\n */\n public override handleWebSocket(ws: WebSocket): void {\n let conversationId: ConversationId | null = null;\n\n ws.on('message', (data: Buffer) => {\n // `EventEmitter` invokes this later with nothing awaiting it, so an async\n // body's rejection would surface as an unhandled rejection. Own it here.\n void (async (): Promise<void> => {\n const message = JSON.parse(data.toString()) as Record<string, unknown>;\n const event = typeof message.event === 'string' ? message.event : '';\n\n if (event === 'start') {\n try {\n const registered = this.registerCall(message.start, ws);\n conversationId = registered.conversationId;\n // Published on the call before the first `await`, so caller audio\n // arriving mid-handshake always finds something to wait on.\n // Mapped to a boolean so waiting frames observe the outcome\n // without re-raising the failure handled below.\n const connecting = this.connectModel(registered.conversationId);\n registered.call.modelReady = connecting.then(\n () => true,\n () => false\n );\n await connecting;\n } catch (err) {\n // No model, no bridge: closing the Twilio socket ends the call\n // instead of holding the caller on an open line to nothing.\n this.logger.error(\n { err, conversation_id: conversationId },\n 'Failed to bridge the call to OpenAI Realtime, ending the call'\n );\n ws.close();\n }\n } else if (event === 'media') {\n const media = (message.media ?? {}) as Record<string, unknown>;\n const payload = media.payload;\n if (conversationId !== null && typeof payload === 'string' && payload) {\n // Twilio does not wait for the OpenAI handshake before streaming,\n // so hold this frame until the model socket exists instead of\n // discarding the caller's first word. See `CallState.modelReady`\n // for why ordering survives the wait.\n const call = this.calls.get(conversationId);\n if (call === undefined) {\n return;\n }\n if (call.modelReady !== null && !(await call.modelReady)) {\n // The handshake failed and the `start` branch above has already\n // logged it and ended the call. Drop the frame without comment.\n return;\n }\n this.modelSend(conversationId, {\n type: 'input_audio_buffer.append',\n audio: payload,\n });\n }\n } else if (event === 'stop') {\n this.logger.info({ conversation_id: conversationId }, 'Media stream stopped');\n if (conversationId !== null) {\n await this.cleanupCall(conversationId);\n }\n // Python returns from its endpoint here, which drops the connection;\n // an event handler has no such exit, so close the leg explicitly.\n ws.close();\n }\n })().catch((err: unknown) => {\n this.logger.error(\n { err, conversation_id: conversationId },\n 'Unhandled error in Media Stream message handler'\n );\n });\n });\n\n ws.on('close', () => {\n this.logger.info({ conversation_id: conversationId }, 'Media stream WebSocket closed');\n if (conversationId !== null) {\n trackEvent('Websocket Disconnected', {\n account_sid: this.tacConfig.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n provider: this.providerId,\n orchestrator_enabled: this.tacConfig.isOrchestratorEnabled(),\n });\n void this.cleanupCall(conversationId).catch((err: unknown) => {\n this.logger.error({ err, conversation_id: conversationId }, 'Call cleanup error');\n });\n }\n });\n\n ws.on('error', (error: Error) => {\n // Routed to the host, unlike the outbound-call failure above: that one is\n // rethrown, so its caller already sees it. A socket error has no caller\n // to rethrow to, so logging alone would hide it from the host entirely.\n this.channel.handleErrorInternal(error, { conversationId });\n });\n }\n\n /**\n * Handle Twilio's `start` event: track the call and open its session.\n *\n * @param start - The event's `start` body, parsed against\n * `StreamStartMessageSchema`.\n * @param ws - The Twilio-facing socket this call arrived on.\n * @returns The conversation id — which is the call SID — and the call's\n * freshly tracked transport state.\n */\n private registerCall(\n start: unknown,\n ws: WebSocket\n ): { conversationId: ConversationId; call: CallState } {\n const message = StreamStartMessageSchema.parse(start ?? {});\n const conversationId = message.callSid as ConversationId;\n\n // This call's Media Stream connected, so an inbound override stashed when\n // the TwiML was answered is about to be consumed — stop its expiry timer.\n // A no-op for outbound calls, which arm no such timer.\n this.cancelInboundConfigExpiry(conversationId);\n\n // An outbound override was stashed under a token before the call was\n // placed, because its SID wasn't known yet. Twilio hands the token back\n // here, which is the first point the two can be joined up.\n const token = message.customParameters[SESSION_CONFIG_TOKEN_PARAM];\n if (token !== undefined) {\n const pending = this.pendingSessionConfigs.get(token);\n if (pending !== undefined) {\n this.pendingSessionConfigs.delete(token);\n this.pendingSessionConfigs.set(conversationId, pending);\n }\n }\n\n try {\n // No profile id: this provider's session lifecycle is independent of\n // Conversation Orchestrator, like ConversationRelay's relay-only mode.\n const session = this.channel.startConversationInternal(conversationId);\n session.callSid = message.callSid;\n session.metadata.streamSid = message.streamSid;\n session.metadata.transcript = [];\n\n trackEvent('Conversation Initialized', {\n account_sid: this.tacConfig.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n provider: this.providerId,\n orchestrator_enabled: this.tacConfig.isOrchestratorEnabled(),\n });\n } catch (err) {\n // startConversationInternal inserts the session before invoking the\n // host's onConversationStarted callback unguarded. A throw from that\n // callback unwinds registerCall before handleWebSocket has learned the\n // conversation id, so its catch path can't reach it. Roll back the\n // pending config just re-keyed under this id and the started session.\n // The `calls` entry is tracked below, after this point, so there is\n // nothing to remove there yet.\n this.pendingSessionConfigs.delete(conversationId);\n void this.channel.endConversationInternal(conversationId).catch(() => undefined);\n throw err;\n }\n\n // Tracked last, once nothing else here can throw: startConversationInternal\n // invokes the host's onConversationStarted callback unguarded, and a throw\n // would leave the caller of this method without the id needed to reclaim\n // the entry, stranding a dead socket in `calls` forever.\n const call = new CallState();\n call.twilioWs = ws;\n this.calls.set(conversationId, call);\n\n this.logger.debug(\n { conversation_id: conversationId, media_format: message.mediaFormat },\n 'Media stream started'\n );\n return { conversationId, call };\n }\n\n /**\n * Open this call's OpenAI Realtime socket and send its session config.\n *\n * @internal\n */\n public async connectModel(conversationId: ConversationId): Promise<void> {\n const sessionConfig = this.resolveSessionConfig(conversationId);\n\n const modelWs = await this.openModelSocket(\n `wss://api.openai.com/v1/realtime?model=${encodeURIComponent(String(sessionConfig.model))}`,\n {\n Authorization: `Bearer ${this.config.openaiApiKey}`,\n 'User-Agent': OPENAI_USER_AGENT,\n }\n );\n\n const call = this.calls.get(conversationId);\n if (call === undefined) {\n // The call ended while the handshake was in flight. Nothing tracks this\n // socket now, so close it rather than leak it.\n modelWs.close();\n return;\n }\n call.modelWs = modelWs;\n this.attachModelHandlers(conversationId, modelWs);\n this.logger.info({ conversation_id: conversationId }, 'Connected to OpenAI Realtime');\n\n this.modelSend(conversationId, { type: 'session.update', session: sessionConfig });\n\n // Server VAD waits for the caller to speak first, so without an explicit\n // response request an outbound call opens on silence.\n if (this.config.welcomeGreetingResponse !== undefined) {\n this.modelSend(conversationId, {\n type: 'response.create',\n response: this.config.welcomeGreetingResponse,\n });\n }\n }\n\n /**\n * The validated session config for this call: its own stashed override if it\n * has one, else the channel-wide default.\n *\n * @throws {Error} if neither exists, if it has no `model`, or if either audio\n * direction is set to a format Twilio can't carry.\n */\n private resolveSessionConfig(conversationId: ConversationId): Record<string, unknown> {\n const sessionConfig =\n this.pendingSessionConfigs.get(conversationId) ?? this.config.defaultSessionConfig;\n this.pendingSessionConfigs.delete(conversationId);\n\n if (sessionConfig === undefined) {\n throw new Error(\n `No sessionConfig available for call ${conversationId} — this call supplied none ` +\n \"and defaultSessionConfig isn't set either.\"\n );\n }\n if (!sessionConfig.model) {\n throw new Error(\n `sessionConfig for call ${conversationId} must include a 'model' field — it's used ` +\n 'as the ?model= query param when opening the OpenAI Realtime WebSocket.'\n );\n }\n\n const audio = (sessionConfig.audio ?? {}) as Record<string, unknown>;\n for (const direction of ['input', 'output'] as const) {\n const format = ((audio[direction] ?? {}) as Record<string, unknown>).format;\n if (!isTwilioMediaStreamAudioFormat(format)) {\n throw new Error(\n `sessionConfig for call ${conversationId} has audio.${direction}.format=` +\n `${JSON.stringify(format)}, expected ` +\n `${JSON.stringify(TWILIO_AUDIO_FORMAT_FOR_REALTIME)}. Twilio Media Streams is ` +\n `always 8kHz G.711 u-law; set audio.${direction}.format to ` +\n `TWILIO_AUDIO_FORMAT_FOR_REALTIME.`\n );\n }\n }\n\n return sessionConfig;\n }\n\n /**\n * Wire up the model socket: dispatch its events, and tear the call down when\n * it goes away.\n *\n * The Python SDK races its two read loops so the Twilio leg dies with the\n * model leg; `ws` is event-driven, so the same guarantee is a close/error\n * handler instead. Python's sequential read loop also handles each model\n * event to completion before reading the next, which `ws` does not — see\n * {@link CallState.modelEvents} for the chain that restores it.\n */\n private attachModelHandlers(conversationId: ConversationId, modelWs: WebSocket): void {\n modelWs.on('message', (raw: Buffer | string) => {\n const call = this.calls.get(conversationId);\n if (call === undefined) {\n return;\n }\n // `handleModelMessage` swallows its own failures, so the chain cannot\n // reject; the catch keeps one escaped bug from poisoning the tail and\n // silently dropping every event after it.\n call.modelEvents = call.modelEvents\n .then(() => this.handleModelMessage(conversationId, raw))\n .catch((err: unknown) => {\n this.logger.error(\n { err, conversation_id: conversationId },\n 'Unhandled error in model message handler'\n );\n });\n });\n\n modelWs.on('close', () => {\n // Still tracked means the model leg went first and closed cleanly: an\n // ordinary Twilio `stop` has already run cleanup, which closed this\n // socket itself, and a model-socket error has already logged itself.\n if (this.calls.has(conversationId)) {\n this.logger.info({ conversation_id: conversationId }, 'Model connection ended');\n }\n this.endCallFromModel(conversationId);\n });\n\n modelWs.on('error', (error: Error) => {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Model socket error');\n this.endCallFromModel(conversationId);\n });\n }\n\n /**\n * Hang up the Twilio leg because the model leg is gone, then clean up. A\n * no-op once the call has already been cleaned up, so both the model socket's\n * `close` and its `error` can call it.\n */\n private endCallFromModel(conversationId: ConversationId): void {\n this.calls.get(conversationId)?.twilioWs?.close();\n void this.cleanupCall(conversationId).catch((err: unknown) => {\n this.logger.error({ err, conversation_id: conversationId }, 'Call cleanup error');\n });\n }\n\n /** Apply one parsed OpenAI Realtime event to the call. */\n protected override async dispatchModelEvent(\n conversationId: ConversationId,\n session: ConversationSession,\n event: Record<string, unknown>\n ): Promise<void> {\n const call = this.calls.get(conversationId);\n if (call === undefined) {\n return;\n }\n const bargeIn = call.bargeIn;\n\n switch (event.type) {\n case 'error': {\n const error = (event.error ?? {}) as Record<string, unknown>;\n if (error.code === 'response_cancel_not_active') {\n // Benign race: a `response.cancel` sent while a response was in\n // flight lost to the model's own `response.done`. There is nothing\n // left to cancel, which is exactly what was wanted.\n this.logger.debug(\n { conversation_id: conversationId, error },\n 'response.cancel raced response.done'\n );\n } else {\n this.logger.error(\n { conversation_id: conversationId, error },\n 'OpenAI Realtime error event'\n );\n }\n break;\n }\n\n case 'input_audio_buffer.speech_started': {\n this.logger.debug({ conversation_id: conversationId }, 'Caller speech detected (VAD)');\n this.handleBargeIn(conversationId, session, call);\n break;\n }\n\n case 'response.created': {\n bargeIn.responseActive = true;\n break;\n }\n\n case 'conversation.item.input_audio_transcription.completed': {\n if (typeof event.transcript === 'string' && event.transcript) {\n this.appendTranscript(session, 'user', event.transcript);\n }\n break;\n }\n\n case 'response.output_item.done': {\n // Fires per item, ahead of `response.done`, for lower tool-call\n // latency. Only \"completed\" calls are run: one cut short by an\n // interruption can carry a truncated `arguments` fragment.\n const item = (event.item ?? {}) as Record<string, unknown>;\n if (item.type === 'function_call' && item.status === 'completed') {\n await this.handleFunctionCall(conversationId, item);\n }\n break;\n }\n\n case 'response.done': {\n // `lastAssistantItem` stays set — the model generates faster than\n // realtime, so Twilio may still be playing this reply. `responseActive`\n // clears, though: there is nothing left to cancel.\n bargeIn.responseActive = false;\n const response = (event.response ?? {}) as Record<string, unknown>;\n const output = Array.isArray(response.output) ? response.output : [];\n for (const entry of output as Record<string, unknown>[]) {\n if (entry.role !== 'assistant') {\n continue;\n }\n const contents = Array.isArray(entry.content) ? entry.content : [];\n for (const content of contents as Record<string, unknown>[]) {\n if (typeof content.transcript === 'string' && content.transcript) {\n this.appendTranscript(session, 'assistant', content.transcript);\n }\n }\n }\n break;\n }\n\n case 'response.output_audio.delta': {\n const delta = event.delta;\n if (typeof delta !== 'string' || !delta) {\n break;\n }\n const itemId = typeof event.item_id === 'string' ? event.item_id : '';\n if (itemId && itemId === bargeIn.mutedItemId) {\n // Stale audio for an item already truncated by a barge-in.\n break;\n }\n if (itemId && itemId !== bargeIn.lastAssistantItem) {\n bargeIn.lastAssistantItem = itemId;\n bargeIn.currentItemAudioMs = 0;\n }\n bargeIn.currentItemAudioMs += Math.floor(\n Buffer.from(delta, 'base64').length / PCMU_BYTES_PER_MS\n );\n this.twilioSend(conversationId, {\n event: 'media',\n streamSid: session.metadata.streamSid,\n media: { payload: delta },\n });\n break;\n }\n\n default:\n break;\n }\n }\n\n /** Record one turn on the session's running transcript. */\n private appendTranscript(session: ConversationSession, role: string, text: string): void {\n const existing = session.metadata.transcript;\n const transcript = Array.isArray(existing) ? (existing as Record<string, string>[]) : [];\n if (transcript !== existing) {\n session.metadata.transcript = transcript;\n }\n transcript.push({ role, text });\n }\n\n /**\n * The caller started talking. Cancel any response still generating, truncate\n * the model's memory of the last reply at the point actually heard, then\n * clear Twilio's buffered audio so playback stops immediately.\n *\n * If no assistant audio has been sent since the last barge-in this is a\n * no-op: there is nothing queued at Twilio to clear, no item id to name in a\n * truncate, and any response still generating is left to run.\n */\n private handleBargeIn(\n conversationId: ConversationId,\n session: ConversationSession,\n call: CallState\n ): void {\n const bargeIn = call.bargeIn;\n\n const lastAssistantItem = bargeIn.lastAssistantItem;\n if (lastAssistantItem === null) {\n this.logger.debug(\n { conversation_id: conversationId },\n 'Barge-in: no assistant item to interrupt'\n );\n return;\n }\n\n this.logger.debug({ conversation_id: conversationId }, 'Barge-in: truncating assistant reply');\n if (bargeIn.responseActive) {\n // Stop the model generating more of a reply nobody will hear — it would\n // otherwise keep burning tokens on discarded audio. Only while a\n // response is actually in flight: `response.cancel` with nothing to\n // cancel is itself an error event.\n this.modelSend(conversationId, { type: 'response.cancel' });\n bargeIn.responseActive = false;\n }\n this.modelSend(conversationId, {\n type: 'conversation.item.truncate',\n item_id: lastAssistantItem,\n content_index: 0,\n // Derived from bytes actually sent for this item, so for every delta\n // that carried an `item_id` it can never overstate the duration —\n // `conversation.item.truncate` rejects an `audio_end_ms` past the item's\n // real content.\n audio_end_ms: bargeIn.currentItemAudioMs,\n });\n this.twilioSend(conversationId, { event: 'clear', streamSid: session.metadata.streamSid });\n\n // Past the guard above, so a reply really was playing when the caller cut\n // in. `currentItemAudioMs` is how much of it they heard, the same quantity\n // ConversationRelay reports as `durationUntilInterruptMs`.\n trackEvent('Voice Interrupt', {\n account_sid: this.tacConfig.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n duration_until_interrupt_ms: bargeIn.currentItemAudioMs,\n provider: this.providerId,\n orchestrator_enabled: this.tacConfig.isOrchestratorEnabled(),\n });\n\n bargeIn.mutedItemId = lastAssistantItem;\n bargeIn.lastAssistantItem = null;\n bargeIn.currentItemAudioMs = 0;\n }\n\n /**\n * Run a model-requested tool call and hand the result back.\n *\n * Always sends a `function_call_output` once a `call_id` is present — even a\n * tool that ran successfully can return something `JSON.stringify` throws on\n * (a circular object, a `BigInt`) or has no JSON form at all, which\n * `JSON.stringify` reports by returning `undefined` rather than throwing (a\n * void tool, a bare function, a `Symbol`). Either way the model would\n * otherwise be left waiting on a `call_id` it never gets a result for.\n * Without a `call_id` there is nothing to reply to, so the item is dropped\n * instead.\n */\n private async handleFunctionCall(\n conversationId: ConversationId,\n item: Record<string, unknown>\n ): Promise<void> {\n const callId = item.call_id;\n if (typeof callId !== 'string' || !callId) {\n // Keys only, never the item: `arguments` carries whatever the caller\n // said, so logging it verbatim would put conversation content in logs.\n this.logger.error(\n { conversation_id: conversationId, item_keys: Object.keys(item) },\n 'Received malformed function_call item without call_id'\n );\n return;\n }\n\n const name = item.name;\n let output: string;\n if (typeof name !== 'string' || !name) {\n // No name means no tool can be selected, so none runs.\n this.logger.error(\n { conversation_id: conversationId, call_id: callId, item_keys: Object.keys(item) },\n 'Received malformed function_call item without tool name'\n );\n output = JSON.stringify({ error: 'Malformed function call: missing tool name.' });\n } else {\n const result = await this.runToolCall(conversationId, name, item.arguments);\n try {\n // `JSON.stringify` returns `undefined`, not a string, for a value with\n // no JSON form (a void tool, a bare function): `null` keeps the reply\n // addressed to `call_id` instead of dropping the required field.\n const serialized: string | undefined = JSON.stringify(result);\n output = serialized ?? 'null';\n } catch (err) {\n this.logger.error(\n { err, conversation_id: conversationId, tool_name: name },\n 'Tool returned a non-JSON-serializable result'\n );\n output = JSON.stringify({ error: `Tool '${name}' returned a non-serializable result.` });\n }\n }\n\n this.modelSend(conversationId, {\n type: 'conversation.item.create',\n item: { type: 'function_call_output', call_id: callId, output },\n });\n this.modelSend(conversationId, { type: 'response.create' });\n }\n\n /**\n * Drop this call's transport state, close the model socket, and end the\n * session.\n *\n * Both legs can report the call ending, and the first one to arrive tears\n * down the other, so this runs at most once per call: a second invocation\n * finds nothing tracked and returns.\n */\n private async cleanupCall(conversationId: ConversationId): Promise<void> {\n const call = this.calls.get(conversationId);\n if (call === undefined) {\n return;\n }\n this.calls.delete(conversationId);\n\n if (call.modelWs !== null) {\n try {\n call.modelWs.close();\n } catch (err) {\n this.logger.debug({ err, conversation_id: conversationId }, 'Error closing model socket');\n }\n }\n await this.channel.endConversationInternal(conversationId);\n }\n}\n","import type { TACTool } from '@twilio/tac-tools';\nimport type { TACConfig } from '../../../../lib/config';\nimport type { TwiMLRequest } from '../../../../types/index';\nimport type { VoiceChannel } from '../../channel';\nimport type { VoiceProvider } from '../../provider';\nimport { MediaStreamsOpenAIProviderConfig } from '../shared/config';\nimport type { MediaStreamsOpenAIProviderConfigOptions } from '../shared/config';\nimport { OpenAIRealtimeProvider } from './provider';\n\n/**\n * Options accepted by {@link OpenAIRealtimeProviderConfig}.\n */\nexport interface OpenAIRealtimeProviderConfigOptions extends MediaStreamsOpenAIProviderConfigOptions {\n /**\n * Executable `TACTool` implementations, looked up by name to run mid-call\n * tool requests. This alone does not tell the model these tools exist — also\n * add each tool's `toRealtimeFormat()` schema to\n * {@link OpenAIRealtimeProviderConfigOptions.defaultSessionConfig}'s `tools`\n * entry.\n */\n // `never`, not `unknown`: `implementation` is a property, so its parameter is\n // contravariant and `TACTool[]` would reject every tool with typed params.\n tools?: TACTool<never, unknown>[];\n\n /**\n * If set, sent verbatim as `response.create`'s `response` payload when the\n * call connects — e.g. `{ instructions: 'Hi there!' }`. No SDK-added wrapping\n * text or language assumption.\n */\n welcomeGreetingResponse?: Record<string, unknown>;\n\n /**\n * The `session.update` payload's `session` body, sent once the model connects\n * — used for any call that doesn't supply its own via\n * {@link OpenAIRealtimeProviderConfigOptions.onInboundCallSessionConfig} or\n * `InitiateVoiceConversationOptionsOpenAIRealtime`.\n *\n * See\n * https://developers.openai.com/api/reference/resources/realtime/client-events#session.update\n * for the schema. If using {@link OpenAIRealtimeProviderConfigOptions.tools},\n * its `tools` entry must separately list each tool's `toRealtimeFormat()`\n * schema — this config is passed to OpenAI as-is, with no tool schemas merged\n * in.\n */\n defaultSessionConfig?: Record<string, unknown>;\n\n /**\n * Per-inbound-call override for\n * {@link OpenAIRealtimeProviderConfigOptions.defaultSessionConfig}, called\n * with the `TwiMLRequest`. Its return value is used verbatim (not merged with\n * `defaultSessionConfig`); return `null` to fall back to it. Outbound calls\n * don't use this — see `InitiateVoiceConversationOptionsOpenAIRealtime`.\n */\n onInboundCallSessionConfig?: (req: TwiMLRequest) => Promise<Record<string, unknown> | null>;\n}\n\n/**\n * Configuration for `OpenAIRealtimeProvider`.\n */\nexport class OpenAIRealtimeProviderConfig extends MediaStreamsOpenAIProviderConfig {\n /**\n * Executable `TACTool` implementations, looked up by name to run mid-call\n * tool requests. This alone does not tell the model these tools exist — also\n * add each tool's `toRealtimeFormat()` schema to\n * {@link OpenAIRealtimeProviderConfig.defaultSessionConfig}'s `tools` entry.\n */\n // See the `never` note on `OpenAIRealtimeProviderConfigOptions.tools`.\n //\n // `declare`: `target: ES2022` implies `useDefineForClassFields`, so a plain\n // redeclaration would emit a field definition that runs after `super()` and\n // overwrite the value the base constructor assigned with `undefined`. These\n // three exist only to carry Realtime-specific TSDoc onto the docs site.\n declare public readonly tools: TACTool<never, unknown>[];\n\n /**\n * If set, sent verbatim as `response.create`'s `response` payload when the\n * call connects — e.g. `{ instructions: 'Hi there!' }`. No SDK-added wrapping\n * text or language assumption.\n */\n public readonly welcomeGreetingResponse?: Record<string, unknown>;\n\n /**\n * The `session.update` payload's `session` body, sent once the model connects\n * — used for any call that doesn't supply its own via\n * {@link OpenAIRealtimeProviderConfig.onInboundCallSessionConfig} or\n * `InitiateVoiceConversationOptionsOpenAIRealtime`.\n *\n * See\n * https://developers.openai.com/api/reference/resources/realtime/client-events#session.update\n * for the schema. If using {@link OpenAIRealtimeProviderConfig.tools}, its\n * `tools` entry must separately list each tool's `toRealtimeFormat()` schema\n * — this config is passed to OpenAI as-is, with no tool schemas merged in.\n */\n declare public readonly defaultSessionConfig?: Record<string, unknown>;\n\n /**\n * Per-inbound-call override for\n * {@link OpenAIRealtimeProviderConfig.defaultSessionConfig}, called with the\n * `TwiMLRequest`. Its return value is used verbatim (not merged with\n * `defaultSessionConfig`); return `null` to fall back to it. Outbound calls\n * don't use this — see `InitiateVoiceConversationOptionsOpenAIRealtime`.\n */\n declare public readonly onInboundCallSessionConfig?: (\n req: TwiMLRequest\n ) => Promise<Record<string, unknown> | null>;\n\n constructor(options?: OpenAIRealtimeProviderConfigOptions) {\n super(options);\n\n if (options?.welcomeGreetingResponse !== undefined) {\n this.welcomeGreetingResponse = options.welcomeGreetingResponse;\n }\n }\n\n public override createProvider(channel: VoiceChannel, tacConfig: TACConfig): VoiceProvider {\n return new OpenAIRealtimeProvider(channel, tacConfig, this);\n }\n}\n","import { MediaStreamsOpenAICallState } from '../shared';\n\n/**\n * Per-call bookkeeping `GPTLiveProvider` needs beyond `ConversationSession`.\n *\n * @internal\n */\nexport class CallState extends MediaStreamsOpenAICallState {\n /**\n * Settles once `session.closed` arrives, so teardown can wait for graceful\n * finalization before tearing the socket down.\n */\n readonly closed: Promise<void>;\n\n private readonly resolveClosed: () => void;\n\n constructor() {\n super();\n let resolve!: () => void;\n this.closed = new Promise<void>(r => {\n resolve = r;\n });\n this.resolveClosed = resolve;\n }\n\n markClosed(): void {\n this.resolveClosed();\n }\n}\n","import type { WebSocket } from 'ws';\nimport {\n MediaStreamsOpenAIProvider,\n OPENAI_USER_AGENT,\n describeIssues,\n} from '../shared/openai-provider';\nimport {\n InitiateVoiceConversationOptionsGPTLiveSchema,\n StreamStartMessageSchema,\n callOptionsToCreateParams,\n type ConversationId,\n type ConversationSession,\n type InitiateVoiceConversationOptions,\n type InitiateVoiceConversationOptionsGPTLive,\n} from '../../../../types/index';\nimport type { InitiateVoiceConversationResult } from '../../../../types/conversation';\nimport { maskPhone, redactTwimlParameters } from '../../../../util/log-redaction';\nimport { trackEvent } from '../../../../lib/analytics';\nimport type { GPTLiveProviderConfig } from './config';\nimport { CallState } from './state';\n\n/**\n * The audio format both directions of a call must use.\n *\n * Twilio Media Streams always sends and expects 8kHz G.711 u-law — see\n * https://www.twilio.com/docs/voice/media-streams/websocket-messages. Not\n * configurable. GPT-Live speaks it natively on both legs, so a single\n * `session.audio.format` covers input and output and nothing transcodes.\n *\n * Spelled with an explicit `rate`, which GPT-Live's schema wants and Realtime's\n * rejects — that is why this is a separate constant from\n * `TWILIO_AUDIO_FORMAT_FOR_REALTIME` rather than a shared one.\n */\nexport const TWILIO_AUDIO_FORMAT_FOR_GPT_LIVE = { type: 'audio/pcmu', rate: 8000 } as const;\n\n/**\n * `ConversationSession.metadata` key holding OpenAI's id for the GPT-Live\n * session behind this call, set once `session.started` arrives. Quote it to\n * OpenAI support when reporting a session.\n *\n * Opaque: the prefix differs across GPT-Live's alpha (`rtc_`) and GA (`live_`),\n * so never parse it, validate it, or branch on it.\n */\nexport const GPT_LIVE_SESSION_ID_METADATA_KEY = 'gpt_live_session_id';\n\n/**\n * Reserved <Stream> customParameters key correlating an outbound call's\n * sessionConfig override to its WebSocket start event.\n */\nconst SESSION_CONFIG_TOKEN_PARAM = '_tac_session_config_token';\n\n/**\n * How long a pending sessionConfig entry may outlive its outbound call before\n * it is purged — covers no-answer, busy, and every other outcome where Twilio\n * never connects the media stream to consume it via `registerCall`.\n */\nconst SESSION_CONFIG_TOKEN_TTL_MS = 120_000;\n\n/**\n * The GPT-Live endpoint. Unlike Realtime's, it carries no `?model=` query\n * param — the model is named inside the `session.start` payload instead.\n */\nconst GPT_LIVE_URL = 'wss://api.openai.com/v1/live/sessions';\n\n/**\n * How long teardown waits for the `session.closed` acknowledging its\n * `session.close`, before dropping the socket anyway.\n *\n * A timeout is tolerable: the handshake only lets the server finalize the\n * session cleanly, and the call is over either way — so a server that never\n * answers must not hold the caller's teardown open indefinitely.\n */\nconst CLOSE_TIMEOUT_MS = 5_000;\n\n/**\n * Whether `value` is exactly {@link TWILIO_AUDIO_FORMAT_FOR_GPT_LIVE}.\n *\n * Compared field by field rather than by serializing both sides, so key order\n * in a caller's session config can't decide the answer.\n */\nfunction isTwilioMediaStreamAudioFormat(value: unknown): boolean {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const expected: Record<string, unknown> = TWILIO_AUDIO_FORMAT_FOR_GPT_LIVE;\n const actual = value as Record<string, unknown>;\n const keys = Object.keys(actual);\n return (\n keys.length === Object.keys(expected).length && keys.every(key => actual[key] === expected[key])\n );\n}\n\n/**\n * Await `promise`, giving up after `ms`. Resolves true if it settled first,\n * false on timeout.\n *\n * The `finally` is load-bearing, not tidiness: a bare `Promise.race` leaves the\n * losing timer armed, so a wait that settled early still holds the event loop\n * open for the full timeout.\n */\nasync function waitWithTimeout(promise: Promise<void>, ms: number): Promise<boolean> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<boolean>(resolve => {\n timer = setTimeout(() => resolve(false), ms);\n });\n try {\n return await Promise.race([promise.then(() => true), timeout]);\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * A {@link VoiceProvider} bridging Twilio Media Streams to OpenAI's GPT-Live\n * API.\n */\nexport class GPTLiveProvider extends MediaStreamsOpenAIProvider<CallState> {\n /** @internal */\n public override get providerId(): string {\n return 'gpt_live';\n }\n\n /**\n * No `override`: TypeScript rejects it alongside `declare` (TS1243), and\n * `declare` is what keeps this a pure type narrowing of the base's field\n * rather than a second field that shadows it.\n */\n declare protected readonly config: GPTLiveProviderConfig;\n\n private readonly pendingTokenExpiries = new Map<string, ReturnType<typeof setTimeout>>();\n\n /** Calls whose teardown has begun but is still awaiting `session.closed`. */\n private readonly closingCalls = new Set<ConversationId>();\n\n public override get channelName(): string {\n return 'VOICE_MEDIA_STREAM_OPENAI_GPT_LIVE';\n }\n\n // =========================================================================\n // Outbound Call Handling\n // =========================================================================\n\n /**\n * Initiate an outbound voice conversation.\n *\n * Places an outbound call with inline TwiML that connects to a Media Stream.\n * Unlike inbound, there is no local session yet at this point — one is\n * created when Twilio's WebSocket `start` event arrives.\n *\n * TwiML fields are merged per-field — see\n * {@link TwiMLBuilderMediaStreams.build}. The WebSocket URL is derived from\n * `TACConfig.voicePublicDomain` + `TACConfig.voiceWebsocketPath` unless\n * overridden per-call via `options.websocketUrl`.\n *\n * Pass `InitiateVoiceConversationOptionsGPTLive` with `sessionConfig` set to\n * override `GPTLiveProviderConfig.defaultSessionConfig` for this call.\n *\n * @param options - Outbound call options.\n * @throws {TypeError} if `options` does not satisfy\n * `InitiateVoiceConversationOptionsGPTLiveSchema`.\n * @throws {Error} if no WebSocket URL can be resolved — neither\n * `options.websocketUrl` nor any TwiML layer sets one and\n * `TACConfig.voicePublicDomain` is unset.\n */\n public override async initiateOutboundConversation(\n options: InitiateVoiceConversationOptions | InitiateVoiceConversationOptionsGPTLive\n ): Promise<InitiateVoiceConversationResult> {\n // Validate the whole options object, not just twimlOptions: this is the\n // only gate between a host's input and `calls.create()`, and it's what\n // makes the schema's `.strict()` upgrade guard fire for this provider.\n // Python gets the same coverage for free from Pydantic; TypeScript has no\n // runtime type to lean on.\n const parsedOptions = InitiateVoiceConversationOptionsGPTLiveSchema.safeParse(options);\n if (!parsedOptions.success) {\n throw new TypeError(\n 'GPTLiveProvider.initiateOutboundConversation requires options to be an ' +\n `InitiateVoiceConversationOptionsGPTLive: ${describeIssues(parsedOptions.error.issues)}`\n );\n }\n const validated = parsedOptions.data;\n let twimlOptions = validated.twimlOptions;\n\n // Why a token instead of the call SID. `calls.create()` returning\n // `call.sid` does not happen-before Twilio connecting the media stream, so\n // the SID is not yet a usable correlation key when the `start` event may\n // already be arriving. The token is embedded in the TwiML before the call\n // is placed, so it always is.\n //\n // Minting it here touches nothing shared: the map is only written once the\n // TwiML has been built, so a `build()` failure has nothing to leak.\n const sessionConfig = validated.sessionConfig ?? null;\n let sessionConfigToken: string | null = null;\n if (sessionConfig !== null) {\n sessionConfigToken = crypto.randomUUID().replace(/-/g, '');\n // Rebuilt rather than mutated because `twimlOptions` is absent whenever\n // the caller omitted it — there is no object to assign the token into,\n // and the caller's own object is never written through.\n twimlOptions = {\n ...twimlOptions,\n customParameters: {\n ...twimlOptions?.customParameters,\n [SESSION_CONFIG_TOKEN_PARAM]: sessionConfigToken,\n },\n };\n }\n\n const fromNumber = this.tacConfig.phoneNumber;\n\n this.logger.info(\n { to: maskPhone(validated.to), from: maskPhone(fromNumber) },\n 'Initiating outbound voice conversation'\n );\n\n // Outbound has no inbound customizer and no host layer; the per-call\n // override is options.twimlOptions. `options.websocketUrl` is the dedicated\n // per-call outbound override and wins over any websocketUrl that came\n // through the layered twimlOptions merge.\n const twiml = this.twimlBuilder.build('initiateOutboundConversation', {\n perCall: twimlOptions,\n websocketUrl: validated.websocketUrl,\n });\n\n const callParams = this.applyCallEventCallbacks(\n validated.callOptions ? callOptionsToCreateParams(validated.callOptions) : {}\n );\n\n if (sessionConfigToken !== null && sessionConfig !== null) {\n this.pendingSessionConfigs.set(sessionConfigToken, sessionConfig);\n }\n\n try {\n // The inline TwiML handed to Twilio. customParameters values are masked —\n // they're arbitrary developer data (profile IDs, caller names), unlike the\n // WebSocket URL.\n this.logger.debug(\n { twiml: redactTwimlParameters(twiml), to: maskPhone(validated.to) },\n 'Outbound call TwiML'\n );\n\n const client = this.channel.getTwilioClientInternal();\n const call = await client.calls.create({\n to: validated.to,\n from: fromNumber,\n twiml,\n ...callParams,\n });\n\n this.logger.info(\n { call_sid: call.sid, to: maskPhone(validated.to) },\n 'Outbound voice call placed'\n );\n\n if (sessionConfigToken !== null) {\n this.armTokenExpiry(sessionConfigToken);\n }\n\n return { callSid: call.sid };\n } catch (error) {\n if (sessionConfigToken !== null) {\n this.pendingSessionConfigs.delete(sessionConfigToken);\n }\n this.logger.error(\n { err: error, to: maskPhone(validated.to) },\n 'Failed to initiate outbound call'\n );\n // Deliberately not routed through `channel.handleErrorInternal`, unlike\n // ConversationRelayProvider: this matches the Python SDK, where an\n // outbound failure is the caller's to handle and is surfaced only by the\n // rethrow below.\n throw error;\n }\n }\n\n /**\n * Start the clock on a stashed token, so a call that never connects cannot\n * strand its override in {@link pendingSessionConfigs} forever.\n *\n * Unref'd: a two-minute timer must not be what keeps the process alive after\n * the call it belongs to is long over.\n */\n private armTokenExpiry(token: string): void {\n const timer = setTimeout(() => {\n this.pendingTokenExpiries.delete(token);\n this.pendingSessionConfigs.delete(token);\n }, SESSION_CONFIG_TOKEN_TTL_MS);\n timer.unref();\n this.pendingTokenExpiries.set(token, timer);\n }\n\n /**\n * Stop the clock on a token, once the call it belongs to has claimed it.\n *\n * Without this a two-minute timer outlives every call that connected\n * normally, waiting to purge an entry that is already gone.\n */\n private cancelTokenExpiry(token: string): void {\n const timer = this.pendingTokenExpiries.get(token);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.pendingTokenExpiries.delete(token);\n }\n }\n\n // =========================================================================\n // Audio Bridge\n // =========================================================================\n\n /**\n * Drive one Twilio Media Stream connection from `start` to disconnect.\n *\n * Twilio's `start` event names the call, which opens the matching GPT-Live\n * socket; from then on caller audio is relayed to the model and the model's\n * audio back to Twilio, until either side goes away. Whichever leg closes\n * first takes the other down with it, so a caller is never left connected to\n * silence.\n *\n * Twilio streams audio without waiting for the GPT-Live socket to finish\n * connecting, so audio that arrives during that handshake is held and\n * forwarded, in order, once the model is ready — a caller who speaks the\n * instant the call connects is heard in full.\n *\n * Called by `VoiceChannel.handleWebSocketConnection`; hosts serve the socket\n * rather than calling this directly.\n *\n * @param ws - The accepted Twilio-facing WebSocket.\n */\n public override handleWebSocket(ws: WebSocket): void {\n let conversationId: ConversationId | null = null;\n\n ws.on('message', (data: Buffer) => {\n // `EventEmitter` invokes this later with nothing awaiting it, so an async\n // body's rejection would surface as an unhandled rejection. Own it here.\n void (async (): Promise<void> => {\n const message = JSON.parse(data.toString()) as Record<string, unknown>;\n const event = typeof message.event === 'string' ? message.event : '';\n\n if (event === 'start') {\n const registered = this.registerCall(message.start, ws);\n conversationId = registered.conversationId;\n // Published on the call before the first `await`, so caller audio\n // arriving mid-handshake always finds something to wait on. Mapped to\n // a boolean so waiting frames observe the outcome without re-raising\n // the failure the outer `.catch` below already owns.\n const connecting = this.connectModel(registered.conversationId);\n registered.call.modelReady = connecting.then(\n () => true,\n () => false\n );\n await connecting;\n } else if (event === 'media') {\n const media = (message.media ?? {}) as Record<string, unknown>;\n const payload = media.payload;\n if (conversationId !== null && typeof payload === 'string' && payload) {\n // Twilio does not wait for the GPT-Live handshake before streaming,\n // so hold this frame until the model socket exists instead of\n // discarding the caller's first word. See `modelReady` for why\n // ordering survives the wait.\n const call = this.calls.get(conversationId);\n if (call === undefined) {\n return;\n }\n if (call.modelReady !== null && !(await call.modelReady)) {\n // The handshake failed and the `start` branch above has already\n // logged it and ended the call. Drop the frame without comment.\n return;\n }\n this.modelSend(conversationId, {\n type: 'session.input_audio.append',\n audio: payload,\n });\n }\n } else if (event === 'stop') {\n this.logger.info({ conversation_id: conversationId }, 'Media stream stopped');\n if (conversationId !== null) {\n await this.cleanupCall(conversationId);\n }\n // Python returns from its endpoint here, which drops the connection;\n // an event handler has no such exit, so close the leg explicitly.\n ws.close();\n }\n })().catch((err: unknown) => {\n // Python breaks its read loop on any exception and cleans up in the\n // `finally`; closing here reaches the same end through the `close`\n // handler below, rather than holding the caller on a line to nothing.\n this.logger.error({ err, conversation_id: conversationId }, 'Media stream WebSocket error');\n ws.close();\n });\n });\n\n ws.on('close', () => {\n this.logger.info({ conversation_id: conversationId }, 'Media stream WebSocket closed');\n if (conversationId !== null) {\n trackEvent('Websocket Disconnected', {\n account_sid: this.tacConfig.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n provider: this.providerId,\n orchestrator_enabled: this.tacConfig.isOrchestratorEnabled(),\n });\n void this.cleanupCall(conversationId).catch((err: unknown) => {\n this.logger.error({ err, conversation_id: conversationId }, 'Call cleanup error');\n });\n }\n });\n\n ws.on('error', (error: Error) => {\n // Routed to the host, unlike the outbound-call failure above: that one is\n // rethrown, so its caller already sees it. A socket error has no caller\n // to rethrow to, so logging alone would hide it from the host entirely.\n this.channel.handleErrorInternal(error, { conversationId });\n });\n }\n\n /**\n * Handle Twilio's `start` event: track the call and open its session.\n *\n * @param start - The event's `start` body, parsed against\n * `StreamStartMessageSchema`.\n * @param ws - The Twilio-facing socket this call arrived on.\n * @returns The conversation id — which is the call SID — and the call's\n * freshly tracked transport state.\n */\n private registerCall(\n start: unknown,\n ws: WebSocket\n ): { conversationId: ConversationId; call: CallState } {\n const message = StreamStartMessageSchema.parse(start ?? {});\n const conversationId = message.callSid as ConversationId;\n\n // This call's Media Stream connected, so an inbound override stashed when\n // the TwiML was answered is about to be consumed — stop its expiry timer.\n // A no-op for outbound calls, which arm no such timer.\n this.cancelInboundConfigExpiry(conversationId);\n\n // An outbound override was stashed under a token before the call was\n // placed, because its SID wasn't known yet. Twilio hands the token back\n // here, which is the first point the two can be joined up.\n const token = message.customParameters[SESSION_CONFIG_TOKEN_PARAM];\n if (token !== undefined) {\n const pending = this.pendingSessionConfigs.get(token);\n if (pending !== undefined) {\n this.pendingSessionConfigs.delete(token);\n this.pendingSessionConfigs.set(conversationId, pending);\n }\n this.cancelTokenExpiry(token);\n }\n\n const call = new CallState();\n call.twilioWs = ws;\n this.calls.set(conversationId, call);\n\n try {\n // No profile id: this provider's session lifecycle is independent of\n // Conversation Orchestrator, like ConversationRelay's relay-only mode.\n const session = this.channel.startConversationInternal(conversationId);\n session.callSid = message.callSid;\n session.metadata.streamSid = message.streamSid;\n session.metadata.transcript = [];\n\n trackEvent('Conversation Initialized', {\n account_sid: this.tacConfig.accountSid,\n channel: 'voice',\n conversation_id: conversationId,\n provider: this.providerId,\n orchestrator_enabled: this.tacConfig.isOrchestratorEnabled(),\n });\n } catch (err) {\n // startConversationInternal inserts the session before invoking the\n // host's onConversationStarted callback unguarded. A throw from that\n // callback unwinds registerCall before handleWebSocket has learned the\n // conversation id, so its catch path can't reach this call to tear it\n // down. Roll back what this method registered: the transport entry, the\n // pending config just re-keyed under this id, and the started session.\n this.calls.delete(conversationId);\n this.pendingSessionConfigs.delete(conversationId);\n void this.channel.endConversationInternal(conversationId).catch(() => undefined);\n throw err;\n }\n\n this.logger.debug(\n { conversation_id: conversationId, media_format: message.mediaFormat },\n 'Media stream started'\n );\n return { conversationId, call };\n }\n\n /**\n * Open this call's GPT-Live socket and send its session config.\n *\n * @internal\n */\n public async connectModel(conversationId: ConversationId): Promise<void> {\n const sessionConfig = this.resolveSessionConfig(conversationId);\n\n const modelWs = await this.openModelSocket(GPT_LIVE_URL, {\n Authorization: `Bearer ${this.config.openaiApiKey}`,\n 'User-Agent': OPENAI_USER_AGENT,\n });\n\n const call = this.calls.get(conversationId);\n if (call === undefined) {\n // The call ended while the handshake was in flight. Nothing tracks this\n // socket now, so close it rather than leak it.\n modelWs.close();\n return;\n }\n call.modelWs = modelWs;\n this.attachModelHandlers(conversationId, modelWs);\n this.logger.info({ conversation_id: conversationId }, 'Connected to GPT-Live');\n\n this.modelSend(conversationId, { type: 'session.start', session: sessionConfig });\n // `welcomeInstruction` is sent once `session.started` arrives, not here —\n // unlike the Realtime provider, which requests its greeting at connect time.\n }\n\n /**\n * The validated session config for this call: its own stashed override if it\n * has one, else the channel-wide default.\n *\n * @throws {Error} if neither exists, if the audio format is one Twilio can't\n * carry, or if it names no model.\n */\n private resolveSessionConfig(conversationId: ConversationId): Record<string, unknown> {\n const sessionConfig =\n this.pendingSessionConfigs.get(conversationId) ?? this.config.defaultSessionConfig;\n this.pendingSessionConfigs.delete(conversationId);\n\n if (sessionConfig === undefined) {\n throw new Error(\n `No sessionConfig available for call ${conversationId} — this call supplied none ` +\n 'and defaultSessionConfig is not set either.'\n );\n }\n\n const audio = (sessionConfig.audio ?? {}) as Record<string, unknown>;\n if (!isTwilioMediaStreamAudioFormat(audio.format)) {\n throw new Error(\n `sessionConfig for call ${conversationId} has audio.format=` +\n `${JSON.stringify(audio.format)}, expected ` +\n `${JSON.stringify(TWILIO_AUDIO_FORMAT_FOR_GPT_LIVE)}. Twilio Media Streams is ` +\n 'always 8kHz G.711 u-law; set audio.format to TWILIO_AUDIO_FORMAT_FOR_GPT_LIVE.'\n );\n }\n if (!sessionConfig.model) {\n throw new Error(`sessionConfig for call ${conversationId} must include 'model'.`);\n }\n\n return sessionConfig;\n }\n\n /**\n * Wire up the model socket: dispatch its events, and tear the call down when\n * it goes away.\n *\n * The Python SDK races its Twilio read against its model-event reader so the\n * Twilio leg dies with the model leg; `ws` is event-driven, so the same\n * guarantee is a close/error handler instead.\n */\n private attachModelHandlers(conversationId: ConversationId, modelWs: WebSocket): void {\n modelWs.on('message', (raw: Buffer | string) => {\n // `handleModelMessage` owns its own failures, so nothing here can reject.\n void this.handleModelMessage(conversationId, raw);\n });\n\n modelWs.on('close', () => {\n // Still tracked means the model leg went first: an ordinary Twilio `stop`\n // has already run cleanup, which closed this socket itself.\n if (this.calls.has(conversationId)) {\n this.logger.info({ conversation_id: conversationId }, 'Model connection ended');\n }\n this.endCallFromModel(conversationId);\n });\n\n modelWs.on('error', (error: Error) => {\n this.logger.error({ err: error, conversation_id: conversationId }, 'Model socket error');\n this.endCallFromModel(conversationId);\n });\n }\n\n /**\n * Hang up the Twilio leg because the model leg is gone, then clean up. A\n * no-op once the call has already been cleaned up, so both the model socket's\n * `close` and its `error` can call it.\n */\n private endCallFromModel(conversationId: ConversationId): void {\n this.calls.get(conversationId)?.twilioWs?.close();\n void this.cleanupCall(conversationId).catch((err: unknown) => {\n this.logger.error({ err, conversation_id: conversationId }, 'Call cleanup error');\n });\n }\n\n /**\n * Close this call's GPT-Live session gracefully, drop its transport state,\n * and end the session.\n *\n * `session.close` asks the server to finalize the session, and teardown waits\n * up to {@link CLOSE_TIMEOUT_MS} for the `session.closed` answering it before\n * the socket goes away — otherwise the socket would be gone before the server\n * could finish.\n *\n * Both legs can report the call ending, and the first one to arrive tears\n * down the other, so this runs at most once per call: a second invocation\n * finds the call either untracked or already closing, and returns.\n */\n private async cleanupCall(conversationId: ConversationId): Promise<void> {\n const call = this.calls.get(conversationId);\n if (call === undefined || this.closingCalls.has(conversationId)) {\n return;\n }\n // The call stays in `this.calls` across the wait below, unlike the sibling\n // provider's teardown: `session.closed` is dispatched through that map, so\n // dropping the entry first would make the acknowledgement unreachable and\n // send every graceful close through the timeout instead. This set is the\n // re-entrancy guard in its place, written before any `await` so a second\n // teardown of the same call cannot interleave with the first.\n this.closingCalls.add(conversationId);\n\n const modelWs = call.modelWs;\n if (modelWs !== null) {\n let requested = true;\n try {\n // Sent on the socket directly rather than through `modelSend`, which\n // reports a send on an untracked call by doing nothing at all — and\n // this call stops being tracked moments from now.\n modelWs.send(JSON.stringify({ type: 'session.close' }));\n } catch (err) {\n requested = false;\n this.logger.debug(\n { err, conversation_id: conversationId },\n 'Error sending session.close to model socket'\n );\n }\n if (requested) {\n try {\n const acknowledged = await waitWithTimeout(call.closed, CLOSE_TIMEOUT_MS);\n if (!acknowledged) {\n this.logger.debug(\n { conversation_id: conversationId },\n 'Timed out waiting for session.closed'\n );\n }\n } catch (err) {\n // Nothing rejects `call.closed` today, but an escaping throw here\n // would strand the call in both maps: every later teardown would\n // return early on the guard, so the session would never end.\n this.logger.debug(\n { err, conversation_id: conversationId },\n 'Error waiting for session.closed'\n );\n }\n }\n }\n\n this.calls.delete(conversationId);\n this.closingCalls.delete(conversationId);\n\n if (modelWs !== null) {\n try {\n modelWs.close();\n } catch (err) {\n this.logger.debug({ err, conversation_id: conversationId }, 'Error closing model socket');\n }\n }\n await this.channel.endConversationInternal(conversationId);\n }\n\n /**\n * Drop this provider's transport state on channel shutdown, including the\n * bookkeeping it keeps beyond the base class's.\n *\n * The token expiry timers are unref'd and delete themselves, so nothing hangs\n * without this — but a shut-down provider must not still be holding entries\n * for calls that can no longer arrive.\n */\n public override shutdown(): void {\n for (const timer of this.pendingTokenExpiries.values()) {\n clearTimeout(timer);\n }\n this.pendingTokenExpiries.clear();\n this.closingCalls.clear();\n super.shutdown();\n }\n\n /** Apply one parsed GPT-Live event to the call. */\n protected override async dispatchModelEvent(\n conversationId: ConversationId,\n session: ConversationSession,\n event: Record<string, unknown>\n ): Promise<void> {\n switch (event.type) {\n case 'error': {\n this.logger.error(\n { conversation_id: conversationId, error: event.error },\n 'GPT-Live error event'\n );\n break;\n }\n\n case 'session.closed': {\n // Carries the session snapshot too, so it is the backstop for a\n // `session.started` that never arrived or arrived malformed.\n this.recordGptLiveSessionId(conversationId, session, event);\n this.calls.get(conversationId)?.markClosed();\n break;\n }\n\n case 'session.started': {\n this.recordGptLiveSessionId(conversationId, session, event);\n // Sending `session.commentary.append` before this event is\n // undocumented behavior, so the greeting waits for it.\n const instruction = this.config.welcomeInstruction;\n if (instruction !== null) {\n this.modelSend(conversationId, {\n type: 'session.commentary.append',\n delegation_id: null,\n content: instruction,\n });\n }\n break;\n }\n\n case 'session.input_transcript.delta': {\n GPTLiveProvider.appendTranscriptDelta(session, 'user', event);\n break;\n }\n\n case 'session.output_transcript.delta': {\n GPTLiveProvider.appendTranscriptDelta(session, 'assistant', event);\n break;\n }\n\n case 'session.output_audio.delta': {\n // No item_id or barge-in bookkeeping: GPT-Live is full-duplex and\n // handles interruption server-side, so there is nothing to truncate.\n const delta = event.delta;\n if (typeof delta !== 'string' || !delta) {\n break;\n }\n this.twilioSend(conversationId, {\n event: 'media',\n streamSid: session.metadata.streamSid,\n media: { payload: delta },\n });\n break;\n }\n\n case 'response.event': {\n // Tool calls arrive wrapped: GPT-Live delegates them to Responses and\n // relays that API's own events inside this envelope.\n const inner = (event.event ?? {}) as Record<string, unknown>;\n if (inner.type !== 'response.output_item.done') {\n break;\n }\n const item = (inner.item ?? {}) as Record<string, unknown>;\n // Only `completed` runs: a call cut short mid-generation can carry a\n // truncated `arguments` fragment, so running it would feed the tool\n // garbage.\n if (item.type === 'function_call' && item.status === 'completed') {\n await this.handleFunctionCall(conversationId, item);\n }\n break;\n }\n\n default:\n break;\n }\n }\n\n /**\n * Run a Responses-delegated tool call and hand the result back.\n *\n * Always sends a `function_call_output` once a `call_id` is present — even a\n * tool that ran successfully can return something `JSON.stringify` throws on\n * (a circular object, a `BigInt`) or has no JSON form at all, which\n * `JSON.stringify` reports by returning `undefined` rather than throwing (a\n * void tool, a bare function, a `Symbol`). Either way the model would\n * otherwise be left waiting on a `call_id` it never gets a result for.\n * Without a `call_id` there is nothing to reply to, so the item is dropped\n * instead.\n */\n private async handleFunctionCall(\n conversationId: ConversationId,\n item: Record<string, unknown>\n ): Promise<void> {\n const callId = item.call_id;\n if (typeof callId !== 'string' || !callId) {\n // Keys only, never the item: `arguments` carries whatever the caller\n // said, so logging it verbatim would put conversation content in logs.\n this.logger.error(\n { conversation_id: conversationId, item_keys: Object.keys(item) },\n 'Received malformed function_call item without call_id'\n );\n return;\n }\n\n const name = item.name;\n let output: string;\n if (typeof name !== 'string' || !name) {\n // No name means no tool can be selected, so none runs.\n this.logger.error(\n { conversation_id: conversationId, call_id: callId, item_keys: Object.keys(item) },\n 'Received malformed function_call item without tool name'\n );\n output = JSON.stringify({ error: 'Malformed function call: missing tool name.' });\n } else {\n const result = await this.runToolCall(conversationId, name, item.arguments);\n try {\n // `JSON.stringify` returns `undefined`, not a string, for a value with\n // no JSON form (a void tool, a bare function): `null` keeps the reply\n // addressed to `call_id` instead of dropping the required field.\n const serialized: string | undefined = JSON.stringify(result);\n output = serialized ?? 'null';\n } catch (err) {\n // Only the generic message goes back: a stack trace or upstream\n // payload must never reach the model.\n this.logger.error(\n { err, conversation_id: conversationId, tool_name: name },\n 'Tool returned a non-JSON-serializable result'\n );\n output = JSON.stringify({ error: `Tool '${name}' returned a non-serializable result.` });\n }\n }\n\n // `response.item.create`, not Realtime's `conversation.item.create`.\n this.modelSend(conversationId, {\n type: 'response.item.create',\n item: { type: 'function_call_output', call_id: callId, output },\n });\n this.modelSend(conversationId, { type: 'response.create' });\n }\n\n /**\n * Surface the GPT-Live session id from a session-snapshot event.\n *\n * OpenAI support asks for this id when investigating a session, so it goes\n * where a caller can reach it — `session.metadata`, which outlives the call\n * into `onConversationEnded` — and is logged once per call.\n */\n private recordGptLiveSessionId(\n conversationId: ConversationId,\n session: ConversationSession,\n event: Record<string, unknown>\n ): void {\n const snapshot = (event.session ?? {}) as Record<string, unknown>;\n const sessionId = snapshot.id;\n if (typeof sessionId !== 'string' || sessionId === '') {\n return;\n }\n // Idempotent: `session.started` and `session.closed` both carry the\n // snapshot, and a normal call sees both.\n if (session.metadata[GPT_LIVE_SESSION_ID_METADATA_KEY] === sessionId) {\n return;\n }\n session.metadata[GPT_LIVE_SESSION_ID_METADATA_KEY] = sessionId;\n this.logger.info(\n { conversation_id: conversationId, gpt_live_session_id: sessionId },\n 'GPT-Live session id'\n );\n }\n\n /** Accumulate one transcript delta into the in-progress turn. */\n private static appendTranscriptDelta(\n session: ConversationSession,\n role: 'user' | 'assistant',\n event: Record<string, unknown>\n ): void {\n const text = event.delta;\n if (typeof text !== 'string' || text === '') {\n return;\n }\n\n const existing = session.metadata.transcript;\n const transcript = Array.isArray(existing)\n ? (existing as { role: string; text: string }[])\n : [];\n if (transcript !== existing) {\n session.metadata.transcript = transcript;\n }\n const last = transcript[transcript.length - 1];\n if (last !== undefined && last.role === role) {\n last.text += text;\n } else {\n transcript.push({ role, text });\n }\n }\n}\n","import { MediaStreamsOpenAIProviderConfig } from '../shared';\nimport type { MediaStreamsOpenAIProviderConfigOptions } from '../shared';\nimport type { VoiceProvider } from '../../provider';\nimport type { VoiceChannel } from '../../channel';\nimport type { TACConfig } from '../../../../lib/config';\nimport { GPTLiveProvider } from './provider';\n\nexport interface GPTLiveProviderConfigOptions extends MediaStreamsOpenAIProviderConfigOptions {\n /**\n * If set, sent verbatim as a `session.commentary.append` once `session.started`\n * arrives. Word it as an instruction, not just a greeting — e.g. \"Greet the\n * caller immediately using: Hi, how can I help you today?\". A bare greeting\n * will not make the model speak first.\n */\n welcomeInstruction?: string;\n}\n\n/**\n * Configuration for `GPTLiveProvider`.\n *\n * Two GPT-Live-specific notes on inherited members:\n *\n * - `tools` holds executable implementations looked up by name. It does **not**\n * tell the model the tools exist — also add each tool's `toRealtimeFormat()`\n * schema to `defaultSessionConfig.delegation.responses.tools`.\n * - `defaultSessionConfig` is the `session.start` payload's `session` body. It\n * must include `model` (e.g. `'gpt-live-1'`), and `audio.format`\n * must be `TWILIO_AUDIO_FORMAT_FOR_GPT_LIVE`.\n */\nexport class GPTLiveProviderConfig extends MediaStreamsOpenAIProviderConfig {\n readonly welcomeInstruction: string | null;\n\n constructor(opts: GPTLiveProviderConfigOptions = {}) {\n super(opts);\n this.welcomeInstruction = opts.welcomeInstruction ?? null;\n }\n\n public override createProvider(channel: VoiceChannel, tacConfig: TACConfig): VoiceProvider {\n return new GPTLiveProvider(channel, tacConfig, this);\n }\n}\n","import { ConversationSession } from '../types/conversation';\n\nfunction formatTraitValue(value: unknown): string {\n // For primitives (string, number, boolean, bigint), return as-is for readability\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'bigint'\n ) {\n return String(value);\n }\n // For objects and arrays, use JSON.stringify with bigint replacer\n try {\n return (\n JSON.stringify(value, (_key, replacerValue: unknown) => {\n if (typeof replacerValue === 'bigint') {\n return String(replacerValue);\n }\n return replacerValue;\n }) ?? String(value)\n );\n } catch {\n return String(value);\n }\n}\n\n/**\n * Build a formatted profile prompt section from conversation session data.\n *\n * Generates a markdown-formatted Customer Profile section with trait information.\n * Each trait is displayed as a bulleted list item with the trait name and formatted value.\n * Primitive values (string, number, boolean, bigint) are shown without quotes for readability,\n * while objects and arrays are JSON-stringified.\n *\n * @param context - The conversation session containing profile data\n * @param traitGroups - Optional array of trait group names to include. If provided, only\n * these trait groups will be included in the output. If an empty array\n * is provided, returns null.\n * @returns Formatted profile section or null if no profile data or no traits match filter\n */\nexport function buildProfilePrompt(\n context: ConversationSession,\n traitGroups?: string[]\n): string | null {\n if (!context.profile || !context.profile.traits) {\n return null;\n }\n\n let filteredTraits: Record<string, unknown>;\n\n if (traitGroups !== undefined) {\n if (traitGroups.length === 0) {\n return null;\n }\n\n filteredTraits = Object.fromEntries(\n Object.entries(context.profile.traits).filter(\n ([key, value]) => traitGroups.includes(key) && value != null\n )\n );\n } else {\n filteredTraits = Object.fromEntries(\n Object.entries(context.profile.traits).filter(([, value]) => value != null)\n );\n }\n\n if (Object.keys(filteredTraits).length === 0) {\n return null;\n }\n\n const lines = ['## Customer Profile', 'Information about this customer:'];\n\n for (const [key, value] of Object.entries(filteredTraits)) {\n lines.push(`- ${key}: ${formatTraitValue(value)}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * Configuration options for adapter utilities like MemoryPromptBuilder.\n */\nexport interface AdapterOptions {\n /**\n * Optional array of profile trait group names to include in the output.\n *\n * - If undefined or not provided, all available trait groups are included\n * - If empty array ([]), no profile traits are included (profile section is omitted)\n * - If populated array, only the specified trait groups are included\n *\n * @example\n * ```typescript\n * // Include only Contact and Preferences traits\n * { profileTraits: ['Contact', 'Preferences'] }\n *\n * // Exclude all profile traits\n * { profileTraits: [] }\n *\n * // Include all traits (default)\n * { } // or undefined\n * ```\n */\n profileTraits?: string[];\n}\n\n/**\n * Extract and normalize profile trait groups from adapter options.\n *\n * This is an internal helper function used by MemoryPromptBuilder to handle trait filtering.\n * The returned array should be treated as immutable.\n *\n * @param options - Adapter options containing optional profileTraits configuration\n * @returns undefined if all traits should be included, empty array if traits should be\n * excluded, or the specified trait groups array. The array is returned by reference.\n * @internal\n */\nexport function getProfileTraits(options?: AdapterOptions): string[] | undefined {\n if (!options || options.profileTraits === undefined) {\n return undefined;\n }\n\n if (options.profileTraits.length === 0) {\n return [];\n }\n\n return options.profileTraits;\n}\n","import { TACMemoryResponse } from '../lib/tac-memory-response';\nimport { buildProfilePrompt } from '../lib/conversation-session-helpers';\nimport { ConversationSession } from '../types/conversation';\nimport { AdapterOptions, getProfileTraits } from './options';\n\n/**\n * Utility class for building formatted LLM prompts from TAC memory and profile data.\n *\n * Generates markdown-formatted prompt sections that can be injected into LLM system messages,\n * providing context about the customer from previous interactions.\n *\n * @example\n * ```typescript\n * // Simple usage with compose() - no if/else needed\n * const systemPrompt = MemoryPromptBuilder.compose(\n * 'You are a helpful assistant.',\n * memoryResponse,\n * session\n * );\n *\n * // Advanced usage with trait filtering\n * const systemPrompt = MemoryPromptBuilder.compose(\n * 'You are a helpful assistant.',\n * memoryResponse,\n * session,\n * { profileTraits: ['Contact', 'Preferences'] }\n * );\n * ```\n */\nexport class MemoryPromptBuilder {\n /**\n * Build a formatted memory prompt from available memory and profile data.\n *\n * **Note:** Most users should use `compose()` instead, which automatically handles\n * combining memory with your system prompt. Use `build()` only if you need the raw\n * memory content without a system prompt.\n *\n * Generates a structured prompt with up to four sections:\n * - **Customer Profile**: Profile traits (filtered by options if provided)\n * - **Key Observations**: Important notes from previous interactions\n * - **Past Conversation Summaries**: Summaries of previous conversations\n * - **Recent Message History**: Recent communications with the customer\n *\n * Sections with no data are omitted. If no data is available at all, returns an empty string.\n *\n * @param memoryResponse - Memory data from TAC.retrieveMemory() containing observations,\n * summaries, and communications. Optional.\n * @param context - Conversation session containing profile data. Optional.\n * @param options - Configuration options for filtering profile traits. If profileTraits is\n * provided, only those trait groups will be included in the output. If an\n * empty array is provided, profile section is omitted. Optional.\n * @returns Formatted markdown prompt string ready for injection into LLM system messages.\n * Returns empty string if no memory or profile data is available.\n *\n * @example\n * ```typescript\n * // Recommended: Use compose() for most cases\n * const prompt = MemoryPromptBuilder.compose(basePrompt, memory, session);\n *\n * // Advanced: Use build() only if you need raw memory content\n * const rawMemory = MemoryPromptBuilder.build(memory, session);\n * if (rawMemory) {\n * // Custom handling of memory content\n * }\n * ```\n */\n static build(\n memoryResponse?: TACMemoryResponse | null,\n context?: ConversationSession | null,\n options?: AdapterOptions\n ): string {\n if (!memoryResponse && (!context || !context.profile)) {\n return '';\n }\n\n const sections: string[] = [];\n\n if (context) {\n const traitGroups = getProfileTraits(options);\n const profileSection = buildProfilePrompt(context, traitGroups);\n if (profileSection) {\n sections.push(profileSection);\n }\n }\n\n if (memoryResponse) {\n const memorySections = memoryResponse.buildMemoryPrompts();\n sections.push(...memorySections);\n }\n\n if (sections.length === 0) {\n return '';\n }\n\n return this.assemblePrompt(sections);\n }\n\n /**\n * Compose system prompt with memory context.\n *\n * Appends memory to systemPrompt if available. Always returns a string.\n * Eliminates the need for manual if/else checks when combining prompts.\n *\n * **Note:** Empty strings and whitespace-only strings are treated as \"no system prompt\"\n * (same as null/undefined). Whitespace is automatically trimmed from systemPrompt.\n *\n * @param systemPrompt - Base system prompt for the LLM. Empty string, whitespace-only,\n * null, and undefined are all treated as \"no system prompt\". Optional.\n * @param memoryResponse - Memory data from TAC.retrieveMemory(). Optional.\n * @param context - Conversation session containing profile data. Optional.\n * @param options - Configuration options for filtering profile traits. Optional.\n * @returns Composed prompt with memory appended to systemPrompt. Returns empty string\n * if both systemPrompt and memory are empty/null/undefined.\n *\n * @example\n * ```typescript\n * // Before (manual if/else)\n * const memoryContext = MemoryPromptBuilder.build(memoryResponse, context);\n * const systemPrompt = basePrompt + (memoryContext ? `\\n\\n${memoryContext}` : '');\n *\n * // After (compose handles it)\n * const systemPrompt = MemoryPromptBuilder.compose(basePrompt, memoryResponse, context);\n *\n * // Empty strings and whitespace are treated as \"no prompt\"\n * MemoryPromptBuilder.compose('', memoryResponse, context); // Returns just memory\n * MemoryPromptBuilder.compose(' ', memoryResponse, context); // Returns just memory (trimmed)\n * MemoryPromptBuilder.compose(null, memoryResponse, context); // Returns just memory\n * ```\n */\n static compose(\n systemPrompt?: string | null,\n memoryResponse?: TACMemoryResponse | null,\n context?: ConversationSession | null,\n options?: AdapterOptions\n ): string {\n const memoryContent = this.build(memoryResponse, context, options);\n const trimmedPrompt = systemPrompt?.trim() || null;\n\n if (!trimmedPrompt && !memoryContent) {\n return '';\n }\n\n if (!trimmedPrompt) {\n return memoryContent;\n }\n\n if (!memoryContent) {\n return trimmedPrompt;\n }\n\n return `${trimmedPrompt}\\n\\n${memoryContent}`;\n }\n\n private static assemblePrompt(sections: string[]): string {\n const header = [\n '# Customer Context',\n 'You have access to the following information about this customer ' +\n 'from previous interactions:',\n '',\n ];\n\n const body = sections.join('\\n\\n');\n\n return header.join('\\n') + body;\n }\n}\n","import {\n ToolFunction,\n JSONSchema,\n OpenAITool,\n AnthropicTool,\n OpenAIRealtimeTool,\n} from '@twilio/tac-core';\n\n/**\n * TAC Tool class with helper methods for LLM integration\n *\n * Matches Python's TACTool dataclass with conversion methods.\n */\nexport class TACTool<TParams = unknown, TResult = unknown> {\n constructor(\n public readonly name: string,\n public readonly description: string,\n public readonly parameters: JSONSchema,\n public readonly implementation: ToolFunction<TParams, TResult>\n ) {}\n\n /**\n * Convert to OpenAI function calling format\n */\n toOpenAIFormat(): OpenAITool {\n return {\n type: 'function',\n function: {\n name: this.name,\n description: this.description,\n parameters: this.parameters,\n },\n };\n }\n\n /**\n * Convert to OpenAI Realtime function calling format.\n *\n * Unlike {@link TACTool.toOpenAIFormat} (Chat Completions, which nests the\n * schema under a `function` key), Realtime's `session.tools` expects the\n * fields flat on the tool object.\n */\n toRealtimeFormat(): OpenAIRealtimeTool {\n return {\n type: 'function',\n name: this.name,\n description: this.description,\n parameters: this.parameters,\n };\n }\n\n /**\n * Convert to Anthropic tool calling format\n */\n toAnthropicFormat(): AnthropicTool {\n return {\n name: this.name,\n description: this.description,\n input_schema: this.parameters,\n };\n }\n\n /**\n * Convert to JSON string (OpenAI format by default)\n */\n toJSON(): string {\n return JSON.stringify(this.toOpenAIFormat(), null, 2);\n }\n\n /**\n * Convert this tool to an OpenAI Agents SDK `FunctionTool` instance.\n *\n * Unlike `toOpenAIFormat` and `toAnthropicFormat` (which return plain\n * objects consumed by HTTP APIs), the OpenAI Agents SDK dispatches on tool\n * *type*, so this returns a live `tool(...)` object with an invoke callback\n * that calls this tool and JSON-encodes the result.\n *\n * Requires the `@openai/agents` package:\n *\n * npm install @openai/agents\n *\n * @returns A FunctionTool ready to pass to `new Agent({ tools: [...] })`.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Return type depends on an optional peer dep we don't declare\n async toOpenAIAgentsSDKTool(): Promise<any> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Optional peer dep: dynamic import, can't declare types\n let agentsModule: any;\n try {\n // Dynamic import of an optional peer dependency. The indirection via a\n // string variable keeps TypeScript from trying to resolve the module\n // at compile time (it isn't a declared dependency).\n const moduleSpec = '@openai/agents';\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- Dynamic optional-dep import\n agentsModule = await import(/* @vite-ignore */ moduleSpec);\n } catch (err) {\n const cause = err instanceof Error ? err.message : String(err);\n throw new Error(\n 'toOpenAIAgentsSDKTool() failed to load @openai/agents. ' +\n 'Install with: npm install @openai/agents. ' +\n `Underlying error: ${cause}`,\n { cause: err }\n );\n }\n\n const impl = this.implementation;\n // The Agents SDK's `JsonObjectSchemaNonStrict` requires `additionalProperties: true`\n // (and `Strict` requires `: false`). Our schema sets neither by default, so normalize\n // for the non-strict path we're opting into.\n const parameters = {\n ...this.parameters,\n additionalProperties: true,\n };\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call -- Optional peer dep\n return agentsModule.tool({\n name: this.name,\n description: this.description,\n parameters,\n // Disable strict mode: the Agents SDK's strict JSON schema rejects\n // some features TAC emits (e.g. unions, top-level description).\n strict: false,\n execute: async (args: unknown): Promise<string> => {\n const result = await impl(args as TParams);\n return JSON.stringify(result);\n },\n });\n }\n}\n\n/**\n * Create a tool directly with all parameters\n *\n * Simplified approach matching Python's create_tool function.\n * No builder pattern - just a simple function call.\n */\nexport function defineTool<TParams = unknown, TResult = unknown>(\n name: string,\n description: string,\n parameters: JSONSchema,\n implementation: ToolFunction<TParams, TResult>\n): TACTool<TParams, TResult> {\n if (!name) {\n throw new Error('Tool name is required');\n }\n\n if (!description) {\n throw new Error('Tool description is required');\n }\n\n if (!parameters) {\n throw new Error('Tool parameters schema is required');\n }\n\n if (!implementation) {\n throw new Error('Tool implementation is required');\n }\n\n return new TACTool(name, description, parameters, implementation);\n}\n","import {\n MemoryRetrievalRequest,\n MemoryRetrievalResponse,\n BuiltInTools,\n MemoryClient,\n} from '@twilio/tac-core';\nimport { TACTool, defineTool } from '../lib/builder';\n\n/**\n * Parameters for memory retrieval tool\n */\ninterface MemoryRetrievalParams {\n query?: string;\n beginDate?: string;\n endDate?: string;\n observationsLimit?: number;\n summariesLimit?: number;\n communicationsLimit?: number;\n relevanceThreshold?: number;\n}\n\n/**\n * Create memory retrieval tool.\n *\n * @param memoryClient - Memory client instance (must be initialized with storeId)\n * @param profileId - Optional profile ID for memory retrieval\n * @param conversationId - Optional conversation ID for memory retrieval\n * @param options - Optional overrides for tool metadata.\n * @param options.name - Tool name exposed to the LLM. Defaults to `retrieve_profile_memory`.\n * @param options.description - Tool description exposed to the LLM. Defaults to a\n * generic \"retrieve memories\" prompt.\n */\nexport function createMemoryRetrievalTool(\n memoryClient: MemoryClient,\n profileId?: string,\n conversationId?: string,\n options: { name?: string; description?: string } = {}\n): TACTool<MemoryRetrievalParams, MemoryRetrievalResponse> {\n return defineTool(\n options.name ?? BuiltInTools.RETRIEVE_MEMORY,\n options.description ??\n 'Retrieve user memories including observations, summaries, and conversation history',\n {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Optional semantic search query to filter memories',\n },\n beginDate: {\n type: 'string',\n description: 'Optional start date for filtering memories (ISO 8601 format)',\n },\n endDate: {\n type: 'string',\n description: 'Optional end date for filtering memories (ISO 8601 format)',\n },\n observationsLimit: {\n type: 'integer',\n minimum: 0,\n maximum: 100,\n default: 20,\n description: 'Maximum number of observations to retrieve. Set to 0 to skip observations.',\n },\n summariesLimit: {\n type: 'integer',\n minimum: 0,\n maximum: 100,\n default: 5,\n description: 'Maximum number of summaries to retrieve. Set to 0 to skip summaries.',\n },\n communicationsLimit: {\n type: 'integer',\n minimum: 0,\n maximum: 100,\n default: 0,\n description:\n 'Maximum number of communications to retrieve. Set to 0 to skip communications.',\n },\n relevanceThreshold: {\n type: 'number',\n minimum: 0.0,\n maximum: 1.0,\n default: 0.0,\n description: 'Minimum relevance score threshold for observations and summaries.',\n },\n },\n required: [], // No required parameters\n description: 'Retrieve memories for the current user',\n },\n async (params: MemoryRetrievalParams) => {\n if (!profileId) {\n throw new Error('No profile ID available for memory retrieval');\n }\n\n const request = Object.fromEntries(\n Object.entries({\n conversationId,\n query: params.query,\n beginDate: params.beginDate,\n endDate: params.endDate,\n observationsLimit: params.observationsLimit,\n summariesLimit: params.summariesLimit,\n communicationsLimit: params.communicationsLimit,\n relevanceThreshold: params.relevanceThreshold,\n }).filter(([_, value]) => value !== undefined)\n ) as Partial<MemoryRetrievalRequest>;\n\n return memoryClient.retrieveMemories(profileId, request);\n }\n );\n}\n\n/**\n * Create factory function for memory tools\n *\n * @param memoryClient - Memory client instance (must be initialized with storeId)\n */\nexport function createMemoryTools(memoryClient: MemoryClient): {\n forProfile: (\n profileId: string,\n conversationId?: string\n ) => TACTool<MemoryRetrievalParams, MemoryRetrievalResponse>;\n forSession: (\n profileId?: string,\n conversationId?: string\n ) => TACTool<MemoryRetrievalParams, MemoryRetrievalResponse>;\n} {\n return {\n forProfile: (profileId: string, conversationId?: string) =>\n createMemoryRetrievalTool(memoryClient, profileId, conversationId),\n\n forSession: (profileId?: string, conversationId?: string) =>\n createMemoryRetrievalTool(memoryClient, profileId, conversationId),\n };\n}\n","import { BuiltInTools, ConversationId, BaseChannel } from '@twilio/tac-core';\nimport { TACTool, defineTool } from '../lib/builder';\n\n/**\n * Parameters for send message tool\n */\ninterface SendMessageParams {\n message: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Result from send message tool\n */\ninterface SendMessageResult {\n success: boolean;\n message_id?: string;\n error?: string;\n}\n\n/**\n * Create send message tool\n */\nexport function createSendMessageTool(\n channel: BaseChannel,\n conversationId: ConversationId\n): TACTool<SendMessageParams, SendMessageResult> {\n return defineTool(\n BuiltInTools.SEND_MESSAGE,\n 'Send a message to the user in the current conversation',\n {\n type: 'object',\n properties: {\n message: {\n type: 'string',\n description: 'The message content to send to the user',\n },\n metadata: {\n type: 'object',\n description: 'Optional metadata to include with the message',\n },\n },\n required: ['message'],\n description: 'Send a message to the user',\n },\n async (params: SendMessageParams) => {\n try {\n await channel.sendResponse(conversationId, params.message, params.metadata);\n\n return {\n success: true,\n message_id: `msg_${Date.now()}`, // Simple ID generation\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n );\n}\n\n/**\n * Create factory function for messaging tools\n */\nexport function createMessagingTools(): {\n forConversation: (\n channel: BaseChannel,\n conversationId: ConversationId\n ) => TACTool<SendMessageParams, SendMessageResult>;\n} {\n return {\n /**\n * Create send message tool for specific channel and conversation\n */\n forConversation: (channel: BaseChannel, conversationId: ConversationId) =>\n createSendMessageTool(channel, conversationId),\n };\n}\n","/**\n * Handoff tool for the Twilio Agent Connect.\n *\n * Generic Studio-backed handoff that routes a conversation to a human agent.\n * Produces a structured HandoffPayload and delivers it as a Twilio Studio\n * Execution (voice via `<Connect action>`, digital channels via direct POST).\n */\n\nimport axios, { AxiosError } from 'axios';\nimport {\n ConversationSession,\n HandoffPayload,\n PendingHandoffData,\n TAC,\n studioExecutionsUrl,\n studioVoiceHandoffUrl,\n} from '@twilio/tac-core';\nimport { TACTool, defineTool } from '../lib/builder';\n\n// Re-export URL helpers for backward compatibility with the Python factory surface.\nexport { studioExecutionsUrl, studioVoiceHandoffUrl };\n\n/**\n * Build a HandoffPayload from session context and attributes.\n *\n * Useful for custom handoff tools that want TAC's payload shape without\n * the Studio-specific delivery in `postStudioHandoff`.\n */\nexport function buildHandoffPayload(\n session: ConversationSession,\n memoryStoreId: string,\n attributes: Record<string, unknown>\n): HandoffPayload {\n return {\n conversationId: session.conversationId,\n storeId: memoryStoreId,\n profileId: session.profileId ?? '',\n attributes,\n };\n}\n\n/**\n * POST a handoff payload to a Twilio Studio Flow Executions endpoint.\n *\n * Emits the Twilio Studio Executions API wire format: form-encoded\n * `To` / `From` / `Parameters` fields with HTTP Basic auth.\n * `Parameters` is a JSON string keyed under `HandoffData` so Studio\n * can reference it via `{{flow.data.HandoffData.*}}`.\n */\nexport async function postStudioHandoff(\n payload: HandoffPayload,\n session: ConversationSession,\n options: {\n handoffUrl: string;\n fromAddress: string;\n apiKey: string;\n apiSecret: string;\n }\n): Promise<void> {\n const { handoffUrl, fromAddress, apiKey, apiSecret } = options;\n const toAddress = session.authorInfo?.address ?? '';\n\n const form = new URLSearchParams();\n form.append('To', toAddress);\n form.append('From', fromAddress);\n form.append('Parameters', JSON.stringify({ HandoffData: payload }));\n\n await axios.post(handoffUrl, form.toString(), {\n timeout: 10_000,\n auth: { username: apiKey, password: apiSecret },\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n });\n}\n\n/**\n * Result returned by the handoff tool.\n */\nexport interface HandoffResult {\n status: 'handoff_initiated' | 'handoff_failed';\n channel: string;\n error?: string;\n}\n\ninterface HandoffParams {\n reason: string;\n}\n\nconst DEFAULT_HANDOFF_TOOL_NAME = 'handoff';\nconst DEFAULT_HANDOFF_TOOL_DESCRIPTION =\n 'Hand off the conversation to a human agent. ' +\n 'Use this when the customer requests a human, or when you ' +\n 'cannot adequately handle the request.';\n\n/**\n * Create a handoff tool that delivers in the Twilio Studio Executions API shape.\n *\n * The returned tool exposes only `handoff({ reason })` to the LLM. All other\n * dependencies (TAC instance, session, static attributes) are captured in the\n * closure.\n *\n * On digital channels, the tool POSTs to the Studio Flow Executions endpoint\n * derived from `tac.getConfig().studioHandoffFlowSid`. For voice channels,\n * the payload is stored on the session and the voice channel automatically\n * sends the WS `end` message with `handoffData` after the LLM's final\n * response is delivered.\n *\n * The tool also sets the conversation to INACTIVE and clears status callbacks\n * to prevent further webhook events from being routed to TAC.\n *\n * **Not available in voice-only mode.** This tool requires Conversation\n * Orchestrator for conversation state management and Conversation Memory for\n * the handoff payload. In voice-only mode, implement your own handoff by\n * setting `session.pendingHandoffData` directly — the voice channel will\n * send the WS `end` message with your payload, and your `<Connect action>`\n * URL handler can route the call accordingly.\n *\n * @throws Error if `tac.getConfig().studioHandoffFlowSid` is unset, if\n * Conversation Orchestrator is not configured (voice-only mode), or if\n * the memory store ID was not resolved at startup.\n */\nexport function createStudioHandoffTool(\n tac: TAC,\n session: ConversationSession,\n options: {\n attributes?: Record<string, unknown>;\n name?: string;\n description?: string;\n } = {}\n): TACTool<HandoffParams, HandoffResult> {\n const config = tac.getConfig();\n if (!config.studioHandoffFlowSid) {\n throw new Error(\n 'createStudioHandoffTool requires tac.getConfig().studioHandoffFlowSid ' +\n '(set TWILIO_STUDIO_HANDOFF_FLOW_SID in your environment).'\n );\n }\n const flowSid = config.studioHandoffFlowSid;\n\n const coClient = tac.getConversationClient();\n if (!coClient) {\n throw new Error(\n 'createStudioHandoffTool requires Conversation Orchestrator ' +\n '(not available in voice-only mode)'\n );\n }\n const memoryStoreId = tac.getMemoryStoreId();\n if (!memoryStoreId) {\n throw new Error(\n 'createStudioHandoffTool requires a memory store ID ' +\n '(resolved from conversationConfigurationId at startup)'\n );\n }\n\n const staticAttributes = options.attributes ?? {};\n const toolName = options.name ?? DEFAULT_HANDOFF_TOOL_NAME;\n const toolDescription = options.description ?? DEFAULT_HANDOFF_TOOL_DESCRIPTION;\n\n return defineTool<HandoffParams, HandoffResult>(\n toolName,\n toolDescription,\n {\n type: 'object',\n properties: {\n reason: {\n type: 'string',\n description: 'The reason for handing off to a human agent',\n },\n },\n required: ['reason'],\n description: 'Hand off the conversation to a human agent',\n },\n async (params: HandoffParams): Promise<HandoffResult> => {\n const attributes = { ...staticAttributes, reason: params.reason };\n const payload = buildHandoffPayload(session, memoryStoreId, attributes);\n\n // 1. Set conversation to INACTIVE to trigger the CO-generated\n // conversation summary that Flex fetches on pickup. Downstream\n // (Studio/Flex) flips it back to ACTIVE on pickup and CLOSED on hangup —\n // we don't close it ourselves.\n try {\n await coClient.updateConversation(session.conversationId, 'INACTIVE');\n } catch (err) {\n tac.logger.warn(\n { err, conversation_id: session.conversationId },\n 'Failed to set conversation INACTIVE during handoff'\n );\n }\n\n // 2. Clear statusCallbacks so TAC stops receiving webhook events for\n // this conversation (Flex/human agent will handle it from here).\n try {\n await coClient.clearStatusCallbacks(session.conversationId);\n } catch (err) {\n tac.logger.warn(\n { err, conversation_id: session.conversationId },\n 'Failed to clear status callbacks during handoff'\n );\n }\n\n // 3. Deliver handoff payload.\n if (session.channel === 'voice') {\n // Voice: store on session for deferred delivery. The voice channel\n // sends the WS \"end\" message after the LLM's final response so the\n // caller hears a goodbye before transfer. handoffData is a JSON\n // *string* — ConversationRelay forwards it verbatim in the POST body\n // to the action URL.\n const pending: PendingHandoffData = {\n type: 'end',\n handoffData: JSON.stringify(payload),\n };\n session.pendingHandoffData = pending;\n } else {\n // Digital channels: POST handoff payload to the Studio Flow Executions\n // endpoint. If the POST fails (network, 4xx, 5xx, timeout), return\n // handoff_failed so the LLM can tell the user instead of claiming\n // success.\n try {\n await postStudioHandoff(payload, session, {\n handoffUrl: studioExecutionsUrl(flowSid),\n fromAddress: config.phoneNumber,\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n });\n } catch (err) {\n const message =\n err instanceof AxiosError\n ? err.message\n : err instanceof Error\n ? err.message\n : String(err);\n tac.logger.error(\n { err, conversation_id: session.conversationId },\n 'Failed to deliver handoff payload'\n );\n return {\n status: 'handoff_failed',\n channel: session.channel,\n error: message,\n };\n }\n }\n\n return { status: 'handoff_initiated', channel: session.channel };\n }\n );\n}\n","import { KnowledgeClient, KnowledgeChunkResult } from '@twilio/tac-core';\nimport { TACTool, defineTool } from '../lib/builder';\n\n/**\n * Parameters for knowledge search tool (visible to LLM)\n */\ninterface KnowledgeSearchParams {\n query: string;\n}\n\n/**\n * Configuration for knowledge search tool\n */\ninterface KnowledgeToolConfig {\n name?: string;\n description?: string;\n topK?: number;\n}\n\n/**\n * Create knowledge search tool with explicit name and description\n *\n * @param knowledgeClient - The Knowledge client instance\n * @param knowledgeBaseId - The knowledge base ID to search\n * @param config - Configuration with required name and description\n * @returns TACTool configured for knowledge search\n */\nexport function createKnowledgeSearchTool(\n knowledgeClient: KnowledgeClient,\n knowledgeBaseId: string,\n config: { name: string; description: string; topK?: number }\n): TACTool<KnowledgeSearchParams, KnowledgeChunkResult[]> {\n const topK = config.topK ?? 5;\n\n return defineTool(\n config.name,\n config.description,\n {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'The search query to find relevant knowledge',\n },\n },\n required: ['query'],\n description: config.description,\n },\n async (params: KnowledgeSearchParams) => {\n return knowledgeClient.searchKnowledgeBase(knowledgeBaseId, params.query, topK);\n }\n );\n}\n\n/**\n * Create knowledge search tool with auto-fetched metadata from knowledge base\n *\n * This async version fetches the knowledge base metadata to auto-generate\n * the tool name and description if not provided.\n *\n * @param knowledgeClient - The Knowledge client instance\n * @param knowledgeBaseId - The knowledge base ID to search\n * @param config - Optional configuration (name/description auto-generated if not provided)\n * @returns Promise containing TACTool configured for knowledge search\n */\nexport async function createKnowledgeSearchToolAsync(\n knowledgeClient: KnowledgeClient,\n knowledgeBaseId: string,\n config?: KnowledgeToolConfig\n): Promise<TACTool<KnowledgeSearchParams, KnowledgeChunkResult[]>> {\n let name = config?.name;\n let description = config?.description;\n\n // Fetch knowledge base metadata if name or description not provided\n if (!name || !description) {\n const kb = await knowledgeClient.getKnowledgeBase(knowledgeBaseId);\n if (!name) {\n // Generate tool name from display name (normalized snake_case)\n const normalized = kb.displayName\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_+|_+$/g, '');\n\n name = normalized ? `search_${normalized}` : 'search_knowledge_base';\n }\n if (!description) {\n description = kb.description || `Search the ${kb.displayName} knowledge base`;\n }\n }\n\n const toolConfig: { name: string; description: string; topK?: number } = {\n name,\n description,\n };\n if (config?.topK !== undefined) {\n toolConfig.topK = config.topK;\n }\n return createKnowledgeSearchTool(knowledgeClient, knowledgeBaseId, toolConfig);\n}\n\n/**\n * Create factory for knowledge tools\n *\n * @param knowledgeClient - The Knowledge client instance\n * @returns Factory object with methods to create knowledge tools\n */\nexport function createKnowledgeTools(knowledgeClient: KnowledgeClient): {\n forKnowledgeBase: (\n knowledgeBaseId: string,\n config: { name: string; description: string; topK?: number }\n ) => TACTool<KnowledgeSearchParams, KnowledgeChunkResult[]>;\n forKnowledgeBaseAsync: (\n knowledgeBaseId: string,\n config?: KnowledgeToolConfig\n ) => Promise<TACTool<KnowledgeSearchParams, KnowledgeChunkResult[]>>;\n} {\n return {\n /**\n * Create knowledge search tool with explicit config\n */\n forKnowledgeBase: (\n knowledgeBaseId: string,\n config: { name: string; description: string; topK?: number }\n ) => createKnowledgeSearchTool(knowledgeClient, knowledgeBaseId, config),\n\n /**\n * Create knowledge search tool with auto-fetched metadata\n */\n forKnowledgeBaseAsync: (knowledgeBaseId: string, config?: KnowledgeToolConfig) =>\n createKnowledgeSearchToolAsync(knowledgeClient, knowledgeBaseId, config),\n };\n}\n","import Fastify, {\n FastifyInstance,\n FastifyServerOptions,\n FastifyRequest,\n FastifyReply,\n} from 'fastify';\nimport formbody from '@fastify/formbody';\nimport websocket from '@fastify/websocket';\nimport gracefulShutdown from 'fastify-graceful-shutdown';\nimport type { WebSocket } from 'ws';\nimport twilio from 'twilio';\n\nimport { twiMLRequestFromForm, CALL_EVENT_KINDS } from '@twilio/tac-core';\nimport { TAC, VoiceChannel, MessagingChannel } from '@twilio/tac-core';\n\n/**\n * Server configuration options\n */\nexport interface TACServerConfig {\n /** Fastify server options (ignored if `fastifyInstance` is provided) */\n fastify?: FastifyServerOptions;\n\n /**\n * Pre-configured Fastify instance to mount TAC routes onto.\n *\n * Use this to control construction-time settings (logger, `trustProxy`,\n * schema, ...) or to register your own plugins/hooks before TAC's\n * routes are set up. If provided, the `fastify` options field is\n * ignored.\n */\n fastifyInstance?: FastifyInstance;\n\n /** Host to bind the server to (default: '0.0.0.0') */\n host?: string;\n\n /** Port to bind the server to (default: 8000) */\n port?: number;\n\n /**\n * Custom server-only webhook paths. The voice WebSocket and ConversationRelay\n * action callback paths live on `TACConfig` (`voiceWebsocketPath` /\n * `voiceActionPath`) because they're consumed by the voice channel regardless\n * of which web framework is used; this server reads them from there.\n */\n webhookPaths?: {\n /**\n * @deprecated Use `conversation` instead. This field will be removed in a future version.\n * If both `messaging` and `conversation` are set, `conversation` takes precedence.\n */\n messaging?: string;\n conversation?: string;\n twiml?: string;\n /** Path for Conversation Intelligence webhook (optional - only registered if provided) */\n cintel?: string;\n };\n\n /** Voice channel instance (alternative to registering on TAC) */\n voiceChannel?: VoiceChannel;\n\n /** Messaging channel instances — webhooks are fanned out to all (alternative to registering on TAC) */\n messagingChannels?: MessagingChannel[];\n}\n\n/**\n * Default server configuration\n */\nconst DEFAULT_CONFIG = {\n host: '0.0.0.0',\n port: 8000,\n webhookPaths: {\n conversation: '/webhook',\n twiml: '/twiml',\n },\n} satisfies Omit<\n TACServerConfig,\n 'fastify' | 'fastifyInstance' | 'voiceChannel' | 'messagingChannels'\n>;\n\n/** Normalize a route path for comparison, so '/hooks' and '/hooks/' collide. */\nfunction stripTrailingSlash(path: string): string {\n return path.replace(/\\/+$/, '');\n}\n\n/** What the voice channel's webhook handlers hand back for a reply. */\ntype CallEventResult = { status: number; content: string; contentType: string };\n\n/**\n * Batteries-included Fastify server for TAC\n *\n * Provides out-of-the-box setup for SMS and Voice channels with\n * proper webhook handling, WebSocket support, and production-ready defaults.\n *\n * Customization:\n * - Pass your own Fastify instance via `config.fastifyInstance` to control\n * construction-time settings (logger, `trustProxy`, schema, ...) and to\n * register plugins/hooks before TAC's routes are set up.\n * - Or mutate `server.fastify` after construction to add routes,\n * decorators, or hooks — before calling `start()`.\n *\n * Example:\n * import Fastify from 'fastify';\n *\n * const app = Fastify({ logger: true, trustProxy: true });\n * const server = new TACServer(tac, { fastifyInstance: app });\n *\n * server.fastify.get('/health', async () => ({ status: 'ok' }));\n *\n * await server.start();\n */\nexport class TACServer {\n public readonly fastify: FastifyInstance;\n private readonly tac: TAC;\n private readonly config: Required<\n Omit<TACServerConfig, 'fastify' | 'fastifyInstance' | 'voiceChannel' | 'messagingChannels'>\n >;\n /** All enabled messaging channels */\n private readonly messagingChannels: MessagingChannel[];\n /** Voice channel instance */\n private readonly voiceChannel: VoiceChannel | undefined;\n /** All channels that need webhook processing (voice + messaging) */\n private readonly webhookChannels: (VoiceChannel | MessagingChannel)[];\n\n constructor(tac: TAC, config: TACServerConfig = {}) {\n this.tac = tac;\n\n // Handle deprecated `messaging` field: log warning and apply fallback if needed\n const webhookPaths = { ...DEFAULT_CONFIG.webhookPaths, ...config.webhookPaths };\n if (config.webhookPaths?.messaging) {\n console.warn(\n 'TACServer: The \"webhookPaths.messaging\" field is deprecated and will be removed in a future version. ' +\n 'Please update your configuration to use \"webhookPaths.conversation\" instead.'\n );\n // If conversation isn't explicitly set, use messaging value as fallback\n if (!config.webhookPaths.conversation) {\n webhookPaths.conversation = config.webhookPaths.messaging;\n }\n }\n\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n webhookPaths,\n };\n\n // Resolve channels: prefer explicit kwargs, fall back to tac.getChannel()\n this.voiceChannel = config.voiceChannel ?? tac.getChannel<VoiceChannel>('voice');\n\n // Fail fast at construction if a voice channel is attached but no public\n // URL is configured. Without this check, the misconfiguration would only\n // surface on the first inbound call as a 500 — easy to miss in CI or smoke\n // tests that don't hit voice. Custom adapters (Express/etc.) constructing\n // VoiceChannel directly still get the runtime error on first request.\n if (this.voiceChannel && !tac.getConfig().voicePublicDomain) {\n throw new Error(\n 'Voice channel is configured but TACConfig.voicePublicDomain is not set. ' +\n 'Set it directly or via the TWILIO_VOICE_PUBLIC_DOMAIN env var.'\n );\n }\n // Unconditional, because the call-event routes register unconditionally\n // (like the TwiML and ConversationRelay routes) — so the collision is real\n // whether or not a voice channel is attached.\n this.validateCallEventPaths();\n this.messagingChannels =\n config.messagingChannels ??\n (\n [\n tac.getChannel<MessagingChannel>('sms'),\n tac.getChannel<MessagingChannel>('rcs'),\n tac.getChannel<MessagingChannel>('chat'),\n tac.getChannel<MessagingChannel>('whatsapp'),\n ] as (MessagingChannel | undefined)[]\n ).filter((ch): ch is MessagingChannel => ch != null);\n\n // Gather all channels that need webhook processing\n this.webhookChannels = [];\n if (this.voiceChannel) {\n this.webhookChannels.push(this.voiceChannel);\n }\n this.webhookChannels.push(...this.messagingChannels);\n\n if (this.webhookChannels.length === 0) {\n console.warn(\n 'TACServer: No channels configured for webhook processing. Register channels with TAC to enable webhooks.'\n );\n }\n // Use the user-supplied Fastify instance if provided; otherwise create\n // a default one with Pino logging.\n if (config.fastifyInstance) {\n this.fastify = config.fastifyInstance;\n } else {\n this.fastify = Fastify({\n logger: {\n level: process.env.TWILIO_LOG_LEVEL || 'info',\n },\n ...config.fastify,\n });\n }\n }\n\n /**\n * Validate `voiceCallEventPath`, the one path that isn't literal.\n *\n * Every other TAC path registers as configured, so a bad value is visible.\n * This one expands into three sub-paths, hiding a mistake the base path looks\n * innocent for: a sub-path colliding with another route while the base looks\n * unrelated (base `/hooks` vs `webhookPaths.twiml = '/hooks/status'`). Both\n * would register as POST routes and requests would reach the wrong handler.\n *\n * The leading-slash requirement is enforced by `TACConfigSchema` at parse\n * time, so it doesn't need re-checking here.\n */\n private validateCallEventPaths(): void {\n const cfg = this.tac.getConfig();\n\n const others: Record<string, string> = {\n [stripTrailingSlash(this.config.webhookPaths.twiml || '/twiml')]: 'webhookPaths.twiml',\n [stripTrailingSlash(cfg.voiceActionPath)]: 'TACConfig.voiceActionPath',\n [stripTrailingSlash(this.config.webhookPaths.conversation || '/webhook')]:\n 'webhookPaths.conversation',\n };\n if (this.config.webhookPaths.cintel) {\n others[stripTrailingSlash(this.config.webhookPaths.cintel)] = 'webhookPaths.cintel';\n }\n\n for (const kind of CALL_EVENT_KINDS) {\n const path = cfg.callEventPath(kind);\n const clash = others[stripTrailingSlash(path)];\n if (clash !== undefined) {\n throw new Error(\n `TACConfig.voiceCallEventPath expands to '${path}', which collides with ` +\n `${clash}. Both would register as POST routes and requests would ` +\n 'reach the wrong handler.'\n );\n }\n }\n }\n\n private getForwardedProto(request: FastifyRequest): string {\n const raw = request.headers['x-forwarded-proto'] as string | undefined;\n return raw?.split(',')[0]?.trim() || 'https';\n }\n\n private getForwardedHost(request: FastifyRequest): string {\n const raw = (request.headers['x-forwarded-host'] as string | undefined) || request.headers.host;\n return raw?.split(',')[0]?.trim() || '';\n }\n\n /**\n * Get the full URL for webhook validation\n * Handles X-Forwarded-* headers for proxy/ngrok scenarios\n */\n private getWebhookUrl(request: FastifyRequest): string {\n const proto = this.getForwardedProto(request);\n const host = this.getForwardedHost(request);\n return `${proto}://${host}${request.url}`;\n }\n\n /**\n * Validate the Twilio signature on an HTTP request. On failure, sends a 403\n * reply (Fastify halts the request once `reply.send` is called in a\n * `preHandler`, so the route handler won't run). Scoped to TAC-registered\n * webhook routes — does not run on user-added routes registered on\n * `server.fastify`.\n */\n private async validateRequestSignature(\n request: FastifyRequest,\n reply: FastifyReply\n ): Promise<void> {\n const signature = request.headers['x-twilio-signature'] as string;\n const url = this.getWebhookUrl(request);\n const authToken = this.tac.getConfig().authToken;\n\n let isValid: boolean;\n if (request.url.includes('bodySHA256=')) {\n const body = (request as FastifyRequest & { rawBody?: string }).rawBody ?? '';\n isValid = twilio.validateRequestWithBody(authToken, signature, url, body);\n } else {\n const params = (request.body as Record<string, string>) || {};\n isValid = twilio.validateRequest(authToken, signature, url, params);\n }\n\n if (!isValid) {\n this.fastify.log.warn({ url, hasSignature: !!signature }, 'Invalid Twilio webhook signature');\n await reply.code(403).send({ error: 'Invalid webhook signature' });\n }\n }\n\n /**\n * Setup routes\n */\n private async setupRoutes(): Promise<void> {\n const validateSignature = {\n preHandler: async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {\n await this.validateRequestSignature(request, reply);\n },\n };\n\n // Conversation Orchestrator webhook — fan out to all enabled channels\n if (this.webhookChannels.length > 0) {\n this.fastify.post(\n this.config.webhookPaths.conversation || '/webhook',\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n const rawHeader = request.headers['i-twilio-idempotency-token'];\n const idempotencyToken = Array.isArray(rawHeader) ? rawHeader[0] : rawHeader;\n\n // Fan out to all channels\n for (const channel of this.webhookChannels) {\n channel.processWebhook(request.body, idempotencyToken).catch((err: unknown) => {\n this.fastify.log.error(\n { err, channel: channel.channelType },\n 'Webhook processing error'\n );\n });\n }\n\n await reply.code(200).send({ status: 'ok' });\n }\n );\n }\n\n // Voice webhook (POST - Twilio calls this when an incoming call arrives)\n this.fastify.post(\n this.config.webhookPaths.twiml || '/twiml',\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n if (!this.voiceChannel) {\n await reply.code(500).send({ error: 'Voice channel not available' });\n return;\n }\n\n const voiceChannel = this.voiceChannel;\n\n // Parse the Twilio webhook form into a framework-neutral TwiMLRequest\n // and hand it to the channel. The channel derives the WebSocket and\n // action URLs from TACConfig (voicePublicDomain + paths), layers in\n // VoiceChannelConfig.defaultTwimlOptions, and runs any per-call\n // customizer registered via voiceChannel.onInboundCallTwiml(...).\n const formDict = (request.body as Record<string, string>) ?? {};\n const twimlRequest = twiMLRequestFromForm(formDict);\n\n const twiml = await voiceChannel.handleIncomingCall(twimlRequest);\n\n await reply.type('application/xml').send(twiml);\n } catch (error) {\n this.fastify.log.error(\n 'TwiML generation error: ' + (error instanceof Error ? error.message : String(error))\n );\n await reply.code(500).send({\n error: 'Internal server error',\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n );\n\n // ConversationRelay callback endpoint. Path lives on TACConfig because the\n // voice channel derives the action URL from it too.\n this.fastify.post(\n this.tac.getConfig().voiceActionPath,\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n if (!this.voiceChannel) {\n await reply.code(500).send({ error: 'Voice channel not available' });\n return;\n }\n\n const voiceChannel = this.voiceChannel;\n\n // Pass the raw form data through; the active provider validates its\n // own callback shape. Parsing against ConversationRelay's schema here\n // would reject Media Streams <Connect action> payloads before they\n // ever reach the provider.\n const formData = request.body as Record<string, string>;\n const result = await voiceChannel.handleTwilioProviderCallback(formData);\n\n await reply.code(result.status).type(result.contentType).send(result.content);\n } catch (error) {\n this.fastify.log.error(\n 'ConversationRelay callback error: ' +\n (error instanceof Error ? error.message : String(error))\n );\n await reply.code(500).send({ error: 'Internal server error' });\n }\n }\n );\n\n // One route per Twilio call callback — the route is the discriminator, so\n // each handler parses its own typed event with no payload sniffing. Paths\n // live on TACConfig because the voice channel derives the callback URLs it\n // hands to the Calls API from the same base.\n const callEventHandlers: Record<\n (typeof CALL_EVENT_KINDS)[number],\n (channel: VoiceChannel, form: Record<string, string>) => Promise<CallEventResult>\n > = {\n status: (channel, form) => channel.handleCallStatusEvent(form),\n amd: (channel, form) => channel.handleAmdEvent(form),\n recording: (channel, form) => channel.handleRecordingEvent(form),\n };\n\n for (const kind of CALL_EVENT_KINDS) {\n const handle = callEventHandlers[kind];\n this.fastify.post(\n this.tac.getConfig().callEventPath(kind),\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n if (!this.voiceChannel) {\n await reply.code(500).send({ error: 'Voice channel not available' });\n return;\n }\n\n const formData = (request.body as Record<string, string>) ?? {};\n const result = await handle(this.voiceChannel, formData);\n\n await reply.code(result.status).type(result.contentType).send(result.content);\n } catch (error) {\n this.fastify.log.error(\n `Call ${kind} callback error: ` +\n (error instanceof Error ? error.message : String(error))\n );\n await reply.code(500).send({ error: 'Internal server error' });\n }\n }\n );\n }\n\n // Voice WebSocket endpoint. Path lives on TACConfig because the voice\n // channel derives the WebSocket URL from it too.\n await this.fastify.register(fastify => {\n fastify.get(\n this.tac.getConfig().voiceWebsocketPath,\n { websocket: true },\n (socket: WebSocket, request: FastifyRequest) => {\n const signature = request.headers['x-twilio-signature'] as string;\n const authToken = this.tac.getConfig().authToken;\n\n const proto = this.getForwardedProto(request);\n const host = this.getForwardedHost(request);\n\n if (!host) {\n this.fastify.log.warn('WebSocket connection rejected: missing host header');\n socket.close(1008, 'Invalid request');\n return;\n }\n\n const wsProto = proto === 'https' ? 'wss' : 'ws';\n const fullUrl = new URL(`${wsProto}://${host}${request.url}`);\n const params: Record<string, string> = {};\n fullUrl.searchParams.forEach((value, key) => {\n params[key] = value;\n });\n const url = fullUrl.origin + fullUrl.pathname;\n\n const isValid = twilio.validateRequest(authToken, signature, url, params);\n\n if (!isValid) {\n this.fastify.log.warn(\n { url, hasSignature: !!signature },\n 'WebSocket connection rejected: invalid Twilio signature'\n );\n socket.close(1008, 'Invalid signature');\n return;\n }\n\n if (!this.voiceChannel) {\n socket.terminate();\n return;\n }\n\n this.voiceChannel.handleWebSocketConnection(socket);\n }\n );\n });\n\n // Conversation Intelligence webhook endpoint (optional - only if path is configured)\n if (this.config.webhookPaths.cintel) {\n this.fastify.post(\n this.config.webhookPaths.cintel,\n validateSignature,\n async (request: FastifyRequest, reply: FastifyReply) => {\n if (!this.tac.isCintelEnabled()) {\n await reply.code(400).send({\n error: 'Conversation Intelligence is not enabled',\n message:\n 'Set TWILIO_TAC_CI_CONFIGURATION_ID and memory credentials to enable CI processing',\n });\n return;\n }\n\n try {\n this.fastify.log.info('Processing Conversation Intelligence webhook');\n const result = await this.tac.processCintelEvent(request.body);\n\n if (result.success) {\n if (result.skipped) {\n this.fastify.log.debug({ reason: result.skipReason }, 'CI event skipped');\n } else {\n this.fastify.log.info(\n { eventType: result.eventType, createdCount: result.createdCount },\n 'CI event processed'\n );\n }\n } else {\n this.fastify.log.error({ error: result.error }, 'CI event processing failed');\n }\n\n await reply.send(result);\n } catch (error) {\n this.fastify.log.error(\n 'CI webhook error: ' + (error instanceof Error ? error.message : String(error))\n );\n await reply.code(500).send({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n );\n }\n }\n\n /**\n * Start the server\n */\n public async start(): Promise<void> {\n try {\n // Register required plugins, guarding against users who pre-registered\n // them on a supplied `fastifyInstance` (duplicate registration throws).\n if (!this.fastify.hasContentTypeParser('application/x-www-form-urlencoded')) {\n await this.fastify.register(formbody);\n }\n if (!this.fastify.hasDecorator('websocketServer')) {\n await this.fastify.register(websocket);\n }\n if (!this.fastify.hasDecorator('gracefulShutdown')) {\n await this.fastify.register(gracefulShutdown);\n }\n\n // Replace the default JSON parser with one that stores the raw body string,\n // needed by validateRequestWithBody for bodySHA256 signature validation.\n const defaultJsonParser = this.fastify.getDefaultJsonParser('error', 'error');\n if (this.fastify.hasContentTypeParser('application/json')) {\n this.fastify.removeContentTypeParser('application/json');\n }\n this.fastify.addContentTypeParser(\n 'application/json',\n { parseAs: 'string' },\n (request, body: string, done) => {\n (request as FastifyRequest & { rawBody?: string }).rawBody = body;\n void defaultJsonParser(request, body, done);\n }\n );\n\n // Set up routes (must be after plugin registration)\n // Signature validation is applied per-route as a `preHandler` so it only\n // runs on TAC-registered webhook routes, not on user-added routes on\n // `server.fastify`.\n await this.setupRoutes();\n\n // Configure graceful shutdown to wait for WebSocket connections\n this.fastify.gracefulShutdown(async (signal: string) => {\n this.fastify.log.info({ signal }, 'Received shutdown signal');\n\n // Wait for WebSocket connections to close naturally\n await this.waitForWebSocketsToClose();\n\n // Shutdown TAC (cleans up channel state)\n this.tac.shutdown();\n });\n\n // Start Fastify server\n await this.fastify.listen({\n host: this.config.host,\n port: this.config.port,\n });\n\n this.fastify.log.info(\n {\n host: this.config.host,\n port: this.config.port,\n conversation_webhook: this.config.webhookPaths.conversation,\n twiml_webhook: this.config.webhookPaths.twiml,\n ws_websocket: this.tac.getConfig().voiceWebsocketPath,\n conversation_relay_callback: this.tac.getConfig().voiceActionPath,\n ...(this.voiceChannel && {\n call_event_callbacks: CALL_EVENT_KINDS.map(kind =>\n this.tac.getConfig().callEventPath(kind)\n ),\n }),\n ...(this.config.webhookPaths.cintel && {\n cintel_webhook: this.config.webhookPaths.cintel,\n }),\n },\n 'TAC Server started'\n );\n } catch (error) {\n this.fastify.log.error({ err: error }, 'Failed to start TAC Server');\n throw error;\n }\n }\n\n /**\n * Wait for all WebSocket connections to close\n */\n private async waitForWebSocketsToClose(timeoutMs = 30000): Promise<void> {\n const wsServer = this.fastify.websocketServer;\n if (!wsServer || wsServer.clients.size === 0) {\n return;\n }\n\n this.fastify.log.info(\n { websocket_count: wsServer.clients.size },\n 'Waiting for WebSocket connections to close...'\n );\n\n const startTime = Date.now();\n\n return new Promise<void>(resolve => {\n const checkInterval = setInterval(() => {\n const clientCount = wsServer.clients.size;\n\n if (clientCount === 0) {\n clearInterval(checkInterval);\n this.fastify.log.info('All WebSocket connections closed');\n resolve();\n return;\n }\n\n // Check for timeout\n if (Date.now() - startTime >= timeoutMs) {\n clearInterval(checkInterval);\n this.fastify.log.warn(\n { remaining_websockets: clientCount },\n 'Timeout waiting for WebSockets to close, proceeding with shutdown'\n );\n resolve();\n return;\n }\n\n this.fastify.log.info(\n { remaining_websockets: clientCount },\n 'Waiting for WebSockets to close...'\n );\n }, 5000);\n });\n }\n\n /**\n * Stop the server gracefully\n */\n public async stop(): Promise<void> {\n try {\n await this.fastify.close();\n this.fastify.log.info('TAC Server stopped');\n } catch (error) {\n this.fastify.log.error({ err: error }, 'Error stopping TAC Server');\n throw error;\n }\n }\n}\n"]}