orbitchat 2.13.1 → 2.14.0
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.
- package/README.md +271 -219
- package/bin/dev-server.js +0 -3
- package/bin/orbitchat.js +146 -82
- package/dist/assets/_baseUniq-BRKsqoH--68FUaYxk.js +1 -0
- package/dist/assets/{arc-pab_su9s-DFq3JYvb.js → arc-pab_su9s-BuY-VRZt.js} +1 -1
- package/dist/assets/{architectureDiagram-VXUJARFQ-DqQ8r_6g-ejnypLyO.js → architectureDiagram-VXUJARFQ-DqQ8r_6g-C5b5VsO8.js} +1 -1
- package/dist/assets/{blockDiagram-VD42YOAC-B-dKfcH3-Bgo8FU6J.js → blockDiagram-VD42YOAC-B-dKfcH3-DVjqMJ-3.js} +4 -4
- package/dist/assets/{c4Diagram-YG6GDRKO-DMUPaBEl-CX9lx-UK.js → c4Diagram-YG6GDRKO-DMUPaBEl-o6ghjFV9.js} +1 -1
- package/dist/assets/channel-HKsfPa5q-rOME8XF8.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-CX67kh_B-Dm2c-Lyy.js → chunk-4BX2VUAB-CX67kh_B-Dl0Loq_e.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-BocSyyvr-lclbFu9j.js → chunk-55IACEB6-BocSyyvr-DYW83vZR.js} +1 -1
- package/dist/assets/{chunk-B4BG7PRW-CO8QAyfE-CvvrZ063.js → chunk-B4BG7PRW-CO8QAyfE-CsF1OX4R.js} +1 -1
- package/dist/assets/{chunk-DI55MBZ5-Dw1L6Eos-BuD2OREa.js → chunk-DI55MBZ5-Dw1L6Eos-Dl1shJzL.js} +3 -3
- package/dist/assets/{chunk-FMBD7UC4-dPK7Boav-D0ZlDI-s.js → chunk-FMBD7UC4-dPK7Boav-Cz7OoDLR.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-vP2PqfVG-DqaIoebO.js → chunk-QN33PNHL-vP2PqfVG-BuQNN8G2.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-Bcidzu63-DG8agfQA.js → chunk-QZHKN3VN-Bcidzu63-Bud1NKOb.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-BtljMjlg-B6xEnbcW.js → chunk-TZMSLE5B-BtljMjlg-BKLxPJ-x.js} +1 -1
- package/dist/assets/{classDiagram-2ON5EDUG-C7cYN9hv-Dd-YCt5Q.js → classDiagram-2ON5EDUG-C7cYN9hv-BHg-LSxQ.js} +1 -1
- package/dist/assets/{classDiagram-v2-WZHVMYZB-C7cYN9hv-Dd-YCt5Q.js → classDiagram-v2-WZHVMYZB-C7cYN9hv-BHg-LSxQ.js} +1 -1
- package/dist/assets/clone-DoPb9X13-DejjKfXe.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-BGzO4EsH-BMVWyh_a.js → cose-bilkent-S5V4N54A-BGzO4EsH-rofdToAx.js} +1 -1
- package/dist/assets/{dagre-6UL2VRFP-TzNvXCds-CbmhexaH.js → dagre-6UL2VRFP-TzNvXCds-Ls1mVyc7.js} +1 -1
- package/dist/assets/{diagram-PSM6KHXK-BqY4RpUg-BqmtaKLy.js → diagram-PSM6KHXK-BqY4RpUg-BJmYXUei.js} +1 -1
- package/dist/assets/{diagram-QEK2KX5R-CTjgBsne-Dbl2BvQJ.js → diagram-QEK2KX5R-CTjgBsne-dz-VLadE.js} +1 -1
- package/dist/assets/{diagram-S2PKOQOG-BqrhTIpA-DnNkr8UG.js → diagram-S2PKOQOG-BqrhTIpA-ikxUE9Dj.js} +2 -2
- package/dist/assets/{erDiagram-Q2GNP2WA-B2hsi_Tl-r9lLCSiy.js → erDiagram-Q2GNP2WA-B2hsi_Tl-B5gu6Jrx.js} +1 -1
- package/dist/assets/{flowDiagram-NV44I4VS-C03vtt_F-Bj1MoEwx.js → flowDiagram-NV44I4VS-C03vtt_F-C9LVdVvn.js} +1 -1
- package/dist/assets/{ganttDiagram-JELNMOA3-B3hAg964-CCnbkzn3.js → ganttDiagram-JELNMOA3-B3hAg964-CYO6ZcQ8.js} +1 -1
- package/dist/assets/{gitGraphDiagram-NY62KEGX-ByhMH0yZ-YRu-SLHD.js → gitGraphDiagram-NY62KEGX-ByhMH0yZ-BvO0WGzP.js} +3 -3
- package/dist/assets/{graph-BmNkcFEM-dUEThWgx.js → graph-BmNkcFEM-Bl2fiTgr.js} +1 -1
- package/dist/assets/{index-BXexqYFc-6FZAvmAF.js → index-BXexqYFc-CFPIFV8r.js} +1 -1
- package/dist/assets/index-KsGsuMGp.css +1 -0
- package/dist/assets/{index-BTk6gbYa.js → index-nqhgVFEP.js} +219 -239
- package/dist/assets/infoDiagram-WHAUD3N6-is6Ho4-T-D6tHdi3J.js +2 -0
- package/dist/assets/{journeyDiagram-XKPGCS4Q-CRTOL26C-BslRBPzU.js → journeyDiagram-XKPGCS4Q-CRTOL26C-CL4DFaQP.js} +1 -1
- package/dist/assets/{kanban-definition-3W4ZIXB7-CNnO_t6O-C2MPRjuS.js → kanban-definition-3W4ZIXB7-CNnO_t6O-DZBlsSao.js} +6 -6
- package/dist/assets/{layout-C0kZPebx-DBUyCsod.js → layout-C0kZPebx-DiUdszUx.js} +1 -1
- package/dist/assets/min-7Gb0pNxh-DsojA8pm.js +1 -0
- package/dist/assets/{mindmap-definition-VGOIOE7T-CJZ2wTTa-DP1XV6kP.js → mindmap-definition-VGOIOE7T-CJZ2wTTa-Cd46k2jT.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-C9OSknjr-BdkTw8nn.js → pieDiagram-ADFJNKIX-C9OSknjr-BGVcHmss.js} +2 -2
- package/dist/assets/{quadrantDiagram-AYHSOK5B-CW8yuAqv-BcCv0sYD.js → quadrantDiagram-AYHSOK5B-CW8yuAqv-CrCYjmJT.js} +3 -3
- package/dist/assets/{requirementDiagram-UZGBJVZJ-nGPhruO1-CZD7Xw4s.js → requirementDiagram-UZGBJVZJ-nGPhruO1-BzOGHXGi.js} +1 -1
- package/dist/assets/{sankeyDiagram-TZEHDZUN-CmL90u-m-BicoH15o.js → sankeyDiagram-TZEHDZUN-CmL90u-m-BWp9STLO.js} +3 -3
- package/dist/assets/{sequenceDiagram-WL72ISMW-B02VRcnM-CvY3TSCC.js → sequenceDiagram-WL72ISMW-B02VRcnM-DB4Adljk.js} +7 -7
- package/dist/assets/{stateDiagram-FKZM4ZOC-DjoyLUdz-Cy3GdNKr.js → stateDiagram-FKZM4ZOC-DjoyLUdz-pDyQ50aU.js} +1 -1
- package/dist/assets/{stateDiagram-v2-4FDKWEC3-Bq76BTB7-BTj88h18.js → stateDiagram-v2-4FDKWEC3-Bq76BTB7-C3j4gDpN.js} +1 -1
- package/dist/assets/{timeline-definition-IT6M3QCI-CTn0Gm3T-BPnEK60y.js → timeline-definition-IT6M3QCI-CTn0Gm3T-O1FhSixZ.js} +1 -1
- package/dist/assets/{treemap-KMMF4GRG-BjgLKKyi-Dpn6IoCt.js → treemap-KMMF4GRG-BjgLKKyi-DG8IQefJ.js} +1 -1
- package/dist/assets/{xychartDiagram-PRI3JC2R-Cgg6Uija-B3NNTn5p.js → xychartDiagram-PRI3JC2R-Cgg6Uija-CPVch5-l.js} +4 -4
- package/dist/index.html +2 -2
- package/package.json +2 -2
- package/dist/assets/__vite-browser-external-BIHI7g3E.js +0 -1
- package/dist/assets/_baseUniq-BRKsqoH--BnZ8jILn.js +0 -1
- package/dist/assets/api-C90fNFdj.js +0 -2
- package/dist/assets/api-Dg2si9TY.js +0 -2
- package/dist/assets/channel-HKsfPa5q-i-PY3wcB.js +0 -1
- package/dist/assets/clone-DoPb9X13-DxnBl06F.js +0 -1
- package/dist/assets/index-BjgS88qB.css +0 -1
- package/dist/assets/infoDiagram-WHAUD3N6-is6Ho4-T-BLBpQ0kq.js +0 -2
- 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.
|
|
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
|
-
##
|
|
19
|
+
## Quick Start
|
|
20
20
|
|
|
21
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
47
|
+
## CLI Options
|
|
31
48
|
|
|
32
49
|
```bash
|
|
33
50
|
orbitchat [options]
|
|
34
51
|
|
|
35
52
|
Options:
|
|
36
|
-
--api-url URL
|
|
37
|
-
--default-adapter NAME
|
|
38
|
-
--
|
|
39
|
-
--
|
|
40
|
-
--
|
|
41
|
-
--console-debug
|
|
42
|
-
--enable-upload
|
|
43
|
-
--enable-
|
|
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
|
-
|
|
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
|
|
65
|
-
orbitchat --
|
|
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": "
|
|
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
|
-
|
|
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
|
-
|
|
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=
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
The application supports multiple ways to configure the API:
|
|
284
|
+
### Development with Express Proxy
|
|
173
285
|
|
|
174
|
-
|
|
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
|
-
|
|
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
|
-
|
|
194
|
-
|
|
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
|
-
|
|
296
|
+
### Building for Production
|
|
197
297
|
|
|
198
|
-
|
|
298
|
+
```bash
|
|
299
|
+
npm run build
|
|
300
|
+
```
|
|
199
301
|
|
|
200
|
-
|
|
302
|
+
The output is written to `dist/`. Serve it with:
|
|
201
303
|
|
|
202
|
-
**Option 1: Use the convenience script** (recommended):
|
|
203
304
|
```bash
|
|
204
|
-
|
|
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
|
-
|
|
212
|
-
```bash
|
|
213
|
-
# Build and copy API files
|
|
214
|
-
npm run build:api
|
|
308
|
+
### Running as a Daemon
|
|
215
309
|
|
|
216
|
-
|
|
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
|
-
#
|
|
223
|
-
|
|
224
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
- **
|
|
240
|
-
- **
|
|
241
|
-
- **
|
|
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
|
-
-
|
|
246
|
-
-
|
|
247
|
-
-
|
|
248
|
-
-
|
|
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
|
-
|
|
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,
|
|
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)
|
|
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
|
-
|
|
290
|
-
- Maximum files per conversation: 5 (configurable)
|
|
364
|
+
### Limits
|
|
291
365
|
|
|
292
|
-
|
|
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
|
-
|
|
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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
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
|
|
317
|
-
- **Zustand** for state management
|
|
318
|
-
-
|
|
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
|
|
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
|
-
###
|
|
390
|
+
### No Adapters Available
|
|
328
391
|
|
|
329
|
-
If
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
|
356
|
-
- **Unsupported format
|
|
357
|
-
- **Upload fails
|
|
358
|
-
- **Processing fails
|
|
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
|
|
406
|
+
Enable debug logging:
|
|
363
407
|
```bash
|
|
364
|
-
|
|
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
|
-
|
|
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
|
});
|