feat(api): implementa /executions con invoke + HITL approve/reject + persistencia
- POST /agents/{name}/invoke, GET /executions, GET /executions/{trace_id},
POST /executions/{trace_id}/{approve,reject}.
- execution_index.json persiste trace_id → (agent_name, version) para reconstruir
el contexto en approve/reject tras un reinicio.
- Refactor del orchestrator: split _snapshot → _build_execution + _snapshot, nuevo
método público snapshot() (lee estado sin avanzar). Sustituye a los helpers
_snapshot_execution/_build_graph_for_snapshot del plan, incompatibles con el
checkpointer por-llamada.
- Aliases Annotated[...] de dependencias movidos a deps.py.
- Fixture mínima tests/fixtures/policies/default/.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -64,6 +65,23 @@ async def test_invoke_camino_feliz(orchestrator: AgentOrchestrator) -> None:
|
||||
]
|
||||
|
||||
|
||||
async def test_snapshot_relee_estado_sin_avanzar(orchestrator: AgentOrchestrator) -> None:
|
||||
agent = _agent()
|
||||
paused = await orchestrator.invoke(
|
||||
agent_def=agent, policy=_policy(), user_input="caída registros sip"
|
||||
)
|
||||
again = await orchestrator.snapshot(agent_def=agent, policy=_policy(), trace_id=paused.trace_id)
|
||||
assert again is not None
|
||||
assert again.status == "awaiting_approval"
|
||||
assert again.trace_id == paused.trace_id
|
||||
# Idempotente: leer no añade pasos al decision_path.
|
||||
assert [s.step for s in again.decision_path] == [s.step for s in paused.decision_path]
|
||||
|
||||
|
||||
async def test_snapshot_trace_id_desconocido_devuelve_none(orchestrator: AgentOrchestrator) -> None:
|
||||
assert await orchestrator.snapshot(agent_def=_agent(), policy=_policy(), trace_id=uuid4()) is None
|
||||
|
||||
|
||||
async def test_invoke_pausa_hitl_y_resume_aprueba(orchestrator: AgentOrchestrator) -> None:
|
||||
agent = _agent()
|
||||
paused = await orchestrator.invoke(
|
||||
|
||||
Reference in New Issue
Block a user