claude-memory-layer 1.0.8 → 1.0.9

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.
Files changed (43) hide show
  1. package/.claude/settings.local.json +7 -1
  2. package/.claude-memory/test.sqlite +0 -0
  3. package/.history/package_20260202114053.json +49 -0
  4. package/HANDOFF.md +92 -0
  5. package/dist/cli/index.js +1150 -71
  6. package/dist/cli/index.js.map +4 -4
  7. package/dist/core/index.js +1033 -47
  8. package/dist/core/index.js.map +4 -4
  9. package/dist/hooks/post-tool-use.js +5589 -0
  10. package/dist/hooks/post-tool-use.js.map +7 -0
  11. package/dist/hooks/session-end.js +1117 -64
  12. package/dist/hooks/session-end.js.map +4 -4
  13. package/dist/hooks/session-start.js +1112 -63
  14. package/dist/hooks/session-start.js.map +4 -4
  15. package/dist/hooks/stop.js +1117 -64
  16. package/dist/hooks/stop.js.map +4 -4
  17. package/dist/hooks/user-prompt-submit.js +1151 -67
  18. package/dist/hooks/user-prompt-submit.js.map +4 -4
  19. package/dist/server/api/index.js +1145 -70
  20. package/dist/server/api/index.js.map +4 -4
  21. package/dist/server/index.js +1145 -70
  22. package/dist/server/index.js.map +4 -4
  23. package/dist/services/memory-service.js +1122 -65
  24. package/dist/services/memory-service.js.map +4 -4
  25. package/dist/ui/app.js +304 -0
  26. package/dist/ui/index.html +195 -1188
  27. package/dist/ui/style.css +595 -0
  28. package/package.json +3 -1
  29. package/scripts/build.ts +2 -0
  30. package/src/core/event-store.ts +18 -0
  31. package/src/core/index.ts +3 -0
  32. package/src/core/retriever.ts +4 -1
  33. package/src/core/sqlite-event-store.ts +849 -0
  34. package/src/core/sqlite-wrapper.ts +108 -0
  35. package/src/core/sync-worker.ts +228 -0
  36. package/src/core/vector-worker.ts +44 -14
  37. package/src/hooks/user-prompt-submit.ts +53 -4
  38. package/src/server/api/stats.ts +37 -7
  39. package/src/services/memory-service.ts +168 -39
  40. package/src/ui/app.js +304 -0
  41. package/src/ui/index.html +195 -1188
  42. package/src/ui/style.css +595 -0
  43. package/test_access.js +49 -0
