ldostadi commited on
Commit
2acd798
·
verified ·
1 Parent(s): f18b0c7

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +1134 -72
index.html CHANGED
@@ -1,105 +1,1167 @@
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>RAG Axiom Extractor - Logical Document Generation</title>
7
- <link rel="stylesheet" href="style.css">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  </head>
9
  <body>
10
- <header>
11
- <h1>🔍 RAG Axiom Extractor & Generator</h1>
12
- <p>Extract axioms from documents and generate logically consistent responses</p>
13
- <div class="attribution">
14
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">Built with anycoder</a>
 
 
 
 
 
 
 
 
 
 
 
15
  </div>
16
  </header>
17
 
18
- <main>
19
- <section class="model-status">
20
- <h2>Model Status</h2>
21
- <div id="statusContainer">
22
- <div class="status-item">
23
- <span>Embedding Model:</span>
24
- <span id="embeddingStatus" class="status pending">⏳ Loading...</span>
 
 
 
 
 
 
 
 
 
 
 
25
  </div>
26
- <div class="status-item">
27
- <span>Generation Model:</span>
28
- <span id="generationStatus" class="status pending">⏳ Loading...</span>
 
 
 
 
 
 
29
  </div>
30
  </div>
31
- <div id="progressContainer" class="progress-container hidden">
32
- <div id="progressBar" class="progress-bar"></div>
33
- <span id="progressText">0%</span>
34
- </div>
35
  </section>
36
 
37
- <section class="upload-section">
38
- <h2>📄 Document Upload</h2>
39
- <div class="upload-area" id="uploadArea">
40
- <input type="file" id="fileInput" accept=".txt,.md,.doc,.docx,.pdf" multiple>
41
- <label for="fileInput" class="upload-label">
42
- <span>📁 Choose files or drag & drop</span>
43
- <small>Supports: TXT, MD, DOC, DOCX, PDF</small>
44
- </label>
 
 
 
 
 
 
 
 
 
45
  </div>
46
- <div id="uploadStatus"></div>
47
  </section>
48
 
49
- <section class="content-grid">
50
- <div class="panel">
51
- <h2>📚 Indexed Documents</h2>
52
- <div id="documentList" class="document-list">
53
- <p class="empty-state">No documents indexed yet. Upload files to begin.</p>
 
 
 
 
 
 
 
 
54
  </div>
55
  </div>
 
56
 
57
- <div class="panel">
58
- <h2>⚡ Extracted Axioms</h2>
59
- <div id="axiomList" class="axiom-list">
60
- <p class="empty-state">No axioms extracted yet. Upload and index documents to extract axioms.</p>
 
 
 
 
 
 
 
 
 
 
 
 
61
  </div>
62
  </div>
63
  </section>
64
 
65
- <section class="generation-section">
66
- <h2>🤖 Generate Response</h2>
67
- <div class="generation-controls">
68
- <textarea
69
- id="queryInput"
70
- placeholder="Enter your query (e.g., 'What are the fundamental principles of quantum mechanics based on the uploaded documents?')"
71
- rows="4"
72
- ></textarea>
73
- <div class="generation-options">
74
- <label>
75
- <input type="checkbox" id="useAxioms" checked>
76
- Use extracted axioms for logical consistency
77
- </label>
78
- <label>
79
- <input type="checkbox" id="useContext" checked>
80
- Use document context (RAG)
81
- </label>
 
 
 
 
 
 
 
 
82
  </div>
83
- <button id="generateBtn" disabled>Generate Response</button>
 
 
84
  </div>
85
- <div id="generationStatusIndicator"></div>
86
- <div id="generationResult" class="result-container hidden">
87
- <h3>Generated Response:</h3>
88
- <div id="responseText" class="response-text"></div>
89
- <details class="context-info">
90
- <summary>View Retrieved Context</summary>
91
- <div id="retrievedContext"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  </details>
93
  </div>
94
  </section>
95
 
96
- <section class="actions">
97
- <button id="clearAllBtn" class="danger">Clear All Data</button>
98
- <button id="exportBtn">Export Axioms</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  </section>
100
  </main>
101
 
