twilio-agent-connect 1.0.2 → 2.0.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
@@ -51,7 +51,9 @@ declare const TACConfigSchema: z.ZodObject<{
51
51
  phoneTraitField: z.ZodDefault<z.ZodString>;
52
52
  }, z.core.$strip>>;
53
53
  conversationConfigurationId: z.ZodOptional<z.ZodString>;
54
- voicePublicDomain: z.ZodOptional<z.ZodString>;
54
+ voicePublicDomain: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
55
+ voiceWebsocketPath: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
56
+ voiceActionPath: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
55
57
  cintelConfigurationId: z.ZodOptional<z.ZodString>;
56
58
  cintelObservationOperatorSid: z.ZodOptional<z.ZodString>;
57
59
  cintelSummaryOperatorSid: z.ZodOptional<z.ZodString>;
@@ -79,6 +81,8 @@ declare const EnvironmentVariables: {
79
81
  readonly TWILIO_MEMORY_PHONE_TRAIT_FIELD: "TWILIO_MEMORY_PHONE_TRAIT_FIELD";
80
82
  readonly TWILIO_CONVERSATION_CONFIGURATION_ID: "TWILIO_CONVERSATION_CONFIGURATION_ID";
81
83
  readonly TWILIO_VOICE_PUBLIC_DOMAIN: "TWILIO_VOICE_PUBLIC_DOMAIN";
84
+ readonly TWILIO_VOICE_WEBSOCKET_PATH: "TWILIO_VOICE_WEBSOCKET_PATH";
85
+ readonly TWILIO_VOICE_ACTION_PATH: "TWILIO_VOICE_ACTION_PATH";
82
86
  readonly TWILIO_TAC_CI_CONFIGURATION_ID: "TWILIO_TAC_CI_CONFIGURATION_ID";
83
87
  readonly TWILIO_TAC_CI_OBSERVATION_OPERATOR_SID: "TWILIO_TAC_CI_OBSERVATION_OPERATOR_SID";
84
88
  readonly TWILIO_TAC_CI_SUMMARY_OPERATOR_SID: "TWILIO_TAC_CI_SUMMARY_OPERATOR_SID";
@@ -87,11 +91,17 @@ declare const EnvironmentVariables: {
87
91
  };
88
92
 
89
93
  /**
90
- * Memory retrieval mode for channels
94
+ * Memory retrieval mode for channels.
95
+ *
96
+ * - "always": Fetch memory with the message as query on every inbound message.
97
+ * - "once": Fetch memory once at conversation start with an empty query and
98
+ * cache it. The cache is invalidated when the conversation becomes INACTIVE.
99
+ * - "never": Never automatically fetch memory (default).
91
100
  */
92
101
  declare const MemoryModeSchema: z.ZodEnum<{
93
102
  never: "never";
94
103
  always: "always";
104
+ once: "once";
95
105
  }>;
96
106
  type MemoryMode = z.infer<typeof MemoryModeSchema>;
97
107
  /**
@@ -471,9 +481,9 @@ declare const CreateConversationSummariesResponseSchema: z.ZodObject<{
471
481
  type CreateConversationSummariesResponse = z.infer<typeof CreateConversationSummariesResponseSchema>;
472
482
 
473
483
  /**
474
- * Participant address type for different communication channels
484
+ * Channel type for communications
475
485
  */
476
- declare const ParticipantAddressTypeSchema: z.ZodEnum<{
486
+ declare const TACChannelTypeSchema: z.ZodEnum<{
477
487
  VOICE: "VOICE";
478
488
  SMS: "SMS";
479
489
  RCS: "RCS";
@@ -483,31 +493,34 @@ declare const ParticipantAddressTypeSchema: z.ZodEnum<{
483
493
  API: "API";
484
494
  SYSTEM: "SYSTEM";
485
495
  }>;
486
- type ParticipantAddressType = z.infer<typeof ParticipantAddressTypeSchema>;
496
+ type TACChannelType = z.infer<typeof TACChannelTypeSchema>;
487
497
  /**
488
- * Participant address containing channel and address
498
+ * Delivery status for communications
489
499
  */
490
- declare const ParticipantAddressSchema: z.ZodObject<{
491
- channel: z.ZodEnum<{
492
- VOICE: "VOICE";
493
- SMS: "SMS";
494
- RCS: "RCS";
495
- EMAIL: "EMAIL";
496
- WHATSAPP: "WHATSAPP";
497
- CHAT: "CHAT";
498
- API: "API";
499
- SYSTEM: "SYSTEM";
500
- }>;
501
- address: z.ZodString;
502
- channelId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
503
- }, z.core.$strip>;
504
- type ParticipantAddress = z.infer<typeof ParticipantAddressSchema>;
500
+ declare const TACDeliveryStatusSchema: z.ZodEnum<{
501
+ INITIATED: "INITIATED";
502
+ IN_PROGRESS: "IN_PROGRESS";
503
+ DELIVERED: "DELIVERED";
504
+ COMPLETED: "COMPLETED";
505
+ FAILED: "FAILED";
506
+ }>;
507
+ type TACDeliveryStatus = z.infer<typeof TACDeliveryStatusSchema>;
505
508
  /**
506
- * Communication participant for Conversations Service API (Conversation Orchestrator).
509
+ * Participant type
510
+ */
511
+ declare const TACParticipantTypeSchema: z.ZodEnum<{
512
+ HUMAN_AGENT: "HUMAN_AGENT";
513
+ CUSTOMER: "CUSTOMER";
514
+ AI_AGENT: "AI_AGENT";
515
+ AGENT: "AGENT";
516
+ }>;
517
+ type TACParticipantType = z.infer<typeof TACParticipantTypeSchema>;
518
+ /**
519
+ * Unified author model with all fields from both Memory and Conversation Orchestrator APIs.
507
520
  *
508
- * Note: participantId is required for SDK validation when creating communications.
521
+ * Fields not available from a particular API will be undefined.
509
522
  */
510
- declare const CommunicationParticipantSchema: z.ZodObject<{
523
+ declare const TACCommunicationAuthorSchema: z.ZodObject<{
511
524
  address: z.ZodString;
512
525
  channel: z.ZodEnum<{
513
526
  VOICE: "VOICE";
@@ -519,7 +532,7 @@ declare const CommunicationParticipantSchema: z.ZodObject<{
519
532
  API: "API";
520
533
  SYSTEM: "SYSTEM";
521
534
  }>;
522
- participantId: z.ZodString;
535
+ participantId: z.ZodOptional<z.ZodString>;
523
536
  deliveryStatus: z.ZodOptional<z.ZodEnum<{
524
537
  INITIATED: "INITIATED";
525
538
  IN_PROGRESS: "IN_PROGRESS";
@@ -527,42 +540,26 @@ declare const CommunicationParticipantSchema: z.ZodObject<{
527
540
  COMPLETED: "COMPLETED";
528
541
  FAILED: "FAILED";
529
542
  }>>;
543
+ id: z.ZodOptional<z.ZodString>;
544
+ name: z.ZodOptional<z.ZodString>;
545
+ type: z.ZodOptional<z.ZodEnum<{
546
+ HUMAN_AGENT: "HUMAN_AGENT";
547
+ CUSTOMER: "CUSTOMER";
548
+ AI_AGENT: "AI_AGENT";
549
+ AGENT: "AGENT";
550
+ }>>;
551
+ profileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
530
552
  }, z.core.$strip>;
531
- type CommunicationParticipant = z.infer<typeof CommunicationParticipantSchema>;
532
- /**
533
- * Word-level transcription data with timing information.
534
- */
535
- declare const TranscriptionWordSchema: z.ZodObject<{
536
- text: z.ZodString;
537
- startTime: z.ZodOptional<z.ZodString>;
538
- endTime: z.ZodOptional<z.ZodString>;
539
- }, z.core.$strip>;
540
- type TranscriptionWord = z.infer<typeof TranscriptionWordSchema>;
541
- /**
542
- * Transcription metadata for communication content.
543
- */
544
- declare const TranscriptionSchema: z.ZodObject<{
545
- channel: z.ZodOptional<z.ZodNumber>;
546
- confidence: z.ZodOptional<z.ZodNumber>;
547
- engine: z.ZodOptional<z.ZodString>;
548
- words: z.ZodOptional<z.ZodArray<z.ZodObject<{
549
- text: z.ZodString;
550
- startTime: z.ZodOptional<z.ZodString>;
551
- endTime: z.ZodOptional<z.ZodString>;
552
- }, z.core.$strip>>>;
553
- }, z.core.$strip>;
554
- type Transcription = z.infer<typeof TranscriptionSchema>;
553
+ type TACCommunicationAuthor = z.infer<typeof TACCommunicationAuthorSchema>;
555
554
  /**
556
- * Communication content (ContentText or ContentTranscription).
557
- *
558
- * Note: In the Conversation Orchestrator API, both `type` and `text` are required fields.
555
+ * Unified content model with all fields from both Memory and Conversation Orchestrator APIs.
559
556
  */
560
- declare const CommunicationContentSchema: z.ZodObject<{
561
- type: z.ZodEnum<{
557
+ declare const TACCommunicationContentSchema: z.ZodObject<{
558
+ type: z.ZodOptional<z.ZodEnum<{
562
559
  TEXT: "TEXT";
563
560
  TRANSCRIPTION: "TRANSCRIPTION";
564
- }>;
565
- text: z.ZodString;
561
+ }>>;
562
+ text: z.ZodOptional<z.ZodString>;
566
563
  transcription: z.ZodOptional<z.ZodObject<{
567
564
  channel: z.ZodOptional<z.ZodNumber>;
568
565
  confidence: z.ZodOptional<z.ZodNumber>;
@@ -574,16 +571,15 @@ declare const CommunicationContentSchema: z.ZodObject<{
574
571
  }, z.core.$strip>>>;
575
572
  }, z.core.$strip>>;
576
573
  }, z.core.$strip>;
577
- type CommunicationContent = z.infer<typeof CommunicationContentSchema>;
574
+ type TACCommunicationContent = z.infer<typeof TACCommunicationContentSchema>;
578
575
  /**
579
- * Communication from Conversations Service API (Conversation Orchestrator).
576
+ * Unified communication model with all fields from both Memory and Conversation Orchestrator APIs.
580
577
  *
581
- * Note: `createdAt` is optional per API spec.
578
+ * Provides complete access to all communication fields regardless of the source.
579
+ * Fields not available from a particular API will be undefined.
582
580
  */
583
- declare const CommunicationSchema: z.ZodObject<{
581
+ declare const TACCommunicationSchema: z.ZodObject<{
584
582
  id: z.ZodString;
585
- conversationId: z.ZodString;
586
- accountId: z.ZodString;
587
583
  author: z.ZodObject<{
588
584
  address: z.ZodString;
589
585
  channel: z.ZodEnum<{
@@ -596,7 +592,7 @@ declare const CommunicationSchema: z.ZodObject<{
596
592
  API: "API";
597
593
  SYSTEM: "SYSTEM";
598
594
  }>;
599
- participantId: z.ZodString;
595
+ participantId: z.ZodOptional<z.ZodString>;
600
596
  deliveryStatus: z.ZodOptional<z.ZodEnum<{
601
597
  INITIATED: "INITIATED";
602
598
  IN_PROGRESS: "IN_PROGRESS";
@@ -604,13 +600,22 @@ declare const CommunicationSchema: z.ZodObject<{
604
600
  COMPLETED: "COMPLETED";
605
601
  FAILED: "FAILED";
606
602
  }>>;
603
+ id: z.ZodOptional<z.ZodString>;
604
+ name: z.ZodOptional<z.ZodString>;
605
+ type: z.ZodOptional<z.ZodEnum<{
606
+ HUMAN_AGENT: "HUMAN_AGENT";
607
+ CUSTOMER: "CUSTOMER";
608
+ AI_AGENT: "AI_AGENT";
609
+ AGENT: "AGENT";
610
+ }>>;
611
+ profileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
607
612
  }, z.core.$strip>;
608
613
  content: z.ZodObject<{
609
- type: z.ZodEnum<{
614
+ type: z.ZodOptional<z.ZodEnum<{
610
615
  TEXT: "TEXT";
611
616
  TRANSCRIPTION: "TRANSCRIPTION";
612
- }>;
613
- text: z.ZodString;
617
+ }>>;
618
+ text: z.ZodOptional<z.ZodString>;
614
619
  transcription: z.ZodOptional<z.ZodObject<{
615
620
  channel: z.ZodOptional<z.ZodNumber>;
616
621
  confidence: z.ZodOptional<z.ZodNumber>;
@@ -622,7 +627,7 @@ declare const CommunicationSchema: z.ZodObject<{
622
627
  }, z.core.$strip>>>;
623
628
  }, z.core.$strip>>;
624
629
  }, z.core.$strip>;
625
- recipients: z.ZodArray<z.ZodObject<{
630
+ recipients: z.ZodDefault<z.ZodArray<z.ZodObject<{
626
631
  address: z.ZodString;
627
632
  channel: z.ZodEnum<{
628
633
  VOICE: "VOICE";
@@ -634,7 +639,7 @@ declare const CommunicationSchema: z.ZodObject<{
634
639
  API: "API";
635
640
  SYSTEM: "SYSTEM";
636
641
  }>;
637
- participantId: z.ZodString;
642
+ participantId: z.ZodOptional<z.ZodString>;
638
643
  deliveryStatus: z.ZodOptional<z.ZodEnum<{
639
644
  INITIATED: "INITIATED";
640
645
  IN_PROGRESS: "IN_PROGRESS";
@@ -642,120 +647,386 @@ declare const CommunicationSchema: z.ZodObject<{
642
647
  COMPLETED: "COMPLETED";
643
648
  FAILED: "FAILED";
644
649
  }>>;
645
- }, z.core.$strip>>;
650
+ id: z.ZodOptional<z.ZodString>;
651
+ name: z.ZodOptional<z.ZodString>;
652
+ type: z.ZodOptional<z.ZodEnum<{
653
+ HUMAN_AGENT: "HUMAN_AGENT";
654
+ CUSTOMER: "CUSTOMER";
655
+ AI_AGENT: "AI_AGENT";
656
+ AGENT: "AGENT";
657
+ }>>;
658
+ profileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
659
+ }, z.core.$strip>>>;
646
660
  channelId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
647
- createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
648
- updatedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
649
- occurredAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
650
- }, z.core.$strip>;
651
- type Communication = z.infer<typeof CommunicationSchema>;
652
- /**
653
- * List communications response
654
- */
655
- declare const ListCommunicationsResponseSchema: z.ZodObject<{
656
- communications: z.ZodArray<z.ZodObject<{
657
- id: z.ZodString;
658
- conversationId: z.ZodString;
659
- accountId: z.ZodString;
660
- author: z.ZodObject<{
661
- address: z.ZodString;
662
- channel: z.ZodEnum<{
663
- VOICE: "VOICE";
664
- SMS: "SMS";
665
- RCS: "RCS";
666
- EMAIL: "EMAIL";
667
- WHATSAPP: "WHATSAPP";
668
- CHAT: "CHAT";
669
- API: "API";
670
- SYSTEM: "SYSTEM";
671
- }>;
672
- participantId: z.ZodString;
673
- deliveryStatus: z.ZodOptional<z.ZodEnum<{
674
- INITIATED: "INITIATED";
675
- IN_PROGRESS: "IN_PROGRESS";
676
- DELIVERED: "DELIVERED";
677
- COMPLETED: "COMPLETED";
678
- FAILED: "FAILED";
679
- }>>;
680
- }, z.core.$strip>;
681
- content: z.ZodObject<{
682
- type: z.ZodEnum<{
683
- TEXT: "TEXT";
684
- TRANSCRIPTION: "TRANSCRIPTION";
685
- }>;
686
- text: z.ZodString;
687
- transcription: z.ZodOptional<z.ZodObject<{
688
- channel: z.ZodOptional<z.ZodNumber>;
689
- confidence: z.ZodOptional<z.ZodNumber>;
690
- engine: z.ZodOptional<z.ZodString>;
691
- words: z.ZodOptional<z.ZodArray<z.ZodObject<{
692
- text: z.ZodString;
693
- startTime: z.ZodOptional<z.ZodString>;
694
- endTime: z.ZodOptional<z.ZodString>;
695
- }, z.core.$strip>>>;
696
- }, z.core.$strip>>;
697
- }, z.core.$strip>;
698
- recipients: z.ZodArray<z.ZodObject<{
699
- address: z.ZodString;
700
- channel: z.ZodEnum<{
701
- VOICE: "VOICE";
702
- SMS: "SMS";
703
- RCS: "RCS";
704
- EMAIL: "EMAIL";
705
- WHATSAPP: "WHATSAPP";
706
- CHAT: "CHAT";
707
- API: "API";
708
- SYSTEM: "SYSTEM";
709
- }>;
710
- participantId: z.ZodString;
711
- deliveryStatus: z.ZodOptional<z.ZodEnum<{
712
- INITIATED: "INITIATED";
713
- IN_PROGRESS: "IN_PROGRESS";
714
- DELIVERED: "DELIVERED";
715
- COMPLETED: "COMPLETED";
716
- FAILED: "FAILED";
717
- }>>;
718
- }, z.core.$strip>>;
719
- channelId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
720
- createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
721
- updatedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
722
- occurredAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
723
- }, z.core.$strip>>;
661
+ createdAt: z.ZodOptional<z.ZodString>;
662
+ updatedAt: z.ZodOptional<z.ZodString>;
663
+ conversationId: z.ZodOptional<z.ZodString>;
664
+ accountId: z.ZodOptional<z.ZodString>;
724
665
  }, z.core.$strip>;
725
- type ListCommunicationsResponse = z.infer<typeof ListCommunicationsResponseSchema>;
666
+ type TACCommunication = z.infer<typeof TACCommunicationSchema>;
667
+
726
668
  /**
727
- * Participant reference for the Actions API (`from`/`to` entries).
669
+ * Unified response wrapper for TAC.retrieveMemory().
728
670
  *
729
- * Either `participantId` or `address` must be supplied; `channel` is always required.
730
- * When both are provided, Conversation Orchestrator uses `participantId` and
731
- * `channel` disambiguates which of the participant's addresses to use.
732
- */
733
- declare const ActionParticipantRefSchema: z.ZodObject<{
734
- participantId: z.ZodOptional<z.ZodString>;
735
- address: z.ZodOptional<z.ZodString>;
736
- channel: z.ZodEnum<{
737
- VOICE: "VOICE";
738
- SMS: "SMS";
739
- RCS: "RCS";
740
- EMAIL: "EMAIL";
741
- WHATSAPP: "WHATSAPP";
742
- CHAT: "CHAT";
743
- API: "API";
744
- SYSTEM: "SYSTEM";
745
- }>;
746
- }, z.core.$strip>;
747
- type ActionParticipantRef = z.infer<typeof ActionParticipantRefSchema>;
748
- /**
749
- * Plain-text content for a SEND_MESSAGE action.
750
- */
751
- declare const ActionTextContentSchema: z.ZodObject<{
752
- text: z.ZodString;
753
- }, z.core.$strip>;
754
- type ActionTextContent = z.infer<typeof ActionTextContentSchema>;
755
- /**
756
- * Channel-specific settings forwarded to the downstream backend.
671
+ * Provides a consistent interface for accessing memory data regardless of whether
672
+ * Memory API is configured or falling back to Conversation Orchestrator Communications API.
757
673
  *
758
- * Open pass-through: any field not explicitly modeled here (e.g.
674
+ * Memory configured:
675
+ * - observations, summaries, communications all populated
676
+ * - communications include Memory-specific fields (author id, name, type, profileId)
677
+ *
678
+ * Conversation Orchestrator fallback:
679
+ * - observations and summaries are empty arrays
680
+ * - communications include Conversation Orchestrator-specific fields (conversationId, accountId, etc.)
681
+ */
682
+ declare class TACMemoryResponse {
683
+ private readonly _data;
684
+ private readonly _communications;
685
+ /**
686
+ * Initialize wrapper with either Memory or Conversation Orchestrator data.
687
+ *
688
+ * @param data - Either MemoryRetrievalResponse (Memory) or Communication[] (Conversation Orchestrator)
689
+ */
690
+ constructor(data: MemoryRetrievalResponse | Communication[]);
691
+ /**
692
+ * Get observation memories.
693
+ *
694
+ * @returns List of observations if Memory is configured, empty array for Conversation Orchestrator fallback
695
+ */
696
+ get observations(): ObservationInfo[];
697
+ /**
698
+ * Get summary memories.
699
+ *
700
+ * @returns List of summaries if Memory is configured, empty array for Conversation Orchestrator fallback
701
+ */
702
+ get summaries(): SummaryInfo[];
703
+ /**
704
+ * Get communications in unified format with all available fields.
705
+ *
706
+ * Communications are converted to a common format during initialization that includes
707
+ * all fields from both Memory and Conversation Orchestrator APIs. Fields not available from a particular
708
+ * API will be undefined.
709
+ *
710
+ * @returns List of unified communications with all available fields
711
+ */
712
+ get communications(): TACCommunication[];
713
+ /**
714
+ * Check if Memory API is configured and providing full features.
715
+ *
716
+ * @returns true if Memory is configured (observations/summaries available),
717
+ * false if using Conversation Orchestrator fallback (only communications available)
718
+ */
719
+ get hasMemoryFeatures(): boolean;
720
+ /**
721
+ * Access raw underlying data for advanced use cases.
722
+ *
723
+ * Use this when you need access to all fields from the original API responses,
724
+ * not just the unified common fields.
725
+ *
726
+ * @returns Either MemoryRetrievalResponse or Communication[] depending on configuration
727
+ */
728
+ get rawData(): MemoryRetrievalResponse | Communication[];
729
+ /**
730
+ * Build formatted prompt sections from available memory data.
731
+ *
732
+ * Generates markdown-formatted sections for observations, summaries, and communications
733
+ * that can be injected into LLM prompts. Each section includes a heading and formatted content.
734
+ * Sections with no data are omitted from the result.
735
+ *
736
+ * @returns Array of formatted prompt sections, empty array if no memory data available
737
+ */
738
+ buildMemoryPrompts(): string[];
739
+ private buildObservationsPrompt;
740
+ private buildSummariesPrompt;
741
+ private buildCommunicationsPrompt;
742
+ }
743
+
744
+ /**
745
+ * Participant address type for different communication channels
746
+ */
747
+ declare const ParticipantAddressTypeSchema: z.ZodEnum<{
748
+ VOICE: "VOICE";
749
+ SMS: "SMS";
750
+ RCS: "RCS";
751
+ EMAIL: "EMAIL";
752
+ WHATSAPP: "WHATSAPP";
753
+ CHAT: "CHAT";
754
+ API: "API";
755
+ SYSTEM: "SYSTEM";
756
+ }>;
757
+ type ParticipantAddressType = z.infer<typeof ParticipantAddressTypeSchema>;
758
+ /**
759
+ * Participant address containing channel and address
760
+ */
761
+ declare const ParticipantAddressSchema: z.ZodObject<{
762
+ channel: z.ZodEnum<{
763
+ VOICE: "VOICE";
764
+ SMS: "SMS";
765
+ RCS: "RCS";
766
+ EMAIL: "EMAIL";
767
+ WHATSAPP: "WHATSAPP";
768
+ CHAT: "CHAT";
769
+ API: "API";
770
+ SYSTEM: "SYSTEM";
771
+ }>;
772
+ address: z.ZodString;
773
+ channelId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
774
+ }, z.core.$strip>;
775
+ type ParticipantAddress = z.infer<typeof ParticipantAddressSchema>;
776
+ /**
777
+ * Communication participant for Conversations Service API (Conversation Orchestrator).
778
+ *
779
+ * Note: participantId is required for SDK validation when creating communications.
780
+ */
781
+ declare const CommunicationParticipantSchema: z.ZodObject<{
782
+ address: z.ZodString;
783
+ channel: z.ZodEnum<{
784
+ VOICE: "VOICE";
785
+ SMS: "SMS";
786
+ RCS: "RCS";
787
+ EMAIL: "EMAIL";
788
+ WHATSAPP: "WHATSAPP";
789
+ CHAT: "CHAT";
790
+ API: "API";
791
+ SYSTEM: "SYSTEM";
792
+ }>;
793
+ participantId: z.ZodString;
794
+ deliveryStatus: z.ZodOptional<z.ZodEnum<{
795
+ INITIATED: "INITIATED";
796
+ IN_PROGRESS: "IN_PROGRESS";
797
+ DELIVERED: "DELIVERED";
798
+ COMPLETED: "COMPLETED";
799
+ FAILED: "FAILED";
800
+ }>>;
801
+ }, z.core.$strip>;
802
+ type CommunicationParticipant = z.infer<typeof CommunicationParticipantSchema>;
803
+ /**
804
+ * Word-level transcription data with timing information.
805
+ */
806
+ declare const TranscriptionWordSchema: z.ZodObject<{
807
+ text: z.ZodString;
808
+ startTime: z.ZodOptional<z.ZodString>;
809
+ endTime: z.ZodOptional<z.ZodString>;
810
+ }, z.core.$strip>;
811
+ type TranscriptionWord = z.infer<typeof TranscriptionWordSchema>;
812
+ /**
813
+ * Transcription metadata for communication content.
814
+ */
815
+ declare const TranscriptionSchema: z.ZodObject<{
816
+ channel: z.ZodOptional<z.ZodNumber>;
817
+ confidence: z.ZodOptional<z.ZodNumber>;
818
+ engine: z.ZodOptional<z.ZodString>;
819
+ words: z.ZodOptional<z.ZodArray<z.ZodObject<{
820
+ text: z.ZodString;
821
+ startTime: z.ZodOptional<z.ZodString>;
822
+ endTime: z.ZodOptional<z.ZodString>;
823
+ }, z.core.$strip>>>;
824
+ }, z.core.$strip>;
825
+ type Transcription = z.infer<typeof TranscriptionSchema>;
826
+ /**
827
+ * Communication content (ContentText or ContentTranscription).
828
+ *
829
+ * Note: In the Conversation Orchestrator API, both `type` and `text` are required fields.
830
+ */
831
+ declare const CommunicationContentSchema: z.ZodObject<{
832
+ type: z.ZodEnum<{
833
+ TEXT: "TEXT";
834
+ TRANSCRIPTION: "TRANSCRIPTION";
835
+ }>;
836
+ text: z.ZodString;
837
+ transcription: z.ZodOptional<z.ZodObject<{
838
+ channel: z.ZodOptional<z.ZodNumber>;
839
+ confidence: z.ZodOptional<z.ZodNumber>;
840
+ engine: z.ZodOptional<z.ZodString>;
841
+ words: z.ZodOptional<z.ZodArray<z.ZodObject<{
842
+ text: z.ZodString;
843
+ startTime: z.ZodOptional<z.ZodString>;
844
+ endTime: z.ZodOptional<z.ZodString>;
845
+ }, z.core.$strip>>>;
846
+ }, z.core.$strip>>;
847
+ }, z.core.$strip>;
848
+ type CommunicationContent = z.infer<typeof CommunicationContentSchema>;
849
+ /**
850
+ * Communication from Conversations Service API (Conversation Orchestrator).
851
+ *
852
+ * Note: `createdAt` is optional per API spec.
853
+ */
854
+ declare const CommunicationSchema: z.ZodObject<{
855
+ id: z.ZodString;
856
+ conversationId: z.ZodString;
857
+ accountId: z.ZodString;
858
+ author: z.ZodObject<{
859
+ address: z.ZodString;
860
+ channel: z.ZodEnum<{
861
+ VOICE: "VOICE";
862
+ SMS: "SMS";
863
+ RCS: "RCS";
864
+ EMAIL: "EMAIL";
865
+ WHATSAPP: "WHATSAPP";
866
+ CHAT: "CHAT";
867
+ API: "API";
868
+ SYSTEM: "SYSTEM";
869
+ }>;
870
+ participantId: z.ZodString;
871
+ deliveryStatus: z.ZodOptional<z.ZodEnum<{
872
+ INITIATED: "INITIATED";
873
+ IN_PROGRESS: "IN_PROGRESS";
874
+ DELIVERED: "DELIVERED";
875
+ COMPLETED: "COMPLETED";
876
+ FAILED: "FAILED";
877
+ }>>;
878
+ }, z.core.$strip>;
879
+ content: z.ZodObject<{
880
+ type: z.ZodEnum<{
881
+ TEXT: "TEXT";
882
+ TRANSCRIPTION: "TRANSCRIPTION";
883
+ }>;
884
+ text: z.ZodString;
885
+ transcription: z.ZodOptional<z.ZodObject<{
886
+ channel: z.ZodOptional<z.ZodNumber>;
887
+ confidence: z.ZodOptional<z.ZodNumber>;
888
+ engine: z.ZodOptional<z.ZodString>;
889
+ words: z.ZodOptional<z.ZodArray<z.ZodObject<{
890
+ text: z.ZodString;
891
+ startTime: z.ZodOptional<z.ZodString>;
892
+ endTime: z.ZodOptional<z.ZodString>;
893
+ }, z.core.$strip>>>;
894
+ }, z.core.$strip>>;
895
+ }, z.core.$strip>;
896
+ recipients: z.ZodArray<z.ZodObject<{
897
+ address: z.ZodString;
898
+ channel: z.ZodEnum<{
899
+ VOICE: "VOICE";
900
+ SMS: "SMS";
901
+ RCS: "RCS";
902
+ EMAIL: "EMAIL";
903
+ WHATSAPP: "WHATSAPP";
904
+ CHAT: "CHAT";
905
+ API: "API";
906
+ SYSTEM: "SYSTEM";
907
+ }>;
908
+ participantId: z.ZodString;
909
+ deliveryStatus: z.ZodOptional<z.ZodEnum<{
910
+ INITIATED: "INITIATED";
911
+ IN_PROGRESS: "IN_PROGRESS";
912
+ DELIVERED: "DELIVERED";
913
+ COMPLETED: "COMPLETED";
914
+ FAILED: "FAILED";
915
+ }>>;
916
+ }, z.core.$strip>>;
917
+ channelId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
918
+ createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
919
+ updatedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
920
+ occurredAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
921
+ }, z.core.$strip>;
922
+ type Communication = z.infer<typeof CommunicationSchema>;
923
+ /**
924
+ * List communications response
925
+ */
926
+ declare const ListCommunicationsResponseSchema: z.ZodObject<{
927
+ communications: z.ZodArray<z.ZodObject<{
928
+ id: z.ZodString;
929
+ conversationId: z.ZodString;
930
+ accountId: z.ZodString;
931
+ author: z.ZodObject<{
932
+ address: z.ZodString;
933
+ channel: z.ZodEnum<{
934
+ VOICE: "VOICE";
935
+ SMS: "SMS";
936
+ RCS: "RCS";
937
+ EMAIL: "EMAIL";
938
+ WHATSAPP: "WHATSAPP";
939
+ CHAT: "CHAT";
940
+ API: "API";
941
+ SYSTEM: "SYSTEM";
942
+ }>;
943
+ participantId: z.ZodString;
944
+ deliveryStatus: z.ZodOptional<z.ZodEnum<{
945
+ INITIATED: "INITIATED";
946
+ IN_PROGRESS: "IN_PROGRESS";
947
+ DELIVERED: "DELIVERED";
948
+ COMPLETED: "COMPLETED";
949
+ FAILED: "FAILED";
950
+ }>>;
951
+ }, z.core.$strip>;
952
+ content: z.ZodObject<{
953
+ type: z.ZodEnum<{
954
+ TEXT: "TEXT";
955
+ TRANSCRIPTION: "TRANSCRIPTION";
956
+ }>;
957
+ text: z.ZodString;
958
+ transcription: z.ZodOptional<z.ZodObject<{
959
+ channel: z.ZodOptional<z.ZodNumber>;
960
+ confidence: z.ZodOptional<z.ZodNumber>;
961
+ engine: z.ZodOptional<z.ZodString>;
962
+ words: z.ZodOptional<z.ZodArray<z.ZodObject<{
963
+ text: z.ZodString;
964
+ startTime: z.ZodOptional<z.ZodString>;
965
+ endTime: z.ZodOptional<z.ZodString>;
966
+ }, z.core.$strip>>>;
967
+ }, z.core.$strip>>;
968
+ }, z.core.$strip>;
969
+ recipients: z.ZodArray<z.ZodObject<{
970
+ address: z.ZodString;
971
+ channel: z.ZodEnum<{
972
+ VOICE: "VOICE";
973
+ SMS: "SMS";
974
+ RCS: "RCS";
975
+ EMAIL: "EMAIL";
976
+ WHATSAPP: "WHATSAPP";
977
+ CHAT: "CHAT";
978
+ API: "API";
979
+ SYSTEM: "SYSTEM";
980
+ }>;
981
+ participantId: z.ZodString;
982
+ deliveryStatus: z.ZodOptional<z.ZodEnum<{
983
+ INITIATED: "INITIATED";
984
+ IN_PROGRESS: "IN_PROGRESS";
985
+ DELIVERED: "DELIVERED";
986
+ COMPLETED: "COMPLETED";
987
+ FAILED: "FAILED";
988
+ }>>;
989
+ }, z.core.$strip>>;
990
+ channelId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
991
+ createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
992
+ updatedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
993
+ occurredAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
994
+ }, z.core.$strip>>;
995
+ }, z.core.$strip>;
996
+ type ListCommunicationsResponse = z.infer<typeof ListCommunicationsResponseSchema>;
997
+ /**
998
+ * Participant reference for the Actions API (`from`/`to` entries).
999
+ *
1000
+ * Either `participantId` or `address` must be supplied; `channel` is always required.
1001
+ * When both are provided, Conversation Orchestrator uses `participantId` and
1002
+ * `channel` disambiguates which of the participant's addresses to use.
1003
+ */
1004
+ declare const ActionParticipantRefSchema: z.ZodObject<{
1005
+ participantId: z.ZodOptional<z.ZodString>;
1006
+ address: z.ZodOptional<z.ZodString>;
1007
+ channel: z.ZodEnum<{
1008
+ VOICE: "VOICE";
1009
+ SMS: "SMS";
1010
+ RCS: "RCS";
1011
+ EMAIL: "EMAIL";
1012
+ WHATSAPP: "WHATSAPP";
1013
+ CHAT: "CHAT";
1014
+ API: "API";
1015
+ SYSTEM: "SYSTEM";
1016
+ }>;
1017
+ }, z.core.$strip>;
1018
+ type ActionParticipantRef = z.infer<typeof ActionParticipantRefSchema>;
1019
+ /**
1020
+ * Plain-text content for a SEND_MESSAGE action.
1021
+ */
1022
+ declare const ActionTextContentSchema: z.ZodObject<{
1023
+ text: z.ZodString;
1024
+ }, z.core.$strip>;
1025
+ type ActionTextContent = z.infer<typeof ActionTextContentSchema>;
1026
+ /**
1027
+ * Channel-specific settings forwarded to the downstream backend.
1028
+ *
1029
+ * Open pass-through: any field not explicitly modeled here (e.g.
759
1030
  * `messagingServiceSid`, `statusCallback`, `Attributes`) can be set by callers and
760
1031
  * will be forwarded as-is.
761
1032
  */
@@ -905,6 +1176,7 @@ declare const ConversationSessionSchema: z.ZodObject<{
905
1176
  type: z.ZodDefault<z.ZodLiteral<"end">>;
906
1177
  handoffData: z.ZodString;
907
1178
  }, z.core.$strip>>;
1179
+ cachedMemory: z.ZodOptional<z.ZodCustom<TACMemoryResponse, TACMemoryResponse>>;
908
1180
  }, z.core.$strip>;
909
1181
  type ConversationSession = z.infer<typeof ConversationSessionSchema>;
910
1182
  /**
@@ -1174,6 +1446,41 @@ interface InitiateConversationResult {
1174
1446
  interface InitiateVoiceConversationResult {
1175
1447
  callSid: string;
1176
1448
  }
1449
+ /**
1450
+ * Webhook payload structure from Twilio Conversation Orchestrator.
1451
+ * This structure is used by all channels (messaging and voice) for webhook events.
1452
+ */
1453
+ interface ConversationWebhookPayload {
1454
+ eventType: string;
1455
+ timestamp?: string;
1456
+ data?: {
1457
+ id?: string;
1458
+ conversationId?: string;
1459
+ accountId?: string;
1460
+ serviceId?: string;
1461
+ status?: string;
1462
+ participantType?: string;
1463
+ profileId?: string;
1464
+ channelId?: string;
1465
+ author?: {
1466
+ address?: string;
1467
+ channel?: string;
1468
+ participantId?: string;
1469
+ };
1470
+ content?: {
1471
+ type?: string;
1472
+ text?: string;
1473
+ };
1474
+ recipients?: Array<{
1475
+ address?: string;
1476
+ channel?: string;
1477
+ participantId?: string;
1478
+ deliveryStatus?: string;
1479
+ }>;
1480
+ [key: string]: unknown;
1481
+ };
1482
+ [key: string]: unknown;
1483
+ }
1177
1484
 
1178
1485
  /**
1179
1486
  * ConversationRelay API Types
@@ -1328,29 +1635,158 @@ declare const WebSocketMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
1328
1635
  }, z.core.$strip>]>;
1329
1636
  type WebSocketMessage = z.infer<typeof WebSocketMessageSchema>;
1330
1637
  /**
1331
- * Text Token Message to send back via WebSocket
1332
- * @see https://www.twilio.com/docs/voice/conversationrelay/websocket-messages#text-tokens-message
1638
+ * Text Token Message to send back via WebSocket
1639
+ * @see https://www.twilio.com/docs/voice/conversationrelay/websocket-messages#text-tokens-message
1640
+ */
1641
+ declare const TextTokenMessageSchema: z.ZodObject<{
1642
+ type: z.ZodLiteral<"text">;
1643
+ token: z.ZodString;
1644
+ last: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1645
+ }, z.core.$strip>;
1646
+ type TextTokenMessage = z.infer<typeof TextTokenMessageSchema>;
1647
+ /**
1648
+ * Extended ConversationRelay configuration that includes child elements.
1649
+ * Includes all ConversationRelayAttributes fields plus support for languages array.
1650
+ *
1651
+ * Note: The type is defined as an explicit interface and the schema is annotated
1652
+ * with z.ZodType<ConversationRelayConfig> to prevent TypeScript's type inference
1653
+ * from collapsing to `any` when resolving complex Zod generics with many optional
1654
+ * fields (especially under exactOptionalPropertyTypes).
1655
+ */
1656
+ interface ConversationRelayConfig extends ConversationRelayAttributes {
1657
+ /** Optional language configurations as child <Language> elements */
1658
+ languages?: LanguageAttributes[] | undefined;
1659
+ }
1660
+ declare const ConversationRelayConfigSchema: z.ZodType<ConversationRelayConfig>;
1661
+ /**
1662
+ * Twilio uses the same four-value enum for several attributes that control
1663
+ * what caller input (DTMF, speech, both, neither) triggers a given behavior.
1664
+ */
1665
+ declare const InterruptModeSchema: z.ZodEnum<{
1666
+ any: "any";
1667
+ speech: "speech";
1668
+ none: "none";
1669
+ dtmf: "dtmf";
1670
+ }>;
1671
+ type InterruptMode = z.infer<typeof InterruptModeSchema>;
1672
+ /**
1673
+ * A single `<Language>` child for multi-language ConversationRelay setups.
1674
+ *
1675
+ * Maps to the `<Language>` element documented at
1676
+ * https://www.twilio.com/docs/voice/twiml/connect/conversationrelay#language-element
1677
+ *
1678
+ * Distinct from {@link LanguageAttributes} (the Twilio-SDK-shaped type used by
1679
+ * `connectConversationRelay`): this is the customization-facing model used in
1680
+ * {@link TwiMLOptions}, mirroring the Python SDK's `LanguageConfig`.
1681
+ */
1682
+ declare const LanguageConfigSchema: z.ZodObject<{
1683
+ code: z.ZodString;
1684
+ voice: z.ZodOptional<z.ZodString>;
1685
+ ttsProvider: z.ZodOptional<z.ZodString>;
1686
+ transcriptionProvider: z.ZodOptional<z.ZodString>;
1687
+ speechModel: z.ZodOptional<z.ZodString>;
1688
+ }, z.core.$strip>;
1689
+ type LanguageConfig = z.infer<typeof LanguageConfigSchema>;
1690
+ /**
1691
+ * Options for the TwiML inside `<ConversationRelay>` (plus the
1692
+ * `<Connect action>` URL).
1693
+ *
1694
+ * Fields map to the attributes documented at
1695
+ * https://www.twilio.com/docs/voice/twiml/connect/conversationrelay . All
1696
+ * fields are optional. `VoiceChannel.handleIncomingCall` merges these values
1697
+ * over TAC defaults per-field — only fields explicitly present on the object
1698
+ * override lower layers (see `VoiceChannel`'s overlay logic).
1699
+ *
1700
+ * This is the customization-facing counterpart to {@link ConversationRelayConfig}
1701
+ * (which is the Twilio-SDK-shaped emit model and carries the required `url`).
1702
+ * Mirrors the Python SDK's `TwiMLOptions`.
1703
+ */
1704
+ declare const TwiMLOptionsSchema: z.ZodObject<{
1705
+ customParameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1706
+ welcomeGreeting: z.ZodOptional<z.ZodString>;
1707
+ welcomeGreetingInterruptible: z.ZodOptional<z.ZodEnum<{
1708
+ any: "any";
1709
+ speech: "speech";
1710
+ none: "none";
1711
+ dtmf: "dtmf";
1712
+ }>>;
1713
+ actionUrl: z.ZodOptional<z.ZodString>;
1714
+ conversationConfiguration: z.ZodOptional<z.ZodString>;
1715
+ websocketUrl: z.ZodOptional<z.ZodString>;
1716
+ language: z.ZodOptional<z.ZodString>;
1717
+ ttsLanguage: z.ZodOptional<z.ZodString>;
1718
+ transcriptionLanguage: z.ZodOptional<z.ZodString>;
1719
+ voice: z.ZodOptional<z.ZodString>;
1720
+ ttsProvider: z.ZodOptional<z.ZodString>;
1721
+ transcriptionProvider: z.ZodOptional<z.ZodString>;
1722
+ speechModel: z.ZodOptional<z.ZodString>;
1723
+ elevenlabsTextNormalization: z.ZodOptional<z.ZodEnum<{
1724
+ on: "on";
1725
+ auto: "auto";
1726
+ off: "off";
1727
+ }>>;
1728
+ eotThreshold: z.ZodOptional<z.ZodNumber>;
1729
+ partialPrompts: z.ZodOptional<z.ZodBoolean>;
1730
+ deepgramSmartFormat: z.ZodOptional<z.ZodBoolean>;
1731
+ speechTimeout: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<"auto">]>>;
1732
+ interruptible: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
1733
+ any: "any";
1734
+ speech: "speech";
1735
+ none: "none";
1736
+ dtmf: "dtmf";
1737
+ }>, z.ZodBoolean]>>;
1738
+ interruptSensitivity: z.ZodOptional<z.ZodEnum<{
1739
+ low: "low";
1740
+ medium: "medium";
1741
+ high: "high";
1742
+ }>>;
1743
+ reportInputDuringAgentSpeech: z.ZodOptional<z.ZodEnum<{
1744
+ any: "any";
1745
+ speech: "speech";
1746
+ none: "none";
1747
+ dtmf: "dtmf";
1748
+ }>>;
1749
+ ignoreBackchannel: z.ZodOptional<z.ZodBoolean>;
1750
+ preemptible: z.ZodOptional<z.ZodBoolean>;
1751
+ dtmfDetection: z.ZodOptional<z.ZodBoolean>;
1752
+ hints: z.ZodOptional<z.ZodString>;
1753
+ events: z.ZodOptional<z.ZodString>;
1754
+ debug: z.ZodOptional<z.ZodString>;
1755
+ intelligenceService: z.ZodOptional<z.ZodString>;
1756
+ languages: z.ZodOptional<z.ZodArray<z.ZodObject<{
1757
+ code: z.ZodString;
1758
+ voice: z.ZodOptional<z.ZodString>;
1759
+ ttsProvider: z.ZodOptional<z.ZodString>;
1760
+ transcriptionProvider: z.ZodOptional<z.ZodString>;
1761
+ speechModel: z.ZodOptional<z.ZodString>;
1762
+ }, z.core.$strip>>>;
1763
+ extra: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodBoolean, z.ZodNumber]>>>;
1764
+ }, z.core.$strict>;
1765
+ type TwiMLOptions = z.infer<typeof TwiMLOptionsSchema>;
1766
+ /**
1767
+ * Framework-neutral view of the Twilio TwiML webhook form.
1768
+ *
1769
+ * Populated by `TACServer` from the incoming Twilio webhook, then passed to a
1770
+ * customizer registered via `VoiceChannel.onInboundCallTwiml(...)` so the
1771
+ * application can produce per-call {@link TwiMLOptions} overrides without
1772
+ * depending on Fastify types. Mirrors the Python SDK's `TwiMLRequest`.
1333
1773
  */
1334
- declare const TextTokenMessageSchema: z.ZodObject<{
1335
- type: z.ZodLiteral<"text">;
1336
- token: z.ZodString;
1337
- last: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1774
+ declare const TwiMLRequestSchema: z.ZodObject<{
1775
+ from: z.ZodOptional<z.ZodString>;
1776
+ to: z.ZodOptional<z.ZodString>;
1777
+ callSid: z.ZodOptional<z.ZodString>;
1778
+ callerCountry: z.ZodOptional<z.ZodString>;
1779
+ callerState: z.ZodOptional<z.ZodString>;
1780
+ callerCity: z.ZodOptional<z.ZodString>;
1781
+ direction: z.ZodOptional<z.ZodString>;
1782
+ extra: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
1338
1783
  }, z.core.$strip>;
1339
- type TextTokenMessage = z.infer<typeof TextTokenMessageSchema>;
1784
+ type TwiMLRequest = z.infer<typeof TwiMLRequestSchema>;
1340
1785
  /**
1341
- * Extended ConversationRelay configuration that includes child elements.
1342
- * Includes all ConversationRelayAttributes fields plus support for languages array.
1343
- *
1344
- * Note: The type is defined as an explicit interface and the schema is annotated
1345
- * with z.ZodType<ConversationRelayConfig> to prevent TypeScript's type inference
1346
- * from collapsing to `any` when resolving complex Zod generics with many optional
1347
- * fields (especially under exactOptionalPropertyTypes).
1786
+ * Build a {@link TwiMLRequest} from a raw Twilio form dict, bucketing unknown
1787
+ * keys into `extra`. Mirrors the Python SDK's `TwiMLRequest.from_form`.
1348
1788
  */
1349
- interface ConversationRelayConfig extends ConversationRelayAttributes {
1350
- /** Optional language configurations as child <Language> elements */
1351
- languages?: LanguageAttributes[] | undefined;
1352
- }
1353
- declare const ConversationRelayConfigSchema: z.ZodType<ConversationRelayConfig>;
1789
+ declare function twiMLRequestFromForm(form: Record<string, string>): TwiMLRequest;
1354
1790
  /**
1355
1791
  * ConversationRelay callback payload from Twilio webhook
1356
1792
  *
@@ -1396,11 +1832,32 @@ type ConversationRelayCallbackPayload = z.infer<typeof ConversationRelayCallback
1396
1832
  *
1397
1833
  * The caller identity is always TAC's configured `config.phoneNumber`.
1398
1834
  * Multi-number deployments should run one TAC instance per line.
1835
+ *
1836
+ * TwiML for the outbound call is built by merging per-field, highest precedence
1837
+ * first:
1838
+ * 1. This call's `twimlOptions` (per-call overrides)
1839
+ * 2. `VoiceChannelConfig.defaultTwimlOptions` (channel-wide defaults)
1840
+ * 3. TAC defaults (welcome greeting, conversationConfiguration, actionUrl
1841
+ * resolved via Studio handoff if configured, else derived from
1842
+ * `TACConfig.voicePublicDomain` + `voiceActionPath`)
1843
+ *
1844
+ * Fields you don't set at a layer fall through to lower layers — so
1845
+ * `twimlOptions: { voice: 'es-MX-Neural2-A' }` on this call overrides only
1846
+ * `voice`; `language`, `interruptible`, etc. from the channel config still apply.
1399
1847
  */
1400
1848
  interface InitiateVoiceConversationOptions {
1401
1849
  to: string;
1402
- conversationRelayConfig: ConversationRelayConfig;
1403
- actionUrl?: string | undefined;
1850
+ /**
1851
+ * Public WebSocket URL for ConversationRelay (e.g. 'wss://your-domain.ngrok.app/ws').
1852
+ * Optional — defaults to the URL derived from `TACConfig.voicePublicDomain` +
1853
+ * `voiceWebsocketPath`. Pass it here only to override the URL for a specific call.
1854
+ */
1855
+ websocketUrl?: string | undefined;
1856
+ /**
1857
+ * Per-call overrides for the TwiML inside `<ConversationRelay>`. Merged over
1858
+ * `VoiceChannelConfig.defaultTwimlOptions` and TAC defaults.
1859
+ */
1860
+ twimlOptions?: TwiMLOptions | undefined;
1404
1861
  }
1405
1862
  declare const InitiateVoiceConversationOptionsSchema: z.ZodType<InitiateVoiceConversationOptions>;
1406
1863
 
@@ -1588,238 +2045,53 @@ declare const OperatorResultEventSchema: z.ZodObject<{
1588
2045
  id: z.ZodString;
1589
2046
  operator: z.ZodObject<{
1590
2047
  id: z.ZodString;
1591
- name: z.ZodOptional<z.ZodString>;
1592
- }, z.core.$strip>;
1593
- outputFormat: z.ZodString;
1594
- result: z.ZodUnknown;
1595
- dateCreated: z.ZodString;
1596
- referenceIds: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
1597
- executionDetails: z.ZodOptional<z.ZodObject<{
1598
- participants: z.ZodOptional<z.ZodArray<z.ZodObject<{
1599
- type: z.ZodString;
1600
- profileId: z.ZodOptional<z.ZodString>;
1601
- mediaParticipantId: z.ZodOptional<z.ZodString>;
1602
- }, z.core.$strip>>>;
1603
- }, z.core.$strip>>;
1604
- }, z.core.$strip>>;
1605
- }, z.core.$strip>;
1606
- type OperatorResultEvent = z.infer<typeof OperatorResultEventSchema>;
1607
- /**
1608
- * Result of processing an operator result event
1609
- */
1610
- declare const OperatorProcessingResultSchema: z.ZodObject<{
1611
- success: z.ZodBoolean;
1612
- eventType: z.ZodOptional<z.ZodString>;
1613
- skipped: z.ZodDefault<z.ZodBoolean>;
1614
- skipReason: z.ZodOptional<z.ZodString>;
1615
- error: z.ZodOptional<z.ZodString>;
1616
- createdCount: z.ZodDefault<z.ZodNumber>;
1617
- }, z.core.$strip>;
1618
- type OperatorProcessingResult = z.infer<typeof OperatorProcessingResultSchema>;
1619
- /**
1620
- * Conversation Intelligence configuration for TAC
1621
- */
1622
- declare const ConversationIntelligenceConfigSchema: z.ZodObject<{
1623
- configurationId: z.ZodString;
1624
- observationOperatorSid: z.ZodOptional<z.ZodString>;
1625
- summaryOperatorSid: z.ZodOptional<z.ZodString>;
1626
- }, z.core.$strip>;
1627
- type ConversationIntelligenceConfig = z.infer<typeof ConversationIntelligenceConfigSchema>;
1628
- /**
1629
- * Summary item for batch creation
1630
- */
1631
- declare const ConversationSummaryItemSchema: z.ZodObject<{
1632
- content: z.ZodString;
1633
- conversationId: z.ZodString;
1634
- occurredAt: z.ZodString;
1635
- source: z.ZodOptional<z.ZodString>;
1636
- }, z.core.$strip>;
1637
- type ConversationSummaryItem = z.infer<typeof ConversationSummaryItemSchema>;
1638
-
1639
- /**
1640
- * Channel type for communications
1641
- */
1642
- declare const TACChannelTypeSchema: z.ZodEnum<{
1643
- VOICE: "VOICE";
1644
- SMS: "SMS";
1645
- RCS: "RCS";
1646
- EMAIL: "EMAIL";
1647
- WHATSAPP: "WHATSAPP";
1648
- CHAT: "CHAT";
1649
- API: "API";
1650
- SYSTEM: "SYSTEM";
1651
- }>;
1652
- type TACChannelType = z.infer<typeof TACChannelTypeSchema>;
1653
- /**
1654
- * Delivery status for communications
1655
- */
1656
- declare const TACDeliveryStatusSchema: z.ZodEnum<{
1657
- INITIATED: "INITIATED";
1658
- IN_PROGRESS: "IN_PROGRESS";
1659
- DELIVERED: "DELIVERED";
1660
- COMPLETED: "COMPLETED";
1661
- FAILED: "FAILED";
1662
- }>;
1663
- type TACDeliveryStatus = z.infer<typeof TACDeliveryStatusSchema>;
1664
- /**
1665
- * Participant type
1666
- */
1667
- declare const TACParticipantTypeSchema: z.ZodEnum<{
1668
- HUMAN_AGENT: "HUMAN_AGENT";
1669
- CUSTOMER: "CUSTOMER";
1670
- AI_AGENT: "AI_AGENT";
1671
- AGENT: "AGENT";
1672
- }>;
1673
- type TACParticipantType = z.infer<typeof TACParticipantTypeSchema>;
1674
- /**
1675
- * Unified author model with all fields from both Memory and Conversation Orchestrator APIs.
1676
- *
1677
- * Fields not available from a particular API will be undefined.
1678
- */
1679
- declare const TACCommunicationAuthorSchema: z.ZodObject<{
1680
- address: z.ZodString;
1681
- channel: z.ZodEnum<{
1682
- VOICE: "VOICE";
1683
- SMS: "SMS";
1684
- RCS: "RCS";
1685
- EMAIL: "EMAIL";
1686
- WHATSAPP: "WHATSAPP";
1687
- CHAT: "CHAT";
1688
- API: "API";
1689
- SYSTEM: "SYSTEM";
1690
- }>;
1691
- participantId: z.ZodOptional<z.ZodString>;
1692
- deliveryStatus: z.ZodOptional<z.ZodEnum<{
1693
- INITIATED: "INITIATED";
1694
- IN_PROGRESS: "IN_PROGRESS";
1695
- DELIVERED: "DELIVERED";
1696
- COMPLETED: "COMPLETED";
1697
- FAILED: "FAILED";
1698
- }>>;
1699
- id: z.ZodOptional<z.ZodString>;
1700
- name: z.ZodOptional<z.ZodString>;
1701
- type: z.ZodOptional<z.ZodEnum<{
1702
- HUMAN_AGENT: "HUMAN_AGENT";
1703
- CUSTOMER: "CUSTOMER";
1704
- AI_AGENT: "AI_AGENT";
1705
- AGENT: "AGENT";
1706
- }>>;
1707
- profileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1708
- }, z.core.$strip>;
1709
- type TACCommunicationAuthor = z.infer<typeof TACCommunicationAuthorSchema>;
1710
- /**
1711
- * Unified content model with all fields from both Memory and Conversation Orchestrator APIs.
1712
- */
1713
- declare const TACCommunicationContentSchema: z.ZodObject<{
1714
- type: z.ZodOptional<z.ZodEnum<{
1715
- TEXT: "TEXT";
1716
- TRANSCRIPTION: "TRANSCRIPTION";
1717
- }>>;
1718
- text: z.ZodOptional<z.ZodString>;
1719
- transcription: z.ZodOptional<z.ZodObject<{
1720
- channel: z.ZodOptional<z.ZodNumber>;
1721
- confidence: z.ZodOptional<z.ZodNumber>;
1722
- engine: z.ZodOptional<z.ZodString>;
1723
- words: z.ZodOptional<z.ZodArray<z.ZodObject<{
1724
- text: z.ZodString;
1725
- startTime: z.ZodOptional<z.ZodString>;
1726
- endTime: z.ZodOptional<z.ZodString>;
1727
- }, z.core.$strip>>>;
1728
- }, z.core.$strip>>;
1729
- }, z.core.$strip>;
1730
- type TACCommunicationContent = z.infer<typeof TACCommunicationContentSchema>;
1731
- /**
1732
- * Unified communication model with all fields from both Memory and Conversation Orchestrator APIs.
1733
- *
1734
- * Provides complete access to all communication fields regardless of the source.
1735
- * Fields not available from a particular API will be undefined.
1736
- */
1737
- declare const TACCommunicationSchema: z.ZodObject<{
1738
- id: z.ZodString;
1739
- author: z.ZodObject<{
1740
- address: z.ZodString;
1741
- channel: z.ZodEnum<{
1742
- VOICE: "VOICE";
1743
- SMS: "SMS";
1744
- RCS: "RCS";
1745
- EMAIL: "EMAIL";
1746
- WHATSAPP: "WHATSAPP";
1747
- CHAT: "CHAT";
1748
- API: "API";
1749
- SYSTEM: "SYSTEM";
1750
- }>;
1751
- participantId: z.ZodOptional<z.ZodString>;
1752
- deliveryStatus: z.ZodOptional<z.ZodEnum<{
1753
- INITIATED: "INITIATED";
1754
- IN_PROGRESS: "IN_PROGRESS";
1755
- DELIVERED: "DELIVERED";
1756
- COMPLETED: "COMPLETED";
1757
- FAILED: "FAILED";
1758
- }>>;
1759
- id: z.ZodOptional<z.ZodString>;
1760
- name: z.ZodOptional<z.ZodString>;
1761
- type: z.ZodOptional<z.ZodEnum<{
1762
- HUMAN_AGENT: "HUMAN_AGENT";
1763
- CUSTOMER: "CUSTOMER";
1764
- AI_AGENT: "AI_AGENT";
1765
- AGENT: "AGENT";
1766
- }>>;
1767
- profileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1768
- }, z.core.$strip>;
1769
- content: z.ZodObject<{
1770
- type: z.ZodOptional<z.ZodEnum<{
1771
- TEXT: "TEXT";
1772
- TRANSCRIPTION: "TRANSCRIPTION";
1773
- }>>;
1774
- text: z.ZodOptional<z.ZodString>;
1775
- transcription: z.ZodOptional<z.ZodObject<{
1776
- channel: z.ZodOptional<z.ZodNumber>;
1777
- confidence: z.ZodOptional<z.ZodNumber>;
1778
- engine: z.ZodOptional<z.ZodString>;
1779
- words: z.ZodOptional<z.ZodArray<z.ZodObject<{
1780
- text: z.ZodString;
1781
- startTime: z.ZodOptional<z.ZodString>;
1782
- endTime: z.ZodOptional<z.ZodString>;
1783
- }, z.core.$strip>>>;
1784
- }, z.core.$strip>>;
1785
- }, z.core.$strip>;
1786
- recipients: z.ZodDefault<z.ZodArray<z.ZodObject<{
1787
- address: z.ZodString;
1788
- channel: z.ZodEnum<{
1789
- VOICE: "VOICE";
1790
- SMS: "SMS";
1791
- RCS: "RCS";
1792
- EMAIL: "EMAIL";
1793
- WHATSAPP: "WHATSAPP";
1794
- CHAT: "CHAT";
1795
- API: "API";
1796
- SYSTEM: "SYSTEM";
1797
- }>;
1798
- participantId: z.ZodOptional<z.ZodString>;
1799
- deliveryStatus: z.ZodOptional<z.ZodEnum<{
1800
- INITIATED: "INITIATED";
1801
- IN_PROGRESS: "IN_PROGRESS";
1802
- DELIVERED: "DELIVERED";
1803
- COMPLETED: "COMPLETED";
1804
- FAILED: "FAILED";
1805
- }>>;
1806
- id: z.ZodOptional<z.ZodString>;
1807
- name: z.ZodOptional<z.ZodString>;
1808
- type: z.ZodOptional<z.ZodEnum<{
1809
- HUMAN_AGENT: "HUMAN_AGENT";
1810
- CUSTOMER: "CUSTOMER";
1811
- AI_AGENT: "AI_AGENT";
1812
- AGENT: "AGENT";
1813
- }>>;
1814
- profileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1815
- }, z.core.$strip>>>;
1816
- channelId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1817
- createdAt: z.ZodOptional<z.ZodString>;
1818
- updatedAt: z.ZodOptional<z.ZodString>;
1819
- conversationId: z.ZodOptional<z.ZodString>;
1820
- accountId: z.ZodOptional<z.ZodString>;
2048
+ name: z.ZodOptional<z.ZodString>;
2049
+ }, z.core.$strip>;
2050
+ outputFormat: z.ZodString;
2051
+ result: z.ZodUnknown;
2052
+ dateCreated: z.ZodString;
2053
+ referenceIds: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
2054
+ executionDetails: z.ZodOptional<z.ZodObject<{
2055
+ participants: z.ZodOptional<z.ZodArray<z.ZodObject<{
2056
+ type: z.ZodString;
2057
+ profileId: z.ZodOptional<z.ZodString>;
2058
+ mediaParticipantId: z.ZodOptional<z.ZodString>;
2059
+ }, z.core.$strip>>>;
2060
+ }, z.core.$strip>>;
2061
+ }, z.core.$strip>>;
1821
2062
  }, z.core.$strip>;
1822
- type TACCommunication = z.infer<typeof TACCommunicationSchema>;
2063
+ type OperatorResultEvent = z.infer<typeof OperatorResultEventSchema>;
2064
+ /**
2065
+ * Result of processing an operator result event
2066
+ */
2067
+ declare const OperatorProcessingResultSchema: z.ZodObject<{
2068
+ success: z.ZodBoolean;
2069
+ eventType: z.ZodOptional<z.ZodString>;
2070
+ skipped: z.ZodDefault<z.ZodBoolean>;
2071
+ skipReason: z.ZodOptional<z.ZodString>;
2072
+ error: z.ZodOptional<z.ZodString>;
2073
+ createdCount: z.ZodDefault<z.ZodNumber>;
2074
+ }, z.core.$strip>;
2075
+ type OperatorProcessingResult = z.infer<typeof OperatorProcessingResultSchema>;
2076
+ /**
2077
+ * Conversation Intelligence configuration for TAC
2078
+ */
2079
+ declare const ConversationIntelligenceConfigSchema: z.ZodObject<{
2080
+ configurationId: z.ZodString;
2081
+ observationOperatorSid: z.ZodOptional<z.ZodString>;
2082
+ summaryOperatorSid: z.ZodOptional<z.ZodString>;
2083
+ }, z.core.$strip>;
2084
+ type ConversationIntelligenceConfig = z.infer<typeof ConversationIntelligenceConfigSchema>;
2085
+ /**
2086
+ * Summary item for batch creation
2087
+ */
2088
+ declare const ConversationSummaryItemSchema: z.ZodObject<{
2089
+ content: z.ZodString;
2090
+ conversationId: z.ZodString;
2091
+ occurredAt: z.ZodString;
2092
+ source: z.ZodOptional<z.ZodString>;
2093
+ }, z.core.$strip>;
2094
+ type ConversationSummaryItem = z.infer<typeof ConversationSummaryItemSchema>;
1823
2095
 
1824
2096
  /**
1825
2097
  * Knowledge base status enum
@@ -1874,82 +2146,6 @@ declare const KnowledgeSearchResponseSchema: z.ZodObject<{
1874
2146
  }, z.core.$strip>;
1875
2147
  type KnowledgeSearchResponse = z.infer<typeof KnowledgeSearchResponseSchema>;
1876
2148
 
1877
- /**
1878
- * Unified response wrapper for TAC.retrieveMemory().
1879
- *
1880
- * Provides a consistent interface for accessing memory data regardless of whether
1881
- * Memory API is configured or falling back to Conversation Orchestrator Communications API.
1882
- *
1883
- * Memory configured:
1884
- * - observations, summaries, communications all populated
1885
- * - communications include Memory-specific fields (author id, name, type, profileId)
1886
- *
1887
- * Conversation Orchestrator fallback:
1888
- * - observations and summaries are empty arrays
1889
- * - communications include Conversation Orchestrator-specific fields (conversationId, accountId, etc.)
1890
- */
1891
- declare class TACMemoryResponse {
1892
- private readonly _data;
1893
- private readonly _communications;
1894
- /**
1895
- * Initialize wrapper with either Memory or Conversation Orchestrator data.
1896
- *
1897
- * @param data - Either MemoryRetrievalResponse (Memory) or Communication[] (Conversation Orchestrator)
1898
- */
1899
- constructor(data: MemoryRetrievalResponse | Communication[]);
1900
- /**
1901
- * Get observation memories.
1902
- *
1903
- * @returns List of observations if Memory is configured, empty array for Conversation Orchestrator fallback
1904
- */
1905
- get observations(): ObservationInfo[];
1906
- /**
1907
- * Get summary memories.
1908
- *
1909
- * @returns List of summaries if Memory is configured, empty array for Conversation Orchestrator fallback
1910
- */
1911
- get summaries(): SummaryInfo[];
1912
- /**
1913
- * Get communications in unified format with all available fields.
1914
- *
1915
- * Communications are converted to a common format during initialization that includes
1916
- * all fields from both Memory and Conversation Orchestrator APIs. Fields not available from a particular
1917
- * API will be undefined.
1918
- *
1919
- * @returns List of unified communications with all available fields
1920
- */
1921
- get communications(): TACCommunication[];
1922
- /**
1923
- * Check if Memory API is configured and providing full features.
1924
- *
1925
- * @returns true if Memory is configured (observations/summaries available),
1926
- * false if using Conversation Orchestrator fallback (only communications available)
1927
- */
1928
- get hasMemoryFeatures(): boolean;
1929
- /**
1930
- * Access raw underlying data for advanced use cases.
1931
- *
1932
- * Use this when you need access to all fields from the original API responses,
1933
- * not just the unified common fields.
1934
- *
1935
- * @returns Either MemoryRetrievalResponse or Communication[] depending on configuration
1936
- */
1937
- get rawData(): MemoryRetrievalResponse | Communication[];
1938
- /**
1939
- * Build formatted prompt sections from available memory data.
1940
- *
1941
- * Generates markdown-formatted sections for observations, summaries, and communications
1942
- * that can be injected into LLM prompts. Each section includes a heading and formatted content.
1943
- * Sections with no data are omitted from the result.
1944
- *
1945
- * @returns Array of formatted prompt sections, empty array if no memory data available
1946
- */
1947
- buildMemoryPrompts(): string[];
1948
- private buildObservationsPrompt;
1949
- private buildSummariesPrompt;
1950
- private buildCommunicationsPrompt;
1951
- }
1952
-
1953
2149
  /**
1954
2150
  * TAC Configuration class with Python-like static factory methods
1955
2151
  *
@@ -1976,6 +2172,10 @@ declare class TACConfig {
1976
2172
  readonly memoryConfig: TACConfigData['memoryConfig'];
1977
2173
  readonly conversationConfigurationId?: string;
1978
2174
  readonly voicePublicDomain?: string;
2175
+ /** Path the voice WebSocket is served at (default '/ws'). */
2176
+ readonly voiceWebsocketPath: string;
2177
+ /** Path the ConversationRelay action callback is served at (default '/conversation-relay-callback'). */
2178
+ readonly voiceActionPath: string;
1979
2179
  readonly cintelConfigurationId?: string;
1980
2180
  readonly cintelObservationOperatorSid?: string;
1981
2181
  readonly cintelSummaryOperatorSid?: string;
@@ -2003,7 +2203,9 @@ declare class TACConfig {
2003
2203
  * Optional environment variables:
2004
2204
  * - TWILIO_WHATSAPP_NUMBER: WhatsApp number for WhatsApp channel (e.g., 'whatsapp:+1234567890')
2005
2205
  * - TWILIO_CONVERSATION_CONFIGURATION_ID: Conversation Orchestrator configuration ID (enables orchestrated mode)
2006
- * - TWILIO_VOICE_PUBLIC_DOMAIN: Public domain for voice WebSocket connections (domain only, without protocol/port/path, e.g., 'abc123.ngrok.app')
2206
+ * - TWILIO_VOICE_PUBLIC_DOMAIN: Public domain for voice routes (required for voice; domain only, without protocol/port/path, e.g., 'abc123.ngrok.app')
2207
+ * - TWILIO_VOICE_WEBSOCKET_PATH: Path for the voice WebSocket (default: /ws)
2208
+ * - TWILIO_VOICE_ACTION_PATH: Path for the ConversationRelay action callback (default: /conversation-relay-callback)
2007
2209
  * - TWILIO_REGION: Twilio region subdomain for API routing (e.g. transforms base URLs to `https://{product}.{region}.twilio.com`)
2008
2210
  * - TWILIO_STUDIO_HANDOFF_FLOW_SID: Studio Flow SID used by createStudioHandoffTool for human handoff
2009
2211
  * - TWILIO_RCS_SENDER_ID: RCS Sender ID for the RCS channel
@@ -2337,15 +2539,27 @@ interface BaseChannelOptions {
2337
2539
  * Memory retrieval mode for this channel. Default is "never".
2338
2540
  *
2339
2541
  * - "never": Memory is not automatically retrieved. Use the memory TAC tool or manually call `tac.retrieveMemory()` in callbacks for conditional retrieval.
2340
- * - "always": Memory is automatically retrieved for every inbound message and available in `onMessageReady` callback.
2542
+ * - "always": Memory is automatically retrieved (using the message as query) for every inbound message and available in `onMessageReady` callback.
2543
+ * - "once": Memory is retrieved once at conversation start with an empty query and cached on the session. Subsequent messages reuse the cache until the conversation becomes INACTIVE.
2341
2544
  */
2342
2545
  memoryMode?: MemoryMode;
2546
+ /**
2547
+ * Maximum number of idempotency tokens to track for webhook deduplication.
2548
+ * Default is 10000. Must be a positive integer.
2549
+ */
2550
+ dedupCapacity?: number;
2343
2551
  }
2344
2552
  /**
2345
2553
  * Abstract base class for all channel implementations
2346
2554
  *
2347
- * Provides common functionality for conversation lifecycle management,
2348
- * session tracking, and shared utilities across different channel types.
2555
+ * Provides common functionality for:
2556
+ * - Conversation lifecycle management and session tracking
2557
+ * - Webhook deduplication using Twilio idempotency tokens
2558
+ * - Event filtering to prevent cross-channel fanout
2559
+ * - Memory retrieval integration
2560
+ * - Error handling and logging
2561
+ *
2562
+ * Subclasses must implement channel-specific webhook processing and message sending.
2349
2563
  */
2350
2564
  declare abstract class BaseChannel {
2351
2565
  protected readonly tac: TAC;
@@ -2355,6 +2569,8 @@ declare abstract class BaseChannel {
2355
2569
  protected readonly activeConversations: Map<ConversationId, ConversationSession>;
2356
2570
  protected readonly callbacks: BaseChannelEvents;
2357
2571
  protected readonly memoryMode: MemoryMode;
2572
+ private readonly processedWebhookTokens;
2573
+ private readonly maxTrackedTokens;
2358
2574
  constructor(tac: TAC, options?: BaseChannelOptions);
2359
2575
  /**
2360
2576
  * Get the channel type (implemented by subclasses)
@@ -2396,26 +2612,88 @@ declare abstract class BaseChannel {
2396
2612
  * Handle errors with proper context
2397
2613
  */
2398
2614
  protected handleError(error: Error, context?: Record<string, unknown>): void;
2615
+ /**
2616
+ * Check if a webhook has already been processed using Twilio's idempotency token.
2617
+ * Uses a sliding window with fixed capacity to track tokens (FIFO eviction).
2618
+ *
2619
+ * This is intentionally a single synchronous check-and-record to prevent race conditions
2620
+ * where a duplicate arrives while the first request is still awaiting async work.
2621
+ */
2622
+ protected isDuplicateWebhook(idempotencyToken: string): boolean;
2623
+ /**
2624
+ * Remove an idempotency token from the deduplication cache.
2625
+ * Used when webhook processing fails and retries should not be blocked.
2626
+ */
2627
+ protected removeWebhookToken(idempotencyToken: string): void;
2628
+ /**
2629
+ * Self-filtering: check if webhook event belongs to this channel.
2630
+ *
2631
+ * - COMMUNICATION_CREATED: require author.channel matches this channel type
2632
+ * - CONVERSATION_UPDATED: only process if conversation is tracked locally
2633
+ * - Other events: pass through
2634
+ */
2635
+ protected isEventForThisChannel(webhookData: ConversationWebhookPayload): boolean;
2399
2636
  /**
2400
2637
  * Validate webhook payload (override in subclasses for specific validation)
2401
2638
  */
2402
2639
  protected validateWebhookPayload(payload: unknown): boolean;
2403
2640
  /**
2404
- * Extract conversation ID from webhook payload (implemented by subclasses)
2641
+ * Preprocess webhook before handling event-specific logic.
2642
+ * Handles deduplication, validation, filtering, and data extraction.
2643
+ *
2644
+ * @param payload - Raw webhook payload from Twilio
2645
+ * @param idempotencyToken - Optional idempotency token for deduplication
2646
+ * @returns Preprocessed webhook data, or null if webhook should be skipped
2647
+ */
2648
+ protected preprocessWebhook(payload: unknown, idempotencyToken: string | undefined): {
2649
+ webhookData: ConversationWebhookPayload;
2650
+ eventType: string;
2651
+ conversationId: string | undefined;
2652
+ } | null;
2653
+ /**
2654
+ * Extract conversation ID from webhook payload with type validation.
2655
+ *
2656
+ * Extracts conversationId from webhookData.data?.conversationId || webhookData.data?.id,
2657
+ * validates the value is a non-empty string, and ensures it passes isConversationId check.
2658
+ *
2659
+ * This prevents invalid IDs from causing downstream issues like incorrect Map key
2660
+ * matching in CONVERSATION_UPDATED self-filtering or propagating malformed IDs.
2405
2661
  */
2406
- protected abstract extractConversationId(payload: unknown): ConversationId | null;
2662
+ protected extractConversationId(payload: unknown): ConversationId | null;
2407
2663
  /**
2408
- * Extract profile ID from webhook payload (implemented by subclasses)
2664
+ * Extract profile ID from webhook payload with type validation.
2665
+ *
2666
+ * Extracts profileId from webhookData.data?.profileId,
2667
+ * validates the value is a non-empty string, and ensures it passes isProfileId check.
2668
+ *
2669
+ * This prevents invalid IDs from propagating downstream and ensures consistent
2670
+ * validation across all channel types.
2409
2671
  */
2410
- protected abstract extractProfileId(payload: unknown): ProfileId | null;
2672
+ protected extractProfileId(payload: unknown): ProfileId | null;
2411
2673
  /**
2412
- * Retrieve memory only when memoryMode === 'always'.
2674
+ * Retrieve memory according to the channel's memoryMode.
2413
2675
  *
2414
2676
  * This method handles the common logic for memory retrieval across all channels,
2415
- * including error handling and debug logging. If memoryMode is 'never',
2416
- * automatic memory retrieval is skipped.
2677
+ * including error handling and debug logging.
2678
+ *
2679
+ * Modes:
2680
+ * - "always": Fetch with the provided query on every message.
2681
+ * - "once": Fetch once with an empty query and cache the result on the
2682
+ * session. Subsequent calls reuse the cache until it is invalidated on the
2683
+ * INACTIVE transition.
2684
+ * - "never": Skip retrieval.
2685
+ *
2686
+ * Memory retrieval failures are logged and swallowed so message processing
2687
+ * continues without memory context.
2417
2688
  */
2418
2689
  protected retrieveMemoryIfEnabled(session: ConversationSession, query?: string): Promise<TACMemoryResponse | undefined>;
2690
+ /**
2691
+ * Invalidate cached memory for "once" mode when a conversation becomes
2692
+ * INACTIVE. Conversation Orchestrator updates memory on the INACTIVE
2693
+ * transition, so the next message re-fetches fresh memory. No-op for other
2694
+ * memory modes.
2695
+ */
2696
+ protected invalidateCachedMemory(conversationId: ConversationId): void;
2419
2697
  /**
2420
2698
  * Cleanup resources when shutting down
2421
2699
  */
@@ -2576,49 +2854,10 @@ declare class TAC {
2576
2854
  }
2577
2855
 
2578
2856
  /**
2579
- * Messaging webhook event types from Twilio Conversations Service
2580
- * Supports the v2 format for SMS and Chat channels
2581
- */
2582
- interface MessagingWebhookPayload {
2583
- eventType: string;
2584
- timestamp?: string;
2585
- data?: {
2586
- id?: string;
2587
- conversationId?: string;
2588
- accountId?: string;
2589
- serviceId?: string;
2590
- status?: string;
2591
- participantType?: string;
2592
- profileId?: string;
2593
- channelId?: string;
2594
- author?: {
2595
- address?: string;
2596
- channel?: string;
2597
- participantId?: string;
2598
- };
2599
- content?: {
2600
- type?: string;
2601
- text?: string;
2602
- };
2603
- recipients?: Array<{
2604
- address?: string;
2605
- channel?: string;
2606
- participantId?: string;
2607
- deliveryStatus?: string;
2608
- }>;
2609
- [key: string]: unknown;
2610
- };
2611
- [key: string]: unknown;
2612
- }
2613
- /**
2614
- * Messaging channel configuration options
2857
+ * Messaging channel configuration options.
2858
+ * Alias for BaseChannelOptions that can be extended by specific channel implementations.
2615
2859
  */
2616
- interface MessagingChannelConfig {
2617
- /** Maximum number of idempotency tokens to track for deduplication (default: 10,000) */
2618
- dedupCapacity?: number;
2619
- /** Memory retrieval mode. Default is "never". Set to "always" to retrieve memory for every message. */
2620
- memoryMode?: MemoryMode;
2621
- }
2860
+ type MessagingChannelConfig = BaseChannelOptions;
2622
2861
  /**
2623
2862
  * Messaging channel event callbacks extending base callbacks
2624
2863
  */
@@ -2651,21 +2890,12 @@ interface MessagingChannelEvents extends BaseChannelEvents {
2651
2890
  declare abstract class MessagingChannel extends BaseChannel {
2652
2891
  protected readonly conversationClient: ConversationClient;
2653
2892
  protected readonly messagingCallbacks: MessagingChannelEvents;
2654
- private readonly processedTokens;
2655
- private readonly maxTrackedTokens;
2656
2893
  /**
2657
2894
  * Controls whether reconciliation promotes an UNKNOWN customer-side
2658
2895
  * participant to CUSTOMER. Subclasses override to opt out (e.g. chat).
2659
2896
  */
2660
2897
  protected reconcileCustomerType: boolean;
2661
2898
  constructor(tac: TAC, config?: MessagingChannelConfig);
2662
- /**
2663
- * Check if a webhook has already been processed, and if not, record the token immediately.
2664
- * This is intentionally a single synchronous check-and-record to prevent race conditions
2665
- * where a duplicate arrives while the first request is still awaiting async work.
2666
- * Uses a sliding window with FIFO eviction at capacity.
2667
- */
2668
- private isDuplicateWebhook;
2669
2899
  /**
2670
2900
  * Fast-path check: is the author address this channel's default agent address?
2671
2901
  * (e.g., config.phoneNumber for SMS, agentAddress for Chat)
@@ -2691,12 +2921,7 @@ declare abstract class MessagingChannel extends BaseChannel {
2691
2921
  */
2692
2922
  on(event: string, callback: (...args: any[]) => void): void;
2693
2923
  /**
2694
- * Check if this webhook event belongs to this channel.
2695
- * Returns false if the event is clearly for a different channel type.
2696
- */
2697
- private isEventForThisChannel;
2698
- /**
2699
- * Process messaging channel webhook from Twilio Conversations Service
2924
+ * Process messaging channel webhook from Conversation Orchestrator
2700
2925
  */
2701
2926
  processWebhook(payload: unknown, idempotencyToken?: string): Promise<void>;
2702
2927
  /**
@@ -2711,14 +2936,6 @@ declare abstract class MessagingChannel extends BaseChannel {
2711
2936
  * Handle conversation updated event
2712
2937
  */
2713
2938
  private handleConversationUpdated;
2714
- /**
2715
- * Extract conversation ID from webhook payload
2716
- */
2717
- protected extractConversationId(payload: unknown): ConversationId | null;
2718
- /**
2719
- * Extract profile ID from webhook payload
2720
- */
2721
- protected extractProfileId(payload: unknown): ProfileId | null;
2722
2939
  /**
2723
2940
  * Validate messaging channel webhook payload structure
2724
2941
  */
@@ -2960,6 +3177,34 @@ declare class ChatChannel extends MessagingChannel {
2960
3177
  initiateOutboundConversation(options: InitiateChatConversationOptions): Promise<InitiateConversationResult>;
2961
3178
  }
2962
3179
 
3180
+ /**
3181
+ * Configuration for the Voice channel.
3182
+ *
3183
+ * `defaultTwimlOptions` is one of several TwiML layers that merge per-field;
3184
+ * see `handleIncomingCall` (inbound) and `initiateOutboundConversation`
3185
+ * (outbound) for the full precedence order.
3186
+ */
3187
+ interface VoiceChannelConfig extends BaseChannelOptions {
3188
+ /**
3189
+ * Static `TwiMLOptions` applied to every call (inbound and outbound).
3190
+ * Controls the TwiML inside `<ConversationRelay>` — voice, language,
3191
+ * transcription provider, welcomeGreeting, `<Language>` children, etc. Use
3192
+ * this when the same ConversationRelay configuration is correct for every call.
3193
+ *
3194
+ * Per-call inbound customization is registered via
3195
+ * `VoiceChannel.onInboundCallTwiml(...)` (not on this config).
3196
+ *
3197
+ * Note: `customParameters` and `languages` replace wholesale when a
3198
+ * higher-priority layer sets them.
3199
+ */
3200
+ defaultTwimlOptions?: TwiMLOptions;
3201
+ }
3202
+ /**
3203
+ * Callback that produces per-call overrides for the TwiML inside
3204
+ * `<ConversationRelay>` on inbound calls. Receives a framework-neutral
3205
+ * {@link TwiMLRequest} and returns {@link TwiMLOptions}.
3206
+ */
3207
+ type InboundCallTwimlHandler = (req: TwiMLRequest) => Promise<TwiMLOptions>;
2963
3208
  /**
2964
3209
  * Voice channel event callbacks extending base callbacks
2965
3210
  */
@@ -3008,7 +3253,45 @@ declare class VoiceChannel extends BaseChannel {
3008
3253
  private readonly callSidToConversationId;
3009
3254
  private readonly MAX_INITIALIZATION_RETRIES;
3010
3255
  private twilioClient;
3011
- constructor(tac: TAC, options?: BaseChannelOptions);
3256
+ private readonly voiceConfig;
3257
+ private onInboundCallTwimlHandler;
3258
+ constructor(tac: TAC, options?: VoiceChannelConfig);
3259
+ /**
3260
+ * Register a callback that produces per-call overrides for the TwiML inside
3261
+ * `<ConversationRelay>` on inbound calls.
3262
+ *
3263
+ * The callback receives a framework-neutral {@link TwiMLRequest} (parsed from
3264
+ * the Twilio webhook form) and returns {@link TwiMLOptions}. Fields the
3265
+ * callback explicitly sets override `defaultTwimlOptions` and TAC defaults;
3266
+ * unset fields fall through.
3267
+ *
3268
+ * @example
3269
+ * ```typescript
3270
+ * voiceChannel.onInboundCallTwiml(async req => {
3271
+ * if (req.callerCountry === 'MX') {
3272
+ * return { language: 'es-MX', welcomeGreeting: '¡Hola!' };
3273
+ * }
3274
+ * return {};
3275
+ * });
3276
+ * ```
3277
+ *
3278
+ * Outbound calls don't use this — pass per-call TwiML via
3279
+ * `InitiateVoiceConversationOptions.twimlOptions` directly.
3280
+ */
3281
+ onInboundCallTwiml(callback: InboundCallTwimlHandler): void;
3282
+ /**
3283
+ * Resolve the public WebSocket URL from `TACConfig.voicePublicDomain` +
3284
+ * `TACConfig.voiceWebsocketPath`. Throws if `voicePublicDomain` isn't set.
3285
+ */
3286
+ private resolveWebsocketUrl;
3287
+ /**
3288
+ * Resolve the default `<Connect action=...>` cleanup URL.
3289
+ *
3290
+ * Returns undefined if `voicePublicDomain` isn't set; that's fine because
3291
+ * actionUrl has higher-priority layers (customizer, twimlOptions, Studio
3292
+ * handoff) above this fallback.
3293
+ */
3294
+ private resolveDefaultActionUrl;
3012
3295
  private getTwilioClient;
3013
3296
  get channelType(): ChannelType;
3014
3297
  /**
@@ -3016,10 +3299,22 @@ declare class VoiceChannel extends BaseChannel {
3016
3299
  */
3017
3300
  on(event: string, callback: (...args: any[]) => void): void;
3018
3301
  /**
3019
- * Process webhook - Voice channel doesn't use traditional webhooks,
3020
- * but this method is required by the base class
3302
+ * Process conversation webhooks for cleanup.
3303
+ *
3304
+ * Voice channel processes CONVERSATION_UPDATED events:
3305
+ * - CLOSED status: Clean up local session state
3306
+ *
3307
+ * Note: Conversation tracking uses instance-local memory. In multi-instance
3308
+ * deployments, webhooks may route to a different instance, preventing cleanup.
3309
+ *
3310
+ * @param payload - Raw webhook event data from Twilio
3311
+ * @param idempotencyToken - Optional Twilio idempotency token from request headers
3312
+ */
3313
+ processWebhook(payload: unknown, idempotencyToken?: string): Promise<void>;
3314
+ /**
3315
+ * Handle conversation updated event
3021
3316
  */
3022
- processWebhook(_payload: unknown): Promise<void>;
3317
+ private handleConversationUpdated;
3023
3318
  /**
3024
3319
  * Get active WebSocket connection for a conversation
3025
3320
  */
@@ -3037,7 +3332,9 @@ declare class VoiceChannel extends BaseChannel {
3037
3332
  */
3038
3333
  private handleInterruptMessage;
3039
3334
  /**
3040
- * Handle WebSocket disconnection
3335
+ * Handle WebSocket disconnection. In orchestrated mode the conversation stays
3336
+ * tracked until the CLOSED webhook (so a follow-up call can reuse it); in
3337
+ * voice-only mode there is no such webhook, so it ends here.
3041
3338
  */
3042
3339
  private handleWebSocketDisconnect;
3043
3340
  /**
@@ -3059,18 +3356,89 @@ declare class VoiceChannel extends BaseChannel {
3059
3356
  signal?: AbortSignal;
3060
3357
  }): Promise<string>;
3061
3358
  /**
3062
- * Handle incoming voice call - generate TwiML to connect to ConversationRelay
3359
+ * Generate the TwiML response for an incoming voice call.
3360
+ *
3361
+ * ConversationRelay automatically handles conversation creation and
3362
+ * participant management via the `conversationConfiguration` parameter.
3363
+ *
3364
+ * The WebSocket URL and default session-cleanup action URL are derived from
3365
+ * `TACConfig.voicePublicDomain` + `TACConfig.voiceWebsocketPath` /
3366
+ * `voiceActionPath`.
3367
+ *
3368
+ * TwiML fields are merged per-field, highest precedence first:
3369
+ * 1. Output of the customizer registered via
3370
+ * `VoiceChannel.onInboundCallTwiml(...)` if configured and `twimlRequest`
3371
+ * is given. (Application-owned.)
3372
+ * 2. `VoiceChannelConfig.defaultTwimlOptions` — per-channel defaults.
3373
+ * 3. `hostTwimlOptions` — per-call transport facts supplied by the host (the
3374
+ * code owning the route), e.g. a per-call `websocketUrl` with an affinity
3375
+ * token.
3376
+ * 4. TAC defaults: a fixed default welcomeGreeting, `conversationConfiguration`
3377
+ * from `TACConfig`, `actionUrl` resolved via Studio handoff (when
3378
+ * `studioHandoffFlowSid` is configured), else derived from
3379
+ * `TACConfig.voicePublicDomain` + `voiceActionPath`, and the `websocketUrl`
3380
+ * derived from `TACConfig.voicePublicDomain` + `voiceWebsocketPath`.
3381
+ *
3382
+ * Fields not set at a layer fall through to lower layers. Arrays (`languages`)
3383
+ * and nested objects (`customParameters`) replace wholesale when set at a
3384
+ * higher-priority layer. `websocketUrl` falls back to the `TACConfig`-derived
3385
+ * URL if unset at every layer.
3386
+ *
3387
+ * @param twimlRequest - Parsed Twilio webhook fields. Passed to the customizer
3388
+ * if one is configured on the channel.
3389
+ * @param options - Additional per-call inputs.
3390
+ * @param options.hostTwimlOptions - Per-call TwiML supplied by a custom
3391
+ * in-process host (e.g. an affinity-routed deployment injecting a per-call
3392
+ * `websocketUrl`), layered below `defaultTwimlOptions` and the application
3393
+ * customizer but above the TAC defaults.
3394
+ * @returns TwiML XML string for call connection.
3395
+ */
3396
+ handleIncomingCall(twimlRequest?: TwiMLRequest, options?: {
3397
+ hostTwimlOptions?: TwiMLOptions;
3398
+ }): Promise<string>;
3399
+ /**
3400
+ * Layer TwiML options, lowest precedence first: TAC defaults → `host`
3401
+ * (calling host's per-call values) → channel `defaultTwimlOptions` → `perCall`
3402
+ * (application customizer output for inbound, or
3403
+ * `InitiateVoiceConversationOptions.twimlOptions` for outbound).
3404
+ */
3405
+ private buildTwimlOptions;
3406
+ /**
3407
+ * Apply fields explicitly present on `source` onto `target`.
3408
+ *
3409
+ * Nested objects (`customParameters`), arrays (`languages`), and dicts
3410
+ * (`extra`) replace wholesale — there's no per-key merging.
3063
3411
  *
3064
- * ConversationRelay will create the conversation automatically. The conversation
3065
- * will be initialized on the first prompt using the callSid.
3412
+ * `actionUrl` is skipped here on purpose it's resolved once via
3413
+ * `resolveActionUrl` looking at every layer at once, and that resolved value
3414
+ * is written into `target` before this overlay runs. Letting it through here
3415
+ * would let a higher-priority layer that didn't set actionUrl silently clobber
3416
+ * a lower layer that did.
3066
3417
  *
3067
- * @param options - Options for handling the incoming call
3068
- * @returns TwiML XML string with ConversationRelay configuration
3418
+ * "Explicitly present" is detected via key presence (`key in source`), which
3419
+ * mirrors Python's `model_fields_set`: a key set to `undefined` is still
3420
+ * "present" and overrides lower layers, while an absent key falls through.
3069
3421
  */
3070
- handleIncomingCall(options: {
3071
- actionUrl?: string;
3072
- conversationRelayConfig: ConversationRelayConfig;
3073
- }): string;
3422
+ private overlayFields;
3423
+ /**
3424
+ * Resolve the TwiML `<Connect action=...>` URL.
3425
+ *
3426
+ * Precedence (highest to lowest):
3427
+ * 1. application customizer
3428
+ * 2. channel `defaultTwimlOptions`
3429
+ * 3. `host` (calling host's per-call options)
3430
+ * 4. Studio handoff (when `studioHandoffFlowSid` is configured)
3431
+ * 5. Channel default — derived from `TACConfig.voicePublicDomain` +
3432
+ * `TACConfig.voiceActionPath`.
3433
+ *
3434
+ * User-expressed intent (Studio handoff is configured explicitly on
3435
+ * `TACConfig`) beats the SDK's generated cleanup default.
3436
+ *
3437
+ * Explicit `actionUrl: undefined` on a layer (key present, value undefined)
3438
+ * suppresses `<Connect action=...>` entirely — all lower layers are skipped.
3439
+ * `actionUrl` left absent (key not present) falls through to the next layer.
3440
+ */
3441
+ private resolveActionUrl;
3074
3442
  /**
3075
3443
  * Initiate an outbound voice conversation
3076
3444
  *
@@ -3079,14 +3447,21 @@ declare class VoiceChannel extends BaseChannel {
3079
3447
  * conversation during passive hydration. The session is initialized lazily
3080
3448
  * on the first prompt when the conversation is discovered by callSid.
3081
3449
  *
3082
- * `conversationRelayConfig.url` must be the publicly accessible WebSocket
3083
- * endpoint (e.g., `wss://your-domain.ngrok.app/ws`). Unlike inbound calls
3084
- * where TACServer sets this automatically, outbound calls require it
3085
- * explicitly since there is no incoming HTTP request to derive the host from.
3450
+ * TwiML fields are merged per-field, highest precedence first:
3451
+ * 1. `options.twimlOptions` per-call overrides
3452
+ * 2. `VoiceChannelConfig.defaultTwimlOptions` channel-wide defaults
3453
+ * 3. TAC defaults: welcome greeting, `conversationConfiguration` from
3454
+ * `TACConfig`, and `actionUrl` from Studio handoff (if configured), else
3455
+ * derived from `TACConfig.voicePublicDomain` + `voiceActionPath`.
3456
+ *
3457
+ * The WebSocket URL is derived from `TACConfig.voicePublicDomain` +
3458
+ * `TACConfig.voiceWebsocketPath`, unless overridden per-call via
3459
+ * `options.websocketUrl`.
3086
3460
  */
3087
3461
  initiateOutboundConversation(options: InitiateVoiceConversationOptions): Promise<InitiateVoiceConversationResult>;
3088
3462
  /**
3089
- * Handle ConversationRelay callback from Twilio
3463
+ * Handle ConversationRelay callback from Twilio. Cleans up on call completion
3464
+ * in voice-only mode; in orchestrated mode the CO webhook owns cleanup.
3090
3465
  *
3091
3466
  * @param payload - Callback payload from Twilio
3092
3467
  * @returns Response with status, content, and content type
@@ -3123,6 +3498,29 @@ declare class VoiceChannel extends BaseChannel {
3123
3498
  * @returns true if an active task exists
3124
3499
  */
3125
3500
  hasActiveStreamTask(conversationId: ConversationId): boolean;
3501
+ /**
3502
+ * Field names on {@link TwiMLOptions} that map directly to `<ConversationRelay>`
3503
+ * attributes (camelCase, emitted as-is). Excludes the fields handled specially
3504
+ * by {@link generateTwiml}: websocketUrl (resolved through the layered merge and
3505
+ * emitted as the `url` attribute), actionUrl, languages, customParameters, extra.
3506
+ */
3507
+ private static readonly RELAY_ATTR_FIELDS;
3508
+ /**
3509
+ * Generate TwiML XML for ConversationRelay from a merged {@link TwiMLOptions}.
3510
+ *
3511
+ * This is the low-level emitter used by `handleIncomingCall` and
3512
+ * `initiateOutboundConversation` after layering. It mirrors the Python SDK's
3513
+ * `generate_twiml`. The WebSocket URL may be passed as `websocketUrl` or via
3514
+ * `options.websocketUrl` (the explicit argument wins when both are given), so a
3515
+ * channel-less caller can pass everything in one object.
3516
+ *
3517
+ * @param websocketUrl - Public WebSocket URL (e.g. 'wss://example.ngrok.app/ws').
3518
+ * Optional if `options.websocketUrl` is set.
3519
+ * @param options - Merged TwiMLOptions to emit.
3520
+ * @returns TwiML XML string ready to return to Twilio.
3521
+ * @throws {Error} if no WebSocket URL is provided via either source.
3522
+ */
3523
+ private generateTwiml;
3126
3524
  /**
3127
3525
  * Generate TwiML to connect a call to ConversationRelay.
3128
3526
  * Validates configuration with Zod before generating TwiML.
@@ -3141,14 +3539,6 @@ declare class VoiceChannel extends BaseChannel {
3141
3539
  * Keeps null, false, 0, and empty strings as they are valid values.
3142
3540
  */
3143
3541
  private filterUnsetValues;
3144
- /**
3145
- * Extract conversation ID - Not applicable for Voice channel
3146
- */
3147
- protected extractConversationId(_payload: unknown): ConversationId | null;
3148
- /**
3149
- * Extract profile ID - Not applicable for Voice channel
3150
- */
3151
- protected extractProfileId(_payload: unknown): ProfileId | null;
3152
3542
  /**
3153
3543
  * Cleanup channel state on shutdown
3154
3544
  *
@@ -3601,17 +3991,23 @@ interface TACServerConfig {
3601
3991
  host?: string;
3602
3992
  /** Port to bind the server to (default: 8000) */
3603
3993
  port?: number;
3604
- /** Custom webhook paths */
3994
+ /**
3995
+ * Custom server-only webhook paths. The voice WebSocket and ConversationRelay
3996
+ * action callback paths live on `TACConfig` (`voiceWebsocketPath` /
3997
+ * `voiceActionPath`) because they're consumed by the voice channel regardless
3998
+ * of which web framework is used; this server reads them from there.
3999
+ */
3605
4000
  webhookPaths?: {
4001
+ /**
4002
+ * @deprecated Use `conversation` instead. This field will be removed in a future version.
4003
+ * If both `messaging` and `conversation` are set, `conversation` takes precedence.
4004
+ */
3606
4005
  messaging?: string;
4006
+ conversation?: string;
3607
4007
  twiml?: string;
3608
- ws?: string;
3609
- conversationRelayCallback?: string;
3610
4008
  /** Path for Conversation Intelligence webhook (optional - only registered if provided) */
3611
4009
  cintel?: string;
3612
4010
  };
3613
- /** ConversationRelay configuration (welcomeGreeting, transcription, TTS, interaction settings, etc.) */
3614
- conversationRelayConfig?: Partial<Omit<ConversationRelayConfig, 'url'>>;
3615
4011
  /** Voice channel instance (alternative to registering on TAC) */
3616
4012
  voiceChannel?: VoiceChannel;
3617
4013
  /** Messaging channel instances — webhooks are fanned out to all (alternative to registering on TAC) */
@@ -3644,10 +4040,12 @@ declare class TACServer {
3644
4040
  readonly fastify: FastifyInstance;
3645
4041
  private readonly tac;
3646
4042
  private readonly config;
3647
- /** All enabled messaging channels — webhooks are fanned out to each one */
4043
+ /** All enabled messaging channels */
3648
4044
  private readonly messagingChannels;
3649
4045
  /** Voice channel instance */
3650
4046
  private readonly voiceChannel;
4047
+ /** All channels that need webhook processing (voice + messaging) */
4048
+ private readonly webhookChannels;
3651
4049
  constructor(tac: TAC, config?: TACServerConfig);
3652
4050
  private getForwardedProto;
3653
4051
  private getForwardedHost;
@@ -3682,4 +4080,4 @@ declare class TACServer {
3682
4080
  stop(): Promise<void>;
3683
4081
  }
3684
4082
 
3685
- export { type ActionChannelSettings, ActionChannelSettingsSchema, type ActionParticipantRef, ActionParticipantRefSchema, type ActionResponse, ActionResponseSchema, type ActionTextContent, ActionTextContentSchema, type AdapterOptions, type AuthorInfo, AuthorInfoSchema, BaseChannel, type BaseChannelEvents, BaseClient, type BuiltInToolName, BuiltInTools, 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 CreateConversationSummariesResponse, CreateConversationSummariesResponseSchema, type CreateObservationResponse, CreateObservationResponseSchema, type CustomParameters, CustomParametersSchema, EMPTY_MEMORY_RESPONSE, EnvironmentVariables, type ExecutionDetails, ExecutionDetailsSchema, type HandoffPayload, HandoffPayloadSchema, type HandoffResult, type InitiateChatConversationOptions, type InitiateConversationResult, type InitiateMessagingConversationOptions, InitiateMessagingConversationOptionsSchema, type InitiateVoiceConversationOptions, InitiateVoiceConversationOptionsSchema, type InitiateVoiceConversationResult, type IntelligenceConfiguration, IntelligenceConfigurationSchema, type InterruptCallback, type InterruptMessage, InterruptMessageSchema, type JSONSchema, JSONSchemaSchema, type KnowledgeBase, KnowledgeBaseSchema, type KnowledgeBaseStatus, KnowledgeBaseStatusSchema, type KnowledgeChunkResult, KnowledgeChunkResultSchema, KnowledgeClient, type KnowledgeSearchResponse, KnowledgeSearchResponseSchema, type LanguageAttributes, LanguageAttributesSchema, 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 MessagingWebhookPayload, 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, 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 TwilioMemoryConfig, TwilioMemoryConfigSchema, VoiceChannel, type VoiceChannelEvents, type WebSocketMessage, WebSocketMessageSchema, WhatsAppChannel, type _SDKDriftGuards, buildHandoffPayload, createKnowledgeSearchTool, createKnowledgeSearchToolAsync, createKnowledgeTools, createLogger, createMemoryRetrievalTool, createMemoryTools, createMessagingTools, createSendMessageTool, createStudioHandoffTool, defineTool, isConversationId, isParticipantId, isProfileId, maskAddress, maskEmail, maskPhone, postStudioHandoff, scrubObject, scrubPii, studioExecutionsUrl, studioVoiceHandoffUrl };
4083
+ export { type ActionChannelSettings, ActionChannelSettingsSchema, type ActionParticipantRef, ActionParticipantRefSchema, type ActionResponse, ActionResponseSchema, type ActionTextContent, ActionTextContentSchema, type AdapterOptions, type AuthorInfo, AuthorInfoSchema, BaseChannel, type BaseChannelEvents, type BaseChannelOptions, BaseClient, type BuiltInToolName, BuiltInTools, 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 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 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, 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, VoiceChannel, type VoiceChannelConfig, type VoiceChannelEvents, type WebSocketMessage, WebSocketMessageSchema, WhatsAppChannel, type _SDKDriftGuards, buildHandoffPayload, createKnowledgeSearchTool, createKnowledgeSearchToolAsync, createKnowledgeTools, createLogger, createMemoryRetrievalTool, createMemoryTools, createMessagingTools, createSendMessageTool, createStudioHandoffTool, defineTool, isConversationId, isParticipantId, isProfileId, maskAddress, maskEmail, maskPhone, postStudioHandoff, scrubObject, scrubPii, studioExecutionsUrl, studioVoiceHandoffUrl, twiMLRequestFromForm };