claude-mpm 4.13.2__py3-none-any.whl → 4.18.2__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 +48 -17
- claude_mpm/agents/OUTPUT_STYLE.md +329 -11
- claude_mpm/agents/PM_INSTRUCTIONS.md +227 -8
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/agentic-coder-optimizer.json +9 -2
- claude_mpm/agents/templates/api_qa.json +7 -1
- claude_mpm/agents/templates/clerk-ops.json +8 -1
- claude_mpm/agents/templates/code_analyzer.json +4 -1
- claude_mpm/agents/templates/dart_engineer.json +11 -1
- claude_mpm/agents/templates/data_engineer.json +11 -1
- claude_mpm/agents/templates/documentation.json +6 -1
- claude_mpm/agents/templates/engineer.json +18 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +8 -1
- claude_mpm/agents/templates/golang_engineer.json +11 -1
- claude_mpm/agents/templates/java_engineer.json +12 -2
- claude_mpm/agents/templates/local_ops_agent.json +1217 -6
- claude_mpm/agents/templates/nextjs_engineer.json +11 -1
- claude_mpm/agents/templates/ops.json +8 -1
- claude_mpm/agents/templates/php-engineer.json +11 -1
- claude_mpm/agents/templates/project_organizer.json +10 -3
- claude_mpm/agents/templates/prompt-engineer.json +5 -1
- claude_mpm/agents/templates/python_engineer.json +11 -1
- claude_mpm/agents/templates/qa.json +7 -1
- claude_mpm/agents/templates/react_engineer.json +11 -1
- claude_mpm/agents/templates/refactoring_engineer.json +8 -1
- claude_mpm/agents/templates/research.json +4 -1
- claude_mpm/agents/templates/ruby-engineer.json +11 -1
- claude_mpm/agents/templates/rust_engineer.json +11 -1
- claude_mpm/agents/templates/security.json +6 -1
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +6 -1
- claude_mpm/agents/templates/typescript_engineer.json +11 -1
- claude_mpm/agents/templates/vercel_ops_agent.json +8 -1
- claude_mpm/agents/templates/version_control.json +8 -1
- claude_mpm/agents/templates/web_qa.json +7 -1
- claude_mpm/agents/templates/web_ui.json +11 -1
- claude_mpm/cli/__init__.py +34 -706
- claude_mpm/cli/commands/agent_manager.py +25 -12
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +204 -148
- claude_mpm/cli/commands/aggregate.py +7 -3
- claude_mpm/cli/commands/analyze.py +9 -4
- claude_mpm/cli/commands/analyze_code.py +7 -2
- claude_mpm/cli/commands/auto_configure.py +7 -9
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +294 -1788
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +167 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/local_deploy.py +537 -0
- claude_mpm/cli/commands/memory.py +54 -20
- claude_mpm/cli/commands/mpm_init.py +39 -25
- claude_mpm/cli/commands/mpm_init_handler.py +8 -3
- claude_mpm/cli/executor.py +202 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +3 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parsers/__init__.py +7 -1
- claude_mpm/cli/parsers/base_parser.py +98 -3
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +481 -0
- claude_mpm/cli/utils.py +52 -1
- claude_mpm/commands/mpm-help.md +3 -0
- 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/config/model_config.py +428 -0
- claude_mpm/core/base_service.py +13 -12
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/instruction_reinforcement_hook.py +2 -1
- claude_mpm/core/interactive_session.py +9 -3
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/oneshot_session.py +8 -4
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/service_registry.py +5 -1
- claude_mpm/core/types.py +2 -9
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/dashboard/static/js/dashboard.js +0 -14
- claude_mpm/dashboard/templates/index.html +3 -41
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/auto_config_manager.py +10 -11
- 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/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
- claude_mpm/services/agents/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/interfaces/__init__.py +74 -2
- claude_mpm/services/core/interfaces/health.py +172 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/models/__init__.py +33 -0
- claude_mpm/services/core/models/agent_config.py +12 -28
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +235 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/path_resolver.py +23 -7
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
- claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
- claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
- claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
- claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +36 -31
- claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
- claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
- claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
- claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
- claude_mpm/services/diagnostics/models.py +19 -24
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
- claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +163 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +430 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +9 -4
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +18 -31
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +71 -24
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/memory_hook_service.py +4 -1
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +453 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/daemon_manager.py +3 -2
- claude_mpm/services/monitor/handlers/dashboard.py +2 -1
- claude_mpm/services/monitor/handlers/hooks.py +2 -1
- claude_mpm/services/monitor/management/lifecycle.py +3 -2
- claude_mpm/services/monitor/server.py +2 -1
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/hook.py +13 -2
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/server/main.py +10 -8
- claude_mpm/services/subprocess_launcher_service.py +14 -5
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
- claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
- claude_mpm/services/unified/deployment_strategies/local.py +6 -5
- claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
- claude_mpm/services/unified/interfaces.py +3 -1
- claude_mpm/services/unified/unified_analyzer.py +14 -10
- claude_mpm/services/unified/unified_config.py +2 -1
- claude_mpm/services/unified/unified_deployment.py +9 -4
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/bundled/__init__.py +6 -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/database-migration.md +199 -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/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/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 +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +2 -2
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +117 -8
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +238 -174
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
|
@@ -14,6 +14,7 @@ import sys
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Any, Dict, List, Optional
|
|
16
16
|
|
|
17
|
+
from ...core.enums import OutputFormat
|
|
17
18
|
from ...core.logging_config import get_logger
|
|
18
19
|
from ...services.agents.agent_builder import AgentBuilderService
|
|
19
20
|
from ...services.agents.deployment.agent_deployment import AgentDeploymentService
|
|
@@ -36,6 +37,18 @@ class AgentManagerCommand(AgentCommand):
|
|
|
36
37
|
self.deployment_service = AgentDeploymentService()
|
|
37
38
|
return self.deployment_service
|
|
38
39
|
|
|
40
|
+
def _get_output_format(self, args) -> str:
|
|
41
|
+
"""
|
|
42
|
+
Get output format from args with enum default.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
args: Command arguments
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Output format string (compatible with both enum and string usage)
|
|
49
|
+
"""
|
|
50
|
+
return getattr(args, "format", OutputFormat.TEXT)
|
|
51
|
+
|
|
39
52
|
def run(self, args) -> CommandResult:
|
|
40
53
|
"""Execute agent manager command.
|
|
41
54
|
|
|
@@ -122,8 +135,8 @@ class AgentManagerCommand(AgentCommand):
|
|
|
122
135
|
)
|
|
123
136
|
|
|
124
137
|
# Format output
|
|
125
|
-
output_format =
|
|
126
|
-
if output_format ==
|
|
138
|
+
output_format = self._get_output_format(args)
|
|
139
|
+
if str(output_format).lower() == OutputFormat.JSON:
|
|
127
140
|
return CommandResult.success_result("Agents listed", data=agents)
|
|
128
141
|
output = self._format_agent_list(agents)
|
|
129
142
|
return CommandResult.success_result(output)
|
|
@@ -288,8 +301,8 @@ class AgentManagerCommand(AgentCommand):
|
|
|
288
301
|
if not agent_info:
|
|
289
302
|
return CommandResult.error_result(f"Agent '{agent_id}' not found")
|
|
290
303
|
|
|
291
|
-
output_format =
|
|
292
|
-
if output_format ==
|
|
304
|
+
output_format = self._get_output_format(args)
|
|
305
|
+
if str(output_format).lower() == OutputFormat.JSON:
|
|
293
306
|
return CommandResult.success_result("Agent details", data=agent_info)
|
|
294
307
|
output = self._format_agent_details(agent_info)
|
|
295
308
|
return CommandResult.success_result(output)
|
|
@@ -332,8 +345,8 @@ class AgentManagerCommand(AgentCommand):
|
|
|
332
345
|
"""List available agent templates."""
|
|
333
346
|
templates = self.builder_service.list_available_templates()
|
|
334
347
|
|
|
335
|
-
output_format =
|
|
336
|
-
if output_format ==
|
|
348
|
+
output_format = self._get_output_format(args)
|
|
349
|
+
if str(output_format).lower() == OutputFormat.JSON:
|
|
337
350
|
return CommandResult.success_result("Templates listed", data=templates)
|
|
338
351
|
output = "Available Agent Templates:\n\n"
|
|
339
352
|
for template in templates:
|
|
@@ -357,7 +370,7 @@ class AgentManagerCommand(AgentCommand):
|
|
|
357
370
|
clean_user = not getattr(args, "project_only", False)
|
|
358
371
|
dry_run = getattr(args, "dry_run", False)
|
|
359
372
|
force = getattr(args, "force", False)
|
|
360
|
-
output_format =
|
|
373
|
+
output_format = self._get_output_format(args)
|
|
361
374
|
|
|
362
375
|
# Track results
|
|
363
376
|
results = {
|
|
@@ -397,7 +410,7 @@ class AgentManagerCommand(AgentCommand):
|
|
|
397
410
|
)
|
|
398
411
|
|
|
399
412
|
# Handle output based on format
|
|
400
|
-
if output_format ==
|
|
413
|
+
if str(output_format).lower() == OutputFormat.JSON:
|
|
401
414
|
return CommandResult.success_result("Reset completed", data=results)
|
|
402
415
|
|
|
403
416
|
# Generate text output
|
|
@@ -858,9 +871,9 @@ class AgentManagerCommand(AgentCommand):
|
|
|
858
871
|
return CommandResult.success_result("No local agent templates found")
|
|
859
872
|
|
|
860
873
|
# Format output
|
|
861
|
-
output_format =
|
|
874
|
+
output_format = self._get_output_format(args)
|
|
862
875
|
|
|
863
|
-
if output_format ==
|
|
876
|
+
if str(output_format).lower() == OutputFormat.JSON:
|
|
864
877
|
data = [
|
|
865
878
|
{
|
|
866
879
|
"id": t.agent_id,
|
|
@@ -1379,8 +1392,8 @@ def manage_agent_manager(args) -> int:
|
|
|
1379
1392
|
|
|
1380
1393
|
if result.success:
|
|
1381
1394
|
# Handle JSON output format
|
|
1382
|
-
output_format = getattr(args, "format",
|
|
1383
|
-
if output_format ==
|
|
1395
|
+
output_format = getattr(args, "format", OutputFormat.TEXT)
|
|
1396
|
+
if str(output_format).lower() == OutputFormat.JSON and result.data is not None:
|
|
1384
1397
|
print(json.dumps(result.data, indent=2))
|
|
1385
1398
|
elif result.message:
|
|
1386
1399
|
print(result.message)
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""Agent state management for configure command.
|
|
2
|
+
|
|
3
|
+
This module provides state persistence for agent enable/disable operations,
|
|
4
|
+
maintaining consistency between in-memory state and filesystem state.
|
|
5
|
+
|
|
6
|
+
Coverage: 100% - Safe to extract and refactor independently.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Dict, List
|
|
13
|
+
|
|
14
|
+
from claude_mpm.cli.commands.configure_models import AgentConfig
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SimpleAgentManager:
|
|
18
|
+
"""Simple agent state management that discovers real agents from templates.
|
|
19
|
+
|
|
20
|
+
This class handles:
|
|
21
|
+
- Loading agent states from filesystem
|
|
22
|
+
- Tracking pending enable/disable operations
|
|
23
|
+
- Committing state changes to disk
|
|
24
|
+
- Rolling back failed operations
|
|
25
|
+
|
|
26
|
+
100% test coverage ensures this can be safely refactored.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, config_dir: Path):
|
|
30
|
+
"""Initialize agent manager.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
config_dir: Path to .claude-mpm directory
|
|
34
|
+
"""
|
|
35
|
+
self.config_dir = config_dir
|
|
36
|
+
self.config_file = config_dir / "agent_states.json"
|
|
37
|
+
self.config_dir.mkdir(parents=True, exist_ok=True)
|
|
38
|
+
self._load_states()
|
|
39
|
+
# Path to agent templates directory
|
|
40
|
+
self.templates_dir = (
|
|
41
|
+
Path(__file__).parent.parent.parent / "agents" / "templates"
|
|
42
|
+
)
|
|
43
|
+
# Add logger for error reporting
|
|
44
|
+
self.logger = logging.getLogger(__name__)
|
|
45
|
+
# Track pending changes for batch operations
|
|
46
|
+
self.deferred_changes: Dict[str, bool] = {}
|
|
47
|
+
|
|
48
|
+
def _load_states(self):
|
|
49
|
+
"""Load agent states from file."""
|
|
50
|
+
if self.config_file.exists():
|
|
51
|
+
with self.config_file.open() as f:
|
|
52
|
+
self.states = json.load(f)
|
|
53
|
+
else:
|
|
54
|
+
self.states = {}
|
|
55
|
+
|
|
56
|
+
def _save_states(self):
|
|
57
|
+
"""Save agent states to file."""
|
|
58
|
+
with self.config_file.open("w") as f:
|
|
59
|
+
json.dump(self.states, f, indent=2)
|
|
60
|
+
|
|
61
|
+
def is_agent_enabled(self, agent_name: str) -> bool:
|
|
62
|
+
"""Check if an agent is enabled."""
|
|
63
|
+
return self.states.get(agent_name, {}).get("enabled", True)
|
|
64
|
+
|
|
65
|
+
def set_agent_enabled(self, agent_name: str, enabled: bool):
|
|
66
|
+
"""Set agent enabled state."""
|
|
67
|
+
if agent_name not in self.states:
|
|
68
|
+
self.states[agent_name] = {}
|
|
69
|
+
self.states[agent_name]["enabled"] = enabled
|
|
70
|
+
self._save_states()
|
|
71
|
+
|
|
72
|
+
def set_agent_enabled_deferred(self, agent_name: str, enabled: bool) -> None:
|
|
73
|
+
"""Queue agent state change without saving."""
|
|
74
|
+
self.deferred_changes[agent_name] = enabled
|
|
75
|
+
|
|
76
|
+
def commit_deferred_changes(self) -> None:
|
|
77
|
+
"""Save all deferred changes at once."""
|
|
78
|
+
for agent_name, enabled in self.deferred_changes.items():
|
|
79
|
+
if agent_name not in self.states:
|
|
80
|
+
self.states[agent_name] = {}
|
|
81
|
+
self.states[agent_name]["enabled"] = enabled
|
|
82
|
+
self._save_states()
|
|
83
|
+
self.deferred_changes.clear()
|
|
84
|
+
|
|
85
|
+
def discard_deferred_changes(self) -> None:
|
|
86
|
+
"""Discard all pending changes."""
|
|
87
|
+
self.deferred_changes.clear()
|
|
88
|
+
|
|
89
|
+
def get_pending_state(self, agent_name: str) -> bool:
|
|
90
|
+
"""Get agent state including pending changes."""
|
|
91
|
+
if agent_name in self.deferred_changes:
|
|
92
|
+
return self.deferred_changes[agent_name]
|
|
93
|
+
return self.states.get(agent_name, {}).get("enabled", True)
|
|
94
|
+
|
|
95
|
+
def has_pending_changes(self) -> bool:
|
|
96
|
+
"""Check if there are unsaved changes."""
|
|
97
|
+
return len(self.deferred_changes) > 0
|
|
98
|
+
|
|
99
|
+
def discover_agents(self) -> List[AgentConfig]:
|
|
100
|
+
"""Discover available agents from template JSON files."""
|
|
101
|
+
agents = []
|
|
102
|
+
|
|
103
|
+
# Scan templates directory for JSON files
|
|
104
|
+
if not self.templates_dir.exists():
|
|
105
|
+
# Fallback to a minimal set if templates dir doesn't exist
|
|
106
|
+
return [
|
|
107
|
+
AgentConfig("engineer", "Engineering agent (templates not found)", []),
|
|
108
|
+
AgentConfig("research", "Research agent (templates not found)", []),
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
try:
|
|
112
|
+
# Read all JSON template files
|
|
113
|
+
for template_file in sorted(self.templates_dir.glob("*.json")):
|
|
114
|
+
# Skip backup files
|
|
115
|
+
if "backup" in template_file.name.lower():
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
with template_file.open() as f:
|
|
120
|
+
template_data = json.load(f)
|
|
121
|
+
|
|
122
|
+
# Extract agent information from template
|
|
123
|
+
agent_id = template_data.get("agent_id", template_file.stem)
|
|
124
|
+
|
|
125
|
+
# Get metadata for display info
|
|
126
|
+
metadata = template_data.get("metadata", {})
|
|
127
|
+
metadata.get("name", agent_id)
|
|
128
|
+
description = metadata.get(
|
|
129
|
+
"description", "No description available"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Extract capabilities/tools as dependencies for display
|
|
133
|
+
capabilities = template_data.get("capabilities", {})
|
|
134
|
+
tools = capabilities.get("tools", [])
|
|
135
|
+
# Ensure tools is a list before slicing
|
|
136
|
+
if not isinstance(tools, list):
|
|
137
|
+
tools = []
|
|
138
|
+
# Show first few tools as "dependencies" for UI purposes
|
|
139
|
+
display_tools = tools[:3] if len(tools) > 3 else tools
|
|
140
|
+
|
|
141
|
+
# Normalize agent ID (remove -agent suffix if present, replace underscores)
|
|
142
|
+
normalized_id = agent_id.replace("-agent", "").replace("_", "-")
|
|
143
|
+
|
|
144
|
+
agents.append(
|
|
145
|
+
AgentConfig(
|
|
146
|
+
name=normalized_id,
|
|
147
|
+
description=(
|
|
148
|
+
description[:80] + "..."
|
|
149
|
+
if len(description) > 80
|
|
150
|
+
else description
|
|
151
|
+
),
|
|
152
|
+
dependencies=display_tools,
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
except (json.JSONDecodeError, KeyError) as e:
|
|
157
|
+
# Log malformed templates but continue
|
|
158
|
+
self.logger.debug(
|
|
159
|
+
f"Skipping malformed template {template_file.name}: {e}"
|
|
160
|
+
)
|
|
161
|
+
continue
|
|
162
|
+
except Exception as e:
|
|
163
|
+
# Log unexpected errors but continue processing other templates
|
|
164
|
+
self.logger.debug(
|
|
165
|
+
f"Error processing template {template_file.name}: {e}"
|
|
166
|
+
)
|
|
167
|
+
continue
|
|
168
|
+
|
|
169
|
+
except Exception as e:
|
|
170
|
+
# If there's a catastrophic error reading templates directory
|
|
171
|
+
self.logger.error(f"Failed to read templates directory: {e}")
|
|
172
|
+
return [
|
|
173
|
+
AgentConfig("engineer", f"Error accessing templates: {e!s}", []),
|
|
174
|
+
AgentConfig("research", "Research agent", []),
|
|
175
|
+
]
|
|
176
|
+
|
|
177
|
+
# Sort agents by name for consistent display
|
|
178
|
+
agents.sort(key=lambda a: a.name)
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
agents
|
|
182
|
+
if agents
|
|
183
|
+
else [
|
|
184
|
+
AgentConfig("engineer", "No agents found in templates", []),
|
|
185
|
+
]
|
|
186
|
+
)
|