102
- <script src="https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.0.0-alpha.14"></script>
103
- <script src="index.js"></script>
104
- </body>
105
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <!DOCTYPE html>
2
+ <html lang="en" data-theme="light">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>RAG Nexus - Intelligent Document Analysis & Axiom Extraction</title>
7
+ <meta name="description" content="Advanced RAG system with axiom extraction, semantic search, and intelligent response generation">
8
+
9
+ <style>
10
+ /* ==================== MODERN CSS RESET & BASE ==================== */
11
+ :root {
12
+ /* Light Theme Colors */
13
+ --color-primary: #6366f1;
14
+ --color-secondary: #8b5cf6;
15
+ --color-success: #10b981;
16
+ --color-warning: #f59e0b;
17
+ --color-error: #ef4444;
18
+ --color-bg: #f8fafc;
19
+ --color-surface: #ffffff;
20
+ --color-surface-variant: #f1f5f9;
21
+ --color-text-primary: #1e293b;
22
+ --color-text-secondary: #64748b;
23
+ --color-border: #e2e8f0;
24
+ --color-shadow: rgba(0, 0, 0, 0.1);
25
+ --color-shadow-lg: rgba(0, 0, 0, 0.15);
26
+
27
+ /* Typography */
28
+ --font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
29
+ --font-mono: 'Fira Code', 'Cascadia Code', 'Roboto Mono', monospace;
30
+
31
+ /* Spacing */
32
+ --space-xs: 0.25rem;
33
+ --space-sm: 0.5rem;
34
+ --space-md: 1rem;
35
+ --space-lg: 1.5rem;
36
+ --space-xl: 2rem;
37
+
38
+ /* Shadows */
39
+ --shadow-sm: 0 1px 2px var(--color-shadow);
40
+ --shadow-md: 0 4px 6px var(--color-shadow);
41
+ --shadow-lg: 0 10px 15px var(--color-shadow-lg);
42
+
43
+ /* Transitions */
44
+ --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
45
+ --transition-medium: 300ms cubic-bezier(0.4, 0, 0.2, 1);
46
+ --transition-slow: 500ms cubic-bezier(0.4, 0, 0.2, 1);
47
+
48
+ /* Layout */
49
+ --container-max: 1400px;
50
+ --border-radius: 12px;
51
+ --border-radius-sm: 6px;
52
+ }
53
+
54
+ /* Dark Theme Colors */
55
+ [data-theme="dark"] {
56
+ --color-primary: #818cf8;
57
+ --color-secondary: #a78bfa;
58
+ --color-bg: #0f172a;
59
+ --color-surface: #1e293b;
60
+ --color-surface-variant: #334155;
61
+ --color-text-primary: #f1f5f9;
62
+ --color-text-secondary: #94a3b8;
63
+ --color-border: #334155;
64
+ --color-shadow: rgba(0, 0, 0, 0.3);
65
+ --color-shadow-lg: rgba(0, 0, 0, 0.4);
66
+ }
67
+
68
+ /* Modern CSS Reset */
69
+ *, *::before, *::after {
70
+ box-sizing: border-box;
71
+ margin: 0;
72
+ padding: 0;
73
+ }
74
+
75
+ * {
76
+ scrollbar-width: thin;
77
+ scrollbar-color: var(--color-primary) transparent;
78
+ }
79
+
80
+ *::-webkit-scrollbar {
81
+ width: 8px;
82
+ height: 8px;
83
+ }
84
+
85
+ *::-webkit-scrollbar-track {
86
+ background: var(--color-bg);
87
+ }
88
+
89
+ *::-webkit-scrollbar-thumb {
90
+ background: var(--color-primary);
91
+ border-radius: var(--border-radius-sm);
92
+ }
93
+
94
+ body {
95
+ font-family: var(--font-sans);
96
+ background: var(--color-bg);
97
+ color: var(--color-text-primary);
98
+ line-height: 1.6;
99
+ -webkit-font-smoothing: antialiased;
100
+ -moz-osx-font-smoothing: grayscale;
101
+ overflow-x: hidden;
102
+ }
103
+
104
+ /* ==================== LAYOUT & CONTAINERS ==================== */
105
+ .container {
106
+ max-width: var(--container-max);
107
+ margin: 0 auto;
108
+ padding: 0 var(--space-lg);
109
+ }
110
+
111
+ .grid {
112
+ display: grid;
113
+ gap: var(--space-lg);
114
+ }
115
+
116
+ .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
117
+ .grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
118
+ .grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
119
+
120
+ .flex { display: flex; }
121
+ .flex-col { flex-direction: column; }
122
+ .items-center { align-items: center; }
123
+ .justify-between { justify-content: space-between; }
124
+ .gap-sm { gap: var(--space-sm); }
125
+ .gap-md { gap: var(--space-md); }
126
+ .gap-lg { gap: var(--space-lg); }
127
+
128
+ /* ==================== HEADER ==================== */
129
+ .app-header {
130
+ background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
131
+ color: white;
132
+ padding: var(--space-xl) 0;
133
+ box-shadow: var(--shadow-lg);
134
+ position: sticky;
135
+ top: 0;
136
+ z-index: 100;
137
+ backdrop-filter: blur(10px);
138
+ -webkit-backdrop-filter: blur(10px);
139
+ }
140
+
141
+ .app-header h1 {
142
+ font-size: clamp(1.5rem, 4vw, 2.5rem);
143
+ font-weight: 800;
144
+ margin-bottom: var(--space-sm);
145
+ display: flex;
146
+ align-items: center;
147
+ gap: var(--space-md);
148
+ }
149
+
150
+ .app-header p {
151
+ font-size: 1.1rem;
152
+ opacity: 0.9;
153
+ max-width: 600px;
154
+ }
155
+
156
+ .header-actions {
157
+ display: flex;
158
+ gap: var(--space-md);
159
+ margin-top: var(--space-md);
160
+ }
161
+
162
+ /* ==================== NAVIGATION & CONTROLS ==================== */
163
+ .nav-tabs {
164
+ display: flex;
165
+ gap: var(--space-sm);
166
+ border-bottom: 2px solid var(--color-border);
167
+ margin-bottom: var(--space-lg);
168
+ }
169
+
170
+ .nav-tab {
171
+ padding: var(--space-md) var(--space-lg);
172
+ background: none;
173
+ border: none;
174
+ color: var(--color-text-secondary);
175
+ cursor: pointer;
176
+ font-size: 1rem;
177
+ font-weight: 500;
178
+ position: relative;
179
+ transition: color var(--transition-fast);
180
+ }
181
+
182
+ .nav-tab:hover {
183
+ color: var(--color-primary);
184
+ }
185
+
186
+ .nav-tab.active {
187
+ color: var(--color-primary);
188
+ }
189
+
190
+ .nav-tab.active::after {
191
+ content: '';
192
+ position: absolute;
193
+ bottom: -2px;
194
+ left: 0;
195
+ right: 0;
196
+ height: 2px;
197
+ background: var(--color-primary);
198
+ animation: slideIn var(--transition-medium);
199
+ }
200
+
201
+ @keyframes slideIn {
202
+ from { transform: scaleX(0); }
203
+ to { transform: scaleX(1); }
204
+ }
205
+
206
+ /* ==================== BUTTONS ==================== */
207
+ .btn {
208
+ display: inline-flex;
209
+ align-items: center;
210
+ justify-content: center;
211
+ gap: var(--space-sm);
212
+ padding: var(--space-md) var(--space-lg);
213
+ border: none;
214
+ border-radius: var(--border-radius-sm);
215
+ font-size: 1rem;
216
+ font-weight: 500;
217
+ cursor: pointer;
218
+ transition: all var(--transition-fast);
219
+ text-decoration: none;
220
+ position: relative;
221
+ overflow: hidden;
222
+ }
223
+
224
+ .btn::before {
225
+ content: '';
226
+ position: absolute;
227
+ inset: 0;
228
+ background: currentColor;
229
+ opacity: 0;
230
+ transition: opacity var(--transition-fast);
231
+ }
232
+
233
+ .btn:hover::before {
234
+ opacity: 0.1;
235
+ }
236
+
237
+ .btn-primary {
238
+ background: var(--color-primary);
239
+ color: white;
240
+ }
241
+
242
+ .btn-secondary {
243
+ background: var(--color-surface-variant);
244
+ color: var(--color-text-primary);
245
+ }
246
+
247
+ .btn-success {
248
+ background: var(--color-success);
249
+ color: white;
250
+ }
251
+
252
+ .btn-warning {
253
+ background: var(--color-warning);
254
+ color: white;
255
+ }
256
+
257
+ .btn-danger {
258
+ background: var(--color-error);
259
+ color: white;
260
+ }
261
+
262
+ .btn:disabled {
263
+ opacity: 0.5;
264
+ cursor: not-allowed;
265
+ }
266
+
267
+ .btn-icon {
268
+ padding: var(--space-sm);
269
+ border-radius: 50%;
270
+ }
271
+
272
+ /* ==================== CARDS & PANELS ==================== */
273
+ .card {
274
+ background: var(--color-surface);
275
+ border-radius: var(--border-radius);
276
+ padding: var(--space-lg);
277
+ box-shadow: var(--shadow-md);
278
+ border: 1px solid var(--color-border);
279
+ transition: transform var(--transition-fast), box-shadow var(--transition-fast);
280
+ }
281
+
282
+ .card:hover {
283
+ box-shadow: var(--shadow-lg);
284
+ transform: translateY(-2px);
285
+ }
286
+
287
+ .card-header {
288
+ display: flex;
289
+ justify-content: space-between;
290
+ align-items: center;
291
+ margin-bottom: var(--space-md);
292
+ padding-bottom: var(--space-md);
293
+ border-bottom: 1px solid var(--color-border);
294
+ }
295
+
296
+ .card-title {
297
+ font-size: 1.25rem;
298
+ font-weight: 600;
299
+ color: var(--color-text-primary);
300
+ }
301
+
302
+ /* ==================== FORM ELEMENTS ==================== */
303
+ .form-group {
304
+ display: flex;
305
+ flex-direction: column;
306
+ gap: var(--space-sm);
307
+ }
308
+
309
+ .form-label {
310
+ font-weight: 500;
311
+ color: var(--color-text-primary);
312
+ }
313
+
314
+ .form-input,
315
+ .form-textarea,
316
+ .form-select {
317
+ padding: var(--space-md);
318
+ border: 2px solid var(--color-border);
319
+ border-radius: var(--border-radius-sm);
320
+ font-size: 1rem;
321
+ font-family: inherit;
322
+ background: var(--color-surface);
323
+ color: var(--color-text-primary);
324
+ transition: border-color var(--transition-fast);
325
+ }
326
+
327
+ .form-input:focus,
328
+ .form-textarea:focus,
329
+ .form-select:focus {
330
+ outline: none;
331
+ border-color: var(--color-primary);
332
+ }
333
+
334
+ .form-textarea {
335
+ resize: vertical;
336
+ min-height: 120px;
337
+ }
338
+
339
+ .form-checkbox {
340
+ display: flex;
341
+ align-items: center;
342
+ gap: var(--space-sm);
343
+ cursor: pointer;
344
+ }
345
+
346
+ /* ==================== UPLOAD AREA ==================== */
347
+ .upload-zone {
348
+ border: 2px dashed var(--color-primary);
349
+ border-radius: var(--border-radius);
350
+ padding: var(--space-xl);
351
+ text-align: center;
352
+ cursor: pointer;
353
+ transition: all var(--transition-medium);
354
+ position: relative;
355
+ overflow: hidden;
356
+ }
357
+
358
+ .upload-zone::before {
359
+ content: '';
360
+ position: absolute;
361
+ inset: 0;
362
+ background: var(--color-primary);
363
+ opacity: 0;
364
+ transition: opacity var(--transition-fast);
365
+ }
366
+
367
+ .upload-zone:hover::before {
368
+ opacity: 0.05;
369
+ }
370
+
371
+ .upload-zone.dragover {
372
+ background: color-mix(in srgb, var(--color-primary) 10%, transparent);
373
+ border-color: var(--color-secondary);
374
+ }
375
+
376
+ .upload-icon {
377
+ font-size: 3rem;
378
+ margin-bottom: var(--space-md);
379
+ }
380
+
381
+ .upload-text {
382
+ font-size: 1.1rem;
383
+ font-weight: 500;
384
+ margin-bottom: var(--space-sm);
385
+ }
386
+
387
+ .upload-hint {
388
+ font-size: 0.9rem;
389
+ color: var(--color-text-secondary);
390
+ }
391
+
392
+ /* ==================== PROGRESS INDICATORS ==================== */
393
+ .progress-container {
394
+ position: relative;
395
+ background: var(--color-surface-variant);
396
+ border-radius: var(--border-radius-sm);
397
+ overflow: hidden;
398
+ height: 24px;
399
+ }
400
+
401
+ .progress-bar {
402
+ height: 100%;
403
+ background: linear-gradient(90deg, var(--color-primary), var(--color-secondary));
404
+ transition: width var(--transition-medium);
405
+ position: relative;
406
+ }
407
+
408
+ .progress-text {
409
+ position: absolute;
410
+ inset: 0;
411
+ display: flex;
412
+ align-items: center;
413
+ justify-content: center;
414
+ font-size: 0.8rem;
415
+ font-weight: 600;
416
+ color: var(--color-text-primary);
417
+ }
418
+
419
+ .spinner {
420
+ width: 20px;
421
+ height: 20px;
422
+ border: 2px solid var(--color-surface-variant);
423
+ border-top-color: var(--color-primary);
424
+ border-radius: 50%;
425
+ animation: spin 1s linear infinite;
426
+ }
427
+
428
+ @keyframes spin {
429
+ to { transform: rotate(360deg); }
430
+ }
431
+
432
+ /* ==================== LISTS & ITEMS ==================== */
433
+ .list {
434
+ display: flex;
435
+ flex-direction: column;
436
+ gap: var(--space-md);
437
+ max-height: 500px;
438
+ overflow-y: auto;
439
+ }
440
+
441
+ .list-item {
442
+ background: var(--color-surface-variant);
443
+ border-radius: var(--border-radius-sm);
444
+ padding: var(--space-md);
445
+ border-left: 4px solid var(--color-primary);
446
+ transition: all var(--transition-fast);
447
+ }
448
+
449
+ .list-item:hover {
450
+ transform: translateX(4px);
451
+ box-shadow: var(--shadow-md);
452
+ }
453
+
454
+ .list-item-header {
455
+ display: flex;
456
+ justify-content: space-between;
457
+ align-items: center;
458
+ margin-bottom: var(--space-sm);
459
+ }
460
+
461
+ .list-item-title {
462
+ font-weight: 600;
463
+ color: var(--color-text-primary);
464
+ }
465
+
466
+ .list-item-meta {
467
+ display: flex;
468
+ gap: var(--space-md);
469
+ font-size: 0.85rem;
470
+ color: var(--color-text-secondary);
471
+ }
472
+
473
+ .list-item-content {
474
+ font-size: 0.9rem;
475
+ color: var(--color-text-secondary);
476
+ line-height: 1.5;
477
+ }
478
+
479
+ /* ==================== TAGS & BADGES ==================== */
480
+ .tag {
481
+ display: inline-flex;
482
+ align-items: center;
483
+ padding: var(--space-xs) var(--space-sm);
484
+ border-radius: var(--border-radius-sm);
485
+ font-size: 0.75rem;
486
+ font-weight: 500;
487
+ text-transform: uppercase;
488
+ letter-spacing: 0.05em;
489
+ }
490
+
491
+ .tag-primary {
492
+ background: color-mix(in srgb, var(--color-primary) 20%, transparent);
493
+ color: var(--color-primary);
494
+ }
495
+
496
+ .tag-success {
497
+ background: color-mix(in srgb, var(--color-success) 20%, transparent);
498
+ color: var(--color-success);
499
+ }
500
+
501
+ .tag-warning {
502
+ background: color-mix(in srgb, var(--color-warning) 20%, transparent);
503
+ color: var(--color-warning);
504
+ }
505
+
506
+ /* ==================== NOTIFICATIONS ==================== */
507
+ .notification-container {
508
+ position: fixed;
509
+ top: var(--space-lg);
510
+ right: var(--space-lg);
511
+ z-index: 1000;
512
+ display: flex;
513
+ flex-direction: column;
514
+ gap: var(--space-md);
515
+ max-width: 400px;
516
+ }
517
+
518
+ .notification {
519
+ background: var(--color-surface);
520
+ border-radius: var(--border-radius);
521
+ padding: var(--space-md);
522
+ box-shadow: var(--shadow-lg);
523
+ border-left: 4px solid var(--color-primary);
524
+ transform: translateX(100%);
525
+ transition: transform var(--transition-medium);
526
+ }
527
+
528
+ .notification.show {
529
+ transform: translateX(0);
530
+ }
531
+
532
+ .notification.success { border-left-color: var(--color-success); }
533
+ .notification.error { border-left-color: var(--color-error); }
534
+ .notification.warning { border-left-color: var(--color-warning); }
535
+
536
+ .notification-header {
537
+ display: flex;
538
+ justify-content: space-between;
539
+ align-items: center;
540
+ margin-bottom: var(--space-sm);
541
+ }
542
+
543
+ .notification-title {
544
+ font-weight: 600;
545
+ color: var(--color-text-primary);
546
+ }
547
+
548
+ .notification-close {
549
+ background: none;
550
+ border: none;
551
+ font-size: 1.2rem;
552
+ cursor: pointer;
553
+ color: var(--color-text-secondary);
554
+ }
555
+
556
+ /* ==================== EMPTY STATE ==================== */
557
+ .empty-state {
558
+ text-align: center;
559
+ padding: var(--space-xl);
560
+ color: var(--color-text-secondary);
561
+ }
562
+
563
+ .empty-icon {
564
+ font-size: 3rem;
565
+ margin-bottom: var(--space-md);
566
+ opacity: 0.5;
567
+ }
568
+
569
+ /* ==================== UTILITIES ==================== */
570
+ .hidden { display: none !important; }
571
+ .visually-hidden {
572
+ position: absolute;
573
+ width: 1px;
574
+ height: 1px;
575
+ padding: 0;
576
+ margin: -1px;
577
+ overflow: hidden;
578
+ clip: rect(0, 0, 0, 0);
579
+ white-space: nowrap;
580
+ border-width: 0;
581
+ }
582
+
583
+ .text-center { text-align: center; }
584
+ .text-muted { color: var(--color-text-secondary); }
585
+ .font-mono { font-family: var(--font-mono); }
586
+
587
+ /* ==================== RESPONSIVE DESIGN ==================== */
588
+ @container (max-width: 768px) {
589
+ .container {
590
+ padding: 0 var(--space-md);
591
+ }
592
+
593
+ .grid-cols-2,
594
+ .grid-cols-3 {
595
+ grid-template-columns: 1fr;
596
+ }
597
+
598
+ .header-actions {
599
+ flex-direction: column;
600
+ }
601
+
602
+ .notification-container {
603
+ left: var(--space-md);
604
+ right: var(--space-md);
605
+ max-width: none;
606
+ }
607
+ }
608
+
609
+ /* ==================== ANIMATIONS ==================== */
610
+ @keyframes fadeIn {
611
+ from { opacity: 0; transform: translateY(10px); }
612
+ to { opacity: 1; transform: translateY(0); }
613
+ }
614
+
615
+ .fade-in {
616
+ animation: fadeIn var(--transition-medium) forwards;
617
+ }
618
+
619
+ @keyframes pulse {
620
+ 0%, 100% { opacity: 1; }
621
+ 50% { opacity: 0.5; }
622
+ }
623
+
624
+ .animate-pulse {
625
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
626
+ }
627
+
628
+ /* ==================== SYNTAX HIGHLIGHTING ==================== */
629
+ .code-block {
630
+ background: var(--color-surface-variant);
631
+ border-radius: var(--border-radius-sm);
632
+ padding: var(--space-md);
633
+ font-family: var(--font-mono);
634
+ font-size: 0.9rem;
635
+ overflow-x: auto;
636
+ border: 1px solid var(--color-border);
637
+ }
638
+
639
+ .code-block pre {
640
+ margin: 0;
641
+ white-space: pre-wrap;
642
+ word-wrap: break-word;
643
+ }
644
+
645
+ /* ==================== MARKDOWN RENDERING ==================== */
646
+ .markdown-content {
647
+ line-height: 1.7;
648
+ }
649
+
650
+ .markdown-content h1,
651
+ .markdown-content h2,
652
+ .markdown-content h3 {
653
+ margin: var(--space-lg) 0 var(--space-md);
654
+ color: var(--color-text-primary);
655
+ }
656
+
657
+ .markdown-content p {
658
+ margin-bottom: var(--space-md);
659
+ }
660
+
661
+ .markdown-content ul,
662
+ .markdown-content ol {
663
+ margin-left: var(--space-lg);
664
+ margin-bottom: var(--space-md);
665
+ }
666
+
667
+ .markdown-content li {
668
+ margin-bottom: var(--space-xs);
669
+ }
670
+
671
+ .markdown-content blockquote {
672
+ border-left: 4px solid var(--color-primary);
673
+ padding-left: var(--space-md);
674
+ margin: var(--space-md) 0;
675
+ color: var(--color-text-secondary);
676
+ font-style: italic;
677
+ }
678
+ </style>
679
  </head>
