claude-mpm 4.1.2__py3-none-any.whl → 4.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +16 -19
- claude_mpm/agents/MEMORY.md +21 -49
- claude_mpm/agents/templates/OPTIMIZATION_REPORT.md +156 -0
- claude_mpm/agents/templates/api_qa.json +36 -116
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +42 -9
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +29 -6
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +34 -6
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +41 -9
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +30 -8
- claude_mpm/agents/templates/backup/research_agent_2025011_234551.json +2 -2
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +29 -6
- claude_mpm/agents/templates/backup/research_memory_efficient.json +2 -2
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +41 -9
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +23 -7
- claude_mpm/agents/templates/code_analyzer.json +18 -36
- claude_mpm/agents/templates/data_engineer.json +43 -14
- claude_mpm/agents/templates/documentation.json +55 -74
- claude_mpm/agents/templates/engineer.json +57 -40
- claude_mpm/agents/templates/imagemagick.json +7 -2
- claude_mpm/agents/templates/memory_manager.json +1 -1
- claude_mpm/agents/templates/ops.json +36 -4
- claude_mpm/agents/templates/project_organizer.json +23 -71
- claude_mpm/agents/templates/qa.json +34 -2
- claude_mpm/agents/templates/refactoring_engineer.json +9 -5
- claude_mpm/agents/templates/research.json +36 -4
- claude_mpm/agents/templates/security.json +29 -2
- claude_mpm/agents/templates/ticketing.json +3 -3
- claude_mpm/agents/templates/vercel_ops_agent.json +2 -2
- claude_mpm/agents/templates/version_control.json +28 -2
- claude_mpm/agents/templates/web_qa.json +38 -151
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/commands/agent_manager.py +221 -1
- claude_mpm/cli/commands/agents.py +556 -1009
- claude_mpm/cli/commands/memory.py +248 -927
- claude_mpm/cli/commands/run.py +139 -484
- claude_mpm/cli/parsers/agent_manager_parser.py +34 -0
- claude_mpm/cli/startup_logging.py +76 -0
- claude_mpm/core/agent_registry.py +6 -10
- claude_mpm/core/framework_loader.py +205 -595
- claude_mpm/core/log_manager.py +49 -1
- claude_mpm/core/logging_config.py +2 -4
- claude_mpm/hooks/claude_hooks/event_handlers.py +7 -117
- claude_mpm/hooks/claude_hooks/hook_handler.py +91 -755
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +42 -454
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +42 -508
- claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
- claude_mpm/services/agents/memory/memory_file_service.py +103 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
- claude_mpm/services/agents/registry/__init__.py +1 -1
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +407 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +589 -0
- claude_mpm/services/cli/dashboard_launcher.py +424 -0
- claude_mpm/services/cli/memory_crud_service.py +617 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/session_manager.py +513 -0
- claude_mpm/services/cli/socketio_manager.py +498 -0
- claude_mpm/services/cli/startup_checker.py +370 -0
- claude_mpm/services/core/cache_manager.py +311 -0
- claude_mpm/services/core/memory_manager.py +637 -0
- claude_mpm/services/core/path_resolver.py +498 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +65 -19
- claude_mpm/services/memory/router.py +116 -10
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/METADATA +1 -1
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/RECORD +86 -55
- claude_mpm/cli/commands/run_config_checker.py +0 -159
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/top_level.txt +0 -0
claude_mpm/core/log_manager.py
CHANGED
|
@@ -179,6 +179,11 @@ class LogManager:
|
|
|
179
179
|
# Add to cache
|
|
180
180
|
self._dir_cache[log_type] = log_dir
|
|
181
181
|
|
|
182
|
+
# One-time migration for MPM logs from old location to new subdirectory
|
|
183
|
+
if log_type == "mpm" and not hasattr(self, "_mpm_logs_migrated"):
|
|
184
|
+
await self._migrate_mpm_logs()
|
|
185
|
+
self._mpm_logs_migrated = True
|
|
186
|
+
|
|
182
187
|
# Schedule cleanup for old logs
|
|
183
188
|
await self.cleanup_old_logs(
|
|
184
189
|
log_dir,
|
|
@@ -206,7 +211,7 @@ class LogManager:
|
|
|
206
211
|
# Map log types to directory names
|
|
207
212
|
dir_mapping = {
|
|
208
213
|
"startup": "startup",
|
|
209
|
-
"mpm": "", #
|
|
214
|
+
"mpm": "mpm", # MPM logs in dedicated subdirectory
|
|
210
215
|
"prompts": "prompts",
|
|
211
216
|
"sessions": "sessions",
|
|
212
217
|
"agents": "agents",
|
|
@@ -343,6 +348,49 @@ class LogManager:
|
|
|
343
348
|
|
|
344
349
|
return deleted_count
|
|
345
350
|
|
|
351
|
+
async def _migrate_mpm_logs(self):
|
|
352
|
+
"""
|
|
353
|
+
One-time migration to move existing MPM logs to new subdirectory.
|
|
354
|
+
|
|
355
|
+
Moves mpm_*.log files from .claude-mpm/logs/ to .claude-mpm/logs/mpm/
|
|
356
|
+
"""
|
|
357
|
+
try:
|
|
358
|
+
old_location = self.base_log_dir
|
|
359
|
+
new_location = self.base_log_dir / "mpm"
|
|
360
|
+
|
|
361
|
+
# Only proceed if old location exists and has MPM logs
|
|
362
|
+
if not old_location.exists():
|
|
363
|
+
return
|
|
364
|
+
|
|
365
|
+
# Find all MPM log files in the old location
|
|
366
|
+
mpm_logs = list(old_location.glob("mpm_*.log"))
|
|
367
|
+
|
|
368
|
+
if not mpm_logs:
|
|
369
|
+
return # No logs to migrate
|
|
370
|
+
|
|
371
|
+
# Ensure new directory exists
|
|
372
|
+
new_location.mkdir(parents=True, exist_ok=True)
|
|
373
|
+
|
|
374
|
+
migrated_count = 0
|
|
375
|
+
for log_file in mpm_logs:
|
|
376
|
+
try:
|
|
377
|
+
# Move file to new location
|
|
378
|
+
new_path = new_location / log_file.name
|
|
379
|
+
if not new_path.exists(): # Don't overwrite existing files
|
|
380
|
+
log_file.rename(new_path)
|
|
381
|
+
migrated_count += 1
|
|
382
|
+
except Exception as e:
|
|
383
|
+
logger.debug(f"Could not migrate {log_file}: {e}")
|
|
384
|
+
|
|
385
|
+
if migrated_count > 0:
|
|
386
|
+
logger.info(
|
|
387
|
+
f"Migrated {migrated_count} MPM log files to {new_location}"
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
except Exception as e:
|
|
391
|
+
# Migration is best-effort, don't fail if something goes wrong
|
|
392
|
+
logger.debug(f"MPM log migration skipped: {e}")
|
|
393
|
+
|
|
346
394
|
async def log_prompt(
|
|
347
395
|
self, prompt_type: str, content: str, metadata: Optional[Dict[str, Any]] = None
|
|
348
396
|
) -> Optional[Path]:
|
|
@@ -27,13 +27,11 @@ from typing import Any, Dict, Optional, Union
|
|
|
27
27
|
from claude_mpm.core.logger import (
|
|
28
28
|
JsonFormatter,
|
|
29
29
|
finalize_streaming_logs,
|
|
30
|
-
|
|
31
|
-
from claude_mpm.core.logger import get_logger as _get_logger
|
|
32
|
-
from claude_mpm.core.logger import (
|
|
30
|
+
get_logger as _get_logger,
|
|
33
31
|
log_async_performance,
|
|
34
32
|
log_performance,
|
|
33
|
+
setup_logging as _setup_logging,
|
|
35
34
|
)
|
|
36
|
-
from claude_mpm.core.logger import setup_logging as _setup_logging
|
|
37
35
|
|
|
38
36
|
# Standard log format for consistency
|
|
39
37
|
STANDARD_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
@@ -5,7 +5,6 @@ This module provides individual event handlers for different types of
|
|
|
5
5
|
Claude Code hook events.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import json
|
|
9
8
|
import os
|
|
10
9
|
import re
|
|
11
10
|
import subprocess
|
|
@@ -544,122 +543,13 @@ class EventHandlers:
|
|
|
544
543
|
self.hook_handler._emit_socketio_event("", "stop", stop_data)
|
|
545
544
|
|
|
546
545
|
def handle_subagent_stop_fast(self, event):
|
|
547
|
-
"""Handle subagent stop events
|
|
548
|
-
#
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
)
|
|
555
|
-
print(f" - event keys: {list(event.keys())}", file=sys.stderr)
|
|
556
|
-
print(
|
|
557
|
-
f" - delegation_requests size: {len(self.hook_handler.delegation_requests)}",
|
|
558
|
-
file=sys.stderr,
|
|
559
|
-
)
|
|
560
|
-
|
|
561
|
-
# First try to get agent type from our tracking
|
|
562
|
-
agent_type = (
|
|
563
|
-
self.hook_handler._get_delegation_agent_type(session_id)
|
|
564
|
-
if session_id
|
|
565
|
-
else "unknown"
|
|
566
|
-
)
|
|
567
|
-
|
|
568
|
-
# Fall back to event data if tracking didn't have it
|
|
569
|
-
if agent_type == "unknown":
|
|
570
|
-
agent_type = event.get("agent_type", event.get("subagent_type", "unknown"))
|
|
571
|
-
|
|
572
|
-
agent_id = event.get("agent_id", event.get("subagent_id", ""))
|
|
573
|
-
reason = event.get("reason", event.get("stop_reason", "unknown"))
|
|
574
|
-
|
|
575
|
-
# Try to infer agent type from other fields if still unknown
|
|
576
|
-
if agent_type == "unknown" and "task" in event:
|
|
577
|
-
task_desc = str(event.get("task", "")).lower()
|
|
578
|
-
if "research" in task_desc:
|
|
579
|
-
agent_type = "research"
|
|
580
|
-
elif "engineer" in task_desc or "code" in task_desc:
|
|
581
|
-
agent_type = "engineer"
|
|
582
|
-
elif "pm" in task_desc or "project" in task_desc:
|
|
583
|
-
agent_type = "pm"
|
|
584
|
-
|
|
585
|
-
# Always log SubagentStop events for debugging
|
|
586
|
-
if DEBUG or agent_type != "unknown":
|
|
587
|
-
print(
|
|
588
|
-
f"Hook handler: Processing SubagentStop - agent: '{agent_type}', session: '{session_id}', reason: '{reason}'",
|
|
589
|
-
file=sys.stderr,
|
|
590
|
-
)
|
|
591
|
-
|
|
592
|
-
# Get working directory and git branch
|
|
593
|
-
working_dir = event.get("cwd", "")
|
|
594
|
-
git_branch = self._get_git_branch(working_dir) if working_dir else "Unknown"
|
|
595
|
-
|
|
596
|
-
# Try to extract structured response from output if available
|
|
597
|
-
output = event.get("output", "")
|
|
598
|
-
structured_response = None
|
|
599
|
-
if output:
|
|
600
|
-
try:
|
|
601
|
-
json_match = re.search(
|
|
602
|
-
r"```json\s*(\{.*?\})\s*```", str(output), re.DOTALL
|
|
603
|
-
)
|
|
604
|
-
if json_match:
|
|
605
|
-
structured_response = json.loads(json_match.group(1))
|
|
606
|
-
if DEBUG:
|
|
607
|
-
print(
|
|
608
|
-
f"Extracted structured response from {agent_type} agent in SubagentStop",
|
|
609
|
-
file=sys.stderr,
|
|
610
|
-
)
|
|
611
|
-
except (json.JSONDecodeError, AttributeError):
|
|
612
|
-
pass # No structured response, that's okay
|
|
613
|
-
|
|
614
|
-
# Handle response tracking with fuzzy matching
|
|
615
|
-
self._handle_subagent_response_tracking(
|
|
616
|
-
session_id,
|
|
617
|
-
agent_type,
|
|
618
|
-
reason,
|
|
619
|
-
output,
|
|
620
|
-
structured_response,
|
|
621
|
-
working_dir,
|
|
622
|
-
git_branch,
|
|
623
|
-
)
|
|
624
|
-
|
|
625
|
-
# Prepare subagent stop data
|
|
626
|
-
subagent_stop_data = {
|
|
627
|
-
"agent_type": agent_type,
|
|
628
|
-
"agent_id": agent_id,
|
|
629
|
-
"reason": reason,
|
|
630
|
-
"session_id": session_id,
|
|
631
|
-
"working_directory": working_dir,
|
|
632
|
-
"git_branch": git_branch,
|
|
633
|
-
"timestamp": datetime.now().isoformat(),
|
|
634
|
-
"is_successful_completion": reason in ["completed", "finished", "done"],
|
|
635
|
-
"is_error_termination": reason in ["error", "timeout", "failed", "blocked"],
|
|
636
|
-
"is_delegation_related": agent_type
|
|
637
|
-
in ["research", "engineer", "pm", "ops", "qa", "documentation", "security"],
|
|
638
|
-
"has_results": bool(event.get("results") or event.get("output")),
|
|
639
|
-
"duration_context": event.get("duration_ms"),
|
|
640
|
-
"hook_event_name": "SubagentStop", # Explicitly set for dashboard
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
# Add structured response data if available
|
|
644
|
-
if structured_response:
|
|
645
|
-
subagent_stop_data["structured_response"] = {
|
|
646
|
-
"task_completed": structured_response.get("task_completed", False),
|
|
647
|
-
"instructions": structured_response.get("instructions", ""),
|
|
648
|
-
"results": structured_response.get("results", ""),
|
|
649
|
-
"files_modified": structured_response.get("files_modified", []),
|
|
650
|
-
"tools_used": structured_response.get("tools_used", []),
|
|
651
|
-
"remember": structured_response.get("remember"),
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
# Debug log the processed data
|
|
655
|
-
if DEBUG:
|
|
656
|
-
print(
|
|
657
|
-
f"SubagentStop processed data: agent_type='{agent_type}', session_id='{session_id}'",
|
|
658
|
-
file=sys.stderr,
|
|
659
|
-
)
|
|
660
|
-
|
|
661
|
-
# Emit normalized event with high priority
|
|
662
|
-
self.hook_handler._emit_socketio_event("", "subagent_stop", subagent_stop_data)
|
|
546
|
+
"""Handle subagent stop events by delegating to the specialized processor."""
|
|
547
|
+
# Delegate to the specialized subagent processor
|
|
548
|
+
if hasattr(self.hook_handler, "subagent_processor"):
|
|
549
|
+
self.hook_handler.subagent_processor.process_subagent_stop(event)
|
|
550
|
+
else:
|
|
551
|
+
# Fallback to handle_subagent_stop if processor not available
|
|
552
|
+
self.hook_handler.handle_subagent_stop(event)
|
|
663
553
|
|
|
664
554
|
def _handle_subagent_response_tracking(
|
|
665
555
|
self,
|