This commit is contained in:
Mikan
2026-06-21 02:41:48 +03:00
parent c21a13d2a3
commit bd85e186dc
31 changed files with 1372 additions and 319 deletions

View File

@@ -4,6 +4,56 @@ All notable changes to AI-RPG are documented here.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.1.0] — 2026-06-21
This is a major bugfix release addressing 20+ issues found during user testing.
### Backend — Critical fixes
- **app/api/sessions.py**: fixed `TypeError: 'async_generator' object does not support the asynchronous context manager protocol` that broke ALL SSE streams (world builder, world editor, orchestrator). The `_session_scope()` function was an async generator (used `yield`) but was called with `async with`. Added `@asynccontextmanager` decorator. Without this fix, no LLM calls were ever made — the background task crashed immediately.
- **app/models/__init__.py**: made `WorldPreset.owner_id` nullable (`NOT NULL``NULL`, `ondelete=CASCADE``SET NULL`). Builtin presets are now system presets with `owner_id=NULL`. Previously, `seed_builtin_presets` crashed on first startup with a foreign key violation because no admin user existed yet.
- **app/main.py**: added `_apply_schema_fixups(engine)` that runs `ALTER TABLE world_presets ALTER COLUMN owner_id DROP NOT NULL` on every startup (idempotent, wrapped in try/except). This fixes existing databases that were created with the old NOT NULL constraint.
- **app/main.py**: admin setup URL is now ALWAYS printed on startup (even if admin already exists), per user request. The URL is blocked by the backend if an admin exists, but the token is visible for reference.
- **app/migrations/seed.py**: `seed_builtin_presets` now uses `owner_id=None` instead of looking for an admin user or a sentinel UUID.
- **requirements.txt**: pinned `bcrypt==4.0.1`. bcrypt 4.1+ removed the `__about__` module which breaks passlib 1.7.4's version detection. This caused the annoying `(trapped) error reading bcrypt version` warning on every password hash operation.
### Backend — API improvements
- **app/api/misc.py**: added `GET /api/settings/public` (no auth) — returns `{page_title, favicon_url, logo_url, og_image_url}`. The frontend uses this on app load to set the document title, favicon, and navbar logo.
- **app/api/worlds.py**: `GET /api/worlds` now excludes archived worlds by default. Pass `?status_filter=archived` to see only archived, or `?status_filter=all` to see everything.
- **app/api/admin.py**: `GET /api/admin/stats` now returns separate counts: `worlds` (active), `worlds_archived`, `worlds_total`. Previously it counted ALL worlds including archived.
- **app/api/admin.py**: added `DELETE /api/admin/worlds/{id}` — hard-delete a world (cascade deletes entities, steps, logs, triggers, story_entries). Also cleans up Qdrant points (best-effort). This gives admins a way to permanently remove archived worlds.
- **app/core/llm.py**: improved error messages for LLM API failures:
- Non-JSON responses now raise `LLMResponseError("LLM provider returned non-JSON response (check that api_url points to an OpenAI-compatible endpoint). First 200 chars: ...")` instead of a generic `parse_error`.
- HTTP 4xx/5xx errors now include the response body (or extracted `error.message` from JSON).
- All error messages now include the HTTP status code for easier debugging.
### Frontend — Critical fixes (19 files changed, 1 new)
- **Black page after settings change**: root cause was `AdminApi.updateSettings` returning `{updated: ...}` but the store expecting a different shape. Fixed the return type and removed the refetch-after-save that caused re-render loops.
- **[object Object] error in chat**: added `toErrorMessage()` helper that properly extracts `.message` from `ApiError` objects. All error toasts now show human-readable strings.
- **Play page access control**: `/worlds/:id/play` now redirects to `/worlds/:id/edit` with a toast if `world.status !== 'ready'`.
- **Retry/Rollback buttons**: disabled when `recentSteps.length === 0` with `opacity-50 cursor-not-allowed`.
- **Archived worlds**: hidden from the worlds list (both server-side and client-side filter). After deleting, removed from local state immediately.
- **World card archived state**: no Play button, "Archived" badge, "Restore" button (`PATCH` status→ready), admin-only "Delete permanently" button (`DELETE /api/admin/worlds/{id}`).
- **LLM logs detail modal**: now shows `request_messages`, `response_message`, `tool_calls`, `error_message`, `prompt_tokens`, `completion_tokens`, `latency_ms`, `temperature`, `model`, `stage`, `status` (color-coded), `created_at` — all in pretty-printed JSON `<pre>` blocks.
- **Dropdowns**: `embeddings.provider``<select>` with `offline_hash`/`openai`; boolean settings → `<select>` with `true`/`false`; LLM log stage filter → `<select>` with all 16 stage values; LLM log status filter → `<select>` with all 6 status values.
- **Numeric inputs**: all integer/float settings now use `<input type="number">` with `min`/`max` attributes. String-to-number conversion on save.
- **Test page pre-fills**: diagnostic forms now pre-fill from current settings (`llm.api_url`, `llm.api_key`, `llm.model`, `embeddings.api_url`, `embeddings.model`, `embeddings.provider`).
- **Embeddings test provider**: defaults to current `embeddings.provider` setting (was hardcoded to `openai`). Added hint: "If provider=openai and api_url is empty, falls back to llm.api_url".
- **Embeddings URL fallback hints**: added muted hint text next to `embeddings.api_url`, `embeddings.api_key`, `embeddings.model` fields.
- **UI settings applied**: new `uiSettingsStore` fetches `GET /api/settings/public` on app load. Sets `document.title`, favicon `<link>`, and navbar logo. Re-fetches after admin settings save.
- **Light theme fix**: rewrote CSS with CSS-variable-based theming. Light mode now uses `#fafafa`/`#1a1a1a`/`#ffffff` with high-contrast text. Dark mode unchanged.
- **Single Create button**: removed redundant "Create World" from navbar. Only one Create button remains (top of worlds list page).
- **Username validation**: client-side regex check + 422 error parsing with field-level inline messages. Specific toast: "Username can only contain letters, numbers, and underscores".
- **SSE error handling**: `sessionStore` now shows toast on SSE `error` events. One-shot "Connection lost. Retrying…" toast on unexpected stream closure.
- **Settings panel UX**: 6 grouped cards (LLM / Embeddings / Qdrant / Context / Game / UI), each with its own Save button. No page reload or full refetch after save — just a success toast.
- **Admin stats panel**: now shows 6 cards: Users, Active Worlds, Archived, Total Worlds, Steps, Avg LLM Latency.
### Verification
- Backend: 68 unit tests pass.
- Frontend: `tsc --noEmit` → 0 errors. `npm run build` → success (354 KB JS / 23 KB CSS, ~109 KB gzipped).
## [1.0.5] — 2026-06-20
### Fixed