from datetime import datetime, timezone import pytest from v1.agent.schemas import AgentSessionSnapshot, RunAgentInput class TestRunAgentInput: def test_requires_full_fields(self): payload = { "threadId": "t1", "runId": "r1", "state": {}, "messages": [], "tools": [], "context": [], "forwardedProps": {}, } model = RunAgentInput.model_validate(payload) assert model.threadId == "t1" assert model.runId == "r1" assert model.parentRunId is None assert model.state == {} assert model.messages == [] assert model.tools == [] assert model.context == [] assert model.forwardedProps == {} assert model.resume is None def test_resume_optional(self): payload = { "threadId": "t1", "runId": "r2", "state": {}, "messages": [], "tools": [], "context": [], "forwardedProps": {}, "resume": {"interruptId": "int-1", "payload": {"decision": "approved"}}, } model = RunAgentInput.model_validate(payload) assert model.resume is not None assert model.resume["interruptId"] == "int-1" assert model.resume["payload"]["decision"] == "approved" def test_parent_run_id_optional(self): payload = { "threadId": "t1", "runId": "r3", "parentRunId": "p1", "state": {"key": "value"}, "messages": [{"role": "user", "content": "hello"}], "tools": [{"name": "ui.navigate_to"}], "context": [{"type": "user", "id": "u1"}], "forwardedProps": {"theme": "dark"}, } model = RunAgentInput.model_validate(payload) assert model.parentRunId == "p1" assert model.state == {"key": "value"} assert len(model.messages) == 1 assert model.messages[0]["role"] == "user" class TestAgentSessionSnapshot: def test_state_snapshot_v2_model_accepts_valid_payload(self): payload = { "version": 2, "pending_tool_call": { "interrupt_id": "int-1", "tool_name": "srv.transfer_funds", "tool_args": {"to": "u2", "amount": 100}, "status": "PENDING_APPROVAL", "expires_at": "2026-03-03T12:00:00Z", "decision": None, "result": None, "updated_at": "2026-03-03T11:59:00Z", }, "run_context": {"thread_id": "t1", "run_id": "r1"}, } model = AgentSessionSnapshot.model_validate(payload) assert model.version == 2 assert model.pending_tool_call is not None assert model.pending_tool_call.interrupt_id == "int-1" assert model.pending_tool_call.updated_at == datetime( 2026, 3, 3, 11, 59, tzinfo=timezone.utc ) def test_state_snapshot_v2_rejects_wrong_version(self): payload = { "version": 1, "pending_tool_call": None, "run_context": {"thread_id": "t1", "run_id": "r1"}, } with pytest.raises(ValueError): AgentSessionSnapshot.model_validate(payload) def test_state_snapshot_v2_requires_pending_tool_call_key(self): payload = { "version": 2, "run_context": {"thread_id": "t1", "run_id": "r1"}, } with pytest.raises(ValueError): AgentSessionSnapshot.model_validate(payload) def test_state_snapshot_v2_rejects_extra_fields(self): payload = { "version": 2, "pending_tool_call": { "interrupt_id": "int-1", "tool_name": "srv.transfer_funds", "tool_args": {"to": "u2", "amount": 100}, "status": "PENDING_APPROVAL", "expires_at": "2026-03-03T12:00:00Z", "decision": None, "result": None, "updated_at": "2026-03-03T11:59:00Z", "unexpected": True, }, "run_context": {"thread_id": "t1", "run_id": "r1", "foo": "bar"}, } with pytest.raises(ValueError): AgentSessionSnapshot.model_validate(payload)