# 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`