Skip to content

Commit 490170f

Browse files
committed
Fix extending conversation time
1 parent 4175964 commit 490170f

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

coffee_ws/src/coffee_voice_agent/scripts/agents/coffee_barista_agent.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,15 @@ async def on_user_turn_completed(self, turn_ctx, new_message):
237237
content="ADMIN: You've been chatting for 7 minutes - time limit reached. Call the manage_conversation_time tool with action='end' to wrap up gracefully, unless there are special circumstances."
238238
)
239239
self.state_manager.seven_minute_warning_sent = True
240+
241+
# Extension expired - needs immediate ending
242+
if self.state_manager.extension_expired_pending:
243+
logger.info("Injecting extension expired admin message via callback")
244+
turn_ctx.add_message(
245+
role="system",
246+
content="ADMIN: Your granted extension time has expired. You must end the conversation gracefully now to help other visitors."
247+
)
248+
self.state_manager.extension_expired_pending = False
240249

241250
async def start_wake_word_detection(self, room):
242251
"""Start wake word detection in a separate thread"""

coffee_ws/src/coffee_voice_agent/scripts/state/state_manager.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def __init__(self, agent=None):
6363
self.five_minute_warning_sent = False
6464
self.six_minute_warning_sent = False
6565
self.seven_minute_warning_sent = False
66+
self.extension_expired_pending = False
6667

6768
# Phase 4: Mutual exclusion for virtual request processing
6869
self.virtual_request_processing_lock = asyncio.Lock()
@@ -123,6 +124,7 @@ async def _enter_new_state(self):
123124
self.five_minute_warning_sent = False
124125
self.six_minute_warning_sent = False
125126
self.seven_minute_warning_sent = False
127+
self.extension_expired_pending = False
126128

127129
# Start max conversation timer (absolute limit)
128130
self.conversation_timer = asyncio.create_task(self._max_conversation_timeout())
@@ -156,6 +158,52 @@ async def _max_conversation_timeout(self):
156158
except asyncio.CancelledError:
157159
pass
158160

161+
async def extend_conversation(self, additional_minutes: int, reason: str):
162+
"""Extend conversation by additional minutes, cancelling and restarting the timeout timer"""
163+
if self.current_state != AgentState.ACTIVE:
164+
logger.warning(f"Cannot extend conversation - not in active state (current: {self.current_state})")
165+
return
166+
167+
logger.info(f"Extending conversation by {additional_minutes} minutes: {reason}")
168+
169+
# Cancel existing conversation timer
170+
if self.conversation_timer:
171+
self.conversation_timer.cancel()
172+
self.conversation_timer = None
173+
174+
# Calculate new timeout duration (additional time from now)
175+
new_timeout_seconds = additional_minutes * 60
176+
177+
# Start new conversation timer with extended duration
178+
async def extended_timeout():
179+
try:
180+
await asyncio.sleep(new_timeout_seconds)
181+
if self.session and self.current_state == AgentState.ACTIVE:
182+
logger.info(f"Extended conversation time reached - flagging for admin message injection")
183+
184+
# Set flag for admin message injection on next user turn
185+
self.extension_expired_pending = True
186+
187+
# Fallback timer - if user doesn't speak within 30 seconds, end with hardcoded message
188+
await asyncio.sleep(30)
189+
if self.session and self.current_state == AgentState.ACTIVE and self.extension_expired_pending:
190+
logger.info("Extension expired and no user response - ending with fallback message")
191+
192+
# Set ending flag to prevent timer conflicts
193+
self.ending_conversation = True
194+
195+
# Fallback ending message
196+
timeout_response = "friendly:I've really enjoyed our extended conversation! To help other visitors, I'll need to wrap up here. Say 'hey barista' if you need me again."
197+
emotion, text = self.process_emotional_response(timeout_response)
198+
await self.say_with_emotion(text, emotion)
199+
200+
await asyncio.sleep(2)
201+
await self.end_conversation()
202+
except asyncio.CancelledError:
203+
pass
204+
205+
self.conversation_timer = asyncio.create_task(extended_timeout())
206+
159207
async def _wait_for_user_response(self):
160208
"""Wait for user response after agent speaks"""
161209
try:

coffee_ws/src/coffee_voice_agent/scripts/tools/coffee_tools.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,14 @@ async def manage_conversation_time_impl(
154154
result = f"Conversation ending initiated: {reason}"
155155

156156
elif action == "extend":
157-
logger.info(f"Conversation extended by {extension_minutes} minutes: {reason}")
158-
result = f"Conversation extended by {extension_minutes} minutes: {reason}"
157+
# Actually extend the conversation by calling state manager
158+
if _agent_instance and hasattr(_agent_instance, 'state_manager') and extension_minutes > 0:
159+
await _agent_instance.state_manager.extend_conversation(extension_minutes, reason)
160+
logger.info(f"Conversation extended by {extension_minutes} minutes: {reason}")
161+
result = f"Conversation extended by {extension_minutes} minutes: {reason}"
162+
else:
163+
logger.warning(f"Cannot extend conversation - no agent instance or invalid extension minutes: {extension_minutes}")
164+
result = f"Extension failed: {reason}"
159165

160166
elif action == "warn":
161167
logger.info(f"Conversation warning acknowledged: {reason}")

0 commit comments

Comments
 (0)