from fastapi import APIRouter, HTTPException, Request, Depends from typing import List import logging import repo_city from schemas_agents import AgentPromptList, AgentPromptUpsertRequest, AgentPrompt router = APIRouter(prefix="/agents", tags=["agents"]) logger = logging.getLogger(__name__) @router.get("/{agent_id}/prompts", response_model=AgentPromptList) async def get_agent_prompts(agent_id: str): """ Отримати системні промти агента. """ try: # Check agent exists agent = await repo_city.get_agent_by_id(agent_id) if not agent: raise HTTPException(status_code=404, detail=f"Agent not found: {agent_id}") # Get prompts dict from repo prompts_dict = await repo_city.get_agent_prompts(agent_id) # Convert to list of AgentPrompt models prompts_list = [] valid_kinds = ["core", "safety", "governance", "tools"] for kind in valid_kinds: p_data = prompts_dict.get(kind) if p_data: prompts_list.append(AgentPrompt( kind=kind, content=p_data["content"], version=p_data["version"], updated_at=p_data["created_at"], # repo returns created_at as isoformat string or datetime? Repo returns isoformat string in dict note=p_data.get("note") )) else: # Should we return empty prompt structure or just skip? # The frontend expects 4 kinds. If we skip, frontend might need adjustment. # But AgentPrompt requires content. # Let's return empty content if missing, or just skip and let frontend handle default. # Frontend AgentSystemPromptsCard handles missing prompts gracefully? # Yes: const currentPrompt = systemPrompts?.[activeTab]; pass # However, the response model is AgentPromptList which has prompts: List[AgentPrompt]. # If we return a list, the frontend needs to map it back to dict by kind. # The user requested GET returns AgentPromptList. # Wait, the frontend `useAgentPrompts` implementation in the prompt suggests: # return { prompts: data?.prompts ?? [] } # And the component maps it: # for (const p of prompts) { map[p.kind] = p.content; } return AgentPromptList(agent_id=agent_id, prompts=prompts_list) except HTTPException: raise except Exception as e: logger.error(f"Failed to get agent prompts: {e}") raise HTTPException(status_code=500, detail="Failed to get agent prompts") @router.put("/{agent_id}/prompts", response_model=AgentPromptList) async def upsert_agent_prompts_endpoint(agent_id: str, payload: AgentPromptUpsertRequest, request: Request): """ Оновити системні промти агента (bulk). """ try: # Check agent exists agent = await repo_city.get_agent_by_id(agent_id) if not agent: raise HTTPException(status_code=404, detail=f"Agent not found: {agent_id}") # TODO: Get user from auth created_by = "ARCHITECT" # Upsert # Convert Pydantic models to dicts for repo prompts_to_update = [] for p in payload.prompts: prompts_to_update.append({ "kind": p.kind, "content": p.content, "note": p.note }) if not prompts_to_update: # Nothing to update, just return current state pass else: await repo_city.upsert_agent_prompts(agent_id, prompts_to_update, created_by) # Return updated state # Re-use get logic prompts_dict = await repo_city.get_agent_prompts(agent_id) prompts_list = [] valid_kinds = ["core", "safety", "governance", "tools"] for kind in valid_kinds: p_data = prompts_dict.get(kind) if p_data: prompts_list.append(AgentPrompt( kind=kind, content=p_data["content"], version=p_data["version"], updated_at=p_data["created_at"], note=p_data.get("note") )) return AgentPromptList(agent_id=agent_id, prompts=prompts_list) except HTTPException: raise except Exception as e: logger.error(f"Failed to upsert agent prompts: {e}") raise HTTPException(status_code=500, detail="Failed to upsert agent prompts")