Добавлены все базовые файлы для запуска проекта

This commit is contained in:
Даниил
2026-09-19 15:19:31 +10:00
commit 34535ac579
23 changed files with 1903 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
"""The two HTTP contracts exposed by the supplied n8n workflows."""
from __future__ import annotations
import httpx
from config import Settings, require_webhook_url
class WebhookError(RuntimeError):
"""An n8n request failed or returned an unusable response."""
class N8NClient:
def __init__(
self,
settings: Settings,
transport: httpx.AsyncBaseTransport | None = None,
) -> None:
self.settings = settings
self._transport = transport
async def ask(self, message: str, collection_name: str, session_id: str) -> str:
message = message.strip()
collection_name = collection_name.strip()
if not message or not collection_name or not session_id:
raise ValueError("Укажите вопрос и коллекцию.")
url = require_webhook_url(self.settings.chat_webhook_url, "вопросов")
try:
async with httpx.AsyncClient(
transport=self._transport,
timeout=self.settings.chat_timeout_seconds,
) as client:
response = await client.post(
url,
json={
"message": message,
"collection_name": collection_name,
"session_id": session_id,
},
)
response.raise_for_status()
except httpx.TimeoutException as exc:
raise WebhookError("Время ожидания ответа истекло. Попробуйте ещё раз.") from exc
except httpx.HTTPStatusError as exc:
raise WebhookError(
f"Webhook вопросов вернул HTTP {exc.response.status_code}."
) from exc
except httpx.RequestError as exc:
raise WebhookError("Не удалось связаться с webhook вопросов.") from exc
answer = response.text.strip()
if not answer:
raise WebhookError("Webhook вопросов вернул пустой ответ.")
return answer
async def upload(self, filename: str, contents: bytes, collection_name: str) -> None:
collection_name = collection_name.strip()
if not collection_name:
raise ValueError("Укажите коллекцию.")
if not filename.lower().endswith(".md"):
raise ValueError("Можно загружать только файлы .md.")
if not contents:
raise ValueError("Выбранный файл пуст.")
if len(contents) > self.settings.max_file_bytes:
raise ValueError("Размер файла превышает допустимый предел.")
url = require_webhook_url(self.settings.upload_webhook_url, "загрузки")
try:
async with httpx.AsyncClient(
transport=self._transport,
timeout=self.settings.upload_timeout_seconds,
) as client:
response = await client.post(
url,
data={"collection_name": collection_name},
files={"file": (filename, contents, "text/markdown")},
)
response.raise_for_status()
except httpx.TimeoutException as exc:
raise WebhookError("Время ожидания загрузки истекло. Проверьте n8n перед повтором.") from exc
except httpx.HTTPStatusError as exc:
raise WebhookError(
f"Webhook загрузки вернул HTTP {exc.response.status_code}."
) from exc
except httpx.RequestError as exc:
raise WebhookError("Не удалось связаться с webhook загрузки.") from exc