"""DevOps Engineer Agent.""" from __future__ import annotations from pydantic import BaseModel from ..prompts import PROMPTS, build_user_prompt from ..schemas import DevopsOutput, ProjectContext from .base import ( BaseAgent, RevisionInstruction, project_context_payload, revision_instruction_text, ) from .digest import ( condense_context, digest_architecture, digest_database, digest_requirements, dumps, summary_or_digest, ) class DevOpsAgent(BaseAgent): """Builds the deployment stack from the architecture and database. Deliberately does not read the API design: the endpoint list does not change a Dockerfile, a compose file or a CI workflow, and dropping it lets DevOps run concurrently with the API agent instead of waiting behind it. """ name = "devops" output_schema: type[BaseModel] = DevopsOutput system_prompt = PROMPTS["devops"].system async def _execute( self, context: ProjectContext, revision: RevisionInstruction | None = None ) -> DevopsOutput: user_prompt = build_user_prompt( "devops", project_context=dumps( condense_context(project_context_payload(context), downstream=True) ), requirements=summary_or_digest( context, "requirements", digest_requirements(context.requirements or {}) ), architecture=summary_or_digest( context, "architecture", digest_architecture(context.architecture or {}) ), database=summary_or_digest( context, "database", digest_database(context.database or {}) ), ) if revision is not None: user_prompt += revision_instruction_text(revision) return await self._llm.generate( self.system_prompt, user_prompt, DevopsOutput, stats=self._stats )