diff --git a/.gitignore b/.gitignore index f254b5b..2f79ea2 100644 --- a/.gitignore +++ b/.gitignore @@ -38,8 +38,8 @@ node_modules/ .npm/ package-lock.json !speech_to_speech/package-lock.json -!frontend-s2s/package-lock.json -frontend-s2s/.eslintcache +!s2s-frontend/package-lock.json +s2s-frontend/.eslintcache yarn-error.log npm-debug.log* yarn-debug.log* diff --git a/README.md b/README.md index b27f90d..de06c9e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ documentation, source identifiers, comments, and internal instructions use Engli | Component | Purpose | |---|---| -| [frontend-s2s](frontend-s2s) | React, TypeScript, and Tailwind browser UI, served by Vite with hot reload | +| [s2s-frontend](s2s-frontend) | React, TypeScript, and Tailwind browser UI, served by Vite with hot reload | | [s2s-client](s2s-client) | FastAPI backend, realtime WebSocket proxy, search and ApiPilot bridges; retained static client | | [speech_to_speech](speech_to_speech) | Queue-driven VAD, speech recognition, language model, and speech synthesis pipeline | | [s2s-reasoning-engine](s2s-reasoning-engine) | Optional Node-RED HTTP reasoning and conversation logging flows | @@ -34,7 +34,7 @@ Leave `SPEECH_TO_SPEECH_URL` unset to use the same-origin speech proxy. The launcher requires Python 3 with venv support, Node.js 22.18+ on the 22.x line or Node.js 24+, npm, Bash 4.4+, `setsid`, and `curl`. For staging hostnames, set `S2S_DEV_ALLOWED_HOSTS` and forward the Vite HMR WebSocket through the existing -HTTPS reverse proxy. See [development setup](frontend-s2s/README.md). +HTTPS reverse proxy. See [development setup](s2s-frontend/README.md). The existing Docker image still serves the retained static client. To build it, use the repository root as the Docker build context so documentation is included: diff --git a/docs/client/architecture.md b/docs/client/architecture.md index 9d319ad..a5e9463 100644 --- a/docs/client/architecture.md +++ b/docs/client/architecture.md @@ -1,6 +1,6 @@ # Client architecture -The [React browser client](../../frontend-s2s) uses the +The [React browser client](../../s2s-frontend) uses the [FastAPI backend](../../s2s-client) for HTTP APIs and a speech WebSocket relay. `start_ui.sh` serves Vite on the existing public port `8420` and FastAPI on loopback port `8421`. Vite forwards backend routes and provides hot reload; @@ -44,13 +44,13 @@ audio. It is not an unconditional byte-for-byte tunnel. |---|---| | [server.py](../../s2s-client/server.py) | Configuration, static serving, WebSocket relay, context loading, ApiPilot, reasoning, search, queue and usage routes | | [start_ui.sh](../../start_ui.sh) | Dependency setup, ports, readiness, reload processes, and shutdown | -| [vite.config.ts](../../frontend-s2s/vite.config.ts) | Public development endpoint, HMR, allowed hosts, and backend routing | -| [App.tsx](../../frontend-s2s/src/App.tsx) | React layout, voice controls, dialogs, profile and reports sidebar | -| [controller.ts](../../frontend-s2s/src/realtime/controller.ts) | Application state, settings, context, queue, tools and external reasoning | -| [client.ts](../../frontend-s2s/src/realtime/client.ts) | Realtime protocol, session lifecycle, audio and transcript events | -| [components](../../frontend-s2s/src/components) | Chat, account, settings and voice components | -| [audio](../../frontend-s2s/src/audio) | TypeScript capture/playback worklets, PCM codec, and visualizer | -| [legacy-theme.css](../../frontend-s2s/src/styles/legacy-theme.css) | Retained themes and responsive visual styles alongside Tailwind | +| [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 | +| [controller.ts](../../s2s-frontend/src/realtime/controller.ts) | Application state, settings, context, queue, tools and external reasoning | +| [client.ts](../../s2s-frontend/src/realtime/client.ts) | Realtime protocol, session lifecycle, audio and transcript events | +| [components](../../s2s-frontend/src/components) | Chat, account, settings and voice components | +| [audio](../../s2s-frontend/src/audio) | TypeScript capture/playback worklets, PCM codec, and visualizer | +| [legacy-theme.css](../../s2s-frontend/src/styles/legacy-theme.css) | Retained themes and responsive visual styles alongside Tailwind | | [auth.py](../../s2s-client/auth.py) | Hugging Face OAuth and caller identity/tier | | [limiter.py](../../s2s-client/limiter.py) | SQLite daily talk-time reservations and reconciliation | | [flows.json](../../s2s-reasoning-engine/flows.json) | Node-RED reasoning and assistant-response logging | @@ -82,11 +82,11 @@ usage; its static responses retain the existing no-cache headers. 1. The browser captures microphone audio with echo cancellation, noise suppression and automatic gain-control settings. -2. [mic-capture.worklet.ts](../../frontend-s2s/src/audio/mic-capture.worklet.ts) resamples to 16 kHz +2. [mic-capture.worklet.ts](../../s2s-frontend/src/audio/mic-capture.worklet.ts) resamples to 16 kHz mono PCM16. The browser sends base64 `input_audio_buffer.append` frames. 3. The backend processes VAD → STT → LLM → TTS and emits realtime events. 4. Assistant PCM16 audio at the current 16 kHz protocol rate is decoded and sent to - [audio-playback.worklet.ts](../../frontend-s2s/src/audio/audio-playback.worklet.ts), which buffers, + [audio-playback.worklet.ts](../../s2s-frontend/src/audio/audio-playback.worklet.ts), which buffers, resamples and fades playback edges. Input speech can clear playback for barge-in. Audio worklets are loaded through `AudioWorklet.addModule`; keep their processor diff --git a/docs/client/usage.md b/docs/client/usage.md index cb72387..d533aa6 100644 --- a/docs/client/usage.md +++ b/docs/client/usage.md @@ -24,7 +24,7 @@ the script, values in that file can replace variables supplied on the command li Use Node.js 22.18+ on the 22.x line or Node.js 24+, npm, Python 3 with venv, 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](../../frontend-s2s/README.md). +and Vite HMR. See [frontend development setup](../../s2s-frontend/README.md). To install and start the backend manually: @@ -36,7 +36,7 @@ S2S_PROXY_TARGET=ws://localhost:8765/v1/realtime \ --host 127.0.0.1 --port 8421 --reload --reload-dir s2s-client ``` -Then, in a second terminal, run `cd frontend-s2s`, `npm ci`, and `npm run dev`. +Then, in a second terminal, run `cd s2s-frontend`, `npm ci`, and `npm run dev`. Open , tap the orb/microphone control, grant microphone access, and speak. Microphone access requires HTTPS or a local browser origin; diff --git a/s2s-client/README.md b/s2s-client/README.md index 81053b3..eff930a 100644 --- a/s2s-client/README.md +++ b/s2s-client/README.md @@ -16,7 +16,7 @@ FastAPI server and retained static voice-chat UI for an OpenAI Realtime-compatib speech-to-speech backend. The browser streams microphone audio over WebSocket, plays assistant audio, displays transcripts, and offers Spanish controls. -The root `start_ui.sh` now serves the [React frontend](../frontend-s2s) with +The root `start_ui.sh` now serves the [React frontend](../s2s-frontend) with Vite on public port `8420`, proxying backend requests here on loopback port `8421`. This directory's static UI remains available when FastAPI is run directly or through the existing Docker image. diff --git a/frontend-s2s/.editorconfig b/s2s-frontend/.editorconfig similarity index 100% rename from frontend-s2s/.editorconfig rename to s2s-frontend/.editorconfig diff --git a/frontend-s2s/.env.example b/s2s-frontend/.env.example similarity index 100% rename from frontend-s2s/.env.example rename to s2s-frontend/.env.example diff --git a/frontend-s2s/.gitignore b/s2s-frontend/.gitignore similarity index 100% rename from frontend-s2s/.gitignore rename to s2s-frontend/.gitignore diff --git a/frontend-s2s/.prettierignore b/s2s-frontend/.prettierignore similarity index 100% rename from frontend-s2s/.prettierignore rename to s2s-frontend/.prettierignore diff --git a/frontend-s2s/README.md b/s2s-frontend/README.md similarity index 99% rename from frontend-s2s/README.md rename to s2s-frontend/README.md index c02462e..9a7d498 100644 --- a/frontend-s2s/README.md +++ b/s2s-frontend/README.md @@ -49,7 +49,7 @@ variables, which are exposed to browser code. ## Staging with hot reload PM2 can continue running the root `start_ui.sh` as its existing `s2s_ui` process. -Ensure the Node/npm versions above are on PM2's PATH and deploy `frontend-s2s` +Ensure the Node/npm versions above are on PM2's PATH and deploy `s2s-frontend` alongside `s2s-client` and `docs`. The reverse proxy still targets port `8420`. Set the exact public hostname in the root `.env`, without scheme or port: @@ -74,7 +74,7 @@ Start FastAPI on `127.0.0.1:8421` as described in the [client usage guide](../docs/client/usage.md), then run: ```sh -cd frontend-s2s +cd s2s-frontend npm ci npm run dev ``` diff --git a/frontend-s2s/config/backend-proxy.ts b/s2s-frontend/config/backend-proxy.ts similarity index 100% rename from frontend-s2s/config/backend-proxy.ts rename to s2s-frontend/config/backend-proxy.ts diff --git a/frontend-s2s/config/launcher.integration.ts b/s2s-frontend/config/launcher.integration.ts similarity index 99% rename from frontend-s2s/config/launcher.integration.ts rename to s2s-frontend/config/launcher.integration.ts index 2720a82..cce8d11 100644 --- a/frontend-s2s/config/launcher.integration.ts +++ b/s2s-frontend/config/launcher.integration.ts @@ -64,7 +64,7 @@ async function waitForFile(filename: string) { async function launcher(context: TestContext, env: Record = {}) { const root = await mkdtemp(join(tmpdir(), "s2s-launcher-")); - const frontend = join(root, "frontend-s2s"); + const frontend = join(root, "s2s-frontend"); const modules = join(frontend, "node_modules"); await mkdir(join(root, ".venv/bin"), { recursive: true }); await mkdir(join(root, "s2s-client")); diff --git a/frontend-s2s/eslint.config.ts b/s2s-frontend/eslint.config.ts similarity index 100% rename from frontend-s2s/eslint.config.ts rename to s2s-frontend/eslint.config.ts diff --git a/frontend-s2s/index.html b/s2s-frontend/index.html similarity index 100% rename from frontend-s2s/index.html rename to s2s-frontend/index.html diff --git a/frontend-s2s/package-lock.json b/s2s-frontend/package-lock.json similarity index 99% rename from frontend-s2s/package-lock.json rename to s2s-frontend/package-lock.json index cf16217..e6de408 100644 --- a/frontend-s2s/package-lock.json +++ b/s2s-frontend/package-lock.json @@ -1,11 +1,11 @@ { - "name": "frontend-s2s", + "name": "s2s-frontend", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "frontend-s2s", + "name": "s2s-frontend", "version": "0.0.0", "dependencies": { "dompurify": "^3.4.16", diff --git a/frontend-s2s/package.json b/s2s-frontend/package.json similarity index 98% rename from frontend-s2s/package.json rename to s2s-frontend/package.json index c61a38a..795f737 100644 --- a/frontend-s2s/package.json +++ b/s2s-frontend/package.json @@ -1,5 +1,5 @@ { - "name": "frontend-s2s", + "name": "s2s-frontend", "private": true, "version": "0.0.0", "type": "module", diff --git a/frontend-s2s/prettier.config.ts b/s2s-frontend/prettier.config.ts similarity index 100% rename from frontend-s2s/prettier.config.ts rename to s2s-frontend/prettier.config.ts diff --git a/frontend-s2s/src/App.test.tsx b/s2s-frontend/src/App.test.tsx similarity index 100% rename from frontend-s2s/src/App.test.tsx rename to s2s-frontend/src/App.test.tsx diff --git a/frontend-s2s/src/App.tsx b/s2s-frontend/src/App.tsx similarity index 100% rename from frontend-s2s/src/App.tsx rename to s2s-frontend/src/App.tsx diff --git a/frontend-s2s/src/audio/audio-playback.worklet.ts b/s2s-frontend/src/audio/audio-playback.worklet.ts similarity index 100% rename from frontend-s2s/src/audio/audio-playback.worklet.ts rename to s2s-frontend/src/audio/audio-playback.worklet.ts diff --git a/frontend-s2s/src/audio/codec.ts b/s2s-frontend/src/audio/codec.ts similarity index 100% rename from frontend-s2s/src/audio/codec.ts rename to s2s-frontend/src/audio/codec.ts diff --git a/frontend-s2s/src/audio/engine.ts b/s2s-frontend/src/audio/engine.ts similarity index 100% rename from frontend-s2s/src/audio/engine.ts rename to s2s-frontend/src/audio/engine.ts diff --git a/frontend-s2s/src/audio/mic-capture.worklet.ts b/s2s-frontend/src/audio/mic-capture.worklet.ts similarity index 100% rename from frontend-s2s/src/audio/mic-capture.worklet.ts rename to s2s-frontend/src/audio/mic-capture.worklet.ts diff --git a/frontend-s2s/src/audio/worklet-globals.d.ts b/s2s-frontend/src/audio/worklet-globals.d.ts similarity index 100% rename from frontend-s2s/src/audio/worklet-globals.d.ts rename to s2s-frontend/src/audio/worklet-globals.d.ts diff --git a/frontend-s2s/src/components/Account.tsx b/s2s-frontend/src/components/Account.tsx similarity index 100% rename from frontend-s2s/src/components/Account.tsx rename to s2s-frontend/src/components/Account.tsx diff --git a/frontend-s2s/src/components/Bubbles.tsx b/s2s-frontend/src/components/Bubbles.tsx similarity index 100% rename from frontend-s2s/src/components/Bubbles.tsx rename to s2s-frontend/src/components/Bubbles.tsx diff --git a/frontend-s2s/src/components/Conversation.tsx b/s2s-frontend/src/components/Conversation.tsx similarity index 100% rename from frontend-s2s/src/components/Conversation.tsx rename to s2s-frontend/src/components/Conversation.tsx diff --git a/frontend-s2s/src/components/Dialog.tsx b/s2s-frontend/src/components/Dialog.tsx similarity index 100% rename from frontend-s2s/src/components/Dialog.tsx rename to s2s-frontend/src/components/Dialog.tsx diff --git a/frontend-s2s/src/components/SettingsDialogs.tsx b/s2s-frontend/src/components/SettingsDialogs.tsx similarity index 100% rename from frontend-s2s/src/components/SettingsDialogs.tsx rename to s2s-frontend/src/components/SettingsDialogs.tsx diff --git a/frontend-s2s/src/components/VoiceStage.tsx b/s2s-frontend/src/components/VoiceStage.tsx similarity index 100% rename from frontend-s2s/src/components/VoiceStage.tsx rename to s2s-frontend/src/components/VoiceStage.tsx diff --git a/frontend-s2s/src/hooks/use-wake-word.ts b/s2s-frontend/src/hooks/use-wake-word.ts similarity index 100% rename from frontend-s2s/src/hooks/use-wake-word.ts rename to s2s-frontend/src/hooks/use-wake-word.ts diff --git a/frontend-s2s/src/lib/api.ts b/s2s-frontend/src/lib/api.ts similarity index 100% rename from frontend-s2s/src/lib/api.ts rename to s2s-frontend/src/lib/api.ts diff --git a/frontend-s2s/src/lib/context.ts b/s2s-frontend/src/lib/context.ts similarity index 100% rename from frontend-s2s/src/lib/context.ts rename to s2s-frontend/src/lib/context.ts diff --git a/frontend-s2s/src/lib/contracts.ts b/s2s-frontend/src/lib/contracts.ts similarity index 100% rename from frontend-s2s/src/lib/contracts.ts rename to s2s-frontend/src/lib/contracts.ts diff --git a/frontend-s2s/src/lib/messages.test.ts b/s2s-frontend/src/lib/messages.test.ts similarity index 100% rename from frontend-s2s/src/lib/messages.test.ts rename to s2s-frontend/src/lib/messages.test.ts diff --git a/frontend-s2s/src/lib/messages.ts b/s2s-frontend/src/lib/messages.ts similarity index 100% rename from frontend-s2s/src/lib/messages.ts rename to s2s-frontend/src/lib/messages.ts diff --git a/frontend-s2s/src/lib/profile.ts b/s2s-frontend/src/lib/profile.ts similarity index 100% rename from frontend-s2s/src/lib/profile.ts rename to s2s-frontend/src/lib/profile.ts diff --git a/frontend-s2s/src/lib/reports.ts b/s2s-frontend/src/lib/reports.ts similarity index 100% rename from frontend-s2s/src/lib/reports.ts rename to s2s-frontend/src/lib/reports.ts diff --git a/frontend-s2s/src/lib/settings.ts b/s2s-frontend/src/lib/settings.ts similarity index 100% rename from frontend-s2s/src/lib/settings.ts rename to s2s-frontend/src/lib/settings.ts diff --git a/frontend-s2s/src/main.tsx b/s2s-frontend/src/main.tsx similarity index 100% rename from frontend-s2s/src/main.tsx rename to s2s-frontend/src/main.tsx diff --git a/frontend-s2s/src/realtime/client.test.ts b/s2s-frontend/src/realtime/client.test.ts similarity index 100% rename from frontend-s2s/src/realtime/client.test.ts rename to s2s-frontend/src/realtime/client.test.ts diff --git a/frontend-s2s/src/realtime/client.ts b/s2s-frontend/src/realtime/client.ts similarity index 100% rename from frontend-s2s/src/realtime/client.ts rename to s2s-frontend/src/realtime/client.ts diff --git a/frontend-s2s/src/realtime/controller.test.ts b/s2s-frontend/src/realtime/controller.test.ts similarity index 100% rename from frontend-s2s/src/realtime/controller.test.ts rename to s2s-frontend/src/realtime/controller.test.ts diff --git a/frontend-s2s/src/realtime/controller.ts b/s2s-frontend/src/realtime/controller.ts similarity index 100% rename from frontend-s2s/src/realtime/controller.ts rename to s2s-frontend/src/realtime/controller.ts diff --git a/frontend-s2s/src/styles.css b/s2s-frontend/src/styles.css similarity index 100% rename from frontend-s2s/src/styles.css rename to s2s-frontend/src/styles.css diff --git a/frontend-s2s/src/styles/legacy-theme.css b/s2s-frontend/src/styles/legacy-theme.css similarity index 100% rename from frontend-s2s/src/styles/legacy-theme.css rename to s2s-frontend/src/styles/legacy-theme.css diff --git a/frontend-s2s/src/test/backend-proxy.test.ts b/s2s-frontend/src/test/backend-proxy.test.ts similarity index 100% rename from frontend-s2s/src/test/backend-proxy.test.ts rename to s2s-frontend/src/test/backend-proxy.test.ts diff --git a/frontend-s2s/src/test/setup.ts b/s2s-frontend/src/test/setup.ts similarity index 100% rename from frontend-s2s/src/test/setup.ts rename to s2s-frontend/src/test/setup.ts diff --git a/frontend-s2s/tsconfig.app.json b/s2s-frontend/tsconfig.app.json similarity index 100% rename from frontend-s2s/tsconfig.app.json rename to s2s-frontend/tsconfig.app.json diff --git a/frontend-s2s/tsconfig.json b/s2s-frontend/tsconfig.json similarity index 100% rename from frontend-s2s/tsconfig.json rename to s2s-frontend/tsconfig.json diff --git a/frontend-s2s/tsconfig.node.json b/s2s-frontend/tsconfig.node.json similarity index 100% rename from frontend-s2s/tsconfig.node.json rename to s2s-frontend/tsconfig.node.json diff --git a/frontend-s2s/vite.config.ts b/s2s-frontend/vite.config.ts similarity index 100% rename from frontend-s2s/vite.config.ts rename to s2s-frontend/vite.config.ts diff --git a/frontend-s2s/vitest.config.ts b/s2s-frontend/vitest.config.ts similarity index 100% rename from frontend-s2s/vitest.config.ts rename to s2s-frontend/vitest.config.ts diff --git a/start_ui.sh b/start_ui.sh index 8381a5d..d2ea824 100755 --- a/start_ui.sh +++ b/start_ui.sh @@ -4,7 +4,7 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" VENV_DIR="$ROOT_DIR/.venv" REQ_FILE="$ROOT_DIR/s2s-client/requirements.txt" -FRONTEND_DIR="$ROOT_DIR/frontend-s2s" +FRONTEND_DIR="$ROOT_DIR/s2s-frontend" if [ -f "$ROOT_DIR/.env" ]; then set -a source "$ROOT_DIR/.env" @@ -28,7 +28,7 @@ for required_command in python3 node npm setsid curl; do done if ! node -e 'const [major, minor] = process.versions.node.split(".").map(Number); process.exit((major === 22 && minor >= 18) || major >= 24 ? 0 : 1)'; then - echo "Error: frontend-s2s requires Node.js 22.18+ on the 22.x line, or Node.js 24+." + echo "Error: s2s-frontend requires Node.js 22.18+ on the 22.x line, or Node.js 24+." exit 1 fi @@ -67,7 +67,7 @@ fi if [ ! -f "$FRONTEND_DIR/node_modules/vite/bin/vite.js" ] || \ ! cmp -s "$FRONTEND_DIR/package-lock.json" "$FRONTEND_DIR/node_modules/.s2s-package-lock.json" || \ ! cmp -s "$FRONTEND_DIR/package.json" "$FRONTEND_DIR/node_modules/.s2s-package.json"; then - echo "Installing frontend dependencies from frontend-s2s/package-lock.json..." + echo "Installing frontend dependencies from s2s-frontend/package-lock.json..." npm --prefix "$FRONTEND_DIR" ci --include=dev cp "$FRONTEND_DIR/package-lock.json" "$FRONTEND_DIR/node_modules/.s2s-package-lock.json" cp "$FRONTEND_DIR/package.json" "$FRONTEND_DIR/node_modules/.s2s-package.json"