55from dotenv import load_dotenv
66from examples .utils import create_user , open_browser
77from getstream import Stream
8+ from getstream .models import StartClosedCaptionsResponse
89from getstream .plugins .sts .openai_realtime import OpenAIRealtime
10+ from dataclasses import asdict
11+ import json
912
1013
1114logging .basicConfig (
@@ -54,33 +57,6 @@ async def main():
5457 voice = "alloy" ,
5558 )
5659
57- @sts_bot .on ("connected" )
58- async def _on_connected ():
59- print ("✅ CONNECTED EVENT RECEIVED" )
60- logging .info ("✅ Bot connected successfully" )
61-
62- @sts_bot .on ("disconnected" )
63- async def _on_disconnected ():
64- print ("❌ DISCONNECTED EVENT RECEIVED" )
65- logging .info ("❌ Bot disconnected" )
66-
67- @sts_bot .on ("error" )
68- async def _on_error (error ):
69- print (f"💥 ERROR EVENT RECEIVED: { error } " )
70- logging .error ("💥 Bot error: %s" , error )
71-
72- @sts_bot .on ("session.created" )
73- @sts_bot .on ("session.updated" )
74- @sts_bot .on ("conversation.item.created" )
75- @sts_bot .on ("response.created" )
76- @sts_bot .on ("response.done" )
77- @sts_bot .on ("call.session_participant_joined" )
78- @sts_bot .on ("call.session_participant_left" )
79- async def _on_openai_event (event ):
80- print (f"🔔 Event received: { event .type } " )
81- print (f" Event data: { event } " )
82- logging .info ("🔔 Event: %s" , event .type )
83-
8460 try :
8561 logging .info ("Connecting to OpenAI Realtime..." )
8662
@@ -89,20 +65,66 @@ async def _on_openai_event(event):
8965 logging .error ("❌ OPENAI_API_KEY not found in environment" )
9066 return
9167
92- await sts_bot .connect (call , agent_user_id = bot_user_id )
93- logging .info ("🎧 Listening for responses... (Press Ctrl+C to stop)" )
94- logging .info ("💡 Try speaking in the browser to generate audio events!" )
95-
96- while sts_bot .is_connected :
97- await asyncio .sleep (1 )
68+ async with await sts_bot .connect (call , agent_user_id = bot_user_id ) as connection :
69+ tools = [
70+ {
71+ "type" : "function" ,
72+ "name" : "start_closed_captions" ,
73+ "description" : "start closed captions for the call" ,
74+ "parameters" : {
75+ "type" : "object" ,
76+ "properties" : {},
77+ "required" : [],
78+ },
79+ }
80+ ]
81+
82+ await sts_bot .update_session (
83+ turn_detection = {
84+ "type" : "semantic_vad" ,
85+ "eagerness" : "low" ,
86+ "create_response" : True ,
87+ "interrupt_response" : True ,
88+ },
89+ tools = tools ,
90+ )
91+
92+ logging .info ("🎧 Listening for responses... (Press Ctrl+C to stop)" )
93+ logging .info ("💡 Try speaking in the browser – ask it something like 'start closed captions' to trigger the function call." )
94+
95+ async def start_closed_captions () -> StartClosedCaptionsResponse :
96+ """Helper that starts closed captions for the call."""
97+ return call .start_closed_captions ().data
98+
99+ async for event in connection :
100+ logging .info ("🔔 Event received: %s" , event .type )
101+
102+ if (
103+ event .type == "response.done"
104+ and event .response .output is not None
105+ and len (event .response .output ) > 0
106+ and event .response .output [0 ].type == "function_call"
107+ ):
108+ tool_call_id = event .response .output [0 ].call_id
109+
110+ if event .response .output [0 ].name == "start_closed_captions" :
111+ logging .info ("🛠 Assistant requested start_closed_captions()" )
112+
113+ result = await start_closed_captions ()
114+
115+ # Send the tool result back to the assistant
116+ await sts_bot .send_function_call_output (tool_call_id , result .to_json ())
117+
118+ logging .info ("🛠 Replied to tool call with result: %s" , result )
119+
120+
98121
99122 except KeyboardInterrupt : # noqa: WPS420
100123 logging .info ("\n ⏹️ Stopping OpenAI Realtime Speech to Speech bot…" )
101124 except Exception as e : # noqa: BLE001
102125 logging .exception ("❌ Error: %s" , e )
103126 finally :
104127 logging .info ("Cleaning up..." )
105- await sts_bot .close ()
106128 client .delete_users ([user_id , bot_user_id ])
107129 logging .info ("Cleanup complete" )
108130
0 commit comments