680
  <body>
681
+ <!-- Header -->
682
+ <header class="app-header">
683
+ <div class="container">
684
+ <h1>
685
+ <span>🔮</span>
686
+ RAG Nexus
687
+ </h1>
688
+ <p>Intelligent Document Analysis & Axiom Extraction System</p>
689
+ <div class="header-actions">
690
+ <button class="btn btn-secondary btn-icon" id="themeToggle" title="Toggle theme">
691
+ <span id="themeIcon">🌙</span>
692
+ </button>
693
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="btn btn-secondary">
694
+ Built with anycoder
695
+ </a>
696
+ </div>
697
  </div>
698
  </header>
699
 
700
+ <!-- Main Content -->
701
+ <main class="container" style="margin-top: var(--space-xl);">
702
+ <!-- Model Status Panel -->
703
+ <section class="card fade-in">
704
+ <div class="card-header">
705
+ <h2 class="card-title">🤖 Model Status</h2>
706
+ <div class="spinner hidden" id="modelSpinner"></div>
707
+ </div>
708
+ <div class="grid grid-cols-2 gap-md">
709
+ <div class="form-group">
710
+ <label class="form-label">Embedding Model</label>
711
+ <div class="status-item">
712
+ <span class="tag tag-warning" id="embeddingStatus">⏳ Initializing</span>
713
+ <div class="progress-container" id="embeddingProgressContainer" style="flex: 1; margin-left: var(--space-md);">
714
+ <div class="progress-bar" id="embeddingProgressBar" style="width: 0%"></div>
715
+ <span class="progress-text" id="embeddingProgressText">0%</span>
716
+ </div>
717
+ </div>
718
  </div>
