claude-mpm 4.0.25__py3-none-any.whl → 4.0.29__py3-none-any.whl
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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/templates/agent-manager.json +24 -0
- claude_mpm/agents/templates/agent-manager.md +304 -0
- claude_mpm/cli/__init__.py +2 -0
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_manager.py +517 -0
- claude_mpm/cli/commands/memory.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +247 -0
- claude_mpm/cli/parsers/base_parser.py +7 -0
- claude_mpm/cli/shared/__init__.py +1 -1
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +3 -2
- claude_mpm/core/constants.py +2 -2
- claude_mpm/core/socketio_pool.py +2 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/built/dashboard.js +1 -1
- claude_mpm/dashboard/static/built/socket-client.js +1 -1
- claude_mpm/dashboard/static/css/dashboard.css +170 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/dashboard.js +1 -1
- claude_mpm/dashboard/static/dist/socket-client.js +1 -1
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +21 -3
- claude_mpm/dashboard/static/js/components/module-viewer.js +129 -1
- claude_mpm/dashboard/static/js/dashboard.js +116 -0
- claude_mpm/dashboard/static/js/socket-client.js +0 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +1 -1
- claude_mpm/hooks/claude_hooks/hook_handler.py +1 -1
- claude_mpm/services/agents/agent_builder.py +455 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +7 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +10 -3
- claude_mpm/services/memory/__init__.py +2 -0
- claude_mpm/services/socketio/handlers/connection.py +27 -33
- {claude_mpm-4.0.25.dist-info → claude_mpm-4.0.29.dist-info}/METADATA +1 -1
- {claude_mpm-4.0.25.dist-info → claude_mpm-4.0.29.dist-info}/RECORD +40 -35
- /claude_mpm/cli/shared/{command_base.py → base_command.py} +0 -0
- {claude_mpm-4.0.25.dist-info → claude_mpm-4.0.29.dist-info}/WHEEL +0 -0
- {claude_mpm-4.0.25.dist-info → claude_mpm-4.0.29.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.0.25.dist-info → claude_mpm-4.0.29.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.0.25.dist-info → claude_mpm-4.0.29.dist-info}/top_level.txt +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{S as e,U as t}from"./socket-client.js";import{E as n,a as i}from"./components/event-viewer.js";import{M as o}from"./components/module-viewer.js";import{S as s}from"./components/session-manager.js";import{A as r}from"./components/agent-inference.js";import{E as a}from"./components/export-manager.js";import{W as l}from"./components/working-directory.js";import{F as c}from"./components/file-tool-tracker.js";class d{constructor(){this.eventViewer=null,this.moduleViewer=null,this.sessionManager=null,this.socketManager=null,this.agentInference=null,this.uiStateManager=null,this.eventProcessor=null,this.exportManager=null,this.workingDirectoryManager=null,this.fileToolTracker=null,this.init()}init(){console.log("Initializing refactored Claude MPM Dashboard..."),this.initializeSocketManager(),this.initializeCoreComponents(),this.initializeAgentInference(),this.initializeUIStateManager(),this.initializeWorkingDirectoryManager(),this.initializeFileToolTracker(),this.initializeEventProcessor(),this.initializeExportManager(),this.setupModuleInteractions(),this.initializeFromURL(),console.log("Claude MPM Dashboard initialized successfully")}initializeSocketManager(){this.socketManager=new e,this.socketManager.setupConnectionControls(),this.socketClient=this.socketManager.getSocketClient(),window.socketClient=this.socketClient}initializeCoreComponents(){this.eventViewer=new n("events-list",this.socketClient),this.moduleViewer=new o,this.sessionManager=new s(this.socketClient),window.eventViewer=this.eventViewer,window.moduleViewer=this.moduleViewer,window.sessionManager=this.sessionManager}initializeAgentInference(){this.agentInference=new r(this.eventViewer),this.agentInference.initialize()}initializeUIStateManager(){this.uiStateManager=new t,this.setupTabFilters()}initializeWorkingDirectoryManager(){this.workingDirectoryManager=new l(this.socketManager)}initializeFileToolTracker(){this.fileToolTracker=new c(this.agentInference,this.workingDirectoryManager)}initializeEventProcessor(){this.eventProcessor=new i(this.eventViewer,this.agentInference)}initializeExportManager(){this.exportManager=new a(this.eventViewer)}setupModuleInteractions(){this.socketManager.onEventUpdate(e=>{this.fileToolTracker.updateFileOperations(e),this.fileToolTracker.updateToolCalls(e),this.agentInference.processAgentInference(),"events"===this.uiStateManager.getCurrentTab()&&this.exportManager.scrollListToBottom("events-list"),this.renderCurrentTab()}),this.socketManager.onConnectionStatusChange((e,t)=>{"connected"===t&&this.workingDirectoryManager.updateGitBranch(this.workingDirectoryManager.getCurrentWorkingDir())}),document.addEventListener("tabChanged",e=>{this.renderCurrentTab(),this.uiStateManager.updateTabNavigationItems()}),document.addEventListener("eventsClearing",()=>{this.fileToolTracker.clear(),this.agentInference.initialize()}),document.addEventListener("showCardDetails",e=>{this.showCardDetails(e.detail.tabName,e.detail.index)}),document.addEventListener("sessionFilterChanged",e=>{console.log("Session filter changed, re-rendering current tab:",this.uiStateManager.getCurrentTab()),this.renderCurrentTab()})}setupTabFilters(){const e=document.getElementById("agents-search-input"),t=document.getElementById("agents-type-filter");e&&e.addEventListener("input",()=>{"agents"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),t&&t.addEventListener("change",()=>{"agents"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()});const n=document.getElementById("tools-search-input"),i=document.getElementById("tools-type-filter");n&&n.addEventListener("input",()=>{"tools"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),i&&i.addEventListener("change",()=>{"tools"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()});const o=document.getElementById("files-search-input"),s=document.getElementById("files-type-filter");o&&o.addEventListener("input",()=>{"files"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),s&&s.addEventListener("change",()=>{"files"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()})}initializeFromURL(){const e=new URLSearchParams(window.location.search);this.socketManager.initializeFromURL(e)}renderCurrentTab(){const e=this.uiStateManager.getCurrentTab();switch(e){case"events":break;case"agents":this.renderAgents();break;case"tools":this.renderTools();break;case"files":this.renderFiles()}this.uiStateManager.getSelectedCard().tab===e&&this.uiStateManager.updateCardSelectionUI(),this.uiStateManager.updateUnifiedSelectionUI()}renderAgents(){const e=document.getElementById("agents-list");if(!e)return;this.agentInference.processAgentInference();const t=this.eventProcessor.getFilteredEventsForTab("agents"),n=this.eventProcessor.generateAgentHTML(t);e.innerHTML=n,this.exportManager.scrollListToBottom("agents-list");const i=this.agentInference.getUniqueAgentInstances();this.updateAgentsFilterDropdowns(i)}renderTools(){const e=document.getElementById("tools-list");if(!e)return;const t=this.fileToolTracker.getToolCalls(),n=Array.from(t.entries()),i=this.eventProcessor.getUniqueToolInstances(n),o=this.eventProcessor.generateToolHTML(i);e.innerHTML=o,this.exportManager.scrollListToBottom("tools-list"),this.updateToolsFilterDropdowns(i)}renderFiles(){const e=document.getElementById("files-list");if(!e)return;const t=this.fileToolTracker.getFileOperations(),n=Array.from(t.entries()),i=this.eventProcessor.getUniqueFileInstances(n),o=this.eventProcessor.generateFileHTML(i);e.innerHTML=o,this.exportManager.scrollListToBottom("files-list"),this.updateFilesFilterDropdowns(n)}updateAgentsFilterDropdowns(e){const t=new Set;e.forEach(e=>{e.agentName&&"Unknown"!==e.agentName&&t.add(e.agentName)});const n=Array.from(t).filter(e=>e&&""!==e.trim());this.populateFilterDropdown("agents-type-filter",n,"All Agent Types"),n.length>0?console.log("Agent types found for filter:",n):console.log("No agent types found for filter. Instances:",e.length)}updateToolsFilterDropdowns(e){const t=[...new Set(e.map(([e,t])=>t.tool_name))].filter(e=>e);this.populateFilterDropdown("tools-type-filter",t,"All Tools")}updateFilesFilterDropdowns(e){const t=[...new Set(e.flatMap(([e,t])=>t.operations.map(e=>e.operation)))].filter(e=>e);this.populateFilterDropdown("files-type-filter",t,"All Operations")}populateFilterDropdown(e,t,n="All"){const i=document.getElementById(e);if(!i)return;const o=i.value,s=t.sort((e,t)=>e.localeCompare(t));i.innerHTML=`<option value="">${n}</option>`,s.forEach(e=>{const t=document.createElement("option");t.value=e,t.textContent=e,i.appendChild(t)}),o&&s.includes(o)&&(i.value=o)}showCardDetails(e,t){switch(e){case"events":this.eventViewer&&this.eventViewer.showEventDetails(t);break;case"agents":this.showAgentDetailsByIndex(t);break;case"tools":this.showToolDetailsByIndex(t);break;case"files":this.showFileDetailsByIndex(t)}}showAgentDetailsByIndex(e){const t=this.eventProcessor.getFilteredEventsForTab("agents");if(!t||!Array.isArray(t)||e<0||e>=t.length)return void console.warn("Dashboard: Invalid agent index or events array");const n=this.eventProcessor.applyAgentsFilters([t[e]]);if(n.length>0&&this.moduleViewer&&"function"==typeof this.moduleViewer.showAgentEvent){const t=n[0];this.moduleViewer.showAgentEvent(t,e)}}showAgentInstanceDetails(e){const t=this.agentInference.getPMDelegations().get(e);if(!t){const t=this.agentInference.getUniqueAgentInstances().find(t=>t.id===e);return t?void this.showImpliedAgentDetails(t):void console.error("Agent instance not found:",e)}this.moduleViewer&&"function"==typeof this.moduleViewer.showAgentInstance?this.moduleViewer.showAgentInstance(t):console.log("Agent Instance Details:",{id:e,agentName:t.agentName,type:"PM Delegation",eventCount:t.agentEvents.length,startTime:t.timestamp,pmCall:t.pmCall})}showImpliedAgentDetails(e){this.moduleViewer&&"function"==typeof this.moduleViewer.showImpliedAgent?this.moduleViewer.showImpliedAgent(e):console.log("Implied Agent Details:",{id:e.id,agentName:e.agentName,type:"Implied PM Delegation",eventCount:e.eventCount,startTime:e.timestamp,note:"No explicit PM call found - inferred from agent activity"})}showToolDetailsByIndex(e){const t=this.fileToolTracker.getToolCalls(),n=Array.from(t.entries()),i=this.eventProcessor.applyToolCallFilters(n);if(e>=0&&e<i.length){const[t]=i[e];this.showToolCallDetails(t)}}showFileDetailsByIndex(e){const t=this.fileToolTracker.getFileOperations();let n=Array.from(t.entries());if(n=this.eventProcessor.applyFilesFilters(n),e>=0&&e<n.length){const[t]=n[e];this.showFileDetails(t)}}showToolCallDetails(e){const t=this.fileToolTracker.getToolCall(e);t&&this.moduleViewer&&this.moduleViewer.showToolCall(t,e)}showFileDetails(e){const t=this.fileToolTracker.getFileOperationsForFile(e);t&&this.moduleViewer&&this.moduleViewer.showFileOperations(t,e)}switchTab(e){this.uiStateManager.switchTab(e)}selectCard(e,t,n,i){this.uiStateManager.selectCard(e,t,n,i)}clearEvents(){this.exportManager.clearEvents()}exportEvents(){this.exportManager.exportEvents()}clearSelection(){this.uiStateManager.clearSelection(),this.eventViewer&&this.eventViewer.clearSelection(),this.moduleViewer&&this.moduleViewer.clear()}get currentWorkingDir(){return this.workingDirectoryManager.getCurrentWorkingDir()}set currentWorkingDir(e){this.workingDirectoryManager.setWorkingDirectory(e)}get currentTab(){return this.uiStateManager.getCurrentTab()}get selectedCard(){return this.uiStateManager.getSelectedCard()}get fileOperations(){return this.fileToolTracker.getFileOperations()}get toolCalls(){return this.fileToolTracker.getToolCalls()}get tabNavigation(){return this.uiStateManager?this.uiStateManager.tabNavigation:null}}function g(){const e=document.createElement("div");return e.id="file-viewer-modal",e.className="modal file-viewer-modal",e.innerHTML='\n <div class="modal-content file-viewer-content">\n <div class="file-viewer-header">\n <h2 class="file-viewer-title">\n <span class="file-viewer-icon">📄</span>\n <span class="file-viewer-title-text">File Viewer</span>\n </h2>\n <div class="file-viewer-meta">\n <span class="file-viewer-file-path"></span>\n <span class="file-viewer-file-size"></span>\n </div>\n <button class="file-viewer-close" onclick="hideFileViewerModal()">\n <span>×</span>\n </button>\n </div>\n <div class="file-viewer-body">\n <div class="file-viewer-loading">\n <div class="loading-spinner"></div>\n <span>Loading file content...</span>\n </div>\n <div class="file-viewer-error" style="display: none;">\n <div class="error-icon">⚠️</div>\n <div class="error-message"></div>\n <div class="error-suggestions"></div>\n </div>\n <div class="file-viewer-content-area" style="display: none;">\n <div class="file-viewer-toolbar">\n <div class="file-viewer-info">\n <span class="file-extension"></span>\n <span class="file-encoding"></span>\n </div>\n <div class="file-viewer-actions">\n <button class="file-content-copy" onclick="copyFileContent()">\n 📋 Copy\n </button>\n </div>\n </div>\n <div class="file-viewer-scroll-wrapper">\n <pre class="file-content-display"><code class="file-content-code"></code></pre>\n </div>\n </div>\n </div>\n </div>\n ',e.addEventListener("click",t=>{t.target===e&&hideFileViewerModal()}),document.addEventListener("keydown",t=>{"Escape"===t.key&&"flex"===e.style.display&&hideFileViewerModal()}),e}async function f(e,t,n){const i=e.querySelector(".file-viewer-file-path"),o=e.querySelector(".file-viewer-file-size");i.textContent=t,o.textContent="",e.querySelector(".file-viewer-loading").style.display="flex",e.querySelector(".file-viewer-error").style.display="none",e.querySelector(".file-viewer-content-area").style.display="none";try{const i=window.socket||window.dashboard?.socketClient?.socket;if(!i)throw new Error("No socket connection available");const o=new Promise((e,n)=>{const o=s=>{s.file_path===t&&(i.off("file_content_response",o),s.success?e(s):n(new Error(s.error||"Failed to read file")))};i.on("file_content_response",o),setTimeout(()=>{i.off("file_content_response",o),n(new Error("Request timeout"))},1e4)});i.emit("read_file",{file_path:t,working_dir:n}),console.log("📄 File viewer request sent:",{filePath:t,workingDir:n});const s=await o;console.log("📦 File content received:",s),e.querySelector(".file-viewer-loading").style.display="none",function(e,t){console.log("📝 displayFileContent called with:",t);const n=e.querySelector(".file-viewer-content-area"),i=e.querySelector(".file-extension"),o=e.querySelector(".file-encoding"),s=e.querySelector(".file-viewer-file-size"),r=e.querySelector(".file-content-code");i&&(i.textContent=`Type: ${t.extension||"unknown"}`);o&&(o.textContent=`Encoding: ${t.encoding||"unknown"}`);s&&(s.textContent=`Size: ${function(e){if(!e)return"0 B";const t=1024,n=["B","KB","MB","GB"],i=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,i)).toFixed(2))+" "+n[i]}(t.file_size)}`);if(r&&t.content){console.log("💡 Setting file content, length:",t.content.length),r.innerHTML=function(e,t){const n=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");switch(t){case".js":case".jsx":case".ts":case".tsx":return function(e){return p(e.replace(/\b(function|const|let|var|if|else|for|while|return|import|export|class|extends)\b/g,'<span class="keyword">$1</span>').replace(/(\/\*[\s\S]*?\*\/|\/\/.*)/g,'<span class="comment">$1</span>').replace(/('[^']*'|"[^"]*"|`[^`]*`)/g,'<span class="string">$1</span>').replace(/\b(\d+)\b/g,'<span class="number">$1</span>'))}(n);case".py":return function(e){return p(e.replace(/\b(def|class|if|elif|else|for|while|return|import|from|as|try|except|finally|with)\b/g,'<span class="keyword">$1</span>').replace(/(#.*)/g,'<span class="comment">$1</span>').replace(/('[^']*'|"[^"]*"|"""[\s\S]*?""")/g,'<span class="string">$1</span>').replace(/\b(\d+)\b/g,'<span class="number">$1</span>'))}(n);case".json":return function(e){return p(e.replace(/("[\w\s]*")\s*:/g,'<span class="property">$1</span>:').replace(/:\s*(".*?")/g,': <span class="string">$1</span>').replace(/:\s*(\d+)/g,': <span class="number">$1</span>').replace(/:\s*(true|false|null)/g,': <span class="keyword">$1</span>'))}(n);case".css":return function(e){return p(e.replace(/([.#]?[\w-]+)\s*\{/g,'<span class="selector">$1</span> {').replace(/([\w-]+)\s*:/g,'<span class="property">$1</span>:').replace(/:\s*([^;]+);/g,': <span class="value">$1</span>;').replace(/(\/\*[\s\S]*?\*\/)/g,'<span class="comment">$1</span>'))}(n);case".html":case".htm":return function(e){return p(e.replace(/(<\/?[\w-]+)/g,'<span class="tag">$1</span>').replace(/([\w-]+)=(['"][^'"]*['"])/g,'<span class="attribute">$1</span>=<span class="string">$2</span>').replace(/(<!--[\s\S]*?-->)/g,'<span class="comment">$1</span>'))}(n);case".md":case".markdown":return function(e){return p(e.replace(/^(#{1,6})\s+(.*)$/gm,'<span class="header">$1</span> <span class="header-text">$2</span>').replace(/\*\*(.*?)\*\*/g,'<span class="bold">**$1**</span>').replace(/\*(.*?)\*/g,'<span class="italic">*$1*</span>').replace(/`([^`]+)`/g,'<span class="code">`$1`</span>').replace(/^\s*[-*+]\s+(.*)$/gm,'<span class="list-marker">•</span> $1'))}(n);default:return p(n)}}(t.content,t.extension);const n=e.querySelector(".file-viewer-scroll-wrapper");n&&setTimeout(()=>{const t=e.querySelector(".modal-content"),i=e.querySelector(".file-viewer-header"),o=e.querySelector(".file-viewer-toolbar"),s=t?.offsetHeight||0,r=i?.offsetHeight||0,a=o?.offsetHeight||0,l=s-r-a-40;console.log("🎯 Setting file viewer scroll height:",{modalHeight:s,headerHeight:r,toolbarHeight:a,availableHeight:l}),n.style.maxHeight=`${l}px`,n.style.overflowY="auto"},50)}else console.warn("⚠️ Missing codeElement or file content");n&&(n.style.display="block",console.log("✅ File content area displayed"))}(e,s)}catch(s){console.error("❌ Failed to fetch file content:",s),e.querySelector(".file-viewer-loading").style.display="none";let i=s.message||"Unknown error occurred",o=[];s.message.includes("No socket connection")?(i="Failed to connect to the monitoring server",o=["Check if the monitoring server is running","Verify the socket connection in the dashboard","Try refreshing the page and reconnecting"]):s.message.includes("timeout")?(i="Request timed out",o=["The file may be too large to load quickly","Check your network connection","Try again in a few moments"]):s.message.includes("File does not exist")?(i="File not found",o=["The file may have been moved or deleted","Check the file path spelling","Refresh the file list to see current files"]):s.message.includes("Access denied")&&(i="Access denied",o=["The file is outside the allowed directories","File access is restricted for security reasons"]),function(e,t){const n=e.querySelector(".file-viewer-error"),i=e.querySelector(".error-message"),o=e.querySelector(".error-suggestions");let s=t.error||"Unknown error occurred";i.innerHTML=`\n <div class="error-main">${s}</div>\n ${t.file_path?`<div class="error-file">File: ${t.file_path}</div>`:""}\n ${t.working_dir?`<div class="error-dir">Working directory: ${t.working_dir}</div>`:""}\n `,t.suggestions&&t.suggestions.length>0?o.innerHTML=`\n <h4>Suggestions:</h4>\n <ul>\n ${t.suggestions.map(e=>`<li>${e}</li>`).join("")}\n </ul>\n `:o.innerHTML="";console.log("📋 Displaying file viewer error:",{originalError:t.error,processedMessage:s,suggestions:t.suggestions}),n.style.display="block"}(e,{error:i,file_path:t,working_dir:n,suggestions:o})}}function p(e){return e.split("\n").map((e,t)=>`<span class="line-number">${String(t+1).padStart(3," ")}</span> ${e||" "}`).join("\n")}function h(e,t){const n=e.querySelector(".git-diff-error"),i=e.querySelector(".error-message"),o=e.querySelector(".error-suggestions");let s=t.error||"Unknown error occurred",r=!1;if(s.includes("not tracked by git")?(s="📝 This file is not tracked by git yet",r=!0):s.includes("No git history found")&&(s="📋 No git history available for this file"),i.innerHTML=`\n <div class="error-main">${s}</div>\n ${t.file_path?`<div class="error-file">File: ${t.file_path}</div>`:""}\n ${t.working_dir?`<div class="error-dir">Working directory: ${t.working_dir}</div>`:""}\n `,t.suggestions&&t.suggestions.length>0){const e=r?"How to track this file:":"Suggestions:";o.innerHTML=`\n <h4>${e}</h4>\n <ul>\n ${t.suggestions.map(e=>`<li>${e}</li>`).join("")}\n </ul>\n `}else o.innerHTML="";console.log("📋 Displaying git diff error:",{originalError:t.error,processedMessage:s,isUntracked:r,suggestions:t.suggestions}),n.style.display="block"}window.clearEvents=function(){window.dashboard&&window.dashboard.clearEvents()},window.exportEvents=function(){window.dashboard&&window.dashboard.exportEvents()},window.clearSelection=function(){window.dashboard&&window.dashboard.clearSelection()},window.switchTab=function(e){window.dashboard&&window.dashboard.switchTab(e)},window.showFileViewerModal=function(e,t){!t&&window.dashboard&&window.dashboard.currentWorkingDir&&(t=window.dashboard.currentWorkingDir);let n=document.getElementById("file-viewer-modal");n||(n=g(),document.body.appendChild(n)),f(n,e,t),n.style.display="flex",document.body.style.overflow="hidden"},window.hideFileViewerModal=function(){const e=document.getElementById("file-viewer-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.copyFileContent=function(){const e=document.getElementById("file-viewer-modal");if(!e)return;const t=e.querySelector(".file-content-code");if(!t)return;const n=t.textContent;if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(n).then(()=>{const t=e.querySelector(".file-content-copy"),n=t.textContent;t.textContent="✅ Copied!",setTimeout(()=>{t.textContent=n},2e3)}).catch(e=>{console.error("Failed to copy text:",e)});else{const t=document.createElement("textarea");t.value=n,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t);const i=e.querySelector(".file-content-copy"),o=i.textContent;i.textContent="✅ Copied!",setTimeout(()=>{i.textContent=o},2e3)}},window.showGitDiffModal=function(e,t,n){!n&&window.dashboard&&window.dashboard.currentWorkingDir&&(n=window.dashboard.currentWorkingDir);let i=document.getElementById("git-diff-modal");i||(i=function(){const e=document.createElement("div");return e.id="git-diff-modal",e.className="modal git-diff-modal",e.innerHTML='\n <div class="modal-content git-diff-content">\n <div class="git-diff-header">\n <h2 class="git-diff-title">\n <span class="git-diff-icon">📋</span>\n <span class="git-diff-title-text">Git Diff</span>\n </h2>\n <div class="git-diff-meta">\n <span class="git-diff-file-path"></span>\n <span class="git-diff-timestamp"></span>\n </div>\n <button class="git-diff-close" onclick="hideGitDiffModal()">\n <span>×</span>\n </button>\n </div>\n <div class="git-diff-body">\n <div class="git-diff-loading">\n <div class="loading-spinner"></div>\n <span>Loading git diff...</span>\n </div>\n <div class="git-diff-error" style="display: none;">\n <div class="error-icon">⚠️</div>\n <div class="error-message"></div>\n <div class="error-suggestions"></div>\n </div>\n <div class="git-diff-content-area" style="display: none;">\n <div class="git-diff-toolbar">\n <div class="git-diff-info">\n <span class="commit-hash"></span>\n <span class="diff-method"></span>\n </div>\n <div class="git-diff-actions">\n <button class="git-diff-copy" onclick="copyGitDiff()">\n 📋 Copy\n </button>\n </div>\n </div>\n <div class="git-diff-scroll-wrapper">\n <pre class="git-diff-display"><code class="git-diff-code"></code></pre>\n </div>\n </div>\n </div>\n </div>\n ',e.addEventListener("click",t=>{t.target===e&&hideGitDiffModal()}),document.addEventListener("keydown",t=>{"Escape"===t.key&&"flex"===e.style.display&&hideGitDiffModal()}),e}(),document.body.appendChild(i)),async function(e,t,n,i){const o=e.querySelector(".git-diff-file-path"),s=e.querySelector(".git-diff-timestamp");o.textContent=t,s.textContent=n?new Date(n).toLocaleString():"Latest",e.querySelector(".git-diff-loading").style.display="flex",e.querySelector(".git-diff-error").style.display="none",e.querySelector(".git-diff-content-area").style.display="none";try{let o=8765;if(window.dashboard&&window.dashboard.socketClient&&window.dashboard.socketClient.port)o=window.dashboard.socketClient.port;else{const e=document.getElementById("port-input");e&&e.value&&(o=e.value)}const s=new URLSearchParams({file:t});n&&s.append("timestamp",n),i&&s.append("working_dir",i);const a=`http://localhost:${o}/api/git-diff?${s}`;console.log("🌐 Making git diff request to:",a),console.log("📋 Git diff request parameters:",{filePath:t,timestamp:n,workingDir:i,urlParams:s.toString()});try{const e=await fetch(`http://localhost:${o}/health`,{method:"GET",headers:{Accept:"application/json","Content-Type":"application/json"},mode:"cors"});if(!e.ok)throw new Error(`Server health check failed: ${e.status} ${e.statusText}`);console.log("✅ Server health check passed")}catch(r){throw new Error(`Cannot reach server at localhost:${o}. Health check failed: ${r.message}`)}const l=await fetch(a,{method:"GET",headers:{Accept:"application/json","Content-Type":"application/json"},mode:"cors"});if(!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText}`);const c=await l.json();console.log("📦 Git diff response:",c),e.querySelector(".git-diff-loading").style.display="none",c.success?(console.log("📊 Displaying successful git diff"),function(e,t){console.log("📝 displayGitDiff called with:",t);const n=e.querySelector(".git-diff-content-area"),i=e.querySelector(".commit-hash"),o=e.querySelector(".diff-method"),s=e.querySelector(".git-diff-code");console.log("🔍 Elements found:",{contentArea:!!n,commitHashElement:!!i,methodElement:!!o,codeElement:!!s}),i&&(i.textContent=`Commit: ${t.commit_hash}`);o&&(o.textContent=`Method: ${t.method}`);if(s&&t.diff){console.log("💡 Setting diff content, length:",t.diff.length),s.innerHTML=t.diff.split("\n").map(e=>{const t=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");return e.startsWith("+++")||e.startsWith("---")?`<span class="diff-header">${t}</span>`:e.startsWith("@@")?`<span class="diff-meta">${t}</span>`:e.startsWith("+")?`<span class="diff-addition">${t}</span>`:e.startsWith("-")?`<span class="diff-deletion">${t}</span>`:e.startsWith("commit ")||e.startsWith("Author:")||e.startsWith("Date:")?`<span class="diff-header">${t}</span>`:`<span class="diff-context">${t}</span>`}).join("\n");const n=e.querySelector(".git-diff-scroll-wrapper");n&&setTimeout(()=>{const t=e.querySelector(".modal-content"),i=e.querySelector(".git-diff-header"),o=e.querySelector(".git-diff-toolbar"),s=t?.offsetHeight||0,r=i?.offsetHeight||0,a=o?.offsetHeight||0,l=s-r-a-40;console.log("🎯 Setting explicit scroll height:",{modalHeight:s,headerHeight:r,toolbarHeight:a,availableHeight:l}),n.style.maxHeight=`${l}px`,n.style.overflowY="auto"},50)}else console.warn("⚠️ Missing codeElement or diff data");n&&(n.style.display="block",console.log("✅ Content area displayed"))}(e,c)):(console.log("⚠️ Displaying git diff error:",c),h(e,c))}catch(a){console.error("❌ Failed to fetch git diff:",a),console.error("Error details:",{name:a.name,message:a.message,stack:a.stack,filePath:t,timestamp:n,workingDir:i}),e.querySelector(".git-diff-loading").style.display="none";let o=`Network error: ${a.message}`,s=[];a.message.includes("Failed to fetch")?(o="Failed to connect to the monitoring server",s=["Check if the monitoring server is running on port 8765","Verify the port configuration in the dashboard","Check browser console for CORS or network errors","Try refreshing the page and reconnecting"]):a.message.includes("health check failed")?(o=a.message,s=["The server may be starting up - try again in a few seconds","Check if another process is using port 8765","Restart the claude-mpm monitoring server"]):a.message.includes("HTTP")&&(o=`Server error: ${a.message}`,s=["The server encountered an internal error","Check the server logs for more details","Try with a different file or working directory"]),h(e,{error:o,file_path:t,working_dir:i,suggestions:s,debug_info:{error_type:a.name,original_message:a.message,port:window.dashboard?.socketClient?.port||document.getElementById("port-input")?.value||"8765",timestamp:(new Date).toISOString()}})}}(i,e,t,n),i.style.display="flex",document.body.style.overflow="hidden"},window.hideGitDiffModal=function(){const e=document.getElementById("git-diff-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.copyGitDiff=function(){const e=document.getElementById("git-diff-modal");if(!e)return;const t=e.querySelector(".git-diff-code");if(!t)return;const n=t.textContent;if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(n).then(()=>{const t=e.querySelector(".git-diff-copy"),n=t.textContent;t.textContent="✅ Copied!",setTimeout(()=>{t.textContent=n},2e3)}).catch(e=>{console.error("Failed to copy text:",e)});else{const t=document.createElement("textarea");t.value=n,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t);const i=e.querySelector(".git-diff-copy"),o=i.textContent;i.textContent="✅ Copied!",setTimeout(()=>{i.textContent=o},2e3)}},window.showFileViewerModal=function(e){let t="";window.dashboard&&window.dashboard.currentWorkingDir&&(t=window.dashboard.currentWorkingDir);let n=document.getElementById("file-viewer-modal");n||(n=g(),document.body.appendChild(n)),f(n,e,t),n.style.display="flex",document.body.style.overflow="hidden"},window.hideFileViewerModal=function(){const e=document.getElementById("file-viewer-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.copyFileContent=function(){const e=document.getElementById("file-viewer-modal");if(!e)return;const t=e.querySelector(".file-content-code");if(!t)return;const n=t.textContent;if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(n).then(()=>{const t=e.querySelector(".file-content-copy"),n=t.textContent;t.textContent="✅ Copied!",setTimeout(()=>{t.textContent=n},2e3)}).catch(e=>{console.error("Failed to copy text:",e)});else{const t=document.createElement("textarea");t.value=n,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t);const i=e.querySelector(".file-content-copy"),o=i.textContent;i.textContent="✅ Copied!",setTimeout(()=>{i.textContent=o},2e3)}},window.showAgentInstanceDetails=function(e){window.dashboard&&"function"==typeof window.dashboard.showAgentInstanceDetails?window.dashboard.showAgentInstanceDetails(e):console.error("Dashboard not available or method not found")},document.addEventListener("DOMContentLoaded",function(){window.dashboard=new d,console.log("Dashboard loaded and initialized")});
|
|
1
|
+
import{S as e,U as t}from"./socket-client.js";import{E as n,a as i}from"./components/event-viewer.js";import{M as o}from"./components/module-viewer.js";import{S as s}from"./components/session-manager.js";import{A as r}from"./components/agent-inference.js";import{E as a}from"./components/export-manager.js";import{W as l}from"./components/working-directory.js";import{F as c}from"./components/file-tool-tracker.js";class d{constructor(){this.eventViewer=null,this.moduleViewer=null,this.sessionManager=null,this.socketManager=null,this.agentInference=null,this.uiStateManager=null,this.eventProcessor=null,this.exportManager=null,this.workingDirectoryManager=null,this.fileToolTracker=null,this.init()}init(){console.log("Initializing refactored Claude MPM Dashboard..."),this.initializeSocketManager(),this.initializeCoreComponents(),this.initializeAgentInference(),this.initializeUIStateManager(),this.initializeWorkingDirectoryManager(),this.initializeFileToolTracker(),this.initializeEventProcessor(),this.initializeExportManager(),this.setupModuleInteractions(),this.initializeFromURL(),console.log("Claude MPM Dashboard initialized successfully")}initializeSocketManager(){this.socketManager=new e,this.socketManager.setupConnectionControls(),this.socketClient=this.socketManager.getSocketClient(),window.socketClient=this.socketClient}initializeCoreComponents(){this.eventViewer=new n("events-list",this.socketClient),this.moduleViewer=new o,this.sessionManager=new s(this.socketClient),window.eventViewer=this.eventViewer,window.moduleViewer=this.moduleViewer,window.sessionManager=this.sessionManager}initializeAgentInference(){this.agentInference=new r(this.eventViewer),this.agentInference.initialize()}initializeUIStateManager(){this.uiStateManager=new t,this.setupTabFilters()}initializeWorkingDirectoryManager(){this.workingDirectoryManager=new l(this.socketManager)}initializeFileToolTracker(){this.fileToolTracker=new c(this.agentInference,this.workingDirectoryManager)}initializeEventProcessor(){this.eventProcessor=new i(this.eventViewer,this.agentInference)}initializeExportManager(){this.exportManager=new a(this.eventViewer)}setupModuleInteractions(){this.socketManager.onEventUpdate(e=>{this.fileToolTracker.updateFileOperations(e),this.fileToolTracker.updateToolCalls(e),this.agentInference.processAgentInference(),"events"===this.uiStateManager.getCurrentTab()&&this.exportManager.scrollListToBottom("events-list"),this.renderCurrentTab()}),this.socketManager.onConnectionStatusChange((e,t)=>{"connected"===t&&this.workingDirectoryManager.updateGitBranch(this.workingDirectoryManager.getCurrentWorkingDir())}),document.addEventListener("tabChanged",e=>{this.renderCurrentTab(),this.uiStateManager.updateTabNavigationItems()}),document.addEventListener("eventsClearing",()=>{this.fileToolTracker.clear(),this.agentInference.initialize()}),document.addEventListener("showCardDetails",e=>{this.showCardDetails(e.detail.tabName,e.detail.index)}),document.addEventListener("sessionFilterChanged",e=>{console.log("Session filter changed, re-rendering current tab:",this.uiStateManager.getCurrentTab()),this.renderCurrentTab()})}setupTabFilters(){const e=document.getElementById("agents-search-input"),t=document.getElementById("agents-type-filter");e&&e.addEventListener("input",()=>{"agents"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),t&&t.addEventListener("change",()=>{"agents"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()});const n=document.getElementById("tools-search-input"),i=document.getElementById("tools-type-filter");n&&n.addEventListener("input",()=>{"tools"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),i&&i.addEventListener("change",()=>{"tools"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()});const o=document.getElementById("files-search-input"),s=document.getElementById("files-type-filter");o&&o.addEventListener("input",()=>{"files"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),s&&s.addEventListener("change",()=>{"files"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()})}initializeFromURL(){const e=new URLSearchParams(window.location.search);this.socketManager.initializeFromURL(e)}renderCurrentTab(){const e=this.uiStateManager.getCurrentTab();switch(e){case"events":break;case"agents":this.renderAgents();break;case"tools":this.renderTools();break;case"files":this.renderFiles()}this.uiStateManager.getSelectedCard().tab===e&&this.uiStateManager.updateCardSelectionUI(),this.uiStateManager.updateUnifiedSelectionUI()}renderAgents(){const e=document.getElementById("agents-list");if(!e)return;this.agentInference.processAgentInference();const t=this.eventProcessor.getFilteredEventsForTab("agents"),n=this.eventProcessor.generateAgentHTML(t);e.innerHTML=n,this.exportManager.scrollListToBottom("agents-list");const i=this.agentInference.getUniqueAgentInstances();this.updateAgentsFilterDropdowns(i)}renderTools(){const e=document.getElementById("tools-list");if(!e)return;const t=this.fileToolTracker.getToolCalls(),n=Array.from(t.entries()),i=this.eventProcessor.getUniqueToolInstances(n),o=this.eventProcessor.generateToolHTML(i);e.innerHTML=o,this.exportManager.scrollListToBottom("tools-list"),this.updateToolsFilterDropdowns(i)}renderFiles(){const e=document.getElementById("files-list");if(!e)return;const t=this.fileToolTracker.getFileOperations(),n=Array.from(t.entries()),i=this.eventProcessor.getUniqueFileInstances(n),o=this.eventProcessor.generateFileHTML(i);e.innerHTML=o,this.exportManager.scrollListToBottom("files-list"),this.updateFilesFilterDropdowns(n)}updateAgentsFilterDropdowns(e){const t=new Set;e.forEach(e=>{e.agentName&&"Unknown"!==e.agentName&&t.add(e.agentName)});const n=Array.from(t).filter(e=>e&&""!==e.trim());this.populateFilterDropdown("agents-type-filter",n,"All Agent Types"),n.length>0?console.log("Agent types found for filter:",n):console.log("No agent types found for filter. Instances:",e.length)}updateToolsFilterDropdowns(e){const t=[...new Set(e.map(([e,t])=>t.tool_name))].filter(e=>e);this.populateFilterDropdown("tools-type-filter",t,"All Tools")}updateFilesFilterDropdowns(e){const t=[...new Set(e.flatMap(([e,t])=>t.operations.map(e=>e.operation)))].filter(e=>e);this.populateFilterDropdown("files-type-filter",t,"All Operations")}populateFilterDropdown(e,t,n="All"){const i=document.getElementById(e);if(!i)return;const o=i.value,s=t.sort((e,t)=>e.localeCompare(t));i.innerHTML=`<option value="">${n}</option>`,s.forEach(e=>{const t=document.createElement("option");t.value=e,t.textContent=e,i.appendChild(t)}),o&&s.includes(o)&&(i.value=o)}showCardDetails(e,t){switch(e){case"events":this.eventViewer&&this.eventViewer.showEventDetails(t);break;case"agents":this.showAgentDetailsByIndex(t);break;case"tools":this.showToolDetailsByIndex(t);break;case"files":this.showFileDetailsByIndex(t)}}showAgentDetailsByIndex(e){const t=this.eventProcessor.getFilteredEventsForTab("agents");if(!t||!Array.isArray(t)||e<0||e>=t.length)return void console.warn("Dashboard: Invalid agent index or events array");const n=this.eventProcessor.applyAgentsFilters([t[e]]);if(n.length>0&&this.moduleViewer&&"function"==typeof this.moduleViewer.showAgentEvent){const t=n[0];this.moduleViewer.showAgentEvent(t,e)}}showAgentInstanceDetails(e){const t=this.agentInference.getPMDelegations().get(e);if(!t){const t=this.agentInference.getUniqueAgentInstances().find(t=>t.id===e);return t?void this.showImpliedAgentDetails(t):void console.error("Agent instance not found:",e)}this.moduleViewer&&"function"==typeof this.moduleViewer.showAgentInstance?this.moduleViewer.showAgentInstance(t):console.log("Agent Instance Details:",{id:e,agentName:t.agentName,type:"PM Delegation",eventCount:t.agentEvents.length,startTime:t.timestamp,pmCall:t.pmCall})}showImpliedAgentDetails(e){this.moduleViewer&&"function"==typeof this.moduleViewer.showImpliedAgent?this.moduleViewer.showImpliedAgent(e):console.log("Implied Agent Details:",{id:e.id,agentName:e.agentName,type:"Implied PM Delegation",eventCount:e.eventCount,startTime:e.timestamp,note:"No explicit PM call found - inferred from agent activity"})}showToolDetailsByIndex(e){const t=this.fileToolTracker.getToolCalls(),n=Array.from(t.entries()),i=this.eventProcessor.applyToolCallFilters(n);if(e>=0&&e<i.length){const[t]=i[e];this.showToolCallDetails(t)}}showFileDetailsByIndex(e){const t=this.fileToolTracker.getFileOperations();let n=Array.from(t.entries());if(n=this.eventProcessor.applyFilesFilters(n),e>=0&&e<n.length){const[t]=n[e];this.showFileDetails(t)}}showToolCallDetails(e){const t=this.fileToolTracker.getToolCall(e);t&&this.moduleViewer&&this.moduleViewer.showToolCall(t,e)}showFileDetails(e){const t=this.fileToolTracker.getFileOperationsForFile(e);t&&this.moduleViewer&&this.moduleViewer.showFileOperations(t,e)}switchTab(e){this.uiStateManager.switchTab(e)}selectCard(e,t,n,i){this.uiStateManager.selectCard(e,t,n,i)}clearEvents(){this.exportManager.clearEvents()}exportEvents(){this.exportManager.exportEvents()}clearSelection(){this.uiStateManager.clearSelection(),this.eventViewer&&this.eventViewer.clearSelection(),this.moduleViewer&&this.moduleViewer.clear()}get currentWorkingDir(){return this.workingDirectoryManager.getCurrentWorkingDir()}set currentWorkingDir(e){this.workingDirectoryManager.setWorkingDirectory(e)}get currentTab(){return this.uiStateManager.getCurrentTab()}get selectedCard(){return this.uiStateManager.getSelectedCard()}get fileOperations(){return this.fileToolTracker.getFileOperations()}get toolCalls(){return this.fileToolTracker.getToolCalls()}get tabNavigation(){return this.uiStateManager?this.uiStateManager.tabNavigation:null}}function g(){const e=document.createElement("div");return e.id="file-viewer-modal",e.className="modal file-viewer-modal",e.innerHTML='\n <div class="modal-content file-viewer-content">\n <div class="file-viewer-header">\n <h2 class="file-viewer-title">\n <span class="file-viewer-icon">📄</span>\n <span class="file-viewer-title-text">File Viewer</span>\n </h2>\n <div class="file-viewer-meta">\n <span class="file-viewer-file-path"></span>\n <span class="file-viewer-file-size"></span>\n </div>\n <button class="file-viewer-close" onclick="hideFileViewerModal()">\n <span>×</span>\n </button>\n </div>\n <div class="file-viewer-body">\n <div class="file-viewer-loading">\n <div class="loading-spinner"></div>\n <span>Loading file content...</span>\n </div>\n <div class="file-viewer-error" style="display: none;">\n <div class="error-icon">⚠️</div>\n <div class="error-message"></div>\n <div class="error-suggestions"></div>\n </div>\n <div class="file-viewer-content-area" style="display: none;">\n <div class="file-viewer-toolbar">\n <div class="file-viewer-info">\n <span class="file-extension"></span>\n <span class="file-encoding"></span>\n </div>\n <div class="file-viewer-actions">\n <button class="file-content-copy" onclick="copyFileContent()">\n 📋 Copy\n </button>\n </div>\n </div>\n <div class="file-viewer-scroll-wrapper">\n <pre class="file-content-display"><code class="file-content-code"></code></pre>\n </div>\n </div>\n </div>\n </div>\n ',e.addEventListener("click",t=>{t.target===e&&hideFileViewerModal()}),document.addEventListener("keydown",t=>{"Escape"===t.key&&"flex"===e.style.display&&hideFileViewerModal()}),e}async function h(e,t,n){const i=e.querySelector(".file-viewer-file-path"),o=e.querySelector(".file-viewer-file-size");i.textContent=t,o.textContent="",e.querySelector(".file-viewer-loading").style.display="flex",e.querySelector(".file-viewer-error").style.display="none",e.querySelector(".file-viewer-content-area").style.display="none";try{const i=window.socket||window.dashboard?.socketClient?.socket;if(!i)throw new Error("No socket connection available");const o=new Promise((e,n)=>{const o=s=>{s.file_path===t&&(i.off("file_content_response",o),s.success?e(s):n(new Error(s.error||"Failed to read file")))};i.on("file_content_response",o),setTimeout(()=>{i.off("file_content_response",o),n(new Error("Request timeout"))},1e4)});i.emit("read_file",{file_path:t,working_dir:n}),console.log("📄 File viewer request sent:",{filePath:t,workingDir:n});const s=await o;console.log("📦 File content received:",s),e.querySelector(".file-viewer-loading").style.display="none",function(e,t){console.log("📝 displayFileContent called with:",t);const n=e.querySelector(".file-viewer-content-area"),i=e.querySelector(".file-extension"),o=e.querySelector(".file-encoding"),s=e.querySelector(".file-viewer-file-size"),r=e.querySelector(".file-content-code");i&&(i.textContent=`Type: ${t.extension||"unknown"}`);o&&(o.textContent=`Encoding: ${t.encoding||"unknown"}`);s&&(s.textContent=`Size: ${function(e){if(!e)return"0 B";const t=1024,n=["B","KB","MB","GB"],i=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,i)).toFixed(2))+" "+n[i]}(t.file_size)}`);if(r&&t.content){console.log("💡 Setting file content, length:",t.content.length),r.innerHTML=function(e,t){const n=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");switch(t){case".js":case".jsx":case".ts":case".tsx":return function(e){return f(e.replace(/\b(function|const|let|var|if|else|for|while|return|import|export|class|extends)\b/g,'<span class="keyword">$1</span>').replace(/(\/\*[\s\S]*?\*\/|\/\/.*)/g,'<span class="comment">$1</span>').replace(/('[^']*'|"[^"]*"|`[^`]*`)/g,'<span class="string">$1</span>').replace(/\b(\d+)\b/g,'<span class="number">$1</span>'))}(n);case".py":return function(e){return f(e.replace(/\b(def|class|if|elif|else|for|while|return|import|from|as|try|except|finally|with)\b/g,'<span class="keyword">$1</span>').replace(/(#.*)/g,'<span class="comment">$1</span>').replace(/('[^']*'|"[^"]*"|"""[\s\S]*?""")/g,'<span class="string">$1</span>').replace(/\b(\d+)\b/g,'<span class="number">$1</span>'))}(n);case".json":return function(e){return f(e.replace(/("[\w\s]*")\s*:/g,'<span class="property">$1</span>:').replace(/:\s*(".*?")/g,': <span class="string">$1</span>').replace(/:\s*(\d+)/g,': <span class="number">$1</span>').replace(/:\s*(true|false|null)/g,': <span class="keyword">$1</span>'))}(n);case".css":return function(e){return f(e.replace(/([.#]?[\w-]+)\s*\{/g,'<span class="selector">$1</span> {').replace(/([\w-]+)\s*:/g,'<span class="property">$1</span>:').replace(/:\s*([^;]+);/g,': <span class="value">$1</span>;').replace(/(\/\*[\s\S]*?\*\/)/g,'<span class="comment">$1</span>'))}(n);case".html":case".htm":return function(e){return f(e.replace(/(<\/?[\w-]+)/g,'<span class="tag">$1</span>').replace(/([\w-]+)=(['"][^'"]*['"])/g,'<span class="attribute">$1</span>=<span class="string">$2</span>').replace(/(<!--[\s\S]*?-->)/g,'<span class="comment">$1</span>'))}(n);case".md":case".markdown":return function(e){return f(e.replace(/^(#{1,6})\s+(.*)$/gm,'<span class="header">$1</span> <span class="header-text">$2</span>').replace(/\*\*(.*?)\*\*/g,'<span class="bold">**$1**</span>').replace(/\*(.*?)\*/g,'<span class="italic">*$1*</span>').replace(/`([^`]+)`/g,'<span class="code">`$1`</span>').replace(/^\s*[-*+]\s+(.*)$/gm,'<span class="list-marker">•</span> $1'))}(n);default:return f(n)}}(t.content,t.extension);const n=e.querySelector(".file-viewer-scroll-wrapper");n&&setTimeout(()=>{const t=e.querySelector(".modal-content"),i=e.querySelector(".file-viewer-header"),o=e.querySelector(".file-viewer-toolbar"),s=t?.offsetHeight||0,r=i?.offsetHeight||0,a=o?.offsetHeight||0,l=s-r-a-40;console.log("🎯 Setting file viewer scroll height:",{modalHeight:s,headerHeight:r,toolbarHeight:a,availableHeight:l}),n.style.maxHeight=`${l}px`,n.style.overflowY="auto"},50)}else console.warn("⚠️ Missing codeElement or file content");n&&(n.style.display="block",console.log("✅ File content area displayed"))}(e,s)}catch(s){console.error("❌ Failed to fetch file content:",s),e.querySelector(".file-viewer-loading").style.display="none";let i=s.message||"Unknown error occurred",o=[];s.message.includes("No socket connection")?(i="Failed to connect to the monitoring server",o=["Check if the monitoring server is running","Verify the socket connection in the dashboard","Try refreshing the page and reconnecting"]):s.message.includes("timeout")?(i="Request timed out",o=["The file may be too large to load quickly","Check your network connection","Try again in a few moments"]):s.message.includes("File does not exist")?(i="File not found",o=["The file may have been moved or deleted","Check the file path spelling","Refresh the file list to see current files"]):s.message.includes("Access denied")&&(i="Access denied",o=["The file is outside the allowed directories","File access is restricted for security reasons"]),function(e,t){const n=e.querySelector(".file-viewer-error"),i=e.querySelector(".error-message"),o=e.querySelector(".error-suggestions");let s=t.error||"Unknown error occurred";i.innerHTML=`\n <div class="error-main">${s}</div>\n ${t.file_path?`<div class="error-file">File: ${t.file_path}</div>`:""}\n ${t.working_dir?`<div class="error-dir">Working directory: ${t.working_dir}</div>`:""}\n `,t.suggestions&&t.suggestions.length>0?o.innerHTML=`\n <h4>Suggestions:</h4>\n <ul>\n ${t.suggestions.map(e=>`<li>${e}</li>`).join("")}\n </ul>\n `:o.innerHTML="";console.log("📋 Displaying file viewer error:",{originalError:t.error,processedMessage:s,suggestions:t.suggestions}),n.style.display="block"}(e,{error:i,file_path:t,working_dir:n,suggestions:o})}}function f(e){return e.split("\n").map((e,t)=>`<span class="line-number">${String(t+1).padStart(3," ")}</span> ${e||" "}`).join("\n")}function p(e,t){const n=e.querySelector(".git-diff-error"),i=e.querySelector(".error-message"),o=e.querySelector(".error-suggestions");let s=t.error||"Unknown error occurred",r=!1;if(s.includes("not tracked by git")?(s="📝 This file is not tracked by git yet",r=!0):s.includes("No git history found")&&(s="📋 No git history available for this file"),i.innerHTML=`\n <div class="error-main">${s}</div>\n ${t.file_path?`<div class="error-file">File: ${t.file_path}</div>`:""}\n ${t.working_dir?`<div class="error-dir">Working directory: ${t.working_dir}</div>`:""}\n `,t.suggestions&&t.suggestions.length>0){const e=r?"How to track this file:":"Suggestions:";o.innerHTML=`\n <h4>${e}</h4>\n <ul>\n ${t.suggestions.map(e=>`<li>${e}</li>`).join("")}\n </ul>\n `}else o.innerHTML="";console.log("📋 Displaying git diff error:",{originalError:t.error,processedMessage:s,isUntracked:r,suggestions:t.suggestions}),n.style.display="block"}function u(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}window.clearEvents=function(){window.dashboard&&window.dashboard.clearEvents()},window.exportEvents=function(){window.dashboard&&window.dashboard.exportEvents()},window.clearSelection=function(){window.dashboard&&window.dashboard.clearSelection()},window.switchTab=function(e){window.dashboard&&window.dashboard.switchTab(e)},window.showFileViewerModal=function(e,t){!t&&window.dashboard&&window.dashboard.currentWorkingDir&&(t=window.dashboard.currentWorkingDir);let n=document.getElementById("file-viewer-modal");n||(n=g(),document.body.appendChild(n)),h(n,e,t),n.style.display="flex",document.body.style.overflow="hidden"},window.hideFileViewerModal=function(){const e=document.getElementById("file-viewer-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.copyFileContent=function(){const e=document.getElementById("file-viewer-modal");if(!e)return;const t=e.querySelector(".file-content-code");if(!t)return;const n=t.textContent;if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(n).then(()=>{const t=e.querySelector(".file-content-copy"),n=t.textContent;t.textContent="✅ Copied!",setTimeout(()=>{t.textContent=n},2e3)}).catch(e=>{console.error("Failed to copy text:",e)});else{const t=document.createElement("textarea");t.value=n,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t);const i=e.querySelector(".file-content-copy"),o=i.textContent;i.textContent="✅ Copied!",setTimeout(()=>{i.textContent=o},2e3)}},window.showGitDiffModal=function(e,t,n){!n&&window.dashboard&&window.dashboard.currentWorkingDir&&(n=window.dashboard.currentWorkingDir);let i=document.getElementById("git-diff-modal");i||(i=function(){const e=document.createElement("div");return e.id="git-diff-modal",e.className="modal git-diff-modal",e.innerHTML='\n <div class="modal-content git-diff-content">\n <div class="git-diff-header">\n <h2 class="git-diff-title">\n <span class="git-diff-icon">📋</span>\n <span class="git-diff-title-text">Git Diff</span>\n </h2>\n <div class="git-diff-meta">\n <span class="git-diff-file-path"></span>\n <span class="git-diff-timestamp"></span>\n </div>\n <button class="git-diff-close" onclick="hideGitDiffModal()">\n <span>×</span>\n </button>\n </div>\n <div class="git-diff-body">\n <div class="git-diff-loading">\n <div class="loading-spinner"></div>\n <span>Loading git diff...</span>\n </div>\n <div class="git-diff-error" style="display: none;">\n <div class="error-icon">⚠️</div>\n <div class="error-message"></div>\n <div class="error-suggestions"></div>\n </div>\n <div class="git-diff-content-area" style="display: none;">\n <div class="git-diff-toolbar">\n <div class="git-diff-info">\n <span class="commit-hash"></span>\n <span class="diff-method"></span>\n </div>\n <div class="git-diff-actions">\n <button class="git-diff-copy" onclick="copyGitDiff()">\n 📋 Copy\n </button>\n </div>\n </div>\n <div class="git-diff-scroll-wrapper">\n <pre class="git-diff-display"><code class="git-diff-code"></code></pre>\n </div>\n </div>\n </div>\n </div>\n ',e.addEventListener("click",t=>{t.target===e&&hideGitDiffModal()}),document.addEventListener("keydown",t=>{"Escape"===t.key&&"flex"===e.style.display&&hideGitDiffModal()}),e}(),document.body.appendChild(i)),async function(e,t,n,i){const o=e.querySelector(".git-diff-file-path"),s=e.querySelector(".git-diff-timestamp");o.textContent=t,s.textContent=n?new Date(n).toLocaleString():"Latest",e.querySelector(".git-diff-loading").style.display="flex",e.querySelector(".git-diff-error").style.display="none",e.querySelector(".git-diff-content-area").style.display="none";try{let o=8765;if(window.dashboard&&window.dashboard.socketClient&&window.dashboard.socketClient.port)o=window.dashboard.socketClient.port;else{const e=document.getElementById("port-input");e&&e.value&&(o=e.value)}const s=new URLSearchParams({file:t});n&&s.append("timestamp",n),i&&s.append("working_dir",i);const a=`http://localhost:${o}/api/git-diff?${s}`;console.log("🌐 Making git diff request to:",a),console.log("📋 Git diff request parameters:",{filePath:t,timestamp:n,workingDir:i,urlParams:s.toString()});try{const e=await fetch(`http://localhost:${o}/health`,{method:"GET",headers:{Accept:"application/json","Content-Type":"application/json"},mode:"cors"});if(!e.ok)throw new Error(`Server health check failed: ${e.status} ${e.statusText}`);console.log("✅ Server health check passed")}catch(r){throw new Error(`Cannot reach server at localhost:${o}. Health check failed: ${r.message}`)}const l=await fetch(a,{method:"GET",headers:{Accept:"application/json","Content-Type":"application/json"},mode:"cors"});if(!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText}`);const c=await l.json();console.log("📦 Git diff response:",c),e.querySelector(".git-diff-loading").style.display="none",c.success?(console.log("📊 Displaying successful git diff"),function(e,t){console.log("📝 displayGitDiff called with:",t);const n=e.querySelector(".git-diff-content-area"),i=e.querySelector(".commit-hash"),o=e.querySelector(".diff-method"),s=e.querySelector(".git-diff-code");console.log("🔍 Elements found:",{contentArea:!!n,commitHashElement:!!i,methodElement:!!o,codeElement:!!s}),i&&(i.textContent=`Commit: ${t.commit_hash}`);o&&(o.textContent=`Method: ${t.method}`);if(s&&t.diff){console.log("💡 Setting diff content, length:",t.diff.length),s.innerHTML=t.diff.split("\n").map(e=>{const t=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");return e.startsWith("+++")||e.startsWith("---")?`<span class="diff-header">${t}</span>`:e.startsWith("@@")?`<span class="diff-meta">${t}</span>`:e.startsWith("+")?`<span class="diff-addition">${t}</span>`:e.startsWith("-")?`<span class="diff-deletion">${t}</span>`:e.startsWith("commit ")||e.startsWith("Author:")||e.startsWith("Date:")?`<span class="diff-header">${t}</span>`:`<span class="diff-context">${t}</span>`}).join("\n");const n=e.querySelector(".git-diff-scroll-wrapper");n&&setTimeout(()=>{const t=e.querySelector(".modal-content"),i=e.querySelector(".git-diff-header"),o=e.querySelector(".git-diff-toolbar"),s=t?.offsetHeight||0,r=i?.offsetHeight||0,a=o?.offsetHeight||0,l=s-r-a-40;console.log("🎯 Setting explicit scroll height:",{modalHeight:s,headerHeight:r,toolbarHeight:a,availableHeight:l}),n.style.maxHeight=`${l}px`,n.style.overflowY="auto"},50)}else console.warn("⚠️ Missing codeElement or diff data");n&&(n.style.display="block",console.log("✅ Content area displayed"))}(e,c)):(console.log("⚠️ Displaying git diff error:",c),p(e,c))}catch(a){console.error("❌ Failed to fetch git diff:",a),console.error("Error details:",{name:a.name,message:a.message,stack:a.stack,filePath:t,timestamp:n,workingDir:i}),e.querySelector(".git-diff-loading").style.display="none";let o=`Network error: ${a.message}`,s=[];a.message.includes("Failed to fetch")?(o="Failed to connect to the monitoring server",s=["Check if the monitoring server is running on port 8765","Verify the port configuration in the dashboard","Check browser console for CORS or network errors","Try refreshing the page and reconnecting"]):a.message.includes("health check failed")?(o=a.message,s=["The server may be starting up - try again in a few seconds","Check if another process is using port 8765","Restart the claude-mpm monitoring server"]):a.message.includes("HTTP")&&(o=`Server error: ${a.message}`,s=["The server encountered an internal error","Check the server logs for more details","Try with a different file or working directory"]),p(e,{error:o,file_path:t,working_dir:i,suggestions:s,debug_info:{error_type:a.name,original_message:a.message,port:window.dashboard?.socketClient?.port||document.getElementById("port-input")?.value||"8765",timestamp:(new Date).toISOString()}})}}(i,e,t,n),i.style.display="flex",document.body.style.overflow="hidden"},window.hideGitDiffModal=function(){const e=document.getElementById("git-diff-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.copyGitDiff=function(){const e=document.getElementById("git-diff-modal");if(!e)return;const t=e.querySelector(".git-diff-code");if(!t)return;const n=t.textContent;if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(n).then(()=>{const t=e.querySelector(".git-diff-copy"),n=t.textContent;t.textContent="✅ Copied!",setTimeout(()=>{t.textContent=n},2e3)}).catch(e=>{console.error("Failed to copy text:",e)});else{const t=document.createElement("textarea");t.value=n,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t);const i=e.querySelector(".git-diff-copy"),o=i.textContent;i.textContent="✅ Copied!",setTimeout(()=>{i.textContent=o},2e3)}},window.showFileViewerModal=function(e){let t="";window.dashboard&&window.dashboard.currentWorkingDir&&(t=window.dashboard.currentWorkingDir);let n=document.getElementById("file-viewer-modal");n||(n=g(),document.body.appendChild(n)),h(n,e,t),n.style.display="flex",document.body.style.overflow="hidden"},window.hideFileViewerModal=function(){const e=document.getElementById("file-viewer-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.copyFileContent=function(){const e=document.getElementById("file-viewer-modal");if(!e)return;const t=e.querySelector(".file-content-code");if(!t)return;const n=t.textContent;if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(n).then(()=>{const t=e.querySelector(".file-content-copy"),n=t.textContent;t.textContent="✅ Copied!",setTimeout(()=>{t.textContent=n},2e3)}).catch(e=>{console.error("Failed to copy text:",e)});else{const t=document.createElement("textarea");t.value=n,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t);const i=e.querySelector(".file-content-copy"),o=i.textContent;i.textContent="✅ Copied!",setTimeout(()=>{i.textContent=o},2e3)}},window.showSearchViewerModal=function(e,t){let n=document.getElementById("search-viewer-modal");n||(n=function(){const e=document.createElement("div");return e.id="search-viewer-modal",e.className="modal search-viewer-modal",e.innerHTML='\n <div class="modal-content search-viewer-content">\n <div class="search-viewer-header">\n <h2 class="search-viewer-title">\n <span class="search-viewer-icon">🔍</span>\n <span class="search-viewer-title-text">Search Results</span>\n </h2>\n <button class="search-viewer-close" onclick="hideSearchViewerModal()">\n <span>×</span>\n </button>\n </div>\n <div class="search-viewer-body">\n <div class="search-params-section">\n <h3>Search Parameters</h3>\n <pre class="search-params-display"></pre>\n </div>\n <div class="search-results-section">\n <h3>Search Results</h3>\n <div class="search-results-display"></div>\n </div>\n </div>\n </div>\n ',e.addEventListener("click",t=>{t.target===e&&hideSearchViewerModal()}),document.addEventListener("keydown",t=>{"Escape"===t.key&&"flex"===e.style.display&&hideSearchViewerModal()}),e}(),document.body.appendChild(n)),function(e,t,n){const i=e.querySelector(".search-params-display"),o=e.querySelector(".search-results-display");i&&t&&(i.textContent=JSON.stringify(t,null,2));if(o&&n){let e="";"string"==typeof n?e=`<pre class="search-results-text">${u(n)}</pre>`:Array.isArray(n)?(e='<ul class="search-results-list">',n.forEach(t=>{e+="object"==typeof t?`<li><pre>${JSON.stringify(t,null,2)}</pre></li>`:`<li>${u(String(t))}</li>`}),e+="</ul>"):e="object"==typeof n?`<pre class="search-results-json">${JSON.stringify(n,null,2)}</pre>`:`<div class="search-results-text">${u(String(n))}</div>`,o.innerHTML=e}}(n,e,t),n.style.display="flex",document.body.style.overflow="hidden"},window.hideSearchViewerModal=function(){const e=document.getElementById("search-viewer-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.showAgentInstanceDetails=function(e){window.dashboard&&"function"==typeof window.dashboard.showAgentInstanceDetails?window.dashboard.showAgentInstanceDetails(e):console.error("Dashboard not available or method not found")},document.addEventListener("DOMContentLoaded",function(){window.dashboard=new d,console.log("Dashboard loaded and initialized")});
|
|
2
2
|
//# sourceMappingURL=dashboard.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const t=window.io;class e{constructor(){this.socket=null,this.port=null,this.connectionCallbacks={connect:[],disconnect:[],error:[],event:[]},this.isConnected=!1,this.isConnecting=!1,this.events=[],this.sessions=new Map,this.currentSessionId=null,this.startStatusCheckFallback()}connect(t="8765"){this.port=t;const e=`http://localhost:${t}`;if(this.socket&&(this.socket.connected||this.socket.connecting))return console.log("Already connected or connecting, disconnecting first..."),this.socket.disconnect(),void setTimeout(()=>this.doConnect(e),100);this.doConnect(e)}doConnect(e){if(console.log(`Connecting to Socket.IO server at ${e}`),void 0===t)return console.error("Socket.IO library not loaded! Make sure socket.io.min.js is loaded before this script."),void this.notifyConnectionStatus("Socket.IO library not loaded","error");this.isConnecting=!0,this.notifyConnectionStatus("Connecting...","connecting"),this.socket=t(e,{autoConnect:!0,reconnection:!0,reconnectionDelay:1e3,reconnectionDelayMax:1e4,maxReconnectionAttempts:10,timeout:1e4,forceNew:!0,transports:["websocket","polling"]}),this.setupSocketHandlers()}setupSocketHandlers(){this.socket.on("connect",()=>{console.log("Connected to Socket.IO server"),this.isConnected=!0,this.isConnecting=!1,this.notifyConnectionStatus("Connected","connected"),this.connectionCallbacks.connect.forEach(t=>t(this.socket.id)),this.requestStatus()}),this.socket.on("disconnect",t=>{console.log("Disconnected from server:",t),this.isConnected=!1,this.isConnecting=!1,this.notifyConnectionStatus(`Disconnected: ${t}`,"disconnected"),this.connectionCallbacks.disconnect.forEach(e=>e(t))}),this.socket.on("connect_error",t=>{console.error("Connection error:",t),this.isConnecting=!1;const e=t.message||t.description||"Unknown error";this.notifyConnectionStatus(`Connection Error: ${e}`,"disconnected"),this.addEvent({type:"connection.error",timestamp:(new Date).toISOString(),data:{error:e,url:this.socket.io.uri}}),this.connectionCallbacks.error.forEach(t=>t(e))}),this.socket.on("claude_event",t=>{const e=this.transformEvent(t);this.addEvent(e)}),this.socket.on("session.started",t=>{this.addEvent({type:"session",subtype:"started",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("session.ended",t=>{this.addEvent({type:"session",subtype:"ended",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("claude.request",t=>{this.addEvent({type:"claude",subtype:"request",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("claude.response",t=>{this.addEvent({type:"claude",subtype:"response",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("agent.loaded",t=>{this.addEvent({type:"agent",subtype:"loaded",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("agent.executed",t=>{this.addEvent({type:"agent",subtype:"executed",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("hook.pre",t=>{this.addEvent({type:"hook",subtype:"pre",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("hook.post",t=>{this.addEvent({type:"hook",subtype:"post",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("todo.updated",t=>{this.addEvent({type:"todo",subtype:"updated",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("memory.operation",t=>{this.addEvent({type:"memory",subtype:"operation",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("log.entry",t=>{this.addEvent({type:"log",subtype:"entry",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("history",t=>{console.log("Received event history:",t),t&&Array.isArray(t.events)?(console.log(`Processing ${t.events.length} historical events (${t.count} sent, ${t.total_available} total available)`),t.events.forEach(t=>{const e=this.transformEvent(t);this.addEvent(e,!1)}),this.notifyEventUpdate(),console.log(`Event history loaded: ${t.events.length} events added to dashboard`)):Array.isArray(t)&&(console.log("Received legacy event history format:",t.length,"events"),t.forEach(t=>{const e=this.transformEvent(t);this.addEvent(e,!1)}),this.notifyEventUpdate())}),this.socket.on("system.status",t=>{console.log("Received system status:",t),t.sessions&&this.updateSessions(t.sessions),t.current_session&&(this.currentSessionId=t.current_session)})}disconnect(){this.socket&&(this.socket.disconnect(),this.socket=null),this.port=null,this.isConnected=!1,this.isConnecting=!1}requestStatus(){this.socket&&this.socket.connected&&(console.log("Requesting server status..."),this.socket.emit("request.status"))}requestHistory(t={}){if(this.socket&&this.socket.connected){const e={limit:t.limit||50,event_types:t.event_types||[]};console.log("Requesting event history...",e),this.socket.emit("get_history",e)}else console.warn("Cannot request history: not connected to server")}addEvent(t,e=!0){if(t.timestamp||(t.timestamp=(new Date).toISOString()),t.id||(t.id=Date.now()+Math.random()),this.events.push(t),t.data&&t.data.session_id){const e=t.data.session_id;this.sessions.has(e)||this.sessions.set(e,{id:e,startTime:t.timestamp,lastActivity:t.timestamp,eventCount:0});const n=this.sessions.get(e);n.lastActivity=t.timestamp,n.eventCount++}e&&this.notifyEventUpdate()}updateSessions(t){Array.isArray(t)&&t.forEach(t=>{this.sessions.set(t.id,t)})}clearEvents(){this.events=[],this.sessions.clear(),this.notifyEventUpdate()}refreshHistory(t={}){this.clearEvents(),this.requestHistory(t)}getEventsBySession(t=null){return t?this.events.filter(e=>e.data&&e.data.session_id===t):this.events}onConnection(t,e){this.connectionCallbacks[t]&&this.connectionCallbacks[t].push(e)}onEventUpdate(t){this.connectionCallbacks.event.push(t)}notifyConnectionStatus(t,e){console.log(`SocketClient: Connection status changed to '${t}' (${e})`),this.updateConnectionStatusDOM(t,e),document.dispatchEvent(new CustomEvent("socketConnectionStatus",{detail:{status:t,type:e}}))}updateConnectionStatusDOM(t,e){const n=document.getElementById("connection-status");n?(n.innerHTML=`<span>●</span> ${t}`,n.className=`status-badge status-${e}`,console.log(`SocketClient: Direct DOM update - status: '${t}' (${e})`)):console.warn("SocketClient: Could not find connection-status element in DOM")}notifyEventUpdate(){this.connectionCallbacks.event.forEach(t=>t(this.events,this.sessions)),document.dispatchEvent(new CustomEvent("socketEventUpdate",{detail:{events:this.events,sessions:this.sessions}}))}getConnectionState(){return{isConnected:this.isConnected,isConnecting:this.isConnecting,socketId:this.socket?this.socket.id:null}}transformEvent(t){if(!t)return t;let e={...t};if(!t.type&&t.event){const n=t.event;"TestStart"===n||"TestEnd"===n?(e.type="test",e.subtype=n.toLowerCase().replace("test","")):"SubagentStart"===n||"SubagentStop"===n?(e.type="subagent",e.subtype=n.toLowerCase().replace("subagent","")):"ToolCall"===n?(e.type="tool",e.subtype="call"):"UserPrompt"===n?(e.type="hook",e.subtype="user_prompt"):(e.type="unknown",e.subtype=n.toLowerCase(),e.type===e.subtype&&(e.subtype="event")),delete e.event}else if(t.type){const n=t.type;if(n.startsWith("hook.")){const t=n.substring(5);e.type="hook",e.subtype=t}else if(n.includes(".")){const[t,...s]=n.split(".");e.type=t,e.subtype=s.join(".")}}else e.type="unknown",e.subtype="";if(!t.type&&t.event?e.originalEventName=t.event:t.type&&(e.originalEventName=t.type),t.data&&"object"==typeof t.data){const n=["type","subtype","timestamp","id","event","event_type","originalEventName"];Object.keys(t.data).forEach(s=>{n.includes(s)?console.warn(`Protected field '${s}' in data object was not copied to top level to preserve event structure`):e[s]=t.data[s]}),e.data=t.data}return"hook"!==e.type||"pre_tool"!==e.subtype&&"post_tool"!==e.subtype||console.log("Transformed tool event:",{type:e.type,subtype:e.subtype,tool_name:e.tool_name,has_data:!!e.data,keys:Object.keys(e).filter(t=>"data"!==t)}),e}getState(){return{events:this.events,sessions:this.sessions,currentSessionId:this.currentSessionId}}startStatusCheckFallback(){setInterval(()=>{this.checkAndUpdateStatus()},2e3),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>this.checkAndUpdateStatus(),100)}):setTimeout(()=>this.checkAndUpdateStatus(),100)}checkAndUpdateStatus(){let t="Disconnected",e="disconnected";this.socket&&(this.socket.connected?(t="Connected",e="connected",this.isConnected=!0,this.isConnecting=!1):this.socket.connecting||this.isConnecting?(t="Connecting...",e="connecting",this.isConnected=!1):(t="Disconnected",e="disconnected",this.isConnected=!1,this.isConnecting=!1));const n=document.getElementById("connection-status");if(n){const s=n.textContent.replace("●","").trim(),o=n.className,i=`status-badge status-${e}`;s===t&&o===i||(console.log(`SocketClient: Fallback update - was '${s}' (${o}), now '${t}' (${i})`),this.updateConnectionStatusDOM(t,e))}}}window.SocketClient=e;class n{constructor(){this.socketClient=null,this.connectionCallbacks=new Set,this.eventUpdateCallbacks=new Set,this.socketClient=new e,window.socketClient=this.socketClient,this.setupSocketEventHandlers(),setTimeout(()=>{this.updateInitialConnectionStatus()},100),console.log("Socket manager initialized")}setupSocketEventHandlers(){document.addEventListener("socketConnectionStatus",t=>{console.log(`SocketManager: Processing connection status update: ${t.detail.status} (${t.detail.type})`),this.handleConnectionStatusChange(t.detail.status,t.detail.type),this.connectionCallbacks.forEach(e=>{try{e(t.detail.status,t.detail.type)}catch(n){console.error("Error in connection callback:",n)}})}),this.socketClient&&this.socketClient.onEventUpdate(t=>{this.eventUpdateCallbacks.forEach(e=>{try{e(t)}catch(n){console.error("Error in event update callback:",n)}})})}handleConnectionStatusChange(t,e){this.updateConnectionStatus(t,e),"connected"===e&&this.socketClient&&this.socketClient.socket&&this.setupGitBranchListener()}updateInitialConnectionStatus(){console.log("SocketManager: Updating initial connection status"),this.socketClient&&"function"==typeof this.socketClient.checkAndUpdateStatus?(console.log("SocketManager: Using socket client checkAndUpdateStatus method"),this.socketClient.checkAndUpdateStatus()):this.socketClient&&this.socketClient.socket?(console.log("SocketManager: Checking socket state directly",{connected:this.socketClient.socket.connected,connecting:this.socketClient.socket.connecting,isConnecting:this.socketClient.isConnecting,isConnected:this.socketClient.isConnected}),this.socketClient.socket.connected?(console.log("SocketManager: Socket is already connected, updating status"),this.updateConnectionStatus("Connected","connected")):this.socketClient.isConnecting||this.socketClient.socket.connecting?(console.log("SocketManager: Socket is connecting, updating status"),this.updateConnectionStatus("Connecting...","connecting")):(console.log("SocketManager: Socket is disconnected, updating status"),this.updateConnectionStatus("Disconnected","disconnected"))):(console.log("SocketManager: No socket client or socket found, setting disconnected status"),this.updateConnectionStatus("Disconnected","disconnected")),setTimeout(()=>{console.log("SocketManager: Secondary status check after 1 second"),this.socketClient&&this.socketClient.socket&&this.socketClient.socket.connected&&(console.log("SocketManager: Socket connected in secondary check, updating status"),this.updateConnectionStatus("Connected","connected"))},1e3)}setupGitBranchListener(){this.socketClient.socket.off("git_branch_response"),this.socketClient.socket.on("git_branch_response",t=>{if(t.success){const e=document.getElementById("footer-git-branch");e&&(e.textContent=t.branch||"unknown"),e&&(e.style.display="inline")}else console.error("Git branch request failed:",t.error)})}updateConnectionStatus(t,e){const n=document.getElementById("connection-status");if(n){if(n.querySelector("span")){const e="●";n.innerHTML=`<span>${e}</span> ${t}`}else n.textContent=t;n.className=`status-badge status-${e}`,console.log(`SocketManager: UI updated - status: '${t}' (${e})`)}else console.error("SocketManager: Could not find connection-status element in DOM")}connect(t){this.socketClient&&this.socketClient.connect(t)}disconnect(){this.socketClient&&this.socketClient.disconnect()}isConnected(){return this.socketClient&&this.socketClient.isConnected}isConnecting(){return this.socketClient&&this.socketClient.isConnecting}getSocketClient(){return this.socketClient}getSocket(){return this.socketClient?this.socketClient.socket:null}onConnectionStatusChange(t){this.connectionCallbacks.add(t)}offConnectionStatusChange(t){this.connectionCallbacks.delete(t)}onEventUpdate(t){this.eventUpdateCallbacks.add(t)}offEventUpdate(t){this.eventUpdateCallbacks.delete(t)}toggleConnectionControls(){const t=document.getElementById("connection-controls-row"),e=document.getElementById("connection-toggle-btn");if(t&&e){t.classList.contains("show")?(t.classList.remove("show"),t.style.display="none",e.textContent="Connection Settings"):(t.classList.add("show"),t.style.display="block",e.textContent="Hide Settings")}}setupConnectionControls(){const t=document.getElementById("connect-btn"),e=document.getElementById("disconnect-btn"),n=document.getElementById("connection-toggle-btn");t&&t.addEventListener("click",()=>{const t=document.getElementById("port-input").value||8765;this.connect(t)}),e&&e.addEventListener("click",()=>{this.disconnect()}),n&&n.addEventListener("click",()=>{this.toggleConnectionControls()})}initializeFromURL(t){const e=t.get("port"),n=document.getElementById("port-input");let s=e;s||"http:"!==window.location.protocol||(s=window.location.port||"8765"),s||(s=n?.value||"8765"),n&&(n.value=s);!("false"!==t.get("connect"))||this.isConnected()||this.isConnecting()||this.connect(s)}}class s{constructor(){this.currentTab="events",this.autoScroll=!0,this.selectedCard={tab:null,index:null,type:null,data:null},this.tabNavigation={events:{selectedIndex:-1,items:[]},agents:{selectedIndex:-1,items:[]},tools:{selectedIndex:-1,items:[]},files:{selectedIndex:-1,items:[]}},this.setupEventHandlers(),console.log("UI state manager initialized")}setupEventHandlers(){this.setupTabNavigation(),this.setupUnifiedKeyboardNavigation()}setupTabNavigation(){document.querySelectorAll(".tab-button").forEach(t=>{t.addEventListener("click",()=>{const e=this.getTabNameFromButton(t);this.switchTab(e)})})}setupUnifiedKeyboardNavigation(){document.addEventListener("keydown",t=>{document.activeElement&&["INPUT","TEXTAREA","SELECT"].includes(document.activeElement.tagName)||("ArrowUp"===t.key||"ArrowDown"===t.key?(t.preventDefault(),this.handleUnifiedArrowNavigation("ArrowDown"===t.key?1:-1)):"Enter"===t.key?(t.preventDefault(),this.handleUnifiedEnterKey()):"Escape"===t.key&&this.clearUnifiedSelection())})}getTabNameFromButton(t){const e=t.textContent.toLowerCase();return e.includes("events")?"events":e.includes("agents")?"agents":e.includes("tools")?"tools":e.includes("files")?"files":"events"}switchTab(t){console.log(`[DEBUG] switchTab called with tabName: ${t}`);const e=this.currentTab;this.currentTab=t,document.querySelectorAll(".tab-button").forEach(e=>{e.classList.remove("active"),this.getTabNameFromButton(e)===t&&e.classList.add("active")}),document.querySelectorAll(".tab-content").forEach(t=>{t.classList.remove("active")});const n=document.getElementById(`${t}-tab`);n&&n.classList.add("active"),this.clearUnifiedSelection(),document.dispatchEvent(new CustomEvent("tabChanged",{detail:{newTab:t,previousTab:e}})),setTimeout(()=>{this.autoScroll&&this.scrollCurrentTabToBottom()},100)}handleUnifiedArrowNavigation(t){const e=this.tabNavigation[this.currentTab];if(!e)return;let n=e.selectedIndex+t;0!==e.items.length&&(n<0?n=e.items.length-1:n>=e.items.length&&(n=0),this.selectCardByIndex(this.currentTab,n))}handleUnifiedEnterKey(){const t=this.tabNavigation[this.currentTab];if(!t||-1===t.selectedIndex)return;const e=t.items[t.selectedIndex];e&&e.onclick&&e.onclick()}clearUnifiedSelection(){Object.keys(this.tabNavigation).forEach(t=>{this.tabNavigation[t].selectedIndex=-1}),this.clearCardSelection()}updateTabNavigationItems(){const t=this.tabNavigation[this.currentTab];if(!t)return;let e;switch(this.currentTab){case"events":e="#events-list .event-item";break;case"agents":e="#agents-list .event-item";break;case"tools":e="#tools-list .event-item";break;case"files":e="#files-list .event-item"}e&&(t.items=Array.from(document.querySelectorAll(e)))}selectCardByIndex(t,e){const n=this.tabNavigation[t];if(!n||e<0||e>=n.items.length)return;n.selectedIndex=e,this.updateUnifiedSelectionUI();n.items[e]&&this.selectCard(t,e,this.getCardType(t),e),this.showCardDetails(t,e)}updateUnifiedSelectionUI(){document.querySelectorAll(".event-item.keyboard-selected").forEach(t=>{t.classList.remove("keyboard-selected")});const t=this.tabNavigation[this.currentTab];t&&-1!==t.selectedIndex&&t.items[t.selectedIndex]&&t.items[t.selectedIndex].classList.add("keyboard-selected")}showCardDetails(t,e){document.dispatchEvent(new CustomEvent("showCardDetails",{detail:{tabName:t,index:e}}))}selectCard(t,e,n,s){this.clearCardSelection(),this.selectedCard={tab:t,index:e,type:n,data:s},this.updateCardSelectionUI(),console.log("Card selected:",this.selectedCard)}clearCardSelection(){document.querySelectorAll(".event-item.selected, .file-item.selected").forEach(t=>{t.classList.remove("selected")}),this.selectedCard={tab:null,index:null,type:null,data:null}}updateCardSelectionUI(){if(!this.selectedCard.tab||null===this.selectedCard.index)return;let t;switch(this.selectedCard.tab){case"events":t=document.getElementById("events-list");break;case"agents":t=document.getElementById("agents-list");break;case"tools":t=document.getElementById("tools-list");break;case"files":t=document.getElementById("files-list")}if(t){const e=t.querySelectorAll(".event-item, .file-item");e[this.selectedCard.index]&&e[this.selectedCard.index].classList.add("selected")}}getCardType(t){switch(t){case"events":return"event";case"agents":return"agent";case"tools":return"tool";case"files":return"file";default:return"unknown"}}scrollCurrentTabToBottom(){const t=`${this.currentTab}-list`,e=document.getElementById(t);e&&this.autoScroll&&(e.scrollTop=e.scrollHeight)}clearSelection(){this.clearCardSelection(),this.clearUnifiedSelection()}getCurrentTab(){return this.currentTab}getSelectedCard(){return{...this.selectedCard}}getTabNavigation(){return{...this.tabNavigation}}setAutoScroll(t){this.autoScroll=t}getAutoScroll(){return this.autoScroll}}export{n as S,s as U};
|
|
1
|
+
const t=window.io;class e{constructor(){this.socket=null,this.port=null,this.connectionCallbacks={connect:[],disconnect:[],error:[],event:[]},this.isConnected=!1,this.isConnecting=!1,this.lastConnectTime=null,this.disconnectTime=null,this.events=[],this.sessions=new Map,this.currentSessionId=null,this.eventQueue=[],this.maxQueueSize=100,this.retryAttempts=0,this.maxRetryAttempts=3,this.retryDelays=[1e3,2e3,4e3],this.pendingEmissions=new Map,this.lastPingTime=null,this.lastPongTime=null,this.pingTimeout=4e4,this.healthCheckInterval=null,this.startStatusCheckFallback(),this.startHealthMonitoring()}connect(t="8765"){this.port=t;const e=`http://localhost:${t}`;if(this.socket&&(this.socket.connected||this.socket.connecting))return console.log("Already connected or connecting, disconnecting first..."),this.socket.disconnect(),void setTimeout(()=>this.doConnect(e),100);this.doConnect(e)}doConnect(e){if(console.log(`Connecting to Socket.IO server at ${e}`),void 0===t)return console.error("Socket.IO library not loaded! Make sure socket.io.min.js is loaded before this script."),void this.notifyConnectionStatus("Socket.IO library not loaded","error");this.isConnecting=!0,this.notifyConnectionStatus("Connecting...","connecting"),this.socket=t(e,{autoConnect:!0,reconnection:!0,reconnectionDelay:1e3,reconnectionDelayMax:1e4,maxReconnectionAttempts:10,timeout:1e4,forceNew:!0,transports:["websocket","polling"]}),this.setupSocketHandlers()}setupSocketHandlers(){this.socket.on("connect",()=>{console.log("Connected to Socket.IO server");const t=this.isConnected;if(this.isConnected=!0,this.isConnecting=!1,this.lastConnectTime=Date.now(),this.retryAttempts=0,this.disconnectTime&&!1===t){const t=(Date.now()-this.disconnectTime)/1e3;console.log(`Reconnected after ${t.toFixed(1)}s downtime`),this.flushEventQueue()}this.notifyConnectionStatus("Connected","connected"),this.connectionCallbacks.connect.forEach(t=>t(this.socket.id)),this.requestStatus()}),this.socket.on("disconnect",t=>{if(console.log("Disconnected from server:",t),this.isConnected=!1,this.isConnecting=!1,this.disconnectTime=Date.now(),this.lastConnectTime){const t=(Date.now()-this.lastConnectTime)/1e3;console.log(`Connection uptime was ${t.toFixed(1)}s`)}this.notifyConnectionStatus(`Disconnected: ${t}`,"disconnected"),this.connectionCallbacks.disconnect.forEach(e=>e(t)),"transport close"!==t&&"ping timeout"!==t||this.scheduleReconnect()}),this.socket.on("connect_error",t=>{console.error("Connection error:",t),this.isConnecting=!1;const e=t.message||t.description||"Unknown error";this.notifyConnectionStatus(`Connection Error: ${e}`,"disconnected"),this.addEvent({type:"connection.error",timestamp:(new Date).toISOString(),data:{error:e,url:this.socket.io.uri,retry_attempt:this.retryAttempts}}),this.connectionCallbacks.error.forEach(t=>t(e)),this.scheduleReconnect()}),this.socket.on("claude_event",t=>{const e=this.transformEvent(t);this.addEvent(e)}),this.socket.on("ping",t=>{this.lastPingTime=Date.now(),this.socket.emit("pong",{timestamp:t.timestamp,client_time:Date.now()})}),this.socket.on("session.started",t=>{this.addEvent({type:"session",subtype:"started",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("session.ended",t=>{this.addEvent({type:"session",subtype:"ended",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("claude.request",t=>{this.addEvent({type:"claude",subtype:"request",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("claude.response",t=>{this.addEvent({type:"claude",subtype:"response",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("agent.loaded",t=>{this.addEvent({type:"agent",subtype:"loaded",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("agent.executed",t=>{this.addEvent({type:"agent",subtype:"executed",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("hook.pre",t=>{this.addEvent({type:"hook",subtype:"pre",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("hook.post",t=>{this.addEvent({type:"hook",subtype:"post",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("todo.updated",t=>{this.addEvent({type:"todo",subtype:"updated",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("memory.operation",t=>{this.addEvent({type:"memory",subtype:"operation",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("log.entry",t=>{this.addEvent({type:"log",subtype:"entry",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("history",t=>{console.log("Received event history:",t),t&&Array.isArray(t.events)?(console.log(`Processing ${t.events.length} historical events (${t.count} sent, ${t.total_available} total available)`),t.events.forEach(t=>{const e=this.transformEvent(t);this.addEvent(e,!1)}),this.notifyEventUpdate(),console.log(`Event history loaded: ${t.events.length} events added to dashboard`)):Array.isArray(t)&&(console.log("Received legacy event history format:",t.length,"events"),t.forEach(t=>{const e=this.transformEvent(t);this.addEvent(e,!1)}),this.notifyEventUpdate())}),this.socket.on("system.status",t=>{console.log("Received system status:",t),t.sessions&&this.updateSessions(t.sessions),t.current_session&&(this.currentSessionId=t.current_session)})}disconnect(){this.socket&&(this.socket.disconnect(),this.socket=null),this.port=null,this.isConnected=!1,this.isConnecting=!1}emitWithRetry(t,e=null,n={}){const{maxRetries:s=3,retryDelays:o=[1e3,2e3,4e3],onSuccess:i=null,onFailure:c=null}=n,a=`${t}_${Date.now()}_${Math.random()}`,l=(n=0)=>{if(this.socket&&this.socket.connected)try{this.socket.emit(t,e),console.log(`Emitted ${t} successfully`),this.pendingEmissions.delete(a),i&&i()}catch(r){if(console.error(`Failed to emit ${t} (attempt ${n+1}):`,r),n<s-1){const s=o[n]||o[o.length-1];console.log(`Retrying ${t} in ${s}ms...`),this.pendingEmissions.set(a,{event:t,data:e,attemptNum:n+1,scheduledTime:Date.now()+s}),setTimeout(()=>l(n+1),s)}else console.error(`Failed to emit ${t} after ${s} attempts`),this.pendingEmissions.delete(a),c&&c("max_retries_exceeded")}else 0===n&&(this.queueEvent(t,e),console.log(`Queued ${t} for later emission (disconnected)`),c&&c("disconnected"))};l()}queueEvent(t,e){if(this.eventQueue.length>=this.maxQueueSize){const t=this.eventQueue.shift();console.warn(`Event queue full, dropped oldest event: ${t.event}`)}this.eventQueue.push({event:t,data:e,timestamp:Date.now()})}flushEventQueue(){if(0===this.eventQueue.length)return;console.log(`Flushing ${this.eventQueue.length} queued events...`);const t=[...this.eventQueue];this.eventQueue=[],t.forEach((t,e)=>{setTimeout(()=>{this.socket&&this.socket.connected&&(this.socket.emit(t.event,t.data),console.log(`Flushed queued event: ${t.event}`))},100*e)})}scheduleReconnect(){if(this.retryAttempts>=this.maxRetryAttempts)return console.log("Max reconnection attempts reached, stopping auto-reconnect"),void this.notifyConnectionStatus("Reconnection failed","disconnected");const t=this.retryDelays[this.retryAttempts]||this.retryDelays[this.retryDelays.length-1];this.retryAttempts++,console.log(`Scheduling reconnect attempt ${this.retryAttempts}/${this.maxRetryAttempts} in ${t}ms...`),this.notifyConnectionStatus(`Reconnecting in ${t/1e3}s...`,"connecting"),setTimeout(()=>{!this.isConnected&&this.port&&(console.log(`Attempting reconnection ${this.retryAttempts}/${this.maxRetryAttempts}...`),this.connect(this.port))},t)}requestStatus(){this.socket&&this.socket.connected&&(console.log("Requesting server status..."),this.emitWithRetry("request.status",null,{maxRetries:2,retryDelays:[500,1e3]}))}requestHistory(t={}){if(this.socket&&this.socket.connected){const e={limit:t.limit||50,event_types:t.event_types||[]};console.log("Requesting event history...",e),this.emitWithRetry("get_history",e,{maxRetries:3,retryDelays:[1e3,2e3,3e3],onFailure:t=>{console.error(`Failed to request history: ${t}`)}})}else console.warn("Cannot request history: not connected to server")}addEvent(t,e=!0){if(t.timestamp||(t.timestamp=(new Date).toISOString()),t.id||(t.id=Date.now()+Math.random()),this.events.push(t),t.data&&t.data.session_id){const e=t.data.session_id;this.sessions.has(e)||this.sessions.set(e,{id:e,startTime:t.timestamp,lastActivity:t.timestamp,eventCount:0});const n=this.sessions.get(e);n.lastActivity=t.timestamp,n.eventCount++}e&&this.notifyEventUpdate()}updateSessions(t){Array.isArray(t)&&t.forEach(t=>{this.sessions.set(t.id,t)})}clearEvents(){this.events=[],this.sessions.clear(),this.notifyEventUpdate()}refreshHistory(t={}){this.clearEvents(),this.requestHistory(t)}getEventsBySession(t=null){return t?this.events.filter(e=>e.data&&e.data.session_id===t):this.events}onConnection(t,e){this.connectionCallbacks[t]&&this.connectionCallbacks[t].push(e)}onEventUpdate(t){this.connectionCallbacks.event.push(t)}notifyConnectionStatus(t,e){console.log(`SocketClient: Connection status changed to '${t}' (${e})`),this.updateConnectionStatusDOM(t,e),document.dispatchEvent(new CustomEvent("socketConnectionStatus",{detail:{status:t,type:e}}))}updateConnectionStatusDOM(t,e){const n=document.getElementById("connection-status");n?(n.innerHTML=`<span>●</span> ${t}`,n.className=`status-badge status-${e}`,console.log(`SocketClient: Direct DOM update - status: '${t}' (${e})`)):console.warn("SocketClient: Could not find connection-status element in DOM")}notifyEventUpdate(){this.connectionCallbacks.event.forEach(t=>t(this.events,this.sessions)),document.dispatchEvent(new CustomEvent("socketEventUpdate",{detail:{events:this.events,sessions:this.sessions}}))}getConnectionState(){return{isConnected:this.isConnected,isConnecting:this.isConnecting,socketId:this.socket?this.socket.id:null}}transformEvent(t){if(!t)return t;let e={...t};if(!t.type&&t.event){const n=t.event;"TestStart"===n||"TestEnd"===n?(e.type="test",e.subtype=n.toLowerCase().replace("test","")):"SubagentStart"===n||"SubagentStop"===n?(e.type="subagent",e.subtype=n.toLowerCase().replace("subagent","")):"ToolCall"===n?(e.type="tool",e.subtype="call"):"UserPrompt"===n?(e.type="hook",e.subtype="user_prompt"):(e.type="unknown",e.subtype=n.toLowerCase(),e.type===e.subtype&&(e.subtype="event")),delete e.event}else if(t.type){const n=t.type;if(n.startsWith("hook.")){const t=n.substring(5);e.type="hook",e.subtype=t}else if(n.includes(".")){const[t,...s]=n.split(".");e.type=t,e.subtype=s.join(".")}}else e.type="unknown",e.subtype="";if(!t.type&&t.event?e.originalEventName=t.event:t.type&&(e.originalEventName=t.type),t.data&&"object"==typeof t.data){const n=["type","subtype","timestamp","id","event","event_type","originalEventName"];Object.keys(t.data).forEach(s=>{n.includes(s)?console.warn(`Protected field '${s}' in data object was not copied to top level to preserve event structure`):e[s]=t.data[s]}),e.data=t.data}return"hook"!==e.type||"pre_tool"!==e.subtype&&"post_tool"!==e.subtype||console.log("Transformed tool event:",{type:e.type,subtype:e.subtype,tool_name:e.tool_name,has_data:!!e.data,keys:Object.keys(e).filter(t=>"data"!==t)}),e}getState(){return{events:this.events,sessions:this.sessions,currentSessionId:this.currentSessionId}}startHealthMonitoring(){this.healthCheckInterval=setInterval(()=>{if(this.isConnected&&this.lastPingTime){const t=Date.now()-this.lastPingTime;t>this.pingTimeout&&(console.warn(`No ping from server for ${t/1e3}s, connection may be stale`),this.socket&&(console.log("Forcing reconnection due to stale connection..."),this.socket.disconnect(),setTimeout(()=>{this.port&&this.connect(this.port)},1e3)))}},1e4)}stopHealthMonitoring(){this.healthCheckInterval&&(clearInterval(this.healthCheckInterval),this.healthCheckInterval=null)}startStatusCheckFallback(){setInterval(()=>{this.checkAndUpdateStatus()},2e3),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>this.checkAndUpdateStatus(),100)}):setTimeout(()=>this.checkAndUpdateStatus(),100)}checkAndUpdateStatus(){let t="Disconnected",e="disconnected";this.socket&&(this.socket.connected?(t="Connected",e="connected",this.isConnected=!0,this.isConnecting=!1):this.socket.connecting||this.isConnecting?(t="Connecting...",e="connecting",this.isConnected=!1):(t="Disconnected",e="disconnected",this.isConnected=!1,this.isConnecting=!1));const n=document.getElementById("connection-status");if(n){const s=n.textContent.replace("●","").trim(),o=n.className,i=`status-badge status-${e}`;s===t&&o===i||(console.log(`SocketClient: Fallback update - was '${s}' (${o}), now '${t}' (${i})`),this.updateConnectionStatusDOM(t,e))}}destroy(){this.stopHealthMonitoring(),this.socket&&(this.socket.disconnect(),this.socket=null),this.eventQueue=[],this.pendingEmissions.clear()}getConnectionMetrics(){return{isConnected:this.isConnected,uptime:this.lastConnectTime?(Date.now()-this.lastConnectTime)/1e3:0,lastPing:this.lastPingTime?(Date.now()-this.lastPingTime)/1e3:null,queuedEvents:this.eventQueue.length,pendingEmissions:this.pendingEmissions.size,retryAttempts:this.retryAttempts}}}window.SocketClient=e;class n{constructor(){this.socketClient=null,this.connectionCallbacks=new Set,this.eventUpdateCallbacks=new Set,this.socketClient=new e,window.socketClient=this.socketClient,this.setupSocketEventHandlers(),setTimeout(()=>{this.updateInitialConnectionStatus()},100),console.log("Socket manager initialized")}setupSocketEventHandlers(){document.addEventListener("socketConnectionStatus",t=>{console.log(`SocketManager: Processing connection status update: ${t.detail.status} (${t.detail.type})`),this.handleConnectionStatusChange(t.detail.status,t.detail.type),this.connectionCallbacks.forEach(e=>{try{e(t.detail.status,t.detail.type)}catch(n){console.error("Error in connection callback:",n)}})}),this.socketClient&&this.socketClient.onEventUpdate(t=>{this.eventUpdateCallbacks.forEach(e=>{try{e(t)}catch(n){console.error("Error in event update callback:",n)}})})}handleConnectionStatusChange(t,e){this.updateConnectionStatus(t,e),"connected"===e&&this.socketClient&&this.socketClient.socket&&this.setupGitBranchListener()}updateInitialConnectionStatus(){console.log("SocketManager: Updating initial connection status"),this.socketClient&&"function"==typeof this.socketClient.checkAndUpdateStatus?(console.log("SocketManager: Using socket client checkAndUpdateStatus method"),this.socketClient.checkAndUpdateStatus()):this.socketClient&&this.socketClient.socket?(console.log("SocketManager: Checking socket state directly",{connected:this.socketClient.socket.connected,connecting:this.socketClient.socket.connecting,isConnecting:this.socketClient.isConnecting,isConnected:this.socketClient.isConnected}),this.socketClient.socket.connected?(console.log("SocketManager: Socket is already connected, updating status"),this.updateConnectionStatus("Connected","connected")):this.socketClient.isConnecting||this.socketClient.socket.connecting?(console.log("SocketManager: Socket is connecting, updating status"),this.updateConnectionStatus("Connecting...","connecting")):(console.log("SocketManager: Socket is disconnected, updating status"),this.updateConnectionStatus("Disconnected","disconnected"))):(console.log("SocketManager: No socket client or socket found, setting disconnected status"),this.updateConnectionStatus("Disconnected","disconnected")),setTimeout(()=>{console.log("SocketManager: Secondary status check after 1 second"),this.socketClient&&this.socketClient.socket&&this.socketClient.socket.connected&&(console.log("SocketManager: Socket connected in secondary check, updating status"),this.updateConnectionStatus("Connected","connected"))},1e3)}setupGitBranchListener(){this.socketClient.socket.off("git_branch_response"),this.socketClient.socket.on("git_branch_response",t=>{if(t.success){const e=document.getElementById("footer-git-branch");e&&(e.textContent=t.branch||"unknown"),e&&(e.style.display="inline")}else console.error("Git branch request failed:",t.error)})}updateConnectionStatus(t,e){const n=document.getElementById("connection-status");if(n){if(n.querySelector("span")){const e="●";n.innerHTML=`<span>${e}</span> ${t}`}else n.textContent=t;n.className=`status-badge status-${e}`,console.log(`SocketManager: UI updated - status: '${t}' (${e})`)}else console.error("SocketManager: Could not find connection-status element in DOM")}connect(t){this.socketClient&&this.socketClient.connect(t)}disconnect(){this.socketClient&&this.socketClient.disconnect()}isConnected(){return this.socketClient&&this.socketClient.isConnected}isConnecting(){return this.socketClient&&this.socketClient.isConnecting}getSocketClient(){return this.socketClient}getSocket(){return this.socketClient?this.socketClient.socket:null}onConnectionStatusChange(t){this.connectionCallbacks.add(t)}offConnectionStatusChange(t){this.connectionCallbacks.delete(t)}onEventUpdate(t){this.eventUpdateCallbacks.add(t)}offEventUpdate(t){this.eventUpdateCallbacks.delete(t)}toggleConnectionControls(){const t=document.getElementById("connection-controls-row"),e=document.getElementById("connection-toggle-btn");if(t&&e){t.classList.contains("show")?(t.classList.remove("show"),t.style.display="none",e.textContent="Connection Settings"):(t.classList.add("show"),t.style.display="block",e.textContent="Hide Settings")}}setupConnectionControls(){const t=document.getElementById("connect-btn"),e=document.getElementById("disconnect-btn"),n=document.getElementById("connection-toggle-btn");t&&t.addEventListener("click",()=>{const t=document.getElementById("port-input").value||8765;this.connect(t)}),e&&e.addEventListener("click",()=>{this.disconnect()}),n&&n.addEventListener("click",()=>{this.toggleConnectionControls()})}initializeFromURL(t){const e=t.get("port"),n=document.getElementById("port-input");let s=e;s||"http:"!==window.location.protocol||(s=window.location.port||"8765"),s||(s=n?.value||"8765"),n&&(n.value=s);!("false"!==t.get("connect"))||this.isConnected()||this.isConnecting()||this.connect(s)}}class s{constructor(){this.currentTab="events",this.autoScroll=!0,this.selectedCard={tab:null,index:null,type:null,data:null},this.tabNavigation={events:{selectedIndex:-1,items:[]},agents:{selectedIndex:-1,items:[]},tools:{selectedIndex:-1,items:[]},files:{selectedIndex:-1,items:[]}},this.setupEventHandlers(),console.log("UI state manager initialized")}setupEventHandlers(){this.setupTabNavigation(),this.setupUnifiedKeyboardNavigation()}setupTabNavigation(){document.querySelectorAll(".tab-button").forEach(t=>{t.addEventListener("click",()=>{const e=this.getTabNameFromButton(t);this.switchTab(e)})})}setupUnifiedKeyboardNavigation(){document.addEventListener("keydown",t=>{document.activeElement&&["INPUT","TEXTAREA","SELECT"].includes(document.activeElement.tagName)||("ArrowUp"===t.key||"ArrowDown"===t.key?(t.preventDefault(),this.handleUnifiedArrowNavigation("ArrowDown"===t.key?1:-1)):"Enter"===t.key?(t.preventDefault(),this.handleUnifiedEnterKey()):"Escape"===t.key&&this.clearUnifiedSelection())})}getTabNameFromButton(t){const e=t.textContent.toLowerCase();return e.includes("events")?"events":e.includes("agents")?"agents":e.includes("tools")?"tools":e.includes("files")?"files":"events"}switchTab(t){console.log(`[DEBUG] switchTab called with tabName: ${t}`);const e=this.currentTab;this.currentTab=t,document.querySelectorAll(".tab-button").forEach(e=>{e.classList.remove("active"),this.getTabNameFromButton(e)===t&&e.classList.add("active")}),document.querySelectorAll(".tab-content").forEach(t=>{t.classList.remove("active")});const n=document.getElementById(`${t}-tab`);n&&n.classList.add("active"),this.clearUnifiedSelection(),document.dispatchEvent(new CustomEvent("tabChanged",{detail:{newTab:t,previousTab:e}})),setTimeout(()=>{this.autoScroll&&this.scrollCurrentTabToBottom()},100)}handleUnifiedArrowNavigation(t){const e=this.tabNavigation[this.currentTab];if(!e)return;let n=e.selectedIndex+t;0!==e.items.length&&(n<0?n=e.items.length-1:n>=e.items.length&&(n=0),this.selectCardByIndex(this.currentTab,n))}handleUnifiedEnterKey(){const t=this.tabNavigation[this.currentTab];if(!t||-1===t.selectedIndex)return;const e=t.items[t.selectedIndex];e&&e.onclick&&e.onclick()}clearUnifiedSelection(){Object.keys(this.tabNavigation).forEach(t=>{this.tabNavigation[t].selectedIndex=-1}),this.clearCardSelection()}updateTabNavigationItems(){const t=this.tabNavigation[this.currentTab];if(!t)return;let e;switch(this.currentTab){case"events":e="#events-list .event-item";break;case"agents":e="#agents-list .event-item";break;case"tools":e="#tools-list .event-item";break;case"files":e="#files-list .event-item"}e&&(t.items=Array.from(document.querySelectorAll(e)))}selectCardByIndex(t,e){const n=this.tabNavigation[t];if(!n||e<0||e>=n.items.length)return;n.selectedIndex=e,this.updateUnifiedSelectionUI();n.items[e]&&this.selectCard(t,e,this.getCardType(t),e),this.showCardDetails(t,e)}updateUnifiedSelectionUI(){document.querySelectorAll(".event-item.keyboard-selected").forEach(t=>{t.classList.remove("keyboard-selected")});const t=this.tabNavigation[this.currentTab];t&&-1!==t.selectedIndex&&t.items[t.selectedIndex]&&t.items[t.selectedIndex].classList.add("keyboard-selected")}showCardDetails(t,e){document.dispatchEvent(new CustomEvent("showCardDetails",{detail:{tabName:t,index:e}}))}selectCard(t,e,n,s){this.clearCardSelection(),this.selectedCard={tab:t,index:e,type:n,data:s},this.updateCardSelectionUI(),console.log("Card selected:",this.selectedCard)}clearCardSelection(){document.querySelectorAll(".event-item.selected, .file-item.selected").forEach(t=>{t.classList.remove("selected")}),this.selectedCard={tab:null,index:null,type:null,data:null}}updateCardSelectionUI(){if(!this.selectedCard.tab||null===this.selectedCard.index)return;let t;switch(this.selectedCard.tab){case"events":t=document.getElementById("events-list");break;case"agents":t=document.getElementById("agents-list");break;case"tools":t=document.getElementById("tools-list");break;case"files":t=document.getElementById("files-list")}if(t){const e=t.querySelectorAll(".event-item, .file-item");e[this.selectedCard.index]&&e[this.selectedCard.index].classList.add("selected")}}getCardType(t){switch(t){case"events":return"event";case"agents":return"agent";case"tools":return"tool";case"files":return"file";default:return"unknown"}}scrollCurrentTabToBottom(){const t=`${this.currentTab}-list`,e=document.getElementById(t);e&&this.autoScroll&&(e.scrollTop=e.scrollHeight)}clearSelection(){this.clearCardSelection(),this.clearUnifiedSelection()}getCurrentTab(){return this.currentTab}getSelectedCard(){return{...this.selectedCard}}getTabNavigation(){return{...this.tabNavigation}}setAutoScroll(t){this.autoScroll=t}getAutoScroll(){return this.autoScroll}}export{n as S,s as U};
|
|
2
2
|
//# sourceMappingURL=socket-client.js.map
|
|
@@ -379,10 +379,28 @@ class FileToolTracker {
|
|
|
379
379
|
// For Bash commands, try to extract file paths from the command
|
|
380
380
|
if (event.tool_name?.toLowerCase() === 'bash' && event.tool_parameters?.command) {
|
|
381
381
|
const command = event.tool_parameters.command;
|
|
382
|
-
|
|
383
|
-
|
|
382
|
+
|
|
383
|
+
// Enhanced regex to handle commands with flags
|
|
384
|
+
// Match command followed by optional flags (starting with -) and then the file path
|
|
385
|
+
// Patterns to handle:
|
|
386
|
+
// 1. tail -50 /path/to/file
|
|
387
|
+
// 2. head -n 100 /path/to/file
|
|
388
|
+
// 3. cat /path/to/file
|
|
389
|
+
// 4. grep -r "pattern" /path/to/file
|
|
390
|
+
const fileMatch = command.match(/(?:cat|less|more|head|tail|touch|mv|cp|rm|mkdir|ls|find|echo.*>|sed|awk|grep)(?:\s+-[a-zA-Z0-9]+)*(?:\s+[0-9]+)*\s+([^\s;|&]+)/);
|
|
391
|
+
|
|
392
|
+
// If first match might be a flag, try a more specific pattern
|
|
384
393
|
if (fileMatch && fileMatch[1]) {
|
|
385
|
-
|
|
394
|
+
const possiblePath = fileMatch[1];
|
|
395
|
+
// Check if it's actually a flag (starts with -)
|
|
396
|
+
if (possiblePath.startsWith('-')) {
|
|
397
|
+
// Try alternative pattern that skips all flags
|
|
398
|
+
const altMatch = command.match(/(?:cat|less|more|head|tail|touch|mv|cp|rm|mkdir|ls|find|echo.*>|sed|awk|grep)(?:\s+-[^\s]+)*\s+([^-][^\s;|&]*)/);
|
|
399
|
+
if (altMatch && altMatch[1]) {
|
|
400
|
+
return altMatch[1];
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return possiblePath;
|
|
386
404
|
}
|
|
387
405
|
}
|
|
388
406
|
|
|
@@ -1184,6 +1184,59 @@ class ModuleViewer {
|
|
|
1184
1184
|
if (!text || text.length <= maxLength) return text;
|
|
1185
1185
|
return text.substring(0, maxLength) + '...';
|
|
1186
1186
|
}
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* Format operation details object for display
|
|
1190
|
+
* @param {Object} details - Details object containing operation information
|
|
1191
|
+
* @returns {string} Formatted HTML string
|
|
1192
|
+
*/
|
|
1193
|
+
formatOperationDetails(details) {
|
|
1194
|
+
if (!details || typeof details !== 'object') {
|
|
1195
|
+
return '';
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
let formattedDetails = '';
|
|
1199
|
+
|
|
1200
|
+
// Display the bash command if available
|
|
1201
|
+
if (details.parameters && details.parameters.command) {
|
|
1202
|
+
formattedDetails += `<br><strong>Command:</strong> <code>${this.escapeHtml(details.parameters.command)}</code>`;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
// Display success/error status
|
|
1206
|
+
if (details.success !== undefined) {
|
|
1207
|
+
formattedDetails += `<br><strong>Status:</strong> ${details.success ? '✅ Success' : '❌ Failed'}`;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// Display exit code if available
|
|
1211
|
+
if (details.exit_code !== undefined && details.exit_code !== null) {
|
|
1212
|
+
formattedDetails += `<br><strong>Exit Code:</strong> ${details.exit_code}`;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// Display duration if available
|
|
1216
|
+
if (details.duration_ms !== undefined && details.duration_ms !== null) {
|
|
1217
|
+
const duration = details.duration_ms > 1000
|
|
1218
|
+
? `${(details.duration_ms / 1000).toFixed(2)}s`
|
|
1219
|
+
: `${details.duration_ms}ms`;
|
|
1220
|
+
formattedDetails += `<br><strong>Duration:</strong> ${duration}`;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
// Display error message if available
|
|
1224
|
+
if (details.error) {
|
|
1225
|
+
formattedDetails += `<br><strong>Error:</strong> ${this.escapeHtml(this.truncateText(details.error, 200))}`;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
return formattedDetails;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* Escape HTML to prevent XSS
|
|
1233
|
+
*/
|
|
1234
|
+
escapeHtml(text) {
|
|
1235
|
+
if (!text) return '';
|
|
1236
|
+
const div = document.createElement('div');
|
|
1237
|
+
div.textContent = text;
|
|
1238
|
+
return div.innerHTML;
|
|
1239
|
+
}
|
|
1187
1240
|
|
|
1188
1241
|
/**
|
|
1189
1242
|
* Format JSON for display
|
|
@@ -1452,6 +1505,81 @@ class ModuleViewer {
|
|
|
1452
1505
|
this.dataContainer.innerHTML = contextualHeader + todoContent + collapsibleJsonSection;
|
|
1453
1506
|
}
|
|
1454
1507
|
|
|
1508
|
+
// Initialize JSON toggle functionality
|
|
1509
|
+
this.initializeJsonToggle();
|
|
1510
|
+
} else if (toolName === 'Grep' || toolName === 'Search' || (parameters && parameters.pattern && !parameters.file_path)) {
|
|
1511
|
+
// Special handling for search operations (Grep tool or any tool with pattern parameter)
|
|
1512
|
+
const searchPattern = parameters.pattern || 'No pattern specified';
|
|
1513
|
+
const searchPath = parameters.path || parameters.directory || '.';
|
|
1514
|
+
const searchType = parameters.type || parameters.glob || 'all files';
|
|
1515
|
+
|
|
1516
|
+
// Extract search results from result_summary
|
|
1517
|
+
let searchResultsContent = '';
|
|
1518
|
+
if (toolCall.result_summary) {
|
|
1519
|
+
if (typeof toolCall.result_summary === 'string') {
|
|
1520
|
+
searchResultsContent = toolCall.result_summary;
|
|
1521
|
+
} else if (toolCall.result_summary.output_preview) {
|
|
1522
|
+
searchResultsContent = toolCall.result_summary.output_preview;
|
|
1523
|
+
} else {
|
|
1524
|
+
searchResultsContent = JSON.stringify(toolCall.result_summary, null, 2);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
const content = `
|
|
1529
|
+
<div class="structured-view-section">
|
|
1530
|
+
<div class="tool-call-details">
|
|
1531
|
+
<div class="tool-call-info ${statusClass}">
|
|
1532
|
+
<div class="structured-field">
|
|
1533
|
+
<strong>Tool Name:</strong> ${toolName}
|
|
1534
|
+
</div>
|
|
1535
|
+
<div class="structured-field">
|
|
1536
|
+
<strong>Agent:</strong> ${agentName}
|
|
1537
|
+
</div>
|
|
1538
|
+
<div class="structured-field">
|
|
1539
|
+
<strong>Status:</strong> ${statusIcon} ${statusText}
|
|
1540
|
+
</div>
|
|
1541
|
+
<div class="structured-field">
|
|
1542
|
+
<strong>Search Pattern:</strong> <code>${searchPattern}</code>
|
|
1543
|
+
</div>
|
|
1544
|
+
<div class="structured-field">
|
|
1545
|
+
<strong>Search Path:</strong> ${searchPath}
|
|
1546
|
+
</div>
|
|
1547
|
+
<div class="structured-field">
|
|
1548
|
+
<strong>File Type:</strong> ${searchType}
|
|
1549
|
+
</div>
|
|
1550
|
+
<div class="structured-field">
|
|
1551
|
+
<strong>Started:</strong> ${new Date(toolCall.timestamp).toLocaleString()}
|
|
1552
|
+
</div>
|
|
1553
|
+
${duration && duration !== '-' ? `
|
|
1554
|
+
<div class="structured-field">
|
|
1555
|
+
<strong>Duration:</strong> ${duration}
|
|
1556
|
+
</div>
|
|
1557
|
+
` : ''}
|
|
1558
|
+
</div>
|
|
1559
|
+
|
|
1560
|
+
<div class="search-view-action" style="margin-top: 20px;">
|
|
1561
|
+
<button class="btn-view-search" data-search-params='${JSON.stringify(parameters)}' data-search-results='${JSON.stringify(searchResultsContent).replace(/'/g, "'")}' onclick="window.showSearchViewerModal(JSON.parse(this.getAttribute('data-search-params')), JSON.parse(this.getAttribute('data-search-results')))">
|
|
1562
|
+
🔍 View Search Details
|
|
1563
|
+
</button>
|
|
1564
|
+
</div>
|
|
1565
|
+
|
|
1566
|
+
${this.createToolResultFromToolCall(toolCall)}
|
|
1567
|
+
</div>
|
|
1568
|
+
</div>
|
|
1569
|
+
`;
|
|
1570
|
+
|
|
1571
|
+
// Create collapsible JSON section
|
|
1572
|
+
const toolCallData = {
|
|
1573
|
+
toolCall: toolCall,
|
|
1574
|
+
preEvent: preEvent,
|
|
1575
|
+
postEvent: postEvent
|
|
1576
|
+
};
|
|
1577
|
+
const collapsibleJsonSection = this.createCollapsibleJsonSection(toolCallData);
|
|
1578
|
+
|
|
1579
|
+
if (this.dataContainer) {
|
|
1580
|
+
this.dataContainer.innerHTML = contextualHeader + content + collapsibleJsonSection;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1455
1583
|
// Initialize JSON toggle functionality
|
|
1456
1584
|
this.initializeJsonToggle();
|
|
1457
1585
|
} else {
|
|
@@ -1581,7 +1709,7 @@ class ModuleViewer {
|
|
|
1581
1709
|
<div class="operation-details">
|
|
1582
1710
|
<strong>Agent:</strong> ${op.agent}<br>
|
|
1583
1711
|
<strong>Session:</strong> ${op.sessionId ? op.sessionId.substring(0, 8) + '...' : 'Unknown'}
|
|
1584
|
-
${op.details ?
|
|
1712
|
+
${op.details ? this.formatOperationDetails(op.details) : ''}
|
|
1585
1713
|
</div>
|
|
1586
1714
|
</div>
|
|
1587
1715
|
`).join('')}
|
|
@@ -1683,6 +1683,122 @@ function displayFileContentError(modal, result) {
|
|
|
1683
1683
|
errorArea.style.display = 'block';
|
|
1684
1684
|
}
|
|
1685
1685
|
|
|
1686
|
+
// Search Viewer Modal Functions
|
|
1687
|
+
window.showSearchViewerModal = function(searchParams, searchResults) {
|
|
1688
|
+
// Create modal if it doesn't exist
|
|
1689
|
+
let modal = document.getElementById('search-viewer-modal');
|
|
1690
|
+
if (!modal) {
|
|
1691
|
+
modal = createSearchViewerModal();
|
|
1692
|
+
document.body.appendChild(modal);
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
// Update modal content
|
|
1696
|
+
updateSearchViewerModal(modal, searchParams, searchResults);
|
|
1697
|
+
|
|
1698
|
+
// Show the modal as flex container
|
|
1699
|
+
modal.style.display = 'flex';
|
|
1700
|
+
document.body.style.overflow = 'hidden'; // Prevent background scrolling
|
|
1701
|
+
};
|
|
1702
|
+
|
|
1703
|
+
window.hideSearchViewerModal = function() {
|
|
1704
|
+
const modal = document.getElementById('search-viewer-modal');
|
|
1705
|
+
if (modal) {
|
|
1706
|
+
modal.style.display = 'none';
|
|
1707
|
+
document.body.style.overflow = ''; // Restore background scrolling
|
|
1708
|
+
}
|
|
1709
|
+
};
|
|
1710
|
+
|
|
1711
|
+
function createSearchViewerModal() {
|
|
1712
|
+
const modal = document.createElement('div');
|
|
1713
|
+
modal.id = 'search-viewer-modal';
|
|
1714
|
+
modal.className = 'modal search-viewer-modal';
|
|
1715
|
+
|
|
1716
|
+
modal.innerHTML = `
|
|
1717
|
+
<div class="modal-content search-viewer-content">
|
|
1718
|
+
<div class="search-viewer-header">
|
|
1719
|
+
<h2 class="search-viewer-title">
|
|
1720
|
+
<span class="search-viewer-icon">🔍</span>
|
|
1721
|
+
<span class="search-viewer-title-text">Search Results</span>
|
|
1722
|
+
</h2>
|
|
1723
|
+
<button class="search-viewer-close" onclick="hideSearchViewerModal()">
|
|
1724
|
+
<span>×</span>
|
|
1725
|
+
</button>
|
|
1726
|
+
</div>
|
|
1727
|
+
<div class="search-viewer-body">
|
|
1728
|
+
<div class="search-params-section">
|
|
1729
|
+
<h3>Search Parameters</h3>
|
|
1730
|
+
<pre class="search-params-display"></pre>
|
|
1731
|
+
</div>
|
|
1732
|
+
<div class="search-results-section">
|
|
1733
|
+
<h3>Search Results</h3>
|
|
1734
|
+
<div class="search-results-display"></div>
|
|
1735
|
+
</div>
|
|
1736
|
+
</div>
|
|
1737
|
+
</div>
|
|
1738
|
+
`;
|
|
1739
|
+
|
|
1740
|
+
// Close modal when clicking outside
|
|
1741
|
+
modal.addEventListener('click', (e) => {
|
|
1742
|
+
if (e.target === modal) {
|
|
1743
|
+
hideSearchViewerModal();
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
|
|
1747
|
+
// Close modal on Escape key
|
|
1748
|
+
document.addEventListener('keydown', (e) => {
|
|
1749
|
+
if (e.key === 'Escape' && modal.style.display === 'flex') {
|
|
1750
|
+
hideSearchViewerModal();
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1753
|
+
|
|
1754
|
+
return modal;
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
function updateSearchViewerModal(modal, searchParams, searchResults) {
|
|
1758
|
+
const paramsDisplay = modal.querySelector('.search-params-display');
|
|
1759
|
+
const resultsDisplay = modal.querySelector('.search-results-display');
|
|
1760
|
+
|
|
1761
|
+
// Display search parameters in formatted JSON
|
|
1762
|
+
if (paramsDisplay && searchParams) {
|
|
1763
|
+
paramsDisplay.textContent = JSON.stringify(searchParams, null, 2);
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
// Display search results
|
|
1767
|
+
if (resultsDisplay && searchResults) {
|
|
1768
|
+
let resultsHTML = '';
|
|
1769
|
+
|
|
1770
|
+
if (typeof searchResults === 'string') {
|
|
1771
|
+
// If results are a string, display as preformatted text
|
|
1772
|
+
resultsHTML = `<pre class="search-results-text">${escapeHtml(searchResults)}</pre>`;
|
|
1773
|
+
} else if (Array.isArray(searchResults)) {
|
|
1774
|
+
// If results are an array, display as a list
|
|
1775
|
+
resultsHTML = '<ul class="search-results-list">';
|
|
1776
|
+
searchResults.forEach(result => {
|
|
1777
|
+
if (typeof result === 'object') {
|
|
1778
|
+
resultsHTML += `<li><pre>${JSON.stringify(result, null, 2)}</pre></li>`;
|
|
1779
|
+
} else {
|
|
1780
|
+
resultsHTML += `<li>${escapeHtml(String(result))}</li>`;
|
|
1781
|
+
}
|
|
1782
|
+
});
|
|
1783
|
+
resultsHTML += '</ul>';
|
|
1784
|
+
} else if (typeof searchResults === 'object') {
|
|
1785
|
+
// If results are an object, display as formatted JSON
|
|
1786
|
+
resultsHTML = `<pre class="search-results-json">${JSON.stringify(searchResults, null, 2)}</pre>`;
|
|
1787
|
+
} else {
|
|
1788
|
+
// Fallback: display as text
|
|
1789
|
+
resultsHTML = `<div class="search-results-text">${escapeHtml(String(searchResults))}</div>`;
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
resultsDisplay.innerHTML = resultsHTML;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
function escapeHtml(text) {
|
|
1797
|
+
const div = document.createElement('div');
|
|
1798
|
+
div.textContent = text;
|
|
1799
|
+
return div.innerHTML;
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1686
1802
|
// Global window functions for backward compatibility
|
|
1687
1803
|
window.showAgentInstanceDetails = function(instanceId) {
|
|
1688
1804
|
if (window.dashboard && typeof window.dashboard.showAgentInstanceDetails === 'function') {
|