claude-mpm 4.1.8__py3-none-any.whl → 4.1.10__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 (103) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +26 -1
  3. claude_mpm/agents/agents_metadata.py +57 -0
  4. claude_mpm/agents/templates/.claude-mpm/memories/README.md +17 -0
  5. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +3 -0
  6. claude_mpm/agents/templates/agent-manager.json +263 -17
  7. claude_mpm/agents/templates/agentic_coder_optimizer.json +222 -0
  8. claude_mpm/agents/templates/code_analyzer.json +18 -8
  9. claude_mpm/agents/templates/engineer.json +1 -1
  10. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +39 -0
  11. claude_mpm/agents/templates/qa.json +1 -1
  12. claude_mpm/agents/templates/research.json +1 -1
  13. claude_mpm/cli/__init__.py +4 -0
  14. claude_mpm/cli/commands/__init__.py +6 -0
  15. claude_mpm/cli/commands/analyze.py +547 -0
  16. claude_mpm/cli/commands/analyze_code.py +524 -0
  17. claude_mpm/cli/commands/configure.py +77 -28
  18. claude_mpm/cli/commands/configure_tui.py +60 -60
  19. claude_mpm/cli/commands/debug.py +1387 -0
  20. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  21. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  22. claude_mpm/cli/parsers/base_parser.py +29 -0
  23. claude_mpm/cli/parsers/debug_parser.py +319 -0
  24. claude_mpm/constants.py +3 -1
  25. claude_mpm/core/framework_loader.py +148 -6
  26. claude_mpm/core/log_manager.py +16 -13
  27. claude_mpm/core/logger.py +1 -1
  28. claude_mpm/core/unified_agent_registry.py +1 -1
  29. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +1 -0
  30. claude_mpm/dashboard/analysis_runner.py +428 -0
  31. claude_mpm/dashboard/static/built/components/activity-tree.js +2 -0
  32. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  33. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  34. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  35. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  36. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  37. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  38. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  39. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  40. claude_mpm/dashboard/static/css/activity.css +549 -0
  41. claude_mpm/dashboard/static/css/code-tree.css +846 -0
  42. claude_mpm/dashboard/static/css/dashboard.css +245 -0
  43. claude_mpm/dashboard/static/dist/components/activity-tree.js +2 -0
  44. claude_mpm/dashboard/static/dist/components/code-tree.js +2 -0
  45. claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
  46. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  47. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  48. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  49. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  50. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  51. claude_mpm/dashboard/static/js/components/activity-tree.js +1139 -0
  52. claude_mpm/dashboard/static/js/components/code-tree.js +1357 -0
  53. claude_mpm/dashboard/static/js/components/code-viewer.js +480 -0
  54. claude_mpm/dashboard/static/js/components/event-viewer.js +11 -0
  55. claude_mpm/dashboard/static/js/components/session-manager.js +40 -4
  56. claude_mpm/dashboard/static/js/components/socket-manager.js +12 -0
  57. claude_mpm/dashboard/static/js/components/ui-state-manager.js +4 -0
  58. claude_mpm/dashboard/static/js/components/working-directory.js +17 -1
  59. claude_mpm/dashboard/static/js/dashboard.js +39 -0
  60. claude_mpm/dashboard/static/js/socket-client.js +414 -20
  61. claude_mpm/dashboard/templates/index.html +184 -4
  62. claude_mpm/hooks/claude_hooks/hook_handler.py +182 -5
  63. claude_mpm/hooks/claude_hooks/installer.py +386 -113
  64. claude_mpm/scripts/claude-hook-handler.sh +161 -0
  65. claude_mpm/scripts/socketio_daemon.py +121 -8
  66. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +2 -2
  67. claude_mpm/services/agents/deployment/agent_record_service.py +1 -2
  68. claude_mpm/services/agents/memory/memory_format_service.py +1 -5
  69. claude_mpm/services/cli/agent_cleanup_service.py +1 -2
  70. claude_mpm/services/cli/agent_dependency_service.py +1 -1
  71. claude_mpm/services/cli/agent_validation_service.py +3 -4
  72. claude_mpm/services/cli/dashboard_launcher.py +2 -3
  73. claude_mpm/services/cli/startup_checker.py +0 -10
  74. claude_mpm/services/core/cache_manager.py +1 -2
  75. claude_mpm/services/core/path_resolver.py +1 -4
  76. claude_mpm/services/core/service_container.py +2 -2
  77. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  78. claude_mpm/services/infrastructure/monitoring/__init__.py +11 -11
  79. claude_mpm/services/infrastructure/monitoring.py +11 -11
  80. claude_mpm/services/project/architecture_analyzer.py +1 -1
  81. claude_mpm/services/project/dependency_analyzer.py +4 -4
  82. claude_mpm/services/project/language_analyzer.py +3 -3
  83. claude_mpm/services/project/metrics_collector.py +3 -6
  84. claude_mpm/services/socketio/handlers/__init__.py +2 -0
  85. claude_mpm/services/socketio/handlers/code_analysis.py +170 -0
  86. claude_mpm/services/socketio/handlers/registry.py +2 -0
  87. claude_mpm/services/socketio/server/connection_manager.py +4 -4
  88. claude_mpm/services/socketio/server/core.py +100 -11
  89. claude_mpm/services/socketio/server/main.py +8 -2
  90. claude_mpm/services/visualization/__init__.py +19 -0
  91. claude_mpm/services/visualization/mermaid_generator.py +938 -0
  92. claude_mpm/tools/__main__.py +208 -0
  93. claude_mpm/tools/code_tree_analyzer.py +778 -0
  94. claude_mpm/tools/code_tree_builder.py +632 -0
  95. claude_mpm/tools/code_tree_events.py +318 -0
  96. claude_mpm/tools/socketio_debug.py +671 -0
  97. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.10.dist-info}/METADATA +1 -1
  98. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.10.dist-info}/RECORD +102 -73
  99. claude_mpm/agents/schema/agent_schema.json +0 -314
  100. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.10.dist-info}/WHEEL +0 -0
  101. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.10.dist-info}/entry_points.txt +0 -0
  102. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.10.dist-info}/licenses/LICENSE +0 -0
  103. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1387 @@