719
+ <div class="form-group">
720
+ <label class="form-label">Generation Model</label>
721
+ <div class="status-item">
722
+ <span class="tag tag-warning" id="generationStatus">⏳ Initializing</span>
723
+ <div class="progress-container" id="generationProgressContainer" style="flex: 1; margin-left: var(--space-md);">
724
+ <div class="progress-bar" id="generationProgressBar" style="width: 0%"></div>
725
+ <span class="progress-text" id="generationProgressText">0%</span>
726
+ </div>
727
+ </div>
728
  </div>
729
  </div>
 
 
 
 
730
  </section>
731
 
732
+ <!-- Navigation Tabs -->
733
+ <nav class="nav-tabs fade-in">
734
+ <button class="nav-tab active" data-tab="upload">📤 Upload</button>
735
+ <button class="nav-tab" data-tab="documents">📚 Documents</button>
736
+ <button class="nav-tab" data-tab="axioms">⚡ Axioms</button>
737
+ <button class="nav-tab" data-tab="generate">🤖 Generate</button>
738
+ <button class="nav-tab" data-tab="analytics">📊 Analytics</button>
739
+ </nav>
740
+
741
+ <!-- Upload Tab -->
742
+ <section class="card fade-in tab-content" id="uploadTab">
743
+ <h2 class="card-title">Document Upload</h2>
744
+ <div class="upload-zone" id="uploadZone">
745
+ <div class="upload-icon">📁</div>
746
+ <div class="upload-text">Drop files here or click to browse</div>
747
+ <div class="upload-hint">Supports: TXT, MD, PDF, DOC, DOCX (Max 10MB each)</div>
748
+ <input type="file" id="fileInput" class="visually-hidden" multiple accept=".txt,.md,.pdf,.doc,.docx">
749
  </div>
