@jungjaehoon/mama-os 0.62.0 → 0.63.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/CHANGELOG.md +34 -0
- package/README.md +1 -1
- package/dist/api/viewer-data.d.ts +77 -0
- package/dist/api/viewer-data.d.ts.map +1 -1
- package/dist/api/viewer-data.js +116 -0
- package/dist/api/viewer-data.js.map +1 -1
- package/dist/api/viewer-server.d.ts +1 -1
- package/dist/api/viewer-server.d.ts.map +1 -1
- package/dist/api/viewer-server.js +87 -3
- package/dist/api/viewer-server.js.map +1 -1
- package/dist/api/work-actions.d.ts +2 -0
- package/dist/api/work-actions.d.ts.map +1 -1
- package/dist/api/work-actions.js +4 -5
- package/dist/api/work-actions.js.map +1 -1
- package/dist/runtime/action-surface.d.ts +1 -1
- package/dist/runtime/action-surface.d.ts.map +1 -1
- package/dist/runtime/action-surface.js +3 -0
- package/dist/runtime/action-surface.js.map +1 -1
- package/dist/runtime/turn-orders.d.ts.map +1 -1
- package/dist/runtime/turn-orders.js +6 -2
- package/dist/runtime/turn-orders.js.map +1 -1
- package/package.json +2 -2
- package/public/viewer/js/modules/graph.js +169 -957
- package/public/viewer/js/modules/memory-timeline.js +215 -0
- package/public/viewer/js/utils/api.js +7 -26
- package/public/viewer/src/modules/graph.ts +185 -1132
- package/public/viewer/src/modules/memory-timeline.ts +272 -0
- package/public/viewer/src/types/global.d.ts +1 -1
- package/public/viewer/src/utils/api.ts +43 -47
- package/public/viewer/viewer.css +257 -7
- package/public/viewer/viewer.html +68 -292
|
@@ -427,7 +427,7 @@
|
|
|
427
427
|
|
|
428
428
|
<div class="tab-content" id="tab-memory">
|
|
429
429
|
<div class="flex-1 flex flex-col min-h-0">
|
|
430
|
-
<!--
|
|
430
|
+
<!-- Period, kinds and search: every control is a server read of the saved timeline -->
|
|
431
431
|
<div
|
|
432
432
|
class="memory-controls flex items-center gap-2 px-3 py-2 border-b border-gray-200 bg-white"
|
|
433
433
|
>
|
|
@@ -436,7 +436,7 @@
|
|
|
436
436
|
id="checkpoint-sidebar-toggle"
|
|
437
437
|
class="w-7 h-7 bg-white border border-gray-200 rounded flex items-center justify-center text-gray-500 hover:bg-gray-100 hover:text-gray-700"
|
|
438
438
|
onclick="toggleCheckpointSidebar()"
|
|
439
|
-
title="
|
|
439
|
+
title="Show or hide the saved list"
|
|
440
440
|
aria-controls="checkpoint-sidebar"
|
|
441
441
|
aria-expanded="true"
|
|
442
442
|
>
|
|
@@ -456,129 +456,29 @@
|
|
|
456
456
|
<line x1="9" y1="21" x2="9" y2="9" />
|
|
457
457
|
</svg>
|
|
458
458
|
</button>
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
"
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
>
|
|
475
|
-
<!-- Spacer -->
|
|
476
|
-
<div style="flex: 1"></div>
|
|
477
|
-
<!-- Topic filter -->
|
|
478
|
-
<input
|
|
479
|
-
list="topic-filter-list"
|
|
480
|
-
class="px-2 py-1 bg-white border border-gray-200 rounded text-xs focus:outline-none focus:ring-1 focus:ring-yellow-400"
|
|
481
|
-
id="topic-filter"
|
|
482
|
-
placeholder="Filter topics..."
|
|
483
|
-
oninput="filterByTopic(this.value)"
|
|
484
|
-
/>
|
|
485
|
-
<datalist id="topic-filter-list"></datalist>
|
|
486
|
-
<select
|
|
487
|
-
class="px-2 py-1 bg-white border border-gray-200 rounded text-xs focus:outline-none focus:ring-1 focus:ring-yellow-400"
|
|
488
|
-
id="outcome-filter"
|
|
489
|
-
onchange="filterByOutcome(this.value)"
|
|
490
|
-
style="display: none"
|
|
491
|
-
>
|
|
492
|
-
<option value="">All Outcomes</option>
|
|
493
|
-
<option value="success">Success</option>
|
|
494
|
-
<option value="failed">Failed</option>
|
|
495
|
-
<option value="partial">Partial</option>
|
|
496
|
-
<option value="pending">Pending</option>
|
|
497
|
-
</select>
|
|
498
|
-
<!-- Search -->
|
|
459
|
+
<div class="memory-periods" role="group" aria-label="Period">
|
|
460
|
+
<button type="button" class="memory-chip" data-memory-period="today">
|
|
461
|
+
Today
|
|
462
|
+
</button>
|
|
463
|
+
<button type="button" class="memory-chip" data-memory-period="7d">7 days</button>
|
|
464
|
+
<button type="button" class="memory-chip" data-memory-period="30d">
|
|
465
|
+
30 days
|
|
466
|
+
</button>
|
|
467
|
+
<input type="date" id="memory-day" class="memory-day" aria-label="One day" />
|
|
468
|
+
</div>
|
|
469
|
+
<div
|
|
470
|
+
id="memory-group-chips"
|
|
471
|
+
class="memory-groups"
|
|
472
|
+
role="group"
|
|
473
|
+
aria-label="Kinds"
|
|
474
|
+
></div>
|
|
499
475
|
<input
|
|
500
|
-
type="
|
|
476
|
+
type="search"
|
|
477
|
+
id="memory-timeline-search"
|
|
501
478
|
class="px-2 py-1 bg-white border border-gray-200 rounded text-xs placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-yellow-400"
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
onkeyup="handleGraphSearch(event)"
|
|
479
|
+
placeholder="Search saved text..."
|
|
480
|
+
aria-label="Search saved text"
|
|
505
481
|
/>
|
|
506
|
-
<button
|
|
507
|
-
onclick="clearFilters()"
|
|
508
|
-
class="px-2 py-1 text-[10px] text-gray-400 hover:text-gray-600"
|
|
509
|
-
>
|
|
510
|
-
Clear
|
|
511
|
-
</button>
|
|
512
|
-
<!-- Export (collapsed) -->
|
|
513
|
-
<details style="position: relative">
|
|
514
|
-
<summary
|
|
515
|
-
style="
|
|
516
|
-
font-size: 10px;
|
|
517
|
-
color: #9e9891;
|
|
518
|
-
cursor: pointer;
|
|
519
|
-
padding: 4px 8px;
|
|
520
|
-
border: 1px solid #ede9e1;
|
|
521
|
-
border-radius: 4px;
|
|
522
|
-
"
|
|
523
|
-
>
|
|
524
|
-
Export
|
|
525
|
-
</summary>
|
|
526
|
-
<div
|
|
527
|
-
style="
|
|
528
|
-
position: absolute;
|
|
529
|
-
right: 0;
|
|
530
|
-
top: 100%;
|
|
531
|
-
background: #fff;
|
|
532
|
-
border: 1px solid #ede9e1;
|
|
533
|
-
border-radius: 4px;
|
|
534
|
-
padding: 4px;
|
|
535
|
-
z-index: 10;
|
|
536
|
-
display: flex;
|
|
537
|
-
gap: 4px;
|
|
538
|
-
margin-top: 2px;
|
|
539
|
-
"
|
|
540
|
-
>
|
|
541
|
-
<button
|
|
542
|
-
onclick="exportDecisions('json')"
|
|
543
|
-
style="
|
|
544
|
-
font-size: 10px;
|
|
545
|
-
padding: 2px 8px;
|
|
546
|
-
background: #f5f2ed;
|
|
547
|
-
border: none;
|
|
548
|
-
border-radius: 2px;
|
|
549
|
-
cursor: pointer;
|
|
550
|
-
"
|
|
551
|
-
>
|
|
552
|
-
JSON
|
|
553
|
-
</button>
|
|
554
|
-
<button
|
|
555
|
-
onclick="exportDecisions('markdown')"
|
|
556
|
-
style="
|
|
557
|
-
font-size: 10px;
|
|
558
|
-
padding: 2px 8px;
|
|
559
|
-
background: #f5f2ed;
|
|
560
|
-
border: none;
|
|
561
|
-
border-radius: 2px;
|
|
562
|
-
cursor: pointer;
|
|
563
|
-
"
|
|
564
|
-
>
|
|
565
|
-
MD
|
|
566
|
-
</button>
|
|
567
|
-
<button
|
|
568
|
-
onclick="exportDecisions('csv')"
|
|
569
|
-
style="
|
|
570
|
-
font-size: 10px;
|
|
571
|
-
padding: 2px 8px;
|
|
572
|
-
background: #f5f2ed;
|
|
573
|
-
border: none;
|
|
574
|
-
border-radius: 2px;
|
|
575
|
-
cursor: pointer;
|
|
576
|
-
"
|
|
577
|
-
>
|
|
578
|
-
CSV
|
|
579
|
-
</button>
|
|
580
|
-
</div>
|
|
581
|
-
</details>
|
|
582
482
|
</div>
|
|
583
483
|
|
|
584
484
|
<!-- Main content area: Sidebar + Graph -->
|
|
@@ -586,25 +486,15 @@
|
|
|
586
486
|
<!-- Decision List Sidebar -->
|
|
587
487
|
<aside
|
|
588
488
|
id="checkpoint-sidebar"
|
|
589
|
-
class="checkpoint-sidebar w-
|
|
590
|
-
style="min-width:
|
|
489
|
+
class="checkpoint-sidebar w-96 border-r border-gray-200 bg-white flex flex-col min-h-0 overflow-hidden"
|
|
490
|
+
style="min-width: 240px; max-width: 640px"
|
|
591
491
|
>
|
|
592
|
-
<div class="
|
|
593
|
-
<span
|
|
594
|
-
|
|
595
|
-
font-family: Inter, 'Noto Sans KR', sans-serif;
|
|
596
|
-
font-size: 12px;
|
|
597
|
-
font-weight: 600;
|
|
598
|
-
color: #1a1a1a;
|
|
599
|
-
"
|
|
600
|
-
>Decisions</span
|
|
601
|
-
>
|
|
602
|
-
<span id="decision-list-count" style="font-size: 10px; color: #9e9891">0</span>
|
|
492
|
+
<div class="mt-head">
|
|
493
|
+
<span id="memory-timeline-range" class="mt-range">Saved</span>
|
|
494
|
+
<span id="memory-timeline-count" class="mt-total"></span>
|
|
603
495
|
</div>
|
|
604
|
-
<div class="flex-1 overflow-y-auto" id="
|
|
605
|
-
<div
|
|
606
|
-
Loading decisions...
|
|
607
|
-
</div>
|
|
496
|
+
<div class="flex-1 overflow-y-auto" id="memory-timeline">
|
|
497
|
+
<div class="mt-empty">Reading what was saved...</div>
|
|
608
498
|
</div>
|
|
609
499
|
</aside>
|
|
610
500
|
|
|
@@ -629,18 +519,25 @@
|
|
|
629
519
|
style="background: #fafafa"
|
|
630
520
|
></div>
|
|
631
521
|
|
|
522
|
+
<div class="absolute inset-0 flex items-center justify-center" id="graph-empty">
|
|
523
|
+
<span class="graph-empty-text"
|
|
524
|
+
>Pick a saved record on the left to see what it rests on and links to.</span
|
|
525
|
+
>
|
|
526
|
+
</div>
|
|
527
|
+
|
|
632
528
|
<div
|
|
633
529
|
class="absolute inset-0 flex flex-col items-center justify-center bg-white/95"
|
|
634
530
|
id="graph-loading"
|
|
531
|
+
style="display: none"
|
|
635
532
|
>
|
|
636
533
|
<div
|
|
637
534
|
class="w-6 h-6 border-2 border-gray-400 border-t-transparent rounded-full animate-spin"
|
|
638
535
|
></div>
|
|
639
|
-
<span class="mt-2 text-xs text-gray-500">
|
|
536
|
+
<span class="mt-2 text-xs text-gray-500">Reading links...</span>
|
|
640
537
|
</div>
|
|
641
538
|
|
|
642
539
|
<div
|
|
643
|
-
class="legend-panel absolute bottom-16 right-4 w-
|
|
540
|
+
class="legend-panel absolute bottom-16 right-4 w-80 bg-white/95 backdrop-blur-sm border border-gray-200 rounded-lg shadow-lg p-3 z-10"
|
|
644
541
|
id="legend-panel"
|
|
645
542
|
>
|
|
646
543
|
<button
|
|
@@ -662,9 +559,7 @@
|
|
|
662
559
|
<line x1="6" y1="6" x2="18" y2="18" />
|
|
663
560
|
</svg>
|
|
664
561
|
</button>
|
|
665
|
-
<h4
|
|
666
|
-
class="text-xs font-semibold text-gray-700 text-gray-700 flex items-center gap-1.5 mb-3"
|
|
667
|
-
>
|
|
562
|
+
<h4 class="text-sm font-semibold text-gray-700 flex items-center gap-1.5 mb-3">
|
|
668
563
|
<svg
|
|
669
564
|
xmlns="http://www.w3.org/2000/svg"
|
|
670
565
|
width="14"
|
|
@@ -680,11 +575,11 @@
|
|
|
680
575
|
<line x1="12" y1="16" x2="12" y2="12" />
|
|
681
576
|
<line x1="12" y1="8" x2="12.01" y2="8" />
|
|
682
577
|
</svg>
|
|
683
|
-
|
|
578
|
+
What the dots and lines mean
|
|
684
579
|
</h4>
|
|
685
580
|
<div
|
|
686
581
|
id="graph-legend-content"
|
|
687
|
-
class="legend-content space-y-3 max-h-
|
|
582
|
+
class="legend-content space-y-3 max-h-80 overflow-y-auto"
|
|
688
583
|
></div>
|
|
689
584
|
</div>
|
|
690
585
|
<button
|
|
@@ -725,7 +620,7 @@
|
|
|
725
620
|
id="detail-modal-header"
|
|
726
621
|
>
|
|
727
622
|
<h3 class="text-sm font-semibold text-gray-900 truncate flex-1" id="detail-topic">
|
|
728
|
-
|
|
623
|
+
Record
|
|
729
624
|
</h3>
|
|
730
625
|
<button
|
|
731
626
|
class="p-1 rounded hover:bg-gray-200 transition-colors text-gray-500 hover:text-gray-700 ml-2"
|
|
@@ -747,9 +642,12 @@
|
|
|
747
642
|
</svg>
|
|
748
643
|
</button>
|
|
749
644
|
</div>
|
|
750
|
-
<div class="flex-1 p-3 overflow-y-auto space-y-3 text-
|
|
645
|
+
<div class="flex-1 p-3 overflow-y-auto space-y-3 text-sm">
|
|
646
|
+
<div class="flex gap-4 text-xs text-gray-500">
|
|
647
|
+
<span id="detail-kind"></span>
|
|
648
|
+
<span>Saved <span id="detail-created"></span></span>
|
|
649
|
+
</div>
|
|
751
650
|
<div>
|
|
752
|
-
<div class="font-semibold text-gray-500 uppercase tracking-wide mb-1">Decision</div>
|
|
753
651
|
<div
|
|
754
652
|
class="text-gray-900 leading-relaxed markdown-content"
|
|
755
653
|
id="detail-decision"
|
|
@@ -757,55 +655,16 @@
|
|
|
757
655
|
</div>
|
|
758
656
|
<div>
|
|
759
657
|
<div
|
|
760
|
-
class="font-semibold text-gray-500 uppercase tracking-wide mb-1 cursor-pointer hover:text-gray-700"
|
|
658
|
+
class="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1 cursor-pointer hover:text-gray-700"
|
|
761
659
|
onclick="toggleReasoning()"
|
|
762
660
|
>
|
|
763
|
-
<span id="reasoning-arrow">▶</span> Reasoning
|
|
661
|
+
<span id="reasoning-arrow">▶</span> Reasoning and evidence
|
|
764
662
|
</div>
|
|
765
663
|
<div
|
|
766
664
|
class="text-gray-900 leading-relaxed markdown-content hidden"
|
|
767
665
|
id="detail-reasoning"
|
|
768
666
|
></div>
|
|
769
667
|
</div>
|
|
770
|
-
<div class="flex items-center gap-3">
|
|
771
|
-
<div class="flex items-center gap-2">
|
|
772
|
-
<span class="font-semibold text-gray-500 uppercase">Outcome:</span>
|
|
773
|
-
<select
|
|
774
|
-
class="px-1.5 py-0.5 bg-white border border-gray-200 rounded text-xs focus:outline-none focus:ring-1 focus:ring-yellow-400"
|
|
775
|
-
id="detail-outcome-select"
|
|
776
|
-
>
|
|
777
|
-
<option value="PENDING">PENDING</option>
|
|
778
|
-
<option value="SUCCESS">SUCCESS</option>
|
|
779
|
-
<option value="FAILED">FAILED</option>
|
|
780
|
-
<option value="PARTIAL">PARTIAL</option>
|
|
781
|
-
</select>
|
|
782
|
-
<button
|
|
783
|
-
class="px-1.5 py-0.5 bg-gray-100 hover:bg-gray-200 rounded transition-colors"
|
|
784
|
-
onclick="saveOutcome()"
|
|
785
|
-
>
|
|
786
|
-
Save
|
|
787
|
-
</button>
|
|
788
|
-
<span id="outcome-status"></span>
|
|
789
|
-
</div>
|
|
790
|
-
</div>
|
|
791
|
-
<div class="flex gap-4">
|
|
792
|
-
<div>
|
|
793
|
-
<span class="font-semibold text-gray-500 uppercase">Confidence:</span>
|
|
794
|
-
<span class="text-gray-900" id="detail-confidence"></span>
|
|
795
|
-
</div>
|
|
796
|
-
<div>
|
|
797
|
-
<span class="font-semibold text-gray-500 uppercase">Created:</span>
|
|
798
|
-
<span class="text-gray-900" id="detail-created"></span>
|
|
799
|
-
</div>
|
|
800
|
-
</div>
|
|
801
|
-
<div>
|
|
802
|
-
<div class="font-semibold text-gray-500 uppercase tracking-wide mb-1">
|
|
803
|
-
Similar Decisions
|
|
804
|
-
</div>
|
|
805
|
-
<div class="text-gray-900" id="detail-similar">
|
|
806
|
-
<span class="text-gray-400">Searching...</span>
|
|
807
|
-
</div>
|
|
808
|
-
</div>
|
|
809
668
|
</div>
|
|
810
669
|
<div
|
|
811
670
|
id="decision-resize-handle"
|
|
@@ -1202,6 +1061,7 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1202
1061
|
|
|
1203
1062
|
<script type="module">
|
|
1204
1063
|
import { GraphModule } from '/viewer/js/modules/graph.js';
|
|
1064
|
+
import { MemoryTimelineModule } from '/viewer/js/modules/memory-timeline.js';
|
|
1205
1065
|
import { MemoryModule } from '/viewer/js/modules/memory.js';
|
|
1206
1066
|
import { WikiModule } from '/viewer/js/modules/wiki.js';
|
|
1207
1067
|
import { renderRuntimeView, renderConnectorsView } from '/viewer/js/modules/system.js';
|
|
@@ -1209,6 +1069,16 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1209
1069
|
|
|
1210
1070
|
const memory = new MemoryModule();
|
|
1211
1071
|
const graph = new GraphModule();
|
|
1072
|
+
const timeline = new MemoryTimelineModule((id) => {
|
|
1073
|
+
graph.showRecord(id).catch((error) => {
|
|
1074
|
+
console.error('[MAMA] Failed to draw the record:', error);
|
|
1075
|
+
const empty = document.getElementById('graph-empty');
|
|
1076
|
+
if (empty) {
|
|
1077
|
+
empty.style.display = '';
|
|
1078
|
+
empty.textContent = `Could not read this record's links: ${error.message}`;
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
});
|
|
1212
1082
|
const wiki = new WikiModule();
|
|
1213
1083
|
|
|
1214
1084
|
// Exposed for inline handlers and debugging.
|
|
@@ -1368,7 +1238,6 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1368
1238
|
route: DEFAULT_ROUTE,
|
|
1369
1239
|
routeKey: null,
|
|
1370
1240
|
theme: 'light',
|
|
1371
|
-
graphLoaded: false,
|
|
1372
1241
|
};
|
|
1373
1242
|
|
|
1374
1243
|
async function applyRoute(route) {
|
|
@@ -1400,22 +1269,7 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1400
1269
|
|
|
1401
1270
|
if (route.view === 'memory') {
|
|
1402
1271
|
updateCheckpointSidebarForScreenSize();
|
|
1403
|
-
|
|
1404
|
-
if (!STATE.graphLoaded) {
|
|
1405
|
-
try {
|
|
1406
|
-
const data = await graph.fetchData();
|
|
1407
|
-
graph.init(data);
|
|
1408
|
-
STATE.graphLoaded = true;
|
|
1409
|
-
const loadingEl = document.getElementById('graph-loading');
|
|
1410
|
-
if (loadingEl) loadingEl.style.display = 'none';
|
|
1411
|
-
} catch (error) {
|
|
1412
|
-
console.error('[MAMA] Failed to load graph:', error);
|
|
1413
|
-
const loadingEl = document.getElementById('graph-loading');
|
|
1414
|
-
if (loadingEl) {
|
|
1415
|
-
loadingEl.innerHTML = '<span class="text-red-500">Failed to load graph data</span>';
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1272
|
+
await timeline.init();
|
|
1419
1273
|
return;
|
|
1420
1274
|
}
|
|
1421
1275
|
|
|
@@ -1668,9 +1522,9 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1668
1522
|
const isExpanding = sidebar.classList.contains('collapsed');
|
|
1669
1523
|
if (isExpanding) {
|
|
1670
1524
|
sidebar.classList.remove('collapsed');
|
|
1671
|
-
sidebar.style.width = '
|
|
1525
|
+
sidebar.style.width = '';
|
|
1672
1526
|
if (toggleBtn) {
|
|
1673
|
-
toggleBtn.title = 'Hide
|
|
1527
|
+
toggleBtn.title = 'Hide the saved list';
|
|
1674
1528
|
toggleBtn.setAttribute('aria-expanded', 'true');
|
|
1675
1529
|
}
|
|
1676
1530
|
if (handle) handle.style.display = '';
|
|
@@ -1678,7 +1532,7 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1678
1532
|
sidebar.classList.add('collapsed');
|
|
1679
1533
|
sidebar.style.width = '0';
|
|
1680
1534
|
if (toggleBtn) {
|
|
1681
|
-
toggleBtn.title = 'Show
|
|
1535
|
+
toggleBtn.title = 'Show the saved list';
|
|
1682
1536
|
toggleBtn.setAttribute('aria-expanded', 'false');
|
|
1683
1537
|
}
|
|
1684
1538
|
if (handle) handle.style.display = 'none';
|
|
@@ -1696,17 +1550,18 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1696
1550
|
// Mobile: stack layout with resizable height
|
|
1697
1551
|
sidebar.classList.remove('collapsed');
|
|
1698
1552
|
sidebar.style.width = '100%';
|
|
1699
|
-
sidebar.style.height = '
|
|
1553
|
+
sidebar.style.height = '55vh';
|
|
1700
1554
|
if (handle) {
|
|
1701
1555
|
handle.style.display = '';
|
|
1702
1556
|
handle.classList.add('sidebar-resize-handle--row');
|
|
1703
1557
|
}
|
|
1704
1558
|
if (toggleBtn) toggleBtn.setAttribute('aria-expanded', 'true');
|
|
1705
1559
|
} else {
|
|
1706
|
-
// Desktop:
|
|
1560
|
+
// Desktop: the stacked layout's full width and any collapse give way to the class width.
|
|
1561
|
+
if (sidebar.style.width === '100%') sidebar.style.width = '';
|
|
1707
1562
|
if (sidebar.classList.contains('collapsed')) {
|
|
1708
1563
|
sidebar.classList.remove('collapsed');
|
|
1709
|
-
sidebar.style.width = '
|
|
1564
|
+
sidebar.style.width = '';
|
|
1710
1565
|
}
|
|
1711
1566
|
sidebar.style.height = '';
|
|
1712
1567
|
if (handle) {
|
|
@@ -1846,79 +1701,6 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1846
1701
|
.catch(() => (result.innerHTML = '<span class="text-red-500">Connection failed</span>'));
|
|
1847
1702
|
}
|
|
1848
1703
|
|
|
1849
|
-
function filterByTopic(topic) {
|
|
1850
|
-
graph.filterByTopic && graph.filterByTopic(topic);
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
|
-
function filterByOutcome(outcome) {
|
|
1854
|
-
graph.filterByOutcome && graph.filterByOutcome(outcome);
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
// Clear is scoped to the Graph module instance that owns the filters. Each
|
|
1858
|
-
// control is looked up defensively: the bar is markup that can be edited,
|
|
1859
|
-
// and one missing input must not take the whole Clear action down.
|
|
1860
|
-
function clearFilters() {
|
|
1861
|
-
const topicFilter = document.getElementById('topic-filter');
|
|
1862
|
-
const outcomeFilter = document.getElementById('outcome-filter');
|
|
1863
|
-
const searchInput = document.getElementById('search-input');
|
|
1864
|
-
if (topicFilter) topicFilter.value = '';
|
|
1865
|
-
if (outcomeFilter) outcomeFilter.value = '';
|
|
1866
|
-
if (searchInput) searchInput.value = '';
|
|
1867
|
-
graph?.clearFilters?.();
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
|
-
async function exportDecisions(format) {
|
|
1871
|
-
try {
|
|
1872
|
-
const response = await fetch(`/api/memory/export?format=${format}`);
|
|
1873
|
-
if (!response.ok) throw new Error('Export failed');
|
|
1874
|
-
|
|
1875
|
-
const blob = await response.blob();
|
|
1876
|
-
const filename =
|
|
1877
|
-
response.headers.get('Content-Disposition')?.match(/filename="(.+)"/)?.[1] ||
|
|
1878
|
-
`mama-export.${format}`;
|
|
1879
|
-
|
|
1880
|
-
const url = URL.createObjectURL(blob);
|
|
1881
|
-
const a = document.createElement('a');
|
|
1882
|
-
a.href = url;
|
|
1883
|
-
a.download = filename;
|
|
1884
|
-
document.body.appendChild(a);
|
|
1885
|
-
a.click();
|
|
1886
|
-
document.body.removeChild(a);
|
|
1887
|
-
URL.revokeObjectURL(url);
|
|
1888
|
-
} catch (error) {
|
|
1889
|
-
console.error('[Export] Error:', error);
|
|
1890
|
-
alert('Export failed: ' + error.message);
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1893
|
-
|
|
1894
|
-
async function updateMemoryStats() {
|
|
1895
|
-
try {
|
|
1896
|
-
const data = await API.get('/api/dashboard/status');
|
|
1897
|
-
const memory = data.memory || {};
|
|
1898
|
-
const totalEl = document.getElementById('memory-stats-total');
|
|
1899
|
-
const weekEl = document.getElementById('memory-stats-week');
|
|
1900
|
-
if (totalEl) totalEl.textContent = memory.total || 0;
|
|
1901
|
-
if (weekEl) weekEl.textContent = `${memory.thisWeek || 0} this week`;
|
|
1902
|
-
} catch (error) {
|
|
1903
|
-
console.error('[MemoryStats] Error:', error);
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
|
-
|
|
1907
|
-
function handleGraphSearch(event) {
|
|
1908
|
-
if (event.key === 'Enter') {
|
|
1909
|
-
graph.search && graph.search();
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
|
|
1913
|
-
function saveOutcome() {
|
|
1914
|
-
const select = document.getElementById('detail-outcome-select');
|
|
1915
|
-
const outcome = select.value;
|
|
1916
|
-
const nodeId = graph.currentNodeId;
|
|
1917
|
-
if (nodeId && outcome) {
|
|
1918
|
-
graph.updateOutcome && graph.updateOutcome(nodeId, outcome);
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
|
|
1922
1704
|
// Expose to window for onclick handlers
|
|
1923
1705
|
window.switchTab = switchTab;
|
|
1924
1706
|
window.toggleTheme = toggleTheme;
|
|
@@ -1931,12 +1713,6 @@ export MAMA_AUTH_TOKEN="your-secure-token-here"</pre
|
|
|
1931
1713
|
window.hideSaveDecisionForm = hideSaveDecisionForm;
|
|
1932
1714
|
window.submitSaveDecision = submitSaveDecision;
|
|
1933
1715
|
window.testConnection = testConnection;
|
|
1934
|
-
window.filterByOutcome = filterByOutcome;
|
|
1935
|
-
window.clearFilters = clearFilters;
|
|
1936
|
-
window.exportDecisions = exportDecisions;
|
|
1937
|
-
window.filterByTopic = filterByTopic;
|
|
1938
|
-
window.handleGraphSearch = handleGraphSearch;
|
|
1939
|
-
window.saveOutcome = saveOutcome;
|
|
1940
1716
|
|
|
1941
1717
|
document.addEventListener('DOMContentLoaded', () => {
|
|
1942
1718
|
const userLang = navigator.language || navigator.userLanguage;
|