loki-mode 7.90.0 → 7.90.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/run.sh +7 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +137 -2
- package/dashboard/static/index.html +243 -383
- package/docs/INSTALLATION.md +2 -2
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
|
@@ -37,7 +37,10 @@
|
|
|
37
37
|
--loki-transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
/* v7.90.1: dark mode removed (light-only). Disabled via an always-false media
|
|
41
|
+
query so an OS dark preference no longer flips the dashboard to the dark
|
|
42
|
+
palette the founder found worse. Kept (not deleted) to minimize churn. */
|
|
43
|
+
@media (prefers-color-scheme: dark) and (max-width: 0px) {
|
|
41
44
|
:root {
|
|
42
45
|
--loki-bg-primary: #0F0B1A;
|
|
43
46
|
--loki-bg-secondary: #150F24;
|
|
@@ -1023,11 +1026,8 @@
|
|
|
1023
1026
|
</div>
|
|
1024
1027
|
</div>
|
|
1025
1028
|
</div>
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
<svg id="theme-icon-moon" width="14" height="14" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" fill="none" style="display:none"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg>
|
|
1029
|
-
<span id="theme-label">Dark</span>
|
|
1030
|
-
</button>
|
|
1029
|
+
<!-- v7.90.1: dark mode removed (light-only). The theme toggle and its
|
|
1030
|
+
handler are gone; the dashboard ships a single light theme. -->
|
|
1031
1031
|
</div>
|
|
1032
1032
|
</div>
|
|
1033
1033
|
</aside>
|
|
@@ -1538,24 +1538,24 @@
|
|
|
1538
1538
|
|
|
1539
1539
|
<!-- Inlined JavaScript Bundle -->
|
|
1540
1540
|
<script>
|
|
1541
|
-
var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropertyDescriptor;var vt=Object.getOwnPropertyNames;var ft=Object.prototype.hasOwnProperty;var bt=(d,e,t)=>e in d?Ae(d,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[e]=t;var kt=(d,e)=>{for(var t in e)Ae(d,t,{get:e[t],enumerable:!0})},xt=(d,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of vt(e))!ft.call(d,a)&&a!==t&&Ae(d,a,{get:()=>e[a],enumerable:!(i=mt(e,a))||i.enumerable});return d};var _t=d=>xt(Ae({},"__esModule",{value:!0}),d);var S=(d,e,t)=>bt(d,typeof e!="symbol"?e+"":e,t);var Xt={};kt(Xt,{ANIMATION:()=>z,ARIA_PATTERNS:()=>De,ApiEvents:()=>v,BASE_STYLES:()=>N,BREAKPOINTS:()=>Te,COMMON_STYLES:()=>Ge,KEYBOARD_SHORTCUTS:()=>Le,KeyboardHandler:()=>I,LokiActivityStream:()=>ve,LokiAgentLeaderboard:()=>ye,LokiAnalytics:()=>le,LokiApiClient:()=>F,LokiApiKeys:()=>ge,LokiAppPreview:()=>Z,LokiAppStatus:()=>X,LokiAuditViewer:()=>ue,LokiChecklistViewer:()=>Q,LokiCheckpointViewer:()=>te,LokiContextTracker:()=>ie,LokiCostDashboard:()=>ee,LokiCostWaterfall:()=>_e,LokiCouncilDashboard:()=>Y,LokiCouncilTranscripts:()=>Ee,LokiElement:()=>u,LokiEscalations:()=>$e,LokiFleet:()=>he,LokiLearningDashboard:()=>W,LokiLogStream:()=>K,LokiManagedMemoryPanel:()=>we,LokiMemoryBrowser:()=>V,LokiMemoryGraph:()=>xe,LokiMigrationDashboard:()=>ne,LokiNotificationCenter:()=>ae,LokiOverview:()=>q,LokiPipelineView:()=>be,LokiPromptOptimizer:()=>re,LokiProviderHealth:()=>fe,LokiQualityGates:()=>de,LokiQualityScore:()=>oe,LokiRarvTimeline:()=>ce,LokiRunManager:()=>pe,LokiSessionControl:()=>G,LokiSessionDiff:()=>se,LokiSpecPanel:()=>Se,LokiState:()=>O,LokiTaskBoard:()=>J,LokiTenantSwitcher:()=>me,LokiTheme:()=>M,LokiWikiBrowser:()=>Ce,RADIUS:()=>D,SPACING:()=>T,STATE_CHANGE_EVENT:()=>He,THEMES:()=>C,THEME_VARIABLES:()=>ze,TYPOGRAPHY:()=>$,UnifiedThemeManager:()=>w,VERSION:()=>Yt,Z_INDEX:()=>R,createApiClient:()=>We,createStore:()=>Ye,generateThemeCSS:()=>E,generateTokensCSS:()=>U,getApiClient:()=>g,getState:()=>P,init:()=>Qt});var C={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-bg-active":"#E6E2DA","--loki-bg-overlay":"rgba(32, 21, 21, 0.5)","--loki-accent":"#553DE9","--loki-accent-hover":"#4432c4","--loki-accent-active":"#3828a0","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-text-disabled":"#C5C0B1","--loki-text-inverse":"#ffffff","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-border-focus":"#553DE9","--loki-success":"#1FC5A8","--loki-success-muted":"rgba(31, 197, 168, 0.12)","--loki-warning":"#D4A03C","--loki-warning-muted":"rgba(212, 160, 60, 0.12)","--loki-error":"#C45B5B","--loki-error-muted":"rgba(196, 91, 91, 0.12)","--loki-info":"#2F71E3","--loki-info-muted":"rgba(47, 113, 227, 0.12)","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-shadow-sm":"0 1px 2px rgba(32, 21, 21, 0.04)","--loki-shadow-md":"0 4px 6px rgba(32, 21, 21, 0.06)","--loki-shadow-lg":"0 10px 15px rgba(32, 21, 21, 0.08)","--loki-shadow-focus":"0 0 0 3px rgba(85, 61, 233, 0.25)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-bg-active":"#352A55","--loki-bg-overlay":"rgba(20, 11, 36, 0.85)","--loki-accent":"#7B6BF0","--loki-accent-hover":"#9488F5","--loki-accent-active":"#6258D0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-text-disabled":"#5A4E78","--loki-text-inverse":"#1A0F2E","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-border-focus":"#7B6BF0","--loki-success":"#2ED8B6","--loki-success-muted":"rgba(46, 216, 182, 0.18)","--loki-warning":"#E8B84A","--loki-warning-muted":"rgba(232, 184, 74, 0.18)","--loki-error":"#E07070","--loki-error-muted":"rgba(224, 112, 112, 0.18)","--loki-info":"#5A9CF5","--loki-info-muted":"rgba(90, 156, 245, 0.18)","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.4)","--loki-shadow-md":"0 4px 12px rgba(0, 0, 0, 0.5)","--loki-shadow-lg":"0 10px 25px rgba(0, 0, 0, 0.6)","--loki-shadow-focus":"0 0 0 3px rgba(123, 107, 240, 0.30)"},"high-contrast":{"--loki-bg-primary":"#000000","--loki-bg-secondary":"#0a0a0a","--loki-bg-tertiary":"#141414","--loki-bg-card":"#0a0a0a","--loki-bg-hover":"#1a1a1a","--loki-bg-active":"#242424","--loki-bg-overlay":"rgba(0, 0, 0, 0.9)","--loki-accent":"#c084fc","--loki-accent-hover":"#d8b4fe","--loki-accent-active":"#e9d5ff","--loki-accent-light":"#d8b4fe","--loki-accent-muted":"rgba(192, 132, 252, 0.25)","--loki-text-primary":"#ffffff","--loki-text-secondary":"#e0e0e0","--loki-text-muted":"#b0b0b0","--loki-text-disabled":"#666666","--loki-text-inverse":"#000000","--loki-border":"#ffffff","--loki-border-light":"#cccccc","--loki-border-focus":"#c084fc","--loki-success":"#4ade80","--loki-success-muted":"rgba(74, 222, 128, 0.25)","--loki-warning":"#fde047","--loki-warning-muted":"rgba(253, 224, 71, 0.25)","--loki-error":"#f87171","--loki-error-muted":"rgba(248, 113, 113, 0.25)","--loki-info":"#60a5fa","--loki-info-muted":"rgba(96, 165, 250, 0.25)","--loki-green":"#4ade80","--loki-green-muted":"rgba(74, 222, 128, 0.25)","--loki-yellow":"#fde047","--loki-yellow-muted":"rgba(253, 224, 71, 0.25)","--loki-red":"#f87171","--loki-red-muted":"rgba(248, 113, 113, 0.25)","--loki-blue":"#60a5fa","--loki-blue-muted":"rgba(96, 165, 250, 0.25)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.25)","--loki-opus":"#fbbf24","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"none","--loki-shadow-md":"none","--loki-shadow-lg":"none","--loki-shadow-focus":"0 0 0 3px #c084fc"},"vscode-light":{"--loki-bg-primary":"var(--vscode-editor-background, #ffffff)","--loki-bg-secondary":"var(--vscode-sideBar-background, #f3f3f3)","--loki-bg-tertiary":"var(--vscode-input-background, #ffffff)","--loki-bg-card":"var(--vscode-editor-background, #ffffff)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #e8e8e8)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #0060c0)","--loki-bg-overlay":"rgba(0, 0, 0, 0.4)","--loki-accent":"var(--vscode-focusBorder, #0066cc)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #0055aa)","--loki-accent-active":"var(--vscode-button-background, #007acc)","--loki-accent-light":"var(--vscode-focusBorder, #0066cc)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 102, 204, 0.2))","--loki-text-primary":"var(--vscode-foreground, #333333)","--loki-text-secondary":"var(--vscode-descriptionForeground, #717171)","--loki-text-muted":"var(--vscode-disabledForeground, #a0a0a0)","--loki-text-disabled":"var(--vscode-disabledForeground, #cccccc)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #c8c8c8)","--loki-border-light":"var(--vscode-widget-border, #e0e0e0)","--loki-border-focus":"var(--vscode-focusBorder, #0066cc)","--loki-success":"var(--vscode-testing-iconPassed, #388a34)","--loki-success-muted":"rgba(56, 138, 52, 0.15)","--loki-warning":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-warning-muted":"rgba(191, 136, 3, 0.15)","--loki-error":"var(--vscode-errorForeground, #e51400)","--loki-error-muted":"rgba(229, 20, 0, 0.15)","--loki-info":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-info-muted":"rgba(26, 133, 255, 0.15)","--loki-green":"var(--vscode-testing-iconPassed, #388a34)","--loki-green-muted":"rgba(56, 138, 52, 0.15)","--loki-yellow":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-yellow-muted":"rgba(191, 136, 3, 0.15)","--loki-red":"var(--vscode-errorForeground, #e51400)","--loki-red-muted":"rgba(229, 20, 0, 0.15)","--loki-blue":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-blue-muted":"rgba(26, 133, 255, 0.15)","--loki-purple":"#9333ea","--loki-purple-muted":"rgba(147, 51, 234, 0.15)","--loki-opus":"#d97706","--loki-sonnet":"#4f46e5","--loki-haiku":"#059669","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.05)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.1)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.15)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #0066cc)"},"vscode-dark":{"--loki-bg-primary":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-secondary":"var(--vscode-sideBar-background, #252526)","--loki-bg-tertiary":"var(--vscode-input-background, #3c3c3c)","--loki-bg-card":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #2a2d2e)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #094771)","--loki-bg-overlay":"rgba(0, 0, 0, 0.6)","--loki-accent":"var(--vscode-focusBorder, #007fd4)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #1177bb)","--loki-accent-active":"var(--vscode-button-background, #0e639c)","--loki-accent-light":"var(--vscode-focusBorder, #007fd4)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 127, 212, 0.25))","--loki-text-primary":"var(--vscode-foreground, #cccccc)","--loki-text-secondary":"var(--vscode-descriptionForeground, #9d9d9d)","--loki-text-muted":"var(--vscode-disabledForeground, #6b6b6b)","--loki-text-disabled":"var(--vscode-disabledForeground, #4d4d4d)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #454545)","--loki-border-light":"var(--vscode-widget-border, #5a5a5a)","--loki-border-focus":"var(--vscode-focusBorder, #007fd4)","--loki-success":"var(--vscode-testing-iconPassed, #89d185)","--loki-success-muted":"rgba(137, 209, 133, 0.2)","--loki-warning":"var(--vscode-editorWarning-foreground, #cca700)","--loki-warning-muted":"rgba(204, 167, 0, 0.2)","--loki-error":"var(--vscode-errorForeground, #f48771)","--loki-error-muted":"rgba(244, 135, 113, 0.2)","--loki-info":"var(--vscode-editorInfo-foreground, #75beff)","--loki-info-muted":"rgba(117, 190, 255, 0.2)","--loki-green":"var(--vscode-testing-iconPassed, #89d185)","--loki-green-muted":"rgba(137, 209, 133, 0.2)","--loki-yellow":"var(--vscode-editorWarning-foreground, #cca700)","--loki-yellow-muted":"rgba(204, 167, 0, 0.2)","--loki-red":"var(--vscode-errorForeground, #f48771)","--loki-red-muted":"rgba(244, 135, 113, 0.2)","--loki-blue":"var(--vscode-editorInfo-foreground, #75beff)","--loki-blue-muted":"rgba(117, 190, 255, 0.2)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.2)","--loki-opus":"#f59e0b","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.3)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.4)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.5)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #007fd4)"}},T={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},D={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},$={fontFamily:{sans:"'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif",serif:"'DM Serif Display', Georgia, 'Times New Roman', serif",mono:"'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace"},fontSize:{xs:"10px",sm:"11px",base:"12px",md:"13px",lg:"14px",xl:"16px","2xl":"18px","3xl":"24px"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.75"}},z={duration:{fast:"100ms",normal:"200ms",slow:"300ms",slower:"500ms"},easing:{default:"cubic-bezier(0.4, 0, 0.2, 1)",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)",bounce:"cubic-bezier(0.68, -0.55, 0.265, 1.55)"}},Te={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},R={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Le={"navigation.nextItem":{key:"ArrowDown",modifiers:[]},"navigation.prevItem":{key:"ArrowUp",modifiers:[]},"navigation.nextSection":{key:"Tab",modifiers:[]},"navigation.prevSection":{key:"Tab",modifiers:["Shift"]},"navigation.confirm":{key:"Enter",modifiers:[]},"navigation.cancel":{key:"Escape",modifiers:[]},"action.refresh":{key:"r",modifiers:["Meta"]},"action.search":{key:"k",modifiers:["Meta"]},"action.save":{key:"s",modifiers:["Meta"]},"action.close":{key:"w",modifiers:["Meta"]},"theme.toggle":{key:"d",modifiers:["Meta","Shift"]},"task.create":{key:"n",modifiers:["Meta"]},"task.complete":{key:"Enter",modifiers:["Meta"]},"view.toggleLogs":{key:"l",modifiers:["Meta","Shift"]},"view.toggleMemory":{key:"m",modifiers:["Meta","Shift"]}},De={button:{role:"button",tabIndex:0},tablist:{role:"tablist"},tab:{role:"tab",ariaSelected:!1,tabIndex:-1},tabpanel:{role:"tabpanel",tabIndex:0},list:{role:"list"},listitem:{role:"listitem"},livePolite:{ariaLive:"polite",ariaAtomic:!0},liveAssertive:{ariaLive:"assertive",ariaAtomic:!0},dialog:{role:"dialog",ariaModal:!0},alertdialog:{role:"alertdialog",ariaModal:!0},status:{role:"status",ariaLive:"polite"},alert:{role:"alert",ariaLive:"assertive"},log:{role:"log",ariaLive:"polite",ariaRelevant:"additions"}};function E(d){let e=C[d];return e?Object.entries(e).map(([t,i])=>`${t}: ${i};`).join(`
|
|
1542
|
-
`):""}function
|
|
1541
|
+
var LokiDashboard=(()=>{var He=Object.defineProperty;var xt=Object.getOwnPropertyDescriptor;var _t=Object.getOwnPropertyNames;var yt=Object.prototype.hasOwnProperty;var wt=(d,e,t)=>e in d?He(d,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[e]=t;var $t=(d,e)=>{for(var t in e)He(d,t,{get:e[t],enumerable:!0})},Et=(d,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of _t(e))!yt.call(d,a)&&a!==t&&He(d,a,{get:()=>e[a],enumerable:!(i=xt(e,a))||i.enumerable});return d};var Ct=d=>Et(He({},"__esModule",{value:!0}),d);var S=(d,e,t)=>wt(d,typeof e!="symbol"?e+"":e,t);var ai={};$t(ai,{ANIMATION:()=>B,ARIA_PATTERNS:()=>Pe,ApiEvents:()=>f,BASE_STYLES:()=>V,BREAKPOINTS:()=>Me,COMMON_STYLES:()=>Xe,KEYBOARD_SHORTCUTS:()=>Be,KeyboardHandler:()=>O,LokiActivityStream:()=>ye,LokiAgentLeaderboard:()=>Ae,LokiAnalytics:()=>ge,LokiApiClient:()=>N,LokiApiKeys:()=>xe,LokiAppPreview:()=>re,LokiAppStatus:()=>se,LokiAuditViewer:()=>ke,LokiChecklistViewer:()=>ae,LokiCheckpointViewer:()=>ne,LokiContextTracker:()=>le,LokiCostDashboard:()=>oe,LokiCostWaterfall:()=>Se,LokiCouncilDashboard:()=>ie,LokiCouncilTranscripts:()=>De,LokiElement:()=>g,LokiEscalations:()=>Le,LokiFleet:()=>be,LokiLearningDashboard:()=>te,LokiLogStream:()=>Z,LokiManagedMemoryPanel:()=>Te,LokiMemoryBrowser:()=>ee,LokiMemoryGraph:()=>Ce,LokiMigrationDashboard:()=>ue,LokiNotificationCenter:()=>de,LokiOverview:()=>Y,LokiPipelineView:()=>$e,LokiPromptOptimizer:()=>pe,LokiProviderHealth:()=>we,LokiQualityGates:()=>me,LokiQualityScore:()=>he,LokiRarvTimeline:()=>ve,LokiRunManager:()=>fe,LokiSessionControl:()=>X,LokiSessionDiff:()=>ce,LokiSpecPanel:()=>Re,LokiState:()=>W,LokiTaskBoard:()=>Q,LokiTenantSwitcher:()=>_e,LokiTheme:()=>j,LokiWikiBrowser:()=>ze,MARKDOWN_STYLES:()=>L,RADIUS:()=>M,SPACING:()=>D,STATE_CHANGE_EVENT:()=>je,THEMES:()=>A,THEME_VARIABLES:()=>Ie,TYPOGRAPHY:()=>$,UnifiedThemeManager:()=>w,VERSION:()=>ti,Z_INDEX:()=>P,createApiClient:()=>tt,createStore:()=>it,escapeHtml:()=>Ue,generateThemeCSS:()=>E,generateTokensCSS:()=>K,getApiClient:()=>m,getState:()=>U,init:()=>ii,renderMarkdown:()=>C});var A={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-bg-active":"#E6E2DA","--loki-bg-overlay":"rgba(32, 21, 21, 0.5)","--loki-accent":"#553DE9","--loki-accent-hover":"#4432c4","--loki-accent-active":"#3828a0","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-text-disabled":"#C5C0B1","--loki-text-inverse":"#ffffff","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-border-focus":"#553DE9","--loki-success":"#1FC5A8","--loki-success-muted":"rgba(31, 197, 168, 0.12)","--loki-warning":"#D4A03C","--loki-warning-muted":"rgba(212, 160, 60, 0.12)","--loki-error":"#C45B5B","--loki-error-muted":"rgba(196, 91, 91, 0.12)","--loki-info":"#2F71E3","--loki-info-muted":"rgba(47, 113, 227, 0.12)","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-shadow-sm":"0 1px 2px rgba(32, 21, 21, 0.04)","--loki-shadow-md":"0 4px 6px rgba(32, 21, 21, 0.06)","--loki-shadow-lg":"0 10px 15px rgba(32, 21, 21, 0.08)","--loki-shadow-focus":"0 0 0 3px rgba(85, 61, 233, 0.25)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-bg-active":"#352A55","--loki-bg-overlay":"rgba(20, 11, 36, 0.85)","--loki-accent":"#7B6BF0","--loki-accent-hover":"#9488F5","--loki-accent-active":"#6258D0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-text-disabled":"#5A4E78","--loki-text-inverse":"#1A0F2E","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-border-focus":"#7B6BF0","--loki-success":"#2ED8B6","--loki-success-muted":"rgba(46, 216, 182, 0.18)","--loki-warning":"#E8B84A","--loki-warning-muted":"rgba(232, 184, 74, 0.18)","--loki-error":"#E07070","--loki-error-muted":"rgba(224, 112, 112, 0.18)","--loki-info":"#5A9CF5","--loki-info-muted":"rgba(90, 156, 245, 0.18)","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.4)","--loki-shadow-md":"0 4px 12px rgba(0, 0, 0, 0.5)","--loki-shadow-lg":"0 10px 25px rgba(0, 0, 0, 0.6)","--loki-shadow-focus":"0 0 0 3px rgba(123, 107, 240, 0.30)"},"high-contrast":{"--loki-bg-primary":"#000000","--loki-bg-secondary":"#0a0a0a","--loki-bg-tertiary":"#141414","--loki-bg-card":"#0a0a0a","--loki-bg-hover":"#1a1a1a","--loki-bg-active":"#242424","--loki-bg-overlay":"rgba(0, 0, 0, 0.9)","--loki-accent":"#c084fc","--loki-accent-hover":"#d8b4fe","--loki-accent-active":"#e9d5ff","--loki-accent-light":"#d8b4fe","--loki-accent-muted":"rgba(192, 132, 252, 0.25)","--loki-text-primary":"#ffffff","--loki-text-secondary":"#e0e0e0","--loki-text-muted":"#b0b0b0","--loki-text-disabled":"#666666","--loki-text-inverse":"#000000","--loki-border":"#ffffff","--loki-border-light":"#cccccc","--loki-border-focus":"#c084fc","--loki-success":"#4ade80","--loki-success-muted":"rgba(74, 222, 128, 0.25)","--loki-warning":"#fde047","--loki-warning-muted":"rgba(253, 224, 71, 0.25)","--loki-error":"#f87171","--loki-error-muted":"rgba(248, 113, 113, 0.25)","--loki-info":"#60a5fa","--loki-info-muted":"rgba(96, 165, 250, 0.25)","--loki-green":"#4ade80","--loki-green-muted":"rgba(74, 222, 128, 0.25)","--loki-yellow":"#fde047","--loki-yellow-muted":"rgba(253, 224, 71, 0.25)","--loki-red":"#f87171","--loki-red-muted":"rgba(248, 113, 113, 0.25)","--loki-blue":"#60a5fa","--loki-blue-muted":"rgba(96, 165, 250, 0.25)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.25)","--loki-opus":"#fbbf24","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"none","--loki-shadow-md":"none","--loki-shadow-lg":"none","--loki-shadow-focus":"0 0 0 3px #c084fc"},"vscode-light":{"--loki-bg-primary":"var(--vscode-editor-background, #ffffff)","--loki-bg-secondary":"var(--vscode-sideBar-background, #f3f3f3)","--loki-bg-tertiary":"var(--vscode-input-background, #ffffff)","--loki-bg-card":"var(--vscode-editor-background, #ffffff)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #e8e8e8)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #0060c0)","--loki-bg-overlay":"rgba(0, 0, 0, 0.4)","--loki-accent":"var(--vscode-focusBorder, #0066cc)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #0055aa)","--loki-accent-active":"var(--vscode-button-background, #007acc)","--loki-accent-light":"var(--vscode-focusBorder, #0066cc)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 102, 204, 0.2))","--loki-text-primary":"var(--vscode-foreground, #333333)","--loki-text-secondary":"var(--vscode-descriptionForeground, #717171)","--loki-text-muted":"var(--vscode-disabledForeground, #a0a0a0)","--loki-text-disabled":"var(--vscode-disabledForeground, #cccccc)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #c8c8c8)","--loki-border-light":"var(--vscode-widget-border, #e0e0e0)","--loki-border-focus":"var(--vscode-focusBorder, #0066cc)","--loki-success":"var(--vscode-testing-iconPassed, #388a34)","--loki-success-muted":"rgba(56, 138, 52, 0.15)","--loki-warning":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-warning-muted":"rgba(191, 136, 3, 0.15)","--loki-error":"var(--vscode-errorForeground, #e51400)","--loki-error-muted":"rgba(229, 20, 0, 0.15)","--loki-info":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-info-muted":"rgba(26, 133, 255, 0.15)","--loki-green":"var(--vscode-testing-iconPassed, #388a34)","--loki-green-muted":"rgba(56, 138, 52, 0.15)","--loki-yellow":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-yellow-muted":"rgba(191, 136, 3, 0.15)","--loki-red":"var(--vscode-errorForeground, #e51400)","--loki-red-muted":"rgba(229, 20, 0, 0.15)","--loki-blue":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-blue-muted":"rgba(26, 133, 255, 0.15)","--loki-purple":"#9333ea","--loki-purple-muted":"rgba(147, 51, 234, 0.15)","--loki-opus":"#d97706","--loki-sonnet":"#4f46e5","--loki-haiku":"#059669","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.05)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.1)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.15)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #0066cc)"},"vscode-dark":{"--loki-bg-primary":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-secondary":"var(--vscode-sideBar-background, #252526)","--loki-bg-tertiary":"var(--vscode-input-background, #3c3c3c)","--loki-bg-card":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #2a2d2e)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #094771)","--loki-bg-overlay":"rgba(0, 0, 0, 0.6)","--loki-accent":"var(--vscode-focusBorder, #007fd4)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #1177bb)","--loki-accent-active":"var(--vscode-button-background, #0e639c)","--loki-accent-light":"var(--vscode-focusBorder, #007fd4)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 127, 212, 0.25))","--loki-text-primary":"var(--vscode-foreground, #cccccc)","--loki-text-secondary":"var(--vscode-descriptionForeground, #9d9d9d)","--loki-text-muted":"var(--vscode-disabledForeground, #6b6b6b)","--loki-text-disabled":"var(--vscode-disabledForeground, #4d4d4d)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #454545)","--loki-border-light":"var(--vscode-widget-border, #5a5a5a)","--loki-border-focus":"var(--vscode-focusBorder, #007fd4)","--loki-success":"var(--vscode-testing-iconPassed, #89d185)","--loki-success-muted":"rgba(137, 209, 133, 0.2)","--loki-warning":"var(--vscode-editorWarning-foreground, #cca700)","--loki-warning-muted":"rgba(204, 167, 0, 0.2)","--loki-error":"var(--vscode-errorForeground, #f48771)","--loki-error-muted":"rgba(244, 135, 113, 0.2)","--loki-info":"var(--vscode-editorInfo-foreground, #75beff)","--loki-info-muted":"rgba(117, 190, 255, 0.2)","--loki-green":"var(--vscode-testing-iconPassed, #89d185)","--loki-green-muted":"rgba(137, 209, 133, 0.2)","--loki-yellow":"var(--vscode-editorWarning-foreground, #cca700)","--loki-yellow-muted":"rgba(204, 167, 0, 0.2)","--loki-red":"var(--vscode-errorForeground, #f48771)","--loki-red-muted":"rgba(244, 135, 113, 0.2)","--loki-blue":"var(--vscode-editorInfo-foreground, #75beff)","--loki-blue-muted":"rgba(117, 190, 255, 0.2)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.2)","--loki-opus":"#f59e0b","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.3)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.4)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.5)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #007fd4)"}},D={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},M={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},$={fontFamily:{sans:"'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif",serif:"'DM Serif Display', Georgia, 'Times New Roman', serif",mono:"'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace"},fontSize:{xs:"10px",sm:"11px",base:"12px",md:"13px",lg:"14px",xl:"16px","2xl":"18px","3xl":"24px"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.75"}},B={duration:{fast:"100ms",normal:"200ms",slow:"300ms",slower:"500ms"},easing:{default:"cubic-bezier(0.4, 0, 0.2, 1)",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)",bounce:"cubic-bezier(0.68, -0.55, 0.265, 1.55)"}},Me={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},P={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Be={"navigation.nextItem":{key:"ArrowDown",modifiers:[]},"navigation.prevItem":{key:"ArrowUp",modifiers:[]},"navigation.nextSection":{key:"Tab",modifiers:[]},"navigation.prevSection":{key:"Tab",modifiers:["Shift"]},"navigation.confirm":{key:"Enter",modifiers:[]},"navigation.cancel":{key:"Escape",modifiers:[]},"action.refresh":{key:"r",modifiers:["Meta"]},"action.search":{key:"k",modifiers:["Meta"]},"action.save":{key:"s",modifiers:["Meta"]},"action.close":{key:"w",modifiers:["Meta"]},"theme.toggle":{key:"d",modifiers:["Meta","Shift"]},"task.create":{key:"n",modifiers:["Meta"]},"task.complete":{key:"Enter",modifiers:["Meta"]},"view.toggleLogs":{key:"l",modifiers:["Meta","Shift"]},"view.toggleMemory":{key:"m",modifiers:["Meta","Shift"]}},Pe={button:{role:"button",tabIndex:0},tablist:{role:"tablist"},tab:{role:"tab",ariaSelected:!1,tabIndex:-1},tabpanel:{role:"tabpanel",tabIndex:0},list:{role:"list"},listitem:{role:"listitem"},livePolite:{ariaLive:"polite",ariaAtomic:!0},liveAssertive:{ariaLive:"assertive",ariaAtomic:!0},dialog:{role:"dialog",ariaModal:!0},alertdialog:{role:"alertdialog",ariaModal:!0},status:{role:"status",ariaLive:"polite"},alert:{role:"alert",ariaLive:"assertive"},log:{role:"log",ariaLive:"polite",ariaRelevant:"additions"}};function E(d){let e=A[d];return e?Object.entries(e).map(([t,i])=>`${t}: ${i};`).join(`
|
|
1542
|
+
`):""}function K(){return`
|
|
1543
1543
|
/* Spacing */
|
|
1544
|
-
--loki-space-xs: ${
|
|
1545
|
-
--loki-space-sm: ${
|
|
1546
|
-
--loki-space-md: ${
|
|
1547
|
-
--loki-space-lg: ${
|
|
1548
|
-
--loki-space-xl: ${
|
|
1549
|
-
--loki-space-2xl: ${
|
|
1550
|
-
--loki-space-3xl: ${
|
|
1544
|
+
--loki-space-xs: ${D.xs};
|
|
1545
|
+
--loki-space-sm: ${D.sm};
|
|
1546
|
+
--loki-space-md: ${D.md};
|
|
1547
|
+
--loki-space-lg: ${D.lg};
|
|
1548
|
+
--loki-space-xl: ${D.xl};
|
|
1549
|
+
--loki-space-2xl: ${D["2xl"]};
|
|
1550
|
+
--loki-space-3xl: ${D["3xl"]};
|
|
1551
1551
|
|
|
1552
1552
|
/* Border Radius */
|
|
1553
|
-
--loki-radius-none: ${
|
|
1554
|
-
--loki-radius-sm: ${
|
|
1555
|
-
--loki-radius-md: ${
|
|
1556
|
-
--loki-radius-lg: ${
|
|
1557
|
-
--loki-radius-xl: ${
|
|
1558
|
-
--loki-radius-full: ${
|
|
1553
|
+
--loki-radius-none: ${M.none};
|
|
1554
|
+
--loki-radius-sm: ${M.sm};
|
|
1555
|
+
--loki-radius-md: ${M.md};
|
|
1556
|
+
--loki-radius-lg: ${M.lg};
|
|
1557
|
+
--loki-radius-xl: ${M.xl};
|
|
1558
|
+
--loki-radius-full: ${M.full};
|
|
1559
1559
|
|
|
1560
1560
|
/* Typography */
|
|
1561
1561
|
--loki-font-sans: ${$.fontFamily.sans};
|
|
@@ -1571,25 +1571,25 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
1571
1571
|
--loki-text-3xl: ${$.fontSize["3xl"]};
|
|
1572
1572
|
|
|
1573
1573
|
/* Animation */
|
|
1574
|
-
--loki-duration-fast: ${
|
|
1575
|
-
--loki-duration-normal: ${
|
|
1576
|
-
--loki-duration-slow: ${
|
|
1577
|
-
--loki-easing-default: ${
|
|
1578
|
-
--loki-transition: ${
|
|
1574
|
+
--loki-duration-fast: ${B.duration.fast};
|
|
1575
|
+
--loki-duration-normal: ${B.duration.normal};
|
|
1576
|
+
--loki-duration-slow: ${B.duration.slow};
|
|
1577
|
+
--loki-easing-default: ${B.easing.default};
|
|
1578
|
+
--loki-transition: ${B.duration.normal} ${B.easing.default};
|
|
1579
1579
|
|
|
1580
1580
|
/* Z-Index */
|
|
1581
|
-
--loki-z-dropdown: ${
|
|
1582
|
-
--loki-z-sticky: ${
|
|
1583
|
-
--loki-z-modal: ${
|
|
1584
|
-
--loki-z-popover: ${
|
|
1585
|
-
--loki-z-tooltip: ${
|
|
1586
|
-
--loki-z-toast: ${
|
|
1581
|
+
--loki-z-dropdown: ${P.dropdown};
|
|
1582
|
+
--loki-z-sticky: ${P.sticky};
|
|
1583
|
+
--loki-z-modal: ${P.modal};
|
|
1584
|
+
--loki-z-popover: ${P.popover};
|
|
1585
|
+
--loki-z-tooltip: ${P.tooltip};
|
|
1586
|
+
--loki-z-toast: ${P.toast};
|
|
1587
1587
|
|
|
1588
1588
|
/* Glass effect */
|
|
1589
1589
|
--loki-glass-bg: rgba(255, 255, 255, 0.03);
|
|
1590
1590
|
--loki-glass-border: rgba(255, 255, 255, 0.06);
|
|
1591
1591
|
--loki-glass-blur: blur(12px);
|
|
1592
|
-
`}var
|
|
1592
|
+
`}var V=`
|
|
1593
1593
|
/* Reset and base */
|
|
1594
1594
|
:host {
|
|
1595
1595
|
font-family: var(--loki-font-sans);
|
|
@@ -1865,20 +1865,20 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
1865
1865
|
}
|
|
1866
1866
|
|
|
1867
1867
|
/* Responsive utilities */
|
|
1868
|
-
@media (max-width: ${
|
|
1868
|
+
@media (max-width: ${Me.md}) {
|
|
1869
1869
|
.hide-mobile { display: none !important; }
|
|
1870
1870
|
}
|
|
1871
1871
|
|
|
1872
|
-
@media (min-width: ${
|
|
1872
|
+
@media (min-width: ${Me.md}) {
|
|
1873
1873
|
.hide-desktop { display: none !important; }
|
|
1874
1874
|
}
|
|
1875
|
-
`,
|
|
1875
|
+
`,y=class y{static detectContext(){return typeof acquireVsCodeApi<"u"||document.body.classList.contains("vscode-body")||getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background")?"vscode":document.documentElement.dataset.lokiContext==="cli"?"cli":"browser"}static detectVSCodeTheme(){let e=document.body;if(e.classList.contains("vscode-high-contrast"))return"high-contrast";if(e.classList.contains("vscode-dark"))return"dark";if(e.classList.contains("vscode-light"))return"light";let t=getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background");if(t){let i=t.match(/\d+/g);if(i)return(parseInt(i[0])*299+parseInt(i[1])*587+parseInt(i[2])*114)/1e3>128?"light":"dark"}return null}static getTheme(){if(y.detectContext()==="vscode"){let t=y.detectVSCodeTheme();return t==="high-contrast"?"high-contrast":t==="dark"?"vscode-dark":"vscode-light"}return"light"}static setTheme(e){if(!A[e]){console.warn(`Unknown theme: ${e}`);return}localStorage.setItem(y.STORAGE_KEY,e),document.documentElement.setAttribute("data-loki-theme",e),window.dispatchEvent(new CustomEvent("loki-theme-change",{detail:{theme:e,context:y.detectContext()}}))}static toggle(){let e=y.getTheme();return e.startsWith("vscode")?e:(y.setTheme("light"),"light")}static getVariables(e=null){let t=e||y.getTheme();return A[t]||A.light}static generateCSS(e=null){let t=e||y.getTheme();return`
|
|
1876
1876
|
:host {
|
|
1877
1877
|
${E(t)}
|
|
1878
|
-
${
|
|
1878
|
+
${K()}
|
|
1879
1879
|
}
|
|
1880
|
-
${
|
|
1881
|
-
`}static init(){let e=
|
|
1880
|
+
${V}
|
|
1881
|
+
`}static init(){let e=y.getTheme();document.documentElement.setAttribute("data-loki-theme",e),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{localStorage.getItem(y.STORAGE_KEY)||y.setTheme(y.getTheme())}),y.detectContext()==="vscode"&&new MutationObserver(()=>{let i=y.getTheme();document.documentElement.setAttribute("data-loki-theme",i),window.dispatchEvent(new CustomEvent("loki-theme-change",{detail:{theme:i,context:"vscode"}}))}).observe(document.body,{attributes:!0,attributeFilter:["class"]})}};S(y,"STORAGE_KEY","loki-theme"),S(y,"CONTEXT_KEY","loki-context");var w=y,O=class{constructor(){this._handlers=new Map,this._enabled=!0}register(e,t){let i=Be[e];if(!i){console.warn(`Unknown keyboard action: ${e}`);return}this._handlers.set(e,{shortcut:i,handler:t})}unregister(e){this._handlers.delete(e)}setEnabled(e){this._enabled=e}handleEvent(e){if(!this._enabled)return!1;for(let[t,{shortcut:i,handler:a}]of this._handlers)if(this._matchesShortcut(e,i))return e.preventDefault(),e.stopPropagation(),a(e),!0;return!1}_matchesShortcut(e,t){let i=e.key.toLowerCase(),a=t.modifiers||[];if(i!==t.key.toLowerCase())return!1;let s=a.includes("Ctrl")||a.includes("Meta"),r=a.includes("Shift"),o=a.includes("Alt"),n=(e.ctrlKey||e.metaKey)===s,l=e.shiftKey===r,c=e.altKey===o;return n&&l&&c}attach(e){this._boundHandler||(this._boundHandler=t=>this.handleEvent(t)),e.addEventListener("keydown",this._boundHandler)}detach(e){this._boundHandler&&e.removeEventListener("keydown",this._boundHandler)}};var Ie={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-accent":"#553DE9","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-transition":"0.2s cubic-bezier(0.4, 0, 0.2, 1)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-accent":"#7B6BF0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-transition":"0.2s cubic-bezier(0.4, 0, 0.2, 1)"}},Xe=`
|
|
1882
1882
|
:host {
|
|
1883
1883
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
1884
1884
|
line-height: 1.5;
|
|
@@ -1974,11 +1974,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
1974
1974
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary); }
|
|
1975
1975
|
::-webkit-scrollbar-thumb { background: var(--loki-border); border-radius: 3px; }
|
|
1976
1976
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light); }
|
|
1977
|
-
`,
|
|
1978
|
-
`)}static applyToElement(e,t=null){let i=
|
|
1977
|
+
`,F=class F{static getTheme(){return w.getTheme()}static setTheme(e){w.setTheme(e)}static toggle(){return w.toggle()}static getVariables(e=null){let t=e||F.getTheme();return A[t]||Ie[t]||Ie.light}static toCSSString(e=null){let t=e||F.getTheme();if(A[t])return E(t);let i=F.getVariables(t);return Object.entries(i).map(([a,s])=>`${a}: ${s};`).join(`
|
|
1978
|
+
`)}static applyToElement(e,t=null){let i=F.getVariables(t);for(let[a,s]of Object.entries(i))e.style.setProperty(a,s)}static init(){w.init()}static detectContext(){return w.detectContext()}static getAvailableThemes(){return Object.keys(A)}};S(F,"STORAGE_KEY","loki-theme");var j=F,g=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._theme=j.getTheme(),this._themeChangeHandler=this._onThemeChange.bind(this),this._keyboardHandler=new O}connectedCallback(){window.addEventListener("loki-theme-change",this._themeChangeHandler),this._applyTheme(),this._setupKeyboardHandling(),this.render()}disconnectedCallback(){window.removeEventListener("loki-theme-change",this._themeChangeHandler),this._keyboardHandler.detach(this)}_onThemeChange(e){this._theme=e.detail.theme,this._applyTheme(),this.onThemeChange&&this.onThemeChange(this._theme)}_applyTheme(){j.applyToElement(this.shadowRoot.host,this._theme),this.setAttribute("data-loki-theme",this._theme)}_setupKeyboardHandling(){this._keyboardHandler.attach(this)}registerShortcut(e,t){this._keyboardHandler.register(e,t)}getBaseStyles(){return`
|
|
1979
1979
|
/* Design tokens */
|
|
1980
1980
|
:host {
|
|
1981
|
-
${
|
|
1981
|
+
${K()}
|
|
1982
1982
|
}
|
|
1983
1983
|
|
|
1984
1984
|
/* Light theme (default) */
|
|
@@ -1986,8 +1986,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
1986
1986
|
${E("light")}
|
|
1987
1987
|
}
|
|
1988
1988
|
|
|
1989
|
-
/*
|
|
1990
|
-
|
|
1989
|
+
/* v7.90.1: dark mode removed (light-only). The OS-preference dark block is
|
|
1990
|
+
disabled via an always-false media query so an OS dark setting no longer
|
|
1991
|
+
flips components to dark. */
|
|
1992
|
+
@media (prefers-color-scheme: dark) and (max-width: 0px) {
|
|
1991
1993
|
:host {
|
|
1992
1994
|
${E("dark")}
|
|
1993
1995
|
}
|
|
@@ -2030,8 +2032,27 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2030
2032
|
}
|
|
2031
2033
|
}
|
|
2032
2034
|
|
|
2033
|
-
${
|
|
2034
|
-
`}getAriaPattern(e){return De[e]||{}}applyAriaPattern(e,t){let i=this.getAriaPattern(t);for(let[a,s]of Object.entries(i))if(a==="role")e.setAttribute("role",s);else{let r=a.replace(/([A-Z])/g,"-$1").toLowerCase();e.setAttribute(r,s)}}render(){}};var H={realtime:1e3,normal:2e3,background:5e3,offline:1e4},Ke={vscode:H.normal,browser:H.realtime,cli:H.background},Ve={baseUrl:typeof window<"u"?window.location.origin:"http://localhost:57374",wsUrl:typeof window<"u"?`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws`:"ws://localhost:57374/ws",pollInterval:2e3,timeout:1e4,retryAttempts:3,retryDelay:1e3},v={CONNECTED:"api:connected",DISCONNECTED:"api:disconnected",ERROR:"api:error",STATUS_UPDATE:"api:status-update",TASK_CREATED:"api:task-created",TASK_UPDATED:"api:task-updated",TASK_DELETED:"api:task-deleted",PROJECT_CREATED:"api:project-created",PROJECT_UPDATED:"api:project-updated",AGENT_UPDATE:"api:agent-update",LOG_MESSAGE:"api:log-message",MEMORY_UPDATE:"api:memory-update",CHECKLIST_UPDATE:"api:checklist-update"},L=class L extends EventTarget{static getInstance(e={}){let t=e.baseUrl||Ve.baseUrl;return L._instances.has(t)||L._instances.set(t,new L(e)),L._instances.get(t)}static clearInstances(){L._instances.forEach(e=>e.disconnect()),L._instances.clear()}constructor(e={}){super(),this.config={...Ve,...e},this._ws=null,this._connected=!1,this._pollInterval=null,this._reconnectTimeout=null,this._reconnectAttempts=0,this._maxReconnectAttempts=20,this._cache=new Map,this._cacheTimeout=5e3,this._vscodeApi=null,this._context=this._detectContext(),this._currentPollInterval=Ke[this._context]||H.normal,this._visibilityChangeHandler=null,this._messageHandler=null,this._setupAdaptivePolling(),this._setupVSCodeBridge()}_detectContext(){return typeof acquireVsCodeApi<"u"?"vscode":typeof window<"u"&&window.location?"browser":"cli"}get context(){return this._context}static get POLL_INTERVALS(){return H}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(H.background):this._setPollInterval(Ke[this._context]||H.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(e){this._currentPollInterval=e,this._pollInterval&&(this.stopPolling(),this.startPolling(null,e))}setPollMode(e){let t=H[e];t&&this._setPollInterval(t)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=e=>{let t=e.data;if(!(!t||!t.type))switch(t.type){case"updateStatus":this._emit(v.STATUS_UPDATE,t.data);break;case"updateTasks":this._emit(v.TASK_UPDATED,t.data);break;case"taskCreated":this._emit(v.TASK_CREATED,t.data);break;case"taskDeleted":this._emit(v.TASK_DELETED,t.data);break;case"projectCreated":this._emit(v.PROJECT_CREATED,t.data);break;case"projectUpdated":this._emit(v.PROJECT_UPDATED,t.data);break;case"agentUpdate":this._emit(v.AGENT_UPDATE,t.data);break;case"logMessage":this._emit(v.LOG_MESSAGE,t.data);break;case"memoryUpdate":this._emit(v.MEMORY_UPDATE,t.data);break;case"connected":this._connected=!0,this._emit(v.CONNECTED,t.data);break;case"disconnected":this._connected=!1,this._emit(v.DISCONNECTED,t.data);break;case"error":this._emit(v.ERROR,t.data);break;case"setPollMode":this.setPollMode(t.data.mode);break;default:this._emit(`api:${t.type}`,t.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(e,t={}){this._vscodeApi&&this._vscodeApi.postMessage({type:e,data:t})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(e,t={}){this.postToVSCode("userAction",{action:e,...t})}get baseUrl(){return this.config.baseUrl}set baseUrl(e){this.config.baseUrl=e,this.config.wsUrl=e.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((e,t)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._reconnectAttempts=0,this._emit(v.CONNECTED),e()},this._ws.onclose=()=>{this._connected=!1,this._emit(v.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=i=>{this._emit(v.ERROR,{error:i}),t(i)},this._ws.onmessage=i=>{try{let a=JSON.parse(i.data);this._handleMessage(a)}catch(a){console.error("Failed to parse WebSocket message:",a)}}}catch(i){t(i)}})}disconnect(){this._ws&&(this._ws.close(),this._ws=null),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._reconnectTimeout&&(clearTimeout(this._reconnectTimeout),this._reconnectTimeout=null),this._connected=!1,this._cleanupGlobalListeners()}_cleanupGlobalListeners(){this._visibilityChangeHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this._visibilityChangeHandler),this._visibilityChangeHandler=null),this._messageHandler&&typeof window<"u"&&(window.removeEventListener("message",this._messageHandler),this._messageHandler=null)}destroy(){this.disconnect()}_scheduleReconnect(){if(this._reconnectTimeout)return;if(this._reconnectAttempts>=this._maxReconnectAttempts){console.warn("WebSocket max reconnect attempts reached, giving up"),this._emit(v.ERROR,{error:"Max reconnect attempts reached"});return}let e=Math.min(this.config.retryDelay*Math.pow(2,this._reconnectAttempts),3e4);this._reconnectAttempts++,this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},e)}_handleMessage(e){if(e.type==="ping"){this._ws&&this._ws.readyState===WebSocket.OPEN&&this._ws.send(JSON.stringify({type:"pong"}));return}let i={connected:v.CONNECTED,status_update:v.STATUS_UPDATE,task_created:v.TASK_CREATED,task_updated:v.TASK_UPDATED,task_deleted:v.TASK_DELETED,task_moved:v.TASK_UPDATED,project_created:v.PROJECT_CREATED,project_updated:v.PROJECT_UPDATED,agent_update:v.AGENT_UPDATE,log:v.LOG_MESSAGE}[e.type]||`api:${e.type}`;this._emit(i,e.data)}_emit(e,t={}){this.dispatchEvent(new CustomEvent(e,{detail:t}))}async _request(e,t={}){let i=`${this.config.baseUrl}${e}`,a=new AbortController,s=t&&typeof t.timeout=="number"?t.timeout:this.config.timeout,r=setTimeout(()=>a.abort(),s);try{let o=await fetch(i,{...t,signal:a.signal,credentials:"include",headers:{"Content-Type":"application/json",...t.headers}});if(clearTimeout(r),!o.ok){let n=await o.text().catch(()=>""),l=o.statusText||`HTTP ${o.status}`;if(n)try{let c=JSON.parse(n);l=c.detail||c.error||c.message||l}catch{l=n.length>200?n.slice(0,200)+"...":n}throw new Error(l)}return o.status===204?null:await o.json()}catch(o){throw clearTimeout(r),o.name==="AbortError"?new Error("Request timeout"):o}}async _get(e,t=!1){if(t&&this._cache.has(e)){let a=this._cache.get(e);if(Date.now()-a.timestamp<this._cacheTimeout)return a.data}let i=await this._request(e);return t&&this._cache.set(e,{data:i,timestamp:Date.now()}),i}async _post(e,t,i={}){return this._request(e,{method:"POST",body:JSON.stringify(t),...i})}async _put(e,t){return this._request(e,{method:"PUT",body:JSON.stringify(t)})}async _delete(e){return this._request(e,{method:"DELETE"})}async get(e){return this._get(e)}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(e=null){let t=e?`?status=${e}`:"";return this._get(`/api/projects${t}`)}async getProject(e){return this._get(`/api/projects/${e}`)}async createProject(e){return this._post("/api/projects",e)}async updateProject(e,t){return this._put(`/api/projects/${e}`,t)}async deleteProject(e){return this._delete(`/api/projects/${e}`)}async listTasks(e={}){let t=new URLSearchParams;e.projectId&&t.append("project_id",e.projectId),e.status&&t.append("status",e.status),e.priority&&t.append("priority",e.priority);let i=t.toString()?`?${t}`:"";return this._get(`/api/tasks${i}`)}async getTask(e){return this._get(`/api/tasks/${e}`)}async createTask(e){return this._post("/api/tasks",e)}async updateTask(e,t){return this._put(`/api/tasks/${e}`,t)}async moveTask(e,t,i){return this._post(`/api/tasks/${e}/move`,{status:t,position:i})}async deleteTask(e){return this._delete(`/api/tasks/${e}`)}async getMemorySummary(){return this._get("/api/memory/summary",!0)}async getMemoryIndex(){return this._get("/api/memory/index",!0)}async getMemoryTimeline(){return this._get("/api/memory/timeline")}async listEpisodes(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/episodes${t?"?"+t:""}`)}async getEpisode(e){return this._get(`/api/memory/episodes/${e}`)}async listPatterns(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/patterns${t?"?"+t:""}`)}async getPattern(e){return this._get(`/api/memory/patterns/${e}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(e){return this._get(`/api/memory/skills/${e}`)}async retrieveMemories(e,t=null,i=5){return this._post("/api/memory/retrieve",{query:e,taskType:t,topK:i},{timeout:3e4})}async consolidateMemory(e=24){return this._post("/api/memory/consolidate",{sinceHours:e},{timeout:12e4})}async getTokenEconomics(){return this._get("/api/memory/economics")}async searchMemory(e,t="all",i=20){let a=new URLSearchParams({q:e,collection:t,limit:String(i)});return this._get(`/api/memory/search?${a}`)}async getMemoryStats(){return this._get("/api/memory/stats",!0)}async listRegisteredProjects(e=!1){return this._get(`/api/registry/projects?include_inactive=${e}`)}async registerProject(e,t=null,i=null){return this._post("/api/registry/projects",{path:e,name:t,alias:i})}async discoverProjects(e=3){return this._get(`/api/registry/discover?max_depth=${e}`)}async syncRegistry(){return this._post("/api/registry/sync",{},{timeout:45e3})}async getCrossProjectTasks(e=null){let t=e?`?project_ids=${e.join(",")}`:"";return this._get(`/api/registry/tasks${t}`)}async getLearningMetrics(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/metrics${i}`)}async getLearningTrends(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/trends${i}`)}async getLearningSignals(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source),e.limit&&t.append("limit",String(e.limit)),e.offset&&t.append("offset",String(e.offset));let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/signals${i}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(e={}){return this._post("/api/learning/aggregate",e,{timeout:6e4})}async getAggregatedPreferences(e=20){return this._get(`/api/learning/preferences?limit=${e}`)}async getAggregatedErrors(e=20){return this._get(`/api/learning/errors?limit=${e}`)}async getAggregatedSuccessPatterns(e=20){return this._get(`/api/learning/success?limit=${e}`)}async getToolEfficiency(e=20){return this._get(`/api/learning/tools?limit=${e}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(e=20){return this._get(`/api/council/verdicts?limit=${e}`)}async getCouncilConvergence(){return this._get("/api/council/convergence")}async getCouncilReport(){return this._get("/api/council/report")}async forceCouncilReview(){return this._post("/api/council/force-review",{})}async getContext(){return this._get("/api/context")}async getNotifications(e,t){let i=new URLSearchParams;e&&i.set("severity",e),t&&i.set("unread_only","true");let a=i.toString();return this._get("/api/notifications"+(a?"?"+a:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(e){return this._put("/api/notifications/triggers",{triggers:e})}async acknowledgeNotification(e){return this._post("/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{})}async startSession(e,t={}){let i={provider:t.provider||"claude",parallel:!!t.parallel};return t.prdPath?i.prd_path=t.prdPath:i.prd_text=e||"",this._post("/api/control/start",i)}async pauseSession(){return this._post("/api/control/pause",{})}async resumeSession(){return this._post("/api/control/resume",{})}async stopSession(){return this._post("/api/control/stop",{})}async getSessionModel(){return this._get("/api/session/model")}async setSessionModel(e){return this._post("/api/session/model",{model:e||null})}async getLogs(e=100){return this._get(`/api/logs?lines=${e}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let e=await fetch(`${this.baseUrl}/api/prd-observations`,{credentials:"include"});if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(e,t,i="dashboard"){return this._post("/api/checklist/waivers",{item_id:e,reason:t,waived_by:i})}async removeChecklistWaiver(e){return this._delete(`/api/checklist/waivers/${encodeURIComponent(e)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(e=100){return this._get(`/api/app-runner/logs?lines=${e}`)}async getAppRunnerErrors(e=50){return this._get(`/api/app-runner/errors?lines=${e}`)}async restartApp(){return this._post("/api/control/app-restart",{})}async stopApp(){return this._post("/api/control/app-stop",{})}async getPlaywrightResults(){return this._get("/api/playwright/results")}async getPlaywrightScreenshot(){return this._get("/api/playwright/screenshot")}startPolling(e,t=null){if(this._pollInterval)return;this._pollCallback=e;let i=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(v.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(v.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};i();let a=t||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(i,a)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};S(L,"_instances",new Map);var F=L;function We(d={}){return new F(d)}function g(d={}){return F.getInstance(d)}var He="loki-state-change",Re={ui:{theme:"light",sidebarCollapsed:!1,activeSection:"kanban",terminalAutoScroll:!0},session:{connected:!1,lastSync:null,mode:"offline",phase:null,iteration:null},localTasks:[],cache:{projects:[],tasks:[],agents:[],memory:null,lastFetch:null},preferences:{pollInterval:2e3,notifications:!0,soundEnabled:!1}},A=class A extends EventTarget{static getInstance(){return A._instance||(A._instance=new A),A._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let e=localStorage.getItem(A.STORAGE_KEY);if(e){let t=JSON.parse(e);return this._mergeState(Re,t)}}catch(e){console.warn("Failed to load state from localStorage:",e)}return{...Re}}_mergeState(e,t){let i={...e};for(let a of Object.keys(t))a in e&&typeof e[a]=="object"&&!Array.isArray(e[a])?i[a]=this._mergeState(e[a],t[a]):i[a]=t[a];return i}_saveState(){try{let e={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(A.STORAGE_KEY,JSON.stringify(e))}catch(e){console.warn("Failed to save state to localStorage:",e)}}get(e=null){if(!e)return{...this._state};let t=e.split("."),i=this._state;for(let a of t){if(i==null)return;i=i[a]}return i}set(e,t,i=!0){let a=e.split("."),s=a.pop(),r=this._state;for(let n of a)n in r||(r[n]={}),r=r[n];let o=r[s];r[s]=t,i&&this._saveState(),this._notifyChange(e,t,o)}update(e,t=!0){let i=[];for(let[a,s]of Object.entries(e)){let r=this.get(a);this.set(a,s,!1),i.push({path:a,value:s,oldValue:r})}t&&this._saveState();for(let a of i)this._notifyChange(a.path,a.value,a.oldValue)}_notifyChange(e,t,i){this.dispatchEvent(new CustomEvent(He,{detail:{path:e,value:t,oldValue:i}}));let a=this._subscribers.get(e)||[];for(let r of a)try{r(t,i,e)}catch(o){console.error("State subscriber error:",o)}let s=e.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let n of o)try{n(this.get(r),null,r)}catch(l){console.error("State subscriber error:",l)}}}subscribe(e,t){return this._subscribers.has(e)||this._subscribers.set(e,[]),this._subscribers.get(e).push(t),()=>{let i=this._subscribers.get(e),a=i.indexOf(t);a>-1&&i.splice(a,1)}}reset(e=null){if(e){let t=e.split("."),i=Re;for(let a of t)i=i?.[a];this.set(e,i)}else this._state={...Re},this._saveState(),this.dispatchEvent(new CustomEvent(He,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(e){let t=this.get("localTasks")||[],i={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...e};return this.set("localTasks",[...t,i]),i}updateLocalTask(e,t){let i=this.get("localTasks")||[],a=i.findIndex(r=>r.id===e);if(a===-1)return null;let s={...i[a],...t,updatedAt:new Date().toISOString()};return i[a]=s,this.set("localTasks",[...i]),s}deleteLocalTask(e){let t=this.get("localTasks")||[];this.set("localTasks",t.filter(i=>i.id!==e))}moveLocalTask(e,t,i=null){let s=(this.get("localTasks")||[]).find(r=>r.id===e);return s?this.updateLocalTask(e,{status:t,position:i??s.position}):null}updateSession(e){this.update(Object.fromEntries(Object.entries(e).map(([t,i])=>[`session.${t}`,i])),!1)}updateCache(e){this.update({"cache.projects":e.projects??this.get("cache.projects"),"cache.tasks":e.tasks??this.get("cache.tasks"),"cache.agents":e.agents??this.get("cache.agents"),"cache.memory":e.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let e=this.get("cache.tasks")||[],i=(this.get("localTasks")||[]).map(a=>({...a,isLocal:!0}));return[...e,...i]}getTasksByStatus(e){return this.getMergedTasks().filter(t=>t.status===e)}};S(A,"STORAGE_KEY","loki-dashboard-state"),S(A,"_instance",null);var O=A;function P(){return O.getInstance()}function Ye(d){let e=P();return{get:()=>e.get(d),set:t=>e.set(d,t),subscribe:t=>e.subscribe(d,t)}}function Qe(d){return!d||typeof d!="string"?null:d.startsWith("page-")?d.slice(5):d}function Be(){if(typeof document>"u")return null;let d=document.querySelector(".section-page.active");if(d&&d.id)return Qe(d.id);try{if(typeof localStorage<"u"){let e=localStorage.getItem("loki-active-section");if(e)return e}}catch{}return null}var Fe=class{constructor(){this._regs=new Map,this._seq=0,this._activeSection=Be(),this._hidden=typeof document<"u"?!!document.hidden:!1,this._listenersInstalled=!1,this._sectionChangeHandler=null,this._visibilityHandler=null,this._mutationObserver=null}get _hasDom(){return typeof document<"u"}_ensureListeners(){if(!(this._listenersInstalled||!this._hasDom)){this._sectionChangeHandler=e=>{let t=e&&e.detail&&e.detail.section?e.detail.section:Be();this._setActiveSection(t)},document.addEventListener("loki:section-change",this._sectionChangeHandler),this._visibilityHandler=()=>{let e=!!document.hidden;e!==this._hidden&&(this._hidden=e,e||(this._activeSection=Be()),this._reevaluateAll())},document.addEventListener("visibilitychange",this._visibilityHandler);try{let e=document.getElementById("main-content")||document.body;e&&typeof MutationObserver<"u"&&(this._mutationObserver=new MutationObserver(()=>{let t=Be();t&&t!==this._activeSection&&this._setActiveSection(t)}),this._mutationObserver.observe(e,{subtree:!0,attributes:!0,attributeFilter:["class"]}))}catch{}this._listenersInstalled=!0}}_setActiveSection(e){e!==this._activeSection&&(this._activeSection=e,this._reevaluateAll())}_resolveSection(e){if(Object.prototype.hasOwnProperty.call(e,"sectionId"))return e.sectionId===null?void 0:e.sectionId;if(e.element&&typeof e.element.closest=="function"){let t=e.element.closest(".section-page"),i=Qe(t&&t.id);return i===null?void 0:i}}_isAllowed(e){if(!this._hasDom)return!0;if(this._hidden)return!1;let t=this._resolveSection(e);return t===void 0?!0:t===this._activeSection}_reevaluateAll(){for(let e of this._regs.values()){let t=this._isAllowed(e);t&&!e._wasAllowed?(e._wasAllowed=!0,this._safeRun(e)):e._wasAllowed=t}}_safeRun(e){try{let t=e.loadFn();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}register(e={}){let{loadFn:t,intervalMs:i}=e;if(typeof t!="function")throw new Error("registerPoll: loadFn must be a function");if(typeof i!="number"||!(i>0))throw new Error("registerPoll: intervalMs must be a positive number");this._ensureListeners();let a=e.id||`poll-${++this._seq}`;this._regs.has(a)&&this._stopReg(this._regs.get(a));let s={id:a,loadFn:t,intervalMs:i,element:e.element||null,_timer:null,_wasAllowed:!1};return Object.prototype.hasOwnProperty.call(e,"sectionId")&&(s.sectionId=e.sectionId),s._wasAllowed=this._isAllowed(s),s._timer=setInterval(()=>{this._isAllowed(s)?(s._wasAllowed=!0,this._safeRun(s)):s._wasAllowed=!1},i),this._regs.set(a,s),e.immediate!==!1&&s._wasAllowed&&this._safeRun(s),{id:a,stop:()=>this.unregister(a),isActive:()=>this._isAllowed(s)}}_stopReg(e){e&&e._timer&&(clearInterval(e._timer),e._timer=null)}unregister(e){let t=this._regs.get(e);return t?(this._stopReg(t),this._regs.delete(e),!0):!1}get activeSection(){return this._activeSection}get size(){return this._regs.size}destroy(){for(let e of this._regs.values())this._stopReg(e);this._regs.clear(),this._hasDom&&(this._sectionChangeHandler&&(document.removeEventListener("loki:section-change",this._sectionChangeHandler),this._sectionChangeHandler=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null),this._mutationObserver&&(this._mutationObserver.disconnect(),this._mutationObserver=null)),this._listenersInstalled=!1}},Ie=null;function yt(){return Ie||(Ie=new Fe),Ie}function f(d){return yt().register(d)}var q=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data={status:"offline",phase:null,iteration:null,provider:null,running_agents:0,pending_tasks:null,uptime_seconds:0,complexity:null,connected:!1},this._api=null,this._pollInterval=null,this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null,this._checklistSummary=null,this._appRunnerStatus=null,this._playwrightResults=null,this._gateStatus=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._startPolling(),this._api.connect().catch(()=>{})}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._loadAbortController&&(this._loadAbortController.abort(),this._loadAbortController=null),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(v.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(v.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(v.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:e}),this._statusUpdateHandler=t=>this._updateFromStatus(t.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(v.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(v.CONNECTED,this._connectedHandler),this._api.addEventListener(v.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){this._loadAbortController&&this._loadAbortController.abort(),this._loadAbortController=new AbortController;let{signal:e}=this._loadAbortController;try{let[t,i,a,s,r]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);if(e.aborted)return;t.status==="fulfilled"?this._updateFromStatus(t.value):(this._data.connected=!1,this._data.status="offline"),i.status==="fulfilled"&&(this._checklistSummary=i.value?.summary||null),a.status==="fulfilled"&&(this._appRunnerStatus=a.value),s.status==="fulfilled"&&(this._playwrightResults=s.value),r.status==="fulfilled"&&(this._gateStatus=r.value),this.render()}catch{if(e.aborted)return;this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(e){e&&(this._data={...this._data,connected:!0,status:e.status||"offline",phase:e.phase||null,iteration:e.iteration!=null?e.iteration:null,provider:e.provider||null,running_agents:e.running_agents||0,pending_tasks:e.pending_tasks!=null?e.pending_tasks:null,uptime_seconds:e.uptime_seconds||0,complexity:e.complexity||null})}_startPolling(){this._poll=f({loadFn:async()=>{try{await this._loadStatus()}catch{this._data.connected=!1,this._data.status="offline",this.render()}},intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatUptime(e){if(!e||e<0)return"--";let t=Math.floor(e/3600),i=Math.floor(e%3600/60),a=Math.floor(e%60);return t>0?`${t}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_getStatusDotClass(){switch(this._data.status){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let e=this._appRunnerStatus;if(!e||e.status==="not_initialized")return`
|
|
2035
|
+
${V}
|
|
2036
|
+
`}getAriaPattern(e){return Pe[e]||{}}applyAriaPattern(e,t){let i=this.getAriaPattern(t);for(let[a,s]of Object.entries(i))if(a==="role")e.setAttribute("role",s);else{let r=a.replace(/([A-Z])/g,"-$1").toLowerCase();e.setAttribute(r,s)}}render(){}};var I={realtime:1e3,normal:2e3,background:5e3,offline:1e4},Ze={vscode:I.normal,browser:I.realtime,cli:I.background},et={baseUrl:typeof window<"u"?window.location.origin:"http://localhost:57374",wsUrl:typeof window<"u"?`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws`:"ws://localhost:57374/ws",pollInterval:2e3,timeout:1e4,retryAttempts:3,retryDelay:1e3},f={CONNECTED:"api:connected",DISCONNECTED:"api:disconnected",ERROR:"api:error",STATUS_UPDATE:"api:status-update",TASK_CREATED:"api:task-created",TASK_UPDATED:"api:task-updated",TASK_DELETED:"api:task-deleted",PROJECT_CREATED:"api:project-created",PROJECT_UPDATED:"api:project-updated",AGENT_UPDATE:"api:agent-update",LOG_MESSAGE:"api:log-message",MEMORY_UPDATE:"api:memory-update",CHECKLIST_UPDATE:"api:checklist-update"},z=class z extends EventTarget{static getInstance(e={}){let t=e.baseUrl||et.baseUrl;return z._instances.has(t)||z._instances.set(t,new z(e)),z._instances.get(t)}static clearInstances(){z._instances.forEach(e=>e.disconnect()),z._instances.clear()}constructor(e={}){super(),this.config={...et,...e},this._ws=null,this._connected=!1,this._pollInterval=null,this._reconnectTimeout=null,this._reconnectAttempts=0,this._maxReconnectAttempts=20,this._cache=new Map,this._cacheTimeout=5e3,this._vscodeApi=null,this._context=this._detectContext(),this._currentPollInterval=Ze[this._context]||I.normal,this._visibilityChangeHandler=null,this._messageHandler=null,this._setupAdaptivePolling(),this._setupVSCodeBridge()}_detectContext(){return typeof acquireVsCodeApi<"u"?"vscode":typeof window<"u"&&window.location?"browser":"cli"}get context(){return this._context}static get POLL_INTERVALS(){return I}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(I.background):this._setPollInterval(Ze[this._context]||I.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(e){this._currentPollInterval=e,this._pollInterval&&(this.stopPolling(),this.startPolling(null,e))}setPollMode(e){let t=I[e];t&&this._setPollInterval(t)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=e=>{let t=e.data;if(!(!t||!t.type))switch(t.type){case"updateStatus":this._emit(f.STATUS_UPDATE,t.data);break;case"updateTasks":this._emit(f.TASK_UPDATED,t.data);break;case"taskCreated":this._emit(f.TASK_CREATED,t.data);break;case"taskDeleted":this._emit(f.TASK_DELETED,t.data);break;case"projectCreated":this._emit(f.PROJECT_CREATED,t.data);break;case"projectUpdated":this._emit(f.PROJECT_UPDATED,t.data);break;case"agentUpdate":this._emit(f.AGENT_UPDATE,t.data);break;case"logMessage":this._emit(f.LOG_MESSAGE,t.data);break;case"memoryUpdate":this._emit(f.MEMORY_UPDATE,t.data);break;case"connected":this._connected=!0,this._emit(f.CONNECTED,t.data);break;case"disconnected":this._connected=!1,this._emit(f.DISCONNECTED,t.data);break;case"error":this._emit(f.ERROR,t.data);break;case"setPollMode":this.setPollMode(t.data.mode);break;default:this._emit(`api:${t.type}`,t.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(e,t={}){this._vscodeApi&&this._vscodeApi.postMessage({type:e,data:t})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(e,t={}){this.postToVSCode("userAction",{action:e,...t})}get baseUrl(){return this.config.baseUrl}set baseUrl(e){this.config.baseUrl=e,this.config.wsUrl=e.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((e,t)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._reconnectAttempts=0,this._emit(f.CONNECTED),e()},this._ws.onclose=()=>{this._connected=!1,this._emit(f.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=i=>{this._emit(f.ERROR,{error:i}),t(i)},this._ws.onmessage=i=>{try{let a=JSON.parse(i.data);this._handleMessage(a)}catch(a){console.error("Failed to parse WebSocket message:",a)}}}catch(i){t(i)}})}disconnect(){this._ws&&(this._ws.close(),this._ws=null),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._reconnectTimeout&&(clearTimeout(this._reconnectTimeout),this._reconnectTimeout=null),this._connected=!1,this._cleanupGlobalListeners()}_cleanupGlobalListeners(){this._visibilityChangeHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this._visibilityChangeHandler),this._visibilityChangeHandler=null),this._messageHandler&&typeof window<"u"&&(window.removeEventListener("message",this._messageHandler),this._messageHandler=null)}destroy(){this.disconnect()}_scheduleReconnect(){if(this._reconnectTimeout)return;if(this._reconnectAttempts>=this._maxReconnectAttempts){console.warn("WebSocket max reconnect attempts reached, giving up"),this._emit(f.ERROR,{error:"Max reconnect attempts reached"});return}let e=Math.min(this.config.retryDelay*Math.pow(2,this._reconnectAttempts),3e4);this._reconnectAttempts++,this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},e)}_handleMessage(e){if(e.type==="ping"){this._ws&&this._ws.readyState===WebSocket.OPEN&&this._ws.send(JSON.stringify({type:"pong"}));return}let i={connected:f.CONNECTED,status_update:f.STATUS_UPDATE,task_created:f.TASK_CREATED,task_updated:f.TASK_UPDATED,task_deleted:f.TASK_DELETED,task_moved:f.TASK_UPDATED,project_created:f.PROJECT_CREATED,project_updated:f.PROJECT_UPDATED,agent_update:f.AGENT_UPDATE,log:f.LOG_MESSAGE}[e.type]||`api:${e.type}`;this._emit(i,e.data)}_emit(e,t={}){this.dispatchEvent(new CustomEvent(e,{detail:t}))}async _request(e,t={}){let i=`${this.config.baseUrl}${e}`,a=new AbortController,s=t&&typeof t.timeout=="number"?t.timeout:this.config.timeout,r=setTimeout(()=>a.abort(),s);try{let o=await fetch(i,{...t,signal:a.signal,credentials:"include",headers:{"Content-Type":"application/json",...t.headers}});if(clearTimeout(r),!o.ok){let n=await o.text().catch(()=>""),l=o.statusText||`HTTP ${o.status}`;if(n)try{let c=JSON.parse(n);l=c.detail||c.error||c.message||l}catch{l=n.length>200?n.slice(0,200)+"...":n}throw new Error(l)}return o.status===204?null:await o.json()}catch(o){throw clearTimeout(r),o.name==="AbortError"?new Error("Request timeout"):o}}async _get(e,t=!1){if(t&&this._cache.has(e)){let a=this._cache.get(e);if(Date.now()-a.timestamp<this._cacheTimeout)return a.data}let i=await this._request(e);return t&&this._cache.set(e,{data:i,timestamp:Date.now()}),i}async _post(e,t,i={}){return this._request(e,{method:"POST",body:JSON.stringify(t),...i})}async _put(e,t){return this._request(e,{method:"PUT",body:JSON.stringify(t)})}async _delete(e){return this._request(e,{method:"DELETE"})}async get(e){return this._get(e)}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(e=null){let t=e?`?status=${e}`:"";return this._get(`/api/projects${t}`)}async getProject(e){return this._get(`/api/projects/${e}`)}async createProject(e){return this._post("/api/projects",e)}async updateProject(e,t){return this._put(`/api/projects/${e}`,t)}async deleteProject(e){return this._delete(`/api/projects/${e}`)}async listTasks(e={}){let t=new URLSearchParams;e.projectId&&t.append("project_id",e.projectId),e.status&&t.append("status",e.status),e.priority&&t.append("priority",e.priority);let i=t.toString()?`?${t}`:"";return this._get(`/api/tasks${i}`)}async getTask(e){return this._get(`/api/tasks/${e}`)}async createTask(e){return this._post("/api/tasks",e)}async updateTask(e,t){return this._put(`/api/tasks/${e}`,t)}async moveTask(e,t,i){return this._post(`/api/tasks/${e}/move`,{status:t,position:i})}async deleteTask(e){return this._delete(`/api/tasks/${e}`)}async getMemorySummary(){return this._get("/api/memory/summary",!0)}async getMemoryIndex(){return this._get("/api/memory/index",!0)}async getMemoryTimeline(){return this._get("/api/memory/timeline")}async listEpisodes(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/episodes${t?"?"+t:""}`)}async getEpisode(e){return this._get(`/api/memory/episodes/${e}`)}async listPatterns(e={}){let t=new URLSearchParams(e).toString();return this._get(`/api/memory/patterns${t?"?"+t:""}`)}async getPattern(e){return this._get(`/api/memory/patterns/${e}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(e){return this._get(`/api/memory/skills/${e}`)}async retrieveMemories(e,t=null,i=5){return this._post("/api/memory/retrieve",{query:e,taskType:t,topK:i},{timeout:3e4})}async consolidateMemory(e=24){return this._post("/api/memory/consolidate",{sinceHours:e},{timeout:12e4})}async getTokenEconomics(){return this._get("/api/memory/economics")}async searchMemory(e,t="all",i=20){let a=new URLSearchParams({q:e,collection:t,limit:String(i)});return this._get(`/api/memory/search?${a}`)}async getMemoryStats(){return this._get("/api/memory/stats",!0)}async listRegisteredProjects(e=!1){return this._get(`/api/registry/projects?include_inactive=${e}`)}async registerProject(e,t=null,i=null){return this._post("/api/registry/projects",{path:e,name:t,alias:i})}async discoverProjects(e=3){return this._get(`/api/registry/discover?max_depth=${e}`)}async syncRegistry(){return this._post("/api/registry/sync",{},{timeout:45e3})}async getCrossProjectTasks(e=null){let t=e?`?project_ids=${e.join(",")}`:"";return this._get(`/api/registry/tasks${t}`)}async getLearningMetrics(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/metrics${i}`)}async getLearningTrends(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source);let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/trends${i}`)}async getLearningSignals(e={}){let t=new URLSearchParams;e.timeRange&&t.append("timeRange",e.timeRange),e.signalType&&t.append("signalType",e.signalType),e.source&&t.append("source",e.source),e.limit&&t.append("limit",String(e.limit)),e.offset&&t.append("offset",String(e.offset));let i=t.toString()?`?${t}`:"";return this._get(`/api/learning/signals${i}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(e={}){return this._post("/api/learning/aggregate",e,{timeout:6e4})}async getAggregatedPreferences(e=20){return this._get(`/api/learning/preferences?limit=${e}`)}async getAggregatedErrors(e=20){return this._get(`/api/learning/errors?limit=${e}`)}async getAggregatedSuccessPatterns(e=20){return this._get(`/api/learning/success?limit=${e}`)}async getToolEfficiency(e=20){return this._get(`/api/learning/tools?limit=${e}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(e=20){return this._get(`/api/council/verdicts?limit=${e}`)}async getCouncilConvergence(){return this._get("/api/council/convergence")}async getCouncilReport(){return this._get("/api/council/report")}async forceCouncilReview(){return this._post("/api/council/force-review",{})}async getContext(){return this._get("/api/context")}async getNotifications(e,t){let i=new URLSearchParams;e&&i.set("severity",e),t&&i.set("unread_only","true");let a=i.toString();return this._get("/api/notifications"+(a?"?"+a:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(e){return this._put("/api/notifications/triggers",{triggers:e})}async acknowledgeNotification(e){return this._post("/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{})}async startSession(e,t={}){let i={provider:t.provider||"claude",parallel:!!t.parallel};return t.prdPath?i.prd_path=t.prdPath:i.prd_text=e||"",this._post("/api/control/start",i)}async pauseSession(){return this._post("/api/control/pause",{})}async resumeSession(){return this._post("/api/control/resume",{})}async stopSession(){return this._post("/api/control/stop",{})}async getSessionModel(){return this._get("/api/session/model")}async setSessionModel(e){return this._post("/api/session/model",{model:e||null})}async getLogs(e=100){return this._get(`/api/logs?lines=${e}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let e=await fetch(`${this.baseUrl}/api/prd-observations`,{credentials:"include"});if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(e,t,i="dashboard"){return this._post("/api/checklist/waivers",{item_id:e,reason:t,waived_by:i})}async removeChecklistWaiver(e){return this._delete(`/api/checklist/waivers/${encodeURIComponent(e)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(e=100){return this._get(`/api/app-runner/logs?lines=${e}`)}async getAppRunnerErrors(e=50){return this._get(`/api/app-runner/errors?lines=${e}`)}async restartApp(){return this._post("/api/control/app-restart",{})}async stopApp(){return this._post("/api/control/app-stop",{})}async getPlaywrightResults(){return this._get("/api/playwright/results")}async getPlaywrightScreenshot(){return this._get("/api/playwright/screenshot")}startPolling(e,t=null){if(this._pollInterval)return;this._pollCallback=e;let i=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(f.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(f.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};i();let a=t||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(i,a)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};S(z,"_instances",new Map);var N=z;function tt(d={}){return new N(d)}function m(d={}){return N.getInstance(d)}var je="loki-state-change",Fe={ui:{theme:"light",sidebarCollapsed:!1,activeSection:"kanban",terminalAutoScroll:!0},session:{connected:!1,lastSync:null,mode:"offline",phase:null,iteration:null},localTasks:[],cache:{projects:[],tasks:[],agents:[],memory:null,lastFetch:null},preferences:{pollInterval:2e3,notifications:!0,soundEnabled:!1}},T=class T extends EventTarget{static getInstance(){return T._instance||(T._instance=new T),T._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let e=localStorage.getItem(T.STORAGE_KEY);if(e){let t=JSON.parse(e);return this._mergeState(Fe,t)}}catch(e){console.warn("Failed to load state from localStorage:",e)}return{...Fe}}_mergeState(e,t){let i={...e};for(let a of Object.keys(t))a in e&&typeof e[a]=="object"&&!Array.isArray(e[a])?i[a]=this._mergeState(e[a],t[a]):i[a]=t[a];return i}_saveState(){try{let e={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(T.STORAGE_KEY,JSON.stringify(e))}catch(e){console.warn("Failed to save state to localStorage:",e)}}get(e=null){if(!e)return{...this._state};let t=e.split("."),i=this._state;for(let a of t){if(i==null)return;i=i[a]}return i}set(e,t,i=!0){let a=e.split("."),s=a.pop(),r=this._state;for(let n of a)n in r||(r[n]={}),r=r[n];let o=r[s];r[s]=t,i&&this._saveState(),this._notifyChange(e,t,o)}update(e,t=!0){let i=[];for(let[a,s]of Object.entries(e)){let r=this.get(a);this.set(a,s,!1),i.push({path:a,value:s,oldValue:r})}t&&this._saveState();for(let a of i)this._notifyChange(a.path,a.value,a.oldValue)}_notifyChange(e,t,i){this.dispatchEvent(new CustomEvent(je,{detail:{path:e,value:t,oldValue:i}}));let a=this._subscribers.get(e)||[];for(let r of a)try{r(t,i,e)}catch(o){console.error("State subscriber error:",o)}let s=e.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let n of o)try{n(this.get(r),null,r)}catch(l){console.error("State subscriber error:",l)}}}subscribe(e,t){return this._subscribers.has(e)||this._subscribers.set(e,[]),this._subscribers.get(e).push(t),()=>{let i=this._subscribers.get(e),a=i.indexOf(t);a>-1&&i.splice(a,1)}}reset(e=null){if(e){let t=e.split("."),i=Fe;for(let a of t)i=i?.[a];this.set(e,i)}else this._state={...Fe},this._saveState(),this.dispatchEvent(new CustomEvent(je,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(e){let t=this.get("localTasks")||[],i={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...e};return this.set("localTasks",[...t,i]),i}updateLocalTask(e,t){let i=this.get("localTasks")||[],a=i.findIndex(r=>r.id===e);if(a===-1)return null;let s={...i[a],...t,updatedAt:new Date().toISOString()};return i[a]=s,this.set("localTasks",[...i]),s}deleteLocalTask(e){let t=this.get("localTasks")||[];this.set("localTasks",t.filter(i=>i.id!==e))}moveLocalTask(e,t,i=null){let s=(this.get("localTasks")||[]).find(r=>r.id===e);return s?this.updateLocalTask(e,{status:t,position:i??s.position}):null}updateSession(e){this.update(Object.fromEntries(Object.entries(e).map(([t,i])=>[`session.${t}`,i])),!1)}updateCache(e){this.update({"cache.projects":e.projects??this.get("cache.projects"),"cache.tasks":e.tasks??this.get("cache.tasks"),"cache.agents":e.agents??this.get("cache.agents"),"cache.memory":e.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let e=this.get("cache.tasks")||[],i=(this.get("localTasks")||[]).map(a=>({...a,isLocal:!0}));return[...e,...i]}getTasksByStatus(e){return this.getMergedTasks().filter(t=>t.status===e)}};S(T,"STORAGE_KEY","loki-dashboard-state"),S(T,"_instance",null);var W=T;function U(){return W.getInstance()}function it(d){let e=U();return{get:()=>e.get(d),set:t=>e.set(d,t),subscribe:t=>e.subscribe(d,t)}}function Ue(d){return String(d??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function C(d){if(d==null||d==="")return"";let e=String(d).replace(/\r\n/g,`
|
|
2037
|
+
`),t=[];e=e.replace(/```[^\n]*\n([\s\S]*?)```/g,(h,v)=>{let u=t.length;return t.push(`<pre class="md-code"><code>${Ue(v.replace(/\n$/,""))}</code></pre>`),`\0CODEBLOCK${u}\0`});let i=Ue(e);i=i.replace(/`([^`\n]+)`/g,(h,v)=>`<code class="md-inline-code">${v}</code>`),i=i.replace(/\[([^\]\n]+)\]\(([^)\s]+)\)/g,(h,v,u)=>/^(https?:|mailto:|\/|#|\.)/.test(u)?`<a class="md-link" href="${u}" target="_blank" rel="noopener noreferrer">${v}</a>`:h);let a=i.split(`
|
|
2038
|
+
`),s=[],r=[],o=[],n=()=>{r.length&&(s.push(`<p class="md-p">${r.join("<br>")}</p>`),r=[])},l=h=>{for(;o.length&&o[o.length-1].indent>=h;)s.push(`</${o.pop().tag}>`)},c=()=>{for(;o.length;)s.push(`</${o.pop().tag}>`)};for(let h of a){let v=h,u=v.trim(),x=u.match(/^CODEBLOCK(\d+)$/);if(x){n(),c(),s.push(t[Number(x[1])]);continue}if(u===""){n(),c();continue}let k=u.match(/^(#{1,6})\s+(.+)$/);if(k){n(),c();let H=Math.min(k[1].length+1,6);s.push(`<h${H} class="md-h${H}">${k[2]}</h${H}>`);continue}if(/^(-{3,}|\*{3,}|_{3,})$/.test(u)){n(),c(),s.push('<hr class="md-hr">');continue}let _=u.match(/^>\s?(.*)$/);if(_){n(),c(),s.push(`<blockquote class="md-quote">${_[1]}</blockquote>`);continue}let R=v.match(/^(\s*)/)[1].replace(/\t/g," ").length,J=u.match(/^([-*+])\s+(.+)$/),G=u.match(/^(\d+)[.)]\s+(.+)$/);if(J||G){n();let H=G?"ol":"ul",kt=J?J[2]:G[2];!o.length||R>o[o.length-1].indent?(s.push(`<${H} class="md-list">`),o.push({tag:H,indent:R})):(l(R+1),o.length||(s.push(`<${H} class="md-list">`),o.push({tag:H,indent:R}))),s.push(`<li>${kt}</li>`);continue}c(),r.push(v.trim())}n(),c();let p=s.join(`
|
|
2039
|
+
`);return p=p.replace(/\*\*([^*\n]+)\*\*/g,"<strong>$1</strong>"),p=p.replace(/__([^_\n]+)__/g,"<strong>$1</strong>"),p=p.replace(/(^|[^*])\*([^*\n]+)\*/g,"$1<em>$2</em>"),p}var L=`
|
|
2040
|
+
.md-body { line-height: 1.6; color: var(--loki-text, #2b2a28); font-size: 14px; word-wrap: break-word; }
|
|
2041
|
+
.md-body .md-h2 { font-size: 18px; font-weight: 650; margin: 18px 0 8px; }
|
|
2042
|
+
.md-body .md-h3 { font-size: 16px; font-weight: 600; margin: 16px 0 6px; }
|
|
2043
|
+
.md-body .md-h4, .md-body .md-h5, .md-body .md-h6 { font-size: 14px; font-weight: 600; margin: 14px 0 6px; }
|
|
2044
|
+
.md-body .md-p { margin: 8px 0; }
|
|
2045
|
+
.md-body .md-list { margin: 8px 0 8px 22px; padding: 0; }
|
|
2046
|
+
.md-body .md-list li { margin: 3px 0; }
|
|
2047
|
+
.md-body .md-code { background: var(--loki-code-bg, #f4f2ee); border: 1px solid var(--loki-border, #e5e1d8); border-radius: 6px; padding: 12px 14px; overflow-x: auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.5; margin: 10px 0; }
|
|
2048
|
+
.md-body .md-code code { background: none; border: 0; padding: 0; }
|
|
2049
|
+
.md-body .md-inline-code { background: var(--loki-code-bg, #f4f2ee); border: 1px solid var(--loki-border, #e5e1d8); border-radius: 4px; padding: 1px 5px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }
|
|
2050
|
+
.md-body .md-quote { border-left: 3px solid var(--loki-accent, #6b6bff); margin: 10px 0; padding: 4px 0 4px 14px; color: var(--loki-text-secondary, #6b6a66); }
|
|
2051
|
+
.md-body .md-link { color: var(--loki-accent, #6b6bff); text-decoration: none; }
|
|
2052
|
+
.md-body .md-link:hover { text-decoration: underline; }
|
|
2053
|
+
.md-body .md-hr { border: 0; border-top: 1px solid var(--loki-border, #e5e1d8); margin: 16px 0; }
|
|
2054
|
+
.md-body strong { font-weight: 650; }
|
|
2055
|
+
`;function at(d){return!d||typeof d!="string"?null:d.startsWith("page-")?d.slice(5):d}function Oe(){if(typeof document>"u")return null;let d=document.querySelector(".section-page.active");if(d&&d.id)return at(d.id);try{if(typeof localStorage<"u"){let e=localStorage.getItem("loki-active-section");if(e)return e}}catch{}return null}var Je=class{constructor(){this._regs=new Map,this._seq=0,this._activeSection=Oe(),this._hidden=typeof document<"u"?!!document.hidden:!1,this._listenersInstalled=!1,this._sectionChangeHandler=null,this._visibilityHandler=null,this._mutationObserver=null}get _hasDom(){return typeof document<"u"}_ensureListeners(){if(!(this._listenersInstalled||!this._hasDom)){this._sectionChangeHandler=e=>{let t=e&&e.detail&&e.detail.section?e.detail.section:Oe();this._setActiveSection(t)},document.addEventListener("loki:section-change",this._sectionChangeHandler),this._visibilityHandler=()=>{let e=!!document.hidden;e!==this._hidden&&(this._hidden=e,e||(this._activeSection=Oe()),this._reevaluateAll())},document.addEventListener("visibilitychange",this._visibilityHandler);try{let e=document.getElementById("main-content")||document.body;e&&typeof MutationObserver<"u"&&(this._mutationObserver=new MutationObserver(()=>{let t=Oe();t&&t!==this._activeSection&&this._setActiveSection(t)}),this._mutationObserver.observe(e,{subtree:!0,attributes:!0,attributeFilter:["class"]}))}catch{}this._listenersInstalled=!0}}_setActiveSection(e){e!==this._activeSection&&(this._activeSection=e,this._reevaluateAll())}_resolveSection(e){if(Object.prototype.hasOwnProperty.call(e,"sectionId"))return e.sectionId===null?void 0:e.sectionId;if(e.element&&typeof e.element.closest=="function"){let t=e.element.closest(".section-page"),i=at(t&&t.id);return i===null?void 0:i}}_isAllowed(e){if(!this._hasDom)return!0;if(this._hidden)return!1;let t=this._resolveSection(e);return t===void 0?!0:t===this._activeSection}_reevaluateAll(){for(let e of this._regs.values()){let t=this._isAllowed(e);t&&!e._wasAllowed?(e._wasAllowed=!0,this._safeRun(e)):e._wasAllowed=t}}_safeRun(e){try{let t=e.loadFn();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}register(e={}){let{loadFn:t,intervalMs:i}=e;if(typeof t!="function")throw new Error("registerPoll: loadFn must be a function");if(typeof i!="number"||!(i>0))throw new Error("registerPoll: intervalMs must be a positive number");this._ensureListeners();let a=e.id||`poll-${++this._seq}`;this._regs.has(a)&&this._stopReg(this._regs.get(a));let s={id:a,loadFn:t,intervalMs:i,element:e.element||null,_timer:null,_wasAllowed:!1};return Object.prototype.hasOwnProperty.call(e,"sectionId")&&(s.sectionId=e.sectionId),s._wasAllowed=this._isAllowed(s),s._timer=setInterval(()=>{this._isAllowed(s)?(s._wasAllowed=!0,this._safeRun(s)):s._wasAllowed=!1},i),this._regs.set(a,s),e.immediate!==!1&&s._wasAllowed&&this._safeRun(s),{id:a,stop:()=>this.unregister(a),isActive:()=>this._isAllowed(s)}}_stopReg(e){e&&e._timer&&(clearInterval(e._timer),e._timer=null)}unregister(e){let t=this._regs.get(e);return t?(this._stopReg(t),this._regs.delete(e),!0):!1}get activeSection(){return this._activeSection}get size(){return this._regs.size}destroy(){for(let e of this._regs.values())this._stopReg(e);this._regs.clear(),this._hasDom&&(this._sectionChangeHandler&&(document.removeEventListener("loki:section-change",this._sectionChangeHandler),this._sectionChangeHandler=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null),this._mutationObserver&&(this._mutationObserver.disconnect(),this._mutationObserver=null)),this._listenersInstalled=!1}},qe=null;function St(){return qe||(qe=new Je),qe}function b(d){return St().register(d)}var Y=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data={status:"offline",phase:null,iteration:null,provider:null,running_agents:0,pending_tasks:null,uptime_seconds:0,complexity:null,connected:!1},this._api=null,this._pollInterval=null,this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null,this._checklistSummary=null,this._appRunnerStatus=null,this._playwrightResults=null,this._gateStatus=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._startPolling(),this._api.connect().catch(()=>{})}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._loadAbortController&&(this._loadAbortController.abort(),this._loadAbortController=null),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(f.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(f.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(f.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e}),this._statusUpdateHandler=t=>this._updateFromStatus(t.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(f.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(f.CONNECTED,this._connectedHandler),this._api.addEventListener(f.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){this._loadAbortController&&this._loadAbortController.abort(),this._loadAbortController=new AbortController;let{signal:e}=this._loadAbortController;try{let[t,i,a,s,r]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);if(e.aborted)return;t.status==="fulfilled"?this._updateFromStatus(t.value):(this._data.connected=!1,this._data.status="offline"),i.status==="fulfilled"&&(this._checklistSummary=i.value?.summary||null),a.status==="fulfilled"&&(this._appRunnerStatus=a.value),s.status==="fulfilled"&&(this._playwrightResults=s.value),r.status==="fulfilled"&&(this._gateStatus=r.value),this.render()}catch{if(e.aborted)return;this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(e){e&&(this._data={...this._data,connected:!0,status:e.status||"offline",phase:e.phase||null,iteration:e.iteration!=null?e.iteration:null,provider:e.provider||null,running_agents:e.running_agents||0,pending_tasks:e.pending_tasks!=null?e.pending_tasks:null,uptime_seconds:e.uptime_seconds||0,complexity:e.complexity||null})}_startPolling(){this._poll=b({loadFn:async()=>{try{await this._loadStatus()}catch{this._data.connected=!1,this._data.status="offline",this.render()}},intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatUptime(e){if(!e||e<0)return"--";let t=Math.floor(e/3600),i=Math.floor(e%3600/60),a=Math.floor(e%60);return t>0?`${t}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_getStatusDotClass(){switch(this._data.status){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let e=this._appRunnerStatus;if(!e||e.status==="not_initialized")return`
|
|
2035
2056
|
<div class="overview-card">
|
|
2036
2057
|
<div class="card-label">App Status</div>
|
|
2037
2058
|
<div class="card-value small-text">${this._data.status==="running"||this._data.status==="autonomous"?"Starting...":"Not started"}</div>
|
|
@@ -2286,8 +2307,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2286
2307
|
</div>
|
|
2287
2308
|
</div>
|
|
2288
2309
|
</div>
|
|
2289
|
-
`}};customElements.get("loki-overview")||customElements.define("loki-overview",
|
|
2290
|
-
<ul class="md-list">${a.trim().split(/\n/).map(r=>r.replace(/^[-*]\s+/,"")).map(r=>`<li>${r}</li>`).join("")}</ul>`),t=t.split(/\n{2,}/).map(i=>/^<(h\d|ul|ol|pre)/.test(i.trim())?i:`<p class="md-p">${i.replace(/\n/g,"<br>")}</p>`).join(""),t}_formatTimestamp(e){if(!e)return"";try{let t=new Date(e);return isNaN(t.getTime())?this._escapeHtml(String(e)):t.toLocaleString()}catch{return this._escapeHtml(String(e))}}_phaseClass(e){let t=String(e||"").toLowerCase();return["reason","plan","planning"].includes(t)?"phase-reason":["act","execute","execution","implement"].includes(t)?"phase-act":["reflect","review"].includes(t)?"phase-reflect":["verify","test","gate"].includes(t)?"phase-verify":"phase-default"}_logLevelClass(e){let t=String(e||"info").toLowerCase();return t==="error"||t==="fatal"?"log-error":t==="warn"||t==="warning"?"log-warn":t==="debug"||t==="trace"?"log-debug":"log-info"}_renderTaskDetailModal(e){if(!e)return"";let t=(e.priority||"medium").toLowerCase(),i=t.charAt(0).toUpperCase()+t.slice(1),a=e.status||"pending",s=a.replace(/_/g," ").replace(/\b\w/g,m=>m.toUpperCase()),r=e.metadata||{},o=e.acceptance_criteria||[],n=e.context_files||[],l=e.specification||"",c=e.description||"",p=Array.isArray(e.notes)?e.notes:[],h=Array.isArray(e.logs)?e.logs:[],b=e.full_content||"";return`
|
|
2310
|
+
`}};customElements.get("loki-overview")||customElements.define("loki-overview",Y);var At=[{id:"pending",label:"Pending",status:"pending",color:"var(--loki-text-muted)"},{id:"in_progress",label:"In Progress",status:"in_progress",color:"var(--loki-blue)"},{id:"review",label:"In Review",status:"review",color:"var(--loki-purple)"},{id:"done",label:"Completed",status:"done",color:"var(--loki-green)"}],Q=class d extends g{static get observedAttributes(){return["api-url","project-id","theme","readonly"]}constructor(){super(),this._tasks=[],this._loading=!0,this._error=null,this._draggedTask=null,this._selectedTask=null,this._expandedCards=new Set,this._selectedTasks=new Set,this._bulkMode=!1,this._activeFilter="all",this._searchQuery="",this._visibleCounts={},this._api=null,this._state=U()}static get PAGE_SIZE(){return 10}_getVisibleCount(e){let t=this._visibleCounts[e];return typeof t=="number"&&t>0?t:d.PAGE_SIZE}_showMore(e){this._visibleCounts[e]=this._getVisibleCount(e)+d.PAGE_SIZE,this.render()}_columnIcon(e){switch(e){case"pending":return'<circle cx="12" cy="12" r="10"/>';case"in_progress":return'<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>';case"review":return'<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>';case"done":return'<path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>';default:return'<circle cx="12" cy="12" r="10"/>'}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadTasks()}disconnectedCallback(){super.disconnectedCallback(),this._api&&(this._api.removeEventListener(f.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(f.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(f.TASK_DELETED,this._onTaskEvent))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadTasks()),e==="project-id"&&this._loadTasks(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e}),this._onTaskEvent&&(this._api.removeEventListener(f.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(f.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(f.TASK_DELETED,this._onTaskEvent)),this._onTaskEvent=()=>this._loadTasks(),this._api.addEventListener(f.TASK_CREATED,this._onTaskEvent),this._api.addEventListener(f.TASK_UPDATED,this._onTaskEvent),this._api.addEventListener(f.TASK_DELETED,this._onTaskEvent)}async _loadTasks(){this._loading=!0,this._error=null,this.render();try{let e=this.getAttribute("project-id"),t=e?{projectId:parseInt(e)}:{};this._tasks=await this._api.listTasks(t);let i=this._state.get("localTasks")||[];i.length>0&&(this._tasks=[...this._tasks,...i.map(a=>({...a,isLocal:!0}))]),this._state.update({"cache.tasks":this._tasks},!1)}catch(e){this._error=e.message,this._tasks=(this._state.get("localTasks")||[]).map(t=>({...t,isLocal:!0}))}this._loading=!1,this.render()}_getTasksByStatus(e){return this._getFilteredTasks().filter(i=>i.status?.toLowerCase().replace(/-/g,"_")===e)}_handleDragStart(e,t){this.hasAttribute("readonly")||(this._draggedTask=t,e.target.classList.add("dragging"),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",t.id.toString()))}_handleDragEnd(e){e.target.classList.remove("dragging"),this._draggedTask=null,this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(t=>{t.classList.remove("drag-over")})}_handleDragOver(e){e.preventDefault(),e.dataTransfer.dropEffect="move"}_handleDragEnter(e){e.preventDefault(),e.currentTarget.classList.add("drag-over")}_handleDragLeave(e){e.currentTarget.contains(e.relatedTarget)||e.currentTarget.classList.remove("drag-over")}async _handleDrop(e,t){if(e.preventDefault(),e.currentTarget.classList.remove("drag-over"),!this._draggedTask||this.hasAttribute("readonly"))return;let i=this._draggedTask.id,a=this._tasks.find(r=>r.id===i);if(!a)return;let s=a.status;if(s!==t){a.status=t,this.render();try{a.isLocal?this._state.moveLocalTask(i,t):await this._api.moveTask(i,t,0),this.dispatchEvent(new CustomEvent("task-moved",{detail:{taskId:i,oldStatus:s,newStatus:t}}))}catch(r){a.status=s,this.render(),console.error("Failed to move task:",r)}}}_toggleCardExpand(e){this._expandedCards.has(e)?this._expandedCards.delete(e):this._expandedCards.add(e),this.render()}_toggleTaskSelection(e,t){t&&t.stopPropagation(),this._selectedTasks.has(e)?this._selectedTasks.delete(e):this._selectedTasks.add(e),this.render()}_toggleBulkMode(){this._bulkMode=!this._bulkMode,this._bulkMode||this._selectedTasks.clear(),this.render()}async _bulkMove(e){let t=[...this._selectedTasks];for(let i of t){let a=this._tasks.find(s=>String(s.id)===String(i));if(a&&a.status!==e)try{a.isLocal?this._state.moveLocalTask(i,e):await this._api.moveTask(i,e,0),a.status=e}catch(s){console.error("Failed to bulk move task:",i,s)}}this._selectedTasks.clear(),this._bulkMode=!1,this.render(),this._loadTasks()}async _bulkDelete(){let e=[...this._selectedTasks];for(let t of e)try{await this._api.deleteTask(t)}catch(i){console.error("Failed to delete task:",t,i)}this._selectedTasks.clear(),this._bulkMode=!1,this._loadTasks()}_setFilter(e){this._activeFilter=e,this._visibleCounts={},this.render()}_setSearch(e){this._searchQuery=e||"",this._visibleCounts={},this._renderTaskRegion();let t=this.shadowRoot.getElementById("task-search");if(t){t.focus();let i=t.value.length;try{t.setSelectionRange(i,i)}catch{}}}_getFilteredTasks(){let e=[...this._tasks],t=new Date,i=new Date(t.getFullYear(),t.getMonth(),t.getDate()),a=new Date(i.getTime()-7*24*60*60*1e3);switch(this._activeFilter){case"today":e=e.filter(r=>{let o=r.created_at?new Date(r.created_at):null;return o&&o>=i});break;case"this-week":e=e.filter(r=>{let o=r.created_at?new Date(r.created_at):null;return o&&o>=a});break;case"running":e=e.filter(r=>r.status==="in_progress");break;case"failed":e=e.filter(r=>r.status==="failed"||r.status==="error");break;default:break}let s=this._searchQuery.trim().toLowerCase();return s&&(e=e.filter(r=>[r.id,r.title,r.description,r.type].map(n=>String(n??"").toLowerCase()).join(" ").includes(s))),e}_openAddTaskModal(e="pending"){this.dispatchEvent(new CustomEvent("add-task",{detail:{status:e}}))}_openTaskDetail(e){this._selectedTask=e,this.render(),this.dispatchEvent(new CustomEvent("task-click",{detail:{task:e}}))}_closeTaskDetail(){this._selectedTask=null,this.render()}_renderMarkdown(e){return C(e)}_formatTimestamp(e){if(!e)return"";try{let t=new Date(e);return isNaN(t.getTime())?this._escapeHtml(String(e)):t.toLocaleString()}catch{return this._escapeHtml(String(e))}}_phaseClass(e){let t=String(e||"").toLowerCase();return["reason","plan","planning"].includes(t)?"phase-reason":["act","execute","execution","implement"].includes(t)?"phase-act":["reflect","review"].includes(t)?"phase-reflect":["verify","test","gate"].includes(t)?"phase-verify":"phase-default"}_logLevelClass(e){let t=String(e||"info").toLowerCase();return t==="error"||t==="fatal"?"log-error":t==="warn"||t==="warning"?"log-warn":t==="debug"||t==="trace"?"log-debug":"log-info"}_renderTaskDetailModal(e){if(!e)return"";let t=(e.priority||"medium").toLowerCase(),i=t.charAt(0).toUpperCase()+t.slice(1),a=e.status||"pending",s=a.replace(/_/g," ").replace(/\b\w/g,u=>u.toUpperCase()),r=e.metadata||{},o=e.acceptance_criteria||[],n=e.context_files||[],l=e.specification||"",c=e.description||"",p=Array.isArray(e.notes)?e.notes:[],h=Array.isArray(e.logs)?e.logs:[],v=e.full_content||"";return`
|
|
2291
2311
|
<div class="modal-overlay" id="task-detail-overlay">
|
|
2292
2312
|
<div class="modal-container">
|
|
2293
2313
|
<div class="modal-header">
|
|
@@ -2304,9 +2324,9 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2304
2324
|
<div class="modal-section">
|
|
2305
2325
|
<h3 class="modal-section-title">Metadata</h3>
|
|
2306
2326
|
<div class="meta-grid">
|
|
2307
|
-
${Object.entries(r).map(([
|
|
2327
|
+
${Object.entries(r).map(([u,x])=>`
|
|
2308
2328
|
<div class="meta-cell">
|
|
2309
|
-
<span class="meta-label">${this._escapeHtml(
|
|
2329
|
+
<span class="meta-label">${this._escapeHtml(u.replace(/_/g," "))}</span>
|
|
2310
2330
|
<span class="meta-value">${this._escapeHtml(String(x))}</span>
|
|
2311
2331
|
</div>
|
|
2312
2332
|
`).join("")}
|
|
@@ -2332,9 +2352,9 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2332
2352
|
<div class="modal-section">
|
|
2333
2353
|
<h3 class="modal-section-title">Acceptance Criteria</h3>
|
|
2334
2354
|
<ul class="criteria-checklist" role="list">
|
|
2335
|
-
${o.map(
|
|
2336
|
-
<span class="criteria-checkbox ${
|
|
2337
|
-
<span class="criteria-text ${
|
|
2355
|
+
${o.map(u=>{let x=u&&typeof u=="object",k=x?u.text||u.title||"":u,_=x?!!u.done:!1;return`<li class="criteria-item">
|
|
2356
|
+
<span class="criteria-checkbox ${_?"checked":""}" aria-hidden="true">${_?"✓":""}</span>
|
|
2357
|
+
<span class="criteria-text ${_?"done":""}">${this._escapeHtml(String(k))}</span>
|
|
2338
2358
|
</li>`}).join("")}
|
|
2339
2359
|
</ul>
|
|
2340
2360
|
</div>
|
|
@@ -2344,12 +2364,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2344
2364
|
<div class="modal-section">
|
|
2345
2365
|
<h3 class="modal-section-title">Notes</h3>
|
|
2346
2366
|
<ul class="notes-timeline" role="list">
|
|
2347
|
-
${p.map(
|
|
2367
|
+
${p.map(u=>{let x=this._formatTimestamp(u&&u.timestamp),k=u&&u.author?this._escapeHtml(String(u.author)):"unknown",_=u&&u.body?this._escapeHtml(String(u.body)):"";return`<li class="note-entry">
|
|
2348
2368
|
<div class="note-meta">
|
|
2349
2369
|
<span class="note-author">${k}</span>
|
|
2350
2370
|
${x?`<span class="note-time">${x}</span>`:""}
|
|
2351
2371
|
</div>
|
|
2352
|
-
<div class="note-body">${
|
|
2372
|
+
<div class="note-body">${_}</div>
|
|
2353
2373
|
</li>`}).join("")}
|
|
2354
2374
|
</ul>
|
|
2355
2375
|
</div>
|
|
@@ -2360,11 +2380,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2360
2380
|
<h3 class="modal-section-title">Logs</h3>
|
|
2361
2381
|
<div class="logs-scroll">
|
|
2362
2382
|
<ul class="logs-timeline" role="list">
|
|
2363
|
-
${h.map(
|
|
2383
|
+
${h.map(u=>{let x=this._formatTimestamp(u&&u.timestamp),k=u&&u.iteration!==void 0&&u.iteration!==null?`i${this._escapeHtml(String(u.iteration))}`:"",_=u&&u.phase?String(u.phase):"",R=this._phaseClass(_),J=this._logLevelClass(u&&u.level),G=u&&u.message?this._escapeHtml(String(u.message)):"";return`<li class="log-entry ${J}">
|
|
2364
2384
|
${x?`<span class="log-time">${x}</span>`:""}
|
|
2365
2385
|
${k?`<span class="log-iter">${k}</span>`:""}
|
|
2366
|
-
${
|
|
2367
|
-
<span class="log-message">${
|
|
2386
|
+
${_?`<span class="log-phase ${R}">${this._escapeHtml(_)}</span>`:""}
|
|
2387
|
+
<span class="log-message">${G}</span>
|
|
2368
2388
|
</li>`}).join("")}
|
|
2369
2389
|
</ul>
|
|
2370
2390
|
</div>
|
|
@@ -2375,15 +2395,15 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2375
2395
|
<div class="modal-section">
|
|
2376
2396
|
<h3 class="modal-section-title">Context Files</h3>
|
|
2377
2397
|
<ul class="context-files-list">
|
|
2378
|
-
${n.map(
|
|
2398
|
+
${n.map(u=>`<li class="mono">${this._escapeHtml(u)}</li>`).join("")}
|
|
2379
2399
|
</ul>
|
|
2380
2400
|
</div>
|
|
2381
2401
|
`:""}
|
|
2382
2402
|
|
|
2383
|
-
${
|
|
2403
|
+
${v&&!l?`
|
|
2384
2404
|
<div class="modal-section">
|
|
2385
2405
|
<h3 class="modal-section-title">Full Content</h3>
|
|
2386
|
-
<pre class="modal-pre">${this._escapeHtml(
|
|
2406
|
+
<pre class="modal-pre">${this._escapeHtml(v)}</pre>
|
|
2387
2407
|
</div>
|
|
2388
2408
|
`:""}
|
|
2389
2409
|
|
|
@@ -2885,7 +2905,13 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
2885
2905
|
color: var(--loki-text-muted);
|
|
2886
2906
|
}
|
|
2887
2907
|
|
|
2888
|
-
/*
|
|
2908
|
+
/* Shared markdown styles first, so the shared renderer's full class set
|
|
2909
|
+
(.md-quote, .md-hr, .md-link, .md-h5/h6, strong) is themed. The
|
|
2910
|
+
task-board overrides below have equal specificity and come after, so
|
|
2911
|
+
they still win on the classes they target (compact fonts/margins). */
|
|
2912
|
+
${L}
|
|
2913
|
+
|
|
2914
|
+
/* Markdown body inside Description section (compact overrides) */
|
|
2889
2915
|
.md-body .md-h2 { font-size: 14px; margin: 8px 0 4px; color: var(--loki-text-primary); }
|
|
2890
2916
|
.md-body .md-h3 { font-size: 13px; margin: 8px 0 4px; color: var(--loki-text-primary); }
|
|
2891
2917
|
.md-body .md-h4 { font-size: 12px; margin: 6px 0 2px; color: var(--loki-text-primary); }
|
|
@@ -3403,7 +3429,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
3403
3429
|
`:""}
|
|
3404
3430
|
|
|
3405
3431
|
<div class="kanban-board">
|
|
3406
|
-
${
|
|
3432
|
+
${At.map(a=>{let s=this._getTasksByStatus(a.status),r=this._getVisibleCount(a.status),o=s.slice(0,r),n=s.length-o.length;return`
|
|
3407
3433
|
<div class="kanban-column" data-status="${a.status}">
|
|
3408
3434
|
<div class="kanban-column-header">
|
|
3409
3435
|
<span class="kanban-column-title">
|
|
@@ -3467,7 +3493,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
3467
3493
|
</div>
|
|
3468
3494
|
`}).join("")}
|
|
3469
3495
|
</div>
|
|
3470
|
-
`}}_attachEventListeners(){let e=this.shadowRoot.getElementById("refresh-btn");e&&e.addEventListener("click",()=>this._loadTasks());let t=this.shadowRoot.getElementById("bulk-toggle-btn");t&&t.addEventListener("click",()=>this._toggleBulkMode()),this.shadowRoot.querySelectorAll(".filter-pill").forEach(r=>{r.addEventListener("click",()=>this._setFilter(r.dataset.filter))});let i=this.shadowRoot.getElementById("task-search");i&&i.addEventListener("input",r=>this._setSearch(r.target.value)),this.shadowRoot.querySelectorAll(".show-more-btn").forEach(r=>{r.addEventListener("click",()=>this._showMore(r.dataset.showMore))}),this.shadowRoot.querySelectorAll(".bulk-btn").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.bulkAction;o==="delete"?this._bulkDelete():this._bulkMove(o)})}),this.shadowRoot.querySelectorAll(".add-task-btn").forEach(r=>{r.addEventListener("click",()=>{this._openAddTaskModal(r.dataset.status)})}),this.shadowRoot.querySelectorAll(".task-checkbox").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation(),this._toggleTaskSelection(r.dataset.checkId,o)})}),this.shadowRoot.querySelectorAll(".expand-toggle").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation(),this._toggleCardExpand(r.dataset.expandId)})}),this.shadowRoot.querySelectorAll(".task-card").forEach(r=>{let o=r.dataset.taskId,n=this._tasks.find(l=>l.id.toString()===o);n&&(r.addEventListener("click",l=>{if(this._bulkMode){this._toggleTaskSelection(o,l);return}this._openTaskDetail(n)}),r.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._bulkMode?this._toggleTaskSelection(o,l):this._openTaskDetail(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateTaskCards(r,l.key==="ArrowDown"?"next":"prev"))}),r.classList.contains("draggable")&&(r.addEventListener("dragstart",l=>this._handleDragStart(l,n)),r.addEventListener("dragend",l=>this._handleDragEnd(l))))}),this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(r=>{r.addEventListener("dragover",o=>this._handleDragOver(o)),r.addEventListener("dragenter",o=>this._handleDragEnter(o)),r.addEventListener("dragleave",o=>this._handleDragLeave(o)),r.addEventListener("drop",o=>this._handleDrop(o,r.dataset.status))});let a=this.shadowRoot.getElementById("modal-close-btn");a&&a.addEventListener("click",()=>this._closeTaskDetail());let s=this.shadowRoot.getElementById("task-detail-overlay");s&&s.addEventListener("click",r=>{r.target===s&&this._closeTaskDetail()})}_escapeHtml(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}_navigateTaskCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".task-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-task-board")||customElements.define("loki-task-board",
|
|
3496
|
+
`}}_attachEventListeners(){let e=this.shadowRoot.getElementById("refresh-btn");e&&e.addEventListener("click",()=>this._loadTasks());let t=this.shadowRoot.getElementById("bulk-toggle-btn");t&&t.addEventListener("click",()=>this._toggleBulkMode()),this.shadowRoot.querySelectorAll(".filter-pill").forEach(r=>{r.addEventListener("click",()=>this._setFilter(r.dataset.filter))});let i=this.shadowRoot.getElementById("task-search");i&&i.addEventListener("input",r=>this._setSearch(r.target.value)),this.shadowRoot.querySelectorAll(".show-more-btn").forEach(r=>{r.addEventListener("click",()=>this._showMore(r.dataset.showMore))}),this.shadowRoot.querySelectorAll(".bulk-btn").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.bulkAction;o==="delete"?this._bulkDelete():this._bulkMove(o)})}),this.shadowRoot.querySelectorAll(".add-task-btn").forEach(r=>{r.addEventListener("click",()=>{this._openAddTaskModal(r.dataset.status)})}),this.shadowRoot.querySelectorAll(".task-checkbox").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation(),this._toggleTaskSelection(r.dataset.checkId,o)})}),this.shadowRoot.querySelectorAll(".expand-toggle").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation(),this._toggleCardExpand(r.dataset.expandId)})}),this.shadowRoot.querySelectorAll(".task-card").forEach(r=>{let o=r.dataset.taskId,n=this._tasks.find(l=>l.id.toString()===o);n&&(r.addEventListener("click",l=>{if(this._bulkMode){this._toggleTaskSelection(o,l);return}this._openTaskDetail(n)}),r.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._bulkMode?this._toggleTaskSelection(o,l):this._openTaskDetail(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateTaskCards(r,l.key==="ArrowDown"?"next":"prev"))}),r.classList.contains("draggable")&&(r.addEventListener("dragstart",l=>this._handleDragStart(l,n)),r.addEventListener("dragend",l=>this._handleDragEnd(l))))}),this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(r=>{r.addEventListener("dragover",o=>this._handleDragOver(o)),r.addEventListener("dragenter",o=>this._handleDragEnter(o)),r.addEventListener("dragleave",o=>this._handleDragLeave(o)),r.addEventListener("drop",o=>this._handleDrop(o,r.dataset.status))});let a=this.shadowRoot.getElementById("modal-close-btn");a&&a.addEventListener("click",()=>this._closeTaskDetail());let s=this.shadowRoot.getElementById("task-detail-overlay");s&&s.addEventListener("click",r=>{r.target===s&&this._closeTaskDetail()})}_escapeHtml(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}_navigateTaskCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".task-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-task-board")||customElements.define("loki-task-board",Q);var X=class extends g{static get observedAttributes(){return["api-url","theme","compact"]}constructor(){super(),this._status={mode:"offline",phase:null,iteration:null,complexity:null,connected:!1,version:null,uptime:0,activeAgents:0,pendingTasks:0},this._model={override:null,default:"sonnet",effective:"sonnet",notice:""},this._modelBusy=!1,this._startBusy=!1,this._startNotice="",this._specText="",this._api=null,this._state=U(),this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._loadModel(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(f.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(f.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(f.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),e==="theme"&&this._applyTheme(),e==="compact"&&this.render())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e}),this._statusUpdateHandler=t=>this._updateFromStatus(t.detail),this._connectedHandler=()=>{this._status.connected=!0,this.render()},this._disconnectedHandler=()=>{this._status.connected=!1,this._status.mode="offline",this.render()},this._api.addEventListener(f.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(f.CONNECTED,this._connectedHandler),this._api.addEventListener(f.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){try{let e=await this._api.getStatus();this._updateFromStatus(e)}catch{this._status.connected=!1,this._status.mode="offline",this.render()}}_updateFromStatus(e){e&&(this._status={...this._status,connected:!0,mode:e.status||"running",version:e.version,uptime:e.uptime_seconds||0,activeAgents:e.running_agents||0,pendingTasks:e.pending_tasks||0,phase:e.phase,iteration:e.iteration,complexity:e.complexity},this._state.updateSession({connected:!0,mode:this._status.mode,lastSync:new Date().toISOString()}),this.render())}_startPolling(){this._poll=b({loadFn:()=>this._loadStatus(),intervalMs:3e3,sectionId:null,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatUptime(e){if(!e||e<0)return"--";let t=Math.floor(e/3600),i=Math.floor(e%3600/60),a=Math.floor(e%60);return t>0?`${t}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_escapeHtml(e){let t=document.createElement("div");return t.textContent=String(e??""),t.innerHTML}_getStatusClass(){switch(this._status.mode){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_getStatusLabel(){switch(this._status.mode){case"running":case"autonomous":return"AUTONOMOUS";case"paused":return"PAUSED";case"stopped":return"STOPPED";case"error":return"ERROR";default:return"OFFLINE"}}async _triggerStart(){if(this._startBusy)return;let e=(this._specText||"").trim();if(!e){this._startNotice="Enter a spec or one-line brief to start a build.",this.render();return}if(!this._api||typeof this._api.startSession!="function"){this._startNotice="Start is not available on this server.",this.render();return}this._startBusy=!0,this._startNotice="Starting build...",this.render();try{let t=await this._api.startSession(e,{provider:this._status.provider||"claude"});if(t&&t.error)throw new Error(t.error);this._startBusy=!1,this._startNotice="",this._specText="",this._status.mode="running",this._status.connected=!0,this.render(),this._loadStatus(),this.dispatchEvent(new CustomEvent("session-start",{detail:{...this._status,pid:t&&t.pid,spec:t&&t.spec}}))}catch(t){console.error("Failed to start build:",t),this._startBusy=!1,this._startNotice=t&&t.message?`Could not start: ${t.message}`:"Could not start the build. Try again.",this.render()}}_onSpecInput(e){this._specText=e}async _triggerPause(){try{let e=await this._api.pauseSession();if(e&&e.error)throw new Error(e.error);this._status.mode="paused",this.render(),this.dispatchEvent(new CustomEvent("session-pause",{detail:this._status}))}catch(e){console.error("Failed to pause session:",e),this.render()}}async _triggerResume(){try{let e=await this._api.resumeSession();if(e&&e.error)throw new Error(e.error);this._status.mode="running",this.render(),this.dispatchEvent(new CustomEvent("session-resume",{detail:this._status}))}catch(e){console.error("Failed to resume session:",e),this.render()}}async _triggerStop(){try{let e=await this._api.stopSession();if(e&&e.error)throw new Error(e.error);this._status.mode="stopped",this.render(),this.dispatchEvent(new CustomEvent("session-stop",{detail:this._status}))}catch(e){console.error("Failed to stop session:",e),this.render()}}async _loadModel(){if(!(!this._api||typeof this._api.getSessionModel!="function"))try{let e=await this._api.getSessionModel();e&&!e.error&&(this._model={...this._model,override:e.override??null,default:e.default||"sonnet",effective:e.effective||e.default||"sonnet"},this.render())}catch{}}async _onModelChange(e){if(this._modelBusy)return;this._modelBusy=!0;let t=e===""?null:e;try{let i=await this._api.setSessionModel(t);if(i&&i.error)throw new Error(i.error);this._model.override=t,this._model.notice=t?`Switching to ${t}. Applies from the next iteration, for the current run only.`:"Override cleared. Reverts to the tier mapping from the next iteration.",this._modelBusy=!1,await this._loadModel()}catch(i){console.error("Failed to set session model:",i),this._model.notice="Could not change the model. Try again.",this._modelBusy=!1,this.render()}}_renderModelControl(){let e=this._model.override||"",i=[{value:"",label:`Default (tier: ${this._escapeHtml(this._model.default)})`},{value:"haiku",label:"Haiku (fastest, cheapest)"},{value:"sonnet",label:"Sonnet (balanced)"},{value:"opus",label:"Opus (top coding)"},{value:"fable",label:"Fable 5 (2x Opus cost: $10/$50 per MTok)"}].map(s=>{let r=s.value===e?" selected":"";return`<option value="${this._escapeHtml(s.value)}"${r}>${this._escapeHtml(s.label)}</option>`}).join(""),a=this._model.effective==="fable";return`
|
|
3471
3497
|
<div class="model-control">
|
|
3472
3498
|
<div class="model-row">
|
|
3473
3499
|
<label for="model-select">Model</label>
|
|
@@ -3495,7 +3521,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
3495
3521
|
</button>
|
|
3496
3522
|
${this._startNotice?`<div class="start-notice">${this._escapeHtml(this._startNotice)}</div>`:""}
|
|
3497
3523
|
</div>
|
|
3498
|
-
`}render(){let e=this.hasAttribute("compact"),t=this._getStatusClass(),i=this._getStatusLabel(),a=["running","autonomous"].includes(this._status.mode),s=this._status.mode==="paused",r=!a&&!s,o=`
|
|
3524
|
+
`}render(){if(this._modelInteracting){this._renderPending=!0;return}let e=this.hasAttribute("compact"),t=this._getStatusClass(),i=this._getStatusLabel(),a=["running","autonomous"].includes(this._status.mode),s=this._status.mode==="paused",r=!a&&!s,o=`
|
|
3499
3525
|
<style>
|
|
3500
3526
|
${this.getBaseStyles()}
|
|
3501
3527
|
|
|
@@ -3866,12 +3892,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
3866
3892
|
</div>
|
|
3867
3893
|
</div>
|
|
3868
3894
|
</div>
|
|
3869
|
-
`,c=this.shadowRoot.activeElement,p=c&&c.id==="spec-input",h=p?c.selectionStart:null,
|
|
3895
|
+
`,c=this.shadowRoot.activeElement,p=c&&c.id==="spec-input",h=p?c.selectionStart:null,v=p?c.selectionEnd:null;if(this.shadowRoot.innerHTML=`
|
|
3870
3896
|
${o}
|
|
3871
3897
|
${e?n:l}
|
|
3872
|
-
`,this._attachEventListeners(),p){let
|
|
3898
|
+
`,this._attachEventListeners(),p){let u=this.shadowRoot.getElementById("spec-input");if(u&&!u.disabled){u.focus();try{u.setSelectionRange(h,v)}catch{}}}}_attachEventListeners(){let e=this.shadowRoot.getElementById("pause-btn"),t=this.shadowRoot.getElementById("resume-btn"),i=this.shadowRoot.getElementById("stop-btn"),a=this.shadowRoot.getElementById("start-btn");e&&e.addEventListener("click",()=>this._triggerPause()),t&&t.addEventListener("click",()=>this._triggerResume()),i&&i.addEventListener("click",()=>this._triggerStop()),a&&a.addEventListener("click",()=>this._triggerStart());let s=this.shadowRoot.getElementById("model-select");if(s){let o=()=>{this._modelInteracting=!1,this._renderPending&&(this._renderPending=!1,this.render())};s.addEventListener("mousedown",()=>{this._modelInteracting=!0}),s.addEventListener("focus",()=>{this._modelInteracting=!0}),s.addEventListener("blur",o),s.addEventListener("change",n=>{this._modelInteracting=!1,this._renderPending=!1,this._onModelChange(n.target.value)})}let r=this.shadowRoot.getElementById("spec-input");r&&r.addEventListener("input",o=>this._onSpecInput(o.target.value))}};customElements.get("loki-session-control")||customElements.define("loki-session-control",X);var st={info:{color:"var(--loki-blue)",label:"INFO"},success:{color:"var(--loki-green)",label:"SUCCESS"},warning:{color:"var(--loki-yellow)",label:"WARN"},error:{color:"var(--loki-red)",label:"ERROR"},step:{color:"var(--loki-purple)",label:"STEP"},agent:{color:"var(--loki-accent)",label:"AGENT"},debug:{color:"var(--loki-text-muted)",label:"DEBUG"}},Z=class extends g{static get observedAttributes(){return["api-url","max-lines","auto-scroll","theme","log-file"]}constructor(){super(),this._logs=[],this._maxLines=500,this._autoScroll=!0,this._filter="",this._levelFilter="all",this._api=null,this._pollInterval=null,this._logMessageHandler=null,this._apiLastCount=0,this._apiLastSig=null,this._fileLastSize=0,this._fileLastSig=null}connectedCallback(){super.connectedCallback(),this._maxLines=parseInt(this.getAttribute("max-lines"))||500,this._autoScroll=this.hasAttribute("auto-scroll"),this._setupApi(),this._startLogPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopLogPolling(),this._api&&this._logMessageHandler&&this._api.removeEventListener(f.LOG_MESSAGE,this._logMessageHandler)}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i);break;case"max-lines":this._maxLines=parseInt(i)||500,this._trimLogs(),this.render();break;case"auto-scroll":this._autoScroll=this.hasAttribute("auto-scroll"),this.render();break;case"theme":this._applyTheme();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e}),this._logMessageHandler=t=>this._addLog(t.detail),this._api.addEventListener(f.LOG_MESSAGE,this._logMessageHandler)}_startLogPolling(){let e=this.getAttribute("log-file");e?this._pollLogFile(e):this._pollApiLogs()}async _pollApiLogs(){await this._apiLogPollTick(),this._poll=b({loadFn:()=>this._apiLogPollTick(),intervalMs:5e3,element:this,immediate:!1})}async _apiLogPollTick(){try{let e=await this._api.getLogs(200);if(!Array.isArray(e))return;let t=e.length?`${e.length}:${e[e.length-1]?.timestamp||""}:${e[e.length-1]?.message||""}`:"0";if(t===this._apiLastSig)return;if(this._apiLastSig=t,e.length>this._apiLastCount){let i=e.slice(this._apiLastCount);for(let a of i)a.message&&a.message.trim()&&this._addLog({message:a.message,level:a.level||"info",timestamp:a.timestamp||new Date().toLocaleTimeString()})}else e.length<this._apiLastCount&&(this._apiLastCount=0);this._apiLastCount=e.length}catch{}}async _pollLogFile(e){await this._fileLogPollTick(e),this._poll=b({loadFn:()=>this._fileLogPollTick(e),intervalMs:1e3,element:this,immediate:!1})}async _fileLogPollTick(e){try{let t=await fetch(`${e}?t=${Date.now()}`,{credentials:"include"});if(!t.ok)return;let i=await t.text(),a=`${i.length}`;if(a===this._fileLastSig)return;this._fileLastSig=a;let s=i.split(`
|
|
3873
3899
|
`);if(s.length>this._fileLastSize){let r=s.slice(this._fileLastSize);for(let o of r)o.trim()&&this._addLog(this._parseLine(o))}else s.length<this._fileLastSize&&(this._fileLastSize=0);this._fileLastSize=s.length}catch{}}_stopLogPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_parseLine(e){let t=e.match(/^\[([^\]]+)\]\s*\[([^\]]+)\]\s*(.+)$/);if(t)return{timestamp:t[1],level:t[2].toLowerCase(),message:t[3]};let i=e.match(/^(\d{2}:\d{2}:\d{2})\s+(\w+)\s+(.+)$/);return i?{timestamp:i[1],level:i[2].toLowerCase(),message:i[3]}:{timestamp:new Date().toLocaleTimeString(),level:"info",message:e}}_addLog(e){if(!e)return;let t={id:Date.now()+Math.random(),timestamp:e.timestamp||new Date().toLocaleTimeString(),level:(e.level||"info").toLowerCase(),message:e.message||e};this._logs.push(t),this._trimLogs(),this.dispatchEvent(new CustomEvent("log-received",{detail:t})),this._renderLogs(),this._autoScroll&&this._scrollToBottom()}_trimLogs(){this._logs.length>this._maxLines&&(this._logs=this._logs.slice(-this._maxLines))}_clearLogs(){this._logs=[],this.dispatchEvent(new CustomEvent("logs-cleared")),this._renderLogs()}_toggleAutoScroll(){this._autoScroll=!this._autoScroll,this.render(),this._autoScroll&&this._scrollToBottom()}_scrollToBottom(){requestAnimationFrame(()=>{let e=this.shadowRoot.getElementById("log-output");e&&(e.scrollTop=e.scrollHeight)})}_downloadLogs(){let e=this._logs.map(s=>`[${s.timestamp}] [${s.level.toUpperCase()}] ${s.message}`).join(`
|
|
3874
|
-
`),t=new Blob([e],{type:"text/plain"}),i=URL.createObjectURL(t),a=document.createElement("a");a.href=i,a.download=`loki-logs-${new Date().toISOString().split("T")[0]}.txt`,a.click(),URL.revokeObjectURL(i)}_setFilter(e){this._filter=e.toLowerCase(),this._renderLogs()}_setLevelFilter(e){this._levelFilter=e,this._renderLogs()}_getFilteredLogs(){return this._logs.filter(e=>!(this._levelFilter!=="all"&&e.level!==this._levelFilter||this._filter&&!e.message.toLowerCase().includes(this._filter)))}_renderLogs(){let e=this.shadowRoot.getElementById("log-output");if(!e)return;let t=this._getFilteredLogs();if(t.length===0){e.innerHTML='<div class="log-empty">No log output yet. Terminal will update when Loki Mode is running.</div>';return}e.innerHTML=t.map(i=>{let a=
|
|
3900
|
+
`),t=new Blob([e],{type:"text/plain"}),i=URL.createObjectURL(t),a=document.createElement("a");a.href=i,a.download=`loki-logs-${new Date().toISOString().split("T")[0]}.txt`,a.click(),URL.revokeObjectURL(i)}_setFilter(e){this._filter=e.toLowerCase(),this._renderLogs()}_setLevelFilter(e){this._levelFilter=e,this._renderLogs()}_getFilteredLogs(){return this._logs.filter(e=>!(this._levelFilter!=="all"&&e.level!==this._levelFilter||this._filter&&!e.message.toLowerCase().includes(this._filter)))}_renderLogs(){let e=this.shadowRoot.getElementById("log-output");if(!e)return;let t=this._getFilteredLogs();if(t.length===0){e.innerHTML='<div class="log-empty">No log output yet. Terminal will update when Loki Mode is running.</div>';return}e.innerHTML=t.map(i=>{let a=st[i.level]||st.info;return`
|
|
3875
3901
|
<div class="log-line">
|
|
3876
3902
|
<span class="timestamp">${this._escapeHtml(i.timestamp)}</span>
|
|
3877
3903
|
<span class="level" style="color: ${a.color}">[${this._escapeHtml(a.label)}]</span>
|
|
@@ -4070,7 +4096,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4070
4096
|
${this._logs.length} lines (${this._getFilteredLogs().length} shown)
|
|
4071
4097
|
</div>
|
|
4072
4098
|
</div>
|
|
4073
|
-
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let e=this.shadowRoot.getElementById("filter-input"),t=this.shadowRoot.getElementById("level-select"),i=this.shadowRoot.getElementById("auto-scroll-btn"),a=this.shadowRoot.getElementById("clear-btn"),s=this.shadowRoot.getElementById("download-btn");e&&(e.value=this._filter,e.addEventListener("input",r=>this._setFilter(r.target.value))),t&&(t.value=this._levelFilter,t.addEventListener("change",r=>this._setLevelFilter(r.target.value))),i&&i.addEventListener("click",()=>this._toggleAutoScroll()),a&&a.addEventListener("click",()=>this._clearLogs()),s&&s.addEventListener("click",()=>this._downloadLogs())}addLog(e,t="info"){this._addLog({message:e,level:t,timestamp:new Date().toLocaleTimeString()})}clear(){this._clearLogs()}};customElements.get("loki-log-stream")||customElements.define("loki-log-stream",
|
|
4099
|
+
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let e=this.shadowRoot.getElementById("filter-input"),t=this.shadowRoot.getElementById("level-select"),i=this.shadowRoot.getElementById("auto-scroll-btn"),a=this.shadowRoot.getElementById("clear-btn"),s=this.shadowRoot.getElementById("download-btn");e&&(e.value=this._filter,e.addEventListener("input",r=>this._setFilter(r.target.value))),t&&(t.value=this._levelFilter,t.addEventListener("change",r=>this._setLevelFilter(r.target.value))),i&&i.addEventListener("click",()=>this._toggleAutoScroll()),a&&a.addEventListener("click",()=>this._clearLogs()),s&&s.addEventListener("click",()=>this._downloadLogs())}addLog(e,t="info"){this._addLog({message:e,level:t,timestamp:new Date().toLocaleTimeString()})}clear(){this._clearLogs()}};customElements.get("loki-log-stream")||customElements.define("loki-log-stream",Z);var Tt=[{id:"summary",label:"Summary",icon:"M4 6h16M4 12h16M4 18h16"},{id:"search",label:"Search",icon:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"},{id:"episodes",label:"Episodes",icon:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"},{id:"patterns",label:"Patterns",icon:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"},{id:"skills",label:"Skills",icon:"M13 10V3L4 14h7v7l9-11h-7z"}],ee=class extends g{static get observedAttributes(){return["api-url","theme","tab"]}constructor(){super(),this._activeTab="summary",this._loading=!1,this._error=null,this._api=null,this._summary=null,this._stats=null,this._episodes=[],this._patterns=[],this._skills=[],this._tokenEconomics=null,this._selectedItem=null,this._lastFocusedElement=null,this._searchQuery="",this._searchCollection="all",this._searchResults=[],this._searchLoading=!1,this._searchError=null}connectedCallback(){super.connectedCallback(),this._activeTab=this.getAttribute("tab")||"summary",this._setupApi(),this._loadData()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadData());break;case"theme":this._applyTheme();break;case"tab":this._setTab(i);break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let[e,t,i]=await Promise.allSettled([this._api.getMemorySummary(),this._api.getTokenEconomics(),this._api.getMemoryStats()]);this._summary=e.status==="fulfilled"?e.value:null,this._tokenEconomics=t.status==="fulfilled"?t.value:null,this._stats=i.status==="fulfilled"?i.value:null,await this._loadTabData()}catch(e){this._error=e.message||"Failed to load memory data"}this._loading=!1,this.render()}async _loadTabData(){switch(this._activeTab){case"episodes":this._episodes=await this._api.listEpisodes({limit:50}).catch(()=>[]);break;case"patterns":this._patterns=await this._api.listPatterns().catch(()=>[]);break;case"skills":this._skills=await this._api.listSkills().catch(()=>[]);break}}_setTab(e){this._activeTab!==e&&(this._activeTab=e,this._selectedItem=null,this._loadTabData().then(()=>this.render()))}async _selectEpisode(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getEpisode(e),this.dispatchEvent(new CustomEvent("episode-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load episode:",t)}}async _selectPattern(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getPattern(e),this.dispatchEvent(new CustomEvent("pattern-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load pattern:",t)}}async _selectSkill(e){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getSkill(e),this.dispatchEvent(new CustomEvent("skill-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(t){console.error("Failed to load skill:",t)}}_focusDetailPanel(){requestAnimationFrame(()=>{let e=this.shadowRoot.getElementById("close-detail");e&&e.focus()})}_closeDetail(){this._selectedItem=null,this.render(),this._lastFocusedElement&&requestAnimationFrame(()=>{this._lastFocusedElement.focus(),this._lastFocusedElement=null})}async _triggerConsolidation(){try{let e=await this._api.consolidateMemory(24);alert(`Consolidation complete:
|
|
4074
4100
|
- Patterns created: ${e.patternsCreated}
|
|
4075
4101
|
- Patterns merged: ${e.patternsMerged}
|
|
4076
4102
|
- Episodes processed: ${e.episodesProcessed}`),this._loadData()}catch(e){alert("Consolidation failed: "+e.message)}}async _executeSearch(){let e=this._searchQuery.trim();if(e){this._searchLoading=!0,this._searchError=null,this.render();try{let t=await this._api.searchMemory(e,this._searchCollection,20);this._searchResults=t.results||[]}catch(t){this._searchError=t.message||"Search failed",this._searchResults=[]}this._searchLoading=!1,this.render(),requestAnimationFrame(()=>{let t=this.shadowRoot.getElementById("memory-search-input");t&&t.focus()})}}_renderSearch(){let e=["all","episodes","patterns","skills"];return`
|
|
@@ -4941,7 +4967,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4941
4967
|
<span class="browser-title">Memory System</span>
|
|
4942
4968
|
</div>
|
|
4943
4969
|
<div class="tabs" role="tablist" aria-label="Memory browser sections">
|
|
4944
|
-
${
|
|
4970
|
+
${Tt.map((i,a)=>`
|
|
4945
4971
|
<button class="tab ${this._activeTab===i.id?"active":""}"
|
|
4946
4972
|
data-tab="${i.id}"
|
|
4947
4973
|
role="tab"
|
|
@@ -4958,12 +4984,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4958
4984
|
${t}
|
|
4959
4985
|
</div>
|
|
4960
4986
|
</div>
|
|
4961
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.querySelectorAll(".tab");e.forEach((n,l)=>{n.addEventListener("click",()=>this._setTab(n.dataset.tab)),n.addEventListener("keydown",c=>{if(c.key==="ArrowRight"||c.key==="ArrowLeft"){c.preventDefault();let p=Array.from(e),h=c.key==="ArrowRight"?(l+1)%p.length:(l-1+p.length)%p.length;p[h].focus(),this._setTab(p[h].dataset.tab)}})}),this.shadowRoot.querySelectorAll(".item-card").forEach(n=>{n.addEventListener("click",()=>this._handleItemClick(n)),n.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._handleItemClick(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateItemCards(n,l.key==="ArrowDown"?"next":"prev"))})});let t=this.shadowRoot.getElementById("close-detail");t&&t.addEventListener("click",()=>this._closeDetail());let i=this.shadowRoot.getElementById("consolidate-btn");i&&i.addEventListener("click",()=>this._triggerConsolidation());let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("memory-search-input"),r=this.shadowRoot.getElementById("search-btn"),o=this.shadowRoot.getElementById("memory-search-collection");s&&(s.addEventListener("keydown",n=>{n.key==="Enter"&&(n.preventDefault(),this._searchQuery=s.value,this._executeSearch())}),s.addEventListener("input",n=>{this._searchQuery=n.target.value})),r&&r.addEventListener("click",()=>{let n=this.shadowRoot.getElementById("memory-search-input");n&&(this._searchQuery=n.value),this._executeSearch()}),o&&o.addEventListener("change",n=>{this._searchCollection=n.target.value})}_handleItemClick(e){let t=e.dataset.id;switch(e.dataset.type){case"episode":this._selectEpisode(t);break;case"pattern":this._selectPattern(t);break;case"skill":this._selectSkill(t);break}}_navigateItemCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".item-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-memory-browser")||customElements.define("loki-memory-browser",
|
|
4987
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.querySelectorAll(".tab");e.forEach((n,l)=>{n.addEventListener("click",()=>this._setTab(n.dataset.tab)),n.addEventListener("keydown",c=>{if(c.key==="ArrowRight"||c.key==="ArrowLeft"){c.preventDefault();let p=Array.from(e),h=c.key==="ArrowRight"?(l+1)%p.length:(l-1+p.length)%p.length;p[h].focus(),this._setTab(p[h].dataset.tab)}})}),this.shadowRoot.querySelectorAll(".item-card").forEach(n=>{n.addEventListener("click",()=>this._handleItemClick(n)),n.addEventListener("keydown",l=>{l.key==="Enter"||l.key===" "?(l.preventDefault(),this._handleItemClick(n)):(l.key==="ArrowDown"||l.key==="ArrowUp")&&(l.preventDefault(),this._navigateItemCards(n,l.key==="ArrowDown"?"next":"prev"))})});let t=this.shadowRoot.getElementById("close-detail");t&&t.addEventListener("click",()=>this._closeDetail());let i=this.shadowRoot.getElementById("consolidate-btn");i&&i.addEventListener("click",()=>this._triggerConsolidation());let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("memory-search-input"),r=this.shadowRoot.getElementById("search-btn"),o=this.shadowRoot.getElementById("memory-search-collection");s&&(s.addEventListener("keydown",n=>{n.key==="Enter"&&(n.preventDefault(),this._searchQuery=s.value,this._executeSearch())}),s.addEventListener("input",n=>{this._searchQuery=n.target.value})),r&&r.addEventListener("click",()=>{let n=this.shadowRoot.getElementById("memory-search-input");n&&(this._searchQuery=n.value),this._executeSearch()}),o&&o.addEventListener("change",n=>{this._searchCollection=n.target.value})}_handleItemClick(e){let t=e.dataset.id;switch(e.dataset.type){case"episode":this._selectEpisode(t);break;case"pattern":this._selectPattern(t);break;case"skill":this._selectSkill(t);break}}_navigateItemCards(e,t){let i=Array.from(this.shadowRoot.querySelectorAll(".item-card")),a=i.indexOf(e);if(a===-1)return;let s=t==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-memory-browser")||customElements.define("loki-memory-browser",ee);var Lt=[{id:"1h",label:"1 Hour",hours:1},{id:"24h",label:"24 Hours",hours:24},{id:"7d",label:"7 Days",hours:168},{id:"30d",label:"30 Days",hours:720}],Dt=[{id:"all",label:"All Signals"},{id:"user_preference",label:"User Preferences"},{id:"error_pattern",label:"Error Patterns"},{id:"success_pattern",label:"Success Patterns"},{id:"tool_efficiency",label:"Tool Efficiency"},{id:"context_relevance",label:"Context Relevance"}],zt=[{id:"all",label:"All Sources"},{id:"cli",label:"CLI"},{id:"api",label:"API"},{id:"vscode",label:"VS Code"},{id:"mcp",label:"MCP"},{id:"dashboard",label:"Dashboard"}],te=class extends g{static get observedAttributes(){return["api-url","theme","time-range","signal-type","source"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._timeRange="7d",this._signalType="all",this._source="all",this._metrics=null,this._trends=null,this._signals=[],this._selectedMetric=null}connectedCallback(){super.connectedCallback(),this._timeRange=this.getAttribute("time-range")||"7d",this._signalType=this.getAttribute("signal-type")||"all",this._source=this.getAttribute("source")||"all",this._setupApi(),this._loadData()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadData());break;case"theme":this._applyTheme();break;case"time-range":this._timeRange=i,this._loadData();break;case"signal-type":this._signalType=i,this._loadData();break;case"source":this._source=i,this._loadData();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let e={timeRange:this._timeRange,signalType:this._signalType!=="all"?this._signalType:void 0,source:this._source!=="all"?this._source:void 0},[t,i,a]=await Promise.all([this._api.getLearningMetrics(e).catch(()=>null),this._api.getLearningTrends(e).catch(()=>null),this._api.getLearningSignals({...e,limit:50}).catch(()=>[])]);this._metrics=t,this._trends=i,this._signals=a||[]}catch(e){this._error=e.message||"Failed to load learning data"}this._loading=!1,this.render()}_setFilter(e,t){switch(e){case"timeRange":this._timeRange=t,this.setAttribute("time-range",t);break;case"signalType":this._signalType=t,this.setAttribute("signal-type",t);break;case"source":this._source=t,this.setAttribute("source",t);break}this.dispatchEvent(new CustomEvent("filter-change",{detail:{timeRange:this._timeRange,signalType:this._signalType,source:this._source}})),this._loadData()}_selectMetric(e,t){this._selectedMetric={type:e,item:t},this.dispatchEvent(new CustomEvent("metric-select",{detail:{type:e,item:t}})),this.render()}_closeDetail(){this._selectedMetric=null,this.render()}_formatNumber(e){return e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":e?.toString()||"0"}_formatPercent(e){return(e*100).toFixed(1)+"%"}_formatDuration(e){return e<60?e.toFixed(0)+"s":e<3600?(e/60).toFixed(1)+"m":(e/3600).toFixed(1)+"h"}_escapeHtml(e){if(!e)return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}_renderFilters(){return`
|
|
4962
4988
|
<div class="filters">
|
|
4963
4989
|
<div class="filter-group">
|
|
4964
4990
|
<label>Time Range</label>
|
|
4965
4991
|
<select id="time-range-select" class="filter-select">
|
|
4966
|
-
${
|
|
4992
|
+
${Lt.map(e=>`
|
|
4967
4993
|
<option value="${e.id}" ${this._timeRange===e.id?"selected":""}>${e.label}</option>
|
|
4968
4994
|
`).join("")}
|
|
4969
4995
|
</select>
|
|
@@ -4971,7 +4997,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4971
4997
|
<div class="filter-group">
|
|
4972
4998
|
<label>Signal Type</label>
|
|
4973
4999
|
<select id="signal-type-select" class="filter-select">
|
|
4974
|
-
${
|
|
5000
|
+
${Dt.map(e=>`
|
|
4975
5001
|
<option value="${e.id}" ${this._signalType===e.id?"selected":""}>${e.label}</option>
|
|
4976
5002
|
`).join("")}
|
|
4977
5003
|
</select>
|
|
@@ -4979,7 +5005,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
4979
5005
|
<div class="filter-group">
|
|
4980
5006
|
<label>Source</label>
|
|
4981
5007
|
<select id="source-select" class="filter-select">
|
|
4982
|
-
${
|
|
5008
|
+
${zt.map(e=>`
|
|
4983
5009
|
<option value="${e.id}" ${this._source===e.id?"selected":""}>${e.label}</option>
|
|
4984
5010
|
`).join("")}
|
|
4985
5011
|
</select>
|
|
@@ -5970,7 +5996,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
5970
5996
|
${t}
|
|
5971
5997
|
</div>
|
|
5972
5998
|
</div>
|
|
5973
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.getElementById("time-range-select");e&&e.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let t=this.shadowRoot.getElementById("signal-type-select");t&&t.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let i=this.shadowRoot.getElementById("source-select");i&&i.addEventListener("change",r=>this._setFilter("source",r.target.value));let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("close-detail");s&&s.addEventListener("click",()=>this._closeDetail()),this.shadowRoot.querySelectorAll(".list-item").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.type,n=r.dataset.id,l=this._findItemData(o,n);l&&this._selectMetric(o,l)}),r.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r.click())})})}_findItemData(e,t){if(!this._metrics?.aggregation)return null;switch(e){case"preference":return this._metrics.aggregation.preferences?.find(i=>i.preference_key===t);case"error_pattern":return this._metrics.aggregation.error_patterns?.find(i=>i.error_type===t);case"success_pattern":return this._metrics.aggregation.success_patterns?.find(i=>i.pattern_name===t);case"tool_efficiency":return this._metrics.aggregation.tool_efficiencies?.find(i=>i.tool_name===t);default:return null}}};customElements.get("loki-learning-dashboard")||customElements.define("loki-learning-dashboard",
|
|
5999
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot.getElementById("time-range-select");e&&e.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let t=this.shadowRoot.getElementById("signal-type-select");t&&t.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let i=this.shadowRoot.getElementById("source-select");i&&i.addEventListener("change",r=>this._setFilter("source",r.target.value));let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("close-detail");s&&s.addEventListener("click",()=>this._closeDetail()),this.shadowRoot.querySelectorAll(".list-item").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.type,n=r.dataset.id,l=this._findItemData(o,n);l&&this._selectMetric(o,l)}),r.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r.click())})})}_findItemData(e,t){if(!this._metrics?.aggregation)return null;switch(e){case"preference":return this._metrics.aggregation.preferences?.find(i=>i.preference_key===t);case"error_pattern":return this._metrics.aggregation.error_patterns?.find(i=>i.error_type===t);case"success_pattern":return this._metrics.aggregation.success_patterns?.find(i=>i.pattern_name===t);case"tool_efficiency":return this._metrics.aggregation.tool_efficiencies?.find(i=>i.tool_name===t);default:return null}}};customElements.get("loki-learning-dashboard")||customElements.define("loki-learning-dashboard",te);var Rt=[{id:"overview",label:"Overview"},{id:"decisions",label:"Decision Log"},{id:"convergence",label:"Convergence"},{id:"agents",label:"Agents"}],ie=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._activeTab="overview",this._pollInterval=null,this._councilState=null,this._verdicts=[],this._convergence=[],this._agents=[],this._selectedAgent=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null),this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null)}async _loadData(){try{let[t,i,a,s]=await Promise.allSettled([this._api._get("/api/council/state"),this._api._get("/api/council/verdicts"),this._api._get("/api/council/convergence"),this._api._get("/api/agents")]);t.status==="fulfilled"&&(this._councilState=t.value),i.status==="fulfilled"&&(this._verdicts=i.value.verdicts||[]),a.status==="fulfilled"&&(this._convergence=a.value.dataPoints||[]),s.status==="fulfilled"&&(this._agents=Array.isArray(s.value)?s.value:[]),this._error=null}catch(t){this._error=t.message}let e=JSON.stringify({s:this._councilState,v:this._verdicts,c:this._convergence,a:this._agents,e:this._error});e!==this._lastDataHash&&(this._lastDataHash=e,this.render())}async _forceReview(){try{await this._api._post("/api/council/force-review"),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"force-review"},bubbles:!0}))}catch(e){this._error=`Failed to force review: ${e.message}`,this.render()}}async _killAgent(e){if(confirm(`Kill agent ${e}?`))try{await this._api._post(`/api/agents/${e}/kill`),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"kill-agent",agentId:e},bubbles:!0})),await this._loadData()}catch(t){this._error=`Failed to kill agent: ${t.message}`,this.render()}}async _pauseAgent(e){try{await this._api._post(`/api/agents/${e}/pause`),await this._loadData()}catch(t){this._error=`Failed to pause agent: ${t.message}`,this.render()}}async _resumeAgent(e){try{await this._api._post(`/api/agents/${e}/resume`),await this._loadData()}catch(t){this._error=`Failed to resume agent: ${t.message}`,this.render()}}_setTab(e){this._activeTab=e,this.render()}_selectAgent(e){this._selectedAgent=this._selectedAgent?.id===e.id?null:e,this.render()}render(){let e=this.shadowRoot;e&&(this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null),e.innerHTML=`
|
|
5974
6000
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
5975
6001
|
<div class="council-dashboard">
|
|
5976
6002
|
<div class="council-header">
|
|
@@ -5984,7 +6010,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
5984
6010
|
</div>
|
|
5985
6011
|
|
|
5986
6012
|
<div class="tabs">
|
|
5987
|
-
${
|
|
6013
|
+
${Rt.map(t=>`
|
|
5988
6014
|
<button
|
|
5989
6015
|
class="tab ${this._activeTab===t.id?"active":""}"
|
|
5990
6016
|
data-tab="${t.id}"
|
|
@@ -6557,7 +6583,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
6557
6583
|
color: var(--loki-error);
|
|
6558
6584
|
font-size: 12px;
|
|
6559
6585
|
}
|
|
6560
|
-
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",
|
|
6586
|
+
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",ie);var rt={critical:0,major:1,minor:2},Ht={critical:"var(--loki-status-error, #ef4444)",major:"var(--loki-status-warning, #f59e0b)",minor:"var(--loki-text-muted, #71717a)"},ae=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._checklist=null,this._waivers=[],this._expandedCategories=new Set,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let[e,t]=await Promise.all([this._api.getChecklist(),this._api.getChecklistWaivers().catch(()=>null)]),i=JSON.stringify(t),a=JSON.stringify(e)+i;if(a===this._lastDataHash)return;this._lastDataHash=a,this._checklist=e,this._waivers=t&&t.waivers?t.waivers.filter(s=>s.active):[],this._error=null,this.render()}catch(e){this._error=`Failed to load checklist: ${e.message}`,this.render()}}_isItemWaived(e){return this._waivers.some(t=>t.item_id===e)}_getWaiverForItem(e){return this._waivers.find(t=>t.item_id===e)||null}async _waiveItem(e){let t=window.prompt("Enter reason for waiving this item:");if(t)try{await this._api.addChecklistWaiver(e,t),this._lastDataHash=null,await this._loadData()}catch(i){this._error=`Failed to add waiver: ${i.message}`,this.render()}}async _unwaiveItem(e){try{await this._api.removeChecklistWaiver(e),this._lastDataHash=null,await this._loadData()}catch(t){this._error=`Failed to remove waiver: ${t.message}`,this.render()}}_toggleCategory(e){this._expandedCategories.has(e)?this._expandedCategories.delete(e):this._expandedCategories.add(e),this.render()}_getStyles(){return`
|
|
6561
6587
|
.checklist-viewer {
|
|
6562
6588
|
padding: 16px;
|
|
6563
6589
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -6846,7 +6872,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
6846
6872
|
</div>
|
|
6847
6873
|
${i?`<div class="category-body">${this._renderItems(a)}</div>`:""}
|
|
6848
6874
|
</div>
|
|
6849
|
-
`}).join(""):this._renderEmpty()}_renderItems(e){return e?.length?[...e].sort((i,a)=>(
|
|
6875
|
+
`}).join(""):this._renderEmpty()}_renderItems(e){return e?.length?[...e].sort((i,a)=>(rt[i.priority]??2)-(rt[a.priority]??2)).map(i=>{let a=i.status==="verified"?"status-verified":i.status==="failing"?"status-failing":"status-pending",s=["critical","major","minor"].includes(i.priority)?i.priority:"minor",r=Ht[s],o=i.verification||[],n=this._getWaiverForItem(i.id),l=!!n,c=i.status==="failing"&&(s==="critical"||s==="major"),p=l?`<span class="item-waived-badge" title="${this._escapeHtml(n.reason||"No reason provided")}">WAIVED</span>`:"",h="";return c&&(l?h=`<button class="waiver-btn waiver-btn-unwaive" data-unwaive-id="${this._escapeHtml(i.id)}">Unwaive</button>`:h=`<button class="waiver-btn" data-waive-id="${this._escapeHtml(i.id)}">Waive</button>`),`
|
|
6850
6876
|
<div class="item">
|
|
6851
6877
|
<div class="item-status ${a}"></div>
|
|
6852
6878
|
<div class="item-title">${this._escapeHtml(i.title||i.id||"?")}</div>
|
|
@@ -6854,7 +6880,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
6854
6880
|
${p}
|
|
6855
6881
|
${h}
|
|
6856
6882
|
<div class="verification-dots">
|
|
6857
|
-
${o.map(
|
|
6883
|
+
${o.map(v=>`<div class="v-dot ${v.passed===!0?"v-dot-pass":v.passed===!1?"v-dot-fail":"v-dot-pending"}" title="${this._escapeHtml(v.type||"")}"></div>`).join("")}
|
|
6858
6884
|
</div>
|
|
6859
6885
|
</div>
|
|
6860
6886
|
`}).join(""):'<div class="item" style="color:var(--loki-text-muted)">No items</div>'}_renderEmpty(){return`
|
|
@@ -6862,7 +6888,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
6862
6888
|
<p><strong>No checklist data yet.</strong></p>
|
|
6863
6889
|
<p class="hint">The spec checklist is generated during the first iteration. Start a session with <code>loki start ./spec.md</code> (PRD files also accepted) -- groups and items will appear here as the session progresses and can be expanded for details.</p>
|
|
6864
6890
|
</div>
|
|
6865
|
-
`}_attachEventListeners(){let e=this.shadowRoot;e&&(e.querySelectorAll(".category-header[data-category]").forEach(t=>{t.addEventListener("click",()=>this._toggleCategory(t.dataset.category))}),e.querySelectorAll("button[data-waive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(t.dataset.waiveId)})}),e.querySelectorAll("button[data-unwaive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(t.dataset.unwaiveId)})}))}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",
|
|
6891
|
+
`}_attachEventListeners(){let e=this.shadowRoot;e&&(e.querySelectorAll(".category-header[data-category]").forEach(t=>{t.addEventListener("click",()=>this._toggleCategory(t.dataset.category))}),e.querySelectorAll("button[data-waive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(t.dataset.waiveId)})}),e.querySelectorAll("button[data-unwaive-id]").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(t.dataset.unwaiveId)})}))}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",ae);var ot={not_initialized:{color:"var(--loki-text-muted, #71717a)",label:"Not Started",pulse:!1},starting:{color:"var(--loki-yellow, #ca8a04)",label:"Starting...",pulse:!0},running:{color:"var(--loki-green, #16a34a)",label:"Running",pulse:!0},stale:{color:"var(--loki-yellow, #ca8a04)",label:"Stale",pulse:!1},completed:{color:"var(--loki-text-muted, #a1a1aa)",label:"Completed",pulse:!1},failed:{color:"var(--loki-red, #dc2626)",label:"Failed",pulse:!1},crashed:{color:"var(--loki-red, #dc2626)",label:"Crashed",pulse:!1},stopped:{color:"var(--loki-text-muted, #a1a1aa)",label:"Stopped",pulse:!1},unknown:{color:"var(--loki-text-muted, #71717a)",label:"Unknown",pulse:!1}},se=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._status=null,this._logs=[],this._lastDataHash=null,this._lastLogsHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let[e,t]=await Promise.all([this._api.getAppRunnerStatus(),this._api.getAppRunnerLogs()]),i=JSON.stringify({status:e?.status,port:e?.port,restarts:e?.restart_count,url:e?.url,services:Array.isArray(e?.services)?e.services.map(r=>`${r?.url||""}|${r?.name||""}`).join(","):null}),a=JSON.stringify(t?.lines?.slice(-5)||[]),s=a!==this._lastLogsHash;if(i===this._lastDataHash&&!s)return;this._lastDataHash=i,this._lastLogsHash=a,this._status=e,this._logs=t?.lines||[],this._error=null,this.render(),this._scrollLogsToBottom()}catch(e){this._error||(this._error=`Failed to load app status: ${e.message}`,this.render())}}_scrollLogsToBottom(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(".log-area");t&&(t.scrollTop=t.scrollHeight)}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(e){this._error=`Restart failed: ${e.message}`,this.render()}}async _handleStop(){try{await this._api.stopApp(),this._loadData()}catch(e){this._error=`Stop failed: ${e.message}`,this.render()}}_formatUptime(e){if(!e)return"--";let t=new Date(e),a=Math.floor((new Date-t)/1e3);if(a<60)return`${a}s`;if(a<3600)return`${Math.floor(a/60)}m ${a%60}s`;let s=Math.floor(a/3600),r=Math.floor(a%3600/60);return`${s}h ${r}m`}_isValidUrl(e){if(!e)return!1;try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}_extraServices(e){if(!e||!Array.isArray(e.services))return[];let t=e.url||"",i=[],a=new Set;for(let s of e.services){if(!s||typeof s.url!="string"||!s.url||s.url===t||a.has(s.url))continue;a.add(s.url);let r=typeof s.name=="string"?s.name.trim():"",o=typeof s.role=="string"?s.role.trim():"",n=s.port!=null?String(s.port):"",l=r||o||(n?`Port ${n}`:"Service");i.push({url:s.url,label:l,urlValid:this._isValidUrl(s.url)})}return i}_getStyles(){return`
|
|
6866
6892
|
.app-status {
|
|
6867
6893
|
padding: 16px;
|
|
6868
6894
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -7038,7 +7064,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7038
7064
|
${i?"":this._renderEmpty()}
|
|
7039
7065
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
7040
7066
|
</div>
|
|
7041
|
-
`,this._attachEventListeners()}_renderStatusBadge(e){let t=e?.status||"not_initialized",i=
|
|
7067
|
+
`,this._attachEventListeners()}_renderStatusBadge(e){let t=e?.status||"not_initialized",i=ot[t]||ot.not_initialized;return`
|
|
7042
7068
|
<span class="status-badge" style="background: color-mix(in srgb, ${i.color} 15%, transparent); color: ${i.color}">
|
|
7043
7069
|
<span class="status-dot ${i.pulse?"pulse":""}" style="background: ${i.color}"></span>
|
|
7044
7070
|
${this._escapeHtml(i.label)}
|
|
@@ -7094,7 +7120,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7094
7120
|
<p>App not running yet</p>
|
|
7095
7121
|
<p class="hint">Your app will start automatically after the first successful build step.</p>
|
|
7096
7122
|
</div>
|
|
7097
|
-
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector('[data-action="restart"]'),i=e.querySelector('[data-action="stop"]');t&&t.addEventListener("click",()=>this._handleRestart()),i&&i.addEventListener("click",()=>this._handleStop())}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-app-status",
|
|
7123
|
+
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector('[data-action="restart"]'),i=e.querySelector('[data-action="stop"]');t&&t.addEventListener("click",()=>this._handleRestart()),i&&i.addEventListener("click",()=>this._handleStop())}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-app-status",se);var nt={not_initialized:{color:"var(--loki-text-muted, #71717a)",label:"No app yet",pulse:!1},starting:{color:"var(--loki-yellow, #ca8a04)",label:"Starting",pulse:!0},running:{color:"var(--loki-green, #16a34a)",label:"Running",pulse:!0},stale:{color:"var(--loki-yellow, #ca8a04)",label:"Stale",pulse:!1},completed:{color:"var(--loki-text-muted, #a1a1aa)",label:"Completed",pulse:!1},failed:{color:"var(--loki-red, #dc2626)",label:"Could not start",pulse:!1},crashed:{color:"var(--loki-red, #dc2626)",label:"Crashed",pulse:!1},stopped:{color:"var(--loki-text-muted, #a1a1aa)",label:"Stopped",pulse:!1},error:{color:"var(--loki-text-muted, #71717a)",label:"Status unavailable",pulse:!1},unknown:{color:"var(--loki-text-muted, #71717a)",label:"Unknown",pulse:!1}},re=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._pollInterval=null,this._status=null,this._errors=null,this._error=null,this._lastDataHash=null,this._detailsOpen=!1,this._iframeFailed=!1,this._iframeLoadTimer=null,this._IFRAME_LOAD_TIMEOUT_MS=6e3,this._activeServiceKey=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this.render(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._clearIframeLoadTimer()}_clearIframeLoadTimer(){this._iframeLoadTimer&&(clearTimeout(this._iframeLoadTimer),this._iframeLoadTimer=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api.getAppRunnerStatus(),t=e?.status||"not_initialized",i=null;if(t==="crashed"||t==="failed")try{i=await this._api.getAppRunnerErrors(50)}catch{i=null}let a=JSON.stringify({status:t,port:e?.port,url:e?.url,crash:e?.crash_count,errLen:i?.lines?.length||0,extMgd:e?.externally_managed===!0,source:e?.source||null,healthOk:e?.last_health?.ok===!0?"ok":e?.last_health?.ok===!1?"down":"unknown",services:Array.isArray(e?.services)?e.services.map(r=>`${r?.url||""}|${r?.role||""}|${r?.name||""}`).join(","):null}),s=this._error!==null;if(a===this._lastDataHash&&!s)return;this._iframeFailed=!1,this._lastDataHash=a,this._status=e,this._errors=i,this._error=null,this.render()}catch(e){this._error||(this._error=`Could not read app status: ${e.message}`,this.render())}}_isValidUrl(e){if(!e)return!1;try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}_getServices(){let e=this._status;if(!e)return[];let t=Array.isArray(e.services)&&e.services.length>0?e.services:[{url:e.url,role:"",name:e.primary_service||"",port:e.port}],i=new Set,a=[];for(let s of t){if(!s||!this._isValidUrl(s.url))continue;let r=typeof s.name=="string"?s.name.trim():"",o=s.port!=null?String(s.port):"",n=this._inferServiceRole(s.role,r),l=s.url||r||o;if(i.has(l))continue;i.add(l);let c=r;c||(c=n==="api"?"API":n==="ui"?"UI":""),c||(c=o?`Port ${o}`:"Service"),a.push({key:l,url:s.url,role:n,name:r,port:o,label:c})}return a}_inferServiceRole(e,t){let i=typeof e=="string"?e.trim().toLowerCase():"";if(i==="ui"||i==="web"||i==="frontend")return"ui";if(i==="api"||i==="backend"||i==="server")return"api";let a=(t||"").toLowerCase();return/\b(api|backend|server|graphql|grpc)\b/.test(a)||a.includes("api")?"api":""}_activeService(e){if(!e||e.length===0)return null;if(this._activeServiceKey){let t=e.find(i=>i.key===this._activeServiceKey);if(t)return t}return e[0]}_handleSelectService(e){this._activeServiceKey!==e&&(this._activeServiceKey=e,this._iframeFailed=!1,this.render())}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(e){this._error=`Restart failed: ${e.message}`,this.render()}}_currentTargetUrl(){let e=this._activeService(this._getServices());if(e&&this._isValidUrl(e.url))return e.url;let t=this._status;return t&&this._isValidUrl(t.url)?t.url:""}_handleRefresh(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector("iframe.preview-frame"),i=this._currentTargetUrl();if(t&&i){this._iframeFailed=!1,this._clearIframeLoadTimer();let a=(i.includes("?")?"&":"?")+"_t="+Date.now();t.src=i+a,this._armIframeLoadDetection()}}_handleRetryFrame(){this._iframeFailed=!1,this._lastDataHash=null,this.render(),this._loadData()}_handleOpenExternal(){let e=this._currentTargetUrl();e&&window.open(e,"_blank","noopener")}_toggleDetails(){this._detailsOpen=!this._detailsOpen,this.render()}_getStyles(){return`
|
|
7098
7124
|
.preview { padding: 16px; font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif); color: var(--loki-text-primary, #201515); display: flex; flex-direction: column; width: 100%; box-sizing: border-box; }
|
|
7099
7125
|
.header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; gap: 12px; flex-wrap: wrap; }
|
|
7100
7126
|
.header-left { display: flex; align-items: center; gap: 10px; }
|
|
@@ -7144,7 +7170,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7144
7170
|
.details-toggle:hover { text-decoration: underline; }
|
|
7145
7171
|
.details-body { margin-top: 8px; background: var(--loki-bg-code, #1e1e1e); color: #d4d4d4; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; padding: 10px; border-radius: 6px; max-height: 200px; overflow: auto; white-space: pre-wrap; }
|
|
7146
7172
|
.error-banner { margin-top: 12px; padding: 10px 12px; border-radius: 6px; background: color-mix(in srgb, var(--loki-red, #dc2626) 10%, transparent); color: var(--loki-red, #dc2626); font-size: 13px; }
|
|
7147
|
-
`}_effectiveView(e,t){let i=this._status,a=i?.last_health,s=a&&typeof a.ok=="boolean"?a.ok:null;if(e==="running"&&t&&(i?.externally_managed===!0||i?.source==="discovered"))return{view:"running",healthOk:s};if(e==="running"&&t){if(s===!1)return{view:"starting",healthOk:s};if(s===!0)return{view:"running",healthOk:s};let r=i?.started_at?Date.parse(i.started_at):NaN;return{view:Number.isFinite(r)&&Date.now()-r<15e3?"running":"starting",healthOk:s}}return{view:e,healthOk:s}}render(){let e=this.shadowRoot;if(!e)return;this._clearIframeLoadTimer();let t=this._status,i=t?.status||"not_initialized",a=this._getServices(),s=this._activeService(a),r=a.length>1,o=s?.url||t?.url,n=this._isValidUrl(o),{view:l,healthOk:c}=this._effectiveView(i,n),p=t?.externally_managed===!0||t?.source==="discovered",h=
|
|
7173
|
+
`}_effectiveView(e,t){let i=this._status,a=i?.last_health,s=a&&typeof a.ok=="boolean"?a.ok:null;if(e==="running"&&t&&(i?.externally_managed===!0||i?.source==="discovered"))return{view:"running",healthOk:s};if(e==="running"&&t){if(s===!1)return{view:"starting",healthOk:s};if(s===!0)return{view:"running",healthOk:s};let r=i?.started_at?Date.parse(i.started_at):NaN;return{view:Number.isFinite(r)&&Date.now()-r<15e3?"running":"starting",healthOk:s}}return{view:e,healthOk:s}}render(){let e=this.shadowRoot;if(!e)return;this._clearIframeLoadTimer();let t=this._status,i=t?.status||"not_initialized",a=this._getServices(),s=this._activeService(a),r=a.length>1,o=s?.url||t?.url,n=this._isValidUrl(o),{view:l,healthOk:c}=this._effectiveView(i,n),p=t?.externally_managed===!0||t?.source==="discovered",h=nt[l]||nt.not_initialized,v=i==="running"&&c===!1?"Starting / not responding yet":h.label;e.innerHTML=`
|
|
7148
7174
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
7149
7175
|
<div class="preview">
|
|
7150
7176
|
<div class="header">
|
|
@@ -7152,7 +7178,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7152
7178
|
<h2 class="title">Live App</h2>
|
|
7153
7179
|
<span class="status-badge" style="background: color-mix(in srgb, ${h.color} 15%, transparent); color: ${h.color}">
|
|
7154
7180
|
<span class="status-dot ${h.pulse?"pulse":""}" style="background: ${h.color}"></span>
|
|
7155
|
-
${this._escapeHtml(
|
|
7181
|
+
${this._escapeHtml(v)}
|
|
7156
7182
|
</span>
|
|
7157
7183
|
</div>
|
|
7158
7184
|
${this._renderToolbar(l,n,p)}
|
|
@@ -7265,7 +7291,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7265
7291
|
</button>
|
|
7266
7292
|
${this._detailsOpen?`<div class="details-body">${s}</div>`:""}
|
|
7267
7293
|
</div>
|
|
7268
|
-
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=(i,a)=>{let s=e.querySelector(i);s&&s.addEventListener("click",a)};e.querySelectorAll('[data-action="restart"]').forEach(i=>i.addEventListener("click",()=>this._handleRestart())),e.querySelectorAll('[data-action="open-external"]').forEach(i=>i.addEventListener("click",()=>this._handleOpenExternal())),e.querySelectorAll('[data-action="retry-frame"]').forEach(i=>i.addEventListener("click",()=>this._handleRetryFrame())),t('[data-action="refresh"]',()=>this._handleRefresh()),t('[data-action="toggle-details"]',()=>this._toggleDetails()),e.querySelectorAll('[data-action="select-service"]').forEach(i=>i.addEventListener("click",()=>this._handleSelectService(i.getAttribute("data-service-key"))))}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}};customElements.define("loki-app-preview",
|
|
7294
|
+
`}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=(i,a)=>{let s=e.querySelector(i);s&&s.addEventListener("click",a)};e.querySelectorAll('[data-action="restart"]').forEach(i=>i.addEventListener("click",()=>this._handleRestart())),e.querySelectorAll('[data-action="open-external"]').forEach(i=>i.addEventListener("click",()=>this._handleOpenExternal())),e.querySelectorAll('[data-action="retry-frame"]').forEach(i=>i.addEventListener("click",()=>this._handleRetryFrame())),t('[data-action="refresh"]',()=>this._handleRefresh()),t('[data-action="toggle-details"]',()=>this._toggleDetails()),e.querySelectorAll('[data-action="select-service"]').forEach(i=>i.addEventListener("click",()=>this._handleSelectService(i.getAttribute("data-service-key"))))}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}};customElements.define("loki-app-preview",re);var Mt={opus:{input:5,output:25,label:"Opus 4.6",provider:"claude"},sonnet:{input:3,output:15,label:"Sonnet 4.5",provider:"claude"},haiku:{input:1,output:5,label:"Haiku 4.5",provider:"claude"},"gpt-5.3-codex":{input:1.5,output:12,label:"GPT-5.3 Codex",provider:"codex"}},oe=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data={total_input_tokens:0,total_output_tokens:0,estimated_cost_usd:0,by_phase:{},by_model:{},budget_limit:null,budget_used:0,budget_remaining:null,connected:!1},this._api=null,this._pollInterval=null,this._modelPricing={...Mt}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadPricing(),this._loadCost(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadCost()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadPricing(){try{let e=await this._api.getPricing();if(e&&e.models){let t={};for(let[i,a]of Object.entries(e.models))t[i]={input:a.input,output:a.output,label:a.label||i,provider:a.provider||"unknown"};this._modelPricing=t,this._pricingSource=e.source||"api",this._pricingDate=e.updated||"",this._activeProvider=e.provider||"claude",this.render()}}catch{}}async _loadCost(){try{let e=await this._api.getCost();this._updateFromCost(e)}catch{this._data.connected=!1,this.render()}}_updateFromCost(e){e&&(this._data={...this._data,connected:!0,total_input_tokens:e.total_input_tokens||0,total_output_tokens:e.total_output_tokens||0,estimated_cost_usd:e.estimated_cost_usd||0,by_phase:e.by_phase||{},by_model:e.by_model||{},budget_limit:e.budget_limit,budget_used:e.budget_used||0,budget_remaining:e.budget_remaining},this.render())}_startPolling(){this._poll=b({loadFn:()=>this._loadCost(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatTokens(e){return!e||e===0?"0":e>=1e6?(e/1e6).toFixed(2)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}_formatUSD(e){return!e||e===0?"$0.00":e<.01?"<$0.01":"$"+e.toFixed(2)}_getBudgetPercent(){return!this._data.budget_limit||this._data.budget_limit<=0?0:Math.min(100,this._data.budget_used/this._data.budget_limit*100)}_getBudgetStatusClass(){let e=this._getBudgetPercent();return e>=90?"critical":e>=70?"warning":"ok"}_renderPhaseRows(){let e=this._data.by_phase;return!e||Object.keys(e).length===0?'<tr><td colspan="4" class="empty-cell">No phase data yet</td></tr>':Object.entries(e).map(([t,i])=>{let a=i.input_tokens||0,s=i.output_tokens||0,r=i.cost_usd||0;return`
|
|
7269
7295
|
<tr>
|
|
7270
7296
|
<td class="phase-name">${this._escapeHTML(t)}</td>
|
|
7271
7297
|
<td class="mono-cell">${this._formatTokens(a)}</td>
|
|
@@ -7667,7 +7693,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7667
7693
|
</div>
|
|
7668
7694
|
</div>
|
|
7669
7695
|
</div>
|
|
7670
|
-
`}};customElements.get("loki-cost-dashboard")||customElements.define("loki-cost-dashboard",
|
|
7696
|
+
`}};customElements.get("loki-cost-dashboard")||customElements.define("loki-cost-dashboard",oe);var ne=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._checkpoints=[],this._pollInterval=null,this._lastDataHash=null,this._showCreateForm=!1,this._creating=!1,this._rollingBack=!1,this._rollbackTarget=null,this._notice=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let[t]=await Promise.allSettled([this._api._get("/api/checkpoints?limit=50")]);t.status==="fulfilled"&&(this._checkpoints=Array.isArray(t.value)?t.value:t.value?.checkpoints||[]),this._error=null}catch(t){this._error=t.message}let e=JSON.stringify({c:this._checkpoints,e:this._error});e!==this._lastDataHash&&(this._lastDataHash=e,this.render())}async _createCheckpoint(){let e=this.shadowRoot.getElementById("checkpoint-message"),t=e?e.value.trim():"";if(t){this._creating=!0,this.render();try{await this._api._post("/api/checkpoints",{message:t}),this._showCreateForm=!1,this._creating=!1,this.dispatchEvent(new CustomEvent("checkpoint-action",{detail:{action:"create",message:t},bubbles:!0})),this._lastDataHash=null,await this._loadData()}catch(i){this._creating=!1,this._error=`Failed to create checkpoint: ${i.message}`,this.render()}}}async _rollbackCheckpoint(e){if(!this._rollingBack){this._rollingBack=!0,this._notice=null,this.render();try{let t=await this._api._post(`/api/checkpoints/${e}/rollback`);this._rollbackTarget=null;let i=t&&t.pre_rollback_snapshot;this._notice=i?`Rolled back to ${e}. Undo this with checkpoint ${i}`:`Rolled back to ${e}.`,this.dispatchEvent(new CustomEvent("checkpoint-action",{detail:{action:"rollback",checkpointId:e,preRollbackSnapshot:i||null},bubbles:!0})),this._lastDataHash=null,await this._loadData()}catch(t){this._rollbackTarget=null,this._error=`Failed to rollback: ${t.message}`}finally{this._rollingBack=!1,this.render()}}}_toggleCreateForm(){this._showCreateForm=!this._showCreateForm,this._rollbackTarget=null,this._notice=null,this.render()}_confirmRollback(e){this._rollbackTarget=e,this.render()}_cancelRollback(){this._rollbackTarget=null,this._notice=null,this.render()}_formatRelativeTime(e){if(!e)return"";try{let t=Date.now(),i=new Date(e).getTime(),a=Math.floor((t-i)/1e3);return a<60?`${a}s ago`:a<3600?`${Math.floor(a/60)}m ago`:a<86400?`${Math.floor(a/3600)}h ago`:`${Math.floor(a/86400)}d ago`}catch{return this._escapeHTML(e)}}render(){let e=this.shadowRoot;if(!e)return;let t=this._checkpoints.length;e.innerHTML=`
|
|
7671
7697
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
7672
7698
|
<div class="checkpoint-viewer">
|
|
7673
7699
|
<div class="checkpoint-header">
|
|
@@ -7986,7 +8012,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
7986
8012
|
color: var(--loki-green, #22c55e);
|
|
7987
8013
|
font-size: 12px;
|
|
7988
8014
|
}
|
|
7989
|
-
`}};customElements.get("loki-checkpoint-viewer")||customElements.define("loki-checkpoint-viewer",
|
|
8015
|
+
`}};customElements.get("loki-checkpoint-viewer")||customElements.define("loki-checkpoint-viewer",ne);var le=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._connected=!1,this._activeTab="gauge",this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadContext(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadContext()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadContext(){try{let e=this.getAttribute("api-url")||window.location.origin,t=await fetch(e+"/api/context");t.ok&&(this._data=await t.json(),this._connected=!0)}catch{this._connected=!1}this.render()}_startPolling(){this._poll=b({loadFn:()=>this._loadContext(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_setTab(e){this._activeTab=e,this.render()}_formatTokens(e){return!e||e===0?"0":e>=1e6?(e/1e6).toFixed(2)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}_formatUSD(e){return!e||e===0?"$0.00":e<.01?"<$0.01":"$"+e.toFixed(2)}_escapeHTML(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGaugeColor(e){return e>80?"var(--loki-red)":e>=60?"var(--loki-yellow)":"var(--loki-green)"}_getGaugeColorClass(e){return e>80?"gauge-red":e>=60?"gauge-yellow":"gauge-green"}_renderGaugeTab(){let e=this._data?.current||{},t=this._data?.totals||{},i=e.context_window_pct||0,a=this._getGaugeColor(i),s=this._getGaugeColorClass(i),r=70,o=2*Math.PI*r,n=o-i/100*o;return`
|
|
7990
8016
|
<div class="gauge-tab">
|
|
7991
8017
|
<div class="gauge-container">
|
|
7992
8018
|
<svg class="gauge-svg" viewBox="0 0 180 180" aria-label="Context window usage: ${i.toFixed(1)}%">
|
|
@@ -8099,14 +8125,14 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
8099
8125
|
<div class="legend-item"><span class="legend-swatch swatch-cache-read"></span> Cache Read</div>
|
|
8100
8126
|
<div class="legend-item"><span class="legend-swatch swatch-cache-create"></span> Cache Creation</div>
|
|
8101
8127
|
</div>
|
|
8102
|
-
`,a="";for(let s of e){let r=s.input_tokens||0,o=s.output_tokens||0,n=s.cache_read_tokens||0,l=s.cache_creation_tokens||0,c=r+o+n+l,p=t>0?r/t*100:0,h=t>0?o/t*100:0,
|
|
8128
|
+
`,a="";for(let s of e){let r=s.input_tokens||0,o=s.output_tokens||0,n=s.cache_read_tokens||0,l=s.cache_creation_tokens||0,c=r+o+n+l,p=t>0?r/t*100:0,h=t>0?o/t*100:0,v=t>0?n/t*100:0,u=t>0?l/t*100:0;a+=`
|
|
8103
8129
|
<div class="breakdown-row">
|
|
8104
8130
|
<div class="breakdown-iter">#${s.iteration}</div>
|
|
8105
8131
|
<div class="breakdown-bar-container">
|
|
8106
8132
|
<div class="breakdown-bar bar-input" style="width: ${p.toFixed(1)}%"></div>
|
|
8107
8133
|
<div class="breakdown-bar bar-output" style="width: ${h.toFixed(1)}%"></div>
|
|
8108
|
-
<div class="breakdown-bar bar-cache-read" style="width: ${
|
|
8109
|
-
<div class="breakdown-bar bar-cache-create" style="width: ${
|
|
8134
|
+
<div class="breakdown-bar bar-cache-read" style="width: ${v.toFixed(1)}%"></div>
|
|
8135
|
+
<div class="breakdown-bar bar-cache-create" style="width: ${u.toFixed(1)}%"></div>
|
|
8110
8136
|
</div>
|
|
8111
8137
|
<div class="breakdown-cost">${this._formatUSD(s.cost_usd)}</div>
|
|
8112
8138
|
</div>
|
|
@@ -8509,7 +8535,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
8509
8535
|
|
|
8510
8536
|
${e}
|
|
8511
8537
|
</div>
|
|
8512
|
-
`,this.shadowRoot.querySelectorAll(".tab").forEach(t=>{t.addEventListener("click",()=>{this._setTab(t.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",
|
|
8538
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(t=>{t.addEventListener("click",()=>{this._setTab(t.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",le);var Ge={critical:"var(--loki-red, #ef4444)",warning:"var(--loki-yellow, #eab308)",info:"var(--loki-blue, #3b82f6)",success:"var(--loki-green, #1FC5A8)"},lt={build:{label:"Build",icon:"B"},quality:{label:"Quality",icon:"Q"},system:{label:"System",icon:"S"},security:{label:"Security",icon:"!"}},de=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._notifications=[],this._triggers=[],this._summary={},this._connected=!1,this._activeTab="feed",this._categoryFilter="all",this._panelOpen=!0,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._loadNotifications(),this._loadTriggers(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&(this._loadNotifications(),this._loadTriggers()),e==="theme"&&this._applyTheme())}async _loadNotifications(){try{let e=this.getAttribute("api-url")||window.location.origin,t=await fetch(e+"/api/notifications");if(t.ok){let i=await t.json();this._notifications=i.notifications||[],this._summary=i.summary||{},this._connected=!0}}catch{this._connected=!1}this.render()}async _loadTriggers(){try{let e=this.getAttribute("api-url")||window.location.origin,t=await fetch(e+"/api/notifications/triggers");if(t.ok){let i=await t.json();this._triggers=i.triggers||[]}}catch{}}async _acknowledgeNotification(e){let t=this.getAttribute("api-url")||window.location.origin;try{await fetch(t+"/api/notifications/"+encodeURIComponent(e)+"/acknowledge",{method:"POST"})}catch{}this._loadNotifications()}async _unacknowledgeNotification(e){let t=this.getAttribute("api-url")||window.location.origin;await fetch(t+"/api/notifications/"+encodeURIComponent(e)+"/unacknowledge",{method:"POST"}),this._loadNotifications()}async _acknowledgeAll(){let e=this.getAttribute("api-url")||window.location.origin,t=this._notifications.filter(i=>!i.acknowledged);for(let i of t)await fetch(e+"/api/notifications/"+encodeURIComponent(i.id)+"/acknowledge",{method:"POST"});this._loadNotifications()}async _toggleTrigger(e,t){let i=this.getAttribute("api-url")||window.location.origin,a=this._triggers.map(s=>s.id===e?{...s,enabled:t}:s);await fetch(i+"/api/notifications/triggers",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({triggers:a})}),this._triggers=a,this.render()}_startPolling(){this._poll=b({loadFn:()=>{this._loadNotifications(),this._loadTriggers()},intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_formatTime(e){if(!e)return"";try{let t=new Date(e),a=new Date-t,s=Math.floor(a/1e3),r=Math.floor(s/60),o=Math.floor(r/60),n=Math.floor(o/24);return s<60?s+"s ago":r<60?r+"m ago":o<24?o+"h ago":n<7?n+"d ago":t.toLocaleDateString()}catch{return String(e)}}_getTimeGroup(e){if(!e)return"Other";try{let t=new Date(e),i=new Date,a=new Date(i.getFullYear(),i.getMonth(),i.getDate()),s=new Date(a);s.setDate(s.getDate()-1);let r=new Date(a);return r.setDate(r.getDate()-7),t>=a?"Today":t>=s?"Yesterday":t>=r?"This Week":"Earlier"}catch{return"Other"}}_escapeHTML(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getSeverityColor(e){return Ge[e]||Ge.info}_getCategory(e){return e.category||e.type||"system"}_switchTab(e){this._activeTab=e,this.render()}_setCategoryFilter(e){this._categoryFilter=e,this.render()}_togglePanel(){this._panelOpen=!this._panelOpen,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".tab").forEach(a=>{a.addEventListener("click",()=>{this._switchTab(a.dataset.tab)})}),e.querySelectorAll(".cat-btn").forEach(a=>{a.addEventListener("click",()=>{this._setCategoryFilter(a.dataset.cat)})}),e.querySelectorAll(".ack-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._acknowledgeNotification(a.dataset.id)})}),e.querySelectorAll(".unread-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._unacknowledgeNotification(a.dataset.id)})});let t=e.querySelector(".ack-all-btn");t&&t.addEventListener("click",()=>{this._acknowledgeAll()});let i=e.querySelector(".bell-icon");i&&i.addEventListener("click",()=>{this._togglePanel()}),e.querySelectorAll(".toggle input").forEach(a=>{a.addEventListener("change",()=>{this._toggleTrigger(a.dataset.triggerId,a.checked)})}),e.querySelectorAll(".dismiss-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._acknowledgeNotification(a.dataset.id)})})}_renderBellIcon(){let e=this._summary.unacknowledged||0;return`
|
|
8513
8539
|
<div class="bell-container">
|
|
8514
8540
|
<button class="bell-icon" title="${e} unread notifications">
|
|
8515
8541
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -8532,7 +8558,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
8532
8558
|
</div>
|
|
8533
8559
|
<div class="summary-card">
|
|
8534
8560
|
<div class="card-label">Critical</div>
|
|
8535
|
-
<div class="card-value" style="color: ${
|
|
8561
|
+
<div class="card-value" style="color: ${Ge.critical}">${i}</div>
|
|
8536
8562
|
</div>
|
|
8537
8563
|
</div>
|
|
8538
8564
|
${t>0?`
|
|
@@ -8541,9 +8567,9 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
8541
8567
|
</div>
|
|
8542
8568
|
`}_renderCategoryFilter(){return`
|
|
8543
8569
|
<div class="category-bar">
|
|
8544
|
-
${["all","build","quality","system","security"].map(t=>{let i=this._categoryFilter===t,a=t==="all"?"All":
|
|
8570
|
+
${["all","build","quality","system","security"].map(t=>{let i=this._categoryFilter===t,a=t==="all"?"All":lt[t]?.label||t;return`<button class="cat-btn ${i?"active":""}" data-cat="${t}">${a}</button>`}).join("")}
|
|
8545
8571
|
</div>
|
|
8546
|
-
`}_renderNotificationList(){let e=[...this._notifications].sort((s,r)=>new Date(r.timestamp)-new Date(s.timestamp));if(this._categoryFilter!=="all"&&(e=e.filter(s=>this._getCategory(s)===this._categoryFilter)),e.length===0)return'<div class="empty-state">No notifications</div>';let t={};for(let s of e){let r=this._getTimeGroup(s.timestamp);t[r]||(t[r]=[]),t[r].push(s)}let i=["Today","Yesterday","This Week","Earlier","Other"],a="";for(let s of i)!t[s]||t[s].length===0||(a+=`<div class="time-group-label">${s}</div>`,a+=t[s].map(r=>{let o=r.acknowledged,n=this._getSeverityColor(r.severity),l=this._getCategory(r),c=
|
|
8572
|
+
`}_renderNotificationList(){let e=[...this._notifications].sort((s,r)=>new Date(r.timestamp)-new Date(s.timestamp));if(this._categoryFilter!=="all"&&(e=e.filter(s=>this._getCategory(s)===this._categoryFilter)),e.length===0)return'<div class="empty-state">No notifications</div>';let t={};for(let s of e){let r=this._getTimeGroup(s.timestamp);t[r]||(t[r]=[]),t[r].push(s)}let i=["Today","Yesterday","This Week","Earlier","Other"],a="";for(let s of i)!t[s]||t[s].length===0||(a+=`<div class="time-group-label">${s}</div>`,a+=t[s].map(r=>{let o=r.acknowledged,n=this._getSeverityColor(r.severity),l=this._getCategory(r),c=lt[l]||{label:l,icon:"?"};return`
|
|
8547
8573
|
<div class="notif-row ${o?"acknowledged":""}">
|
|
8548
8574
|
<span class="severity-dot" style="background: ${n};" title="${this._escapeHTML(r.severity)}"></span>
|
|
8549
8575
|
<span class="cat-icon" title="${c.label}">${c.icon}</span>
|
|
@@ -9026,7 +9052,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9026
9052
|
`:""}
|
|
9027
9053
|
`:""}
|
|
9028
9054
|
</div>
|
|
9029
|
-
`,this._bindEvents()}};customElements.get("loki-notification-center")||customElements.define("loki-notification-center",
|
|
9055
|
+
`,this._bindEvents()}};customElements.get("loki-notification-center")||customElements.define("loki-notification-center",de);var ce=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._error=null,this._loading=!0,this._api=null,this._pollInterval=null,this._expandedDecisions=new Set}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._data=await this._api._get("/api/session-diff"),this._error=null}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleDecision(e){this._expandedDecisions.has(e)?this._expandedDecisions.delete(e):this._expandedDecisions.add(e),this.render()}render(){let e=`
|
|
9030
9056
|
${this.getBaseStyles()}
|
|
9031
9057
|
|
|
9032
9058
|
:host {
|
|
@@ -9292,7 +9318,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9292
9318
|
${n}
|
|
9293
9319
|
${l}
|
|
9294
9320
|
</div>
|
|
9295
|
-
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(c=>{c.addEventListener("click",()=>{this._toggleDecision(parseInt(c.dataset.index))})})}};customElements.get("loki-session-diff")||customElements.define("loki-session-diff",
|
|
9321
|
+
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(c=>{c.addEventListener("click",()=>{this._toggleDecision(parseInt(c.dataset.index))})})}};customElements.get("loki-session-diff")||customElements.define("loki-session-diff",ce);var pe=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._error=null,this._loading=!0,this._optimizing=!1,this._api=null,this._pollInterval=null,this._expandedChanges=new Set}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._data=await this._api._get("/api/prompt-versions"),this._error=null}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}async _triggerOptimize(){if(!this._optimizing){this._optimizing=!0,this.render();try{await this._api._post("/api/prompt-optimize?dry_run=false",{}),await this._loadData()}catch(e){this._error=e.message}this._optimizing=!1,this.render()}}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:6e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_formatTime(e){if(!e)return"--";try{let t=new Date(e),a=new Date-t,s=Math.floor(a/6e4);if(s<1)return"Just now";if(s<60)return`${s}m ago`;let r=Math.floor(s/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}catch{return"--"}}_toggleChange(e){this._expandedChanges.has(e)?this._expandedChanges.delete(e):this._expandedChanges.add(e),this.render()}render(){let e=`
|
|
9296
9322
|
${this.getBaseStyles()}
|
|
9297
9323
|
|
|
9298
9324
|
:host {
|
|
@@ -9543,7 +9569,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9543
9569
|
|
|
9544
9570
|
${o}
|
|
9545
9571
|
</div>
|
|
9546
|
-
`;let n=this.shadowRoot.getElementById("optimize-btn");n&&n.addEventListener("click",()=>this._triggerOptimize()),this.shadowRoot.querySelectorAll(".change-header").forEach(l=>{l.addEventListener("click",()=>{this._toggleChange(parseInt(l.dataset.index))})})}};customElements.get("loki-prompt-optimizer")||customElements.define("loki-prompt-optimizer",
|
|
9572
|
+
`;let n=this.shadowRoot.getElementById("optimize-btn");n&&n.addEventListener("click",()=>this._triggerOptimize()),this.shadowRoot.querySelectorAll(".change-header").forEach(l=>{l.addEventListener("click",()=>{this._toggleChange(parseInt(l.dataset.index))})})}};customElements.get("loki-prompt-optimizer")||customElements.define("loki-prompt-optimizer",pe);var he=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._history=[],this._error=null,this._loading=!0,this._scanning=!1,this._rigourAvailable=!0,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{let[e,t]=await Promise.allSettled([this._api._get("/api/quality-score"),this._api._get("/api/quality-score/history")]);if(e.status==="fulfilled"){let i=e.value;i&&i.error&&i.error.includes("not installed")?(this._rigourAvailable=!1,this._data=null):i&&i.available===!1?(this._rigourAvailable=!1,this._data=null):i&&i.score==null?(this._rigourAvailable=!0,this._data=null):(this._rigourAvailable=!0,this._data=i),this._error=null}else(e.reason?.message||"").includes("404")?(this._rigourAvailable=!1,this._data=null,this._error=null):(this._error="Failed to load quality score",this._data=null);if(t.status==="fulfilled"){let i=t.value;this._history=Array.isArray(i)?i.slice(-10):(i.scores||[]).slice(-10)}}catch(e){this._error=e.message,this._data=null}this._loading=!1,this.render()}async _triggerScan(){if(!this._scanning){this._scanning=!0,this.render();try{await this._api._post("/api/quality-scan",{},{timeout:3e5}),await this._loadData()}catch(e){this._error=e.message}this._scanning=!1,this.render()}}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:6e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGrade(e){return e>=90?{grade:"A",color:"var(--loki-success)"}:e>=80?{grade:"B",color:"var(--loki-success)"}:e>=70?{grade:"C",color:"var(--loki-warning)"}:e>=60?{grade:"D",color:"var(--loki-warning)"}:{grade:"F",color:"var(--loki-error)"}}_renderSparkline(e){if(!e||e.length<2)return"";let t=e.map(c=>typeof c=="number"?c:c.score||0),i=Math.min(...t),s=Math.max(...t)-i||1,r=120,o=32,n=2,l=t.map((c,p)=>{let h=n+p/(t.length-1)*(r-n*2),v=n+(1-(c-i)/s)*(o-n*2);return`${h},${v}`}).join(" ");return`
|
|
9547
9573
|
<svg width="${r}" height="${o}" viewBox="0 0 ${r} ${o}" class="sparkline">
|
|
9548
9574
|
<polyline points="${l}" fill="none" stroke="var(--loki-accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9549
9575
|
<circle cx="${l.split(" ").pop().split(",")[0]}" cy="${l.split(" ").pop().split(",")[1]}" r="2.5" fill="var(--loki-accent)"/>
|
|
@@ -9933,15 +9959,15 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9933
9959
|
</button>
|
|
9934
9960
|
</div>
|
|
9935
9961
|
</div>
|
|
9936
|
-
`;let k=this.shadowRoot.getElementById("scan-btn");k&&k.addEventListener("click",()=>this._triggerScan());return}let i=this._data||{},a=i.score!=null?Math.round(i.score):0,{grade:s,color:r}=this._getGrade(a),o=i.categories||{},n=i.findings||{},l=["security","code_quality","compliance","best_practices"],c={security:"Security",code_quality:"Code Quality",compliance:"Compliance",best_practices:"Best Practices"},p=l.map(k=>{let
|
|
9962
|
+
`;let k=this.shadowRoot.getElementById("scan-btn");k&&k.addEventListener("click",()=>this._triggerScan());return}let i=this._data||{},a=i.score!=null?Math.round(i.score):0,{grade:s,color:r}=this._getGrade(a),o=i.categories||{},n=i.findings||{},l=["security","code_quality","compliance","best_practices"],c={security:"Security",code_quality:"Code Quality",compliance:"Compliance",best_practices:"Best Practices"},p=l.map(k=>{let _=o[k]!=null?Math.round(o[k]):0,R=_>=80?"var(--loki-success)":_>=60?"var(--loki-warning)":"var(--loki-error)";return`
|
|
9937
9963
|
<div class="category-item">
|
|
9938
9964
|
<span class="category-name">${c[k]||k}</span>
|
|
9939
9965
|
<div class="progress-bar">
|
|
9940
|
-
<div class="progress-fill" style="width:${
|
|
9966
|
+
<div class="progress-fill" style="width:${_}%;background:${R};"></div>
|
|
9941
9967
|
</div>
|
|
9942
|
-
<span class="category-score">${
|
|
9968
|
+
<span class="category-score">${_}</span>
|
|
9943
9969
|
</div>
|
|
9944
|
-
`}).join(""),
|
|
9970
|
+
`}).join(""),v=[{key:"critical",cls:"finding-critical",label:"Critical"},{key:"major",cls:"finding-major",label:"Major"},{key:"minor",cls:"finding-minor",label:"Minor"},{key:"info",cls:"finding-info",label:"Info"}].filter(k=>(n[k.key]||0)>0).map(k=>`<span class="finding-badge ${k.cls}">${k.label}: ${n[k.key]}</span>`).join(""),u=this._renderSparkline(this._history);this.shadowRoot.innerHTML=`
|
|
9945
9971
|
<style>${e}</style>
|
|
9946
9972
|
<div class="quality-container">
|
|
9947
9973
|
<div class="quality-header">
|
|
@@ -9957,10 +9983,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9957
9983
|
<div class="score-number">${a}</div>
|
|
9958
9984
|
<span class="grade-badge" style="background:${r};color:#fff;">${s}</span>
|
|
9959
9985
|
</div>
|
|
9960
|
-
${
|
|
9986
|
+
${u?`
|
|
9961
9987
|
<div class="sparkline-container">
|
|
9962
9988
|
<span class="sparkline-label">Trend (last ${this._history.length})</span>
|
|
9963
|
-
${
|
|
9989
|
+
${u}
|
|
9964
9990
|
</div>
|
|
9965
9991
|
`:""}
|
|
9966
9992
|
</div>
|
|
@@ -9970,19 +9996,19 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
9970
9996
|
${p}
|
|
9971
9997
|
</div>
|
|
9972
9998
|
|
|
9973
|
-
${
|
|
9999
|
+
${v?`
|
|
9974
10000
|
<div class="findings-section">
|
|
9975
10001
|
<div class="section-label">Findings</div>
|
|
9976
|
-
<div class="findings-row">${
|
|
10002
|
+
<div class="findings-row">${v}</div>
|
|
9977
10003
|
</div>
|
|
9978
10004
|
`:""}
|
|
9979
10005
|
</div>
|
|
9980
|
-
`;let x=this.shadowRoot.getElementById("scan-btn");x&&x.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-score")||customElements.define("loki-quality-score",
|
|
10006
|
+
`;let x=this.shadowRoot.getElementById("scan-btn");x&&x.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-score")||customElements.define("loki-quality-score",he);var dt=["understand","guardrail","migrate","verify"],ct={understand:"Understand",guardrail:"Guardrail",migrate:"Migrate",verify:"Verify"},Bt={understand:"#5b9bd5",guardrail:"#e8b84a",migrate:"#5bb870",verify:"#5bc8c8"},ue=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._migration=null,this._migrations=[],this._loading=!0,this._error=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._fetchMigrations(),this._poll=b({loadFn:()=>this._fetchData(),intervalMs:15e3,element:this,immediate:!1})}disconnectedCallback(){super.disconnectedCallback(),this._poll&&(this._poll.stop(),this._poll=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._fetchMigrations()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _fetchMigrations(){try{let e=await this._api._get("/api/migration/list");this._migrations=Array.isArray(e)?e:e.migrations||[],this._error=null;let t=this._migrations.find(i=>i.status==="in_progress"||i.status==="active");t?await this._fetchStatus(t.migration_id||t.id):this._migration=null}catch(e){this._error=e.message,this._migrations=[],this._migration=null}this._loading=!1,this.render()}async _fetchStatus(e){try{this._migration=await this._api._get(`/api/migration/${encodeURIComponent(e)}/status`),this._error=null}catch(t){this._error=t.message}}async _fetchData(){let e=this._migration&&(this._migration.migration_id||this._migration.id);e?(await this._fetchStatus(e),this.render()):await this._fetchMigrations()}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"):""}_getPhaseIcon(e,t,i){return(i||[]).includes(e)?"[x]":e===t?"[>]":"[ ]"}_getPhaseIndex(e){let t=dt.indexOf(e);return t>=0?t:0}_renderPhaseBar(e,t){let i=t||[];return dt.map(a=>{let s=i.includes(a),r=a===e,o=Bt[a],n=s?"1":r?"0.7":"0.2",l=this._getPhaseIcon(a,e,t);return`
|
|
9981
10007
|
<div class="phase-segment">
|
|
9982
10008
|
<div class="phase-bar-fill" style="background:${o};opacity:${n};"></div>
|
|
9983
10009
|
<div class="phase-label">
|
|
9984
10010
|
<span class="phase-icon">${l}</span>
|
|
9985
|
-
${
|
|
10011
|
+
${ct[a]}
|
|
9986
10012
|
</div>
|
|
9987
10013
|
</div>
|
|
9988
10014
|
`}).join("")}_renderFeatureStats(e){if(!e)return"";let t=e.passing||0,i=e.total||0,a=i>0?Math.round(t/i*100):0,s=a>=80?"var(--loki-success)":a>=50?"var(--loki-warning)":"var(--loki-error)";return`
|
|
@@ -10373,7 +10399,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
10373
10399
|
</div>
|
|
10374
10400
|
<div class="meta-item">
|
|
10375
10401
|
<span class="meta-label">Phase</span>
|
|
10376
|
-
<span>${
|
|
10402
|
+
<span>${ct[o]||this._escapeHtml(o)}</span>
|
|
10377
10403
|
</div>
|
|
10378
10404
|
</div>
|
|
10379
10405
|
|
|
@@ -10400,7 +10426,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
10400
10426
|
<div class="section-label">Migrations</div>
|
|
10401
10427
|
${this._renderMigrationList()}
|
|
10402
10428
|
</div>
|
|
10403
|
-
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",
|
|
10429
|
+
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",ue);var Pt=[["claude-opus","claude"],["claude-sonnet","claude"],["claude-haiku","claude"],["opus","claude"],["sonnet","claude"],["haiku","claude"],["claude","claude"],["gpt-4","codex"],["gpt-5","codex"],["gpt","codex"],["codex","codex"],["o1","codex"],["o3","codex"],["cline","cline"],["aider","aider"]];function It(d){if(d==null)return null;switch(d%4){case 0:return{tier:"planning",model:"opus",provider:"claude"};case 1:return{tier:"development",model:"sonnet",provider:"claude"};case 2:return{tier:"development",model:"sonnet",provider:"claude"};case 3:return{tier:"fast",model:"haiku",provider:"claude"};default:return{tier:"development",model:"sonnet",provider:"claude"}}}function Ft(d,e){if(e!=null){let i=It(e);if(i)return i.provider}let t=(d||"").toLowerCase();for(let[i,a]of Pt)if(t.includes(i))return a;return"unknown"}var ge=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._pollInterval=null,this._activeTab="heatmap",this._activity=[],this._tools=[],this._cost={},this._context={},this._trends=[],this._toolTimeRange="7d",this._connected=!1,this._loading=!1,this._loadedOnce=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _fetchActivity(){let e=this._api.baseUrl||window.location.origin,t=new AbortController,i=setTimeout(()=>t.abort(),1e4);try{let a=await fetch(`${e}/api/activity?limit=1000`,{signal:t.signal});if(clearTimeout(i),!a.ok)throw new Error(`Activity API ${a.status}`);return a.json()}catch(a){throw clearTimeout(i),a}}async _loadData(){if(!(!this.isConnected||this._loading)){this._loading=!0;try{let e=await Promise.allSettled([this._fetchActivity(),this._api.getToolEfficiency(50),this._api.getCost(),this._api.getContext(),this._api.getLearningTrends({timeRange:this._toolTimeRange})]);if(e[0].status==="fulfilled"&&(this._activity=e[0].value||[]),e[1].status==="fulfilled"&&(this._tools=e[1].value||[]),e[2].status==="fulfilled"&&(this._cost=e[2].value||{}),e[3].status==="fulfilled"&&(this._context=e[3].value||{}),e[4].status==="fulfilled"){let t=e[4].value||{};this._trends=Array.isArray(t)?t:t.dataPoints||[]}this._connected=e.some(t=>t.status==="fulfilled"),this._loadedOnce=!0,this.render()}finally{this._loading=!1}}}_hasAnyData(){let e=Array.isArray(this._activity)?this._activity.length:0,t=Array.isArray(this._tools)?this._tools.length:0,i=this._cost&&this._cost.by_model?Object.keys(this._cost.by_model).length:0,a=this._context||{},r=(a.totals||{}).iterations_tracked||a.total_iterations||a.iteration||0;return e>0||t>0||i>0||r>0}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}_computeHeatmap(){let e={},t=Array.isArray(this._activity)?this._activity:[];for(let c of t){let p=c.timestamp||c.ts||c.created_at;if(!p)continue;let h=new Date(p);if(isNaN(h.getTime()))continue;let v=this._localDateKey(h);e[v]=(e[v]||0)+1}let i=new Date;i.setHours(0,0,0,0);let a=i.getDay(),s=new Date(i),r=new Date(i);r.setDate(r.getDate()-(52*7+a));let o=[],n=new Date(r),l=0;for(;n<=s;){let c=this._localDateKey(n),p=e[c]||0;p>l&&(l=p),o.push({date:c,count:p,day:n.getDay()}),n.setDate(n.getDate()+1)}return{cells:o,maxCount:l}}_getHeatmapLevel(e,t){if(e===0||t===0)return 0;let i=e/t;return i<=.25?1:i<=.5?2:i<=.75?3:4}_renderHeatmap(){let{cells:e,maxCount:t}=this._computeHeatmap(),i=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],a=["","Mon","","Wed","","Fri",""],s=[],r=-1,o=-1;for(let p=0;p<e.length;p++){e[p].day===0&&o++;let h=new Date(e[p].date).getMonth();h!==r&&(s.push({month:i[h],col:Math.max(o,1)}),r=h)}let n=s.map(p=>`<span class="heatmap-month" style="grid-column: ${p.col}">${p.month}</span>`).join(""),l=e.map(p=>`<div class="heatmap-cell level-${this._getHeatmapLevel(p.count,t)}" title="${p.date}: ${p.count} activities"></div>`).join(""),c=a.map(p=>`<span class="heatmap-day-label">${p}</span>`).join("");return`
|
|
10404
10430
|
<div class="heatmap-container">
|
|
10405
10431
|
<div class="heatmap-months">${n}</div>
|
|
10406
10432
|
<div class="heatmap-body">
|
|
@@ -10450,7 +10476,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
10450
10476
|
<div class="sparkline-label">Activity Trend (hourly)</div>
|
|
10451
10477
|
<div class="sparkline">${s}</div>
|
|
10452
10478
|
</div>
|
|
10453
|
-
`}_computeProviders(){let e=this._cost.by_model||{},t={};for(let[r,o]of Object.entries(e)){let n=
|
|
10479
|
+
`}_computeProviders(){let e=this._cost.by_model||{},t={};for(let[r,o]of Object.entries(e)){let n=Ft(r);t[n]||(t[n]={cost:0,tokens:0,iterations:0,models:[]});let l=o.cost_usd||0,c=(o.input_tokens||0)+(o.output_tokens||0);t[n].cost+=l,t[n].tokens+=c,t[n].models.push(r)}let a=(this._context.totals||{}).iterations_tracked||this._context.total_iterations||this._context.iteration||0,s=this._cost.estimated_cost_usd||0;for(let r of Object.values(t))if(s>0&&a>0){let o=r.cost/s;r.iterations=Math.round(o*a)}return t}_renderProviders(){let e=this._computeProviders(),t={claude:{label:"Claude",color:"var(--loki-accent)"},codex:{label:"Codex",color:"var(--loki-success)"},cline:{label:"Cline",color:"var(--loki-info)"},aider:{label:"Aider",color:"var(--loki-blue)"},unknown:{label:"Other",color:"var(--loki-text-muted)"}},i=Object.entries(e);return i.length===0?'<div class="empty-state">No provider activity yet. Start a build to compare providers side by side.</div>':`
|
|
10454
10480
|
<div class="provider-grid">
|
|
10455
10481
|
${i.map(([a,s])=>{let r=t[a]||t.unknown,o=s.iterations>0?(s.cost/s.iterations).toFixed(4):"--",n=s.iterations>0?Math.round(s.tokens/s.iterations).toLocaleString():"--";return`
|
|
10456
10482
|
<div class="provider-card">
|
|
@@ -10953,7 +10979,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
10953
10979
|
</div>
|
|
10954
10980
|
`}
|
|
10955
10981
|
</div>
|
|
10956
|
-
`,this.shadowRoot.querySelectorAll("[data-tab]").forEach(l=>{l.addEventListener("click",c=>this._handleTabClick(c))});let r=this.shadowRoot.getElementById("tool-time-range");r&&r.addEventListener("change",l=>this._handleTimeRangeChange(l));let o=this.shadowRoot.getElementById("analytics-retry-btn");o&&o.addEventListener("click",()=>this._loadData());let n=this.shadowRoot.getElementById("analytics-overview-btn");n&&n.addEventListener("click",()=>this._navigateToOverview())}_navigateToOverview(){this.dispatchEvent(new CustomEvent("loki-navigate",{detail:{view:"overview"},bubbles:!0,composed:!0}))}};customElements.get("loki-analytics")||customElements.define("loki-analytics",
|
|
10982
|
+
`,this.shadowRoot.querySelectorAll("[data-tab]").forEach(l=>{l.addEventListener("click",c=>this._handleTabClick(c))});let r=this.shadowRoot.getElementById("tool-time-range");r&&r.addEventListener("change",l=>this._handleTimeRangeChange(l));let o=this.shadowRoot.getElementById("analytics-retry-btn");o&&o.addEventListener("click",()=>this._loadData());let n=this.shadowRoot.getElementById("analytics-overview-btn");n&&n.addEventListener("click",()=>this._navigateToOverview())}_navigateToOverview(){this.dispatchEvent(new CustomEvent("loki-navigate",{detail:{view:"overview"},bubbles:!0,composed:!0}))}};customElements.get("loki-analytics")||customElements.define("loki-analytics",ge);var pt={pass:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"PASS"},fail:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"FAIL"},pending:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"PENDING"}};function jt(d){if(!d)return"Never";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return"Unknown"}}function Ut(d){if(!d||d.length===0)return{pass:0,fail:0,pending:0,total:0};let e={pass:0,fail:0,pending:0,total:d.length};for(let t of d){let i=(t.status||"pending").toLowerCase();i==="pass"?e.pass++:i==="fail"?e.fail++:e.pending++}return e}var me=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._gates=[],this._evidence={blocked:!1},this._pollInterval=null,this._lastDataHash=null,this._scanning=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{this._loading=!0;let e=await this._api._get("/api/council/gate"),t=e?.gates||e||[],i=e?.evidence||{blocked:!1},a=JSON.stringify({gates:t,evidence:i});if(a===this._lastDataHash)return;this._lastDataHash=a,this._gates=Array.isArray(t)?t:[],this._evidence=i,this._error=null}catch(e){this._error||(this._error=`Failed to load quality gates: ${e.message}`)}finally{this._loading=!1}this.render()}async _triggerScan(){if(!this._scanning){this._scanning=!0,this.render();try{await this._api._post("/api/quality-scan",{},{timeout:3e5}),this._lastDataHash=null,await this._loadData()}catch(e){this._error=`Quality scan failed: ${e.message}`}finally{this._scanning=!1,this.render()}}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
10957
10983
|
:host {
|
|
10958
10984
|
display: block;
|
|
10959
10985
|
}
|
|
@@ -11213,7 +11239,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11213
11239
|
color: var(--loki-text-muted, #939084);
|
|
11214
11240
|
font-size: 13px;
|
|
11215
11241
|
}
|
|
11216
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._gates,i=
|
|
11242
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._gates,i=Ut(t),a='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>',s;this._loading&&t.length===0?s='<div class="loading">Loading quality gates...</div>':t.length===0?s=`
|
|
11217
11243
|
<div class="es">
|
|
11218
11244
|
<div class="es-icon">${a}</div>
|
|
11219
11245
|
<div class="es-title">No gate results yet</div>
|
|
@@ -11221,20 +11247,20 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11221
11247
|
<button class="es-cta" id="gates-scan-btn" ${this._scanning?"disabled":""}>
|
|
11222
11248
|
${this._scanning?'<span class="es-spinner"></span> Scanning...':"Run quality scan"}
|
|
11223
11249
|
</button>
|
|
11224
|
-
</div>`:s=`<div class="gates-grid">${t.map(p=>{let h=(p.status||"pending").toLowerCase(),
|
|
11250
|
+
</div>`:s=`<div class="gates-grid">${t.map(p=>{let h=(p.status||"pending").toLowerCase(),v=pt[h]||pt.pending;return`
|
|
11225
11251
|
<div class="gate-card status-${h}">
|
|
11226
11252
|
<div class="gate-header">
|
|
11227
11253
|
<span class="gate-name">${this._escapeHtml(p.name||"Unnamed Gate")}</span>
|
|
11228
|
-
<span class="gate-badge" style="background: ${
|
|
11254
|
+
<span class="gate-badge" style="background: ${v.bg}; color: ${v.color};">${v.label}</span>
|
|
11229
11255
|
</div>
|
|
11230
11256
|
${p.description?`<div class="gate-description">${this._escapeHtml(p.description)}</div>`:""}
|
|
11231
|
-
<div class="gate-meta">Last checked: ${
|
|
11257
|
+
<div class="gate-meta">Last checked: ${jt(p.last_checked||p.lastChecked)}</div>
|
|
11232
11258
|
</div>
|
|
11233
|
-
`}).join("")}</div>`;let r="",o=this._evidence||{};if(o.blocked){let c={empty_diff:"No changes were shipped (empty diff vs run start).",tests_red:"Tests ran and were red.",empty_diff_and_tests_red:"No changes shipped and tests were red.",no_evidence_of_completion:"No evidence of completion."},p=o.error?this._escapeHtml(o.error):c[o.reason]||this._escapeHtml(o.reason||"Completion blocked."),h=Array.isArray(o.failures)?o.failures:[],
|
|
11259
|
+
`}).join("")}</div>`;let r="",o=this._evidence||{};if(o.blocked){let c={empty_diff:"No changes were shipped (empty diff vs run start).",tests_red:"Tests ran and were red.",empty_diff_and_tests_red:"No changes shipped and tests were red.",no_evidence_of_completion:"No evidence of completion."},p=o.error?this._escapeHtml(o.error):c[o.reason]||this._escapeHtml(o.reason||"Completion blocked."),h=Array.isArray(o.failures)?o.failures:[],v=h.length?`<ul class="evidence-failures">${h.map(u=>`<li>${this._escapeHtml(u)}</li>`).join("")}</ul>`:"";r=`
|
|
11234
11260
|
<div class="evidence-banner">
|
|
11235
11261
|
<div class="evidence-title">Verified completion blocked</div>
|
|
11236
11262
|
<div class="evidence-reason">${p}</div>
|
|
11237
|
-
${
|
|
11263
|
+
${v}
|
|
11238
11264
|
<div class="evidence-hint">The run will keep iterating until there is real evidence of completion. Set <code>LOKI_EVIDENCE_GATE=0</code> to opt out.</div>
|
|
11239
11265
|
</div>
|
|
11240
11266
|
`}let n=i.total>0?`
|
|
@@ -11263,7 +11289,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11263
11289
|
${s}
|
|
11264
11290
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11265
11291
|
</div>
|
|
11266
|
-
`;let l=e.getElementById("gates-scan-btn");l&&l.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-gates")||customElements.define("loki-quality-gates",
|
|
11292
|
+
`;let l=e.getElementById("gates-scan-btn");l&&l.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-gates")||customElements.define("loki-quality-gates",me);var q={reason:{color:"var(--loki-blue, #3b82f6)",label:"Reason",description:"Analyzing requirements and planning approach"},act:{color:"var(--loki-green, #22c55e)",label:"Act",description:"Implementing changes and executing tasks"},reflect:{color:"var(--loki-purple, #a78bfa)",label:"Reflect",description:"Reviewing results and evaluating quality"},verify:{color:"var(--loki-yellow, #eab308)",label:"Verify",description:"Running tests and validating correctness"}},Ke=["reason","act","reflect","verify"];function Ne(d){if(d==null||d<0)return"--";if(d<1e3)return`${d}ms`;let e=Math.floor(d/1e3);if(e<60)return`${e}s`;let t=Math.floor(e/60),i=e%60;if(t<60)return`${t}m ${i}s`;let a=Math.floor(t/60),s=t%60;return`${a}h ${s}m`}function Ot(d){if(!d||d.length===0)return[];let e=d.reduce((t,i)=>t+(i.duration_ms||0),0);return e===0?d.map(t=>({phase:t.phase,pct:100/d.length,duration:0})):d.map(t=>({phase:t.phase,pct:(t.duration_ms||0)/e*100,duration:t.duration_ms||0}))}function Nt(d){return d==null?"--":d>=1e6?(d/1e6).toFixed(1)+"M":d>=1e3?(d/1e3).toFixed(1)+"K":String(d)}var ve=class extends g{static get observedAttributes(){return["run-id","api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._timeline=null,this._pollInterval=null,this._selectedPhase=null,this._cycleHistory=[]}get runId(){let e=this.getAttribute("run-id");return e?parseInt(e,10):null}set runId(e){e!=null?this.setAttribute("run-id",String(e)):this.removeAttribute("run-id")}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="run-id"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){let e=this.runId;if(e==null){this._timeline=null,this.render();return}try{this._loading=!0;let t=await this._api._get(`/api/v2/runs/${e}/timeline`);this._timeline=t,this._cycleHistory=t.history||[],this._error=null}catch(t){t.message&&(t.message.includes("404")||t.message.includes("Not Found"))?(this._timeline=null,this._error=null):this._error=`Failed to load timeline: ${t.message}`}finally{this._loading=!1}this.render()}_selectPhase(e){this._selectedPhase=this._selectedPhase===e?null:e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".phase-segment-interactive").forEach(t=>{t.addEventListener("click",()=>{this._selectPhase(t.dataset.phase)})}),e.querySelectorAll(".legend-item-interactive").forEach(t=>{t.addEventListener("click",()=>{this._selectPhase(t.dataset.phase)})}),e.querySelectorAll(".close-detail").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this._selectedPhase=null,this.render()})})}_getStyles(){return`
|
|
11267
11293
|
:host {
|
|
11268
11294
|
display: block;
|
|
11269
11295
|
}
|
|
@@ -11548,12 +11574,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11548
11574
|
color: var(--loki-text-muted, #939084);
|
|
11549
11575
|
font-size: 13px;
|
|
11550
11576
|
}
|
|
11551
|
-
`}_renderPlaceholderTimeline(){let e=
|
|
11577
|
+
`}_renderPlaceholderTimeline(){let e=Ke.map(i=>{let a=q[i];return`<div class="phase-segment-interactive"
|
|
11552
11578
|
data-phase="${i}"
|
|
11553
11579
|
style="width: 25%; background: ${a.color}; opacity: 0.3;"
|
|
11554
11580
|
title="${a.label}: awaiting data">
|
|
11555
11581
|
${a.label}
|
|
11556
|
-
</div>`}).join(""),t=
|
|
11582
|
+
</div>`}).join(""),t=Ke.map(i=>{let a=q[i];return`<div class="legend-item-interactive" data-phase="${i}">
|
|
11557
11583
|
<span class="legend-dot" style="background: ${a.color}; opacity: 0.4;"></span>
|
|
11558
11584
|
<span class="legend-label">${a.label}</span>
|
|
11559
11585
|
<span class="legend-duration">--</span>
|
|
@@ -11565,7 +11591,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11565
11591
|
Each step fills in as your build progresses
|
|
11566
11592
|
</div>
|
|
11567
11593
|
</div>
|
|
11568
|
-
`}_renderPhaseDetail(e){let t=
|
|
11594
|
+
`}_renderPhaseDetail(e){let t=q[e];if(!t)return"";let a=(this._timeline?.phases||[]).find(s=>s.phase===e);return`
|
|
11569
11595
|
<div class="phase-detail">
|
|
11570
11596
|
<div class="detail-header">
|
|
11571
11597
|
<div class="detail-title">
|
|
@@ -11578,11 +11604,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11578
11604
|
<div class="detail-metrics">
|
|
11579
11605
|
<div class="detail-metric">
|
|
11580
11606
|
<span class="detail-metric-label">Time Spent</span>
|
|
11581
|
-
<span class="detail-metric-value">${
|
|
11607
|
+
<span class="detail-metric-value">${Ne(a?.duration_ms)}</span>
|
|
11582
11608
|
</div>
|
|
11583
11609
|
<div class="detail-metric">
|
|
11584
11610
|
<span class="detail-metric-label">Tokens Used</span>
|
|
11585
|
-
<span class="detail-metric-value">${
|
|
11611
|
+
<span class="detail-metric-value">${Nt(a?.tokens_used)}</span>
|
|
11586
11612
|
</div>
|
|
11587
11613
|
<div class="detail-metric">
|
|
11588
11614
|
<span class="detail-metric-label">Quality</span>
|
|
@@ -11594,22 +11620,22 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11594
11620
|
</div>
|
|
11595
11621
|
</div>
|
|
11596
11622
|
</div>
|
|
11597
|
-
`}_renderCycleHistory(){if(this._cycleHistory.length===0)return"";let t=this._cycleHistory.slice(-8).map((i,a)=>`<div class="history-cycle">${
|
|
11598
|
-
title="Cycle ${a+1}: ${n.label} - ${
|
|
11623
|
+
`}_renderCycleHistory(){if(this._cycleHistory.length===0)return"";let t=this._cycleHistory.slice(-8).map((i,a)=>`<div class="history-cycle">${Ke.map(r=>{let o=i.phases?.find(p=>p.phase===r),n=q[r],l=o?.status||"pending",c=l==="complete"?"0.8":l==="active"?"1":"0.3";return`<div class="history-dot" style="background: ${n.color}; opacity: ${c};"
|
|
11624
|
+
title="Cycle ${a+1}: ${n.label} - ${Ne(o?.duration_ms)}"></div>`}).join("")}</div>`).join('<div class="history-separator"></div>');return`
|
|
11599
11625
|
<div class="cycle-history">
|
|
11600
11626
|
<div class="history-label">Past Cycles (${this._cycleHistory.length} total)</div>
|
|
11601
11627
|
<div class="history-cycles">${t}</div>
|
|
11602
11628
|
</div>
|
|
11603
|
-
`}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let e=this.shadowRoot;if(!e)return;let t=this.runId,i=this._timeline,a=i?.phases||[],s=i?.current_phase||null,r=
|
|
11629
|
+
`}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let e=this.shadowRoot;if(!e)return;let t=this.runId,i=this._timeline,a=i?.phases||[],s=i?.current_phase||null,r=Ot(a),o;if(this._loading&&!i)o='<div class="loading">Loading timeline...</div>';else if(t==null)o=this._renderPlaceholderTimeline();else if(a.length===0)o=this._renderPlaceholderTimeline();else{let n=r.map(h=>{let v=q[h.phase]||{color:"var(--loki-text-muted)",label:h.phase},u=s===h.phase,x=this._selectedPhase===h.phase;return`<div class="phase-segment-interactive ${u?"current":""} ${x?"selected":""}"
|
|
11604
11630
|
data-phase="${h.phase}"
|
|
11605
|
-
style="width: ${Math.max(h.pct,2)}%; background: ${
|
|
11606
|
-
title="${
|
|
11607
|
-
${h.pct>12?
|
|
11608
|
-
</div>`}).join(""),l=a.map(h=>{let
|
|
11609
|
-
<span class="legend-dot" style="background: ${
|
|
11610
|
-
<span class="legend-label">${
|
|
11611
|
-
<span class="legend-duration">${
|
|
11612
|
-
${
|
|
11631
|
+
style="width: ${Math.max(h.pct,2)}%; background: ${v.color};"
|
|
11632
|
+
title="${v.label}: ${Ne(h.duration)}">
|
|
11633
|
+
${h.pct>12?v.label:""}
|
|
11634
|
+
</div>`}).join(""),l=a.map(h=>{let v=q[h.phase]||{color:"var(--loki-text-muted)",label:h.phase},u=s===h.phase;return`<div class="legend-item-interactive ${this._selectedPhase===h.phase?"selected":""}" data-phase="${h.phase}">
|
|
11635
|
+
<span class="legend-dot" style="background: ${v.color}"></span>
|
|
11636
|
+
<span class="legend-label">${v.label}</span>
|
|
11637
|
+
<span class="legend-duration">${Ne(h.duration_ms)}</span>
|
|
11638
|
+
${u?'<span class="phase-current-tag">ACTIVE</span>':""}
|
|
11613
11639
|
</div>`}).join(""),c=this._selectedPhase?this._renderPhaseDetail(this._selectedPhase):"",p=this._renderCycleHistory();o=`
|
|
11614
11640
|
<div class="timeline-bar">${n}</div>
|
|
11615
11641
|
<div class="legend">${l}</div>
|
|
@@ -11625,7 +11651,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11625
11651
|
${o}
|
|
11626
11652
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11627
11653
|
</div>
|
|
11628
|
-
`,this._bindEvents()}};customElements.get("loki-rarv-timeline")||customElements.define("loki-rarv-timeline",
|
|
11654
|
+
`,this._bindEvents()}};customElements.get("loki-rarv-timeline")||customElements.define("loki-rarv-timeline",ve);var ht={running:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"Running"},completed:{color:"var(--loki-blue, #3b82f6)",bg:"var(--loki-blue-muted, rgba(59, 130, 246, 0.15))",label:"Completed"},failed:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"Failed"},cancelled:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"Cancelled"},pending:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Pending"},queued:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Queued"}};function qt(d,e,t){let i=d;if(i==null&&e){let l=new Date(e).getTime();i=(t?new Date(t).getTime():Date.now())-l}if(i==null||i<0)return"--";if(i<1e3)return`${i}ms`;let a=Math.floor(i/1e3);if(a<60)return`${a}s`;let s=Math.floor(a/60),r=a%60;if(s<60)return`${s}m ${r}s`;let o=Math.floor(s/60),n=s%60;return`${o}h ${n}m`}function Jt(d){if(!d)return"--";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return String(d)}}var fe=class extends g{static get observedAttributes(){return["api-url","project-id","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._runs=[],this._pollInterval=null,this._lastDataHash=null}get projectId(){let e=this.getAttribute("project-id");return e?parseInt(e,10):null}set projectId(e){e!=null?this.setAttribute("project-id",String(e)):this.removeAttribute("project-id")}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="project-id"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=this.projectId,t=e!=null?`?project_id=${e}`:"",i=await this._api._get(`/api/v2/runs${t}`),a=i?.runs||i||[],s=JSON.stringify(a);if(s===this._lastDataHash)return;this._lastDataHash=s,this._runs=Array.isArray(a)?a:[],this._error=null}catch(e){this._error||(this._error=`Failed to load runs: ${e.message}`)}finally{this._loading=!1}this.render()}async _cancelRun(e){try{await this._api._post(`/api/v2/runs/${e}/cancel`),await this._loadData()}catch(t){this._error=`Cancel failed: ${t.message}`,this.render()}}async _replayRun(e){try{await this._api._post(`/api/v2/runs/${e}/replay`),await this._loadData()}catch(t){this._error=`Replay failed: ${t.message}`,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11629
11655
|
:host {
|
|
11630
11656
|
display: block;
|
|
11631
11657
|
}
|
|
@@ -11778,13 +11804,13 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11778
11804
|
color: var(--loki-text-muted, #939084);
|
|
11779
11805
|
margin-bottom: 8px;
|
|
11780
11806
|
}
|
|
11781
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading runs...</div>';else if(t.length===0)i='<div class="empty-state">No runs found.</div>';else{let a=t.map(s=>{let r=(s.status||"pending").toLowerCase(),o=
|
|
11807
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading runs...</div>';else if(t.length===0)i='<div class="empty-state">No runs found.</div>';else{let a=t.map(s=>{let r=(s.status||"pending").toLowerCase(),o=ht[r]||ht.pending,n=r==="running",l=r==="completed"||r==="failed"||r==="cancelled",c=qt(s.duration_ms,s.started_at,s.ended_at);return`
|
|
11782
11808
|
<tr>
|
|
11783
11809
|
<td><span class="run-id">#${s.id}</span></td>
|
|
11784
11810
|
<td>${this._escapeHtml(s.project_name||s.project||(s.project_id?`Project #${s.project_id}`:"--"))}</td>
|
|
11785
11811
|
<td><span class="status-badge" style="background: ${o.bg}; color: ${o.color};">${o.label}</span></td>
|
|
11786
11812
|
<td>${this._escapeHtml(s.trigger||s.trigger_type||"--")}</td>
|
|
11787
|
-
<td>${
|
|
11813
|
+
<td>${Jt(s.started_at)}</td>
|
|
11788
11814
|
<td>${c}</td>
|
|
11789
11815
|
<td>
|
|
11790
11816
|
<div class="actions-cell">
|
|
@@ -11821,7 +11847,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11821
11847
|
${i}
|
|
11822
11848
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11823
11849
|
</div>
|
|
11824
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadData()),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.runId))}),e.querySelectorAll('[data-action="replay"]').forEach(i=>{i.addEventListener("click",()=>this._replayRun(i.dataset.runId))})}};customElements.get("loki-run-manager")||customElements.define("loki-run-manager",
|
|
11850
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadData()),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.runId))}),e.querySelectorAll('[data-action="replay"]').forEach(i=>{i.addEventListener("click",()=>this._replayRun(i.dataset.runId))})}};customElements.get("loki-run-manager")||customElements.define("loki-run-manager",fe);var ut={running:{color:"var(--loki-green, #22c55e)",bg:"var(--loki-green-muted, rgba(34, 197, 94, 0.15))",label:"Running"},stopped:{color:"var(--loki-yellow, #eab308)",bg:"var(--loki-yellow-muted, rgba(234, 179, 8, 0.15))",label:"Stopped"},active:{color:"var(--loki-blue, #3b82f6)",bg:"var(--loki-blue-muted, rgba(59, 130, 246, 0.15))",label:"Idle"},missing:{color:"var(--loki-red, #ef4444)",bg:"var(--loki-red-muted, rgba(239, 68, 68, 0.15))",label:"Missing"},unknown:{color:"var(--loki-text-muted, #939084)",bg:"var(--loki-bg-tertiary, #ECEAE3)",label:"Unknown"}};function Gt(d){if(d==null||d<0)return"--";if(d<60)return`${d}s`;let e=Math.floor(d/60),t=d%60;if(e<60)return`${e}m ${t}s`;let i=Math.floor(e/60),a=e%60;return`${i}h ${a}m`}function gt(d){return d==null||isNaN(d)?"$0.00":`$${Number(d).toFixed(2)}`}var be=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!0,this._error=null,this._api=null,this._runs=[],this._summary=null,this._pollInterval=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let[e,t]=await Promise.all([this._api._get("/api/fleet/runs"),this._api._get("/api/fleet/summary")]),i=Array.isArray(e)?e:e?.runs||[],a=JSON.stringify({runs:i,summaryResp:t});if(a===this._lastDataHash)return;this._lastDataHash=a,this._runs=Array.isArray(i)?i:[],this._summary=t||null,this._error=null}catch(e){this._error||(this._error=`Failed to load fleet: ${e.message}`)}finally{this._loading=!1}this.render()}async _cancelRun(e){if(e&&!(typeof confirm=="function"&&!confirm(`Cancel build "${e}"? This stops the running build.`)))try{await this._api._post(`/api/fleet/runs/${encodeURIComponent(e)}/cancel`),this._lastDataHash=null,await this._loadData()}catch(t){this._error=`Cancel failed: ${t.message}`,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11825
11851
|
:host { display: block; }
|
|
11826
11852
|
|
|
11827
11853
|
.fleet {
|
|
@@ -11989,10 +12015,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
11989
12015
|
</div>
|
|
11990
12016
|
<div class="summary-card">
|
|
11991
12017
|
<div class="summary-label">Total Cost</div>
|
|
11992
|
-
<div class="summary-value">${
|
|
12018
|
+
<div class="summary-value">${gt(e.total_cost_usd)}</div>
|
|
11993
12019
|
</div>
|
|
11994
12020
|
</div>
|
|
11995
|
-
`:""}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading fleet...</div>';else if(t.length===0)i='<div class="empty-state">No registered builds. Run <code>loki start</code> in a project to populate the fleet.</div>';else{let a=t.map(s=>{let r=(s.status||"unknown").toLowerCase(),o=
|
|
12021
|
+
`:""}render(){let e=this.shadowRoot;if(!e)return;let t=this._runs,i;if(this._loading&&t.length===0)i='<div class="loading">Loading fleet...</div>';else if(t.length===0)i='<div class="empty-state">No registered builds. Run <code>loki start</code> in a project to populate the fleet.</div>';else{let a=t.map(s=>{let r=(s.status||"unknown").toLowerCase(),o=ut[r]||ut.unknown,n=s.running===!0,l=Gt(s.duration_seconds),c=s.iteration!=null?s.iteration:0,p=s.phase?this._escapeHtml(s.phase):"--";return`
|
|
11996
12022
|
<tr>
|
|
11997
12023
|
<td>
|
|
11998
12024
|
<div class="project-name">${this._escapeHtml(s.name||"project")}</div>
|
|
@@ -12001,7 +12027,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12001
12027
|
<td><span class="status-badge" style="background: ${o.bg}; color: ${o.color};">${o.label}</span></td>
|
|
12002
12028
|
<td>${p}</td>
|
|
12003
12029
|
<td>${c}</td>
|
|
12004
|
-
<td class="cost-cell">${
|
|
12030
|
+
<td class="cost-cell">${gt(s.cost_usd)}</td>
|
|
12005
12031
|
<td>${l}</td>
|
|
12006
12032
|
<td>
|
|
12007
12033
|
${n?`<button class="btn btn-cancel" data-action="cancel" data-id="${this._escapeHtml(s.id||s.path||"")}">Cancel</button>`:""}
|
|
@@ -12041,7 +12067,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12041
12067
|
${i}
|
|
12042
12068
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
12043
12069
|
</div>
|
|
12044
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>{this._lastDataHash=null,this._loadData()}),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.id))})}};customElements.get("loki-fleet")||customElements.define("loki-fleet",
|
|
12070
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("refresh-btn");t&&t.addEventListener("click",()=>{this._lastDataHash=null,this._loadData()}),e.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.id))})}};customElements.get("loki-fleet")||customElements.define("loki-fleet",be);function Kt(d){if(!d)return"--";try{return new Date(d).toLocaleString([],{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return String(d)}}function Vt(d){let e=new URLSearchParams;for(let[i,a]of Object.entries(d))a!=null&&a!==""&&e.set(i,String(a));let t=e.toString();return t?`?${t}`:""}var ke=class extends g{static get observedAttributes(){return["api-url","limit","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._entries=[],this._verifyResult=null,this._verifying=!1,this._filters={action:"",resource:"",dateFrom:"",dateTo:""}}get limit(){let e=this.getAttribute("limit");return e?parseInt(e,10):50}set limit(e){this.setAttribute("limit",String(e))}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData()}disconnectedCallback(){super.disconnectedCallback()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="limit"&&this._loadData(),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._loading=!0,this.render();let e={limit:this.limit,action:this._filters.action,resource:this._filters.resource,date_from:this._filters.dateFrom,date_to:this._filters.dateTo},t=Vt(e),i=await this._api._get(`/api/v2/audit${t}`);this._entries=i?.entries||i||[],this._error=null}catch(e){this._error=`Failed to load audit log: ${e.message}`}finally{this._loading=!1}this.render()}async _verifyIntegrity(){try{this._verifying=!0,this._verifyResult=null,this.render();let e=await this._api._get("/api/v2/audit/verify");this._verifyResult=e}catch(e){this._verifyResult={valid:!1,error:e.message}}finally{this._verifying=!1}this.render()}_onFilterChange(e,t){this._filters[e]=t,this._loadData()}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
12045
12071
|
:host {
|
|
12046
12072
|
display: block;
|
|
12047
12073
|
}
|
|
@@ -12261,7 +12287,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12261
12287
|
</div>
|
|
12262
12288
|
`}let a;if(this._loading&&t.length===0)a='<div class="loading">Loading audit log...</div>';else if(t.length===0)a='<div class="empty-state">No audit entries found matching filters.</div>';else{let s=t.map(r=>`
|
|
12263
12289
|
<tr>
|
|
12264
|
-
<td>${
|
|
12290
|
+
<td>${Kt(r.timestamp)}</td>
|
|
12265
12291
|
<td>${this._escapeHtml(r.action||"--")}</td>
|
|
12266
12292
|
<td>${this._escapeHtml(r.resource||r.resource_type||"--")}</td>
|
|
12267
12293
|
<td>${this._escapeHtml(r.user||r.actor||"--")}</td>
|
|
@@ -12325,7 +12351,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12325
12351
|
${a}
|
|
12326
12352
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
12327
12353
|
</div>
|
|
12328
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("verify-btn");t&&t.addEventListener("click",()=>this._verifyIntegrity());let i=e.getElementById("refresh-btn");i&&i.addEventListener("click",()=>this._loadData());let a=e.getElementById("filter-action");a&&a.addEventListener("change",n=>this._onFilterChange("action",n.target.value));let s=e.getElementById("filter-resource");s&&s.addEventListener("change",n=>this._onFilterChange("resource",n.target.value));let r=e.getElementById("filter-date-from");r&&r.addEventListener("change",n=>this._onFilterChange("dateFrom",n.target.value));let o=e.getElementById("filter-date-to");o&&o.addEventListener("change",n=>this._onFilterChange("dateTo",n.target.value))}};customElements.get("loki-audit-viewer")||customElements.define("loki-audit-viewer",
|
|
12354
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("verify-btn");t&&t.addEventListener("click",()=>this._verifyIntegrity());let i=e.getElementById("refresh-btn");i&&i.addEventListener("click",()=>this._loadData());let a=e.getElementById("filter-action");a&&a.addEventListener("change",n=>this._onFilterChange("action",n.target.value));let s=e.getElementById("filter-resource");s&&s.addEventListener("change",n=>this._onFilterChange("resource",n.target.value));let r=e.getElementById("filter-date-from");r&&r.addEventListener("change",n=>this._onFilterChange("dateFrom",n.target.value));let o=e.getElementById("filter-date-to");o&&o.addEventListener("change",n=>this._onFilterChange("dateTo",n.target.value))}};customElements.get("loki-audit-viewer")||customElements.define("loki-audit-viewer",ke);function mt(d){if(!d)return"Never";try{return new Date(d).toLocaleString([],{month:"short",day:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return String(d)}}var xe=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._keys=[],this._showCreateForm=!1,this._newToken=null,this._confirmDeleteId=null,this._rotateKeyId=null,this._rotateGracePeriod="24",this._createName="",this._createRole="read",this._createExpiration=""}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData()}disconnectedCallback(){super.disconnectedCallback()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._loading=!0,this.render();let e=await this._api._get("/api/v2/api-keys");this._keys=Array.isArray(e)?e:e?.keys||[],this._error=null}catch(e){this._error=`Failed to load API keys: ${e.message}`}finally{this._loading=!1}this.render()}async _createKey(){if(!this._createName.trim()){this._error="Key name is required.",this.render();return}try{let e={name:this._createName.trim(),role:this._createRole};this._createExpiration&&(e.expiration=this._createExpiration);let t=await this._api._post("/api/v2/api-keys",e);this._newToken=t?.token||t?.key||null,this._showCreateForm=!1,this._createName="",this._createRole="read",this._createExpiration="",this._error=null,await this._loadData()}catch(e){this._error=`Create failed: ${e.message}`,this.render()}}async _rotateKey(e){try{let t={grace_period_hours:parseInt(this._rotateGracePeriod,10)||24},i=await this._api._post(`/api/v2/api-keys/${e}/rotate`,t);this._newToken=i?.token||i?.key||null,this._rotateKeyId=null,this._error=null,await this._loadData()}catch(t){this._error=`Rotate failed: ${t.message}`,this.render()}}async _deleteKey(e){try{await this._api._delete(`/api/v2/api-keys/${e}`),this._confirmDeleteId=null,this._error=null,await this._loadData()}catch(t){this._error=`Delete failed: ${t.message}`,this._confirmDeleteId=null,this.render()}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
12329
12355
|
:host {
|
|
12330
12356
|
display: block;
|
|
12331
12357
|
}
|
|
@@ -12680,13 +12706,13 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12680
12706
|
<th>Actions</th>
|
|
12681
12707
|
</tr>
|
|
12682
12708
|
</thead>
|
|
12683
|
-
<tbody>${t.map(o=>{let n=o.id||o.key_id,l=(o.status||"active").toLowerCase(),c=l==="active"?"key-status-active":l==="expired"?"key-status-expired":"key-status-revoked",p=this._confirmDeleteId===n,h=this._rotateKeyId===n,
|
|
12709
|
+
<tbody>${t.map(o=>{let n=o.id||o.key_id,l=(o.status||"active").toLowerCase(),c=l==="active"?"key-status-active":l==="expired"?"key-status-expired":"key-status-revoked",p=this._confirmDeleteId===n,h=this._rotateKeyId===n,v;return p?v=`
|
|
12684
12710
|
<div class="confirm-delete">
|
|
12685
12711
|
<span>Delete this key?</span>
|
|
12686
12712
|
<button class="btn btn-sm btn-danger" data-action="confirm-delete" data-key-id="${n}">Yes</button>
|
|
12687
12713
|
<button class="btn btn-sm" data-action="cancel-delete">No</button>
|
|
12688
12714
|
</div>
|
|
12689
|
-
`:
|
|
12715
|
+
`:v=`
|
|
12690
12716
|
<div class="action-row">
|
|
12691
12717
|
<button class="btn btn-sm btn-warn" data-action="rotate" data-key-id="${n}">Rotate</button>
|
|
12692
12718
|
<button class="btn btn-sm btn-danger" data-action="delete" data-key-id="${n}">Delete</button>
|
|
@@ -12704,10 +12730,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12704
12730
|
<tr>
|
|
12705
12731
|
<td><span class="key-name">${this._escapeHtml(o.name||"Unnamed")}</span></td>
|
|
12706
12732
|
<td><span class="key-role">${this._escapeHtml(o.role||o.scopes||"--")}</span></td>
|
|
12707
|
-
<td>${
|
|
12708
|
-
<td>${
|
|
12733
|
+
<td>${mt(o.created_at||o.created)}</td>
|
|
12734
|
+
<td>${mt(o.last_used_at||o.last_used)}</td>
|
|
12709
12735
|
<td><span class="${c}">${this._escapeHtml(l)}</span></td>
|
|
12710
|
-
<td><div class="actions-cell">${
|
|
12736
|
+
<td><div class="actions-cell">${v}</div></td>
|
|
12711
12737
|
</tr>
|
|
12712
12738
|
`}).join("")}</tbody>
|
|
12713
12739
|
</table>
|
|
@@ -12724,7 +12750,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12724
12750
|
${s}
|
|
12725
12751
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
12726
12752
|
</div>
|
|
12727
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("show-create");t&&t.addEventListener("click",()=>{this._showCreateForm=!0,this.render()});let i=e.getElementById("dismiss-token");i&&i.addEventListener("click",()=>{this._newToken=null,this.render()});let a=e.getElementById("submit-create");a&&a.addEventListener("click",()=>{let r=e.getElementById("create-name"),o=e.getElementById("create-role"),n=e.getElementById("create-expiration");this._createName=r?.value||"",this._createRole=o?.value||"read",this._createExpiration=n?.value||"",this._createKey()});let s=e.getElementById("cancel-create");s&&s.addEventListener("click",()=>{this._showCreateForm=!1,this.render()}),e.querySelectorAll('[data-action="delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._deleteKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=null,this.render()})}),e.querySelectorAll('[data-action="rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-rotate"]').forEach(r=>{r.addEventListener("click",()=>{let o=e.getElementById(`rotate-grace-${r.dataset.keyId}`);this._rotateGracePeriod=o?.value||"24",this._rotateKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=null,this.render()})})}};customElements.get("loki-api-keys")||customElements.define("loki-api-keys",
|
|
12753
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("show-create");t&&t.addEventListener("click",()=>{this._showCreateForm=!0,this.render()});let i=e.getElementById("dismiss-token");i&&i.addEventListener("click",()=>{this._newToken=null,this.render()});let a=e.getElementById("submit-create");a&&a.addEventListener("click",()=>{let r=e.getElementById("create-name"),o=e.getElementById("create-role"),n=e.getElementById("create-expiration");this._createName=r?.value||"",this._createRole=o?.value||"read",this._createExpiration=n?.value||"",this._createKey()});let s=e.getElementById("cancel-create");s&&s.addEventListener("click",()=>{this._showCreateForm=!1,this.render()}),e.querySelectorAll('[data-action="delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._deleteKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=null,this.render()})}),e.querySelectorAll('[data-action="rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=r.dataset.keyId,this.render()})}),e.querySelectorAll('[data-action="confirm-rotate"]').forEach(r=>{r.addEventListener("click",()=>{let o=e.getElementById(`rotate-grace-${r.dataset.keyId}`);this._rotateGracePeriod=o?.value||"24",this._rotateKey(r.dataset.keyId)})}),e.querySelectorAll('[data-action="cancel-rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=null,this.render()})})}};customElements.get("loki-api-keys")||customElements.define("loki-api-keys",xe);function Wt(d){return d?d.slug&&d.name?`${d.name} (${d.slug})`:d.name||d.slug||"Unknown":"Unknown"}var _e=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._tenants=[],this._selectedTenantId=null,this._dropdownOpen=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._outsideClickHandler=e=>{this._dropdownOpen&&!this.contains(e.target)&&(this._dropdownOpen=!1,this.render())},document.addEventListener("click",this._outsideClickHandler)}disconnectedCallback(){super.disconnectedCallback(),this._outsideClickHandler&&(document.removeEventListener("click",this._outsideClickHandler),this._outsideClickHandler=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _loadData(){try{this._loading=!0;let e=await this._api._get("/api/v2/tenants");this._tenants=Array.isArray(e)?e:e?.tenants||[],this._error=null}catch(e){this._error=`Failed to load tenants: ${e.message}`}finally{this._loading=!1}this.render()}_toggleDropdown(){this._dropdownOpen=!this._dropdownOpen,this.render()}_selectTenant(e,t){this._selectedTenantId=e,this._dropdownOpen=!1,this.render(),this.dispatchEvent(new CustomEvent("tenant-changed",{detail:{tenantId:e,tenantName:t},bubbles:!0,composed:!0}))}_getSelectedTenant(){return this._selectedTenantId==null?null:this._tenants.find(e=>(e.id||e.slug)===this._selectedTenantId)||null}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
12728
12754
|
:host {
|
|
12729
12755
|
display: inline-block;
|
|
12730
12756
|
position: relative;
|
|
@@ -12858,7 +12884,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12858
12884
|
color: var(--loki-text-muted, #939084);
|
|
12859
12885
|
font-size: 12px;
|
|
12860
12886
|
}
|
|
12861
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getSelectedTenant(),i=t?
|
|
12887
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getSelectedTenant(),i=t?Wt(t):"All Tenants",a=this._dropdownOpen,s="";if(a){let r;if(this._loading)r='<div class="loading-text">Loading tenants...</div>';else if(this._error)r=`<div class="error-text">${this._escapeHtml(this._error)}</div>`;else{let o=this._selectedTenantId==null;r=`
|
|
12862
12888
|
<button class="dropdown-item all-tenants ${o?"selected":""}" data-tenant-id="">
|
|
12863
12889
|
<span class="tenant-name">All Tenants</span>
|
|
12864
12890
|
${o?'<span class="check-mark">*</span>':""}
|
|
@@ -12883,7 +12909,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
12883
12909
|
</button>
|
|
12884
12910
|
${s}
|
|
12885
12911
|
</div>
|
|
12886
|
-
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("trigger-btn");t&&t.addEventListener("click",i=>{i.stopPropagation(),this._toggleDropdown()}),e.querySelectorAll(".dropdown-item").forEach(i=>{i.addEventListener("click",a=>{a.stopPropagation();let s=i.dataset.tenantId||null,r=i.dataset.tenantName||null;this._selectTenant(s||null,r||"All Tenants")})})}};customElements.get("loki-tenant-switcher")||customElements.define("loki-tenant-switcher",
|
|
12912
|
+
`,this._attachEventListeners()}_attachEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.getElementById("trigger-btn");t&&t.addEventListener("click",i=>{i.stopPropagation(),this._toggleDropdown()}),e.querySelectorAll(".dropdown-item").forEach(i=>{i.addEventListener("click",a=>{a.stopPropagation();let s=i.dataset.tenantId||null,r=i.dataset.tenantName||null;this._selectTenant(s||null,r||"All Tenants")})})}};customElements.get("loki-tenant-switcher")||customElements.define("loki-tenant-switcher",_e);var Ve={info:{color:"var(--loki-blue, #2F71E3)",label:"INFO",icon:"i"},success:{color:"var(--loki-green, #1FC5A8)",label:"OK",icon:"+"},warning:{color:"var(--loki-yellow, #D4A03C)",label:"WARN",icon:"!"},error:{color:"var(--loki-red, #C45B5B)",label:"ERR",icon:"x"}},Yt=100,ye=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._items=[],this._filter="all",this._api=null,this._pollInterval=null,this._paused=!1,this._lastTimestamp=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:3e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/activity"),t=e.events||e.activities||[];if(t.length>0){let i=t.filter(a=>!this._lastTimestamp||new Date(a.timestamp)>new Date(this._lastTimestamp)).map(a=>({id:a.id||crypto.randomUUID(),timestamp:a.timestamp||new Date().toISOString(),message:a.message||a.description||"",severity:a.severity||a.level||"info",source:a.source||a.component||"",isNew:!0}));i.length>0&&(this._items=[...i,...this._items].slice(0,Yt),this._lastTimestamp=i[0].timestamp,setTimeout(()=>{this._items.forEach(a=>a.isNew=!1)},600))}}catch{this._items.length===0&&(this._items=this._getDemoItems())}this.render()}_getDemoItems(){let e=Date.now();return[{id:"1",timestamp:new Date(e-2e3).toISOString(),message:"Build iteration #12 started",severity:"info",source:"runner"},{id:"2",timestamp:new Date(e-5e3).toISOString(),message:"Code review passed (3/3 reviewers)",severity:"success",source:"review"},{id:"3",timestamp:new Date(e-8e3).toISOString(),message:"Context window at 78% capacity",severity:"warning",source:"context"},{id:"4",timestamp:new Date(e-12e3).toISOString(),message:"Test suite completed: 42/42 passed",severity:"success",source:"testing"},{id:"5",timestamp:new Date(e-15e3).toISOString(),message:"Verify step complete: changes checked",severity:"info",source:"rarv"}]}_formatTime(e){if(!e)return"";try{return new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return""}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getFilteredItems(){return this._filter==="all"?this._items:this._items.filter(e=>e.severity===this._filter)}_setFilter(e){this._filter=e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".filter-btn").forEach(i=>{i.addEventListener("click",()=>{this._setFilter(i.dataset.filter)})});let t=e.querySelector(".activity-feed");t&&(t.addEventListener("mouseenter",()=>{this._paused=!0}),t.addEventListener("mouseleave",()=>{this._paused=!1}))}_getStyles(){return`
|
|
12887
12913
|
:host {
|
|
12888
12914
|
display: block;
|
|
12889
12915
|
}
|
|
@@ -13069,7 +13095,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13069
13095
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary, #FFFEFB); }
|
|
13070
13096
|
::-webkit-scrollbar-thumb { background: var(--loki-border, #ECEAE3); border-radius: 3px; }
|
|
13071
13097
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light, #C5C0B1); }
|
|
13072
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getFilteredItems(),a=["all","info","success","warning","error"].map(r=>{let o=this._filter===r,n=r==="all"?"All":
|
|
13098
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=this._getFilteredItems(),a=["all","info","success","warning","error"].map(r=>{let o=this._filter===r,n=r==="all"?"All":Ve[r]?.label||r;return`<button class="filter-btn ${o?"active":""}" data-filter="${r}">${n}</button>`}).join(""),s;if(t.length===0?s='<div class="empty-state">No activity yet. Updates will stream here as your build runs.</div>':s=t.map(r=>{let o=Ve[r.severity]||Ve.info;return`
|
|
13073
13099
|
<div class="activity-item ${r.isNew?"new-item":""}">
|
|
13074
13100
|
<div class="severity-band" style="background: ${o.color};"></div>
|
|
13075
13101
|
<div class="item-content">
|
|
@@ -13090,7 +13116,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13090
13116
|
${s}
|
|
13091
13117
|
</div>
|
|
13092
13118
|
</div>
|
|
13093
|
-
`,this._bindEvents(),!this._paused){let r=e.querySelector(".activity-feed");r&&(r.scrollTop=0)}}};customElements.get("loki-activity-stream")||customElements.define("loki-activity-stream",
|
|
13119
|
+
`,this._bindEvents(),!this._paused){let r=e.querySelector(".activity-feed");r&&(r.scrollTop=0)}}};customElements.get("loki-activity-stream")||customElements.define("loki-activity-stream",ye);var Qt={claude:{initial:"C",color:"#553DE9",bgColor:"rgba(85, 61, 233, 0.12)"},codex:{initial:"X",color:"#1FC5A8",bgColor:"rgba(31, 197, 168, 0.12)"},cline:{initial:"L",color:"#D4A03C",bgColor:"rgba(212, 160, 60, 0.12)"},aider:{initial:"A",color:"#C45B5B",bgColor:"rgba(196, 91, 91, 0.12)"}},vt={healthy:"var(--loki-green, #1FC5A8)",degraded:"var(--loki-yellow, #D4A03C)",down:"var(--loki-red, #C45B5B)",unknown:"var(--loki-text-muted, #939084)"},we=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._providers=[],this._expandedProvider=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:1e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/providers/health");this._providers=e.providers||[]}catch{this._providers.length===0&&(this._providers=this._getDemoData())}this.render()}_getDemoData(){return[{name:"claude",status:"healthy",latency_ms:245,tokens_used:125400,model:"claude-opus-4-7",api_version:"v1",rate_limit:{remaining:45,limit:50},cost_usd:3.42},{name:"codex",status:"degraded",latency_ms:890,tokens_used:45200,model:"gpt-5.3-codex",api_version:"v1",rate_limit:{remaining:12,limit:60},cost_usd:.87},{name:"cline",status:"healthy",latency_ms:320,tokens_used:78600,model:"cline-default",api_version:"v1",rate_limit:{remaining:55,limit:60},cost_usd:1.15}]}_formatTokens(e){return e==null?"--":e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}_formatLatency(e){return e==null?"--":e<1e3?e+"ms":(e/1e3).toFixed(1)+"s"}_formatCost(e){return e==null?"--":"$"+e.toFixed(2)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleExpand(e){this._expandedProvider=this._expandedProvider===e?null:e,this.render()}_bindEvents(){this.shadowRoot.querySelectorAll(".provider-card").forEach(t=>{t.addEventListener("click",()=>{this._toggleExpand(t.dataset.provider)})})}_getStyles(){return`
|
|
13094
13120
|
:host {
|
|
13095
13121
|
display: block;
|
|
13096
13122
|
}
|
|
@@ -13269,7 +13295,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13269
13295
|
border: 1px solid var(--loki-border, #ECEAE3);
|
|
13270
13296
|
border-radius: 5px;
|
|
13271
13297
|
}
|
|
13272
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t;this._providers.length===0?t='<div class="empty-state">Provider status will appear once a build starts.</div>':t=`<div class="provider-grid">${this._providers.map(i=>{let a=
|
|
13298
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t;this._providers.length===0?t='<div class="empty-state">Provider status will appear once a build starts.</div>':t=`<div class="provider-grid">${this._providers.map(i=>{let a=Qt[i.name]||{initial:(i.name??"?").charAt(0).toUpperCase(),color:"#939084",bgColor:"rgba(147, 144, 132, 0.12)"},s=vt[i.status]||vt.unknown,r=this._expandedProvider===i.name,o=i.rate_limit?i.rate_limit.remaining/i.rate_limit.limit*100:100,n=o>50?"var(--loki-green)":o>20?"var(--loki-yellow)":"var(--loki-red)";return`
|
|
13273
13299
|
<div class="provider-card ${r?"expanded":""}" data-provider="${this._escapeHtml(i.name)}">
|
|
13274
13300
|
<div class="card-header">
|
|
13275
13301
|
<div class="provider-icon" style="background: ${a.bgColor}; color: ${a.color};">${a.initial}</div>
|
|
@@ -13321,7 +13347,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13321
13347
|
</div>
|
|
13322
13348
|
${t}
|
|
13323
13349
|
</div>
|
|
13324
|
-
`,this._bindEvents()}};customElements.get("loki-provider-health")||customElements.define("loki-provider-health",
|
|
13350
|
+
`,this._bindEvents()}};customElements.get("loki-provider-health")||customElements.define("loki-provider-health",we);var We=[{id:"planning",label:"Planning",icon:"P"},{id:"scaffolding",label:"Scaffolding",icon:"S"},{id:"implementation",label:"Implementation",icon:"I"},{id:"testing",label:"Testing",icon:"T"},{id:"review",label:"Review",icon:"R"},{id:"deploy",label:"Deploy",icon:"D"}],Ye={waiting:{color:"var(--loki-text-muted, #939084)",bgColor:"var(--loki-bg-tertiary, #ECEAE3)",label:"Waiting"},active:{color:"var(--loki-accent, #553DE9)",bgColor:"var(--loki-accent-muted, rgba(85, 61, 233, 0.10))",label:"Active"},complete:{color:"var(--loki-green, #1FC5A8)",bgColor:"var(--loki-green-muted, rgba(31, 197, 168, 0.12))",label:"Complete"},failed:{color:"var(--loki-red, #C45B5B)",bgColor:"var(--loki-red-muted, rgba(196, 91, 91, 0.12))",label:"Failed"}},$e=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._stages=[],this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:5e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/pipeline/status");this._stages=e.stages||[]}catch{this._stages.length===0&&(this._stages=this._getDemoData())}this.render()}_getDemoData(){return[{id:"planning",status:"complete",errors:0,duration_ms:12500},{id:"scaffolding",status:"complete",errors:0,duration_ms:8300},{id:"implementation",status:"active",errors:0,duration_ms:45e3},{id:"testing",status:"waiting",errors:0,duration_ms:null},{id:"review",status:"waiting",errors:0,duration_ms:null},{id:"deploy",status:"waiting",errors:0,duration_ms:null}]}_getStageData(e){return this._stages.find(t=>t.id===e)||{id:e,status:"waiting",errors:0}}_formatDuration(e){if(e==null||e<0)return"";if(e<1e3)return e+"ms";let t=Math.floor(e/1e3);if(t<60)return t+"s";let i=Math.floor(t/60),a=t%60;return i+"m "+a+"s"}_getStyles(){return`
|
|
13325
13351
|
:host {
|
|
13326
13352
|
display: block;
|
|
13327
13353
|
}
|
|
@@ -13484,7 +13510,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13484
13510
|
border-radius: 50%;
|
|
13485
13511
|
flex-shrink: 0;
|
|
13486
13512
|
}
|
|
13487
|
-
`}render(){let e=this.shadowRoot;if(!e)return;let t=
|
|
13513
|
+
`}render(){let e=this.shadowRoot;if(!e)return;let t=We.map((a,s)=>{let r=this._getStageData(a.id),o=Ye[r.status]||Ye.waiting,n=r.status==="complete",l=r.status==="active",c=r.status==="failed",p=n?'<span class="stage-check">✓</span>':c?'<span class="stage-check">✗</span>':a.icon,h=`
|
|
13488
13514
|
<div class="stage-node">
|
|
13489
13515
|
<div class="stage-circle ${l?"active":""}"
|
|
13490
13516
|
style="background: ${o.bgColor}; color: ${o.color}; border: 2px solid ${o.color};">
|
|
@@ -13494,12 +13520,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13494
13520
|
${r.duration_ms?`<span class="stage-duration">${this._formatDuration(r.duration_ms)}</span>`:""}
|
|
13495
13521
|
${r.errors>0?`<span class="stage-error-count">${r.errors} error${r.errors>1?"s":""}</span>`:""}
|
|
13496
13522
|
</div>
|
|
13497
|
-
`;if(s<
|
|
13523
|
+
`;if(s<We.length-1){let v=this._getStageData(We[s+1].id),u=n,x=l||n&&(v.status==="active"||v.status==="waiting");return h+`
|
|
13498
13524
|
<div class="connector">
|
|
13499
|
-
<div class="connector-line ${
|
|
13525
|
+
<div class="connector-line ${u?"completed":l?"active":"pending"}"></div>
|
|
13500
13526
|
${l?'<div class="flow-dot"></div>':""}
|
|
13501
13527
|
</div>
|
|
13502
|
-
`}return h}).join(""),i=Object.entries(
|
|
13528
|
+
`}return h}).join(""),i=Object.entries(Ye).map(([a,s])=>`<div class="legend-item">
|
|
13503
13529
|
<div class="legend-dot" style="background: ${s.color};"></div>
|
|
13504
13530
|
<span>${s.label}</span>
|
|
13505
13531
|
</div>`).join("");e.innerHTML=`
|
|
@@ -13515,7 +13541,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13515
13541
|
${i}
|
|
13516
13542
|
</div>
|
|
13517
13543
|
</div>
|
|
13518
|
-
`}};customElements.get("loki-pipeline-view")||customElements.define("loki-pipeline-view"
|
|
13544
|
+
`}};customElements.get("loki-pipeline-view")||customElements.define("loki-pipeline-view",$e);var Ee={episode:{color:"var(--loki-blue, #2F71E3)",shape:"circle",label:"Episode"},pattern:{color:"var(--loki-green, #1FC5A8)",shape:"square",label:"Pattern"},skill:{color:"var(--loki-purple, #553DE9)",shape:"diamond",label:"Skill"}};function Xt(d,e,t){let i=e/2,a=t/2,s=Math.min(i,a)*.65,r=d.length;return d.map((o,n)=>{let l=2*Math.PI*n/r-Math.PI/2,c=o.importance||.5,p=s*(.5+c*.5);return{...o,x:i+p*Math.cos(l),y:a+p*Math.sin(l)}})}var Ce=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._nodes=[],this._edges=[],this._selectedNode=null,this._api=null,this._pollInterval=null,this._graphWidth=600,this._graphHeight=400}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:15e3,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/memory/graph");this._nodes=e.nodes||[],this._edges=e.edges||[]}catch{if(this._nodes.length===0){let e=this._getDemoData();this._nodes=e.nodes,this._edges=e.edges}}this.render()}_getDemoData(){return{nodes:[{id:"ep1",type:"episode",label:"Build iteration #12",importance:.8,details:"Completed scaffolding and initial implementation"},{id:"ep2",type:"episode",label:"Code review #5",importance:.6,details:"Quality gate passed with 3/3 approval"},{id:"ep3",type:"episode",label:"Test failure #3",importance:.7,details:"Integration test timeout resolved"},{id:"pt1",type:"pattern",label:"Error recovery",importance:.9,details:"Retry with exponential backoff pattern"},{id:"pt2",type:"pattern",label:"API design",importance:.7,details:"REST endpoint naming conventions"},{id:"pt3",type:"pattern",label:"Test structure",importance:.5,details:"Arrange-Act-Assert with setup helpers"},{id:"sk1",type:"skill",label:"Playwright E2E",importance:.85,details:"Browser automation test writing"},{id:"sk2",type:"skill",label:"FastAPI routing",importance:.6,details:"Python API server development"}],edges:[{source:"ep1",target:"pt1",strength:.8},{source:"ep1",target:"sk1",strength:.6},{source:"ep2",target:"pt2",strength:.9},{source:"ep3",target:"pt1",strength:.7},{source:"ep3",target:"pt3",strength:.5},{source:"pt1",target:"sk2",strength:.4},{source:"pt2",target:"sk2",strength:.7},{source:"pt3",target:"sk1",strength:.6}]}}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_selectNode(e){this._selectedNode=this._selectedNode===e?null:e,this.render()}_bindEvents(){let e=this.shadowRoot;e.querySelectorAll(".graph-node").forEach(t=>{t.addEventListener("click",()=>{this._selectNode(t.dataset.nodeId)})}),e.querySelectorAll(".close-detail").forEach(t=>{t.addEventListener("click",()=>{this._selectedNode=null,this.render()})})}_renderNodeShape(e,t,i){let a=Ee[e.type]||Ee.episode,s=10+(e.importance||.5)*16,r=this._selectedNode===e.id,o=r?"var(--loki-accent, #553DE9)":a.color,n=r?3:1.5,l=this._selectedNode&&!r?.4:1,c;switch(a.shape){case"square":c=`<rect x="${t-s/2}" y="${i-s/2}" width="${s}" height="${s}"
|
|
13519
13545
|
rx="3" fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break;case"diamond":{let h=s/2;c=`<polygon points="${t},${i-h} ${t+h},${i} ${t},${i+h} ${t-h},${i}"
|
|
13520
13546
|
fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break}default:c=`<circle cx="${t}" cy="${i}" r="${s/2}" fill="${a.color}" fill-opacity="0.2"
|
|
13521
13547
|
stroke="${o}" stroke-width="${n}" opacity="${l}" />`}let p=`<text x="${t}" y="${i+s/2+14}" text-anchor="middle" font-size="10"
|
|
@@ -13676,7 +13702,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13676
13702
|
</div>
|
|
13677
13703
|
<div class="empty-state">No memory entries to visualize</div>
|
|
13678
13704
|
</div>
|
|
13679
|
-
`;return}let t=this._graphWidth,i=this._graphHeight,a=
|
|
13705
|
+
`;return}let t=this._graphWidth,i=this._graphHeight,a=Xt(this._nodes,t,i),s=this._edges.map(l=>this._renderEdge(l,a)).join(""),r=a.map(l=>this._renderNodeShape(l,l.x,l.y)).join(""),o="";if(this._selectedNode){let l=this._nodes.find(c=>c.id===this._selectedNode);if(l){let c=Ee[l.type]||Ee.episode;o=`
|
|
13680
13706
|
<div class="detail-panel">
|
|
13681
13707
|
<div class="detail-header">
|
|
13682
13708
|
<span class="detail-title">${this._escapeHtml(l.label)}</span>
|
|
@@ -13685,7 +13711,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13685
13711
|
</div>
|
|
13686
13712
|
<div class="detail-body">${this._escapeHtml(l.details||"No details available")}</div>
|
|
13687
13713
|
</div>
|
|
13688
|
-
`}}let n=Object.entries(
|
|
13714
|
+
`}}let n=Object.entries(Ee).map(([,l])=>{let c;return l.shape==="circle"?c=`<div class="legend-circle" style="border-color: ${l.color};"></div>`:l.shape==="square"?c=`<div class="legend-square" style="border-color: ${l.color};"></div>`:c=`<div class="legend-diamond" style="border-color: ${l.color};"></div>`,`<div class="legend-item">
|
|
13689
13715
|
<div class="legend-shape">${c}</div>
|
|
13690
13716
|
<span>${l.label}</span>
|
|
13691
13717
|
</div>`}).join("");e.innerHTML=`
|
|
@@ -13703,7 +13729,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13703
13729
|
</div>
|
|
13704
13730
|
<div class="legend">${n}</div>
|
|
13705
13731
|
</div>
|
|
13706
|
-
`,this._bindEvents()}};customElements.get("loki-memory-graph")||customElements.define("loki-memory-graph",
|
|
13732
|
+
`,this._bindEvents()}};customElements.get("loki-memory-graph")||customElements.define("loki-memory-graph",Ce);var Qe={planning:{color:"var(--loki-blue, #2F71E3)",label:"Planning"},building:{color:"var(--loki-green, #1FC5A8)",label:"Building"},implementation:{color:"var(--loki-green, #1FC5A8)",label:"Building"},testing:{color:"var(--loki-purple, #553DE9)",label:"Testing"},review:{color:"var(--loki-yellow, #D4A03C)",label:"Review"},overhead:{color:"var(--loki-text-muted, #939084)",label:"Overhead"}},Se=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._phases=[],this._budget=null,this._totalCost=0,this._hoveredPhase=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:1e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let e=await this._api._get("/api/v2/cost/breakdown");this._phases=e.phases||[],this._budget=e.budget_usd||null,this._totalCost=e.total_usd||this._phases.reduce((t,i)=>t+(i.cost_usd||0),0)}catch{this._phases.length===0&&(this._phases=this._getDemoData(),this._budget=10,this._totalCost=this._phases.reduce((e,t)=>e+t.cost_usd,0))}this.render()}_getDemoData(){return[{phase:"planning",cost_usd:.85,tokens:12400},{phase:"building",cost_usd:3.2,tokens:68500},{phase:"testing",cost_usd:1.45,tokens:31200},{phase:"review",cost_usd:.9,tokens:18800},{phase:"overhead",cost_usd:.35,tokens:5600}]}_formatCost(e){return e==null?"--":"$"+e.toFixed(2)}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_bindEvents(){this.shadowRoot.querySelectorAll(".waterfall-bar").forEach(t=>{t.addEventListener("mouseenter",()=>{this._hoveredPhase=t.dataset.phase,this._updateTooltip(t)}),t.addEventListener("mouseleave",()=>{this._hoveredPhase=null,this._hideTooltip()})})}_updateTooltip(e){let t=this.shadowRoot.querySelector(".tooltip");if(!t)return;let i=this._phases.find(o=>o.phase===this._hoveredPhase);if(!i)return;let a=Qe[i.phase]||{label:i.phase};t.innerHTML=`<strong>${a.label}</strong>: ${this._formatCost(i.cost_usd)}`,t.style.display="block";let s=e.getBoundingClientRect(),r=this.shadowRoot.querySelector(".chart-area").getBoundingClientRect();t.style.left=s.left-r.left+s.width/2+"px",t.style.top=s.top-r.top-30+"px"}_hideTooltip(){let e=this.shadowRoot.querySelector(".tooltip");e&&(e.style.display="none")}_getStyles(){return`
|
|
13707
13733
|
:host {
|
|
13708
13734
|
display: block;
|
|
13709
13735
|
}
|
|
@@ -13893,7 +13919,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13893
13919
|
</div>
|
|
13894
13920
|
<div class="empty-state">Cost details will appear once a build starts running.</div>
|
|
13895
13921
|
</div>
|
|
13896
|
-
`;return}let t=Math.max(...this._phases.map(l=>l.cost_usd||0),.01),i=160,a=this._budget?Math.max(t,this._budget):t,s=this._budget?this._budget/a*i:null,r=this._phases.map(l=>{let c=
|
|
13922
|
+
`;return}let t=Math.max(...this._phases.map(l=>l.cost_usd||0),.01),i=160,a=this._budget?Math.max(t,this._budget):t,s=this._budget?this._budget/a*i:null,r=this._phases.map(l=>{let c=Qe[l.phase]||{color:"var(--loki-text-muted)",label:l.phase},p=(l.cost_usd||0)/a*i,h=this._hoveredPhase===l.phase;return`
|
|
13897
13923
|
<div class="bar-group">
|
|
13898
13924
|
<span class="bar-value">${this._formatCost(l.cost_usd)}</span>
|
|
13899
13925
|
<div class="waterfall-bar" data-phase="${this._escapeHtml(l.phase)}"
|
|
@@ -13905,7 +13931,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13905
13931
|
<div class="budget-line" style="bottom: ${s+40}px;">
|
|
13906
13932
|
<span class="budget-label">Budget: ${this._formatCost(this._budget)}</span>
|
|
13907
13933
|
</div>
|
|
13908
|
-
`:"",n=this._phases.map(l=>{let c=
|
|
13934
|
+
`:"",n=this._phases.map(l=>{let c=Qe[l.phase]||{color:"var(--loki-text-muted)",label:l.phase},p=this._totalCost>0?(l.cost_usd/this._totalCost*100).toFixed(0):0;return`<div class="summary-item">
|
|
13909
13935
|
<div class="summary-dot" style="background: ${c.color};"></div>
|
|
13910
13936
|
<span class="summary-label">${c.label}</span>
|
|
13911
13937
|
<span class="summary-value">${this._formatCost(l.cost_usd)} (${p}%)</span>
|
|
@@ -13927,7 +13953,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
13927
13953
|
</div>
|
|
13928
13954
|
</div>
|
|
13929
13955
|
</div>
|
|
13930
|
-
`,this._bindEvents()}};customElements.get("loki-cost-waterfall")||customElements.define("loki-cost-waterfall",
|
|
13956
|
+
`,this._bindEvents()}};customElements.get("loki-cost-waterfall")||customElements.define("loki-cost-waterfall",Se);var Zt={1:{bg:"rgba(212, 160, 60, 0.15)",border:"#D4A03C",label:"1st"},2:{bg:"rgba(147, 144, 132, 0.15)",border:"#939084",label:"2nd"},3:{bg:"rgba(196, 130, 91, 0.15)",border:"#C4825B",label:"3rd"}},Ae=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._agents=[],this._expandedAgent=null,this._api=null,this._pollInterval=null,this._previousRanks={}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_startPolling(){this._poll=b({loadFn:()=>this._loadData(),intervalMs:1e4,element:this,immediate:!1})}_stopPolling(){this._poll&&(this._poll.stop(),this._poll=null)}async _loadData(){try{let t=(await this._api._get("/api/v2/agents/leaderboard")).agents||[],i={};t.forEach((a,s)=>{i[a.type||a.name]=s+1}),this._previousRanks={...this._currentRanks||{}},this._currentRanks=i,this._agents=t}catch{this._agents.length===0&&(this._agents=this._getDemoData(),this._currentRanks={},this._agents.forEach((e,t)=>{this._currentRanks[e.type]=t+1}),this._previousRanks={})}this.render()}_getDemoData(){return[{type:"code-generator",name:"Code Generator",tasks:24,quality:9.2,speed:"fast",cost_usd:2.4},{type:"test-writer",name:"Test Writer",tasks:18,quality:9,speed:"fast",cost_usd:1.2},{type:"code-reviewer",name:"Code Reviewer",tasks:15,quality:8.8,speed:"medium",cost_usd:1.8},{type:"architect",name:"Architect",tasks:8,quality:9.5,speed:"slow",cost_usd:3.1},{type:"debugger",name:"Debugger",tasks:12,quality:8.5,speed:"fast",cost_usd:.95},{type:"doc-writer",name:"Documentation",tasks:10,quality:8.3,speed:"fast",cost_usd:.6}]}_getRankChange(e){let t=this._currentRanks?.[e],i=this._previousRanks?.[e];return t==null||i==null?0:i-t}_escapeHtml(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleAgent(e){this._expandedAgent=this._expandedAgent===e?null:e,this.render()}_bindEvents(){this.shadowRoot.querySelectorAll(".agent-row").forEach(t=>{t.addEventListener("click",()=>{this._toggleAgent(t.dataset.agent)})})}_getQualityColor(e){return e>=9?"var(--loki-green, #1FC5A8)":e>=8?"var(--loki-blue, #2F71E3)":e>=7?"var(--loki-yellow, #D4A03C)":"var(--loki-red, #C45B5B)"}_getSpeedLabel(e){return e==="fast"?{label:"Fast",color:"var(--loki-green, #1FC5A8)"}:e==="medium"?{label:"Medium",color:"var(--loki-yellow, #D4A03C)"}:{label:"Slow",color:"var(--loki-red, #C45B5B)"}}_getStyles(){return`
|
|
13931
13957
|
:host {
|
|
13932
13958
|
display: block;
|
|
13933
13959
|
}
|
|
@@ -14140,7 +14166,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14140
14166
|
</div>
|
|
14141
14167
|
<div class="empty-state">No agent performance data available</div>
|
|
14142
14168
|
</div>
|
|
14143
|
-
`;return}let t=this._agents.map((i,a)=>{let s=a+1,r=
|
|
14169
|
+
`;return}let t=this._agents.map((i,a)=>{let s=a+1,r=Zt[s],o=i.type||i.name,n=this._getRankChange(o),l=this._expandedAgent===o,c=this._getQualityColor(i.quality),p=this._getSpeedLabel(i.speed),h=(i.quality||0)/10*100,v;r?v=`<div class="rank-badge" style="background: ${r.bg}; color: ${r.border};">${s}</div>`:v=`<span class="rank-number" style="color: var(--loki-text-muted);">${s}</span>`;let u="";n>0?u=`<span class="rank-change rank-up">+${n}</span>`:n<0&&(u=`<span class="rank-change rank-down">${n}</span>`);let x=l?`
|
|
14144
14170
|
<div class="agent-detail">
|
|
14145
14171
|
<div class="detail-metric">
|
|
14146
14172
|
<span class="detail-label">Total Cost</span>
|
|
@@ -14158,7 +14184,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14158
14184
|
`:"";return`
|
|
14159
14185
|
<div class="agent-row ${s<=3?"top-3":""}" data-agent="${this._escapeHtml(o)}"
|
|
14160
14186
|
style="${r?"border-left-color: "+r.border+";":""}">
|
|
14161
|
-
<div class="rank-cell">${
|
|
14187
|
+
<div class="rank-cell">${v}${u}</div>
|
|
14162
14188
|
<div class="agent-name-cell">
|
|
14163
14189
|
<span class="agent-name">${this._escapeHtml(i.name||i.type)}</span>
|
|
14164
14190
|
<span class="agent-type">${this._escapeHtml(i.type||"")}</span>
|
|
@@ -14193,7 +14219,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14193
14219
|
${t}
|
|
14194
14220
|
</div>
|
|
14195
14221
|
</div>
|
|
14196
|
-
`,this._bindEvents()}};customElements.get("loki-agent-leaderboard")||customElements.define("loki-agent-leaderboard",
|
|
14222
|
+
`,this._bindEvents()}};customElements.get("loki-agent-leaderboard")||customElements.define("loki-agent-leaderboard",Ae);var ft=50,Te=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._statusLoading=!1,this._statusError=null,this._status=null,this._eventsLoading=!1,this._eventsError=null,this._events=[],this._eventsSource=null,this._eventsCount=0,this._lookupId="",this._lookupLoading=!1,this._lookupError=null,this._lookupResult=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"api-url":this._api&&(this._api.baseUrl=i,this._loadStatus());break;case"theme":this._applyTheme(),this.render();break}}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_stopPolling(){}async _loadStatus(){this._statusLoading=!0,this._statusError=null,this.render();try{this._status=await this._api.get("/api/managed/status")}catch(e){this._statusError=e&&e.message?e.message:"Failed to load managed status",this._status=null}finally{this._statusLoading=!1}this._status&&this._status.enabled?await this._loadEvents():this.render()}async _loadEvents(e=ft){this._eventsLoading=!0,this._eventsError=null,this.render();try{let t=await this._api.get("/api/managed/events?limit="+encodeURIComponent(e));Array.isArray(t)?(this._events=t,this._eventsCount=t.length,this._eventsSource=null):t&&typeof t=="object"?(this._events=Array.isArray(t.events)?t.events:[],this._eventsCount=typeof t.count=="number"?t.count:this._events.length,this._eventsSource=t.source||null):(this._events=[],this._eventsCount=0,this._eventsSource=null)}catch(t){this._eventsError=t&&t.message?t.message:"Failed to load managed events",this._events=[],this._eventsCount=0,this._eventsSource=null}finally{this._eventsLoading=!1,this.render()}}async _lookupMemoryVersion(){let e=(this._lookupId||"").trim();if(!e){this._lookupError="Enter a memory ID to look up",this._lookupResult=null,this.render();return}this._lookupLoading=!0,this._lookupError=null,this._lookupResult=null,this.render();try{let t="/api/managed/memory_versions/"+encodeURIComponent(e);this._lookupResult=await this._api.get(t)}catch(t){this._lookupError=t&&t.message?t.message:"Failed to load memory versions",this._lookupResult=null}finally{this._lookupLoading=!1,this.render()}}_onLookupInput(e){this._lookupId=e&&e.target?e.target.value:""}_onLookupKeyDown(e){e&&e.key==="Enter"&&(e.preventDefault(),this._lookupMemoryVersion())}_attachEventHandlers(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector("#refresh-status-btn");t&&t.addEventListener("click",()=>this._loadStatus());let i=e.querySelector("#refresh-events-btn");i&&i.addEventListener("click",()=>this._loadEvents());let a=e.querySelector("#lookup-input");a&&(a.addEventListener("input",r=>this._onLookupInput(r)),a.addEventListener("keydown",r=>this._onLookupKeyDown(r)));let s=e.querySelector("#lookup-btn");s&&s.addEventListener("click",()=>this._lookupMemoryVersion())}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_formatTimestamp(e){if(!e)return"";let t;return typeof e=="number"?t=new Date(e>1e12?e:e*1e3):t=new Date(e),Number.isNaN(t.getTime())?String(e):t.toISOString().replace("T"," ").replace(/\.\d+Z$/,"Z")}_renderStatusSection(){if(this._statusLoading)return'<div class="status-row muted">Loading managed memory status...</div>';if(this._statusError)return`
|
|
14197
14223
|
<div class="error-banner" role="alert">
|
|
14198
14224
|
<strong>Status error:</strong>
|
|
14199
14225
|
<span>${this._escapeHtml(this._statusError)}</span>
|
|
@@ -14572,7 +14598,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14572
14598
|
${t?`
|
|
14573
14599
|
<div class="section">
|
|
14574
14600
|
<div class="panel-header">
|
|
14575
|
-
<h3 class="section-title">Recent events (limit ${
|
|
14601
|
+
<h3 class="section-title">Recent events (limit ${ft})</h3>
|
|
14576
14602
|
<button id="refresh-events-btn" class="btn" type="button">Refresh events</button>
|
|
14577
14603
|
</div>
|
|
14578
14604
|
${this._renderEventsSection()}
|
|
@@ -14584,7 +14610,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14584
14610
|
</div>
|
|
14585
14611
|
`:this._statusError?"":this._renderDisabledNotice()}
|
|
14586
14612
|
</div>
|
|
14587
|
-
`,this._attachEventHandlers()}};customElements.get("loki-managed-memory-panel")||customElements.define("loki-managed-memory-panel",
|
|
14613
|
+
`,this._attachEventHandlers()}};customElements.get("loki-managed-memory-panel")||customElements.define("loki-managed-memory-panel",Te);var Le=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._items=[],this._loading=!1,this._error=null,this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._ensureMarkdownStyles(),this._setupApi(),this._loadList(),this._poll=b({loadFn:()=>this._loadList(),intervalMs:1e4,element:this,immediate:!1})}disconnectedCallback(){super.disconnectedCallback(),this._poll&&(this._poll.stop(),this._poll=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadList()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||(typeof window<"u"?window.location.origin:"");this._api=m({baseUrl:e})}async _loadList(){this._loading=!0,this._error=null;try{let e=await this._api.get("/api/escalations");this._items=Array.isArray(e&&e.escalations)?e.escalations:[]}catch(e){this._error=e&&e.message?e.message:String(e),this._items=[]}finally{this._loading=!1,this.render()}}async _openFile(e){this._activeFile=e,this._activeBody=null,this._activeBodyError=null,this.render();try{let t=(this._api.baseUrl||"")+"/api/escalations/"+encodeURIComponent(e),i=await fetch(t,{credentials:"include"});if(!i.ok)throw new Error("HTTP "+i.status);this._activeBody=await i.text()}catch(t){this._activeBodyError=t&&t.message?t.message:String(t)}this.render()}_closeFile(){this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this.render()}_formatSize(e){return typeof e!="number"?"--":e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":(e/(1024*1024)).toFixed(1)+" MB"}_formatDate(e){if(!e)return"--";try{let t=new Date(e);return isNaN(t.getTime())?e:t.toLocaleString()}catch{return e}}_ensureMarkdownStyles(){if(typeof document>"u"||!document.head||document.getElementById("loki-markdown-styles"))return;let e=document.createElement("style");e.id="loki-markdown-styles",e.textContent=L,document.head.appendChild(e)}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}render(){let e=this.shadowRoot||this;if(!e)return;let t=`
|
|
14588
14614
|
<style>
|
|
14589
14615
|
:host { display: block; }
|
|
14590
14616
|
.esc-wrapper {
|
|
@@ -14642,10 +14668,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14642
14668
|
color: var(--text-secondary, #36342E);
|
|
14643
14669
|
font-size: 0.75rem;
|
|
14644
14670
|
}
|
|
14671
|
+
/* Scroll chrome for the handoff viewer. The rendered markdown is styled
|
|
14672
|
+
by MARKDOWN_STYLES (.md-body), injected once into document.head. The
|
|
14673
|
+
monospace/pre-wrap below only applies to the plain-text loading line
|
|
14674
|
+
(a bare .esc-body without .md-body). */
|
|
14645
14675
|
.esc-body {
|
|
14646
|
-
font-family: 'JetBrains Mono', monospace;
|
|
14647
|
-
font-size: 0.78rem;
|
|
14648
|
-
white-space: pre-wrap;
|
|
14649
14676
|
word-wrap: break-word;
|
|
14650
14677
|
max-height: 480px;
|
|
14651
14678
|
overflow: auto;
|
|
@@ -14653,8 +14680,13 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14653
14680
|
padding: 10px;
|
|
14654
14681
|
border-radius: 4px;
|
|
14655
14682
|
}
|
|
14683
|
+
.esc-body:not(.md-body) {
|
|
14684
|
+
font-family: 'JetBrains Mono', monospace;
|
|
14685
|
+
font-size: 0.78rem;
|
|
14686
|
+
white-space: pre-wrap;
|
|
14687
|
+
}
|
|
14656
14688
|
</style>
|
|
14657
|
-
`,i="";this._loading&&this._items.length===0?i='<div class="esc-empty">Loading escalations...</div>':this._error?i='<div class="esc-error">Failed to load escalations: '+this._escapeHtml(this._error)+"</div>":!this._items||this._items.length===0?i='<div class="esc-empty">No handoff notes yet. If a build needs your attention, its notes will appear here.</div>':i='<div class="esc-list">'+this._items.map(n=>{let l=this._escapeHtml(n.filename||""),c=this._escapeHtml(this._formatSize(n.size_bytes)),p=this._escapeHtml(this._formatDate(n.modified_at));return'<div class="esc-item" data-filename="'+l+'"><span class="esc-name">'+l+'</span><span class="esc-meta">'+c+" · "+p+"</span></div>"}).join("")+"</div>";let a="";if(this._activeFile){let o=this._escapeHtml(this._activeFile),n;this._activeBodyError?n='<div class="esc-error">Failed to load: '+this._escapeHtml(this._activeBodyError)+"</div>":this._activeBody===null?n='<div class="esc-body">Loading '+o+"...</div>":n='<div class="esc-body">'+
|
|
14689
|
+
`,i="";this._loading&&this._items.length===0?i='<div class="esc-empty">Loading escalations...</div>':this._error?i='<div class="esc-error">Failed to load escalations: '+this._escapeHtml(this._error)+"</div>":!this._items||this._items.length===0?i='<div class="esc-empty">No handoff notes yet. If a build needs your attention, its notes will appear here.</div>':i='<div class="esc-list">'+this._items.map(n=>{let l=this._escapeHtml(n.filename||""),c=this._escapeHtml(this._formatSize(n.size_bytes)),p=this._escapeHtml(this._formatDate(n.modified_at));return'<div class="esc-item" data-filename="'+l+'"><span class="esc-name">'+l+'</span><span class="esc-meta">'+c+" · "+p+"</span></div>"}).join("")+"</div>";let a="";if(this._activeFile){let o=this._escapeHtml(this._activeFile),n;this._activeBodyError?n='<div class="esc-error">Failed to load: '+this._escapeHtml(this._activeBodyError)+"</div>":this._activeBody===null?n='<div class="esc-body">Loading '+o+"...</div>":n='<div class="esc-body md-body">'+C(this._activeBody)+"</div>",a='<div class="esc-viewer"><div class="esc-viewer-header"><span class="esc-name">'+o+'</span><button class="esc-close-btn" data-action="close">Close</button></div>'+n+"</div>"}e.innerHTML=t+'<div class="esc-wrapper"><div class="esc-explain">Handoff/escalation documents written under .loki/escalations/. Click an entry to view its contents.</div>'+i+a+"</div>",e.querySelectorAll(".esc-item").forEach(o=>{o.addEventListener("click",()=>{let n=o.getAttribute("data-filename");n&&this._openFile(n)})});let r=e.querySelector('.esc-close-btn[data-action="close"]');r&&r.addEventListener("click",()=>this._closeFile())}};typeof customElements<"u"&&!customElements.get("loki-escalations")&&customElements.define("loki-escalations",Le);var De=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._transcripts=[],this._hookEvents=[],this._loading=!1,this._error=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._load(),this._poll=b({loadFn:()=>this._load(),intervalMs:3e4,element:this,immediate:!1})}disconnectedCallback(){super.disconnectedCallback(),this._poll&&(this._poll.stop(),this._poll=null)}attributeChangedCallback(e,t,i){t!==i&&(e==="api-url"&&this._api&&(this._api.baseUrl=i,this._load()),e==="theme"&&this._applyTheme())}_setupApi(){let e=this.getAttribute("api-url")||(typeof window<"u"?window.location.origin:"");this._api=m({baseUrl:e})}async _load(){this._loading=!0,this._error=null;try{let e=await this._api.get("/api/council/transcripts?limit=10");this._transcripts=Array.isArray(e&&e.transcripts)?e.transcripts:[]}catch(e){this._error=e&&e.message?e.message:String(e),this._transcripts=[]}try{let e=await this._api.get("/api/council/transcripts?limit=20&type_prefix=claude_hook_");this._hookEvents=Array.isArray(e&&e.hook_events)?e.hook_events:[]}catch{this._hookEvents=[]}finally{this._loading=!1,this.render()}}_escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_formatTimestamp(e){if(!e)return"--";try{let t=new Date(e);return isNaN(t.getTime())?e:t.toLocaleString()}catch{return e}}_truncate(e,t){if(!e)return"";let i=String(e);return i.length>t?i.slice(0,t)+"...":i}_verdictBadgeHtml(e){let t=String(e||"").toUpperCase();return t==="APPROVE"?'<span class="ct-badge ct-badge-approve">APPROVE</span>':t==="REJECT"?'<span class="ct-badge ct-badge-reject">REJECT</span>':t==="CANNOT_VALIDATE"?'<span class="ct-badge ct-badge-cannot">CANNOT_VALIDATE</span>':'<span class="ct-badge ct-badge-unknown">'+this._escapeHtml(t||"UNKNOWN")+"</span>"}_outcomeBadgeHtml(e){let t=String(e||"").toUpperCase();return t==="APPROVED"?'<span class="ct-badge ct-badge-approve">APPROVED</span>':t==="REJECTED"?'<span class="ct-badge ct-badge-reject">REJECTED</span>':t==="BLOCKED_BY_GATE"?'<span class="ct-badge ct-badge-blocked">BLOCKED BY GATE</span>':'<span class="ct-badge ct-badge-unknown">'+this._escapeHtml(t||"UNKNOWN")+"</span>"}_voterRowHtml(e,t){let i=e.is_contrarian===!0,a=i&&t===!0,s="ct-voter-row";i&&(s+=" ct-voter-contrarian"),a&&(s+=" ct-voter-flipped");let r=this._escapeHtml(e.name||"unknown"),o=this._verdictBadgeHtml(e.verdict),n=this._escapeHtml(this._truncate(e.reasoning,300)),l="",c="";a?(l='<span class="ct-badge ct-badge-override">OVERRIDE</span>',c=`<div class="ct-flip-caption">Devil's Advocate flipped this outcome</div>`):i&&e.triggered&&(l=`<span class="ct-badge ct-badge-da">DEVIL'S ADVOCATE</span>`);let p="";i&&Array.isArray(e.challenges)&&e.challenges.length>0&&(p='<ul class="ct-challenges">'+e.challenges.map(u=>"<li>"+this._escapeHtml(String(u))+"</li>").join("")+"</ul>");let h="";return Array.isArray(e.issues)&&e.issues.length>0&&(h='<ul class="ct-issues">'+e.issues.map(u=>{let x=this._escapeHtml(u.severity||""),k=this._escapeHtml(u.description||"");return'<li><span class="ct-issue-sev ct-issue-sev-'+x.toLowerCase()+'">'+x+"</span> "+k+"</li>"}).join("")+"</ul>"),'<div class="'+s+'"><div class="ct-voter-header"><span class="ct-voter-name">'+r+"</span>"+o+l+"</div>"+(n?'<div class="ct-voter-reason">'+n+"</div>":"")+p+h+c+"</div>"}_transcriptCardHtml(e){let t=this._escapeHtml(String(e.iteration||"--")),i=this._escapeHtml(this._formatTimestamp(e.timestamp)),a=this._escapeHtml(this._truncate(e.task_or_prd,200)),s=this._outcomeBadgeHtml(e.outcome),r=Array.isArray(e.voters)?e.voters:[],o=r.filter(u=>!u.is_contrarian),n=r.filter(u=>u.is_contrarian),l=o.map(u=>this._voterRowHtml(u,!1)).join(""),c="";e.contrarian_triggered&&(c='<div class="ct-contrarian-section"><div class="ct-section-label">Anti-Sycophancy Check</div>'+n.map(x=>this._voterRowHtml(x,e.contrarian_flipped)).join("")+"</div>");let p=typeof e.approve_count=="number"?e.approve_count:"--",h=typeof e.reject_count=="number"?e.reject_count:"--",v=typeof e.threshold=="number"?e.threshold:"--";return'<div class="ct-card"><div class="ct-card-header"><div class="ct-card-meta"><span class="ct-iter-label">Iteration '+t+'</span><span class="ct-ts">'+i+"</span></div>"+s+"</div>"+(a?'<div class="ct-prd-preview">'+a+"</div>":"")+'<div class="ct-tally">Approve: '+p+" · Reject: "+h+" · Threshold: "+v+'</div><div class="ct-voters">'+l+"</div>"+c+"</div>"}render(){let e=this.shadowRoot||this;if(!e)return;let t=`
|
|
14658
14690
|
<style>
|
|
14659
14691
|
:host { display: block; margin-top: 24px; }
|
|
14660
14692
|
.ct-wrapper {
|
|
@@ -14823,7 +14855,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14823
14855
|
.ct-badge-da { background: #fdf3d4; color: #8a6c0e; }
|
|
14824
14856
|
.ct-badge-unknown { background: var(--bg-secondary, #F8F4F0); color: var(--text-muted, #939084); }
|
|
14825
14857
|
</style>
|
|
14826
|
-
`,i="";this._loading&&this._transcripts.length===0?i='<div class="ct-empty">Loading council transcripts...</div>':this._error?i='<div class="ct-error">Failed to load transcripts: '+this._escapeHtml(this._error)+"</div>":!this._transcripts||this._transcripts.length===0?i='<div class="ct-empty">No review rounds recorded yet. Transcripts appear after the first completion vote.</div>':i='<div class="ct-list">'+this._transcripts.map(s=>this._transcriptCardHtml(s)).join("")+"</div>",e.innerHTML=t+'<div class="ct-wrapper"><h3 class="ct-heading">Council Transcripts</h3><div class="ct-explain">Per-iteration voting records from .loki/council/transcripts/. Polls every 30 seconds.</div>'+i+this._hookEventsHtml()+"</div>"}_hookEventsHtml(){let e=Array.isArray(this._hookEvents)?this._hookEvents:[],t;return e.length===0?t='<div class="ct-empty">No live tool activity yet -- Claude hook events stream here while a run is active.</div>':t='<div class="ct-voters">'+e.slice(0,20).map(a=>{let s=this._escapeHtml(a.type||a.event||"event"),r=this._escapeHtml(this._formatTimestamp(a.timestamp||a.ts)),o=this._escapeHtml(this._truncate(a.tool||a.message||a.summary||(a.data?JSON.stringify(a.data):""),120));return'<div class="ct-voter-row"><span class="ct-iter-label">'+s+'</span> <span class="ct-ts">'+r+"</span>"+(o?'<div class="ct-prd-preview">'+o+"</div>":"")+"</div>"}).join("")+"</div>",'<h3 class="ct-heading" style="margin-top:24px;">Live Tool Activity</h3><div class="ct-explain">Claude hook events (PreToolUse / PostToolUse / Stop) streamed from .loki/events.jsonl. Lets you watch background tool calls as they run.</div>'+t}};typeof customElements<"u"&&!customElements.get("loki-council-transcripts")&&customElements.define("loki-council-transcripts",
|
|
14858
|
+
`,i="";this._loading&&this._transcripts.length===0?i='<div class="ct-empty">Loading council transcripts...</div>':this._error?i='<div class="ct-error">Failed to load transcripts: '+this._escapeHtml(this._error)+"</div>":!this._transcripts||this._transcripts.length===0?i='<div class="ct-empty">No review rounds recorded yet. Transcripts appear after the first completion vote.</div>':i='<div class="ct-list">'+this._transcripts.map(s=>this._transcriptCardHtml(s)).join("")+"</div>",e.innerHTML=t+'<div class="ct-wrapper"><h3 class="ct-heading">Council Transcripts</h3><div class="ct-explain">Per-iteration voting records from .loki/council/transcripts/. Polls every 30 seconds.</div>'+i+this._hookEventsHtml()+"</div>"}_hookEventsHtml(){let e=Array.isArray(this._hookEvents)?this._hookEvents:[],t;return e.length===0?t='<div class="ct-empty">No live tool activity yet -- Claude hook events stream here while a run is active.</div>':t='<div class="ct-voters">'+e.slice(0,20).map(a=>{let s=this._escapeHtml(a.type||a.event||"event"),r=this._escapeHtml(this._formatTimestamp(a.timestamp||a.ts)),o=this._escapeHtml(this._truncate(a.tool||a.message||a.summary||(a.data?JSON.stringify(a.data):""),120));return'<div class="ct-voter-row"><span class="ct-iter-label">'+s+'</span> <span class="ct-ts">'+r+"</span>"+(o?'<div class="ct-prd-preview">'+o+"</div>":"")+"</div>"}).join("")+"</div>",'<h3 class="ct-heading" style="margin-top:24px;">Live Tool Activity</h3><div class="ct-explain">Claude hook events (PreToolUse / PostToolUse / Stop) streamed from .loki/events.jsonl. Lets you watch background tool calls as they run.</div>'+t}};typeof customElements<"u"&&!customElements.get("loki-council-transcripts")&&customElements.define("loki-council-transcripts",De);var ei=[{id:"overview",label:"Overview"},{id:"architecture",label:"Architecture"},{id:"modules",label:"Key Modules"},{id:"data-flow",label:"Data Flow"},{id:"ask",label:"Ask"}],ze=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._activeTab="overview",this._loading=!1,this._error=null,this._api=null,this._meta=null,this._metaPromise=null,this._sectionCache={},this._sectionState={},this._question="",this._answer=null,this._asking=!1,this._askError=null,this._mermaid=null,this._mermaidPromise=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadMeta()}disconnectedCallback(){super.disconnectedCallback&&super.disconnectedCallback(),this._disconnected=!0}attributeChangedCallback(e,t,i){e==="api-url"&&this._api&&(this._api.baseUrl=i)}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}_loadMeta(){return this._loading=!0,this._error=null,this.render(),this._metaPromise=(async()=>{try{this._meta=await this._api._get("/api/wiki")}catch(e){this._error=e&&e.message?e.message:"Failed to load wiki"}finally{this._loading=!1,this.render()}})(),this._metaPromise}async _loadSection(e){if(this._sectionCache[e])return this._sectionState[e]=this._sectionCache[e].error?"error":"loaded",this._sectionCache[e];this._sectionState[e]="loading";try{let t=await this._api._get(`/api/wiki/${encodeURIComponent(e)}`);return this._sectionCache[e]=t,this._sectionState[e]=t&&t.error?"error":"loaded",t}catch(t){let i={error:t&&t.message||"load failed"};return this._sectionCache[e]=i,this._sectionState[e]="error",i}}async _selectTab(e){if(this._activeTab=e,e!=="architecture"&&e!=="modules"&&e!=="data-flow"){this.render();return}if(this._sectionCache[e]){this.render();return}if(this._sectionState[e]="loading",this.render(),this._metaPromise)try{await this._metaPromise}catch{}if(!(this._disconnected||this._activeTab!==e)){if(!this._meta||!this._meta.generated){delete this._sectionState[e],this.render();return}await this._loadSection(e),!(this._disconnected||this._activeTab!==e)&&this.render()}}_ensureMermaid(){return this._mermaid?Promise.resolve(this._mermaid):this._mermaidPromise?this._mermaidPromise:(this._mermaidPromise=(async()=>{try{if(typeof window<"u"&&window.mermaid)return this._mermaid=window.mermaid,this._mermaid;if(typeof window>"u"||typeof document>"u")return null;let t=`${this._api&&this._api.baseUrl||window.location.origin}/assets/mermaid.min.js`;return await new Promise((i,a)=>{let s=document.querySelector("script[data-loki-mermaid]");if(s){s.addEventListener("load",i,{once:!0}),s.addEventListener("error",a,{once:!0}),window.mermaid&&i();return}let r=document.createElement("script");r.src=t,r.async=!0,r.setAttribute("data-loki-mermaid","1"),r.addEventListener("load",i,{once:!0}),r.addEventListener("error",()=>a(new Error("mermaid load failed")),{once:!0}),document.head.appendChild(r)}),this._mermaid=typeof window<"u"&&window.mermaid||null,this._mermaid}catch{return null}})(),this._mermaidPromise)}async _maybeRenderDiagram(e){let t=this._sectionCache[e],i=this._diagramSource(t);if(!i)return;let a;try{a=await this._ensureMermaid()}catch{a=null}if(!(!a||this._disconnected||this._activeTab!==e))try{a.initialize({startOnLoad:!1,securityLevel:"strict",theme:this._mermaidTheme(),flowchart:{htmlLabels:!1,useMaxWidth:!0},deterministicIds:!0}),typeof a.parse=="function"&&await a.parse(i);let s=`wiki-mmd-${e}-${Date.now()}`,r=await a.render(s,i),o=r&&(r.svg||r);if(typeof o!="string"||o.indexOf("<svg")===-1||this._disconnected||this._activeTab!==e||!this.shadowRoot)return;let n=this.shadowRoot.getElementById("wiki-diagram");n&&(n.innerHTML=o)}catch{}}_mermaidTheme(){return(this.getAttribute("theme")||typeof document<"u"&&document.documentElement.getAttribute("data-loki-theme")||"").toLowerCase().includes("dark")?"dark":"neutral"}async _ask(){let e=(this._question||"").trim();if(e){this._asking=!0,this._askError=null,this._answer=null,this.render();try{this._answer=await this._api._post("/api/wiki/ask",{question:e},{timeout:2e5})}catch(t){this._askError=t&&t.message?t.message:"Ask failed"}finally{this._asking=!1,this.render()}}}_esc(e){return String(e??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}_renderCitations(e){return!e||!e.length?"":`<div class="cites"><strong>Sources:</strong><ul>${e.map(i=>`<li><code>${this._esc(i.file)}:${this._esc(i.line)}</code></li>`).join("")}</ul></div>`}_renderNotGenerated(){return`<div class="es">
|
|
14827
14859
|
<div class="es-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg></div>
|
|
14828
14860
|
<div class="es-title">No wiki generated yet</div>
|
|
14829
14861
|
<div class="es-desc">Generate a cited codebase wiki to browse architecture, modules, and data flow. Every section links to real file:line locations.</div>
|
|
@@ -14841,12 +14873,12 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14841
14873
|
</div>`}_renderSection(e){if(this._sectionState[e]==="loading")return'<div class="es-loading"><span class="es-spinner"></span> Loading section...</div>';if(!this._meta||!this._meta.generated)return this._renderNotGenerated();let i=this._sectionCache[e];return i?i.error?this._renderError(i.error):`<div class="section">
|
|
14842
14874
|
<h3>${this._esc(i.title)}</h3>
|
|
14843
14875
|
${this._renderDiagram(e,i)}
|
|
14844
|
-
<
|
|
14876
|
+
<div class="body md-body">${C(i.body)}</div>
|
|
14845
14877
|
${this._renderCitations(i.citations)}
|
|
14846
14878
|
</div>`:'<div class="es-loading"><span class="es-spinner"></span> Loading section...</div>'}_diagramSource(e){let t=e&&typeof e.diagram=="string"?e.diagram.trim():"";if(!t)return"";let i=t.match(/^```(?:mermaid)?\s*\n([\s\S]*?)\n```$/);return i&&(t=i[1].trim()),t}_renderDiagram(e,t){let i=this._diagramSource(t);return i?`<div class="diagram" id="wiki-diagram" data-section="${this._esc(e)}">
|
|
14847
14879
|
<pre class="diagram-fallback"><code>${this._esc(i)}</code></pre>
|
|
14848
14880
|
</div>`:""}_renderAsk(){let e="";if(this._asking)e='<div class="es-loading"><span class="es-spinner"></span> Searching the codebase...</div>';else if(this._askError)e=`<div class="es-inline-error">${this._esc(this._askError)}</div>`;else if(this._answer){let t=this._answer.note?`<p class="dim">${this._esc(this._answer.note)}</p>`:"";e=`<div class="answer">
|
|
14849
|
-
<
|
|
14881
|
+
<div class="body md-body">${C(this._answer.answer||"")}</div>
|
|
14850
14882
|
${t}
|
|
14851
14883
|
${this._renderCitations(this._answer.citations)}
|
|
14852
14884
|
</div>`}return`<div class="ask">
|
|
@@ -14862,10 +14894,11 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14862
14894
|
<div class="es-title">Couldn't load wiki</div>
|
|
14863
14895
|
<div class="es-desc">${this._esc(e)}</div>
|
|
14864
14896
|
<button class="es-cta" id="wiki-retry-btn">Retry</button>
|
|
14865
|
-
</div>`}_renderBody(){if(this._loading)return'<div class="es-loading"><span class="es-spinner"></span> Loading wiki...</div>';if(this._error)return this._renderError(this._error);switch(this._activeTab){case"overview":return this._renderOverview();case"architecture":return this._renderSection("architecture");case"modules":return this._renderSection("modules");case"data-flow":return this._renderSection("data-flow");case"ask":return this._renderAsk();default:return this._renderOverview()}}render(){if(!this.shadowRoot)return;let e=
|
|
14897
|
+
</div>`}_renderBody(){if(this._loading)return'<div class="es-loading"><span class="es-spinner"></span> Loading wiki...</div>';if(this._error)return this._renderError(this._error);switch(this._activeTab){case"overview":return this._renderOverview();case"architecture":return this._renderSection("architecture");case"modules":return this._renderSection("modules");case"data-flow":return this._renderSection("data-flow");case"ask":return this._renderAsk();default:return this._renderOverview()}}render(){if(!this.shadowRoot)return;let e=ei.map(o=>`<button class="tab ${o.id===this._activeTab?"active":""}"
|
|
14866
14898
|
data-tab="${o.id}">${this._esc(o.label)}</button>`).join("");this.shadowRoot.innerHTML=`
|
|
14867
14899
|
<style>
|
|
14868
14900
|
${this.getBaseStyles()}
|
|
14901
|
+
${L}
|
|
14869
14902
|
:host { display: block; }
|
|
14870
14903
|
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--loki-border);
|
|
14871
14904
|
margin-bottom: 12px; flex-wrap: wrap; }
|
|
@@ -14874,9 +14907,10 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14874
14907
|
border-bottom: 2px solid transparent; transition: color 0.15s ease; }
|
|
14875
14908
|
.tab:hover { color: var(--loki-text-primary); }
|
|
14876
14909
|
.tab.active { color: var(--loki-accent); border-bottom-color: var(--loki-accent); }
|
|
14877
|
-
|
|
14878
|
-
|
|
14879
|
-
|
|
14910
|
+
/* Chrome for the rendered section / answer document. The markdown itself
|
|
14911
|
+
is styled by MARKDOWN_STYLES (.md-body), injected into this root. */
|
|
14912
|
+
.body { word-break: break-word;
|
|
14913
|
+
background: var(--loki-bg-secondary);
|
|
14880
14914
|
padding: 14px; border-radius: var(--loki-radius-lg, 5px);
|
|
14881
14915
|
border: 1px solid var(--loki-border); }
|
|
14882
14916
|
.cites { margin-top: 10px; font-size: 12px; color: var(--loki-text-secondary); }
|
|
@@ -14978,7 +15012,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
14978
15012
|
</style>
|
|
14979
15013
|
<div class="tabs">${e}</div>
|
|
14980
15014
|
<div class="content">${this._renderBody()}</div>
|
|
14981
|
-
`,this.shadowRoot.querySelectorAll(".tab").forEach(o=>{o.addEventListener("click",()=>this._selectTab(o.dataset.tab))});let t=this.shadowRoot.getElementById("wiki-q");t&&(t.addEventListener("input",o=>{this._question=o.target.value}),t.addEventListener("keydown",o=>{o.key==="Enter"&&this._ask()}));let i=this.shadowRoot.getElementById("wiki-ask-btn");i&&i.addEventListener("click",()=>this._ask());let a=this.shadowRoot.getElementById("wiki-gen-copy");a&&a.addEventListener("click",()=>this._copyGenerateCmd(a));let s=this.shadowRoot.getElementById("wiki-retry-btn");s&&s.addEventListener("click",()=>{this._sectionCache={},this._sectionState={},this._loadMeta()});let r=this._activeTab;(r==="architecture"||r==="data-flow")&&this._sectionCache[r]&&!this._sectionCache[r].error&&this.shadowRoot.getElementById("wiki-diagram")&&this._maybeRenderDiagram(r)}_copyGenerateCmd(e){let t="loki wiki generate",i=()=>{let a=e.innerHTML;e.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',setTimeout(()=>{e.innerHTML=a},1500)};navigator.clipboard&&navigator.clipboard.writeText&&navigator.clipboard.writeText(t).then(i).catch(()=>{})}};customElements.get("loki-wiki-browser")||customElements.define("loki-wiki-browser",
|
|
15015
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(o=>{o.addEventListener("click",()=>this._selectTab(o.dataset.tab))});let t=this.shadowRoot.getElementById("wiki-q");t&&(t.addEventListener("input",o=>{this._question=o.target.value}),t.addEventListener("keydown",o=>{o.key==="Enter"&&this._ask()}));let i=this.shadowRoot.getElementById("wiki-ask-btn");i&&i.addEventListener("click",()=>this._ask());let a=this.shadowRoot.getElementById("wiki-gen-copy");a&&a.addEventListener("click",()=>this._copyGenerateCmd(a));let s=this.shadowRoot.getElementById("wiki-retry-btn");s&&s.addEventListener("click",()=>{this._sectionCache={},this._sectionState={},this._loadMeta()});let r=this._activeTab;(r==="architecture"||r==="data-flow")&&this._sectionCache[r]&&!this._sectionCache[r].error&&this.shadowRoot.getElementById("wiki-diagram")&&this._maybeRenderDiagram(r)}_copyGenerateCmd(e){let t="loki wiki generate",i=()=>{let a=e.innerHTML;e.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',setTimeout(()=>{e.innerHTML=a},1500)};navigator.clipboard&&navigator.clipboard.writeText&&navigator.clipboard.writeText(t).then(i).catch(()=>{})}};customElements.get("loki-wiki-browser")||customElements.define("loki-wiki-browser",ze);var bt={prd:"PRD file",spec:"Generated spec",issue:"GitHub issue",brief:"One-line brief","codebase-analysis":"Codebase analysis",none:"No spec yet",unknown:"Unknown spec"},Re=class extends g{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._spec=null,this._history=null,this._loading=!1,this._error=null,this._historyError=null,this._historyOpen=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._load()}attributeChangedCallback(e,t,i){e==="api-url"&&this._api&&(this._api.baseUrl=i)}_setupApi(){let e=this.getAttribute("api-url")||window.location.origin;this._api=m({baseUrl:e})}async _load(){this._loading=!0,this._error=null,this.render();try{this._spec=await this._api._get("/api/spec")}catch(e){this._error=e&&e.message?e.message:"Failed to load spec"}finally{this._loading=!1,this.render()}try{let e=await this._api._get("/api/spec/history");this._history=e&&Array.isArray(e.history)?e.history:[]}catch(e){this._historyError=e&&e.message?e.message:"Failed to load history",this._history=[]}this.render()}_esc(e){return String(e??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}_when(e){if(!e)return"unknown time";let t=new Date(e);if(isNaN(t.getTime()))return this._esc(e);try{return t.toLocaleString()}catch{return this._esc(e)}}_typeLabel(e){return bt[e]||bt.unknown}_typeBadge(e){return`<span class="badge badge-${this._esc(e)}">${this._esc(this._typeLabel(e))}</span>`}_renderActive(){if(this._loading)return'<div class="es-loading"><span class="es-spinner"></span> Loading active spec...</div>';if(this._error)return this._renderError(this._error);let e=this._spec;if(!e||!e.type||e.type==="none")return this._renderEmpty();let t=this._typeBadge(e.type),i="",a="";if(e.type==="prd"||e.type==="spec"){e.path&&(i=`<code class="src">${this._esc(e.path)}</code>`);let s=e.content||"";s.trim()?a=`<div class="body md-body">${C(s)}</div>`+(e.truncated?'<p class="dim">Preview truncated -- see the full file on disk.</p>':""):a='<p class="dim">No content available.</p>'}else if(e.type==="issue"){i=e.ref?`<code class="src">${this._esc(e.ref)}</code>`:"";let r=e.title?`<p class="issue-title">${this._esc(e.title)}</p>`:"",o=(e.body||"").trim()?`<div class="body md-body">${C(e.body)}</div>`+(e.truncated?'<p class="dim">Preview truncated.</p>':""):"";a=`${r}${o}`}else if(e.type==="brief"){let s=(e.text||"").trim();a=s?`<pre class="body brief">${this._esc(s)}</pre>`+(e.truncated?'<p class="dim">Preview truncated.</p>':""):'<p class="dim">No brief recorded.</p>'}else e.type==="codebase-analysis"?a='<p class="dim">No explicit spec. Loki is building from an analysis of the existing codebase.</p>':a='<p class="dim">The spec source could not be resolved.</p>';return`<div class="active">
|
|
14982
15016
|
<div class="active-head">
|
|
14983
15017
|
<span class="active-label">Building from</span>
|
|
14984
15018
|
${t}
|
|
@@ -15008,6 +15042,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
15008
15042
|
</div>`}render(){if(!this.shadowRoot)return;this.shadowRoot.innerHTML=`
|
|
15009
15043
|
<style>
|
|
15010
15044
|
${this.getBaseStyles()}
|
|
15045
|
+
${L}
|
|
15011
15046
|
:host { display: block; }
|
|
15012
15047
|
.active { background: var(--loki-bg-secondary); border: 1px solid var(--loki-border);
|
|
15013
15048
|
border-radius: var(--loki-radius-lg, 5px); padding: 16px; }
|
|
@@ -15024,12 +15059,17 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
15024
15059
|
.src { font-family: var(--loki-font-mono, monospace); font-size: 12px;
|
|
15025
15060
|
background: var(--loki-bg-tertiary); color: var(--loki-text-secondary);
|
|
15026
15061
|
padding: 2px 7px; border-radius: 3px; word-break: break-all; }
|
|
15027
|
-
|
|
15028
|
-
|
|
15062
|
+
/* Scroll chrome for the rendered spec/issue document. The markdown
|
|
15063
|
+
itself is styled by MARKDOWN_STYLES (.md-body), injected below. */
|
|
15064
|
+
.body { word-break: break-word;
|
|
15029
15065
|
max-height: 320px; overflow: auto;
|
|
15030
|
-
background: var(--loki-bg-tertiary);
|
|
15066
|
+
background: var(--loki-bg-tertiary);
|
|
15031
15067
|
padding: 12px; border-radius: var(--loki-radius-md, 4px);
|
|
15032
15068
|
border: 1px solid var(--loki-border); margin: 0; }
|
|
15069
|
+
/* The brief is a one-line plain-text spec, kept as a preformatted block. */
|
|
15070
|
+
.body.brief { white-space: pre-wrap;
|
|
15071
|
+
font-family: var(--loki-font-mono, monospace); font-size: 12px;
|
|
15072
|
+
line-height: 1.6; color: var(--loki-text-primary); }
|
|
15033
15073
|
.dim { color: var(--loki-text-muted); font-size: 12px; }
|
|
15034
15074
|
|
|
15035
15075
|
/* History */
|
|
@@ -15074,7 +15114,7 @@ var LokiDashboard=(()=>{var Ae=Object.defineProperty;var mt=Object.getOwnPropert
|
|
|
15074
15114
|
</style>
|
|
15075
15115
|
<div class="active-wrap">${this._renderActive()}</div>
|
|
15076
15116
|
${this._error||this._spec&&this._spec.type==="none"?"":this._renderHistory()}
|
|
15077
|
-
`;let e=this.shadowRoot.getElementById("spec-retry-btn");e&&e.addEventListener("click",()=>this._load());let t=this.shadowRoot.getElementById("hist-toggle");t&&t.addEventListener("click",()=>{this._historyOpen=!this._historyOpen,this.render()})}};customElements.get("loki-spec-panel")||customElements.define("loki-spec-panel",
|
|
15117
|
+
`;let e=this.shadowRoot.getElementById("spec-retry-btn");e&&e.addEventListener("click",()=>this._load());let t=this.shadowRoot.getElementById("hist-toggle");t&&t.addEventListener("click",()=>{this._historyOpen=!this._historyOpen,this.render()})}};customElements.get("loki-spec-panel")||customElements.define("loki-spec-panel",Re);var ti="1.4.0";function ii(d={}){return d.theme?w.setTheme(d.theme):d.autoDetectContext!==!1?w.init():j.init(),d.apiUrl&&m({baseUrl:d.apiUrl}),{theme:w.getTheme(),context:w.detectContext()}}return Ct(ai);})();
|
|
15078
15118
|
|
|
15079
15119
|
|
|
15080
15120
|
// Initialize dashboard when DOM is ready
|
|
@@ -15215,60 +15255,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
15215
15255
|
setInterval(refresh, 15000);
|
|
15216
15256
|
})();
|
|
15217
15257
|
|
|
15218
|
-
//
|
|
15219
|
-
|
|
15220
|
-
|
|
15221
|
-
|
|
15222
|
-
|
|
15223
|
-
|
|
15224
|
-
|
|
15225
|
-
|
|
15226
|
-
|
|
15227
|
-
|
|
15228
|
-
function lokiResolvedTheme() {
|
|
15229
|
-
var theme = LokiDashboard.UnifiedThemeManager.getTheme();
|
|
15230
|
-
return (theme.includes('dark') || theme === 'high-contrast') ? 'dark' : 'light';
|
|
15231
|
-
}
|
|
15232
|
-
|
|
15233
|
-
// Keep the trust iframe's theme in sync with the SPA toggle. If the frame is
|
|
15234
|
-
// already loaded, re-point its src with the new ?theme= so its palette flips
|
|
15235
|
-
// with the SPA instead of clashing.
|
|
15236
|
-
function syncTrustFrameTheme() {
|
|
15237
|
-
var tframe = document.getElementById('trust-frame');
|
|
15238
|
-
if (!tframe) return;
|
|
15239
|
-
var cur = tframe.getAttribute('src') || '';
|
|
15240
|
-
if (!cur || cur === 'about:blank') return; // not opened yet; opens with theme
|
|
15241
|
-
tframe.src = '/trust?theme=' + lokiResolvedTheme();
|
|
15242
|
-
}
|
|
15243
|
-
|
|
15244
|
-
function updateThemeUI() {
|
|
15245
|
-
var theme = LokiDashboard.UnifiedThemeManager.getTheme();
|
|
15246
|
-
var isDark = theme.includes('dark') || theme === 'high-contrast';
|
|
15247
|
-
themeLabel.textContent = isDark ? 'Light' : 'Dark';
|
|
15248
|
-
if (sunIcon) sunIcon.style.display = isDark ? 'inline' : 'none';
|
|
15249
|
-
if (moonIcon) moonIcon.style.display = isDark ? 'none' : 'inline';
|
|
15250
|
-
}
|
|
15251
|
-
|
|
15252
|
-
themeToggle.addEventListener('click', function() {
|
|
15253
|
-
LokiDashboard.UnifiedThemeManager.toggle();
|
|
15254
|
-
// updateThemeUI + syncTrustFrameTheme run via the loki-theme-change
|
|
15255
|
-
// listener below (toggle() dispatches it), so we do NOT call them here too
|
|
15256
|
-
// -- a direct call would re-point the trust iframe src twice per toggle.
|
|
15257
|
-
});
|
|
15258
|
-
|
|
15259
|
-
window.addEventListener('loki-theme-change', function() {
|
|
15260
|
-
updateThemeUI();
|
|
15261
|
-
syncTrustFrameTheme();
|
|
15262
|
-
});
|
|
15263
|
-
|
|
15264
|
-
updateThemeUI();
|
|
15258
|
+
// v7.90.1: dark mode removed -- the dashboard is light-only. The theme toggle
|
|
15259
|
+
// button + handler are gone; everything renders in the single light theme.
|
|
15260
|
+
// Force light on the SPA and pin the iframe/standalone pages (trust/cost/
|
|
15261
|
+
// proofs) to ?theme=light so they match.
|
|
15262
|
+
try {
|
|
15263
|
+
if (LokiDashboard && LokiDashboard.UnifiedThemeManager &&
|
|
15264
|
+
typeof LokiDashboard.UnifiedThemeManager.setTheme === 'function') {
|
|
15265
|
+
LokiDashboard.UnifiedThemeManager.setTheme('light');
|
|
15266
|
+
}
|
|
15267
|
+
} catch (_e) { /* theme manager optional; light is the CSS default anyway */ }
|
|
15265
15268
|
|
|
15266
|
-
// Carry the SPA theme to the full-page standalone views (cost/proofs) opened
|
|
15267
|
-
// via direct links, so a user who toggled Dark gets a matching page instead
|
|
15268
|
-
// of an OS-default one. Updated on click so it always reflects the current
|
|
15269
|
-
// toggle state. v7.18.0.
|
|
15270
15269
|
function lokiThemeHref(base) {
|
|
15271
|
-
return base + (base.indexOf('?') >= 0 ? '&' : '?') + 'theme='
|
|
15270
|
+
return base + (base.indexOf('?') >= 0 ? '&' : '?') + 'theme=light';
|
|
15272
15271
|
}
|
|
15273
15272
|
var costLink = document.getElementById('budget-banner-link');
|
|
15274
15273
|
if (costLink) {
|
|
@@ -15504,7 +15503,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
15504
15503
|
var tframe = document.getElementById('trust-frame');
|
|
15505
15504
|
if (tframe && (!tframe.src || tframe.src === 'about:blank' ||
|
|
15506
15505
|
tframe.getAttribute('src') === 'about:blank')) {
|
|
15507
|
-
tframe.src = '/trust?theme='
|
|
15506
|
+
tframe.src = '/trust?theme=light';
|
|
15508
15507
|
}
|
|
15509
15508
|
}
|
|
15510
15509
|
// Update nav active state
|
|
@@ -15576,148 +15575,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
15576
15575
|
}
|
|
15577
15576
|
});
|
|
15578
15577
|
|
|
15579
|
-
// Keyboard shortcuts:
|
|
15580
|
-
|
|
15581
|
-
|
|
15582
|
-
e.preventDefault();
|
|
15583
|
-
var sections = ['overview', 'fleet', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'trust', 'checkpoint', 'context', 'notifications', 'migration', 'analytics', 'escalations'];
|
|
15584
|
-
var idx = e.key === '0' ? 9 : parseInt(e.key) - 1;
|
|
15585
|
-
if (idx < sections.length) switchSection(sections[idx]);
|
|
15586
|
-
}
|
|
15587
|
-
});
|
|
15588
|
-
|
|
15589
|
-
// --- Keyboard Shortcuts (Issue #18) ---
|
|
15590
|
-
var shortcutsOverlay = document.getElementById('shortcuts-overlay');
|
|
15591
|
-
var shortcutsClose = document.getElementById('shortcuts-close');
|
|
15592
|
-
|
|
15593
|
-
function toggleShortcutsOverlay() {
|
|
15594
|
-
shortcutsOverlay.classList.toggle('visible');
|
|
15595
|
-
}
|
|
15596
|
-
|
|
15597
|
-
function closeShortcutsOverlay() {
|
|
15598
|
-
shortcutsOverlay.classList.remove('visible');
|
|
15599
|
-
}
|
|
15600
|
-
|
|
15601
|
-
shortcutsClose.addEventListener('click', closeShortcutsOverlay);
|
|
15602
|
-
|
|
15603
|
-
// Close overlay when clicking outside the dialog
|
|
15604
|
-
shortcutsOverlay.addEventListener('click', function(e) {
|
|
15605
|
-
if (e.target === shortcutsOverlay) {
|
|
15606
|
-
closeShortcutsOverlay();
|
|
15607
|
-
}
|
|
15608
|
-
});
|
|
15609
|
-
|
|
15610
|
-
document.addEventListener('keydown', function(e) {
|
|
15611
|
-
// Skip shortcuts when typing in input, textarea, or select elements
|
|
15612
|
-
var tag = (e.target.tagName || '').toLowerCase();
|
|
15613
|
-
if (tag === 'input' || tag === 'textarea' || tag === 'select' || e.target.isContentEditable) {
|
|
15614
|
-
// Allow Escape to blur input fields
|
|
15615
|
-
if (e.key === 'Escape') {
|
|
15616
|
-
e.target.blur();
|
|
15617
|
-
}
|
|
15618
|
-
return;
|
|
15619
|
-
}
|
|
15620
|
-
|
|
15621
|
-
// Skip if modifier keys are held (let browser defaults work)
|
|
15622
|
-
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
15623
|
-
|
|
15624
|
-
var sections = ['overview', 'fleet', 'insights', 'prd-checklist', 'app-runner', 'council', 'quality', 'cost', 'trust', 'checkpoint', 'context', 'notifications', 'migration', 'analytics', 'escalations'];
|
|
15625
|
-
|
|
15626
|
-
switch (e.key) {
|
|
15627
|
-
// Section navigation: 1-9, 0
|
|
15628
|
-
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
|
15629
|
-
e.preventDefault();
|
|
15630
|
-
switchSection(sections[parseInt(e.key) - 1]);
|
|
15631
|
-
break;
|
|
15632
|
-
case '0':
|
|
15633
|
-
e.preventDefault();
|
|
15634
|
-
switchSection(sections[9]);
|
|
15635
|
-
break;
|
|
15636
|
-
|
|
15637
|
-
// Migration page
|
|
15638
|
-
case 'm':
|
|
15639
|
-
e.preventDefault();
|
|
15640
|
-
switchSection('migration');
|
|
15641
|
-
break;
|
|
15642
|
-
|
|
15643
|
-
// Analytics page
|
|
15644
|
-
case 'a':
|
|
15645
|
-
e.preventDefault();
|
|
15646
|
-
switchSection('analytics');
|
|
15647
|
-
break;
|
|
15648
|
-
|
|
15649
|
-
// Escalations page
|
|
15650
|
-
case 'e':
|
|
15651
|
-
e.preventDefault();
|
|
15652
|
-
switchSection('escalations');
|
|
15653
|
-
break;
|
|
15654
|
-
|
|
15655
|
-
// Help overlay
|
|
15656
|
-
case '?':
|
|
15657
|
-
e.preventDefault();
|
|
15658
|
-
toggleShortcutsOverlay();
|
|
15659
|
-
break;
|
|
15660
|
-
|
|
15661
|
-
// Close overlays
|
|
15662
|
-
case 'Escape':
|
|
15663
|
-
if (shortcutsOverlay.classList.contains('visible')) {
|
|
15664
|
-
e.preventDefault();
|
|
15665
|
-
closeShortcutsOverlay();
|
|
15666
|
-
}
|
|
15667
|
-
break;
|
|
15668
|
-
|
|
15669
|
-
// Focus API URL input
|
|
15670
|
-
case '/':
|
|
15671
|
-
e.preventDefault();
|
|
15672
|
-
apiUrlInput.focus();
|
|
15673
|
-
apiUrlInput.select();
|
|
15674
|
-
break;
|
|
15675
|
-
|
|
15676
|
-
// Theme toggle. updateThemeUI + syncTrustFrameTheme run via the
|
|
15677
|
-
// loki-theme-change listener (toggle() dispatches it); do not call them
|
|
15678
|
-
// here too, or the trust iframe re-points twice per toggle.
|
|
15679
|
-
case 't':
|
|
15680
|
-
e.preventDefault();
|
|
15681
|
-
LokiDashboard.UnifiedThemeManager.toggle();
|
|
15682
|
-
break;
|
|
15683
|
-
|
|
15684
|
-
// Session controls
|
|
15685
|
-
case 'p':
|
|
15686
|
-
e.preventDefault();
|
|
15687
|
-
var sessionCtrl = document.getElementById('session-control');
|
|
15688
|
-
if (sessionCtrl) {
|
|
15689
|
-
var pauseBtn = sessionCtrl.shadowRoot && sessionCtrl.shadowRoot.getElementById('pause-btn');
|
|
15690
|
-
if (pauseBtn && !pauseBtn.disabled) {
|
|
15691
|
-
pauseBtn.click();
|
|
15692
|
-
}
|
|
15693
|
-
}
|
|
15694
|
-
break;
|
|
15695
|
-
|
|
15696
|
-
case 'r':
|
|
15697
|
-
e.preventDefault();
|
|
15698
|
-
var sessionCtrl2 = document.getElementById('session-control');
|
|
15699
|
-
if (sessionCtrl2) {
|
|
15700
|
-
var resumeBtn = sessionCtrl2.shadowRoot && sessionCtrl2.shadowRoot.getElementById('resume-btn');
|
|
15701
|
-
if (resumeBtn) {
|
|
15702
|
-
resumeBtn.click();
|
|
15703
|
-
}
|
|
15704
|
-
}
|
|
15705
|
-
break;
|
|
15706
|
-
|
|
15707
|
-
case 's':
|
|
15708
|
-
e.preventDefault();
|
|
15709
|
-
var sessionCtrl3 = document.getElementById('session-control');
|
|
15710
|
-
if (sessionCtrl3) {
|
|
15711
|
-
var stopBtn = sessionCtrl3.shadowRoot && sessionCtrl3.shadowRoot.getElementById('stop-btn');
|
|
15712
|
-
if (stopBtn && !stopBtn.disabled) {
|
|
15713
|
-
if (window.confirm('Are you sure you want to stop the session?')) {
|
|
15714
|
-
stopBtn.click();
|
|
15715
|
-
}
|
|
15716
|
-
}
|
|
15717
|
-
}
|
|
15718
|
-
break;
|
|
15719
|
-
}
|
|
15720
|
-
});
|
|
15578
|
+
// Keyboard shortcuts removed (v7.90.1): app-level hotkeys fired while
|
|
15579
|
+
// typing in inputs (switching tabs / toggling theme), so they are gone
|
|
15580
|
+
// entirely. Native browser behavior + per-modal Escape handling remain.
|
|
15721
15581
|
|
|
15722
15582
|
// Restore last section from localStorage (overrides default overview)
|
|
15723
15583
|
var savedSection = localStorage.getItem('loki-active-section');
|