twilio-agent-connect 2.2.0 → 2.3.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.d.ts CHANGED
@@ -1649,6 +1649,19 @@ declare const InterruptMessageSchema: z.ZodObject<{
1649
1649
  durationUntilInterruptMs: z.ZodOptional<z.ZodNumber>;
1650
1650
  }, z.core.$strip>;
1651
1651
  type InterruptMessage = z.infer<typeof InterruptMessageSchema>;
1652
+ /**
1653
+ * WebSocket DTMF message (caller pressed a key).
1654
+ *
1655
+ * Only sent when `dtmfDetection` is enabled on `<ConversationRelay>`, and one
1656
+ * message per keypress — digits are never batched.
1657
+ *
1658
+ * @see https://www.twilio.com/docs/voice/conversationrelay/websocket-messages#dtmf-message
1659
+ */
1660
+ declare const DtmfMessageSchema: z.ZodObject<{
1661
+ type: z.ZodLiteral<"dtmf">;
1662
+ digit: z.ZodString;
1663
+ }, z.core.$strip>;
1664
+ type DtmfMessage = z.infer<typeof DtmfMessageSchema>;
1652
1665
  /**
1653
1666
  * Union of all WebSocket message types
1654
1667
  */
@@ -1676,6 +1689,9 @@ declare const WebSocketMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
1676
1689
  type: z.ZodLiteral<"interrupt">;
1677
1690
  utteranceUntilInterrupt: z.ZodOptional<z.ZodString>;
1678
1691
  durationUntilInterruptMs: z.ZodOptional<z.ZodNumber>;
1692
+ }, z.core.$strip>, z.ZodObject<{
1693
+ type: z.ZodLiteral<"dtmf">;
1694
+ digit: z.ZodString;
1679
1695
  }, z.core.$strip>]>;
1680
1696
  type WebSocketMessage = z.infer<typeof WebSocketMessageSchema>;
1681
1697
  /**
@@ -3532,6 +3548,22 @@ type CallStatusHandler = (event: CallStatusEvent) => Promise<void> | void;
3532
3548
  type AmdHandler = (event: AmdEvent) => Promise<void> | void;
3533
3549
  /** Handler for Twilio `recordingStatusCallback` webhooks. */
3534
3550
  type RecordingHandler = (event: RecordingEvent) => Promise<void> | void;
3551
+ /** One ConversationRelay keypress, as delivered to a {@link DtmfHandler}. */
3552
+ interface DtmfEvent {
3553
+ /**
3554
+ * Undefined only when the keypress beat conversation setup: `dtmf` before
3555
+ * ConversationRelay's `setup`, or an orchestrated-mode lookup that failed.
3556
+ */
3557
+ conversationId: ConversationId | undefined;
3558
+ /** Undefined only before ConversationRelay's `setup` message. */
3559
+ callSid: string | undefined;
3560
+ /** The key pressed: `0`-`9`, `*`, `#`, or `A`-`D`. */
3561
+ digit: string;
3562
+ /** Present whenever `conversationId` is. */
3563
+ session?: ConversationSession;
3564
+ }
3565
+ /** Handler for ConversationRelay `dtmf` messages (caller keypresses). */
3566
+ type DtmfHandler = (event: DtmfEvent) => Promise<void> | void;
3535
3567
  /**
3536
3568
  * Voice channel event callbacks extending base callbacks
3537
3569
  */
@@ -3554,6 +3586,8 @@ interface VoiceChannelEvents extends BaseChannelEvents {
3554
3586
  utteranceUntilInterrupt: string | undefined;
3555
3587
  durationUntilInterruptMs: number | undefined;
3556
3588
  }) => void;
3589
+ /** Caller keypress. See {@link VoiceChannel.onDtmf}. */
3590
+ onDtmf?: DtmfHandler;
3557
3591
  /**
3558
3592
  * Fired once the session and WebSocket registration exist — in orchestrated
3559
3593
  * mode possibly before the first prompt, since the lookup starts at setup.
@@ -3675,6 +3709,30 @@ declare class VoiceChannel extends BaseChannel {
3675
3709
  * ```
3676
3710
  */
3677
3711
  onRecording(callback: RecordingHandler): void;
3712
+ /**
3713
+ * Register a handler for DTMF keypresses, called once per key in order.
3714
+ *
3715
+ * Requires `dtmfDetection: true` on the ConversationRelay config — without it
3716
+ * Twilio sends nothing and this never fires. Digits aren't buffered, so
3717
+ * accumulating a multi-digit entry is the handler's job.
3718
+ *
3719
+ * A keypress initializes the conversation just as a prompt does, since a
3720
+ * caller can type without ever speaking; if that fails the digit still
3721
+ * arrives, with `conversationId` and `session` undefined. Keypresses don't
3722
+ * cancel in-flight streaming on their own — that's a separate `interrupt`
3723
+ * message, sent when `interruptible` includes `dtmf`.
3724
+ *
3725
+ * @example
3726
+ * ```typescript
3727
+ * const digits = new Map<string, string>();
3728
+ *
3729
+ * voiceChannel.onDtmf(({ conversationId, digit }) => {
3730
+ * if (!conversationId) return;
3731
+ * digits.set(conversationId, (digits.get(conversationId) ?? '') + digit);
3732
+ * });
3733
+ * ```
3734
+ */
3735
+ onDtmf(callback: DtmfHandler): void;
3678
3736
  /**
3679
3737
  * Resolve the public WebSocket URL from `TACConfig.voicePublicDomain` +
3680
3738
  * `TACConfig.voiceWebsocketPath`. Throws if `voicePublicDomain` isn't set.
@@ -3734,6 +3792,10 @@ declare class VoiceChannel extends BaseChannel {
3734
3792
  * Handle WebSocket interrupt message
3735
3793
  */
