@trlc/super-memory 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/1 +0 -0
- package/dashboard/index.html +851 -0
- package/dashboard/package-lock.json +1158 -0
- package/dashboard/package.json +15 -0
- package/dashboard/server.js +355 -0
- package/dist/commands/categorize.js +70 -0
- package/dist/commands/dashboard.js +165 -0
- package/dist/commands/flush.js +70 -0
- package/dist/commands/indexUpdate.js +47 -0
- package/dist/commands/maintenance.js +68 -0
- package/dist/index.js +83 -0
- package/dist/utils/config.js +44 -0
- package/package.json +3 -1
|
@@ -0,0 +1,851 @@
|
|
|
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>Super Memory Dashboard</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
8
|
+
<style>
|
|
9
|
+
:root {
|
|
10
|
+
--bg-dark: #0A0A0A;
|
|
11
|
+
--bg-card: #1F1F1F;
|
|
12
|
+
--bg-hover: #2A2A2A;
|
|
13
|
+
--accent-red: #DC2626;
|
|
14
|
+
--accent-red-hover: #B91C1C;
|
|
15
|
+
--text-primary: #FFFFFF;
|
|
16
|
+
--text-secondary: #A1A1AA;
|
|
17
|
+
--text-muted: #71717A;
|
|
18
|
+
--border-color: #333333;
|
|
19
|
+
--category-gotcha: #EF4444;
|
|
20
|
+
--category-problem: #F59E0B;
|
|
21
|
+
--category-decision: #8B5CF6;
|
|
22
|
+
--category-discovery: #10B981;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
* {
|
|
26
|
+
margin: 0;
|
|
27
|
+
padding: 0;
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
body {
|
|
32
|
+
font-family: 'Inter', sans-serif;
|
|
33
|
+
background: var(--bg-dark);
|
|
34
|
+
color: var(--text-primary);
|
|
35
|
+
min-height: 100vh;
|
|
36
|
+
line-height: 1.6;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Header */
|
|
40
|
+
.header {
|
|
41
|
+
background: var(--bg-card);
|
|
42
|
+
border-bottom: 1px solid var(--border-color);
|
|
43
|
+
padding: 1rem 2rem;
|
|
44
|
+
display: flex;
|
|
45
|
+
justify-content: space-between;
|
|
46
|
+
align-items: center;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.logo {
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
gap: 0.75rem;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.logo-icon {
|
|
56
|
+
font-size: 1.5rem;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.logo-text {
|
|
60
|
+
font-weight: 700;
|
|
61
|
+
font-size: 1.25rem;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.header-actions {
|
|
65
|
+
display: flex;
|
|
66
|
+
gap: 1rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.action-bar {
|
|
70
|
+
background: var(--bg-card);
|
|
71
|
+
border: 1px solid var(--border-color);
|
|
72
|
+
border-radius: 0.75rem;
|
|
73
|
+
padding: 1rem;
|
|
74
|
+
margin-bottom: 2rem;
|
|
75
|
+
display: flex;
|
|
76
|
+
gap: 1rem;
|
|
77
|
+
align-items: center;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.btn {
|
|
81
|
+
padding: 0.5rem 1rem;
|
|
82
|
+
border-radius: 0.5rem;
|
|
83
|
+
border: none;
|
|
84
|
+
cursor: pointer;
|
|
85
|
+
font-size: 0.875rem;
|
|
86
|
+
font-weight: 500;
|
|
87
|
+
transition: all 0.2s;
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
gap: 0.5rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.btn-secondary {
|
|
94
|
+
background: var(--bg-hover);
|
|
95
|
+
color: var(--text-primary);
|
|
96
|
+
border: 1px solid var(--border-color);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.btn-secondary:hover {
|
|
100
|
+
background: var(--border-color);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.btn-primary {
|
|
104
|
+
background: var(--accent-red);
|
|
105
|
+
color: white;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.btn-primary:hover {
|
|
109
|
+
background: var(--accent-red-hover);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Main Layout */
|
|
113
|
+
.container {
|
|
114
|
+
max-width: 1400px;
|
|
115
|
+
margin: 0 auto;
|
|
116
|
+
padding: 2rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.grid {
|
|
120
|
+
display: grid;
|
|
121
|
+
grid-template-columns: 280px 1fr;
|
|
122
|
+
gap: 2rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* Stats Cards */
|
|
126
|
+
.stats-section {
|
|
127
|
+
margin-bottom: 2rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.stats-grid {
|
|
131
|
+
display: grid;
|
|
132
|
+
grid-template-columns: repeat(5, 1fr);
|
|
133
|
+
gap: 1rem;
|
|
134
|
+
margin-bottom: 2rem;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.stat-card {
|
|
138
|
+
background: var(--bg-card);
|
|
139
|
+
border: 1px solid var(--border-color);
|
|
140
|
+
border-radius: 0.75rem;
|
|
141
|
+
padding: 1.25rem;
|
|
142
|
+
transition: transform 0.2s;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.stat-card:hover {
|
|
146
|
+
transform: translateY(-2px);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.stat-icon {
|
|
150
|
+
font-size: 1.5rem;
|
|
151
|
+
margin-bottom: 0.5rem;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.stat-value {
|
|
155
|
+
font-size: 1.75rem;
|
|
156
|
+
font-weight: 700;
|
|
157
|
+
margin-bottom: 0.25rem;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.stat-label {
|
|
161
|
+
font-size: 0.75rem;
|
|
162
|
+
color: var(--text-muted);
|
|
163
|
+
text-transform: uppercase;
|
|
164
|
+
letter-spacing: 0.05em;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* Search */
|
|
168
|
+
.search-section {
|
|
169
|
+
margin-bottom: 2rem;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.search-input {
|
|
173
|
+
width: 100%;
|
|
174
|
+
padding: 0.875rem 1rem;
|
|
175
|
+
background: var(--bg-card);
|
|
176
|
+
border: 1px solid var(--border-color);
|
|
177
|
+
border-radius: 0.5rem;
|
|
178
|
+
color: var(--text-primary);
|
|
179
|
+
font-size: 0.9375rem;
|
|
180
|
+
font-family: 'Inter', sans-serif;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.search-input:focus {
|
|
184
|
+
outline: none;
|
|
185
|
+
border-color: var(--accent-red);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.search-input::placeholder {
|
|
189
|
+
color: var(--text-muted);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* Sidebar */
|
|
193
|
+
.sidebar {
|
|
194
|
+
background: var(--bg-card);
|
|
195
|
+
border: 1px solid var(--border-color);
|
|
196
|
+
border-radius: 0.75rem;
|
|
197
|
+
padding: 1.5rem;
|
|
198
|
+
height: fit-content;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.sidebar-title {
|
|
202
|
+
font-size: 0.75rem;
|
|
203
|
+
font-weight: 600;
|
|
204
|
+
color: var(--text-muted);
|
|
205
|
+
text-transform: uppercase;
|
|
206
|
+
letter-spacing: 0.05em;
|
|
207
|
+
margin-bottom: 1rem;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.category-list {
|
|
211
|
+
list-style: none;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.category-item {
|
|
215
|
+
display: flex;
|
|
216
|
+
align-items: center;
|
|
217
|
+
gap: 0.75rem;
|
|
218
|
+
padding: 0.625rem;
|
|
219
|
+
border-radius: 0.5rem;
|
|
220
|
+
cursor: pointer;
|
|
221
|
+
transition: background 0.2s;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.category-item:hover {
|
|
225
|
+
background: var(--bg-hover);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.category-item.active {
|
|
229
|
+
background: var(--bg-hover);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.category-dot {
|
|
233
|
+
width: 8px;
|
|
234
|
+
height: 8px;
|
|
235
|
+
border-radius: 50%;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.category-dot.gotcha { background: var(--category-gotcha); }
|
|
239
|
+
.category-dot.problem { background: var(--category-problem); }
|
|
240
|
+
.category-dot.decision { background: var(--category-decision); }
|
|
241
|
+
.category-dot.discovery { background: var(--category-discovery); }
|
|
242
|
+
|
|
243
|
+
.category-name {
|
|
244
|
+
flex: 1;
|
|
245
|
+
font-size: 0.875rem;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.category-count {
|
|
249
|
+
font-size: 0.75rem;
|
|
250
|
+
color: var(--text-muted);
|
|
251
|
+
font-family: 'JetBrains Mono', monospace;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Memory List */
|
|
255
|
+
.memories-section {
|
|
256
|
+
background: var(--bg-card);
|
|
257
|
+
border: 1px solid var(--border-color);
|
|
258
|
+
border-radius: 0.75rem;
|
|
259
|
+
padding: 1.5rem;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.memories-header {
|
|
263
|
+
display: flex;
|
|
264
|
+
justify-content: space-between;
|
|
265
|
+
align-items: center;
|
|
266
|
+
margin-bottom: 1.5rem;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.memories-title {
|
|
270
|
+
font-size: 1.125rem;
|
|
271
|
+
font-weight: 600;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.memories-count {
|
|
275
|
+
font-size: 0.875rem;
|
|
276
|
+
color: var(--text-muted);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.memory-list {
|
|
280
|
+
display: flex;
|
|
281
|
+
flex-direction: column;
|
|
282
|
+
gap: 0.75rem;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.memory-item {
|
|
286
|
+
background: var(--bg-dark);
|
|
287
|
+
border: 1px solid var(--border-color);
|
|
288
|
+
border-radius: 0.5rem;
|
|
289
|
+
padding: 1rem;
|
|
290
|
+
cursor: pointer;
|
|
291
|
+
transition: all 0.2s;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.memory-item:hover {
|
|
295
|
+
border-color: var(--accent-red);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.memory-header {
|
|
299
|
+
display: flex;
|
|
300
|
+
justify-content: space-between;
|
|
301
|
+
align-items: flex-start;
|
|
302
|
+
margin-bottom: 0.5rem;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.memory-category {
|
|
306
|
+
display: flex;
|
|
307
|
+
align-items: center;
|
|
308
|
+
gap: 0.375rem;
|
|
309
|
+
font-size: 0.75rem;
|
|
310
|
+
font-weight: 500;
|
|
311
|
+
padding: 0.25rem 0.5rem;
|
|
312
|
+
border-radius: 0.25rem;
|
|
313
|
+
background: rgba(255,255,255,0.05);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.memory-date {
|
|
317
|
+
font-size: 0.75rem;
|
|
318
|
+
color: var(--text-muted);
|
|
319
|
+
font-family: 'JetBrains Mono', monospace;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.memory-content {
|
|
323
|
+
font-size: 0.875rem;
|
|
324
|
+
color: var(--text-secondary);
|
|
325
|
+
line-height: 1.5;
|
|
326
|
+
display: -webkit-box;
|
|
327
|
+
-webkit-line-clamp: 2;
|
|
328
|
+
-webkit-box-orient: vertical;
|
|
329
|
+
overflow: hidden;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.memory-layer {
|
|
333
|
+
margin-top: 0.75rem;
|
|
334
|
+
font-size: 0.75rem;
|
|
335
|
+
color: var(--text-muted);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Modal */
|
|
339
|
+
.modal-overlay {
|
|
340
|
+
display: none;
|
|
341
|
+
position: fixed;
|
|
342
|
+
top: 0;
|
|
343
|
+
left: 0;
|
|
344
|
+
right: 0;
|
|
345
|
+
bottom: 0;
|
|
346
|
+
background: rgba(0,0,0,0.8);
|
|
347
|
+
z-index: 100;
|
|
348
|
+
align-items: center;
|
|
349
|
+
justify-content: center;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.modal-overlay.active {
|
|
353
|
+
display: flex;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.modal {
|
|
357
|
+
background: var(--bg-card);
|
|
358
|
+
border: 1px solid var(--border-color);
|
|
359
|
+
border-radius: 0.75rem;
|
|
360
|
+
width: 90%;
|
|
361
|
+
max-width: 700px;
|
|
362
|
+
max-height: 90vh;
|
|
363
|
+
overflow-y: auto;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.modal-header {
|
|
367
|
+
display: flex;
|
|
368
|
+
justify-content: space-between;
|
|
369
|
+
align-items: center;
|
|
370
|
+
padding: 1.25rem;
|
|
371
|
+
border-bottom: 1px solid var(--border-color);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.modal-title {
|
|
375
|
+
font-size: 1rem;
|
|
376
|
+
font-weight: 600;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.modal-close {
|
|
380
|
+
background: none;
|
|
381
|
+
border: none;
|
|
382
|
+
color: var(--text-muted);
|
|
383
|
+
font-size: 1.5rem;
|
|
384
|
+
cursor: pointer;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.modal-body {
|
|
388
|
+
padding: 1.5rem;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.modal-content {
|
|
392
|
+
white-space: pre-wrap;
|
|
393
|
+
font-size: 0.9375rem;
|
|
394
|
+
line-height: 1.7;
|
|
395
|
+
color: var(--text-secondary);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* Loading */
|
|
399
|
+
.loading {
|
|
400
|
+
text-align: center;
|
|
401
|
+
padding: 3rem;
|
|
402
|
+
color: var(--text-muted);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.spinner {
|
|
406
|
+
display: inline-block;
|
|
407
|
+
width: 24px;
|
|
408
|
+
height: 24px;
|
|
409
|
+
border: 2px solid var(--border-color);
|
|
410
|
+
border-top-color: var(--accent-red);
|
|
411
|
+
border-radius: 50%;
|
|
412
|
+
animation: spin 1s linear infinite;
|
|
413
|
+
margin-right: 0.75rem;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
@keyframes spin {
|
|
417
|
+
to { transform: rotate(360deg); }
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* Empty State */
|
|
421
|
+
.empty-state {
|
|
422
|
+
text-align: center;
|
|
423
|
+
padding: 4rem 2rem;
|
|
424
|
+
color: var(--text-muted);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.empty-icon {
|
|
428
|
+
font-size: 3rem;
|
|
429
|
+
margin-bottom: 1rem;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/* Responsive */
|
|
433
|
+
@media (max-width: 1024px) {
|
|
434
|
+
.grid {
|
|
435
|
+
grid-template-columns: 1fr;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.stats-grid {
|
|
439
|
+
grid-template-columns: repeat(3, 1fr);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.sidebar {
|
|
443
|
+
order: 2;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
@media (max-width: 640px) {
|
|
448
|
+
.header {
|
|
449
|
+
flex-direction: column;
|
|
450
|
+
gap: 1rem;
|
|
451
|
+
text-align: center;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.stats-grid {
|
|
455
|
+
grid-template-columns: repeat(2, 1fr);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.container {
|
|
459
|
+
padding: 1rem;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
</style>
|
|
463
|
+
</head>
|
|
464
|
+
<body>
|
|
465
|
+
<header class="header">
|
|
466
|
+
<div class="logo">
|
|
467
|
+
<span class="logo-icon">🦞</span>
|
|
468
|
+
<span class="logo-text">Super Memory</span>
|
|
469
|
+
</div>
|
|
470
|
+
<div class="header-actions">
|
|
471
|
+
<button class="btn btn-secondary" onclick="refreshData()">
|
|
472
|
+
🔄 Refresh
|
|
473
|
+
</button>
|
|
474
|
+
<button class="btn btn-secondary" onclick="exportData()">
|
|
475
|
+
📥 Export
|
|
476
|
+
</button>
|
|
477
|
+
</div>
|
|
478
|
+
</header>
|
|
479
|
+
|
|
480
|
+
<main class="container">
|
|
481
|
+
<!-- Action Bar -->
|
|
482
|
+
<section class="action-bar">
|
|
483
|
+
<button class="btn btn-primary" onclick="runIndexUpdate()">
|
|
484
|
+
🗂️ Update Index
|
|
485
|
+
</button>
|
|
486
|
+
<button class="btn btn-secondary" onclick="promptFlush()">
|
|
487
|
+
💾 Flush Context
|
|
488
|
+
</button>
|
|
489
|
+
<button class="btn btn-secondary" onclick="runMaintenance()">
|
|
490
|
+
🧹 Maintenance
|
|
491
|
+
</button>
|
|
492
|
+
</section>
|
|
493
|
+
|
|
494
|
+
<!-- Stats Section -->
|
|
495
|
+
<section class="stats-section">
|
|
496
|
+
<div class="stats-grid" id="stats-grid">
|
|
497
|
+
<div class="stat-card">
|
|
498
|
+
<div class="spinner"></div>
|
|
499
|
+
<div class="stat-label">Loading...</div>
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
</section>
|
|
503
|
+
|
|
504
|
+
<!-- Search Section -->
|
|
505
|
+
<section class="search-section">
|
|
506
|
+
<input
|
|
507
|
+
type="text"
|
|
508
|
+
class="search-input"
|
|
509
|
+
id="search-input"
|
|
510
|
+
placeholder="🔍 Search your memories..."
|
|
511
|
+
onkeyup="handleSearch(event)"
|
|
512
|
+
>
|
|
513
|
+
</section>
|
|
514
|
+
|
|
515
|
+
<div class="grid">
|
|
516
|
+
<!-- Sidebar -->
|
|
517
|
+
<aside class="sidebar">
|
|
518
|
+
<h3 class="sidebar-title">Categories</h3>
|
|
519
|
+
<ul class="category-list" id="category-list">
|
|
520
|
+
<li class="category-item active" onclick="filterCategory('all')">
|
|
521
|
+
<span class="category-dot" style="background: #666;"></span>
|
|
522
|
+
<span class="category-name">All</span>
|
|
523
|
+
<span class="category-count" id="count-all">-</span>
|
|
524
|
+
</li>
|
|
525
|
+
<li class="category-item" onclick="filterCategory('gotcha')">
|
|
526
|
+
<span class="category-dot gotcha"></span>
|
|
527
|
+
<span class="category-name">Gotcha</span>
|
|
528
|
+
<span class="category-count" id="count-gotcha">-</span>
|
|
529
|
+
</li>
|
|
530
|
+
<li class="category-item" onclick="filterCategory('problem')">
|
|
531
|
+
<span class="category-dot problem"></span>
|
|
532
|
+
<span class="category-name">Problem-Fix</span>
|
|
533
|
+
<span class="category-count" id="count-problem">-</span>
|
|
534
|
+
</li>
|
|
535
|
+
<li class="category-item" onclick="filterCategory('decision')">
|
|
536
|
+
<span class="category-dot decision"></span>
|
|
537
|
+
<span class="category-name">Decision</span>
|
|
538
|
+
<span class="category-count" id="count-decision">-</span>
|
|
539
|
+
</li>
|
|
540
|
+
<li class="category-item" onclick="filterCategory('discovery')">
|
|
541
|
+
<span class="category-dot discovery"></span>
|
|
542
|
+
<span class="category-name">Discovery</span>
|
|
543
|
+
<span class="category-count" id="count-discovery">-</span>
|
|
544
|
+
</li>
|
|
545
|
+
</ul>
|
|
546
|
+
</aside>
|
|
547
|
+
|
|
548
|
+
<!-- Memories List -->
|
|
549
|
+
<section class="memories-section">
|
|
550
|
+
<div class="memories-header">
|
|
551
|
+
<h2 class="memories-title">Recent Memories</h2>
|
|
552
|
+
<span class="memories-count" id="memories-count">Loading...</span>
|
|
553
|
+
</div>
|
|
554
|
+
<div class="memory-list" id="memory-list">
|
|
555
|
+
<div class="loading">
|
|
556
|
+
<div class="spinner"></div>
|
|
557
|
+
Loading memories...
|
|
558
|
+
</div>
|
|
559
|
+
</div>
|
|
560
|
+
</section>
|
|
561
|
+
</div>
|
|
562
|
+
</main>
|
|
563
|
+
|
|
564
|
+
<!-- Modal -->
|
|
565
|
+
<div class="modal-overlay" id="modal" onclick="closeModal(event)">
|
|
566
|
+
<div class="modal" onclick="event.stopPropagation()">
|
|
567
|
+
<div class="modal-header">
|
|
568
|
+
<h3 class="modal-title" id="modal-title">Memory Details</h3>
|
|
569
|
+
<button class="modal-close" onclick="closeModal()">×</button>
|
|
570
|
+
</div>
|
|
571
|
+
<div class="modal-body">
|
|
572
|
+
<div class="modal-content" id="modal-content"></div>
|
|
573
|
+
<div style="margin-top: 1.5rem; display: flex; gap: 0.5rem; border-top: 1px solid var(--border-color); padding-top: 1rem;">
|
|
574
|
+
<button class="btn btn-secondary" id="modal-categorize-btn" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;">
|
|
575
|
+
🧠 Auto-Categorize
|
|
576
|
+
</button>
|
|
577
|
+
</div>
|
|
578
|
+
</div>
|
|
579
|
+
</div>
|
|
580
|
+
</div>
|
|
581
|
+
|
|
582
|
+
<script>
|
|
583
|
+
// State
|
|
584
|
+
let currentCategory = 'all';
|
|
585
|
+
let memories = [];
|
|
586
|
+
|
|
587
|
+
// Actions
|
|
588
|
+
async function runIndexUpdate() {
|
|
589
|
+
if (!confirm('Update progressive MEMORY_INDEX.md? This will optimize token usage by 70%.')) return;
|
|
590
|
+
try {
|
|
591
|
+
const response = await fetch('/api/index-update', { method: 'POST' });
|
|
592
|
+
const result = await response.json();
|
|
593
|
+
if (result.success) alert('✅ Index updated successfully!');
|
|
594
|
+
else alert('❌ Failed: ' + result.error);
|
|
595
|
+
refreshData();
|
|
596
|
+
} catch (error) { alert('Error: ' + error.message); }
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
async function promptFlush() {
|
|
600
|
+
const context = prompt('Enter critical context to flush (protected from session compaction):');
|
|
601
|
+
if (!context) return;
|
|
602
|
+
try {
|
|
603
|
+
const response = await fetch('/api/flush', {
|
|
604
|
+
method: 'POST',
|
|
605
|
+
headers: { 'Content-Type': 'application/json' },
|
|
606
|
+
body: JSON.stringify({ content: context })
|
|
607
|
+
});
|
|
608
|
+
const result = await response.json();
|
|
609
|
+
if (result.success) alert('✅ Context flushed!');
|
|
610
|
+
else alert('❌ Failed: ' + result.error);
|
|
611
|
+
refreshData();
|
|
612
|
+
} catch (error) { alert('Error: ' + error.message); }
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
async function runMaintenance() {
|
|
616
|
+
try {
|
|
617
|
+
const response = await fetch('/api/maintenance');
|
|
618
|
+
const result = await response.json();
|
|
619
|
+
if (result.success && result.suggestions.length > 0) {
|
|
620
|
+
let msg = '🧹 Maintenance Suggestions:\n\n';
|
|
621
|
+
result.suggestions.forEach(s => msg += `• [${s.priority.toUpperCase()}] ${s.message}\n 👉 Action: ${s.action}\n\n`);
|
|
622
|
+
alert(msg);
|
|
623
|
+
} else {
|
|
624
|
+
alert('✅ System healthy. No maintenance needed.');
|
|
625
|
+
}
|
|
626
|
+
} catch (error) { alert('Error: ' + error.message); }
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
async function runCategorize(id) {
|
|
630
|
+
try {
|
|
631
|
+
const response = await fetch(`/api/categorize/${id}`, { method: 'POST' });
|
|
632
|
+
const result = await response.json();
|
|
633
|
+
if (result.success) {
|
|
634
|
+
alert('✅ Re-categorized as: ' + result.newCategory.toUpperCase());
|
|
635
|
+
refreshData();
|
|
636
|
+
} else {
|
|
637
|
+
alert('❌ Failed: ' + result.error);
|
|
638
|
+
}
|
|
639
|
+
} catch (error) { alert('Error: ' + error.message); }
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Initialize
|
|
643
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
644
|
+
loadStats();
|
|
645
|
+
loadMemories();
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
// Load Stats
|
|
649
|
+
async function loadStats() {
|
|
650
|
+
try {
|
|
651
|
+
const response = await fetch('/api/stats');
|
|
652
|
+
const stats = await response.json();
|
|
653
|
+
renderStats(stats);
|
|
654
|
+
} catch (error) {
|
|
655
|
+
console.error('Failed to load stats:', error);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Render Stats
|
|
660
|
+
function renderStats(stats) {
|
|
661
|
+
const grid = document.getElementById('stats-grid');
|
|
662
|
+
grid.innerHTML = `
|
|
663
|
+
<div class="stat-card">
|
|
664
|
+
<div class="stat-icon">💭</div>
|
|
665
|
+
<div class="stat-value">${stats.layers.session?.count || 0}</div>
|
|
666
|
+
<div class="stat-label">Session Context</div>
|
|
667
|
+
</div>
|
|
668
|
+
<div class="stat-card">
|
|
669
|
+
<div class="stat-icon">📅</div>
|
|
670
|
+
<div class="stat-value">${stats.layers.daily?.count || 0}</div>
|
|
671
|
+
<div class="stat-label">Daily Logs</div>
|
|
672
|
+
</div>
|
|
673
|
+
<div class="stat-card">
|
|
674
|
+
<div class="stat-icon">🧠</div>
|
|
675
|
+
<div class="stat-value">${stats.layers.longterm?.exists ? '✓' : '✗'}</div>
|
|
676
|
+
<div class="stat-label">Long-term Memory</div>
|
|
677
|
+
</div>
|
|
678
|
+
<div class="stat-card">
|
|
679
|
+
<div class="stat-icon">📚</div>
|
|
680
|
+
<div class="stat-value">${stats.layers.index?.exists ? '✓' : '✗'}</div>
|
|
681
|
+
<div class="stat-label">Memory Index</div>
|
|
682
|
+
</div>
|
|
683
|
+
<div class="stat-card">
|
|
684
|
+
<div class="stat-icon">📝</div>
|
|
685
|
+
<div class="stat-value">${stats.layers.logs?.count || 0}</div>
|
|
686
|
+
<div class="stat-label">Action Logs</div>
|
|
687
|
+
</div>
|
|
688
|
+
`;
|
|
689
|
+
|
|
690
|
+
// Update category counts
|
|
691
|
+
document.getElementById('count-gotcha').textContent = stats.categories?.gotcha || 0;
|
|
692
|
+
document.getElementById('count-problem').textContent = stats.categories?.problem || 0;
|
|
693
|
+
document.getElementById('count-decision').textContent = stats.categories?.decision || 0;
|
|
694
|
+
document.getElementById('count-discovery').textContent = stats.categories?.discovery || 0;
|
|
695
|
+
document.getElementById('count-all').textContent = stats.totalEntries || 0;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// Load Memories
|
|
699
|
+
async function loadMemories() {
|
|
700
|
+
try {
|
|
701
|
+
const response = await fetch('/api/entries');
|
|
702
|
+
const data = await response.json();
|
|
703
|
+
memories = data.entries || [];
|
|
704
|
+
renderMemories(memories);
|
|
705
|
+
} catch (error) {
|
|
706
|
+
console.error('Failed to load memories:', error);
|
|
707
|
+
document.getElementById('memory-list').innerHTML = `
|
|
708
|
+
<div class="empty-state">
|
|
709
|
+
<div class="empty-icon">❌</div>
|
|
710
|
+
<p>Failed to load memories</p>
|
|
711
|
+
</div>
|
|
712
|
+
`;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// Render Memories
|
|
717
|
+
function renderMemories(entries) {
|
|
718
|
+
const list = document.getElementById('memory-list');
|
|
719
|
+
document.getElementById('memories-count').textContent = `${entries.length} memories`;
|
|
720
|
+
|
|
721
|
+
if (entries.length === 0) {
|
|
722
|
+
list.innerHTML = `
|
|
723
|
+
<div class="empty-state">
|
|
724
|
+
<div class="empty-icon">📝</div>
|
|
725
|
+
<p>No memories found</p>
|
|
726
|
+
<p style="font-size: 0.875rem; margin-top: 0.5rem;">
|
|
727
|
+
Use <code>super-memory save "your memory"</code> to add one
|
|
728
|
+
</p>
|
|
729
|
+
</div>
|
|
730
|
+
`;
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
list.innerHTML = entries.map(entry => `
|
|
735
|
+
<div class="memory-item" onclick="openModal('${entry.id}')">
|
|
736
|
+
<div class="memory-header">
|
|
737
|
+
<span class="memory-category">
|
|
738
|
+
${getCategoryEmoji(entry.category)} ${entry.category}
|
|
739
|
+
</span>
|
|
740
|
+
<span class="memory-date">${formatDate(entry.date)}</span>
|
|
741
|
+
</div>
|
|
742
|
+
<div class="memory-content">${escapeHtml(entry.preview || entry.content)}</div>
|
|
743
|
+
<div class="memory-layer">Layer ${entry.layer} • ${entry.source || 'Unknown'}</div>
|
|
744
|
+
</div>
|
|
745
|
+
`).join('');
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Search
|
|
749
|
+
async function handleSearch(event) {
|
|
750
|
+
if (event.key === 'Enter') {
|
|
751
|
+
const query = event.target.value;
|
|
752
|
+
if (!query) {
|
|
753
|
+
renderMemories(memories);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
try {
|
|
758
|
+
const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
|
|
759
|
+
const results = await response.json();
|
|
760
|
+
renderMemories(results);
|
|
761
|
+
} catch (error) {
|
|
762
|
+
console.error('Search failed:', error);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Filter Category
|
|
768
|
+
function filterCategory(category) {
|
|
769
|
+
currentCategory = category;
|
|
770
|
+
|
|
771
|
+
// Update UI
|
|
772
|
+
document.querySelectorAll('.category-item').forEach(item => {
|
|
773
|
+
item.classList.remove('active');
|
|
774
|
+
});
|
|
775
|
+
event.currentTarget.classList.add('active');
|
|
776
|
+
|
|
777
|
+
// Filter memories
|
|
778
|
+
if (category === 'all') {
|
|
779
|
+
renderMemories(memories);
|
|
780
|
+
} else {
|
|
781
|
+
const filtered = memories.filter(m => m.category === category);
|
|
782
|
+
renderMemories(filtered);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Open Modal
|
|
787
|
+
async function openModal(id) {
|
|
788
|
+
try {
|
|
789
|
+
const response = await fetch(`/api/memory/${id}`);
|
|
790
|
+
const memory = await response.json();
|
|
791
|
+
|
|
792
|
+
document.getElementById('modal-title').textContent =
|
|
793
|
+
`${getCategoryEmoji(memory.category)} ${memory.category}`;
|
|
794
|
+
document.getElementById('modal-content').textContent = memory.content;
|
|
795
|
+
|
|
796
|
+
const catBtn = document.getElementById('modal-categorize-btn');
|
|
797
|
+
catBtn.onclick = () => runCategorize(id);
|
|
798
|
+
|
|
799
|
+
document.getElementById('modal').classList.add('active');
|
|
800
|
+
} catch (error) {
|
|
801
|
+
console.error('Failed to load memory:', error);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Close Modal
|
|
806
|
+
function closeModal(event) {
|
|
807
|
+
if (!event || event.target === document.getElementById('modal')) {
|
|
808
|
+
document.getElementById('modal').classList.remove('active');
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// Export
|
|
813
|
+
function exportData() {
|
|
814
|
+
window.location.href = '/api/export';
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// Refresh
|
|
818
|
+
function refreshData() {
|
|
819
|
+
loadStats();
|
|
820
|
+
loadMemories();
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Helpers
|
|
824
|
+
function getCategoryEmoji(category) {
|
|
825
|
+
const emojis = {
|
|
826
|
+
gotcha: '🔴',
|
|
827
|
+
problem: '🟡',
|
|
828
|
+
decision: '🟤',
|
|
829
|
+
discovery: '🟣'
|
|
830
|
+
};
|
|
831
|
+
return emojis[category] || '⚪';
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
function formatDate(dateStr) {
|
|
835
|
+
if (!dateStr) return 'Unknown';
|
|
836
|
+
const date = new Date(dateStr);
|
|
837
|
+
return date.toLocaleDateString('en-US', {
|
|
838
|
+
year: 'numeric',
|
|
839
|
+
month: 'short',
|
|
840
|
+
day: 'numeric'
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
function escapeHtml(text) {
|
|
845
|
+
const div = document.createElement('div');
|
|
846
|
+
div.textContent = text;
|
|
847
|
+
return div.innerHTML;
|
|
848
|
+
}
|
|
849
|
+
</script>
|
|
850
|
+
</body>
|
|
851
|
+
</html>
|