ocerebro 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,579 @@
1
+ /* Dashboard do OCerebro - Tema Escuro */
2
+
3
+ :root {
4
+ /* Cores principais */
5
+ --bg-primary: #0F172A; /* slate-900 */
6
+ --bg-secondary: #1E293B; /* slate-800 */
7
+ --bg-tertiary: #334155; /* slate-700 */
8
+ --text-primary: #F1F5F9; /* slate-100 */
9
+ --text-secondary: #94A3B8; /* slate-400 */
10
+ --accent: #6366F1; /* indigo-500 */
11
+ --accent-hover: #4F46E5; /* indigo-600 */
12
+
13
+ /* Cores dos tipos de entidade */
14
+ --color-project: #3B82F6; /* azul */
15
+ --color-tech: #10B981; /* verde */
16
+ --color-person: #F59E0B; /* laranja */
17
+ --color-tag: #6B7280; /* cinza */
18
+ --color-meta: #8B5CF6; /* roxo */
19
+ --color-org: #EF4444; /* vermelho */
20
+
21
+ /* Bordas */
22
+ --border-color: #334155; /* slate-700 */
23
+ --border-radius: 8px;
24
+
25
+ /* Shadows */
26
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
27
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);
28
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
29
+ }
30
+
31
+ * {
32
+ margin: 0;
33
+ padding: 0;
34
+ box-sizing: border-box;
35
+ }
36
+
37
+ body {
38
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
39
+ background-color: var(--bg-primary);
40
+ color: var(--text-primary);
41
+ line-height: 1.6;
42
+ min-height: 100vh;
43
+ }
44
+
45
+ /* Header */
46
+ header {
47
+ background-color: var(--bg-secondary);
48
+ border-bottom: 1px solid var(--border-color);
49
+ padding: 1rem 2rem;
50
+ display: flex;
51
+ justify-content: space-between;
52
+ align-items: center;
53
+ position: sticky;
54
+ top: 0;
55
+ z-index: 100;
56
+ }
57
+
58
+ .logo {
59
+ font-size: 1.5rem;
60
+ font-weight: bold;
61
+ display: flex;
62
+ align-items: center;
63
+ gap: 0.5rem;
64
+ }
65
+
66
+ .status-dot {
67
+ width: 10px;
68
+ height: 10px;
69
+ border-radius: 50%;
70
+ background-color: #10B981;
71
+ animation: pulse 2s infinite;
72
+ }
73
+
74
+ .status-dot.offline {
75
+ background-color: #EF4444;
76
+ animation: none;
77
+ }
78
+
79
+ @keyframes pulse {
80
+ 0%, 100% { opacity: 1; }
81
+ 50% { opacity: 0.5; }
82
+ }
83
+
84
+ /* Tabs de navegação */
85
+ .tabs {
86
+ display: flex;
87
+ gap: 0.5rem;
88
+ background-color: var(--bg-secondary);
89
+ padding: 0.5rem 2rem;
90
+ border-bottom: 1px solid var(--border-color);
91
+ }
92
+
93
+ .tab-btn {
94
+ background: none;
95
+ border: none;
96
+ color: var(--text-secondary);
97
+ padding: 0.75rem 1.5rem;
98
+ cursor: pointer;
99
+ font-size: 0.95rem;
100
+ border-radius: var(--border-radius) var(--border-radius) 0 0;
101
+ transition: all 0.2s;
102
+ }
103
+
104
+ .tab-btn:hover {
105
+ color: var(--text-primary);
106
+ background-color: var(--bg-tertiary);
107
+ }
108
+
109
+ .tab-btn.active {
110
+ color: var(--text-primary);
111
+ background-color: var(--bg-primary);
112
+ border-bottom: 2px solid var(--accent);
113
+ }
114
+
115
+ /* Conteúdo principal */
116
+ main {
117
+ padding: 2rem;
118
+ max-width: 1600px;
119
+ margin: 0 auto;
120
+ }
121
+
122
+ .tab-content {
123
+ display: none;
124
+ }
125
+
126
+ .tab-content.active {
127
+ display: block;
128
+ }
129
+
130
+ /* Cards de status */
131
+ .status-grid {
132
+ display: grid;
133
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
134
+ gap: 1.5rem;
135
+ margin-bottom: 2rem;
136
+ }
137
+
138
+ .status-card {
139
+ background-color: var(--bg-secondary);
140
+ border: 1px solid var(--border-color);
141
+ border-radius: var(--border-radius);
142
+ padding: 1.5rem;
143
+ text-align: center;
144
+ box-shadow: var(--shadow-sm);
145
+ }
146
+
147
+ .status-card h3 {
148
+ color: var(--text-secondary);
149
+ font-size: 0.875rem;
150
+ text-transform: uppercase;
151
+ letter-spacing: 0.05em;
152
+ margin-bottom: 0.5rem;
153
+ }
154
+
155
+ .status-card .value {
156
+ font-size: 2.5rem;
157
+ font-weight: bold;
158
+ color: var(--accent);
159
+ }
160
+
161
+ /* Grid de projetos */
162
+ .projects-grid {
163
+ display: grid;
164
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
165
+ gap: 1.5rem;
166
+ }
167
+
168
+ .project-card {
169
+ background-color: var(--bg-secondary);
170
+ border: 1px solid var(--border-color);
171
+ border-radius: var(--border-radius);
172
+ padding: 1.5rem;
173
+ cursor: pointer;
174
+ transition: all 0.2s;
175
+ box-shadow: var(--shadow-sm);
176
+ }
177
+
178
+ .project-card:hover {
179
+ border-color: var(--accent);
180
+ transform: translateY(-2px);
181
+ box-shadow: var(--shadow-md);
182
+ }
183
+
184
+ .project-card h3 {
185
+ font-size: 1.25rem;
186
+ margin-bottom: 0.75rem;
187
+ color: var(--text-primary);
188
+ }
189
+
190
+ .project-stats {
191
+ display: flex;
192
+ flex-wrap: wrap;
193
+ gap: 0.5rem;
194
+ }
195
+
196
+ .badge {
197
+ display: inline-flex;
198
+ align-items: center;
199
+ padding: 0.25rem 0.75rem;
200
+ border-radius: 9999px;
201
+ font-size: 0.75rem;
202
+ font-weight: 500;
203
+ }
204
+
205
+ .badge-decision { background-color: #3B82F633; color: #3B82F6; }
206
+ .badge-error { background-color: #EF444433; color: #EF4444; }
207
+ .badge-reference { background-color: #10B98133; color: #10B981; }
208
+ .badge-feedback { background-color: #F59E0B33; color: #F59E0B; }
209
+
210
+ /* Grafo */
211
+ .graph-container {
212
+ display: grid;
213
+ grid-template-columns: 1fr 350px;
214
+ gap: 1.5rem;
215
+ height: calc(100vh - 200px);
216
+ min-height: 500px;
217
+ }
218
+
219
+ #cy {
220
+ background-color: var(--bg-secondary);
221
+ border: 1px solid var(--border-color);
222
+ border-radius: var(--border-radius);
223
+ box-shadow: var(--shadow-sm);
224
+ }
225
+
226
+ .graph-panel {
227
+ background-color: var(--bg-secondary);
228
+ border: 1px solid var(--border-color);
229
+ border-radius: var(--border-radius);
230
+ padding: 1.5rem;
231
+ display: flex;
232
+ flex-direction: column;
233
+ gap: 1rem;
234
+ overflow-y: auto;
235
+ }
236
+
237
+ .graph-controls {
238
+ display: flex;
239
+ flex-direction: column;
240
+ gap: 0.75rem;
241
+ padding-bottom: 1rem;
242
+ border-bottom: 1px solid var(--border-color);
243
+ }
244
+
245
+ .graph-controls label {
246
+ display: flex;
247
+ align-items: center;
248
+ gap: 0.5rem;
249
+ font-size: 0.875rem;
250
+ color: var(--text-secondary);
251
+ }
252
+
253
+ .node-details {
254
+ flex: 1;
255
+ overflow-y: auto;
256
+ }
257
+
258
+ .node-details h3 {
259
+ font-size: 1.25rem;
260
+ margin-bottom: 0.5rem;
261
+ }
262
+
263
+ .node-details .type {
264
+ font-size: 0.875rem;
265
+ color: var(--text-secondary);
266
+ margin-bottom: 1rem;
267
+ }
268
+
269
+ .node-details .related-memories {
270
+ margin-top: 1rem;
271
+ }
272
+
273
+ .node-details .related-memories h4 {
274
+ font-size: 0.875rem;
275
+ color: var(--text-secondary);
276
+ margin-bottom: 0.5rem;
277
+ }
278
+
279
+ .memory-link {
280
+ display: block;
281
+ padding: 0.5rem;
282
+ background-color: var(--bg-tertiary);
283
+ border-radius: var(--border-radius);
284
+ color: var(--text-primary);
285
+ text-decoration: none;
286
+ margin-bottom: 0.5rem;
287
+ font-size: 0.875rem;
288
+ transition: background-color 0.2s;
289
+ }
290
+
291
+ .memory-link:hover {
292
+ background-color: var(--accent);
293
+ }
294
+
295
+ /* Memórias */
296
+ .memories-controls {
297
+ display: flex;
298
+ gap: 1rem;
299
+ margin-bottom: 1.5rem;
300
+ flex-wrap: wrap;
301
+ }
302
+
303
+ .search-input {
304
+ flex: 1;
305
+ min-width: 200px;
306
+ padding: 0.75rem 1rem;
307
+ background-color: var(--bg-secondary);
308
+ border: 1px solid var(--border-color);
309
+ border-radius: var(--border-radius);
310
+ color: var(--text-primary);
311
+ font-size: 0.95rem;
312
+ }
313
+
314
+ .search-input:focus {
315
+ outline: none;
316
+ border-color: var(--accent);
317
+ }
318
+
319
+ .filter-select {
320
+ padding: 0.75rem 1rem;
321
+ background-color: var(--bg-secondary);
322
+ border: 1px solid var(--border-color);
323
+ border-radius: var(--border-radius);
324
+ color: var(--text-primary);
325
+ font-size: 0.95rem;
326
+ cursor: pointer;
327
+ }
328
+
329
+ .filter-select:focus {
330
+ outline: none;
331
+ border-color: var(--accent);
332
+ }
333
+
334
+ .memories-list {
335
+ display: flex;
336
+ flex-direction: column;
337
+ gap: 1rem;
338
+ }
339
+
340
+ .memory-card {
341
+ background-color: var(--bg-secondary);
342
+ border: 1px solid var(--border-color);
343
+ border-radius: var(--border-radius);
344
+ padding: 1.5rem;
345
+ cursor: pointer;
346
+ transition: all 0.2s;
347
+ box-shadow: var(--shadow-sm);
348
+ }
349
+
350
+ .memory-card:hover {
351
+ border-color: var(--accent);
352
+ box-shadow: var(--shadow-md);
353
+ }
354
+
355
+ .memory-card.high-gc-risk {
356
+ border-left: 4px solid #EF4444;
357
+ }
358
+
359
+ .memory-header {
360
+ display: flex;
361
+ justify-content: space-between;
362
+ align-items: flex-start;
363
+ margin-bottom: 0.75rem;
364
+ }
365
+
366
+ .memory-header h3 {
367
+ font-size: 1.125rem;
368
+ color: var(--text-primary);
369
+ }
370
+
371
+ .memory-meta {
372
+ display: flex;
373
+ gap: 0.75rem;
374
+ align-items: center;
375
+ flex-wrap: wrap;
376
+ font-size: 0.875rem;
377
+ color: var(--text-secondary);
378
+ }
379
+
380
+ .memory-tags {
381
+ display: flex;
382
+ gap: 0.5rem;
383
+ margin-top: 0.75rem;
384
+ flex-wrap: wrap;
385
+ }
386
+
387
+ .tag {
388
+ padding: 0.25rem 0.5rem;
389
+ background-color: var(--bg-tertiary);
390
+ border-radius: 4px;
391
+ font-size: 0.75rem;
392
+ color: var(--text-secondary);
393
+ }
394
+
395
+ /* Modal */
396
+ .modal-overlay {
397
+ position: fixed;
398
+ top: 0;
399
+ left: 0;
400
+ right: 0;
401
+ bottom: 0;
402
+ background-color: rgba(0, 0, 0, 0.8);
403
+ display: none;
404
+ justify-content: center;
405
+ align-items: center;
406
+ z-index: 1000;
407
+ }
408
+
409
+ .modal-overlay.active {
410
+ display: flex;
411
+ }
412
+
413
+ .modal {
414
+ background-color: var(--bg-secondary);
415
+ border: 1px solid var(--border-color);
416
+ border-radius: var(--border-radius);
417
+ max-width: 900px;
418
+ width: 90%;
419
+ max-height: 90vh;
420
+ overflow: hidden;
421
+ display: flex;
422
+ flex-direction: column;
423
+ }
424
+
425
+ .modal-header {
426
+ display: flex;
427
+ justify-content: space-between;
428
+ align-items: center;
429
+ padding: 1rem 1.5rem;
430
+ border-bottom: 1px solid var(--border-color);
431
+ }
432
+
433
+ .modal-header h2 {
434
+ font-size: 1.25rem;
435
+ }
436
+
437
+ .modal-close {
438
+ background: none;
439
+ border: none;
440
+ color: var(--text-secondary);
441
+ font-size: 1.5rem;
442
+ cursor: pointer;
443
+ padding: 0.25rem;
444
+ line-height: 1;
445
+ }
446
+
447
+ .modal-close:hover {
448
+ color: var(--text-primary);
449
+ }
450
+
451
+ .modal-body {
452
+ padding: 1.5rem;
453
+ overflow-y: auto;
454
+ flex: 1;
455
+ }
456
+
457
+ .modal-body .markdown-content {
458
+ line-height: 1.8;
459
+ }
460
+
461
+ .modal-body .markdown-content h1,
462
+ .modal-body .markdown-content h2,
463
+ .modal-body .markdown-content h3 {
464
+ margin-top: 1.5rem;
465
+ margin-bottom: 0.75rem;
466
+ color: var(--text-primary);
467
+ }
468
+
469
+ .modal-body .markdown-content p {
470
+ margin-bottom: 1rem;
471
+ }
472
+
473
+ .modal-body .markdown-content code {
474
+ background-color: var(--bg-tertiary);
475
+ padding: 0.25rem 0.5rem;
476
+ border-radius: 4px;
477
+ font-size: 0.875rem;
478
+ }
479
+
480
+ .modal-body .markdown-content pre {
481
+ background-color: var(--bg-tertiary);
482
+ padding: 1rem;
483
+ border-radius: var(--border-radius);
484
+ overflow-x: auto;
485
+ margin: 1rem 0;
486
+ }
487
+
488
+ /* Timeline */
489
+ .timeline-container {
490
+ background-color: var(--bg-secondary);
491
+ border: 1px solid var(--border-color);
492
+ border-radius: var(--border-radius);
493
+ padding: 1.5rem;
494
+ box-shadow: var(--shadow-sm);
495
+ }
496
+
497
+ .timeline-controls {
498
+ display: flex;
499
+ gap: 1rem;
500
+ margin-bottom: 1.5rem;
501
+ align-items: center;
502
+ }
503
+
504
+ /* Loading */
505
+ .loading {
506
+ display: flex;
507
+ justify-content: center;
508
+ align-items: center;
509
+ padding: 3rem;
510
+ color: var(--text-secondary);
511
+ }
512
+
513
+ .loading::after {
514
+ content: '';
515
+ width: 24px;
516
+ height: 24px;
517
+ border: 3px solid var(--border-color);
518
+ border-top-color: var(--accent);
519
+ border-radius: 50%;
520
+ animation: spin 1s linear infinite;
521
+ margin-left: 0.75rem;
522
+ }
523
+
524
+ @keyframes spin {
525
+ to { transform: rotate(360deg); }
526
+ }
527
+
528
+ /* Botões */
529
+ .btn {
530
+ padding: 0.75rem 1.5rem;
531
+ border-radius: var(--border-radius);
532
+ font-size: 0.95rem;
533
+ font-weight: 500;
534
+ cursor: pointer;
535
+ transition: all 0.2s;
536
+ border: none;
537
+ }
538
+
539
+ .btn-primary {
540
+ background-color: var(--accent);
541
+ color: white;
542
+ }
543
+
544
+ .btn-primary:hover {
545
+ background-color: var(--accent-hover);
546
+ }
547
+
548
+ .btn-secondary {
549
+ background-color: var(--bg-tertiary);
550
+ color: var(--text-primary);
551
+ }
552
+
553
+ .btn-secondary:hover {
554
+ background-color: #475569;
555
+ }
556
+
557
+ /* Responsividade */
558
+ @media (max-width: 768px) {
559
+ .graph-container {
560
+ grid-template-columns: 1fr;
561
+ }
562
+
563
+ .graph-panel {
564
+ max-height: 300px;
565
+ }
566
+
567
+ header {
568
+ padding: 1rem;
569
+ }
570
+
571
+ .tabs {
572
+ padding: 0.5rem 1rem;
573
+ overflow-x: auto;
574
+ }
575
+
576
+ main {
577
+ padding: 1rem;
578
+ }
579
+ }
@@ -614,14 +614,18 @@ class EntitiesDB:
614
614
  cached_hash = self.get_cached_hash(memory_id)
615
615
  current_hash = self._compute_hash(content)
616
616
 
617
+ skip_delete = False
617
618
  if cached_hash == current_hash:
618
619
  # Conteúdo igual, verifica se já tem entidades
619
620
  existing = self.get_entities_by_memory(memory_id)
620
621
  if existing:
621
622
  return [] # Já processado, sem mudanças
623
+ # Cache bate mas entidades vazias (ex: banco limpo) - reprocessa sem delete
624
+ skip_delete = True
622
625
 
623
626
  # Conteúdo novo ou mudou - remove apenas entidades de conteúdo e reprocessa
624
- self.delete_entities_by_source(memory_id, "content")
627
+ if not skip_delete:
628
+ self.delete_entities_by_source(memory_id, "content")
625
629
 
626
630
  entity_ids = []
627
631