loki-mode 7.90.0 → 7.90.2
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/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/run.sh +7 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +137 -2
- package/dashboard/static/index.html +243 -522
- package/docs/INSTALLATION.md +2 -2
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
|
@@ -37,7 +37,10 @@
|
|
|
37
37
|
--loki-transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
/* v7.90.1: dark mode removed (light-only). Disabled via an always-false media
|
|
41
|
+
query so an OS dark preference no longer flips the dashboard to the dark
|
|
42
|
+
palette the founder found worse. Kept (not deleted) to minimize churn. */
|
|
43
|
+
@media (prefers-color-scheme: dark) and (max-width: 0px) {
|
|
41
44
|
:root {
|
|
42
45
|
--loki-bg-primary: #0F0B1A;
|
|
43
46
|
--loki-bg-secondary: #150F24;
|
|
@@ -386,9 +389,6 @@
|
|
|
386
389
|
flex-shrink: 0;
|
|
387
390
|
}
|
|
388
391
|
|
|
389
|
-
.theme-toggle {
|
|
390
|
-
margin-left: auto;
|
|
391
|
-
}
|
|
392
392
|
|
|
393
393
|
.footer-settings {
|
|
394
394
|
position: relative;
|
|
@@ -738,105 +738,6 @@
|
|
|
738
738
|
::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.2); }
|
|
739
739
|
|
|
740
740
|
/* Keyboard Shortcuts Help Overlay */
|
|
741
|
-
.shortcuts-overlay {
|
|
742
|
-
display: none;
|
|
743
|
-
position: fixed;
|
|
744
|
-
inset: 0;
|
|
745
|
-
background: rgba(0, 0, 0, 0.6);
|
|
746
|
-
z-index: 1000;
|
|
747
|
-
align-items: center;
|
|
748
|
-
justify-content: center;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
.shortcuts-overlay.visible {
|
|
752
|
-
display: flex;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
.shortcuts-dialog {
|
|
756
|
-
background: var(--loki-glass-bg);
|
|
757
|
-
backdrop-filter: blur(20px) saturate(1.4);
|
|
758
|
-
-webkit-backdrop-filter: blur(20px) saturate(1.4);
|
|
759
|
-
border: 1px solid var(--loki-glass-border);
|
|
760
|
-
border-radius: 12px;
|
|
761
|
-
padding: 24px;
|
|
762
|
-
max-width: 480px;
|
|
763
|
-
width: 90%;
|
|
764
|
-
max-height: 80vh;
|
|
765
|
-
overflow-y: auto;
|
|
766
|
-
box-shadow: var(--loki-glass-shadow);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
.shortcuts-header {
|
|
770
|
-
display: flex;
|
|
771
|
-
justify-content: space-between;
|
|
772
|
-
align-items: center;
|
|
773
|
-
margin-bottom: 16px;
|
|
774
|
-
padding-bottom: 12px;
|
|
775
|
-
border-bottom: 1px solid var(--loki-border);
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
.shortcuts-title {
|
|
779
|
-
font-size: 16px;
|
|
780
|
-
font-weight: 600;
|
|
781
|
-
color: var(--loki-text-primary);
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
.shortcuts-close {
|
|
785
|
-
background: none;
|
|
786
|
-
border: none;
|
|
787
|
-
color: var(--loki-text-muted);
|
|
788
|
-
cursor: pointer;
|
|
789
|
-
padding: 4px;
|
|
790
|
-
font-size: 18px;
|
|
791
|
-
line-height: 1;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
.shortcuts-close:hover {
|
|
795
|
-
color: var(--loki-text-primary);
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
.shortcuts-group {
|
|
799
|
-
margin-bottom: 16px;
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
.shortcuts-group-title {
|
|
803
|
-
font-size: 11px;
|
|
804
|
-
font-weight: 500;
|
|
805
|
-
text-transform: uppercase;
|
|
806
|
-
letter-spacing: 0.05em;
|
|
807
|
-
color: var(--loki-text-muted);
|
|
808
|
-
margin-bottom: 8px;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
.shortcut-row {
|
|
812
|
-
display: flex;
|
|
813
|
-
justify-content: space-between;
|
|
814
|
-
align-items: center;
|
|
815
|
-
padding: 4px 0;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
.shortcut-keys {
|
|
819
|
-
display: flex;
|
|
820
|
-
gap: 4px;
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
.shortcut-key {
|
|
824
|
-
display: inline-block;
|
|
825
|
-
padding: 2px 8px;
|
|
826
|
-
background: var(--loki-bg-tertiary);
|
|
827
|
-
border: 1px solid var(--loki-border);
|
|
828
|
-
border-radius: 6px;
|
|
829
|
-
font-size: 12px;
|
|
830
|
-
font-family: 'JetBrains Mono', monospace;
|
|
831
|
-
color: var(--loki-text-primary);
|
|
832
|
-
min-width: 24px;
|
|
833
|
-
text-align: center;
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
.shortcut-desc {
|
|
837
|
-
font-size: 13px;
|
|
838
|
-
color: var(--loki-text-secondary);
|
|
839
|
-
}
|
|
840
741
|
|
|
841
742
|
/* USAGE.md markdown render styles */
|
|
842
743
|
.usage-md { max-height: 480px; overflow: auto; padding: 12px; background: var(--loki-bg-secondary, #F2F0EB); border-radius: 4px; color: var(--loki-text-primary, #1A1614); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 13px; line-height: 1.6; }
|
|
@@ -1023,11 +924,8 @@
|
|
|
1023
924
|
</div>
|
|
1024
925
|
</div>
|
|
1025
926
|
</div>
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
<svg id="theme-icon-moon" width="14" height="14" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" fill="none" style="display:none"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg>
|
|
1029
|
-
<span id="theme-label">Dark</span>
|
|
1030
|
-
</button>
|
|
927
|
+
<!-- v7.90.1: dark mode removed (light-only). The theme toggle and its
|
|
928
|
+
handler are gone; the dashboard ships a single light theme. -->
|
|
1031
929
|
</div>
|
|
1032
930
|
</div>
|
|
1033
931
|
</aside>
|
|
@@ -1498,64 +1396,27 @@
|
|
|
1498
1396
|
</div>
|
|
1499
1397
|
|
|
1500
1398
|
<!-- Keyboard Shortcuts Help Overlay -->
|
|
1501
|
-
<div class="shortcuts-overlay" id="shortcuts-overlay">
|
|
1502
|
-
<div class="shortcuts-dialog">
|
|
1503
|
-
<div class="shortcuts-header">
|
|
1504
|
-
<span class="shortcuts-title">Keyboard Shortcuts</span>
|
|
1505
|
-
<button class="shortcuts-close" id="shortcuts-close" aria-label="Close">×</button>
|
|
1506
|
-
</div>
|
|
1507
|
-
<div class="shortcuts-group">
|
|
1508
|
-
<div class="shortcuts-group-title">Navigation</div>
|
|
1509
|
-
<div class="shortcut-row"><span class="shortcut-desc">Overview</span><span class="shortcut-keys"><kbd class="shortcut-key">1</kbd></span></div>
|
|
1510
|
-
<div class="shortcut-row"><span class="shortcut-desc">Insights</span><span class="shortcut-keys"><kbd class="shortcut-key">2</kbd></span></div>
|
|
1511
|
-
<div class="shortcut-row"><span class="shortcut-desc">Spec Checklist</span><span class="shortcut-keys"><kbd class="shortcut-key">3</kbd></span></div>
|
|
1512
|
-
<div class="shortcut-row"><span class="shortcut-desc">App Runner</span><span class="shortcut-keys"><kbd class="shortcut-key">4</kbd></span></div>
|
|
1513
|
-
<div class="shortcut-row"><span class="shortcut-desc">Council</span><span class="shortcut-keys"><kbd class="shortcut-key">5</kbd></span></div>
|
|
1514
|
-
<div class="shortcut-row"><span class="shortcut-desc">Quality</span><span class="shortcut-keys"><kbd class="shortcut-key">6</kbd></span></div>
|
|
1515
|
-
<div class="shortcut-row"><span class="shortcut-desc">Cost</span><span class="shortcut-keys"><kbd class="shortcut-key">7</kbd></span></div>
|
|
1516
|
-
<div class="shortcut-row"><span class="shortcut-desc">Checkpoints</span><span class="shortcut-keys"><kbd class="shortcut-key">8</kbd></span></div>
|
|
1517
|
-
<div class="shortcut-row"><span class="shortcut-desc">Context</span><span class="shortcut-keys"><kbd class="shortcut-key">9</kbd></span></div>
|
|
1518
|
-
<div class="shortcut-row"><span class="shortcut-desc">Notifications</span><span class="shortcut-keys"><kbd class="shortcut-key">0</kbd></span></div>
|
|
1519
|
-
<div class="shortcut-row"><span class="shortcut-desc">Migration</span><span class="shortcut-keys"><kbd class="shortcut-key">m</kbd></span></div>
|
|
1520
|
-
<div class="shortcut-row"><span class="shortcut-desc">Analytics</span><span class="shortcut-keys"><kbd class="shortcut-key">a</kbd></span></div>
|
|
1521
|
-
<div class="shortcut-row"><span class="shortcut-desc">Escalations</span><span class="shortcut-keys"><kbd class="shortcut-key">e</kbd></span></div>
|
|
1522
|
-
</div>
|
|
1523
|
-
<div class="shortcuts-group">
|
|
1524
|
-
<div class="shortcuts-group-title">Session</div>
|
|
1525
|
-
<div class="shortcut-row"><span class="shortcut-desc">Pause session</span><span class="shortcut-keys"><kbd class="shortcut-key">p</kbd></span></div>
|
|
1526
|
-
<div class="shortcut-row"><span class="shortcut-desc">Resume session</span><span class="shortcut-keys"><kbd class="shortcut-key">r</kbd></span></div>
|
|
1527
|
-
<div class="shortcut-row"><span class="shortcut-desc">Stop session</span><span class="shortcut-keys"><kbd class="shortcut-key">s</kbd></span></div>
|
|
1528
|
-
</div>
|
|
1529
|
-
<div class="shortcuts-group">
|
|
1530
|
-
<div class="shortcuts-group-title">General</div>
|
|
1531
|
-
<div class="shortcut-row"><span class="shortcut-desc">Toggle theme</span><span class="shortcut-keys"><kbd class="shortcut-key">t</kbd></span></div>
|
|
1532
|
-
<div class="shortcut-row"><span class="shortcut-desc">Focus API URL</span><span class="shortcut-keys"><kbd class="shortcut-key">/</kbd></span></div>
|
|
1533
|
-
<div class="shortcut-row"><span class="shortcut-desc">Show shortcuts</span><span class="shortcut-keys"><kbd class="shortcut-key">?</kbd></span></div>
|
|
1534
|
-
<div class="shortcut-row"><span class="shortcut-desc">Close overlay</span><span class="shortcut-keys"><kbd class="shortcut-key">Esc</kbd></span></div>
|
|
1535
|
-
</div>
|
|
1536
|
-
</div>
|
|
1537
|
-
</div>
|
|
1538
1399
|
|
|
1539
1400
|
<!-- Inlined JavaScript Bundle -->
|
|
1540
1401
|
<script>
|
|
1541
|
-
var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropertyDescriptor;var vt=Object.getOwnPropertyNames;var ft=Object.prototype.hasOwnProperty;var bt=(d,e,t)=>e in d?Ae(d,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[e]=t;var kt=(d,e)=>{for(var t in e)Ae(d,t,{get:e[t],enumerable:!0})},xt=(d,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of vt(e))!ft.call(d,a)&&a!==t&&Ae(d,a,{get:()=>e[a],enumerable:!(i=mt(e,a))||i.enumerable});return d};var _t=d=>xt(Ae({},"__esModule",{value:!0}),d);var S=(d,e,t)=>bt(d,typeof e!="symbol"?e+"":e,t);var Xt={};kt(Xt,{ANIMATION:()=>z,ARIA_PATTERNS:()=>De,ApiEvents:()=>v,BASE_STYLES:()=>N,BREAKPOINTS:()=>Te,COMMON_STYLES:()=>Ge,KEYBOARD_SHORTCUTS:()=>Le,KeyboardHandler:()=>I,LokiActivityStream:()=>ve,LokiAgentLeaderboard:()=>ye,LokiAnalytics:()=>le,LokiApiClient:()=>F,LokiApiKeys:()=>ge,LokiAppPreview:()=>Z,LokiAppStatus:()=>X,LokiAuditViewer:()=>ue,LokiChecklistViewer:()=>Q,LokiCheckpointViewer:()=>te,LokiContextTracker:()=>ie,LokiCostDashboard:()=>ee,LokiCostWaterfall:()=>_e,LokiCouncilDashboard:()=>Y,LokiCouncilTranscripts:()=>Ee,LokiElement:()=>u,LokiEscalations:()=>$e,LokiFleet:()=>he,LokiLearningDashboard:()=>W,LokiLogStream:()=>K,LokiManagedMemoryPanel:()=>we,LokiMemoryBrowser:()=>V,LokiMemoryGraph:()=>xe,LokiMigrationDashboard:()=>ne,LokiNotificationCenter:()=>ae,LokiOverview:()=>q,LokiPipelineView:()=>be,LokiPromptOptimizer:()=>re,LokiProviderHealth:()=>fe,LokiQualityGates:()=>de,LokiQualityScore:()=>oe,LokiRarvTimeline:()=>ce,LokiRunManager:()=>pe,LokiSessionControl:()=>G,LokiSessionDiff:()=>se,LokiSpecPanel:()=>Se,LokiState:()=>O,LokiTaskBoard:()=>J,LokiTenantSwitcher:()=>me,LokiTheme:()=>M,LokiWikiBrowser:()=>Ce,RADIUS:()=>D,SPACING:()=>T,STATE_CHANGE_EVENT:()=>He,THEMES:()=>C,THEME_VARIABLES:()=>ze,TYPOGRAPHY:()=>$,UnifiedThemeManager:()=>w,VERSION:()=>Yt,Z_INDEX:()=>R,createApiClient:()=>We,createStore:()=>Ye,generateThemeCSS:()=>E,generateTokensCSS:()=>U,getApiClient:()=>g,getState:()=>P,init:()=>Qt});var C={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-bg-active":"#E6E2DA","--loki-bg-overlay":"rgba(32, 21, 21, 0.5)","--loki-accent":"#553DE9","--loki-accent-hover":"#4432c4","--loki-accent-active":"#3828a0","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-text-disabled":"#C5C0B1","--loki-text-inverse":"#ffffff","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-border-focus":"#553DE9","--loki-success":"#1FC5A8","--loki-success-muted":"rgba(31, 197, 168, 0.12)","--loki-warning":"#D4A03C","--loki-warning-muted":"rgba(212, 160, 60, 0.12)","--loki-error":"#C45B5B","--loki-error-muted":"rgba(196, 91, 91, 0.12)","--loki-info":"#2F71E3","--loki-info-muted":"rgba(47, 113, 227, 0.12)","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-shadow-sm":"0 1px 2px rgba(32, 21, 21, 0.04)","--loki-shadow-md":"0 4px 6px rgba(32, 21, 21, 0.06)","--loki-shadow-lg":"0 10px 15px rgba(32, 21, 21, 0.08)","--loki-shadow-focus":"0 0 0 3px rgba(85, 61, 233, 0.25)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-bg-active":"#352A55","--loki-bg-overlay":"rgba(20, 11, 36, 0.85)","--loki-accent":"#7B6BF0","--loki-accent-hover":"#9488F5","--loki-accent-active":"#6258D0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-text-disabled":"#5A4E78","--loki-text-inverse":"#1A0F2E","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-border-focus":"#7B6BF0","--loki-success":"#2ED8B6","--loki-success-muted":"rgba(46, 216, 182, 0.18)","--loki-warning":"#E8B84A","--loki-warning-muted":"rgba(232, 184, 74, 0.18)","--loki-error":"#E07070","--loki-error-muted":"rgba(224, 112, 112, 0.18)","--loki-info":"#5A9CF5","--loki-info-muted":"rgba(90, 156, 245, 0.18)","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.4)","--loki-shadow-md":"0 4px 12px rgba(0, 0, 0, 0.5)","--loki-shadow-lg":"0 10px 25px rgba(0, 0, 0, 0.6)","--loki-shadow-focus":"0 0 0 3px rgba(123, 107, 240, 0.30)"},"high-contrast":{"--loki-bg-primary":"#000000","--loki-bg-secondary":"#0a0a0a","--loki-bg-tertiary":"#141414","--loki-bg-card":"#0a0a0a","--loki-bg-hover":"#1a1a1a","--loki-bg-active":"#242424","--loki-bg-overlay":"rgba(0, 0, 0, 0.9)","--loki-accent":"#c084fc","--loki-accent-hover":"#d8b4fe","--loki-accent-active":"#e9d5ff","--loki-accent-light":"#d8b4fe","--loki-accent-muted":"rgba(192, 132, 252, 0.25)","--loki-text-primary":"#ffffff","--loki-text-secondary":"#e0e0e0","--loki-text-muted":"#b0b0b0","--loki-text-disabled":"#666666","--loki-text-inverse":"#000000","--loki-border":"#ffffff","--loki-border-light":"#cccccc","--loki-border-focus":"#c084fc","--loki-success":"#4ade80","--loki-success-muted":"rgba(74, 222, 128, 0.25)","--loki-warning":"#fde047","--loki-warning-muted":"rgba(253, 224, 71, 0.25)","--loki-error":"#f87171","--loki-error-muted":"rgba(248, 113, 113, 0.25)","--loki-info":"#60a5fa","--loki-info-muted":"rgba(96, 165, 250, 0.25)","--loki-green":"#4ade80","--loki-green-muted":"rgba(74, 222, 128, 0.25)","--loki-yellow":"#fde047","--loki-yellow-muted":"rgba(253, 224, 71, 0.25)","--loki-red":"#f87171","--loki-red-muted":"rgba(248, 113, 113, 0.25)","--loki-blue":"#60a5fa","--loki-blue-muted":"rgba(96, 165, 250, 0.25)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.25)","--loki-opus":"#fbbf24","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"none","--loki-shadow-md":"none","--loki-shadow-lg":"none","--loki-shadow-focus":"0 0 0 3px #c084fc"},"vscode-light":{"--loki-bg-primary":"var(--vscode-editor-background, #ffffff)","--loki-bg-secondary":"var(--vscode-sideBar-background, #f3f3f3)","--loki-bg-tertiary":"var(--vscode-input-background, #ffffff)","--loki-bg-card":"var(--vscode-editor-background, #ffffff)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #e8e8e8)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #0060c0)","--loki-bg-overlay":"rgba(0, 0, 0, 0.4)","--loki-accent":"var(--vscode-focusBorder, #0066cc)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #0055aa)","--loki-accent-active":"var(--vscode-button-background, #007acc)","--loki-accent-light":"var(--vscode-focusBorder, #0066cc)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 102, 204, 0.2))","--loki-text-primary":"var(--vscode-foreground, #333333)","--loki-text-secondary":"var(--vscode-descriptionForeground, #717171)","--loki-text-muted":"var(--vscode-disabledForeground, #a0a0a0)","--loki-text-disabled":"var(--vscode-disabledForeground, #cccccc)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #c8c8c8)","--loki-border-light":"var(--vscode-widget-border, #e0e0e0)","--loki-border-focus":"var(--vscode-focusBorder, #0066cc)","--loki-success":"var(--vscode-testing-iconPassed, #388a34)","--loki-success-muted":"rgba(56, 138, 52, 0.15)","--loki-warning":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-warning-muted":"rgba(191, 136, 3, 0.15)","--loki-error":"var(--vscode-errorForeground, #e51400)","--loki-error-muted":"rgba(229, 20, 0, 0.15)","--loki-info":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-info-muted":"rgba(26, 133, 255, 0.15)","--loki-green":"var(--vscode-testing-iconPassed, #388a34)","--loki-green-muted":"rgba(56, 138, 52, 0.15)","--loki-yellow":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-yellow-muted":"rgba(191, 136, 3, 0.15)","--loki-red":"var(--vscode-errorForeground, #e51400)","--loki-red-muted":"rgba(229, 20, 0, 0.15)","--loki-blue":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-blue-muted":"rgba(26, 133, 255, 0.15)","--loki-purple":"#9333ea","--loki-purple-muted":"rgba(147, 51, 234, 0.15)","--loki-opus":"#d97706","--loki-sonnet":"#4f46e5","--loki-haiku":"#059669","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.05)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.1)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.15)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #0066cc)"},"vscode-dark":{"--loki-bg-primary":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-secondary":"var(--vscode-sideBar-background, #252526)","--loki-bg-tertiary":"var(--vscode-input-background, #3c3c3c)","--loki-bg-card":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #2a2d2e)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #094771)","--loki-bg-overlay":"rgba(0, 0, 0, 0.6)","--loki-accent":"var(--vscode-focusBorder, #007fd4)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #1177bb)","--loki-accent-active":"var(--vscode-button-background, #0e639c)","--loki-accent-light":"var(--vscode-focusBorder, #007fd4)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 127, 212, 0.25))","--loki-text-primary":"var(--vscode-foreground, #cccccc)","--loki-text-secondary":"var(--vscode-descriptionForeground, #9d9d9d)","--loki-text-muted":"var(--vscode-disabledForeground, #6b6b6b)","--loki-text-disabled":"var(--vscode-disabledForeground, #4d4d4d)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #454545)","--loki-border-light":"var(--vscode-widget-border, #5a5a5a)","--loki-border-focus":"var(--vscode-focusBorder, #007fd4)","--loki-success":"var(--vscode-testing-iconPassed, #89d185)","--loki-success-muted":"rgba(137, 209, 133, 0.2)","--loki-warning":"var(--vscode-editorWarning-foreground, #cca700)","--loki-warning-muted":"rgba(204, 167, 0, 0.2)","--loki-error":"var(--vscode-errorForeground, #f48771)","--loki-error-muted":"rgba(244, 135, 113, 0.2)","--loki-info":"var(--vscode-editorInfo-foreground, #75beff)","--loki-info-muted":"rgba(117, 190, 255, 0.2)","--loki-green":"var(--vscode-testing-iconPassed, #89d185)","--loki-green-muted":"rgba(137, 209, 133, 0.2)","--loki-yellow":"var(--vscode-editorWarning-foreground, #cca700)","--loki-yellow-muted":"rgba(204, 167, 0, 0.2)","--loki-red":"var(--vscode-errorForeground, #f48771)","--loki-red-muted":"rgba(244, 135, 113, 0.2)","--loki-blue":"var(--vscode-editorInfo-foreground, #75beff)","--loki-blue-muted":"rgba(117, 190, 255, 0.2)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.2)","--loki-opus":"#f59e0b","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.3)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.4)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.5)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #007fd4)"}},T={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},D={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},$={fontFamily:{sans:"'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif",serif:"'DM Serif Display', Georgia, 'Times New Roman', serif",mono:"'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace"},fontSize:{xs:"10px",sm:"11px",base:"12px",md:"13px",lg:"14px",xl:"16px","2xl":"18px","3xl":"24px"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.75"}},z={duration:{fast:"100ms",normal:"200ms",slow:"300ms",slower:"500ms"},easing:{default:"cubic-bezier(0.4, 0, 0.2, 1)",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)",bounce:"cubic-bezier(0.68, -0.55, 0.265, 1.55)"}},Te={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},R={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Le={"navigation.nextItem":{key:"ArrowDown",modifiers:[]},"navigation.prevItem":{key:"ArrowUp",modifiers:[]},"navigation.nextSection":{key:"Tab",modifiers:[]},"navigation.prevSection":{key:"Tab",modifiers:["Shift"]},"navigation.confirm":{key:"Enter",modifiers:[]},"navigation.cancel":{key:"Escape",modifiers:[]},"action.refresh":{key:"r",modifiers:["Meta"]},"action.search":{key:"k",modifiers:["Meta"]},"action.save":{key:"s",modifiers:["Meta"]},"action.close":{key:"w",modifiers:["Meta"]},"theme.toggle":{key:"d",modifiers:["Meta","Shift"]},"task.create":{key:"n",modifiers:["Meta"]},"task.complete":{key:"Enter",modifiers:["Meta"]},"view.toggleLogs":{key:"l",modifiers:["Meta","Shift"]},"view.toggleMemory":{key:"m",modifiers:["Meta","Shift"]}},De={button:{role:"button",tabIndex:0},tablist:{role:"tablist"},tab:{role:"tab",ariaSelected:!1,tabIndex:-1},tabpanel:{role:"tabpanel",tabIndex:0},list:{role:"list"},listitem:{role:"listitem"},livePolite:{ariaLive:"polite",ariaAtomic:!0},liveAssertive:{ariaLive:"assertive",ariaAtomic:!0},dialog:{role:"dialog",ariaModal:!0},alertdialog:{role:"alertdialog",ariaModal:!0},status:{role:"status",ariaLive:"polite"},alert:{role:"alert",ariaLive:"assertive"},log:{role:"log",ariaLive:"polite",ariaRelevant:"additions"}};function E(d){let e=C[d];return e?Object.entries(e).map(([t,i])=>`${t}: ${i};`).join(`
|
|
1542
|
-
`):""}function
|
|
1402
|
+
var LokiDashboard=(()=>{var He=Object.defineProperty;var xt=Object.getOwnPropertyDescriptor;var _t=Object.getOwnPropertyNames;var yt=Object.prototype.hasOwnProperty;var wt=(d,e,t)=>e in d?He(d,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[e]=t;var $t=(d,e)=>{for(var t in e)He(d,t,{get:e[t],enumerable:!0})},Et=(d,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of _t(e))!yt.call(d,a)&&a!==t&&He(d,a,{get:()=>e[a],enumerable:!(i=xt(e,a))||i.enumerable});return d};var Ct=d=>Et(He({},"__esModule",{value:!0}),d);var S=(d,e,t)=>wt(d,typeof e!="symbol"?e+"":e,t);var ai={};$t(ai,{ANIMATION:()=>B,ARIA_PATTERNS:()=>Pe,ApiEvents:()=>f,BASE_STYLES:()=>V,BREAKPOINTS:()=>Me,COMMON_STYLES:()=>Xe,KEYBOARD_SHORTCUTS:()=>Be,KeyboardHandler:()=>O,LokiActivityStream:()=>ye,LokiAgentLeaderboard:()=>Ae,LokiAnalytics:()=>ge,LokiApiClient:()=>N,LokiApiKeys:()=>xe,LokiAppPreview:()=>re,LokiAppStatus:()=>se,LokiAuditViewer:()=>ke,LokiChecklistViewer:()=>ae,LokiCheckpointViewer:()=>ne,LokiContextTracker:()=>le,LokiCostDashboard:()=>oe,LokiCostWaterfall:()=>Se,LokiCouncilDashboard:()=>ie,LokiCouncilTranscripts:()=>De,LokiElement:()=>g,LokiEscalations:()=>Le,LokiFleet:()=>be,LokiLearningDashboard:()=>te,LokiLogStream:()=>Z,LokiManagedMemoryPanel:()=>Te,LokiMemoryBrowser:()=>ee,LokiMemoryGraph:()=>Ce,LokiMigrationDashboard:()=>ue,LokiNotificationCenter:()=>de,LokiOverview:()=>Y,LokiPipelineView:()=>$e,LokiPromptOptimizer:()=>pe,LokiProviderHealth:()=>we,LokiQualityGates:()=>me,LokiQualityScore:()=>he,LokiRarvTimeline:()=>ve,LokiRunManager:()=>fe,LokiSessionControl:()=>X,LokiSessionDiff:()=>ce,LokiSpecPanel:()=>Re,LokiState:()=>W,LokiTaskBoard:()=>Q,LokiTenantSwitcher:()=>_e,LokiTheme:()=>j,LokiWikiBrowser:()=>ze,MARKDOWN_STYLES:()=>L,RADIUS:()=>M,SPACING:()=>D,STATE_CHANGE_EVENT:()=>je,THEMES:()=>A,THEME_VARIABLES:()=>Ie,TYPOGRAPHY:()=>$,UnifiedThemeManager:()=>w,VERSION:()=>ti,Z_INDEX:()=>P,createApiClient:()=>tt,createStore:()=>it,escapeHtml:()=>Ue,generateThemeCSS:()=>E,generateTokensCSS:()=>K,getApiClient:()=>m,getState:()=>U,init:()=>ii,renderMarkdown:()=>C});var A={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-bg-active":"#E6E2DA","--loki-bg-overlay":"rgba(32, 21, 21, 0.5)","--loki-accent":"#553DE9","--loki-accent-hover":"#4432c4","--loki-accent-active":"#3828a0","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-text-disabled":"#C5C0B1","--loki-text-inverse":"#ffffff","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-border-focus":"#553DE9","--loki-success":"#1FC5A8","--loki-success-muted":"rgba(31, 197, 168, 0.12)","--loki-warning":"#D4A03C","--loki-warning-muted":"rgba(212, 160, 60, 0.12)","--loki-error":"#C45B5B","--loki-error-muted":"rgba(196, 91, 91, 0.12)","--loki-info":"#2F71E3","--loki-info-muted":"rgba(47, 113, 227, 0.12)","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-shadow-sm":"0 1px 2px rgba(32, 21, 21, 0.04)","--loki-shadow-md":"0 4px 6px rgba(32, 21, 21, 0.06)","--loki-shadow-lg":"0 10px 15px rgba(32, 21, 21, 0.08)","--loki-shadow-focus":"0 0 0 3px rgba(85, 61, 233, 0.25)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-bg-active":"#352A55","--loki-bg-overlay":"rgba(20, 11, 36, 0.85)","--loki-accent":"#7B6BF0","--loki-accent-hover":"#9488F5","--loki-accent-active":"#6258D0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-text-disabled":"#5A4E78","--loki-text-inverse":"#1A0F2E","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-border-focus":"#7B6BF0","--loki-success":"#2ED8B6","--loki-success-muted":"rgba(46, 216, 182, 0.18)","--loki-warning":"#E8B84A","--loki-warning-muted":"rgba(232, 184, 74, 0.18)","--loki-error":"#E07070","--loki-error-muted":"rgba(224, 112, 112, 0.18)","--loki-info":"#5A9CF5","--loki-info-muted":"rgba(90, 156, 245, 0.18)","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.4)","--loki-shadow-md":"0 4px 12px rgba(0, 0, 0, 0.5)","--loki-shadow-lg":"0 10px 25px rgba(0, 0, 0, 0.6)","--loki-shadow-focus":"0 0 0 3px rgba(123, 107, 240, 0.30)"},"high-contrast":{"--loki-bg-primary":"#000000","--loki-bg-secondary":"#0a0a0a","--loki-bg-tertiary":"#141414","--loki-bg-card":"#0a0a0a","--loki-bg-hover":"#1a1a1a","--loki-bg-active":"#242424","--loki-bg-overlay":"rgba(0, 0, 0, 0.9)","--loki-accent":"#c084fc","--loki-accent-hover":"#d8b4fe","--loki-accent-active":"#e9d5ff","--loki-accent-light":"#d8b4fe","--loki-accent-muted":"rgba(192, 132, 252, 0.25)","--loki-text-primary":"#ffffff","--loki-text-secondary":"#e0e0e0","--loki-text-muted":"#b0b0b0","--loki-text-disabled":"#666666","--loki-text-inverse":"#000000","--loki-border":"#ffffff","--loki-border-light":"#cccccc","--loki-border-focus":"#c084fc","--loki-success":"#4ade80","--loki-success-muted":"rgba(74, 222, 128, 0.25)","--loki-warning":"#fde047","--loki-warning-muted":"rgba(253, 224, 71, 0.25)","--loki-error":"#f87171","--loki-error-muted":"rgba(248, 113, 113, 0.25)","--loki-info":"#60a5fa","--loki-info-muted":"rgba(96, 165, 250, 0.25)","--loki-green":"#4ade80","--loki-green-muted":"rgba(74, 222, 128, 0.25)","--loki-yellow":"#fde047","--loki-yellow-muted":"rgba(253, 224, 71, 0.25)","--loki-red":"#f87171","--loki-red-muted":"rgba(248, 113, 113, 0.25)","--loki-blue":"#60a5fa","--loki-blue-muted":"rgba(96, 165, 250, 0.25)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.25)","--loki-opus":"#fbbf24","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"none","--loki-shadow-md":"none","--loki-shadow-lg":"none","--loki-shadow-focus":"0 0 0 3px #c084fc"},"vscode-light":{"--loki-bg-primary":"var(--vscode-editor-background, #ffffff)","--loki-bg-secondary":"var(--vscode-sideBar-background, #f3f3f3)","--loki-bg-tertiary":"var(--vscode-input-background, #ffffff)","--loki-bg-card":"var(--vscode-editor-background, #ffffff)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #e8e8e8)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #0060c0)","--loki-bg-overlay":"rgba(0, 0, 0, 0.4)","--loki-accent":"var(--vscode-focusBorder, #0066cc)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #0055aa)","--loki-accent-active":"var(--vscode-button-background, #007acc)","--loki-accent-light":"var(--vscode-focusBorder, #0066cc)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 102, 204, 0.2))","--loki-text-primary":"var(--vscode-foreground, #333333)","--loki-text-secondary":"var(--vscode-descriptionForeground, #717171)","--loki-text-muted":"var(--vscode-disabledForeground, #a0a0a0)","--loki-text-disabled":"var(--vscode-disabledForeground, #cccccc)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #c8c8c8)","--loki-border-light":"var(--vscode-widget-border, #e0e0e0)","--loki-border-focus":"var(--vscode-focusBorder, #0066cc)","--loki-success":"var(--vscode-testing-iconPassed, #388a34)","--loki-success-muted":"rgba(56, 138, 52, 0.15)","--loki-warning":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-warning-muted":"rgba(191, 136, 3, 0.15)","--loki-error":"var(--vscode-errorForeground, #e51400)","--loki-error-muted":"rgba(229, 20, 0, 0.15)","--loki-info":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-info-muted":"rgba(26, 133, 255, 0.15)","--loki-green":"var(--vscode-testing-iconPassed, #388a34)","--loki-green-muted":"rgba(56, 138, 52, 0.15)","--loki-yellow":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-yellow-muted":"rgba(191, 136, 3, 0.15)","--loki-red":"var(--vscode-errorForeground, #e51400)","--loki-red-muted":"rgba(229, 20, 0, 0.15)","--loki-blue":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-blue-muted":"rgba(26, 133, 255, 0.15)","--loki-purple":"#9333ea","--loki-purple-muted":"rgba(147, 51, 234, 0.15)","--loki-opus":"#d97706","--loki-sonnet":"#4f46e5","--loki-haiku":"#059669","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.05)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.1)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.15)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #0066cc)"},"vscode-dark":{"--loki-bg-primary":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-secondary":"var(--vscode-sideBar-background, #252526)","--loki-bg-tertiary":"var(--vscode-input-background, #3c3c3c)","--loki-bg-card":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #2a2d2e)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #094771)","--loki-bg-overlay":"rgba(0, 0, 0, 0.6)","--loki-accent":"var(--vscode-focusBorder, #007fd4)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #1177bb)","--loki-accent-active":"var(--vscode-button-background, #0e639c)","--loki-accent-light":"var(--vscode-focusBorder, #007fd4)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 127, 212, 0.25))","--loki-text-primary":"var(--vscode-foreground, #cccccc)","--loki-text-secondary":"var(--vscode-descriptionForeground, #9d9d9d)","--loki-text-muted":"var(--vscode-disabledForeground, #6b6b6b)","--loki-text-disabled":"var(--vscode-disabledForeground, #4d4d4d)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #454545)","--loki-border-light":"var(--vscode-widget-border, #5a5a5a)","--loki-border-focus":"var(--vscode-focusBorder, #007fd4)","--loki-success":"var(--vscode-testing-iconPassed, #89d185)","--loki-success-muted":"rgba(137, 209, 133, 0.2)","--loki-warning":"var(--vscode-editorWarning-foreground, #cca700)","--loki-warning-muted":"rgba(204, 167, 0, 0.2)","--loki-error":"var(--vscode-errorForeground, #f48771)","--loki-error-muted":"rgba(244, 135, 113, 0.2)","--loki-info":"var(--vscode-editorInfo-foreground, #75beff)","--loki-info-muted":"rgba(117, 190, 255, 0.2)","--loki-green":"var(--vscode-testing-iconPassed, #89d185)","--loki-green-muted":"rgba(137, 209, 133, 0.2)","--loki-yellow":"var(--vscode-editorWarning-foreground, #cca700)","--loki-yellow-muted":"rgba(204, 167, 0, 0.2)","--loki-red":"var(--vscode-errorForeground, #f48771)","--loki-red-muted":"rgba(244, 135, 113, 0.2)","--loki-blue":"var(--vscode-editorInfo-foreground, #75beff)","--loki-blue-muted":"rgba(117, 190, 255, 0.2)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.2)","--loki-opus":"#f59e0b","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.3)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.4)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.5)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #007fd4)"}},D={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},M={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},$={fontFamily:{sans:"'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif",serif:"'DM Serif Display', Georgia, 'Times New Roman', serif",mono:"'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace"},fontSize:{xs:"10px",sm:"11px",base:"12px",md:"13px",lg:"14px",xl:"16px","2xl":"18px","3xl":"24px"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.75"}},B={duration:{fast:"100ms",normal:"200ms",slow:"300ms",slower:"500ms"},easing:{default:"cubic-bezier(0.4, 0, 0.2, 1)",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)",bounce:"cubic-bezier(0.68, -0.55, 0.265, 1.55)"}},Me={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},P={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Be={"navigation.nextItem":{key:"ArrowDown",modifiers:[]},"navigation.prevItem":{key:"ArrowUp",modifiers:[]},"navigation.nextSection":{key:"Tab",modifiers:[]},"navigation.prevSection":{key:"Tab",modifiers:["Shift"]},"navigation.confirm":{key:"Enter",modifiers:[]},"navigation.cancel":{key:"Escape",modifiers:[]},"action.refresh":{key:"r",modifiers:["Meta"]},"action.search":{key:"k",modifiers:["Meta"]},"action.save":{key:"s",modifiers:["Meta"]},"action.close":{key:"w",modifiers:["Meta"]},"theme.toggle":{key:"d",modifiers:["Meta","Shift"]},"task.create":{key:"n",modifiers:["Meta"]},"task.complete":{key:"Enter",modifiers:["Meta"]},"view.toggleLogs":{key:"l",modifiers:["Meta","Shift"]},"view.toggleMemory":{key:"m",modifiers:["Meta","Shift"]}},Pe={button:{role:"button",tabIndex:0},tablist:{role:"tablist"},tab:{role:"tab",ariaSelected:!1,tabIndex:-1},tabpanel:{role:"tabpanel",tabIndex:0},list:{role:"list"},listitem:{role:"listitem"},livePolite:{ariaLive:"polite",ariaAtomic:!0},liveAssertive:{ariaLive:"assertive",ariaAtomic:!0},dialog:{role:"dialog",ariaModal:!0},alertdialog:{role:"alertdialog",ariaModal:!0},status:{role:"status",ariaLive:"polite"},alert:{role:"alert",ariaLive:"assertive"},log:{role:"log",ariaLive:"polite",ariaRelevant:"additions"}};function E(d){let e=A[d];return e?Object.entries(e).map(([t,i])=>`${t}: ${i};`).join(`
|
|
1403
|
+
`):""}function K(){return`
|
|
1543
1404
|
/* Spacing */
|
|
1544
|
-
--loki-space-xs: ${
|
|
1545
|
-
--loki-space-sm: ${
|
|
1546
|
-
--loki-space-md: ${
|
|
1547
|
-
--loki-space-lg: ${
|
|
1548
|
-
--loki-space-xl: ${
|
|
1549
|
-
--loki-space-2xl: ${
|
|
1550
|
-
--loki-space-3xl: ${
|
|
1405
|
+
--loki-space-xs: ${D.xs};
|
|
1406
|
+
--loki-space-sm: ${D.sm};
|
|
1407
|
+
--loki-space-md: ${D.md};
|
|
1408
|
+
--loki-space-lg: ${D.lg};
|
|
1409
|
+
--loki-space-xl: ${D.xl};
|
|
1410
|
+
--loki-space-2xl: ${D["2xl"]};
|
|
1411
|
+
--loki-space-3xl: ${D["3xl"]};
|
|
1551
1412
|
|
|
1552
1413
|
/* Border Radius */
|
|
1553
|
-
--loki-radius-none: ${
|
|
1554
|
-
--loki-radius-sm: ${
|
|
1555
|
-
--loki-radius-md: ${
|
|
1556
|
-
--loki-radius-lg: ${
|
|
1557
|
-
--loki-radius-xl: ${
|
|
1558
|
-
--loki-radius-full: ${
|
|
1414
|
+
--loki-radius-none: ${M.none};
|
|
1415
|
+
--loki-radius-sm: ${M.sm};
|
|
1416
|
+
--loki-radius-md: ${M.md};
|
|
1417
|
+
--loki-radius-lg: ${M.lg};
|
|
1418
|
+
--loki-radius-xl: ${M.xl};
|
|
1419
|
+
--loki-radius-full: ${M.full};
|
|
1559
1420
|
|
|
1560
1421
|
/* Typography */
|
|
1561
1422
|
--loki-font-sans: ${$.fontFamily.sans};
|
|
@@ -1571,25 +1432,25 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
1571
1432
|
--loki-text-3xl: ${$.fontSize["3xl"]};
|
|
1572
1433
|
|
|
1573
1434
|
/* Animation */
|
|
1574
|
-
--loki-duration-fast: ${
|
|
1575
|
-
--loki-duration-normal: ${
|
|
1576
|
-
--loki-duration-slow: ${
|
|
1577
|
-
--loki-easing-default: ${
|
|
1578
|
-
--loki-transition: ${
|
|
1435
|
+
--loki-duration-fast: ${B.duration.fast};
|
|
1436
|
+
--loki-duration-normal: ${B.duration.normal};
|
|
1437
|
+
--loki-duration-slow: ${B.duration.slow};
|
|
1438
|
+
--loki-easing-default: ${B.easing.default};
|
|
1439
|
+
--loki-transition: ${B.duration.normal} ${B.easing.default};
|
|
1579
1440
|
|
|
1580
1441
|
/* Z-Index */
|
|
1581
|
-
--loki-z-dropdown: ${
|
|
1582
|
-
--loki-z-sticky: ${
|
|
1583
|
-
--loki-z-modal: ${
|
|
1584
|
-
--loki-z-popover: ${
|
|
1585
|
-
--loki-z-tooltip: ${
|
|
1586
|
-
--loki-z-toast: ${
|
|
1442
|
+
--loki-z-dropdown: ${P.dropdown};
|
|
1443
|
+
--loki-z-sticky: ${P.sticky};
|
|
1444
|
+
--loki-z-modal: ${P.modal};
|
|
1445
|
+
--loki-z-popover: ${P.popover};
|
|
1446
|
+
--loki-z-tooltip: ${P.tooltip};
|
|
1447
|
+
--loki-z-toast: ${P.toast};
|
|
1587
1448
|
|
|
1588
1449
|
/* Glass effect */
|
|
1589
1450
|
--loki-glass-bg: rgba(255, 255, 255, 0.03);
|
|
1590
1451
|
--loki-glass-border: rgba(255, 255, 255, 0.06);
|
|
1591
1452
|
--loki-glass-blur: blur(12px);
|
|
1592
|
-
`}var
|
|
1453
|
+
`}var V=`
|
|
1593
1454
|
/* Reset and base */
|
|
1594
1455
|
:host {
|
|
1595
1456
|
font-family: var(--loki-font-sans);
|
|
@@ -1865,20 +1726,20 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
1865
1726
|
}
|
|
1866
1727
|
|
|
1867
1728
|
/* Responsive utilities */
|
|
1868
|
-
@media (max-width: ${
|
|
1729
|
+
@media (max-width: ${Me.md}) {
|
|
1869
1730
|
.hide-mobile { display: none !important; }
|
|
1870
1731
|
}
|
|
1871
1732
|
|
|
1872
|
-
@media (min-width: ${
|
|
1733
|
+
@media (min-width: ${Me.md}) {
|
|
1873
1734
|
.hide-desktop { display: none !important; }
|
|
1874
1735
|
}
|
|
1875
|
-
`,
|
|
1736
|
+
`,y=class y{static detectContext(){return typeof acquireVsCodeApi<"u"||document.body.classList.contains("vscode-body")||getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background")?"vscode":document.documentElement.dataset.lokiContext==="cli"?"cli":"browser"}static detectVSCodeTheme(){let e=document.body;if(e.classList.contains("vscode-high-contrast"))return"high-contrast";if(e.classList.contains("vscode-dark"))return"dark";if(e.classList.contains("vscode-light"))return"light";let t=getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background");if(t){let i=t.match(/\d+/g);if(i)return(parseInt(i[0])*299+parseInt(i[1])*587+parseInt(i[2])*114)/1e3>128?"light":"dark"}return null}static getTheme(){if(y.detectContext()==="vscode"){let t=y.detectVSCodeTheme();return t==="high-contrast"?"high-contrast":t==="dark"?"vscode-dark":"vscode-light"}return"light"}static setTheme(e){if(!A[e]){console.warn(`Unknown theme: ${e}`);return}localStorage.setItem(y.STORAGE_KEY,e),document.documentElement.setAttribute("data-loki-theme",e),window.dispatchEvent(new CustomEvent("loki-theme-change",{detail:{theme:e,context:y.detectContext()}}))}static toggle(){let e=y.getTheme();return e.startsWith("vscode")?e:(y.setTheme("light"),"light")}static getVariables(e=null){let t=e||y.getTheme();return A[t]||A.light}static generateCSS(e=null){let t=e||y.getTheme();return`
|
|
1876
1737
|
:host {
|
|
1877
1738
|
${E(t)}
|
|
1878
|
-
${
|
|
1739
|
+
${K()}
|
|
1879
1740
|
}
|
|
1880
|
-
${
|
|
1881
|
-
`}static init(){let e=
|
|
1741
|
+
${V}
|
|
1742
|
+
`}static init(){let e=y.getTheme();document.documentElement.setAttribute("data-loki-theme",e),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{localStorage.getItem(y.STORAGE_KEY)||y.setTheme(y.getTheme())}),y.detectContext()==="vscode"&&new MutationObserver(()=>{let i=y.getTheme();document.documentElement.setAttribute("data-loki-theme",i),window.dispatchEvent(new CustomEvent("loki-theme-change",{detail:{theme:i,context:"vscode"}}))}).observe(document.body,{attributes:!0,attributeFilter:["class"]})}};S(y,"STORAGE_KEY","loki-theme"),S(y,"CONTEXT_KEY","loki-context");var w=y,O=class{constructor(){this._handlers=new Map,this._enabled=!0}register(e,t){let i=Be[e];if(!i){console.warn(`Unknown keyboard action: ${e}`);return}this._handlers.set(e,{shortcut:i,handler:t})}unregister(e){this._handlers.delete(e)}setEnabled(e){this._enabled=e}handleEvent(e){if(!this._enabled)return!1;for(let[t,{shortcut:i,handler:a}]of this._handlers)if(this._matchesShortcut(e,i))return e.preventDefault(),e.stopPropagation(),a(e),!0;return!1}_matchesShortcut(e,t){let i=e.key.toLowerCase(),a=t.modifiers||[];if(i!==t.key.toLowerCase())return!1;let s=a.includes("Ctrl")||a.includes("Meta"),r=a.includes("Shift"),o=a.includes("Alt"),n=(e.ctrlKey||e.metaKey)===s,l=e.shiftKey===r,c=e.altKey===o;return n&&l&&c}attach(e){this._boundHandler||(this._boundHandler=t=>this.handleEvent(t)),e.addEventListener("keydown",this._boundHandler)}detach(e){this._boundHandler&&e.removeEventListener("keydown",this._boundHandler)}};var Ie={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-accent":"#553DE9","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-transition":"0.2s cubic-bezier(0.4, 0, 0.2, 1)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-accent":"#7B6BF0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-transition":"0.2s cubic-bezier(0.4, 0, 0.2, 1)"}},Xe=`
|
|
1882
1743
|
:host {
|
|
1883
1744
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
1884
1745
|
line-height: 1.5;
|
|
@@ -1974,11 +1835,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
1974
1835
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary); }
|
|
1975
1836
|
::-webkit-scrollbar-thumb { background: var(--loki-border); border-radius: 3px; }
|
|
1976
1837
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light); }
|
|
1977
|
-
`,
|
|
1978
|
-
`)}static applyToElement(e,t=null){let i=
|
|
1838
|
+
`,F=class F{static getTheme(){return w.getTheme()}static setTheme(e){w.setTheme(e)}static toggle(){return w.toggle()}static getVariables(e=null){let t=e||F.getTheme();return A[t]||Ie[t]||Ie.light}static toCSSString(e=null){let t=e||F.getTheme();if(A[t])return E(t);let i=F.getVariables(t);return Object.entries(i).map(([a,s])=>`${a}: ${s};`).join(`
|
|
1839
|
+
`)}static applyToElement(e,t=null){let i=F.getVariables(t);for(let[a,s]of Object.entries(i))e.style.setProperty(a,s)}static init(){w.init()}static detectContext(){return w.detectContext()}static getAvailableThemes(){return Object.keys(A)}};S(F,"STORAGE_KEY","loki-theme");var j=F,g=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._theme=j.getTheme(),this._themeChangeHandler=this._onThemeChange.bind(this),this._keyboardHandler=new O}connectedCallback(){window.addEventListener("loki-theme-change",this._themeChangeHandler),this._applyTheme(),this._setupKeyboardHandling(),this.render()}disconnectedCallback(){window.removeEventListener("loki-theme-change",this._themeChangeHandler),this._keyboardHandler.detach(this)}_onThemeChange(e){this._theme=e.detail.theme,this._applyTheme(),this.onThemeChange&&this.onThemeChange(this._theme)}_applyTheme(){j.applyToElement(this.shadowRoot.host,this._theme),this.setAttribute("data-loki-theme",this._theme)}_setupKeyboardHandling(){this._keyboardHandler.attach(this)}registerShortcut(e,t){this._keyboardHandler.register(e,t)}getBaseStyles(){return`
|
|
1979
1840
|
/* Design tokens */
|
|
1980
1841
|
:host {
|
|
1981
|
-
${
|
|
1842
|
+
${K()}
|
|
1982
1843
|
}
|
|
1983
1844
|
|
|
1984
1845
|
/* Light theme (default) */
|
|
@@ -1986,8 +1847,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
1986
1847
|
${E("light")}
|
|
1987
1848
|
}
|
|
1988
1849
|
|
|
1989
|
-
/*
|
|
1990
|
-
|
|
1850
|
+
/* v7.90.1: dark mode removed (light-only). The OS-preference dark block is
|
|
1851
|
+
disabled via an always-false media query so an OS dark setting no longer
|
|
1852
|
+
flips components to dark. */
|
|
1853
|
+
@media (prefers-color-scheme: dark) and (max-width: 0px) {
|
|
1991
1854
|
:host {
|
|
1992
1855
|
${E("dark")}
|
|
1993
1856
|
}
|
|
@@ -2030,8 +1893,27 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2030
1893
|
}
|
|
2031
1894
|
}
|
|
2032
1895
|
|
|
2033
|
-
${
|
|
2034
|
-
`}getAriaPattern(e){return De[e]||{}}applyAriaPattern(e,t){let i=this.getAriaPattern(t);for(let[a,s]of Object.entries(i))if(a==="role")e.setAttribute("role",s);else{let r=a.replace(/([A-Z])/g,"-$1").toLowerCase();e.setAttribute(r,s)}}render(){}};var H={realtime:1e3,normal:2e3,background:5e3,offline:1e4},Ke={vscode:H.normal,browser:H.realtime,cli:H.background},Ve={baseUrl:typeof window<"u"?window.location.origin:"http://localhost:57374",wsUrl:typeof window<"u"?`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws`:"ws://localhost:57374/ws",pollInterval:2e3,timeout:1e4,retryAttempts:3,retryDelay:1e3},v={CONNECTED:"api:connected",DISCONNECTED:"api:disconnected",ERROR:"api:error",STATUS_UPDATE:"api:status-update",TASK_CREATED:"api:task-created",TASK_UPDATED:"api:task-updated",TASK_DELETED:"api:task-deleted",PROJECT_CREATED:"api:project-created",PROJECT_UPDATED:"api:project-updated",AGENT_UPDATE:"api:agent-update",LOG_MESSAGE:"api:log-message",MEMORY_UPDATE:"api:memory-update",CHECKLIST_UPDATE:"api:checklist-update"},L=class L extends EventTarget{static getInstance(e={}){let t=e.baseUrl||Ve.baseUrl;return L._instances.has(t)||L._instances.set(t,new L(e)),L._instances.get(t)}static clearInstances(){L._instances.forEach(e=>e.disconnect()),L._instances.clear()}constructor(e={}){super(),this.config={...Ve,...e},this._ws=null,this._connected=!1,this._pollInterval=null,this._reconnectTimeout=null,this._reconnectAttempts=0,this._maxReconnectAttempts=20,this._cache=new Map,this._cacheTimeout=5e3,this._vscodeApi=null,this._context=this._detectContext(),this._currentPollInterval=Ke[this._context]||H.normal,this._visibilityChangeHandler=null,this._messageHandler=null,this._setupAdaptivePolling(),this._setupVSCodeBridge()}_detectContext(){return typeof acquireVsCodeApi<"u"?"vscode":typeof window<"u"&&window.location?"browser":"cli"}get context(){return this._context}static get POLL_INTERVALS(){return H}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(H.background):this._setPollInterval(Ke[this._context]||H.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(e){this._currentPollInterval=e,this._pollInterval&&(this.stopPolling(),this.startPolling(null,e))}setPollMode(e){let t=H[e];t&&this._setPollInterval(t)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=e=>{let t=e.data;if(!(!t||!t.type))switch(t.type){case"updateStatus":this._emit(v.STATUS_UPDATE,t.data);break;case"updateTasks":this._emit(v.TASK_UPDATED,t.data);break;case"taskCreated":this._emit(v.TASK_CREATED,t.data);break;case"taskDeleted":this._emit(v.TASK_DELETED,t.data);break;case"projectCreated":this._emit(v.PROJECT_CREATED,t.data);break;case"projectUpdated":this._emit(v.PROJECT_UPDATED,t.data);break;case"agentUpdate":this._emit(v.AGENT_UPDATE,t.data);break;case"logMessage":this._emit(v.LOG_MESSAGE,t.data);break;case"memoryUpdate":this._emit(v.MEMORY_UPDATE,t.data);break;case"connected":this._connected=!0,this._emit(v.CONNECTED,t.data);break;case"disconnected":this._connected=!1,this._emit(v.DISCONNECTED,t.data);break;case"error":this._emit(v.ERROR,t.data);break;case"setPollMode":this.setPollMode(t.data.mode);break;default:this._emit(`api:${t.type}`,t.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(e,t={}){this._vscodeApi&&this._vscodeApi.postMessage({type:e,data:t})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(e,t={}){this.postToVSCode("userAction",{action:e,...t})}get baseUrl(){return this.config.baseUrl}set baseUrl(e){this.config.baseUrl=e,this.config.wsUrl=e.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((e,t)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._reconnectAttempts=0,this._emit(v.CONNECTED),e()},this._ws.onclose=()=>{this._connected=!1,this._emit(v.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=i=>{this._emit(v.ERROR,{error:i}),t(i)},this._ws.onmessage=i=>{try{let a=JSON.parse(i.data);this._handleMessage(a)}catch(a){console.error("Failed to parse WebSocket message:",a)}}}catch(i){t(i)}})}disconnect(){this._ws&&(this._ws.close(),this._ws=null),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._reconnectTimeout&&(clearTimeout(this._reconnectTimeout),this._reconnectTimeout=null),this._connected=!1,this._cleanupGlobalListeners()}_cleanupGlobalListeners(){this._visibilityChangeHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this._visibilityChangeHandler),this._visibilityChangeHandler=null),this._messageHandler&&typeof window<"u"&&(window.removeEventListener("message",this._messageHandler),this._messageHandler=null)}destroy(){this.disconnect()}_scheduleReconnect(){if(this._reconnectTimeout)return;if(this._reconnectAttempts>=this._maxReconnectAttempts){console.warn("WebSocket max reconnect attempts reached, giving up"),this._emit(v.ERROR,{error:"Max reconnect attempts reached"});return}let e=Math.min(this.config.retryDelay*Math.pow(2,this._reconnectAttempts),3e4);this._reconnectAttempts++,this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},e)}_handleMessage(e){if(e.type==="ping"){this._ws&&this._ws.readyState===WebSocket.OPEN&&this._ws.send(JSON.stringify({type:"pong"}));return}let i={connected:v.CONNECTED,status_update:v.STATUS_UPDATE,task_created:v.TASK_CREATED,task_updated:v.TASK_UPDATED,task_deleted:v.TASK_DELETED,task_moved:v.TASK_UPDATED,project_created:v.PROJECT_CREATED,project_updated:v.PROJECT_UPDATED,agent_update:v.AGENT_UPDATE,log:v.LOG_MESSAGE}[e.type]||`api:${e.type}`;this._emit(i,e.data)}_emit(e,t={}){this.dispatchEvent(new CustomEvent(e,{detail:t}))}async _request(e,t={}){let i=`${this.config.baseUrl}${e}`,a=new AbortController,s=t&&typeof t.timeout=="number"?t.timeout:this.config.timeout,r=setTimeout(()=>a.abort(),s);try{let o=await fetch(i,{...t,signal:a.signal,credentials:"include",headers:{"Content-Type":"application/json",...t.headers}});if(clearTimeout(r),!o.ok){let n=await o.text().catch(()=>""),l=o.statusText||`HTTP ${o.status}`;if(n)try{let c=JSON.parse(n);l=c.detail||c.error||c.message||l}catch{l=n.length>200?n.slice(0,200)+"...":n}throw new Error(l)}return o.status===204?null:await o.json()}catch(o){throw clearTimeout(r),o.name==="AbortError"?new Error("Request timeout"):o}}async _get(e,t=!1){if(t&&this._cache.has(e)){let a=this._cache.get(e);if(Date.now()-a.timestamp<this._cacheTimeout)return a.data}let i=await this._request(e);return t&&this._cache.set(e,{data:i,timestamp:Date.now()}),i}async _post(e,t,i={}){return this._request(e,{method:"POST",body:JSON.stringify(t),...i})}async _put(e,t){return this._request(e,{method:"PUT",body:JSON.stringify(t)})}async _delete(e){return this._request(e,{method:"DELETE"})}async get(e){return this._get(e)}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(e=null){let t=e?`?status=${e}`:"";return this._get(`/api/projects${t}`)}async getProject(e){return this._get(`/api/projects/${e}`)}async createProject(e){return this._post("/api/projects",e)}async updateProject(e,t){return this._put(`/api/projects/${e}`,t)}async deleteProject(e){return this._delete(`/api/projects/${e}`)}async listTasks(e={}){let t=new URLSearchParams;e.projectId&&t.append("project_id",e.projectId),e.status&&t.append("status",e.status),e.priority&&t.append("priority",e.priority);let i=t.toString()?`?${t}`:"";return this._get(`/api/tasks${i}`)}async getTask(e){return this._get(`/api/tasks/${e}`)}async createTask(e){return this._post("/api/tasks",e)}async updateTask(e,t){return this._put(`/api/tasks/${e}`,t)}async moveTask(e,t,i){return this._post(`/api/tasks/${e}/move`,{status:t,position:i})}async deleteTask(e){return this._delete(`/api/tasks/${e}`)}async getMemorySummary(){return this._get("/api/memory/summary",!0)}async getMemoryIndex(){return this._get("/api/memory/index",!0)}async getMemoryTimeline(){return this._get("/api/memory/timeline")}async listEpisodes(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/episodes${t?"?"+t:""}`)}async getEpisode(e){return this._get(`/api/memory/episodes/${e}`)}async listPatterns(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/patterns${t?"?"+t:""}`)}async getPattern(e){return this._get(`/api/memory/patterns/${e}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(e){return this._get(`/api/memory/skills/${e}`)}async retrieveMemories(e,t=null,i=5){return this._post("/api/memory/retrieve",{query:e,taskType:t,topK:i},{timeout:3e4})}async consolidateMemory(e=24){return this._post("/api/memory/consolidate",{sinceHours:e},{timeout:12e4})}async getTokenEconomics(){return this._get("/api/memory/economics")}async searchMemory(e,t="all",i=20){let a=new URLSearchParams({q:e,collection:t,limit:String(i)});return this._get(`/api/memory/search?${a}`)}async getMemoryStats(){return this._get("/api/memory/stats",!0)}async listRegisteredProjects(e=!1){return this._get(`/api/registry/projects?include_inactive=${e}`)}async registerProject(e,t=null,i=null){return this._post("/api/registry/projects",{path:e,name:t,alias:i})}async discoverProjects(e=3){return this._get(`/api/registry/discover?max_depth=${e}`)}async syncRegistry(){return this._post("/api/registry/sync",{},{timeout:45e3})}async getCrossProjectTasks(e=null){let t=e?`?project_ids=${e.join(",")}`:"";return this._get(`/api/registry/tasks${t}`)}async getLearningMetrics(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/metrics${i}`)}async getLearningTrends(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/trends${i}`)}async getLearningSignals(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source),e.limit&&t.append("limit",String(e.limit)),e.offset&&t.append("offset",String(e.offset));let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/signals${i}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(e={}){return this._post("/api/learning/aggregate",e,{timeout:6e4})}async getAggregatedPreferences(e=20){return this._get(`/api/learning/preferences?limit=${e}`)}async getAggregatedErrors(e=20){return this._get(`/api/learning/errors?limit=${e}`)}async getAggregatedSuccessPatterns(e=20){return this._get(`/api/learning/success?limit=${e}`)}async getToolEfficiency(e=20){return this._get(`/api/learning/tools?limit=${e}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(e=20){return this._get(`/api/council/verdicts?limit=${e}`)}async getCouncilConvergence(){return this._get("/api/council/convergence")}async getCouncilReport(){return this._get("/api/council/report")}async forceCouncilReview(){return this._post("/api/council/force-review",{})}async getContext(){return this._get("/api/context")}async getNotifications(e,t){let i=new URLSearchParams;e&&i.set("severity",e),t&&i.set("unread_only","true");let a=i.toString();return this._get("/api/notifications"+(a?"?"+a:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(e){return this._put("/api/notifications/triggers",{triggers:e})}async acknowledgeNotification(e){return this._post("/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{})}async startSession(e,t={}){let i={provider:t.provider||"claude",parallel:!!t.parallel};return t.prdPath?i.prd_path=t.prdPath:i.prd_text=e||"",this._post("/api/control/start",i)}async pauseSession(){return this._post("/api/control/pause",{})}async resumeSession(){return this._post("/api/control/resume",{})}async stopSession(){return this._post("/api/control/stop",{})}async getSessionModel(){return this._get("/api/session/model")}async setSessionModel(e){return this._post("/api/session/model",{model:e||null})}async getLogs(e=100){return this._get(`/api/logs?lines=${e}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let e=await fetch(`${this.baseUrl}/api/prd-observations`,{credentials:"include"});if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(e,t,i="dashboard"){return this._post("/api/checklist/waivers",{item_id:e,reason:t,waived_by:i})}async removeChecklistWaiver(e){return this._delete(`/api/checklist/waivers/${encodeURIComponent(e)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(e=100){return this._get(`/api/app-runner/logs?lines=${e}`)}async getAppRunnerErrors(e=50){return this._get(`/api/app-runner/errors?lines=${e}`)}async restartApp(){return this._post("/api/control/app-restart",{})}async stopApp(){return this._post("/api/control/app-stop",{})}async getPlaywrightResults(){return this._get("/api/playwright/results")}async getPlaywrightScreenshot(){return this._get("/api/playwright/screenshot")}startPolling(e,t=null){if(this._pollInterval)return;this._pollCallback=e;let i=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(v.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(v.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};i();let a=t||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(i,a)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};S(L,"_instances",new Map);var F=L;function We(d={}){return new F(d)}function g(d={}){return F.getInstance(d)}var He="loki-state-change",Re={ui:{theme:"light",sidebarCollapsed:!1,activeSection:"kanban",terminalAutoScroll:!0},session:{connected:!1,lastSync:null,mode:"offline",phase:null,iteration:null},localTasks:[],cache:{projects:[],tasks:[],agents:[],memory:null,lastFetch:null},preferences:{pollInterval:2e3,notifications:!0,soundEnabled:!1}},A=class A extends EventTarget{static getInstance(){return A._instance||(A._instance=new A),A._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let e=localStorage.getItem(A.STORAGE_KEY);if(e){let t=JSON.parse(e);return this._mergeState(Re,t)}}catch(e){console.warn("Failed to load state from localStorage:",e)}return{...Re}}_mergeState(e,t){let i={...e};for(let a of Object.keys(t))a in e&&typeof e[a]=="object"&&!Array.isArray(e[a])?i[a]=this._mergeState(e[a],t[a]):i[a]=t[a];return i}_saveState(){try{let e={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(A.STORAGE_KEY,JSON.stringify(e))}catch(e){console.warn("Failed to save state to localStorage:",e)}}get(e=null){if(!e)return{...this._state};let t=e.split("."),i=this._state;for(let a of t){if(i==null)return;i=i[a]}return i}set(e,t,i=!0){let a=e.split("."),s=a.pop(),r=this._state;for(let n of a)n in r||(r[n]={}),r=r[n];let o=r[s];r[s]=t,i&&this._saveState(),this._notifyChange(e,t,o)}update(e,t=!0){let i=[];for(let[a,s]of Object.entries(e)){let r=this.get(a);this.set(a,s,!1),i.push({path:a,value:s,oldValue:r})}t&&this._saveState();for(let a of i)this._notifyChange(a.path,a.value,a.oldValue)}_notifyChange(e,t,i){this.dispatchEvent(new CustomEvent(He,{detail:{path:e,value:t,oldValue:i}}));let a=this._subscribers.get(e)||[];for(let r of a)try{r(t,i,e)}catch(o){console.error("State subscriber error:",o)}let s=e.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let n of o)try{n(this.get(r),null,r)}catch(l){console.error("State subscriber error:",l)}}}subscribe(e,t){return this._subscribers.has(e)||this._subscribers.set(e,[]),this._subscribers.get(e).push(t),()=>{let i=this._subscribers.get(e),a=i.indexOf(t);a>-1&&i.splice(a,1)}}reset(e=null){if(e){let t=e.split("."),i=Re;for(let a of t)i=i?.[a];this.set(e,i)}else this._state={...Re},this._saveState(),this.dispatchEvent(new CustomEvent(He,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(e){let t=this.get("localTasks")||[],i={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...e};return this.set("localTasks",[...t,i]),i}updateLocalTask(e,t){let i=this.get("localTasks")||[],a=i.findIndex(r=>r.id===e);if(a===-1)return null;let s={...i[a],...t,updatedAt:new Date().toISOString()};return i[a]=s,this.set("localTasks",[...i]),s}deleteLocalTask(e){let t=this.get("localTasks")||[];this.set("localTasks",t.filter(i=>i.id!==e))}moveLocalTask(e,t,i=null){let s=(this.get("localTasks")||[]).find(r=>r.id===e);return s?this.updateLocalTask(e,{status:t,position:i??s.position}):null}updateSession(e){this.update(Object.fromEntries(Object.entries(e).map(([t,i])=>[`session.${t}`,i])),!1)}updateCache(e){this.update({"cache.projects":e.projects??this.get("cache.projects"),"cache.tasks":e.tasks??this.get("cache.tasks"),"cache.agents":e.agents??this.get("cache.agents"),"cache.memory":e.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let e=this.get("cache.tasks")||[],i=(this.get("localTasks")||[]).map(a=>({...a,isLocal:!0}));return[...e,...i]}getTasksByStatus(e){return this.getMergedTasks().filter(t=>t.status===e)}};S(A,"STORAGE_KEY","loki-dashboard-state"),S(A,"_instance",null);var O=A;function P(){return O.getInstance()}function Ye(d){let e=P();return{get:()=>e.get(d),set:t=>e.set(d,t),subscribe:t=>e.subscribe(d,t)}}function Qe(d){return!d||typeof d!="string"?null:d.startsWith("page-")?d.slice(5):d}function Be(){if(typeof document>"u")return null;let d=document.querySelector(".section-page.active");if(d&&d.id)return Qe(d.id);try{if(typeof localStorage<"u"){let e=localStorage.getItem("loki-active-section");if(e)return e}}catch{}return null}var Fe=class{constructor(){this._regs=new Map,this._seq=0,this._activeSection=Be(),this._hidden=typeof document<"u"?!!document.hidden:!1,this._listenersInstalled=!1,this._sectionChangeHandler=null,this._visibilityHandler=null,this._mutationObserver=null}get _hasDom(){return typeof document<"u"}_ensureListeners(){if(!(this._listenersInstalled||!this._hasDom)){this._sectionChangeHandler=e=>{let t=e&&e.detail&&e.detail.section?e.detail.section:Be();this._setActiveSection(t)},document.addEventListener("loki:section-change",this._sectionChangeHandler),this._visibilityHandler=()=>{let e=!!document.hidden;e!==this._hidden&&(this._hidden=e,e||(this._activeSection=Be()),this._reevaluateAll())},document.addEventListener("visibilitychange",this._visibilityHandler);try{let e=document.getElementById("main-content")||document.body;e&&typeof MutationObserver<"u"&&(this._mutationObserver=new MutationObserver(()=>{let t=Be();t&&t!==this._activeSection&&this._setActiveSection(t)}),this._mutationObserver.observe(e,{subtree:!0,attributes:!0,attributeFilter:["class"]}))}catch{}this._listenersInstalled=!0}}_setActiveSection(e){e!==this._activeSection&&(this._activeSection=e,this._reevaluateAll())}_resolveSection(e){if(Object.prototype.hasOwnProperty.call(e,"sectionId"))return e.sectionId===null?void 0:e.sectionId;if(e.element&&typeof e.element.closest=="function"){let t=e.element.closest(".section-page"),i=Qe(t&&t.id);return i===null?void 0:i}}_isAllowed(e){if(!this._hasDom)return!0;if(this._hidden)return!1;let t=this._resolveSection(e);return t===void 0?!0:t===this._activeSection}_reevaluateAll(){for(let e of this._regs.values()){let t=this._isAllowed(e);t&&!e._wasAllowed?(e._wasAllowed=!0,this._safeRun(e)):e._wasAllowed=t}}_safeRun(e){try{let t=e.loadFn();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}register(e={}){let{loadFn:t,intervalMs:i}=e;if(typeof t!="function")throw new Error("registerPoll: loadFn must be a function");if(typeof i!="number"||!(i>0))throw new Error("registerPoll: intervalMs must be a positive number");this._ensureListeners();let a=e.id||`poll-${++this._seq}`;this._regs.has(a)&&this._stopReg(this._regs.get(a));let s={id:a,loadFn:t,intervalMs:i,element:e.element||null,_timer:null,_wasAllowed:!1};return Object.prototype.hasOwnProperty.call(e,"sectionId")&&(s.sectionId=e.sectionId),s._wasAllowed=this._isAllowed(s),s._timer=setInterval(()=>{this._isAllowed(s)?(s._wasAllowed=!0,this._safeRun(s)):s._wasAllowed=!1},i),this._regs.set(a,s),e.immediate!==!1&&s._wasAllowed&&this._safeRun(s),{id:a,stop:()=>this.unregister(a),isActive:()=>this._isAllowed(s)}}_stopReg(e){e&&e._timer&&(clearInterval(e._timer),e._timer=null)}unregister(e){let t=this._regs.get(e);return t?(this._stopReg(t),this._regs.delete(e),!0):!1}get activeSection(){return this._activeSection}get size(){return this._regs.size}destroy(){for(let e of this._regs.values())this._stopReg(e);this._regs.clear(),this._hasDom&&(this._sectionChangeHandler&&(document.removeEventListener("loki:section-change",this._sectionChangeHandler),this._sectionChangeHandler=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null),this._mutationObserver&&(this._mutationObserver.disconnect(),this._mutationObserver=null)),this._listenersInstalled=!1}},Ie=null;function yt(){return Ie||(Ie=new Fe),Ie}function f(d){return yt().register(d)}var q=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data={status:"offline",phase:null,iteration:null,provider:null,running_agents:0,pending_tasks:null,uptime_seconds:0,complexity:null,connected:!1},this._api=null,this._pollInterval=null,this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null,this._checklistSummary=null,this._appRunnerStatus=null,this._playwrightResults=null,this._gateStatus=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._startPolling(),this._api.connect().catch(()=>{})}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._loadAbortController&&(this._loadAbortController.abort(),this._loadAbortController=null),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(v.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(v.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(v.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e}),this._statusUpdateHandler=t=>this._updateFromStatus(t.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(v.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(v.CONNECTED,this._connectedHandler),this._api.addEventListener(v.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){this._loadAbortController&&this._loadAbortController.abort(),this._loadAbortController=new AbortController;let{signal:e}=this._loadAbortController;try{let[t,i,a,s,r]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);if(e.aborted)return;t.status==="fulfilled"?this._updateFromStatus(t.value):(this._data.connected=!1,this._data.status="offline"),i.status==="fulfilled"&&(this._checklistSummary=i.value?.summary||null),a.status==="fulfilled"&&(this._appRunnerStatus=a.value),s.status==="fulfilled"&&(this._playwrightResults=s.value),r.status==="fulfilled"&&(this._gateStatus=r.value),this.render()}catch{if(e.aborted)return;this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(e){e&&(this._data={...this._data,connected:!0,status:e.status||"offline",phase:e.phase||null,iteration:e.iteration!=null?e.iteration:null,provider:e.provider||null,running_agents:e.running_agents||0,pending_tasks:e.pending_tasks!=null?e.pending_tasks:null,uptime_seconds:e.uptime_seconds||0,complexity:e.complexity||null})}_startPolling(){this._poll=f({loadFn:async()=>{try{await this._loadStatus()}catch{this._data.connected=!1,this._data.status="offline",this.render()}},intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatUptime(e){if(!e||e<0)return"--";let t=Math.floor(e/3600),i=Math.floor(e%3600/60),a=Math.floor(e%60);return t>0?`${t}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_getStatusDotClass(){switch(this._data.status){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let e=this._appRunnerStatus;if(!e||e.status==="not_initialized")return`
|
|
1896
|
+
${V}
|
|
1897
|
+
`}getAriaPattern(e){return Pe[e]||{}}applyAriaPattern(e,t){let i=this.getAriaPattern(t);for(let[a,s]of Object.entries(i))if(a==="role")e.setAttribute("role",s);else{let r=a.replace(/([A-Z])/g,"-$1").toLowerCase();e.setAttribute(r,s)}}render(){}};var I={realtime:1e3,normal:2e3,background:5e3,offline:1e4},Ze={vscode:I.normal,browser:I.realtime,cli:I.background},et={baseUrl:typeof window<"u"?window.location.origin:"http://localhost:57374",wsUrl:typeof window<"u"?`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws`:"ws://localhost:57374/ws",pollInterval:2e3,timeout:1e4,retryAttempts:3,retryDelay:1e3},f={CONNECTED:"api:connected",DISCONNECTED:"api:disconnected",ERROR:"api:error",STATUS_UPDATE:"api:status-update",TASK_CREATED:"api:task-created",TASK_UPDATED:"api:task-updated",TASK_DELETED:"api:task-deleted",PROJECT_CREATED:"api:project-created",PROJECT_UPDATED:"api:project-updated",AGENT_UPDATE:"api:agent-update",LOG_MESSAGE:"api:log-message",MEMORY_UPDATE:"api:memory-update",CHECKLIST_UPDATE:"api:checklist-update"},z=class z extends EventTarget{static getInstance(e={}){let t=e.baseUrl||et.baseUrl;return z._instances.has(t)||z._instances.set(t,new z(e)),z._instances.get(t)}static clearInstances(){z._instances.forEach(e=>e.disconnect()),z._instances.clear()}constructor(e={}){super(),this.config={...et,...e},this._ws=null,this._connected=!1,this._pollInterval=null,this._reconnectTimeout=null,this._reconnectAttempts=0,this._maxReconnectAttempts=20,this._cache=new Map,this._cacheTimeout=5e3,this._vscodeApi=null,this._context=this._detectContext(),this._currentPollInterval=Ze[this._context]||I.normal,this._visibilityChangeHandler=null,this._messageHandler=null,this._setupAdaptivePolling(),this._setupVSCodeBridge()}_detectContext(){return typeof acquireVsCodeApi<"u"?"vscode":typeof window<"u"&&window.location?"browser":"cli"}get context(){return this._context}static get POLL_INTERVALS(){return I}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(I.background):this._setPollInterval(Ze[this._context]||I.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(e){this._currentPollInterval=e,this._pollInterval&&(this.stopPolling(),this.startPolling(null,e))}setPollMode(e){let t=I[e];t&&this._setPollInterval(t)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=e=>{let t=e.data;if(!(!t||!t.type))switch(t.type){case"updateStatus":this._emit(f.STATUS_UPDATE,t.data);break;case"updateTasks":this._emit(f.TASK_UPDATED,t.data);break;case"taskCreated":this._emit(f.TASK_CREATED,t.data);break;case"taskDeleted":this._emit(f.TASK_DELETED,t.data);break;case"projectCreated":this._emit(f.PROJECT_CREATED,t.data);break;case"projectUpdated":this._emit(f.PROJECT_UPDATED,t.data);break;case"agentUpdate":this._emit(f.AGENT_UPDATE,t.data);break;case"logMessage":this._emit(f.LOG_MESSAGE,t.data);break;case"memoryUpdate":this._emit(f.MEMORY_UPDATE,t.data);break;case"connected":this._connected=!0,this._emit(f.CONNECTED,t.data);break;case"disconnected":this._connected=!1,this._emit(f.DISCONNECTED,t.data);break;case"error":this._emit(f.ERROR,t.data);break;case"setPollMode":this.setPollMode(t.data.mode);break;default:this._emit(`api:${t.type}`,t.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(e,t={}){this._vscodeApi&&this._vscodeApi.postMessage({type:e,data:t})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(e,t={}){this.postToVSCode("userAction",{action:e,...t})}get baseUrl(){return this.config.baseUrl}set baseUrl(e){this.config.baseUrl=e,this.config.wsUrl=e.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((e,t)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._reconnectAttempts=0,this._emit(f.CONNECTED),e()},this._ws.onclose=()=>{this._connected=!1,this._emit(f.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=i=>{this._emit(f.ERROR,{error:i}),t(i)},this._ws.onmessage=i=>{try{let a=JSON.parse(i.data);this._handleMessage(a)}catch(a){console.error("Failed to parse WebSocket message:",a)}}}catch(i){t(i)}})}disconnect(){this._ws&&(this._ws.close(),this._ws=null),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._reconnectTimeout&&(clearTimeout(this._reconnectTimeout),this._reconnectTimeout=null),this._connected=!1,this._cleanupGlobalListeners()}_cleanupGlobalListeners(){this._visibilityChangeHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this._visibilityChangeHandler),this._visibilityChangeHandler=null),this._messageHandler&&typeof window<"u"&&(window.removeEventListener("message",this._messageHandler),this._messageHandler=null)}destroy(){this.disconnect()}_scheduleReconnect(){if(this._reconnectTimeout)return;if(this._reconnectAttempts>=this._maxReconnectAttempts){console.warn("WebSocket max reconnect attempts reached, giving up"),this._emit(f.ERROR,{error:"Max reconnect attempts reached"});return}let e=Math.min(this.config.retryDelay*Math.pow(2,this._reconnectAttempts),3e4);this._reconnectAttempts++,this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},e)}_handleMessage(e){if(e.type==="ping"){this._ws&&this._ws.readyState===WebSocket.OPEN&&this._ws.send(JSON.stringify({type:"pong"}));return}let i={connected:f.CONNECTED,status_update:f.STATUS_UPDATE,task_created:f.TASK_CREATED,task_updated:f.TASK_UPDATED,task_deleted:f.TASK_DELETED,task_moved:f.TASK_UPDATED,project_created:f.PROJECT_CREATED,project_updated:f.PROJECT_UPDATED,agent_update:f.AGENT_UPDATE,log:f.LOG_MESSAGE}[e.type]||`api:${e.type}`;this._emit(i,e.data)}_emit(e,t={}){this.dispatchEvent(new CustomEvent(e,{detail:t}))}async _request(e,t={}){let i=`${this.config.baseUrl}${e}`,a=new AbortController,s=t&&typeof t.timeout=="number"?t.timeout:this.config.timeout,r=setTimeout(()=>a.abort(),s);try{let o=await fetch(i,{...t,signal:a.signal,credentials:"include",headers:{"Content-Type":"application/json",...t.headers}});if(clearTimeout(r),!o.ok){let n=await o.text().catch(()=>""),l=o.statusText||`HTTP ${o.status}`;if(n)try{let c=JSON.parse(n);l=c.detail||c.error||c.message||l}catch{l=n.length>200?n.slice(0,200)+"...":n}throw new Error(l)}return o.status===204?null:await o.json()}catch(o){throw clearTimeout(r),o.name==="AbortError"?new Error("Request timeout"):o}}async _get(e,t=!1){if(t&&this._cache.has(e)){let a=this._cache.get(e);if(Date.now()-a.timestamp<this._cacheTimeout)return a.data}let i=await this._request(e);return t&&this._cache.set(e,{data:i,timestamp:Date.now()}),i}async _post(e,t,i={}){return this._request(e,{method:"POST",body:JSON.stringify(t),...i})}async _put(e,t){return this._request(e,{method:"PUT",body:JSON.stringify(t)})}async _delete(e){return this._request(e,{method:"DELETE"})}async get(e){return this._get(e)}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(e=null){let t=e?`?status=${e}`:"";return this._get(`/api/projects${t}`)}async getProject(e){return this._get(`/api/projects/${e}`)}async createProject(e){return this._post("/api/projects",e)}async updateProject(e,t){return this._put(`/api/projects/${e}`,t)}async deleteProject(e){return this._delete(`/api/projects/${e}`)}async listTasks(e={}){let t=new URLSearchParams;e.projectId&&t.append("project_id",e.projectId),e.status&&t.append("status",e.status),e.priority&&t.append("priority",e.priority);let i=t.toString()?`?${t}`:"";return this._get(`/api/tasks${i}`)}async getTask(e){return this._get(`/api/tasks/${e}`)}async createTask(e){return this._post("/api/tasks",e)}async updateTask(e,t){return this._put(`/api/tasks/${e}`,t)}async moveTask(e,t,i){return this._post(`/api/tasks/${e}/move`,{status:t,position:i})}async deleteTask(e){return this._delete(`/api/tasks/${e}`)}async getMemorySummary(){return this._get("/api/memory/summary",!0)}async getMemoryIndex(){return this._get("/api/memory/index",!0)}async getMemoryTimeline(){return this._get("/api/memory/timeline")}async listEpisodes(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/episodes${t?"?"+t:""}`)}async getEpisode(e){return this._get(`/api/memory/episodes/${e}`)}async listPatterns(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/patterns${t?"?"+t:""}`)}async getPattern(e){return this._get(`/api/memory/patterns/${e}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(e){return this._get(`/api/memory/skills/${e}`)}async retrieveMemories(e,t=null,i=5){return this._post("/api/memory/retrieve",{query:e,taskType:t,topK:i},{timeout:3e4})}async consolidateMemory(e=24){return this._post("/api/memory/consolidate",{sinceHours:e},{timeout:12e4})}async getTokenEconomics(){return this._get("/api/memory/economics")}async searchMemory(e,t="all",i=20){let a=new URLSearchParams({q:e,collection:t,limit:String(i)});return this._get(`/api/memory/search?${a}`)}async getMemoryStats(){return this._get("/api/memory/stats",!0)}async listRegisteredProjects(e=!1){return this._get(`/api/registry/projects?include_inactive=${e}`)}async registerProject(e,t=null,i=null){return this._post("/api/registry/projects",{path:e,name:t,alias:i})}async discoverProjects(e=3){return this._get(`/api/registry/discover?max_depth=${e}`)}async syncRegistry(){return this._post("/api/registry/sync",{},{timeout:45e3})}async getCrossProjectTasks(e=null){let t=e?`?project_ids=${e.join(",")}`:"";return this._get(`/api/registry/tasks${t}`)}async getLearningMetrics(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/metrics${i}`)}async getLearningTrends(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/trends${i}`)}async getLearningSignals(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source),e.limit&&t.append("limit",String(e.limit)),e.offset&&t.append("offset",String(e.offset));let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/signals${i}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(e={}){return this._post("/api/learning/aggregate",e,{timeout:6e4})}async getAggregatedPreferences(e=20){return this._get(`/api/learning/preferences?limit=${e}`)}async getAggregatedErrors(e=20){return this._get(`/api/learning/errors?limit=${e}`)}async getAggregatedSuccessPatterns(e=20){return this._get(`/api/learning/success?limit=${e}`)}async getToolEfficiency(e=20){return this._get(`/api/learning/tools?limit=${e}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(e=20){return this._get(`/api/council/verdicts?limit=${e}`)}async getCouncilConvergence(){return this._get("/api/council/convergence")}async getCouncilReport(){return this._get("/api/council/report")}async forceCouncilReview(){return this._post("/api/council/force-review",{})}async getContext(){return this._get("/api/context")}async getNotifications(e,t){let i=new URLSearchParams;e&&i.set("severity",e),t&&i.set("unread_only","true");let a=i.toString();return this._get("/api/notifications"+(a?"?"+a:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(e){return this._put("/api/notifications/triggers",{triggers:e})}async acknowledgeNotification(e){return this._post("/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{})}async startSession(e,t={}){let i={provider:t.provider||"claude",parallel:!!t.parallel};return t.prdPath?i.prd_path=t.prdPath:i.prd_text=e||"",this._post("/api/control/start",i)}async pauseSession(){return this._post("/api/control/pause",{})}async resumeSession(){return this._post("/api/control/resume",{})}async stopSession(){return this._post("/api/control/stop",{})}async getSessionModel(){return this._get("/api/session/model")}async setSessionModel(e){return this._post("/api/session/model",{model:e||null})}async getLogs(e=100){return this._get(`/api/logs?lines=${e}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let e=await fetch(`${this.baseUrl}/api/prd-observations`,{credentials:"include"});if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(e,t,i="dashboard"){return this._post("/api/checklist/waivers",{item_id:e,reason:t,waived_by:i})}async removeChecklistWaiver(e){return this._delete(`/api/checklist/waivers/${encodeURIComponent(e)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(e=100){return this._get(`/api/app-runner/logs?lines=${e}`)}async getAppRunnerErrors(e=50){return this._get(`/api/app-runner/errors?lines=${e}`)}async restartApp(){return this._post("/api/control/app-restart",{})}async stopApp(){return this._post("/api/control/app-stop",{})}async getPlaywrightResults(){return this._get("/api/playwright/results")}async getPlaywrightScreenshot(){return this._get("/api/playwright/screenshot")}startPolling(e,t=null){if(this._pollInterval)return;this._pollCallback=e;let i=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(f.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(f.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};i();let a=t||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(i,a)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};S(z,"_instances",new Map);var N=z;function tt(d={}){return new N(d)}function m(d={}){return N.getInstance(d)}var je="loki-state-change",Fe={ui:{theme:"light",sidebarCollapsed:!1,activeSection:"kanban",terminalAutoScroll:!0},session:{connected:!1,lastSync:null,mode:"offline",phase:null,iteration:null},localTasks:[],cache:{projects:[],tasks:[],agents:[],memory:null,lastFetch:null},preferences:{pollInterval:2e3,notifications:!0,soundEnabled:!1}},T=class T extends EventTarget{static getInstance(){return T._instance||(T._instance=new T),T._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let e=localStorage.getItem(T.STORAGE_KEY);if(e){let t=JSON.parse(e);return this._mergeState(Fe,t)}}catch(e){console.warn("Failed to load state from localStorage:",e)}return{...Fe}}_mergeState(e,t){let i={...e};for(let a of Object.keys(t))a in e&&typeof e[a]=="object"&&!Array.isArray(e[a])?i[a]=this._mergeState(e[a],t[a]):i[a]=t[a];return i}_saveState(){try{let e={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(T.STORAGE_KEY,JSON.stringify(e))}catch(e){console.warn("Failed to save state to localStorage:",e)}}get(e=null){if(!e)return{...this._state};let t=e.split("."),i=this._state;for(let a of t){if(i==null)return;i=i[a]}return i}set(e,t,i=!0){let a=e.split("."),s=a.pop(),r=this._state;for(let n of a)n in r||(r[n]={}),r=r[n];let o=r[s];r[s]=t,i&&this._saveState(),this._notifyChange(e,t,o)}update(e,t=!0){let i=[];for(let[a,s]of Object.entries(e)){let r=this.get(a);this.set(a,s,!1),i.push({path:a,value:s,oldValue:r})}t&&this._saveState();for(let a of i)this._notifyChange(a.path,a.value,a.oldValue)}_notifyChange(e,t,i){this.dispatchEvent(new CustomEvent(je,{detail:{path:e,value:t,oldValue:i}}));let a=this._subscribers.get(e)||[];for(let r of a)try{r(t,i,e)}catch(o){console.error("State subscriber error:",o)}let s=e.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let n of o)try{n(this.get(r),null,r)}catch(l){console.error("State subscriber error:",l)}}}subscribe(e,t){return this._subscribers.has(e)||this._subscribers.set(e,[]),this._subscribers.get(e).push(t),()=>{let i=this._subscribers.get(e),a=i.indexOf(t);a>-1&&i.splice(a,1)}}reset(e=null){if(e){let t=e.split("."),i=Fe;for(let a of t)i=i?.[a];this.set(e,i)}else this._state={...Fe},this._saveState(),this.dispatchEvent(new CustomEvent(je,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(e){let t=this.get("localTasks")||[],i={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...e};return this.set("localTasks",[...t,i]),i}updateLocalTask(e,t){let i=this.get("localTasks")||[],a=i.findIndex(r=>r.id===e);if(a===-1)return null;let s={...i[a],...t,updatedAt:new Date().toISOString()};return i[a]=s,this.set("localTasks",[...i]),s}deleteLocalTask(e){let t=this.get("localTasks")||[];this.set("localTasks",t.filter(i=>i.id!==e))}moveLocalTask(e,t,i=null){let s=(this.get("localTasks")||[]).find(r=>r.id===e);return s?this.updateLocalTask(e,{status:t,position:i??s.position}):null}updateSession(e){this.update(Object.fromEntries(Object.entries(e).map(([t,i])=>[`session.${t}`,i])),!1)}updateCache(e){this.update({"cache.projects":e.projects??this.get("cache.projects"),"cache.tasks":e.tasks??this.get("cache.tasks"),"cache.agents":e.agents??this.get("cache.agents"),"cache.memory":e.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let e=this.get("cache.tasks")||[],i=(this.get("localTasks")||[]).map(a=>({...a,isLocal:!0}));return[...e,...i]}getTasksByStatus(e){return this.getMergedTasks().filter(t=>t.status===e)}};S(T,"STORAGE_KEY","loki-dashboard-state"),S(T,"_instance",null);var W=T;function U(){return W.getInstance()}function it(d){let e=U();return{get:()=>e.get(d),set:t=>e.set(d,t),subscribe:t=>e.subscribe(d,t)}}function Ue(d){return String(d??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function C(d){if(d==null||d==="")return"";let e=String(d).replace(/\r\n/g,`
|
|
1898
|
+
`),t=[];e=e.replace(/```[^\n]*\n([\s\S]*?)```/g,(h,v)=>{let u=t.length;return t.push(`<pre class="md-code"><code>${Ue(v.replace(/\n$/,""))}</code></pre>`),`\0CODEBLOCK${u}\0`});let i=Ue(e);i=i.replace(/`([^`\n]+)`/g,(h,v)=>`<code class="md-inline-code">${v}</code>`),i=i.replace(/\[([^\]\n]+)\]\(([^)\s]+)\)/g,(h,v,u)=>/^(https?:|mailto:|\/|#|\.)/.test(u)?`<a class="md-link" href="${u}" target="_blank" rel="noopener noreferrer">${v}</a>`:h);let a=i.split(`
|
|
1899
|
+
`),s=[],r=[],o=[],n=()=>{r.length&&(s.push(`<p class="md-p">${r.join("<br>")}</p>`),r=[])},l=h=>{for(;o.length&&o[o.length-1].indent>=h;)s.push(`</${o.pop().tag}>`)},c=()=>{for(;o.length;)s.push(`</${o.pop().tag}>`)};for(let h of a){let v=h,u=v.trim(),x=u.match(/^CODEBLOCK(\d+)$/);if(x){n(),c(),s.push(t[Number(x[1])]);continue}if(u===""){n(),c();continue}let k=u.match(/^(#{1,6})\s+(.+)$/);if(k){n(),c();let H=Math.min(k[1].length+1,6);s.push(`<h${H} class="md-h${H}">${k[2]}</h${H}>`);continue}if(/^(-{3,}|\*{3,}|_{3,})$/.test(u)){n(),c(),s.push('<hr class="md-hr">');continue}let _=u.match(/^>\s?(.*)$/);if(_){n(),c(),s.push(`<blockquote class="md-quote">${_[1]}</blockquote>`);continue}let R=v.match(/^(\s*)/)[1].replace(/\t/g," ").length,J=u.match(/^([-*+])\s+(.+)$/),G=u.match(/^(\d+)[.)]\s+(.+)$/);if(J||G){n();let H=G?"ol":"ul",kt=J?J[2]:G[2];!o.length||R>o[o.length-1].indent?(s.push(`<${H} class="md-list">`),o.push({tag:H,indent:R})):(l(R+1),o.length||(s.push(`<${H} class="md-list">`),o.push({tag:H,indent:R}))),s.push(`<li>${kt}</li>`);continue}c(),r.push(v.trim())}n(),c();let p=s.join(`
|
|
1900
|
+
`);return p=p.replace(/\*\*([^*\n]+)\*\*/g,"<strong>$1</strong>"),p=p.replace(/__([^_\n]+)__/g,"<strong>$1</strong>"),p=p.replace(/(^|[^*])\*([^*\n]+)\*/g,"$1<em>$2</em>"),p}var L=`
|
|
1901
|
+
.md-body { line-height: 1.6; color: var(--loki-text, #2b2a28); font-size: 14px; word-wrap: break-word; }
|
|
1902
|
+
.md-body .md-h2 { font-size: 18px; font-weight: 650; margin: 18px 0 8px; }
|
|
1903
|
+
.md-body .md-h3 { font-size: 16px; font-weight: 600; margin: 16px 0 6px; }
|
|
1904
|
+
.md-body .md-h4, .md-body .md-h5, .md-body .md-h6 { font-size: 14px; font-weight: 600; margin: 14px 0 6px; }
|
|
1905
|
+
.md-body .md-p { margin: 8px 0; }
|
|
1906
|
+
.md-body .md-list { margin: 8px 0 8px 22px; padding: 0; }
|
|
1907
|
+
.md-body .md-list li { margin: 3px 0; }
|
|
1908
|
+
.md-body .md-code { background: var(--loki-code-bg, #f4f2ee); border: 1px solid var(--loki-border, #e5e1d8); border-radius: 6px; padding: 12px 14px; overflow-x: auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.5; margin: 10px 0; }
|
|
1909
|
+
.md-body .md-code code { background: none; border: 0; padding: 0; }
|
|
1910
|
+
.md-body .md-inline-code { background: var(--loki-code-bg, #f4f2ee); border: 1px solid var(--loki-border, #e5e1d8); border-radius: 4px; padding: 1px 5px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }
|
|
1911
|
+
.md-body .md-quote { border-left: 3px solid var(--loki-accent, #6b6bff); margin: 10px 0; padding: 4px 0 4px 14px; color: var(--loki-text-secondary, #6b6a66); }
|
|
1912
|
+
.md-body .md-link { color: var(--loki-accent, #6b6bff); text-decoration: none; }
|
|
1913
|
+
.md-body .md-link:hover { text-decoration: underline; }
|
|
1914
|
+
.md-body .md-hr { border: 0; border-top: 1px solid var(--loki-border, #e5e1d8); margin: 16px 0; }
|
|
1915
|
+
.md-body strong { font-weight: 650; }
|
|
1916
|
+
`;function at(d){return!d||typeof d!="string"?null:d.startsWith("page-")?d.slice(5):d}function Oe(){if(typeof document>"u")return null;let d=document.querySelector(".section-page.active");if(d&&d.id)return at(d.id);try{if(typeof localStorage<"u"){let e=localStorage.getItem("loki-active-section");if(e)return e}}catch{}return null}var Je=class{constructor(){this._regs=new Map,this._seq=0,this._activeSection=Oe(),this._hidden=typeof document<"u"?!!document.hidden:!1,this._listenersInstalled=!1,this._sectionChangeHandler=null,this._visibilityHandler=null,this._mutationObserver=null}get _hasDom(){return typeof document<"u"}_ensureListeners(){if(!(this._listenersInstalled||!this._hasDom)){this._sectionChangeHandler=e=>{let t=e&&e.detail&&e.detail.section?e.detail.section:Oe();this._setActiveSection(t)},document.addEventListener("loki:section-change",this._sectionChangeHandler),this._visibilityHandler=()=>{let e=!!document.hidden;e!==this._hidden&&(this._hidden=e,e||(this._activeSection=Oe()),this._reevaluateAll())},document.addEventListener("visibilitychange",this._visibilityHandler);try{let e=document.getElementById("main-content")||document.body;e&&typeof MutationObserver<"u"&&(this._mutationObserver=new MutationObserver(()=>{let t=Oe();t&&t!==this._activeSection&&this._setActiveSection(t)}),this._mutationObserver.observe(e,{subtree:!0,attributes:!0,attributeFilter:["class"]}))}catch{}this._listenersInstalled=!0}}_setActiveSection(e){e!==this._activeSection&&(this._activeSection=e,this._reevaluateAll())}_resolveSection(e){if(Object.prototype.hasOwnProperty.call(e,"sectionId"))return e.sectionId===null?void 0:e.sectionId;if(e.element&&typeof e.element.closest=="function"){let t=e.element.closest(".section-page"),i=at(t&&t.id);return i===null?void 0:i}}_isAllowed(e){if(!this._hasDom)return!0;if(this._hidden)return!1;let t=this._resolveSection(e);return t===void 0?!0:t===this._activeSection}_reevaluateAll(){for(let e of this._regs.values()){let t=this._isAllowed(e);t&&!e._wasAllowed?(e._wasAllowed=!0,this._safeRun(e)):e._wasAllowed=t}}_safeRun(e){try{let t=e.loadFn();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}register(e={}){let{loadFn:t,intervalMs:i}=e;if(typeof t!="function")throw new Error("registerPoll: loadFn must be a function");if(typeof i!="number"||!(i>0))throw new Error("registerPoll: intervalMs must be a positive number");this._ensureListeners();let a=e.id||`poll-${++this._seq}`;this._regs.has(a)&&this._stopReg(this._regs.get(a));let s={id:a,loadFn:t,intervalMs:i,element:e.element||null,_timer:null,_wasAllowed:!1};return Object.prototype.hasOwnProperty.call(e,"sectionId")&&(s.sectionId=e.sectionId),s._wasAllowed=this._isAllowed(s),s._timer=setInterval(()=>{this._isAllowed(s)?(s._wasAllowed=!0,this._safeRun(s)):s._wasAllowed=!1},i),this._regs.set(a,s),e.immediate!==!1&&s._wasAllowed&&this._safeRun(s),{id:a,stop:()=>this.unregister(a),isActive:()=>this._isAllowed(s)}}_stopReg(e){e&&e._timer&&(clearInterval(e._timer),e._timer=null)}unregister(e){let t=this._regs.get(e);return t?(this._stopReg(t),this._regs.delete(e),!0):!1}get activeSection(){return this._activeSection}get size(){return this._regs.size}destroy(){for(let e of this._regs.values())this._stopReg(e);this._regs.clear(),this._hasDom&&(this._sectionChangeHandler&&(document.removeEventListener("loki:section-change",this._sectionChangeHandler),this._sectionChangeHandler=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null),this._mutationObserver&&(this._mutationObserver.disconnect(),this._mutationObserver=null)),this._listenersInstalled=!1}},qe=null;function St(){return qe||(qe=new Je),qe}function b(d){return St().register(d)}var Y=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data={status:"offline",phase:null,iteration:null,provider:null,running_agents:0,pending_tasks:null,uptime_seconds:0,complexity:null,connected:!1},this._api=null,this._pollInterval=null,this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null,this._checklistSummary=null,this._appRunnerStatus=null,this._playwrightResults=null,this._gateStatus=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._startPolling(),this._api.connect().catch(()=>{})}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._loadAbortController&&(this._loadAbortController.abort(),this._loadAbortController=null),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(f.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(f.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(f.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e}),this._statusUpdateHandler=t=>this._updateFromStatus(t.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(f.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(f.CONNECTED,this._connectedHandler),this._api.addEventListener(f.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){this._loadAbortController&&this._loadAbortController.abort(),this._loadAbortController=new AbortController;let{signal:e}=this._loadAbortController;try{let[t,i,a,s,r]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);if(e.aborted)return;t.status==="fulfilled"?this._updateFromStatus(t.value):(this._data.connected=!1,this._data.status="offline"),i.status==="fulfilled"&&(this._checklistSummary=i.value?.summary||null),a.status==="fulfilled"&&(this._appRunnerStatus=a.value),s.status==="fulfilled"&&(this._playwrightResults=s.value),r.status==="fulfilled"&&(this._gateStatus=r.value),this.render()}catch{if(e.aborted)return;this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(e){e&&(this._data={...this._data,connected:!0,status:e.status||"offline",phase:e.phase||null,iteration:e.iteration!=null?e.iteration:null,provider:e.provider||null,running_agents:e.running_agents||0,pending_tasks:e.pending_tasks!=null?e.pending_tasks:null,uptime_seconds:e.uptime_seconds||0,complexity:e.complexity||null})}_startPolling(){this._poll=b({loadFn:async()=>{try{await this._loadStatus()}catch{this._data.connected=!1,this._data.status="offline",this.render()}},intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatUptime(e){if(!e||e<0)return"--";let t=Math.floor(e/3600),i=Math.floor(e%3600/60),a=Math.floor(e%60);return t>0?`${t}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_getStatusDotClass(){switch(this._data.status){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let e=this._appRunnerStatus;if(!e||e.status==="not_initialized")return`
|
|
2035
1917
|
<div class="overview-card">
|
|
2036
1918
|
<div class="card-label">App Status</div>
|
|
2037
1919
|
<div class="card-value small-text">${this._data.status==="running"||this._data.status==="autonomous"?"Starting...":"Not started"}</div>
|
|
@@ -2286,8 +2168,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2286
2168
|
</div>
|
|
2287
2169
|
</div>
|
|
2288
2170
|
</div>
|
|
2289
|
-
`}};customElements.get("loki-overview")||customElements.define("loki-overview",
|
|
2290
|
-
<ul class="md-list">${a.trim().split(/\n/).map(r=>r.replace(/^[-*]\s+/,"")).map(r=>`<li>${r}</li>`).join("")}</ul>`),t=t.split(/\n{2,}/).map(i=>/^<(h\d|ul|ol|pre)/.test(i.trim())?i:`<p class="md-p">${i.replace(/\n/g,"<br>")}</p>`).join(""),t}_formatTimestamp(e){if(!e)return"";try{let t=new Date(e);return isNaN(t.getTime())?this._escapeHtml(String(e)):t.toLocaleString()}catch{return this._escapeHtml(String(e))}}_phaseClass(e){let t=String(e||"").toLowerCase();return["reason","plan","planning"].includes(t)?"phase-reason":["act","execute","execution","implement"].includes(t)?"phase-act":["reflect","review"].includes(t)?"phase-reflect":["verify","test","gate"].includes(t)?"phase-verify":"phase-default"}_logLevelClass(e){let t=String(e||"info").toLowerCase();return t==="error"||t==="fatal"?"log-error":t==="warn"||t==="warning"?"log-warn":t==="debug"||t==="trace"?"log-debug":"log-info"}_renderTaskDetailModal(e){if(!e)return"";let t=(e.priority||"medium").toLowerCase(),i=t.charAt(0).toUpperCase()+t.slice(1),a=e.status||"pending",s=a.replace(/_/g," ").replace(/\b\w/g,m=>m.toUpperCase()),r=e.metadata||{},o=e.acceptance_criteria||[],n=e.context_files||[],l=e.specification||"",c=e.description||"",p=Array.isArray(e.notes)?e.notes:[],h=Array.isArray(e.logs)?e.logs:[],b=e.full_content||"";return`
|
|
2171
|
+
`}};customElements.get("loki-overview")||customElements.define("loki-overview",Y);var At=[{id:"pending",label:"Pending",status:"pending",color:"var(--loki-text-muted)"},{id:"in_progress",label:"In Progress",status:"in_progress",color:"var(--loki-blue)"},{id:"review",label:"In Review",status:"review",color:"var(--loki-purple)"},{id:"done",label:"Completed",status:"done",color:"var(--loki-green)"}],Q=class d extends g{static get observedAttributes(){return["api-url","project-id","theme","readonly"]}constructor(){super(),this._tasks=[],this._loading=!0,this._error=null,this._draggedTask=null,this._selectedTask=null,this._expandedCards=new Set,this._selectedTasks=new Set,this._bulkMode=!1,this._activeFilter="all",this._searchQuery="",this._visibleCounts={},this._api=null,this._state=U()}static get PAGE_SIZE(){return 10}_getVisibleCount(e){let t=this._visibleCounts[e];return typeof t=="number"&&t>0?t:d.PAGE_SIZE}_showMore(e){this._visibleCounts[e]=this._getVisibleCount(e)+d.PAGE_SIZE,this.render()}_columnIcon(e){switch(e){case"pending":return'<circle cx="12" cy="12" r="10"/>';case"in_progress":return'<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>';case"review":return'<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>';case"done":return'<path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>';default:return'<circle cx="12" cy="12" r="10"/>'}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadTasks()}disconnectedCallback(){super.disconnectedCallback(),this._api&&(this._api.removeEventListener(f.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(f.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(f.TASK_DELETED,this._onTaskEvent))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadTasks()),e==="project-id"&&this._loadTasks(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e}),this._onTaskEvent&&(this._api.removeEventListener(f.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(f.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(f.TASK_DELETED,this._onTaskEvent)),this._onTaskEvent=()=>this._loadTasks(),this._api.addEventListener(f.TASK_CREATED,this._onTaskEvent),this._api.addEventListener(f.TASK_UPDATED,this._onTaskEvent),this._api.addEventListener(f.TASK_DELETED,this._onTaskEvent)}async _loadTasks(){this._loading=!0,this._error=null,this.render();try{let e=this.getAttribute("project-id"),t=e?{projectId:parseInt(e)}:{};this._tasks=await this._api.listTasks(t);let i=this._state.get("localTasks")||[];i.length>0&&(this._tasks=[...this._tasks,...i.map(a=>({...a,isLocal:!0}))]),this._state.update({"cache.tasks":this._tasks},!1)}catch(e){this._error=e.message,this._tasks=(this._state.get("localTasks")||[]).map(t=>({...t,isLocal:!0}))}this._loading=!1,this.render()}_getTasksByStatus(e){return this._getFilteredTasks().filter(i=>i.status?.toLowerCase().replace(/-/g,"_")===e)}_handleDragStart(e,t){this.hasAttribute("readonly")||(this._draggedTask=t,e.target.classList.add("dragging"),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",t.id.toString()))}_handleDragEnd(e){e.target.classList.remove("dragging"),this._draggedTask=null,this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(t=>{t.classList.remove("drag-over")})}_handleDragOver(e){e.preventDefault(),e.dataTransfer.dropEffect="move"}_handleDragEnter(e){e.preventDefault(),e.currentTarget.classList.add("drag-over")}_handleDragLeave(e){e.currentTarget.contains(e.relatedTarget)||e.currentTarget.classList.remove("drag-over")}async _handleDrop(e,t){if(e.preventDefault(),e.currentTarget.classList.remove("drag-over"),!this._draggedTask||this.hasAttribute("readonly"))return;let i=this._draggedTask.id,a=this._tasks.find(r=>r.id===i);if(!a)return;let s=a.status;if(s!==t){a.status=t,this.render();try{a.isLocal?this._state.moveLocalTask(i,t):await this._api.moveTask(i,t,0),this.dispatchEvent(new CustomEvent("task-moved",{detail:{taskId:i,oldStatus:s,newStatus:t}}))}catch(r){a.status=s,this.render(),console.error("Failed to move task:",r)}}}_toggleCardExpand(e){this._expandedCards.has(e)?this._expandedCards.delete(e):this._expandedCards.add(e),this.render()}_toggleTaskSelection(e,t){t&&t.stopPropagation(),this._selectedTasks.has(e)?this._selectedTasks.delete(e):this._selectedTasks.add(e),this.render()}_toggleBulkMode(){this._bulkMode=!this._bulkMode,this._bulkMode||this._selectedTasks.clear(),this.render()}async _bulkMove(e){let t=[...this._selectedTasks];for(let i of t){let a=this._tasks.find(s=>String(s.id)===String(i));if(a&&a.status!==e)try{a.isLocal?this._state.moveLocalTask(i,e):await this._api.moveTask(i,e,0),a.status=e}catch(s){console.error("Failed to bulk move task:",i,s)}}this._selectedTasks.clear(),this._bulkMode=!1,this.render(),this._loadTasks()}async _bulkDelete(){let e=[...this._selectedTasks];for(let t of e)try{await this._api.deleteTask(t)}catch(i){console.error("Failed to delete task:",t,i)}this._selectedTasks.clear(),this._bulkMode=!1,this._loadTasks()}_setFilter(e){this._activeFilter=e,this._visibleCounts={},this.render()}_setSearch(e){this._searchQuery=e||"",this._visibleCounts={},this._renderTaskRegion();let t=this.shadowRoot.getElementById("task-search");if(t){t.focus();let i=t.value.length;try{t.setSelectionRange(i,i)}catch{}}}_getFilteredTasks(){let e=[...this._tasks],t=new Date,i=new Date(t.getFullYear(),t.getMonth(),t.getDate()),a=new Date(i.getTime()-7*24*60*60*1e3);switch(this._activeFilter){case"today":e=e.filter(r=>{let o=r.created_at?new Date(r.created_at):null;return o&&o>=i});break;case"this-week":e=e.filter(r=>{let o=r.created_at?new Date(r.created_at):null;return o&&o>=a});break;case"running":e=e.filter(r=>r.status==="in_progress");break;case"failed":e=e.filter(r=>r.status==="failed"||r.status==="error");break;default:break}let s=this._searchQuery.trim().toLowerCase();return s&&(e=e.filter(r=>[r.id,r.title,r.description,r.type].map(n=>String(n??"").toLowerCase()).join(" ").includes(s))),e}_openAddTaskModal(e="pending"){this.dispatchEvent(new CustomEvent("add-task",{detail:{status:e}}))}_openTaskDetail(e){this._selectedTask=e,this.render(),this.dispatchEvent(new CustomEvent("task-click",{detail:{task:e}}))}_closeTaskDetail(){this._selectedTask=null,this.render()}_renderMarkdown(e){return C(e)}_formatTimestamp(e){if(!e)return"";try{let t=new Date(e);return isNaN(t.getTime())?this._escapeHtml(String(e)):t.toLocaleString()}catch{return this._escapeHtml(String(e))}}_phaseClass(e){let t=String(e||"").toLowerCase();return["reason","plan","planning"].includes(t)?"phase-reason":["act","execute","execution","implement"].includes(t)?"phase-act":["reflect","review"].includes(t)?"phase-reflect":["verify","test","gate"].includes(t)?"phase-verify":"phase-default"}_logLevelClass(e){let t=String(e||"info").toLowerCase();return t==="error"||t==="fatal"?"log-error":t==="warn"||t==="warning"?"log-warn":t==="debug"||t==="trace"?"log-debug":"log-info"}_renderTaskDetailModal(e){if(!e)return"";let t=(e.priority||"medium").toLowerCase(),i=t.charAt(0).toUpperCase()+t.slice(1),a=e.status||"pending",s=a.replace(/_/g," ").replace(/\b\w/g,u=>u.toUpperCase()),r=e.metadata||{},o=e.acceptance_criteria||[],n=e.context_files||[],l=e.specification||"",c=e.description||"",p=Array.isArray(e.notes)?e.notes:[],h=Array.isArray(e.logs)?e.logs:[],v=e.full_content||"";return`
|
|
2291
2172
|
<div class="modal-overlay" id="task-detail-overlay">
|
|
2292
2173
|
<div class="modal-container">
|
|
2293
2174
|
<div class="modal-header">
|
|
@@ -2304,9 +2185,9 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2304
2185
|
<div class="modal-section">
|
|
2305
2186
|
<h3 class="modal-section-title">Metadata</h3>
|
|
2306
2187
|
<div class="meta-grid">
|
|
2307
|
-
${Object.entries(r).map(([
|
|
2188
|
+
${Object.entries(r).map(([u,x])=>`
|
|
2308
2189
|
<div class="meta-cell">
|
|
2309
|
-
<span class="meta-label">${this._escapeHtml(
|
|
2190
|
+
<span class="meta-label">${this._escapeHtml(u.replace(/_/g," "))}</span>
|
|
2310
2191
|
<span class="meta-value">${this._escapeHtml(String(x))}</span>
|
|
2311
2192
|
</div>
|
|
2312
2193
|
`).join("")}
|
|
@@ -2332,9 +2213,9 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2332
2213
|
<div class="modal-section">
|
|
2333
2214
|
<h3 class="modal-section-title">Acceptance Criteria</h3>
|
|
2334
2215
|
<ul class="criteria-checklist" role="list">
|
|
2335
|
-
${o.map(
|
|
2336
|
-
<span class="criteria-checkbox ${
|
|
2337
|
-
<span class="criteria-text ${
|
|
2216
|
+
${o.map(u=>{let x=u&&typeof u=="object",k=x?u.text||u.title||"":u,_=x?!!u.done:!1;return`<li class="criteria-item">
|
|
2217
|
+
<span class="criteria-checkbox ${_?"checked":""}" aria-hidden="true">${_?"✓":""}</span>
|
|
2218
|
+
<span class="criteria-text ${_?"done":""}">${this._escapeHtml(String(k))}</span>
|
|
2338
2219
|
</li>`}).join("")}
|
|
2339
2220
|
</ul>
|
|
2340
2221
|
</div>
|
|
@@ -2344,12 +2225,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2344
2225
|
<div class="modal-section">
|
|
2345
2226
|
<h3 class="modal-section-title">Notes</h3>
|
|
2346
2227
|
<ul class="notes-timeline" role="list">
|
|
2347
|
-
${p.map(
|
|
2228
|
+
${p.map(u=>{let x=this._formatTimestamp(u&&u.timestamp),k=u&&u.author?this._escapeHtml(String(u.author)):"unknown",_=u&&u.body?this._escapeHtml(String(u.body)):"";return`<li class="note-entry">
|
|
2348
2229
|
<div class="note-meta">
|
|
2349
2230
|
<span class="note-author">${k}</span>
|
|
2350
2231
|
${x?`<span class="note-time">${x}</span>`:""}
|
|
2351
2232
|
</div>
|
|
2352
|
-
<div class="note-body">${
|
|
2233
|
+
<div class="note-body">${_}</div>
|
|
2353
2234
|
</li>`}).join("")}
|
|
2354
2235
|
</ul>
|
|
2355
2236
|
</div>
|
|
@@ -2360,11 +2241,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2360
2241
|
<h3 class="modal-section-title">Logs</h3>
|
|
2361
2242
|
<div class="logs-scroll">
|
|
2362
2243
|
<ul class="logs-timeline" role="list">
|
|
2363
|
-
${h.map(
|
|
2244
|
+
${h.map(u=>{let x=this._formatTimestamp(u&&u.timestamp),k=u&&u.iteration!==void 0&&u.iteration!==null?`i${this._escapeHtml(String(u.iteration))}`:"",_=u&&u.phase?String(u.phase):"",R=this._phaseClass(_),J=this._logLevelClass(u&&u.level),G=u&&u.message?this._escapeHtml(String(u.message)):"";return`<li class="log-entry ${J}">
|
|
2364
2245
|
${x?`<span class="log-time">${x}</span>`:""}
|
|
2365
2246
|
${k?`<span class="log-iter">${k}</span>`:""}
|
|
2366
|
-
${
|
|
2367
|
-
<span class="log-message">${
|
|
2247
|
+
${_?`<span class="log-phase ${R}">${this._escapeHtml(_)}</span>`:""}
|
|
2248
|
+
<span class="log-message">${G}</span>
|
|
2368
2249
|
</li>`}).join("")}
|
|
2369
2250
|
</ul>
|
|
2370
2251
|
</div>
|
|
@@ -2375,15 +2256,15 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2375
2256
|
<div class="modal-section">
|
|
2376
2257
|
<h3 class="modal-section-title">Context Files</h3>
|
|
2377
2258
|
<ul class="context-files-list">
|
|
2378
|
-
${n.map(
|
|
2259
|
+
${n.map(u=>`<li class="mono">${this._escapeHtml(u)}</li>`).join("")}
|
|
2379
2260
|
</ul>
|
|
2380
2261
|
</div>
|
|
2381
2262
|
`:""}
|
|
2382
2263
|
|
|
2383
|
-
${
|
|
2264
|
+
${v&&!l?`
|
|
2384
2265
|
<div class="modal-section">
|
|
2385
2266
|
<h3 class="modal-section-title">Full Content</h3>
|
|
2386
|
-
<pre class="modal-pre">${this._escapeHtml(
|
|
2267
|
+
<pre class="modal-pre">${this._escapeHtml(v)}</pre>
|
|
2387
2268
|
</div>
|
|
2388
2269
|
`:""}
|
|
2389
2270
|
|
|
@@ -2885,7 +2766,13 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2885
2766
|
color: var(--loki-text-muted);
|
|
2886
2767
|
}
|
|
2887
2768
|
|
|
2888
|
-
/*
|
|
2769
|
+
/* Shared markdown styles first, so the shared renderer's full class set
|
|
2770
|
+
(.md-quote, .md-hr, .md-link, .md-h5/h6, strong) is themed. The
|
|
2771
|
+
task-board overrides below have equal specificity and come after, so
|
|
2772
|
+
they still win on the classes they target (compact fonts/margins). */
|
|
2773
|
+
${L}
|
|
2774
|
+
|
|
2775
|
+
/* Markdown body inside Description section (compact overrides) */
|
|
2889
2776
|
.md-body .md-h2 { font-size: 14px; margin: 8px 0 4px; color: var(--loki-text-primary); }
|
|
2890
2777
|
.md-body .md-h3 { font-size: 13px; margin: 8px 0 4px; color: var(--loki-text-primary); }
|
|
2891
2778
|
.md-body .md-h4 { font-size: 12px; margin: 6px 0 2px; color: var(--loki-text-primary); }
|
|
@@ -3403,7 +3290,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
3403
3290
|
`:""}
|
|
3404
3291
|
|
|
3405
3292
|
<div class="kanban-board">
|
|
3406
|
-
${
|
|
3293
|
+
${At.map(a=>{let s=this._getTasksByStatus(a.status),r=this._getVisibleCount(a.status),o=s.slice(0,r),n=s.length-o.length;return`
|
|
3407
3294
|
<div class="kanban-column" data-status="${a.status}">
|
|
3408
3295
|
<div class="kanban-column-header">
|
|
3409
3296
|
<span class="kanban-column-title">
|
|
@@ -3467,7 +3354,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
3467
3354
|
</div>
|
|
3468
3355
|
`}).join("")}
|
|
3469
3356
|
</div>
|
|
3470
|
-
`}}_attachEventListeners(){let e=this.shadowRoot.getElementById("refresh-btn");e&&e.addEventListener("click",()=>this._loadTasks());let t=this.shadowRoot.getElementById("bulk-toggle-btn");t&&t.addEventListener("click",()=>this._toggleBulkMode()),this.shadowRoot.querySelectorAll(".filter-pill").forEach(r=>{r.addEventListener("click",()=>this._setFilter(r.dataset.filter))});let i=this.shadowRoot.getElementById("task-search");i&&i.addEventListener("input",r=>this._setSearch(r.target.value)),this.shadowRoot.querySelectorAll(".show-more-btn").forEach(r=>{r.addEventListener("click",()=>this._showMore(r.dataset.showMore))}),this.shadowRoot.querySelectorAll(".bulk-btn").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.bulkAction;o==="delete"?this._bulkDelete():this._bulkMove(o)})}),this.shadowRoot.querySelectorAll(".add-task-btn").forEach(r=>{r.addEventListener("click",()=>{this._openAddTaskModal(r.dataset.status)})}),this.shadowRoot.querySelectorAll(".task-checkbox").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation(),this._toggleTaskSelection(r.dataset.checkId,o)})}),this.shadowRoot.querySelectorAll(".expand-toggle").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation(),this._toggleCardExpand(r.dataset.expandId)})}),this.shadowRoot.querySelectorAll(".task-card").forEach(r=>{let o=r.dataset.taskId,n=this._tasks.find(l=>l.id.toString()===o);n&&(r.addEventListener("click",l=>{if(this._bulkMode){this._toggleTaskSelection(o,l);return}this._openTaskDetail(n)}),r.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._bulkMode?this._toggleTaskSelection(o,l):this._openTaskDetail(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateTaskCards(r,l.key==="ArrowDown"?"next":"prev"))}),r.classList.contains("draggable")&&(r.addEventListener("dragstart",l=>this._handleDragStart(l,n)),r.addEventListener("dragend",l=>this._handleDragEnd(l))))}),this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(r=>{r.addEventListener("dragover",o=>this._handleDragOver(o)),r.addEventListener("dragenter",o=>this._handleDragEnter(o)),r.addEventListener("dragleave",o=>this._handleDragLeave(o)),r.addEventListener("drop",o=>this._handleDrop(o,r.dataset.status))});let a=this.shadowRoot.getElementById("modal-close-btn");a&&a.addEventListener("click",()=>this._closeTaskDetail());let s=this.shadowRoot.getElementById("task-detail-overlay");s&&s.addEventListener("click",r=>{r.target===s&&this._closeTaskDetail()})}_escapeHtml(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}_navigateTaskCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".task-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-task-board")||customElements.define("loki-task-board",
|
|
3357
|
+
`}}_attachEventListeners(){let e=this.shadowRoot.getElementById("refresh-btn");e&&e.addEventListener("click",()=>this._loadTasks());let t=this.shadowRoot.getElementById("bulk-toggle-btn");t&&t.addEventListener("click",()=>this._toggleBulkMode()),this.shadowRoot.querySelectorAll(".filter-pill").forEach(r=>{r.addEventListener("click",()=>this._setFilter(r.dataset.filter))});let i=this.shadowRoot.getElementById("task-search");i&&i.addEventListener("input",r=>this._setSearch(r.target.value)),this.shadowRoot.querySelectorAll(".show-more-btn").forEach(r=>{r.addEventListener("click",()=>this._showMore(r.dataset.showMore))}),this.shadowRoot.querySelectorAll(".bulk-btn").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.bulkAction;o==="delete"?this._bulkDelete():this._bulkMove(o)})}),this.shadowRoot.querySelectorAll(".add-task-btn").forEach(r=>{r.addEventListener("click",()=>{this._openAddTaskModal(r.dataset.status)})}),this.shadowRoot.querySelectorAll(".task-checkbox").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation(),this._toggleTaskSelection(r.dataset.checkId,o)})}),this.shadowRoot.querySelectorAll(".expand-toggle").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation(),this._toggleCardExpand(r.dataset.expandId)})}),this.shadowRoot.querySelectorAll(".task-card").forEach(r=>{let o=r.dataset.taskId,n=this._tasks.find(l=>l.id.toString()===o);n&&(r.addEventListener("click",l=>{if(this._bulkMode){this._toggleTaskSelection(o,l);return}this._openTaskDetail(n)}),r.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._bulkMode?this._toggleTaskSelection(o,l):this._openTaskDetail(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateTaskCards(r,l.key==="ArrowDown"?"next":"prev"))}),r.classList.contains("draggable")&&(r.addEventListener("dragstart",l=>this._handleDragStart(l,n)),r.addEventListener("dragend",l=>this._handleDragEnd(l))))}),this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(r=>{r.addEventListener("dragover",o=>this._handleDragOver(o)),r.addEventListener("dragenter",o=>this._handleDragEnter(o)),r.addEventListener("dragleave",o=>this._handleDragLeave(o)),r.addEventListener("drop",o=>this._handleDrop(o,r.dataset.status))});let a=this.shadowRoot.getElementById("modal-close-btn");a&&a.addEventListener("click",()=>this._closeTaskDetail());let s=this.shadowRoot.getElementById("task-detail-overlay");s&&s.addEventListener("click",r=>{r.target===s&&this._closeTaskDetail()})}_escapeHtml(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}_navigateTaskCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".task-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-task-board")||customElements.define("loki-task-board",Q);var X=class extends g{static get observedAttributes(){return["api-url","theme","compact"]}constructor(){super(),this._status={mode:"offline",phase:null,iteration:null,complexity:null,connected:!1,version:null,uptime:0,activeAgents:0,pendingTasks:0},this._model={override:null,default:"sonnet",effective:"sonnet",notice:""},this._modelBusy=!1,this._startBusy=!1,this._startNotice="",this._specText="",this._api=null,this._state=U(),this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._loadModel(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(f.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(f.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(f.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),e==="theme"&&this._applyTheme(),e==="compact"&&this.render())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e}),this._statusUpdateHandler=t=>this._updateFromStatus(t.detail),this._connectedHandler=()=>{this._status.connected=!0,this.render()},this._disconnectedHandler=()=>{this._status.connected=!1,this._status.mode="offline",this.render()},this._api.addEventListener(f.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(f.CONNECTED,this._connectedHandler),this._api.addEventListener(f.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){try{let e=await this._api.getStatus();this._updateFromStatus(e)}catch{this._status.connected=!1,this._status.mode="offline",this.render()}}_updateFromStatus(e){e&&(this._status={...this._status,connected:!0,mode:e.status||"running",version:e.version,uptime:e.uptime_seconds||0,activeAgents:e.running_agents||0,pendingTasks:e.pending_tasks||0,phase:e.phase,iteration:e.iteration,complexity:e.complexity},this._state.updateSession({connected:!0,mode:this._status.mode,lastSync:new Date().toISOString()}),this.render())}_startPolling(){this._poll=b({loadFn:()=>this._loadStatus(),intervalMs:3e3,sectionId:null,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatUptime(e){if(!e||e<0)return"--";let t=Math.floor(e/3600),i=Math.floor(e%3600/60),a=Math.floor(e%60);return t>0?`${t}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_escapeHtml(e){let t=document.createElement("div");return t.textContent=String(e??""),t.innerHTML}_getStatusClass(){switch(this._status.mode){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_getStatusLabel(){switch(this._status.mode){case"running":case"autonomous":return"AUTONOMOUS";case"paused":return"PAUSED";case"stopped":return"STOPPED";case"error":return"ERROR";default:return"OFFLINE"}}async _triggerStart(){if(this._startBusy)return;let e=(this._specText||"").trim();if(!e){this._startNotice="Enter a spec or one-line brief to start a build.",this.render();return}if(!this._api||typeof this._api.startSession!="function"){this._startNotice="Start is not available on this server.",this.render();return}this._startBusy=!0,this._startNotice="Starting build...",this.render();try{let t=await this._api.startSession(e,{provider:this._status.provider||"claude"});if(t&&t.error)throw new Error(t.error);this._startBusy=!1,this._startNotice="",this._specText="",this._status.mode="running",this._status.connected=!0,this.render(),this._loadStatus(),this.dispatchEvent(new CustomEvent("session-start",{detail:{...this._status,pid:t&&t.pid,spec:t&&t.spec}}))}catch(t){console.error("Failed to start build:",t),this._startBusy=!1,this._startNotice=t&&t.message?`Could not start: ${t.message}`:"Could not start the build. Try again.",this.render()}}_onSpecInput(e){this._specText=e}async _triggerPause(){try{let e=await this._api.pauseSession();if(e&&e.error)throw new Error(e.error);this._status.mode="paused",this.render(),this.dispatchEvent(new CustomEvent("session-pause",{detail:this._status}))}catch(e){console.error("Failed to pause session:",e),this.render()}}async _triggerResume(){try{let e=await this._api.resumeSession();if(e&&e.error)throw new Error(e.error);this._status.mode="running",this.render(),this.dispatchEvent(new CustomEvent("session-resume",{detail:this._status}))}catch(e){console.error("Failed to resume session:",e),this.render()}}async _triggerStop(){try{let e=await this._api.stopSession();if(e&&e.error)throw new Error(e.error);this._status.mode="stopped",this.render(),this.dispatchEvent(new CustomEvent("session-stop",{detail:this._status}))}catch(e){console.error("Failed to stop session:",e),this.render()}}async _loadModel(){if(!(!this._api||typeof this._api.getSessionModel!="function"))try{let e=await this._api.getSessionModel();e&&!e.error&&(this._model={...this._model,override:e.override??null,default:e.default||"sonnet",effective:e.effective||e.default||"sonnet"},this.render())}catch{}}async _onModelChange(e){if(this._modelBusy)return;this._modelBusy=!0;let t=e===""?null:e;try{let i=await this._api.setSessionModel(t);if(i&&i.error)throw new Error(i.error);this._model.override=t,this._model.notice=t?`Switching to ${t}. Applies from the next iteration, for the current run only.`:"Override cleared. Reverts to the tier mapping from the next iteration.",this._modelBusy=!1,await this._loadModel()}catch(i){console.error("Failed to set session model:",i),this._model.notice="Could not change the model. Try again.",this._modelBusy=!1,this.render()}}_renderModelControl(){let e=this._model.override||"",i=[{value:"",label:`Default (tier: ${this._escapeHtml(this._model.default)})`},{value:"haiku",label:"Haiku (fastest, cheapest)"},{value:"sonnet",label:"Sonnet (balanced)"},{value:"opus",label:"Opus (top coding)"},{value:"fable",label:"Fable 5 (2x Opus cost: $10/$50 per MTok)"}].map(s=>{let r=s.value===e?" selected":"";return`<option value="${this._escapeHtml(s.value)}"${r}>${this._escapeHtml(s.label)}</option>`}).join(""),a=this._model.effective==="fable";return`
|
|
3471
3358
|
<div class="model-control">
|
|
3472
3359
|
<div class="model-row">
|
|
3473
3360
|
<label for="model-select">Model</label>
|
|
@@ -3495,7 +3382,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
3495
3382
|
</button>
|
|
3496
3383
|
${this._startNotice?`<div class="start-notice">${this._escapeHtml(this._startNotice)}</div>`:""}
|
|
3497
3384
|
</div>
|
|
3498
|
-
`}render(){let e=this.hasAttribute("compact"),t=this._getStatusClass(),i=this._getStatusLabel(),a=["running","autonomous"].includes(this._status.mode),s=this._status.mode==="paused",r=!a&&!s,o=`
|
|
3385
|
+
`}render(){if(this._modelInteracting){this._renderPending=!0;return}let e=this.hasAttribute("compact"),t=this._getStatusClass(),i=this._getStatusLabel(),a=["running","autonomous"].includes(this._status.mode),s=this._status.mode==="paused",r=!a&&!s,o=`
|
|
3499
3386
|
<style>
|
|
3500
3387
|
${this.getBaseStyles()}
|
|
3501
3388
|
|
|
@@ -3866,12 +3753,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
3866
3753
|
</div>
|
|
3867
3754
|
</div>
|
|
3868
3755
|
</div>
|
|
3869
|
-
`,c=this.shadowRoot.activeElement,p=c&&c.id==="spec-input",h=p?c.selectionStart:null,
|
|
3756
|
+
`,c=this.shadowRoot.activeElement,p=c&&c.id==="spec-input",h=p?c.selectionStart:null,v=p?c.selectionEnd:null;if(this.shadowRoot.innerHTML=`
|
|
3870
3757
|
${o}
|
|
3871
3758
|
${e?n:l}
|
|
3872
|
-
`,this._attachEventListeners(),p){let
|
|
3759
|
+
`,this._attachEventListeners(),p){let u=this.shadowRoot.getElementById("spec-input");if(u&&!u.disabled){u.focus();try{u.setSelectionRange(h,v)}catch{}}}}_attachEventListeners(){let e=this.shadowRoot.getElementById("pause-btn"),t=this.shadowRoot.getElementById("resume-btn"),i=this.shadowRoot.getElementById("stop-btn"),a=this.shadowRoot.getElementById("start-btn");e&&e.addEventListener("click",()=>this._triggerPause()),t&&t.addEventListener("click",()=>this._triggerResume()),i&&i.addEventListener("click",()=>this._triggerStop()),a&&a.addEventListener("click",()=>this._triggerStart());let s=this.shadowRoot.getElementById("model-select");if(s){let o=()=>{this._modelInteracting=!1,this._renderPending&&(this._renderPending=!1,this.render())};s.addEventListener("mousedown",()=>{this._modelInteracting=!0}),s.addEventListener("focus",()=>{this._modelInteracting=!0}),s.addEventListener("blur",o),s.addEventListener("change",n=>{this._modelInteracting=!1,this._renderPending=!1,this._onModelChange(n.target.value)})}let r=this.shadowRoot.getElementById("spec-input");r&&r.addEventListener("input",o=>this._onSpecInput(o.target.value))}};customElements.get("loki-session-control")||customElements.define("loki-session-control",X);var st={info:{color:"var(--loki-blue)",label:"INFO"},success:{color:"var(--loki-green)",label:"SUCCESS"},warning:{color:"var(--loki-yellow)",label:"WARN"},error:{color:"var(--loki-red)",label:"ERROR"},step:{color:"var(--loki-purple)",label:"STEP"},agent:{color:"var(--loki-accent)",label:"AGENT"},debug:{color:"var(--loki-text-muted)",label:"DEBUG"}},Z=class extends g{static get observedAttributes(){return["api-url","max-lines","auto-scroll","theme","log-file"]}constructor(){super(),this._logs=[],this._maxLines=500,this._autoScroll=!0,this._filter="",this._levelFilter="all",this._api=null,this._pollInterval=null,this._logMessageHandler=null,this._apiLastCount=0,this._apiLastSig=null,this._fileLastSize=0,this._fileLastSig=null}connectedCallback(){super.connectedCallback(),this._maxLines=parseInt(this.getAttribute("max-lines"))||500,this._autoScroll=this.hasAttribute("auto-scroll"),this._setupApi(),this._startLogPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopLogPolling(),this._api&&this._logMessageHandler&&this._api.removeEventListener(f.LOG_MESSAGE,this._logMessageHandler)}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i);break;case"max-lines":this._maxLines=parseInt(i)||500,this._trimLogs(),this.render();break;case"auto-scroll":this._autoScroll=this.hasAttribute("auto-scroll"),this.render();break;case"theme":this._applyTheme();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e}),this._logMessageHandler=t=>this._addLog(t.detail),this._api.addEventListener(f.LOG_MESSAGE,this._logMessageHandler)}_startLogPolling(){let e=this.getAttribute("log-file");e?this._pollLogFile(e):this._pollApiLogs()}async _pollApiLogs(){await this._apiLogPollTick(),this._poll=b({loadFn:()=>this._apiLogPollTick(),intervalMs:5e3,element:this,immediate:!1})}async _apiLogPollTick(){try{let e=await this._api.getLogs(200);if(!Array.isArray(e))return;let t=e.length?`${e.length}:${e[e.length-1]?.timestamp||""}:${e[e.length-1]?.message||""}`:"0";if(t===this._apiLastSig)return;if(this._apiLastSig=t,e.length>this._apiLastCount){let i=e.slice(this._apiLastCount);for(let a of i)a.message&&a.message.trim()&&this._addLog({message:a.message,level:a.level||"info",timestamp:a.timestamp||new Date().toLocaleTimeString()})}else e.length<this._apiLastCount&&(this._apiLastCount=0);this._apiLastCount=e.length}catch{}}async _pollLogFile(e){await this._fileLogPollTick(e),this._poll=b({loadFn:()=>this._fileLogPollTick(e),intervalMs:1e3,element:this,immediate:!1})}async _fileLogPollTick(e){try{let t=await fetch(`${e}?t=${Date.now()}`,{credentials:"include"});if(!t.ok)return;let i=await t.text(),a=`${i.length}`;if(a===this._fileLastSig)return;this._fileLastSig=a;let s=i.split(`
|
|
3873
3760
|
`);if(s.length>this._fileLastSize){let r=s.slice(this._fileLastSize);for(let o of r)o.trim()&&this._addLog(this._parseLine(o))}else s.length<this._fileLastSize&&(this._fileLastSize=0);this._fileLastSize=s.length}catch{}}_stopLogPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_parseLine(e){let t=e.match(/^\[([^\]]+)\]\s*\[([^\]]+)\]\s*(.+)$/);if(t)return{timestamp:t[1],level:t[2].toLowerCase(),message:t[3]};let i=e.match(/^(\d{2}:\d{2}:\d{2})\s+(\w+)\s+(.+)$/);return i?{timestamp:i[1],level:i[2].toLowerCase(),message:i[3]}:{timestamp:new Date().toLocaleTimeString(),level:"info",message:e}}_addLog(e){if(!e)return;let t={id:Date.now()+Math.random(),timestamp:e.timestamp||new Date().toLocaleTimeString(),level:(e.level||"info").toLowerCase(),message:e.message||e};this._logs.push(t),this._trimLogs(),this.dispatchEvent(new CustomEvent("log-received",{detail:t})),this._renderLogs(),this._autoScroll&&this._scrollToBottom()}_trimLogs(){this._logs.length>this._maxLines&&(this._logs=this._logs.slice(-this._maxLines))}_clearLogs(){this._logs=[],this.dispatchEvent(new CustomEvent("logs-cleared")),this._renderLogs()}_toggleAutoScroll(){this._autoScroll=!this._autoScroll,this.render(),this._autoScroll&&this._scrollToBottom()}_scrollToBottom(){requestAnimationFrame(()=>{let e=this.shadowRoot.getElementById("log-output");e&&(e.scrollTop=e.scrollHeight)})}_downloadLogs(){let e=this._logs.map(s=>`[${s.timestamp}] [${s.level.toUpperCase()}] ${s.message}`).join(`
|
|
3874
|
-
`),t=new Blob([e],{type:"text/plain"}),i=URL.createObjectURL(t),a=document.createElement("a");a.href=i,a.download=`loki-logs-${new Date().toISOString().split("T")[0]}.txt`,a.click(),URL.revokeObjectURL(i)}_setFilter(e){this._filter=e.toLowerCase(),this._renderLogs()}_setLevelFilter(e){this._levelFilter=e,this._renderLogs()}_getFilteredLogs(){return this._logs.filter(e=>!(this._levelFilter!=="all"&&e.level!==this._levelFilter||this._filter&&!e.message.toLowerCase().includes(this._filter)))}_renderLogs(){let e=this.shadowRoot.getElementById("log-output");if(!e)return;let t=this._getFilteredLogs();if(t.length===0){e.innerHTML='<div class="log-empty">No log output yet. Terminal will update when Loki Mode is running.</div>';return}e.innerHTML=t.map(i=>{let a=
|
|
3761
|
+
`),t=new Blob([e],{type:"text/plain"}),i=URL.createObjectURL(t),a=document.createElement("a");a.href=i,a.download=`loki-logs-${new Date().toISOString().split("T")[0]}.txt`,a.click(),URL.revokeObjectURL(i)}_setFilter(e){this._filter=e.toLowerCase(),this._renderLogs()}_setLevelFilter(e){this._levelFilter=e,this._renderLogs()}_getFilteredLogs(){return this._logs.filter(e=>!(this._levelFilter!=="all"&&e.level!==this._levelFilter||this._filter&&!e.message.toLowerCase().includes(this._filter)))}_renderLogs(){let e=this.shadowRoot.getElementById("log-output");if(!e)return;let t=this._getFilteredLogs();if(t.length===0){e.innerHTML='<div class="log-empty">No log output yet. Terminal will update when Loki Mode is running.</div>';return}e.innerHTML=t.map(i=>{let a=st[i.level]||st.info;return`
|
|
3875
3762
|
<div class="log-line">
|
|
3876
3763
|
<span class="timestamp">${this._escapeHtml(i.timestamp)}</span>
|
|
3877
3764
|
<span class="level" style="color: ${a.color}">[${this._escapeHtml(a.label)}]</span>
|
|
@@ -4070,7 +3957,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4070
3957
|
${this._logs.length} lines (${this._getFilteredLogs().length} shown)
|
|
4071
3958
|
</div>
|
|
4072
3959
|
</div>
|
|
4073
|
-
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let e=this.shadowRoot.getElementById("filter-input"),t=this.shadowRoot.getElementById("level-select"),i=this.shadowRoot.getElementById("auto-scroll-btn"),a=this.shadowRoot.getElementById("clear-btn"),s=this.shadowRoot.getElementById("download-btn");e&&(e.value=this._filter,e.addEventListener("input",r=>this._setFilter(r.target.value))),t&&(t.value=this._levelFilter,t.addEventListener("change",r=>this._setLevelFilter(r.target.value))),i&&i.addEventListener("click",()=>this._toggleAutoScroll()),a&&a.addEventListener("click",()=>this._clearLogs()),s&&s.addEventListener("click",()=>this._downloadLogs())}addLog(e,t="info"){this._addLog({message:e,level:t,timestamp:new Date().toLocaleTimeString()})}clear(){this._clearLogs()}};customElements.get("loki-log-stream")||customElements.define("loki-log-stream",
|
|
3960
|
+
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let e=this.shadowRoot.getElementById("filter-input"),t=this.shadowRoot.getElementById("level-select"),i=this.shadowRoot.getElementById("auto-scroll-btn"),a=this.shadowRoot.getElementById("clear-btn"),s=this.shadowRoot.getElementById("download-btn");e&&(e.value=this._filter,e.addEventListener("input",r=>this._setFilter(r.target.value))),t&&(t.value=this._levelFilter,t.addEventListener("change",r=>this._setLevelFilter(r.target.value))),i&&i.addEventListener("click",()=>this._toggleAutoScroll()),a&&a.addEventListener("click",()=>this._clearLogs()),s&&s.addEventListener("click",()=>this._downloadLogs())}addLog(e,t="info"){this._addLog({message:e,level:t,timestamp:new Date().toLocaleTimeString()})}clear(){this._clearLogs()}};customElements.get("loki-log-stream")||customElements.define("loki-log-stream",Z);var Tt=[{id:"summary",label:"Summary",icon:"M4 6h16M4 12h16M4 18h16"},{id:"search",label:"Search",icon:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"},{id:"episodes",label:"Episodes",icon:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"},{id:"patterns",label:"Patterns",icon:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"},{id:"skills",label:"Skills",icon:"M13 10V3L4 14h7v7l9-11h-7z"}],ee=class extends g{static get observedAttributes(){return["api-url","theme","tab"]}constructor(){super(),this._activeTab="summary",this._loading=!1,this._error=null,this._api=null,this._summary=null,this._stats=null,this._episodes=[],this._patterns=[],this._skills=[],this._tokenEconomics=null,this._selectedItem=null,this._lastFocusedElement=null,this._searchQuery="",this._searchCollection="all",this._searchResults=[],this._searchLoading=!1,this._searchError=null}connectedCallback(){super.connectedCallback(),this._activeTab=this.getAttribute("tab")||"summary",this._setupApi(),this._loadData()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadData());break;case"theme":this._applyTheme();break;case"tab":this._setTab(i);break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let[e,t,i]=await Promise.allSettled([this._api.getMemorySummary(),this._api.getTokenEconomics(),this._api.getMemoryStats()]);this._summary=e.status==="fulfilled"?e.value:null,this._tokenEconomics=t.status==="fulfilled"?t.value:null,this._stats=i.status==="fulfilled"?i.value:null,await this._loadTabData()}catch(e){this._error=e.message||"Failed to load memory data"}this._loading=!1,this.render()}async _loadTabData(){switch(this._activeTab){case"episodes":this._episodes=await this._api.listEpisodes({limit:50}).catch(()=>[]);break;case"patterns":this._patterns=await this._api.listPatterns().catch(()=>[]);break;case"skills":this._skills=await this._api.listSkills().catch(()=>[]);break}}_setTab(e){this._activeTab!==e&&(this._activeTab=e,this._selectedItem=null,this._loadTabData().then(()=>this.render()))}async _selectEpisode(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getEpisode(e),this.dispatchEvent(new CustomEvent("episode-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load episode:",t)}}async _selectPattern(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getPattern(e),this.dispatchEvent(new CustomEvent("pattern-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load pattern:",t)}}async _selectSkill(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getSkill(e),this.dispatchEvent(new CustomEvent("skill-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load skill:",t)}}_focusDetailPanel(){requestAnimationFrame(()=>{let e=this.shadowRoot.getElementById("close-detail");e&&e.focus()})}_closeDetail(){this._selectedItem=null,this.render(),this._lastFocusedElement&&requestAnimationFrame(()=>{this._lastFocusedElement.focus(),this._lastFocusedElement=null})}async _triggerConsolidation(){try{let e=await this._api.consolidateMemory(24);alert(`Consolidation complete:
|
|
4074
3961
|
- Patterns created: ${e.patternsCreated}
|
|
4075
3962
|
- Patterns merged: ${e.patternsMerged}
|
|
4076
3963
|
- Episodes processed: ${e.episodesProcessed}`),this._loadData()}catch(e){alert("Consolidation failed: "+e.message)}}async _executeSearch(){let e=this._searchQuery.trim();if(e){this._searchLoading=!0,this._searchError=null,this.render();try{let t=await this._api.searchMemory(e,this._searchCollection,20);this._searchResults=t.results||[]}catch(t){this._searchError=t.message||"Search failed",this._searchResults=[]}this._searchLoading=!1,this.render(),requestAnimationFrame(()=>{let t=this.shadowRoot.getElementById("memory-search-input");t&&t.focus()})}}_renderSearch(){let e=["all","episodes","patterns","skills"];return`
|
|
@@ -4941,7 +4828,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4941
4828
|
<span class="browser-title">Memory System</span>
|
|
4942
4829
|
</div>
|
|
4943
4830
|
<div class="tabs" role="tablist" aria-label="Memory browser sections">
|
|
4944
|
-
${
|
|
4831
|
+
${Tt.map((i,a)=>`
|
|
4945
4832
|
<button class="tab ${this._activeTab===i.id?"active":""}"
|
|
4946
4833
|
data-tab="${i.id}"
|
|
4947
4834
|
role="tab"
|
|
@@ -4958,12 +4845,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4958
4845
|
${t}
|
|
4959
4846
|
</div>
|
|
4960
4847
|
</div>
|
|
4961
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.querySelectorAll(".tab");e.forEach((n,l)=>{n.addEventListener("click",()=>this._setTab(n.dataset.tab)),n.addEventListener("keydown",c=>{if(c.key==="ArrowRight"||c.key==="ArrowLeft"){c.preventDefault();let p=Array.from(e),h=c.key==="ArrowRight"?(l+1)%p.length:(l-1+p.length)%p.length;p[h].focus(),this._setTab(p[h].dataset.tab)}})}),this.shadowRoot.querySelectorAll(".item-card").forEach(n=>{n.addEventListener("click",()=>this._handleItemClick(n)),n.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._handleItemClick(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateItemCards(n,l.key==="ArrowDown"?"next":"prev"))})});let t=this.shadowRoot.getElementById("close-detail");t&&t.addEventListener("click",()=>this._closeDetail());let i=this.shadowRoot.getElementById("consolidate-btn");i&&i.addEventListener("click",()=>this._triggerConsolidation());let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("memory-search-input"),r=this.shadowRoot.getElementById("search-btn"),o=this.shadowRoot.getElementById("memory-search-collection");s&&(s.addEventListener("keydown",n=>{n.key==="Enter"&&(n.preventDefault(),this._searchQuery=s.value,this._executeSearch())}),s.addEventListener("input",n=>{this._searchQuery=n.target.value})),r&&r.addEventListener("click",()=>{let n=this.shadowRoot.getElementById("memory-search-input");n&&(this._searchQuery=n.value),this._executeSearch()}),o&&o.addEventListener("change",n=>{this._searchCollection=n.target.value})}_handleItemClick(e){let t=e.dataset.id;switch(e.dataset.type){case"episode":this._selectEpisode(t);break;case"pattern":this._selectPattern(t);break;case"skill":this._selectSkill(t);break}}_navigateItemCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".item-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-memory-browser")||customElements.define("loki-memory-browser",
|
|
4848
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.querySelectorAll(".tab");e.forEach((n,l)=>{n.addEventListener("click",()=>this._setTab(n.dataset.tab)),n.addEventListener("keydown",c=>{if(c.key==="ArrowRight"||c.key==="ArrowLeft"){c.preventDefault();let p=Array.from(e),h=c.key==="ArrowRight"?(l+1)%p.length:(l-1+p.length)%p.length;p[h].focus(),this._setTab(p[h].dataset.tab)}})}),this.shadowRoot.querySelectorAll(".item-card").forEach(n=>{n.addEventListener("click",()=>this._handleItemClick(n)),n.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._handleItemClick(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateItemCards(n,l.key==="ArrowDown"?"next":"prev"))})});let t=this.shadowRoot.getElementById("close-detail");t&&t.addEventListener("click",()=>this._closeDetail());let i=this.shadowRoot.getElementById("consolidate-btn");i&&i.addEventListener("click",()=>this._triggerConsolidation());let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("memory-search-input"),r=this.shadowRoot.getElementById("search-btn"),o=this.shadowRoot.getElementById("memory-search-collection");s&&(s.addEventListener("keydown",n=>{n.key==="Enter"&&(n.preventDefault(),this._searchQuery=s.value,this._executeSearch())}),s.addEventListener("input",n=>{this._searchQuery=n.target.value})),r&&r.addEventListener("click",()=>{let n=this.shadowRoot.getElementById("memory-search-input");n&&(this._searchQuery=n.value),this._executeSearch()}),o&&o.addEventListener("change",n=>{this._searchCollection=n.target.value})}_handleItemClick(e){let t=e.dataset.id;switch(e.dataset.type){case"episode":this._selectEpisode(t);break;case"pattern":this._selectPattern(t);break;case"skill":this._selectSkill(t);break}}_navigateItemCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".item-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-memory-browser")||customElements.define("loki-memory-browser",ee);var Lt=[{id:"1h",label:"1 Hour",hours:1},{id:"24h",label:"24 Hours",hours:24},{id:"7d",label:"7 Days",hours:168},{id:"30d",label:"30 Days",hours:720}],Dt=[{id:"all",label:"All Signals"},{id:"user_preference",label:"User Preferences"},{id:"error_pattern",label:"Error Patterns"},{id:"success_pattern",label:"Success Patterns"},{id:"tool_efficiency",label:"Tool Efficiency"},{id:"context_relevance",label:"Context Relevance"}],zt=[{id:"all",label:"All Sources"},{id:"cli",label:"CLI"},{id:"api",label:"API"},{id:"vscode",label:"VS Code"},{id:"mcp",label:"MCP"},{id:"dashboard",label:"Dashboard"}],te=class extends g{static get observedAttributes(){return["api-url","theme","time-range","signal-type","source"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._timeRange="7d",this._signalType="all",this._source="all",this._metrics=null,this._trends=null,this._signals=[],this._selectedMetric=null}connectedCallback(){super.connectedCallback(),this._timeRange=this.getAttribute("time-range")||"7d",this._signalType=this.getAttribute("signal-type")||"all",this._source=this.getAttribute("source")||"all",this._setupApi(),this._loadData()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadData());break;case"theme":this._applyTheme();break;case"time-range":this._timeRange=i,this._loadData();break;case"signal-type":this._signalType=i,this._loadData();break;case"source":this._source=i,this._loadData();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let e={timeRange:this._timeRange,signalType:this._signalType!=="all"?this._signalType:void 0,source:this._source!=="all"?this._source:void 0},[t,i,a]=await Promise.all([this._api.getLearningMetrics(e).catch(()=>null),this._api.getLearningTrends(e).catch(()=>null),this._api.getLearningSignals({...e,limit:50}).catch(()=>[])]);this._metrics=t,this._trends=i,this._signals=a||[]}catch(e){this._error=e.message||"Failed to load learning data"}this._loading=!1,this.render()}_setFilter(e,t){switch(e){case"timeRange":this._timeRange=t,this.setAttribute("time-range",t);break;case"signalType":this._signalType=t,this.setAttribute("signal-type",t);break;case"source":this._source=t,this.setAttribute("source",t);break}this.dispatchEvent(new CustomEvent("filter-change",{detail:{timeRange:this._timeRange,signalType:this._signalType,source:this._source}})),this._loadData()}_selectMetric(e,t){this._selectedMetric={type:e,item:t},this.dispatchEvent(new CustomEvent("metric-select",{detail:{type:e,item:t}})),this.render()}_closeDetail(){this._selectedMetric=null,this.render()}_formatNumber(e){return e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":e?.toString()||"0"}_formatPercent(e){return(e*100).toFixed(1)+"%"}_formatDuration(e){return e<60?e.toFixed(0)+"s":e<3600?(e/60).toFixed(1)+"m":(e/3600).toFixed(1)+"h"}_escapeHtml(e){if(!e)return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}_renderFilters(){return`
|
|
4962
4849
|
<div class="filters">
|
|
4963
4850
|
<div class="filter-group">
|
|
4964
4851
|
<label>Time Range</label>
|
|
4965
4852
|
<select id="time-range-select" class="filter-select">
|
|
4966
|
-
${
|
|
4853
|
+
${Lt.map(e=>`
|
|
4967
4854
|
<option value="${e.id}" ${this._timeRange===e.id?"selected":""}>${e.label}</option>
|
|
4968
4855
|
`).join("")}
|
|
4969
4856
|
</select>
|
|
@@ -4971,7 +4858,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4971
4858
|
<div class="filter-group">
|
|
4972
4859
|
<label>Signal Type</label>
|
|
4973
4860
|
<select id="signal-type-select" class="filter-select">
|
|
4974
|
-
${
|
|
4861
|
+
${Dt.map(e=>`
|
|
4975
4862
|
<option value="${e.id}" ${this._signalType===e.id?"selected":""}>${e.label}</option>
|
|
4976
4863
|
`).join("")}
|
|
4977
4864
|
</select>
|
|
@@ -4979,7 +4866,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4979
4866
|
<div class="filter-group">
|
|
4980
4867
|
<label>Source</label>
|
|
4981
4868
|
<select id="source-select" class="filter-select">
|
|
4982
|
-
${
|
|
4869
|
+
${zt.map(e=>`
|
|
4983
4870
|
<option value="${e.id}" ${this._source===e.id?"selected":""}>${e.label}</option>
|
|
4984
4871
|
`).join("")}
|
|
4985
4872
|
</select>
|
|
@@ -5970,7 +5857,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
5970
5857
|
${t}
|
|
5971
5858
|
</div>
|
|
5972
5859
|
</div>
|
|
5973
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.getElementById("time-range-select");e&&e.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let t=this.shadowRoot.getElementById("signal-type-select");t&&t.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let i=this.shadowRoot.getElementById("source-select");i&&i.addEventListener("change",r=>this._setFilter("source",r.target.value));let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("close-detail");s&&s.addEventListener("click",()=>this._closeDetail()),this.shadowRoot.querySelectorAll(".list-item").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.type,n=r.dataset.id,l=this._findItemData(o,n);l&&this._selectMetric(o,l)}),r.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r.click())})})}_findItemData(e,t){if(!this._metrics?.aggregation)return null;switch(e){case"preference":return this._metrics.aggregation.preferences?.find(i=>i.preference_key===t);case"error_pattern":return this._metrics.aggregation.error_patterns?.find(i=>i.error_type===t);case"success_pattern":return this._metrics.aggregation.success_patterns?.find(i=>i.pattern_name===t);case"tool_efficiency":return this._metrics.aggregation.tool_efficiencies?.find(i=>i.tool_name===t);default:return null}}};customElements.get("loki-learning-dashboard")||customElements.define("loki-learning-dashboard",
|
|
5860
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.getElementById("time-range-select");e&&e.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let t=this.shadowRoot.getElementById("signal-type-select");t&&t.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let i=this.shadowRoot.getElementById("source-select");i&&i.addEventListener("change",r=>this._setFilter("source",r.target.value));let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("close-detail");s&&s.addEventListener("click",()=>this._closeDetail()),this.shadowRoot.querySelectorAll(".list-item").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.type,n=r.dataset.id,l=this._findItemData(o,n);l&&this._selectMetric(o,l)}),r.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r.click())})})}_findItemData(e,t){if(!this._metrics?.aggregation)return null;switch(e){case"preference":return this._metrics.aggregation.preferences?.find(i=>i.preference_key===t);case"error_pattern":return this._metrics.aggregation.error_patterns?.find(i=>i.error_type===t);case"success_pattern":return this._metrics.aggregation.success_patterns?.find(i=>i.pattern_name===t);case"tool_efficiency":return this._metrics.aggregation.tool_efficiencies?.find(i=>i.tool_name===t);default:return null}}};customElements.get("loki-learning-dashboard")||customElements.define("loki-learning-dashboard",te);var Rt=[{id:"overview",label:"Overview"},{id:"decisions",label:"Decision Log"},{id:"convergence",label:"Convergence"},{id:"agents",label:"Agents"}],ie=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._activeTab="overview",this._pollInterval=null,this._councilState=null,this._verdicts=[],this._convergence=[],this._agents=[],this._selectedAgent=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null),this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null)}async _loadData(){try{let[t,i,a,s]=await Promise.allSettled([this._api._get("/api/council/state"),this._api._get("/api/council/verdicts"),this._api._get("/api/council/convergence"),this._api._get("/api/agents")]);t.status==="fulfilled"&&(this._councilState=t.value),i.status==="fulfilled"&&(this._verdicts=i.value.verdicts||[]),a.status==="fulfilled"&&(this._convergence=a.value.dataPoints||[]),s.status==="fulfilled"&&(this._agents=Array.isArray(s.value)?s.value:[]),this._error=null}catch(t){this._error=t.message}let e=JSON.stringify({s:this._councilState,v:this._verdicts,c:this._convergence,a:this._agents,e:this._error});e!==this._lastDataHash&&(this._lastDataHash=e,this.render())}async _forceReview(){try{await this._api._post("/api/council/force-review"),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"force-review"},bubbles:!0}))}catch(e){this._error=`Failed to force review: ${e.message}`,this.render()}}async _killAgent(e){if(confirm(`Kill agent ${e}?`))try{await this._api._post(`/api/agents/${e}/kill`),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"kill-agent",agentId:e},bubbles:!0})),await this._loadData()}catch(t){this._error=`Failed to kill agent: ${t.message}`,this.render()}}async _pauseAgent(e){try{await this._api._post(`/api/agents/${e}/pause`),await this._loadData()}catch(t){this._error=`Failed to pause agent: ${t.message}`,this.render()}}async _resumeAgent(e){try{await this._api._post(`/api/agents/${e}/resume`),await this._loadData()}catch(t){this._error=`Failed to resume agent: ${t.message}`,this.render()}}_setTab(e){this._activeTab=e,this.render()}_selectAgent(e){this._selectedAgent=this._selectedAgent?.id===e.id?null:e,this.render()}render(){let e=this.shadowRoot;e&&(this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null),e.innerHTML=`
|
|
5974
5861
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
5975
5862
|
<div class="council-dashboard">
|
|
5976
5863
|
<div class="council-header">
|
|
@@ -5984,7 +5871,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
5984
5871
|
</div>
|
|
5985
5872
|
|
|
5986
5873
|
<div class="tabs">
|
|
5987
|
-
${
|
|
5874
|
+
${Rt.map(t=>`
|
|
5988
5875
|
<button
|
|
5989
5876
|
class="tab ${this._activeTab===t.id?"active":""}"
|
|
5990
5877
|
data-tab="${t.id}"
|
|
@@ -6557,7 +6444,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
6557
6444
|
color: var(--loki-error);
|
|
6558
6445
|
font-size: 12px;
|
|
6559
6446
|
}
|
|
6560
|
-
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",
|
|
6447
|
+
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",ie);var rt={critical:0,major:1,minor:2},Ht={critical:"var(--loki-status-error, #ef4444)",major:"var(--loki-status-warning, #f59e0b)",minor:"var(--loki-text-muted, #71717a)"},ae=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._checklist=null,this._waivers=[],this._expandedCategories=new Set,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let[e,t]=await Promise.all([this._api.getChecklist(),this._api.getChecklistWaivers().catch(()=>null)]),i=JSON.stringify(t),a=JSON.stringify(e)+i;if(a===this._lastDataHash)return;this._lastDataHash=a,this._checklist=e,this._waivers=t&&t.waivers?t.waivers.filter(s=>s.active):[],this._error=null,this.render()}catch(e){this._error=`Failed to load checklist: ${e.message}`,this.render()}}_isItemWaived(e){return this._waivers.some(t=>t.item_id===e)}_getWaiverForItem(e){return this._waivers.find(t=>t.item_id===e)||null}async _waiveItem(e){let t=window.prompt("Enter reason for waiving this item:");if(t)try{await this._api.addChecklistWaiver(e,t),this._lastDataHash=null,await this._loadData()}catch(i){this._error=`Failed to add waiver: ${i.message}`,this.render()}}async _unwaiveItem(e){try{await this._api.removeChecklistWaiver(e),this._lastDataHash=null,await this._loadData()}catch(t){this._error=`Failed to remove waiver: ${t.message}`,this.render()}}_toggleCategory(e){this._expandedCategories.has(e)?this._expandedCategories.delete(e):this._expandedCategories.add(e),this.render()}_getStyles(){return`
|
|
6561
6448
|
.checklist-viewer {
|
|
6562
6449
|
padding: 16px;
|
|
6563
6450
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -6846,7 +6733,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
6846
6733
|
</div>
|
|
6847
6734
|
${i?`<div class="category-body">${this._renderItems(a)}</div>`:""}
|
|
6848
6735
|
</div>
|
|
6849
|
-
`}).join(""):this._renderEmpty()}_renderItems(e){return e?.length?[...e].sort((i,a)=>(
|
|
6736
|
+
`}).join(""):this._renderEmpty()}_renderItems(e){return e?.length?[...e].sort((i,a)=>(rt[i.priority]??2)-(rt[a.priority]??2)).map(i=>{let a=i.status==="verified"?"status-verified":i.status==="failing"?"status-failing":"status-pending",s=["critical","major","minor"].includes(i.priority)?i.priority:"minor",r=Ht[s],o=i.verification||[],n=this._getWaiverForItem(i.id),l=!!n,c=i.status==="failing"&&(s==="critical"||s==="major"),p=l?`<span class="item-waived-badge" title="${this._escapeHtml(n.reason||"No reason provided")}">WAIVED</span>`:"",h="";return c&&(l?h=`<button class="waiver-btn waiver-btn-unwaive" data-unwaive-id="${this._escapeHtml(i.id)}">Unwaive</button>`:h=`<button class="waiver-btn" data-waive-id="${this._escapeHtml(i.id)}">Waive</button>`),`
|
|
6850
6737
|
<div class="item">
|
|
6851
6738
|
<div class="item-status ${a}"></div>
|
|
6852
6739
|
<div class="item-title">${this._escapeHtml(i.title||i.id||"?")}</div>
|
|
@@ -6854,7 +6741,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
6854
6741
|
${p}
|
|
6855
6742
|
${h}
|
|
6856
6743
|
<div class="verification-dots">
|
|
6857
|
-
${o.map(
|
|
6744
|
+
${o.map(v=>`<div class="v-dot ${v.passed===!0?"v-dot-pass":v.passed===!1?"v-dot-fail":"v-dot-pending"}" title="${this._escapeHtml(v.type||"")}"></div>`).join("")}
|
|
6858
6745
|
</div>
|
|
6859
6746
|
</div>
|
|
6860
6747
|
`}).join(""):'<div class="item" style="color:var(--loki-text-muted)">No items</div>'}_renderEmpty(){return`
|
|
@@ -6862,7 +6749,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
6862
6749
|
<p><strong>No checklist data yet.</strong></p>
|
|
6863
6750
|
<p class="hint">The spec checklist is generated during the first iteration. Start a session with <code>loki start ./spec.md</code> (PRD files also accepted) -- groups and items will appear here as the session progresses and can be expanded for details.</p>
|
|
6864
6751
|
</div>
|
|
6865
|
-
`}_attachEventListeners(){let e=this.shadowRoot;e&&(e.querySelectorAll(".category-header[data-category]").forEach(t=>{t.addEventListener("click",()=>this._toggleCategory(t.dataset.category))}),e.querySelectorAll("button[data-waive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(t.dataset.waiveId)})}),e.querySelectorAll("button[data-unwaive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(t.dataset.unwaiveId)})}))}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",
|
|
6752
|
+
`}_attachEventListeners(){let e=this.shadowRoot;e&&(e.querySelectorAll(".category-header[data-category]").forEach(t=>{t.addEventListener("click",()=>this._toggleCategory(t.dataset.category))}),e.querySelectorAll("button[data-waive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(t.dataset.waiveId)})}),e.querySelectorAll("button[data-unwaive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(t.dataset.unwaiveId)})}))}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",ae);var ot={not_initialized:{color:"var(--loki-text-muted, #71717a)",label:"Not Started",pulse:!1},starting:{color:"var(--loki-yellow, #ca8a04)",label:"Starting...",pulse:!0},running:{color:"var(--loki-green, #16a34a)",label:"Running",pulse:!0},stale:{color:"var(--loki-yellow, #ca8a04)",label:"Stale",pulse:!1},completed:{color:"var(--loki-text-muted, #a1a1aa)",label:"Completed",pulse:!1},failed:{color:"var(--loki-red, #dc2626)",label:"Failed",pulse:!1},crashed:{color:"var(--loki-red, #dc2626)",label:"Crashed",pulse:!1},stopped:{color:"var(--loki-text-muted, #a1a1aa)",label:"Stopped",pulse:!1},unknown:{color:"var(--loki-text-muted, #71717a)",label:"Unknown",pulse:!1}},se=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._status=null,this._logs=[],this._lastDataHash=null,this._lastLogsHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let[e,t]=await Promise.all([this._api.getAppRunnerStatus(),this._api.getAppRunnerLogs()]),i=JSON.stringify({status:e?.status,port:e?.port,restarts:e?.restart_count,url:e?.url,services:Array.isArray(e?.services)?e.services.map(r=>`${r?.url||""}|${r?.name||""}`).join(","):null}),a=JSON.stringify(t?.lines?.slice(-5)||[]),s=a!==this._lastLogsHash;if(i===this._lastDataHash&&!s)return;this._lastDataHash=i,this._lastLogsHash=a,this._status=e,this._logs=t?.lines||[],this._error=null,this.render(),this._scrollLogsToBottom()}catch(e){this._error||(this._error=`Failed to load app status: ${e.message}`,this.render())}}_scrollLogsToBottom(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(".log-area");t&&(t.scrollTop=t.scrollHeight)}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(e){this._error=`Restart failed: ${e.message}`,this.render()}}async _handleStop(){try{await this._api.stopApp(),this._loadData()}catch(e){this._error=`Stop failed: ${e.message}`,this.render()}}_formatUptime(e){if(!e)return"--";let t=new Date(e),a=Math.floor((new Date-t)/1e3);if(a<60)return`${a}s`;if(a<3600)return`${Math.floor(a/60)}m ${a%60}s`;let s=Math.floor(a/3600),r=Math.floor(a%3600/60);return`${s}h ${r}m`}_isValidUrl(e){if(!e)return!1;try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}_extraServices(e){if(!e||!Array.isArray(e.services))return[];let t=e.url||"",i=[],a=new Set;for(let s of e.services){if(!s||typeof s.url!="string"||!s.url||s.url===t||a.has(s.url))continue;a.add(s.url);let r=typeof s.name=="string"?s.name.trim():"",o=typeof s.role=="string"?s.role.trim():"",n=s.port!=null?String(s.port):"",l=r||o||(n?`Port ${n}`:"Service");i.push({url:s.url,label:l,urlValid:this._isValidUrl(s.url)})}return i}_getStyles(){return`
|
|
6866
6753
|
.app-status {
|
|
6867
6754
|
padding: 16px;
|
|
6868
6755
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -7038,7 +6925,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7038
6925
|
${i?"":this._renderEmpty()}
|
|
7039
6926
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
7040
6927
|
</div>
|
|
7041
|
-
`,this._attachEventListeners()}_renderStatusBadge(e){let t=e?.status||"not_initialized",i=
|
|
6928
|
+
`,this._attachEventListeners()}_renderStatusBadge(e){let t=e?.status||"not_initialized",i=ot[t]||ot.not_initialized;return`
|
|
7042
6929
|
<span class="status-badge" style="background: color-mix(in srgb, ${i.color} 15%, transparent); color: ${i.color}">
|
|
7043
6930
|
<span class="status-dot ${i.pulse?"pulse":""}" style="background: ${i.color}"></span>
|
|
7044
6931
|
${this._escapeHtml(i.label)}
|
|
@@ -7094,7 +6981,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7094
6981
|
<p>App not running yet</p>
|
|
7095
6982
|
<p class="hint">Your app will start automatically after the first successful build step.</p>
|
|
7096
6983
|
</div>
|
|
7097
|
-
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector('[data-action="restart"]'),i=e.querySelector('[data-action="stop"]');t&&t.addEventListener("click",()=>this._handleRestart()),i&&i.addEventListener("click",()=>this._handleStop())}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-app-status",
|
|
6984
|
+
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector('[data-action="restart"]'),i=e.querySelector('[data-action="stop"]');t&&t.addEventListener("click",()=>this._handleRestart()),i&&i.addEventListener("click",()=>this._handleStop())}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-app-status",se);var nt={not_initialized:{color:"var(--loki-text-muted, #71717a)",label:"No app yet",pulse:!1},starting:{color:"var(--loki-yellow, #ca8a04)",label:"Starting",pulse:!0},running:{color:"var(--loki-green, #16a34a)",label:"Running",pulse:!0},stale:{color:"var(--loki-yellow, #ca8a04)",label:"Stale",pulse:!1},completed:{color:"var(--loki-text-muted, #a1a1aa)",label:"Completed",pulse:!1},failed:{color:"var(--loki-red, #dc2626)",label:"Could not start",pulse:!1},crashed:{color:"var(--loki-red, #dc2626)",label:"Crashed",pulse:!1},stopped:{color:"var(--loki-text-muted, #a1a1aa)",label:"Stopped",pulse:!1},error:{color:"var(--loki-text-muted, #71717a)",label:"Status unavailable",pulse:!1},unknown:{color:"var(--loki-text-muted, #71717a)",label:"Unknown",pulse:!1}},re=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._pollInterval=null,this._status=null,this._errors=null,this._error=null,this._lastDataHash=null,this._detailsOpen=!1,this._iframeFailed=!1,this._iframeLoadTimer=null,this._IFRAME_LOAD_TIMEOUT_MS=6e3,this._activeServiceKey=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this.render(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._clearIframeLoadTimer()}_clearIframeLoadTimer(){this._iframeLoadTimer&&(clearTimeout(this._iframeLoadTimer),this._iframeLoadTimer=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api.getAppRunnerStatus(),t=e?.status||"not_initialized",i=null;if(t==="crashed"||t==="failed")try{i=await this._api.getAppRunnerErrors(50)}catch{i=null}let a=JSON.stringify({status:t,port:e?.port,url:e?.url,crash:e?.crash_count,errLen:i?.lines?.length||0,extMgd:e?.externally_managed===!0,source:e?.source||null,healthOk:e?.last_health?.ok===!0?"ok":e?.last_health?.ok===!1?"down":"unknown",services:Array.isArray(e?.services)?e.services.map(r=>`${r?.url||""}|${r?.role||""}|${r?.name||""}`).join(","):null}),s=this._error!==null;if(a===this._lastDataHash&&!s)return;this._iframeFailed=!1,this._lastDataHash=a,this._status=e,this._errors=i,this._error=null,this.render()}catch(e){this._error||(this._error=`Could not read app status: ${e.message}`,this.render())}}_isValidUrl(e){if(!e)return!1;try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}_getServices(){let e=this._status;if(!e)return[];let t=Array.isArray(e.services)&&e.services.length>0?e.services:[{url:e.url,role:"",name:e.primary_service||"",port:e.port}],i=new Set,a=[];for(let s of t){if(!s||!this._isValidUrl(s.url))continue;let r=typeof s.name=="string"?s.name.trim():"",o=s.port!=null?String(s.port):"",n=this._inferServiceRole(s.role,r),l=s.url||r||o;if(i.has(l))continue;i.add(l);let c=r;c||(c=n==="api"?"API":n==="ui"?"UI":""),c||(c=o?`Port ${o}`:"Service"),a.push({key:l,url:s.url,role:n,name:r,port:o,label:c})}return a}_inferServiceRole(e,t){let i=typeof e=="string"?e.trim().toLowerCase():"";if(i==="ui"||i==="web"||i==="frontend")return"ui";if(i==="api"||i==="backend"||i==="server")return"api";let a=(t||"").toLowerCase();return/\b(api|backend|server|graphql|grpc)\b/.test(a)||a.includes("api")?"api":""}_activeService(e){if(!e||e.length===0)return null;if(this._activeServiceKey){let t=e.find(i=>i.key===this._activeServiceKey);if(t)return t}return e[0]}_handleSelectService(e){this._activeServiceKey!==e&&(this._activeServiceKey=e,this._iframeFailed=!1,this.render())}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(e){this._error=`Restart failed: ${e.message}`,this.render()}}_currentTargetUrl(){let e=this._activeService(this._getServices());if(e&&this._isValidUrl(e.url))return e.url;let t=this._status;return t&&this._isValidUrl(t.url)?t.url:""}_handleRefresh(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector("iframe.preview-frame"),i=this._currentTargetUrl();if(t&&i){this._iframeFailed=!1,this._clearIframeLoadTimer();let a=(i.includes("?")?"&":"?")+"_t="+Date.now();t.src=i+a,this._armIframeLoadDetection()}}_handleRetryFrame(){this._iframeFailed=!1,this._lastDataHash=null,this.render(),this._loadData()}_handleOpenExternal(){let e=this._currentTargetUrl();e&&window.open(e,"_blank","noopener")}_toggleDetails(){this._detailsOpen=!this._detailsOpen,this.render()}_getStyles(){return`
|
|
7098
6985
|
.preview { padding: 16px; font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif); color: var(--loki-text-primary, #201515); display: flex; flex-direction: column; width: 100%; box-sizing: border-box; }
|
|
7099
6986
|
.header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; gap: 12px; flex-wrap: wrap; }
|
|
7100
6987
|
.header-left { display: flex; align-items: center; gap: 10px; }
|
|
@@ -7144,7 +7031,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7144
7031
|
.details-toggle:hover { text-decoration: underline; }
|
|
7145
7032
|
.details-body { margin-top: 8px; background: var(--loki-bg-code, #1e1e1e); color: #d4d4d4; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; padding: 10px; border-radius: 6px; max-height: 200px; overflow: auto; white-space: pre-wrap; }
|
|
7146
7033
|
.error-banner { margin-top: 12px; padding: 10px 12px; border-radius: 6px; background: color-mix(in srgb, var(--loki-red, #dc2626) 10%, transparent); color: var(--loki-red, #dc2626); font-size: 13px; }
|
|
7147
|
-
`}_effectiveView(e,t){let i=this._status,a=i?.last_health,s=a&&typeof a.ok=="boolean"?a.ok:null;if(e==="running"&&t&&(i?.externally_managed===!0||i?.source==="discovered"))return{view:"running",healthOk:s};if(e==="running"&&t){if(s===!1)return{view:"starting",healthOk:s};if(s===!0)return{view:"running",healthOk:s};let r=i?.started_at?Date.parse(i.started_at):NaN;return{view:Number.isFinite(r)&&Date.now()-r<15e3?"running":"starting",healthOk:s}}return{view:e,healthOk:s}}render(){let e=this.shadowRoot;if(!e)return;this._clearIframeLoadTimer();let t=this._status,i=t?.status||"not_initialized",a=this._getServices(),s=this._activeService(a),r=a.length>1,o=s?.url||t?.url,n=this._isValidUrl(o),{view:l,healthOk:c}=this._effectiveView(i,n),p=t?.externally_managed===!0||t?.source==="discovered",h=
|
|
7034
|
+
`}_effectiveView(e,t){let i=this._status,a=i?.last_health,s=a&&typeof a.ok=="boolean"?a.ok:null;if(e==="running"&&t&&(i?.externally_managed===!0||i?.source==="discovered"))return{view:"running",healthOk:s};if(e==="running"&&t){if(s===!1)return{view:"starting",healthOk:s};if(s===!0)return{view:"running",healthOk:s};let r=i?.started_at?Date.parse(i.started_at):NaN;return{view:Number.isFinite(r)&&Date.now()-r<15e3?"running":"starting",healthOk:s}}return{view:e,healthOk:s}}render(){let e=this.shadowRoot;if(!e)return;this._clearIframeLoadTimer();let t=this._status,i=t?.status||"not_initialized",a=this._getServices(),s=this._activeService(a),r=a.length>1,o=s?.url||t?.url,n=this._isValidUrl(o),{view:l,healthOk:c}=this._effectiveView(i,n),p=t?.externally_managed===!0||t?.source==="discovered",h=nt[l]||nt.not_initialized,v=i==="running"&&c===!1?"Starting / not responding yet":h.label;e.innerHTML=`
|
|
7148
7035
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
7149
7036
|
<div class="preview">
|
|
7150
7037
|
<div class="header">
|
|
@@ -7152,7 +7039,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7152
7039
|
<h2 class="title">Live App</h2>
|
|
7153
7040
|
<span class="status-badge" style="background: color-mix(in srgb, ${h.color} 15%, transparent); color: ${h.color}">
|
|
7154
7041
|
<span class="status-dot ${h.pulse?"pulse":""}" style="background: ${h.color}"></span>
|
|
7155
|
-
${this._escapeHtml(
|
|
7042
|
+
${this._escapeHtml(v)}
|
|
7156
7043
|
</span>
|
|
7157
7044
|
</div>
|
|
7158
7045
|
${this._renderToolbar(l,n,p)}
|
|
@@ -7265,7 +7152,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7265
7152
|
</button>
|
|
7266
7153
|
${this._detailsOpen?`<div class="details-body">${s}</div>`:""}
|
|
7267
7154
|
</div>
|
|
7268
|
-
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=(i,a)=>{let s=e.querySelector(i);s&&s.addEventListener("click",a)};e.querySelectorAll('[data-action="restart"]').forEach(i=>i.addEventListener("click",()=>this._handleRestart())),e.querySelectorAll('[data-action="open-external"]').forEach(i=>i.addEventListener("click",()=>this._handleOpenExternal())),e.querySelectorAll('[data-action="retry-frame"]').forEach(i=>i.addEventListener("click",()=>this._handleRetryFrame())),t('[data-action="refresh"]',()=>this._handleRefresh()),t('[data-action="toggle-details"]',()=>this._toggleDetails()),e.querySelectorAll('[data-action="select-service"]').forEach(i=>i.addEventListener("click",()=>this._handleSelectService(i.getAttribute("data-service-key"))))}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}};customElements.define("loki-app-preview",
|
|
7155
|
+
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=(i,a)=>{let s=e.querySelector(i);s&&s.addEventListener("click",a)};e.querySelectorAll('[data-action="restart"]').forEach(i=>i.addEventListener("click",()=>this._handleRestart())),e.querySelectorAll('[data-action="open-external"]').forEach(i=>i.addEventListener("click",()=>this._handleOpenExternal())),e.querySelectorAll('[data-action="retry-frame"]').forEach(i=>i.addEventListener("click",()=>this._handleRetryFrame())),t('[data-action="refresh"]',()=>this._handleRefresh()),t('[data-action="toggle-details"]',()=>this._toggleDetails()),e.querySelectorAll('[data-action="select-service"]').forEach(i=>i.addEventListener("click",()=>this._handleSelectService(i.getAttribute("data-service-key"))))}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}};customElements.define("loki-app-preview",re);var Mt={opus:{input:5,output:25,label:"Opus 4.6",provider:"claude"},sonnet:{input:3,output:15,label:"Sonnet 4.5",provider:"claude"},haiku:{input:1,output:5,label:"Haiku 4.5",provider:"claude"},"gpt-5.3-codex":{input:1.5,output:12,label:"GPT-5.3 Codex",provider:"codex"}},oe=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data={total_input_tokens:0,total_output_tokens:0,estimated_cost_usd:0,by_phase:{},by_model:{},budget_limit:null,budget_used:0,budget_remaining:null,connected:!1},this._api=null,this._pollInterval=null,this._modelPricing={...Mt}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadPricing(),this._loadCost(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadCost()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadPricing(){try{let e=await this._api.getPricing();if(e&&e.models){let t={};for(let[i,a]of Object.entries(e.models))t[i]={input:a.input,output:a.output,label:a.label||i,provider:a.provider||"unknown"};this._modelPricing=t,this._pricingSource=e.source||"api",this._pricingDate=e.updated||"",this._activeProvider=e.provider||"claude",this.render()}}catch{}}async _loadCost(){try{let e=await this._api.getCost();this._updateFromCost(e)}catch{this._data.connected=!1,this.render()}}_updateFromCost(e){e&&(this._data={...this._data,connected:!0,total_input_tokens:e.total_input_tokens||0,total_output_tokens:e.total_output_tokens||0,estimated_cost_usd:e.estimated_cost_usd||0,by_phase:e.by_phase||{},by_model:e.by_model||{},budget_limit:e.budget_limit,budget_used:e.budget_used||0,budget_remaining:e.budget_remaining},this.render())}_startPolling(){this._poll=b({loadFn:()=>this._loadCost(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatTokens(e){return!e||e===0?"0":e>=1e6?(e/1e6).toFixed(2)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}_formatUSD(e){return!e||e===0?"$0.00":e<.01?"<$0.01":"$"+e.toFixed(2)}_getBudgetPercent(){return!this._data.budget_limit||this._data.budget_limit<=0?0:Math.min(100,this._data.budget_used/this._data.budget_limit*100)}_getBudgetStatusClass(){let e=this._getBudgetPercent();return e>=90?"critical":e>=70?"warning":"ok"}_renderPhaseRows(){let e=this._data.by_phase;return!e||Object.keys(e).length===0?'<tr><td colspan="4" class="empty-cell">No phase data yet</td></tr>':Object.entries(e).map(([t,i])=>{let a=i.input_tokens||0,s=i.output_tokens||0,r=i.cost_usd||0;return`
|
|
7269
7156
|
<tr>
|
|
7270
7157
|
<td class="phase-name">${this._escapeHTML(t)}</td>
|
|
7271
7158
|
<td class="mono-cell">${this._formatTokens(a)}</td>
|
|
@@ -7667,7 +7554,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7667
7554
|
</div>
|
|
7668
7555
|
</div>
|
|
7669
7556
|
</div>
|
|
7670
|
-
`}};customElements.get("loki-cost-dashboard")||customElements.define("loki-cost-dashboard",
|
|
7557
|
+
`}};customElements.get("loki-cost-dashboard")||customElements.define("loki-cost-dashboard",oe);var ne=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._checkpoints=[],this._pollInterval=null,this._lastDataHash=null,this._showCreateForm=!1,this._creating=!1,this._rollingBack=!1,this._rollbackTarget=null,this._notice=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let[t]=await Promise.allSettled([this._api._get("/api/checkpoints?limit=50")]);t.status==="fulfilled"&&(this._checkpoints=Array.isArray(t.value)?t.value:t.value?.checkpoints||[]),this._error=null}catch(t){this._error=t.message}let e=JSON.stringify({c:this._checkpoints,e:this._error});e!==this._lastDataHash&&(this._lastDataHash=e,this.render())}async _createCheckpoint(){let e=this.shadowRoot.getElementById("checkpoint-message"),t=e?e.value.trim():"";if(t){this._creating=!0,this.render();try{await this._api._post("/api/checkpoints",{message:t}),this._showCreateForm=!1,this._creating=!1,this.dispatchEvent(new CustomEvent("checkpoint-action",{detail:{action:"create",message:t},bubbles:!0})),this._lastDataHash=null,await this._loadData()}catch(i){this._creating=!1,this._error=`Failed to create checkpoint: ${i.message}`,this.render()}}}async _rollbackCheckpoint(e){if(!this._rollingBack){this._rollingBack=!0,this._notice=null,this.render();try{let t=await this._api._post(`/api/checkpoints/${e}/rollback`);this._rollbackTarget=null;let i=t&&t.pre_rollback_snapshot;this._notice=i?`Rolled back to ${e}. Undo this with checkpoint ${i}`:`Rolled back to ${e}.`,this.dispatchEvent(new CustomEvent("checkpoint-action",{detail:{action:"rollback",checkpointId:e,preRollbackSnapshot:i||null},bubbles:!0})),this._lastDataHash=null,await this._loadData()}catch(t){this._rollbackTarget=null,this._error=`Failed to rollback: ${t.message}`}finally{this._rollingBack=!1,this.render()}}}_toggleCreateForm(){this._showCreateForm=!this._showCreateForm,this._rollbackTarget=null,this._notice=null,this.render()}_confirmRollback(e){this._rollbackTarget=e,this.render()}_cancelRollback(){this._rollbackTarget=null,this._notice=null,this.render()}_formatRelativeTime(e){if(!e)return"";try{let t=Date.now(),i=new Date(e).getTime(),a=Math.floor((t-i)/1e3);return a<60?`${a}s ago`:a<3600?`${Math.floor(a/60)}m ago`:a<86400?`${Math.floor(a/3600)}h ago`:`${Math.floor(a/86400)}d ago`}catch{return this._escapeHTML(e)}}render(){let e=this.shadowRoot;if(!e)return;let t=this._checkpoints.length;e.innerHTML=`
|
|
7671
7558
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
7672
7559
|
<div class="checkpoint-viewer">
|
|
7673
7560
|
<div class="checkpoint-header">
|
|
@@ -7986,7 +7873,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7986
7873
|
color: var(--loki-green, #22c55e);
|
|
7987
7874
|
font-size: 12px;
|
|
7988
7875
|
}
|
|
7989
|
-
`}};customElements.get("loki-checkpoint-viewer")||customElements.define("loki-checkpoint-viewer",
|
|
7876
|
+
`}};customElements.get("loki-checkpoint-viewer")||customElements.define("loki-checkpoint-viewer",ne);var le=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._connected=!1,this._activeTab="gauge",this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadContext(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadContext()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadContext(){try{let e=this.getAttribute("api-url")||window.location.origin,t=await fetch(e+"/api/context");t.ok&&(this._data=await t.json(),this._connected=!0)}catch{this._connected=!1}this.render()}_startPolling(){this._poll=b({loadFn:()=>this._loadContext(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_setTab(e){this._activeTab=e,this.render()}_formatTokens(e){return!e||e===0?"0":e>=1e6?(e/1e6).toFixed(2)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}_formatUSD(e){return!e||e===0?"$0.00":e<.01?"<$0.01":"$"+e.toFixed(2)}_escapeHTML(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGaugeColor(e){return e>80?"var(--loki-red)":e>=60?"var(--loki-yellow)":"var(--loki-green)"}_getGaugeColorClass(e){return e>80?"gauge-red":e>=60?"gauge-yellow":"gauge-green"}_renderGaugeTab(){let e=this._data?.current||{},t=this._data?.totals||{},i=e.context_window_pct||0,a=this._getGaugeColor(i),s=this._getGaugeColorClass(i),r=70,o=2*Math.PI*r,n=o-i/100*o;return`
|
|
7990
7877
|
<div class="gauge-tab">
|
|
7991
7878
|
<div class="gauge-container">
|
|
7992
7879
|
<svg class="gauge-svg" viewBox="0 0 180 180" aria-label="Context window usage: ${i.toFixed(1)}%">
|
|
@@ -8099,14 +7986,14 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
8099
7986
|
<div class="legend-item"><span class="legend-swatch swatch-cache-read"></span> Cache Read</div>
|
|
8100
7987
|
<div class="legend-item"><span class="legend-swatch swatch-cache-create"></span> Cache Creation</div>
|
|
8101
7988
|
</div>
|
|
8102
|
-
`,a="";for(let s of e){let r=s.input_tokens||0,o=s.output_tokens||0,n=s.cache_read_tokens||0,l=s.cache_creation_tokens||0,c=r+o+n+l,p=t>0?r/t*100:0,h=t>0?o/t*100:0,
|
|
7989
|
+
`,a="";for(let s of e){let r=s.input_tokens||0,o=s.output_tokens||0,n=s.cache_read_tokens||0,l=s.cache_creation_tokens||0,c=r+o+n+l,p=t>0?r/t*100:0,h=t>0?o/t*100:0,v=t>0?n/t*100:0,u=t>0?l/t*100:0;a+=`
|
|
8103
7990
|
<div class="breakdown-row">
|
|
8104
7991
|
<div class="breakdown-iter">#${s.iteration}</div>
|
|
8105
7992
|
<div class="breakdown-bar-container">
|
|
8106
7993
|
<div class="breakdown-bar bar-input" style="width: ${p.toFixed(1)}%"></div>
|
|
8107
7994
|
<div class="breakdown-bar bar-output" style="width: ${h.toFixed(1)}%"></div>
|
|
8108
|
-
<div class="breakdown-bar bar-cache-read" style="width: ${
|
|
8109
|
-
<div class="breakdown-bar bar-cache-create" style="width: ${
|
|
7995
|
+
<div class="breakdown-bar bar-cache-read" style="width: ${v.toFixed(1)}%"></div>
|
|
7996
|
+
<div class="breakdown-bar bar-cache-create" style="width: ${u.toFixed(1)}%"></div>
|
|
8110
7997
|
</div>
|
|
8111
7998
|
<div class="breakdown-cost">${this._formatUSD(s.cost_usd)}</div>
|
|
8112
7999
|
</div>
|
|
@@ -8509,7 +8396,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
8509
8396
|
|
|
8510
8397
|
${e}
|
|
8511
8398
|
</div>
|
|
8512
|
-
`,this.shadowRoot.querySelectorAll(".tab").forEach(t=>{t.addEventListener("click",()=>{this._setTab(t.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",
|
|
8399
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(t=>{t.addEventListener("click",()=>{this._setTab(t.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",le);var Ge={critical:"var(--loki-red, #ef4444)",warning:"var(--loki-yellow, #eab308)",info:"var(--loki-blue, #3b82f6)",success:"var(--loki-green, #1FC5A8)"},lt={build:{label:"Build",icon:"B"},quality:{label:"Quality",icon:"Q"},system:{label:"System",icon:"S"},security:{label:"Security",icon:"!"}},de=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._notifications=[],this._triggers=[],this._summary={},this._connected=!1,this._activeTab="feed",this._categoryFilter="all",this._panelOpen=!0,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._loadNotifications(),this._loadTriggers(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&(this._loadNotifications(),this._loadTriggers()),e==="theme"&&this._applyTheme())}async _loadNotifications(){try{let e=this.getAttribute("api-url")||window.location.origin,t=await fetch(e+"/api/notifications");if(t.ok){let i=await t.json();this._notifications=i.notifications||[],this._summary=i.summary||{},this._connected=!0}}catch{this._connected=!1}this.render()}async _loadTriggers(){try{let e=this.getAttribute("api-url")||window.location.origin,t=await fetch(e+"/api/notifications/triggers");if(t.ok){let i=await t.json();this._triggers=i.triggers||[]}}catch{}}async _acknowledgeNotification(e){let t=this.getAttribute("api-url")||window.location.origin;try{await fetch(t+"/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{method:"POST"})}catch{}this._loadNotifications()}async _unacknowledgeNotification(e){let t=this.getAttribute("api-url")||window.location.origin;await fetch(t+"/api/notifications/"+encodeURIComponent(e)+"/unacknowledge",{method:"POST"}),this._loadNotifications()}async _acknowledgeAll(){let e=this.getAttribute("api-url")||window.location.origin,t=this._notifications.filter(i=>!i.acknowledged);for(let i of t)await fetch(e+"/api/notifications/"+encodeURIComponent(i.id)+"/acknowledge",{method:"POST"});this._loadNotifications()}async _toggleTrigger(e,t){let i=this.getAttribute("api-url")||window.location.origin,a=this._triggers.map(s=>s.id===e?{...s,enabled:t}:s);await fetch(i+"/api/notifications/triggers",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({triggers:a})}),this._triggers=a,this.render()}_startPolling(){this._poll=b({loadFn:()=>{this._loadNotifications(),this._loadTriggers()},intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatTime(e){if(!e)return"";try{let t=new Date(e),a=new Date-t,s=Math.floor(a/1e3),r=Math.floor(s/60),o=Math.floor(r/60),n=Math.floor(o/24);return s<60?s+"s ago":r<60?r+"m ago":o<24?o+"h ago":n<7?n+"d ago":t.toLocaleDateString()}catch{return String(e)}}_getTimeGroup(e){if(!e)return"Other";try{let t=new Date(e),i=new Date,a=new Date(i.getFullYear(),i.getMonth(),i.getDate()),s=new Date(a);s.setDate(s.getDate()-1);let r=new Date(a);return r.setDate(r.getDate()-7),t>=a?"Today":t>=s?"Yesterday":t>=r?"This Week":"Earlier"}catch{return"Other"}}_escapeHTML(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getSeverityColor(e){return Ge[e]||Ge.info}_getCategory(e){return e.category||e.type||"system"}_switchTab(e){this._activeTab=e,this.render()}_setCategoryFilter(e){this._categoryFilter=e,this.render()}_togglePanel(){this._panelOpen=!this._panelOpen,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".tab").forEach(a=>{a.addEventListener("click",()=>{this._switchTab(a.dataset.tab)})}),e.querySelectorAll(".cat-btn").forEach(a=>{a.addEventListener("click",()=>{this._setCategoryFilter(a.dataset.cat)})}),e.querySelectorAll(".ack-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._acknowledgeNotification(a.dataset.id)})}),e.querySelectorAll(".unread-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._unacknowledgeNotification(a.dataset.id)})});let t=e.querySelector(".ack-all-btn");t&&t.addEventListener("click",()=>{this._acknowledgeAll()});let i=e.querySelector(".bell-icon");i&&i.addEventListener("click",()=>{this._togglePanel()}),e.querySelectorAll(".toggle input").forEach(a=>{a.addEventListener("change",()=>{this._toggleTrigger(a.dataset.triggerId,a.checked)})}),e.querySelectorAll(".dismiss-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._acknowledgeNotification(a.dataset.id)})})}_renderBellIcon(){let e=this._summary.unacknowledged||0;return`
|
|
8513
8400
|
<div class="bell-container">
|
|
8514
8401
|
<button class="bell-icon" title="${e} unread notifications">
|
|
8515
8402
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -8532,7 +8419,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
8532
8419
|
</div>
|
|
8533
8420
|
<div class="summary-card">
|
|
8534
8421
|
<div class="card-label">Critical</div>
|
|
8535
|
-
<div class="card-value" style="color: ${
|
|
8422
|
+
<div class="card-value" style="color: ${Ge.critical}">${i}</div>
|
|
8536
8423
|
</div>
|
|
8537
8424
|
</div>
|
|
8538
8425
|
${t>0?`
|
|
@@ -8541,9 +8428,9 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
8541
8428
|
</div>
|
|
8542
8429
|
`}_renderCategoryFilter(){return`
|
|
8543
8430
|
<div class="category-bar">
|
|
8544
|
-
${["all","build","quality","system","security"].map(t=>{let i=this._categoryFilter===t,a=t==="all"?"All":
|
|
8431
|
+
${["all","build","quality","system","security"].map(t=>{let i=this._categoryFilter===t,a=t==="all"?"All":lt[t]?.label||t;return`<button class="cat-btn ${i?"active":""}" data-cat="${t}">${a}</button>`}).join("")}
|
|
8545
8432
|
</div>
|
|
8546
|
-
`}_renderNotificationList(){let e=[...this._notifications].sort((s,r)=>new Date(r.timestamp)-new Date(s.timestamp));if(this._categoryFilter!=="all"&&(e=e.filter(s=>this._getCategory(s)===this._categoryFilter)),e.length===0)return'<div class="empty-state">No notifications</div>';let t={};for(let s of e){let r=this._getTimeGroup(s.timestamp);t[r]||(t[r]=[]),t[r].push(s)}let i=["Today","Yesterday","This Week","Earlier","Other"],a="";for(let s of i)!t[s]||t[s].length===0||(a+=`<div class="time-group-label">${s}</div>`,a+=t[s].map(r=>{let o=r.acknowledged,n=this._getSeverityColor(r.severity),l=this._getCategory(r),c=
|
|
8433
|
+
`}_renderNotificationList(){let e=[...this._notifications].sort((s,r)=>new Date(r.timestamp)-new Date(s.timestamp));if(this._categoryFilter!=="all"&&(e=e.filter(s=>this._getCategory(s)===this._categoryFilter)),e.length===0)return'<div class="empty-state">No notifications</div>';let t={};for(let s of e){let r=this._getTimeGroup(s.timestamp);t[r]||(t[r]=[]),t[r].push(s)}let i=["Today","Yesterday","This Week","Earlier","Other"],a="";for(let s of i)!t[s]||t[s].length===0||(a+=`<div class="time-group-label">${s}</div>`,a+=t[s].map(r=>{let o=r.acknowledged,n=this._getSeverityColor(r.severity),l=this._getCategory(r),c=lt[l]||{label:l,icon:"?"};return`
|
|
8547
8434
|
<div class="notif-row ${o?"acknowledged":""}">
|
|
8548
8435
|
<span class="severity-dot" style="background: ${n};" title="${this._escapeHTML(r.severity)}"></span>
|
|
8549
8436
|
<span class="cat-icon" title="${c.label}">${c.icon}</span>
|
|
@@ -9026,7 +8913,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9026
8913
|
`:""}
|
|
9027
8914
|
`:""}
|
|
9028
8915
|
</div>
|
|
9029
|
-
`,this._bindEvents()}};customElements.get("loki-notification-center")||customElements.define("loki-notification-center",
|
|
8916
|
+
`,this._bindEvents()}};customElements.get("loki-notification-center")||customElements.define("loki-notification-center",de);var ce=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._error=null,this._loading=!0,this._api=null,this._pollInterval=null,this._expandedDecisions=new Set}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._data=await this._api._get("/api/session-diff"),this._error=null}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleDecision(e){this._expandedDecisions.has(e)?this._expandedDecisions.delete(e):this._expandedDecisions.add(e),this.render()}render(){let e=`
|
|
9030
8917
|
${this.getBaseStyles()}
|
|
9031
8918
|
|
|
9032
8919
|
:host {
|
|
@@ -9292,7 +9179,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9292
9179
|
${n}
|
|
9293
9180
|
${l}
|
|
9294
9181
|
</div>
|
|
9295
|
-
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(c=>{c.addEventListener("click",()=>{this._toggleDecision(parseInt(c.dataset.index))})})}};customElements.get("loki-session-diff")||customElements.define("loki-session-diff",
|
|
9182
|
+
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(c=>{c.addEventListener("click",()=>{this._toggleDecision(parseInt(c.dataset.index))})})}};customElements.get("loki-session-diff")||customElements.define("loki-session-diff",ce);var pe=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._error=null,this._loading=!0,this._optimizing=!1,this._api=null,this._pollInterval=null,this._expandedChanges=new Set}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._data=await this._api._get("/api/prompt-versions"),this._error=null}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}async _triggerOptimize(){if(!this._optimizing){this._optimizing=!0,this.render();try{await this._api._post("/api/prompt-optimize?dry_run=false",{}),await this._loadData()}catch(e){this._error=e.message}this._optimizing=!1,this.render()}}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:6e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_formatTime(e){if(!e)return"--";try{let t=new Date(e),a=new Date-t,s=Math.floor(a/6e4);if(s<1)return"Just now";if(s<60)return`${s}m ago`;let r=Math.floor(s/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}catch{return"--"}}_toggleChange(e){this._expandedChanges.has(e)?this._expandedChanges.delete(e):this._expandedChanges.add(e),this.render()}render(){let e=`
|
|
9296
9183
|
${this.getBaseStyles()}
|
|
9297
9184
|
|
|
9298
9185
|
:host {
|
|
@@ -9543,7 +9430,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9543
9430
|
|
|
9544
9431
|
${o}
|
|
9545
9432
|
</div>
|
|
9546
|
-
`;let n=this.shadowRoot.getElementById("optimize-btn");n&&n.addEventListener("click",()=>this._triggerOptimize()),this.shadowRoot.querySelectorAll(".change-header").forEach(l=>{l.addEventListener("click",()=>{this._toggleChange(parseInt(l.dataset.index))})})}};customElements.get("loki-prompt-optimizer")||customElements.define("loki-prompt-optimizer",
|
|
9433
|
+
`;let n=this.shadowRoot.getElementById("optimize-btn");n&&n.addEventListener("click",()=>this._triggerOptimize()),this.shadowRoot.querySelectorAll(".change-header").forEach(l=>{l.addEventListener("click",()=>{this._toggleChange(parseInt(l.dataset.index))})})}};customElements.get("loki-prompt-optimizer")||customElements.define("loki-prompt-optimizer",pe);var he=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._history=[],this._error=null,this._loading=!0,this._scanning=!1,this._rigourAvailable=!0,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{let[e,t]=await Promise.allSettled([this._api._get("/api/quality-score"),this._api._get("/api/quality-score/history")]);if(e.status==="fulfilled"){let i=e.value;i&&i.error&&i.error.includes("not installed")?(this._rigourAvailable=!1,this._data=null):i&&i.available===!1?(this._rigourAvailable=!1,this._data=null):i&&i.score==null?(this._rigourAvailable=!0,this._data=null):(this._rigourAvailable=!0,this._data=i),this._error=null}else(e.reason?.message||"").includes("404")?(this._rigourAvailable=!1,this._data=null,this._error=null):(this._error="Failed to load quality score",this._data=null);if(t.status==="fulfilled"){let i=t.value;this._history=Array.isArray(i)?i.slice(-10):(i.scores||[]).slice(-10)}}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}async _triggerScan(){if(!this._scanning){this._scanning=!0,this.render();try{await this._api._post("/api/quality-scan",{},{timeout:3e5}),await this._loadData()}catch(e){this._error=e.message}this._scanning=!1,this.render()}}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:6e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGrade(e){return e>=90?{grade:"A",color:"var(--loki-success)"}:e>=80?{grade:"B",color:"var(--loki-success)"}:e>=70?{grade:"C",color:"var(--loki-warning)"}:e>=60?{grade:"D",color:"var(--loki-warning)"}:{grade:"F",color:"var(--loki-error)"}}_renderSparkline(e){if(!e||e.length<2)return"";let t=e.map(c=>typeof c=="number"?c:c.score||0),i=Math.min(...t),s=Math.max(...t)-i||1,r=120,o=32,n=2,l=t.map((c,p)=>{let h=n+p/(t.length-1)*(r-n*2),v=n+(1-(c-i)/s)*(o-n*2);return`${h},${v}`}).join(" ");return`
|
|
9547
9434
|
<svg width="${r}" height="${o}" viewBox="0 0 ${r} ${o}" class="sparkline">
|
|
9548
9435
|
<polyline points="${l}" fill="none" stroke="var(--loki-accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9549
9436
|
<circle cx="${l.split(" ").pop().split(",")[0]}" cy="${l.split(" ").pop().split(",")[1]}" r="2.5" fill="var(--loki-accent)"/>
|
|
@@ -9933,15 +9820,15 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9933
9820
|
</button>
|
|
9934
9821
|
</div>
|
|
9935
9822
|
</div>
|
|
9936
|
-
`;let k=this.shadowRoot.getElementById("scan-btn");k&&k.addEventListener("click",()=>this._triggerScan());return}let i=this._data||{},a=i.score!=null?Math.round(i.score):0,{grade:s,color:r}=this._getGrade(a),o=i.categories||{},n=i.findings||{},l=["security","code_quality","compliance","best_practices"],c={security:"Security",code_quality:"Code Quality",compliance:"Compliance",best_practices:"Best Practices"},p=l.map(k=>{let
|
|
9823
|
+
`;let k=this.shadowRoot.getElementById("scan-btn");k&&k.addEventListener("click",()=>this._triggerScan());return}let i=this._data||{},a=i.score!=null?Math.round(i.score):0,{grade:s,color:r}=this._getGrade(a),o=i.categories||{},n=i.findings||{},l=["security","code_quality","compliance","best_practices"],c={security:"Security",code_quality:"Code Quality",compliance:"Compliance",best_practices:"Best Practices"},p=l.map(k=>{let _=o[k]!=null?Math.round(o[k]):0,R=_>=80?"var(--loki-success)":_>=60?"var(--loki-warning)":"var(--loki-error)";return`
|
|
9937
9824
|
<div class="category-item">
|
|
9938
9825
|
<span class="category-name">${c[k]||k}</span>
|
|
9939
9826
|
<div class="progress-bar">
|
|
9940
|
-
<div class="progress-fill" style="width:${
|
|
9827
|
+
<div class="progress-fill" style="width:${_}%;background:${R};"></div>
|
|
9941
9828
|
</div>
|
|
9942
|
-
<span class="category-score">${
|
|
9829
|
+
<span class="category-score">${_}</span>
|
|
9943
9830
|
</div>
|
|
9944
|
-
`}).join(""),
|
|
9831
|
+
`}).join(""),v=[{key:"critical",cls:"finding-critical",label:"Critical"},{key:"major",cls:"finding-major",label:"Major"},{key:"minor",cls:"finding-minor",label:"Minor"},{key:"info",cls:"finding-info",label:"Info"}].filter(k=>(n[k.key]||0)>0).map(k=>`<span class="finding-badge ${k.cls}">${k.label}: ${n[k.key]}</span>`).join(""),u=this._renderSparkline(this._history);this.shadowRoot.innerHTML=`
|
|
9945
9832
|
<style>${e}</style>
|
|
9946
9833
|
<div class="quality-container">
|
|
9947
9834
|
<div class="quality-header">
|
|
@@ -9957,10 +9844,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9957
9844
|
<div class="score-number">${a}</div>
|
|
9958
9845
|
<span class="grade-badge" style="background:${r};color:#fff;">${s}</span>
|
|
9959
9846
|
</div>
|
|
9960
|
-
${
|
|
9847
|
+
${u?`
|
|
9961
9848
|
<div class="sparkline-container">
|
|
9962
9849
|
<span class="sparkline-label">Trend (last ${this._history.length})</span>
|
|
9963
|
-
${
|
|
9850
|
+
${u}
|
|
9964
9851
|
</div>
|
|
9965
9852
|
`:""}
|
|
9966
9853
|
</div>
|
|
@@ -9970,19 +9857,19 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9970
9857
|
${p}
|
|
9971
9858
|
</div>
|
|
9972
9859
|
|
|
9973
|
-
${
|
|
9860
|
+
${v?`
|
|
9974
9861
|
<div class="findings-section">
|
|
9975
9862
|
<div class="section-label">Findings</div>
|
|
9976
|
-
<div class="findings-row">${
|
|
9863
|
+
<div class="findings-row">${v}</div>
|
|
9977
9864
|
</div>
|
|
9978
9865
|
`:""}
|
|
9979
9866
|
</div>
|
|
9980
|
-
`;let x=this.shadowRoot.getElementById("scan-btn");x&&x.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-score")||customElements.define("loki-quality-score",
|
|
9867
|
+
`;let x=this.shadowRoot.getElementById("scan-btn");x&&x.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-score")||customElements.define("loki-quality-score",he);var dt=["understand","guardrail","migrate","verify"],ct={understand:"Understand",guardrail:"Guardrail",migrate:"Migrate",verify:"Verify"},Bt={understand:"#5b9bd5",guardrail:"#e8b84a",migrate:"#5bb870",verify:"#5bc8c8"},ue=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._migration=null,this._migrations=[],this._loading=!0,this._error=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._fetchMigrations(),this._poll=b({loadFn:()=>this._fetchData(),intervalMs:15e3,element:this,immediate:!1})}disconnectedCallback(){super.disconnectedCallback(),this._poll&&(this._poll.stop(),this._poll=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._fetchMigrations()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _fetchMigrations(){try{let e=await this._api._get("/api/migration/list");this._migrations=Array.isArray(e)?e:e.migrations||[],this._error=null;let t=this._migrations.find(i=>i.status==="in_progress"||i.status==="active");t?await this._fetchStatus(t.migration_id||t.id):this._migration=null}catch(e){this._error=e.message,this._migrations=[],this._migration=null}this._loading=!1,this.render()}async _fetchStatus(e){try{this._migration=await this._api._get(`/api/migration/${encodeURIComponent(e)}/status`),this._error=null}catch(t){this._error=t.message}}async _fetchData(){let e=this._migration&&(this._migration.migration_id||this._migration.id);e?(await this._fetchStatus(e),this.render()):await this._fetchMigrations()}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"):""}_getPhaseIcon(e,t,i){return(i||[]).includes(e)?"[x]":e===t?"[>]":"[ ]"}_getPhaseIndex(e){let t=dt.indexOf(e);return t>=0?t:0}_renderPhaseBar(e,t){let i=t||[];return dt.map(a=>{let s=i.includes(a),r=a===e,o=Bt[a],n=s?"1":r?"0.7":"0.2",l=this._getPhaseIcon(a,e,t);return`
|
|
9981
9868
|
<div class="phase-segment">
|
|
9982
9869
|
<div class="phase-bar-fill" style="background:${o};opacity:${n};"></div>
|
|
9983
9870
|
<div class="phase-label">
|
|
9984
9871
|
<span class="phase-icon">${l}</span>
|
|
9985
|
-
${
|
|
9872
|
+
${ct[a]}
|
|
9986
9873
|
</div>
|
|
9987
9874
|
</div>
|
|
9988
9875
|
`}).join("")}_renderFeatureStats(e){if(!e)return"";let t=e.passing||0,i=e.total||0,a=i>0?Math.round(t/i*100):0,s=a>=80?"var(--loki-success)":a>=50?"var(--loki-warning)":"var(--loki-error)";return`
|
|
@@ -10373,7 +10260,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
10373
10260
|
</div>
|
|
10374
10261
|
<div class="meta-item">
|
|
10375
10262
|
<span class="meta-label">Phase</span>
|
|
10376
|
-
<span>${
|
|
10263
|
+
<span>${ct[o]||this._escapeHtml(o)}</span>
|
|
10377
10264
|
</div>
|
|
10378
10265
|
</div>
|
|
10379
10266
|
|
|
@@ -10400,7 +10287,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
10400
10287
|
<div class="section-label">Migrations</div>
|
|
10401
10288
|
${this._renderMigrationList()}
|
|
10402
10289
|
</div>
|
|
10403
|
-
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",
|
|
10290
|
+
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",ue);var Pt=[["claude-opus","claude"],["claude-sonnet","claude"],["claude-haiku","claude"],["opus","claude"],["sonnet","claude"],["haiku","claude"],["claude","claude"],["gpt-4","codex"],["gpt-5","codex"],["gpt","codex"],["codex","codex"],["o1","codex"],["o3","codex"],["cline","cline"],["aider","aider"]];function It(d){if(d==null)return null;switch(d%4){case 0:return{tier:"planning",model:"opus",provider:"claude"};case 1:return{tier:"development",model:"sonnet",provider:"claude"};case 2:return{tier:"development",model:"sonnet",provider:"claude"};case 3:return{tier:"fast",model:"haiku",provider:"claude"};default:return{tier:"development",model:"sonnet",provider:"claude"}}}function Ft(d,e){if(e!=null){let i=It(e);if(i)return i.provider}let t=(d||"").toLowerCase();for(let[i,a]of Pt)if(t.includes(i))return a;return"unknown"}var ge=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._pollInterval=null,this._activeTab="heatmap",this._activity=[],this._tools=[],this._cost={},this._context={},this._trends=[],this._toolTimeRange="7d",this._connected=!1,this._loading=!1,this._loadedOnce=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _fetchActivity(){let e=this._api.baseUrl||window.location.origin,t=new AbortController,i=setTimeout(()=>t.abort(),1e4);try{let a=await fetch(`${e}/api/activity?limit=1000`,{signal:t.signal});if(clearTimeout(i),!a.ok)throw new Error(`Activity API ${a.status}`);return a.json()}catch(a){throw clearTimeout(i),a}}async _loadData(){if(!(!this.isConnected||this._loading)){this._loading=!0;try{let e=await Promise.allSettled([this._fetchActivity(),this._api.getToolEfficiency(50),this._api.getCost(),this._api.getContext(),this._api.getLearningTrends({timeRange:this._toolTimeRange})]);if(e[0].status==="fulfilled"&&(this._activity=e[0].value||[]),e[1].status==="fulfilled"&&(this._tools=e[1].value||[]),e[2].status==="fulfilled"&&(this._cost=e[2].value||{}),e[3].status==="fulfilled"&&(this._context=e[3].value||{}),e[4].status==="fulfilled"){let t=e[4].value||{};this._trends=Array.isArray(t)?t:t.dataPoints||[]}this._connected=e.some(t=>t.status==="fulfilled"),this._loadedOnce=!0,this.render()}finally{this._loading=!1}}}_hasAnyData(){let e=Array.isArray(this._activity)?this._activity.length:0,t=Array.isArray(this._tools)?this._tools.length:0,i=this._cost&&this._cost.by_model?Object.keys(this._cost.by_model).length:0,a=this._context||{},r=(a.totals||{}).iterations_tracked||a.total_iterations||a.iteration||0;return e>0||t>0||i>0||r>0}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_computeHeatmap(){let e={},t=Array.isArray(this._activity)?this._activity:[];for(let c of t){let p=c.timestamp||c.ts||c.created_at;if(!p)continue;let h=new Date(p);if(isNaN(h.getTime()))continue;let v=this._localDateKey(h);e[v]=(e[v]||0)+1}let i=new Date;i.setHours(0,0,0,0);let a=i.getDay(),s=new Date(i),r=new Date(i);r.setDate(r.getDate()-(52*7+a));let o=[],n=new Date(r),l=0;for(;n<=s;){let c=this._localDateKey(n),p=e[c]||0;p>l&&(l=p),o.push({date:c,count:p,day:n.getDay()}),n.setDate(n.getDate()+1)}return{cells:o,maxCount:l}}_getHeatmapLevel(e,t){if(e===0||t===0)return 0;let i=e/t;return i<=.25?1:i<=.5?2:i<=.75?3:4}_renderHeatmap(){let{cells:e,maxCount:t}=this._computeHeatmap(),i=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],a=["","Mon","","Wed","","Fri",""],s=[],r=-1,o=-1;for(let p=0;p<e.length;p++){e[p].day===0&&o++;let h=new Date(e[p].date).getMonth();h!==r&&(s.push({month:i[h],col:Math.max(o,1)}),r=h)}let n=s.map(p=>`<span class="heatmap-month" style="grid-column: ${p.col}">${p.month}</span>`).join(""),l=e.map(p=>`<div class="heatmap-cell level-${this._getHeatmapLevel(p.count,t)}" title="${p.date}: ${p.count} activities"></div>`).join(""),c=a.map(p=>`<span class="heatmap-day-label">${p}</span>`).join("");return`
|
|
10404
10291
|
<div class="heatmap-container">
|
|
10405
10292
|
<div class="heatmap-months">${n}</div>
|
|
10406
10293
|
<div class="heatmap-body">
|
|
@@ -10450,7 +10337,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
10450
10337
|
<div class="sparkline-label">Activity Trend (hourly)</div>
|
|
10451
10338
|
<div class="sparkline">${s}</div>
|
|
10452
10339
|
</div>
|
|
10453
|
-
`}_computeProviders(){let e=this._cost.by_model||{},t={};for(let[r,o]of Object.entries(e)){let n=
|
|
10340
|
+
`}_computeProviders(){let e=this._cost.by_model||{},t={};for(let[r,o]of Object.entries(e)){let n=Ft(r);t[n]||(t[n]={cost:0,tokens:0,iterations:0,models:[]});let l=o.cost_usd||0,c=(o.input_tokens||0)+(o.output_tokens||0);t[n].cost+=l,t[n].tokens+=c,t[n].models.push(r)}let a=(this._context.totals||{}).iterations_tracked||this._context.total_iterations||this._context.iteration||0,s=this._cost.estimated_cost_usd||0;for(let r of Object.values(t))if(s>0&&a>0){let o=r.cost/s;r.iterations=Math.round(o*a)}return t}_renderProviders(){let e=this._computeProviders(),t={claude:{label:"Claude",color:"var(--loki-accent)"},codex:{label:"Codex",color:"var(--loki-success)"},cline:{label:"Cline",color:"var(--loki-info)"},aider:{label:"Aider",color:"var(--loki-blue)"},unknown:{label:"Other",color:"var(--loki-text-muted)"}},i=Object.entries(e);return i.length===0?'<div class="empty-state">No provider activity yet. Start a build to compare providers side by side.</div>':`
|
|
10454
10341
|
<div class="provider-grid">
|
|
10455
10342
|
${i.map(([a,s])=>{let r=t[a]||t.unknown,o=s.iterations>0?(s.cost/s.iterations).toFixed(4):"--",n=s.iterations>0?Math.round(s.tokens/s.iterations).toLocaleString():"--";return`
|
|
10456
10343
|
<div class="provider-card">
|
|
@@ -10953,7 +10840,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
10953
10840
|
</div>
|
|
10954
10841
|
`}
|
|
10955
10842
|
</div>
|
|
10956
|
-
`,this.shadowRoot.querySelectorAll("[data-tab]").forEach(l=>{l.addEventListener("click",c=>this._handleTabClick(c))});let r=this.shadowRoot.getElementById("tool-time-range");r&&r.addEventListener("change",l=>this._handleTimeRangeChange(l));let o=this.shadowRoot.getElementById("analytics-retry-btn");o&&o.addEventListener("click",()=>this._loadData());let n=this.shadowRoot.getElementById("analytics-overview-btn");n&&n.addEventListener("click",()=>this._navigateToOverview())}_navigateToOverview(){this.dispatchEvent(new CustomEvent("loki-navigate",{detail:{view:"overview"},bubbles:!0,composed:!0}))}};customElements.get("loki-analytics")||customElements.define("loki-analytics",
|
|
10843
|
+
`,this.shadowRoot.querySelectorAll("[data-tab]").forEach(l=>{l.addEventListener("click",c=>this._handleTabClick(c))});let r=this.shadowRoot.getElementById("tool-time-range");r&&r.addEventListener("change",l=>this._handleTimeRangeChange(l));let o=this.shadowRoot.getElementById("analytics-retry-btn");o&&o.addEventListener("click",()=>this._loadData());let n=this.shadowRoot.getElementById("analytics-overview-btn");n&&n.addEventListener("click",()=>this._navigateToOverview())}_navigateToOverview(){this.dispatchEvent(new CustomEvent("loki-navigate",{detail:{view:"overview"},bubbles:!0,composed:!0}))}};customElements.get("loki-analytics")||customElements.define("loki-analytics",ge);var pt={pass:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"PASS"},fail:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"FAIL"},pending:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"PENDING"}};function jt(d){if(!d)return"Never";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return"Unknown"}}function Ut(d){if(!d||d.length===0)return{pass:0,fail:0,pending:0,total:0};let e={pass:0,fail:0,pending:0,total:d.length};for(let t of d){let i=(t.status||"pending").toLowerCase();i==="pass"?e.pass++:i==="fail"?e.fail++:e.pending++}return e}var me=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._gates=[],this._evidence={blocked:!1},this._pollInterval=null,this._lastDataHash=null,this._scanning=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{this._loading=!0;let e=await this._api._get("/api/council/gate"),t=e?.gates||e||[],i=e?.evidence||{blocked:!1},a=JSON.stringify({gates:t,evidence:i});if(a===this._lastDataHash)return;this._lastDataHash=a,this._gates=Array.isArray(t)?t:[],this._evidence=i,this._error=null}catch(e){this._error||(this._error=`Failed to load quality gates: ${e.message}`)}finally{this._loading=!1}this.render()}async _triggerScan(){if(!this._scanning){this._scanning=!0,this.render();try{await this._api._post("/api/quality-scan",{},{timeout:3e5}),this._lastDataHash=null,await this._loadData()}catch(e){this._error=`Quality scan failed: ${e.message}`}finally{this._scanning=!1,this.render()}}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
10957
10844
|
:host {
|
|
10958
10845
|
display: block;
|
|
10959
10846
|
}
|
|
@@ -11213,7 +11100,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11213
11100
|
color: var(--loki-text-muted, #939084);
|
|
11214
11101
|
font-size: 13px;
|
|
11215
11102
|
}
|
|
11216
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._gates,i=
|
|
11103
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._gates,i=Ut(t),a='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>',s;this._loading&&t.length===0?s='<div class="loading">Loading quality gates...</div>':t.length===0?s=`
|
|
11217
11104
|
<div class="es">
|
|
11218
11105
|
<div class="es-icon">${a}</div>
|
|
11219
11106
|
<div class="es-title">No gate results yet</div>
|
|
@@ -11221,20 +11108,20 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11221
11108
|
<button class="es-cta" id="gates-scan-btn" ${this._scanning?"disabled":""}>
|
|
11222
11109
|
${this._scanning?'<span class="es-spinner"></span> Scanning...':"Run quality scan"}
|
|
11223
11110
|
</button>
|
|
11224
|
-
</div>`:s=`<div class="gates-grid">${t.map(p=>{let h=(p.status||"pending").toLowerCase(),
|
|
11111
|
+
</div>`:s=`<div class="gates-grid">${t.map(p=>{let h=(p.status||"pending").toLowerCase(),v=pt[h]||pt.pending;return`
|
|
11225
11112
|
<div class="gate-card status-${h}">
|
|
11226
11113
|
<div class="gate-header">
|
|
11227
11114
|
<span class="gate-name">${this._escapeHtml(p.name||"Unnamed Gate")}</span>
|
|
11228
|
-
<span class="gate-badge" style="background: ${
|
|
11115
|
+
<span class="gate-badge" style="background: ${v.bg}; color: ${v.color};">${v.label}</span>
|
|
11229
11116
|
</div>
|
|
11230
11117
|
${p.description?`<div class="gate-description">${this._escapeHtml(p.description)}</div>`:""}
|
|
11231
|
-
<div class="gate-meta">Last checked: ${
|
|
11118
|
+
<div class="gate-meta">Last checked: ${jt(p.last_checked||p.lastChecked)}</div>
|
|
11232
11119
|
</div>
|
|
11233
|
-
`}).join("")}</div>`;let r="",o=this._evidence||{};if(o.blocked){let c={empty_diff:"No changes were shipped (empty diff vs run start).",tests_red:"Tests ran and were red.",empty_diff_and_tests_red:"No changes shipped and tests were red.",no_evidence_of_completion:"No evidence of completion."},p=o.error?this._escapeHtml(o.error):c[o.reason]||this._escapeHtml(o.reason||"Completion blocked."),h=Array.isArray(o.failures)?o.failures:[],
|
|
11120
|
+
`}).join("")}</div>`;let r="",o=this._evidence||{};if(o.blocked){let c={empty_diff:"No changes were shipped (empty diff vs run start).",tests_red:"Tests ran and were red.",empty_diff_and_tests_red:"No changes shipped and tests were red.",no_evidence_of_completion:"No evidence of completion."},p=o.error?this._escapeHtml(o.error):c[o.reason]||this._escapeHtml(o.reason||"Completion blocked."),h=Array.isArray(o.failures)?o.failures:[],v=h.length?`<ul class="evidence-failures">${h.map(u=>`<li>${this._escapeHtml(u)}</li>`).join("")}</ul>`:"";r=`
|
|
11234
11121
|
<div class="evidence-banner">
|
|
11235
11122
|
<div class="evidence-title">Verified completion blocked</div>
|
|
11236
11123
|
<div class="evidence-reason">${p}</div>
|
|
11237
|
-
${
|
|
11124
|
+
${v}
|
|
11238
11125
|
<div class="evidence-hint">The run will keep iterating until there is real evidence of completion. Set <code>LOKI_EVIDENCE_GATE=0</code> to opt out.</div>
|
|
11239
11126
|
</div>
|
|
11240
11127
|
`}let n=i.total>0?`
|
|
@@ -11263,7 +11150,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11263
11150
|
${s}
|
|
11264
11151
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11265
11152
|
</div>
|
|
11266
|
-
`;let l=e.getElementById("gates-scan-btn");l&&l.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-gates")||customElements.define("loki-quality-gates",
|
|
11153
|
+
`;let l=e.getElementById("gates-scan-btn");l&&l.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-gates")||customElements.define("loki-quality-gates",me);var q={reason:{color:"var(--loki-blue, #3b82f6)",label:"Reason",description:"Analyzing requirements and planning approach"},act:{color:"var(--loki-green, #22c55e)",label:"Act",description:"Implementing changes and executing tasks"},reflect:{color:"var(--loki-purple, #a78bfa)",label:"Reflect",description:"Reviewing results and evaluating quality"},verify:{color:"var(--loki-yellow, #eab308)",label:"Verify",description:"Running tests and validating correctness"}},Ke=["reason","act","reflect","verify"];function Ne(d){if(d==null||d<0)return"--";if(d<1e3)return`${d}ms`;let e=Math.floor(d/1e3);if(e<60)return`${e}s`;let t=Math.floor(e/60),i=e%60;if(t<60)return`${t}m ${i}s`;let a=Math.floor(t/60),s=t%60;return`${a}h ${s}m`}function Ot(d){if(!d||d.length===0)return[];let e=d.reduce((t,i)=>t+(i.duration_ms||0),0);return e===0?d.map(t=>({phase:t.phase,pct:100/d.length,duration:0})):d.map(t=>({phase:t.phase,pct:(t.duration_ms||0)/e*100,duration:t.duration_ms||0}))}function Nt(d){return d==null?"--":d>=1e6?(d/1e6).toFixed(1)+"M":d>=1e3?(d/1e3).toFixed(1)+"K":String(d)}var ve=class extends g{static get observedAttributes(){return["run-id","api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._timeline=null,this._pollInterval=null,this._selectedPhase=null,this._cycleHistory=[]}get runId(){let e=this.getAttribute("run-id");return e?parseInt(e,10):null}set runId(e){e!=null?this.setAttribute("run-id",String(e)):this.removeAttribute("run-id")}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="run-id"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){let e=this.runId;if(e==null){this._timeline=null,this.render();return}try{this._loading=!0;let t=await this._api._get(`/api/v2/runs/${e}/timeline`);this._timeline=t,this._cycleHistory=t.history||[],this._error=null}catch(t){t.message&&(t.message.includes("404")||t.message.includes("Not Found"))?(this._timeline=null,this._error=null):this._error=`Failed to load timeline: ${t.message}`}finally{this._loading=!1}this.render()}_selectPhase(e){this._selectedPhase=this._selectedPhase===e?null:e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".phase-segment-interactive").forEach(t=>{t.addEventListener("click",()=>{this._selectPhase(t.dataset.phase)})}),e.querySelectorAll(".legend-item-interactive").forEach(t=>{t.addEventListener("click",()=>{this._selectPhase(t.dataset.phase)})}),e.querySelectorAll(".close-detail").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._selectedPhase=null,this.render()})})}_getStyles(){return`
|
|
11267
11154
|
:host {
|
|
11268
11155
|
display: block;
|
|
11269
11156
|
}
|
|
@@ -11548,12 +11435,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11548
11435
|
color: var(--loki-text-muted, #939084);
|
|
11549
11436
|
font-size: 13px;
|
|
11550
11437
|
}
|
|
11551
|
-
`}_renderPlaceholderTimeline(){let e=
|
|
11438
|
+
`}_renderPlaceholderTimeline(){let e=Ke.map(i=>{let a=q[i];return`<div class="phase-segment-interactive"
|
|
11552
11439
|
data-phase="${i}"
|
|
11553
11440
|
style="width: 25%; background: ${a.color}; opacity: 0.3;"
|
|
11554
11441
|
title="${a.label}: awaiting data">
|
|
11555
11442
|
${a.label}
|
|
11556
|
-
</div>`}).join(""),t=
|
|
11443
|
+
</div>`}).join(""),t=Ke.map(i=>{let a=q[i];return`<div class="legend-item-interactive" data-phase="${i}">
|
|
11557
11444
|
<span class="legend-dot" style="background: ${a.color}; opacity: 0.4;"></span>
|
|
11558
11445
|
<span class="legend-label">${a.label}</span>
|
|
11559
11446
|
<span class="legend-duration">--</span>
|
|
@@ -11565,7 +11452,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11565
11452
|
Each step fills in as your build progresses
|
|
11566
11453
|
</div>
|
|
11567
11454
|
</div>
|
|
11568
|
-
`}_renderPhaseDetail(e){let t=
|
|
11455
|
+
`}_renderPhaseDetail(e){let t=q[e];if(!t)return"";let a=(this._timeline?.phases||[]).find(s=>s.phase===e);return`
|
|
11569
11456
|
<div class="phase-detail">
|
|
11570
11457
|
<div class="detail-header">
|
|
11571
11458
|
<div class="detail-title">
|
|
@@ -11578,11 +11465,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11578
11465
|
<div class="detail-metrics">
|
|
11579
11466
|
<div class="detail-metric">
|
|
11580
11467
|
<span class="detail-metric-label">Time Spent</span>
|
|
11581
|
-
<span class="detail-metric-value">${
|
|
11468
|
+
<span class="detail-metric-value">${Ne(a?.duration_ms)}</span>
|
|
11582
11469
|
</div>
|
|
11583
11470
|
<div class="detail-metric">
|
|
11584
11471
|
<span class="detail-metric-label">Tokens Used</span>
|
|
11585
|
-
<span class="detail-metric-value">${
|
|
11472
|
+
<span class="detail-metric-value">${Nt(a?.tokens_used)}</span>
|
|
11586
11473
|
</div>
|
|
11587
11474
|
<div class="detail-metric">
|
|
11588
11475
|
<span class="detail-metric-label">Quality</span>
|
|
@@ -11594,22 +11481,22 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11594
11481
|
</div>
|
|
11595
11482
|
</div>
|
|
11596
11483
|
</div>
|
|
11597
|
-
`}_renderCycleHistory(){if(this._cycleHistory.length===0)return"";let t=this._cycleHistory.slice(-8).map((i,a)=>`<div class="history-cycle">${
|
|
11598
|
-
title="Cycle ${a+1}: ${n.label} - ${
|
|
11484
|
+
`}_renderCycleHistory(){if(this._cycleHistory.length===0)return"";let t=this._cycleHistory.slice(-8).map((i,a)=>`<div class="history-cycle">${Ke.map(r=>{let o=i.phases?.find(p=>p.phase===r),n=q[r],l=o?.status||"pending",c=l==="complete"?"0.8":l==="active"?"1":"0.3";return`<div class="history-dot" style="background: ${n.color}; opacity: ${c};"
|
|
11485
|
+
title="Cycle ${a+1}: ${n.label} - ${Ne(o?.duration_ms)}"></div>`}).join("")}</div>`).join('<div class="history-separator"></div>');return`
|
|
11599
11486
|
<div class="cycle-history">
|
|
11600
11487
|
<div class="history-label">Past Cycles (${this._cycleHistory.length} total)</div>
|
|
11601
11488
|
<div class="history-cycles">${t}</div>
|
|
11602
11489
|
</div>
|
|
11603
|
-
`}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let e=this.shadowRoot;if(!e)return;let t=this.runId,i=this._timeline,a=i?.phases||[],s=i?.current_phase||null,r=
|
|
11490
|
+
`}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let e=this.shadowRoot;if(!e)return;let t=this.runId,i=this._timeline,a=i?.phases||[],s=i?.current_phase||null,r=Ot(a),o;if(this._loading&&!i)o='<div class="loading">Loading timeline...</div>';else if(t==null)o=this._renderPlaceholderTimeline();else if(a.length===0)o=this._renderPlaceholderTimeline();else{let n=r.map(h=>{let v=q[h.phase]||{color:"var(--loki-text-muted)",label:h.phase},u=s===h.phase,x=this._selectedPhase===h.phase;return`<div class="phase-segment-interactive ${u?"current":""} ${x?"selected":""}"
|
|
11604
11491
|
data-phase="${h.phase}"
|
|
11605
|
-
style="width: ${Math.max(h.pct,2)}%; background: ${
|
|
11606
|
-
title="${
|
|
11607
|
-
${h.pct>12?
|
|
11608
|
-
</div>`}).join(""),l=a.map(h=>{let
|
|
11609
|
-
<span class="legend-dot" style="background: ${
|
|
11610
|
-
<span class="legend-label">${
|
|
11611
|
-
<span class="legend-duration">${
|
|
11612
|
-
${
|
|
11492
|
+
style="width: ${Math.max(h.pct,2)}%; background: ${v.color};"
|
|
11493
|
+
title="${v.label}: ${Ne(h.duration)}">
|
|
11494
|
+
${h.pct>12?v.label:""}
|
|
11495
|
+
</div>`}).join(""),l=a.map(h=>{let v=q[h.phase]||{color:"var(--loki-text-muted)",label:h.phase},u=s===h.phase;return`<div class="legend-item-interactive ${this._selectedPhase===h.phase?"selected":""}" data-phase="${h.phase}">
|
|
11496
|
+
<span class="legend-dot" style="background: ${v.color}"></span>
|
|
11497
|
+
<span class="legend-label">${v.label}</span>
|
|
11498
|
+
<span class="legend-duration">${Ne(h.duration_ms)}</span>
|
|
11499
|
+
${u?'<span class="phase-current-tag">ACTIVE</span>':""}
|
|
11613
11500
|
</div>`}).join(""),c=this._selectedPhase?this._renderPhaseDetail(this._selectedPhase):"",p=this._renderCycleHistory();o=`
|
|
11614
11501
|
<div class="timeline-bar">${n}</div>
|
|
11615
11502
|
<div class="legend">${l}</div>
|
|
@@ -11625,7 +11512,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11625
11512
|
${o}
|
|
11626
11513
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11627
11514
|
</div>
|
|
11628
|
-
`,this._bindEvents()}};customElements.get("loki-rarv-timeline")||customElements.define("loki-rarv-timeline",
|
|
11515
|
+
`,this._bindEvents()}};customElements.get("loki-rarv-timeline")||customElements.define("loki-rarv-timeline",ve);var ht={running:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"Running"},completed:{color:"var(--loki-blue, #3b82f6)",bg:"var(--loki-blue-muted, rgba(59, 130, 246, 0.15))",label:"Completed"},failed:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"Failed"},cancelled:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"Cancelled"},pending:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Pending"},queued:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Queued"}};function qt(d,e,t){let i=d;if(i==null&&e){let l=new Date(e).getTime();i=(t?new Date(t).getTime():Date.now())-l}if(i==null||i<0)return"--";if(i<1e3)return`${i}ms`;let a=Math.floor(i/1e3);if(a<60)return`${a}s`;let s=Math.floor(a/60),r=a%60;if(s<60)return`${s}m ${r}s`;let o=Math.floor(s/60),n=s%60;return`${o}h ${n}m`}function Jt(d){if(!d)return"--";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return String(d)}}var fe=class extends g{static get observedAttributes(){return["api-url","project-id","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._runs=[],this._pollInterval=null,this._lastDataHash=null}get projectId(){let e=this.getAttribute("project-id");return e?parseInt(e,10):null}set projectId(e){e!=null?this.setAttribute("project-id",String(e)):this.removeAttribute("project-id")}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="project-id"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=this.projectId,t=e!=null?`?project_id=${e}`:"",i=await this._api._get(`/api/v2/runs${t}`),a=i?.runs||i||[],s=JSON.stringify(a);if(s===this._lastDataHash)return;this._lastDataHash=s,this._runs=Array.isArray(a)?a:[],this._error=null}catch(e){this._error||(this._error=`Failed to load runs: ${e.message}`)}finally{this._loading=!1}this.render()}async _cancelRun(e){try{await this._api._post(`/api/v2/runs/${e}/cancel`),await this._loadData()}catch(t){this._error=`Cancel failed: ${t.message}`,this.render()}}async _replayRun(e){try{await this._api._post(`/api/v2/runs/${e}/replay`),await this._loadData()}catch(t){this._error=`Replay failed: ${t.message}`,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11629
11516
|
:host {
|
|
11630
11517
|
display: block;
|
|
11631
11518
|
}
|
|
@@ -11778,13 +11665,13 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11778
11665
|
color: var(--loki-text-muted, #939084);
|
|
11779
11666
|
margin-bottom: 8px;
|
|
11780
11667
|
}
|
|
11781
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading runs...</div>';else if(t.length===0)i='<div class="empty-state">No runs found.</div>';else{let a=t.map(s=>{let r=(s.status||"pending").toLowerCase(),o=
|
|
11668
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading runs...</div>';else if(t.length===0)i='<div class="empty-state">No runs found.</div>';else{let a=t.map(s=>{let r=(s.status||"pending").toLowerCase(),o=ht[r]||ht.pending,n=r==="running",l=r==="completed"||r==="failed"||r==="cancelled",c=qt(s.duration_ms,s.started_at,s.ended_at);return`
|
|
11782
11669
|
<tr>
|
|
11783
11670
|
<td><span class="run-id">#${s.id}</span></td>
|
|
11784
11671
|
<td>${this._escapeHtml(s.project_name||s.project||(s.project_id?`Project #${s.project_id}`:"--"))}</td>
|
|
11785
11672
|
<td><span class="status-badge" style="background: ${o.bg}; color: ${o.color};">${o.label}</span></td>
|
|
11786
11673
|
<td>${this._escapeHtml(s.trigger||s.trigger_type||"--")}</td>
|
|
11787
|
-
<td>${
|
|
11674
|
+
<td>${Jt(s.started_at)}</td>
|
|
11788
11675
|
<td>${c}</td>
|
|
11789
11676
|
<td>
|
|
11790
11677
|
<div class="actions-cell">
|
|
@@ -11821,7 +11708,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11821
11708
|
${i}
|
|
11822
11709
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11823
11710
|
</div>
|
|
11824
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadData()),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.runId))}),e.querySelectorAll('[data-action="replay"]').forEach(i=>{i.addEventListener("click",()=>this._replayRun(i.dataset.runId))})}};customElements.get("loki-run-manager")||customElements.define("loki-run-manager",
|
|
11711
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadData()),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.runId))}),e.querySelectorAll('[data-action="replay"]').forEach(i=>{i.addEventListener("click",()=>this._replayRun(i.dataset.runId))})}};customElements.get("loki-run-manager")||customElements.define("loki-run-manager",fe);var ut={running:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"Running"},stopped:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"Stopped"},active:{color:"var(--loki-blue, #3b82f6)",bg:"var(--loki-blue-muted, rgba(59, 130, 246, 0.15))",label:"Idle"},missing:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"Missing"},unknown:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Unknown"}};function Gt(d){if(d==null||d<0)return"--";if(d<60)return`${d}s`;let e=Math.floor(d/60),t=d%60;if(e<60)return`${e}m ${t}s`;let i=Math.floor(e/60),a=e%60;return`${i}h ${a}m`}function gt(d){return d==null||isNaN(d)?"$0.00":`$${Number(d).toFixed(2)}`}var be=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!0,this._error=null,this._api=null,this._runs=[],this._summary=null,this._pollInterval=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let[e,t]=await Promise.all([this._api._get("/api/fleet/runs"),this._api._get("/api/fleet/summary")]),i=Array.isArray(e)?e:e?.runs||[],a=JSON.stringify({runs:i,summaryResp:t});if(a===this._lastDataHash)return;this._lastDataHash=a,this._runs=Array.isArray(i)?i:[],this._summary=t||null,this._error=null}catch(e){this._error||(this._error=`Failed to load fleet: ${e.message}`)}finally{this._loading=!1}this.render()}async _cancelRun(e){if(e&&!(typeof confirm=="function"&&!confirm(`Cancel build "${e}"? This stops the running build.`)))try{await this._api._post(`/api/fleet/runs/${encodeURIComponent(e)}/cancel`),this._lastDataHash=null,await this._loadData()}catch(t){this._error=`Cancel failed: ${t.message}`,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11825
11712
|
:host { display: block; }
|
|
11826
11713
|
|
|
11827
11714
|
.fleet {
|
|
@@ -11989,10 +11876,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11989
11876
|
</div>
|
|
11990
11877
|
<div class="summary-card">
|
|
11991
11878
|
<div class="summary-label">Total Cost</div>
|
|
11992
|
-
<div class="summary-value">${
|
|
11879
|
+
<div class="summary-value">${gt(e.total_cost_usd)}</div>
|
|
11993
11880
|
</div>
|
|
11994
11881
|
</div>
|
|
11995
|
-
`:""}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading fleet...</div>';else if(t.length===0)i='<div class="empty-state">No registered builds. Run <code>loki start</code> in a project to populate the fleet.</div>';else{let a=t.map(s=>{let r=(s.status||"unknown").toLowerCase(),o=
|
|
11882
|
+
`:""}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading fleet...</div>';else if(t.length===0)i='<div class="empty-state">No registered builds. Run <code>loki start</code> in a project to populate the fleet.</div>';else{let a=t.map(s=>{let r=(s.status||"unknown").toLowerCase(),o=ut[r]||ut.unknown,n=s.running===!0,l=Gt(s.duration_seconds),c=s.iteration!=null?s.iteration:0,p=s.phase?this._escapeHtml(s.phase):"--";return`
|
|
11996
11883
|
<tr>
|
|
11997
11884
|
<td>
|
|
11998
11885
|
<div class="project-name">${this._escapeHtml(s.name||"project")}</div>
|
|
@@ -12001,7 +11888,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12001
11888
|
<td><span class="status-badge" style="background: ${o.bg}; color: ${o.color};">${o.label}</span></td>
|
|
12002
11889
|
<td>${p}</td>
|
|
12003
11890
|
<td>${c}</td>
|
|
12004
|
-
<td class="cost-cell">${
|
|
11891
|
+
<td class="cost-cell">${gt(s.cost_usd)}</td>
|
|
12005
11892
|
<td>${l}</td>
|
|
12006
11893
|
<td>
|
|
12007
11894
|
${n?`<button class="btn btn-cancel" data-action="cancel" data-id="${this._escapeHtml(s.id||s.path||"")}">Cancel</button>`:""}
|
|
@@ -12041,7 +11928,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12041
11928
|
${i}
|
|
12042
11929
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
12043
11930
|
</div>
|
|
12044
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>{this._lastDataHash=null,this._loadData()}),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.id))})}};customElements.get("loki-fleet")||customElements.define("loki-fleet",
|
|
11931
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>{this._lastDataHash=null,this._loadData()}),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.id))})}};customElements.get("loki-fleet")||customElements.define("loki-fleet",be);function Kt(d){if(!d)return"--";try{return new Date(d).toLocaleString([],{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return String(d)}}function Vt(d){let e=new URLSearchParams;for(let[i,a]of Object.entries(d))a!=null&&a!==""&&e.set(i,String(a));let t=e.toString();return t?`?${t}`:""}var ke=class extends g{static get observedAttributes(){return["api-url","limit","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._entries=[],this._verifyResult=null,this._verifying=!1,this._filters={action:"",resource:"",dateFrom:"",dateTo:""}}get limit(){let e=this.getAttribute("limit");return e?parseInt(e,10):50}set limit(e){this.setAttribute("limit",String(e))}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData()}disconnectedCallback(){super.disconnectedCallback()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="limit"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._loading=!0,this.render();let e={limit:this.limit,action:this._filters.action,resource:this._filters.resource,date_from:this._filters.dateFrom,date_to:this._filters.dateTo},t=Vt(e),i=await this._api._get(`/api/v2/audit${t}`);this._entries=i?.entries||i||[],this._error=null}catch(e){this._error=`Failed to load audit log: ${e.message}`}finally{this._loading=!1}this.render()}async _verifyIntegrity(){try{this._verifying=!0,this._verifyResult=null,this.render();let e=await this._api._get("/api/v2/audit/verify");this._verifyResult=e}catch(e){this._verifyResult={valid:!1,error:e.message}}finally{this._verifying=!1}this.render()}_onFilterChange(e,t){this._filters[e]=t,this._loadData()}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
12045
11932
|
:host {
|
|
12046
11933
|
display: block;
|
|
12047
11934
|
}
|
|
@@ -12261,7 +12148,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12261
12148
|
</div>
|
|
12262
12149
|
`}let a;if(this._loading&&t.length===0)a='<div class="loading">Loading audit log...</div>';else if(t.length===0)a='<div class="empty-state">No audit entries found matching filters.</div>';else{let s=t.map(r=>`
|
|
12263
12150
|
<tr>
|
|
12264
|
-
<td>${
|
|
12151
|
+
<td>${Kt(r.timestamp)}</td>
|
|
12265
12152
|
<td>${this._escapeHtml(r.action||"--")}</td>
|
|
12266
12153
|
<td>${this._escapeHtml(r.resource||r.resource_type||"--")}</td>
|
|
12267
12154
|
<td>${this._escapeHtml(r.user||r.actor||"--")}</td>
|
|
@@ -12325,7 +12212,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12325
12212
|
${a}
|
|
12326
12213
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
12327
12214
|
</div>
|
|
12328
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("verify-btn");t&&t.addEventListener("click",()=>this._verifyIntegrity());let i=e.getElementById("refresh-btn");i&&i.addEventListener("click",()=>this._loadData());let a=e.getElementById("filter-action");a&&a.addEventListener("change",n=>this._onFilterChange("action",n.target.value));let s=e.getElementById("filter-resource");s&&s.addEventListener("change",n=>this._onFilterChange("resource",n.target.value));let r=e.getElementById("filter-date-from");r&&r.addEventListener("change",n=>this._onFilterChange("dateFrom",n.target.value));let o=e.getElementById("filter-date-to");o&&o.addEventListener("change",n=>this._onFilterChange("dateTo",n.target.value))}};customElements.get("loki-audit-viewer")||customElements.define("loki-audit-viewer",
|
|
12215
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("verify-btn");t&&t.addEventListener("click",()=>this._verifyIntegrity());let i=e.getElementById("refresh-btn");i&&i.addEventListener("click",()=>this._loadData());let a=e.getElementById("filter-action");a&&a.addEventListener("change",n=>this._onFilterChange("action",n.target.value));let s=e.getElementById("filter-resource");s&&s.addEventListener("change",n=>this._onFilterChange("resource",n.target.value));let r=e.getElementById("filter-date-from");r&&r.addEventListener("change",n=>this._onFilterChange("dateFrom",n.target.value));let o=e.getElementById("filter-date-to");o&&o.addEventListener("change",n=>this._onFilterChange("dateTo",n.target.value))}};customElements.get("loki-audit-viewer")||customElements.define("loki-audit-viewer",ke);function mt(d){if(!d)return"Never";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return String(d)}}var xe=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._keys=[],this._showCreateForm=!1,this._newToken=null,this._confirmDeleteId=null,this._rotateKeyId=null,this._rotateGracePeriod="24",this._createName="",this._createRole="read",this._createExpiration=""}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData()}disconnectedCallback(){super.disconnectedCallback()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._loading=!0,this.render();let e=await this._api._get("/api/v2/api-keys");this._keys=Array.isArray(e)?e:e?.keys||[],this._error=null}catch(e){this._error=`Failed to load API keys: ${e.message}`}finally{this._loading=!1}this.render()}async _createKey(){if(!this._createName.trim()){this._error="Key name is required.",this.render();return}try{let e={name:this._createName.trim(),role:this._createRole};this._createExpiration&&(e.expiration=this._createExpiration);let t=await this._api._post("/api/v2/api-keys",e);this._newToken=t?.token||t?.key||null,this._showCreateForm=!1,this._createName="",this._createRole="read",this._createExpiration="",this._error=null,await this._loadData()}catch(e){this._error=`Create failed: ${e.message}`,this.render()}}async _rotateKey(e){try{let t={grace_period_hours:parseInt(this._rotateGracePeriod,10)||24},i=await this._api._post(`/api/v2/api-keys/${e}/rotate`,t);this._newToken=i?.token||i?.key||null,this._rotateKeyId=null,this._error=null,await this._loadData()}catch(t){this._error=`Rotate failed: ${t.message}`,this.render()}}async _deleteKey(e){try{await this._api._delete(`/api/v2/api-keys/${e}`),this._confirmDeleteId=null,this._error=null,await this._loadData()}catch(t){this._error=`Delete failed: ${t.message}`,this._confirmDeleteId=null,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
12329
12216
|
:host {
|
|
12330
12217
|
display: block;
|
|
12331
12218
|
}
|
|
@@ -12680,13 +12567,13 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12680
12567
|
<th>Actions</th>
|
|
12681
12568
|
</tr>
|
|
12682
12569
|
</thead>
|
|
12683
|
-
<tbody>${t.map(o=>{let n=o.id||o.key_id,l=(o.status||"active").toLowerCase(),c=l==="active"?"key-status-active":l==="expired"?"key-status-expired":"key-status-revoked",p=this._confirmDeleteId===n,h=this._rotateKeyId===n,
|
|
12570
|
+
<tbody>${t.map(o=>{let n=o.id||o.key_id,l=(o.status||"active").toLowerCase(),c=l==="active"?"key-status-active":l==="expired"?"key-status-expired":"key-status-revoked",p=this._confirmDeleteId===n,h=this._rotateKeyId===n,v;return p?v=`
|
|
12684
12571
|
<div class="confirm-delete">
|
|
12685
12572
|
<span>Delete this key?</span>
|
|
12686
12573
|
<button class="btn btn-sm btn-danger" data-action="confirm-delete" data-key-id="${n}">Yes</button>
|
|
12687
12574
|
<button class="btn btn-sm" data-action="cancel-delete">No</button>
|
|
12688
12575
|
</div>
|
|
12689
|
-
`:
|
|
12576
|
+
`:v=`
|
|
12690
12577
|
<div class="action-row">
|
|
12691
12578
|
<button class="btn btn-sm btn-warn" data-action="rotate" data-key-id="${n}">Rotate</button>
|
|
12692
12579
|
<button class="btn btn-sm btn-danger" data-action="delete" data-key-id="${n}">Delete</button>
|
|
@@ -12704,10 +12591,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12704
12591
|
<tr>
|
|
12705
12592
|
<td><span class="key-name">${this._escapeHtml(o.name||"Unnamed")}</span></td>
|
|
12706
12593
|
<td><span class="key-role">${this._escapeHtml(o.role||o.scopes||"--")}</span></td>
|
|
12707
|
-
<td>${
|
|
12708
|
-
<td>${
|
|
12594
|
+
<td>${mt(o.created_at||o.created)}</td>
|
|
12595
|
+
<td>${mt(o.last_used_at||o.last_used)}</td>
|
|
12709
12596
|
<td><span class="${c}">${this._escapeHtml(l)}</span></td>
|
|
12710
|
-
<td><div class="actions-cell">${
|
|
12597
|
+
<td><div class="actions-cell">${v}</div></td>
|
|
12711
12598
|
</tr>
|
|
12712
12599
|
`}).join("")}</tbody>
|
|
12713
12600
|
</table>
|
|
@@ -12724,7 +12611,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12724
12611
|
${s}
|
|
12725
12612
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
12726
12613
|
</div>
|
|
12727
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("show-create");t&&t.addEventListener("click",()=>{this._showCreateForm=!0,this.render()});let i=e.getElementById("dismiss-token");i&&i.addEventListener("click",()=>{this._newToken=null,this.render()});let a=e.getElementById("submit-create");a&&a.addEventListener("click",()=>{let r=e.getElementById("create-name"),o=e.getElementById("create-role"),n=e.getElementById("create-expiration");this._createName=r?.value||"",this._createRole=o?.value||"read",this._createExpiration=n?.value||"",this._createKey()});let s=e.getElementById("cancel-create");s&&s.addEventListener("click",()=>{this._showCreateForm=!1,this.render()}),e.querySelectorAll('[data-action="delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._deleteKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=null,this.render()})}),e.querySelectorAll('[data-action="rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-rotate"]').forEach(r=>{r.addEventListener("click",()=>{let o=e.getElementById(`rotate-grace-${r.dataset.keyId}`);this._rotateGracePeriod=o?.value||"24",this._rotateKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=null,this.render()})})}};customElements.get("loki-api-keys")||customElements.define("loki-api-keys",
|
|
12614
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("show-create");t&&t.addEventListener("click",()=>{this._showCreateForm=!0,this.render()});let i=e.getElementById("dismiss-token");i&&i.addEventListener("click",()=>{this._newToken=null,this.render()});let a=e.getElementById("submit-create");a&&a.addEventListener("click",()=>{let r=e.getElementById("create-name"),o=e.getElementById("create-role"),n=e.getElementById("create-expiration");this._createName=r?.value||"",this._createRole=o?.value||"read",this._createExpiration=n?.value||"",this._createKey()});let s=e.getElementById("cancel-create");s&&s.addEventListener("click",()=>{this._showCreateForm=!1,this.render()}),e.querySelectorAll('[data-action="delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._deleteKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=null,this.render()})}),e.querySelectorAll('[data-action="rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-rotate"]').forEach(r=>{r.addEventListener("click",()=>{let o=e.getElementById(`rotate-grace-${r.dataset.keyId}`);this._rotateGracePeriod=o?.value||"24",this._rotateKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=null,this.render()})})}};customElements.get("loki-api-keys")||customElements.define("loki-api-keys",xe);function Wt(d){return d?d.slug&&d.name?`${d.name} (${d.slug})`:d.name||d.slug||"Unknown":"Unknown"}var _e=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._tenants=[],this._selectedTenantId=null,this._dropdownOpen=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._outsideClickHandler=e=>{this._dropdownOpen&&!this.contains(e.target)&&(this._dropdownOpen=!1,this.render())},document.addEventListener("click",this._outsideClickHandler)}disconnectedCallback(){super.disconnectedCallback(),this._outsideClickHandler&&(document.removeEventListener("click",this._outsideClickHandler),this._outsideClickHandler=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._loading=!0;let e=await this._api._get("/api/v2/tenants");this._tenants=Array.isArray(e)?e:e?.tenants||[],this._error=null}catch(e){this._error=`Failed to load tenants: ${e.message}`}finally{this._loading=!1}this.render()}_toggleDropdown(){this._dropdownOpen=!this._dropdownOpen,this.render()}_selectTenant(e,t){this._selectedTenantId=e,this._dropdownOpen=!1,this.render(),this.dispatchEvent(new CustomEvent("tenant-changed",{detail:{tenantId:e,tenantName:t},bubbles:!0,composed:!0}))}_getSelectedTenant(){return this._selectedTenantId==null?null:this._tenants.find(e=>(e.id||e.slug)===this._selectedTenantId)||null}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
12728
12615
|
:host {
|
|
12729
12616
|
display: inline-block;
|
|
12730
12617
|
position: relative;
|
|
@@ -12858,7 +12745,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12858
12745
|
color: var(--loki-text-muted, #939084);
|
|
12859
12746
|
font-size: 12px;
|
|
12860
12747
|
}
|
|
12861
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getSelectedTenant(),i=t?
|
|
12748
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getSelectedTenant(),i=t?Wt(t):"All Tenants",a=this._dropdownOpen,s="";if(a){let r;if(this._loading)r='<div class="loading-text">Loading tenants...</div>';else if(this._error)r=`<div class="error-text">${this._escapeHtml(this._error)}</div>`;else{let o=this._selectedTenantId==null;r=`
|
|
12862
12749
|
<button class="dropdown-item all-tenants ${o?"selected":""}" data-tenant-id="">
|
|
12863
12750
|
<span class="tenant-name">All Tenants</span>
|
|
12864
12751
|
${o?'<span class="check-mark">*</span>':""}
|
|
@@ -12883,7 +12770,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12883
12770
|
</button>
|
|
12884
12771
|
${s}
|
|
12885
12772
|
</div>
|
|
12886
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("trigger-btn");t&&t.addEventListener("click",i=>{i.stopPropagation(),this._toggleDropdown()}),e.querySelectorAll(".dropdown-item").forEach(i=>{i.addEventListener("click",a=>{a.stopPropagation();let s=i.dataset.tenantId||null,r=i.dataset.tenantName||null;this._selectTenant(s||null,r||"All Tenants")})})}};customElements.get("loki-tenant-switcher")||customElements.define("loki-tenant-switcher",
|
|
12773
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("trigger-btn");t&&t.addEventListener("click",i=>{i.stopPropagation(),this._toggleDropdown()}),e.querySelectorAll(".dropdown-item").forEach(i=>{i.addEventListener("click",a=>{a.stopPropagation();let s=i.dataset.tenantId||null,r=i.dataset.tenantName||null;this._selectTenant(s||null,r||"All Tenants")})})}};customElements.get("loki-tenant-switcher")||customElements.define("loki-tenant-switcher",_e);var Ve={info:{color:"var(--loki-blue, #2F71E3)",label:"INFO",icon:"i"},success:{color:"var(--loki-green, #1FC5A8)",label:"OK",icon:"+"},warning:{color:"var(--loki-yellow, #D4A03C)",label:"WARN",icon:"!"},error:{color:"var(--loki-red, #C45B5B)",label:"ERR",icon:"x"}},Yt=100,ye=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._items=[],this._filter="all",this._api=null,this._pollInterval=null,this._paused=!1,this._lastTimestamp=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/activity"),t=e.events||e.activities||[];if(t.length>0){let i=t.filter(a=>!this._lastTimestamp||new Date(a.timestamp)>new Date(this._lastTimestamp)).map(a=>({id:a.id||crypto.randomUUID(),timestamp:a.timestamp||new Date().toISOString(),message:a.message||a.description||"",severity:a.severity||a.level||"info",source:a.source||a.component||"",isNew:!0}));i.length>0&&(this._items=[...i,...this._items].slice(0,Yt),this._lastTimestamp=i[0].timestamp,setTimeout(()=>{this._items.forEach(a=>a.isNew=!1)},600))}}catch{this._items.length===0&&(this._items=this._getDemoItems())}this.render()}_getDemoItems(){let e=Date.now();return[{id:"1",timestamp:new Date(e-2e3).toISOString(),message:"Build iteration #12 started",severity:"info",source:"runner"},{id:"2",timestamp:new Date(e-5e3).toISOString(),message:"Code review passed (3/3 reviewers)",severity:"success",source:"review"},{id:"3",timestamp:new Date(e-8e3).toISOString(),message:"Context window at 78% capacity",severity:"warning",source:"context"},{id:"4",timestamp:new Date(e-12e3).toISOString(),message:"Test suite completed: 42/42 passed",severity:"success",source:"testing"},{id:"5",timestamp:new Date(e-15e3).toISOString(),message:"Verify step complete: changes checked",severity:"info",source:"rarv"}]}_formatTime(e){if(!e)return"";try{return new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return""}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getFilteredItems(){return this._filter==="all"?this._items:this._items.filter(e=>e.severity===this._filter)}_setFilter(e){this._filter=e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".filter-btn").forEach(i=>{i.addEventListener("click",()=>{this._setFilter(i.dataset.filter)})});let t=e.querySelector(".activity-feed");t&&(t.addEventListener("mouseenter",()=>{this._paused=!0}),t.addEventListener("mouseleave",()=>{this._paused=!1}))}_getStyles(){return`
|
|
12887
12774
|
:host {
|
|
12888
12775
|
display: block;
|
|
12889
12776
|
}
|
|
@@ -13069,7 +12956,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13069
12956
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary, #FFFEFB); }
|
|
13070
12957
|
::-webkit-scrollbar-thumb { background: var(--loki-border, #ECEAE3); border-radius: 3px; }
|
|
13071
12958
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light, #C5C0B1); }
|
|
13072
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getFilteredItems(),a=["all","info","success","warning","error"].map(r=>{let o=this._filter===r,n=r==="all"?"All":
|
|
12959
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getFilteredItems(),a=["all","info","success","warning","error"].map(r=>{let o=this._filter===r,n=r==="all"?"All":Ve[r]?.label||r;return`<button class="filter-btn ${o?"active":""}" data-filter="${r}">${n}</button>`}).join(""),s;if(t.length===0?s='<div class="empty-state">No activity yet. Updates will stream here as your build runs.</div>':s=t.map(r=>{let o=Ve[r.severity]||Ve.info;return`
|
|
13073
12960
|
<div class="activity-item ${r.isNew?"new-item":""}">
|
|
13074
12961
|
<div class="severity-band" style="background: ${o.color};"></div>
|
|
13075
12962
|
<div class="item-content">
|
|
@@ -13090,7 +12977,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13090
12977
|
${s}
|
|
13091
12978
|
</div>
|
|
13092
12979
|
</div>
|
|
13093
|
-
`,this._bindEvents(),!this._paused){let r=e.querySelector(".activity-feed");r&&(r.scrollTop=0)}}};customElements.get("loki-activity-stream")||customElements.define("loki-activity-stream",
|
|
12980
|
+
`,this._bindEvents(),!this._paused){let r=e.querySelector(".activity-feed");r&&(r.scrollTop=0)}}};customElements.get("loki-activity-stream")||customElements.define("loki-activity-stream",ye);var Qt={claude:{initial:"C",color:"#553DE9",bgColor:"rgba(85, 61, 233, 0.12)"},codex:{initial:"X",color:"#1FC5A8",bgColor:"rgba(31, 197, 168, 0.12)"},cline:{initial:"L",color:"#D4A03C",bgColor:"rgba(212, 160, 60, 0.12)"},aider:{initial:"A",color:"#C45B5B",bgColor:"rgba(196, 91, 91, 0.12)"}},vt={healthy:"var(--loki-green, #1FC5A8)",degraded:"var(--loki-yellow, #D4A03C)",down:"var(--loki-red, #C45B5B)",unknown:"var(--loki-text-muted, #939084)"},we=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._providers=[],this._expandedProvider=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:1e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/providers/health");this._providers=e.providers||[]}catch{this._providers.length===0&&(this._providers=this._getDemoData())}this.render()}_getDemoData(){return[{name:"claude",status:"healthy",latency_ms:245,tokens_used:125400,model:"claude-opus-4-7",api_version:"v1",rate_limit:{remaining:45,limit:50},cost_usd:3.42},{name:"codex",status:"degraded",latency_ms:890,tokens_used:45200,model:"gpt-5.3-codex",api_version:"v1",rate_limit:{remaining:12,limit:60},cost_usd:.87},{name:"cline",status:"healthy",latency_ms:320,tokens_used:78600,model:"cline-default",api_version:"v1",rate_limit:{remaining:55,limit:60},cost_usd:1.15}]}_formatTokens(e){return e==null?"--":e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}_formatLatency(e){return e==null?"--":e<1e3?e+"ms":(e/1e3).toFixed(1)+"s"}_formatCost(e){return e==null?"--":"$"+e.toFixed(2)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleExpand(e){this._expandedProvider=this._expandedProvider===e?null:e,this.render()}_bindEvents(){this.shadowRoot.querySelectorAll(".provider-card").forEach(t=>{t.addEventListener("click",()=>{this._toggleExpand(t.dataset.provider)})})}_getStyles(){return`
|
|
13094
12981
|
:host {
|
|
13095
12982
|
display: block;
|
|
13096
12983
|
}
|
|
@@ -13269,7 +13156,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13269
13156
|
border: 1px solid var(--loki-border, #ECEAE3);
|
|
13270
13157
|
border-radius: 5px;
|
|
13271
13158
|
}
|
|
13272
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t;this._providers.length===0?t='<div class="empty-state">Provider status will appear once a build starts.</div>':t=`<div class="provider-grid">${this._providers.map(i=>{let a=
|
|
13159
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t;this._providers.length===0?t='<div class="empty-state">Provider status will appear once a build starts.</div>':t=`<div class="provider-grid">${this._providers.map(i=>{let a=Qt[i.name]||{initial:(i.name??"?").charAt(0).toUpperCase(),color:"#939084",bgColor:"rgba(147, 144, 132, 0.12)"},s=vt[i.status]||vt.unknown,r=this._expandedProvider===i.name,o=i.rate_limit?i.rate_limit.remaining/i.rate_limit.limit*100:100,n=o>50?"var(--loki-green)":o>20?"var(--loki-yellow)":"var(--loki-red)";return`
|
|
13273
13160
|
<div class="provider-card ${r?"expanded":""}" data-provider="${this._escapeHtml(i.name)}">
|
|
13274
13161
|
<div class="card-header">
|
|
13275
13162
|
<div class="provider-icon" style="background: ${a.bgColor}; color: ${a.color};">${a.initial}</div>
|
|
@@ -13321,7 +13208,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13321
13208
|
</div>
|
|
13322
13209
|
${t}
|
|
13323
13210
|
</div>
|
|
13324
|
-
`,this._bindEvents()}};customElements.get("loki-provider-health")||customElements.define("loki-provider-health",
|
|
13211
|
+
`,this._bindEvents()}};customElements.get("loki-provider-health")||customElements.define("loki-provider-health",we);var We=[{id:"planning",label:"Planning",icon:"P"},{id:"scaffolding",label:"Scaffolding",icon:"S"},{id:"implementation",label:"Implementation",icon:"I"},{id:"testing",label:"Testing",icon:"T"},{id:"review",label:"Review",icon:"R"},{id:"deploy",label:"Deploy",icon:"D"}],Ye={waiting:{color:"var(--loki-text-muted, #939084)",bgColor:"var(--loki-bg-tertiary, #ECEAE3)",label:"Waiting"},active:{color:"var(--loki-accent, #553DE9)",bgColor:"var(--loki-accent-muted, rgba(85, 61, 233, 0.10))",label:"Active"},complete:{color:"var(--loki-green, #1FC5A8)",bgColor:"var(--loki-green-muted, rgba(31, 197, 168, 0.12))",label:"Complete"},failed:{color:"var(--loki-red, #C45B5B)",bgColor:"var(--loki-red-muted, rgba(196, 91, 91, 0.12))",label:"Failed"}},$e=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._stages=[],this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/pipeline/status");this._stages=e.stages||[]}catch{this._stages.length===0&&(this._stages=this._getDemoData())}this.render()}_getDemoData(){return[{id:"planning",status:"complete",errors:0,duration_ms:12500},{id:"scaffolding",status:"complete",errors:0,duration_ms:8300},{id:"implementation",status:"active",errors:0,duration_ms:45e3},{id:"testing",status:"waiting",errors:0,duration_ms:null},{id:"review",status:"waiting",errors:0,duration_ms:null},{id:"deploy",status:"waiting",errors:0,duration_ms:null}]}_getStageData(e){return this._stages.find(t=>t.id===e)||{id:e,status:"waiting",errors:0}}_formatDuration(e){if(e==null||e<0)return"";if(e<1e3)return e+"ms";let t=Math.floor(e/1e3);if(t<60)return t+"s";let i=Math.floor(t/60),a=t%60;return i+"m "+a+"s"}_getStyles(){return`
|
|
13325
13212
|
:host {
|
|
13326
13213
|
display: block;
|
|
13327
13214
|
}
|
|
@@ -13484,7 +13371,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13484
13371
|
border-radius: 50%;
|
|
13485
13372
|
flex-shrink: 0;
|
|
13486
13373
|
}
|
|
13487
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=
|
|
13374
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=We.map((a,s)=>{let r=this._getStageData(a.id),o=Ye[r.status]||Ye.waiting,n=r.status==="complete",l=r.status==="active",c=r.status==="failed",p=n?'<span class="stage-check">✓</span>':c?'<span class="stage-check">✗</span>':a.icon,h=`
|
|
13488
13375
|
<div class="stage-node">
|
|
13489
13376
|
<div class="stage-circle ${l?"active":""}"
|
|
13490
13377
|
style="background: ${o.bgColor}; color: ${o.color}; border: 2px solid ${o.color};">
|
|
@@ -13494,12 +13381,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13494
13381
|
${r.duration_ms?`<span class="stage-duration">${this._formatDuration(r.duration_ms)}</span>`:""}
|
|
13495
13382
|
${r.errors>0?`<span class="stage-error-count">${r.errors} error${r.errors>1?"s":""}</span>`:""}
|
|
13496
13383
|
</div>
|
|
13497
|
-
`;if(s<
|
|
13384
|
+
`;if(s<We.length-1){let v=this._getStageData(We[s+1].id),u=n,x=l||n&&(v.status==="active"||v.status==="waiting");return h+`
|
|
13498
13385
|
<div class="connector">
|
|
13499
|
-
<div class="connector-line ${
|
|
13386
|
+
<div class="connector-line ${u?"completed":l?"active":"pending"}"></div>
|
|
13500
13387
|
${l?'<div class="flow-dot"></div>':""}
|
|
13501
13388
|
</div>
|
|
13502
|
-
`}return h}).join(""),i=Object.entries(
|
|
13389
|
+
`}return h}).join(""),i=Object.entries(Ye).map(([a,s])=>`<div class="legend-item">
|
|
13503
13390
|
<div class="legend-dot" style="background: ${s.color};"></div>
|
|
13504
13391
|
<span>${s.label}</span>
|
|
13505
13392
|
</div>`).join("");e.innerHTML=`
|
|
@@ -13515,7 +13402,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13515
13402
|
${i}
|
|
13516
13403
|
</div>
|
|
13517
13404
|
</div>
|
|
13518
|
-
`}};customElements.get("loki-pipeline-view")||customElements.define("loki-pipeline-view"
|
|
13405
|
+
`}};customElements.get("loki-pipeline-view")||customElements.define("loki-pipeline-view",$e);var Ee={episode:{color:"var(--loki-blue, #2F71E3)",shape:"circle",label:"Episode"},pattern:{color:"var(--loki-green, #1FC5A8)",shape:"square",label:"Pattern"},skill:{color:"var(--loki-purple, #553DE9)",shape:"diamond",label:"Skill"}};function Xt(d,e,t){let i=e/2,a=t/2,s=Math.min(i,a)*.65,r=d.length;return d.map((o,n)=>{let l=2*Math.PI*n/r-Math.PI/2,c=o.importance||.5,p=s*(.5+c*.5);return{...o,x:i+p*Math.cos(l),y:a+p*Math.sin(l)}})}var Ce=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._nodes=[],this._edges=[],this._selectedNode=null,this._api=null,this._pollInterval=null,this._graphWidth=600,this._graphHeight=400}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:15e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/memory/graph");this._nodes=e.nodes||[],this._edges=e.edges||[]}catch{if(this._nodes.length===0){let e=this._getDemoData();this._nodes=e.nodes,this._edges=e.edges}}this.render()}_getDemoData(){return{nodes:[{id:"ep1",type:"episode",label:"Build iteration #12",importance:.8,details:"Completed scaffolding and initial implementation"},{id:"ep2",type:"episode",label:"Code review #5",importance:.6,details:"Quality gate passed with 3/3 approval"},{id:"ep3",type:"episode",label:"Test failure #3",importance:.7,details:"Integration test timeout resolved"},{id:"pt1",type:"pattern",label:"Error recovery",importance:.9,details:"Retry with exponential backoff pattern"},{id:"pt2",type:"pattern",label:"API design",importance:.7,details:"REST endpoint naming conventions"},{id:"pt3",type:"pattern",label:"Test structure",importance:.5,details:"Arrange-Act-Assert with setup helpers"},{id:"sk1",type:"skill",label:"Playwright E2E",importance:.85,details:"Browser automation test writing"},{id:"sk2",type:"skill",label:"FastAPI routing",importance:.6,details:"Python API server development"}],edges:[{source:"ep1",target:"pt1",strength:.8},{source:"ep1",target:"sk1",strength:.6},{source:"ep2",target:"pt2",strength:.9},{source:"ep3",target:"pt1",strength:.7},{source:"ep3",target:"pt3",strength:.5},{source:"pt1",target:"sk2",strength:.4},{source:"pt2",target:"sk2",strength:.7},{source:"pt3",target:"sk1",strength:.6}]}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_selectNode(e){this._selectedNode=this._selectedNode===e?null:e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".graph-node").forEach(t=>{t.addEventListener("click",()=>{this._selectNode(t.dataset.nodeId)})}),e.querySelectorAll(".close-detail").forEach(t=>{t.addEventListener("click",()=>{this._selectedNode=null,this.render()})})}_renderNodeShape(e,t,i){let a=Ee[e.type]||Ee.episode,s=10+(e.importance||.5)*16,r=this._selectedNode===e.id,o=r?"var(--loki-accent, #553DE9)":a.color,n=r?3:1.5,l=this._selectedNode&&!r?.4:1,c;switch(a.shape){case"square":c=`<rect x="${t-s/2}" y="${i-s/2}" width="${s}" height="${s}"
|
|
13519
13406
|
rx="3" fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break;case"diamond":{let h=s/2;c=`<polygon points="${t},${i-h} ${t+h},${i} ${t},${i+h} ${t-h},${i}"
|
|
13520
13407
|
fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break}default:c=`<circle cx="${t}" cy="${i}" r="${s/2}" fill="${a.color}" fill-opacity="0.2"
|
|
13521
13408
|
stroke="${o}" stroke-width="${n}" opacity="${l}" />`}let p=`<text x="${t}" y="${i+s/2+14}" text-anchor="middle" font-size="10"
|
|
@@ -13676,7 +13563,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13676
13563
|
</div>
|
|
13677
13564
|
<div class="empty-state">No memory entries to visualize</div>
|
|
13678
13565
|
</div>
|
|
13679
|
-
`;return}let t=this._graphWidth,i=this._graphHeight,a=
|
|
13566
|
+
`;return}let t=this._graphWidth,i=this._graphHeight,a=Xt(this._nodes,t,i),s=this._edges.map(l=>this._renderEdge(l,a)).join(""),r=a.map(l=>this._renderNodeShape(l,l.x,l.y)).join(""),o="";if(this._selectedNode){let l=this._nodes.find(c=>c.id===this._selectedNode);if(l){let c=Ee[l.type]||Ee.episode;o=`
|
|
13680
13567
|
<div class="detail-panel">
|
|
13681
13568
|
<div class="detail-header">
|
|
13682
13569
|
<span class="detail-title">${this._escapeHtml(l.label)}</span>
|
|
@@ -13685,7 +13572,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13685
13572
|
</div>
|
|
13686
13573
|
<div class="detail-body">${this._escapeHtml(l.details||"No details available")}</div>
|
|
13687
13574
|
</div>
|
|
13688
|
-
`}}let n=Object.entries(
|
|
13575
|
+
`}}let n=Object.entries(Ee).map(([,l])=>{let c;return l.shape==="circle"?c=`<div class="legend-circle" style="border-color: ${l.color};"></div>`:l.shape==="square"?c=`<div class="legend-square" style="border-color: ${l.color};"></div>`:c=`<div class="legend-diamond" style="border-color: ${l.color};"></div>`,`<div class="legend-item">
|
|
13689
13576
|
<div class="legend-shape">${c}</div>
|
|
13690
13577
|
<span>${l.label}</span>
|
|
13691
13578
|
</div>`}).join("");e.innerHTML=`
|
|
@@ -13703,7 +13590,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13703
13590
|
</div>
|
|
13704
13591
|
<div class="legend">${n}</div>
|
|
13705
13592
|
</div>
|
|
13706
|
-
`,this._bindEvents()}};customElements.get("loki-memory-graph")||customElements.define("loki-memory-graph",
|
|
13593
|
+
`,this._bindEvents()}};customElements.get("loki-memory-graph")||customElements.define("loki-memory-graph",Ce);var Qe={planning:{color:"var(--loki-blue, #2F71E3)",label:"Planning"},building:{color:"var(--loki-green, #1FC5A8)",label:"Building"},implementation:{color:"var(--loki-green, #1FC5A8)",label:"Building"},testing:{color:"var(--loki-purple, #553DE9)",label:"Testing"},review:{color:"var(--loki-yellow, #D4A03C)",label:"Review"},overhead:{color:"var(--loki-text-muted, #939084)",label:"Overhead"}},Se=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._phases=[],this._budget=null,this._totalCost=0,this._hoveredPhase=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:1e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/cost/breakdown");this._phases=e.phases||[],this._budget=e.budget_usd||null,this._totalCost=e.total_usd||this._phases.reduce((t,i)=>t+(i.cost_usd||0),0)}catch{this._phases.length===0&&(this._phases=this._getDemoData(),this._budget=10,this._totalCost=this._phases.reduce((e,t)=>e+t.cost_usd,0))}this.render()}_getDemoData(){return[{phase:"planning",cost_usd:.85,tokens:12400},{phase:"building",cost_usd:3.2,tokens:68500},{phase:"testing",cost_usd:1.45,tokens:31200},{phase:"review",cost_usd:.9,tokens:18800},{phase:"overhead",cost_usd:.35,tokens:5600}]}_formatCost(e){return e==null?"--":"$"+e.toFixed(2)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_bindEvents(){this.shadowRoot.querySelectorAll(".waterfall-bar").forEach(t=>{t.addEventListener("mouseenter",()=>{this._hoveredPhase=t.dataset.phase,this._updateTooltip(t)}),t.addEventListener("mouseleave",()=>{this._hoveredPhase=null,this._hideTooltip()})})}_updateTooltip(e){let t=this.shadowRoot.querySelector(".tooltip");if(!t)return;let i=this._phases.find(o=>o.phase===this._hoveredPhase);if(!i)return;let a=Qe[i.phase]||{label:i.phase};t.innerHTML=`<strong>${a.label}</strong>: ${this._formatCost(i.cost_usd)}`,t.style.display="block";let s=e.getBoundingClientRect(),r=this.shadowRoot.querySelector(".chart-area").getBoundingClientRect();t.style.left=s.left-r.left+s.width/2+"px",t.style.top=s.top-r.top-30+"px"}_hideTooltip(){let e=this.shadowRoot.querySelector(".tooltip");e&&(e.style.display="none")}_getStyles(){return`
|
|
13707
13594
|
:host {
|
|
13708
13595
|
display: block;
|
|
13709
13596
|
}
|
|
@@ -13893,7 +13780,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13893
13780
|
</div>
|
|
13894
13781
|
<div class="empty-state">Cost details will appear once a build starts running.</div>
|
|
13895
13782
|
</div>
|
|
13896
|
-
`;return}let t=Math.max(...this._phases.map(l=>l.cost_usd||0),.01),i=160,a=this._budget?Math.max(t,this._budget):t,s=this._budget?this._budget/a*i:null,r=this._phases.map(l=>{let c=
|
|
13783
|
+
`;return}let t=Math.max(...this._phases.map(l=>l.cost_usd||0),.01),i=160,a=this._budget?Math.max(t,this._budget):t,s=this._budget?this._budget/a*i:null,r=this._phases.map(l=>{let c=Qe[l.phase]||{color:"var(--loki-text-muted)",label:l.phase},p=(l.cost_usd||0)/a*i,h=this._hoveredPhase===l.phase;return`
|
|
13897
13784
|
<div class="bar-group">
|
|
13898
13785
|
<span class="bar-value">${this._formatCost(l.cost_usd)}</span>
|
|
13899
13786
|
<div class="waterfall-bar" data-phase="${this._escapeHtml(l.phase)}"
|
|
@@ -13905,7 +13792,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13905
13792
|
<div class="budget-line" style="bottom: ${s+40}px;">
|
|
13906
13793
|
<span class="budget-label">Budget: ${this._formatCost(this._budget)}</span>
|
|
13907
13794
|
</div>
|
|
13908
|
-
`:"",n=this._phases.map(l=>{let c=
|
|
13795
|
+
`:"",n=this._phases.map(l=>{let c=Qe[l.phase]||{color:"var(--loki-text-muted)",label:l.phase},p=this._totalCost>0?(l.cost_usd/this._totalCost*100).toFixed(0):0;return`<div class="summary-item">
|
|
13909
13796
|
<div class="summary-dot" style="background: ${c.color};"></div>
|
|
13910
13797
|
<span class="summary-label">${c.label}</span>
|
|
13911
13798
|
<span class="summary-value">${this._formatCost(l.cost_usd)} (${p}%)</span>
|
|
@@ -13927,7 +13814,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13927
13814
|
</div>
|
|
13928
13815
|
</div>
|
|
13929
13816
|
</div>
|
|
13930
|
-
`,this._bindEvents()}};customElements.get("loki-cost-waterfall")||customElements.define("loki-cost-waterfall",
|
|
13817
|
+
`,this._bindEvents()}};customElements.get("loki-cost-waterfall")||customElements.define("loki-cost-waterfall",Se);var Zt={1:{bg:"rgba(212, 160, 60, 0.15)",border:"#D4A03C",label:"1st"},2:{bg:"rgba(147, 144, 132, 0.15)",border:"#939084",label:"2nd"},3:{bg:"rgba(196, 130, 91, 0.15)",border:"#C4825B",label:"3rd"}},Ae=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._agents=[],this._expandedAgent=null,this._api=null,this._pollInterval=null,this._previousRanks={}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:1e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let t=(await this._api._get("/api/v2/agents/leaderboard")).agents||[],i={};t.forEach((a,s)=>{i[a.type||a.name]=s+1}),this._previousRanks={...this._currentRanks||{}},this._currentRanks=i,this._agents=t}catch{this._agents.length===0&&(this._agents=this._getDemoData(),this._currentRanks={},this._agents.forEach((e,t)=>{this._currentRanks[e.type]=t+1}),this._previousRanks={})}this.render()}_getDemoData(){return[{type:"code-generator",name:"Code Generator",tasks:24,quality:9.2,speed:"fast",cost_usd:2.4},{type:"test-writer",name:"Test Writer",tasks:18,quality:9,speed:"fast",cost_usd:1.2},{type:"code-reviewer",name:"Code Reviewer",tasks:15,quality:8.8,speed:"medium",cost_usd:1.8},{type:"architect",name:"Architect",tasks:8,quality:9.5,speed:"slow",cost_usd:3.1},{type:"debugger",name:"Debugger",tasks:12,quality:8.5,speed:"fast",cost_usd:.95},{type:"doc-writer",name:"Documentation",tasks:10,quality:8.3,speed:"fast",cost_usd:.6}]}_getRankChange(e){let t=this._currentRanks?.[e],i=this._previousRanks?.[e];return t==null||i==null?0:i-t}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleAgent(e){this._expandedAgent=this._expandedAgent===e?null:e,this.render()}_bindEvents(){this.shadowRoot.querySelectorAll(".agent-row").forEach(t=>{t.addEventListener("click",()=>{this._toggleAgent(t.dataset.agent)})})}_getQualityColor(e){return e>=9?"var(--loki-green, #1FC5A8)":e>=8?"var(--loki-blue, #2F71E3)":e>=7?"var(--loki-yellow, #D4A03C)":"var(--loki-red, #C45B5B)"}_getSpeedLabel(e){return e==="fast"?{label:"Fast",color:"var(--loki-green, #1FC5A8)"}:e==="medium"?{label:"Medium",color:"var(--loki-yellow, #D4A03C)"}:{label:"Slow",color:"var(--loki-red, #C45B5B)"}}_getStyles(){return`
|
|
13931
13818
|
:host {
|
|
13932
13819
|
display: block;
|
|
13933
13820
|
}
|
|
@@ -14140,7 +14027,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14140
14027
|
</div>
|
|
14141
14028
|
<div class="empty-state">No agent performance data available</div>
|
|
14142
14029
|
</div>
|
|
14143
|
-
`;return}let t=this._agents.map((i,a)=>{let s=a+1,r=
|
|
14030
|
+
`;return}let t=this._agents.map((i,a)=>{let s=a+1,r=Zt[s],o=i.type||i.name,n=this._getRankChange(o),l=this._expandedAgent===o,c=this._getQualityColor(i.quality),p=this._getSpeedLabel(i.speed),h=(i.quality||0)/10*100,v;r?v=`<div class="rank-badge" style="background: ${r.bg}; color: ${r.border};">${s}</div>`:v=`<span class="rank-number" style="color: var(--loki-text-muted);">${s}</span>`;let u="";n>0?u=`<span class="rank-change rank-up">+${n}</span>`:n<0&&(u=`<span class="rank-change rank-down">${n}</span>`);let x=l?`
|
|
14144
14031
|
<div class="agent-detail">
|
|
14145
14032
|
<div class="detail-metric">
|
|
14146
14033
|
<span class="detail-label">Total Cost</span>
|
|
@@ -14158,7 +14045,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14158
14045
|
`:"";return`
|
|
14159
14046
|
<div class="agent-row ${s<=3?"top-3":""}" data-agent="${this._escapeHtml(o)}"
|
|
14160
14047
|
style="${r?"border-left-color: "+r.border+";":""}">
|
|
14161
|
-
<div class="rank-cell">${
|
|
14048
|
+
<div class="rank-cell">${v}${u}</div>
|
|
14162
14049
|
<div class="agent-name-cell">
|
|
14163
14050
|
<span class="agent-name">${this._escapeHtml(i.name||i.type)}</span>
|
|
14164
14051
|
<span class="agent-type">${this._escapeHtml(i.type||"")}</span>
|
|
@@ -14193,7 +14080,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14193
14080
|
${t}
|
|
14194
14081
|
</div>
|
|
14195
14082
|
</div>
|
|
14196
|
-
`,this._bindEvents()}};customElements.get("loki-agent-leaderboard")||customElements.define("loki-agent-leaderboard",
|
|
14083
|
+
`,this._bindEvents()}};customElements.get("loki-agent-leaderboard")||customElements.define("loki-agent-leaderboard",Ae);var ft=50,Te=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._statusLoading=!1,this._statusError=null,this._status=null,this._eventsLoading=!1,this._eventsError=null,this._events=[],this._eventsSource=null,this._eventsCount=0,this._lookupId="",this._lookupLoading=!1,this._lookupError=null,this._lookupResult=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadStatus());break;case"theme":this._applyTheme(),this.render();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_stopPolling(){}async _loadStatus(){this._statusLoading=!0,this._statusError=null,this.render();try{this._status=await this._api.get("/api/managed/status")}catch(e){this._statusError=e&&e.message?e.message:"Failed to load managed status",this._status=null}finally{this._statusLoading=!1}this._status&&this._status.enabled?await this._loadEvents():this.render()}async _loadEvents(e=ft){this._eventsLoading=!0,this._eventsError=null,this.render();try{let t=await this._api.get("/api/managed/events?limit="+encodeURIComponent(e));Array.isArray(t)?(this._events=t,this._eventsCount=t.length,this._eventsSource=null):t&&typeof t=="object"?(this._events=Array.isArray(t.events)?t.events:[],this._eventsCount=typeof t.count=="number"?t.count:this._events.length,this._eventsSource=t.source||null):(this._events=[],this._eventsCount=0,this._eventsSource=null)}catch(t){this._eventsError=t&&t.message?t.message:"Failed to load managed events",this._events=[],this._eventsCount=0,this._eventsSource=null}finally{this._eventsLoading=!1,this.render()}}async _lookupMemoryVersion(){let e=(this._lookupId||"").trim();if(!e){this._lookupError="Enter a memory ID to look up",this._lookupResult=null,this.render();return}this._lookupLoading=!0,this._lookupError=null,this._lookupResult=null,this.render();try{let t="/api/managed/memory_versions/"+encodeURIComponent(e);this._lookupResult=await this._api.get(t)}catch(t){this._lookupError=t&&t.message?t.message:"Failed to load memory versions",this._lookupResult=null}finally{this._lookupLoading=!1,this.render()}}_onLookupInput(e){this._lookupId=e&&e.target?e.target.value:""}_onLookupKeyDown(e){e&&e.key==="Enter"&&(e.preventDefault(),this._lookupMemoryVersion())}_attachEventHandlers(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector("#refresh-status-btn");t&&t.addEventListener("click",()=>this._loadStatus());let i=e.querySelector("#refresh-events-btn");i&&i.addEventListener("click",()=>this._loadEvents());let a=e.querySelector("#lookup-input");a&&(a.addEventListener("input",r=>this._onLookupInput(r)),a.addEventListener("keydown",r=>this._onLookupKeyDown(r)));let s=e.querySelector("#lookup-btn");s&&s.addEventListener("click",()=>this._lookupMemoryVersion())}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_formatTimestamp(e){if(!e)return"";let t;return typeof e=="number"?t=new Date(e>1e12?e:e*1e3):t=new Date(e),Number.isNaN(t.getTime())?String(e):t.toISOString().replace("T"," ").replace(/\.\d+Z$/,"Z")}_renderStatusSection(){if(this._statusLoading)return'<div class="status-row muted">Loading managed memory status...</div>';if(this._statusError)return`
|
|
14197
14084
|
<div class="error-banner" role="alert">
|
|
14198
14085
|
<strong>Status error:</strong>
|
|
14199
14086
|
<span>${this._escapeHtml(this._statusError)}</span>
|
|
@@ -14572,7 +14459,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14572
14459
|
${t?`
|
|
14573
14460
|
<div class="section">
|
|
14574
14461
|
<div class="panel-header">
|
|
14575
|
-
<h3 class="section-title">Recent events (limit ${
|
|
14462
|
+
<h3 class="section-title">Recent events (limit ${ft})</h3>
|
|
14576
14463
|
<button id="refresh-events-btn" class="btn" type="button">Refresh events</button>
|
|
14577
14464
|
</div>
|
|
14578
14465
|
${this._renderEventsSection()}
|
|
@@ -14584,7 +14471,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14584
14471
|
</div>
|
|
14585
14472
|
`:this._statusError?"":this._renderDisabledNotice()}
|
|
14586
14473
|
</div>
|
|
14587
|
-
`,this._attachEventHandlers()}};customElements.get("loki-managed-memory-panel")||customElements.define("loki-managed-memory-panel",
|
|
14474
|
+
`,this._attachEventHandlers()}};customElements.get("loki-managed-memory-panel")||customElements.define("loki-managed-memory-panel",Te);var Le=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._items=[],this._loading=!1,this._error=null,this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._ensureMarkdownStyles(),this._setupApi(),this._loadList(),this._poll=b({loadFn:()=>this._loadList(),intervalMs:1e4,element:this,immediate:!1})}disconnectedCallback(){super.disconnectedCallback(),this._poll&&(this._poll.stop(),this._poll=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadList()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||(typeof window<"u"?window.location.origin:"");this._api=m({baseUrl:e})}async _loadList(){this._loading=!0,this._error=null;try{let e=await this._api.get("/api/escalations");this._items=Array.isArray(e&&e.escalations)?e.escalations:[]}catch(e){this._error=e&&e.message?e.message:String(e),this._items=[]}finally{this._loading=!1,this.render()}}async _openFile(e){this._activeFile=e,this._activeBody=null,this._activeBodyError=null,this.render();try{let t=(this._api.baseUrl||"")+"/api/escalations/"+encodeURIComponent(e),i=await fetch(t,{credentials:"include"});if(!i.ok)throw new Error("HTTP "+i.status);this._activeBody=await i.text()}catch(t){this._activeBodyError=t&&t.message?t.message:String(t)}this.render()}_closeFile(){this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this.render()}_formatSize(e){return typeof e!="number"?"--":e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":(e/(1024*1024)).toFixed(1)+" MB"}_formatDate(e){if(!e)return"--";try{let t=new Date(e);return isNaN(t.getTime())?e:t.toLocaleString()}catch{return e}}_ensureMarkdownStyles(){if(typeof document>"u"||!document.head||document.getElementById("loki-markdown-styles"))return;let e=document.createElement("style");e.id="loki-markdown-styles",e.textContent=L,document.head.appendChild(e)}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}render(){let e=this.shadowRoot||this;if(!e)return;let t=`
|
|
14588
14475
|
<style>
|
|
14589
14476
|
:host { display: block; }
|
|
14590
14477
|
.esc-wrapper {
|
|
@@ -14642,10 +14529,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14642
14529
|
color: var(--text-secondary, #36342E);
|
|
14643
14530
|
font-size: 0.75rem;
|
|
14644
14531
|
}
|
|
14532
|
+
/* Scroll chrome for the handoff viewer. The rendered markdown is styled
|
|
14533
|
+
by MARKDOWN_STYLES (.md-body), injected once into document.head. The
|
|
14534
|
+
monospace/pre-wrap below only applies to the plain-text loading line
|
|
14535
|
+
(a bare .esc-body without .md-body). */
|
|
14645
14536
|
.esc-body {
|
|
14646
|
-
font-family: 'JetBrains Mono', monospace;
|
|
14647
|
-
font-size: 0.78rem;
|
|
14648
|
-
white-space: pre-wrap;
|
|
14649
14537
|
word-wrap: break-word;
|
|
14650
14538
|
max-height: 480px;
|
|
14651
14539
|
overflow: auto;
|
|
@@ -14653,8 +14541,13 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14653
14541
|
padding: 10px;
|
|
14654
14542
|
border-radius: 4px;
|
|
14655
14543
|
}
|
|
14544
|
+
.esc-body:not(.md-body) {
|
|
14545
|
+
font-family: 'JetBrains Mono', monospace;
|
|
14546
|
+
font-size: 0.78rem;
|
|
14547
|
+
white-space: pre-wrap;
|
|
14548
|
+
}
|
|
14656
14549
|
</style>
|
|
14657
|
-
`,i="";this._loading&&this._items.length===0?i='<div class="esc-empty">Loading escalations...</div>':this._error?i='<div class="esc-error">Failed to load escalations: '+this._escapeHtml(this._error)+"</div>":!this._items||this._items.length===0?i='<div class="esc-empty">No handoff notes yet. If a build needs your attention, its notes will appear here.</div>':i='<div class="esc-list">'+this._items.map(n=>{let l=this._escapeHtml(n.filename||""),c=this._escapeHtml(this._formatSize(n.size_bytes)),p=this._escapeHtml(this._formatDate(n.modified_at));return'<div class="esc-item" data-filename="'+l+'"><span class="esc-name">'+l+'</span><span class="esc-meta">'+c+" · "+p+"</span></div>"}).join("")+"</div>";let a="";if(this._activeFile){let o=this._escapeHtml(this._activeFile),n;this._activeBodyError?n='<div class="esc-error">Failed to load: '+this._escapeHtml(this._activeBodyError)+"</div>":this._activeBody===null?n='<div class="esc-body">Loading '+o+"...</div>":n='<div class="esc-body">'+
|
|
14550
|
+
`,i="";this._loading&&this._items.length===0?i='<div class="esc-empty">Loading escalations...</div>':this._error?i='<div class="esc-error">Failed to load escalations: '+this._escapeHtml(this._error)+"</div>":!this._items||this._items.length===0?i='<div class="esc-empty">No handoff notes yet. If a build needs your attention, its notes will appear here.</div>':i='<div class="esc-list">'+this._items.map(n=>{let l=this._escapeHtml(n.filename||""),c=this._escapeHtml(this._formatSize(n.size_bytes)),p=this._escapeHtml(this._formatDate(n.modified_at));return'<div class="esc-item" data-filename="'+l+'"><span class="esc-name">'+l+'</span><span class="esc-meta">'+c+" · "+p+"</span></div>"}).join("")+"</div>";let a="";if(this._activeFile){let o=this._escapeHtml(this._activeFile),n;this._activeBodyError?n='<div class="esc-error">Failed to load: '+this._escapeHtml(this._activeBodyError)+"</div>":this._activeBody===null?n='<div class="esc-body">Loading '+o+"...</div>":n='<div class="esc-body md-body">'+C(this._activeBody)+"</div>",a='<div class="esc-viewer"><div class="esc-viewer-header"><span class="esc-name">'+o+'</span><button class="esc-close-btn" data-action="close">Close</button></div>'+n+"</div>"}e.innerHTML=t+'<div class="esc-wrapper"><div class="esc-explain">Handoff/escalation documents written under .loki/escalations/. Click an entry to view its contents.</div>'+i+a+"</div>",e.querySelectorAll(".esc-item").forEach(o=>{o.addEventListener("click",()=>{let n=o.getAttribute("data-filename");n&&this._openFile(n)})});let r=e.querySelector('.esc-close-btn[data-action="close"]');r&&r.addEventListener("click",()=>this._closeFile())}};typeof customElements<"u"&&!customElements.get("loki-escalations")&&customElements.define("loki-escalations",Le);var De=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._transcripts=[],this._hookEvents=[],this._loading=!1,this._error=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._load(),this._poll=b({loadFn:()=>this._load(),intervalMs:3e4,element:this,immediate:!1})}disconnectedCallback(){super.disconnectedCallback(),this._poll&&(this._poll.stop(),this._poll=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._load()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||(typeof window<"u"?window.location.origin:"");this._api=m({baseUrl:e})}async _load(){this._loading=!0,this._error=null;try{let e=await this._api.get("/api/council/transcripts?limit=10");this._transcripts=Array.isArray(e&&e.transcripts)?e.transcripts:[]}catch(e){this._error=e&&e.message?e.message:String(e),this._transcripts=[]}try{let e=await this._api.get("/api/council/transcripts?limit=20&type_prefix=claude_hook_");this._hookEvents=Array.isArray(e&&e.hook_events)?e.hook_events:[]}catch{this._hookEvents=[]}finally{this._loading=!1,this.render()}}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_formatTimestamp(e){if(!e)return"--";try{let t=new Date(e);return isNaN(t.getTime())?e:t.toLocaleString()}catch{return e}}_truncate(e,t){if(!e)return"";let i=String(e);return i.length>t?i.slice(0,t)+"...":i}_verdictBadgeHtml(e){let t=String(e||"").toUpperCase();return t==="APPROVE"?'<span class="ct-badge ct-badge-approve">APPROVE</span>':t==="REJECT"?'<span class="ct-badge ct-badge-reject">REJECT</span>':t==="CANNOT_VALIDATE"?'<span class="ct-badge ct-badge-cannot">CANNOT_VALIDATE</span>':'<span class="ct-badge ct-badge-unknown">'+this._escapeHtml(t||"UNKNOWN")+"</span>"}_outcomeBadgeHtml(e){let t=String(e||"").toUpperCase();return t==="APPROVED"?'<span class="ct-badge ct-badge-approve">APPROVED</span>':t==="REJECTED"?'<span class="ct-badge ct-badge-reject">REJECTED</span>':t==="BLOCKED_BY_GATE"?'<span class="ct-badge ct-badge-blocked">BLOCKED BY GATE</span>':'<span class="ct-badge ct-badge-unknown">'+this._escapeHtml(t||"UNKNOWN")+"</span>"}_voterRowHtml(e,t){let i=e.is_contrarian===!0,a=i&&t===!0,s="ct-voter-row";i&&(s+=" ct-voter-contrarian"),a&&(s+=" ct-voter-flipped");let r=this._escapeHtml(e.name||"unknown"),o=this._verdictBadgeHtml(e.verdict),n=this._escapeHtml(this._truncate(e.reasoning,300)),l="",c="";a?(l='<span class="ct-badge ct-badge-override">OVERRIDE</span>',c=`<div class="ct-flip-caption">Devil's Advocate flipped this outcome</div>`):i&&e.triggered&&(l=`<span class="ct-badge ct-badge-da">DEVIL'S ADVOCATE</span>`);let p="";i&&Array.isArray(e.challenges)&&e.challenges.length>0&&(p='<ul class="ct-challenges">'+e.challenges.map(u=>"<li>"+this._escapeHtml(String(u))+"</li>").join("")+"</ul>");let h="";return Array.isArray(e.issues)&&e.issues.length>0&&(h='<ul class="ct-issues">'+e.issues.map(u=>{let x=this._escapeHtml(u.severity||""),k=this._escapeHtml(u.description||"");return'<li><span class="ct-issue-sev ct-issue-sev-'+x.toLowerCase()+'">'+x+"</span> "+k+"</li>"}).join("")+"</ul>"),'<div class="'+s+'"><div class="ct-voter-header"><span class="ct-voter-name">'+r+"</span>"+o+l+"</div>"+(n?'<div class="ct-voter-reason">'+n+"</div>":"")+p+h+c+"</div>"}_transcriptCardHtml(e){let t=this._escapeHtml(String(e.iteration||"--")),i=this._escapeHtml(this._formatTimestamp(e.timestamp)),a=this._escapeHtml(this._truncate(e.task_or_prd,200)),s=this._outcomeBadgeHtml(e.outcome),r=Array.isArray(e.voters)?e.voters:[],o=r.filter(u=>!u.is_contrarian),n=r.filter(u=>u.is_contrarian),l=o.map(u=>this._voterRowHtml(u,!1)).join(""),c="";e.contrarian_triggered&&(c='<div class="ct-contrarian-section"><div class="ct-section-label">Anti-Sycophancy Check</div>'+n.map(x=>this._voterRowHtml(x,e.contrarian_flipped)).join("")+"</div>");let p=typeof e.approve_count=="number"?e.approve_count:"--",h=typeof e.reject_count=="number"?e.reject_count:"--",v=typeof e.threshold=="number"?e.threshold:"--";return'<div class="ct-card"><div class="ct-card-header"><div class="ct-card-meta"><span class="ct-iter-label">Iteration '+t+'</span><span class="ct-ts">'+i+"</span></div>"+s+"</div>"+(a?'<div class="ct-prd-preview">'+a+"</div>":"")+'<div class="ct-tally">Approve: '+p+" · Reject: "+h+" · Threshold: "+v+'</div><div class="ct-voters">'+l+"</div>"+c+"</div>"}render(){let e=this.shadowRoot||this;if(!e)return;let t=`
|
|
14658
14551
|
<style>
|
|
14659
14552
|
:host { display: block; margin-top: 24px; }
|
|
14660
14553
|
.ct-wrapper {
|
|
@@ -14823,7 +14716,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14823
14716
|
.ct-badge-da { background: #fdf3d4; color: #8a6c0e; }
|
|
14824
14717
|
.ct-badge-unknown { background: var(--bg-secondary, #F8F4F0); color: var(--text-muted, #939084); }
|
|
14825
14718
|
</style>
|
|
14826
|
-
`,i="";this._loading&&this._transcripts.length===0?i='<div class="ct-empty">Loading council transcripts...</div>':this._error?i='<div class="ct-error">Failed to load transcripts: '+this._escapeHtml(this._error)+"</div>":!this._transcripts||this._transcripts.length===0?i='<div class="ct-empty">No review rounds recorded yet. Transcripts appear after the first completion vote.</div>':i='<div class="ct-list">'+this._transcripts.map(s=>this._transcriptCardHtml(s)).join("")+"</div>",e.innerHTML=t+'<div class="ct-wrapper"><h3 class="ct-heading">Council Transcripts</h3><div class="ct-explain">Per-iteration voting records from .loki/council/transcripts/. Polls every 30 seconds.</div>'+i+this._hookEventsHtml()+"</div>"}_hookEventsHtml(){let e=Array.isArray(this._hookEvents)?this._hookEvents:[],t;return e.length===0?t='<div class="ct-empty">No live tool activity yet -- Claude hook events stream here while a run is active.</div>':t='<div class="ct-voters">'+e.slice(0,20).map(a=>{let s=this._escapeHtml(a.type||a.event||"event"),r=this._escapeHtml(this._formatTimestamp(a.timestamp||a.ts)),o=this._escapeHtml(this._truncate(a.tool||a.message||a.summary||(a.data?JSON.stringify(a.data):""),120));return'<div class="ct-voter-row"><span class="ct-iter-label">'+s+'</span> <span class="ct-ts">'+r+"</span>"+(o?'<div class="ct-prd-preview">'+o+"</div>":"")+"</div>"}).join("")+"</div>",'<h3 class="ct-heading" style="margin-top:24px;">Live Tool Activity</h3><div class="ct-explain">Claude hook events (PreToolUse / PostToolUse / Stop) streamed from .loki/events.jsonl. Lets you watch background tool calls as they run.</div>'+t}};typeof customElements<"u"&&!customElements.get("loki-council-transcripts")&&customElements.define("loki-council-transcripts",
|
|
14719
|
+
`,i="";this._loading&&this._transcripts.length===0?i='<div class="ct-empty">Loading council transcripts...</div>':this._error?i='<div class="ct-error">Failed to load transcripts: '+this._escapeHtml(this._error)+"</div>":!this._transcripts||this._transcripts.length===0?i='<div class="ct-empty">No review rounds recorded yet. Transcripts appear after the first completion vote.</div>':i='<div class="ct-list">'+this._transcripts.map(s=>this._transcriptCardHtml(s)).join("")+"</div>",e.innerHTML=t+'<div class="ct-wrapper"><h3 class="ct-heading">Council Transcripts</h3><div class="ct-explain">Per-iteration voting records from .loki/council/transcripts/. Polls every 30 seconds.</div>'+i+this._hookEventsHtml()+"</div>"}_hookEventsHtml(){let e=Array.isArray(this._hookEvents)?this._hookEvents:[],t;return e.length===0?t='<div class="ct-empty">No live tool activity yet -- Claude hook events stream here while a run is active.</div>':t='<div class="ct-voters">'+e.slice(0,20).map(a=>{let s=this._escapeHtml(a.type||a.event||"event"),r=this._escapeHtml(this._formatTimestamp(a.timestamp||a.ts)),o=this._escapeHtml(this._truncate(a.tool||a.message||a.summary||(a.data?JSON.stringify(a.data):""),120));return'<div class="ct-voter-row"><span class="ct-iter-label">'+s+'</span> <span class="ct-ts">'+r+"</span>"+(o?'<div class="ct-prd-preview">'+o+"</div>":"")+"</div>"}).join("")+"</div>",'<h3 class="ct-heading" style="margin-top:24px;">Live Tool Activity</h3><div class="ct-explain">Claude hook events (PreToolUse / PostToolUse / Stop) streamed from .loki/events.jsonl. Lets you watch background tool calls as they run.</div>'+t}};typeof customElements<"u"&&!customElements.get("loki-council-transcripts")&&customElements.define("loki-council-transcripts",De);var ei=[{id:"overview",label:"Overview"},{id:"architecture",label:"Architecture"},{id:"modules",label:"Key Modules"},{id:"data-flow",label:"Data Flow"},{id:"ask",label:"Ask"}],ze=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._activeTab="overview",this._loading=!1,this._error=null,this._api=null,this._meta=null,this._metaPromise=null,this._sectionCache={},this._sectionState={},this._question="",this._answer=null,this._asking=!1,this._askError=null,this._mermaid=null,this._mermaidPromise=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadMeta()}disconnectedCallback(){super.disconnectedCallback&&super.disconnectedCallback(),this._disconnected=!0}attributeChangedCallback(e,t,i){e==="api-url"&&this._api&&(this._api.baseUrl=i)}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_loadMeta(){return this._loading=!0,this._error=null,this.render(),this._metaPromise=(async()=>{try{this._meta=await this._api._get("/api/wiki")}catch(e){this._error=e&&e.message?e.message:"Failed to load wiki"}finally{this._loading=!1,this.render()}})(),this._metaPromise}async _loadSection(e){if(this._sectionCache[e])return this._sectionState[e]=this._sectionCache[e].error?"error":"loaded",this._sectionCache[e];this._sectionState[e]="loading";try{let t=await this._api._get(`/api/wiki/${encodeURIComponent(e)}`);return this._sectionCache[e]=t,this._sectionState[e]=t&&t.error?"error":"loaded",t}catch(t){let i={error:t&&t.message||"load failed"};return this._sectionCache[e]=i,this._sectionState[e]="error",i}}async _selectTab(e){if(this._activeTab=e,e!=="architecture"&&e!=="modules"&&e!=="data-flow"){this.render();return}if(this._sectionCache[e]){this.render();return}if(this._sectionState[e]="loading",this.render(),this._metaPromise)try{await this._metaPromise}catch{}if(!(this._disconnected||this._activeTab!==e)){if(!this._meta||!this._meta.generated){delete this._sectionState[e],this.render();return}await this._loadSection(e),!(this._disconnected||this._activeTab!==e)&&this.render()}}_ensureMermaid(){return this._mermaid?Promise.resolve(this._mermaid):this._mermaidPromise?this._mermaidPromise:(this._mermaidPromise=(async()=>{try{if(typeof window<"u"&&window.mermaid)return this._mermaid=window.mermaid,this._mermaid;if(typeof window>"u"||typeof document>"u")return null;let t=`${this._api&&this._api.baseUrl||window.location.origin}/assets/mermaid.min.js`;return await new Promise((i,a)=>{let s=document.querySelector("script[data-loki-mermaid]");if(s){s.addEventListener("load",i,{once:!0}),s.addEventListener("error",a,{once:!0}),window.mermaid&&i();return}let r=document.createElement("script");r.src=t,r.async=!0,r.setAttribute("data-loki-mermaid","1"),r.addEventListener("load",i,{once:!0}),r.addEventListener("error",()=>a(new Error("mermaid load failed")),{once:!0}),document.head.appendChild(r)}),this._mermaid=typeof window<"u"&&window.mermaid||null,this._mermaid}catch{return null}})(),this._mermaidPromise)}async _maybeRenderDiagram(e){let t=this._sectionCache[e],i=this._diagramSource(t);if(!i)return;let a;try{a=await this._ensureMermaid()}catch{a=null}if(!(!a||this._disconnected||this._activeTab!==e))try{a.initialize({startOnLoad:!1,securityLevel:"strict",theme:this._mermaidTheme(),flowchart:{htmlLabels:!1,useMaxWidth:!0},deterministicIds:!0}),typeof a.parse=="function"&&await a.parse(i);let s=`wiki-mmd-${e}-${Date.now()}`,r=await a.render(s,i),o=r&&(r.svg||r);if(typeof o!="string"||o.indexOf("<svg")===-1||this._disconnected||this._activeTab!==e||!this.shadowRoot)return;let n=this.shadowRoot.getElementById("wiki-diagram");n&&(n.innerHTML=o)}catch{}}_mermaidTheme(){return(this.getAttribute("theme")||typeof document<"u"&&document.documentElement.getAttribute("data-loki-theme")||"").toLowerCase().includes("dark")?"dark":"neutral"}async _ask(){let e=(this._question||"").trim();if(e){this._asking=!0,this._askError=null,this._answer=null,this.render();try{this._answer=await this._api._post("/api/wiki/ask",{question:e},{timeout:2e5})}catch(t){this._askError=t&&t.message?t.message:"Ask failed"}finally{this._asking=!1,this.render()}}}_esc(e){return String(e??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}_renderCitations(e){return!e||!e.length?"":`<div class="cites"><strong>Sources:</strong><ul>${e.map(i=>`<li><code>${this._esc(i.file)}:${this._esc(i.line)}</code></li>`).join("")}</ul></div>`}_renderNotGenerated(){return`<div class="es">
|
|
14827
14720
|
<div class="es-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg></div>
|
|
14828
14721
|
<div class="es-title">No wiki generated yet</div>
|
|
14829
14722
|
<div class="es-desc">Generate a cited codebase wiki to browse architecture, modules, and data flow. Every section links to real file:line locations.</div>
|
|
@@ -14841,12 +14734,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14841
14734
|
</div>`}_renderSection(e){if(this._sectionState[e]==="loading")return'<div class="es-loading"><span class="es-spinner"></span> Loading section...</div>';if(!this._meta||!this._meta.generated)return this._renderNotGenerated();let i=this._sectionCache[e];return i?i.error?this._renderError(i.error):`<div class="section">
|
|
14842
14735
|
<h3>${this._esc(i.title)}</h3>
|
|
14843
14736
|
${this._renderDiagram(e,i)}
|
|
14844
|
-
<
|
|
14737
|
+
<div class="body md-body">${C(i.body)}</div>
|
|
14845
14738
|
${this._renderCitations(i.citations)}
|
|
14846
14739
|
</div>`:'<div class="es-loading"><span class="es-spinner"></span> Loading section...</div>'}_diagramSource(e){let t=e&&typeof e.diagram=="string"?e.diagram.trim():"";if(!t)return"";let i=t.match(/^```(?:mermaid)?\s*\n([\s\S]*?)\n```$/);return i&&(t=i[1].trim()),t}_renderDiagram(e,t){let i=this._diagramSource(t);return i?`<div class="diagram" id="wiki-diagram" data-section="${this._esc(e)}">
|
|
14847
14740
|
<pre class="diagram-fallback"><code>${this._esc(i)}</code></pre>
|
|
14848
14741
|
</div>`:""}_renderAsk(){let e="";if(this._asking)e='<div class="es-loading"><span class="es-spinner"></span> Searching the codebase...</div>';else if(this._askError)e=`<div class="es-inline-error">${this._esc(this._askError)}</div>`;else if(this._answer){let t=this._answer.note?`<p class="dim">${this._esc(this._answer.note)}</p>`:"";e=`<div class="answer">
|
|
14849
|
-
<
|
|
14742
|
+
<div class="body md-body">${C(this._answer.answer||"")}</div>
|
|
14850
14743
|
${t}
|
|
14851
14744
|
${this._renderCitations(this._answer.citations)}
|
|
14852
14745
|
</div>`}return`<div class="ask">
|
|
@@ -14862,10 +14755,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14862
14755
|
<div class="es-title">Couldn't load wiki</div>
|
|
14863
14756
|
<div class="es-desc">${this._esc(e)}</div>
|
|
14864
14757
|
<button class="es-cta" id="wiki-retry-btn">Retry</button>
|
|
14865
|
-
</div>`}_renderBody(){if(this._loading)return'<div class="es-loading"><span class="es-spinner"></span> Loading wiki...</div>';if(this._error)return this._renderError(this._error);switch(this._activeTab){case"overview":return this._renderOverview();case"architecture":return this._renderSection("architecture");case"modules":return this._renderSection("modules");case"data-flow":return this._renderSection("data-flow");case"ask":return this._renderAsk();default:return this._renderOverview()}}render(){if(!this.shadowRoot)return;let e=
|
|
14758
|
+
</div>`}_renderBody(){if(this._loading)return'<div class="es-loading"><span class="es-spinner"></span> Loading wiki...</div>';if(this._error)return this._renderError(this._error);switch(this._activeTab){case"overview":return this._renderOverview();case"architecture":return this._renderSection("architecture");case"modules":return this._renderSection("modules");case"data-flow":return this._renderSection("data-flow");case"ask":return this._renderAsk();default:return this._renderOverview()}}render(){if(!this.shadowRoot)return;let e=ei.map(o=>`<button class="tab ${o.id===this._activeTab?"active":""}"
|
|
14866
14759
|
data-tab="${o.id}">${this._esc(o.label)}</button>`).join("");this.shadowRoot.innerHTML=`
|
|
14867
14760
|
<style>
|
|
14868
14761
|
${this.getBaseStyles()}
|
|
14762
|
+
${L}
|
|
14869
14763
|
:host { display: block; }
|
|
14870
14764
|
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--loki-border);
|
|
14871
14765
|
margin-bottom: 12px; flex-wrap: wrap; }
|
|
@@ -14874,9 +14768,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14874
14768
|
border-bottom: 2px solid transparent; transition: color 0.15s ease; }
|
|
14875
14769
|
.tab:hover { color: var(--loki-text-primary); }
|
|
14876
14770
|
.tab.active { color: var(--loki-accent); border-bottom-color: var(--loki-accent); }
|
|
14877
|
-
|
|
14878
|
-
|
|
14879
|
-
|
|
14771
|
+
/* Chrome for the rendered section / answer document. The markdown itself
|
|
14772
|
+
is styled by MARKDOWN_STYLES (.md-body), injected into this root. */
|
|
14773
|
+
.body { word-break: break-word;
|
|
14774
|
+
background: var(--loki-bg-secondary);
|
|
14880
14775
|
padding: 14px; border-radius: var(--loki-radius-lg, 5px);
|
|
14881
14776
|
border: 1px solid var(--loki-border); }
|
|
14882
14777
|
.cites { margin-top: 10px; font-size: 12px; color: var(--loki-text-secondary); }
|
|
@@ -14978,7 +14873,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14978
14873
|
</style>
|
|
14979
14874
|
<div class="tabs">${e}</div>
|
|
14980
14875
|
<div class="content">${this._renderBody()}</div>
|
|
14981
|
-
`,this.shadowRoot.querySelectorAll(".tab").forEach(o=>{o.addEventListener("click",()=>this._selectTab(o.dataset.tab))});let t=this.shadowRoot.getElementById("wiki-q");t&&(t.addEventListener("input",o=>{this._question=o.target.value}),t.addEventListener("keydown",o=>{o.key==="Enter"&&this._ask()}));let i=this.shadowRoot.getElementById("wiki-ask-btn");i&&i.addEventListener("click",()=>this._ask());let a=this.shadowRoot.getElementById("wiki-gen-copy");a&&a.addEventListener("click",()=>this._copyGenerateCmd(a));let s=this.shadowRoot.getElementById("wiki-retry-btn");s&&s.addEventListener("click",()=>{this._sectionCache={},this._sectionState={},this._loadMeta()});let r=this._activeTab;(r==="architecture"||r==="data-flow")&&this._sectionCache[r]&&!this._sectionCache[r].error&&this.shadowRoot.getElementById("wiki-diagram")&&this._maybeRenderDiagram(r)}_copyGenerateCmd(e){let t="loki wiki generate",i=()=>{let a=e.innerHTML;e.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',setTimeout(()=>{e.innerHTML=a},1500)};navigator.clipboard&&navigator.clipboard.writeText&&navigator.clipboard.writeText(t).then(i).catch(()=>{})}};customElements.get("loki-wiki-browser")||customElements.define("loki-wiki-browser",
|
|
14876
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(o=>{o.addEventListener("click",()=>this._selectTab(o.dataset.tab))});let t=this.shadowRoot.getElementById("wiki-q");t&&(t.addEventListener("input",o=>{this._question=o.target.value}),t.addEventListener("keydown",o=>{o.key==="Enter"&&this._ask()}));let i=this.shadowRoot.getElementById("wiki-ask-btn");i&&i.addEventListener("click",()=>this._ask());let a=this.shadowRoot.getElementById("wiki-gen-copy");a&&a.addEventListener("click",()=>this._copyGenerateCmd(a));let s=this.shadowRoot.getElementById("wiki-retry-btn");s&&s.addEventListener("click",()=>{this._sectionCache={},this._sectionState={},this._loadMeta()});let r=this._activeTab;(r==="architecture"||r==="data-flow")&&this._sectionCache[r]&&!this._sectionCache[r].error&&this.shadowRoot.getElementById("wiki-diagram")&&this._maybeRenderDiagram(r)}_copyGenerateCmd(e){let t="loki wiki generate",i=()=>{let a=e.innerHTML;e.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',setTimeout(()=>{e.innerHTML=a},1500)};navigator.clipboard&&navigator.clipboard.writeText&&navigator.clipboard.writeText(t).then(i).catch(()=>{})}};customElements.get("loki-wiki-browser")||customElements.define("loki-wiki-browser",ze);var bt={prd:"PRD file",spec:"Generated spec",issue:"GitHub issue",brief:"One-line brief","codebase-analysis":"Codebase analysis",none:"No spec yet",unknown:"Unknown spec"},Re=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._spec=null,this._history=null,this._loading=!1,this._error=null,this._historyError=null,this._historyOpen=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._load()}attributeChangedCallback(e,t,i){e==="api-url"&&this._api&&(this._api.baseUrl=i)}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _load(){this._loading=!0,this._error=null,this.render();try{this._spec=await this._api._get("/api/spec")}catch(e){this._error=e&&e.message?e.message:"Failed to load spec"}finally{this._loading=!1,this.render()}try{let e=await this._api._get("/api/spec/history");this._history=e&&Array.isArray(e.history)?e.history:[]}catch(e){this._historyError=e&&e.message?e.message:"Failed to load history",this._history=[]}this.render()}_esc(e){return String(e??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}_when(e){if(!e)return"unknown time";let t=new Date(e);if(isNaN(t.getTime()))return this._esc(e);try{return t.toLocaleString()}catch{return this._esc(e)}}_typeLabel(e){return bt[e]||bt.unknown}_typeBadge(e){return`<span class="badge badge-${this._esc(e)}">${this._esc(this._typeLabel(e))}</span>`}_renderActive(){if(this._loading)return'<div class="es-loading"><span class="es-spinner"></span> Loading active spec...</div>';if(this._error)return this._renderError(this._error);let e=this._spec;if(!e||!e.type||e.type==="none")return this._renderEmpty();let t=this._typeBadge(e.type),i="",a="";if(e.type==="prd"||e.type==="spec"){e.path&&(i=`<code class="src">${this._esc(e.path)}</code>`);let s=e.content||"";s.trim()?a=`<div class="body md-body">${C(s)}</div>`+(e.truncated?'<p class="dim">Preview truncated -- see the full file on disk.</p>':""):a='<p class="dim">No content available.</p>'}else if(e.type==="issue"){i=e.ref?`<code class="src">${this._esc(e.ref)}</code>`:"";let r=e.title?`<p class="issue-title">${this._esc(e.title)}</p>`:"",o=(e.body||"").trim()?`<div class="body md-body">${C(e.body)}</div>`+(e.truncated?'<p class="dim">Preview truncated.</p>':""):"";a=`${r}${o}`}else if(e.type==="brief"){let s=(e.text||"").trim();a=s?`<pre class="body brief">${this._esc(s)}</pre>`+(e.truncated?'<p class="dim">Preview truncated.</p>':""):'<p class="dim">No brief recorded.</p>'}else e.type==="codebase-analysis"?a='<p class="dim">No explicit spec. Loki is building from an analysis of the existing codebase.</p>':a='<p class="dim">The spec source could not be resolved.</p>';return`<div class="active">
|
|
14982
14877
|
<div class="active-head">
|
|
14983
14878
|
<span class="active-label">Building from</span>
|
|
14984
14879
|
${t}
|
|
@@ -15008,6 +14903,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
15008
14903
|
</div>`}render(){if(!this.shadowRoot)return;this.shadowRoot.innerHTML=`
|
|
15009
14904
|
<style>
|
|
15010
14905
|
${this.getBaseStyles()}
|
|
14906
|
+
${L}
|
|
15011
14907
|
:host { display: block; }
|
|
15012
14908
|
.active { background: var(--loki-bg-secondary); border: 1px solid var(--loki-border);
|
|
15013
14909
|
border-radius: var(--loki-radius-lg, 5px); padding: 16px; }
|
|
@@ -15024,12 +14920,17 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
15024
14920
|
.src { font-family: var(--loki-font-mono, monospace); font-size: 12px;
|
|
15025
14921
|
background: var(--loki-bg-tertiary); color: var(--loki-text-secondary);
|
|
15026
14922
|
padding: 2px 7px; border-radius: 3px; word-break: break-all; }
|
|
15027
|
-
|
|
15028
|
-
|
|
14923
|
+
/* Scroll chrome for the rendered spec/issue document. The markdown
|
|
14924
|
+
itself is styled by MARKDOWN_STYLES (.md-body), injected below. */
|
|
14925
|
+
.body { word-break: break-word;
|
|
15029
14926
|
max-height: 320px; overflow: auto;
|
|
15030
|
-
background: var(--loki-bg-tertiary);
|
|
14927
|
+
background: var(--loki-bg-tertiary);
|
|
15031
14928
|
padding: 12px; border-radius: var(--loki-radius-md, 4px);
|
|
15032
14929
|
border: 1px solid var(--loki-border); margin: 0; }
|
|
14930
|
+
/* The brief is a one-line plain-text spec, kept as a preformatted block. */
|
|
14931
|
+
.body.brief { white-space: pre-wrap;
|
|
14932
|
+
font-family: var(--loki-font-mono, monospace); font-size: 12px;
|
|
14933
|
+
line-height: 1.6; color: var(--loki-text-primary); }
|
|
15033
14934
|
.dim { color: var(--loki-text-muted); font-size: 12px; }
|
|
15034
14935
|
|
|
15035
14936
|
/* History */
|
|
@@ -15074,7 +14975,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
15074
14975
|
</style>
|
|
15075
14976
|
<div class="active-wrap">${this._renderActive()}</div>
|
|
15076
14977
|
${this._error||this._spec&&this._spec.type==="none"?"":this._renderHistory()}
|
|
15077
|
-
`;let e=this.shadowRoot.getElementById("spec-retry-btn");e&&e.addEventListener("click",()=>this._load());let t=this.shadowRoot.getElementById("hist-toggle");t&&t.addEventListener("click",()=>{this._historyOpen=!this._historyOpen,this.render()})}};customElements.get("loki-spec-panel")||customElements.define("loki-spec-panel",
|
|
14978
|
+
`;let e=this.shadowRoot.getElementById("spec-retry-btn");e&&e.addEventListener("click",()=>this._load());let t=this.shadowRoot.getElementById("hist-toggle");t&&t.addEventListener("click",()=>{this._historyOpen=!this._historyOpen,this.render()})}};customElements.get("loki-spec-panel")||customElements.define("loki-spec-panel",Re);var ti="1.4.0";function ii(d={}){return d.theme?w.setTheme(d.theme):d.autoDetectContext!==!1?w.init():j.init(),d.apiUrl&&m({baseUrl:d.apiUrl}),{theme:w.getTheme(),context:w.detectContext()}}return Ct(ai);})();
|
|
15078
14979
|
|
|
15079
14980
|
|
|
15080
14981
|
// Initialize dashboard when DOM is ready
|
|
@@ -15215,60 +15116,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
15215
15116
|
setInterval(refresh, 15000);
|
|
15216
15117
|
})();
|
|
15217
15118
|
|
|
15218
|
-
//
|
|
15219
|
-
|
|
15220
|
-
|
|
15221
|
-
|
|
15222
|
-
|
|
15223
|
-
|
|
15224
|
-
|
|
15225
|
-
|
|
15226
|
-
|
|
15227
|
-
|
|
15228
|
-
function lokiResolvedTheme() {
|
|
15229
|
-
var theme = LokiDashboard.UnifiedThemeManager.getTheme();
|
|
15230
|
-
return (theme.includes('dark') || theme === 'high-contrast') ? 'dark' : 'light';
|
|
15231
|
-
}
|
|
15232
|
-
|
|
15233
|
-
// Keep the trust iframe's theme in sync with the SPA toggle. If the frame is
|
|
15234
|
-
// already loaded, re-point its src with the new ?theme= so its palette flips
|
|
15235
|
-
// with the SPA instead of clashing.
|
|
15236
|
-
function syncTrustFrameTheme() {
|
|
15237
|
-
var tframe = document.getElementById('trust-frame');
|
|
15238
|
-
if (!tframe) return;
|
|
15239
|
-
var cur = tframe.getAttribute('src') || '';
|
|
15240
|
-
if (!cur || cur === 'about:blank') return; // not opened yet; opens with theme
|
|
15241
|
-
tframe.src = '/trust?theme=' + lokiResolvedTheme();
|
|
15242
|
-
}
|
|
15243
|
-
|
|
15244
|
-
function updateThemeUI() {
|
|
15245
|
-
var theme = LokiDashboard.UnifiedThemeManager.getTheme();
|
|
15246
|
-
var isDark = theme.includes('dark') || theme === 'high-contrast';
|
|
15247
|
-
themeLabel.textContent = isDark ? 'Light' : 'Dark';
|
|
15248
|
-
if (sunIcon) sunIcon.style.display = isDark ? 'inline' : 'none';
|
|
15249
|
-
if (moonIcon) moonIcon.style.display = isDark ? 'none' : 'inline';
|
|
15250
|
-
}
|
|
15251
|
-
|
|
15252
|
-
themeToggle.addEventListener('click', function() {
|
|
15253
|
-
LokiDashboard.UnifiedThemeManager.toggle();
|
|
15254
|
-
// updateThemeUI + syncTrustFrameTheme run via the loki-theme-change
|
|
15255
|
-
// listener below (toggle() dispatches it), so we do NOT call them here too
|
|
15256
|
-
// -- a direct call would re-point the trust iframe src twice per toggle.
|
|
15257
|
-
});
|
|
15258
|
-
|
|
15259
|
-
window.addEventListener('loki-theme-change', function() {
|
|
15260
|
-
updateThemeUI();
|
|
15261
|
-
syncTrustFrameTheme();
|
|
15262
|
-
});
|
|
15263
|
-
|
|
15264
|
-
updateThemeUI();
|
|
15119
|
+
// v7.90.1: dark mode removed -- the dashboard is light-only. The theme toggle
|
|
15120
|
+
// button + handler are gone; everything renders in the single light theme.
|
|
15121
|
+
// Force light on the SPA and pin the iframe/standalone pages (trust/cost/
|
|
15122
|
+
// proofs) to ?theme=light so they match.
|
|
15123
|
+
try {
|
|
15124
|
+
if (LokiDashboard && LokiDashboard.UnifiedThemeManager &&
|
|
15125
|
+
typeof LokiDashboard.UnifiedThemeManager.setTheme === 'function') {
|
|
15126
|
+
LokiDashboard.UnifiedThemeManager.setTheme('light');
|
|
15127
|
+
}
|
|
15128
|
+
} catch (_e) { /* theme manager optional; light is the CSS default anyway */ }
|
|
15265
15129
|
|
|
15266
|
-
// Carry the SPA theme to the full-page standalone views (cost/proofs) opened
|
|
15267
|
-
// via direct links, so a user who toggled Dark gets a matching page instead
|
|
15268
|
-
// of an OS-default one. Updated on click so it always reflects the current
|
|
15269
|
-
// toggle state. v7.18.0.
|
|
15270
15130
|
function lokiThemeHref(base) {
|
|
15271
|
-
return base + (base.indexOf('?') >= 0 ? '&' : '?') + 'theme='
|
|
15131
|
+
return base + (base.indexOf('?') >= 0 ? '&' : '?') + 'theme=light';
|
|
15272
15132
|
}
|
|
15273
15133
|
var costLink = document.getElementById('budget-banner-link');
|
|
15274
15134
|
if (costLink) {
|
|
@@ -15504,7 +15364,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
15504
15364
|
var tframe = document.getElementById('trust-frame');
|
|
15505
15365
|
if (tframe && (!tframe.src || tframe.src === 'about:blank' ||
|
|
15506
15366
|
tframe.getAttribute('src') === 'about:blank')) {
|
|
15507
|
-
tframe.src = '/trust?theme='
|
|
15367
|
+
tframe.src = '/trust?theme=light';
|
|
15508
15368
|
}
|
|
15509
15369
|
}
|
|
15510
15370
|
// Update nav active state
|
|
@@ -15576,148 +15436,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
15576
15436
|
}
|
|
15577
15437
|
});
|
|
15578
15438
|
|
|
15579
|
-
// Keyboard shortcuts:
|
|
15580
|
-
|
|
15581
|
-
|
|
15582
|
-
e.preventDefault();
|
|
15583
|
-
var sections = ['overview', 'fleet', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'trust', 'checkpoint', 'context', 'notifications', 'migration', 'analytics', 'escalations'];
|
|
15584
|
-
var idx = e.key === '0' ? 9 : parseInt(e.key) - 1;
|
|
15585
|
-
if (idx < sections.length) switchSection(sections[idx]);
|
|
15586
|
-
}
|
|
15587
|
-
});
|
|
15588
|
-
|
|
15589
|
-
// --- Keyboard Shortcuts (Issue #18) ---
|
|
15590
|
-
var shortcutsOverlay = document.getElementById('shortcuts-overlay');
|
|
15591
|
-
var shortcutsClose = document.getElementById('shortcuts-close');
|
|
15592
|
-
|
|
15593
|
-
function toggleShortcutsOverlay() {
|
|
15594
|
-
shortcutsOverlay.classList.toggle('visible');
|
|
15595
|
-
}
|
|
15596
|
-
|
|
15597
|
-
function closeShortcutsOverlay() {
|
|
15598
|
-
shortcutsOverlay.classList.remove('visible');
|
|
15599
|
-
}
|
|
15600
|
-
|
|
15601
|
-
shortcutsClose.addEventListener('click', closeShortcutsOverlay);
|
|
15602
|
-
|
|
15603
|
-
// Close overlay when clicking outside the dialog
|
|
15604
|
-
shortcutsOverlay.addEventListener('click', function(e) {
|
|
15605
|
-
if (e.target === shortcutsOverlay) {
|
|
15606
|
-
closeShortcutsOverlay();
|
|
15607
|
-
}
|
|
15608
|
-
});
|
|
15609
|
-
|
|
15610
|
-
document.addEventListener('keydown', function(e) {
|
|
15611
|
-
// Skip shortcuts when typing in input, textarea, or select elements
|
|
15612
|
-
var tag = (e.target.tagName || '').toLowerCase();
|
|
15613
|
-
if (tag === 'input' || tag === 'textarea' || tag === 'select' || e.target.isContentEditable) {
|
|
15614
|
-
// Allow Escape to blur input fields
|
|
15615
|
-
if (e.key === 'Escape') {
|
|
15616
|
-
e.target.blur();
|
|
15617
|
-
}
|
|
15618
|
-
return;
|
|
15619
|
-
}
|
|
15620
|
-
|
|
15621
|
-
// Skip if modifier keys are held (let browser defaults work)
|
|
15622
|
-
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
15623
|
-
|
|
15624
|
-
var sections = ['overview', 'fleet', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'trust', 'checkpoint', 'context', 'notifications', 'migration', 'analytics', 'escalations'];
|
|
15625
|
-
|
|
15626
|
-
switch (e.key) {
|
|
15627
|
-
// Section navigation: 1-9, 0
|
|
15628
|
-
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
|
15629
|
-
e.preventDefault();
|
|
15630
|
-
switchSection(sections[parseInt(e.key) - 1]);
|
|
15631
|
-
break;
|
|
15632
|
-
case '0':
|
|
15633
|
-
e.preventDefault();
|
|
15634
|
-
switchSection(sections[9]);
|
|
15635
|
-
break;
|
|
15636
|
-
|
|
15637
|
-
// Migration page
|
|
15638
|
-
case 'm':
|
|
15639
|
-
e.preventDefault();
|
|
15640
|
-
switchSection('migration');
|
|
15641
|
-
break;
|
|
15642
|
-
|
|
15643
|
-
// Analytics page
|
|
15644
|
-
case 'a':
|
|
15645
|
-
e.preventDefault();
|
|
15646
|
-
switchSection('analytics');
|
|
15647
|
-
break;
|
|
15648
|
-
|
|
15649
|
-
// Escalations page
|
|
15650
|
-
case 'e':
|
|
15651
|
-
e.preventDefault();
|
|
15652
|
-
switchSection('escalations');
|
|
15653
|
-
break;
|
|
15654
|
-
|
|
15655
|
-
// Help overlay
|
|
15656
|
-
case '?':
|
|
15657
|
-
e.preventDefault();
|
|
15658
|
-
toggleShortcutsOverlay();
|
|
15659
|
-
break;
|
|
15660
|
-
|
|
15661
|
-
// Close overlays
|
|
15662
|
-
case 'Escape':
|
|
15663
|
-
if (shortcutsOverlay.classList.contains('visible')) {
|
|
15664
|
-
e.preventDefault();
|
|
15665
|
-
closeShortcutsOverlay();
|
|
15666
|
-
}
|
|
15667
|
-
break;
|
|
15668
|
-
|
|
15669
|
-
// Focus API URL input
|
|
15670
|
-
case '/':
|
|
15671
|
-
e.preventDefault();
|
|
15672
|
-
apiUrlInput.focus();
|
|
15673
|
-
apiUrlInput.select();
|
|
15674
|
-
break;
|
|
15675
|
-
|
|
15676
|
-
// Theme toggle. updateThemeUI + syncTrustFrameTheme run via the
|
|
15677
|
-
// loki-theme-change listener (toggle() dispatches it); do not call them
|
|
15678
|
-
// here too, or the trust iframe re-points twice per toggle.
|
|
15679
|
-
case 't':
|
|
15680
|
-
e.preventDefault();
|
|
15681
|
-
LokiDashboard.UnifiedThemeManager.toggle();
|
|
15682
|
-
break;
|
|
15683
|
-
|
|
15684
|
-
// Session controls
|
|
15685
|
-
case 'p':
|
|
15686
|
-
e.preventDefault();
|
|
15687
|
-
var sessionCtrl = document.getElementById('session-control');
|
|
15688
|
-
if (sessionCtrl) {
|
|
15689
|
-
var pauseBtn = sessionCtrl.shadowRoot && sessionCtrl.shadowRoot.getElementById('pause-btn');
|
|
15690
|
-
if (pauseBtn && !pauseBtn.disabled) {
|
|
15691
|
-
pauseBtn.click();
|
|
15692
|
-
}
|
|
15693
|
-
}
|
|
15694
|
-
break;
|
|
15695
|
-
|
|
15696
|
-
case 'r':
|
|
15697
|
-
e.preventDefault();
|
|
15698
|
-
var sessionCtrl2 = document.getElementById('session-control');
|
|
15699
|
-
if (sessionCtrl2) {
|
|
15700
|
-
var resumeBtn = sessionCtrl2.shadowRoot && sessionCtrl2.shadowRoot.getElementById('resume-btn');
|
|
15701
|
-
if (resumeBtn) {
|
|
15702
|
-
resumeBtn.click();
|
|
15703
|
-
}
|
|
15704
|
-
}
|
|
15705
|
-
break;
|
|
15706
|
-
|
|
15707
|
-
case 's':
|
|
15708
|
-
e.preventDefault();
|
|
15709
|
-
var sessionCtrl3 = document.getElementById('session-control');
|
|
15710
|
-
if (sessionCtrl3) {
|
|
15711
|
-
var stopBtn = sessionCtrl3.shadowRoot && sessionCtrl3.shadowRoot.getElementById('stop-btn');
|
|
15712
|
-
if (stopBtn && !stopBtn.disabled) {
|
|
15713
|
-
if (window.confirm('Are you sure you want to stop the session?')) {
|
|
15714
|
-
stopBtn.click();
|
|
15715
|
-
}
|
|
15716
|
-
}
|
|
15717
|
-
}
|
|
15718
|
-
break;
|
|
15719
|
-
}
|
|
15720
|
-
});
|
|
15439
|
+
// Keyboard shortcuts removed (v7.90.1): app-level hotkeys fired while
|
|
15440
|
+
// typing in inputs (switching tabs / toggling theme), so they are gone
|
|
15441
|
+
// entirely. Native browser behavior + per-modal Escape handling remain.
|
|
15721
15442
|
|
|
15722
15443
|
// Restore last section from localStorage (overrides default overview)
|
|
15723
15444
|
var savedSection = localStorage.getItem('loki-active-section');
|