api.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. from __future__ import annotations
  2. from fastapi import FastAPI, HTTPException
  3. from content_agent.run_service import RunService
  4. from content_agent.schemas import (
  5. JsonFileResponse,
  6. RecordsResponse,
  7. RunStartRequest,
  8. RunStartResponse,
  9. RunSummaryResponse,
  10. ValidationResponse,
  11. )
  12. app = FastAPI(title="Content Agent V1")
  13. service = RunService()
  14. @app.post("/runs", response_model=RunStartResponse)
  15. def start_run(request: RunStartRequest) -> RunStartResponse:
  16. state = service.start_run(request)
  17. if state["status"] != "success":
  18. raise HTTPException(status_code=500, detail=state.get("errors", ["run failed"]))
  19. trace_id = state["trace_id"]
  20. return RunStartResponse(
  21. trace_id=trace_id,
  22. status=state["status"],
  23. policy_bundle_version=state["policy_bundle_version"],
  24. platform=state["platform"],
  25. platform_mode=state["platform_mode"],
  26. output_dir=str(service.runtime.run_dir(trace_id)),
  27. )
  28. @app.get("/runs/{trace_id}", response_model=RunSummaryResponse)
  29. def get_run(trace_id: str) -> RunSummaryResponse:
  30. _ensure_run_exists(trace_id)
  31. return RunSummaryResponse(**service.get_summary(trace_id))
  32. @app.get("/runs/{trace_id}/candidates", response_model=RecordsResponse)
  33. def get_candidates(trace_id: str) -> RecordsResponse:
  34. return _jsonl_response(trace_id, "candidate_pool.jsonl")
  35. @app.get("/runs/{trace_id}/rule-decisions", response_model=RecordsResponse)
  36. def get_rule_decisions(trace_id: str) -> RecordsResponse:
  37. return _jsonl_response(trace_id, "rule_decisions.jsonl")
  38. @app.get("/runs/{trace_id}/source-edges", response_model=RecordsResponse)
  39. def get_source_edges(trace_id: str) -> RecordsResponse:
  40. return _jsonl_response(trace_id, "source_edges.jsonl")
  41. @app.get("/runs/{trace_id}/final-output", response_model=JsonFileResponse)
  42. def get_final_output(trace_id: str) -> JsonFileResponse:
  43. return _json_response(trace_id, "final_output.json")
  44. @app.get("/runs/{trace_id}/strategy-review", response_model=JsonFileResponse)
  45. def get_strategy_review(trace_id: str) -> JsonFileResponse:
  46. _ensure_run_exists(trace_id)
  47. return JsonFileResponse(trace_id=trace_id, data=service.strategy_review(trace_id))
  48. @app.get("/runs/{trace_id}/validation", response_model=ValidationResponse)
  49. def get_validation(trace_id: str) -> ValidationResponse:
  50. _ensure_run_exists(trace_id)
  51. return ValidationResponse(**service.validate_run(trace_id))
  52. def _jsonl_response(trace_id: str, filename: str) -> RecordsResponse:
  53. _ensure_run_exists(trace_id)
  54. return RecordsResponse(trace_id=trace_id, records=service.read_jsonl(trace_id, filename))
  55. def _json_response(trace_id: str, filename: str) -> JsonFileResponse:
  56. _ensure_run_exists(trace_id)
  57. return JsonFileResponse(trace_id=trace_id, data=service.read_json(trace_id, filename))
  58. def _ensure_run_exists(trace_id: str) -> None:
  59. if not service.runtime.run_dir(trace_id).exists():
  60. raise HTTPException(status_code=404, detail=f"run not found: {trace_id}")