diff --git a/app/services/orchestration/conversation_policy.py b/app/services/orchestration/conversation_policy.py index 22d5205..35dc761 100644 --- a/app/services/orchestration/conversation_policy.py +++ b/app/services/orchestration/conversation_policy.py @@ -171,10 +171,10 @@ class ConversationPolicy: and inferred != active_domain and self.has_open_flow(user_id=user_id, domain=active_domain) ): - self.queue_order(user_id=user_id, domain=inferred, order_message=message) - queue_hint = self.render_queue_notice(1) - prompt = self.render_open_flow_prompt(user_id=user_id, domain=active_domain) - return message, None, f"{prompt}\n{queue_hint}" if queue_hint else prompt + # Para uma troca explicita de dominio com fluxo aberto, + # deixa a confirmacao de context switch acontecer no ponto + # normal da policy em vez de enfileirar cedo demais. + return message, None, None return message, None, None if self.has_open_flow(user_id=user_id, domain=active_domain): diff --git a/tests/test_turn_decision_contract.py b/tests/test_turn_decision_contract.py index 0d82ab1..05b606b 100644 --- a/tests/test_turn_decision_contract.py +++ b/tests/test_turn_decision_contract.py @@ -96,6 +96,9 @@ class FakePolicyService: def _new_tab_memory(self, user_id: int | None): return {} + def _coerce_extraction_contract(self, payload): + return payload if isinstance(payload, dict) else self.normalizer.empty_extraction_payload() + def _is_affirmative_message(self, text: str) -> bool: normalized = self.normalizer.normalize_text(text).strip().rstrip(".!?,;:") return normalized in {"sim", "pode", "ok", "confirmo", "aceito", "fechado", "pode sim"} @@ -1220,6 +1223,40 @@ class TurnDecisionContractTests(unittest.IsolatedAsyncioTestCase): self.assertEqual(response, "Certo, contexto anterior encerrado. Vamos seguir com agendamento de revisao.") + def test_prepare_message_for_single_order_defers_explicit_domain_switch_with_open_flow(self): + state = FakeState( + entries={ + "pending_review_drafts": { + 9: { + "payload": {"placa": "ABC1234"}, + "expires_at": datetime.utcnow() + timedelta(minutes=15), + } + } + }, + contexts={ + 9: { + "active_domain": "review", + "generic_memory": {}, + "order_queue": [], + "pending_order_selection": None, + "pending_switch": None, + } + }, + ) + service = FakePolicyService(state) + policy = ConversationPolicy(service=service) + + routed_message, queue_notice, early_response = policy.prepare_message_for_single_order( + message="quero comprar um carro de ate 62 mil", + user_id=9, + routing_plan={"orders": [{"domain": "sales", "message": "quero comprar um carro de ate 62 mil"}]}, + ) + + self.assertEqual(routed_message, "quero comprar um carro de ate 62 mil") + self.assertIsNone(queue_notice) + self.assertIsNone(early_response) + self.assertEqual(service._get_user_context(9).get("order_queue"), []) + if __name__ == "__main__": unittest.main()