"""FastAPI route registration for resume editing and optimization.""" from fastapi import FastAPI from fastapi.responses import StreamingResponse from .agent import ResumeAgent from .fsm import FSMError from .models import ActionResponse, OptimizeEntryRequest, OptimizeRequest, ResumePatchRequest from .optimization_models import ( OptimizationRunView, OptimizationStartRequest, TargetPositionRequest, ) from .resume_api_models import SkillRecommendationRequest, SkillRecommendationResponse def register_resume_routes(application: FastAPI, agent: ResumeAgent, prefix: str) -> None: @application.patch( f"{prefix}/sessions/{{session_id}}/resume", response_model=ActionResponse, tags=["resume-agent"], ) def patch_resume(session_id: str, request: ResumePatchRequest) -> ActionResponse: return agent.patch_resume(session_id, request) @application.post( f"{prefix}/sessions/{{session_id}}/resume/profile-summary/generate", response_model=ActionResponse, tags=["resume-agent"], ) def generate_profile_summary(session_id: str) -> ActionResponse: return agent.generate_profile_summary(session_id) @application.post( f"{prefix}/sessions/{{session_id}}/resume/profile-summary/confirm", response_model=ActionResponse, tags=["resume-agent"], ) def confirm_profile_summary(session_id: str) -> ActionResponse: return agent.confirm_profile_summary(session_id) @application.post( f"{prefix}/sessions/{{session_id}}/resume/profile-summary/reject", response_model=ActionResponse, tags=["resume-agent"], ) def reject_profile_summary(session_id: str) -> ActionResponse: return agent.reject_profile_summary(session_id) @application.post( f"{prefix}/sessions/{{session_id}}/resume/skills/recommend", response_model=SkillRecommendationResponse, tags=["resume-agent"], ) def recommend_skills( session_id: str, request: SkillRecommendationRequest ) -> SkillRecommendationResponse: return SkillRecommendationResponse( candidates=agent.recommend_skills(session_id, request.question) ) @application.post( f"{prefix}/sessions/{{session_id}}/resume/optimize", response_model=ActionResponse, tags=["resume-agent"], ) def optimize_entry(session_id: str, request: OptimizeRequest) -> ActionResponse: return agent.optimize_entry(session_id, request) @application.post( f"{prefix}/sessions/{{session_id}}/resume/optimize/confirm", response_model=ActionResponse, tags=["resume-agent"], ) def confirm_optimize(session_id: str, request: OptimizeEntryRequest) -> ActionResponse: return agent.confirm_optimize(session_id, request) @application.post( f"{prefix}/sessions/{{session_id}}/resume/optimize/reject", response_model=ActionResponse, tags=["resume-agent"], ) def reject_optimize(session_id: str, request: OptimizeEntryRequest) -> ActionResponse: return agent.reject_optimize(session_id, request) @application.post( f"{prefix}/sessions/{{session_id}}/resume/optimize/undo", response_model=ActionResponse, tags=["resume-agent"], ) def undo_optimize(session_id: str, request: OptimizeEntryRequest) -> ActionResponse: return agent.undo_optimize(session_id, request) @application.post( f"{prefix}/sessions/{{session_id}}/target-position", tags=["resume-agent"], ) def set_session_target_position( session_id: str, request: TargetPositionRequest ) -> dict[str, object]: return agent.set_target_position(session_id, request.target_position) @application.post( f"{prefix}/sessions/{{session_id}}/resume/optimize/light", response_model=OptimizationRunView, tags=["resume-agent"], ) def optimize_light(session_id: str, request: OptimizationStartRequest) -> OptimizationRunView: limiter = getattr(application.state, "light_opt_limiter", None) if limiter is not None and not limiter.allow(session_id): raise FSMError( "rate_limited", "操作过于频繁,请稍后再试(轻度优化每小时最多 20 次)。", status_code=429, ) return agent.optimize_light(session_id, request) @application.get( f"{prefix}/sessions/{{session_id}}/resume/optimize/runs/active", response_model=list[OptimizationRunView], tags=["resume-agent"], ) def list_active_optimization_runs(session_id: str) -> list[OptimizationRunView]: return agent.list_active_optimization_runs(session_id) @application.post( f"{prefix}/sessions/{{session_id}}/resume/optimize/runs/{{run_id}}/confirm", response_model=OptimizationRunView, tags=["resume-agent"], ) def confirm_deep_optimization(session_id: str, run_id: str) -> OptimizationRunView: return agent.confirm_deep_optimization(session_id, run_id) @application.post( f"{prefix}/sessions/{{session_id}}/resume/optimize/runs/{{run_id}}/reject", response_model=OptimizationRunView, tags=["resume-agent"], ) def reject_optimization(session_id: str, run_id: str) -> OptimizationRunView: return agent.reject_optimization(session_id, run_id)