- фото/документ/видео без подписи выпадали из триажа (_pending_inbox и build_context пускали только текст/голос): висели до 23 ч, все 4 неотвеченных за неделю — такие. Один фильтр _is_pending, медиа с тегом и путём файла; окно свежести SIMBIOT_MEDIA_PENDING_H=6 — старые не будят LLM задним числом; стикер без текста — не повод. - MinNudge: мин-тик через 3 с тишины после MessageReceived/Transcribed, не ждём границы минуты (было: медиана 36 с до старта LLM, p90 93 с при 24 с самой модели). Слот следующего такта, граница его пропускает; SIMBIOT_MIN_NUDGE=0 — выключить. - сек-уровень: CycleTicked+ReflexObserved каждую секунду = 1.35 млн подписанных событий/нед (98% стора 1.37 ГБ). Теперь heartbeat раз в 60 с + такты с событием (алерт, команды, каналы); «reflex ok» не спамит журнал. - 6 тестов писали в боевой стор под SIMBIOT_HOME тика (TTFTWatchdogRetry с бюджетом 0.5 с в проде — это они): изоляция SIMBIOT_DB. Тест: tests/test_tick_latency_noise.py 20 PASS; полный набор — без регрессий. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
83 lines
No EOL
4 KiB
Python
83 lines
No EOL
4 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""t-261001091912-24602f: ROUTER_BASE_URL/ключ берётся и из .env, не только из env.
|
||
|
||
Запуск: ./venv/bin/python tests/test_router_env_fallback.py
|
||
|
||
Баг в e2e: systemd-юниты харнеса не экспортируют .env, runtime.py читал
|
||
ROUTER_BASE_URL только из окружения → у свежеразвёрнутого агента
|
||
base_url тихо уходил в дефолт 127.0.0.1:20128 (на эталонном хосте так
|
||
жив 9router, на Hetzner-агенте — нет) и LLM-тики падали до первого
|
||
look в .env. Фикс: _env_or_file() — env имеет приоритет, .env рядом
|
||
с кодом — фолбэк (как раньше делал _router_key); EnvironmentFile в
|
||
юнитах cloud-init — страховка сверху.
|
||
"""
|
||
import os
|
||
import sys
|
||
import tempfile
|
||
|
||
sys.path.insert(0, "/root/simbiot-harness")
|
||
|
||
fails = []
|
||
|
||
|
||
def check(name, cond, extra=""):
|
||
print(("PASS" if cond else "FAIL"), name, ("| " + extra) if not cond else "")
|
||
if not cond:
|
||
fails.append(name)
|
||
|
||
|
||
# изоляция стора (аудит 2026-10-16): тест не пишет в боевой стор, даже
|
||
# когда его гоняет тик харнеса под SIMBIOT_HOME (TTFTWatchdogRetry с
|
||
# бюджетом 0.5с из этого набора оседали в проде)
|
||
import tempfile as _iso_tf # noqa: E402
|
||
os.environ["SIMBIOT_DB"] = os.path.join(_iso_tf.mkdtemp(prefix="simbiot_test_"), "harness.db")
|
||
|
||
from harness import runtime
|
||
|
||
# hermetic: окружение тест-процесса не должно подсказывать значения
|
||
for _v in ("ROUTER_BASE_URL", "ROUTER_KEY", "OPENAI_API_KEY", "OPENAI_BASE_URL"):
|
||
os.environ.pop(_v, None)
|
||
|
||
# временный "каталог харнеса" с фейковым .env — реальный не трогаем
|
||
tmpdir = tempfile.mkdtemp(prefix="simbiot-envtest-")
|
||
with open(os.path.join(tmpdir, ".env"), "w") as f:
|
||
f.write("ROUTER_BASE_URL=https://router.cil.by/v1\n")
|
||
f.write("ROUTER_KEY=sk-envtest-key\n")
|
||
f.write("# комментарий\n")
|
||
|
||
# t-261004113351: runtime читает .env через paths.env_path() (SIMBIOT_HOME),
|
||
# _HARNESS_DIR больше не источник — патчим актуальный механизм (с рестором)
|
||
runtime._paths.env_path = lambda: os.path.join(tmpdir, ".env")
|
||
|
||
# 1. env отсутствует, .env есть → значение из .env (суть фикса)
|
||
check("1: base_url из .env quando env пуст",
|
||
runtime._router_base_url() == "https://router.cil.by/v1",
|
||
str(runtime._router_base_url()))
|
||
check("1: ключ из .env (прежнее поведение сохранено)",
|
||
runtime._router_key() == "sk-envtest-key")
|
||
|
||
# 2. env присутствует → env сильнее .env
|
||
os.environ["ROUTER_BASE_URL"] = "https://env.takes/priority/v1"
|
||
check("2: env приоритетнее .env",
|
||
runtime._router_base_url() == "https://env.takes/priority/v1")
|
||
os.environ.pop("ROUTER_BASE_URL")
|
||
|
||
# 3. нет ни env, ни .env → дефолт с локальным роутером
|
||
runtime._paths.env_path = lambda: os.path.join(
|
||
tempfile.mkdtemp(prefix="simbiot-envtest-empty-"), ".env")
|
||
check("3: нет .env → дефолт 127.0.0.1:20128",
|
||
runtime._router_base_url() == "http://127.0.0.1:20128/v1",
|
||
str(runtime._router_base_url()))
|
||
|
||
# 4. setup_provider(): end-to-end маппинг .env → OPENAI_* env
|
||
runtime._paths.env_path = lambda: os.path.join(tmpdir, ".env")
|
||
runtime.setup_provider()
|
||
check("4: setup_provider кладёт OPENAI_BASE_URL из .env",
|
||
os.environ["OPENAI_BASE_URL"] == "https://router.cil.by/v1",
|
||
os.environ.get("OPENAI_BASE_URL", ""))
|
||
check("4: setup_provider кладёт OPENAI_API_KEY из .env",
|
||
os.environ.get("OPENAI_API_KEY") == "sk-envtest-key")
|
||
|
||
print()
|
||
print("FAILS:", len(fails), "| файл:", " | ".join(fails) if fails else "—")
|
||
sys.exit(1 if fails else 0) |