feat: backend orkestrasyonunu ve arac entegrasyonlarini genislet

This commit is contained in:
2026-03-22 04:45:43 +03:00
parent d07bc365f5
commit 5f4c19a18d
25 changed files with 3750 additions and 82 deletions

View File

@@ -1,3 +1,4 @@
import httpx
from typing import Any
from app.tools.base import Tool
@@ -7,12 +8,119 @@ class BraveSearchTool(Tool):
name = "brave_search"
description = "Search the web with Brave Search."
async def run(self, payload: dict[str, Any]) -> dict[str, Any]:
query = str(payload.get("query", "")).strip()
def __init__(self, api_key: str) -> None:
self.api_key = api_key
def parameters_schema(self) -> dict[str, Any]:
return {
"tool": self.name,
"status": "stub",
"query": query,
"message": "Brave Search integration is not wired yet.",
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The web search query.",
},
"count": {
"type": "integer",
"description": "Optional number of results from 1 to 10.",
"minimum": 1,
"maximum": 10,
},
"mode": {
"type": "string",
"description": "Search mode: web or images.",
"enum": ["web", "images"],
},
},
"required": ["query"],
"additionalProperties": False,
}
async def run(self, payload: dict[str, Any]) -> dict[str, Any]:
query = str(payload.get("query", "")).strip()
count = int(payload.get("count", 5) or 5)
count = max(1, min(10, count))
mode = str(payload.get("mode", "web") or "web").strip().lower()
if mode not in {"web", "images"}:
mode = "web"
if not query:
return {
"tool": self.name,
"status": "error",
"message": "Query is required.",
}
if not self.api_key:
return {
"tool": self.name,
"status": "error",
"query": query,
"message": "Brave Search API key is not configured.",
}
try:
async with httpx.AsyncClient(timeout=15.0) as client:
response = await client.get(
"https://api.search.brave.com/res/v1/images/search"
if mode == "images"
else "https://api.search.brave.com/res/v1/web/search",
headers={
"Accept": "application/json",
"Accept-Encoding": "gzip",
"X-Subscription-Token": self.api_key,
},
params={
"q": query,
"count": count,
"search_lang": "en",
"country": "us",
},
)
response.raise_for_status()
except httpx.HTTPError as exc:
return {
"tool": self.name,
"status": "error",
"query": query,
"message": str(exc),
}
payload_json = response.json()
if mode == "images":
images = []
for item in payload_json.get("results", [])[:count]:
images.append(
{
"title": item.get("title", ""),
"url": item.get("url", ""),
"source": item.get("source", ""),
"thumbnail": item.get("thumbnail", {}).get("src", "") if isinstance(item.get("thumbnail"), dict) else "",
"properties_url": item.get("properties", {}).get("url", "") if isinstance(item.get("properties"), dict) else "",
}
)
return {
"tool": self.name,
"status": "ok",
"mode": mode,
"query": query,
"images": images,
"total_results": len(images),
}
results = []
for item in payload_json.get("web", {}).get("results", [])[:count]:
results.append(
{
"title": item.get("title", ""),
"url": item.get("url", ""),
"description": item.get("description", ""),
}
)
return {
"tool": self.name,
"status": "ok",
"mode": mode,
"query": query,
"results": results,
"total_results": len(results),
}