claude-mpm 4.16.0__py3-none-any.whl → 4.20.3__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_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +255 -23
- claude_mpm/agents/PM_INSTRUCTIONS.md +40 -0
- claude_mpm/agents/agent_loader.py +4 -4
- claude_mpm/agents/templates/engineer.json +5 -1
- claude_mpm/agents/templates/python_engineer.json +8 -3
- claude_mpm/agents/templates/rust_engineer.json +12 -7
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/mpm_init.py +109 -24
- claude_mpm/cli/commands/skills.py +434 -0
- claude_mpm/cli/executor.py +2 -0
- claude_mpm/cli/parsers/base_parser.py +7 -0
- claude_mpm/cli/parsers/skills_parser.py +137 -0
- claude_mpm/cli/startup.py +57 -0
- claude_mpm/commands/mpm-auto-configure.md +52 -0
- claude_mpm/commands/mpm-help.md +3 -0
- claude_mpm/commands/mpm-init.md +112 -6
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/constants.py +12 -0
- claude_mpm/core/config.py +42 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/hooks/__init__.py +8 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/auto_config_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/recommender.py +47 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +87 -0
- claude_mpm/services/cli/session_resume_helper.py +352 -0
- claude_mpm/services/core/path_resolver.py +1 -1
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/mcp_config_manager.py +7 -131
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/unified/deployment_strategies/local.py +1 -1
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/agent_skills_injector.py +331 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +75 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +184 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +107 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/code-reviewer.md +146 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +118 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +177 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +175 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/common-failures.md +213 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +314 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +227 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +74 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +32 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +328 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +150 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +372 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +209 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +302 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +111 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +65 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +123 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +304 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +96 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +40 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +107 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +97 -9
- claude_mpm/skills/skills_registry.py +351 -0
- claude_mpm/skills/skills_service.py +730 -0
- claude_mpm/utils/agent_dependency_loader.py +2 -2
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.20.3.dist-info}/METADATA +181 -32
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.20.3.dist-info}/RECORD +130 -48
- claude_mpm/agents/INSTRUCTIONS_OLD_DEPRECATED.md +0 -602
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.20.3.dist-info}/WHEEL +0 -0
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.20.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.20.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.20.3.dist-info}/top_level.txt +0 -0
|
@@ -6,12 +6,19 @@ Ensures a single session ID is generated and used across all components.
|
|
|
6
6
|
|
|
7
7
|
This service addresses race conditions and duplicate session ID generation
|
|
8
8
|
by providing a single source of truth for session identifiers.
|
|
9
|
+
|
|
10
|
+
Extended with:
|
|
11
|
+
- Token usage tracking and monitoring
|
|
12
|
+
- Resume log generation on session end
|
|
13
|
+
- Context metrics persistence
|
|
14
|
+
- Automatic resume log injection on session startup
|
|
9
15
|
"""
|
|
10
16
|
|
|
11
17
|
import os
|
|
12
18
|
from datetime import datetime, timezone
|
|
19
|
+
from pathlib import Path
|
|
13
20
|
from threading import Lock
|
|
14
|
-
from typing import Optional
|
|
21
|
+
from typing import Any, Dict, Optional
|
|
15
22
|
|
|
16
23
|
from claude_mpm.core.logging_utils import get_logger
|
|
17
24
|
|
|
@@ -64,6 +71,24 @@ class SessionManager:
|
|
|
64
71
|
self._session_id = self._generate_session_id()
|
|
65
72
|
self._session_start_time = datetime.now(timezone.utc)
|
|
66
73
|
|
|
74
|
+
# Token usage tracking
|
|
75
|
+
self._cumulative_tokens = 0
|
|
76
|
+
self._total_budget = 200000 # Default Claude Code budget
|
|
77
|
+
self._last_stop_reason: Optional[str] = None
|
|
78
|
+
|
|
79
|
+
# Context metrics storage
|
|
80
|
+
self._context_metrics: Dict[str, Any] = {
|
|
81
|
+
"total_budget": self._total_budget,
|
|
82
|
+
"used_tokens": 0,
|
|
83
|
+
"remaining_tokens": self._total_budget,
|
|
84
|
+
"percentage_used": 0.0,
|
|
85
|
+
"stop_reason": None,
|
|
86
|
+
"model": "claude-sonnet-4.5",
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# Resume log reference (loaded on startup if exists)
|
|
90
|
+
self._resume_log_content: Optional[str] = None
|
|
91
|
+
|
|
67
92
|
# Mark as initialized
|
|
68
93
|
self.__class__._initialized = True
|
|
69
94
|
|
|
@@ -71,6 +96,9 @@ class SessionManager:
|
|
|
71
96
|
f"SessionManager initialized with session ID: {self._session_id}"
|
|
72
97
|
)
|
|
73
98
|
|
|
99
|
+
# Check for resume log from previous session
|
|
100
|
+
self._load_resume_log()
|
|
101
|
+
|
|
74
102
|
def _generate_session_id(self) -> str:
|
|
75
103
|
"""
|
|
76
104
|
Generate or retrieve a session ID.
|
|
@@ -134,6 +162,182 @@ class SessionManager:
|
|
|
134
162
|
f"Session ID already set to {session_id}, no change needed"
|
|
135
163
|
)
|
|
136
164
|
|
|
165
|
+
def update_token_usage(
|
|
166
|
+
self,
|
|
167
|
+
input_tokens: int = 0,
|
|
168
|
+
output_tokens: int = 0,
|
|
169
|
+
stop_reason: Optional[str] = None,
|
|
170
|
+
) -> Dict[str, Any]:
|
|
171
|
+
"""
|
|
172
|
+
Update cumulative token usage for the session.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
input_tokens: Input tokens from latest API call
|
|
176
|
+
output_tokens: Output tokens from latest API call
|
|
177
|
+
stop_reason: Stop reason from Claude API
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
Updated context metrics
|
|
181
|
+
"""
|
|
182
|
+
with self.__class__._lock:
|
|
183
|
+
# Update cumulative usage
|
|
184
|
+
tokens_used = input_tokens + output_tokens
|
|
185
|
+
self._cumulative_tokens += tokens_used
|
|
186
|
+
|
|
187
|
+
# Update stop reason if provided
|
|
188
|
+
if stop_reason:
|
|
189
|
+
self._last_stop_reason = stop_reason
|
|
190
|
+
|
|
191
|
+
# Calculate metrics
|
|
192
|
+
remaining = max(0, self._total_budget - self._cumulative_tokens)
|
|
193
|
+
percentage = (self._cumulative_tokens / self._total_budget) * 100
|
|
194
|
+
|
|
195
|
+
# Update context metrics
|
|
196
|
+
self._context_metrics = {
|
|
197
|
+
"total_budget": self._total_budget,
|
|
198
|
+
"used_tokens": self._cumulative_tokens,
|
|
199
|
+
"remaining_tokens": remaining,
|
|
200
|
+
"percentage_used": percentage,
|
|
201
|
+
"stop_reason": self._last_stop_reason,
|
|
202
|
+
"model": "claude-sonnet-4.5",
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
logger.debug(
|
|
206
|
+
f"Token usage updated: {self._cumulative_tokens}/{self._total_budget} "
|
|
207
|
+
f"({percentage:.1f}%) - Stop reason: {stop_reason}"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return self._context_metrics.copy()
|
|
211
|
+
|
|
212
|
+
def get_context_metrics(self) -> Dict[str, Any]:
|
|
213
|
+
"""
|
|
214
|
+
Get current context metrics.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
Dictionary containing token usage and context metrics
|
|
218
|
+
"""
|
|
219
|
+
with self.__class__._lock:
|
|
220
|
+
return self._context_metrics.copy()
|
|
221
|
+
|
|
222
|
+
def get_token_usage_percentage(self) -> float:
|
|
223
|
+
"""
|
|
224
|
+
Get current token usage as a percentage (0.0 to 1.0).
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
Token usage percentage
|
|
228
|
+
"""
|
|
229
|
+
with self.__class__._lock:
|
|
230
|
+
return self._context_metrics["percentage_used"] / 100.0
|
|
231
|
+
|
|
232
|
+
def should_warn_context_limit(self, threshold: float = 0.70) -> bool:
|
|
233
|
+
"""
|
|
234
|
+
Check if context usage has reached warning threshold.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
threshold: Warning threshold (0.0 to 1.0)
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
True if threshold reached
|
|
241
|
+
"""
|
|
242
|
+
return self.get_token_usage_percentage() >= threshold
|
|
243
|
+
|
|
244
|
+
def _load_resume_log(self) -> None:
|
|
245
|
+
"""
|
|
246
|
+
Load resume log from previous session if it exists.
|
|
247
|
+
|
|
248
|
+
This is called during initialization to check for session continuity.
|
|
249
|
+
"""
|
|
250
|
+
try:
|
|
251
|
+
# Lazy import to avoid circular dependencies
|
|
252
|
+
from claude_mpm.services.infrastructure.resume_log_generator import (
|
|
253
|
+
ResumeLogGenerator,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
generator = ResumeLogGenerator()
|
|
257
|
+
|
|
258
|
+
# Check if there's a resume log for this session
|
|
259
|
+
# (Could be from a previous interrupted session with same ID)
|
|
260
|
+
resume_content = generator.load_resume_log(self._session_id)
|
|
261
|
+
|
|
262
|
+
if resume_content:
|
|
263
|
+
self._resume_log_content = resume_content
|
|
264
|
+
logger.info(f"Loaded resume log for session {self._session_id}")
|
|
265
|
+
else:
|
|
266
|
+
logger.debug("No resume log found for current session")
|
|
267
|
+
|
|
268
|
+
except Exception as e:
|
|
269
|
+
logger.warning(f"Failed to load resume log: {e}")
|
|
270
|
+
# Non-critical error, continue without resume log
|
|
271
|
+
|
|
272
|
+
def get_resume_log_content(self) -> Optional[str]:
|
|
273
|
+
"""
|
|
274
|
+
Get resume log content if loaded.
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
Resume log markdown content or None
|
|
278
|
+
"""
|
|
279
|
+
with self.__class__._lock:
|
|
280
|
+
return self._resume_log_content
|
|
281
|
+
|
|
282
|
+
def generate_resume_log(
|
|
283
|
+
self,
|
|
284
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
285
|
+
) -> Optional[Path]:
|
|
286
|
+
"""
|
|
287
|
+
Generate and save resume log for current session.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
session_state: Optional session state data to include
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
Path to saved resume log or None if generation failed
|
|
294
|
+
"""
|
|
295
|
+
try:
|
|
296
|
+
# Lazy import to avoid circular dependencies
|
|
297
|
+
from claude_mpm.models.resume_log import ContextMetrics, ResumeLog
|
|
298
|
+
from claude_mpm.services.infrastructure.resume_log_generator import (
|
|
299
|
+
ResumeLogGenerator,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
generator = ResumeLogGenerator()
|
|
303
|
+
|
|
304
|
+
# Create context metrics from current state
|
|
305
|
+
context_metrics = ContextMetrics(
|
|
306
|
+
total_budget=self._total_budget,
|
|
307
|
+
used_tokens=self._cumulative_tokens,
|
|
308
|
+
remaining_tokens=self._context_metrics["remaining_tokens"],
|
|
309
|
+
percentage_used=self._context_metrics["percentage_used"],
|
|
310
|
+
stop_reason=self._last_stop_reason,
|
|
311
|
+
model=self._context_metrics["model"],
|
|
312
|
+
session_id=self._session_id,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
if session_state:
|
|
316
|
+
# Generate from provided session state
|
|
317
|
+
resume_log = generator.generate_from_session_state(
|
|
318
|
+
session_id=self._session_id,
|
|
319
|
+
session_state=session_state,
|
|
320
|
+
stop_reason=self._last_stop_reason,
|
|
321
|
+
)
|
|
322
|
+
else:
|
|
323
|
+
# Create minimal resume log
|
|
324
|
+
resume_log = ResumeLog(
|
|
325
|
+
session_id=self._session_id,
|
|
326
|
+
context_metrics=context_metrics,
|
|
327
|
+
mission_summary="Session ended - resume log auto-generated.",
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
if resume_log:
|
|
331
|
+
file_path = generator.save_resume_log(resume_log)
|
|
332
|
+
logger.info(f"Resume log generated and saved: {file_path}")
|
|
333
|
+
return file_path
|
|
334
|
+
logger.warning("Resume log generation returned None")
|
|
335
|
+
return None
|
|
336
|
+
|
|
337
|
+
except Exception as e:
|
|
338
|
+
logger.error(f"Failed to generate resume log: {e}", exc_info=True)
|
|
339
|
+
return None
|
|
340
|
+
|
|
137
341
|
@classmethod
|
|
138
342
|
def reset(cls) -> None:
|
|
139
343
|
"""
|
|
@@ -9,7 +9,7 @@ Extracted from ClaudeRunner to follow Single Responsibility Principle.
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Any, Dict, Optional
|
|
12
|
+
from typing import Any, Dict, List, Optional
|
|
13
13
|
|
|
14
14
|
from claude_mpm.config.paths import paths
|
|
15
15
|
from claude_mpm.core.base_service import BaseService
|
|
@@ -274,3 +274,106 @@ class VersionService(BaseService, VersionServiceInterface):
|
|
|
274
274
|
"message": "Update checking not implemented",
|
|
275
275
|
"checked_at": None,
|
|
276
276
|
}
|
|
277
|
+
|
|
278
|
+
def get_agents_versions(self) -> Dict[str, List[Dict[str, str]]]:
|
|
279
|
+
"""Get all agents grouped by tier with versions.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
Dict with keys: system, user, project
|
|
283
|
+
Each value is list of agent dicts with: name, version, id
|
|
284
|
+
"""
|
|
285
|
+
from claude_mpm.core.unified_agent_registry import get_agent_registry
|
|
286
|
+
|
|
287
|
+
agents_by_tier = {"system": [], "user": [], "project": []}
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
registry = get_agent_registry()
|
|
291
|
+
all_agents = registry.list_agents()
|
|
292
|
+
|
|
293
|
+
for agent in all_agents:
|
|
294
|
+
agent_info = {
|
|
295
|
+
"name": agent.name,
|
|
296
|
+
"version": agent.version,
|
|
297
|
+
"id": agent.name, # Use name as ID since agent_id doesn't exist
|
|
298
|
+
}
|
|
299
|
+
tier = (
|
|
300
|
+
agent.tier.value
|
|
301
|
+
if hasattr(agent.tier, "value")
|
|
302
|
+
else str(agent.tier)
|
|
303
|
+
)
|
|
304
|
+
if tier in agents_by_tier:
|
|
305
|
+
agents_by_tier[tier].append(agent_info)
|
|
306
|
+
else:
|
|
307
|
+
agents_by_tier["system"].append(agent_info)
|
|
308
|
+
|
|
309
|
+
# Sort each tier alphabetically by name
|
|
310
|
+
for tier, agents in agents_by_tier.items():
|
|
311
|
+
agents.sort(key=lambda x: x["name"])
|
|
312
|
+
|
|
313
|
+
except Exception as e:
|
|
314
|
+
self.logger.error(f"Failed to get agent versions: {e}")
|
|
315
|
+
|
|
316
|
+
return agents_by_tier
|
|
317
|
+
|
|
318
|
+
def get_skills_versions(self) -> Dict[str, List[Dict[str, str]]]:
|
|
319
|
+
"""Get all skills grouped by source with versions.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
Dict with keys: bundled, user, project
|
|
323
|
+
Each value is list of skill dicts with: name, version, description
|
|
324
|
+
"""
|
|
325
|
+
from claude_mpm.skills.registry import get_registry
|
|
326
|
+
|
|
327
|
+
skills_by_source = {"bundled": [], "user": [], "project": []}
|
|
328
|
+
|
|
329
|
+
try:
|
|
330
|
+
registry = get_registry()
|
|
331
|
+
|
|
332
|
+
for skill in registry.list_skills():
|
|
333
|
+
skill_info = {
|
|
334
|
+
"name": skill.name,
|
|
335
|
+
"version": skill.version,
|
|
336
|
+
"description": (
|
|
337
|
+
skill.description[:60] + "..."
|
|
338
|
+
if len(skill.description) > 60
|
|
339
|
+
else skill.description
|
|
340
|
+
),
|
|
341
|
+
}
|
|
342
|
+
source = skill.source if skill.source in skills_by_source else "bundled"
|
|
343
|
+
skills_by_source[source].append(skill_info)
|
|
344
|
+
|
|
345
|
+
# Sort each source alphabetically by name
|
|
346
|
+
for source, skills in skills_by_source.items():
|
|
347
|
+
skills.sort(key=lambda x: x["name"])
|
|
348
|
+
|
|
349
|
+
except Exception as e:
|
|
350
|
+
self.logger.error(f"Failed to get skill versions: {e}")
|
|
351
|
+
|
|
352
|
+
return skills_by_source
|
|
353
|
+
|
|
354
|
+
def get_version_summary(self) -> Dict:
|
|
355
|
+
"""Get complete version summary.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
Dict with project_version, build, agents, skills, and counts
|
|
359
|
+
"""
|
|
360
|
+
agents = self.get_agents_versions()
|
|
361
|
+
skills = self.get_skills_versions()
|
|
362
|
+
build = self.get_build_number()
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
"project_version": self.get_base_version(),
|
|
366
|
+
"build": build,
|
|
367
|
+
"agents": agents,
|
|
368
|
+
"skills": skills,
|
|
369
|
+
"counts": {
|
|
370
|
+
"agents_total": sum(len(v) for v in agents.values()),
|
|
371
|
+
"agents_system": len(agents.get("system", [])),
|
|
372
|
+
"agents_user": len(agents.get("user", [])),
|
|
373
|
+
"agents_project": len(agents.get("project", [])),
|
|
374
|
+
"skills_total": sum(len(v) for v in skills.values()),
|
|
375
|
+
"skills_bundled": len(skills.get("bundled", [])),
|
|
376
|
+
"skills_user": len(skills.get("user", [])),
|
|
377
|
+
"skills_project": len(skills.get("project", [])),
|
|
378
|
+
},
|
|
379
|
+
}
|
claude_mpm/skills/__init__.py
CHANGED
|
@@ -8,12 +8,33 @@ Skills can be:
|
|
|
8
8
|
- Bundled with MPM (in skills/bundled/)
|
|
9
9
|
- User-installed (in ~/.claude/skills/)
|
|
10
10
|
- Project-specific (in .claude/skills/)
|
|
11
|
+
|
|
12
|
+
New Skills Integration System:
|
|
13
|
+
- SkillsService: Core service for skill management
|
|
14
|
+
- AgentSkillsInjector: Dynamic skill injection into agent templates
|
|
15
|
+
- SkillsRegistry: Helper class for registry operations
|
|
16
|
+
|
|
17
|
+
Legacy System (maintained for compatibility):
|
|
18
|
+
- Skill: Dataclass for skill representation
|
|
19
|
+
- SkillManager: Legacy skill manager
|
|
20
|
+
- get_registry: Legacy registry access
|
|
11
21
|
"""
|
|
12
22
|
|
|
23
|
+
# New Skills Integration System
|
|
24
|
+
from .agent_skills_injector import AgentSkillsInjector
|
|
25
|
+
|
|
26
|
+
# Legacy System (maintained for compatibility)
|
|
13
27
|
from .registry import Skill, SkillsRegistry, get_registry
|
|
14
28
|
from .skill_manager import SkillManager
|
|
29
|
+
from .skills_registry import SkillsRegistry as SkillsRegistryHelper
|
|
30
|
+
from .skills_service import SkillsService
|
|
15
31
|
|
|
16
32
|
__all__ = [
|
|
33
|
+
# New Skills Integration System
|
|
34
|
+
"SkillsService",
|
|
35
|
+
"AgentSkillsInjector",
|
|
36
|
+
"SkillsRegistryHelper",
|
|
37
|
+
# Legacy System
|
|
17
38
|
"Skill",
|
|
18
39
|
"SkillManager",
|
|
19
40
|
"SkillsRegistry",
|