build(client): use locked uv environment in launcher and Docker
This commit is contained in:
@@ -8,6 +8,7 @@ do not define the current implementation.
|
||||
|
||||
- [Usage and configuration](client/usage.md)
|
||||
- [Architecture and source map](client/architecture.md)
|
||||
- [Backend development and compatibility](client/development.md)
|
||||
- [Reasoning modes](client/reasoning.md)
|
||||
- [Context injection](client/context-injection.md)
|
||||
- [Tool calling](client/tool-calling.md)
|
||||
|
||||
@@ -42,7 +42,14 @@ audio. It is not an unconditional byte-for-byte tunnel.
|
||||
|
||||
| Source | Responsibility |
|
||||
|---|---|
|
||||
| [server.py](../../s2s-client/server.py) | Configuration, documentation serving, WebSocket relay, context loading, ApiPilot, reasoning, search and queue routes |
|
||||
| [server.py](../../s2s-client/server.py) | Compatibility entry point for existing `server:app` commands |
|
||||
| [main.py](../../s2s-client/s2s_client/main.py) | FastAPI assembly, documentation serving and redirects |
|
||||
| [api](../../s2s-client/s2s_client/api) | HTTP route registration, handlers and compatible response validation |
|
||||
| [models](../../s2s-client/s2s_client/models) | Pydantic request and response contracts |
|
||||
| [core](../../s2s-client/s2s_client/core) | Existing environment parsing, logging, URL helpers and diagnostics |
|
||||
| [providers](../../s2s-client/s2s_client/providers) | Caller context and ApiPilot HTTP integrations |
|
||||
| [services](../../s2s-client/s2s_client/services) | Context construction, reasoning and tool-context rendering |
|
||||
| [realtime](../../s2s-client/s2s_client/realtime) | WebSocket relay, events, markers and audio handling |
|
||||
| [start_ui.sh](../../start_ui.sh) | Dependency setup, ports, readiness, reload processes, and shutdown |
|
||||
| [vite.config.ts](../../s2s-frontend/vite.config.ts) | Public development endpoint, HMR, allowed hosts, and backend routing |
|
||||
| [App.tsx](../../s2s-frontend/src/App.tsx) | React layout, voice controls, dialogs, profile and reports sidebar |
|
||||
@@ -75,6 +82,10 @@ source text, and directories without `index.html` are not browsable pages.
|
||||
FastAPI serves backend and documentation routes only. The frontend source and
|
||||
assets live in `s2s-frontend` and are served by Vite.
|
||||
|
||||
The uv project and its Python tools are scoped to `s2s-client/`. Response models
|
||||
describe service-owned structure and retain loose upstream values. See
|
||||
[development and compatibility](development.md) before tightening a contract.
|
||||
|
||||
## Audio path
|
||||
|
||||
1. The browser captures microphone audio with echo cancellation, noise
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
Context reaches the assistant through browser-built instructions, server-patched
|
||||
realtime session instructions, and HTTP reasoning context. The implementation is
|
||||
in [server.py](../../s2s-client/server.py),
|
||||
in the server's [context services](../../s2s-client/s2s_client/services/context.py),
|
||||
[realtime proxy](../../s2s-client/s2s_client/realtime/proxy.py),
|
||||
[context.ts](../../s2s-frontend/src/lib/context.ts), and the
|
||||
[WebSocket client](../../s2s-frontend/src/realtime/client.ts).
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# Backend development and compatibility
|
||||
|
||||
The FastAPI project lives entirely in `s2s-client/`. It uses uv 0.12.5, Python
|
||||
3.12, and a committed `uv.lock`. The frontend and speech pipeline keep their
|
||||
own tooling. Runtime dependency versions match the environment used to capture
|
||||
the pre-migration server; framework upgrades require a separate compatibility
|
||||
review.
|
||||
|
||||
## Commands
|
||||
|
||||
From the repository root:
|
||||
|
||||
```bash
|
||||
make -C s2s-client install # uv sync --locked, including development tools
|
||||
make -C s2s-client format # Ruff safe fixes and formatting
|
||||
make -C s2s-client check # lock freshness, format, lint, mypy, pytest
|
||||
make -C s2s-client test-launcher # Bash supervisor integration fixtures
|
||||
make -C s2s-client test-image # Docker build and isolated runtime smoke test
|
||||
```
|
||||
|
||||
Run `uv lock` inside `s2s-client/` when intentionally changing dependencies.
|
||||
Do not install server packages into a shared root environment. The launcher
|
||||
syncs `s2s-client/.venv` and retains root `.env` loading, port defaults,
|
||||
readiness checks, and process-group shutdown. Offline starts require the
|
||||
locked packages and Python runtime to have been installed or cached already.
|
||||
|
||||
Optional hooks use `make -C s2s-client hooks-install`; the configuration stays
|
||||
in `s2s-client/.pre-commit-config.yaml`. `make -C s2s-client hooks-run` runs the
|
||||
same hooks without installing them. Hooks and Python quality checks apply
|
||||
only to the client service. The server entry points are `s2s_client.main:app`
|
||||
and the retained `server:app` shim; use `--app-dir s2s-client` from the root.
|
||||
|
||||
## Schema boundaries
|
||||
|
||||
`models/requests.py` retains the existing search, reasoning, and ApiPilot
|
||||
request models, including their defaults, coercion, and ignored extra fields.
|
||||
The queue beacon still accepts malformed JSON and non-object bodies as before;
|
||||
its Pydantic view is applied only after the original object check, and
|
||||
`queueId` remains unconstrained.
|
||||
|
||||
`models/responses.py` validates structure constructed by this server. Fields
|
||||
owned by external services remain `Any` where the old parser imposed no type
|
||||
constraint. Object models allow extra fields. Caller profiles can be arbitrary
|
||||
JSON; load-balancer fields remain optional; execution results and error details
|
||||
remain open. Existing provider parsing, authentication precedence, argument
|
||||
filtering, environment parsing, and WebSocket frames are unchanged.
|
||||
|
||||
HTTP handlers call `validated_json_response`: Pydantic validates the payload,
|
||||
then `JSONResponse` serializes the original object. Returning a dumped model
|
||||
would insert defaults or change values/key order, so do not replace this helper
|
||||
with model serialization without a contract review. Route `response_model`
|
||||
declarations publish the new response schemas in OpenAPI. Existing request
|
||||
schemas and validation errors remain unchanged. HTTP exceptions retain their
|
||||
existing error shapes; there is no new common error envelope.
|
||||
|
||||
## Compatibility evidence
|
||||
|
||||
`tests/fixtures/legacy-contracts.json` was captured from the original monolithic
|
||||
server at commit `3d42df5`, before refactoring. Tests compare 86 HTTP scenarios,
|
||||
including exact response text, statuses, selected headers, and outgoing mock
|
||||
HTTP requests. They also compare request OpenAPI definitions and representative
|
||||
realtime frames. Additional tests cover response validation and permissive
|
||||
upstream values; the original local HTTP/WebSocket tests remain in the suite.
|
||||
|
||||
The captures deliberately preserve unknown fields, omitted fields, unusual JSON
|
||||
values, queue beacon edge cases, permissive tool arguments, and known failures.
|
||||
Examples include reasoning's existing uninitialized local variables in certain
|
||||
configuration combinations, API-key-only tool precheck behavior, the catalog
|
||||
cache's existing key, and relay termination after a suppressed invalid
|
||||
`session.update` error. Fix those in separately reviewed behavior changes;
|
||||
do not regenerate golden captures to make a refactor pass.
|
||||
|
||||
These checks use local fixtures and do not claim exhaustive coverage of all
|
||||
provider responses, live speech models, or production configuration. No deployed
|
||||
services or real credentials are needed. The Docker check verifies the actual
|
||||
runtime image, API configuration, documentation, OpenAPI, and the backend's
|
||||
existing root 404; it removes its temporary container and image afterward.
|
||||
@@ -99,7 +99,7 @@ realtime backend instead.
|
||||
|---|---|
|
||||
| Change the base agent prompt | `S2S_PRIMARY_PROMPT` or browser settings when unpinned |
|
||||
| Change browser context assembly | `buildInstructions()` in `s2s-frontend/src/lib/context.ts` |
|
||||
| Change HTTP provider messages | `reasoning()` in `server.py` |
|
||||
| Change HTTP provider messages | `reasoning()` in `s2s-client/s2s_client/services/reasoning.py` |
|
||||
| Change external-answer rendering | `VoiceController.reason()` and `RealtimeClient.renderExternalAnswer()` |
|
||||
| Change Node-RED processing | `s2s-reasoning-engine/flows.json` |
|
||||
| Change native model/tool generation | `speech_to_speech/LLM` and realtime handlers |
|
||||
|
||||
@@ -35,9 +35,10 @@ launcher. If the page loads but edits do not appear, check the browser's
|
||||
`/__vite_hmr` WebSocket and the reverse proxy's upgrade handling. Speech uses
|
||||
the separate `/v1/realtime` WebSocket on the same public origin.
|
||||
|
||||
For a startup dependency error, check Node/npm on the process manager's PATH,
|
||||
Python venv support, and `setsid`/`curl`. The first start installs dependencies;
|
||||
later starts reuse them until frontend manifests change. Changes to root
|
||||
For a startup dependency error, check uv 0.12.5 and Node/npm on the process
|
||||
manager's PATH, plus `setsid`/`curl`. uv manages Python 3.12 in
|
||||
`s2s-client/.venv` and checks the committed lock on every start. Frontend
|
||||
dependencies are reused until their manifests change. Changes to root
|
||||
`.env` or launcher settings require a restart.
|
||||
|
||||
## The assistant promises a tool but nothing happens
|
||||
@@ -126,7 +127,7 @@ From the repository root, run the frontend checks and local backend fixtures:
|
||||
```bash
|
||||
npm --prefix s2s-frontend run check
|
||||
npm --prefix s2s-frontend run build
|
||||
.venv/bin/python -m unittest discover -s s2s-client/tests -v
|
||||
make -C s2s-client check
|
||||
```
|
||||
|
||||
These checks cover frontend contracts and local session/queue/WebSocket
|
||||
|
||||
@@ -12,8 +12,8 @@ From the repository root:
|
||||
S2S_PROXY_TARGET=ws://localhost:8765/v1/realtime ./start_ui.sh
|
||||
```
|
||||
|
||||
The launcher loads the root `.env`, creates `.venv` if needed, installs the
|
||||
client requirements when the dependency check fails, and installs the locked
|
||||
The launcher loads the root `.env`, syncs `s2s-client/.venv` from the committed
|
||||
`s2s-client/uv.lock`, and installs the locked
|
||||
frontend dependencies when needed. Vite serves the React frontend on port
|
||||
8420 and proxies the backend routes to Uvicorn on `127.0.0.1:8421`.
|
||||
`UI_PORT` overrides the public port; `S2S_BACKEND_PORT` overrides the internal
|
||||
@@ -21,7 +21,7 @@ port. Both servers reload source edits, and stopping the launcher stops both.
|
||||
The speech pipeline remains a separate service. Because `.env` is sourced by
|
||||
the script, values in that file can replace variables supplied on the command line.
|
||||
|
||||
Use Node.js 22.18+ on the 22.x line or Node.js 24+, npm, Python 3 with venv,
|
||||
Use Node.js 22.18+ on the 22.x line or Node.js 24+, npm, uv 0.12.5,
|
||||
Bash 4.4+, `setsid`, and `curl`. Remote staging access also needs the exact
|
||||
hostname in `S2S_DEV_ALLOWED_HOSTS`, HTTPS, and WebSocket forwarding for speech
|
||||
and Vite HMR. See [frontend development setup](../../s2s-frontend/README.md).
|
||||
@@ -29,15 +29,18 @@ and Vite HMR. See [frontend development setup](../../s2s-frontend/README.md).
|
||||
To install and start the backend manually:
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
.venv/bin/python -m pip install -r s2s-client/requirements.txt
|
||||
uv sync --project s2s-client --locked
|
||||
S2S_PROXY_TARGET=ws://localhost:8765/v1/realtime \
|
||||
.venv/bin/python -m uvicorn --app-dir s2s-client server:app \
|
||||
uv run --project s2s-client --locked uvicorn --app-dir s2s-client s2s_client.main:app \
|
||||
--host 127.0.0.1 --port 8421 --reload --reload-dir s2s-client
|
||||
```
|
||||
|
||||
Then, in a second terminal, run `cd s2s-frontend`, `npm ci`, and `npm run dev`.
|
||||
|
||||
uv provisions Python 3.12 when needed. The Python environment belongs only to
|
||||
`s2s-client`; an existing root `.venv` for speech dependencies is left alone.
|
||||
See [development and compatibility](development.md) for checks and schema rules.
|
||||
|
||||
Open <http://localhost:8420/>, tap the orb/microphone control, grant microphone
|
||||
access, and speak. Microphone access requires HTTPS or a local browser origin;
|
||||
use HTTPS when accessing the UI from another machine.
|
||||
|
||||
Reference in New Issue
Block a user