orbitchat 2.13.1 → 2.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +271 -219
  2. package/bin/dev-server.js +0 -3
  3. package/bin/orbitchat.js +146 -82
  4. package/dist/assets/_baseUniq-BRKsqoH--CzpIYnbF.js +1 -0
  5. package/dist/assets/{arc-pab_su9s-DFq3JYvb.js → arc-pab_su9s-DhurQhL4.js} +1 -1
  6. package/dist/assets/{architectureDiagram-VXUJARFQ-DqQ8r_6g-ejnypLyO.js → architectureDiagram-VXUJARFQ-DqQ8r_6g-eqA8fOch.js} +1 -1
  7. package/dist/assets/{blockDiagram-VD42YOAC-B-dKfcH3-Bgo8FU6J.js → blockDiagram-VD42YOAC-B-dKfcH3-DT3R176S.js} +4 -4
  8. package/dist/assets/{c4Diagram-YG6GDRKO-DMUPaBEl-CX9lx-UK.js → c4Diagram-YG6GDRKO-DMUPaBEl-q6bAZUce.js} +1 -1
  9. package/dist/assets/channel-HKsfPa5q-DshlUHWu.js +1 -0
  10. package/dist/assets/{chunk-4BX2VUAB-CX67kh_B-Dm2c-Lyy.js → chunk-4BX2VUAB-CX67kh_B-gkWPpLiy.js} +1 -1
  11. package/dist/assets/{chunk-55IACEB6-BocSyyvr-lclbFu9j.js → chunk-55IACEB6-BocSyyvr-9ksZ29Ab.js} +1 -1
  12. package/dist/assets/{chunk-B4BG7PRW-CO8QAyfE-CvvrZ063.js → chunk-B4BG7PRW-CO8QAyfE-CNBeArXO.js} +1 -1
  13. package/dist/assets/{chunk-DI55MBZ5-Dw1L6Eos-BuD2OREa.js → chunk-DI55MBZ5-Dw1L6Eos-BVbGVMNG.js} +3 -3
  14. package/dist/assets/{chunk-FMBD7UC4-dPK7Boav-D0ZlDI-s.js → chunk-FMBD7UC4-dPK7Boav-tO950uDG.js} +1 -1
  15. package/dist/assets/{chunk-QN33PNHL-vP2PqfVG-DqaIoebO.js → chunk-QN33PNHL-vP2PqfVG-Y3PYDsm9.js} +1 -1
  16. package/dist/assets/{chunk-QZHKN3VN-Bcidzu63-DG8agfQA.js → chunk-QZHKN3VN-Bcidzu63-BAQ3PYro.js} +1 -1
  17. package/dist/assets/{chunk-TZMSLE5B-BtljMjlg-B6xEnbcW.js → chunk-TZMSLE5B-BtljMjlg-CwIvybWR.js} +1 -1
  18. package/dist/assets/{classDiagram-2ON5EDUG-C7cYN9hv-Dd-YCt5Q.js → classDiagram-2ON5EDUG-C7cYN9hv-CGN1Rq_o.js} +1 -1
  19. package/dist/assets/{classDiagram-v2-WZHVMYZB-C7cYN9hv-Dd-YCt5Q.js → classDiagram-v2-WZHVMYZB-C7cYN9hv-CGN1Rq_o.js} +1 -1
  20. package/dist/assets/clone-DoPb9X13-C3rfr14F.js +1 -0
  21. package/dist/assets/{cose-bilkent-S5V4N54A-BGzO4EsH-BMVWyh_a.js → cose-bilkent-S5V4N54A-BGzO4EsH-DtYXpCOp.js} +1 -1
  22. package/dist/assets/{dagre-6UL2VRFP-TzNvXCds-CbmhexaH.js → dagre-6UL2VRFP-TzNvXCds-xMthYtzg.js} +1 -1
  23. package/dist/assets/{diagram-PSM6KHXK-BqY4RpUg-BqmtaKLy.js → diagram-PSM6KHXK-BqY4RpUg-CtQy_-7V.js} +1 -1
  24. package/dist/assets/{diagram-QEK2KX5R-CTjgBsne-Dbl2BvQJ.js → diagram-QEK2KX5R-CTjgBsne-DROkeGJL.js} +1 -1
  25. package/dist/assets/{diagram-S2PKOQOG-BqrhTIpA-DnNkr8UG.js → diagram-S2PKOQOG-BqrhTIpA-Bv0e-7TM.js} +2 -2
  26. package/dist/assets/{erDiagram-Q2GNP2WA-B2hsi_Tl-r9lLCSiy.js → erDiagram-Q2GNP2WA-B2hsi_Tl-BbvH-Jb1.js} +1 -1
  27. package/dist/assets/{flowDiagram-NV44I4VS-C03vtt_F-Bj1MoEwx.js → flowDiagram-NV44I4VS-C03vtt_F-DT9Y-btb.js} +1 -1
  28. package/dist/assets/{ganttDiagram-JELNMOA3-B3hAg964-CCnbkzn3.js → ganttDiagram-JELNMOA3-B3hAg964-CnqUJtIB.js} +1 -1
  29. package/dist/assets/{gitGraphDiagram-NY62KEGX-ByhMH0yZ-YRu-SLHD.js → gitGraphDiagram-NY62KEGX-ByhMH0yZ-CdQlDU7A.js} +3 -3
  30. package/dist/assets/{graph-BmNkcFEM-dUEThWgx.js → graph-BmNkcFEM-mCcAnvHY.js} +1 -1
  31. package/dist/assets/{index-BXexqYFc-6FZAvmAF.js → index-BXexqYFc-D_cjFmh8.js} +1 -1
  32. package/dist/assets/index-DBOy9259.css +1 -0
  33. package/dist/assets/{index-BTk6gbYa.js → index-zlswAhjt.js} +219 -239
  34. package/dist/assets/infoDiagram-WHAUD3N6-is6Ho4-T-BHS1wv7y.js +2 -0
  35. package/dist/assets/{journeyDiagram-XKPGCS4Q-CRTOL26C-BslRBPzU.js → journeyDiagram-XKPGCS4Q-CRTOL26C-DkQ68DJ6.js} +1 -1
  36. package/dist/assets/{kanban-definition-3W4ZIXB7-CNnO_t6O-C2MPRjuS.js → kanban-definition-3W4ZIXB7-CNnO_t6O-DWZm5JX4.js} +6 -6
  37. package/dist/assets/{layout-C0kZPebx-DBUyCsod.js → layout-C0kZPebx-CygTh9Uo.js} +1 -1
  38. package/dist/assets/min-7Gb0pNxh-BfuBtSqq.js +1 -0
  39. package/dist/assets/{mindmap-definition-VGOIOE7T-CJZ2wTTa-DP1XV6kP.js → mindmap-definition-VGOIOE7T-CJZ2wTTa-B7rvUdG3.js} +1 -1
  40. package/dist/assets/{pieDiagram-ADFJNKIX-C9OSknjr-BdkTw8nn.js → pieDiagram-ADFJNKIX-C9OSknjr-eiZAefZN.js} +2 -2
  41. package/dist/assets/{quadrantDiagram-AYHSOK5B-CW8yuAqv-BcCv0sYD.js → quadrantDiagram-AYHSOK5B-CW8yuAqv-DzBEpWQk.js} +3 -3
  42. package/dist/assets/{requirementDiagram-UZGBJVZJ-nGPhruO1-CZD7Xw4s.js → requirementDiagram-UZGBJVZJ-nGPhruO1-z5Z4Fwg9.js} +1 -1
  43. package/dist/assets/{sankeyDiagram-TZEHDZUN-CmL90u-m-BicoH15o.js → sankeyDiagram-TZEHDZUN-CmL90u-m-Dk028WXo.js} +3 -3
  44. package/dist/assets/{sequenceDiagram-WL72ISMW-B02VRcnM-CvY3TSCC.js → sequenceDiagram-WL72ISMW-B02VRcnM-Cz8sPx_Q.js} +7 -7
  45. package/dist/assets/{stateDiagram-FKZM4ZOC-DjoyLUdz-Cy3GdNKr.js → stateDiagram-FKZM4ZOC-DjoyLUdz-BxsZBi1n.js} +1 -1
  46. package/dist/assets/{stateDiagram-v2-4FDKWEC3-Bq76BTB7-BTj88h18.js → stateDiagram-v2-4FDKWEC3-Bq76BTB7-BTybFIdr.js} +1 -1
  47. package/dist/assets/{timeline-definition-IT6M3QCI-CTn0Gm3T-BPnEK60y.js → timeline-definition-IT6M3QCI-CTn0Gm3T-CI07_-Ei.js} +1 -1
  48. package/dist/assets/{treemap-KMMF4GRG-BjgLKKyi-Dpn6IoCt.js → treemap-KMMF4GRG-BjgLKKyi-Dg9N7uMT.js} +1 -1
  49. package/dist/assets/{xychartDiagram-PRI3JC2R-Cgg6Uija-B3NNTn5p.js → xychartDiagram-PRI3JC2R-Cgg6Uija-BDR2Lfu_.js} +4 -4
  50. package/dist/index.html +2 -2
  51. package/package.json +2 -2
  52. package/dist/assets/__vite-browser-external-BIHI7g3E.js +0 -1
  53. package/dist/assets/_baseUniq-BRKsqoH--BnZ8jILn.js +0 -1
  54. package/dist/assets/api-C90fNFdj.js +0 -2
  55. package/dist/assets/api-Dg2si9TY.js +0 -2
  56. package/dist/assets/channel-HKsfPa5q-i-PY3wcB.js +0 -1
  57. package/dist/assets/clone-DoPb9X13-DxnBl06F.js +0 -1
  58. package/dist/assets/index-BjgS88qB.css +0 -1
  59. package/dist/assets/infoDiagram-WHAUD3N6-is6Ho4-T-BLBpQ0kq.js +0 -2
  60. package/dist/assets/min-7Gb0pNxh-9FduVVTw.js +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ORBIT Chat App
