deploy-ready-copilot / docs_agent.py
Priyanshujha18's picture
feat: Interactive Deployment & Professional README
6e1b170
"""Context7-powered documentation agent for deployment readiness."""
from __future__ import annotations
import os
from typing import Any, Dict, List, Optional
from enhanced_mcp_client import EnhancedMCPClient
from schemas import ReadinessPlan, ReadinessRequest
class DocumentationLookupAgent:
"""Uses Context7 MCP to lookup framework/platform documentation."""
def __init__(self):
self.mcp_client = EnhancedMCPClient()
async def extract_framework_from_request(self, request: ReadinessRequest) -> Optional[str]:
"""Extract framework/library from code summary with multi-framework support."""
code_lower = request.code_summary.lower()
infra_lower = (request.infra_notes or "").lower()
combined = f"{code_lower} {infra_lower}"
# Extended framework detection with priority order
frameworks = {
# React ecosystem (highest priority)
"next.js": "next.js",
"nextjs": "next.js",
"remix": "remix",
"gatsby": "gatsby",
# Python frameworks
"django": "django",
"fastapi": "fastapi",
"flask": "flask",
"fastapi": "fastapi",
"starlette": "starlette",
# Node.js frameworks
"express": "express",
"nestjs": "nestjs",
"koa": "koa",
"hapi": "hapi",
# Frontend frameworks
"react": "react",
"vue": "vue",
"angular": "angular",
"svelte": "svelte",
"nuxt": "nuxt",
# Other
"spring": "spring",
"rails": "rails",
"laravel": "laravel",
}
# Check for multiple frameworks (return the most specific one)
detected = []
for key, framework in frameworks.items():
if key in combined:
detected.append((len(key), framework)) # Prioritize longer matches
if detected:
# Return the most specific (longest) match
detected.sort(reverse=True, key=lambda x: x[0])
return detected[0][1]
return None
async def extract_platform_from_request(self, request: ReadinessRequest) -> Optional[str]:
"""Extract deployment platform from infra notes with multi-platform support."""
infra_lower = (request.infra_notes or "").lower()
code_lower = (request.code_summary or "").lower()
combined = f"{infra_lower} {code_lower}"
# Extended platform detection
platforms = {
# Serverless/Edge
"vercel": "vercel",
"netlify": "netlify",
"cloudflare": "cloudflare",
"cloudflare pages": "cloudflare",
# Cloud providers
"aws": "aws",
"amazon web services": "aws",
"azure": "azure",
"microsoft azure": "azure",
"gcp": "gcp",
"google cloud": "gcp",
"google cloud platform": "gcp",
# PaaS
"railway": "railway",
"render": "render",
"fly.io": "fly.io",
"flyio": "fly.io",
"heroku": "heroku",
"digitalocean": "digitalocean",
"digital ocean": "digitalocean",
# Containers/Orchestration
"kubernetes": "kubernetes",
"k8s": "kubernetes",
"docker": "docker",
"docker compose": "docker",
"docker-compose": "docker",
}
# Check for multiple platforms (return the most specific one)
detected = []
for key, platform in platforms.items():
if key in combined:
detected.append((len(key), platform))
if detected:
detected.sort(reverse=True, key=lambda x: x[0])
return detected[0][1]
return None
async def lookup_deployment_docs(
self, request: ReadinessRequest, plan: ReadinessPlan
) -> Dict[str, Any]:
"""Comprehensive documentation lookup for deployment readiness."""
framework = await self.extract_framework_from_request(request)
platform = await self.extract_platform_from_request(request)
docs_results = {
"framework": framework,
"platform": platform,
"lookups": []
}
if not framework and not platform:
docs_results["lookups"].append({
"type": "general",
"topic": "deployment best practices",
"status": "no_framework_detected"
})
return docs_results
# Lookup framework deployment docs
if framework:
framework_docs = await self.mcp_client.lookup_documentation(
framework, "deployment guide"
)
docs_results["lookups"].append({
"type": "framework_deployment",
"framework": framework,
"docs": framework_docs,
"status": "found" if framework_docs.get("success") else "not_found"
})
# Lookup platform-specific docs
if platform:
platform_docs = await self.mcp_client.lookup_documentation(
platform, "deployment configuration"
)
docs_results["lookups"].append({
"type": "platform_deployment",
"platform": platform,
"docs": platform_docs,
"status": "found" if platform_docs.get("success") else "not_found"
})
# Check dependency compatibility
if framework:
# Extract dependencies from code summary (simplified)
deps = [] # Would parse from package.json, requirements.txt, etc.
compat_check = await self.mcp_client.check_dependency_compatibility(
deps, framework
)
docs_results["lookups"].append({
"type": "dependency_compatibility",
"result": compat_check,
"status": "checked"
})
# Validate deployment configs
if platform:
config_validation = await self.mcp_client.validate_deployment_config(
"dockerfile", "", platform # Would have actual config content
)
docs_results["lookups"].append({
"type": "config_validation",
"result": config_validation,
"status": "validated"
})
# Get deployment runbook
if framework and platform:
runbook = await self.mcp_client.get_deployment_runbook(
framework, platform, "production"
)
docs_results["lookups"].append({
"type": "deployment_runbook",
"result": runbook,
"status": "generated"
})
# Environment variables check
if framework:
env_check = await self.mcp_client.check_environment_variables(
[], framework # Would extract from request
)
docs_results["lookups"].append({
"type": "environment_variables",
"result": env_check,
"status": "checked"
})
# Migration guide if needed
if framework:
migration_guide = await self.mcp_client.get_migration_guide(
framework, "database"
)
docs_results["lookups"].append({
"type": "migration_guide",
"result": migration_guide,
"status": "found"
})
# Observability setup
if framework and platform:
observability = await self.mcp_client.get_observability_setup(
framework, platform
)
docs_results["lookups"].append({
"type": "observability_setup",
"result": observability,
"status": "found"
})
return docs_results
def generate_readme(self, analysis: Dict[str, Any]) -> str:
"""Generate a professional README.md based on analysis."""
framework = analysis.get("framework", "Project")
summary = analysis.get("code_summary", "No summary available.")
dependencies = analysis.get("dependencies", [])
platform = analysis.get("platform", "Not configured")
# Badges
badges = f"![{framework}](https://img.shields.io/badge/{framework}-black?style=for-the-badge&logo={framework.lower()})\n"
if platform != "Not configured":
badges += f"![{platform}](https://img.shields.io/badge/{platform}-black?style=for-the-badge&logo={platform.lower()})\n"
readme = f"""# {framework.title()} Project
{badges}
## πŸš€ Overview
{summary}
## πŸ› οΈ Tech Stack
| Component | Details |
|-----------|---------|
| **Framework** | {framework} |
| **Platform** | {platform} |
| **Dependencies** | {len(dependencies)} packages |
## πŸ“¦ Installation
```bash
"""
if analysis.get("package_manager") == "npm":
readme += "npm install\nnpm run dev\n"
elif analysis.get("package_manager") == "pip":
readme += "pip install -r requirements.txt\npython app.py\n"
else:
readme += "# Install dependencies\n# Run application\n"
readme += """```
## 🚒 Deployment
This project is ready for deployment via **Deploy Ready Copilot**.
### Steps
1. Connect your GitHub repository.
2. Select your target platform ({platform}).
3. Click "Deploy".
---
*Generated by [Deploy Ready Copilot](https://huggingface.co/spaces/HIMANSHUKUMARJHA/deploy-ready-copilot)*
"""
return readme