File size: 6,659 Bytes
e43a4a9
 
 
 
adb34c2
 
 
 
e43a4a9
 
 
 
 
 
 
 
 
 
2671e04
e43a4a9
 
 
 
 
 
adb34c2
2671e04
adb34c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e43a4a9
 
 
 
 
adb34c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e43a4a9
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# 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`