Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
"""Tests: typed reason codes survive the A2A relay roundtrip (#93091).
|
||||
|
||||
The sending agent must receive the machine-readable failure code, not just
|
||||
provider prose: bot_relay.deliver ships `reason` in JSON-RPC error.data
|
||||
(pinned in test_bot_retry_policy), the Desktop forwards it to bot_relay.reply,
|
||||
write_reply persists it, and the waiter script prints it. This file pins the
|
||||
persist + waiter surfaces.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from tools import bot_failure_reasons as bfr
|
||||
from tools import bot_relay
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def home(tmp_path, monkeypatch):
|
||||
h = tmp_path / ".hermes"
|
||||
h.mkdir()
|
||||
monkeypatch.setenv("HERMES_HOME", str(h))
|
||||
return h
|
||||
|
||||
|
||||
def _reply_file(home, envelope_id):
|
||||
return bot_relay.relay_root(home) / bot_relay.REPLIES_DIR / f"{envelope_id}.json"
|
||||
|
||||
|
||||
def test_write_reply_persists_forwarded_reason(home):
|
||||
"""A reason forwarded by the Desktop drain loop lands in the reply file."""
|
||||
envelope_id = "a" * 32
|
||||
bot_relay.write_reply(
|
||||
home,
|
||||
envelope_id,
|
||||
error="delivery turn failed: Error code: 429",
|
||||
reason=bfr.PROVIDER_RATE_LIMIT,
|
||||
)
|
||||
data = json.loads(_reply_file(home, envelope_id).read_text(encoding="utf-8"))
|
||||
assert data["reason"] == bfr.PROVIDER_RATE_LIMIT
|
||||
|
||||
|
||||
def test_write_reply_classifies_when_reason_omitted(home):
|
||||
"""Old senders that never forward a reason still get a classified code."""
|
||||
envelope_id = "b" * 32
|
||||
bot_relay.write_reply(
|
||||
home,
|
||||
envelope_id,
|
||||
error="Error code: 401 - Your API key is invalid, blocked or out of funds",
|
||||
)
|
||||
data = json.loads(_reply_file(home, envelope_id).read_text(encoding="utf-8"))
|
||||
assert data["reason"] == bfr.PROVIDER_AUTH_OR_ACCESS
|
||||
|
||||
|
||||
def _run_waiter(home, envelope):
|
||||
cmd = bot_relay.waiter_command(home, envelope)
|
||||
return subprocess.run(
|
||||
["bash", "-c", cmd], capture_output=True, text=True, timeout=30
|
||||
)
|
||||
|
||||
|
||||
def _envelope(home):
|
||||
target = {
|
||||
"profile": "scout",
|
||||
"handle": "scout",
|
||||
"connection_id": "cloud-1",
|
||||
"connection_label": "",
|
||||
"title": "",
|
||||
"description": "",
|
||||
}
|
||||
return bot_relay.enqueue_envelope(
|
||||
home,
|
||||
target=target,
|
||||
message="ping",
|
||||
sender_profile="default",
|
||||
sender_handle="hermes",
|
||||
)
|
||||
|
||||
|
||||
def test_waiter_surfaces_reason_tag_to_sending_agent(home, monkeypatch):
|
||||
"""The waiter's stdout — the sending agent's completion notification —
|
||||
carries the typed reason so the agent can branch without parsing prose."""
|
||||
monkeypatch.setattr(bot_relay, "_target_liveness", lambda *a, **k: True)
|
||||
env = _envelope(home)
|
||||
bot_relay.write_reply(
|
||||
home,
|
||||
env["id"],
|
||||
error="delivery turn failed: rate limit exceeded",
|
||||
reason=bfr.PROVIDER_RATE_LIMIT,
|
||||
)
|
||||
proc = _run_waiter(home, env)
|
||||
assert proc.returncode == 1
|
||||
assert f"[reason: {bfr.PROVIDER_RATE_LIMIT}]" in proc.stdout
|
||||
|
||||
|
||||
def test_waiter_healthy_reply_has_no_reason_tag(home, monkeypatch):
|
||||
"""Success path unchanged: no reason tag noise on good replies."""
|
||||
monkeypatch.setattr(bot_relay, "_target_liveness", lambda *a, **k: True)
|
||||
env = _envelope(home)
|
||||
bot_relay.write_reply(home, env["id"], reply="pong")
|
||||
proc = _run_waiter(home, env)
|
||||
assert proc.returncode == 0
|
||||
assert "pong" in proc.stdout
|
||||
assert "[reason:" not in proc.stdout
|
||||
|
||||
|
||||
def test_waiter_reasonless_error_prints_plain(home, monkeypatch):
|
||||
"""A reply file with error text whose classification is unknown still
|
||||
prints cleanly — the unknown code is a valid tag, never a crash."""
|
||||
monkeypatch.setattr(bot_relay, "_target_liveness", lambda *a, **k: True)
|
||||
env = _envelope(home)
|
||||
bot_relay.write_reply(home, env["id"], error="something odd happened")
|
||||
proc = _run_waiter(home, env)
|
||||
assert proc.returncode == 1
|
||||
assert "failed" in proc.stdout
|
||||
# classify_agent_error("something odd happened") == unknown → tagged
|
||||
assert f"[reason: {bfr.UNKNOWN}]" in proc.stdout
|
||||
Reference in New Issue
Block a user