claude-mpm 4.0.3__py3-none-any.whl → 4.0.8__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.
Files changed (40) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/templates/ticketing.json +1 -1
  3. claude_mpm/cli/commands/monitor.py +131 -9
  4. claude_mpm/cli/commands/tickets.py +61 -26
  5. claude_mpm/cli/parsers/monitor_parser.py +22 -2
  6. claude_mpm/constants.py +4 -1
  7. claude_mpm/core/framework_loader.py +102 -14
  8. claude_mpm/dashboard/static/built/components/agent-inference.js +2 -0
  9. claude_mpm/dashboard/static/built/components/event-processor.js +2 -0
  10. claude_mpm/dashboard/static/built/components/event-viewer.js +2 -0
  11. claude_mpm/dashboard/static/built/components/export-manager.js +2 -0
  12. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +2 -0
  13. claude_mpm/dashboard/static/built/components/hud-library-loader.js +2 -0
  14. claude_mpm/dashboard/static/built/components/hud-manager.js +2 -0
  15. claude_mpm/dashboard/static/built/components/hud-visualizer.js +2 -0
  16. claude_mpm/dashboard/static/built/components/module-viewer.js +2 -0
  17. claude_mpm/dashboard/static/built/components/session-manager.js +2 -0
  18. claude_mpm/dashboard/static/built/components/socket-manager.js +2 -0
  19. claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -0
  20. claude_mpm/dashboard/static/built/components/working-directory.js +2 -0
  21. claude_mpm/dashboard/static/built/dashboard.js +2 -0
  22. claude_mpm/dashboard/static/built/socket-client.js +2 -0
  23. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  24. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
  25. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  26. claude_mpm/dashboard/static/js/components/event-viewer.js +24 -3
  27. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +5 -5
  28. claude_mpm/dashboard/static/js/socket-client.js +25 -5
  29. claude_mpm/hooks/claude_hooks/connection_pool.py +75 -12
  30. claude_mpm/hooks/claude_hooks/hook_handler.py +63 -12
  31. claude_mpm/services/port_manager.py +370 -18
  32. claude_mpm/services/socketio/handlers/connection.py +41 -19
  33. claude_mpm/services/socketio/handlers/hook.py +23 -8
  34. claude_mpm/services/system_instructions_service.py +22 -7
  35. {claude_mpm-4.0.3.dist-info → claude_mpm-4.0.8.dist-info}/METADATA +64 -22
  36. {claude_mpm-4.0.3.dist-info → claude_mpm-4.0.8.dist-info}/RECORD +40 -25
  37. {claude_mpm-4.0.3.dist-info → claude_mpm-4.0.8.dist-info}/WHEEL +0 -0
  38. {claude_mpm-4.0.3.dist-info → claude_mpm-4.0.8.dist-info}/entry_points.txt +0 -0
  39. {claude_mpm-4.0.3.dist-info → claude_mpm-4.0.8.dist-info}/licenses/LICENSE +0 -0
  40. {claude_mpm-4.0.3.dist-info → claude_mpm-4.0.8.dist-info}/top_level.txt +0 -0
claude_mpm/constants.py CHANGED
@@ -1,4 +1,7 @@
1
- """Constants for Claude MPM."""
1
+ """Constants for Claude MPM.
2
+
3
+ Build number tracking is now enabled for all builds.
4
+ """
2
5
 
3
6
  from enum import Enum
4
7
  from pathlib import Path
@@ -61,9 +61,11 @@ class FrameworkLoader:
61
61
 
62
62
  # Otherwise check common locations for claude-mpm
63
63
  candidates = [
64
+ # Current directory (if we're already in claude-mpm)
65
+ Path.cwd(),
64
66
  # Development location
65
67
  Path.home() / "Projects" / "claude-mpm",
66
- # Current directory
68
+ # Current directory subdirectory
67
69
  Path.cwd() / "claude-mpm",
68
70
  ]
69
71
 
@@ -256,29 +258,102 @@ class FrameworkLoader:
256
258
  content["project_memory"] = "system"
257
259
  self.logger.info("Using system MEMORY.md")
258
260
 
261
+ def _get_deployed_agents(self) -> set:
262
+ """
263
+ Get a set of deployed agent names from .claude/agents/ directories.
264
+
265
+ Returns:
266
+ Set of agent names (file stems) that are deployed
267
+ """
268
+ deployed = set()
269
+
270
+ # Check multiple locations for deployed agents
271
+ agents_dirs = [
272
+ Path.cwd() / ".claude" / "agents", # Project-specific agents
273
+ Path.home() / ".claude" / "agents", # User's system agents
274
+ ]
275
+
276
+ for agents_dir in agents_dirs:
277
+ if agents_dir.exists():
278
+ for agent_file in agents_dir.glob("*.md"):
279
+ if not agent_file.name.startswith("."):
280
+ # Use stem to get agent name without extension
281
+ deployed.add(agent_file.stem)
282
+ self.logger.debug(f"Found deployed agent: {agent_file.stem} in {agents_dir}")
283
+
284
+ self.logger.debug(f"Total deployed agents found: {len(deployed)}")
285
+ return deployed
286
+
259
287
  def _load_actual_memories(self, content: Dict[str, Any]) -> None:
260
288
  """
261
- Load actual PM memories from .claude-mpm/memories/PM.md.
289
+ Load actual memories from .claude-mpm/memories/ directory.
262
290
 
263
- These are the actual memories/knowledge that the PM should have,
264
- as opposed to the memory system instructions in MEMORY.md.
291
+ This loads:
292
+ 1. PM memories from PM.md (always loaded)
293
+ 2. Agent memories from <agent>.md (only if agent is deployed)
265
294
 
266
295
  Args:
267
296
  content: Dictionary to update with actual memories
268
297
  """
269
- memories_path = Path.cwd() / ".claude-mpm" / "memories" / "PM.md"
270
- if memories_path.exists():
298
+ memories_dir = Path.cwd() / ".claude-mpm" / "memories"
299
+
300
+ # Log the memory loading process
301
+ if memories_dir.exists():
302
+ self.logger.info(f"Loading memory files from: {memories_dir}")
303
+ else:
304
+ self.logger.debug(f"No memories directory found at: {memories_dir}")
305
+ return
306
+
307
+ # Check for deployed agents
308
+ deployed_agents = self._get_deployed_agents()
309
+
310
+ # Track loading statistics
311
+ loaded_count = 0
312
+ skipped_count = 0
313
+
314
+ # Load PM memories (always loaded)
315
+ pm_memory_path = memories_dir / "PM.md"
316
+ if pm_memory_path.exists():
271
317
  loaded_content = self._try_load_file(
272
- memories_path, "PM memories"
318
+ pm_memory_path, "PM memory"
273
319
  )
274
320
  if loaded_content:
275
321
  content["actual_memories"] = loaded_content
276
- self.logger.info(f"Loaded PM memories from: {memories_path}")
277
- # Log memory size for monitoring
278
322
  memory_size = len(loaded_content.encode('utf-8'))
279
- self.logger.debug(f"PM memory size: {memory_size:,} bytes")
323
+ self.logger.info(f"Loaded PM memory: {pm_memory_path} ({memory_size:,} bytes)")
324
+ loaded_count += 1
280
325
  else:
281
- self.logger.debug(f"No PM memories found at: {memories_path}")
326
+ self.logger.debug(f"No PM memory found at: {pm_memory_path}")
327
+
328
+ # Load agent memories (only for deployed agents)
329
+ for memory_file in memories_dir.glob("*.md"):
330
+ # Skip PM.md as we already handled it
331
+ if memory_file.name == "PM.md":
332
+ continue
333
+
334
+ # Extract agent name from file
335
+ agent_name = memory_file.stem
336
+
337
+ # Check if agent is deployed
338
+ if agent_name in deployed_agents:
339
+ loaded_content = self._try_load_file(
340
+ memory_file, f"agent memory: {agent_name}"
341
+ )
342
+ if loaded_content:
343
+ # Store agent memories separately (for future use)
344
+ if "agent_memories" not in content:
345
+ content["agent_memories"] = {}
346
+ content["agent_memories"][agent_name] = loaded_content
347
+ memory_size = len(loaded_content.encode('utf-8'))
348
+ self.logger.info(f"Loaded agent memory: {memory_file.name} (deployed agent found, {memory_size:,} bytes)")
349
+ loaded_count += 1
350
+ else:
351
+ self.logger.info(f"Skipped agent memory: {memory_file.name} (agent not deployed)")
352
+ skipped_count += 1
353
+
354
+ # Log summary
355
+ if loaded_count > 0 or skipped_count > 0:
356
+ self.logger.info(f"Memory loading complete: {loaded_count} memories loaded, {skipped_count} skipped")
282
357
 