3736
3794
  private handleInterruptMessage;
3795
+ /**
3796
+ * Handle WebSocket DTMF message (caller keypress)
3797
+ */
3798
+ private handleDtmfMessage;
3737
3799
  /**
3738
3800
  * Handle WebSocket disconnection. In orchestrated mode the conversation stays
3739
3801
  * tracked until the CLOSED webhook (so a follow-up call can reuse it); in
@@ -4650,4 +4712,4 @@ declare class TACServer {
4650
4712
  stop(): Promise<void>;
4651
4713
  }
4652
4714
 
4653
- export { type ActionChannelSettings, ActionChannelSettingsSchema, type ActionParticipantRef, ActionParticipantRefSchema, type ActionResponse, ActionResponseSchema, type ActionTextContent, ActionTextContentSchema, type AdapterOptions, type AmdEvent, AmdEventSchema, type AmdHandler, type AnthropicTool, AnthropicToolSchema, type AuthorInfo, AuthorInfoSchema, BaseChannel, type BaseChannelEvents, type BaseChannelOptions, BaseClient, type BuiltInToolName, BuiltInTools, CALL_EVENT_KINDS, type CallEventKind, CallEventKindSchema, type CallOptions, CallOptionsSchema, type CallStatusEvent, CallStatusEventSchema, type CallStatusHandler, type CaptureRule, CaptureRuleSchema, type ChannelSettings, ChannelSettingsSchema, type ChannelType, ChannelTypeSchema, ChatChannel, type ChatChannelConfig, type CintelParticipant, CintelParticipantSchema, type Communication, type CommunicationContent, CommunicationContentSchema, type CommunicationParticipant, CommunicationParticipantSchema, CommunicationSchema, type ConversationAddress, ConversationAddressSchema, ConversationClient, type ConversationConfiguration, ConversationConfigurationSchema, type ConversationEndedCallback, type ConversationGroupingType, ConversationGroupingTypeSchema, type ConversationId, type ConversationIntelligenceConfig, ConversationIntelligenceConfigSchema, type ConversationParticipant, ConversationParticipantSchema, type ConversationRelayAttributes, ConversationRelayAttributesSchema, type ConversationRelayCallbackPayload, ConversationRelayCallbackPayloadSchema, type ConversationRelayConfig, ConversationRelayConfigSchema, type ConversationResponse, ConversationResponseSchema, type ConversationSession, ConversationSessionSchema, type ConversationSummaryItem, ConversationSummaryItemSchema, type ConversationWebhookPayload, type CreateConversationSummariesResponse, CreateConversationSummariesResponseSchema, type CreateObservationResponse, CreateObservationResponseSchema, type CreateObservationsRequest, CreateObservationsRequestSchema, type CustomParameters, CustomParametersSchema, EMPTY_MEMORY_RESPONSE, EnvironmentVariables, type ExecutionDetails, ExecutionDetailsSchema, type HandoffPayload, HandoffPayloadSchema, type HandoffResult, type InboundCallTwimlHandler, type InitiateChatConversationOptions, type InitiateConversationResult, type InitiateMessagingConversationOptions, InitiateMessagingConversationOptionsSchema, type InitiateVoiceConversationOptions, InitiateVoiceConversationOptionsSchema, type InitiateVoiceConversationResult, type IntelligenceConfiguration, IntelligenceConfigurationSchema, type InterruptCallback, type InterruptMessage, InterruptMessageSchema, type InterruptMode, InterruptModeSchema, type JSONSchema, JSONSchemaSchema, type KnowledgeBase, KnowledgeBaseSchema, type KnowledgeBaseStatus, KnowledgeBaseStatusSchema, type KnowledgeChunkResult, KnowledgeChunkResultSchema, KnowledgeClient, type KnowledgeSearchResponse, KnowledgeSearchResponseSchema, type LanguageAttributes, LanguageAttributesSchema, type LanguageConfig, LanguageConfigSchema, type ListCommunicationsResponse, ListCommunicationsResponseSchema, type ListConversationsResponse, ListConversationsResponseSchema, type ListParticipantsResponse, ListParticipantsResponseSchema, type Logger, type MemoryChannelType, MemoryChannelTypeSchema, MemoryClient, type MemoryCommunication, type MemoryCommunicationContent, MemoryCommunicationContentSchema, MemoryCommunicationSchema, type MemoryDeliveryStatus, MemoryDeliveryStatusSchema, type MemoryMode, MemoryModeSchema, type MemoryParticipant, MemoryParticipantSchema, type MemoryParticipantType, MemoryParticipantTypeSchema, MemoryPromptBuilder, type MemoryRetrievalRequest, MemoryRetrievalRequestSchema, type MemoryRetrievalResponse, MemoryRetrievalResponseSchema, type MessageDirection, MessageDirectionSchema, type MessageReadyCallback, MessagingChannel, type MessagingChannelConfig, type MessagingChannelEvents, type ObservationCreateRequest, ObservationCreateRequestSchema, type ObservationInfo, ObservationInfoSchema, type OpenAITool, OpenAIToolSchema, type Operator, type OperatorProcessingResult, OperatorProcessingResultSchema, type OperatorResult, type OperatorResultEvent, OperatorResultEventSchema, OperatorResultProcessor, OperatorResultSchema, OperatorSchema, type ParticipantAddress, ParticipantAddressSchema, type ParticipantAddressType, ParticipantAddressTypeSchema, type ParticipantId, type PendingHandoffData, PendingHandoffDataSchema, type Profile, type ProfileId, type ProfileLookupResponse, ProfileLookupResponseSchema, type ProfileResponse, ProfileResponseSchema, type PromptMessage, PromptMessageSchema, RCSChannel, type RecordingEvent, RecordingEventSchema, type RecordingHandler, SMSChannel, type SendMessageActionPayload, SendMessageActionPayloadSchema, type SendMessageActionRequest, SendMessageActionRequestSchema, type SessionInfo, SessionInfoSchema, type SessionMessage, SessionMessageSchema, type SetupMessage, SetupMessageSchema, type StatusCallback, StatusCallbackSchema, type StatusTimeouts, StatusTimeoutsSchema, type StreamTask, type SummaryInfo, SummaryInfoSchema, TAC, type TACChannelType, TACChannelTypeSchema, type TACCommunication, type TACCommunicationAuthor, TACCommunicationAuthorSchema, type TACCommunicationContent, TACCommunicationContentSchema, TACCommunicationSchema, TACConfig, type TACConfigData, TACConfigSchema, type TACDeliveryStatus, TACDeliveryStatusSchema, TACMemoryResponse, type TACOptions, type TACParticipantType, TACParticipantTypeSchema, TACServer, type TACServerConfig, TACTool, type TextTokenMessage, TextTokenMessageSchema, type ToolContext, type ToolExecutionResult, ToolExecutionResultSchema, type ToolFunction, type Transcription, TranscriptionSchema, type TranscriptionWord, TranscriptionWordSchema, type TwiMLOptions, TwiMLOptionsSchema, type TwiMLRequest, TwiMLRequestSchema, type TwilioMemoryConfig, TwilioMemoryConfigSchema, type TypedCallOptions, VoiceChannel, type VoiceChannelConfig, type VoiceChannelEvents, type WebSocketMessage, WebSocketMessageSchema, WhatsAppChannel, type _CallsCreateDriftGuards, type _SDKDriftGuards, amdEventFromForm, buildHandoffPayload, callOptionsToCreateParams, callStatusEventFromForm, createKnowledgeSearchTool, createKnowledgeSearchToolAsync, createKnowledgeTools, createLogger, createMemoryRetrievalTool, createMemoryTools, createMessagingTools, createSendMessageTool, createStudioHandoffTool, defineTool, isConversationId, isParticipantId, isProfileId, maskAddress, maskEmail, maskPhone, postStudioHandoff, recordingEventFromForm, redactTwimlParameters, scrubObject, scrubPii, studioExecutionsUrl, studioVoiceHandoffUrl, twiMLRequestFromForm };
4715
+ export { type ActionChannelSettings, ActionChannelSettingsSchema, type ActionParticipantRef, ActionParticipantRefSchema, type ActionResponse, ActionResponseSchema, type ActionTextContent, ActionTextContentSchema, type AdapterOptions, type AmdEvent, AmdEventSchema, type AmdHandler, type AnthropicTool, AnthropicToolSchema, type AuthorInfo, AuthorInfoSchema, BaseChannel, type BaseChannelEvents, type BaseChannelOptions, BaseClient, type BuiltInToolName, BuiltInTools, CALL_EVENT_KINDS, type CallEventKind, CallEventKindSchema, type CallOptions, CallOptionsSchema, type CallStatusEvent, CallStatusEventSchema, type CallStatusHandler, type CaptureRule, CaptureRuleSchema, type ChannelSettings, ChannelSettingsSchema, type ChannelType, ChannelTypeSchema, ChatChannel, type ChatChannelConfig, type CintelParticipant, CintelParticipantSchema, type Communication, type CommunicationContent, CommunicationContentSchema, type CommunicationParticipant, CommunicationParticipantSchema, CommunicationSchema, type ConversationAddress, ConversationAddressSchema, ConversationClient, type ConversationConfiguration, ConversationConfigurationSchema, type ConversationEndedCallback, type ConversationGroupingType, ConversationGroupingTypeSchema, type ConversationId, type ConversationIntelligenceConfig, ConversationIntelligenceConfigSchema, type ConversationParticipant, ConversationParticipantSchema, type ConversationRelayAttributes, ConversationRelayAttributesSchema, type ConversationRelayCallbackPayload, ConversationRelayCallbackPayloadSchema, type ConversationRelayConfig, ConversationRelayConfigSchema, type ConversationResponse, ConversationResponseSchema, type ConversationSession, ConversationSessionSchema, type ConversationSummaryItem, ConversationSummaryItemSchema, type ConversationWebhookPayload, type CreateConversationSummariesResponse, CreateConversationSummariesResponseSchema, type CreateObservationResponse, CreateObservationResponseSchema, type CreateObservationsRequest, CreateObservationsRequestSchema, type CustomParameters, CustomParametersSchema, type DtmfEvent, type DtmfHandler, type DtmfMessage, DtmfMessageSchema, EMPTY_MEMORY_RESPONSE, EnvironmentVariables, type ExecutionDetails, ExecutionDetailsSchema, type HandoffPayload, HandoffPayloadSchema, type HandoffResult, type InboundCallTwimlHandler, type InitiateChatConversationOptions, type InitiateConversationResult, type InitiateMessagingConversationOptions, InitiateMessagingConversationOptionsSchema, type InitiateVoiceConversationOptions, InitiateVoiceConversationOptionsSchema, type InitiateVoiceConversationResult, type IntelligenceConfiguration, IntelligenceConfigurationSchema, type InterruptCallback, type InterruptMessage, InterruptMessageSchema, type InterruptMode, InterruptModeSchema, type JSONSchema, JSONSchemaSchema, type KnowledgeBase, KnowledgeBaseSchema, type KnowledgeBaseStatus, KnowledgeBaseStatusSchema, type KnowledgeChunkResult, KnowledgeChunkResultSchema, KnowledgeClient, type KnowledgeSearchResponse, KnowledgeSearchResponseSchema, type LanguageAttributes, LanguageAttributesSchema, type LanguageConfig, LanguageConfigSchema, type ListCommunicationsResponse, ListCommunicationsResponseSchema, type ListConversationsResponse, ListConversationsResponseSchema, type ListParticipantsResponse, ListParticipantsResponseSchema, type Logger, type MemoryChannelType, MemoryChannelTypeSchema, MemoryClient, type MemoryCommunication, type MemoryCommunicationContent, MemoryCommunicationContentSchema, MemoryCommunicationSchema, type MemoryDeliveryStatus, MemoryDeliveryStatusSchema, type MemoryMode, MemoryModeSchema, type MemoryParticipant, MemoryParticipantSchema, type MemoryParticipantType, MemoryParticipantTypeSchema, MemoryPromptBuilder, type MemoryRetrievalRequest, MemoryRetrievalRequestSchema, type MemoryRetrievalResponse, MemoryRetrievalResponseSchema, type MessageDirection, MessageDirectionSchema, type MessageReadyCallback, MessagingChannel, type MessagingChannelConfig, type MessagingChannelEvents, type ObservationCreateRequest, ObservationCreateRequestSchema, type ObservationInfo, ObservationInfoSchema, type OpenAITool, OpenAIToolSchema, type Operator, type OperatorProcessingResult, OperatorProcessingResultSchema, type OperatorResult, type OperatorResultEvent, OperatorResultEventSchema, OperatorResultProcessor, OperatorResultSchema, OperatorSchema, type ParticipantAddress, ParticipantAddressSchema, type ParticipantAddressType, ParticipantAddressTypeSchema, type ParticipantId, type PendingHandoffData, PendingHandoffDataSchema, type Profile, type ProfileId, type ProfileLookupResponse, ProfileLookupResponseSchema, type ProfileResponse, ProfileResponseSchema, type PromptMessage, PromptMessageSchema, RCSChannel, type RecordingEvent, RecordingEventSchema, type RecordingHandler, SMSChannel, type SendMessageActionPayload, SendMessageActionPayloadSchema, type SendMessageActionRequest, SendMessageActionRequestSchema, type SessionInfo, SessionInfoSchema, type SessionMessage, SessionMessageSchema, type SetupMessage, SetupMessageSchema, type StatusCallback, StatusCallbackSchema, type StatusTimeouts, StatusTimeoutsSchema, type StreamTask, type SummaryInfo, SummaryInfoSchema, TAC, type TACChannelType, TACChannelTypeSchema, type TACCommunication, type TACCommunicationAuthor, TACCommunicationAuthorSchema, type TACCommunicationContent, TACCommunicationContentSchema, TACCommunicationSchema, TACConfig, type TACConfigData, TACConfigSchema, type TACDeliveryStatus, TACDeliveryStatusSchema, TACMemoryResponse, type TACOptions, type TACParticipantType, TACParticipantTypeSchema, TACServer, type TACServerConfig, TACTool, type TextTokenMessage, TextTokenMessageSchema, type ToolContext, type ToolExecutionResult, ToolExecutionResultSchema, type ToolFunction, type Transcription, TranscriptionSchema, type TranscriptionWord, TranscriptionWordSchema, type TwiMLOptions, TwiMLOptionsSchema, type TwiMLRequest, TwiMLRequestSchema, type TwilioMemoryConfig, TwilioMemoryConfigSchema, type TypedCallOptions, VoiceChannel, type VoiceChannelConfig, type VoiceChannelEvents, type WebSocketMessage, WebSocketMessageSchema, WhatsAppChannel, type _CallsCreateDriftGuards, type _SDKDriftGuards, amdEventFromForm, buildHandoffPayload, callOptionsToCreateParams, callStatusEventFromForm, createKnowledgeSearchTool, createKnowledgeSearchToolAsync, createKnowledgeTools, createLogger, createMemoryRetrievalTool, createMemoryTools, createMessagingTools, createSendMessageTool, createStudioHandoffTool, defineTool, isConversationId, isParticipantId, isProfileId, maskAddress, maskEmail, maskPhone, postStudioHandoff, recordingEventFromForm, redactTwimlParameters, scrubObject, scrubPii, studioExecutionsUrl, studioVoiceHandoffUrl, twiMLRequestFromForm };
package/dist/index.js CHANGED
@@ -769,10 +769,16 @@ var InterruptMessageSchema = z.object({
769
769
  utteranceUntilInterrupt: z.string().optional(),
770
770
  durationUntilInterruptMs: z.number().int().nonnegative().optional()
771
771
  });
772
+ var DtmfMessageSchema = z.object({
773
+ type: z.literal("dtmf"),
774
+ /** The key pressed: `0`-`9`, `*`, `#`, or `A`-`D`. */
775
+ digit: z.string()
776
+ });
772
777
  var WebSocketMessageSchema = z.union([
773
778
  SetupMessageSchema,
774
779
  PromptMessageSchema,
775
- InterruptMessageSchema
780
+ InterruptMessageSchema,
781
+ DtmfMessageSchema
776
782
  ]);
