@ -17,6 +17,11 @@ class ConversationPolicy:
def __init__ ( self , service : " OrquestradorService " ) :
def __init__ ( self , service : " OrquestradorService " ) :
self . service = service
self . service = service
def _save_context ( self , user_id : int | None , context : dict | None ) - > None :
if user_id is None or not isinstance ( context , dict ) :
return
self . service . _save_user_context ( user_id = user_id , context = context )
def _decision_action ( self , turn_decision : dict | None ) - > str :
def _decision_action ( self , turn_decision : dict | None ) - > str :
return str ( ( turn_decision or { } ) . get ( " action " ) or " " ) . strip ( ) . lower ( )
return str ( ( turn_decision or { } ) . get ( " action " ) or " " ) . strip ( ) . lower ( )
@ -72,6 +77,7 @@ class ConversationPolicy:
" created_at " : datetime . utcnow ( ) . isoformat ( ) ,
" created_at " : datetime . utcnow ( ) . isoformat ( ) ,
}
}
)
)
self . _save_context ( user_id = user_id , context = context )
# Transforma as entidades extraídas de um pedido em uma memória temporária pronta para usar quando esse pedido for processado.
# Transforma as entidades extraídas de um pedido em uma memória temporária pronta para usar quando esse pedido for processado.
@ -109,7 +115,9 @@ class ConversationPolicy:
queue = context . setdefault ( " order_queue " , [ ] )
queue = context . setdefault ( " order_queue " , [ ] )
if not queue :
if not queue :
return None
return None
return queue . pop ( 0 )
popped = queue . pop ( 0 )
self . _save_context ( user_id = user_id , context = context )
return popped
@ -196,6 +204,7 @@ class ConversationPolicy:
queued_count + = 1
queued_count + = 1
context [ " active_domain " ] = first [ " domain " ]
context [ " active_domain " ] = first [ " domain " ]
context [ " generic_memory " ] = self . build_order_memory_seed ( user_id = user_id , order = first )
context [ " generic_memory " ] = self . build_order_memory_seed ( user_id = user_id , order = first )
self . _save_context ( user_id = user_id , context = context )
queue_notice = self . render_queue_notice ( queued_count )
queue_notice = self . render_queue_notice ( queued_count )
return first [ " message " ] , queue_notice , None
return first [ " message " ] , queue_notice , None
@ -226,6 +235,7 @@ class ConversationPolicy:
] ,
] ,
" expires_at " : datetime . utcnow ( ) + timedelta ( minutes = PENDING_ORDER_SELECTION_TTL_MINUTES ) ,
" expires_at " : datetime . utcnow ( ) + timedelta ( minutes = PENDING_ORDER_SELECTION_TTL_MINUTES ) ,
}
}
self . _save_context ( user_id = user_id , context = context )
# Cria o texto de escolha para o usuário.
# Cria o texto de escolha para o usuário.
@ -437,10 +447,12 @@ class ConversationPolicy:
return None
return None
if pending . get ( " expires_at " ) and pending [ " expires_at " ] < datetime . utcnow ( ) :
if pending . get ( " expires_at " ) and pending [ " expires_at " ] < datetime . utcnow ( ) :
context [ " pending_order_selection " ] = None
context [ " pending_order_selection " ] = None
self . _save_context ( user_id = user_id , context = context )
return None
return None
orders = pending . get ( " orders " ) or [ ]
orders = pending . get ( " orders " ) or [ ]
if len ( orders ) < 2 :
if len ( orders ) < 2 :
context [ " pending_order_selection " ] = None
context [ " pending_order_selection " ] = None
self . _save_context ( user_id = user_id , context = context )
return None
return None
decision_action = self . _decision_action ( turn_decision )
decision_action = self . _decision_action ( turn_decision )
@ -459,6 +471,7 @@ class ConversationPolicy:
if selected_index is None :
if selected_index is None :
if self . looks_like_fresh_operational_request ( message , turn_decision = turn_decision ) :
if self . looks_like_fresh_operational_request ( message , turn_decision = turn_decision ) :
context [ " pending_order_selection " ] = None
context [ " pending_order_selection " ] = None
self . _save_context ( user_id = user_id , context = context )
return None
return None
return self . render_order_selection_prompt ( orders )
return self . render_order_selection_prompt ( orders )
@ -480,6 +493,7 @@ class ConversationPolicy:
selected_memory = dict ( selected_order . get ( " memory_seed " ) or { } )
selected_memory = dict ( selected_order . get ( " memory_seed " ) or { } )
if selected_memory :
if selected_memory :
context [ " generic_memory " ] = selected_memory
context [ " generic_memory " ] = selected_memory
self . _save_context ( user_id = user_id , context = context )
next_response = await self . service . handle_message ( str ( selected_order . get ( " message " ) or " " ) , user_id = user_id )
next_response = await self . service . handle_message ( str ( selected_order . get ( " message " ) or " " ) , user_id = user_id )
return f " { intro } \n { next_response } "
return f " { intro } \n { next_response } "
@ -564,6 +578,7 @@ class ConversationPolicy:
" memory_seed " : dict ( next_order . get ( " memory_seed " ) or self . service . _new_tab_memory ( user_id = user_id ) ) ,
" memory_seed " : dict ( next_order . get ( " memory_seed " ) or self . service . _new_tab_memory ( user_id = user_id ) ) ,
" expires_at " : datetime . utcnow ( ) + timedelta ( minutes = 15 ) ,
" expires_at " : datetime . utcnow ( ) + timedelta ( minutes = 15 ) ,
}
}
self . _save_context ( user_id = user_id , context = context )
transition = self . build_next_order_transition ( next_order [ " domain " ] )
transition = self . build_next_order_transition ( next_order [ " domain " ] )
return (
return (
f " { base_response } \n \n "
f " { base_response } \n \n "
@ -622,6 +637,7 @@ class ConversationPolicy:
return None
return None
if pending_switch . get ( " expires_at " ) and pending_switch [ " expires_at " ] < datetime . utcnow ( ) :
if pending_switch . get ( " expires_at " ) and pending_switch [ " expires_at " ] < datetime . utcnow ( ) :
context [ " pending_switch " ] = None
context [ " pending_switch " ] = None
self . _save_context ( user_id = user_id , context = context )
return None
return None
queued_message = str ( pending_switch . get ( " queued_message " ) or " " ) . strip ( )
queued_message = str ( pending_switch . get ( " queued_message " ) or " " ) . strip ( )
if not queued_message :
if not queued_message :
@ -630,6 +646,7 @@ class ConversationPolicy:
decision_action = self . _decision_action ( turn_decision )
decision_action = self . _decision_action ( turn_decision )
if self . service . _is_negative_message ( message ) and decision_action != " continue_queue " :
if self . service . _is_negative_message ( message ) and decision_action != " continue_queue " :
context [ " pending_switch " ] = None
context [ " pending_switch " ] = None
self . _save_context ( user_id = user_id , context = context )
return " Tudo bem. Mantive o proximo pedido fora da fila por enquanto. "
return " Tudo bem. Mantive o proximo pedido fora da fila por enquanto. "
if not (
if not (
self . is_continue_queue_message ( message , turn_decision = turn_decision )
self . is_continue_queue_message ( message , turn_decision = turn_decision )
@ -643,6 +660,7 @@ class ConversationPolicy:
refreshed = self . service . _get_user_context ( user_id )
refreshed = self . service . _get_user_context ( user_id )
if refreshed is not None :
if refreshed is not None :
refreshed [ " generic_memory " ] = memory_seed
refreshed [ " generic_memory " ] = memory_seed
self . _save_context ( user_id = user_id , context = refreshed )
transition = self . build_next_order_transition ( target_domain )
transition = self . build_next_order_transition ( target_domain )
next_response = await self . service . handle_message ( queued_message , user_id = user_id )
next_response = await self . service . handle_message ( queued_message , user_id = user_id )
return f " { transition } \n { next_response } "
return f " { transition } \n { next_response } "
@ -681,6 +699,7 @@ class ConversationPolicy:
context [ " generic_memory " ] = self . service . _new_tab_memory ( user_id = user_id )
context [ " generic_memory " ] = self . service . _new_tab_memory ( user_id = user_id )
context [ " pending_order_selection " ] = None
context [ " pending_order_selection " ] = None
context [ " pending_switch " ] = None
context [ " pending_switch " ] = None
self . _save_context ( user_id = user_id , context = context )
# Controla a confirmação de “você quer mesmo sair deste assunto e ir para outro?”.
# Controla a confirmação de “você quer mesmo sair deste assunto e ir para outro?”.
@ -698,17 +717,20 @@ class ConversationPolicy:
if pending_switch :
if pending_switch :
if pending_switch [ " expires_at " ] < datetime . utcnow ( ) :
if pending_switch [ " expires_at " ] < datetime . utcnow ( ) :
context [ " pending_switch " ] = None
context [ " pending_switch " ] = None
self . _save_context ( user_id = user_id , context = context )
elif self . is_context_switch_confirmation ( message , turn_decision = turn_decision ) :
elif self . is_context_switch_confirmation ( message , turn_decision = turn_decision ) :
if self . service . _is_affirmative_message ( message ) or self . _decision_domain ( turn_decision ) == pending_switch [ " target_domain " ] :
if self . service . _is_affirmative_message ( message ) or self . _decision_domain ( turn_decision ) == pending_switch [ " target_domain " ] :
target_domain = pending_switch [ " target_domain " ]
target_domain = pending_switch [ " target_domain " ]
self . apply_domain_switch ( user_id = user_id , target_domain = target_domain )
self . apply_domain_switch ( user_id = user_id , target_domain = target_domain )
return self . render_context_switched_message ( target_domain = target_domain )
return self . render_context_switched_message ( target_domain = target_domain )
context [ " pending_switch " ] = None
context [ " pending_switch " ] = None
self . _save_context ( user_id = user_id , context = context )
return " Perfeito, vamos continuar no fluxo atual. "
return " Perfeito, vamos continuar no fluxo atual. "
pending_order_selection = context . get ( " pending_order_selection " )
pending_order_selection = context . get ( " pending_order_selection " )
if pending_order_selection and pending_order_selection . get ( " expires_at " ) < datetime . utcnow ( ) :
if pending_order_selection and pending_order_selection . get ( " expires_at " ) < datetime . utcnow ( ) :
context [ " pending_order_selection " ] = None
context [ " pending_order_selection " ] = None
self . _save_context ( user_id = user_id , context = context )
current_domain = context . get ( " active_domain " , " general " )
current_domain = context . get ( " active_domain " , " general " )
if target_domain_hint == " general " or target_domain_hint == current_domain :
if target_domain_hint == " general " or target_domain_hint == current_domain :
@ -721,6 +743,7 @@ class ConversationPolicy:
" target_domain " : target_domain_hint ,
" target_domain " : target_domain_hint ,
" expires_at " : datetime . utcnow ( ) + timedelta ( minutes = 15 ) ,
" expires_at " : datetime . utcnow ( ) + timedelta ( minutes = 15 ) ,
}
}
self . _save_context ( user_id = user_id , context = context )
return self . render_context_switch_confirmation ( source_domain = current_domain , target_domain = target_domain_hint )
return self . render_context_switch_confirmation ( source_domain = current_domain , target_domain = target_domain_hint )
@ -729,6 +752,7 @@ class ConversationPolicy:
context = self . service . _get_user_context ( user_id )
context = self . service . _get_user_context ( user_id )
if context and domain_hint != " general " :
if context and domain_hint != " general " :
context [ " active_domain " ] = domain_hint
context [ " active_domain " ] = domain_hint
self . _save_context ( user_id = user_id , context = context )
# Serve para exibir o nome do domínio em mensagens para o usuário.
# Serve para exibir o nome do domínio em mensagens para o usuário.