Fix empty gateway_embed_key causing embeddings API fallback to invalid key

Add migration in migrate_ai_gateway_settings() to copy OPENROUTER_API_KEY
into gateway_embed_key site setting when empty, matching the existing
pattern for gateway_vision_key. The effective_config() fallback chain
already cascades gateway_embed_key -> gateway_vision_key ->
OPENROUTER_API_KEY, but without the migration the DB setting stays
empty string on every boot, so the fallback only works when the vision
key itself was also never migrated (unlikely after the first boot).
This commit is contained in:
Typosaurus 2026-07-19 18:57:56 +00:00
parent 43c5a948e8
commit 33ca56ddc4
2 changed files with 4 additions and 1 deletions

View File

@ -1353,6 +1353,9 @@ def migrate_ai_gateway_settings() -> None:
if not get_setting("gateway_vision_key", "") and openrouter:
set_setting("gateway_vision_key", openrouter)
logger.info("Migrated gateway vision key from environment")
if not get_setting("gateway_embed_key", "") and openrouter:
set_setting("gateway_embed_key", openrouter)
logger.info("Migrated gateway embed key from environment")
for key in ("news_ai_url", "bot_api_url", "devii_ai_url"):
if get_setting(key, "") == OLD_GATEWAY_URL:
set_setting(key, INTERNAL_GATEWAY_URL)

View File

@ -76,7 +76,7 @@ The gateway is the only place that holds real provider URLs/models/keys. Every o
- Defaults live in `config.py`: `INTERNAL_GATEWAY_URL` (`http://localhost:10500/openai/v1/chat/completions`, override with `DEVPLACE_INTERNAL_BASE_URL`) and `INTERNAL_MODEL` (`molodetz`). `news_ai_url`, `bot_api_url`, `devii_ai_url` default to `INTERNAL_GATEWAY_URL`; their model defaults to `molodetz`.
- Each consumer's key falls back to `database.internal_gateway_key()` (reads the `gateway_internal_key` setting) when its own key field/env is unset - the provider-key fallbacks (`DEEPSEEK_API_KEY`/`OPENROUTER_API_KEY`) were removed from news and bots.
- `gateway_force_model` (default on) and a `molodetz`/empty alias in `handle_chat` make the upstream always receive `gateway_model`, so `molodetz` is a stable generic alias.
- `database.migrate_ai_gateway_settings()` (called at the end of `init_db()`, under the startup `init_lock`): generates `gateway_internal_key` (uuid4) if missing; migrates `DEEPSEEK_API_KEY`/`OPENROUTER_API_KEY` env into `gateway_api_key`/`gateway_vision_key` when the db value is empty; and rewrites any consumer AI URL still equal to the old `openai.app.molodetz.nl` default to the gateway, plus `bot_model` `deepseek-chat` -> `molodetz` (only uncustomized values).
- `database.migrate_ai_gateway_settings()` (called at the end of `init_db()`, under the startup `init_lock`): generates `gateway_internal_key` (uuid4) if missing; migrates `DEEPSEEK_API_KEY`/`OPENROUTER_API_KEY` env into `gateway_api_key`/`gateway_vision_key`/`gateway_embed_key` when the db value is empty; and rewrites any consumer AI URL still equal to the old `openai.app.molodetz.nl` default to the gateway, plus `bot_model` `deepseek-chat` -> `molodetz` (only uncustomized values).
- The gateway's `gateway_api_key`/`gateway_vision_key`/`gateway_internal_key` fields are **non-secret** so the admin services page shows the value actually in use, editable.
- Bot LLM calls are synchronous `urllib` but already run via `asyncio.to_thread` (`bot/bot.py`), so the local round-trip never blocks the event loop.
- Real provider keys/URLs/models live ONLY in the gateway. The gateway is `default_enabled=True`.