Implement AI orchestration wedding demo

This commit is contained in:
pelpanagiotis
2026-06-27 13:50:11 +03:00
commit 55d4fe95b4
67 changed files with 4736 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
import re
from typing import Any
from app.domain.schemas import ToolDefinition
def operation_name(method: str, path: str) -> str:
clean = path.strip("/").replace("{", "").replace("}", "")
parts = [part for part in re.split(r"[/_-]+", clean) if part and part != "id"]
resource = "_".join(parts)
verb = {"POST": "create", "PATCH": "update", "PUT": "replace", "GET": "get", "DELETE": "delete"}[method.upper()]
return f"{verb}_{resource}".rstrip("_")
def path_params(path: str) -> list[str]:
return re.findall(r"{([^}]+)}", path)
class OpenAPIToolGenerator:
"""Generates callable tool metadata from OpenAPI operations."""
def __init__(self, spec: dict[str, Any]) -> None:
self.spec = spec
def generate(self) -> list[ToolDefinition]:
tools: list[ToolDefinition] = []
for path, methods in self.spec.get("paths", {}).items():
for method, operation in methods.items():
upper = method.upper()
if upper not in {"POST", "PATCH", "PUT", "DELETE", "GET"}:
continue
request_schema = self._request_schema(operation)
params = path_params(path)
if not request_schema and upper in {"POST", "PATCH", "PUT"}:
continue
schema = request_schema or {"type": "object", "properties": {}}
if params:
schema = {
**schema,
"properties": {
**schema.get("properties", {}),
**{param: {"type": "string"} for param in params},
},
"required": list(dict.fromkeys([*schema.get("required", []), *params])),
}
tools.append(
ToolDefinition(
name=operation.get("operationId") or operation_name(upper, path),
description=operation.get("summary") or operation.get("description") or f"{upper} {path}",
method=upper,
path=path,
schema=schema,
required=schema.get("required", []),
path_params=params,
)
)
return tools
def _request_schema(self, operation: dict[str, Any]) -> dict[str, Any] | None:
body = operation.get("requestBody", {}).get("content", {}).get("application/json", {})
schema = body.get("schema")
if not schema:
return None
return self._resolve(schema)
def _resolve(self, schema: dict[str, Any]) -> dict[str, Any]:
ref = schema.get("$ref")
if not ref:
return schema
name = ref.split("/")[-1]
return self.spec.get("components", {}).get("schemas", {}).get(name, {})