750
+ <div id="uploadQueue" class="list" style="margin-top: var(--space-lg);"></div>
751
  </section>
752
 
753
+ <!-- Documents Tab -->
754
+ <section class="card fade-in tab-content hidden" id="documentsTab">
755
+ <div class="card-header">
756
+ <h2 class="card-title">Indexed Documents</h2>
757
+ <div class="flex gap-sm">
758
+ <input type="text" id="documentSearch" class="form-input" placeholder="Search documents..." style="max-width: 300px;">
759
+ <button class="btn btn-danger" id="clearDocumentsBtn">Clear All</button>
760
+ </div>
761
+ </div>
762
+ <div id="documentList" class="list">
763
+ <div class="empty-state">
764
+ <div class="empty-icon">📄</div>
765
+ <p>No documents indexed yet. Upload files to begin.</p>
766
  </div>
767
  </div>
768
+ </section>
769
 
770
+ <!-- Axioms Tab -->
771
+ <section class="card fade-in tab-content hidden" id="axiomsTab">
772
+ <div class="card-header">
773
+ <h2 class="card-title">Extracted Axioms</h2>
774
+ <div class="flex gap-sm">
775
+ <input type="text" id="axiomSearch" class="form-input" placeholder="Search axioms..." style="max-width: 300px;">
776
+ <select id="axiomFilter" class="form-select" style="max-width: 200px;">
777
+ <option value="">All Sources</option>
778
+ </select>
779
+ <button class="btn btn-secondary" id="exportAxiomsBtn">Export JSON</button>
780
+ </div>
781
+ </div>
782
+ <div id="axiomList" class="list">
783
+ <div class="empty-state">
784
+ <div class="empty-icon">⚡</div>
785
+ <p>No axioms extracted yet. Process documents to extract axioms.</p>
786
  </div>
