Files
ToDoList/AGENTS.md
2026-05-17 11:21:41 +08:00

5.2 KiB

AGENTS.md

Project overview

  • Full-stack todo app: Vue 3 + Element Plus (WebUI/) + FastAPI + SQLAlchemy (api/)
  • Python 3.10+, Node 18+; SQLite database
  • Single master branch, no CI/CD

Quick commands

# Install Python deps (required before first run)
pip install -r requirements.txt

# Full-stack one-shot (builds frontend, then starts backend on :23994)
python main.py

# Frontend dev only (hot-reload on :5173, proxies /api → :23994)
cd WebUI; npm run dev

# Backend only
cd api; uvicorn app.main:app --host 0.0.0.0 --port 23994

# Type-check frontend (noEmit; uses project references tsconfig)
cd WebUI; npm run typecheck

# Run the one hand-written test (backend must be running on :23994)
python tests/test_accounts.py

Build order matters: python main.py automatically compiles WebUI (npm install + npm run build), copies WebUI/dist/api/webui/, then starts uvicorn. It checks timestamps to skip rebuilds when frontend is unchanged.

Import path: main.py injects api/ into sys.path (no os.chdir). Backend imports resolve relative to api/ — e.g. from app.config import ..., not from api.app.config import ....

Port conflict: main.py will auto-kill any process already listening on port 23994 before starting. If you have another instance running, it will be terminated without warning.

Architecture

Backend (api/app/)

  • Config is hardcoded in api/app/config.py — no .env, no os.getenv(). Port 23994, CORS origins ["http://localhost:5173", "http://localhost:23994"]. Note: pydantic-settings is in requirements.txt but unused.
  • SQLite path is computed relative to api/ via __file__ — safe regardless of cwd. connect_args={"check_same_thread": False} for FastAPI async compatibility.
  • database.py:init_db() auto-creates tables on startup (create_all) and auto-adds missing columns via ALTER TABLE ADD COLUMN (no Alembic). Columns that are non-nullable with no default are skipped.
  • UserSettings is a singleton: always id=1, auto-created on first GET.
  • Account balance changes auto-create AccountHistory records in update_balance().
  • Habit checkins for the same day accumulate count (not new rows), enforced by a (habit_id, checkin_date) unique constraint.
  • Anniversaries / DebtInstallments have computed fields (next_date, days_until, year_count / remaining_periods) calculated at request time, not stored in DB.
  • task_tags M2M table is defined in models/tag.py (not models/task.py).
  • Update schemas use clearable_fields + exclude_unset=True to distinguish "field not sent" from "field sent as null".
  • JWT authentication — mandatory for all /api/* routes except /api/auth/* and /health. Default password: elysia. Login via POST /api/auth/login. Token key in localStorage: elysia_auth_token. Frontend axios interceptor auto-attaches Authorization: Bearer <token>.

Frontend (WebUI/)

  • Vue Router uses createWebHistory() (HTML5 history mode) — requires the backend SPA fallback (/{full_path:path}index.html).
  • Vite dev proxy forwards /apihttp://localhost:23994.
  • @ alias maps to src/.
  • Global styles in SCSS (src/styles/).
  • 8 Pinia stores; Element Plus icons registered globally in main.ts.
  • Element Plus uses Chinese locale (zh-cn).

Route registration order matters

The /health endpoint must be registered before the /{full_path:path} SPA fallback catch-all, otherwise /health requests return index.html. This is enforced in api/app/main.py:114 — do not reorder these registrations.

Docker

  • Dockerfile copies pre-built api/webui/ — you must build frontend before docker build.
  • Docker CMD is an inline python -c one-liner that injects api/ into sys.path and starts uvicorn. No separate entrypoint script.
  • docker-compose.yml mounts api/data/ and api/logs/ for persistence; api/webui/ is read-only.

Testing quirks

  • Only one test file: tests/test_accounts.pyhand-written, no framework (not pytest). It counts pass/fail manually and uses requests directly against localhost:23994.
  • Backend must be running before executing tests.
  • The test permanently mutates the database — Section 15 deliberately leaves test data in place for UI display. Run it on a disposable database copy or reset manually if you need a clean state.
  • The test sends no auth headers and will fail with 401 if JWT auth is enforced. You must first POST /api/auth/login with {"password": "elysia"} to get a token, then include Authorization: Bearer <token> in requests, or temporarily comment out the auth middleware for testing.
  • No test coverage for tasks, habits, anniversaries, or tags.

What's missing (agents should not assume)

  • No linter, formatter, pre-commit hooks, or CI/CD
  • No .env or environment variable loading
  • No database migrations framework (Alembic)

Additional notes

  • Swagger UI at /docs when backend is running — the live, auto-generated API reference.
  • python-multipart in requirements.txt is required for FastAPI to parse form data (not optional).
  • sass is a runtime dependency (not devDependency) in package.json — unusual, but intentional.