Настройка из браузера: вкладка ⚙ вместо правки файла
Инсталлятор спрашивает адрес Ollama в консоли, но это можно пропустить и задать всё с телефона: адрес, модель для разбора фраз, модель для поиска по смыслу. «Проверить связь» показывает, отвечает ли Ollama и сколько там моделей; сами модели выбираются из реально установленных, а не вводятся руками. Если Ollama молчит, предупреждение наверху ведёт прямо в настройки. Настройки применяются сразу: модули читают их через config.X, а не забирают копию при импорте, поэтому перезапуск не нужен. Из веба правятся только OLLAMA_HOST и две модели — по белому списку, потому что .env читает приложение при запуске. Адрес проверяется на формат, имена моделей — на недопустимые символы. Попутно исправлены два дефекта, найденных тестами: - .env в песочнице теперь тоже свой; до этого прогон тестов перезаписывал рабочий файл настроек; - значения проверяются все до применения: раньше неверное имя модели оставляло уже подменённый адрес Ollama. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -177,6 +177,45 @@ config.DB_FILE.write_text("{ битый json", encoding="utf-8")
|
||||
r.check("битая база не роняет", c.get("/api/tree").status_code == 200)
|
||||
r.check("пустой ввод не роняет", "reply" in j("POST", "/api/say", text=" "))
|
||||
|
||||
print("\n== Настройки из браузера ==")
|
||||
d = c.get("/api/config").get_json()
|
||||
r.check("отдаёт текущие", d.get("ollama_host") and d.get("chat_model"), d)
|
||||
r.check("говорит, где файл", str(d.get("env_file", "")).endswith(".env"), d.get("env_file"))
|
||||
|
||||
was_host = config.OLLAMA_HOST
|
||||
# Самое важное: файл настроек тоже в песочнице. Иначе тест перезаписывает
|
||||
# рабочий .env пользователя — так однажды и случилось.
|
||||
r.check("файл .env внутри песочницы", str(SANDBOX) in str(config.ENV_FILE),
|
||||
config.ENV_FILE)
|
||||
|
||||
d = j("POST", "/api/config", ollama_host="http://10.11.12.13:11434")
|
||||
r.check("сохранилось", d.get("ok"), d)
|
||||
r.check("применилось без перезапуска", config.OLLAMA_HOST == "http://10.11.12.13:11434",
|
||||
config.OLLAMA_HOST)
|
||||
r.check("ollama.py видит новый адрес",
|
||||
c.get("/api/health").get_json()["host"] == "http://10.11.12.13:11434")
|
||||
r.check("записалось в файл", config.ENV_FILE.exists()
|
||||
and "10.11.12.13" in config.ENV_FILE.read_text(encoding="utf-8"))
|
||||
|
||||
r.check("мусорный адрес — 400",
|
||||
c.post("/api/config", json={"ollama_host": "не адрес"}).status_code == 400)
|
||||
r.check("инъекция в имя модели — 400",
|
||||
c.post("/api/config",
|
||||
json={"ollama_host": "http://127.0.0.1:11434",
|
||||
"chat_model": "модель\nOLLAMA_HOST=http://зло"}).status_code == 400)
|
||||
# Отказ должен быть полным: адрес из того же запроса применяться не должен,
|
||||
# иначе половина настроек принята, а половина отвергнута.
|
||||
r.check("при отказе НИЧЕГО не применилось",
|
||||
config.OLLAMA_HOST == "http://10.11.12.13:11434", config.OLLAMA_HOST)
|
||||
r.check("посторонние ключи игнорируются", config.save_settings({"PATH": "/зло"}) == [])
|
||||
|
||||
d = j("POST", "/api/config/probe", ollama_host="http://127.0.0.1:1")
|
||||
r.check("проба мёртвого адреса не роняет", d.get("ok") is False, d)
|
||||
r.check("проба не меняет настройку", config.OLLAMA_HOST == "http://10.11.12.13:11434",
|
||||
config.OLLAMA_HOST)
|
||||
j("POST", "/api/config", ollama_host=was_host) # возвращаем как было
|
||||
r.check("адрес восстановлен", config.OLLAMA_HOST == was_host, config.OLLAMA_HOST)
|
||||
|
||||
print("\n== Разбор фразы ==")
|
||||
p = brain.fallback_parse("положил изоленту в коробку B2 на полке 1 в гараже")
|
||||
r.check("регулярки: put", p["action"] == "put" and store.norm_code(p["container"]) == "B2", p)
|
||||
|
||||
Reference in New Issue
Block a user