Spaces:
Building
Building
Update state_orchestrator.py
Browse files- state_orchestrator.py +79 -47
state_orchestrator.py
CHANGED
@@ -81,6 +81,7 @@ class StateOrchestrator:
|
|
81 |
|
82 |
# Conversation events
|
83 |
self.event_bus.subscribe(EventType.CONVERSATION_STARTED, self._handle_conversation_started)
|
|
|
84 |
|
85 |
# Session lifecycle
|
86 |
self.event_bus.subscribe(EventType.SESSION_STARTED, self._handle_session_started)
|
@@ -116,23 +117,65 @@ class StateOrchestrator:
|
|
116 |
|
117 |
log_info(f"🎤 Conversation started | session_id={session_id}")
|
118 |
|
119 |
-
#
|
120 |
-
|
|
|
|
|
|
|
121 |
await self.transition_to(session_id, ConversationState.PREPARING_WELCOME)
|
122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
else:
|
124 |
-
# Welcome yoksa direkt
|
125 |
await self.transition_to(session_id, ConversationState.LISTENING)
|
126 |
|
127 |
# Start STT
|
128 |
-
await self.
|
129 |
Event(
|
130 |
-
type=EventType.
|
131 |
-
data={
|
132 |
session_id=session_id
|
133 |
)
|
134 |
)
|
135 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
async def _handle_session_started(self, event: Event):
|
137 |
"""Handle session start"""
|
138 |
session_id = event.session_id
|
@@ -152,62 +195,51 @@ class StateOrchestrator:
|
|
152 |
|
153 |
self.sessions[session_id] = context
|
154 |
|
155 |
-
#
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
|
162 |
-
#
|
163 |
await self.event_bus.publish(Event(
|
164 |
-
type=EventType.
|
165 |
session_id=session_id,
|
166 |
-
data={
|
167 |
-
"text": session_data.get("welcome_text", ""),
|
168 |
-
"is_welcome": True
|
169 |
-
}
|
170 |
))
|
171 |
-
else:
|
172 |
-
# No welcome, go straight to listening
|
173 |
-
await self.transition_to(session_id, ConversationState.LISTENING)
|
174 |
|
175 |
-
# Request STT start
|
176 |
await self.event_bus.publish(Event(
|
177 |
-
type=EventType.
|
178 |
session_id=session_id,
|
179 |
-
data={}
|
180 |
))
|
181 |
|
182 |
-
|
183 |
-
"""Handle session end"""
|
184 |
-
session_id = event.session_id
|
185 |
-
|
186 |
-
log_info(f"🏁 Session ended", session_id=session_id)
|
187 |
-
|
188 |
-
# Get context for cleanup
|
189 |
-
context = self.sessions.get(session_id)
|
190 |
-
|
191 |
-
# Transition to ended
|
192 |
-
await self.transition_to(session_id, ConversationState.ENDED)
|
193 |
-
|
194 |
-
# Stop all components
|
195 |
-
await self.event_bus.publish(Event(
|
196 |
-
type=EventType.STT_STOPPED,
|
197 |
-
session_id=session_id,
|
198 |
-
data={"reason": "session_ended"}
|
199 |
-
))
|
200 |
-
|
201 |
-
# Cleanup session context
|
202 |
-
if context:
|
203 |
await context.cleanup()
|
204 |
-
|
205 |
# Remove session
|
206 |
self.sessions.pop(session_id, None)
|
207 |
|
208 |
# Clear event bus session data
|
209 |
self.event_bus.clear_session_data(session_id)
|
210 |
|
|
|
|
|
211 |
async def _handle_stt_ready(self, event: Event):
|
212 |
"""Handle STT ready signal"""
|
213 |
session_id = event.session_id
|
|
|
81 |
|
82 |
# Conversation events
|
83 |
self.event_bus.subscribe(EventType.CONVERSATION_STARTED, self._handle_conversation_started)
|
84 |
+
self.event_bus.subscribe(EventType.CONVERSATION_ENDED, self._handle_conversation_ended)
|
85 |
|
86 |
# Session lifecycle
|
87 |
self.event_bus.subscribe(EventType.SESSION_STARTED, self._handle_session_started)
|
|
|
117 |
|
118 |
log_info(f"🎤 Conversation started | session_id={session_id}")
|
119 |
|
120 |
+
# İlk olarak IDLE'dan INITIALIZING'e geç
|
121 |
+
await self.transition_to(session_id, ConversationState.INITIALIZING)
|
122 |
+
|
123 |
+
# Welcome mesajı varsa
|
124 |
+
if context.metadata.get("has_welcome") and context.metadata.get("welcome_text"):
|
125 |
await self.transition_to(session_id, ConversationState.PREPARING_WELCOME)
|
126 |
+
|
127 |
+
# Request TTS for welcome message
|
128 |
+
await self.event_bus.publish(Event(
|
129 |
+
type=EventType.TTS_STARTED,
|
130 |
+
session_id=session_id,
|
131 |
+
data={
|
132 |
+
"text": context.metadata.get("welcome_text", ""),
|
133 |
+
"is_welcome": True
|
134 |
+
}
|
135 |
+
))
|
136 |
else:
|
137 |
+
# Welcome yoksa direkt LISTENING'e geç
|
138 |
await self.transition_to(session_id, ConversationState.LISTENING)
|
139 |
|
140 |
# Start STT
|
141 |
+
await self.event_bus.publish(
|
142 |
Event(
|
143 |
+
type=EventType.STT_STARTED,
|
144 |
+
data={},
|
145 |
session_id=session_id
|
146 |
)
|
147 |
)
|
148 |
+
|
149 |
+
async def _handle_conversation_ended(self, event: Event) -> None:
|
150 |
+
"""Handle conversation end - but keep session alive"""
|
151 |
+
session_id = event.session_id
|
152 |
+
context = self.sessions.get(session_id)
|
153 |
+
|
154 |
+
if not context:
|
155 |
+
log_warning(f"⚠️ Session not found for conversation end | session_id={session_id}")
|
156 |
+
return
|
157 |
+
|
158 |
+
log_info(f"🔚 Conversation ended | session_id={session_id}")
|
159 |
+
|
160 |
+
# Stop STT if running
|
161 |
+
await self.event_bus.publish(Event(
|
162 |
+
type=EventType.STT_STOPPED,
|
163 |
+
session_id=session_id,
|
164 |
+
data={"reason": "conversation_ended"}
|
165 |
+
))
|
166 |
+
|
167 |
+
# Stop any ongoing TTS
|
168 |
+
await self.event_bus.publish(Event(
|
169 |
+
type=EventType.TTS_STOPPED,
|
170 |
+
session_id=session_id,
|
171 |
+
data={"reason": "conversation_ended"}
|
172 |
+
))
|
173 |
+
|
174 |
+
# Transition back to IDLE - session still alive!
|
175 |
+
await self.transition_to(session_id, ConversationState.IDLE)
|
176 |
+
|
177 |
+
log_info(f"💤 Session back to IDLE, ready for new conversation | session_id={session_id}")
|
178 |
+
|
179 |
async def _handle_session_started(self, event: Event):
|
180 |
"""Handle session start"""
|
181 |
session_id = event.session_id
|
|
|
195 |
|
196 |
self.sessions[session_id] = context
|
197 |
|
198 |
+
# Session başladığında IDLE state'te kalmalı
|
199 |
+
# Conversation başlayana kadar bekleyeceğiz
|
200 |
+
# Zaten SessionContext default state'i IDLE
|
201 |
+
log_info(f"📍 Session created in IDLE state | session_id={session_id}")
|
202 |
+
|
203 |
+
async def _handle_session_ended(self, event: Event):
|
204 |
+
"""Handle session end - complete cleanup"""
|
205 |
+
session_id = event.session_id
|
206 |
|
207 |
+
log_info(f"🏁 Session ended | session_id={session_id}")
|
208 |
+
|
209 |
+
# Get context for cleanup
|
210 |
+
context = self.sessions.get(session_id)
|
211 |
+
|
212 |
+
if context:
|
213 |
+
# Try to transition to ENDED if possible
|
214 |
+
try:
|
215 |
+
await self.transition_to(session_id, ConversationState.ENDED)
|
216 |
+
except Exception as e:
|
217 |
+
log_warning(f"Could not transition to ENDED state: {e}")
|
218 |
|
219 |
+
# Stop all components
|
220 |
await self.event_bus.publish(Event(
|
221 |
+
type=EventType.STT_STOPPED,
|
222 |
session_id=session_id,
|
223 |
+
data={"reason": "session_ended"}
|
|
|
|
|
|
|
224 |
))
|
|
|
|
|
|
|
225 |
|
|
|
226 |
await self.event_bus.publish(Event(
|
227 |
+
type=EventType.TTS_STOPPED,
|
228 |
session_id=session_id,
|
229 |
+
data={"reason": "session_ended"}
|
230 |
))
|
231 |
|
232 |
+
# Cleanup session context
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
await context.cleanup()
|
234 |
+
|
235 |
# Remove session
|
236 |
self.sessions.pop(session_id, None)
|
237 |
|
238 |
# Clear event bus session data
|
239 |
self.event_bus.clear_session_data(session_id)
|
240 |
|
241 |
+
log_info(f"✅ Session fully cleaned up | session_id={session_id}")
|
242 |
+
|
243 |
async def _handle_stt_ready(self, event: Event):
|
244 |
"""Handle STT ready signal"""
|
245 |
session_id = event.session_id
|