test_team_service.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. from pathlib import Path
  2. from datetime import datetime
  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_team_service_post_contract_supports_team_configs_and_runs(
  10. tmp_path: Path,
  11. monkeypatch,
  12. ) -> None:
  13. prepare_known_service_import("team-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, "teams-api")
  18. monkeypatch.setenv("AGENT_PLATFORM_DATABASE_URL", database_url)
  19. monkeypatch.setenv("AGENT_PLATFORM_REDIS_URL", "")
  20. monkeypatch.setenv("AGENT_PLATFORM_AUTO_WORKER_ENABLED", "false")
  21. engine = build_postgres_engine(database_url)
  22. Base.metadata.create_all(engine)
  23. app = create_app()
  24. app.state.session_factory = create_session_factory(engine)
  25. client = build_fastapi_test_client(app)
  26. team_response = client.post(
  27. "/teams/create",
  28. json={
  29. "name": "Support Team",
  30. "description": "Handles support escalations",
  31. "teamType": "collaborative",
  32. "ownerUserId": "demo-user",
  33. },
  34. )
  35. assert team_response.status_code == 200
  36. team_payload = team_response.json()["data"]
  37. assert team_payload["name"] == "Support Team"
  38. assert team_payload["teamType"] == "collaborative"
  39. assert "code" not in team_payload
  40. config_response = client.post(
  41. "/teams/configs/create",
  42. json={
  43. "teamId": team_payload["id"],
  44. "coordinationMode": "supervisor",
  45. "objective": "Resolve the customer request",
  46. "memberRefs": [
  47. {
  48. "role": "worker",
  49. "agentId": "agent_support",
  50. "responsibility": "Draft the answer",
  51. }
  52. ],
  53. "policy": {
  54. "max_rounds": 3,
  55. "handoff": "supervisor",
  56. },
  57. },
  58. )
  59. assert config_response.status_code == 200
  60. config_payload = config_response.json()["data"]
  61. assert config_payload["teamId"] == team_payload["id"]
  62. assert config_payload["memberRefs"][0]["role"] == "executor"
  63. assert config_payload["memberRefs"][0]["member_key"] == "member_1"
  64. list_response = client.post(
  65. "/teams/list",
  66. json={"page": 1, "pageSize": 20, "keyword": "support"},
  67. )
  68. assert list_response.status_code == 200
  69. assert list_response.json()["data"]["total"] == 1
  70. configs_response = client.post(
  71. "/teams/configs/list",
  72. json={"page": 1, "pageSize": 20, "teamId": team_payload["id"]},
  73. )
  74. assert configs_response.status_code == 200
  75. assert configs_response.json()["data"]["total"] == 1
  76. run_response = client.post(
  77. "/teams/runs/create",
  78. json={
  79. "teamId": team_payload["id"],
  80. "teamConfigId": config_payload["id"],
  81. "inputText": "Help the customer reset MFA",
  82. },
  83. )
  84. assert run_response.status_code == 200
  85. run_payload = run_response.json()["data"]
  86. assert run_payload["teamId"] == team_payload["id"]
  87. assert run_payload["teamConfigId"] == config_payload["id"]
  88. assert run_payload["status"] == "queued"
  89. status_response = client.post(
  90. "/teams/runs/status",
  91. json={
  92. "teamRunId": run_payload["id"],
  93. "status": "completed",
  94. "workerKey": "test-worker",
  95. "outputText": "MFA reset steps prepared.",
  96. },
  97. )
  98. assert status_response.status_code == 200
  99. assert status_response.json()["data"]["status"] == "completed"
  100. runs_response = client.post(
  101. "/teams/runs/list",
  102. json={"page": 1, "pageSize": 20, "teamId": team_payload["id"]},
  103. )
  104. assert runs_response.status_code == 200
  105. assert runs_response.json()["data"]["total"] == 1
  106. update_response = client.post(
  107. "/teams/update",
  108. json={
  109. "teamId": team_payload["id"],
  110. "name": "Support Team Updated",
  111. "status": "active",
  112. },
  113. )
  114. assert update_response.status_code == 200
  115. assert update_response.json()["data"]["name"] == "Support Team Updated"
  116. assert update_response.json()["data"]["status"] == "active"
  117. delete_run_response = client.post(
  118. "/teams/runs/delete",
  119. json={"teamRunId": run_payload["id"]},
  120. )
  121. assert delete_run_response.status_code == 200
  122. assert delete_run_response.json()["data"]["deleted"] is True
  123. delete_config_response = client.post(
  124. "/teams/configs/delete",
  125. json={"configId": config_payload["id"]},
  126. )
  127. assert delete_config_response.status_code == 200
  128. assert delete_config_response.json()["data"]["deleted"] is True
  129. delete_team_response = client.post(
  130. "/teams/delete",
  131. json={"teamId": team_payload["id"]},
  132. )
  133. assert delete_team_response.status_code == 200
  134. assert delete_team_response.json()["data"]["deleted"] is True
  135. def test_team_service_compacts_member_context_between_agent_calls() -> None:
  136. prepare_known_service_import("team-service")
  137. from app.application.services import TeamApplicationService, TeamMemberRunResult
  138. from core_domain import AgentRunContract, TeamMemberContract
  139. service = TeamApplicationService(
  140. team_repository=None,
  141. team_config_repository=None,
  142. team_run_repository=None)
  143. result = TeamMemberRunResult(
  144. member=TeamMemberContract(
  145. member_key="member_1",
  146. agent_id="agent_1",
  147. role="supervisor",
  148. name="Planner"),
  149. run=AgentRunContract(
  150. id="run_1",
  151. agent_id="agent_1",
  152. agent_config_id="config_1",
  153. output_text="x" * 2000,
  154. output_json={
  155. "model": "demo-model",
  156. "finish_reason": "stop",
  157. "messages": [{"role": "user", "content": "large prompt"}],
  158. "raw_response_json": {"thinking": "hidden debug payload"},
  159. },
  160. status="completed",
  161. created_time=datetime.utcnow()))
  162. prior_output = service._compact_prior_output(result)
  163. member_json = service._member_result_to_json(result)
  164. assert prior_output["output_text"].endswith("[truncated]")
  165. assert prior_output["output_json"] == {
  166. "model": "demo-model",
  167. "finish_reason": "stop",
  168. "debug_payload_omitted": True,
  169. }
  170. assert "messages" not in member_json["output_json"]
  171. assert "raw_response_json" not in member_json["output_json"]