787
  </div>
788
  </section>
789
 
790
+ <!-- Generate Tab -->
791
+ <section class="card fade-in tab-content hidden" id="generateTab">
792
+ <h2 class="card-title">Intelligent Response Generation</h2>
793
+ <div class="grid grid-cols-1 gap-lg">
794
+ <div class="form-group">
795
+ <label class="form-label" for="queryInput">Enter your query</label>
796
+ <textarea
797
+ id="queryInput"
798
+ class="form-textarea"
799
+ placeholder="Ask anything about your documents... (e.g., 'What are the fundamental principles of quantum mechanics based on the uploaded documents?')"
800
+ rows="4"
801
+ ></textarea>
802
+ <div class="flex justify-between items-center" style="margin-top: var(--space-sm);">
803
+ <div class="flex gap-md">
804
+ <label class="form-checkbox">
805
+ <input type="checkbox" id="useAxioms" checked>
806
+ <span>Use Axioms</span>
807
+ </label>
808
+ <label class="form-checkbox">
809
+ <input type="checkbox" id="useContext" checked>
810
+ <span>Use Context (RAG)</span>
811
+ </label>
812
+ </div>
813
+ <div class="text-muted" id="queryStats"></div>
814
+ </div>
815
  </div>
816
+ <button class="btn btn-primary" id="generateBtn" style="align-self: flex-start;">
817
+ <span>🚀 Generate Response</span>
818
+ </button>
819
  </div>
820
+
821
+ <div id="generationStatus" class="hidden" style="margin-top: var(--space-lg);"></div>
822
+
823
+ <div id="generationResult" class="hidden" style="margin-top: var(--space-lg);">
824
+ <div class="card" style="background: color-mix(in srgb, var(--color-success) 5%, transparent);">
825
+ <div class="card-header">
826
+ <h3 class="card-title">Generated Response</h3>
827
+ <div class="flex gap-sm">
828
+ <button class="btn btn-icon btn-secondary" id="copyResponseBtn" title="Copy to clipboard">
829
+ 📋
830
+ </button>
831
+ <button class="btn btn-icon btn-secondary" id="saveResponseBtn" title="Save response">
832
+ 💾
833
+ </button>
834
+ </div>
835
+ </div>
836
+ <div class="markdown-content" id="responseContent"></div>
837
+ </div>
838
+
839
+ <details class="card" style="margin-top: var(--space-md);">
840
+ <summary class="card-header" style="cursor: pointer;">
841
+ <h3 class="card-title">Retrieved Context & Axioms</h3>
842
+ </summary>
843
+ <div id="retrievedContext" class="list" style="max-height: 300px;"></div>
844
  </details>
845
  </div>
846
  </section>
847
 
