claude-mpm 5.4.75__py3-none-any.whl → 5.4.81__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/cli/commands/configure.py +230 -19
- claude_mpm/cli/startup.py +7 -4
- claude_mpm/core/claude_runner.py +2 -2
- claude_mpm/core/interactive_session.py +7 -7
- claude_mpm/core/output_style_manager.py +7 -7
- claude_mpm/core/unified_config.py +16 -0
- claude_mpm/core/unified_paths.py +30 -13
- claude_mpm/services/agents/deployment/deployment_reconciler.py +39 -1
- claude_mpm/services/skills/git_skill_source_manager.py +5 -1
- claude_mpm/services/skills/selective_skill_deployer.py +0 -10
- {claude_mpm-5.4.75.dist-info → claude_mpm-5.4.81.dist-info}/METADATA +1 -1
- {claude_mpm-5.4.75.dist-info → claude_mpm-5.4.81.dist-info}/RECORD +18 -42
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.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__/event_handlers.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.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__/memory_integration.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.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__/connection_manager_http.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
- {claude_mpm-5.4.75.dist-info → claude_mpm-5.4.81.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.75.dist-info → claude_mpm-5.4.81.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.75.dist-info → claude_mpm-5.4.81.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.75.dist-info → claude_mpm-5.4.81.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.75.dist-info → claude_mpm-5.4.81.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.4.
|
|
1
|
+
5.4.81
|
|
@@ -26,6 +26,7 @@ from rich.prompt import Confirm, Prompt
|
|
|
26
26
|
from rich.text import Text
|
|
27
27
|
|
|
28
28
|
from ...core.config import Config
|
|
29
|
+
from ...core.unified_config import UnifiedConfig
|
|
29
30
|
from ...services.agents.agent_recommendation_service import AgentRecommendationService
|
|
30
31
|
from ...services.version_service import VersionService
|
|
31
32
|
from ...utils.agent_filters import apply_all_filters, get_deployed_agent_ids
|
|
@@ -79,6 +80,7 @@ class ConfigureCommand(BaseCommand):
|
|
|
79
80
|
self._template_editor = None # Lazy-initialized
|
|
80
81
|
self._startup_manager = None # Lazy-initialized
|
|
81
82
|
self._recommendation_service = None # Lazy-initialized
|
|
83
|
+
self._unified_config = None # Lazy-initialized
|
|
82
84
|
|
|
83
85
|
def validate_args(self, args) -> Optional[str]:
|
|
84
86
|
"""Validate command arguments."""
|
|
@@ -162,6 +164,18 @@ class ConfigureCommand(BaseCommand):
|
|
|
162
164
|
self._recommendation_service = AgentRecommendationService()
|
|
163
165
|
return self._recommendation_service
|
|
164
166
|
|
|
167
|
+
@property
|
|
168
|
+
def unified_config(self) -> UnifiedConfig:
|
|
169
|
+
"""Lazy-initialize unified config."""
|
|
170
|
+
if self._unified_config is None:
|
|
171
|
+
try:
|
|
172
|
+
self._unified_config = UnifiedConfig()
|
|
173
|
+
except Exception as e:
|
|
174
|
+
self.logger.warning(f"Failed to load unified config: {e}")
|
|
175
|
+
# Fallback to default config
|
|
176
|
+
self._unified_config = UnifiedConfig()
|
|
177
|
+
return self._unified_config
|
|
178
|
+
|
|
165
179
|
def run(self, args) -> CommandResult:
|
|
166
180
|
"""Execute the configure command."""
|
|
167
181
|
# Set configuration scope
|
|
@@ -805,6 +819,86 @@ class ConfigureCommand(BaseCommand):
|
|
|
805
819
|
self.console.print("[red]Invalid choice. Please try again.[/red]")
|
|
806
820
|
Prompt.ask("\nPress Enter to continue")
|
|
807
821
|
|
|
822
|
+
def _detect_skill_patterns(self, skills: list[dict]) -> dict[str, list[dict]]:
|
|
823
|
+
"""Group skills by detected common prefixes.
|
|
824
|
+
|
|
825
|
+
Args:
|
|
826
|
+
skills: List of skill dictionaries
|
|
827
|
+
|
|
828
|
+
Returns:
|
|
829
|
+
Dict mapping pattern prefix to list of skills.
|
|
830
|
+
Skills without pattern match go under "" (empty string) key.
|
|
831
|
+
"""
|
|
832
|
+
from collections import defaultdict
|
|
833
|
+
|
|
834
|
+
# Count prefix occurrences (try 1-segment and 2-segment prefixes)
|
|
835
|
+
prefix_counts = defaultdict(list)
|
|
836
|
+
|
|
837
|
+
for skill in skills:
|
|
838
|
+
skill_id = skill.get("name", skill.get("skill_id", ""))
|
|
839
|
+
|
|
840
|
+
# Try to extract prefixes (split by hyphen)
|
|
841
|
+
parts = skill_id.split("-")
|
|
842
|
+
|
|
843
|
+
if len(parts) >= 2:
|
|
844
|
+
# Try 2-segment prefix first (e.g., "toolchains-universal")
|
|
845
|
+
two_seg_prefix = f"{parts[0]}-{parts[1]}"
|
|
846
|
+
prefix_counts[two_seg_prefix].append(skill)
|
|
847
|
+
|
|
848
|
+
# Also try 1-segment prefix (e.g., "digitalocean")
|
|
849
|
+
one_seg_prefix = parts[0]
|
|
850
|
+
if one_seg_prefix != two_seg_prefix:
|
|
851
|
+
prefix_counts[one_seg_prefix].append(skill)
|
|
852
|
+
|
|
853
|
+
# Build pattern groups (require at least 2 skills per pattern)
|
|
854
|
+
pattern_groups = defaultdict(list)
|
|
855
|
+
used_skills = set()
|
|
856
|
+
|
|
857
|
+
# Prefer longer (more specific) prefixes
|
|
858
|
+
sorted_prefixes = sorted(prefix_counts.keys(), key=lambda x: (-len(x), x))
|
|
859
|
+
|
|
860
|
+
for prefix in sorted_prefixes:
|
|
861
|
+
matching_skills = prefix_counts[prefix]
|
|
862
|
+
|
|
863
|
+
# Only create a pattern group if we have 2+ skills and they're not already grouped
|
|
864
|
+
available_skills = [s for s in matching_skills if id(s) not in used_skills]
|
|
865
|
+
|
|
866
|
+
if len(available_skills) >= 2:
|
|
867
|
+
pattern_groups[prefix] = available_skills
|
|
868
|
+
used_skills.update(id(s) for s in available_skills)
|
|
869
|
+
|
|
870
|
+
# Add ungrouped skills to "" (Other) group
|
|
871
|
+
for skill in skills:
|
|
872
|
+
if id(skill) not in used_skills:
|
|
873
|
+
pattern_groups[""].append(skill)
|
|
874
|
+
|
|
875
|
+
return dict(pattern_groups)
|
|
876
|
+
|
|
877
|
+
def _get_pattern_icon(self, prefix: str) -> str:
|
|
878
|
+
"""Get icon for a pattern prefix.
|
|
879
|
+
|
|
880
|
+
Args:
|
|
881
|
+
prefix: Pattern prefix (e.g., "digitalocean", "vercel")
|
|
882
|
+
|
|
883
|
+
Returns:
|
|
884
|
+
Emoji icon for the pattern
|
|
885
|
+
"""
|
|
886
|
+
pattern_icons = {
|
|
887
|
+
"digitalocean": "🌊",
|
|
888
|
+
"aws": "☁️",
|
|
889
|
+
"github": "🐙",
|
|
890
|
+
"google": "🔍",
|
|
891
|
+
"vercel": "▲",
|
|
892
|
+
"netlify": "🦋",
|
|
893
|
+
"universal-testing": "🧪",
|
|
894
|
+
"universal-debugging": "🐛",
|
|
895
|
+
"universal-security": "🔒",
|
|
896
|
+
"toolchains-python": "🐍",
|
|
897
|
+
"toolchains-typescript": "📘",
|
|
898
|
+
"toolchains-javascript": "📒",
|
|
899
|
+
}
|
|
900
|
+
return pattern_icons.get(prefix, "📦")
|
|
901
|
+
|
|
808
902
|
def _manage_skill_installation(self) -> None:
|
|
809
903
|
"""Manage skill installation with category-based questionary checkbox selection."""
|
|
810
904
|
import questionary
|
|
@@ -890,30 +984,99 @@ class ConfigureCommand(BaseCommand):
|
|
|
890
984
|
# Show skills in category with checkbox selection
|
|
891
985
|
category_skills = grouped[selected_cat]
|
|
892
986
|
|
|
893
|
-
#
|
|
987
|
+
# Detect pattern groups within category
|
|
988
|
+
pattern_groups = self._detect_skill_patterns(category_skills)
|
|
989
|
+
|
|
990
|
+
# Build choices with pattern grouping and installation status
|
|
894
991
|
skill_choices = []
|
|
895
|
-
for skill in sorted(category_skills, key=lambda x: x.get("name", "")):
|
|
896
|
-
skill_id = skill.get("name", skill.get("skill_id", "unknown"))
|
|
897
|
-
deploy_name = skill.get("deployment_name", skill_id)
|
|
898
|
-
description = skill.get("description", "")[:50]
|
|
899
992
|
|
|
900
|
-
|
|
901
|
-
|
|
993
|
+
# Track which skills belong to which group for expansion later
|
|
994
|
+
group_to_skills = {}
|
|
902
995
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
996
|
+
# Sort pattern groups: "" (Other) last, rest alphabetically
|
|
997
|
+
sorted_patterns = sorted(pattern_groups.keys(), key=lambda x: (x == "", x))
|
|
998
|
+
|
|
999
|
+
for pattern in sorted_patterns:
|
|
1000
|
+
pattern_skills = pattern_groups[pattern]
|
|
1001
|
+
|
|
1002
|
+
# Skip empty groups
|
|
1003
|
+
if not pattern_skills:
|
|
1004
|
+
continue
|
|
1005
|
+
|
|
1006
|
+
# Collect skill IDs in this group
|
|
1007
|
+
skill_ids_in_group = []
|
|
1008
|
+
for skill in pattern_skills:
|
|
1009
|
+
skill_id = skill.get("name", skill.get("skill_id", "unknown"))
|
|
1010
|
+
skill_ids_in_group.append(skill_id)
|
|
1011
|
+
|
|
1012
|
+
# Check if all skills in group are installed
|
|
1013
|
+
all_installed = all(
|
|
1014
|
+
skill.get(
|
|
1015
|
+
"deployment_name", skill.get("name", skill.get("skill_id"))
|
|
908
1016
|
)
|
|
1017
|
+
in deployed
|
|
1018
|
+
or skill.get("name", skill.get("skill_id")) in deployed
|
|
1019
|
+
for skill in pattern_skills
|
|
909
1020
|
)
|
|
910
1021
|
|
|
1022
|
+
# Add pattern group header as selectable choice
|
|
1023
|
+
if pattern:
|
|
1024
|
+
# Named pattern group
|
|
1025
|
+
pattern_icon = self._get_pattern_icon(pattern)
|
|
1026
|
+
skill_count = len(pattern_skills)
|
|
1027
|
+
group_key = f"__group__:{pattern}"
|
|
1028
|
+
group_to_skills[group_key] = skill_ids_in_group
|
|
1029
|
+
|
|
1030
|
+
skill_choices.append(
|
|
1031
|
+
Choice(
|
|
1032
|
+
title=f"{pattern_icon} {pattern} ({skill_count} skills) [Select All]",
|
|
1033
|
+
value=group_key,
|
|
1034
|
+
checked=all_installed,
|
|
1035
|
+
)
|
|
1036
|
+
)
|
|
1037
|
+
elif pattern_skills:
|
|
1038
|
+
# "Other" group - only show if there are skills
|
|
1039
|
+
group_key = "__group__:Other"
|
|
1040
|
+
group_to_skills[group_key] = skill_ids_in_group
|
|
1041
|
+
|
|
1042
|
+
skill_choices.append(
|
|
1043
|
+
Choice(
|
|
1044
|
+
title=f"📦 Other ({len(pattern_skills)} skills) [Select All]",
|
|
1045
|
+
value=group_key,
|
|
1046
|
+
checked=all_installed,
|
|
1047
|
+
)
|
|
1048
|
+
)
|
|
1049
|
+
|
|
1050
|
+
# Add skills in this pattern group
|
|
1051
|
+
for skill in sorted(pattern_skills, key=lambda x: x.get("name", "")):
|
|
1052
|
+
skill_id = skill.get("name", skill.get("skill_id", "unknown"))
|
|
1053
|
+
deploy_name = skill.get("deployment_name", skill_id)
|
|
1054
|
+
description = skill.get("description", "")[:50]
|
|
1055
|
+
|
|
1056
|
+
# Check if installed
|
|
1057
|
+
is_installed = deploy_name in deployed or skill_id in deployed
|
|
1058
|
+
|
|
1059
|
+
# Add indentation for pattern-grouped skills (all skills are indented)
|
|
1060
|
+
skill_choices.append(
|
|
1061
|
+
Choice(
|
|
1062
|
+
title=f" {skill_id} - {description}",
|
|
1063
|
+
value=skill_id,
|
|
1064
|
+
checked=is_installed,
|
|
1065
|
+
)
|
|
1066
|
+
)
|
|
1067
|
+
|
|
1068
|
+
# Add spacing between pattern groups (not after last group)
|
|
1069
|
+
if pattern != sorted_patterns[-1]:
|
|
1070
|
+
skill_choices.append(Separator())
|
|
1071
|
+
|
|
911
1072
|
self.console.clear()
|
|
912
1073
|
self._display_header()
|
|
913
1074
|
self.console.print(
|
|
914
1075
|
f"\n{icons.get(selected_cat, '📦')} [bold]{selected_cat.title()}[/bold]"
|
|
915
1076
|
)
|
|
916
|
-
self.console.print(
|
|
1077
|
+
self.console.print(
|
|
1078
|
+
"[dim]Use spacebar to toggle individual skills or entire groups, enter to confirm[/dim]\n"
|
|
1079
|
+
)
|
|
917
1080
|
|
|
918
1081
|
selected = questionary.checkbox(
|
|
919
1082
|
"Select skills to install:",
|
|
@@ -924,8 +1087,16 @@ class ConfigureCommand(BaseCommand):
|
|
|
924
1087
|
if selected is None:
|
|
925
1088
|
continue # User cancelled, go back to category selection
|
|
926
1089
|
|
|
927
|
-
# Process
|
|
928
|
-
selected_set = set(
|
|
1090
|
+
# Process group selections - expand to individual skills
|
|
1091
|
+
selected_set = set()
|
|
1092
|
+
for item in selected:
|
|
1093
|
+
if item.startswith("__group__:"):
|
|
1094
|
+
# Expand group selection to all skills in that group
|
|
1095
|
+
selected_set.update(group_to_skills[item])
|
|
1096
|
+
else:
|
|
1097
|
+
# Individual skill selection
|
|
1098
|
+
selected_set.add(item)
|
|
1099
|
+
|
|
929
1100
|
current_in_cat = set()
|
|
930
1101
|
|
|
931
1102
|
# Find currently installed skills in this category
|
|
@@ -1905,18 +2076,32 @@ class ConfigureCommand(BaseCommand):
|
|
|
1905
2076
|
)
|
|
1906
2077
|
display_name = self._format_display_name(raw_display_name)
|
|
1907
2078
|
|
|
1908
|
-
# Check if agent is
|
|
2079
|
+
# Check if agent is required (cannot be unchecked)
|
|
2080
|
+
required_agents = set(self.unified_config.agents.required)
|
|
2081
|
+
is_required = (
|
|
2082
|
+
agent_leaf_name in required_agents
|
|
2083
|
+
or agent_id in required_agents
|
|
2084
|
+
)
|
|
1909
2085
|
|
|
1910
|
-
# Format choice text
|
|
1911
|
-
|
|
2086
|
+
# Format choice text with [Required] indicator
|
|
2087
|
+
if is_required:
|
|
2088
|
+
choice_text = f" {display_name} [Required]"
|
|
2089
|
+
else:
|
|
2090
|
+
choice_text = f" {display_name}"
|
|
1912
2091
|
|
|
1913
|
-
|
|
2092
|
+
# Required agents are always selected
|
|
2093
|
+
is_selected = is_required or agent_id in current_selection
|
|
2094
|
+
|
|
2095
|
+
# Add to current selection if required
|
|
2096
|
+
if is_required:
|
|
2097
|
+
current_selection.add(agent_id)
|
|
1914
2098
|
|
|
1915
2099
|
choices.append(
|
|
1916
2100
|
Choice(
|
|
1917
2101
|
title=choice_text,
|
|
1918
2102
|
value=agent_id, # Use agent_id for value
|
|
1919
2103
|
checked=is_selected,
|
|
2104
|
+
disabled=is_required, # Disable checkbox for required agents
|
|
1920
2105
|
)
|
|
1921
2106
|
)
|
|
1922
2107
|
|
|
@@ -1925,6 +2110,7 @@ class ConfigureCommand(BaseCommand):
|
|
|
1925
2110
|
self.console.print(
|
|
1926
2111
|
"[dim][ ] Unchecked = Available (check to install)[/dim]"
|
|
1927
2112
|
)
|
|
2113
|
+
self.console.print("[dim][Required] = Core agents (always installed)[/dim]")
|
|
1928
2114
|
self.console.print(
|
|
1929
2115
|
"[dim]Use arrow keys to navigate, space to toggle, Enter to apply[/dim]\n"
|
|
1930
2116
|
)
|
|
@@ -2011,12 +2197,37 @@ class ConfigureCommand(BaseCommand):
|
|
|
2011
2197
|
|
|
2012
2198
|
# No controls selected - use the individual selections as final
|
|
2013
2199
|
final_selection = set(selected_values)
|
|
2200
|
+
|
|
2201
|
+
# Ensure required agents are always in the final selection
|
|
2202
|
+
required_agents = set(self.unified_config.agents.required)
|
|
2203
|
+
for agent in agents:
|
|
2204
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
2205
|
+
agent_leaf_name = agent_id.split("/")[-1]
|
|
2206
|
+
if agent_leaf_name in required_agents or agent_id in required_agents:
|
|
2207
|
+
final_selection.add(agent_id)
|
|
2208
|
+
|
|
2014
2209
|
break
|
|
2015
2210
|
|
|
2016
2211
|
# Determine changes
|
|
2017
2212
|
to_deploy = final_selection - deployed_full_paths
|
|
2018
2213
|
to_remove = deployed_full_paths - final_selection
|
|
2019
2214
|
|
|
2215
|
+
# Prevent removal of required agents
|
|
2216
|
+
required_agents = set(self.unified_config.agents.required)
|
|
2217
|
+
to_remove_filtered = set()
|
|
2218
|
+
for agent_id in to_remove:
|
|
2219
|
+
agent_leaf_name = agent_id.split("/")[-1]
|
|
2220
|
+
if (
|
|
2221
|
+
agent_leaf_name not in required_agents
|
|
2222
|
+
and agent_id not in required_agents
|
|
2223
|
+
):
|
|
2224
|
+
to_remove_filtered.add(agent_id)
|
|
2225
|
+
else:
|
|
2226
|
+
self.console.print(
|
|
2227
|
+
f"[yellow]⚠ Cannot remove required agent: {agent_id}[/yellow]"
|
|
2228
|
+
)
|
|
2229
|
+
to_remove = to_remove_filtered
|
|
2230
|
+
|
|
2020
2231
|
if not to_deploy and not to_remove:
|
|
2021
2232
|
self.console.print("[yellow]No changes needed[/yellow]")
|
|
2022
2233
|
Prompt.ask("\nPress Enter to continue")
|
claude_mpm/cli/startup.py
CHANGED
|
@@ -700,8 +700,7 @@ def sync_remote_agents_on_startup(force_sync: bool = False):
|
|
|
700
700
|
agent_files = [
|
|
701
701
|
f
|
|
702
702
|
for f in all_md_files
|
|
703
|
-
if
|
|
704
|
-
(
|
|
703
|
+
if (
|
|
705
704
|
# Must be in an agent directory
|
|
706
705
|
# Supports: cache/agents/{category}/... (flat)
|
|
707
706
|
# Supports: cache/agents/{owner}/{repo}/agents/{category}/... (GitHub sync)
|
|
@@ -1467,7 +1466,9 @@ def run_background_services(force_sync: bool = False):
|
|
|
1467
1466
|
check_mcp_auto_configuration()
|
|
1468
1467
|
verify_mcp_gateway_startup()
|
|
1469
1468
|
check_for_updates_async()
|
|
1470
|
-
sync_remote_agents_on_startup(
|
|
1469
|
+
sync_remote_agents_on_startup(
|
|
1470
|
+
force_sync=force_sync
|
|
1471
|
+
) # Sync agents from remote sources
|
|
1471
1472
|
show_agent_summary() # Display agent counts after deployment
|
|
1472
1473
|
|
|
1473
1474
|
# Skills deployment order (precedence: remote > bundled)
|
|
@@ -1476,7 +1477,9 @@ def run_background_services(force_sync: bool = False):
|
|
|
1476
1477
|
# 3. Discover and link runtime skills (user-added skills)
|
|
1477
1478
|
# This ensures remote skills take precedence over bundled skills when names conflict
|
|
1478
1479
|
deploy_bundled_skills() # Base layer: package-bundled skills
|
|
1479
|
-
sync_remote_skills_on_startup(
|
|
1480
|
+
sync_remote_skills_on_startup(
|
|
1481
|
+
force_sync=force_sync
|
|
1482
|
+
) # Override layer: Git-based skills (takes precedence)
|
|
1480
1483
|
discover_and_link_runtime_skills() # Discovery: user-added skills
|
|
1481
1484
|
show_skill_summary() # Display skill counts after deployment
|
|
1482
1485
|
verify_and_show_pm_skills() # PM skills verification and status
|
claude_mpm/core/claude_runner.py
CHANGED
|
@@ -730,7 +730,7 @@ Use these agents to delegate specialized work via the Task tool.
|
|
|
730
730
|
import json
|
|
731
731
|
|
|
732
732
|
settings = json.loads(settings_file.read_text())
|
|
733
|
-
if settings.get("activeOutputStyle") == "
|
|
733
|
+
if settings.get("activeOutputStyle") == "Claude MPM":
|
|
734
734
|
# Already active, check if file exists
|
|
735
735
|
output_style_file = (
|
|
736
736
|
Path.home() / ".claude" / "output-styles" / "claude-mpm.md"
|
|
@@ -740,7 +740,7 @@ Use these agents to delegate specialized work via the Task tool.
|
|
|
740
740
|
"Output style 'Claude MPM' already deployed and active"
|
|
741
741
|
)
|
|
742
742
|
return
|
|
743
|
-
except Exception:
|
|
743
|
+
except Exception: # nosec B110
|
|
744
744
|
pass # Continue with deployment if we can't read settings
|
|
745
745
|
|
|
746
746
|
# Read the OUTPUT_STYLE.md content if it exists
|
|
@@ -12,7 +12,7 @@ of InteractiveSession without circular dependency issues.
|
|
|
12
12
|
|
|
13
13
|
import contextlib
|
|
14
14
|
import os
|
|
15
|
-
import subprocess
|
|
15
|
+
import subprocess # nosec B404
|
|
16
16
|
import uuid
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple
|
|
@@ -359,19 +359,19 @@ class InteractiveSession:
|
|
|
359
359
|
osm = self.runner.framework_loader.output_style_manager
|
|
360
360
|
if osm:
|
|
361
361
|
if osm.claude_version and osm.supports_output_styles():
|
|
362
|
-
# Check if
|
|
362
|
+
# Check if Claude MPM style is active
|
|
363
363
|
settings_file = osm.settings_file
|
|
364
364
|
if settings_file.exists():
|
|
365
365
|
import json
|
|
366
366
|
|
|
367
367
|
settings = json.loads(settings_file.read_text())
|
|
368
368
|
active_style = settings.get("activeOutputStyle")
|
|
369
|
-
if active_style
|
|
370
|
-
return "Output Style:
|
|
369
|
+
if active_style in ("Claude MPM", "Claude MPM Teacher"):
|
|
370
|
+
return f"Output Style: {active_style} ✅"
|
|
371
371
|
return f"Output Style: {active_style or 'none'}"
|
|
372
372
|
return "Output Style: Available"
|
|
373
373
|
return "Output Style: Injected (legacy)"
|
|
374
|
-
except Exception:
|
|
374
|
+
except Exception: # nosec B110
|
|
375
375
|
pass
|
|
376
376
|
return None
|
|
377
377
|
|
|
@@ -582,7 +582,7 @@ class InteractiveSession:
|
|
|
582
582
|
)
|
|
583
583
|
|
|
584
584
|
# This will not return if successful
|
|
585
|
-
os.execvpe(cmd[0], cmd, env)
|
|
585
|
+
os.execvpe(cmd[0], cmd, env) # nosec B606
|
|
586
586
|
return False # Only reached on failure
|
|
587
587
|
|
|
588
588
|
def _launch_subprocess_mode(self, cmd: list, env: dict) -> bool:
|
|
@@ -641,7 +641,7 @@ class InteractiveSession:
|
|
|
641
641
|
cmd = environment["command"]
|
|
642
642
|
env = environment["environment"]
|
|
643
643
|
|
|
644
|
-
result = subprocess.run(
|
|
644
|
+
result = subprocess.run( # nosec B603
|
|
645
645
|
cmd, stdin=None, stdout=None, stderr=None, env=env, check=False
|
|
646
646
|
)
|
|
647
647
|
|
|
@@ -13,7 +13,7 @@ Users can change it if they want, and the system will respect their choice.
|
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
15
|
import re
|
|
16
|
-
import subprocess
|
|
16
|
+
import subprocess # nosec B404
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import Any, Dict, Literal, Optional, TypedDict, cast
|
|
19
19
|
|
|
@@ -62,14 +62,14 @@ class OutputStyleManager:
|
|
|
62
62
|
/ "agents"
|
|
63
63
|
/ "CLAUDE_MPM_OUTPUT_STYLE.md",
|
|
64
64
|
target=self.output_style_dir / "claude-mpm.md",
|
|
65
|
-
name="
|
|
65
|
+
name="Claude MPM",
|
|
66
66
|
),
|
|
67
67
|
"teaching": StyleConfig(
|
|
68
68
|
source=Path(__file__).parent.parent
|
|
69
69
|
/ "agents"
|
|
70
70
|
/ "CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md",
|
|
71
71
|
target=self.output_style_dir / "claude-mpm-teacher.md",
|
|
72
|
-
name="
|
|
72
|
+
name="Claude MPM Teacher",
|
|
73
73
|
),
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -93,7 +93,7 @@ class OutputStyleManager:
|
|
|
93
93
|
|
|
94
94
|
try:
|
|
95
95
|
# Run claude --version command
|
|
96
|
-
result = subprocess.run(
|
|
96
|
+
result = subprocess.run( # nosec B603 B607
|
|
97
97
|
["claude", "--version"],
|
|
98
98
|
capture_output=True,
|
|
99
99
|
text=True,
|
|
@@ -300,12 +300,12 @@ class OutputStyleManager:
|
|
|
300
300
|
self.logger.error(f"Failed to deploy {style} style: {e}")
|
|
301
301
|
return False
|
|
302
302
|
|
|
303
|
-
def _activate_output_style(self, style_name: str = "
|
|
303
|
+
def _activate_output_style(self, style_name: str = "Claude MPM") -> bool:
|
|
304
304
|
"""
|
|
305
305
|
Update Claude Code settings to activate a specific output style.
|
|
306
306
|
|
|
307
307
|
Args:
|
|
308
|
-
style_name: Name of the style to activate (e.g., "
|
|
308
|
+
style_name: Name of the style to activate (e.g., "Claude MPM", "Claude MPM Teacher")
|
|
309
309
|
|
|
310
310
|
Returns:
|
|
311
311
|
True if activated successfully, False otherwise
|
|
@@ -443,7 +443,7 @@ class OutputStyleManager:
|
|
|
443
443
|
|
|
444
444
|
# Activate the default style if requested
|
|
445
445
|
if activate_default and results.get("professional", False):
|
|
446
|
-
self._activate_output_style("
|
|
446
|
+
self._activate_output_style("Claude MPM")
|
|
447
447
|
|
|
448
448
|
return results
|
|
449
449
|
|
|
@@ -72,6 +72,22 @@ class AgentConfig(BaseModel):
|
|
|
72
72
|
description="Explicit list of agent IDs to deploy (empty = use auto_discover)",
|
|
73
73
|
)
|
|
74
74
|
|
|
75
|
+
# Required agents that are always deployed
|
|
76
|
+
required: List[str] = Field(
|
|
77
|
+
default_factory=lambda: [
|
|
78
|
+
"research",
|
|
79
|
+
"mpm-skills-manager",
|
|
80
|
+
"mpm-agent-manager",
|
|
81
|
+
"memory-manager",
|
|
82
|
+
],
|
|
83
|
+
description="Agents that are always deployed (core system agents)",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
include_universal: bool = Field(
|
|
87
|
+
default=True,
|
|
88
|
+
description="Auto-include all agents with 'universal' toolchain/category",
|
|
89
|
+
)
|
|
90
|
+
|
|
75
91
|
auto_discover: bool = Field(
|
|
76
92
|
default=False,
|
|
77
93
|
description="Enable automatic agent discovery (deprecated, use enabled list)",
|
claude_mpm/core/unified_paths.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
1
|
"""
|
|
3
2
|
Unified Path Management System for Claude MPM
|
|
4
3
|
==============================================
|
|
@@ -36,6 +35,24 @@ from claude_mpm.core.logging_utils import get_logger
|
|
|
36
35
|
logger = get_logger(__name__)
|
|
37
36
|
|
|
38
37
|
|
|
38
|
+
def _safe_cwd() -> Path:
|
|
39
|
+
"""Safely get the current working directory.
|
|
40
|
+
|
|
41
|
+
If the current directory no longer exists (deleted/moved), fall back to home directory.
|
|
42
|
+
This prevents FileNotFoundError when Path.cwd() is called from a deleted directory.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Path: Current working directory, or home directory if cwd doesn't exist
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
return Path.cwd()
|
|
49
|
+
except (FileNotFoundError, OSError) as e:
|
|
50
|
+
logger.debug(
|
|
51
|
+
f"Current directory doesn't exist ({e}), falling back to home directory"
|
|
52
|
+
)
|
|
53
|
+
return Path.home()
|
|
54
|
+
|
|
55
|
+
|
|
39
56
|
class PathType(Enum):
|
|
40
57
|
"""Enumeration of different path types for categorization."""
|
|
41
58
|
|
|
@@ -95,7 +112,7 @@ class PathContext:
|
|
|
95
112
|
|
|
96
113
|
# Additional check: If we're running from within a claude-mpm development directory
|
|
97
114
|
# This handles the case where pipx claude-mpm is invoked from within the dev directory
|
|
98
|
-
cwd =
|
|
115
|
+
cwd = _safe_cwd()
|
|
99
116
|
current = cwd
|
|
100
117
|
for _ in range(5): # Check up to 5 levels up from current directory
|
|
101
118
|
if (current / "pyproject.toml").exists() and (
|
|
@@ -114,7 +131,7 @@ class PathContext:
|
|
|
114
131
|
# Verify this is a development setup by checking for key files
|
|
115
132
|
if (current / "scripts" / "claude-mpm").exists():
|
|
116
133
|
return True
|
|
117
|
-
except Exception:
|
|
134
|
+
except Exception: # nosec B110
|
|
118
135
|
pass
|
|
119
136
|
if current == current.parent:
|
|
120
137
|
break
|
|
@@ -140,7 +157,7 @@ class PathContext:
|
|
|
140
157
|
f"Found editable install via .pth file: {pth_file}"
|
|
141
158
|
)
|
|
142
159
|
return True
|
|
143
|
-
except Exception:
|
|
160
|
+
except Exception: # nosec B112
|
|
144
161
|
continue
|
|
145
162
|
|
|
146
163
|
# Check for egg-link files
|
|
@@ -156,7 +173,7 @@ class PathContext:
|
|
|
156
173
|
f"Found editable install via egg-link: {egg_link}"
|
|
157
174
|
)
|
|
158
175
|
return True
|
|
159
|
-
except Exception:
|
|
176
|
+
except Exception: # nosec B112
|
|
160
177
|
continue
|
|
161
178
|
except ImportError:
|
|
162
179
|
pass
|
|
@@ -186,7 +203,7 @@ class PathContext:
|
|
|
186
203
|
|
|
187
204
|
# Check if current working directory is a claude-mpm development project
|
|
188
205
|
# This handles the case where pipx claude-mpm is run from within the dev directory
|
|
189
|
-
cwd =
|
|
206
|
+
cwd = _safe_cwd()
|
|
190
207
|
current = cwd
|
|
191
208
|
for _ in range(5): # Check up to 5 levels up from current directory
|
|
192
209
|
if (current / "pyproject.toml").exists() and (
|
|
@@ -206,7 +223,7 @@ class PathContext:
|
|
|
206
223
|
"Using development mode for local source preference"
|
|
207
224
|
)
|
|
208
225
|
return DeploymentContext.DEVELOPMENT
|
|
209
|
-
except Exception:
|
|
226
|
+
except Exception: # nosec B110
|
|
210
227
|
pass
|
|
211
228
|
if current == current.parent:
|
|
212
229
|
break
|
|
@@ -228,7 +245,7 @@ class PathContext:
|
|
|
228
245
|
if "pipx" in str(module_path):
|
|
229
246
|
# Running via pipx but from within a development directory
|
|
230
247
|
# Use development mode to prefer local source over pipx installation
|
|
231
|
-
cwd =
|
|
248
|
+
cwd = _safe_cwd()
|
|
232
249
|
current = cwd
|
|
233
250
|
for _ in range(5):
|
|
234
251
|
if (current / "src" / "claude_mpm").exists() and (
|
|
@@ -346,7 +363,7 @@ class UnifiedPathManager:
|
|
|
346
363
|
):
|
|
347
364
|
# For development mode, first check if we're running from within a dev directory
|
|
348
365
|
# This handles the case where pipx is invoked from a development directory
|
|
349
|
-
cwd =
|
|
366
|
+
cwd = _safe_cwd()
|
|
350
367
|
current = cwd
|
|
351
368
|
for _ in range(5):
|
|
352
369
|
if (current / "src" / "claude_mpm").exists() and (
|
|
@@ -360,7 +377,7 @@ class UnifiedPathManager:
|
|
|
360
377
|
f"Found framework root via cwd at {current}"
|
|
361
378
|
)
|
|
362
379
|
return current
|
|
363
|
-
except Exception:
|
|
380
|
+
except Exception: # nosec B110
|
|
364
381
|
pass
|
|
365
382
|
if current == current.parent:
|
|
366
383
|
break
|
|
@@ -403,7 +420,7 @@ class UnifiedPathManager:
|
|
|
403
420
|
@lru_cache(maxsize=1)
|
|
404
421
|
def project_root(self) -> Path:
|
|
405
422
|
"""Get the current project root directory."""
|
|
406
|
-
current =
|
|
423
|
+
current = _safe_cwd()
|
|
407
424
|
while current != current.parent:
|
|
408
425
|
for marker in self._project_markers:
|
|
409
426
|
if (current / marker).exists():
|
|
@@ -413,7 +430,7 @@ class UnifiedPathManager:
|
|
|
413
430
|
|
|
414
431
|
# Fallback to current directory
|
|
415
432
|
logger.warning("Could not find project root, using current directory")
|
|
416
|
-
return
|
|
433
|
+
return _safe_cwd()
|
|
417
434
|
|
|
418
435
|
@property
|
|
419
436
|
def package_root(self) -> Path:
|
|
@@ -562,7 +579,7 @@ class UnifiedPathManager:
|
|
|
562
579
|
self, filename: str, start_path: Optional[Path] = None
|
|
563
580
|
) -> Optional[Path]:
|
|
564
581
|
"""Search for a file by traversing up the directory tree."""
|
|
565
|
-
current = start_path or
|
|
582
|
+
current = start_path or _safe_cwd()
|
|
566
583
|
|
|
567
584
|
while current != current.parent:
|
|
568
585
|
candidate = current / filename
|
|
@@ -240,12 +240,50 @@ class DeploymentReconciler:
|
|
|
240
240
|
self, cache_dir: Path, deploy_dir: Path
|
|
241
241
|
) -> ReconciliationState:
|
|
242
242
|
"""Get current agent deployment state."""
|
|
243
|
+
# Start with enabled agents
|
|
244
|
+
configured_agents = set(self.config.agents.enabled)
|
|
245
|
+
|
|
246
|
+
# Add required agents (cannot be disabled)
|
|
247
|
+
configured_agents.update(self.config.agents.required)
|
|
248
|
+
|
|
249
|
+
# Add universal agents if enabled
|
|
250
|
+
if self.config.agents.include_universal:
|
|
251
|
+
universal_agents = self._get_universal_agents(cache_dir)
|
|
252
|
+
configured_agents.update(universal_agents)
|
|
253
|
+
|
|
243
254
|
return ReconciliationState(
|
|
244
|
-
configured=
|
|
255
|
+
configured=configured_agents,
|
|
245
256
|
deployed=self._list_deployed_agents(deploy_dir),
|
|
246
257
|
cached=self._list_cached_agents(cache_dir),
|
|
247
258
|
)
|
|
248
259
|
|
|
260
|
+
def _get_universal_agents(self, cache_dir: Path) -> Set[str]:
|
|
261
|
+
"""Get all agents with 'universal' toolchain/category."""
|
|
262
|
+
universal_agents = set()
|
|
263
|
+
if not cache_dir.exists():
|
|
264
|
+
return universal_agents
|
|
265
|
+
|
|
266
|
+
for agent_file in cache_dir.glob("**/*.md"):
|
|
267
|
+
try:
|
|
268
|
+
# Read frontmatter to check toolchain/category
|
|
269
|
+
content = agent_file.read_text(encoding="utf-8")
|
|
270
|
+
|
|
271
|
+
# Check for universal markers in frontmatter (within first 1000 chars)
|
|
272
|
+
frontmatter_section = content[:1000].lower()
|
|
273
|
+
if (
|
|
274
|
+
"toolchain: universal" in frontmatter_section
|
|
275
|
+
or "category: universal" in frontmatter_section
|
|
276
|
+
or "toolchain:\n - universal" in frontmatter_section
|
|
277
|
+
):
|
|
278
|
+
universal_agents.add(agent_file.stem)
|
|
279
|
+
except Exception as e:
|
|
280
|
+
logger.debug(
|
|
281
|
+
f"Failed to check universal marker for {agent_file.name}: {e}"
|
|
282
|
+
)
|
|
283
|
+
continue
|
|
284
|
+
|
|
285
|
+
return universal_agents
|
|
286
|
+
|
|
249
287
|
def _list_deployed_agents(self, deploy_dir: Path) -> Set[str]:
|
|
250
288
|
"""List agent IDs currently deployed."""
|
|
251
289
|
if not deploy_dir.exists():
|
|
@@ -1095,7 +1095,11 @@ class GitSkillSourceManager:
|
|
|
1095
1095
|
if removed_skills:
|
|
1096
1096
|
self.logger.info(
|
|
1097
1097
|
f"Removed {len(removed_skills)} orphaned skills not referenced by agents: {removed_skills[:10]}"
|
|
1098
|
-
+ (
|
|
1098
|
+
+ (
|
|
1099
|
+
f" (and {len(removed_skills) - 10} more)"
|
|
1100
|
+
if len(removed_skills) > 10
|
|
1101
|
+
else ""
|
|
1102
|
+
)
|
|
1099
1103
|
)
|
|
1100
1104
|
|
|
1101
1105
|
self.logger.info(
|
|
@@ -44,7 +44,6 @@ from typing import Any, Dict, List, Set, Tuple
|
|
|
44
44
|
import yaml
|
|
45
45
|
|
|
46
46
|
from claude_mpm.core.logging_config import get_logger
|
|
47
|
-
from claude_mpm.services.skills.skill_to_agent_mapper import SkillToAgentMapper
|
|
48
47
|
|
|
49
48
|
logger = get_logger(__name__)
|
|
50
49
|
|
|
@@ -60,26 +59,20 @@ CORE_SKILLS = {
|
|
|
60
59
|
"universal-debugging-verification-before-completion",
|
|
61
60
|
"universal-verification-pre-merge",
|
|
62
61
|
"universal-verification-screenshot",
|
|
63
|
-
|
|
64
62
|
# Universal testing patterns (2 skills)
|
|
65
63
|
"universal-testing-test-driven-development",
|
|
66
64
|
"universal-testing-testing-anti-patterns",
|
|
67
|
-
|
|
68
65
|
# Universal architecture and design (1 skill)
|
|
69
66
|
"universal-architecture-software-patterns",
|
|
70
|
-
|
|
71
67
|
# Universal infrastructure (3 skills)
|
|
72
68
|
"universal-infrastructure-env-manager",
|
|
73
69
|
"universal-infrastructure-docker",
|
|
74
70
|
"universal-infrastructure-github-actions",
|
|
75
|
-
|
|
76
71
|
# Universal collaboration (1 skill)
|
|
77
72
|
"universal-collaboration-stacked-prs",
|
|
78
|
-
|
|
79
73
|
# Universal emergency/operations (1 skill)
|
|
80
74
|
"toolchains-universal-emergency-release",
|
|
81
75
|
"toolchains-universal-dependency-audit",
|
|
82
|
-
|
|
83
76
|
# Common language toolchains (6 skills)
|
|
84
77
|
"toolchains-typescript-core",
|
|
85
78
|
"toolchains-python-core",
|
|
@@ -87,17 +80,14 @@ CORE_SKILLS = {
|
|
|
87
80
|
"toolchains-python-tooling-mypy",
|
|
88
81
|
"toolchains-typescript-testing-vitest",
|
|
89
82
|
"toolchains-python-frameworks-flask",
|
|
90
|
-
|
|
91
83
|
# Common web frameworks (4 skills)
|
|
92
84
|
"toolchains-javascript-frameworks-nextjs",
|
|
93
85
|
"toolchains-nextjs-core",
|
|
94
86
|
"toolchains-typescript-frameworks-nodejs-backend",
|
|
95
87
|
"toolchains-javascript-frameworks-react-state-machine",
|
|
96
|
-
|
|
97
88
|
# Common testing tools (2 skills)
|
|
98
89
|
"toolchains-javascript-testing-playwright",
|
|
99
90
|
"toolchains-typescript-testing-jest",
|
|
100
|
-
|
|
101
91
|
# Common data/UI tools (3 skills)
|
|
102
92
|
"universal-data-xlsx",
|
|
103
93
|
"toolchains-ui-styling-tailwind",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=9JfxhnDtr-8l3kCP2U5TVXSErptHoga8m7XA8zqgGOc,4
|
|
2
|
-
claude_mpm/VERSION,sha256=
|
|
2
|
+
claude_mpm/VERSION,sha256=Y7K2U181JWRkGEesrtmhDtqq53Z1iVyIoUzjER77XLg,7
|
|
3
3
|
claude_mpm/__init__.py,sha256=AGfh00BHKvLYD-UVFw7qbKtl7NMRIzRXOWw7vEuZ-h4,2214
|
|
4
4
|
claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
|
|
5
5
|
claude_mpm/constants.py,sha256=pz3lTrZZR5HhV3eZzYtIbtBwWo7iM6pkBHP_ixxmI6Y,6827
|
|
@@ -41,7 +41,7 @@ claude_mpm/cli/chrome_devtools_installer.py,sha256=efA_ZX1iR3oaJi3222079BQw6DEG8
|
|
|
41
41
|
claude_mpm/cli/executor.py,sha256=1MQdNPNoIewSR1q8nXjJuES3zKEi_IqVcZQzt9bsxw8,10601
|
|
42
42
|
claude_mpm/cli/helpers.py,sha256=CypEhw0tbNH6_GzVTaQdi4w7ThCWO43Ep92YbJzPR4I,3638
|
|
43
43
|
claude_mpm/cli/parser.py,sha256=Vqx9n-6Xo1uNhXR4rThmgWpZXTr0nOtkgDf3oMS9b0g,5855
|
|
44
|
-
claude_mpm/cli/startup.py,sha256=
|
|
44
|
+
claude_mpm/cli/startup.py,sha256=6sfkFbapu7X76hBPmKjxkUEMlo9DUjF4x7mhaVE7IJw,74374
|
|
45
45
|
claude_mpm/cli/startup_display.py,sha256=R_QIamjfdaY5o_VxpIeymyYj1Qde2B9hPXy1P-KmUKI,14972
|
|
46
46
|
claude_mpm/cli/startup_logging.py,sha256=RTuyd6CbhiFQz7Z07LDDhK_ZAnZfuJ9B0NghVSntHFI,29390
|
|
47
47
|
claude_mpm/cli/utils.py,sha256=FSMPftBZM8MeUyTtiB63Lz7oFOgkzwTetQs58RbRb_Q,8785
|
|
@@ -60,7 +60,7 @@ claude_mpm/cli/commands/auto_configure.py,sha256=0Suzil6O0SBNeHUCwHOkt2q7gfuXRTy
|
|
|
60
60
|
claude_mpm/cli/commands/cleanup.py,sha256=RQikOGLuLFWXzjeoHArdr5FA4Pf7tSK9w2NXL4vCrok,19769
|
|
61
61
|
claude_mpm/cli/commands/cleanup_orphaned_agents.py,sha256=JR8crvgrz7Sa6d-SI-gKywok5S9rwc_DzDVk_h85sVs,4467
|
|
62
62
|
claude_mpm/cli/commands/config.py,sha256=2M9VUPYcQkBUCIyyB-v1qTL3xYvao9YI2l_JGBUDauA,23374
|
|
63
|
-
claude_mpm/cli/commands/configure.py,sha256=
|
|
63
|
+
claude_mpm/cli/commands/configure.py,sha256=VUokhUcV90GzEEivV3xNmfQHogM94mdDadW3S4mp83M,136509
|
|
64
64
|
claude_mpm/cli/commands/configure_agent_display.py,sha256=oSvUhR861o_Pyqmop4ACAQNjwL02-Rf6TMqFvmQNh24,10575
|
|
65
65
|
claude_mpm/cli/commands/configure_behavior_manager.py,sha256=_tfpcKW0KgMGO52q6IHFXL3W5xwjC8-q2_KpIvHVuoI,6827
|
|
66
66
|
claude_mpm/cli/commands/configure_hook_manager.py,sha256=1X5brU6cgKRRF-2lQYA0aiKD7ZjTClqNHUSWuayktEw,9205
|
|
@@ -177,7 +177,7 @@ claude_mpm/core/agent_session_manager.py,sha256=F10LS-nyTQxzMP3fkhbI94klsJy5xpSA
|
|
|
177
177
|
claude_mpm/core/api_validator.py,sha256=zxeUykC2asy1KwHBDu5w3Eoo64E51PJyNe4PT7CTJf0,12282
|
|
178
178
|
claude_mpm/core/base_service.py,sha256=4Zrt-vQ6g_KVk4hEfvd4QccuItYoOf7wUHCimIW6zJQ,29953
|
|
179
179
|
claude_mpm/core/cache.py,sha256=orh8B40oYnRRGmXdANR4P4f-KVMIHV0vg7vrsemk0no,17232
|
|
180
|
-
claude_mpm/core/claude_runner.py,sha256=
|
|
180
|
+
claude_mpm/core/claude_runner.py,sha256=Wle-wI-ag25oC0EYX3n8dDC56I5GIdbpi5NtvT4IgBw,34263
|
|
181
181
|
claude_mpm/core/config.py,sha256=RLjN1OSW5AadWju6kooEEbud8mntSkorapP1wzUrPGk,42491
|
|
182
182
|
claude_mpm/core/config_aliases.py,sha256=QpNNECkTY4TYYAhVlFZvB-msPnZrui90g19u0-v0HDE,9703
|
|
183
183
|
claude_mpm/core/config_constants.py,sha256=MEF35Y2Lj5FMzRdhgSgZrZeTzHfCzistPGZVY8INta4,10073
|
|
@@ -194,7 +194,7 @@ claude_mpm/core/hook_manager.py,sha256=FI5wfa1zczm_SJQXOtpL7BYKxVZD4BMXRbqCBZQkD
|
|
|
194
194
|
claude_mpm/core/hook_performance_config.py,sha256=e7a7oFctkRhA3aPXMO5Wavr-E6ku7ikLxMzPU7P1-yg,5779
|
|
195
195
|
claude_mpm/core/injectable_service.py,sha256=9N4mHt6a_PwoP0pQo-QhVTnXLJlgDCCOg358d0jPEs4,7384
|
|
196
196
|
claude_mpm/core/instruction_reinforcement_hook.py,sha256=hSYvUp_ducWnhcKTkUbUoCLUb_yCzbIgsqEp7VpF9h0,9542
|
|
197
|
-
claude_mpm/core/interactive_session.py,sha256=
|
|
197
|
+
claude_mpm/core/interactive_session.py,sha256=CW3_HNSMQ5pRi0mIh9_zBMncywARFV2AXLITBTaOxIU,27936
|
|
198
198
|
claude_mpm/core/interfaces.py,sha256=sSipQa2tjf9EbRaKhxeCE31E-alS_iddvUfI0X_I0LQ,26909
|
|
199
199
|
claude_mpm/core/lazy.py,sha256=pyCfEqGHyLz18yXTu_uG52-II-9nCaBcpzwwQGBrQro,14808
|
|
200
200
|
claude_mpm/core/log_manager.py,sha256=yf82AKC-DYLtl7h0ka5IEoVC8aC0_II-zCjHOwD3RxQ,24661
|
|
@@ -206,7 +206,7 @@ claude_mpm/core/mixins.py,sha256=vmZ7Nu2ZOnKjbhN07Ixk4noIej9nsJiknrp-Sclfu0A,534
|
|
|
206
206
|
claude_mpm/core/oneshot_session.py,sha256=nA86Zk7W3Rh_yIhPuegFL7Xgc9S63vQ_MqfLk52doV0,21994
|
|
207
207
|
claude_mpm/core/optimized_agent_loader.py,sha256=yevEwTZWzVeZYEJhV3czD45OU7ukJIaJos4MGnFP7YQ,15857
|
|
208
208
|
claude_mpm/core/optimized_startup.py,sha256=U5I4f7PNYXCBOLbCkbWT2V2sv01T8iWP2Bw-f928Q9M,17927
|
|
209
|
-
claude_mpm/core/output_style_manager.py,sha256=
|
|
209
|
+
claude_mpm/core/output_style_manager.py,sha256=QkH62HRCH6FYxg2lop_3Xml3BLOieE12024vAjS6SyI,17091
|
|
210
210
|
claude_mpm/core/pm_hook_interceptor.py,sha256=92C8TrpK-XVQD8BiXbqs8lSCX72PU0KZG5oAjhf8GOQ,11197
|
|
211
211
|
claude_mpm/core/service_registry.py,sha256=QpmAMWCov8XXaxQwE7WiNbgv6u_CRjpKPB64kLYvZKk,11722
|
|
212
212
|
claude_mpm/core/session_manager.py,sha256=iEDZWKBYHSu001nFX8vFvH33RvQOW0eIgomWhFM53sw,12078
|
|
@@ -216,8 +216,8 @@ claude_mpm/core/tool_access_control.py,sha256=dpdxxp_77SuxGM2C7SsHUZbtysJmHw1rLD
|
|
|
216
216
|
claude_mpm/core/types.py,sha256=Sv62QhMYvfxbt7oIGoAhhN_jxonFTeLRf-BuhxZ4vYw,7719
|
|
217
217
|
claude_mpm/core/typing_utils.py,sha256=qny3rA9mAeXqdLgUj9DZg642shw4LmLbkPqADN-765s,13314
|
|
218
218
|
claude_mpm/core/unified_agent_registry.py,sha256=YbL-oWeHU85zdf1mF7tyMHBYKtFBupsMeH9BCdzD6ZI,34161
|
|
219
|
-
claude_mpm/core/unified_config.py,sha256=
|
|
220
|
-
claude_mpm/core/unified_paths.py,sha256=
|
|
219
|
+
claude_mpm/core/unified_config.py,sha256=DUC5PB9P9s_27xs6_87vc3t-rkrU6jITwOFu6W8At7o,21743
|
|
220
|
+
claude_mpm/core/unified_paths.py,sha256=F2NYAK6RNtn_xsZnVHVfP7MErzDh_O9hyaa3B4OyT9A,36690
|
|
221
221
|
claude_mpm/core/framework/__init__.py,sha256=IJCp6-MQO8gW31uG8aMWHdNg54NgGvXb4GvOuwZF6Iw,736
|
|
222
222
|
claude_mpm/core/framework/formatters/__init__.py,sha256=OKkLN2x21rcbg3d3feZLixIS-UjHPlxl768uGmQy7Qc,307
|
|
223
223
|
claude_mpm/core/framework/formatters/capability_generator.py,sha256=mZpnuKiNhGtE7R39VftWiHaSCabnpUDnUbH3FKKTMUk,14649
|
|
@@ -338,36 +338,12 @@ claude_mpm/hooks/claude_hooks/installer.py,sha256=VbvVGMcrmCXQB3Pf9zOdjeGET2AFqb
|
|
|
338
338
|
claude_mpm/hooks/claude_hooks/memory_integration.py,sha256=73w7A5-3s5i1oYdkbEgw7qhgalQvSuJjfx6OFqfaw64,9963
|
|
339
339
|
claude_mpm/hooks/claude_hooks/response_tracking.py,sha256=bz_8csYxxUZ3k_SI6q9uvtE7wfH-T15v_jpP2nq45nk,16896
|
|
340
340
|
claude_mpm/hooks/claude_hooks/tool_analysis.py,sha256=3_o2PP9D7wEMwLriCtIBOw0cj2fSZfepN7lI4P1meSQ,7862
|
|
341
|
-
claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc,sha256=EGpgXqhPM0iRRZtCqHaLVQ6wDH42OH_M7Gt5GiFLyro,346
|
|
342
|
-
claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc,sha256=RdPlaoNPDoSlTFV36Ku4vxs7xYqh7t2038D4pyULy-g,322
|
|
343
|
-
claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc,sha256=SQX5iiP9bQZkLL-cj_2tlGH7lpAzarO0mYal7btj3tc,3521
|
|
344
|
-
claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc,sha256=T9FMRyRjvHTRJm0LXosba7MezdUVw6I-nt_KP--LTwA,35923
|
|
345
|
-
claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc,sha256=-ayyVTxDW5_BVD2TD14e4zDteH0l_mXIcyEG8AQCERg,32006
|
|
346
|
-
claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc,sha256=AsvVXkge1Pio3jgnS-zNbPt9brySB8ZeVPSn7VvuKjs,29654
|
|
347
|
-
claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc,sha256=heIj2o28Pw6QF5zgZBAebUInR8nxi6Ezdlfau9p-WJQ,27040
|
|
348
|
-
claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc,sha256=9mpAKY4gNcbU5VvZ5tGbf2UM0uIEWdreKSUvVr_BKcM,33917
|
|
349
|
-
claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc,sha256=YbwauQDKSGvXkT1972faalJLuxwyvq328DYQhkCnel0,10513
|
|
350
|
-
claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc,sha256=K-FbzUxbOffBSol-RUZkyFr9k1Ktg0HRdykSKbAn0NI,9489
|
|
351
|
-
claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc,sha256=0xWsBZ63F-akLopSiRi36-hmhh1v9R5aKFBM0z93Jd0,16730
|
|
352
|
-
claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc,sha256=QZDMBrRbhD5lnm1sDcONSU5s5qsrcRme-vQOGUD5J3U,14632
|
|
353
|
-
claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc,sha256=ZjcNfNY5Ht6FhalPeh7M7OzMffcey5iF4AVjDDg9kak,10694
|
|
354
|
-
claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc,sha256=T98zonvVkllflFNw_pptXXAXbDrIgeBfY6aXvSY8el8,9071
|
|
355
341
|
claude_mpm/hooks/claude_hooks/services/__init__.py,sha256=OIYOKsUNw1BHYawOCp-KFK5kmQKuj92cCqCEPO0nwo0,585
|
|
356
342
|
claude_mpm/hooks/claude_hooks/services/connection_manager.py,sha256=l-aKzxwK-PWKL3TO1Iiu0sfSbj6Y9JMBOm3pgAiUYZc,9378
|
|
357
343
|
claude_mpm/hooks/claude_hooks/services/connection_manager_http.py,sha256=n14k1byOBbviu0nFab3q0gb7p6eMqGO8hS0b7Gt2JRg,10262
|
|
358
344
|
claude_mpm/hooks/claude_hooks/services/duplicate_detector.py,sha256=Fh9LmEMsVmQM9t0U1v2l_fuBwvNpVkl_0EF8Wu5KLHQ,3882
|
|
359
345
|
claude_mpm/hooks/claude_hooks/services/state_manager.py,sha256=QB0JPJQThTVg0TGRO3Dc_3y3bac-hkulgMqqzo_71ng,11189
|
|
360
346
|
claude_mpm/hooks/claude_hooks/services/subagent_processor.py,sha256=f7a_vgo_kuG9MalDTka2UPXwDyCkqNgCvG8i1hp0oRo,15263
|
|
361
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc,sha256=xBfLBSqnpcKfcQBWfh7xUm454g1lq1LvbO7SxGvcOPc,644
|
|
362
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.pyc,sha256=75pkmoqE7CeBOc2ZHTYfgSR-mtVjKrcKaOA6PxFGW64,565
|
|
363
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc,sha256=bvZ_QcuI0j125Ebv8RzeWUh1BkuRTUfufGi0NV7HjuY,12359
|
|
364
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc,sha256=HEBjsWvdkCpV8X4UyDsKhm0HXpstuHnObck_Yr-QQBA,11177
|
|
365
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc,sha256=Yy_REAUhJCiFjOhxeDb4v0qyEvEbUtCmXD9PAz40dhw,5321
|
|
366
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc,sha256=ef_Tx9Uv1CvS18tC_PXmGVvIoMDsRnEUhKRUZaUdGBw,4751
|
|
367
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc,sha256=TPkEc-Zi3oNS5dCXBpGbSZwg_8RQvzNzd4pVx9B3WeM,12364
|
|
368
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc,sha256=uDZ1o2NYu0e2-sXxHovFOy28cklRaMOOX4vkLTRDjq0,11477
|
|
369
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc,sha256=YjWbj0qXMjew5bZCgvHWrb3dxp3BQZkpuOqsXgu4Wis,15045
|
|
370
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc,sha256=c2Y-gHruenFjPNTimrkiSUvXamZayjpMinAKIppzMoM,13611
|
|
371
347
|
claude_mpm/hooks/failure_learning/__init__.py,sha256=iJ80AKFHiT8DjIH2a72DQVJvL6nAFrizNA2yTKwZ4rw,1805
|
|
372
348
|
claude_mpm/hooks/failure_learning/failure_detection_hook.py,sha256=KENoB5N-dBm5hb0SxeIZtCvNKbmG2BKHOJSrSO-3Z_I,7500
|
|
373
349
|
claude_mpm/hooks/failure_learning/fix_detection_hook.py,sha256=XUk1bnBVLdfhQ9AMQSvGsTSeFQsKsVud2wbWX-Jjor8,7164
|
|
@@ -461,7 +437,7 @@ claude_mpm/services/agents/deployment/agents_directory_resolver.py,sha256=8Bavjt
|
|
|
461
437
|
claude_mpm/services/agents/deployment/async_agent_deployment.py,sha256=niPalcfjtl2Ko5k3f0nq-xbsuFLIC7cMI_cVpSt1axA,28549
|
|
462
438
|
claude_mpm/services/agents/deployment/base_agent_locator.py,sha256=szw9N1Di6AJuuWGIZHRfgWij6wwMbag--6XzjFvmpiA,4751
|
|
463
439
|
claude_mpm/services/agents/deployment/deployment_config_loader.py,sha256=xma4xWUp5QLQL0z4wSM9KTXmVR19CSw0iXAlaFyr6ow,6739
|
|
464
|
-
claude_mpm/services/agents/deployment/deployment_reconciler.py,sha256=
|
|
440
|
+
claude_mpm/services/agents/deployment/deployment_reconciler.py,sha256=L3Z92beXFYzGjMZ3xwbOPvh-wcscfAh2oGtF3dhDoY8,20672
|
|
465
441
|
claude_mpm/services/agents/deployment/deployment_results_manager.py,sha256=oNJ8DhmeXswD4_6qmLpDusI2edyJy2gd203ePxmJEy8,6609
|
|
466
442
|
claude_mpm/services/agents/deployment/deployment_type_detector.py,sha256=8VavaJX1T-sWf5_XwVB4NZXh5WnHg-F7J8TzN_TwLnM,4201
|
|
467
443
|
claude_mpm/services/agents/deployment/deployment_wrapper.py,sha256=RfmplaLjbxfWGJRT3i7eDtNsiC-S3n3lJDrDn8MQByI,4761
|
|
@@ -717,8 +693,8 @@ claude_mpm/services/shared/lifecycle_service_base.py,sha256=YJZHs2sUrnIsbHHjrd8l
|
|
|
717
693
|
claude_mpm/services/shared/manager_base.py,sha256=kmjhpVqgfYC1N4YQnPAilCfdrSpAh9Qz7wcQ602L4x4,9296
|
|
718
694
|
claude_mpm/services/shared/service_factory.py,sha256=9yvnD62urrNQCGmtk_3OcR5tVUCnoS6wHkaI5PK34mg,9891
|
|
719
695
|
claude_mpm/services/skills/__init__.py,sha256=X1fPRCGZjteLd35HlhWv2M6tAJ_WbYrEv84kbaqBAiU,742
|
|
720
|
-
claude_mpm/services/skills/git_skill_source_manager.py,sha256=
|
|
721
|
-
claude_mpm/services/skills/selective_skill_deployer.py,sha256=
|
|
696
|
+
claude_mpm/services/skills/git_skill_source_manager.py,sha256=q8pKRLBza7Uh3vEpCXuQKdp1pF0b9P1CTUzUkL5VBJA,51623
|
|
697
|
+
claude_mpm/services/skills/selective_skill_deployer.py,sha256=l20QnElbYXHTNuZozDU_a8c_799RTbjesqrILZBDQcQ,25747
|
|
722
698
|
claude_mpm/services/skills/skill_discovery_service.py,sha256=riy0PTnJS8e5R2ai8y1KPhBIR7SxlYIa9bnI9YccRMQ,20247
|
|
723
699
|
claude_mpm/services/skills/skill_to_agent_mapper.py,sha256=4PRwcSDSNGS55lg4t-VmBK2ottE_cGFq1zsvjiumAlI,14847
|
|
724
700
|
claude_mpm/services/socketio/__init__.py,sha256=PS-2twllga-2mhSfKdu4MgpikfKp_730gMLAqU_9YX4,556
|
|
@@ -993,10 +969,10 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
|
|
|
993
969
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
|
994
970
|
claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
|
|
995
971
|
claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
|
|
996
|
-
claude_mpm-5.4.
|
|
997
|
-
claude_mpm-5.4.
|
|
998
|
-
claude_mpm-5.4.
|
|
999
|
-
claude_mpm-5.4.
|
|
1000
|
-
claude_mpm-5.4.
|
|
1001
|
-
claude_mpm-5.4.
|
|
1002
|
-
claude_mpm-5.4.
|
|
972
|
+
claude_mpm-5.4.81.dist-info/licenses/LICENSE,sha256=ca3y_Rk4aPrbF6f62z8Ht5MJM9OAvbGlHvEDcj9vUQ4,3867
|
|
973
|
+
claude_mpm-5.4.81.dist-info/licenses/LICENSE-FAQ.md,sha256=TxfEkXVCK98RzDOer09puc7JVCP_q_bN4dHtZKHCMcM,5104
|
|
974
|
+
claude_mpm-5.4.81.dist-info/METADATA,sha256=fOQVWlYERj2MKYvoU71D1bChHaowwX-6iGyt2HiC730,38503
|
|
975
|
+
claude_mpm-5.4.81.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
976
|
+
claude_mpm-5.4.81.dist-info/entry_points.txt,sha256=n-Uk4vwHPpuvu-g_I7-GHORzTnN_m6iyOsoLveKKD0E,228
|
|
977
|
+
claude_mpm-5.4.81.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
|
978
|
+
claude_mpm-5.4.81.dist-info/RECORD,,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|