loki-mode 7.12.0 → 7.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +4 -2
- package/VERSION +1 -1
- package/autonomy/lib/wiki-ask.py +137 -0
- package/autonomy/lib/wiki-generator.py +322 -0
- package/autonomy/lib/wiki_index.py +258 -0
- package/autonomy/lib/wiki_llm.py +140 -0
- package/autonomy/loki +304 -11
- package/autonomy/run.sh +62 -12
- package/bin/loki +1 -1
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +202 -0
- package/dashboard/static/index.html +405 -329
- package/docs/INSTALLATION.md +1 -1
- package/docs/R5-AUTO-WIKI-DESIGN.md +137 -0
- package/docs/R6-ROLLBACK-CHECKPOINT-PLAN.md +107 -0
- package/loki-ts/dist/loki.js +245 -206
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
|
@@ -704,6 +704,10 @@
|
|
|
704
704
|
<svg viewBox="0 0 24 24"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
|
705
705
|
Escalations
|
|
706
706
|
</button>
|
|
707
|
+
<button class="nav-link" data-section="wiki" id="nav-wiki">
|
|
708
|
+
<svg viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg>
|
|
709
|
+
Wiki
|
|
710
|
+
</button>
|
|
707
711
|
</nav>
|
|
708
712
|
|
|
709
713
|
<div class="sidebar-footer">
|
|
@@ -1152,6 +1156,14 @@
|
|
|
1152
1156
|
</div>
|
|
1153
1157
|
<loki-escalations id="escalations-panel"></loki-escalations>
|
|
1154
1158
|
</div>
|
|
1159
|
+
|
|
1160
|
+
<!-- Wiki: auto-generated cited codebase wiki + Q&A (R5) -->
|
|
1161
|
+
<div class="section-page" id="page-wiki">
|
|
1162
|
+
<div class="section-page-header">
|
|
1163
|
+
<h2 class="section-page-title">Wiki</h2>
|
|
1164
|
+
</div>
|
|
1165
|
+
<loki-wiki-browser id="wiki-browser"></loki-wiki-browser>
|
|
1166
|
+
</div>
|
|
1155
1167
|
</main>
|
|
1156
1168
|
</div>
|
|
1157
1169
|
|
|
@@ -1196,7 +1208,7 @@
|
|
|
1196
1208
|
|
|
1197
1209
|
<!-- Inlined JavaScript Bundle -->
|
|
1198
1210
|
<script>
|
|
1199
|
-
var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var se=Object.prototype.hasOwnProperty;var re=(d,t,e)=>t in d?wt(d,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):d[t]=e;var oe=(d,t)=>{for(var e in t)wt(d,e,{get:t[e],enumerable:!0})},ne=(d,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ie(t))!se.call(d,i)&&i!==e&&wt(d,i,{get:()=>t[i],enumerable:!(a=ae(t,i))||a.enumerable});return d};var le=d=>ne(wt({},"__esModule",{value:!0}),d);var C=(d,t,e)=>re(d,typeof t!="symbol"?t+"":t,e);var Be={};oe(Be,{ANIMATION:()=>L,ARIA_PATTERNS:()=>Ct,ApiEvents:()=>v,BASE_STYLES:()=>U,BREAKPOINTS:()=>$t,COMMON_STYLES:()=>Pt,KEYBOARD_SHORTCUTS:()=>Et,KeyboardHandler:()=>P,LokiActivityStream:()=>ht,LokiAgentLeaderboard:()=>kt,LokiAnalytics:()=>ot,LokiApiClient:()=>M,LokiApiKeys:()=>pt,LokiAppStatus:()=>Q,LokiAuditViewer:()=>ct,LokiChecklistViewer:()=>W,LokiCheckpointViewer:()=>Z,LokiContextTracker:()=>tt,LokiCostDashboard:()=>X,LokiCostWaterfall:()=>ft,LokiCouncilDashboard:()=>Y,LokiCouncilTranscripts:()=>yt,LokiElement:()=>h,LokiEscalations:()=>_t,LokiLearningDashboard:()=>V,LokiLogStream:()=>G,LokiManagedMemoryPanel:()=>xt,LokiMemoryBrowser:()=>K,LokiMemoryGraph:()=>bt,LokiMigrationDashboard:()=>rt,LokiNotificationCenter:()=>et,LokiOverview:()=>O,LokiPipelineView:()=>mt,LokiPromptOptimizer:()=>it,LokiProviderHealth:()=>gt,LokiQualityGates:()=>nt,LokiQualityScore:()=>st,LokiRarvTimeline:()=>lt,LokiRunManager:()=>dt,LokiSessionControl:()=>J,LokiSessionDiff:()=>at,LokiState:()=>N,LokiTaskBoard:()=>q,LokiTenantSwitcher:()=>ut,LokiTheme:()=>R,RADIUS:()=>I,SPACING:()=>A,STATE_CHANGE_EVENT:()=>Tt,THEMES:()=>E,THEME_VARIABLES:()=>St,TYPOGRAPHY:()=>y,UnifiedThemeManager:()=>_,VERSION:()=>He,Z_INDEX:()=>D,createApiClient:()=>jt,createStore:()=>Ut,generateThemeCSS:()=>$,generateTokensCSS:()=>j,getApiClient:()=>g,getState:()=>B,init:()=>Re});var E={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-bg-active":"#E6E2DA","--loki-bg-overlay":"rgba(32, 21, 21, 0.5)","--loki-accent":"#553DE9","--loki-accent-hover":"#4432c4","--loki-accent-active":"#3828a0","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-text-disabled":"#C5C0B1","--loki-text-inverse":"#ffffff","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-border-focus":"#553DE9","--loki-success":"#1FC5A8","--loki-success-muted":"rgba(31, 197, 168, 0.12)","--loki-warning":"#D4A03C","--loki-warning-muted":"rgba(212, 160, 60, 0.12)","--loki-error":"#C45B5B","--loki-error-muted":"rgba(196, 91, 91, 0.12)","--loki-info":"#2F71E3","--loki-info-muted":"rgba(47, 113, 227, 0.12)","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-shadow-sm":"0 1px 2px rgba(32, 21, 21, 0.04)","--loki-shadow-md":"0 4px 6px rgba(32, 21, 21, 0.06)","--loki-shadow-lg":"0 10px 15px rgba(32, 21, 21, 0.08)","--loki-shadow-focus":"0 0 0 3px rgba(85, 61, 233, 0.25)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-bg-active":"#352A55","--loki-bg-overlay":"rgba(20, 11, 36, 0.85)","--loki-accent":"#7B6BF0","--loki-accent-hover":"#9488F5","--loki-accent-active":"#6258D0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-text-disabled":"#5A4E78","--loki-text-inverse":"#1A0F2E","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-border-focus":"#7B6BF0","--loki-success":"#2ED8B6","--loki-success-muted":"rgba(46, 216, 182, 0.18)","--loki-warning":"#E8B84A","--loki-warning-muted":"rgba(232, 184, 74, 0.18)","--loki-error":"#E07070","--loki-error-muted":"rgba(224, 112, 112, 0.18)","--loki-info":"#5A9CF5","--loki-info-muted":"rgba(90, 156, 245, 0.18)","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.4)","--loki-shadow-md":"0 4px 12px rgba(0, 0, 0, 0.5)","--loki-shadow-lg":"0 10px 25px rgba(0, 0, 0, 0.6)","--loki-shadow-focus":"0 0 0 3px rgba(123, 107, 240, 0.30)"},"high-contrast":{"--loki-bg-primary":"#000000","--loki-bg-secondary":"#0a0a0a","--loki-bg-tertiary":"#141414","--loki-bg-card":"#0a0a0a","--loki-bg-hover":"#1a1a1a","--loki-bg-active":"#242424","--loki-bg-overlay":"rgba(0, 0, 0, 0.9)","--loki-accent":"#c084fc","--loki-accent-hover":"#d8b4fe","--loki-accent-active":"#e9d5ff","--loki-accent-light":"#d8b4fe","--loki-accent-muted":"rgba(192, 132, 252, 0.25)","--loki-text-primary":"#ffffff","--loki-text-secondary":"#e0e0e0","--loki-text-muted":"#b0b0b0","--loki-text-disabled":"#666666","--loki-text-inverse":"#000000","--loki-border":"#ffffff","--loki-border-light":"#cccccc","--loki-border-focus":"#c084fc","--loki-success":"#4ade80","--loki-success-muted":"rgba(74, 222, 128, 0.25)","--loki-warning":"#fde047","--loki-warning-muted":"rgba(253, 224, 71, 0.25)","--loki-error":"#f87171","--loki-error-muted":"rgba(248, 113, 113, 0.25)","--loki-info":"#60a5fa","--loki-info-muted":"rgba(96, 165, 250, 0.25)","--loki-green":"#4ade80","--loki-green-muted":"rgba(74, 222, 128, 0.25)","--loki-yellow":"#fde047","--loki-yellow-muted":"rgba(253, 224, 71, 0.25)","--loki-red":"#f87171","--loki-red-muted":"rgba(248, 113, 113, 0.25)","--loki-blue":"#60a5fa","--loki-blue-muted":"rgba(96, 165, 250, 0.25)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.25)","--loki-opus":"#fbbf24","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"none","--loki-shadow-md":"none","--loki-shadow-lg":"none","--loki-shadow-focus":"0 0 0 3px #c084fc"},"vscode-light":{"--loki-bg-primary":"var(--vscode-editor-background, #ffffff)","--loki-bg-secondary":"var(--vscode-sideBar-background, #f3f3f3)","--loki-bg-tertiary":"var(--vscode-input-background, #ffffff)","--loki-bg-card":"var(--vscode-editor-background, #ffffff)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #e8e8e8)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #0060c0)","--loki-bg-overlay":"rgba(0, 0, 0, 0.4)","--loki-accent":"var(--vscode-focusBorder, #0066cc)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #0055aa)","--loki-accent-active":"var(--vscode-button-background, #007acc)","--loki-accent-light":"var(--vscode-focusBorder, #0066cc)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 102, 204, 0.2))","--loki-text-primary":"var(--vscode-foreground, #333333)","--loki-text-secondary":"var(--vscode-descriptionForeground, #717171)","--loki-text-muted":"var(--vscode-disabledForeground, #a0a0a0)","--loki-text-disabled":"var(--vscode-disabledForeground, #cccccc)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #c8c8c8)","--loki-border-light":"var(--vscode-widget-border, #e0e0e0)","--loki-border-focus":"var(--vscode-focusBorder, #0066cc)","--loki-success":"var(--vscode-testing-iconPassed, #388a34)","--loki-success-muted":"rgba(56, 138, 52, 0.15)","--loki-warning":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-warning-muted":"rgba(191, 136, 3, 0.15)","--loki-error":"var(--vscode-errorForeground, #e51400)","--loki-error-muted":"rgba(229, 20, 0, 0.15)","--loki-info":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-info-muted":"rgba(26, 133, 255, 0.15)","--loki-green":"var(--vscode-testing-iconPassed, #388a34)","--loki-green-muted":"rgba(56, 138, 52, 0.15)","--loki-yellow":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-yellow-muted":"rgba(191, 136, 3, 0.15)","--loki-red":"var(--vscode-errorForeground, #e51400)","--loki-red-muted":"rgba(229, 20, 0, 0.15)","--loki-blue":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-blue-muted":"rgba(26, 133, 255, 0.15)","--loki-purple":"#9333ea","--loki-purple-muted":"rgba(147, 51, 234, 0.15)","--loki-opus":"#d97706","--loki-sonnet":"#4f46e5","--loki-haiku":"#059669","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.05)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.1)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.15)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #0066cc)"},"vscode-dark":{"--loki-bg-primary":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-secondary":"var(--vscode-sideBar-background, #252526)","--loki-bg-tertiary":"var(--vscode-input-background, #3c3c3c)","--loki-bg-card":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #2a2d2e)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #094771)","--loki-bg-overlay":"rgba(0, 0, 0, 0.6)","--loki-accent":"var(--vscode-focusBorder, #007fd4)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #1177bb)","--loki-accent-active":"var(--vscode-button-background, #0e639c)","--loki-accent-light":"var(--vscode-focusBorder, #007fd4)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 127, 212, 0.25))","--loki-text-primary":"var(--vscode-foreground, #cccccc)","--loki-text-secondary":"var(--vscode-descriptionForeground, #9d9d9d)","--loki-text-muted":"var(--vscode-disabledForeground, #6b6b6b)","--loki-text-disabled":"var(--vscode-disabledForeground, #4d4d4d)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #454545)","--loki-border-light":"var(--vscode-widget-border, #5a5a5a)","--loki-border-focus":"var(--vscode-focusBorder, #007fd4)","--loki-success":"var(--vscode-testing-iconPassed, #89d185)","--loki-success-muted":"rgba(137, 209, 133, 0.2)","--loki-warning":"var(--vscode-editorWarning-foreground, #cca700)","--loki-warning-muted":"rgba(204, 167, 0, 0.2)","--loki-error":"var(--vscode-errorForeground, #f48771)","--loki-error-muted":"rgba(244, 135, 113, 0.2)","--loki-info":"var(--vscode-editorInfo-foreground, #75beff)","--loki-info-muted":"rgba(117, 190, 255, 0.2)","--loki-green":"var(--vscode-testing-iconPassed, #89d185)","--loki-green-muted":"rgba(137, 209, 133, 0.2)","--loki-yellow":"var(--vscode-editorWarning-foreground, #cca700)","--loki-yellow-muted":"rgba(204, 167, 0, 0.2)","--loki-red":"var(--vscode-errorForeground, #f48771)","--loki-red-muted":"rgba(244, 135, 113, 0.2)","--loki-blue":"var(--vscode-editorInfo-foreground, #75beff)","--loki-blue-muted":"rgba(117, 190, 255, 0.2)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.2)","--loki-opus":"#f59e0b","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.3)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.4)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.5)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #007fd4)"}},A={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},I={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},y={fontFamily:{sans:"'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif",serif:"'DM Serif Display', Georgia, 'Times New Roman', serif",mono:"'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace"},fontSize:{xs:"10px",sm:"11px",base:"12px",md:"13px",lg:"14px",xl:"16px","2xl":"18px","3xl":"24px"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.75"}},L={duration:{fast:"100ms",normal:"200ms",slow:"300ms",slower:"500ms"},easing:{default:"cubic-bezier(0.4, 0, 0.2, 1)",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)",bounce:"cubic-bezier(0.68, -0.55, 0.265, 1.55)"}},$t={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},D={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Et={"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"]}},Ct={button:{role:"button",tabIndex:0},tablist:{role:"tablist"},tab:{role:"tab",ariaSelected:!1,tabIndex:-1},tabpanel:{role:"tabpanel",tabIndex:0},list:{role:"list"},listitem:{role:"listitem"},livePolite:{ariaLive:"polite",ariaAtomic:!0},liveAssertive:{ariaLive:"assertive",ariaAtomic:!0},dialog:{role:"dialog",ariaModal:!0},alertdialog:{role:"alertdialog",ariaModal:!0},status:{role:"status",ariaLive:"polite"},alert:{role:"alert",ariaLive:"assertive"},log:{role:"log",ariaLive:"polite",ariaRelevant:"additions"}};function $(d){let t=E[d];return t?Object.entries(t).map(([e,a])=>`${e}: ${a};`).join(`
|
|
1211
|
+
var LokiDashboard=(()=>{var $t=Object.defineProperty;var ae=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var re=Object.prototype.hasOwnProperty;var oe=(d,t,e)=>t in d?$t(d,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):d[t]=e;var ne=(d,t)=>{for(var e in t)$t(d,e,{get:t[e],enumerable:!0})},le=(d,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of se(t))!re.call(d,a)&&a!==e&&$t(d,a,{get:()=>t[a],enumerable:!(i=ae(t,a))||i.enumerable});return d};var de=d=>le($t({},"__esModule",{value:!0}),d);var C=(d,t,e)=>oe(d,typeof t!="symbol"?t+"":t,e);var Me={};ne(Me,{ANIMATION:()=>L,ARIA_PATTERNS:()=>St,ApiEvents:()=>m,BASE_STYLES:()=>U,BREAKPOINTS:()=>Et,COMMON_STYLES:()=>Mt,KEYBOARD_SHORTCUTS:()=>Ct,KeyboardHandler:()=>P,LokiActivityStream:()=>ut,LokiAgentLeaderboard:()=>kt,LokiAnalytics:()=>ot,LokiApiClient:()=>M,LokiApiKeys:()=>pt,LokiAppStatus:()=>Q,LokiAuditViewer:()=>ct,LokiChecklistViewer:()=>W,LokiCheckpointViewer:()=>Z,LokiContextTracker:()=>tt,LokiCostDashboard:()=>X,LokiCostWaterfall:()=>ft,LokiCouncilDashboard:()=>Y,LokiCouncilTranscripts:()=>yt,LokiElement:()=>h,LokiEscalations:()=>_t,LokiLearningDashboard:()=>V,LokiLogStream:()=>G,LokiManagedMemoryPanel:()=>xt,LokiMemoryBrowser:()=>K,LokiMemoryGraph:()=>bt,LokiMigrationDashboard:()=>rt,LokiNotificationCenter:()=>et,LokiOverview:()=>O,LokiPipelineView:()=>vt,LokiPromptOptimizer:()=>at,LokiProviderHealth:()=>gt,LokiQualityGates:()=>nt,LokiQualityScore:()=>st,LokiRarvTimeline:()=>lt,LokiRunManager:()=>dt,LokiSessionControl:()=>J,LokiSessionDiff:()=>it,LokiState:()=>N,LokiTaskBoard:()=>q,LokiTenantSwitcher:()=>ht,LokiTheme:()=>R,LokiWikiBrowser:()=>wt,RADIUS:()=>I,SPACING:()=>A,STATE_CHANGE_EVENT:()=>It,THEMES:()=>E,THEME_VARIABLES:()=>At,TYPOGRAPHY:()=>y,UnifiedThemeManager:()=>_,VERSION:()=>Be,Z_INDEX:()=>D,createApiClient:()=>Ut,createStore:()=>Nt,generateThemeCSS:()=>$,generateTokensCSS:()=>j,getApiClient:()=>g,getState:()=>B,init:()=>Pe});var E={light:{"--loki-bg-primary":"#FFFEFB","--loki-bg-secondary":"#F8F4F0","--loki-bg-tertiary":"#ECEAE3","--loki-bg-card":"#ffffff","--loki-bg-hover":"#F3EFE9","--loki-bg-active":"#E6E2DA","--loki-bg-overlay":"rgba(32, 21, 21, 0.5)","--loki-accent":"#553DE9","--loki-accent-hover":"#4432c4","--loki-accent-active":"#3828a0","--loki-accent-light":"#7B6BF0","--loki-accent-muted":"rgba(85, 61, 233, 0.10)","--loki-text-primary":"#201515","--loki-text-secondary":"#36342E","--loki-text-muted":"#939084","--loki-text-disabled":"#C5C0B1","--loki-text-inverse":"#ffffff","--loki-border":"#ECEAE3","--loki-border-light":"#C5C0B1","--loki-border-focus":"#553DE9","--loki-success":"#1FC5A8","--loki-success-muted":"rgba(31, 197, 168, 0.12)","--loki-warning":"#D4A03C","--loki-warning-muted":"rgba(212, 160, 60, 0.12)","--loki-error":"#C45B5B","--loki-error-muted":"rgba(196, 91, 91, 0.12)","--loki-info":"#2F71E3","--loki-info-muted":"rgba(47, 113, 227, 0.12)","--loki-green":"#1FC5A8","--loki-green-muted":"rgba(31, 197, 168, 0.12)","--loki-yellow":"#D4A03C","--loki-yellow-muted":"rgba(212, 160, 60, 0.12)","--loki-red":"#C45B5B","--loki-red-muted":"rgba(196, 91, 91, 0.12)","--loki-blue":"#2F71E3","--loki-blue-muted":"rgba(47, 113, 227, 0.12)","--loki-purple":"#553DE9","--loki-purple-muted":"rgba(85, 61, 233, 0.10)","--loki-opus":"#d97706","--loki-sonnet":"#553DE9","--loki-haiku":"#1FC5A8","--loki-shadow-sm":"0 1px 2px rgba(32, 21, 21, 0.04)","--loki-shadow-md":"0 4px 6px rgba(32, 21, 21, 0.06)","--loki-shadow-lg":"0 10px 15px rgba(32, 21, 21, 0.08)","--loki-shadow-focus":"0 0 0 3px rgba(85, 61, 233, 0.25)"},dark:{"--loki-bg-primary":"#1A0F2E","--loki-bg-secondary":"#140B24","--loki-bg-tertiary":"#251842","--loki-bg-card":"#1F1338","--loki-bg-hover":"#2A1F4A","--loki-bg-active":"#352A55","--loki-bg-overlay":"rgba(20, 11, 36, 0.85)","--loki-accent":"#7B6BF0","--loki-accent-hover":"#9488F5","--loki-accent-active":"#6258D0","--loki-accent-light":"#9488F5","--loki-accent-muted":"rgba(123, 107, 240, 0.18)","--loki-text-primary":"#F0ECF8","--loki-text-secondary":"#C0B8D0","--loki-text-muted":"#8B7FA8","--loki-text-disabled":"#5A4E78","--loki-text-inverse":"#1A0F2E","--loki-border":"#2A1F3E","--loki-border-light":"#3D3060","--loki-border-focus":"#7B6BF0","--loki-success":"#2ED8B6","--loki-success-muted":"rgba(46, 216, 182, 0.18)","--loki-warning":"#E8B84A","--loki-warning-muted":"rgba(232, 184, 74, 0.18)","--loki-error":"#E07070","--loki-error-muted":"rgba(224, 112, 112, 0.18)","--loki-info":"#5A9CF5","--loki-info-muted":"rgba(90, 156, 245, 0.18)","--loki-green":"#2ED8B6","--loki-green-muted":"rgba(46, 216, 182, 0.18)","--loki-yellow":"#E8B84A","--loki-yellow-muted":"rgba(232, 184, 74, 0.18)","--loki-red":"#E07070","--loki-red-muted":"rgba(224, 112, 112, 0.18)","--loki-blue":"#5A9CF5","--loki-blue-muted":"rgba(90, 156, 245, 0.18)","--loki-purple":"#9488F5","--loki-purple-muted":"rgba(148, 136, 245, 0.18)","--loki-opus":"#f59e0b","--loki-sonnet":"#7B6BF0","--loki-haiku":"#2ED8B6","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.4)","--loki-shadow-md":"0 4px 12px rgba(0, 0, 0, 0.5)","--loki-shadow-lg":"0 10px 25px rgba(0, 0, 0, 0.6)","--loki-shadow-focus":"0 0 0 3px rgba(123, 107, 240, 0.30)"},"high-contrast":{"--loki-bg-primary":"#000000","--loki-bg-secondary":"#0a0a0a","--loki-bg-tertiary":"#141414","--loki-bg-card":"#0a0a0a","--loki-bg-hover":"#1a1a1a","--loki-bg-active":"#242424","--loki-bg-overlay":"rgba(0, 0, 0, 0.9)","--loki-accent":"#c084fc","--loki-accent-hover":"#d8b4fe","--loki-accent-active":"#e9d5ff","--loki-accent-light":"#d8b4fe","--loki-accent-muted":"rgba(192, 132, 252, 0.25)","--loki-text-primary":"#ffffff","--loki-text-secondary":"#e0e0e0","--loki-text-muted":"#b0b0b0","--loki-text-disabled":"#666666","--loki-text-inverse":"#000000","--loki-border":"#ffffff","--loki-border-light":"#cccccc","--loki-border-focus":"#c084fc","--loki-success":"#4ade80","--loki-success-muted":"rgba(74, 222, 128, 0.25)","--loki-warning":"#fde047","--loki-warning-muted":"rgba(253, 224, 71, 0.25)","--loki-error":"#f87171","--loki-error-muted":"rgba(248, 113, 113, 0.25)","--loki-info":"#60a5fa","--loki-info-muted":"rgba(96, 165, 250, 0.25)","--loki-green":"#4ade80","--loki-green-muted":"rgba(74, 222, 128, 0.25)","--loki-yellow":"#fde047","--loki-yellow-muted":"rgba(253, 224, 71, 0.25)","--loki-red":"#f87171","--loki-red-muted":"rgba(248, 113, 113, 0.25)","--loki-blue":"#60a5fa","--loki-blue-muted":"rgba(96, 165, 250, 0.25)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.25)","--loki-opus":"#fbbf24","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"none","--loki-shadow-md":"none","--loki-shadow-lg":"none","--loki-shadow-focus":"0 0 0 3px #c084fc"},"vscode-light":{"--loki-bg-primary":"var(--vscode-editor-background, #ffffff)","--loki-bg-secondary":"var(--vscode-sideBar-background, #f3f3f3)","--loki-bg-tertiary":"var(--vscode-input-background, #ffffff)","--loki-bg-card":"var(--vscode-editor-background, #ffffff)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #e8e8e8)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #0060c0)","--loki-bg-overlay":"rgba(0, 0, 0, 0.4)","--loki-accent":"var(--vscode-focusBorder, #0066cc)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #0055aa)","--loki-accent-active":"var(--vscode-button-background, #007acc)","--loki-accent-light":"var(--vscode-focusBorder, #0066cc)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 102, 204, 0.2))","--loki-text-primary":"var(--vscode-foreground, #333333)","--loki-text-secondary":"var(--vscode-descriptionForeground, #717171)","--loki-text-muted":"var(--vscode-disabledForeground, #a0a0a0)","--loki-text-disabled":"var(--vscode-disabledForeground, #cccccc)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #c8c8c8)","--loki-border-light":"var(--vscode-widget-border, #e0e0e0)","--loki-border-focus":"var(--vscode-focusBorder, #0066cc)","--loki-success":"var(--vscode-testing-iconPassed, #388a34)","--loki-success-muted":"rgba(56, 138, 52, 0.15)","--loki-warning":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-warning-muted":"rgba(191, 136, 3, 0.15)","--loki-error":"var(--vscode-errorForeground, #e51400)","--loki-error-muted":"rgba(229, 20, 0, 0.15)","--loki-info":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-info-muted":"rgba(26, 133, 255, 0.15)","--loki-green":"var(--vscode-testing-iconPassed, #388a34)","--loki-green-muted":"rgba(56, 138, 52, 0.15)","--loki-yellow":"var(--vscode-editorWarning-foreground, #bf8803)","--loki-yellow-muted":"rgba(191, 136, 3, 0.15)","--loki-red":"var(--vscode-errorForeground, #e51400)","--loki-red-muted":"rgba(229, 20, 0, 0.15)","--loki-blue":"var(--vscode-editorInfo-foreground, #1a85ff)","--loki-blue-muted":"rgba(26, 133, 255, 0.15)","--loki-purple":"#9333ea","--loki-purple-muted":"rgba(147, 51, 234, 0.15)","--loki-opus":"#d97706","--loki-sonnet":"#4f46e5","--loki-haiku":"#059669","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.05)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.1)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.15)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #0066cc)"},"vscode-dark":{"--loki-bg-primary":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-secondary":"var(--vscode-sideBar-background, #252526)","--loki-bg-tertiary":"var(--vscode-input-background, #3c3c3c)","--loki-bg-card":"var(--vscode-editor-background, #1e1e1e)","--loki-bg-hover":"var(--vscode-list-hoverBackground, #2a2d2e)","--loki-bg-active":"var(--vscode-list-activeSelectionBackground, #094771)","--loki-bg-overlay":"rgba(0, 0, 0, 0.6)","--loki-accent":"var(--vscode-focusBorder, #007fd4)","--loki-accent-hover":"var(--vscode-button-hoverBackground, #1177bb)","--loki-accent-active":"var(--vscode-button-background, #0e639c)","--loki-accent-light":"var(--vscode-focusBorder, #007fd4)","--loki-accent-muted":"var(--vscode-editor-selectionBackground, rgba(0, 127, 212, 0.25))","--loki-text-primary":"var(--vscode-foreground, #cccccc)","--loki-text-secondary":"var(--vscode-descriptionForeground, #9d9d9d)","--loki-text-muted":"var(--vscode-disabledForeground, #6b6b6b)","--loki-text-disabled":"var(--vscode-disabledForeground, #4d4d4d)","--loki-text-inverse":"var(--vscode-button-foreground, #ffffff)","--loki-border":"var(--vscode-widget-border, #454545)","--loki-border-light":"var(--vscode-widget-border, #5a5a5a)","--loki-border-focus":"var(--vscode-focusBorder, #007fd4)","--loki-success":"var(--vscode-testing-iconPassed, #89d185)","--loki-success-muted":"rgba(137, 209, 133, 0.2)","--loki-warning":"var(--vscode-editorWarning-foreground, #cca700)","--loki-warning-muted":"rgba(204, 167, 0, 0.2)","--loki-error":"var(--vscode-errorForeground, #f48771)","--loki-error-muted":"rgba(244, 135, 113, 0.2)","--loki-info":"var(--vscode-editorInfo-foreground, #75beff)","--loki-info-muted":"rgba(117, 190, 255, 0.2)","--loki-green":"var(--vscode-testing-iconPassed, #89d185)","--loki-green-muted":"rgba(137, 209, 133, 0.2)","--loki-yellow":"var(--vscode-editorWarning-foreground, #cca700)","--loki-yellow-muted":"rgba(204, 167, 0, 0.2)","--loki-red":"var(--vscode-errorForeground, #f48771)","--loki-red-muted":"rgba(244, 135, 113, 0.2)","--loki-blue":"var(--vscode-editorInfo-foreground, #75beff)","--loki-blue-muted":"rgba(117, 190, 255, 0.2)","--loki-purple":"#c084fc","--loki-purple-muted":"rgba(192, 132, 252, 0.2)","--loki-opus":"#f59e0b","--loki-sonnet":"#818cf8","--loki-haiku":"#34d399","--loki-shadow-sm":"0 1px 2px rgba(0, 0, 0, 0.3)","--loki-shadow-md":"0 2px 4px rgba(0, 0, 0, 0.4)","--loki-shadow-lg":"0 4px 8px rgba(0, 0, 0, 0.5)","--loki-shadow-focus":"0 0 0 2px var(--vscode-focusBorder, #007fd4)"}},A={xs:"4px",sm:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"32px","3xl":"48px"},I={none:"0",sm:"2px",md:"4px",lg:"5px",xl:"5px",full:"9999px"},y={fontFamily:{sans:"'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif",serif:"'DM Serif Display', Georgia, 'Times New Roman', serif",mono:"'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace"},fontSize:{xs:"10px",sm:"11px",base:"12px",md:"13px",lg:"14px",xl:"16px","2xl":"18px","3xl":"24px"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.75"}},L={duration:{fast:"100ms",normal:"200ms",slow:"300ms",slower:"500ms"},easing:{default:"cubic-bezier(0.4, 0, 0.2, 1)",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)",bounce:"cubic-bezier(0.68, -0.55, 0.265, 1.55)"}},Et={sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},D={base:"0",dropdown:"100",sticky:"200",modal:"300",popover:"400",tooltip:"500",toast:"600"},Ct={"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"]}},St={button:{role:"button",tabIndex:0},tablist:{role:"tablist"},tab:{role:"tab",ariaSelected:!1,tabIndex:-1},tabpanel:{role:"tabpanel",tabIndex:0},list:{role:"list"},listitem:{role:"listitem"},livePolite:{ariaLive:"polite",ariaAtomic:!0},liveAssertive:{ariaLive:"assertive",ariaAtomic:!0},dialog:{role:"dialog",ariaModal:!0},alertdialog:{role:"alertdialog",ariaModal:!0},status:{role:"status",ariaLive:"polite"},alert:{role:"alert",ariaLive:"assertive"},log:{role:"log",ariaLive:"polite",ariaRelevant:"additions"}};function $(d){let t=E[d];return t?Object.entries(t).map(([e,i])=>`${e}: ${i};`).join(`
|
|
1200
1212
|
`):""}function j(){return`
|
|
1201
1213
|
/* Spacing */
|
|
1202
1214
|
--loki-space-xs: ${A.xs};
|
|
@@ -1523,20 +1535,20 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1523
1535
|
}
|
|
1524
1536
|
|
|
1525
1537
|
/* Responsive utilities */
|
|
1526
|
-
@media (max-width: ${
|
|
1538
|
+
@media (max-width: ${Et.md}) {
|
|
1527
1539
|
.hide-mobile { display: none !important; }
|
|
1528
1540
|
}
|
|
1529
1541
|
|
|
1530
|
-
@media (min-width: ${
|
|
1542
|
+
@media (min-width: ${Et.md}) {
|
|
1531
1543
|
.hide-desktop { display: none !important; }
|
|
1532
1544
|
}
|
|
1533
|
-
`,k=class k{static detectContext(){return typeof acquireVsCodeApi<"u"||document.body.classList.contains("vscode-body")||getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background")?"vscode":document.documentElement.dataset.lokiContext==="cli"?"cli":"browser"}static detectVSCodeTheme(){let t=document.body;if(t.classList.contains("vscode-high-contrast"))return"high-contrast";if(t.classList.contains("vscode-dark"))return"dark";if(t.classList.contains("vscode-light"))return"light";let e=getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background");if(e){let
|
|
1545
|
+
`,k=class k{static detectContext(){return typeof acquireVsCodeApi<"u"||document.body.classList.contains("vscode-body")||getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background")?"vscode":document.documentElement.dataset.lokiContext==="cli"?"cli":"browser"}static detectVSCodeTheme(){let t=document.body;if(t.classList.contains("vscode-high-contrast"))return"high-contrast";if(t.classList.contains("vscode-dark"))return"dark";if(t.classList.contains("vscode-light"))return"light";let e=getComputedStyle(document.documentElement).getPropertyValue("--vscode-editor-background");if(e){let i=e.match(/\d+/g);if(i)return(parseInt(i[0])*299+parseInt(i[1])*587+parseInt(i[2])*114)/1e3>128?"light":"dark"}return null}static getTheme(){if(k.detectContext()==="vscode"){let i=k.detectVSCodeTheme();return i==="high-contrast"?"high-contrast":i==="dark"?"vscode-dark":"vscode-light"}let e=localStorage.getItem(k.STORAGE_KEY);return e&&E[e]?e:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}static setTheme(t){if(!E[t]){console.warn(`Unknown theme: ${t}`);return}localStorage.setItem(k.STORAGE_KEY,t),document.documentElement.setAttribute("data-loki-theme",t),window.dispatchEvent(new CustomEvent("loki-theme-change",{detail:{theme:t,context:k.detectContext()}}))}static toggle(){let t=k.getTheme(),e;return t.includes("dark")||t==="high-contrast"?e=t.startsWith("vscode")?"vscode-light":"light":e=t.startsWith("vscode")?"vscode-dark":"dark",k.setTheme(e),e}static getVariables(t=null){let e=t||k.getTheme();return E[e]||E.light}static generateCSS(t=null){let e=t||k.getTheme();return`
|
|
1534
1546
|
:host {
|
|
1535
1547
|
${$(e)}
|
|
1536
1548
|
${j()}
|
|
1537
1549
|
}
|
|
1538
1550
|
${U}
|
|
1539
|
-
`}static init(){let t=k.getTheme();document.documentElement.setAttribute("data-loki-theme",t),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{localStorage.getItem(k.STORAGE_KEY)||k.setTheme(k.getTheme())}),k.detectContext()==="vscode"&&new MutationObserver(()=>{let
|
|
1551
|
+
`}static init(){let t=k.getTheme();document.documentElement.setAttribute("data-loki-theme",t),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{localStorage.getItem(k.STORAGE_KEY)||k.setTheme(k.getTheme())}),k.detectContext()==="vscode"&&new MutationObserver(()=>{let i=k.getTheme();document.documentElement.setAttribute("data-loki-theme",i),window.dispatchEvent(new CustomEvent("loki-theme-change",{detail:{theme:i,context:"vscode"}}))}).observe(document.body,{attributes:!0,attributeFilter:["class"]})}};C(k,"STORAGE_KEY","loki-theme"),C(k,"CONTEXT_KEY","loki-context");var _=k,P=class{constructor(){this._handlers=new Map,this._enabled=!0}register(t,e){let i=Ct[t];if(!i){console.warn(`Unknown keyboard action: ${t}`);return}this._handlers.set(t,{shortcut:i,handler:e})}unregister(t){this._handlers.delete(t)}setEnabled(t){this._enabled=t}handleEvent(t){if(!this._enabled)return!1;for(let[e,{shortcut:i,handler:a}]of this._handlers)if(this._matchesShortcut(t,i))return t.preventDefault(),t.stopPropagation(),a(t),!0;return!1}_matchesShortcut(t,e){let i=t.key.toLowerCase(),a=e.modifiers||[];if(i!==e.key.toLowerCase())return!1;let s=a.includes("Ctrl")||a.includes("Meta"),r=a.includes("Shift"),o=a.includes("Alt"),n=(t.ctrlKey||t.metaKey)===s,l=t.shiftKey===r,c=t.altKey===o;return n&&l&&c}attach(t){this._boundHandler||(this._boundHandler=e=>this.handleEvent(e)),t.addEventListener("keydown",this._boundHandler)}detach(t){this._boundHandler&&t.removeEventListener("keydown",this._boundHandler)}};var At={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)"}},Mt=`
|
|
1540
1552
|
:host {
|
|
1541
1553
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
1542
1554
|
line-height: 1.5;
|
|
@@ -1632,8 +1644,8 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1632
1644
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary); }
|
|
1633
1645
|
::-webkit-scrollbar-thumb { background: var(--loki-border); border-radius: 3px; }
|
|
1634
1646
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light); }
|
|
1635
|
-
`,H=class H{static getTheme(){return _.getTheme()}static setTheme(t){_.setTheme(t)}static toggle(){return _.toggle()}static getVariables(t=null){let e=t||H.getTheme();return E[e]||
|
|
1636
|
-
`)}static applyToElement(t,e=null){let
|
|
1647
|
+
`,H=class H{static getTheme(){return _.getTheme()}static setTheme(t){_.setTheme(t)}static toggle(){return _.toggle()}static getVariables(t=null){let e=t||H.getTheme();return E[e]||At[e]||At.light}static toCSSString(t=null){let e=t||H.getTheme();if(E[e])return $(e);let i=H.getVariables(e);return Object.entries(i).map(([a,s])=>`${a}: ${s};`).join(`
|
|
1648
|
+
`)}static applyToElement(t,e=null){let i=H.getVariables(e);for(let[a,s]of Object.entries(i))t.style.setProperty(a,s)}static init(){_.init()}static detectContext(){return _.detectContext()}static getAvailableThemes(){return Object.keys(E)}};C(H,"STORAGE_KEY","loki-theme");var R=H,h=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._theme=R.getTheme(),this._themeChangeHandler=this._onThemeChange.bind(this),this._keyboardHandler=new P}connectedCallback(){window.addEventListener("loki-theme-change",this._themeChangeHandler),this._applyTheme(),this._setupKeyboardHandling(),this.render()}disconnectedCallback(){window.removeEventListener("loki-theme-change",this._themeChangeHandler),this._keyboardHandler.detach(this)}_onThemeChange(t){this._theme=t.detail.theme,this._applyTheme(),this.onThemeChange&&this.onThemeChange(this._theme)}_applyTheme(){R.applyToElement(this.shadowRoot.host,this._theme),this.setAttribute("data-loki-theme",this._theme)}_setupKeyboardHandling(){this._keyboardHandler.attach(this)}registerShortcut(t,e){this._keyboardHandler.register(t,e)}getBaseStyles(){return`
|
|
1637
1649
|
/* Design tokens */
|
|
1638
1650
|
:host {
|
|
1639
1651
|
${j()}
|
|
@@ -1689,15 +1701,15 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1689
1701
|
}
|
|
1690
1702
|
|
|
1691
1703
|
${U}
|
|
1692
|
-
`}getAriaPattern(t){return Ct[t]||{}}applyAriaPattern(t,e){let a=this.getAriaPattern(e);for(let[i,s]of Object.entries(a))if(i==="role")t.setAttribute("role",s);else{let r=i.replace(/([A-Z])/g,"-$1").toLowerCase();t.setAttribute(r,s)}}render(){}};var z={realtime:1e3,normal:2e3,background:5e3,offline:1e4},Mt={vscode:z.normal,browser:z.realtime,cli:z.background},Ft={baseUrl:typeof window<"u"?window.location.origin:"http://localhost:57374",wsUrl:typeof window<"u"?`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws`:"ws://localhost:57374/ws",pollInterval:2e3,timeout:1e4,retryAttempts:3,retryDelay:1e3},v={CONNECTED:"api:connected",DISCONNECTED:"api:disconnected",ERROR:"api:error",STATUS_UPDATE:"api:status-update",TASK_CREATED:"api:task-created",TASK_UPDATED:"api:task-updated",TASK_DELETED:"api:task-deleted",PROJECT_CREATED:"api:project-created",PROJECT_UPDATED:"api:project-updated",AGENT_UPDATE:"api:agent-update",LOG_MESSAGE:"api:log-message",MEMORY_UPDATE:"api:memory-update",CHECKLIST_UPDATE:"api:checklist-update"},T=class T extends EventTarget{static getInstance(t={}){let e=t.baseUrl||Ft.baseUrl;return T._instances.has(e)||T._instances.set(e,new T(t)),T._instances.get(e)}static clearInstances(){T._instances.forEach(t=>t.disconnect()),T._instances.clear()}constructor(t={}){super(),this.config={...Ft,...t},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=Mt[this._context]||z.normal,this._visibilityChangeHandler=null,this._messageHandler=null,this._setupAdaptivePolling(),this._setupVSCodeBridge()}_detectContext(){return typeof acquireVsCodeApi<"u"?"vscode":typeof window<"u"&&window.location?"browser":"cli"}get context(){return this._context}static get POLL_INTERVALS(){return z}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(z.background):this._setPollInterval(Mt[this._context]||z.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(t){this._currentPollInterval=t,this._pollInterval&&(this.stopPolling(),this.startPolling(null,t))}setPollMode(t){let e=z[t];e&&this._setPollInterval(e)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=t=>{let e=t.data;if(!(!e||!e.type))switch(e.type){case"updateStatus":this._emit(v.STATUS_UPDATE,e.data);break;case"updateTasks":this._emit(v.TASK_UPDATED,e.data);break;case"taskCreated":this._emit(v.TASK_CREATED,e.data);break;case"taskDeleted":this._emit(v.TASK_DELETED,e.data);break;case"projectCreated":this._emit(v.PROJECT_CREATED,e.data);break;case"projectUpdated":this._emit(v.PROJECT_UPDATED,e.data);break;case"agentUpdate":this._emit(v.AGENT_UPDATE,e.data);break;case"logMessage":this._emit(v.LOG_MESSAGE,e.data);break;case"memoryUpdate":this._emit(v.MEMORY_UPDATE,e.data);break;case"connected":this._connected=!0,this._emit(v.CONNECTED,e.data);break;case"disconnected":this._connected=!1,this._emit(v.DISCONNECTED,e.data);break;case"error":this._emit(v.ERROR,e.data);break;case"setPollMode":this.setPollMode(e.data.mode);break;default:this._emit(`api:${e.type}`,e.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(t,e={}){this._vscodeApi&&this._vscodeApi.postMessage({type:t,data:e})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(t,e={}){this.postToVSCode("userAction",{action:t,...e})}get baseUrl(){return this.config.baseUrl}set baseUrl(t){this.config.baseUrl=t,this.config.wsUrl=t.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((t,e)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._reconnectAttempts=0,this._emit(v.CONNECTED),t()},this._ws.onclose=()=>{this._connected=!1,this._emit(v.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=a=>{this._emit(v.ERROR,{error:a}),e(a)},this._ws.onmessage=a=>{try{let i=JSON.parse(a.data);this._handleMessage(i)}catch(i){console.error("Failed to parse WebSocket message:",i)}}}catch(a){e(a)}})}disconnect(){this._ws&&(this._ws.close(),this._ws=null),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._reconnectTimeout&&(clearTimeout(this._reconnectTimeout),this._reconnectTimeout=null),this._connected=!1,this._cleanupGlobalListeners()}_cleanupGlobalListeners(){this._visibilityChangeHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this._visibilityChangeHandler),this._visibilityChangeHandler=null),this._messageHandler&&typeof window<"u"&&(window.removeEventListener("message",this._messageHandler),this._messageHandler=null)}destroy(){this.disconnect()}_scheduleReconnect(){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 t=Math.min(this.config.retryDelay*Math.pow(2,this._reconnectAttempts),3e4);this._reconnectAttempts++,this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},t)}_handleMessage(t){if(t.type==="ping"){this._ws&&this._ws.readyState===WebSocket.OPEN&&this._ws.send(JSON.stringify({type:"pong"}));return}let a={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}[t.type]||`api:${t.type}`;this._emit(a,t.data)}_emit(t,e={}){this.dispatchEvent(new CustomEvent(t,{detail:e}))}async _request(t,e={}){let a=`${this.config.baseUrl}${t}`,i=new AbortController,s=setTimeout(()=>i.abort(),this.config.timeout);try{let r=await fetch(a,{...e,signal:i.signal,credentials:"include",headers:{"Content-Type":"application/json",...e.headers}});if(clearTimeout(s),!r.ok){let o=await r.text().catch(()=>""),n=r.statusText||`HTTP ${r.status}`;if(o)try{let l=JSON.parse(o);n=l.detail||l.error||l.message||n}catch{n=o.length>200?o.slice(0,200)+"...":o}throw new Error(n)}return r.status===204?null:await r.json()}catch(r){throw clearTimeout(s),r.name==="AbortError"?new Error("Request timeout"):r}}async _get(t,e=!1){if(e&&this._cache.has(t)){let i=this._cache.get(t);if(Date.now()-i.timestamp<this._cacheTimeout)return i.data}let a=await this._request(t);return e&&this._cache.set(t,{data:a,timestamp:Date.now()}),a}async _post(t,e){return this._request(t,{method:"POST",body:JSON.stringify(e)})}async _put(t,e){return this._request(t,{method:"PUT",body:JSON.stringify(e)})}async _delete(t){return this._request(t,{method:"DELETE"})}async get(t){return this._get(t)}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(t=null){let e=t?`?status=${t}`:"";return this._get(`/api/projects${e}`)}async getProject(t){return this._get(`/api/projects/${t}`)}async createProject(t){return this._post("/api/projects",t)}async updateProject(t,e){return this._put(`/api/projects/${t}`,e)}async deleteProject(t){return this._delete(`/api/projects/${t}`)}async listTasks(t={}){let e=new URLSearchParams;t.projectId&&e.append("project_id",t.projectId),t.status&&e.append("status",t.status),t.priority&&e.append("priority",t.priority);let a=e.toString()?`?${e}`:"";return this._get(`/api/tasks${a}`)}async getTask(t){return this._get(`/api/tasks/${t}`)}async createTask(t){return this._post("/api/tasks",t)}async updateTask(t,e){return this._put(`/api/tasks/${t}`,e)}async moveTask(t,e,a){return this._post(`/api/tasks/${t}/move`,{status:e,position:a})}async deleteTask(t){return this._delete(`/api/tasks/${t}`)}async getMemorySummary(){return this._get("/api/memory/summary",!0)}async getMemoryIndex(){return this._get("/api/memory/index",!0)}async getMemoryTimeline(){return this._get("/api/memory/timeline")}async listEpisodes(t={}){let e=new URLSearchParams(t).toString();return this._get(`/api/memory/episodes${e?"?"+e:""}`)}async getEpisode(t){return this._get(`/api/memory/episodes/${t}`)}async listPatterns(t={}){let e=new URLSearchParams(t).toString();return this._get(`/api/memory/patterns${e?"?"+e:""}`)}async getPattern(t){return this._get(`/api/memory/patterns/${t}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(t){return this._get(`/api/memory/skills/${t}`)}async retrieveMemories(t,e=null,a=5){return this._post("/api/memory/retrieve",{query:t,taskType:e,topK:a})}async consolidateMemory(t=24){return this._post("/api/memory/consolidate",{sinceHours:t})}async getTokenEconomics(){return this._get("/api/memory/economics")}async searchMemory(t,e="all",a=20){let i=new URLSearchParams({q:t,collection:e,limit:String(a)});return this._get(`/api/memory/search?${i}`)}async getMemoryStats(){return this._get("/api/memory/stats",!0)}async listRegisteredProjects(t=!1){return this._get(`/api/registry/projects?include_inactive=${t}`)}async registerProject(t,e=null,a=null){return this._post("/api/registry/projects",{path:t,name:e,alias:a})}async discoverProjects(t=3){return this._get(`/api/registry/discover?max_depth=${t}`)}async syncRegistry(){return this._post("/api/registry/sync",{})}async getCrossProjectTasks(t=null){let e=t?`?project_ids=${t.join(",")}`:"";return this._get(`/api/registry/tasks${e}`)}async getLearningMetrics(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source);let a=e.toString()?`?${e}`:"";return this._get(`/api/learning/metrics${a}`)}async getLearningTrends(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source);let a=e.toString()?`?${e}`:"";return this._get(`/api/learning/trends${a}`)}async getLearningSignals(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source),t.limit&&e.append("limit",String(t.limit)),t.offset&&e.append("offset",String(t.offset));let a=e.toString()?`?${e}`:"";return this._get(`/api/learning/signals${a}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(t={}){return this._post("/api/learning/aggregate",t)}async getAggregatedPreferences(t=20){return this._get(`/api/learning/preferences?limit=${t}`)}async getAggregatedErrors(t=20){return this._get(`/api/learning/errors?limit=${t}`)}async getAggregatedSuccessPatterns(t=20){return this._get(`/api/learning/success?limit=${t}`)}async getToolEfficiency(t=20){return this._get(`/api/learning/tools?limit=${t}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(t=20){return this._get(`/api/council/verdicts?limit=${t}`)}async getCouncilConvergence(){return this._get("/api/council/convergence")}async getCouncilReport(){return this._get("/api/council/report")}async forceCouncilReview(){return this._post("/api/council/force-review",{})}async getContext(){return this._get("/api/context")}async getNotifications(t,e){let a=new URLSearchParams;t&&a.set("severity",t),e&&a.set("unread_only","true");let i=a.toString();return this._get("/api/notifications"+(i?"?"+i:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(t){return this._put("/api/notifications/triggers",{triggers:t})}async acknowledgeNotification(t){return this._post("/api/notifications/"+encodeURIComponent(t)+"/acknowledge",{})}async pauseSession(){return this._post("/api/control/pause",{})}async resumeSession(){return this._post("/api/control/resume",{})}async stopSession(){return this._post("/api/control/stop",{})}async getLogs(t=100){return this._get(`/api/logs?lines=${t}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let t=await fetch(`${this.baseUrl}/api/prd-observations`,{credentials:"include"});if(!t.ok)throw new Error(`HTTP ${t.status}`);return t.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(t,e,a="dashboard"){return this._post("/api/checklist/waivers",{item_id:t,reason:e,waived_by:a})}async removeChecklistWaiver(t){return this._delete(`/api/checklist/waivers/${encodeURIComponent(t)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(t=100){return this._get(`/api/app-runner/logs?lines=${t}`)}async restartApp(){return this._post("/api/control/app-restart",{})}async stopApp(){return this._post("/api/control/app-stop",{})}async getPlaywrightResults(){return this._get("/api/playwright/results")}async getPlaywrightScreenshot(){return this._get("/api/playwright/screenshot")}startPolling(t,e=null){if(this._pollInterval)return;this._pollCallback=t;let a=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(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})}};a();let i=e||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(a,i)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};C(T,"_instances",new Map);var M=T;function jt(d={}){return new M(d)}function g(d={}){return M.getInstance(d)}var Tt="loki-state-change",At={ui:{theme:"light",sidebarCollapsed:!1,activeSection:"kanban",terminalAutoScroll:!0},session:{connected:!1,lastSync:null,mode:"offline",phase:null,iteration:null},localTasks:[],cache:{projects:[],tasks:[],agents:[],memory:null,lastFetch:null},preferences:{pollInterval:2e3,notifications:!0,soundEnabled:!1}},S=class S extends EventTarget{static getInstance(){return S._instance||(S._instance=new S),S._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let t=localStorage.getItem(S.STORAGE_KEY);if(t){let e=JSON.parse(t);return this._mergeState(At,e)}}catch(t){console.warn("Failed to load state from localStorage:",t)}return{...At}}_mergeState(t,e){let a={...t};for(let i of Object.keys(e))i in t&&typeof t[i]=="object"&&!Array.isArray(t[i])?a[i]=this._mergeState(t[i],e[i]):a[i]=e[i];return a}_saveState(){try{let t={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(S.STORAGE_KEY,JSON.stringify(t))}catch(t){console.warn("Failed to save state to localStorage:",t)}}get(t=null){if(!t)return{...this._state};let e=t.split("."),a=this._state;for(let i of e){if(a==null)return;a=a[i]}return a}set(t,e,a=!0){let i=t.split("."),s=i.pop(),r=this._state;for(let n of i)n in r||(r[n]={}),r=r[n];let o=r[s];r[s]=e,a&&this._saveState(),this._notifyChange(t,e,o)}update(t,e=!0){let a=[];for(let[i,s]of Object.entries(t)){let r=this.get(i);this.set(i,s,!1),a.push({path:i,value:s,oldValue:r})}e&&this._saveState();for(let i of a)this._notifyChange(i.path,i.value,i.oldValue)}_notifyChange(t,e,a){this.dispatchEvent(new CustomEvent(Tt,{detail:{path:t,value:e,oldValue:a}}));let i=this._subscribers.get(t)||[];for(let r of i)try{r(e,a,t)}catch(o){console.error("State subscriber error:",o)}let s=t.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let n of o)try{n(this.get(r),null,r)}catch(l){console.error("State subscriber error:",l)}}}subscribe(t,e){return this._subscribers.has(t)||this._subscribers.set(t,[]),this._subscribers.get(t).push(e),()=>{let a=this._subscribers.get(t),i=a.indexOf(e);i>-1&&a.splice(i,1)}}reset(t=null){if(t){let e=t.split("."),a=At;for(let i of e)a=a?.[i];this.set(t,a)}else this._state={...At},this._saveState(),this.dispatchEvent(new CustomEvent(Tt,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(t){let e=this.get("localTasks")||[],a={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...t};return this.set("localTasks",[...e,a]),a}updateLocalTask(t,e){let a=this.get("localTasks")||[],i=a.findIndex(r=>r.id===t);if(i===-1)return null;let s={...a[i],...e,updatedAt:new Date().toISOString()};return a[i]=s,this.set("localTasks",[...a]),s}deleteLocalTask(t){let e=this.get("localTasks")||[];this.set("localTasks",e.filter(a=>a.id!==t))}moveLocalTask(t,e,a=null){let s=(this.get("localTasks")||[]).find(r=>r.id===t);return s?this.updateLocalTask(t,{status:e,position:a??s.position}):null}updateSession(t){this.update(Object.fromEntries(Object.entries(t).map(([e,a])=>[`session.${e}`,a])),!1)}updateCache(t){this.update({"cache.projects":t.projects??this.get("cache.projects"),"cache.tasks":t.tasks??this.get("cache.tasks"),"cache.agents":t.agents??this.get("cache.agents"),"cache.memory":t.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let t=this.get("cache.tasks")||[],a=(this.get("localTasks")||[]).map(i=>({...i,isLocal:!0}));return[...t,...a]}getTasksByStatus(t){return this.getMergedTasks().filter(e=>e.status===t)}};C(S,"STORAGE_KEY","loki-dashboard-state"),C(S,"_instance",null);var N=S;function B(){return N.getInstance()}function Ut(d){let t=B();return{get:()=>t.get(d),set:e=>t.set(d,e),subscribe:e=>t.subscribe(d,e)}}var O=class extends h{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(t,e,a){e!==a&&(t==="api-url"&&this._api&&(this._api.baseUrl=a,this._loadStatus()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t}),this._statusUpdateHandler=e=>this._updateFromStatus(e.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(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:t}=this._loadAbortController;try{let[e,a,i,s,r]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);if(t.aborted)return;e.status==="fulfilled"?this._updateFromStatus(e.value):(this._data.connected=!1,this._data.status="offline"),a.status==="fulfilled"&&(this._checklistSummary=a.value?.summary||null),i.status==="fulfilled"&&(this._appRunnerStatus=i.value),s.status==="fulfilled"&&(this._playwrightResults=s.value),r.status==="fulfilled"&&(this._gateStatus=r.value),this.render()}catch{if(t.aborted)return;this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(t){t&&(this._data={...this._data,connected:!0,status:t.status||"offline",phase:t.phase||null,iteration:t.iteration!=null?t.iteration:null,provider:t.provider||null,running_agents:t.running_agents||0,pending_tasks:t.pending_tasks!=null?t.pending_tasks:null,uptime_seconds:t.uptime_seconds||0,complexity:t.complexity||null})}_startPolling(){this._pollInterval=setInterval(async()=>{try{await this._loadStatus()}catch{this._data.connected=!1,this._data.status="offline",this.render()}},5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_formatUptime(t){if(!t||t<0)return"--";let e=Math.floor(t/3600),a=Math.floor(t%3600/60),i=Math.floor(t%60);return e>0?`${e}h ${a}m`:a>0?`${a}m ${i}s`:`${i}s`}_getStatusDotClass(){switch(this._data.status){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let t=this._appRunnerStatus;if(!t||t.status==="not_initialized")return`
|
|
1704
|
+
`}getAriaPattern(t){return St[t]||{}}applyAriaPattern(t,e){let i=this.getAriaPattern(e);for(let[a,s]of Object.entries(i))if(a==="role")t.setAttribute("role",s);else{let r=a.replace(/([A-Z])/g,"-$1").toLowerCase();t.setAttribute(r,s)}}render(){}};var z={realtime:1e3,normal:2e3,background:5e3,offline:1e4},Ft={vscode:z.normal,browser:z.realtime,cli:z.background},jt={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},m={CONNECTED:"api:connected",DISCONNECTED:"api:disconnected",ERROR:"api:error",STATUS_UPDATE:"api:status-update",TASK_CREATED:"api:task-created",TASK_UPDATED:"api:task-updated",TASK_DELETED:"api:task-deleted",PROJECT_CREATED:"api:project-created",PROJECT_UPDATED:"api:project-updated",AGENT_UPDATE:"api:agent-update",LOG_MESSAGE:"api:log-message",MEMORY_UPDATE:"api:memory-update",CHECKLIST_UPDATE:"api:checklist-update"},T=class T extends EventTarget{static getInstance(t={}){let e=t.baseUrl||jt.baseUrl;return T._instances.has(e)||T._instances.set(e,new T(t)),T._instances.get(e)}static clearInstances(){T._instances.forEach(t=>t.disconnect()),T._instances.clear()}constructor(t={}){super(),this.config={...jt,...t},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=Ft[this._context]||z.normal,this._visibilityChangeHandler=null,this._messageHandler=null,this._setupAdaptivePolling(),this._setupVSCodeBridge()}_detectContext(){return typeof acquireVsCodeApi<"u"?"vscode":typeof window<"u"&&window.location?"browser":"cli"}get context(){return this._context}static get POLL_INTERVALS(){return z}_setupAdaptivePolling(){typeof document>"u"||(this._visibilityChangeHandler=()=>{document.hidden?this._setPollInterval(z.background):this._setPollInterval(Ft[this._context]||z.normal)},document.addEventListener("visibilitychange",this._visibilityChangeHandler))}_setPollInterval(t){this._currentPollInterval=t,this._pollInterval&&(this.stopPolling(),this.startPolling(null,t))}setPollMode(t){let e=z[t];e&&this._setPollInterval(e)}_setupVSCodeBridge(){if(!(typeof acquireVsCodeApi>"u")){try{this._vscodeApi=acquireVsCodeApi()}catch{console.warn("VS Code API already acquired or unavailable");return}this._messageHandler=t=>{let e=t.data;if(!(!e||!e.type))switch(e.type){case"updateStatus":this._emit(m.STATUS_UPDATE,e.data);break;case"updateTasks":this._emit(m.TASK_UPDATED,e.data);break;case"taskCreated":this._emit(m.TASK_CREATED,e.data);break;case"taskDeleted":this._emit(m.TASK_DELETED,e.data);break;case"projectCreated":this._emit(m.PROJECT_CREATED,e.data);break;case"projectUpdated":this._emit(m.PROJECT_UPDATED,e.data);break;case"agentUpdate":this._emit(m.AGENT_UPDATE,e.data);break;case"logMessage":this._emit(m.LOG_MESSAGE,e.data);break;case"memoryUpdate":this._emit(m.MEMORY_UPDATE,e.data);break;case"connected":this._connected=!0,this._emit(m.CONNECTED,e.data);break;case"disconnected":this._connected=!1,this._emit(m.DISCONNECTED,e.data);break;case"error":this._emit(m.ERROR,e.data);break;case"setPollMode":this.setPollMode(e.data.mode);break;default:this._emit(`api:${e.type}`,e.data)}},window.addEventListener("message",this._messageHandler)}}get isVSCode(){return this._context==="vscode"}postToVSCode(t,e={}){this._vscodeApi&&this._vscodeApi.postMessage({type:t,data:e})}requestRefresh(){this.postToVSCode("requestRefresh")}notifyVSCode(t,e={}){this.postToVSCode("userAction",{action:t,...e})}get baseUrl(){return this.config.baseUrl}set baseUrl(t){this.config.baseUrl=t,this.config.wsUrl=t.replace(/^http/,"ws")+"/ws"}get isConnected(){return this._connected}async connect(){if(!(this._ws&&this._ws.readyState===WebSocket.OPEN))return new Promise((t,e)=>{try{this._ws=new WebSocket(this.config.wsUrl),this._ws.onopen=()=>{this._connected=!0,this._reconnectAttempts=0,this._emit(m.CONNECTED),t()},this._ws.onclose=()=>{this._connected=!1,this._emit(m.DISCONNECTED),this._scheduleReconnect()},this._ws.onerror=i=>{this._emit(m.ERROR,{error:i}),e(i)},this._ws.onmessage=i=>{try{let a=JSON.parse(i.data);this._handleMessage(a)}catch(a){console.error("Failed to parse WebSocket message:",a)}}}catch(i){e(i)}})}disconnect(){this._ws&&(this._ws.close(),this._ws=null),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._reconnectTimeout&&(clearTimeout(this._reconnectTimeout),this._reconnectTimeout=null),this._connected=!1,this._cleanupGlobalListeners()}_cleanupGlobalListeners(){this._visibilityChangeHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this._visibilityChangeHandler),this._visibilityChangeHandler=null),this._messageHandler&&typeof window<"u"&&(window.removeEventListener("message",this._messageHandler),this._messageHandler=null)}destroy(){this.disconnect()}_scheduleReconnect(){if(this._reconnectTimeout)return;if(this._reconnectAttempts>=this._maxReconnectAttempts){console.warn("WebSocket max reconnect attempts reached, giving up"),this._emit(m.ERROR,{error:"Max reconnect attempts reached"});return}let t=Math.min(this.config.retryDelay*Math.pow(2,this._reconnectAttempts),3e4);this._reconnectAttempts++,this._reconnectTimeout=setTimeout(()=>{this._reconnectTimeout=null,this.connect().catch(()=>{})},t)}_handleMessage(t){if(t.type==="ping"){this._ws&&this._ws.readyState===WebSocket.OPEN&&this._ws.send(JSON.stringify({type:"pong"}));return}let i={connected:m.CONNECTED,status_update:m.STATUS_UPDATE,task_created:m.TASK_CREATED,task_updated:m.TASK_UPDATED,task_deleted:m.TASK_DELETED,task_moved:m.TASK_UPDATED,project_created:m.PROJECT_CREATED,project_updated:m.PROJECT_UPDATED,agent_update:m.AGENT_UPDATE,log:m.LOG_MESSAGE}[t.type]||`api:${t.type}`;this._emit(i,t.data)}_emit(t,e={}){this.dispatchEvent(new CustomEvent(t,{detail:e}))}async _request(t,e={}){let i=`${this.config.baseUrl}${t}`,a=new AbortController,s=setTimeout(()=>a.abort(),this.config.timeout);try{let r=await fetch(i,{...e,signal:a.signal,credentials:"include",headers:{"Content-Type":"application/json",...e.headers}});if(clearTimeout(s),!r.ok){let o=await r.text().catch(()=>""),n=r.statusText||`HTTP ${r.status}`;if(o)try{let l=JSON.parse(o);n=l.detail||l.error||l.message||n}catch{n=o.length>200?o.slice(0,200)+"...":o}throw new Error(n)}return r.status===204?null:await r.json()}catch(r){throw clearTimeout(s),r.name==="AbortError"?new Error("Request timeout"):r}}async _get(t,e=!1){if(e&&this._cache.has(t)){let a=this._cache.get(t);if(Date.now()-a.timestamp<this._cacheTimeout)return a.data}let i=await this._request(t);return e&&this._cache.set(t,{data:i,timestamp:Date.now()}),i}async _post(t,e){return this._request(t,{method:"POST",body:JSON.stringify(e)})}async _put(t,e){return this._request(t,{method:"PUT",body:JSON.stringify(e)})}async _delete(t){return this._request(t,{method:"DELETE"})}async get(t){return this._get(t)}async getStatus(){return this._get("/api/status")}async healthCheck(){return this._get("/health")}async listProjects(t=null){let e=t?`?status=${t}`:"";return this._get(`/api/projects${e}`)}async getProject(t){return this._get(`/api/projects/${t}`)}async createProject(t){return this._post("/api/projects",t)}async updateProject(t,e){return this._put(`/api/projects/${t}`,e)}async deleteProject(t){return this._delete(`/api/projects/${t}`)}async listTasks(t={}){let e=new URLSearchParams;t.projectId&&e.append("project_id",t.projectId),t.status&&e.append("status",t.status),t.priority&&e.append("priority",t.priority);let i=e.toString()?`?${e}`:"";return this._get(`/api/tasks${i}`)}async getTask(t){return this._get(`/api/tasks/${t}`)}async createTask(t){return this._post("/api/tasks",t)}async updateTask(t,e){return this._put(`/api/tasks/${t}`,e)}async moveTask(t,e,i){return this._post(`/api/tasks/${t}/move`,{status:e,position:i})}async deleteTask(t){return this._delete(`/api/tasks/${t}`)}async getMemorySummary(){return this._get("/api/memory/summary",!0)}async getMemoryIndex(){return this._get("/api/memory/index",!0)}async getMemoryTimeline(){return this._get("/api/memory/timeline")}async listEpisodes(t={}){let e=new URLSearchParams(t).toString();return this._get(`/api/memory/episodes${e?"?"+e:""}`)}async getEpisode(t){return this._get(`/api/memory/episodes/${t}`)}async listPatterns(t={}){let e=new URLSearchParams(t).toString();return this._get(`/api/memory/patterns${e?"?"+e:""}`)}async getPattern(t){return this._get(`/api/memory/patterns/${t}`)}async listSkills(){return this._get("/api/memory/skills")}async getSkill(t){return this._get(`/api/memory/skills/${t}`)}async retrieveMemories(t,e=null,i=5){return this._post("/api/memory/retrieve",{query:t,taskType:e,topK:i})}async consolidateMemory(t=24){return this._post("/api/memory/consolidate",{sinceHours:t})}async getTokenEconomics(){return this._get("/api/memory/economics")}async searchMemory(t,e="all",i=20){let a=new URLSearchParams({q:t,collection:e,limit:String(i)});return this._get(`/api/memory/search?${a}`)}async getMemoryStats(){return this._get("/api/memory/stats",!0)}async listRegisteredProjects(t=!1){return this._get(`/api/registry/projects?include_inactive=${t}`)}async registerProject(t,e=null,i=null){return this._post("/api/registry/projects",{path:t,name:e,alias:i})}async discoverProjects(t=3){return this._get(`/api/registry/discover?max_depth=${t}`)}async syncRegistry(){return this._post("/api/registry/sync",{})}async getCrossProjectTasks(t=null){let e=t?`?project_ids=${t.join(",")}`:"";return this._get(`/api/registry/tasks${e}`)}async getLearningMetrics(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source);let i=e.toString()?`?${e}`:"";return this._get(`/api/learning/metrics${i}`)}async getLearningTrends(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source);let i=e.toString()?`?${e}`:"";return this._get(`/api/learning/trends${i}`)}async getLearningSignals(t={}){let e=new URLSearchParams;t.timeRange&&e.append("timeRange",t.timeRange),t.signalType&&e.append("signalType",t.signalType),t.source&&e.append("source",t.source),t.limit&&e.append("limit",String(t.limit)),t.offset&&e.append("offset",String(t.offset));let i=e.toString()?`?${e}`:"";return this._get(`/api/learning/signals${i}`)}async getLatestAggregation(){return this._get("/api/learning/aggregation")}async triggerAggregation(t={}){return this._post("/api/learning/aggregate",t)}async getAggregatedPreferences(t=20){return this._get(`/api/learning/preferences?limit=${t}`)}async getAggregatedErrors(t=20){return this._get(`/api/learning/errors?limit=${t}`)}async getAggregatedSuccessPatterns(t=20){return this._get(`/api/learning/success?limit=${t}`)}async getToolEfficiency(t=20){return this._get(`/api/learning/tools?limit=${t}`)}async getCost(){return this._get("/api/cost")}async getPricing(){return this._get("/api/pricing")}async getCouncilState(){return this._get("/api/council/state")}async getCouncilVerdicts(t=20){return this._get(`/api/council/verdicts?limit=${t}`)}async getCouncilConvergence(){return this._get("/api/council/convergence")}async getCouncilReport(){return this._get("/api/council/report")}async forceCouncilReview(){return this._post("/api/council/force-review",{})}async getContext(){return this._get("/api/context")}async getNotifications(t,e){let i=new URLSearchParams;t&&i.set("severity",t),e&&i.set("unread_only","true");let a=i.toString();return this._get("/api/notifications"+(a?"?"+a:""))}async getNotificationTriggers(){return this._get("/api/notifications/triggers")}async updateNotificationTriggers(t){return this._put("/api/notifications/triggers",{triggers:t})}async acknowledgeNotification(t){return this._post("/api/notifications/"+encodeURIComponent(t)+"/acknowledge",{})}async pauseSession(){return this._post("/api/control/pause",{})}async resumeSession(){return this._post("/api/control/resume",{})}async stopSession(){return this._post("/api/control/stop",{})}async getLogs(t=100){return this._get(`/api/logs?lines=${t}`)}async getChecklist(){return this._get("/api/checklist")}async getChecklistSummary(){return this._get("/api/checklist/summary")}async getPrdObservations(){let t=await fetch(`${this.baseUrl}/api/prd-observations`,{credentials:"include"});if(!t.ok)throw new Error(`HTTP ${t.status}`);return t.text()}async getChecklistWaivers(){return this._get("/api/checklist/waivers")}async addChecklistWaiver(t,e,i="dashboard"){return this._post("/api/checklist/waivers",{item_id:t,reason:e,waived_by:i})}async removeChecklistWaiver(t){return this._delete(`/api/checklist/waivers/${encodeURIComponent(t)}`)}async getCouncilGate(){return this._get("/api/council/gate")}async getAppRunnerStatus(){return this._get("/api/app-runner/status")}async getAppRunnerLogs(t=100){return this._get(`/api/app-runner/logs?lines=${t}`)}async restartApp(){return this._post("/api/control/app-restart",{})}async stopApp(){return this._post("/api/control/app-stop",{})}async getPlaywrightResults(){return this._get("/api/playwright/results")}async getPlaywrightScreenshot(){return this._get("/api/playwright/screenshot")}startPolling(t,e=null){if(this._pollInterval)return;this._pollCallback=t;let i=async()=>{try{let s=await this.getStatus();this._connected=!0,this._pollCallback&&this._pollCallback(s),this._emit(m.STATUS_UPDATE,s),this._vscodeApi&&this.postToVSCode("pollSuccess",{timestamp:Date.now()})}catch(s){this._connected=!1,this._emit(m.ERROR,{error:s}),this._vscodeApi&&this.postToVSCode("pollError",{error:s.message})}};i();let a=e||this._currentPollInterval||this.config.pollInterval;this._pollInterval=setInterval(i,a)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}};C(T,"_instances",new Map);var M=T;function Ut(d={}){return new M(d)}function g(d={}){return M.getInstance(d)}var It="loki-state-change",Tt={ui:{theme:"light",sidebarCollapsed:!1,activeSection:"kanban",terminalAutoScroll:!0},session:{connected:!1,lastSync:null,mode:"offline",phase:null,iteration:null},localTasks:[],cache:{projects:[],tasks:[],agents:[],memory:null,lastFetch:null},preferences:{pollInterval:2e3,notifications:!0,soundEnabled:!1}},S=class S extends EventTarget{static getInstance(){return S._instance||(S._instance=new S),S._instance}constructor(){super(),this._state=this._loadState(),this._subscribers=new Map,this._batchUpdates=[],this._batchTimeout=null}_loadState(){try{let t=localStorage.getItem(S.STORAGE_KEY);if(t){let e=JSON.parse(t);return this._mergeState(Tt,e)}}catch(t){console.warn("Failed to load state from localStorage:",t)}return{...Tt}}_mergeState(t,e){let i={...t};for(let a of Object.keys(e))a in t&&typeof t[a]=="object"&&!Array.isArray(t[a])?i[a]=this._mergeState(t[a],e[a]):i[a]=e[a];return i}_saveState(){try{let t={ui:this._state.ui,localTasks:this._state.localTasks,preferences:this._state.preferences};localStorage.setItem(S.STORAGE_KEY,JSON.stringify(t))}catch(t){console.warn("Failed to save state to localStorage:",t)}}get(t=null){if(!t)return{...this._state};let e=t.split("."),i=this._state;for(let a of e){if(i==null)return;i=i[a]}return i}set(t,e,i=!0){let a=t.split("."),s=a.pop(),r=this._state;for(let n of a)n in r||(r[n]={}),r=r[n];let o=r[s];r[s]=e,i&&this._saveState(),this._notifyChange(t,e,o)}update(t,e=!0){let i=[];for(let[a,s]of Object.entries(t)){let r=this.get(a);this.set(a,s,!1),i.push({path:a,value:s,oldValue:r})}e&&this._saveState();for(let a of i)this._notifyChange(a.path,a.value,a.oldValue)}_notifyChange(t,e,i){this.dispatchEvent(new CustomEvent(It,{detail:{path:t,value:e,oldValue:i}}));let a=this._subscribers.get(t)||[];for(let r of a)try{r(e,i,t)}catch(o){console.error("State subscriber error:",o)}let s=t.split(".");for(;s.length>1;){s.pop();let r=s.join("."),o=this._subscribers.get(r)||[];for(let n of o)try{n(this.get(r),null,r)}catch(l){console.error("State subscriber error:",l)}}}subscribe(t,e){return this._subscribers.has(t)||this._subscribers.set(t,[]),this._subscribers.get(t).push(e),()=>{let i=this._subscribers.get(t),a=i.indexOf(e);a>-1&&i.splice(a,1)}}reset(t=null){if(t){let e=t.split("."),i=Tt;for(let a of e)i=i?.[a];this.set(t,i)}else this._state={...Tt},this._saveState(),this.dispatchEvent(new CustomEvent(It,{detail:{path:null,value:this._state,oldValue:null}}))}addLocalTask(t){let e=this.get("localTasks")||[],i={id:`local-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,createdAt:new Date().toISOString(),status:"pending",...t};return this.set("localTasks",[...e,i]),i}updateLocalTask(t,e){let i=this.get("localTasks")||[],a=i.findIndex(r=>r.id===t);if(a===-1)return null;let s={...i[a],...e,updatedAt:new Date().toISOString()};return i[a]=s,this.set("localTasks",[...i]),s}deleteLocalTask(t){let e=this.get("localTasks")||[];this.set("localTasks",e.filter(i=>i.id!==t))}moveLocalTask(t,e,i=null){let s=(this.get("localTasks")||[]).find(r=>r.id===t);return s?this.updateLocalTask(t,{status:e,position:i??s.position}):null}updateSession(t){this.update(Object.fromEntries(Object.entries(t).map(([e,i])=>[`session.${e}`,i])),!1)}updateCache(t){this.update({"cache.projects":t.projects??this.get("cache.projects"),"cache.tasks":t.tasks??this.get("cache.tasks"),"cache.agents":t.agents??this.get("cache.agents"),"cache.memory":t.memory??this.get("cache.memory"),"cache.lastFetch":new Date().toISOString()},!1)}getMergedTasks(){let t=this.get("cache.tasks")||[],i=(this.get("localTasks")||[]).map(a=>({...a,isLocal:!0}));return[...t,...i]}getTasksByStatus(t){return this.getMergedTasks().filter(e=>e.status===t)}};C(S,"STORAGE_KEY","loki-dashboard-state"),C(S,"_instance",null);var N=S;function B(){return N.getInstance()}function Nt(d){let t=B();return{get:()=>t.get(d),set:e=>t.set(d,e),subscribe:e=>t.subscribe(d,e)}}var O=class extends h{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(m.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(m.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(m.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t}),this._statusUpdateHandler=e=>this._updateFromStatus(e.detail),this._connectedHandler=()=>{this._data.connected=!0,this.render()},this._disconnectedHandler=()=>{this._data.connected=!1,this._data.status="offline",this.render()},this._api.addEventListener(m.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(m.CONNECTED,this._connectedHandler),this._api.addEventListener(m.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){this._loadAbortController&&this._loadAbortController.abort(),this._loadAbortController=new AbortController;let{signal:t}=this._loadAbortController;try{let[e,i,a,s,r]=await Promise.allSettled([this._api.getStatus(),this._api.getChecklistSummary(),this._api.getAppRunnerStatus(),this._api.getPlaywrightResults(),this._api.getCouncilGate()]);if(t.aborted)return;e.status==="fulfilled"?this._updateFromStatus(e.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(t.aborted)return;this._data.connected=!1,this._data.status="offline",this.render()}}_updateFromStatus(t){t&&(this._data={...this._data,connected:!0,status:t.status||"offline",phase:t.phase||null,iteration:t.iteration!=null?t.iteration:null,provider:t.provider||null,running_agents:t.running_agents||0,pending_tasks:t.pending_tasks!=null?t.pending_tasks:null,uptime_seconds:t.uptime_seconds||0,complexity:t.complexity||null})}_startPolling(){this._pollInterval=setInterval(async()=>{try{await this._loadStatus()}catch{this._data.connected=!1,this._data.status="offline",this.render()}},5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_formatUptime(t){if(!t||t<0)return"--";let e=Math.floor(t/3600),i=Math.floor(t%3600/60),a=Math.floor(t%60);return e>0?`${e}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_getStatusDotClass(){switch(this._data.status){case"running":case"autonomous":return"active";case"paused":return"paused";case"stopped":return"stopped";case"error":return"error";default:return"offline"}}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_renderAppRunnerCard(){let t=this._appRunnerStatus;if(!t||t.status==="not_initialized")return`
|
|
1693
1705
|
<div class="overview-card">
|
|
1694
1706
|
<div class="card-label">App Runner</div>
|
|
1695
1707
|
<div class="card-value small-text">${this._data.status==="running"||this._data.status==="autonomous"?"Waiting...":"Not started"}</div>
|
|
1696
1708
|
</div>
|
|
1697
|
-
`;let
|
|
1709
|
+
`;let i={running:"var(--loki-green, #22c55e)",starting:"var(--loki-yellow, #f59e0b)",crashed:"var(--loki-red, #ef4444)",stopped:"var(--loki-text-muted, #a1a1aa)"}[t.status]||"var(--loki-text-muted)",a=t.status==="running"?"active":t.status==="crashed"?"error":"offline",s=(t.status||"unknown").toUpperCase(),r=t.port?`:${t.port}`:"",o=t.url&&typeof t.url=="string"?t.url:null;!o&&t.port&&t.status==="running"&&(o=`http://localhost:${t.port}`);let n=`
|
|
1698
1710
|
<div class="card-label">App Runner${o?' <span style="font-size:10px;color:var(--loki-text-muted);">(click to open)</span>':""}</div>
|
|
1699
1711
|
<div class="card-value small-text">
|
|
1700
|
-
<span class="status-dot ${
|
|
1712
|
+
<span class="status-dot ${a}"></span>
|
|
1701
1713
|
${s}${r}
|
|
1702
1714
|
</div>
|
|
1703
1715
|
${t.method?`<div style="font-size:10px;color:var(--loki-text-muted);margin-top:2px;">${this._escapeHtml(t.method)}</div>`:""}
|
|
@@ -1716,12 +1728,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1716
1728
|
<div class="card-label">Verification</div>
|
|
1717
1729
|
<div class="card-value small-text">${this._data.status==="running"||this._data.status==="autonomous"?"Pending":"Not run"}</div>
|
|
1718
1730
|
</div>
|
|
1719
|
-
`;let e=t.passed===!0,
|
|
1731
|
+
`;let e=t.passed===!0,i=e?"var(--loki-green, #22c55e)":"var(--loki-red, #ef4444)",a=e?"PASSED":"FAILED",s=e?"active":"error",r=t.checks||{},o=Object.values(r).filter(n=>!n).length;return`
|
|
1720
1732
|
<div class="overview-card">
|
|
1721
1733
|
<div class="card-label">Verification</div>
|
|
1722
1734
|
<div class="card-value small-text">
|
|
1723
1735
|
<span class="status-dot ${s}"></span>
|
|
1724
|
-
${
|
|
1736
|
+
${a}
|
|
1725
1737
|
</div>
|
|
1726
1738
|
${!e&&o>0?`<div style="font-size:10px;color:var(--loki-red,#ef4444);margin-top:2px;">${o} check(s) failed</div>`:""}
|
|
1727
1739
|
</div>
|
|
@@ -1730,12 +1742,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1730
1742
|
<div class="card-label">Spec Progress</div>
|
|
1731
1743
|
<div class="card-value small-text">${this._data.status==="running"||this._data.status==="autonomous"?"Analyzing spec...":"No checklist"}</div>
|
|
1732
1744
|
</div>
|
|
1733
|
-
`;let e=Math.round(t.verified/t.total*100),
|
|
1745
|
+
`;let e=Math.round(t.verified/t.total*100),i=t.failing>0?"var(--loki-yellow, #f59e0b)":"var(--loki-green, #22c55e)";return`
|
|
1734
1746
|
<div class="overview-card">
|
|
1735
1747
|
<div class="card-label">Spec Progress</div>
|
|
1736
1748
|
<div class="card-value small-text">${t.verified}/${t.total} (${e}%)</div>
|
|
1737
1749
|
<div class="mini-progress" style="margin-top:4px;height:4px;background:var(--loki-bg-secondary,#e4e4e7);border-radius:2px;overflow:hidden;">
|
|
1738
|
-
<div style="width:${e}%;height:100%;background:${
|
|
1750
|
+
<div style="width:${e}%;height:100%;background:${i};transition:width 0.3s;"></div>
|
|
1739
1751
|
</div>
|
|
1740
1752
|
${t.failing?`<div style="font-size:10px;color:var(--loki-red,#ef4444);margin-top:2px;">${t.failing} failing</div>`:""}
|
|
1741
1753
|
</div>
|
|
@@ -1764,7 +1776,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1764
1776
|
PASSED
|
|
1765
1777
|
</div>
|
|
1766
1778
|
</div>
|
|
1767
|
-
`}render(){let t=this._getStatusDotClass(),e=this._escapeHtml((this._data.status||"OFFLINE").toUpperCase()),
|
|
1779
|
+
`}render(){let t=this._getStatusDotClass(),e=this._escapeHtml((this._data.status||"OFFLINE").toUpperCase()),i=this._escapeHtml(this._data.phase||"--"),a=this._escapeHtml(this._data.iteration!=null?String(this._data.iteration):"0"),s=this._escapeHtml((this._data.provider||"CLAUDE").toUpperCase()),r=this._data.status==="running"||this._data.status==="autonomous",o=this._data.running_agents||0,n=r&&o===0?"Sequential":this._escapeHtml(String(o)),l=this._escapeHtml(this._data.pending_tasks!=null?`${this._data.pending_tasks} pending`:r?"Inline":"--"),c=this._escapeHtml(this._formatUptime(this._data.uptime_seconds)),p=this._escapeHtml((this._data.complexity||"STANDARD").toUpperCase());this.shadowRoot.innerHTML=`
|
|
1768
1780
|
<style>
|
|
1769
1781
|
${this.getBaseStyles()}
|
|
1770
1782
|
|
|
@@ -1898,12 +1910,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1898
1910
|
|
|
1899
1911
|
<div class="overview-card">
|
|
1900
1912
|
<div class="card-label">Phase</div>
|
|
1901
|
-
<div class="card-value small-text">${
|
|
1913
|
+
<div class="card-value small-text">${i}</div>
|
|
1902
1914
|
</div>
|
|
1903
1915
|
|
|
1904
1916
|
<div class="overview-card">
|
|
1905
1917
|
<div class="card-label">Iteration</div>
|
|
1906
|
-
<div class="card-value">${
|
|
1918
|
+
<div class="card-value">${a}</div>
|
|
1907
1919
|
</div>
|
|
1908
1920
|
|
|
1909
1921
|
<div class="overview-card">
|
|
@@ -1940,15 +1952,15 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1940
1952
|
</div>
|
|
1941
1953
|
</div>
|
|
1942
1954
|
</div>
|
|
1943
|
-
`}};customElements.get("loki-overview")||customElements.define("loki-overview",O);var
|
|
1944
|
-
<ul class="md-list">${
|
|
1955
|
+
`}};customElements.get("loki-overview")||customElements.define("loki-overview",O);var ce=[{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 extends h{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._api=null,this._state=B()}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadTasks()}disconnectedCallback(){super.disconnectedCallback(),this._api&&(this._api.removeEventListener(m.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(m.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(m.TASK_DELETED,this._onTaskEvent))}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadTasks()),t==="project-id"&&this._loadTasks(),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t}),this._onTaskEvent&&(this._api.removeEventListener(m.TASK_CREATED,this._onTaskEvent),this._api.removeEventListener(m.TASK_UPDATED,this._onTaskEvent),this._api.removeEventListener(m.TASK_DELETED,this._onTaskEvent)),this._onTaskEvent=()=>this._loadTasks(),this._api.addEventListener(m.TASK_CREATED,this._onTaskEvent),this._api.addEventListener(m.TASK_UPDATED,this._onTaskEvent),this._api.addEventListener(m.TASK_DELETED,this._onTaskEvent)}async _loadTasks(){this._loading=!0,this._error=null,this.render();try{let t=this.getAttribute("project-id"),e=t?{projectId:parseInt(t)}:{};this._tasks=await this._api.listTasks(e);let i=this._state.get("localTasks")||[];i.length>0&&(this._tasks=[...this._tasks,...i.map(a=>({...a,isLocal:!0}))]),this._state.update({"cache.tasks":this._tasks},!1)}catch(t){this._error=t.message,this._tasks=(this._state.get("localTasks")||[]).map(e=>({...e,isLocal:!0}))}this._loading=!1,this.render()}_getTasksByStatus(t){return this._getFilteredTasks().filter(i=>i.status?.toLowerCase().replace(/-/g,"_")===t)}_handleDragStart(t,e){this.hasAttribute("readonly")||(this._draggedTask=e,t.target.classList.add("dragging"),t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",e.id.toString()))}_handleDragEnd(t){t.target.classList.remove("dragging"),this._draggedTask=null,this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(e=>{e.classList.remove("drag-over")})}_handleDragOver(t){t.preventDefault(),t.dataTransfer.dropEffect="move"}_handleDragEnter(t){t.preventDefault(),t.currentTarget.classList.add("drag-over")}_handleDragLeave(t){t.currentTarget.contains(t.relatedTarget)||t.currentTarget.classList.remove("drag-over")}async _handleDrop(t,e){if(t.preventDefault(),t.currentTarget.classList.remove("drag-over"),!this._draggedTask||this.hasAttribute("readonly"))return;let i=this._draggedTask.id,a=this._tasks.find(r=>r.id===i);if(!a)return;let s=a.status;if(s!==e){a.status=e,this.render();try{a.isLocal?this._state.moveLocalTask(i,e):await this._api.moveTask(i,e,0),this.dispatchEvent(new CustomEvent("task-moved",{detail:{taskId:i,oldStatus:s,newStatus:e}}))}catch(r){a.status=s,this.render(),console.error("Failed to move task:",r)}}}_toggleCardExpand(t){this._expandedCards.has(t)?this._expandedCards.delete(t):this._expandedCards.add(t),this.render()}_toggleTaskSelection(t,e){e&&e.stopPropagation(),this._selectedTasks.has(t)?this._selectedTasks.delete(t):this._selectedTasks.add(t),this.render()}_toggleBulkMode(){this._bulkMode=!this._bulkMode,this._bulkMode||this._selectedTasks.clear(),this.render()}async _bulkMove(t){let e=[...this._selectedTasks];for(let i of e){let a=this._tasks.find(s=>String(s.id)===String(i));if(a&&a.status!==t)try{a.isLocal?this._state.moveLocalTask(i,t):await this._api.moveTask(i,t,0),a.status=t}catch(s){console.error("Failed to bulk move task:",i,s)}}this._selectedTasks.clear(),this._bulkMode=!1,this.render(),this._loadTasks()}async _bulkDelete(){let t=[...this._selectedTasks];for(let e of t)try{await this._api.deleteTask(e)}catch(i){console.error("Failed to delete task:",e,i)}this._selectedTasks.clear(),this._bulkMode=!1,this._loadTasks()}_setFilter(t){this._activeFilter=t,this.render()}_getFilteredTasks(){let t=[...this._tasks],e=new Date,i=new Date(e.getFullYear(),e.getMonth(),e.getDate()),a=new Date(i.getTime()-7*24*60*60*1e3);switch(this._activeFilter){case"today":t=t.filter(s=>{let r=s.created_at?new Date(s.created_at):null;return r&&r>=i});break;case"this-week":t=t.filter(s=>{let r=s.created_at?new Date(s.created_at):null;return r&&r>=a});break;case"running":t=t.filter(s=>s.status==="in_progress");break;case"failed":t=t.filter(s=>s.status==="failed"||s.status==="error");break;default:break}return t}_openAddTaskModal(t="pending"){this.dispatchEvent(new CustomEvent("add-task",{detail:{status:t}}))}_openTaskDetail(t){this._selectedTask=t,this.render(),this.dispatchEvent(new CustomEvent("task-click",{detail:{task:t}}))}_closeTaskDetail(){this._selectedTask=null,this.render()}_renderMarkdown(t){if(!t)return"";let e=this._escapeHtml(String(t));return e=e.replace(/```([\s\S]*?)```/g,(i,a)=>`<pre class="md-code">${a.trim()}</pre>`),e=e.replace(/`([^`\n]+)`/g,'<code class="md-inline-code">$1</code>'),e=e.replace(/^###\s+(.+)$/gm,'<h4 class="md-h4">$1</h4>'),e=e.replace(/^##\s+(.+)$/gm,'<h3 class="md-h3">$1</h3>'),e=e.replace(/^#\s+(.+)$/gm,'<h2 class="md-h2">$1</h2>'),e=e.replace(/\*\*([^*\n]+)\*\*/g,"<strong>$1</strong>"),e=e.replace(/(^|[^*])\*([^*\n]+)\*/g,"$1<em>$2</em>"),e=e.replace(/(?:^|\n)((?:[-*]\s+.+(?:\n|$))+)/g,(i,a)=>`
|
|
1956
|
+
<ul class="md-list">${a.trim().split(/\n/).map(r=>r.replace(/^[-*]\s+/,"")).map(r=>`<li>${r}</li>`).join("")}</ul>`),e=e.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(""),e}_formatTimestamp(t){if(!t)return"";try{let e=new Date(t);return isNaN(e.getTime())?this._escapeHtml(String(t)):e.toLocaleString()}catch{return this._escapeHtml(String(t))}}_phaseClass(t){let e=String(t||"").toLowerCase();return["reason","plan","planning"].includes(e)?"phase-reason":["act","execute","execution","implement"].includes(e)?"phase-act":["reflect","review"].includes(e)?"phase-reflect":["verify","test","gate"].includes(e)?"phase-verify":"phase-default"}_logLevelClass(t){let e=String(t||"info").toLowerCase();return e==="error"||e==="fatal"?"log-error":e==="warn"||e==="warning"?"log-warn":e==="debug"||e==="trace"?"log-debug":"log-info"}_renderTaskDetailModal(t){if(!t)return"";let e=(t.priority||"medium").toLowerCase(),i=e.charAt(0).toUpperCase()+e.slice(1),a=t.status||"pending",s=a.replace(/_/g," ").replace(/\b\w/g,v=>v.toUpperCase()),r=t.metadata||{},o=t.acceptance_criteria||[],n=t.context_files||[],l=t.specification||"",c=t.description||"",p=Array.isArray(t.notes)?t.notes:[],u=Array.isArray(t.logs)?t.logs:[],b=t.full_content||"";return`
|
|
1945
1957
|
<div class="modal-overlay" id="task-detail-overlay">
|
|
1946
1958
|
<div class="modal-container">
|
|
1947
1959
|
<div class="modal-header">
|
|
1948
1960
|
<div class="modal-header-left">
|
|
1949
1961
|
<span class="task-id">${t.isLocal?"LOCAL":"#"+this._escapeHtml(String(t.id))}</span>
|
|
1950
|
-
<span class="task-priority ${e}">${
|
|
1951
|
-
<span class="task-status-badge ${
|
|
1962
|
+
<span class="task-priority ${e}">${i}</span>
|
|
1963
|
+
<span class="task-status-badge ${a}">${s}</span>
|
|
1952
1964
|
</div>
|
|
1953
1965
|
<button class="modal-close" id="modal-close-btn" aria-label="Close">×</button>
|
|
1954
1966
|
</div>
|
|
@@ -1958,9 +1970,9 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1958
1970
|
<div class="modal-section">
|
|
1959
1971
|
<h3 class="modal-section-title">Metadata</h3>
|
|
1960
1972
|
<div class="meta-grid">
|
|
1961
|
-
${Object.entries(r).map(([
|
|
1973
|
+
${Object.entries(r).map(([v,f])=>`
|
|
1962
1974
|
<div class="meta-cell">
|
|
1963
|
-
<span class="meta-label">${this._escapeHtml(
|
|
1975
|
+
<span class="meta-label">${this._escapeHtml(v.replace(/_/g," "))}</span>
|
|
1964
1976
|
<span class="meta-value">${this._escapeHtml(String(f))}</span>
|
|
1965
1977
|
</div>
|
|
1966
1978
|
`).join("")}
|
|
@@ -1986,7 +1998,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1986
1998
|
<div class="modal-section">
|
|
1987
1999
|
<h3 class="modal-section-title">Acceptance Criteria</h3>
|
|
1988
2000
|
<ul class="criteria-checklist" role="list">
|
|
1989
|
-
${o.map(
|
|
2001
|
+
${o.map(v=>{let f=v&&typeof v=="object",x=f?v.text||v.title||"":v,w=f?!!v.done:!1;return`<li class="criteria-item">
|
|
1990
2002
|
<span class="criteria-checkbox ${w?"checked":""}" aria-hidden="true">${w?"✓":""}</span>
|
|
1991
2003
|
<span class="criteria-text ${w?"done":""}">${this._escapeHtml(String(x))}</span>
|
|
1992
2004
|
</li>`}).join("")}
|
|
@@ -1998,7 +2010,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
1998
2010
|
<div class="modal-section">
|
|
1999
2011
|
<h3 class="modal-section-title">Notes</h3>
|
|
2000
2012
|
<ul class="notes-timeline" role="list">
|
|
2001
|
-
${p.map(
|
|
2013
|
+
${p.map(v=>{let f=this._formatTimestamp(v&&v.timestamp),x=v&&v.author?this._escapeHtml(String(v.author)):"unknown",w=v&&v.body?this._escapeHtml(String(v.body)):"";return`<li class="note-entry">
|
|
2002
2014
|
<div class="note-meta">
|
|
2003
2015
|
<span class="note-author">${x}</span>
|
|
2004
2016
|
${f?`<span class="note-time">${f}</span>`:""}
|
|
@@ -2014,11 +2026,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
2014
2026
|
<h3 class="modal-section-title">Logs</h3>
|
|
2015
2027
|
<div class="logs-scroll">
|
|
2016
2028
|
<ul class="logs-timeline" role="list">
|
|
2017
|
-
${u.map(
|
|
2029
|
+
${u.map(v=>{let f=this._formatTimestamp(v&&v.timestamp),x=v&&v.iteration!==void 0&&v.iteration!==null?`i${this._escapeHtml(String(v.iteration))}`:"",w=v&&v.phase?String(v.phase):"",te=this._phaseClass(w),ee=this._logLevelClass(v&&v.level),ie=v&&v.message?this._escapeHtml(String(v.message)):"";return`<li class="log-entry ${ee}">
|
|
2018
2030
|
${f?`<span class="log-time">${f}</span>`:""}
|
|
2019
2031
|
${x?`<span class="log-iter">${x}</span>`:""}
|
|
2020
|
-
${w?`<span class="log-phase ${
|
|
2021
|
-
<span class="log-message">${
|
|
2032
|
+
${w?`<span class="log-phase ${te}">${this._escapeHtml(w)}</span>`:""}
|
|
2033
|
+
<span class="log-message">${ie}</span>
|
|
2022
2034
|
</li>`}).join("")}
|
|
2023
2035
|
</ul>
|
|
2024
2036
|
</div>
|
|
@@ -2029,7 +2041,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
2029
2041
|
<div class="modal-section">
|
|
2030
2042
|
<h3 class="modal-section-title">Context Files</h3>
|
|
2031
2043
|
<ul class="context-files-list">
|
|
2032
|
-
${n.map(
|
|
2044
|
+
${n.map(v=>`<li class="mono">${this._escapeHtml(v)}</li>`).join("")}
|
|
2033
2045
|
</ul>
|
|
2034
2046
|
</div>
|
|
2035
2047
|
`:""}
|
|
@@ -2894,13 +2906,13 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
2894
2906
|
display: block;
|
|
2895
2907
|
}
|
|
2896
2908
|
</style>
|
|
2897
|
-
`,e=
|
|
2909
|
+
`,e=a=>{switch(a){case"pending":return'<circle cx="12" cy="12" r="10"/>';case"in_progress":return'<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>';case"review":return'<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>';case"done":return'<path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>';default:return'<circle cx="12" cy="12" r="10"/>'}},i;if(this._loading)i='<div class="loading">Loading tasks...</div>';else if(this._error&&this._tasks.length===0)i=`<div class="error">Error: ${this._escapeHtml(this._error)}</div>`;else{let a=this.hasAttribute("readonly"),s=[{id:"all",label:"All"},{id:"today",label:"Today"},{id:"this-week",label:"This Week"},{id:"running",label:"Running"},{id:"failed",label:"Failed"}],r=o=>{if(!o.assigned_agent_id&&!o.agent_type)return"";let n=(o.agent_type||"").toLowerCase(),l="AG",c="default",p="idle",u=`Agent #${o.assigned_agent_id||"?"}`;return n.includes("architect")||n==="ar"?(l="AR",c="architect",u="Architect"):n.includes("develop")||n==="dv"?(l="DV",c="developer",u="Developer"):n.includes("test")||n==="ts"?(l="TS",c="tester",u="Tester"):(n.includes("review")||n==="rv")&&(l="RV",c="reviewer",u="Reviewer"),o.status==="in_progress"&&(p="active"),(o.status==="failed"||o.status==="error")&&(p="failed"),`
|
|
2898
2910
|
<div class="agent-avatar ${c}">
|
|
2899
2911
|
${l}
|
|
2900
2912
|
<span class="agent-status-dot ${p}"></span>
|
|
2901
2913
|
<span class="agent-tooltip">${this._escapeHtml(u)}</span>
|
|
2902
2914
|
</div>
|
|
2903
|
-
`};
|
|
2915
|
+
`};i=`
|
|
2904
2916
|
<div class="filter-bar">
|
|
2905
2917
|
<span class="filter-label">Filter:</span>
|
|
2906
2918
|
${s.map(o=>`
|
|
@@ -2918,7 +2930,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
2918
2930
|
`:""}
|
|
2919
2931
|
|
|
2920
2932
|
<div class="kanban-board">
|
|
2921
|
-
${
|
|
2933
|
+
${ce.map(o=>{let n=this._getTasksByStatus(o.status);return`
|
|
2922
2934
|
<div class="kanban-column" data-status="${o.status}">
|
|
2923
2935
|
<div class="kanban-column-header">
|
|
2924
2936
|
<span class="kanban-column-title">
|
|
@@ -2932,12 +2944,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
2932
2944
|
<div class="kanban-tasks" data-status="${o.status}">
|
|
2933
2945
|
${n.length===0?'<div class="empty-column">No tasks</div>':""}
|
|
2934
2946
|
${n.map(l=>{let c=String(l.id||""),p=this._expandedCards.has(c),u=this._selectedTasks.has(c);return`
|
|
2935
|
-
<div class="task-card ${!
|
|
2947
|
+
<div class="task-card ${!a&&!l.fromServer?"draggable":""} ${l.isLocal?"local":""} ${p?"expanded":""} ${u?"selected":""}"
|
|
2936
2948
|
data-task-id="${this._escapeHtml(c)}"
|
|
2937
2949
|
tabindex="0"
|
|
2938
2950
|
role="button"
|
|
2939
2951
|
aria-label="Task: ${this._escapeHtml(l.title||"Untitled")}, ${this._escapeHtml(String(l.priority||"medium"))} priority"
|
|
2940
|
-
${!
|
|
2952
|
+
${!a&&!l.fromServer?'draggable="true"':""}>
|
|
2941
2953
|
<div class="task-card-header">
|
|
2942
2954
|
<div style="display:flex;align-items:center;gap:6px;">
|
|
2943
2955
|
${this._bulkMode?`<div class="task-checkbox ${u?"checked":""}" data-check-id="${this._escapeHtml(c)}"></div>`:""}
|
|
@@ -2970,7 +2982,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
2970
2982
|
</div>
|
|
2971
2983
|
`}).join("")}
|
|
2972
2984
|
</div>
|
|
2973
|
-
${!
|
|
2985
|
+
${!a&&o.status==="pending"?`
|
|
2974
2986
|
<button class="add-task-btn" data-status="${o.status}" aria-label="Add new task to ${o.label}">+ Add Task</button>
|
|
2975
2987
|
`:""}
|
|
2976
2988
|
</div>
|
|
@@ -2999,10 +3011,10 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
2999
3011
|
</button>
|
|
3000
3012
|
</div>
|
|
3001
3013
|
</div>
|
|
3002
|
-
${
|
|
3014
|
+
${i}
|
|
3003
3015
|
</div>
|
|
3004
3016
|
${this._selectedTask?this._renderTaskDetailModal(this._selectedTask):""}
|
|
3005
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadTasks());let e=this.shadowRoot.getElementById("bulk-toggle-btn");e&&e.addEventListener("click",()=>this._toggleBulkMode()),this.shadowRoot.querySelectorAll(".filter-pill").forEach(s=>{s.addEventListener("click",()=>this._setFilter(s.dataset.filter))}),this.shadowRoot.querySelectorAll(".bulk-btn").forEach(s=>{s.addEventListener("click",()=>{let r=s.dataset.bulkAction;r==="delete"?this._bulkDelete():this._bulkMove(r)})}),this.shadowRoot.querySelectorAll(".add-task-btn").forEach(s=>{s.addEventListener("click",()=>{this._openAddTaskModal(s.dataset.status)})}),this.shadowRoot.querySelectorAll(".task-checkbox").forEach(s=>{s.addEventListener("click",r=>{r.stopPropagation(),this._toggleTaskSelection(s.dataset.checkId,r)})}),this.shadowRoot.querySelectorAll(".expand-toggle").forEach(s=>{s.addEventListener("click",r=>{r.stopPropagation(),this._toggleCardExpand(s.dataset.expandId)})}),this.shadowRoot.querySelectorAll(".task-card").forEach(s=>{let r=s.dataset.taskId,o=this._tasks.find(n=>n.id.toString()===r);o&&(s.addEventListener("click",n=>{if(this._bulkMode){this._toggleTaskSelection(r,n);return}this._openTaskDetail(o)}),s.addEventListener("keydown",n=>{n.key==="Enter"||n.key===" "?(n.preventDefault(),this._bulkMode?this._toggleTaskSelection(r,n):this._openTaskDetail(o)):(n.key==="ArrowDown"||n.key==="ArrowUp")&&(n.preventDefault(),this._navigateTaskCards(s,n.key==="ArrowDown"?"next":"prev"))}),s.classList.contains("draggable")&&(s.addEventListener("dragstart",n=>this._handleDragStart(n,o)),s.addEventListener("dragend",n=>this._handleDragEnd(n))))}),this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(s=>{s.addEventListener("dragover",r=>this._handleDragOver(r)),s.addEventListener("dragenter",r=>this._handleDragEnter(r)),s.addEventListener("dragleave",r=>this._handleDragLeave(r)),s.addEventListener("drop",r=>this._handleDrop(r,s.dataset.status))});let
|
|
3017
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("refresh-btn");t&&t.addEventListener("click",()=>this._loadTasks());let e=this.shadowRoot.getElementById("bulk-toggle-btn");e&&e.addEventListener("click",()=>this._toggleBulkMode()),this.shadowRoot.querySelectorAll(".filter-pill").forEach(s=>{s.addEventListener("click",()=>this._setFilter(s.dataset.filter))}),this.shadowRoot.querySelectorAll(".bulk-btn").forEach(s=>{s.addEventListener("click",()=>{let r=s.dataset.bulkAction;r==="delete"?this._bulkDelete():this._bulkMove(r)})}),this.shadowRoot.querySelectorAll(".add-task-btn").forEach(s=>{s.addEventListener("click",()=>{this._openAddTaskModal(s.dataset.status)})}),this.shadowRoot.querySelectorAll(".task-checkbox").forEach(s=>{s.addEventListener("click",r=>{r.stopPropagation(),this._toggleTaskSelection(s.dataset.checkId,r)})}),this.shadowRoot.querySelectorAll(".expand-toggle").forEach(s=>{s.addEventListener("click",r=>{r.stopPropagation(),this._toggleCardExpand(s.dataset.expandId)})}),this.shadowRoot.querySelectorAll(".task-card").forEach(s=>{let r=s.dataset.taskId,o=this._tasks.find(n=>n.id.toString()===r);o&&(s.addEventListener("click",n=>{if(this._bulkMode){this._toggleTaskSelection(r,n);return}this._openTaskDetail(o)}),s.addEventListener("keydown",n=>{n.key==="Enter"||n.key===" "?(n.preventDefault(),this._bulkMode?this._toggleTaskSelection(r,n):this._openTaskDetail(o)):(n.key==="ArrowDown"||n.key==="ArrowUp")&&(n.preventDefault(),this._navigateTaskCards(s,n.key==="ArrowDown"?"next":"prev"))}),s.classList.contains("draggable")&&(s.addEventListener("dragstart",n=>this._handleDragStart(n,o)),s.addEventListener("dragend",n=>this._handleDragEnd(n))))}),this.shadowRoot.querySelectorAll(".kanban-tasks").forEach(s=>{s.addEventListener("dragover",r=>this._handleDragOver(r)),s.addEventListener("dragenter",r=>this._handleDragEnter(r)),s.addEventListener("dragleave",r=>this._handleDragLeave(r)),s.addEventListener("drop",r=>this._handleDrop(r,s.dataset.status))});let i=this.shadowRoot.getElementById("modal-close-btn");i&&i.addEventListener("click",()=>this._closeTaskDetail());let a=this.shadowRoot.getElementById("task-detail-overlay");a&&a.addEventListener("click",s=>{s.target===a&&this._closeTaskDetail()})}_escapeHtml(t){let e=document.createElement("div");return e.textContent=t,e.innerHTML}_navigateTaskCards(t,e){let i=Array.from(this.shadowRoot.querySelectorAll(".task-card")),a=i.indexOf(t);if(a===-1)return;let s=e==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-task-board")||customElements.define("loki-task-board",q);var J=class extends h{static get observedAttributes(){return["api-url","theme","compact"]}constructor(){super(),this._status={mode:"offline",phase:null,iteration:null,complexity:null,connected:!1,version:null,uptime:0,activeAgents:0,pendingTasks:0},this._api=null,this._state=B(),this._statusUpdateHandler=null,this._connectedHandler=null,this._disconnectedHandler=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadStatus(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling(),this._api&&(this._statusUpdateHandler&&this._api.removeEventListener(m.STATUS_UPDATE,this._statusUpdateHandler),this._connectedHandler&&this._api.removeEventListener(m.CONNECTED,this._connectedHandler),this._disconnectedHandler&&this._api.removeEventListener(m.DISCONNECTED,this._disconnectedHandler))}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadStatus()),t==="theme"&&this._applyTheme(),t==="compact"&&this.render())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t}),this._statusUpdateHandler=e=>this._updateFromStatus(e.detail),this._connectedHandler=()=>{this._status.connected=!0,this.render()},this._disconnectedHandler=()=>{this._status.connected=!1,this._status.mode="offline",this.render()},this._api.addEventListener(m.STATUS_UPDATE,this._statusUpdateHandler),this._api.addEventListener(m.CONNECTED,this._connectedHandler),this._api.addEventListener(m.DISCONNECTED,this._disconnectedHandler)}async _loadStatus(){try{let t=await this._api.getStatus();this._updateFromStatus(t)}catch{this._status.connected=!1,this._status.mode="offline",this.render()}}_updateFromStatus(t){t&&(this._status={...this._status,connected:!0,mode:t.status||"running",version:t.version,uptime:t.uptime_seconds||0,activeAgents:t.running_agents||0,pendingTasks:t.pending_tasks||0,phase:t.phase,iteration:t.iteration,complexity:t.complexity},this._state.updateSession({connected:!0,mode:this._status.mode,lastSync:new Date().toISOString()}),this.render())}_startPolling(){this._ownPollInterval=setInterval(async()=>{try{let t=await this._api.getStatus();this._updateFromStatus(t)}catch{this._status.connected=!1,this._status.mode="offline",this.render()}},3e3)}_stopPolling(){this._ownPollInterval&&(clearInterval(this._ownPollInterval),this._ownPollInterval=null)}_formatUptime(t){if(!t||t<0)return"--";let e=Math.floor(t/3600),i=Math.floor(t%3600/60),a=Math.floor(t%60);return e>0?`${e}h ${i}m`:i>0?`${i}m ${a}s`:`${a}s`}_escapeHtml(t){let e=document.createElement("div");return e.textContent=String(t??""),e.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"}}_triggerStart(){this.dispatchEvent(new CustomEvent("session-start",{detail:this._status}))}async _triggerPause(){try{let t=await this._api.pauseSession();if(t&&t.error)throw new Error(t.error);this._status.mode="paused",this.render(),this.dispatchEvent(new CustomEvent("session-pause",{detail:this._status}))}catch(t){console.error("Failed to pause session:",t),this.render()}}async _triggerResume(){try{let t=await this._api.resumeSession();if(t&&t.error)throw new Error(t.error);this._status.mode="running",this.render(),this.dispatchEvent(new CustomEvent("session-resume",{detail:this._status}))}catch(t){console.error("Failed to resume session:",t),this.render()}}async _triggerStop(){try{let t=await this._api.stopSession();if(t&&t.error)throw new Error(t.error);this._status.mode="stopped",this.render(),this.dispatchEvent(new CustomEvent("session-stop",{detail:this._status}))}catch(t){console.error("Failed to stop session:",t),this.render()}}render(){let t=this.hasAttribute("compact"),e=this._getStatusClass(),i=this._getStatusLabel(),a=["running","autonomous"].includes(this._status.mode),s=this._status.mode==="paused",r=`
|
|
3006
3018
|
<style>
|
|
3007
3019
|
${this.getBaseStyles()}
|
|
3008
3020
|
|
|
@@ -3190,7 +3202,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
3190
3202
|
<div class="status-row">
|
|
3191
3203
|
<span class="status-value">
|
|
3192
3204
|
<span class="status-dot ${e}"></span>
|
|
3193
|
-
${
|
|
3205
|
+
${i}
|
|
3194
3206
|
</span>
|
|
3195
3207
|
</div>
|
|
3196
3208
|
<div class="control-buttons" role="group" aria-label="Session controls">
|
|
@@ -3200,12 +3212,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
3200
3212
|
Resume
|
|
3201
3213
|
</button>
|
|
3202
3214
|
`:`
|
|
3203
|
-
<button class="control-btn pause" id="pause-btn" aria-label="Pause session" ${
|
|
3215
|
+
<button class="control-btn pause" id="pause-btn" aria-label="Pause session" ${a?"":"disabled"}>
|
|
3204
3216
|
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>
|
|
3205
3217
|
Pause
|
|
3206
3218
|
</button>
|
|
3207
3219
|
`}
|
|
3208
|
-
<button class="control-btn stop" id="stop-btn" aria-label="Stop session" ${!
|
|
3220
|
+
<button class="control-btn stop" id="stop-btn" aria-label="Stop session" ${!a&&!s?"disabled":""}>
|
|
3209
3221
|
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="2"/></svg>
|
|
3210
3222
|
Stop
|
|
3211
3223
|
</button>
|
|
@@ -3219,7 +3231,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
3219
3231
|
<span class="status-label">Mode</span>
|
|
3220
3232
|
<span class="status-value">
|
|
3221
3233
|
<span class="status-dot ${e}"></span>
|
|
3222
|
-
${
|
|
3234
|
+
${i}
|
|
3223
3235
|
</span>
|
|
3224
3236
|
</div>
|
|
3225
3237
|
|
|
@@ -3250,12 +3262,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
3250
3262
|
Resume
|
|
3251
3263
|
</button>
|
|
3252
3264
|
`:`
|
|
3253
|
-
<button class="control-btn pause" id="pause-btn" aria-label="Pause session" ${
|
|
3265
|
+
<button class="control-btn pause" id="pause-btn" aria-label="Pause session" ${a?"":"disabled"}>
|
|
3254
3266
|
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>
|
|
3255
3267
|
Pause
|
|
3256
3268
|
</button>
|
|
3257
3269
|
`}
|
|
3258
|
-
<button class="control-btn stop" id="stop-btn" aria-label="Stop session" ${!
|
|
3270
|
+
<button class="control-btn stop" id="stop-btn" aria-label="Stop session" ${!a&&!s?"disabled":""}>
|
|
3259
3271
|
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="2"/></svg>
|
|
3260
3272
|
Stop
|
|
3261
3273
|
</button>
|
|
@@ -3281,13 +3293,13 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
3281
3293
|
`;this.shadowRoot.innerHTML=`
|
|
3282
3294
|
${r}
|
|
3283
3295
|
${t?o:n}
|
|
3284
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("pause-btn"),e=this.shadowRoot.getElementById("resume-btn"),
|
|
3285
|
-
`);if(r.length>e){let o=r.slice(e);for(let n of o)n.trim()&&this._addLog(this._parseLine(n));e=r.length}}catch{}};
|
|
3286
|
-
`),e=new Blob([t],{type:"text/plain"}),
|
|
3296
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("pause-btn"),e=this.shadowRoot.getElementById("resume-btn"),i=this.shadowRoot.getElementById("stop-btn"),a=this.shadowRoot.getElementById("start-btn");t&&t.addEventListener("click",()=>this._triggerPause()),e&&e.addEventListener("click",()=>this._triggerResume()),i&&i.addEventListener("click",()=>this._triggerStop()),a&&a.addEventListener("click",()=>this._triggerStart())}};customElements.get("loki-session-control")||customElements.define("loki-session-control",J);var Ot={info:{color:"var(--loki-blue)",label:"INFO"},success:{color:"var(--loki-green)",label:"SUCCESS"},warning:{color:"var(--loki-yellow)",label:"WARN"},error:{color:"var(--loki-red)",label:"ERROR"},step:{color:"var(--loki-purple)",label:"STEP"},agent:{color:"var(--loki-accent)",label:"AGENT"},debug:{color:"var(--loki-text-muted)",label:"DEBUG"}},G=class extends h{static get observedAttributes(){return["api-url","max-lines","auto-scroll","theme","log-file"]}constructor(){super(),this._logs=[],this._maxLines=500,this._autoScroll=!0,this._filter="",this._levelFilter="all",this._api=null,this._pollInterval=null,this._logMessageHandler=null}connectedCallback(){super.connectedCallback(),this._maxLines=parseInt(this.getAttribute("max-lines"))||500,this._autoScroll=this.hasAttribute("auto-scroll"),this._setupApi(),this._startLogPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopLogPolling(),this._api&&this._logMessageHandler&&this._api.removeEventListener(m.LOG_MESSAGE,this._logMessageHandler)}attributeChangedCallback(t,e,i){if(e!==i)switch(t){case"api-url":this._api&&(this._api.baseUrl=i);break;case"max-lines":this._maxLines=parseInt(i)||500,this._trimLogs(),this.render();break;case"auto-scroll":this._autoScroll=this.hasAttribute("auto-scroll"),this.render();break;case"theme":this._applyTheme();break}}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t}),this._logMessageHandler=e=>this._addLog(e.detail),this._api.addEventListener(m.LOG_MESSAGE,this._logMessageHandler)}_startLogPolling(){let t=this.getAttribute("log-file");t?this._pollLogFile(t):this._pollApiLogs()}async _pollApiLogs(){let t=0,e=async()=>{try{let i=await this._api.getLogs(200);if(Array.isArray(i)&&i.length>t){let a=i.slice(t);for(let s of a)s.message&&s.message.trim()&&this._addLog({message:s.message,level:s.level||"info",timestamp:s.timestamp||new Date().toLocaleTimeString()});t=i.length}}catch{}};e(),this._apiPollInterval=setInterval(e,2e3)}async _pollLogFile(t){let e=0,i=async()=>{try{let a=await fetch(`${t}?t=${Date.now()}`,{credentials:"include"});if(!a.ok)return;let r=(await a.text()).split(`
|
|
3297
|
+
`);if(r.length>e){let o=r.slice(e);for(let n of o)n.trim()&&this._addLog(this._parseLine(n));e=r.length}}catch{}};i(),this._pollInterval=setInterval(i,1e3)}_stopLogPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._apiPollInterval&&(clearInterval(this._apiPollInterval),this._apiPollInterval=null)}_parseLine(t){let e=t.match(/^\[([^\]]+)\]\s*\[([^\]]+)\]\s*(.+)$/);if(e)return{timestamp:e[1],level:e[2].toLowerCase(),message:e[3]};let i=t.match(/^(\d{2}:\d{2}:\d{2})\s+(\w+)\s+(.+)$/);return i?{timestamp:i[1],level:i[2].toLowerCase(),message:i[3]}:{timestamp:new Date().toLocaleTimeString(),level:"info",message:t}}_addLog(t){if(!t)return;let e={id:Date.now()+Math.random(),timestamp:t.timestamp||new Date().toLocaleTimeString(),level:(t.level||"info").toLowerCase(),message:t.message||t};this._logs.push(e),this._trimLogs(),this.dispatchEvent(new CustomEvent("log-received",{detail:e})),this._renderLogs(),this._autoScroll&&this._scrollToBottom()}_trimLogs(){this._logs.length>this._maxLines&&(this._logs=this._logs.slice(-this._maxLines))}_clearLogs(){this._logs=[],this.dispatchEvent(new CustomEvent("logs-cleared")),this._renderLogs()}_toggleAutoScroll(){this._autoScroll=!this._autoScroll,this.render(),this._autoScroll&&this._scrollToBottom()}_scrollToBottom(){requestAnimationFrame(()=>{let t=this.shadowRoot.getElementById("log-output");t&&(t.scrollTop=t.scrollHeight)})}_downloadLogs(){let t=this._logs.map(s=>`[${s.timestamp}] [${s.level.toUpperCase()}] ${s.message}`).join(`
|
|
3298
|
+
`),e=new Blob([t],{type:"text/plain"}),i=URL.createObjectURL(e),a=document.createElement("a");a.href=i,a.download=`loki-logs-${new Date().toISOString().split("T")[0]}.txt`,a.click(),URL.revokeObjectURL(i)}_setFilter(t){this._filter=t.toLowerCase(),this._renderLogs()}_setLevelFilter(t){this._levelFilter=t,this._renderLogs()}_getFilteredLogs(){return this._logs.filter(t=>!(this._levelFilter!=="all"&&t.level!==this._levelFilter||this._filter&&!t.message.toLowerCase().includes(this._filter)))}_renderLogs(){let t=this.shadowRoot.getElementById("log-output");if(!t)return;let e=this._getFilteredLogs();if(e.length===0){t.innerHTML='<div class="log-empty">No log output yet. Terminal will update when Loki Mode is running.</div>';return}t.innerHTML=e.map(i=>{let a=Ot[i.level]||Ot.info;return`
|
|
3287
3299
|
<div class="log-line">
|
|
3288
|
-
<span class="timestamp">${this._escapeHtml(
|
|
3289
|
-
<span class="level" style="color: ${
|
|
3290
|
-
<span class="message">${this._escapeHtml(
|
|
3300
|
+
<span class="timestamp">${this._escapeHtml(i.timestamp)}</span>
|
|
3301
|
+
<span class="level" style="color: ${a.color}">[${this._escapeHtml(a.label)}]</span>
|
|
3302
|
+
<span class="message">${this._escapeHtml(i.message)}</span>
|
|
3291
3303
|
</div>
|
|
3292
3304
|
`}).join(""),this._autoScroll&&this._scrollToBottom()}_escapeHtml(t){let e=document.createElement("div");return e.textContent=t,e.innerHTML}render(){let t=`
|
|
3293
3305
|
<style>
|
|
@@ -3482,7 +3494,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
3482
3494
|
${this._logs.length} lines (${this._getFilteredLogs().length} shown)
|
|
3483
3495
|
</div>
|
|
3484
3496
|
</div>
|
|
3485
|
-
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let t=this.shadowRoot.getElementById("filter-input"),e=this.shadowRoot.getElementById("level-select"),
|
|
3497
|
+
`,this._attachEventListeners(),this._renderLogs()}_attachEventListeners(){let t=this.shadowRoot.getElementById("filter-input"),e=this.shadowRoot.getElementById("level-select"),i=this.shadowRoot.getElementById("auto-scroll-btn"),a=this.shadowRoot.getElementById("clear-btn"),s=this.shadowRoot.getElementById("download-btn");t&&(t.value=this._filter,t.addEventListener("input",r=>this._setFilter(r.target.value))),e&&(e.value=this._levelFilter,e.addEventListener("change",r=>this._setLevelFilter(r.target.value))),i&&i.addEventListener("click",()=>this._toggleAutoScroll()),a&&a.addEventListener("click",()=>this._clearLogs()),s&&s.addEventListener("click",()=>this._downloadLogs())}addLog(t,e="info"){this._addLog({message:t,level:e,timestamp:new Date().toLocaleTimeString()})}clear(){this._clearLogs()}};customElements.get("loki-log-stream")||customElements.define("loki-log-stream",G);var pe=[{id:"summary",label:"Summary",icon:"M4 6h16M4 12h16M4 18h16"},{id:"search",label:"Search",icon:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"},{id:"episodes",label:"Episodes",icon:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"},{id:"patterns",label:"Patterns",icon:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"},{id:"skills",label:"Skills",icon:"M13 10V3L4 14h7v7l9-11h-7z"}],K=class extends h{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(t,e,i){if(e!==i)switch(t){case"api-url":this._api&&(this._api.baseUrl=i,this._loadData());break;case"theme":this._applyTheme();break;case"tab":this._setTab(i);break}}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let[t,e,i]=await Promise.allSettled([this._api.getMemorySummary(),this._api.getTokenEconomics(),this._api.getMemoryStats()]);this._summary=t.status==="fulfilled"?t.value:null,this._tokenEconomics=e.status==="fulfilled"?e.value:null,this._stats=i.status==="fulfilled"?i.value:null,await this._loadTabData()}catch(t){this._error=t.message||"Failed to load memory data"}this._loading=!1,this.render()}async _loadTabData(){switch(this._activeTab){case"episodes":this._episodes=await this._api.listEpisodes({limit:50}).catch(()=>[]);break;case"patterns":this._patterns=await this._api.listPatterns().catch(()=>[]);break;case"skills":this._skills=await this._api.listSkills().catch(()=>[]);break}}_setTab(t){this._activeTab!==t&&(this._activeTab=t,this._selectedItem=null,this._loadTabData().then(()=>this.render()))}async _selectEpisode(t){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getEpisode(t),this.dispatchEvent(new CustomEvent("episode-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(e){console.error("Failed to load episode:",e)}}async _selectPattern(t){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getPattern(t),this.dispatchEvent(new CustomEvent("pattern-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(e){console.error("Failed to load pattern:",e)}}async _selectSkill(t){try{this._lastFocusedElement=this.shadowRoot.activeElement,this._selectedItem=await this._api.getSkill(t),this.dispatchEvent(new CustomEvent("skill-select",{detail:this._selectedItem})),this.render(),this._focusDetailPanel()}catch(e){console.error("Failed to load skill:",e)}}_focusDetailPanel(){requestAnimationFrame(()=>{let t=this.shadowRoot.getElementById("close-detail");t&&t.focus()})}_closeDetail(){this._selectedItem=null,this.render(),this._lastFocusedElement&&requestAnimationFrame(()=>{this._lastFocusedElement.focus(),this._lastFocusedElement=null})}async _triggerConsolidation(){try{let t=await this._api.consolidateMemory(24);alert(`Consolidation complete:
|
|
3486
3498
|
- Patterns created: ${t.patternsCreated}
|
|
3487
3499
|
- Patterns merged: ${t.patternsMerged}
|
|
3488
3500
|
- Episodes processed: ${t.episodesProcessed}`),this._loadData()}catch(t){alert("Consolidation failed: "+t.message)}}async _executeSearch(){let t=this._searchQuery.trim();if(t){this._searchLoading=!0,this._searchError=null,this.render();try{let e=await this._api.searchMemory(t,this._searchCollection,20);this._searchResults=e.results||[]}catch(e){this._searchError=e.message||"Search failed",this._searchResults=[]}this._searchLoading=!1,this.render(),requestAnimationFrame(()=>{let e=this.shadowRoot.getElementById("memory-search-input");e&&e.focus()})}}_renderSearch(){let t=["all","episodes","patterns","skills"];return`
|
|
@@ -3524,7 +3536,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
3524
3536
|
`:!this._searchLoading&&this._searchQuery?'<div class="empty-state">No results found</div>':""}
|
|
3525
3537
|
${this._searchQuery?"":'<div class="empty-state">Enter a query to search across all memory layers using full-text search</div>'}
|
|
3526
3538
|
</div>
|
|
3527
|
-
`}_renderSummary(){if(!this._summary)return'<div class="empty-state">No memory data available</div>';let{episodic:t,semantic:e,procedural:
|
|
3539
|
+
`}_renderSummary(){if(!this._summary)return'<div class="empty-state">No memory data available</div>';let{episodic:t,semantic:e,procedural:i,tokenEconomics:a}=this._summary;return`
|
|
3528
3540
|
<div class="summary-grid">
|
|
3529
3541
|
<div class="summary-card">
|
|
3530
3542
|
<div class="summary-card-header">
|
|
@@ -3557,13 +3569,13 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
3557
3569
|
<div class="summary-card">
|
|
3558
3570
|
<div class="summary-card-header">
|
|
3559
3571
|
<span class="summary-card-title">Procedural Memory</span>
|
|
3560
|
-
<span class="summary-card-count">${
|
|
3572
|
+
<span class="summary-card-count">${i?.skills||0}</span>
|
|
3561
3573
|
</div>
|
|
3562
3574
|
<div class="summary-card-detail">
|
|
3563
3575
|
Learned skills and procedures
|
|
3564
3576
|
</div>
|
|
3565
3577
|
<div class="memory-bar">
|
|
3566
|
-
<div class="memory-bar-fill procedural" style="width: ${Math.min((
|
|
3578
|
+
<div class="memory-bar-fill procedural" style="width: ${Math.min((i?.skills||0)/100*100,100)}%"></div>
|
|
3567
3579
|
</div>
|
|
3568
3580
|
</div>
|
|
3569
3581
|
|
|
@@ -4343,8 +4355,8 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4343
4355
|
font-size: 12px;
|
|
4344
4356
|
}
|
|
4345
4357
|
</style>
|
|
4346
|
-
`,e;if(this._loading)e='<div class="loading">Loading memory data...</div>';else if(this._error)e=`<div class="error-state">Error: ${this._escapeHtml(this._error)}</div>`;else{let
|
|
4347
|
-
<div class="content-main">${
|
|
4358
|
+
`,e;if(this._loading)e='<div class="loading">Loading memory data...</div>';else if(this._error)e=`<div class="error-state">Error: ${this._escapeHtml(this._error)}</div>`;else{let i;switch(this._activeTab){case"summary":i=this._renderSummary();break;case"search":i=this._renderSearch();break;case"episodes":i=this._renderEpisodes();break;case"patterns":i=this._renderPatterns();break;case"skills":i=this._renderSkills();break;default:i=this._renderSummary()}e=`
|
|
4359
|
+
<div class="content-main">${i}</div>
|
|
4348
4360
|
${this._renderDetail()}
|
|
4349
4361
|
`}this.shadowRoot.innerHTML=`
|
|
4350
4362
|
${t}
|
|
@@ -4353,16 +4365,16 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4353
4365
|
<span class="browser-title">Memory System</span>
|
|
4354
4366
|
</div>
|
|
4355
4367
|
<div class="tabs" role="tablist" aria-label="Memory browser sections">
|
|
4356
|
-
${
|
|
4357
|
-
<button class="tab ${this._activeTab===
|
|
4358
|
-
data-tab="${
|
|
4368
|
+
${pe.map((i,a)=>`
|
|
4369
|
+
<button class="tab ${this._activeTab===i.id?"active":""}"
|
|
4370
|
+
data-tab="${i.id}"
|
|
4359
4371
|
role="tab"
|
|
4360
|
-
id="tab-${
|
|
4361
|
-
aria-selected="${this._activeTab===
|
|
4362
|
-
aria-controls="tabpanel-${
|
|
4363
|
-
tabindex="${this._activeTab===
|
|
4364
|
-
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${
|
|
4365
|
-
${
|
|
4372
|
+
id="tab-${i.id}"
|
|
4373
|
+
aria-selected="${this._activeTab===i.id}"
|
|
4374
|
+
aria-controls="tabpanel-${i.id}"
|
|
4375
|
+
tabindex="${this._activeTab===i.id?"0":"-1"}">
|
|
4376
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${i.icon}"/></svg>
|
|
4377
|
+
${i.label}
|
|
4366
4378
|
</button>
|
|
4367
4379
|
`).join("")}
|
|
4368
4380
|
</div>
|
|
@@ -4370,12 +4382,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4370
4382
|
${e}
|
|
4371
4383
|
</div>
|
|
4372
4384
|
</div>
|
|
4373
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.querySelectorAll(".tab");t.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(t),u=c.key==="ArrowRight"?(l+1)%p.length:(l-1+p.length)%p.length;p[u].focus(),this._setTab(p[u].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 e=this.shadowRoot.getElementById("close-detail");e&&e.addEventListener("click",()=>this._closeDetail());let
|
|
4385
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.querySelectorAll(".tab");t.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(t),u=c.key==="ArrowRight"?(l+1)%p.length:(l-1+p.length)%p.length;p[u].focus(),this._setTab(p[u].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 e=this.shadowRoot.getElementById("close-detail");e&&e.addEventListener("click",()=>this._closeDetail());let i=this.shadowRoot.getElementById("consolidate-btn");i&&i.addEventListener("click",()=>this._triggerConsolidation());let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());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(t){let e=t.dataset.id;switch(t.dataset.type){case"episode":this._selectEpisode(e);break;case"pattern":this._selectPattern(e);break;case"skill":this._selectSkill(e);break}}_navigateItemCards(t,e){let i=Array.from(this.shadowRoot.querySelectorAll(".item-card")),a=i.indexOf(t);if(a===-1)return;let s=e==="next"?a+1:a-1;s>=0&&s<i.length&&i[s].focus()}};customElements.get("loki-memory-browser")||customElements.define("loki-memory-browser",K);var he=[{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}],ue=[{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"}],ge=[{id:"all",label:"All Sources"},{id:"cli",label:"CLI"},{id:"api",label:"API"},{id:"vscode",label:"VS Code"},{id:"mcp",label:"MCP"},{id:"dashboard",label:"Dashboard"}],V=class extends h{static get observedAttributes(){return["api-url","theme","time-range","signal-type","source"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._timeRange="7d",this._signalType="all",this._source="all",this._metrics=null,this._trends=null,this._signals=[],this._selectedMetric=null}connectedCallback(){super.connectedCallback(),this._timeRange=this.getAttribute("time-range")||"7d",this._signalType=this.getAttribute("signal-type")||"all",this._source=this.getAttribute("source")||"all",this._setupApi(),this._loadData()}attributeChangedCallback(t,e,i){if(e!==i)switch(t){case"api-url":this._api&&(this._api.baseUrl=i,this._loadData());break;case"theme":this._applyTheme();break;case"time-range":this._timeRange=i,this._loadData();break;case"signal-type":this._signalType=i,this._loadData();break;case"source":this._source=i,this._loadData();break}}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadData(){this._loading=!0,this._error=null,this.render();try{let t={timeRange:this._timeRange,signalType:this._signalType!=="all"?this._signalType:void 0,source:this._source!=="all"?this._source:void 0},[e,i,a]=await Promise.all([this._api.getLearningMetrics(t).catch(()=>null),this._api.getLearningTrends(t).catch(()=>null),this._api.getLearningSignals({...t,limit:50}).catch(()=>[])]);this._metrics=e,this._trends=i,this._signals=a||[]}catch(t){this._error=t.message||"Failed to load learning data"}this._loading=!1,this.render()}_setFilter(t,e){switch(t){case"timeRange":this._timeRange=e,this.setAttribute("time-range",e);break;case"signalType":this._signalType=e,this.setAttribute("signal-type",e);break;case"source":this._source=e,this.setAttribute("source",e);break}this.dispatchEvent(new CustomEvent("filter-change",{detail:{timeRange:this._timeRange,signalType:this._signalType,source:this._source}})),this._loadData()}_selectMetric(t,e){this._selectedMetric={type:t,item:e},this.dispatchEvent(new CustomEvent("metric-select",{detail:{type:t,item:e}})),this.render()}_closeDetail(){this._selectedMetric=null,this.render()}_formatNumber(t){return t>=1e6?(t/1e6).toFixed(1)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":t?.toString()||"0"}_formatPercent(t){return(t*100).toFixed(1)+"%"}_formatDuration(t){return t<60?t.toFixed(0)+"s":t<3600?(t/60).toFixed(1)+"m":(t/3600).toFixed(1)+"h"}_escapeHtml(t){if(!t)return"";let e=document.createElement("div");return e.textContent=t,e.innerHTML}_renderFilters(){return`
|
|
4374
4386
|
<div class="filters">
|
|
4375
4387
|
<div class="filter-group">
|
|
4376
4388
|
<label>Time Range</label>
|
|
4377
4389
|
<select id="time-range-select" class="filter-select">
|
|
4378
|
-
${
|
|
4390
|
+
${he.map(t=>`
|
|
4379
4391
|
<option value="${t.id}" ${this._timeRange===t.id?"selected":""}>${t.label}</option>
|
|
4380
4392
|
`).join("")}
|
|
4381
4393
|
</select>
|
|
@@ -4391,7 +4403,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4391
4403
|
<div class="filter-group">
|
|
4392
4404
|
<label>Source</label>
|
|
4393
4405
|
<select id="source-select" class="filter-select">
|
|
4394
|
-
${
|
|
4406
|
+
${ge.map(t=>`
|
|
4395
4407
|
<option value="${t.id}" ${this._source===t.id?"selected":""}>${t.label}</option>
|
|
4396
4408
|
`).join("")}
|
|
4397
4409
|
</select>
|
|
@@ -4404,7 +4416,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4404
4416
|
Refresh
|
|
4405
4417
|
</button>
|
|
4406
4418
|
</div>
|
|
4407
|
-
`}_renderSummaryCards(){if(!this._metrics)return'<div class="empty-state">No metrics available</div>';let{totalSignals:t,signalsByType:e,signalsBySource:
|
|
4419
|
+
`}_renderSummaryCards(){if(!this._metrics)return'<div class="empty-state">No metrics available</div>';let{totalSignals:t,signalsByType:e,signalsBySource:i,aggregation:a}=this._metrics;return`
|
|
4408
4420
|
<div class="summary-cards">
|
|
4409
4421
|
<div class="summary-card">
|
|
4410
4422
|
<div class="summary-card-header">
|
|
@@ -4425,11 +4437,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4425
4437
|
<div class="summary-card">
|
|
4426
4438
|
<div class="summary-card-header">
|
|
4427
4439
|
<span class="summary-card-title">Sources</span>
|
|
4428
|
-
<span class="summary-card-count">${Object.keys(
|
|
4440
|
+
<span class="summary-card-count">${Object.keys(i||{}).length}</span>
|
|
4429
4441
|
</div>
|
|
4430
4442
|
<div class="summary-card-detail">Signal sources active</div>
|
|
4431
4443
|
<div class="signal-breakdown">
|
|
4432
|
-
${Object.entries(
|
|
4444
|
+
${Object.entries(i||{}).map(([s,r])=>`
|
|
4433
4445
|
<div class="breakdown-item">
|
|
4434
4446
|
<span class="breakdown-label source-badge ${s}">${s}</span>
|
|
4435
4447
|
<span class="breakdown-value">${this._formatNumber(r)}</span>
|
|
@@ -4441,21 +4453,21 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4441
4453
|
<div class="summary-card">
|
|
4442
4454
|
<div class="summary-card-header">
|
|
4443
4455
|
<span class="summary-card-title">Patterns Found</span>
|
|
4444
|
-
<span class="summary-card-count">${this._formatNumber((
|
|
4456
|
+
<span class="summary-card-count">${this._formatNumber((a?.preferences?.length||0)+(a?.error_patterns?.length||0)+(a?.success_patterns?.length||0))}</span>
|
|
4445
4457
|
</div>
|
|
4446
4458
|
<div class="summary-card-detail">Aggregated learnings</div>
|
|
4447
4459
|
<div class="pattern-counts">
|
|
4448
4460
|
<div class="pattern-count">
|
|
4449
4461
|
<span class="pattern-icon preferences">P</span>
|
|
4450
|
-
<span>${
|
|
4462
|
+
<span>${a?.preferences?.length||0} Preferences</span>
|
|
4451
4463
|
</div>
|
|
4452
4464
|
<div class="pattern-count">
|
|
4453
4465
|
<span class="pattern-icon errors">E</span>
|
|
4454
|
-
<span>${
|
|
4466
|
+
<span>${a?.error_patterns?.length||0} Errors</span>
|
|
4455
4467
|
</div>
|
|
4456
4468
|
<div class="pattern-count">
|
|
4457
4469
|
<span class="pattern-icon success">S</span>
|
|
4458
|
-
<span>${
|
|
4470
|
+
<span>${a?.success_patterns?.length||0} Success</span>
|
|
4459
4471
|
</div>
|
|
4460
4472
|
</div>
|
|
4461
4473
|
</div>
|
|
@@ -4473,16 +4485,16 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4473
4485
|
</div>
|
|
4474
4486
|
</div>
|
|
4475
4487
|
</div>
|
|
4476
|
-
`}_renderTrendChart(){if(!this._trends||!this._trends.dataPoints||this._trends.dataPoints.length===0)return'<div class="chart-empty">No trend data available</div>';let{dataPoints:t,maxValue:e}=this._trends,
|
|
4488
|
+
`}_renderTrendChart(){if(!this._trends||!this._trends.dataPoints||this._trends.dataPoints.length===0)return'<div class="chart-empty">No trend data available</div>';let{dataPoints:t,maxValue:e}=this._trends,i=120,a=400,s=20,r=t.map((n,l)=>{let c=s+l/(t.length-1||1)*(a-s*2),p=i-s-n.count/(e||1)*(i-s*2);return`${c},${p}`}).join(" "),o=`${s},${i-s} ${r} ${a-s},${i-s}`;return`
|
|
4477
4489
|
<div class="trend-chart">
|
|
4478
4490
|
<div class="chart-header">
|
|
4479
4491
|
<span class="chart-title">Signal Volume Over Time</span>
|
|
4480
4492
|
<span class="chart-subtitle">${this._trends.period}</span>
|
|
4481
4493
|
</div>
|
|
4482
|
-
<svg class="chart-svg" viewBox="0 0 ${
|
|
4494
|
+
<svg class="chart-svg" viewBox="0 0 ${a} ${i}">
|
|
4483
4495
|
<!-- Grid lines -->
|
|
4484
|
-
<line x1="${s}" y1="${s}" x2="${s}" y2="${
|
|
4485
|
-
<line x1="${s}" y1="${
|
|
4496
|
+
<line x1="${s}" y1="${s}" x2="${s}" y2="${i-s}" stroke="var(--loki-border)" stroke-width="1"/>
|
|
4497
|
+
<line x1="${s}" y1="${i-s}" x2="${a-s}" y2="${i-s}" stroke="var(--loki-border)" stroke-width="1"/>
|
|
4486
4498
|
|
|
4487
4499
|
<!-- Area fill -->
|
|
4488
4500
|
<polygon points="${o}" fill="var(--loki-accent-muted)" />
|
|
@@ -4491,7 +4503,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4491
4503
|
<polyline points="${r}" fill="none" stroke="var(--loki-accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4492
4504
|
|
|
4493
4505
|
<!-- Data points -->
|
|
4494
|
-
${t.map((n,l)=>{let c=s+l/(t.length-1||1)*(
|
|
4506
|
+
${t.map((n,l)=>{let c=s+l/(t.length-1||1)*(a-s*2),p=i-s-n.count/(e||1)*(i-s*2);return`<circle cx="${c}" cy="${p}" r="3" fill="var(--loki-accent)" />`}).join("")}
|
|
4495
4507
|
</svg>
|
|
4496
4508
|
<div class="chart-labels">
|
|
4497
4509
|
${t.length>0?`
|
|
@@ -4500,7 +4512,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4500
4512
|
`:""}
|
|
4501
4513
|
</div>
|
|
4502
4514
|
</div>
|
|
4503
|
-
`}_renderTopLists(){if(!this._metrics?.aggregation)return"";let{preferences:t,error_patterns:e,success_patterns:
|
|
4515
|
+
`}_renderTopLists(){if(!this._metrics?.aggregation)return"";let{preferences:t,error_patterns:e,success_patterns:i,tool_efficiencies:a}=this._metrics.aggregation;return`
|
|
4504
4516
|
<div class="top-lists">
|
|
4505
4517
|
<!-- User Preferences -->
|
|
4506
4518
|
<div class="top-list">
|
|
@@ -4550,10 +4562,10 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4550
4562
|
<div class="top-list">
|
|
4551
4563
|
<div class="list-header">
|
|
4552
4564
|
<span class="list-title">Success Patterns</span>
|
|
4553
|
-
<span class="list-count">${
|
|
4565
|
+
<span class="list-count">${i?.length||0}</span>
|
|
4554
4566
|
</div>
|
|
4555
4567
|
<div class="list-items" role="list">
|
|
4556
|
-
${(
|
|
4568
|
+
${(i||[]).slice(0,5).map(s=>`
|
|
4557
4569
|
<div class="list-item success-item" data-type="success_pattern" data-id="${s.pattern_name}" tabindex="0" role="listitem">
|
|
4558
4570
|
<div class="item-main">
|
|
4559
4571
|
<span class="item-key">${this._escapeHtml(s.pattern_name)}</span>
|
|
@@ -4572,10 +4584,10 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4572
4584
|
<div class="top-list">
|
|
4573
4585
|
<div class="list-header">
|
|
4574
4586
|
<span class="list-title">Tool Efficiency Rankings</span>
|
|
4575
|
-
<span class="list-count">${
|
|
4587
|
+
<span class="list-count">${a?.length||0}</span>
|
|
4576
4588
|
</div>
|
|
4577
4589
|
<div class="list-items" role="list">
|
|
4578
|
-
${(
|
|
4590
|
+
${(a||[]).slice(0,5).map((s,r)=>`
|
|
4579
4591
|
<div class="list-item tool-item" data-type="tool_efficiency" data-id="${s.tool_name}" tabindex="0" role="listitem">
|
|
4580
4592
|
<div class="item-rank">#${r+1}</div>
|
|
4581
4593
|
<div class="item-main">
|
|
@@ -4598,11 +4610,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4598
4610
|
<span class="signals-count">${this._signals.length}</span>
|
|
4599
4611
|
</div>
|
|
4600
4612
|
<div class="signals-list">
|
|
4601
|
-
${this._signals.slice(0,10).map(t=>{let e=t.data||{},
|
|
4613
|
+
${this._signals.slice(0,10).map(t=>{let e=t.data||{},i=t.type||"unknown",a=e.action||t.action||i,s=e.source||t.source||"-",r=e.outcome||t.outcome||"-",o=t.timestamp?new Date(t.timestamp).toLocaleTimeString():"-";return`
|
|
4602
4614
|
<div class="signal-item">
|
|
4603
|
-
<div class="signal-type ${
|
|
4615
|
+
<div class="signal-type ${i}">${i.replace("_"," ")}</div>
|
|
4604
4616
|
<div class="signal-content">
|
|
4605
|
-
<span class="signal-action">${this._escapeHtml(
|
|
4617
|
+
<span class="signal-action">${this._escapeHtml(a)}</span>
|
|
4606
4618
|
<span class="signal-source">${s}</span>
|
|
4607
4619
|
</div>
|
|
4608
4620
|
<div class="signal-meta">
|
|
@@ -4612,7 +4624,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4612
4624
|
</div>`}).join("")}
|
|
4613
4625
|
</div>
|
|
4614
4626
|
</div>
|
|
4615
|
-
`}_renderDetailPanel(){if(!this._selectedMetric)return"";let{type:t,item:e}=this._selectedMetric,
|
|
4627
|
+
`}_renderDetailPanel(){if(!this._selectedMetric)return"";let{type:t,item:e}=this._selectedMetric,i="";switch(t){case"preference":i=`
|
|
4616
4628
|
<div class="detail-row">
|
|
4617
4629
|
<span class="detail-label">Preference Key</span>
|
|
4618
4630
|
<span class="detail-value">${this._escapeHtml(e.preference_key)}</span>
|
|
@@ -4633,11 +4645,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4633
4645
|
<div class="detail-section">
|
|
4634
4646
|
<div class="detail-label">Alternatives Rejected</div>
|
|
4635
4647
|
<ul class="detail-list">
|
|
4636
|
-
${e.alternatives_rejected.map(
|
|
4648
|
+
${e.alternatives_rejected.map(a=>`<li>${this._escapeHtml(a)}</li>`).join("")}
|
|
4637
4649
|
</ul>
|
|
4638
4650
|
</div>
|
|
4639
4651
|
`:""}
|
|
4640
|
-
`;break;case"error_pattern":
|
|
4652
|
+
`;break;case"error_pattern":i=`
|
|
4641
4653
|
<div class="detail-row">
|
|
4642
4654
|
<span class="detail-label">Error Type</span>
|
|
4643
4655
|
<span class="detail-value">${this._escapeHtml(e.error_type)}</span>
|
|
@@ -4650,7 +4662,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4650
4662
|
<div class="detail-section">
|
|
4651
4663
|
<div class="detail-label">Common Messages</div>
|
|
4652
4664
|
<ul class="detail-list">
|
|
4653
|
-
${e.common_messages.map(
|
|
4665
|
+
${e.common_messages.map(a=>`<li>${this._escapeHtml(a)}</li>`).join("")}
|
|
4654
4666
|
</ul>
|
|
4655
4667
|
</div>
|
|
4656
4668
|
`:""}
|
|
@@ -4658,11 +4670,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4658
4670
|
<div class="detail-section">
|
|
4659
4671
|
<div class="detail-label">Known Resolutions</div>
|
|
4660
4672
|
<ul class="detail-list success">
|
|
4661
|
-
${e.resolutions.map(
|
|
4673
|
+
${e.resolutions.map(a=>`<li>${this._escapeHtml(a)}</li>`).join("")}
|
|
4662
4674
|
</ul>
|
|
4663
4675
|
</div>
|
|
4664
4676
|
`:""}
|
|
4665
|
-
`;break;case"success_pattern":
|
|
4677
|
+
`;break;case"success_pattern":i=`
|
|
4666
4678
|
<div class="detail-row">
|
|
4667
4679
|
<span class="detail-label">Pattern Name</span>
|
|
4668
4680
|
<span class="detail-value">${this._escapeHtml(e.pattern_name)}</span>
|
|
@@ -4675,11 +4687,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4675
4687
|
<div class="detail-section">
|
|
4676
4688
|
<div class="detail-label">Common Actions</div>
|
|
4677
4689
|
<ol class="detail-list numbered">
|
|
4678
|
-
${e.common_actions.map(
|
|
4690
|
+
${e.common_actions.map(a=>`<li>${this._escapeHtml(a)}</li>`).join("")}
|
|
4679
4691
|
</ol>
|
|
4680
4692
|
</div>
|
|
4681
4693
|
`:""}
|
|
4682
|
-
`;break;case"tool_efficiency":
|
|
4694
|
+
`;break;case"tool_efficiency":i=`
|
|
4683
4695
|
<div class="detail-row">
|
|
4684
4696
|
<span class="detail-label">Tool Name</span>
|
|
4685
4697
|
<span class="detail-value">${this._escapeHtml(e.tool_name)}</span>
|
|
@@ -4704,22 +4716,22 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
4704
4716
|
<div class="detail-section">
|
|
4705
4717
|
<div class="detail-label">Alternative Tools</div>
|
|
4706
4718
|
<div class="tag-list">
|
|
4707
|
-
${e.alternative_tools.map(
|
|
4719
|
+
${e.alternative_tools.map(a=>`<span class="tag">${this._escapeHtml(a)}</span>`).join("")}
|
|
4708
4720
|
</div>
|
|
4709
4721
|
</div>
|
|
4710
4722
|
`:""}
|
|
4711
4723
|
`;break}return`
|
|
4712
4724
|
<div class="detail-panel">
|
|
4713
4725
|
<div class="detail-header">
|
|
4714
|
-
<h3>${t.replace("_"," ").replace(/\b\w/g,
|
|
4726
|
+
<h3>${t.replace("_"," ").replace(/\b\w/g,a=>a.toUpperCase())}</h3>
|
|
4715
4727
|
<button class="close-btn" id="close-detail">×</button>
|
|
4716
4728
|
</div>
|
|
4717
4729
|
<div class="detail-body">
|
|
4718
|
-
${
|
|
4730
|
+
${i}
|
|
4719
4731
|
<div class="detail-row">
|
|
4720
4732
|
<span class="detail-label">Sources</span>
|
|
4721
4733
|
<div class="source-tags">
|
|
4722
|
-
${(e.sources||[]).map(
|
|
4734
|
+
${(e.sources||[]).map(a=>`<span class="source-badge ${a}">${a}</span>`).join("")}
|
|
4723
4735
|
</div>
|
|
4724
4736
|
</div>
|
|
4725
4737
|
<div class="detail-row">
|
|
@@ -5382,7 +5394,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5382
5394
|
${e}
|
|
5383
5395
|
</div>
|
|
5384
5396
|
</div>
|
|
5385
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("time-range-select");t&&t.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let e=this.shadowRoot.getElementById("signal-type-select");e&&e.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let
|
|
5397
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot.getElementById("time-range-select");t&&t.addEventListener("change",r=>this._setFilter("timeRange",r.target.value));let e=this.shadowRoot.getElementById("signal-type-select");e&&e.addEventListener("change",r=>this._setFilter("signalType",r.target.value));let i=this.shadowRoot.getElementById("source-select");i&&i.addEventListener("change",r=>this._setFilter("source",r.target.value));let a=this.shadowRoot.getElementById("refresh-btn");a&&a.addEventListener("click",()=>this._loadData());let s=this.shadowRoot.getElementById("close-detail");s&&s.addEventListener("click",()=>this._closeDetail()),this.shadowRoot.querySelectorAll(".list-item").forEach(r=>{r.addEventListener("click",()=>{let o=r.dataset.type,n=r.dataset.id,l=this._findItemData(o,n);l&&this._selectMetric(o,l)}),r.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r.click())})})}_findItemData(t,e){if(!this._metrics?.aggregation)return null;switch(t){case"preference":return this._metrics.aggregation.preferences?.find(i=>i.preference_key===e);case"error_pattern":return this._metrics.aggregation.error_patterns?.find(i=>i.error_type===e);case"success_pattern":return this._metrics.aggregation.success_patterns?.find(i=>i.pattern_name===e);case"tool_efficiency":return this._metrics.aggregation.tool_efficiencies?.find(i=>i.tool_name===e);default:return null}}};customElements.get("loki-learning-dashboard")||customElements.define("loki-learning-dashboard",V);var ve=[{id:"overview",label:"Overview"},{id:"decisions",label:"Decision Log"},{id:"convergence",label:"Convergence"},{id:"agents",label:"Agents"}],Y=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._activeTab="overview",this._pollInterval=null,this._councilState=null,this._verdicts=[],this._convergence=[],this._agents=[],this._selectedAgent=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null),this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null)}async _loadData(){try{let[e,i,a,s]=await Promise.allSettled([this._api._get("/api/council/state"),this._api._get("/api/council/verdicts"),this._api._get("/api/council/convergence"),this._api._get("/api/agents")]);e.status==="fulfilled"&&(this._councilState=e.value),i.status==="fulfilled"&&(this._verdicts=i.value.verdicts||[]),a.status==="fulfilled"&&(this._convergence=a.value.dataPoints||[]),s.status==="fulfilled"&&(this._agents=Array.isArray(s.value)?s.value:[]),this._error=null}catch(e){this._error=e.message}let t=JSON.stringify({s:this._councilState,v:this._verdicts,c:this._convergence,a:this._agents,e:this._error});t!==this._lastDataHash&&(this._lastDataHash=t,this.render())}async _forceReview(){try{await this._api._post("/api/council/force-review"),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"force-review"},bubbles:!0}))}catch(t){this._error=`Failed to force review: ${t.message}`,this.render()}}async _killAgent(t){if(confirm(`Kill agent ${t}?`))try{await this._api._post(`/api/agents/${t}/kill`),this.dispatchEvent(new CustomEvent("council-action",{detail:{action:"kill-agent",agentId:t},bubbles:!0})),await this._loadData()}catch(e){this._error=`Failed to kill agent: ${e.message}`,this.render()}}async _pauseAgent(t){try{await this._api._post(`/api/agents/${t}/pause`),await this._loadData()}catch(e){this._error=`Failed to pause agent: ${e.message}`,this.render()}}async _resumeAgent(t){try{await this._api._post(`/api/agents/${t}/resume`),await this._loadData()}catch(e){this._error=`Failed to resume agent: ${e.message}`,this.render()}}_setTab(t){this._activeTab=t,this.render()}_selectAgent(t){this._selectedAgent=this._selectedAgent?.id===t.id?null:t,this.render()}render(){let t=this.shadowRoot;t&&(this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=null),t.innerHTML=`
|
|
5386
5398
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
5387
5399
|
<div class="council-dashboard">
|
|
5388
5400
|
<div class="council-header">
|
|
@@ -5396,7 +5408,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5396
5408
|
</div>
|
|
5397
5409
|
|
|
5398
5410
|
<div class="tabs">
|
|
5399
|
-
${
|
|
5411
|
+
${ve.map(e=>`
|
|
5400
5412
|
<button
|
|
5401
5413
|
class="tab ${this._activeTab===e.id?"active":""}"
|
|
5402
5414
|
data-tab="${e.id}"
|
|
@@ -5410,7 +5422,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5410
5422
|
|
|
5411
5423
|
${this._error?`<div class="error-banner">${this._error}</div>`:""}
|
|
5412
5424
|
</div>
|
|
5413
|
-
`,this._attachEventListeners())}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("force-review-btn");e&&e.addEventListener("click",()=>this._forceReview()),t.querySelectorAll(".tab[data-tab]").forEach(
|
|
5425
|
+
`,this._attachEventListeners())}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("force-review-btn");e&&e.addEventListener("click",()=>this._forceReview()),t.querySelectorAll(".tab[data-tab]").forEach(i=>{i.addEventListener("click",()=>this._setTab(i.dataset.tab))})}_renderTabContent(){switch(this._activeTab){case"overview":return this._renderOverview();case"decisions":return this._renderDecisions();case"convergence":return this._renderConvergence();case"agents":return this._renderAgents();default:return""}}_renderOverview(){let t=this._councilState||{},e=t.consecutive_no_change||0,i=t.done_signals||0,a=t.total_votes||0,s=t.approve_votes||0,r=this._verdicts.length>0?this._verdicts[this._verdicts.length-1]:null,o=this._agents.filter(n=>n.alive).length;return`
|
|
5414
5426
|
<div class="overview-grid">
|
|
5415
5427
|
<div class="stat-card">
|
|
5416
5428
|
<div class="stat-label">Council Status</div>
|
|
@@ -5420,7 +5432,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5420
5432
|
</div>
|
|
5421
5433
|
<div class="stat-card">
|
|
5422
5434
|
<div class="stat-label">Total Votes Cast</div>
|
|
5423
|
-
<div class="stat-value">${
|
|
5435
|
+
<div class="stat-value">${a}</div>
|
|
5424
5436
|
<div class="stat-sub">${s} approved</div>
|
|
5425
5437
|
</div>
|
|
5426
5438
|
<div class="stat-card">
|
|
@@ -5430,7 +5442,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5430
5442
|
</div>
|
|
5431
5443
|
<div class="stat-card">
|
|
5432
5444
|
<div class="stat-label">Done Signals</div>
|
|
5433
|
-
<div class="stat-value ${
|
|
5445
|
+
<div class="stat-value ${i>=2?"text-green":""}">${i}</div>
|
|
5434
5446
|
<div class="stat-sub">from agent output</div>
|
|
5435
5447
|
</div>
|
|
5436
5448
|
<div class="stat-card">
|
|
@@ -5455,12 +5467,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5455
5467
|
</div>
|
|
5456
5468
|
</div>
|
|
5457
5469
|
`:""}
|
|
5458
|
-
`}_renderConvergenceBar(){let t=this._convergence.slice(-20);if(t.length===0)return'<span class="text-muted">No data</span>';let e=Math.max(...t.map(
|
|
5470
|
+
`}_renderConvergenceBar(){let t=this._convergence.slice(-20);if(t.length===0)return'<span class="text-muted">No data</span>';let e=Math.max(...t.map(i=>i.files_changed),1);return`
|
|
5459
5471
|
<div class="bar-chart">
|
|
5460
|
-
${t.map(
|
|
5461
|
-
<div class="bar-wrapper" title="Iter ${
|
|
5462
|
-
<div class="bar ${s?"bar-stagnant":"bar-active"}" style="height: ${
|
|
5463
|
-
<div class="bar-label">${
|
|
5472
|
+
${t.map(i=>{let a=Math.max(4,i.files_changed/e*60),s=i.no_change_streak>0;return`
|
|
5473
|
+
<div class="bar-wrapper" title="Iter ${i.iteration}: ${i.files_changed} files changed">
|
|
5474
|
+
<div class="bar ${s?"bar-stagnant":"bar-active"}" style="height: ${a}px"></div>
|
|
5475
|
+
<div class="bar-label">${i.iteration}</div>
|
|
5464
5476
|
</div>
|
|
5465
5477
|
`}).join("")}
|
|
5466
5478
|
</div>
|
|
@@ -5517,9 +5529,9 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5517
5529
|
</div>
|
|
5518
5530
|
`}_renderAgents(){if(this._agents.length===0)return'<div class="empty-state">No agents registered.</div>';let t=`
|
|
5519
5531
|
<div class="agents-list">
|
|
5520
|
-
${this._agents.map((e,
|
|
5532
|
+
${this._agents.map((e,i)=>`
|
|
5521
5533
|
<div class="agent-card ${this._selectedAgent?.id===e.id?"agent-selected":""}"
|
|
5522
|
-
data-agent-index="${
|
|
5534
|
+
data-agent-index="${i}">
|
|
5523
5535
|
<div class="agent-header">
|
|
5524
5536
|
<span class="agent-name">${e.name||e.id||"Unknown"}</span>
|
|
5525
5537
|
<span class="agent-status ${e.alive?"status-alive":"status-dead"}">
|
|
@@ -5550,7 +5562,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5550
5562
|
</div>
|
|
5551
5563
|
`).join("")}
|
|
5552
5564
|
</div>
|
|
5553
|
-
`;return this._pendingRaf=requestAnimationFrame(()=>{this._pendingRaf=null;let e=this.shadowRoot;e&&e.querySelectorAll(".agent-card[data-agent-index]").forEach(
|
|
5565
|
+
`;return this._pendingRaf=requestAnimationFrame(()=>{this._pendingRaf=null;let e=this.shadowRoot;e&&e.querySelectorAll(".agent-card[data-agent-index]").forEach(i=>{let a=parseInt(i.dataset.agentIndex,10),s=this._agents[a];s&&(i.addEventListener("click",()=>this._selectAgent(s)),i.querySelectorAll("[data-action]").forEach(r=>{r.addEventListener("click",o=>{o.stopPropagation();let n=r.dataset.action,l=r.dataset.agentId;n==="pause"?this._pauseAgent(l):n==="kill"?this._killAgent(l):n==="resume"&&this._resumeAgent(l)})}))})}),t}_formatTime(t){if(!t)return"";try{return new Date(t).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}catch{return t}}_getStyles(){return`
|
|
5554
5566
|
:host {
|
|
5555
5567
|
display: block;
|
|
5556
5568
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
@@ -5969,7 +5981,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
5969
5981
|
color: var(--loki-error);
|
|
5970
5982
|
font-size: 12px;
|
|
5971
5983
|
}
|
|
5972
|
-
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",Y);var
|
|
5984
|
+
`}};customElements.get("loki-council-dashboard")||customElements.define("loki-council-dashboard",Y);var qt={critical:0,major:1,minor:2},me={critical:"var(--loki-status-error, #ef4444)",major:"var(--loki-status-warning, #f59e0b)",minor:"var(--loki-text-muted, #71717a)"},W=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._checklist=null,this._waivers=[],this._expandedCategories=new Set,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),5e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),5e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{let[t,e]=await Promise.all([this._api.getChecklist(),this._api.getChecklistWaivers().catch(()=>null)]),i=JSON.stringify(e),a=JSON.stringify(t)+i;if(a===this._lastDataHash)return;this._lastDataHash=a,this._checklist=t,this._waivers=e&&e.waivers?e.waivers.filter(s=>s.active):[],this._error=null,this.render()}catch(t){this._error=`Failed to load checklist: ${t.message}`,this.render()}}_isItemWaived(t){return this._waivers.some(e=>e.item_id===t)}_getWaiverForItem(t){return this._waivers.find(e=>e.item_id===t)||null}async _waiveItem(t){let e=window.prompt("Enter reason for waiving this item:");if(e)try{await this._api.addChecklistWaiver(t,e),this._lastDataHash=null,await this._loadData()}catch(i){this._error=`Failed to add waiver: ${i.message}`,this.render()}}async _unwaiveItem(t){try{await this._api.removeChecklistWaiver(t),this._lastDataHash=null,await this._loadData()}catch(e){this._error=`Failed to remove waiver: ${e.message}`,this.render()}}_toggleCategory(t){this._expandedCategories.has(t)?this._expandedCategories.delete(t):this._expandedCategories.add(t),this.render()}_getStyles(){return`
|
|
5973
5985
|
.checklist-viewer {
|
|
5974
5986
|
padding: 16px;
|
|
5975
5987
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -6217,16 +6229,16 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6217
6229
|
border-radius: 4px;
|
|
6218
6230
|
font-size: 12px;
|
|
6219
6231
|
}
|
|
6220
|
-
`}_getUnwaivedCriticalFailures(){if(!this._checklist?.categories)return[];let t=[];for(let e of this._checklist.categories)for(let
|
|
6232
|
+
`}_getUnwaivedCriticalFailures(){if(!this._checklist?.categories)return[];let t=[];for(let e of this._checklist.categories)for(let i of e.items||[])i.status==="failing"&&i.priority==="critical"&&!this._isItemWaived(i.id)&&t.push(i);return t}_renderGateBanner(){let t=this._getUnwaivedCriticalFailures();return t.length>0?`<div class="gate-banner gate-blocked">COUNCIL GATE: BLOCKED - ${t.length} critical item${t.length!==1?"s":""} must be verified or waived before completion</div>`:'<div class="gate-banner gate-passed">COUNCIL GATE: PASSED - No blocking critical failures</div>'}render(){let t=this.shadowRoot;if(!t)return;let e=this._checklist,i=e&&e.status!=="not_initialized"&&e.categories?.length>0;t.innerHTML=`
|
|
6221
6233
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
6222
6234
|
<div class="checklist-viewer">
|
|
6223
6235
|
<div class="checklist-header">
|
|
6224
6236
|
<h2 class="title">Spec Checklist</h2>
|
|
6225
|
-
${
|
|
6237
|
+
${i?this._renderBadges(e.summary):""}
|
|
6226
6238
|
</div>
|
|
6227
|
-
${
|
|
6228
|
-
${
|
|
6229
|
-
${
|
|
6239
|
+
${i?this._renderGateBanner():""}
|
|
6240
|
+
${i?this._renderProgress(e.summary):""}
|
|
6241
|
+
${i?this._renderCategories(e.categories):this._renderEmpty()}
|
|
6230
6242
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
6231
6243
|
</div>
|
|
6232
6244
|
`,this._attachEventListeners()}_renderBadges(t){if(!t)return"";let e=this._waivers.length;return`
|
|
@@ -6236,32 +6248,32 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6236
6248
|
${e?`<span class="badge badge-waived">${e} waived</span>`:""}
|
|
6237
6249
|
${t.pending?`<span class="badge badge-pending">${t.pending} pending</span>`:""}
|
|
6238
6250
|
</div>
|
|
6239
|
-
`}_renderProgress(t){if(!t||!t.total)return"";let e=t.verified/t.total*100,
|
|
6251
|
+
`}_renderProgress(t){if(!t||!t.total)return"";let e=t.verified/t.total*100,i=t.failing/t.total*100;return`
|
|
6240
6252
|
<div class="progress-container">
|
|
6241
6253
|
<div class="progress-bar">
|
|
6242
6254
|
<div class="progress-verified" style="width: ${e}%"></div>
|
|
6243
|
-
<div class="progress-failing" style="width: ${
|
|
6255
|
+
<div class="progress-failing" style="width: ${i}%"></div>
|
|
6244
6256
|
</div>
|
|
6245
6257
|
<div class="progress-label">
|
|
6246
6258
|
<span>${t.verified}/${t.total} verified | ${t.failing||0} failing | ${this._waivers.length} waived | ${t.pending||0} pending</span>
|
|
6247
6259
|
<span>${Math.round(e)}%</span>
|
|
6248
6260
|
</div>
|
|
6249
6261
|
</div>
|
|
6250
|
-
`}_renderCategories(t){return t?.length?t.map(e=>{let
|
|
6262
|
+
`}_renderCategories(t){return t?.length?t.map(e=>{let i=this._expandedCategories.has(e.name),a=e.items||[],s=a.filter(o=>o.status==="verified").length,r=a.filter(o=>o.status==="failing").length;return`
|
|
6251
6263
|
<div class="category">
|
|
6252
6264
|
<div class="category-header" data-category="${this._escapeHtml(e.name)}">
|
|
6253
6265
|
<div>
|
|
6254
6266
|
<span class="category-name">${this._escapeHtml(e.name)}</span>
|
|
6255
|
-
<span class="category-stats">${s}/${
|
|
6267
|
+
<span class="category-stats">${s}/${a.length} verified${r?`, ${r} failing`:""}</span>
|
|
6256
6268
|
</div>
|
|
6257
|
-
<span class="category-arrow ${
|
|
6269
|
+
<span class="category-arrow ${i?"expanded":""}">▶</span>
|
|
6258
6270
|
</div>
|
|
6259
|
-
${
|
|
6271
|
+
${i?`<div class="category-body">${this._renderItems(a)}</div>`:""}
|
|
6260
6272
|
</div>
|
|
6261
|
-
`}).join(""):this._renderEmpty()}_renderItems(t){return t?.length?[...t].sort((a
|
|
6273
|
+
`}).join(""):this._renderEmpty()}_renderItems(t){return t?.length?[...t].sort((i,a)=>(qt[i.priority]??2)-(qt[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=me[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>`:"",u="";return c&&(l?u=`<button class="waiver-btn waiver-btn-unwaive" data-unwaive-id="${this._escapeHtml(i.id)}">Unwaive</button>`:u=`<button class="waiver-btn" data-waive-id="${this._escapeHtml(i.id)}">Waive</button>`),`
|
|
6262
6274
|
<div class="item">
|
|
6263
|
-
<div class="item-status ${
|
|
6264
|
-
<div class="item-title">${this._escapeHtml(
|
|
6275
|
+
<div class="item-status ${a}"></div>
|
|
6276
|
+
<div class="item-title">${this._escapeHtml(i.title||i.id||"?")}</div>
|
|
6265
6277
|
<span class="item-priority" style="color:${r};border:1px solid ${r}">${s}</span>
|
|
6266
6278
|
${p}
|
|
6267
6279
|
${u}
|
|
@@ -6274,7 +6286,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6274
6286
|
<p><strong>No checklist data yet.</strong></p>
|
|
6275
6287
|
<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>
|
|
6276
6288
|
</div>
|
|
6277
|
-
`}_attachEventListeners(){let t=this.shadowRoot;t&&(t.querySelectorAll(".category-header[data-category]").forEach(e=>{e.addEventListener("click",()=>this._toggleCategory(e.dataset.category))}),t.querySelectorAll("button[data-waive-id]").forEach(e=>{e.addEventListener("click",
|
|
6289
|
+
`}_attachEventListeners(){let t=this.shadowRoot;t&&(t.querySelectorAll(".category-header[data-category]").forEach(e=>{e.addEventListener("click",()=>this._toggleCategory(e.dataset.category))}),t.querySelectorAll("button[data-waive-id]").forEach(e=>{e.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(e.dataset.waiveId)})}),t.querySelectorAll("button[data-unwaive-id]").forEach(e=>{e.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(e.dataset.unwaiveId)})}))}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",W);var Jt={not_initialized:{color:"var(--loki-text-muted, #71717a)",label:"Not Started",pulse:!1},starting:{color:"var(--loki-yellow, #ca8a04)",label:"Starting...",pulse:!0},running:{color:"var(--loki-green, #16a34a)",label:"Running",pulse:!0},stale:{color:"var(--loki-yellow, #ca8a04)",label:"Stale",pulse:!1},completed:{color:"var(--loki-text-muted, #a1a1aa)",label:"Completed",pulse:!1},failed:{color:"var(--loki-red, #dc2626)",label:"Failed",pulse:!1},crashed:{color:"var(--loki-red, #dc2626)",label:"Crashed",pulse:!1},stopped:{color:"var(--loki-text-muted, #a1a1aa)",label:"Stopped",pulse:!1},unknown:{color:"var(--loki-text-muted, #71717a)",label:"Unknown",pulse:!1}},Q=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._status=null,this._logs=[],this._lastDataHash=null,this._lastLogsHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{let[t,e]=await Promise.all([this._api.getAppRunnerStatus(),this._api.getAppRunnerLogs()]),i=JSON.stringify({status:t?.status,port:t?.port,restarts:t?.restart_count,url:t?.url}),a=JSON.stringify(e?.lines?.slice(-5)||[]),s=a!==this._lastLogsHash;if(i===this._lastDataHash&&!s)return;this._lastDataHash=i,this._lastLogsHash=a,this._status=t,this._logs=e?.lines||[],this._error=null,this.render(),this._scrollLogsToBottom()}catch(t){this._error||(this._error=`Failed to load app status: ${t.message}`,this.render())}}_scrollLogsToBottom(){let t=this.shadowRoot;if(!t)return;let e=t.querySelector(".log-area");e&&(e.scrollTop=e.scrollHeight)}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(t){this._error=`Restart failed: ${t.message}`,this.render()}}async _handleStop(){try{await this._api.stopApp(),this._loadData()}catch(t){this._error=`Stop failed: ${t.message}`,this.render()}}_formatUptime(t){if(!t)return"--";let e=new Date(t),a=Math.floor((new Date-e)/1e3);if(a<60)return`${a}s`;if(a<3600)return`${Math.floor(a/60)}m ${a%60}s`;let s=Math.floor(a/3600),r=Math.floor(a%3600/60);return`${s}h ${r}m`}_isValidUrl(t){if(!t)return!1;try{let e=new URL(t);return e.protocol==="http:"||e.protocol==="https:"}catch{return!1}}_getStyles(){return`
|
|
6278
6290
|
.app-status {
|
|
6279
6291
|
padding: 16px;
|
|
6280
6292
|
font-family: var(--loki-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -6435,7 +6447,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6435
6447
|
border-radius: 4px;
|
|
6436
6448
|
font-size: 12px;
|
|
6437
6449
|
}
|
|
6438
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._status,
|
|
6450
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._status,i=e&&e.status&&e.status!=="not_initialized";t.innerHTML=`
|
|
6439
6451
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
6440
6452
|
<div class="app-status">
|
|
6441
6453
|
<div class="header">
|
|
@@ -6443,19 +6455,19 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6443
6455
|
<h2 class="title">App Runner</h2>
|
|
6444
6456
|
${this._renderStatusBadge(e)}
|
|
6445
6457
|
</div>
|
|
6446
|
-
${
|
|
6458
|
+
${i?this._renderActions(e):""}
|
|
6447
6459
|
</div>
|
|
6448
|
-
${
|
|
6449
|
-
${
|
|
6450
|
-
${
|
|
6460
|
+
${i?this._renderStatusCard(e):""}
|
|
6461
|
+
${i&&this._logs.length>0?this._renderLogs():""}
|
|
6462
|
+
${i?"":this._renderEmpty()}
|
|
6451
6463
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
6452
6464
|
</div>
|
|
6453
|
-
`,this._attachEventListeners()}_renderStatusBadge(t){let e=t?.status||"not_initialized",
|
|
6454
|
-
<span class="status-badge" style="background: color-mix(in srgb, ${
|
|
6455
|
-
<span class="status-dot ${
|
|
6456
|
-
${this._escapeHtml(
|
|
6465
|
+
`,this._attachEventListeners()}_renderStatusBadge(t){let e=t?.status||"not_initialized",i=Jt[e]||Jt.not_initialized;return`
|
|
6466
|
+
<span class="status-badge" style="background: color-mix(in srgb, ${i.color} 15%, transparent); color: ${i.color}">
|
|
6467
|
+
<span class="status-dot ${i.pulse?"pulse":""}" style="background: ${i.color}"></span>
|
|
6468
|
+
${this._escapeHtml(i.label)}
|
|
6457
6469
|
</span>
|
|
6458
|
-
`}_renderStatusCard(t){let
|
|
6470
|
+
`}_renderStatusCard(t){let i=this._isValidUrl(t.url)?`<a href="${this._escapeHtml(t.url)}" target="_blank" rel="noopener noreferrer">${this._escapeHtml(t.url)}</a>`:this._escapeHtml(t.url||"--");return`
|
|
6459
6471
|
<div class="status-card">
|
|
6460
6472
|
<div class="status-row">
|
|
6461
6473
|
<span class="status-label">Method</span>
|
|
@@ -6467,7 +6479,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6467
6479
|
</div>
|
|
6468
6480
|
<div class="status-row">
|
|
6469
6481
|
<span class="status-label">URL</span>
|
|
6470
|
-
<span class="status-value">${
|
|
6482
|
+
<span class="status-value">${i}</span>
|
|
6471
6483
|
</div>
|
|
6472
6484
|
<div class="status-row">
|
|
6473
6485
|
<span class="status-label">Restarts</span>
|
|
@@ -6490,27 +6502,27 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6490
6502
|
<div class="log-area">${t.length>0?t.map(e=>this._escapeHtml(e)).join(`
|
|
6491
6503
|
`):'<span class="log-empty">No log output yet</span>'}</div>
|
|
6492
6504
|
</div>
|
|
6493
|
-
`}_renderActions(t){let e=t.status==="running"||t.status==="crashed"||t.status==="stopped",
|
|
6505
|
+
`}_renderActions(t){let e=t.status==="running"||t.status==="crashed"||t.status==="stopped",i=t.status==="running"||t.status==="starting";return`
|
|
6494
6506
|
<div class="actions">
|
|
6495
6507
|
<button class="btn" data-action="restart" ${e?"":"disabled"}>Restart</button>
|
|
6496
|
-
<button class="btn btn-danger" data-action="stop" ${
|
|
6508
|
+
<button class="btn btn-danger" data-action="stop" ${i?"":"disabled"}>Stop</button>
|
|
6497
6509
|
</div>
|
|
6498
6510
|
`}_renderEmpty(){return`
|
|
6499
6511
|
<div class="empty-state">
|
|
6500
6512
|
<p>App runner not started</p>
|
|
6501
6513
|
<p class="hint">App runner will start after the first successful build iteration.</p>
|
|
6502
6514
|
</div>
|
|
6503
|
-
`}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.querySelector('[data-action="restart"]'),
|
|
6515
|
+
`}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.querySelector('[data-action="restart"]'),i=t.querySelector('[data-action="stop"]');e&&e.addEventListener("click",()=>this._handleRestart()),i&&i.addEventListener("click",()=>this._handleStop())}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-app-status",Q);var be={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"}},X=class extends h{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={...be}}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadPricing(),this._loadCost(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadCost()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadPricing(){try{let t=await this._api.getPricing();if(t&&t.models){let e={};for(let[i,a]of Object.entries(t.models))e[i]={input:a.input,output:a.output,label:a.label||i,provider:a.provider||"unknown"};this._modelPricing=e,this._pricingSource=t.source||"api",this._pricingDate=t.updated||"",this._activeProvider=t.provider||"claude",this.render()}}catch{}}async _loadCost(){try{let t=await this._api.getCost();this._updateFromCost(t)}catch{this._data.connected=!1,this.render()}}_updateFromCost(t){t&&(this._data={...this._data,connected:!0,total_input_tokens:t.total_input_tokens||0,total_output_tokens:t.total_output_tokens||0,estimated_cost_usd:t.estimated_cost_usd||0,by_phase:t.by_phase||{},by_model:t.by_model||{},budget_limit:t.budget_limit,budget_used:t.budget_used||0,budget_remaining:t.budget_remaining},this.render())}_startPolling(){this._pollInterval=setInterval(async()=>{try{let t=await this._api.getCost();this._updateFromCost(t)}catch{this._data.connected=!1,this.render()}},5e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadCost(),this._pollInterval=setInterval(async()=>{try{let t=await this._api.getCost();this._updateFromCost(t)}catch{this._data.connected=!1,this.render()}},5e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}_formatTokens(t){return!t||t===0?"0":t>=1e6?(t/1e6).toFixed(2)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":String(t)}_formatUSD(t){return!t||t===0?"$0.00":t<.01?"<$0.01":"$"+t.toFixed(2)}_getBudgetPercent(){return!this._data.budget_limit||this._data.budget_limit<=0?0:Math.min(100,this._data.budget_used/this._data.budget_limit*100)}_getBudgetStatusClass(){let t=this._getBudgetPercent();return t>=90?"critical":t>=70?"warning":"ok"}_renderPhaseRows(){let t=this._data.by_phase;return!t||Object.keys(t).length===0?'<tr><td colspan="4" class="empty-cell">No phase data yet</td></tr>':Object.entries(t).map(([e,i])=>{let a=i.input_tokens||0,s=i.output_tokens||0,r=i.cost_usd||0;return`
|
|
6504
6516
|
<tr>
|
|
6505
6517
|
<td class="phase-name">${this._escapeHTML(e)}</td>
|
|
6506
|
-
<td class="mono-cell">${this._formatTokens(
|
|
6518
|
+
<td class="mono-cell">${this._formatTokens(a)}</td>
|
|
6507
6519
|
<td class="mono-cell">${this._formatTokens(s)}</td>
|
|
6508
6520
|
<td class="mono-cell cost-cell">${this._formatUSD(r)}</td>
|
|
6509
6521
|
</tr>
|
|
6510
|
-
`}).join("")}_renderModelRows(){let t=this._data.by_model;return!t||Object.keys(t).length===0?'<tr><td colspan="4" class="empty-cell">No model data yet</td></tr>':Object.entries(t).map(([e,
|
|
6522
|
+
`}).join("")}_renderModelRows(){let t=this._data.by_model;return!t||Object.keys(t).length===0?'<tr><td colspan="4" class="empty-cell">No model data yet</td></tr>':Object.entries(t).map(([e,i])=>{let a=i.input_tokens||0,s=i.output_tokens||0,r=i.cost_usd||0;return`
|
|
6511
6523
|
<tr>
|
|
6512
6524
|
<td class="model-name">${this._escapeHTML(e)}</td>
|
|
6513
|
-
<td class="mono-cell">${this._formatTokens(
|
|
6525
|
+
<td class="mono-cell">${this._formatTokens(a)}</td>
|
|
6514
6526
|
<td class="mono-cell">${this._formatTokens(s)}</td>
|
|
6515
6527
|
<td class="mono-cell cost-cell">${this._formatUSD(r)}</td>
|
|
6516
6528
|
</tr>
|
|
@@ -6524,7 +6536,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6524
6536
|
</div>
|
|
6525
6537
|
<div class="budget-not-set">No budget configured</div>
|
|
6526
6538
|
</div>
|
|
6527
|
-
`;let t=this._getBudgetPercent(),e=this._getBudgetStatusClass(),
|
|
6539
|
+
`;let t=this._getBudgetPercent(),e=this._getBudgetStatusClass(),i=this._data.budget_remaining!=null?this._formatUSD(this._data.budget_remaining):this._formatUSD(this._data.budget_limit-this._data.budget_used);return`
|
|
6528
6540
|
<div class="budget-section">
|
|
6529
6541
|
<div class="section-header">
|
|
6530
6542
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
@@ -6537,11 +6549,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6537
6549
|
</div>
|
|
6538
6550
|
<div class="budget-details">
|
|
6539
6551
|
<span class="budget-used">${this._formatUSD(this._data.budget_used)} used</span>
|
|
6540
|
-
<span class="budget-remaining">${
|
|
6552
|
+
<span class="budget-remaining">${i} remaining</span>
|
|
6541
6553
|
<span class="budget-limit">of ${this._formatUSD(this._data.budget_limit)}</span>
|
|
6542
6554
|
</div>
|
|
6543
6555
|
</div>
|
|
6544
|
-
`}_getRARVTier(t){if(t==null)return null;switch(t%4){case 0:return"opus";case 1:return"sonnet";case 2:return"sonnet";case 3:return"haiku";default:return"sonnet"}}_getPricingColorClass(t,e){if(e.tier==="planning")return"opus";if(e.tier==="development")return"sonnet";if(e.tier==="fast")return"haiku";if(e.iteration!=null)return this._getRARVTier(e.iteration)||"";let
|
|
6556
|
+
`}_getRARVTier(t){if(t==null)return null;switch(t%4){case 0:return"opus";case 1:return"sonnet";case 2:return"sonnet";case 3:return"haiku";default:return"sonnet"}}_getPricingColorClass(t,e){if(e.tier==="planning")return"opus";if(e.tier==="development")return"sonnet";if(e.tier==="fast")return"haiku";if(e.iteration!=null)return this._getRARVTier(e.iteration)||"";let i=(t||"").toLowerCase();return i.includes("opus")?"opus":i.includes("sonnet")?"sonnet":i.includes("haiku")?"haiku":e.provider==="codex"||i.includes("gpt")||i.includes("codex")?"codex":""}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let t=this._data.total_input_tokens+this._data.total_output_tokens;this.shadowRoot.innerHTML=`
|
|
6545
6557
|
<style>
|
|
6546
6558
|
${this.getBaseStyles()}
|
|
6547
6559
|
|
|
@@ -6894,15 +6906,15 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6894
6906
|
${this._pricingDate?`<span class="pricing-meta">Updated: ${this._escapeHTML(this._pricingDate)}</span>`:""}
|
|
6895
6907
|
</div>
|
|
6896
6908
|
<div class="pricing-grid">
|
|
6897
|
-
${Object.entries(this._modelPricing).map(([e,
|
|
6909
|
+
${Object.entries(this._modelPricing).map(([e,i])=>`
|
|
6898
6910
|
<div class="pricing-item">
|
|
6899
|
-
<div class="pricing-model ${this._getPricingColorClass(e,
|
|
6900
|
-
<div class="pricing-rates">In: $${Number(
|
|
6911
|
+
<div class="pricing-model ${this._getPricingColorClass(e,i)}">${i.label||e}</div>
|
|
6912
|
+
<div class="pricing-rates">In: $${Number(i.input??0).toFixed(2)} / Out: $${Number(i.output??0).toFixed(2)}</div>
|
|
6901
6913
|
</div>`).join("")}
|
|
6902
6914
|
</div>
|
|
6903
6915
|
</div>
|
|
6904
6916
|
</div>
|
|
6905
|
-
`}};customElements.get("loki-cost-dashboard")||customElements.define("loki-cost-dashboard",X);var Z=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._checkpoints=[],this._pollInterval=null,this._lastDataHash=null,this._showCreateForm=!1,this._creating=!1,this._rollingBack=!1,this._rollbackTarget=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,
|
|
6917
|
+
`}};customElements.get("loki-cost-dashboard")||customElements.define("loki-cost-dashboard",X);var Z=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{let[e]=await Promise.allSettled([this._api._get("/api/checkpoints?limit=50")]);e.status==="fulfilled"&&(this._checkpoints=Array.isArray(e.value)?e.value:e.value?.checkpoints||[]),this._error=null}catch(e){this._error=e.message}let t=JSON.stringify({c:this._checkpoints,e:this._error});t!==this._lastDataHash&&(this._lastDataHash=t,this.render())}async _createCheckpoint(){let t=this.shadowRoot.getElementById("checkpoint-message"),e=t?t.value.trim():"";if(e){this._creating=!0,this.render();try{await this._api._post("/api/checkpoints",{message:e}),this._showCreateForm=!1,this._creating=!1,this.dispatchEvent(new CustomEvent("checkpoint-action",{detail:{action:"create",message:e},bubbles:!0})),this._lastDataHash=null,await this._loadData()}catch(i){this._creating=!1,this._error=`Failed to create checkpoint: ${i.message}`,this.render()}}}async _rollbackCheckpoint(t){if(!this._rollingBack){this._rollingBack=!0,this._notice=null,this.render();try{let e=await this._api._post(`/api/checkpoints/${t}/rollback`);this._rollbackTarget=null;let i=e&&e.pre_rollback_snapshot;this._notice=i?`Rolled back to ${t}. Undo this with checkpoint ${i}`:`Rolled back to ${t}.`,this.dispatchEvent(new CustomEvent("checkpoint-action",{detail:{action:"rollback",checkpointId:t,preRollbackSnapshot:i||null},bubbles:!0})),this._lastDataHash=null,await this._loadData()}catch(e){this._rollbackTarget=null,this._error=`Failed to rollback: ${e.message}`}finally{this._rollingBack=!1,this.render()}}}_toggleCreateForm(){this._showCreateForm=!this._showCreateForm,this._rollbackTarget=null,this._notice=null,this.render()}_confirmRollback(t){this._rollbackTarget=t,this.render()}_cancelRollback(){this._rollbackTarget=null,this._notice=null,this.render()}_formatRelativeTime(t){if(!t)return"";try{let e=Date.now(),i=new Date(t).getTime(),a=Math.floor((e-i)/1e3);return a<60?`${a}s ago`:a<3600?`${Math.floor(a/60)}m ago`:a<86400?`${Math.floor(a/3600)}h ago`:`${Math.floor(a/86400)}d ago`}catch{return this._escapeHTML(t)}}render(){let t=this.shadowRoot;if(!t)return;let e=this._checkpoints.length;t.innerHTML=`
|
|
6906
6918
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
6907
6919
|
<div class="checkpoint-viewer">
|
|
6908
6920
|
<div class="checkpoint-header">
|
|
@@ -6920,9 +6932,10 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6920
6932
|
<div class="checkpoint-list">
|
|
6921
6933
|
${this._loading?'<div class="loading-state">Loading checkpoints...</div>':""}
|
|
6922
6934
|
${!this._loading&&e===0?'<div class="empty-state">No checkpoints yet. Create one to save the current state.</div>':""}
|
|
6923
|
-
${this._checkpoints.map(
|
|
6935
|
+
${this._checkpoints.map(i=>this._renderCheckpointCard(i)).join("")}
|
|
6924
6936
|
</div>
|
|
6925
6937
|
|
|
6938
|
+
${this._notice?`<div class="notice-banner">${this._escapeHTML(this._notice)}</div>`:""}
|
|
6926
6939
|
${this._error?`<div class="error-banner">${this._escapeHTML(this._error)}</div>`:""}
|
|
6927
6940
|
</div>
|
|
6928
6941
|
`,this._attachEventListeners()}_renderCreateForm(){return`
|
|
@@ -6939,7 +6952,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6939
6952
|
${this._creating?"Creating...":"Save"}
|
|
6940
6953
|
</button>
|
|
6941
6954
|
</div>
|
|
6942
|
-
`}_renderCheckpointCard(t){let e=t.git_sha?t.git_sha.substring(0,7):"",
|
|
6955
|
+
`}_renderCheckpointCard(t){let e=t.git_sha?t.git_sha.substring(0,7):"",i=t.files_count||(Array.isArray(t.files)?t.files.length:0),a=this._rollbackTarget===t.id,s=t.iteration!=null?`Iter ${t.iteration}`:"",r=t.provider||"",o=t.phase||"",n=t.git_branch||"",l=[s,r,o].filter(Boolean);return`
|
|
6943
6956
|
<div class="checkpoint-card" data-checkpoint-id="${this._escapeHTML(t.id)}">
|
|
6944
6957
|
<div class="card-header">
|
|
6945
6958
|
<div class="header-tags">
|
|
@@ -6951,13 +6964,13 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6951
6964
|
<div class="card-body">
|
|
6952
6965
|
<p class="checkpoint-message">${this._escapeHTML(t.message||"Checkpoint")}</p>
|
|
6953
6966
|
<div class="card-meta">
|
|
6954
|
-
${
|
|
6967
|
+
${i>0?`<span class="meta-item">${i} file${i!==1?"s":""}</span>`:""}
|
|
6955
6968
|
${n?`<span class="meta-item mono">${this._escapeHTML(n)}</span>`:""}
|
|
6956
6969
|
<span class="meta-item mono">${this._escapeHTML(t.id)}</span>
|
|
6957
6970
|
</div>
|
|
6958
6971
|
</div>
|
|
6959
6972
|
<div class="card-actions">
|
|
6960
|
-
${
|
|
6973
|
+
${a?`
|
|
6961
6974
|
<span class="rollback-confirm-text">Rollback to this checkpoint?</span>
|
|
6962
6975
|
<button class="btn btn-sm btn-danger" data-action="confirm-rollback" data-id="${this._escapeHTML(t.id)}">Confirm</button>
|
|
6963
6976
|
<button class="btn btn-sm" data-action="cancel-rollback">Cancel</button>
|
|
@@ -6966,7 +6979,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
6966
6979
|
`}
|
|
6967
6980
|
</div>
|
|
6968
6981
|
</div>
|
|
6969
|
-
`}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("create-btn");e&&e.addEventListener("click",()=>this._toggleCreateForm());let
|
|
6982
|
+
`}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("create-btn");e&&e.addEventListener("click",()=>this._toggleCreateForm());let i=t.getElementById("submit-create-btn");i&&i.addEventListener("click",()=>this._createCheckpoint());let a=t.getElementById("checkpoint-message");a&&(a.addEventListener("keydown",s=>{s.key==="Enter"&&!this._creating&&(s.preventDefault(),this._createCheckpoint())}),requestAnimationFrame(()=>a.focus())),t.querySelectorAll("[data-action]").forEach(s=>{s.addEventListener("click",r=>{r.stopPropagation();let o=s.dataset.action,n=s.dataset.id;o==="rollback"?this._confirmRollback(n):o==="confirm-rollback"?this._rollbackCheckpoint(n):o==="cancel-rollback"&&this._cancelRollback()})})}_getStyles(){return`
|
|
6970
6983
|
:host {
|
|
6971
6984
|
display: block;
|
|
6972
6985
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
@@ -7210,10 +7223,20 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7210
7223
|
color: var(--loki-red);
|
|
7211
7224
|
font-size: 12px;
|
|
7212
7225
|
}
|
|
7213
|
-
|
|
7226
|
+
|
|
7227
|
+
.notice-banner {
|
|
7228
|
+
margin-top: 12px;
|
|
7229
|
+
padding: 10px 14px;
|
|
7230
|
+
background: var(--loki-green-muted, rgba(34, 197, 94, 0.12));
|
|
7231
|
+
border: 1px solid var(--loki-green-muted, rgba(34, 197, 94, 0.3));
|
|
7232
|
+
border-radius: 4px;
|
|
7233
|
+
color: var(--loki-green, #22c55e);
|
|
7234
|
+
font-size: 12px;
|
|
7235
|
+
}
|
|
7236
|
+
`}};customElements.get("loki-checkpoint-viewer")||customElements.define("loki-checkpoint-viewer",Z);var tt=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._connected=!1,this._activeTab="gauge",this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadContext(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadContext()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadContext(){try{let t=this.getAttribute("api-url")||window.location.origin,e=await fetch(t+"/api/context");e.ok&&(this._data=await e.json(),this._connected=!0)}catch{this._connected=!1}this.render()}_startPolling(){this._pollInterval=setInterval(()=>{this._loadContext()},5e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadContext(),this._pollInterval=setInterval(()=>this._loadContext(),5e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}_setTab(t){this._activeTab=t,this.render()}_formatTokens(t){return!t||t===0?"0":t>=1e6?(t/1e6).toFixed(2)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":String(t)}_formatUSD(t){return!t||t===0?"$0.00":t<.01?"<$0.01":"$"+t.toFixed(2)}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGaugeColor(t){return t>80?"var(--loki-red)":t>=60?"var(--loki-yellow)":"var(--loki-green)"}_getGaugeColorClass(t){return t>80?"gauge-red":t>=60?"gauge-yellow":"gauge-green"}_renderGaugeTab(){let t=this._data?.current||{},e=this._data?.totals||{},i=t.context_window_pct||0,a=this._getGaugeColor(i),s=this._getGaugeColorClass(i),r=70,o=2*Math.PI*r,n=o-i/100*o;return`
|
|
7214
7237
|
<div class="gauge-tab">
|
|
7215
7238
|
<div class="gauge-container">
|
|
7216
|
-
<svg class="gauge-svg" viewBox="0 0 180 180" aria-label="Context window usage: ${
|
|
7239
|
+
<svg class="gauge-svg" viewBox="0 0 180 180" aria-label="Context window usage: ${i.toFixed(1)}%">
|
|
7217
7240
|
<circle
|
|
7218
7241
|
class="gauge-bg"
|
|
7219
7242
|
cx="90" cy="90" r="${r}"
|
|
@@ -7225,7 +7248,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7225
7248
|
class="gauge-ring ${s}"
|
|
7226
7249
|
cx="90" cy="90" r="${r}"
|
|
7227
7250
|
fill="none"
|
|
7228
|
-
stroke="${
|
|
7251
|
+
stroke="${a}"
|
|
7229
7252
|
stroke-width="12"
|
|
7230
7253
|
stroke-linecap="round"
|
|
7231
7254
|
stroke-dasharray="${o}"
|
|
@@ -7235,7 +7258,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7235
7258
|
<text class="gauge-pct" x="90" y="85" text-anchor="middle"
|
|
7236
7259
|
fill="var(--loki-text-primary)" font-size="28" font-weight="600"
|
|
7237
7260
|
font-family="'JetBrains Mono', monospace">
|
|
7238
|
-
${
|
|
7261
|
+
${i.toFixed(1)}%
|
|
7239
7262
|
</text>
|
|
7240
7263
|
<text class="gauge-label" x="90" y="108" text-anchor="middle"
|
|
7241
7264
|
fill="var(--loki-text-muted)" font-size="11">
|
|
@@ -7285,7 +7308,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7285
7308
|
</div>
|
|
7286
7309
|
</div>
|
|
7287
7310
|
</div>
|
|
7288
|
-
`}_renderTimelineTab(){let t=this._data?.per_iteration||[],e=this._data?.compactions||[];if(t.length===0)return'<div class="empty-state">No iteration data yet</div>';let
|
|
7311
|
+
`}_renderTimelineTab(){let t=this._data?.per_iteration||[],e=this._data?.compactions||[];if(t.length===0)return'<div class="empty-state">No iteration data yet</div>';let i=Math.max(...t.map(r=>(r.input_tokens||0)+(r.output_tokens||0)+(r.cache_read_tokens||0)+(r.cache_creation_tokens||0))),a=new Set(e.map(r=>r.at_iteration)),s="";for(let r of t){let o=(r.input_tokens||0)+(r.output_tokens||0)+(r.cache_read_tokens||0)+(r.cache_creation_tokens||0),n=i>0?o/i*100:0,l=r.compacted===!0;a.has(r.iteration)&&(s+=`
|
|
7289
7312
|
<div class="timeline-compaction-row">
|
|
7290
7313
|
<div class="compaction-line"></div>
|
|
7291
7314
|
<span class="compaction-label">Context Compacted</span>
|
|
@@ -7316,21 +7339,21 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7316
7339
|
</div>
|
|
7317
7340
|
${s}
|
|
7318
7341
|
</div>
|
|
7319
|
-
`}_renderBreakdownTab(){let t=this._data?.per_iteration||[];if(t.length===0)return'<div class="empty-state">No iteration data yet</div>';let e=Math.max(...t.map(s=>(s.input_tokens||0)+(s.output_tokens||0)+(s.cache_read_tokens||0)+(s.cache_creation_tokens||0))),
|
|
7342
|
+
`}_renderBreakdownTab(){let t=this._data?.per_iteration||[];if(t.length===0)return'<div class="empty-state">No iteration data yet</div>';let e=Math.max(...t.map(s=>(s.input_tokens||0)+(s.output_tokens||0)+(s.cache_read_tokens||0)+(s.cache_creation_tokens||0))),i=`
|
|
7320
7343
|
<div class="breakdown-legend">
|
|
7321
7344
|
<div class="legend-item"><span class="legend-swatch swatch-input"></span> Input</div>
|
|
7322
7345
|
<div class="legend-item"><span class="legend-swatch swatch-output"></span> Output</div>
|
|
7323
7346
|
<div class="legend-item"><span class="legend-swatch swatch-cache-read"></span> Cache Read</div>
|
|
7324
7347
|
<div class="legend-item"><span class="legend-swatch swatch-cache-create"></span> Cache Creation</div>
|
|
7325
7348
|
</div>
|
|
7326
|
-
`,
|
|
7349
|
+
`,a="";for(let s of t){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=e>0?r/e*100:0,u=e>0?o/e*100:0,b=e>0?n/e*100:0,v=e>0?l/e*100:0;a+=`
|
|
7327
7350
|
<div class="breakdown-row">
|
|
7328
7351
|
<div class="breakdown-iter">#${s.iteration}</div>
|
|
7329
7352
|
<div class="breakdown-bar-container">
|
|
7330
7353
|
<div class="breakdown-bar bar-input" style="width: ${p.toFixed(1)}%"></div>
|
|
7331
7354
|
<div class="breakdown-bar bar-output" style="width: ${u.toFixed(1)}%"></div>
|
|
7332
7355
|
<div class="breakdown-bar bar-cache-read" style="width: ${b.toFixed(1)}%"></div>
|
|
7333
|
-
<div class="breakdown-bar bar-cache-create" style="width: ${
|
|
7356
|
+
<div class="breakdown-bar bar-cache-create" style="width: ${v.toFixed(1)}%"></div>
|
|
7334
7357
|
</div>
|
|
7335
7358
|
<div class="breakdown-cost">${this._formatUSD(s.cost_usd)}</div>
|
|
7336
7359
|
</div>
|
|
@@ -7344,8 +7367,8 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7344
7367
|
</svg>
|
|
7345
7368
|
<span class="section-title">Token Type Breakdown</span>
|
|
7346
7369
|
</div>
|
|
7347
|
-
${a}
|
|
7348
7370
|
${i}
|
|
7371
|
+
${a}
|
|
7349
7372
|
</div>
|
|
7350
7373
|
`}render(){let t=this._activeTab==="gauge"?this._renderGaugeTab():this._activeTab==="timeline"?this._renderTimelineTab():this._renderBreakdownTab();this.shadowRoot.innerHTML=`
|
|
7351
7374
|
<style>
|
|
@@ -7733,7 +7756,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7733
7756
|
|
|
7734
7757
|
${t}
|
|
7735
7758
|
</div>
|
|
7736
|
-
`,this.shadowRoot.querySelectorAll(".tab").forEach(e=>{e.addEventListener("click",()=>{this._setTab(e.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",tt);var
|
|
7759
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(e=>{e.addEventListener("click",()=>{this._setTab(e.dataset.tab)})})}};customElements.get("loki-context-tracker")||customElements.define("loki-context-tracker",tt);var Dt={critical:"var(--loki-red, #ef4444)",warning:"var(--loki-yellow, #eab308)",info:"var(--loki-blue, #3b82f6)",success:"var(--loki-green, #1FC5A8)"},Gt={build:{label:"Build",icon:"B"},quality:{label:"Quality",icon:"Q"},system:{label:"System",icon:"S"},security:{label:"Security",icon:"!"}},et=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&(this._loadNotifications(),this._loadTriggers()),t==="theme"&&this._applyTheme())}async _loadNotifications(){try{let t=this.getAttribute("api-url")||window.location.origin,e=await fetch(t+"/api/notifications");if(e.ok){let i=await e.json();this._notifications=i.notifications||[],this._summary=i.summary||{},this._connected=!0}}catch{this._connected=!1}this.render()}async _loadTriggers(){try{let t=this.getAttribute("api-url")||window.location.origin,e=await fetch(t+"/api/notifications/triggers");if(e.ok){let i=await e.json();this._triggers=i.triggers||[]}}catch{}}async _acknowledgeNotification(t){let e=this.getAttribute("api-url")||window.location.origin;await fetch(e+"/api/notifications/"+encodeURIComponent(t)+"/acknowledge",{method:"POST"}),this._loadNotifications()}async _unacknowledgeNotification(t){let e=this.getAttribute("api-url")||window.location.origin;await fetch(e+"/api/notifications/"+encodeURIComponent(t)+"/unacknowledge",{method:"POST"}),this._loadNotifications()}async _acknowledgeAll(){let t=this.getAttribute("api-url")||window.location.origin,e=this._notifications.filter(i=>!i.acknowledged);for(let i of e)await fetch(t+"/api/notifications/"+encodeURIComponent(i.id)+"/acknowledge",{method:"POST"});this._loadNotifications()}async _toggleTrigger(t,e){let i=this.getAttribute("api-url")||window.location.origin,a=this._triggers.map(s=>s.id===t?{...s,enabled:e}:s);await fetch(i+"/api/notifications/triggers",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({triggers:a})}),this._triggers=a,this.render()}_startPolling(){this._pollInterval=setInterval(()=>{this._loadNotifications(),this._loadTriggers()},5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_formatTime(t){if(!t)return"";try{let e=new Date(t),a=new Date-e,s=Math.floor(a/1e3),r=Math.floor(s/60),o=Math.floor(r/60),n=Math.floor(o/24);return s<60?s+"s ago":r<60?r+"m ago":o<24?o+"h ago":n<7?n+"d ago":e.toLocaleDateString()}catch{return String(t)}}_getTimeGroup(t){if(!t)return"Other";try{let e=new Date(t),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),e>=a?"Today":e>=s?"Yesterday":e>=r?"This Week":"Earlier"}catch{return"Other"}}_escapeHTML(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getSeverityColor(t){return Dt[t]||Dt.info}_getCategory(t){return t.category||t.type||"system"}_switchTab(t){this._activeTab=t,this.render()}_setCategoryFilter(t){this._categoryFilter=t,this.render()}_togglePanel(){this._panelOpen=!this._panelOpen,this.render()}_bindEvents(){let t=this.shadowRoot;t.querySelectorAll(".tab").forEach(a=>{a.addEventListener("click",()=>{this._switchTab(a.dataset.tab)})}),t.querySelectorAll(".cat-btn").forEach(a=>{a.addEventListener("click",()=>{this._setCategoryFilter(a.dataset.cat)})}),t.querySelectorAll(".ack-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._acknowledgeNotification(a.dataset.id)})}),t.querySelectorAll(".unread-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._unacknowledgeNotification(a.dataset.id)})});let e=t.querySelector(".ack-all-btn");e&&e.addEventListener("click",()=>{this._acknowledgeAll()});let i=t.querySelector(".bell-icon");i&&i.addEventListener("click",()=>{this._togglePanel()}),t.querySelectorAll(".toggle input").forEach(a=>{a.addEventListener("change",()=>{this._toggleTrigger(a.dataset.triggerId,a.checked)})}),t.querySelectorAll(".dismiss-btn").forEach(a=>{a.addEventListener("click",s=>{s.stopPropagation(),this._acknowledgeNotification(a.dataset.id)})})}_renderBellIcon(){let t=this._summary.unacknowledged||0;return`
|
|
7737
7760
|
<div class="bell-container">
|
|
7738
7761
|
<button class="bell-icon" title="${t} unread notifications">
|
|
7739
7762
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -7743,7 +7766,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7743
7766
|
${t>0?`<span class="badge">${t>99?"99+":t}</span>`:""}
|
|
7744
7767
|
</button>
|
|
7745
7768
|
</div>
|
|
7746
|
-
`}_renderSummaryBar(){let t=this._summary.total||0,e=this._summary.unacknowledged||0,
|
|
7769
|
+
`}_renderSummaryBar(){let t=this._summary.total||0,e=this._summary.unacknowledged||0,i=this._summary.critical||0;return`
|
|
7747
7770
|
<div class="summary-row">
|
|
7748
7771
|
<div class="summary-grid">
|
|
7749
7772
|
<div class="summary-card">
|
|
@@ -7756,7 +7779,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7756
7779
|
</div>
|
|
7757
7780
|
<div class="summary-card">
|
|
7758
7781
|
<div class="card-label">Critical</div>
|
|
7759
|
-
<div class="card-value" style="color: ${
|
|
7782
|
+
<div class="card-value" style="color: ${Dt.critical}">${i}</div>
|
|
7760
7783
|
</div>
|
|
7761
7784
|
</div>
|
|
7762
7785
|
${e>0?`
|
|
@@ -7765,9 +7788,9 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7765
7788
|
</div>
|
|
7766
7789
|
`}_renderCategoryFilter(){return`
|
|
7767
7790
|
<div class="category-bar">
|
|
7768
|
-
${["all","build","quality","system","security"].map(e=>{let
|
|
7791
|
+
${["all","build","quality","system","security"].map(e=>{let i=this._categoryFilter===e,a=e==="all"?"All":Gt[e]?.label||e;return`<button class="cat-btn ${i?"active":""}" data-cat="${e}">${a}</button>`}).join("")}
|
|
7769
7792
|
</div>
|
|
7770
|
-
`}_renderNotificationList(){let t=[...this._notifications].sort((s,r)=>new Date(r.timestamp)-new Date(s.timestamp));if(this._categoryFilter!=="all"&&(t=t.filter(s=>this._getCategory(s)===this._categoryFilter)),t.length===0)return'<div class="empty-state">No notifications</div>';let e={};for(let s of t){let r=this._getTimeGroup(s.timestamp);e[r]||(e[r]=[]),e[r].push(s)}let
|
|
7793
|
+
`}_renderNotificationList(){let t=[...this._notifications].sort((s,r)=>new Date(r.timestamp)-new Date(s.timestamp));if(this._categoryFilter!=="all"&&(t=t.filter(s=>this._getCategory(s)===this._categoryFilter)),t.length===0)return'<div class="empty-state">No notifications</div>';let e={};for(let s of t){let r=this._getTimeGroup(s.timestamp);e[r]||(e[r]=[]),e[r].push(s)}let i=["Today","Yesterday","This Week","Earlier","Other"],a="";for(let s of i)!e[s]||e[s].length===0||(a+=`<div class="time-group-label">${s}</div>`,a+=e[s].map(r=>{let o=r.acknowledged,n=this._getSeverityColor(r.severity),l=this._getCategory(r),c=Gt[l]||{label:l,icon:"?"};return`
|
|
7771
7794
|
<div class="notif-row ${o?"acknowledged":""}">
|
|
7772
7795
|
<span class="severity-dot" style="background: ${n};" title="${this._escapeHTML(r.severity)}"></span>
|
|
7773
7796
|
<span class="cat-icon" title="${c.label}">${c.icon}</span>
|
|
@@ -7779,7 +7802,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7779
7802
|
<button class="dismiss-btn" data-id="${this._escapeHTML(r.id)}" title="Dismiss">✕</button>
|
|
7780
7803
|
</span>
|
|
7781
7804
|
</div>
|
|
7782
|
-
`}).join(""));return
|
|
7805
|
+
`}).join(""));return a}_renderTriggerList(){return this._triggers.length===0?'<div class="empty-state">No triggers configured</div>':this._triggers.map(t=>{let e=this._getSeverityColor(t.severity),i=t.threshold_pct!=null?`Threshold: ${t.threshold_pct}%`:t.pattern||"";return`
|
|
7783
7806
|
<div class="trigger-row">
|
|
7784
7807
|
<label class="toggle">
|
|
7785
7808
|
<input type="checkbox" data-trigger-id="${this._escapeHTML(t.id)}" ${t.enabled?"checked":""}>
|
|
@@ -7788,7 +7811,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
7788
7811
|
<span class="trigger-name">${this._escapeHTML(t.id)}</span>
|
|
7789
7812
|
<span class="trigger-badge type-badge">${this._escapeHTML(t.type||"custom")}</span>
|
|
7790
7813
|
<span class="trigger-badge severity-badge" style="background: ${e}; color: #fff;">${this._escapeHTML(t.severity||"info")}</span>
|
|
7791
|
-
${
|
|
7814
|
+
${i?`<span class="trigger-info">${this._escapeHTML(i)}</span>`:""}
|
|
7792
7815
|
</div>
|
|
7793
7816
|
`}).join("")}render(){this.shadowRoot.innerHTML=`
|
|
7794
7817
|
<style>
|
|
@@ -8250,7 +8273,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
8250
8273
|
`:""}
|
|
8251
8274
|
`:""}
|
|
8252
8275
|
</div>
|
|
8253
|
-
`,this._bindEvents()}};customElements.get("loki-notification-center")||customElements.define("loki-notification-center",et);var
|
|
8276
|
+
`,this._bindEvents()}};customElements.get("loki-notification-center")||customElements.define("loki-notification-center",et);var it=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._error=null,this._loading=!0,this._api=null,this._pollInterval=null,this._expandedDecisions=new Set}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadData(){try{this._data=await this._api._get("/api/session-diff"),this._error=null}catch(t){this._error=t.message,this._data=null}this._loading=!1,this.render()}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleDecision(t){this._expandedDecisions.has(t)?this._expandedDecisions.delete(t):this._expandedDecisions.add(t),this.render()}render(){let t=`
|
|
8254
8277
|
${this.getBaseStyles()}
|
|
8255
8278
|
|
|
8256
8279
|
:host {
|
|
@@ -8461,7 +8484,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
8461
8484
|
</div>
|
|
8462
8485
|
<div class="empty-state">No session diff available</div>
|
|
8463
8486
|
</div>
|
|
8464
|
-
`;return}let e=this._data||{},
|
|
8487
|
+
`;return}let e=this._data||{},i=this._escapeHtml(e.period||"--"),a=e.counts||{},s=e.highlights||[],r=e.decisions||[],o="";s.length>0&&(o=`
|
|
8465
8488
|
<div class="highlights-section">
|
|
8466
8489
|
<div class="section-label">Highlights</div>
|
|
8467
8490
|
<ul class="highlight-list">
|
|
@@ -8487,32 +8510,32 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
8487
8510
|
<div class="diff-header">
|
|
8488
8511
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
|
|
8489
8512
|
<span class="diff-title">Session Resume</span>
|
|
8490
|
-
<span class="diff-period">${
|
|
8513
|
+
<span class="diff-period">${i}</span>
|
|
8491
8514
|
</div>
|
|
8492
8515
|
|
|
8493
8516
|
<div class="summary-grid">
|
|
8494
8517
|
<div class="summary-item">
|
|
8495
8518
|
<div class="summary-label">Created</div>
|
|
8496
|
-
<div class="summary-value">${
|
|
8519
|
+
<div class="summary-value">${a.tasks_created!=null?a.tasks_created:"--"}</div>
|
|
8497
8520
|
</div>
|
|
8498
8521
|
<div class="summary-item">
|
|
8499
8522
|
<div class="summary-label">Completed</div>
|
|
8500
|
-
<div class="summary-value">${
|
|
8523
|
+
<div class="summary-value">${a.tasks_completed!=null?a.tasks_completed:"--"}</div>
|
|
8501
8524
|
</div>
|
|
8502
8525
|
<div class="summary-item">
|
|
8503
8526
|
<div class="summary-label">Blocked</div>
|
|
8504
|
-
<div class="summary-value">${
|
|
8527
|
+
<div class="summary-value">${a.tasks_blocked!=null?a.tasks_blocked:"--"}</div>
|
|
8505
8528
|
</div>
|
|
8506
8529
|
<div class="summary-item">
|
|
8507
8530
|
<div class="summary-label">Errors</div>
|
|
8508
|
-
<div class="summary-value ${(
|
|
8531
|
+
<div class="summary-value ${(a.errors||0)>0?"error-count":""}">${a.errors!=null?a.errors:"--"}</div>
|
|
8509
8532
|
</div>
|
|
8510
8533
|
</div>
|
|
8511
8534
|
|
|
8512
8535
|
${o}
|
|
8513
8536
|
${n}
|
|
8514
8537
|
</div>
|
|
8515
|
-
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(l=>{l.addEventListener("click",()=>{this._toggleDecision(parseInt(l.dataset.index))})})}};customElements.get("loki-session-diff")||customElements.define("loki-session-diff",
|
|
8538
|
+
`,this.shadowRoot.querySelectorAll(".decision-header").forEach(l=>{l.addEventListener("click",()=>{this._toggleDecision(parseInt(l.dataset.index))})})}};customElements.get("loki-session-diff")||customElements.define("loki-session-diff",it);var at=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._error=null,this._loading=!0,this._optimizing=!1,this._api=null,this._pollInterval=null,this._expandedChanges=new Set}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadData(){try{this._data=await this._api._get("/api/prompt-versions"),this._error=null}catch(t){this._error=t.message,this._data=null}this._loading=!1,this.render()}async _triggerOptimize(){if(!this._optimizing){this._optimizing=!0,this.render();try{await this._api._post("/api/prompt-optimize?dry_run=false",{}),await this._loadData()}catch(t){this._error=t.message}this._optimizing=!1,this.render()}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),6e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_formatTime(t){if(!t)return"--";try{let e=new Date(t),a=new Date-e,s=Math.floor(a/6e4);if(s<1)return"Just now";if(s<60)return`${s}m ago`;let r=Math.floor(s/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}catch{return"--"}}_toggleChange(t){this._expandedChanges.has(t)?this._expandedChanges.delete(t):this._expandedChanges.add(t),this.render()}render(){let t=`
|
|
8516
8539
|
${this.getBaseStyles()}
|
|
8517
8540
|
|
|
8518
8541
|
:host {
|
|
@@ -8722,7 +8745,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
8722
8745
|
</div>
|
|
8723
8746
|
<div class="empty-state">No prompt optimization data available</div>
|
|
8724
8747
|
</div>
|
|
8725
|
-
`;return}let e=this._data||{},
|
|
8748
|
+
`;return}let e=this._data||{},i=e.version!=null?e.version:"--",a=this._formatTime(e.last_optimized),s=e.failures_analyzed!=null?e.failures_analyzed:"--",r=e.changes||[],o="";r.length>0&&(o=`
|
|
8726
8749
|
<div class="changes-section">
|
|
8727
8750
|
<div class="section-label">Changes</div>
|
|
8728
8751
|
${r.map((l,c)=>{let p=this._expandedChanges.has(c);return`
|
|
@@ -8749,11 +8772,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
8749
8772
|
<div class="info-grid">
|
|
8750
8773
|
<div class="info-item">
|
|
8751
8774
|
<div class="info-label">Version</div>
|
|
8752
|
-
<div class="info-value">v${this._escapeHtml(String(
|
|
8775
|
+
<div class="info-value">v${this._escapeHtml(String(i))}</div>
|
|
8753
8776
|
</div>
|
|
8754
8777
|
<div class="info-item">
|
|
8755
8778
|
<div class="info-label">Last Optimized</div>
|
|
8756
|
-
<div class="info-value muted">${this._escapeHtml(
|
|
8779
|
+
<div class="info-value muted">${this._escapeHtml(a)}</div>
|
|
8757
8780
|
</div>
|
|
8758
8781
|
<div class="info-item">
|
|
8759
8782
|
<div class="info-label">Failures Analyzed</div>
|
|
@@ -8763,7 +8786,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
8763
8786
|
|
|
8764
8787
|
${o}
|
|
8765
8788
|
</div>
|
|
8766
|
-
`;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",
|
|
8789
|
+
`;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",at);var st=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._data=null,this._history=[],this._error=null,this._loading=!0,this._scanning=!1,this._rigourAvailable=!0,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadData(){try{let[t,e]=await Promise.allSettled([this._api._get("/api/quality-score"),this._api._get("/api/quality-score/history")]);if(t.status==="fulfilled"){let i=t.value;i&&i.error&&i.error.includes("not installed")?(this._rigourAvailable=!1,this._data=null):(this._rigourAvailable=!0,this._data=i),this._error=null}else(t.reason?.message||"").includes("404")?(this._rigourAvailable=!1,this._data=null,this._error=null):(this._error="Failed to load quality score",this._data=null);if(e.status==="fulfilled"){let i=e.value;this._history=Array.isArray(i)?i.slice(-10):(i.scores||[]).slice(-10)}}catch(t){this._error=t.message,this._data=null}this._loading=!1,this.render()}async _triggerScan(){if(!this._scanning){this._scanning=!0,this.render();try{await this._api._post("/api/quality-scan",{}),await this._loadData()}catch(t){this._error=t.message}this._scanning=!1,this.render()}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),6e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getGrade(t){return t>=90?{grade:"A",color:"var(--loki-success)"}:t>=80?{grade:"B",color:"var(--loki-success)"}:t>=70?{grade:"C",color:"var(--loki-warning)"}:t>=60?{grade:"D",color:"var(--loki-warning)"}:{grade:"F",color:"var(--loki-error)"}}_renderSparkline(t){if(!t||t.length<2)return"";let e=t.map(c=>typeof c=="number"?c:c.score||0),i=Math.min(...e),s=Math.max(...e)-i||1,r=120,o=32,n=2,l=e.map((c,p)=>{let u=n+p/(e.length-1)*(r-n*2),b=n+(1-(c-i)/s)*(o-n*2);return`${u},${b}`}).join(" ");return`
|
|
8767
8790
|
<svg width="${r}" height="${o}" viewBox="0 0 ${r} ${o}" class="sparkline">
|
|
8768
8791
|
<polyline points="${l}" fill="none" stroke="var(--loki-accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
8769
8792
|
<circle cx="${l.split(" ").pop().split(",")[0]}" cy="${l.split(" ").pop().split(",")[1]}" r="2.5" fill="var(--loki-accent)"/>
|
|
@@ -9060,7 +9083,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9060
9083
|
</div>
|
|
9061
9084
|
<div class="empty-state">No quality data available</div>
|
|
9062
9085
|
</div>
|
|
9063
|
-
`;return}let e=this._data||{},
|
|
9086
|
+
`;return}let e=this._data||{},i=e.score!=null?Math.round(e.score):0,{grade:a,color:s}=this._getGrade(i),r=e.categories||{},o=e.findings||{},n=["security","code_quality","compliance","best_practices"],l={security:"Security",code_quality:"Code Quality",compliance:"Compliance",best_practices:"Best Practices"},c=n.map(f=>{let x=r[f]!=null?Math.round(r[f]):0,w=x>=80?"var(--loki-success)":x>=60?"var(--loki-warning)":"var(--loki-error)";return`
|
|
9064
9087
|
<div class="category-item">
|
|
9065
9088
|
<span class="category-name">${l[f]||f}</span>
|
|
9066
9089
|
<div class="progress-bar">
|
|
@@ -9081,8 +9104,8 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9081
9104
|
|
|
9082
9105
|
<div class="score-section">
|
|
9083
9106
|
<div class="score-display">
|
|
9084
|
-
<div class="score-number">${
|
|
9085
|
-
<span class="grade-badge" style="background:${s};color:#fff;">${
|
|
9107
|
+
<div class="score-number">${i}</div>
|
|
9108
|
+
<span class="grade-badge" style="background:${s};color:#fff;">${a}</span>
|
|
9086
9109
|
</div>
|
|
9087
9110
|
${b?`
|
|
9088
9111
|
<div class="sparkline-container">
|
|
@@ -9104,43 +9127,43 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9104
9127
|
</div>
|
|
9105
9128
|
`:""}
|
|
9106
9129
|
</div>
|
|
9107
|
-
`;let
|
|
9130
|
+
`;let v=this.shadowRoot.getElementById("scan-btn");v&&v.addEventListener("click",()=>this._triggerScan())}};customElements.get("loki-quality-score")||customElements.define("loki-quality-score",st);var Kt=["understand","guardrail","migrate","verify"],Vt={understand:"Understand",guardrail:"Guardrail",migrate:"Migrate",verify:"Verify"},fe={understand:"#5b9bd5",guardrail:"#e8b84a",migrate:"#5bb870",verify:"#5bc8c8"},rt=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._migration=null,this._migrations=[],this._loading=!0,this._error=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._fetchMigrations(),this._pollInterval=setInterval(()=>this._fetchData(),15e3)}disconnectedCallback(){super.disconnectedCallback(),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._fetchMigrations()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _fetchMigrations(){try{let t=await this._api._get("/api/migration/list");this._migrations=Array.isArray(t)?t:t.migrations||[],this._error=null;let e=this._migrations.find(i=>i.status==="in_progress"||i.status==="active");e?await this._fetchStatus(e.migration_id||e.id):this._migration=null}catch(t){this._error=t.message,this._migrations=[],this._migration=null}this._loading=!1,this.render()}async _fetchStatus(t){try{this._migration=await this._api._get(`/api/migration/${encodeURIComponent(t)}/status`),this._error=null}catch(e){this._error=e.message}}async _fetchData(){let t=this._migration&&(this._migration.migration_id||this._migration.id);t?(await this._fetchStatus(t),this.render()):await this._fetchMigrations()}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"):""}_getPhaseIcon(t,e,i){return(i||[]).includes(t)?"[x]":t===e?"[>]":"[ ]"}_getPhaseIndex(t){let e=Kt.indexOf(t);return e>=0?e:0}_renderPhaseBar(t,e){let i=e||[];return Kt.map(a=>{let s=i.includes(a),r=a===t,o=fe[a],n=s?"1":r?"0.7":"0.2",l=this._getPhaseIcon(a,t,e);return`
|
|
9108
9131
|
<div class="phase-segment">
|
|
9109
9132
|
<div class="phase-bar-fill" style="background:${o};opacity:${n};"></div>
|
|
9110
9133
|
<div class="phase-label">
|
|
9111
9134
|
<span class="phase-icon">${l}</span>
|
|
9112
|
-
${
|
|
9135
|
+
${Vt[a]}
|
|
9113
9136
|
</div>
|
|
9114
9137
|
</div>
|
|
9115
|
-
`}).join("")}_renderFeatureStats(t){if(!t)return"";let e=t.passing||0,
|
|
9138
|
+
`}).join("")}_renderFeatureStats(t){if(!t)return"";let e=t.passing||0,i=t.total||0,a=i>0?Math.round(e/i*100):0,s=a>=80?"var(--loki-success)":a>=50?"var(--loki-warning)":"var(--loki-error)";return`
|
|
9116
9139
|
<div class="stat-card">
|
|
9117
9140
|
<div class="stat-header">Feature Tracking</div>
|
|
9118
|
-
<div class="stat-value">${e} / ${
|
|
9119
|
-
<div class="stat-pct">${
|
|
9141
|
+
<div class="stat-value">${e} / ${i}</div>
|
|
9142
|
+
<div class="stat-pct">${a}% passing</div>
|
|
9120
9143
|
<div class="progress-bar">
|
|
9121
|
-
<div class="progress-fill" style="width:${
|
|
9144
|
+
<div class="progress-fill" style="width:${a}%;background:${s};"></div>
|
|
9122
9145
|
</div>
|
|
9123
9146
|
</div>
|
|
9124
|
-
`}_renderStepProgress(t){if(!t)return"";let e=t.current||0,
|
|
9147
|
+
`}_renderStepProgress(t){if(!t)return"";let e=t.current||0,i=t.total||0,a=i>0?Math.round(e/i*100):0;return`
|
|
9125
9148
|
<div class="stat-card">
|
|
9126
9149
|
<div class="stat-header">Step Progress</div>
|
|
9127
|
-
<div class="stat-value">${e} / ${
|
|
9128
|
-
<div class="stat-pct">${
|
|
9150
|
+
<div class="stat-value">${e} / ${i}</div>
|
|
9151
|
+
<div class="stat-pct">${a}% complete</div>
|
|
9129
9152
|
<div class="progress-bar">
|
|
9130
|
-
<div class="progress-fill" style="width:${
|
|
9153
|
+
<div class="progress-fill" style="width:${a}%;background:var(--loki-accent);"></div>
|
|
9131
9154
|
</div>
|
|
9132
9155
|
</div>
|
|
9133
|
-
`}_renderSeamSummary(t){if(!t)return"";let e=t.total||0,
|
|
9156
|
+
`}_renderSeamSummary(t){if(!t)return"";let e=t.total||0,i=t.high||0,a=t.medium||0,s=t.low||0;return`
|
|
9134
9157
|
<div class="stat-card">
|
|
9135
9158
|
<div class="stat-header">Seam Summary</div>
|
|
9136
9159
|
<div class="stat-value">${e} seams</div>
|
|
9137
9160
|
<div class="seam-breakdown">
|
|
9138
|
-
<span class="seam-badge seam-high">High: ${
|
|
9139
|
-
<span class="seam-badge seam-medium">Med: ${
|
|
9161
|
+
<span class="seam-badge seam-high">High: ${i}</span>
|
|
9162
|
+
<span class="seam-badge seam-medium">Med: ${a}</span>
|
|
9140
9163
|
<span class="seam-badge seam-low">Low: ${s}</span>
|
|
9141
9164
|
</div>
|
|
9142
9165
|
</div>
|
|
9143
|
-
`}_renderCheckpoint(t){if(!t)return"";let e=t.timestamp?new Date(t.timestamp).toLocaleString():"--",
|
|
9166
|
+
`}_renderCheckpoint(t){if(!t)return"";let e=t.timestamp?new Date(t.timestamp).toLocaleString():"--",i=this._escapeHtml(t.step_id||t.stepId||"--");return`
|
|
9144
9167
|
<div class="checkpoint-section">
|
|
9145
9168
|
<div class="section-label">Last Checkpoint</div>
|
|
9146
9169
|
<div class="checkpoint-row">
|
|
@@ -9149,7 +9172,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9149
9172
|
</div>
|
|
9150
9173
|
<div class="checkpoint-row">
|
|
9151
9174
|
<span class="checkpoint-label">Step:</span>
|
|
9152
|
-
<span class="checkpoint-value mono">${
|
|
9175
|
+
<span class="checkpoint-value mono">${i}</span>
|
|
9153
9176
|
</div>
|
|
9154
9177
|
</div>
|
|
9155
9178
|
`}_renderMigrationList(){return this._migrations.length===0?'<div class="empty-state">No migrations found</div>':`
|
|
@@ -9157,10 +9180,10 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9157
9180
|
<thead>
|
|
9158
9181
|
<tr><th>ID</th><th>Migration</th><th>Status</th></tr>
|
|
9159
9182
|
</thead>
|
|
9160
|
-
<tbody>${this._migrations.map(e=>{let
|
|
9183
|
+
<tbody>${this._migrations.map(e=>{let i=this._escapeHtml(e.migration_id||e.id||"--"),a=this._escapeHtml(e.source||"--"),s=this._escapeHtml(e.target||"--"),r=this._escapeHtml(e.status||"--"),o=e.status==="completed"?"status-done":e.status==="failed"?"status-failed":"status-pending";return`
|
|
9161
9184
|
<tr>
|
|
9162
|
-
<td class="mono">${
|
|
9163
|
-
<td>${
|
|
9185
|
+
<td class="mono">${i}</td>
|
|
9186
|
+
<td>${a} -> ${s}</td>
|
|
9164
9187
|
<td><span class="status-badge ${o}">${r}</span></td>
|
|
9165
9188
|
</tr>
|
|
9166
9189
|
`}).join("")}</tbody>
|
|
@@ -9477,13 +9500,13 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9477
9500
|
</div>
|
|
9478
9501
|
<div class="empty-state">No migration data available</div>
|
|
9479
9502
|
</div>
|
|
9480
|
-
`;return}if(this._migration){let
|
|
9503
|
+
`;return}if(this._migration){let i=this._migration,a=this._escapeHtml(i.migration_id||i.id||"--"),s=this._escapeHtml(i.source||"--"),r=this._escapeHtml(i.target||"--"),o=i.current_phase||i.phase||"understand",n=i.completed_phases||[];this.shadowRoot.innerHTML=`
|
|
9481
9504
|
<style>${t}</style>
|
|
9482
9505
|
<div class="migration-container">
|
|
9483
9506
|
<div class="migration-header">
|
|
9484
9507
|
${e}
|
|
9485
9508
|
<span class="migration-title">Migration Dashboard</span>
|
|
9486
|
-
<span class="migration-id">${
|
|
9509
|
+
<span class="migration-id">${a}</span>
|
|
9487
9510
|
</div>
|
|
9488
9511
|
|
|
9489
9512
|
<div class="meta-row">
|
|
@@ -9500,7 +9523,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9500
9523
|
</div>
|
|
9501
9524
|
<div class="meta-item">
|
|
9502
9525
|
<span class="meta-label">Phase</span>
|
|
9503
|
-
<span>${
|
|
9526
|
+
<span>${Vt[o]||this._escapeHtml(o)}</span>
|
|
9504
9527
|
</div>
|
|
9505
9528
|
</div>
|
|
9506
9529
|
|
|
@@ -9510,12 +9533,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9510
9533
|
</div>
|
|
9511
9534
|
|
|
9512
9535
|
<div class="stats-grid">
|
|
9513
|
-
${this._renderFeatureStats(
|
|
9514
|
-
${this._renderStepProgress(
|
|
9515
|
-
${this._renderSeamSummary(
|
|
9536
|
+
${this._renderFeatureStats(i.features)}
|
|
9537
|
+
${this._renderStepProgress(i.steps)}
|
|
9538
|
+
${this._renderSeamSummary(i.seams)}
|
|
9516
9539
|
</div>
|
|
9517
9540
|
|
|
9518
|
-
${this._renderCheckpoint(
|
|
9541
|
+
${this._renderCheckpoint(i.last_checkpoint||i.checkpoint)}
|
|
9519
9542
|
</div>
|
|
9520
9543
|
`;return}this.shadowRoot.innerHTML=`
|
|
9521
9544
|
<style>${t}</style>
|
|
@@ -9527,7 +9550,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9527
9550
|
<div class="section-label">Migrations</div>
|
|
9528
9551
|
${this._renderMigrationList()}
|
|
9529
9552
|
</div>
|
|
9530
|
-
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",rt);var
|
|
9553
|
+
`}};customElements.get("loki-migration-dashboard")||customElements.define("loki-migration-dashboard",rt);var ke=[["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 xe(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 _e(d,t){if(t!=null){let i=xe(t);if(i)return i.provider}let e=(d||"").toLowerCase();for(let[i,a]of ke)if(e.includes(i))return a;return"unknown"}var ot=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._api=null,this._pollInterval=null,this._activeTab="heatmap",this._activity=[],this._tools=[],this._cost={},this._context={},this._trends=[],this._toolTimeRange="7d",this._connected=!1,this._loading=!1}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _fetchActivity(){let t=this._api.baseUrl||window.location.origin,e=new AbortController,i=setTimeout(()=>e.abort(),1e4);try{let a=await fetch(`${t}/api/activity?limit=1000`,{signal:e.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 t=await Promise.allSettled([this._fetchActivity(),this._api.getToolEfficiency(50),this._api.getCost(),this._api.getContext(),this._api.getLearningTrends({timeRange:this._toolTimeRange})]);if(t[0].status==="fulfilled"&&(this._activity=t[0].value||[]),t[1].status==="fulfilled"&&(this._tools=t[1].value||[]),t[2].status==="fulfilled"&&(this._cost=t[2].value||{}),t[3].status==="fulfilled"&&(this._context=t[3].value||{}),t[4].status==="fulfilled"){let e=t[4].value||{};this._trends=Array.isArray(e)?e:e.dataPoints||[]}this._connected=t.some(e=>e.status==="fulfilled"),this.render()}finally{this._loading=!1}}}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e4),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e4))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}_computeHeatmap(){let t={},e=Array.isArray(this._activity)?this._activity:[];for(let c of e){let p=c.timestamp||c.ts||c.created_at;if(!p)continue;let u=new Date(p);if(isNaN(u.getTime()))continue;let b=this._localDateKey(u);t[b]=(t[b]||0)+1}let i=new Date;i.setHours(0,0,0,0);let a=i.getDay(),s=new Date(i),r=new Date(i);r.setDate(r.getDate()-(52*7+a));let o=[],n=new Date(r),l=0;for(;n<=s;){let c=this._localDateKey(n),p=t[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(t,e){if(t===0||e===0)return 0;let i=t/e;return i<=.25?1:i<=.5?2:i<=.75?3:4}_renderHeatmap(){let{cells:t,maxCount:e}=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<t.length;p++){t[p].day===0&&o++;let u=new Date(t[p].date).getMonth();u!==r&&(s.push({month:i[u],col:Math.max(o,1)}),r=u)}let n=s.map(p=>`<span class="heatmap-month" style="grid-column: ${p.col}">${p.month}</span>`).join(""),l=t.map(p=>`<div class="heatmap-cell level-${this._getHeatmapLevel(p.count,e)}" title="${p.date}: ${p.count} activities"></div>`).join(""),c=a.map(p=>`<span class="heatmap-day-label">${p}</span>`).join("");return`
|
|
9531
9554
|
<div class="heatmap-container">
|
|
9532
9555
|
<div class="heatmap-months">${n}</div>
|
|
9533
9556
|
<div class="heatmap-body">
|
|
@@ -9544,15 +9567,15 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9544
9567
|
<span class="heatmap-legend-label">More</span>
|
|
9545
9568
|
</div>
|
|
9546
9569
|
</div>
|
|
9547
|
-
`}_computeToolUsage(){let t=Array.isArray(this._tools)?this._tools:[],e={};for(let
|
|
9570
|
+
`}_computeToolUsage(){let t=Array.isArray(this._tools)?this._tools:[],e={};for(let i of t){let a=i.tool||i.name||i.tool_name||i.data&&i.data.tool_name||"unknown",s=i.count??i.calls??i.frequency??(i.data&&i.data.count)??1;e[a]=(e[a]||0)+s}return Object.entries(e).sort((i,a)=>a[1]-i[1]).slice(0,15)}_renderToolUsage(){let t=this._computeToolUsage(),e=t.length>0?t[0][1]:0;return t.length===0?'<div class="empty-state">No tool usage data available</div>':'<div class="tool-bars">'+t.map(([a,s])=>{let r=e>0?s/e*100:0;return`
|
|
9548
9571
|
<div class="tool-row">
|
|
9549
|
-
<span class="tool-name" title="${this._esc(
|
|
9572
|
+
<span class="tool-name" title="${this._esc(a)}">${this._esc(a)}</span>
|
|
9550
9573
|
<div class="tool-bar-track">
|
|
9551
9574
|
<div class="tool-bar-fill" style="width: ${r.toFixed(1)}%"></div>
|
|
9552
9575
|
</div>
|
|
9553
9576
|
<span class="tool-count">${s}</span>
|
|
9554
9577
|
</div>
|
|
9555
|
-
`}).join("")+"</div>"}_computeVelocity(){let t=this._context||{},e=t.per_iteration||t.iterations||[],
|
|
9578
|
+
`}).join("")+"</div>"}_computeVelocity(){let t=this._context||{},e=t.per_iteration||t.iterations||[],i=Array.isArray(e)&&e.length>0?e.length:t.totals&&t.totals.iterations_tracked||t.total_iterations||0,a=0;if(Array.isArray(e)&&e.length>=2){let o=e.map(n=>new Date(n.timestamp||n.started_at||n.ts).getTime()).filter(n=>!isNaN(n)).sort((n,l)=>n-l);if(o.length>=2){let n=(o[o.length-1]-o[0])/36e5;n>0&&(a=Math.max(o.length-1,1)/n)}}let s=[],r=Array.isArray(this._trends)?this._trends:[];if(r.length>0)for(let o of r.slice(-24))s.push(o.count??o.value??0);else if(Array.isArray(e)&&e.length>0){let o={};for(let l of e){let c=l.timestamp||l.started_at||l.ts;if(!c)continue;let u=new Date(c).toISOString().slice(0,13);o[u]=(o[u]||0)+1}let n=Object.keys(o).sort().slice(-24);for(let l of n)s.push(o[l])}return{iterPerHour:a,totalIterations:i,hourlyBuckets:s}}_renderVelocity(){let{iterPerHour:t,totalIterations:e,hourlyBuckets:i}=this._computeVelocity(),a=Math.max(1,...i),s=i.length>0?i.map(o=>{let n=o/a*100;return`<div class="spark-bar" style="height: ${Math.max(2,n)}%" title="${o}"></div>`}).join(""):'<div class="empty-state" style="padding: 12px">No trend data</div>';return`
|
|
9556
9579
|
${`
|
|
9557
9580
|
<div class="tool-filter">
|
|
9558
9581
|
<select class="tool-time-select" id="tool-time-range">
|
|
@@ -9577,9 +9600,9 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9577
9600
|
<div class="sparkline-label">Activity Trend (hourly)</div>
|
|
9578
9601
|
<div class="sparkline">${s}</div>
|
|
9579
9602
|
</div>
|
|
9580
|
-
`}_computeProviders(){let t=this._cost.by_model||{},e={};for(let[r,o]of Object.entries(t)){let n=
|
|
9603
|
+
`}_computeProviders(){let t=this._cost.by_model||{},e={};for(let[r,o]of Object.entries(t)){let n=_e(r);e[n]||(e[n]={cost:0,tokens:0,iterations:0,models:[]});let l=o.cost_usd||0,c=(o.input_tokens||0)+(o.output_tokens||0);e[n].cost+=l,e[n].tokens+=c,e[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(e))if(s>0&&a>0){let o=r.cost/s;r.iterations=Math.round(o*a)}return e}_renderProviders(){let t=this._computeProviders(),e={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(t);return i.length===0?'<div class="empty-state">No provider data available. Start a session to see cross-provider comparison.</div>':`
|
|
9581
9604
|
<div class="provider-grid">
|
|
9582
|
-
${
|
|
9605
|
+
${i.map(([a,s])=>{let r=e[a]||e.unknown,o=s.iterations>0?(s.cost/s.iterations).toFixed(4):"--",n=s.iterations>0?Math.round(s.tokens/s.iterations).toLocaleString():"--";return`
|
|
9583
9606
|
<div class="provider-card">
|
|
9584
9607
|
<div class="provider-accent" style="background: ${r.color}"></div>
|
|
9585
9608
|
<div class="provider-body">
|
|
@@ -9964,9 +9987,9 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9964
9987
|
${this._connected?"":'<div class="offline-notice">Connecting to analytics API...</div>'}
|
|
9965
9988
|
|
|
9966
9989
|
<div class="tab-bar">
|
|
9967
|
-
${t.map(
|
|
9968
|
-
<button class="tab-btn ${this._activeTab===
|
|
9969
|
-
${
|
|
9990
|
+
${t.map(a=>`
|
|
9991
|
+
<button class="tab-btn ${this._activeTab===a.id?"active":""}" data-tab="${a.id}" aria-label="${a.label}">
|
|
9992
|
+
${a.icon}<span>${a.label}</span>
|
|
9970
9993
|
</button>
|
|
9971
9994
|
`).join("")}
|
|
9972
9995
|
</div>
|
|
@@ -9975,7 +9998,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
9975
9998
|
${e}
|
|
9976
9999
|
</div>
|
|
9977
10000
|
</div>
|
|
9978
|
-
`,this.shadowRoot.querySelectorAll("[data-tab]").forEach(
|
|
10001
|
+
`,this.shadowRoot.querySelectorAll("[data-tab]").forEach(a=>{a.addEventListener("click",s=>this._handleTabClick(s))});let i=this.shadowRoot.getElementById("tool-time-range");i&&i.addEventListener("change",a=>this._handleTimeRangeChange(a))}};customElements.get("loki-analytics")||customElements.define("loki-analytics",ot);var Yt={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 ye(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 we(d){if(!d||d.length===0)return{pass:0,fail:0,pending:0,total:0};let t={pass:0,fail:0,pending:0,total:d.length};for(let e of d){let i=(e.status||"pending").toLowerCase();i==="pass"?t.pass++:i==="fail"?t.fail++:t.pending++}return t}var nt=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._gates=[],this._pollInterval=null,this._lastDataHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e4),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e4))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{this._loading=!0;let t=await this._api._get("/api/council/gate"),e=t?.gates||t||[],i=JSON.stringify(e);if(i===this._lastDataHash)return;this._lastDataHash=i,this._gates=Array.isArray(e)?e:[],this._error=null}catch(t){this._error||(this._error=`Failed to load quality gates: ${t.message}`)}finally{this._loading=!1}this.render()}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
9979
10002
|
:host {
|
|
9980
10003
|
display: block;
|
|
9981
10004
|
}
|
|
@@ -10106,28 +10129,28 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10106
10129
|
color: var(--loki-text-muted, #939084);
|
|
10107
10130
|
font-size: 13px;
|
|
10108
10131
|
}
|
|
10109
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._gates,
|
|
10132
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._gates,i=we(e),a;this._loading&&e.length===0?a='<div class="loading">Loading quality gates...</div>':e.length===0?a='<div class="empty-state"><strong>No gate results yet.</strong> Quality gates run automatically between RARV iterations during an active session. Start a session with <code>loki start ./prd.md</code> to see results here. You can also run gates manually with <code>loki review</code>.</div>':a=`<div class="gates-grid">${e.map(o=>{let n=(o.status||"pending").toLowerCase(),l=Yt[n]||Yt.pending;return`
|
|
10110
10133
|
<div class="gate-card status-${n}">
|
|
10111
10134
|
<div class="gate-header">
|
|
10112
10135
|
<span class="gate-name">${this._escapeHtml(o.name||"Unnamed Gate")}</span>
|
|
10113
10136
|
<span class="gate-badge" style="background: ${l.bg}; color: ${l.color};">${l.label}</span>
|
|
10114
10137
|
</div>
|
|
10115
10138
|
${o.description?`<div class="gate-description">${this._escapeHtml(o.description)}</div>`:""}
|
|
10116
|
-
<div class="gate-meta">Last checked: ${
|
|
10139
|
+
<div class="gate-meta">Last checked: ${ye(o.last_checked||o.lastChecked)}</div>
|
|
10117
10140
|
</div>
|
|
10118
|
-
`}).join("")}</div>`;let s=
|
|
10141
|
+
`}).join("")}</div>`;let s=i.total>0?`
|
|
10119
10142
|
<div class="summary">
|
|
10120
10143
|
<span class="summary-item">
|
|
10121
10144
|
<span class="summary-dot" style="background: var(--loki-green, #22c55e)"></span>
|
|
10122
|
-
${
|
|
10145
|
+
${i.pass} Pass
|
|
10123
10146
|
</span>
|
|
10124
10147
|
<span class="summary-item">
|
|
10125
10148
|
<span class="summary-dot" style="background: var(--loki-red, #ef4444)"></span>
|
|
10126
|
-
${
|
|
10149
|
+
${i.fail} Fail
|
|
10127
10150
|
</span>
|
|
10128
10151
|
<span class="summary-item">
|
|
10129
10152
|
<span class="summary-dot" style="background: var(--loki-yellow, #eab308)"></span>
|
|
10130
|
-
${
|
|
10153
|
+
${i.pending} Pending
|
|
10131
10154
|
</span>
|
|
10132
10155
|
</div>
|
|
10133
10156
|
`:"";t.innerHTML=`
|
|
@@ -10137,10 +10160,10 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10137
10160
|
<h2 class="title">Quality Gates</h2>
|
|
10138
10161
|
${s}
|
|
10139
10162
|
</div>
|
|
10140
|
-
${
|
|
10163
|
+
${a}
|
|
10141
10164
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
10142
10165
|
</div>
|
|
10143
|
-
`}};customElements.get("loki-quality-gates")||customElements.define("loki-quality-gates",nt);var F={reason:{color:"var(--loki-blue, #3b82f6)",label:"Reason",description:"Analyzing requirements and planning approach"},act:{color:"var(--loki-green, #22c55e)",label:"Act",description:"Implementing changes and executing tasks"},reflect:{color:"var(--loki-purple, #a78bfa)",label:"Reflect",description:"Reviewing results and evaluating quality"},verify:{color:"var(--loki-yellow, #eab308)",label:"Verify",description:"Running tests and validating correctness"}},
|
|
10166
|
+
`}};customElements.get("loki-quality-gates")||customElements.define("loki-quality-gates",nt);var F={reason:{color:"var(--loki-blue, #3b82f6)",label:"Reason",description:"Analyzing requirements and planning approach"},act:{color:"var(--loki-green, #22c55e)",label:"Act",description:"Implementing changes and executing tasks"},reflect:{color:"var(--loki-purple, #a78bfa)",label:"Reflect",description:"Reviewing results and evaluating quality"},verify:{color:"var(--loki-yellow, #eab308)",label:"Verify",description:"Running tests and validating correctness"}},zt=["reason","act","reflect","verify"];function Lt(d){if(d==null||d<0)return"--";if(d<1e3)return`${d}ms`;let t=Math.floor(d/1e3);if(t<60)return`${t}s`;let e=Math.floor(t/60),i=t%60;if(e<60)return`${e}m ${i}s`;let a=Math.floor(e/60),s=e%60;return`${a}h ${s}m`}function $e(d){if(!d||d.length===0)return[];let t=d.reduce((e,i)=>e+(i.duration_ms||0),0);return t===0?d.map(e=>({phase:e.phase,pct:100/d.length,duration:0})):d.map(e=>({phase:e.phase,pct:(e.duration_ms||0)/t*100,duration:e.duration_ms||0}))}function Ee(d){return d==null?"--":d>=1e6?(d/1e6).toFixed(1)+"M":d>=1e3?(d/1e3).toFixed(1)+"K":String(d)}var lt=class extends h{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 t=this.getAttribute("run-id");return t?parseInt(t,10):null}set runId(t){t!=null?this.setAttribute("run-id",String(t)):this.removeAttribute("run-id")}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="run-id"&&this._loadData(),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),5e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),5e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){let t=this.runId;if(t==null){this._timeline=null,this.render();return}try{this._loading=!0;let e=await this._api._get(`/api/v2/runs/${t}/timeline`);this._timeline=e,this._cycleHistory=e.history||[],this._error=null}catch(e){e.message&&(e.message.includes("404")||e.message.includes("Not Found"))?(this._timeline=null,this._error=null):this._error=`Failed to load timeline: ${e.message}`}finally{this._loading=!1}this.render()}_selectPhase(t){this._selectedPhase=this._selectedPhase===t?null:t,this.render()}_bindEvents(){let t=this.shadowRoot;t.querySelectorAll(".phase-segment-interactive").forEach(e=>{e.addEventListener("click",()=>{this._selectPhase(e.dataset.phase)})}),t.querySelectorAll(".legend-item-interactive").forEach(e=>{e.addEventListener("click",()=>{this._selectPhase(e.dataset.phase)})}),t.querySelectorAll(".close-detail").forEach(e=>{e.addEventListener("click",i=>{i.stopPropagation(),this._selectedPhase=null,this.render()})})}_getStyles(){return`
|
|
10144
10167
|
:host {
|
|
10145
10168
|
display: block;
|
|
10146
10169
|
}
|
|
@@ -10425,14 +10448,14 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10425
10448
|
color: var(--loki-text-muted, #939084);
|
|
10426
10449
|
font-size: 13px;
|
|
10427
10450
|
}
|
|
10428
|
-
`}_renderPlaceholderTimeline(){let t=
|
|
10429
|
-
data-phase="${
|
|
10430
|
-
style="width: 25%; background: ${
|
|
10431
|
-
title="${
|
|
10432
|
-
${
|
|
10433
|
-
</div>`}).join(""),e=
|
|
10434
|
-
<span class="legend-dot" style="background: ${
|
|
10435
|
-
<span class="legend-label">${
|
|
10451
|
+
`}_renderPlaceholderTimeline(){let t=zt.map(i=>{let a=F[i];return`<div class="phase-segment-interactive"
|
|
10452
|
+
data-phase="${i}"
|
|
10453
|
+
style="width: 25%; background: ${a.color}; opacity: 0.3;"
|
|
10454
|
+
title="${a.label}: awaiting data">
|
|
10455
|
+
${a.label}
|
|
10456
|
+
</div>`}).join(""),e=zt.map(i=>{let a=F[i];return`<div class="legend-item-interactive" data-phase="${i}">
|
|
10457
|
+
<span class="legend-dot" style="background: ${a.color}; opacity: 0.4;"></span>
|
|
10458
|
+
<span class="legend-label">${a.label}</span>
|
|
10436
10459
|
<span class="legend-duration">--</span>
|
|
10437
10460
|
</div>`}).join("");return`
|
|
10438
10461
|
<div class="empty-state" style="padding: 0; text-align: left;">
|
|
@@ -10442,7 +10465,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10442
10465
|
RARV phases will populate as the session progresses
|
|
10443
10466
|
</div>
|
|
10444
10467
|
</div>
|
|
10445
|
-
`}_renderPhaseDetail(t){let e=F[t];if(!e)return"";let
|
|
10468
|
+
`}_renderPhaseDetail(t){let e=F[t];if(!e)return"";let a=(this._timeline?.phases||[]).find(s=>s.phase===t);return`
|
|
10446
10469
|
<div class="phase-detail">
|
|
10447
10470
|
<div class="detail-header">
|
|
10448
10471
|
<div class="detail-title">
|
|
@@ -10455,38 +10478,38 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10455
10478
|
<div class="detail-metrics">
|
|
10456
10479
|
<div class="detail-metric">
|
|
10457
10480
|
<span class="detail-metric-label">Time Spent</span>
|
|
10458
|
-
<span class="detail-metric-value">${
|
|
10481
|
+
<span class="detail-metric-value">${Lt(a?.duration_ms)}</span>
|
|
10459
10482
|
</div>
|
|
10460
10483
|
<div class="detail-metric">
|
|
10461
10484
|
<span class="detail-metric-label">Tokens Used</span>
|
|
10462
|
-
<span class="detail-metric-value">${
|
|
10485
|
+
<span class="detail-metric-value">${Ee(a?.tokens_used)}</span>
|
|
10463
10486
|
</div>
|
|
10464
10487
|
<div class="detail-metric">
|
|
10465
10488
|
<span class="detail-metric-label">Quality</span>
|
|
10466
|
-
<span class="detail-metric-value">${
|
|
10489
|
+
<span class="detail-metric-value">${a?.quality_score!=null?a.quality_score.toFixed(1):"--"}</span>
|
|
10467
10490
|
</div>
|
|
10468
10491
|
<div class="detail-metric">
|
|
10469
10492
|
<span class="detail-metric-label">Actions</span>
|
|
10470
|
-
<span class="detail-metric-value">${
|
|
10493
|
+
<span class="detail-metric-value">${a?.action_count!=null?a.action_count:"--"}</span>
|
|
10471
10494
|
</div>
|
|
10472
10495
|
</div>
|
|
10473
10496
|
</div>
|
|
10474
|
-
`}_renderCycleHistory(){if(this._cycleHistory.length===0)return"";let e=this._cycleHistory.slice(-8).map((a
|
|
10475
|
-
title="Cycle ${
|
|
10497
|
+
`}_renderCycleHistory(){if(this._cycleHistory.length===0)return"";let e=this._cycleHistory.slice(-8).map((i,a)=>`<div class="history-cycle">${zt.map(r=>{let o=i.phases?.find(p=>p.phase===r),n=F[r],l=o?.status||"pending",c=l==="complete"?"0.8":l==="active"?"1":"0.3";return`<div class="history-dot" style="background: ${n.color}; opacity: ${c};"
|
|
10498
|
+
title="Cycle ${a+1}: ${n.label} - ${Lt(o?.duration_ms)}"></div>`}).join("")}</div>`).join('<div class="history-separator"></div>');return`
|
|
10476
10499
|
<div class="cycle-history">
|
|
10477
10500
|
<div class="history-label">Past Cycles (${this._cycleHistory.length} total)</div>
|
|
10478
10501
|
<div class="history-cycles">${e}</div>
|
|
10479
10502
|
</div>
|
|
10480
|
-
`}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let t=this.shadowRoot;if(!t)return;let e=this.runId,
|
|
10503
|
+
`}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}render(){let t=this.shadowRoot;if(!t)return;let e=this.runId,i=this._timeline,a=i?.phases||[],s=i?.current_phase||null,r=$e(a),o;if(this._loading&&!i)o='<div class="loading">Loading timeline...</div>';else if(e==null)o=this._renderPlaceholderTimeline();else if(a.length===0)o=this._renderPlaceholderTimeline();else{let n=r.map(u=>{let b=F[u.phase]||{color:"var(--loki-text-muted)",label:u.phase},v=s===u.phase,f=this._selectedPhase===u.phase;return`<div class="phase-segment-interactive ${v?"current":""} ${f?"selected":""}"
|
|
10481
10504
|
data-phase="${u.phase}"
|
|
10482
10505
|
style="width: ${Math.max(u.pct,2)}%; background: ${b.color};"
|
|
10483
|
-
title="${b.label}: ${
|
|
10506
|
+
title="${b.label}: ${Lt(u.duration)}">
|
|
10484
10507
|
${u.pct>12?b.label:""}
|
|
10485
|
-
</div>`}).join(""),l=
|
|
10508
|
+
</div>`}).join(""),l=a.map(u=>{let b=F[u.phase]||{color:"var(--loki-text-muted)",label:u.phase},v=s===u.phase;return`<div class="legend-item-interactive ${this._selectedPhase===u.phase?"selected":""}" data-phase="${u.phase}">
|
|
10486
10509
|
<span class="legend-dot" style="background: ${b.color}"></span>
|
|
10487
10510
|
<span class="legend-label">${b.label}</span>
|
|
10488
|
-
<span class="legend-duration">${
|
|
10489
|
-
${
|
|
10511
|
+
<span class="legend-duration">${Lt(u.duration_ms)}</span>
|
|
10512
|
+
${v?'<span class="phase-current-tag">ACTIVE</span>':""}
|
|
10490
10513
|
</div>`}).join(""),c=this._selectedPhase?this._renderPhaseDetail(this._selectedPhase):"",p=this._renderCycleHistory();o=`
|
|
10491
10514
|
<div class="timeline-bar">${n}</div>
|
|
10492
10515
|
<div class="legend">${l}</div>
|
|
@@ -10502,7 +10525,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10502
10525
|
${o}
|
|
10503
10526
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
10504
10527
|
</div>
|
|
10505
|
-
`,this._bindEvents()}};customElements.get("loki-rarv-timeline")||customElements.define("loki-rarv-timeline",lt);var
|
|
10528
|
+
`,this._bindEvents()}};customElements.get("loki-rarv-timeline")||customElements.define("loki-rarv-timeline",lt);var Wt={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 Ce(d,t,e){let i=d;if(i==null&&t){let l=new Date(t).getTime();i=(e?new Date(e).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 Se(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 dt=class extends h{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 t=this.getAttribute("project-id");return t?parseInt(t,10):null}set projectId(t){t!=null?this.setAttribute("project-id",String(t)):this.removeAttribute("project-id")}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="project-id"&&this._loadData(),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),5e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),5e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{let t=this.projectId,e=t!=null?`?project_id=${t}`:"",i=await this._api._get(`/api/v2/runs${e}`),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(t){this._error||(this._error=`Failed to load runs: ${t.message}`)}finally{this._loading=!1}this.render()}async _cancelRun(t){try{await this._api._post(`/api/v2/runs/${t}/cancel`),await this._loadData()}catch(e){this._error=`Cancel failed: ${e.message}`,this.render()}}async _replayRun(t){try{await this._api._post(`/api/v2/runs/${t}/replay`),await this._loadData()}catch(e){this._error=`Replay failed: ${e.message}`,this.render()}}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
10506
10529
|
:host {
|
|
10507
10530
|
display: block;
|
|
10508
10531
|
}
|
|
@@ -10655,13 +10678,13 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10655
10678
|
color: var(--loki-text-muted, #939084);
|
|
10656
10679
|
margin-bottom: 8px;
|
|
10657
10680
|
}
|
|
10658
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._runs,
|
|
10681
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._runs,i;if(this._loading&&e.length===0)i='<div class="loading">Loading runs...</div>';else if(e.length===0)i='<div class="empty-state">No runs found.</div>';else{let a=e.map(s=>{let r=(s.status||"pending").toLowerCase(),o=Wt[r]||Wt.pending,n=r==="running",l=r==="completed"||r==="failed"||r==="cancelled",c=Ce(s.duration_ms,s.started_at,s.ended_at);return`
|
|
10659
10682
|
<tr>
|
|
10660
10683
|
<td><span class="run-id">#${s.id}</span></td>
|
|
10661
10684
|
<td>${this._escapeHtml(s.project_name||s.project||(s.project_id?`Project #${s.project_id}`:"--"))}</td>
|
|
10662
10685
|
<td><span class="status-badge" style="background: ${o.bg}; color: ${o.color};">${o.label}</span></td>
|
|
10663
10686
|
<td>${this._escapeHtml(s.trigger||s.trigger_type||"--")}</td>
|
|
10664
|
-
<td>${
|
|
10687
|
+
<td>${Se(s.started_at)}</td>
|
|
10665
10688
|
<td>${c}</td>
|
|
10666
10689
|
<td>
|
|
10667
10690
|
<div class="actions-cell">
|
|
@@ -10670,7 +10693,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10670
10693
|
</div>
|
|
10671
10694
|
</td>
|
|
10672
10695
|
</tr>
|
|
10673
|
-
`}).join("");
|
|
10696
|
+
`}).join("");i=`
|
|
10674
10697
|
<div class="run-count">${e.length} runs</div>
|
|
10675
10698
|
<div class="runs-table-wrapper">
|
|
10676
10699
|
<table>
|
|
@@ -10685,7 +10708,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10685
10708
|
<th>Actions</th>
|
|
10686
10709
|
</tr>
|
|
10687
10710
|
</thead>
|
|
10688
|
-
<tbody>${
|
|
10711
|
+
<tbody>${a}</tbody>
|
|
10689
10712
|
</table>
|
|
10690
10713
|
</div>
|
|
10691
10714
|
`}t.innerHTML=`
|
|
@@ -10695,10 +10718,10 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10695
10718
|
<h2 class="title">Run Manager</h2>
|
|
10696
10719
|
<button class="btn btn-refresh" id="refresh-btn">Refresh</button>
|
|
10697
10720
|
</div>
|
|
10698
|
-
${
|
|
10721
|
+
${i}
|
|
10699
10722
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
10700
10723
|
</div>
|
|
10701
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("refresh-btn");e&&e.addEventListener("click",()=>this._loadData()),t.querySelectorAll('[data-action="cancel"]').forEach(
|
|
10724
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("refresh-btn");e&&e.addEventListener("click",()=>this._loadData()),t.querySelectorAll('[data-action="cancel"]').forEach(i=>{i.addEventListener("click",()=>this._cancelRun(i.dataset.runId))}),t.querySelectorAll('[data-action="replay"]').forEach(i=>{i.addEventListener("click",()=>this._replayRun(i.dataset.runId))})}};customElements.get("loki-run-manager")||customElements.define("loki-run-manager",dt);function Ae(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 Te(d){let t=new URLSearchParams;for(let[i,a]of Object.entries(d))a!=null&&a!==""&&t.set(i,String(a));let e=t.toString();return e?`?${e}`:""}var ct=class extends h{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 t=this.getAttribute("limit");return t?parseInt(t,10):50}set limit(t){this.setAttribute("limit",String(t))}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData()}disconnectedCallback(){super.disconnectedCallback()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="limit"&&this._loadData(),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadData(){try{this._loading=!0,this.render();let t={limit:this.limit,action:this._filters.action,resource:this._filters.resource,date_from:this._filters.dateFrom,date_to:this._filters.dateTo},e=Te(t),i=await this._api._get(`/api/v2/audit${e}`);this._entries=i?.entries||i||[],this._error=null}catch(t){this._error=`Failed to load audit log: ${t.message}`}finally{this._loading=!1}this.render()}async _verifyIntegrity(){try{this._verifying=!0,this._verifyResult=null,this.render();let t=await this._api._get("/api/v2/audit/verify");this._verifyResult=t}catch(t){this._verifyResult={valid:!1,error:t.message}}finally{this._verifying=!1}this.render()}_onFilterChange(t,e){this._filters[t]=e,this._loadData()}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
10702
10725
|
:host {
|
|
10703
10726
|
display: block;
|
|
10704
10727
|
}
|
|
@@ -10912,19 +10935,19 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10912
10935
|
color: var(--loki-text-muted, #939084);
|
|
10913
10936
|
margin-bottom: 8px;
|
|
10914
10937
|
}
|
|
10915
|
-
`}_getStatusClass(t){if(!t)return"status-warning";let e=t.toLowerCase();return e==="success"||e==="ok"||e==="pass"?"status-success":e==="failure"||e==="error"||e==="fail"?"status-failure":"status-warning"}render(){let t=this.shadowRoot;if(!t)return;let e=this._entries,
|
|
10938
|
+
`}_getStatusClass(t){if(!t)return"status-warning";let e=t.toLowerCase();return e==="success"||e==="ok"||e==="pass"?"status-success":e==="failure"||e==="error"||e==="fail"?"status-failure":"status-warning"}render(){let t=this.shadowRoot;if(!t)return;let e=this._entries,i="";if(this._verifyResult){let s=this._verifyResult.valid!==!1;i=`
|
|
10916
10939
|
<div class="verify-result ${s?"verify-valid":"verify-invalid"}">
|
|
10917
10940
|
${s?"[VALID] Audit chain integrity verified.":`[TAMPERED] ${this._escapeHtml(this._verifyResult.error||"Integrity check failed.")}`}
|
|
10918
10941
|
</div>
|
|
10919
|
-
`}let
|
|
10942
|
+
`}let a;if(this._loading&&e.length===0)a='<div class="loading">Loading audit log...</div>';else if(e.length===0)a='<div class="empty-state">No audit entries found matching filters.</div>';else{let s=e.map(r=>`
|
|
10920
10943
|
<tr>
|
|
10921
|
-
<td>${
|
|
10944
|
+
<td>${Ae(r.timestamp)}</td>
|
|
10922
10945
|
<td>${this._escapeHtml(r.action||"--")}</td>
|
|
10923
10946
|
<td>${this._escapeHtml(r.resource||r.resource_type||"--")}</td>
|
|
10924
10947
|
<td>${this._escapeHtml(r.user||r.actor||"--")}</td>
|
|
10925
10948
|
<td><span class="status-badge ${this._getStatusClass(r.status)}">${this._escapeHtml(r.status||"unknown")}</span></td>
|
|
10926
10949
|
</tr>
|
|
10927
|
-
`).join("");
|
|
10950
|
+
`).join("");a=`
|
|
10928
10951
|
<div class="entry-count">${e.length} entries</div>
|
|
10929
10952
|
<div class="audit-table-wrapper">
|
|
10930
10953
|
<table>
|
|
@@ -10978,11 +11001,11 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
10978
11001
|
</div>
|
|
10979
11002
|
</div>
|
|
10980
11003
|
|
|
10981
|
-
${a}
|
|
10982
11004
|
${i}
|
|
11005
|
+
${a}
|
|
10983
11006
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
10984
11007
|
</div>
|
|
10985
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("verify-btn");e&&e.addEventListener("click",()=>this._verifyIntegrity());let
|
|
11008
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("verify-btn");e&&e.addEventListener("click",()=>this._verifyIntegrity());let i=t.getElementById("refresh-btn");i&&i.addEventListener("click",()=>this._loadData());let a=t.getElementById("filter-action");a&&a.addEventListener("change",n=>this._onFilterChange("action",n.target.value));let s=t.getElementById("filter-resource");s&&s.addEventListener("change",n=>this._onFilterChange("resource",n.target.value));let r=t.getElementById("filter-date-from");r&&r.addEventListener("change",n=>this._onFilterChange("dateFrom",n.target.value));let o=t.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",ct);function Qt(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 pt=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadData(){try{this._loading=!0,this.render();let t=await this._api._get("/api/v2/api-keys");this._keys=Array.isArray(t)?t:t?.keys||[],this._error=null}catch(t){this._error=`Failed to load API keys: ${t.message}`}finally{this._loading=!1}this.render()}async _createKey(){if(!this._createName.trim()){this._error="Key name is required.",this.render();return}try{let t={name:this._createName.trim(),role:this._createRole};this._createExpiration&&(t.expiration=this._createExpiration);let e=await this._api._post("/api/v2/api-keys",t);this._newToken=e?.token||e?.key||null,this._showCreateForm=!1,this._createName="",this._createRole="read",this._createExpiration="",this._error=null,await this._loadData()}catch(t){this._error=`Create failed: ${t.message}`,this.render()}}async _rotateKey(t){try{let e={grace_period_hours:parseInt(this._rotateGracePeriod,10)||24},i=await this._api._post(`/api/v2/api-keys/${t}/rotate`,e);this._newToken=i?.token||i?.key||null,this._rotateKeyId=null,this._error=null,await this._loadData()}catch(e){this._error=`Rotate failed: ${e.message}`,this.render()}}async _deleteKey(t){try{await this._api._delete(`/api/v2/api-keys/${t}`),this._confirmDeleteId=null,this._error=null,await this._loadData()}catch(e){this._error=`Delete failed: ${e.message}`,this._confirmDeleteId=null,this.render()}}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
10986
11009
|
:host {
|
|
10987
11010
|
display: block;
|
|
10988
11011
|
}
|
|
@@ -11288,14 +11311,14 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11288
11311
|
color: var(--loki-text-muted, #939084);
|
|
11289
11312
|
font-size: 13px;
|
|
11290
11313
|
}
|
|
11291
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._keys,
|
|
11314
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._keys,i="";this._newToken&&(i=`
|
|
11292
11315
|
<div class="new-token-banner">
|
|
11293
11316
|
<div class="new-token-label">API Key Created</div>
|
|
11294
11317
|
<div class="new-token-warning">Copy this token now. It will not be shown again.</div>
|
|
11295
11318
|
<div class="new-token-value">${this._escapeHtml(this._newToken)}</div>
|
|
11296
11319
|
<button class="new-token-dismiss" id="dismiss-token">Dismiss</button>
|
|
11297
11320
|
</div>
|
|
11298
|
-
`);let
|
|
11321
|
+
`);let a="";this._showCreateForm&&(a=`
|
|
11299
11322
|
<div class="create-form">
|
|
11300
11323
|
<div class="form-title">Create New API Key</div>
|
|
11301
11324
|
<div class="form-row">
|
|
@@ -11361,8 +11384,8 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11361
11384
|
<tr>
|
|
11362
11385
|
<td><span class="key-name">${this._escapeHtml(o.name||"Unnamed")}</span></td>
|
|
11363
11386
|
<td><span class="key-role">${this._escapeHtml(o.role||o.scopes||"--")}</span></td>
|
|
11364
|
-
<td>${
|
|
11365
|
-
<td>${
|
|
11387
|
+
<td>${Qt(o.created_at||o.created)}</td>
|
|
11388
|
+
<td>${Qt(o.last_used_at||o.last_used)}</td>
|
|
11366
11389
|
<td><span class="${c}">${this._escapeHtml(l)}</span></td>
|
|
11367
11390
|
<td><div class="actions-cell">${b}</div></td>
|
|
11368
11391
|
</tr>
|
|
@@ -11376,12 +11399,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11376
11399
|
<h2 class="title">API Keys</h2>
|
|
11377
11400
|
${this._showCreateForm?"":'<button class="btn btn-primary" id="show-create">Create Key</button>'}
|
|
11378
11401
|
</div>
|
|
11379
|
-
${a}
|
|
11380
11402
|
${i}
|
|
11403
|
+
${a}
|
|
11381
11404
|
${s}
|
|
11382
11405
|
${this._error?`<div class="error-banner">${this._escapeHtml(this._error)}</div>`:""}
|
|
11383
11406
|
</div>
|
|
11384
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("show-create");e&&e.addEventListener("click",()=>{this._showCreateForm=!0,this.render()});let
|
|
11407
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("show-create");e&&e.addEventListener("click",()=>{this._showCreateForm=!0,this.render()});let i=t.getElementById("dismiss-token");i&&i.addEventListener("click",()=>{this._newToken=null,this.render()});let a=t.getElementById("submit-create");a&&a.addEventListener("click",()=>{let r=t.getElementById("create-name"),o=t.getElementById("create-role"),n=t.getElementById("create-expiration");this._createName=r?.value||"",this._createRole=o?.value||"read",this._createExpiration=n?.value||"",this._createKey()});let s=t.getElementById("cancel-create");s&&s.addEventListener("click",()=>{this._showCreateForm=!1,this.render()}),t.querySelectorAll('[data-action="delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=r.dataset.keyId,this.render()})}),t.querySelectorAll('[data-action="confirm-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._deleteKey(r.dataset.keyId)})}),t.querySelectorAll('[data-action="cancel-delete"]').forEach(r=>{r.addEventListener("click",()=>{this._confirmDeleteId=null,this.render()})}),t.querySelectorAll('[data-action="rotate"]').forEach(r=>{r.addEventListener("click",()=>{this._rotateKeyId=r.dataset.keyId,this.render()})}),t.querySelectorAll('[data-action="confirm-rotate"]').forEach(r=>{r.addEventListener("click",()=>{let o=t.getElementById(`rotate-grace-${r.dataset.keyId}`);this._rotateGracePeriod=o?.value||"24",this._rotateKey(r.dataset.keyId)})}),t.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",pt);function Ie(d){return d?d.slug&&d.name?`${d.name} (${d.slug})`:d.name||d.slug||"Unknown":"Unknown"}var ht=class extends h{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=t=>{this._dropdownOpen&&!this.contains(t.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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadData(){try{this._loading=!0;let t=await this._api._get("/api/v2/tenants");this._tenants=Array.isArray(t)?t:t?.tenants||[],this._error=null}catch(t){this._error=`Failed to load tenants: ${t.message}`}finally{this._loading=!1}this.render()}_toggleDropdown(){this._dropdownOpen=!this._dropdownOpen,this.render()}_selectTenant(t,e){this._selectedTenantId=t,this._dropdownOpen=!1,this.render(),this.dispatchEvent(new CustomEvent("tenant-changed",{detail:{tenantId:t,tenantName:e},bubbles:!0,composed:!0}))}_getSelectedTenant(){return this._selectedTenantId==null?null:this._tenants.find(t=>(t.id||t.slug)===this._selectedTenantId)||null}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getStyles(){return`
|
|
11385
11408
|
:host {
|
|
11386
11409
|
display: inline-block;
|
|
11387
11410
|
position: relative;
|
|
@@ -11515,7 +11538,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11515
11538
|
color: var(--loki-text-muted, #939084);
|
|
11516
11539
|
font-size: 12px;
|
|
11517
11540
|
}
|
|
11518
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._getSelectedTenant(),
|
|
11541
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._getSelectedTenant(),i=e?Ie(e):"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=`
|
|
11519
11542
|
<button class="dropdown-item all-tenants ${o?"selected":""}" data-tenant-id="">
|
|
11520
11543
|
<span class="tenant-name">All Tenants</span>
|
|
11521
11544
|
${o?'<span class="check-mark">*</span>':""}
|
|
@@ -11534,13 +11557,13 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11534
11557
|
`}s=`<div class="dropdown">${r}</div>`}t.innerHTML=`
|
|
11535
11558
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
11536
11559
|
<div class="tenant-switcher">
|
|
11537
|
-
<button class="trigger ${
|
|
11538
|
-
<span class="trigger-label">${this._escapeHtml(
|
|
11539
|
-
<span class="trigger-icon ${
|
|
11560
|
+
<button class="trigger ${a?"open":""}" id="trigger-btn">
|
|
11561
|
+
<span class="trigger-label">${this._escapeHtml(i)}</span>
|
|
11562
|
+
<span class="trigger-icon ${a?"open":""}">▼</span>
|
|
11540
11563
|
</button>
|
|
11541
11564
|
${s}
|
|
11542
11565
|
</div>
|
|
11543
|
-
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("trigger-btn");e&&e.addEventListener("click",
|
|
11566
|
+
`,this._attachEventListeners()}_attachEventListeners(){let t=this.shadowRoot;if(!t)return;let e=t.getElementById("trigger-btn");e&&e.addEventListener("click",i=>{i.stopPropagation(),this._toggleDropdown()}),t.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",ht);var Ht={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"}},Le=100,ut=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let t=await this._api._get("/api/v2/activity"),e=t.events||t.activities||[];if(e.length>0){let i=e.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,Le),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 t=Date.now();return[{id:"1",timestamp:new Date(t-2e3).toISOString(),message:"Build iteration #12 started",severity:"info",source:"runner"},{id:"2",timestamp:new Date(t-5e3).toISOString(),message:"Code review passed (3/3 reviewers)",severity:"success",source:"review"},{id:"3",timestamp:new Date(t-8e3).toISOString(),message:"Context window at 78% capacity",severity:"warning",source:"context"},{id:"4",timestamp:new Date(t-12e3).toISOString(),message:"Test suite completed: 42/42 passed",severity:"success",source:"testing"},{id:"5",timestamp:new Date(t-15e3).toISOString(),message:"RARV cycle: Verify phase complete",severity:"info",source:"rarv"}]}_formatTime(t){if(!t)return"";try{return new Date(t).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return""}}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_getFilteredItems(){return this._filter==="all"?this._items:this._items.filter(t=>t.severity===this._filter)}_setFilter(t){this._filter=t,this.render()}_bindEvents(){let t=this.shadowRoot;t.querySelectorAll(".filter-btn").forEach(i=>{i.addEventListener("click",()=>{this._setFilter(i.dataset.filter)})});let e=t.querySelector(".activity-feed");e&&(e.addEventListener("mouseenter",()=>{this._paused=!0}),e.addEventListener("mouseleave",()=>{this._paused=!1}))}_getStyles(){return`
|
|
11544
11567
|
:host {
|
|
11545
11568
|
display: block;
|
|
11546
11569
|
}
|
|
@@ -11726,7 +11749,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11726
11749
|
::-webkit-scrollbar-track { background: var(--loki-bg-primary, #FFFEFB); }
|
|
11727
11750
|
::-webkit-scrollbar-thumb { background: var(--loki-border, #ECEAE3); border-radius: 3px; }
|
|
11728
11751
|
::-webkit-scrollbar-thumb:hover { background: var(--loki-border-light, #C5C0B1); }
|
|
11729
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._getFilteredItems(),
|
|
11752
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e=this._getFilteredItems(),a=["all","info","success","warning","error"].map(r=>{let o=this._filter===r,n=r==="all"?"All":Ht[r]?.label||r;return`<button class="filter-btn ${o?"active":""}" data-filter="${r}">${n}</button>`}).join(""),s;if(e.length===0?s='<div class="empty-state">No activity to display</div>':s=e.map(r=>{let o=Ht[r.severity]||Ht.info;return`
|
|
11730
11753
|
<div class="activity-item ${r.isNew?"new-item":""}">
|
|
11731
11754
|
<div class="severity-band" style="background: ${o.color};"></div>
|
|
11732
11755
|
<div class="item-content">
|
|
@@ -11741,13 +11764,13 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11741
11764
|
<div class="stream-container">
|
|
11742
11765
|
<div class="header">
|
|
11743
11766
|
<h3 class="title">Activity Stream <span class="count-badge">${this._items.length}</span></h3>
|
|
11744
|
-
<div class="filter-bar">${
|
|
11767
|
+
<div class="filter-bar">${a}</div>
|
|
11745
11768
|
</div>
|
|
11746
11769
|
<div class="activity-feed">
|
|
11747
11770
|
${s}
|
|
11748
11771
|
</div>
|
|
11749
11772
|
</div>
|
|
11750
|
-
`,this._bindEvents(),!this._paused){let r=t.querySelector(".activity-feed");r&&(r.scrollTop=0)}}};customElements.get("loki-activity-stream")||customElements.define("loki-activity-stream",
|
|
11773
|
+
`,this._bindEvents(),!this._paused){let r=t.querySelector(".activity-feed");r&&(r.scrollTop=0)}}};customElements.get("loki-activity-stream")||customElements.define("loki-activity-stream",ut);var De={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)"}},Xt={healthy:"var(--loki-green, #1FC5A8)",degraded:"var(--loki-yellow, #D4A03C)",down:"var(--loki-red, #C45B5B)",unknown:"var(--loki-text-muted, #939084)"},gt=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),1e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let t=await this._api._get("/api/v2/providers/health");this._providers=t.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(t){return t==null?"--":t>=1e6?(t/1e6).toFixed(1)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":String(t)}_formatLatency(t){return t==null?"--":t<1e3?t+"ms":(t/1e3).toFixed(1)+"s"}_formatCost(t){return t==null?"--":"$"+t.toFixed(2)}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleExpand(t){this._expandedProvider=this._expandedProvider===t?null:t,this.render()}_bindEvents(){this.shadowRoot.querySelectorAll(".provider-card").forEach(e=>{e.addEventListener("click",()=>{this._toggleExpand(e.dataset.provider)})})}_getStyles(){return`
|
|
11751
11774
|
:host {
|
|
11752
11775
|
display: block;
|
|
11753
11776
|
}
|
|
@@ -11926,41 +11949,41 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11926
11949
|
border: 1px solid var(--loki-border, #ECEAE3);
|
|
11927
11950
|
border-radius: 5px;
|
|
11928
11951
|
}
|
|
11929
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e;this._providers.length===0?e='<div class="empty-state">No provider data available</div>':e=`<div class="provider-grid">${this._providers.map(
|
|
11930
|
-
<div class="provider-card ${r?"expanded":""}" data-provider="${this._escapeHtml(
|
|
11952
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e;this._providers.length===0?e='<div class="empty-state">No provider data available</div>':e=`<div class="provider-grid">${this._providers.map(i=>{let a=De[i.name]||{initial:(i.name??"?").charAt(0).toUpperCase(),color:"#939084",bgColor:"rgba(147, 144, 132, 0.12)"},s=Xt[i.status]||Xt.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`
|
|
11953
|
+
<div class="provider-card ${r?"expanded":""}" data-provider="${this._escapeHtml(i.name)}">
|
|
11931
11954
|
<div class="card-header">
|
|
11932
|
-
<div class="provider-icon" style="background: ${
|
|
11933
|
-
<span class="provider-name">${this._escapeHtml(
|
|
11934
|
-
<div class="status-dot ${
|
|
11955
|
+
<div class="provider-icon" style="background: ${a.bgColor}; color: ${a.color};">${a.initial}</div>
|
|
11956
|
+
<span class="provider-name">${this._escapeHtml(i.name)}</span>
|
|
11957
|
+
<div class="status-dot ${i.status==="healthy"?"pulse":""}" style="background: ${s};" title="${this._escapeHtml(i.status)}"></div>
|
|
11935
11958
|
</div>
|
|
11936
11959
|
<div class="card-metrics">
|
|
11937
11960
|
<div class="metric">
|
|
11938
11961
|
<span class="metric-label">Latency</span>
|
|
11939
|
-
<span class="metric-value">${this._formatLatency(
|
|
11962
|
+
<span class="metric-value">${this._formatLatency(i.latency_ms)}</span>
|
|
11940
11963
|
</div>
|
|
11941
11964
|
<div class="metric">
|
|
11942
11965
|
<span class="metric-label">Tokens</span>
|
|
11943
|
-
<span class="metric-value">${this._formatTokens(
|
|
11966
|
+
<span class="metric-value">${this._formatTokens(i.tokens_used)}</span>
|
|
11944
11967
|
</div>
|
|
11945
11968
|
</div>
|
|
11946
11969
|
${r?`
|
|
11947
11970
|
<div class="expand-details">
|
|
11948
11971
|
<div class="detail-row">
|
|
11949
11972
|
<span class="detail-label">Model</span>
|
|
11950
|
-
<span class="detail-value">${this._escapeHtml(
|
|
11973
|
+
<span class="detail-value">${this._escapeHtml(i.model||"--")}</span>
|
|
11951
11974
|
</div>
|
|
11952
11975
|
<div class="detail-row">
|
|
11953
11976
|
<span class="detail-label">API Version</span>
|
|
11954
|
-
<span class="detail-value">${this._escapeHtml(
|
|
11977
|
+
<span class="detail-value">${this._escapeHtml(i.api_version||"--")}</span>
|
|
11955
11978
|
</div>
|
|
11956
11979
|
<div class="detail-row">
|
|
11957
11980
|
<span class="detail-label">Cost</span>
|
|
11958
|
-
<span class="detail-value">${this._formatCost(
|
|
11981
|
+
<span class="detail-value">${this._formatCost(i.cost_usd)}</span>
|
|
11959
11982
|
</div>
|
|
11960
11983
|
<div class="detail-row">
|
|
11961
11984
|
<span class="detail-label">Rate Limit</span>
|
|
11962
|
-
<span class="detail-value">${
|
|
11963
|
-
${
|
|
11985
|
+
<span class="detail-value">${i.rate_limit?i.rate_limit.remaining+"/"+i.rate_limit.limit:"--"}</span>
|
|
11986
|
+
${i.rate_limit?`
|
|
11964
11987
|
<div class="rate-limit-bar">
|
|
11965
11988
|
<div class="rate-limit-fill" style="width: ${o}%; background: ${n};"></div>
|
|
11966
11989
|
</div>
|
|
@@ -11978,7 +12001,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
11978
12001
|
</div>
|
|
11979
12002
|
${e}
|
|
11980
12003
|
</div>
|
|
11981
|
-
`,this._bindEvents()}};customElements.get("loki-provider-health")||customElements.define("loki-provider-health",gt);var
|
|
12004
|
+
`,this._bindEvents()}};customElements.get("loki-provider-health")||customElements.define("loki-provider-health",gt);var Rt=[{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"}],Bt={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"}},vt=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),5e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let t=await this._api._get("/api/v2/pipeline/status");this._stages=t.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(t){return this._stages.find(e=>e.id===t)||{id:t,status:"waiting",errors:0}}_formatDuration(t){if(t==null||t<0)return"";if(t<1e3)return t+"ms";let e=Math.floor(t/1e3);if(e<60)return e+"s";let i=Math.floor(e/60),a=e%60;return i+"m "+a+"s"}_getStyles(){return`
|
|
11982
12005
|
:host {
|
|
11983
12006
|
display: block;
|
|
11984
12007
|
}
|
|
@@ -12141,22 +12164,22 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12141
12164
|
border-radius: 50%;
|
|
12142
12165
|
flex-shrink: 0;
|
|
12143
12166
|
}
|
|
12144
|
-
`}render(){let t=this.shadowRoot;if(!t)return;let e=
|
|
12167
|
+
`}render(){let t=this.shadowRoot;if(!t)return;let e=Rt.map((a,s)=>{let r=this._getStageData(a.id),o=Bt[r.status]||Bt.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,u=`
|
|
12145
12168
|
<div class="stage-node">
|
|
12146
12169
|
<div class="stage-circle ${l?"active":""}"
|
|
12147
12170
|
style="background: ${o.bgColor}; color: ${o.color}; border: 2px solid ${o.color};">
|
|
12148
12171
|
${p}
|
|
12149
12172
|
</div>
|
|
12150
|
-
<span class="stage-label">${
|
|
12173
|
+
<span class="stage-label">${a.label}</span>
|
|
12151
12174
|
${r.duration_ms?`<span class="stage-duration">${this._formatDuration(r.duration_ms)}</span>`:""}
|
|
12152
12175
|
${r.errors>0?`<span class="stage-error-count">${r.errors} error${r.errors>1?"s":""}</span>`:""}
|
|
12153
12176
|
</div>
|
|
12154
|
-
`;if(s<
|
|
12177
|
+
`;if(s<Rt.length-1){let b=this._getStageData(Rt[s+1].id),v=n,f=l||n&&(b.status==="active"||b.status==="waiting");return u+`
|
|
12155
12178
|
<div class="connector">
|
|
12156
|
-
<div class="connector-line ${
|
|
12179
|
+
<div class="connector-line ${v?"completed":l?"active":"pending"}"></div>
|
|
12157
12180
|
${l?'<div class="flow-dot"></div>':""}
|
|
12158
12181
|
</div>
|
|
12159
|
-
`}return u}).join(""),
|
|
12182
|
+
`}return u}).join(""),i=Object.entries(Bt).map(([a,s])=>`<div class="legend-item">
|
|
12160
12183
|
<div class="legend-dot" style="background: ${s.color};"></div>
|
|
12161
12184
|
<span>${s.label}</span>
|
|
12162
12185
|
</div>`).join("");t.innerHTML=`
|
|
@@ -12169,16 +12192,16 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12169
12192
|
${e}
|
|
12170
12193
|
</div>
|
|
12171
12194
|
<div class="status-legend">
|
|
12172
|
-
${
|
|
12195
|
+
${i}
|
|
12173
12196
|
</div>
|
|
12174
12197
|
</div>
|
|
12175
|
-
`}};customElements.get("loki-pipeline-view")||customElements.define("loki-pipeline-view",
|
|
12176
|
-
rx="3" fill="${
|
|
12177
|
-
fill="${
|
|
12178
|
-
stroke="${o}" stroke-width="${n}" opacity="${l}" />`}let p=`<text x="${e}" y="${
|
|
12198
|
+
`}};customElements.get("loki-pipeline-view")||customElements.define("loki-pipeline-view",vt);var mt={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 ze(d,t,e){let i=t/2,a=e/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 bt=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),15e3)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let t=await this._api._get("/api/v2/memory/graph");this._nodes=t.nodes||[],this._edges=t.edges||[]}catch{if(this._nodes.length===0){let t=this._getDemoData();this._nodes=t.nodes,this._edges=t.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(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_selectNode(t){this._selectedNode=this._selectedNode===t?null:t,this.render()}_bindEvents(){let t=this.shadowRoot;t.querySelectorAll(".graph-node").forEach(e=>{e.addEventListener("click",()=>{this._selectNode(e.dataset.nodeId)})}),t.querySelectorAll(".close-detail").forEach(e=>{e.addEventListener("click",()=>{this._selectedNode=null,this.render()})})}_renderNodeShape(t,e,i){let a=mt[t.type]||mt.episode,s=10+(t.importance||.5)*16,r=this._selectedNode===t.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="${e-s/2}" y="${i-s/2}" width="${s}" height="${s}"
|
|
12199
|
+
rx="3" fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break;case"diamond":{let u=s/2;c=`<polygon points="${e},${i-u} ${e+u},${i} ${e},${i+u} ${e-u},${i}"
|
|
12200
|
+
fill="${a.color}" fill-opacity="0.2" stroke="${o}" stroke-width="${n}" opacity="${l}" />`;break}default:c=`<circle cx="${e}" cy="${i}" r="${s/2}" fill="${a.color}" fill-opacity="0.2"
|
|
12201
|
+
stroke="${o}" stroke-width="${n}" opacity="${l}" />`}let p=`<text x="${e}" y="${i+s/2+14}" text-anchor="middle" font-size="10"
|
|
12179
12202
|
font-family="Inter, sans-serif" fill="var(--loki-text-secondary, #36342E)" opacity="${l}">${this._escapeHtml(t.label)}</text>`;return`<g class="graph-node" data-node-id="${this._escapeHtml(t.id)}" style="cursor: pointer;">
|
|
12180
12203
|
${c}${p}
|
|
12181
|
-
</g>`}_renderEdge(t,e){let
|
|
12204
|
+
</g>`}_renderEdge(t,e){let i=e.find(n=>n.id===t.source),a=e.find(n=>n.id===t.target);if(!i||!a)return"";let s=(t.strength||1)<.6,r=this._selectedNode?t.source===this._selectedNode||t.target===this._selectedNode?.8:.15:.4,o=s?'stroke-dasharray="4 4"':"";return`<line x1="${i.x}" y1="${i.y}" x2="${a.x}" y2="${a.y}"
|
|
12182
12205
|
stroke="var(--loki-border-light, #C5C0B1)" stroke-width="1.5" opacity="${r}" ${o} />`}_getStyles(){return`
|
|
12183
12206
|
:host {
|
|
12184
12207
|
display: block;
|
|
@@ -12333,7 +12356,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12333
12356
|
</div>
|
|
12334
12357
|
<div class="empty-state">No memory entries to visualize</div>
|
|
12335
12358
|
</div>
|
|
12336
|
-
`;return}let e=this._graphWidth,
|
|
12359
|
+
`;return}let e=this._graphWidth,i=this._graphHeight,a=ze(this._nodes,e,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=mt[l.type]||mt.episode;o=`
|
|
12337
12360
|
<div class="detail-panel">
|
|
12338
12361
|
<div class="detail-header">
|
|
12339
12362
|
<span class="detail-title">${this._escapeHtml(l.label)}</span>
|
|
@@ -12342,7 +12365,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12342
12365
|
</div>
|
|
12343
12366
|
<div class="detail-body">${this._escapeHtml(l.details||"No details available")}</div>
|
|
12344
12367
|
</div>
|
|
12345
|
-
`}}let n=Object.entries(
|
|
12368
|
+
`}}let n=Object.entries(mt).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">
|
|
12346
12369
|
<div class="legend-shape">${c}</div>
|
|
12347
12370
|
<span>${l.label}</span>
|
|
12348
12371
|
</div>`}).join("");t.innerHTML=`
|
|
@@ -12352,7 +12375,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12352
12375
|
<h3 class="title">Memory Network</h3>
|
|
12353
12376
|
</div>
|
|
12354
12377
|
<div class="graph-wrap">
|
|
12355
|
-
<svg class="graph-svg" viewBox="0 0 ${e} ${
|
|
12378
|
+
<svg class="graph-svg" viewBox="0 0 ${e} ${i}" xmlns="http://www.w3.org/2000/svg">
|
|
12356
12379
|
${s}
|
|
12357
12380
|
${r}
|
|
12358
12381
|
</svg>
|
|
@@ -12360,7 +12383,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12360
12383
|
</div>
|
|
12361
12384
|
<div class="legend">${n}</div>
|
|
12362
12385
|
</div>
|
|
12363
|
-
`,this._bindEvents()}};customElements.get("loki-memory-graph")||customElements.define("loki-memory-graph",bt);var
|
|
12386
|
+
`,this._bindEvents()}};customElements.get("loki-memory-graph")||customElements.define("loki-memory-graph",bt);var Pt={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"}},ft=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),1e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let t=await this._api._get("/api/v2/cost/breakdown");this._phases=t.phases||[],this._budget=t.budget_usd||null,this._totalCost=t.total_usd||this._phases.reduce((e,i)=>e+(i.cost_usd||0),0)}catch{this._phases.length===0&&(this._phases=this._getDemoData(),this._budget=10,this._totalCost=this._phases.reduce((t,e)=>t+e.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(t){return t==null?"--":"$"+t.toFixed(2)}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_bindEvents(){this.shadowRoot.querySelectorAll(".waterfall-bar").forEach(e=>{e.addEventListener("mouseenter",()=>{this._hoveredPhase=e.dataset.phase,this._updateTooltip(e)}),e.addEventListener("mouseleave",()=>{this._hoveredPhase=null,this._hideTooltip()})})}_updateTooltip(t){let e=this.shadowRoot.querySelector(".tooltip");if(!e)return;let i=this._phases.find(o=>o.phase===this._hoveredPhase);if(!i)return;let a=Pt[i.phase]||{label:i.phase};e.innerHTML=`<strong>${a.label}</strong>: ${this._formatCost(i.cost_usd)}`,e.style.display="block";let s=t.getBoundingClientRect(),r=this.shadowRoot.querySelector(".chart-area").getBoundingClientRect();e.style.left=s.left-r.left+s.width/2+"px",e.style.top=s.top-r.top-30+"px"}_hideTooltip(){let t=this.shadowRoot.querySelector(".tooltip");t&&(t.style.display="none")}_getStyles(){return`
|
|
12364
12387
|
:host {
|
|
12365
12388
|
display: block;
|
|
12366
12389
|
}
|
|
@@ -12550,7 +12573,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12550
12573
|
</div>
|
|
12551
12574
|
<div class="empty-state">No cost data available</div>
|
|
12552
12575
|
</div>
|
|
12553
|
-
`;return}let e=Math.max(...this._phases.map(l=>l.cost_usd||0),.01),
|
|
12576
|
+
`;return}let e=Math.max(...this._phases.map(l=>l.cost_usd||0),.01),i=160,a=this._budget?Math.max(e,this._budget):e,s=this._budget?this._budget/a*i:null,r=this._phases.map(l=>{let c=Pt[l.phase]||{color:"var(--loki-text-muted)",label:l.phase},p=(l.cost_usd||0)/a*i,u=this._hoveredPhase===l.phase;return`
|
|
12554
12577
|
<div class="bar-group">
|
|
12555
12578
|
<span class="bar-value">${this._formatCost(l.cost_usd)}</span>
|
|
12556
12579
|
<div class="waterfall-bar" data-phase="${this._escapeHtml(l.phase)}"
|
|
@@ -12562,7 +12585,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12562
12585
|
<div class="budget-line" style="bottom: ${s+40}px;">
|
|
12563
12586
|
<span class="budget-label">Budget: ${this._formatCost(this._budget)}</span>
|
|
12564
12587
|
</div>
|
|
12565
|
-
`:"",n=this._phases.map(l=>{let c=
|
|
12588
|
+
`:"",n=this._phases.map(l=>{let c=Pt[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">
|
|
12566
12589
|
<div class="summary-dot" style="background: ${c.color};"></div>
|
|
12567
12590
|
<span class="summary-label">${c.label}</span>
|
|
12568
12591
|
<span class="summary-value">${this._formatCost(l.cost_usd)} (${p}%)</span>
|
|
@@ -12584,7 +12607,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12584
12607
|
</div>
|
|
12585
12608
|
</div>
|
|
12586
12609
|
</div>
|
|
12587
|
-
`,this._bindEvents()}};customElements.get("loki-cost-waterfall")||customElements.define("loki-cost-waterfall",ft);var
|
|
12610
|
+
`,this._bindEvents()}};customElements.get("loki-cost-waterfall")||customElements.define("loki-cost-waterfall",ft);var He={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"}},kt=class extends h{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(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),1e4)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}async _loadData(){try{let e=(await this._api._get("/api/v2/agents/leaderboard")).agents||[],i={};e.forEach((a,s)=>{i[a.type||a.name]=s+1}),this._previousRanks={...this._currentRanks||{}},this._currentRanks=i,this._agents=e}catch{this._agents.length===0&&(this._agents=this._getDemoData(),this._currentRanks={},this._agents.forEach((t,e)=>{this._currentRanks[t.type]=e+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(t){let e=this._currentRanks?.[t],i=this._previousRanks?.[t];return e==null||i==null?0:i-e}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}_toggleAgent(t){this._expandedAgent=this._expandedAgent===t?null:t,this.render()}_bindEvents(){this.shadowRoot.querySelectorAll(".agent-row").forEach(e=>{e.addEventListener("click",()=>{this._toggleAgent(e.dataset.agent)})})}_getQualityColor(t){return t>=9?"var(--loki-green, #1FC5A8)":t>=8?"var(--loki-blue, #2F71E3)":t>=7?"var(--loki-yellow, #D4A03C)":"var(--loki-red, #C45B5B)"}_getSpeedLabel(t){return t==="fast"?{label:"Fast",color:"var(--loki-green, #1FC5A8)"}:t==="medium"?{label:"Medium",color:"var(--loki-yellow, #D4A03C)"}:{label:"Slow",color:"var(--loki-red, #C45B5B)"}}_getStyles(){return`
|
|
12588
12611
|
:host {
|
|
12589
12612
|
display: block;
|
|
12590
12613
|
}
|
|
@@ -12797,33 +12820,33 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12797
12820
|
</div>
|
|
12798
12821
|
<div class="empty-state">No agent performance data available</div>
|
|
12799
12822
|
</div>
|
|
12800
|
-
`;return}let e=this._agents.map((a
|
|
12823
|
+
`;return}let e=this._agents.map((i,a)=>{let s=a+1,r=He[s],o=i.type||i.name,n=this._getRankChange(o),l=this._expandedAgent===o,c=this._getQualityColor(i.quality),p=this._getSpeedLabel(i.speed),u=(i.quality||0)/10*100,b;r?b=`<div class="rank-badge" style="background: ${r.bg}; color: ${r.border};">${s}</div>`:b=`<span class="rank-number" style="color: var(--loki-text-muted);">${s}</span>`;let v="";n>0?v=`<span class="rank-change rank-up">+${n}</span>`:n<0&&(v=`<span class="rank-change rank-down">${n}</span>`);let f=l?`
|
|
12801
12824
|
<div class="agent-detail">
|
|
12802
12825
|
<div class="detail-metric">
|
|
12803
12826
|
<span class="detail-label">Total Cost</span>
|
|
12804
|
-
<span class="detail-value">$${(
|
|
12827
|
+
<span class="detail-value">$${(i.cost_usd||0).toFixed(2)}</span>
|
|
12805
12828
|
</div>
|
|
12806
12829
|
<div class="detail-metric">
|
|
12807
12830
|
<span class="detail-label">Avg Time/Task</span>
|
|
12808
|
-
<span class="detail-value">${
|
|
12831
|
+
<span class="detail-value">${i.avg_time||"--"}</span>
|
|
12809
12832
|
</div>
|
|
12810
12833
|
<div class="detail-metric">
|
|
12811
12834
|
<span class="detail-label">Success Rate</span>
|
|
12812
|
-
<span class="detail-value">${
|
|
12835
|
+
<span class="detail-value">${i.success_rate!=null?i.success_rate+"%":"--"}</span>
|
|
12813
12836
|
</div>
|
|
12814
12837
|
</div>
|
|
12815
12838
|
`:"";return`
|
|
12816
12839
|
<div class="agent-row ${s<=3?"top-3":""}" data-agent="${this._escapeHtml(o)}"
|
|
12817
12840
|
style="${r?"border-left-color: "+r.border+";":""}">
|
|
12818
|
-
<div class="rank-cell">${b}${
|
|
12841
|
+
<div class="rank-cell">${b}${v}</div>
|
|
12819
12842
|
<div class="agent-name-cell">
|
|
12820
|
-
<span class="agent-name">${this._escapeHtml(
|
|
12821
|
-
<span class="agent-type">${this._escapeHtml(
|
|
12843
|
+
<span class="agent-name">${this._escapeHtml(i.name||i.type)}</span>
|
|
12844
|
+
<span class="agent-type">${this._escapeHtml(i.type||"")}</span>
|
|
12822
12845
|
</div>
|
|
12823
|
-
<div class="metric-cell">${
|
|
12846
|
+
<div class="metric-cell">${i.tasks||0}</div>
|
|
12824
12847
|
<div class="metric-cell">
|
|
12825
12848
|
<div class="quality-score">
|
|
12826
|
-
<span style="color: ${c};">${(
|
|
12849
|
+
<span style="color: ${c};">${(i.quality||0).toFixed(1)}</span>
|
|
12827
12850
|
<div class="quality-bar"><div class="quality-fill" style="width: ${u}%; background: ${c};"></div></div>
|
|
12828
12851
|
</div>
|
|
12829
12852
|
</div>
|
|
@@ -12850,12 +12873,12 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12850
12873
|
${e}
|
|
12851
12874
|
</div>
|
|
12852
12875
|
</div>
|
|
12853
|
-
`,this._bindEvents()}};customElements.get("loki-agent-leaderboard")||customElements.define("loki-agent-leaderboard",kt);var
|
|
12876
|
+
`,this._bindEvents()}};customElements.get("loki-agent-leaderboard")||customElements.define("loki-agent-leaderboard",kt);var Zt=50,xt=class extends h{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(t,e,i){if(e!==i)switch(t){case"api-url":this._api&&(this._api.baseUrl=i,this._loadStatus());break;case"theme":this._applyTheme(),this.render();break}}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_stopPolling(){}async _loadStatus(){this._statusLoading=!0,this._statusError=null,this.render();try{this._status=await this._api.get("/api/managed/status")}catch(t){this._statusError=t&&t.message?t.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(t=Zt){this._eventsLoading=!0,this._eventsError=null,this.render();try{let e=await this._api.get("/api/managed/events?limit="+encodeURIComponent(t));Array.isArray(e)?(this._events=e,this._eventsCount=e.length,this._eventsSource=null):e&&typeof e=="object"?(this._events=Array.isArray(e.events)?e.events:[],this._eventsCount=typeof e.count=="number"?e.count:this._events.length,this._eventsSource=e.source||null):(this._events=[],this._eventsCount=0,this._eventsSource=null)}catch(e){this._eventsError=e&&e.message?e.message:"Failed to load managed events",this._events=[],this._eventsCount=0,this._eventsSource=null}finally{this._eventsLoading=!1,this.render()}}async _lookupMemoryVersion(){let t=(this._lookupId||"").trim();if(!t){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 e="/api/managed/memory_versions/"+encodeURIComponent(t);this._lookupResult=await this._api.get(e)}catch(e){this._lookupError=e&&e.message?e.message:"Failed to load memory versions",this._lookupResult=null}finally{this._lookupLoading=!1,this.render()}}_onLookupInput(t){this._lookupId=t&&t.target?t.target.value:""}_onLookupKeyDown(t){t&&t.key==="Enter"&&(t.preventDefault(),this._lookupMemoryVersion())}_attachEventHandlers(){let t=this.shadowRoot;if(!t)return;let e=t.querySelector("#refresh-status-btn");e&&e.addEventListener("click",()=>this._loadStatus());let i=t.querySelector("#refresh-events-btn");i&&i.addEventListener("click",()=>this._loadEvents());let a=t.querySelector("#lookup-input");a&&(a.addEventListener("input",r=>this._onLookupInput(r)),a.addEventListener("keydown",r=>this._onLookupKeyDown(r)));let s=t.querySelector("#lookup-btn");s&&s.addEventListener("click",()=>this._lookupMemoryVersion())}_escapeHtml(t){return t==null?"":String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_formatTimestamp(t){if(!t)return"";let e;return typeof t=="number"?e=new Date(t>1e12?t:t*1e3):e=new Date(t),Number.isNaN(e.getTime())?String(t):e.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`
|
|
12854
12877
|
<div class="error-banner" role="alert">
|
|
12855
12878
|
<strong>Status error:</strong>
|
|
12856
12879
|
<span>${this._escapeHtml(this._statusError)}</span>
|
|
12857
12880
|
</div>
|
|
12858
|
-
`;if(!this._status)return'<div class="status-row muted">No managed memory status available.</div>';let t=!!this._status.enabled,e=this._status.parent_flag,
|
|
12881
|
+
`;if(!this._status)return'<div class="status-row muted">No managed memory status available.</div>';let t=!!this._status.enabled,e=this._status.parent_flag,i=this._status.child_flags,a=this._status.beta_header,s=this._status.last_fallback_ts,r=i&&typeof i=="object"?Object.entries(i).map(([o,n])=>`${this._escapeHtml(o)}=${this._escapeHtml(n)}`).join(", "):i==null?"":String(i);return`
|
|
12859
12882
|
<div class="status-grid">
|
|
12860
12883
|
<div class="status-cell">
|
|
12861
12884
|
<div class="status-label">Enabled</div>
|
|
@@ -12871,7 +12894,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12871
12894
|
</div>
|
|
12872
12895
|
<div class="status-cell">
|
|
12873
12896
|
<div class="status-label">Beta header</div>
|
|
12874
|
-
<div class="status-value mono">${this._escapeHtml(
|
|
12897
|
+
<div class="status-value mono">${this._escapeHtml(a||"-")}</div>
|
|
12875
12898
|
</div>
|
|
12876
12899
|
<div class="status-cell">
|
|
12877
12900
|
<div class="status-label">Last fallback</div>
|
|
@@ -12892,9 +12915,9 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12892
12915
|
<strong>Events error:</strong>
|
|
12893
12916
|
<span>${this._escapeHtml(this._eventsError)}</span>
|
|
12894
12917
|
</div>
|
|
12895
|
-
`;if(!this._events.length)return'<div class="events-empty muted">No managed memory events recorded yet.</div>';let t=this._events.map(
|
|
12918
|
+
`;if(!this._events.length)return'<div class="events-empty muted">No managed memory events recorded yet.</div>';let t=this._events.map(i=>{let a=this._formatTimestamp(i&&(i.ts||i.timestamp||i.time)),s=i&&(i.type||i.event_type||i.kind||"event"),r=i&&(i.memory_id||i.memoryId||i.id||""),o=i&&(i.summary||i.message||i.detail||""),n=typeof o=="string"?o:JSON.stringify(o);return`
|
|
12896
12919
|
<tr>
|
|
12897
|
-
<td class="mono nowrap">${this._escapeHtml(
|
|
12920
|
+
<td class="mono nowrap">${this._escapeHtml(a)}</td>
|
|
12898
12921
|
<td><span class="badge">${this._escapeHtml(s)}</span></td>
|
|
12899
12922
|
<td class="mono">${this._escapeHtml(r)}</td>
|
|
12900
12923
|
<td>${this._escapeHtml(n)}</td>
|
|
@@ -12922,7 +12945,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
12922
12945
|
<strong>Lookup error:</strong>
|
|
12923
12946
|
<span>${this._escapeHtml(this._lookupError)}</span>
|
|
12924
12947
|
</div>
|
|
12925
|
-
`;else if(this._lookupResult!==null&&this._lookupResult!==void 0){let
|
|
12948
|
+
`;else if(this._lookupResult!==null&&this._lookupResult!==void 0){let i;try{i=JSON.stringify(this._lookupResult,null,2)}catch{i=String(this._lookupResult)}t=`<pre class="lookup-result mono">${this._escapeHtml(i)}</pre>`}return`
|
|
12926
12949
|
<div class="lookup-controls">
|
|
12927
12950
|
<input
|
|
12928
12951
|
id="lookup-input"
|
|
@@ -13229,7 +13252,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
13229
13252
|
${e?`
|
|
13230
13253
|
<div class="section">
|
|
13231
13254
|
<div class="panel-header">
|
|
13232
|
-
<h3 class="section-title">Recent events (limit ${
|
|
13255
|
+
<h3 class="section-title">Recent events (limit ${Zt})</h3>
|
|
13233
13256
|
<button id="refresh-events-btn" class="btn" type="button">Refresh events</button>
|
|
13234
13257
|
</div>
|
|
13235
13258
|
${this._renderEventsSection()}
|
|
@@ -13241,7 +13264,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
13241
13264
|
</div>
|
|
13242
13265
|
`:this._statusError?"":this._renderDisabledNotice()}
|
|
13243
13266
|
</div>
|
|
13244
|
-
`,this._attachEventHandlers()}};customElements.get("loki-managed-memory-panel")||customElements.define("loki-managed-memory-panel",xt);var _t=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._items=[],this._loading=!1,this._error=null,this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadList(),this._pollInterval=setInterval(()=>this._loadList(),1e4)}disconnectedCallback(){super.disconnectedCallback(),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}attributeChangedCallback(t,e,
|
|
13267
|
+
`,this._attachEventHandlers()}};customElements.get("loki-managed-memory-panel")||customElements.define("loki-managed-memory-panel",xt);var _t=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._items=[],this._loading=!1,this._error=null,this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadList(),this._pollInterval=setInterval(()=>this._loadList(),1e4)}disconnectedCallback(){super.disconnectedCallback(),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadList()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||(typeof window<"u"?window.location.origin:"");this._api=g({baseUrl:t})}async _loadList(){this._loading=!0,this._error=null;try{let t=await this._api.get("/api/escalations");this._items=Array.isArray(t&&t.escalations)?t.escalations:[]}catch(t){this._error=t&&t.message?t.message:String(t),this._items=[]}finally{this._loading=!1,this.render()}}async _openFile(t){this._activeFile=t,this._activeBody=null,this._activeBodyError=null,this.render();try{let e=(this._api.baseUrl||"")+"/api/escalations/"+encodeURIComponent(t),i=await fetch(e,{credentials:"include"});if(!i.ok)throw new Error("HTTP "+i.status);this._activeBody=await i.text()}catch(e){this._activeBodyError=e&&e.message?e.message:String(e)}this.render()}_closeFile(){this._activeFile=null,this._activeBody=null,this._activeBodyError=null,this.render()}_formatSize(t){return typeof t!="number"?"--":t<1024?t+" B":t<1024*1024?(t/1024).toFixed(1)+" KB":(t/(1024*1024)).toFixed(1)+" MB"}_formatDate(t){if(!t)return"--";try{let e=new Date(t);return isNaN(e.getTime())?t:e.toLocaleString()}catch{return t}}_escapeHtml(t){return t==null?"":String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}render(){let t=this.shadowRoot||this;if(!t)return;let e=`
|
|
13245
13268
|
<style>
|
|
13246
13269
|
:host { display: block; }
|
|
13247
13270
|
.esc-wrapper {
|
|
@@ -13311,7 +13334,7 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
13311
13334
|
border-radius: 4px;
|
|
13312
13335
|
}
|
|
13313
13336
|
</style>
|
|
13314
|
-
`,
|
|
13337
|
+
`,i="";this._loading&&this._items.length===0?i='<div class="esc-empty">Loading escalations...</div>':this._error?i='<div class="esc-error">Failed to load escalations: '+this._escapeHtml(this._error)+"</div>":!this._items||this._items.length===0?i='<div class="esc-empty">Escalations: no events yet. Handoff/escalation markdown documents written by the runner under .loki/escalations/ will appear here.</div>':i='<div class="esc-list">'+this._items.map(n=>{let l=this._escapeHtml(n.filename||""),c=this._escapeHtml(this._formatSize(n.size_bytes)),p=this._escapeHtml(this._formatDate(n.modified_at));return'<div class="esc-item" data-filename="'+l+'"><span class="esc-name">'+l+'</span><span class="esc-meta">'+c+" · "+p+"</span></div>"}).join("")+"</div>";let a="";if(this._activeFile){let o=this._escapeHtml(this._activeFile),n;this._activeBodyError?n='<div class="esc-error">Failed to load: '+this._escapeHtml(this._activeBodyError)+"</div>":this._activeBody===null?n='<div class="esc-body">Loading '+o+"...</div>":n='<div class="esc-body">'+this._escapeHtml(this._activeBody)+"</div>",a='<div class="esc-viewer"><div class="esc-viewer-header"><span class="esc-name">'+o+'</span><button class="esc-close-btn" data-action="close">Close</button></div>'+n+"</div>"}t.innerHTML=e+'<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>",t.querySelectorAll(".esc-item").forEach(o=>{o.addEventListener("click",()=>{let n=o.getAttribute("data-filename");n&&this._openFile(n)})});let r=t.querySelector('.esc-close-btn[data-action="close"]');r&&r.addEventListener("click",()=>this._closeFile())}};typeof customElements<"u"&&!customElements.get("loki-escalations")&&customElements.define("loki-escalations",_t);var yt=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._transcripts=[],this._hookEvents=[],this._loading=!1,this._error=null,this._api=null,this._pollInterval=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._load(),this._pollInterval=setInterval(()=>this._load(),3e4)}disconnectedCallback(){super.disconnectedCallback(),this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._load()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||(typeof window<"u"?window.location.origin:"");this._api=g({baseUrl:t})}async _load(){this._loading=!0,this._error=null;try{let t=await this._api.get("/api/council/transcripts?limit=10");this._transcripts=Array.isArray(t&&t.transcripts)?t.transcripts:[]}catch(t){this._error=t&&t.message?t.message:String(t),this._transcripts=[]}try{let t=await this._api.get("/api/council/transcripts?limit=20&type_prefix=claude_hook_");this._hookEvents=Array.isArray(t&&t.hook_events)?t.hook_events:[]}catch{this._hookEvents=[]}finally{this._loading=!1,this.render()}}_escapeHtml(t){return t==null?"":String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_formatTimestamp(t){if(!t)return"--";try{let e=new Date(t);return isNaN(e.getTime())?t:e.toLocaleString()}catch{return t}}_truncate(t,e){if(!t)return"";let i=String(t);return i.length>e?i.slice(0,e)+"...":i}_verdictBadgeHtml(t){let e=String(t||"").toUpperCase();return e==="APPROVE"?'<span class="ct-badge ct-badge-approve">APPROVE</span>':e==="REJECT"?'<span class="ct-badge ct-badge-reject">REJECT</span>':e==="CANNOT_VALIDATE"?'<span class="ct-badge ct-badge-cannot">CANNOT_VALIDATE</span>':'<span class="ct-badge ct-badge-unknown">'+this._escapeHtml(e||"UNKNOWN")+"</span>"}_outcomeBadgeHtml(t){let e=String(t||"").toUpperCase();return e==="APPROVED"?'<span class="ct-badge ct-badge-approve">APPROVED</span>':e==="REJECTED"?'<span class="ct-badge ct-badge-reject">REJECTED</span>':e==="BLOCKED_BY_GATE"?'<span class="ct-badge ct-badge-blocked">BLOCKED BY GATE</span>':'<span class="ct-badge ct-badge-unknown">'+this._escapeHtml(e||"UNKNOWN")+"</span>"}_voterRowHtml(t,e){let i=t.is_contrarian===!0,a=i&&e===!0,s="ct-voter-row";i&&(s+=" ct-voter-contrarian"),a&&(s+=" ct-voter-flipped");let r=this._escapeHtml(t.name||"unknown"),o=this._verdictBadgeHtml(t.verdict),n=this._escapeHtml(this._truncate(t.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&&t.triggered&&(l=`<span class="ct-badge ct-badge-da">DEVIL'S ADVOCATE</span>`);let p="";i&&Array.isArray(t.challenges)&&t.challenges.length>0&&(p='<ul class="ct-challenges">'+t.challenges.map(v=>"<li>"+this._escapeHtml(String(v))+"</li>").join("")+"</ul>");let u="";return Array.isArray(t.issues)&&t.issues.length>0&&(u='<ul class="ct-issues">'+t.issues.map(v=>{let f=this._escapeHtml(v.severity||""),x=this._escapeHtml(v.description||"");return'<li><span class="ct-issue-sev ct-issue-sev-'+f.toLowerCase()+'">'+f+"</span> "+x+"</li>"}).join("")+"</ul>"),'<div class="'+s+'"><div class="ct-voter-header"><span class="ct-voter-name">'+r+"</span>"+o+l+"</div>"+(n?'<div class="ct-voter-reason">'+n+"</div>":"")+p+u+c+"</div>"}_transcriptCardHtml(t){let e=this._escapeHtml(String(t.iteration||"--")),i=this._escapeHtml(this._formatTimestamp(t.timestamp)),a=this._escapeHtml(this._truncate(t.task_or_prd,200)),s=this._outcomeBadgeHtml(t.outcome),r=Array.isArray(t.voters)?t.voters:[],o=r.filter(v=>!v.is_contrarian),n=r.filter(v=>v.is_contrarian),l=o.map(v=>this._voterRowHtml(v,!1)).join(""),c="";t.contrarian_triggered&&(c='<div class="ct-contrarian-section"><div class="ct-section-label">Anti-Sycophancy Check</div>'+n.map(f=>this._voterRowHtml(f,t.contrarian_flipped)).join("")+"</div>");let p=typeof t.approve_count=="number"?t.approve_count:"--",u=typeof t.reject_count=="number"?t.reject_count:"--",b=typeof t.threshold=="number"?t.threshold:"--";return'<div class="ct-card"><div class="ct-card-header"><div class="ct-card-meta"><span class="ct-iter-label">Iteration '+e+'</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: "+u+" · Threshold: "+b+'</div><div class="ct-voters">'+l+"</div>"+c+"</div>"}render(){let t=this.shadowRoot||this;if(!t)return;let e=`
|
|
13315
13338
|
<style>
|
|
13316
13339
|
:host { display: block; margin-top: 24px; }
|
|
13317
13340
|
.ct-wrapper {
|
|
@@ -13480,7 +13503,59 @@ var LokiDashboard=(()=>{var wt=Object.defineProperty;var ae=Object.getOwnPropert
|
|
|
13480
13503
|
.ct-badge-da { background: #fdf3d4; color: #8a6c0e; }
|
|
13481
13504
|
.ct-badge-unknown { background: var(--bg-secondary, #F8F4F0); color: var(--text-muted, #939084); }
|
|
13482
13505
|
</style>
|
|
13483
|
-
`,
|
|
13506
|
+
`,i="";this._loading&&this._transcripts.length===0?i='<div class="ct-empty">Loading council transcripts...</div>':this._error?i='<div class="ct-error">Failed to load transcripts: '+this._escapeHtml(this._error)+"</div>":!this._transcripts||this._transcripts.length===0?i='<div class="ct-empty">No council rounds recorded yet -- transcripts appear after the first iteration vote.</div>':i='<div class="ct-list">'+this._transcripts.map(s=>this._transcriptCardHtml(s)).join("")+"</div>",t.innerHTML=e+'<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 t=Array.isArray(this._hookEvents)?this._hookEvents:[],e;return t.length===0?e='<div class="ct-empty">No live tool activity yet -- Claude hook events stream here while a run is active.</div>':e='<div class="ct-voters">'+t.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>'+e}};typeof customElements<"u"&&!customElements.get("loki-council-transcripts")&&customElements.define("loki-council-transcripts",yt);var Re=[{id:"overview",label:"Overview"},{id:"architecture",label:"Architecture"},{id:"modules",label:"Key Modules"},{id:"data-flow",label:"Data Flow"},{id:"ask",label:"Ask"}],wt=class extends h{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._activeTab="overview",this._loading=!1,this._error=null,this._api=null,this._meta=null,this._sectionCache={},this._question="",this._answer=null,this._asking=!1,this._askError=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadMeta()}attributeChangedCallback(t,e,i){t==="api-url"&&this._api&&(this._api.baseUrl=i)}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}async _loadMeta(){this._loading=!0,this._error=null,this.render();try{this._meta=await this._api._get("/api/wiki")}catch(t){this._error=t&&t.message?t.message:"Failed to load wiki"}finally{this._loading=!1,this.render()}}async _loadSection(t){if(this._sectionCache[t])return this._sectionCache[t];try{let e=await this._api._get(`/api/wiki/${encodeURIComponent(t)}`);return this._sectionCache[t]=e,e}catch(e){return this._sectionCache[t]={error:e&&e.message||"load failed"},this._sectionCache[t]}}async _selectTab(t){this._activeTab=t,(t==="architecture"||t==="modules"||t==="data-flow")&&(this.render(),await this._loadSection(t)),this.render()}async _ask(){let t=(this._question||"").trim();if(t){this._asking=!0,this._askError=null,this._answer=null,this.render();try{this._answer=await this._api._post("/api/wiki/ask",{question:t})}catch(e){this._askError=e&&e.message?e.message:"Ask failed"}finally{this._asking=!1,this.render()}}}_esc(t){return String(t??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}_renderCitations(t){return!t||!t.length?"":`<div class="cites"><strong>Sources:</strong><ul>${t.map(i=>`<li><code>${this._esc(i.file)}:${this._esc(i.line)}</code></li>`).join("")}</ul></div>`}_renderOverview(){let t=this._meta;if(!t||!t.generated)return`<div class="empty">
|
|
13507
|
+
<p>No wiki has been generated for this project yet.</p>
|
|
13508
|
+
<p>Run <code>loki wiki generate</code> to build a cited codebase wiki.</p>
|
|
13509
|
+
</div>`;let e=(t.sections||[]).map(i=>`<li>${this._esc(i.title)} <span class="dim">(${this._esc(i.citation_count)} citations)</span></li>`).join("");return`<div class="overview">
|
|
13510
|
+
<p><strong>${this._esc(t.project||"Project")}</strong> wiki -
|
|
13511
|
+
${this._esc(t.file_count||0)} source files indexed.</p>
|
|
13512
|
+
<p class="dim">Generated: ${this._esc(t.generated_at||"unknown")}</p>
|
|
13513
|
+
<ul>${e}</ul>
|
|
13514
|
+
</div>`}_renderSection(t){let e=this._sectionCache[t];return e?e.error?`<div class="error">${this._esc(e.error)}</div>`:`<div class="section">
|
|
13515
|
+
<h3>${this._esc(e.title)}</h3>
|
|
13516
|
+
<pre class="body">${this._esc(e.body)}</pre>
|
|
13517
|
+
${this._renderCitations(e.citations)}
|
|
13518
|
+
</div>`:'<div class="empty">Loading...</div>'}_renderAsk(){let t="";if(this._asking)t='<div class="empty">Searching the codebase...</div>';else if(this._askError)t=`<div class="error">${this._esc(this._askError)}</div>`;else if(this._answer){let e=this._answer.note?`<p class="dim">${this._esc(this._answer.note)}</p>`:"";t=`<div class="answer">
|
|
13519
|
+
<pre class="body">${this._esc(this._answer.answer||"")}</pre>
|
|
13520
|
+
${e}
|
|
13521
|
+
${this._renderCitations(this._answer.citations)}
|
|
13522
|
+
</div>`}return`<div class="ask">
|
|
13523
|
+
<div class="ask-row">
|
|
13524
|
+
<input id="wiki-q" type="text" placeholder="Ask about this codebase..."
|
|
13525
|
+
value="${this._esc(this._question)}" />
|
|
13526
|
+
<button id="wiki-ask-btn">Ask</button>
|
|
13527
|
+
</div>
|
|
13528
|
+
<p class="dim">Answers are grounded in the indexed codebase and cite real file:line locations.</p>
|
|
13529
|
+
${t}
|
|
13530
|
+
</div>`}_renderBody(){if(this._loading)return'<div class="empty">Loading wiki...</div>';if(this._error)return`<div class="error">${this._esc(this._error)}</div>`;switch(this._activeTab){case"overview":return this._renderOverview();case"architecture":return this._renderSection("architecture");case"modules":return this._renderSection("modules");case"data-flow":return this._renderSection("data-flow");case"ask":return this._renderAsk();default:return this._renderOverview()}}render(){if(!this.shadowRoot)return;let t=Re.map(a=>`<button class="tab ${a.id===this._activeTab?"active":""}"
|
|
13531
|
+
data-tab="${a.id}">${this._esc(a.label)}</button>`).join("");this.shadowRoot.innerHTML=`
|
|
13532
|
+
<style>
|
|
13533
|
+
:host { display: block; font-family: var(--loki-font, system-ui, sans-serif);
|
|
13534
|
+
color: var(--loki-fg, #1a1a1a); }
|
|
13535
|
+
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--loki-border, #ddd);
|
|
13536
|
+
margin-bottom: 12px; flex-wrap: wrap; }
|
|
13537
|
+
.tab { background: none; border: none; padding: 8px 14px; cursor: pointer;
|
|
13538
|
+
font-size: 0.9rem; color: var(--loki-fg-dim, #666); border-bottom: 2px solid transparent; }
|
|
13539
|
+
.tab.active { color: var(--loki-accent, #2563eb); border-bottom-color: var(--loki-accent, #2563eb); }
|
|
13540
|
+
.body { white-space: pre-wrap; word-break: break-word; font-family: inherit;
|
|
13541
|
+
background: var(--loki-bg-alt, #f6f8fa); padding: 12px; border-radius: 6px; }
|
|
13542
|
+
.cites { margin-top: 10px; font-size: 0.85rem; }
|
|
13543
|
+
.cites ul { margin: 4px 0 0; padding-left: 18px; }
|
|
13544
|
+
code { font-family: ui-monospace, monospace; font-size: 0.85em;
|
|
13545
|
+
background: var(--loki-bg-alt, #eef); padding: 1px 4px; border-radius: 3px; }
|
|
13546
|
+
.dim { color: var(--loki-fg-dim, #888); }
|
|
13547
|
+
.empty, .error { padding: 16px; }
|
|
13548
|
+
.error { color: var(--loki-danger, #c00); }
|
|
13549
|
+
.ask-row { display: flex; gap: 8px; margin-bottom: 8px; }
|
|
13550
|
+
#wiki-q { flex: 1; padding: 8px; border: 1px solid var(--loki-border, #ccc);
|
|
13551
|
+
border-radius: 6px; font-size: 0.9rem; }
|
|
13552
|
+
#wiki-ask-btn { padding: 8px 16px; border: none; border-radius: 6px;
|
|
13553
|
+
background: var(--loki-accent, #2563eb); color: #fff; cursor: pointer; }
|
|
13554
|
+
h3 { margin-top: 0; }
|
|
13555
|
+
</style>
|
|
13556
|
+
<div class="tabs">${t}</div>
|
|
13557
|
+
<div class="content">${this._renderBody()}</div>
|
|
13558
|
+
`,this.shadowRoot.querySelectorAll(".tab").forEach(a=>{a.addEventListener("click",()=>this._selectTab(a.dataset.tab))});let e=this.shadowRoot.getElementById("wiki-q");e&&(e.addEventListener("input",a=>{this._question=a.target.value}),e.addEventListener("keydown",a=>{a.key==="Enter"&&this._ask()}));let i=this.shadowRoot.getElementById("wiki-ask-btn");i&&i.addEventListener("click",()=>this._ask())}};customElements.get("loki-wiki-browser")||customElements.define("loki-wiki-browser",wt);var Be="1.4.0";function Pe(d={}){return d.theme?_.setTheme(d.theme):d.autoDetectContext!==!1?_.init():R.init(),d.apiUrl&&g({baseUrl:d.apiUrl}),{theme:_.getTheme(),context:_.detectContext()}}return de(Me);})();
|
|
13484
13559
|
|
|
13485
13560
|
|
|
13486
13561
|
// Initialize dashboard when DOM is ready
|
|
@@ -13623,7 +13698,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
13623
13698
|
'migration-dashboard',
|
|
13624
13699
|
'analytics-dashboard',
|
|
13625
13700
|
'escalations-panel',
|
|
13626
|
-
'council-transcripts'
|
|
13701
|
+
'council-transcripts',
|
|
13702
|
+
'wiki-browser'
|
|
13627
13703
|
];
|
|
13628
13704
|
components.forEach(function(id) {
|
|
13629
13705
|
var el = document.getElementById(id);
|