@@ -0,0 +1,595 @@
1
+ /*
2
+ Theme: Deep Space (Premium Dark Mode)
3
+ Font: Outfit
4
+ */
5
+ @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap');
6
+
7
+ :root {
8
+ /* Core Palette */
9
+ --bg-dark: #05050A; /* Deepest black/blue */
10
+ --bg-panel: #0F1019; /* Slightly lighter for panels */
11
+ --bg-card: rgba(22, 23, 35, 0.7); /* Glassy card background */
12
+
13
+ /* Accents */
14
+ --accent-primary: #7B61FF; /* Soft Electric Purple */
15
+ --accent-secondary: #00F0FF; /* Cyber Blue */
16
+ --accent-glow: rgba(123, 97, 255, 0.4);
17
+
18
+ /* Status Colors */
19
+ --success: #00E396;
20
+ --warning: #FEB019;
21
+ --error: #FF4560;
22
+
23
+ /* Text */
24
+ --text-primary: #FFFFFF;
25
+ --text-secondary: #8B9BB4;
26
+ --text-muted: #53627C;
27
+
28
+ /* Borders & Effects */
29
+ --border-subtle: rgba(255, 255, 255, 0.08);
30
+ --glass-border: 1px solid rgba(255, 255, 255, 0.05);
31
+ --glass-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
32
+ --backdrop-blur: blur(12px);
33
+
34
+ /* Spacing */
35
+ --sidebar-width: 260px;
36
+ --header-height: 80px;
37
+ }
38
+
39
+ * {
40
+ margin: 0;
41
+ padding: 0;
42
+ box-sizing: border-box;
43
+ }
44
+
45
+ body {
46
+ font-family: 'Outfit', sans-serif;
47
+ background-color: var(--bg-dark);
48
+ color: var(--text-primary);
49
+ min-height: 100vh;
50
+ overflow-x: hidden;
51
+ background-image:
52
+ radial-gradient(circle at 10% 10%, rgba(123, 97, 255, 0.05) 0%, transparent 40%),
53
+ radial-gradient(circle at 90% 90%, rgba(0, 240, 255, 0.05) 0%, transparent 40%);
54
+ }
55
+
56
+ /* Scrollbar */
57
+ ::-webkit-scrollbar {
58
+ width: 6px;
59
+ height: 6px;
60
+ }
61
+ ::-webkit-scrollbar-track {
62
+ background: var(--bg-dark);
63
+ }
64
+ ::-webkit-scrollbar-thumb {
65
+ background: var(--border-subtle);
66
+ border-radius: 3px;
67
+ }
68
+ ::-webkit-scrollbar-thumb:hover {
69
+ background: var(--text-muted);
70
+ }
71
+
72
+ /* Layout */
73
+ .app-container {
74
+ display: flex;
75
+ min-height: 100vh;
76
+ }
77
+
78
+ /* Sidebar */
79
+ .sidebar {
80
+ width: var(--sidebar-width);
81
+ background: var(--bg-panel);
82
+ border-right: var(--glass-border);
83
+ padding: 24px;
84
+ display: flex;
85
+ flex-direction: column;
86
+ position: fixed;
87
+ height: 100vh;
88
+ z-index: 100;
89
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
90
+ }
91
+
92
+ .logo-area {
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 12px;
96
+ margin-bottom: 40px;
97
+ padding-left: 12px;
98
+ }
99
+
100
+ .logo-icon {
101
+ font-size: 24px;
102
+ filter: drop-shadow(0 0 8px var(--accent-glow));
103
+ }
104
+
105
+ .logo-text {
106
+ font-size: 20px;
107
+ font-weight: 700;
108
+ background: linear-gradient(135deg, #FFF 0%, #A5B4FC 100%);
109
+ -webkit-background-clip: text;
110
+ -webkit-text-fill-color: transparent;
111
+ }
112
+
113
+ .nav-menu {
114
+ list-style: none;
115
+ display: flex;
116
+ flex-direction: column;
117
+ gap: 8px;
118
+ }
119
+
120
+ .nav-item {
121
+ display: flex;
122
+ align-items: center;
123
+ gap: 12px;
124
+ padding: 14px 16px;
125
+ border-radius: 12px;
126
+ color: var(--text-secondary);
127
+ text-decoration: none;
128
+ font-weight: 500;
129
+ transition: all 0.2s ease;
130
+ cursor: pointer;
131
+ }
132
+
133
+ .nav-item:hover {
134
+ background: rgba(255, 255, 255, 0.03);
135
+ color: var(--text-primary);
136
+ }
137
+
138
+ .nav-item.active {
139
+ background: rgba(123, 97, 255, 0.1);
140
+ color: var(--accent-primary);
141
+ border: 1px solid rgba(123, 97, 255, 0.1);
142
+ }
143
+
144
+ .nav-item i {
145
+ font-size: 1.2rem;
146
+ }
147
+
148
+ /* Main Content */
149
+ .main-content {
150
+ flex: 1;
151
+ margin-left: var(--sidebar-width);
152
+ padding: 32px 40px;
153
+ }
154
+
155
+ /* Header */
156
+ .top-header {
157
+ display: flex;
158
+ justify-content: space-between;
159
+ align-items: center;
160
+ margin-bottom: 32px;
161
+ }
162
+
163
+ .page-title h1 {
164
+ font-size: 28px;
165
+ font-weight: 600;
166
+ letter-spacing: -0.5px;
167
+ }
168
+
169
+ .page-title p {
170
+ color: var(--text-secondary);
171
+ font-size: 14px;
172
+ margin-top: 4px;
173
+ }
174
+
175
+ .header-actions {
176
+ display: flex;
177
+ gap: 16px;
178
+ align-items: center;
179
+ }
180
+
181
+ .btn {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: 8px;
185
+ padding: 10px 20px;
186
+ border-radius: 10px;
187
+ font-family: inherit;
188
+ font-weight: 600;
189
+ font-size: 14px;
190
+ cursor: pointer;
191
+ transition: all 0.2s ease;
192
+ border: none;
193
+ outline: none;
194
+ }
195
+
196
+ .btn-primary {
197
+ background: linear-gradient(135deg, var(--accent-primary) 0%, #6343E0 100%);
198
+ color: white;
199
+ box-shadow: 0 4px 12px var(--accent-glow);
200
+ }
201
+
202
+ .btn-primary:hover {
203
+ transform: translateY(-2px);
204
+ box-shadow: 0 6px 16px var(--accent-glow);
205
+ }
206
+
207
+ .btn-secondary {
208
+ background: rgba(255, 255, 255, 0.05);
209
+ color: var(--text-primary);
210
+ border: 1px solid rgba(255, 255, 255, 0.1);
211
+ }
212
+
213
+ .btn-secondary:hover {
214
+ background: rgba(255, 255, 255, 0.1);
215
+ }
216
+
217
+ .search-wrapper {
218
+ position: relative;
219
+ width: 300px;
220
+ }
221
+
222
+ .search-wrapper i {
223
+ position: absolute;
224
+ left: 14px;
225
+ top: 50%;
226
+ transform: translateY(-50%);
227
+ color: var(--text-secondary);
228
+ }
229
+
230
+ .search-input {
231
+ width: 100%;
232
+ padding: 12px 14px 12px 40px;
233
+ background: var(--bg-panel);
234
+ border: var(--glass-border);
235
+ border-radius: 10px;
236
+ color: var(--text-primary);
237
+ font-family: inherit;
238
+ transition: all 0.2s;
239
+ }
240
+
241
+ .search-input:focus {
242
+ outline: none;
243
+ border-color: var(--accent-primary);
244
+ box-shadow: 0 0 0 2px rgba(123, 97, 255, 0.1);
245
+ }
246
+
247
+ /* Stats Grid */
248
+ .stats-grid {
249
+ display: grid;
250
+ grid-template-columns: repeat(4, 1fr);
251
+ gap: 24px;
252
+ margin-bottom: 32px;
253
+ }
254
+
255
+ .stat-card {
256
+ background: var(--bg-card);
257
+ backdrop-filter: var(--backdrop-blur);
258
+ border: var(--glass-border);
259
+ padding: 24px;
260
+ border-radius: 16px;
261
+ position: relative;
262
+ overflow: hidden;
263
+ transition: transform 0.2s;
264
+ }
265
+
266
+ .stat-card:hover {
267
+ transform: translateY(-4px);
268
+ }
269
+
270
+ .stat-card::before {
271
+ content: '';
272
+ position: absolute;
273
+ top: 0;
274
+ left: 0;
275
+ width: 100%;
276
+ height: 4px;
277
+ background: linear-gradient(90deg, var(--accent-primary), transparent);
278
+ opacity: 0.5;
279
+ }
280
+
281
+ .stat-value {
282
+ font-size: 36px;
283
+ font-weight: 700;
284
+ margin-bottom: 8px;
285
+ background: linear-gradient(180deg, #FFF 0%, #E0E0E0 100%);
286
+ -webkit-background-clip: text;
287
+ -webkit-text-fill-color: transparent;
288
+ }
289
+
290
+ .stat-label {
291
+ color: var(--text-secondary);
292
+ font-size: 13px;
293
+ text-transform: uppercase;
294
+ letter-spacing: 1px;
295
+ display: flex;
296
+ align-items: center;
297
+ gap: 8px;
298
+ }
299
+
300
+ /* Content Grid */
301
+ .dashboard-grid {
302
+ display: grid;
303
+ grid-template-columns: 2fr 1fr;
304
+ gap: 24px;
305
+ }
306
+
307
+ /* Card Common */
308
+ .card {
309
+ background: var(--bg-card);
310
+ border: var(--glass-border);
311
+ border-radius: 16px;
312
+ padding: 24px;
313
+ margin-bottom: 24px;
314
+ }
315
+
316
+ .card-header {
317
+ display: flex;
318
+ justify-content: space-between;
319
+ align-items: center;
320
+ margin-bottom: 20px;
321
+ }
322
+
323
+ .card-title {
324
+ font-size: 18px;
325
+ font-weight: 600;
326
+ display: flex;
327
+ align-items: center;
328
+ gap: 10px;
329
+ }
330
+
331
+ .card-title i {
332
+ color: var(--accent-primary);
333
+ }
334
+
335
+ /* Memory Pipeline */
336
+ .pipeline-container {
337
+ position: relative;
338
+ padding: 20px 0;
339
+ }
340
+
341
+ .pipeline-steps {
342
+ display: flex;
343
+ justify-content: space-between;
344
+ position: relative;
345
+ }
346
+
347
+ .pipeline-steps::before {
348
+ content: '';
349
+ position: absolute;
350
+ top: 50%;
351
+ left: 0;
352
+ width: 100%;
353
+ height: 2px;
354
+ background: var(--bg-panel);
355
+ z-index: 0;
356
+ transform: translateY(-50%);
357
+ }
358
+
359
+ .p-step {
360
+ position: relative;
361
+ z-index: 1;
362
+ background: var(--bg-panel);
363
+ border: 1px solid var(--border-subtle);
364
+ padding: 12px 24px;
365
+ border-radius: 12px;
366
+ display: flex;
367
+ flex-direction: column;
368
+ align-items: center;
369
+ gap: 6px;
370
+ cursor: pointer;
371
+ transition: all 0.3s;
372
+ min-width: 120px;
373
+ }
374
+
375
+ .p-step.active {
376
+ background: rgba(123, 97, 255, 0.1);
377
+ border-color: var(--accent-primary);
378
+ box-shadow: 0 0 20px rgba(123, 97, 255, 0.15);
379
+ }
380
+
381
+ .p-step-name {
382
+ font-weight: 600;
383
+ font-size: 14px;
384
+ }
385
+
386
+ .p-step-count {
387
+ font-size: 12px;
388
+ color: var(--text-secondary);
389
+ }
390
+
391
+ .p-step.active .p-step-name {
392
+ color: var(--accent-primary);
393
+ }
394
+
395
+ .p-step.active .p-step-count {
396
+ color: var(--text-primary);
397
+ }
398
+
399
+ /* Event List */
400
+ .event-list {
401
+ display: flex;
402
+ flex-direction: column;
403
+ gap: 12px;
404
+ max-height: 500px;
405
+ overflow-y: auto;
406
+ padding-right: 8px;
407
+ }
408
+
409
+ .event-item {
410
+ background: rgba(255, 255, 255, 0.02);
411
+ border: 1px solid transparent;
412
+ padding: 16px;
413
+ border-radius: 10px;
414
+ transition: all 0.2s;
415
+ }
416
+
417
+ .event-item:hover {
418
+ background: rgba(255, 255, 255, 0.04);
419
+ border-color: var(--border-subtle);
420
+ }
421
+
422
+ .event-header {
423
+ display: flex;
424
+ justify-content: space-between;
425
+ margin-bottom: 8px;
426
+ }
427
+
428
+ .event-type-badge {
429
+ font-size: 11px;
430
+ padding: 4px 8px;
431
+ border-radius: 6px;
432
+ font-weight: 600;
433
+ text-transform: uppercase;
434
+ }
435
+
436
+ .type-user { background: rgba(59, 130, 246, 0.2); color: #60A5FA; }
437
+ .type-agent { background: rgba(16, 185, 129, 0.2); color: #34D399; }
438
+ .type-tool { background: rgba(245, 158, 11, 0.2); color: #FBBF24; }
439
+ .type-system { background: rgba(139, 92, 246, 0.2); color: #A78BFA; }
440
+
441
+ .event-time {
442
+ font-size: 12px;
443
+ color: var(--text-muted);
444
+ }
445
+
446
+ .event-content {
447
+ font-size: 14px;
448
+ color: var(--text-secondary);
449
+ line-height: 1.5;
450
+ display: -webkit-box;
451
+ -webkit-line-clamp: 2;
452
+ -webkit-box-orient: vertical;
453
+ overflow: hidden;
454
+ }
455
+
456
+ /* Shared Items */
457
+ .shared-list {
458
+ display: flex;
459
+ flex-direction: column;
460
+ gap: 12px;
461
+ }
462
+
463
+ .shared-item {
464
+ display: flex;
465
+ align-items: center;
466
+ justify-content: space-between;
467
+ padding: 16px;
468
+ background: var(--bg-panel);
469
+ border-radius: 10px;
470
+ }
471
+
472
+ .shared-info {
473
+ display: flex;
474
+ align-items: center;
475
+ gap: 12px;
476
+ }
477
+
478
+ .shared-icon {
479
+ width: 40px;
480
+ height: 40px;
481
+ background: rgba(255, 255, 255, 0.05);
482
+ border-radius: 8px;
483
+ display: flex;
484
+ align-items: center;
485
+ justify-content: center;
486
+ font-size: 18px;
487
+ }
488
+
489
+ .shared-count {
490
+ font-family: monospace;
491
+ font-size: 16px;
492
+ font-weight: 700;
493
+ color: var(--accent-secondary);
494
+ }
495
+
496
+ /* Endless Mode */
497
+ .endless-card {
498
+ background: linear-gradient(135deg, rgba(16, 16, 24, 0.6) 0%, rgba(20, 20, 30, 0.6) 100%);
499
+ position: relative;
500
+ overflow: hidden;
501
+ }
502
+
503
+ .endless-card::after {
504
+ content: '';
505
+ position: absolute;
506
+ top: 0;
507
+ right: 0;
508
+ width: 150px;
509
+ height: 150px;
510
+ background: radial-gradient(circle, rgba(123, 97, 255, 0.1) 0%, transparent 70%);
511
+ pointer-events: none;
512
+ }
513
+
514
+ .status-dot {
515
+ width: 8px;
516
+ height: 8px;
517
+ border-radius: 50%;
518
+ background: var(--text-muted);
519
+ box-shadow: 0 0 0 2px rgba(255,255,255,0.05);
520
+ }
521
+
522
+ .status-dot.active {
523
+ background: var(--success);
524
+ box-shadow: 0 0 0 4px rgba(0, 227, 150, 0.1);
525
+ animation: pulse 2s infinite;
526
+ }
527
+
528
+ @keyframes pulse {
529
+ 0% { box-shadow: 0 0 0 0 rgba(0, 227, 150, 0.4); }
530
+ 70% { box-shadow: 0 0 0 10px rgba(0, 227, 150, 0); }
531
+ 100% { box-shadow: 0 0 0 0 rgba(0, 227, 150, 0); }
532
+ }
533
+
534
+ /* Chart Container Overrides */
535
+ .apexcharts-tooltip {
536
+ background: var(--bg-panel) !important;
537
+ border-color: var(--border-subtle) !important;
538
+ color: var(--text-primary) !important;
539
+ box-shadow: var(--glass-shadow) !important;
540
+ }
541
+
542
+ .apexcharts-tooltip-title {
543
+ background: var(--bg-dark) !important;
544
+ border-bottom: 1px solid var(--border-subtle) !important;
545
+ font-family: 'Outfit', sans-serif !important;
546
+ }
547
+
548
+ .apexcharts-text {
549
+ fill: var(--text-muted) !important;
550
+ font-family: 'Outfit', sans-serif !important;
551
+ }
552
+
553
+ .apexcharts-gridline {
554
+ stroke: var(--border-subtle) !important;
555
+ }
556
+
557
+ /* Mobile Responsive */
558
+ @media (max-width: 1024px) {
559
+ .sidebar {
560
+ transform: translateX(-100%);
561
+ }
562
+
563
+ .sidebar.mobile-open {
564
+ transform: translateX(0);
565
+ }
566
+
567
+ .main-content {
568
+ margin-left: 0;
569
+ padding: 20px;
570
+ }
571
+ .stats-grid {
572
+ grid-template-columns: repeat(2, 1fr);
573
+ }
574
+ .dashboard-grid {
575
+ grid-template-columns: 1fr;
576
+ }
577
+ }
578
+
579
+ @media (max-width: 600px) {
580
+ .stats-grid {
581
+ grid-template-columns: 1fr;
582
+ }
583
+ .pipeline-steps {
584
+ flex-direction: column;
585
+ gap: 12px;
586
+ }
587
+ .pipeline-steps::before {
588
+ display: none;
589
+ }
590
+ .p-step {
591
+ width: 100%;
592
+ flex-direction: row;
593
+ justify-content: space-between;
594
+ }
595
+ }
package/test_access.js ADDED
@@ -0,0 +1,49 @@
1
+ const { SQLiteEventStore } = require('./dist/cli/index.js');
2
+ const path = require('path');
3
+
4
+ async function test() {
5
+ const dbPath = path.join(process.cwd(), '.claude-memory', 'test.sqlite');
6
+ const store = new SQLiteEventStore(dbPath);
7
+
8
+ await store.initialize();
9
+
10
+ // Add some test events
11
+ const event1 = {
12
+ eventType: 'user_prompt',
13
+ sessionId: 'test-session',
14
+ content: 'Test content about DuckDB implementation',
15
+ metadata: {}
16
+ };
17
+
18
+ const event2 = {
19
+ eventType: 'agent_response',
20
+ sessionId: 'test-session',
21
+ content: 'Response about memory tracking and access counts',
22
+ metadata: {}
23
+ };
24
+
25
+ const result1 = await store.append(event1);
26
+ const result2 = await store.append(event2);
27
+
28
+ console.log('Added events:', result1.eventId, result2.eventId);
29
+
30
+ // Now increment access counts
31
+ if (result1.eventId && result2.eventId) {
32
+ await store.incrementAccessCount([result1.eventId]);
33
+ await store.incrementAccessCount([result1.eventId]);
34
+ await store.incrementAccessCount([result2.eventId]);
35
+
36
+ console.log('Incremented access counts');
37
+
38
+ // Get most accessed
39
+ const mostAccessed = await store.getMostAccessed(5);
40
+ console.log('Most accessed events:');
41
+ mostAccessed.forEach(e => {
42
+ console.log(`- ${e.id}: ${e.access_count} accesses - ${e.content.substring(0, 50)}...`);
43
+ });
44
+ }
45
+
46
+ await store.close();
47
+ }
48
+
49
+ test().catch(console.error);