claude-mpm 5.1.9__py3-none-any.whl → 5.4.48__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +4 -0
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +1 -1
- claude_mpm/agents/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +843 -900
- claude_mpm/agents/WORKFLOW.md +5 -254
- claude_mpm/agents/agent_loader.py +13 -44
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/frontmatter_validator.py +2 -2
- claude_mpm/agents/templates/circuit-breakers.md +138 -1
- claude_mpm/cli/__main__.py +4 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/agent_state_manager.py +18 -27
- claude_mpm/cli/commands/agents.py +9 -40
- claude_mpm/cli/commands/auto_configure.py +210 -25
- claude_mpm/cli/commands/config.py +88 -2
- claude_mpm/cli/commands/configure.py +1098 -159
- claude_mpm/cli/commands/configure_agent_display.py +25 -6
- claude_mpm/cli/commands/mpm_init/core.py +225 -46
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
- claude_mpm/cli/commands/postmortem.py +1 -1
- claude_mpm/cli/commands/profile.py +277 -0
- claude_mpm/cli/commands/skills.py +218 -197
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/executor.py +21 -3
- claude_mpm/cli/interactive/agent_wizard.py +2 -2
- claude_mpm/cli/parsers/agents_parser.py +0 -9
- claude_mpm/cli/parsers/auto_configure_parser.py +0 -138
- claude_mpm/cli/parsers/base_parser.py +12 -0
- claude_mpm/cli/parsers/config_parser.py +153 -83
- claude_mpm/cli/parsers/profile_parser.py +148 -0
- claude_mpm/cli/parsers/skills_parser.py +0 -5
- claude_mpm/cli/startup.py +876 -149
- claude_mpm/commands/mpm-config.md +28 -0
- claude_mpm/commands/mpm-doctor.md +9 -22
- claude_mpm/commands/mpm-help.md +5 -287
- claude_mpm/commands/mpm-init.md +81 -507
- claude_mpm/commands/mpm-monitor.md +15 -402
- claude_mpm/commands/mpm-organize.md +120 -0
- claude_mpm/commands/mpm-postmortem.md +6 -108
- claude_mpm/commands/mpm-session-resume.md +12 -363
- claude_mpm/commands/mpm-status.md +5 -69
- claude_mpm/commands/mpm-ticket-view.md +52 -495
- claude_mpm/commands/mpm-version.md +5 -107
- claude_mpm/config/agent_sources.py +27 -0
- claude_mpm/core/config.py +2 -4
- claude_mpm/core/framework/formatters/content_formatter.py +3 -13
- claude_mpm/core/framework/loaders/agent_loader.py +8 -5
- claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
- claude_mpm/core/framework_loader.py +4 -2
- claude_mpm/core/logger.py +13 -0
- claude_mpm/core/optimized_startup.py +59 -0
- claude_mpm/core/shared/config_loader.py +1 -1
- claude_mpm/core/socketio_pool.py +3 -3
- claude_mpm/core/unified_agent_registry.py +5 -15
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
- claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
- claude_mpm/hooks/claude_hooks/installer.py +33 -10
- claude_mpm/hooks/claude_hooks/memory_integration.py +26 -9
- claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +30 -6
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/memory_integration_hook.py +46 -1
- claude_mpm/init.py +63 -19
- claude_mpm/models/git_repository.py +3 -3
- claude_mpm/scripts/claude-hook-handler.sh +58 -18
- claude_mpm/scripts/launch_monitor.py +93 -13
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/cache_git_manager.py +6 -6
- claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -5
- claude_mpm/services/agents/deployment/agent_format_converter.py +23 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +32 -20
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +247 -35
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +392 -87
- claude_mpm/services/agents/git_source_manager.py +53 -4
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
- claude_mpm/services/agents/sources/git_source_sync_service.py +120 -7
- claude_mpm/services/agents/startup_sync.py +22 -2
- claude_mpm/services/agents/toolchain_detector.py +10 -6
- claude_mpm/services/analysis/__init__.py +11 -1
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/command_deployment_service.py +81 -10
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
- claude_mpm/services/event_bus/config.py +3 -1
- claude_mpm/services/git/git_operations_service.py +101 -16
- claude_mpm/services/monitor/daemon.py +9 -2
- claude_mpm/services/monitor/daemon_manager.py +39 -3
- claude_mpm/services/monitor/management/lifecycle.py +8 -1
- claude_mpm/services/monitor/server.py +698 -22
- claude_mpm/services/pm_skills_deployer.py +711 -0
- claude_mpm/services/profile_manager.py +331 -0
- claude_mpm/services/self_upgrade_service.py +120 -12
- claude_mpm/services/skills/__init__.py +3 -0
- claude_mpm/services/skills/git_skill_source_manager.py +130 -2
- claude_mpm/services/skills/selective_skill_deployer.py +704 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_deployer.py +127 -9
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +51 -6
- claude_mpm/services/socketio/server/core.py +386 -108
- claude_mpm/services/version_control/git_operations.py +103 -0
- claude_mpm/skills/skill_manager.py +92 -3
- claude_mpm/utils/agent_dependency_loader.py +14 -2
- claude_mpm/utils/agent_filters.py +17 -44
- claude_mpm/utils/migration.py +4 -4
- claude_mpm/utils/robust_installer.py +47 -3
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.48.dist-info}/METADATA +53 -87
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.48.dist-info}/RECORD +157 -197
- claude_mpm-5.4.48.dist-info/entry_points.txt +5 -0
- claude_mpm-5.4.48.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.48.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
- claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
- claude_mpm/agents/BASE_OPS.md +0 -219
- claude_mpm/agents/BASE_PM.md +0 -480
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
- claude_mpm/agents/BASE_QA.md +0 -167
- claude_mpm/agents/BASE_RESEARCH.md +0 -53
- claude_mpm/agents/base_agent_loader.py +0 -601
- claude_mpm/cli/commands/agents_detect.py +0 -380
- claude_mpm/cli/commands/agents_recommend.py +0 -309
- claude_mpm/cli/ticket_cli.py +0 -35
- claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
- claude_mpm/commands/mpm-agents-detect.md +0 -177
- claude_mpm/commands/mpm-agents-list.md +0 -131
- claude_mpm/commands/mpm-agents-recommend.md +0 -223
- claude_mpm/commands/mpm-config-view.md +0 -150
- claude_mpm/commands/mpm-ticket-organize.md +0 -304
- claude_mpm/dashboard/analysis_runner.py +0 -455
- claude_mpm/dashboard/index.html +0 -13
- claude_mpm/dashboard/open_dashboard.py +0 -66
- claude_mpm/dashboard/static/css/activity.css +0 -1958
- claude_mpm/dashboard/static/css/connection-status.css +0 -370
- claude_mpm/dashboard/static/css/dashboard.css +0 -4701
- claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
- claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
- claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
- claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
- claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
- claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
- claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
- claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
- claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
- claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
- claude_mpm/dashboard/static/js/connection-manager.js +0 -536
- claude_mpm/dashboard/static/js/dashboard.js +0 -1914
- claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/js/socket-client.js +0 -1474
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/socket.io.min.js +0 -7
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
- claude_mpm/dashboard/templates/code_simple.html +0 -153
- claude_mpm/dashboard/templates/index.html +0 -606
- claude_mpm/dashboard/test_dashboard.html +0 -372
- claude_mpm/scripts/mcp_server.py +0 -75
- claude_mpm/scripts/mcp_wrapper.py +0 -39
- claude_mpm/services/mcp_gateway/__init__.py +0 -159
- claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
- claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
- claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
- claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
- claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
- claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
- claude_mpm/services/mcp_gateway/core/base.py +0 -312
- claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
- claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
- claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
- claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
- claude_mpm/services/mcp_gateway/main.py +0 -589
- claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
- claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
- claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
- claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
- claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
- claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
- claude_mpm-5.1.9.dist-info/entry_points.txt +0 -10
- claude_mpm-5.1.9.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.48.dist-info}/WHEEL +0 -0
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.48.dist-info}/top_level.txt +0 -0
|
@@ -50,10 +50,10 @@ class GitSourceManager:
|
|
|
50
50
|
|
|
51
51
|
Args:
|
|
52
52
|
cache_root: Root directory for repository caches.
|
|
53
|
-
Defaults to ~/.claude-mpm/cache/
|
|
53
|
+
Defaults to ~/.claude-mpm/cache/agents/
|
|
54
54
|
"""
|
|
55
55
|
if cache_root is None:
|
|
56
|
-
cache_root = Path.home() / ".claude-mpm" / "cache" / "
|
|
56
|
+
cache_root = Path.home() / ".claude-mpm" / "cache" / "agents"
|
|
57
57
|
|
|
58
58
|
self.cache_root = cache_root
|
|
59
59
|
self.cache_root.mkdir(parents=True, exist_ok=True)
|
|
@@ -339,14 +339,48 @@ class GitSourceManager:
|
|
|
339
339
|
|
|
340
340
|
# Walk cache directory structure
|
|
341
341
|
logger.debug(f"[DEBUG] Walking cache root: {self.cache_root}")
|
|
342
|
+
|
|
343
|
+
# Known legacy category directories to skip (flat cache structure)
|
|
344
|
+
LEGACY_CATEGORIES = {
|
|
345
|
+
"universal",
|
|
346
|
+
"engineer",
|
|
347
|
+
"ops",
|
|
348
|
+
"qa",
|
|
349
|
+
"security",
|
|
350
|
+
"documentation",
|
|
351
|
+
"claude-mpm",
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
# Repositories that are NOT agent repositories (should be excluded from agent discovery)
|
|
355
|
+
# These contain skills, documentation, or other non-agent content
|
|
356
|
+
EXCLUDED_REPOSITORIES = {
|
|
357
|
+
"claude-mpm-skills", # Skills repository, not agents
|
|
358
|
+
}
|
|
359
|
+
|
|
342
360
|
for owner_dir in self.cache_root.iterdir():
|
|
343
361
|
if not owner_dir.is_dir():
|
|
344
362
|
continue
|
|
363
|
+
|
|
364
|
+
# Skip legacy category directories (they're not GitHub owners)
|
|
365
|
+
if owner_dir.name.lower() in LEGACY_CATEGORIES:
|
|
366
|
+
logger.debug(
|
|
367
|
+
f"[DEBUG] Skipping legacy category directory: {owner_dir.name}"
|
|
368
|
+
)
|
|
369
|
+
continue
|
|
370
|
+
|
|
345
371
|
logger.debug(f"[DEBUG] Processing owner_dir: {owner_dir.name}")
|
|
346
372
|
|
|
347
373
|
for repo_dir in owner_dir.iterdir():
|
|
348
374
|
if not repo_dir.is_dir():
|
|
349
375
|
continue
|
|
376
|
+
|
|
377
|
+
# Skip excluded repositories (e.g., skills repos are not agent repos)
|
|
378
|
+
if repo_dir.name in EXCLUDED_REPOSITORIES:
|
|
379
|
+
logger.debug(
|
|
380
|
+
f"[DEBUG] Skipping excluded repository: {repo_dir.name}"
|
|
381
|
+
)
|
|
382
|
+
continue
|
|
383
|
+
|
|
350
384
|
logger.debug(f"[DEBUG] Processing repo_dir: {repo_dir.name}")
|
|
351
385
|
|
|
352
386
|
# Bug #5 fix: Don't iterate subdirectories - RemoteAgentDiscoveryService
|
|
@@ -361,8 +395,23 @@ class GitSourceManager:
|
|
|
361
395
|
)
|
|
362
396
|
logger.debug(f"[DEBUG] Found {len(agents)} agents so far")
|
|
363
397
|
|
|
364
|
-
logger.debug(f"[DEBUG] list_cached_agents COMPLETE: {len(agents)} total agents")
|
|
365
|
-
|
|
398
|
+
logger.debug(f"[DEBUG] list_cached_agents COMPLETE: {len(agents)} total agents (before deduplication)")
|
|
399
|
+
|
|
400
|
+
# Deduplicate agents by agent_id (Bug #2 fix)
|
|
401
|
+
# When same agent exists in multiple locations, keep only first occurrence
|
|
402
|
+
seen_ids = set()
|
|
403
|
+
deduplicated_agents = []
|
|
404
|
+
|
|
405
|
+
for agent in agents:
|
|
406
|
+
agent_id = agent.get("agent_id") or agent.get("metadata", {}).get("name")
|
|
407
|
+
if agent_id and agent_id not in seen_ids:
|
|
408
|
+
seen_ids.add(agent_id)
|
|
409
|
+
deduplicated_agents.append(agent)
|
|
410
|
+
elif agent_id:
|
|
411
|
+
logger.debug(f"[DEBUG] Skipping duplicate agent: {agent_id}")
|
|
412
|
+
|
|
413
|
+
logger.debug(f"[DEBUG] After deduplication: {len(deduplicated_agents)} unique agents")
|
|
414
|
+
return deduplicated_agents
|
|
366
415
|
|
|
367
416
|
def _discover_agents_in_directory(
|
|
368
417
|
self,
|
|
@@ -13,9 +13,6 @@ from enum import Enum
|
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from typing import Any, Dict, List, Optional
|
|
15
15
|
|
|
16
|
-
# Lazy import for base_agent_loader to reduce initialization overhead
|
|
17
|
-
# base_agent_loader adds ~500ms to import time
|
|
18
|
-
# from claude_mpm.agents.base_agent_loader import clear_base_agent_cache
|
|
19
16
|
from claude_mpm.core.logging_utils import get_logger
|
|
20
17
|
from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
|
|
21
18
|
from claude_mpm.services.shared import ConfigServiceBase
|
|
@@ -23,13 +20,6 @@ from claude_mpm.services.shared import ConfigServiceBase
|
|
|
23
20
|
logger = get_logger(__name__)
|
|
24
21
|
|
|
25
22
|
|
|
26
|
-
def _get_clear_base_agent_cache():
|
|
27
|
-
"""Lazy loader for clear_base_agent_cache function."""
|
|
28
|
-
from claude_mpm.agents.base_agent_loader import clear_base_agent_cache
|
|
29
|
-
|
|
30
|
-
return clear_base_agent_cache
|
|
31
|
-
|
|
32
|
-
|
|
33
23
|
class BaseAgentSection(str, Enum):
|
|
34
24
|
"""Base agent markdown sections."""
|
|
35
25
|
|
|
@@ -143,9 +133,7 @@ class BaseAgentManager(ConfigServiceBase):
|
|
|
143
133
|
content = self._structure_to_markdown(current)
|
|
144
134
|
self.base_agent_path.write_text(content, encoding="utf-8")
|
|
145
135
|
|
|
146
|
-
# Clear
|
|
147
|
-
clear_base_agent_cache = _get_clear_base_agent_cache()
|
|
148
|
-
clear_base_agent_cache()
|
|
136
|
+
# Clear cache
|
|
149
137
|
self.cache.invalidate("base_agent:instructions")
|
|
150
138
|
|
|
151
139
|
logger.info("Base agent updated successfully")
|
|
@@ -226,9 +226,11 @@ class AgentRecommenderService(BaseService, IAgentRecommender):
|
|
|
226
226
|
if max_agents is not None:
|
|
227
227
|
recommendations = recommendations[:max_agents]
|
|
228
228
|
|
|
229
|
-
# Check if
|
|
230
|
-
if not recommendations
|
|
231
|
-
self.logger.info(
|
|
229
|
+
# Check if we have no recommendations (any reason: unknown language, low scores, etc.)
|
|
230
|
+
if not recommendations:
|
|
231
|
+
self.logger.info(
|
|
232
|
+
f"No agents scored above threshold for {toolchain.primary_language}; using defaults"
|
|
233
|
+
)
|
|
232
234
|
|
|
233
235
|
# Get default configuration
|
|
234
236
|
default_config = self._capabilities_config.get("default_configuration", {})
|
|
@@ -78,14 +78,14 @@ class SingleTierDeploymentService:
|
|
|
78
78
|
config: Agent source configuration with repositories
|
|
79
79
|
deployment_dir: Target deployment directory (.claude/agents/)
|
|
80
80
|
cache_root: Cache root for repositories
|
|
81
|
-
(defaults to ~/.claude-mpm/cache/
|
|
81
|
+
(defaults to ~/.claude-mpm/cache/agents/)
|
|
82
82
|
"""
|
|
83
83
|
self.config = config
|
|
84
84
|
self.deployment_dir = deployment_dir
|
|
85
85
|
self.deployment_dir.mkdir(parents=True, exist_ok=True)
|
|
86
86
|
|
|
87
87
|
if cache_root is None:
|
|
88
|
-
cache_root = Path.home() / ".claude-mpm" / "cache" / "
|
|
88
|
+
cache_root = Path.home() / ".claude-mpm" / "cache" / "agents"
|
|
89
89
|
|
|
90
90
|
self.cache_root = cache_root
|
|
91
91
|
self.git_source_manager = GitSourceManager(cache_root)
|
|
@@ -13,11 +13,16 @@ import logging
|
|
|
13
13
|
import time
|
|
14
14
|
from datetime import datetime, timezone
|
|
15
15
|
from pathlib import Path
|
|
16
|
-
from typing import Any, Dict, List, Optional, Tuple
|
|
16
|
+
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
17
17
|
|
|
18
18
|
import requests
|
|
19
19
|
|
|
20
20
|
from claude_mpm.core.file_utils import get_file_hash
|
|
21
|
+
|
|
22
|
+
# Import normalize function for exclusion filtering
|
|
23
|
+
from claude_mpm.services.agents.deployment.multi_source_deployment_service import (
|
|
24
|
+
_normalize_agent_name,
|
|
25
|
+
)
|
|
21
26
|
from claude_mpm.services.agents.sources.agent_sync_state import AgentSyncState
|
|
22
27
|
from claude_mpm.utils.progress import create_progress_bar
|
|
23
28
|
|
|
@@ -188,10 +193,10 @@ class GitSourceSyncService:
|
|
|
188
193
|
|
|
189
194
|
Args:
|
|
190
195
|
source_url: Base URL for raw files (without trailing slash)
|
|
191
|
-
cache_dir: Local cache directory (defaults to ~/.claude-mpm/cache/
|
|
196
|
+
cache_dir: Local cache directory (defaults to ~/.claude-mpm/cache/agents/)
|
|
192
197
|
source_id: Unique identifier for this source (for multi-source support)
|
|
193
198
|
|
|
194
|
-
Design Decision: Cache to ~/.claude-mpm/cache/
|
|
199
|
+
Design Decision: Cache to ~/.claude-mpm/cache/agents/ (canonical location)
|
|
195
200
|
|
|
196
201
|
Rationale: Separates cached repository structure from deployed agents.
|
|
197
202
|
This allows preserving nested directory structure in cache while
|
|
@@ -207,13 +212,13 @@ class GitSourceSyncService:
|
|
|
207
212
|
self.source_url = source_url.rstrip("/")
|
|
208
213
|
self.source_id = source_id
|
|
209
214
|
|
|
210
|
-
# Setup cache directory (canonical: ~/.claude-mpm/cache/
|
|
215
|
+
# Setup cache directory (canonical: ~/.claude-mpm/cache/agents/)
|
|
211
216
|
if cache_dir:
|
|
212
217
|
self.cache_dir = Path(cache_dir)
|
|
213
218
|
else:
|
|
214
|
-
# Default to ~/.claude-mpm/cache/
|
|
219
|
+
# Default to ~/.claude-mpm/cache/agents/ (canonical cache location)
|
|
215
220
|
home = Path.home()
|
|
216
|
-
self.cache_dir = home / ".claude-mpm" / "cache" / "
|
|
221
|
+
self.cache_dir = home / ".claude-mpm" / "cache" / "agents"
|
|
217
222
|
|
|
218
223
|
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
219
224
|
|
|
@@ -851,6 +856,12 @@ class GitSourceSyncService:
|
|
|
851
856
|
if base_path and not path.startswith(base_path + "/"):
|
|
852
857
|
continue
|
|
853
858
|
|
|
859
|
+
# Exclude build/dist directories (prevents double-counting)
|
|
860
|
+
# e.g., both "agents/engineer.md" and "dist/agents/engineer.md"
|
|
861
|
+
path_parts = path.split("/")
|
|
862
|
+
if any(excluded in path_parts for excluded in ["dist", "build", ".cache"]):
|
|
863
|
+
continue
|
|
864
|
+
|
|
854
865
|
# Remove base_path prefix for relative paths
|
|
855
866
|
if base_path:
|
|
856
867
|
relative_path = path[len(base_path) + 1 :]
|
|
@@ -917,6 +928,62 @@ class GitSourceSyncService:
|
|
|
917
928
|
"""
|
|
918
929
|
return self.cache_dir
|
|
919
930
|
|
|
931
|
+
def _cleanup_excluded_agents(
|
|
932
|
+
self,
|
|
933
|
+
deployment_dir: Path,
|
|
934
|
+
excluded_set: Set[str],
|
|
935
|
+
) -> Dict[str, List[str]]:
|
|
936
|
+
"""Remove excluded agents from deployment directory.
|
|
937
|
+
|
|
938
|
+
Removes any agents in the deployment directory whose normalized
|
|
939
|
+
names match the exclusion list. This ensures that excluded agents
|
|
940
|
+
are cleaned up from previous deployments.
|
|
941
|
+
|
|
942
|
+
Args:
|
|
943
|
+
deployment_dir: Directory containing deployed agents
|
|
944
|
+
excluded_set: Set of normalized agent names to exclude
|
|
945
|
+
|
|
946
|
+
Returns:
|
|
947
|
+
Dictionary with cleanup results:
|
|
948
|
+
- removed: List of agent names that were removed
|
|
949
|
+
"""
|
|
950
|
+
cleanup_results: Dict[str, List[str]] = {"removed": []}
|
|
951
|
+
|
|
952
|
+
if not deployment_dir.exists():
|
|
953
|
+
logger.debug("Deployment directory does not exist, no cleanup needed")
|
|
954
|
+
return cleanup_results
|
|
955
|
+
|
|
956
|
+
for item in deployment_dir.iterdir():
|
|
957
|
+
# Only process .md files
|
|
958
|
+
if not item.is_file() or item.suffix != ".md":
|
|
959
|
+
continue
|
|
960
|
+
|
|
961
|
+
# Skip hidden files
|
|
962
|
+
if item.name.startswith("."):
|
|
963
|
+
continue
|
|
964
|
+
|
|
965
|
+
# Normalize agent name for comparison
|
|
966
|
+
agent_name = _normalize_agent_name(item.stem)
|
|
967
|
+
|
|
968
|
+
# Check if this agent is excluded
|
|
969
|
+
if agent_name in excluded_set:
|
|
970
|
+
try:
|
|
971
|
+
item.unlink()
|
|
972
|
+
cleanup_results["removed"].append(item.stem)
|
|
973
|
+
logger.info(f"Removed excluded agent: {item.stem}")
|
|
974
|
+
except PermissionError as e:
|
|
975
|
+
logger.error(f"Permission denied removing {item.stem}: {e}")
|
|
976
|
+
except Exception as e:
|
|
977
|
+
logger.error(f"Failed to remove {item.stem}: {e}")
|
|
978
|
+
|
|
979
|
+
# Log summary
|
|
980
|
+
if cleanup_results["removed"]:
|
|
981
|
+
logger.info(
|
|
982
|
+
f"Cleanup complete: removed {len(cleanup_results['removed'])} excluded agents"
|
|
983
|
+
)
|
|
984
|
+
|
|
985
|
+
return cleanup_results
|
|
986
|
+
|
|
920
987
|
def deploy_agents_to_project(
|
|
921
988
|
self,
|
|
922
989
|
project_dir: Path,
|
|
@@ -971,7 +1038,10 @@ class GitSourceSyncService:
|
|
|
971
1038
|
"""
|
|
972
1039
|
import shutil
|
|
973
1040
|
|
|
974
|
-
|
|
1041
|
+
from claude_mpm.core.config import Config
|
|
1042
|
+
|
|
1043
|
+
# Deploy to .claude/agents/ where Claude Code expects them
|
|
1044
|
+
deployment_dir = project_dir / ".claude" / "agents"
|
|
975
1045
|
deployment_dir.mkdir(parents=True, exist_ok=True)
|
|
976
1046
|
|
|
977
1047
|
results = {
|
|
@@ -982,10 +1052,53 @@ class GitSourceSyncService:
|
|
|
982
1052
|
"deployment_dir": str(deployment_dir),
|
|
983
1053
|
}
|
|
984
1054
|
|
|
1055
|
+
# Load project config to get exclusion list
|
|
1056
|
+
config_file = project_dir / ".claude-mpm" / "configuration.yaml"
|
|
1057
|
+
if config_file.exists():
|
|
1058
|
+
config = Config(config_file=config_file)
|
|
1059
|
+
excluded_agents = config.get("excluded_agents", [])
|
|
1060
|
+
else:
|
|
1061
|
+
# No project config, no exclusions
|
|
1062
|
+
excluded_agents = []
|
|
1063
|
+
|
|
1064
|
+
# Create normalized exclusion set
|
|
1065
|
+
excluded_set: Set[str] = (
|
|
1066
|
+
{_normalize_agent_name(name) for name in excluded_agents}
|
|
1067
|
+
if excluded_agents
|
|
1068
|
+
else set()
|
|
1069
|
+
)
|
|
1070
|
+
|
|
1071
|
+
if excluded_set:
|
|
1072
|
+
logger.info(
|
|
1073
|
+
f"Applying exclusions: {', '.join(sorted(excluded_agents))} "
|
|
1074
|
+
f"(normalized: {', '.join(sorted(excluded_set))})"
|
|
1075
|
+
)
|
|
1076
|
+
|
|
985
1077
|
# Get agents from cache or use provided list
|
|
986
1078
|
if agent_list is None:
|
|
987
1079
|
agent_list = self._discover_cached_agents()
|
|
988
1080
|
|
|
1081
|
+
# Filter out excluded agents
|
|
1082
|
+
if excluded_set:
|
|
1083
|
+
original_count = len(agent_list)
|
|
1084
|
+
agent_list = [
|
|
1085
|
+
agent_path
|
|
1086
|
+
for agent_path in agent_list
|
|
1087
|
+
if _normalize_agent_name(Path(agent_path).stem) not in excluded_set
|
|
1088
|
+
]
|
|
1089
|
+
filtered_count = original_count - len(agent_list)
|
|
1090
|
+
if filtered_count > 0:
|
|
1091
|
+
logger.info(f"Filtered out {filtered_count} excluded agents")
|
|
1092
|
+
|
|
1093
|
+
# Clean up any previously deployed excluded agents
|
|
1094
|
+
if excluded_set:
|
|
1095
|
+
cleanup_results = self._cleanup_excluded_agents(deployment_dir, excluded_set)
|
|
1096
|
+
if cleanup_results["removed"]:
|
|
1097
|
+
logger.info(
|
|
1098
|
+
f"Cleaned up {len(cleanup_results['removed'])} excluded agents: "
|
|
1099
|
+
f"{', '.join(cleanup_results['removed'])}"
|
|
1100
|
+
)
|
|
1101
|
+
|
|
989
1102
|
logger.info(
|
|
990
1103
|
f"Deploying {len(agent_list)} agents from cache to {deployment_dir}"
|
|
991
1104
|
)
|
|
@@ -110,6 +110,26 @@ def sync_agents_on_startup(config: Optional[Dict[str, Any]] = None) -> Dict[str,
|
|
|
110
110
|
else:
|
|
111
111
|
cache_dir = None # Will use default
|
|
112
112
|
|
|
113
|
+
# Check for old cache directory names and provide migration guidance
|
|
114
|
+
# This handles users upgrading from older versions
|
|
115
|
+
old_cache_paths = [
|
|
116
|
+
Path.home() / ".claude-mpm" / "cache" / "remote-agents",
|
|
117
|
+
]
|
|
118
|
+
new_cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
|
|
119
|
+
|
|
120
|
+
for old_cache in old_cache_paths:
|
|
121
|
+
if old_cache.exists() and not new_cache_dir.exists():
|
|
122
|
+
logger.warning(f"Found old cache directory: {old_cache}")
|
|
123
|
+
logger.warning(
|
|
124
|
+
"The cache directory location has changed to: ~/.claude-mpm/cache/agents"
|
|
125
|
+
)
|
|
126
|
+
logger.warning("To migrate your existing cache, run:")
|
|
127
|
+
logger.warning(f" mv {old_cache} {new_cache_dir}")
|
|
128
|
+
logger.info(
|
|
129
|
+
"Agents will be re-synced to the new cache location automatically."
|
|
130
|
+
)
|
|
131
|
+
break # Only show warning once
|
|
132
|
+
|
|
113
133
|
# Sync each enabled source
|
|
114
134
|
for source_config in sources:
|
|
115
135
|
try:
|
|
@@ -217,7 +237,7 @@ def get_sync_status() -> Dict[str, Any]:
|
|
|
217
237
|
"enabled": agent_sync_config.get("enabled", True),
|
|
218
238
|
"sources_configured": len(enabled_sources),
|
|
219
239
|
"cache_dir": agent_sync_config.get(
|
|
220
|
-
"cache_dir", "~/.claude-mpm/cache/
|
|
240
|
+
"cache_dir", "~/.claude-mpm/cache/agents"
|
|
221
241
|
),
|
|
222
242
|
}
|
|
223
243
|
|
|
@@ -233,7 +253,7 @@ def get_sync_status() -> Dict[str, Any]:
|
|
|
233
253
|
return {
|
|
234
254
|
"enabled": False,
|
|
235
255
|
"sources_configured": 0,
|
|
236
|
-
"cache_dir": "~/.claude-mpm/cache/
|
|
256
|
+
"cache_dir": "~/.claude-mpm/cache/agents",
|
|
237
257
|
"last_sync": None,
|
|
238
258
|
"error": str(e),
|
|
239
259
|
}
|
|
@@ -158,12 +158,15 @@ class ToolchainDetector:
|
|
|
158
158
|
"make": ["ops"],
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
# Core agents always included
|
|
161
|
+
# Core agents always included (use exact agent IDs from repository)
|
|
162
162
|
CORE_AGENTS = [
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
-
"
|
|
163
|
+
"engineer",
|
|
164
|
+
"qa-agent",
|
|
165
|
+
"memory-manager-agent",
|
|
166
|
+
"local-ops-agent",
|
|
167
|
+
"research-agent",
|
|
168
|
+
"documentation-agent",
|
|
169
|
+
"security-agent",
|
|
167
170
|
]
|
|
168
171
|
|
|
169
172
|
# Directories to exclude from scanning
|
|
@@ -365,7 +368,8 @@ class ToolchainDetector:
|
|
|
365
368
|
"""Map detected toolchain to recommended agents.
|
|
366
369
|
|
|
367
370
|
Combines language-specific, framework-specific, and ops agents with
|
|
368
|
-
core agents (qa,
|
|
371
|
+
core agents (engineer, qa-agent, memory-manager-agent, local-ops-agent, research-agent,
|
|
372
|
+
documentation-agent, security-agent).
|
|
369
373
|
|
|
370
374
|
Args:
|
|
371
375
|
toolchain: Detected toolchain dictionary with languages, frameworks, tools
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Analysis services for Claude MPM.
|
|
3
3
|
|
|
4
|
-
Provides postmortem analysis
|
|
4
|
+
Provides postmortem analysis, error improvement suggestions, and code clone detection.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from .clone_detector import (
|
|
8
|
+
CloneDetector,
|
|
9
|
+
CloneReport,
|
|
10
|
+
RefactoringSuggestion,
|
|
11
|
+
SimilarityReport,
|
|
12
|
+
)
|
|
7
13
|
from .postmortem_service import (
|
|
8
14
|
ActionType,
|
|
9
15
|
ErrorAnalysis,
|
|
@@ -16,10 +22,14 @@ from .postmortem_service import (
|
|
|
16
22
|
|
|
17
23
|
__all__ = [
|
|
18
24
|
"ActionType",
|
|
25
|
+
"CloneDetector",
|
|
26
|
+
"CloneReport",
|
|
19
27
|
"ErrorAnalysis",
|
|
20
28
|
"ErrorCategory",
|
|
21
29
|
"ImprovementAction",
|
|
22
30
|
"PostmortemReport",
|
|
23
31
|
"PostmortemService",
|
|
32
|
+
"RefactoringSuggestion",
|
|
33
|
+
"SimilarityReport",
|
|
24
34
|
"get_postmortem_service",
|
|
25
35
|
]
|