848
+ <!-- Analytics Tab -->
849
+ <section class="card fade-in tab-content hidden" id="analyticsTab">
850
+ <h2 class="card-title">System Analytics</h2>
851
+ <div class="grid grid-cols-3 gap-lg">
852
+ <div class="card" style="background: color-mix(in srgb, var(--color-primary) 10%, transparent);">
853
+ <div class="card-header">
854
+ <h3 class="card-title">Documents</h3>
855
+ </div>
856
+ <div class="text-center">
857
+ <div style="font-size: 3rem; font-weight: 800; color: var(--color-primary);" id="docCount">0</div>
858
+ <p class="text-muted">Total Indexed</p>
859
+ </div>
860
+ </div>
861
+ <div class="card" style="background: color-mix(in srgb, var(--color-success) 10%, transparent);">
862
+ <div class="card-header">
863
+ <h3 class="card-title">Axioms</h3>
864
+ </div>
865
+ <div class="text-center">
866
+ <div style="font-size: 3rem; font-weight: 800; color: var(--color-success);" id="axiomCount">0</div>
867
+ <p class="text-muted">Extracted</p>
868
+ </div>
869
+ </div>
870
+ <div class="card" style="background: color-mix(in srgb, var(--color-secondary) 10%, transparent);">
871
+ <div class="card-header">
872
+ <h3 class="card-title">Storage</h3>
873
+ </div>
874
+ <div class="text-center">
875
+ <div style="font-size: 3rem; font-weight: 800; color: var(--color-secondary);" id="storageUsed">0MB</div>
876
+ <p class="text-muted">Used</p>
877
+ </div>
878
+ </div>
879
+ </div>
880
+ <div class="card" style="margin-top: var(--space-lg);">
881
+ <h3 class="card-title">Recent Activity</h3>
882
+ <div id="activityLog" class="list" style="max-height: 300px;"></div>
883
+ </div>
884
  </section>
885
  </main>
886
 