777
783
  var TextTokenMessageSchema = z.object({
778
784
  type: z.literal("text"),
@@ -1681,7 +1687,7 @@ function createLogger(options) {
1681
1687
 
1682
1688
  // package.json
1683
1689
  var package_default = {
1684
- version: "2.2.0"};
1690
+ version: "2.3.0"};
1685
1691
  function buildUserAgent() {
1686
1692
  return `twilio-agent-connect-typescript/${package_default.version}`;
1687
1693
  }
@@ -4803,6 +4809,32 @@ var VoiceChannel = class _VoiceChannel extends BaseChannel {
4803
4809
  onRecording(callback) {
4804
4810
  this.onRecordingHandler = callback;
4805
4811
  }
4812
+ /**
4813
+ * Register a handler for DTMF keypresses, called once per key in order.
4814
+ *
4815
+ * Requires `dtmfDetection: true` on the ConversationRelay config — without it
4816
+ * Twilio sends nothing and this never fires. Digits aren't buffered, so
4817
+ * accumulating a multi-digit entry is the handler's job.
4818
+ *
4819
+ * A keypress initializes the conversation just as a prompt does, since a
4820
+ * caller can type without ever speaking; if that fails the digit still
4821
+ * arrives, with `conversationId` and `session` undefined. Keypresses don't
4822
+ * cancel in-flight streaming on their own — that's a separate `interrupt`
4823
+ * message, sent when `interruptible` includes `dtmf`.
4824
+ *
4825
+ * @example
4826
+ * ```typescript
4827
+ * const digits = new Map<string, string>();
4828
+ *
4829
+ * voiceChannel.onDtmf(({ conversationId, digit }) => {
4830
+ * if (!conversationId) return;
4831
+ * digits.set(conversationId, (digits.get(conversationId) ?? '') + digit);
4832
+ * });
4833
+ * ```
4834
+ */
4835
+ onDtmf(callback) {
4836
+ this.voiceCallbacks.onDtmf = callback;
4837
+ }
4806
4838
  /**
4807
4839
  * Resolve the public WebSocket URL from `TACConfig.voicePublicDomain` +
4808
4840
  * `TACConfig.voiceWebsocketPath`. Throws if `voicePublicDomain` isn't set.
@@ -4854,6 +4886,9 @@ var VoiceChannel = class _VoiceChannel extends BaseChannel {
4854
4886
  case "interrupt":
4855
4887
  this.voiceCallbacks.onInterrupt = callback;
4856
4888
  break;
4889
+ case "dtmf":
4890
+ this.voiceCallbacks.onDtmf = callback;
4891
+ break;
4857
4892
  case "webSocketConnected":
4858
4893
  this.voiceCallbacks.onWebSocketConnected = callback;
4859
4894
  break;
@@ -4994,6 +5029,64 @@ var VoiceChannel = class _VoiceChannel extends BaseChannel {
4994
5029
  let fromNumber = null;
4995
5030
  let initializationFailed = false;
4996
5031
  let initPromise = null;
5032
+ const ensureConversation = async () => {
5033
+ if (conversationId) {
5034
+ return conversationId;
5035
+ }
5036
+ const sid = callSid;
5037
+ if (!sid) {
5038
+ return null;
5039
+ }
5040
+ const retryCount = this.initializationRetries.get(sid) ?? 0;
5041
+ if (retryCount >= this.MAX_INITIALIZATION_RETRIES) {
5042
+ throw new Error(
5043
+ `Cannot process message - conversation initialization failed after ${retryCount} attempts for callSid ${sid}`
5044
+ );
5045
+ }
5046
+ try {
5047
+ if (initializationFailed) {
5048
+ this.logger.info(
5049
+ { call_sid: sid, retry_count: retryCount },
5050
+ "Retrying conversation initialization after previous failure"
5051
+ );
5052
+ }
5053
+ if (!this.tac.isOrchestratorEnabled()) {
5054
+ conversationId = sid;
5055
+ this.webSocketConnections.set(conversationId, ws);
5056
+ this.callSidToConversationId.set(sid, conversationId);
5057
+ const session = this.startConversation(conversationId);
5058
+ session.callSid = sid;
5059
+ if (fromNumber) {
5060
+ session.authorInfo = { address: fromNumber };
5061
+ }
5062
+ if (this.voiceCallbacks.onWebSocketConnected) {
5063
+ this.voiceCallbacks.onWebSocketConnected({ conversationId });
5064
+ }
5065
+ } else {
5066
+ initPromise ??= this.initializeOrchestratedConversation(sid, fromNumber, ws);
5067
+ try {
5068
+ conversationId = await initPromise;
5069
+ } finally {
5070
+ initPromise = null;
5071
+ }
5072
+ }
5073
+ initializationFailed = false;
5074
+ this.initializationRetries.delete(sid);
5075
+ this.logger.info(
5076
+ { conversation_id: conversationId, call_sid: sid },
5077
+ "Conversation initialization succeeded"
5078
+ );
5079
+ return conversationId;
5080
+ } catch (err) {
5081
+ initializationFailed = true;
5082
+ this.initializationRetries.set(sid, retryCount + 1);
5083
+ this.logger.error(
5084
+ { err, call_sid: sid, retry_count: retryCount + 1 },
5085
+ "Conversation initialization failed"
5086
+ );
5087
+ throw err;
5088
+ }
5089
+ };
4997
5090
  ws.on("message", (data) => {
4998
5091
  (async () => {
4999
5092
  try {
@@ -5034,60 +5127,7 @@ var VoiceChannel = class _VoiceChannel extends BaseChannel {
5034
5127
  }
5035
5128
  break;
5036
5129
  case "prompt":
5037
- if (!conversationId && callSid) {
5038
- const retryCount = this.initializationRetries.get(callSid) ?? 0;
5039
- if (retryCount >= this.MAX_INITIALIZATION_RETRIES) {
5040
- throw new Error(
5041
- `Cannot process prompt - conversation initialization failed after ${retryCount} attempts for callSid ${callSid}`
5042
- );
5043
- }
5044
- try {
5045
- if (initializationFailed) {
5046
- this.logger.info(
5047
- { call_sid: callSid, retry_count: retryCount },
5048
- "Retrying conversation initialization after previous failure"
5049
- );
5050
- }
5051
- if (!this.tac.isOrchestratorEnabled()) {
5052
- conversationId = callSid;
5053
- this.webSocketConnections.set(conversationId, ws);
5054
- this.callSidToConversationId.set(callSid, conversationId);
5055
- const session = this.startConversation(conversationId);
5056
- session.callSid = callSid;
5057
- if (fromNumber) {
5058
- session.authorInfo = { address: fromNumber };
5059
- }
5060
- if (this.voiceCallbacks.onWebSocketConnected) {
5061
- this.voiceCallbacks.onWebSocketConnected({ conversationId });
5062
- }
5063
- } else {
5064
- initPromise ??= this.initializeOrchestratedConversation(
5065
- callSid,
5066
- fromNumber,
5067
- ws
5068
- );
5069
- try {
5070
- conversationId = await initPromise;
5071
- } finally {
5072
- initPromise = null;
5073
- }
5074
- }
5075
- initializationFailed = false;
5076
- this.initializationRetries.delete(callSid);
5077
- this.logger.info(
5078
- { conversation_id: conversationId, call_sid: callSid },
5079
- "Conversation initialization succeeded"
5080
- );
5081
- } catch (err) {
5082
- initializationFailed = true;
5083
- this.initializationRetries.set(callSid, retryCount + 1);
5084
- this.logger.error(
5085
- { err, call_sid: callSid, retry_count: retryCount + 1 },
5086
- "Conversation initialization failed"
5087
- );
5088
- throw err;
5089
- }
5090
- }
5130
+ await ensureConversation();
5091
5131
  if (conversationId) {
5092
5132
  const previousPrompt = this.promptQueues.get(conversationId) ?? Promise.resolve();
5093
5133
  const currentPrompt = previousPrompt.then(() => this.handlePromptMessage(conversationId, message)).catch((err) => {
@@ -5106,6 +5146,17 @@ var VoiceChannel = class _VoiceChannel extends BaseChannel {
5106
5146
  this.handleInterruptMessage(conversationId, message);
5107
5147
  }
5108
5148
  break;
5149
+ case "dtmf":
5150
+ try {
5151
+ await ensureConversation();
5152
+ } catch (err) {
5153
+ this.logger.warn(
5154
+ { err, call_sid: callSid },
5155
+ "Conversation initialization failed on DTMF keypress, delivering digit without a conversation"
5156
+ );
5157
+ }
5158
+ await this.handleDtmfMessage(conversationId, callSid, message);
5159
+ break;
5109
5160
  default:
5110
5161
  this.logger.debug(
5111
5162
  {
@@ -5211,6 +5262,23 @@ var VoiceChannel = class _VoiceChannel extends BaseChannel {
5211
5262
  });
5212
5263
  }
5213
5264
  }
5265
+ /**
5266
+ * Handle WebSocket DTMF message (caller keypress)
5267
+ */
5268
+ async handleDtmfMessage(conversationId, callSid, message) {
5269
+ const { digit } = message;
5270
+ this.logger.debug({ conversation_id: conversationId, call_sid: callSid }, "DTMF keypress");
5271
+ if (!this.voiceCallbacks.onDtmf) {
5272
+ return;
5273
+ }
5274
+ const session = conversationId ? this.getConversationSession(conversationId) : void 0;
5275
+ await this.voiceCallbacks.onDtmf({
5276
+ conversationId: conversationId ?? void 0,
5277
+ callSid: callSid ?? void 0,
5278
+ digit,
5279
+ ...session !== void 0 && { session }
5280
+ });
5281
+ }
5214
5282
  /**
5215
5283
  * Handle WebSocket disconnection. In orchestrated mode the conversation stays
5216
5284
  * tracked until the CLOSED webhook (so a follow-up call can reuse it); in
@@ -7016,6 +7084,6 @@ var TACServer = class {
7016
7084
  }
7017
7085
  };
7018
7086
 
7019
- export { ActionChannelSettingsSchema, ActionParticipantRefSchema, ActionResponseSchema, ActionTextContentSchema, AmdEventSchema, AnthropicToolSchema, AuthorInfoSchema, BaseChannel, BaseClient, BuiltInTools, CALL_EVENT_KINDS, CallEventKindSchema, CallOptionsSchema, CallStatusEventSchema, CaptureRuleSchema, ChannelSettingsSchema, ChannelTypeSchema, ChatChannel, CintelParticipantSchema, CommunicationContentSchema, CommunicationParticipantSchema, CommunicationSchema, ConversationAddressSchema, ConversationClient, ConversationConfigurationSchema, ConversationGroupingTypeSchema, ConversationIntelligenceConfigSchema, ConversationParticipantSchema, ConversationRelayAttributesSchema, ConversationRelayCallbackPayloadSchema, ConversationRelayConfigSchema, ConversationResponseSchema, ConversationSessionSchema, ConversationSummaryItemSchema, CreateConversationSummariesResponseSchema, CreateObservationResponseSchema, CreateObservationsRequestSchema, CustomParametersSchema, EMPTY_MEMORY_RESPONSE, EnvironmentVariables, ExecutionDetailsSchema, HandoffPayloadSchema, InitiateMessagingConversationOptionsSchema, InitiateVoiceConversationOptionsSchema, IntelligenceConfigurationSchema, InterruptMessageSchema, InterruptModeSchema, JSONSchemaSchema, KnowledgeBaseSchema, KnowledgeBaseStatusSchema, KnowledgeChunkResultSchema, KnowledgeClient, KnowledgeSearchResponseSchema, LanguageAttributesSchema, LanguageConfigSchema, ListCommunicationsResponseSchema, ListConversationsResponseSchema, ListParticipantsResponseSchema, MemoryChannelTypeSchema, MemoryClient, MemoryCommunicationContentSchema, MemoryCommunicationSchema, MemoryDeliveryStatusSchema, MemoryModeSchema, MemoryParticipantSchema, MemoryParticipantTypeSchema, MemoryPromptBuilder, MemoryRetrievalRequestSchema, MemoryRetrievalResponseSchema, MessageDirectionSchema, MessagingChannel, ObservationCreateRequestSchema, ObservationInfoSchema, OpenAIToolSchema, OperatorProcessingResultSchema, OperatorResultEventSchema, OperatorResultProcessor, OperatorResultSchema, OperatorSchema, ParticipantAddressSchema, ParticipantAddressTypeSchema, PendingHandoffDataSchema, ProfileLookupResponseSchema, ProfileResponseSchema, PromptMessageSchema, RCSChannel, RecordingEventSchema, SMSChannel, SendMessageActionPayloadSchema, SendMessageActionRequestSchema, SessionInfoSchema, SessionMessageSchema, SetupMessageSchema, StatusCallbackSchema, StatusTimeoutsSchema, SummaryInfoSchema, TAC, TACChannelTypeSchema, TACCommunicationAuthorSchema, TACCommunicationContentSchema, TACCommunicationSchema, TACConfig, TACConfigSchema, TACDeliveryStatusSchema, TACMemoryResponse, TACParticipantTypeSchema, TACServer, TACTool, TextTokenMessageSchema, ToolExecutionResultSchema, TranscriptionSchema, TranscriptionWordSchema, TwiMLOptionsSchema, TwiMLRequestSchema, TwilioMemoryConfigSchema, VoiceChannel, WebSocketMessageSchema, WhatsAppChannel, amdEventFromForm, buildHandoffPayload, callOptionsToCreateParams, callStatusEventFromForm, createKnowledgeSearchTool, createKnowledgeSearchToolAsync, createKnowledgeTools, createLogger, createMemoryRetrievalTool, createMemoryTools, createMessagingTools, createSendMessageTool, createStudioHandoffTool, defineTool, isConversationId, isParticipantId, isProfileId, maskAddress, maskEmail, maskPhone, postStudioHandoff, recordingEventFromForm, redactTwimlParameters, scrubObject, scrubPii, studioExecutionsUrl, studioVoiceHandoffUrl, twiMLRequestFromForm };
7087
+ export { ActionChannelSettingsSchema, ActionParticipantRefSchema, ActionResponseSchema, ActionTextContentSchema, AmdEventSchema, AnthropicToolSchema, AuthorInfoSchema, BaseChannel, BaseClient, BuiltInTools, CALL_EVENT_KINDS, CallEventKindSchema, CallOptionsSchema, CallStatusEventSchema, CaptureRuleSchema, ChannelSettingsSchema, ChannelTypeSchema, ChatChannel, CintelParticipantSchema, CommunicationContentSchema, CommunicationParticipantSchema, CommunicationSchema, ConversationAddressSchema, ConversationClient, ConversationConfigurationSchema, ConversationGroupingTypeSchema, ConversationIntelligenceConfigSchema, ConversationParticipantSchema, ConversationRelayAttributesSchema, ConversationRelayCallbackPayloadSchema, ConversationRelayConfigSchema, ConversationResponseSchema, ConversationSessionSchema, ConversationSummaryItemSchema, CreateConversationSummariesResponseSchema, CreateObservationResponseSchema, CreateObservationsRequestSchema, CustomParametersSchema, DtmfMessageSchema, EMPTY_MEMORY_RESPONSE, EnvironmentVariables, ExecutionDetailsSchema, HandoffPayloadSchema, InitiateMessagingConversationOptionsSchema, InitiateVoiceConversationOptionsSchema, IntelligenceConfigurationSchema, InterruptMessageSchema, InterruptModeSchema, JSONSchemaSchema, KnowledgeBaseSchema, KnowledgeBaseStatusSchema, KnowledgeChunkResultSchema, KnowledgeClient, KnowledgeSearchResponseSchema, LanguageAttributesSchema, LanguageConfigSchema, ListCommunicationsResponseSchema, ListConversationsResponseSchema, ListParticipantsResponseSchema, MemoryChannelTypeSchema, MemoryClient, MemoryCommunicationContentSchema, MemoryCommunicationSchema, MemoryDeliveryStatusSchema, MemoryModeSchema, MemoryParticipantSchema, MemoryParticipantTypeSchema, MemoryPromptBuilder, MemoryRetrievalRequestSchema, MemoryRetrievalResponseSchema, MessageDirectionSchema, MessagingChannel, ObservationCreateRequestSchema, ObservationInfoSchema, OpenAIToolSchema, OperatorProcessingResultSchema, OperatorResultEventSchema, OperatorResultProcessor, OperatorResultSchema, OperatorSchema, ParticipantAddressSchema, ParticipantAddressTypeSchema, PendingHandoffDataSchema, ProfileLookupResponseSchema, ProfileResponseSchema, PromptMessageSchema, RCSChannel, RecordingEventSchema, SMSChannel, SendMessageActionPayloadSchema, SendMessageActionRequestSchema, SessionInfoSchema, SessionMessageSchema, SetupMessageSchema, StatusCallbackSchema, StatusTimeoutsSchema, SummaryInfoSchema, TAC, TACChannelTypeSchema, TACCommunicationAuthorSchema, TACCommunicationContentSchema, TACCommunicationSchema, TACConfig, TACConfigSchema, TACDeliveryStatusSchema, TACMemoryResponse, TACParticipantTypeSchema, TACServer, TACTool, TextTokenMessageSchema, ToolExecutionResultSchema, TranscriptionSchema, TranscriptionWordSchema, TwiMLOptionsSchema, TwiMLRequestSchema, TwilioMemoryConfigSchema, VoiceChannel, WebSocketMessageSchema, WhatsAppChannel, amdEventFromForm, buildHandoffPayload, callOptionsToCreateParams, callStatusEventFromForm, createKnowledgeSearchTool, createKnowledgeSearchToolAsync, createKnowledgeTools, createLogger, createMemoryRetrievalTool, createMemoryTools, createMessagingTools, createSendMessageTool, createStudioHandoffTool, defineTool, isConversationId, isParticipantId, isProfileId, maskAddress, maskEmail, maskPhone, postStudioHandoff, recordingEventFromForm, redactTwimlParameters, scrubObject, scrubPii, studioExecutionsUrl, studioVoiceHandoffUrl, twiMLRequestFromForm };
7020
7088
  //# sourceMappingURL=index.js.map
7021
7089
  //# sourceMappingURL=index.js.map