claude-mpm 5.6.5__py3-none-any.whl → 5.6.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +5 -3
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +5 -0
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/core/config.py +27 -19
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +16 -16
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.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-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-312.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-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/installer.py +41 -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-312.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-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
- claude_mpm/scripts/claude-hook-handler.sh +5 -5
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/skills/git_skill_source_manager.py +79 -8
- claude_mpm/services/skills/selective_skill_deployer.py +28 -0
- claude_mpm/services/skills/skill_discovery_service.py +17 -1
- claude_mpm/services/skills_deployer.py +31 -5
- {claude_mpm-5.6.5.dist-info → claude_mpm-5.6.8.dist-info}/METADATA +1 -1
- {claude_mpm-5.6.5.dist-info → claude_mpm-5.6.8.dist-info}/RECORD +39 -26
- {claude_mpm-5.6.5.dist-info → claude_mpm-5.6.8.dist-info}/WHEEL +0 -0
- {claude_mpm-5.6.5.dist-info → claude_mpm-5.6.8.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.6.5.dist-info → claude_mpm-5.6.8.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.6.5.dist-info → claude_mpm-5.6.8.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.6.5.dist-info → claude_mpm-5.6.8.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.6.
|
|
1
|
+
5.6.8
|
|
@@ -11,6 +11,7 @@ for better UX. Handles errors gracefully with actionable messages.
|
|
|
11
11
|
|
|
12
12
|
import json
|
|
13
13
|
import logging
|
|
14
|
+
import os
|
|
14
15
|
import re
|
|
15
16
|
|
|
16
17
|
from ...config.skill_sources import SkillSource, SkillSourceConfiguration
|
|
@@ -20,6 +21,33 @@ from ...services.skills.skill_discovery_service import SkillDiscoveryService
|
|
|
20
21
|
logger = logging.getLogger(__name__)
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
def _get_github_token(source: SkillSource | None = None) -> str | None:
|
|
25
|
+
"""Get GitHub token with source-specific override support.
|
|
26
|
+
|
|
27
|
+
Priority: source.token > GITHUB_TOKEN > GH_TOKEN
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
source: Optional SkillSource to check for per-source token
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
GitHub token if found, None otherwise
|
|
34
|
+
|
|
35
|
+
Security Note:
|
|
36
|
+
Token is never logged or printed to avoid exposure.
|
|
37
|
+
"""
|
|
38
|
+
# Priority 1: Per-source token (env var reference or direct)
|
|
39
|
+
if source and source.token:
|
|
40
|
+
if source.token.startswith("$"):
|
|
41
|
+
# Env var reference: $VAR_NAME -> os.environ.get("VAR_NAME")
|
|
42
|
+
env_var_name = source.token[1:]
|
|
43
|
+
return os.environ.get(env_var_name)
|
|
44
|
+
# Direct token (not recommended but supported)
|
|
45
|
+
return source.token
|
|
46
|
+
|
|
47
|
+
# Priority 2-3: Global environment variables
|
|
48
|
+
return os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
|
49
|
+
|
|
50
|
+
|
|
23
51
|
def _test_skill_repository_access(source: SkillSource) -> dict:
|
|
24
52
|
"""Test if skill repository is accessible via GitHub API.
|
|
25
53
|
|
|
@@ -58,7 +86,13 @@ def _test_skill_repository_access(source: SkillSource) -> dict:
|
|
|
58
86
|
# Test GitHub API access
|
|
59
87
|
api_url = f"https://api.github.com/repos/{owner_repo}"
|
|
60
88
|
|
|
61
|
-
|
|
89
|
+
# Build headers with authentication if token available
|
|
90
|
+
headers = {"Accept": "application/vnd.github+json"}
|
|
91
|
+
token = _get_github_token(source)
|
|
92
|
+
if token:
|
|
93
|
+
headers["Authorization"] = f"token {token}"
|
|
94
|
+
|
|
95
|
+
response = requests.get(api_url, headers=headers, timeout=10)
|
|
62
96
|
|
|
63
97
|
if response.status_code == 200:
|
|
64
98
|
return {"accessible": True, "error": None}
|
|
@@ -68,9 +102,14 @@ def _test_skill_repository_access(source: SkillSource) -> dict:
|
|
|
68
102
|
"error": f"Repository not found: {owner_repo}",
|
|
69
103
|
}
|
|
70
104
|
if response.status_code == 403:
|
|
105
|
+
error_msg = "Access denied (private repository or rate limit)"
|
|
106
|
+
if not token:
|
|
107
|
+
error_msg += (
|
|
108
|
+
". Try setting GITHUB_TOKEN environment variable for private repos"
|
|
109
|
+
)
|
|
71
110
|
return {
|
|
72
111
|
"accessible": False,
|
|
73
|
-
"error":
|
|
112
|
+
"error": error_msg,
|
|
74
113
|
}
|
|
75
114
|
return {
|
|
76
115
|
"accessible": False,
|
|
@@ -263,6 +302,15 @@ def handle_add_skill_source(args) -> int:
|
|
|
263
302
|
|
|
264
303
|
# Create new source
|
|
265
304
|
enabled = not args.disabled
|
|
305
|
+
token = getattr(args, "token", None)
|
|
306
|
+
|
|
307
|
+
# Security warning for direct tokens
|
|
308
|
+
if token and not token.startswith("$"):
|
|
309
|
+
print("⚠️ Warning: Direct token values in config are not recommended")
|
|
310
|
+
print(" Consider using environment variable reference instead:")
|
|
311
|
+
print(" --token $MY_PRIVATE_TOKEN")
|
|
312
|
+
print()
|
|
313
|
+
|
|
266
314
|
source = SkillSource(
|
|
267
315
|
id=source_id,
|
|
268
316
|
type="git",
|
|
@@ -270,6 +318,7 @@ def handle_add_skill_source(args) -> int:
|
|
|
270
318
|
branch=args.branch,
|
|
271
319
|
priority=args.priority,
|
|
272
320
|
enabled=enabled,
|
|
321
|
+
token=token,
|
|
273
322
|
)
|
|
274
323
|
|
|
275
324
|
# Determine if we should test
|
|
@@ -538,6 +538,7 @@ class SkillsManagementCommand(BaseCommand):
|
|
|
538
538
|
toolchain = getattr(args, "toolchain", None)
|
|
539
539
|
categories = getattr(args, "categories", None)
|
|
540
540
|
force = getattr(args, "force", False)
|
|
541
|
+
deploy_all = getattr(args, "all", False)
|
|
541
542
|
|
|
542
543
|
if collection:
|
|
543
544
|
console.print(
|
|
@@ -548,14 +549,15 @@ class SkillsManagementCommand(BaseCommand):
|
|
|
548
549
|
"\n[bold cyan]Deploying skills from default collection...[/bold cyan]\n"
|
|
549
550
|
)
|
|
550
551
|
|
|
551
|
-
#
|
|
552
|
-
#
|
|
552
|
+
# Use selective deployment unless --all flag is provided
|
|
553
|
+
# Selective mode deploys only agent-referenced skills
|
|
554
|
+
# --all mode deploys all available skills from the collection
|
|
553
555
|
result = self.skills_deployer.deploy_skills(
|
|
554
556
|
collection=collection,
|
|
555
557
|
toolchain=toolchain,
|
|
556
558
|
categories=categories,
|
|
557
559
|
force=force,
|
|
558
|
-
selective=
|
|
560
|
+
selective=not deploy_all,
|
|
559
561
|
)
|
|
560
562
|
|
|
561
563
|
# Display results
|
|
@@ -76,6 +76,10 @@ def add_skill_source_subparser(subparsers) -> argparse.ArgumentParser:
|
|
|
76
76
|
dest="skip_test",
|
|
77
77
|
help="Skip immediate testing (not recommended)",
|
|
78
78
|
)
|
|
79
|
+
add_parser.add_argument(
|
|
80
|
+
"--token",
|
|
81
|
+
help="GitHub token or env var reference (e.g., ghp_xxx or $PRIVATE_TOKEN)",
|
|
82
|
+
)
|
|
79
83
|
|
|
80
84
|
# Remove repository
|
|
81
85
|
remove_parser = skill_source_subparsers.add_parser(
|
|
@@ -167,6 +167,11 @@ def add_skills_subparser(subparsers) -> argparse.ArgumentParser:
|
|
|
167
167
|
action="store_true",
|
|
168
168
|
help="Force redeployment of already deployed skills",
|
|
169
169
|
)
|
|
170
|
+
deploy_github_parser.add_argument(
|
|
171
|
+
"--all",
|
|
172
|
+
action="store_true",
|
|
173
|
+
help="Deploy all available skills, not just agent-referenced ones",
|
|
174
|
+
)
|
|
170
175
|
|
|
171
176
|
# List available GitHub skills
|
|
172
177
|
list_available_parser = skills_subparsers.add_parser(
|
|
@@ -54,6 +54,7 @@ class SkillSource:
|
|
|
54
54
|
branch: Git branch to use (default: "main")
|
|
55
55
|
priority: Priority for skill resolution (lower = higher precedence)
|
|
56
56
|
enabled: Whether this source should be synced
|
|
57
|
+
token: Optional GitHub token or env var reference (e.g., "$MY_TOKEN")
|
|
57
58
|
|
|
58
59
|
Priority System:
|
|
59
60
|
- 0: Reserved for system repository (highest precedence)
|
|
@@ -61,6 +62,12 @@ class SkillSource:
|
|
|
61
62
|
- 100-999: Normal priority custom sources
|
|
62
63
|
- 1000+: Low priority custom sources
|
|
63
64
|
|
|
65
|
+
Token Authentication:
|
|
66
|
+
- Direct token: "ghp_xxxxx" (stored in config, not recommended)
|
|
67
|
+
- Env var reference: "$PRIVATE_REPO_TOKEN" (resolved at runtime)
|
|
68
|
+
- If None, falls back to GITHUB_TOKEN or GH_TOKEN env vars
|
|
69
|
+
- Priority: source.token > GITHUB_TOKEN > GH_TOKEN
|
|
70
|
+
|
|
64
71
|
Example:
|
|
65
72
|
>>> source = SkillSource(
|
|
66
73
|
... id="system",
|
|
@@ -70,6 +77,12 @@ class SkillSource:
|
|
|
70
77
|
... )
|
|
71
78
|
>>> source.validate()
|
|
72
79
|
[]
|
|
80
|
+
>>> private_source = SkillSource(
|
|
81
|
+
... id="private",
|
|
82
|
+
... type="git",
|
|
83
|
+
... url="https://github.com/myorg/private-skills",
|
|
84
|
+
... token="$PRIVATE_REPO_TOKEN"
|
|
85
|
+
... )
|
|
73
86
|
"""
|
|
74
87
|
|
|
75
88
|
id: str
|
|
@@ -78,6 +91,7 @@ class SkillSource:
|
|
|
78
91
|
branch: str = "main"
|
|
79
92
|
priority: int = 100
|
|
80
93
|
enabled: bool = True
|
|
94
|
+
token: Optional[str] = None
|
|
81
95
|
|
|
82
96
|
def __post_init__(self):
|
|
83
97
|
"""Validate skill source configuration after initialization.
|
|
@@ -262,6 +276,7 @@ class SkillSourceConfiguration:
|
|
|
262
276
|
branch=source_data.get("branch", "main"),
|
|
263
277
|
priority=source_data.get("priority", 100),
|
|
264
278
|
enabled=source_data.get("enabled", True),
|
|
279
|
+
token=source_data.get("token"),
|
|
265
280
|
)
|
|
266
281
|
sources.append(source)
|
|
267
282
|
except (KeyError, ValueError) as e:
|
|
@@ -326,6 +341,7 @@ class SkillSourceConfiguration:
|
|
|
326
341
|
"branch": source.branch,
|
|
327
342
|
"priority": source.priority,
|
|
328
343
|
"enabled": source.enabled,
|
|
344
|
+
**({"token": source.token} if source.token else {}),
|
|
329
345
|
}
|
|
330
346
|
for source in sources
|
|
331
347
|
]
|
claude_mpm/core/config.py
CHANGED
|
@@ -12,11 +12,10 @@ import threading
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
14
14
|
|
|
15
|
-
import yaml
|
|
16
|
-
|
|
17
15
|
from claude_mpm.core.logging_utils import get_logger
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
# Lazy import ConfigurationManager to avoid importing yaml at module level
|
|
18
|
+
# This prevents hook errors when yaml isn't available in the execution environment
|
|
20
19
|
from .exceptions import ConfigurationError, FileOperationError
|
|
21
20
|
from .unified_paths import get_path_manager
|
|
22
21
|
|
|
@@ -104,6 +103,9 @@ class Config:
|
|
|
104
103
|
Config._initialized = True
|
|
105
104
|
logger.debug("Initializing Config singleton for the first time")
|
|
106
105
|
|
|
106
|
+
# Lazy import ConfigurationManager at runtime to avoid yaml import at module level
|
|
107
|
+
from ..utils.config_manager import ConfigurationManager
|
|
108
|
+
|
|
107
109
|
# Initialize instance variables inside the lock to ensure thread safety
|
|
108
110
|
self._config: Dict[str, Any] = {}
|
|
109
111
|
self._env_prefix = env_prefix
|
|
@@ -224,21 +226,6 @@ class Config:
|
|
|
224
226
|
f"Response logging format: {response_logging.get('format', 'json')}"
|
|
225
227
|
)
|
|
226
228
|
|
|
227
|
-
except yaml.YAMLError as e:
|
|
228
|
-
logger.error(f"YAML syntax error in {file_path}: {e}")
|
|
229
|
-
if hasattr(e, "problem_mark"):
|
|
230
|
-
mark = e.problem_mark
|
|
231
|
-
logger.error(f"Error at line {mark.line + 1}, column {mark.column + 1}")
|
|
232
|
-
logger.info(
|
|
233
|
-
"TIP: Validate your YAML at https://www.yamllint.com/ or run: python scripts/validate_configuration.py"
|
|
234
|
-
)
|
|
235
|
-
logger.info(
|
|
236
|
-
"TIP: Common issue - YAML requires spaces, not tabs. Fix with: sed -i '' 's/\t/ /g' "
|
|
237
|
-
+ str(file_path)
|
|
238
|
-
)
|
|
239
|
-
# Store error for later retrieval
|
|
240
|
-
self._config["_load_error"] = str(e)
|
|
241
|
-
|
|
242
229
|
except json.JSONDecodeError as e:
|
|
243
230
|
logger.error(f"JSON syntax error in {file_path}: {e}")
|
|
244
231
|
logger.error(f"Error at line {e.lineno}, column {e.colno}")
|
|
@@ -255,7 +242,28 @@ class Config:
|
|
|
255
242
|
},
|
|
256
243
|
) from e
|
|
257
244
|
except Exception as e:
|
|
258
|
-
#
|
|
245
|
+
# Handle YAML errors without importing yaml at module level
|
|
246
|
+
# ConfigurationManager.load_yaml raises yaml.YAMLError, but we don't want to import yaml
|
|
247
|
+
# Check if it's a YAML error by class name to avoid import
|
|
248
|
+
if e.__class__.__name__ == "YAMLError":
|
|
249
|
+
logger.error(f"YAML syntax error in {file_path}: {e}")
|
|
250
|
+
if hasattr(e, "problem_mark"):
|
|
251
|
+
mark = e.problem_mark
|
|
252
|
+
logger.error(
|
|
253
|
+
f"Error at line {mark.line + 1}, column {mark.column + 1}"
|
|
254
|
+
)
|
|
255
|
+
logger.info(
|
|
256
|
+
"TIP: Validate your YAML at https://www.yamllint.com/ or run: python scripts/validate_configuration.py"
|
|
257
|
+
)
|
|
258
|
+
logger.info(
|
|
259
|
+
"TIP: Common issue - YAML requires spaces, not tabs. Fix with: sed -i '' 's/\t/ /g' "
|
|
260
|
+
+ str(file_path)
|
|
261
|
+
)
|
|
262
|
+
# Store error for later retrieval
|
|
263
|
+
self._config["_load_error"] = str(e)
|
|
264
|
+
return # Don't re-raise, we handled it
|
|
265
|
+
|
|
266
|
+
# Not a YAML error, wrap as configuration error
|
|
259
267
|
raise ConfigurationError(
|
|
260
268
|
f"Unexpected error loading configuration from {file_path}: {e}",
|
|
261
269
|
context={
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const env={}
|
|
1
|
+
export const env={}
|
|
@@ -43,10 +43,10 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
43
43
|
vec2 v = ab*vec2(-cs.y,cs.x);
|
|
44
44
|
w = w + dot(p-u,v)/(dot(p-u,u)+dot(v,v));
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
// compute final point and distance
|
|
48
48
|
float d = length(p-ab*vec2(cos(w),sin(w)));
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
// return signed distance
|
|
51
51
|
return (dot(p/ab,p/ab)>1.0) ? d : -d;
|
|
52
52
|
}
|
|
@@ -55,16 +55,16 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
55
55
|
|
|
56
56
|
uniform mat3 uPanZoomMatrix;
|
|
57
57
|
uniform int uAtlasSize;
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
// instanced
|
|
60
60
|
in vec2 aPosition; // a vertex from the unit square
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
in mat3 aTransform; // used to transform verticies, eg into a bounding box
|
|
63
63
|
in int aVertType; // the type of thing we are rendering
|
|
64
64
|
|
|
65
65
|
// the z-index that is output when using picking mode
|
|
66
66
|
in vec4 aIndex;
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
// For textures
|
|
69
69
|
in int aAtlasId; // which shader unit/atlas to use
|
|
70
70
|
in vec4 aTex; // x/y/w/h of texture in atlas
|
|
@@ -84,7 +84,7 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
84
84
|
out vec4 vColor;
|
|
85
85
|
out vec2 vPosition;
|
|
86
86
|
// flat values are not interpolated
|
|
87
|
-
flat out int vAtlasId;
|
|
87
|
+
flat out int vAtlasId;
|
|
88
88
|
flat out int vVertType;
|
|
89
89
|
flat out vec2 vTopRight;
|
|
90
90
|
flat out vec2 vBotLeft;
|
|
@@ -92,7 +92,7 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
92
92
|
flat out vec4 vBorderColor;
|
|
93
93
|
flat out vec2 vBorderWidth;
|
|
94
94
|
flat out vec4 vIndex;
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
void main(void) {
|
|
97
97
|
int vid = gl_VertexID;
|
|
98
98
|
vec2 position = aPosition; // TODO make this a vec3, simplifies some code below
|
|
@@ -115,7 +115,7 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
115
115
|
|
|
116
116
|
gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0);
|
|
117
117
|
}
|
|
118
|
-
else if(aVertType == `).concat(_t," || aVertType == ").concat(pa,`
|
|
118
|
+
else if(aVertType == `).concat(_t," || aVertType == ").concat(pa,`
|
|
119
119
|
|| aVertType == `).concat(sn," || aVertType == ").concat(ga,`) { // simple shapes
|
|
120
120
|
|
|
121
121
|
// the bounding box is needed by the fragment shader
|
|
@@ -145,7 +145,7 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
145
145
|
|
|
146
146
|
gl_Position = vec4(uPanZoomMatrix * vec3(point, 1.0), 1.0);
|
|
147
147
|
vColor = aColor;
|
|
148
|
-
}
|
|
148
|
+
}
|
|
149
149
|
else if(aVertType == `).concat(Xl,`) {
|
|
150
150
|
vec2 pointA = aPointAPointB.xy;
|
|
151
151
|
vec2 pointB = aPointAPointB.zw;
|
|
@@ -194,7 +194,7 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
vColor = aColor;
|
|
197
|
-
}
|
|
197
|
+
}
|
|
198
198
|
else if(aVertType == `).concat(Ts,` && vid < 3) {
|
|
199
199
|
// massage the first triangle into an edge arrow
|
|
200
200
|
if(vid == 0)
|
|
@@ -246,16 +246,16 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
246
246
|
`).concat(vm,`
|
|
247
247
|
|
|
248
248
|
vec4 blend(vec4 top, vec4 bot) { // blend colors with premultiplied alpha
|
|
249
|
-
return vec4(
|
|
249
|
+
return vec4(
|
|
250
250
|
top.rgb + (bot.rgb * (1.0 - top.a)),
|
|
251
|
-
top.a + (bot.a * (1.0 - top.a))
|
|
251
|
+
top.a + (bot.a * (1.0 - top.a))
|
|
252
252
|
);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
vec4 distInterp(vec4 cA, vec4 cB, float d) { // interpolate color using Signed Distance
|
|
256
256
|
// scale to the zoom level so that borders don't look blurry when zoomed in
|
|
257
257
|
// note 1.5 is an aribitrary value chosen because it looks good
|
|
258
|
-
return mix(cA, cB, 1.0 - smoothstep(0.0, 1.5 / uZoom, abs(d)));
|
|
258
|
+
return mix(cA, cB, 1.0 - smoothstep(0.0, 1.5 / uZoom, abs(d)));
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
void main(void) {
|
|
@@ -263,7 +263,7 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
263
263
|
// look up the texel from the texture unit
|
|
264
264
|
`).concat(i.map(function(u){return"if(vAtlasId == ".concat(u,") outColor = texture(uTexture").concat(u,", vTexCoord);")}).join(`
|
|
265
265
|
else `),`
|
|
266
|
-
}
|
|
266
|
+
}
|
|
267
267
|
else if(vVertType == `).concat(Ts,`) {
|
|
268
268
|
// mimics how canvas renderer uses context.globalCompositeOperation = 'destination-out';
|
|
269
269
|
outColor = blend(vColor, uBGColor);
|
|
@@ -272,7 +272,7 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
272
272
|
else if(vVertType == `).concat(_t,` && vBorderWidth == vec2(0.0)) { // simple rectangle with no border
|
|
273
273
|
outColor = vColor; // unit square is already transformed to the rectangle, nothing else needs to be done
|
|
274
274
|
}
|
|
275
|
-
else if(vVertType == `).concat(_t," || vVertType == ").concat(pa,`
|
|
275
|
+
else if(vVertType == `).concat(_t," || vVertType == ").concat(pa,`
|
|
276
276
|
|| vVertType == `).concat(sn," || vVertType == ").concat(ga,`) { // use SDF
|
|
277
277
|
|
|
278
278
|
float outerBorder = vBorderWidth[0];
|
|
@@ -307,7 +307,7 @@ https://github.com/jquery/jquery/blob/master/src/event.js
|
|
|
307
307
|
vec4 outerColor = outerBorder == 0.0 ? vec4(0) : vBorderColor;
|
|
308
308
|
vec4 innerBorderColor = blend(vBorderColor, vColor);
|
|
309
309
|
outColor = distInterp(innerBorderColor, outerColor, d);
|
|
310
|
-
}
|
|
310
|
+
}
|
|
311
311
|
else {
|
|
312
312
|
vec4 outerColor;
|
|
313
313
|
if(innerBorder == 0.0 && outerBorder == 0.0) {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -537,6 +537,44 @@ main "$@"
|
|
|
537
537
|
except Exception as e:
|
|
538
538
|
self.logger.warning(f"Could not clean up old settings file: {e}")
|
|
539
539
|
|
|
540
|
+
def _fix_status_line(self, settings: Dict) -> None:
|
|
541
|
+
"""Fix statusLine command to handle both output style schema formats.
|
|
542
|
+
|
|
543
|
+
The statusLine command receives input in different formats:
|
|
544
|
+
- Newer format: {"activeOutputStyle": "Claude MPM", ...}
|
|
545
|
+
- Older format: {"output_style": {"name": "Claude MPM"}, ...}
|
|
546
|
+
|
|
547
|
+
This method ensures the jq expression checks both locations.
|
|
548
|
+
|
|
549
|
+
Args:
|
|
550
|
+
settings: The settings dictionary to update
|
|
551
|
+
"""
|
|
552
|
+
if "statusLine" not in settings:
|
|
553
|
+
return
|
|
554
|
+
|
|
555
|
+
status_line = settings.get("statusLine", {})
|
|
556
|
+
if "command" not in status_line:
|
|
557
|
+
return
|
|
558
|
+
|
|
559
|
+
command = status_line["command"]
|
|
560
|
+
|
|
561
|
+
# Pattern to match: '.output_style.name // "default"'
|
|
562
|
+
# We need to update it to: '.output_style.name // .activeOutputStyle // "default"'
|
|
563
|
+
old_pattern = r'\.output_style\.name\s*//\s*"default"'
|
|
564
|
+
new_pattern = '.output_style.name // .activeOutputStyle // "default"'
|
|
565
|
+
|
|
566
|
+
# Check if the command needs updating
|
|
567
|
+
if re.search(old_pattern, command) and ".activeOutputStyle" not in command:
|
|
568
|
+
updated_command = re.sub(old_pattern, new_pattern, command)
|
|
569
|
+
settings["statusLine"]["command"] = updated_command
|
|
570
|
+
self.logger.info(
|
|
571
|
+
"Fixed statusLine command to handle both output style schemas"
|
|
572
|
+
)
|
|
573
|
+
else:
|
|
574
|
+
self.logger.debug(
|
|
575
|
+
"StatusLine command already supports both schemas or not present"
|
|
576
|
+
)
|
|
577
|
+
|
|
540
578
|
def _update_claude_settings(self, hook_script_path: Path) -> None:
|
|
541
579
|
"""Update Claude settings to use the installed hook."""
|
|
542
580
|
self.logger.info("Updating Claude settings...")
|
|
@@ -598,6 +636,9 @@ main "$@"
|
|
|
598
636
|
}
|
|
599
637
|
]
|
|
600
638
|
|
|
639
|
+
# Fix statusLine command to handle both output style schemas
|
|
640
|
+
self._fix_status_line(settings)
|
|
641
|
+
|
|
601
642
|
# Write settings to settings.json
|
|
602
643
|
with self.settings_file.open("w") as f:
|
|
603
644
|
json.dump(settings, f, indent=2)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -125,7 +125,7 @@ find_python_command() {
|
|
|
125
125
|
# 1. Check for UV project first (uv.lock or pyproject.toml with uv)
|
|
126
126
|
if [ -f "$CLAUDE_MPM_ROOT/uv.lock" ]; then
|
|
127
127
|
if command -v uv &> /dev/null; then
|
|
128
|
-
echo "uv run python"
|
|
128
|
+
echo "uv run --directory \"$CLAUDE_MPM_ROOT\" python"
|
|
129
129
|
return
|
|
130
130
|
fi
|
|
131
131
|
fi
|
|
@@ -219,8 +219,8 @@ log_debug() {
|
|
|
219
219
|
|
|
220
220
|
# Test Python works and module exists
|
|
221
221
|
# Handle UV's multi-word command specially
|
|
222
|
-
if [[ "$PYTHON_CMD" == "uv run
|
|
223
|
-
if ! uv run python -c "import claude_mpm" 2>/dev/null; then
|
|
222
|
+
if [[ "$PYTHON_CMD" == "uv run"* ]]; then
|
|
223
|
+
if ! uv run --directory "$CLAUDE_MPM_ROOT" python -c "import claude_mpm" 2>/dev/null; then
|
|
224
224
|
log_debug "claude_mpm module not available, continuing without hook"
|
|
225
225
|
echo '{"action": "continue"}'
|
|
226
226
|
exit 0
|
|
@@ -237,8 +237,8 @@ fi
|
|
|
237
237
|
# Use exec to replace the shell process with Python
|
|
238
238
|
# Handle UV's multi-word command specially
|
|
239
239
|
# Suppress RuntimeWarning to prevent stderr output (which causes hook errors)
|
|
240
|
-
if [[ "$PYTHON_CMD" == "uv run
|
|
241
|
-
exec uv run python -W ignore::RuntimeWarning -m claude_mpm.hooks.claude_hooks.hook_handler "$@" 2>/tmp/claude-mpm-hook-error.log
|
|
240
|
+
if [[ "$PYTHON_CMD" == "uv run"* ]]; then
|
|
241
|
+
exec uv run --directory "$CLAUDE_MPM_ROOT" python -W ignore::RuntimeWarning -m claude_mpm.hooks.claude_hooks.hook_handler "$@" 2>/tmp/claude-mpm-hook-error.log
|
|
242
242
|
else
|
|
243
243
|
exec "$PYTHON_CMD" -W ignore::RuntimeWarning -m claude_mpm.hooks.claude_hooks.hook_handler "$@" 2>/tmp/claude-mpm-hook-error.log
|
|
244
244
|
fi
|
|
@@ -39,10 +39,10 @@ import logging
|
|
|
39
39
|
from pathlib import Path
|
|
40
40
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
41
41
|
|
|
42
|
-
from
|
|
42
|
+
from claude_mpm.services.agents.single_tier_deployment_service import (
|
|
43
43
|
SingleTierDeploymentService,
|
|
44
44
|
)
|
|
45
|
-
from
|
|
45
|
+
from claude_mpm.services.agents.toolchain_detector import ToolchainDetector
|
|
46
46
|
|
|
47
47
|
logger = logging.getLogger(__name__)
|
|
48
48
|
|
|
@@ -30,12 +30,12 @@ from datetime import datetime, timezone
|
|
|
30
30
|
from pathlib import Path
|
|
31
31
|
from typing import Any, Dict, List, Optional
|
|
32
32
|
|
|
33
|
-
from
|
|
34
|
-
from
|
|
35
|
-
from
|
|
33
|
+
from claude_mpm.config.agent_sources import AgentSourceConfiguration
|
|
34
|
+
from claude_mpm.models.git_repository import GitRepository
|
|
35
|
+
from claude_mpm.services.agents.deployment.remote_agent_discovery_service import (
|
|
36
36
|
RemoteAgentDiscoveryService,
|
|
37
37
|
)
|
|
38
|
-
from
|
|
38
|
+
from claude_mpm.services.agents.git_source_manager import GitSourceManager
|
|
39
39
|
|
|
40
40
|
logger = logging.getLogger(__name__)
|
|
41
41
|
|
|
@@ -16,6 +16,7 @@ Trade-offs:
|
|
|
16
16
|
- Flexibility: Easy to extend with skills-specific features
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
+
import os
|
|
19
20
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
20
21
|
from datetime import datetime, timezone
|
|
21
22
|
from pathlib import Path
|
|
@@ -32,6 +33,46 @@ from claude_mpm.services.skills.skill_discovery_service import SkillDiscoverySer
|
|
|
32
33
|
logger = get_logger(__name__)
|
|
33
34
|
|
|
34
35
|
|
|
36
|
+
def _get_github_token(source: Optional[SkillSource] = None) -> Optional[str]:
|
|
37
|
+
"""Get GitHub token with source-specific override support.
|
|
38
|
+
|
|
39
|
+
Priority: source.token > GITHUB_TOKEN > GH_TOKEN
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
source: Optional SkillSource to check for per-source token
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
GitHub token if found, None otherwise
|
|
46
|
+
|
|
47
|
+
Token Resolution:
|
|
48
|
+
1. If source has token starting with "$", resolve as env var
|
|
49
|
+
2. If source has direct token, use it (not recommended for security)
|
|
50
|
+
3. Fall back to GITHUB_TOKEN env var
|
|
51
|
+
4. Fall back to GH_TOKEN env var
|
|
52
|
+
5. Return None if no token found
|
|
53
|
+
|
|
54
|
+
Security Note:
|
|
55
|
+
Token is never logged or printed to avoid exposure.
|
|
56
|
+
Direct tokens in config are discouraged - use env var refs ($VAR_NAME).
|
|
57
|
+
|
|
58
|
+
Example:
|
|
59
|
+
>>> source = SkillSource(..., token="$PRIVATE_TOKEN")
|
|
60
|
+
>>> token = _get_github_token(source) # Resolves $PRIVATE_TOKEN from env
|
|
61
|
+
>>> token = _get_github_token() # Falls back to GITHUB_TOKEN
|
|
62
|
+
"""
|
|
63
|
+
# Priority 1: Per-source token (env var reference or direct)
|
|
64
|
+
if source and source.token:
|
|
65
|
+
if source.token.startswith("$"):
|
|
66
|
+
# Env var reference: $VAR_NAME -> os.environ.get("VAR_NAME")
|
|
67
|
+
env_var_name = source.token[1:]
|
|
68
|
+
return os.environ.get(env_var_name)
|
|
69
|
+
# Direct token (not recommended but supported)
|
|
70
|
+
return source.token
|
|
71
|
+
|
|
72
|
+
# Priority 2-3: Global environment variables
|
|
73
|
+
return os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
|
74
|
+
|
|
75
|
+
|
|
35
76
|
class GitSkillSourceManager:
|
|
36
77
|
"""Manages multiple Git-based skill sources with priority resolution.
|
|
37
78
|
|
|
@@ -217,9 +258,21 @@ class GitSkillSourceManager:
|
|
|
217
258
|
)
|
|
218
259
|
|
|
219
260
|
# Discover skills in cache
|
|
261
|
+
self.logger.debug(f"Scanning cache path for skills: {cache_path}")
|
|
220
262
|
discovery_service = SkillDiscoveryService(cache_path)
|
|
221
263
|
discovered_skills = discovery_service.discover_skills()
|
|
222
264
|
|
|
265
|
+
# Log discovery results
|
|
266
|
+
if len(discovered_skills) == 0:
|
|
267
|
+
self.logger.info(
|
|
268
|
+
f"No SKILL.md files found in {cache_path}. "
|
|
269
|
+
"Ensure your skill source has SKILL.md files with valid frontmatter."
|
|
270
|
+
)
|
|
271
|
+
else:
|
|
272
|
+
self.logger.debug(
|
|
273
|
+
f"Successfully parsed {len(discovered_skills)} skills from {cache_path}"
|
|
274
|
+
)
|
|
275
|
+
|
|
223
276
|
# Build result
|
|
224
277
|
result = {
|
|
225
278
|
"synced": True,
|
|
@@ -469,7 +522,7 @@ class GitSkillSourceManager:
|
|
|
469
522
|
# Step 1: Discover all files via GitHub Tree API (single request)
|
|
470
523
|
# This discovers the COMPLETE repository structure (272 files for skills)
|
|
471
524
|
all_files = self._discover_repository_files_via_tree_api(
|
|
472
|
-
owner_repo, source.branch
|
|
525
|
+
owner_repo, source.branch, source
|
|
473
526
|
)
|
|
474
527
|
|
|
475
528
|
if not all_files:
|
|
@@ -504,7 +557,7 @@ class GitSkillSourceManager:
|
|
|
504
557
|
raw_url = f"https://raw.githubusercontent.com/{owner_repo}/{source.branch}/{file_path}"
|
|
505
558
|
cache_file = cache_path / file_path
|
|
506
559
|
future = executor.submit(
|
|
507
|
-
self._download_file_with_etag, raw_url, cache_file, force
|
|
560
|
+
self._download_file_with_etag, raw_url, cache_file, force, source
|
|
508
561
|
)
|
|
509
562
|
future_to_file[future] = file_path
|
|
510
563
|
|
|
@@ -533,7 +586,7 @@ class GitSkillSourceManager:
|
|
|
533
586
|
return files_updated, files_cached
|
|
534
587
|
|
|
535
588
|
def _discover_repository_files_via_tree_api(
|
|
536
|
-
self, owner_repo: str, branch: str
|
|
589
|
+
self, owner_repo: str, branch: str, source: Optional[SkillSource] = None
|
|
537
590
|
) -> List[str]:
|
|
538
591
|
"""Discover all files in repository using GitHub Git Tree API.
|
|
539
592
|
|
|
@@ -596,9 +649,17 @@ class GitSkillSourceManager:
|
|
|
596
649
|
)
|
|
597
650
|
self.logger.debug(f"Fetching commit SHA from {refs_url}")
|
|
598
651
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
)
|
|
652
|
+
# Build headers with authentication if token available
|
|
653
|
+
headers = {"Accept": "application/vnd.github+json"}
|
|
654
|
+
token = _get_github_token(source)
|
|
655
|
+
if token:
|
|
656
|
+
headers["Authorization"] = f"token {token}"
|
|
657
|
+
if source and source.token:
|
|
658
|
+
self.logger.debug(f"Using source-specific token for {source.id}")
|
|
659
|
+
else:
|
|
660
|
+
self.logger.debug("Using GitHub token for authentication")
|
|
661
|
+
|
|
662
|
+
refs_response = requests.get(refs_url, headers=headers, timeout=30)
|
|
602
663
|
|
|
603
664
|
# Check for rate limiting
|
|
604
665
|
if refs_response.status_code == 403:
|
|
@@ -621,7 +682,7 @@ class GitSkillSourceManager:
|
|
|
621
682
|
self.logger.debug(f"Fetching recursive tree from {tree_url}")
|
|
622
683
|
tree_response = requests.get(
|
|
623
684
|
tree_url,
|
|
624
|
-
headers=
|
|
685
|
+
headers=headers, # Reuse headers with auth from Step 1
|
|
625
686
|
params=params,
|
|
626
687
|
timeout=30,
|
|
627
688
|
)
|
|
@@ -652,7 +713,11 @@ class GitSkillSourceManager:
|
|
|
652
713
|
return all_files
|
|
653
714
|
|
|
654
715
|
def _download_file_with_etag(
|
|
655
|
-
self,
|
|
716
|
+
self,
|
|
717
|
+
url: str,
|
|
718
|
+
local_path: Path,
|
|
719
|
+
force: bool = False,
|
|
720
|
+
source: Optional[SkillSource] = None,
|
|
656
721
|
) -> bool:
|
|
657
722
|
"""Download file from URL with ETag caching (thread-safe).
|
|
658
723
|
|
|
@@ -660,6 +725,7 @@ class GitSkillSourceManager:
|
|
|
660
725
|
url: Raw GitHub URL
|
|
661
726
|
local_path: Local file path to save to
|
|
662
727
|
force: Force download even if cached
|
|
728
|
+
source: Optional SkillSource for token resolution
|
|
663
729
|
|
|
664
730
|
Returns:
|
|
665
731
|
True if file was updated, False if cached
|
|
@@ -692,6 +758,11 @@ class GitSkillSourceManager:
|
|
|
692
758
|
if cached_etag and not force:
|
|
693
759
|
headers["If-None-Match"] = cached_etag
|
|
694
760
|
|
|
761
|
+
# Add GitHub authentication if token available
|
|
762
|
+
token = _get_github_token(source)
|
|
763
|
+
if token:
|
|
764
|
+
headers["Authorization"] = f"token {token}"
|
|
765
|
+
|
|
695
766
|
try:
|
|
696
767
|
response = requests.get(url, headers=headers, timeout=30)
|
|
697
768
|
|
|
@@ -50,6 +50,22 @@ logger = get_logger(__name__)
|
|
|
50
50
|
# Deployment tracking index file
|
|
51
51
|
DEPLOYED_INDEX_FILE = ".mpm-deployed-skills.json"
|
|
52
52
|
|
|
53
|
+
# Core PM skills that should always be deployed
|
|
54
|
+
# These are referenced in PM_INSTRUCTIONS.md with [SKILL: name] markers
|
|
55
|
+
# Without these skills, PM only sees placeholders, not actual content
|
|
56
|
+
PM_CORE_SKILLS = {
|
|
57
|
+
"mpm-delegation-patterns",
|
|
58
|
+
"mpm-verification-protocols",
|
|
59
|
+
"mpm-tool-usage-guide",
|
|
60
|
+
"mpm-git-file-tracking",
|
|
61
|
+
"mpm-pr-workflow",
|
|
62
|
+
"mpm-ticketing-integration",
|
|
63
|
+
"mpm-teaching-mode",
|
|
64
|
+
"mpm-bug-reporting",
|
|
65
|
+
"mpm-circuit-breaker-enforcement",
|
|
66
|
+
"mpm-session-management",
|
|
67
|
+
}
|
|
68
|
+
|
|
53
69
|
# Core skills that are universally useful across all projects
|
|
54
70
|
# These are deployed when skill mapping returns too many skills (>60)
|
|
55
71
|
# Target: ~25-30 core skills for balanced functionality
|
|
@@ -376,6 +392,18 @@ def get_required_skills_from_agents(agents_dir: Path) -> Set[str]:
|
|
|
376
392
|
"(converted slashes to dashes)"
|
|
377
393
|
)
|
|
378
394
|
|
|
395
|
+
# Always include PM core skills to ensure PM_INSTRUCTIONS.md markers are resolved
|
|
396
|
+
# These skills are referenced in PM_INSTRUCTIONS.md and must be deployed
|
|
397
|
+
# for PM to see actual content instead of [SKILL: name] placeholders
|
|
398
|
+
before_pm_skills = len(normalized_skills)
|
|
399
|
+
normalized_skills = normalized_skills | PM_CORE_SKILLS
|
|
400
|
+
pm_skills_added = len(normalized_skills) - before_pm_skills
|
|
401
|
+
|
|
402
|
+
if pm_skills_added > 0:
|
|
403
|
+
logger.info(
|
|
404
|
+
f"Added {pm_skills_added} PM core skills to ensure PM_INSTRUCTIONS.md markers resolve"
|
|
405
|
+
)
|
|
406
|
+
|
|
379
407
|
return normalized_skills
|
|
380
408
|
|
|
381
409
|
|
|
@@ -188,6 +188,15 @@ class SkillDiscoveryService:
|
|
|
188
188
|
f"and {len(legacy_md_files)} legacy .md files in {self.skills_dir}"
|
|
189
189
|
)
|
|
190
190
|
|
|
191
|
+
# Log first few file paths for debugging
|
|
192
|
+
if all_skill_files:
|
|
193
|
+
sample_files = [
|
|
194
|
+
str(f.relative_to(self.skills_dir)) for f in all_skill_files[:5]
|
|
195
|
+
]
|
|
196
|
+
self.logger.debug(f"Sample skill files: {sample_files}")
|
|
197
|
+
else:
|
|
198
|
+
self.logger.debug(f"No SKILL.md or .md files found in {self.skills_dir}")
|
|
199
|
+
|
|
191
200
|
# Track deployment names to detect collisions
|
|
192
201
|
deployment_names = {}
|
|
193
202
|
|
|
@@ -226,7 +235,14 @@ class SkillDiscoveryService:
|
|
|
226
235
|
except Exception as e:
|
|
227
236
|
self.logger.warning(f"Failed to parse skill {skill_file}: {e}")
|
|
228
237
|
|
|
229
|
-
|
|
238
|
+
# Summary logging
|
|
239
|
+
parsed_count = len(skills)
|
|
240
|
+
failed_count = len(all_skill_files) - parsed_count
|
|
241
|
+
self.logger.info(
|
|
242
|
+
f"Discovered {parsed_count} skills from {self.skills_dir.name} "
|
|
243
|
+
f"({len(all_skill_files)} files found, {failed_count} failed to parse)"
|
|
244
|
+
)
|
|
245
|
+
|
|
230
246
|
return skills
|
|
231
247
|
|
|
232
248
|
def _parse_skill_file(self, skill_file: Path) -> Optional[Dict[str, Any]]:
|
|
@@ -28,7 +28,7 @@ References:
|
|
|
28
28
|
import json
|
|
29
29
|
import platform
|
|
30
30
|
import shutil
|
|
31
|
-
import subprocess
|
|
31
|
+
import subprocess # nosec B404 - subprocess needed for safe git operations
|
|
32
32
|
from pathlib import Path
|
|
33
33
|
from typing import Any, Dict, List, Optional
|
|
34
34
|
|
|
@@ -653,7 +653,7 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
653
653
|
f"Updating existing collection '{collection_name}' at {target_dir}"
|
|
654
654
|
)
|
|
655
655
|
try:
|
|
656
|
-
result = subprocess.run(
|
|
656
|
+
result = subprocess.run( # nosec B603 B607 - Safe: hardcoded git command
|
|
657
657
|
["git", "pull"],
|
|
658
658
|
cwd=target_dir,
|
|
659
659
|
capture_output=True,
|
|
@@ -684,7 +684,7 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
684
684
|
f"Installing new collection '{collection_name}' to {target_dir}"
|
|
685
685
|
)
|
|
686
686
|
try:
|
|
687
|
-
result = subprocess.run(
|
|
687
|
+
result = subprocess.run( # nosec B603 B607 - Safe: hardcoded git command
|
|
688
688
|
["git", "clone", repo_url, str(target_dir)],
|
|
689
689
|
capture_output=True,
|
|
690
690
|
text=True,
|
|
@@ -773,6 +773,32 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
773
773
|
if isinstance(skills_data, dict):
|
|
774
774
|
flat_skills = []
|
|
775
775
|
|
|
776
|
+
# Define valid top-level categories
|
|
777
|
+
VALID_CATEGORIES = {"universal", "toolchains"}
|
|
778
|
+
|
|
779
|
+
# Check for unknown categories and warn user
|
|
780
|
+
unknown_categories = set(skills_data.keys()) - VALID_CATEGORIES
|
|
781
|
+
if unknown_categories:
|
|
782
|
+
# Count skills in unknown categories
|
|
783
|
+
skipped_count = 0
|
|
784
|
+
for cat in unknown_categories:
|
|
785
|
+
cat_data = skills_data.get(cat, [])
|
|
786
|
+
if isinstance(cat_data, list):
|
|
787
|
+
skipped_count += len(cat_data)
|
|
788
|
+
elif isinstance(cat_data, dict):
|
|
789
|
+
# If it's a dict like toolchains, count nested skills
|
|
790
|
+
for skills_list in cat_data.values():
|
|
791
|
+
if isinstance(skills_list, list):
|
|
792
|
+
skipped_count += len(skills_list)
|
|
793
|
+
|
|
794
|
+
self.logger.warning(
|
|
795
|
+
f"Unknown categories in manifest will be skipped: "
|
|
796
|
+
f"{', '.join(sorted(unknown_categories))} ({skipped_count} skills)"
|
|
797
|
+
)
|
|
798
|
+
self.logger.info(
|
|
799
|
+
f"Valid top-level categories: {', '.join(sorted(VALID_CATEGORIES))}"
|
|
800
|
+
)
|
|
801
|
+
|
|
776
802
|
# Add universal skills
|
|
777
803
|
universal_skills = skills_data.get("universal", [])
|
|
778
804
|
if isinstance(universal_skills, list):
|
|
@@ -1022,12 +1048,12 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
1022
1048
|
"""
|
|
1023
1049
|
try:
|
|
1024
1050
|
if platform.system() == "Windows":
|
|
1025
|
-
result = subprocess.run(
|
|
1051
|
+
result = subprocess.run( # nosec B603 B607 - Safe: hardcoded tasklist command
|
|
1026
1052
|
["tasklist"], check=False, capture_output=True, text=True, timeout=5
|
|
1027
1053
|
)
|
|
1028
1054
|
return "claude" in result.stdout.lower()
|
|
1029
1055
|
# macOS and Linux
|
|
1030
|
-
result = subprocess.run(
|
|
1056
|
+
result = subprocess.run( # nosec B603 B607 - Safe: hardcoded ps command
|
|
1031
1057
|
["ps", "aux"], check=False, capture_output=True, text=True, timeout=5
|
|
1032
1058
|
)
|
|
1033
1059
|
# Look for "Claude Code" or "claude-code" process
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=9JfxhnDtr-8l3kCP2U5TVXSErptHoga8m7XA8zqgGOc,4
|
|
2
|
-
claude_mpm/VERSION,sha256=
|
|
2
|
+
claude_mpm/VERSION,sha256=TPELZ4bSYPd1-ct4QNuu3EP8d8XmrNtWst8upoSOwfY,6
|
|
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
|
|
@@ -19,7 +19,7 @@ claude_mpm/agents/agent_loader.py,sha256=lrE6IMmvFeGVFguNTmi8d6WYyMb8goqcXj6RmiP
|
|
|
19
19
|
claude_mpm/agents/agent_loader_integration.py,sha256=cU1LKCYvopZn66UefwzZxJUdTSxn6HLxdbukTjmP-KM,7280
|
|
20
20
|
claude_mpm/agents/agents_metadata.py,sha256=XklRSaYxKt8_2hnGn9xr-V15RMcm57Fi-QzPbAe4ZR4,9867
|
|
21
21
|
claude_mpm/agents/async_agent_loader.py,sha256=w9zk88SZUBycQeTHKrUiUez0CY_BrWZi13-EF6IOwWU,14597
|
|
22
|
-
claude_mpm/agents/base_agent.json,sha256=
|
|
22
|
+
claude_mpm/agents/base_agent.json,sha256=CTy670tMO_U7KiVuqtjk4LNU-TDociRNHX_J6hfEcH4,27615
|
|
23
23
|
claude_mpm/agents/frontmatter_validator.py,sha256=H0R7rCrNdaok5q7yCxEX2uiIcELU286tgGbTK05tRf0,27471
|
|
24
24
|
claude_mpm/agents/system_agent_config.py,sha256=19axX46jzvY6svETjfMaFyAYtgbQO2PRXKJ-VYnCPDk,24137
|
|
25
25
|
claude_mpm/agents/templates/README.md,sha256=qqhKh10y2CGuoytQmqlQtXCa_RD1ZmeT0m24S5VPQnI,18511
|
|
@@ -98,8 +98,8 @@ claude_mpm/cli/commands/postmortem.py,sha256=QkEymFR43IyN2dHBlaEHxsrDVrmhApLNJCp
|
|
|
98
98
|
claude_mpm/cli/commands/profile.py,sha256=heXuBrrpIsu3JEsl7k-apUbxV0sVeDENF9Ct9aCJ5NM,10610
|
|
99
99
|
claude_mpm/cli/commands/run.py,sha256=fWDwyJ6huzG0nyTkbwfxb8IL4UUWGG5HRl2TJWLnWPA,47973
|
|
100
100
|
claude_mpm/cli/commands/search.py,sha256=alv6udvKcn-xkqeBlLuPRvfSDV1yxEX4n9mjjRT5uLM,16581
|
|
101
|
-
claude_mpm/cli/commands/skill_source.py,sha256=
|
|
102
|
-
claude_mpm/cli/commands/skills.py,sha256=
|
|
101
|
+
claude_mpm/cli/commands/skill_source.py,sha256=qhP2gtr-cnnoVABv84y_XRqktfG5n52zcjLZ-zmZvWE,24227
|
|
102
|
+
claude_mpm/cli/commands/skills.py,sha256=pcsbqD2vkql9gyDr01mZmeXOUiFcgRd9UXWFUwMDs1E,58300
|
|
103
103
|
claude_mpm/cli/commands/summarize.py,sha256=1eb6i3IEZ3DqLNBT_HRzEygQ3NPHvrLOTdvQI0pURso,12460
|
|
104
104
|
claude_mpm/cli/commands/tickets.py,sha256=kl2dklTBnG3Y4jUUJ_PcEVsTx4CtVJfkGWboWBx_mQM,21234
|
|
105
105
|
claude_mpm/cli/commands/uninstall.py,sha256=KGlVG6veEs1efLVjrZ3wSty7e1zVR9wpt-VXQA1RzWw,5945
|
|
@@ -138,8 +138,8 @@ claude_mpm/cli/parsers/mpm_init_parser.py,sha256=yIqsUeOtXsUTOD-pJCAEr3euSGxmN3w
|
|
|
138
138
|
claude_mpm/cli/parsers/profile_parser.py,sha256=HlPRekiPeDxqRYSpXoR3NlbOtupXww0mCSrRohHedzs,4414
|
|
139
139
|
claude_mpm/cli/parsers/run_parser.py,sha256=oUB5k3VmIxmsMUlOacfWJxesDw8h4ISf1WkikZLLyzQ,5249
|
|
140
140
|
claude_mpm/cli/parsers/search_parser.py,sha256=L8-65kndg-zutSKpzj-eCvTNkeySCZ-WlSHdhk7pEak,6916
|
|
141
|
-
claude_mpm/cli/parsers/skill_source_parser.py,sha256=
|
|
142
|
-
claude_mpm/cli/parsers/skills_parser.py,sha256=
|
|
141
|
+
claude_mpm/cli/parsers/skill_source_parser.py,sha256=82-ysrXTHJcJI_nOD5FdAUAMU5WeqXLU3Euia8_oojU,5012
|
|
142
|
+
claude_mpm/cli/parsers/skills_parser.py,sha256=rtpmBm-wMZiwvSluV_K3Efz7BVjwTl3ZpJM4J8Du53U,8908
|
|
143
143
|
claude_mpm/cli/parsers/source_parser.py,sha256=NUYpN6hh-yvL1IQ7or4Y8fs8kDX5Sw7E_rMLVjwwkpo,4023
|
|
144
144
|
claude_mpm/cli/parsers/tickets_parser.py,sha256=FYl-VNH7PrZzfZUCcjnf6F7g6JXnL8YDxwrmR5svIcg,6966
|
|
145
145
|
claude_mpm/cli/shared/__init__.py,sha256=c3Ff46Az3U-YpYgcjOowMcNUkSzDngflAJotv6Bs8TE,1019
|
|
@@ -245,7 +245,7 @@ claude_mpm/config/experimental_features.py,sha256=cH95HqMUEQL-_Hs833dAAC33GHMUE5
|
|
|
245
245
|
claude_mpm/config/model_config.py,sha256=34JnIb_U19UYns3yLX-jjpuNywDnVZhiUSvvDzGzx0g,12410
|
|
246
246
|
claude_mpm/config/paths.py,sha256=wTZxXt6LjD-gK9lG4i2QSuSnFRXe5lFaVU4dIr22ap8,7643
|
|
247
247
|
claude_mpm/config/skill_presets.py,sha256=CReZz9CAGQnXdfSBIa0fN5S1vM5dDxh-9S-tG0WiY5M,13919
|
|
248
|
-
claude_mpm/config/skill_sources.py,sha256=
|
|
248
|
+
claude_mpm/config/skill_sources.py,sha256=apZDFdSlUFsewhDQWIjC_zwSMkmG2SGdf1go7pb55eo,20504
|
|
249
249
|
claude_mpm/config/socketio_config.py,sha256=Z8O438z2taOPX2Eh_so-WOvvv-IHiM_WFbf4UBQ4iqg,11342
|
|
250
250
|
claude_mpm/core/__init__.py,sha256=2bufzjbIXffZnSg5k-JH9czMDTkmtz-Jb9opgHmQY-0,2598
|
|
251
251
|
claude_mpm/core/agent_name_normalizer.py,sha256=ZvdQsToFqxLWEPbf8gU1Hl8h3M47DBPmZ8zSAkEp-fc,8939
|
|
@@ -255,7 +255,7 @@ claude_mpm/core/api_validator.py,sha256=zxeUykC2asy1KwHBDu5w3Eoo64E51PJyNe4PT7CT
|
|
|
255
255
|
claude_mpm/core/base_service.py,sha256=4Zrt-vQ6g_KVk4hEfvd4QccuItYoOf7wUHCimIW6zJQ,29953
|
|
256
256
|
claude_mpm/core/cache.py,sha256=orh8B40oYnRRGmXdANR4P4f-KVMIHV0vg7vrsemk0no,17232
|
|
257
257
|
claude_mpm/core/claude_runner.py,sha256=Wle-wI-ag25oC0EYX3n8dDC56I5GIdbpi5NtvT4IgBw,34263
|
|
258
|
-
claude_mpm/core/config.py,sha256=
|
|
258
|
+
claude_mpm/core/config.py,sha256=0R1ZLdwxTM2N3-uIBgcbr37jDiEe-G7h7x4YmYIVit0,43385
|
|
259
259
|
claude_mpm/core/config_aliases.py,sha256=QpNNECkTY4TYYAhVlFZvB-msPnZrui90g19u0-v0HDE,9703
|
|
260
260
|
claude_mpm/core/config_constants.py,sha256=MEF35Y2Lj5FMzRdhgSgZrZeTzHfCzistPGZVY8INta4,10073
|
|
261
261
|
claude_mpm/core/constants.py,sha256=tm6IkmDxnsEqdEImtdQOeWvvGEHrThWCgAz5FMjckCQ,11557
|
|
@@ -320,7 +320,7 @@ claude_mpm/dashboard/__init__.py,sha256=b5QKcz0kt_ZMCFkac7caRzA8DlMiICG9VzmunmxH
|
|
|
320
320
|
claude_mpm/dashboard/api/simple_directory.py,sha256=b-ExWd9wutYIYa4dTYBW0y1s0hsElPn4_LLJglahUEY,7140
|
|
321
321
|
claude_mpm/dashboard/static/svelte-build/favicon.svg,sha256=8WC8JPrjCWsajGxiyBr7WA7Sj896PtUZbYkVjNwd2K0,395
|
|
322
322
|
claude_mpm/dashboard/static/svelte-build/index.html,sha256=QBZs_8cByu6lVPp5Upp1gxXDblACI74nlRjWIGqK6Pk,1173
|
|
323
|
-
claude_mpm/dashboard/static/svelte-build/_app/env.js,sha256=
|
|
323
|
+
claude_mpm/dashboard/static/svelte-build/_app/env.js,sha256=Iu6wbiiLCcW1n9HhTsju7Y83nmMPQC3Myj_B4dOvWXM,20
|
|
324
324
|
claude_mpm/dashboard/static/svelte-build/_app/version.json,sha256=SqUDoSw125-s8xi_Diq0Oy3VjnesiIuCvs7CTZgjwIE,28
|
|
325
325
|
claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css,sha256=BLNxSTDsHOlvyrjeUgRzDhb4A3kPpI1pnIayA6UNBPM,28444
|
|
326
326
|
claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css,sha256=HC7G-CRMmKQWPd26CLlZAL1pa0oUXXQbZ6A88CbTqvg,15985
|
|
@@ -332,7 +332,7 @@ claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js,sha25
|
|
|
332
332
|
claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js,sha256=roecan2HnDRdCpfyDiBPgrwlIi5l5IEWT-CTweT5jDI,29257
|
|
333
333
|
claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js,sha256=7kfWcHYrVg1L5QidpYuUJJvy1YdmERs_srdTBnEad34,27498
|
|
334
334
|
claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js,sha256=LAuNlMt2us_gAtGKbVup7j2MXE8emIrHx0I82WAe9Hk,571
|
|
335
|
-
claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js,sha256=
|
|
335
|
+
claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js,sha256=bc2Upkbz5NyfLBmTs6l1D25pzEVLAaFVnCglNqBdPqA,442400
|
|
336
336
|
claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js,sha256=n6_iC4k_7w0Rxpw3zt0p6KoyL3_2S0EOJ_Nw7MmEH2Y,11160
|
|
337
337
|
claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js,sha256=Pcz47MBoSVumz-ilxfVzQOSz67t1FtEb0lADSpVoad0,523
|
|
338
338
|
claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js,sha256=GNpl2Q76B1KopKPiIz6MrmyucF0eoqMzRhQjeZ2bJ3w,5891
|
|
@@ -414,25 +414,33 @@ claude_mpm/hooks/claude_hooks/correlation_manager.py,sha256=3n-RxzqE8egG4max_Ncp
|
|
|
414
414
|
claude_mpm/hooks/claude_hooks/event_handlers.py,sha256=u7qkfthzAJxE5X4vAp5dCYhVDsadfC--vsqZVlmcrvE,45768
|
|
415
415
|
claude_mpm/hooks/claude_hooks/hook_handler.py,sha256=UOl5IVvz0Ro8Z0Owx4sKUWCxoIhvQpt7VTJ8lRC7Y8o,28266
|
|
416
416
|
claude_mpm/hooks/claude_hooks/hook_wrapper.sh,sha256=XYkdYtcM0nfnwYvMdyIFCasr80ry3uI5-fLYsLtDGw4,2214
|
|
417
|
-
claude_mpm/hooks/claude_hooks/installer.py,sha256=
|
|
417
|
+
claude_mpm/hooks/claude_hooks/installer.py,sha256=GgXqRjm_LpukrMl-eLw3cVDJqwwemNAaEKZvKM0QDYQ,34919
|
|
418
418
|
claude_mpm/hooks/claude_hooks/memory_integration.py,sha256=fj_d9N7aytLELomdphLLwYApXzmbhBxtwSK4xkmd55o,10759
|
|
419
419
|
claude_mpm/hooks/claude_hooks/response_tracking.py,sha256=2dyDOK9u-N4KcqWF7qq2T17bkps0grbs8MeWBRSC8vE,16323
|
|
420
420
|
claude_mpm/hooks/claude_hooks/tool_analysis.py,sha256=3_o2PP9D7wEMwLriCtIBOw0cj2fSZfepN7lI4P1meSQ,7862
|
|
421
421
|
claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc,sha256=EGpgXqhPM0iRRZtCqHaLVQ6wDH42OH_M7Gt5GiFLyro,346
|
|
422
|
+
claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc,sha256=RdPlaoNPDoSlTFV36Ku4vxs7xYqh7t2038D4pyULy-g,322
|
|
422
423
|
claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-314.pyc,sha256=tBzcQ_3WxkmgPTQAPd7uKgFGtz-Yb6r2hEgF9Y_Flwc,319
|
|
423
424
|
claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc,sha256=7YbusOM2EaL4NqIuNsLTJRCRJWRxo0DhVLXm9ZVFc7Y,20829
|
|
425
|
+
claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.pyc,sha256=aUV7xCwxrzM4iW4Jf0RbUskIs2whf7lXt6HppAEMp1g,18982
|
|
424
426
|
claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-314.pyc,sha256=vo_mPXj0KTtBz2_SAU4NZ7TEWPfgBZtLeXD3CMAvJ3M,21381
|
|
425
427
|
claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc,sha256=SQX5iiP9bQZkLL-cj_2tlGH7lpAzarO0mYal7btj3tc,3521
|
|
426
428
|
claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc,sha256=43y-O3fzE07cyJx1we9DfLeaIkL0GQR4KKpnzh_94uk,44526
|
|
429
|
+
claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc,sha256=3ezkq2yC1cejVa-II4cl335SWCJhD8dv_NEDtVsCpUo,39235
|
|
427
430
|
claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-314.pyc,sha256=DC4owkvPyhcCT7ScUxlKS6pUygaUYEMj0k3eVYZHdMk,42528
|
|
428
431
|
claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc,sha256=vhJjvAMTdDWkB_qWaWr_PeDb4I8-h7UymR1wDVHeyYM,30789
|
|
432
|
+
claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc,sha256=bj168CD_Md4vpYJfS9YvPafP7-nw1hAUnuuEpzSQNKY,27815
|
|
429
433
|
claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-314.pyc,sha256=RVz6WvW-sD7kLbh6S5a96WarpPvZv4_qfFMR5SN8WUo,30603
|
|
434
|
+
claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc,sha256=Tt3L5Ye7RJCLvIAaz6uLwKe3WGEaMLx6WElvqK60G0Q,38428
|
|
430
435
|
claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-314.pyc,sha256=hxxLzkAFGV4sBK3NiYZ6zVlc1Cq9yTc8YPzp-mf5sxo,37219
|
|
431
436
|
claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc,sha256=Xu_hwOf9AG0mZthl5gcDcVv68FiSo5KgZ6lDxdZXCfU,11185
|
|
437
|
+
claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc,sha256=w9SKmvg60p6kvNzuOIddYE-X9LYt-ZQzX3LWiKs4nZY,10055
|
|
432
438
|
claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-314.pyc,sha256=oJhMGouqaFI1u3NZryHoRh6ucfPKHPe8GufcsPzi89o,11081
|
|
433
439
|
claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc,sha256=qJ5xY8yYwo8ZO7P-Gem_GK4VZdqyNeYvs8ANvC45jnw,16228
|
|
440
|
+
claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc,sha256=uyjnluDUFQql1N2oYP6IYP8dxhxnHoSvrmUubEMRNXI,14000
|
|
434
441
|
claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-314.pyc,sha256=yu70SIPNsdECY8l_P971JPFuUPXqD4HmjuuGMU-nSAU,15820
|
|
435
442
|
claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc,sha256=ZjcNfNY5Ht6FhalPeh7M7OzMffcey5iF4AVjDDg9kak,10694
|
|
443
|
+
claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc,sha256=T98zonvVkllflFNw_pptXXAXbDrIgeBfY6aXvSY8el8,9071
|
|
436
444
|
claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-314.pyc,sha256=ck8ifVIoVPaMVVRcMgvsM8RfIHnQbwGBUVs25A-yQBw,10771
|
|
437
445
|
claude_mpm/hooks/claude_hooks/services/__init__.py,sha256=OIYOKsUNw1BHYawOCp-KFK5kmQKuj92cCqCEPO0nwo0,585
|
|
438
446
|
claude_mpm/hooks/claude_hooks/services/connection_manager.py,sha256=shpoCLJpM9qoCDMUuUhk6L9WEKdzLB_OsPtwtDyJMdk,10197
|
|
@@ -441,14 +449,19 @@ claude_mpm/hooks/claude_hooks/services/duplicate_detector.py,sha256=Fh9LmEMsVmQM
|
|
|
441
449
|
claude_mpm/hooks/claude_hooks/services/state_manager.py,sha256=PcEpAzwEnZRjw6JnbtbekDRdhIoaKql5VhhZJCEPNt4,10899
|
|
442
450
|
claude_mpm/hooks/claude_hooks/services/subagent_processor.py,sha256=unHGeU6PJxc00_3xnLyyZHeLa47x98knxn6cl-i8ALA,15040
|
|
443
451
|
claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc,sha256=xBfLBSqnpcKfcQBWfh7xUm454g1lq1LvbO7SxGvcOPc,644
|
|
452
|
+
claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.pyc,sha256=75pkmoqE7CeBOc2ZHTYfgSR-mtVjKrcKaOA6PxFGW64,565
|
|
444
453
|
claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-314.pyc,sha256=nZDxNz67tIFwbZNRqyCRX8cSi0v3JKCZS5U5FhwwApA,562
|
|
445
454
|
claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc,sha256=SydGEQ9oUWs161Ro4ULHfnPB0wiZgiB7V628B3V6N2U,9613
|
|
455
|
+
claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc,sha256=qdBU-mDyJxcwjwxfGhqzvo_s7YMO4mva-8hdObDAOcY,8616
|
|
446
456
|
claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-314.pyc,sha256=PjdPDUyUQWm0FqYRdG2knPoZDSKS0g1vk-BDAXfzCi8,9627
|
|
447
457
|
claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc,sha256=Yy_REAUhJCiFjOhxeDb4v0qyEvEbUtCmXD9PAz40dhw,5321
|
|
458
|
+
claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc,sha256=ef_Tx9Uv1CvS18tC_PXmGVvIoMDsRnEUhKRUZaUdGBw,4751
|
|
448
459
|
claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-314.pyc,sha256=Xy9iNAtQMfXC_eW9rvumG9rFqK5t-QlLPmUahlqza_I,5341
|
|
449
460
|
claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc,sha256=P-Au2P5H0enEeKm7sP1eQv-SU6AAnCqjjOE5jhXcrgs,12352
|
|
450
|
-
claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-
|
|
461
|
+
claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc,sha256=g_Lo7LUYOEgIqS_Rz-6hy_caraHW9nzVJ6f0W4Y14rg,11378
|
|
462
|
+
claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc,sha256=2QqT8edjLqG8-9q446zpLJ347lzkgvJxPJG-A8u_HAU,13101
|
|
451
463
|
claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc,sha256=4SfbElFMcQK07Frewl9mQ0eB5yCqZUe-CGfGYNUUMh0,14931
|
|
464
|
+
claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc,sha256=Cky-0tvyWmn9I44WdupIdJ4Qml0k-qlCs5E0x0Y130Q,13301
|
|
452
465
|
claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-314.pyc,sha256=o6Dc1-yyZjUdVh_JWZmEIvVt0qG0R1-aLhr7XTt-oX0,15104
|
|
453
466
|
claude_mpm/hooks/failure_learning/__init__.py,sha256=iJ80AKFHiT8DjIH2a72DQVJvL6nAFrizNA2yTKwZ4rw,1805
|
|
454
467
|
claude_mpm/hooks/failure_learning/failure_detection_hook.py,sha256=KENoB5N-dBm5hb0SxeIZtCvNKbmG2BKHOJSrSO-3Z_I,7500
|
|
@@ -463,7 +476,7 @@ claude_mpm/models/git_repository.py,sha256=Lp2I5tv4fu6idIXCTW50MCTWgjuIE-rwsgVIr
|
|
|
463
476
|
claude_mpm/models/resume_log.py,sha256=aDiFC_2FR7tue_Kn46ZDUiKmuw9a_W9yE9zE7gA6Hys,12515
|
|
464
477
|
claude_mpm/schemas/__init__.py,sha256=2SLpkojJq34KnwPkVxrsVmw_cEI66872i75QBT1C2To,446
|
|
465
478
|
claude_mpm/scripts/__init__.py,sha256=IffMdVD99Pxyw85yluRa0VDPi4dRQecIWce764pcfZE,553
|
|
466
|
-
claude_mpm/scripts/claude-hook-handler.sh,sha256=
|
|
479
|
+
claude_mpm/scripts/claude-hook-handler.sh,sha256=1e5ZsZJQdp9lKLwEmmAtqnEGZPf5UIAG2ReGfwmXtOE,10907
|
|
467
480
|
claude_mpm/scripts/launch_monitor.py,sha256=M0CSAYJp5UnoyXKnICZgrAFwqqP5XAWDCiii_IIcrCk,5348
|
|
468
481
|
claude_mpm/scripts/mpm_doctor.py,sha256=98vBiTIB4xpaSgOvTP9N3EU22V2Odxd9DivhQizG0VM,8822
|
|
469
482
|
claude_mpm/scripts/socketio_daemon.py,sha256=wWFcvKkHa_oR-NQwhvV-O8s3m1TgicBp9UQ-NR8AQmU,6041
|
|
@@ -497,7 +510,7 @@ claude_mpm/services/self_upgrade_service.py,sha256=O5-uqjdt9BHt0bxLNzuYdzlwgtWF_
|
|
|
497
510
|
claude_mpm/services/session_management_service.py,sha256=za_ljDawCJjOq5ezEdxw71MFFFFIbWlV6ujlWL3vImg,10723
|
|
498
511
|
claude_mpm/services/session_manager.py,sha256=ddVdINaHzBol24KvFCLOyM5SuBG_-Vd8_iT2YTBlGiU,12328
|
|
499
512
|
claude_mpm/services/skills_config.py,sha256=R9F3BV3BEVmjqlxBy2mZycH4cCH4Ieh3K1n_8w9a5zQ,18005
|
|
500
|
-
claude_mpm/services/skills_deployer.py,sha256=
|
|
513
|
+
claude_mpm/services/skills_deployer.py,sha256=iNT939b6akNEe0libu00fyYSceSKh4YYeu7ehb3v5F0,47270
|
|
501
514
|
claude_mpm/services/socketio_client_manager.py,sha256=cZjIsnoi2VPXFA-5pNhoz5Vv3qv0iuSTy510TgAJU4U,18179
|
|
502
515
|
claude_mpm/services/socketio_server.py,sha256=yE14_4pHERXBC5L1WQCpIBHuy0tpklsUY_icyl-nLkg,3033
|
|
503
516
|
claude_mpm/services/subprocess_launcher_service.py,sha256=lYSlg2G_oDAv1dHrOdHaOEIppDwisANCASuNFdp0WqY,11226
|
|
@@ -510,7 +523,7 @@ claude_mpm/services/agents/agent_builder.py,sha256=ehnzIgQ3OcF5ThqvbmS4c4ZyA-hbp
|
|
|
510
523
|
claude_mpm/services/agents/agent_preset_service.py,sha256=YpIKwaq52Pi4ox6ha3L9qTT4GHc-1nPeGgV0MWGRIAs,8588
|
|
511
524
|
claude_mpm/services/agents/agent_recommendation_service.py,sha256=f3F6LkPG1S42ZE52o8QnSdFwZFsv_7vgegJ6bCNbWWk,9846
|
|
512
525
|
claude_mpm/services/agents/agent_review_service.py,sha256=1meV6u8FGbYMx1vhSsCX8OembWbF3gXfl26hRdGd95Y,10001
|
|
513
|
-
claude_mpm/services/agents/agent_selection_service.py,sha256=
|
|
526
|
+
claude_mpm/services/agents/agent_selection_service.py,sha256=rhbLrwuNsofH-U6sfJIn7Zp0Ek3YDmznNEIQUlJe1tM,17943
|
|
514
527
|
claude_mpm/services/agents/auto_config_manager.py,sha256=WdrOaosxmK1iD-1Me7eZ-VJzMW-p8liei6iEjGkbodA,30706
|
|
515
528
|
claude_mpm/services/agents/auto_deploy_index_parser.py,sha256=-29NBjr6u8QEcFYfygt2CqqGtS1XEN6NoJtsM6cDUAU,19465
|
|
516
529
|
claude_mpm/services/agents/cache_git_manager.py,sha256=gfrcAZULY-oZDBuf20ubUE1STYLBu4c-UIjIu5cYsCA,23583
|
|
@@ -518,7 +531,7 @@ claude_mpm/services/agents/git_source_manager.py,sha256=SRGX4T-dUuLn2PDe1EkTL493
|
|
|
518
531
|
claude_mpm/services/agents/local_template_manager.py,sha256=v1vlukIVEpiw5u11KseJhEMkhi1tlm6FTp0FYwK9YFU,27980
|
|
519
532
|
claude_mpm/services/agents/observers.py,sha256=2OUEMc2TzHrME2AHHnBmquWmbhGEMTNpTc08sIoHno0,18484
|
|
520
533
|
claude_mpm/services/agents/recommender.py,sha256=TC8iLNi_uP0byj8w9jXHhl0PYn0JDfAgRMjbTgSwafE,23756
|
|
521
|
-
claude_mpm/services/agents/single_tier_deployment_service.py,sha256=
|
|
534
|
+
claude_mpm/services/agents/single_tier_deployment_service.py,sha256=M1ep-yTcwk8OLhnkg5p2vNsqynpP49rRAxPxvpsG7ac,25380
|
|
522
535
|
claude_mpm/services/agents/startup_sync.py,sha256=VoTSFtYF-BZZSCzoeAF6LpQ-tq3BjE4Ua-N9sdRikak,9310
|
|
523
536
|
claude_mpm/services/agents/toolchain_detector.py,sha256=eGzMprsD1M7DXHGN0RhhUz3diITbiXtHZw0uK7rZ6Nk,16854
|
|
524
537
|
claude_mpm/services/agents/deployment/__init__.py,sha256=iprW-Ww3LBtWu9pVFjAX45_CswfSqnPMoG0QoFPd1Dg,539
|
|
@@ -803,9 +816,9 @@ claude_mpm/services/shared/lifecycle_service_base.py,sha256=YJZHs2sUrnIsbHHjrd8l
|
|
|
803
816
|
claude_mpm/services/shared/manager_base.py,sha256=kmjhpVqgfYC1N4YQnPAilCfdrSpAh9Qz7wcQ602L4x4,9296
|
|
804
817
|
claude_mpm/services/shared/service_factory.py,sha256=9yvnD62urrNQCGmtk_3OcR5tVUCnoS6wHkaI5PK34mg,9891
|
|
805
818
|
claude_mpm/services/skills/__init__.py,sha256=X1fPRCGZjteLd35HlhWv2M6tAJ_WbYrEv84kbaqBAiU,742
|
|
806
|
-
claude_mpm/services/skills/git_skill_source_manager.py,sha256=
|
|
807
|
-
claude_mpm/services/skills/selective_skill_deployer.py,sha256=
|
|
808
|
-
claude_mpm/services/skills/skill_discovery_service.py,sha256=
|
|
819
|
+
claude_mpm/services/skills/git_skill_source_manager.py,sha256=92fz9I7zYemQ7tV3-s0wzmU5wV7KCMnd-MzKXq6ssfY,56857
|
|
820
|
+
claude_mpm/services/skills/selective_skill_deployer.py,sha256=tWWs2RLatD1cP4MnDcVN6J2-hk6GuYPKg9chTXyDXGM,30639
|
|
821
|
+
claude_mpm/services/skills/skill_discovery_service.py,sha256=uJUdjB54N6w9g8KFi7WmobA-R-pBh3ND12qA2HYxd5I,23003
|
|
809
822
|
claude_mpm/services/skills/skill_to_agent_mapper.py,sha256=4PRwcSDSNGS55lg4t-VmBK2ottE_cGFq1zsvjiumAlI,14847
|
|
810
823
|
claude_mpm/services/socketio/__init__.py,sha256=PS-2twllga-2mhSfKdu4MgpikfKp_730gMLAqU_9YX4,556
|
|
811
824
|
claude_mpm/services/socketio/client_proxy.py,sha256=DFPO5OIl-cHusldHPYWKSbnL0dxSLz8h07D9307FfzY,8853
|
|
@@ -1096,10 +1109,10 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
|
|
|
1096
1109
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
|
1097
1110
|
claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
|
|
1098
1111
|
claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
|
|
1099
|
-
claude_mpm-5.6.
|
|
1100
|
-
claude_mpm-5.6.
|
|
1101
|
-
claude_mpm-5.6.
|
|
1102
|
-
claude_mpm-5.6.
|
|
1103
|
-
claude_mpm-5.6.
|
|
1104
|
-
claude_mpm-5.6.
|
|
1105
|
-
claude_mpm-5.6.
|
|
1112
|
+
claude_mpm-5.6.8.dist-info/licenses/LICENSE,sha256=ca3y_Rk4aPrbF6f62z8Ht5MJM9OAvbGlHvEDcj9vUQ4,3867
|
|
1113
|
+
claude_mpm-5.6.8.dist-info/licenses/LICENSE-FAQ.md,sha256=TxfEkXVCK98RzDOer09puc7JVCP_q_bN4dHtZKHCMcM,5104
|
|
1114
|
+
claude_mpm-5.6.8.dist-info/METADATA,sha256=8lS7j7tnOGNu9c1kzaDSZwcUK-D84gQbbCb_MoncT_4,14983
|
|
1115
|
+
claude_mpm-5.6.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
1116
|
+
claude_mpm-5.6.8.dist-info/entry_points.txt,sha256=n-Uk4vwHPpuvu-g_I7-GHORzTnN_m6iyOsoLveKKD0E,228
|
|
1117
|
+
claude_mpm-5.6.8.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
|
1118
|
+
claude_mpm-5.6.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|