887
+ <!-- Notification Container -->
888
+ <div class="notification-container" id="notificationContainer"></div>
889
+
890
+ <!-- Service Worker Registration -->
891
+ <script>
892
+ if ('serviceWorker' in navigator) {
893
+ navigator.serviceWorker.register('data:text/javascript;base64,' + btoa(`
894
+ // Service Worker - Simulated Backend
895
+ const CACHE_NAME = 'rag-nexus-v1';
896
+ const DB_NAME = 'RAGNexusDB';
897
+ const DB_VERSION = 1;
898
+
899
+ let db = null;
900
+
901
+ // Initialize IndexedDB
902
+ async function initDB() {
903
+ return new Promise((resolve, reject) => {
904
+ const request = indexedDB.open(DB_NAME, DB_VERSION);
905
+
906
+ request.onerror = () => reject(request.error);
907
+ request.onsuccess = () => {
908
+ db = request.result;
909
+ resolve(db);
910
+ };
911
+
912
+ request.onupgradeneeded = (e) => {
913
+ const db = e.target.result;
914
+
915
+ if (!db.objectStoreNames.contains('documents')) {
916
+ const docStore = db.createObjectStore('documents', { keyPath: 'id' });
917
+ docStore.createIndex('name', 'name', { unique: false });
918
+ docStore.createIndex('uploadedAt', 'uploadedAt', { unique: false });
919
+ }
920
+
921
+ if (!db.objectStoreNames.contains('axioms')) {
922
+ const axiomStore = db.createObjectStore('axioms', { keyPath: 'id', autoIncrement: true });
923
+ axiomStore.createIndex('docId', 'docId', { unique: false });
924
+ axiomStore.createIndex('source', 'source', { unique: false });
925
+ }
926
+
927
+ if (!db.objectStoreNames.contains('responses')) {
928
+ const responseStore = db.createObjectStore('responses', { keyPath: 'id', autoIncrement: true });
929
+ responseStore.createIndex('timestamp', 'timestamp', { unique: false });
930
+ }
931
+
932
+ if (!db.objectStoreNames.contains('activity')) {
933
+ const activityStore = db.createObjectStore('activity', { keyPath: 'id', autoIncrement: true });
934
+ activityStore.createIndex('timestamp', 'timestamp', { unique: false });
935
+ }
936
+ };
937
+ });
938
+ }
939
+
940
+ // API Endpoints
941
+ const API_ENDPOINTS = {
942
+ '/api/documents': {
943
+ GET: async () => {
944
+ const tx = db.transaction('documents', 'readonly');
945
+ const store = tx.objectStore('documents');
946
+ const docs = await store.getAll();
947
+ return { success: true, data: docs };
948
+ },
949
+ POST: async (data) => {
950
+ const tx = db.transaction('documents', 'readwrite');
951
+ const store = tx.objectStore('documents');
952
+ await store.put(data);
953
+ return { success: true, data: { id: data.id } };
954
+ },
955
+ DELETE: async (id) => {
956
+ const tx = db.transaction('documents', 'readwrite');
957
+ const store = tx.objectStore('documents');
958
+ await store.delete(id);
959
+ return { success: true };
960
+ }
961
+ },
962
+ '/api/axioms': {
963
+ GET: async (params) => {
964
+ const tx = db.transaction('axioms', 'readonly');
965
+ const store = tx.objectStore('axioms');
966
+ const axioms = await store.getAll();
967
+
968
+ // Filter by docId if provided
969
+ if (params.docId) {
970
+ const filtered = axioms.filter(a => a.docId === params.docId);
971
+ return { success: true, data: filtered };
972
+ }
973
+
974
+ return { success: true, data: axioms };
975
+ },
976
+ POST: async (data) => {
977
+ const tx = db.transaction('axioms', 'readwrite');
978
+ const store = tx.objectStore('axioms');
979
+ const id = await store.add(data);
980
+ return { success: true, data: { id } };
981
+ }
982
+ },
983
+ '/api/responses': {
984
+ GET: async () => {
985
+ const tx = db.transaction('responses', 'readonly');
986
+ const store = tx.objectStore('responses');
987
+ const responses = await store.getAll();
988
+ return { success: true, data: responses };
989
+ },
990
+ POST: async (data) => {
991
+ const tx = db.transaction('responses', 'readwrite');
992
+ const store = tx.objectStore('responses');
993
+ const id = await store.add({ ...data, timestamp: new Date().toISOString() });
994
+ return { success: true, data: { id } };
995
+ }
996
+ },
997
+ '/api/activity': {
998
+ POST: async (data) => {
999
+ const tx = db.transaction('activity', 'readwrite');
1000
+ const store = tx.objectStore('activity');
1001
+ await store.add({ ...data, timestamp: new Date().toISOString() });
1002
+ return { success: true };
1003
+ }
1004
+ },
1005
+ '/api/clear': {
1006
+ POST: async () => {
1007
+ const tx = db.transaction(['documents', 'axioms', 'responses', 'activity'], 'readwrite');
1008
+ await Promise.all([
1009
+ tx.objectStore('documents').clear(),
1010
+ tx.objectStore('axioms').clear(),
1011
+ tx.objectStore('responses').clear(),
1012
+ tx.objectStore('activity').clear()
1013
+ ]);
1014
+ return { success: true };
1015
+ }
1016
+ }
1017
+ };
1018
+
1019
+ // Handle fetch events
1020
+ self.addEventListener('fetch', (event) => {
1021
+ const url = new URL(event.request.url);
1022
+
1023
+ // Only handle API requests
1024
+ if (!url.pathname.startsWith('/api/')) {
1025
+ return;
1026
+ }
1027
+
1028
+ event.respondWith(handleAPIRequest(event.request));
1029
+ });
1030
+
1031
+ async function handleAPIRequest(request) {
1032
+ try {
1033
+ await initDB();
1034
+
1035
+ const url = new URL(request.url);
1036
+ const endpoint = '/' + url.pathname.split('/').slice(1, 3).join('/');
1037
+ const method = request.method;
1038
+ const handler = API_ENDPOINTS[endpoint]?.[method];
1039
+
1040
+ if (!handler) {
1041
+ return new Response(JSON.stringify({ error: 'Not found' }), {
1042
+ status: 404,
1043
+ headers: { 'Content-Type': 'application/json' }
1044
+ });
1045
+ }
1046
+
1047
+ let data = null;
1048
+ if (method === 'POST' || method === 'PUT') {
1049
+ data = await request.json();
1050
+ } else if (method === 'GET') {
1051
+ data = Object.fromEntries(url.searchParams);
1052
+ }
1053
+
1054
+ const result = await handler(data);
1055
+
1056
+ return new Response(JSON.stringify(result), {
1057
+ status: 200,
1058
+ headers: { 'Content-Type': 'application/json' }
1059
+ });
1060
+ } catch (error) {
1061
+ console.error('API Error:', error);
1062
+ return new Response(JSON.stringify({ error: error.message }), {
1063
+ status: 500,
1064
+ headers: { 'Content-Type': 'application/json' }
1065
+ });
1066
+ }
1067
+ }
1068
+
1069
+ // Handle messages from main thread
1070
+ self.addEventListener('message', (event) => {
1071
+ if (event.data.type === 'SKIP_WAITING') {
1072
+ self.skipWaiting();
1073
+ }
1074
+ });
1075
+
1076
+ // Cache static assets
1077
+ self.addEventListener('install', (event) => {
1078
+ self.skipWaiting();
1079
+ });
1080
+
1081
+ self.addEventListener('activate', (event) => {
1082
+ event.waitUntil(self.clients.claim());
1083
+ });
1084
+ `)).then(registration => {
1085
+ console.log('Service Worker registered:', registration);
1086
+ }).catch(error => {
1087
+ console.log('Service Worker registration failed:', error);
1088
+ });
1089
+ }
1090
+ </script>
1091
+
1092
+ <!-- Main Application Script -->
1093
+ <script type="module">
1094
+ // ==================== APPLICATION STATE ====================
1095
+ class AppState {
1096
+ constructor() {
1097
+ this.documents = new Map();
1098
+ this.axioms = [];
1099
+ this.embeddings = new Map();
1100
+ this.models = {
1101
+ embedding: null,
1102
+ generation: null,
1103
+ summarization: null
1104
+ };
1105
+ this.isInitialized = false;
1106
+ this.currentTab = 'upload';
1107
+ this.activityLog = [];
1108
+ }
1109
+
1110
+ async loadFromDB() {
1111
+ try {
1112
+ const [docsRes, axiomsRes] = await Promise.all([
1113
+ fetch('/api/documents').then(r => r.json()),
1114
+ fetch('/api/axioms').then(r => r.json())
1115
+ ]);
1116
+
1117
+ if (docsRes.success) {
1118
+ this.documents = new Map(docsRes.data.map(d => [d.id, d]));
1119
+ }
1120
+
1121
+ if (axiomsRes.success) {
1122
+ this.axioms = axiomsRes.data;
1123
+ }
1124
+
1125
+ this.updateAnalytics();
1126
+ } catch (error) {
1127
+ console.warn('Failed to load from DB:', error);
1128
+ }
1129
+ }
1130
+
1131
+ async saveDocument(doc) {
1132
+ this.documents.set(doc.id, doc);
1133
+ await fetch('/api/documents', {
1134
+ method: 'POST',
1135
+ headers: { 'Content-Type': 'application/json' },
1136
+ body: JSON.stringify(doc)
1137
+ });
1138
+ this.updateAnalytics();
1139
+ }
1140
+
1141
+ async saveAxiom(axiom) {
1142
+ const id = Date.now() + Math.random();
1143
+ const axiomData = { ...axiom, id };
1144
+ this.axioms.push(axiomData);
1145
+
1146
+ await fetch('/api/axioms', {
1147
+ method: 'POST',
1148
+ headers: { 'Content-Type': 'application/json' },
1149
+ body: JSON.stringify(axiomData)
1150
+ });
1151
+
1152
+ this.updateAnalytics();
1153
+ return axiomData;
1154
+ }
1155
+
1156
+ async logActivity(action, details) {
1157
+ const activity = { action, details };
1158
+ this.activityLog.unshift(activity);
1159
+
1160
+ await fetch('/api/activity', {
1161
+ method: 'POST',
1162
+ headers: { 'Content-Type': 'application/json' },
1163
+ body: JSON.stringify(activity)
1164
+ });
1165
+ }
1166
+
1167
+ updateAnalytics() {