loki-mode 5.53.0 → 5.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/loki +939 -4
- package/autonomy/migration-agents.sh +500 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/activity_logger.py +231 -0
- package/dashboard/failure_extractor.py +228 -0
- package/dashboard/migration_engine.py +886 -0
- package/dashboard/prompt_optimizer.py +281 -0
- package/dashboard/rigour_integration.py +331 -0
- package/dashboard/server.py +428 -0
- package/dashboard/static/index.html +1667 -350
- package/docs/INSTALLATION.md +1 -1
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
|
@@ -537,6 +537,10 @@
|
|
|
537
537
|
<svg viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
|
|
538
538
|
Council
|
|
539
539
|
</button>
|
|
540
|
+
<button class="nav-link" data-section="quality" id="nav-quality">
|
|
541
|
+
<svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" fill="none" stroke="currentColor" stroke-width="2"/></svg>
|
|
542
|
+
Quality
|
|
543
|
+
</button>
|
|
540
544
|
<button class="nav-link" data-section="cost" id="nav-cost">
|
|
541
545
|
<svg viewBox="0 0 24 24"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg>
|
|
542
546
|
Cost
|
|
@@ -554,6 +558,10 @@
|
|
|
554
558
|
Notifications
|
|
555
559
|
<span class="notification-badge" id="notif-badge" style="display:none;background:var(--loki-red);color:#fff;font-size:10px;padding:1px 5px;border-radius:8px;margin-left:4px;">0</span>
|
|
556
560
|
</button>
|
|
561
|
+
<button class="nav-link" data-section="migration" id="nav-migration">
|
|
562
|
+
<svg viewBox="0 0 24 24"><path d="M4 14h6v6H4z" fill="none" stroke="currentColor" stroke-width="2"/><path d="M14 4h6v6h-6z" fill="none" stroke="currentColor" stroke-width="2"/><path d="M17 10v4h-4" fill="none" stroke="currentColor" stroke-width="2"/><path d="M7 14v-4h4" fill="none" stroke="currentColor" stroke-width="2"/></svg>
|
|
563
|
+
Migration
|
|
564
|
+
</button>
|
|
557
565
|
</nav>
|
|
558
566
|
|
|
559
567
|
<div class="sidebar-footer">
|
|
@@ -575,6 +583,7 @@
|
|
|
575
583
|
<!-- Overview + Tasks (combined) -->
|
|
576
584
|
<div class="section-page active" id="page-overview">
|
|
577
585
|
<loki-overview id="overview"></loki-overview>
|
|
586
|
+
<loki-session-diff id="session-diff"></loki-session-diff>
|
|
578
587
|
<div style="margin-top: 28px;">
|
|
579
588
|
<div class="section-page-header">
|
|
580
589
|
<h2 class="section-page-title">Tasks</h2>
|
|
@@ -628,6 +637,17 @@
|
|
|
628
637
|
<loki-council-dashboard id="council-dashboard"></loki-council-dashboard>
|
|
629
638
|
</div>
|
|
630
639
|
|
|
640
|
+
<!-- Quality -->
|
|
641
|
+
<div class="section-page" id="page-quality">
|
|
642
|
+
<div class="section-page-header">
|
|
643
|
+
<h2 class="section-page-title">Quality</h2>
|
|
644
|
+
</div>
|
|
645
|
+
<div style="display: grid; gap: 24px;">
|
|
646
|
+
<loki-quality-score id="quality-score"></loki-quality-score>
|
|
647
|
+
<loki-prompt-optimizer id="prompt-optimizer"></loki-prompt-optimizer>
|
|
648
|
+
</div>
|
|
649
|
+
</div>
|
|
650
|
+
|
|
631
651
|
<!-- Cost Dashboard -->
|
|
632
652
|
<div class="section-page" id="page-cost">
|
|
633
653
|
<div class="section-page-header">
|
|
@@ -659,6 +679,14 @@
|
|
|
659
679
|
</div>
|
|
660
680
|
<loki-notification-center id="notification-center"></loki-notification-center>
|
|
661
681
|
</div>
|
|
682
|
+
|
|
683
|
+
<!-- Migration -->
|
|
684
|
+
<div class="section-page" id="page-migration">
|
|
685
|
+
<div class="section-page-header">
|
|
686
|
+
<h2 class="section-page-title">Migration</h2>
|
|
687
|
+
</div>
|
|
688
|
+
<loki-migration-dashboard id="migration-dashboard"></loki-migration-dashboard>
|
|
689
|
+
</div>
|
|
662
690
|
</main>
|
|
663
691
|
</div>
|
|
664
692
|
|
|
@@ -676,10 +704,12 @@
|
|
|
676
704
|
<div class="shortcut-row"><span class="shortcut-desc">PRD Checklist</span><span class="shortcut-keys"><kbd class="shortcut-key">3</kbd></span></div>
|
|
677
705
|
<div class="shortcut-row"><span class="shortcut-desc">App Runner</span><span class="shortcut-keys"><kbd class="shortcut-key">4</kbd></span></div>
|
|
678
706
|
<div class="shortcut-row"><span class="shortcut-desc">Council</span><span class="shortcut-keys"><kbd class="shortcut-key">5</kbd></span></div>
|
|
679
|
-
<div class="shortcut-row"><span class="shortcut-desc">
|
|
680
|
-
<div class="shortcut-row"><span class="shortcut-desc">
|
|
681
|
-
<div class="shortcut-row"><span class="shortcut-desc">
|
|
682
|
-
<div class="shortcut-row"><span class="shortcut-desc">
|
|
707
|
+
<div class="shortcut-row"><span class="shortcut-desc">Quality</span><span class="shortcut-keys"><kbd class="shortcut-key">6</kbd></span></div>
|
|
708
|
+
<div class="shortcut-row"><span class="shortcut-desc">Cost</span><span class="shortcut-keys"><kbd class="shortcut-key">7</kbd></span></div>
|
|
709
|
+
<div class="shortcut-row"><span class="shortcut-desc">Checkpoints</span><span class="shortcut-keys"><kbd class="shortcut-key">8</kbd></span></div>
|
|
710
|
+
<div class="shortcut-row"><span class="shortcut-desc">Context</span><span class="shortcut-keys"><kbd class="shortcut-key">9</kbd></span></div>
|
|
711
|
+
<div class="shortcut-row"><span class="shortcut-desc">Notifications</span><span class="shortcut-keys"><kbd class="shortcut-key">0</kbd></span></div>
|
|
712
|
+
<div class="shortcut-row"><span class="shortcut-desc">Migration</span><span class="shortcut-keys"><kbd class="shortcut-key">m</kbd></span></div>
|
|
683
713
|
</div>
|
|
684
714
|
<div class="shortcuts-group">
|
|
685
715
|
<div class="shortcuts-group-title">Session</div>
|
|
@@ -699,52 +729,52 @@
|
|
|
699
729
|
|
|
700
730
|
<!-- Inlined JavaScript Bundle -->
|
|
701
731
|
<script>
|
|
702
|
-
var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnPropertyDescriptor;var vt=Object.getOwnPropertyNames;var mt=Object.prototype.hasOwnProperty;var bt=(d,t,e)=>t in d?X(d,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):d[t]=e;var kt=(d,t)=>{for(var e in t)X(d,e,{get:t[e],enumerable:!0})},ft=(d,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of vt(t))!mt.call(d,i)&&i!==e&&X(d,i,{get:()=>t[i],enumerable:!(a=gt(t,i))||a.enumerable});return d};var _t=d=>ft(X({},"__esModule",{value:!0}),d);var k=(d,t,e)=>bt(d,typeof t!="symbol"?t+"":t,e);var Dt={};kt(Dt,{ANIMATION:()=>$,ARIA_PATTERNS:()=>tt,ApiEvents:()=>n,BASE_STYLES:()=>B,BREAKPOINTS:()=>Z,COMMON_STYLES:()=>ot,KEYBOARD_SHORTCUTS:()=>Q,KeyboardHandler:()=>D,LokiApiClient:()=>I,LokiAppStatus:()=>J,LokiChecklistViewer:()=>G,LokiCheckpointViewer:()=>V,LokiContextTracker:()=>Y,LokiCostDashboard:()=>K,LokiCouncilDashboard:()=>q,LokiElement:()=>c,LokiLearningDashboard:()=>N,LokiLogStream:()=>j,LokiMemoryBrowser:()=>O,LokiNotificationCenter:()=>W,LokiOverview:()=>F,LokiSessionControl:()=>U,LokiState:()=>M,LokiTaskBoard:()=>z,LokiTheme:()=>A,RADIUS:()=>w,SPACING:()=>_,STATE_CHANGE_EVENT:()=>it,THEMES:()=>b,THEME_VARIABLES:()=>et,TYPOGRAPHY:()=>v,UnifiedThemeManager:()=>g,VERSION:()=>At,Z_INDEX:()=>E,createApiClient:()=>dt,createStore:()=>ct,generateThemeCSS:()=>m,generateTokensCSS:()=>H,getApiClient:()=>u,getState:()=>L,init:()=>Lt});var b={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)"}},_={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},w={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},v={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"}},$={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)"}},Z={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},E={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Q={"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"]}},tt={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 m(d){let t=b[d];return t?Object.entries(t).map(([e,a])=>`${e}: ${a};`).join(`
|
|
732
|
+
var LokiDashboard=(()=>{var st=Object.defineProperty;var wt=Object.getOwnPropertyDescriptor;var $t=Object.getOwnPropertyNames;var Et=Object.prototype.hasOwnProperty;var Ct=(c,t,e)=>t in c?st(c,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):c[t]=e;var St=(c,t)=>{for(var e in t)st(c,e,{get:t[e],enumerable:!0})},Tt=(c,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of $t(t))!Et.call(c,a)&&a!==e&&st(c,a,{get:()=>t[a],enumerable:!(i=wt(t,a))||i.enumerable});return c};var At=c=>Tt(st({},"__esModule",{value:!0}),c);var w=(c,t,e)=>Ct(c,typeof t!="symbol"?t+"":t,e);var Ut={};St(Ut,{ANIMATION:()=>T,ARIA_PATTERNS:()=>nt,ApiEvents:()=>l,BASE_STYLES:()=>B,BREAKPOINTS:()=>rt,COMMON_STYLES:()=>ut,KEYBOARD_SHORTCUTS:()=>ot,KeyboardHandler:()=>P,LokiApiClient:()=>R,LokiAppStatus:()=>V,LokiChecklistViewer:()=>K,LokiCheckpointViewer:()=>W,LokiContextTracker:()=>Q,LokiCostDashboard:()=>Y,LokiCouncilDashboard:()=>J,LokiElement:()=>p,LokiLearningDashboard:()=>G,LokiLogStream:()=>N,LokiMemoryBrowser:()=>q,LokiMigrationDashboard:()=>it,LokiNotificationCenter:()=>X,LokiOverview:()=>j,LokiPromptOptimizer:()=>tt,LokiQualityScore:()=>et,LokiSessionControl:()=>O,LokiSessionDiff:()=>Z,LokiState:()=>F,LokiTaskBoard:()=>U,LokiTheme:()=>D,RADIUS:()=>S,SPACING:()=>E,STATE_CHANGE_EVENT:()=>ct,THEMES:()=>k,THEME_VARIABLES:()=>lt,TYPOGRAPHY:()=>b,UnifiedThemeManager:()=>m,VERSION:()=>Ft,Z_INDEX:()=>A,createApiClient:()=>vt,createStore:()=>mt,generateThemeCSS:()=>f,generateTokensCSS:()=>H,getApiClient:()=>u,getState:()=>z,init:()=>jt});var k={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)"}},E={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},S={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},b={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"}},T={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)"}},rt={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},A={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},ot={"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"]}},nt={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 f(c){let t=k[c];return t?Object.entries(t).map(([e,i])=>`${e}: ${i};`).join(`
|
|
703
733
|
`):""}function H(){return`
|
|
704
734
|
/* Spacing */
|
|
705
|
-
--loki-space-xs: ${
|
|
706
|
-
--loki-space-sm: ${
|
|
707
|
-
--loki-space-md: ${
|
|
708
|
-
--loki-space-lg: ${
|
|
709
|
-
--loki-space-xl: ${
|
|
710
|
-
--loki-space-2xl: ${
|
|
711
|
-
--loki-space-3xl: ${
|
|
735
|
+
--loki-space-xs: ${E.xs};
|
|
736
|
+
--loki-space-sm: ${E.sm};
|
|
737
|
+
--loki-space-md: ${E.md};
|
|
738
|
+
--loki-space-lg: ${E.lg};
|
|
739
|
+
--loki-space-xl: ${E.xl};
|
|
740
|
+
--loki-space-2xl: ${E["2xl"]};
|
|
741
|
+
--loki-space-3xl: ${E["3xl"]};
|
|
712
742
|
|
|
713
743
|
/* Border Radius */
|
|
714
|
-
--loki-radius-none: ${
|
|
715
|
-
--loki-radius-sm: ${
|
|
716
|
-
--loki-radius-md: ${
|
|
717
|
-
--loki-radius-lg: ${
|
|
718
|
-
--loki-radius-xl: ${
|
|
719
|
-
--loki-radius-full: ${
|
|
744
|
+
--loki-radius-none: ${S.none};
|
|
745
|
+
--loki-radius-sm: ${S.sm};
|
|
746
|
+
--loki-radius-md: ${S.md};
|
|
747
|
+
--loki-radius-lg: ${S.lg};
|
|
748
|
+
--loki-radius-xl: ${S.xl};
|
|
749
|
+
--loki-radius-full: ${S.full};
|
|
720
750
|
|
|
721
751
|
/* Typography */
|
|
722
|
-
--loki-font-sans: ${
|
|
723
|
-
--loki-font-serif: ${
|
|
724
|
-
--loki-font-mono: ${
|
|
725
|
-
--loki-text-xs: ${
|
|
726
|
-
--loki-text-sm: ${
|
|
727
|
-
--loki-text-base: ${
|
|
728
|
-
--loki-text-md: ${
|
|
729
|
-
--loki-text-lg: ${
|
|
730
|
-
--loki-text-xl: ${
|
|
731
|
-
--loki-text-2xl: ${
|
|
732
|
-
--loki-text-3xl: ${
|
|
752
|
+
--loki-font-sans: ${b.fontFamily.sans};
|
|
753
|
+
--loki-font-serif: ${b.fontFamily.serif};
|
|
754
|
+
--loki-font-mono: ${b.fontFamily.mono};
|
|
755
|
+
--loki-text-xs: ${b.fontSize.xs};
|
|
756
|
+
--loki-text-sm: ${b.fontSize.sm};
|
|
757
|
+
--loki-text-base: ${b.fontSize.base};
|
|
758
|
+
--loki-text-md: ${b.fontSize.md};
|
|
759
|
+
--loki-text-lg: ${b.fontSize.lg};
|
|
760
|
+
--loki-text-xl: ${b.fontSize.xl};
|
|
761
|
+
--loki-text-2xl: ${b.fontSize["2xl"]};
|
|
762
|
+
--loki-text-3xl: ${b.fontSize["3xl"]};
|
|
733
763
|
|
|
734
764
|
/* Animation */
|
|
735
|
-
--loki-duration-fast: ${
|
|
736
|
-
--loki-duration-normal: ${
|
|
737
|
-
--loki-duration-slow: ${
|
|
738
|
-
--loki-easing-default: ${
|
|
739
|
-
--loki-transition: ${
|
|
765
|
+
--loki-duration-fast: ${T.duration.fast};
|
|
766
|
+
--loki-duration-normal: ${T.duration.normal};
|
|
767
|
+
--loki-duration-slow: ${T.duration.slow};
|
|
768
|
+
--loki-easing-default: ${T.easing.default};
|
|
769
|
+
--loki-transition: ${T.duration.normal} ${T.easing.default};
|
|
740
770
|
|
|
741
771
|
/* Z-Index */
|
|
742
|
-
--loki-z-dropdown: ${
|
|
743
|
-
--loki-z-sticky: ${
|
|
744
|
-
--loki-z-modal: ${
|
|
745
|
-
--loki-z-popover: ${
|
|
746
|
-
--loki-z-tooltip: ${
|
|
747
|
-
--loki-z-toast: ${
|
|
772
|
+
--loki-z-dropdown: ${A.dropdown};
|
|
773
|
+
--loki-z-sticky: ${A.sticky};
|
|
774
|
+
--loki-z-modal: ${A.modal};
|
|
775
|
+
--loki-z-popover: ${A.popover};
|
|
776
|
+
--loki-z-tooltip: ${A.tooltip};
|
|
777
|
+
--loki-z-toast: ${A.toast};
|
|
748
778
|
|
|
749
779
|
/* Glass effect */
|
|
750
780
|
--loki-glass-bg: rgba(255, 255, 255, 0.03);
|
|
@@ -1026,20 +1056,20 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1026
1056
|
}
|
|
1027
1057
|
|
|
1028
1058
|
/* Responsive utilities */
|
|
1029
|
-
@media (max-width: ${
|
|
1059
|
+
@media (max-width: ${rt.md}) {
|
|
1030
1060
|
.hide-mobile { display: none !important; }
|
|
1031
1061
|
}
|
|
1032
1062
|
|
|
1033
|
-
@media (min-width: ${
|
|
1063
|
+
@media (min-width: ${rt.md}) {
|
|
1034
1064
|
.hide-desktop { display: none !important; }
|
|
1035
1065
|
}
|
|
1036
|
-
`,h=class h{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 t=document.body;if(t.classList.contains("vscode-high-contrast"))return"high-contrast";if(t.classList.contains("vscode-dark"))return"dark";if(t.classList.contains("vscode-light"))return"light";let e=getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background");if(e){let
|
|
1066
|
+
`,h=class h{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 t=document.body;if(t.classList.contains("vscode-high-contrast"))return"high-contrast";if(t.classList.contains("vscode-dark"))return"dark";if(t.classList.contains("vscode-light"))return"light";let e=getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background");if(e){let i=e.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(h.detectContext()==="vscode"){let i=h.detectVSCodeTheme();return i==="high-contrast"?"high-contrast":i==="dark"?"vscode-dark":"vscode-light"}let e=localStorage.getItem(h.STORAGE_KEY);return e&&k[e]?e:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}static setTheme(t){if(!k[t]){console.warn(`Unknown theme: ${t}`);return}localStorage.setItem(h.STORAGE_KEY,t),document.documentElement.setAttribute("data-loki-theme",t),window.dispatchEvent(new CustomEvent("loki-theme-change",{detail:{theme:t,context:h.detectContext()}}))}static toggle(){let t=h.getTheme(),e;return t.includes("dark")||t==="high-contrast"?e=t.startsWith("vscode")?"vscode-light":"light":e=t.startsWith("vscode")?"vscode-dark":"dark",h.setTheme(e),e}static getVariables(t=null){let e=t||h.getTheme();return k[e]||k.light}static generateCSS(t=null){let e=t||h.getTheme();return`
|
|
1037
1067
|
:host {
|
|
1038
|
-
${
|
|
1068
|
+
${f(e)}
|
|
1039
1069
|
${H()}
|
|
1040
1070
|
}
|
|
1041
1071
|
${B}
|
|
1042
|
-
`}static init(){let t=h.getTheme();document.documentElement.setAttribute("data-loki-theme",t),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{localStorage.getItem(h.STORAGE_KEY)||h.setTheme(h.getTheme())}),h.detectContext()==="vscode"&&new MutationObserver(()=>{let
|
|
1072
|
+
`}static init(){let t=h.getTheme();document.documentElement.setAttribute("data-loki-theme",t),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{localStorage.getItem(h.STORAGE_KEY)||h.setTheme(h.getTheme())}),h.detectContext()==="vscode"&&new MutationObserver(()=>{let i=h.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"]})}};w(h,"STORAGE_KEY","loki-theme"),w(h,"CONTEXT_KEY","loki-context");var m=h,P=class{constructor(){this._handlers=new Map,this._enabled=!0}register(t,e){let i=ot[t];if(!i){console.warn(`Unknown keyboard action: ${t}`);return}this._handlers.set(t,{shortcut:i,handler:e})}unregister(t){this._handlers.delete(t)}setEnabled(t){this._enabled=t}handleEvent(t){if(!this._enabled)return!1;for(let[e,{shortcut:i,handler:a}]of this._handlers)if(this._matchesShortcut(t,i))return t.preventDefault(),t.stopPropagation(),a(t),!0;return!1}_matchesShortcut(t,e){let i=t.key.toLowerCase(),a=e.modifiers||[];if(i!==e.key.toLowerCase())return!1;let s=a.includes("Ctrl")||a.includes("Meta"),r=a.includes("Shift"),o=a.includes("Alt"),n=(t.ctrlKey||t.metaKey)===s,d=t.shiftKey===r,g=t.altKey===o;return n&&d&&g}attach(t){this._boundHandler||(this._boundHandler=e=>this.handleEvent(e)),t.addEventListener("keydown",this._boundHandler)}detach(t){this._boundHandler&&t.removeEventListener("keydown",this._boundHandler)}};var lt={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)"}},ut=`
|
|
1043
1073
|
:host {
|
|
1044
1074
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
1045
1075
|
line-height: 1.5;
|
|
@@ -1135,8 +1165,8 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1135
1165
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary); }
|
|
1136
1166
|
::-webkit-scrollbar-thumb { background: var(--loki-border); border-radius: 3px; }
|
|
1137
1167
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light); }
|
|
1138
|
-
`,
|
|
1139
|
-
`)}static applyToElement(t,e=null){let
|
|
1168
|
+
`,I=class I{static getTheme(){return m.getTheme()}static setTheme(t){m.setTheme(t)}static toggle(){return m.toggle()}static getVariables(t=null){let e=t||I.getTheme();return k[e]||lt[e]||lt.light}static toCSSString(t=null){let e=t||I.getTheme();if(k[e])return f(e);let i=I.getVariables(e);return Object.entries(i).map(([a,s])=>`${a}: ${s};`).join(`
|
|
1169
|
+
`)}static applyToElement(t,e=null){let i=I.getVariables(e);for(let[a,s]of Object.entries(i))t.style.setProperty(a,s)}static init(){m.init()}static detectContext(){return m.detectContext()}static getAvailableThemes(){return Object.keys(k)}};w(I,"STORAGE_KEY","loki-theme");var D=I,p=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._theme=D.getTheme(),this._themeChangeHandler=this._onThemeChange.bind(this),this._keyboardHandler=new P}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(t){this._theme=t.detail.theme,this._applyTheme(),this.onThemeChange&&this.onThemeChange(this._theme)}_applyTheme(){D.applyToElement(this.shadowRoot.host,this._theme),this.setAttribute("data-loki-theme",this._theme)}_setupKeyboardHandling(){this._keyboardHandler.attach(this)}registerShortcut(t,e){this._keyboardHandler.register(t,e)}getBaseStyles(){return`
|
|
1140
1170
|
/* Design tokens */
|
|
1141
1171
|
:host {
|
|
1142
1172
|
${H()}
|
|
@@ -1144,40 +1174,40 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1144
1174
|
|
|
1145
1175
|
/* Light theme (default) */
|
|
1146
1176
|
:host {
|
|
1147
|
-
${
|
|
1177
|
+
${f("light")}
|
|
1148
1178
|
}
|
|
1149
1179
|
|
|
1150
1180
|
/* Dark theme via system preference */
|
|
1151
1181
|
@media (prefers-color-scheme: dark) {
|
|
1152
1182
|
:host {
|
|
1153
|
-
${
|
|
1183
|
+
${f("dark")}
|
|
1154
1184
|
}
|
|
1155
1185
|
}
|
|
1156
1186
|
|
|
1157
1187
|
/* Explicit theme attributes */
|
|
1158
1188
|
:host([theme="dark"]),
|
|
1159
1189
|
:host([data-loki-theme="dark"]) {
|
|
1160
|
-
${
|
|
1190
|
+
${f("dark")}
|
|
1161
1191
|
}
|
|
1162
1192
|
|
|
1163
1193
|
:host([theme="light"]),
|
|
1164
1194
|
:host([data-loki-theme="light"]) {
|
|
1165
|
-
${
|
|
1195
|
+
${f("light")}
|
|
1166
1196
|
}
|
|
1167
1197
|
|
|
1168
1198
|
:host([theme="high-contrast"]),
|
|
1169
1199
|
:host([data-loki-theme="high-contrast"]) {
|
|
1170
|
-
${
|
|
1200
|
+
${f("high-contrast")}
|
|
1171
1201
|
}
|
|
1172
1202
|
|
|
1173
1203
|
:host([theme="vscode-light"]),
|
|
1174
1204
|
:host([data-loki-theme="vscode-light"]) {
|
|
1175
|
-
${
|
|
1205
|
+
${f("vscode-light")}
|
|
1176
1206
|
}
|
|
1177
1207
|
|
|
1178
1208
|
:host([theme="vscode-dark"]),
|
|
1179
1209
|
:host([data-loki-theme="vscode-dark"]) {
|
|
1180
|
-
${
|
|
1210
|
+
${f("vscode-dark")}
|
|
1181
1211
|
}
|
|
1182
1212
|
|
|
1183
1213
|
/* Reduced motion preference */
|
|
@@ -1192,16 +1222,16 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1192
1222
|
}
|
|
1193
1223
|
|
|
1194
1224
|
${B}
|
|
1195
|
-
`}getAriaPattern(t){return tt[t]||{}}applyAriaPattern(t,e){let a=this.getAriaPattern(e);for(let[i,s]of Object.entries(a))if(i==="role")t.setAttribute("role",s);else{let r=i.replace(/([A-Z])/g,"-$1").toLowerCase();t.setAttribute(r,s)}}render(){}};var C={realtime:1e3,normal:2e3,background:5e3,offline:1e4},nt={vscode:C.normal,browser:C.realtime,cli:C.background},lt={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},n={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"},x=class x extends EventTarget{static getInstance(t={}){let e=t.baseUrl||lt.baseUrl;return x._instances.has(e)||x._instances.set(e,new x(t)),x._instances.get(e)}static clearInstances(){x._instances.forEach(t=>t.disconnect()),x._instances.clear()}constructor(t={}){super(),this.config={...lt,...t},this._ws=null,this._connected=!1,this._pollInterval=null,this._reconnectTimeout=null,this._cache=new Map,this._cacheTimeout=5e3,this._vscodeApi=null,this._context=this._detectContext(),this._currentPollInterval=nt[this._context]||C.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 C}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(C.background):this._setPollInterval(nt[this._context]||C.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(t){this._currentPollInterval=t,this._pollInterval&&(this.stopPolling(),this.startPolling(null,t))}setPollMode(t){let e=C[t];e&&this._setPollInterval(e)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=t=>{let e=t.data;if(!(!e||!e.type))switch(e.type){case"updateStatus":this._emit(n.STATUS_UPDATE,e.data);break;case"updateTasks":this._emit(n.TASK_UPDATED,e.data);break;case"taskCreated":this._emit(n.TASK_CREATED,e.data);break;case"taskDeleted":this._emit(n.TASK_DELETED,e.data);break;case"projectCreated":this._emit(n.PROJECT_CREATED,e.data);break;case"projectUpdated":this._emit(n.PROJECT_UPDATED,e.data);break;case"agentUpdate":this._emit(n.AGENT_UPDATE,e.data);break;case"logMessage":this._emit(n.LOG_MESSAGE,e.data);break;case"memoryUpdate":this._emit(n.MEMORY_UPDATE,e.data);break;case"connected":this._connected=!0,this._emit(n.CONNECTED,e.data);break;case"disconnected":this._connected=!1,this._emit(n.DISCONNECTED,e.data);break;case"error":this._emit(n.ERROR,e.data);break;case"setPollMode":this.setPollMode(e.data.mode);break;default:this._emit(`api:${e.type}`,e.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(t,e={}){this._vscodeApi&&this._vscodeApi.postMessage({type:t,data:e})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(t,e={}){this.postToVSCode("userAction",{action:t,...e})}get baseUrl(){return this.config.baseUrl}set baseUrl(t){this.config.baseUrl=t,this.config.wsUrl=t.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((t,e)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._emit(n.CONNECTED),t()},this._ws.onclose=()=>{this._connected=!1,this._emit(n.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=a=>{this._emit(n.ERROR,{error:a}),e(a)},this._ws.onmessage=a=>{try{let i=JSON.parse(a.data);this._handleMessage(i)}catch(i){console.error("Failed to parse WebSocket message:",i)}}}catch(a){e(a)}})}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(){this._reconnectTimeout||(this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},this.config.retryDelay))}_handleMessage(t){let a={connected:n.CONNECTED,status_update:n.STATUS_UPDATE,task_created:n.TASK_CREATED,task_updated:n.TASK_UPDATED,task_deleted:n.TASK_DELETED,task_moved:n.TASK_UPDATED,project_created:n.PROJECT_CREATED,project_updated:n.PROJECT_UPDATED,agent_update:n.AGENT_UPDATE,log:n.LOG_MESSAGE}[t.type]||`api:${t.type}`;this._emit(a,t.data)}_emit(t,e={}){this.dispatchEvent(new CustomEvent(t,{detail:e}))}async _request(t,e={}){let a=`${this.config.baseUrl}${t}`,i=new AbortController,s=setTimeout(()=>i.abort(),this.config.timeout);try{let r=await fetch(a,{...e,signal:i.signal,headers:{"Content-Type":"application/json",...e.headers}});if(clearTimeout(s),!r.ok){let o=await r.json().catch(()=>({detail:r.statusText}));throw new Error(o.detail||`HTTP ${r.status}`)}return r.status===204?null:await r.json()}catch(r){throw clearTimeout(s),r.name==="AbortError"?new Error("Request timeout"):r}}async _get(t,e=!1){if(e&&this._cache.has(t)){let i=this._cache.get(t);if(Date.now()-i.timestamp<this._cacheTimeout)return i.data}let a=await this._request(t);return e&&this._cache.set(t,{data:a,timestamp:Date.now()}),a}async _post(t,e){return this._request(t,{method:"POST",body:JSON.stringify(e)})}async _put(t,e){return this._request(t,{method:"PUT",body:JSON.stringify(e)})}async _delete(t){return this._request(t,{method:"DELETE"})}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(t=null){let e=t?`?status=${t}`:"";return this._get(`/api/projects${e}`)}async getProject(t){return this._get(`/api/projects/${t}`)}async createProject(t){return this._post("/api/projects",t)}async updateProject(t,e){return this._put(`/api/projects/${t}`,e)}async deleteProject(t){return this._delete(`/api/projects/${t}`)}async listTasks(t={}){let e=new URLSearchParams;t.projectId&&e.append("project_id",t.projectId),t.status&&e.append("status",t.status),t.priority&&e.append("priority",t.priority);let a=e.toString()?`?${e}`:"";return this._get(`/api/tasks${a}`)}async getTask(t){return this._get(`/api/tasks/${t}`)}async createTask(t){return this._post("/api/tasks",t)}async updateTask(t,e){return this._put(`/api/tasks/${t}`,e)}async moveTask(t,e,a){return this._post(`/api/tasks/${t}/move`,{status:e,position:a})}async deleteTask(t){return this._delete(`/api/tasks/${t}`)}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(t={}){let e=new URLSearchParams(t).toString();return this._get(`/api/memory/episodes${e?"?"+e:""}`)}async getEpisode(t){return this._get(`/api/memory/episodes/${t}`)}async listPatterns(t={}){let e=new URLSearchParams(t).toString();return this._get(`/api/memory/patterns${e?"?"+e:""}`)}async getPattern(t){return this._get(`/api/memory/patterns/${t}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(t){return this._get(`/api/memory/skills/${t}`)}async retrieveMemories(t,e=null,a=5){return this._post("/api/memory/retrieve",{query:t,taskType:e,topK:a})}async consolidateMemory(t=24){return this._post("/api/memory/consolidate",{sinceHours:t})}async getTokenEconomics(){return this._get("/api/memory/economics")}async listRegisteredProjects(t=!1){return this._get(`/api/registry/projects?include_inactive=${t}`)}async registerProject(t,e=null,a=null){return this._post("/api/registry/projects",{path:t,name:e,alias:a})}async discoverProjects(t=3){return this._get(`/api/registry/discover?max_depth=${t}`)}async syncRegistry(){return this._post("/api/registry/sync",{})}async getCrossProjectTasks(t=null){let e=t?`?project_ids=${t.join(",")}`:"";return this._get(`/api/registry/tasks${e}`)}async getLearningMetrics(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source);let a=e.toString()?`?${e}`:"";return this._get(`/api/learning/metrics${a}`)}async getLearningTrends(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source);let a=e.toString()?`?${e}`:"";return this._get(`/api/learning/trends${a}`)}async getLearningSignals(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source),t.limit&&e.append("limit",String(t.limit)),t.offset&&e.append("offset",String(t.offset));let a=e.toString()?`?${e}`:"";return this._get(`/api/learning/signals${a}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(t={}){return this._post("/api/learning/aggregate",t)}async getAggregatedPreferences(t=20){return this._get(`/api/learning/preferences?limit=${t}`)}async getAggregatedErrors(t=20){return this._get(`/api/learning/errors?limit=${t}`)}async getAggregatedSuccessPatterns(t=20){return this._get(`/api/learning/success?limit=${t}`)}async getToolEfficiency(t=20){return this._get(`/api/learning/tools?limit=${t}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(t=20){return this._get(`/api/council/verdicts?limit=${t}`)}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(t,e){let a=new URLSearchParams;t&&a.set("severity",t),e&&a.set("unread_only","true");let i=a.toString();return this._get("/api/notifications"+(i?"?"+i:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(t){return this._put("/api/notifications/triggers",{triggers:t})}async acknowledgeNotification(t){return this._post("/api/notifications/"+encodeURIComponent(t)+"/acknowledge",{})}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 getLogs(t=100){return this._get(`/api/logs?lines=${t}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let t=await fetch(`${this.baseUrl}/api/prd-observations`);if(!t.ok)throw new Error(`HTTP ${t.status}`);return t.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(t,e,a="dashboard"){return this._post("/api/checklist/waivers",{item_id:t,reason:e,waived_by:a})}async removeChecklistWaiver(t){return this._delete(`/api/checklist/waivers/${encodeURIComponent(t)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(t=100){return this._get(`/api/app-runner/logs?lines=${t}`)}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(t,e=null){if(this._pollInterval)return;this._pollCallback=t;let a=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(n.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(n.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};a();let i=e||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(a,i)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};k(x,"_instances",new Map);var I=x;function dt(d={}){return new I(d)}function u(d={}){return I.getInstance(d)}var it="loki-state-change",at={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}},f=class f extends EventTarget{static getInstance(){return f._instance||(f._instance=new f),f._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let t=localStorage.getItem(f.STORAGE_KEY);if(t){let e=JSON.parse(t);return this._mergeState(at,e)}}catch(t){console.warn("Failed to load state from localStorage:",t)}return{...at}}_mergeState(t,e){let a={...t};for(let i of Object.keys(e))i in t&&typeof t[i]=="object"&&!Array.isArray(t[i])?a[i]=this._mergeState(t[i],e[i]):a[i]=e[i];return a}_saveState(){try{let t={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(f.STORAGE_KEY,JSON.stringify(t))}catch(t){console.warn("Failed to save state to localStorage:",t)}}get(t=null){if(!t)return{...this._state};let e=t.split("."),a=this._state;for(let i of e){if(a==null)return;a=a[i]}return a}set(t,e,a=!0){let i=t.split("."),s=i.pop(),r=this._state;for(let l of i)l in r||(r[l]={}),r=r[l];let o=r[s];r[s]=e,a&&this._saveState(),this._notifyChange(t,e,o)}update(t,e=!0){let a=[];for(let[i,s]of Object.entries(t)){let r=this.get(i);this.set(i,s,!1),a.push({path:i,value:s,oldValue:r})}e&&this._saveState();for(let i of a)this._notifyChange(i.path,i.value,i.oldValue)}_notifyChange(t,e,a){this.dispatchEvent(new CustomEvent(it,{detail:{path:t,value:e,oldValue:a}}));let i=this._subscribers.get(t)||[];for(let r of i)try{r(e,a,t)}catch(o){console.error("State subscriber error:",o)}let s=t.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let l of o)try{l(this.get(r),null,r)}catch(p){console.error("State subscriber error:",p)}}}subscribe(t,e){return this._subscribers.has(t)||this._subscribers.set(t,[]),this._subscribers.get(t).push(e),()=>{let a=this._subscribers.get(t),i=a.indexOf(e);i>-1&&a.splice(i,1)}}reset(t=null){if(t){let e=t.split("."),a=at;for(let i of e)a=a?.[i];this.set(t,a)}else this._state={...at},this._saveState(),this.dispatchEvent(new CustomEvent(it,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(t){let e=this.get("localTasks")||[],a={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...t};return this.set("localTasks",[...e,a]),a}updateLocalTask(t,e){let a=this.get("localTasks")||[],i=a.findIndex(r=>r.id===t);if(i===-1)return null;let s={...a[i],...e,updatedAt:new Date().toISOString()};return a[i]=s,this.set("localTasks",[...a]),s}deleteLocalTask(t){let e=this.get("localTasks")||[];this.set("localTasks",e.filter(a=>a.id!==t))}moveLocalTask(t,e,a=null){let s=(this.get("localTasks")||[]).find(r=>r.id===t);return s?this.updateLocalTask(t,{status:e,position:a??s.position}):null}updateSession(t){this.update(Object.fromEntries(Object.entries(t).map(([e,a])=>[`session.${e}`,a])),!1)}updateCache(t){this.update({"cache.projects":t.projects??this.get("cache.projects"),"cache.tasks":t.tasks??this.get("cache.tasks"),"cache.agents":t.agents??this.get("cache.agents"),"cache.memory":t.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let t=this.get("cache.tasks")||[],a=(this.get("localTasks")||[]).map(i=>({...i,isLocal:!0}));return[...t,...a]}getTasksByStatus(t){return this.getMergedTasks().filter(e=>e.status===t)}};k(f,"STORAGE_KEY","loki-dashboard-state"),k(f,"_instance",null);var M=f;function L(){return M.getInstance()}function ct(d){let t=L();return{get:()=>t.get(d),set:e=>t.set(d,e),subscribe:e=>t.subscribe(d,e)}}var F=class extends c{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()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(n.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(n.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(n.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(t,e,a){e!==a&&(t==="api-url"&&this._api&&(this._api.baseUrl=a,this._loadStatus()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t}),this._statusUpdateHandler=e=>this._updateFromStatus(e.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(n.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(n.CONNECTED,this._connectedHandler),this._api.addEventListener(n.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){try{let[t,e,a,i,s]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);t.status==="fulfilled"?this._updateFromStatus(t.value):(this._data.connected=!1,this._data.status="offline"),e.status==="fulfilled"&&(this._checklistSummary=e.value?.summary||null),a.status==="fulfilled"&&(this._appRunnerStatus=a.value),i.status==="fulfilled"&&(this._playwrightResults=i.value),s.status==="fulfilled"&&(this._gateStatus=s.value),this.render()}catch{this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(t){t&&(this._data={...this._data,connected:!0,status:t.status||"offline",phase:t.phase||null,iteration:t.iteration!=null?t.iteration:null,provider:t.provider||null,running_agents:t.running_agents||0,pending_tasks:t.pending_tasks!=null?t.pending_tasks:null,uptime_seconds:t.uptime_seconds||0,complexity:t.complexity||null})}_startPolling(){this._pollInterval=setInterval(async()=>{try{await this._loadStatus()}catch{this._data.connected=!1,this._data.status="offline",this.render()}},5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_formatUptime(t){if(!t||t<0)return"--";let e=Math.floor(t/3600),a=Math.floor(t%3600/60),i=Math.floor(t%60);return e>0?`${e}h ${a}m`:a>0?`${a}m ${i}s`:`${i}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(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let t=this._appRunnerStatus;if(!t||t.status==="not_initialized")return`
|
|
1225
|
+
`}getAriaPattern(t){return nt[t]||{}}applyAriaPattern(t,e){let i=this.getAriaPattern(e);for(let[a,s]of Object.entries(i))if(a==="role")t.setAttribute("role",s);else{let r=a.replace(/([A-Z])/g,"-$1").toLowerCase();t.setAttribute(r,s)}}render(){}};var L={realtime:1e3,normal:2e3,background:5e3,offline:1e4},gt={vscode:L.normal,browser:L.realtime,cli:L.background},ht={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},l={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"},C=class C extends EventTarget{static getInstance(t={}){let e=t.baseUrl||ht.baseUrl;return C._instances.has(e)||C._instances.set(e,new C(t)),C._instances.get(e)}static clearInstances(){C._instances.forEach(t=>t.disconnect()),C._instances.clear()}constructor(t={}){super(),this.config={...ht,...t},this._ws=null,this._connected=!1,this._pollInterval=null,this._reconnectTimeout=null,this._cache=new Map,this._cacheTimeout=5e3,this._vscodeApi=null,this._context=this._detectContext(),this._currentPollInterval=gt[this._context]||L.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 L}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(L.background):this._setPollInterval(gt[this._context]||L.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(t){this._currentPollInterval=t,this._pollInterval&&(this.stopPolling(),this.startPolling(null,t))}setPollMode(t){let e=L[t];e&&this._setPollInterval(e)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=t=>{let e=t.data;if(!(!e||!e.type))switch(e.type){case"updateStatus":this._emit(l.STATUS_UPDATE,e.data);break;case"updateTasks":this._emit(l.TASK_UPDATED,e.data);break;case"taskCreated":this._emit(l.TASK_CREATED,e.data);break;case"taskDeleted":this._emit(l.TASK_DELETED,e.data);break;case"projectCreated":this._emit(l.PROJECT_CREATED,e.data);break;case"projectUpdated":this._emit(l.PROJECT_UPDATED,e.data);break;case"agentUpdate":this._emit(l.AGENT_UPDATE,e.data);break;case"logMessage":this._emit(l.LOG_MESSAGE,e.data);break;case"memoryUpdate":this._emit(l.MEMORY_UPDATE,e.data);break;case"connected":this._connected=!0,this._emit(l.CONNECTED,e.data);break;case"disconnected":this._connected=!1,this._emit(l.DISCONNECTED,e.data);break;case"error":this._emit(l.ERROR,e.data);break;case"setPollMode":this.setPollMode(e.data.mode);break;default:this._emit(`api:${e.type}`,e.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(t,e={}){this._vscodeApi&&this._vscodeApi.postMessage({type:t,data:e})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(t,e={}){this.postToVSCode("userAction",{action:t,...e})}get baseUrl(){return this.config.baseUrl}set baseUrl(t){this.config.baseUrl=t,this.config.wsUrl=t.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((t,e)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._emit(l.CONNECTED),t()},this._ws.onclose=()=>{this._connected=!1,this._emit(l.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=i=>{this._emit(l.ERROR,{error:i}),e(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){e(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(){this._reconnectTimeout||(this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},this.config.retryDelay))}_handleMessage(t){let i={connected:l.CONNECTED,status_update:l.STATUS_UPDATE,task_created:l.TASK_CREATED,task_updated:l.TASK_UPDATED,task_deleted:l.TASK_DELETED,task_moved:l.TASK_UPDATED,project_created:l.PROJECT_CREATED,project_updated:l.PROJECT_UPDATED,agent_update:l.AGENT_UPDATE,log:l.LOG_MESSAGE}[t.type]||`api:${t.type}`;this._emit(i,t.data)}_emit(t,e={}){this.dispatchEvent(new CustomEvent(t,{detail:e}))}async _request(t,e={}){let i=`${this.config.baseUrl}${t}`,a=new AbortController,s=setTimeout(()=>a.abort(),this.config.timeout);try{let r=await fetch(i,{...e,signal:a.signal,headers:{"Content-Type":"application/json",...e.headers}});if(clearTimeout(s),!r.ok){let o=await r.json().catch(()=>({detail:r.statusText}));throw new Error(o.detail||`HTTP ${r.status}`)}return r.status===204?null:await r.json()}catch(r){throw clearTimeout(s),r.name==="AbortError"?new Error("Request timeout"):r}}async _get(t,e=!1){if(e&&this._cache.has(t)){let a=this._cache.get(t);if(Date.now()-a.timestamp<this._cacheTimeout)return a.data}let i=await this._request(t);return e&&this._cache.set(t,{data:i,timestamp:Date.now()}),i}async _post(t,e){return this._request(t,{method:"POST",body:JSON.stringify(e)})}async _put(t,e){return this._request(t,{method:"PUT",body:JSON.stringify(e)})}async _delete(t){return this._request(t,{method:"DELETE"})}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(t=null){let e=t?`?status=${t}`:"";return this._get(`/api/projects${e}`)}async getProject(t){return this._get(`/api/projects/${t}`)}async createProject(t){return this._post("/api/projects",t)}async updateProject(t,e){return this._put(`/api/projects/${t}`,e)}async deleteProject(t){return this._delete(`/api/projects/${t}`)}async listTasks(t={}){let e=new URLSearchParams;t.projectId&&e.append("project_id",t.projectId),t.status&&e.append("status",t.status),t.priority&&e.append("priority",t.priority);let i=e.toString()?`?${e}`:"";return this._get(`/api/tasks${i}`)}async getTask(t){return this._get(`/api/tasks/${t}`)}async createTask(t){return this._post("/api/tasks",t)}async updateTask(t,e){return this._put(`/api/tasks/${t}`,e)}async moveTask(t,e,i){return this._post(`/api/tasks/${t}/move`,{status:e,position:i})}async deleteTask(t){return this._delete(`/api/tasks/${t}`)}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(t={}){let e=new URLSearchParams(t).toString();return this._get(`/api/memory/episodes${e?"?"+e:""}`)}async getEpisode(t){return this._get(`/api/memory/episodes/${t}`)}async listPatterns(t={}){let e=new URLSearchParams(t).toString();return this._get(`/api/memory/patterns${e?"?"+e:""}`)}async getPattern(t){return this._get(`/api/memory/patterns/${t}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(t){return this._get(`/api/memory/skills/${t}`)}async retrieveMemories(t,e=null,i=5){return this._post("/api/memory/retrieve",{query:t,taskType:e,topK:i})}async consolidateMemory(t=24){return this._post("/api/memory/consolidate",{sinceHours:t})}async getTokenEconomics(){return this._get("/api/memory/economics")}async listRegisteredProjects(t=!1){return this._get(`/api/registry/projects?include_inactive=${t}`)}async registerProject(t,e=null,i=null){return this._post("/api/registry/projects",{path:t,name:e,alias:i})}async discoverProjects(t=3){return this._get(`/api/registry/discover?max_depth=${t}`)}async syncRegistry(){return this._post("/api/registry/sync",{})}async getCrossProjectTasks(t=null){let e=t?`?project_ids=${t.join(",")}`:"";return this._get(`/api/registry/tasks${e}`)}async getLearningMetrics(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source);let i=e.toString()?`?${e}`:"";return this._get(`/api/learning/metrics${i}`)}async getLearningTrends(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source);let i=e.toString()?`?${e}`:"";return this._get(`/api/learning/trends${i}`)}async getLearningSignals(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source),t.limit&&e.append("limit",String(t.limit)),t.offset&&e.append("offset",String(t.offset));let i=e.toString()?`?${e}`:"";return this._get(`/api/learning/signals${i}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(t={}){return this._post("/api/learning/aggregate",t)}async getAggregatedPreferences(t=20){return this._get(`/api/learning/preferences?limit=${t}`)}async getAggregatedErrors(t=20){return this._get(`/api/learning/errors?limit=${t}`)}async getAggregatedSuccessPatterns(t=20){return this._get(`/api/learning/success?limit=${t}`)}async getToolEfficiency(t=20){return this._get(`/api/learning/tools?limit=${t}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(t=20){return this._get(`/api/council/verdicts?limit=${t}`)}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(t,e){let i=new URLSearchParams;t&&i.set("severity",t),e&&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(t){return this._put("/api/notifications/triggers",{triggers:t})}async acknowledgeNotification(t){return this._post("/api/notifications/"+encodeURIComponent(t)+"/acknowledge",{})}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 getLogs(t=100){return this._get(`/api/logs?lines=${t}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let t=await fetch(`${this.baseUrl}/api/prd-observations`);if(!t.ok)throw new Error(`HTTP ${t.status}`);return t.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(t,e,i="dashboard"){return this._post("/api/checklist/waivers",{item_id:t,reason:e,waived_by:i})}async removeChecklistWaiver(t){return this._delete(`/api/checklist/waivers/${encodeURIComponent(t)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(t=100){return this._get(`/api/app-runner/logs?lines=${t}`)}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(t,e=null){if(this._pollInterval)return;this._pollCallback=t;let i=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(l.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(l.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};i();let a=e||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(i,a)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};w(C,"_instances",new Map);var R=C;function vt(c={}){return new R(c)}function u(c={}){return R.getInstance(c)}var ct="loki-state-change",dt={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}},$=class $ extends EventTarget{static getInstance(){return $._instance||($._instance=new $),$._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let t=localStorage.getItem($.STORAGE_KEY);if(t){let e=JSON.parse(t);return this._mergeState(dt,e)}}catch(t){console.warn("Failed to load state from localStorage:",t)}return{...dt}}_mergeState(t,e){let i={...t};for(let a of Object.keys(e))a in t&&typeof t[a]=="object"&&!Array.isArray(t[a])?i[a]=this._mergeState(t[a],e[a]):i[a]=e[a];return i}_saveState(){try{let t={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem($.STORAGE_KEY,JSON.stringify(t))}catch(t){console.warn("Failed to save state to localStorage:",t)}}get(t=null){if(!t)return{...this._state};let e=t.split("."),i=this._state;for(let a of e){if(i==null)return;i=i[a]}return i}set(t,e,i=!0){let a=t.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]=e,i&&this._saveState(),this._notifyChange(t,e,o)}update(t,e=!0){let i=[];for(let[a,s]of Object.entries(t)){let r=this.get(a);this.set(a,s,!1),i.push({path:a,value:s,oldValue:r})}e&&this._saveState();for(let a of i)this._notifyChange(a.path,a.value,a.oldValue)}_notifyChange(t,e,i){this.dispatchEvent(new CustomEvent(ct,{detail:{path:t,value:e,oldValue:i}}));let a=this._subscribers.get(t)||[];for(let r of a)try{r(e,i,t)}catch(o){console.error("State subscriber error:",o)}let s=t.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(d){console.error("State subscriber error:",d)}}}subscribe(t,e){return this._subscribers.has(t)||this._subscribers.set(t,[]),this._subscribers.get(t).push(e),()=>{let i=this._subscribers.get(t),a=i.indexOf(e);a>-1&&i.splice(a,1)}}reset(t=null){if(t){let e=t.split("."),i=dt;for(let a of e)i=i?.[a];this.set(t,i)}else this._state={...dt},this._saveState(),this.dispatchEvent(new CustomEvent(ct,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(t){let e=this.get("localTasks")||[],i={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...t};return this.set("localTasks",[...e,i]),i}updateLocalTask(t,e){let i=this.get("localTasks")||[],a=i.findIndex(r=>r.id===t);if(a===-1)return null;let s={...i[a],...e,updatedAt:new Date().toISOString()};return i[a]=s,this.set("localTasks",[...i]),s}deleteLocalTask(t){let e=this.get("localTasks")||[];this.set("localTasks",e.filter(i=>i.id!==t))}moveLocalTask(t,e,i=null){let s=(this.get("localTasks")||[]).find(r=>r.id===t);return s?this.updateLocalTask(t,{status:e,position:i??s.position}):null}updateSession(t){this.update(Object.fromEntries(Object.entries(t).map(([e,i])=>[`session.${e}`,i])),!1)}updateCache(t){this.update({"cache.projects":t.projects??this.get("cache.projects"),"cache.tasks":t.tasks??this.get("cache.tasks"),"cache.agents":t.agents??this.get("cache.agents"),"cache.memory":t.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let t=this.get("cache.tasks")||[],i=(this.get("localTasks")||[]).map(a=>({...a,isLocal:!0}));return[...t,...i]}getTasksByStatus(t){return this.getMergedTasks().filter(e=>e.status===t)}};w($,"STORAGE_KEY","loki-dashboard-state"),w($,"_instance",null);var F=$;function z(){return F.getInstance()}function mt(c){let t=z();return{get:()=>t.get(c),set:e=>t.set(c,e),subscribe:e=>t.subscribe(c,e)}}var j=class extends p{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()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(l.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(l.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(l.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t}),this._statusUpdateHandler=e=>this._updateFromStatus(e.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(l.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(l.CONNECTED,this._connectedHandler),this._api.addEventListener(l.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){try{let[t,e,i,a,s]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);t.status==="fulfilled"?this._updateFromStatus(t.value):(this._data.connected=!1,this._data.status="offline"),e.status==="fulfilled"&&(this._checklistSummary=e.value?.summary||null),i.status==="fulfilled"&&(this._appRunnerStatus=i.value),a.status==="fulfilled"&&(this._playwrightResults=a.value),s.status==="fulfilled"&&(this._gateStatus=s.value),this.render()}catch{this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(t){t&&(this._data={...this._data,connected:!0,status:t.status||"offline",phase:t.phase||null,iteration:t.iteration!=null?t.iteration:null,provider:t.provider||null,running_agents:t.running_agents||0,pending_tasks:t.pending_tasks!=null?t.pending_tasks:null,uptime_seconds:t.uptime_seconds||0,complexity:t.complexity||null})}_startPolling(){this._pollInterval=setInterval(async()=>{try{await this._loadStatus()}catch{this._data.connected=!1,this._data.status="offline",this.render()}},5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_formatUptime(t){if(!t||t<0)return"--";let e=Math.floor(t/3600),i=Math.floor(t%3600/60),a=Math.floor(t%60);return e>0?`${e}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(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let t=this._appRunnerStatus;if(!t||t.status==="not_initialized")return`
|
|
1196
1226
|
<div class="overview-card">
|
|
1197
1227
|
<div class="card-label">App Runner</div>
|
|
1198
1228
|
<div class="card-value small-text">--</div>
|
|
1199
1229
|
</div>
|
|
1200
|
-
`;let
|
|
1230
|
+
`;let i={running:"var(--loki-green, #22c55e)",starting:"var(--loki-yellow, #f59e0b)",crashed:"var(--loki-red, #ef4444)",stopped:"var(--loki-text-muted, #a1a1aa)"}[t.status]||"var(--loki-text-muted)",a=t.status==="running"?"active":t.status==="crashed"?"error":"offline",s=(t.status||"unknown").toUpperCase(),r=t.port?`:${t.port}`:"";return`
|
|
1201
1231
|
<div class="overview-card">
|
|
1202
1232
|
<div class="card-label">App Runner</div>
|
|
1203
1233
|
<div class="card-value small-text">
|
|
1204
|
-
<span class="status-dot ${
|
|
1234
|
+
<span class="status-dot ${a}"></span>
|
|
1205
1235
|
${s}${r}
|
|
1206
1236
|
</div>
|
|
1207
1237
|
${t.method?`<div style="font-size:10px;color:var(--loki-text-muted);margin-top:2px;">${this._escapeHtml(t.method)}</div>`:""}
|
|
@@ -1211,12 +1241,12 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1211
1241
|
<div class="card-label">Verification</div>
|
|
1212
1242
|
<div class="card-value small-text">--</div>
|
|
1213
1243
|
</div>
|
|
1214
|
-
`;let e=t.passed===!0,
|
|
1244
|
+
`;let e=t.passed===!0,i=e?"var(--loki-green, #22c55e)":"var(--loki-red, #ef4444)",a=e?"PASSED":"FAILED",s=e?"active":"error",r=t.checks||{},o=Object.values(r).filter(n=>!n).length;return`
|
|
1215
1245
|
<div class="overview-card">
|
|
1216
1246
|
<div class="card-label">Verification</div>
|
|
1217
1247
|
<div class="card-value small-text">
|
|
1218
1248
|
<span class="status-dot ${s}"></span>
|
|
1219
|
-
${
|
|
1249
|
+
${a}
|
|
1220
1250
|
</div>
|
|
1221
1251
|
${!e&&o>0?`<div style="font-size:10px;color:var(--loki-red,#ef4444);margin-top:2px;">${o} check(s) failed</div>`:""}
|
|
1222
1252
|
</div>
|
|
@@ -1225,12 +1255,12 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1225
1255
|
<div class="card-label">PRD Progress</div>
|
|
1226
1256
|
<div class="card-value small-text">--</div>
|
|
1227
1257
|
</div>
|
|
1228
|
-
`;let e=Math.round(t.verified/t.total*100),
|
|
1258
|
+
`;let e=Math.round(t.verified/t.total*100),i=t.failing>0?"var(--loki-yellow, #f59e0b)":"var(--loki-green, #22c55e)";return`
|
|
1229
1259
|
<div class="overview-card">
|
|
1230
1260
|
<div class="card-label">PRD Progress</div>
|
|
1231
1261
|
<div class="card-value small-text">${t.verified}/${t.total} (${e}%)</div>
|
|
1232
1262
|
<div class="mini-progress" style="margin-top:4px;height:4px;background:var(--loki-bg-secondary,#e4e4e7);border-radius:2px;overflow:hidden;">
|
|
1233
|
-
<div style="width:${e}%;height:100%;background:${
|
|
1263
|
+
<div style="width:${e}%;height:100%;background:${i};transition:width 0.3s;"></div>
|
|
1234
1264
|
</div>
|
|
1235
1265
|
${t.failing?`<div style="font-size:10px;color:var(--loki-red,#ef4444);margin-top:2px;">${t.failing} failing</div>`:""}
|
|
1236
1266
|
</div>
|
|
@@ -1259,7 +1289,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1259
1289
|
PASSED
|
|
1260
1290
|
</div>
|
|
1261
1291
|
</div>
|
|
1262
|
-
`}render(){let t=this._getStatusDotClass(),e=this._escapeHtml((this._data.status||"OFFLINE").toUpperCase()),
|
|
1292
|
+
`}render(){let t=this._getStatusDotClass(),e=this._escapeHtml((this._data.status||"OFFLINE").toUpperCase()),i=this._escapeHtml(this._data.phase||"--"),a=this._escapeHtml(this._data.iteration!=null?String(this._data.iteration):"0"),s=this._escapeHtml((this._data.provider||"CLAUDE").toUpperCase()),r=this._escapeHtml(String(this._data.running_agents||0)),o=this._escapeHtml(this._data.pending_tasks!=null?`${this._data.pending_tasks} pending`:"--"),n=this._escapeHtml(this._formatUptime(this._data.uptime_seconds)),d=this._escapeHtml((this._data.complexity||"STANDARD").toUpperCase());this.shadowRoot.innerHTML=`
|
|
1263
1293
|
<style>
|
|
1264
1294
|
${this.getBaseStyles()}
|
|
1265
1295
|
|
|
@@ -1393,12 +1423,12 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1393
1423
|
|
|
1394
1424
|
<div class="overview-card">
|
|
1395
1425
|
<div class="card-label">Phase</div>
|
|
1396
|
-
<div class="card-value small-text">${
|
|
1426
|
+
<div class="card-value small-text">${i}</div>
|
|
1397
1427
|
</div>
|
|
1398
1428
|
|
|
1399
1429
|
<div class="overview-card">
|
|
1400
1430
|
<div class="card-label">Iteration</div>
|
|
1401
|
-
<div class="card-value">${
|
|
1431
|
+
<div class="card-value">${a}</div>
|
|
1402
1432
|
</div>
|
|
1403
1433
|
|
|
1404
1434
|
<div class="overview-card">
|
|
@@ -1426,16 +1456,16 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1426
1456
|
|
|
1427
1457
|
<div class="overview-card">
|
|
1428
1458
|
<div class="card-label">Uptime</div>
|
|
1429
|
-
<div class="card-value small-text">${
|
|
1459
|
+
<div class="card-value small-text">${n}</div>
|
|
1430
1460
|
</div>
|
|
1431
1461
|
|
|
1432
1462
|
<div class="overview-card">
|
|
1433
1463
|
<div class="card-label">Complexity</div>
|
|
1434
|
-
<div class="card-value small-text">${
|
|
1464
|
+
<div class="card-value small-text">${d}</div>
|
|
1435
1465
|
</div>
|
|
1436
1466
|
</div>
|
|
1437
1467
|
</div>
|
|
1438
|
-
`}};customElements.get("loki-overview")||customElements.define("loki-overview",
|
|
1468
|
+
`}};customElements.get("loki-overview")||customElements.define("loki-overview",j);var Lt=[{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)"}];var U=class extends p{static get observedAttributes(){return["api-url","project-id","theme","readonly"]}constructor(){super(),this._tasks=[],this._loading=!0,this._error=null,this._draggedTask=null,this._api=null,this._state=z()}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadTasks()}disconnectedCallback(){super.disconnectedCallback(),this._api&&(this._api.removeEventListener(l.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(l.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(l.TASK_DELETED,this._onTaskEvent))}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadTasks()),t==="project-id"&&this._loadTasks(),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t}),this._onTaskEvent&&(this._api.removeEventListener(l.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(l.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(l.TASK_DELETED,this._onTaskEvent)),this._onTaskEvent=()=>this._loadTasks(),this._api.addEventListener(l.TASK_CREATED,this._onTaskEvent),this._api.addEventListener(l.TASK_UPDATED,this._onTaskEvent),this._api.addEventListener(l.TASK_DELETED,this._onTaskEvent)}async _loadTasks(){this._loading=!0,this._error=null,this.render();try{let t=this.getAttribute("project-id"),e=t?{projectId:parseInt(t)}:{};this._tasks=await this._api.listTasks(e);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(t){this._error=t.message,this._tasks=(this._state.get("localTasks")||[]).map(e=>({...e,isLocal:!0}))}this._loading=!1,this.render()}_getTasksByStatus(t){return this._tasks.filter(e=>e.status?.toLowerCase().replace(/-/g,"_")===t)}_handleDragStart(t,e){this.hasAttribute("readonly")||(this._draggedTask=e,t.target.classList.add("dragging"),t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",e.id.toString()))}_handleDragEnd(t){t.target.classList.remove("dragging"),this._draggedTask=null,this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(e=>{e.classList.remove("drag-over")})}_handleDragOver(t){t.preventDefault(),t.dataTransfer.dropEffect="move"}_handleDragEnter(t){t.preventDefault(),t.currentTarget.classList.add("drag-over")}_handleDragLeave(t){t.currentTarget.contains(t.relatedTarget)||t.currentTarget.classList.remove("drag-over")}async _handleDrop(t,e){if(t.preventDefault(),t.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!==e){a.status=e,this.render();try{a.isLocal?this._state.moveLocalTask(i,e):await this._api.moveTask(i,e,0),this.dispatchEvent(new CustomEvent("task-moved",{detail:{taskId:i,oldStatus:s,newStatus:e}}))}catch(r){a.status=s,this.render(),console.error("Failed to move task:",r)}}}_openAddTaskModal(t="pending"){this.dispatchEvent(new CustomEvent("add-task",{detail:{status:t}}))}_openTaskDetail(t){this.dispatchEvent(new CustomEvent("task-click",{detail:{task:t}}))}render(){let t=`
|
|
1439
1469
|
<style>
|
|
1440
1470
|
${this.getBaseStyles()}
|
|
1441
1471
|
|
|
@@ -1672,9 +1702,9 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1672
1702
|
fill: none;
|
|
1673
1703
|
}
|
|
1674
1704
|
</style>
|
|
1675
|
-
`,e=
|
|
1705
|
+
`,e=a=>{switch(a){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"/>'}},i;if(this._loading)i='<div class="loading">Loading tasks...</div>';else if(this._error&&this._tasks.length===0)i=`<div class="error">Error: ${this._error}</div>`;else{let a=this.hasAttribute("readonly");i=`
|
|
1676
1706
|
<div class="kanban-board">
|
|
1677
|
-
${
|
|
1707
|
+
${Lt.map(s=>{let r=this._getTasksByStatus(s.status);return`
|
|
1678
1708
|
<div class="kanban-column" data-status="${s.status}">
|
|
1679
1709
|
<div class="kanban-column-header">
|
|
1680
1710
|
<span class="kanban-column-title">
|
|
@@ -1688,12 +1718,12 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1688
1718
|
<div class="kanban-tasks" data-status="${s.status}">
|
|
1689
1719
|
${r.length===0?'<div class="empty-column">No tasks</div>':""}
|
|
1690
1720
|
${r.map(o=>`
|
|
1691
|
-
<div class="task-card ${!
|
|
1721
|
+
<div class="task-card ${!a&&!o.fromServer?"draggable":""} ${o.isLocal?"local":""}"
|
|
1692
1722
|
data-task-id="${o.id}"
|
|
1693
1723
|
tabindex="0"
|
|
1694
1724
|
role="button"
|
|
1695
1725
|
aria-label="Task: ${this._escapeHtml(o.title||"Untitled")}, ${o.priority||"medium"} priority"
|
|
1696
|
-
${!
|
|
1726
|
+
${!a&&!o.fromServer?'draggable="true"':""}>
|
|
1697
1727
|
<div class="task-card-header">
|
|
1698
1728
|
<span class="task-id">${o.isLocal?"LOCAL":"#"+o.id}</span>
|
|
1699
1729
|
<span class="task-priority ${(o.priority||"medium").toLowerCase()}">${o.priority||"medium"}</span>
|
|
@@ -1706,7 +1736,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1706
1736
|
</div>
|
|
1707
1737
|
`).join("")}
|
|
1708
1738
|
</div>
|
|
1709
|
-
${!
|
|
1739
|
+
${!a&&s.status==="pending"?`
|
|
1710
1740
|
<button class="add-task-btn" data-status="${s.status}" aria-label="Add new task to ${s.label}">+ Add Task</button>
|
|
1711
1741
|
`:""}
|
|
1712
1742
|
</div>
|
|
@@ -1728,9 +1758,9 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1728
1758
|
</button>
|
|
1729
1759
|
</div>
|
|
1730
1760
|
</div>
|
|
1731
|
-
${
|
|
1761
|
+
${i}
|
|
1732
1762
|
</div>
|
|
1733
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadTasks()),this.shadowRoot.querySelectorAll(".add-task-btn").forEach(e=>{e.addEventListener("click",()=>{this._openAddTaskModal(e.dataset.status)})}),this.shadowRoot.querySelectorAll(".task-card").forEach(e=>{let
|
|
1763
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadTasks()),this.shadowRoot.querySelectorAll(".add-task-btn").forEach(e=>{e.addEventListener("click",()=>{this._openAddTaskModal(e.dataset.status)})}),this.shadowRoot.querySelectorAll(".task-card").forEach(e=>{let i=e.dataset.taskId,a=this._tasks.find(s=>s.id.toString()===i);a&&(e.addEventListener("click",()=>this._openTaskDetail(a)),e.addEventListener("keydown",s=>{s.key==="Enter"||s.key===" "?(s.preventDefault(),this._openTaskDetail(a)):(s.key==="ArrowDown"||s.key==="ArrowUp")&&(s.preventDefault(),this._navigateTaskCards(e,s.key==="ArrowDown"?"next":"prev"))}),e.classList.contains("draggable")&&(e.addEventListener("dragstart",s=>this._handleDragStart(s,a)),e.addEventListener("dragend",s=>this._handleDragEnd(s))))}),this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(e=>{e.addEventListener("dragover",i=>this._handleDragOver(i)),e.addEventListener("dragenter",i=>this._handleDragEnter(i)),e.addEventListener("dragleave",i=>this._handleDragLeave(i)),e.addEventListener("drop",i=>this._handleDrop(i,e.dataset.status))})}_escapeHtml(t){let e=document.createElement("div");return e.textContent=t,e.innerHTML}_navigateTaskCards(t,e){let i=Array.from(this.shadowRoot.querySelectorAll(".task-card")),a=i.indexOf(t);if(a===-1)return;let s=e==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-task-board")||customElements.define("loki-task-board",U);var O=class extends p{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._api=null,this._state=z(),this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(l.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(l.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(l.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),t==="theme"&&this._applyTheme(),t==="compact"&&this.render())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t}),this._statusUpdateHandler=e=>this._updateFromStatus(e.detail),this._connectedHandler=()=>{this._status.connected=!0,this.render()},this._disconnectedHandler=()=>{this._status.connected=!1,this._status.mode="offline",this.render()},this._api.addEventListener(l.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(l.CONNECTED,this._connectedHandler),this._api.addEventListener(l.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){try{let t=await this._api.getStatus();this._updateFromStatus(t)}catch{this._status.connected=!1,this._status.mode="offline",this.render()}}_updateFromStatus(t){t&&(this._status={...this._status,connected:!0,mode:t.status||"running",version:t.version,uptime:t.uptime_seconds||0,activeAgents:t.running_agents||0,pendingTasks:t.pending_tasks||0,phase:t.phase,iteration:t.iteration,complexity:t.complexity},this._state.updateSession({connected:!0,mode:this._status.mode,lastSync:new Date().toISOString()}),this.render())}_startPolling(){this._ownPollInterval=setInterval(async()=>{try{let t=await this._api.getStatus();this._updateFromStatus(t)}catch{this._status.connected=!1,this._status.mode="offline",this.render()}},3e3)}_stopPolling(){this._ownPollInterval&&(clearInterval(this._ownPollInterval),this._ownPollInterval=null)}_formatUptime(t){if(!t||t<0)return"--";let e=Math.floor(t/3600),i=Math.floor(t%3600/60),a=Math.floor(t%60);return e>0?`${e}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_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"}}_triggerStart(){this.dispatchEvent(new CustomEvent("session-start",{detail:this._status}))}async _triggerPause(){try{await this._api.pauseSession(),this._status.mode="paused",this.render()}catch(t){console.error("Failed to pause session:",t)}this.dispatchEvent(new CustomEvent("session-pause",{detail:this._status}))}async _triggerResume(){try{await this._api.resumeSession(),this._status.mode="running",this.render()}catch(t){console.error("Failed to resume session:",t)}this.dispatchEvent(new CustomEvent("session-resume",{detail:this._status}))}async _triggerStop(){try{await this._api.stopSession(),this._status.mode="stopped",this.render()}catch(t){console.error("Failed to stop session:",t)}this.dispatchEvent(new CustomEvent("session-stop",{detail:this._status}))}render(){let t=this.hasAttribute("compact"),e=this._getStatusClass(),i=this._getStatusLabel(),a=["running","autonomous"].includes(this._status.mode),s=this._status.mode==="paused",r=`
|
|
1734
1764
|
<style>
|
|
1735
1765
|
${this.getBaseStyles()}
|
|
1736
1766
|
|
|
@@ -1918,7 +1948,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1918
1948
|
<div class="status-row">
|
|
1919
1949
|
<span class="status-value">
|
|
1920
1950
|
<span class="status-dot ${e}"></span>
|
|
1921
|
-
${
|
|
1951
|
+
${i}
|
|
1922
1952
|
</span>
|
|
1923
1953
|
</div>
|
|
1924
1954
|
<div class="control-buttons" role="group" aria-label="Session controls">
|
|
@@ -1928,18 +1958,18 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1928
1958
|
Resume
|
|
1929
1959
|
</button>
|
|
1930
1960
|
`:`
|
|
1931
|
-
<button class="control-btn pause" id="pause-btn" aria-label="Pause session" ${
|
|
1961
|
+
<button class="control-btn pause" id="pause-btn" aria-label="Pause session" ${a?"":"disabled"}>
|
|
1932
1962
|
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>
|
|
1933
1963
|
Pause
|
|
1934
1964
|
</button>
|
|
1935
1965
|
`}
|
|
1936
|
-
<button class="control-btn stop" id="stop-btn" aria-label="Stop session" ${!
|
|
1966
|
+
<button class="control-btn stop" id="stop-btn" aria-label="Stop session" ${!a&&!s?"disabled":""}>
|
|
1937
1967
|
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="2"/></svg>
|
|
1938
1968
|
Stop
|
|
1939
1969
|
</button>
|
|
1940
1970
|
</div>
|
|
1941
1971
|
</div>
|
|
1942
|
-
`,
|
|
1972
|
+
`,n=`
|
|
1943
1973
|
<div class="control-panel">
|
|
1944
1974
|
<div class="panel-title">System Status</div>
|
|
1945
1975
|
|
|
@@ -1947,7 +1977,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1947
1977
|
<span class="status-label">Mode</span>
|
|
1948
1978
|
<span class="status-value">
|
|
1949
1979
|
<span class="status-dot ${e}"></span>
|
|
1950
|
-
${
|
|
1980
|
+
${i}
|
|
1951
1981
|
</span>
|
|
1952
1982
|
</div>
|
|
1953
1983
|
|
|
@@ -1978,12 +2008,12 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
1978
2008
|
Resume
|
|
1979
2009
|
</button>
|
|
1980
2010
|
`:`
|
|
1981
|
-
<button class="control-btn pause" id="pause-btn" aria-label="Pause session" ${
|
|
2011
|
+
<button class="control-btn pause" id="pause-btn" aria-label="Pause session" ${a?"":"disabled"}>
|
|
1982
2012
|
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>
|
|
1983
2013
|
Pause
|
|
1984
2014
|
</button>
|
|
1985
2015
|
`}
|
|
1986
|
-
<button class="control-btn stop" id="stop-btn" aria-label="Stop session" ${!
|
|
2016
|
+
<button class="control-btn stop" id="stop-btn" aria-label="Stop session" ${!a&&!s?"disabled":""}>
|
|
1987
2017
|
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="2"/></svg>
|
|
1988
2018
|
Stop
|
|
1989
2019
|
</button>
|
|
@@ -2008,14 +2038,14 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2008
2038
|
</div>
|
|
2009
2039
|
`;this.shadowRoot.innerHTML=`
|
|
2010
2040
|
${r}
|
|
2011
|
-
${t?o:
|
|
2012
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("pause-btn"),e=this.shadowRoot.getElementById("resume-btn"),
|
|
2013
|
-
`);if(r.length>e){let o=r.slice(e);for(let
|
|
2014
|
-
`),e=new Blob([t],{type:"text/plain"}),
|
|
2041
|
+
${t?o:n}
|
|
2042
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("pause-btn"),e=this.shadowRoot.getElementById("resume-btn"),i=this.shadowRoot.getElementById("stop-btn"),a=this.shadowRoot.getElementById("start-btn");t&&t.addEventListener("click",()=>this._triggerPause()),e&&e.addEventListener("click",()=>this._triggerResume()),i&&i.addEventListener("click",()=>this._triggerStop()),a&&a.addEventListener("click",()=>this._triggerStart())}};customElements.get("loki-session-control")||customElements.define("loki-session-control",O);var bt={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"}},N=class extends p{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}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(l.LOG_MESSAGE,this._logMessageHandler)}attributeChangedCallback(t,e,i){if(e!==i)switch(t){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 t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t}),this._logMessageHandler=e=>this._addLog(e.detail),this._api.addEventListener(l.LOG_MESSAGE,this._logMessageHandler)}_startLogPolling(){let t=this.getAttribute("log-file");t?this._pollLogFile(t):this._pollApiLogs()}async _pollApiLogs(){let t=0,e=async()=>{try{let i=await this._api.getLogs(200);if(Array.isArray(i)&&i.length>t){let a=i.slice(t);for(let s of a)s.message&&s.message.trim()&&this._addLog({message:s.message,level:s.level||"info",timestamp:s.timestamp||new Date().toLocaleTimeString()});t=i.length}}catch{}};e(),this._apiPollInterval=setInterval(e,2e3)}async _pollLogFile(t){let e=0,i=async()=>{try{let a=await fetch(`${t}?t=${Date.now()}`);if(!a.ok)return;let r=(await a.text()).split(`
|
|
2043
|
+
`);if(r.length>e){let o=r.slice(e);for(let n of o)n.trim()&&this._addLog(this._parseLine(n));e=r.length}}catch{}};i(),this._pollInterval=setInterval(i,1e3)}_stopLogPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._apiPollInterval&&(clearInterval(this._apiPollInterval),this._apiPollInterval=null)}_parseLine(t){let e=t.match(/^\[([^\]]+)\]\s*\[([^\]]+)\]\s*(.+)$/);if(e)return{timestamp:e[1],level:e[2].toLowerCase(),message:e[3]};let i=t.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:t}}_addLog(t){if(!t)return;let e={id:Date.now()+Math.random(),timestamp:t.timestamp||new Date().toLocaleTimeString(),level:(t.level||"info").toLowerCase(),message:t.message||t};this._logs.push(e),this._trimLogs(),this.dispatchEvent(new CustomEvent("log-received",{detail:e})),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 t=this.shadowRoot.getElementById("log-output");t&&(t.scrollTop=t.scrollHeight)})}_downloadLogs(){let t=this._logs.map(s=>`[${s.timestamp}] [${s.level.toUpperCase()}] ${s.message}`).join(`
|
|
2044
|
+
`),e=new Blob([t],{type:"text/plain"}),i=URL.createObjectURL(e),a=document.createElement("a");a.href=i,a.download=`loki-logs-${new Date().toISOString().split("T")[0]}.txt`,a.click(),URL.revokeObjectURL(i)}_setFilter(t){this._filter=t.toLowerCase(),this._renderLogs()}_setLevelFilter(t){this._levelFilter=t,this._renderLogs()}_getFilteredLogs(){return this._logs.filter(t=>!(this._levelFilter!=="all"&&t.level!==this._levelFilter||this._filter&&!t.message.toLowerCase().includes(this._filter)))}_renderLogs(){let t=this.shadowRoot.getElementById("log-output");if(!t)return;let e=this._getFilteredLogs();if(e.length===0){t.innerHTML='<div class="log-empty">No log output yet. Terminal will update when Loki Mode is running.</div>';return}t.innerHTML=e.map(i=>{let a=bt[i.level]||bt.info;return`
|
|
2015
2045
|
<div class="log-line">
|
|
2016
|
-
<span class="timestamp">${this._escapeHtml(
|
|
2017
|
-
<span class="level" style="color: ${
|
|
2018
|
-
<span class="message">${this._escapeHtml(
|
|
2046
|
+
<span class="timestamp">${this._escapeHtml(i.timestamp)}</span>
|
|
2047
|
+
<span class="level" style="color: ${a.color}">[${this._escapeHtml(a.label)}]</span>
|
|
2048
|
+
<span class="message">${this._escapeHtml(i.message)}</span>
|
|
2019
2049
|
</div>
|
|
2020
2050
|
`}).join(""),this._autoScroll&&this._scrollToBottom()}_escapeHtml(t){let e=document.createElement("div");return e.textContent=t,e.innerHTML}render(){let t=`
|
|
2021
2051
|
<style>
|
|
@@ -2210,10 +2240,10 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2210
2240
|
${this._logs.length} lines (${this._getFilteredLogs().length} shown)
|
|
2211
2241
|
</div>
|
|
2212
2242
|
</div>
|
|
2213
|
-
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let t=this.shadowRoot.getElementById("filter-input"),e=this.shadowRoot.getElementById("level-select"),
|
|
2243
|
+
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let t=this.shadowRoot.getElementById("filter-input"),e=this.shadowRoot.getElementById("level-select"),i=this.shadowRoot.getElementById("auto-scroll-btn"),a=this.shadowRoot.getElementById("clear-btn"),s=this.shadowRoot.getElementById("download-btn");t&&(t.value=this._filter,t.addEventListener("input",r=>this._setFilter(r.target.value))),e&&(e.value=this._levelFilter,e.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(t,e="info"){this._addLog({message:t,level:e,timestamp:new Date().toLocaleTimeString()})}clear(){this._clearLogs()}};customElements.get("loki-log-stream")||customElements.define("loki-log-stream",N);var It=[{id:"summary",label:"Summary",icon:"M4 6h16M4 12h16M4 18h16"},{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"}],q=class extends p{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._episodes=[],this._patterns=[],this._skills=[],this._tokenEconomics=null,this._selectedItem=null,this._lastFocusedElement=null}connectedCallback(){super.connectedCallback(),this._activeTab=this.getAttribute("tab")||"summary",this._setupApi(),this._loadData()}attributeChangedCallback(t,e,i){if(e!==i)switch(t){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 t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}async _loadData(){this._loading=!0,this._error=null,this.render();try{this._summary=await this._api.getMemorySummary().catch(()=>null),this._tokenEconomics=await this._api.getTokenEconomics().catch(()=>null),await this._loadTabData()}catch(t){this._error=t.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(t){this._activeTab!==t&&(this._activeTab=t,this._selectedItem=null,this._loadTabData().then(()=>this.render()))}async _selectEpisode(t){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getEpisode(t),this.dispatchEvent(new CustomEvent("episode-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(e){console.error("Failed to load episode:",e)}}async _selectPattern(t){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getPattern(t),this.dispatchEvent(new CustomEvent("pattern-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(e){console.error("Failed to load pattern:",e)}}async _selectSkill(t){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getSkill(t),this.dispatchEvent(new CustomEvent("skill-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(e){console.error("Failed to load skill:",e)}}_focusDetailPanel(){requestAnimationFrame(()=>{let t=this.shadowRoot.getElementById("close-detail");t&&t.focus()})}_closeDetail(){this._selectedItem=null,this.render(),this._lastFocusedElement&&requestAnimationFrame(()=>{this._lastFocusedElement.focus(),this._lastFocusedElement=null})}async _triggerConsolidation(){try{let t=await this._api.consolidateMemory(24);alert(`Consolidation complete:
|
|
2214
2244
|
- Patterns created: ${t.patternsCreated}
|
|
2215
2245
|
- Patterns merged: ${t.patternsMerged}
|
|
2216
|
-
- Episodes processed: ${t.episodesProcessed}`),this._loadData()}catch(t){alert("Consolidation failed: "+t.message)}}_renderSummary(){if(!this._summary)return'<div class="empty-state">No memory data available</div>';let{episodic:t,semantic:e,procedural:
|
|
2246
|
+
- Episodes processed: ${t.episodesProcessed}`),this._loadData()}catch(t){alert("Consolidation failed: "+t.message)}}_renderSummary(){if(!this._summary)return'<div class="empty-state">No memory data available</div>';let{episodic:t,semantic:e,procedural:i,tokenEconomics:a}=this._summary;return`
|
|
2217
2247
|
<div class="summary-grid">
|
|
2218
2248
|
<div class="summary-card">
|
|
2219
2249
|
<div class="summary-card-header">
|
|
@@ -2246,13 +2276,13 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2246
2276
|
<div class="summary-card">
|
|
2247
2277
|
<div class="summary-card-header">
|
|
2248
2278
|
<span class="summary-card-title">Procedural Memory</span>
|
|
2249
|
-
<span class="summary-card-count">${
|
|
2279
|
+
<span class="summary-card-count">${i?.skills||0}</span>
|
|
2250
2280
|
</div>
|
|
2251
2281
|
<div class="summary-card-detail">
|
|
2252
2282
|
Learned skills and procedures
|
|
2253
2283
|
</div>
|
|
2254
2284
|
<div class="memory-bar">
|
|
2255
|
-
<div class="memory-bar-fill procedural" style="width: ${Math.min((
|
|
2285
|
+
<div class="memory-bar-fill procedural" style="width: ${Math.min((i?.skills||0)/100*100,100)}%"></div>
|
|
2256
2286
|
</div>
|
|
2257
2287
|
</div>
|
|
2258
2288
|
|
|
@@ -2878,8 +2908,8 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2878
2908
|
font-size: 12px;
|
|
2879
2909
|
}
|
|
2880
2910
|
</style>
|
|
2881
|
-
`,e;if(this._loading)e='<div class="loading">Loading memory data...</div>';else if(this._error)e=`<div class="error-state">Error: ${this._error}</div>`;else{let
|
|
2882
|
-
<div class="content-main">${
|
|
2911
|
+
`,e;if(this._loading)e='<div class="loading">Loading memory data...</div>';else if(this._error)e=`<div class="error-state">Error: ${this._error}</div>`;else{let i;switch(this._activeTab){case"summary":i=this._renderSummary();break;case"episodes":i=this._renderEpisodes();break;case"patterns":i=this._renderPatterns();break;case"skills":i=this._renderSkills();break;default:i=this._renderSummary()}e=`
|
|
2912
|
+
<div class="content-main">${i}</div>
|
|
2883
2913
|
${this._renderDetail()}
|
|
2884
2914
|
`}this.shadowRoot.innerHTML=`
|
|
2885
2915
|
${t}
|
|
@@ -2888,16 +2918,16 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2888
2918
|
<span class="browser-title">Memory System</span>
|
|
2889
2919
|
</div>
|
|
2890
2920
|
<div class="tabs" role="tablist" aria-label="Memory browser sections">
|
|
2891
|
-
${
|
|
2892
|
-
<button class="tab ${this._activeTab===
|
|
2893
|
-
data-tab="${
|
|
2921
|
+
${It.map((i,a)=>`
|
|
2922
|
+
<button class="tab ${this._activeTab===i.id?"active":""}"
|
|
2923
|
+
data-tab="${i.id}"
|
|
2894
2924
|
role="tab"
|
|
2895
|
-
id="tab-${
|
|
2896
|
-
aria-selected="${this._activeTab===
|
|
2897
|
-
aria-controls="tabpanel-${
|
|
2898
|
-
tabindex="${this._activeTab===
|
|
2899
|
-
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${
|
|
2900
|
-
${
|
|
2925
|
+
id="tab-${i.id}"
|
|
2926
|
+
aria-selected="${this._activeTab===i.id}"
|
|
2927
|
+
aria-controls="tabpanel-${i.id}"
|
|
2928
|
+
tabindex="${this._activeTab===i.id?"0":"-1"}">
|
|
2929
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${i.icon}"/></svg>
|
|
2930
|
+
${i.label}
|
|
2901
2931
|
</button>
|
|
2902
2932
|
`).join("")}
|
|
2903
2933
|
</div>
|
|
@@ -2905,12 +2935,12 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2905
2935
|
${e}
|
|
2906
2936
|
</div>
|
|
2907
2937
|
</div>
|
|
2908
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.querySelectorAll(".tab");t.forEach((s,r)=>{s.addEventListener("click",()=>this._setTab(s.dataset.tab)),s.addEventListener("keydown",o=>{if(o.key==="ArrowRight"||o.key==="ArrowLeft"){o.preventDefault();let
|
|
2938
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.querySelectorAll(".tab");t.forEach((s,r)=>{s.addEventListener("click",()=>this._setTab(s.dataset.tab)),s.addEventListener("keydown",o=>{if(o.key==="ArrowRight"||o.key==="ArrowLeft"){o.preventDefault();let n=Array.from(t),d=o.key==="ArrowRight"?(r+1)%n.length:(r-1+n.length)%n.length;n[d].focus(),this._setTab(n[d].dataset.tab)}})}),this.shadowRoot.querySelectorAll(".item-card").forEach(s=>{s.addEventListener("click",()=>this._handleItemClick(s)),s.addEventListener("keydown",r=>{r.key==="Enter"||r.key===" "?(r.preventDefault(),this._handleItemClick(s)):(r.key==="ArrowDown"||r.key==="ArrowUp")&&(r.preventDefault(),this._navigateItemCards(s,r.key==="ArrowDown"?"next":"prev"))})});let e=this.shadowRoot.getElementById("close-detail");e&&e.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())}_handleItemClick(t){let e=t.dataset.id;switch(t.dataset.type){case"episode":this._selectEpisode(e);break;case"pattern":this._selectPattern(e);break;case"skill":this._selectSkill(e);break}}_navigateItemCards(t,e){let i=Array.from(this.shadowRoot.querySelectorAll(".item-card")),a=i.indexOf(t);if(a===-1)return;let s=e==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-memory-browser")||customElements.define("loki-memory-browser",q);var Dt=[{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}],zt=[{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"}],Pt=[{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"}],G=class extends p{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(t,e,i){if(e!==i)switch(t){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 t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let t={timeRange:this._timeRange,signalType:this._signalType!=="all"?this._signalType:void 0,source:this._source!=="all"?this._source:void 0},[e,i,a]=await Promise.all([this._api.getLearningMetrics(t).catch(()=>null),this._api.getLearningTrends(t).catch(()=>null),this._api.getLearningSignals({...t,limit:50}).catch(()=>[])]);this._metrics=e,this._trends=i,this._signals=a||[]}catch(t){this._error=t.message||"Failed to load learning data"}this._loading=!1,this.render()}_setFilter(t,e){switch(t){case"timeRange":this._timeRange=e,this.setAttribute("time-range",e);break;case"signalType":this._signalType=e,this.setAttribute("signal-type",e);break;case"source":this._source=e,this.setAttribute("source",e);break}this.dispatchEvent(new CustomEvent("filter-change",{detail:{timeRange:this._timeRange,signalType:this._signalType,source:this._source}})),this._loadData()}_selectMetric(t,e){this._selectedMetric={type:t,item:e},this.dispatchEvent(new CustomEvent("metric-select",{detail:{type:t,item:e}})),this.render()}_closeDetail(){this._selectedMetric=null,this.render()}_formatNumber(t){return t>=1e6?(t/1e6).toFixed(1)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":t?.toString()||"0"}_formatPercent(t){return(t*100).toFixed(1)+"%"}_formatDuration(t){return t<60?t.toFixed(0)+"s":t<3600?(t/60).toFixed(1)+"m":(t/3600).toFixed(1)+"h"}_escapeHtml(t){if(!t)return"";let e=document.createElement("div");return e.textContent=t,e.innerHTML}_renderFilters(){return`
|
|
2909
2939
|
<div class="filters">
|
|
2910
2940
|
<div class="filter-group">
|
|
2911
2941
|
<label>Time Range</label>
|
|
2912
2942
|
<select id="time-range-select" class="filter-select">
|
|
2913
|
-
${
|
|
2943
|
+
${Dt.map(t=>`
|
|
2914
2944
|
<option value="${t.id}" ${this._timeRange===t.id?"selected":""}>${t.label}</option>
|
|
2915
2945
|
`).join("")}
|
|
2916
2946
|
</select>
|
|
@@ -2918,7 +2948,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2918
2948
|
<div class="filter-group">
|
|
2919
2949
|
<label>Signal Type</label>
|
|
2920
2950
|
<select id="signal-type-select" class="filter-select">
|
|
2921
|
-
${
|
|
2951
|
+
${zt.map(t=>`
|
|
2922
2952
|
<option value="${t.id}" ${this._signalType===t.id?"selected":""}>${t.label}</option>
|
|
2923
2953
|
`).join("")}
|
|
2924
2954
|
</select>
|
|
@@ -2926,7 +2956,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2926
2956
|
<div class="filter-group">
|
|
2927
2957
|
<label>Source</label>
|
|
2928
2958
|
<select id="source-select" class="filter-select">
|
|
2929
|
-
${
|
|
2959
|
+
${Pt.map(t=>`
|
|
2930
2960
|
<option value="${t.id}" ${this._source===t.id?"selected":""}>${t.label}</option>
|
|
2931
2961
|
`).join("")}
|
|
2932
2962
|
</select>
|
|
@@ -2939,7 +2969,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2939
2969
|
Refresh
|
|
2940
2970
|
</button>
|
|
2941
2971
|
</div>
|
|
2942
|
-
`}_renderSummaryCards(){if(!this._metrics)return'<div class="empty-state">No metrics available</div>';let{totalSignals:t,signalsByType:e,signalsBySource:
|
|
2972
|
+
`}_renderSummaryCards(){if(!this._metrics)return'<div class="empty-state">No metrics available</div>';let{totalSignals:t,signalsByType:e,signalsBySource:i,aggregation:a}=this._metrics;return`
|
|
2943
2973
|
<div class="summary-cards">
|
|
2944
2974
|
<div class="summary-card">
|
|
2945
2975
|
<div class="summary-card-header">
|
|
@@ -2960,11 +2990,11 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2960
2990
|
<div class="summary-card">
|
|
2961
2991
|
<div class="summary-card-header">
|
|
2962
2992
|
<span class="summary-card-title">Sources</span>
|
|
2963
|
-
<span class="summary-card-count">${Object.keys(
|
|
2993
|
+
<span class="summary-card-count">${Object.keys(i||{}).length}</span>
|
|
2964
2994
|
</div>
|
|
2965
2995
|
<div class="summary-card-detail">Signal sources active</div>
|
|
2966
2996
|
<div class="signal-breakdown">
|
|
2967
|
-
${Object.entries(
|
|
2997
|
+
${Object.entries(i||{}).map(([s,r])=>`
|
|
2968
2998
|
<div class="breakdown-item">
|
|
2969
2999
|
<span class="breakdown-label source-badge ${s}">${s}</span>
|
|
2970
3000
|
<span class="breakdown-value">${this._formatNumber(r)}</span>
|
|
@@ -2976,21 +3006,21 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
2976
3006
|
<div class="summary-card">
|
|
2977
3007
|
<div class="summary-card-header">
|
|
2978
3008
|
<span class="summary-card-title">Patterns Found</span>
|
|
2979
|
-
<span class="summary-card-count">${this._formatNumber((
|
|
3009
|
+
<span class="summary-card-count">${this._formatNumber((a?.preferences?.length||0)+(a?.error_patterns?.length||0)+(a?.success_patterns?.length||0))}</span>
|
|
2980
3010
|
</div>
|
|
2981
3011
|
<div class="summary-card-detail">Aggregated learnings</div>
|
|
2982
3012
|
<div class="pattern-counts">
|
|
2983
3013
|
<div class="pattern-count">
|
|
2984
3014
|
<span class="pattern-icon preferences">P</span>
|
|
2985
|
-
<span>${
|
|
3015
|
+
<span>${a?.preferences?.length||0} Preferences</span>
|
|
2986
3016
|
</div>
|
|
2987
3017
|
<div class="pattern-count">
|
|
2988
3018
|
<span class="pattern-icon errors">E</span>
|
|
2989
|
-
<span>${
|
|
3019
|
+
<span>${a?.error_patterns?.length||0} Errors</span>
|
|
2990
3020
|
</div>
|
|
2991
3021
|
<div class="pattern-count">
|
|
2992
3022
|
<span class="pattern-icon success">S</span>
|
|
2993
|
-
<span>${
|
|
3023
|
+
<span>${a?.success_patterns?.length||0} Success</span>
|
|
2994
3024
|
</div>
|
|
2995
3025
|
</div>
|
|
2996
3026
|
</div>
|
|
@@ -3008,16 +3038,16 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3008
3038
|
</div>
|
|
3009
3039
|
</div>
|
|
3010
3040
|
</div>
|
|
3011
|
-
`}_renderTrendChart(){if(!this._trends||!this._trends.dataPoints||this._trends.dataPoints.length===0)return'<div class="chart-empty">No trend data available</div>';let{dataPoints:t,maxValue:e}=this._trends,
|
|
3041
|
+
`}_renderTrendChart(){if(!this._trends||!this._trends.dataPoints||this._trends.dataPoints.length===0)return'<div class="chart-empty">No trend data available</div>';let{dataPoints:t,maxValue:e}=this._trends,i=120,a=400,s=20,r=t.map((n,d)=>{let g=s+d/(t.length-1||1)*(a-s*2),v=i-s-n.count/(e||1)*(i-s*2);return`${g},${v}`}).join(" "),o=`${s},${i-s} ${r} ${a-s},${i-s}`;return`
|
|
3012
3042
|
<div class="trend-chart">
|
|
3013
3043
|
<div class="chart-header">
|
|
3014
3044
|
<span class="chart-title">Signal Volume Over Time</span>
|
|
3015
3045
|
<span class="chart-subtitle">${this._trends.period}</span>
|
|
3016
3046
|
</div>
|
|
3017
|
-
<svg class="chart-svg" viewBox="0 0 ${
|
|
3047
|
+
<svg class="chart-svg" viewBox="0 0 ${a} ${i}">
|
|
3018
3048
|
<!-- Grid lines -->
|
|
3019
|
-
<line x1="${s}" y1="${s}" x2="${s}" y2="${
|
|
3020
|
-
<line x1="${s}" y1="${
|
|
3049
|
+
<line x1="${s}" y1="${s}" x2="${s}" y2="${i-s}" stroke="var(--loki-border)" stroke-width="1"/>
|
|
3050
|
+
<line x1="${s}" y1="${i-s}" x2="${a-s}" y2="${i-s}" stroke="var(--loki-border)" stroke-width="1"/>
|
|
3021
3051
|
|
|
3022
3052
|
<!-- Area fill -->
|
|
3023
3053
|
<polygon points="${o}" fill="var(--loki-accent-muted)" />
|
|
@@ -3026,7 +3056,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3026
3056
|
<polyline points="${r}" fill="none" stroke="var(--loki-accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3027
3057
|
|
|
3028
3058
|
<!-- Data points -->
|
|
3029
|
-
${t.map((
|
|
3059
|
+
${t.map((n,d)=>{let g=s+d/(t.length-1||1)*(a-s*2),v=i-s-n.count/(e||1)*(i-s*2);return`<circle cx="${g}" cy="${v}" r="3" fill="var(--loki-accent)" />`}).join("")}
|
|
3030
3060
|
</svg>
|
|
3031
3061
|
<div class="chart-labels">
|
|
3032
3062
|
${t.length>0?`
|
|
@@ -3035,7 +3065,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3035
3065
|
`:""}
|
|
3036
3066
|
</div>
|
|
3037
3067
|
</div>
|
|
3038
|
-
`}_renderTopLists(){if(!this._metrics?.aggregation)return"";let{preferences:t,error_patterns:e,success_patterns:
|
|
3068
|
+
`}_renderTopLists(){if(!this._metrics?.aggregation)return"";let{preferences:t,error_patterns:e,success_patterns:i,tool_efficiencies:a}=this._metrics.aggregation;return`
|
|
3039
3069
|
<div class="top-lists">
|
|
3040
3070
|
<!-- User Preferences -->
|
|
3041
3071
|
<div class="top-list">
|
|
@@ -3085,10 +3115,10 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3085
3115
|
<div class="top-list">
|
|
3086
3116
|
<div class="list-header">
|
|
3087
3117
|
<span class="list-title">Success Patterns</span>
|
|
3088
|
-
<span class="list-count">${
|
|
3118
|
+
<span class="list-count">${i?.length||0}</span>
|
|
3089
3119
|
</div>
|
|
3090
3120
|
<div class="list-items" role="list">
|
|
3091
|
-
${(
|
|
3121
|
+
${(i||[]).slice(0,5).map(s=>`
|
|
3092
3122
|
<div class="list-item success-item" data-type="success_pattern" data-id="${s.pattern_name}" tabindex="0" role="listitem">
|
|
3093
3123
|
<div class="item-main">
|
|
3094
3124
|
<span class="item-key">${this._escapeHtml(s.pattern_name)}</span>
|
|
@@ -3107,10 +3137,10 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3107
3137
|
<div class="top-list">
|
|
3108
3138
|
<div class="list-header">
|
|
3109
3139
|
<span class="list-title">Tool Efficiency Rankings</span>
|
|
3110
|
-
<span class="list-count">${
|
|
3140
|
+
<span class="list-count">${a?.length||0}</span>
|
|
3111
3141
|
</div>
|
|
3112
3142
|
<div class="list-items" role="list">
|
|
3113
|
-
${(
|
|
3143
|
+
${(a||[]).slice(0,5).map((s,r)=>`
|
|
3114
3144
|
<div class="list-item tool-item" data-type="tool_efficiency" data-id="${s.tool_name}" tabindex="0" role="listitem">
|
|
3115
3145
|
<div class="item-rank">#${r+1}</div>
|
|
3116
3146
|
<div class="item-main">
|
|
@@ -3133,11 +3163,11 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3133
3163
|
<span class="signals-count">${this._signals.length}</span>
|
|
3134
3164
|
</div>
|
|
3135
3165
|
<div class="signals-list">
|
|
3136
|
-
${this._signals.slice(0,10).map(t=>{let e=t.data||{},
|
|
3166
|
+
${this._signals.slice(0,10).map(t=>{let e=t.data||{},i=t.type||"unknown",a=e.action||t.action||i,s=e.source||t.source||"-",r=e.outcome||t.outcome||"-",o=t.timestamp?new Date(t.timestamp).toLocaleTimeString():"-";return`
|
|
3137
3167
|
<div class="signal-item">
|
|
3138
|
-
<div class="signal-type ${
|
|
3168
|
+
<div class="signal-type ${i}">${i.replace("_"," ")}</div>
|
|
3139
3169
|
<div class="signal-content">
|
|
3140
|
-
<span class="signal-action">${this._escapeHtml(
|
|
3170
|
+
<span class="signal-action">${this._escapeHtml(a)}</span>
|
|
3141
3171
|
<span class="signal-source">${s}</span>
|
|
3142
3172
|
</div>
|
|
3143
3173
|
<div class="signal-meta">
|
|
@@ -3147,7 +3177,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3147
3177
|
</div>`}).join("")}
|
|
3148
3178
|
</div>
|
|
3149
3179
|
</div>
|
|
3150
|
-
`}_renderDetailPanel(){if(!this._selectedMetric)return"";let{type:t,item:e}=this._selectedMetric,
|
|
3180
|
+
`}_renderDetailPanel(){if(!this._selectedMetric)return"";let{type:t,item:e}=this._selectedMetric,i="";switch(t){case"preference":i=`
|
|
3151
3181
|
<div class="detail-row">
|
|
3152
3182
|
<span class="detail-label">Preference Key</span>
|
|
3153
3183
|
<span class="detail-value">${this._escapeHtml(e.preference_key)}</span>
|
|
@@ -3168,11 +3198,11 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3168
3198
|
<div class="detail-section">
|
|
3169
3199
|
<div class="detail-label">Alternatives Rejected</div>
|
|
3170
3200
|
<ul class="detail-list">
|
|
3171
|
-
${e.alternatives_rejected.map(
|
|
3201
|
+
${e.alternatives_rejected.map(a=>`<li>${this._escapeHtml(a)}</li>`).join("")}
|
|
3172
3202
|
</ul>
|
|
3173
3203
|
</div>
|
|
3174
3204
|
`:""}
|
|
3175
|
-
`;break;case"error_pattern":
|
|
3205
|
+
`;break;case"error_pattern":i=`
|
|
3176
3206
|
<div class="detail-row">
|
|
3177
3207
|
<span class="detail-label">Error Type</span>
|
|
3178
3208
|
<span class="detail-value">${this._escapeHtml(e.error_type)}</span>
|
|
@@ -3185,7 +3215,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3185
3215
|
<div class="detail-section">
|
|
3186
3216
|
<div class="detail-label">Common Messages</div>
|
|
3187
3217
|
<ul class="detail-list">
|
|
3188
|
-
${e.common_messages.map(
|
|
3218
|
+
${e.common_messages.map(a=>`<li>${this._escapeHtml(a)}</li>`).join("")}
|
|
3189
3219
|
</ul>
|
|
3190
3220
|
</div>
|
|
3191
3221
|
`:""}
|
|
@@ -3193,11 +3223,11 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3193
3223
|
<div class="detail-section">
|
|
3194
3224
|
<div class="detail-label">Known Resolutions</div>
|
|
3195
3225
|
<ul class="detail-list success">
|
|
3196
|
-
${e.resolutions.map(
|
|
3226
|
+
${e.resolutions.map(a=>`<li>${this._escapeHtml(a)}</li>`).join("")}
|
|
3197
3227
|
</ul>
|
|
3198
3228
|
</div>
|
|
3199
3229
|
`:""}
|
|
3200
|
-
`;break;case"success_pattern":
|
|
3230
|
+
`;break;case"success_pattern":i=`
|
|
3201
3231
|
<div class="detail-row">
|
|
3202
3232
|
<span class="detail-label">Pattern Name</span>
|
|
3203
3233
|
<span class="detail-value">${this._escapeHtml(e.pattern_name)}</span>
|
|
@@ -3210,11 +3240,11 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3210
3240
|
<div class="detail-section">
|
|
3211
3241
|
<div class="detail-label">Common Actions</div>
|
|
3212
3242
|
<ol class="detail-list numbered">
|
|
3213
|
-
${e.common_actions.map(
|
|
3243
|
+
${e.common_actions.map(a=>`<li>${this._escapeHtml(a)}</li>`).join("")}
|
|
3214
3244
|
</ol>
|
|
3215
3245
|
</div>
|
|
3216
3246
|
`:""}
|
|
3217
|
-
`;break;case"tool_efficiency":
|
|
3247
|
+
`;break;case"tool_efficiency":i=`
|
|
3218
3248
|
<div class="detail-row">
|
|
3219
3249
|
<span class="detail-label">Tool Name</span>
|
|
3220
3250
|
<span class="detail-value">${this._escapeHtml(e.tool_name)}</span>
|
|
@@ -3239,22 +3269,22 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3239
3269
|
<div class="detail-section">
|
|
3240
3270
|
<div class="detail-label">Alternative Tools</div>
|
|
3241
3271
|
<div class="tag-list">
|
|
3242
|
-
${e.alternative_tools.map(
|
|
3272
|
+
${e.alternative_tools.map(a=>`<span class="tag">${this._escapeHtml(a)}</span>`).join("")}
|
|
3243
3273
|
</div>
|
|
3244
3274
|
</div>
|
|
3245
3275
|
`:""}
|
|
3246
3276
|
`;break}return`
|
|
3247
3277
|
<div class="detail-panel">
|
|
3248
3278
|
<div class="detail-header">
|
|
3249
|
-
<h3>${t.replace("_"," ").replace(/\b\w/g,
|
|
3279
|
+
<h3>${t.replace("_"," ").replace(/\b\w/g,a=>a.toUpperCase())}</h3>
|
|
3250
3280
|
<button class="close-btn" id="close-detail">×</button>
|
|
3251
3281
|
</div>
|
|
3252
3282
|
<div class="detail-body">
|
|
3253
|
-
${
|
|
3283
|
+
${i}
|
|
3254
3284
|
<div class="detail-row">
|
|
3255
3285
|
<span class="detail-label">Sources</span>
|
|
3256
3286
|
<div class="source-tags">
|
|
3257
|
-
${(e.sources||[]).map(
|
|
3287
|
+
${(e.sources||[]).map(a=>`<span class="source-badge ${a}">${a}</span>`).join("")}
|
|
3258
3288
|
</div>
|
|
3259
3289
|
</div>
|
|
3260
3290
|
<div class="detail-row">
|
|
@@ -3917,7 +3947,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3917
3947
|
${e}
|
|
3918
3948
|
</div>
|
|
3919
3949
|
</div>
|
|
3920
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("time-range-select");t&&t.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let e=this.shadowRoot.getElementById("signal-type-select");e&&e.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let
|
|
3950
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("time-range-select");t&&t.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let e=this.shadowRoot.getElementById("signal-type-select");e&&e.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,d=this._findItemData(o,n);d&&this._selectMetric(o,d)}),r.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r.click())})})}_findItemData(t,e){if(!this._metrics?.aggregation)return null;switch(t){case"preference":return this._metrics.aggregation.preferences?.find(i=>i.preference_key===e);case"error_pattern":return this._metrics.aggregation.error_patterns?.find(i=>i.error_type===e);case"success_pattern":return this._metrics.aggregation.success_patterns?.find(i=>i.pattern_name===e);case"tool_efficiency":return this._metrics.aggregation.tool_efficiencies?.find(i=>i.tool_name===e);default:return null}}};customElements.get("loki-learning-dashboard")||customElements.define("loki-learning-dashboard",G);var Rt=[{id:"overview",label:"Overview"},{id:"decisions",label:"Decision Log"},{id:"convergence",label:"Convergence"},{id:"agents",label:"Agents"}],J=class extends p{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null),this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null)}async _loadData(){try{let[e,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")]);e.status==="fulfilled"&&(this._councilState=e.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(e){this._error=e.message}let t=JSON.stringify({s:this._councilState,v:this._verdicts,c:this._convergence,a:this._agents,e:this._error});t!==this._lastDataHash&&(this._lastDataHash=t,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(t){this._error=`Failed to force review: ${t.message}`,this.render()}}async _killAgent(t){if(confirm(`Kill agent ${t}?`))try{await this._api._post(`/api/agents/${t}/kill`),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"kill-agent",agentId:t},bubbles:!0})),await this._loadData()}catch(e){this._error=`Failed to kill agent: ${e.message}`,this.render()}}async _pauseAgent(t){try{await this._api._post(`/api/agents/${t}/pause`),await this._loadData()}catch(e){this._error=`Failed to pause agent: ${e.message}`,this.render()}}async _resumeAgent(t){try{await this._api._post(`/api/agents/${t}/resume`),await this._loadData()}catch(e){this._error=`Failed to resume agent: ${e.message}`,this.render()}}_setTab(t){this._activeTab=t,this.render()}_selectAgent(t){this._selectedAgent=this._selectedAgent?.id===t.id?null:t,this.render()}render(){let t=this.shadowRoot;t&&(this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null),t.innerHTML=`
|
|
3921
3951
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
3922
3952
|
<div class="council-dashboard">
|
|
3923
3953
|
<div class="council-header">
|
|
@@ -3931,7 +3961,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3931
3961
|
</div>
|
|
3932
3962
|
|
|
3933
3963
|
<div class="tabs">
|
|
3934
|
-
${
|
|
3964
|
+
${Rt.map(e=>`
|
|
3935
3965
|
<button
|
|
3936
3966
|
class="tab ${this._activeTab===e.id?"active":""}"
|
|
3937
3967
|
data-tab="${e.id}"
|
|
@@ -3945,7 +3975,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3945
3975
|
|
|
3946
3976
|
${this._error?`<div class="error-banner">${this._error}</div>`:""}
|
|
3947
3977
|
</div>
|
|
3948
|
-
`,this._attachEventListeners())}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("force-review-btn");e&&e.addEventListener("click",()=>this._forceReview()),t.querySelectorAll(".tab[data-tab]").forEach(
|
|
3978
|
+
`,this._attachEventListeners())}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("force-review-btn");e&&e.addEventListener("click",()=>this._forceReview()),t.querySelectorAll(".tab[data-tab]").forEach(i=>{i.addEventListener("click",()=>this._setTab(i.dataset.tab))})}_renderTabContent(){switch(this._activeTab){case"overview":return this._renderOverview();case"decisions":return this._renderDecisions();case"convergence":return this._renderConvergence();case"agents":return this._renderAgents();default:return""}}_renderOverview(){let t=this._councilState||{},e=t.consecutive_no_change||0,i=t.done_signals||0,a=t.total_votes||0,s=t.approve_votes||0,r=this._verdicts.length>0?this._verdicts[this._verdicts.length-1]:null,o=this._agents.filter(n=>n.alive).length;return`
|
|
3949
3979
|
<div class="overview-grid">
|
|
3950
3980
|
<div class="stat-card">
|
|
3951
3981
|
<div class="stat-label">Council Status</div>
|
|
@@ -3955,7 +3985,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3955
3985
|
</div>
|
|
3956
3986
|
<div class="stat-card">
|
|
3957
3987
|
<div class="stat-label">Total Votes Cast</div>
|
|
3958
|
-
<div class="stat-value">${
|
|
3988
|
+
<div class="stat-value">${a}</div>
|
|
3959
3989
|
<div class="stat-sub">${s} approved</div>
|
|
3960
3990
|
</div>
|
|
3961
3991
|
<div class="stat-card">
|
|
@@ -3965,7 +3995,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3965
3995
|
</div>
|
|
3966
3996
|
<div class="stat-card">
|
|
3967
3997
|
<div class="stat-label">Done Signals</div>
|
|
3968
|
-
<div class="stat-value ${
|
|
3998
|
+
<div class="stat-value ${i>=2?"text-green":""}">${i}</div>
|
|
3969
3999
|
<div class="stat-sub">from agent output</div>
|
|
3970
4000
|
</div>
|
|
3971
4001
|
<div class="stat-card">
|
|
@@ -3990,12 +4020,12 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
3990
4020
|
</div>
|
|
3991
4021
|
</div>
|
|
3992
4022
|
`:""}
|
|
3993
|
-
`}_renderConvergenceBar(){let t=this._convergence.slice(-20);if(t.length===0)return'<span class="text-muted">No data</span>';let e=Math.max(...t.map(
|
|
4023
|
+
`}_renderConvergenceBar(){let t=this._convergence.slice(-20);if(t.length===0)return'<span class="text-muted">No data</span>';let e=Math.max(...t.map(i=>i.files_changed),1);return`
|
|
3994
4024
|
<div class="bar-chart">
|
|
3995
|
-
${t.map(
|
|
3996
|
-
<div class="bar-wrapper" title="Iter ${
|
|
3997
|
-
<div class="bar ${s?"bar-stagnant":"bar-active"}" style="height: ${
|
|
3998
|
-
<div class="bar-label">${
|
|
4025
|
+
${t.map(i=>{let a=Math.max(4,i.files_changed/e*60),s=i.no_change_streak>0;return`
|
|
4026
|
+
<div class="bar-wrapper" title="Iter ${i.iteration}: ${i.files_changed} files changed">
|
|
4027
|
+
<div class="bar ${s?"bar-stagnant":"bar-active"}" style="height: ${a}px"></div>
|
|
4028
|
+
<div class="bar-label">${i.iteration}</div>
|
|
3999
4029
|
</div>
|
|
4000
4030
|
`}).join("")}
|
|
4001
4031
|
</div>
|
|
@@ -4052,9 +4082,9 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
4052
4082
|
</div>
|
|
4053
4083
|
`}_renderAgents(){if(this._agents.length===0)return'<div class="empty-state">No agents registered.</div>';let t=`
|
|
4054
4084
|
<div class="agents-list">
|
|
4055
|
-
${this._agents.map((e,
|
|
4085
|
+
${this._agents.map((e,i)=>`
|
|
4056
4086
|
<div class="agent-card ${this._selectedAgent?.id===e.id?"agent-selected":""}"
|
|
4057
|
-
data-agent-index="${
|
|
4087
|
+
data-agent-index="${i}">
|
|
4058
4088
|
<div class="agent-header">
|
|
4059
4089
|
<span class="agent-name">${e.name||e.id||"Unknown"}</span>
|
|
4060
4090
|
<span class="agent-status ${e.alive?"status-alive":"status-dead"}">
|
|
@@ -4085,7 +4115,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
4085
4115
|
</div>
|
|
4086
4116
|
`).join("")}
|
|
4087
4117
|
</div>
|
|
4088
|
-
`;return this._pendingRaf=requestAnimationFrame(()=>{this._pendingRaf=null;let e=this.shadowRoot;e&&e.querySelectorAll(".agent-card[data-agent-index]").forEach(
|
|
4118
|
+
`;return this._pendingRaf=requestAnimationFrame(()=>{this._pendingRaf=null;let e=this.shadowRoot;e&&e.querySelectorAll(".agent-card[data-agent-index]").forEach(i=>{let a=parseInt(i.dataset.agentIndex,10),s=this._agents[a];s&&(i.addEventListener("click",()=>this._selectAgent(s)),i.querySelectorAll("[data-action]").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation();let n=r.dataset.action,d=r.dataset.agentId;n==="pause"?this._pauseAgent(d):n==="kill"?this._killAgent(d):n==="resume"&&this._resumeAgent(d)})}))})}),t}_formatTime(t){if(!t)return"";try{return new Date(t).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}catch{return t}}_getStyles(){return`
|
|
4089
4119
|
:host {
|
|
4090
4120
|
display: block;
|
|
4091
4121
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
@@ -4504,7 +4534,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
4504
4534
|
color: var(--loki-error);
|
|
4505
4535
|
font-size: 12px;
|
|
4506
4536
|
}
|
|
4507
|
-
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",
|
|
4537
|
+
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",J);var ft={critical:0,major:1,minor:2},Mt={critical:"var(--loki-status-error, #ef4444)",major:"var(--loki-status-warning, #f59e0b)",minor:"var(--loki-text-muted, #71717a)"},K=class extends p{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),5e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),5e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{let[t,e]=await Promise.all([this._api.getChecklist(),this._api.getChecklistWaivers().catch(()=>null)]),i=JSON.stringify(e),a=JSON.stringify(t)+i;if(a===this._lastDataHash)return;this._lastDataHash=a,this._checklist=t,this._waivers=e&&e.waivers?e.waivers.filter(s=>s.active):[],this._error=null,this.render()}catch(t){this._error=`Failed to load checklist: ${t.message}`,this.render()}}_isItemWaived(t){return this._waivers.some(e=>e.item_id===t)}_getWaiverForItem(t){return this._waivers.find(e=>e.item_id===t)||null}async _waiveItem(t){let e=window.prompt("Enter reason for waiving this item:");if(e)try{await this._api.addChecklistWaiver(t,e),this._lastDataHash=null,await this._loadData()}catch(i){this._error=`Failed to add waiver: ${i.message}`,this.render()}}async _unwaiveItem(t){try{await this._api.removeChecklistWaiver(t),this._lastDataHash=null,await this._loadData()}catch(e){this._error=`Failed to remove waiver: ${e.message}`,this.render()}}_toggleCategory(t){this._expandedCategories.has(t)?this._expandedCategories.delete(t):this._expandedCategories.add(t),this.render()}_getStyles(){return`
|
|
4508
4538
|
.checklist-viewer {
|
|
4509
4539
|
padding: 16px;
|
|
4510
4540
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -4752,16 +4782,16 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
4752
4782
|
border-radius: 4px;
|
|
4753
4783
|
font-size: 12px;
|
|
4754
4784
|
}
|
|
4755
|
-
`}_getUnwaivedCriticalFailures(){if(!this._checklist?.categories)return[];let t=[];for(let e of this._checklist.categories)for(let
|
|
4785
|
+
`}_getUnwaivedCriticalFailures(){if(!this._checklist?.categories)return[];let t=[];for(let e of this._checklist.categories)for(let i of e.items||[])i.status==="failing"&&i.priority==="critical"&&!this._isItemWaived(i.id)&&t.push(i);return t}_renderGateBanner(){let t=this._getUnwaivedCriticalFailures();return t.length>0?`<div class="gate-banner gate-blocked">COUNCIL GATE: BLOCKED - ${t.length} critical item${t.length!==1?"s":""} must be verified or waived before completion</div>`:'<div class="gate-banner gate-passed">COUNCIL GATE: PASSED - No blocking critical failures</div>'}render(){let t=this.shadowRoot;if(!t)return;let e=this._checklist,i=e&&e.status!=="not_initialized"&&e.categories?.length>0;t.innerHTML=`
|
|
4756
4786
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
4757
4787
|
<div class="checklist-viewer">
|
|
4758
4788
|
<div class="checklist-header">
|
|
4759
4789
|
<h2 class="title">PRD Checklist</h2>
|
|
4760
|
-
${
|
|
4790
|
+
${i?this._renderBadges(e.summary):""}
|
|
4761
4791
|
</div>
|
|
4762
|
-
${
|
|
4763
|
-
${
|
|
4764
|
-
${
|
|
4792
|
+
${i?this._renderGateBanner():""}
|
|
4793
|
+
${i?this._renderProgress(e.summary):""}
|
|
4794
|
+
${i?this._renderCategories(e.categories):this._renderEmpty()}
|
|
4765
4795
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
4766
4796
|
</div>
|
|
4767
4797
|
`,this._attachEventListeners()}_renderBadges(t){if(!t)return"";let e=this._waivers.length;return`
|
|
@@ -4771,37 +4801,37 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
4771
4801
|
${e?`<span class="badge badge-waived">${e} waived</span>`:""}
|
|
4772
4802
|
${t.pending?`<span class="badge badge-pending">${t.pending} pending</span>`:""}
|
|
4773
4803
|
</div>
|
|
4774
|
-
`}_renderProgress(t){if(!t||!t.total)return"";let e=t.verified/t.total*100,
|
|
4804
|
+
`}_renderProgress(t){if(!t||!t.total)return"";let e=t.verified/t.total*100,i=t.failing/t.total*100;return`
|
|
4775
4805
|
<div class="progress-container">
|
|
4776
4806
|
<div class="progress-bar">
|
|
4777
4807
|
<div class="progress-verified" style="width: ${e}%"></div>
|
|
4778
|
-
<div class="progress-failing" style="width: ${
|
|
4808
|
+
<div class="progress-failing" style="width: ${i}%"></div>
|
|
4779
4809
|
</div>
|
|
4780
4810
|
<div class="progress-label">
|
|
4781
4811
|
<span>${t.verified}/${t.total} verified | ${t.failing||0} failing | ${this._waivers.length} waived | ${t.pending||0} pending</span>
|
|
4782
4812
|
<span>${Math.round(e)}%</span>
|
|
4783
4813
|
</div>
|
|
4784
4814
|
</div>
|
|
4785
|
-
`}_renderCategories(t){return t?.length?t.map(e=>{let
|
|
4815
|
+
`}_renderCategories(t){return t?.length?t.map(e=>{let i=this._expandedCategories.has(e.name),a=e.items||[],s=a.filter(o=>o.status==="verified").length,r=a.filter(o=>o.status==="failing").length;return`
|
|
4786
4816
|
<div class="category">
|
|
4787
4817
|
<div class="category-header" data-category="${this._escapeHtml(e.name)}">
|
|
4788
4818
|
<div>
|
|
4789
4819
|
<span class="category-name">${this._escapeHtml(e.name)}</span>
|
|
4790
|
-
<span class="category-stats">${s}/${
|
|
4820
|
+
<span class="category-stats">${s}/${a.length} verified${r?`, ${r} failing`:""}</span>
|
|
4791
4821
|
</div>
|
|
4792
|
-
<span class="category-arrow ${
|
|
4822
|
+
<span class="category-arrow ${i?"expanded":""}">▶</span>
|
|
4793
4823
|
</div>
|
|
4794
|
-
${
|
|
4824
|
+
${i?`<div class="category-body">${this._renderItems(a)}</div>`:""}
|
|
4795
4825
|
</div>
|
|
4796
|
-
`}).join(""):this._renderEmpty()}_renderItems(t){return t?.length?[...t].sort((a
|
|
4826
|
+
`}).join(""):this._renderEmpty()}_renderItems(t){return t?.length?[...t].sort((i,a)=>(ft[i.priority]??2)-(ft[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=Mt[s],o=i.verification||[],n=this._getWaiverForItem(i.id),d=!!n,g=i.status==="failing"&&(s==="critical"||s==="major"),v=d?`<span class="item-waived-badge" title="${this._escapeHtml(n.reason||"No reason provided")}">WAIVED</span>`:"",x="";return g&&(d?x=`<button class="waiver-btn waiver-btn-unwaive" data-unwaive-id="${this._escapeHtml(i.id)}">Unwaive</button>`:x=`<button class="waiver-btn" data-waive-id="${this._escapeHtml(i.id)}">Waive</button>`),`
|
|
4797
4827
|
<div class="item">
|
|
4798
|
-
<div class="item-status ${
|
|
4799
|
-
<div class="item-title">${this._escapeHtml(
|
|
4828
|
+
<div class="item-status ${a}"></div>
|
|
4829
|
+
<div class="item-title">${this._escapeHtml(i.title||i.id||"?")}</div>
|
|
4800
4830
|
<span class="item-priority" style="color:${r};border:1px solid ${r}">${s}</span>
|
|
4801
|
-
${
|
|
4802
|
-
${
|
|
4831
|
+
${v}
|
|
4832
|
+
${x}
|
|
4803
4833
|
<div class="verification-dots">
|
|
4804
|
-
${o.map(
|
|
4834
|
+
${o.map(_=>`<div class="v-dot ${_.passed===!0?"v-dot-pass":_.passed===!1?"v-dot-fail":"v-dot-pending"}" title="${this._escapeHtml(_.type||"")}"></div>`).join("")}
|
|
4805
4835
|
</div>
|
|
4806
4836
|
</div>
|
|
4807
4837
|
`}).join(""):'<div class="item" style="color:var(--loki-text-muted)">No items</div>'}_renderEmpty(){return`
|
|
@@ -4809,7 +4839,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
4809
4839
|
<p>Checklist not initialized</p>
|
|
4810
4840
|
<p class="hint">The PRD checklist will be created during the first iteration when a PRD is provided.</p>
|
|
4811
4841
|
</div>
|
|
4812
|
-
`}_attachEventListeners(){let t=this.shadowRoot;t&&(t.querySelectorAll(".category-header[data-category]").forEach(e=>{e.addEventListener("click",()=>this._toggleCategory(e.dataset.category))}),t.querySelectorAll("button[data-waive-id]").forEach(e=>{e.addEventListener("click",
|
|
4842
|
+
`}_attachEventListeners(){let t=this.shadowRoot;t&&(t.querySelectorAll(".category-header[data-category]").forEach(e=>{e.addEventListener("click",()=>this._toggleCategory(e.dataset.category))}),t.querySelectorAll("button[data-waive-id]").forEach(e=>{e.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(e.dataset.waiveId)})}),t.querySelectorAll("button[data-unwaive-id]").forEach(e=>{e.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(e.dataset.unwaiveId)})}))}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",K);var kt={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}},V=class extends p{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{let[t,e]=await Promise.all([this._api.getAppRunnerStatus(),this._api.getAppRunnerLogs()]),i=JSON.stringify({status:t?.status,port:t?.port,restarts:t?.restart_count,url:t?.url}),a=JSON.stringify(e?.lines?.slice(-5)||[]),s=a!==this._lastLogsHash;if(i===this._lastDataHash&&!s)return;this._lastDataHash=i,this._lastLogsHash=a,this._status=t,this._logs=e?.lines||[],this._error=null,this.render(),this._scrollLogsToBottom()}catch(t){this._error||(this._error=`Failed to load app status: ${t.message}`,this.render())}}_scrollLogsToBottom(){let t=this.shadowRoot;if(!t)return;let e=t.querySelector(".log-area");e&&(e.scrollTop=e.scrollHeight)}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(t){this._error=`Restart failed: ${t.message}`,this.render()}}async _handleStop(){try{await this._api.stopApp(),this._loadData()}catch(t){this._error=`Stop failed: ${t.message}`,this.render()}}_formatUptime(t){if(!t)return"--";let e=new Date(t),a=Math.floor((new Date-e)/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(t){if(!t)return!1;try{let e=new URL(t);return e.protocol==="http:"||e.protocol==="https:"}catch{return!1}}_getStyles(){return`
|
|
4813
4843
|
.app-status {
|
|
4814
4844
|
padding: 16px;
|
|
4815
4845
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -4970,7 +5000,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
4970
5000
|
border-radius: 4px;
|
|
4971
5001
|
font-size: 12px;
|
|
4972
5002
|
}
|
|
4973
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._status,
|
|
5003
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._status,i=e&&e.status&&e.status!=="not_initialized";t.innerHTML=`
|
|
4974
5004
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
4975
5005
|
<div class="app-status">
|
|
4976
5006
|
<div class="header">
|
|
@@ -4978,19 +5008,19 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
4978
5008
|
<h2 class="title">App Runner</h2>
|
|
4979
5009
|
${this._renderStatusBadge(e)}
|
|
4980
5010
|
</div>
|
|
4981
|
-
${
|
|
5011
|
+
${i?this._renderActions(e):""}
|
|
4982
5012
|
</div>
|
|
4983
|
-
${
|
|
4984
|
-
${
|
|
4985
|
-
${
|
|
5013
|
+
${i?this._renderStatusCard(e):""}
|
|
5014
|
+
${i&&this._logs.length>0?this._renderLogs():""}
|
|
5015
|
+
${i?"":this._renderEmpty()}
|
|
4986
5016
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
4987
5017
|
</div>
|
|
4988
|
-
`,this._attachEventListeners()}_renderStatusBadge(t){let e=t?.status||"not_initialized",
|
|
4989
|
-
<span class="status-badge" style="background: color-mix(in srgb, ${
|
|
4990
|
-
<span class="status-dot ${
|
|
4991
|
-
${this._escapeHtml(
|
|
5018
|
+
`,this._attachEventListeners()}_renderStatusBadge(t){let e=t?.status||"not_initialized",i=kt[e]||kt.not_initialized;return`
|
|
5019
|
+
<span class="status-badge" style="background: color-mix(in srgb, ${i.color} 15%, transparent); color: ${i.color}">
|
|
5020
|
+
<span class="status-dot ${i.pulse?"pulse":""}" style="background: ${i.color}"></span>
|
|
5021
|
+
${this._escapeHtml(i.label)}
|
|
4992
5022
|
</span>
|
|
4993
|
-
`}_renderStatusCard(t){let
|
|
5023
|
+
`}_renderStatusCard(t){let i=this._isValidUrl(t.url)?`<a href="${this._escapeHtml(t.url)}" target="_blank" rel="noopener noreferrer">${this._escapeHtml(t.url)}</a>`:this._escapeHtml(t.url||"--");return`
|
|
4994
5024
|
<div class="status-card">
|
|
4995
5025
|
<div class="status-row">
|
|
4996
5026
|
<span class="status-label">Method</span>
|
|
@@ -5002,7 +5032,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5002
5032
|
</div>
|
|
5003
5033
|
<div class="status-row">
|
|
5004
5034
|
<span class="status-label">URL</span>
|
|
5005
|
-
<span class="status-value">${
|
|
5035
|
+
<span class="status-value">${i}</span>
|
|
5006
5036
|
</div>
|
|
5007
5037
|
<div class="status-row">
|
|
5008
5038
|
<span class="status-label">Restarts</span>
|
|
@@ -5025,27 +5055,27 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5025
5055
|
<div class="log-area">${t.length>0?t.map(e=>this._escapeHtml(e)).join(`
|
|
5026
5056
|
`):'<span class="log-empty">No log output yet</span>'}</div>
|
|
5027
5057
|
</div>
|
|
5028
|
-
`}_renderActions(t){let e=t.status==="running"||t.status==="crashed"||t.status==="stopped",
|
|
5058
|
+
`}_renderActions(t){let e=t.status==="running"||t.status==="crashed"||t.status==="stopped",i=t.status==="running"||t.status==="starting";return`
|
|
5029
5059
|
<div class="actions">
|
|
5030
5060
|
<button class="btn" data-action="restart" ${e?"":"disabled"}>Restart</button>
|
|
5031
|
-
<button class="btn btn-danger" data-action="stop" ${
|
|
5061
|
+
<button class="btn btn-danger" data-action="stop" ${i?"":"disabled"}>Stop</button>
|
|
5032
5062
|
</div>
|
|
5033
5063
|
`}_renderEmpty(){return`
|
|
5034
5064
|
<div class="empty-state">
|
|
5035
5065
|
<p>App runner not started</p>
|
|
5036
5066
|
<p class="hint">App runner will start after the first successful build iteration.</p>
|
|
5037
5067
|
</div>
|
|
5038
|
-
`}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.querySelector('[data-action="restart"]'),
|
|
5068
|
+
`}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.querySelector('[data-action="restart"]'),i=t.querySelector('[data-action="stop"]');e&&e.addEventListener("click",()=>this._handleRestart()),i&&i.addEventListener("click",()=>this._handleStop())}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-app-status",V);var Ht={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"},"gemini-3-pro":{input:1.25,output:10,label:"Gemini 3 Pro",provider:"gemini"},"gemini-3-flash":{input:.1,output:.4,label:"Gemini 3 Flash",provider:"gemini"}},Y=class extends p{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={...Ht}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadPricing(),this._loadCost(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadCost()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}async _loadPricing(){try{let t=await this._api.getPricing();if(t&&t.models){let e={};for(let[i,a]of Object.entries(t.models))e[i]={input:a.input,output:a.output,label:a.label||i,provider:a.provider||"unknown"};this._modelPricing=e,this._pricingSource=t.source||"api",this._pricingDate=t.updated||"",this._activeProvider=t.provider||"claude",this.render()}}catch{}}async _loadCost(){try{let t=await this._api.getCost();this._updateFromCost(t)}catch{this._data.connected=!1,this.render()}}_updateFromCost(t){t&&(this._data={...this._data,connected:!0,total_input_tokens:t.total_input_tokens||0,total_output_tokens:t.total_output_tokens||0,estimated_cost_usd:t.estimated_cost_usd||0,by_phase:t.by_phase||{},by_model:t.by_model||{},budget_limit:t.budget_limit,budget_used:t.budget_used||0,budget_remaining:t.budget_remaining},this.render())}_startPolling(){this._pollInterval=setInterval(async()=>{try{let t=await this._api.getCost();this._updateFromCost(t)}catch{this._data.connected=!1,this.render()}},5e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadCost(),this._pollInterval=setInterval(async()=>{try{let t=await this._api.getCost();this._updateFromCost(t)}catch{this._data.connected=!1,this.render()}},5e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}_formatTokens(t){return!t||t===0?"0":t>=1e6?(t/1e6).toFixed(2)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":String(t)}_formatUSD(t){return!t||t===0?"$0.00":t<.01?"<$0.01":"$"+t.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 t=this._getBudgetPercent();return t>=90?"critical":t>=70?"warning":"ok"}_renderPhaseRows(){let t=this._data.by_phase;return!t||Object.keys(t).length===0?'<tr><td colspan="4" class="empty-cell">No phase data yet</td></tr>':Object.entries(t).map(([e,i])=>{let a=i.input_tokens||0,s=i.output_tokens||0,r=i.cost_usd||0;return`
|
|
5039
5069
|
<tr>
|
|
5040
5070
|
<td class="phase-name">${this._escapeHTML(e)}</td>
|
|
5041
|
-
<td class="mono-cell">${this._formatTokens(
|
|
5071
|
+
<td class="mono-cell">${this._formatTokens(a)}</td>
|
|
5042
5072
|
<td class="mono-cell">${this._formatTokens(s)}</td>
|
|
5043
5073
|
<td class="mono-cell cost-cell">${this._formatUSD(r)}</td>
|
|
5044
5074
|
</tr>
|
|
5045
|
-
`}).join("")}_renderModelRows(){let t=this._data.by_model;return!t||Object.keys(t).length===0?'<tr><td colspan="4" class="empty-cell">No model data yet</td></tr>':Object.entries(t).map(([e,
|
|
5075
|
+
`}).join("")}_renderModelRows(){let t=this._data.by_model;return!t||Object.keys(t).length===0?'<tr><td colspan="4" class="empty-cell">No model data yet</td></tr>':Object.entries(t).map(([e,i])=>{let a=i.input_tokens||0,s=i.output_tokens||0,r=i.cost_usd||0;return`
|
|
5046
5076
|
<tr>
|
|
5047
5077
|
<td class="model-name">${this._escapeHTML(e)}</td>
|
|
5048
|
-
<td class="mono-cell">${this._formatTokens(
|
|
5078
|
+
<td class="mono-cell">${this._formatTokens(a)}</td>
|
|
5049
5079
|
<td class="mono-cell">${this._formatTokens(s)}</td>
|
|
5050
5080
|
<td class="mono-cell cost-cell">${this._formatUSD(r)}</td>
|
|
5051
5081
|
</tr>
|
|
@@ -5059,7 +5089,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5059
5089
|
</div>
|
|
5060
5090
|
<div class="budget-not-set">No budget configured</div>
|
|
5061
5091
|
</div>
|
|
5062
|
-
`;let t=this._getBudgetPercent(),e=this._getBudgetStatusClass(),
|
|
5092
|
+
`;let t=this._getBudgetPercent(),e=this._getBudgetStatusClass(),i=this._data.budget_remaining!=null?this._formatUSD(this._data.budget_remaining):this._formatUSD(this._data.budget_limit-this._data.budget_used);return`
|
|
5063
5093
|
<div class="budget-section">
|
|
5064
5094
|
<div class="section-header">
|
|
5065
5095
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
@@ -5072,7 +5102,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5072
5102
|
</div>
|
|
5073
5103
|
<div class="budget-details">
|
|
5074
5104
|
<span class="budget-used">${this._formatUSD(this._data.budget_used)} used</span>
|
|
5075
|
-
<span class="budget-remaining">${
|
|
5105
|
+
<span class="budget-remaining">${i} remaining</span>
|
|
5076
5106
|
<span class="budget-limit">of ${this._formatUSD(this._data.budget_limit)}</span>
|
|
5077
5107
|
</div>
|
|
5078
5108
|
</div>
|
|
@@ -5430,15 +5460,15 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5430
5460
|
${this._pricingDate?`<span class="pricing-meta">Updated: ${this._escapeHTML(this._pricingDate)}</span>`:""}
|
|
5431
5461
|
</div>
|
|
5432
5462
|
<div class="pricing-grid">
|
|
5433
|
-
${Object.entries(this._modelPricing).map(([e,
|
|
5463
|
+
${Object.entries(this._modelPricing).map(([e,i])=>`
|
|
5434
5464
|
<div class="pricing-item">
|
|
5435
|
-
<div class="pricing-model ${this._getPricingColorClass(e,
|
|
5436
|
-
<div class="pricing-rates">In: $${
|
|
5465
|
+
<div class="pricing-model ${this._getPricingColorClass(e,i)}">${i.label||e}</div>
|
|
5466
|
+
<div class="pricing-rates">In: $${i.input.toFixed(2)} / Out: $${i.output.toFixed(2)}</div>
|
|
5437
5467
|
</div>`).join("")}
|
|
5438
5468
|
</div>
|
|
5439
5469
|
</div>
|
|
5440
5470
|
</div>
|
|
5441
|
-
`}};customElements.get("loki-cost-dashboard")||customElements.define("loki-cost-dashboard",
|
|
5471
|
+
`}};customElements.get("loki-cost-dashboard")||customElements.define("loki-cost-dashboard",Y);var W=class extends p{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}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{let[e]=await Promise.allSettled([this._api._get("/api/checkpoints?limit=50")]);e.status==="fulfilled"&&(this._checkpoints=Array.isArray(e.value)?e.value:e.value?.checkpoints||[]),this._error=null}catch(e){this._error=e.message}let t=JSON.stringify({c:this._checkpoints,e:this._error});t!==this._lastDataHash&&(this._lastDataHash=t,this.render())}async _createCheckpoint(){let t=this.shadowRoot.getElementById("checkpoint-message"),e=t?t.value.trim():"";if(e){this._creating=!0,this.render();try{await this._api._post("/api/checkpoints",{message:e}),this._showCreateForm=!1,this._creating=!1,this.dispatchEvent(new CustomEvent("checkpoint-action",{detail:{action:"create",message:e},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(t){if(!this._rollingBack){this._rollingBack=!0,this.render();try{await this._api._post(`/api/checkpoints/${t}/rollback`),this._rollbackTarget=null,this.dispatchEvent(new CustomEvent("checkpoint-action",{detail:{action:"rollback",checkpointId:t},bubbles:!0})),this._lastDataHash=null,await this._loadData()}catch(e){this._rollbackTarget=null,this._error=`Failed to rollback: ${e.message}`}finally{this._rollingBack=!1,this.render()}}}_toggleCreateForm(){this._showCreateForm=!this._showCreateForm,this._rollbackTarget=null,this.render()}_confirmRollback(t){this._rollbackTarget=t,this.render()}_cancelRollback(){this._rollbackTarget=null,this.render()}_formatRelativeTime(t){if(!t)return"";try{let e=Date.now(),i=new Date(t).getTime(),a=Math.floor((e-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(t)}}render(){let t=this.shadowRoot;if(!t)return;let e=this._checkpoints.length;t.innerHTML=`
|
|
5442
5472
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
5443
5473
|
<div class="checkpoint-viewer">
|
|
5444
5474
|
<div class="checkpoint-header">
|
|
@@ -5456,7 +5486,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5456
5486
|
<div class="checkpoint-list">
|
|
5457
5487
|
${this._loading?'<div class="loading-state">Loading checkpoints...</div>':""}
|
|
5458
5488
|
${!this._loading&&e===0?'<div class="empty-state">No checkpoints yet. Create one to save the current state.</div>':""}
|
|
5459
|
-
${this._checkpoints.map(
|
|
5489
|
+
${this._checkpoints.map(i=>this._renderCheckpointCard(i)).join("")}
|
|
5460
5490
|
</div>
|
|
5461
5491
|
|
|
5462
5492
|
${this._error?`<div class="error-banner">${this._escapeHTML(this._error)}</div>`:""}
|
|
@@ -5475,7 +5505,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5475
5505
|
${this._creating?"Creating...":"Save"}
|
|
5476
5506
|
</button>
|
|
5477
5507
|
</div>
|
|
5478
|
-
`}_renderCheckpointCard(t){let e=t.git_sha?t.git_sha.substring(0,7):"unknown",
|
|
5508
|
+
`}_renderCheckpointCard(t){let e=t.git_sha?t.git_sha.substring(0,7):"unknown",i=Array.isArray(t.files)?t.files.length:t.files_count||0,a=this._rollbackTarget===t.id;return`
|
|
5479
5509
|
<div class="checkpoint-card" data-checkpoint-id="${this._escapeHTML(t.id)}">
|
|
5480
5510
|
<div class="card-header">
|
|
5481
5511
|
<span class="checkpoint-sha mono">${this._escapeHTML(e)}</span>
|
|
@@ -5484,12 +5514,12 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5484
5514
|
<div class="card-body">
|
|
5485
5515
|
<p class="checkpoint-message">${this._escapeHTML(t.message||"No message")}</p>
|
|
5486
5516
|
<div class="card-meta">
|
|
5487
|
-
<span class="meta-item">${
|
|
5517
|
+
<span class="meta-item">${i} file${i!==1?"s":""}</span>
|
|
5488
5518
|
<span class="meta-item mono">ID: ${this._escapeHTML(t.id)}</span>
|
|
5489
5519
|
</div>
|
|
5490
5520
|
</div>
|
|
5491
5521
|
<div class="card-actions">
|
|
5492
|
-
${
|
|
5522
|
+
${a?`
|
|
5493
5523
|
<span class="rollback-confirm-text">Rollback to this checkpoint?</span>
|
|
5494
5524
|
<button class="btn btn-sm btn-danger" data-action="confirm-rollback" data-id="${this._escapeHTML(t.id)}">Confirm</button>
|
|
5495
5525
|
<button class="btn btn-sm" data-action="cancel-rollback">Cancel</button>
|
|
@@ -5498,7 +5528,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5498
5528
|
`}
|
|
5499
5529
|
</div>
|
|
5500
5530
|
</div>
|
|
5501
|
-
`}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("create-btn");e&&e.addEventListener("click",()=>this._toggleCreateForm());let
|
|
5531
|
+
`}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("create-btn");e&&e.addEventListener("click",()=>this._toggleCreateForm());let i=t.getElementById("submit-create-btn");i&&i.addEventListener("click",()=>this._createCheckpoint());let a=t.getElementById("checkpoint-message");a&&(a.addEventListener("keydown",s=>{s.key==="Enter"&&!this._creating&&(s.preventDefault(),this._createCheckpoint())}),requestAnimationFrame(()=>a.focus())),t.querySelectorAll("[data-action]").forEach(s=>{s.addEventListener("click",r=>{r.stopPropagation();let o=s.dataset.action,n=s.dataset.id;o==="rollback"?this._confirmRollback(n):o==="confirm-rollback"?this._rollbackCheckpoint(n):o==="cancel-rollback"&&this._cancelRollback()})})}_getStyles(){return`
|
|
5502
5532
|
:host {
|
|
5503
5533
|
display: block;
|
|
5504
5534
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
@@ -5725,10 +5755,10 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5725
5755
|
color: var(--loki-red);
|
|
5726
5756
|
font-size: 12px;
|
|
5727
5757
|
}
|
|
5728
|
-
`}};customElements.get("loki-checkpoint-viewer")||customElements.define("loki-checkpoint-viewer",
|
|
5758
|
+
`}};customElements.get("loki-checkpoint-viewer")||customElements.define("loki-checkpoint-viewer",W);var Q=class extends p{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadContext()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}async _loadContext(){try{let t=this.getAttribute("api-url")||window.location.origin,e=await fetch(t+"/api/context");e.ok&&(this._data=await e.json(),this._connected=!0)}catch{this._connected=!1}this.render()}_startPolling(){this._pollInterval=setInterval(()=>{this._loadContext()},5e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadContext(),this._pollInterval=setInterval(()=>this._loadContext(),5e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}_setTab(t){this._activeTab=t,this.render()}_formatTokens(t){return!t||t===0?"0":t>=1e6?(t/1e6).toFixed(2)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":String(t)}_formatUSD(t){return!t||t===0?"$0.00":t<.01?"<$0.01":"$"+t.toFixed(2)}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGaugeColor(t){return t>80?"var(--loki-red)":t>=60?"var(--loki-yellow)":"var(--loki-green)"}_getGaugeColorClass(t){return t>80?"gauge-red":t>=60?"gauge-yellow":"gauge-green"}_renderGaugeTab(){let t=this._data?.current||{},e=this._data?.totals||{},i=t.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`
|
|
5729
5759
|
<div class="gauge-tab">
|
|
5730
5760
|
<div class="gauge-container">
|
|
5731
|
-
<svg class="gauge-svg" viewBox="0 0 180 180" aria-label="Context window usage: ${
|
|
5761
|
+
<svg class="gauge-svg" viewBox="0 0 180 180" aria-label="Context window usage: ${i.toFixed(1)}%">
|
|
5732
5762
|
<circle
|
|
5733
5763
|
class="gauge-bg"
|
|
5734
5764
|
cx="90" cy="90" r="${r}"
|
|
@@ -5740,17 +5770,17 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5740
5770
|
class="gauge-ring ${s}"
|
|
5741
5771
|
cx="90" cy="90" r="${r}"
|
|
5742
5772
|
fill="none"
|
|
5743
|
-
stroke="${
|
|
5773
|
+
stroke="${a}"
|
|
5744
5774
|
stroke-width="12"
|
|
5745
5775
|
stroke-linecap="round"
|
|
5746
5776
|
stroke-dasharray="${o}"
|
|
5747
|
-
stroke-dashoffset="${
|
|
5777
|
+
stroke-dashoffset="${n}"
|
|
5748
5778
|
transform="rotate(-90 90 90)"
|
|
5749
5779
|
/>
|
|
5750
5780
|
<text class="gauge-pct" x="90" y="85" text-anchor="middle"
|
|
5751
5781
|
fill="var(--loki-text-primary)" font-size="28" font-weight="600"
|
|
5752
5782
|
font-family="'JetBrains Mono', monospace">
|
|
5753
|
-
${
|
|
5783
|
+
${i.toFixed(1)}%
|
|
5754
5784
|
</text>
|
|
5755
5785
|
<text class="gauge-label" x="90" y="108" text-anchor="middle"
|
|
5756
5786
|
fill="var(--loki-text-muted)" font-size="11">
|
|
@@ -5800,17 +5830,17 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5800
5830
|
</div>
|
|
5801
5831
|
</div>
|
|
5802
5832
|
</div>
|
|
5803
|
-
`}_renderTimelineTab(){let t=this._data?.per_iteration||[],e=this._data?.compactions||[];if(t.length===0)return'<div class="empty-state">No iteration data yet</div>';let
|
|
5833
|
+
`}_renderTimelineTab(){let t=this._data?.per_iteration||[],e=this._data?.compactions||[];if(t.length===0)return'<div class="empty-state">No iteration data yet</div>';let i=Math.max(...t.map(r=>(r.input_tokens||0)+(r.output_tokens||0)+(r.cache_read_tokens||0)+(r.cache_creation_tokens||0))),a=new Set(e.map(r=>r.at_iteration)),s="";for(let r of t){let o=(r.input_tokens||0)+(r.output_tokens||0)+(r.cache_read_tokens||0)+(r.cache_creation_tokens||0),n=i>0?o/i*100:0,d=r.compacted===!0;a.has(r.iteration)&&(s+=`
|
|
5804
5834
|
<div class="timeline-compaction-row">
|
|
5805
5835
|
<div class="compaction-line"></div>
|
|
5806
5836
|
<span class="compaction-label">Context Compacted</span>
|
|
5807
5837
|
<div class="compaction-line"></div>
|
|
5808
5838
|
</div>
|
|
5809
5839
|
`),s+=`
|
|
5810
|
-
<div class="timeline-row ${
|
|
5840
|
+
<div class="timeline-row ${d?"compacted":""}">
|
|
5811
5841
|
<div class="timeline-iter">#${r.iteration}</div>
|
|
5812
5842
|
<div class="timeline-bar-container">
|
|
5813
|
-
<div class="timeline-bar" style="width: ${
|
|
5843
|
+
<div class="timeline-bar" style="width: ${n.toFixed(1)}%"></div>
|
|
5814
5844
|
</div>
|
|
5815
5845
|
<div class="timeline-tokens">${this._formatTokens(o)}</div>
|
|
5816
5846
|
<div class="timeline-cost">${this._formatUSD(r.cost_usd)}</div>
|
|
@@ -5831,21 +5861,21 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5831
5861
|
</div>
|
|
5832
5862
|
${s}
|
|
5833
5863
|
</div>
|
|
5834
|
-
`}_renderBreakdownTab(){let t=this._data?.per_iteration||[];if(t.length===0)return'<div class="empty-state">No iteration data yet</div>';let e=Math.max(...t.map(s=>(s.input_tokens||0)+(s.output_tokens||0)+(s.cache_read_tokens||0)+(s.cache_creation_tokens||0))),
|
|
5864
|
+
`}_renderBreakdownTab(){let t=this._data?.per_iteration||[];if(t.length===0)return'<div class="empty-state">No iteration data yet</div>';let e=Math.max(...t.map(s=>(s.input_tokens||0)+(s.output_tokens||0)+(s.cache_read_tokens||0)+(s.cache_creation_tokens||0))),i=`
|
|
5835
5865
|
<div class="breakdown-legend">
|
|
5836
5866
|
<div class="legend-item"><span class="legend-swatch swatch-input"></span> Input</div>
|
|
5837
5867
|
<div class="legend-item"><span class="legend-swatch swatch-output"></span> Output</div>
|
|
5838
5868
|
<div class="legend-item"><span class="legend-swatch swatch-cache-read"></span> Cache Read</div>
|
|
5839
5869
|
<div class="legend-item"><span class="legend-swatch swatch-cache-create"></span> Cache Creation</div>
|
|
5840
5870
|
</div>
|
|
5841
|
-
`,
|
|
5871
|
+
`,a="";for(let s of t){let r=s.input_tokens||0,o=s.output_tokens||0,n=s.cache_read_tokens||0,d=s.cache_creation_tokens||0,g=r+o+n+d,v=e>0?r/e*100:0,x=e>0?o/e*100:0,_=e>0?n/e*100:0,M=e>0?d/e*100:0;a+=`
|
|
5842
5872
|
<div class="breakdown-row">
|
|
5843
5873
|
<div class="breakdown-iter">#${s.iteration}</div>
|
|
5844
5874
|
<div class="breakdown-bar-container">
|
|
5845
|
-
<div class="breakdown-bar bar-input" style="width: ${
|
|
5846
|
-
<div class="breakdown-bar bar-output" style="width: ${
|
|
5847
|
-
<div class="breakdown-bar bar-cache-read" style="width: ${
|
|
5848
|
-
<div class="breakdown-bar bar-cache-create" style="width: ${
|
|
5875
|
+
<div class="breakdown-bar bar-input" style="width: ${v.toFixed(1)}%"></div>
|
|
5876
|
+
<div class="breakdown-bar bar-output" style="width: ${x.toFixed(1)}%"></div>
|
|
5877
|
+
<div class="breakdown-bar bar-cache-read" style="width: ${_.toFixed(1)}%"></div>
|
|
5878
|
+
<div class="breakdown-bar bar-cache-create" style="width: ${M.toFixed(1)}%"></div>
|
|
5849
5879
|
</div>
|
|
5850
5880
|
<div class="breakdown-cost">${this._formatUSD(s.cost_usd)}</div>
|
|
5851
5881
|
</div>
|
|
@@ -5859,8 +5889,8 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
5859
5889
|
</svg>
|
|
5860
5890
|
<span class="section-title">Token Type Breakdown</span>
|
|
5861
5891
|
</div>
|
|
5862
|
-
${a}
|
|
5863
5892
|
${i}
|
|
5893
|
+
${a}
|
|
5864
5894
|
</div>
|
|
5865
5895
|
`}render(){let t=this._activeTab==="gauge"?this._renderGaugeTab():this._activeTab==="timeline"?this._renderTimelineTab():this._renderBreakdownTab();this.shadowRoot.innerHTML=`
|
|
5866
5896
|
<style>
|
|
@@ -6248,7 +6278,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
6248
6278
|
|
|
6249
6279
|
${t}
|
|
6250
6280
|
</div>
|
|
6251
|
-
`,this.shadowRoot.querySelectorAll(".tab").forEach(e=>{e.addEventListener("click",()=>{this._setTab(e.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",
|
|
6281
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(e=>{e.addEventListener("click",()=>{this._setTab(e.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",Q);var pt={critical:"var(--loki-red, #ef4444)",warning:"var(--loki-yellow, #eab308)",info:"var(--loki-blue, #3b82f6)"},X=class extends p{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._notifications=[],this._triggers=[],this._summary={},this._connected=!1,this._activeTab="feed",this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._loadNotifications(),this._loadTriggers(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&(this._loadNotifications(),this._loadTriggers()),t==="theme"&&this._applyTheme())}async _loadNotifications(){try{let t=this.getAttribute("api-url")||window.location.origin,e=await fetch(t+"/api/notifications");if(e.ok){let i=await e.json();this._notifications=i.notifications||[],this._summary=i.summary||{},this._connected=!0}}catch{this._connected=!1}this.render()}async _loadTriggers(){try{let t=this.getAttribute("api-url")||window.location.origin,e=await fetch(t+"/api/notifications/triggers");if(e.ok){let i=await e.json();this._triggers=i.triggers||[]}}catch{}}async _acknowledgeNotification(t){let e=this.getAttribute("api-url")||window.location.origin;await fetch(e+"/api/notifications/"+encodeURIComponent(t)+"/acknowledge",{method:"POST"}),this._loadNotifications()}async _acknowledgeAll(){let t=this.getAttribute("api-url")||window.location.origin,e=this._notifications.filter(i=>!i.acknowledged);for(let i of e)await fetch(t+"/api/notifications/"+encodeURIComponent(i.id)+"/acknowledge",{method:"POST"});this._loadNotifications()}async _toggleTrigger(t,e){let i=this.getAttribute("api-url")||window.location.origin,a=this._triggers.map(s=>s.id===t?{...s,enabled:e}: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._pollInterval=setInterval(()=>{this._loadNotifications(),this._loadTriggers()},5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_formatTime(t){if(!t)return"";try{let e=new Date(t),a=new Date-e,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":e.toLocaleDateString()}catch{return String(t)}}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getSeverityColor(t){return pt[t]||pt.info}_switchTab(t){this._activeTab=t,this.render()}_bindEvents(){let t=this.shadowRoot;t.querySelectorAll(".tab").forEach(i=>{i.addEventListener("click",()=>{this._switchTab(i.dataset.tab)})}),t.querySelectorAll(".ack-btn").forEach(i=>{i.addEventListener("click",()=>{this._acknowledgeNotification(i.dataset.id)})});let e=t.querySelector(".ack-all-btn");e&&e.addEventListener("click",()=>{this._acknowledgeAll()}),t.querySelectorAll(".toggle input").forEach(i=>{i.addEventListener("change",()=>{this._toggleTrigger(i.dataset.triggerId,i.checked)})})}_renderSummaryBar(){let t=this._summary.total||0,e=this._summary.unacknowledged||0,i=this._summary.critical||0;return`
|
|
6252
6282
|
<div class="summary-row">
|
|
6253
6283
|
<div class="summary-grid">
|
|
6254
6284
|
<div class="summary-card">
|
|
@@ -6261,22 +6291,22 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
6261
6291
|
</div>
|
|
6262
6292
|
<div class="summary-card">
|
|
6263
6293
|
<div class="card-label">Critical</div>
|
|
6264
|
-
<div class="card-value" style="color: ${
|
|
6294
|
+
<div class="card-value" style="color: ${pt.critical}">${i}</div>
|
|
6265
6295
|
</div>
|
|
6266
6296
|
</div>
|
|
6267
6297
|
${e>0?`
|
|
6268
6298
|
<button class="ack-all-btn">Acknowledge All</button>
|
|
6269
6299
|
`:""}
|
|
6270
6300
|
</div>
|
|
6271
|
-
`}_renderNotificationList(){return this._notifications.length===0?'<div class="empty-state">No notifications</div>':[...this._notifications].sort((e,
|
|
6272
|
-
<div class="notif-row ${
|
|
6273
|
-
<span class="severity-dot" style="background: ${
|
|
6301
|
+
`}_renderNotificationList(){return this._notifications.length===0?'<div class="empty-state">No notifications</div>':[...this._notifications].sort((e,i)=>new Date(i.timestamp)-new Date(e.timestamp)).map(e=>{let i=e.acknowledged,a=this._getSeverityColor(e.severity);return`
|
|
6302
|
+
<div class="notif-row ${i?"acknowledged":""}">
|
|
6303
|
+
<span class="severity-dot" style="background: ${a};" title="${this._escapeHTML(e.severity)}"></span>
|
|
6274
6304
|
<span class="notif-time">${this._formatTime(e.timestamp)}</span>
|
|
6275
6305
|
<span class="notif-message">${this._escapeHTML(e.message)}</span>
|
|
6276
6306
|
${e.iteration!=null?`<span class="notif-iteration">iter ${e.iteration}</span>`:""}
|
|
6277
|
-
${
|
|
6307
|
+
${i?"":`<button class="ack-btn" data-id="${this._escapeHTML(e.id)}">Ack</button>`}
|
|
6278
6308
|
</div>
|
|
6279
|
-
`}).join("")}_renderTriggerList(){return this._triggers.length===0?'<div class="empty-state">No triggers configured</div>':this._triggers.map(t=>{let e=this._getSeverityColor(t.severity),
|
|
6309
|
+
`}).join("")}_renderTriggerList(){return this._triggers.length===0?'<div class="empty-state">No triggers configured</div>':this._triggers.map(t=>{let e=this._getSeverityColor(t.severity),i=t.threshold_pct!=null?`Threshold: ${t.threshold_pct}%`:t.pattern||"";return`
|
|
6280
6310
|
<div class="trigger-row">
|
|
6281
6311
|
<label class="toggle">
|
|
6282
6312
|
<input type="checkbox" data-trigger-id="${this._escapeHTML(t.id)}" ${t.enabled?"checked":""}>
|
|
@@ -6285,7 +6315,7 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
6285
6315
|
<span class="trigger-name">${this._escapeHTML(t.id)}</span>
|
|
6286
6316
|
<span class="trigger-badge type-badge">${this._escapeHTML(t.type||"custom")}</span>
|
|
6287
6317
|
<span class="trigger-badge severity-badge" style="background: ${e}; color: #fff;">${this._escapeHTML(t.severity||"info")}</span>
|
|
6288
|
-
${
|
|
6318
|
+
${i?`<span class="trigger-info">${this._escapeHTML(i)}</span>`:""}
|
|
6289
6319
|
</div>
|
|
6290
6320
|
`}).join("")}render(){this.shadowRoot.innerHTML=`
|
|
6291
6321
|
<style>
|
|
@@ -6623,158 +6653,1439 @@ var LokiDashboard=(()=>{var X=Object.defineProperty;var gt=Object.getOwnProperty
|
|
|
6623
6653
|
</div>
|
|
6624
6654
|
`:""}
|
|
6625
6655
|
</div>
|
|
6626
|
-
`,this._bindEvents()}};customElements.get("loki-notification-center")||customElements.define("loki-notification-center",
|
|
6656
|
+
`,this._bindEvents()}};customElements.get("loki-notification-center")||customElements.define("loki-notification-center",X);var Z=class extends p{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}async _loadData(){try{this._data=await this._api._get("/api/session-diff"),this._error=null}catch(t){this._error=t.message,this._data=null}this._loading=!1,this.render()}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleDecision(t){this._expandedDecisions.has(t)?this._expandedDecisions.delete(t):this._expandedDecisions.add(t),this.render()}render(){let t=`
|
|
6657
|
+
${this.getBaseStyles()}
|
|
6627
6658
|
|
|
6659
|
+
:host {
|
|
6660
|
+
display: block;
|
|
6661
|
+
}
|
|
6628
6662
|
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
var themeLabel = document.getElementById('theme-label');
|
|
6663
|
+
.diff-container {
|
|
6664
|
+
background: var(--loki-bg-card);
|
|
6665
|
+
border: 1px solid var(--loki-glass-border);
|
|
6666
|
+
border-radius: 5px;
|
|
6667
|
+
padding: 16px;
|
|
6668
|
+
margin-top: 16px;
|
|
6669
|
+
transition: all var(--loki-transition);
|
|
6670
|
+
}
|
|
6638
6671
|
|
|
6639
|
-
|
|
6640
|
-
|
|
6672
|
+
.diff-header {
|
|
6673
|
+
display: flex;
|
|
6674
|
+
align-items: center;
|
|
6675
|
+
gap: 8px;
|
|
6676
|
+
margin-bottom: 14px;
|
|
6677
|
+
}
|
|
6641
6678
|
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
}
|
|
6679
|
+
.diff-header svg {
|
|
6680
|
+
width: 16px;
|
|
6681
|
+
height: 16px;
|
|
6682
|
+
color: var(--loki-text-muted);
|
|
6683
|
+
flex-shrink: 0;
|
|
6684
|
+
}
|
|
6649
6685
|
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6686
|
+
.diff-title {
|
|
6687
|
+
font-size: 12px;
|
|
6688
|
+
font-weight: 600;
|
|
6689
|
+
text-transform: uppercase;
|
|
6690
|
+
letter-spacing: 0.05em;
|
|
6691
|
+
color: var(--loki-text-muted);
|
|
6692
|
+
}
|
|
6654
6693
|
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6694
|
+
.diff-period {
|
|
6695
|
+
font-size: 11px;
|
|
6696
|
+
color: var(--loki-text-muted);
|
|
6697
|
+
margin-left: auto;
|
|
6698
|
+
font-family: 'JetBrains Mono', monospace;
|
|
6699
|
+
}
|
|
6658
6700
|
|
|
6659
|
-
|
|
6701
|
+
.summary-grid {
|
|
6702
|
+
display: grid;
|
|
6703
|
+
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
|
|
6704
|
+
gap: 8px;
|
|
6705
|
+
margin-bottom: 14px;
|
|
6706
|
+
}
|
|
6660
6707
|
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6708
|
+
.summary-item {
|
|
6709
|
+
background: var(--loki-bg-secondary);
|
|
6710
|
+
border: 1px solid var(--loki-border);
|
|
6711
|
+
border-radius: 5px;
|
|
6712
|
+
padding: 10px 12px;
|
|
6713
|
+
text-align: center;
|
|
6714
|
+
}
|
|
6666
6715
|
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
'checklist-viewer',
|
|
6676
|
-
'app-status',
|
|
6677
|
-
'council-dashboard',
|
|
6678
|
-
'cost-dashboard',
|
|
6679
|
-
'checkpoint-viewer',
|
|
6680
|
-
'context-tracker',
|
|
6681
|
-
'notification-center'
|
|
6682
|
-
];
|
|
6683
|
-
components.forEach(function(id) {
|
|
6684
|
-
var el = document.getElementById(id);
|
|
6685
|
-
if (el) el.setAttribute('api-url', apiUrl);
|
|
6686
|
-
});
|
|
6687
|
-
console.log('API URL updated:', apiUrl);
|
|
6688
|
-
}
|
|
6716
|
+
.summary-label {
|
|
6717
|
+
font-size: 10px;
|
|
6718
|
+
font-weight: 600;
|
|
6719
|
+
text-transform: uppercase;
|
|
6720
|
+
letter-spacing: 0.05em;
|
|
6721
|
+
color: var(--loki-text-muted);
|
|
6722
|
+
margin-bottom: 4px;
|
|
6723
|
+
}
|
|
6689
6724
|
|
|
6690
|
-
|
|
6691
|
-
|
|
6725
|
+
.summary-value {
|
|
6726
|
+
font-size: 18px;
|
|
6727
|
+
font-weight: 600;
|
|
6728
|
+
font-family: 'JetBrains Mono', monospace;
|
|
6729
|
+
color: var(--loki-accent);
|
|
6730
|
+
}
|
|
6692
6731
|
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6732
|
+
.summary-value.error-count {
|
|
6733
|
+
color: var(--loki-red);
|
|
6734
|
+
}
|
|
6696
6735
|
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
});
|
|
6736
|
+
.highlights-section {
|
|
6737
|
+
margin-bottom: 14px;
|
|
6738
|
+
}
|
|
6701
6739
|
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6740
|
+
.section-label {
|
|
6741
|
+
font-size: 11px;
|
|
6742
|
+
font-weight: 600;
|
|
6743
|
+
text-transform: uppercase;
|
|
6744
|
+
letter-spacing: 0.05em;
|
|
6745
|
+
color: var(--loki-text-muted);
|
|
6746
|
+
margin-bottom: 8px;
|
|
6747
|
+
}
|
|
6705
6748
|
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6749
|
+
.highlight-list {
|
|
6750
|
+
list-style: none;
|
|
6751
|
+
padding: 0;
|
|
6752
|
+
margin: 0;
|
|
6753
|
+
display: flex;
|
|
6754
|
+
flex-direction: column;
|
|
6755
|
+
gap: 4px;
|
|
6756
|
+
}
|
|
6709
6757
|
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6758
|
+
.highlight-item {
|
|
6759
|
+
font-size: 12px;
|
|
6760
|
+
color: var(--loki-text-secondary);
|
|
6761
|
+
padding: 6px 10px;
|
|
6762
|
+
background: var(--loki-bg-secondary);
|
|
6763
|
+
border-radius: 4px;
|
|
6764
|
+
border-left: 3px solid var(--loki-accent);
|
|
6765
|
+
}
|
|
6713
6766
|
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6767
|
+
.decisions-section {
|
|
6768
|
+
margin-top: 14px;
|
|
6769
|
+
}
|
|
6717
6770
|
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
}
|
|
6725
|
-
});
|
|
6771
|
+
.decision-item {
|
|
6772
|
+
border: 1px solid var(--loki-border);
|
|
6773
|
+
border-radius: 5px;
|
|
6774
|
+
margin-bottom: 6px;
|
|
6775
|
+
overflow: hidden;
|
|
6776
|
+
}
|
|
6726
6777
|
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6778
|
+
.decision-header {
|
|
6779
|
+
display: flex;
|
|
6780
|
+
align-items: center;
|
|
6781
|
+
gap: 8px;
|
|
6782
|
+
padding: 8px 12px;
|
|
6783
|
+
cursor: pointer;
|
|
6784
|
+
background: var(--loki-bg-secondary);
|
|
6785
|
+
font-size: 12px;
|
|
6786
|
+
font-weight: 500;
|
|
6787
|
+
color: var(--loki-text-primary);
|
|
6788
|
+
transition: background var(--loki-transition);
|
|
6789
|
+
border: none;
|
|
6790
|
+
width: 100%;
|
|
6791
|
+
text-align: left;
|
|
6792
|
+
font-family: inherit;
|
|
6793
|
+
}
|
|
6730
6794
|
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
allPages.forEach(function(page) { page.classList.remove('active'); });
|
|
6735
|
-
var pageEl = document.getElementById('page-' + sectionId);
|
|
6736
|
-
if (pageEl) {
|
|
6737
|
-
pageEl.classList.add('active');
|
|
6738
|
-
}
|
|
6739
|
-
// Update nav active state
|
|
6740
|
-
navLinks.forEach(function(link) { link.classList.remove('active'); });
|
|
6741
|
-
var navEl = document.querySelector('.nav-link[data-section="' + sectionId + '"]');
|
|
6742
|
-
if (navEl) navEl.classList.add('active');
|
|
6743
|
-
// Scroll main content to top on section switch
|
|
6744
|
-
mainContent.scrollTop = 0;
|
|
6745
|
-
localStorage.setItem('loki-active-section', sectionId);
|
|
6746
|
-
}
|
|
6795
|
+
.decision-header:hover {
|
|
6796
|
+
background: var(--loki-bg-hover);
|
|
6797
|
+
}
|
|
6747
6798
|
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
if (window.innerWidth <= 768) {
|
|
6753
|
-
sidebar.classList.remove('mobile-open');
|
|
6799
|
+
.decision-arrow {
|
|
6800
|
+
font-size: 10px;
|
|
6801
|
+
color: var(--loki-text-muted);
|
|
6802
|
+
transition: transform 0.15s ease;
|
|
6754
6803
|
}
|
|
6755
|
-
});
|
|
6756
|
-
});
|
|
6757
6804
|
|
|
6758
|
-
|
|
6759
|
-
|
|
6805
|
+
.decision-arrow.expanded {
|
|
6806
|
+
transform: rotate(90deg);
|
|
6807
|
+
}
|
|
6760
6808
|
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
}
|
|
6769
|
-
});
|
|
6809
|
+
.decision-reasoning {
|
|
6810
|
+
padding: 8px 12px;
|
|
6811
|
+
font-size: 11px;
|
|
6812
|
+
color: var(--loki-text-secondary);
|
|
6813
|
+
border-top: 1px solid var(--loki-border);
|
|
6814
|
+
line-height: 1.5;
|
|
6815
|
+
}
|
|
6770
6816
|
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6817
|
+
.empty-state {
|
|
6818
|
+
text-align: center;
|
|
6819
|
+
padding: 20px;
|
|
6820
|
+
color: var(--loki-text-muted);
|
|
6821
|
+
font-size: 12px;
|
|
6822
|
+
}
|
|
6774
6823
|
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6824
|
+
.error-state {
|
|
6825
|
+
text-align: center;
|
|
6826
|
+
padding: 16px;
|
|
6827
|
+
color: var(--loki-red);
|
|
6828
|
+
font-size: 12px;
|
|
6829
|
+
}
|
|
6830
|
+
|
|
6831
|
+
.loading-state {
|
|
6832
|
+
display: flex;
|
|
6833
|
+
align-items: center;
|
|
6834
|
+
justify-content: center;
|
|
6835
|
+
padding: 20px;
|
|
6836
|
+
gap: 8px;
|
|
6837
|
+
color: var(--loki-text-muted);
|
|
6838
|
+
font-size: 12px;
|
|
6839
|
+
}
|
|
6840
|
+
|
|
6841
|
+
.spinner {
|
|
6842
|
+
width: 14px;
|
|
6843
|
+
height: 14px;
|
|
6844
|
+
border: 2px solid var(--loki-border);
|
|
6845
|
+
border-top-color: var(--loki-accent);
|
|
6846
|
+
border-radius: 50%;
|
|
6847
|
+
animation: spin 0.8s linear infinite;
|
|
6848
|
+
}
|
|
6849
|
+
|
|
6850
|
+
@keyframes spin {
|
|
6851
|
+
to { transform: rotate(360deg); }
|
|
6852
|
+
}
|
|
6853
|
+
`;if(this._loading){this.shadowRoot.innerHTML=`
|
|
6854
|
+
<style>${t}</style>
|
|
6855
|
+
<div class="diff-container">
|
|
6856
|
+
<div class="loading-state"><div class="spinner"></div> Loading session diff...</div>
|
|
6857
|
+
</div>
|
|
6858
|
+
`;return}if(this._error){this.shadowRoot.innerHTML=`
|
|
6859
|
+
<style>${t}</style>
|
|
6860
|
+
<div class="diff-container">
|
|
6861
|
+
<div class="diff-header">
|
|
6862
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
|
|
6863
|
+
<span class="diff-title">Session Resume</span>
|
|
6864
|
+
</div>
|
|
6865
|
+
<div class="empty-state">No session diff available</div>
|
|
6866
|
+
</div>
|
|
6867
|
+
`;return}let e=this._data||{},i=this._escapeHtml(e.period||"--"),a=e.counts||{},s=e.highlights||[],r=e.decisions||[],o="";s.length>0&&(o=`
|
|
6868
|
+
<div class="highlights-section">
|
|
6869
|
+
<div class="section-label">Highlights</div>
|
|
6870
|
+
<ul class="highlight-list">
|
|
6871
|
+
${s.map(d=>`<li class="highlight-item">${this._escapeHtml(d)}</li>`).join("")}
|
|
6872
|
+
</ul>
|
|
6873
|
+
</div>
|
|
6874
|
+
`);let n="";r.length>0&&(n=`
|
|
6875
|
+
<div class="decisions-section">
|
|
6876
|
+
<div class="section-label">Decisions</div>
|
|
6877
|
+
${r.map((d,g)=>{let v=this._expandedDecisions.has(g);return`
|
|
6878
|
+
<div class="decision-item">
|
|
6879
|
+
<button class="decision-header" data-index="${g}">
|
|
6880
|
+
<span class="decision-arrow ${v?"expanded":""}">▶</span>
|
|
6881
|
+
${this._escapeHtml(d.title||d.decision||"Decision")}
|
|
6882
|
+
</button>
|
|
6883
|
+
${v?`<div class="decision-reasoning">${this._escapeHtml(d.reasoning||d.rationale||"No reasoning provided")}</div>`:""}
|
|
6884
|
+
</div>
|
|
6885
|
+
`}).join("")}
|
|
6886
|
+
</div>
|
|
6887
|
+
`),this.shadowRoot.innerHTML=`
|
|
6888
|
+
<style>${t}</style>
|
|
6889
|
+
<div class="diff-container">
|
|
6890
|
+
<div class="diff-header">
|
|
6891
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
|
|
6892
|
+
<span class="diff-title">Session Resume</span>
|
|
6893
|
+
<span class="diff-period">${i}</span>
|
|
6894
|
+
</div>
|
|
6895
|
+
|
|
6896
|
+
<div class="summary-grid">
|
|
6897
|
+
<div class="summary-item">
|
|
6898
|
+
<div class="summary-label">Created</div>
|
|
6899
|
+
<div class="summary-value">${a.tasks_created!=null?a.tasks_created:"--"}</div>
|
|
6900
|
+
</div>
|
|
6901
|
+
<div class="summary-item">
|
|
6902
|
+
<div class="summary-label">Completed</div>
|
|
6903
|
+
<div class="summary-value">${a.tasks_completed!=null?a.tasks_completed:"--"}</div>
|
|
6904
|
+
</div>
|
|
6905
|
+
<div class="summary-item">
|
|
6906
|
+
<div class="summary-label">Blocked</div>
|
|
6907
|
+
<div class="summary-value">${a.tasks_blocked!=null?a.tasks_blocked:"--"}</div>
|
|
6908
|
+
</div>
|
|
6909
|
+
<div class="summary-item">
|
|
6910
|
+
<div class="summary-label">Errors</div>
|
|
6911
|
+
<div class="summary-value ${(a.errors||0)>0?"error-count":""}">${a.errors!=null?a.errors:"--"}</div>
|
|
6912
|
+
</div>
|
|
6913
|
+
</div>
|
|
6914
|
+
|
|
6915
|
+
${o}
|
|
6916
|
+
${n}
|
|
6917
|
+
</div>
|
|
6918
|
+
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(d=>{d.addEventListener("click",()=>{this._toggleDecision(parseInt(d.dataset.index))})})}};customElements.get("loki-session-diff")||customElements.define("loki-session-diff",Z);var tt=class extends p{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}async _loadData(){try{this._data=await this._api._get("/api/prompt-versions"),this._error=null}catch(t){this._error=t.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(t){this._error=t.message}this._optimizing=!1,this.render()}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),6e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_formatTime(t){if(!t)return"--";try{let e=new Date(t),a=new Date-e,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(t){this._expandedChanges.has(t)?this._expandedChanges.delete(t):this._expandedChanges.add(t),this.render()}render(){let t=`
|
|
6919
|
+
${this.getBaseStyles()}
|
|
6920
|
+
|
|
6921
|
+
:host {
|
|
6922
|
+
display: block;
|
|
6923
|
+
}
|
|
6924
|
+
|
|
6925
|
+
.optimizer-container {
|
|
6926
|
+
background: var(--loki-bg-card);
|
|
6927
|
+
border: 1px solid var(--loki-glass-border);
|
|
6928
|
+
border-radius: 5px;
|
|
6929
|
+
padding: 16px;
|
|
6930
|
+
transition: all var(--loki-transition);
|
|
6931
|
+
}
|
|
6932
|
+
|
|
6933
|
+
.optimizer-header {
|
|
6934
|
+
display: flex;
|
|
6935
|
+
align-items: center;
|
|
6936
|
+
gap: 8px;
|
|
6937
|
+
margin-bottom: 14px;
|
|
6938
|
+
}
|
|
6939
|
+
|
|
6940
|
+
.optimizer-header svg {
|
|
6941
|
+
width: 16px;
|
|
6942
|
+
height: 16px;
|
|
6943
|
+
color: var(--loki-text-muted);
|
|
6944
|
+
flex-shrink: 0;
|
|
6945
|
+
}
|
|
6946
|
+
|
|
6947
|
+
.optimizer-title {
|
|
6948
|
+
font-size: 12px;
|
|
6949
|
+
font-weight: 600;
|
|
6950
|
+
text-transform: uppercase;
|
|
6951
|
+
letter-spacing: 0.05em;
|
|
6952
|
+
color: var(--loki-text-muted);
|
|
6953
|
+
}
|
|
6954
|
+
|
|
6955
|
+
.optimize-btn {
|
|
6956
|
+
margin-left: auto;
|
|
6957
|
+
padding: 4px 12px;
|
|
6958
|
+
background: var(--loki-accent);
|
|
6959
|
+
color: #fff;
|
|
6960
|
+
border: none;
|
|
6961
|
+
border-radius: 4px;
|
|
6962
|
+
font-size: 11px;
|
|
6963
|
+
font-weight: 500;
|
|
6964
|
+
cursor: pointer;
|
|
6965
|
+
transition: all var(--loki-transition);
|
|
6966
|
+
font-family: inherit;
|
|
6967
|
+
display: flex;
|
|
6968
|
+
align-items: center;
|
|
6969
|
+
gap: 6px;
|
|
6970
|
+
}
|
|
6971
|
+
|
|
6972
|
+
.optimize-btn:hover:not(:disabled) {
|
|
6973
|
+
background: var(--loki-accent-hover);
|
|
6974
|
+
}
|
|
6975
|
+
|
|
6976
|
+
.optimize-btn:disabled {
|
|
6977
|
+
opacity: 0.5;
|
|
6978
|
+
cursor: not-allowed;
|
|
6979
|
+
}
|
|
6980
|
+
|
|
6981
|
+
.info-grid {
|
|
6982
|
+
display: grid;
|
|
6983
|
+
grid-template-columns: repeat(3, 1fr);
|
|
6984
|
+
gap: 8px;
|
|
6985
|
+
margin-bottom: 14px;
|
|
6986
|
+
}
|
|
6987
|
+
|
|
6988
|
+
.info-item {
|
|
6989
|
+
background: var(--loki-bg-secondary);
|
|
6990
|
+
border: 1px solid var(--loki-border);
|
|
6991
|
+
border-radius: 5px;
|
|
6992
|
+
padding: 10px 12px;
|
|
6993
|
+
text-align: center;
|
|
6994
|
+
}
|
|
6995
|
+
|
|
6996
|
+
.info-label {
|
|
6997
|
+
font-size: 10px;
|
|
6998
|
+
font-weight: 600;
|
|
6999
|
+
text-transform: uppercase;
|
|
7000
|
+
letter-spacing: 0.05em;
|
|
7001
|
+
color: var(--loki-text-muted);
|
|
7002
|
+
margin-bottom: 4px;
|
|
7003
|
+
}
|
|
7004
|
+
|
|
7005
|
+
.info-value {
|
|
7006
|
+
font-size: 16px;
|
|
7007
|
+
font-weight: 600;
|
|
7008
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7009
|
+
color: var(--loki-accent);
|
|
7010
|
+
}
|
|
7011
|
+
|
|
7012
|
+
.info-value.muted {
|
|
7013
|
+
font-size: 12px;
|
|
7014
|
+
color: var(--loki-text-secondary);
|
|
7015
|
+
}
|
|
7016
|
+
|
|
7017
|
+
.changes-section {
|
|
7018
|
+
margin-top: 14px;
|
|
7019
|
+
}
|
|
7020
|
+
|
|
7021
|
+
.section-label {
|
|
7022
|
+
font-size: 11px;
|
|
7023
|
+
font-weight: 600;
|
|
7024
|
+
text-transform: uppercase;
|
|
7025
|
+
letter-spacing: 0.05em;
|
|
7026
|
+
color: var(--loki-text-muted);
|
|
7027
|
+
margin-bottom: 8px;
|
|
7028
|
+
}
|
|
7029
|
+
|
|
7030
|
+
.change-item {
|
|
7031
|
+
border: 1px solid var(--loki-border);
|
|
7032
|
+
border-radius: 5px;
|
|
7033
|
+
margin-bottom: 6px;
|
|
7034
|
+
overflow: hidden;
|
|
7035
|
+
}
|
|
7036
|
+
|
|
7037
|
+
.change-header {
|
|
7038
|
+
display: flex;
|
|
7039
|
+
align-items: center;
|
|
7040
|
+
gap: 8px;
|
|
7041
|
+
padding: 8px 12px;
|
|
7042
|
+
cursor: pointer;
|
|
7043
|
+
background: var(--loki-bg-secondary);
|
|
7044
|
+
font-size: 12px;
|
|
7045
|
+
font-weight: 500;
|
|
7046
|
+
color: var(--loki-text-primary);
|
|
7047
|
+
transition: background var(--loki-transition);
|
|
7048
|
+
border: none;
|
|
7049
|
+
width: 100%;
|
|
7050
|
+
text-align: left;
|
|
7051
|
+
font-family: inherit;
|
|
7052
|
+
}
|
|
7053
|
+
|
|
7054
|
+
.change-header:hover {
|
|
7055
|
+
background: var(--loki-bg-hover);
|
|
7056
|
+
}
|
|
7057
|
+
|
|
7058
|
+
.change-arrow {
|
|
7059
|
+
font-size: 10px;
|
|
7060
|
+
color: var(--loki-text-muted);
|
|
7061
|
+
transition: transform 0.15s ease;
|
|
7062
|
+
}
|
|
7063
|
+
|
|
7064
|
+
.change-arrow.expanded {
|
|
7065
|
+
transform: rotate(90deg);
|
|
7066
|
+
}
|
|
7067
|
+
|
|
7068
|
+
.change-rationale {
|
|
7069
|
+
padding: 8px 12px;
|
|
7070
|
+
font-size: 11px;
|
|
7071
|
+
color: var(--loki-text-secondary);
|
|
7072
|
+
border-top: 1px solid var(--loki-border);
|
|
7073
|
+
line-height: 1.5;
|
|
7074
|
+
}
|
|
7075
|
+
|
|
7076
|
+
.empty-state {
|
|
7077
|
+
text-align: center;
|
|
7078
|
+
padding: 20px;
|
|
7079
|
+
color: var(--loki-text-muted);
|
|
7080
|
+
font-size: 12px;
|
|
7081
|
+
}
|
|
7082
|
+
|
|
7083
|
+
.loading-state {
|
|
7084
|
+
display: flex;
|
|
7085
|
+
align-items: center;
|
|
7086
|
+
justify-content: center;
|
|
7087
|
+
padding: 20px;
|
|
7088
|
+
gap: 8px;
|
|
7089
|
+
color: var(--loki-text-muted);
|
|
7090
|
+
font-size: 12px;
|
|
7091
|
+
}
|
|
7092
|
+
|
|
7093
|
+
.spinner {
|
|
7094
|
+
width: 14px;
|
|
7095
|
+
height: 14px;
|
|
7096
|
+
border: 2px solid var(--loki-border);
|
|
7097
|
+
border-top-color: var(--loki-accent);
|
|
7098
|
+
border-radius: 50%;
|
|
7099
|
+
animation: spin 0.8s linear infinite;
|
|
7100
|
+
}
|
|
7101
|
+
|
|
7102
|
+
.spinner-sm {
|
|
7103
|
+
width: 12px;
|
|
7104
|
+
height: 12px;
|
|
7105
|
+
border: 2px solid rgba(255,255,255,0.3);
|
|
7106
|
+
border-top-color: #fff;
|
|
7107
|
+
border-radius: 50%;
|
|
7108
|
+
animation: spin 0.8s linear infinite;
|
|
7109
|
+
}
|
|
7110
|
+
|
|
7111
|
+
@keyframes spin {
|
|
7112
|
+
to { transform: rotate(360deg); }
|
|
7113
|
+
}
|
|
7114
|
+
`;if(this._loading){this.shadowRoot.innerHTML=`
|
|
7115
|
+
<style>${t}</style>
|
|
7116
|
+
<div class="optimizer-container">
|
|
7117
|
+
<div class="loading-state"><div class="spinner"></div> Loading prompt data...</div>
|
|
7118
|
+
</div>
|
|
7119
|
+
`;return}if(this._error&&!this._data){this.shadowRoot.innerHTML=`
|
|
7120
|
+
<style>${t}</style>
|
|
7121
|
+
<div class="optimizer-container">
|
|
7122
|
+
<div class="optimizer-header">
|
|
7123
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
7124
|
+
<span class="optimizer-title">Prompt Optimizer</span>
|
|
7125
|
+
</div>
|
|
7126
|
+
<div class="empty-state">No prompt optimization data available</div>
|
|
7127
|
+
</div>
|
|
7128
|
+
`;return}let e=this._data||{},i=e.version!=null?e.version:"--",a=this._formatTime(e.last_optimized),s=e.failures_analyzed!=null?e.failures_analyzed:"--",r=e.changes||[],o="";r.length>0&&(o=`
|
|
7129
|
+
<div class="changes-section">
|
|
7130
|
+
<div class="section-label">Changes</div>
|
|
7131
|
+
${r.map((d,g)=>{let v=this._expandedChanges.has(g);return`
|
|
7132
|
+
<div class="change-item">
|
|
7133
|
+
<button class="change-header" data-index="${g}">
|
|
7134
|
+
<span class="change-arrow ${v?"expanded":""}">▶</span>
|
|
7135
|
+
${this._escapeHtml(d.description||d.title||"Change")}
|
|
7136
|
+
</button>
|
|
7137
|
+
${v?`<div class="change-rationale">${this._escapeHtml(d.rationale||d.reasoning||"No rationale provided")}</div>`:""}
|
|
7138
|
+
</div>
|
|
7139
|
+
`}).join("")}
|
|
7140
|
+
</div>
|
|
7141
|
+
`),this.shadowRoot.innerHTML=`
|
|
7142
|
+
<style>${t}</style>
|
|
7143
|
+
<div class="optimizer-container">
|
|
7144
|
+
<div class="optimizer-header">
|
|
7145
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
7146
|
+
<span class="optimizer-title">Prompt Optimizer</span>
|
|
7147
|
+
<button class="optimize-btn" id="optimize-btn" ${this._optimizing?"disabled":""}>
|
|
7148
|
+
${this._optimizing?'<div class="spinner-sm"></div> Optimizing...':"Optimize Now"}
|
|
7149
|
+
</button>
|
|
7150
|
+
</div>
|
|
7151
|
+
|
|
7152
|
+
<div class="info-grid">
|
|
7153
|
+
<div class="info-item">
|
|
7154
|
+
<div class="info-label">Version</div>
|
|
7155
|
+
<div class="info-value">v${this._escapeHtml(String(i))}</div>
|
|
7156
|
+
</div>
|
|
7157
|
+
<div class="info-item">
|
|
7158
|
+
<div class="info-label">Last Optimized</div>
|
|
7159
|
+
<div class="info-value muted">${this._escapeHtml(a)}</div>
|
|
7160
|
+
</div>
|
|
7161
|
+
<div class="info-item">
|
|
7162
|
+
<div class="info-label">Failures Analyzed</div>
|
|
7163
|
+
<div class="info-value">${s}</div>
|
|
7164
|
+
</div>
|
|
7165
|
+
</div>
|
|
7166
|
+
|
|
7167
|
+
${o}
|
|
7168
|
+
</div>
|
|
7169
|
+
`;let n=this.shadowRoot.getElementById("optimize-btn");n&&n.addEventListener("click",()=>this._triggerOptimize()),this.shadowRoot.querySelectorAll(".change-header").forEach(d=>{d.addEventListener("click",()=>{this._toggleChange(parseInt(d.dataset.index))})})}};customElements.get("loki-prompt-optimizer")||customElements.define("loki-prompt-optimizer",tt);var et=class extends p{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}async _loadData(){try{let[t,e]=await Promise.allSettled([this._api._get("/api/quality-score"),this._api._get("/api/quality-score/history")]);if(t.status==="fulfilled"){let i=t.value;i&&i.error&&i.error.includes("not installed")?(this._rigourAvailable=!1,this._data=null):(this._rigourAvailable=!0,this._data=i),this._error=null}else(t.reason?.message||"").includes("404")?(this._rigourAvailable=!1,this._data=null,this._error=null):(this._error="Failed to load quality score",this._data=null);if(e.status==="fulfilled"){let i=e.value;this._history=Array.isArray(i)?i.slice(-10):(i.scores||[]).slice(-10)}}catch(t){this._error=t.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",{}),await this._loadData()}catch(t){this._error=t.message}this._scanning=!1,this.render()}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),6e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGrade(t){return t>=90?{grade:"A",color:"var(--loki-success)"}:t>=80?{grade:"B",color:"var(--loki-success)"}:t>=70?{grade:"C",color:"var(--loki-warning)"}:t>=60?{grade:"D",color:"var(--loki-warning)"}:{grade:"F",color:"var(--loki-error)"}}_renderSparkline(t){if(!t||t.length<2)return"";let e=t.map(g=>typeof g=="number"?g:g.score||0),i=Math.min(...e),s=Math.max(...e)-i||1,r=120,o=32,n=2,d=e.map((g,v)=>{let x=n+v/(e.length-1)*(r-n*2),_=n+(1-(g-i)/s)*(o-n*2);return`${x},${_}`}).join(" ");return`
|
|
7170
|
+
<svg width="${r}" height="${o}" viewBox="0 0 ${r} ${o}" class="sparkline">
|
|
7171
|
+
<polyline points="${d}" fill="none" stroke="var(--loki-accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
7172
|
+
<circle cx="${d.split(" ").pop().split(",")[0]}" cy="${d.split(" ").pop().split(",")[1]}" r="2.5" fill="var(--loki-accent)"/>
|
|
7173
|
+
</svg>
|
|
7174
|
+
`}render(){let t=`
|
|
7175
|
+
${this.getBaseStyles()}
|
|
7176
|
+
|
|
7177
|
+
:host {
|
|
7178
|
+
display: block;
|
|
7179
|
+
}
|
|
7180
|
+
|
|
7181
|
+
.quality-container {
|
|
7182
|
+
background: var(--loki-bg-card);
|
|
7183
|
+
border: 1px solid var(--loki-glass-border);
|
|
7184
|
+
border-radius: 5px;
|
|
7185
|
+
padding: 16px;
|
|
7186
|
+
transition: all var(--loki-transition);
|
|
7187
|
+
}
|
|
7188
|
+
|
|
7189
|
+
.quality-header {
|
|
7190
|
+
display: flex;
|
|
7191
|
+
align-items: center;
|
|
7192
|
+
gap: 8px;
|
|
7193
|
+
margin-bottom: 14px;
|
|
7194
|
+
}
|
|
7195
|
+
|
|
7196
|
+
.quality-header svg {
|
|
7197
|
+
width: 16px;
|
|
7198
|
+
height: 16px;
|
|
7199
|
+
color: var(--loki-text-muted);
|
|
7200
|
+
flex-shrink: 0;
|
|
7201
|
+
}
|
|
7202
|
+
|
|
7203
|
+
.quality-title {
|
|
7204
|
+
font-size: 12px;
|
|
7205
|
+
font-weight: 600;
|
|
7206
|
+
text-transform: uppercase;
|
|
7207
|
+
letter-spacing: 0.05em;
|
|
7208
|
+
color: var(--loki-text-muted);
|
|
7209
|
+
}
|
|
7210
|
+
|
|
7211
|
+
.scan-btn {
|
|
7212
|
+
margin-left: auto;
|
|
7213
|
+
padding: 4px 12px;
|
|
7214
|
+
background: var(--loki-accent);
|
|
7215
|
+
color: #fff;
|
|
7216
|
+
border: none;
|
|
7217
|
+
border-radius: 4px;
|
|
7218
|
+
font-size: 11px;
|
|
7219
|
+
font-weight: 500;
|
|
7220
|
+
cursor: pointer;
|
|
7221
|
+
transition: all var(--loki-transition);
|
|
7222
|
+
font-family: inherit;
|
|
7223
|
+
display: flex;
|
|
7224
|
+
align-items: center;
|
|
7225
|
+
gap: 6px;
|
|
7226
|
+
}
|
|
7227
|
+
|
|
7228
|
+
.scan-btn:hover:not(:disabled) {
|
|
7229
|
+
background: var(--loki-accent-hover);
|
|
7230
|
+
}
|
|
7231
|
+
|
|
7232
|
+
.scan-btn:disabled {
|
|
7233
|
+
opacity: 0.5;
|
|
7234
|
+
cursor: not-allowed;
|
|
7235
|
+
}
|
|
7236
|
+
|
|
7237
|
+
.score-section {
|
|
7238
|
+
display: flex;
|
|
7239
|
+
align-items: center;
|
|
7240
|
+
gap: 16px;
|
|
7241
|
+
margin-bottom: 16px;
|
|
7242
|
+
}
|
|
7243
|
+
|
|
7244
|
+
.score-display {
|
|
7245
|
+
text-align: center;
|
|
7246
|
+
min-width: 80px;
|
|
7247
|
+
}
|
|
7248
|
+
|
|
7249
|
+
.score-number {
|
|
7250
|
+
font-size: 36px;
|
|
7251
|
+
font-weight: 700;
|
|
7252
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7253
|
+
line-height: 1;
|
|
7254
|
+
color: var(--loki-text-primary);
|
|
7255
|
+
}
|
|
7256
|
+
|
|
7257
|
+
.grade-badge {
|
|
7258
|
+
display: inline-block;
|
|
7259
|
+
padding: 2px 10px;
|
|
7260
|
+
border-radius: 4px;
|
|
7261
|
+
font-size: 12px;
|
|
7262
|
+
font-weight: 600;
|
|
7263
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7264
|
+
margin-top: 4px;
|
|
7265
|
+
}
|
|
7266
|
+
|
|
7267
|
+
.sparkline-container {
|
|
7268
|
+
flex: 1;
|
|
7269
|
+
display: flex;
|
|
7270
|
+
flex-direction: column;
|
|
7271
|
+
align-items: flex-end;
|
|
7272
|
+
}
|
|
7273
|
+
|
|
7274
|
+
.sparkline-label {
|
|
7275
|
+
font-size: 10px;
|
|
7276
|
+
color: var(--loki-text-muted);
|
|
7277
|
+
margin-bottom: 4px;
|
|
7278
|
+
}
|
|
7279
|
+
|
|
7280
|
+
.sparkline {
|
|
7281
|
+
display: block;
|
|
7282
|
+
}
|
|
7283
|
+
|
|
7284
|
+
.categories-section {
|
|
7285
|
+
margin-bottom: 14px;
|
|
7286
|
+
}
|
|
7287
|
+
|
|
7288
|
+
.section-label {
|
|
7289
|
+
font-size: 11px;
|
|
7290
|
+
font-weight: 600;
|
|
7291
|
+
text-transform: uppercase;
|
|
7292
|
+
letter-spacing: 0.05em;
|
|
7293
|
+
color: var(--loki-text-muted);
|
|
7294
|
+
margin-bottom: 8px;
|
|
7295
|
+
}
|
|
7296
|
+
|
|
7297
|
+
.category-item {
|
|
7298
|
+
display: flex;
|
|
7299
|
+
align-items: center;
|
|
7300
|
+
gap: 10px;
|
|
7301
|
+
margin-bottom: 6px;
|
|
7302
|
+
}
|
|
7303
|
+
|
|
7304
|
+
.category-name {
|
|
7305
|
+
font-size: 11px;
|
|
7306
|
+
color: var(--loki-text-secondary);
|
|
7307
|
+
min-width: 100px;
|
|
7308
|
+
text-transform: capitalize;
|
|
7309
|
+
}
|
|
7310
|
+
|
|
7311
|
+
.progress-bar {
|
|
7312
|
+
flex: 1;
|
|
7313
|
+
height: 6px;
|
|
7314
|
+
background: var(--loki-bg-tertiary);
|
|
7315
|
+
border-radius: 3px;
|
|
7316
|
+
overflow: hidden;
|
|
7317
|
+
}
|
|
7318
|
+
|
|
7319
|
+
.progress-fill {
|
|
7320
|
+
height: 100%;
|
|
7321
|
+
border-radius: 3px;
|
|
7322
|
+
transition: width 0.3s ease;
|
|
7323
|
+
}
|
|
7324
|
+
|
|
7325
|
+
.category-score {
|
|
7326
|
+
font-size: 11px;
|
|
7327
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7328
|
+
color: var(--loki-text-secondary);
|
|
7329
|
+
min-width: 28px;
|
|
7330
|
+
text-align: right;
|
|
7331
|
+
}
|
|
7332
|
+
|
|
7333
|
+
.findings-section {
|
|
7334
|
+
margin-top: 14px;
|
|
7335
|
+
}
|
|
7336
|
+
|
|
7337
|
+
.findings-row {
|
|
7338
|
+
display: flex;
|
|
7339
|
+
gap: 8px;
|
|
7340
|
+
flex-wrap: wrap;
|
|
7341
|
+
}
|
|
7342
|
+
|
|
7343
|
+
.finding-badge {
|
|
7344
|
+
display: inline-flex;
|
|
7345
|
+
align-items: center;
|
|
7346
|
+
gap: 4px;
|
|
7347
|
+
padding: 3px 10px;
|
|
7348
|
+
border-radius: 4px;
|
|
7349
|
+
font-size: 11px;
|
|
7350
|
+
font-weight: 500;
|
|
7351
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7352
|
+
}
|
|
7353
|
+
|
|
7354
|
+
.finding-critical {
|
|
7355
|
+
background: rgba(224, 112, 112, 0.15);
|
|
7356
|
+
color: var(--loki-error);
|
|
7357
|
+
}
|
|
7358
|
+
|
|
7359
|
+
.finding-major {
|
|
7360
|
+
background: rgba(232, 184, 74, 0.15);
|
|
7361
|
+
color: var(--loki-warning);
|
|
7362
|
+
}
|
|
7363
|
+
|
|
7364
|
+
.finding-minor {
|
|
7365
|
+
background: rgba(232, 184, 74, 0.10);
|
|
7366
|
+
color: var(--loki-warning);
|
|
7367
|
+
}
|
|
7368
|
+
|
|
7369
|
+
.finding-info {
|
|
7370
|
+
background: var(--loki-bg-tertiary);
|
|
7371
|
+
color: var(--loki-text-muted);
|
|
7372
|
+
}
|
|
7373
|
+
|
|
7374
|
+
.not-installed {
|
|
7375
|
+
text-align: center;
|
|
7376
|
+
padding: 24px 16px;
|
|
7377
|
+
color: var(--loki-text-muted);
|
|
7378
|
+
font-size: 12px;
|
|
7379
|
+
line-height: 1.6;
|
|
7380
|
+
}
|
|
7381
|
+
|
|
7382
|
+
.not-installed-title {
|
|
7383
|
+
font-size: 13px;
|
|
7384
|
+
font-weight: 600;
|
|
7385
|
+
color: var(--loki-text-secondary);
|
|
7386
|
+
margin-bottom: 6px;
|
|
7387
|
+
}
|
|
7388
|
+
|
|
7389
|
+
.install-cmd {
|
|
7390
|
+
display: inline-block;
|
|
7391
|
+
padding: 4px 10px;
|
|
7392
|
+
background: var(--loki-bg-secondary);
|
|
7393
|
+
border: 1px solid var(--loki-border);
|
|
7394
|
+
border-radius: 4px;
|
|
7395
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7396
|
+
font-size: 11px;
|
|
7397
|
+
color: var(--loki-accent);
|
|
7398
|
+
margin-top: 8px;
|
|
7399
|
+
}
|
|
7400
|
+
|
|
7401
|
+
.empty-state {
|
|
7402
|
+
text-align: center;
|
|
7403
|
+
padding: 20px;
|
|
7404
|
+
color: var(--loki-text-muted);
|
|
7405
|
+
font-size: 12px;
|
|
7406
|
+
}
|
|
7407
|
+
|
|
7408
|
+
.loading-state {
|
|
7409
|
+
display: flex;
|
|
7410
|
+
align-items: center;
|
|
7411
|
+
justify-content: center;
|
|
7412
|
+
padding: 20px;
|
|
7413
|
+
gap: 8px;
|
|
7414
|
+
color: var(--loki-text-muted);
|
|
7415
|
+
font-size: 12px;
|
|
7416
|
+
}
|
|
7417
|
+
|
|
7418
|
+
.spinner {
|
|
7419
|
+
width: 14px;
|
|
7420
|
+
height: 14px;
|
|
7421
|
+
border: 2px solid var(--loki-border);
|
|
7422
|
+
border-top-color: var(--loki-accent);
|
|
7423
|
+
border-radius: 50%;
|
|
7424
|
+
animation: spin 0.8s linear infinite;
|
|
7425
|
+
}
|
|
7426
|
+
|
|
7427
|
+
.spinner-sm {
|
|
7428
|
+
width: 12px;
|
|
7429
|
+
height: 12px;
|
|
7430
|
+
border: 2px solid rgba(255,255,255,0.3);
|
|
7431
|
+
border-top-color: #fff;
|
|
7432
|
+
border-radius: 50%;
|
|
7433
|
+
animation: spin 0.8s linear infinite;
|
|
7434
|
+
}
|
|
7435
|
+
|
|
7436
|
+
@keyframes spin {
|
|
7437
|
+
to { transform: rotate(360deg); }
|
|
7438
|
+
}
|
|
7439
|
+
`;if(this._loading){this.shadowRoot.innerHTML=`
|
|
7440
|
+
<style>${t}</style>
|
|
7441
|
+
<div class="quality-container">
|
|
7442
|
+
<div class="loading-state"><div class="spinner"></div> Loading quality score...</div>
|
|
7443
|
+
</div>
|
|
7444
|
+
`;return}if(!this._rigourAvailable){this.shadowRoot.innerHTML=`
|
|
7445
|
+
<style>${t}</style>
|
|
7446
|
+
<div class="quality-container">
|
|
7447
|
+
<div class="quality-header">
|
|
7448
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
|
7449
|
+
<span class="quality-title">Quality Score</span>
|
|
7450
|
+
</div>
|
|
7451
|
+
<div class="not-installed">
|
|
7452
|
+
<div class="not-installed-title">Rigour not installed</div>
|
|
7453
|
+
<div>Quality scoring requires the Rigour analysis engine.</div>
|
|
7454
|
+
<div class="install-cmd">pip install rigour</div>
|
|
7455
|
+
</div>
|
|
7456
|
+
</div>
|
|
7457
|
+
`;return}if(this._error&&!this._data){this.shadowRoot.innerHTML=`
|
|
7458
|
+
<style>${t}</style>
|
|
7459
|
+
<div class="quality-container">
|
|
7460
|
+
<div class="quality-header">
|
|
7461
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
|
7462
|
+
<span class="quality-title">Quality Score</span>
|
|
7463
|
+
</div>
|
|
7464
|
+
<div class="empty-state">No quality data available</div>
|
|
7465
|
+
</div>
|
|
7466
|
+
`;return}let e=this._data||{},i=e.score!=null?Math.round(e.score):0,{grade:a,color:s}=this._getGrade(i),r=e.categories||{},o=e.findings||{},n=["security","code_quality","compliance","best_practices"],d={security:"Security",code_quality:"Code Quality",compliance:"Compliance",best_practices:"Best Practices"},g=n.map(y=>{let at=r[y]!=null?Math.round(r[y]):0,yt=at>=80?"var(--loki-success)":at>=60?"var(--loki-warning)":"var(--loki-error)";return`
|
|
7467
|
+
<div class="category-item">
|
|
7468
|
+
<span class="category-name">${d[y]||y}</span>
|
|
7469
|
+
<div class="progress-bar">
|
|
7470
|
+
<div class="progress-fill" style="width:${at}%;background:${yt};"></div>
|
|
7471
|
+
</div>
|
|
7472
|
+
<span class="category-score">${at}</span>
|
|
7473
|
+
</div>
|
|
7474
|
+
`}).join(""),x=[{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(y=>(o[y.key]||0)>0).map(y=>`<span class="finding-badge ${y.cls}">${y.label}: ${o[y.key]}</span>`).join(""),_=this._renderSparkline(this._history);this.shadowRoot.innerHTML=`
|
|
7475
|
+
<style>${t}</style>
|
|
7476
|
+
<div class="quality-container">
|
|
7477
|
+
<div class="quality-header">
|
|
7478
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
|
7479
|
+
<span class="quality-title">Quality Score</span>
|
|
7480
|
+
<button class="scan-btn" id="scan-btn" ${this._scanning?"disabled":""}>
|
|
7481
|
+
${this._scanning?'<div class="spinner-sm"></div> Scanning...':"Run Scan"}
|
|
7482
|
+
</button>
|
|
7483
|
+
</div>
|
|
7484
|
+
|
|
7485
|
+
<div class="score-section">
|
|
7486
|
+
<div class="score-display">
|
|
7487
|
+
<div class="score-number">${i}</div>
|
|
7488
|
+
<span class="grade-badge" style="background:${s};color:#fff;">${a}</span>
|
|
7489
|
+
</div>
|
|
7490
|
+
${_?`
|
|
7491
|
+
<div class="sparkline-container">
|
|
7492
|
+
<span class="sparkline-label">Trend (last ${this._history.length})</span>
|
|
7493
|
+
${_}
|
|
7494
|
+
</div>
|
|
7495
|
+
`:""}
|
|
7496
|
+
</div>
|
|
7497
|
+
|
|
7498
|
+
<div class="categories-section">
|
|
7499
|
+
<div class="section-label">Categories</div>
|
|
7500
|
+
${g}
|
|
7501
|
+
</div>
|
|
7502
|
+
|
|
7503
|
+
${x?`
|
|
7504
|
+
<div class="findings-section">
|
|
7505
|
+
<div class="section-label">Findings</div>
|
|
7506
|
+
<div class="findings-row">${x}</div>
|
|
7507
|
+
</div>
|
|
7508
|
+
`:""}
|
|
7509
|
+
</div>
|
|
7510
|
+
`;let M=this.shadowRoot.getElementById("scan-btn");M&&M.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-score")||customElements.define("loki-quality-score",et);var xt=["understand","guardrail","migrate","verify"],_t={understand:"Understand",guardrail:"Guardrail",migrate:"Migrate",verify:"Verify"},Bt={understand:"#5b9bd5",guardrail:"#e8b84a",migrate:"#5bb870",verify:"#5bc8c8"},it=class extends p{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._pollInterval=setInterval(()=>this._fetchData(),15e3)}disconnectedCallback(){super.disconnectedCallback(),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._fetchMigrations()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=u({baseUrl:t})}async _fetchMigrations(){try{let t=await this._api._get("/api/migration/list");this._migrations=Array.isArray(t)?t:t.migrations||[],this._error=null;let e=this._migrations.find(i=>i.status==="in_progress"||i.status==="active");e?await this._fetchStatus(e.migration_id||e.id):this._migration=null}catch(t){this._error=t.message,this._migrations=[],this._migration=null}this._loading=!1,this.render()}async _fetchStatus(t){try{this._migration=await this._api._get(`/api/migration/${encodeURIComponent(t)}/status`),this._error=null}catch(e){this._error=e.message}}async _fetchData(){let t=this._migration&&(this._migration.migration_id||this._migration.id);t?(await this._fetchStatus(t),this.render()):await this._fetchMigrations()}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"):""}_getPhaseIcon(t,e,i){return(i||[]).includes(t)?"[x]":t===e?"[>]":"[ ]"}_getPhaseIndex(t){let e=xt.indexOf(t);return e>=0?e:0}_renderPhaseBar(t,e){let i=e||[];return xt.map(a=>{let s=i.includes(a),r=a===t,o=Bt[a],n=s?"1":r?"0.7":"0.2",d=this._getPhaseIcon(a,t,e);return`
|
|
7511
|
+
<div class="phase-segment">
|
|
7512
|
+
<div class="phase-bar-fill" style="background:${o};opacity:${n};"></div>
|
|
7513
|
+
<div class="phase-label">
|
|
7514
|
+
<span class="phase-icon">${d}</span>
|
|
7515
|
+
${_t[a]}
|
|
7516
|
+
</div>
|
|
7517
|
+
</div>
|
|
7518
|
+
`}).join("")}_renderFeatureStats(t){if(!t)return"";let e=t.passing||0,i=t.total||0,a=i>0?Math.round(e/i*100):0,s=a>=80?"var(--loki-success)":a>=50?"var(--loki-warning)":"var(--loki-error)";return`
|
|
7519
|
+
<div class="stat-card">
|
|
7520
|
+
<div class="stat-header">Feature Tracking</div>
|
|
7521
|
+
<div class="stat-value">${e} / ${i}</div>
|
|
7522
|
+
<div class="stat-pct">${a}% passing</div>
|
|
7523
|
+
<div class="progress-bar">
|
|
7524
|
+
<div class="progress-fill" style="width:${a}%;background:${s};"></div>
|
|
7525
|
+
</div>
|
|
7526
|
+
</div>
|
|
7527
|
+
`}_renderStepProgress(t){if(!t)return"";let e=t.current||0,i=t.total||0,a=i>0?Math.round(e/i*100):0;return`
|
|
7528
|
+
<div class="stat-card">
|
|
7529
|
+
<div class="stat-header">Step Progress</div>
|
|
7530
|
+
<div class="stat-value">${e} / ${i}</div>
|
|
7531
|
+
<div class="stat-pct">${a}% complete</div>
|
|
7532
|
+
<div class="progress-bar">
|
|
7533
|
+
<div class="progress-fill" style="width:${a}%;background:var(--loki-accent);"></div>
|
|
7534
|
+
</div>
|
|
7535
|
+
</div>
|
|
7536
|
+
`}_renderSeamSummary(t){if(!t)return"";let e=t.total||0,i=t.high||0,a=t.medium||0,s=t.low||0;return`
|
|
7537
|
+
<div class="stat-card">
|
|
7538
|
+
<div class="stat-header">Seam Summary</div>
|
|
7539
|
+
<div class="stat-value">${e} seams</div>
|
|
7540
|
+
<div class="seam-breakdown">
|
|
7541
|
+
<span class="seam-badge seam-high">High: ${i}</span>
|
|
7542
|
+
<span class="seam-badge seam-medium">Med: ${a}</span>
|
|
7543
|
+
<span class="seam-badge seam-low">Low: ${s}</span>
|
|
7544
|
+
</div>
|
|
7545
|
+
</div>
|
|
7546
|
+
`}_renderCheckpoint(t){if(!t)return"";let e=t.timestamp?new Date(t.timestamp).toLocaleString():"--",i=this._escapeHtml(t.step_id||t.stepId||"--");return`
|
|
7547
|
+
<div class="checkpoint-section">
|
|
7548
|
+
<div class="section-label">Last Checkpoint</div>
|
|
7549
|
+
<div class="checkpoint-row">
|
|
7550
|
+
<span class="checkpoint-label">Time:</span>
|
|
7551
|
+
<span class="checkpoint-value">${this._escapeHtml(e)}</span>
|
|
7552
|
+
</div>
|
|
7553
|
+
<div class="checkpoint-row">
|
|
7554
|
+
<span class="checkpoint-label">Step:</span>
|
|
7555
|
+
<span class="checkpoint-value mono">${i}</span>
|
|
7556
|
+
</div>
|
|
7557
|
+
</div>
|
|
7558
|
+
`}_renderMigrationList(){return this._migrations.length===0?'<div class="empty-state">No migrations found</div>':`
|
|
7559
|
+
<table class="migration-table">
|
|
7560
|
+
<thead>
|
|
7561
|
+
<tr><th>ID</th><th>Migration</th><th>Status</th></tr>
|
|
7562
|
+
</thead>
|
|
7563
|
+
<tbody>${this._migrations.map(e=>{let i=this._escapeHtml(e.migration_id||e.id||"--"),a=this._escapeHtml(e.source||"--"),s=this._escapeHtml(e.target||"--"),r=this._escapeHtml(e.status||"--"),o=e.status==="completed"?"status-done":e.status==="failed"?"status-failed":"status-pending";return`
|
|
7564
|
+
<tr>
|
|
7565
|
+
<td class="mono">${i}</td>
|
|
7566
|
+
<td>${a} -> ${s}</td>
|
|
7567
|
+
<td><span class="status-badge ${o}">${r}</span></td>
|
|
7568
|
+
</tr>
|
|
7569
|
+
`}).join("")}</tbody>
|
|
7570
|
+
</table>
|
|
7571
|
+
`}render(){let t=`
|
|
7572
|
+
${this.getBaseStyles()}
|
|
7573
|
+
|
|
7574
|
+
:host { display: block; }
|
|
7575
|
+
|
|
7576
|
+
.migration-container {
|
|
7577
|
+
background: var(--loki-bg-card);
|
|
7578
|
+
border: 1px solid var(--loki-glass-border);
|
|
7579
|
+
border-radius: 5px;
|
|
7580
|
+
padding: 16px;
|
|
7581
|
+
transition: all var(--loki-transition);
|
|
7582
|
+
}
|
|
7583
|
+
|
|
7584
|
+
.migration-header {
|
|
7585
|
+
display: flex;
|
|
7586
|
+
align-items: center;
|
|
7587
|
+
gap: 8px;
|
|
7588
|
+
margin-bottom: 14px;
|
|
7589
|
+
}
|
|
7590
|
+
|
|
7591
|
+
.migration-header svg {
|
|
7592
|
+
width: 16px;
|
|
7593
|
+
height: 16px;
|
|
7594
|
+
color: var(--loki-text-muted);
|
|
7595
|
+
flex-shrink: 0;
|
|
7596
|
+
}
|
|
7597
|
+
|
|
7598
|
+
.migration-title {
|
|
7599
|
+
font-size: 12px;
|
|
7600
|
+
font-weight: 600;
|
|
7601
|
+
text-transform: uppercase;
|
|
7602
|
+
letter-spacing: 0.05em;
|
|
7603
|
+
color: var(--loki-text-muted);
|
|
7604
|
+
}
|
|
7605
|
+
|
|
7606
|
+
.migration-id {
|
|
7607
|
+
margin-left: auto;
|
|
7608
|
+
font-size: 11px;
|
|
7609
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7610
|
+
color: var(--loki-text-muted);
|
|
7611
|
+
}
|
|
7612
|
+
|
|
7613
|
+
.meta-row {
|
|
7614
|
+
display: flex;
|
|
7615
|
+
align-items: center;
|
|
7616
|
+
gap: 16px;
|
|
7617
|
+
margin-bottom: 14px;
|
|
7618
|
+
flex-wrap: wrap;
|
|
7619
|
+
}
|
|
7620
|
+
|
|
7621
|
+
.meta-item {
|
|
7622
|
+
font-size: 12px;
|
|
7623
|
+
color: var(--loki-text-secondary);
|
|
7624
|
+
}
|
|
7625
|
+
|
|
7626
|
+
.meta-label {
|
|
7627
|
+
font-weight: 600;
|
|
7628
|
+
color: var(--loki-text-muted);
|
|
7629
|
+
font-size: 10px;
|
|
7630
|
+
text-transform: uppercase;
|
|
7631
|
+
letter-spacing: 0.05em;
|
|
7632
|
+
display: block;
|
|
7633
|
+
margin-bottom: 2px;
|
|
7634
|
+
}
|
|
7635
|
+
|
|
7636
|
+
.mono {
|
|
7637
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7638
|
+
}
|
|
7639
|
+
|
|
7640
|
+
.phase-bar-container {
|
|
7641
|
+
display: grid;
|
|
7642
|
+
grid-template-columns: repeat(4, 1fr);
|
|
7643
|
+
gap: 4px;
|
|
7644
|
+
margin-bottom: 16px;
|
|
7645
|
+
}
|
|
7646
|
+
|
|
7647
|
+
.phase-segment {
|
|
7648
|
+
display: flex;
|
|
7649
|
+
flex-direction: column;
|
|
7650
|
+
align-items: center;
|
|
7651
|
+
gap: 4px;
|
|
7652
|
+
}
|
|
7653
|
+
|
|
7654
|
+
.phase-bar-fill {
|
|
7655
|
+
width: 100%;
|
|
7656
|
+
height: 8px;
|
|
7657
|
+
border-radius: 4px;
|
|
7658
|
+
transition: opacity 0.3s ease;
|
|
7659
|
+
}
|
|
7660
|
+
|
|
7661
|
+
.phase-label {
|
|
7662
|
+
font-size: 10px;
|
|
7663
|
+
font-weight: 600;
|
|
7664
|
+
text-transform: uppercase;
|
|
7665
|
+
letter-spacing: 0.03em;
|
|
7666
|
+
color: var(--loki-text-muted);
|
|
7667
|
+
display: flex;
|
|
7668
|
+
align-items: center;
|
|
7669
|
+
gap: 4px;
|
|
7670
|
+
}
|
|
7671
|
+
|
|
7672
|
+
.phase-icon {
|
|
7673
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7674
|
+
font-size: 9px;
|
|
7675
|
+
}
|
|
7676
|
+
|
|
7677
|
+
.stats-grid {
|
|
7678
|
+
display: grid;
|
|
7679
|
+
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
7680
|
+
gap: 10px;
|
|
7681
|
+
margin-bottom: 14px;
|
|
7682
|
+
}
|
|
7683
|
+
|
|
7684
|
+
.stat-card {
|
|
7685
|
+
background: var(--loki-bg-secondary);
|
|
7686
|
+
border: 1px solid var(--loki-border);
|
|
7687
|
+
border-radius: 5px;
|
|
7688
|
+
padding: 10px 12px;
|
|
7689
|
+
}
|
|
7690
|
+
|
|
7691
|
+
.stat-header {
|
|
7692
|
+
font-size: 10px;
|
|
7693
|
+
font-weight: 600;
|
|
7694
|
+
text-transform: uppercase;
|
|
7695
|
+
letter-spacing: 0.05em;
|
|
7696
|
+
color: var(--loki-text-muted);
|
|
7697
|
+
margin-bottom: 6px;
|
|
7698
|
+
}
|
|
7699
|
+
|
|
7700
|
+
.stat-value {
|
|
7701
|
+
font-size: 20px;
|
|
7702
|
+
font-weight: 700;
|
|
7703
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7704
|
+
color: var(--loki-text-primary);
|
|
7705
|
+
line-height: 1;
|
|
7706
|
+
margin-bottom: 4px;
|
|
7707
|
+
}
|
|
7708
|
+
|
|
7709
|
+
.stat-pct {
|
|
7710
|
+
font-size: 11px;
|
|
7711
|
+
color: var(--loki-text-muted);
|
|
7712
|
+
margin-bottom: 6px;
|
|
7713
|
+
}
|
|
7714
|
+
|
|
7715
|
+
.progress-bar {
|
|
7716
|
+
width: 100%;
|
|
7717
|
+
height: 6px;
|
|
7718
|
+
background: var(--loki-bg-tertiary);
|
|
7719
|
+
border-radius: 3px;
|
|
7720
|
+
overflow: hidden;
|
|
7721
|
+
}
|
|
7722
|
+
|
|
7723
|
+
.progress-fill {
|
|
7724
|
+
height: 100%;
|
|
7725
|
+
border-radius: 3px;
|
|
7726
|
+
transition: width 0.3s ease;
|
|
7727
|
+
}
|
|
7728
|
+
|
|
7729
|
+
.seam-breakdown {
|
|
7730
|
+
display: flex;
|
|
7731
|
+
gap: 6px;
|
|
7732
|
+
margin-top: 6px;
|
|
7733
|
+
flex-wrap: wrap;
|
|
7734
|
+
}
|
|
7735
|
+
|
|
7736
|
+
.seam-badge {
|
|
7737
|
+
display: inline-block;
|
|
7738
|
+
padding: 2px 8px;
|
|
7739
|
+
border-radius: 4px;
|
|
7740
|
+
font-size: 10px;
|
|
7741
|
+
font-weight: 500;
|
|
7742
|
+
font-family: 'JetBrains Mono', monospace;
|
|
7743
|
+
}
|
|
7744
|
+
|
|
7745
|
+
.seam-high {
|
|
7746
|
+
background: rgba(224, 112, 112, 0.15);
|
|
7747
|
+
color: var(--loki-error);
|
|
7748
|
+
}
|
|
7749
|
+
|
|
7750
|
+
.seam-medium {
|
|
7751
|
+
background: rgba(232, 184, 74, 0.15);
|
|
7752
|
+
color: var(--loki-warning);
|
|
7753
|
+
}
|
|
7754
|
+
|
|
7755
|
+
.seam-low {
|
|
7756
|
+
background: var(--loki-bg-tertiary);
|
|
7757
|
+
color: var(--loki-text-muted);
|
|
7758
|
+
}
|
|
7759
|
+
|
|
7760
|
+
.checkpoint-section {
|
|
7761
|
+
margin-bottom: 14px;
|
|
7762
|
+
}
|
|
7763
|
+
|
|
7764
|
+
.section-label {
|
|
7765
|
+
font-size: 11px;
|
|
7766
|
+
font-weight: 600;
|
|
7767
|
+
text-transform: uppercase;
|
|
7768
|
+
letter-spacing: 0.05em;
|
|
7769
|
+
color: var(--loki-text-muted);
|
|
7770
|
+
margin-bottom: 8px;
|
|
7771
|
+
}
|
|
7772
|
+
|
|
7773
|
+
.checkpoint-row {
|
|
7774
|
+
display: flex;
|
|
7775
|
+
gap: 8px;
|
|
7776
|
+
align-items: baseline;
|
|
7777
|
+
margin-bottom: 4px;
|
|
7778
|
+
font-size: 12px;
|
|
7779
|
+
}
|
|
7780
|
+
|
|
7781
|
+
.checkpoint-label {
|
|
7782
|
+
color: var(--loki-text-muted);
|
|
7783
|
+
min-width: 40px;
|
|
7784
|
+
}
|
|
7785
|
+
|
|
7786
|
+
.checkpoint-value {
|
|
7787
|
+
color: var(--loki-text-secondary);
|
|
7788
|
+
}
|
|
7789
|
+
|
|
7790
|
+
.migration-table {
|
|
7791
|
+
width: 100%;
|
|
7792
|
+
border-collapse: collapse;
|
|
7793
|
+
font-size: 12px;
|
|
7794
|
+
}
|
|
7795
|
+
|
|
7796
|
+
.migration-table th {
|
|
7797
|
+
text-align: left;
|
|
7798
|
+
font-size: 10px;
|
|
7799
|
+
font-weight: 600;
|
|
7800
|
+
text-transform: uppercase;
|
|
7801
|
+
letter-spacing: 0.05em;
|
|
7802
|
+
color: var(--loki-text-muted);
|
|
7803
|
+
padding: 6px 10px;
|
|
7804
|
+
border-bottom: 1px solid var(--loki-border);
|
|
7805
|
+
}
|
|
7806
|
+
|
|
7807
|
+
.migration-table td {
|
|
7808
|
+
padding: 8px 10px;
|
|
7809
|
+
color: var(--loki-text-secondary);
|
|
7810
|
+
border-bottom: 1px solid var(--loki-border);
|
|
7811
|
+
}
|
|
7812
|
+
|
|
7813
|
+
.migration-table tbody tr:last-child td {
|
|
7814
|
+
border-bottom: none;
|
|
7815
|
+
}
|
|
7816
|
+
|
|
7817
|
+
.status-badge {
|
|
7818
|
+
display: inline-block;
|
|
7819
|
+
padding: 2px 8px;
|
|
7820
|
+
border-radius: 4px;
|
|
7821
|
+
font-size: 10px;
|
|
7822
|
+
font-weight: 500;
|
|
7823
|
+
}
|
|
7824
|
+
|
|
7825
|
+
.status-done {
|
|
7826
|
+
background: rgba(91, 184, 112, 0.15);
|
|
7827
|
+
color: var(--loki-success);
|
|
7828
|
+
}
|
|
7829
|
+
|
|
7830
|
+
.status-failed {
|
|
7831
|
+
background: rgba(224, 112, 112, 0.15);
|
|
7832
|
+
color: var(--loki-error);
|
|
7833
|
+
}
|
|
7834
|
+
|
|
7835
|
+
.status-pending {
|
|
7836
|
+
background: var(--loki-bg-tertiary);
|
|
7837
|
+
color: var(--loki-text-muted);
|
|
7838
|
+
}
|
|
7839
|
+
|
|
7840
|
+
.empty-state {
|
|
7841
|
+
text-align: center;
|
|
7842
|
+
padding: 20px;
|
|
7843
|
+
color: var(--loki-text-muted);
|
|
7844
|
+
font-size: 12px;
|
|
7845
|
+
}
|
|
7846
|
+
|
|
7847
|
+
.loading-state {
|
|
7848
|
+
display: flex;
|
|
7849
|
+
align-items: center;
|
|
7850
|
+
justify-content: center;
|
|
7851
|
+
padding: 20px;
|
|
7852
|
+
gap: 8px;
|
|
7853
|
+
color: var(--loki-text-muted);
|
|
7854
|
+
font-size: 12px;
|
|
7855
|
+
}
|
|
7856
|
+
|
|
7857
|
+
.spinner {
|
|
7858
|
+
width: 14px;
|
|
7859
|
+
height: 14px;
|
|
7860
|
+
border: 2px solid var(--loki-border);
|
|
7861
|
+
border-top-color: var(--loki-accent);
|
|
7862
|
+
border-radius: 50%;
|
|
7863
|
+
animation: spin 0.8s linear infinite;
|
|
7864
|
+
}
|
|
7865
|
+
|
|
7866
|
+
@keyframes spin {
|
|
7867
|
+
to { transform: rotate(360deg); }
|
|
7868
|
+
}
|
|
7869
|
+
`,e='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/><line x1="4" y1="4" x2="9" y2="9"/></svg>';if(this._loading){this.shadowRoot.innerHTML=`
|
|
7870
|
+
<style>${t}</style>
|
|
7871
|
+
<div class="migration-container">
|
|
7872
|
+
<div class="loading-state"><div class="spinner"></div> Loading migrations...</div>
|
|
7873
|
+
</div>
|
|
7874
|
+
`;return}if(this._error&&!this._migration&&this._migrations.length===0){this.shadowRoot.innerHTML=`
|
|
7875
|
+
<style>${t}</style>
|
|
7876
|
+
<div class="migration-container">
|
|
7877
|
+
<div class="migration-header">
|
|
7878
|
+
${e}
|
|
7879
|
+
<span class="migration-title">Migration Dashboard</span>
|
|
7880
|
+
</div>
|
|
7881
|
+
<div class="empty-state">No migration data available</div>
|
|
7882
|
+
</div>
|
|
7883
|
+
`;return}if(this._migration){let i=this._migration,a=this._escapeHtml(i.migration_id||i.id||"--"),s=this._escapeHtml(i.source||"--"),r=this._escapeHtml(i.target||"--"),o=i.current_phase||i.phase||"understand",n=i.completed_phases||[];this.shadowRoot.innerHTML=`
|
|
7884
|
+
<style>${t}</style>
|
|
7885
|
+
<div class="migration-container">
|
|
7886
|
+
<div class="migration-header">
|
|
7887
|
+
${e}
|
|
7888
|
+
<span class="migration-title">Migration Dashboard</span>
|
|
7889
|
+
<span class="migration-id">${a}</span>
|
|
7890
|
+
</div>
|
|
7891
|
+
|
|
7892
|
+
<div class="meta-row">
|
|
7893
|
+
<div class="meta-item">
|
|
7894
|
+
<span class="meta-label">Source</span>
|
|
7895
|
+
<span class="mono">${s}</span>
|
|
7896
|
+
</div>
|
|
7897
|
+
<div class="meta-item">
|
|
7898
|
+
<span class="meta-label">-></span>
|
|
7899
|
+
</div>
|
|
7900
|
+
<div class="meta-item">
|
|
7901
|
+
<span class="meta-label">Target</span>
|
|
7902
|
+
<span class="mono">${r}</span>
|
|
7903
|
+
</div>
|
|
7904
|
+
<div class="meta-item">
|
|
7905
|
+
<span class="meta-label">Phase</span>
|
|
7906
|
+
<span>${_t[o]||this._escapeHtml(o)}</span>
|
|
7907
|
+
</div>
|
|
7908
|
+
</div>
|
|
7909
|
+
|
|
7910
|
+
<div class="section-label">Phase Progress</div>
|
|
7911
|
+
<div class="phase-bar-container">
|
|
7912
|
+
${this._renderPhaseBar(o,n)}
|
|
7913
|
+
</div>
|
|
7914
|
+
|
|
7915
|
+
<div class="stats-grid">
|
|
7916
|
+
${this._renderFeatureStats(i.features)}
|
|
7917
|
+
${this._renderStepProgress(i.steps)}
|
|
7918
|
+
${this._renderSeamSummary(i.seams)}
|
|
7919
|
+
</div>
|
|
7920
|
+
|
|
7921
|
+
${this._renderCheckpoint(i.last_checkpoint||i.checkpoint)}
|
|
7922
|
+
</div>
|
|
7923
|
+
`;return}this.shadowRoot.innerHTML=`
|
|
7924
|
+
<style>${t}</style>
|
|
7925
|
+
<div class="migration-container">
|
|
7926
|
+
<div class="migration-header">
|
|
7927
|
+
${e}
|
|
7928
|
+
<span class="migration-title">Migration Dashboard</span>
|
|
7929
|
+
</div>
|
|
7930
|
+
<div class="section-label">Migrations</div>
|
|
7931
|
+
${this._renderMigrationList()}
|
|
7932
|
+
</div>
|
|
7933
|
+
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",it);var Ft="1.3.0";function jt(c={}){return c.theme?m.setTheme(c.theme):c.autoDetectContext!==!1?m.init():D.init(),c.apiUrl&&u({baseUrl:c.apiUrl}),{theme:m.getTheme(),context:m.detectContext()}}return At(Ut);})();
|
|
7934
|
+
|
|
7935
|
+
|
|
7936
|
+
// Initialize dashboard when DOM is ready
|
|
7937
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
7938
|
+
// Initialize the dashboard with auto-detect
|
|
7939
|
+
var initResult = LokiDashboard.init({ autoDetectContext: true });
|
|
7940
|
+
console.log('Loki Dashboard initialized:', initResult);
|
|
7941
|
+
|
|
7942
|
+
// Theme toggle functionality
|
|
7943
|
+
var themeToggle = document.getElementById('theme-toggle');
|
|
7944
|
+
var themeLabel = document.getElementById('theme-label');
|
|
7945
|
+
|
|
7946
|
+
var sunIcon = document.getElementById('theme-icon-sun');
|
|
7947
|
+
var moonIcon = document.getElementById('theme-icon-moon');
|
|
7948
|
+
|
|
7949
|
+
function updateThemeUI() {
|
|
7950
|
+
var theme = LokiDashboard.UnifiedThemeManager.getTheme();
|
|
7951
|
+
var isDark = theme.includes('dark') || theme === 'high-contrast';
|
|
7952
|
+
themeLabel.textContent = isDark ? 'Light' : 'Dark';
|
|
7953
|
+
if (sunIcon) sunIcon.style.display = isDark ? 'inline' : 'none';
|
|
7954
|
+
if (moonIcon) moonIcon.style.display = isDark ? 'none' : 'inline';
|
|
7955
|
+
}
|
|
7956
|
+
|
|
7957
|
+
themeToggle.addEventListener('click', function() {
|
|
7958
|
+
LokiDashboard.UnifiedThemeManager.toggle();
|
|
7959
|
+
updateThemeUI();
|
|
7960
|
+
});
|
|
7961
|
+
|
|
7962
|
+
window.addEventListener('loki-theme-change', function() {
|
|
7963
|
+
updateThemeUI();
|
|
7964
|
+
});
|
|
7965
|
+
|
|
7966
|
+
updateThemeUI();
|
|
7967
|
+
|
|
7968
|
+
// API URL configuration - auto-detect from current server
|
|
7969
|
+
var apiUrlInput = document.getElementById('api-url');
|
|
7970
|
+
var connectBtn = document.getElementById('connect-btn');
|
|
7971
|
+
var detectedUrl = window.location.origin;
|
|
7972
|
+
apiUrlInput.value = detectedUrl;
|
|
7973
|
+
|
|
7974
|
+
function updateComponentsApiUrl(apiUrl) {
|
|
7975
|
+
var components = [
|
|
7976
|
+
'overview',
|
|
7977
|
+
'task-board',
|
|
7978
|
+
'session-control',
|
|
7979
|
+
'log-stream',
|
|
7980
|
+
'memory-browser',
|
|
7981
|
+
'learning-dashboard',
|
|
7982
|
+
'checklist-viewer',
|
|
7983
|
+
'app-status',
|
|
7984
|
+
'council-dashboard',
|
|
7985
|
+
'cost-dashboard',
|
|
7986
|
+
'checkpoint-viewer',
|
|
7987
|
+
'context-tracker',
|
|
7988
|
+
'notification-center',
|
|
7989
|
+
'session-diff',
|
|
7990
|
+
'prompt-optimizer',
|
|
7991
|
+
'quality-score',
|
|
7992
|
+
'migration-dashboard'
|
|
7993
|
+
];
|
|
7994
|
+
components.forEach(function(id) {
|
|
7995
|
+
var el = document.getElementById(id);
|
|
7996
|
+
if (el) el.setAttribute('api-url', apiUrl);
|
|
7997
|
+
});
|
|
7998
|
+
console.log('API URL updated:', apiUrl);
|
|
7999
|
+
}
|
|
8000
|
+
|
|
8001
|
+
// Auto-connect to current server on load
|
|
8002
|
+
updateComponentsApiUrl(detectedUrl);
|
|
8003
|
+
|
|
8004
|
+
connectBtn.addEventListener('click', function() {
|
|
8005
|
+
updateComponentsApiUrl(apiUrlInput.value);
|
|
8006
|
+
});
|
|
8007
|
+
|
|
8008
|
+
// Offline detection
|
|
8009
|
+
window.addEventListener('online', function() {
|
|
8010
|
+
document.getElementById('offline-banner').classList.remove('show');
|
|
8011
|
+
});
|
|
8012
|
+
|
|
8013
|
+
window.addEventListener('offline', function() {
|
|
8014
|
+
document.getElementById('offline-banner').classList.add('show');
|
|
8015
|
+
});
|
|
8016
|
+
|
|
8017
|
+
if (!navigator.onLine) {
|
|
8018
|
+
document.getElementById('offline-banner').classList.add('show');
|
|
8019
|
+
}
|
|
8020
|
+
|
|
8021
|
+
// Mobile menu toggle
|
|
8022
|
+
var mobileMenuBtn = document.getElementById('mobile-menu-btn');
|
|
8023
|
+
var sidebar = document.getElementById('sidebar');
|
|
8024
|
+
|
|
8025
|
+
mobileMenuBtn.addEventListener('click', function() {
|
|
8026
|
+
sidebar.classList.toggle('mobile-open');
|
|
8027
|
+
});
|
|
8028
|
+
|
|
8029
|
+
document.addEventListener('click', function(e) {
|
|
8030
|
+
if (window.innerWidth <= 768 &&
|
|
8031
|
+
sidebar.classList.contains('mobile-open') &&
|
|
8032
|
+
!sidebar.contains(e.target) &&
|
|
8033
|
+
!mobileMenuBtn.contains(e.target)) {
|
|
8034
|
+
sidebar.classList.remove('mobile-open');
|
|
8035
|
+
}
|
|
8036
|
+
});
|
|
8037
|
+
|
|
8038
|
+
// --- Section Navigation ---
|
|
8039
|
+
var navLinks = document.querySelectorAll('.nav-link');
|
|
8040
|
+
var mainContent = document.getElementById('main-content');
|
|
8041
|
+
|
|
8042
|
+
function switchSection(sectionId) {
|
|
8043
|
+
// Hide all section pages, show only the active one
|
|
8044
|
+
var allPages = document.querySelectorAll('.section-page');
|
|
8045
|
+
allPages.forEach(function(page) { page.classList.remove('active'); });
|
|
8046
|
+
var pageEl = document.getElementById('page-' + sectionId);
|
|
8047
|
+
if (pageEl) {
|
|
8048
|
+
pageEl.classList.add('active');
|
|
8049
|
+
}
|
|
8050
|
+
// Update nav active state
|
|
8051
|
+
navLinks.forEach(function(link) { link.classList.remove('active'); });
|
|
8052
|
+
var navEl = document.querySelector('.nav-link[data-section="' + sectionId + '"]');
|
|
8053
|
+
if (navEl) navEl.classList.add('active');
|
|
8054
|
+
// Scroll main content to top on section switch
|
|
8055
|
+
mainContent.scrollTop = 0;
|
|
8056
|
+
localStorage.setItem('loki-active-section', sectionId);
|
|
8057
|
+
}
|
|
8058
|
+
|
|
8059
|
+
navLinks.forEach(function(link) {
|
|
8060
|
+
link.addEventListener('click', function() {
|
|
8061
|
+
switchSection(link.dataset.section);
|
|
8062
|
+
// Close mobile sidebar
|
|
8063
|
+
if (window.innerWidth <= 768) {
|
|
8064
|
+
sidebar.classList.remove('mobile-open');
|
|
8065
|
+
}
|
|
8066
|
+
});
|
|
8067
|
+
});
|
|
8068
|
+
|
|
8069
|
+
// Show the default section (overview) on load
|
|
8070
|
+
switchSection('overview');
|
|
8071
|
+
|
|
8072
|
+
// Keyboard shortcuts: Cmd/Ctrl + 1-7
|
|
8073
|
+
document.addEventListener('keydown', function(e) {
|
|
8074
|
+
if ((e.metaKey || e.ctrlKey) && ((e.key >= '1' && e.key <= '9') || e.key === '0')) {
|
|
8075
|
+
e.preventDefault();
|
|
8076
|
+
var sections = ['overview', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'checkpoint', 'context', 'notifications', 'migration'];
|
|
8077
|
+
var idx = e.key === '0' ? 9 : parseInt(e.key) - 1;
|
|
8078
|
+
if (idx < sections.length) switchSection(sections[idx]);
|
|
8079
|
+
}
|
|
8080
|
+
});
|
|
8081
|
+
|
|
8082
|
+
// --- Keyboard Shortcuts (Issue #18) ---
|
|
8083
|
+
var shortcutsOverlay = document.getElementById('shortcuts-overlay');
|
|
8084
|
+
var shortcutsClose = document.getElementById('shortcuts-close');
|
|
8085
|
+
|
|
8086
|
+
function toggleShortcutsOverlay() {
|
|
8087
|
+
shortcutsOverlay.classList.toggle('visible');
|
|
8088
|
+
}
|
|
6778
8089
|
|
|
6779
8090
|
function closeShortcutsOverlay() {
|
|
6780
8091
|
shortcutsOverlay.classList.remove('visible');
|
|
@@ -6803,7 +8114,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
6803
8114
|
// Skip if modifier keys are held (let browser defaults work)
|
|
6804
8115
|
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
6805
8116
|
|
|
6806
|
-
var sections = ['overview', 'insights', 'prd-checklist', 'app-runner', 'council', 'cost', 'checkpoint', 'context', 'notifications'];
|
|
8117
|
+
var sections = ['overview', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'checkpoint', 'context', 'notifications', 'migration'];
|
|
6807
8118
|
|
|
6808
8119
|
switch (e.key) {
|
|
6809
8120
|
// Section navigation: 1-9, 0
|
|
@@ -6816,6 +8127,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
6816
8127
|
switchSection(sections[9]);
|
|
6817
8128
|
break;
|
|
6818
8129
|
|
|
8130
|
+
// Migration page
|
|
8131
|
+
case 'm':
|
|
8132
|
+
e.preventDefault();
|
|
8133
|
+
switchSection('migration');
|
|
8134
|
+
break;
|
|
8135
|
+
|
|
6819
8136
|
// Help overlay
|
|
6820
8137
|
case '?':
|
|
6821
8138
|
e.preventDefault();
|