Implement AI orchestration wedding demo
This commit is contained in:
3
backend/app/executor/README.md
Normal file
3
backend/app/executor/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Executor
|
||||
|
||||
Generates exact HTTP call descriptions for approved pending actions. It resolves generated tools, path parameters, headers, URL, JSON body, and cURL, but never sends the request to the Wed backend.
|
||||
1
backend/app/executor/__init__.py
Normal file
1
backend/app/executor/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Action execution services."""
|
||||
57
backend/app/executor/action_executor.py
Normal file
57
backend/app/executor/action_executor.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.ai.tool_registry import ToolRegistry
|
||||
from app.config import get_settings
|
||||
from app.domain.schemas import ActionStatus
|
||||
from app.infrastructure.database import PendingAction
|
||||
|
||||
|
||||
class ActionExecutor:
|
||||
"""Generates approved API calls without sending them to the Wed backend."""
|
||||
|
||||
def __init__(self, registry: ToolRegistry) -> None:
|
||||
self.registry = registry
|
||||
self.settings = get_settings()
|
||||
self.base_url = self.settings.wed_api_base_url.rstrip("/")
|
||||
|
||||
async def execute(self, session: Session, action: PendingAction) -> PendingAction:
|
||||
if action.status != ActionStatus.APPROVED:
|
||||
raise ValueError("Only approved actions can be converted into API calls.")
|
||||
tool = self.registry.get(action.tool)
|
||||
if not tool:
|
||||
raise ValueError(f"Unknown tool: {action.tool}")
|
||||
path = tool.path
|
||||
body = dict(action.payload)
|
||||
for param in tool.path_params:
|
||||
value = body.pop(param, None)
|
||||
if value is None:
|
||||
raise ValueError(f"Missing path parameter: {param}")
|
||||
path = path.replace(f"{{{param}}}", str(value))
|
||||
headers = {}
|
||||
if self.settings.wed_api_bearer_token:
|
||||
headers["Authorization"] = "Bearer <configured WED_API_BEARER_TOKEN>"
|
||||
action.execution_result = {
|
||||
"generated_only": True,
|
||||
"method": tool.method,
|
||||
"url": f"{self.base_url}{path}",
|
||||
"path": path,
|
||||
"headers": headers,
|
||||
"json": body,
|
||||
"curl": self._curl(tool.method, f"{self.base_url}{path}", headers, body),
|
||||
}
|
||||
session.add(action)
|
||||
session.commit()
|
||||
session.refresh(action)
|
||||
return action
|
||||
|
||||
def _curl(self, method: str, url: str, headers: dict[str, str], body: dict[str, Any]) -> str:
|
||||
import json
|
||||
import shlex
|
||||
|
||||
parts = ["curl", "-X", method, url, "-H", "Content-Type: application/json"]
|
||||
for key, value in headers.items():
|
||||
parts.extend(["-H", f"{key}: {value}"])
|
||||
parts.extend(["--data", json.dumps(body, default=str)])
|
||||
return " ".join(shlex.quote(part) for part in parts)
|
||||
Reference in New Issue
Block a user