Add persistent multi-user sessions and Docker deployment
This commit is contained in:
parent
51a6e845d1
commit
104577c826
24 changed files with 2094 additions and 468 deletions
18
AGENTS.md
18
AGENTS.md
|
|
@ -32,7 +32,8 @@ LLM-translator/
|
|||
│ ├── llm_client.py # OpenAI-compatible client (async)
|
||||
│ ├── models.py # Pydantic schemas for all API I/O
|
||||
│ ├── prompts.py # Phase 1–4 prompt templates
|
||||
│ └── sessions.py # In-memory session store (TTL 24h, UUID keys)
|
||||
│ ├── database.py # SQLite schema, users, sessions, revision persistence
|
||||
│ └── sessions.py # Persistent session facade + transient progress
|
||||
├── frontend/ # Vue 3 SPA source
|
||||
│ ├── src/
|
||||
│ │ ├── main.ts # App entry + dark mode pre-mount class application
|
||||
|
|
@ -46,7 +47,7 @@ LLM-translator/
|
|||
│ │ │ └── ComparisonView.vue # 3-column Phase 1/3/4 result comparison
|
||||
│ │ ├── stores/
|
||||
│ │ │ ├── auth.ts # JWT state (check/login/logout)
|
||||
│ │ │ ├── translation.ts # Pipeline state + localStorage persistence
|
||||
│ │ │ ├── translation.ts # Pipeline state + server session persistence
|
||||
│ │ │ └── theme.ts # Dark mode toggle + localStorage + system preference detection
|
||||
│ │ ├── api.ts # Axios client with JWT interceptor
|
||||
│ │ └── types.ts # TypeScript interfaces mirroring backend models
|
||||
|
|
@ -68,7 +69,9 @@ LLM-translator/
|
|||
|
||||
- **No `passlib`** — use `bcrypt` module directly (`bcrypt.hashpw`, `bcrypt.checkpw`). The project uses Python 3.14 which has compatibility issues with passlib's bcrypt wrapper.
|
||||
- **LLM client caching** — `llm_client.py` caches an `AsyncOpenAI` client by alias. Clients are lazily instantiated on first use.
|
||||
- **Session store** — process-local in-memory dict (`sessions.py`) scoped by authenticated owner. Key is UUID hex (16 chars). TTL is 24h from last access; there is no persistence beyond process lifetime.
|
||||
- **Session store** — SQLite-backed, owner-scoped sessions with no automatic TTL deletion. Completed and draft sessions persist across restarts. Streaming progress remains process-local and transient.
|
||||
- **Session revisions** — the latest previous translation snapshot is saved before an edit or phase rerun overwrites results, allowing one-step restore.
|
||||
- **Users** — users are stored in SQLite and created by administrators. `users.json` is imported once for compatibility; password changes and deactivation invalidate existing JWTs through `token_version`.
|
||||
- **JSON extraction** — LLM responses may be wrapped in markdown code blocks. `_extract_json()` strips ```` ```json` ... ```` wrappers before `json.loads()`.
|
||||
- **Long-text chunking** — phases 1, 3, and 4 process text sequentially near sentence boundaries. Defaults are 1,500 characters per chunk and a 180-second timeout per LLM call; both are configurable by environment variables.
|
||||
- **Progress feedback** — LLM calls stream response deltas into transient session progress. The frontend polls `/api/sessions/{session_id}/progress` and displays the current chunk and a rolling preview.
|
||||
|
|
@ -77,7 +80,8 @@ LLM-translator/
|
|||
### Frontend
|
||||
|
||||
- **All Vue components use `<script setup lang="ts">`** with Composition API. No Options API.
|
||||
- **State management via Pinia stores** — `auth`, `translation`, `theme`. Stores persist model selections and history to `localStorage`.
|
||||
- **State management via Pinia stores** — `auth`, `translation`, `theme`. Only model preferences, JWT, and theme are persisted to `localStorage`.
|
||||
- **Server history** — translation history is canonical in SQLite. The frontend keeps only JWT, theme, and model preferences in `localStorage`, and debounces draft changes to the active server session.
|
||||
- **Dark mode is class-based** (`<html class="dark">`). Applied in `main.ts` before mount to prevent flash, then toggled by `useThemeStore.toggle()`. Every UI component has corresponding `dark:` Tailwind classes.
|
||||
- **API calls go through `/api` proxy** during dev (vite.config.ts). In production the same origin serves both API and static files.
|
||||
|
||||
|
|
@ -127,8 +131,8 @@ cd frontend && npm install && cd ..
|
|||
# 2. Build frontend (required before serving in production mode)
|
||||
cd frontend && npm run build && cd ..
|
||||
|
||||
# 3. Configure LLM servers and users
|
||||
# Edit config/llms.json and config/users.json directly
|
||||
# 3. Configure LLM servers and initial users
|
||||
# users.json is imported once; later users are managed in the admin UI
|
||||
|
||||
# 4. Start server
|
||||
uvicorn backend.main:app --host 0.0.0.0 --port 8000
|
||||
|
|
@ -160,7 +164,7 @@ JWT_SECRET_KEY=your-secret uvicorn backend.main:app --reload
|
|||
## File I/O Notes
|
||||
|
||||
- **config/llms.json** — loaded once at startup by `llm_client.py._load_llm_configs()`. Not re-read on requests. Changes require server restart.
|
||||
- **config/users.json** — loaded once at startup by `auth.py._load_users_file()`. Plain-text passwords are auto-migrated to bcrypt hashes and saved back on first run only.
|
||||
- **config/users.json** — imported transactionally once into SQLite. Plain-text passwords are accepted only when the file is writable so they can be replaced with bcrypt hashes; Docker deployments should use pre-hashed entries or bootstrap environment variables.
|
||||
|
||||
## Testing Against LLM Server
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue