105 lines
4.5 KiB
Python
105 lines
4.5 KiB
Python
import asyncio
|
|
from pathlib import Path
|
|
|
|
from a2a_pack import LocalRunContext, PlatformUserAuth
|
|
from a2a_pack.cli.local import load_local_project
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
FIXTURE = """From: alex@company.example
|
|
Subject: Concern about team behavior
|
|
Body: I want to report behavior that feels like harassment and retaliation after I raised a concern. What should I do next?
|
|
---
|
|
From: priya@company.example
|
|
Subject: Benefits enrollment for dependent
|
|
Body: I need to add a dependent to my insurance and want to understand eligibility and enrollment timing.
|
|
---
|
|
From: marco@company.example
|
|
Subject: PTO request next month
|
|
Body: I would like to take leave from May 6 to May 10. Can People approve this?
|
|
"""
|
|
|
|
|
|
def test_full_stack_product_contract():
|
|
manifest = (ROOT / "a2a.yaml").read_text(encoding="utf-8")
|
|
source = (ROOT / "agent.py").read_text(encoding="utf-8")
|
|
frontend = (ROOT / "frontend" / "src" / "App.jsx").read_text(encoding="utf-8")
|
|
frontend_client = (ROOT / "frontend" / "src" / "a2a.js").read_text(encoding="utf-8")
|
|
|
|
assert "frontend:" in manifest and "mount: /app" in manifest
|
|
assert "public: false" in manifest
|
|
assert "mailbox: true" in manifest
|
|
assert "resources:" in manifest and "databases:" in manifest
|
|
assert "migrations:" in manifest and "db/migrations" in manifest
|
|
assert "PlatformUserAuth" in source
|
|
assert "AccountAccess(required=True, platform_skill_calls=3, after_trial=\"byok\")" in source
|
|
assert "AgentPlatformResources" in source and "AgentDatabase(" in source
|
|
assert "ctx.write_artifact" in source and "ctx.emit_artifact" in source
|
|
assert "Skill runner" not in frontend, "replace the generic scaffold with the product workflow"
|
|
assert "data-testid=\"agent-app\"" in frontend
|
|
assert "data-testid=\"agent-submit\"" in frontend
|
|
assert "data-testid=\"agent-result\"" in frontend
|
|
assert "data-testid=\"agent-download\"" in frontend
|
|
assert "unwrapInvokeResponse" in frontend_client, "unwrap the /invoke result envelope before rendering"
|
|
|
|
migrations = list((ROOT / "db" / "migrations").glob("*.sql"))
|
|
assert migrations and all(path.read_text(encoding="utf-8").strip() for path in migrations)
|
|
|
|
card = load_local_project(ROOT).agent_cls().card()
|
|
assert {skill.name for skill in card.skills} >= {
|
|
"triage_people_inbox",
|
|
"mailbox_status",
|
|
"receive_people_email",
|
|
}
|
|
triage = next(skill for skill in card.skills if skill.name == "triage_people_inbox")
|
|
assert set(triage.input_schema["properties"]) == {"inbox_text", "policy_text", "max_messages"}
|
|
databases = card.runtime.platform_resources.databases
|
|
assert databases, "live Agent Card must declare its managed database"
|
|
assert databases[0].migrations is not None
|
|
assert databases[0].migrations.path == "db/migrations"
|
|
assert card.runtime.platform_resources.mailbox is True
|
|
assert card.runtime.account_access.required is True
|
|
assert card.runtime.account_access.platform_skill_calls == 3
|
|
assert card.runtime.account_access.after_trial == "byok"
|
|
|
|
|
|
def test_smoke_triage_returns_structured_result_without_secrets(monkeypatch):
|
|
monkeypatch.delenv("DATABASE_URL", raising=False)
|
|
project = load_local_project(ROOT)
|
|
agent = project.agent_cls()()
|
|
ctx = LocalRunContext(
|
|
auth=PlatformUserAuth(sub="user-123", user_id=123, email="person@example.com"),
|
|
task_id="test-triage",
|
|
)
|
|
|
|
result = asyncio.run(
|
|
agent.invoke(
|
|
"triage_people_inbox",
|
|
ctx,
|
|
inbox_text=FIXTURE,
|
|
max_messages=3,
|
|
)
|
|
)
|
|
|
|
assert result.status == "ok"
|
|
assert len(result.queue) == 3
|
|
assert result.queue[0].priority == "urgent"
|
|
assert result.queue[0].draft.approval_required is True
|
|
assert result.artifact.name == "people-team-inbox-triage.json"
|
|
assert result.artifact.media_type == "application/json"
|
|
assert "DATABASE_URL" not in result.model_dump_json()
|
|
assert "api_key" not in result.model_dump_json().lower()
|
|
assert ctx.artifacts["people-team-inbox-triage.json"]
|
|
assert result.receipt.receipt_id
|
|
|
|
|
|
def test_bad_input_returns_validation_error(monkeypatch):
|
|
monkeypatch.delenv("DATABASE_URL", raising=False)
|
|
project = load_local_project(ROOT)
|
|
agent = project.agent_cls()()
|
|
ctx = LocalRunContext(auth=PlatformUserAuth(sub="user-123", user_id=123), task_id="test-bad")
|
|
result = asyncio.run(agent.invoke("triage_people_inbox", ctx, inbox_text="short but long enough words"))
|
|
assert result.status == "validation_error"
|
|
assert result.queue == []
|