test_post_contract_aliases.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. from datetime import datetime, timedelta
  2. from pathlib import Path
  3. from tests.conftest import (
  4. build_fastapi_test_client,
  5. build_postgres_database_url,
  6. build_postgres_engine,
  7. prepare_known_service_import,
  8. )
  9. def test_agent_service_post_contract_aliases(
  10. tmp_path: Path,
  11. monkeypatch,
  12. ) -> None:
  13. prepare_known_service_import("agent-service")
  14. from app.bootstrap.app import create_app
  15. from app.db.models import Base
  16. from core_db import create_session_factory
  17. database_url = build_postgres_database_url(tmp_path, "agent-contracts")
  18. monkeypatch.setenv("AGENT_PLATFORM_DATABASE_URL", database_url)
  19. monkeypatch.setenv("AGENT_PLATFORM_REDIS_URL", "")
  20. engine = build_postgres_engine(database_url)
  21. Base.metadata.create_all(engine)
  22. app = create_app()
  23. app.state.session_factory = create_session_factory(engine)
  24. client = build_fastapi_test_client(app)
  25. create_response = client.post(
  26. "/agents",
  27. json={"name": "Contract Agent", "agent_type": "assistant"},
  28. )
  29. assert create_response.status_code == 200
  30. agent = create_response.json()
  31. list_response = client.post("/agents/list", json={})
  32. assert list_response.status_code == 200
  33. assert any(item["id"] == agent["id"] for item in list_response.json())
  34. detail_response = client.post("/agents/detail", json={"agent_id": agent["id"]})
  35. assert detail_response.status_code == 200
  36. assert detail_response.json()["name"] == "Contract Agent"
  37. config_response = client.post(
  38. "/agents/configs/create",
  39. json={
  40. "agent_id": agent["id"],
  41. "role": "assistant",
  42. "system_prompt": "You are a contract test agent.",
  43. "model_config": {"model": "test-model"},
  44. "memory_policy": {"enabled": False},
  45. "tool_refs": [],
  46. "skill_refs": [],
  47. },
  48. )
  49. assert config_response.status_code == 200
  50. config = config_response.json()
  51. run_response = client.post(
  52. "/agents/runs",
  53. json={
  54. "agent_id": agent["id"],
  55. "agent_config_id": config["id"],
  56. "input_text": "hello",
  57. },
  58. )
  59. assert run_response.status_code == 200
  60. run = run_response.json()
  61. runs_response = client.post("/agents/runs/list", json={"agent_id": agent["id"]})
  62. assert runs_response.status_code == 200
  63. assert runs_response.json()[0]["id"] == run["id"]
  64. execute_response = client.post(
  65. "/agents/runs/execute",
  66. json={"agent_run_id": run["id"], "worker_key": "contract-worker", "dry_run": True},
  67. )
  68. assert execute_response.status_code == 200
  69. assert execute_response.json()["dry_run"] is True
  70. assert execute_response.json()["run"]["status"] == "completed"
  71. delete_response = client.post("/agents/delete", json={"agent_id": agent["id"]})
  72. assert delete_response.status_code == 200
  73. assert delete_response.json() == {"deleted": True, "agent_id": agent["id"], "agent_run_id": None}
  74. def test_session_service_post_contract_aliases(
  75. tmp_path: Path,
  76. monkeypatch,
  77. ) -> None:
  78. prepare_known_service_import("session-service")
  79. from app.bootstrap.app import create_app
  80. from app.db.models import Base
  81. from core_db import create_session_factory
  82. database_url = build_postgres_database_url(tmp_path, "session-contracts")
  83. monkeypatch.setenv("AGENT_PLATFORM_DATABASE_URL", database_url)
  84. engine = build_postgres_engine(database_url)
  85. Base.metadata.create_all(engine)
  86. app = create_app()
  87. app.state.session_factory = create_session_factory(engine)
  88. client = build_fastapi_test_client(app)
  89. create_response = client.post(
  90. "/sessions",
  91. json={"app_id": "app_contract", "user_id": "user_contract", "title": "Contract Chat"},
  92. )
  93. assert create_response.status_code == 200
  94. session = create_response.json()
  95. list_response = client.post("/sessions/list", json={"app_id": "app_contract"})
  96. assert list_response.status_code == 200
  97. assert list_response.json()[0]["id"] == session["id"]
  98. message_response = client.post(
  99. "/sessions/messages",
  100. json={"session_id": session["id"], "role": "user", "content_text": "hello"},
  101. )
  102. assert message_response.status_code == 200
  103. messages_response = client.post("/sessions/messages/list", json={"session_id": session["id"]})
  104. assert messages_response.status_code == 200
  105. assert messages_response.json()[0]["content_text"] == "hello"
  106. request_response = client.post(
  107. "/sessions/run-requests",
  108. json={
  109. "session_id": session["id"],
  110. "app_config_id": "appc_contract",
  111. "workflow_config_id": "wfc_contract",
  112. },
  113. )
  114. assert request_response.status_code == 200
  115. requests_response = client.post(
  116. "/sessions/run-requests/list",
  117. json={"session_id": session["id"]},
  118. )
  119. assert requests_response.status_code == 200
  120. assert requests_response.json()[0]["session_id"] == session["id"]
  121. def test_gateway_api_key_post_contract_aliases(
  122. tmp_path: Path,
  123. monkeypatch,
  124. ) -> None:
  125. prepare_known_service_import("api-gateway")
  126. from app.bootstrap.app import create_app
  127. from app.db.models import Base
  128. from core_db import create_session_factory
  129. database_url = build_postgres_database_url(tmp_path, "gateway-contracts")
  130. monkeypatch.setenv("AGENT_PLATFORM_DATABASE_URL", database_url)
  131. monkeypatch.setenv("AGENT_PLATFORM_REDIS_URL", "")
  132. engine = build_postgres_engine(database_url)
  133. Base.metadata.create_all(engine)
  134. app = create_app()
  135. app.state.session_factory = create_session_factory(engine)
  136. client = build_fastapi_test_client(app)
  137. create_response = client.post("/gateway/api-keys", json={"name": "Contract Key"})
  138. assert create_response.status_code == 200
  139. api_key = create_response.json()
  140. assert api_key["api_key"]
  141. list_response = client.post("/gateway/api-keys/list", json={})
  142. assert list_response.status_code == 200
  143. assert list_response.json()[0]["id"] == api_key["id"]
  144. status_response = client.post(
  145. "/gateway/api-keys/status",
  146. json={"api_key_id": api_key["id"], "status": "revoked"},
  147. )
  148. assert status_response.status_code == 200
  149. assert status_response.json()["status"] == "revoked"
  150. def test_human_event_scheduler_post_contract_aliases(
  151. tmp_path: Path,
  152. monkeypatch,
  153. ) -> None:
  154. prepare_known_service_import("human-service")
  155. from app.bootstrap.app import create_app as create_human_app
  156. from app.db.models import Base as HumanBase
  157. from core_db import create_session_factory
  158. human_database_url = build_postgres_database_url(tmp_path, "human-contracts")
  159. monkeypatch.setenv("AGENT_PLATFORM_DATABASE_URL", human_database_url)
  160. human_engine = build_postgres_engine(human_database_url)
  161. HumanBase.metadata.create_all(human_engine)
  162. human_app = create_human_app()
  163. human_app.state.session_factory = create_session_factory(human_engine)
  164. human_client = build_fastapi_test_client(human_app)
  165. task_response = human_client.post(
  166. "/human/tasks",
  167. json={
  168. "task_type": "approval",
  169. "title": "Approve deployment",
  170. "assigned_to": "operator",
  171. "run_id": "run_contract",
  172. },
  173. )
  174. assert task_response.status_code == 200
  175. task = task_response.json()
  176. assert human_client.post("/human/tasks/list", json={"assigned_to": "operator"}).json()[0]["id"] == task["id"]
  177. assert human_client.post("/human/tasks/detail", json={"human_task_id": task["id"]}).json()["id"] == task["id"]
  178. claim_response = human_client.post(
  179. "/human/tasks/claim",
  180. json={"human_task_id": task["id"], "claimed_by": "operator"},
  181. )
  182. assert claim_response.status_code == 200
  183. assert claim_response.json()["status"] == "claimed"
  184. complete_response = human_client.post(
  185. "/human/tasks/complete",
  186. json={
  187. "human_task_id": task["id"],
  188. "status": "completed",
  189. "response_payload_json": {"approved": True},
  190. },
  191. )
  192. assert complete_response.status_code == 200
  193. assert complete_response.json()["response_payload_json"] == {"approved": True}
  194. prepare_known_service_import("event-service")
  195. from app.bootstrap.app import create_app as create_event_app
  196. from app.db.models import Base as EventBase
  197. event_database_url = build_postgres_database_url(tmp_path, "event-contracts")
  198. monkeypatch.setenv("AGENT_PLATFORM_DATABASE_URL", event_database_url)
  199. event_engine = build_postgres_engine(event_database_url)
  200. EventBase.metadata.create_all(event_engine)
  201. event_app = create_event_app()
  202. event_app.state.session_factory = create_session_factory(event_engine)
  203. event_client = build_fastapi_test_client(event_app)
  204. publish_response = event_client.post(
  205. "/events",
  206. json={
  207. "event_type": "contract.created",
  208. "source_service": "test",
  209. "aggregate_type": "contract",
  210. "aggregate_id": "contract_1",
  211. },
  212. )
  213. assert publish_response.status_code == 200
  214. event = publish_response.json()
  215. assert event_client.post("/events/list", json={"event_type": "contract.created"}).json()[0]["id"] == event["id"]
  216. delivery_response = event_client.post(
  217. "/events/delivery-status",
  218. json={"event_record_id": event["id"], "status": "published"},
  219. )
  220. assert delivery_response.status_code == 200
  221. assert delivery_response.json()["status"] == "published"
  222. assert event_client.post("/events/stats", json={}).status_code == 200
  223. prepare_known_service_import("scheduler-service")
  224. from app.bootstrap.app import create_app as create_scheduler_app
  225. from app.db.models import Base as SchedulerBase
  226. scheduler_database_url = build_postgres_database_url(tmp_path, "scheduler-contracts")
  227. monkeypatch.setenv("AGENT_PLATFORM_DATABASE_URL", scheduler_database_url)
  228. monkeypatch.setenv("AGENT_PLATFORM_REDIS_URL", "")
  229. scheduler_engine = build_postgres_engine(scheduler_database_url)
  230. SchedulerBase.metadata.create_all(scheduler_engine)
  231. scheduler_app = create_scheduler_app()
  232. scheduler_app.state.session_factory = create_session_factory(scheduler_engine)
  233. scheduler_client = build_fastapi_test_client(scheduler_app)
  234. job_response = scheduler_client.post(
  235. "/scheduler/jobs",
  236. json={
  237. "job_type": "agent",
  238. "name": "Run agent",
  239. "schedule_time": (datetime.utcnow() + timedelta(minutes=5)).isoformat(),
  240. },
  241. )
  242. assert job_response.status_code == 200
  243. job = job_response.json()
  244. assert scheduler_client.post("/scheduler/jobs/list", json={"job_type": "agent"}).json()[0]["id"] == job["id"]
  245. status_response = scheduler_client.post(
  246. "/scheduler/jobs/status",
  247. json={"job_id": job["id"], "status": "cancelled"},
  248. )
  249. assert status_response.status_code == 200
  250. assert status_response.json()["status"] == "cancelled"