From 9f4746005373d4b60694ce88909c8a32145c737d Mon Sep 17 00:00:00 2001 From: h Date: Fri, 28 Aug 2026 17:57:24 +0200 Subject: [PATCH] feat(config): telegram frontend as home of master and branch --- config.py | 19 +++++++++++++++++-- uv.lock | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/config.py b/config.py index df0f26f..81b7d71 100644 --- a/config.py +++ b/config.py @@ -15,6 +15,7 @@ from beaver_gateway.frontends.api import ApiFrontend from beaver_gateway.frontends.base import Frontend from beaver_gateway.frontends.markdown import MarkdownFrontend from beaver_gateway.frontends.mcp_server import McpServerFrontend +from beaver_gateway.frontends.telegram import TelegramFrontend from beaver_gateway.mcp.types import HttpMcp, McpServer, McpServerT VAULT = Path("/vault") @@ -216,14 +217,28 @@ def _public(suffix: str) -> str | None: return f"{PUBLIC_BASE_URL}{suffix}" if PUBLIC_BASE_URL else None +# §3.8: личка с ботом - домашний фронтенд мастера и веток (General и топики). +# Токен и id - секреты gateway, в env процесса модели они не попадают. +TELEGRAM = ( + TelegramFrontend( + token=os.environ["TELEGRAM_BOT_TOKEN"], + user_id=int(os.environ["TELEGRAM_USER_ID"]), + master_agent="beaver-dispatcher", + branch_agent="beaver-dispatcher", + ) + if os.environ.get("TELEGRAM_BOT_TOKEN") + else None +) + frontends: list[Frontend] = [ + *([TELEGRAM] if TELEGRAM is not None else []), AnthropicMessagesFrontend( host="0.0.0.0", port=62990, public_base_url=_public("/anthropic") ), McpServerFrontend(host="0.0.0.0", port=62991, public_base_url=_public("/mcp")), AdminFrontend(host="0.0.0.0", port=62992, public_base_url=_public("/admin")), - # §3.9: /api показывает всё; домашний фронтенд мастера/ветки до S5 - он же, - # поэтому дефолтный агент на master/branch живёт здесь, deep - у markdown. + # §3.9: /api показывает всё; дефолт master/branch здесь - запасной на случай + # gateway без телеграма, deep - у markdown. ApiFrontend( host="0.0.0.0", port=62994, diff --git a/uv.lock b/uv.lock index 4797c5b..807b7ef 100644 --- a/uv.lock +++ b/uv.lock @@ -25,6 +25,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/67/cd/0d76dfc5de72bde52f55f53e925c7d152d9c7906634ec1e0cbc7e8d4ad93/aiofile-3.11.1-py3-none-any.whl", hash = "sha256:ce77d14ac07f77bc2b757834a5c129321f3f705c474593deed5ab209079a52c9", size = 20446, upload-time = "2026-05-16T08:18:32.051Z" }, ] +[[package]] +name = "aiofiles" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/c3/534eac40372d8ee36ef40df62ec129bee4fdb5ad9706e58a29be53b2c970/aiofiles-25.1.0.tar.gz", hash = "sha256:a8d728f0a29de45dc521f18f07297428d56992a742f0cd2701ba86e44d23d5b2", size = 46354, upload-time = "2025-10-09T20:51:04.358Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/8a/340a1555ae33d7354dbca4faa54948d76d89a27ceef032c8c3bc661d003e/aiofiles-25.1.0-py3-none-any.whl", hash = "sha256:abe311e527c862958650f9438e859c1fa7568a141b22abcd015e120e86a85695", size = 14668, upload-time = "2025-10-09T20:51:03.174Z" }, +] + +[[package]] +name = "aiogram" +version = "3.31.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiofiles" }, + { name = "aiohttp" }, + { name = "certifi" }, + { name = "magic-filter" }, + { name = "pydantic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ec/5f/b2ee094181bb578c0987eef92a51af1fc2caa2be3589da2e37543c0f2906/aiogram-3.31.0.tar.gz", hash = "sha256:f2c5064fe52d88898c86af62261c405440a014216e45dd99b2c6555a5602ce30", size = 2025095, upload-time = "2026-08-26T00:00:42.97Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/dd/c1ea24eb687e564b6b64db3939b858bbcbd3f6998496508a168ce54c5770/aiogram-3.31.0-py3-none-any.whl", hash = "sha256:d889493c5917a867fc9da81fd6e6b3ae438e98bfe1b004fcdafe7400461a6c1b", size = 859100, upload-time = "2026-08-26T00:00:41.178Z" }, +] + [[package]] name = "aiohappyeyeballs" version = "2.6.2" @@ -327,6 +353,7 @@ resolution-markers = [ ] dependencies = [ { name = "aiofile" }, + { name = "aiogram" }, { name = "aiohttp" }, { name = "aiosqlite" }, { name = "anthropic" }, @@ -351,6 +378,7 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "aiofile", specifier = ">=3.11.1" }, + { name = "aiogram", specifier = ">=3.31.0" }, { name = "aiohttp", specifier = ">=3.13.5" }, { name = "aiosqlite", specifier = ">=0.22.1" }, { name = "anthropic", specifier = ">=0.103.0" }, @@ -1124,6 +1152,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, ] +[[package]] +name = "magic-filter" +version = "1.0.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e6/08/da7c2cc7398cc0376e8da599d6330a437c01d3eace2f2365f300e0f3f758/magic_filter-1.0.12.tar.gz", hash = "sha256:4751d0b579a5045d1dc250625c4c508c18c3def5ea6afaf3957cb4530d03f7f9", size = 11071, upload-time = "2023-10-01T12:33:19.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/75/f620449f0056eff0ec7c1b1e088f71068eb4e47a46eb54f6c065c6ad7675/magic_filter-1.0.12-py3-none-any.whl", hash = "sha256:e5929e544f310c2b1f154318db8c5cdf544dd658efa998172acd2e4ba0f6c6a6", size = 11335, upload-time = "2023-10-01T12:33:17.711Z" }, +] + [[package]] name = "markdown-it-py" version = "4.2.0"