File size: 4,397 Bytes
a42a6a0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | """Agent-facing errors at the hub boundary: every failure is the standard
{"error": {code, message, hint?}} body, never a bare 500 or a FastAPI 422."""
from __future__ import annotations
from fakes import seed_agent
SOURCE = "hf://buckets/test-org/test-agent-1/drafts/note.md"
RESULT = "hf://buckets/test-org/test-agent-1/results/run1.md"
def _error(r, status: int, code: str) -> dict:
assert r.status_code == status, r.text
err = r.json()["error"]
assert err["code"] == code and err["message"]
return err
def test_missing_message_source_is_404_with_upload_hint(env):
seed_agent(env.hub, "agent-1")
r = env.client.post("/v1/messages", json={"source": SOURCE})
err = _error(r, 404, "SOURCE_NOT_FOUND")
assert SOURCE in err["message"]
assert "hf buckets cp" in err["hint"]
def test_failed_source_read_is_404(env):
seed_agent(env.hub, "agent-1")
env.hub.seed("results/run1.md", "---\nscore: 1\n---\nx", bucket="test-org/test-agent-1")
env.hub.fail_next_read("results/run1.md")
_error(env.client.post("/v1/results", json={"source": RESULT}), 404, "SOURCE_NOT_FOUND")
def test_binary_source_is_400(env):
seed_agent(env.hub, "agent-1")
env.hub.buckets["test-org/test-agent-1"] = {"drafts/note.md": b"\xff\xfe\x00binary"}
for route, uri in [("/v1/messages", SOURCE), ("/v1/results", SOURCE)]:
err = _error(env.client.post(route, json={"source": uri}), 400, "INVALID_FRONTMATTER")
assert "UTF-8" in err["message"]
def test_oversized_source_is_413_naming_the_limit(make_env):
env = make_env(MESSAGE_MAX_BYTES=100)
seed_agent(env.hub, "agent-1")
env.hub.seed("drafts/note.md", "x" * 101, bucket="test-org/test-agent-1")
err = _error(env.client.post("/v1/messages", json={"source": SOURCE}), 413, "TOO_LARGE")
assert "100" in err["message"]
def test_hub_write_failure_is_503_with_retry_after(env):
seed_agent(env.hub, "agent-1")
env.hub.fail_next_write()
r = env.client.post("/v1/messages", json={"agent_id": "agent-1", "body": "hi"})
err = _error(r, 503, "STORAGE_UNAVAILABLE")
assert "nothing was written" in err["message"]
assert r.headers["retry-after"] == "5"
assert env.client.get("/v1/messages").json()["count"] == 0
def test_missing_required_fields_is_400_listing_each(env):
r = env.client.post("/v1/agents/register", json={"agent_id": "agent-1"})
err = _error(r, 400, "INVALID_REQUEST")
lines = err["message"].splitlines()
assert "body.model: Field required" in lines
assert "body.harness: Field required" in lines
def test_unknown_field_is_400_naming_it(env):
seed_agent(env.hub, "agent-1")
r = env.client.post(
"/v1/messages", json={"agent_id": "agent-1", "body": "hi", "mentions": ["agent-2"]}
)
err = _error(r, 400, "INVALID_REQUEST")
assert "body.mentions: Extra inputs are not permitted" in err["message"]
def test_oversized_raw_body_is_413(env):
seed_agent(env.hub, "agent-1")
r = env.client.post("/v1/messages", json={"agent_id": "agent-1", "body": "x" * 40_000})
err = _error(r, 413, "TOO_LARGE")
assert "32768" in err["message"]
def test_raw_refs_accepts_a_list(env):
seed_agent(env.hub, "agent-1")
seed_agent(env.hub, "agent-2")
refs = ["20260601-100000-000_agent-2.md"]
r = env.client.post(
"/v1/messages", json={"agent_id": "agent-1", "body": "building on it", "refs": refs}
)
assert r.status_code == 201, r.text
assert r.json()["mentions_delivered"] == ["agent-2"]
fm = env.client.get(f"/v1/messages/{r.json()['filename']}").json()["frontmatter"]
assert fm["refs"] == refs
def test_cold_listing_failure_is_503_not_an_empty_folder(env):
env.hub.seed("message_board/20260601-100000-000_agent-1.md", "---\nagent: agent-1\n---\nhi")
env.hub.fail_next_listing("message_board")
r = env.client.get("/v1/messages")
_error(r, 503, "STORAGE_UNAVAILABLE")
assert r.headers["retry-after"] == "5"
assert env.client.get("/v1/messages").json()["count"] == 1
def test_failed_batch_download_is_503_not_404(env):
fn = "20260601-100000-000_agent-1.md"
env.hub.seed(f"message_board/{fn}", "---\nagent: agent-1\n---\nhi")
env.hub.fail_next_read("message_board/")
_error(env.client.get(f"/v1/messages/{fn}"), 503, "STORAGE_UNAVAILABLE")
assert env.client.get(f"/v1/messages/{fn}").status_code == 200
|