loki-mode 7.78.0 → 7.80.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/lib/checkpoint_sync.py +189 -0
- package/autonomy/lib/config-map.sh +955 -0
- package/autonomy/loki +273 -8
- package/autonomy/run.sh +230 -195
- package/autonomy/sandbox.sh +98 -0
- package/autonomy/trigger-server.py +419 -43
- package/dashboard/__init__.py +1 -1
- package/dashboard/registry.py +212 -0
- package/dashboard/server.py +299 -7
- package/dashboard/static/index.html +383 -150
- package/docs/CONFIG-FILE-PLAN.md +459 -0
- package/docs/ENTERPRISE-IDENTITY-ROADMAP.md +206 -0
- package/docs/INSTALLATION.md +2 -2
- package/loki-ts/dist/loki.js +2 -2
- package/lokistore/__init__.py +65 -0
- package/lokistore/base.py +172 -0
- package/lokistore/cloud.py +305 -0
- package/lokistore/factory.py +187 -0
- package/lokistore/local.py +219 -0
- package/mcp/__init__.py +1 -1
- package/memory/retrieval.py +147 -0
- package/memory/tree_index.py +499 -0
- package/memory/tree_search.py +305 -0
- package/package.json +2 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
|
@@ -766,6 +766,10 @@
|
|
|
766
766
|
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
|
767
767
|
Overview
|
|
768
768
|
</button>
|
|
769
|
+
<button class="nav-link" data-section="fleet" id="nav-fleet">
|
|
770
|
+
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
|
|
771
|
+
Fleet
|
|
772
|
+
</button>
|
|
769
773
|
<button class="nav-link" data-section="insights" id="nav-insights">
|
|
770
774
|
<svg viewBox="0 0 24 24"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
|
|
771
775
|
Insights
|
|
@@ -854,6 +858,15 @@
|
|
|
854
858
|
</div>
|
|
855
859
|
</div>
|
|
856
860
|
|
|
861
|
+
<!-- Fleet: cross-project build observability (v1 polls the shared
|
|
862
|
+
metadata store; not a controller). -->
|
|
863
|
+
<div class="section-page" id="page-fleet">
|
|
864
|
+
<div class="section-page-header">
|
|
865
|
+
<h2 class="section-page-title">Fleet</h2>
|
|
866
|
+
</div>
|
|
867
|
+
<loki-fleet id="fleet-panel"></loki-fleet>
|
|
868
|
+
</div>
|
|
869
|
+
|
|
857
870
|
<!-- Insights: Logs + Memory + Learning (combined) -->
|
|
858
871
|
<div class="section-page" id="page-insights">
|
|
859
872
|
<div class="section-page-header">
|
|
@@ -1329,7 +1342,7 @@
|
|
|
1329
1342
|
|
|
1330
1343
|
<!-- Inlined JavaScript Bundle -->
|
|
1331
1344
|
<script>
|
|
1332
|
-
var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var nt=Object.prototype.hasOwnProperty;var lt=(c,e,t)=>e in c?Ee(c,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):c[e]=t;var dt=(c,e)=>{for(var t in e)Ee(c,t,{get:e[t],enumerable:!0})},ct=(c,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of ot(e))!nt.call(c,a)&&a!==t&&Ee(c,a,{get:()=>e[a],enumerable:!(i=rt(e,a))||i.enumerable});return c};var pt=c=>ct(Ee({},"__esModule",{value:!0}),c);var C=(c,e,t)=>lt(c,typeof e!="symbol"?e+"":e,t);var jt={};dt(jt,{ANIMATION:()=>I,ARIA_PATTERNS:()=>Ae,ApiEvents:()=>v,BASE_STYLES:()=>U,BREAKPOINTS:()=>Ce,COMMON_STYLES:()=>Fe,KEYBOARD_SHORTCUTS:()=>Se,KeyboardHandler:()=>M,LokiActivityStream:()=>ge,LokiAgentLeaderboard:()=>xe,LokiAnalytics:()=>ne,LokiApiClient:()=>P,LokiApiKeys:()=>he,LokiAppPreview:()=>X,LokiAppStatus:()=>Q,LokiAuditViewer:()=>pe,LokiChecklistViewer:()=>W,LokiCheckpointViewer:()=>ee,LokiContextTracker:()=>te,LokiCostDashboard:()=>Z,LokiCostWaterfall:()=>ke,LokiCouncilDashboard:()=>Y,LokiCouncilTranscripts:()=>we,LokiElement:()=>u,LokiEscalations:()=>ye,LokiLearningDashboard:()=>V,LokiLogStream:()=>G,LokiManagedMemoryPanel:()=>_e,LokiMemoryBrowser:()=>K,LokiMemoryGraph:()=>fe,LokiMigrationDashboard:()=>oe,LokiNotificationCenter:()=>ie,LokiOverview:()=>O,LokiPipelineView:()=>ve,LokiPromptOptimizer:()=>se,LokiProviderHealth:()=>me,LokiQualityGates:()=>le,LokiQualityScore:()=>re,LokiRarvTimeline:()=>de,LokiRunManager:()=>ce,LokiSessionControl:()=>J,LokiSessionDiff:()=>ae,LokiState:()=>N,LokiTaskBoard:()=>q,LokiTenantSwitcher:()=>ue,LokiTheme:()=>R,LokiWikiBrowser:()=>$e,RADIUS:()=>L,SPACING:()=>A,STATE_CHANGE_EVENT:()=>Ie,THEMES:()=>E,THEME_VARIABLES:()=>Te,TYPOGRAPHY:()=>y,UnifiedThemeManager:()=>_,VERSION:()=>Pt,Z_INDEX:()=>D,createApiClient:()=>Ne,createStore:()=>Oe,generateThemeCSS:()=>$,generateTokensCSS:()=>j,getApiClient:()=>g,getState:()=>B,init:()=>Ft});var E={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)"}},A={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},L={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},y={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"}},I={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)"}},Ce={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},D={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Se={"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"]}},Ae={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 $(c){let e=E[c];return e?Object.entries(e).map(([t,i])=>`${t}: ${i};`).join(`
|
|
1345
|
+
var LokiDashboard=(()=>{var Ce=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var dt=Object.getOwnPropertyNames;var ct=Object.prototype.hasOwnProperty;var pt=(d,e,t)=>e in d?Ce(d,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[e]=t;var ht=(d,e)=>{for(var t in e)Ce(d,t,{get:e[t],enumerable:!0})},ut=(d,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of dt(e))!ct.call(d,a)&&a!==t&&Ce(d,a,{get:()=>e[a],enumerable:!(i=lt(e,a))||i.enumerable});return d};var gt=d=>ut(Ce({},"__esModule",{value:!0}),d);var C=(d,e,t)=>pt(d,typeof e!="symbol"?e+"":e,t);var qt={};ht(qt,{ANIMATION:()=>L,ARIA_PATTERNS:()=>Te,ApiEvents:()=>v,BASE_STYLES:()=>U,BREAKPOINTS:()=>Se,COMMON_STYLES:()=>je,KEYBOARD_SHORTCUTS:()=>Ae,KeyboardHandler:()=>M,LokiActivityStream:()=>me,LokiAgentLeaderboard:()=>_e,LokiAnalytics:()=>ne,LokiApiClient:()=>P,LokiApiKeys:()=>ue,LokiAppPreview:()=>X,LokiAppStatus:()=>Q,LokiAuditViewer:()=>he,LokiChecklistViewer:()=>W,LokiCheckpointViewer:()=>ee,LokiContextTracker:()=>te,LokiCostDashboard:()=>Z,LokiCostWaterfall:()=>xe,LokiCouncilDashboard:()=>Y,LokiCouncilTranscripts:()=>$e,LokiElement:()=>u,LokiEscalations:()=>we,LokiFleet:()=>pe,LokiLearningDashboard:()=>V,LokiLogStream:()=>G,LokiManagedMemoryPanel:()=>ye,LokiMemoryBrowser:()=>K,LokiMemoryGraph:()=>ke,LokiMigrationDashboard:()=>oe,LokiNotificationCenter:()=>ie,LokiOverview:()=>O,LokiPipelineView:()=>be,LokiPromptOptimizer:()=>se,LokiProviderHealth:()=>ve,LokiQualityGates:()=>le,LokiQualityScore:()=>re,LokiRarvTimeline:()=>de,LokiRunManager:()=>ce,LokiSessionControl:()=>J,LokiSessionDiff:()=>ae,LokiState:()=>N,LokiTaskBoard:()=>q,LokiTenantSwitcher:()=>ge,LokiTheme:()=>R,LokiWikiBrowser:()=>Ee,RADIUS:()=>I,SPACING:()=>A,STATE_CHANGE_EVENT:()=>De,THEMES:()=>E,THEME_VARIABLES:()=>Ie,TYPOGRAPHY:()=>y,UnifiedThemeManager:()=>_,VERSION:()=>Nt,Z_INDEX:()=>D,createApiClient:()=>Oe,createStore:()=>qe,generateThemeCSS:()=>$,generateTokensCSS:()=>j,getApiClient:()=>g,getState:()=>B,init:()=>Ot});var E={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)"}},A={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},I={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},y={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"}},L={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)"}},Se={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},D={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Ae={"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"]}},Te={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 $(d){let e=E[d];return e?Object.entries(e).map(([t,i])=>`${t}: ${i};`).join(`
|
|
1333
1346
|
`):""}function j(){return`
|
|
1334
1347
|
/* Spacing */
|
|
1335
1348
|
--loki-space-xs: ${A.xs};
|
|
@@ -1341,12 +1354,12 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
1341
1354
|
--loki-space-3xl: ${A["3xl"]};
|
|
1342
1355
|
|
|
1343
1356
|
/* Border Radius */
|
|
1344
|
-
--loki-radius-none: ${
|
|
1345
|
-
--loki-radius-sm: ${
|
|
1346
|
-
--loki-radius-md: ${
|
|
1347
|
-
--loki-radius-lg: ${
|
|
1348
|
-
--loki-radius-xl: ${
|
|
1349
|
-
--loki-radius-full: ${
|
|
1357
|
+
--loki-radius-none: ${I.none};
|
|
1358
|
+
--loki-radius-sm: ${I.sm};
|
|
1359
|
+
--loki-radius-md: ${I.md};
|
|
1360
|
+
--loki-radius-lg: ${I.lg};
|
|
1361
|
+
--loki-radius-xl: ${I.xl};
|
|
1362
|
+
--loki-radius-full: ${I.full};
|
|
1350
1363
|
|
|
1351
1364
|
/* Typography */
|
|
1352
1365
|
--loki-font-sans: ${y.fontFamily.sans};
|
|
@@ -1362,11 +1375,11 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
1362
1375
|
--loki-text-3xl: ${y.fontSize["3xl"]};
|
|
1363
1376
|
|
|
1364
1377
|
/* Animation */
|
|
1365
|
-
--loki-duration-fast: ${
|
|
1366
|
-
--loki-duration-normal: ${
|
|
1367
|
-
--loki-duration-slow: ${
|
|
1368
|
-
--loki-easing-default: ${
|
|
1369
|
-
--loki-transition: ${
|
|
1378
|
+
--loki-duration-fast: ${L.duration.fast};
|
|
1379
|
+
--loki-duration-normal: ${L.duration.normal};
|
|
1380
|
+
--loki-duration-slow: ${L.duration.slow};
|
|
1381
|
+
--loki-easing-default: ${L.easing.default};
|
|
1382
|
+
--loki-transition: ${L.duration.normal} ${L.easing.default};
|
|
1370
1383
|
|
|
1371
1384
|
/* Z-Index */
|
|
1372
1385
|
--loki-z-dropdown: ${D.dropdown};
|
|
@@ -1656,11 +1669,11 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
1656
1669
|
}
|
|
1657
1670
|
|
|
1658
1671
|
/* Responsive utilities */
|
|
1659
|
-
@media (max-width: ${
|
|
1672
|
+
@media (max-width: ${Se.md}) {
|
|
1660
1673
|
.hide-mobile { display: none !important; }
|
|
1661
1674
|
}
|
|
1662
1675
|
|
|
1663
|
-
@media (min-width: ${
|
|
1676
|
+
@media (min-width: ${Se.md}) {
|
|
1664
1677
|
.hide-desktop { display: none !important; }
|
|
1665
1678
|
}
|
|
1666
1679
|
`,k=class k{static detectContext(){return typeof acquireVsCodeApi<"u"||document.body.classList.contains("vscode-body")||getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background")?"vscode":document.documentElement.dataset.lokiContext==="cli"?"cli":"browser"}static detectVSCodeTheme(){let e=document.body;if(e.classList.contains("vscode-high-contrast"))return"high-contrast";if(e.classList.contains("vscode-dark"))return"dark";if(e.classList.contains("vscode-light"))return"light";let t=getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background");if(t){let i=t.match(/\d+/g);if(i)return(parseInt(i[0])*299+parseInt(i[1])*587+parseInt(i[2])*114)/1e3>128?"light":"dark"}return null}static getTheme(){if(k.detectContext()==="vscode"){let i=k.detectVSCodeTheme();return i==="high-contrast"?"high-contrast":i==="dark"?"vscode-dark":"vscode-light"}let t=localStorage.getItem(k.STORAGE_KEY);return t&&E[t]?t:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}static setTheme(e){if(!E[e]){console.warn(`Unknown theme: ${e}`);return}localStorage.setItem(k.STORAGE_KEY,e),document.documentElement.setAttribute("data-loki-theme",e),window.dispatchEvent(new CustomEvent("loki-theme-change",{detail:{theme:e,context:k.detectContext()}}))}static toggle(){let e=k.getTheme(),t;return e.includes("dark")||e==="high-contrast"?t=e.startsWith("vscode")?"vscode-light":"light":t=e.startsWith("vscode")?"vscode-dark":"dark",k.setTheme(t),t}static getVariables(e=null){let t=e||k.getTheme();return E[t]||E.light}static generateCSS(e=null){let t=e||k.getTheme();return`
|
|
@@ -1669,7 +1682,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
1669
1682
|
${j()}
|
|
1670
1683
|
}
|
|
1671
1684
|
${U}
|
|
1672
|
-
`}static init(){let e=k.getTheme();document.documentElement.setAttribute("data-loki-theme",e),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{localStorage.getItem(k.STORAGE_KEY)||k.setTheme(k.getTheme())}),k.detectContext()==="vscode"&&new MutationObserver(()=>{let i=k.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"]})}};C(k,"STORAGE_KEY","loki-theme"),C(k,"CONTEXT_KEY","loki-context");var _=k,M=class{constructor(){this._handlers=new Map,this._enabled=!0}register(e,t){let i=
|
|
1685
|
+
`}static init(){let e=k.getTheme();document.documentElement.setAttribute("data-loki-theme",e),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{localStorage.getItem(k.STORAGE_KEY)||k.setTheme(k.getTheme())}),k.detectContext()==="vscode"&&new MutationObserver(()=>{let i=k.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"]})}};C(k,"STORAGE_KEY","loki-theme"),C(k,"CONTEXT_KEY","loki-context");var _=k,M=class{constructor(){this._handlers=new Map,this._enabled=!0}register(e,t){let i=Ae[e];if(!i){console.warn(`Unknown keyboard action: ${e}`);return}this._handlers.set(e,{shortcut:i,handler:t})}unregister(e){this._handlers.delete(e)}setEnabled(e){this._enabled=e}handleEvent(e){if(!this._enabled)return!1;for(let[t,{shortcut:i,handler:a}]of this._handlers)if(this._matchesShortcut(e,i))return e.preventDefault(),e.stopPropagation(),a(e),!0;return!1}_matchesShortcut(e,t){let i=e.key.toLowerCase(),a=t.modifiers||[];if(i!==t.key.toLowerCase())return!1;let s=a.includes("Ctrl")||a.includes("Meta"),r=a.includes("Shift"),o=a.includes("Alt"),n=(e.ctrlKey||e.metaKey)===s,l=e.shiftKey===r,c=e.altKey===o;return n&&l&&c}attach(e){this._boundHandler||(this._boundHandler=t=>this.handleEvent(t)),e.addEventListener("keydown",this._boundHandler)}detach(e){this._boundHandler&&e.removeEventListener("keydown",this._boundHandler)}};var Ie={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-accent":"#553DE9","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-transition":"0.2s cubic-bezier(0.4, 0, 0.2, 1)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-accent":"#7B6BF0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-transition":"0.2s cubic-bezier(0.4, 0, 0.2, 1)"}},je=`
|
|
1673
1686
|
:host {
|
|
1674
1687
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
1675
1688
|
line-height: 1.5;
|
|
@@ -1765,7 +1778,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
1765
1778
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary); }
|
|
1766
1779
|
::-webkit-scrollbar-thumb { background: var(--loki-border); border-radius: 3px; }
|
|
1767
1780
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light); }
|
|
1768
|
-
`,H=class H{static getTheme(){return _.getTheme()}static setTheme(e){_.setTheme(e)}static toggle(){return _.toggle()}static getVariables(e=null){let t=e||H.getTheme();return E[t]||
|
|
1781
|
+
`,H=class H{static getTheme(){return _.getTheme()}static setTheme(e){_.setTheme(e)}static toggle(){return _.toggle()}static getVariables(e=null){let t=e||H.getTheme();return E[t]||Ie[t]||Ie.light}static toCSSString(e=null){let t=e||H.getTheme();if(E[t])return $(t);let i=H.getVariables(t);return Object.entries(i).map(([a,s])=>`${a}: ${s};`).join(`
|
|
1769
1782
|
`)}static applyToElement(e,t=null){let i=H.getVariables(t);for(let[a,s]of Object.entries(i))e.style.setProperty(a,s)}static init(){_.init()}static detectContext(){return _.detectContext()}static getAvailableThemes(){return Object.keys(E)}};C(H,"STORAGE_KEY","loki-theme");var R=H,u=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._theme=R.getTheme(),this._themeChangeHandler=this._onThemeChange.bind(this),this._keyboardHandler=new M}connectedCallback(){window.addEventListener("loki-theme-change",this._themeChangeHandler),this._applyTheme(),this._setupKeyboardHandling(),this.render()}disconnectedCallback(){window.removeEventListener("loki-theme-change",this._themeChangeHandler),this._keyboardHandler.detach(this)}_onThemeChange(e){this._theme=e.detail.theme,this._applyTheme(),this.onThemeChange&&this.onThemeChange(this._theme)}_applyTheme(){R.applyToElement(this.shadowRoot.host,this._theme),this.setAttribute("data-loki-theme",this._theme)}_setupKeyboardHandling(){this._keyboardHandler.attach(this)}registerShortcut(e,t){this._keyboardHandler.register(e,t)}getBaseStyles(){return`
|
|
1770
1783
|
/* Design tokens */
|
|
1771
1784
|
:host {
|
|
@@ -1822,7 +1835,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
1822
1835
|
}
|
|
1823
1836
|
|
|
1824
1837
|
${U}
|
|
1825
|
-
`}getAriaPattern(e){return Ae[e]||{}}applyAriaPattern(e,t){let i=this.getAriaPattern(t);for(let[a,s]of Object.entries(i))if(a==="role")e.setAttribute("role",s);else{let r=a.replace(/([A-Z])/g,"-$1").toLowerCase();e.setAttribute(r,s)}}render(){}};var z={realtime:1e3,normal:2e3,background:5e3,offline:1e4},je={vscode:z.normal,browser:z.realtime,cli:z.background},Ue={baseUrl:typeof window<"u"?window.location.origin:"http://localhost:57374",wsUrl:typeof window<"u"?`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws`:"ws://localhost:57374/ws",pollInterval:2e3,timeout:1e4,retryAttempts:3,retryDelay:1e3},v={CONNECTED:"api:connected",DISCONNECTED:"api:disconnected",ERROR:"api:error",STATUS_UPDATE:"api:status-update",TASK_CREATED:"api:task-created",TASK_UPDATED:"api:task-updated",TASK_DELETED:"api:task-deleted",PROJECT_CREATED:"api:project-created",PROJECT_UPDATED:"api:project-updated",AGENT_UPDATE:"api:agent-update",LOG_MESSAGE:"api:log-message",MEMORY_UPDATE:"api:memory-update",CHECKLIST_UPDATE:"api:checklist-update"},T=class T extends EventTarget{static getInstance(e={}){let t=e.baseUrl||Ue.baseUrl;return T._instances.has(t)||T._instances.set(t,new T(e)),T._instances.get(t)}static clearInstances(){T._instances.forEach(e=>e.disconnect()),T._instances.clear()}constructor(e={}){super(),this.config={...Ue,...e},this._ws=null,this._connected=!1,this._pollInterval=null,this._reconnectTimeout=null,this._reconnectAttempts=0,this._maxReconnectAttempts=20,this._cache=new Map,this._cacheTimeout=5e3,this._vscodeApi=null,this._context=this._detectContext(),this._currentPollInterval=je[this._context]||z.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 z}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(z.background):this._setPollInterval(je[this._context]||z.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(e){this._currentPollInterval=e,this._pollInterval&&(this.stopPolling(),this.startPolling(null,e))}setPollMode(e){let t=z[e];t&&this._setPollInterval(t)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=e=>{let t=e.data;if(!(!t||!t.type))switch(t.type){case"updateStatus":this._emit(v.STATUS_UPDATE,t.data);break;case"updateTasks":this._emit(v.TASK_UPDATED,t.data);break;case"taskCreated":this._emit(v.TASK_CREATED,t.data);break;case"taskDeleted":this._emit(v.TASK_DELETED,t.data);break;case"projectCreated":this._emit(v.PROJECT_CREATED,t.data);break;case"projectUpdated":this._emit(v.PROJECT_UPDATED,t.data);break;case"agentUpdate":this._emit(v.AGENT_UPDATE,t.data);break;case"logMessage":this._emit(v.LOG_MESSAGE,t.data);break;case"memoryUpdate":this._emit(v.MEMORY_UPDATE,t.data);break;case"connected":this._connected=!0,this._emit(v.CONNECTED,t.data);break;case"disconnected":this._connected=!1,this._emit(v.DISCONNECTED,t.data);break;case"error":this._emit(v.ERROR,t.data);break;case"setPollMode":this.setPollMode(t.data.mode);break;default:this._emit(`api:${t.type}`,t.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(e,t={}){this._vscodeApi&&this._vscodeApi.postMessage({type:e,data:t})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(e,t={}){this.postToVSCode("userAction",{action:e,...t})}get baseUrl(){return this.config.baseUrl}set baseUrl(e){this.config.baseUrl=e,this.config.wsUrl=e.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((e,t)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._reconnectAttempts=0,this._emit(v.CONNECTED),e()},this._ws.onclose=()=>{this._connected=!1,this._emit(v.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=i=>{this._emit(v.ERROR,{error:i}),t(i)},this._ws.onmessage=i=>{try{let a=JSON.parse(i.data);this._handleMessage(a)}catch(a){console.error("Failed to parse WebSocket message:",a)}}}catch(i){t(i)}})}disconnect(){this._ws&&(this._ws.close(),this._ws=null),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._reconnectTimeout&&(clearTimeout(this._reconnectTimeout),this._reconnectTimeout=null),this._connected=!1,this._cleanupGlobalListeners()}_cleanupGlobalListeners(){this._visibilityChangeHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this._visibilityChangeHandler),this._visibilityChangeHandler=null),this._messageHandler&&typeof window<"u"&&(window.removeEventListener("message",this._messageHandler),this._messageHandler=null)}destroy(){this.disconnect()}_scheduleReconnect(){if(this._reconnectTimeout)return;if(this._reconnectAttempts>=this._maxReconnectAttempts){console.warn("WebSocket max reconnect attempts reached, giving up"),this._emit(v.ERROR,{error:"Max reconnect attempts reached"});return}let e=Math.min(this.config.retryDelay*Math.pow(2,this._reconnectAttempts),3e4);this._reconnectAttempts++,this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},e)}_handleMessage(e){if(e.type==="ping"){this._ws&&this._ws.readyState===WebSocket.OPEN&&this._ws.send(JSON.stringify({type:"pong"}));return}let i={connected:v.CONNECTED,status_update:v.STATUS_UPDATE,task_created:v.TASK_CREATED,task_updated:v.TASK_UPDATED,task_deleted:v.TASK_DELETED,task_moved:v.TASK_UPDATED,project_created:v.PROJECT_CREATED,project_updated:v.PROJECT_UPDATED,agent_update:v.AGENT_UPDATE,log:v.LOG_MESSAGE}[e.type]||`api:${e.type}`;this._emit(i,e.data)}_emit(e,t={}){this.dispatchEvent(new CustomEvent(e,{detail:t}))}async _request(e,t={}){let i=`${this.config.baseUrl}${e}`,a=new AbortController,s=t&&typeof t.timeout=="number"?t.timeout:this.config.timeout,r=setTimeout(()=>a.abort(),s);try{let o=await fetch(i,{...t,signal:a.signal,credentials:"include",headers:{"Content-Type":"application/json",...t.headers}});if(clearTimeout(r),!o.ok){let n=await o.text().catch(()=>""),l=o.statusText||`HTTP ${o.status}`;if(n)try{let d=JSON.parse(n);l=d.detail||d.error||d.message||l}catch{l=n.length>200?n.slice(0,200)+"...":n}throw new Error(l)}return o.status===204?null:await o.json()}catch(o){throw clearTimeout(r),o.name==="AbortError"?new Error("Request timeout"):o}}async _get(e,t=!1){if(t&&this._cache.has(e)){let a=this._cache.get(e);if(Date.now()-a.timestamp<this._cacheTimeout)return a.data}let i=await this._request(e);return t&&this._cache.set(e,{data:i,timestamp:Date.now()}),i}async _post(e,t,i={}){return this._request(e,{method:"POST",body:JSON.stringify(t),...i})}async _put(e,t){return this._request(e,{method:"PUT",body:JSON.stringify(t)})}async _delete(e){return this._request(e,{method:"DELETE"})}async get(e){return this._get(e)}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(e=null){let t=e?`?status=${e}`:"";return this._get(`/api/projects${t}`)}async getProject(e){return this._get(`/api/projects/${e}`)}async createProject(e){return this._post("/api/projects",e)}async updateProject(e,t){return this._put(`/api/projects/${e}`,t)}async deleteProject(e){return this._delete(`/api/projects/${e}`)}async listTasks(e={}){let t=new URLSearchParams;e.projectId&&t.append("project_id",e.projectId),e.status&&t.append("status",e.status),e.priority&&t.append("priority",e.priority);let i=t.toString()?`?${t}`:"";return this._get(`/api/tasks${i}`)}async getTask(e){return this._get(`/api/tasks/${e}`)}async createTask(e){return this._post("/api/tasks",e)}async updateTask(e,t){return this._put(`/api/tasks/${e}`,t)}async moveTask(e,t,i){return this._post(`/api/tasks/${e}/move`,{status:t,position:i})}async deleteTask(e){return this._delete(`/api/tasks/${e}`)}async getMemorySummary(){return this._get("/api/memory/summary",!0)}async getMemoryIndex(){return this._get("/api/memory/index",!0)}async getMemoryTimeline(){return this._get("/api/memory/timeline")}async listEpisodes(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/episodes${t?"?"+t:""}`)}async getEpisode(e){return this._get(`/api/memory/episodes/${e}`)}async listPatterns(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/patterns${t?"?"+t:""}`)}async getPattern(e){return this._get(`/api/memory/patterns/${e}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(e){return this._get(`/api/memory/skills/${e}`)}async retrieveMemories(e,t=null,i=5){return this._post("/api/memory/retrieve",{query:e,taskType:t,topK:i},{timeout:3e4})}async consolidateMemory(e=24){return this._post("/api/memory/consolidate",{sinceHours:e},{timeout:12e4})}async getTokenEconomics(){return this._get("/api/memory/economics")}async searchMemory(e,t="all",i=20){let a=new URLSearchParams({q:e,collection:t,limit:String(i)});return this._get(`/api/memory/search?${a}`)}async getMemoryStats(){return this._get("/api/memory/stats",!0)}async listRegisteredProjects(e=!1){return this._get(`/api/registry/projects?include_inactive=${e}`)}async registerProject(e,t=null,i=null){return this._post("/api/registry/projects",{path:e,name:t,alias:i})}async discoverProjects(e=3){return this._get(`/api/registry/discover?max_depth=${e}`)}async syncRegistry(){return this._post("/api/registry/sync",{},{timeout:45e3})}async getCrossProjectTasks(e=null){let t=e?`?project_ids=${e.join(",")}`:"";return this._get(`/api/registry/tasks${t}`)}async getLearningMetrics(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/metrics${i}`)}async getLearningTrends(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/trends${i}`)}async getLearningSignals(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source),e.limit&&t.append("limit",String(e.limit)),e.offset&&t.append("offset",String(e.offset));let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/signals${i}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(e={}){return this._post("/api/learning/aggregate",e,{timeout:6e4})}async getAggregatedPreferences(e=20){return this._get(`/api/learning/preferences?limit=${e}`)}async getAggregatedErrors(e=20){return this._get(`/api/learning/errors?limit=${e}`)}async getAggregatedSuccessPatterns(e=20){return this._get(`/api/learning/success?limit=${e}`)}async getToolEfficiency(e=20){return this._get(`/api/learning/tools?limit=${e}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(e=20){return this._get(`/api/council/verdicts?limit=${e}`)}async getCouncilConvergence(){return this._get("/api/council/convergence")}async getCouncilReport(){return this._get("/api/council/report")}async forceCouncilReview(){return this._post("/api/council/force-review",{})}async getContext(){return this._get("/api/context")}async getNotifications(e,t){let i=new URLSearchParams;e&&i.set("severity",e),t&&i.set("unread_only","true");let a=i.toString();return this._get("/api/notifications"+(a?"?"+a:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(e){return this._put("/api/notifications/triggers",{triggers:e})}async acknowledgeNotification(e){return this._post("/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{})}async startSession(e,t={}){let i={provider:t.provider||"claude",parallel:!!t.parallel};return t.prdPath?i.prd_path=t.prdPath:i.prd_text=e||"",this._post("/api/control/start",i)}async pauseSession(){return this._post("/api/control/pause",{})}async resumeSession(){return this._post("/api/control/resume",{})}async stopSession(){return this._post("/api/control/stop",{})}async getSessionModel(){return this._get("/api/session/model")}async setSessionModel(e){return this._post("/api/session/model",{model:e||null})}async getLogs(e=100){return this._get(`/api/logs?lines=${e}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let e=await fetch(`${this.baseUrl}/api/prd-observations`,{credentials:"include"});if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(e,t,i="dashboard"){return this._post("/api/checklist/waivers",{item_id:e,reason:t,waived_by:i})}async removeChecklistWaiver(e){return this._delete(`/api/checklist/waivers/${encodeURIComponent(e)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(e=100){return this._get(`/api/app-runner/logs?lines=${e}`)}async getAppRunnerErrors(e=50){return this._get(`/api/app-runner/errors?lines=${e}`)}async restartApp(){return this._post("/api/control/app-restart",{})}async stopApp(){return this._post("/api/control/app-stop",{})}async getPlaywrightResults(){return this._get("/api/playwright/results")}async getPlaywrightScreenshot(){return this._get("/api/playwright/screenshot")}startPolling(e,t=null){if(this._pollInterval)return;this._pollCallback=e;let i=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(v.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(v.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};i();let a=t||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(i,a)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};C(T,"_instances",new Map);var P=T;function Ne(c={}){return new P(c)}function g(c={}){return P.getInstance(c)}var Ie="loki-state-change",Le={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}},S=class S extends EventTarget{static getInstance(){return S._instance||(S._instance=new S),S._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let e=localStorage.getItem(S.STORAGE_KEY);if(e){let t=JSON.parse(e);return this._mergeState(Le,t)}}catch(e){console.warn("Failed to load state from localStorage:",e)}return{...Le}}_mergeState(e,t){let i={...e};for(let a of Object.keys(t))a in e&&typeof e[a]=="object"&&!Array.isArray(e[a])?i[a]=this._mergeState(e[a],t[a]):i[a]=t[a];return i}_saveState(){try{let e={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(S.STORAGE_KEY,JSON.stringify(e))}catch(e){console.warn("Failed to save state to localStorage:",e)}}get(e=null){if(!e)return{...this._state};let t=e.split("."),i=this._state;for(let a of t){if(i==null)return;i=i[a]}return i}set(e,t,i=!0){let a=e.split("."),s=a.pop(),r=this._state;for(let n of a)n in r||(r[n]={}),r=r[n];let o=r[s];r[s]=t,i&&this._saveState(),this._notifyChange(e,t,o)}update(e,t=!0){let i=[];for(let[a,s]of Object.entries(e)){let r=this.get(a);this.set(a,s,!1),i.push({path:a,value:s,oldValue:r})}t&&this._saveState();for(let a of i)this._notifyChange(a.path,a.value,a.oldValue)}_notifyChange(e,t,i){this.dispatchEvent(new CustomEvent(Ie,{detail:{path:e,value:t,oldValue:i}}));let a=this._subscribers.get(e)||[];for(let r of a)try{r(t,i,e)}catch(o){console.error("State subscriber error:",o)}let s=e.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let n of o)try{n(this.get(r),null,r)}catch(l){console.error("State subscriber error:",l)}}}subscribe(e,t){return this._subscribers.has(e)||this._subscribers.set(e,[]),this._subscribers.get(e).push(t),()=>{let i=this._subscribers.get(e),a=i.indexOf(t);a>-1&&i.splice(a,1)}}reset(e=null){if(e){let t=e.split("."),i=Le;for(let a of t)i=i?.[a];this.set(e,i)}else this._state={...Le},this._saveState(),this.dispatchEvent(new CustomEvent(Ie,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(e){let t=this.get("localTasks")||[],i={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...e};return this.set("localTasks",[...t,i]),i}updateLocalTask(e,t){let i=this.get("localTasks")||[],a=i.findIndex(r=>r.id===e);if(a===-1)return null;let s={...i[a],...t,updatedAt:new Date().toISOString()};return i[a]=s,this.set("localTasks",[...i]),s}deleteLocalTask(e){let t=this.get("localTasks")||[];this.set("localTasks",t.filter(i=>i.id!==e))}moveLocalTask(e,t,i=null){let s=(this.get("localTasks")||[]).find(r=>r.id===e);return s?this.updateLocalTask(e,{status:t,position:i??s.position}):null}updateSession(e){this.update(Object.fromEntries(Object.entries(e).map(([t,i])=>[`session.${t}`,i])),!1)}updateCache(e){this.update({"cache.projects":e.projects??this.get("cache.projects"),"cache.tasks":e.tasks??this.get("cache.tasks"),"cache.agents":e.agents??this.get("cache.agents"),"cache.memory":e.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let e=this.get("cache.tasks")||[],i=(this.get("localTasks")||[]).map(a=>({...a,isLocal:!0}));return[...e,...i]}getTasksByStatus(e){return this.getMergedTasks().filter(t=>t.status===e)}};C(S,"STORAGE_KEY","loki-dashboard-state"),C(S,"_instance",null);var N=S;function B(){return N.getInstance()}function Oe(c){let e=B();return{get:()=>e.get(c),set:t=>e.set(c,t),subscribe:t=>e.subscribe(c,t)}}var O=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data={status:"offline",phase:null,iteration:null,provider:null,running_agents:0,pending_tasks:null,uptime_seconds:0,complexity:null,connected:!1},this._api=null,this._pollInterval=null,this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null,this._checklistSummary=null,this._appRunnerStatus=null,this._playwrightResults=null,this._gateStatus=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._startPolling(),this._api.connect().catch(()=>{})}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._loadAbortController&&(this._loadAbortController.abort(),this._loadAbortController=null),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(v.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(v.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(v.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e}),this._statusUpdateHandler=t=>this._updateFromStatus(t.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(v.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(v.CONNECTED,this._connectedHandler),this._api.addEventListener(v.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){this._loadAbortController&&this._loadAbortController.abort(),this._loadAbortController=new AbortController;let{signal:e}=this._loadAbortController;try{let[t,i,a,s,r]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);if(e.aborted)return;t.status==="fulfilled"?this._updateFromStatus(t.value):(this._data.connected=!1,this._data.status="offline"),i.status==="fulfilled"&&(this._checklistSummary=i.value?.summary||null),a.status==="fulfilled"&&(this._appRunnerStatus=a.value),s.status==="fulfilled"&&(this._playwrightResults=s.value),r.status==="fulfilled"&&(this._gateStatus=r.value),this.render()}catch{if(e.aborted)return;this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(e){e&&(this._data={...this._data,connected:!0,status:e.status||"offline",phase:e.phase||null,iteration:e.iteration!=null?e.iteration:null,provider:e.provider||null,running_agents:e.running_agents||0,pending_tasks:e.pending_tasks!=null?e.pending_tasks:null,uptime_seconds:e.uptime_seconds||0,complexity:e.complexity||null})}_startPolling(){this._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(e){if(!e||e<0)return"--";let t=Math.floor(e/3600),i=Math.floor(e%3600/60),a=Math.floor(e%60);return t>0?`${t}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_getStatusDotClass(){switch(this._data.status){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let e=this._appRunnerStatus;if(!e||e.status==="not_initialized")return`
|
|
1838
|
+
`}getAriaPattern(e){return Te[e]||{}}applyAriaPattern(e,t){let i=this.getAriaPattern(t);for(let[a,s]of Object.entries(i))if(a==="role")e.setAttribute("role",s);else{let r=a.replace(/([A-Z])/g,"-$1").toLowerCase();e.setAttribute(r,s)}}render(){}};var z={realtime:1e3,normal:2e3,background:5e3,offline:1e4},Ue={vscode:z.normal,browser:z.realtime,cli:z.background},Ne={baseUrl:typeof window<"u"?window.location.origin:"http://localhost:57374",wsUrl:typeof window<"u"?`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws`:"ws://localhost:57374/ws",pollInterval:2e3,timeout:1e4,retryAttempts:3,retryDelay:1e3},v={CONNECTED:"api:connected",DISCONNECTED:"api:disconnected",ERROR:"api:error",STATUS_UPDATE:"api:status-update",TASK_CREATED:"api:task-created",TASK_UPDATED:"api:task-updated",TASK_DELETED:"api:task-deleted",PROJECT_CREATED:"api:project-created",PROJECT_UPDATED:"api:project-updated",AGENT_UPDATE:"api:agent-update",LOG_MESSAGE:"api:log-message",MEMORY_UPDATE:"api:memory-update",CHECKLIST_UPDATE:"api:checklist-update"},T=class T extends EventTarget{static getInstance(e={}){let t=e.baseUrl||Ne.baseUrl;return T._instances.has(t)||T._instances.set(t,new T(e)),T._instances.get(t)}static clearInstances(){T._instances.forEach(e=>e.disconnect()),T._instances.clear()}constructor(e={}){super(),this.config={...Ne,...e},this._ws=null,this._connected=!1,this._pollInterval=null,this._reconnectTimeout=null,this._reconnectAttempts=0,this._maxReconnectAttempts=20,this._cache=new Map,this._cacheTimeout=5e3,this._vscodeApi=null,this._context=this._detectContext(),this._currentPollInterval=Ue[this._context]||z.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 z}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(z.background):this._setPollInterval(Ue[this._context]||z.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(e){this._currentPollInterval=e,this._pollInterval&&(this.stopPolling(),this.startPolling(null,e))}setPollMode(e){let t=z[e];t&&this._setPollInterval(t)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=e=>{let t=e.data;if(!(!t||!t.type))switch(t.type){case"updateStatus":this._emit(v.STATUS_UPDATE,t.data);break;case"updateTasks":this._emit(v.TASK_UPDATED,t.data);break;case"taskCreated":this._emit(v.TASK_CREATED,t.data);break;case"taskDeleted":this._emit(v.TASK_DELETED,t.data);break;case"projectCreated":this._emit(v.PROJECT_CREATED,t.data);break;case"projectUpdated":this._emit(v.PROJECT_UPDATED,t.data);break;case"agentUpdate":this._emit(v.AGENT_UPDATE,t.data);break;case"logMessage":this._emit(v.LOG_MESSAGE,t.data);break;case"memoryUpdate":this._emit(v.MEMORY_UPDATE,t.data);break;case"connected":this._connected=!0,this._emit(v.CONNECTED,t.data);break;case"disconnected":this._connected=!1,this._emit(v.DISCONNECTED,t.data);break;case"error":this._emit(v.ERROR,t.data);break;case"setPollMode":this.setPollMode(t.data.mode);break;default:this._emit(`api:${t.type}`,t.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(e,t={}){this._vscodeApi&&this._vscodeApi.postMessage({type:e,data:t})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(e,t={}){this.postToVSCode("userAction",{action:e,...t})}get baseUrl(){return this.config.baseUrl}set baseUrl(e){this.config.baseUrl=e,this.config.wsUrl=e.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((e,t)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._reconnectAttempts=0,this._emit(v.CONNECTED),e()},this._ws.onclose=()=>{this._connected=!1,this._emit(v.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=i=>{this._emit(v.ERROR,{error:i}),t(i)},this._ws.onmessage=i=>{try{let a=JSON.parse(i.data);this._handleMessage(a)}catch(a){console.error("Failed to parse WebSocket message:",a)}}}catch(i){t(i)}})}disconnect(){this._ws&&(this._ws.close(),this._ws=null),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._reconnectTimeout&&(clearTimeout(this._reconnectTimeout),this._reconnectTimeout=null),this._connected=!1,this._cleanupGlobalListeners()}_cleanupGlobalListeners(){this._visibilityChangeHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this._visibilityChangeHandler),this._visibilityChangeHandler=null),this._messageHandler&&typeof window<"u"&&(window.removeEventListener("message",this._messageHandler),this._messageHandler=null)}destroy(){this.disconnect()}_scheduleReconnect(){if(this._reconnectTimeout)return;if(this._reconnectAttempts>=this._maxReconnectAttempts){console.warn("WebSocket max reconnect attempts reached, giving up"),this._emit(v.ERROR,{error:"Max reconnect attempts reached"});return}let e=Math.min(this.config.retryDelay*Math.pow(2,this._reconnectAttempts),3e4);this._reconnectAttempts++,this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},e)}_handleMessage(e){if(e.type==="ping"){this._ws&&this._ws.readyState===WebSocket.OPEN&&this._ws.send(JSON.stringify({type:"pong"}));return}let i={connected:v.CONNECTED,status_update:v.STATUS_UPDATE,task_created:v.TASK_CREATED,task_updated:v.TASK_UPDATED,task_deleted:v.TASK_DELETED,task_moved:v.TASK_UPDATED,project_created:v.PROJECT_CREATED,project_updated:v.PROJECT_UPDATED,agent_update:v.AGENT_UPDATE,log:v.LOG_MESSAGE}[e.type]||`api:${e.type}`;this._emit(i,e.data)}_emit(e,t={}){this.dispatchEvent(new CustomEvent(e,{detail:t}))}async _request(e,t={}){let i=`${this.config.baseUrl}${e}`,a=new AbortController,s=t&&typeof t.timeout=="number"?t.timeout:this.config.timeout,r=setTimeout(()=>a.abort(),s);try{let o=await fetch(i,{...t,signal:a.signal,credentials:"include",headers:{"Content-Type":"application/json",...t.headers}});if(clearTimeout(r),!o.ok){let n=await o.text().catch(()=>""),l=o.statusText||`HTTP ${o.status}`;if(n)try{let c=JSON.parse(n);l=c.detail||c.error||c.message||l}catch{l=n.length>200?n.slice(0,200)+"...":n}throw new Error(l)}return o.status===204?null:await o.json()}catch(o){throw clearTimeout(r),o.name==="AbortError"?new Error("Request timeout"):o}}async _get(e,t=!1){if(t&&this._cache.has(e)){let a=this._cache.get(e);if(Date.now()-a.timestamp<this._cacheTimeout)return a.data}let i=await this._request(e);return t&&this._cache.set(e,{data:i,timestamp:Date.now()}),i}async _post(e,t,i={}){return this._request(e,{method:"POST",body:JSON.stringify(t),...i})}async _put(e,t){return this._request(e,{method:"PUT",body:JSON.stringify(t)})}async _delete(e){return this._request(e,{method:"DELETE"})}async get(e){return this._get(e)}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(e=null){let t=e?`?status=${e}`:"";return this._get(`/api/projects${t}`)}async getProject(e){return this._get(`/api/projects/${e}`)}async createProject(e){return this._post("/api/projects",e)}async updateProject(e,t){return this._put(`/api/projects/${e}`,t)}async deleteProject(e){return this._delete(`/api/projects/${e}`)}async listTasks(e={}){let t=new URLSearchParams;e.projectId&&t.append("project_id",e.projectId),e.status&&t.append("status",e.status),e.priority&&t.append("priority",e.priority);let i=t.toString()?`?${t}`:"";return this._get(`/api/tasks${i}`)}async getTask(e){return this._get(`/api/tasks/${e}`)}async createTask(e){return this._post("/api/tasks",e)}async updateTask(e,t){return this._put(`/api/tasks/${e}`,t)}async moveTask(e,t,i){return this._post(`/api/tasks/${e}/move`,{status:t,position:i})}async deleteTask(e){return this._delete(`/api/tasks/${e}`)}async getMemorySummary(){return this._get("/api/memory/summary",!0)}async getMemoryIndex(){return this._get("/api/memory/index",!0)}async getMemoryTimeline(){return this._get("/api/memory/timeline")}async listEpisodes(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/episodes${t?"?"+t:""}`)}async getEpisode(e){return this._get(`/api/memory/episodes/${e}`)}async listPatterns(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/patterns${t?"?"+t:""}`)}async getPattern(e){return this._get(`/api/memory/patterns/${e}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(e){return this._get(`/api/memory/skills/${e}`)}async retrieveMemories(e,t=null,i=5){return this._post("/api/memory/retrieve",{query:e,taskType:t,topK:i},{timeout:3e4})}async consolidateMemory(e=24){return this._post("/api/memory/consolidate",{sinceHours:e},{timeout:12e4})}async getTokenEconomics(){return this._get("/api/memory/economics")}async searchMemory(e,t="all",i=20){let a=new URLSearchParams({q:e,collection:t,limit:String(i)});return this._get(`/api/memory/search?${a}`)}async getMemoryStats(){return this._get("/api/memory/stats",!0)}async listRegisteredProjects(e=!1){return this._get(`/api/registry/projects?include_inactive=${e}`)}async registerProject(e,t=null,i=null){return this._post("/api/registry/projects",{path:e,name:t,alias:i})}async discoverProjects(e=3){return this._get(`/api/registry/discover?max_depth=${e}`)}async syncRegistry(){return this._post("/api/registry/sync",{},{timeout:45e3})}async getCrossProjectTasks(e=null){let t=e?`?project_ids=${e.join(",")}`:"";return this._get(`/api/registry/tasks${t}`)}async getLearningMetrics(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/metrics${i}`)}async getLearningTrends(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/trends${i}`)}async getLearningSignals(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source),e.limit&&t.append("limit",String(e.limit)),e.offset&&t.append("offset",String(e.offset));let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/signals${i}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(e={}){return this._post("/api/learning/aggregate",e,{timeout:6e4})}async getAggregatedPreferences(e=20){return this._get(`/api/learning/preferences?limit=${e}`)}async getAggregatedErrors(e=20){return this._get(`/api/learning/errors?limit=${e}`)}async getAggregatedSuccessPatterns(e=20){return this._get(`/api/learning/success?limit=${e}`)}async getToolEfficiency(e=20){return this._get(`/api/learning/tools?limit=${e}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(e=20){return this._get(`/api/council/verdicts?limit=${e}`)}async getCouncilConvergence(){return this._get("/api/council/convergence")}async getCouncilReport(){return this._get("/api/council/report")}async forceCouncilReview(){return this._post("/api/council/force-review",{})}async getContext(){return this._get("/api/context")}async getNotifications(e,t){let i=new URLSearchParams;e&&i.set("severity",e),t&&i.set("unread_only","true");let a=i.toString();return this._get("/api/notifications"+(a?"?"+a:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(e){return this._put("/api/notifications/triggers",{triggers:e})}async acknowledgeNotification(e){return this._post("/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{})}async startSession(e,t={}){let i={provider:t.provider||"claude",parallel:!!t.parallel};return t.prdPath?i.prd_path=t.prdPath:i.prd_text=e||"",this._post("/api/control/start",i)}async pauseSession(){return this._post("/api/control/pause",{})}async resumeSession(){return this._post("/api/control/resume",{})}async stopSession(){return this._post("/api/control/stop",{})}async getSessionModel(){return this._get("/api/session/model")}async setSessionModel(e){return this._post("/api/session/model",{model:e||null})}async getLogs(e=100){return this._get(`/api/logs?lines=${e}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let e=await fetch(`${this.baseUrl}/api/prd-observations`,{credentials:"include"});if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(e,t,i="dashboard"){return this._post("/api/checklist/waivers",{item_id:e,reason:t,waived_by:i})}async removeChecklistWaiver(e){return this._delete(`/api/checklist/waivers/${encodeURIComponent(e)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(e=100){return this._get(`/api/app-runner/logs?lines=${e}`)}async getAppRunnerErrors(e=50){return this._get(`/api/app-runner/errors?lines=${e}`)}async restartApp(){return this._post("/api/control/app-restart",{})}async stopApp(){return this._post("/api/control/app-stop",{})}async getPlaywrightResults(){return this._get("/api/playwright/results")}async getPlaywrightScreenshot(){return this._get("/api/playwright/screenshot")}startPolling(e,t=null){if(this._pollInterval)return;this._pollCallback=e;let i=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(v.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(v.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};i();let a=t||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(i,a)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};C(T,"_instances",new Map);var P=T;function Oe(d={}){return new P(d)}function g(d={}){return P.getInstance(d)}var De="loki-state-change",Le={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}},S=class S extends EventTarget{static getInstance(){return S._instance||(S._instance=new S),S._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let e=localStorage.getItem(S.STORAGE_KEY);if(e){let t=JSON.parse(e);return this._mergeState(Le,t)}}catch(e){console.warn("Failed to load state from localStorage:",e)}return{...Le}}_mergeState(e,t){let i={...e};for(let a of Object.keys(t))a in e&&typeof e[a]=="object"&&!Array.isArray(e[a])?i[a]=this._mergeState(e[a],t[a]):i[a]=t[a];return i}_saveState(){try{let e={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(S.STORAGE_KEY,JSON.stringify(e))}catch(e){console.warn("Failed to save state to localStorage:",e)}}get(e=null){if(!e)return{...this._state};let t=e.split("."),i=this._state;for(let a of t){if(i==null)return;i=i[a]}return i}set(e,t,i=!0){let a=e.split("."),s=a.pop(),r=this._state;for(let n of a)n in r||(r[n]={}),r=r[n];let o=r[s];r[s]=t,i&&this._saveState(),this._notifyChange(e,t,o)}update(e,t=!0){let i=[];for(let[a,s]of Object.entries(e)){let r=this.get(a);this.set(a,s,!1),i.push({path:a,value:s,oldValue:r})}t&&this._saveState();for(let a of i)this._notifyChange(a.path,a.value,a.oldValue)}_notifyChange(e,t,i){this.dispatchEvent(new CustomEvent(De,{detail:{path:e,value:t,oldValue:i}}));let a=this._subscribers.get(e)||[];for(let r of a)try{r(t,i,e)}catch(o){console.error("State subscriber error:",o)}let s=e.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let n of o)try{n(this.get(r),null,r)}catch(l){console.error("State subscriber error:",l)}}}subscribe(e,t){return this._subscribers.has(e)||this._subscribers.set(e,[]),this._subscribers.get(e).push(t),()=>{let i=this._subscribers.get(e),a=i.indexOf(t);a>-1&&i.splice(a,1)}}reset(e=null){if(e){let t=e.split("."),i=Le;for(let a of t)i=i?.[a];this.set(e,i)}else this._state={...Le},this._saveState(),this.dispatchEvent(new CustomEvent(De,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(e){let t=this.get("localTasks")||[],i={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...e};return this.set("localTasks",[...t,i]),i}updateLocalTask(e,t){let i=this.get("localTasks")||[],a=i.findIndex(r=>r.id===e);if(a===-1)return null;let s={...i[a],...t,updatedAt:new Date().toISOString()};return i[a]=s,this.set("localTasks",[...i]),s}deleteLocalTask(e){let t=this.get("localTasks")||[];this.set("localTasks",t.filter(i=>i.id!==e))}moveLocalTask(e,t,i=null){let s=(this.get("localTasks")||[]).find(r=>r.id===e);return s?this.updateLocalTask(e,{status:t,position:i??s.position}):null}updateSession(e){this.update(Object.fromEntries(Object.entries(e).map(([t,i])=>[`session.${t}`,i])),!1)}updateCache(e){this.update({"cache.projects":e.projects??this.get("cache.projects"),"cache.tasks":e.tasks??this.get("cache.tasks"),"cache.agents":e.agents??this.get("cache.agents"),"cache.memory":e.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let e=this.get("cache.tasks")||[],i=(this.get("localTasks")||[]).map(a=>({...a,isLocal:!0}));return[...e,...i]}getTasksByStatus(e){return this.getMergedTasks().filter(t=>t.status===e)}};C(S,"STORAGE_KEY","loki-dashboard-state"),C(S,"_instance",null);var N=S;function B(){return N.getInstance()}function qe(d){let e=B();return{get:()=>e.get(d),set:t=>e.set(d,t),subscribe:t=>e.subscribe(d,t)}}var O=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data={status:"offline",phase:null,iteration:null,provider:null,running_agents:0,pending_tasks:null,uptime_seconds:0,complexity:null,connected:!1},this._api=null,this._pollInterval=null,this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null,this._checklistSummary=null,this._appRunnerStatus=null,this._playwrightResults=null,this._gateStatus=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._startPolling(),this._api.connect().catch(()=>{})}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._loadAbortController&&(this._loadAbortController.abort(),this._loadAbortController=null),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(v.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(v.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(v.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e}),this._statusUpdateHandler=t=>this._updateFromStatus(t.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(v.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(v.CONNECTED,this._connectedHandler),this._api.addEventListener(v.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){this._loadAbortController&&this._loadAbortController.abort(),this._loadAbortController=new AbortController;let{signal:e}=this._loadAbortController;try{let[t,i,a,s,r]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);if(e.aborted)return;t.status==="fulfilled"?this._updateFromStatus(t.value):(this._data.connected=!1,this._data.status="offline"),i.status==="fulfilled"&&(this._checklistSummary=i.value?.summary||null),a.status==="fulfilled"&&(this._appRunnerStatus=a.value),s.status==="fulfilled"&&(this._playwrightResults=s.value),r.status==="fulfilled"&&(this._gateStatus=r.value),this.render()}catch{if(e.aborted)return;this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(e){e&&(this._data={...this._data,connected:!0,status:e.status||"offline",phase:e.phase||null,iteration:e.iteration!=null?e.iteration:null,provider:e.provider||null,running_agents:e.running_agents||0,pending_tasks:e.pending_tasks!=null?e.pending_tasks:null,uptime_seconds:e.uptime_seconds||0,complexity:e.complexity||null})}_startPolling(){this._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(e){if(!e||e<0)return"--";let t=Math.floor(e/3600),i=Math.floor(e%3600/60),a=Math.floor(e%60);return t>0?`${t}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_getStatusDotClass(){switch(this._data.status){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let e=this._appRunnerStatus;if(!e||e.status==="not_initialized")return`
|
|
1826
1839
|
<div class="overview-card">
|
|
1827
1840
|
<div class="card-label">App Runner</div>
|
|
1828
1841
|
<div class="card-value small-text">${this._data.status==="running"||this._data.status==="autonomous"?"Waiting...":"Not started"}</div>
|
|
@@ -1897,7 +1910,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
1897
1910
|
PASSED
|
|
1898
1911
|
</div>
|
|
1899
1912
|
</div>
|
|
1900
|
-
`}render(){let e=this._getStatusDotClass(),t=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._data.status==="running"||this._data.status==="autonomous",o=this._data.running_agents||0,n=r&&o===0?"Sequential":this._escapeHtml(String(o)),l=this._escapeHtml(this._data.pending_tasks!=null?`${this._data.pending_tasks} pending`:r?"Inline":"--"),
|
|
1913
|
+
`}render(){let e=this._getStatusDotClass(),t=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._data.status==="running"||this._data.status==="autonomous",o=this._data.running_agents||0,n=r&&o===0?"Sequential":this._escapeHtml(String(o)),l=this._escapeHtml(this._data.pending_tasks!=null?`${this._data.pending_tasks} pending`:r?"Inline":"--"),c=this._escapeHtml(this._formatUptime(this._data.uptime_seconds)),p=this._escapeHtml((this._data.complexity||"STANDARD").toUpperCase());this.shadowRoot.innerHTML=`
|
|
1901
1914
|
<style>
|
|
1902
1915
|
${this.getBaseStyles()}
|
|
1903
1916
|
|
|
@@ -2068,7 +2081,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
2068
2081
|
|
|
2069
2082
|
<div class="overview-card">
|
|
2070
2083
|
<div class="card-label">Uptime</div>
|
|
2071
|
-
<div class="card-value small-text">${
|
|
2084
|
+
<div class="card-value small-text">${c}</div>
|
|
2072
2085
|
</div>
|
|
2073
2086
|
|
|
2074
2087
|
<div class="overview-card">
|
|
@@ -2077,8 +2090,8 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
2077
2090
|
</div>
|
|
2078
2091
|
</div>
|
|
2079
2092
|
</div>
|
|
2080
|
-
`}};customElements.get("loki-overview")||customElements.define("loki-overview",O);var
|
|
2081
|
-
<ul class="md-list">${a.trim().split(/\n/).map(r=>r.replace(/^[-*]\s+/,"")).map(r=>`<li>${r}</li>`).join("")}</ul>`),t=t.split(/\n{2,}/).map(i=>/^<(h\d|ul|ol|pre)/.test(i.trim())?i:`<p class="md-p">${i.replace(/\n/g,"<br>")}</p>`).join(""),t}_formatTimestamp(e){if(!e)return"";try{let t=new Date(e);return isNaN(t.getTime())?this._escapeHtml(String(e)):t.toLocaleString()}catch{return this._escapeHtml(String(e))}}_phaseClass(e){let t=String(e||"").toLowerCase();return["reason","plan","planning"].includes(t)?"phase-reason":["act","execute","execution","implement"].includes(t)?"phase-act":["reflect","review"].includes(t)?"phase-reflect":["verify","test","gate"].includes(t)?"phase-verify":"phase-default"}_logLevelClass(e){let t=String(e||"info").toLowerCase();return t==="error"||t==="fatal"?"log-error":t==="warn"||t==="warning"?"log-warn":t==="debug"||t==="trace"?"log-debug":"log-info"}_renderTaskDetailModal(e){if(!e)return"";let t=(e.priority||"medium").toLowerCase(),i=t.charAt(0).toUpperCase()+t.slice(1),a=e.status||"pending",s=a.replace(/_/g," ").replace(/\b\w/g,m=>m.toUpperCase()),r=e.metadata||{},o=e.acceptance_criteria||[],n=e.context_files||[],l=e.specification||"",
|
|
2093
|
+
`}};customElements.get("loki-overview")||customElements.define("loki-overview",O);var mt=[{id:"pending",label:"Pending",status:"pending",color:"var(--loki-text-muted)"},{id:"in_progress",label:"In Progress",status:"in_progress",color:"var(--loki-blue)"},{id:"review",label:"In Review",status:"review",color:"var(--loki-purple)"},{id:"done",label:"Completed",status:"done",color:"var(--loki-green)"}],q=class d extends u{static get observedAttributes(){return["api-url","project-id","theme","readonly"]}constructor(){super(),this._tasks=[],this._loading=!0,this._error=null,this._draggedTask=null,this._selectedTask=null,this._expandedCards=new Set,this._selectedTasks=new Set,this._bulkMode=!1,this._activeFilter="all",this._searchQuery="",this._visibleCounts={},this._api=null,this._state=B()}static get PAGE_SIZE(){return 10}_getVisibleCount(e){let t=this._visibleCounts[e];return typeof t=="number"&&t>0?t:d.PAGE_SIZE}_showMore(e){this._visibleCounts[e]=this._getVisibleCount(e)+d.PAGE_SIZE,this.render()}_columnIcon(e){switch(e){case"pending":return'<circle cx="12" cy="12" r="10"/>';case"in_progress":return'<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>';case"review":return'<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>';case"done":return'<path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>';default:return'<circle cx="12" cy="12" r="10"/>'}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadTasks()}disconnectedCallback(){super.disconnectedCallback(),this._api&&(this._api.removeEventListener(v.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(v.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(v.TASK_DELETED,this._onTaskEvent))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadTasks()),e==="project-id"&&this._loadTasks(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e}),this._onTaskEvent&&(this._api.removeEventListener(v.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(v.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(v.TASK_DELETED,this._onTaskEvent)),this._onTaskEvent=()=>this._loadTasks(),this._api.addEventListener(v.TASK_CREATED,this._onTaskEvent),this._api.addEventListener(v.TASK_UPDATED,this._onTaskEvent),this._api.addEventListener(v.TASK_DELETED,this._onTaskEvent)}async _loadTasks(){this._loading=!0,this._error=null,this.render();try{let e=this.getAttribute("project-id"),t=e?{projectId:parseInt(e)}:{};this._tasks=await this._api.listTasks(t);let i=this._state.get("localTasks")||[];i.length>0&&(this._tasks=[...this._tasks,...i.map(a=>({...a,isLocal:!0}))]),this._state.update({"cache.tasks":this._tasks},!1)}catch(e){this._error=e.message,this._tasks=(this._state.get("localTasks")||[]).map(t=>({...t,isLocal:!0}))}this._loading=!1,this.render()}_getTasksByStatus(e){return this._getFilteredTasks().filter(i=>i.status?.toLowerCase().replace(/-/g,"_")===e)}_handleDragStart(e,t){this.hasAttribute("readonly")||(this._draggedTask=t,e.target.classList.add("dragging"),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",t.id.toString()))}_handleDragEnd(e){e.target.classList.remove("dragging"),this._draggedTask=null,this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(t=>{t.classList.remove("drag-over")})}_handleDragOver(e){e.preventDefault(),e.dataTransfer.dropEffect="move"}_handleDragEnter(e){e.preventDefault(),e.currentTarget.classList.add("drag-over")}_handleDragLeave(e){e.currentTarget.contains(e.relatedTarget)||e.currentTarget.classList.remove("drag-over")}async _handleDrop(e,t){if(e.preventDefault(),e.currentTarget.classList.remove("drag-over"),!this._draggedTask||this.hasAttribute("readonly"))return;let i=this._draggedTask.id,a=this._tasks.find(r=>r.id===i);if(!a)return;let s=a.status;if(s!==t){a.status=t,this.render();try{a.isLocal?this._state.moveLocalTask(i,t):await this._api.moveTask(i,t,0),this.dispatchEvent(new CustomEvent("task-moved",{detail:{taskId:i,oldStatus:s,newStatus:t}}))}catch(r){a.status=s,this.render(),console.error("Failed to move task:",r)}}}_toggleCardExpand(e){this._expandedCards.has(e)?this._expandedCards.delete(e):this._expandedCards.add(e),this.render()}_toggleTaskSelection(e,t){t&&t.stopPropagation(),this._selectedTasks.has(e)?this._selectedTasks.delete(e):this._selectedTasks.add(e),this.render()}_toggleBulkMode(){this._bulkMode=!this._bulkMode,this._bulkMode||this._selectedTasks.clear(),this.render()}async _bulkMove(e){let t=[...this._selectedTasks];for(let i of t){let a=this._tasks.find(s=>String(s.id)===String(i));if(a&&a.status!==e)try{a.isLocal?this._state.moveLocalTask(i,e):await this._api.moveTask(i,e,0),a.status=e}catch(s){console.error("Failed to bulk move task:",i,s)}}this._selectedTasks.clear(),this._bulkMode=!1,this.render(),this._loadTasks()}async _bulkDelete(){let e=[...this._selectedTasks];for(let t of e)try{await this._api.deleteTask(t)}catch(i){console.error("Failed to delete task:",t,i)}this._selectedTasks.clear(),this._bulkMode=!1,this._loadTasks()}_setFilter(e){this._activeFilter=e,this._visibleCounts={},this.render()}_setSearch(e){this._searchQuery=e||"",this._visibleCounts={},this._renderTaskRegion();let t=this.shadowRoot.getElementById("task-search");if(t){t.focus();let i=t.value.length;try{t.setSelectionRange(i,i)}catch{}}}_getFilteredTasks(){let e=[...this._tasks],t=new Date,i=new Date(t.getFullYear(),t.getMonth(),t.getDate()),a=new Date(i.getTime()-7*24*60*60*1e3);switch(this._activeFilter){case"today":e=e.filter(r=>{let o=r.created_at?new Date(r.created_at):null;return o&&o>=i});break;case"this-week":e=e.filter(r=>{let o=r.created_at?new Date(r.created_at):null;return o&&o>=a});break;case"running":e=e.filter(r=>r.status==="in_progress");break;case"failed":e=e.filter(r=>r.status==="failed"||r.status==="error");break;default:break}let s=this._searchQuery.trim().toLowerCase();return s&&(e=e.filter(r=>[r.id,r.title,r.description,r.type].map(n=>String(n??"").toLowerCase()).join(" ").includes(s))),e}_openAddTaskModal(e="pending"){this.dispatchEvent(new CustomEvent("add-task",{detail:{status:e}}))}_openTaskDetail(e){this._selectedTask=e,this.render(),this.dispatchEvent(new CustomEvent("task-click",{detail:{task:e}}))}_closeTaskDetail(){this._selectedTask=null,this.render()}_renderMarkdown(e){if(!e)return"";let t=this._escapeHtml(String(e));return t=t.replace(/```([\s\S]*?)```/g,(i,a)=>`<pre class="md-code">${a.trim()}</pre>`),t=t.replace(/`([^`\n]+)`/g,'<code class="md-inline-code">$1</code>'),t=t.replace(/^###\s+(.+)$/gm,'<h4 class="md-h4">$1</h4>'),t=t.replace(/^##\s+(.+)$/gm,'<h3 class="md-h3">$1</h3>'),t=t.replace(/^#\s+(.+)$/gm,'<h2 class="md-h2">$1</h2>'),t=t.replace(/\*\*([^*\n]+)\*\*/g,"<strong>$1</strong>"),t=t.replace(/(^|[^*])\*([^*\n]+)\*/g,"$1<em>$2</em>"),t=t.replace(/(?:^|\n)((?:[-*]\s+.+(?:\n|$))+)/g,(i,a)=>`
|
|
2094
|
+
<ul class="md-list">${a.trim().split(/\n/).map(r=>r.replace(/^[-*]\s+/,"")).map(r=>`<li>${r}</li>`).join("")}</ul>`),t=t.split(/\n{2,}/).map(i=>/^<(h\d|ul|ol|pre)/.test(i.trim())?i:`<p class="md-p">${i.replace(/\n/g,"<br>")}</p>`).join(""),t}_formatTimestamp(e){if(!e)return"";try{let t=new Date(e);return isNaN(t.getTime())?this._escapeHtml(String(e)):t.toLocaleString()}catch{return this._escapeHtml(String(e))}}_phaseClass(e){let t=String(e||"").toLowerCase();return["reason","plan","planning"].includes(t)?"phase-reason":["act","execute","execution","implement"].includes(t)?"phase-act":["reflect","review"].includes(t)?"phase-reflect":["verify","test","gate"].includes(t)?"phase-verify":"phase-default"}_logLevelClass(e){let t=String(e||"info").toLowerCase();return t==="error"||t==="fatal"?"log-error":t==="warn"||t==="warning"?"log-warn":t==="debug"||t==="trace"?"log-debug":"log-info"}_renderTaskDetailModal(e){if(!e)return"";let t=(e.priority||"medium").toLowerCase(),i=t.charAt(0).toUpperCase()+t.slice(1),a=e.status||"pending",s=a.replace(/_/g," ").replace(/\b\w/g,m=>m.toUpperCase()),r=e.metadata||{},o=e.acceptance_criteria||[],n=e.context_files||[],l=e.specification||"",c=e.description||"",p=Array.isArray(e.notes)?e.notes:[],h=Array.isArray(e.logs)?e.logs:[],b=e.full_content||"";return`
|
|
2082
2095
|
<div class="modal-overlay" id="task-detail-overlay">
|
|
2083
2096
|
<div class="modal-container">
|
|
2084
2097
|
<div class="modal-header">
|
|
@@ -2105,10 +2118,10 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
2105
2118
|
</div>
|
|
2106
2119
|
`:""}
|
|
2107
2120
|
|
|
2108
|
-
${
|
|
2121
|
+
${c?`
|
|
2109
2122
|
<div class="modal-section">
|
|
2110
2123
|
<h3 class="modal-section-title">Description</h3>
|
|
2111
|
-
<div class="modal-prose md-body">${this._renderMarkdown(
|
|
2124
|
+
<div class="modal-prose md-body">${this._renderMarkdown(c)}</div>
|
|
2112
2125
|
</div>
|
|
2113
2126
|
`:""}
|
|
2114
2127
|
|
|
@@ -2151,11 +2164,11 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
2151
2164
|
<h3 class="modal-section-title">Logs</h3>
|
|
2152
2165
|
<div class="logs-scroll">
|
|
2153
2166
|
<ul class="logs-timeline" role="list">
|
|
2154
|
-
${h.map(m=>{let f=this._formatTimestamp(m&&m.timestamp),x=m&&m.iteration!==void 0&&m.iteration!==null?`i${this._escapeHtml(String(m.iteration))}`:"",w=m&&m.phase?String(m.phase):"",
|
|
2167
|
+
${h.map(m=>{let f=this._formatTimestamp(m&&m.timestamp),x=m&&m.iteration!==void 0&&m.iteration!==null?`i${this._escapeHtml(String(m.iteration))}`:"",w=m&&m.phase?String(m.phase):"",rt=this._phaseClass(w),ot=this._logLevelClass(m&&m.level),nt=m&&m.message?this._escapeHtml(String(m.message)):"";return`<li class="log-entry ${ot}">
|
|
2155
2168
|
${f?`<span class="log-time">${f}</span>`:""}
|
|
2156
2169
|
${x?`<span class="log-iter">${x}</span>`:""}
|
|
2157
|
-
${w?`<span class="log-phase ${
|
|
2158
|
-
<span class="log-message">${
|
|
2170
|
+
${w?`<span class="log-phase ${rt}">${this._escapeHtml(w)}</span>`:""}
|
|
2171
|
+
<span class="log-message">${nt}</span>
|
|
2159
2172
|
</li>`}).join("")}
|
|
2160
2173
|
</ul>
|
|
2161
2174
|
</div>
|
|
@@ -3165,7 +3178,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
3165
3178
|
`:""}
|
|
3166
3179
|
|
|
3167
3180
|
<div class="kanban-board">
|
|
3168
|
-
${
|
|
3181
|
+
${mt.map(a=>{let s=this._getTasksByStatus(a.status),r=this._getVisibleCount(a.status),o=s.slice(0,r),n=s.length-o.length;return`
|
|
3169
3182
|
<div class="kanban-column" data-status="${a.status}">
|
|
3170
3183
|
<div class="kanban-column-header">
|
|
3171
3184
|
<span class="kanban-column-title">
|
|
@@ -3178,17 +3191,17 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
3178
3191
|
</div>
|
|
3179
3192
|
<div class="kanban-tasks" data-status="${a.status}">
|
|
3180
3193
|
${s.length===0?'<div class="empty-column">No tasks</div>':""}
|
|
3181
|
-
${o.map(l=>{let
|
|
3194
|
+
${o.map(l=>{let c=String(l.id||""),p=this._expandedCards.has(c),h=this._selectedTasks.has(c);return`
|
|
3182
3195
|
<div class="task-card ${!e&&!l.fromServer?"draggable":""} ${l.isLocal?"local":""} ${p?"expanded":""} ${h?"selected":""}"
|
|
3183
|
-
data-task-id="${this._escapeHtml(
|
|
3196
|
+
data-task-id="${this._escapeHtml(c)}"
|
|
3184
3197
|
tabindex="0"
|
|
3185
3198
|
role="button"
|
|
3186
3199
|
aria-label="Task: ${this._escapeHtml(l.title||"Untitled")}, ${this._escapeHtml(String(l.priority||"medium"))} priority"
|
|
3187
3200
|
${!e&&!l.fromServer?'draggable="true"':""}>
|
|
3188
3201
|
<div class="task-card-header">
|
|
3189
3202
|
<div style="display:flex;align-items:center;gap:6px;">
|
|
3190
|
-
${this._bulkMode?`<div class="task-checkbox ${h?"checked":""}" data-check-id="${this._escapeHtml(
|
|
3191
|
-
<span class="task-id">${l.isLocal?"LOCAL":"#"+this._escapeHtml(
|
|
3203
|
+
${this._bulkMode?`<div class="task-checkbox ${h?"checked":""}" data-check-id="${this._escapeHtml(c)}"></div>`:""}
|
|
3204
|
+
<span class="task-id">${l.isLocal?"LOCAL":"#"+this._escapeHtml(c)}</span>
|
|
3192
3205
|
</div>
|
|
3193
3206
|
<div style="display:flex;align-items:center;gap:6px;">
|
|
3194
3207
|
${i(l)}
|
|
@@ -3199,7 +3212,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
3199
3212
|
${!p&&l.description?`<div class="task-desc">${this._escapeHtml(String(l.description??"").substring(0,80))}${String(l.description??"").length>80?"...":""}</div>`:""}
|
|
3200
3213
|
<div class="task-meta">
|
|
3201
3214
|
<span class="task-type">${this._escapeHtml(String(l.type||"task"))}</span>
|
|
3202
|
-
<span class="expand-toggle" data-expand-id="${this._escapeHtml(
|
|
3215
|
+
<span class="expand-toggle" data-expand-id="${this._escapeHtml(c)}">
|
|
3203
3216
|
${p?'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"/></svg> Less':'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg> More'}
|
|
3204
3217
|
</span>
|
|
3205
3218
|
</div>
|
|
@@ -3219,8 +3232,8 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
3219
3232
|
</div>
|
|
3220
3233
|
${n>0?`
|
|
3221
3234
|
<button class="show-more-btn" data-show-more="${a.status}"
|
|
3222
|
-
aria-label="Show ${Math.min(n,
|
|
3223
|
-
Show ${Math.min(n,
|
|
3235
|
+
aria-label="Show ${Math.min(n,d.PAGE_SIZE)} more in ${a.label}">
|
|
3236
|
+
Show ${Math.min(n,d.PAGE_SIZE)} more (${n} hidden)
|
|
3224
3237
|
</button>
|
|
3225
3238
|
`:""}
|
|
3226
3239
|
${!e&&a.status==="pending"?`
|
|
@@ -3628,12 +3641,12 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
3628
3641
|
</div>
|
|
3629
3642
|
</div>
|
|
3630
3643
|
</div>
|
|
3631
|
-
`,
|
|
3644
|
+
`,c=this.shadowRoot.activeElement,p=c&&c.id==="spec-input",h=p?c.selectionStart:null,b=p?c.selectionEnd:null;if(this.shadowRoot.innerHTML=`
|
|
3632
3645
|
${o}
|
|
3633
3646
|
${e?n:l}
|
|
3634
|
-
`,this._attachEventListeners(),p){let m=this.shadowRoot.getElementById("spec-input");if(m&&!m.disabled){m.focus();try{m.setSelectionRange(h,b)}catch{}}}}_attachEventListeners(){let e=this.shadowRoot.getElementById("pause-btn"),t=this.shadowRoot.getElementById("resume-btn"),i=this.shadowRoot.getElementById("stop-btn"),a=this.shadowRoot.getElementById("start-btn");e&&e.addEventListener("click",()=>this._triggerPause()),t&&t.addEventListener("click",()=>this._triggerResume()),i&&i.addEventListener("click",()=>this._triggerStop()),a&&a.addEventListener("click",()=>this._triggerStart());let s=this.shadowRoot.getElementById("model-select");s&&s.addEventListener("change",o=>this._onModelChange(o.target.value));let r=this.shadowRoot.getElementById("spec-input");r&&r.addEventListener("input",o=>this._onSpecInput(o.target.value))}};customElements.get("loki-session-control")||customElements.define("loki-session-control",J);var
|
|
3647
|
+
`,this._attachEventListeners(),p){let m=this.shadowRoot.getElementById("spec-input");if(m&&!m.disabled){m.focus();try{m.setSelectionRange(h,b)}catch{}}}}_attachEventListeners(){let e=this.shadowRoot.getElementById("pause-btn"),t=this.shadowRoot.getElementById("resume-btn"),i=this.shadowRoot.getElementById("stop-btn"),a=this.shadowRoot.getElementById("start-btn");e&&e.addEventListener("click",()=>this._triggerPause()),t&&t.addEventListener("click",()=>this._triggerResume()),i&&i.addEventListener("click",()=>this._triggerStop()),a&&a.addEventListener("click",()=>this._triggerStart());let s=this.shadowRoot.getElementById("model-select");s&&s.addEventListener("change",o=>this._onModelChange(o.target.value));let r=this.shadowRoot.getElementById("spec-input");r&&r.addEventListener("input",o=>this._onSpecInput(o.target.value))}};customElements.get("loki-session-control")||customElements.define("loki-session-control",J);var Je={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"}},G=class extends u{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(v.LOG_MESSAGE,this._logMessageHandler)}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i);break;case"max-lines":this._maxLines=parseInt(i)||500,this._trimLogs(),this.render();break;case"auto-scroll":this._autoScroll=this.hasAttribute("auto-scroll"),this.render();break;case"theme":this._applyTheme();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e}),this._logMessageHandler=t=>this._addLog(t.detail),this._api.addEventListener(v.LOG_MESSAGE,this._logMessageHandler)}_startLogPolling(){let e=this.getAttribute("log-file");e?this._pollLogFile(e):this._pollApiLogs()}async _pollApiLogs(){let e=0,t=async()=>{try{let i=await this._api.getLogs(200);if(Array.isArray(i)&&i.length>e){let a=i.slice(e);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()});e=i.length}}catch{}};t(),this._apiPollInterval=setInterval(t,2e3)}async _pollLogFile(e){let t=0,i=async()=>{try{let a=await fetch(`${e}?t=${Date.now()}`,{credentials:"include"});if(!a.ok)return;let r=(await a.text()).split(`
|
|
3635
3648
|
`);if(r.length>t){let o=r.slice(t);for(let n of o)n.trim()&&this._addLog(this._parseLine(n));t=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(e){let t=e.match(/^\[([^\]]+)\]\s*\[([^\]]+)\]\s*(.+)$/);if(t)return{timestamp:t[1],level:t[2].toLowerCase(),message:t[3]};let i=e.match(/^(\d{2}:\d{2}:\d{2})\s+(\w+)\s+(.+)$/);return i?{timestamp:i[1],level:i[2].toLowerCase(),message:i[3]}:{timestamp:new Date().toLocaleTimeString(),level:"info",message:e}}_addLog(e){if(!e)return;let t={id:Date.now()+Math.random(),timestamp:e.timestamp||new Date().toLocaleTimeString(),level:(e.level||"info").toLowerCase(),message:e.message||e};this._logs.push(t),this._trimLogs(),this.dispatchEvent(new CustomEvent("log-received",{detail:t})),this._renderLogs(),this._autoScroll&&this._scrollToBottom()}_trimLogs(){this._logs.length>this._maxLines&&(this._logs=this._logs.slice(-this._maxLines))}_clearLogs(){this._logs=[],this.dispatchEvent(new CustomEvent("logs-cleared")),this._renderLogs()}_toggleAutoScroll(){this._autoScroll=!this._autoScroll,this.render(),this._autoScroll&&this._scrollToBottom()}_scrollToBottom(){requestAnimationFrame(()=>{let e=this.shadowRoot.getElementById("log-output");e&&(e.scrollTop=e.scrollHeight)})}_downloadLogs(){let e=this._logs.map(s=>`[${s.timestamp}] [${s.level.toUpperCase()}] ${s.message}`).join(`
|
|
3636
|
-
`),t=new Blob([e],{type:"text/plain"}),i=URL.createObjectURL(t),a=document.createElement("a");a.href=i,a.download=`loki-logs-${new Date().toISOString().split("T")[0]}.txt`,a.click(),URL.revokeObjectURL(i)}_setFilter(e){this._filter=e.toLowerCase(),this._renderLogs()}_setLevelFilter(e){this._levelFilter=e,this._renderLogs()}_getFilteredLogs(){return this._logs.filter(e=>!(this._levelFilter!=="all"&&e.level!==this._levelFilter||this._filter&&!e.message.toLowerCase().includes(this._filter)))}_renderLogs(){let e=this.shadowRoot.getElementById("log-output");if(!e)return;let t=this._getFilteredLogs();if(t.length===0){e.innerHTML='<div class="log-empty">No log output yet. Terminal will update when Loki Mode is running.</div>';return}e.innerHTML=t.map(i=>{let a=
|
|
3649
|
+
`),t=new Blob([e],{type:"text/plain"}),i=URL.createObjectURL(t),a=document.createElement("a");a.href=i,a.download=`loki-logs-${new Date().toISOString().split("T")[0]}.txt`,a.click(),URL.revokeObjectURL(i)}_setFilter(e){this._filter=e.toLowerCase(),this._renderLogs()}_setLevelFilter(e){this._levelFilter=e,this._renderLogs()}_getFilteredLogs(){return this._logs.filter(e=>!(this._levelFilter!=="all"&&e.level!==this._levelFilter||this._filter&&!e.message.toLowerCase().includes(this._filter)))}_renderLogs(){let e=this.shadowRoot.getElementById("log-output");if(!e)return;let t=this._getFilteredLogs();if(t.length===0){e.innerHTML='<div class="log-empty">No log output yet. Terminal will update when Loki Mode is running.</div>';return}e.innerHTML=t.map(i=>{let a=Je[i.level]||Je.info;return`
|
|
3637
3650
|
<div class="log-line">
|
|
3638
3651
|
<span class="timestamp">${this._escapeHtml(i.timestamp)}</span>
|
|
3639
3652
|
<span class="level" style="color: ${a.color}">[${this._escapeHtml(a.label)}]</span>
|
|
@@ -3832,7 +3845,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
3832
3845
|
${this._logs.length} lines (${this._getFilteredLogs().length} shown)
|
|
3833
3846
|
</div>
|
|
3834
3847
|
</div>
|
|
3835
|
-
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let e=this.shadowRoot.getElementById("filter-input"),t=this.shadowRoot.getElementById("level-select"),i=this.shadowRoot.getElementById("auto-scroll-btn"),a=this.shadowRoot.getElementById("clear-btn"),s=this.shadowRoot.getElementById("download-btn");e&&(e.value=this._filter,e.addEventListener("input",r=>this._setFilter(r.target.value))),t&&(t.value=this._levelFilter,t.addEventListener("change",r=>this._setLevelFilter(r.target.value))),i&&i.addEventListener("click",()=>this._toggleAutoScroll()),a&&a.addEventListener("click",()=>this._clearLogs()),s&&s.addEventListener("click",()=>this._downloadLogs())}addLog(e,t="info"){this._addLog({message:e,level:t,timestamp:new Date().toLocaleTimeString()})}clear(){this._clearLogs()}};customElements.get("loki-log-stream")||customElements.define("loki-log-stream",G);var
|
|
3848
|
+
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let e=this.shadowRoot.getElementById("filter-input"),t=this.shadowRoot.getElementById("level-select"),i=this.shadowRoot.getElementById("auto-scroll-btn"),a=this.shadowRoot.getElementById("clear-btn"),s=this.shadowRoot.getElementById("download-btn");e&&(e.value=this._filter,e.addEventListener("input",r=>this._setFilter(r.target.value))),t&&(t.value=this._levelFilter,t.addEventListener("change",r=>this._setLevelFilter(r.target.value))),i&&i.addEventListener("click",()=>this._toggleAutoScroll()),a&&a.addEventListener("click",()=>this._clearLogs()),s&&s.addEventListener("click",()=>this._downloadLogs())}addLog(e,t="info"){this._addLog({message:e,level:t,timestamp:new Date().toLocaleTimeString()})}clear(){this._clearLogs()}};customElements.get("loki-log-stream")||customElements.define("loki-log-stream",G);var vt=[{id:"summary",label:"Summary",icon:"M4 6h16M4 12h16M4 18h16"},{id:"search",label:"Search",icon:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"},{id:"episodes",label:"Episodes",icon:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"},{id:"patterns",label:"Patterns",icon:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"},{id:"skills",label:"Skills",icon:"M13 10V3L4 14h7v7l9-11h-7z"}],K=class extends u{static get observedAttributes(){return["api-url","theme","tab"]}constructor(){super(),this._activeTab="summary",this._loading=!1,this._error=null,this._api=null,this._summary=null,this._stats=null,this._episodes=[],this._patterns=[],this._skills=[],this._tokenEconomics=null,this._selectedItem=null,this._lastFocusedElement=null,this._searchQuery="",this._searchCollection="all",this._searchResults=[],this._searchLoading=!1,this._searchError=null}connectedCallback(){super.connectedCallback(),this._activeTab=this.getAttribute("tab")||"summary",this._setupApi(),this._loadData()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadData());break;case"theme":this._applyTheme();break;case"tab":this._setTab(i);break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let[e,t,i]=await Promise.allSettled([this._api.getMemorySummary(),this._api.getTokenEconomics(),this._api.getMemoryStats()]);this._summary=e.status==="fulfilled"?e.value:null,this._tokenEconomics=t.status==="fulfilled"?t.value:null,this._stats=i.status==="fulfilled"?i.value:null,await this._loadTabData()}catch(e){this._error=e.message||"Failed to load memory data"}this._loading=!1,this.render()}async _loadTabData(){switch(this._activeTab){case"episodes":this._episodes=await this._api.listEpisodes({limit:50}).catch(()=>[]);break;case"patterns":this._patterns=await this._api.listPatterns().catch(()=>[]);break;case"skills":this._skills=await this._api.listSkills().catch(()=>[]);break}}_setTab(e){this._activeTab!==e&&(this._activeTab=e,this._selectedItem=null,this._loadTabData().then(()=>this.render()))}async _selectEpisode(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getEpisode(e),this.dispatchEvent(new CustomEvent("episode-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load episode:",t)}}async _selectPattern(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getPattern(e),this.dispatchEvent(new CustomEvent("pattern-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load pattern:",t)}}async _selectSkill(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getSkill(e),this.dispatchEvent(new CustomEvent("skill-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load skill:",t)}}_focusDetailPanel(){requestAnimationFrame(()=>{let e=this.shadowRoot.getElementById("close-detail");e&&e.focus()})}_closeDetail(){this._selectedItem=null,this.render(),this._lastFocusedElement&&requestAnimationFrame(()=>{this._lastFocusedElement.focus(),this._lastFocusedElement=null})}async _triggerConsolidation(){try{let e=await this._api.consolidateMemory(24);alert(`Consolidation complete:
|
|
3836
3849
|
- Patterns created: ${e.patternsCreated}
|
|
3837
3850
|
- Patterns merged: ${e.patternsMerged}
|
|
3838
3851
|
- Episodes processed: ${e.episodesProcessed}`),this._loadData()}catch(e){alert("Consolidation failed: "+e.message)}}async _executeSearch(){let e=this._searchQuery.trim();if(e){this._searchLoading=!0,this._searchError=null,this.render();try{let t=await this._api.searchMemory(e,this._searchCollection,20);this._searchResults=t.results||[]}catch(t){this._searchError=t.message||"Search failed",this._searchResults=[]}this._searchLoading=!1,this.render(),requestAnimationFrame(()=>{let t=this.shadowRoot.getElementById("memory-search-input");t&&t.focus()})}}_renderSearch(){let e=["all","episodes","patterns","skills"];return`
|
|
@@ -4703,7 +4716,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
4703
4716
|
<span class="browser-title">Memory System</span>
|
|
4704
4717
|
</div>
|
|
4705
4718
|
<div class="tabs" role="tablist" aria-label="Memory browser sections">
|
|
4706
|
-
${
|
|
4719
|
+
${vt.map((i,a)=>`
|
|
4707
4720
|
<button class="tab ${this._activeTab===i.id?"active":""}"
|
|
4708
4721
|
data-tab="${i.id}"
|
|
4709
4722
|
role="tab"
|
|
@@ -4720,12 +4733,12 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
4720
4733
|
${t}
|
|
4721
4734
|
</div>
|
|
4722
4735
|
</div>
|
|
4723
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.querySelectorAll(".tab");e.forEach((n,l)=>{n.addEventListener("click",()=>this._setTab(n.dataset.tab)),n.addEventListener("keydown",
|
|
4736
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.querySelectorAll(".tab");e.forEach((n,l)=>{n.addEventListener("click",()=>this._setTab(n.dataset.tab)),n.addEventListener("keydown",c=>{if(c.key==="ArrowRight"||c.key==="ArrowLeft"){c.preventDefault();let p=Array.from(e),h=c.key==="ArrowRight"?(l+1)%p.length:(l-1+p.length)%p.length;p[h].focus(),this._setTab(p[h].dataset.tab)}})}),this.shadowRoot.querySelectorAll(".item-card").forEach(n=>{n.addEventListener("click",()=>this._handleItemClick(n)),n.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._handleItemClick(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateItemCards(n,l.key==="ArrowDown"?"next":"prev"))})});let t=this.shadowRoot.getElementById("close-detail");t&&t.addEventListener("click",()=>this._closeDetail());let i=this.shadowRoot.getElementById("consolidate-btn");i&&i.addEventListener("click",()=>this._triggerConsolidation());let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("memory-search-input"),r=this.shadowRoot.getElementById("search-btn"),o=this.shadowRoot.getElementById("memory-search-collection");s&&(s.addEventListener("keydown",n=>{n.key==="Enter"&&(n.preventDefault(),this._searchQuery=s.value,this._executeSearch())}),s.addEventListener("input",n=>{this._searchQuery=n.target.value})),r&&r.addEventListener("click",()=>{let n=this.shadowRoot.getElementById("memory-search-input");n&&(this._searchQuery=n.value),this._executeSearch()}),o&&o.addEventListener("change",n=>{this._searchCollection=n.target.value})}_handleItemClick(e){let t=e.dataset.id;switch(e.dataset.type){case"episode":this._selectEpisode(t);break;case"pattern":this._selectPattern(t);break;case"skill":this._selectSkill(t);break}}_navigateItemCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".item-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-memory-browser")||customElements.define("loki-memory-browser",K);var bt=[{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}],ft=[{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"}],kt=[{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"}],V=class extends u{static get observedAttributes(){return["api-url","theme","time-range","signal-type","source"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._timeRange="7d",this._signalType="all",this._source="all",this._metrics=null,this._trends=null,this._signals=[],this._selectedMetric=null}connectedCallback(){super.connectedCallback(),this._timeRange=this.getAttribute("time-range")||"7d",this._signalType=this.getAttribute("signal-type")||"all",this._source=this.getAttribute("source")||"all",this._setupApi(),this._loadData()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadData());break;case"theme":this._applyTheme();break;case"time-range":this._timeRange=i,this._loadData();break;case"signal-type":this._signalType=i,this._loadData();break;case"source":this._source=i,this._loadData();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let e={timeRange:this._timeRange,signalType:this._signalType!=="all"?this._signalType:void 0,source:this._source!=="all"?this._source:void 0},[t,i,a]=await Promise.all([this._api.getLearningMetrics(e).catch(()=>null),this._api.getLearningTrends(e).catch(()=>null),this._api.getLearningSignals({...e,limit:50}).catch(()=>[])]);this._metrics=t,this._trends=i,this._signals=a||[]}catch(e){this._error=e.message||"Failed to load learning data"}this._loading=!1,this.render()}_setFilter(e,t){switch(e){case"timeRange":this._timeRange=t,this.setAttribute("time-range",t);break;case"signalType":this._signalType=t,this.setAttribute("signal-type",t);break;case"source":this._source=t,this.setAttribute("source",t);break}this.dispatchEvent(new CustomEvent("filter-change",{detail:{timeRange:this._timeRange,signalType:this._signalType,source:this._source}})),this._loadData()}_selectMetric(e,t){this._selectedMetric={type:e,item:t},this.dispatchEvent(new CustomEvent("metric-select",{detail:{type:e,item:t}})),this.render()}_closeDetail(){this._selectedMetric=null,this.render()}_formatNumber(e){return e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":e?.toString()||"0"}_formatPercent(e){return(e*100).toFixed(1)+"%"}_formatDuration(e){return e<60?e.toFixed(0)+"s":e<3600?(e/60).toFixed(1)+"m":(e/3600).toFixed(1)+"h"}_escapeHtml(e){if(!e)return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}_renderFilters(){return`
|
|
4724
4737
|
<div class="filters">
|
|
4725
4738
|
<div class="filter-group">
|
|
4726
4739
|
<label>Time Range</label>
|
|
4727
4740
|
<select id="time-range-select" class="filter-select">
|
|
4728
|
-
${
|
|
4741
|
+
${bt.map(e=>`
|
|
4729
4742
|
<option value="${e.id}" ${this._timeRange===e.id?"selected":""}>${e.label}</option>
|
|
4730
4743
|
`).join("")}
|
|
4731
4744
|
</select>
|
|
@@ -4733,7 +4746,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
4733
4746
|
<div class="filter-group">
|
|
4734
4747
|
<label>Signal Type</label>
|
|
4735
4748
|
<select id="signal-type-select" class="filter-select">
|
|
4736
|
-
${
|
|
4749
|
+
${ft.map(e=>`
|
|
4737
4750
|
<option value="${e.id}" ${this._signalType===e.id?"selected":""}>${e.label}</option>
|
|
4738
4751
|
`).join("")}
|
|
4739
4752
|
</select>
|
|
@@ -4741,7 +4754,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
4741
4754
|
<div class="filter-group">
|
|
4742
4755
|
<label>Source</label>
|
|
4743
4756
|
<select id="source-select" class="filter-select">
|
|
4744
|
-
${
|
|
4757
|
+
${kt.map(e=>`
|
|
4745
4758
|
<option value="${e.id}" ${this._source===e.id?"selected":""}>${e.label}</option>
|
|
4746
4759
|
`).join("")}
|
|
4747
4760
|
</select>
|
|
@@ -4823,7 +4836,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
4823
4836
|
</div>
|
|
4824
4837
|
</div>
|
|
4825
4838
|
</div>
|
|
4826
|
-
`}_renderTrendChart(){if(!this._trends||!this._trends.dataPoints||this._trends.dataPoints.length===0)return'<div class="chart-empty">No trend data available</div>';let{dataPoints:e,maxValue:t}=this._trends,i=120,a=400,s=20,r=e.map((n,l)=>{let
|
|
4839
|
+
`}_renderTrendChart(){if(!this._trends||!this._trends.dataPoints||this._trends.dataPoints.length===0)return'<div class="chart-empty">No trend data available</div>';let{dataPoints:e,maxValue:t}=this._trends,i=120,a=400,s=20,r=e.map((n,l)=>{let c=s+l/(e.length-1||1)*(a-s*2),p=i-s-n.count/(t||1)*(i-s*2);return`${c},${p}`}).join(" "),o=`${s},${i-s} ${r} ${a-s},${i-s}`;return`
|
|
4827
4840
|
<div class="trend-chart">
|
|
4828
4841
|
<div class="chart-header">
|
|
4829
4842
|
<span class="chart-title">Signal Volume Over Time</span>
|
|
@@ -4841,7 +4854,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
4841
4854
|
<polyline points="${r}" fill="none" stroke="var(--loki-accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4842
4855
|
|
|
4843
4856
|
<!-- Data points -->
|
|
4844
|
-
${e.map((n,l)=>{let
|
|
4857
|
+
${e.map((n,l)=>{let c=s+l/(e.length-1||1)*(a-s*2),p=i-s-n.count/(t||1)*(i-s*2);return`<circle cx="${c}" cy="${p}" r="3" fill="var(--loki-accent)" />`}).join("")}
|
|
4845
4858
|
</svg>
|
|
4846
4859
|
<div class="chart-labels">
|
|
4847
4860
|
${e.length>0?`
|
|
@@ -5732,7 +5745,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
5732
5745
|
${t}
|
|
5733
5746
|
</div>
|
|
5734
5747
|
</div>
|
|
5735
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.getElementById("time-range-select");e&&e.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let t=this.shadowRoot.getElementById("signal-type-select");t&&t.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let i=this.shadowRoot.getElementById("source-select");i&&i.addEventListener("change",r=>this._setFilter("source",r.target.value));let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("close-detail");s&&s.addEventListener("click",()=>this._closeDetail()),this.shadowRoot.querySelectorAll(".list-item").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.type,n=r.dataset.id,l=this._findItemData(o,n);l&&this._selectMetric(o,l)}),r.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r.click())})})}_findItemData(e,t){if(!this._metrics?.aggregation)return null;switch(e){case"preference":return this._metrics.aggregation.preferences?.find(i=>i.preference_key===t);case"error_pattern":return this._metrics.aggregation.error_patterns?.find(i=>i.error_type===t);case"success_pattern":return this._metrics.aggregation.success_patterns?.find(i=>i.pattern_name===t);case"tool_efficiency":return this._metrics.aggregation.tool_efficiencies?.find(i=>i.tool_name===t);default:return null}}};customElements.get("loki-learning-dashboard")||customElements.define("loki-learning-dashboard",V);var
|
|
5748
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.getElementById("time-range-select");e&&e.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let t=this.shadowRoot.getElementById("signal-type-select");t&&t.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let i=this.shadowRoot.getElementById("source-select");i&&i.addEventListener("change",r=>this._setFilter("source",r.target.value));let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("close-detail");s&&s.addEventListener("click",()=>this._closeDetail()),this.shadowRoot.querySelectorAll(".list-item").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.type,n=r.dataset.id,l=this._findItemData(o,n);l&&this._selectMetric(o,l)}),r.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r.click())})})}_findItemData(e,t){if(!this._metrics?.aggregation)return null;switch(e){case"preference":return this._metrics.aggregation.preferences?.find(i=>i.preference_key===t);case"error_pattern":return this._metrics.aggregation.error_patterns?.find(i=>i.error_type===t);case"success_pattern":return this._metrics.aggregation.success_patterns?.find(i=>i.pattern_name===t);case"tool_efficiency":return this._metrics.aggregation.tool_efficiencies?.find(i=>i.tool_name===t);default:return null}}};customElements.get("loki-learning-dashboard")||customElements.define("loki-learning-dashboard",V);var xt=[{id:"overview",label:"Overview"},{id:"decisions",label:"Decision Log"},{id:"convergence",label:"Convergence"},{id:"agents",label:"Agents"}],Y=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._activeTab="overview",this._pollInterval=null,this._councilState=null,this._verdicts=[],this._convergence=[],this._agents=[],this._selectedAgent=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_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[t,i,a,s]=await Promise.allSettled([this._api._get("/api/council/state"),this._api._get("/api/council/verdicts"),this._api._get("/api/council/convergence"),this._api._get("/api/agents")]);t.status==="fulfilled"&&(this._councilState=t.value),i.status==="fulfilled"&&(this._verdicts=i.value.verdicts||[]),a.status==="fulfilled"&&(this._convergence=a.value.dataPoints||[]),s.status==="fulfilled"&&(this._agents=Array.isArray(s.value)?s.value:[]),this._error=null}catch(t){this._error=t.message}let e=JSON.stringify({s:this._councilState,v:this._verdicts,c:this._convergence,a:this._agents,e:this._error});e!==this._lastDataHash&&(this._lastDataHash=e,this.render())}async _forceReview(){try{await this._api._post("/api/council/force-review"),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"force-review"},bubbles:!0}))}catch(e){this._error=`Failed to force review: ${e.message}`,this.render()}}async _killAgent(e){if(confirm(`Kill agent ${e}?`))try{await this._api._post(`/api/agents/${e}/kill`),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"kill-agent",agentId:e},bubbles:!0})),await this._loadData()}catch(t){this._error=`Failed to kill agent: ${t.message}`,this.render()}}async _pauseAgent(e){try{await this._api._post(`/api/agents/${e}/pause`),await this._loadData()}catch(t){this._error=`Failed to pause agent: ${t.message}`,this.render()}}async _resumeAgent(e){try{await this._api._post(`/api/agents/${e}/resume`),await this._loadData()}catch(t){this._error=`Failed to resume agent: ${t.message}`,this.render()}}_setTab(e){this._activeTab=e,this.render()}_selectAgent(e){this._selectedAgent=this._selectedAgent?.id===e.id?null:e,this.render()}render(){let e=this.shadowRoot;e&&(this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null),e.innerHTML=`
|
|
5736
5749
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
5737
5750
|
<div class="council-dashboard">
|
|
5738
5751
|
<div class="council-header">
|
|
@@ -5746,7 +5759,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
5746
5759
|
</div>
|
|
5747
5760
|
|
|
5748
5761
|
<div class="tabs">
|
|
5749
|
-
${
|
|
5762
|
+
${xt.map(t=>`
|
|
5750
5763
|
<button
|
|
5751
5764
|
class="tab ${this._activeTab===t.id?"active":""}"
|
|
5752
5765
|
data-tab="${t.id}"
|
|
@@ -6319,7 +6332,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6319
6332
|
color: var(--loki-error);
|
|
6320
6333
|
font-size: 12px;
|
|
6321
6334
|
}
|
|
6322
|
-
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",Y);var
|
|
6335
|
+
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",Y);var Ge={critical:0,major:1,minor:2},_t={critical:"var(--loki-status-error, #ef4444)",major:"var(--loki-status-warning, #f59e0b)",minor:"var(--loki-text-muted, #71717a)"},W=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._checklist=null,this._waivers=[],this._expandedCategories=new Set,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_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[e,t]=await Promise.all([this._api.getChecklist(),this._api.getChecklistWaivers().catch(()=>null)]),i=JSON.stringify(t),a=JSON.stringify(e)+i;if(a===this._lastDataHash)return;this._lastDataHash=a,this._checklist=e,this._waivers=t&&t.waivers?t.waivers.filter(s=>s.active):[],this._error=null,this.render()}catch(e){this._error=`Failed to load checklist: ${e.message}`,this.render()}}_isItemWaived(e){return this._waivers.some(t=>t.item_id===e)}_getWaiverForItem(e){return this._waivers.find(t=>t.item_id===e)||null}async _waiveItem(e){let t=window.prompt("Enter reason for waiving this item:");if(t)try{await this._api.addChecklistWaiver(e,t),this._lastDataHash=null,await this._loadData()}catch(i){this._error=`Failed to add waiver: ${i.message}`,this.render()}}async _unwaiveItem(e){try{await this._api.removeChecklistWaiver(e),this._lastDataHash=null,await this._loadData()}catch(t){this._error=`Failed to remove waiver: ${t.message}`,this.render()}}_toggleCategory(e){this._expandedCategories.has(e)?this._expandedCategories.delete(e):this._expandedCategories.add(e),this.render()}_getStyles(){return`
|
|
6323
6336
|
.checklist-viewer {
|
|
6324
6337
|
padding: 16px;
|
|
6325
6338
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -6608,7 +6621,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6608
6621
|
</div>
|
|
6609
6622
|
${i?`<div class="category-body">${this._renderItems(a)}</div>`:""}
|
|
6610
6623
|
</div>
|
|
6611
|
-
`}).join(""):this._renderEmpty()}_renderItems(e){return e?.length?[...e].sort((i,a)=>(
|
|
6624
|
+
`}).join(""):this._renderEmpty()}_renderItems(e){return e?.length?[...e].sort((i,a)=>(Ge[i.priority]??2)-(Ge[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=_t[s],o=i.verification||[],n=this._getWaiverForItem(i.id),l=!!n,c=i.status==="failing"&&(s==="critical"||s==="major"),p=l?`<span class="item-waived-badge" title="${this._escapeHtml(n.reason||"No reason provided")}">WAIVED</span>`:"",h="";return c&&(l?h=`<button class="waiver-btn waiver-btn-unwaive" data-unwaive-id="${this._escapeHtml(i.id)}">Unwaive</button>`:h=`<button class="waiver-btn" data-waive-id="${this._escapeHtml(i.id)}">Waive</button>`),`
|
|
6612
6625
|
<div class="item">
|
|
6613
6626
|
<div class="item-status ${a}"></div>
|
|
6614
6627
|
<div class="item-title">${this._escapeHtml(i.title||i.id||"?")}</div>
|
|
@@ -6624,7 +6637,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6624
6637
|
<p><strong>No checklist data yet.</strong></p>
|
|
6625
6638
|
<p class="hint">The spec checklist is generated during the first iteration. Start a session with <code>loki start ./spec.md</code> (PRD files also accepted) -- groups and items will appear here as the session progresses and can be expanded for details.</p>
|
|
6626
6639
|
</div>
|
|
6627
|
-
`}_attachEventListeners(){let e=this.shadowRoot;e&&(e.querySelectorAll(".category-header[data-category]").forEach(t=>{t.addEventListener("click",()=>this._toggleCategory(t.dataset.category))}),e.querySelectorAll("button[data-waive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(t.dataset.waiveId)})}),e.querySelectorAll("button[data-unwaive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(t.dataset.unwaiveId)})}))}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",W);var
|
|
6640
|
+
`}_attachEventListeners(){let e=this.shadowRoot;e&&(e.querySelectorAll(".category-header[data-category]").forEach(t=>{t.addEventListener("click",()=>this._toggleCategory(t.dataset.category))}),e.querySelectorAll("button[data-waive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(t.dataset.waiveId)})}),e.querySelectorAll("button[data-unwaive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(t.dataset.unwaiveId)})}))}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",W);var Ke={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}},Q=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._status=null,this._logs=[],this._lastDataHash=null,this._lastLogsHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_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,t]=await Promise.all([this._api.getAppRunnerStatus(),this._api.getAppRunnerLogs()]),i=JSON.stringify({status:e?.status,port:e?.port,restarts:e?.restart_count,url:e?.url,services:Array.isArray(e?.services)?e.services.map(r=>`${r?.url||""}|${r?.name||""}`).join(","):null}),a=JSON.stringify(t?.lines?.slice(-5)||[]),s=a!==this._lastLogsHash;if(i===this._lastDataHash&&!s)return;this._lastDataHash=i,this._lastLogsHash=a,this._status=e,this._logs=t?.lines||[],this._error=null,this.render(),this._scrollLogsToBottom()}catch(e){this._error||(this._error=`Failed to load app status: ${e.message}`,this.render())}}_scrollLogsToBottom(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(".log-area");t&&(t.scrollTop=t.scrollHeight)}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(e){this._error=`Restart failed: ${e.message}`,this.render()}}async _handleStop(){try{await this._api.stopApp(),this._loadData()}catch(e){this._error=`Stop failed: ${e.message}`,this.render()}}_formatUptime(e){if(!e)return"--";let t=new Date(e),a=Math.floor((new Date-t)/1e3);if(a<60)return`${a}s`;if(a<3600)return`${Math.floor(a/60)}m ${a%60}s`;let s=Math.floor(a/3600),r=Math.floor(a%3600/60);return`${s}h ${r}m`}_isValidUrl(e){if(!e)return!1;try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}_extraServices(e){if(!e||!Array.isArray(e.services))return[];let t=e.url||"",i=[],a=new Set;for(let s of e.services){if(!s||typeof s.url!="string"||!s.url||s.url===t||a.has(s.url))continue;a.add(s.url);let r=typeof s.name=="string"?s.name.trim():"",o=typeof s.role=="string"?s.role.trim():"",n=s.port!=null?String(s.port):"",l=r||o||(n?`Port ${n}`:"Service");i.push({url:s.url,label:l,urlValid:this._isValidUrl(s.url)})}return i}_getStyles(){return`
|
|
6628
6641
|
.app-status {
|
|
6629
6642
|
padding: 16px;
|
|
6630
6643
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -6800,7 +6813,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6800
6813
|
${i?"":this._renderEmpty()}
|
|
6801
6814
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
6802
6815
|
</div>
|
|
6803
|
-
`,this._attachEventListeners()}_renderStatusBadge(e){let t=e?.status||"not_initialized",i=
|
|
6816
|
+
`,this._attachEventListeners()}_renderStatusBadge(e){let t=e?.status||"not_initialized",i=Ke[t]||Ke.not_initialized;return`
|
|
6804
6817
|
<span class="status-badge" style="background: color-mix(in srgb, ${i.color} 15%, transparent); color: ${i.color}">
|
|
6805
6818
|
<span class="status-dot ${i.pulse?"pulse":""}" style="background: ${i.color}"></span>
|
|
6806
6819
|
${this._escapeHtml(i.label)}
|
|
@@ -6856,7 +6869,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6856
6869
|
<p>App runner not started</p>
|
|
6857
6870
|
<p class="hint">App runner will start after the first successful build iteration.</p>
|
|
6858
6871
|
</div>
|
|
6859
|
-
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector('[data-action="restart"]'),i=e.querySelector('[data-action="stop"]');t&&t.addEventListener("click",()=>this._handleRestart()),i&&i.addEventListener("click",()=>this._handleStop())}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-app-status",Q);var
|
|
6872
|
+
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector('[data-action="restart"]'),i=e.querySelector('[data-action="stop"]');t&&t.addEventListener("click",()=>this._handleRestart()),i&&i.addEventListener("click",()=>this._handleStop())}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-app-status",Q);var Ve={not_initialized:{color:"var(--loki-text-muted, #71717a)",label:"No app yet",pulse:!1},starting:{color:"var(--loki-yellow, #ca8a04)",label:"Starting",pulse:!0},running:{color:"var(--loki-green, #16a34a)",label:"Running",pulse:!0},stale:{color:"var(--loki-yellow, #ca8a04)",label:"Stale",pulse:!1},completed:{color:"var(--loki-text-muted, #a1a1aa)",label:"Completed",pulse:!1},failed:{color:"var(--loki-red, #dc2626)",label:"Could not start",pulse:!1},crashed:{color:"var(--loki-red, #dc2626)",label:"Crashed",pulse:!1},stopped:{color:"var(--loki-text-muted, #a1a1aa)",label:"Stopped",pulse:!1},error:{color:"var(--loki-text-muted, #71717a)",label:"Status unavailable",pulse:!1},unknown:{color:"var(--loki-text-muted, #71717a)",label:"Unknown",pulse:!1}},X=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._pollInterval=null,this._visibilityHandler=null,this._status=null,this._errors=null,this._error=null,this._lastDataHash=null,this._detailsOpen=!1,this._iframeFailed=!1,this._iframeLoadTimer=null,this._IFRAME_LOAD_TIMEOUT_MS=6e3,this._activeServiceKey=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this.render(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._clearIframeLoadTimer()}_clearIframeLoadTimer(){this._iframeLoadTimer&&(clearTimeout(this._iframeLoadTimer),this._iframeLoadTimer=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_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 this._api.getAppRunnerStatus(),t=e?.status||"not_initialized",i=null;if(t==="crashed"||t==="failed")try{i=await this._api.getAppRunnerErrors(50)}catch{i=null}let a=JSON.stringify({status:t,port:e?.port,url:e?.url,crash:e?.crash_count,errLen:i?.lines?.length||0,extMgd:e?.externally_managed===!0,source:e?.source||null,healthOk:e?.last_health?.ok===!0?"ok":e?.last_health?.ok===!1?"down":"unknown",services:Array.isArray(e?.services)?e.services.map(r=>`${r?.url||""}|${r?.role||""}|${r?.name||""}`).join(","):null}),s=this._error!==null;if(a===this._lastDataHash&&!s)return;this._iframeFailed=!1,this._lastDataHash=a,this._status=e,this._errors=i,this._error=null,this.render()}catch(e){this._error||(this._error=`Could not read app status: ${e.message}`,this.render())}}_isValidUrl(e){if(!e)return!1;try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}_getServices(){let e=this._status;if(!e)return[];let t=Array.isArray(e.services)&&e.services.length>0?e.services:[{url:e.url,role:"",name:e.primary_service||"",port:e.port}],i=new Set,a=[];for(let s of t){if(!s||!this._isValidUrl(s.url))continue;let r=typeof s.name=="string"?s.name.trim():"",o=s.port!=null?String(s.port):"",n=this._inferServiceRole(s.role,r),l=s.url||r||o;if(i.has(l))continue;i.add(l);let c=r;c||(c=n==="api"?"API":n==="ui"?"UI":""),c||(c=o?`Port ${o}`:"Service"),a.push({key:l,url:s.url,role:n,name:r,port:o,label:c})}return a}_inferServiceRole(e,t){let i=typeof e=="string"?e.trim().toLowerCase():"";if(i==="ui"||i==="web"||i==="frontend")return"ui";if(i==="api"||i==="backend"||i==="server")return"api";let a=(t||"").toLowerCase();return/\b(api|backend|server|graphql|grpc)\b/.test(a)||a.includes("api")?"api":""}_activeService(e){if(!e||e.length===0)return null;if(this._activeServiceKey){let t=e.find(i=>i.key===this._activeServiceKey);if(t)return t}return e[0]}_handleSelectService(e){this._activeServiceKey!==e&&(this._activeServiceKey=e,this._iframeFailed=!1,this.render())}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(e){this._error=`Restart failed: ${e.message}`,this.render()}}_currentTargetUrl(){let e=this._activeService(this._getServices());if(e&&this._isValidUrl(e.url))return e.url;let t=this._status;return t&&this._isValidUrl(t.url)?t.url:""}_handleRefresh(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector("iframe.preview-frame"),i=this._currentTargetUrl();if(t&&i){this._iframeFailed=!1,this._clearIframeLoadTimer();let a=(i.includes("?")?"&":"?")+"_t="+Date.now();t.src=i+a,this._armIframeLoadDetection()}}_handleRetryFrame(){this._iframeFailed=!1,this._lastDataHash=null,this.render(),this._loadData()}_handleOpenExternal(){let e=this._currentTargetUrl();e&&window.open(e,"_blank","noopener")}_toggleDetails(){this._detailsOpen=!this._detailsOpen,this.render()}_getStyles(){return`
|
|
6860
6873
|
.preview { padding: 16px; font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif); color: var(--loki-text-primary, #201515); display: flex; flex-direction: column; width: 100%; box-sizing: border-box; }
|
|
6861
6874
|
.header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; gap: 12px; flex-wrap: wrap; }
|
|
6862
6875
|
.header-left { display: flex; align-items: center; gap: 10px; }
|
|
@@ -6906,7 +6919,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6906
6919
|
.details-toggle:hover { text-decoration: underline; }
|
|
6907
6920
|
.details-body { margin-top: 8px; background: var(--loki-bg-code, #1e1e1e); color: #d4d4d4; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; padding: 10px; border-radius: 6px; max-height: 200px; overflow: auto; white-space: pre-wrap; }
|
|
6908
6921
|
.error-banner { margin-top: 12px; padding: 10px 12px; border-radius: 6px; background: color-mix(in srgb, var(--loki-red, #dc2626) 10%, transparent); color: var(--loki-red, #dc2626); font-size: 13px; }
|
|
6909
|
-
`}_effectiveView(e,t){let i=this._status,a=i?.last_health,s=a&&typeof a.ok=="boolean"?a.ok:null;if(e==="running"&&t&&(i?.externally_managed===!0||i?.source==="discovered"))return{view:"running",healthOk:s};if(e==="running"&&t){if(s===!1)return{view:"starting",healthOk:s};if(s===!0)return{view:"running",healthOk:s};let r=i?.started_at?Date.parse(i.started_at):NaN;return{view:Number.isFinite(r)&&Date.now()-r<15e3?"running":"starting",healthOk:s}}return{view:e,healthOk:s}}render(){let e=this.shadowRoot;if(!e)return;this._clearIframeLoadTimer();let t=this._status,i=t?.status||"not_initialized",a=this._getServices(),s=this._activeService(a),r=a.length>1,o=s?.url||t?.url,n=this._isValidUrl(o),{view:l,healthOk:
|
|
6922
|
+
`}_effectiveView(e,t){let i=this._status,a=i?.last_health,s=a&&typeof a.ok=="boolean"?a.ok:null;if(e==="running"&&t&&(i?.externally_managed===!0||i?.source==="discovered"))return{view:"running",healthOk:s};if(e==="running"&&t){if(s===!1)return{view:"starting",healthOk:s};if(s===!0)return{view:"running",healthOk:s};let r=i?.started_at?Date.parse(i.started_at):NaN;return{view:Number.isFinite(r)&&Date.now()-r<15e3?"running":"starting",healthOk:s}}return{view:e,healthOk:s}}render(){let e=this.shadowRoot;if(!e)return;this._clearIframeLoadTimer();let t=this._status,i=t?.status||"not_initialized",a=this._getServices(),s=this._activeService(a),r=a.length>1,o=s?.url||t?.url,n=this._isValidUrl(o),{view:l,healthOk:c}=this._effectiveView(i,n),p=t?.externally_managed===!0||t?.source==="discovered",h=Ve[l]||Ve.not_initialized,b=i==="running"&&c===!1?"Starting / not responding yet":h.label;e.innerHTML=`
|
|
6910
6923
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
6911
6924
|
<div class="preview">
|
|
6912
6925
|
<div class="header">
|
|
@@ -6923,7 +6936,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6923
6936
|
<p class="transport">${p?"Detected running app":"Running locally"} - <a href="${this._escapeHtml(o)}" target="_blank" rel="noopener noreferrer">${this._escapeHtml(o)}</a>${p?' <span style="color: var(--loki-text-muted, #71717a);">(managed outside Loki)</span>':""}</p>
|
|
6924
6937
|
`:""}
|
|
6925
6938
|
${r&&(l==="running"||l==="starting")?this._renderServiceTabs(a,s):""}
|
|
6926
|
-
${this._renderSurface(l,n,
|
|
6939
|
+
${this._renderSurface(l,n,c,p,s,r)}
|
|
6927
6940
|
${this._renderErrorBanner(i)}
|
|
6928
6941
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
6929
6942
|
</div>
|
|
@@ -6976,7 +6989,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6976
6989
|
title="Live preview of the running app"></iframe>
|
|
6977
6990
|
</div>
|
|
6978
6991
|
<p class="transport" style="margin-top: 8px;">Not rendering? Some apps block being embedded. Use "Open in browser" above.</p>
|
|
6979
|
-
`}if(e==="starting"){let o=i===!1,n=o?"App is up but not responding yet":"Starting your app...",l=o?"The process started but is not answering requests yet. This can take a few seconds, or it may mean the app is still booting or failing to bind its port.":"Waiting for the app to respond. This usually takes a few seconds.",
|
|
6992
|
+
`}if(e==="starting"){let o=i===!1,n=o?"App is up but not responding yet":"Starting your app...",l=o?"The process started but is not answering requests yet. This can take a few seconds, or it may mean the app is still booting or failing to bind its port.":"Waiting for the app to respond. This usually takes a few seconds.",c=t?`
|
|
6980
6993
|
<div class="err-actions" style="justify-content: center; margin-top: 12px;">
|
|
6981
6994
|
<button class="btn" data-action="open-external">Open in browser</button>
|
|
6982
6995
|
<button class="btn" data-action="retry-frame">Retry</button>
|
|
@@ -6986,7 +6999,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
6986
6999
|
<div class="spinner"></div>
|
|
6987
7000
|
<h3>${this._escapeHtml(n)}</h3>
|
|
6988
7001
|
<p>${this._escapeHtml(l)}</p>
|
|
6989
|
-
${
|
|
7002
|
+
${c}
|
|
6990
7003
|
</div>
|
|
6991
7004
|
`}return e==="stale"?`
|
|
6992
7005
|
<div class="state-block">
|
|
@@ -7027,7 +7040,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
7027
7040
|
</button>
|
|
7028
7041
|
${this._detailsOpen?`<div class="details-body">${s}</div>`:""}
|
|
7029
7042
|
</div>
|
|
7030
|
-
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=(i,a)=>{let s=e.querySelector(i);s&&s.addEventListener("click",a)};e.querySelectorAll('[data-action="restart"]').forEach(i=>i.addEventListener("click",()=>this._handleRestart())),e.querySelectorAll('[data-action="open-external"]').forEach(i=>i.addEventListener("click",()=>this._handleOpenExternal())),e.querySelectorAll('[data-action="retry-frame"]').forEach(i=>i.addEventListener("click",()=>this._handleRetryFrame())),t('[data-action="refresh"]',()=>this._handleRefresh()),t('[data-action="toggle-details"]',()=>this._toggleDetails()),e.querySelectorAll('[data-action="select-service"]').forEach(i=>i.addEventListener("click",()=>this._handleSelectService(i.getAttribute("data-service-key"))))}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}};customElements.define("loki-app-preview",X);var
|
|
7043
|
+
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=(i,a)=>{let s=e.querySelector(i);s&&s.addEventListener("click",a)};e.querySelectorAll('[data-action="restart"]').forEach(i=>i.addEventListener("click",()=>this._handleRestart())),e.querySelectorAll('[data-action="open-external"]').forEach(i=>i.addEventListener("click",()=>this._handleOpenExternal())),e.querySelectorAll('[data-action="retry-frame"]').forEach(i=>i.addEventListener("click",()=>this._handleRetryFrame())),t('[data-action="refresh"]',()=>this._handleRefresh()),t('[data-action="toggle-details"]',()=>this._toggleDetails()),e.querySelectorAll('[data-action="select-service"]').forEach(i=>i.addEventListener("click",()=>this._handleSelectService(i.getAttribute("data-service-key"))))}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}};customElements.define("loki-app-preview",X);var yt={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"}},Z=class extends u{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={...yt}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadPricing(),this._loadCost(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadCost()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadPricing(){try{let e=await this._api.getPricing();if(e&&e.models){let t={};for(let[i,a]of Object.entries(e.models))t[i]={input:a.input,output:a.output,label:a.label||i,provider:a.provider||"unknown"};this._modelPricing=t,this._pricingSource=e.source||"api",this._pricingDate=e.updated||"",this._activeProvider=e.provider||"claude",this.render()}}catch{}}async _loadCost(){try{let e=await this._api.getCost();this._updateFromCost(e)}catch{this._data.connected=!1,this.render()}}_updateFromCost(e){e&&(this._data={...this._data,connected:!0,total_input_tokens:e.total_input_tokens||0,total_output_tokens:e.total_output_tokens||0,estimated_cost_usd:e.estimated_cost_usd||0,by_phase:e.by_phase||{},by_model:e.by_model||{},budget_limit:e.budget_limit,budget_used:e.budget_used||0,budget_remaining:e.budget_remaining},this.render())}_startPolling(){this._pollInterval=setInterval(async()=>{try{let e=await this._api.getCost();this._updateFromCost(e)}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 e=await this._api.getCost();this._updateFromCost(e)}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(e){return!e||e===0?"0":e>=1e6?(e/1e6).toFixed(2)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}_formatUSD(e){return!e||e===0?"$0.00":e<.01?"<$0.01":"$"+e.toFixed(2)}_getBudgetPercent(){return!this._data.budget_limit||this._data.budget_limit<=0?0:Math.min(100,this._data.budget_used/this._data.budget_limit*100)}_getBudgetStatusClass(){let e=this._getBudgetPercent();return e>=90?"critical":e>=70?"warning":"ok"}_renderPhaseRows(){let e=this._data.by_phase;return!e||Object.keys(e).length===0?'<tr><td colspan="4" class="empty-cell">No phase data yet</td></tr>':Object.entries(e).map(([t,i])=>{let a=i.input_tokens||0,s=i.output_tokens||0,r=i.cost_usd||0;return`
|
|
7031
7044
|
<tr>
|
|
7032
7045
|
<td class="phase-name">${this._escapeHTML(t)}</td>
|
|
7033
7046
|
<td class="mono-cell">${this._formatTokens(a)}</td>
|
|
@@ -7472,7 +7485,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
7472
7485
|
<div class="card-header">
|
|
7473
7486
|
<div class="header-tags">
|
|
7474
7487
|
${t?`<span class="checkpoint-sha mono">${this._escapeHTML(t)}</span>`:""}
|
|
7475
|
-
${l.map(
|
|
7488
|
+
${l.map(c=>`<span class="checkpoint-tag">${this._escapeHTML(c)}</span>`).join("")}
|
|
7476
7489
|
</div>
|
|
7477
7490
|
<span class="checkpoint-time">${this._formatRelativeTime(e.created_at)}</span>
|
|
7478
7491
|
</div>
|
|
@@ -7861,7 +7874,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
7861
7874
|
<div class="legend-item"><span class="legend-swatch swatch-cache-read"></span> Cache Read</div>
|
|
7862
7875
|
<div class="legend-item"><span class="legend-swatch swatch-cache-create"></span> Cache Creation</div>
|
|
7863
7876
|
</div>
|
|
7864
|
-
`,a="";for(let s of e){let r=s.input_tokens||0,o=s.output_tokens||0,n=s.cache_read_tokens||0,l=s.cache_creation_tokens||0,
|
|
7877
|
+
`,a="";for(let s of e){let r=s.input_tokens||0,o=s.output_tokens||0,n=s.cache_read_tokens||0,l=s.cache_creation_tokens||0,c=r+o+n+l,p=t>0?r/t*100:0,h=t>0?o/t*100:0,b=t>0?n/t*100:0,m=t>0?l/t*100:0;a+=`
|
|
7865
7878
|
<div class="breakdown-row">
|
|
7866
7879
|
<div class="breakdown-iter">#${s.iteration}</div>
|
|
7867
7880
|
<div class="breakdown-bar-container">
|
|
@@ -8271,7 +8284,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
8271
8284
|
|
|
8272
8285
|
${e}
|
|
8273
8286
|
</div>
|
|
8274
|
-
`,this.shadowRoot.querySelectorAll(".tab").forEach(t=>{t.addEventListener("click",()=>{this._setTab(t.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",te);var
|
|
8287
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(t=>{t.addEventListener("click",()=>{this._setTab(t.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",te);var He={critical:"var(--loki-red, #ef4444)",warning:"var(--loki-yellow, #eab308)",info:"var(--loki-blue, #3b82f6)",success:"var(--loki-green, #1FC5A8)"},Ye={build:{label:"Build",icon:"B"},quality:{label:"Quality",icon:"Q"},system:{label:"System",icon:"S"},security:{label:"Security",icon:"!"}},ie=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._notifications=[],this._triggers=[],this._summary={},this._connected=!1,this._activeTab="feed",this._categoryFilter="all",this._panelOpen=!0,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._loadNotifications(),this._loadTriggers(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&(this._loadNotifications(),this._loadTriggers()),e==="theme"&&this._applyTheme())}async _loadNotifications(){try{let e=this.getAttribute("api-url")||window.location.origin,t=await fetch(e+"/api/notifications");if(t.ok){let i=await t.json();this._notifications=i.notifications||[],this._summary=i.summary||{},this._connected=!0}}catch{this._connected=!1}this.render()}async _loadTriggers(){try{let e=this.getAttribute("api-url")||window.location.origin,t=await fetch(e+"/api/notifications/triggers");if(t.ok){let i=await t.json();this._triggers=i.triggers||[]}}catch{}}async _acknowledgeNotification(e){let t=this.getAttribute("api-url")||window.location.origin;try{await fetch(t+"/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{method:"POST"})}catch{}this._loadNotifications()}async _unacknowledgeNotification(e){let t=this.getAttribute("api-url")||window.location.origin;await fetch(t+"/api/notifications/"+encodeURIComponent(e)+"/unacknowledge",{method:"POST"}),this._loadNotifications()}async _acknowledgeAll(){let e=this.getAttribute("api-url")||window.location.origin,t=this._notifications.filter(i=>!i.acknowledged);for(let i of t)await fetch(e+"/api/notifications/"+encodeURIComponent(i.id)+"/acknowledge",{method:"POST"});this._loadNotifications()}async _toggleTrigger(e,t){let i=this.getAttribute("api-url")||window.location.origin,a=this._triggers.map(s=>s.id===e?{...s,enabled:t}:s);await fetch(i+"/api/notifications/triggers",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({triggers:a})}),this._triggers=a,this.render()}_startPolling(){this._pollInterval=setInterval(()=>{this._loadNotifications(),this._loadTriggers()},5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_formatTime(e){if(!e)return"";try{let t=new Date(e),a=new Date-t,s=Math.floor(a/1e3),r=Math.floor(s/60),o=Math.floor(r/60),n=Math.floor(o/24);return s<60?s+"s ago":r<60?r+"m ago":o<24?o+"h ago":n<7?n+"d ago":t.toLocaleDateString()}catch{return String(e)}}_getTimeGroup(e){if(!e)return"Other";try{let t=new Date(e),i=new Date,a=new Date(i.getFullYear(),i.getMonth(),i.getDate()),s=new Date(a);s.setDate(s.getDate()-1);let r=new Date(a);return r.setDate(r.getDate()-7),t>=a?"Today":t>=s?"Yesterday":t>=r?"This Week":"Earlier"}catch{return"Other"}}_escapeHTML(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getSeverityColor(e){return He[e]||He.info}_getCategory(e){return e.category||e.type||"system"}_switchTab(e){this._activeTab=e,this.render()}_setCategoryFilter(e){this._categoryFilter=e,this.render()}_togglePanel(){this._panelOpen=!this._panelOpen,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".tab").forEach(a=>{a.addEventListener("click",()=>{this._switchTab(a.dataset.tab)})}),e.querySelectorAll(".cat-btn").forEach(a=>{a.addEventListener("click",()=>{this._setCategoryFilter(a.dataset.cat)})}),e.querySelectorAll(".ack-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._acknowledgeNotification(a.dataset.id)})}),e.querySelectorAll(".unread-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._unacknowledgeNotification(a.dataset.id)})});let t=e.querySelector(".ack-all-btn");t&&t.addEventListener("click",()=>{this._acknowledgeAll()});let i=e.querySelector(".bell-icon");i&&i.addEventListener("click",()=>{this._togglePanel()}),e.querySelectorAll(".toggle input").forEach(a=>{a.addEventListener("change",()=>{this._toggleTrigger(a.dataset.triggerId,a.checked)})}),e.querySelectorAll(".dismiss-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._acknowledgeNotification(a.dataset.id)})})}_renderBellIcon(){let e=this._summary.unacknowledged||0;return`
|
|
8275
8288
|
<div class="bell-container">
|
|
8276
8289
|
<button class="bell-icon" title="${e} unread notifications">
|
|
8277
8290
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -8294,7 +8307,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
8294
8307
|
</div>
|
|
8295
8308
|
<div class="summary-card">
|
|
8296
8309
|
<div class="card-label">Critical</div>
|
|
8297
|
-
<div class="card-value" style="color: ${
|
|
8310
|
+
<div class="card-value" style="color: ${He.critical}">${i}</div>
|
|
8298
8311
|
</div>
|
|
8299
8312
|
</div>
|
|
8300
8313
|
${t>0?`
|
|
@@ -8303,12 +8316,12 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
8303
8316
|
</div>
|
|
8304
8317
|
`}_renderCategoryFilter(){return`
|
|
8305
8318
|
<div class="category-bar">
|
|
8306
|
-
${["all","build","quality","system","security"].map(t=>{let i=this._categoryFilter===t,a=t==="all"?"All":
|
|
8319
|
+
${["all","build","quality","system","security"].map(t=>{let i=this._categoryFilter===t,a=t==="all"?"All":Ye[t]?.label||t;return`<button class="cat-btn ${i?"active":""}" data-cat="${t}">${a}</button>`}).join("")}
|
|
8307
8320
|
</div>
|
|
8308
|
-
`}_renderNotificationList(){let e=[...this._notifications].sort((s,r)=>new Date(r.timestamp)-new Date(s.timestamp));if(this._categoryFilter!=="all"&&(e=e.filter(s=>this._getCategory(s)===this._categoryFilter)),e.length===0)return'<div class="empty-state">No notifications</div>';let t={};for(let s of e){let r=this._getTimeGroup(s.timestamp);t[r]||(t[r]=[]),t[r].push(s)}let i=["Today","Yesterday","This Week","Earlier","Other"],a="";for(let s of i)!t[s]||t[s].length===0||(a+=`<div class="time-group-label">${s}</div>`,a+=t[s].map(r=>{let o=r.acknowledged,n=this._getSeverityColor(r.severity),l=this._getCategory(r),
|
|
8321
|
+
`}_renderNotificationList(){let e=[...this._notifications].sort((s,r)=>new Date(r.timestamp)-new Date(s.timestamp));if(this._categoryFilter!=="all"&&(e=e.filter(s=>this._getCategory(s)===this._categoryFilter)),e.length===0)return'<div class="empty-state">No notifications</div>';let t={};for(let s of e){let r=this._getTimeGroup(s.timestamp);t[r]||(t[r]=[]),t[r].push(s)}let i=["Today","Yesterday","This Week","Earlier","Other"],a="";for(let s of i)!t[s]||t[s].length===0||(a+=`<div class="time-group-label">${s}</div>`,a+=t[s].map(r=>{let o=r.acknowledged,n=this._getSeverityColor(r.severity),l=this._getCategory(r),c=Ye[l]||{label:l,icon:"?"};return`
|
|
8309
8322
|
<div class="notif-row ${o?"acknowledged":""}">
|
|
8310
8323
|
<span class="severity-dot" style="background: ${n};" title="${this._escapeHTML(r.severity)}"></span>
|
|
8311
|
-
<span class="cat-icon" title="${
|
|
8324
|
+
<span class="cat-icon" title="${c.label}">${c.icon}</span>
|
|
8312
8325
|
<span class="notif-time">${this._formatTime(r.timestamp)}</span>
|
|
8313
8326
|
<span class="notif-message">${this._escapeHTML(r.message)}</span>
|
|
8314
8327
|
${r.iteration!=null?`<span class="notif-iteration">iter ${r.iteration}</span>`:""}
|
|
@@ -9003,19 +9016,19 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
9003
9016
|
<div class="highlights-section">
|
|
9004
9017
|
<div class="section-label">Highlights</div>
|
|
9005
9018
|
<ul class="highlight-list">
|
|
9006
|
-
${r.map(
|
|
9019
|
+
${r.map(c=>`<li class="highlight-item">${this._escapeHtml(c)}</li>`).join("")}
|
|
9007
9020
|
</ul>
|
|
9008
9021
|
</div>
|
|
9009
9022
|
`);let l="";o.length>0&&(l=`
|
|
9010
9023
|
<div class="decisions-section">
|
|
9011
9024
|
<div class="section-label">Decisions</div>
|
|
9012
|
-
${o.map((
|
|
9025
|
+
${o.map((c,p)=>{let h=this._expandedDecisions.has(p);return`
|
|
9013
9026
|
<div class="decision-item">
|
|
9014
9027
|
<button class="decision-header" data-index="${p}">
|
|
9015
9028
|
<span class="decision-arrow ${h?"expanded":""}">▶</span>
|
|
9016
|
-
${this._escapeHtml(
|
|
9029
|
+
${this._escapeHtml(c.title||c.decision||"Decision")}
|
|
9017
9030
|
</button>
|
|
9018
|
-
${h?`<div class="decision-reasoning">${this._escapeHtml(
|
|
9031
|
+
${h?`<div class="decision-reasoning">${this._escapeHtml(c.reasoning||c.rationale||"No reasoning provided")}</div>`:""}
|
|
9019
9032
|
</div>
|
|
9020
9033
|
`}).join("")}
|
|
9021
9034
|
</div>
|
|
@@ -9054,7 +9067,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
9054
9067
|
${n}
|
|
9055
9068
|
${l}
|
|
9056
9069
|
</div>
|
|
9057
|
-
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(
|
|
9070
|
+
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(c=>{c.addEventListener("click",()=>{this._toggleDecision(parseInt(c.dataset.index))})})}};customElements.get("loki-session-diff")||customElements.define("loki-session-diff",ae);var se=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._error=null,this._loading=!0,this._optimizing=!1,this._api=null,this._pollInterval=null,this._expandedChanges=new Set}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadData(){try{this._data=await this._api._get("/api/prompt-versions"),this._error=null}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}async _triggerOptimize(){if(!this._optimizing){this._optimizing=!0,this.render();try{await this._api._post("/api/prompt-optimize?dry_run=false",{}),await this._loadData()}catch(e){this._error=e.message}this._optimizing=!1,this.render()}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),6e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_formatTime(e){if(!e)return"--";try{let t=new Date(e),a=new Date-t,s=Math.floor(a/6e4);if(s<1)return"Just now";if(s<60)return`${s}m ago`;let r=Math.floor(s/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}catch{return"--"}}_toggleChange(e){this._expandedChanges.has(e)?this._expandedChanges.delete(e):this._expandedChanges.add(e),this.render()}render(){let e=`
|
|
9058
9071
|
${this.getBaseStyles()}
|
|
9059
9072
|
|
|
9060
9073
|
:host {
|
|
@@ -9267,9 +9280,9 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
9267
9280
|
`;return}let t=this._data||{},i=t.version!=null?t.version:"--",a=this._formatTime(t.last_optimized),s=t.failures_analyzed!=null?t.failures_analyzed:"--",r=t.changes||[],o="";r.length>0&&(o=`
|
|
9268
9281
|
<div class="changes-section">
|
|
9269
9282
|
<div class="section-label">Changes</div>
|
|
9270
|
-
${r.map((l,
|
|
9283
|
+
${r.map((l,c)=>{let p=this._expandedChanges.has(c);return`
|
|
9271
9284
|
<div class="change-item">
|
|
9272
|
-
<button class="change-header" data-index="${
|
|
9285
|
+
<button class="change-header" data-index="${c}">
|
|
9273
9286
|
<span class="change-arrow ${p?"expanded":""}">▶</span>
|
|
9274
9287
|
${this._escapeHtml(l.description||l.title||"Change")}
|
|
9275
9288
|
</button>
|
|
@@ -9305,7 +9318,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
9305
9318
|
|
|
9306
9319
|
${o}
|
|
9307
9320
|
</div>
|
|
9308
|
-
`;let n=this.shadowRoot.getElementById("optimize-btn");n&&n.addEventListener("click",()=>this._triggerOptimize()),this.shadowRoot.querySelectorAll(".change-header").forEach(l=>{l.addEventListener("click",()=>{this._toggleChange(parseInt(l.dataset.index))})})}};customElements.get("loki-prompt-optimizer")||customElements.define("loki-prompt-optimizer",se);var re=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._history=[],this._error=null,this._loading=!0,this._scanning=!1,this._rigourAvailable=!0,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadData(){try{let[e,t]=await Promise.allSettled([this._api._get("/api/quality-score"),this._api._get("/api/quality-score/history")]);if(e.status==="fulfilled"){let i=e.value;i&&i.error&&i.error.includes("not installed")?(this._rigourAvailable=!1,this._data=null):(this._rigourAvailable=!0,this._data=i),this._error=null}else(e.reason?.message||"").includes("404")?(this._rigourAvailable=!1,this._data=null,this._error=null):(this._error="Failed to load quality score",this._data=null);if(t.status==="fulfilled"){let i=t.value;this._history=Array.isArray(i)?i.slice(-10):(i.scores||[]).slice(-10)}}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}async _triggerScan(){if(!this._scanning){this._scanning=!0,this.render();try{await this._api._post("/api/quality-scan",{},{timeout:3e5}),await this._loadData()}catch(e){this._error=e.message}this._scanning=!1,this.render()}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),6e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGrade(e){return e>=90?{grade:"A",color:"var(--loki-success)"}:e>=80?{grade:"B",color:"var(--loki-success)"}:e>=70?{grade:"C",color:"var(--loki-warning)"}:e>=60?{grade:"D",color:"var(--loki-warning)"}:{grade:"F",color:"var(--loki-error)"}}_renderSparkline(e){if(!e||e.length<2)return"";let t=e.map(
|
|
9321
|
+
`;let n=this.shadowRoot.getElementById("optimize-btn");n&&n.addEventListener("click",()=>this._triggerOptimize()),this.shadowRoot.querySelectorAll(".change-header").forEach(l=>{l.addEventListener("click",()=>{this._toggleChange(parseInt(l.dataset.index))})})}};customElements.get("loki-prompt-optimizer")||customElements.define("loki-prompt-optimizer",se);var re=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._history=[],this._error=null,this._loading=!0,this._scanning=!1,this._rigourAvailable=!0,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadData(){try{let[e,t]=await Promise.allSettled([this._api._get("/api/quality-score"),this._api._get("/api/quality-score/history")]);if(e.status==="fulfilled"){let i=e.value;i&&i.error&&i.error.includes("not installed")?(this._rigourAvailable=!1,this._data=null):(this._rigourAvailable=!0,this._data=i),this._error=null}else(e.reason?.message||"").includes("404")?(this._rigourAvailable=!1,this._data=null,this._error=null):(this._error="Failed to load quality score",this._data=null);if(t.status==="fulfilled"){let i=t.value;this._history=Array.isArray(i)?i.slice(-10):(i.scores||[]).slice(-10)}}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}async _triggerScan(){if(!this._scanning){this._scanning=!0,this.render();try{await this._api._post("/api/quality-scan",{},{timeout:3e5}),await this._loadData()}catch(e){this._error=e.message}this._scanning=!1,this.render()}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),6e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGrade(e){return e>=90?{grade:"A",color:"var(--loki-success)"}:e>=80?{grade:"B",color:"var(--loki-success)"}:e>=70?{grade:"C",color:"var(--loki-warning)"}:e>=60?{grade:"D",color:"var(--loki-warning)"}:{grade:"F",color:"var(--loki-error)"}}_renderSparkline(e){if(!e||e.length<2)return"";let t=e.map(c=>typeof c=="number"?c:c.score||0),i=Math.min(...t),s=Math.max(...t)-i||1,r=120,o=32,n=2,l=t.map((c,p)=>{let h=n+p/(t.length-1)*(r-n*2),b=n+(1-(c-i)/s)*(o-n*2);return`${h},${b}`}).join(" ");return`
|
|
9309
9322
|
<svg width="${r}" height="${o}" viewBox="0 0 ${r} ${o}" class="sparkline">
|
|
9310
9323
|
<polyline points="${l}" fill="none" stroke="var(--loki-accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9311
9324
|
<circle cx="${l.split(" ").pop().split(",")[0]}" cy="${l.split(" ").pop().split(",")[1]}" r="2.5" fill="var(--loki-accent)"/>
|
|
@@ -9602,7 +9615,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
9602
9615
|
</div>
|
|
9603
9616
|
<div class="empty-state">No quality data available</div>
|
|
9604
9617
|
</div>
|
|
9605
|
-
`;return}let t=this._data||{},i=t.score!=null?Math.round(t.score):0,{grade:a,color:s}=this._getGrade(i),r=t.categories||{},o=t.findings||{},n=["security","code_quality","compliance","best_practices"],l={security:"Security",code_quality:"Code Quality",compliance:"Compliance",best_practices:"Best Practices"},
|
|
9618
|
+
`;return}let t=this._data||{},i=t.score!=null?Math.round(t.score):0,{grade:a,color:s}=this._getGrade(i),r=t.categories||{},o=t.findings||{},n=["security","code_quality","compliance","best_practices"],l={security:"Security",code_quality:"Code Quality",compliance:"Compliance",best_practices:"Best Practices"},c=n.map(f=>{let x=r[f]!=null?Math.round(r[f]):0,w=x>=80?"var(--loki-success)":x>=60?"var(--loki-warning)":"var(--loki-error)";return`
|
|
9606
9619
|
<div class="category-item">
|
|
9607
9620
|
<span class="category-name">${l[f]||f}</span>
|
|
9608
9621
|
<div class="progress-bar">
|
|
@@ -9636,7 +9649,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
9636
9649
|
|
|
9637
9650
|
<div class="categories-section">
|
|
9638
9651
|
<div class="section-label">Categories</div>
|
|
9639
|
-
${
|
|
9652
|
+
${c}
|
|
9640
9653
|
</div>
|
|
9641
9654
|
|
|
9642
9655
|
${h?`
|
|
@@ -9646,12 +9659,12 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
9646
9659
|
</div>
|
|
9647
9660
|
`:""}
|
|
9648
9661
|
</div>
|
|
9649
|
-
`;let m=this.shadowRoot.getElementById("scan-btn");m&&m.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-score")||customElements.define("loki-quality-score",re);var
|
|
9662
|
+
`;let m=this.shadowRoot.getElementById("scan-btn");m&&m.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-score")||customElements.define("loki-quality-score",re);var We=["understand","guardrail","migrate","verify"],Qe={understand:"Understand",guardrail:"Guardrail",migrate:"Migrate",verify:"Verify"},wt={understand:"#5b9bd5",guardrail:"#e8b84a",migrate:"#5bb870",verify:"#5bc8c8"},oe=class extends u{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(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._fetchMigrations()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _fetchMigrations(){try{let e=await this._api._get("/api/migration/list");this._migrations=Array.isArray(e)?e:e.migrations||[],this._error=null;let t=this._migrations.find(i=>i.status==="in_progress"||i.status==="active");t?await this._fetchStatus(t.migration_id||t.id):this._migration=null}catch(e){this._error=e.message,this._migrations=[],this._migration=null}this._loading=!1,this.render()}async _fetchStatus(e){try{this._migration=await this._api._get(`/api/migration/${encodeURIComponent(e)}/status`),this._error=null}catch(t){this._error=t.message}}async _fetchData(){let e=this._migration&&(this._migration.migration_id||this._migration.id);e?(await this._fetchStatus(e),this.render()):await this._fetchMigrations()}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"):""}_getPhaseIcon(e,t,i){return(i||[]).includes(e)?"[x]":e===t?"[>]":"[ ]"}_getPhaseIndex(e){let t=We.indexOf(e);return t>=0?t:0}_renderPhaseBar(e,t){let i=t||[];return We.map(a=>{let s=i.includes(a),r=a===e,o=wt[a],n=s?"1":r?"0.7":"0.2",l=this._getPhaseIcon(a,e,t);return`
|
|
9650
9663
|
<div class="phase-segment">
|
|
9651
9664
|
<div class="phase-bar-fill" style="background:${o};opacity:${n};"></div>
|
|
9652
9665
|
<div class="phase-label">
|
|
9653
9666
|
<span class="phase-icon">${l}</span>
|
|
9654
|
-
${
|
|
9667
|
+
${Qe[a]}
|
|
9655
9668
|
</div>
|
|
9656
9669
|
</div>
|
|
9657
9670
|
`}).join("")}_renderFeatureStats(e){if(!e)return"";let t=e.passing||0,i=e.total||0,a=i>0?Math.round(t/i*100):0,s=a>=80?"var(--loki-success)":a>=50?"var(--loki-warning)":"var(--loki-error)";return`
|
|
@@ -10042,7 +10055,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
10042
10055
|
</div>
|
|
10043
10056
|
<div class="meta-item">
|
|
10044
10057
|
<span class="meta-label">Phase</span>
|
|
10045
|
-
<span>${
|
|
10058
|
+
<span>${Qe[o]||this._escapeHtml(o)}</span>
|
|
10046
10059
|
</div>
|
|
10047
10060
|
</div>
|
|
10048
10061
|
|
|
@@ -10069,11 +10082,11 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
10069
10082
|
<div class="section-label">Migrations</div>
|
|
10070
10083
|
${this._renderMigrationList()}
|
|
10071
10084
|
</div>
|
|
10072
|
-
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",oe);var
|
|
10085
|
+
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",oe);var $t=[["claude-opus","claude"],["claude-sonnet","claude"],["claude-haiku","claude"],["opus","claude"],["sonnet","claude"],["haiku","claude"],["claude","claude"],["gpt-4","codex"],["gpt-5","codex"],["gpt","codex"],["codex","codex"],["o1","codex"],["o3","codex"],["cline","cline"],["aider","aider"]];function Et(d){if(d==null)return null;switch(d%4){case 0:return{tier:"planning",model:"opus",provider:"claude"};case 1:return{tier:"development",model:"sonnet",provider:"claude"};case 2:return{tier:"development",model:"sonnet",provider:"claude"};case 3:return{tier:"fast",model:"haiku",provider:"claude"};default:return{tier:"development",model:"sonnet",provider:"claude"}}}function Ct(d,e){if(e!=null){let i=Et(e);if(i)return i.provider}let t=(d||"").toLowerCase();for(let[i,a]of $t)if(t.includes(i))return a;return"unknown"}var ne=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._pollInterval=null,this._activeTab="heatmap",this._activity=[],this._tools=[],this._cost={},this._context={},this._trends=[],this._toolTimeRange="7d",this._connected=!1,this._loading=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _fetchActivity(){let e=this._api.baseUrl||window.location.origin,t=new AbortController,i=setTimeout(()=>t.abort(),1e4);try{let a=await fetch(`${e}/api/activity?limit=1000`,{signal:t.signal});if(clearTimeout(i),!a.ok)throw new Error(`Activity API ${a.status}`);return a.json()}catch(a){throw clearTimeout(i),a}}async _loadData(){if(!(!this.isConnected||this._loading)){this._loading=!0;try{let e=await Promise.allSettled([this._fetchActivity(),this._api.getToolEfficiency(50),this._api.getCost(),this._api.getContext(),this._api.getLearningTrends({timeRange:this._toolTimeRange})]);if(e[0].status==="fulfilled"&&(this._activity=e[0].value||[]),e[1].status==="fulfilled"&&(this._tools=e[1].value||[]),e[2].status==="fulfilled"&&(this._cost=e[2].value||{}),e[3].status==="fulfilled"&&(this._context=e[3].value||{}),e[4].status==="fulfilled"){let t=e[4].value||{};this._trends=Array.isArray(t)?t:t.dataPoints||[]}this._connected=e.some(t=>t.status==="fulfilled"),this.render()}finally{this._loading=!1}}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e4),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e4))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}_computeHeatmap(){let e={},t=Array.isArray(this._activity)?this._activity:[];for(let c of t){let p=c.timestamp||c.ts||c.created_at;if(!p)continue;let h=new Date(p);if(isNaN(h.getTime()))continue;let b=this._localDateKey(h);e[b]=(e[b]||0)+1}let i=new Date;i.setHours(0,0,0,0);let a=i.getDay(),s=new Date(i),r=new Date(i);r.setDate(r.getDate()-(52*7+a));let o=[],n=new Date(r),l=0;for(;n<=s;){let c=this._localDateKey(n),p=e[c]||0;p>l&&(l=p),o.push({date:c,count:p,day:n.getDay()}),n.setDate(n.getDate()+1)}return{cells:o,maxCount:l}}_getHeatmapLevel(e,t){if(e===0||t===0)return 0;let i=e/t;return i<=.25?1:i<=.5?2:i<=.75?3:4}_renderHeatmap(){let{cells:e,maxCount:t}=this._computeHeatmap(),i=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],a=["","Mon","","Wed","","Fri",""],s=[],r=-1,o=-1;for(let p=0;p<e.length;p++){e[p].day===0&&o++;let h=new Date(e[p].date).getMonth();h!==r&&(s.push({month:i[h],col:Math.max(o,1)}),r=h)}let n=s.map(p=>`<span class="heatmap-month" style="grid-column: ${p.col}">${p.month}</span>`).join(""),l=e.map(p=>`<div class="heatmap-cell level-${this._getHeatmapLevel(p.count,t)}" title="${p.date}: ${p.count} activities"></div>`).join(""),c=a.map(p=>`<span class="heatmap-day-label">${p}</span>`).join("");return`
|
|
10073
10086
|
<div class="heatmap-container">
|
|
10074
10087
|
<div class="heatmap-months">${n}</div>
|
|
10075
10088
|
<div class="heatmap-body">
|
|
10076
|
-
<div class="heatmap-day-labels">${
|
|
10089
|
+
<div class="heatmap-day-labels">${c}</div>
|
|
10077
10090
|
<div class="heatmap-grid">${l}</div>
|
|
10078
10091
|
</div>
|
|
10079
10092
|
<div class="heatmap-legend">
|
|
@@ -10094,7 +10107,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
10094
10107
|
</div>
|
|
10095
10108
|
<span class="tool-count">${s}</span>
|
|
10096
10109
|
</div>
|
|
10097
|
-
`}).join("")+"</div>"}_computeVelocity(){let e=this._context||{},t=e.per_iteration||e.iterations||[],i=Array.isArray(t)&&t.length>0?t.length:e.totals&&e.totals.iterations_tracked||e.total_iterations||0,a=0;if(Array.isArray(t)&&t.length>=2){let o=t.map(n=>new Date(n.timestamp||n.started_at||n.ts).getTime()).filter(n=>!isNaN(n)).sort((n,l)=>n-l);if(o.length>=2){let n=(o[o.length-1]-o[0])/36e5;n>0&&(a=Math.max(o.length-1,1)/n)}}let s=[],r=Array.isArray(this._trends)?this._trends:[];if(r.length>0)for(let o of r.slice(-24))s.push(o.count??o.value??0);else if(Array.isArray(t)&&t.length>0){let o={};for(let l of t){let
|
|
10110
|
+
`}).join("")+"</div>"}_computeVelocity(){let e=this._context||{},t=e.per_iteration||e.iterations||[],i=Array.isArray(t)&&t.length>0?t.length:e.totals&&e.totals.iterations_tracked||e.total_iterations||0,a=0;if(Array.isArray(t)&&t.length>=2){let o=t.map(n=>new Date(n.timestamp||n.started_at||n.ts).getTime()).filter(n=>!isNaN(n)).sort((n,l)=>n-l);if(o.length>=2){let n=(o[o.length-1]-o[0])/36e5;n>0&&(a=Math.max(o.length-1,1)/n)}}let s=[],r=Array.isArray(this._trends)?this._trends:[];if(r.length>0)for(let o of r.slice(-24))s.push(o.count??o.value??0);else if(Array.isArray(t)&&t.length>0){let o={};for(let l of t){let c=l.timestamp||l.started_at||l.ts;if(!c)continue;let h=new Date(c).toISOString().slice(0,13);o[h]=(o[h]||0)+1}let n=Object.keys(o).sort().slice(-24);for(let l of n)s.push(o[l])}return{iterPerHour:a,totalIterations:i,hourlyBuckets:s}}_renderVelocity(){let{iterPerHour:e,totalIterations:t,hourlyBuckets:i}=this._computeVelocity(),a=Math.max(1,...i),s=i.length>0?i.map(o=>{let n=o/a*100;return`<div class="spark-bar" style="height: ${Math.max(2,n)}%" title="${o}"></div>`}).join(""):'<div class="empty-state" style="padding: 12px">No trend data</div>';return`
|
|
10098
10111
|
${`
|
|
10099
10112
|
<div class="tool-filter">
|
|
10100
10113
|
<select class="tool-time-select" id="tool-time-range">
|
|
@@ -10119,7 +10132,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
10119
10132
|
<div class="sparkline-label">Activity Trend (hourly)</div>
|
|
10120
10133
|
<div class="sparkline">${s}</div>
|
|
10121
10134
|
</div>
|
|
10122
|
-
`}_computeProviders(){let e=this._cost.by_model||{},t={};for(let[r,o]of Object.entries(e)){let n=
|
|
10135
|
+
`}_computeProviders(){let e=this._cost.by_model||{},t={};for(let[r,o]of Object.entries(e)){let n=Ct(r);t[n]||(t[n]={cost:0,tokens:0,iterations:0,models:[]});let l=o.cost_usd||0,c=(o.input_tokens||0)+(o.output_tokens||0);t[n].cost+=l,t[n].tokens+=c,t[n].models.push(r)}let a=(this._context.totals||{}).iterations_tracked||this._context.total_iterations||this._context.iteration||0,s=this._cost.estimated_cost_usd||0;for(let r of Object.values(t))if(s>0&&a>0){let o=r.cost/s;r.iterations=Math.round(o*a)}return t}_renderProviders(){let e=this._computeProviders(),t={claude:{label:"Claude",color:"var(--loki-accent)"},codex:{label:"Codex",color:"var(--loki-success)"},cline:{label:"Cline",color:"var(--loki-info)"},aider:{label:"Aider",color:"var(--loki-blue)"},unknown:{label:"Other",color:"var(--loki-text-muted)"}},i=Object.entries(e);return i.length===0?'<div class="empty-state">No provider data available. Start a session to see cross-provider comparison.</div>':`
|
|
10123
10136
|
<div class="provider-grid">
|
|
10124
10137
|
${i.map(([a,s])=>{let r=t[a]||t.unknown,o=s.iterations>0?(s.cost/s.iterations).toFixed(4):"--",n=s.iterations>0?Math.round(s.tokens/s.iterations).toLocaleString():"--";return`
|
|
10125
10138
|
<div class="provider-card">
|
|
@@ -10517,7 +10530,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
10517
10530
|
${t}
|
|
10518
10531
|
</div>
|
|
10519
10532
|
</div>
|
|
10520
|
-
`,this.shadowRoot.querySelectorAll("[data-tab]").forEach(a=>{a.addEventListener("click",s=>this._handleTabClick(s))});let i=this.shadowRoot.getElementById("tool-time-range");i&&i.addEventListener("change",a=>this._handleTimeRangeChange(a))}};customElements.get("loki-analytics")||customElements.define("loki-analytics",ne);var
|
|
10533
|
+
`,this.shadowRoot.querySelectorAll("[data-tab]").forEach(a=>{a.addEventListener("click",s=>this._handleTabClick(s))});let i=this.shadowRoot.getElementById("tool-time-range");i&&i.addEventListener("change",a=>this._handleTimeRangeChange(a))}};customElements.get("loki-analytics")||customElements.define("loki-analytics",ne);var Xe={pass:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"PASS"},fail:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"FAIL"},pending:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"PENDING"}};function St(d){if(!d)return"Never";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return"Unknown"}}function At(d){if(!d||d.length===0)return{pass:0,fail:0,pending:0,total:0};let e={pass:0,fail:0,pending:0,total:d.length};for(let t of d){let i=(t.status||"pending").toLowerCase();i==="pass"?e.pass++:i==="fail"?e.fail++:e.pending++}return e}var le=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._gates=[],this._evidence={blocked:!1},this._pollInterval=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e4),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e4))},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{this._loading=!0;let e=await this._api._get("/api/council/gate"),t=e?.gates||e||[],i=e?.evidence||{blocked:!1},a=JSON.stringify({gates:t,evidence:i});if(a===this._lastDataHash)return;this._lastDataHash=a,this._gates=Array.isArray(t)?t:[],this._evidence=i,this._error=null}catch(e){this._error||(this._error=`Failed to load quality gates: ${e.message}`)}finally{this._loading=!1}this.render()}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
10521
10534
|
:host {
|
|
10522
10535
|
display: block;
|
|
10523
10536
|
}
|
|
@@ -10686,16 +10699,16 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
10686
10699
|
color: var(--loki-text-muted, #939084);
|
|
10687
10700
|
font-size: 13px;
|
|
10688
10701
|
}
|
|
10689
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._gates,i=
|
|
10690
|
-
<div class="gate-card status-${
|
|
10702
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._gates,i=At(t),a;this._loading&&t.length===0?a='<div class="loading">Loading quality gates...</div>':t.length===0?a='<div class="empty-state"><strong>No gate results yet.</strong> Quality gates run automatically between RARV iterations during an active session. Start a session with <code>loki start ./prd.md</code> to see results here. You can also run gates manually with <code>loki review</code>.</div>':a=`<div class="gates-grid">${t.map(l=>{let c=(l.status||"pending").toLowerCase(),p=Xe[c]||Xe.pending;return`
|
|
10703
|
+
<div class="gate-card status-${c}">
|
|
10691
10704
|
<div class="gate-header">
|
|
10692
10705
|
<span class="gate-name">${this._escapeHtml(l.name||"Unnamed Gate")}</span>
|
|
10693
10706
|
<span class="gate-badge" style="background: ${p.bg}; color: ${p.color};">${p.label}</span>
|
|
10694
10707
|
</div>
|
|
10695
10708
|
${l.description?`<div class="gate-description">${this._escapeHtml(l.description)}</div>`:""}
|
|
10696
|
-
<div class="gate-meta">Last checked: ${
|
|
10709
|
+
<div class="gate-meta">Last checked: ${St(l.last_checked||l.lastChecked)}</div>
|
|
10697
10710
|
</div>
|
|
10698
|
-
`}).join("")}</div>`;let s="",r=this._evidence||{};if(r.blocked){let n={empty_diff:"No changes were shipped (empty diff vs run start).",tests_red:"Tests ran and were red.",empty_diff_and_tests_red:"No changes shipped and tests were red.",no_evidence_of_completion:"No evidence of completion."},l=r.error?this._escapeHtml(r.error):n[r.reason]||this._escapeHtml(r.reason||"Completion blocked."),
|
|
10711
|
+
`}).join("")}</div>`;let s="",r=this._evidence||{};if(r.blocked){let n={empty_diff:"No changes were shipped (empty diff vs run start).",tests_red:"Tests ran and were red.",empty_diff_and_tests_red:"No changes shipped and tests were red.",no_evidence_of_completion:"No evidence of completion."},l=r.error?this._escapeHtml(r.error):n[r.reason]||this._escapeHtml(r.reason||"Completion blocked."),c=Array.isArray(r.failures)?r.failures:[],p=c.length?`<ul class="evidence-failures">${c.map(h=>`<li>${this._escapeHtml(h)}</li>`).join("")}</ul>`:"";s=`
|
|
10699
10712
|
<div class="evidence-banner">
|
|
10700
10713
|
<div class="evidence-title">Verified completion blocked</div>
|
|
10701
10714
|
<div class="evidence-reason">${l}</div>
|
|
@@ -10728,7 +10741,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
10728
10741
|
${a}
|
|
10729
10742
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
10730
10743
|
</div>
|
|
10731
|
-
`}};customElements.get("loki-quality-gates")||customElements.define("loki-quality-gates",le);var F={reason:{color:"var(--loki-blue, #3b82f6)",label:"Reason",description:"Analyzing requirements and planning approach"},act:{color:"var(--loki-green, #22c55e)",label:"Act",description:"Implementing changes and executing tasks"},reflect:{color:"var(--loki-purple, #a78bfa)",label:"Reflect",description:"Reviewing results and evaluating quality"},verify:{color:"var(--loki-yellow, #eab308)",label:"Verify",description:"Running tests and validating correctness"}},
|
|
10744
|
+
`}};customElements.get("loki-quality-gates")||customElements.define("loki-quality-gates",le);var F={reason:{color:"var(--loki-blue, #3b82f6)",label:"Reason",description:"Analyzing requirements and planning approach"},act:{color:"var(--loki-green, #22c55e)",label:"Act",description:"Implementing changes and executing tasks"},reflect:{color:"var(--loki-purple, #a78bfa)",label:"Reflect",description:"Reviewing results and evaluating quality"},verify:{color:"var(--loki-yellow, #eab308)",label:"Verify",description:"Running tests and validating correctness"}},Re=["reason","act","reflect","verify"];function ze(d){if(d==null||d<0)return"--";if(d<1e3)return`${d}ms`;let e=Math.floor(d/1e3);if(e<60)return`${e}s`;let t=Math.floor(e/60),i=e%60;if(t<60)return`${t}m ${i}s`;let a=Math.floor(t/60),s=t%60;return`${a}h ${s}m`}function Tt(d){if(!d||d.length===0)return[];let e=d.reduce((t,i)=>t+(i.duration_ms||0),0);return e===0?d.map(t=>({phase:t.phase,pct:100/d.length,duration:0})):d.map(t=>({phase:t.phase,pct:(t.duration_ms||0)/e*100,duration:t.duration_ms||0}))}function It(d){return d==null?"--":d>=1e6?(d/1e6).toFixed(1)+"M":d>=1e3?(d/1e3).toFixed(1)+"K":String(d)}var de=class extends u{static get observedAttributes(){return["run-id","api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._timeline=null,this._pollInterval=null,this._selectedPhase=null,this._cycleHistory=[]}get runId(){let e=this.getAttribute("run-id");return e?parseInt(e,10):null}set runId(e){e!=null?this.setAttribute("run-id",String(e)):this.removeAttribute("run-id")}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="run-id"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_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(){let e=this.runId;if(e==null){this._timeline=null,this.render();return}try{this._loading=!0;let t=await this._api._get(`/api/v2/runs/${e}/timeline`);this._timeline=t,this._cycleHistory=t.history||[],this._error=null}catch(t){t.message&&(t.message.includes("404")||t.message.includes("Not Found"))?(this._timeline=null,this._error=null):this._error=`Failed to load timeline: ${t.message}`}finally{this._loading=!1}this.render()}_selectPhase(e){this._selectedPhase=this._selectedPhase===e?null:e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".phase-segment-interactive").forEach(t=>{t.addEventListener("click",()=>{this._selectPhase(t.dataset.phase)})}),e.querySelectorAll(".legend-item-interactive").forEach(t=>{t.addEventListener("click",()=>{this._selectPhase(t.dataset.phase)})}),e.querySelectorAll(".close-detail").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._selectedPhase=null,this.render()})})}_getStyles(){return`
|
|
10732
10745
|
:host {
|
|
10733
10746
|
display: block;
|
|
10734
10747
|
}
|
|
@@ -11013,12 +11026,12 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11013
11026
|
color: var(--loki-text-muted, #939084);
|
|
11014
11027
|
font-size: 13px;
|
|
11015
11028
|
}
|
|
11016
|
-
`}_renderPlaceholderTimeline(){let e=
|
|
11029
|
+
`}_renderPlaceholderTimeline(){let e=Re.map(i=>{let a=F[i];return`<div class="phase-segment-interactive"
|
|
11017
11030
|
data-phase="${i}"
|
|
11018
11031
|
style="width: 25%; background: ${a.color}; opacity: 0.3;"
|
|
11019
11032
|
title="${a.label}: awaiting data">
|
|
11020
11033
|
${a.label}
|
|
11021
|
-
</div>`}).join(""),t=
|
|
11034
|
+
</div>`}).join(""),t=Re.map(i=>{let a=F[i];return`<div class="legend-item-interactive" data-phase="${i}">
|
|
11022
11035
|
<span class="legend-dot" style="background: ${a.color}; opacity: 0.4;"></span>
|
|
11023
11036
|
<span class="legend-label">${a.label}</span>
|
|
11024
11037
|
<span class="legend-duration">--</span>
|
|
@@ -11043,11 +11056,11 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11043
11056
|
<div class="detail-metrics">
|
|
11044
11057
|
<div class="detail-metric">
|
|
11045
11058
|
<span class="detail-metric-label">Time Spent</span>
|
|
11046
|
-
<span class="detail-metric-value">${
|
|
11059
|
+
<span class="detail-metric-value">${ze(a?.duration_ms)}</span>
|
|
11047
11060
|
</div>
|
|
11048
11061
|
<div class="detail-metric">
|
|
11049
11062
|
<span class="detail-metric-label">Tokens Used</span>
|
|
11050
|
-
<span class="detail-metric-value">${
|
|
11063
|
+
<span class="detail-metric-value">${It(a?.tokens_used)}</span>
|
|
11051
11064
|
</div>
|
|
11052
11065
|
<div class="detail-metric">
|
|
11053
11066
|
<span class="detail-metric-label">Quality</span>
|
|
@@ -11059,26 +11072,26 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11059
11072
|
</div>
|
|
11060
11073
|
</div>
|
|
11061
11074
|
</div>
|
|
11062
|
-
`}_renderCycleHistory(){if(this._cycleHistory.length===0)return"";let t=this._cycleHistory.slice(-8).map((i,a)=>`<div class="history-cycle">${
|
|
11063
|
-
title="Cycle ${a+1}: ${n.label} - ${
|
|
11075
|
+
`}_renderCycleHistory(){if(this._cycleHistory.length===0)return"";let t=this._cycleHistory.slice(-8).map((i,a)=>`<div class="history-cycle">${Re.map(r=>{let o=i.phases?.find(p=>p.phase===r),n=F[r],l=o?.status||"pending",c=l==="complete"?"0.8":l==="active"?"1":"0.3";return`<div class="history-dot" style="background: ${n.color}; opacity: ${c};"
|
|
11076
|
+
title="Cycle ${a+1}: ${n.label} - ${ze(o?.duration_ms)}"></div>`}).join("")}</div>`).join('<div class="history-separator"></div>');return`
|
|
11064
11077
|
<div class="cycle-history">
|
|
11065
11078
|
<div class="history-label">Past Cycles (${this._cycleHistory.length} total)</div>
|
|
11066
11079
|
<div class="history-cycles">${t}</div>
|
|
11067
11080
|
</div>
|
|
11068
|
-
`}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let e=this.shadowRoot;if(!e)return;let t=this.runId,i=this._timeline,a=i?.phases||[],s=i?.current_phase||null,r=
|
|
11081
|
+
`}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let e=this.shadowRoot;if(!e)return;let t=this.runId,i=this._timeline,a=i?.phases||[],s=i?.current_phase||null,r=Tt(a),o;if(this._loading&&!i)o='<div class="loading">Loading timeline...</div>';else if(t==null)o=this._renderPlaceholderTimeline();else if(a.length===0)o=this._renderPlaceholderTimeline();else{let n=r.map(h=>{let b=F[h.phase]||{color:"var(--loki-text-muted)",label:h.phase},m=s===h.phase,f=this._selectedPhase===h.phase;return`<div class="phase-segment-interactive ${m?"current":""} ${f?"selected":""}"
|
|
11069
11082
|
data-phase="${h.phase}"
|
|
11070
11083
|
style="width: ${Math.max(h.pct,2)}%; background: ${b.color};"
|
|
11071
|
-
title="${b.label}: ${
|
|
11084
|
+
title="${b.label}: ${ze(h.duration)}">
|
|
11072
11085
|
${h.pct>12?b.label:""}
|
|
11073
11086
|
</div>`}).join(""),l=a.map(h=>{let b=F[h.phase]||{color:"var(--loki-text-muted)",label:h.phase},m=s===h.phase;return`<div class="legend-item-interactive ${this._selectedPhase===h.phase?"selected":""}" data-phase="${h.phase}">
|
|
11074
11087
|
<span class="legend-dot" style="background: ${b.color}"></span>
|
|
11075
11088
|
<span class="legend-label">${b.label}</span>
|
|
11076
|
-
<span class="legend-duration">${
|
|
11089
|
+
<span class="legend-duration">${ze(h.duration_ms)}</span>
|
|
11077
11090
|
${m?'<span class="phase-current-tag">ACTIVE</span>':""}
|
|
11078
|
-
</div>`}).join(""),
|
|
11091
|
+
</div>`}).join(""),c=this._selectedPhase?this._renderPhaseDetail(this._selectedPhase):"",p=this._renderCycleHistory();o=`
|
|
11079
11092
|
<div class="timeline-bar">${n}</div>
|
|
11080
11093
|
<div class="legend">${l}</div>
|
|
11081
|
-
${
|
|
11094
|
+
${c}
|
|
11082
11095
|
${p}
|
|
11083
11096
|
`}e.innerHTML=`
|
|
11084
11097
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
@@ -11090,7 +11103,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11090
11103
|
${o}
|
|
11091
11104
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11092
11105
|
</div>
|
|
11093
|
-
`,this._bindEvents()}};customElements.get("loki-rarv-timeline")||customElements.define("loki-rarv-timeline",de);var
|
|
11106
|
+
`,this._bindEvents()}};customElements.get("loki-rarv-timeline")||customElements.define("loki-rarv-timeline",de);var Ze={running:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"Running"},completed:{color:"var(--loki-blue, #3b82f6)",bg:"var(--loki-blue-muted, rgba(59, 130, 246, 0.15))",label:"Completed"},failed:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"Failed"},cancelled:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"Cancelled"},pending:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Pending"},queued:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Queued"}};function Lt(d,e,t){let i=d;if(i==null&&e){let l=new Date(e).getTime();i=(t?new Date(t).getTime():Date.now())-l}if(i==null||i<0)return"--";if(i<1e3)return`${i}ms`;let a=Math.floor(i/1e3);if(a<60)return`${a}s`;let s=Math.floor(a/60),r=a%60;if(s<60)return`${s}m ${r}s`;let o=Math.floor(s/60),n=s%60;return`${o}h ${n}m`}function Dt(d){if(!d)return"--";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return String(d)}}var ce=class extends u{static get observedAttributes(){return["api-url","project-id","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._runs=[],this._pollInterval=null,this._lastDataHash=null}get projectId(){let e=this.getAttribute("project-id");return e?parseInt(e,10):null}set projectId(e){e!=null?this.setAttribute("project-id",String(e)):this.removeAttribute("project-id")}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="project-id"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_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 e=this.projectId,t=e!=null?`?project_id=${e}`:"",i=await this._api._get(`/api/v2/runs${t}`),a=i?.runs||i||[],s=JSON.stringify(a);if(s===this._lastDataHash)return;this._lastDataHash=s,this._runs=Array.isArray(a)?a:[],this._error=null}catch(e){this._error||(this._error=`Failed to load runs: ${e.message}`)}finally{this._loading=!1}this.render()}async _cancelRun(e){try{await this._api._post(`/api/v2/runs/${e}/cancel`),await this._loadData()}catch(t){this._error=`Cancel failed: ${t.message}`,this.render()}}async _replayRun(e){try{await this._api._post(`/api/v2/runs/${e}/replay`),await this._loadData()}catch(t){this._error=`Replay failed: ${t.message}`,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11094
11107
|
:host {
|
|
11095
11108
|
display: block;
|
|
11096
11109
|
}
|
|
@@ -11243,14 +11256,14 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11243
11256
|
color: var(--loki-text-muted, #939084);
|
|
11244
11257
|
margin-bottom: 8px;
|
|
11245
11258
|
}
|
|
11246
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading runs...</div>';else if(t.length===0)i='<div class="empty-state">No runs found.</div>';else{let a=t.map(s=>{let r=(s.status||"pending").toLowerCase(),o=
|
|
11259
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading runs...</div>';else if(t.length===0)i='<div class="empty-state">No runs found.</div>';else{let a=t.map(s=>{let r=(s.status||"pending").toLowerCase(),o=Ze[r]||Ze.pending,n=r==="running",l=r==="completed"||r==="failed"||r==="cancelled",c=Lt(s.duration_ms,s.started_at,s.ended_at);return`
|
|
11247
11260
|
<tr>
|
|
11248
11261
|
<td><span class="run-id">#${s.id}</span></td>
|
|
11249
11262
|
<td>${this._escapeHtml(s.project_name||s.project||(s.project_id?`Project #${s.project_id}`:"--"))}</td>
|
|
11250
11263
|
<td><span class="status-badge" style="background: ${o.bg}; color: ${o.color};">${o.label}</span></td>
|
|
11251
11264
|
<td>${this._escapeHtml(s.trigger||s.trigger_type||"--")}</td>
|
|
11252
|
-
<td>${
|
|
11253
|
-
<td>${
|
|
11265
|
+
<td>${Dt(s.started_at)}</td>
|
|
11266
|
+
<td>${c}</td>
|
|
11254
11267
|
<td>
|
|
11255
11268
|
<div class="actions-cell">
|
|
11256
11269
|
${n?`<button class="btn btn-cancel" data-action="cancel" data-run-id="${s.id}">Cancel</button>`:""}
|
|
@@ -11286,7 +11299,227 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11286
11299
|
${i}
|
|
11287
11300
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11288
11301
|
</div>
|
|
11289
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadData()),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.runId))}),e.querySelectorAll('[data-action="replay"]').forEach(i=>{i.addEventListener("click",()=>this._replayRun(i.dataset.runId))})}};customElements.get("loki-run-manager")||customElements.define("loki-run-manager",ce);
|
|
11302
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadData()),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.runId))}),e.querySelectorAll('[data-action="replay"]').forEach(i=>{i.addEventListener("click",()=>this._replayRun(i.dataset.runId))})}};customElements.get("loki-run-manager")||customElements.define("loki-run-manager",ce);var et={running:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"Running"},stopped:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"Stopped"},active:{color:"var(--loki-blue, #3b82f6)",bg:"var(--loki-blue-muted, rgba(59, 130, 246, 0.15))",label:"Idle"},missing:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"Missing"},unknown:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Unknown"}};function zt(d){if(d==null||d<0)return"--";if(d<60)return`${d}s`;let e=Math.floor(d/60),t=d%60;if(e<60)return`${e}m ${t}s`;let i=Math.floor(e/60),a=e%60;return`${i}h ${a}m`}function tt(d){return d==null||isNaN(d)?"$0.00":`$${Number(d).toFixed(2)}`}var pe=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!0,this._error=null,this._api=null,this._runs=[],this._summary=null,this._pollInterval=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_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[e,t]=await Promise.all([this._api._get("/api/fleet/runs"),this._api._get("/api/fleet/summary")]),i=Array.isArray(e)?e:e?.runs||[],a=JSON.stringify({runs:i,summaryResp:t});if(a===this._lastDataHash)return;this._lastDataHash=a,this._runs=Array.isArray(i)?i:[],this._summary=t||null,this._error=null}catch(e){this._error||(this._error=`Failed to load fleet: ${e.message}`)}finally{this._loading=!1}this.render()}async _cancelRun(e){if(e&&!(typeof confirm=="function"&&!confirm(`Cancel build "${e}"? This stops the running build.`)))try{await this._api._post(`/api/fleet/runs/${encodeURIComponent(e)}/cancel`),this._lastDataHash=null,await this._loadData()}catch(t){this._error=`Cancel failed: ${t.message}`,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11303
|
+
:host { display: block; }
|
|
11304
|
+
|
|
11305
|
+
.fleet {
|
|
11306
|
+
padding: 16px;
|
|
11307
|
+
font-family: var(--loki-font-family, 'Inter', -apple-system, sans-serif);
|
|
11308
|
+
color: var(--loki-text-primary, #201515);
|
|
11309
|
+
}
|
|
11310
|
+
|
|
11311
|
+
.header {
|
|
11312
|
+
display: flex;
|
|
11313
|
+
align-items: center;
|
|
11314
|
+
justify-content: space-between;
|
|
11315
|
+
margin-bottom: 16px;
|
|
11316
|
+
}
|
|
11317
|
+
|
|
11318
|
+
.title { font-size: 18px; font-weight: 600; margin: 0; }
|
|
11319
|
+
|
|
11320
|
+
.summary-cards {
|
|
11321
|
+
display: grid;
|
|
11322
|
+
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
11323
|
+
gap: 12px;
|
|
11324
|
+
margin-bottom: 16px;
|
|
11325
|
+
}
|
|
11326
|
+
|
|
11327
|
+
.summary-card {
|
|
11328
|
+
background: var(--loki-bg-card, #ffffff);
|
|
11329
|
+
border: 1px solid var(--loki-border, #ECEAE3);
|
|
11330
|
+
border-radius: 8px;
|
|
11331
|
+
padding: 12px 14px;
|
|
11332
|
+
}
|
|
11333
|
+
|
|
11334
|
+
.summary-label {
|
|
11335
|
+
font-size: 11px;
|
|
11336
|
+
font-weight: 600;
|
|
11337
|
+
text-transform: uppercase;
|
|
11338
|
+
letter-spacing: 0.05em;
|
|
11339
|
+
color: var(--loki-text-muted, #939084);
|
|
11340
|
+
margin-bottom: 4px;
|
|
11341
|
+
}
|
|
11342
|
+
|
|
11343
|
+
.summary-value {
|
|
11344
|
+
font-size: 22px;
|
|
11345
|
+
font-weight: 700;
|
|
11346
|
+
color: var(--loki-text-primary, #201515);
|
|
11347
|
+
}
|
|
11348
|
+
|
|
11349
|
+
.scope-note {
|
|
11350
|
+
font-size: 11px;
|
|
11351
|
+
color: var(--loki-text-muted, #939084);
|
|
11352
|
+
margin-bottom: 12px;
|
|
11353
|
+
line-height: 1.4;
|
|
11354
|
+
}
|
|
11355
|
+
|
|
11356
|
+
.btn {
|
|
11357
|
+
padding: 4px 10px;
|
|
11358
|
+
border: 1px solid var(--loki-border, #ECEAE3);
|
|
11359
|
+
border-radius: 5px;
|
|
11360
|
+
background: var(--loki-bg-tertiary, #ECEAE3);
|
|
11361
|
+
color: var(--loki-text-primary, #201515);
|
|
11362
|
+
cursor: pointer;
|
|
11363
|
+
font-size: 11px;
|
|
11364
|
+
font-weight: 500;
|
|
11365
|
+
transition: all 0.15s ease;
|
|
11366
|
+
}
|
|
11367
|
+
|
|
11368
|
+
.btn:hover {
|
|
11369
|
+
background: var(--loki-bg-hover, #1f1f23);
|
|
11370
|
+
border-color: var(--loki-border-light, #C5C0B1);
|
|
11371
|
+
}
|
|
11372
|
+
|
|
11373
|
+
.btn-cancel {
|
|
11374
|
+
border-color: var(--loki-red, #ef4444);
|
|
11375
|
+
color: var(--loki-red, #ef4444);
|
|
11376
|
+
}
|
|
11377
|
+
|
|
11378
|
+
.btn-cancel:hover { background: var(--loki-red-muted, rgba(239, 68, 68, 0.15)); }
|
|
11379
|
+
|
|
11380
|
+
.btn-refresh { padding: 6px 14px; font-size: 12px; }
|
|
11381
|
+
|
|
11382
|
+
.runs-table-wrapper {
|
|
11383
|
+
background: var(--loki-bg-card, #ffffff);
|
|
11384
|
+
border: 1px solid var(--loki-border, #ECEAE3);
|
|
11385
|
+
border-radius: 5px;
|
|
11386
|
+
overflow: auto;
|
|
11387
|
+
}
|
|
11388
|
+
|
|
11389
|
+
table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
11390
|
+
|
|
11391
|
+
th {
|
|
11392
|
+
text-align: left;
|
|
11393
|
+
padding: 10px 14px;
|
|
11394
|
+
font-size: 11px;
|
|
11395
|
+
font-weight: 600;
|
|
11396
|
+
text-transform: uppercase;
|
|
11397
|
+
letter-spacing: 0.05em;
|
|
11398
|
+
color: var(--loki-text-muted, #939084);
|
|
11399
|
+
border-bottom: 1px solid var(--loki-border, #ECEAE3);
|
|
11400
|
+
background: var(--loki-bg-tertiary, #ECEAE3);
|
|
11401
|
+
white-space: nowrap;
|
|
11402
|
+
}
|
|
11403
|
+
|
|
11404
|
+
td {
|
|
11405
|
+
padding: 8px 14px;
|
|
11406
|
+
border-bottom: 1px solid var(--loki-border, #ECEAE3);
|
|
11407
|
+
white-space: nowrap;
|
|
11408
|
+
}
|
|
11409
|
+
|
|
11410
|
+
tr:last-child td { border-bottom: none; }
|
|
11411
|
+
tr:hover td { background: var(--loki-bg-hover, #1f1f23); }
|
|
11412
|
+
|
|
11413
|
+
.project-name { font-weight: 600; color: var(--loki-text-primary, #201515); }
|
|
11414
|
+
|
|
11415
|
+
.project-path {
|
|
11416
|
+
font-size: 10px;
|
|
11417
|
+
color: var(--loki-text-muted, #939084);
|
|
11418
|
+
font-family: 'JetBrains Mono', monospace;
|
|
11419
|
+
}
|
|
11420
|
+
|
|
11421
|
+
.status-badge {
|
|
11422
|
+
display: inline-block;
|
|
11423
|
+
font-size: 10px;
|
|
11424
|
+
font-weight: 600;
|
|
11425
|
+
padding: 2px 8px;
|
|
11426
|
+
border-radius: 5px;
|
|
11427
|
+
text-transform: uppercase;
|
|
11428
|
+
}
|
|
11429
|
+
|
|
11430
|
+
.cost-cell { font-family: 'JetBrains Mono', monospace; }
|
|
11431
|
+
|
|
11432
|
+
.empty-state {
|
|
11433
|
+
text-align: center;
|
|
11434
|
+
padding: 40px;
|
|
11435
|
+
color: var(--loki-text-muted, #939084);
|
|
11436
|
+
font-size: 13px;
|
|
11437
|
+
}
|
|
11438
|
+
|
|
11439
|
+
.error-banner {
|
|
11440
|
+
margin-top: 12px;
|
|
11441
|
+
padding: 8px 12px;
|
|
11442
|
+
background: var(--loki-red-muted, rgba(239, 68, 68, 0.15));
|
|
11443
|
+
color: var(--loki-red, #ef4444);
|
|
11444
|
+
border-radius: 4px;
|
|
11445
|
+
font-size: 12px;
|
|
11446
|
+
}
|
|
11447
|
+
|
|
11448
|
+
.loading {
|
|
11449
|
+
text-align: center;
|
|
11450
|
+
padding: 24px;
|
|
11451
|
+
color: var(--loki-text-muted, #939084);
|
|
11452
|
+
font-size: 13px;
|
|
11453
|
+
}
|
|
11454
|
+
`}_renderSummary(){let e=this._summary;return e?`
|
|
11455
|
+
<div class="summary-cards">
|
|
11456
|
+
<div class="summary-card">
|
|
11457
|
+
<div class="summary-label">Builds</div>
|
|
11458
|
+
<div class="summary-value">${Number(e.total_runs||0)}</div>
|
|
11459
|
+
</div>
|
|
11460
|
+
<div class="summary-card">
|
|
11461
|
+
<div class="summary-label">Running</div>
|
|
11462
|
+
<div class="summary-value">${Number(e.running_runs||0)}</div>
|
|
11463
|
+
</div>
|
|
11464
|
+
<div class="summary-card">
|
|
11465
|
+
<div class="summary-label">Stopped</div>
|
|
11466
|
+
<div class="summary-value">${Number(e.stopped_runs||0)}</div>
|
|
11467
|
+
</div>
|
|
11468
|
+
<div class="summary-card">
|
|
11469
|
+
<div class="summary-label">Total Cost</div>
|
|
11470
|
+
<div class="summary-value">${tt(e.total_cost_usd)}</div>
|
|
11471
|
+
</div>
|
|
11472
|
+
</div>
|
|
11473
|
+
`:""}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading fleet...</div>';else if(t.length===0)i='<div class="empty-state">No registered builds. Run <code>loki start</code> in a project to populate the fleet.</div>';else{let a=t.map(s=>{let r=(s.status||"unknown").toLowerCase(),o=et[r]||et.unknown,n=s.running===!0,l=zt(s.duration_seconds),c=s.iteration!=null?s.iteration:0,p=s.phase?this._escapeHtml(s.phase):"--";return`
|
|
11474
|
+
<tr>
|
|
11475
|
+
<td>
|
|
11476
|
+
<div class="project-name">${this._escapeHtml(s.name||"project")}</div>
|
|
11477
|
+
<div class="project-path">${this._escapeHtml(s.path||"")}</div>
|
|
11478
|
+
</td>
|
|
11479
|
+
<td><span class="status-badge" style="background: ${o.bg}; color: ${o.color};">${o.label}</span></td>
|
|
11480
|
+
<td>${p}</td>
|
|
11481
|
+
<td>${c}</td>
|
|
11482
|
+
<td class="cost-cell">${tt(s.cost_usd)}</td>
|
|
11483
|
+
<td>${l}</td>
|
|
11484
|
+
<td>
|
|
11485
|
+
${n?`<button class="btn btn-cancel" data-action="cancel" data-id="${this._escapeHtml(s.id||s.path||"")}">Cancel</button>`:""}
|
|
11486
|
+
</td>
|
|
11487
|
+
</tr>
|
|
11488
|
+
`}).join("");i=`
|
|
11489
|
+
${this._renderSummary()}
|
|
11490
|
+
<div class="runs-table-wrapper">
|
|
11491
|
+
<table>
|
|
11492
|
+
<thead>
|
|
11493
|
+
<tr>
|
|
11494
|
+
<th>Project</th>
|
|
11495
|
+
<th>Status</th>
|
|
11496
|
+
<th>Phase</th>
|
|
11497
|
+
<th>Iteration</th>
|
|
11498
|
+
<th>Cost</th>
|
|
11499
|
+
<th>Duration</th>
|
|
11500
|
+
<th>Actions</th>
|
|
11501
|
+
</tr>
|
|
11502
|
+
</thead>
|
|
11503
|
+
<tbody>${a}</tbody>
|
|
11504
|
+
</table>
|
|
11505
|
+
</div>
|
|
11506
|
+
`}e.innerHTML=`
|
|
11507
|
+
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
11508
|
+
<div class="fleet">
|
|
11509
|
+
<div class="header">
|
|
11510
|
+
<h2 class="title">Fleet</h2>
|
|
11511
|
+
<button class="btn btn-refresh" id="refresh-btn">Refresh</button>
|
|
11512
|
+
</div>
|
|
11513
|
+
<div class="scope-note">
|
|
11514
|
+
Fleet view aggregates every registered build on this machine (the
|
|
11515
|
+
shared registry plus each project's local state). v1 polls that
|
|
11516
|
+
shared metadata store; it is not a controller. A Kubernetes
|
|
11517
|
+
Job-watcher is future work.
|
|
11518
|
+
</div>
|
|
11519
|
+
${i}
|
|
11520
|
+
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11521
|
+
</div>
|
|
11522
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>{this._lastDataHash=null,this._loadData()}),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.id))})}};customElements.get("loki-fleet")||customElements.define("loki-fleet",pe);function Ht(d){if(!d)return"--";try{return new Date(d).toLocaleString([],{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return String(d)}}function Rt(d){let e=new URLSearchParams;for(let[i,a]of Object.entries(d))a!=null&&a!==""&&e.set(i,String(a));let t=e.toString();return t?`?${t}`:""}var he=class extends u{static get observedAttributes(){return["api-url","limit","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._entries=[],this._verifyResult=null,this._verifying=!1,this._filters={action:"",resource:"",dateFrom:"",dateTo:""}}get limit(){let e=this.getAttribute("limit");return e?parseInt(e,10):50}set limit(e){this.setAttribute("limit",String(e))}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData()}disconnectedCallback(){super.disconnectedCallback()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="limit"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadData(){try{this._loading=!0,this.render();let e={limit:this.limit,action:this._filters.action,resource:this._filters.resource,date_from:this._filters.dateFrom,date_to:this._filters.dateTo},t=Rt(e),i=await this._api._get(`/api/v2/audit${t}`);this._entries=i?.entries||i||[],this._error=null}catch(e){this._error=`Failed to load audit log: ${e.message}`}finally{this._loading=!1}this.render()}async _verifyIntegrity(){try{this._verifying=!0,this._verifyResult=null,this.render();let e=await this._api._get("/api/v2/audit/verify");this._verifyResult=e}catch(e){this._verifyResult={valid:!1,error:e.message}}finally{this._verifying=!1}this.render()}_onFilterChange(e,t){this._filters[e]=t,this._loadData()}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11290
11523
|
:host {
|
|
11291
11524
|
display: block;
|
|
11292
11525
|
}
|
|
@@ -11506,7 +11739,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11506
11739
|
</div>
|
|
11507
11740
|
`}let a;if(this._loading&&t.length===0)a='<div class="loading">Loading audit log...</div>';else if(t.length===0)a='<div class="empty-state">No audit entries found matching filters.</div>';else{let s=t.map(r=>`
|
|
11508
11741
|
<tr>
|
|
11509
|
-
<td>${
|
|
11742
|
+
<td>${Ht(r.timestamp)}</td>
|
|
11510
11743
|
<td>${this._escapeHtml(r.action||"--")}</td>
|
|
11511
11744
|
<td>${this._escapeHtml(r.resource||r.resource_type||"--")}</td>
|
|
11512
11745
|
<td>${this._escapeHtml(r.user||r.actor||"--")}</td>
|
|
@@ -11570,7 +11803,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11570
11803
|
${a}
|
|
11571
11804
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11572
11805
|
</div>
|
|
11573
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("verify-btn");t&&t.addEventListener("click",()=>this._verifyIntegrity());let i=e.getElementById("refresh-btn");i&&i.addEventListener("click",()=>this._loadData());let a=e.getElementById("filter-action");a&&a.addEventListener("change",n=>this._onFilterChange("action",n.target.value));let s=e.getElementById("filter-resource");s&&s.addEventListener("change",n=>this._onFilterChange("resource",n.target.value));let r=e.getElementById("filter-date-from");r&&r.addEventListener("change",n=>this._onFilterChange("dateFrom",n.target.value));let o=e.getElementById("filter-date-to");o&&o.addEventListener("change",n=>this._onFilterChange("dateTo",n.target.value))}};customElements.get("loki-audit-viewer")||customElements.define("loki-audit-viewer",
|
|
11806
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("verify-btn");t&&t.addEventListener("click",()=>this._verifyIntegrity());let i=e.getElementById("refresh-btn");i&&i.addEventListener("click",()=>this._loadData());let a=e.getElementById("filter-action");a&&a.addEventListener("change",n=>this._onFilterChange("action",n.target.value));let s=e.getElementById("filter-resource");s&&s.addEventListener("change",n=>this._onFilterChange("resource",n.target.value));let r=e.getElementById("filter-date-from");r&&r.addEventListener("change",n=>this._onFilterChange("dateFrom",n.target.value));let o=e.getElementById("filter-date-to");o&&o.addEventListener("change",n=>this._onFilterChange("dateTo",n.target.value))}};customElements.get("loki-audit-viewer")||customElements.define("loki-audit-viewer",he);function it(d){if(!d)return"Never";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return String(d)}}var ue=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._keys=[],this._showCreateForm=!1,this._newToken=null,this._confirmDeleteId=null,this._rotateKeyId=null,this._rotateGracePeriod="24",this._createName="",this._createRole="read",this._createExpiration=""}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData()}disconnectedCallback(){super.disconnectedCallback()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadData(){try{this._loading=!0,this.render();let e=await this._api._get("/api/v2/api-keys");this._keys=Array.isArray(e)?e:e?.keys||[],this._error=null}catch(e){this._error=`Failed to load API keys: ${e.message}`}finally{this._loading=!1}this.render()}async _createKey(){if(!this._createName.trim()){this._error="Key name is required.",this.render();return}try{let e={name:this._createName.trim(),role:this._createRole};this._createExpiration&&(e.expiration=this._createExpiration);let t=await this._api._post("/api/v2/api-keys",e);this._newToken=t?.token||t?.key||null,this._showCreateForm=!1,this._createName="",this._createRole="read",this._createExpiration="",this._error=null,await this._loadData()}catch(e){this._error=`Create failed: ${e.message}`,this.render()}}async _rotateKey(e){try{let t={grace_period_hours:parseInt(this._rotateGracePeriod,10)||24},i=await this._api._post(`/api/v2/api-keys/${e}/rotate`,t);this._newToken=i?.token||i?.key||null,this._rotateKeyId=null,this._error=null,await this._loadData()}catch(t){this._error=`Rotate failed: ${t.message}`,this.render()}}async _deleteKey(e){try{await this._api._delete(`/api/v2/api-keys/${e}`),this._confirmDeleteId=null,this._error=null,await this._loadData()}catch(t){this._error=`Delete failed: ${t.message}`,this._confirmDeleteId=null,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11574
11807
|
:host {
|
|
11575
11808
|
display: block;
|
|
11576
11809
|
}
|
|
@@ -11925,7 +12158,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11925
12158
|
<th>Actions</th>
|
|
11926
12159
|
</tr>
|
|
11927
12160
|
</thead>
|
|
11928
|
-
<tbody>${t.map(o=>{let n=o.id||o.key_id,l=(o.status||"active").toLowerCase(),
|
|
12161
|
+
<tbody>${t.map(o=>{let n=o.id||o.key_id,l=(o.status||"active").toLowerCase(),c=l==="active"?"key-status-active":l==="expired"?"key-status-expired":"key-status-revoked",p=this._confirmDeleteId===n,h=this._rotateKeyId===n,b;return p?b=`
|
|
11929
12162
|
<div class="confirm-delete">
|
|
11930
12163
|
<span>Delete this key?</span>
|
|
11931
12164
|
<button class="btn btn-sm btn-danger" data-action="confirm-delete" data-key-id="${n}">Yes</button>
|
|
@@ -11949,9 +12182,9 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11949
12182
|
<tr>
|
|
11950
12183
|
<td><span class="key-name">${this._escapeHtml(o.name||"Unnamed")}</span></td>
|
|
11951
12184
|
<td><span class="key-role">${this._escapeHtml(o.role||o.scopes||"--")}</span></td>
|
|
11952
|
-
<td>${
|
|
11953
|
-
<td>${
|
|
11954
|
-
<td><span class="${
|
|
12185
|
+
<td>${it(o.created_at||o.created)}</td>
|
|
12186
|
+
<td>${it(o.last_used_at||o.last_used)}</td>
|
|
12187
|
+
<td><span class="${c}">${this._escapeHtml(l)}</span></td>
|
|
11955
12188
|
<td><div class="actions-cell">${b}</div></td>
|
|
11956
12189
|
</tr>
|
|
11957
12190
|
`}).join("")}</tbody>
|
|
@@ -11969,7 +12202,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
11969
12202
|
${s}
|
|
11970
12203
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11971
12204
|
</div>
|
|
11972
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("show-create");t&&t.addEventListener("click",()=>{this._showCreateForm=!0,this.render()});let i=e.getElementById("dismiss-token");i&&i.addEventListener("click",()=>{this._newToken=null,this.render()});let a=e.getElementById("submit-create");a&&a.addEventListener("click",()=>{let r=e.getElementById("create-name"),o=e.getElementById("create-role"),n=e.getElementById("create-expiration");this._createName=r?.value||"",this._createRole=o?.value||"read",this._createExpiration=n?.value||"",this._createKey()});let s=e.getElementById("cancel-create");s&&s.addEventListener("click",()=>{this._showCreateForm=!1,this.render()}),e.querySelectorAll('[data-action="delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._deleteKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=null,this.render()})}),e.querySelectorAll('[data-action="rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-rotate"]').forEach(r=>{r.addEventListener("click",()=>{let o=e.getElementById(`rotate-grace-${r.dataset.keyId}`);this._rotateGracePeriod=o?.value||"24",this._rotateKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=null,this.render()})})}};customElements.get("loki-api-keys")||customElements.define("loki-api-keys",
|
|
12205
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("show-create");t&&t.addEventListener("click",()=>{this._showCreateForm=!0,this.render()});let i=e.getElementById("dismiss-token");i&&i.addEventListener("click",()=>{this._newToken=null,this.render()});let a=e.getElementById("submit-create");a&&a.addEventListener("click",()=>{let r=e.getElementById("create-name"),o=e.getElementById("create-role"),n=e.getElementById("create-expiration");this._createName=r?.value||"",this._createRole=o?.value||"read",this._createExpiration=n?.value||"",this._createKey()});let s=e.getElementById("cancel-create");s&&s.addEventListener("click",()=>{this._showCreateForm=!1,this.render()}),e.querySelectorAll('[data-action="delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._deleteKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=null,this.render()})}),e.querySelectorAll('[data-action="rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-rotate"]').forEach(r=>{r.addEventListener("click",()=>{let o=e.getElementById(`rotate-grace-${r.dataset.keyId}`);this._rotateGracePeriod=o?.value||"24",this._rotateKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=null,this.render()})})}};customElements.get("loki-api-keys")||customElements.define("loki-api-keys",ue);function Bt(d){return d?d.slug&&d.name?`${d.name} (${d.slug})`:d.name||d.slug||"Unknown":"Unknown"}var ge=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._tenants=[],this._selectedTenantId=null,this._dropdownOpen=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._outsideClickHandler=e=>{this._dropdownOpen&&!this.contains(e.target)&&(this._dropdownOpen=!1,this.render())},document.addEventListener("click",this._outsideClickHandler)}disconnectedCallback(){super.disconnectedCallback(),this._outsideClickHandler&&(document.removeEventListener("click",this._outsideClickHandler),this._outsideClickHandler=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadData(){try{this._loading=!0;let e=await this._api._get("/api/v2/tenants");this._tenants=Array.isArray(e)?e:e?.tenants||[],this._error=null}catch(e){this._error=`Failed to load tenants: ${e.message}`}finally{this._loading=!1}this.render()}_toggleDropdown(){this._dropdownOpen=!this._dropdownOpen,this.render()}_selectTenant(e,t){this._selectedTenantId=e,this._dropdownOpen=!1,this.render(),this.dispatchEvent(new CustomEvent("tenant-changed",{detail:{tenantId:e,tenantName:t},bubbles:!0,composed:!0}))}_getSelectedTenant(){return this._selectedTenantId==null?null:this._tenants.find(e=>(e.id||e.slug)===this._selectedTenantId)||null}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11973
12206
|
:host {
|
|
11974
12207
|
display: inline-block;
|
|
11975
12208
|
position: relative;
|
|
@@ -12103,20 +12336,20 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12103
12336
|
color: var(--loki-text-muted, #939084);
|
|
12104
12337
|
font-size: 12px;
|
|
12105
12338
|
}
|
|
12106
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getSelectedTenant(),i=t?
|
|
12339
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getSelectedTenant(),i=t?Bt(t):"All Tenants",a=this._dropdownOpen,s="";if(a){let r;if(this._loading)r='<div class="loading-text">Loading tenants...</div>';else if(this._error)r=`<div class="error-text">${this._escapeHtml(this._error)}</div>`;else{let o=this._selectedTenantId==null;r=`
|
|
12107
12340
|
<button class="dropdown-item all-tenants ${o?"selected":""}" data-tenant-id="">
|
|
12108
12341
|
<span class="tenant-name">All Tenants</span>
|
|
12109
12342
|
${o?'<span class="check-mark">*</span>':""}
|
|
12110
12343
|
</button>
|
|
12111
|
-
${this._tenants.map(n=>{let l=n.id||n.slug,
|
|
12112
|
-
<button class="dropdown-item ${
|
|
12344
|
+
${this._tenants.map(n=>{let l=n.id||n.slug,c=this._selectedTenantId===l;return`
|
|
12345
|
+
<button class="dropdown-item ${c?"selected":""}"
|
|
12113
12346
|
data-tenant-id="${this._escapeHtml(String(l))}"
|
|
12114
12347
|
data-tenant-name="${this._escapeHtml(n.name||"")}">
|
|
12115
12348
|
<div class="tenant-info">
|
|
12116
12349
|
<span class="tenant-name">${this._escapeHtml(n.name||"Unnamed")}</span>
|
|
12117
12350
|
${n.slug?`<span class="tenant-slug">${this._escapeHtml(n.slug)}</span>`:""}
|
|
12118
12351
|
</div>
|
|
12119
|
-
${
|
|
12352
|
+
${c?'<span class="check-mark">*</span>':""}
|
|
12120
12353
|
</button>
|
|
12121
12354
|
`}).join("")}
|
|
12122
12355
|
`}s=`<div class="dropdown">${r}</div>`}e.innerHTML=`
|
|
@@ -12128,7 +12361,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12128
12361
|
</button>
|
|
12129
12362
|
${s}
|
|
12130
12363
|
</div>
|
|
12131
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("trigger-btn");t&&t.addEventListener("click",i=>{i.stopPropagation(),this._toggleDropdown()}),e.querySelectorAll(".dropdown-item").forEach(i=>{i.addEventListener("click",a=>{a.stopPropagation();let s=i.dataset.tenantId||null,r=i.dataset.tenantName||null;this._selectTenant(s||null,r||"All Tenants")})})}};customElements.get("loki-tenant-switcher")||customElements.define("loki-tenant-switcher",
|
|
12364
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("trigger-btn");t&&t.addEventListener("click",i=>{i.stopPropagation(),this._toggleDropdown()}),e.querySelectorAll(".dropdown-item").forEach(i=>{i.addEventListener("click",a=>{a.stopPropagation();let s=i.dataset.tenantId||null,r=i.dataset.tenantName||null;this._selectTenant(s||null,r||"All Tenants")})})}};customElements.get("loki-tenant-switcher")||customElements.define("loki-tenant-switcher",ge);var Be={info:{color:"var(--loki-blue, #2F71E3)",label:"INFO",icon:"i"},success:{color:"var(--loki-green, #1FC5A8)",label:"OK",icon:"+"},warning:{color:"var(--loki-yellow, #D4A03C)",label:"WARN",icon:"!"},error:{color:"var(--loki-red, #C45B5B)",label:"ERR",icon:"x"}},Mt=100,me=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._items=[],this._filter="all",this._api=null,this._pollInterval=null,this._paused=!1,this._lastTimestamp=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let e=await this._api._get("/api/v2/activity"),t=e.events||e.activities||[];if(t.length>0){let i=t.filter(a=>!this._lastTimestamp||new Date(a.timestamp)>new Date(this._lastTimestamp)).map(a=>({id:a.id||crypto.randomUUID(),timestamp:a.timestamp||new Date().toISOString(),message:a.message||a.description||"",severity:a.severity||a.level||"info",source:a.source||a.component||"",isNew:!0}));i.length>0&&(this._items=[...i,...this._items].slice(0,Mt),this._lastTimestamp=i[0].timestamp,setTimeout(()=>{this._items.forEach(a=>a.isNew=!1)},600))}}catch{this._items.length===0&&(this._items=this._getDemoItems())}this.render()}_getDemoItems(){let e=Date.now();return[{id:"1",timestamp:new Date(e-2e3).toISOString(),message:"Build iteration #12 started",severity:"info",source:"runner"},{id:"2",timestamp:new Date(e-5e3).toISOString(),message:"Code review passed (3/3 reviewers)",severity:"success",source:"review"},{id:"3",timestamp:new Date(e-8e3).toISOString(),message:"Context window at 78% capacity",severity:"warning",source:"context"},{id:"4",timestamp:new Date(e-12e3).toISOString(),message:"Test suite completed: 42/42 passed",severity:"success",source:"testing"},{id:"5",timestamp:new Date(e-15e3).toISOString(),message:"RARV cycle: Verify phase complete",severity:"info",source:"rarv"}]}_formatTime(e){if(!e)return"";try{return new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return""}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getFilteredItems(){return this._filter==="all"?this._items:this._items.filter(e=>e.severity===this._filter)}_setFilter(e){this._filter=e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".filter-btn").forEach(i=>{i.addEventListener("click",()=>{this._setFilter(i.dataset.filter)})});let t=e.querySelector(".activity-feed");t&&(t.addEventListener("mouseenter",()=>{this._paused=!0}),t.addEventListener("mouseleave",()=>{this._paused=!1}))}_getStyles(){return`
|
|
12132
12365
|
:host {
|
|
12133
12366
|
display: block;
|
|
12134
12367
|
}
|
|
@@ -12314,7 +12547,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12314
12547
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary, #FFFEFB); }
|
|
12315
12548
|
::-webkit-scrollbar-thumb { background: var(--loki-border, #ECEAE3); border-radius: 3px; }
|
|
12316
12549
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light, #C5C0B1); }
|
|
12317
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getFilteredItems(),a=["all","info","success","warning","error"].map(r=>{let o=this._filter===r,n=r==="all"?"All":
|
|
12550
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getFilteredItems(),a=["all","info","success","warning","error"].map(r=>{let o=this._filter===r,n=r==="all"?"All":Be[r]?.label||r;return`<button class="filter-btn ${o?"active":""}" data-filter="${r}">${n}</button>`}).join(""),s;if(t.length===0?s='<div class="empty-state">No activity to display</div>':s=t.map(r=>{let o=Be[r.severity]||Be.info;return`
|
|
12318
12551
|
<div class="activity-item ${r.isNew?"new-item":""}">
|
|
12319
12552
|
<div class="severity-band" style="background: ${o.color};"></div>
|
|
12320
12553
|
<div class="item-content">
|
|
@@ -12335,7 +12568,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12335
12568
|
${s}
|
|
12336
12569
|
</div>
|
|
12337
12570
|
</div>
|
|
12338
|
-
`,this._bindEvents(),!this._paused){let r=e.querySelector(".activity-feed");r&&(r.scrollTop=0)}}};customElements.get("loki-activity-stream")||customElements.define("loki-activity-stream",
|
|
12571
|
+
`,this._bindEvents(),!this._paused){let r=e.querySelector(".activity-feed");r&&(r.scrollTop=0)}}};customElements.get("loki-activity-stream")||customElements.define("loki-activity-stream",me);var Pt={claude:{initial:"C",color:"#553DE9",bgColor:"rgba(85, 61, 233, 0.12)"},codex:{initial:"X",color:"#1FC5A8",bgColor:"rgba(31, 197, 168, 0.12)"},cline:{initial:"L",color:"#D4A03C",bgColor:"rgba(212, 160, 60, 0.12)"},aider:{initial:"A",color:"#C45B5B",bgColor:"rgba(196, 91, 91, 0.12)"}},at={healthy:"var(--loki-green, #1FC5A8)",degraded:"var(--loki-yellow, #D4A03C)",down:"var(--loki-red, #C45B5B)",unknown:"var(--loki-text-muted, #939084)"},ve=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._providers=[],this._expandedProvider=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),1e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let e=await this._api._get("/api/v2/providers/health");this._providers=e.providers||[]}catch{this._providers.length===0&&(this._providers=this._getDemoData())}this.render()}_getDemoData(){return[{name:"claude",status:"healthy",latency_ms:245,tokens_used:125400,model:"claude-opus-4-7",api_version:"v1",rate_limit:{remaining:45,limit:50},cost_usd:3.42},{name:"codex",status:"degraded",latency_ms:890,tokens_used:45200,model:"gpt-5.3-codex",api_version:"v1",rate_limit:{remaining:12,limit:60},cost_usd:.87},{name:"cline",status:"healthy",latency_ms:320,tokens_used:78600,model:"cline-default",api_version:"v1",rate_limit:{remaining:55,limit:60},cost_usd:1.15}]}_formatTokens(e){return e==null?"--":e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}_formatLatency(e){return e==null?"--":e<1e3?e+"ms":(e/1e3).toFixed(1)+"s"}_formatCost(e){return e==null?"--":"$"+e.toFixed(2)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleExpand(e){this._expandedProvider=this._expandedProvider===e?null:e,this.render()}_bindEvents(){this.shadowRoot.querySelectorAll(".provider-card").forEach(t=>{t.addEventListener("click",()=>{this._toggleExpand(t.dataset.provider)})})}_getStyles(){return`
|
|
12339
12572
|
:host {
|
|
12340
12573
|
display: block;
|
|
12341
12574
|
}
|
|
@@ -12514,7 +12747,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12514
12747
|
border: 1px solid var(--loki-border, #ECEAE3);
|
|
12515
12748
|
border-radius: 5px;
|
|
12516
12749
|
}
|
|
12517
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t;this._providers.length===0?t='<div class="empty-state">No provider data available</div>':t=`<div class="provider-grid">${this._providers.map(i=>{let a=
|
|
12750
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t;this._providers.length===0?t='<div class="empty-state">No provider data available</div>':t=`<div class="provider-grid">${this._providers.map(i=>{let a=Pt[i.name]||{initial:(i.name??"?").charAt(0).toUpperCase(),color:"#939084",bgColor:"rgba(147, 144, 132, 0.12)"},s=at[i.status]||at.unknown,r=this._expandedProvider===i.name,o=i.rate_limit?i.rate_limit.remaining/i.rate_limit.limit*100:100,n=o>50?"var(--loki-green)":o>20?"var(--loki-yellow)":"var(--loki-red)";return`
|
|
12518
12751
|
<div class="provider-card ${r?"expanded":""}" data-provider="${this._escapeHtml(i.name)}">
|
|
12519
12752
|
<div class="card-header">
|
|
12520
12753
|
<div class="provider-icon" style="background: ${a.bgColor}; color: ${a.color};">${a.initial}</div>
|
|
@@ -12566,7 +12799,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12566
12799
|
</div>
|
|
12567
12800
|
${t}
|
|
12568
12801
|
</div>
|
|
12569
|
-
`,this._bindEvents()}};customElements.get("loki-provider-health")||customElements.define("loki-provider-health",
|
|
12802
|
+
`,this._bindEvents()}};customElements.get("loki-provider-health")||customElements.define("loki-provider-health",ve);var Me=[{id:"planning",label:"Planning",icon:"P"},{id:"scaffolding",label:"Scaffolding",icon:"S"},{id:"implementation",label:"Implementation",icon:"I"},{id:"testing",label:"Testing",icon:"T"},{id:"review",label:"Review",icon:"R"},{id:"deploy",label:"Deploy",icon:"D"}],Pe={waiting:{color:"var(--loki-text-muted, #939084)",bgColor:"var(--loki-bg-tertiary, #ECEAE3)",label:"Waiting"},active:{color:"var(--loki-accent, #553DE9)",bgColor:"var(--loki-accent-muted, rgba(85, 61, 233, 0.10))",label:"Active"},complete:{color:"var(--loki-green, #1FC5A8)",bgColor:"var(--loki-green-muted, rgba(31, 197, 168, 0.12))",label:"Complete"},failed:{color:"var(--loki-red, #C45B5B)",bgColor:"var(--loki-red-muted, rgba(196, 91, 91, 0.12))",label:"Failed"}},be=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._stages=[],this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let e=await this._api._get("/api/v2/pipeline/status");this._stages=e.stages||[]}catch{this._stages.length===0&&(this._stages=this._getDemoData())}this.render()}_getDemoData(){return[{id:"planning",status:"complete",errors:0,duration_ms:12500},{id:"scaffolding",status:"complete",errors:0,duration_ms:8300},{id:"implementation",status:"active",errors:0,duration_ms:45e3},{id:"testing",status:"waiting",errors:0,duration_ms:null},{id:"review",status:"waiting",errors:0,duration_ms:null},{id:"deploy",status:"waiting",errors:0,duration_ms:null}]}_getStageData(e){return this._stages.find(t=>t.id===e)||{id:e,status:"waiting",errors:0}}_formatDuration(e){if(e==null||e<0)return"";if(e<1e3)return e+"ms";let t=Math.floor(e/1e3);if(t<60)return t+"s";let i=Math.floor(t/60),a=t%60;return i+"m "+a+"s"}_getStyles(){return`
|
|
12570
12803
|
:host {
|
|
12571
12804
|
display: block;
|
|
12572
12805
|
}
|
|
@@ -12729,7 +12962,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12729
12962
|
border-radius: 50%;
|
|
12730
12963
|
flex-shrink: 0;
|
|
12731
12964
|
}
|
|
12732
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=
|
|
12965
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=Me.map((a,s)=>{let r=this._getStageData(a.id),o=Pe[r.status]||Pe.waiting,n=r.status==="complete",l=r.status==="active",c=r.status==="failed",p=n?'<span class="stage-check">✓</span>':c?'<span class="stage-check">✗</span>':a.icon,h=`
|
|
12733
12966
|
<div class="stage-node">
|
|
12734
12967
|
<div class="stage-circle ${l?"active":""}"
|
|
12735
12968
|
style="background: ${o.bgColor}; color: ${o.color}; border: 2px solid ${o.color};">
|
|
@@ -12739,12 +12972,12 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12739
12972
|
${r.duration_ms?`<span class="stage-duration">${this._formatDuration(r.duration_ms)}</span>`:""}
|
|
12740
12973
|
${r.errors>0?`<span class="stage-error-count">${r.errors} error${r.errors>1?"s":""}</span>`:""}
|
|
12741
12974
|
</div>
|
|
12742
|
-
`;if(s<
|
|
12975
|
+
`;if(s<Me.length-1){let b=this._getStageData(Me[s+1].id),m=n,f=l||n&&(b.status==="active"||b.status==="waiting");return h+`
|
|
12743
12976
|
<div class="connector">
|
|
12744
12977
|
<div class="connector-line ${m?"completed":l?"active":"pending"}"></div>
|
|
12745
12978
|
${l?'<div class="flow-dot"></div>':""}
|
|
12746
12979
|
</div>
|
|
12747
|
-
`}return h}).join(""),i=Object.entries(
|
|
12980
|
+
`}return h}).join(""),i=Object.entries(Pe).map(([a,s])=>`<div class="legend-item">
|
|
12748
12981
|
<div class="legend-dot" style="background: ${s.color};"></div>
|
|
12749
12982
|
<span>${s.label}</span>
|
|
12750
12983
|
</div>`).join("");e.innerHTML=`
|
|
@@ -12760,12 +12993,12 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12760
12993
|
${i}
|
|
12761
12994
|
</div>
|
|
12762
12995
|
</div>
|
|
12763
|
-
`}};customElements.get("loki-pipeline-view")||customElements.define("loki-pipeline-view",
|
|
12764
|
-
rx="3" fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break;case"diamond":{let h=s/2;
|
|
12765
|
-
fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break}default:
|
|
12996
|
+
`}};customElements.get("loki-pipeline-view")||customElements.define("loki-pipeline-view",be);var fe={episode:{color:"var(--loki-blue, #2F71E3)",shape:"circle",label:"Episode"},pattern:{color:"var(--loki-green, #1FC5A8)",shape:"square",label:"Pattern"},skill:{color:"var(--loki-purple, #553DE9)",shape:"diamond",label:"Skill"}};function Ft(d,e,t){let i=e/2,a=t/2,s=Math.min(i,a)*.65,r=d.length;return d.map((o,n)=>{let l=2*Math.PI*n/r-Math.PI/2,c=o.importance||.5,p=s*(.5+c*.5);return{...o,x:i+p*Math.cos(l),y:a+p*Math.sin(l)}})}var ke=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._nodes=[],this._edges=[],this._selectedNode=null,this._api=null,this._pollInterval=null,this._graphWidth=600,this._graphHeight=400}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),15e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let e=await this._api._get("/api/v2/memory/graph");this._nodes=e.nodes||[],this._edges=e.edges||[]}catch{if(this._nodes.length===0){let e=this._getDemoData();this._nodes=e.nodes,this._edges=e.edges}}this.render()}_getDemoData(){return{nodes:[{id:"ep1",type:"episode",label:"Build iteration #12",importance:.8,details:"Completed scaffolding and initial implementation"},{id:"ep2",type:"episode",label:"Code review #5",importance:.6,details:"Quality gate passed with 3/3 approval"},{id:"ep3",type:"episode",label:"Test failure #3",importance:.7,details:"Integration test timeout resolved"},{id:"pt1",type:"pattern",label:"Error recovery",importance:.9,details:"Retry with exponential backoff pattern"},{id:"pt2",type:"pattern",label:"API design",importance:.7,details:"REST endpoint naming conventions"},{id:"pt3",type:"pattern",label:"Test structure",importance:.5,details:"Arrange-Act-Assert with setup helpers"},{id:"sk1",type:"skill",label:"Playwright E2E",importance:.85,details:"Browser automation test writing"},{id:"sk2",type:"skill",label:"FastAPI routing",importance:.6,details:"Python API server development"}],edges:[{source:"ep1",target:"pt1",strength:.8},{source:"ep1",target:"sk1",strength:.6},{source:"ep2",target:"pt2",strength:.9},{source:"ep3",target:"pt1",strength:.7},{source:"ep3",target:"pt3",strength:.5},{source:"pt1",target:"sk2",strength:.4},{source:"pt2",target:"sk2",strength:.7},{source:"pt3",target:"sk1",strength:.6}]}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_selectNode(e){this._selectedNode=this._selectedNode===e?null:e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".graph-node").forEach(t=>{t.addEventListener("click",()=>{this._selectNode(t.dataset.nodeId)})}),e.querySelectorAll(".close-detail").forEach(t=>{t.addEventListener("click",()=>{this._selectedNode=null,this.render()})})}_renderNodeShape(e,t,i){let a=fe[e.type]||fe.episode,s=10+(e.importance||.5)*16,r=this._selectedNode===e.id,o=r?"var(--loki-accent, #553DE9)":a.color,n=r?3:1.5,l=this._selectedNode&&!r?.4:1,c;switch(a.shape){case"square":c=`<rect x="${t-s/2}" y="${i-s/2}" width="${s}" height="${s}"
|
|
12997
|
+
rx="3" fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break;case"diamond":{let h=s/2;c=`<polygon points="${t},${i-h} ${t+h},${i} ${t},${i+h} ${t-h},${i}"
|
|
12998
|
+
fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break}default:c=`<circle cx="${t}" cy="${i}" r="${s/2}" fill="${a.color}" fill-opacity="0.2"
|
|
12766
12999
|
stroke="${o}" stroke-width="${n}" opacity="${l}" />`}let p=`<text x="${t}" y="${i+s/2+14}" text-anchor="middle" font-size="10"
|
|
12767
13000
|
font-family="Inter, sans-serif" fill="var(--loki-text-secondary, #36342E)" opacity="${l}">${this._escapeHtml(e.label)}</text>`;return`<g class="graph-node" data-node-id="${this._escapeHtml(e.id)}" style="cursor: pointer;">
|
|
12768
|
-
${
|
|
13001
|
+
${c}${p}
|
|
12769
13002
|
</g>`}_renderEdge(e,t){let i=t.find(n=>n.id===e.source),a=t.find(n=>n.id===e.target);if(!i||!a)return"";let s=(e.strength||1)<.6,r=this._selectedNode?e.source===this._selectedNode||e.target===this._selectedNode?.8:.15:.4,o=s?'stroke-dasharray="4 4"':"";return`<line x1="${i.x}" y1="${i.y}" x2="${a.x}" y2="${a.y}"
|
|
12770
13003
|
stroke="var(--loki-border-light, #C5C0B1)" stroke-width="1.5" opacity="${r}" ${o} />`}_getStyles(){return`
|
|
12771
13004
|
:host {
|
|
@@ -12921,17 +13154,17 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12921
13154
|
</div>
|
|
12922
13155
|
<div class="empty-state">No memory entries to visualize</div>
|
|
12923
13156
|
</div>
|
|
12924
|
-
`;return}let t=this._graphWidth,i=this._graphHeight,a=
|
|
13157
|
+
`;return}let t=this._graphWidth,i=this._graphHeight,a=Ft(this._nodes,t,i),s=this._edges.map(l=>this._renderEdge(l,a)).join(""),r=a.map(l=>this._renderNodeShape(l,l.x,l.y)).join(""),o="";if(this._selectedNode){let l=this._nodes.find(c=>c.id===this._selectedNode);if(l){let c=fe[l.type]||fe.episode;o=`
|
|
12925
13158
|
<div class="detail-panel">
|
|
12926
13159
|
<div class="detail-header">
|
|
12927
13160
|
<span class="detail-title">${this._escapeHtml(l.label)}</span>
|
|
12928
|
-
<span class="detail-type" style="background: ${
|
|
13161
|
+
<span class="detail-type" style="background: ${c.color}; color: white;">${c.label}</span>
|
|
12929
13162
|
<button class="close-detail" title="Close">✕</button>
|
|
12930
13163
|
</div>
|
|
12931
13164
|
<div class="detail-body">${this._escapeHtml(l.details||"No details available")}</div>
|
|
12932
13165
|
</div>
|
|
12933
|
-
`}}let n=Object.entries(
|
|
12934
|
-
<div class="legend-shape">${
|
|
13166
|
+
`}}let n=Object.entries(fe).map(([,l])=>{let c;return l.shape==="circle"?c=`<div class="legend-circle" style="border-color: ${l.color};"></div>`:l.shape==="square"?c=`<div class="legend-square" style="border-color: ${l.color};"></div>`:c=`<div class="legend-diamond" style="border-color: ${l.color};"></div>`,`<div class="legend-item">
|
|
13167
|
+
<div class="legend-shape">${c}</div>
|
|
12935
13168
|
<span>${l.label}</span>
|
|
12936
13169
|
</div>`}).join("");e.innerHTML=`
|
|
12937
13170
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
@@ -12948,7 +13181,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
12948
13181
|
</div>
|
|
12949
13182
|
<div class="legend">${n}</div>
|
|
12950
13183
|
</div>
|
|
12951
|
-
`,this._bindEvents()}};customElements.get("loki-memory-graph")||customElements.define("loki-memory-graph",
|
|
13184
|
+
`,this._bindEvents()}};customElements.get("loki-memory-graph")||customElements.define("loki-memory-graph",ke);var Fe={planning:{color:"var(--loki-blue, #2F71E3)",label:"Planning"},building:{color:"var(--loki-green, #1FC5A8)",label:"Building"},implementation:{color:"var(--loki-green, #1FC5A8)",label:"Building"},testing:{color:"var(--loki-purple, #553DE9)",label:"Testing"},review:{color:"var(--loki-yellow, #D4A03C)",label:"Review"},overhead:{color:"var(--loki-text-muted, #939084)",label:"Overhead"}},xe=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._phases=[],this._budget=null,this._totalCost=0,this._hoveredPhase=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),1e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let e=await this._api._get("/api/v2/cost/breakdown");this._phases=e.phases||[],this._budget=e.budget_usd||null,this._totalCost=e.total_usd||this._phases.reduce((t,i)=>t+(i.cost_usd||0),0)}catch{this._phases.length===0&&(this._phases=this._getDemoData(),this._budget=10,this._totalCost=this._phases.reduce((e,t)=>e+t.cost_usd,0))}this.render()}_getDemoData(){return[{phase:"planning",cost_usd:.85,tokens:12400},{phase:"building",cost_usd:3.2,tokens:68500},{phase:"testing",cost_usd:1.45,tokens:31200},{phase:"review",cost_usd:.9,tokens:18800},{phase:"overhead",cost_usd:.35,tokens:5600}]}_formatCost(e){return e==null?"--":"$"+e.toFixed(2)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_bindEvents(){this.shadowRoot.querySelectorAll(".waterfall-bar").forEach(t=>{t.addEventListener("mouseenter",()=>{this._hoveredPhase=t.dataset.phase,this._updateTooltip(t)}),t.addEventListener("mouseleave",()=>{this._hoveredPhase=null,this._hideTooltip()})})}_updateTooltip(e){let t=this.shadowRoot.querySelector(".tooltip");if(!t)return;let i=this._phases.find(o=>o.phase===this._hoveredPhase);if(!i)return;let a=Fe[i.phase]||{label:i.phase};t.innerHTML=`<strong>${a.label}</strong>: ${this._formatCost(i.cost_usd)}`,t.style.display="block";let s=e.getBoundingClientRect(),r=this.shadowRoot.querySelector(".chart-area").getBoundingClientRect();t.style.left=s.left-r.left+s.width/2+"px",t.style.top=s.top-r.top-30+"px"}_hideTooltip(){let e=this.shadowRoot.querySelector(".tooltip");e&&(e.style.display="none")}_getStyles(){return`
|
|
12952
13185
|
:host {
|
|
12953
13186
|
display: block;
|
|
12954
13187
|
}
|
|
@@ -13138,21 +13371,21 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
13138
13371
|
</div>
|
|
13139
13372
|
<div class="empty-state">No cost data available</div>
|
|
13140
13373
|
</div>
|
|
13141
|
-
`;return}let t=Math.max(...this._phases.map(l=>l.cost_usd||0),.01),i=160,a=this._budget?Math.max(t,this._budget):t,s=this._budget?this._budget/a*i:null,r=this._phases.map(l=>{let
|
|
13374
|
+
`;return}let t=Math.max(...this._phases.map(l=>l.cost_usd||0),.01),i=160,a=this._budget?Math.max(t,this._budget):t,s=this._budget?this._budget/a*i:null,r=this._phases.map(l=>{let c=Fe[l.phase]||{color:"var(--loki-text-muted)",label:l.phase},p=(l.cost_usd||0)/a*i,h=this._hoveredPhase===l.phase;return`
|
|
13142
13375
|
<div class="bar-group">
|
|
13143
13376
|
<span class="bar-value">${this._formatCost(l.cost_usd)}</span>
|
|
13144
13377
|
<div class="waterfall-bar" data-phase="${this._escapeHtml(l.phase)}"
|
|
13145
|
-
style="height: ${Math.max(p,4)}px; background: ${
|
|
13378
|
+
style="height: ${Math.max(p,4)}px; background: ${c.color}; ${h?"opacity: 0.85;":""}">
|
|
13146
13379
|
</div>
|
|
13147
|
-
<span class="bar-label">${
|
|
13380
|
+
<span class="bar-label">${c.label}</span>
|
|
13148
13381
|
</div>
|
|
13149
13382
|
`}).join(""),o=s!=null?`
|
|
13150
13383
|
<div class="budget-line" style="bottom: ${s+40}px;">
|
|
13151
13384
|
<span class="budget-label">Budget: ${this._formatCost(this._budget)}</span>
|
|
13152
13385
|
</div>
|
|
13153
|
-
`:"",n=this._phases.map(l=>{let
|
|
13154
|
-
<div class="summary-dot" style="background: ${
|
|
13155
|
-
<span class="summary-label">${
|
|
13386
|
+
`:"",n=this._phases.map(l=>{let c=Fe[l.phase]||{color:"var(--loki-text-muted)",label:l.phase},p=this._totalCost>0?(l.cost_usd/this._totalCost*100).toFixed(0):0;return`<div class="summary-item">
|
|
13387
|
+
<div class="summary-dot" style="background: ${c.color};"></div>
|
|
13388
|
+
<span class="summary-label">${c.label}</span>
|
|
13156
13389
|
<span class="summary-value">${this._formatCost(l.cost_usd)} (${p}%)</span>
|
|
13157
13390
|
</div>`}).join("");e.innerHTML=`
|
|
13158
13391
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
@@ -13172,7 +13405,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
13172
13405
|
</div>
|
|
13173
13406
|
</div>
|
|
13174
13407
|
</div>
|
|
13175
|
-
`,this._bindEvents()}};customElements.get("loki-cost-waterfall")||customElements.define("loki-cost-waterfall",
|
|
13408
|
+
`,this._bindEvents()}};customElements.get("loki-cost-waterfall")||customElements.define("loki-cost-waterfall",xe);var jt={1:{bg:"rgba(212, 160, 60, 0.15)",border:"#D4A03C",label:"1st"},2:{bg:"rgba(147, 144, 132, 0.15)",border:"#939084",label:"2nd"},3:{bg:"rgba(196, 130, 91, 0.15)",border:"#C4825B",label:"3rd"}},_e=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._agents=[],this._expandedAgent=null,this._api=null,this._pollInterval=null,this._previousRanks={}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),1e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let t=(await this._api._get("/api/v2/agents/leaderboard")).agents||[],i={};t.forEach((a,s)=>{i[a.type||a.name]=s+1}),this._previousRanks={...this._currentRanks||{}},this._currentRanks=i,this._agents=t}catch{this._agents.length===0&&(this._agents=this._getDemoData(),this._currentRanks={},this._agents.forEach((e,t)=>{this._currentRanks[e.type]=t+1}),this._previousRanks={})}this.render()}_getDemoData(){return[{type:"code-generator",name:"Code Generator",tasks:24,quality:9.2,speed:"fast",cost_usd:2.4},{type:"test-writer",name:"Test Writer",tasks:18,quality:9,speed:"fast",cost_usd:1.2},{type:"code-reviewer",name:"Code Reviewer",tasks:15,quality:8.8,speed:"medium",cost_usd:1.8},{type:"architect",name:"Architect",tasks:8,quality:9.5,speed:"slow",cost_usd:3.1},{type:"debugger",name:"Debugger",tasks:12,quality:8.5,speed:"fast",cost_usd:.95},{type:"doc-writer",name:"Documentation",tasks:10,quality:8.3,speed:"fast",cost_usd:.6}]}_getRankChange(e){let t=this._currentRanks?.[e],i=this._previousRanks?.[e];return t==null||i==null?0:i-t}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleAgent(e){this._expandedAgent=this._expandedAgent===e?null:e,this.render()}_bindEvents(){this.shadowRoot.querySelectorAll(".agent-row").forEach(t=>{t.addEventListener("click",()=>{this._toggleAgent(t.dataset.agent)})})}_getQualityColor(e){return e>=9?"var(--loki-green, #1FC5A8)":e>=8?"var(--loki-blue, #2F71E3)":e>=7?"var(--loki-yellow, #D4A03C)":"var(--loki-red, #C45B5B)"}_getSpeedLabel(e){return e==="fast"?{label:"Fast",color:"var(--loki-green, #1FC5A8)"}:e==="medium"?{label:"Medium",color:"var(--loki-yellow, #D4A03C)"}:{label:"Slow",color:"var(--loki-red, #C45B5B)"}}_getStyles(){return`
|
|
13176
13409
|
:host {
|
|
13177
13410
|
display: block;
|
|
13178
13411
|
}
|
|
@@ -13385,7 +13618,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
13385
13618
|
</div>
|
|
13386
13619
|
<div class="empty-state">No agent performance data available</div>
|
|
13387
13620
|
</div>
|
|
13388
|
-
`;return}let t=this._agents.map((i,a)=>{let s=a+1,r=
|
|
13621
|
+
`;return}let t=this._agents.map((i,a)=>{let s=a+1,r=jt[s],o=i.type||i.name,n=this._getRankChange(o),l=this._expandedAgent===o,c=this._getQualityColor(i.quality),p=this._getSpeedLabel(i.speed),h=(i.quality||0)/10*100,b;r?b=`<div class="rank-badge" style="background: ${r.bg}; color: ${r.border};">${s}</div>`:b=`<span class="rank-number" style="color: var(--loki-text-muted);">${s}</span>`;let m="";n>0?m=`<span class="rank-change rank-up">+${n}</span>`:n<0&&(m=`<span class="rank-change rank-down">${n}</span>`);let f=l?`
|
|
13389
13622
|
<div class="agent-detail">
|
|
13390
13623
|
<div class="detail-metric">
|
|
13391
13624
|
<span class="detail-label">Total Cost</span>
|
|
@@ -13411,8 +13644,8 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
13411
13644
|
<div class="metric-cell">${i.tasks||0}</div>
|
|
13412
13645
|
<div class="metric-cell">
|
|
13413
13646
|
<div class="quality-score">
|
|
13414
|
-
<span style="color: ${
|
|
13415
|
-
<div class="quality-bar"><div class="quality-fill" style="width: ${h}%; background: ${
|
|
13647
|
+
<span style="color: ${c};">${(i.quality||0).toFixed(1)}</span>
|
|
13648
|
+
<div class="quality-bar"><div class="quality-fill" style="width: ${h}%; background: ${c};"></div></div>
|
|
13416
13649
|
</div>
|
|
13417
13650
|
</div>
|
|
13418
13651
|
<div class="metric-cell">
|
|
@@ -13438,7 +13671,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
13438
13671
|
${t}
|
|
13439
13672
|
</div>
|
|
13440
13673
|
</div>
|
|
13441
|
-
`,this._bindEvents()}};customElements.get("loki-agent-leaderboard")||customElements.define("loki-agent-leaderboard",
|
|
13674
|
+
`,this._bindEvents()}};customElements.get("loki-agent-leaderboard")||customElements.define("loki-agent-leaderboard",_e);var st=50,ye=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._statusLoading=!1,this._statusError=null,this._status=null,this._eventsLoading=!1,this._eventsError=null,this._events=[],this._eventsSource=null,this._eventsCount=0,this._lookupId="",this._lookupLoading=!1,this._lookupError=null,this._lookupResult=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadStatus());break;case"theme":this._applyTheme(),this.render();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}_stopPolling(){}async _loadStatus(){this._statusLoading=!0,this._statusError=null,this.render();try{this._status=await this._api.get("/api/managed/status")}catch(e){this._statusError=e&&e.message?e.message:"Failed to load managed status",this._status=null}finally{this._statusLoading=!1}this._status&&this._status.enabled?await this._loadEvents():this.render()}async _loadEvents(e=st){this._eventsLoading=!0,this._eventsError=null,this.render();try{let t=await this._api.get("/api/managed/events?limit="+encodeURIComponent(e));Array.isArray(t)?(this._events=t,this._eventsCount=t.length,this._eventsSource=null):t&&typeof t=="object"?(this._events=Array.isArray(t.events)?t.events:[],this._eventsCount=typeof t.count=="number"?t.count:this._events.length,this._eventsSource=t.source||null):(this._events=[],this._eventsCount=0,this._eventsSource=null)}catch(t){this._eventsError=t&&t.message?t.message:"Failed to load managed events",this._events=[],this._eventsCount=0,this._eventsSource=null}finally{this._eventsLoading=!1,this.render()}}async _lookupMemoryVersion(){let e=(this._lookupId||"").trim();if(!e){this._lookupError="Enter a memory ID to look up",this._lookupResult=null,this.render();return}this._lookupLoading=!0,this._lookupError=null,this._lookupResult=null,this.render();try{let t="/api/managed/memory_versions/"+encodeURIComponent(e);this._lookupResult=await this._api.get(t)}catch(t){this._lookupError=t&&t.message?t.message:"Failed to load memory versions",this._lookupResult=null}finally{this._lookupLoading=!1,this.render()}}_onLookupInput(e){this._lookupId=e&&e.target?e.target.value:""}_onLookupKeyDown(e){e&&e.key==="Enter"&&(e.preventDefault(),this._lookupMemoryVersion())}_attachEventHandlers(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector("#refresh-status-btn");t&&t.addEventListener("click",()=>this._loadStatus());let i=e.querySelector("#refresh-events-btn");i&&i.addEventListener("click",()=>this._loadEvents());let a=e.querySelector("#lookup-input");a&&(a.addEventListener("input",r=>this._onLookupInput(r)),a.addEventListener("keydown",r=>this._onLookupKeyDown(r)));let s=e.querySelector("#lookup-btn");s&&s.addEventListener("click",()=>this._lookupMemoryVersion())}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_formatTimestamp(e){if(!e)return"";let t;return typeof e=="number"?t=new Date(e>1e12?e:e*1e3):t=new Date(e),Number.isNaN(t.getTime())?String(e):t.toISOString().replace("T"," ").replace(/\.\d+Z$/,"Z")}_renderStatusSection(){if(this._statusLoading)return'<div class="status-row muted">Loading managed memory status...</div>';if(this._statusError)return`
|
|
13442
13675
|
<div class="error-banner" role="alert">
|
|
13443
13676
|
<strong>Status error:</strong>
|
|
13444
13677
|
<span>${this._escapeHtml(this._statusError)}</span>
|
|
@@ -13817,7 +14050,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
13817
14050
|
${t?`
|
|
13818
14051
|
<div class="section">
|
|
13819
14052
|
<div class="panel-header">
|
|
13820
|
-
<h3 class="section-title">Recent events (limit ${
|
|
14053
|
+
<h3 class="section-title">Recent events (limit ${st})</h3>
|
|
13821
14054
|
<button id="refresh-events-btn" class="btn" type="button">Refresh events</button>
|
|
13822
14055
|
</div>
|
|
13823
14056
|
${this._renderEventsSection()}
|
|
@@ -13829,7 +14062,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
13829
14062
|
</div>
|
|
13830
14063
|
`:this._statusError?"":this._renderDisabledNotice()}
|
|
13831
14064
|
</div>
|
|
13832
|
-
`,this._attachEventHandlers()}};customElements.get("loki-managed-memory-panel")||customElements.define("loki-managed-memory-panel",
|
|
14065
|
+
`,this._attachEventHandlers()}};customElements.get("loki-managed-memory-panel")||customElements.define("loki-managed-memory-panel",ye);var we=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._items=[],this._loading=!1,this._error=null,this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadList(),this._pollInterval=setInterval(()=>this._loadList(),1e4)}disconnectedCallback(){super.disconnectedCallback(),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadList()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||(typeof window<"u"?window.location.origin:"");this._api=g({baseUrl:e})}async _loadList(){this._loading=!0,this._error=null;try{let e=await this._api.get("/api/escalations");this._items=Array.isArray(e&&e.escalations)?e.escalations:[]}catch(e){this._error=e&&e.message?e.message:String(e),this._items=[]}finally{this._loading=!1,this.render()}}async _openFile(e){this._activeFile=e,this._activeBody=null,this._activeBodyError=null,this.render();try{let t=(this._api.baseUrl||"")+"/api/escalations/"+encodeURIComponent(e),i=await fetch(t,{credentials:"include"});if(!i.ok)throw new Error("HTTP "+i.status);this._activeBody=await i.text()}catch(t){this._activeBodyError=t&&t.message?t.message:String(t)}this.render()}_closeFile(){this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this.render()}_formatSize(e){return typeof e!="number"?"--":e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":(e/(1024*1024)).toFixed(1)+" MB"}_formatDate(e){if(!e)return"--";try{let t=new Date(e);return isNaN(t.getTime())?e:t.toLocaleString()}catch{return e}}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}render(){let e=this.shadowRoot||this;if(!e)return;let t=`
|
|
13833
14066
|
<style>
|
|
13834
14067
|
:host { display: block; }
|
|
13835
14068
|
.esc-wrapper {
|
|
@@ -13899,7 +14132,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
13899
14132
|
border-radius: 4px;
|
|
13900
14133
|
}
|
|
13901
14134
|
</style>
|
|
13902
|
-
`,i="";this._loading&&this._items.length===0?i='<div class="esc-empty">Loading escalations...</div>':this._error?i='<div class="esc-error">Failed to load escalations: '+this._escapeHtml(this._error)+"</div>":!this._items||this._items.length===0?i='<div class="esc-empty">Escalations: no events yet. Handoff/escalation markdown documents written by the runner under .loki/escalations/ will appear here.</div>':i='<div class="esc-list">'+this._items.map(n=>{let l=this._escapeHtml(n.filename||""),
|
|
14135
|
+
`,i="";this._loading&&this._items.length===0?i='<div class="esc-empty">Loading escalations...</div>':this._error?i='<div class="esc-error">Failed to load escalations: '+this._escapeHtml(this._error)+"</div>":!this._items||this._items.length===0?i='<div class="esc-empty">Escalations: no events yet. Handoff/escalation markdown documents written by the runner under .loki/escalations/ will appear here.</div>':i='<div class="esc-list">'+this._items.map(n=>{let l=this._escapeHtml(n.filename||""),c=this._escapeHtml(this._formatSize(n.size_bytes)),p=this._escapeHtml(this._formatDate(n.modified_at));return'<div class="esc-item" data-filename="'+l+'"><span class="esc-name">'+l+'</span><span class="esc-meta">'+c+" · "+p+"</span></div>"}).join("")+"</div>";let a="";if(this._activeFile){let o=this._escapeHtml(this._activeFile),n;this._activeBodyError?n='<div class="esc-error">Failed to load: '+this._escapeHtml(this._activeBodyError)+"</div>":this._activeBody===null?n='<div class="esc-body">Loading '+o+"...</div>":n='<div class="esc-body">'+this._escapeHtml(this._activeBody)+"</div>",a='<div class="esc-viewer"><div class="esc-viewer-header"><span class="esc-name">'+o+'</span><button class="esc-close-btn" data-action="close">Close</button></div>'+n+"</div>"}e.innerHTML=t+'<div class="esc-wrapper"><div class="esc-explain">Handoff/escalation documents written under .loki/escalations/. Click an entry to view its contents.</div>'+i+a+"</div>",e.querySelectorAll(".esc-item").forEach(o=>{o.addEventListener("click",()=>{let n=o.getAttribute("data-filename");n&&this._openFile(n)})});let r=e.querySelector('.esc-close-btn[data-action="close"]');r&&r.addEventListener("click",()=>this._closeFile())}};typeof customElements<"u"&&!customElements.get("loki-escalations")&&customElements.define("loki-escalations",we);var $e=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._transcripts=[],this._hookEvents=[],this._loading=!1,this._error=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._load(),this._pollInterval=setInterval(()=>this._load(),3e4)}disconnectedCallback(){super.disconnectedCallback(),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._load()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||(typeof window<"u"?window.location.origin:"");this._api=g({baseUrl:e})}async _load(){this._loading=!0,this._error=null;try{let e=await this._api.get("/api/council/transcripts?limit=10");this._transcripts=Array.isArray(e&&e.transcripts)?e.transcripts:[]}catch(e){this._error=e&&e.message?e.message:String(e),this._transcripts=[]}try{let e=await this._api.get("/api/council/transcripts?limit=20&type_prefix=claude_hook_");this._hookEvents=Array.isArray(e&&e.hook_events)?e.hook_events:[]}catch{this._hookEvents=[]}finally{this._loading=!1,this.render()}}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_formatTimestamp(e){if(!e)return"--";try{let t=new Date(e);return isNaN(t.getTime())?e:t.toLocaleString()}catch{return e}}_truncate(e,t){if(!e)return"";let i=String(e);return i.length>t?i.slice(0,t)+"...":i}_verdictBadgeHtml(e){let t=String(e||"").toUpperCase();return t==="APPROVE"?'<span class="ct-badge ct-badge-approve">APPROVE</span>':t==="REJECT"?'<span class="ct-badge ct-badge-reject">REJECT</span>':t==="CANNOT_VALIDATE"?'<span class="ct-badge ct-badge-cannot">CANNOT_VALIDATE</span>':'<span class="ct-badge ct-badge-unknown">'+this._escapeHtml(t||"UNKNOWN")+"</span>"}_outcomeBadgeHtml(e){let t=String(e||"").toUpperCase();return t==="APPROVED"?'<span class="ct-badge ct-badge-approve">APPROVED</span>':t==="REJECTED"?'<span class="ct-badge ct-badge-reject">REJECTED</span>':t==="BLOCKED_BY_GATE"?'<span class="ct-badge ct-badge-blocked">BLOCKED BY GATE</span>':'<span class="ct-badge ct-badge-unknown">'+this._escapeHtml(t||"UNKNOWN")+"</span>"}_voterRowHtml(e,t){let i=e.is_contrarian===!0,a=i&&t===!0,s="ct-voter-row";i&&(s+=" ct-voter-contrarian"),a&&(s+=" ct-voter-flipped");let r=this._escapeHtml(e.name||"unknown"),o=this._verdictBadgeHtml(e.verdict),n=this._escapeHtml(this._truncate(e.reasoning,300)),l="",c="";a?(l='<span class="ct-badge ct-badge-override">OVERRIDE</span>',c=`<div class="ct-flip-caption">Devil's Advocate flipped this outcome</div>`):i&&e.triggered&&(l=`<span class="ct-badge ct-badge-da">DEVIL'S ADVOCATE</span>`);let p="";i&&Array.isArray(e.challenges)&&e.challenges.length>0&&(p='<ul class="ct-challenges">'+e.challenges.map(m=>"<li>"+this._escapeHtml(String(m))+"</li>").join("")+"</ul>");let h="";return Array.isArray(e.issues)&&e.issues.length>0&&(h='<ul class="ct-issues">'+e.issues.map(m=>{let f=this._escapeHtml(m.severity||""),x=this._escapeHtml(m.description||"");return'<li><span class="ct-issue-sev ct-issue-sev-'+f.toLowerCase()+'">'+f+"</span> "+x+"</li>"}).join("")+"</ul>"),'<div class="'+s+'"><div class="ct-voter-header"><span class="ct-voter-name">'+r+"</span>"+o+l+"</div>"+(n?'<div class="ct-voter-reason">'+n+"</div>":"")+p+h+c+"</div>"}_transcriptCardHtml(e){let t=this._escapeHtml(String(e.iteration||"--")),i=this._escapeHtml(this._formatTimestamp(e.timestamp)),a=this._escapeHtml(this._truncate(e.task_or_prd,200)),s=this._outcomeBadgeHtml(e.outcome),r=Array.isArray(e.voters)?e.voters:[],o=r.filter(m=>!m.is_contrarian),n=r.filter(m=>m.is_contrarian),l=o.map(m=>this._voterRowHtml(m,!1)).join(""),c="";e.contrarian_triggered&&(c='<div class="ct-contrarian-section"><div class="ct-section-label">Anti-Sycophancy Check</div>'+n.map(f=>this._voterRowHtml(f,e.contrarian_flipped)).join("")+"</div>");let p=typeof e.approve_count=="number"?e.approve_count:"--",h=typeof e.reject_count=="number"?e.reject_count:"--",b=typeof e.threshold=="number"?e.threshold:"--";return'<div class="ct-card"><div class="ct-card-header"><div class="ct-card-meta"><span class="ct-iter-label">Iteration '+t+'</span><span class="ct-ts">'+i+"</span></div>"+s+"</div>"+(a?'<div class="ct-prd-preview">'+a+"</div>":"")+'<div class="ct-tally">Approve: '+p+" · Reject: "+h+" · Threshold: "+b+'</div><div class="ct-voters">'+l+"</div>"+c+"</div>"}render(){let e=this.shadowRoot||this;if(!e)return;let t=`
|
|
13903
14136
|
<style>
|
|
13904
14137
|
:host { display: block; margin-top: 24px; }
|
|
13905
14138
|
.ct-wrapper {
|
|
@@ -14068,7 +14301,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
14068
14301
|
.ct-badge-da { background: #fdf3d4; color: #8a6c0e; }
|
|
14069
14302
|
.ct-badge-unknown { background: var(--bg-secondary, #F8F4F0); color: var(--text-muted, #939084); }
|
|
14070
14303
|
</style>
|
|
14071
|
-
`,i="";this._loading&&this._transcripts.length===0?i='<div class="ct-empty">Loading council transcripts...</div>':this._error?i='<div class="ct-error">Failed to load transcripts: '+this._escapeHtml(this._error)+"</div>":!this._transcripts||this._transcripts.length===0?i='<div class="ct-empty">No council rounds recorded yet -- transcripts appear after the first iteration vote.</div>':i='<div class="ct-list">'+this._transcripts.map(s=>this._transcriptCardHtml(s)).join("")+"</div>",e.innerHTML=t+'<div class="ct-wrapper"><h3 class="ct-heading">Council Transcripts</h3><div class="ct-explain">Per-iteration voting records from .loki/council/transcripts/. Polls every 30 seconds.</div>'+i+this._hookEventsHtml()+"</div>"}_hookEventsHtml(){let e=Array.isArray(this._hookEvents)?this._hookEvents:[],t;return e.length===0?t='<div class="ct-empty">No live tool activity yet -- Claude hook events stream here while a run is active.</div>':t='<div class="ct-voters">'+e.slice(0,20).map(a=>{let s=this._escapeHtml(a.type||a.event||"event"),r=this._escapeHtml(this._formatTimestamp(a.timestamp||a.ts)),o=this._escapeHtml(this._truncate(a.tool||a.message||a.summary||(a.data?JSON.stringify(a.data):""),120));return'<div class="ct-voter-row"><span class="ct-iter-label">'+s+'</span> <span class="ct-ts">'+r+"</span>"+(o?'<div class="ct-prd-preview">'+o+"</div>":"")+"</div>"}).join("")+"</div>",'<h3 class="ct-heading" style="margin-top:24px;">Live Tool Activity</h3><div class="ct-explain">Claude hook events (PreToolUse / PostToolUse / Stop) streamed from .loki/events.jsonl. Lets you watch background tool calls as they run.</div>'+t}};typeof customElements<"u"&&!customElements.get("loki-council-transcripts")&&customElements.define("loki-council-transcripts"
|
|
14304
|
+
`,i="";this._loading&&this._transcripts.length===0?i='<div class="ct-empty">Loading council transcripts...</div>':this._error?i='<div class="ct-error">Failed to load transcripts: '+this._escapeHtml(this._error)+"</div>":!this._transcripts||this._transcripts.length===0?i='<div class="ct-empty">No council rounds recorded yet -- transcripts appear after the first iteration vote.</div>':i='<div class="ct-list">'+this._transcripts.map(s=>this._transcriptCardHtml(s)).join("")+"</div>",e.innerHTML=t+'<div class="ct-wrapper"><h3 class="ct-heading">Council Transcripts</h3><div class="ct-explain">Per-iteration voting records from .loki/council/transcripts/. Polls every 30 seconds.</div>'+i+this._hookEventsHtml()+"</div>"}_hookEventsHtml(){let e=Array.isArray(this._hookEvents)?this._hookEvents:[],t;return e.length===0?t='<div class="ct-empty">No live tool activity yet -- Claude hook events stream here while a run is active.</div>':t='<div class="ct-voters">'+e.slice(0,20).map(a=>{let s=this._escapeHtml(a.type||a.event||"event"),r=this._escapeHtml(this._formatTimestamp(a.timestamp||a.ts)),o=this._escapeHtml(this._truncate(a.tool||a.message||a.summary||(a.data?JSON.stringify(a.data):""),120));return'<div class="ct-voter-row"><span class="ct-iter-label">'+s+'</span> <span class="ct-ts">'+r+"</span>"+(o?'<div class="ct-prd-preview">'+o+"</div>":"")+"</div>"}).join("")+"</div>",'<h3 class="ct-heading" style="margin-top:24px;">Live Tool Activity</h3><div class="ct-explain">Claude hook events (PreToolUse / PostToolUse / Stop) streamed from .loki/events.jsonl. Lets you watch background tool calls as they run.</div>'+t}};typeof customElements<"u"&&!customElements.get("loki-council-transcripts")&&customElements.define("loki-council-transcripts",$e);var Ut=[{id:"overview",label:"Overview"},{id:"architecture",label:"Architecture"},{id:"modules",label:"Key Modules"},{id:"data-flow",label:"Data Flow"},{id:"ask",label:"Ask"}],Ee=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._activeTab="overview",this._loading=!1,this._error=null,this._api=null,this._meta=null,this._sectionCache={},this._question="",this._answer=null,this._asking=!1,this._askError=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadMeta()}attributeChangedCallback(e,t,i){e==="api-url"&&this._api&&(this._api.baseUrl=i)}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e})}async _loadMeta(){this._loading=!0,this._error=null,this.render();try{this._meta=await this._api._get("/api/wiki")}catch(e){this._error=e&&e.message?e.message:"Failed to load wiki"}finally{this._loading=!1,this.render();let e=this._activeTab;this._meta&&this._meta.generated&&(e==="architecture"||e==="modules"||e==="data-flow")&&!this._sectionCache[e]&&this._loadSection(e).then(()=>this.render())}}async _loadSection(e){if(this._sectionCache[e])return this._sectionCache[e];try{let t=await this._api._get(`/api/wiki/${encodeURIComponent(e)}`);return this._sectionCache[e]=t,t}catch(t){return this._sectionCache[e]={error:t&&t.message||"load failed"},this._sectionCache[e]}}async _selectTab(e){this._activeTab=e,e==="architecture"||e==="modules"||e==="data-flow"?this._meta&&this._meta.generated?(this.render(),await this._loadSection(e)):this.render():this.render()}async _ask(){let e=(this._question||"").trim();if(e){this._asking=!0,this._askError=null,this._answer=null,this.render();try{this._answer=await this._api._post("/api/wiki/ask",{question:e},{timeout:2e5})}catch(t){this._askError=t&&t.message?t.message:"Ask failed"}finally{this._asking=!1,this.render()}}}_esc(e){return String(e??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}_renderCitations(e){return!e||!e.length?"":`<div class="cites"><strong>Sources:</strong><ul>${e.map(i=>`<li><code>${this._esc(i.file)}:${this._esc(i.line)}</code></li>`).join("")}</ul></div>`}_renderOverview(){let e=this._meta;if(!e||!e.generated)return`<div class="empty">
|
|
14072
14305
|
<p>No wiki has been generated for this project yet.</p>
|
|
14073
14306
|
<p>Run <code>loki wiki generate</code> to build a cited codebase wiki.</p>
|
|
14074
14307
|
</div>`;let t=(e.sections||[]).map(i=>`<li>${this._esc(i.title)} <span class="dim">(${this._esc(i.citation_count)} citations)</span></li>`).join("");return`<div class="overview">
|
|
@@ -14095,7 +14328,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
14095
14328
|
</div>
|
|
14096
14329
|
<p class="dim">Answers are grounded in the indexed codebase and cite real file:line locations.</p>
|
|
14097
14330
|
${e}
|
|
14098
|
-
</div>`}_renderBody(){if(this._loading)return'<div class="empty">Loading wiki...</div>';if(this._error)return`<div class="error">${this._esc(this._error)}</div>`;switch(this._activeTab){case"overview":return this._renderOverview();case"architecture":return this._renderSection("architecture");case"modules":return this._renderSection("modules");case"data-flow":return this._renderSection("data-flow");case"ask":return this._renderAsk();default:return this._renderOverview()}}render(){if(!this.shadowRoot)return;let e=
|
|
14331
|
+
</div>`}_renderBody(){if(this._loading)return'<div class="empty">Loading wiki...</div>';if(this._error)return`<div class="error">${this._esc(this._error)}</div>`;switch(this._activeTab){case"overview":return this._renderOverview();case"architecture":return this._renderSection("architecture");case"modules":return this._renderSection("modules");case"data-flow":return this._renderSection("data-flow");case"ask":return this._renderAsk();default:return this._renderOverview()}}render(){if(!this.shadowRoot)return;let e=Ut.map(a=>`<button class="tab ${a.id===this._activeTab?"active":""}"
|
|
14099
14332
|
data-tab="${a.id}">${this._esc(a.label)}</button>`).join("");this.shadowRoot.innerHTML=`
|
|
14100
14333
|
<style>
|
|
14101
14334
|
:host { display: block; font-family: var(--loki-font, system-ui, sans-serif);
|
|
@@ -14123,7 +14356,7 @@ var LokiDashboard=(()=>{var Ee=Object.defineProperty;var rt=Object.getOwnPropert
|
|
|
14123
14356
|
</style>
|
|
14124
14357
|
<div class="tabs">${e}</div>
|
|
14125
14358
|
<div class="content">${this._renderBody()}</div>
|
|
14126
|
-
`,this.shadowRoot.querySelectorAll(".tab").forEach(a=>{a.addEventListener("click",()=>this._selectTab(a.dataset.tab))});let t=this.shadowRoot.getElementById("wiki-q");t&&(t.addEventListener("input",a=>{this._question=a.target.value}),t.addEventListener("keydown",a=>{a.key==="Enter"&&this._ask()}));let i=this.shadowRoot.getElementById("wiki-ask-btn");i&&i.addEventListener("click",()=>this._ask())}};customElements.get("loki-wiki-browser")||customElements.define("loki-wiki-browser"
|
|
14359
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(a=>{a.addEventListener("click",()=>this._selectTab(a.dataset.tab))});let t=this.shadowRoot.getElementById("wiki-q");t&&(t.addEventListener("input",a=>{this._question=a.target.value}),t.addEventListener("keydown",a=>{a.key==="Enter"&&this._ask()}));let i=this.shadowRoot.getElementById("wiki-ask-btn");i&&i.addEventListener("click",()=>this._ask())}};customElements.get("loki-wiki-browser")||customElements.define("loki-wiki-browser",Ee);var Nt="1.4.0";function Ot(d={}){return d.theme?_.setTheme(d.theme):d.autoDetectContext!==!1?_.init():R.init(),d.apiUrl&&g({baseUrl:d.apiUrl}),{theme:_.getTheme(),context:_.detectContext()}}return gt(qt);})();
|
|
14127
14360
|
|
|
14128
14361
|
|
|
14129
14362
|
// Initialize dashboard when DOM is ready
|
|
@@ -14545,7 +14778,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
14545
14778
|
document.addEventListener('keydown', function(e) {
|
|
14546
14779
|
if ((e.metaKey || e.ctrlKey) && ((e.key >= '1' && e.key <= '9') || e.key === '0')) {
|
|
14547
14780
|
e.preventDefault();
|
|
14548
|
-
var sections = ['overview', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'trust', 'checkpoint', 'context', 'notifications', 'migration', 'analytics', 'escalations'];
|
|
14781
|
+
var sections = ['overview', 'fleet', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'trust', 'checkpoint', 'context', 'notifications', 'migration', 'analytics', 'escalations'];
|
|
14549
14782
|
var idx = e.key === '0' ? 9 : parseInt(e.key) - 1;
|
|
14550
14783
|
if (idx < sections.length) switchSection(sections[idx]);
|
|
14551
14784
|
}
|
|
@@ -14586,7 +14819,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
14586
14819
|
// Skip if modifier keys are held (let browser defaults work)
|
|
14587
14820
|
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
14588
14821
|
|
|
14589
|
-
var sections = ['overview', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'trust', 'checkpoint', 'context', 'notifications', 'migration', 'analytics', 'escalations'];
|
|
14822
|
+
var sections = ['overview', 'fleet', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'trust', 'checkpoint', 'context', 'notifications', 'migration', 'analytics', 'escalations'];
|
|
14590
14823
|
|
|
14591
14824
|
switch (e.key) {
|
|
14592
14825
|
// Section navigation: 1-9, 0
|