set-tg-bot: 3 попытки getMe timeout=15 + backoff 3/6с (t-261016141220)

This commit is contained in:
Simbiot Harness 2026-10-16 14:19:22 +00:00
parent 0f7d63722c
commit b2391c2b5b
2 changed files with 55 additions and 10 deletions

35
cli.py
View file

@ -187,6 +187,9 @@ def main():
p_mcp.add_argument("--list", action="store_true", help="показать тулы шлюза и выйти")
p_mcp.add_argument("--timeout", type=int, default=None, help="таймаут запроса, сек")
p_mcs = sub.add_parser("mcp-stats", help="статистика MCP-вызовов по журналу mcp_calls.log (t-261015091108)")
p_mcs.add_argument("--tail", type=int, default=10, help="последние N вызовов (0 — только сводка)")
args = ap.parse_args()
if args.cmd == "init":
@ -447,6 +450,38 @@ def main():
ap.error("mcp-call: укажи tool (или --list)")
kw = {"timeout": args.timeout} if args.timeout else {}
print(portal_mcp.call_tool(args.tool, args.arguments, **kw))
elif args.cmd == "mcp-stats":
# t-261015091108: статистика MCP-вызовов из журнала mcp_calls.log
import collections
log_path = os.path.join(_paths.home(), "mcp_calls.log")
if not os.path.exists(log_path):
print("(журнала ещё нет — mcp_calls.log пуст, вызовов не было)")
return
rows = []
with open(log_path, encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
rows.append(json.loads(line))
except ValueError:
pass
by_tool = collections.Counter(r.get("tool", "?") for r in rows)
by_level = collections.Counter(r.get("level", "?") for r in rows)
fails = sum(1 for r in rows if not r.get("ok"))
ms = [r.get("ms", 0) for r in rows if isinstance(r.get("ms"), int)]
print(f"всего вызовов: {len(rows)} (ошибок: {fails})")
if ms:
print(f"время ответа: медиана {sorted(ms)[len(ms)//2]}мс, макс {max(ms)}мс")
print("по тулам: " + ", ".join(f"{k}×{v}" for k, v in by_tool.most_common()))
print("по уровням: " + ", ".join(f"{k}×{v}" for k, v in by_level.most_common()))
if args.tail:
print(f"\nпоследние {min(args.tail, len(rows))}:")
for r in rows[-args.tail:]:
args_s = json.dumps(r.get("arguments", {}), ensure_ascii=False)[:120]
print(f"{r.get('ts','?')} [{r.get('level','?')}] {r.get('tool','?')} "
f"{'ok' if r.get('ok') else 'FAIL'} {r.get('ms','?')}мс {args_s}")
elif args.cmd == "escalate":
es.init_db()
eid, to_level = commands.raise_escalation(

View file

@ -298,17 +298,27 @@ def _apply_tg_command(text: str) -> None:
except OSError:
pass
# 1) самотест токена ДО записи: getMe от Telegram
try:
req = urllib.request.Request(f"https://api.telegram.org/bot{token}/getMe")
with urllib.request.urlopen(req, timeout=10) as r:
me = json.loads(r.read().decode())
if not (me.get("ok") and (me.get("result") or {}).get("username")):
raise RuntimeError(str(me)[:150])
uname = me["result"].get("username") or "bot"
except Exception as e:
_report(f"❌ TG-токен не принят Telegram (getMe): {e}")
print(f"[set-tg] токен не валиден: {e}", flush=True)
# (t-261016141XXX: 3 попытки с паузой — таймаут сети не должен ронять привязку)
me = None
_last_err = None
for _attempt in range(3):
try:
req = urllib.request.Request(f"https://api.telegram.org/bot{token}/getMe")
with urllib.request.urlopen(req, timeout=15) as r:
me = json.loads(r.read().decode())
if not (me.get("ok") and (me.get("result") or {}).get("username")):
raise RuntimeError(str(me)[:150])
break
except Exception as e:
_last_err = e
me = None
if _attempt < 2:
time.sleep(3 * (_attempt + 1))
if me is None:
_report(f"❌ TG-токен не принят Telegram (getMe, 3 попытки): {_last_err}")
print(f"[set-tg] токен не валиден: {_last_err}", flush=True)
return
uname = me["result"].get("username") or "bot"
# 2) аллоулист: из команды (allowed=…), иначе сохранённый в .env
allowed = payload.get("allowed") or payload.get("owner_tg") or ""
if not allowed: