orbitchat 1.0.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 +314 -0
- package/bin/orbitchat.js +435 -0
- package/dist/assets/Tableau10-D7jGxypv-Cyu9clx1.js +1 -0
- package/dist/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/dist/assets/api-m_QXEYxU.js +2 -0
- package/dist/assets/arc-hH97QygY-EgRQ19vy.js +1 -0
- package/dist/assets/blockDiagram-c4efeb88-CLLcV2XJ-BlzQog67.js +118 -0
- package/dist/assets/c4Diagram-c83219d4-Bq976NrW-DIPXTaap.js +10 -0
- package/dist/assets/channel-CSC8iKVS-o3Tgkjx3.js +1 -0
- package/dist/assets/classDiagram-beda092f-7G8Y9ObP-CrnhVq3q.js +2 -0
- package/dist/assets/classDiagram-v2-2358418a-CYz_KHej-BnPcDcYV.js +2 -0
- package/dist/assets/clone-vCPXKFeo-DdQ4WIiO.js +1 -0
- package/dist/assets/createText-1719965b-Cbn6MBZp-zrb_KsAx.js +7 -0
- package/dist/assets/edges-96097737-XAH6P1yX-hj5ay2ub.js +4 -0
- package/dist/assets/erDiagram-0228fc6a-Bj5SeSQq-SNOEiwxn.js +51 -0
- package/dist/assets/flowDb-c6c81e3f-CaVKc_SB-DeOFQ2aw.js +10 -0
- package/dist/assets/flowDiagram-50d868cf-BcT1Qv7E-CI_0iUc_.js +4 -0
- package/dist/assets/flowDiagram-v2-4f6560a1-B0fti9Da-D8Np9r9b.js +1 -0
- package/dist/assets/flowchart-elk-definition-6af322e1-CIF5zs_e-CA7galDX.js +139 -0
- package/dist/assets/ganttDiagram-a2739b55-wX4z0bcl-BV5WSU0F.js +257 -0
- package/dist/assets/gitGraphDiagram-82fe8481-BTMrrqSM-BAXm_J1X.js +70 -0
- package/dist/assets/graph-Bc6U-Oet-BbypjADy.js +1 -0
- package/dist/assets/index-5325376f-DCLsNwAa-BxOfAZRl.js +1 -0
- package/dist/assets/index-BKRCw_DF.js +966 -0
- package/dist/assets/index-BbD-jy76.css +1 -0
- package/dist/assets/infoDiagram-8eee0895-CGdieI3d-CeI4A8me.js +7 -0
- package/dist/assets/journeyDiagram-c64418c1-D741T7Vx-D7bBbz5a.js +139 -0
- package/dist/assets/layout-BtHnec7v-DPk8SWBY.js +1 -0
- package/dist/assets/mindmap-definition-8da855dc-DYXCEYTW-C9VeqS3S.js +425 -0
- package/dist/assets/pieDiagram-a8764435-56nwm0bs-OTliuzET.js +35 -0
- package/dist/assets/quadrantDiagram-1e28029f-BPDrTwrc-BeDUiVSw.js +7 -0
- package/dist/assets/requirementDiagram-08caed73-ErOyM087-fZE1bidE.js +52 -0
- package/dist/assets/sankeyDiagram-a04cb91d-Dr_h6k2R-DV92AQzo.js +8 -0
- package/dist/assets/sequenceDiagram-c5b8d532-wtK0ihCE-CMdlx77G.js +122 -0
- package/dist/assets/stateDiagram-1ecb1508-D6rDYnWS-BXgBNGIv.js +1 -0
- package/dist/assets/stateDiagram-v2-c2b004d7-K0flL3uN-DMmV3VwJ.js +1 -0
- package/dist/assets/styles-b4e223ce-CPkoRhK8-B88f_9TS.js +160 -0
- package/dist/assets/styles-ca3715f6-FCD4s0nN-BJNUoxcm.js +207 -0
- package/dist/assets/styles-d45a18b0-7fTS_K4G-BSFqTrx5.js +116 -0
- package/dist/assets/svgDrawCommon-b86b1483-C9ebAubK-DzwEtGVK.js +1 -0
- package/dist/assets/timeline-definition-faaaa080-C-TPmIif-CPB6N7Tu.js +61 -0
- package/dist/assets/xychartDiagram-f5964ef8-Dy6Sev6Z-UG5jLwgB.js +7 -0
- package/dist/index.html +26 -0
- package/package.json +56 -0
package/bin/orbitchat.js
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ORBIT Chat CLI
|
|
4
|
+
*
|
|
5
|
+
* Serves the chat-app as a standalone application with runtime configuration.
|
|
6
|
+
* Configuration can be provided via CLI arguments, config file, or environment variables.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import http from 'http';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { homedir } from 'os';
|
|
13
|
+
import { execSync } from 'child_process';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { dirname } from 'path';
|
|
16
|
+
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = dirname(__filename);
|
|
19
|
+
|
|
20
|
+
// Default configuration matching env.example
|
|
21
|
+
// Note: GitHub stats/owner/repo are hardcoded and only configurable via build-time env vars
|
|
22
|
+
const DEFAULT_CONFIG = {
|
|
23
|
+
apiUrl: 'http://localhost:3000',
|
|
24
|
+
defaultKey: 'default-key',
|
|
25
|
+
useLocalApi: false,
|
|
26
|
+
localApiPath: undefined,
|
|
27
|
+
consoleDebug: false,
|
|
28
|
+
enableUploadButton: false,
|
|
29
|
+
enableFeedbackButtons: false,
|
|
30
|
+
maxFilesPerConversation: 5,
|
|
31
|
+
maxFileSizeMB: 50,
|
|
32
|
+
maxTotalFiles: 100,
|
|
33
|
+
maxConversations: 10,
|
|
34
|
+
maxMessagesPerConversation: 1000,
|
|
35
|
+
maxTotalMessages: 10000,
|
|
36
|
+
maxMessageLength: 1000,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Parse command-line arguments
|
|
41
|
+
*/
|
|
42
|
+
function parseArgs() {
|
|
43
|
+
const args = process.argv.slice(2);
|
|
44
|
+
const config = { ...DEFAULT_CONFIG };
|
|
45
|
+
const serverConfig = {
|
|
46
|
+
port: 5173,
|
|
47
|
+
host: 'localhost',
|
|
48
|
+
open: false,
|
|
49
|
+
configFile: null,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
for (let i = 0; i < args.length; i++) {
|
|
53
|
+
const arg = args[i];
|
|
54
|
+
|
|
55
|
+
switch (arg) {
|
|
56
|
+
case '--api-url':
|
|
57
|
+
config.apiUrl = args[++i];
|
|
58
|
+
break;
|
|
59
|
+
case '--api-key':
|
|
60
|
+
case '--default-key':
|
|
61
|
+
config.defaultKey = args[++i];
|
|
62
|
+
break;
|
|
63
|
+
case '--use-local-api':
|
|
64
|
+
config.useLocalApi = args[++i] === 'true';
|
|
65
|
+
break;
|
|
66
|
+
case '--local-api-path':
|
|
67
|
+
config.localApiPath = args[++i];
|
|
68
|
+
break;
|
|
69
|
+
case '--console-debug':
|
|
70
|
+
config.consoleDebug = args[++i] === 'true';
|
|
71
|
+
break;
|
|
72
|
+
case '--enable-upload-button':
|
|
73
|
+
config.enableUploadButton = args[++i] === 'true';
|
|
74
|
+
break;
|
|
75
|
+
case '--enable-feedback-buttons':
|
|
76
|
+
config.enableFeedbackButtons = args[++i] === 'true';
|
|
77
|
+
break;
|
|
78
|
+
case '--max-files-per-conversation':
|
|
79
|
+
config.maxFilesPerConversation = parseInt(args[++i], 10);
|
|
80
|
+
break;
|
|
81
|
+
case '--max-file-size-mb':
|
|
82
|
+
config.maxFileSizeMB = parseInt(args[++i], 10);
|
|
83
|
+
break;
|
|
84
|
+
case '--max-total-files':
|
|
85
|
+
config.maxTotalFiles = parseInt(args[++i], 10);
|
|
86
|
+
break;
|
|
87
|
+
case '--max-conversations':
|
|
88
|
+
config.maxConversations = parseInt(args[++i], 10);
|
|
89
|
+
break;
|
|
90
|
+
case '--max-messages-per-conversation':
|
|
91
|
+
config.maxMessagesPerConversation = parseInt(args[++i], 10);
|
|
92
|
+
break;
|
|
93
|
+
case '--max-total-messages':
|
|
94
|
+
config.maxTotalMessages = parseInt(args[++i], 10);
|
|
95
|
+
break;
|
|
96
|
+
case '--max-message-length':
|
|
97
|
+
config.maxMessageLength = parseInt(args[++i], 10);
|
|
98
|
+
break;
|
|
99
|
+
case '--port':
|
|
100
|
+
serverConfig.port = parseInt(args[++i], 10);
|
|
101
|
+
break;
|
|
102
|
+
case '--host':
|
|
103
|
+
serverConfig.host = args[++i];
|
|
104
|
+
break;
|
|
105
|
+
case '--open':
|
|
106
|
+
serverConfig.open = true;
|
|
107
|
+
break;
|
|
108
|
+
case '--config':
|
|
109
|
+
serverConfig.configFile = args[++i];
|
|
110
|
+
break;
|
|
111
|
+
case '--help':
|
|
112
|
+
case '-h':
|
|
113
|
+
// Handled in main() function
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
if (arg.startsWith('--')) {
|
|
117
|
+
console.error(`Unknown option: ${arg}`);
|
|
118
|
+
console.error('Use --help for usage information');
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return { config, serverConfig };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Load configuration from file
|
|
129
|
+
*/
|
|
130
|
+
function loadConfigFile(filePath) {
|
|
131
|
+
try {
|
|
132
|
+
if (fs.existsSync(filePath)) {
|
|
133
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
134
|
+
return JSON.parse(content);
|
|
135
|
+
}
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.warn(`Warning: Could not load config file ${filePath}:`, error.message);
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Load configuration from environment variables
|
|
144
|
+
*/
|
|
145
|
+
function loadConfigFromEnv() {
|
|
146
|
+
const envConfig = {};
|
|
147
|
+
|
|
148
|
+
// Map VITE_* environment variables to config keys
|
|
149
|
+
const envMap = {
|
|
150
|
+
VITE_API_URL: 'apiUrl',
|
|
151
|
+
VITE_DEFAULT_KEY: 'defaultKey',
|
|
152
|
+
VITE_USE_LOCAL_API: 'useLocalApi',
|
|
153
|
+
VITE_LOCAL_API_PATH: 'localApiPath',
|
|
154
|
+
VITE_CONSOLE_DEBUG: 'consoleDebug',
|
|
155
|
+
VITE_ENABLE_UPLOAD_BUTTON: 'enableUploadButton',
|
|
156
|
+
VITE_ENABLE_FEEDBACK_BUTTONS: 'enableFeedbackButtons',
|
|
157
|
+
VITE_MAX_FILES_PER_CONVERSATION: 'maxFilesPerConversation',
|
|
158
|
+
VITE_MAX_FILE_SIZE_MB: 'maxFileSizeMB',
|
|
159
|
+
VITE_MAX_TOTAL_FILES: 'maxTotalFiles',
|
|
160
|
+
VITE_MAX_CONVERSATIONS: 'maxConversations',
|
|
161
|
+
VITE_MAX_MESSAGES_PER_CONVERSATION: 'maxMessagesPerConversation',
|
|
162
|
+
VITE_MAX_TOTAL_MESSAGES: 'maxTotalMessages',
|
|
163
|
+
VITE_MAX_MESSAGE_LENGTH: 'maxMessageLength',
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
for (const [envKey, configKey] of Object.entries(envMap)) {
|
|
167
|
+
const value = process.env[envKey];
|
|
168
|
+
if (value !== undefined) {
|
|
169
|
+
if (configKey === 'useLocalApi' || configKey === 'consoleDebug' ||
|
|
170
|
+
configKey === 'enableUploadButton' || configKey === 'enableFeedbackButtons') {
|
|
171
|
+
envConfig[configKey] = value === 'true';
|
|
172
|
+
} else if (configKey.includes('max') && configKey !== 'maxFileSizeMB') {
|
|
173
|
+
const parsed = parseInt(value, 10);
|
|
174
|
+
if (!isNaN(parsed)) {
|
|
175
|
+
envConfig[configKey] = parsed;
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
envConfig[configKey] = value;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return envConfig;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Merge configurations in priority order: CLI args > config file > env vars > defaults
|
|
188
|
+
* Note: GitHub stats/owner/repo are not included in runtime config - they're hardcoded
|
|
189
|
+
* and only configurable via build-time env vars for developers who fork.
|
|
190
|
+
*/
|
|
191
|
+
function mergeConfig(cliConfig, serverConfig) {
|
|
192
|
+
// Start with defaults
|
|
193
|
+
let config = { ...DEFAULT_CONFIG };
|
|
194
|
+
|
|
195
|
+
// Load from environment variables (excluding GitHub config)
|
|
196
|
+
const envConfig = loadConfigFromEnv();
|
|
197
|
+
config = { ...config, ...envConfig };
|
|
198
|
+
|
|
199
|
+
// Load from config file (excluding GitHub config)
|
|
200
|
+
const configDir = path.join(homedir(), '.orbit-chat-app');
|
|
201
|
+
const defaultConfigFile = path.join(configDir, 'config.json');
|
|
202
|
+
const configFile = serverConfig.configFile || defaultConfigFile;
|
|
203
|
+
|
|
204
|
+
const fileConfig = loadConfigFile(configFile);
|
|
205
|
+
if (fileConfig) {
|
|
206
|
+
// Remove GitHub config from file config if present
|
|
207
|
+
const { showGitHubStats, githubOwner, githubRepo, ...fileConfigWithoutGitHub } = fileConfig;
|
|
208
|
+
config = { ...config, ...fileConfigWithoutGitHub };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// CLI arguments override everything (excluding GitHub config)
|
|
212
|
+
const { showGitHubStats, githubOwner, githubRepo, ...cliConfigWithoutGitHub } = cliConfig;
|
|
213
|
+
config = { ...config, ...cliConfigWithoutGitHub };
|
|
214
|
+
|
|
215
|
+
return config;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Inject configuration into HTML
|
|
220
|
+
*/
|
|
221
|
+
function injectConfig(html, config) {
|
|
222
|
+
const configScript = `
|
|
223
|
+
<script>
|
|
224
|
+
window.ORBIT_CHAT_CONFIG = ${JSON.stringify(config, null, 2)};
|
|
225
|
+
</script>
|
|
226
|
+
`;
|
|
227
|
+
|
|
228
|
+
// Replace the placeholder script tag
|
|
229
|
+
return html.replace(
|
|
230
|
+
/<script id="orbit-chat-config" type="application\/json">[\s\S]*?<\/script>/,
|
|
231
|
+
configScript
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get MIME type for file extension
|
|
237
|
+
*/
|
|
238
|
+
function getMimeType(filePath) {
|
|
239
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
240
|
+
const mimeTypes = {
|
|
241
|
+
'.html': 'text/html',
|
|
242
|
+
'.js': 'application/javascript',
|
|
243
|
+
'.mjs': 'application/javascript',
|
|
244
|
+
'.json': 'application/json',
|
|
245
|
+
'.css': 'text/css',
|
|
246
|
+
'.png': 'image/png',
|
|
247
|
+
'.jpg': 'image/jpeg',
|
|
248
|
+
'.jpeg': 'image/jpeg',
|
|
249
|
+
'.gif': 'image/gif',
|
|
250
|
+
'.svg': 'image/svg+xml',
|
|
251
|
+
'.ico': 'image/x-icon',
|
|
252
|
+
'.woff': 'font/woff',
|
|
253
|
+
'.woff2': 'font/woff2',
|
|
254
|
+
'.ttf': 'font/ttf',
|
|
255
|
+
'.eot': 'application/vnd.ms-fontobject',
|
|
256
|
+
};
|
|
257
|
+
return mimeTypes[ext] || 'application/octet-stream';
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Create HTTP server to serve the built app
|
|
262
|
+
*/
|
|
263
|
+
function createServer(distPath, config) {
|
|
264
|
+
return http.createServer((req, res) => {
|
|
265
|
+
let filePath = path.join(distPath, req.url === '/' ? 'index.html' : req.url);
|
|
266
|
+
|
|
267
|
+
// Security: prevent directory traversal
|
|
268
|
+
filePath = path.normalize(filePath);
|
|
269
|
+
if (!filePath.startsWith(distPath)) {
|
|
270
|
+
res.writeHead(403);
|
|
271
|
+
res.end('Forbidden');
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Check if file exists
|
|
276
|
+
if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) {
|
|
277
|
+
// For SPA routing, serve index.html for non-file requests
|
|
278
|
+
if (!path.extname(filePath)) {
|
|
279
|
+
filePath = path.join(distPath, 'index.html');
|
|
280
|
+
} else {
|
|
281
|
+
res.writeHead(404);
|
|
282
|
+
res.end('Not Found');
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Read and serve file
|
|
288
|
+
try {
|
|
289
|
+
let content = fs.readFileSync(filePath);
|
|
290
|
+
|
|
291
|
+
// Inject configuration into HTML files
|
|
292
|
+
if (path.extname(filePath) === '.html') {
|
|
293
|
+
content = Buffer.from(injectConfig(content.toString(), config));
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const mimeType = getMimeType(filePath);
|
|
297
|
+
res.writeHead(200, { 'Content-Type': mimeType });
|
|
298
|
+
res.end(content);
|
|
299
|
+
} catch (error) {
|
|
300
|
+
res.writeHead(500);
|
|
301
|
+
res.end('Internal Server Error');
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Open browser
|
|
308
|
+
*/
|
|
309
|
+
function openBrowser(url) {
|
|
310
|
+
const platform = process.platform;
|
|
311
|
+
let command;
|
|
312
|
+
|
|
313
|
+
if (platform === 'darwin') {
|
|
314
|
+
command = `open "${url}"`;
|
|
315
|
+
} else if (platform === 'linux') {
|
|
316
|
+
command = `xdg-open "${url}"`;
|
|
317
|
+
} else if (platform === 'win32') {
|
|
318
|
+
command = `start "${url}"`;
|
|
319
|
+
} else {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
execSync(command, { stdio: 'ignore' });
|
|
325
|
+
} catch (error) {
|
|
326
|
+
// Ignore errors
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Print help message
|
|
332
|
+
*/
|
|
333
|
+
function printHelp() {
|
|
334
|
+
console.log(`
|
|
335
|
+
ORBIT Chat CLI
|
|
336
|
+
|
|
337
|
+
Usage: orbitchat [options]
|
|
338
|
+
|
|
339
|
+
Options:
|
|
340
|
+
--api-url URL API URL (default: http://localhost:3000)
|
|
341
|
+
--api-key KEY Default API key (default: default-key)
|
|
342
|
+
--use-local-api BOOLEAN Use local API build (default: false)
|
|
343
|
+
--local-api-path PATH Path to local API
|
|
344
|
+
--console-debug BOOLEAN Enable console debug (default: false)
|
|
345
|
+
--enable-upload-button BOOLEAN Enable upload button (default: false)
|
|
346
|
+
--enable-feedback-buttons BOOLEAN Enable feedback buttons (default: false)
|
|
347
|
+
--max-files-per-conversation N Max files per conversation (default: 5)
|
|
348
|
+
--max-file-size-mb N Max file size in MB (default: 50)
|
|
349
|
+
--max-total-files N Max total files (default: 100, 0 = unlimited)
|
|
350
|
+
--max-conversations N Max conversations (default: 10, 0 = unlimited)
|
|
351
|
+
--max-messages-per-conversation N Max messages per conversation (default: 1000, 0 = unlimited)
|
|
352
|
+
--max-total-messages N Max total messages (default: 10000, 0 = unlimited)
|
|
353
|
+
--max-message-length N Max message length (default: 1000)
|
|
354
|
+
--port PORT Server port (default: 5173)
|
|
355
|
+
--host HOST Server host (default: localhost)
|
|
356
|
+
--open Open browser automatically
|
|
357
|
+
--config PATH Path to config file (default: ~/.orbit-chat-app/config.json)
|
|
358
|
+
--help, -h Show this help message
|
|
359
|
+
|
|
360
|
+
Configuration Priority:
|
|
361
|
+
1. CLI arguments
|
|
362
|
+
2. Config file (~/.orbit-chat-app/config.json)
|
|
363
|
+
3. Environment variables (VITE_*)
|
|
364
|
+
4. Default values
|
|
365
|
+
|
|
366
|
+
Examples:
|
|
367
|
+
orbitchat --api-url http://localhost:3000 --port 8080
|
|
368
|
+
orbitchat --api-key my-key --open
|
|
369
|
+
orbitchat --config /path/to/config.json
|
|
370
|
+
`);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Main function
|
|
375
|
+
*/
|
|
376
|
+
function main() {
|
|
377
|
+
// Check for help flag first
|
|
378
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
379
|
+
printHelp();
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const { config: cliConfig, serverConfig } = parseArgs();
|
|
384
|
+
const config = mergeConfig(cliConfig, serverConfig);
|
|
385
|
+
|
|
386
|
+
// Find dist directory
|
|
387
|
+
// Use __dirname which we defined at the top of the file
|
|
388
|
+
const distPath = path.join(__dirname, '..', 'dist');
|
|
389
|
+
|
|
390
|
+
if (!fs.existsSync(distPath)) {
|
|
391
|
+
console.error('Error: dist directory not found. Please run "npm run build" first.');
|
|
392
|
+
process.exit(1);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Create and start server
|
|
396
|
+
const server = createServer(distPath, config);
|
|
397
|
+
|
|
398
|
+
server.listen(serverConfig.port, serverConfig.host, () => {
|
|
399
|
+
const url = `http://${serverConfig.host}:${serverConfig.port}`;
|
|
400
|
+
console.log(`\n🚀 ORBIT Chat App is running at ${url}\n`);
|
|
401
|
+
console.log('Configuration:');
|
|
402
|
+
console.log(` API URL: ${config.apiUrl}`);
|
|
403
|
+
console.log(` Default Key: ${config.defaultKey}`);
|
|
404
|
+
console.log(` Port: ${serverConfig.port}`);
|
|
405
|
+
console.log(` Host: ${serverConfig.host}\n`);
|
|
406
|
+
|
|
407
|
+
if (serverConfig.open) {
|
|
408
|
+
openBrowser(url);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// Handle graceful shutdown
|
|
413
|
+
process.on('SIGINT', () => {
|
|
414
|
+
console.log('\n\nShutting down server...');
|
|
415
|
+
server.close(() => {
|
|
416
|
+
console.log('Server closed.');
|
|
417
|
+
process.exit(0);
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Run if called directly (ES module equivalent of require.main === module)
|
|
423
|
+
// For ES modules, we check if this file is being executed directly
|
|
424
|
+
const isMainModule = process.argv[1] && (
|
|
425
|
+
import.meta.url === `file://${process.argv[1]}` ||
|
|
426
|
+
import.meta.url.endsWith(process.argv[1].replace(/\\/g, '/')) ||
|
|
427
|
+
process.argv[1].includes('orbitchat')
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
if (isMainModule) {
|
|
431
|
+
main();
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
export { main, parseArgs, mergeConfig };
|
|
435
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function b(f){for(var r=f.length/6|0,a=new Array(r),e=0;e<r;)a[e]="#"+f.slice(e*6,++e*6);return a}const c=b("4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab");export{c as r};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={};export{e as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{_ as P}from"./index-BKRCw_DF.js";var F=Object.defineProperty,b=(o,t,e)=>t in o?F(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e,m=(o,t,e)=>b(o,typeof t!="symbol"?t+"":t,e);let v=null,E=null;typeof window>"u"&&Promise.all([P(()=>import("./__vite-browser-external-BIHI7g3E.js"),[]).catch(()=>null),P(()=>import("./__vite-browser-external-BIHI7g3E.js"),[]).catch(()=>null)]).then(([o,t])=>{var e,r;(e=o==null?void 0:o.default)!=null&&e.Agent?v=new o.default.Agent({keepAlive:!0}):o!=null&&o.Agent&&(v=new o.Agent({keepAlive:!0})),(r=t==null?void 0:t.default)!=null&&r.Agent?E=new t.default.Agent({keepAlive:!0}):t!=null&&t.Agent&&(E=new t.Agent({keepAlive:!0}))}).catch(o=>{console.warn("Failed to initialize HTTP agents:",o.message)});class C{constructor(t){if(m(this,"apiUrl"),m(this,"apiKey"),m(this,"sessionId"),!t.apiUrl||typeof t.apiUrl!="string")throw new Error("API URL must be a valid string");if(t.apiKey!==void 0&&t.apiKey!==null&&typeof t.apiKey!="string")throw new Error("API key must be a valid string or null");if(t.sessionId!==void 0&&t.sessionId!==null&&typeof t.sessionId!="string")throw new Error("Session ID must be a valid string or null");this.apiUrl=t.apiUrl,this.apiKey=t.apiKey??null,this.sessionId=t.sessionId??null}setSessionId(t){if(t!==null&&typeof t!="string")throw new Error("Session ID must be a valid string or null");this.sessionId=t}getSessionId(){return this.sessionId}async validateApiKey(){var t;if(!this.apiKey)throw new Error("API key is required for validation");try{const e=await fetch(`${this.apiUrl}/admin/api-keys/${this.apiKey}/status`,{...this.getFetchOptions({method:"GET"})}).catch(s=>{throw s.name==="TypeError"&&s.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):s});if(!e.ok){let s="";try{s=await e.text()}catch{s=`HTTP ${e.status}`}let i,n;try{const a=JSON.parse(s);i=a.detail||a.message||s}catch{i=s||`HTTP ${e.status}`}switch(e.status){case 401:n="API key is invalid or expired";break;case 403:n="Access denied: API key does not have required permissions";break;case 404:n="API key not found";break;case 503:n="API key management is not available in inference-only mode";break;default:n=`Failed to validate API key: ${i}`;break}throw new Error(n)}const r=await e.json();if(!r.exists){const s="API key does not exist";throw new Error(s)}if(!r.active){const s="API key is inactive";throw new Error(s)}return r}catch(e){let r;throw e instanceof Error&&e.message?e.message.includes("API key")||e.message.includes("Access denied")||e.message.includes("invalid")||e.message.includes("expired")||e.message.includes("inactive")||e.message.includes("not found")||e.message.includes("Could not connect")?r=e.message:r=`API key validation failed: ${e.message}`:e.name==="TypeError"&&(t=e.message)!=null&&t.includes("Failed to fetch")?r="Could not connect to the server. Please check if the server is running.":r="API key validation failed. Please check your API key and try again.",console.warn(`[ApiClient] ${r}`),new Error(r)}}async getAdapterInfo(){var t;if(!this.apiKey)throw new Error("API key is required to get adapter information");try{const e=await fetch(`${this.apiUrl}/admin/api-keys/info`,{...this.getFetchOptions({method:"GET"})}).catch(r=>{throw r.name==="TypeError"&&r.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):r});if(!e.ok){let r="";try{r=await e.text()}catch{r=`HTTP ${e.status}`}let s,i;try{const n=JSON.parse(r);s=n.detail||n.message||r}catch{s=r||`HTTP ${e.status}`}switch(e.status){case 401:i="API key is invalid, disabled, or has no associated adapter";break;case 404:i="Adapter configuration not found";break;case 503:i="Service is not available";break;default:i=`Failed to get adapter info: ${s}`;break}throw new Error(i)}return await e.json()}catch(e){let r;throw e instanceof Error&&e.message?e.message.includes("API key")||e.message.includes("Adapter")||e.message.includes("invalid")||e.message.includes("disabled")||e.message.includes("not found")||e.message.includes("Could not connect")?r=e.message:r=`Failed to get adapter info: ${e.message}`:e.name==="TypeError"&&(t=e.message)!=null&&t.includes("Failed to fetch")?r="Could not connect to the server. Please check if the server is running.":r="Failed to get adapter information. Please try again.",console.warn(`[ApiClient] ${r}`),new Error(r)}}getFetchOptions(t={}){const e={};if(typeof window>"u"){const s=this.apiUrl.startsWith("https:")?E:v;s&&(e.agent=s)}else e.headers={Connection:"keep-alive"};const r={"X-Request-ID":Date.now().toString(36)+Math.random().toString(36).substring(2)};if(e.headers&&Object.assign(r,e.headers),t.headers){const s=t.headers;for(const[i,n]of Object.entries(s))(i.toLowerCase()!=="x-api-key"||!this.apiKey)&&(r[i]=n)}return this.apiKey&&(r["X-API-Key"]=this.apiKey),this.sessionId&&(r["X-Session-ID"]=this.sessionId),{...t,...e,headers:r}}createChatRequest(t,e=!0,r){const s={messages:[{role:"user",content:t}],stream:e};return r&&r.length>0&&(s.file_ids=r),s}async*streamChat(t,e=!0,r){var s,i;try{const n=new AbortController,a=setTimeout(()=>n.abort(),6e4),c=await fetch(`${this.apiUrl}/v1/chat`,{...this.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json",Accept:e?"text/event-stream":"application/json"},body:JSON.stringify(this.createChatRequest(t,e,r))}),signal:n.signal});if(clearTimeout(a),!c.ok){const h=await c.text();throw new Error(`Network response was not ok: ${c.status} ${h}`)}if(!e){const h=await c.json();h.response&&(yield{text:h.response,done:!0});return}const w=(s=c.body)==null?void 0:s.getReader();if(!w)throw new Error("No reader available");const I=new TextDecoder;let l="",p=!1;try{for(;;){const{done:h,value:$}=await w.read();if(h)break;const T=I.decode($,{stream:!0});l+=T;let f=0,y;for(;(y=l.indexOf(`
|
|
2
|
+
`,f))!==-1;){const u=l.slice(f,y).trim();if(f=y+1,u&&u.startsWith("data: ")){const g=u.slice(6).trim();if(!g||g==="[DONE]"){yield{text:"",done:!0};return}try{const d=JSON.parse(g);if(d.error){const A=`Server error: ${((i=d.error)==null?void 0:i.message)||d.error||"Unknown server error"}`;throw console.warn(`[ApiClient] ${A}`),new Error(A)}if(d.response&&(p=!0,yield{text:d.response,done:d.done||!1}),d.done){yield{text:"",done:!0};return}}catch{console.warn("[ApiClient] Unable to parse server response. This may be a temporary issue.")}}else u&&(p=!0,yield{text:u,done:!1})}l=l.slice(f),l.length>1e6&&(console.warn("Buffer too large, truncating..."),l=l.slice(-5e5))}p&&(yield{text:"",done:!0})}finally{w.releaseLock()}}catch(n){throw n.name==="AbortError"?new Error("Connection timed out. Please check if the server is running."):n.name==="TypeError"&&n.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):n}}async clearConversationHistory(t){const e=t||this.sessionId;if(!e)throw new Error("No session ID provided and no current session available");if(!this.apiKey)throw new Error("API key is required for clearing conversation history");const r={"Content-Type":"application/json","X-Session-ID":e,"X-API-Key":this.apiKey};try{const s=await fetch(`${this.apiUrl}/admin/chat-history/${e}`,{...this.getFetchOptions({method:"DELETE",headers:r})});if(!s.ok){const i=await s.text();throw new Error(`Failed to clear conversation history: ${s.status} ${i}`)}return await s.json()}catch(s){throw s.name==="TypeError"&&s.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):s}}async deleteConversationWithFiles(t,e){const r=t||this.sessionId;if(!r)throw new Error("No session ID provided and no current session available");if(!this.apiKey)throw new Error("API key is required for deleting conversation");const s={"Content-Type":"application/json","X-Session-ID":r,"X-API-Key":this.apiKey},i=e&&e.length>0?`?file_ids=${e.join(",")}`:"",n=`${this.apiUrl}/admin/conversations/${r}${i}`;try{const a=await fetch(n,{...this.getFetchOptions({method:"DELETE",headers:s})});if(!a.ok){const c=await a.text();throw new Error(`Failed to delete conversation: ${a.status} ${c}`)}return await a.json()}catch(a){throw a.name==="TypeError"&&a.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):a}}async uploadFile(t){if(!this.apiKey)throw new Error("API key is required for file upload");const e=new FormData;e.append("file",t);try{const r=await fetch(`${this.apiUrl}/api/files/upload`,{...this.getFetchOptions({method:"POST",body:e})});if(!r.ok){const s=await r.text();throw new Error(`Failed to upload file: ${r.status} ${s}`)}return await r.json()}catch(r){throw r.name==="TypeError"&&r.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):r}}async listFiles(){if(!this.apiKey)throw new Error("API key is required for listing files");try{const t=await fetch(`${this.apiUrl}/api/files`,{...this.getFetchOptions({method:"GET"})});if(!t.ok){const e=await t.text();throw new Error(`Failed to list files: ${t.status} ${e}`)}return await t.json()}catch(t){throw t.name==="TypeError"&&t.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):t}}async getFileInfo(t){if(!this.apiKey)throw new Error("API key is required for getting file info");try{const e=await fetch(`${this.apiUrl}/api/files/${t}`,{...this.getFetchOptions({method:"GET"})});if(!e.ok){const r=await e.text();throw new Error(`Failed to get file info: ${e.status} ${r}`)}return await e.json()}catch(e){throw e.name==="TypeError"&&e.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):e}}async queryFile(t,e,r=10){if(!this.apiKey)throw new Error("API key is required for querying files");try{const s=await fetch(`${this.apiUrl}/api/files/${t}/query`,{...this.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({query:e,max_results:r})})});if(!s.ok){const i=await s.text();throw new Error(`Failed to query file: ${s.status} ${i}`)}return await s.json()}catch(s){throw s.name==="TypeError"&&s.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):s}}async deleteFile(t){if(!this.apiKey)throw new Error("API key is required for deleting files");const e=`${this.apiUrl}/api/files/${t}`,r=this.getFetchOptions({method:"DELETE"});try{const s=await fetch(e,r);if(!s.ok){const i=await s.text();let n;try{const a=JSON.parse(i);n=a.detail||a.message||`Failed to delete file (HTTP ${s.status})`}catch{n=`Failed to delete file (HTTP ${s.status})`}throw console.warn(`[ApiClient] ${n}`),new Error(n)}return await s.json()}catch(s){let i;throw s.name==="TypeError"&&s.message.includes("Failed to fetch")?i="Could not connect to the server. Please check if the server is running.":s.message&&!s.message.includes("Failed to delete file")?i=s.message:i="Failed to delete file. Please try again.",console.warn(`[ApiClient] ${i}`),new Error(i)}}}let k=null;const x=(o,t=null,e=null)=>{k=new C({apiUrl:o,apiKey:t,sessionId:e})};async function*K(o,t=!0,e){if(!k)throw new Error("API not configured. Please call configureApi() with your server URL before using any API functions.");yield*k.streamChat(o,t,e)}export{C as ApiClient,x as configureApi,K as streamChat};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{aP as sn,aQ as an,aR as I,aS as _,ag as Z,aT as un,aU as l,ai as on,aV as $,aW as q,aX as cn,aY as e,aZ as en,a_ as rn,a$ as yn}from"./index-BKRCw_DF.js";function fn(s){return s.innerRadius}function ln(s){return s.outerRadius}function gn(s){return s.startAngle}function mn(s){return s.endAngle}function pn(s){return s&&s.padAngle}function xn(s,v,B,D,R,d,O,a){var K=B-s,r=D-v,n=O-R,m=a-d,u=m*K-n*r;if(!(u*u<l))return u=(n*(v-d)-m*(s-R))/u,[s+u*K,v+u*r]}function F(s,v,B,D,R,d,O){var a=s-B,K=v-D,r=(O?d:-d)/$(a*a+K*K),n=r*K,m=-r*a,u=s+n,i=v+m,y=B+n,f=D+m,Q=(u+y)/2,o=(i+f)/2,p=y-u,g=f-i,T=p*p+g*g,A=R-d,E=u*f-y*i,P=(g<0?-1:1)*$(en(0,A*A*T-E*E)),S=(E*g-p*P)/T,V=(-E*p-g*P)/T,X=(E*g+p*P)/T,x=(-E*p+g*P)/T,h=S-Q,t=V-o,c=X-Q,U=x-o;return h*h+t*t>c*c+U*U&&(S=X,V=x),{cx:S,cy:V,x01:-n,y01:-m,x11:S*(R/A-1),y11:V*(R/A-1)}}function vn(){var s=fn,v=ln,B=Z(0),D=null,R=gn,d=mn,O=pn,a=null,K=sn(r);function r(){var n,m,u=+s.apply(this,arguments),i=+v.apply(this,arguments),y=R.apply(this,arguments)-un,f=d.apply(this,arguments)-un,Q=cn(f-y),o=f>y;if(a||(a=n=K()),i<u&&(m=i,i=u,u=m),!(i>l))a.moveTo(0,0);else if(Q>on-l)a.moveTo(i*I(y),i*_(y)),a.arc(0,0,i,y,f,!o),u>l&&(a.moveTo(u*I(f),u*_(f)),a.arc(0,0,u,f,y,o));else{var p=y,g=f,T=y,A=f,E=Q,P=Q,S=O.apply(this,arguments)/2,V=S>l&&(D?+D.apply(this,arguments):$(u*u+i*i)),X=q(cn(i-u)/2,+B.apply(this,arguments)),x=X,h=X,t,c;if(V>l){var U=rn(V/u*_(S)),b=rn(V/i*_(S));(E-=U*2)>l?(U*=o?1:-1,T+=U,A-=U):(E=0,T=A=(y+f)/2),(P-=b*2)>l?(b*=o?1:-1,p+=b,g-=b):(P=0,p=g=(y+f)/2)}var L=i*I(p),Y=i*_(p),k=u*I(A),C=u*_(A);if(X>l){var M=i*I(g),N=i*_(g),G=u*I(T),H=u*_(T),W;if(Q<an)if(W=xn(L,Y,G,H,M,N,k,C)){var J=L-W[0],j=Y-W[1],w=M-W[0],z=N-W[1],nn=1/_(yn((J*w+j*z)/($(J*J+j*j)*$(w*w+z*z)))/2),tn=$(W[0]*W[0]+W[1]*W[1]);x=q(X,(u-tn)/(nn-1)),h=q(X,(i-tn)/(nn+1))}else x=h=0}P>l?h>l?(t=F(G,H,L,Y,i,h,o),c=F(M,N,k,C,i,h,o),a.moveTo(t.cx+t.x01,t.cy+t.y01),h<X?a.arc(t.cx,t.cy,h,e(t.y01,t.x01),e(c.y01,c.x01),!o):(a.arc(t.cx,t.cy,h,e(t.y01,t.x01),e(t.y11,t.x11),!o),a.arc(0,0,i,e(t.cy+t.y11,t.cx+t.x11),e(c.cy+c.y11,c.cx+c.x11),!o),a.arc(c.cx,c.cy,h,e(c.y11,c.x11),e(c.y01,c.x01),!o))):(a.moveTo(L,Y),a.arc(0,0,i,p,g,!o)):a.moveTo(L,Y),!(u>l)||!(E>l)?a.lineTo(k,C):x>l?(t=F(k,C,M,N,u,-x,o),c=F(L,Y,G,H,u,-x,o),a.lineTo(t.cx+t.x01,t.cy+t.y01),x<X?a.arc(t.cx,t.cy,x,e(t.y01,t.x01),e(c.y01,c.x01),!o):(a.arc(t.cx,t.cy,x,e(t.y01,t.x01),e(t.y11,t.x11),!o),a.arc(0,0,u,e(t.cy+t.y11,t.cx+t.x11),e(c.cy+c.y11,c.cx+c.x11),o),a.arc(c.cx,c.cy,x,e(c.y11,c.x11),e(c.y01,c.x01),!o))):a.arc(0,0,u,A,T,o)}if(a.closePath(),n)return a=null,n+""||null}return r.centroid=function(){var n=(+s.apply(this,arguments)+ +v.apply(this,arguments))/2,m=(+R.apply(this,arguments)+ +d.apply(this,arguments))/2-an/2;return[I(m)*n,_(m)*n]},r.innerRadius=function(n){return arguments.length?(s=typeof n=="function"?n:Z(+n),r):s},r.outerRadius=function(n){return arguments.length?(v=typeof n=="function"?n:Z(+n),r):v},r.cornerRadius=function(n){return arguments.length?(B=typeof n=="function"?n:Z(+n),r):B},r.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:Z(+n),r):D},r.startAngle=function(n){return arguments.length?(R=typeof n=="function"?n:Z(+n),r):R},r.endAngle=function(n){return arguments.length?(d=typeof n=="function"?n:Z(+n),r):d},r.padAngle=function(n){return arguments.length?(O=typeof n=="function"?n:Z(+n),r):O},r.context=function(n){return arguments.length?(a=n??null,r):a},r}export{vn as h};
|