2
2
 
3
- A standalone chat application for ORBIT that can be installed as an npm package and run as a CLI tool. Integrates with the `@schmitech/chatbot-api` package for real-time streaming chat responses and uses the open-source [`@schmitech/markdown-renderer`](https://github.com/schmitech/markdown-renderer) for rich content display including math and charts.
3
+ A standalone chat application for ORBIT that can be installed as an npm package and run as a CLI tool. All API communication is routed through a built-in Express proxy that maps adapter names to backend API keys, so **no secrets ever reach the browser**. Uses the open-source [`@schmitech/markdown-renderer`](https://github.com/schmitech/markdown-renderer) for rich content display including math and charts.
4
4
 
5
5
  ## Installation
6
6
 
@@ -16,58 +16,217 @@ Or install locally:
16
16
  npm install orbitchat
17
17
  ```
18
18
 
19
- ## Usage
19
+ ## Quick Start
20
20
 
21
- ### CLI Tool
21
+ 1. Define your adapters (agents) via the `ORBIT_ADAPTERS` or `VITE_ADAPTERS` environment variable:
22
+ ```bash
23
+ export ORBIT_ADAPTERS='[
24
+ {"name":"Simple Chat","apiKey":"my-key","apiUrl":"http://localhost:3000","description":"Default conversational agent."}
25
+ ]'
26
+ ```
22
27
 
23
- After installing globally, run:
24
- ```bash
25
- orbitchat
28
+ 2. Run the CLI:
29
+ ```bash
30
+ orbitchat --enable-upload --port 5173
31
+ ```
32
+
33
+ 3. Open `http://localhost:5173` — select an agent and start chatting.
34
+
35
+ ## Architecture
36
+
37
+ ```
38
+ Browser ──X-Adapter-Name──▶ Express proxy ──X-API-Key──▶ ORBIT backend
39
+ (bin/orbitchat.js)
26
40
  ```
27
41
 
28
- The app will start a server at `http://localhost:5173` by default.
42
+ The frontend never handles API keys. Instead:
43
+ - The browser sends an `X-Adapter-Name` header with every API request.
44
+ - The Express proxy looks up the adapter, injects the real `X-API-Key`, and forwards the request to the configured backend URL.
45
+ - `GET /api/adapters` returns only adapter names and descriptions — never keys or URLs.
29
46
 
30
- #### CLI Options
47
+ ## CLI Options
31
48
 
32
49
  ```bash
33
50
  orbitchat [options]
34
51
 
35
52
  Options:
36
- --api-url URL API URL (default: http://localhost:3000)
37
- --default-adapter NAME Default adapter to preselect when middleware is enabled
38
- --api-key KEY Default API key (default: default-key)
39
- --use-local-api BOOLEAN Use local API build (default: false)
40
- --local-api-path PATH Path to local API
41
- --console-debug BOOLEAN Enable console debug (default: false)
42
- --enable-upload BOOLEAN Enable upload button (default: false)
43
- --enable-feedback BOOLEAN Enable feedback buttons (default: false)
53
+ --api-url URL Default backend URL (default: http://localhost:3000)
54
+ --default-adapter NAME Adapter to preselect for new conversations
55
+ --application-name NAME Name shown in browser tab (default: ORBIT Chat)
56
+ --application-description TEXT Subtitle shown under the welcome heading
57
+ --default-input-placeholder TEXT Message input placeholder (default: Message ORBIT...)
58
+ --console-debug Enable console debug logging (default: false)
59
+ --enable-upload Enable file upload button (default: false)
60
+ --enable-audio Enable audio output button (default: false)
61
+ --enable-audio-input Enable microphone input button (default: false)
62
+ --enable-feedback Enable feedback buttons (default: false)
63
+ --enable-autocomplete Enable autocomplete suggestions (default: false)
64
+ --voice-silence-timeout-ms N Auto-stop voice capture after N ms of silence (default: 4000)
65
+ --voice-recognition-lang LANG Speech recognition language code (default: browser locale)
66
+ --out-of-service-message TEXT Show maintenance screen blocking access
44
67
  --max-files-per-conversation N Max files per conversation (default: 5)
45
68
  --max-file-size-mb N Max file size in MB (default: 50)
46
69
  --max-total-files N Max total files (default: 100, 0 = unlimited)
47
70
  --max-conversations N Max conversations (default: 10, 0 = unlimited)
48
71
  --max-messages-per-conversation N Max messages per conversation (default: 1000, 0 = unlimited)
72
+ --max-messages-per-thread N Max messages per thread (default: 1000, 0 = unlimited)
49
73
  --max-total-messages N Max total messages (default: 10000, 0 = unlimited)
50
74
  --max-message-length N Max message length (default: 1000)
51
75
  --port PORT Server port (default: 5173)
52
76
  --host HOST Server host (default: localhost)
53
77
  --open Open browser automatically
78
+ --api-only Run API proxy only (no UI serving, no build required)
79
+ --cors-origin ORIGIN Allowed CORS origin in api-only mode (default: *)
54
80
  --config PATH Path to config file (default: ~/.orbit-chat-app/config.json)
55
81
  --help, -h Show help message
82
+ --version, -v Show version number
56
83
  ```
57
84
 
58
- #### Examples
85
+ ### Examples
59
86
 
60
87
  ```bash
61
88
  # Start with custom API URL and port
62
89
  orbitchat --api-url http://localhost:3000 --port 8080
63
90
 
64
- # Start with API key and open browser
65
- orbitchat --api-key my-key --open
91
+ # Start with upload, audio output, mic input, and autocomplete enabled
92
+ orbitchat --enable-upload --enable-audio --enable-audio-input --enable-autocomplete --open
66
93
 
67
- # Start with custom config file
94
+ # Start with a custom config file
68
95
  orbitchat --config /path/to/config.json
96
+
97
+ # Start with adapters defined inline
98
+ ORBIT_ADAPTERS='[{"name":"Chat","apiKey":"mykey","apiUrl":"https://api.example.com"}]' orbitchat
99
+
100
+ # API proxy only — no UI, no build required
101
+ orbitchat --api-only --port 5174
102
+
103
+ # API proxy with restricted CORS origin
104
+ orbitchat --api-only --port 5174 --cors-origin http://localhost:3001
105
+ ```
106
+
107
+ ## API-Only Mode
108
+
109
+ Use `--api-only` to run the Express proxy **without** serving the built-in chat UI. This is useful when you are building your own frontend and only need the proxy layer to keep API keys off the browser.
110
+
111
+ ```bash
112
+ orbitchat --api-only --port 5174
113
+ ```
114
+
115
+ In this mode:
116
+ - No `dist/` directory or `npm run build` is required.
117
+ - CORS headers are added automatically (default `Access-Control-Allow-Origin: *`). Use `--cors-origin` to restrict to a specific origin.
118
+ - All `/api/*` proxy routes and `GET /api/adapters` work exactly the same as in full mode.
119
+
120
+ ### API contract for custom UIs
121
+
122
+ Your frontend needs to do two things:
123
+
124
+ 1. **Discover adapters** — `GET /api/adapters` returns:
125
+ ```json
126
+ {
127
+ "adapters": [
128
+ { "name": "Simple Chat", "description": "...", "notes": "..." }
129
+ ]
130
+ }
131
+ ```
132
+
133
+ 2. **Send requests with `X-Adapter-Name`** — every call to `/api/*` must include the header:
134
+ ```
135
+ X-Adapter-Name: Simple Chat
136
+ ```
137
+ The proxy resolves the adapter, injects the real `X-API-Key`, and forwards the request to the backend URL configured for that adapter.
138
+
139
+ ### Endpoint reference
140
+
141
+ | Method | Path | Headers | Description |
142
+ |--------|------|---------|-------------|
143
+ | GET | `/api/adapters` | — | List available adapter names and descriptions |
144
+ | POST | `/api/v1/chat` | `X-Adapter-Name`, `X-Session-ID` | Send a chat message (SSE streaming response) |
145
+ | POST | `/api/files/upload` | `X-Adapter-Name` | Upload a file (multipart/form-data) |
146
+ | GET | `/api/files` | `X-Adapter-Name` | List uploaded files |
147
+ | GET | `/api/files/:id` | `X-Adapter-Name` | Get file info |
148
+ | DELETE | `/api/files/:id` | `X-Adapter-Name` | Delete a file |
149
+ | GET | `/api/v1/autocomplete?q=...&limit=5` | `X-Adapter-Name` | Autocomplete suggestions |
150
+
151
+ ### Example: calling from a custom React app
152
+
153
+ ```js
154
+ // Discover adapters
155
+ const res = await fetch('http://localhost:5174/api/adapters');
156
+ const { adapters } = await res.json();
157
+
158
+ // Send a chat message (SSE stream)
159
+ const response = await fetch('http://localhost:5174/api/v1/chat', {
160
+ method: 'POST',
161
+ headers: {
162
+ 'Content-Type': 'application/json',
163
+ 'X-Adapter-Name': adapters[0].name,
164
+ 'X-Session-ID': crypto.randomUUID(),
165
+ },
166
+ body: JSON.stringify({ message: 'Hello!' }),
167
+ });
168
+
169
+ // Read the SSE stream
170
+ const reader = response.body.getReader();
171
+ const decoder = new TextDecoder();
172
+ while (true) {
173
+ const { done, value } = await reader.read();
174
+ if (done) break;
175
+ console.log(decoder.decode(value));
176
+ }
177
+ ```
178
+
179
+ ## Configuring Adapters
180
+
181
+ Adapters map a user-visible name to a backend API key and URL. Configure them via the `ORBIT_ADAPTERS` (or `VITE_ADAPTERS`) environment variable as a JSON array:
182
+
183
+ ```bash
184
+ export ORBIT_ADAPTERS='[
185
+ {
186
+ "name": "Simple Chat",
187
+ "apiKey": "default-key",
188
+ "apiUrl": "http://localhost:3000",
189
+ "description": "Basic chat interface using the default conversational agent."
190
+ },
191
+ {
192
+ "name": "Document QA",
193
+ "apiKey": "doc-qa-key",
194
+ "apiUrl": "http://localhost:3000",
195
+ "description": "Chat with uploaded documents.",
196
+ "notes": "Supports PDF, DOCX, and plain text uploads."
197
+ }
198
+ ]'
69
199
  ```
70
200
 
201
+ Each adapter object supports:
202
+
203
+ | Field | Required | Description |
204
+ |-------|----------|-------------|
205
+ | `name` | Yes | Display name shown in the agent selector |
206
+ | `apiKey` | Yes | Backend API key (never exposed to the browser) |
207
+ | `apiUrl` | No | Backend URL (defaults to `--api-url` value) |
208
+ | `description` | No | Short summary shown in dropdowns |
209
+ | `notes` | No | Markdown content shown in the chat empty state |
210
+
211
+ If `--default-adapter` is not specified, the first adapter in the list is preselected for new conversations.
212
+
213
+ ### Agent Selector UX
214
+
215
+ - When a conversation has no messages, the chat canvas shows a centered agent selector with the adapter's notes rendered beneath it.
216
+ - Once an adapter is selected, the input field unlocks.
217
+ - Sidebar cards display the agent assigned to each conversation.
218
+ - To change the adapter after messages exist, use the "Change agent" action in the sidebar.
219
+
220
+ ## Configuration
221
+
222
+ ### Configuration Priority
223
+
224
+ Configuration is loaded in the following priority order:
225
+ 1. CLI arguments (highest priority)
226
+ 2. Config file (`~/.orbit-chat-app/config.json`)
227
+ 3. Environment variables (`VITE_*`)
228
+ 4. Default values (lowest priority)
229
+
71
230
  ### Configuration File
72
231
 
73
232
  Create a config file at `~/.orbit-chat-app/config.json`:
@@ -75,7 +234,7 @@ Create a config file at `~/.orbit-chat-app/config.json`:
75
234
  ```json
76
235
  {
77
236
  "apiUrl": "http://localhost:3000",
78
- "defaultKey": "default-key",
237
+ "defaultKey": "Simple Chat",
79
238
  "port": 5173,
80
239
  "host": "localhost",
81
240
  "enableUploadButton": false,
@@ -90,189 +249,105 @@ Create a config file at `~/.orbit-chat-app/config.json`:
90
249
  }
91
250
  ```
92
251
 
93
- ### Configuration Priority
94
-
95
- Configuration is loaded in the following priority order:
96
- 1. CLI arguments (highest priority)
97
- 2. Config file (`~/.orbit-chat-app/config.json`)
98
- 3. Environment variables (`VITE_*`)
99
- 4. Default values (lowest priority)
100
-
101
- **Note:** GitHub stats and GitHub owner/repo are always shown and default to "schmitech/orbit". These are only configurable via build-time environment variables (`VITE_SHOW_GITHUB_STATS`, `VITE_GITHUB_OWNER`, `VITE_GITHUB_REPO`) for developers who fork the repository and build their own version.
102
-
103
- ### Protect API Keys with the Middleware Proxy
104
-
105
- You can prevent API keys from ever reaching the browser by enabling the built-in middleware layer:
106
-
107
- 1. Create an `adapters.yaml` file (next to `bin/orbitchat.js`, in your working directory, or in `~/.orbit-chat-app/`). Example:
108
- ```yaml
109
- adapters:
110
- local-dev:
111
- apiKey: orbit_dev_key
112
- apiUrl: http://localhost:3000
113
- description: Local development agent
114
- notes: >
115
- Use this agent for local testing against http://localhost:3000.
116
- Markdown is supported in notes and will appear inside the chat UI.
117
- production:
118
- apiKey: orbit_prod_key
119
- apiUrl: https://api.example.com
120
- description: Production agent
121
- notes: |
122
- ### Production adapter
123
- - Connects to https://api.example.com
124
- - Requires valid credentials
125
- ```
126
- - `description` is a short, single-line summary that shows inside dropdowns.
127
- - `notes` is optional markdown surfaced in the chat empty state so end users immediately understand the agent’s capabilities.
128
- - If you only have `notes`, the first non-empty line is automatically reused as a fallback `description`.
129
- 2. Start the CLI with `--enable-api-middleware` (or export `VITE_ENABLE_API_MIDDLEWARE=true`). The Express server now:
130
- - Serves `GET /api/adapters` so the React app can list safe adapter names.
131
- - Proxies all chat/file/thread/admin calls through `/api/...`, injecting the adapter's real `X-API-Key`.
132
- 3. The UI automatically swaps the API-key modal for an Adapter Selector and stores adapter names per conversation.
133
-
134
- Keep `adapters.yaml` out of source control and run the CLI behind HTTPS (or another reverse proxy) when deploying.
252
+ > **Note:** `defaultKey` should be set to an adapter name (e.g. `"Simple Chat"`). If left as `"default-key"` or empty, the app falls back to the first adapter in `ORBIT_ADAPTERS`.
135
253
 
136
254
  ### Environment Variables
137
255
 
138
- You can also set configuration via environment variables (for development):
256
+ For development, set configuration via environment variables:
139
257
 
140
258
  ```bash
141
259
  VITE_API_URL=http://localhost:3000
142
- VITE_DEFAULT_KEY=default-key
260
+ VITE_DEFAULT_KEY=Simple Chat # Adapter name to preselect
143
261
  VITE_ENABLE_UPLOAD=false
262
+ VITE_ENABLE_AUDIO_OUTPUT=false
263
+ VITE_ENABLE_AUDIO_INPUT=false
264
+ VITE_VOICE_SILENCE_TIMEOUT_MS=4000
265
+ VITE_VOICE_RECOGNITION_LANG=
266
+ VITE_ENABLE_FEEDBACK=false
267
+ VITE_ENABLE_AUTOCOMPLETE=false
144
268
  VITE_CONSOLE_DEBUG=false
145
- # ... etc
146
-
147
- `VITE_DEFAULT_KEY` is dual-purpose:
148
- - When **middleware is disabled**, it should contain the literal API key that the frontend will send to the backend (same as before).
149
- - When **middleware is enabled**, set it to the adapter name you want preselected (or pass `--default-adapter`). If you leave it as `default-key` or empty, the app automatically falls back to the first adapter defined in `VITE_ADAPTERS`/`ORBIT_ADAPTERS`.
150
269
  ```
151
270
 
152
- ### Understanding the Agent Selector UX
153
-
154
- - When middleware mode is enabled and a conversation has no messages, the main chat canvas now shows a centered agent selector with the adapter’s notes rendered directly beneath it. This is the primary place users choose or review agents.
155
- - Once an adapter is selected, the input field unlocks and aligns with the selector/notes card to keep the first-time experience focused.
156
- - Sidebar cards display the agent assigned to each conversation under the timestamp/badges so it is easy to scan which assistant was used.
157
- - To change the adapter after messages exist, open the “Change agent” action in the sidebar (or configure API modal) and select a new adapter. This ensures there is a single, predictable entry point instead of multiple dropdowns.
271
+ > **Note:** GitHub stats and owner/repo are hardcoded and only configurable via build-time environment variables (`VITE_SHOW_GITHUB_STATS`, `VITE_GITHUB_OWNER`, `VITE_GITHUB_REPO`) for developers who fork the repository.
158
272
 
159
273
  ## Development
160
274
 
161
275
  ### Local Development Setup
162
276
 
163
- For local development, clone the repository and install dependencies:
277
+ Clone the repository and install dependencies:
164
278
 
165
279
  ```bash
166
280
  npm install
167
281
  npm run dev
168
282
  ```
169
283
 
170
- ## Configuration
171
-
172
- The application supports multiple ways to configure the API:
284
+ ### Development with Express Proxy
173
285
 
174
- ### 1. Environment Variables (Vite)
175
- Create a `.env.local` file in the root directory:
286
+ To run both the Express proxy and Vite dev server together:
176
287
 
177
288
  ```bash
178
- VITE_API_URL=https://your-api-endpoint.com
179
- VITE_DEFAULT_KEY=default-key # API key in direct mode, or adapter name in middleware mode
180
- VITE_USE_LOCAL_API=true # Set to 'true' to use local API build
181
- VITE_LOCAL_API_PATH=/api.mjs # Path to local API (defaults to /api.mjs from public directory)
182
- VITE_CONSOLE_DEBUG=false # Enable debug logging
183
- ```
184
-
185
- ### 2. Window Variables
186
- Set global variables in your HTML or before the app loads:
187
-
188
- ```javascript
189
- window.CHATBOT_API_URL = 'https://your-api-endpoint.com';
190
- window.CHATBOT_API_KEY = 'your-api-key-here';
289
+ node bin/dev-server.js
191
290
  ```
192
291
 
193
- ### 3. Runtime Configuration
194
- Use the "Configure API" button in the chat interface to set the API URL and key at runtime.
292
+ This starts:
293
+ - Express proxy on port 5174 (handles `/api/*` routes)
294
+ - Vite dev server on port 5173 (proxies API requests to Express)
195
295
 
196
- ## Local Development Setup
296
+ ### Building for Production
197
297
 
198
- ### Using Local API Build
298
+ ```bash
299
+ npm run build
300
+ ```
199
301
 
200
- For local development, you can use the local API build instead of the npm package:
302
+ The output is written to `dist/`. Serve it with:
201
303
 
202
- **Option 1: Use the convenience script** (recommended):
203
304
  ```bash
204
- npm run dev:with-api
305
+ orbitchat --port 8080
205
306
  ```
206
- This script automatically:
207
- 1. Builds the API from `../node-api`
208
- 2. Copies the built files to `public/api.mjs`
209
- 3. Starts the dev server with local API enabled
210
307
 
211
- **Option 2: Manual setup**:
212
- ```bash
213
- # Build and copy API files
214
- npm run build:api
308
+ ### Running as a Daemon
215
309
 
216
- # Start dev server with local API
217
- npm run dev:local
218
- ```
310
+ Use the included `run-chat-app.sh` script:
219
311
 
220
- **Option 3: Build API separately**:
221
312
  ```bash
222
- # From node-api directory
223
- cd ../node-api
224
- npm run build:chat-app
225
-
226
- # Then start chat-app
227
- cd ../chat-app
228
- npm run dev:local
313
+ ./run-chat-app.sh --start # Start in background
314
+ ./run-chat-app.sh --start 8080 # Start on custom port
315
+ ./run-chat-app.sh --stop # Stop
316
+ ./run-chat-app.sh --status # Check status
229
317
  ```
230
318
 
231
- The local API files will be copied to `src/api/local/` directory. When `VITE_USE_LOCAL_API=true` is set, the app will load `./local/api.mjs` from the src directory instead of the npm package.
319
+ ## Available Scripts
320
+
321
+ - `npm run dev` — Start Vite dev server
322
+ - `npm run build` — Build for production
323
+ - `npm run preview` — Preview production build
324
+ - `npm run dev:local` — Start dev server with local API build
325
+ - `npm run dev:with-api` — Build API from `../node-api` and start dev server
326
+ - `npm run build:local` — Build for production with local API
327
+ - `npm run build:api` — Build and copy API from `../node-api`
232
328
 
233
329
  ## Features
234
330
 
235
- - **Streaming Responses**: Real-time streaming of AI responses
331
+ - **Streaming Responses**: Real-time streaming of AI responses via SSE
332
+ - **Agent Selection**: Choose from configured adapters per conversation
236
333
  - **File Upload**: Upload and attach files (PDF, DOCX, TXT, CSV, JSON, HTML, images, audio) to conversations
237
- - **File Context**: Query uploaded files and include them in chat context
334
+ - **File Context**: Query uploaded files — they are chunked, embedded, and included in chat context
335
+ - **Autocomplete**: Optional type-ahead suggestions via `/api/v1/autocomplete`
336
+ - **Conversation Threads**: Branch conversations into focused sub-threads
238
337
  - **Session Management**: Automatic session ID generation and persistence
239
- - **Error Handling**: Comprehensive error handling with user-friendly messages
240
- - **Conversation Persistence**: Chat history is saved to localStorage
241
- - **API Configuration**: Flexible API configuration options
338
+ - **Conversation Persistence**: Chat history saved to localStorage
339
+ - **Audio Output**: Optional text-to-speech for AI responses
340
+ - **Feedback Buttons**: Optional thumbs-up/down per message
242
341
 
243
342
  ## Security
244
343
 
245
- - When **API middleware** is enabled, the browser never sees your real API keys. The CLI proxy serves `/api/adapters` with adapter names only and injects the real `X-API-Key` on the server before calling the backend. Keep `ORBIT_ADAPTERS` / `VITE_ADAPTERS` on the server (out of git) and run the proxy behind HTTPS so users cannot intercept traffic.
246
- - Even though the app falls back to the first adapter in `VITE_ADAPTERS`, the adapters list itself is still server-side; clients only learn the names you expose. Someone would need filesystem or shell access to the machine running `bin/orbitchat.js` to read the adapters config and extract the real keys.
247
- - In direct mode (middleware disabled), the browser stores API keys locally to send them with requests—treat that mode as developer-only unless you’re comfortable distributing the key to end users.
248
- - Regardless of mode, secure the host running the CLI and restrict who can reach it; a compromised host or misconfigured reverse proxy can leak the adapters file or intercept proxied traffic.
249
-
250
- ## Usage
251
-
252
- ### Basic Chat
253
-
254
- 1. Configure your API settings using one of the methods above
255
- 2. Start a conversation by typing a message
256
- 3. The AI will respond with streaming text
257
- 4. Use the regenerate button (↻) to regenerate responses
258
- 5. Use the copy button to copy AI responses to clipboard
259
-
260
- ### File Upload
344
+ - The browser **never** sees real API keys. The Express proxy maps adapter names to keys server-side.
345
+ - `GET /api/adapters` only exposes names and descriptions never keys or backend URLs.
346
+ - Keep `ORBIT_ADAPTERS` / `VITE_ADAPTERS` out of source control.
347
+ - Run the proxy behind HTTPS (or another reverse proxy) in production so users cannot intercept traffic.
348
+ - Secure the host running the CLI — a compromised host can leak the adapters config or intercept proxied traffic.
261
349
 
262
- 1. Click the paperclip icon (📎) in the message input
263
- 2. Upload files using drag-and-drop or file picker
264
- 3. Supported formats: PDF, DOCX, TXT, CSV, JSON, HTML, Markdown, images (PNG, JPEG, TIFF), audio (WAV, MP3, MP4, OGG, FLAC, WebM, M4A, AAC)
265
- 4. Files are automatically processed and indexed
266
- 5. Attach files to messages - they will be included in the chat context
267
- 6. Files are chunked and stored in the vector store for semantic search
268
-
269
- **File Upload Flow**:
270
- - Upload files using the file upload UI
271
- - Files are processed on the server (extraction, chunking, embedding)
272
- - File IDs are automatically included with your messages
273
- - The AI can query and reference uploaded files in responses
274
-
275
- ## File Upload Details
350
+ ## File Upload
276
351
 
277
352
  ### Supported File Types
278
353
 
@@ -280,88 +355,65 @@ The local API files will be copied to `src/api/local/` directory. When `VITE_USE
280
355
  |------|---------|------------|
281
356
  | Documents | PDF, DOCX, PPTX, XLSX | Text extraction, chunking, vector indexing |
282
357
  | Text | TXT, MD, HTML | Direct chunking and indexing |
283
- | Data | CSV, Parquet | DuckDB integration or vector store |
358
+ | Data | CSV, JSON | Chunking and indexing |
359
+ | Code | PY, JS, TS, Java, Go, Rust, C/C++, and more | Direct indexing |
284
360
  | Images | PNG, JPEG, TIFF | OCR via vision service |
285
- | Audio | WAV, MP3, MP4, OGG, FLAC, WebM, M4A, AAC | ASR (Automatic Speech Recognition) via audio transcription |
286
-
287
- ### File Size Limits
361
+ | Audio | WAV, MP3, MP4, OGG, FLAC, WebM, M4A, AAC | ASR (Automatic Speech Recognition) |
362
+ | Subtitles | VTT | Direct indexing |
288
363
 
289
- - Maximum file size: 50MB
290
- - Maximum files per conversation: 5 (configurable)
364
+ ### Limits
291
365
 
292
- ### File Processing
366
+ - Maximum file size: 50 MB (configurable via `--max-file-size-mb`)
367
+ - Maximum files per conversation: 5 (configurable via `--max-files-per-conversation`)
293
368
 
294
- Files are processed through the following pipeline:
295
- 1. **Upload**: File uploaded via `/api/files/upload`
296
- 2. **Validation**: File type and size validation
297
- 3. **Storage**: File saved to filesystem (or S3 in production)
298
- 4. **Extraction**: Text and metadata extracted using format-specific processors
299
- 5. **Chunking**: Content chunked using configured strategy (fixed or semantic)
300
- 6. **Indexing**: Chunks indexed in vector store for semantic search
301
- 7. **Metadata**: Processing status tracked in SQLite
302
-
303
- ## Available Scripts
369
+ ### Processing Pipeline
304
370
 
305
- - `npm run dev` - Start dev server (uses npm package)
306
- - `npm run dev:local` - Start dev server with local API enabled
307
- - `npm run dev:with-api` - Build API and start dev server with local API
308
- - `npm run build` - Build for production (uses npm package)
309
- - `npm run build:local` - Build for production with local API
310
- - `npm run build:api` - Build API and copy to public directory
311
- - `npm run preview` - Preview production build
312
- - `npm run preview:local` - Preview production build with local API
371
+ 1. **Upload** File uploaded via the Express proxy to `/api/files/upload`
372
+ 2. **Validation** File type and size validated client-side and server-side
373
+ 3. **Storage** File saved to filesystem (or S3 in production)
374
+ 4. **Extraction** Text and metadata extracted using format-specific processors
375
+ 5. **Chunking** Content chunked using configured strategy (fixed or semantic)
376
+ 6. **Indexing** Chunks indexed in vector store for semantic search
377
+ 7. **Status Polling** Client polls until processing completes
313
378
 
314
379
  ## Integration Details
315
380
 
316
- The integration uses:
317
- - **Zustand** for state management (replacing React Context)
318
- - **@schmitech/chatbot-api** for streaming chat functionality and file operations
381
+ The application uses:
382
+ - **Zustand** for state management
383
+ - **Express** + `http-proxy-middleware` for the API proxy layer
319
384
  - **@schmitech/markdown-renderer** ([GitHub](https://github.com/schmitech/markdown-renderer) | [NPM](https://www.npmjs.com/package/@schmitech/markdown-renderer)) for rich markdown rendering
320
385
  - **localStorage** for persistent session and conversation storage
321
- - **TypeScript** for type safety throughout the integration
322
- - **File Upload Service** for handling file uploads with progress tracking
323
- - **Vector Store** for semantic search over uploaded file content
386
+ - **TypeScript** for type safety throughout
324
387
 
325
388
  ## Troubleshooting
326
389
 
327
- ### Local API Not Loading
390
+ ### No Adapters Available
328
391
 
329
- If you see a 404 error for `api.mjs`:
330
-
331
- 1. **Ensure API is built**:
332
- ```bash
333
- cd ../node-api
334
- npm run build
335
- ```
336
-
337
- 2. **Copy files to src/api/local directory**:
338
- ```bash
339
- mkdir -p ../chat-app/src/api/local
340
- cp dist/api.mjs ../chat-app/src/api/local/api.mjs
341
- cp dist/api.d.ts ../chat-app/src/api/local/api.d.ts
342
- ```
343
-
344
- 3. **Restart dev server with local API enabled**:
345
- ```bash
346
- npm run dev:local
347
- ```
348
-
349
- 4. **Check environment variable**:
350
- - Ensure `VITE_USE_LOCAL_API=true` is set (or use `npm run dev:local`)
351
- - The default path `./local/api.mjs` should work if files are in `src/api/local/`
392
+ If the agent selector shows no adapters:
393
+ 1. Ensure `ORBIT_ADAPTERS` or `VITE_ADAPTERS` is set and valid JSON
394
+ 2. Check the CLI startup logs for "Available Adapters: ..."
395
+ 3. Verify each adapter has a `name` and `apiKey` field
352
396
 
353
397
  ### File Upload Issues
354
398
 
355
- - **File size exceeded**: Check file size (max 50MB)
356
- - **Unsupported format**: Verify file type is in supported list
357
- - **Upload fails**: Check server logs and API key configuration
358
- - **Processing fails**: Ensure file processing service is initialized on server
399
+ - **File size exceeded** Check file size against the configured limit
400
+ - **Unsupported format** Verify file type is in the supported list above
401
+ - **Upload fails** Check server logs and adapter configuration
402
+ - **Processing fails** Ensure the file processing service is initialized on the backend
359
403
 
360
404
  ### Debug Mode
361
405
 
362
- Enable debug logging by setting:
406
+ Enable debug logging:
363
407
  ```bash
364
- VITE_CONSOLE_DEBUG=true
408
+ orbitchat --console-debug
365
409
  ```
410
+ Or set `VITE_CONSOLE_DEBUG=true` during development. This shows detailed API and file upload information in the browser console.
411
+
412
+ ## Deployment Checklist
366
413
 
367
- This will show detailed API loading and file upload information in the console.
414
+ 1. **Build the app**: `npm run build`
415
+ 2. **Set `ORBIT_ADAPTERS`** with your production adapter configs (keep out of git)
416
+ 3. **Run behind HTTPS** — use a reverse proxy like nginx or Caddy in front of `orbitchat`
417
+ 4. **Bind to the right interface**: use `--host 0.0.0.0` to allow external access, or keep the default `localhost` for local-only
418
+ 5. **Tune limits** — set `--max-conversations`, `--max-message-length`, etc. appropriate for your deployment
419
+ 6. **Monitor logs** — use `run-chat-app.sh --start` for daemon mode with log file, or run directly and pipe to your log aggregator
package/bin/dev-server.js CHANGED
@@ -20,12 +20,10 @@ console.log('Starting Express middleware server on port', expressPort);
20
20
  const expressServer = spawn('node', [
21
21
  path.join(__dirname, 'orbitchat.js'),
22
22
  '--port', expressPort.toString(),
23
- '--enable-api-middleware'
24
23
  ], {
25
24
  stdio: 'inherit',
26
25
  env: {
27
26
  ...process.env,
28
- VITE_ENABLE_API_MIDDLEWARE: 'true',
29
27
  }
30
28
  });
31
29
 
@@ -35,7 +33,6 @@ const viteServer = spawn('npm', ['run', 'dev'], {
35
33
  stdio: 'inherit',
36
34
  env: {
37
35
  ...process.env,
38
- VITE_ENABLE_API_MIDDLEWARE: 'true',
39
36
  VITE_MIDDLEWARE_SERVER_URL: `http://localhost:${expressPort}`,
40
37
  }
41
38
  });