1
+ """
2
+ Debug command for claude-mpm CLI.
3
+
4
+ This module provides comprehensive debugging tools for developers, including:
5
+ - Service debugging (status, dependencies, health)
6
+ - Agent debugging (deployed, memory, trace)
7
+ - Hook system debugging (list, trace, performance)
8
+ - Cache inspection and management
9
+ - Performance profiling and analysis
10
+ - SocketIO event monitoring
11
+ """
12
+
13
+ import contextlib
14
+ import json
15
+ import time
16
+ from collections import defaultdict
17
+ from datetime import datetime
18
+ from pathlib import Path
19
+ from typing import Any, Dict
20
+
21
+ from ...core.logger import get_logger
22
+
23
+
24
+ def manage_debug(args):
25
+ """
26
+ Main entry point for debug commands.
27
+
28
+ Args:
29
+ args: Parsed command-line arguments
30
+
31
+ Returns:
32
+ int: Exit code (0 for success, non-zero for failure)
33
+ """
34
+ # Get logger (it will use the logging level set by main CLI)
35
+ logger = get_logger("debug")
36
+
37
+ # Dispatch to appropriate subcommand
38
+ if args.debug_command == "socketio":
39
+ return debug_socketio(args, logger)
40
+ if args.debug_command == "events":
41
+ # Alias for socketio
42
+ return debug_socketio(args, logger)
43
+ if args.debug_command == "connections":
44
+ return debug_connections(args, logger)
45
+ if args.debug_command == "services":
46
+ return debug_services(args, logger)
47
+ if args.debug_command == "agents":
48
+ return debug_agents(args, logger)
49
+ if args.debug_command == "hooks":
50
+ return debug_hooks(args, logger)
51
+ if args.debug_command == "cache":
52
+ return debug_cache(args, logger)
53
+ if args.debug_command == "performance":
54
+ return debug_performance(args, logger)
55
+ logger.error(f"Unknown debug command: {args.debug_command}")
56
+ return 1
57
+
58
+
59
+ def debug_socketio(args, logger):
60
+ """
61
+ Debug SocketIO events using the professional debugging tool.
62
+
63
+ Args:
64
+ args: Parsed command-line arguments
65
+ logger: Logger instance
66
+
67
+ Returns:
68
+ int: Exit code
69
+ """
70
+ try:
71
+ from ...tools.socketio_debug import DisplayMode, SocketIODebugger
72
+
73
+ logger.info("Starting SocketIO debugger...")
74
+
75
+ # Map display mode from args
76
+ mode = DisplayMode.LIVE # Default
77
+ if args.summary:
78
+ mode = DisplayMode.SUMMARY
79
+ elif args.raw:
80
+ mode = DisplayMode.RAW
81
+ elif args.pretty:
82
+ mode = DisplayMode.PRETTY
83
+ elif args.filter_types:
84
+ mode = DisplayMode.FILTERED
85
+
86
+ # Create debugger instance
87
+ debugger = SocketIODebugger(
88
+ host=args.host,
89
+ port=args.port,
90
+ mode=mode,
91
+ filter_types=args.filter_types,
92
+ output_file=Path(args.output) if args.output else None,
93
+ quiet=args.quiet,
94
+ show_raw=args.raw,
95
+ max_reconnect_attempts=getattr(args, "max_reconnect", 10),
96
+ reconnect_delay=getattr(args, "reconnect_delay", 1.0),
97
+ )
98
+
99
+ # Run the debugger
100
+ success = debugger.run()
101
+
102
+ if success:
103
+ logger.info("SocketIO debugger stopped successfully")
104
+ return 0
105
+ logger.error("SocketIO debugger encountered an error")
106
+ return 1
107
+
108
+ except ImportError as e:
109
+ logger.error(f"Failed to import debugging tool: {e}")
110
+ print(
111
+ "❌ Debugging tool not available. Please ensure all dependencies are installed."
112
+ )
113
+ return 1
114
+ except KeyboardInterrupt:
115
+ logger.info("SocketIO debugger interrupted by user")
116
+ return 0
117
+ except Exception as e:
118
+ logger.error(f"Unexpected error in SocketIO debugger: {e}", exc_info=True)
119
+ return 1
120
+
121
+
122
+ def debug_connections(args, logger):
123
+ """
124
+ Debug active SocketIO connections and server status.
125
+
126
+ Args:
127
+ args: Parsed command-line arguments
128
+ logger: Logger instance
129
+
130
+ Returns:
131
+ int: Exit code
132
+ """
133
+ try:
134
+ import json
135
+
136
+ from ...services.port_manager import PortManager
137
+
138
+ logger.info("Checking SocketIO connections...")
139
+
140
+ # Get port manager
141
+ port_manager = PortManager()
142
+
143
+ # Clean up dead instances
144
+ port_manager.cleanup_dead_instances()
145
+
146
+ # Get active instances
147
+ active_instances = port_manager.list_active_instances()
148
+
149
+ if not active_instances:
150
+ print("No active SocketIO servers found")
151
+ return 0
152
+
153
+ print(f"\n📡 Active SocketIO Servers ({len(active_instances)}):")
154
+ print("-" * 60)
155
+
156
+ for instance in active_instances:
157
+ port = instance.get("port", "unknown")
158
+ pid = instance.get("pid", "unknown")
159
+ start_time = instance.get("start_time", "unknown")
160
+
161
+ print(f"\n🔌 Server on port {port}")
162
+ print(f" PID: {pid}")
163
+ print(f" Started: {start_time}")
164
+
165
+ # Try to check if it's actually responding
166
+ import socket
167
+
168
+ try:
169
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
170
+ s.settimeout(1.0)
171
+ result = s.connect_ex(("127.0.0.1", port))
172
+ if result == 0:
173
+ print(" Status: ✅ Responding")
174
+ else:
175
+ print(" Status: ⚠️ Not responding (may be stale)")
176
+ except Exception as e:
177
+ print(f" Status: ❌ Error checking: {e}")
178
+
179
+ print("\n" + "-" * 60)
180
+ print(f"Total: {len(active_instances)} server(s)")
181
+
182
+ # If verbose, show full JSON
183
+ if getattr(args, "verbose", False):
184
+ print("\nFull instance data:")
185
+ print(json.dumps(active_instances, indent=2, default=str))
186
+
187
+ return 0
188
+
189
+ except Exception as e:
190
+ logger.error(f"Failed to check connections: {e}", exc_info=True)
191
+ return 1
192
+
193
+
194
+ def debug_services(args, logger):
195
+ """
196
+ Debug services: list, status, dependencies, and health.
197
+
198
+ Args:
199
+ args: Parsed command-line arguments
200
+ logger: Logger instance
201
+
202
+ Returns:
203
+ int: Exit code
204
+ """
205
+ try:
206
+ # Import service-related modules
207
+ from ...core.container import DIContainer
208
+
209
+ logger.info("Debugging services...")
210
+
211
+ # Get the global container if available
212
+ container = None
213
+ try:
214
+ # Try to get a container instance if it has the method
215
+ if hasattr(DIContainer, "get_instance"):
216
+ container = DIContainer.get_instance()
217
+ else:
218
+ container = DIContainer()
219
+ except:
220
+ # Create a new container if none exists
221
+ container = DIContainer()
222
+ logger.warning("No active container found, created new instance")
223
+
224
+ if args.list:
225
+ # List all registered services
226
+ print("\n📦 Registered Services:")
227
+ print("=" * 60)
228
+
229
+ services = container._services if hasattr(container, "_services") else {}
230
+ if not services:
231
+ print("No services registered")
232
+ else:
233
+ for service_type, registration in services.items():
234
+ service_name = (
235
+ service_type.__name__
236
+ if hasattr(service_type, "__name__")
237
+ else str(service_type)
238
+ )
239
+ impl_name = (
240
+ registration.implementation.__name__
241
+ if hasattr(registration.implementation, "__name__")
242
+ else str(registration.implementation)
243
+ )
244
+ print(f"\n🔧 {service_name}")
245
+ print(f" Implementation: {impl_name}")
246
+ print(f" Lifetime: {registration.lifetime.value}")
247
+ if registration.instance:
248
+ print(" Status: ✅ Instantiated")
249
+ else:
250
+ print(" Status: ⏸️ Not instantiated")
251
+
252
+ elif args.status:
253
+ # Show service status and health
254
+ print("\n🏥 Service Health Status:")
255
+ print("=" * 60)
256
+
257
+ # Try to get monitoring service
258
+ try:
259
+ from ...services.infrastructure.monitoring import MonitoringService
260
+
261
+ monitor = MonitoringService()
262
+
263
+ # Collect health metrics
264
+ metrics = monitor.collect_metrics()
265
+
266
+ print("\n📊 System Metrics:")
267
+ print(f" CPU Usage: {metrics.get('cpu_percent', 'N/A')}%")
268
+ print(f" Memory Usage: {metrics.get('memory_percent', 'N/A')}%")
269
+ print(f" Disk Usage: {metrics.get('disk_percent', 'N/A')}%")
270
+
271
+ if "network" in metrics:
272
+ net = metrics["network"]
273
+ print("\n🌐 Network:")
274
+ print(f" Bytes Sent: {net.get('bytes_sent', 0):,}")
275
+ print(f" Bytes Received: {net.get('bytes_recv', 0):,}")
276
+
277
+ except Exception as e:
278
+ logger.warning(f"Could not get monitoring metrics: {e}")
279
+ print("⚠️ Monitoring service not available")
280
+
281
+ elif args.dependencies:
282
+ # Show service dependency graph
283
+ print("\n🕸️ Service Dependencies:")
284
+ print("=" * 60)
285
+
286
+ services = container._services if hasattr(container, "_services") else {}
287
+ if not services:
288
+ print("No services registered")
289
+ else:
290
+ # Build dependency graph
291
+ for service_type, registration in services.items():
292
+ service_name = (
293
+ service_type.__name__
294
+ if hasattr(service_type, "__name__")
295
+ else str(service_type)
296
+ )
297
+ print(f"\n📌 {service_name}")
298
+
299
+ if registration.dependencies:
300
+ for dep_name, dep_type in registration.dependencies.items():
301
+ dep_type_name = (
302
+ dep_type.__name__
303
+ if hasattr(dep_type, "__name__")
304
+ else str(dep_type)
305
+ )
306
+ print(f" └─> {dep_name}: {dep_type_name}")
307
+ else:
308
+ print(" └─> No dependencies")
309
+
310
+ elif args.trace:
311
+ # Trace service resolution
312
+ service_name = args.trace
313
+ print(f"\n🔍 Tracing service resolution for: {service_name}")
314
+ print("=" * 60)
315
+
316
+ # Try to find and resolve the service
317
+ services = container._services if hasattr(container, "_services") else {}
318
+ found = False
319
+
320
+ for service_type, registration in services.items():
321
+ type_name = (
322
+ service_type.__name__
323
+ if hasattr(service_type, "__name__")
324
+ else str(service_type)
325
+ )
326
+ if service_name in type_name:
327
+ found = True
328
+ print(f"\n✅ Found service: {type_name}")
329
+ print(f" Implementation: {registration.implementation}")
330
+ print(f" Lifetime: {registration.lifetime.value}")
331
+
332
+ # Try to resolve
333
+ try:
334
+ instance = container.resolve(service_type)
335
+ print(" Resolution: ✅ Success")
336
+ print(f" Instance Type: {type(instance).__name__}")
337
+ except Exception as e:
338
+ print(" Resolution: ❌ Failed")
339
+ print(f" Error: {e}")
340
+ break
341
+
342
+ if not found:
343
+ print(f"❌ Service '{service_name}' not found")
344
+
345
+ else:
346
+ # Default: show summary
347
+ print("\n📊 Services Summary:")
348
+ print("=" * 60)
349
+ services = container._services if hasattr(container, "_services") else {}
350
+ print(f"Total Registered: {len(services)}")
351
+
352
+ # Count by lifetime
353
+ lifetime_counts = defaultdict(int)
354
+ instantiated = 0
355
+
356
+ for registration in services.values():
357
+ lifetime_counts[registration.lifetime.value] += 1
358
+ if registration.instance:
359
+ instantiated += 1
360
+
361
+ print("\nLifetime Distribution:")
362
+ for lifetime, count in lifetime_counts.items():
363
+ print(f" {lifetime}: {count}")
364
+
365
+ print(f"\nInstantiated: {instantiated}/{len(services)}")
366
+
367
+ return 0
368
+
369
+ except Exception as e:
370
+ logger.error(f"Failed to debug services: {e}", exc_info=True)
371
+ return 1
372
+
373
+
374
+ def debug_agents(args, logger):
375
+ """
376
+ Debug agents: deployed agents, memory, and tracing.
377
+
378
+ Args:
379
+ args: Parsed command-line arguments
380
+ logger: Logger instance
381
+
382
+ Returns:
383
+ int: Exit code
384
+ """
385
+ try:
386
+ logger.info("Debugging agents...")
387
+
388
+ if args.deployed:
389
+ # List deployed agents
390
+ from pathlib import Path
391
+
392
+
393
+ print("\n🤖 Deployed Agents:")
394
+ print("=" * 60)
395
+
396
+ # Check different deployment locations
397
+ locations = [
398
+ Path.home() / ".claude" / "agents",
399
+ Path.cwd() / ".claude" / "agents",
400
+ ]
401
+
402
+ total_agents = 0
403
+ for location in locations:
404
+ if location.exists():
405
+ print(f"\n📁 Location: {location}")
406
+ agent_files = list(location.glob("*.md"))
407
+ if agent_files:
408
+ for agent_file in agent_files:
409
+ agent_name = agent_file.stem
410
+ size = agent_file.stat().st_size
411
+ modified = datetime.fromtimestamp(
412
+ agent_file.stat().st_mtime
413
+ )
414
+ print(f" • {agent_name}")
415
+ print(f" Size: {size:,} bytes")
416
+ print(
417
+ f" Modified: {modified.strftime('%Y-%m-%d %H:%M:%S')}"
418
+ )
419
+ total_agents += 1
420
+ else:
421
+ print(" No agents found")
422
+
423
+ print(f"\nTotal Agents: {total_agents}")
424
+
425
+ elif args.memory:
426
+ # Show agent memory status
427
+ from ...services.agents.memory import get_memory_manager
428
+
429
+ print("\n🧠 Agent Memory Status:")
430
+ print("=" * 60)
431
+
432
+ try:
433
+ get_memory_manager()
434
+
435
+ # List all memory files
436
+ memory_dir = Path.home() / ".claude" / "memory"
437
+ if not memory_dir.exists():
438
+ memory_dir = Path.cwd() / ".claude" / "memory"
439
+
440
+ if memory_dir.exists():
441
+ memory_files = list(memory_dir.glob("*.json"))
442
+
443
+ total_size = 0
444
+ for mem_file in memory_files:
445
+ agent_name = mem_file.stem
446
+ size = mem_file.stat().st_size
447
+
448
+ # Try to load and analyze memory
449
+ try:
450
+ with open(mem_file) as f:
451
+ memory_data = json.load(f)
452
+
453
+ entry_count = (
454
+ len(memory_data) if isinstance(memory_data, list) else 1
455
+ )
456
+ print(f"\n📝 Agent: {agent_name}")
457
+ print(f" File: {mem_file}")
458
+ print(f" Size: {size:,} bytes")
459
+ print(f" Entries: {entry_count}")
460
+ total_size += size
461
+
462
+ # Show recent entries if requested
463
+ if (
464
+ args.verbose
465
+ and isinstance(memory_data, list)
466
+ and memory_data
467
+ ):
468
+ print(" Recent entries:")
469
+ for entry in memory_data[-3:]:
470
+ timestamp = entry.get("timestamp", "N/A")
471
+ category = entry.get("category", "N/A")
472
+ print(f" - [{timestamp}] {category}")
473
+
474
+ except Exception as e:
475
+ print(f"\n📝 Agent: {agent_name}")
476
+ print(f" ⚠️ Could not parse memory: {e}")
477
+
478
+ print("\n📊 Summary:")
479
+ print(f" Total Memory Files: {len(memory_files)}")
480
+ print(f" Total Size: {total_size:,} bytes")
481
+ else:
482
+ print("No memory directory found")
483
+
484
+ except Exception as e:
485
+ logger.warning(f"Could not access memory manager: {e}")
486
+ print("⚠️ Memory manager not available")
487
+
488
+ elif args.trace:
489
+ # Trace agent execution
490
+ agent_name = args.trace
491
+ print(f"\n🔍 Tracing agent: {agent_name}")
492
+ print("=" * 60)
493
+
494
+ # Look for the agent
495
+ from pathlib import Path
496
+
497
+ # Check different locations
498
+ locations = [
499
+ Path.home() / ".claude" / "agents",
500
+ Path.cwd() / ".claude" / "agents",
501
+ ]
502
+
503
+ found = False
504
+ for location in locations:
505
+ agent_file = location / f"{agent_name}.md"
506
+ if agent_file.exists():
507
+ found = True
508
+ print(f"✅ Agent found: {agent_name}")
509
+ print(f" Location: {agent_file}")
510
+ print(f" Size: {agent_file.stat().st_size:,} bytes")
511
+
512
+ # Read first few lines for type detection
513
+ with open(agent_file) as f:
514
+ lines = f.readlines()[:10]
515
+ for line in lines:
516
+ if "role:" in line.lower():
517
+ print(f" Role: {line.split(':')[1].strip()}")
518
+ elif "type:" in line.lower():
519
+ print(f" Type: {line.split(':')[1].strip()}")
520
+ break
521
+
522
+ if not found:
523
+ print(f"❌ Agent '{agent_name}' not found")
524
+
525
+ else:
526
+ # Default: show summary
527
+ print("\n📊 Agents Summary:")
528
+ print("=" * 60)
529
+
530
+ # Count agents in different locations
531
+ locations = [
532
+ (Path.home() / ".claude" / "agents", "User"),
533
+ (Path.cwd() / ".claude" / "agents", "Project"),
534
+ ]
535
+
536
+ total = 0
537
+ for location, label in locations:
538
+ if location.exists():
539
+ count = len(list(location.glob("*.md")))
540
+ print(f"{label} Agents: {count}")
541
+ total += count
542
+
543
+ print(f"\nTotal Agents: {total}")
544
+
545
+ return 0
546
+
547
+ except Exception as e:
548
+ logger.error(f"Failed to debug agents: {e}", exc_info=True)
549
+ return 1
550
+
551
+
552
+ def debug_hooks(args, logger):
553
+ """
554
+ Debug hook system: list hooks, trace execution, analyze performance.
555
+
556
+ Args:
557
+ args: Parsed command-line arguments
558
+ logger: Logger instance
559
+
560
+ Returns:
561
+ int: Exit code
562
+ """
563
+ try:
564
+ from ...services.hook_service import HookService
565
+
566
+ logger.info("Debugging hooks...")
567
+
568
+ # Try to get the hook service
569
+ hook_service = HookService()
570
+
571
+ if args.list:
572
+ # List all registered hooks
573
+ print("\n🪝 Registered Hooks:")
574
+ print("=" * 60)
575
+
576
+ print("\n📥 Pre-Delegation Hooks:")
577
+ if hook_service.pre_delegation_hooks:
578
+ for hook in hook_service.pre_delegation_hooks:
579
+ print(f" • {hook.name}")
580
+ print(f" Priority: {hook.priority}")
581
+ print(f" Enabled: {hook.enabled}")
582
+ if hasattr(hook, "description"):
583
+ print(f" Description: {hook.description}")
584
+ else:
585
+ print(" No pre-delegation hooks registered")
586
+
587
+ print("\n📤 Post-Delegation Hooks:")
588
+ if hook_service.post_delegation_hooks:
589
+ for hook in hook_service.post_delegation_hooks:
590
+ print(f" • {hook.name}")
591
+ print(f" Priority: {hook.priority}")
592
+ print(f" Enabled: {hook.enabled}")
593
+ if hasattr(hook, "description"):
594
+ print(f" Description: {hook.description}")
595
+ else:
596
+ print(" No post-delegation hooks registered")
597
+
598
+ # Show statistics
599
+ print("\n📊 Hook Statistics:")
600
+ print(
601
+ f" Pre-delegation executed: {hook_service.stats.get('pre_delegation_executed', 0)}"
602
+ )
603
+ print(
604
+ f" Post-delegation executed: {hook_service.stats.get('post_delegation_executed', 0)}"
605
+ )
606
+ print(f" Errors: {hook_service.stats.get('errors', 0)}")
607
+
608
+ elif args.trace:
609
+ # Trace hook execution
610
+ hook_name = args.trace
611
+ print(f"\n🔍 Tracing hook: {hook_name}")
612
+ print("=" * 60)
613
+
614
+ found = False
615
+
616
+ # Search in pre-delegation hooks
617
+ for hook in hook_service.pre_delegation_hooks:
618
+ if hook_name.lower() in hook.name.lower():
619
+ found = True
620
+ print(f"\n✅ Found pre-delegation hook: {hook.name}")
621
+ print(f" Priority: {hook.priority}")
622
+ print(f" Enabled: {hook.enabled}")
623
+ print(f" Type: {type(hook).__name__}")
624
+
625
+ # Test execution
626
+ if args.test:
627
+ print("\n🧪 Test Execution:")
628
+ from ...hooks.base_hook import HookContext
629
+
630
+ test_context = HookContext(
631
+ agent_name="test_agent",
632
+ task="test_task",
633
+ metadata={"test": True},
634
+ )
635
+
636
+ try:
637
+ start_time = time.time()
638
+ result = hook.execute(test_context)
639
+ elapsed = time.time() - start_time
640
+
641
+ print(" Status: ✅ Success")
642
+ print(f" Execution Time: {elapsed:.3f}s")
643
+ print(f" Modified: {result.context_modified}")
644
+ if result.error:
645
+ print(f" Error: {result.error}")
646
+ except Exception as e:
647
+ print(" Status: ❌ Failed")
648
+ print(f" Error: {e}")
649
+ break
650
+
651
+ # Search in post-delegation hooks
652
+ for hook in hook_service.post_delegation_hooks:
653
+ if hook_name.lower() in hook.name.lower():
654
+ found = True
655
+ print(f"\n✅ Found post-delegation hook: {hook.name}")
656
+ print(f" Priority: {hook.priority}")
657
+ print(f" Enabled: {hook.enabled}")
658
+ print(f" Type: {type(hook).__name__}")
659
+ break
660
+
661
+ if not found:
662
+ print(f"❌ Hook '{hook_name}' not found")
663
+
664
+ elif args.performance:
665
+ # Analyze hook performance
666
+ print("\n⚡ Hook Performance Analysis:")
667
+ print("=" * 60)
668
+
669
+ # Performance test each hook
670
+ print("\n📥 Pre-Delegation Hooks Performance:")
671
+ for hook in hook_service.pre_delegation_hooks:
672
+ from ...hooks.base_hook import HookContext
673
+
674
+ test_context = HookContext(
675
+ agent_name="perf_test", task="performance test", metadata={}
676
+ )
677
+
678
+ # Run multiple iterations
679
+ iterations = 10
680
+ times = []
681
+
682
+ for _ in range(iterations):
683
+ try:
684
+ start = time.time()
685
+ hook.execute(test_context)
686
+ elapsed = time.time() - start
687
+ times.append(elapsed)
688
+ except:
689
+ pass
690
+
691
+ if times:
692
+ avg_time = sum(times) / len(times)
693
+ min_time = min(times)
694
+ max_time = max(times)
695
+
696
+ print(f"\n {hook.name}:")
697
+ print(f" Average: {avg_time*1000:.2f}ms")
698
+ print(f" Min: {min_time*1000:.2f}ms")
699
+ print(f" Max: {max_time*1000:.2f}ms")
700
+
701
+ else:
702
+ # Default: show summary
703
+ print("\n📊 Hooks Summary:")
704
+ print("=" * 60)
705
+ print(f"Pre-delegation hooks: {len(hook_service.pre_delegation_hooks)}")
706
+ print(f"Post-delegation hooks: {len(hook_service.post_delegation_hooks)}")
707
+ print("\nExecution Statistics:")
708
+ print(
709
+ f" Pre-delegation executed: {hook_service.stats.get('pre_delegation_executed', 0)}"
710
+ )
711
+ print(
712
+ f" Post-delegation executed: {hook_service.stats.get('post_delegation_executed', 0)}"
713
+ )
714
+ print(f" Total errors: {hook_service.stats.get('errors', 0)}")
715
+
716
+ return 0
717
+
718
+ except Exception as e:
719
+ logger.error(f"Failed to debug hooks: {e}", exc_info=True)
720
+ return 1
721
+
722
+
723
+ def debug_cache(args, logger):
724
+ """
725
+ Debug cache: inspect, clear, and analyze cache performance.
726
+
727
+ Args:
728
+ args: Parsed command-line arguments
729
+ logger: Logger instance
730
+
731
+ Returns:
732
+ int: Exit code
733
+ """
734
+ try:
735
+ from ...services.core.cache_manager import CacheManager
736
+
737
+ logger.info("Debugging cache...")
738
+
739
+ if args.inspect:
740
+ # Inspect cache contents
741
+ print("\n🗄️ Cache Inspection:")
742
+ print("=" * 60)
743
+
744
+ # Get cache directory
745
+ cache_dir = Path.home() / ".cache" / "claude-mpm"
746
+ if not cache_dir.exists():
747
+ print("No cache directory found")
748
+ return 0
749
+
750
+ # Analyze cache files
751
+ cache_files = list(cache_dir.rglob("*"))
752
+ total_size = 0
753
+ file_count = 0
754
+
755
+ categories = defaultdict(list)
756
+
757
+ for file_path in cache_files:
758
+ if file_path.is_file():
759
+ file_count += 1
760
+ size = file_path.stat().st_size
761
+ total_size += size
762
+
763
+ # Categorize by parent directory
764
+ category = file_path.parent.name
765
+ categories[category].append((file_path.name, size))
766
+
767
+ print("\n📊 Cache Statistics:")
768
+ print(f" Location: {cache_dir}")
769
+ print(f" Total Files: {file_count}")
770
+ print(
771
+ f" Total Size: {total_size:,} bytes ({total_size/1024/1024:.2f} MB)"
772
+ )
773
+
774
+ print("\n📁 Categories:")
775
+ for category, files in categories.items():
776
+ cat_size = sum(size for _, size in files)
777
+ print(f"\n {category}:")
778
+ print(f" Files: {len(files)}")
779
+ print(f" Size: {cat_size:,} bytes")
780
+
781
+ if args.verbose:
782
+ # Show individual files
783
+ for name, size in sorted(files, key=lambda x: x[1], reverse=True)[
784
+ :5
785
+ ]:
786
+ print(f" • {name}: {size:,} bytes")
787
+
788
+ elif args.clear:
789
+ # Clear cache
790
+ print("\n🧹 Clearing cache...")
791
+ print("=" * 60)
792
+
793
+ cache_dir = Path.home() / ".cache" / "claude-mpm"
794
+
795
+ if not cache_dir.exists():
796
+ print("No cache to clear")
797
+ return 0
798
+
799
+ # Count files before clearing
800
+ files_before = list(cache_dir.rglob("*"))
801
+ file_count = len([f for f in files_before if f.is_file()])
802
+
803
+ if (
804
+ args.confirm
805
+ or input(f"Clear {file_count} cache files? (y/N): ").lower() == "y"
806
+ ):
807
+ # Clear cache
808
+ import shutil
809
+
810
+ try:
811
+ shutil.rmtree(cache_dir)
812
+ print(f"✅ Cleared {file_count} cache files")
813
+ except Exception as e:
814
+ print(f"❌ Failed to clear cache: {e}")
815
+ return 1
816
+ else:
817
+ print("Cache clear cancelled")
818
+
819
+ elif args.stats:
820
+ # Show cache performance statistics
821
+ print("\n📈 Cache Performance Statistics:")
822
+ print("=" * 60)
823
+
824
+ # Try to get cache manager
825
+ cache_manager = CacheManager()
826
+
827
+ # Simulate cache operations to gather stats
828
+ print("\n🔄 Cache TTL Configuration:")
829
+ print(f" Capabilities TTL: {cache_manager.capabilities_ttl}s")
830
+ print(f" Deployed Agents TTL: {cache_manager.deployed_agents_ttl}s")
831
+ print(f" Metadata TTL: {cache_manager.metadata_ttl}s")
832
+ print(f" Memories TTL: {cache_manager.memories_ttl}s")
833
+
834
+ # Check cache status
835
+ current_time = time.time()
836
+
837
+ print("\n⏱️ Cache Status:")
838
+
839
+ # Check capabilities cache
840
+ if cache_manager._capabilities_cache:
841
+ age = current_time - cache_manager._capabilities_cache_time
842
+ status = (
843
+ "✅ Valid" if age < cache_manager.capabilities_ttl else "❌ Expired"
844
+ )
845
+ print(f" Capabilities: {status} (age: {age:.1f}s)")
846
+ else:
847
+ print(" Capabilities: ⚫ Empty")
848
+
849
+ # Check deployed agents cache
850
+ if cache_manager._deployed_agents_cache:
851
+ age = current_time - cache_manager._deployed_agents_cache_time
852
+ status = (
853
+ "✅ Valid"
854
+ if age < cache_manager.deployed_agents_ttl
855
+ else "❌ Expired"
856
+ )
857
+ print(f" Deployed Agents: {status} (age: {age:.1f}s)")
858
+ else:
859
+ print(" Deployed Agents: ⚫ Empty")
860
+
861
+ else:
862
+ # Default: show summary
863
+ print("\n📊 Cache Summary:")
864
+ print("=" * 60)
865
+
866
+ cache_dir = Path.home() / ".cache" / "claude-mpm"
867
+
868
+ if cache_dir.exists():
869
+ cache_files = list(cache_dir.rglob("*"))
870
+ file_count = len([f for f in cache_files if f.is_file()])
871
+ total_size = sum(f.stat().st_size for f in cache_files if f.is_file())
872
+
873
+ print(f"Location: {cache_dir}")
874
+ print(f"Files: {file_count}")
875
+ print(f"Size: {total_size:,} bytes ({total_size/1024/1024:.2f} MB)")
876
+ else:
877
+ print("No cache found")
878
+
879
+ return 0
880
+
881
+ except Exception as e:
882
+ logger.error(f"Failed to debug cache: {e}", exc_info=True)
883
+ return 1
884
+
885
+
886
+ def debug_performance(args, logger):
887
+ """
888
+ Debug performance: profile operations, analyze bottlenecks.
889
+
890
+ Args:
891
+ args: Parsed command-line arguments
892
+ logger: Logger instance
893
+
894
+ Returns:
895
+ int: Exit code
896
+ """
897
+ try:
898
+ logger.info("Running performance analysis...")
899
+
900
+ print("\n⚡ Performance Analysis:")
901
+ print("=" * 60)
902
+
903
+ if args.profile:
904
+ # Profile specific operation
905
+ operation = args.profile
906
+ print(f"\n🔍 Profiling operation: {operation}")
907
+
908
+ import cProfile
909
+ import pstats
910
+ from io import StringIO
911
+
912
+ profiler = cProfile.Profile()
913
+
914
+ # Map operation to actual function
915
+ operations = {
916
+ "agent_load": lambda: _profile_agent_load(),
917
+ "service_init": lambda: _profile_service_init(),
918
+ "cache_ops": lambda: _profile_cache_operations(),
919
+ "memory_ops": lambda: _profile_memory_operations(),
920
+ }
921
+
922
+ if operation in operations:
923
+ print("Starting profile...")
924
+
925
+ profiler.enable()
926
+ start_time = time.time()
927
+
928
+ try:
929
+ operations[operation]()
930
+ except Exception as e:
931
+ print(f"⚠️ Operation failed: {e}")
932
+
933
+ elapsed = time.time() - start_time
934
+ profiler.disable()
935
+
936
+ # Print statistics
937
+ print(f"\n✅ Profile complete (elapsed: {elapsed:.3f}s)")
938
+
939
+ s = StringIO()
940
+ ps = pstats.Stats(profiler, stream=s).sort_stats("cumulative")
941
+ ps.print_stats(20) # Top 20 functions
942
+
943
+ print("\n📊 Top Functions by Cumulative Time:")
944
+ print(s.getvalue())
945
+ else:
946
+ print(f"❌ Unknown operation: {operation}")
947
+ print(" Available: agent_load, service_init, cache_ops, memory_ops")
948
+
949
+ elif args.benchmark:
950
+ # Run benchmarks
951
+ print("\n🏃 Running benchmarks...")
952
+
953
+ benchmarks = [
954
+ ("Service Container Resolution", _benchmark_service_resolution),
955
+ ("Cache Operations", _benchmark_cache_operations),
956
+ ("Agent Loading", _benchmark_agent_loading),
957
+ ("Hook Execution", _benchmark_hook_execution),
958
+ ]
959
+
960
+ results = []
961
+
962
+ for name, benchmark_func in benchmarks:
963
+ print(f"\n▶️ {name}...")
964
+ try:
965
+ result = benchmark_func()
966
+ results.append((name, result))
967
+ print(f" Time: {result['time']:.3f}s")
968
+ print(f" Ops/sec: {result.get('ops_per_sec', 'N/A')}")
969
+ except Exception as e:
970
+ print(f" ❌ Failed: {e}")
971
+ results.append((name, {"error": str(e)}))
972
+
973
+ # Summary
974
+ print("\n📊 Benchmark Summary:")
975
+ print("=" * 60)
976
+ for name, result in results:
977
+ if "error" in result:
978
+ print(f"{name}: ❌ Failed")
979
+ else:
980
+ print(f"{name}: {result['time']:.3f}s")
981
+
982
+ else:
983
+ # Default: show system performance
984
+ print("\n📊 System Performance:")
985
+
986
+ try:
987
+ import psutil
988
+ except ImportError:
989
+ print("⚠️ psutil not installed. Install with: pip install psutil")
990
+ return 0
991
+
992
+ # CPU info
993
+ print("\n🖥️ CPU:")
994
+ print(f" Usage: {psutil.cpu_percent(interval=1)}%")
995
+ print(
996
+ f" Cores: {psutil.cpu_count(logical=False)} physical, {psutil.cpu_count()} logical"
997
+ )
998
+
999
+ # Memory info
1000
+ mem = psutil.virtual_memory()
1001
+ print("\n💾 Memory:")
1002
+ print(f" Total: {mem.total/1024/1024/1024:.2f} GB")
1003
+ print(f" Used: {mem.used/1024/1024/1024:.2f} GB ({mem.percent}%)")
1004
+ print(f" Available: {mem.available/1024/1024/1024:.2f} GB")
1005
+
1006
+ # Disk info
1007
+ disk = psutil.disk_usage("/")
1008
+ print("\n💿 Disk:")
1009
+ print(f" Total: {disk.total/1024/1024/1024:.2f} GB")
1010
+ print(f" Used: {disk.used/1024/1024/1024:.2f} GB ({disk.percent}%)")
1011
+ print(f" Free: {disk.free/1024/1024/1024:.2f} GB")
1012
+
1013
+ # Process info
1014
+ process = psutil.Process()
1015
+ print("\n📦 Current Process:")
1016
+ print(f" PID: {process.pid}")
1017
+ print(f" Memory: {process.memory_info().rss/1024/1024:.2f} MB")
1018
+ print(f" CPU: {process.cpu_percent()}%")
1019
+ print(f" Threads: {process.num_threads()}")
1020
+
1021
+ return 0
1022
+
1023
+ except Exception as e:
1024
+ logger.error(f"Failed to run performance analysis: {e}", exc_info=True)
1025
+ return 1
1026
+
1027
+
1028
+ # Helper functions for profiling
1029
+ def _profile_agent_load():
1030
+ """Profile agent loading operation."""
1031
+ from ...services.agents.deployment import AgentDeploymentService
1032
+
1033
+ service = AgentDeploymentService()
1034
+ # Simulate loading agents
1035
+ for _ in range(10):
1036
+ with contextlib.suppress(Exception):
1037
+ service.list_agents()
1038
+
1039
+
1040
+ def _profile_service_init():
1041
+ """Profile service initialization."""
1042
+ from ...core.container import DIContainer
1043
+
1044
+ container = DIContainer()
1045
+ # Register and resolve services
1046
+
1047
+ class TestService:
1048
+ pass
1049
+
1050
+ for i in range(20):
1051
+ container.register(f"TestService{i}", TestService)
1052
+ container.resolve(f"TestService{i}")
1053
+
1054
+
1055
+ def _profile_cache_operations():
1056
+ """Profile cache operations."""
1057
+ from ...services.core.cache_manager import CacheManager
1058
+
1059
+ cache = CacheManager()
1060
+
1061
+ # Simulate cache operations
1062
+ for i in range(100):
1063
+ cache.set_capabilities(f"test_cap_{i}")
1064
+ cache.get_capabilities()
1065
+ cache.invalidate_capabilities()
1066
+
1067
+
1068
+ def _profile_memory_operations():
1069
+ """Profile memory operations."""
1070
+ from ...services.agents.memory import AgentMemoryManager
1071
+
1072
+ memory = AgentMemoryManager("test_agent")
1073
+
1074
+ # Simulate memory operations
1075
+ for i in range(50):
1076
+ try:
1077
+ memory.add_memory(f"category_{i}", {"data": f"test_{i}"})
1078
+ memory.get_memories()
1079
+ except:
1080
+ pass
1081
+
1082
+
1083
+ # Helper functions for benchmarking
1084
+ def _benchmark_service_resolution() -> Dict[str, Any]:
1085
+ """Benchmark service container resolution."""
1086
+ from ...core.container import DIContainer
1087
+
1088
+ container = DIContainer()
1089
+
1090
+ class TestService:
1091
+ pass
1092
+
1093
+ container.register(TestService, TestService)
1094
+
1095
+ iterations = 1000
1096
+ start = time.time()
1097
+
1098
+ for _ in range(iterations):
1099
+ container.resolve(TestService)
1100
+
1101
+ elapsed = time.time() - start
1102
+
1103
+ return {
1104
+ "time": elapsed,
1105
+ "iterations": iterations,
1106
+ "ops_per_sec": iterations / elapsed,
1107
+ }
1108
+
1109
+
1110
+ def _benchmark_cache_operations() -> Dict[str, Any]:
1111
+ """Benchmark cache operations."""
1112
+ from ...services.core.cache_manager import CacheManager
1113
+
1114
+ cache = CacheManager()
1115
+ iterations = 1000
1116
+
1117
+ start = time.time()
1118
+
1119
+ for i in range(iterations):
1120
+ cache.set_capabilities(f"test_{i}")
1121
+ cache.get_capabilities()
1122
+
1123
+ elapsed = time.time() - start
1124
+
1125
+ return {
1126
+ "time": elapsed,
1127
+ "iterations": iterations * 2, # set + get
1128
+ "ops_per_sec": (iterations * 2) / elapsed,
1129
+ }
1130
+
1131
+
1132
+ def _benchmark_agent_loading() -> Dict[str, Any]:
1133
+ """Benchmark agent loading."""
1134
+ from pathlib import Path
1135
+
1136
+ iterations = 100
1137
+ start = time.time()
1138
+
1139
+ for _ in range(iterations):
1140
+ # Simulate agent discovery
1141
+ agent_dir = Path.home() / ".claude" / "agents"
1142
+ if agent_dir.exists():
1143
+ list(agent_dir.glob("*.md"))
1144
+
1145
+ elapsed = time.time() - start
1146
+
1147
+ return {
1148
+ "time": elapsed,
1149
+ "iterations": iterations,
1150
+ "ops_per_sec": iterations / elapsed,
1151
+ }
1152
+
1153
+
1154
+ def _benchmark_hook_execution() -> Dict[str, Any]:
1155
+ """Benchmark hook execution."""
1156
+ from ...hooks.base_hook import HookContext, HookResult, PreDelegationHook
1157
+
1158
+ class TestHook(PreDelegationHook):
1159
+ def execute(self, context: HookContext) -> HookResult:
1160
+ return HookResult(context=context)
1161
+
1162
+ hook = TestHook(name="test", priority=0)
1163
+ context = HookContext(agent_name="test", task="test", metadata={})
1164
+
1165
+ iterations = 1000
1166
+ start = time.time()
1167
+
1168
+ for _ in range(iterations):
1169
+ hook.execute(context)
1170
+
1171
+ elapsed = time.time() - start
1172
+
1173
+ return {
1174
+ "time": elapsed,
1175
+ "iterations": iterations,
1176
+ "ops_per_sec": iterations / elapsed,
1177
+ }
1178
+
1179
+
1180
+ def add_debug_parser(subparsers):
1181
+ """
1182
+ Add the debug subparser with debugging commands.
1183
+
1184
+ This function is called by the main parser to add debug commands.
1185
+
1186
+ Args:
1187
+ subparsers: The subparsers object from the main parser
1188
+
1189
+ Returns:
1190
+ The configured debug subparser
1191
+ """
1192
+
1193
+ # Main debug parser
1194
+ debug_parser = subparsers.add_parser(
1195
+ "debug",
1196
+ help="Development debugging tools",
1197
+ description="Tools for debugging and monitoring claude-mpm components",
1198
+ )
1199
+
1200
+ # Add debug subcommands
1201
+ debug_subparsers = debug_parser.add_subparsers(
1202
+ dest="debug_command", help="Debug commands", metavar="SUBCOMMAND"
1203
+ )
1204
+
1205
+ # SocketIO debugging
1206
+ socketio_parser = debug_subparsers.add_parser(
1207
+ "socketio",
1208
+ help="Debug SocketIO events in real-time",
1209
+ aliases=["events"],
1210
+ description="Professional SocketIO event monitoring and analysis tool",
1211
+ )
1212
+
1213
+ # Connection options
1214
+ socketio_parser.add_argument(
1215
+ "--host", default="localhost", help="SocketIO server host (default: localhost)"
1216
+ )
1217
+ socketio_parser.add_argument(
1218
+ "--port", type=int, default=8765, help="SocketIO server port (default: 8765)"
1219
+ )
1220
+
1221
+ # Display options
1222
+ display_group = socketio_parser.add_mutually_exclusive_group()
1223
+ display_group.add_argument(
1224
+ "--live",
1225
+ action="store_true",
1226
+ default=True,
1227
+ help="Live event monitoring (default)",
1228
+ )
1229
+ display_group.add_argument(
1230
+ "--summary", action="store_true", help="Show aggregated statistics and summary"
1231
+ )
1232
+ display_group.add_argument(
1233
+ "--raw", action="store_true", help="Display raw JSON output"
1234
+ )
1235
+ display_group.add_argument(
1236
+ "--pretty", action="store_true", help="Enhanced formatted output with colors"
1237
+ )
1238
+
1239
+ # Filtering
1240
+ socketio_parser.add_argument(
1241
+ "--filter",
1242
+ nargs="+",
1243
+ dest="filter_types",
1244
+ help="Filter specific event types (e.g., PreToolUse PostToolUse)",
1245
+ )
1246
+
1247
+ # Output options
1248
+ socketio_parser.add_argument(
1249
+ "--output", "-o", help="Save events to file (JSONL format)"
1250
+ )
1251
+ socketio_parser.add_argument(
1252
+ "--quiet",
1253
+ "-q",
1254
+ action="store_true",
1255
+ help="Suppress output except errors (useful with --output)",
1256
+ )
1257
+
1258
+ # Connection resilience
1259
+ socketio_parser.add_argument(
1260
+ "--max-reconnect",
1261
+ type=int,
1262
+ default=10,
1263
+ help="Maximum reconnection attempts (default: 10)",
1264
+ )
1265
+ socketio_parser.add_argument(
1266
+ "--reconnect-delay",
1267
+ type=float,
1268
+ default=1.0,
1269
+ help="Reconnection delay in seconds (default: 1.0)",
1270
+ )
1271
+
1272
+ # Connection debugging
1273
+ connections_parser = debug_subparsers.add_parser(
1274
+ "connections",
1275
+ help="Show active SocketIO server connections",
1276
+ description="Display information about active SocketIO servers and their status",
1277
+ )
1278
+ connections_parser.add_argument(
1279
+ "--verbose",
1280
+ "-v",
1281
+ action="store_true",
1282
+ help="Show detailed connection information",
1283
+ )
1284
+
1285
+ # Services debugging
1286
+ services_parser = debug_subparsers.add_parser(
1287
+ "services",
1288
+ help="Debug service container and dependencies",
1289
+ description="Inspect services, dependencies, and health status",
1290
+ )
1291
+ services_group = services_parser.add_mutually_exclusive_group()
1292
+ services_group.add_argument(
1293
+ "--list", action="store_true", help="List all registered services"
1294
+ )
1295
+ services_group.add_argument(
1296
+ "--status", action="store_true", help="Show service health status"
1297
+ )
1298
+ services_group.add_argument(
1299
+ "--dependencies", action="store_true", help="Show service dependency graph"
1300
+ )
1301
+ services_group.add_argument(
1302
+ "--trace",
1303
+ metavar="SERVICE",
1304
+ help="Trace service resolution for specific service",
1305
+ )
1306
+
1307
+ # Agents debugging
1308
+ agents_parser = debug_subparsers.add_parser(
1309
+ "agents",
1310
+ help="Debug deployed agents and memory",
1311
+ description="Inspect deployed agents, memory, and traces",
1312
+ )
1313
+ agents_group = agents_parser.add_mutually_exclusive_group()
1314
+ agents_group.add_argument(
1315
+ "--deployed", action="store_true", help="List all deployed agents"
1316
+ )
1317
+ agents_group.add_argument(
1318
+ "--memory", action="store_true", help="Show agent memory status"
1319
+ )
1320
+ agents_group.add_argument(
1321
+ "--trace", metavar="AGENT", help="Trace specific agent execution"
1322
+ )
1323
+ agents_parser.add_argument(
1324
+ "--verbose", "-v", action="store_true", help="Show detailed information"
1325
+ )
1326
+
1327
+ # Hooks debugging
1328
+ hooks_parser = debug_subparsers.add_parser(
1329
+ "hooks",
1330
+ help="Debug hook system",
1331
+ description="List hooks, trace execution, analyze performance",
1332
+ )
1333
+ hooks_group = hooks_parser.add_mutually_exclusive_group()
1334
+ hooks_group.add_argument(
1335
+ "--list", action="store_true", help="List all registered hooks"
1336
+ )
1337
+ hooks_group.add_argument(
1338
+ "--trace", metavar="HOOK", help="Trace specific hook execution"
1339
+ )
1340
+ hooks_group.add_argument(
1341
+ "--performance", action="store_true", help="Analyze hook performance"
1342
+ )
1343
+ hooks_parser.add_argument(
1344
+ "--test", action="store_true", help="Run test execution when tracing"
1345
+ )
1346
+
1347
+ # Cache debugging
1348
+ cache_parser = debug_subparsers.add_parser(
1349
+ "cache",
1350
+ help="Debug cache system",
1351
+ description="Inspect, clear, and analyze cache",
1352
+ )
1353
+ cache_group = cache_parser.add_mutually_exclusive_group()
1354
+ cache_group.add_argument(
1355
+ "--inspect", action="store_true", help="Inspect cache contents"
1356
+ )
1357
+ cache_group.add_argument("--clear", action="store_true", help="Clear all cache")
1358
+ cache_group.add_argument(
1359
+ "--stats", action="store_true", help="Show cache performance statistics"
1360
+ )
1361
+ cache_parser.add_argument(
1362
+ "--verbose", "-v", action="store_true", help="Show detailed cache information"
1363
+ )
1364
+ cache_parser.add_argument(
1365
+ "--confirm",
1366
+ "-y",
1367
+ action="store_true",
1368
+ help="Skip confirmation for clear operation",
1369
+ )
1370
+
1371
+ # Performance debugging
1372
+ performance_parser = debug_subparsers.add_parser(
1373
+ "performance",
1374
+ help="Performance profiling and analysis",
1375
+ description="Profile operations and analyze bottlenecks",
1376
+ )
1377
+ perf_group = performance_parser.add_mutually_exclusive_group()
1378
+ perf_group.add_argument(
1379
+ "--profile",
1380
+ metavar="OPERATION",
1381
+ help="Profile specific operation (agent_load, service_init, cache_ops, memory_ops)",
1382
+ )
1383
+ perf_group.add_argument(
1384
+ "--benchmark", action="store_true", help="Run performance benchmarks"
1385
+ )
1386
+
1387
+ return debug_parser