From f8e42cdce1a8df0c00addc6af33cd7980d6f5eac Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 8 Jun 2026 22:12:57 +0100 Subject: [PATCH] chore: update docs --- .devcontainer/devc-welcome.md | 11 ++++++-- AGENTS.md | 27 ++++++++++--------- .../Deploying/Development-Environment.mdx | 22 +++++++-------- docs/content/Deploying/Postgres-Migration.mdx | 4 +-- docs/runbooks/sse-notifications.md | 10 +++++++ 5 files changed, 46 insertions(+), 28 deletions(-) diff --git a/.devcontainer/devc-welcome.md b/.devcontainer/devc-welcome.md index a119c590..2ee76adf 100644 --- a/.devcontainer/devc-welcome.md +++ b/.devcontainer/devc-welcome.md @@ -13,12 +13,19 @@ cd frontend npm run dev -- --host ``` -### Flask (Backend) +### Backend (ASGI) + +Run the full app under uvicorn (serves `/mcp` and the async SSE reconnect +routes, and matches production): ```bash -flask --app application/app.py run --host=0.0.0.0 --port=7091 +uvicorn application.asgi:asgi_app --host 0.0.0.0 --port 7091 --reload ``` +`flask --app application/app.py run --host=0.0.0.0 --port=7091` is faster but +serves only the WSGI Flask app — it omits `/mcp` and the reconnect reader +`GET /api/messages//events`, so a dropped stream won't auto-resume. + ### Celery (Task Queue) ```bash diff --git a/AGENTS.md b/AGENTS.md index 74f25a35..033047c0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,24 +31,25 @@ source .venv/bin/activate # macOS/Linux uv pip install -r application/requirements.txt # or: pip install -r application/requirements.txt ``` -Run the Flask API (if needed): - -```bash -flask --app application/app.py run --host=0.0.0.0 --port=7091 -``` - -That's the fast inner-loop option — quick startup, the Werkzeug interactive -debugger still works, and it hot-reloads on source changes. It serves the -Flask routes only (`/api/*`, `/stream`, etc.). - -If you need to exercise the full ASGI stack — the `/mcp` FastMCP endpoint, -or to match the production runtime exactly — run the ASGI composition under -uvicorn instead: +Run the API. For local dev, prefer the ASGI entrypoint under uvicorn — it +serves the **whole** app, matches production, and hot-reloads: ```bash uvicorn application.asgi:asgi_app --host 0.0.0.0 --port 7091 --reload ``` +`flask --app application/app.py run --host=0.0.0.0 --port=7091` is a faster +inner loop (quick startup, the Werkzeug interactive debugger), but it serves +**only** the WSGI Flask app and omits the routes mounted on the ASGI shell +in `application/asgi.py`: + +- the `/mcp` FastMCP endpoint, and +- the native-async SSE reconnect reader `GET /api/messages//events`. + +Under `flask run` those paths 404. Chat still works (`POST /stream` is a +Flask route), but a stream interrupted by a disconnect won't auto-resume on +reconnect. Use `flask run` only when you don't need those routes. + Production uses `gunicorn -k uvicorn_worker.UvicornWorker` against the same `application.asgi:asgi_app` target; see `application/Dockerfile` for the full flag set. diff --git a/docs/content/Deploying/Development-Environment.mdx b/docs/content/Deploying/Development-Environment.mdx index bbe1ebc6..b94e8056 100644 --- a/docs/content/Deploying/Development-Environment.mdx +++ b/docs/content/Deploying/Development-Environment.mdx @@ -96,23 +96,23 @@ To run the DocsGPT backend locally, you'll need to set up a Python environment a pip install -r application/requirements.txt ``` -5. **Run the Flask App:** +5. **Run the Backend:** - Start the Flask backend application: - - ```bash - flask --app application/app.py run --host=0.0.0.0 --port=7091 - ``` - - This command will launch the backend server, making it accessible on `http://localhost:7091`. It's the fastest inner-loop option for day-to-day development — the Werkzeug interactive debugger still works and it hot-reloads on source changes. It serves the Flask routes only. - - If you need to exercise the full ASGI stack — the `/mcp` endpoint (FastMCP server), or to match the production runtime — run the ASGI composition under uvicorn instead: + For local development, run the ASGI composition under uvicorn. It serves the **whole** application, hot-reloads on source changes, and matches the production runtime: ```bash uvicorn application.asgi:asgi_app --host 0.0.0.0 --port 7091 --reload ``` - Production uses `gunicorn -k uvicorn_worker.UvicornWorker` against the same `application.asgi:asgi_app` target. + This makes the backend accessible on `http://localhost:7091`. Production uses `gunicorn -k uvicorn_worker.UvicornWorker` against the same `application.asgi:asgi_app` target. + + A plain Flask run is a faster inner loop (quick startup, the Werkzeug interactive debugger): + + ```bash + flask --app application/app.py run --host=0.0.0.0 --port=7091 + ``` + + But it serves **only** the WSGI Flask app and omits the routes mounted on the ASGI shell in `application/asgi.py`: the `/mcp` FastMCP endpoint and the native-async SSE reconnect reader `GET /api/messages//events`. Under `flask run` those paths return 404 — chat still works (`POST /stream` is a Flask route), but a stream interrupted by a disconnect won't auto-resume on reconnect. Use `flask run` only when you don't need those routes. 6. **Start the Celery Worker:** diff --git a/docs/content/Deploying/Postgres-Migration.mdx b/docs/content/Deploying/Postgres-Migration.mdx index f8a8b1e8..7d439eb8 100644 --- a/docs/content/Deploying/Postgres-Migration.mdx +++ b/docs/content/Deploying/Postgres-Migration.mdx @@ -37,7 +37,7 @@ schema on first boot. ```bash export POSTGRES_URI="postgresql://user:pass@host/docsgpt?sslmode=require" -flask --app application/app.py run --host=0.0.0.0 --port=7091 +uvicorn application.asgi:asgi_app --host 0.0.0.0 --port 7091 ``` ### Bare-metal Postgres @@ -47,7 +47,7 @@ First boot creates both the database and the schema. ```bash export POSTGRES_URI="postgresql://postgres@localhost/docsgpt" -flask --app application/app.py run --host=0.0.0.0 --port=7091 +uvicorn application.asgi:asgi_app --host 0.0.0.0 --port 7091 ``` Prefer a dedicated non-superuser role? Create it once as superuser — the diff --git a/docs/runbooks/sse-notifications.md b/docs/runbooks/sse-notifications.md index 1dc1bc1b..721aeb11 100644 --- a/docs/runbooks/sse-notifications.md +++ b/docs/runbooks/sse-notifications.md @@ -360,6 +360,16 @@ running task and the terminal SSE arrives later, the toast pops back. Intentional ("notify the user it's done"); revisit if the re-surface UX is too aggressive for v2. +### Reconnect reader needs the ASGI entrypoint + +The chat-stream reconnect reader `GET /api/messages//events` +is a native-async Starlette route mounted in +`application/asgi.py`, not a Flask route. Plain `flask run` +serves only the WSGI Flask app, so under it that endpoint 404s +and reconnect-after-disconnect can't resume. Run the backend via +`uvicorn application.asgi:asgi_app --reload` (or the production +gunicorn uvicorn-worker) to exercise it. + ### Werkzeug doesn't auto-reload route files The dev server (`flask run`) doesn't watch