"""ADK Artifact Management for GCP Solution Architecture Agent. Uses google.adk.artifacts.ArtifactRepository backed by local filesystem and PostgreSQL persistence. """ import logging from pathlib import Path from typing import Any, Dict, Optional, List from app.adk.compat import Artifact, ArtifactRepository from app.database import get_db_manager logger = logging.getLogger(__name__) class PostgresArtifactRepository(ArtifactRepository): """ADK Artifact Repository with PostgreSQL database & filesystem synchronization.""" def __init__(self, base_dir: Optional[Path] = None) -> None: super().__init__() self.base_dir = base_dir or Path(".").resolve() self.db_manager = get_db_manager() def save_solution_artifacts(self, execution_id: str, state: Dict[str, Any]) -> List[Artifact]: """Write workflow execution output artifacts to disk and PostgreSQL database.""" saved_artifacts: List[Artifact] = [] artifact_mapping = [ # Structured scalable active deliverables ("source_discovery_doc", "deliverables/as-is/source-architecture.md", "markdown"), ("source_mermaid_diagram", "deliverables/as-is/source-architecture.mmd", "mermaid"), ("requirements_doc", "deliverables/target/requirements.md", "markdown"), ("architecture_doc", "deliverables/target/architecture.md", "markdown"), ("mermaid_diagram", "deliverables/target/architecture.mmd", "mermaid"), ("terraform_code", "terraform/main.tf", "hcl"), ("validation_results", "deliverables/validation/validation-results.md", "markdown"), ("solution_guide", "deliverables/guides/solution-architecture-guide.md", "markdown"), # Per-execution isolated deliverables for scalable history tracking ("source_discovery_doc", f"deliverables/executions/{execution_id}/as-is/source-architecture.md", "markdown"), ("source_mermaid_diagram", f"deliverables/executions/{execution_id}/as-is/source-architecture.mmd", "mermaid"), ("requirements_doc", f"deliverables/executions/{execution_id}/target/requirements.md", "markdown"), ("architecture_doc", f"deliverables/executions/{execution_id}/target/architecture.md", "markdown"), ("mermaid_diagram", f"deliverables/executions/{execution_id}/target/architecture.mmd", "mermaid"), ("validation_results", f"deliverables/executions/{execution_id}/validation/validation-results.md", "markdown"), ("solution_guide", f"deliverables/executions/{execution_id}/guides/solution-architecture-guide.md", "markdown"), # Mirror docs for specification compatibility ("source_discovery_doc", "docs/source-architecture.md", "markdown"), ("requirements_doc", "docs/requirements.md", "markdown"), ("architecture_doc", "docs/architecture.md", "markdown"), ] for state_key, rel_path, art_type in artifact_mapping: content = state.get(state_key) if not content: continue full_path = self.base_dir / rel_path full_path.parent.mkdir(parents=True, exist_ok=True) full_path.write_text(content, encoding="utf-8") # Save in ADK memory store art = self.save_artifact(art_type, str(rel_path), content) saved_artifacts.append(art) # Persist to PostgreSQL database self.db_manager.save_artifact( artifact_id=art.artifact_id, execution_id=execution_id, artifact_type=art_type, file_path=str(rel_path), content=content, ) logger.info("Persisted ADK artifact '%s' (%s) to DB and %s", art_type, art.artifact_id, rel_path) return saved_artifacts