Terminal / api /TELEGRAM_MODULES.md
Baida07's picture
fix: sync registry+fallback fixes da A (registry.py line692, LLM_TIMEOUT, _ANALYTICAL_VERBS_RE)
815b2e9 verified
|
Raw
History Blame
7.18 kB
# backend/api β€” Moduli Telegram (M2 Split)
> **Refactor M2 β€” 2 Luglio 2026**
> Il monolite `telegram_webhook.py` (2844 righe, 5 hotfix consecutivi) Γ¨ stato
> spezzato in 6 moduli a responsabilitΓ  singola. Hotfix futuri toccano **un solo file**.
---
## Grafo delle dipendenze
```
telegram_tg_client.py (stdlib + httpx only)
β”‚
β”œβ”€β”€β–Ί telegram_keyboards.py (solo costanti/dict β€” zero import interni)
β”‚ β”‚
β”‚ β”œβ”€β”€β–Ί telegram_cmd_monitoring.py
β”‚ β”‚ └──► (esposto via telegram_webhook.py)
β”‚ β”‚
β”‚ β”œβ”€β”€β–Ί telegram_cmd_ai.py
β”‚ β”‚ └──► (esposto via telegram_webhook.py)
β”‚ β”‚
β”‚ └──► telegram_callbacks.py
β”‚ β”œβ”€β”€ importa _cmd_do, _cmd_autofix ... da telegram_cmd_ai
β”‚ └── importa _cmd_help, _cmd_status ... da telegram_cmd_monitoring
β”‚
└──► telegram_webhook.py (router FastAPI puro β€” importa da tutti)
└──► montato in backend/main.py come _tg_webhook_router
```
---
## Moduli
### `telegram_tg_client.py` β€” 276 righe
**Ruolo:** Telegram Bot API puro. Layer 0 senza dipendenze interne.
| Simbolo | Descrizione |
|---------|-------------|
| `_get_bot_token()` | Legge `TELEGRAM_BOT_TOKEN` dall'env |
| `_log_tg_exc(task)` | Log eccezioni fire-and-forget (Gap-2.6) |
| `_fmt_elapsed(sec)` | Formatta durata in human-readable |
| `_tg_reply(chat_id, text)` | Invia messaggio con parse_mode=HTML |
| `_tg_send(chat_id, text)` | Come reply, ritorna `message_id` |
| `_tg_edit(chat_id, msg_id, text)` | Modifica messaggio esistente |
| `_tg_photo(chat_id, url, caption)` | Invia foto via URL |
| `_tg_typing(chat_id)` | Invia `sendChatAction typing` |
| `_tg_react(chat_id, msg_id, emoji)` | Imposta reaction emoji |
| `_tg_answer_callback(callback_id)` | Risponde a `callback_query` (≀3s) |
**Import:** `asyncio, html, logging, os, time, httpx`
---
### `telegram_keyboards.py` β€” 109 righe
**Ruolo:** Costanti UI e keyboards. Zero logica, zero import interni.
| Simbolo | Tipo | Descrizione |
|---------|------|-------------|
| `_QUICK_PICK_KB` | `dict` | Inline keyboard selezione task rapida |
| `_MAIN_KB` | `dict` | Reply keyboard principale |
| `_BENCH_ACTION_KB` | `dict` | Keyboard post-benchmark |
| `_TASK_MENU_KB` | `dict` | Sub-menu task |
| `_STATUS_MENU_KB` | `dict` | Sub-menu stato sistema |
| `_PERF_MENU_KB` | `dict` | Sub-menu performance |
| `_HEALTH_MENU_KB` | `dict` | Sub-menu health |
| `_DEV_MENU_KB` | `dict` | Sub-menu developer |
| `_LAST_GOAL` | `dict[int,str]` | Memoria per bottone πŸ” Rifai |
| `_BENCH_CACHE` | `dict[int,dict]` | Ultimo run benchmark per chat |
| `_after_task_kb(chat_id)` | func | Keyboard dinamica post-task |
**Import:** solo `from __future__ import annotations`
---
### `telegram_cmd_monitoring.py` β€” 456 righe
**Ruolo:** Comandi di monitoraggio, stato e diagnostica.
| Comando / Funzione | Trigger Telegram |
|--------------------|-----------------|
| `_cmd_help(chat_id)` | `/start` `/help` `tgw_help` |
| `_cmd_logs(chat_id)` | `/logs` `tgw_logs` |
| `_cmd_status(chat_id)` | `/stato` `tgw_status` |
| `_cmd_commit_summary(chat_id)` | `/commit` `tgw_commits` |
| `_cmd_check(chat_id)` | `/salute` `tgw_health` |
| `_cmd_tasks(chat_id)` | `/attivitΓ ` `tgw_tasks` |
| `_cmd_git(chat_id, args)` | `/git` `tgw_git` |
| `_cmd_coord(chat_id)` | `/coord` `tgw_coord` |
| `_cmd_scan_now(chat_id)` | `/scan` `tgw_scan` |
| `_cmd_telemetry(chat_id)` | `/telemetria` `tgw_telemetry` |
**Import:** stdlib + `telegram_tg_client` + `telegram_keyboards`
---
### `telegram_cmd_ai.py` β€” 1152 righe
**Ruolo:** Comandi AI, LLM e operativi. Modulo piΓΉ pesante β€” contiene lo streaming loop.
| Comando / Funzione | Trigger Telegram |
|--------------------|-----------------|
| `_cmd_do(chat_id, goal)` | `/avvia` β€” lancia task AI con streaming |
| `_cmd_autofix(chat_id)` | `/fix` `tgw_autofix` |
| `_cmd_nota(chat_id, text)` | `/nota` `tgw_nota` |
| `_cmd_cerca(chat_id, query)` | `/cerca` `tgw_cerca` |
| `_cmd_meteo(chat_id, city)` | `/meteo` `tgw_meteo` |
| `_cmd_riepilogo(chat_id)` | `/riepilogo` `tgw_briefing` |
| `_cmd_score(chat_id)` | `/score` `tgw_score` |
| `_cmd_bench(chat_id)` | `/bench` `tgw_bench` |
| `_cmd_improve(chat_id, target)` | `/migliora` `tgw_improve` |
**Import:** stdlib + `telegram_tg_client` + `telegram_keyboards`
---
### `telegram_callbacks.py` β€” 353 righe
**Ruolo:** Smista `callback_query` e `inline_query` in arrivo da Telegram.
| Funzione | Descrizione |
|----------|-------------|
| `_handle_inline(iq, token)` | Risponde alle inline query (`@ARJagent_ap_bot testo`) |
| `_handle_callback(cb, token)` | Dispatch per tutti i `callback_data` `tgw_*` / `agent` / `qp_*` |
**Import:** `telegram_tg_client` + `telegram_keyboards` + `telegram_cmd_ai` + `telegram_cmd_monitoring`
> ⚠️ **Questo modulo crea dipendenze circolari potenziali** β€” non importare
> `telegram_callbacks` da `telegram_cmd_ai` o `telegram_cmd_monitoring`.
---
### `telegram_webhook.py` β€” 605 righe *(era 2844)*
**Ruolo:** Router FastAPI puro. Solo endpoint HTTP, zero logica di business.
| Endpoint | Metodo | Descrizione |
|----------|--------|-------------|
| `/api/telegram/webhook` | POST | Ricezione update getUpdates (polling daemon) |
| `/api/telegram/process` | POST | Endpoint alternativo per CF Pages proxy |
| `/api/telegram/config/invalidate` | POST | Invalida cache config bot |
**Import:** FastAPI + tutti i 5 moduli sopra
**Montato in:** `backend/main.py` β†’ `app.include_router(_tg_webhook_router)`
---
## Regole per gli hotfix
| Vuoi cambiare... | Tocca solo... |
|------------------|---------------|
| Aspetto di un bottone / label | `telegram_keyboards.py` |
| Risposta a un comando /help, /stato… | `telegram_cmd_monitoring.py` |
| Logica task AI / streaming / bench | `telegram_cmd_ai.py` |
| Routing dei bottoni inline (tgw_*) | `telegram_callbacks.py` |
| Helpers HTTP verso api.telegram.org | `telegram_tg_client.py` |
| Routing endpoint FastAPI | `telegram_webhook.py` |
---
## Daemon Node.js (scripts/lib/daemon-callbacks.mjs)
Il daemon usa **getUpdates polling** (non webhook registrato).
Riceve gli update, li smista ai command handler Python via HTTP interno.
Il flusso `callback_data tgw_*` viene elaborato da `telegram_callbacks.py::_handle_callback`.
```
Telegram ──► getUpdates daemon ──► POST /api/telegram/process
β”‚
telegram_webhook.py (router)
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
message? callback_query?
β”‚ β”‚
telegram_cmd_*.py telegram_callbacks.py
::_handle_callback
```