283
358
  def _load_single_agent(
284
359
  self, agent_file: Path
@@ -639,10 +714,23 @@ Extract tickets from these patterns:
639
714
  import yaml
640
715
 
641
716
  # Read directly from deployed agents in .claude/agents/
642
- agents_dir = Path.cwd() / ".claude" / "agents"
717
+ # Check multiple locations for deployed agents
718
+ # Priority order: project > user home > fallback
719
+ agents_dirs = [
720
+ Path.cwd() / ".claude" / "agents", # Project-specific agents
721
+ Path.home() / ".claude" / "agents", # User's system agents
722
+ ]
723
+
724
+ agents_dir = None
725
+ for potential_dir in agents_dirs:
726
+ if potential_dir.exists() and any(potential_dir.glob("*.md")):
727
+ agents_dir = potential_dir
728
+ self.logger.debug(f"Found agents directory at: {agents_dir}")
729
+ break
730
+
643
731
 
644
- if not agents_dir.exists():
645
- self.logger.warning("No .claude/agents directory found")
732
+ if not agents_dir:
733
+ self.logger.warning(f"No .claude/agents directory found in any location: {agents_dirs}")
646
734
  return self._get_fallback_capabilities()
647
735
 
648
736
  # Build capabilities section
@@ -0,0 +1,2 @@
1
+ class e{constructor(e){this.eventViewer=e,this.state={currentDelegation:null,sessionAgents:new Map,eventAgentMap:new Map,pmDelegations:new Map,agentToDelegation:new Map},console.log("Agent inference system initialized")}initialize(){this.state={currentDelegation:null,sessionAgents:new Map,eventAgentMap:new Map,pmDelegations:new Map,agentToDelegation:new Map}}inferAgentFromEvent(e){const t=e.data||{},n=e.session_id||t.session_id||"unknown",a=e.hook_event_name||t.hook_event_name||e.type||"",s=e.subtype||t.subtype||"",i=e.tool_name||t.tool_name||"";if(Math.random()<.1&&console.log("Agent inference debug:",{eventType:a,toolName:i,hasData:!!e.data,dataKeys:Object.keys(t),eventKeys:Object.keys(e),agentType:e.agent_type||t.agent_type,subagentType:e.subagent_type||t.subagent_type}),"SubagentStop"===a||"subagent_stop"===s){const i=this.extractAgentNameFromEvent(e);return console.log("SubagentStop event detected:",{agentName:i,sessionId:n,eventType:a,subtype:s,rawAgentType:e.agent_type||t.agent_type}),{type:"subagent",confidence:"definitive",agentName:i,reason:"SubagentStop event"}}if("Stop"===a||"stop"===s)return{type:"main_agent",confidence:"definitive",agentName:"PM",reason:"Stop event"};if("Task"===i){const t=this.extractSubagentTypeFromTask(e);if(t)return console.log("Task delegation detected:",{agentName:t,sessionId:n,eventType:a}),{type:"subagent",confidence:"high",agentName:t,reason:"Task tool with subagent_type"}}if("PreToolUse"===a&&"Task"===i){const t=this.extractSubagentTypeFromTask(e);if(t)return{type:"subagent",confidence:"high",agentName:t,reason:"PreToolUse Task delegation"}}{const e=n.toLowerCase();if(["subagent","task","agent-"].some(t=>e.includes(t)))return{type:"subagent",confidence:"medium",agentName:"Subagent",reason:"Session ID pattern"}}const o=e.agent_type||t.agent_type||e.agent_id||t.agent_id,g=e.subagent_type||t.subagent_type;if(g&&"unknown"!==g)return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(g),reason:"subagent_type field"};if(o&&"unknown"!==o&&"main"!==o)return{type:"subagent",confidence:"medium",agentName:this.normalizeAgentName(o),reason:"agent_type field"};if(t.delegation_details?.agent_type)return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(t.delegation_details.agent_type),reason:"delegation_details"};if(e.type&&e.type.startsWith("hook.")){const a=e.type.replace("hook.","");if("subagent_start"===a||"SubagentStart"===t.hook_event_name){const e=t.agent_type||t.agent_id||"Subagent";return console.log("SubagentStart event from Socket.IO:",{agentName:e,sessionId:n,hookType:a}),{type:"subagent",confidence:"definitive",agentName:this.normalizeAgentName(e),reason:"Socket.IO hook SubagentStart"}}if("subagent_stop"===a||"SubagentStop"===t.hook_event_name){const e=t.agent_type||t.agent_id||"Subagent";return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(e),reason:"Socket.IO hook SubagentStop"}}}return{type:"main_agent",confidence:"default",agentName:"PM",reason:"default classification"}}normalizeAgentName(e){if(!e)return"Unknown";const t={engineer:"Engineer Agent",research:"Research Agent",qa:"QA Agent",documentation:"Documentation Agent",security:"Security Agent",ops:"Ops Agent",version_control:"Version Control Agent",data_engineer:"Data Engineer Agent",test_integration:"Test Integration Agent",pm:"PM Agent"}[e.toLowerCase()];if(t)return t;let n=e.replace(/_/g," ").split(" ").map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(" ");return n.toLowerCase().includes("agent")||(n+=" Agent"),n}extractSubagentTypeFromTask(e){let t=null;return e.tool_parameters?.subagent_type?t=e.tool_parameters.subagent_type:e.data?.tool_parameters?.subagent_type?t=e.data.tool_parameters.subagent_type:e.data?.delegation_details?.agent_type?t=e.data.delegation_details.agent_type:e.tool_input?.subagent_type&&(t=e.tool_input.subagent_type),t?this.normalizeAgentName(t):null}extractAgentNameFromEvent(e){const t=e.data||{};if("Task"===e.tool_name||"Task"===t.tool_name){const t=this.extractSubagentTypeFromTask(e);if(t)return t}return e.subagent_type&&"unknown"!==e.subagent_type?this.normalizeAgentName(e.subagent_type):t.subagent_type&&"unknown"!==t.subagent_type?this.normalizeAgentName(t.subagent_type):t.delegation_details?.agent_type&&"unknown"!==t.delegation_details.agent_type?this.normalizeAgentName(t.delegation_details.agent_type):e.agent_type&&!["main","unknown"].includes(e.agent_type)?this.normalizeAgentName(e.agent_type):t.agent_type&&!["main","unknown"].includes(t.agent_type)?this.normalizeAgentName(t.agent_type):e.agent_id&&!["main","unknown"].includes(e.agent_id)?this.normalizeAgentName(e.agent_id):t.agent_id&&!["main","unknown"].includes(t.agent_id)?this.normalizeAgentName(t.agent_id):e.agent&&"unknown"!==e.agent?this.normalizeAgentName(e.agent):e.name&&"unknown"!==e.name?this.normalizeAgentName(e.name):"Unknown"}processAgentInference(){const e=this.eventViewer.events;this.state.currentDelegation=null,this.state.sessionAgents.clear(),this.state.eventAgentMap.clear(),this.state.pmDelegations.clear(),this.state.agentToDelegation.clear(),console.log("Processing agent inference for",e.length,"events"),e&&0!==e.length?(e.forEach((e,t)=>{let n;try{const a=this.inferAgentFromEvent(e),s=e.session_id||e.data?.session_id||"default";if(n=a,this.state.currentDelegation&&"default"===a.confidence&&s===this.state.currentDelegation.sessionId&&(n={type:"subagent",confidence:"inherited",agentName:this.state.currentDelegation.agentName,reason:"inherited from delegation context"}),"Task"===e.tool_name&&"subagent"===a.type){const n=`pm_${s}_${t}_${a.agentName}`,i={id:n,agentName:a.agentName,sessionId:s,startIndex:t,endIndex:null,pmCall:e,timestamp:e.timestamp,agentEvents:[]};this.state.pmDelegations.set(n,i),this.state.agentToDelegation.set(a.agentName,n),this.state.currentDelegation={agentName:a.agentName,sessionId:s,startIndex:t,endIndex:null,delegationId:n},console.log("Delegation started:",this.state.currentDelegation)}else if("definitive"===a.confidence&&"SubagentStop event"===a.reason&&this.state.currentDelegation){this.state.currentDelegation.endIndex=t;const e=this.state.pmDelegations.get(this.state.currentDelegation.delegationId);e&&(e.endIndex=t),console.log("Delegation ended:",this.state.currentDelegation),this.state.currentDelegation=null}if(this.state.currentDelegation&&"subagent"===n.type){const a=this.state.pmDelegations.get(this.state.currentDelegation.delegationId);a&&a.agentEvents.push({eventIndex:t,event:e,inference:n})}this.state.eventAgentMap.set(t,n),this.state.sessionAgents.set(s,n),t<5&&console.log(`Event ${t} agent inference:`,{event_type:e.type||e.hook_event_name,subtype:e.subtype,tool_name:e.tool_name,inference:n,hasData:!!e.data,agentType:e.agent_type||e.data?.agent_type})}catch(a){console.error(`Error processing event ${t} for agent inference:`,a),n||(n={type:"main_agent",confidence:"error",agentName:"PM",reason:"error during processing"}),this.state.eventAgentMap.set(t,n)}}),console.log("Agent inference processing complete. Results:",{total_events:e.length,inferred_agents:this.state.eventAgentMap.size,unique_sessions:this.state.sessionAgents.size,pm_delegations:this.state.pmDelegations.size,agent_to_delegation_mappings:this.state.agentToDelegation.size})):console.log("No events to process for agent inference")}getInferredAgent(e){return this.state.eventAgentMap.get(e)||null}getInferredAgentForEvent(e){const t=this.eventViewer.events;let n=t.indexOf(e);if(-1===n&&e.timestamp&&(n=t.findIndex(t=>t.timestamp===e.timestamp&&t.session_id===e.session_id)),-1===n)return console.log("Agent inference: Could not find event in events array, performing inline inference"),this.inferAgentFromEvent(e);let a=this.getInferredAgent(n);return a||(a=this.inferAgentFromEvent(e),this.state.eventAgentMap.set(n,a)),a}getCurrentDelegation(){return this.state.currentDelegation}getSessionAgents(){return this.state.sessionAgents}getEventAgentMap(){return this.state.eventAgentMap}getPMDelegations(){return this.state.pmDelegations}getAgentToDelegationMap(){return this.state.agentToDelegation}getUniqueAgentInstances(){const e=new Map;for(const[a,s]of this.state.pmDelegations){const t=s.agentName;e.has(t)||e.set(t,{id:`consolidated_${t}`,type:"consolidated_agent",agentName:t,delegations:[],pmCalls:[],allEvents:[],firstTimestamp:s.timestamp,lastTimestamp:s.timestamp,totalEventCount:s.agentEvents.length,delegationCount:1});const n=e.get(t);n.delegations.push({id:a,pmCall:s.pmCall,timestamp:s.timestamp,eventCount:s.agentEvents.length,startIndex:s.startIndex,endIndex:s.endIndex,events:s.agentEvents}),s.pmCall&&n.pmCalls.push(s.pmCall),n.allEvents=n.allEvents.concat(s.agentEvents),new Date(s.timestamp)<new Date(n.firstTimestamp)&&(n.firstTimestamp=s.timestamp),new Date(s.timestamp)>new Date(n.lastTimestamp)&&(n.lastTimestamp=s.timestamp),n.totalEventCount+=s.agentEvents.length,n.delegationCount++}const t=this.eventViewer.events;for(let a=0;a<t.length;a++){const n=this.getInferredAgent(a);n&&"subagent"===n.type&&!e.has(n.agentName)&&e.set(n.agentName,{id:`consolidated_${n.agentName}`,type:"consolidated_agent",agentName:n.agentName,delegations:[{id:`implied_pm_${n.agentName}_${a}`,pmCall:null,timestamp:t[a].timestamp,eventCount:1,startIndex:a,endIndex:null,events:[{eventIndex:a,event:t[a],inference:n}]}],pmCalls:[],allEvents:[{eventIndex:a,event:t[a],inference:n}],firstTimestamp:t[a].timestamp,lastTimestamp:t[a].timestamp,totalEventCount:1,delegationCount:1,isImplied:!0})}const n=Array.from(e.values()).sort((e,t)=>new Date(e.firstTimestamp)-new Date(t.firstTimestamp));return console.log("Consolidated unique agents:",{total_unique_agents:n.length,agents:n.map(e=>({name:e.agentName,delegations:e.delegationCount,totalEvents:e.totalEventCount}))}),n}}export{e as A};
2
+ //# sourceMappingURL=agent-inference.js.map
@@ -0,0 +1,2 @@
1
+ import{a as e,a as r}from"./event-viewer.js";export{e as EventProcessor,r as default};
2
+ //# sourceMappingURL=event-processor.js.map
@@ -0,0 +1,2 @@
1
+ class e{constructor(e,t){this.container=document.getElementById(e),this.socketClient=t,this.events=[],this.filteredEvents=[],this.selectedEventIndex=-1,this.filteredEventElements=[],this.autoScroll=!0,this.searchFilter="",this.typeFilter="",this.sessionFilter="",this.eventTypeCount={},this.availableEventTypes=new Set,this.errorCount=0,this.eventsThisMinute=0,this.lastMinute=(new Date).getMinutes(),this.init()}init(){this.setupEventHandlers(),this.setupKeyboardNavigation(),this.socketClient.onEventUpdate((e,t)=>{this.events=Array.isArray(e)?e:[],this.updateDisplay()})}setupEventHandlers(){const e=document.getElementById("events-search-input");e&&e.addEventListener("input",e=>{this.searchFilter=e.target.value.toLowerCase(),this.applyFilters()});const t=document.getElementById("events-type-filter");t&&t.addEventListener("change",e=>{this.typeFilter=e.target.value,this.applyFilters()})}setupKeyboardNavigation(){console.log("EventViewer: Keyboard navigation handled by unified Dashboard system")}handleArrowNavigation(e){if(0===this.filteredEventElements.length)return;let t=this.selectedEventIndex+e;t>=this.filteredEventElements.length?t=0:t<0&&(t=this.filteredEventElements.length-1),this.showEventDetails(t)}applyFilters(){this.events&&Array.isArray(this.events)||(console.warn("EventViewer: events array is not initialized, using empty array"),this.events=[]),this.filteredEvents=this.events.filter(e=>{if(this.searchFilter){if(![e.type||"",e.subtype||"",JSON.stringify(e.data||{})].join(" ").toLowerCase().includes(this.searchFilter))return!1}if(this.typeFilter){const t=e.type&&""!==e.type.trim()?e.type:"";if((e.subtype&&t?`${t}.${e.subtype}`:t)!==this.typeFilter)return!1}return!(this.sessionFilter&&""!==this.sessionFilter&&(!e.data||e.data.session_id!==this.sessionFilter))}),this.renderEvents(),this.updateMetrics()}updateEventTypeDropdown(){const e=document.getElementById("events-type-filter");if(!e)return;const t=new Set;this.events&&Array.isArray(this.events)||(console.warn("EventViewer: events array is not initialized in updateEventTypeDropdown"),this.events=[]),this.events.forEach(e=>{if(e.type&&""!==e.type.trim()){const n=e.subtype?`${e.type}.${e.subtype}`:e.type;t.add(n)}});const n=Array.from(t).sort(),s=Array.from(this.availableEventTypes).sort();if(JSON.stringify(n)===JSON.stringify(s))return;this.availableEventTypes=t;const i=e.value;e.innerHTML='<option value="">All Events</option>';Array.from(t).sort().forEach(t=>{const n=document.createElement("option");n.value=t,n.textContent=t,e.appendChild(n)}),i&&t.has(i)?e.value=i:i&&!t.has(i)&&(e.value="",this.typeFilter="")}updateDisplay(){this.updateEventTypeDropdown(),this.applyFilters()}renderEvents(){const e=document.getElementById("events-list");if(!e)return;if(0===this.filteredEvents.length)return e.innerHTML=`\n <div class="no-events">\n ${0===this.events.length?"Connect to Socket.IO server to see events...":"No events match current filters..."}\n </div>\n `,void(this.filteredEventElements=[]);const t=this.filteredEvents.map((e,t)=>{const n=new Date(e.timestamp).toLocaleTimeString();return`\n <div class="event-item single-row ${e.type?`event-${e.type}`:"event-default"} ${t===this.selectedEventIndex?"selected":""}"\n onclick="eventViewer.showEventDetails(${t})"\n data-index="${t}">\n <span class="event-single-row-content">\n <span class="event-content-main">${this.formatSingleRowEventContent(e)}</span>\n <span class="event-timestamp">${n}</span>\n </span>\n ${this.createInlineEditDiffViewer(e,t)}\n </div>\n `}).join("");e.innerHTML=t,this.filteredEventElements=Array.from(e.querySelectorAll(".event-item")),window.dashboard&&"events"===window.dashboard.currentTab&&window.dashboard.tabNavigation&&window.dashboard.tabNavigation.events&&(window.dashboard.tabNavigation.events.items=this.filteredEventElements),this.autoScroll&&this.filteredEvents.length>0&&(e.scrollTop=e.scrollHeight)}formatEventType(e){return e.type&&e.subtype?`${e.type}.${e.subtype}`:e.type?e.type:e.originalEventName?e.originalEventName:"unknown"}formatEventData(e){if(!e.data)return"No data";switch(e.type){case"session":return this.formatSessionEvent(e);case"claude":return this.formatClaudeEvent(e);case"agent":return this.formatAgentEvent(e);case"hook":return this.formatHookEvent(e);case"todo":return this.formatTodoEvent(e);case"memory":return this.formatMemoryEvent(e);case"log":return this.formatLogEvent(e);default:return this.formatGenericEvent(e)}}formatSessionEvent(e){const t=e.data;return"started"===e.subtype?`<strong>Session started:</strong> ${t.session_id||"Unknown"}`:"ended"===e.subtype?`<strong>Session ended:</strong> ${t.session_id||"Unknown"}`:`<strong>Session:</strong> ${JSON.stringify(t)}`}formatClaudeEvent(e){const t=e.data;if("request"===e.subtype){const e=t.prompt||t.message||"";return`<strong>Request:</strong> ${e.length>100?e.substring(0,100)+"...":e}`}if("response"===e.subtype){const e=t.response||t.content||"";return`<strong>Response:</strong> ${e.length>100?e.substring(0,100)+"...":e}`}return`<strong>Claude:</strong> ${JSON.stringify(t)}`}formatAgentEvent(e){const t=e.data;return"loaded"===e.subtype?`<strong>Agent loaded:</strong> ${t.agent_type||t.name||"Unknown"}`:"executed"===e.subtype?`<strong>Agent executed:</strong> ${t.agent_type||t.name||"Unknown"}`:`<strong>Agent:</strong> ${JSON.stringify(t)}`}formatHookEvent(e){const t=e.data,n=t.event_type||e.subtype||"unknown";switch(n){case"user_prompt":const s=t.prompt_text||t.prompt_preview||"";return`<strong>User Prompt:</strong> ${(s.length>80?s.substring(0,80)+"...":s)||"No prompt text"}`;case"pre_tool":const i=t.tool_name||"Unknown tool";return`<strong>Pre-Tool (${t.operation_type||"operation"}):</strong> ${i}`;case"post_tool":const o=t.tool_name||"Unknown tool";return`<strong>Post-Tool (${t.success?"success":t.status||"failed"}):</strong> ${o}${t.duration_ms?` (${t.duration_ms}ms)`:""}`;case"notification":return`<strong>Notification (${t.notification_type||"notification"}):</strong> ${t.message_preview||t.message||"No message"}`;case"stop":const r=t.reason||"unknown";return`<strong>Stop (${t.stop_type||"normal"}):</strong> ${r}`;case"subagent_stop":return`<strong>Subagent Stop (${t.agent_type||"unknown agent"}):</strong> ${t.reason||"unknown"}`;default:const a=t.hook_name||t.name||t.event_type||"Unknown";return`<strong>Hook ${e.subtype||n}:</strong> ${a}`}}formatTodoEvent(e){const t=e.data;if(t.todos&&Array.isArray(t.todos)){const e=t.todos.length;return`<strong>Todo updated:</strong> ${e} item${1!==e?"s":""}`}return`<strong>Todo:</strong> ${JSON.stringify(t)}`}formatMemoryEvent(e){const t=e.data;return`<strong>Memory ${t.operation||"unknown"}:</strong> ${t.key||"Unknown key"}`}formatLogEvent(e){const t=e.data,n=t.level||"info",s=t.message||"",i=s.length>80?s.substring(0,80)+"...":s;return`<strong>[${n.toUpperCase()}]</strong> ${i}`}formatGenericEvent(e){const t=e.data;return"string"==typeof t?t.length>100?t.substring(0,100)+"...":t:JSON.stringify(t)}formatSingleRowEventContent(e){const t=this.formatEventType(e),n=e.data||{};let s="",i="";switch(e.type){case"hook":const t=e.tool_name||n.tool_name||"Unknown",o=e.subtype||"Unknown",r=this.getHookDisplayName(o,n);i=this.getEventCategory(e),s=`${r} (${i}): ${t}`;break;case"agent":i="agent_operations",s=`${e.subagent_type||n.subagent_type||"PM"} ${e.subtype||"action"}`;break;case"todo":i="task_management",s=`TodoWrite (${n.todos?n.todos.length:0} items)`;break;case"memory":i="memory_operations",s=`${n.operation||"unknown"} ${n.key||"unknown"}`;break;case"session":i="session_management",s=`Session ${e.subtype||"unknown"}`;break;case"claude":i="claude_interactions",s=`Claude ${e.subtype||"interaction"}`;break;default:i="general",s=e.type||"Unknown Event"}return`${t} ${s}`}getHookDisplayName(e,t){return{pre_tool:"Pre-Tool",post_tool:"Post-Tool",user_prompt:"User-Prompt",stop:"Stop",subagent_stop:"Subagent-Stop",notification:"Notification"}[e]||e.replace("_","-")}getEventCategory(e){const t=e.data||{},n=e.tool_name||t.tool_name||"";return["Read","Write","Edit","MultiEdit"].includes(n)?"file_operations":["Bash","grep","Glob"].includes(n)?"system_operations":"TodoWrite"===n?"task_management":"Task"===n?"agent_delegation":"stop"===e.subtype||"subagent_stop"===e.subtype?"session_control":"general"}showEventDetails(e){if(!this.filteredEvents||!Array.isArray(this.filteredEvents))return void console.warn("EventViewer: filteredEvents array is not initialized");if(e<0||e>=this.filteredEvents.length)return;this.selectedEventIndex=e;const t=this.filteredEvents[e];window.dashboard&&(window.dashboard.tabNavigation&&window.dashboard.tabNavigation.events&&(window.dashboard.tabNavigation.events.selectedIndex=e),window.dashboard.selectCard&&window.dashboard.selectCard("events",e,"event",t)),this.filteredEventElements.forEach((t,n)=>{t.classList.toggle("selected",n===e)}),document.dispatchEvent(new CustomEvent("eventSelected",{detail:{event:t,index:e}}));const n=this.filteredEventElements[e];n&&n.scrollIntoView({behavior:"smooth",block:"nearest"})}clearSelection(){this.selectedEventIndex=-1,this.filteredEventElements.forEach(e=>{e.classList.remove("selected")}),window.dashboard&&(window.dashboard.tabNavigation&&window.dashboard.tabNavigation.events&&(window.dashboard.tabNavigation.events.selectedIndex=-1),window.dashboard.clearCardSelection&&window.dashboard.clearCardSelection()),document.dispatchEvent(new CustomEvent("eventSelectionCleared"))}updateMetrics(){this.eventTypeCount={},this.errorCount=0,this.events&&Array.isArray(this.events)||(console.warn("EventViewer: events array is not initialized in updateMetrics"),this.events=[]),this.events.forEach(e=>{const t=e.type||"unknown";this.eventTypeCount[t]=(this.eventTypeCount[t]||0)+1,"log"===e.type&&e.data&&["error","critical"].includes(e.data.level)&&this.errorCount++});const e=(new Date).getMinutes();e!==this.lastMinute&&(this.lastMinute=e,this.eventsThisMinute=0);const t=new Date(Date.now()-6e4);this.eventsThisMinute=this.events.filter(e=>new Date(e.timestamp)>t).length,this.updateMetricsUI()}updateMetricsUI(){const e=document.getElementById("total-events"),t=document.getElementById("events-per-minute"),n=document.getElementById("unique-types"),s=document.getElementById("error-count");e&&(e.textContent=this.events.length),t&&(t.textContent=this.eventsThisMinute),n&&(n.textContent=Object.keys(this.eventTypeCount).length),s&&(s.textContent=this.errorCount)}exportEvents(){const e=JSON.stringify(this.filteredEvents,null,2),t=new Blob([e],{type:"application/json"}),n=URL.createObjectURL(t),s=document.createElement("a");s.href=n,s.download=`claude-mpm-events-${(new Date).toISOString().split("T")[0]}.json`,s.click(),URL.revokeObjectURL(n)}clearEvents(){this.socketClient.clearEvents(),this.selectedEventIndex=-1,this.updateDisplay()}setSessionFilter(e){this.sessionFilter=e,this.applyFilters()}getFilters(){return{search:this.searchFilter,type:this.typeFilter,session:this.sessionFilter}}getFilteredEvents(){return this.filteredEvents}getAllEvents(){return this.events}createInlineEditDiffViewer(e,t){const n=e.data||{},s=e.tool_name||n.tool_name||"";if(!["Edit","MultiEdit"].includes(s))return"";let i=[];if("Edit"===s){const t=e.tool_parameters||n.tool_parameters||{};t.old_string&&t.new_string&&i.push({old_string:t.old_string,new_string:t.new_string,file_path:t.file_path||"unknown"})}else if("MultiEdit"===s){const t=e.tool_parameters||n.tool_parameters||{};t.edits&&Array.isArray(t.edits)&&(i=t.edits.map(e=>({...e,file_path:t.file_path||"unknown"})))}if(0===i.length)return"";const o=`edit-diff-${t}`,r=i.length>1;let a="";return i.forEach((e,t)=>{const n=this.createDiffHtml(e.old_string,e.new_string);a+=`\n <div class="edit-diff-section">\n ${r?`<div class="edit-diff-header">Edit ${t+1}</div>`:""}\n <div class="diff-content">${n}</div>\n </div>\n `}),`\n <div class="inline-edit-diff-viewer">\n <div class="diff-toggle-header" onclick="eventViewer.toggleEditDiff('${o}', event)">\n <span class="diff-toggle-icon">📋</span>\n <span class="diff-toggle-text">Show ${r?i.length+" edits":"edit"}</span>\n <span class="diff-toggle-arrow">▼</span>\n </div>\n <div id="${o}" class="diff-content-container" style="display: none;">\n ${a}\n </div>\n </div>\n `}createDiffHtml(e,t){const n=e.split("\n"),s=t.split("\n");let i="",o=0,r=0;for(;o<n.length||r<s.length;){const e=o<n.length?n[o]:null,t=r<s.length?s[r]:null;null===e?(i+=`<div class="diff-line diff-added">+ ${this.escapeHtml(t)}</div>`,r++):null===t?(i+=`<div class="diff-line diff-removed">- ${this.escapeHtml(e)}</div>`,o++):e===t?(i+=`<div class="diff-line diff-unchanged"> ${this.escapeHtml(e)}</div>`,o++,r++):(i+=`<div class="diff-line diff-removed">- ${this.escapeHtml(e)}</div>`,i+=`<div class="diff-line diff-added">+ ${this.escapeHtml(t)}</div>`,o++,r++)}return`<div class="diff-container">${i}</div>`}toggleEditDiff(e,t){t.stopPropagation();const n=document.getElementById(e),s=t.currentTarget.querySelector(".diff-toggle-arrow");if(n){const e="none"!==n.style.display;n.style.display=e?"none":"block",s&&(s.textContent=e?"▼":"▲")}}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}}window.EventViewer=e;class t{constructor(e,t){this.eventViewer=e,this.agentInference=t,this.agentEvents=[],this.filteredAgentEvents=[],this.filteredToolEvents=[],this.filteredFileEvents=[],this.selectedSessionId=null,this.fileTrackingCache=new Map,this.trackingCheckTimeout=3e4,console.log("Event processor initialized")}getFilteredEventsForTab(e){const t=this.eventViewer.events;console.log(`getFilteredEventsForTab(${e}) - using RAW events: ${t.length} total`);const n=window.sessionManager;if(n&&n.selectedSessionId){const e=n.getEventsForSession(n.selectedSessionId);return console.log(`Filtering by session ${n.selectedSessionId}: ${e.length} events`),e}return t}applyAgentsFilters(e){const t=document.getElementById("agents-search-input"),n=document.getElementById("agents-type-filter"),s=t?t.value.toLowerCase():"",i=n?n.value:"";return e.filter(e=>{if(s){if(![e.agentName||"",e.type||"",e.isImplied?"implied":"explicit"].join(" ").toLowerCase().includes(s))return!1}if(i){if(!(e.agentName||"unknown").toLowerCase().includes(i.toLowerCase()))return!1}return!0})}applyToolsFilters(e){const t=document.getElementById("tools-search-input"),n=document.getElementById("tools-type-filter"),s=t?t.value.toLowerCase():"",i=n?n.value:"";return e.filter(e=>{if(s){if(![e.tool_name||"",e.agent_type||"",e.type||"",e.subtype||""].join(" ").toLowerCase().includes(s))return!1}if(i){if((e.tool_name||"")!==i)return!1}return!0})}applyToolCallFilters(e){const t=document.getElementById("tools-search-input"),n=document.getElementById("tools-type-filter"),s=t?t.value.toLowerCase():"",i=n?n.value:"";return e.filter(([e,t])=>{if(s){if(![t.tool_name||"",t.agent_type||"","tool_call"].join(" ").toLowerCase().includes(s))return!1}if(i){if((t.tool_name||"")!==i)return!1}return!0})}applyFilesFilters(e){const t=document.getElementById("files-search-input"),n=document.getElementById("files-type-filter"),s=t?t.value.toLowerCase():"",i=n?n.value:"";return e.filter(([e,t])=>{if(this.selectedSessionId){const e=t.operations.filter(e=>e.sessionId===this.selectedSessionId);if(0===e.length)return!1;t={...t,operations:e,lastOperation:e[e.length-1]?.timestamp||t.lastOperation}}if(s){if(![e,...t.operations.map(e=>e.operation),...t.operations.map(e=>e.agent)].join(" ").toLowerCase().includes(s))return!1}if(i){if(!t.operations.map(e=>e.operation).includes(i))return!1}return!0})}extractOperation(e){if(!e)return"unknown";const t=e.toLowerCase();return t.includes("read")?"read":t.includes("write")?"write":t.includes("edit")?"edit":t.includes("create")?"create":t.includes("delete")?"delete":t.includes("move")||t.includes("rename")?"move":"other"}extractToolFromHook(e){if(!e)return"";const t=e.match(/^(?:Pre|Post)(.+)Use$/);return t?t[1]:""}extractToolFromSubtype(e){if(!e)return"";if(e.includes("_")){return e.split("_")[0]||""}return e}extractToolTarget(e,t,n){const s=t||n||{};switch(e?.toLowerCase()){case"read":case"write":case"edit":return s.file_path||s.path||"";case"bash":return s.command||"";case"grep":return s.pattern||"";case"task":return s.subagent_type||s.agent_type||"";default:const e=Object.keys(s),t=["path","file_path","command","pattern","query","target"];for(const n of t)if(s[n])return s[n];return e.length>0?`${e[0]}: ${s[e[0]]}`:""}}generateAgentHTML(e){const t=this.agentInference.getUniqueAgentInstances();return this.applyAgentsFilters(t).map((e,t)=>{const n=e.agentName,s=this.formatTimestamp(e.firstTimestamp||e.timestamp),i=e.isImplied?"implied":"explicit",o=e.totalEventCount||e.eventCount||0;return`\n <div class="event-item single-row event-agent" onclick="${`dashboard.selectCard('agents', ${t}, 'agent_instance', '${e.id}'); dashboard.showAgentInstanceDetails('${e.id}');`}">\n <span class="event-single-row-content">\n <span class="event-content-main">${`${n} (${i}, ${o} events)`}</span>\n <span class="event-timestamp">${s}</span>\n </span>\n </div>\n `}).join("")}generateToolHTML(e){return this.applyToolCallFilters(e).map(([e,t],n)=>{const s=t.tool_name||"Unknown",i=t.agent_type||"Unknown",o=this.formatTimestamp(t.timestamp);return`\n <div class="event-item single-row event-tool ${"completed"===(t.post_event?"completed":"pending")?"status-success":"status-pending"}" onclick="dashboard.selectCard('tools', ${n}, 'toolCall', '${e}'); dashboard.showToolCallDetails('${e}')">\n <span class="event-single-row-content">\n <span class="event-content-main">${`${s} (${"pm"===i.toLowerCase()?"pm":i})`}</span>\n <span class="event-timestamp">${o}</span>\n </span>\n </div>\n `}).join("")}generateFileHTML(e){return this.applyFilesFilters(e).map(([e,t],n)=>{const s=t.operations.map(e=>e.operation),i=this.formatTimestamp(t.lastOperation),o={};s.forEach(e=>{o[e]=(o[e]||0)+1});const r=Object.entries(o).map(([e,t])=>`${e}(${t})`).join(", "),a=[...new Set(t.operations.map(e=>e.agent))],l=a.length>1?`by ${a.length} agents`:`by ${a[0]||"unknown"}`;return`\n <div class="event-item single-row file-item" onclick="dashboard.selectCard('files', ${n}, 'file', '${e}'); dashboard.showFileDetails('${e}')">\n <span class="event-single-row-content">\n <span class="event-content-main">${`${this.getRelativeFilePath(e)} ${r} ${l}`}</span>\n <span class="event-timestamp">${i}</span>\n </span>\n </div>\n `}).join("")}getFileOperationIcon(e){return e.includes("write")||e.includes("create")?"📝":e.includes("edit")?"✏️":e.includes("read")?"👁️":e.includes("delete")?"🗑️":e.includes("move")?"📦":"📄"}getRelativeFilePath(e){if(!e)return"";const t=e.split("/");return t.length>3?".../"+t.slice(-2).join("/"):e}formatTimestamp(e){if(!e)return"";return new Date(e).toLocaleTimeString()}setSelectedSessionId(e){this.selectedSessionId=e}getSelectedSessionId(){return this.selectedSessionId}getUniqueToolInstances(e){return this.applyToolCallFilters(e)}getUniqueFileInstances(e){return this.applyFilesFilters(e)}async isFileTracked(e,t){const n=`${t}:${e}`,s=Date.now(),i=this.fileTrackingCache.get(n);if(i&&s-i.timestamp<this.trackingCheckTimeout)return i.is_tracked;try{const i=window.socket;return i?new Promise(o=>{const r=t=>{if(t.file_path===e){const e=t.success&&t.is_tracked;this.fileTrackingCache.set(n,{is_tracked:e,timestamp:s}),i.off("file_tracked_response",r),o(e)}};i.on("file_tracked_response",r),i.emit("check_file_tracked",{file_path:e,working_dir:t}),setTimeout(()=>{i.off("file_tracked_response",r),o(!1)},5e3)}):(console.warn("No socket connection available for git tracking check"),!1)}catch(o){return console.error("Error checking file tracking status:",o),!1}}generateGitDiffIcon(e,t,n){const s=`git-icon-${e.replace(/[^a-zA-Z0-9]/g,"-")}-${t}`,i=`\n <span id="${s}" class="git-diff-icon"\n onclick="event.stopPropagation(); showGitDiffModal('${e}', '${t}')"\n title="View git diff for this file operation"\n style="margin-left: 8px; cursor: pointer; font-size: 16px;">\n 📋\n </span>\n `;return this.isFileTracked(e,n).then(e=>{const t=document.getElementById(s);t&&(e?(t.innerHTML="📋",t.title="View git diff for this file operation",t.classList.add("tracked-file")):(t.innerHTML="📋❌",t.title="File not tracked by git - click to see details",t.classList.add("untracked-file")))}).catch(e=>{console.error("Error updating git diff icon:",e)}),i}showAgentInstanceDetails(e){const t=this.agentInference.getPMDelegations().get(e);if(!t)return void console.error("Agent instance not found:",e);console.log("Showing agent instance details for:",e,t);const n=`\n <div class="agent-instance-details">\n <h3>Agent Instance: ${t.agentName}</h3>\n <p><strong>Type:</strong> ${t.isImplied?"Implied PM Delegation":"Explicit PM Delegation"}</p>\n <p><strong>Start Time:</strong> ${this.formatTimestamp(t.timestamp)}</p>\n <p><strong>Event Count:</strong> ${t.agentEvents.length}</p>\n <p><strong>Session:</strong> ${t.sessionId}</p>\n ${t.pmCall?`<p><strong>PM Call:</strong> Task delegation to ${t.agentName}</p>`:"<p><strong>Note:</strong> Implied delegation (no explicit PM call found)</p>"}\n </div>\n `;console.log("Agent instance details HTML:",n)}}export{e as E,t as a};
2
+ //# sourceMappingURL=event-viewer.js.map
@@ -0,0 +1,2 @@
1
+ class e{constructor(e){this.eventViewer=e,this.setupEventHandlers(),console.log("Export manager initialized")}setupEventHandlers(){const e=document.querySelector('button[onclick="clearEvents()"]'),t=document.getElementById("export-btn");e&&e.addEventListener("click",()=>{this.clearEvents()}),t&&t.addEventListener("click",()=>{this.exportEvents()})}exportEvents(){this.eventViewer?this.eventViewer.exportEvents():console.error("Cannot export events: EventViewer not available")}clearEvents(){document.dispatchEvent(new CustomEvent("eventsClearing")),this.eventViewer&&this.eventViewer.clearEvents(),document.dispatchEvent(new CustomEvent("eventsCleared")),console.log("Events cleared")}exportEventsCustom(e={}){const{format:t="json",events:n=null,filename:o=null}=e,r=n||(this.eventViewer?this.eventViewer.events:[]);if(0===r.length)return void console.warn("No events to export");const i=(new Date).toISOString().replace(/[:.]/g,"-"),s=o||`claude-mpm-events-${i}`;let l="",a="",c="";switch(t.toLowerCase()){case"json":l=JSON.stringify(r,null,2),a="application/json",c=".json";break;case"csv":l=this.convertEventsToCSV(r),a="text/csv",c=".csv";break;case"txt":l=this.convertEventsToText(r),a="text/plain",c=".txt";break;default:return void console.error("Unsupported export format:",t)}this.downloadFile(l,s+c,a)}convertEventsToCSV(e){if(0===e.length)return"";return[["timestamp","type","subtype","tool_name","agent_type","session_id","data"],...e.map(e=>[e.timestamp||"",e.type||"",e.subtype||"",e.tool_name||"",e.agent_type||"",e.session_id||"",JSON.stringify(e.data||{}).replace(/"/g,'""')])].map(e=>e.map(e=>`"${e}"`).join(",")).join("\n")}convertEventsToText(e){return 0===e.length?"No events to export.":e.map((e,t)=>{const n=this.formatTimestamp(e.timestamp);let o=`Event ${t+1}: ${e.type||"Unknown"}${e.subtype?` (${e.subtype})`:""}${e.tool_name?` - Tool: ${e.tool_name}`:""}${e.agent_type?` - Agent: ${e.agent_type}`:""}\n`;return o+=` Time: ${n}\n`,o+=` Session: ${e.session_id||"Unknown"}\n`,e.data&&Object.keys(e.data).length>0&&(o+=` Data: ${JSON.stringify(e.data,null,2)}\n`),o}).join("\n"+"=".repeat(80)+"\n")}downloadFile(e,t,n){try{const o=new Blob([e],{type:n}),r=window.URL.createObjectURL(o),i=document.createElement("a");i.href=r,i.download=t,i.style.display="none",document.body.appendChild(i),i.click(),document.body.removeChild(i),window.URL.revokeObjectURL(r),console.log(`File exported: ${t}`)}catch(o){console.error("Failed to export file:",o)}}formatTimestamp(e){if(!e)return"Unknown time";try{const t=new Date(e);return isNaN(t.getTime())?"Invalid time":t.toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch(t){return console.error("Error formatting timestamp:",t),"Error formatting time"}}formatFullTimestamp(e){if(!e)return"Unknown time";try{const t=new Date(e);return isNaN(t.getTime())?"Invalid time":t.toLocaleString("en-US",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})}catch(t){return console.error("Error formatting full timestamp:",t),"Error formatting time"}}scrollListToBottom(e){console.log(`[DEBUG] scrollListToBottom called with listId: ${e}`),setTimeout(()=>{const t=document.getElementById(e);console.log(`[DEBUG] Element found for ${e}:`,t),t?(console.log(`[DEBUG] Scrolling ${e} - scrollHeight: ${t.scrollHeight}, scrollTop before: ${t.scrollTop}`),t.scrollTop=t.scrollHeight,console.log(`[DEBUG] Scrolled ${e} - scrollTop after: ${t.scrollTop}`)):console.warn(`[DEBUG] Element with ID '${e}' not found for scrolling`)},50)}debounce(e,t){let n;return function(...o){clearTimeout(n),n=setTimeout(()=>{clearTimeout(n),e(...o)},t)}}throttle(e,t){let n;return function(...o){n||(e.apply(this,o),n=!0,setTimeout(()=>n=!1,t))}}generateId(){return Date.now().toString(36)+Math.random().toString(36).substr(2)}deepClone(e){if(null===e||"object"!=typeof e)return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(e=>this.deepClone(e));if("object"==typeof e){const t={};for(const n in e)e.hasOwnProperty(n)&&(t[n]=this.deepClone(e[n]));return t}return e}}export{e as E};
2
+ //# sourceMappingURL=export-manager.js.map
@@ -0,0 +1,2 @@
1
+ class e{constructor(e,t){this.agentInference=e,this.workingDirectoryManager=t,this.fileOperations=new Map,this.toolCalls=new Map,console.log("File-tool tracker initialized")}updateFileOperations(e){this.fileOperations.clear(),console.log("updateFileOperations - processing",e.length,"events");const t=new Map;let o=0;e.forEach((e,a)=>{const n=this.isFileOperation(e);if(n&&o++,a<5&&console.log(`Event ${a}:`,{type:e.type,subtype:e.subtype,tool_name:e.tool_name,tool_parameters:e.tool_parameters,isFileOp:n}),n){const o=e.tool_name||e.data&&e.data.tool_name,a=e.session_id||e.data&&e.data.session_id||"unknown",n=`${a}_${o}_${Math.floor(new Date(e.timestamp).getTime()/1e3)}`;t.has(n)||t.set(n,{pre_event:null,post_event:null,tool_name:o,session_id:a});const s=t.get(n);"pre_tool"===e.subtype||"hook"===e.type&&e.subtype&&!e.subtype.includes("post")?s.pre_event=e:("post_tool"===e.subtype||e.subtype&&e.subtype.includes("post")||(s.pre_event=e),s.post_event=e)}}),console.log("updateFileOperations - found",o,"file operations in",t.size,"event pairs"),t.forEach((e,t)=>{const o=this.extractFilePathFromPair(e);if(o){console.log("File operation detected for:",o,"from pair:",t),this.fileOperations.has(o)||this.fileOperations.set(o,{path:o,operations:[],lastOperation:null});const a=this.fileOperations.get(o),n=this.getFileOperationFromPair(e),s=e.post_event?.timestamp||e.pre_event?.timestamp,r=this.extractAgentFromPair(e),i=this.workingDirectoryManager.extractWorkingDirectoryFromPair(e);a.operations.push({operation:n,timestamp:s,agent:r.name,confidence:r.confidence,sessionId:e.session_id,details:this.getFileOperationDetailsFromPair(e),workingDirectory:i}),a.lastOperation=s}else console.log("No file path found for pair:",t,e)}),console.log("updateFileOperations - final result:",this.fileOperations.size,"file operations"),this.fileOperations.size>0&&console.log("File operations map:",Array.from(this.fileOperations.entries()))}updateToolCalls(e){this.toolCalls.clear(),console.log("updateToolCalls - processing",e.length,"events");const t=[],o=[];let a=0;e.forEach((e,n)=>{const s=this.isToolOperation(e);s&&a++,n<5&&console.log(`Tool Event ${n}:`,{type:e.type,subtype:e.subtype,tool_name:e.tool_name,tool_parameters:e.tool_parameters,isToolOp:s}),s&&("pre_tool"===e.subtype||"hook"===e.type&&e.subtype&&!e.subtype.includes("post")?t.push(e):("post_tool"===e.subtype||e.subtype&&e.subtype.includes("post")||t.push(e),o.push(e)))}),console.log("updateToolCalls - found",a,"tool operations:",t.length,"pre_tool,",o.length,"post_tool");const n=new Map,s=new Set;t.forEach((e,t)=>{const a=e.tool_name||e.data&&e.data.tool_name,r=e.session_id||e.data&&e.data.session_id||"unknown",i=new Date(e.timestamp).getTime(),l=`${r}_${a}_${t}_${i}`,p={pre_event:e,post_event:null,tool_name:a,session_id:r,operation_type:e.operation_type||"tool_execution",timestamp:e.timestamp,duration_ms:null,success:null,exit_code:null,result_summary:null,agent_type:null,agent_confidence:null},c=this.extractAgentFromEvent(e);p.agent_type=c.name,p.agent_confidence=c.confidence;let _=-1,m=-1;if(o.forEach((t,o)=>{if(s.has(o))return;const n=t.tool_name||t.data&&t.data.tool_name,l=t.session_id||t.data&&t.data.session_id||"unknown";if(n!==a||l!==r)return;const p=new Date(t.timestamp).getTime(),c=Math.abs(p-i);let u=0;p>=i-1e3&&c<=3e5&&(u=1e3-c/1e3,this.compareToolParameters(e,t)&&(u+=500),e.working_directory&&t.working_directory&&e.working_directory===t.working_directory&&(u+=100)),u>m&&(m=u,_=o)}),_>=0&&m>0){const t=o[_];p.post_event=t,p.duration_ms=t.duration_ms,p.success=t.success,p.exit_code=t.exit_code,p.result_summary=t.result_summary,s.add(_),console.log(`Paired pre_tool ${a} at ${e.timestamp} with post_tool at ${t.timestamp} (score: ${m})`)}else console.log(`No matching post_tool found for ${a} at ${e.timestamp} (still running or orphaned)`);n.set(l,p)}),o.forEach((e,t)=>{if(s.has(t))return;const o=e.tool_name||e.data&&e.data.tool_name;console.log("Orphaned post_tool event found:",o,"at",e.timestamp);const a=e.session_id||e.data&&e.data.session_id||"unknown",r=`orphaned_${a}_${o}_${t}_${new Date(e.timestamp).getTime()}`,i={pre_event:null,post_event:e,tool_name:o,session_id:a,operation_type:"tool_execution",timestamp:e.timestamp,duration_ms:e.duration_ms,success:e.success,exit_code:e.exit_code,result_summary:e.result_summary,agent_type:null,agent_confidence:null},l=this.extractAgentFromEvent(e);i.agent_type=l.name,i.agent_confidence=l.confidence,n.set(r,i)}),this.toolCalls=n,console.log("updateToolCalls - final result:",this.toolCalls.size,"tool calls"),this.toolCalls.size>0&&console.log("Tool calls map keys:",Array.from(this.toolCalls.keys()))}isToolOperation(e){const t=e.tool_name||e.data&&e.data.tool_name,o="hook"===e.type,a="pre_tool"===e.subtype||"post_tool"===e.subtype||e.subtype&&"string"==typeof e.subtype&&e.subtype.includes("tool");return t&&o&&a}isFileOperation(e){let t=e.tool_name||e.data&&e.data.tool_name||"";t=t.toLowerCase();const o=e.tool_parameters||e.data&&e.data.tool_parameters;if("bash"===t&&o){if((o.command||"").match(/\b(cat|less|more|head|tail|touch|mv|cp|rm|mkdir|ls|find)\b/))return!0}return t&&["read","write","edit","grep","multiedit","glob","ls","bash","notebookedit"].includes(t)}extractFilePath(e){if(e.tool_parameters?.file_path)return e.tool_parameters.file_path;if(e.tool_parameters?.path)return e.tool_parameters.path;if(e.tool_parameters?.notebook_path)return e.tool_parameters.notebook_path;if(e.data?.tool_parameters?.file_path)return e.data.tool_parameters.file_path;if(e.data?.tool_parameters?.path)return e.data.tool_parameters.path;if(e.data?.tool_parameters?.notebook_path)return e.data.tool_parameters.notebook_path;if(e.file_path)return e.file_path;if(e.path)return e.path;if("glob"===e.tool_name?.toLowerCase()&&e.tool_parameters?.pattern)return`[glob] ${e.tool_parameters.pattern}`;if("bash"===e.tool_name?.toLowerCase()&&e.tool_parameters?.command){const t=e.tool_parameters.command.match(/(?:cat|less|more|head|tail|touch|mv|cp|rm|mkdir|ls|find|echo.*>|sed|awk|grep)\s+([^\s;|&]+)/);if(t&&t[1])return t[1]}return null}extractFilePathFromPair(e){let t=null;return e.pre_event&&(t=this.extractFilePath(e.pre_event)),!t&&e.post_event&&(t=this.extractFilePath(e.post_event)),t}getFileOperation(e){if(!e.tool_name)return"unknown";const t=e.tool_name.toLowerCase();switch(t){case"read":return"read";case"write":return"write";case"edit":case"multiedit":case"notebookedit":return"edit";case"grep":case"glob":return"search";case"ls":return"list";case"bash":const o=e.tool_parameters?.command||"";return o.match(/\b(cat|less|more|head|tail)\b/)?"read":o.match(/\b(touch|echo.*>|tee)\b/)?"write":o.match(/\b(sed|awk)\b/)?"edit":o.match(/\b(grep|find)\b/)?"search":o.match(/\b(ls|dir)\b/)?"list":o.match(/\b(mv|cp)\b/)?"copy/move":o.match(/\b(rm|rmdir)\b/)?"delete":o.match(/\b(mkdir)\b/)?"create":"bash";default:return t}}getFileOperationFromPair(e){return e.pre_event?this.getFileOperation(e.pre_event):e.post_event?this.getFileOperation(e.post_event):"unknown"}extractAgentFromPair(e){const t=e.pre_event||e.post_event;if(t&&this.agentInference){const e=this.agentInference.getInferredAgentForEvent(t);if(e)return{name:e.agentName||"Unknown",confidence:e.confidence||"unknown"}}return{name:t?.agent_type||t?.subagent_type||e.pre_event?.agent_type||e.post_event?.agent_type||"PM",confidence:"direct"}}getFileOperationDetailsFromPair(e){const t={};if(e.pre_event){const o=e.pre_event.tool_parameters||e.pre_event.data?.tool_parameters||{};t.parameters=o,t.tool_input=e.pre_event.tool_input}return e.post_event&&(t.result=e.post_event.result,t.success=e.post_event.success,t.error=e.post_event.error,t.exit_code=e.post_event.exit_code,t.duration_ms=e.post_event.duration_ms),t}getFileOperations(){return this.fileOperations}getToolCalls(){return this.toolCalls}getToolCallsArray(){return Array.from(this.toolCalls.entries())}getFileOperationsForFile(e){return this.fileOperations.get(e)||null}getToolCall(e){return this.toolCalls.get(e)||null}clear(){this.fileOperations.clear(),this.toolCalls.clear(),console.log("File-tool tracker cleared")}getStatistics(){return{fileOperations:this.fileOperations.size,toolCalls:this.toolCalls.size,uniqueFiles:this.fileOperations.size,totalFileOperations:Array.from(this.fileOperations.values()).reduce((e,t)=>e+t.operations.length,0)}}compareToolParameters(e,t){const o=e.tool_parameters||e.data?.tool_parameters||{},a=t.tool_parameters||t.data?.tool_parameters||{};if(0===Object.keys(o).length&&0===Object.keys(a).length)return!1;let n=0,s=0;if(["file_path","path","pattern","command","notebook_path"].forEach(e=>{const t=o[e],r=a[e];void 0===t&&void 0===r||(s++,t===r&&n++)}),s>0)return n/s>=.8;const r=Object.keys(o).sort(),i=Object.keys(a).sort();if(0===r.length&&0===i.length)return!1;if(r.length===i.length){return r.filter(e=>i.includes(e)).length>=Math.max(1,.5*r.length)}return!1}extractAgentFromEvent(e){if(this.agentInference){const t=this.agentInference.getInferredAgentForEvent(e);if(t)return{name:t.agentName||"Unknown",confidence:t.confidence||"unknown"}}return{name:e.agent_type||e.subagent_type||e.data?.agent_type||e.data?.subagent_type||"PM",confidence:"direct"}}}export{e as F};
2
+ //# sourceMappingURL=file-tool-tracker.js.map
@@ -0,0 +1,2 @@
1
+ window.HUDLibraryLoader=new class{constructor(){this.loadedLibraries=new Set,this.loadingPromises=new Map,this.loadingCallbacks=new Map,this.libraries=[{name:"cytoscape",url:"https://unpkg.com/cytoscape@3.26.0/dist/cytoscape.min.js",globalCheck:()=>void 0!==window.cytoscape,dependencies:[]},{name:"dagre",url:"https://unpkg.com/dagre@0.8.5/dist/dagre.min.js",globalCheck:()=>void 0!==window.dagre,dependencies:[]},{name:"cytoscape-dagre",url:"https://unpkg.com/cytoscape-dagre@2.5.0/cytoscape-dagre.js",globalCheck:()=>void 0!==window.cytoscapeDagre,dependencies:["cytoscape","dagre"]}]}loadLibrary(e){if(e.globalCheck())return this.loadedLibraries.add(e.name),Promise.resolve();if(this.loadingPromises.has(e.name))return this.loadingPromises.get(e.name);console.log(`Loading library: ${e.name} from ${e.url}`);const r=new Promise((r,a)=>{const i=document.createElement("script");i.src=e.url,i.async=!0,i.onload=()=>{if(e.globalCheck())console.log(`Successfully loaded library: ${e.name}`),this.loadedLibraries.add(e.name),this.loadingPromises.delete(e.name),r();else{const r=new Error(`Library ${e.name} failed global check after loading`);console.error(r),this.loadingPromises.delete(e.name),a(r)}},i.onerror=()=>{const r=new Error(`Failed to load library: ${e.name} from ${e.url}`);console.error(r),this.loadingPromises.delete(e.name),a(r)},document.head.appendChild(i)});return this.loadingPromises.set(e.name,r),r}async loadDependencies(e){const r=e.map(e=>{const r=this.libraries.find(r=>r.name===e);if(!r)throw new Error(`Dependency ${e} not found in library configuration`);return this.loadLibraryWithDependencies(r)});return Promise.all(r)}async loadLibraryWithDependencies(e){return e.dependencies.length>0&&await this.loadDependencies(e.dependencies),this.loadLibrary(e)}async loadHUDLibraries(e=null){console.log("Starting HUD libraries loading...");try{for(let a=0;a<this.libraries.length;a++){const r=this.libraries[a];e&&e({library:r.name,current:a+1,total:this.libraries.length,message:`Loading ${r.name}...`}),await this.loadLibraryWithDependencies(r)}const r=this.libraries.filter(e=>!e.globalCheck());if(r.length>0)throw new Error(`Failed to load libraries: ${r.map(e=>e.name).join(", ")}`);return console.log("All HUD libraries loaded successfully"),e&&e({library:"complete",current:this.libraries.length,total:this.libraries.length,message:"All libraries loaded successfully"}),!0}catch(r){throw console.error("Failed to load HUD libraries:",r),e&&e({library:"error",current:0,total:this.libraries.length,message:`Error: ${r.message}`,error:r}),r}}areLibrariesLoaded(){return this.libraries.every(e=>e.globalCheck())}getLoadingStatus(){return{loaded:Array.from(this.loadedLibraries),loading:Array.from(this.loadingPromises.keys()),total:this.libraries.length,allLoaded:this.areLibrariesLoaded()}}reset(){this.loadedLibraries.clear(),this.loadingPromises.clear(),this.loadingCallbacks.clear()}};
2
+ //# sourceMappingURL=hud-library-loader.js.map
@@ -0,0 +1,2 @@
1
+ window.HUDVisualizer=class{constructor(){this.cy=null,this.container=null,this.nodes=new Map,this.isActive=!1,this.librariesLoaded=!1,this.loadingPromise=null,this.pendingEvents=[],this.layoutConfig={name:"dagre",rankDir:"TB",animate:!0,animationDuration:500,fit:!0,padding:30,rankSep:100,nodeSep:80},this.nodeTypes={PM:{color:"#48bb78",shape:"rectangle",width:120,height:40,icon:"👤"},AGENT:{color:"#9f7aea",shape:"ellipse",width:100,height:60,icon:"🤖"},TOOL:{color:"#4299e1",shape:"diamond",width:80,height:50,icon:"🔧"},TODO:{color:"#e53e3e",shape:"triangle",width:70,height:40,icon:"📝"}}}initialize(){return this.container=document.getElementById("hud-cytoscape"),this.container?(this.container.style.pointerEvents="auto",this.container.style.cursor="default",this.container.style.position="relative",this.container.style.zIndex="1",this.setupBasicEventHandlers(),console.log("HUD Visualizer initialized (libraries will load lazily)"),!0):(console.error("HUD container not found"),!1)}async loadLibrariesAndInitialize(){return this.librariesLoaded&&this.cy?Promise.resolve():(this.loadingPromise||(this.loadingPromise=this._performLazyLoading()),this.loadingPromise)}async _performLazyLoading(){try{if(console.log("[HUD-VISUALIZER-DEBUG] _performLazyLoading() called"),console.log("[HUD-VISUALIZER-DEBUG] Loading HUD visualization libraries..."),this.showLoadingIndicator(),!window.HUDLibraryLoader)throw new Error("HUD Library Loader not available");if(console.log("[HUD-VISUALIZER-DEBUG] HUD Library Loader found, loading libraries..."),await window.HUDLibraryLoader.loadHUDLibraries(e=>{console.log("[HUD-VISUALIZER-DEBUG] Loading progress:",e),this.updateLoadingProgress(e)}),console.log("[HUD-VISUALIZER-DEBUG] Verifying libraries are loaded..."),void 0===window.cytoscape)throw new Error("Cytoscape.js not loaded");if(void 0===window.dagre)throw new Error("Dagre not loaded");if(void 0===window.cytoscapeDagre)throw new Error("Cytoscape-dagre not loaded");return console.log("[HUD-VISUALIZER-DEBUG] All HUD libraries loaded successfully"),this.librariesLoaded=!0,console.log("[HUD-VISUALIZER-DEBUG] Initializing Cytoscape..."),this.initializeCytoscape(),console.log("[HUD-VISUALIZER-DEBUG] Setting up Cytoscape event handlers..."),this.setupCytoscapeEventHandlers(),console.log("[HUD-VISUALIZER-DEBUG] Processing pending events..."),this.processPendingEvents(),this.hideLoadingIndicator(),console.log("[HUD-VISUALIZER-DEBUG] HUD Visualizer fully initialized with lazy loading"),!0}catch(e){throw console.error("[HUD-VISUALIZER-DEBUG] Failed to load HUD libraries:",e),console.error("[HUD-VISUALIZER-DEBUG] Error stack:",e.stack),this.showLoadingError(e.message),this.librariesLoaded=!1,this.loadingPromise=null,e}}initializeCytoscape(){this.librariesLoaded&&window.cytoscape?(void 0!==window.cytoscape&&void 0!==window.cytoscapeDagre&&window.cytoscape.use(window.cytoscapeDagre),this.cy=window.cytoscape({container:this.container,elements:[],userZoomingEnabled:!0,userPanningEnabled:!0,boxSelectionEnabled:!1,autoungrabify:!1,autounselectify:!1,style:[{selector:"node",style:{"background-color":"data(color)","border-color":"data(borderColor)","border-width":2,color:"#ffffff",label:"data(label)","text-valign":"center","text-halign":"center","font-size":"12px","font-weight":"bold",width:"data(width)",height:"data(height)",shape:"data(shape)","text-wrap":"wrap","text-max-width":"100px"}},{selector:"edge",style:{width:2,"line-color":"#718096","target-arrow-color":"#718096","target-arrow-shape":"triangle","curve-style":"bezier","arrow-scale":1.2}},{selector:".pm-node",style:{"background-color":"#48bb78","border-color":"#38a169",shape:"rectangle"}},{selector:".agent-node",style:{"background-color":"#9f7aea","border-color":"#805ad5",shape:"ellipse"}},{selector:".tool-node",style:{"background-color":"#4299e1","border-color":"#3182ce",shape:"diamond"}},{selector:".todo-node",style:{"background-color":"#e53e3e","border-color":"#c53030",shape:"triangle"}},{selector:"node:active",style:{"overlay-opacity":.2,"overlay-color":"#000000"}}],layout:this.layoutConfig}),this.setupResizeHandler()):console.error("Cannot initialize Cytoscape: libraries not loaded")}setupBasicEventHandlers(){const e=document.getElementById("hud-reset-layout");e&&e.addEventListener("click",()=>{this.resetLayout()});const t=document.getElementById("hud-center-view");t&&t.addEventListener("click",()=>{this.centerView()})}setupCytoscapeEventHandlers(){this.cy?(console.log("[HUD-VISUALIZER-DEBUG] Setting up Cytoscape event handlers..."),this.cy.on("tap","node",e=>{const t=e.target,o=t.data();console.log("[HUD-VISUALIZER-DEBUG] Node clicked:",o),this.highlightConnectedNodes(t)}),this.cy.on("tap",e=>{e.target===this.cy&&(console.log("[HUD-VISUALIZER-DEBUG] Background clicked - resetting highlights"),this.cy.nodes().style({opacity:1}),this.cy.edges().style({opacity:1}))}),this.cy.on("mouseover","node",e=>{e.target.style("opacity",.8)}),this.cy.on("mouseout","node",e=>{e.target.style("opacity",1)}),console.log("[HUD-VISUALIZER-DEBUG] Cytoscape event handlers set up successfully")):console.warn("[HUD-VISUALIZER-DEBUG] Cannot setup Cytoscape event handlers: no cy instance")}setupResizeHandler(){const e=new ResizeObserver(()=>{this.cy&&this.isActive&&this.ensureContainerResize()});this.container&&e.observe(this.container)}ensureContainerResize(){if(!this.cy||!this.container)return void console.log("[HUD-VISUALIZER-DEBUG] Cannot resize: missing cy or container");this.ensureContainerInteractivity();const e=this.container.getBoundingClientRect();if(console.log("[HUD-VISUALIZER-DEBUG] Container dimensions:",{width:e.width,height:e.height,offsetWidth:this.container.offsetWidth,offsetHeight:this.container.offsetHeight,isVisible:e.width>0&&e.height>0}),e.width>0&&e.height>0){console.log("[HUD-VISUALIZER-DEBUG] Container is visible, resizing Cytoscape...");try{this.cy.resize();const e=this.cy.nodes().length,t=this.cy.edges().length;console.log("[HUD-VISUALIZER-DEBUG] Cytoscape elements after resize:",{nodes:e,edges:t}),e>0?(console.log("[HUD-VISUALIZER-DEBUG] Running fit and layout..."),this.cy.fit(),this.runLayout()):console.log("[HUD-VISUALIZER-DEBUG] No nodes to display")}catch(t){console.error("[HUD-VISUALIZER-DEBUG] Error during resize:",t)}}else console.log("[HUD-VISUALIZER-DEBUG] Container not visible yet, skipping resize")}ensureContainerInteractivity(){if(!this.container)return;this.container.style.pointerEvents="auto",this.container.style.cursor="default",this.container.style.userSelect="none",this.container.style.touchAction="manipulation";const e=this.container.parentElement;e&&(e.style.pointerEvents="auto",e.style.position="relative"),console.log("[HUD-VISUALIZER-DEBUG] Container interactivity ensured")}async activate(){console.log("[HUD-VISUALIZER-DEBUG] activate() called"),this.isActive=!0;try{console.log("[HUD-VISUALIZER-DEBUG] Loading libraries and initializing..."),await this.loadLibrariesAndInitialize(),console.log("[HUD-VISUALIZER-DEBUG] Libraries loaded, cy exists:",!!this.cy),this.cy||(console.log("[HUD-VISUALIZER-DEBUG] Cytoscape instance missing, recreating..."),this.initializeCytoscape(),this.setupCytoscapeEventHandlers()),this.cy&&(console.log("[HUD-VISUALIZER-DEBUG] Triggering resize and fit..."),setTimeout(()=>{console.log("[HUD-VISUALIZER-DEBUG] First resize attempt..."),this.ensureContainerResize()},50),setTimeout(()=>{console.log("[HUD-VISUALIZER-DEBUG] Second resize attempt..."),this.ensureContainerResize()},200),setTimeout(()=>{console.log("[HUD-VISUALIZER-DEBUG] Final resize attempt..."),this.ensureContainerResize()},500)),console.log("[HUD-VISUALIZER-DEBUG] activate() completed successfully")}catch(e){throw console.error("[HUD-VISUALIZER-DEBUG] Failed to activate HUD:",e),console.error("[HUD-VISUALIZER-DEBUG] Error stack:",e.stack),e}}deactivate(){this.isActive=!1}processPendingEvents(){if(this.pendingEvents.length>0){console.log(`Processing ${this.pendingEvents.length} pending events`);for(const e of this.pendingEvents)this._processEventInternal(e);this.pendingEvents=[]}}processExistingEvents(e){if(console.log(`[HUD-VISUALIZER-DEBUG] processExistingEvents called with ${e?e.length:0} events`),!e)return void console.error("[HUD-VISUALIZER-DEBUG] No events provided to processExistingEvents");if(!Array.isArray(e))return void console.error("[HUD-VISUALIZER-DEBUG] Events is not an array:",typeof e);if(console.log(`[HUD-VISUALIZER-DEBUG] Libraries loaded: ${this.librariesLoaded}, Cytoscape available: ${!!this.cy}`),!this.librariesLoaded||!this.cy)return console.warn("[HUD-VISUALIZER-DEBUG] HUD libraries not loaded, cannot process existing events"),console.log(`[HUD-VISUALIZER-DEBUG] Storing ${e.length} events as pending`),void(this.pendingEvents=[...e]);console.log(`[HUD-VISUALIZER-DEBUG] 🏗️ Building HUD tree structure from ${e.length} historical events`),e.length>0&&(console.log("[HUD-VISUALIZER-DEBUG] Sample events:"),e.slice(0,3).forEach((e,t)=>{console.log(`[HUD-VISUALIZER-DEBUG] Event ${t+1}:`,{timestamp:e.timestamp,hook_event_name:e.hook_event_name,type:e.type,subtype:e.subtype,session_id:e.session_id,data_session_id:e.data?.session_id,data_keys:e.data?Object.keys(e.data):"no data"})})),this.clear();const t=this.groupEventsBySession(e);Object.entries(t).forEach(([e,t])=>{console.log(` 📂 Processing session ${e}: ${t.length} events`),this.buildSessionTree(e,t)}),this.runLayout(),console.log("✅ HUD tree structure built successfully")}groupEventsBySession(e){const t={};return e.forEach(e=>{const o=e.session_id||e.data?.session_id||"unknown";t[o]||(t[o]=[]),t[o].push(e)}),t}buildSessionTree(e,t){console.log(`[HUD-VISUALIZER-DEBUG] Building session tree for ${e} with ${t.length} events`);const o=new Map;let n=null;const s=t.sort((e,t)=>new Date(e.timestamp).getTime()-new Date(t.timestamp).getTime());console.log(`[HUD-VISUALIZER-DEBUG] Sorted ${s.length} events chronologically`),s.forEach((t,s)=>{const i=this.createNodeFromEvent(t,e);i&&(this.addNode(i.id,i.type,i.label,{sessionId:e,timestamp:t.timestamp,eventData:t,isSessionRoot:i.isSessionRoot}),o.set(i.id,{...i,event:t,index:s}),i.isSessionRoot&&!n&&(n=i.id),this.createHierarchicalRelationships(i.id,t,o,n))})}createNodeFromEvent(e,t){const o=e.hook_event_name||e.type||"",n=e.subtype||"",s=new Date(e.timestamp||Date.now());console.log(`[HUD-VISUALIZER-DEBUG] Creating node from event: ${o}/${n} for session ${t}`);let i,r,a,l=!1;const c=s.getTime(),d=Math.random().toString(36).substring(2,7);if("session"===o&&"started"===n)r="PM",a=`Session ${t.substring(0,8)}...`,i=`session-${t.replace(/[^a-zA-Z0-9]/g,"")}`,l=!0;else if("hook"===o&&"user_prompt"===n){r="PM";const t=e.data?.prompt_preview||"User Prompt";a=t.length>20?t.substring(0,20)+"...":t,i=`user-prompt-${c}-${d}`}else if("hook"===o&&"claude_response"===n)r="PM",a="Claude Response",i=`claude-response-${c}-${d}`;else if("hook"===o&&"pre_tool"===n){r="TOOL";const t=e.data?.tool_name||"Unknown Tool",o=t.replace(/[^a-zA-Z0-9]/g,"");a=`${t}`,i=`tool-${o}-${c}-${d}`}else if("agent"===o||e.data?.agent_type){r="AGENT";const t=e.data?.agent_type||e.data?.agent_name||"Agent",o=t.replace(/[^a-zA-Z0-9]/g,"");a=t,i=`agent-${o}-${c}-${d}`}else if("todo"===o||n.includes("todo"))r="TODO",a="Todo Update",i=`todo-${c}-${d}`;else{if("hook"===o&&"notification"===n)return null;if("log"===o){const t=e.data?.level||"info";if(!["error","critical"].includes(t))return null;r="PM",a=`${t.toUpperCase()} Log`,i=`log-${t}-${c}-${d}`}else{r="PM";const e=o.replace(/[^a-zA-Z0-9]/g,"")||"Event";a=o||"Event",i=`generic-${e}-${c}-${d}`}}return{id:i,type:r,label:a,isSessionRoot:l}}createHierarchicalRelationships(e,t,o,n){const s=t.hook_event_name||t.type||"",i=t.subtype||"";let r=null;"session"===s&&"started"===i||(r="hook"===s&&"pre_tool"===i?this.findRecentParentNode(o,["user-prompt","agent"],e):"hook"===s&&"claude_response"===i?this.findRecentParentNode(o,["user-prompt"],e):"agent"===s?this.findRecentParentNode(o,["user-prompt","agent"],e):"todo"===s?this.findRecentParentNode(o,["agent","user-prompt"],e):this.findRecentParentNode(o,["user-prompt","agent","session"],e),!r&&n&&e!==n&&(r=n),r&&r!==e&&this.addEdge(r,e))}findRecentParentNode(e,t,o){const n=Array.from(e.entries()).reverse();for(const[s,i]of n)if(s!==o)for(const e of t)if(s.startsWith(e))return s;return null}processEvent(e){this.isActive&&(this.librariesLoaded&&this.cy?this._processEventInternal(e):this.pendingEvents.push(e))}_processEventInternal(e){const t=e.hook_event_name||e.type||"",o=e.session_id||"unknown",n=new Date(e.timestamp||Date.now());let s=`${t}-${n.getTime()}`,i="PM",r=t;if(t.includes("tool_call")){i="TOOL";const t=e.data?.tool_name||"Unknown Tool";r=t,s=`tool-${t}-${n.getTime()}`}else if(t.includes("agent")){i="AGENT";const t=e.data?.agent_name||"Agent";r=t,s=`agent-${t}-${n.getTime()}`}else t.includes("todo")?(i="TODO",r="Todo List",s=`todo-${n.getTime()}`):(t.includes("user_prompt")||t.includes("claude_response"))&&(i="PM",r=t.includes("user_prompt")?"User Prompt":"Claude Response",s=`pm-${r.replace(" ","")}-${n.getTime()}`);this.addNode(s,i,r,{sessionId:o,timestamp:n.toISOString(),eventData:e}),this.createEventRelationships(s,e)}addNode(e,t,o,n={}){if(console.log(`[HUD-VISUALIZER-DEBUG] Adding node: ${e} (${t}) - ${o}`),this.nodes.has(e))return void console.log(`[HUD-VISUALIZER-DEBUG] Node ${e} already exists, skipping`);const s=this.nodeTypes[t]||this.nodeTypes.PM,i={id:e,label:`${s.icon} ${o}`,type:t,color:s.color,borderColor:this.darkenColor(s.color,20),shape:s.shape,width:s.width,height:s.height,...n};if(this.nodes.set(e,i),this.cy){const e={group:"nodes",data:i,classes:`${t.toLowerCase()}-node`};console.log("[HUD-VISUALIZER-DEBUG] Adding node element to Cytoscape:",e),this.cy.add(e),console.log(`[HUD-VISUALIZER-DEBUG] Node added successfully. Total nodes in cy: ${this.cy.nodes().length}`),this.runLayout()}}addEdge(e,t,o=null,n={}){if(e&&t)if(e!==t){if(o||(o=`edge-${e}-to-${t}`),this.cy){if(this.cy.getElementById(o).length>0)return void console.log(`[HUD-VISUALIZER-DEBUG] Edge ${o} already exists, skipping`);const i=this.cy.getElementById(e),r=this.cy.getElementById(t);if(0===i.length)return void console.warn(`[HUD-VISUALIZER-DEBUG] Source node ${e} does not exist, cannot create edge`);if(0===r.length)return void console.warn(`[HUD-VISUALIZER-DEBUG] Target node ${t} does not exist, cannot create edge`);const a={group:"edges",data:{id:o,source:e,target:t,...n}};console.log("[HUD-VISUALIZER-DEBUG] Adding edge element to Cytoscape:",a);try{this.cy.add(a),console.log(`[HUD-VISUALIZER-DEBUG] Edge added successfully. Total edges in cy: ${this.cy.edges().length}`),this.runLayout()}catch(s){console.error(`[HUD-VISUALIZER-DEBUG] Failed to add edge ${o}:`,s),console.error("[HUD-VISUALIZER-DEBUG] Element details:",a)}}}else console.warn(`[HUD-VISUALIZER-DEBUG] Cannot create self-loop edge from ${e} to itself`);else console.warn(`[HUD-VISUALIZER-DEBUG] Cannot create edge: missing source (${e}) or target (${t})`)}createEventRelationships(e,t){const o=t.hook_event_name||t.type||"",n=t.session_id||"unknown";if(Array.from(this.nodes.entries()),o.includes("tool_call")&&t.data?.tool_name){const t=this.findParentNode(n,["PM","AGENT"]);if(t)return void this.addEdge(t,e)}if(o.includes("agent")||t.data?.agent_name){const t=this.findParentNode(n,["PM"]);if(t)return void this.addEdge(t,e)}if(o.includes("todo")){const t=this.findParentNode(n,["AGENT","PM"]);if(t)return void this.addEdge(t,e)}const s=Array.from(this.nodes.keys()),i=s.indexOf(e);if(i>0){const t=s[i-1];this.addEdge(t,e)}}findParentNode(e,t){const o=Array.from(this.nodes.entries()).reverse();for(const[n,s]of o)if(s.sessionId===e&&t.includes(s.type))return n;return null}highlightConnectedNodes(e){if(!this.cy)return;this.cy.nodes().style({opacity:.3}),this.cy.edges().style({opacity:.2});const t=e.neighborhood();e.style("opacity",1),t.style("opacity",1)}resetLayout(){this.cy&&this.cy.layout(this.layoutConfig).run()}centerView(){this.cy&&(this.cy.fit(),this.cy.center())}runLayout(){if(console.log(`[HUD-VISUALIZER-DEBUG] runLayout called - isActive: ${this.isActive}, cy exists: ${!!this.cy}`),this.cy&&this.isActive){const e=this.cy.nodes().length,t=this.cy.edges().length;if(console.log(`[HUD-VISUALIZER-DEBUG] Running layout with ${e} nodes and ${t} edges`),this.container){const e=this.container.getBoundingClientRect();console.log("[HUD-VISUALIZER-DEBUG] Container dimensions before layout:",{width:e.width,height:e.height,offsetWidth:this.container.offsetWidth,offsetHeight:this.container.offsetHeight})}const o=this.cy.layout(this.layoutConfig);o.on("layoutstop",()=>{console.log("[HUD-VISUALIZER-DEBUG] Layout completed. Final node positions:"),this.cy.nodes().forEach((e,t)=>{const o=e.position(),n=e.data();console.log(`[HUD-VISUALIZER-DEBUG] Node ${t+1}: ${n.label} at (${o.x.toFixed(1)}, ${o.y.toFixed(1)})`)})}),o.run()}else console.log("[HUD-VISUALIZER-DEBUG] Skipping layout - not active or no Cytoscape instance")}clear(){if(console.log(`[HUD-VISUALIZER-DEBUG] Clearing HUD: ${this.nodes.size} nodes, ${this.pendingEvents.length} pending events`),this.nodes.clear(),this.pendingEvents=[],this.cy){const o=this.cy.elements().length;try{this.cy.elements().remove(),console.log(`[HUD-VISUALIZER-DEBUG] Removed ${o} Cytoscape elements`)}catch(e){console.error("[HUD-VISUALIZER-DEBUG] Error clearing Cytoscape elements:",e);try{this.cy.destroy(),this.cy=null,console.log("[HUD-VISUALIZER-DEBUG] Destroyed Cytoscape instance due to clear error")}catch(t){console.error("[HUD-VISUALIZER-DEBUG] Error destroying Cytoscape:",t)}}}}showLoadingIndicator(){this.container&&(this.container.innerHTML='\n <div class="hud-loading-container">\n <div class="hud-loading-spinner"></div>\n <div class="hud-loading-text">Loading HUD visualization libraries...</div>\n <div class="hud-loading-progress" id="hud-loading-progress"></div>\n </div>\n ')}updateLoadingProgress(e){const t=document.getElementById("hud-loading-progress");t&&(e.error?t.innerHTML=`<span class="hud-error">❌ ${e.message}</span>`:t.innerHTML=`\n <div class="hud-progress-bar">\n <div class="hud-progress-fill" style="width: ${e.current/e.total*100}%"></div>\n </div>\n <div class="hud-progress-text">${e.message} (${e.current}/${e.total})</div>\n `)}hideLoadingIndicator(){this.container&&(this.container.innerHTML="")}showLoadingError(e){this.container&&(this.container.innerHTML=`\n <div class="hud-error-container">\n <div class="hud-error-icon">⚠️</div>\n <div class="hud-error-text">Failed to load HUD libraries</div>\n <div class="hud-error-message">${e}</div>\n <button class="hud-retry-button" onclick="window.hudVisualizer && window.hudVisualizer.retryLoading()">\n Retry Loading\n </button>\n </div>\n `)}retryLoading(){this.librariesLoaded=!1,this.loadingPromise=null,this.activate()}debugTest(){return console.log("[HUD-VISUALIZER-DEBUG] debugTest() called manually"),console.log("[HUD-VISUALIZER-DEBUG] Current state:",{isActive:this.isActive,librariesLoaded:this.librariesLoaded,hasCy:!!this.cy,hasContainer:!!this.container,nodeCount:this.nodes.size,pendingEventCount:this.pendingEvents.length,hasHUDLibraryLoader:!!window.HUDLibraryLoader}),this.container&&console.log("[HUD-VISUALIZER-DEBUG] Container info:",{id:this.container.id,className:this.container.className,offsetWidth:this.container.offsetWidth,offsetHeight:this.container.offsetHeight,innerHTML:this.container.innerHTML?"has content":"empty"}),console.log("[HUD-VISUALIZER-DEBUG] Library availability:",{cytoscape:typeof window.cytoscape,dagre:typeof window.dagre,cytoscapeDagre:typeof window.cytoscapeDagre,HUDLibraryLoader:typeof window.HUDLibraryLoader}),{isActive:this.isActive,librariesLoaded:this.librariesLoaded,hasCy:!!this.cy,containerFound:!!this.container}}debugBlankScreen(){console.log("[HUD-BLANK-SCREEN-DEBUG] ================================="),console.log("[HUD-BLANK-SCREEN-DEBUG] COMPREHENSIVE BLANK SCREEN DEBUG"),console.log("[HUD-BLANK-SCREEN-DEBUG] =================================");const e={isActive:this.isActive,librariesLoaded:this.librariesLoaded,hasCy:!!this.cy,hasContainer:!!this.container,nodeCount:this.nodes.size,cytoscapeElementCount:this.cy?this.cy.elements().length:0};if(console.log("[HUD-BLANK-SCREEN-DEBUG] 1. Basic State:",e),!this.container)return console.error("[HUD-BLANK-SCREEN-DEBUG] 2. Container not found!"),!1;{const e=this.getContainerDebugInfo();console.log("[HUD-BLANK-SCREEN-DEBUG] 2. Container Info:",e),this.debugAddContainerBackground()}if(!this.cy)return console.error("[HUD-BLANK-SCREEN-DEBUG] 3. Cytoscape instance not found!"),!1;{const e=this.getCytoscapeDebugInfo();console.log("[HUD-BLANK-SCREEN-DEBUG] 3. Cytoscape Info:",e)}return this.debugNodePositions(),this.debugManualRenderingTriggers(),this.cy&&0===this.cy.nodes().length&&(console.log("[HUD-BLANK-SCREEN-DEBUG] 6. No nodes found, adding test nodes..."),this.debugAddTestNodes()),this.debugForceZoomFit(),console.log("[HUD-BLANK-SCREEN-DEBUG] Debug complete. Check visual results."),!0}getContainerDebugInfo(){const e=this.container.getBoundingClientRect(),t=window.getComputedStyle(this.container);return{id:this.container.id,className:this.container.className,offsetWidth:this.container.offsetWidth,offsetHeight:this.container.offsetHeight,clientWidth:this.container.clientWidth,clientHeight:this.container.clientHeight,scrollWidth:this.container.scrollWidth,scrollHeight:this.container.scrollHeight,boundingRect:{width:e.width,height:e.height,top:e.top,left:e.left,bottom:e.bottom,right:e.right},computedStyles:{display:t.display,visibility:t.visibility,opacity:t.opacity,position:t.position,overflow:t.overflow,zIndex:t.zIndex,backgroundColor:t.backgroundColor,transform:t.transform},isVisible:e.width>0&&e.height>0&&"none"!==t.display&&"hidden"!==t.visibility,parentElement:this.container.parentElement?{tagName:this.container.parentElement.tagName,className:this.container.parentElement.className,offsetWidth:this.container.parentElement.offsetWidth,offsetHeight:this.container.parentElement.offsetHeight}:null}}getCytoscapeDebugInfo(){const e=this.cy.extent(),t=this.cy.zoom(),o=this.cy.pan(),n=this.cy.viewport();return{nodeCount:this.cy.nodes().length,edgeCount:this.cy.edges().length,elementCount:this.cy.elements().length,zoom:t,pan:o,extent:e,viewport:n,containerWidth:this.cy.width(),containerHeight:this.cy.height(),isInitialized:void 0!==this.cy.scratch("_cytoscape-initialized"),renderer:this.cy.renderer()?{name:this.cy.renderer().name,options:this.cy.renderer().options}:null}}debugNodePositions(){if(!this.cy||0===this.cy.nodes().length)return void console.log("[HUD-BLANK-SCREEN-DEBUG] 4. No nodes to check positions");console.log("[HUD-BLANK-SCREEN-DEBUG] 4. Node Positions:");const e=this.cy.nodes(),t=this.cy.extent(),o=this.cy.viewport();console.log("[HUD-BLANK-SCREEN-DEBUG] Viewport extent:",t),console.log("[HUD-BLANK-SCREEN-DEBUG] Current viewport:",o),e.forEach((e,t)=>{const o=e.position(),n=e.data(),s=e.boundingBox();console.log(`[HUD-BLANK-SCREEN-DEBUG] Node ${t+1}:`,{id:n.id,label:n.label,position:o,boundingBox:s,isVisible:e.visible(),opacity:e.style("opacity"),width:e.style("width"),height:e.style("height")})})}debugAddContainerBackground(){this.container&&(this.container.style.backgroundColor="#ff000020",this.container.style.border="2px solid #ff0000",this.container.style.minHeight="400px",console.log("[HUD-BLANK-SCREEN-DEBUG] Added red background and border to container for visibility test"))}debugManualRenderingTriggers(){if(this.cy){console.log("[HUD-BLANK-SCREEN-DEBUG] 5. Triggering manual rendering operations...");try{console.log("[HUD-BLANK-SCREEN-DEBUG] - Forcing resize..."),this.cy.resize(),console.log("[HUD-BLANK-SCREEN-DEBUG] - Forcing redraw..."),this.cy.forceRender(),this.cy.nodes().length>0&&(console.log("[HUD-BLANK-SCREEN-DEBUG] - Running layout..."),this.cy.layout(this.layoutConfig).run()),console.log("[HUD-BLANK-SCREEN-DEBUG] - Updating viewport..."),this.cy.viewport({zoom:this.cy.zoom(),pan:this.cy.pan()}),console.log("[HUD-BLANK-SCREEN-DEBUG] Manual rendering triggers completed")}catch(e){console.error("[HUD-BLANK-SCREEN-DEBUG] Error during manual rendering:",e)}}else console.log("[HUD-BLANK-SCREEN-DEBUG] 5. No Cytoscape instance for manual rendering")}debugAddTestNodes(){if(this.cy){console.log("[HUD-BLANK-SCREEN-DEBUG] Adding test nodes...");try{this.cy.elements().remove();const e=[{group:"nodes",data:{id:"test-node-1",label:"🤖 Test Node 1",color:"#48bb78",borderColor:"#38a169",shape:"rectangle",width:120,height:40},classes:"pm-node"},{group:"nodes",data:{id:"test-node-2",label:"🔧 Test Node 2",color:"#4299e1",borderColor:"#3182ce",shape:"diamond",width:80,height:50},classes:"tool-node"},{group:"nodes",data:{id:"test-node-3",label:"📝 Test Node 3",color:"#e53e3e",borderColor:"#c53030",shape:"triangle",width:70,height:40},classes:"todo-node"}],t=[{group:"edges",data:{id:"test-edge-1",source:"test-node-1",target:"test-node-2"}},{group:"edges",data:{id:"test-edge-2",source:"test-node-2",target:"test-node-3"}}];this.cy.add(e),this.cy.add(t),console.log("[HUD-BLANK-SCREEN-DEBUG] Added 3 test nodes and 2 test edges"),e.forEach(e=>{this.nodes.set(e.data.id,e.data)}),this.runLayout()}catch(e){console.error("[HUD-BLANK-SCREEN-DEBUG] Error adding test nodes:",e)}}}debugForceZoomFit(){if(!this.cy)return;console.log("[HUD-BLANK-SCREEN-DEBUG] 7. Forcing zoom fit...");const e=e=>{try{console.log(`[HUD-BLANK-SCREEN-DEBUG] Zoom fit attempt ${e}...`);const t=this.cy.zoom(),o=this.cy.pan(),n=this.cy.elements();if(console.log("[HUD-BLANK-SCREEN-DEBUG] Before fit:",{zoom:t,pan:o,elementCount:n.length}),n.length>0){this.cy.fit(n,50);const e=this.cy.zoom(),s=this.cy.pan();console.log("[HUD-BLANK-SCREEN-DEBUG] After fit:",{zoom:e,pan:s,changed:t!==e||o.x!==s.x||o.y!==s.y}),this.cy.center(n)}else console.log("[HUD-BLANK-SCREEN-DEBUG] No elements to fit")}catch(t){console.error(`[HUD-BLANK-SCREEN-DEBUG] Zoom fit attempt ${e} failed:`,t)}};e(1),setTimeout(()=>e(2),100),setTimeout(()=>e(3),500),setTimeout(()=>e(4),1e3)}debugDrawSimpleShape(){if(!this.cy)return console.log("[HUD-CANVAS-TEST] No Cytoscape instance"),!1;console.log("[HUD-CANVAS-TEST] Testing Cytoscape canvas rendering...");try{return this.cy.elements().remove(),this.cy.add({group:"nodes",data:{id:"canvas-test",label:"✅ CANVAS TEST",color:"#ff0000",borderColor:"#000000",width:200,height:100,shape:"rectangle"},position:{x:200,y:200}}),this.cy.forceRender(),this.cy.fit(this.cy.$("#canvas-test"),50),console.log("[HUD-CANVAS-TEST] Canvas test node added and positioned"),console.log('[HUD-CANVAS-TEST] If you see a red rectangle with "CANVAS TEST", rendering works!'),!0}catch(e){return console.error("[HUD-CANVAS-TEST] Canvas test failed:",e),!1}}darkenColor(e,t){const o=parseInt(e.replace("#",""),16),n=Math.round(2.55*t),s=(o>>16)-n,i=(o>>8&255)-n,r=(255&o)-n;return"#"+(16777216+65536*(s<255?s<1?0:s:255)+256*(i<255?i<1?0:i:255)+(r<255?r<1?0:r:255)).toString(16).slice(1)}};
2
+ //# sourceMappingURL=hud-manager.js.map
@@ -0,0 +1,2 @@
1
+ import"./hud-manager.js";
2
+ //# sourceMappingURL=hud-visualizer.js.map
@@ -0,0 +1,2 @@
1
+ class t{constructor(t){this.container=document.getElementById(t),this.dataContainer=null,this.jsonContainer=null,this.currentEvent=null,this.eventsByClass=new Map,this.globalJsonExpanded="true"===localStorage.getItem("dashboard-json-expanded"),this.keyboardListenerAdded=!1,this.init()}init(){this.setupContainers(),this.setupEventHandlers(),this.showEmptyState()}setupContainers(){this.dataContainer=document.getElementById("module-data-content"),this.jsonContainer=null,this.dataContainer||console.error("Module viewer data container not found")}setupEventHandlers(){document.addEventListener("eventSelected",t=>{this.showEventDetails(t.detail.event)}),document.addEventListener("eventSelectionCleared",()=>{this.showEmptyState()}),document.addEventListener("socketEventUpdate",t=>{this.updateEventsByClass(t.detail.events)})}showEmptyState(){this.dataContainer&&(this.dataContainer.innerHTML='\n <div class="module-empty">\n <p>Click on an event to view structured data</p>\n <p class="module-hint">Data is organized by event type</p>\n </div>\n '),this.currentEvent=null}showEventDetails(t){this.currentEvent=t,this.renderStructuredData(t),this.renderJsonData(t)}renderStructuredData(t){if(!this.dataContainer)return;const e=this.createContextualHeader(t),n=this.createEventStructuredView(t),o=this.createCollapsibleJsonSection(t);this.dataContainer.innerHTML=e+n+o,this.initializeJsonToggle()}renderJsonData(t){}ingest(t){Array.isArray(t)?t.length>0?this.showEventDetails(t[0]):this.showEmptyState():t&&"object"==typeof t?this.showEventDetails(t):this.showEmptyState()}updateEventsByClass(t){this.eventsByClass.clear(),t.forEach(t=>{const e=this.getEventClass(t);this.eventsByClass.has(e)||this.eventsByClass.set(e,[]),this.eventsByClass.get(e).push(t)})}getEventClass(t){if(!t.type)return"unknown";switch(t.type){case"session":return"Session Management";case"claude":return"Claude Interactions";case"agent":return"Agent Operations";case"hook":return"Hook System";case"todo":return"Task Management";case"memory":return"Memory Operations";case"log":return"System Logs";case"connection":return"Connection Events";default:return"Other Events"}}createContextualHeader(t){const e=this.formatTimestamp(t.timestamp),n=t.data||{};let o="";switch(t.type){case"hook":const s=this.extractToolName(n),i=this.extractAgent(t)||"Unknown";if(s)o=`${s}: ${i} ${e}`;else{o=`${this.getHookDisplayName(t,n)}: ${i} ${e}`}break;case"agent":o=`Agent: ${n.agent_type||n.name||"Unknown"} ${e}`;break;case"todo":o=`TodoWrite: ${this.extractAgent(t)||"PM"} ${e}`;break;case"memory":o=`Memory: ${n.operation||"Unknown"} ${e}`;break;case"session":case"claude":case"log":case"connection":o=`Event: ${t.type}.${t.subtype||"default"} ${e}`;break;default:const a=this.extractFileName(n);if(a)o=`File: ${a} ${e}`;else{o=`Event: ${t.type||"Unknown"}.${t.subtype||"default"} ${e}`}}return`\n <div class="contextual-header">\n <h3 class="contextual-header-text">${o}</h3>\n </div>\n `}createEventStructuredView(t){const e=this.getEventClass(t),n=(this.eventsByClass.get(e)||[]).length;let o=`\n <div class="structured-view-section">\n ${this.createEventDetailCard(t.type,t,n)}\n </div>\n `;switch(t.type){case"agent":o+=this.createAgentStructuredView(t);break;case"hook":"Task"===t.data?.tool_name&&t.data?.tool_parameters?.subagent_type?o+=this.createAgentStructuredView(t):o+=this.createHookStructuredView(t);break;case"todo":o+=this.createTodoStructuredView(t);break;case"memory":o+=this.createMemoryStructuredView(t);break;case"claude":o+=this.createClaudeStructuredView(t);break;case"session":o+=this.createSessionStructuredView(t);break;default:o+=this.createGenericStructuredView(t)}return o}createEventDetailCard(t,e,n){const o=new Date(e.timestamp).toLocaleString();return`\n <div class="event-detail-card">\n <div class="event-detail-header">\n <div class="event-detail-title">\n ${this.getEventIcon(t)} ${t||"Unknown"}.${e.subtype||"default"}\n </div>\n <div class="event-detail-time">${o}</div>\n </div>\n <div class="event-detail-content">\n ${this.createProperty("Event ID",e.id||"N/A")}\n ${this.createProperty("Type",`${t}.${e.subtype||"default"}`)}\n ${this.createProperty("Class Events",n)}\n ${e.data&&e.data.session_id?this.createProperty("Session",e.data.session_id):""}\n </div>\n </div>\n `}createAgentStructuredView(t){const e=t.data||{};if("hook"===t.type&&"Task"===e.tool_name&&e.tool_parameters?.subagent_type){const n=e.tool_parameters;return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Agent Type",n.subagent_type)}\n ${this.createProperty("Task Type","Subagent Delegation")}\n ${this.createProperty("Phase",t.subtype||"pre_tool")}\n ${n.description?this.createProperty("Description",n.description):""}\n ${n.prompt?this.createProperty("Prompt Preview",this.truncateText(n.prompt,200)):""}\n ${e.session_id?this.createProperty("Session ID",e.session_id):""}\n ${e.working_directory?this.createProperty("Working Directory",e.working_directory):""}\n </div>\n ${n.prompt?`\n <div class="prompt-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">📝 Task Prompt</h3>\n </div>\n <div class="structured-data">\n <div class="task-prompt" style="white-space: pre-wrap; max-height: 300px; overflow-y: auto; padding: 10px; background: #f8fafc; border-radius: 6px; font-family: monospace; font-size: 12px; line-height: 1.4;">\n ${n.prompt}\n </div>\n </div>\n </div>\n `:""}\n </div>\n `}return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Agent Type",e.agent_type||e.subagent_type||"Unknown")}\n ${this.createProperty("Name",e.name||"N/A")}\n ${this.createProperty("Phase",t.subtype||"N/A")}\n ${e.config?this.createProperty("Config","object"==typeof e.config?Object.keys(e.config).join(", "):String(e.config)):""}\n ${e.capabilities?this.createProperty("Capabilities",e.capabilities.join(", ")):""}\n ${e.result?this.createProperty("Result","object"==typeof e.result?"[Object]":String(e.result)):""}\n </div>\n </div>\n `}createHookStructuredView(t){const e=t.data||{},n=this.extractFilePathFromHook(e),o=this.extractToolInfoFromHook(e),s=this.createInlineToolResultContent(e,t);return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Hook Name",this.getHookDisplayName(t,e))}\n ${this.createProperty("Event Type",e.event_type||t.subtype||"N/A")}\n ${n?this.createProperty("File Path",n):""}\n ${o.tool_name?this.createProperty("Tool",o.tool_name):""}\n ${o.operation_type?this.createProperty("Operation",o.operation_type):""}\n ${e.session_id?this.createProperty("Session ID",e.session_id):""}\n ${e.working_directory?this.createProperty("Working Directory",e.working_directory):""}\n ${e.duration_ms?this.createProperty("Duration",`${e.duration_ms}ms`):""}\n ${s}\n </div>\n </div>\n `}createInlineToolResultContent(t,e=null){const n=t.result_summary,o=e?.subtype||t.event_type||t.phase,s="post_tool"===o||o?.includes("post");if(window.DEBUG_TOOL_RESULTS&&console.log("🔧 createInlineToolResultContent debug:",{hasResultSummary:!!n,eventPhase:o,isPostTool:s,eventSubtype:e?.subtype,dataEventType:t.event_type,dataPhase:t.phase,toolName:t.tool_name,resultSummaryKeys:n?Object.keys(n):[]}),!n)return"";if("pre_tool"===o||o?.includes("pre")&&!o?.includes("post"))return"";let i="";if(n.has_output&&n.output_preview&&(i+=`\n ${this.createProperty("Output",this.truncateText(n.output_preview,200))}\n ${n.output_lines?this.createProperty("Output Lines",n.output_lines):""}\n `),n.has_error&&n.error_preview&&(i+=`\n ${this.createProperty("Error",this.truncateText(n.error_preview,200))}\n `),!n.has_output&&!n.has_error&&Object.keys(n).length>3){i+=Object.entries(n).filter(([t,e])=>!["has_output","has_error","exit_code"].includes(t)&&void 0!==e).map(([t,e])=>this.createProperty(this.formatFieldName(t),String(e))).join("")}return i}createToolResultSection(t,e=null){const n=t.result_summary,o=e?.subtype||t.event_type||t.phase,s="post_tool"===o||o?.includes("post");if(window.DEBUG_TOOL_RESULTS&&console.log("🔧 createToolResultSection debug:",{hasResultSummary:!!n,eventPhase:o,isPostTool:s,eventSubtype:e?.subtype,dataEventType:t.event_type,dataPhase:t.phase,toolName:t.tool_name,resultSummaryKeys:n?Object.keys(n):[]}),!n)return"";if("pre_tool"===o||o?.includes("pre")&&!o?.includes("post"))return"";let i="⏳",a="tool-running",r="Unknown";!0===t.success?(i="✅",a="tool-success",r="Success"):!1===t.success?(i="❌",a="tool-failure",r="Failed"):0===t.exit_code?(i="✅",a="tool-success",r="Completed"):2===t.exit_code?(i="⚠️",a="tool-blocked",r="Blocked"):void 0!==t.exit_code&&0!==t.exit_code&&(i="❌",a="tool-failure",r="Error");let l="";if(l+=`\n <div class="tool-result-status ${a}">\n <span class="tool-result-icon">${i}</span>\n <span class="tool-result-text">${r}</span>\n ${void 0!==t.exit_code?`<span class="tool-exit-code">Exit Code: ${t.exit_code}</span>`:""}\n </div>\n `,n.has_output&&n.output_preview&&(l+=`\n <div class="tool-result-output">\n <div class="tool-result-label">📄 Output:</div>\n <div class="tool-result-preview">\n <pre>${this.escapeHtml(n.output_preview)}</pre>\n </div>\n ${n.output_lines?`<div class="tool-result-meta">Lines: ${n.output_lines}</div>`:""}\n </div>\n `),n.has_error&&n.error_preview&&(l+=`\n <div class="tool-result-error">\n <div class="tool-result-label">⚠️ Error:</div>\n <div class="tool-result-preview error-preview">\n <pre>${this.escapeHtml(n.error_preview)}</pre>\n </div>\n </div>\n `),!n.has_output&&!n.has_error&&Object.keys(n).length>3){const t=Object.entries(n).filter(([t,e])=>!["has_output","has_error","exit_code"].includes(t)&&void 0!==e).map(([t,e])=>this.createProperty(this.formatFieldName(t),String(e))).join("");t&&(l+=`\n <div class="tool-result-other">\n <div class="tool-result-label">📊 Result Details:</div>\n <div class="structured-data">\n ${t}\n </div>\n </div>\n `)}return l.trim()?`\n <div class="tool-result-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">🔧 Tool Result</h3>\n </div>\n <div class="tool-result-content">\n ${l}\n </div>\n </div>\n `:""}isWriteOperation(t,e){if(["Write","Edit","MultiEdit","NotebookEdit"].includes(t))return!0;if(e.tool_parameters){const t=e.tool_parameters;if(t.content||t.new_string||t.edits)return!0;if(t.edit_mode&&"read"!==t.edit_mode)return!0}return!("post_tool"!==e.event_type&&"pre_tool"!==e.event_type||!t||!(t.toLowerCase().includes("write")||t.toLowerCase().includes("edit")||t.toLowerCase().includes("modify")))}isReadOnlyOperation(t){if(!t)return!0;const e=t.toLowerCase();return!!["read"].includes(e)||!["write","edit","multiedit","create","delete","move","copy"].includes(e)}createTodoStructuredView(t){const e=t.data||{};let n="";return e.todos&&Array.isArray(e.todos)&&(n+=`\n <div class="todo-checklist">\n ${e.todos.map(t=>`\n <div class="todo-item todo-${t.status||"pending"}">\n <span class="todo-status">${this.getTodoStatusIcon(t.status)}</span>\n <span class="todo-content">${t.content||"No content"}</span>\n <span class="todo-priority priority-${t.priority||"medium"}">${this.getTodoPriorityIcon(t.priority)}</span>\n </div>\n `).join("")}\n </div>\n `),n}createMemoryStructuredView(t){const e=t.data||{};return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Operation",e.operation||"Unknown")}\n ${this.createProperty("Key",e.key||"N/A")}\n ${e.value?this.createProperty("Value","object"==typeof e.value?"[Object]":String(e.value)):""}\n ${e.namespace?this.createProperty("Namespace",e.namespace):""}\n ${e.metadata?this.createProperty("Metadata","object"==typeof e.metadata?"[Object]":String(e.metadata)):""}\n </div>\n </div>\n `}createClaudeStructuredView(t){const e=t.data||{};return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Type",t.subtype||"N/A")}\n ${e.prompt?this.createProperty("Prompt",this.truncateText(e.prompt,200)):""}\n ${e.message?this.createProperty("Message",this.truncateText(e.message,200)):""}\n ${e.response?this.createProperty("Response",this.truncateText(e.response,200)):""}\n ${e.content?this.createProperty("Content",this.truncateText(e.content,200)):""}\n ${e.tokens?this.createProperty("Tokens",e.tokens):""}\n ${e.model?this.createProperty("Model",e.model):""}\n </div>\n </div>\n `}createSessionStructuredView(t){const e=t.data||{};return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Action",t.subtype||"N/A")}\n ${this.createProperty("Session ID",e.session_id||"N/A")}\n ${e.working_directory?this.createProperty("Working Dir",e.working_directory):""}\n ${e.git_branch?this.createProperty("Git Branch",e.git_branch):""}\n ${e.agent_type?this.createProperty("Agent Type",e.agent_type):""}\n </div>\n </div>\n `}createGenericStructuredView(t){const e=t.data||{},n=Object.keys(e);return 0===n.length?"":`\n <div class="structured-view-section">\n <div class="structured-data">\n ${n.map(t=>this.createProperty(t,"object"==typeof e[t]?"[Object]":String(e[t]))).join("")}\n </div>\n </div>\n `}createCollapsibleJsonSection(t){const e="json-section-"+Math.random().toString(36).substr(2,9),n=this.formatJSON(t),o=this.globalJsonExpanded;return`\n <div class="collapsible-json-section" id="${e}">\n <div class="json-toggle-header"\n onclick="window.moduleViewer.toggleJsonSection()"\n role="button"\n tabindex="0"\n aria-expanded="${o?"true":"false"}"\n onkeydown="if(event.key==='Enter'||event.key===' '){window.moduleViewer.toggleJsonSection();event.preventDefault();}">\n <span class="json-toggle-text">Raw JSON</span>\n <span class="json-toggle-arrow">${o?"▲":"▼"}</span>\n </div>\n <div class="json-content-collapsible" style="display: ${o?"block":"none"};" aria-hidden="${!o}">\n <div class="json-display" onclick="window.moduleViewer.copyJsonToClipboard(event)">\n <pre>${n}</pre>\n </div>\n </div>\n </div>\n `}async copyJsonToClipboard(t){const e=t.currentTarget.getBoundingClientRect(),n=t.clientX-e.left,o=t.clientY-e.top;if(n>e.width-50&&o<30){const e=t.currentTarget.querySelector("pre");if(e)try{await navigator.clipboard.writeText(e.textContent),this.showNotification("JSON copied to clipboard","success")}catch(s){console.error("Failed to copy JSON:",s),this.showNotification("Failed to copy JSON","error")}t.stopPropagation()}}initializeJsonToggle(){window.moduleViewer=this,this.globalJsonExpanded&&setTimeout(()=>{this.updateAllJsonSections()},0),this.keyboardListenerAdded||(this.keyboardListenerAdded=!0,document.addEventListener("keydown",t=>{t.target.classList.contains("json-toggle-header")&&("Enter"!==t.key&&" "!==t.key||(this.toggleJsonSection(),t.preventDefault()))}))}toggleJsonSection(){this.globalJsonExpanded=!this.globalJsonExpanded,localStorage.setItem("dashboard-json-expanded",this.globalJsonExpanded.toString()),this.updateAllJsonSections(),document.dispatchEvent(new CustomEvent("jsonToggleChanged",{detail:{expanded:this.globalJsonExpanded}}))}updateAllJsonSections(){const t=document.querySelectorAll(".json-content-collapsible"),e=document.querySelectorAll(".json-toggle-arrow"),n=document.querySelectorAll(".json-toggle-header");t.forEach((t,o)=>{this.globalJsonExpanded?(t.style.display="block",t.setAttribute("aria-hidden","false"),e[o]&&(e[o].textContent="▲"),n[o]&&n[o].setAttribute("aria-expanded","true")):(t.style.display="none",t.setAttribute("aria-hidden","true"),e[o]&&(e[o].textContent="▼"),n[o]&&n[o].setAttribute("aria-expanded","false"))}),this.globalJsonExpanded&&t.length>0&&setTimeout(()=>{const e=t[0];e&&e.scrollIntoView({behavior:"smooth",block:"nearest"})},100)}createProperty(t,e){const n=this.truncateText(String(e),300);return this.isFilePathProperty(t,e)?`\n <div class="event-property">\n <span class="event-property-key">${t}:</span>\n <span class="event-property-value">\n ${this.createClickableFilePath(e)}\n </span>\n </div>\n `:`\n <div class="event-property">\n <span class="event-property-key">${t}:</span>\n <span class="event-property-value">${n}</span>\n </div>\n `}isFilePathProperty(t,e){if(["File Path","file_path","notebook_path","Full Path","Working Directory","working_directory"].some(e=>t.toLowerCase().includes(e.toLowerCase()))){const t=String(e);return t.length>0&&(t.includes("/")||t.includes("\\"))&&t.length<500}return!1}createClickableFilePath(t){const e=this.truncateText(String(t),300);return`\n <span class="clickable-file-path"\n onclick="showFileViewerModal('${t.replace(/'/g,"\\'")}')"\n title="Click to view file contents with syntax highlighting&#10;Path: ${t}">\n ${e}\n </span>\n `}getEventIcon(t){const e={session:"📱",claude:"🤖",agent:"🎯",hook:"🔗",todo:"✅",memory:"🧠",log:"📝",connection:"🔌",unknown:"❓"};return e[t]||e.unknown}getTodoStatusIcon(t){const e={completed:"✅",in_progress:"🔄",pending:"⏳",cancelled:"❌"};return e[t]||e.pending}getTodoPriorityIcon(t){const e={high:"🔴",medium:"🟡",low:"🟢"};return e[t]||e.medium}getHookDisplayName(t,e){if(e.hook_name)return e.hook_name;if(e.name)return e.name;const n=t.subtype||e.event_type,o={user_prompt:"User Prompt",pre_tool:"Tool Execution (Pre)",post_tool:"Tool Execution (Post)",notification:"Notification",stop:"Session Stop",subagent_stop:"Subagent Stop"};if(o[n])return o[n];if("string"==typeof t.type&&t.type.startsWith("hook.")){const e=t.type.replace("hook.","");if(o[e])return o[e]}return n?n.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" "):"Unknown Hook"}extractFilePathFromHook(t){return t.tool_parameters&&t.tool_parameters.file_path?t.tool_parameters.file_path:t.file_path?t.file_path:t.tool_input&&t.tool_input.file_path?t.tool_input.file_path:t.tool_parameters&&t.tool_parameters.notebook_path?t.tool_parameters.notebook_path:null}extractToolInfoFromHook(t){return{tool_name:t.tool_name||t.tool_parameters&&t.tool_parameters.tool_name,operation_type:t.operation_type||t.tool_parameters&&t.tool_parameters.operation_type}}truncateText(t,e){return!t||t.length<=e?t:t.substring(0,e)+"..."}formatJSON(t){try{return JSON.stringify(t,null,2)}catch(e){return String(t)}}formatTimestamp(t){if(!t)return"Unknown time";try{return new Date(t).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit",hour12:!0})}catch(e){return"Invalid time"}}escapeHtml(t){if(!t)return"";const e=document.createElement("div");return e.textContent=t,e.innerHTML}formatFieldName(t){return t.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}extractToolName(t){if(t.tool_name)return t.tool_name;if(t.tool_parameters&&t.tool_parameters.tool_name)return t.tool_parameters.tool_name;if(t.tool_input&&t.tool_input.tool_name)return t.tool_input.tool_name;if(t.tool_parameters){if(t.tool_parameters.file_path||t.tool_parameters.notebook_path)return"FileOperation";if(t.tool_parameters.pattern)return"Search";if(t.tool_parameters.command)return"Bash";if(t.tool_parameters.todos)return"TodoWrite"}return null}extractAgent(t){if(t._agentName&&"Unknown Agent"!==t._agentName)return t._agentName;if(t._inference&&t._inference.agentName&&"Unknown"!==t._inference.agentName)return t._inference.agentName;if(t.agent)return t.agent;if(t.agent_type)return t.agent_type;if(t.agent_name)return t.agent_name;if(t.session_id&&"string"==typeof t.session_id){const e=t.session_id.split("_");if(e.length>1)return e[0].toUpperCase()}return t.todos||"TodoWrite"===t.tool_name?"PM":null}extractFileName(t){const e=this.extractFilePathFromHook(t);if(e){const t=e.split("/");return t[t.length-1]}return t.filename?t.filename:t.file?t.file:null}clear(){this.showEmptyState()}showToolCall(t,e){if(!t)return void this.showEmptyState();const n=t.tool_name||"Unknown Tool",o=t.agent_type||"PM",s=this.formatTimestamp(t.timestamp),i=t.pre_event,a=t.post_event,r=i?.tool_parameters||{},l=i?this.extractToolTarget(n,r):"Unknown target",c=t.duration_ms?`${t.duration_ms}ms`:"-",d=void 0!==t.success?t.success:null;void 0!==t.exit_code&&t.exit_code;let p=t.result_summary||"No summary available";if("object"==typeof p&&null!==p){const t=[];void 0!==p.exit_code&&t.push(`Exit Code: ${p.exit_code}`),void 0!==p.has_output&&t.push("Has Output: "+(p.has_output?"Yes":"No")),void 0!==p.has_error&&t.push("Has Error: "+(p.has_error?"Yes":"No")),void 0!==p.output_lines&&t.push(`Output Lines: ${p.output_lines}`),p.output_preview&&t.push(`Output Preview: ${p.output_preview}`),p.error_preview&&t.push(`Error Preview: ${p.error_preview}`)}let u="⏳",h="Running...",m="tool-running";a&&(!0===d?(u="✅",h="Success",m="tool-success"):!1===d?(u="❌",h="Failed",m="tool-failure"):(u="⏳",h="Completed",m="tool-completed"));const g=`\n <div class="contextual-header">\n <h3 class="contextual-header-text">${n}: ${o} ${s}</h3>\n </div>\n `;if("TodoWrite"===n&&r.todos){const e=`\n <div class="todo-checklist">\n ${r.todos.map(t=>{const e=this.getTodoStatusIcon(t.status),n=this.getTodoPriorityIcon(t.priority);return`\n <div class="todo-item todo-${t.status||"pending"}">\n <span class="todo-status">${e}</span>\n <span class="todo-content">${t.content||"No content"}</span>\n <span class="todo-priority priority-${t.priority||"medium"}">${n}</span>\n </div>\n `}).join("")}\n </div>\n `,n={toolCall:t,preEvent:i,postEvent:a},o=this.createCollapsibleJsonSection(n);this.dataContainer&&(this.dataContainer.innerHTML=g+e+o),this.initializeJsonToggle()}else{const e=`\n <div class="structured-view-section">\n <div class="tool-call-details">\n <div class="tool-call-info ${m}">\n <div class="structured-field">\n <strong>Tool Name:</strong> ${n}\n </div>\n <div class="structured-field">\n <strong>Agent:</strong> ${o}\n </div>\n <div class="structured-field">\n <strong>Status:</strong> ${u} ${h}\n </div>\n <div class="structured-field">\n <strong>Target:</strong> ${l}\n </div>\n <div class="structured-field">\n <strong>Started:</strong> ${new Date(t.timestamp).toLocaleString()}\n </div>\n ${c&&"-"!==c?`\n <div class="structured-field">\n <strong>Duration:</strong> ${c}\n </div>\n `:""}\n ${t.session_id?`\n <div class="structured-field">\n <strong>Session ID:</strong> ${t.session_id}\n </div>\n `:""}\n </div>\n\n ${this.createToolResultFromToolCall(t)}\n </div>\n </div>\n `,s={toolCall:t,preEvent:i,postEvent:a},r=this.createCollapsibleJsonSection(s);this.dataContainer&&(this.dataContainer.innerHTML=g+e+r),this.initializeJsonToggle()}}showFileOperations(t,e){if(!t||!e)return void this.showEmptyState();const n=e.split("/").pop()||e,o=t.operations||[],s=o[o.length-1],i=`\n <div class="contextual-header">\n <h3 class="contextual-header-text">File: ${n} ${s?this.formatTimestamp(s.timestamp):""}</h3>\n </div>\n `,a=`\n <div class="structured-view-section">\n <div class="file-details">\n <div class="file-path-display">\n <strong>Full Path:</strong> ${this.createClickableFilePath(e)}\n <div id="git-track-status-${e.replace(/[^a-zA-Z0-9]/g,"-")}" class="git-track-status" style="margin-top: 8px;">\n \x3c!-- Git tracking status will be populated here --\x3e\n </div>\n </div>\n <div class="operations-list">\n ${o.map(t=>`\n <div class="operation-item">\n <div class="operation-header">\n <span class="operation-icon">${this.getOperationIcon(t.operation)}</span>\n <span class="operation-type">${t.operation}</span>\n <span class="operation-timestamp">${new Date(t.timestamp).toLocaleString()}</span>\n ${this.isReadOnlyOperation(t.operation)?`\n \x3c!-- Read-only operation: show only file viewer --\x3e\n <span class="file-viewer-icon"\n onclick="showFileViewerModal('${e}')"\n title="View file contents with syntax highlighting"\n style="margin-left: 8px; cursor: pointer; font-size: 16px;">\n 👁️\n </span>\n `:`\n \x3c!-- Edit operation: show both file viewer and git diff --\x3e\n <span class="file-viewer-icon"\n onclick="showFileViewerModal('${e}')"\n title="View file contents with syntax highlighting"\n style="margin-left: 8px; cursor: pointer; font-size: 16px;">\n 👁️\n </span>\n <span class="git-diff-icon"\n onclick="showGitDiffModal('${e}', '${t.timestamp}')"\n title="View git diff for this file operation"\n style="margin-left: 8px; cursor: pointer; font-size: 16px; display: none;"\n data-file-path="${e}"\n data-operation-timestamp="${t.timestamp}">\n 📋\n </span>\n `}\n </div>\n <div class="operation-details">\n <strong>Agent:</strong> ${t.agent}<br>\n <strong>Session:</strong> ${t.sessionId?t.sessionId.substring(0,8)+"...":"Unknown"}\n ${t.details?`<br><strong>Details:</strong> ${t.details}`:""}\n </div>\n </div>\n `).join("")}\n </div>\n </div>\n </div>\n `;this.checkAndShowTrackControl(e),this.checkAndShowGitDiffIcons(e);const r=this.createCollapsibleJsonSection(t);this.dataContainer&&(this.dataContainer.innerHTML=i+a+r),this.initializeJsonToggle()}showErrorMessage(t,e){const n=`\n <div class="module-error">\n <div class="error-header">\n <h3>❌ ${t}</h3>\n </div>\n <div class="error-message">\n <p>${e}</p>\n </div>\n </div>\n `,o={title:t,message:e},s=this.createCollapsibleJsonSection(o);this.dataContainer&&(this.dataContainer.innerHTML=n+s),this.initializeJsonToggle()}showAgentEvent(t,e){this.showAgentSpecificDetails(t,e)}showAgentSpecificDetails(t,e){if(!t)return void this.showEmptyState();const n=window.dashboard?.agentInference,o=window.dashboard?.eventViewer;if(!n||!o)return console.warn("AgentInference or EventViewer not available, falling back to single event view"),void this.showEventDetails(t);const s=n.getInferredAgentForEvent(t),i=s?.agentName||this.extractAgent(t)||"Unknown",a=o.events||[],r=this.getAgentSpecificEvents(a,i,n);console.log(`Showing details for agent: ${i}, found ${r.length} related events`);const l=this.extractAgentSpecificData(i,r);this.renderAgentSpecificView(i,l,t)}getAgentSpecificEvents(t,e,n){return t.filter(t=>{const o=n.getInferredAgentForEvent(t);return(o?.agentName||this.extractAgent(t)||"Unknown").toLowerCase()===e.toLowerCase()})}extractAgentSpecificData(t,e){const n={agentName:t,totalEvents:e.length,prompt:null,todos:[],toolsCalled:[],sessions:new Set,firstSeen:null,lastSeen:null,eventTypes:new Set};return e.forEach(e=>{const o=e.data||{},s=new Date(e.timestamp);(!n.firstSeen||s<n.firstSeen)&&(n.firstSeen=s),(!n.lastSeen||s>n.lastSeen)&&(n.lastSeen=s),(e.session_id||o.session_id)&&n.sessions.add(e.session_id||o.session_id);const i=e.hook_event_name||e.type||"unknown";if(n.eventTypes.add(i),"hook"===e.type&&"Task"===o.tool_name&&o.tool_parameters){const e=o.tool_parameters;e.prompt&&!n.prompt&&(n.prompt=e.prompt),e.description&&!n.description&&(n.description=e.description),e.subagent_type===t&&e.prompt&&(n.prompt=e.prompt)}if(!o.prompt||o.agent_type!==t&&o.subagent_type!==t||(n.prompt=o.prompt),"todo"===e.type||"hook"===e.type&&"TodoWrite"===o.tool_name){const t=o.todos||o.tool_parameters?.todos;t&&Array.isArray(t)&&t.forEach(t=>{const e=n.todos.findIndex(e=>e.id===t.id||e.content===t.content);e>=0?n.todos[e]={...n.todos[e],...t,timestamp:s}:n.todos.push({...t,timestamp:s})})}if("hook"===e.type&&o.tool_name){const t=e.subtype||o.event_type,i=this.generateToolCallId(o.tool_name,o.tool_parameters,s);"pre_tool"===t?(n._preToolEvents||(n._preToolEvents=new Map),n._preToolEvents.set(i,{toolName:o.tool_name,timestamp:s,target:this.extractToolTarget(o.tool_name,o.tool_parameters,null),parameters:o.tool_parameters})):"post_tool"===t&&(n._postToolEvents||(n._postToolEvents=new Map),n._postToolEvents.set(i,{toolName:o.tool_name,timestamp:s,success:o.success,duration:o.duration_ms,resultSummary:o.result_summary,exitCode:o.exit_code}))}}),n.todos.sort((t,e)=>(e.timestamp||0)-(t.timestamp||0)),n.toolsCalled=this.consolidateToolCalls(n._preToolEvents,n._postToolEvents),delete n._preToolEvents,delete n._postToolEvents,n.toolsCalled.sort((t,e)=>e.timestamp-t.timestamp),n}generateToolCallId(t,e,n){const o=Math.floor(n.getTime()/5e3);let s="";if(e){const t=[];e.file_path&&t.push(e.file_path),e.command&&t.push(e.command.substring(0,50)),e.pattern&&t.push(e.pattern),e.subagent_type&&t.push(e.subagent_type),e.notebook_path&&t.push(e.notebook_path),e.url&&t.push(e.url),e.prompt&&t.push(e.prompt.substring(0,30)),s=t.join("|")}return s||(s="default"),`${t}:${o}:${s}`}consolidateToolCalls(t,e){const n=[],o=new Set;t||(t=new Map),e||(e=new Map);for(const[s,i]of t){if(o.has(s))continue;const t=e.get(s),a={toolName:i.toolName,timestamp:i.timestamp,target:i.target,parameters:i.parameters,status:this.determineToolCallStatus(i,t),statusIcon:this.getToolCallStatusIcon(i,t),phase:t?"completed":"running"};t&&(a.success=t.success,a.duration=t.duration,a.resultSummary=t.resultSummary,a.exitCode=t.exitCode,a.completedAt=t.timestamp),n.push(a),o.add(s)}for(const[s,i]of e){if(o.has(s))continue;const t={toolName:i.toolName,timestamp:i.timestamp,target:"Unknown target",parameters:null,status:this.determineToolCallStatus(null,i),statusIcon:this.getToolCallStatusIcon(null,i),phase:"completed",success:i.success,duration:i.duration,resultSummary:i.resultSummary,exitCode:i.exitCode,completedAt:i.timestamp};n.push(t),o.add(s)}return n}determineToolCallStatus(t,e){return e?!0===e.success?"Success":!1===e.success?"Failed":0===e.exitCode?"Completed":2===e.exitCode?"Blocked":void 0!==e.exitCode&&0!==e.exitCode?"Error":"Completed":"Running..."}getToolCallStatusIcon(t,e){return e?!0===e.success?"✅":!1===e.success?"❌":0===e.exitCode?"✅":2===e.exitCode?"⚠️":void 0!==e.exitCode&&0!==e.exitCode?"❌":"✅":"⏳"}estimateTokenCount(t){if(!t||"string"!=typeof t)return 0;const e=t.trim().split(/\s+/).length,n=Math.ceil(t.length/4);return Math.max(1.3*e,n)}trimPromptWhitespace(t){return t&&"string"==typeof t?t=(t=(t=t.trim()).replace(/\n\s*\n\s*\n+/g,"\n\n")).split("\n").map(t=>t.replace(/\s+$/,"")).join("\n"):""}renderAgentSpecificView(t,e,n){const o=this.formatTimestamp(n.timestamp),s=`\n <div class="contextual-header">\n <h3 class="contextual-header-text">🤖 ${t} Agent Details ${o}</h3>\n </div>\n `;let i=`\n <div class="agent-overview-section">\n <div class="structured-data">\n ${this.createProperty("Agent Name",t)}\n ${this.createProperty("Total Events",e.totalEvents)}\n ${this.createProperty("Active Sessions",e.sessions.size)}\n ${this.createProperty("Event Types",Array.from(e.eventTypes).join(", "))}\n ${e.firstSeen?this.createProperty("First Seen",e.firstSeen.toLocaleString()):""}\n ${e.lastSeen?this.createProperty("Last Seen",e.lastSeen.toLocaleString()):""}\n </div>\n </div>\n `;if(e.prompt){const t=this.trimPromptWhitespace(e.prompt);i+=`\n <div class="agent-prompt-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">📝 Agent Task Prompt</h3>\n <div class="prompt-stats" style="font-size: 11px; color: #64748b; margin-top: 4px;">\n ~${Math.round(this.estimateTokenCount(t))} tokens • ${t.trim().split(/\s+/).length} words • ${t.length} characters\n </div>\n </div>\n <div class="structured-data">\n <div class="agent-prompt" style="white-space: pre-wrap; max-height: 300px; overflow-y: auto; padding: 10px; background: #f8fafc; border-radius: 6px; font-family: monospace; font-size: 12px; line-height: 1.4; border: 1px solid #e2e8f0;">\n ${this.escapeHtml(t)}\n </div>\n </div>\n </div>\n `}e.todos.length>0&&(i+=`\n <div class="agent-todos-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">✅ Agent Todo List (${e.todos.length} items)</h3>\n </div>\n <div class="todo-checklist">\n ${e.todos.map(t=>`\n <div class="todo-item todo-${t.status||"pending"}">\n <span class="todo-status">${this.getTodoStatusIcon(t.status)}</span>\n <span class="todo-content">${t.content||"No content"}</span>\n <span class="todo-priority priority-${t.priority||"medium"}">${this.getTodoPriorityIcon(t.priority)}</span>\n ${t.timestamp?`<span class="todo-timestamp">${new Date(t.timestamp).toLocaleTimeString()}</span>`:""}\n </div>\n `).join("")}\n </div>\n </div>\n `),e.toolsCalled.length>0&&(i+=`\n <div class="agent-tools-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">🔧 Tools Called by Agent (${e.toolsCalled.length} calls)</h3>\n </div>\n <div class="tools-list">\n ${e.toolsCalled.map(e=>{let n="";return"✅"===e.statusIcon?n="status-success":"❌"===e.statusIcon?n="status-failed":"⚠️"===e.statusIcon?n="status-blocked":"⏳"===e.statusIcon&&(n="status-running"),`\n <div class="tool-call-item">\n <div class="tool-call-header">\n <div style="display: flex; align-items: center; gap: 12px; flex: 1;">\n <span class="tool-name">🔧 ${e.toolName}</span>\n <span class="tool-agent">${t}</span>\n <span class="tool-status-indicator ${n}">${e.statusIcon} ${e.status}</span>\n </div>\n <span class="tool-timestamp" style="margin-left: auto;">${e.timestamp.toLocaleTimeString()}</span>\n </div>\n <div class="tool-call-details">\n ${e.target?`<span class="tool-target">Target: ${e.target}</span>`:""}\n ${e.duration?`<span class="tool-duration">Duration: ${e.duration}ms</span>`:""}\n ${e.completedAt&&e.completedAt!==e.timestamp?`<span class="tool-completed">Completed: ${e.completedAt.toLocaleTimeString()}</span>`:""}\n </div>\n </div>\n `}).join("")}\n </div>\n </div>\n `);const a={agentName:t,agentData:e,originalEvent:n},r=this.createCollapsibleJsonSection(a);this.dataContainer&&(this.dataContainer.innerHTML=s+i+r),this.initializeJsonToggle()}createToolResultFromToolCall(t){if(!t.result_summary)return"";const e={event_type:"post_tool",result_summary:t.result_summary,success:t.success,exit_code:t.exit_code},n=this.createInlineToolResultContent(e,{subtype:"post_tool"});return n.trim()?`\n <div class="tool-result-inline">\n <div class="structured-data">\n ${n}\n </div>\n </div>\n `:""}extractToolTarget(t,e,n){const o=e||n||{};switch(t?.toLowerCase()){case"write":case"read":case"edit":case"multiedit":return o.file_path||"Unknown file";case"bash":return o.command?`${o.command.substring(0,50)}${o.command.length>50?"...":""}`:"Unknown command";case"grep":return o.pattern?`Pattern: ${o.pattern}`:"Unknown pattern";case"glob":return o.pattern?`Pattern: ${o.pattern}`:"Unknown glob";case"todowrite":return`${o.todos?.length||0} todos`;case"task":return o.subagent_type||o.agent_type||"Subagent delegation";default:return o.file_path?o.file_path:o.pattern?`Pattern: ${o.pattern}`:o.command?`Command: ${o.command.substring(0,30)}...`:o.path?o.path:"Unknown target"}}getOperationIcon(t){return{read:"👁️",write:"✏️",edit:"📝",multiedit:"📝",create:"🆕",delete:"🗑️",move:"📦",copy:"📋"}[t?.toLowerCase()]||"📄"}getCurrentEvent(){return this.currentEvent}async checkAndShowTrackControl(t){if(t)try{const e=window.socket||window.dashboard?.socketClient?.socket;if(!e)return void console.warn("No socket connection available for git tracking check");let n=window.dashboard?.currentWorkingDir;if(!n||"Unknown"===n||""===n.trim()){const t=document.getElementById("footer-working-dir");n=t?.textContent?.trim()&&"Unknown"!==t.textContent.trim()?t.textContent.trim():".",console.log("[MODULE-VIEWER-DEBUG] Working directory fallback used:",n)}const o=new Promise((n,o)=>{const s=o=>{o.file_path===t&&(e.off("file_tracked_response",s),n(o))};e.on("file_tracked_response",s),setTimeout(()=>{e.off("file_tracked_response",s),o(new Error("Request timeout"))},5e3)});e.emit("check_file_tracked",{file_path:t,working_dir:n});const s=await o;this.displayTrackingStatus(t,s)}catch(e){console.error("Error checking file tracking status:",e),this.displayTrackingStatus(t,{success:!1,error:e.message,file_path:t})}}displayTrackingStatus(t,e){const n=`git-track-status-${t.replace(/[^a-zA-Z0-9]/g,"-")}`,o=document.getElementById(n);o&&(e.success&&!1===e.is_tracked?o.innerHTML=`\n <div class="untracked-file-notice">\n <span class="untracked-icon">⚠️</span>\n <span class="untracked-text">This file is not tracked by git</span>\n <button class="track-file-button"\n onclick="window.moduleViewer.trackFile('${t}')"\n title="Add this file to git tracking">\n <span class="git-icon">📁</span> Track File\n </button>\n </div>\n `:e.success&&!0===e.is_tracked?o.innerHTML='\n <div class="tracked-file-notice">\n <span class="tracked-icon">✅</span>\n <span class="tracked-text">This file is tracked by git</span>\n </div>\n ':e.success||(o.innerHTML=`\n <div class="tracking-error-notice">\n <span class="error-icon">❌</span>\n <span class="error-text">Could not check git status: ${e.error||"Unknown error"}</span>\n </div>\n `))}async trackFile(t){if(t)try{const e=window.socket||window.dashboard?.socketClient?.socket;if(!e)return void console.warn("No socket connection available for git add");let n=window.dashboard?.currentWorkingDir;if(!n||"Unknown"===n||""===n.trim()){const t=document.getElementById("footer-working-dir");n=t?.textContent?.trim()&&"Unknown"!==t.textContent.trim()?t.textContent.trim():".",console.log("[MODULE-VIEWER-DEBUG] Working directory fallback used:",n)}const o=`git-track-status-${t.replace(/[^a-zA-Z0-9]/g,"-")}`,s=document.getElementById(o);s&&(s.innerHTML='\n <div class="tracking-file-notice">\n <span class="loading-icon">⏳</span>\n <span class="loading-text">Adding file to git tracking...</span>\n </div>\n ');const i=new Promise((n,o)=>{const s=o=>{o.file_path===t&&(e.off("git_add_response",s),n(o))};e.on("git_add_response",s),setTimeout(()=>{e.off("git_add_response",s),o(new Error("Request timeout"))},1e4)});e.emit("git_add_file",{file_path:t,working_dir:n}),console.log("📁 Git add request sent:",{filePath:t,workingDir:n});const a=await i;console.log("📦 Git add result:",a),a.success?(s&&(s.innerHTML='\n <div class="tracked-file-notice">\n <span class="tracked-icon">✅</span>\n <span class="tracked-text">File successfully added to git tracking</span>\n </div>\n '),this.showNotification("File tracked successfully","success")):(s&&(s.innerHTML=`\n <div class="tracking-error-notice">\n <span class="error-icon">❌</span>\n <span class="error-text">Failed to track file: ${a.error||"Unknown error"}</span>\n <button class="track-file-button"\n onclick="window.moduleViewer.trackFile('${t}')"\n title="Try again">\n <span class="git-icon">📁</span> Retry\n </button>\n </div>\n `),this.showNotification(`Failed to track file: ${a.error}`,"error"))}catch(e){console.error("❌ Failed to track file:",e);const n=`git-track-status-${t.replace(/[^a-zA-Z0-9]/g,"-")}`,o=document.getElementById(n);o&&(o.innerHTML=`\n <div class="tracking-error-notice">\n <span class="error-icon">❌</span>\n <span class="error-text">Error: ${e.message}</span>\n <button class="track-file-button"\n onclick="window.moduleViewer.trackFile('${t}')"\n title="Try again">\n <span class="git-icon">📁</span> Retry\n </button>\n </div>\n `),this.showNotification(`Error tracking file: ${e.message}`,"error")}}async checkAndShowGitDiffIcons(t){if(t){console.debug("[GIT-DIFF-ICONS] Checking git diff icons for file:",t);try{const e=window.socket||window.dashboard?.socketClient?.socket;if(!e)return void console.warn("[GIT-DIFF-ICONS] No socket connection available for git status check");console.debug("[GIT-DIFF-ICONS] Socket connection available, proceeding");let n=window.dashboard?.currentWorkingDir;if(n&&"Unknown"!==n&&""!==n.trim())console.debug("[GIT-DIFF-ICONS] Using working directory:",n);else{const t=document.getElementById("footer-working-dir");n=t?.textContent?.trim()&&"Unknown"!==t.textContent.trim()?t.textContent.trim():".",console.log("[GIT-DIFF-ICONS] Working directory fallback used:",n)}const o=new Promise((n,o)=>{const s=o=>{console.debug("[GIT-DIFF-ICONS] Received git status response:",o),o.file_path===t?(e.off("git_status_response",s),n(o)):console.debug("[GIT-DIFF-ICONS] Response for different file, ignoring:",o.file_path)};e.on("git_status_response",s),setTimeout(()=>{e.off("git_status_response",s),console.warn("[GIT-DIFF-ICONS] Timeout waiting for git status response"),o(new Error("Request timeout"))},3e3)});console.debug("[GIT-DIFF-ICONS] Sending check_git_status event"),e.emit("check_git_status",{file_path:t,working_dir:n});const s=await o;console.debug("[GIT-DIFF-ICONS] Git status check result:",s),s.success?(console.debug("[GIT-DIFF-ICONS] Git status check successful, showing icons for:",t),this.showGitDiffIconsForFile(t)):console.debug("[GIT-DIFF-ICONS] Git status check failed, icons will remain hidden:",s.error)}catch(e){console.warn("[GIT-DIFF-ICONS] Git status check failed, hiding git diff icons:",e.message)}}else console.debug("[GIT-DIFF-ICONS] No filePath provided, skipping git diff icon check")}showGitDiffIconsForFile(t){console.debug("[GIT-DIFF-ICONS] Showing git diff icons for file:",t);const e=document.querySelectorAll(`[data-file-path="${t}"]`);console.debug("[GIT-DIFF-ICONS] Found",e.length,"elements with matching file path");let n=0;e.forEach((t,e)=>{console.debug("[GIT-DIFF-ICONS] Processing element",e,":",t),console.debug("[GIT-DIFF-ICONS] Element classes:",t.classList.toString()),t.classList.contains("git-diff-icon")?(console.debug("[GIT-DIFF-ICONS] Setting display to inline for git-diff-icon"),t.style.display="inline",n++):console.debug("[GIT-DIFF-ICONS] Element is not a git-diff-icon, skipping")}),console.debug("[GIT-DIFF-ICONS] Showed",n,"git diff icons for file:",t)}showNotification(t,e="info"){const n=document.createElement("div");n.className=`notification notification-${e}`,n.innerHTML=`\n <span class="notification-icon">${"success"===e?"✅":"error"===e?"❌":"ℹ️"}</span>\n <span class="notification-message">${t}</span>\n `,n.style.cssText=`\n position: fixed;\n top: 20px;\n right: 20px;\n background: ${"success"===e?"#d4edda":"error"===e?"#f8d7da":"#d1ecf1"};\n color: ${"success"===e?"#155724":"error"===e?"#721c24":"#0c5460"};\n border: 1px solid ${"success"===e?"#c3e6cb":"error"===e?"#f5c6cb":"#bee5eb"};\n border-radius: 6px;\n padding: 12px 16px;\n font-size: 14px;\n font-weight: 500;\n z-index: 2000;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n display: flex;\n align-items: center;\n gap: 8px;\n max-width: 400px;\n animation: slideIn 0.3s ease-out;\n `;const o=document.createElement("style");o.textContent="\n @keyframes slideIn {\n from { transform: translateX(100%); opacity: 0; }\n to { transform: translateX(0); opacity: 1; }\n }\n @keyframes slideOut {\n from { transform: translateX(0); opacity: 1; }\n to { transform: translateX(100%); opacity: 0; }\n }\n ",document.head.appendChild(o),document.body.appendChild(n),setTimeout(()=>{n.style.animation="slideOut 0.3s ease-in",setTimeout(()=>{n.parentNode&&n.parentNode.removeChild(n),o.parentNode&&o.parentNode.removeChild(o)},300)},5e3)}showAgentInstance(t){if(!t)return void this.showEmptyState();const e={type:"pm_delegation",subtype:t.agentName,agent_type:t.agentName,timestamp:t.timestamp,session_id:t.sessionId,metadata:{delegation_type:"explicit",event_count:t.agentEvents.length,pm_call:t.pmCall||null,agent_events:t.agentEvents}};console.log("Showing PM delegation details:",t),this.showAgentSpecificDetails(e,0)}showImpliedAgent(t){if(!t)return void this.showEmptyState();const e={type:"implied_delegation",subtype:t.agentName,agent_type:t.agentName,timestamp:t.timestamp,session_id:t.sessionId,metadata:{delegation_type:"implied",event_count:t.eventCount,pm_call:null,note:"No explicit PM call found - inferred from agent activity"}};console.log("Showing implied agent details:",t),this.showAgentSpecificDetails(e,0)}}window.ModuleViewer=t,window.enableToolResultDebugging=function(){window.DEBUG_TOOL_RESULTS=!0,console.log("🔧 Tool result debugging enabled. Click on tool events to see debug info.")},window.disableToolResultDebugging=function(){window.DEBUG_TOOL_RESULTS=!1,console.log("🔧 Tool result debugging disabled.")};export{t as M};
2
+ //# sourceMappingURL=module-viewer.js.map
@@ -0,0 +1,2 @@
1
+ class e{constructor(e){this.socketClient=e,this.sessions=new Map,this.currentSessionId=null,this.selectedSessionId="",this.init()}init(){this.setupEventHandlers(),this.setupSocketListeners(),this.updateSessionSelect()}setupEventHandlers(){const e=document.getElementById("session-select");e&&e.addEventListener("change",e=>{this.selectedSessionId=e.target.value,this.onSessionFilterChanged(),window.dashboard&&window.dashboard.loadWorkingDirectoryForSession&&window.dashboard.loadWorkingDirectoryForSession(e.target.value)});const s=document.querySelector('button[onclick="refreshSessions()"]');s&&s.addEventListener("click",()=>{this.refreshSessions()})}setupSocketListeners(){this.socketClient.onEventUpdate((e,s)=>{this.sessions=s,this.updateSessionSelect(),this.updateFooterInfo()}),document.addEventListener("socketConnectionStatus",e=>{"connected"===e.detail.type&&setTimeout(()=>this.refreshSessions(),1e3)})}updateSessionSelect(){const e=document.getElementById("session-select");if(!e)return;const s=e.value;if(e.innerHTML='\n <option value="">All Sessions</option>\n ',this.sessions&&this.sessions.size>0){Array.from(this.sessions.values()).sort((e,s)=>new Date(s.lastActivity||s.startTime)-new Date(e.lastActivity||e.startTime)).forEach(s=>{const t=document.createElement("option");t.value=s.id;const n=new Date(s.startTime||s.last_activity).toLocaleString(),o=s.eventCount||s.event_count||0,i=s.id===this.currentSessionId;t.textContent=`${s.id.substring(0,8)}... (${o} events, ${n})${i?" [ACTIVE]":""}`,e.appendChild(t)})}s&&Array.from(e.options).some(e=>e.value===s)?(e.value=s,this.selectedSessionId=s,this.onSessionFilterChanged()):(this.selectedSessionId=e.value,this.selectedSessionId&&this.onSessionFilterChanged())}onSessionFilterChanged(){const e=window.eventViewer;e&&e.setSessionFilter(this.selectedSessionId),this.updateFooterInfo(),document.dispatchEvent(new CustomEvent("sessionFilterChanged",{detail:{sessionId:this.selectedSessionId}})),document.dispatchEvent(new CustomEvent("sessionChanged",{detail:{sessionId:this.selectedSessionId}}))}refreshSessions(){this.socketClient&&this.socketClient.getConnectionState().isConnected?(console.log("Refreshing sessions..."),this.socketClient.requestStatus()):console.warn("Cannot refresh sessions: not connected to server")}updateFooterInfo(){console.log("[SESSION-DEBUG] updateFooterInfo called, selectedSessionId:",this.selectedSessionId);const e=document.getElementById("footer-session"),s=document.getElementById("footer-working-dir"),t=document.getElementById("footer-git-branch");if(!e)return void console.warn("[SESSION-DEBUG] footer-session element not found");let n="All Sessions",o=window.dashboard?.workingDirectoryManager?.getDefaultWorkingDir()||process?.cwd?.()||"/Users/masa/Projects/claude-mpm",i="Unknown";if(console.log("[SESSION-DEBUG] Initial values - sessionInfo:",n,"workingDir:",o,"gitBranch:",i),"current"===this.selectedSessionId){if(n=this.currentSessionId?`Current: ${this.currentSessionId.substring(0,8)}...`:"Current: None",this.currentSessionId){const e=this.extractSessionInfoFromEvents(this.currentSessionId);o=e.workingDir||window.dashboard?.workingDirectoryManager?.getDefaultWorkingDir()||"/Users/masa/Projects/claude-mpm",i=e.gitBranch||"Unknown"}}else if(this.selectedSessionId){const e=this.sessions.get(this.selectedSessionId);if(e&&(n=`${this.selectedSessionId.substring(0,8)}...`,o=e.working_directory||e.workingDirectory||"",i=e.git_branch||e.gitBranch||"",!o||!i)){const e=this.extractSessionInfoFromEvents(this.selectedSessionId);o=o||e.workingDir||".",i=i||e.gitBranch||""}}console.log("[SESSION-DEBUG] Final values before setting footer - sessionInfo:",n,"workingDir:",o,"gitBranch:",i),e.textContent=n,s?(console.log("[SESSION-DEBUG] Setting footer working dir to:",o),s.textContent=o):console.warn("[SESSION-DEBUG] footer-working-dir element not found"),t?(console.log("[SESSION-DEBUG] Setting footer git branch to:",i),t.textContent=i):console.warn("[SESSION-DEBUG] footer-git-branch element not found")}extractSessionInfoFromEvents(e){let s="",t="";console.log(`[DEBUG] extractSessionInfoFromEvents called for sessionId: ${e}`);const n=this.socketClient;if(n&&n.events){console.log(`[DEBUG] Total events available: ${n.events.length}`);const o=n.events.filter(s=>s.data&&s.data.session_id===e);console.log(`[DEBUG] Events matching sessionId ${e}: ${o.length}`),o.length>0&&(console.log(`[DEBUG] Sample events for session ${e}:`),o.slice(0,3).forEach((e,s)=>{console.log(`[DEBUG] Event ${s+1}:`,{type:e.type,timestamp:e.timestamp,data_keys:e.data?Object.keys(e.data):"no data",full_event:e})}),o.length>3&&(console.log(`[DEBUG] Last 3 events for session ${e}:`),o.slice(-3).forEach((e,s)=>{console.log(`[DEBUG] Last Event ${s+1}:`,{type:e.type,timestamp:e.timestamp,data_keys:e.data?Object.keys(e.data):"no data",full_event:e})})));for(let e=o.length-1;e>=0;e--){const n=o[e];if(n.data){if(console.log(`[DEBUG] Examining event ${e} data:`,n.data),s||(n.data.working_directory?(s=n.data.working_directory,console.log(`[DEBUG] Found working_directory: ${s}`)):n.data.cwd?(s=n.data.cwd,console.log(`[DEBUG] Found cwd: ${s}`)):n.data.instance_info&&n.data.instance_info.working_dir&&(s=n.data.instance_info.working_dir,console.log(`[DEBUG] Found instance_info.working_dir: ${s}`))),!t){const e=["git_branch","gitBranch","branch","git.branch","vcs_branch","current_branch"];for(const s of e)if(n.data[s]){t=n.data[s],console.log(`[DEBUG] Found git branch in field '${s}': ${t}`);break}if(!t){if(n.data.instance_info){console.log("[DEBUG] Checking instance_info for branch:",n.data.instance_info);for(const s of e)if(n.data.instance_info[s]){t=n.data.instance_info[s],console.log(`[DEBUG] Found git branch in instance_info.${s}: ${t}`);break}}!t&&n.data.git&&(console.log("[DEBUG] Checking git object:",n.data.git),n.data.git.branch&&(t=n.data.git.branch,console.log(`[DEBUG] Found git branch in git.branch: ${t}`)))}}if(s&&t){console.log("[DEBUG] Found both workingDir and gitBranch, stopping search");break}}}}else console.log("[DEBUG] No socket client or events available");return console.log(`[DEBUG] Final results - workingDir: '${s}', gitBranch: '${t}'`),{workingDir:s,gitBranch:t}}setCurrentSessionId(e){this.currentSessionId=e,this.updateSessionSelect(),this.updateFooterInfo()}addSession(e){if(!e.id)return;const s=this.sessions.get(e.id);s?Object.assign(s,e):this.sessions.set(e.id,{id:e.id,startTime:e.startTime||e.start_time||(new Date).toISOString(),lastActivity:e.lastActivity||e.last_activity||(new Date).toISOString(),eventCount:e.eventCount||e.event_count||0,working_directory:e.working_directory||e.workingDirectory||"",git_branch:e.git_branch||e.gitBranch||"",agent_type:e.agent_type||e.agentType||"",...e}),this.updateSessionSelect()}removeSession(e){if(this.sessions.has(e)){if(this.sessions.delete(e),this.selectedSessionId===e){this.selectedSessionId="";const e=document.getElementById("session-select");e&&(e.value=""),this.onSessionFilterChanged()}this.updateSessionSelect()}}getCurrentFilter(){return this.selectedSessionId}getSession(e){return this.sessions.get(e)||null}getAllSessions(){return this.sessions}getCurrentSessionId(){return this.currentSessionId}clearSessions(){this.sessions.clear(),this.currentSessionId=null,this.selectedSessionId="",this.updateSessionSelect(),this.updateFooterInfo()}exportSessionData(){return{sessions:Array.from(this.sessions.entries()),currentSessionId:this.currentSessionId,selectedSessionId:this.selectedSessionId}}importSessionData(e){e.sessions&&Array.isArray(e.sessions)&&(this.sessions.clear(),e.sessions.forEach(([e,s])=>{this.sessions.set(e,s)})),e.currentSessionId&&(this.currentSessionId=e.currentSessionId),void 0!==e.selectedSessionId&&(this.selectedSessionId=e.selectedSessionId),this.updateSessionSelect(),this.updateFooterInfo()}getEventsForSession(e){if(!e||!this.socketClient)return[];return(this.socketClient.events||[]).filter(s=>(s.session_id||s.data&&s.data.session_id||null)===e)}}window.refreshSessions=function(){window.sessionManager&&window.sessionManager.refreshSessions()},window.SessionManager=e;export{e as S};
2
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1,2 @@
1
+ import{S as a,S as e}from"../socket-client.js";export{a as SocketManager,e as default};
2
+ //# sourceMappingURL=socket-manager.js.map
@@ -0,0 +1,2 @@
1
+ import{U as a,U as t}from"../socket-client.js";export{a as UIStateManager,t as default};
2
+ //# sourceMappingURL=ui-state-manager.js.map