This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
"""Workflows package."""
|
||||
|
||||
from .gcp_architecture_graph import create_agent, create_gcp_architecture_graph
|
||||
|
||||
__all__ = ["create_agent", "create_gcp_architecture_graph"]
|
||||
|
||||
BIN
app/workflows/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
app/workflows/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
app/workflows/__pycache__/gcp_architecture_graph.cpython-312.pyc
Normal file
BIN
app/workflows/__pycache__/gcp_architecture_graph.cpython-312.pyc
Normal file
Binary file not shown.
BIN
app/workflows/__pycache__/routes.cpython-312.pyc
Normal file
BIN
app/workflows/__pycache__/routes.cpython-312.pyc
Normal file
Binary file not shown.
56
app/workflows/gcp_architecture_graph.py
Normal file
56
app/workflows/gcp_architecture_graph.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""Dynamic LangGraph StateGraph Factory with Skill Injection."""
|
||||
|
||||
import logging
|
||||
from typing import Any, Callable
|
||||
from langgraph.graph import END, START, StateGraph
|
||||
from langgraph.graph.state import CompiledStateGraph
|
||||
|
||||
from app.config import get_settings
|
||||
from app.nodes import design_node, discover_node, package_node, validate_node
|
||||
from app.skills.loader import SkillLoader
|
||||
from app.states.state import GCPArchitectureState
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_gcp_architecture_graph(skill_loader: SkillLoader | None = None) -> CompiledStateGraph:
|
||||
"""Creates and compiles the 4-phase LangGraph StateGraph with dynamic local skill injection."""
|
||||
if skill_loader is None:
|
||||
settings = get_settings()
|
||||
skill_loader = SkillLoader(settings.SKILLS_DIR)
|
||||
skill_loader.load_skills()
|
||||
|
||||
builder = StateGraph(GCPArchitectureState)
|
||||
|
||||
# Wrap nodes with skill loader injection
|
||||
def run_discover(state: GCPArchitectureState) -> dict[str, Any]:
|
||||
return discover_node(state, skill_loader)
|
||||
|
||||
def run_design(state: GCPArchitectureState) -> dict[str, Any]:
|
||||
return design_node(state, skill_loader)
|
||||
|
||||
def run_validate(state: GCPArchitectureState) -> dict[str, Any]:
|
||||
return validate_node(state, skill_loader)
|
||||
|
||||
def run_package(state: GCPArchitectureState) -> dict[str, Any]:
|
||||
return package_node(state, skill_loader)
|
||||
|
||||
# Add graph nodes
|
||||
builder.add_node("discover", run_discover)
|
||||
builder.add_node("design", run_design)
|
||||
builder.add_node("validate", run_validate)
|
||||
builder.add_node("package", run_package)
|
||||
|
||||
# Add sequential workflow edges
|
||||
builder.add_edge(START, "discover")
|
||||
builder.add_edge("discover", "design")
|
||||
builder.add_edge("design", "validate")
|
||||
builder.add_edge("validate", "package")
|
||||
builder.add_edge("package", END)
|
||||
|
||||
return builder.compile()
|
||||
|
||||
|
||||
def create_agent(skill_loader: SkillLoader | None = None) -> CompiledStateGraph:
|
||||
"""Alias for create_gcp_architecture_graph to support standardized agent creation."""
|
||||
return create_gcp_architecture_graph(skill_loader)
|
||||
82
app/workflows/routes.py
Normal file
82
app/workflows/routes.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""Starlette REST Route Handlers for GCP Solution Architecture Agent."""
|
||||
|
||||
import logging
|
||||
from typing import Any, Dict
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
from app.card import AGENT_CARD
|
||||
from app.config import get_settings
|
||||
from app.skills.loader import SkillLoader
|
||||
from app.tools.validation_tools import validate_repository_artifacts
|
||||
from app.workflows.gcp_architecture_graph import create_agent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def health_check(request: Request) -> JSONResponse:
|
||||
"""GET /health - Operational health endpoint."""
|
||||
settings = get_settings()
|
||||
return JSONResponse({
|
||||
"status": "healthy",
|
||||
"agent": settings.AGENT_NAME,
|
||||
"version": settings.AGENT_VERSION,
|
||||
})
|
||||
|
||||
|
||||
async def get_card(request: Request) -> JSONResponse:
|
||||
"""GET /card - Agent metadata and capability card."""
|
||||
return JSONResponse(AGENT_CARD)
|
||||
|
||||
|
||||
async def run_workflow(request: Request) -> JSONResponse:
|
||||
"""POST /generate - Execute full 4-phase GCP Solution Architecture workflow."""
|
||||
try:
|
||||
body = await request.json() if request.headers.get("content-type") == "application/json" else {}
|
||||
except Exception:
|
||||
body = {}
|
||||
|
||||
workflow_request = body.get("request", "Default event-driven HTTP architecture")
|
||||
target_dir = body.get("target_dir", ".")
|
||||
|
||||
settings = get_settings()
|
||||
loader = SkillLoader(settings.SKILLS_DIR)
|
||||
loader.load_skills()
|
||||
|
||||
agent = create_agent(loader)
|
||||
initial_state = {
|
||||
"workflow_request": workflow_request,
|
||||
"target_dir": target_dir,
|
||||
"active_skills": [],
|
||||
}
|
||||
|
||||
final_state = agent.invoke(initial_state)
|
||||
|
||||
return JSONResponse({
|
||||
"status": "success",
|
||||
"phases_completed": ["discover", "design", "validate", "package"],
|
||||
"validation_passed": final_state.get("validation_passed", True),
|
||||
"artifacts": {
|
||||
"requirements_doc": final_state.get("requirements_doc"),
|
||||
"architecture_doc": final_state.get("architecture_doc"),
|
||||
"mermaid_diagram": final_state.get("mermaid_diagram"),
|
||||
"terraform_code": final_state.get("terraform_code"),
|
||||
"validation_results": final_state.get("validation_results"),
|
||||
"solution_guide": final_state.get("solution_guide"),
|
||||
},
|
||||
"active_skills": final_state.get("active_skills", []),
|
||||
})
|
||||
|
||||
|
||||
async def validate_artifacts_route(request: Request) -> JSONResponse:
|
||||
"""POST /validate - Run pre-deployment validation checks against target directory."""
|
||||
try:
|
||||
body = await request.json() if request.headers.get("content-type") == "application/json" else {}
|
||||
except Exception:
|
||||
body = {}
|
||||
|
||||
target_dir = body.get("target_dir", ".")
|
||||
result = validate_repository_artifacts.invoke({"target_dir": target_dir})
|
||||
|
||||
status_code = 200 if result.get("valid") else 400
|
||||
return JSONResponse(result, status_code=status_code)
|
||||
Reference in New Issue
Block a user