# DeepSeek Harness (DSH) — Architecture & Integration Spec ## 1. System Overview **DeepSeek Harness (`dsh`)** is a single-user, multi-tenant streaming chat web application that serves as the AI chat interface for Family Home Lab members. Instead of running a single shared application with multi-user authentication, DSH is deployed as **isolated, per-user container instances** on `.13`. The portal (`console.lab.audasmedia.com.au`) embeds each user's dedicated DSH instance inline via iframe or links directly to their subdomains (`https://dsh-{username}.lab.audasmedia.com.au`). --- ## 2. Multi-Tenancy & Port Allocation Each family member gets a dedicated DSH container instance running on host `.13`: | User | Subdomain | Host Port | Container Name | Host Workspace Directory | | :--- | :--- | :--- | :--- | :--- | | **Sam** | `dsh-sam.lab.audasmedia.com.au` | `3081` | `dsh-sam` | `/mnt/data/family-home-lab/dsh/sam` | | **Jo** | `dsh-jo.lab.audasmedia.com.au` | `3082` | `dsh-jo` | `/mnt/data/family-home-lab/dsh/jo` | | **Harry** | `dsh-harry.lab.audasmedia.com.au` | `3083` | `dsh-harry` | `/mnt/data/family-home-lab/dsh/harry` | | **Finn** | `dsh-finn.lab.audasmedia.com.au` | `3084` | `dsh-finn` | `/mnt/data/family-home-lab/dsh/finn` | ### Reverse Proxy & Routing - Caddy on `.35` terminates HTTPS for `dsh-*.lab.audasmedia.com.au` and proxies traffic to `.13:{port}`. - Portal `tools.py` dynamically resolves the user's DSH URL via `_dsh_for_user(user)` based on their authenticated portal session. --- ## 3. Storage & Session Persistence Chat history and sessions are stored directly as JSON files inside each container's `/workspace/sessions/` directory (mapped to host `/mnt/data/family-home-lab/dsh/{user}`): ### Session Directory Structure ``` /workspace/ ├── sessions/ │ ├── main.json │ ├── session-172840192.json │ └── ... └── uploads/ ``` ### Session File Schema (`sessions/{id}.json`) ```json { "id": "session-172840192", "name": "Project discussion", "updated": "2026-10-08T19:30:00Z", "messages": [ { "role": "user", "content": "Summarise the home lab setup", "timestamp": 172840191 }, { "role": "assistant", "content": "The family home lab consists of...", "timestamp": 172840192 } ] } ``` --- ## 4. Multi-Model Routing & External Integration Table DSH routes user requests across specialized AI services and local house infrastructure: | Function | Backend Endpoint | Model / Engine | Environment Variable | | :--- | :--- | :--- | :--- | | **Text Chat (SSE Stream)** | `http://192.168.20.13:20129/v1` | `auto/best-chat` (OmniRoute) | `DSH_LLM_BASE`, `DSH_LLM_MODEL` | | **Vision (Image Ingest)** | `https://openrouter.ai/api/v1` | `openai/gpt-5` | `DSH_VISION_BASE`, `DSH_VISION_MODEL` | | **Speech-to-Text (STT)** | `http://192.168.20.13:5000/transcribe` | `faster-whisper` (`voice_whisper`) | `DSH_WHISPER_URL` | | **Voice Agent (Action/TTS)** | `http://192.168.20.13:8501/voice` | Jervis Voice Agent | `DSH_VOICE_AGENT_URL` | | **Image Generation** | `https://openrouter.ai/api/v1` | `openai/gpt-image-1` | `DSH_IMAGE_MODEL` | | **Video Generation** | `https://openrouter.ai/api/v1` | `z-ai/glm-5v-turbo` | `DSH_VIDEO_MODEL` | --- ## 5. API Endpoints & Request Flow ### Primary API Routes (`dsh/app.py`) | Method | Route | Description | | :--- | :--- | :--- | | `GET` | `/` | Serves main single-page chat UI (`templates/chat.html`). | | `POST` | `/chat/stream` | Primary chat endpoint. Receives `{message, session_id}`,Streams response via Server-Sent Events (SSE). | | `POST` | `/transcribe` | Uploads `.wav`/`.mp3`/`.m4a` file; forwards to `voice_whisper` (`:5000`); returns transcribed text. | | `POST` | `/upload-image` | Uploads image; forwards to Vision model (`openai/gpt-5`) with user prompt; returns image description. | | `POST` | `/voice-agent` | Forwards prompt to Jervis Voice Agent (`:8501`); triggers house audio/action. | | `POST` | `/generate-image` | Generates image via OpenRouter API and saves output to workspace. | | `POST` | `/generate-video` | Generates video via OpenRouter API and saves output to workspace. | | `GET` | `/sessions` | Returns list of all session summaries for the current user. | | `POST` | `/sessions/new` | Creates a new conversation session. | | `POST` | `/sessions/{id}/delete` | Deletes a conversation session file. | --- ## 6. Embedding & Security Headers To support seamless inline framing inside the Family Home Lab Console (`/tool/dsh`): - **Content Security Policy (CSP)**: `frame-ancestors https://console.lab.audasmedia.com.au` - **X-Frame-Options**: Explicitly omitted (not set to `DENY` or `SAMEORIGIN`), allowing Caddy and Portal to frame DSH cleanly. --- ## 7. Environment Variables Reference | Variable | Default Value | Purpose | | :--- | :--- | :--- | | `DSH_USER` | `user` | Name of the user (e.g., `sam`, `jo`). | | `DSH_SLOT` | `Welcome to DeepSeek Harness` | Subtitle/greeting shown in the header. | | `DSH_LLM_BASE` | `http://192.168.20.13:20129/v1` | OmniRoute OpenAI-compatible base URL. | | `DSH_LLM_MODEL` | `auto/best-chat` | Default model passed to OmniRoute. | | `DSH_LLM_KEY` | `""` | Optional API key for OmniRoute. | | `DSH_SYSTEM_PROMPT` | `"You are {USER_NAME}'s helpful DeepSeek assistant..."` | Custom system prompt per user instance. | | `DSH_VISION_BASE` | `https://openrouter.ai/api/v1` | OpenRouter base URL for multimodal vision. | | `DSH_VISION_MODEL` | `openai/gpt-5` | Multimodal model for image analysis. | | `DSH_WHISPER_URL` | `http://192.168.20.13:5000/transcribe` | Local faster-whisper STT service. | | `DSH_VOICE_AGENT_URL` | `http://192.168.20.13:8501/voice` | Jervis Voice Agent execution endpoint. | | `DSH_HISTORY_DIR` | `/workspace` | Mount point for history and session storage. |