| # Overview | |
| ## Current Status | |
| - Project type: Node.js OpenAI-compatible chat completions proxy with a browser chat client. | |
| - Status: backend proxy is working, and `public/chatclient/` now provides a simplified tabbed rich-text workspace with auto-saved draft input, settings, image/audio attachments by upload or link, assistant output rendering, and raw response inspection. | |
| - Verified with `npm test`, `npm run build`, and `node --check` on the browser chat client modules. | |
| - Build output folder: `C:\Users\a\AppData\Local\Temp\oapix-chatclient-preview-build` | |
| ## What The App Does | |
| - Exposes `POST /v1/chat/completions` as a proxy to an OpenAI-compatible upstream base URL. | |
| - Accepts image input as URL, data URL, or raw base64 on `image_url.url`. | |
| - Accepts audio input as base64 on `input_audio.data` or as `input_audio.url`. | |
| - Downloads audio URLs, converts them to mp3, base64-encodes them, and forwards them upstream. | |
| - Exposes audio output base64 as a temporary proxy URL on non-stream responses. | |
| - Exposes image data URLs returned by compatible upstreams as temporary proxy URLs on non-stream responses. | |
| - Exposes `GET /v1/media/:mediaId` for temporary media retrieval and `GET /v1/health` for health checks. | |
| - Serves a landing page from `/` and an interactive demo chat client from `/chatclient/`. | |
| ## Runtime Notes | |
| - Configure `OPENAI_API_KEY` and `OPENAI_BASE_URL` in the local `.env` file. | |
| - Media files are stored in memory and expire after `MEDIA_TTL_SECONDS`. | |
| - Stream responses are passed through directly and do not get extra proxy media URLs added. | |
| - The build script writes a bundled server file and static assets into the temp build folder. | |
| - Static frontend files are served directly from `public/` with a service worker for cached HTML, CSS, and JS. | |
| - The chat client stores endpoint, model, system prompt, audio toggle, and voice settings in browser local storage. | |
| - The chat client also auto-saves compose draft HTML, link-picker state, and link-based attachments in browser local storage. | |
| ## Chat Client Status | |
| - Compose tab: contenteditable rich text editor with basic formatting tools and `Ctrl+Enter` send. | |
| - Layout: the large intro/header block and Back button were removed, leaving a compact top tab bar. | |
| - Tool row: single-line icon toolbar with settings, add-attachment, and a right-aligned send button. | |
| - Settings panel: endpoint, model, system prompt, audio output, and voice selection. | |
| - Output tab: formatted assistant text plus returned image and audio media. | |
| - Raw Output tab: exact JSON returned by the proxy, plus structured error output on failed requests. | |
| - Attachment flow: image/audio attachments can be added by uploaded file or direct `http(s)` link; image files are sent as data URLs, audio files are sent as base64 with format metadata, and links are forwarded as URLs. | |
| - Attachment preview: attachments render as compact mini items, and clicking one opens a larger preview overlay for the selected image or audio. | |
| - Draft flow: editor content and link-based compose state restore automatically when `/chatclient/` is reopened. | |
| - Send behavior: clicking Send switches to the Output tab immediately, and successful requests keep both the editor prompt text and current attachments in place. | |
| ## Project Structure | |
| ```text | |
| oapix/ | |
| |-- .env.example # Example environment variables for local setup | |
| |-- .gitignore # Node.js and local-secret ignore rules | |
| |-- package-lock.json # Locked dependency versions | |
| |-- package.json # Scripts, runtime deps, and build deps | |
| |-- doc/ | |
| | |-- agent.md # Human-maintained task instructions for agents | |
| | |-- common_mistakes.md # Project-specific pitfalls to avoid | |
| | |-- overview.md # Current project status, structure, and file map | |
| | |-- update.md # Latest finished task summary | |
| | `-- updates.md # Historical task log, newest first | |
| |-- public/ | |
| | |-- app.js # Landing-page script and service-worker registration | |
| | |-- index.html # Landing page with proxy overview and links | |
| | |-- styles.css # Landing-page styles | |
| | |-- sw-register.js # Shared service-worker registration helper | |
| | `-- sw.js # Offline cache and timed refresh logic | |
| |-- public/chatclient/ | |
| | |-- app.js # Chat client controller, tabs, send flow, draft restore, and local state | |
| | |-- draft.js # Browser-local draft persistence for compose input and link attachments | |
| | |-- index.html # Tabbed chat client shell and settings/output panels | |
| | |-- media.js # Attachment creation from uploads/links, previews, and payload conversion | |
| | |-- preview.js # Large attachment preview overlay controller | |
| | |-- render.js # Attachment list rendering, assistant rendering, and status/toast UI | |
| | |-- richText.js # Safe rich-text rendering helpers for assistant output | |
| | |-- settings.js # Browser-local chat client settings persistence | |
| | `-- styles.css # Chat client workspace styles | |
| |-- scripts/ | |
| | `-- build.mjs # Temp-folder build output script | |
| |-- src/ | |
| | |-- app.js # Express app factory and error handling | |
| | |-- config.js # Env loading and validation | |
| | |-- server.js # Dependency wiring and server startup | |
| | |-- controllers/ | |
| | | |-- chatController.js # Chat proxy request handling | |
| | | `-- mediaController.js # Temporary media download handling | |
| | |-- routes/ | |
| | | `-- apiRouter.js # `/v1` routes | |
| | |-- services/ | |
| | | |-- audioConversionService.js # Audio URL download and mp3 conversion | |
| | | |-- mediaStore.js # In-memory temporary media storage | |
| | | |-- openAiService.js # Upstream OpenAI-compatible fetch client | |
| | | |-- requestNormalizationService.js # Input media normalization | |
| | | `-- responseNormalizationService.js # Output media normalization | |
| | `-- utils/ | |
| | |-- dataUrl.js # Data URL and base64 helpers | |
| | |-- httpError.js # HTTP error shape | |
| | `-- mediaTypes.js # Audio/image MIME helpers | |
| `-- test/ | |
| |-- requestNormalization.test.js # Request normalization tests | |
| `-- responseNormalization.test.js# Response normalization tests | |
| ``` | |
| ## Main Commands | |
| - `npm install` | |
| - `npm start` | |
| - `npm test` | |
| - `npm run build` | |