claude-mpm 4.15.2__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/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 +216 -37
- 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 +9 -2
- claude_mpm/agents/templates/prompt-engineer.json +5 -1
- claude_mpm/agents/templates/python_engineer.json +19 -4
- 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 +23 -8
- 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/commands/__init__.py +2 -0
- claude_mpm/cli/commands/configure.py +164 -16
- claude_mpm/cli/commands/configure_agent_display.py +6 -6
- claude_mpm/cli/commands/configure_behavior_manager.py +8 -8
- claude_mpm/cli/commands/configure_navigation.py +20 -18
- claude_mpm/cli/commands/configure_startup_manager.py +14 -14
- claude_mpm/cli/commands/configure_template_editor.py +8 -8
- 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/interactive/__init__.py +3 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parsers/base_parser.py +7 -0
- claude_mpm/cli/parsers/skills_parser.py +137 -0
- claude_mpm/cli/startup.py +83 -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/enums.py +18 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/core/types.py +2 -9
- claude_mpm/dashboard/static/js/dashboard.js +0 -14
- claude_mpm/dashboard/templates/index.html +3 -41
- 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/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/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/models/health.py +1 -28
- claude_mpm/services/core/path_resolver.py +1 -1
- 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 +1 -1
- claude_mpm/services/local_ops/crash_detector.py +1 -1
- claude_mpm/services/local_ops/health_checks/http_check.py +2 -1
- claude_mpm/services/local_ops/health_checks/process_check.py +2 -1
- claude_mpm/services/local_ops/health_checks/resource_check.py +2 -1
- claude_mpm/services/local_ops/health_manager.py +1 -1
- claude_mpm/services/local_ops/restart_manager.py +1 -1
- claude_mpm/services/mcp_config_manager.py +7 -131
- 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 +10 -0
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/server/main.py +7 -7
- claude_mpm/services/unified/deployment_strategies/local.py +1 -1
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +331 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -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/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 +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- 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.15.2.dist-info → claude_mpm-4.20.3.dist-info}/METADATA +211 -33
- {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/RECORD +195 -115
- claude_mpm/agents/INSTRUCTIONS_OLD_DEPRECATED.md +0 -602
- 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-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/WHEEL +0 -0
- {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/top_level.txt +0 -0
|
@@ -26,10 +26,10 @@ import threading
|
|
|
26
26
|
from collections import defaultdict
|
|
27
27
|
from typing import Callable, Dict, List, Set
|
|
28
28
|
|
|
29
|
+
from claude_mpm.core.enums import HealthStatus
|
|
29
30
|
from claude_mpm.services.core.base import SyncBaseService
|
|
30
31
|
from claude_mpm.services.core.interfaces.health import IHealthCheckManager
|
|
31
32
|
from claude_mpm.services.core.interfaces.restart import ICrashDetector
|
|
32
|
-
from claude_mpm.services.core.models.health import HealthStatus
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class CrashDetector(SyncBaseService, ICrashDetector):
|
|
@@ -29,10 +29,11 @@ import time
|
|
|
29
29
|
import requests
|
|
30
30
|
from requests.exceptions import ConnectionError, RequestException, Timeout
|
|
31
31
|
|
|
32
|
+
from claude_mpm.core.enums import HealthStatus
|
|
32
33
|
from claude_mpm.services.core.base import SyncBaseService
|
|
33
34
|
from claude_mpm.services.core.interfaces.health import IHealthCheck
|
|
34
35
|
from claude_mpm.services.core.interfaces.process import ILocalProcessManager
|
|
35
|
-
from claude_mpm.services.core.models.health import HealthCheckResult
|
|
36
|
+
from claude_mpm.services.core.models.health import HealthCheckResult
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
class HttpHealthCheck(SyncBaseService, IHealthCheck):
|
|
@@ -22,10 +22,11 @@ USAGE:
|
|
|
22
22
|
|
|
23
23
|
import psutil
|
|
24
24
|
|
|
25
|
+
from claude_mpm.core.enums import HealthStatus
|
|
25
26
|
from claude_mpm.services.core.base import SyncBaseService
|
|
26
27
|
from claude_mpm.services.core.interfaces.health import IHealthCheck
|
|
27
28
|
from claude_mpm.services.core.interfaces.process import ILocalProcessManager
|
|
28
|
-
from claude_mpm.services.core.models.health import HealthCheckResult
|
|
29
|
+
from claude_mpm.services.core.models.health import HealthCheckResult
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
class ProcessHealthCheck(SyncBaseService, IHealthCheck):
|
|
@@ -28,10 +28,11 @@ import platform
|
|
|
28
28
|
|
|
29
29
|
import psutil
|
|
30
30
|
|
|
31
|
+
from claude_mpm.core.enums import HealthStatus
|
|
31
32
|
from claude_mpm.services.core.base import SyncBaseService
|
|
32
33
|
from claude_mpm.services.core.interfaces.health import IHealthCheck
|
|
33
34
|
from claude_mpm.services.core.interfaces.process import ILocalProcessManager
|
|
34
|
-
from claude_mpm.services.core.models.health import HealthCheckResult
|
|
35
|
+
from claude_mpm.services.core.models.health import HealthCheckResult
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
class ResourceHealthCheck(SyncBaseService, IHealthCheck):
|
|
@@ -39,13 +39,13 @@ import threading
|
|
|
39
39
|
from collections import defaultdict
|
|
40
40
|
from typing import Callable, Dict, List, Optional
|
|
41
41
|
|
|
42
|
+
from claude_mpm.core.enums import HealthStatus
|
|
42
43
|
from claude_mpm.services.core.base import SyncBaseService
|
|
43
44
|
from claude_mpm.services.core.interfaces.health import IHealthCheckManager
|
|
44
45
|
from claude_mpm.services.core.interfaces.process import ILocalProcessManager
|
|
45
46
|
from claude_mpm.services.core.models.health import (
|
|
46
47
|
DeploymentHealth,
|
|
47
48
|
HealthCheckResult,
|
|
48
|
-
HealthStatus,
|
|
49
49
|
)
|
|
50
50
|
from claude_mpm.services.local_ops.health_checks import (
|
|
51
51
|
HttpHealthCheck,
|
|
@@ -43,6 +43,7 @@ import time
|
|
|
43
43
|
from pathlib import Path
|
|
44
44
|
from typing import Optional, Set
|
|
45
45
|
|
|
46
|
+
from claude_mpm.core.enums import HealthStatus
|
|
46
47
|
from claude_mpm.services.core.base import SyncBaseService
|
|
47
48
|
from claude_mpm.services.core.interfaces.health import IHealthCheckManager
|
|
48
49
|
from claude_mpm.services.core.interfaces.process import ILocalProcessManager
|
|
@@ -51,7 +52,6 @@ from claude_mpm.services.core.interfaces.restart import (
|
|
|
51
52
|
IRestartManager,
|
|
52
53
|
IRestartPolicy,
|
|
53
54
|
)
|
|
54
|
-
from claude_mpm.services.core.models.health import HealthStatus
|
|
55
55
|
from claude_mpm.services.core.models.restart import RestartHistory
|
|
56
56
|
|
|
57
57
|
|
|
@@ -1130,139 +1130,15 @@ class MCPConfigManager:
|
|
|
1130
1130
|
"""
|
|
1131
1131
|
Detect and fix corrupted MCP service installations.
|
|
1132
1132
|
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
3. Fixes missing dependencies (like mcp-ticketer's gql)
|
|
1137
|
-
4. Validates fixes worked
|
|
1133
|
+
NOTE: Proactive health checking has been disabled.
|
|
1134
|
+
Each MCP service should stand on its own and handle its own issues.
|
|
1135
|
+
This function now only returns success without checking services.
|
|
1138
1136
|
|
|
1139
1137
|
Returns:
|
|
1140
1138
|
Tuple of (success, message)
|
|
1141
1139
|
"""
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
failed_services = []
|
|
1145
|
-
|
|
1146
|
-
# Check each service for issues
|
|
1147
|
-
for service_name in self.PIPX_SERVICES:
|
|
1148
|
-
# Check if service is enabled in config
|
|
1149
|
-
if not self.should_enable_service(service_name):
|
|
1150
|
-
self.logger.debug(f"Skipping {service_name} (disabled in config)")
|
|
1151
|
-
continue
|
|
1152
|
-
|
|
1153
|
-
self.logger.debug(f"🔍 Checking {service_name} for issues...")
|
|
1154
|
-
issue_type = self._detect_service_issue(service_name)
|
|
1155
|
-
if issue_type:
|
|
1156
|
-
services_to_fix.append((service_name, issue_type))
|
|
1157
|
-
self.logger.debug(f" ⚠️ Found issue with {service_name}: {issue_type}")
|
|
1158
|
-
else:
|
|
1159
|
-
self.logger.debug(f" ✅ {service_name} is functioning correctly")
|
|
1160
|
-
|
|
1161
|
-
if not services_to_fix:
|
|
1162
|
-
return True, "All MCP services are functioning correctly"
|
|
1163
|
-
|
|
1164
|
-
# Fix each problematic service
|
|
1165
|
-
for service_name, issue_type in services_to_fix:
|
|
1166
|
-
self.logger.info(f"🔧 Fixing {service_name}: {issue_type}")
|
|
1167
|
-
|
|
1168
|
-
if issue_type == "not_installed":
|
|
1169
|
-
# Install the service
|
|
1170
|
-
success, method = self._install_service_with_fallback(service_name)
|
|
1171
|
-
if success:
|
|
1172
|
-
fixed_services.append(f"{service_name} (installed via {method})")
|
|
1173
|
-
else:
|
|
1174
|
-
failed_services.append(f"{service_name} (installation failed)")
|
|
1175
|
-
|
|
1176
|
-
elif issue_type == "import_error":
|
|
1177
|
-
# Reinstall to fix corrupted installation
|
|
1178
|
-
self.logger.info(
|
|
1179
|
-
f" Reinstalling {service_name} to fix import errors..."
|
|
1180
|
-
)
|
|
1181
|
-
success = self._reinstall_service(service_name)
|
|
1182
|
-
if success:
|
|
1183
|
-
# NOTE: Removed automatic dependency injection workaround
|
|
1184
|
-
# Package maintainers should fix dependency declarations
|
|
1185
|
-
fixed_services.append(f"{service_name} (reinstalled)")
|
|
1186
|
-
else:
|
|
1187
|
-
failed_services.append(f"{service_name} (reinstall failed)")
|
|
1188
|
-
|
|
1189
|
-
elif issue_type == "missing_dependency":
|
|
1190
|
-
# Fix missing dependencies - try injection first, then reinstall if needed
|
|
1191
|
-
self.logger.info(
|
|
1192
|
-
f" {service_name} has missing dependencies - attempting fix..."
|
|
1193
|
-
)
|
|
1194
|
-
|
|
1195
|
-
# First try to inject dependencies without reinstalling
|
|
1196
|
-
injection_success = self._inject_missing_dependencies(service_name)
|
|
1197
|
-
|
|
1198
|
-
if injection_success:
|
|
1199
|
-
# Verify the fix worked
|
|
1200
|
-
issue_after_injection = self._detect_service_issue(service_name)
|
|
1201
|
-
if issue_after_injection is None:
|
|
1202
|
-
fixed_services.append(f"{service_name} (dependencies injected)")
|
|
1203
|
-
self.logger.info(
|
|
1204
|
-
f" ✅ Fixed {service_name} with dependency injection"
|
|
1205
|
-
)
|
|
1206
|
-
continue # Move to next service
|
|
1207
|
-
|
|
1208
|
-
# If injection alone didn't work, try full reinstall
|
|
1209
|
-
self.logger.info(
|
|
1210
|
-
" Dependency injection insufficient, trying full reinstall..."
|
|
1211
|
-
)
|
|
1212
|
-
success = self._auto_reinstall_mcp_service(service_name)
|
|
1213
|
-
if success:
|
|
1214
|
-
fixed_services.append(
|
|
1215
|
-
f"{service_name} (auto-reinstalled with dependencies)"
|
|
1216
|
-
)
|
|
1217
|
-
else:
|
|
1218
|
-
# Provide specific manual fix for known services
|
|
1219
|
-
if service_name == "mcp-ticketer":
|
|
1220
|
-
self.logger.warning(
|
|
1221
|
-
f" Auto-fix failed for {service_name}. Manual fix: "
|
|
1222
|
-
f"pipx uninstall {service_name} && pipx install {service_name} && pipx inject {service_name} gql"
|
|
1223
|
-
)
|
|
1224
|
-
else:
|
|
1225
|
-
self.logger.warning(
|
|
1226
|
-
f" Auto-reinstall failed for {service_name}. Manual fix: "
|
|
1227
|
-
f"pipx uninstall {service_name} && pipx install {service_name}"
|
|
1228
|
-
)
|
|
1229
|
-
failed_services.append(f"{service_name} (auto-reinstall failed)")
|
|
1230
|
-
|
|
1231
|
-
elif issue_type == "path_issue":
|
|
1232
|
-
# Path issues are handled by config updates
|
|
1233
|
-
self.logger.info(
|
|
1234
|
-
f" Path issue for {service_name} will be fixed by config update"
|
|
1235
|
-
)
|
|
1236
|
-
fixed_services.append(f"{service_name} (config updated)")
|
|
1237
|
-
|
|
1238
|
-
# Build result message
|
|
1239
|
-
messages = []
|
|
1240
|
-
if fixed_services:
|
|
1241
|
-
messages.append(f"✅ Fixed: {', '.join(fixed_services)}")
|
|
1242
|
-
if failed_services:
|
|
1243
|
-
messages.append(f"❌ Failed: {', '.join(failed_services)}")
|
|
1244
|
-
|
|
1245
|
-
# Return success if at least some services were fixed
|
|
1246
|
-
success = len(fixed_services) > 0 or len(failed_services) == 0
|
|
1247
|
-
message = " | ".join(messages) if messages else "No services needed fixing"
|
|
1248
|
-
|
|
1249
|
-
# Provide manual fix instructions if auto-fix failed
|
|
1250
|
-
if failed_services:
|
|
1251
|
-
message += "\n\n💡 Manual fix instructions:"
|
|
1252
|
-
for failed in failed_services:
|
|
1253
|
-
service = failed.split(" ")[0]
|
|
1254
|
-
if service in self.SERVICE_MISSING_DEPENDENCIES:
|
|
1255
|
-
deps = " ".join(
|
|
1256
|
-
[
|
|
1257
|
-
f"&& pipx inject {service} {dep}"
|
|
1258
|
-
for dep in self.SERVICE_MISSING_DEPENDENCIES[service]
|
|
1259
|
-
]
|
|
1260
|
-
)
|
|
1261
|
-
message += f"\n • {service}: pipx uninstall {service} && pipx install {service} {deps}"
|
|
1262
|
-
else:
|
|
1263
|
-
message += f"\n • {service}: pipx uninstall {service} && pipx install {service}"
|
|
1264
|
-
|
|
1265
|
-
return success, message
|
|
1140
|
+
# Services should stand on their own - no proactive health checking
|
|
1141
|
+
return True, "MCP services managing their own health"
|
|
1266
1142
|
|
|
1267
1143
|
def _detect_service_issue(self, service_name: str) -> Optional[str]:
|
|
1268
1144
|
"""
|
|
@@ -1497,7 +1373,7 @@ class MCPConfigManager:
|
|
|
1497
1373
|
)
|
|
1498
1374
|
|
|
1499
1375
|
if result.returncode == 0:
|
|
1500
|
-
self.logger.
|
|
1376
|
+
self.logger.debug(f" ✅ Successfully injected {dep}")
|
|
1501
1377
|
# Check if already injected (pipx will complain if package already exists)
|
|
1502
1378
|
elif (
|
|
1503
1379
|
"already satisfied" in result.stderr.lower()
|
|
@@ -1582,7 +1458,7 @@ class MCPConfigManager:
|
|
|
1582
1458
|
)
|
|
1583
1459
|
|
|
1584
1460
|
# Verify the reinstall worked
|
|
1585
|
-
self.logger.
|
|
1461
|
+
self.logger.debug(f" → Verifying {service_name} installation...")
|
|
1586
1462
|
issue = self._detect_service_issue(service_name)
|
|
1587
1463
|
|
|
1588
1464
|
if issue is None:
|
|
@@ -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
|
"""
|
|
@@ -4,23 +4,12 @@ Base class for asynchronous services to reduce duplication.
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
from abc import ABC, abstractmethod
|
|
7
|
-
from enum import Enum
|
|
8
7
|
from typing import Any, Dict, Optional
|
|
9
8
|
|
|
9
|
+
from ...core.enums import ServiceState
|
|
10
10
|
from ...core.mixins import LoggerMixin
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class AsyncServiceState(Enum):
|
|
14
|
-
"""Standard states for async services."""
|
|
15
|
-
|
|
16
|
-
UNINITIALIZED = "uninitialized"
|
|
17
|
-
INITIALIZING = "initializing"
|
|
18
|
-
RUNNING = "running"
|
|
19
|
-
STOPPING = "stopping"
|
|
20
|
-
STOPPED = "stopped"
|
|
21
|
-
ERROR = "error"
|
|
22
|
-
|
|
23
|
-
|
|
24
13
|
class AsyncServiceBase(LoggerMixin, ABC):
|
|
25
14
|
"""
|
|
26
15
|
Base class for asynchronous services.
|
|
@@ -45,7 +34,7 @@ class AsyncServiceBase(LoggerMixin, ABC):
|
|
|
45
34
|
self.config = config or {}
|
|
46
35
|
|
|
47
36
|
# State management
|
|
48
|
-
self._state =
|
|
37
|
+
self._state = ServiceState.UNINITIALIZED
|
|
49
38
|
self._state_lock = asyncio.Lock()
|
|
50
39
|
|
|
51
40
|
# Background tasks
|
|
@@ -57,19 +46,19 @@ class AsyncServiceBase(LoggerMixin, ABC):
|
|
|
57
46
|
self._error_count = 0
|
|
58
47
|
|
|
59
48
|
@property
|
|
60
|
-
def state(self) ->
|
|
49
|
+
def state(self) -> ServiceState:
|
|
61
50
|
"""Get current service state."""
|
|
62
51
|
return self._state
|
|
63
52
|
|
|
64
53
|
@property
|
|
65
54
|
def is_running(self) -> bool:
|
|
66
55
|
"""Check if service is running."""
|
|
67
|
-
return self._state ==
|
|
56
|
+
return self._state == ServiceState.RUNNING
|
|
68
57
|
|
|
69
58
|
@property
|
|
70
59
|
def is_healthy(self) -> bool:
|
|
71
60
|
"""Check if service is healthy."""
|
|
72
|
-
return self._state ==
|
|
61
|
+
return self._state == ServiceState.RUNNING and self._last_error is None
|
|
73
62
|
|
|
74
63
|
async def initialize(self) -> bool:
|
|
75
64
|
"""
|
|
@@ -79,22 +68,22 @@ class AsyncServiceBase(LoggerMixin, ABC):
|
|
|
79
68
|
True if initialization successful
|
|
80
69
|
"""
|
|
81
70
|
async with self._state_lock:
|
|
82
|
-
if self._state !=
|
|
71
|
+
if self._state != ServiceState.UNINITIALIZED:
|
|
83
72
|
self.logger.warning(f"Service {self.service_name} already initialized")
|
|
84
|
-
return self._state ==
|
|
73
|
+
return self._state == ServiceState.RUNNING
|
|
85
74
|
|
|
86
|
-
self._state =
|
|
75
|
+
self._state = ServiceState.INITIALIZING
|
|
87
76
|
self.logger.info(f"Initializing service: {self.service_name}")
|
|
88
77
|
|
|
89
78
|
try:
|
|
90
79
|
success = await self._do_initialize()
|
|
91
80
|
if success:
|
|
92
|
-
self._state =
|
|
81
|
+
self._state = ServiceState.RUNNING
|
|
93
82
|
self.logger.info(
|
|
94
83
|
f"Service {self.service_name} initialized successfully"
|
|
95
84
|
)
|
|
96
85
|
else:
|
|
97
|
-
self._state =
|
|
86
|
+
self._state = ServiceState.ERROR
|
|
98
87
|
self.logger.error(
|
|
99
88
|
f"Service {self.service_name} initialization failed"
|
|
100
89
|
)
|
|
@@ -102,7 +91,7 @@ class AsyncServiceBase(LoggerMixin, ABC):
|
|
|
102
91
|
return success
|
|
103
92
|
|
|
104
93
|
except Exception as e:
|
|
105
|
-
self._state =
|
|
94
|
+
self._state = ServiceState.ERROR
|
|
106
95
|
self._last_error = e
|
|
107
96
|
self._error_count += 1
|
|
108
97
|
self.logger.error(
|
|
@@ -114,10 +103,10 @@ class AsyncServiceBase(LoggerMixin, ABC):
|
|
|
114
103
|
async def shutdown(self) -> None:
|
|
115
104
|
"""Shutdown the service gracefully."""
|
|
116
105
|
async with self._state_lock:
|
|
117
|
-
if self._state in (
|
|
106
|
+
if self._state in (ServiceState.STOPPED, ServiceState.STOPPING):
|
|
118
107
|
return
|
|
119
108
|
|
|
120
|
-
self._state =
|
|
109
|
+
self._state = ServiceState.STOPPING
|
|
121
110
|
self.logger.info(f"Shutting down service: {self.service_name}")
|
|
122
111
|
|
|
123
112
|
try:
|
|
@@ -130,11 +119,11 @@ class AsyncServiceBase(LoggerMixin, ABC):
|
|
|
130
119
|
# Service-specific shutdown
|
|
131
120
|
await self._do_shutdown()
|
|
132
121
|
|
|
133
|
-
self._state =
|
|
122
|
+
self._state = ServiceState.STOPPED
|
|
134
123
|
self.logger.info(f"Service {self.service_name} shut down successfully")
|
|
135
124
|
|
|
136
125
|
except Exception as e:
|
|
137
|
-
self._state =
|
|
126
|
+
self._state = ServiceState.ERROR
|
|
138
127
|
self._last_error = e
|
|
139
128
|
self.logger.error(
|
|
140
129
|
f"Service {self.service_name} shutdown error: {e}", exc_info=True
|
|
@@ -146,7 +135,7 @@ class AsyncServiceBase(LoggerMixin, ABC):
|
|
|
146
135
|
await self.shutdown()
|
|
147
136
|
|
|
148
137
|
# Reset state for restart
|
|
149
|
-
self._state =
|
|
138
|
+
self._state = ServiceState.UNINITIALIZED
|
|
150
139
|
self._shutdown_event.clear()
|
|
151
140
|
self._last_error = None
|
|
152
141
|
|
|
@@ -4,25 +4,12 @@ Base class for services with complex lifecycle management.
|
|
|
4
4
|
|
|
5
5
|
import time
|
|
6
6
|
from abc import ABC, abstractmethod
|
|
7
|
-
from enum import Enum
|
|
8
7
|
from typing import Any, Dict, List, Optional
|
|
9
8
|
|
|
9
|
+
from ...core.enums import ServiceState
|
|
10
10
|
from ...core.mixins import LoggerMixin
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class ServiceState(Enum):
|
|
14
|
-
"""Standard service states."""
|
|
15
|
-
|
|
16
|
-
UNINITIALIZED = "uninitialized"
|
|
17
|
-
INITIALIZING = "initializing"
|
|
18
|
-
INITIALIZED = "initialized"
|
|
19
|
-
STARTING = "starting"
|
|
20
|
-
RUNNING = "running"
|
|
21
|
-
STOPPING = "stopping"
|
|
22
|
-
STOPPED = "stopped"
|
|
23
|
-
ERROR = "error"
|
|
24
|
-
|
|
25
|
-
|
|
26
13
|
class LifecycleServiceBase(LoggerMixin, ABC):
|
|
27
14
|
"""
|
|
28
15
|
Base class for services with complex lifecycle management.
|
|
@@ -7,7 +7,9 @@ and maintainability.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from .base import BaseEventHandler
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
# DISABLED: File Tree interface removed from dashboard
|
|
12
|
+
# from .code_analysis import CodeAnalysisEventHandler
|
|
11
13
|
from .connection import ConnectionEventHandler
|
|
12
14
|
from .file import FileEventHandler
|
|
13
15
|
from .git import GitEventHandler
|
|
@@ -17,7 +19,8 @@ from .registry import EventHandlerRegistry
|
|
|
17
19
|
|
|
18
20
|
__all__ = [
|
|
19
21
|
"BaseEventHandler",
|
|
20
|
-
|
|
22
|
+
# DISABLED: File Tree interface removed from dashboard
|
|
23
|
+
# "CodeAnalysisEventHandler",
|
|
21
24
|
"ConnectionEventHandler",
|
|
22
25
|
"EventHandlerRegistry",
|
|
23
26
|
"FileEventHandler",
|