001/* 002 * SPDX-License-Identifier: Apache-2.0 003 * 004 * Copyright 2025-2026 The Enola <https://enola.dev> Authors 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package dev.enola.audio.voice.twilio.relay; 019 020import com.fasterxml.jackson.annotation.JsonSubTypes; 021import com.fasterxml.jackson.annotation.JsonTypeInfo; 022 023import dev.enola.audio.voice.twilio.relay.ConversationRelayResponse.DTMF; 024import dev.enola.audio.voice.twilio.relay.ConversationRelayResponse.End; 025import dev.enola.audio.voice.twilio.relay.ConversationRelayResponse.Language; 026import dev.enola.audio.voice.twilio.relay.ConversationRelayResponse.Play; 027import dev.enola.audio.voice.twilio.relay.ConversationRelayResponse.Text; 028 029import java.net.URI; 030import java.util.Locale; 031 032/** 033 * Twilio's <a 034 * href="https://www.twilio.com/docs/voice/conversationrelay/websocket-messages">ConversationRelay 035 * response messages</a> JSON format. 036 */ 037@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") 038@JsonSubTypes({ 039 @JsonSubTypes.Type(value = Text.class, name = "text"), 040 @JsonSubTypes.Type(value = Play.class, name = "play"), 041 @JsonSubTypes.Type(value = DTMF.class, name = "sendDigits"), 042 @JsonSubTypes.Type(value = Language.class, name = "language"), 043 @JsonSubTypes.Type(value = End.class, name = "end") 044}) 045public sealed interface ConversationRelayResponse { 046 047 record Text(String token, Locale lang, boolean last, boolean interruptible, boolean preemptible) 048 implements ConversationRelayResponse {} 049 050 record Play(URI source, boolean interruptible, boolean preemptible) 051 implements ConversationRelayResponse {} 052 053 record DTMF(String digits) implements ConversationRelayResponse {} 054 055 record Language(Locale ttsLanguage, Locale transcriptionLanguage) 056 implements ConversationRelayResponse {} 057 058 // TODO Should handoffData be Map<String, Object> instead of String? 059 record End(String handoffData) implements ConversationRelayResponse {} 060}