@timmeck/brain-core 2.33.0 → 2.34.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.
- package/README.md +76 -28
- package/dist/unified/unified-server.d.ts +17 -0
- package/dist/unified/unified-server.js +226 -0
- package/dist/unified/unified-server.js.map +1 -1
- package/package.json +1 -1
- package/unified-dashboard.html +1198 -1006
package/unified-dashboard.html
CHANGED
|
@@ -3,1083 +3,1275 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Brain
|
|
6
|
+
<title>Brain Mission Control</title>
|
|
7
7
|
<style>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
border-left: 3px solid var(--purple);
|
|
338
|
-
}
|
|
339
|
-
.analogy-narrative { font-size: 12px; color: var(--text-secondary); margin-bottom: 4px; }
|
|
340
|
-
.analogy-meta { font-size: 10px; color: var(--text-muted); display: flex; gap: 12px; }
|
|
341
|
-
|
|
342
|
-
/* ── Attention View ────────────────────────────── */
|
|
343
|
-
.topic-bar {
|
|
344
|
-
display: flex;
|
|
345
|
-
align-items: center;
|
|
346
|
-
gap: 10px;
|
|
347
|
-
margin-bottom: 6px;
|
|
348
|
-
font-size: 12px;
|
|
349
|
-
}
|
|
350
|
-
.topic-name { min-width: 120px; color: var(--text-secondary); }
|
|
351
|
-
.topic-bar-fill {
|
|
352
|
-
height: 16px;
|
|
353
|
-
border-radius: 3px;
|
|
354
|
-
background: linear-gradient(90deg, var(--cyan), var(--blue));
|
|
355
|
-
transition: width 0.5s;
|
|
356
|
-
min-width: 2px;
|
|
357
|
-
}
|
|
358
|
-
.topic-score { min-width: 50px; text-align: right; color: var(--text-muted); font-size: 11px; }
|
|
359
|
-
|
|
360
|
-
.context-badge {
|
|
361
|
-
display: inline-block;
|
|
362
|
-
padding: 3px 10px;
|
|
363
|
-
border-radius: 12px;
|
|
364
|
-
font-size: 11px;
|
|
365
|
-
font-weight: 500;
|
|
366
|
-
margin-right: 6px;
|
|
367
|
-
}
|
|
368
|
-
.context-badge.debugging { background: rgba(255, 61, 61, 0.15); color: var(--red); }
|
|
369
|
-
.context-badge.coding { background: rgba(0, 229, 255, 0.15); color: var(--cyan); }
|
|
370
|
-
.context-badge.reviewing { background: rgba(179, 136, 255, 0.15); color: var(--purple); }
|
|
371
|
-
.context-badge.trading { background: rgba(0, 255, 136, 0.15); color: var(--green); }
|
|
372
|
-
.context-badge.publishing { background: rgba(255, 145, 0, 0.15); color: var(--orange); }
|
|
373
|
-
.context-badge.monitoring { background: rgba(68, 138, 255, 0.15); color: var(--blue); }
|
|
374
|
-
|
|
375
|
-
/* ── Engines Table ──────────────────────────────── */
|
|
376
|
-
.engine-grid {
|
|
377
|
-
display: grid;
|
|
378
|
-
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
|
379
|
-
gap: 8px;
|
|
380
|
-
}
|
|
381
|
-
.engine-chip {
|
|
382
|
-
display: flex;
|
|
383
|
-
align-items: center;
|
|
384
|
-
gap: 6px;
|
|
385
|
-
padding: 6px 10px;
|
|
386
|
-
background: rgba(0, 0, 0, 0.2);
|
|
387
|
-
border-radius: 6px;
|
|
388
|
-
font-size: 11px;
|
|
389
|
-
}
|
|
390
|
-
.engine-dot {
|
|
391
|
-
width: 6px; height: 6px;
|
|
392
|
-
border-radius: 50%;
|
|
393
|
-
}
|
|
394
|
-
.engine-dot.active { background: var(--green); box-shadow: 0 0 4px var(--green); }
|
|
395
|
-
.engine-dot.idle { background: var(--text-muted); }
|
|
396
|
-
|
|
397
|
-
/* ── Two Column Layout ───────────────────────── */
|
|
398
|
-
.two-col {
|
|
399
|
-
display: grid;
|
|
400
|
-
grid-template-columns: 1fr 1fr;
|
|
401
|
-
gap: 16px;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/* ── Transfer History Table ──────────────────── */
|
|
405
|
-
.transfer-table {
|
|
406
|
-
width: 100%;
|
|
407
|
-
border-collapse: collapse;
|
|
408
|
-
font-size: 12px;
|
|
409
|
-
}
|
|
410
|
-
.transfer-table th {
|
|
411
|
-
text-align: left;
|
|
412
|
-
padding: 6px 10px;
|
|
413
|
-
font-size: 10px;
|
|
414
|
-
text-transform: uppercase;
|
|
415
|
-
letter-spacing: 1px;
|
|
416
|
-
color: var(--text-muted);
|
|
417
|
-
border-bottom: 1px solid var(--border);
|
|
418
|
-
}
|
|
419
|
-
.transfer-table td {
|
|
420
|
-
padding: 6px 10px;
|
|
421
|
-
border-bottom: 1px solid rgba(100, 120, 180, 0.06);
|
|
422
|
-
color: var(--text-secondary);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
.status-badge {
|
|
426
|
-
display: inline-block;
|
|
427
|
-
padding: 1px 8px;
|
|
428
|
-
border-radius: 3px;
|
|
429
|
-
font-size: 10px;
|
|
430
|
-
font-weight: 600;
|
|
431
|
-
text-transform: uppercase;
|
|
432
|
-
}
|
|
433
|
-
.status-badge.pending { background: rgba(255, 215, 0, 0.15); color: var(--gold); }
|
|
434
|
-
.status-badge.applied { background: rgba(0, 229, 255, 0.15); color: var(--cyan); }
|
|
435
|
-
.status-badge.validated { background: rgba(0, 255, 136, 0.15); color: var(--green); }
|
|
436
|
-
.status-badge.rejected { background: rgba(255, 61, 61, 0.15); color: var(--red); }
|
|
437
|
-
|
|
438
|
-
/* ── Animations ──────────────────────────────── */
|
|
439
|
-
@keyframes pulse {
|
|
440
|
-
0%, 100% { opacity: 0.6; transform: scale(1); }
|
|
441
|
-
50% { opacity: 1; transform: scale(1.1); }
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
@keyframes slideIn {
|
|
445
|
-
from { opacity: 0; transform: translateY(-8px); }
|
|
446
|
-
to { opacity: 1; transform: translateY(0); }
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/* ── Responsive ──────────────────────────────── */
|
|
450
|
-
@media (max-width: 1000px) {
|
|
451
|
-
.brain-grid { grid-template-columns: 1fr; }
|
|
452
|
-
.two-col { grid-template-columns: 1fr; }
|
|
453
|
-
}
|
|
8
|
+
/* ── Reset + Variables ─────────────────────────────── */
|
|
9
|
+
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
|
10
|
+
:root{
|
|
11
|
+
--bg-deep:#050810;
|
|
12
|
+
--bg-primary:#0a0e1a;
|
|
13
|
+
--bg-card:rgba(12,16,28,0.65);
|
|
14
|
+
--bg-card-hover:rgba(16,22,40,0.75);
|
|
15
|
+
--bg-glass:rgba(20,28,50,0.45);
|
|
16
|
+
--border:rgba(80,120,200,0.12);
|
|
17
|
+
--border-bright:rgba(80,120,200,0.25);
|
|
18
|
+
--text:#e0e6f0;
|
|
19
|
+
--text-dim:#7a8ba8;
|
|
20
|
+
--text-muted:#4a5a78;
|
|
21
|
+
--cyan:#00e5ff;
|
|
22
|
+
--green:#00ff88;
|
|
23
|
+
--magenta:#ff0090;
|
|
24
|
+
--gold:#ffd700;
|
|
25
|
+
--purple:#b388ff;
|
|
26
|
+
--orange:#ff9100;
|
|
27
|
+
--red:#ff3d3d;
|
|
28
|
+
--blue:#448aff;
|
|
29
|
+
--sidebar-w:60px;
|
|
30
|
+
--sidebar-exp:220px;
|
|
31
|
+
--header-h:52px;
|
|
32
|
+
--font:'SF Mono','Cascadia Code','JetBrains Mono','Fira Code',monospace;
|
|
33
|
+
--radius:10px;
|
|
34
|
+
}
|
|
35
|
+
html,body{height:100%;overflow:hidden;font-family:var(--font);font-size:12px;color:var(--text);background:var(--bg-deep)}
|
|
36
|
+
|
|
37
|
+
/* ── Animated Background ───────────────────────────── */
|
|
38
|
+
body::before{
|
|
39
|
+
content:'';position:fixed;inset:0;z-index:0;
|
|
40
|
+
background:linear-gradient(135deg,#050810 0%,#0d0a20 30%,#080c1a 60%,#0a0818 100%);
|
|
41
|
+
animation:bgShift 30s ease infinite alternate;
|
|
42
|
+
}
|
|
43
|
+
@keyframes bgShift{
|
|
44
|
+
0%{filter:hue-rotate(0deg) brightness(1)}
|
|
45
|
+
50%{filter:hue-rotate(8deg) brightness(1.05)}
|
|
46
|
+
100%{filter:hue-rotate(-5deg) brightness(0.98)}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* ── Layout ────────────────────────────────────────── */
|
|
50
|
+
.app{display:flex;height:100vh;position:relative;z-index:1}
|
|
51
|
+
|
|
52
|
+
/* ── Sidebar ───────────────────────────────────────── */
|
|
53
|
+
.sidebar{
|
|
54
|
+
width:var(--sidebar-w);height:100vh;
|
|
55
|
+
background:rgba(8,12,24,0.85);
|
|
56
|
+
backdrop-filter:blur(20px);
|
|
57
|
+
border-right:1px solid var(--border);
|
|
58
|
+
display:flex;flex-direction:column;
|
|
59
|
+
transition:width 0.3s cubic-bezier(0.4,0,0.2,1);
|
|
60
|
+
overflow:hidden;flex-shrink:0;z-index:10;
|
|
61
|
+
}
|
|
62
|
+
.sidebar:hover{width:var(--sidebar-exp)}
|
|
63
|
+
.sidebar-logo{
|
|
64
|
+
height:var(--header-h);display:flex;align-items:center;
|
|
65
|
+
padding:0 16px;gap:10px;border-bottom:1px solid var(--border);
|
|
66
|
+
white-space:nowrap;overflow:hidden;
|
|
67
|
+
}
|
|
68
|
+
.sidebar-logo .dot{width:10px;height:10px;border-radius:50%;background:var(--cyan);flex-shrink:0;animation:pulse 3s infinite}
|
|
69
|
+
.sidebar-logo span{font-size:13px;font-weight:600;letter-spacing:0.5px;opacity:0;transition:opacity 0.3s}
|
|
70
|
+
.sidebar:hover .sidebar-logo span{opacity:1}
|
|
71
|
+
@keyframes pulse{0%,100%{opacity:1;box-shadow:0 0 6px var(--cyan)}50%{opacity:0.5;box-shadow:0 0 2px var(--cyan)}}
|
|
72
|
+
|
|
73
|
+
.nav{flex:1;display:flex;flex-direction:column;gap:2px;padding:8px 6px}
|
|
74
|
+
.nav-item{
|
|
75
|
+
display:flex;align-items:center;gap:12px;
|
|
76
|
+
padding:10px;border-radius:8px;cursor:pointer;
|
|
77
|
+
color:var(--text-dim);transition:all 0.2s;
|
|
78
|
+
white-space:nowrap;overflow:hidden;
|
|
79
|
+
}
|
|
80
|
+
.nav-item:hover{background:rgba(0,229,255,0.06);color:var(--text)}
|
|
81
|
+
.nav-item.active{background:rgba(0,229,255,0.1);color:var(--cyan)}
|
|
82
|
+
.nav-item svg{width:20px;height:20px;flex-shrink:0}
|
|
83
|
+
.nav-item span{font-size:11px;letter-spacing:0.5px;opacity:0;transition:opacity 0.3s}
|
|
84
|
+
.sidebar:hover .nav-item span{opacity:1}
|
|
85
|
+
|
|
86
|
+
.sidebar-footer{padding:12px;border-top:1px solid var(--border);overflow:hidden;white-space:nowrap}
|
|
87
|
+
.conn-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:6px;animation:pulse 2s infinite}
|
|
88
|
+
.conn-dot.on{background:var(--green)}
|
|
89
|
+
.conn-dot.off{background:var(--red);animation:none}
|
|
90
|
+
.sidebar-footer .label{font-size:10px;color:var(--text-muted);opacity:0;transition:opacity 0.3s}
|
|
91
|
+
.sidebar:hover .sidebar-footer .label{opacity:1}
|
|
92
|
+
|
|
93
|
+
/* ── Main Content ──────────────────────────────────── */
|
|
94
|
+
.main{flex:1;display:flex;flex-direction:column;overflow:hidden}
|
|
95
|
+
|
|
96
|
+
/* ── Header ────────────────────────────────────────── */
|
|
97
|
+
.header{
|
|
98
|
+
height:var(--header-h);display:flex;align-items:center;justify-content:space-between;
|
|
99
|
+
padding:0 20px;border-bottom:1px solid var(--border);
|
|
100
|
+
background:rgba(8,12,24,0.6);backdrop-filter:blur(12px);flex-shrink:0;
|
|
101
|
+
}
|
|
102
|
+
.header-left{display:flex;align-items:center;gap:16px}
|
|
103
|
+
.header-title{font-size:14px;font-weight:600;letter-spacing:0.5px}
|
|
104
|
+
.header-badge{font-size:10px;padding:2px 8px;border-radius:4px;background:rgba(0,229,255,0.15);color:var(--cyan);letter-spacing:0.5px}
|
|
105
|
+
.header-right{display:flex;align-items:center;gap:12px}
|
|
106
|
+
.uptime{font-size:10px;color:var(--text-muted)}
|
|
107
|
+
.trigger-btn{
|
|
108
|
+
padding:6px 14px;border-radius:6px;border:1px solid var(--cyan);
|
|
109
|
+
background:transparent;color:var(--cyan);cursor:pointer;font-family:var(--font);
|
|
110
|
+
font-size:10px;letter-spacing:0.5px;transition:all 0.2s;
|
|
111
|
+
}
|
|
112
|
+
.trigger-btn:hover{background:rgba(0,229,255,0.15);box-shadow:0 0 12px rgba(0,229,255,0.2)}
|
|
113
|
+
.trigger-btn:active{transform:scale(0.97)}
|
|
114
|
+
|
|
115
|
+
/* ── Content ───────────────────────────────────────── */
|
|
116
|
+
.content{flex:1;overflow-y:auto;padding:16px 20px;position:relative}
|
|
117
|
+
.content::-webkit-scrollbar{width:4px}
|
|
118
|
+
.content::-webkit-scrollbar-track{background:transparent}
|
|
119
|
+
.content::-webkit-scrollbar-thumb{background:var(--border-bright);border-radius:2px}
|
|
120
|
+
|
|
121
|
+
.page{display:none;animation:fadeIn 0.25s ease}
|
|
122
|
+
.page.active{display:block}
|
|
123
|
+
@keyframes fadeIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
|
|
124
|
+
|
|
125
|
+
/* ── Cards ─────────────────────────────────────────── */
|
|
126
|
+
.glass{
|
|
127
|
+
background:var(--bg-card);
|
|
128
|
+
backdrop-filter:blur(16px);
|
|
129
|
+
border:1px solid var(--border);
|
|
130
|
+
border-radius:var(--radius);
|
|
131
|
+
padding:16px;
|
|
132
|
+
transition:border-color 0.3s, box-shadow 0.3s;
|
|
133
|
+
}
|
|
134
|
+
.glass:hover{border-color:var(--border-bright);box-shadow:0 4px 24px rgba(0,0,0,0.3)}
|
|
135
|
+
|
|
136
|
+
.section-title{
|
|
137
|
+
font-size:10px;text-transform:uppercase;letter-spacing:2px;
|
|
138
|
+
color:var(--text-muted);margin-bottom:12px;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* ── Stat Grid ─────────────────────────────────────── */
|
|
142
|
+
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin-bottom:16px}
|
|
143
|
+
.stat-card{text-align:center;padding:14px 10px}
|
|
144
|
+
.stat-val{font-size:26px;font-weight:700;line-height:1.2}
|
|
145
|
+
.stat-label{font-size:10px;color:var(--text-dim);text-transform:uppercase;letter-spacing:1px;margin-top:4px}
|
|
146
|
+
|
|
147
|
+
/* ── Brain Cards ───────────────────────────────────── */
|
|
148
|
+
.brain-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-bottom:16px}
|
|
149
|
+
.brain-card{position:relative;overflow:hidden}
|
|
150
|
+
.brain-card::before{
|
|
151
|
+
content:'';position:absolute;top:0;left:0;right:0;height:2px;
|
|
152
|
+
}
|
|
153
|
+
.brain-card.brain-main::before{background:var(--cyan)}
|
|
154
|
+
.brain-card.brain-trading::before{background:var(--green)}
|
|
155
|
+
.brain-card.brain-marketing::before{background:var(--magenta)}
|
|
156
|
+
.brain-name{font-size:12px;font-weight:600;margin-bottom:8px}
|
|
157
|
+
.brain-stat{display:flex;justify-content:space-between;font-size:10px;color:var(--text-dim);margin-top:4px}
|
|
158
|
+
.brain-stat .val{color:var(--text)}
|
|
159
|
+
|
|
160
|
+
/* ── Notification Feed ─────────────────────────────── */
|
|
161
|
+
.notif-feed{max-height:300px;overflow-y:auto;display:flex;flex-direction:column;gap:6px}
|
|
162
|
+
.notif-feed::-webkit-scrollbar{width:3px}
|
|
163
|
+
.notif-feed::-webkit-scrollbar-thumb{background:var(--border-bright);border-radius:2px}
|
|
164
|
+
.notif-item{
|
|
165
|
+
display:flex;gap:10px;padding:8px 10px;border-radius:6px;
|
|
166
|
+
background:rgba(10,14,26,0.5);border-left:2px solid var(--border);
|
|
167
|
+
animation:slideIn 0.3s ease;font-size:11px;
|
|
168
|
+
}
|
|
169
|
+
@keyframes slideIn{from{opacity:0;transform:translateX(-8px)}to{opacity:1;transform:none}}
|
|
170
|
+
.notif-item.breakthrough{border-left-color:var(--gold);background:rgba(255,215,0,0.04)}
|
|
171
|
+
.notif-item.notable{border-left-color:var(--cyan)}
|
|
172
|
+
.notif-time{color:var(--text-muted);font-size:10px;flex-shrink:0;width:50px}
|
|
173
|
+
.notif-engine{
|
|
174
|
+
font-size:9px;padding:1px 6px;border-radius:3px;
|
|
175
|
+
background:rgba(0,229,255,0.1);color:var(--cyan);flex-shrink:0;
|
|
176
|
+
}
|
|
177
|
+
.notif-msg{flex:1;color:var(--text-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
178
|
+
|
|
179
|
+
/* ── Neural Canvas ─────────────────────────────────── */
|
|
180
|
+
.neural-wrap{position:relative;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border)}
|
|
181
|
+
.neural-canvas{display:block;width:100%;background:transparent;cursor:grab}
|
|
182
|
+
.neural-canvas:active{cursor:grabbing}
|
|
183
|
+
.neural-controls{
|
|
184
|
+
position:absolute;bottom:10px;right:10px;display:flex;gap:4px;
|
|
185
|
+
}
|
|
186
|
+
.neural-btn{
|
|
187
|
+
width:28px;height:28px;border-radius:6px;border:1px solid var(--border);
|
|
188
|
+
background:var(--bg-card);color:var(--text-dim);cursor:pointer;
|
|
189
|
+
display:flex;align-items:center;justify-content:center;font-size:14px;
|
|
190
|
+
transition:all 0.2s;font-family:var(--font);
|
|
191
|
+
}
|
|
192
|
+
.neural-btn:hover{background:var(--bg-card-hover);color:var(--cyan);border-color:var(--cyan)}
|
|
193
|
+
.neural-info{
|
|
194
|
+
position:absolute;top:10px;left:10px;font-size:10px;color:var(--text-muted);
|
|
195
|
+
background:rgba(5,8,16,0.7);padding:4px 8px;border-radius:4px;pointer-events:none;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* ── Thought Stream ────────────────────────────────── */
|
|
199
|
+
.thought-filters{display:flex;gap:6px;margin-bottom:12px;flex-wrap:wrap}
|
|
200
|
+
.thought-filter{
|
|
201
|
+
font-size:10px;padding:3px 10px;border-radius:4px;cursor:pointer;
|
|
202
|
+
border:1px solid var(--border);background:transparent;color:var(--text-dim);
|
|
203
|
+
font-family:var(--font);transition:all 0.2s;
|
|
204
|
+
}
|
|
205
|
+
.thought-filter.active{border-color:var(--cyan);color:var(--cyan);background:rgba(0,229,255,0.08)}
|
|
206
|
+
.thought-list{display:flex;flex-direction:column;gap:4px;max-height:calc(100vh - 200px);overflow-y:auto}
|
|
207
|
+
.thought-list::-webkit-scrollbar{width:3px}
|
|
208
|
+
.thought-list::-webkit-scrollbar-thumb{background:var(--border-bright);border-radius:2px}
|
|
209
|
+
.thought-item{
|
|
210
|
+
display:flex;gap:8px;padding:6px 10px;border-radius:6px;
|
|
211
|
+
background:rgba(10,14,26,0.4);font-size:11px;animation:slideIn 0.2s ease;
|
|
212
|
+
}
|
|
213
|
+
.thought-item .time{color:var(--text-muted);font-size:10px;flex-shrink:0;width:55px}
|
|
214
|
+
.thought-item .engine-tag{
|
|
215
|
+
font-size:9px;padding:1px 6px;border-radius:3px;flex-shrink:0;
|
|
216
|
+
}
|
|
217
|
+
.thought-item .msg{flex:1;color:var(--text-dim)}
|
|
218
|
+
.thought-item.sig-breakthrough{background:rgba(255,215,0,0.05);border-left:2px solid var(--gold)}
|
|
219
|
+
.thought-item.sig-notable{border-left:2px solid var(--cyan)}
|
|
220
|
+
|
|
221
|
+
/* ── CodeGen ───────────────────────────────────────── */
|
|
222
|
+
.codegen-form{display:flex;gap:8px;margin-bottom:16px}
|
|
223
|
+
.codegen-form textarea{
|
|
224
|
+
flex:1;height:60px;resize:vertical;padding:10px;
|
|
225
|
+
background:rgba(10,14,26,0.6);border:1px solid var(--border);
|
|
226
|
+
border-radius:8px;color:var(--text);font-family:var(--font);font-size:11px;
|
|
227
|
+
}
|
|
228
|
+
.codegen-form textarea:focus{outline:none;border-color:var(--cyan)}
|
|
229
|
+
.codegen-form select{
|
|
230
|
+
padding:8px;background:rgba(10,14,26,0.6);border:1px solid var(--border);
|
|
231
|
+
border-radius:8px;color:var(--text);font-family:var(--font);font-size:11px;
|
|
232
|
+
}
|
|
233
|
+
.codegen-form select:focus{outline:none;border-color:var(--cyan)}
|
|
234
|
+
.gen-btn{
|
|
235
|
+
padding:8px 20px;border-radius:8px;border:none;
|
|
236
|
+
background:linear-gradient(135deg,rgba(0,229,255,0.2),rgba(0,229,255,0.1));
|
|
237
|
+
color:var(--cyan);cursor:pointer;font-family:var(--font);font-size:11px;
|
|
238
|
+
font-weight:600;transition:all 0.2s;align-self:flex-end;
|
|
239
|
+
}
|
|
240
|
+
.gen-btn:hover{background:linear-gradient(135deg,rgba(0,229,255,0.3),rgba(0,229,255,0.15));box-shadow:0 0 16px rgba(0,229,255,0.2)}
|
|
241
|
+
|
|
242
|
+
.pending-card{margin-bottom:12px;position:relative}
|
|
243
|
+
.pending-card .code-block{
|
|
244
|
+
background:rgba(5,8,16,0.8);border-radius:6px;padding:12px;
|
|
245
|
+
overflow-x:auto;font-size:11px;line-height:1.6;max-height:300px;overflow-y:auto;
|
|
246
|
+
margin:8px 0;
|
|
247
|
+
}
|
|
248
|
+
.pending-card .code-block::-webkit-scrollbar{width:3px;height:3px}
|
|
249
|
+
.pending-card .code-block::-webkit-scrollbar-thumb{background:var(--border-bright);border-radius:2px}
|
|
250
|
+
.review-actions{display:flex;gap:8px;align-items:center;margin-top:8px}
|
|
251
|
+
.review-actions input{
|
|
252
|
+
flex:1;padding:6px 10px;background:rgba(10,14,26,0.5);border:1px solid var(--border);
|
|
253
|
+
border-radius:6px;color:var(--text);font-family:var(--font);font-size:11px;
|
|
254
|
+
}
|
|
255
|
+
.review-actions input:focus{outline:none;border-color:var(--cyan)}
|
|
256
|
+
.btn-approve{
|
|
257
|
+
padding:5px 14px;border-radius:6px;border:1px solid var(--green);
|
|
258
|
+
background:rgba(0,255,136,0.08);color:var(--green);cursor:pointer;
|
|
259
|
+
font-family:var(--font);font-size:10px;transition:all 0.2s;
|
|
260
|
+
}
|
|
261
|
+
.btn-approve:hover{background:rgba(0,255,136,0.15)}
|
|
262
|
+
.btn-reject{
|
|
263
|
+
padding:5px 14px;border-radius:6px;border:1px solid var(--red);
|
|
264
|
+
background:rgba(255,61,61,0.08);color:var(--red);cursor:pointer;
|
|
265
|
+
font-family:var(--font);font-size:10px;transition:all 0.2s;
|
|
266
|
+
}
|
|
267
|
+
.btn-reject:hover{background:rgba(255,61,61,0.15)}
|
|
268
|
+
.btn-test{
|
|
269
|
+
padding:5px 14px;border-radius:6px;border:1px solid var(--gold);
|
|
270
|
+
background:rgba(255,215,0,0.08);color:var(--gold);cursor:pointer;
|
|
271
|
+
font-family:var(--font);font-size:10px;transition:all 0.2s;
|
|
272
|
+
}
|
|
273
|
+
.btn-test:hover{background:rgba(255,215,0,0.15)}
|
|
274
|
+
|
|
275
|
+
.gen-history{margin-top:16px}
|
|
276
|
+
.gen-table{width:100%;border-collapse:collapse;font-size:10px}
|
|
277
|
+
.gen-table th{text-align:left;padding:6px 8px;color:var(--text-muted);text-transform:uppercase;letter-spacing:1px;border-bottom:1px solid var(--border)}
|
|
278
|
+
.gen-table td{padding:6px 8px;border-bottom:1px solid rgba(80,120,200,0.06);color:var(--text-dim)}
|
|
279
|
+
.gen-table tr:hover td{background:rgba(0,229,255,0.03)}
|
|
280
|
+
.status-badge{font-size:9px;padding:1px 6px;border-radius:3px;display:inline-block}
|
|
281
|
+
.status-badge.approved{background:rgba(0,255,136,0.12);color:var(--green)}
|
|
282
|
+
.status-badge.rejected{background:rgba(255,61,61,0.12);color:var(--red)}
|
|
283
|
+
.status-badge.generated{background:rgba(0,229,255,0.12);color:var(--cyan)}
|
|
284
|
+
.status-badge.generating{background:rgba(255,145,0,0.12);color:var(--orange)}
|
|
285
|
+
.status-badge.ready{background:rgba(0,255,136,0.12);color:var(--green)}
|
|
286
|
+
.status-badge.testing{background:rgba(255,215,0,0.12);color:var(--gold)}
|
|
287
|
+
.status-badge.proposed{background:rgba(179,136,255,0.12);color:var(--purple)}
|
|
288
|
+
.status-badge.applied{background:rgba(0,255,136,0.12);color:var(--green)}
|
|
289
|
+
.status-badge.failed{background:rgba(255,61,61,0.12);color:var(--red)}
|
|
290
|
+
|
|
291
|
+
/* ── Self-Mod ──────────────────────────────────────── */
|
|
292
|
+
.diff-viewer{display:grid;grid-template-columns:1fr 1fr;gap:2px;margin:8px 0;font-size:10px;border-radius:6px;overflow:hidden}
|
|
293
|
+
.diff-old,.diff-new{padding:10px;background:rgba(5,8,16,0.8);overflow-x:auto;max-height:250px;overflow-y:auto;line-height:1.6}
|
|
294
|
+
.diff-old::-webkit-scrollbar,.diff-new::-webkit-scrollbar{width:3px;height:3px}
|
|
295
|
+
.diff-old::-webkit-scrollbar-thumb,.diff-new::-webkit-scrollbar-thumb{background:var(--border-bright);border-radius:2px}
|
|
296
|
+
.diff-label{font-size:9px;color:var(--text-muted);text-transform:uppercase;letter-spacing:1px;margin-bottom:4px}
|
|
297
|
+
.diff-line-del{color:var(--red);opacity:0.8}
|
|
298
|
+
.diff-line-add{color:var(--green);opacity:0.8}
|
|
299
|
+
|
|
300
|
+
/* ── Engine Grid ───────────────────────────────────── */
|
|
301
|
+
.engine-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}
|
|
302
|
+
.engine-card{padding:12px}
|
|
303
|
+
.engine-card .e-name{font-size:11px;font-weight:600;margin-bottom:6px;display:flex;align-items:center;gap:6px}
|
|
304
|
+
.engine-card .e-dot{width:6px;height:6px;border-radius:50%}
|
|
305
|
+
.engine-card .e-stat{display:flex;justify-content:space-between;font-size:10px;color:var(--text-dim);margin-top:3px}
|
|
306
|
+
.engine-card .e-bar{height:3px;border-radius:2px;background:rgba(80,120,200,0.1);margin-top:6px;overflow:hidden}
|
|
307
|
+
.engine-card .e-bar-fill{height:100%;border-radius:2px;transition:width 0.5s ease}
|
|
308
|
+
|
|
309
|
+
/* ── Intelligence (Attention + Transfer) ───────────── */
|
|
310
|
+
.topic-list{display:flex;flex-direction:column;gap:6px}
|
|
311
|
+
.topic-item{display:flex;align-items:center;gap:10px;padding:6px 10px;border-radius:6px;background:rgba(10,14,26,0.4)}
|
|
312
|
+
.topic-name{flex:1;font-size:11px}
|
|
313
|
+
.topic-bar-bg{width:120px;height:4px;border-radius:2px;background:rgba(80,120,200,0.1)}
|
|
314
|
+
.topic-bar-fill{height:100%;border-radius:2px;background:var(--cyan);transition:width 0.4s ease}
|
|
315
|
+
.topic-score{font-size:10px;color:var(--text-dim);width:40px;text-align:right}
|
|
316
|
+
|
|
317
|
+
.rule-list{display:flex;flex-direction:column;gap:4px;margin-top:8px}
|
|
318
|
+
.rule-item{padding:6px 10px;border-radius:6px;background:rgba(10,14,26,0.4);font-size:10px;display:flex;justify-content:space-between}
|
|
319
|
+
.rule-item .r-name{color:var(--text)}
|
|
320
|
+
.rule-item .r-status{text-transform:uppercase;letter-spacing:0.5px}
|
|
321
|
+
|
|
322
|
+
/* ── Syntax Coloring ───────────────────────────────── */
|
|
323
|
+
.syn-keyword{color:var(--magenta)}
|
|
324
|
+
.syn-string{color:var(--green)}
|
|
325
|
+
.syn-comment{color:var(--text-muted);font-style:italic}
|
|
326
|
+
.syn-number{color:var(--gold)}
|
|
327
|
+
.syn-type{color:var(--cyan)}
|
|
328
|
+
.syn-fn{color:var(--blue)}
|
|
329
|
+
|
|
330
|
+
/* ── Two-Column Layout ─────────────────────────────── */
|
|
331
|
+
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:12px}
|
|
332
|
+
@media(max-width:1000px){.two-col{grid-template-columns:1fr}}
|
|
333
|
+
|
|
334
|
+
/* ── Unavailable Message ───────────────────────────── */
|
|
335
|
+
.unavailable{text-align:center;padding:40px;color:var(--text-muted);font-size:12px}
|
|
336
|
+
.unavailable .icon{font-size:32px;margin-bottom:12px;opacity:0.3}
|
|
454
337
|
</style>
|
|
455
338
|
</head>
|
|
456
339
|
<body>
|
|
457
|
-
|
|
458
|
-
<!--
|
|
459
|
-
<nav class="sidebar">
|
|
460
|
-
|
|
461
|
-
<div class="
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
<div class="nav-section">Dashboard</div>
|
|
466
|
-
<div class="nav-item active" data-page="overview">
|
|
467
|
-
<span class="nav-icon">☍</span> Overview
|
|
468
|
-
</div>
|
|
469
|
-
<div class="nav-item" data-page="notifications">
|
|
470
|
-
<span class="nav-icon">⚠</span> Notifications
|
|
471
|
-
</div>
|
|
472
|
-
<div class="nav-section">Intelligence</div>
|
|
473
|
-
<div class="nav-item" data-page="attention">
|
|
474
|
-
<span class="nav-icon">◎</span> Attention
|
|
475
|
-
</div>
|
|
476
|
-
<div class="nav-item" data-page="transfer">
|
|
477
|
-
<span class="nav-icon">⇄</span> Transfer
|
|
478
|
-
</div>
|
|
479
|
-
<div class="nav-item" data-page="engines">
|
|
480
|
-
<span class="nav-icon">⚙</span> Engines
|
|
481
|
-
</div>
|
|
482
|
-
<div class="nav-section">Links</div>
|
|
483
|
-
<a class="nav-item" href="http://localhost:7784" target="_blank" style="text-decoration:none">
|
|
484
|
-
<span class="nav-icon" style="color:var(--cyan)">●</span> Brain :7784
|
|
485
|
-
</a>
|
|
486
|
-
<a class="nav-item" href="http://localhost:7785" target="_blank" style="text-decoration:none">
|
|
487
|
-
<span class="nav-icon" style="color:var(--green)">●</span> Trading :7785
|
|
488
|
-
</a>
|
|
489
|
-
<a class="nav-item" href="http://localhost:7786" target="_blank" style="text-decoration:none">
|
|
490
|
-
<span class="nav-icon" style="color:var(--magenta)">●</span> Marketing :7786
|
|
491
|
-
</a>
|
|
492
|
-
<a class="nav-item" href="http://localhost:7787" target="_blank" style="text-decoration:none">
|
|
493
|
-
<span class="nav-icon" style="color:var(--gold)">●</span> CodeGen :7787
|
|
494
|
-
</a>
|
|
495
|
-
</div>
|
|
496
|
-
<div class="sidebar-footer">
|
|
497
|
-
<span class="connection-dot" id="connDot"></span>
|
|
498
|
-
<span id="connLabel">Connecting...</span>
|
|
499
|
-
<div style="margin-top:4px;font-size:10px" id="uptimeLabel">Uptime: --</div>
|
|
500
|
-
</div>
|
|
501
|
-
</nav>
|
|
502
|
-
|
|
503
|
-
<!-- ═══════ Header ═══════ -->
|
|
504
|
-
<header class="header">
|
|
505
|
-
<div class="header-title" id="pageTitle">Overview</div>
|
|
506
|
-
<div class="header-actions">
|
|
507
|
-
<div class="health-badge healthy" id="healthBadge">
|
|
508
|
-
<span id="healthScore">--</span>
|
|
509
|
-
</div>
|
|
510
|
-
<button class="btn" id="triggerBtn" title="Trigger Brain Feedback Cycle">⚡ Trigger Cycle</button>
|
|
511
|
-
</div>
|
|
512
|
-
</header>
|
|
513
|
-
|
|
514
|
-
<!-- ═══════ Main Content ═══════ -->
|
|
515
|
-
<main class="main">
|
|
516
|
-
|
|
517
|
-
<!-- ── Overview Page ─────────── -->
|
|
518
|
-
<div class="page active" id="page-overview">
|
|
519
|
-
<!-- Stat Cards -->
|
|
520
|
-
<div class="stat-grid" id="overviewStats">
|
|
521
|
-
<div class="card">
|
|
522
|
-
<div class="card-title">Total Thoughts</div>
|
|
523
|
-
<div class="card-value" id="statThoughts" style="color:var(--cyan)">0</div>
|
|
524
|
-
<div class="card-sub" id="statThoughtsSub">across all engines</div>
|
|
340
|
+
<div class="app">
|
|
341
|
+
<!-- SIDEBAR -->
|
|
342
|
+
<nav class="sidebar">
|
|
343
|
+
<div class="sidebar-logo"><div class="dot"></div><span>Mission Control</span></div>
|
|
344
|
+
<div class="nav">
|
|
345
|
+
<div class="nav-item active" data-page="overview">
|
|
346
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
|
|
347
|
+
<span>Overview</span>
|
|
525
348
|
</div>
|
|
526
|
-
<div class="
|
|
527
|
-
<
|
|
528
|
-
<
|
|
529
|
-
<div class="card-sub">breakthroughs + notable</div>
|
|
349
|
+
<div class="nav-item" data-page="neural">
|
|
350
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><circle cx="5" cy="6" r="2"/><circle cx="19" cy="6" r="2"/><circle cx="5" cy="18" r="2"/><circle cx="19" cy="18" r="2"/><line x1="7" y1="7" x2="10" y2="10"/><line x1="14" y1="10" x2="17" y2="7"/><line x1="7" y1="17" x2="10" y2="14"/><line x1="14" y1="14" x2="17" y2="17"/></svg>
|
|
351
|
+
<span>Neural</span>
|
|
530
352
|
</div>
|
|
531
|
-
<div class="
|
|
532
|
-
<
|
|
533
|
-
<
|
|
534
|
-
<div class="card-sub" id="statEnginesSub">of 16 running</div>
|
|
353
|
+
<div class="nav-item" data-page="thoughts">
|
|
354
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
|
|
355
|
+
<span>Thoughts</span>
|
|
535
356
|
</div>
|
|
536
|
-
<div class="
|
|
537
|
-
<
|
|
538
|
-
<
|
|
539
|
-
<div class="card-sub">cross-domain effectiveness</div>
|
|
357
|
+
<div class="nav-item" data-page="codegen">
|
|
358
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
|
|
359
|
+
<span>CodeGen</span>
|
|
540
360
|
</div>
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
<div class="brain-grid" id="brainGrid">
|
|
545
|
-
<div class="card brain-card brain">
|
|
546
|
-
<div class="glow"></div>
|
|
547
|
-
<div class="brain-name"><span class="brain-status-dot unknown" id="brainDot"></span> Brain</div>
|
|
548
|
-
<div class="brain-stat-row"><span class="label">Cycle</span><span class="value" id="brainCycle">--</span></div>
|
|
549
|
-
<div class="brain-stat-row"><span class="label">Principles</span><span class="value" id="brainPrinciples">--</span></div>
|
|
550
|
-
<div class="brain-stat-row"><span class="label">Hypotheses</span><span class="value" id="brainHypotheses">--</span></div>
|
|
551
|
-
<div class="brain-stat-row"><span class="label">Experiments</span><span class="value" id="brainExperiments">--</span></div>
|
|
552
|
-
<div class="brain-stat-row"><span class="label">Focus</span><span class="value" id="brainFocus">--</span></div>
|
|
553
|
-
<a class="dash-link" href="http://localhost:7784" target="_blank">Open Consciousness Dashboard →</a>
|
|
361
|
+
<div class="nav-item" data-page="selfmod">
|
|
362
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
|
|
363
|
+
<span>Self-Mod</span>
|
|
554
364
|
</div>
|
|
555
|
-
<div class="
|
|
556
|
-
<
|
|
557
|
-
<
|
|
558
|
-
<div class="brain-stat-row"><span class="label">Cycle</span><span class="value" id="tradingCycle">--</span></div>
|
|
559
|
-
<div class="brain-stat-row"><span class="label">Principles</span><span class="value" id="tradingPrinciples">--</span></div>
|
|
560
|
-
<div class="brain-stat-row"><span class="label">Hypotheses</span><span class="value" id="tradingHypotheses">--</span></div>
|
|
561
|
-
<div class="brain-stat-row"><span class="label">Experiments</span><span class="value" id="tradingExperiments">--</span></div>
|
|
562
|
-
<div class="brain-stat-row"><span class="label">Focus</span><span class="value" id="tradingFocus">--</span></div>
|
|
563
|
-
<a class="dash-link" href="http://localhost:7785" target="_blank">Open Consciousness Dashboard →</a>
|
|
365
|
+
<div class="nav-item" data-page="engines">
|
|
366
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
|
367
|
+
<span>Engines</span>
|
|
564
368
|
</div>
|
|
565
|
-
<div class="
|
|
566
|
-
<
|
|
567
|
-
<
|
|
568
|
-
<div class="brain-stat-row"><span class="label">Cycle</span><span class="value" id="marketingCycle">--</span></div>
|
|
569
|
-
<div class="brain-stat-row"><span class="label">Principles</span><span class="value" id="marketingPrinciples">--</span></div>
|
|
570
|
-
<div class="brain-stat-row"><span class="label">Hypotheses</span><span class="value" id="marketingHypotheses">--</span></div>
|
|
571
|
-
<div class="brain-stat-row"><span class="label">Experiments</span><span class="value" id="marketingExperiments">--</span></div>
|
|
572
|
-
<div class="brain-stat-row"><span class="label">Focus</span><span class="value" id="marketingFocus">--</span></div>
|
|
573
|
-
<a class="dash-link" href="http://localhost:7786" target="_blank">Open Consciousness Dashboard →</a>
|
|
369
|
+
<div class="nav-item" data-page="intelligence">
|
|
370
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
|
|
371
|
+
<span>Intelligence</span>
|
|
574
372
|
</div>
|
|
575
373
|
</div>
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
<div class="card-title">⚠ Recent Notifications</div>
|
|
580
|
-
<div class="notification-feed" id="overviewNotifs" style="max-height:280px"></div>
|
|
581
|
-
</div>
|
|
582
|
-
</div>
|
|
583
|
-
|
|
584
|
-
<!-- ── Notifications Page ────── -->
|
|
585
|
-
<div class="page" id="page-notifications">
|
|
586
|
-
<div class="card">
|
|
587
|
-
<div class="card-title">⚠ Live Thought Stream</div>
|
|
588
|
-
<div class="notification-feed" id="allNotifs"></div>
|
|
374
|
+
<div class="sidebar-footer">
|
|
375
|
+
<span class="conn-dot off" id="connDot"></span>
|
|
376
|
+
<span class="label" id="connLabel">Disconnected</span>
|
|
589
377
|
</div>
|
|
590
|
-
</
|
|
591
|
-
|
|
592
|
-
<!--
|
|
593
|
-
<div class="
|
|
594
|
-
<
|
|
595
|
-
<div class="
|
|
596
|
-
<
|
|
597
|
-
<
|
|
598
|
-
<span class="context-badge monitoring">unknown</span>
|
|
599
|
-
</div>
|
|
600
|
-
<div class="card-title" style="margin-top:14px">Top Attention Topics</div>
|
|
601
|
-
<div id="topTopics"></div>
|
|
378
|
+
</nav>
|
|
379
|
+
|
|
380
|
+
<!-- MAIN -->
|
|
381
|
+
<div class="main">
|
|
382
|
+
<header class="header">
|
|
383
|
+
<div class="header-left">
|
|
384
|
+
<span class="header-title">Brain Ecosystem</span>
|
|
385
|
+
<span class="header-badge" id="healthBadge">--</span>
|
|
602
386
|
</div>
|
|
603
|
-
<div class="
|
|
604
|
-
<
|
|
605
|
-
<
|
|
606
|
-
<div class="card-title" style="margin-top:20px">Context Switches</div>
|
|
607
|
-
<div id="contextSwitches" style="font-size:12px;color:var(--text-secondary)"></div>
|
|
387
|
+
<div class="header-right">
|
|
388
|
+
<span class="uptime" id="uptimeEl">Uptime: --</span>
|
|
389
|
+
<button class="trigger-btn" onclick="triggerCycle()">Trigger Cycle</button>
|
|
608
390
|
</div>
|
|
609
|
-
</
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
391
|
+
</header>
|
|
392
|
+
|
|
393
|
+
<div class="content">
|
|
394
|
+
<!-- OVERVIEW PAGE -->
|
|
395
|
+
<div class="page active" id="page-overview">
|
|
396
|
+
<div class="stat-grid" id="overviewStats"></div>
|
|
397
|
+
<div class="brain-grid" id="brainCards"></div>
|
|
398
|
+
<div class="two-col">
|
|
399
|
+
<div>
|
|
400
|
+
<div class="section-title">Live Notifications</div>
|
|
401
|
+
<div class="glass"><div class="notif-feed" id="notifFeed"></div></div>
|
|
402
|
+
</div>
|
|
403
|
+
<div>
|
|
404
|
+
<div class="section-title">Neural Preview</div>
|
|
405
|
+
<div class="neural-wrap glass" style="padding:0">
|
|
406
|
+
<canvas class="neural-canvas" id="overviewCanvas" height="280"></canvas>
|
|
407
|
+
<div class="neural-info" id="overviewInfo">0 nodes, 0 edges</div>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
622
411
|
</div>
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
412
|
+
|
|
413
|
+
<!-- NEURAL PAGE -->
|
|
414
|
+
<div class="page" id="page-neural">
|
|
415
|
+
<div class="section-title">Neural Network</div>
|
|
416
|
+
<div class="neural-wrap" style="height:calc(100vh - 130px)">
|
|
417
|
+
<canvas class="neural-canvas" id="neuralCanvas"></canvas>
|
|
418
|
+
<div class="neural-info" id="neuralInfo">0 nodes, 0 edges</div>
|
|
419
|
+
<div class="neural-controls">
|
|
420
|
+
<button class="neural-btn" onclick="neuralZoom(1.2)" title="Zoom In">+</button>
|
|
421
|
+
<button class="neural-btn" onclick="neuralZoom(0.8)" title="Zoom Out">-</button>
|
|
422
|
+
<button class="neural-btn" onclick="neuralReset()" title="Reset">R</button>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
626
425
|
</div>
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
426
|
+
|
|
427
|
+
<!-- THOUGHTS PAGE -->
|
|
428
|
+
<div class="page" id="page-thoughts">
|
|
429
|
+
<div class="section-title">Thought Stream</div>
|
|
430
|
+
<div class="thought-filters" id="thoughtFilters"></div>
|
|
431
|
+
<div class="thought-list" id="thoughtList"></div>
|
|
630
432
|
</div>
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
433
|
+
|
|
434
|
+
<!-- CODEGEN PAGE -->
|
|
435
|
+
<div class="page" id="page-codegen">
|
|
436
|
+
<div class="section-title">Code Generation</div>
|
|
437
|
+
<div id="codegenContent"></div>
|
|
634
438
|
</div>
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
<div class="
|
|
638
|
-
<div class="
|
|
639
|
-
<div id="
|
|
439
|
+
|
|
440
|
+
<!-- SELF-MOD PAGE -->
|
|
441
|
+
<div class="page" id="page-selfmod">
|
|
442
|
+
<div class="section-title">Self-Modification</div>
|
|
443
|
+
<div id="selfmodContent"></div>
|
|
640
444
|
</div>
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
445
|
+
|
|
446
|
+
<!-- ENGINES PAGE -->
|
|
447
|
+
<div class="page" id="page-engines">
|
|
448
|
+
<div class="section-title">Engine Status</div>
|
|
449
|
+
<div class="engine-grid" id="engineGrid"></div>
|
|
644
450
|
</div>
|
|
645
|
-
</div>
|
|
646
|
-
<div class="card">
|
|
647
|
-
<div class="card-title">Transfer History</div>
|
|
648
|
-
<table class="transfer-table" id="transferHistory">
|
|
649
|
-
<thead>
|
|
650
|
-
<tr><th>Source</th><th>Knowledge</th><th>Status</th><th>Confidence</th><th>Date</th></tr>
|
|
651
|
-
</thead>
|
|
652
|
-
<tbody></tbody>
|
|
653
|
-
</table>
|
|
654
|
-
</div>
|
|
655
|
-
</div>
|
|
656
451
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
452
|
+
<!-- INTELLIGENCE PAGE -->
|
|
453
|
+
<div class="page" id="page-intelligence">
|
|
454
|
+
<div class="two-col">
|
|
455
|
+
<div>
|
|
456
|
+
<div class="section-title">Attention Topics</div>
|
|
457
|
+
<div class="glass"><div class="topic-list" id="attentionTopics"></div></div>
|
|
458
|
+
</div>
|
|
459
|
+
<div>
|
|
460
|
+
<div class="section-title">Transfer Rules</div>
|
|
461
|
+
<div class="glass"><div class="rule-list" id="transferRules"></div></div>
|
|
462
|
+
</div>
|
|
463
|
+
</div>
|
|
464
|
+
<div style="margin-top:16px">
|
|
465
|
+
<div class="section-title">Transfer Analogies</div>
|
|
466
|
+
<div class="glass"><div id="analogies"></div></div>
|
|
467
|
+
</div>
|
|
468
|
+
</div>
|
|
666
469
|
</div>
|
|
667
470
|
</div>
|
|
668
|
-
|
|
669
|
-
</main>
|
|
471
|
+
</div>
|
|
670
472
|
|
|
671
473
|
<script>
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
474
|
+
// ═══ STATE ═══
|
|
475
|
+
const MAX_THOUGHTS = 500;
|
|
476
|
+
const MAX_NOTIFS = 100;
|
|
477
|
+
let state = {
|
|
478
|
+
overview: null, transfer: null, attention: null,
|
|
479
|
+
thoughts: [], engines: {}, stats: {},
|
|
480
|
+
notifications: [], network: { nodes: [], edges: [] },
|
|
481
|
+
codegen: null, selfmod: null,
|
|
482
|
+
};
|
|
483
|
+
let connected = false;
|
|
484
|
+
const startTime = Date.now();
|
|
485
|
+
|
|
486
|
+
// Engine colors
|
|
487
|
+
const EC = {
|
|
488
|
+
orchestrator:'#00e5ff', self_observer:'#448aff', anomaly_detective:'#ff9100',
|
|
489
|
+
dream:'#b388ff', cross_domain:'#ff4081', journal:'#00ff88',
|
|
490
|
+
knowledge_distiller:'#ffd700', prediction:'#00e5ff', attention:'#ff6e40',
|
|
491
|
+
transfer:'#ea80fc', narrative:'#69f0ae', curiosity:'#40c4ff',
|
|
492
|
+
emergence:'#ffab40', debate:'#ff80ab', metacognition:'#b2ff59',
|
|
493
|
+
auto_experiment:'#ffd740', selftest:'#84ffff', teach:'#a7ffeb',
|
|
494
|
+
datascout:'#f48fb1', simulation:'#80d8ff', memory_palace:'#ce93d8',
|
|
495
|
+
goal:'#fff176', evolution:'#a5d6a7', reasoning:'#90caf9',
|
|
496
|
+
emotional:'#ef9a9a', self_scanner:'#80cbc4', self_modification:'#ffcc80',
|
|
497
|
+
codegen:'#b0bec5', code_miner:'#8d6e63', bootstrap:'#78909c',
|
|
498
|
+
};
|
|
499
|
+
function engineColor(name) {
|
|
500
|
+
const key = name ? name.toLowerCase().replace(/[^a-z_]/g, '') : '';
|
|
501
|
+
return EC[key] || '#6e7a8a';
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// ═══ SSE CONNECTION ═══
|
|
505
|
+
let evtSource = null;
|
|
506
|
+
function connect() {
|
|
507
|
+
evtSource = new EventSource('/events');
|
|
508
|
+
evtSource.addEventListener('connected', function() {
|
|
509
|
+
connected = true;
|
|
510
|
+
document.getElementById('connDot').className = 'conn-dot on';
|
|
511
|
+
document.getElementById('connLabel').textContent = 'Connected';
|
|
512
|
+
});
|
|
513
|
+
evtSource.addEventListener('thought', function(e) {
|
|
514
|
+
const t = JSON.parse(e.data);
|
|
515
|
+
state.thoughts.unshift(t);
|
|
516
|
+
if (state.thoughts.length > MAX_THOUGHTS) state.thoughts.pop();
|
|
517
|
+
if (t.significance === 'breakthrough' || t.significance === 'notable') {
|
|
518
|
+
state.notifications.unshift(t);
|
|
519
|
+
if (state.notifications.length > MAX_NOTIFS) state.notifications.pop();
|
|
520
|
+
}
|
|
521
|
+
renderThoughts();
|
|
522
|
+
renderNotifications();
|
|
523
|
+
});
|
|
524
|
+
evtSource.addEventListener('status', function(e) {
|
|
525
|
+
const d = JSON.parse(e.data);
|
|
526
|
+
if (d.overview) state.overview = d.overview;
|
|
527
|
+
if (d.engines) state.engines = d.engines;
|
|
528
|
+
if (d.stats) state.stats = d.stats;
|
|
529
|
+
renderOverview();
|
|
530
|
+
renderEngines();
|
|
531
|
+
});
|
|
532
|
+
evtSource.addEventListener('network', function(e) {
|
|
533
|
+
state.network = JSON.parse(e.data);
|
|
534
|
+
renderNetwork();
|
|
535
|
+
});
|
|
536
|
+
evtSource.addEventListener('codegen:generated', function() { fetchCodegen(); });
|
|
537
|
+
evtSource.addEventListener('codegen:approved', function() { fetchCodegen(); });
|
|
538
|
+
evtSource.addEventListener('codegen:rejected', function() { fetchCodegen(); });
|
|
539
|
+
evtSource.addEventListener('selfmod:approved', function() { fetchSelfmod(); });
|
|
540
|
+
evtSource.addEventListener('selfmod:rejected', function() { fetchSelfmod(); });
|
|
541
|
+
evtSource.addEventListener('selfmod:ready', function() { fetchSelfmod(); });
|
|
542
|
+
evtSource.addEventListener('heartbeat', function() {});
|
|
543
|
+
evtSource.onerror = function() {
|
|
544
|
+
connected = false;
|
|
545
|
+
document.getElementById('connDot').className = 'conn-dot off';
|
|
546
|
+
document.getElementById('connLabel').textContent = 'Reconnecting...';
|
|
684
547
|
};
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// ═══ INITIAL FETCH ═══
|
|
551
|
+
async function fetchInitial() {
|
|
552
|
+
try {
|
|
553
|
+
const r = await fetch('/api/state');
|
|
554
|
+
const d = await r.json();
|
|
555
|
+
state.overview = d.overview;
|
|
556
|
+
state.transfer = d.transfer;
|
|
557
|
+
state.attention = d.attention;
|
|
558
|
+
state.thoughts = (d.thoughts || []).slice(0, MAX_THOUGHTS);
|
|
559
|
+
state.engines = d.engines || {};
|
|
560
|
+
state.stats = d.stats || {};
|
|
561
|
+
state.notifications = (d.notifications || []).slice(0, MAX_NOTIFS);
|
|
562
|
+
renderAll();
|
|
563
|
+
} catch(e) { console.warn('fetchInitial failed', e); }
|
|
564
|
+
try {
|
|
565
|
+
const r = await fetch('/api/network');
|
|
566
|
+
state.network = await r.json();
|
|
567
|
+
renderNetwork();
|
|
568
|
+
} catch(e) { console.warn('fetchNetwork failed', e); }
|
|
569
|
+
fetchCodegen();
|
|
570
|
+
fetchSelfmod();
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
async function fetchCodegen() {
|
|
574
|
+
try {
|
|
575
|
+
const r = await fetch('/api/codegen/state');
|
|
576
|
+
state.codegen = await r.json();
|
|
577
|
+
renderCodegen();
|
|
578
|
+
} catch(e) { console.warn('fetchCodegen failed', e); }
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
async function fetchSelfmod() {
|
|
582
|
+
try {
|
|
583
|
+
const r = await fetch('/api/selfmod/list');
|
|
584
|
+
state.selfmod = await r.json();
|
|
585
|
+
renderSelfmod();
|
|
586
|
+
} catch(e) { console.warn('fetchSelfmod failed', e); }
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// ═══ NAVIGATION ═══
|
|
590
|
+
document.querySelectorAll('.nav-item').forEach(function(el) {
|
|
591
|
+
el.addEventListener('click', function() {
|
|
592
|
+
document.querySelectorAll('.nav-item').forEach(function(n) { n.classList.remove('active'); });
|
|
593
|
+
document.querySelectorAll('.page').forEach(function(p) { p.classList.remove('active'); });
|
|
594
|
+
el.classList.add('active');
|
|
595
|
+
var page = el.dataset.page;
|
|
596
|
+
document.getElementById('page-' + page).classList.add('active');
|
|
597
|
+
if (page === 'neural') requestAnimationFrame(function() { resizeNeuralCanvas(); });
|
|
598
|
+
if (page === 'codegen') fetchCodegen();
|
|
599
|
+
if (page === 'selfmod') fetchSelfmod();
|
|
703
600
|
});
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
// ═══ RENDER ═══
|
|
604
|
+
function renderAll() {
|
|
605
|
+
renderOverview();
|
|
606
|
+
renderNotifications();
|
|
607
|
+
renderThoughts();
|
|
608
|
+
renderEngines();
|
|
609
|
+
renderIntelligence();
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
function escapeHtml(s) {
|
|
613
|
+
if (!s) return '';
|
|
614
|
+
return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
function timeSince(ts) {
|
|
618
|
+
var s = Math.floor((Date.now() - ts) / 1000);
|
|
619
|
+
if (s < 60) return s + 's';
|
|
620
|
+
if (s < 3600) return Math.floor(s / 60) + 'm';
|
|
621
|
+
if (s < 86400) return Math.floor(s / 3600) + 'h';
|
|
622
|
+
return Math.floor(s / 86400) + 'd';
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function formatTime(ts) {
|
|
626
|
+
if (!ts) return '--';
|
|
627
|
+
var d = new Date(typeof ts === 'number' ? ts : ts);
|
|
628
|
+
return d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// ── Overview ──
|
|
632
|
+
function renderOverview() {
|
|
633
|
+
var o = state.overview;
|
|
634
|
+
var healthScore = o && o.healthScore != null ? o.healthScore : '--';
|
|
635
|
+
document.getElementById('healthBadge').textContent = typeof healthScore === 'number' ? 'Health: ' + healthScore : '--';
|
|
636
|
+
|
|
637
|
+
var stats = state.stats;
|
|
638
|
+
var el = document.getElementById('overviewStats');
|
|
639
|
+
var brains = o && o.brains ? o.brains : {};
|
|
640
|
+
var brain = brains.brain || {};
|
|
641
|
+
el.innerHTML =
|
|
642
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--cyan)">' + (stats.total || 0) + '</div><div class="stat-label">Thoughts</div></div>' +
|
|
643
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--green)">' + (brain.principles || 0) + '</div><div class="stat-label">Principles</div></div>' +
|
|
644
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--gold)">' + (brain.hypotheses || 0) + '</div><div class="stat-label">Hypotheses</div></div>' +
|
|
645
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--purple)">' + (brain.experiments || 0) + '</div><div class="stat-label">Experiments</div></div>' +
|
|
646
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--orange)">' + (brain.cycle || 0) + '</div><div class="stat-label">Cycle</div></div>';
|
|
647
|
+
|
|
648
|
+
var grid = document.getElementById('brainCards');
|
|
649
|
+
var html = '';
|
|
650
|
+
for (var name in brains) {
|
|
651
|
+
var b = brains[name];
|
|
652
|
+
var cls = name === 'brain' ? 'brain-main' : name.indexOf('trading') >= 0 ? 'brain-trading' : 'brain-marketing';
|
|
653
|
+
html += '<div class="glass brain-card ' + cls + '">' +
|
|
654
|
+
'<div class="brain-name">' + escapeHtml(name) + '</div>' +
|
|
655
|
+
'<div class="brain-stat"><span>Status</span><span class="val">' + (b.status || '--') + '</span></div>' +
|
|
656
|
+
'<div class="brain-stat"><span>Cycle</span><span class="val">' + (b.cycle || 0) + '</span></div>' +
|
|
657
|
+
'<div class="brain-stat"><span>Focus</span><span class="val">' + escapeHtml(b.focus || 'idle') + '</span></div>' +
|
|
658
|
+
'</div>';
|
|
659
|
+
}
|
|
660
|
+
grid.innerHTML = html;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// ── Notifications ──
|
|
664
|
+
function renderNotifications() {
|
|
665
|
+
var el = document.getElementById('notifFeed');
|
|
666
|
+
var items = state.notifications.slice(0, 50);
|
|
667
|
+
var html = '';
|
|
668
|
+
for (var i = 0; i < items.length; i++) {
|
|
669
|
+
var t = items[i];
|
|
670
|
+
var cls = t.significance === 'breakthrough' ? 'breakthrough' : t.significance === 'notable' ? 'notable' : '';
|
|
671
|
+
html += '<div class="notif-item ' + cls + '">' +
|
|
672
|
+
'<span class="notif-time">' + formatTime(t.timestamp) + '</span>' +
|
|
673
|
+
'<span class="notif-engine" style="background:' + engineColor(t.engine) + '22;color:' + engineColor(t.engine) + '">' + escapeHtml(t.engine) + '</span>' +
|
|
674
|
+
'<span class="notif-msg">' + escapeHtml(t.content) + '</span></div>';
|
|
675
|
+
}
|
|
676
|
+
el.innerHTML = html || '<div style="color:var(--text-muted);padding:20px;text-align:center">No notifications yet</div>';
|
|
677
|
+
}
|
|
704
678
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
const res = await fetch('/api/trigger', { method: 'POST' });
|
|
709
|
-
const data = await res.json();
|
|
710
|
-
if (data.triggered) {
|
|
711
|
-
document.getElementById('triggerBtn').textContent = '\u2713 Triggered!';
|
|
712
|
-
setTimeout(() => { document.getElementById('triggerBtn').innerHTML = '⚡ Trigger Cycle'; }, 2000);
|
|
713
|
-
}
|
|
714
|
-
} catch (e) { console.error('Trigger failed', e); }
|
|
715
|
-
});
|
|
679
|
+
// ── Thoughts ──
|
|
680
|
+
var thoughtFilter = 'all';
|
|
681
|
+
var knownEngines = {};
|
|
716
682
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
if (
|
|
720
|
-
|
|
721
|
-
|
|
683
|
+
function renderThoughtFilters() {
|
|
684
|
+
for (var i = 0; i < state.thoughts.length; i++) {
|
|
685
|
+
if (state.thoughts[i].engine) knownEngines[state.thoughts[i].engine] = true;
|
|
686
|
+
}
|
|
687
|
+
var el = document.getElementById('thoughtFilters');
|
|
688
|
+
var engines = ['all'].concat(Object.keys(knownEngines).sort());
|
|
689
|
+
var html = '';
|
|
690
|
+
for (var j = 0; j < engines.length; j++) {
|
|
691
|
+
html += '<button class="thought-filter ' + (engines[j] === thoughtFilter ? 'active' : '') + '" onclick="setThoughtFilter(\'' + engines[j] + '\')">' + engines[j] + '</button>';
|
|
692
|
+
}
|
|
693
|
+
el.innerHTML = html;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
function setThoughtFilter(f) {
|
|
697
|
+
thoughtFilter = f;
|
|
698
|
+
renderThoughts();
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function renderThoughts() {
|
|
702
|
+
renderThoughtFilters();
|
|
703
|
+
var filtered = thoughtFilter === 'all' ? state.thoughts : state.thoughts.filter(function(t) { return t.engine === thoughtFilter; });
|
|
704
|
+
var el = document.getElementById('thoughtList');
|
|
705
|
+
var html = '';
|
|
706
|
+
var items = filtered.slice(0, 200);
|
|
707
|
+
for (var i = 0; i < items.length; i++) {
|
|
708
|
+
var t = items[i];
|
|
709
|
+
var sig = t.significance === 'breakthrough' ? 'sig-breakthrough' : t.significance === 'notable' ? 'sig-notable' : '';
|
|
710
|
+
html += '<div class="thought-item ' + sig + '">' +
|
|
711
|
+
'<span class="time">' + formatTime(t.timestamp) + '</span>' +
|
|
712
|
+
'<span class="engine-tag" style="background:' + engineColor(t.engine) + '18;color:' + engineColor(t.engine) + '">' + escapeHtml(t.engine) + '</span>' +
|
|
713
|
+
'<span class="msg">' + escapeHtml(t.content) + '</span></div>';
|
|
714
|
+
}
|
|
715
|
+
el.innerHTML = html || '<div style="color:var(--text-muted);padding:20px;text-align:center">No thoughts yet</div>';
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// ── CodeGen ──
|
|
719
|
+
function renderCodegen() {
|
|
720
|
+
var el = document.getElementById('codegenContent');
|
|
721
|
+
var cg = state.codegen;
|
|
722
|
+
if (!cg || !cg.available) {
|
|
723
|
+
el.innerHTML = '<div class="unavailable glass"><div class="icon"></></div><div>CodeGenerator not available.</div>' +
|
|
724
|
+
'<div style="margin-top:12px;font-size:11px;color:var(--text-dim)">Set the <code style="color:var(--cyan)">ANTHROPIC_API_KEY</code> environment variable before starting the Brain daemon to enable autonomous code generation and self-modification.</div>' +
|
|
725
|
+
'<div style="margin-top:12px;padding:10px;background:rgba(5,8,16,0.6);border-radius:6px;font-size:10px;color:var(--text-muted);text-align:left;max-width:500px;margin-left:auto;margin-right:auto">' +
|
|
726
|
+
'<div style="margin-bottom:4px;color:var(--text-dim)">Linux / macOS:</div>' +
|
|
727
|
+
'<code style="color:var(--green)">export ANTHROPIC_API_KEY=sk-ant-...</code>' +
|
|
728
|
+
'<div style="margin-top:8px;margin-bottom:4px;color:var(--text-dim)">Windows:</div>' +
|
|
729
|
+
'<code style="color:var(--green)">set ANTHROPIC_API_KEY=sk-ant-...</code>' +
|
|
730
|
+
'</div><div style="margin-top:10px;font-size:10px;color:var(--text-muted)">Then restart the Brain process.</div></div>';
|
|
731
|
+
return;
|
|
722
732
|
}
|
|
723
733
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
734
|
+
var summary = cg.summary || {};
|
|
735
|
+
var pending = cg.pending || [];
|
|
736
|
+
var gens = cg.generations || [];
|
|
737
|
+
var html = '';
|
|
738
|
+
|
|
739
|
+
// Stats
|
|
740
|
+
html += '<div class="stat-grid" style="margin-bottom:16px">' +
|
|
741
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--cyan)">' + (summary.totalGenerations || 0) + '</div><div class="stat-label">Total</div></div>' +
|
|
742
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--green)">' + (summary.approvalRate != null ? Math.round(summary.approvalRate * 100) + '%' : '--') + '</div><div class="stat-label">Approval</div></div>' +
|
|
743
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--gold)">' + (summary.totalTokens || 0) + '</div><div class="stat-label">Tokens</div></div></div>';
|
|
744
|
+
|
|
745
|
+
// Generate form
|
|
746
|
+
html += '<div class="glass" style="margin-bottom:16px"><div class="section-title">Generate Code</div>' +
|
|
747
|
+
'<div class="codegen-form"><textarea id="codegenTask" placeholder="Describe the task..."></textarea>' +
|
|
748
|
+
'<div style="display:flex;flex-direction:column;gap:6px">' +
|
|
749
|
+
'<select id="codegenLang"><option>typescript</option><option>javascript</option><option>python</option><option>rust</option><option>go</option></select>' +
|
|
750
|
+
'<button class="gen-btn" onclick="generateCode()">Generate</button></div></div></div>';
|
|
751
|
+
|
|
752
|
+
// Pending reviews
|
|
753
|
+
for (var i = 0; i < pending.length; i++) {
|
|
754
|
+
var g = pending[i];
|
|
755
|
+
html += '<div class="glass pending-card">' +
|
|
756
|
+
'<div style="font-size:11px;font-weight:600;margin-bottom:4px">#' + g.id + ' — ' + escapeHtml(g.task) + '</div>' +
|
|
757
|
+
'<div class="code-block">' + highlightSyntax(escapeHtml(g.generated_code || '')) + '</div>';
|
|
758
|
+
if (g.generated_explanation) {
|
|
759
|
+
html += '<div style="font-size:10px;color:var(--text-dim);margin:4px 0;padding:6px 10px;border-left:2px solid var(--purple);background:rgba(179,136,255,0.04)">' + escapeHtml(g.generated_explanation) + '</div>';
|
|
760
|
+
}
|
|
761
|
+
html += '<div class="review-actions"><input type="text" id="notes-' + g.id + '" placeholder="Notes (optional)...">' +
|
|
762
|
+
'<button class="btn-approve" onclick="reviewCode(' + g.id + ',\'approve\')">Approve</button>' +
|
|
763
|
+
'<button class="btn-reject" onclick="reviewCode(' + g.id + ',\'reject\')">Reject</button></div></div>';
|
|
731
764
|
}
|
|
732
765
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
766
|
+
// History table
|
|
767
|
+
html += '<div class="gen-history"><div class="section-title">Generation History</div><div class="glass" style="overflow-x:auto"><table class="gen-table"><thead><tr><th>ID</th><th>Task</th><th>Status</th><th>Tokens</th><th>Time</th><th>Created</th></tr></thead><tbody>';
|
|
768
|
+
for (var j = 0; j < Math.min(gens.length, 30); j++) {
|
|
769
|
+
var gen = gens[j];
|
|
770
|
+
html += '<tr><td>#' + gen.id + '</td><td>' + escapeHtml((gen.task || '').substring(0, 60)) + '</td>' +
|
|
771
|
+
'<td><span class="status-badge ' + gen.status + '">' + gen.status + '</span></td>' +
|
|
772
|
+
'<td>' + (gen.tokens_used || 0) + '</td><td>' + (gen.generation_time_ms ? gen.generation_time_ms + 'ms' : '--') + '</td>' +
|
|
773
|
+
'<td>' + formatTime(gen.created_at) + '</td></tr>';
|
|
774
|
+
}
|
|
775
|
+
html += '</tbody></table></div></div>';
|
|
776
|
+
el.innerHTML = html;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
async function generateCode() {
|
|
780
|
+
var task = document.getElementById('codegenTask');
|
|
781
|
+
var lang = document.getElementById('codegenLang');
|
|
782
|
+
if (!task || !task.value.trim()) return;
|
|
783
|
+
try {
|
|
784
|
+
await fetch('/api/codegen/generate', {
|
|
785
|
+
method: 'POST',
|
|
786
|
+
headers: { 'Content-Type': 'application/json' },
|
|
787
|
+
body: JSON.stringify({ task: task.value.trim(), language: lang ? lang.value : 'typescript' }),
|
|
788
|
+
});
|
|
789
|
+
task.value = '';
|
|
790
|
+
} catch(e) { console.warn('generateCode failed', e); }
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
async function reviewCode(id, action) {
|
|
794
|
+
var notes = document.getElementById('notes-' + id);
|
|
795
|
+
try {
|
|
796
|
+
await fetch('/api/codegen/' + action + '/' + id, {
|
|
797
|
+
method: 'POST',
|
|
798
|
+
headers: { 'Content-Type': 'application/json' },
|
|
799
|
+
body: JSON.stringify({ notes: notes ? notes.value : '' }),
|
|
800
|
+
});
|
|
801
|
+
fetchCodegen();
|
|
802
|
+
} catch(e) { console.warn('reviewCode failed', e); }
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// ── Self-Mod ──
|
|
806
|
+
function renderSelfmod() {
|
|
807
|
+
var el = document.getElementById('selfmodContent');
|
|
808
|
+
var sm = state.selfmod;
|
|
809
|
+
if (!sm || !sm.available) {
|
|
810
|
+
el.innerHTML = '<div class="unavailable glass"><div class="icon">✎</div><div>SelfModificationEngine not available.</div></div>';
|
|
811
|
+
return;
|
|
737
812
|
}
|
|
738
813
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
814
|
+
var status = sm.status || {};
|
|
815
|
+
var pending = sm.pending || [];
|
|
816
|
+
var history = sm.history || [];
|
|
817
|
+
var html = '';
|
|
818
|
+
|
|
819
|
+
// Stats
|
|
820
|
+
var byStatus = status.byStatus || {};
|
|
821
|
+
html += '<div class="stat-grid" style="margin-bottom:16px">' +
|
|
822
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--cyan)">' + (status.totalModifications || 0) + '</div><div class="stat-label">Total</div></div>' +
|
|
823
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--green)">' + (byStatus.applied || 0) + '</div><div class="stat-label">Applied</div></div>' +
|
|
824
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--gold)">' + (byStatus.ready || 0) + '</div><div class="stat-label">Ready</div></div>' +
|
|
825
|
+
'<div class="glass stat-card"><div class="stat-val" style="color:var(--red)">' + (byStatus.rejected || 0) + '</div><div class="stat-label">Rejected</div></div></div>';
|
|
826
|
+
|
|
827
|
+
// Pending modifications
|
|
828
|
+
for (var i = 0; i < pending.length; i++) {
|
|
829
|
+
var m = pending[i];
|
|
830
|
+
html += '<div class="glass pending-card" style="margin-bottom:12px">' +
|
|
831
|
+
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px">' +
|
|
832
|
+
'<span style="font-size:11px;font-weight:600">#' + m.id + ' — ' + escapeHtml(m.title) + '</span>' +
|
|
833
|
+
'<span class="status-badge ' + m.status + '">' + m.status + '</span></div>' +
|
|
834
|
+
'<div style="font-size:10px;color:var(--text-dim);margin-bottom:8px">' + escapeHtml(m.problem_description) + '</div>' +
|
|
835
|
+
'<div style="font-size:10px;color:var(--text-muted);margin-bottom:4px">Files: ' + (m.target_files || []).map(function(f) { return escapeHtml(f); }).join(', ') + '</div>';
|
|
836
|
+
|
|
837
|
+
// Diff viewer
|
|
838
|
+
if (m.generated_diff && m.generated_diff.length > 0) {
|
|
839
|
+
for (var d = 0; d < m.generated_diff.length; d++) {
|
|
840
|
+
var diff = m.generated_diff[d];
|
|
841
|
+
html += '<div style="font-size:9px;color:var(--text-muted);margin-top:6px">' + escapeHtml(diff.filePath) + '</div>' +
|
|
842
|
+
'<div class="diff-viewer">' +
|
|
843
|
+
'<div class="diff-old"><div class="diff-label">Old</div>' + renderDiffLines(diff.oldContent, 'del') + '</div>' +
|
|
844
|
+
'<div class="diff-new"><div class="diff-label">New</div>' + renderDiffLines(diff.newContent, 'add') + '</div></div>';
|
|
845
|
+
}
|
|
763
846
|
}
|
|
764
847
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
// Brain cards
|
|
769
|
-
renderBrainCards(ov);
|
|
848
|
+
if (m.test_output) {
|
|
849
|
+
html += '<div style="font-size:10px;margin-top:6px;padding:8px;background:rgba(5,8,16,0.6);border-radius:4px;color:var(--text-dim);max-height:100px;overflow-y:auto"><pre style="margin:0;white-space:pre-wrap">' + escapeHtml(m.test_output) + '</pre></div>';
|
|
850
|
+
}
|
|
770
851
|
|
|
771
|
-
|
|
772
|
-
|
|
852
|
+
html += '<div class="review-actions">' +
|
|
853
|
+
'<button class="btn-test" onclick="selfmodAction(' + m.id + ',\'test\')">Test</button>' +
|
|
854
|
+
'<button class="btn-approve" onclick="selfmodAction(' + m.id + ',\'approve\')">Approve</button>' +
|
|
855
|
+
'<button class="btn-reject" onclick="selfmodAction(' + m.id + ',\'reject\')">Reject</button></div></div>';
|
|
773
856
|
}
|
|
774
857
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
badge.className = 'health-badge healthy';
|
|
785
|
-
}
|
|
858
|
+
// History table
|
|
859
|
+
html += '<div style="margin-top:16px"><div class="section-title">Modification History</div><div class="glass" style="overflow-x:auto"><table class="gen-table"><thead><tr><th>ID</th><th>Title</th><th>Status</th><th>Test</th><th>Files</th><th>Created</th></tr></thead><tbody>';
|
|
860
|
+
for (var j = 0; j < history.length; j++) {
|
|
861
|
+
var h = history[j];
|
|
862
|
+
var testCls = h.test_result === 'passed' ? 'approved' : h.test_result === 'failed' ? 'failed' : 'proposed';
|
|
863
|
+
html += '<tr><td>#' + h.id + '</td><td>' + escapeHtml((h.title || '').substring(0, 50)) + '</td>' +
|
|
864
|
+
'<td><span class="status-badge ' + h.status + '">' + h.status + '</span></td>' +
|
|
865
|
+
'<td><span class="status-badge ' + testCls + '">' + (h.test_result || 'pending') + '</span></td>' +
|
|
866
|
+
'<td>' + (h.target_files || []).length + '</td><td>' + formatTime(h.created_at) + '</td></tr>';
|
|
786
867
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
setText('marketingHypotheses', marketing.hypotheses);
|
|
816
|
-
setText('marketingExperiments', marketing.experiments);
|
|
817
|
-
setText('marketingFocus', marketing.focus || '--');
|
|
868
|
+
html += '</tbody></table></div></div>';
|
|
869
|
+
el.innerHTML = html;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
function renderDiffLines(content, type) {
|
|
873
|
+
if (!content) return '<span style="color:var(--text-muted)">Empty</span>';
|
|
874
|
+
return escapeHtml(content).split('\n').map(function(line) {
|
|
875
|
+
return '<div class="diff-line-' + type + '">' + (line || ' ') + '</div>';
|
|
876
|
+
}).join('');
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
async function selfmodAction(id, action) {
|
|
880
|
+
try {
|
|
881
|
+
await fetch('/api/selfmod/' + id + '/' + action, { method: 'POST' });
|
|
882
|
+
fetchSelfmod();
|
|
883
|
+
} catch(e) { console.warn('selfmodAction failed', e); }
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// ── Engines ──
|
|
887
|
+
function renderEngines() {
|
|
888
|
+
var el = document.getElementById('engineGrid');
|
|
889
|
+
var engines = state.engines || {};
|
|
890
|
+
var entries = [];
|
|
891
|
+
for (var name in engines) entries.push([name, engines[name]]);
|
|
892
|
+
entries.sort(function(a, b) { return (b[1].count || 0) - (a[1].count || 0); });
|
|
893
|
+
if (entries.length === 0) {
|
|
894
|
+
el.innerHTML = '<div style="color:var(--text-muted);padding:20px;text-align:center;grid-column:1/-1">No engine data yet</div>';
|
|
895
|
+
return;
|
|
818
896
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
897
|
+
var maxCount = 1;
|
|
898
|
+
for (var i = 0; i < entries.length; i++) maxCount = Math.max(maxCount, entries[i][1].count || 0);
|
|
899
|
+
var html = '';
|
|
900
|
+
for (var j = 0; j < entries.length; j++) {
|
|
901
|
+
var n = entries[j][0], data = entries[j][1];
|
|
902
|
+
var col = engineColor(n);
|
|
903
|
+
var pct = Math.round(((data.count || 0) / maxCount) * 100);
|
|
904
|
+
html += '<div class="glass engine-card">' +
|
|
905
|
+
'<div class="e-name"><div class="e-dot" style="background:' + col + '"></div>' + escapeHtml(n) + '</div>' +
|
|
906
|
+
'<div class="e-stat"><span>Thoughts</span><span>' + (data.count || 0) + '</span></div>' +
|
|
907
|
+
'<div class="e-stat"><span>Last</span><span>' + (data.lastTimestamp ? timeSince(data.lastTimestamp) + ' ago' : '--') + '</span></div>' +
|
|
908
|
+
'<div class="e-bar"><div class="e-bar-fill" style="width:' + pct + '%;background:' + col + '"></div></div></div>';
|
|
824
909
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
910
|
+
el.innerHTML = html;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// ── Intelligence ──
|
|
914
|
+
function renderIntelligence() {
|
|
915
|
+
var att = state.attention;
|
|
916
|
+
var topEl = document.getElementById('attentionTopics');
|
|
917
|
+
if (att && att.topTopics && att.topTopics.length) {
|
|
918
|
+
var max = 1;
|
|
919
|
+
for (var i = 0; i < att.topTopics.length; i++) max = Math.max(max, att.topTopics[i].score || 0);
|
|
920
|
+
var html = '';
|
|
921
|
+
var items = att.topTopics.slice(0, 15);
|
|
922
|
+
for (var j = 0; j < items.length; j++) {
|
|
923
|
+
var t = items[j];
|
|
924
|
+
var pct = Math.round(((t.score || 0) / max) * 100);
|
|
925
|
+
html += '<div class="topic-item"><span class="topic-name">' + escapeHtml(t.topic) + '</span>' +
|
|
926
|
+
'<div class="topic-bar-bg"><div class="topic-bar-fill" style="width:' + pct + '%"></div></div>' +
|
|
927
|
+
'<span class="topic-score">' + (t.score || 0).toFixed(1) + '</span></div>';
|
|
928
|
+
}
|
|
929
|
+
topEl.innerHTML = html;
|
|
930
|
+
} else {
|
|
931
|
+
topEl.innerHTML = '<div style="color:var(--text-muted);text-align:center;padding:16px">No attention data</div>';
|
|
829
932
|
}
|
|
830
933
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
}).join('');
|
|
934
|
+
var tr = state.transfer;
|
|
935
|
+
var ruleEl = document.getElementById('transferRules');
|
|
936
|
+
if (tr && tr.rules && tr.rules.length) {
|
|
937
|
+
var rHtml = '';
|
|
938
|
+
for (var k = 0; k < tr.rules.length; k++) {
|
|
939
|
+
var r = tr.rules[k];
|
|
940
|
+
rHtml += '<div class="rule-item"><span class="r-name">' + escapeHtml(r.name || r.event_pattern || 'Rule') + '</span>' +
|
|
941
|
+
'<span class="r-status" style="color:' + (r.active ? 'var(--green)' : 'var(--text-muted)') + '">' + (r.active ? 'active' : 'inactive') + '</span></div>';
|
|
942
|
+
}
|
|
943
|
+
ruleEl.innerHTML = rHtml;
|
|
944
|
+
} else {
|
|
945
|
+
ruleEl.innerHTML = '<div style="color:var(--text-muted);text-align:center;padding:16px">No transfer rules</div>';
|
|
844
946
|
}
|
|
845
947
|
|
|
846
|
-
|
|
847
|
-
|
|
948
|
+
var anaEl = document.getElementById('analogies');
|
|
949
|
+
if (tr && tr.analogies && tr.analogies.length) {
|
|
950
|
+
var aHtml = '<div style="display:flex;flex-direction:column;gap:4px">';
|
|
951
|
+
var anas = tr.analogies.slice(0, 15);
|
|
952
|
+
for (var l = 0; l < anas.length; l++) {
|
|
953
|
+
var a = anas[l];
|
|
954
|
+
aHtml += '<div style="display:flex;justify-content:space-between;font-size:10px;padding:4px 0;border-bottom:1px solid var(--border)">' +
|
|
955
|
+
'<span>' + escapeHtml(a.source_concept) + ' ↔ ' + escapeHtml(a.target_concept) + '</span>' +
|
|
956
|
+
'<span style="color:var(--gold)">' + (a.similarity || 0).toFixed(2) + '</span></div>';
|
|
957
|
+
}
|
|
958
|
+
aHtml += '</div>';
|
|
959
|
+
anaEl.innerHTML = aHtml;
|
|
960
|
+
} else {
|
|
961
|
+
anaEl.innerHTML = '<div style="color:var(--text-muted);text-align:center;padding:16px">No analogies found</div>';
|
|
848
962
|
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// ═══ NEURAL GRAPH ═══
|
|
966
|
+
var nodeTypeColors = {
|
|
967
|
+
project:'#00e5ff', error:'#ff3d3d', solution:'#00ff88',
|
|
968
|
+
code_module:'#448aff', insight:'#ffd700', memory:'#b388ff'
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
var neuralNodes = [];
|
|
972
|
+
var neuralEdges = [];
|
|
973
|
+
var neuralZoomLevel = 1;
|
|
974
|
+
var neuralPanX = 0, neuralPanY = 0;
|
|
975
|
+
var neuralDragging = null;
|
|
976
|
+
var neuralPanning = false;
|
|
977
|
+
var neuralPanStart = { x: 0, y: 0 };
|
|
978
|
+
var neuralHover = null;
|
|
979
|
+
var neuralAnimId = null;
|
|
980
|
+
|
|
981
|
+
function initNeuralGraph(canvasId) {
|
|
982
|
+
var canvas = document.getElementById(canvasId);
|
|
983
|
+
if (!canvas) return;
|
|
984
|
+
|
|
985
|
+
canvas.addEventListener('mousedown', function(e) {
|
|
986
|
+
var pos = getCanvasPos(canvas, e);
|
|
987
|
+
var node = findNodeAt(pos.x, pos.y);
|
|
988
|
+
if (node) {
|
|
989
|
+
neuralDragging = node;
|
|
990
|
+
node.pinned = true;
|
|
991
|
+
} else {
|
|
992
|
+
neuralPanning = true;
|
|
993
|
+
neuralPanStart = { x: e.clientX - neuralPanX, y: e.clientY - neuralPanY };
|
|
994
|
+
}
|
|
995
|
+
});
|
|
849
996
|
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
997
|
+
canvas.addEventListener('mousemove', function(e) {
|
|
998
|
+
var pos = getCanvasPos(canvas, e);
|
|
999
|
+
if (neuralDragging) {
|
|
1000
|
+
neuralDragging.x = pos.x;
|
|
1001
|
+
neuralDragging.y = pos.y;
|
|
1002
|
+
} else if (neuralPanning) {
|
|
1003
|
+
neuralPanX = e.clientX - neuralPanStart.x;
|
|
1004
|
+
neuralPanY = e.clientY - neuralPanStart.y;
|
|
1005
|
+
} else {
|
|
1006
|
+
neuralHover = findNodeAt(pos.x, pos.y);
|
|
1007
|
+
canvas.style.cursor = neuralHover ? 'pointer' : 'grab';
|
|
856
1008
|
}
|
|
1009
|
+
});
|
|
857
1010
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
1011
|
+
canvas.addEventListener('mouseup', function() {
|
|
1012
|
+
if (neuralDragging) neuralDragging.pinned = false;
|
|
1013
|
+
neuralDragging = null;
|
|
1014
|
+
neuralPanning = false;
|
|
1015
|
+
});
|
|
862
1016
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1017
|
+
canvas.addEventListener('mouseleave', function() {
|
|
1018
|
+
neuralDragging = null;
|
|
1019
|
+
neuralPanning = false;
|
|
1020
|
+
neuralHover = null;
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
canvas.addEventListener('wheel', function(e) {
|
|
1024
|
+
e.preventDefault();
|
|
1025
|
+
var factor = e.deltaY < 0 ? 1.1 : 0.9;
|
|
1026
|
+
neuralZoomLevel = Math.max(0.2, Math.min(5, neuralZoomLevel * factor));
|
|
1027
|
+
}, { passive: false });
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
function getCanvasPos(canvas, e) {
|
|
1031
|
+
var rect = canvas.getBoundingClientRect();
|
|
1032
|
+
return {
|
|
1033
|
+
x: (e.clientX - rect.left - neuralPanX) / neuralZoomLevel,
|
|
1034
|
+
y: (e.clientY - rect.top - neuralPanY) / neuralZoomLevel,
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
function findNodeAt(x, y) {
|
|
1039
|
+
for (var i = 0; i < neuralNodes.length; i++) {
|
|
1040
|
+
var n = neuralNodes[i];
|
|
1041
|
+
var dx = n.x - x, dy = n.y - y;
|
|
1042
|
+
if (dx * dx + dy * dy < (n.radius || 5) * (n.radius || 5) * 4) return n;
|
|
1043
|
+
}
|
|
1044
|
+
return null;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
function neuralZoom(factor) {
|
|
1048
|
+
neuralZoomLevel = Math.max(0.2, Math.min(5, neuralZoomLevel * factor));
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
function neuralReset() {
|
|
1052
|
+
neuralZoomLevel = 1;
|
|
1053
|
+
neuralPanX = 0;
|
|
1054
|
+
neuralPanY = 0;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
function updateNeuralNodes(network) {
|
|
1058
|
+
var existingMap = {};
|
|
1059
|
+
for (var i = 0; i < neuralNodes.length; i++) existingMap[neuralNodes[i].id] = neuralNodes[i];
|
|
1060
|
+
var newNodes = [];
|
|
1061
|
+
var nodes = network.nodes || [];
|
|
1062
|
+
|
|
1063
|
+
for (var j = 0; j < nodes.length; j++) {
|
|
1064
|
+
var n = nodes[j];
|
|
1065
|
+
var existing = existingMap[n.id];
|
|
1066
|
+
if (existing) {
|
|
1067
|
+
existing.label = n.label;
|
|
1068
|
+
existing.type = n.type;
|
|
1069
|
+
existing.importance = n.importance != null ? n.importance : 0.5;
|
|
1070
|
+
newNodes.push(existing);
|
|
867
1071
|
} else {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
1072
|
+
var angle = (j / Math.max(1, nodes.length)) * Math.PI * 2;
|
|
1073
|
+
var r = 150 + Math.random() * 100;
|
|
1074
|
+
newNodes.push({
|
|
1075
|
+
id: n.id, label: n.label, type: n.type,
|
|
1076
|
+
importance: n.importance != null ? n.importance : 0.5,
|
|
1077
|
+
x: 300 + Math.cos(angle) * r + (Math.random() - 0.5) * 50,
|
|
1078
|
+
y: 250 + Math.sin(angle) * r + (Math.random() - 0.5) * 50,
|
|
1079
|
+
vx: 0, vy: 0,
|
|
1080
|
+
radius: 3 + (n.importance != null ? n.importance : 0.5) * 5,
|
|
1081
|
+
pinned: false,
|
|
1082
|
+
});
|
|
877
1083
|
}
|
|
878
|
-
|
|
879
|
-
// Urgent topics
|
|
880
|
-
const urgent = att.urgentTopics || [];
|
|
881
|
-
document.getElementById('urgentTopics').innerHTML = urgent.length === 0
|
|
882
|
-
? '<span style="color:var(--text-muted)">No urgent topics</span>'
|
|
883
|
-
: urgent.map(t =>
|
|
884
|
-
'<div class="topic-bar">' +
|
|
885
|
-
'<span class="topic-name" style="color:var(--gold)">' + escapeHtml(t.topic || t.name || '?') + '</span>' +
|
|
886
|
-
'<span class="topic-score" style="color:var(--gold)">' + (t.urgency || t.score || 0).toFixed(2) + '</span>' +
|
|
887
|
-
'</div>'
|
|
888
|
-
).join('');
|
|
889
|
-
|
|
890
|
-
// Context switches
|
|
891
|
-
const switches = att.recentSwitches || [];
|
|
892
|
-
document.getElementById('contextSwitches').innerHTML = switches.length === 0
|
|
893
|
-
? '<span style="color:var(--text-muted)">No context switches</span>'
|
|
894
|
-
: switches.slice(0, 10).map(s =>
|
|
895
|
-
'<div style="padding:3px 0">' + formatTime(s.timestamp) + ' — ' +
|
|
896
|
-
'<span class="context-badge ' + (s.from || '') + '">' + escapeHtml(s.from || '?') + '</span>' +
|
|
897
|
-
' → <span class="context-badge ' + (s.to || '') + '">' + escapeHtml(s.to || '?') + '</span>' +
|
|
898
|
-
'</div>'
|
|
899
|
-
).join('');
|
|
900
|
-
|
|
901
|
-
// Focus timeline
|
|
902
|
-
const timeline = att.focusTimeline || att.timeline || [];
|
|
903
|
-
document.getElementById('focusTimeline').innerHTML = timeline.length === 0
|
|
904
|
-
? '<span style="color:var(--text-muted)">No focus history</span>'
|
|
905
|
-
: timeline.slice(0, 20).map(f =>
|
|
906
|
-
'<div style="padding:2px 0">' + formatTime(f.timestamp) + ' — ' +
|
|
907
|
-
'<strong>' + escapeHtml(f.topic || '?') + '</strong> (score: ' + (f.score || 0).toFixed(2) + ')' +
|
|
908
|
-
'</div>'
|
|
909
|
-
).join('');
|
|
910
1084
|
}
|
|
911
1085
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
const rules = tr.rules || [];
|
|
940
|
-
document.getElementById('ruleList').innerHTML = rules.length === 0
|
|
941
|
-
? '<span style="color:var(--text-muted)">No rules configured</span>'
|
|
942
|
-
: rules.map(r =>
|
|
943
|
-
'<div class="rule-item">' +
|
|
944
|
-
'<span class="' + (r.enabled ? 'rule-enabled' : 'rule-disabled') + '">' + (r.enabled ? '\u25CF' : '\u25CB') + '</span>' +
|
|
945
|
-
'<span style="color:var(--text-primary)">' + escapeHtml(r.name || '?') + '</span>' +
|
|
946
|
-
'<span class="rule-arrow">' + escapeHtml(r.source_brain || '?') + ' → ' + escapeHtml(r.target_brain || '?') + '</span>' +
|
|
947
|
-
'<span style="color:var(--text-muted);margin-left:auto">fired: ' + (r.fire_count || 0) + '</span>' +
|
|
948
|
-
'</div>'
|
|
949
|
-
).join('');
|
|
950
|
-
|
|
951
|
-
// Transfer history
|
|
952
|
-
const history = tr.history || [];
|
|
953
|
-
const tbody = document.querySelector('#transferHistory tbody');
|
|
954
|
-
if (tbody) {
|
|
955
|
-
tbody.innerHTML = history.length === 0
|
|
956
|
-
? '<tr><td colspan="5" style="color:var(--text-muted)">No transfers yet</td></tr>'
|
|
957
|
-
: history.slice(0, 30).map(h =>
|
|
958
|
-
'<tr>' +
|
|
959
|
-
'<td>' + escapeHtml(h.source_brain || '?') + '</td>' +
|
|
960
|
-
'<td style="max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + escapeHtml(h.knowledge || h.statement || '?') + '</td>' +
|
|
961
|
-
'<td><span class="status-badge ' + (h.status || '') + '">' + escapeHtml(h.status || '?') + '</span></td>' +
|
|
962
|
-
'<td>' + ((h.confidence || 0) * 100).toFixed(0) + '%</td>' +
|
|
963
|
-
'<td>' + formatTime(h.created_at || h.timestamp) + '</td>' +
|
|
964
|
-
'</tr>'
|
|
965
|
-
).join('');
|
|
1086
|
+
neuralNodes = newNodes;
|
|
1087
|
+
neuralEdges = (network.edges || []).map(function(e) {
|
|
1088
|
+
return {
|
|
1089
|
+
source: e.source || e.source_id,
|
|
1090
|
+
target: e.target || e.target_id,
|
|
1091
|
+
weight: e.weight != null ? e.weight : 0.5,
|
|
1092
|
+
};
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
function simulatePhysics() {
|
|
1097
|
+
var k = 0.008;
|
|
1098
|
+
var repulsion = 800;
|
|
1099
|
+
var damping = 0.92;
|
|
1100
|
+
var gravity = 0.01;
|
|
1101
|
+
var cx = 300, cy = 250;
|
|
1102
|
+
|
|
1103
|
+
for (var i = 0; i < neuralNodes.length; i++) {
|
|
1104
|
+
for (var j = i + 1; j < neuralNodes.length; j++) {
|
|
1105
|
+
var a = neuralNodes[i], b = neuralNodes[j];
|
|
1106
|
+
var dx = a.x - b.x, dy = a.y - b.y;
|
|
1107
|
+
var dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
1108
|
+
var f = repulsion / (dist * dist);
|
|
1109
|
+
dx = (dx / dist) * f;
|
|
1110
|
+
dy = (dy / dist) * f;
|
|
1111
|
+
if (!a.pinned) { a.vx += dx; a.vy += dy; }
|
|
1112
|
+
if (!b.pinned) { b.vx -= dx; b.vy -= dy; }
|
|
966
1113
|
}
|
|
967
1114
|
}
|
|
968
1115
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
'<span style="margin-left:auto;color:var(--text-muted)">' + (e?.count || 0) + '</span>' +
|
|
983
|
-
'</div>';
|
|
984
|
-
}).join('');
|
|
985
|
-
|
|
986
|
-
// Engine thought counts as bars
|
|
987
|
-
const sorted = names.map(n => ({ name: n, count: engines[n]?.count || 0 })).sort((a, b) => b.count - a.count);
|
|
988
|
-
const maxCount = Math.max(...sorted.map(s => s.count), 1);
|
|
989
|
-
document.getElementById('engineCounts').innerHTML = sorted.map(s => {
|
|
990
|
-
const pct = Math.round((s.count / maxCount) * 100);
|
|
991
|
-
return '<div class="topic-bar">' +
|
|
992
|
-
'<span class="topic-name">' + escapeHtml(s.name) + '</span>' +
|
|
993
|
-
'<div style="flex:1"><div class="topic-bar-fill" style="width:' + pct + '%;background:linear-gradient(90deg,var(--green),var(--cyan))"></div></div>' +
|
|
994
|
-
'<span class="topic-score">' + s.count + '</span>' +
|
|
995
|
-
'</div>';
|
|
996
|
-
}).join('');
|
|
1116
|
+
var nodeMap = {};
|
|
1117
|
+
for (var m = 0; m < neuralNodes.length; m++) nodeMap[neuralNodes[m].id] = neuralNodes[m];
|
|
1118
|
+
for (var e = 0; e < neuralEdges.length; e++) {
|
|
1119
|
+
var edge = neuralEdges[e];
|
|
1120
|
+
var ea = nodeMap[edge.source], eb = nodeMap[edge.target];
|
|
1121
|
+
if (!ea || !eb) continue;
|
|
1122
|
+
var edx = eb.x - ea.x, edy = eb.y - ea.y;
|
|
1123
|
+
var edist = Math.sqrt(edx * edx + edy * edy) || 1;
|
|
1124
|
+
var ideal = 60;
|
|
1125
|
+
var ef = k * (edist - ideal);
|
|
1126
|
+
var efx = (edx / edist) * ef, efy = (edy / edist) * ef;
|
|
1127
|
+
if (!ea.pinned) { ea.vx += efx; ea.vy += efy; }
|
|
1128
|
+
if (!eb.pinned) { eb.vx -= efx; eb.vy -= efy; }
|
|
997
1129
|
}
|
|
998
1130
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1131
|
+
for (var n = 0; n < neuralNodes.length; n++) {
|
|
1132
|
+
var node = neuralNodes[n];
|
|
1133
|
+
if (node.pinned) continue;
|
|
1134
|
+
node.vx += (cx - node.x) * gravity;
|
|
1135
|
+
node.vy += (cy - node.y) * gravity;
|
|
1136
|
+
node.vx *= damping;
|
|
1137
|
+
node.vy *= damping;
|
|
1138
|
+
node.x += node.vx;
|
|
1139
|
+
node.y += node.vy;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
function drawNeuralCanvas(canvasId, isOverview) {
|
|
1144
|
+
var canvas = document.getElementById(canvasId);
|
|
1145
|
+
if (!canvas) return;
|
|
1146
|
+
var ctx = canvas.getContext('2d');
|
|
1147
|
+
var w = canvas.width, h = canvas.height;
|
|
1148
|
+
|
|
1149
|
+
ctx.clearRect(0, 0, w, h);
|
|
1150
|
+
ctx.save();
|
|
1151
|
+
ctx.translate(neuralPanX, neuralPanY);
|
|
1152
|
+
ctx.scale(neuralZoomLevel, neuralZoomLevel);
|
|
1153
|
+
|
|
1154
|
+
var nodeMap = {};
|
|
1155
|
+
for (var m = 0; m < neuralNodes.length; m++) nodeMap[neuralNodes[m].id] = neuralNodes[m];
|
|
1156
|
+
|
|
1157
|
+
// Edges
|
|
1158
|
+
for (var e = 0; e < neuralEdges.length; e++) {
|
|
1159
|
+
var edge = neuralEdges[e];
|
|
1160
|
+
var a = nodeMap[edge.source], b = nodeMap[edge.target];
|
|
1161
|
+
if (!a || !b) continue;
|
|
1162
|
+
ctx.beginPath();
|
|
1163
|
+
ctx.moveTo(a.x, a.y);
|
|
1164
|
+
ctx.lineTo(b.x, b.y);
|
|
1165
|
+
ctx.strokeStyle = 'rgba(0,229,255,' + Math.min(0.3, edge.weight * 0.4) + ')';
|
|
1166
|
+
ctx.lineWidth = 0.5 + edge.weight;
|
|
1167
|
+
ctx.stroke();
|
|
1006
1168
|
}
|
|
1007
1169
|
|
|
1008
|
-
//
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
state.thoughts.unshift(thought);
|
|
1022
|
-
if (state.thoughts.length > MAX_THOUGHTS) state.thoughts.length = MAX_THOUGHTS;
|
|
1023
|
-
|
|
1024
|
-
// Live update notification feeds
|
|
1025
|
-
renderNotifFeed('overviewNotifs', state.thoughts.slice(0, 30));
|
|
1026
|
-
renderNotifFeed('allNotifs', state.thoughts.slice(0, 200));
|
|
1027
|
-
} catch { /* ignore parse errors */ }
|
|
1028
|
-
});
|
|
1029
|
-
|
|
1030
|
-
es.addEventListener('status', (e) => {
|
|
1031
|
-
try {
|
|
1032
|
-
const data = JSON.parse(e.data);
|
|
1033
|
-
if (data.overview) state.overview = data.overview;
|
|
1034
|
-
if (data.engines) state.engines = data.engines;
|
|
1035
|
-
if (data.stats) state.stats = data.stats;
|
|
1036
|
-
renderOverview();
|
|
1037
|
-
renderEngines();
|
|
1038
|
-
} catch { /* ignore */ }
|
|
1039
|
-
});
|
|
1170
|
+
// Nodes
|
|
1171
|
+
for (var i = 0; i < neuralNodes.length; i++) {
|
|
1172
|
+
var n = neuralNodes[i];
|
|
1173
|
+
var col = nodeTypeColors[n.type] || '#6e7a8a';
|
|
1174
|
+
var r = n.radius || 4;
|
|
1175
|
+
var isHovered = neuralHover && neuralHover.id === n.id;
|
|
1176
|
+
|
|
1177
|
+
if (isHovered || n.importance > 0.7) {
|
|
1178
|
+
ctx.beginPath();
|
|
1179
|
+
ctx.arc(n.x, n.y, r * 2.5, 0, Math.PI * 2);
|
|
1180
|
+
ctx.fillStyle = col + '14';
|
|
1181
|
+
ctx.fill();
|
|
1182
|
+
}
|
|
1040
1183
|
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1184
|
+
ctx.beginPath();
|
|
1185
|
+
ctx.arc(n.x, n.y, r, 0, Math.PI * 2);
|
|
1186
|
+
ctx.fillStyle = col;
|
|
1187
|
+
ctx.fill();
|
|
1044
1188
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
};
|
|
1051
|
-
}
|
|
1189
|
+
if (isHovered) {
|
|
1190
|
+
ctx.strokeStyle = '#fff';
|
|
1191
|
+
ctx.lineWidth = 1.5;
|
|
1192
|
+
ctx.stroke();
|
|
1193
|
+
}
|
|
1052
1194
|
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
const data = await res.json();
|
|
1058
|
-
state = {
|
|
1059
|
-
overview: data.overview || null,
|
|
1060
|
-
transfer: data.transfer || null,
|
|
1061
|
-
attention: data.attention || null,
|
|
1062
|
-
thoughts: (data.thoughts || []).reverse(),
|
|
1063
|
-
engines: data.engines || {},
|
|
1064
|
-
stats: data.stats || {},
|
|
1065
|
-
notifications: data.notifications || [],
|
|
1066
|
-
};
|
|
1067
|
-
renderAll();
|
|
1068
|
-
} catch (e) {
|
|
1069
|
-
console.error('Failed to load initial state', e);
|
|
1195
|
+
if (isHovered || (!isOverview && neuralZoomLevel > 0.8 && n.importance > 0.6)) {
|
|
1196
|
+
ctx.fillStyle = 'rgba(224,230,240,0.8)';
|
|
1197
|
+
ctx.font = '9px ' + getComputedStyle(document.body).fontFamily;
|
|
1198
|
+
ctx.fillText((n.label || '').substring(0, 30), n.x + r + 3, n.y + 3);
|
|
1070
1199
|
}
|
|
1071
1200
|
}
|
|
1072
1201
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1202
|
+
ctx.restore();
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
function resizeNeuralCanvas() {
|
|
1206
|
+
var canvas = document.getElementById('neuralCanvas');
|
|
1207
|
+
if (!canvas) return;
|
|
1208
|
+
var wrap = canvas.parentElement;
|
|
1209
|
+
canvas.width = wrap.clientWidth;
|
|
1210
|
+
canvas.height = wrap.clientHeight;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
function renderNetwork() {
|
|
1214
|
+
updateNeuralNodes(state.network);
|
|
1215
|
+
var txt = neuralNodes.length + ' nodes, ' + neuralEdges.length + ' edges';
|
|
1216
|
+
var info1 = document.getElementById('overviewInfo');
|
|
1217
|
+
var info2 = document.getElementById('neuralInfo');
|
|
1218
|
+
if (info1) info1.textContent = txt;
|
|
1219
|
+
if (info2) info2.textContent = txt;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
function neuralLoop() {
|
|
1223
|
+
simulatePhysics();
|
|
1224
|
+
|
|
1225
|
+
var oc = document.getElementById('overviewCanvas');
|
|
1226
|
+
if (oc) {
|
|
1227
|
+
if (oc.width !== oc.parentElement.clientWidth) oc.width = oc.parentElement.clientWidth;
|
|
1228
|
+
drawNeuralCanvas('overviewCanvas', true);
|
|
1229
|
+
}
|
|
1081
1230
|
|
|
1082
|
-
|
|
1231
|
+
var nc = document.getElementById('neuralCanvas');
|
|
1232
|
+
if (nc && nc.offsetParent !== null) drawNeuralCanvas('neuralCanvas', false);
|
|
1233
|
+
|
|
1234
|
+
neuralAnimId = requestAnimationFrame(neuralLoop);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
// ═══ SYNTAX HIGHLIGHTING ═══
|
|
1238
|
+
function highlightSyntax(code) {
|
|
1239
|
+
return code
|
|
1240
|
+
.replace(/(\/\/.*)/g, '<span class="syn-comment">$1</span>')
|
|
1241
|
+
.replace(/(\/\*[\s\S]*?\*\/)/g, '<span class="syn-comment">$1</span>')
|
|
1242
|
+
.replace(/('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*`)/g, '<span class="syn-string">$1</span>')
|
|
1243
|
+
.replace(/\b(\d+\.?\d*)\b/g, '<span class="syn-number">$1</span>')
|
|
1244
|
+
.replace(/\b(const|let|var|function|return|if|else|for|while|class|import|export|from|async|await|new|this|type|interface|extends|implements|try|catch|throw|switch|case|break|default)\b/g, '<span class="syn-keyword">$1</span>')
|
|
1245
|
+
.replace(/\b(string|number|boolean|void|null|undefined|any|unknown|never|Promise|Array|Record|Map|Set)\b/g, '<span class="syn-type">$1</span>');
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
// ═══ TRIGGER ═══
|
|
1249
|
+
async function triggerCycle() {
|
|
1250
|
+
try {
|
|
1251
|
+
var btn = document.querySelector('.trigger-btn');
|
|
1252
|
+
btn.textContent = 'Triggering...';
|
|
1253
|
+
btn.style.opacity = '0.6';
|
|
1254
|
+
await fetch('/api/trigger', { method: 'POST' });
|
|
1255
|
+
setTimeout(function() { btn.textContent = 'Trigger Cycle'; btn.style.opacity = '1'; }, 1500);
|
|
1256
|
+
} catch(e) { console.warn('triggerCycle failed', e); }
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// ═══ UPTIME ═══
|
|
1260
|
+
setInterval(function() {
|
|
1261
|
+
var s = Math.floor((Date.now() - startTime) / 1000);
|
|
1262
|
+
var h = Math.floor(s / 3600);
|
|
1263
|
+
var m = Math.floor((s % 3600) / 60);
|
|
1264
|
+
document.getElementById('uptimeEl').textContent = 'Uptime: ' + h + 'h ' + m + 'm';
|
|
1265
|
+
}, 10000);
|
|
1266
|
+
|
|
1267
|
+
// ═══ BOOT ═══
|
|
1268
|
+
initNeuralGraph('overviewCanvas');
|
|
1269
|
+
initNeuralGraph('neuralCanvas');
|
|
1270
|
+
window.addEventListener('resize', resizeNeuralCanvas);
|
|
1271
|
+
|
|
1272
|
+
connect();
|
|
1273
|
+
fetchInitial();
|
|
1274
|
+
neuralLoop();
|
|
1083
1275
|
</script>
|
|
1084
1276
|
</body>
|
|
1085
1277
|
</html>
|