Ajustes conforme relatorio de testes 2026-08-27
This commit is contained in:
130
tests/migration/test_invoice_explanation_handoff_policy.py
Normal file
130
tests/migration/test_invoice_explanation_handoff_policy.py
Normal file
@@ -0,0 +1,130 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from types import SimpleNamespace
|
||||
|
||||
from app.agents.faturas_agent import FaturasAgent
|
||||
from app.domain.contas.workflow_actions import build_contas_workflow_actions
|
||||
from contas_mcp.servers.contas_mcp_server import main as mcp_main
|
||||
|
||||
|
||||
def test_invoice_explanation_handoff_action_is_structural_and_uses_configured_message():
|
||||
class Service:
|
||||
pass
|
||||
|
||||
action = build_contas_workflow_actions(Service()).get("preparar_handoff_invoice_explanation")
|
||||
result = action(
|
||||
{
|
||||
"mensagem": "Para continuar com a sua solicitação, aguarde um instante.",
|
||||
"reason": "invoice_explanation_not_resolved",
|
||||
},
|
||||
{"input": {}},
|
||||
)
|
||||
assert result["mensagem"] == "Para continuar com a sua solicitação, aguarde um instante."
|
||||
assert result["session_control"] == "HUMAN_HANDOFF"
|
||||
assert result["human_handoff_requested"] is True
|
||||
assert result["handoff"] is True
|
||||
assert result["session_ended"] is True
|
||||
assert result["terminal_status"] == "human_handoff"
|
||||
|
||||
|
||||
def test_result_payload_promotes_invoice_explanation_handoff_control():
|
||||
result = {
|
||||
"execution_id": "exec-1",
|
||||
"status": "COMPLETED",
|
||||
"output": {
|
||||
"handoff_pos_explicacao_nao": {
|
||||
"success": True,
|
||||
"mensagem": "Para continuar com a sua solicitação, aguarde um instante.",
|
||||
"session_control": "HUMAN_HANDOFF",
|
||||
"handoff_reason": "invoice_explanation_not_resolved",
|
||||
}
|
||||
},
|
||||
"state": {"current_node": "handoff_pos_explicacao_nao"},
|
||||
"trace": [{"node": "handoff_pos_explicacao_nao", "status": "COMPLETED"}],
|
||||
}
|
||||
payload = mcp_main._result_payload(result, workflow_name="invoice_explanation")
|
||||
assert payload["mensagem"] == "Para continuar com a sua solicitação, aguarde um instante."
|
||||
assert payload["session_control"] == "HUMAN_HANDOFF"
|
||||
assert payload["human_handoff_requested"] is True
|
||||
assert payload["handoff"] is True
|
||||
assert payload["session_ended"] is True
|
||||
|
||||
|
||||
def test_faturas_agent_promotes_handoff_from_tool_context_to_graph_state():
|
||||
context = [{
|
||||
"tool_name": "retomar_workflow",
|
||||
"ok": True,
|
||||
"result": {
|
||||
"workflow_name": "invoice_explanation",
|
||||
"status": "COMPLETED",
|
||||
"mensagem": "Para continuar com a sua solicitação, aguarde um instante.",
|
||||
"session_control": "HUMAN_HANDOFF",
|
||||
"human_handoff_requested": True,
|
||||
"session_ended": True,
|
||||
"terminal_status": "human_handoff",
|
||||
"handoff_reason": "invoice_explanation_not_resolved",
|
||||
},
|
||||
}]
|
||||
patch = FaturasAgent._handoff_patch_from_tool_context(context)
|
||||
assert patch == {
|
||||
"session_control": "HUMAN_HANDOFF",
|
||||
"human_handoff_requested": True,
|
||||
"session_ended": True,
|
||||
"terminal_status": "human_handoff",
|
||||
"handoff_reason": "invoice_explanation_not_resolved",
|
||||
}
|
||||
|
||||
|
||||
def test_completed_terminal_workflow_short_circuits_llm_composition_directive():
|
||||
agent = FaturasAgent.__new__(FaturasAgent)
|
||||
context = [{
|
||||
"tool_name": "retomar_workflow",
|
||||
"ok": True,
|
||||
"result": {
|
||||
"status": "COMPLETED",
|
||||
"workflow_name": "generic_workflow",
|
||||
# Earlier node still carries a composition directive. It must not win
|
||||
# over the terminal last node.
|
||||
"requires_llm_composition": True,
|
||||
"response_instruction": "Componha uma nova resposta.",
|
||||
"output": {
|
||||
"formatar": {
|
||||
"requires_llm_composition": True,
|
||||
"mensagem": "mensagem anterior",
|
||||
},
|
||||
"final": {
|
||||
"mensagem": "Encaminhando para atendimento humano.",
|
||||
"session_control": "HUMAN_HANDOFF",
|
||||
"handoff": True,
|
||||
"session_ended": True,
|
||||
"terminal_status": "human_handoff",
|
||||
},
|
||||
},
|
||||
"state": {"current_node": "final"},
|
||||
},
|
||||
}]
|
||||
answer = agent.build_direct_mcp_answer({}, context, agent_label="AnyAgent")
|
||||
assert answer == "Encaminhando para atendimento humano."
|
||||
|
||||
|
||||
def test_result_payload_promotes_generic_terminal_last_node_contract():
|
||||
result = {
|
||||
"execution_id": "exec-generic",
|
||||
"status": "COMPLETED",
|
||||
"output": {
|
||||
"final": {
|
||||
"mensagem": "Sessão encerrada.",
|
||||
"session_control": "END_SESSION",
|
||||
"session_ended": True,
|
||||
"terminal_status": "done",
|
||||
}
|
||||
},
|
||||
"state": {"current_node": "final"},
|
||||
"trace": [{"node": "final", "status": "COMPLETED"}],
|
||||
}
|
||||
payload = mcp_main._result_payload(result, workflow_name="generic_example")
|
||||
assert payload["terminal"] is True
|
||||
assert payload["terminal_action"] == "end_session"
|
||||
assert payload["mensagem"] == "Sessão encerrada."
|
||||
assert payload["session_ended"] is True
|
||||
Reference in New Issue
Block a user