LeroyDyer commited on
Commit
e085a8d
·
verified ·
1 Parent(s): fbf057f

Upload 8 files

Browse files
Files changed (8) hide show
  1. Console A.jpg +0 -0
  2. Console_B.jpg +0 -0
  3. LCARS_0047.JPG +0 -0
  4. LCARS_PANEL.png +0 -0
  5. LCARS__LOGO.jpg +0 -0
  6. Padd_1.html +590 -0
  7. Padd_2.html +765 -0
  8. Padd_3.html +726 -0
Console A.jpg ADDED
Console_B.jpg ADDED
LCARS_0047.JPG ADDED
LCARS_PANEL.png ADDED
LCARS__LOGO.jpg ADDED
Padd_1.html ADDED
@@ -0,0 +1,590 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LCARS Multimodal Chat Agent</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ body {
16
+ font-family: 'Orbitron', monospace;
17
+ background: linear-gradient(135deg, #000 0%, #111 50%, #000 100%);
18
+ color: #ff9900;
19
+ min-height: 100vh;
20
+ overflow-x: hidden;
21
+ }
22
+
23
+ .lcars-container {
24
+ display: grid;
25
+ grid-template-areas:
26
+ "header header header"
27
+ "left-panel main-content right-panel"
28
+ "bottom-left bottom-center bottom-right";
29
+ grid-template-rows: 80px 1fr 60px;
30
+ grid-template-columns: 200px 1fr 200px;
31
+ height: 100vh;
32
+ gap: 8px;
33
+ padding: 8px;
34
+ }
35
+
36
+ .lcars-panel {
37
+ background: linear-gradient(45deg, #336699, #4488bb);
38
+ border-radius: 20px;
39
+ position: relative;
40
+ overflow: hidden;
41
+ }
42
+
43
+ .lcars-panel::before {
44
+ content: '';
45
+ position: absolute;
46
+ top: 0;
47
+ left: 0;
48
+ right: 0;
49
+ bottom: 0;
50
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
51
+ animation: shimmer 3s infinite;
52
+ }
53
+
54
+ @keyframes shimmer {
55
+ 0% { transform: translateX(-100%); }
56
+ 100% { transform: translateX(100%); }
57
+ }
58
+
59
+ .header {
60
+ grid-area: header;
61
+ background: linear-gradient(90deg, #ff6600, #ff9900);
62
+ display: flex;
63
+ align-items: center;
64
+ padding: 0 30px;
65
+ border-radius: 0 0 40px 40px;
66
+ }
67
+
68
+ .header h1 {
69
+ color: #000;
70
+ font-weight: 900;
71
+ font-size: 1.8rem;
72
+ text-shadow: 2px 2px 4px rgba(255,255,255,0.3);
73
+ }
74
+
75
+ .left-panel {
76
+ grid-area: left-panel;
77
+ background: linear-gradient(180deg, #cc3366, #ff3366);
78
+ border-radius: 0 40px 40px 0;
79
+ padding: 20px;
80
+ }
81
+
82
+ .right-panel {
83
+ grid-area: right-panel;
84
+ background: linear-gradient(180deg, #6633cc, #9933ff);
85
+ border-radius: 40px 0 0 40px;
86
+ padding: 20px;
87
+ }
88
+
89
+ .main-content {
90
+ grid-area: main-content;
91
+ background: rgba(0, 0, 0, 0.8);
92
+ border: 2px solid #ff9900;
93
+ border-radius: 20px;
94
+ padding: 20px;
95
+ display: flex;
96
+ flex-direction: column;
97
+ gap: 15px;
98
+ }
99
+
100
+ .bottom-left {
101
+ grid-area: bottom-left;
102
+ background: linear-gradient(90deg, #00ccff, #0099cc);
103
+ border-radius: 40px 40px 0 0;
104
+ }
105
+
106
+ .bottom-center {
107
+ grid-area: bottom-center;
108
+ background: linear-gradient(90deg, #00ff66, #00cc44);
109
+ border-radius: 40px 40px 40px 40px;
110
+ }
111
+
112
+ .bottom-right {
113
+ grid-area: bottom-right;
114
+ background: linear-gradient(90deg, #ffcc00, #ff9900);
115
+ border-radius: 40px 40px 0 0;
116
+ }
117
+
118
+ .chat-container {
119
+ flex: 1;
120
+ display: flex;
121
+ flex-direction: column;
122
+ gap: 15px;
123
+ }
124
+
125
+ .message-area {
126
+ flex: 1;
127
+ background: rgba(0, 20, 40, 0.9);
128
+ border: 1px solid #336699;
129
+ border-radius: 15px;
130
+ padding: 15px;
131
+ overflow-y: auto;
132
+ min-height: 300px;
133
+ }
134
+
135
+ .message {
136
+ margin-bottom: 15px;
137
+ padding: 10px;
138
+ border-radius: 10px;
139
+ animation: slideIn 0.3s ease-out;
140
+ }
141
+
142
+ @keyframes slideIn {
143
+ from { opacity: 0; transform: translateY(20px); }
144
+ to { opacity: 1; transform: translateY(0); }
145
+ }
146
+
147
+ .user-message {
148
+ background: linear-gradient(135deg, #ff6600, #ff9900);
149
+ color: #000;
150
+ margin-left: 50px;
151
+ border-radius: 15px 15px 5px 15px;
152
+ }
153
+
154
+ .assistant-message {
155
+ background: linear-gradient(135deg, #336699, #4488bb);
156
+ color: #fff;
157
+ margin-right: 50px;
158
+ border-radius: 15px 15px 15px 5px;
159
+ }
160
+
161
+ .thinking-message {
162
+ background: linear-gradient(135deg, #cc3366, #ff3366);
163
+ color: #fff;
164
+ margin-right: 100px;
165
+ border-radius: 10px;
166
+ font-style: italic;
167
+ font-size: 0.9em;
168
+ }
169
+
170
+ .input-section {
171
+ background: rgba(0, 30, 60, 0.9);
172
+ border: 1px solid #ff9900;
173
+ border-radius: 15px;
174
+ padding: 15px;
175
+ }
176
+
177
+ .input-row {
178
+ display: flex;
179
+ gap: 10px;
180
+ align-items: center;
181
+ margin-bottom: 10px;
182
+ }
183
+
184
+ .lcars-input {
185
+ flex: 1;
186
+ background: rgba(0, 0, 0, 0.8);
187
+ border: 1px solid #ff9900;
188
+ border-radius: 10px;
189
+ padding: 12px;
190
+ color: #ff9900;
191
+ font-family: 'Orbitron', monospace;
192
+ font-size: 14px;
193
+ }
194
+
195
+ .lcars-input:focus {
196
+ outline: none;
197
+ border-color: #ffcc00;
198
+ box-shadow: 0 0 10px rgba(255, 204, 0, 0.3);
199
+ }
200
+
201
+ .lcars-button {
202
+ background: linear-gradient(45deg, #ff6600, #ff9900);
203
+ border: none;
204
+ border-radius: 20px;
205
+ padding: 12px 25px;
206
+ color: #000;
207
+ font-family: 'Orbitron', monospace;
208
+ font-weight: 700;
209
+ cursor: pointer;
210
+ transition: all 0.3s;
211
+ text-transform: uppercase;
212
+ }
213
+
214
+ .lcars-button:hover {
215
+ background: linear-gradient(45deg, #ff9900, #ffcc00);
216
+ transform: translateY(-2px);
217
+ box-shadow: 0 4px 15px rgba(255, 153, 0, 0.4);
218
+ }
219
+
220
+ .file-input {
221
+ display: none;
222
+ }
223
+
224
+ .file-label {
225
+ background: linear-gradient(45deg, #336699, #4488bb);
226
+ border-radius: 15px;
227
+ padding: 8px 15px;
228
+ color: #fff;
229
+ cursor: pointer;
230
+ font-size: 12px;
231
+ transition: all 0.3s;
232
+ }
233
+
234
+ .file-label:hover {
235
+ background: linear-gradient(45deg, #4488bb, #66aadd);
236
+ }
237
+
238
+ .settings-grid {
239
+ display: grid;
240
+ grid-template-columns: 1fr 1fr;
241
+ gap: 10px;
242
+ margin-top: 15px;
243
+ }
244
+
245
+ .settings-row label {
246
+ font-size: 12px;
247
+ color: #66aadd;
248
+ min-width: 80px;
249
+ }
250
+
251
+ .settings-input {
252
+ background: rgba(0, 0, 0, 0.6);
253
+ border: 1px solid #66aadd;
254
+ border-radius: 5px;
255
+ padding: 5px 10px;
256
+ color: #66aadd;
257
+ font-family: 'Orbitron', monospace;
258
+ font-size: 12px;
259
+ flex: 1;
260
+ }
261
+
262
+ .status-bar {
263
+ display: flex;
264
+ justify-content: space-between;
265
+ align-items: center;
266
+ padding: 0 20px;
267
+ background: rgba(0, 0, 0, 0.8);
268
+ border-top: 1px solid #ff9900;
269
+ height: 40px;
270
+ font-size: 12px;
271
+ }
272
+
273
+ .status-indicator {
274
+ display: flex;
275
+ align-items: center;
276
+ gap: 5px;
277
+ }
278
+
279
+ .status-dot {
280
+ width: 8px;
281
+ height: 8px;
282
+ border-radius: 50%;
283
+ background: #00ff66;
284
+ animation: pulse 2s infinite;
285
+ }
286
+
287
+ @keyframes pulse {
288
+ 0%, 100% { opacity: 1; }
289
+ 50% { opacity: 0.5; }
290
+ }
291
+
292
+ .side-button {
293
+ width: 100%;
294
+ background: rgba(255, 255, 255, 0.1);
295
+ border: 1px solid rgba(255, 255, 255, 0.3);
296
+ border-radius: 10px;
297
+ padding: 10px;
298
+ color: #fff;
299
+ font-family: 'Orbitron', monospace;
300
+ font-size: 11px;
301
+ cursor: pointer;
302
+ margin-bottom: 10px;
303
+ transition: all 0.3s;
304
+ }
305
+
306
+ .side-button:hover {
307
+ background: rgba(255, 255, 255, 0.2);
308
+ transform: scale(1.05);
309
+ }
310
+
311
+ .session-info {
312
+ font-size: 10px;
313
+ color: rgba(255, 255, 255, 0.7);
314
+ margin-top: 10px;
315
+ }
316
+
317
+ @media (max-width: 1200px) {
318
+ .lcars-container {
319
+ grid-template-areas:
320
+ "header header header"
321
+ "main-content main-content main-content"
322
+ "bottom-left bottom-center bottom-right";
323
+ grid-template-columns: 1fr;
324
+ }
325
+ .left-panel, .right-panel { display: none; }
326
+ }
327
+ </style>
328
+ </head>
329
+ <body>
330
+ <div class="lcars-container">
331
+ <div class="header">
332
+ <h1>🧠 MULTIMODAL CHAT AGENT - LCARS INTERFACE</h1>
333
+ </div>
334
+
335
+ <div class="left-panel lcars-panel">
336
+ <div class="side-controls">
337
+ <button class="side-button" onclick="saveSession()">SAVE SESSION</button>
338
+ <button class="side-button" onclick="document.getElementById('load-session').click()">LOAD SESSION</button>
339
+ <button class="side-button" onclick="createDataset()">CREATE DATASET</button>
340
+ <button class="side-button" onclick="clearChat()">CLEAR CHAT</button>
341
+ <div class="session-info">
342
+ <div>SESSION: ACTIVE</div>
343
+ <div>MESSAGES: <span id="message-count">0</span></div>
344
+ </div>
345
+ </div>
346
+ </div>
347
+
348
+ <div class="main-content">
349
+ <div class="chat-container">
350
+ <div class="message-area" id="messages">
351
+ <div class="message assistant-message">
352
+ <strong>SYSTEM:</strong> LCARS Multimodal Chat Agent initialized. Ready for communication.
353
+ </div>
354
+ </div>
355
+
356
+ <div class="input-section">
357
+ <div class="input-row">
358
+ <input type="text" class="lcars-input" id="user-input" placeholder="Enter your message..." />
359
+ <button class="lcars-button" onclick="sendMessage()">TRANSMIT</button>
360
+ </div>
361
+ <div class="input-row">
362
+ <input type="file" id="image-input" class="file-input" accept=".png,.jpg,.jpeg" onchange="handleFileSelect(this, 'image')" />
363
+ <label for="image-input" class="file-label">📷 IMAGE</label>
364
+
365
+ <input type="file" id="file-input" class="file-input" accept=".py,.txt,.md,.json,.csv" onchange="handleFileSelect(this, 'file')" />
366
+ <label for="file-input" class="file-label">📄 FILE</label>
367
+
368
+ <span id="file-status"></span>
369
+ </div>
370
+
371
+ <div class="settings-grid">
372
+ <div class="settings-row">
373
+ <label>API:</label>
374
+ <input type="text" class="settings-input" id="api-key" value="not-needed" />
375
+ </div>
376
+ <div class="settings-row">
377
+ <label>URL:</label>
378
+ <input type="text" class="settings-input" id="base-url" value="http://localhost:1234/v1" />
379
+ </div>
380
+ <div class="settings-row">
381
+ <label>MODEL:</label>
382
+ <input type="text" class="settings-input" id="model" value="qwen2-vl-2b-instruct" />
383
+ </div>
384
+ <div class="settings-row">
385
+ <label>TEMP:</label>
386
+ <input type="range" class="settings-input" id="temperature" min="0" max="1" step="0.1" value="0.7" oninput="document.getElementById('temp-display').textContent=this.value" />
387
+ <span id="temp-display">0.7</span>
388
+ </div>
389
+ </div>
390
+ </div>
391
+ </div>
392
+
393
+ <div class="status-bar">
394
+ <div class="status-indicator">
395
+ <div class="status-dot"></div>
396
+ <span>SYSTEM ONLINE</span>
397
+ </div>
398
+ <div>STARDATE: <span id="stardate"></span></div>
399
+ </div>
400
+ </div>
401
+
402
+ <div class="right-panel lcars-panel">
403
+ <div class="side-controls">
404
+ <button class="side-button" onclick="toggleSettings()">SETTINGS</button>
405
+ <button class="side-button" onclick="showHelp()">HELP</button>
406
+ <button class="side-button" onclick="showStats()">STATISTICS</button>
407
+ <button class="side-button" onclick="exportChat()">EXPORT</button>
408
+ <div class="session-info">
409
+ <div>TEMP: <span id="temp-display">0.7</span></div>
410
+ <div>TOKENS: <span id="token-count">512</span></div>
411
+ <div>STATUS: READY</div>
412
+ </div>
413
+ </div>
414
+ </div>
415
+
416
+ <div class="bottom-left lcars-panel"></div>
417
+ <div class="bottom-center lcars-panel"></div>
418
+ <div class="bottom-right lcars-panel"></div>
419
+ </div>
420
+
421
+ <input type="file" id="load-session" class="file-input" accept=".json" onchange="loadSession(this)" />
422
+
423
+ <script>
424
+ let chatHistory = [];
425
+ let currentImage = null;
426
+ let currentFile = null;
427
+ let messageCount = 0;
428
+
429
+ document.addEventListener('DOMContentLoaded', function () {
430
+ updateStardate();
431
+ setInterval(updateStardate, 1000);
432
+
433
+ document.getElementById('user-input').addEventListener('keypress', e => {
434
+ if (e.key === 'Enter') sendMessage();
435
+ });
436
+ });
437
+
438
+ function updateStardate() {
439
+ const now = new Date();
440
+ const stardate = (now.getFullYear() - 2000) * 1000 + (now.getMonth() + 1) * 30 + now.getDate() + (now.getHours() / 24);
441
+ document.getElementById('stardate').textContent = stardate.toFixed(1);
442
+ }
443
+
444
+ function addMessage(content, type, isThinking = false) {
445
+ const messagesArea = document.getElementById('messages');
446
+ const messageDiv = document.createElement('div');
447
+ messageDiv.className = `message ${type}-message ${isThinking ? 'thinking-message' : ''}`;
448
+
449
+ if (isThinking) {
450
+ messageDiv.innerHTML = `<strong>PROCESSING:</strong> ${content}`;
451
+ } else if (type === 'user') {
452
+ messageDiv.innerHTML = `<strong>USER:</strong> ${content}`;
453
+ } else {
454
+ messageDiv.innerHTML = `<strong>ASSISTANT:</strong> ${content}`;
455
+ }
456
+
457
+ messagesArea.appendChild(messageDiv);
458
+ messagesArea.scrollTop = messagesArea.scrollHeight;
459
+
460
+ if (!isThinking) {
461
+ messageCount++;
462
+ document.getElementById('message-count').textContent = messageCount;
463
+ }
464
+ }
465
+
466
+ async function sendMessage() {
467
+ const input = document.getElementById('user-input');
468
+ const message = input.value.trim();
469
+ if (!message && !currentImage && !currentFile) return;
470
+
471
+ addMessage(message + (currentImage ? ' [📷]' : '') + (currentFile ? ' [📄]' : ''), 'user');
472
+ input.value = '';
473
+ addMessage('Analyzing input and generating response...', 'assistant', true);
474
+
475
+ setTimeout(() => {
476
+ const thinkingMsg = document.querySelector('.thinking-message');
477
+ if (thinkingMsg) thinkingMsg.remove();
478
+
479
+ let response = "I've processed your input. ";
480
+ if (message.includes("hello")) response = "Greetings, Captain. How may I assist you today?";
481
+ else if (currentImage) response = "Image analysis complete. Visual data is coherent and within expected parameters.";
482
+ else if (currentFile) response = "File processed. Data structure is intact. Awaiting further instructions.";
483
+ else response += "Response generated successfully.";
484
+
485
+ addMessage(response, 'assistant');
486
+ chatHistory.push({ role: 'user', content: message, image: currentImage, file: currentFile });
487
+ chatHistory.push({ role: 'assistant', content: response });
488
+
489
+ currentImage = currentFile = null;
490
+ document.getElementById('file-status').textContent = '';
491
+ }, 1500);
492
+ }
493
+
494
+ function handleFileSelect(input, type) {
495
+ const file = input.files[0];
496
+ if (file) {
497
+ const reader = new FileReader();
498
+ reader.onload = function (e) {
499
+ if (type === 'image') {
500
+ currentImage = e.target.result.split(',')[1];
501
+ document.getElementById('file-status').textContent = '📷 Image loaded';
502
+ } else {
503
+ currentFile = e.target.result;
504
+ document.getElementById('file-status').textContent = '📄 File loaded';
505
+ }
506
+ };
507
+ type === 'image' ? reader.readAsDataURL(file) : reader.readAsText(file);
508
+ }
509
+ }
510
+
511
+ function saveSession() {
512
+ const data = {
513
+ timestamp: new Date().toISOString(),
514
+ chatHistory,
515
+ settings: {
516
+ apiKey: document.getElementById('api-key').value,
517
+ baseUrl: document.getElementById('base-url').value,
518
+ model: document.getElementById('model').value,
519
+ temperature: document.getElementById('temperature').value
520
+ }
521
+ };
522
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
523
+ const url = URL.createObjectURL(blob);
524
+ const a = document.createElement('a');
525
+ a.href = url;
526
+ a.download = `lcars_session_${new Date().toISOString().split('T')[0]}.json`;
527
+ a.click();
528
+ URL.revokeObjectURL(url);
529
+ addMessage("Session saved.", "assistant");
530
+ }
531
+
532
+ function loadSession(input) {
533
+ const file = input.files[0];
534
+ if (file) {
535
+ const reader = new FileReader();
536
+ reader.onload = function (e) {
537
+ try {
538
+ const data = JSON.parse(e.target.result);
539
+ chatHistory = data.chatHistory || [];
540
+ document.getElementById('messages').innerHTML = '';
541
+ addMessage("Session restored from backup.", "assistant");
542
+ } catch (err) {
543
+ addMessage("Error loading session.", "assistant");
544
+ }
545
+ };
546
+ reader.readAsText(file);
547
+ }
548
+ }
549
+
550
+ function createDataset() {
551
+ if (chatHistory.length === 0) {
552
+ addMessage("No chat history to create dataset.", "assistant");
553
+ return;
554
+ }
555
+ const dataset = [chatHistory];
556
+ const blob = new Blob([JSON.stringify(dataset, null, 2)], { type: 'application/json' });
557
+ const url = URL.createObjectURL(blob);
558
+ const a = document.createElement('a');
559
+ a.href = url;
560
+ a.download = `dataset_${new Date().toISOString().split('T')[0]}.json`;
561
+ a.click();
562
+ URL.revokeObjectURL(url);
563
+ addMessage("Training dataset created.", "assistant");
564
+ }
565
+
566
+ function clearChat() {
567
+ document.getElementById('messages').innerHTML = '';
568
+ chatHistory = [];
569
+ messageCount = 0;
570
+ document.getElementById('message-count').textContent = '0';
571
+ addMessage("Chat cleared.", "assistant");
572
+ }
573
+
574
+ function exportChat() {
575
+ const text = chatHistory.map(m => `${m.role.toUpperCase()}: ${m.content}`).join('\n');
576
+ const blob = new Blob([text], { type: 'text/plain' });
577
+ const url = URL.createObjectURL(blob);
578
+ const a = document.createElement('a');
579
+ a.href = url;
580
+ a.download = 'chat_export.txt';
581
+ a.click();
582
+ URL.revokeObjectURL(url);
583
+ }
584
+
585
+ function showHelp() { addMessage("Help: Type a message, attach files, and press TRANSMIT.", "assistant"); }
586
+ function showStats() { addMessage(`Messages: ${messageCount}`, "assistant"); }
587
+ function toggleSettings() { addMessage("Settings panel toggled.", "assistant"); }
588
+ </script>
589
+ </body>
590
+ </html>
Padd_2.html ADDED
@@ -0,0 +1,765 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LCARS Multimodal Chat Agent</title>
7
+ <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
9
+
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ body {
17
+ font-family: 'Orbitron', monospace;
18
+ background: linear-gradient(135deg, #000 0%, #111 50%, #000 100%);
19
+ color: #ff9900;
20
+ min-height: 100vh;
21
+ overflow-x: hidden;
22
+ }
23
+
24
+ .lcars-container {
25
+ display: grid;
26
+ grid-template-areas:
27
+ "header"
28
+ "main-content"
29
+ "bottom-panel";
30
+ grid-template-rows: 80px 1fr 60px;
31
+ height: 100vh;
32
+ gap: 8px;
33
+ padding: 8px;
34
+ }
35
+
36
+ .header {
37
+ grid-area: header;
38
+ background: linear-gradient(90deg, #ff6600, #ff9900);
39
+ display: flex;
40
+ align-items: center;
41
+ padding: 0 30px;
42
+ border-radius: 0 0 40px 40px;
43
+ }
44
+
45
+ .header h1 {
46
+ color: #000;
47
+ font-weight: 900;
48
+ font-size: 1.8rem;
49
+ text-shadow: 2px 2px 4px rgba(255,255,255,0.3);
50
+ }
51
+
52
+ .main-content {
53
+ grid-area: main-content;
54
+ background: rgba(0, 0, 0, 0.8);
55
+ border: 2px solid #ff9900;
56
+ border-radius: 20px;
57
+ padding: 20px;
58
+ display: flex;
59
+ flex-direction: column;
60
+ gap: 15px;
61
+ position: relative;
62
+ }
63
+
64
+ .chat-container {
65
+ flex: 1;
66
+ display: flex;
67
+ flex-direction: column;
68
+ gap: 15px;
69
+ }
70
+
71
+ .message-area {
72
+ flex: 1;
73
+ background: rgba(0, 20, 40, 0.9);
74
+ border: 1px solid #336699;
75
+ border-radius: 15px;
76
+ padding: 15px;
77
+ overflow-y: auto;
78
+ min-height: 300px;
79
+ }
80
+
81
+ .message {
82
+ margin-bottom: 15px;
83
+ padding: 10px;
84
+ border-radius: 10px;
85
+ animation: slideIn 0.3s ease-out;
86
+ }
87
+
88
+ @keyframes slideIn {
89
+ from { opacity: 0; transform: translateY(20px); }
90
+ to { opacity: 1; transform: translateY(0); }
91
+ }
92
+
93
+ .user-message {
94
+ background: linear-gradient(135deg, #ff6600, #ff9900);
95
+ color: #000;
96
+ margin-left: 50px;
97
+ border-radius: 15px 15px 5px 15px;
98
+ }
99
+
100
+ .assistant-message {
101
+ background: linear-gradient(135deg, #336699, #4488bb);
102
+ color: #fff;
103
+ margin-right: 50px;
104
+ border-radius: 15px 15px 15px 5px;
105
+ }
106
+
107
+ .thinking-message {
108
+ background: linear-gradient(135deg, #cc3366, #ff3366);
109
+ color: #fff;
110
+ margin-right: 100px;
111
+ border-radius: 10px;
112
+ font-style: italic;
113
+ font-size: 0.9em;
114
+ }
115
+
116
+ .input-section {
117
+ background: rgba(0, 30, 60, 0.9);
118
+ border: 1px solid #ff9900;
119
+ border-radius: 15px;
120
+ padding: 15px;
121
+ }
122
+
123
+ .input-row {
124
+ display: flex;
125
+ gap: 10px;
126
+ align-items: center;
127
+ margin-bottom: 10px;
128
+ }
129
+
130
+ .lcars-input {
131
+ flex: 1;
132
+ background: rgba(0, 0, 0, 0.8);
133
+ border: 1px solid #ff9900;
134
+ border-radius: 10px;
135
+ padding: 12px;
136
+ color: #ff9900;
137
+ font-family: 'Orbitron', monospace;
138
+ font-size: 14px;
139
+ }
140
+
141
+ .lcars-input:focus {
142
+ outline: none;
143
+ border-color: #ffcc00;
144
+ box-shadow: 0 0 10px rgba(255, 204, 0, 0.3);
145
+ }
146
+
147
+ .lcars-button {
148
+ background: linear-gradient(45deg, #ff6600, #ff9900);
149
+ border: none;
150
+ border-radius: 20px;
151
+ padding: 12px 25px;
152
+ color: #000;
153
+ font-family: 'Orbitron', monospace;
154
+ font-weight: 700;
155
+ cursor: pointer;
156
+ transition: all 0.3s;
157
+ text-transform: uppercase;
158
+ }
159
+
160
+ .lcars-button:hover {
161
+ background: linear-gradient(45deg, #ff9900, #ffcc00);
162
+ transform: translateY(-2px);
163
+ box-shadow: 0 4px 15px rgba(255, 153, 0, 0.4);
164
+ }
165
+
166
+ .lcars-button:active {
167
+ transform: translateY(0);
168
+ }
169
+
170
+ .file-input {
171
+ display: none;
172
+ }
173
+
174
+ .file-label {
175
+ background: linear-gradient(45deg, #336699, #4488bb);
176
+ border-radius: 15px;
177
+ padding: 8px 15px;
178
+ color: #fff;
179
+ cursor: pointer;
180
+ font-size: 12px;
181
+ transition: all 0.3s;
182
+ }
183
+
184
+ .file-label:hover {
185
+ background: linear-gradient(45deg, #4488bb, #66aadd);
186
+ }
187
+
188
+ .controls-panel {
189
+ display: flex;
190
+ justify-content: space-between;
191
+ gap: 10px;
192
+ margin-top: 15px;
193
+ flex-wrap: wrap;
194
+ }
195
+
196
+ .control-group {
197
+ flex: 1;
198
+ min-width: 200px;
199
+ background: rgba(0, 0, 0, 0.6);
200
+ border: 1px solid #66aadd;
201
+ border-radius: 10px;
202
+ padding: 10px;
203
+ }
204
+
205
+ .control-group h3 {
206
+ color: #66aadd;
207
+ font-size: 14px;
208
+ margin-bottom: 10px;
209
+ text-align: center;
210
+ }
211
+
212
+ .settings-row {
213
+ display: flex;
214
+ align-items: center;
215
+ gap: 10px;
216
+ margin-bottom: 8px;
217
+ }
218
+
219
+ .settings-row label {
220
+ font-size: 12px;
221
+ color: #66aadd;
222
+ min-width: 80px;
223
+ }
224
+
225
+ .settings-input {
226
+ flex: 1;
227
+ background: rgba(0, 0, 0, 0.6);
228
+ border: 1px solid #66aadd;
229
+ border-radius: 5px;
230
+ padding: 5px 10px;
231
+ color: #66aadd;
232
+ font-family: 'Orbitron', monospace;
233
+ font-size: 12px;
234
+ }
235
+
236
+ .bottom-panel {
237
+ grid-area: bottom-panel;
238
+ background: rgba(0, 0, 0, 0.8);
239
+ border-top: 1px solid #ff9900;
240
+ display: flex;
241
+ justify-content: space-between;
242
+ align-items: center;
243
+ padding: 0 20px;
244
+ font-size: 12px;
245
+ }
246
+
247
+ .status-indicator {
248
+ display: flex;
249
+ align-items: center;
250
+ gap: 5px;
251
+ }
252
+
253
+ .status-dot {
254
+ width: 8px;
255
+ height: 8px;
256
+ border-radius: 50%;
257
+ background: #00ff66;
258
+ animation: pulse 2s infinite;
259
+ }
260
+
261
+ @keyframes pulse {
262
+ 0%, 100% { opacity: 1; }
263
+ 50% { opacity: 0.5; }
264
+ }
265
+
266
+ .session-info {
267
+ display: flex;
268
+ gap: 15px;
269
+ }
270
+
271
+ .session-info span {
272
+ color: #ffffff;
273
+ }
274
+
275
+ .thinking-content {
276
+ white-space: pre-wrap;
277
+ line-height: 1.4;
278
+ }
279
+
280
+ @media (max-width: 768px) {
281
+ .input-row {
282
+ flex-direction: column;
283
+ }
284
+
285
+ .controls-panel {
286
+ flex-direction: column;
287
+ }
288
+
289
+ .control-group {
290
+ min-width: 100%;
291
+ }
292
+
293
+ .status-indicator {
294
+ flex-direction: column;
295
+ align-items: flex-start;
296
+ }
297
+ }
298
+ </style>
299
+ </head>
300
+ <body>
301
+ <div class="lcars-container">
302
+ <div class="header">
303
+ <h1>L.C.A.R.S - Local Computer Advanced Reasoning System v3.0 </h1>
304
+ </div>
305
+
306
+ <div class="main-content">
307
+ <div class="chat-container">
308
+ <div class="message-area" id="messages">
309
+ <div class="message assistant-message">
310
+ <strong>SYSTEM:</strong> LCARS Multimodal Chat Agent initialized. Ready for communication.
311
+ </div>
312
+ </div>
313
+
314
+ <div class="input-section">
315
+ <div class="input-row">
316
+ <input type="text" class="lcars-input" id="user-input" placeholder="Enter your message..." />
317
+ <button class="lcars-button" onclick="sendMessage()">TRANSMIT</button>
318
+ </div>
319
+ <div class="input-row">
320
+ <input type="file" id="image-input" class="file-input" accept=".png,.jpg,.jpeg" onchange="handleFileSelect(this, 'image')" />
321
+ <label for="image-input" class="file-label">📷 IMAGE</label>
322
+
323
+ <input type="file" id="file-input" class="file-input" accept=".py,.txt,.md,.json,.csv" onchange="handleFileSelect(this, 'file')" />
324
+ <label for="file-input" class="file-label">📄 FILE</label>
325
+
326
+ <span id="file-status"></span>
327
+ </div>
328
+
329
+ <div class="controls-panel">
330
+ <div class="control-group">
331
+ <h3>SYSTEM CONFIGURATION</h3>
332
+ <div class="settings-row">
333
+ <label>API KEY:</label>
334
+ <input type="text" class="settings-input" id="api-key" value="not-needed" />
335
+ </div>
336
+ <div class="settings-row">
337
+ <label>BASE URL:</label>
338
+ <input type="text" class="settings-input" id="base-url" value="http://localhost:1234/v1" />
339
+ </div>
340
+ <div class="settings-row">
341
+ <label>MODEL:</label>
342
+ <input type="text" class="settings-input" id="model" value="leroydyer/qwen/qwen2-vl-2b-instruct-q4_k_m.gguf" />
343
+ </div>
344
+ </div>
345
+
346
+ <div class="control-group">
347
+ <h3>GENERATION PARAMETERS</h3>
348
+ <div class="settings-row">
349
+ <label>TEMP:</label>
350
+ <input type="range" class="settings-input" id="temperature" min="0" max="1" step="0.1" value="0.7" />
351
+ <span id="temp-display">0.7</span>
352
+ </div>
353
+ <div class="settings-row">
354
+ <label>TOP-P:</label>
355
+ <input type="range" class="settings-input" id="top_p" min="0" max="1" step="0.1" value="1.0" />
356
+ <span id="top_p-display">1.0</span>
357
+ </div>
358
+ <div class="settings-row">
359
+ <label>TOKENS:</label>
360
+ <input type="number" class="settings-input" id="max_tokens" value="512" />
361
+ </div>
362
+ </div>
363
+
364
+ <div class="control-group">
365
+ <h3>SESSION MANAGEMENT</h3>
366
+ <div class="input-row">
367
+ <button class="lcars-button" style="flex:1; padding:8px; font-size:12px;" onclick="saveSession()">SAVE SESSION</button>
368
+ <button class="lcars-button" style="flex:1; padding:8px; font-size:12px;" onclick="document.getElementById('load-session').click()">LOAD SESSION</button>
369
+ </div>
370
+ <div class="input-row" style="margin-top:5px;">
371
+ <button class="lcars-button" style="flex:1; padding:8px; font-size:12px;" onclick="createDataset()">CREATE DATASET</button>
372
+ <button class="lcars-button" style="flex:1; padding:8px; font-size:12px;" onclick="clearChat()">CLEAR CHAT</button>
373
+ </div>
374
+ </div>
375
+ </div>
376
+ </div>
377
+ </div>
378
+ </div>
379
+
380
+ <div class="bottom-panel">
381
+ <div class="status-indicator">
382
+ <div class="status-dot"></div>
383
+ <span id="system-status">SYSTEM ONLINE</span>
384
+ </div>
385
+ <div class="session-info">
386
+ <span>MESSAGES: <span id="message-count">0</span></span>
387
+ <span>STARDATE: <span id="stardate"></span></span>
388
+ <span>TEMP: <span id="temp-value">0.7</span></span>
389
+ </div>
390
+ </div>
391
+ </div>
392
+
393
+ <input type="file" id="load-session" class="file-input" accept=".json" onchange="loadSession(this)" />
394
+
395
+ <script>
396
+ // State management
397
+ let chatHistory = [];
398
+ let currentImage = null;
399
+ let currentFile = null;
400
+ let messageCount = 0;
401
+ let isProcessing = false;
402
+
403
+ // Initialize
404
+ document.addEventListener('DOMContentLoaded', function() {
405
+ updateStardate();
406
+ setInterval(updateStardate, 1000);
407
+
408
+ // Enter key support
409
+ document.getElementById('user-input').addEventListener('keypress', function(e) {
410
+ if (e.key === 'Enter' && !isProcessing) {
411
+ sendMessage();
412
+ }
413
+ });
414
+
415
+ // Slider updates
416
+ document.getElementById('temperature').addEventListener('input', function(e) {
417
+ document.getElementById('temp-display').textContent = e.target.value;
418
+ document.getElementById('temp-value').textContent = e.target.value;
419
+ });
420
+
421
+ document.getElementById('top_p').addEventListener('input', function(e) {
422
+ document.getElementById('top_p-display').textContent = e.target.value;
423
+ });
424
+ });
425
+
426
+ function updateStardate() {
427
+ const now = new Date();
428
+ const stardate = (now.getFullYear() - 2000) * 1000 +
429
+ (now.getMonth() + 1) * 30 +
430
+ now.getDate() +
431
+ (now.getHours() / 24);
432
+ document.getElementById('stardate').textContent = stardate.toFixed(1);
433
+ }
434
+
435
+ function addMessage(content, type, isThinking = false) {
436
+ const messagesArea = document.getElementById('messages');
437
+ const messageDiv = document.createElement('div');
438
+ messageDiv.className = `message ${type}-message ${isThinking ? 'thinking-message' : ''}`;
439
+
440
+ if (isThinking) {
441
+ messageDiv.innerHTML = `<strong>THINKING:</strong> <div class="thinking-content">${content}</div>`;
442
+ } else if (type === 'user') {
443
+ messageDiv.innerHTML = `<strong>USER:</strong> ${content}`;
444
+ } else {
445
+ messageDiv.innerHTML = `<strong>ASSISTANT:</strong> ${content}`;
446
+ }
447
+
448
+ messagesArea.appendChild(messageDiv);
449
+ messagesArea.scrollTop = messagesArea.scrollHeight;
450
+
451
+ if (!isThinking) {
452
+ messageCount++;
453
+ document.getElementById('message-count').textContent = messageCount;
454
+ }
455
+
456
+ return messageDiv;
457
+ }
458
+
459
+ async function sendMessage() {
460
+ const userInput = document.getElementById('user-input');
461
+ const message = userInput.value.trim();
462
+
463
+ if (!message && !currentImage && !currentFile) return;
464
+ if (isProcessing) return;
465
+
466
+ isProcessing = true;
467
+ document.getElementById('system-status').textContent = 'PROCESSING REQUEST';
468
+
469
+ // Add user message
470
+ let displayMessage = message;
471
+ if (currentImage) displayMessage += ' [IMAGE ATTACHED]';
472
+ if (currentFile) displayMessage += ' [FILE ATTACHED]';
473
+
474
+ addMessage(displayMessage, 'user');
475
+ userInput.value = '';
476
+
477
+ // Show thinking
478
+ const thinkingDiv = addMessage('Connecting to API and analyzing input...', 'assistant', true);
479
+
480
+ try {
481
+ // Connect to the API
482
+ const response = await callAPI(message, currentImage, currentFile);
483
+
484
+ // Remove thinking message
485
+ if (thinkingDiv && thinkingDiv.parentNode) {
486
+ thinkingDiv.parentNode.removeChild(thinkingDiv);
487
+ }
488
+
489
+ // Add response
490
+ addMessage(response.answer, 'assistant');
491
+
492
+ // Update chat history
493
+ chatHistory.push({
494
+ role: 'user',
495
+ content: message,
496
+ image: currentImage ? 'attached' : null,
497
+ file: currentFile ? 'attached' : null
498
+ });
499
+ chatHistory.push({
500
+ role: 'assistant',
501
+ content: response.answer,
502
+ thinking: response.thinking
503
+ });
504
+
505
+ // Clear attachments
506
+ currentImage = null;
507
+ currentFile = null;
508
+ document.getElementById('file-status').textContent = '';
509
+
510
+ } catch (error) {
511
+ // Remove thinking message
512
+ if (thinkingDiv && thinkingDiv.parentNode) {
513
+ thinkingDiv.parentNode.removeChild(thinkingDiv);
514
+ }
515
+
516
+ addMessage(`ERROR: ${error.message}`, 'assistant');
517
+ } finally {
518
+ isProcessing = false;
519
+ document.getElementById('system-status').textContent = 'SYSTEM ONLINE';
520
+ }
521
+ }
522
+
523
+ async function callAPI(message, image = null, fileContent = null) {
524
+ const apiKey = document.getElementById('api-key').value;
525
+ const baseUrl = document.getElementById('base-url').value;
526
+ const model = document.getElementById('model').value;
527
+ const temperature = parseFloat(document.getElementById('temperature').value);
528
+ const top_p = parseFloat(document.getElementById('top_p').value);
529
+ const max_tokens = parseInt(document.getElementById('max_tokens').value);
530
+
531
+ // Prepare the content for the API
532
+ let content = [{ type: "text", text: message }];
533
+
534
+ if (image) {
535
+ content.push({
536
+ type: "image_url",
537
+ image_url: { url: `data:image/png;base64,${image}` }
538
+ });
539
+ }
540
+
541
+ if (fileContent) {
542
+ content.push({
543
+ type: "text",
544
+ text: `File content:\n${fileContent}`
545
+ });
546
+ }
547
+
548
+ // Prepare the messages history
549
+ const messages = [...chatHistory, { role: "user", content: content }];
550
+
551
+ try {
552
+ const response = await fetch(`${baseUrl}/chat/completions`, {
553
+ method: 'POST',
554
+ headers: {
555
+ 'Content-Type': 'application/json',
556
+ 'Authorization': `Bearer ${apiKey}`
557
+ },
558
+ body: JSON.stringify({
559
+ model: model,
560
+ messages: messages,
561
+ temperature: temperature,
562
+ top_p: top_p,
563
+ max_tokens: max_tokens
564
+ })
565
+ });
566
+
567
+ if (!response.ok) {
568
+ throw new Error(`API error: ${response.status} ${response.statusText}`);
569
+ }
570
+
571
+ const data = await response.json();
572
+ const assistantMessage = data.choices[0].message.content;
573
+
574
+ // Parse thinking, answer, and artifacts
575
+ const result = parseResponse(assistantMessage);
576
+ return result;
577
+
578
+ } catch (error) {
579
+ console.error('API call failed:', error);
580
+ throw error;
581
+ }
582
+ }
583
+
584
+ function parseResponse(text) {
585
+ let thinking = "";
586
+ let answer = text;
587
+ let artifacts = [];
588
+
589
+ // Extract code blocks
590
+ if (text.includes("```")) {
591
+ const parts = text.split("```");
592
+ for (let i = 1; i < parts.length; i += 2) {
593
+ let code = parts[i].trim();
594
+ if (code.startsWith("python")) {
595
+ code = code.substring(6).trim();
596
+ }
597
+ artifacts.push(code);
598
+ }
599
+ answer = parts.filter((_, i) => i % 2 === 0).join("");
600
+ }
601
+
602
+ // Extract thinking if present
603
+ if (text.includes("<thinking>") && text.includes("</thinking>")) {
604
+ thinking = text.split("<thinking>")[1].split("</thinking>")[0].trim();
605
+ }
606
+
607
+ return {
608
+ thinking: thinking,
609
+ answer: answer.trim(),
610
+ artifacts: artifacts
611
+ };
612
+ }
613
+
614
+ function handleFileSelect(input, type) {
615
+ const file = input.files[0];
616
+ if (file) {
617
+ const reader = new FileReader();
618
+ reader.onload = function(e) {
619
+ if (type === 'image') {
620
+ currentImage = e.target.result.split(',')[1]; // Remove data URL prefix
621
+ document.getElementById('file-status').innerHTML = '📷 Image loaded';
622
+ } else {
623
+ currentFile = e.target.result;
624
+ document.getElementById('file-status').innerHTML = '📄 File loaded';
625
+ }
626
+ };
627
+
628
+ if (type === 'image') {
629
+ reader.readAsDataURL(file);
630
+ } else {
631
+ reader.readAsText(file);
632
+ }
633
+ }
634
+ }
635
+
636
+ function saveSession() {
637
+ const sessionData = {
638
+ timestamp: new Date().toISOString(),
639
+ chatHistory: chatHistory,
640
+ settings: {
641
+ apiKey: document.getElementById('api-key').value,
642
+ baseUrl: document.getElementById('base-url').value,
643
+ model: document.getElementById('model').value,
644
+ temperature: document.getElementById('temperature').value,
645
+ top_p: document.getElementById('top_p').value,
646
+ max_tokens: document.getElementById('max_tokens').value
647
+ }
648
+ };
649
+
650
+ const blob = new Blob([JSON.stringify(sessionData, null, 2)], { type: 'application/json' });
651
+ const url = URL.createObjectURL(blob);
652
+ const a = document.createElement('a');
653
+ a.href = url;
654
+ a.download = `lcars_session_${new Date().toISOString().split('T')[0]}.json`;
655
+ document.body.appendChild(a);
656
+ a.click();
657
+ document.body.removeChild(a);
658
+ URL.revokeObjectURL(url);
659
+
660
+ addMessage('Session saved successfully.', 'assistant');
661
+ }
662
+
663
+ function loadSession(input) {
664
+ const file = input.files[0];
665
+ if (file) {
666
+ const reader = new FileReader();
667
+ reader.onload = function(e) {
668
+ try {
669
+ const sessionData = JSON.parse(e.target.result);
670
+ chatHistory = sessionData.chatHistory || [];
671
+
672
+ // Clear current messages
673
+ document.getElementById('messages').innerHTML = '';
674
+ messageCount = 0;
675
+ document.getElementById('message-count').textContent = '0';
676
+
677
+ // Load messages
678
+ chatHistory.forEach(msg => {
679
+ if (msg.role === 'user') {
680
+ addMessage(msg.content, 'user');
681
+ } else if (msg.role === 'assistant') {
682
+ addMessage(msg.content, 'assistant');
683
+ }
684
+ });
685
+
686
+ // Load settings if available
687
+ if (sessionData.settings) {
688
+ document.getElementById('api-key').value = sessionData.settings.apiKey || 'not-needed';
689
+ document.getElementById('base-url').value = sessionData.settings.baseUrl || 'http://localhost:1234/v1';
690
+ document.getElementById('model').value = sessionData.settings.model || 'gpt-4o-mini';
691
+ document.getElementById('temperature').value = sessionData.settings.temperature || 0.7;
692
+ document.getElementById('temp-display').textContent = sessionData.settings.temperature || 0.7;
693
+ document.getElementById('temp-value').textContent = sessionData.settings.temperature || 0.7;
694
+ document.getElementById('top_p').value = sessionData.settings.top_p || 1.0;
695
+ document.getElementById('top_p-display').textContent = sessionData.settings.top_p || 1.0;
696
+ document.getElementById('max_tokens').value = sessionData.settings.max_tokens || 512;
697
+ }
698
+
699
+ addMessage('Session loaded successfully.', 'assistant');
700
+ } catch (error) {
701
+ addMessage(`Error loading session: ${error.message}`, 'assistant');
702
+ }
703
+ };
704
+ reader.readAsText(file);
705
+ }
706
+ }
707
+
708
+ function createDataset() {
709
+ if (chatHistory.length === 0) {
710
+ addMessage('No chat history to create dataset from.', 'assistant');
711
+ return;
712
+ }
713
+
714
+ // Group conversations (every user message and following assistant response)
715
+ const conversations = [];
716
+ let currentConversation = [];
717
+
718
+ for (let i = 0; i < chatHistory.length; i++) {
719
+ currentConversation.push(chatHistory[i]);
720
+
721
+ // When we have an assistant response, save the conversation
722
+ if (chatHistory[i].role === 'assistant') {
723
+ if (currentConversation.length > 0) {
724
+ conversations.push(currentConversation);
725
+ currentConversation = [];
726
+ }
727
+ }
728
+ }
729
+
730
+ // Add any remaining messages
731
+ if (currentConversation.length > 0) {
732
+ conversations.push(currentConversation);
733
+ }
734
+
735
+ const dataset = {
736
+ created: new Date().toISOString(),
737
+ conversations: conversations,
738
+ count: conversations.length
739
+ };
740
+
741
+ const blob = new Blob([JSON.stringify(dataset, null, 2)], { type: 'application/json' });
742
+ const url = URL.createObjectURL(blob);
743
+ const a = document.createElement('a');
744
+ a.href = url;
745
+ a.download = `lcars_dataset_${new Date().toISOString().split('T')[0]}.json`;
746
+ document.body.appendChild(a);
747
+ a.click();
748
+ document.body.removeChild(a);
749
+ URL.revokeObjectURL(url);
750
+
751
+ addMessage(`Dataset created with ${conversations.length} conversations and downloaded successfully.`, 'assistant');
752
+ }
753
+
754
+ function clearChat() {
755
+ if (confirm('Are you sure you want to clear the chat history?')) {
756
+ document.getElementById('messages').innerHTML = '';
757
+ chatHistory = [];
758
+ messageCount = 0;
759
+ document.getElementById('message-count').textContent = '0';
760
+ addMessage('Chat cleared.', 'assistant');
761
+ }
762
+ }
763
+ </script>
764
+ </body>
765
+ </html>
Padd_3.html ADDED
@@ -0,0 +1,726 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LCARS Multimodal Chat Agent</title>
7
+ <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
9
+
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ body {
17
+ font-family: 'Orbitron', monospace;
18
+ background: linear-gradient(135deg, #000 0%, #111 50%, #000 100%);
19
+ color: #ff9900;
20
+ min-height: 100vh;
21
+ overflow-x: hidden;
22
+ }
23
+
24
+ .lcars-container {
25
+ display: grid;
26
+ grid-template-areas:
27
+ "header header"
28
+ "main-content sidebar"
29
+ "status status";
30
+ grid-template-rows: 80px 1fr 40px;
31
+ grid-template-columns: 1fr 250px;
32
+ height: 100vh;
33
+ gap: 8px;
34
+ padding: 8px;
35
+ }
36
+
37
+ .lcars-panel {
38
+ background: linear-gradient(45deg, #336699, #4488bb);
39
+ border-radius: 20px;
40
+ position: relative;
41
+ overflow: hidden;
42
+ }
43
+
44
+ .lcars-panel::before {
45
+ content: '';
46
+ position: absolute;
47
+ top: 0;
48
+ left: 0;
49
+ right: 0;
50
+ bottom: 0;
51
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
52
+ animation: shimmer 3s infinite;
53
+ }
54
+
55
+ @keyframes shimmer {
56
+ 0% { transform: translateX(-100%); }
57
+ 100% { transform: translateX(100%); }
58
+ }
59
+
60
+ .header {
61
+ grid-area: header;
62
+ background: linear-gradient(90deg, #ff6600, #ff9900);
63
+ display: flex;
64
+ align-items: center;
65
+ padding: 0 30px;
66
+ border-radius: 0 0 40px 40px;
67
+ }
68
+
69
+ .header h1 {
70
+ color: #000;
71
+ font-weight: 900;
72
+ font-size: 1.8rem;
73
+ text-shadow: 2px 2px 4px rgba(255,255,255,0.3);
74
+ }
75
+
76
+ .main-content {
77
+ grid-area: main-content;
78
+ background: rgba(0, 0, 0, 0.8);
79
+ border: 2px solid #ff9900;
80
+ border-radius: 20px;
81
+ padding: 20px;
82
+ display: flex;
83
+ flex-direction: column;
84
+ gap: 15px;
85
+ position: relative;
86
+ }
87
+
88
+ .sidebar {
89
+ grid-area: sidebar;
90
+ background: linear-gradient(180deg, #6633cc, #9933ff);
91
+ border-radius: 20px;
92
+ padding: 20px;
93
+ display: flex;
94
+ flex-direction: column;
95
+ gap: 15px;
96
+ }
97
+
98
+ .chat-container {
99
+ flex: 1;
100
+ display: flex;
101
+ flex-direction: column;
102
+ gap: 15px;
103
+ }
104
+
105
+ .message-area {
106
+ flex: 1;
107
+ background: rgba(0, 20, 40, 0.9);
108
+ border: 1px solid #336699;
109
+ border-radius: 15px;
110
+ padding: 15px;
111
+ overflow-y: auto;
112
+ min-height: 300px;
113
+ }
114
+
115
+ .message {
116
+ margin-bottom: 15px;
117
+ padding: 10px;
118
+ border-radius: 10px;
119
+ animation: slideIn 0.3s ease-out;
120
+ }
121
+
122
+ @keyframes slideIn {
123
+ from { opacity: 0; transform: translateY(20px); }
124
+ to { opacity: 1; transform: translateY(0); }
125
+ }
126
+
127
+ .user-message {
128
+ background: linear-gradient(135deg, #ff6600, #ff9900);
129
+ color: #000;
130
+ margin-left: 50px;
131
+ border-radius: 15px 15px 5px 15px;
132
+ }
133
+
134
+ .assistant-message {
135
+ background: linear-gradient(135deg, #336699, #4488bb);
136
+ color: #fff;
137
+ margin-right: 50px;
138
+ border-radius: 15px 15px 15px 5px;
139
+ }
140
+
141
+ .thinking-message {
142
+ background: linear-gradient(135deg, #cc3366, #ff3366);
143
+ color: #fff;
144
+ margin-right: 100px;
145
+ border-radius: 10px;
146
+ font-style: italic;
147
+ font-size: 0.9em;
148
+ }
149
+
150
+ .input-section {
151
+ background: rgba(0, 30, 60, 0.9);
152
+ border: 1px solid #ff9900;
153
+ border-radius: 15px;
154
+ padding: 15px;
155
+ }
156
+
157
+ .input-row {
158
+ display: flex;
159
+ gap: 10px;
160
+ align-items: center;
161
+ margin-bottom: 10px;
162
+ }
163
+
164
+ .lcars-input {
165
+ flex: 1;
166
+ background: rgba(0, 0, 0, 0.8);
167
+ border: 1px solid #ff9900;
168
+ border-radius: 10px;
169
+ padding: 12px;
170
+ color: #ff9900;
171
+ font-family: 'Orbitron', monospace;
172
+ font-size: 14px;
173
+ }
174
+
175
+ .lcars-input:focus {
176
+ outline: none;
177
+ border-color: #ffcc00;
178
+ box-shadow: 0 0 10px rgba(255, 204, 0, 0.3);
179
+ }
180
+
181
+ .lcars-button {
182
+ background: linear-gradient(45deg, #ff6600, #ff9900);
183
+ border: none;
184
+ border-radius: 20px;
185
+ padding: 12px 25px;
186
+ color: #000;
187
+ font-family: 'Orbitron', monospace;
188
+ font-weight: 700;
189
+ cursor: pointer;
190
+ transition: all 0.3s;
191
+ text-transform: uppercase;
192
+ }
193
+
194
+ .lcars-button:hover {
195
+ background: linear-gradient(45deg, #ff9900, #ffcc00);
196
+ transform: translateY(-2px);
197
+ box-shadow: 0 4px 15px rgba(255, 153, 0, 0.4);
198
+ }
199
+
200
+ .lcars-button:active {
201
+ transform: translateY(0);
202
+ }
203
+
204
+ .file-input {
205
+ display: none;
206
+ }
207
+
208
+ .file-label {
209
+ background: linear-gradient(45deg, #336699, #4488bb);
210
+ border-radius: 15px;
211
+ padding: 8px 15px;
212
+ color: #fff;
213
+ cursor: pointer;
214
+ font-size: 12px;
215
+ transition: all 0.3s;
216
+ }
217
+
218
+ .file-label:hover {
219
+ background: linear-gradient(45deg, #4488bb, #66aadd);
220
+ }
221
+
222
+ .settings-grid {
223
+ display: flex;
224
+ flex-direction: column;
225
+ gap: 10px;
226
+ margin-top: 15px;
227
+ }
228
+
229
+ .settings-row {
230
+ display: flex;
231
+ align-items: center;
232
+ gap: 10px;
233
+ }
234
+
235
+ .settings-row label {
236
+ font-size: 12px;
237
+ color: #66aadd;
238
+ min-width: 80px;
239
+ }
240
+
241
+ .settings-input {
242
+ background: rgba(0, 0, 0, 0.6);
243
+ border: 1px solid #66aadd;
244
+ border-radius: 5px;
245
+ padding: 5px 10px;
246
+ color: #66aadd;
247
+ font-family: 'Orbitron', monospace;
248
+ font-size: 12px;
249
+ flex: 1;
250
+ }
251
+
252
+ .status-bar {
253
+ grid-area: status;
254
+ display: flex;
255
+ justify-content: space-between;
256
+ align-items: center;
257
+ padding: 0 20px;
258
+ background: rgba(0, 0, 0, 0.8);
259
+ border: 1px solid #ff9900;
260
+ border-radius: 20px;
261
+ height: 40px;
262
+ font-size: 12px;
263
+ }
264
+
265
+ .status-indicator {
266
+ display: flex;
267
+ align-items: center;
268
+ gap: 5px;
269
+ }
270
+
271
+ .status-dot {
272
+ width: 8px;
273
+ height: 8px;
274
+ border-radius: 50%;
275
+ background: #00ff66;
276
+ animation: pulse 2s infinite;
277
+ }
278
+
279
+ @keyframes pulse {
280
+ 0%, 100% { opacity: 1; }
281
+ 50% { opacity: 0.5; }
282
+ }
283
+
284
+ .side-controls {
285
+ color: #fff;
286
+ font-size: 12px;
287
+ }
288
+
289
+ .side-button {
290
+ width: 100%;
291
+ background: rgba(255, 255, 255, 0.1);
292
+ border: 1px solid rgba(255, 255, 255, 0.3);
293
+ border-radius: 10px;
294
+ padding: 10px;
295
+ color: #fff;
296
+ font-family: 'Orbitron', monospace;
297
+ font-size: 11px;
298
+ cursor: pointer;
299
+ margin-bottom: 10px;
300
+ transition: all 0.3s;
301
+ }
302
+
303
+ .side-button:hover {
304
+ background: rgba(255, 255, 255, 0.2);
305
+ transform: scale(1.05);
306
+ }
307
+
308
+ .session-info {
309
+ font-size: 10px;
310
+ color: rgba(255, 255, 255, 0.7);
311
+ margin-top: 10px;
312
+ }
313
+
314
+ .section-title {
315
+ color: #ffcc00;
316
+ font-size: 14px;
317
+ margin-bottom: 10px;
318
+ text-align: center;
319
+ }
320
+
321
+ .control-group {
322
+ margin-bottom: 15px;
323
+ }
324
+
325
+ .control-group label {
326
+ display: block;
327
+ margin-bottom: 5px;
328
+ font-size: 11px;
329
+ color: #66aadd;
330
+ }
331
+
332
+ .slider-container {
333
+ display: flex;
334
+ align-items: center;
335
+ gap: 10px;
336
+ }
337
+
338
+ .slider-value {
339
+ min-width: 30px;
340
+ text-align: center;
341
+ font-size: 12px;
342
+ }
343
+
344
+ @media (max-width: 900px) {
345
+ .lcars-container {
346
+ grid-template-areas:
347
+ "header"
348
+ "main-content"
349
+ "status";
350
+ grid-template-columns: 1fr;
351
+ grid-template-rows: 80px 1fr 40px;
352
+ }
353
+ .sidebar {
354
+ display: none;
355
+ }
356
+ }
357
+ </style>
358
+ </head>
359
+ <body>
360
+ <div class="lcars-container">
361
+ <div class="header">
362
+ <h1>🧠 MULTIMODAL CHAT AGENT - LCARS INTERFACE</h1>
363
+ </div>
364
+
365
+ <div class="main-content">
366
+ <div class="chat-container">
367
+ <div class="message-area" id="messages">
368
+ <div class="message assistant-message">
369
+ <strong>SYSTEM:</strong> LCARS Multimodal Chat Agent initialized. Ready for communication.
370
+ </div>
371
+ </div>
372
+
373
+ <div class="input-section">
374
+ <div class="input-row">
375
+ <input type="text" class="lcars-input" id="user-input" placeholder="Enter your message..." />
376
+ <button class="lcars-button" onclick="sendMessage()">TRANSMIT</button>
377
+ </div>
378
+ <div class="input-row">
379
+ <input type="file" id="image-input" class="file-input" accept=".png,.jpg,.jpeg" onchange="handleFileSelect(this, 'image')" />
380
+ <label for="image-input" class="file-label">📷 IMAGE</label>
381
+
382
+ <input type="file" id="file-input" class="file-input" accept=".py,.txt,.md,.json,.csv" onchange="handleFileSelect(this, 'file')" />
383
+ <label for="file-input" class="file-label">📄 FILE</label>
384
+
385
+ <span id="file-status"></span>
386
+ </div>
387
+ </div>
388
+ </div>
389
+ </div>
390
+
391
+ <div class="sidebar lcars-panel">
392
+ <div class="side-controls">
393
+ <div class="section-title">⚙️ SYSTEM CONTROLS</div>
394
+
395
+ <div class="control-group">
396
+ <button class="side-button" onclick="saveSession()">💾 SAVE SESSION</button>
397
+ <button class="side-button" onclick="document.getElementById('load-session').click()">📂 LOAD SESSION</button>
398
+ <button class="side-button" onclick="createDataset()">📊 CREATE DATASET</button>
399
+ <button class="side-button" onclick="clearChat()">🧹 CLEAR CHAT</button>
400
+ </div>
401
+
402
+ <div class="section-title">🎛️ API SETTINGS</div>
403
+
404
+ <div class="control-group">
405
+ <label>API KEY</label>
406
+ <input type="text" class="settings-input" id="api-key" value="not-needed" />
407
+ </div>
408
+
409
+ <div class="control-group">
410
+ <label>BASE URL</label>
411
+ <input type="text" class="settings-input" id="base-url" value="http://localhost:1234/v1" />
412
+ </div>
413
+
414
+ <div class="control-group">
415
+ <label>MODEL</label>
416
+ <input type="text" class="settings-input" id="model" value="leroydyer/qwen/qwen2-vl-2b-instruct-q4_k_m.gguf" />
417
+ </div>
418
+
419
+ <div class="control-group">
420
+ <label>TEMPERATURE</label>
421
+ <div class="slider-container">
422
+ <input type="range" class="settings-input" id="temperature" min="0" max="1" step="0.1" value="0.7" />
423
+ <span class="slider-value" id="temp-display">0.7</span>
424
+ </div>
425
+ </div>
426
+
427
+ <div class="control-group">
428
+ <label>MAX TOKENS</label>
429
+ <input type="number" class="settings-input" id="max-tokens" value="512" min="1" max="4096" />
430
+ </div>
431
+
432
+ <div class="session-info">
433
+ <div>MESSAGES: <span id="message-count">0</span></div>
434
+ <div>STATUS: <span id="connection-status">READY</span></div>
435
+ </div>
436
+ </div>
437
+ </div>
438
+
439
+ <div class="status-bar">
440
+ <div class="status-indicator">
441
+ <div class="status-dot"></div>
442
+ <span>SYSTEM ONLINE</span>
443
+ </div>
444
+ <div>STARDATE: <span id="stardate"></span></div>
445
+ </div>
446
+ </div>
447
+
448
+ <input type="file" id="load-session" class="file-input" accept=".json" onchange="loadSession(this)" />
449
+
450
+ <script>
451
+ // State management
452
+ let chatHistory = [];
453
+ let currentImage = null;
454
+ let currentFile = null;
455
+ let messageCount = 0;
456
+
457
+ // Initialize
458
+ document.addEventListener('DOMContentLoaded', function() {
459
+ updateStardate();
460
+ setInterval(updateStardate, 1000);
461
+
462
+ // Enter key support
463
+ document.getElementById('user-input').addEventListener('keypress', function(e) {
464
+ if (e.key === 'Enter') {
465
+ sendMessage();
466
+ }
467
+ });
468
+
469
+ // Temperature slider update
470
+ document.getElementById('temperature').addEventListener('input', function(e) {
471
+ document.getElementById('temp-display').textContent = e.target.value;
472
+ });
473
+ });
474
+
475
+ function updateStardate() {
476
+ const now = new Date();
477
+ const stardate = (now.getFullYear() - 2000) * 1000 +
478
+ (now.getMonth() + 1) * 30 +
479
+ now.getDate() +
480
+ (now.getHours() / 24);
481
+ document.getElementById('stardate').textContent = stardate.toFixed(1);
482
+ }
483
+
484
+ function addMessage(content, type, isThinking = false) {
485
+ const messagesArea = document.getElementById('messages');
486
+ const messageDiv = document.createElement('div');
487
+ messageDiv.className = `message ${type}-message ${isThinking ? 'thinking-message' : ''}`;
488
+
489
+ if (isThinking) {
490
+ messageDiv.innerHTML = `<strong>PROCESSING:</strong> ${content}`;
491
+ } else if (type === 'user') {
492
+ messageDiv.innerHTML = `<strong>USER:</strong> ${content}`;
493
+ } else {
494
+ messageDiv.innerHTML = `<strong>ASSISTANT:</strong> ${content}`;
495
+ }
496
+
497
+ messagesArea.appendChild(messageDiv);
498
+ messagesArea.scrollTop = messagesArea.scrollHeight;
499
+
500
+ if (!isThinking) {
501
+ messageCount++;
502
+ document.getElementById('message-count').textContent = messageCount;
503
+ }
504
+ }
505
+
506
+ async function sendMessage() {
507
+ const userInput = document.getElementById('user-input');
508
+ const message = userInput.value.trim();
509
+
510
+ if (!message && !currentImage && !currentFile) return;
511
+
512
+ // Add user message
513
+ let displayMessage = message;
514
+ if (currentImage) displayMessage += ' [IMAGE ATTACHED]';
515
+ if (currentFile) displayMessage += ' [FILE ATTACHED]';
516
+
517
+ addMessage(displayMessage, 'user');
518
+ userInput.value = '';
519
+
520
+ // Show thinking
521
+ const thinkingMsg = addMessage('Analyzing input and generating response...', 'assistant', true);
522
+
523
+ try {
524
+ // Get API settings
525
+ const apiKey = document.getElementById('api-key').value;
526
+ const baseUrl = document.getElementById('base-url').value;
527
+ const model = document.getElementById('model').value;
528
+ const temperature = parseFloat(document.getElementById('temperature').value);
529
+ const maxTokens = parseInt(document.getElementById('max-tokens').value);
530
+
531
+ // Prepare content
532
+ const content = [{"type": "text", "text": message}];
533
+ if (currentImage) {
534
+ content.push({"type": "image_url", "image_url": {"url": `data:image/png;base64,${currentImage}`}});
535
+ }
536
+ if (currentFile) {
537
+ content.push({"type": "text", "text": currentFile});
538
+ }
539
+
540
+ // Update chat history
541
+ chatHistory.push({"role": "user", "content": content});
542
+
543
+ // Call API
544
+ const response = await fetch(`${baseUrl}/chat/completions`, {
545
+ method: 'POST',
546
+ headers: {
547
+ 'Content-Type': 'application/json',
548
+ 'Authorization': `Bearer ${apiKey}`
549
+ },
550
+ body: JSON.stringify({
551
+ model: model,
552
+ messages: chatHistory,
553
+ temperature: temperature,
554
+ max_tokens: maxTokens
555
+ })
556
+ });
557
+
558
+ if (!response.ok) {
559
+ throw new Error(`API Error: ${response.status} ${response.statusText}`);
560
+ }
561
+
562
+ const data = await response.json();
563
+ const assistantMessage = data.choices[0].message.content;
564
+
565
+ // Remove thinking message
566
+ const messages = document.querySelectorAll('.thinking-message');
567
+ if (messages.length > 0) {
568
+ messages[messages.length - 1].remove();
569
+ }
570
+
571
+ // Add response
572
+ addMessage(assistantMessage, 'assistant');
573
+
574
+ // Update chat history
575
+ chatHistory.push({"role": "assistant", "content": assistantMessage});
576
+
577
+ // Clear attachments
578
+ currentImage = null;
579
+ currentFile = null;
580
+ document.getElementById('file-status').textContent = '';
581
+
582
+ } catch (error) {
583
+ // Remove thinking message
584
+ const messages = document.querySelectorAll('.thinking-message');
585
+ if (messages.length > 0) {
586
+ messages[messages.length - 1].remove();
587
+ }
588
+
589
+ addMessage(`ERROR: ${error.message}`, 'assistant');
590
+ document.getElementById('connection-status').textContent = 'ERROR';
591
+ setTimeout(() => {
592
+ document.getElementById('connection-status').textContent = 'READY';
593
+ }, 3000);
594
+ }
595
+ }
596
+
597
+ function handleFileSelect(input, type) {
598
+ const file = input.files[0];
599
+ if (file) {
600
+ const reader = new FileReader();
601
+ reader.onload = function(e) {
602
+ if (type === 'image') {
603
+ currentImage = e.target.result.split(',')[1]; // Remove data URL prefix
604
+ document.getElementById('file-status').innerHTML = '📷 Image loaded';
605
+ } else {
606
+ currentFile = e.target.result;
607
+ document.getElementById('file-status').innerHTML = '📄 File loaded';
608
+ }
609
+ };
610
+
611
+ if (type === 'image') {
612
+ reader.readAsDataURL(file);
613
+ } else {
614
+ reader.readAsText(file);
615
+ }
616
+ }
617
+ }
618
+
619
+ function saveSession() {
620
+ const sessionData = {
621
+ timestamp: new Date().toISOString(),
622
+ chatHistory: chatHistory,
623
+ settings: {
624
+ apiKey: document.getElementById('api-key').value,
625
+ baseUrl: document.getElementById('base-url').value,
626
+ model: document.getElementById('model').value,
627
+ temperature: document.getElementById('temperature').value,
628
+ maxTokens: document.getElementById('max-tokens').value
629
+ }
630
+ };
631
+
632
+ const blob = new Blob([JSON.stringify(sessionData, null, 2)], { type: 'application/json' });
633
+ const url = URL.createObjectURL(blob);
634
+ const a = document.createElement('a');
635
+ a.href = url;
636
+ a.download = `lcars_session_${new Date().toISOString().split('T')[0]}.json`;
637
+ document.body.appendChild(a);
638
+ a.click();
639
+ document.body.removeChild(a);
640
+ URL.revokeObjectURL(url);
641
+
642
+ addMessage('Session saved successfully.', 'assistant');
643
+ }
644
+
645
+ function loadSession(input) {
646
+ const file = input.files[0];
647
+ if (file) {
648
+ const reader = new FileReader();
649
+ reader.onload = function(e) {
650
+ try {
651
+ const sessionData = JSON.parse(e.target.result);
652
+ chatHistory = sessionData.chatHistory || [];
653
+
654
+ // Clear current messages
655
+ document.getElementById('messages').innerHTML = '';
656
+ messageCount = 0;
657
+ document.getElementById('message-count').textContent = '0';
658
+
659
+ // Load messages
660
+ chatHistory.forEach(msg => {
661
+ if (msg.role === 'user') {
662
+ // Handle content array
663
+ let content = '';
664
+ if (Array.isArray(msg.content)) {
665
+ content = msg.content.map(item =>
666
+ item.type === 'text' ? item.text :
667
+ item.type === 'image_url' ? '[IMAGE]' : ''
668
+ ).join(' ');
669
+ } else {
670
+ content = msg.content;
671
+ }
672
+ addMessage(content, 'user');
673
+ } else if (msg.role === 'assistant') {
674
+ addMessage(msg.content, 'assistant');
675
+ }
676
+ });
677
+
678
+ // Load settings if available
679
+ if (sessionData.settings) {
680
+ document.getElementById('api-key').value = sessionData.settings.apiKey || 'not-needed';
681
+ document.getElementById('base-url').value = sessionData.settings.baseUrl || 'http://localhost:1234/v1';
682
+ document.getElementById('model').value = sessionData.settings.model || 'leroydyer/qwen/qwen2-vl-2b-instruct-q4_k_m.gguf';
683
+ document.getElementById('temperature').value = sessionData.settings.temperature || 0.7;
684
+ document.getElementById('temp-display').textContent = sessionData.settings.temperature || 0.7;
685
+ document.getElementById('max-tokens').value = sessionData.settings.maxTokens || 512;
686
+ }
687
+
688
+ addMessage('Session loaded successfully.', 'assistant');
689
+ } catch (error) {
690
+ addMessage(`Error loading session: ${error.message}`, 'assistant');
691
+ }
692
+ };
693
+ reader.readAsText(file);
694
+ }
695
+ }
696
+
697
+ function createDataset() {
698
+ if (chatHistory.length === 0) {
699
+ addMessage('No chat history to create dataset from.', 'assistant');
700
+ return;
701
+ }
702
+
703
+ const dataset = [chatHistory];
704
+ const blob = new Blob([JSON.stringify(dataset, null, 2)], { type: 'application/json' });
705
+ const url = URL.createObjectURL(blob);
706
+ const a = document.createElement('a');
707
+ a.href = url;
708
+ a.download = `lcars_dataset_${new Date().toISOString().split('T')[0]}.json`;
709
+ document.body.appendChild(a);
710
+ a.click();
711
+ document.body.removeChild(a);
712
+ URL.revokeObjectURL(url);
713
+
714
+ addMessage('Dataset created and downloaded successfully.', 'assistant');
715
+ }
716
+
717
+ function clearChat() {
718
+ document.getElementById('messages').innerHTML = '';
719
+ chatHistory = [];
720
+ messageCount = 0;
721
+ document.getElementById('message-count').textContent = '0';
722
+ addMessage('Chat cleared.', 'assistant');
723
+ }
724
+ </script>
725
+ </body>
726
+ </html>