claude-mpm 4.3.12__py3-none-any.whl → 4.3.14__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/PM_INSTRUCTIONS.md +414 -28
- claude_mpm/agents/templates/data_engineer.json +39 -14
- claude_mpm/agents/templates/engineer.json +11 -3
- claude_mpm/cli/commands/agent_manager.py +3 -3
- claude_mpm/cli/commands/agents.py +2 -2
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/config.py +2 -2
- claude_mpm/cli/commands/configure.py +5 -5
- claude_mpm/cli/commands/configure_tui.py +7 -7
- claude_mpm/cli/commands/dashboard.py +1 -1
- claude_mpm/cli/commands/debug.py +5 -5
- claude_mpm/cli/commands/mcp.py +1 -1
- claude_mpm/cli/commands/mcp_command_router.py +1 -1
- claude_mpm/cli/commands/mcp_config.py +7 -10
- claude_mpm/cli/commands/mcp_external_commands.py +40 -32
- claude_mpm/cli/commands/mcp_install_commands.py +38 -10
- claude_mpm/cli/commands/mcp_setup_external.py +143 -102
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init_handler.py +1 -1
- claude_mpm/cli/commands/run.py +54 -2
- claude_mpm/cli/commands/search.py +41 -34
- claude_mpm/cli/interactive/agent_wizard.py +6 -2
- claude_mpm/cli/parsers/mcp_parser.py +1 -3
- claude_mpm/cli/parsers/search_parser.py +10 -4
- claude_mpm/cli/startup_logging.py +158 -5
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/core/agent_registry.py +2 -2
- claude_mpm/core/agent_session_manager.py +8 -8
- claude_mpm/core/api_validator.py +6 -4
- claude_mpm/core/base_service.py +10 -10
- claude_mpm/core/cache.py +5 -5
- claude_mpm/core/config_constants.py +1 -1
- claude_mpm/core/container.py +1 -1
- claude_mpm/core/error_handler.py +2 -2
- claude_mpm/core/file_utils.py +1 -1
- claude_mpm/core/framework_loader.py +3 -3
- claude_mpm/core/hook_manager.py +8 -6
- claude_mpm/core/instruction_reinforcement_hook.py +2 -2
- claude_mpm/core/interactive_session.py +3 -1
- claude_mpm/core/lazy.py +3 -3
- claude_mpm/core/log_manager.py +16 -12
- claude_mpm/core/logger.py +16 -11
- claude_mpm/core/optimized_agent_loader.py +6 -6
- claude_mpm/core/output_style_manager.py +1 -1
- claude_mpm/core/pm_hook_interceptor.py +3 -3
- claude_mpm/core/service_registry.py +1 -1
- claude_mpm/core/session_manager.py +11 -9
- claude_mpm/core/socketio_pool.py +13 -13
- claude_mpm/core/types.py +2 -2
- claude_mpm/core/unified_agent_registry.py +2 -2
- claude_mpm/core/unified_paths.py +1 -1
- claude_mpm/dashboard/analysis_runner.py +4 -4
- claude_mpm/dashboard/api/simple_directory.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +4 -2
- claude_mpm/hooks/base_hook.py +2 -2
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
- claude_mpm/hooks/claude_hooks/event_handlers.py +12 -12
- claude_mpm/hooks/claude_hooks/hook_handler.py +4 -4
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +3 -3
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +15 -14
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +4 -4
- claude_mpm/hooks/claude_hooks/installer.py +3 -3
- claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
- claude_mpm/hooks/claude_hooks/response_tracking.py +3 -3
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +8 -5
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +3 -3
- claude_mpm/hooks/claude_hooks/services/state_manager.py +8 -7
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
- claude_mpm/hooks/claude_hooks/tool_analysis.py +2 -2
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- claude_mpm/hooks/tool_call_interceptor.py +2 -2
- claude_mpm/models/agent_session.py +7 -5
- claude_mpm/scripts/mcp_server.py +0 -0
- claude_mpm/scripts/start_activity_logging.py +0 -0
- claude_mpm/services/__init__.py +1 -1
- claude_mpm/services/agent_capabilities_service.py +1 -1
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/deployment/agent_deployment.py +2 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +9 -3
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +3 -1
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +1 -1
- claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
- claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
- claude_mpm/services/agents/deployment/agent_template_builder.py +1 -1
- claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +2 -3
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +5 -3
- claude_mpm/services/agents/loading/base_agent_manager.py +2 -2
- claude_mpm/services/agents/local_template_manager.py +6 -6
- claude_mpm/services/agents/management/agent_management_service.py +3 -3
- claude_mpm/services/agents/memory/content_manager.py +3 -3
- claude_mpm/services/agents/memory/memory_format_service.py +2 -2
- claude_mpm/services/agents/memory/template_generator.py +3 -3
- claude_mpm/services/agents/registry/modification_tracker.py +2 -2
- claude_mpm/services/async_session_logger.py +3 -3
- claude_mpm/services/claude_session_logger.py +4 -4
- claude_mpm/services/cli/agent_listing_service.py +3 -1
- claude_mpm/services/cli/agent_validation_service.py +2 -0
- claude_mpm/services/cli/memory_crud_service.py +11 -6
- claude_mpm/services/cli/memory_output_formatter.py +1 -1
- claude_mpm/services/cli/session_manager.py +15 -11
- claude_mpm/services/core/memory_manager.py +81 -23
- claude_mpm/services/core/path_resolver.py +1 -1
- claude_mpm/services/diagnostics/checks/installation_check.py +1 -1
- claude_mpm/services/event_aggregator.py +4 -2
- claude_mpm/services/event_bus/direct_relay.py +5 -3
- claude_mpm/services/event_bus/event_bus.py +3 -3
- claude_mpm/services/event_bus/relay.py +6 -4
- claude_mpm/services/events/consumers/dead_letter.py +5 -3
- claude_mpm/services/events/core.py +3 -3
- claude_mpm/services/events/producers/hook.py +6 -6
- claude_mpm/services/events/producers/system.py +8 -8
- claude_mpm/services/exceptions.py +5 -5
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
- claude_mpm/services/hook_installer_service.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +6 -4
- claude_mpm/services/infrastructure/daemon_manager.py +2 -2
- claude_mpm/services/infrastructure/logging.py +2 -2
- claude_mpm/services/mcp_config_manager.py +175 -30
- claude_mpm/services/mcp_gateway/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/auto_configure.py +3 -3
- claude_mpm/services/mcp_gateway/config/config_loader.py +1 -1
- claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
- claude_mpm/services/mcp_gateway/core/base.py +2 -2
- claude_mpm/services/mcp_gateway/main.py +21 -7
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +10 -8
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
- claude_mpm/services/mcp_gateway/server/stdio_server.py +5 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +7 -5
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +190 -137
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +5 -5
- claude_mpm/services/mcp_gateway/tools/hello_world.py +9 -9
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +16 -16
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +16 -16
- claude_mpm/services/memory/builder.py +7 -5
- claude_mpm/services/memory/indexed_memory.py +4 -4
- claude_mpm/services/memory/optimizer.py +6 -6
- claude_mpm/services/memory/router.py +3 -3
- claude_mpm/services/monitor/daemon.py +1 -1
- claude_mpm/services/monitor/daemon_manager.py +6 -6
- claude_mpm/services/monitor/event_emitter.py +2 -2
- claude_mpm/services/monitor/management/lifecycle.py +3 -1
- claude_mpm/services/monitor/server.py +4 -4
- claude_mpm/services/monitor_build_service.py +2 -2
- claude_mpm/services/port_manager.py +3 -1
- claude_mpm/services/response_tracker.py +2 -2
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/socketio/client_proxy.py +2 -2
- claude_mpm/services/socketio/dashboard_server.py +4 -3
- claude_mpm/services/socketio/event_normalizer.py +11 -7
- claude_mpm/services/socketio/handlers/base.py +2 -2
- claude_mpm/services/socketio/handlers/connection.py +10 -10
- claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
- claude_mpm/services/socketio/handlers/hook.py +16 -15
- claude_mpm/services/socketio/migration_utils.py +1 -1
- claude_mpm/services/socketio/monitor_client.py +5 -5
- claude_mpm/services/socketio/server/broadcaster.py +9 -7
- claude_mpm/services/socketio/server/connection_manager.py +2 -2
- claude_mpm/services/socketio/server/core.py +7 -5
- claude_mpm/services/socketio/server/eventbus_integration.py +18 -12
- claude_mpm/services/socketio/server/main.py +13 -13
- claude_mpm/services/socketio_client_manager.py +4 -4
- claude_mpm/services/system_instructions_service.py +2 -2
- claude_mpm/services/utility_service.py +5 -2
- claude_mpm/services/version_control/branch_strategy.py +2 -2
- claude_mpm/services/version_control/git_operations.py +22 -20
- claude_mpm/services/version_control/semantic_versioning.py +3 -3
- claude_mpm/services/version_control/version_parser.py +7 -5
- claude_mpm/services/visualization/mermaid_generator.py +3 -1
- claude_mpm/storage/state_storage.py +1 -1
- claude_mpm/tools/code_tree_analyzer.py +23 -18
- claude_mpm/tools/code_tree_builder.py +2 -2
- claude_mpm/tools/code_tree_events.py +10 -8
- claude_mpm/tools/socketio_debug.py +3 -3
- claude_mpm/utils/agent_dependency_loader.py +6 -2
- claude_mpm/utils/dependency_strategies.py +8 -3
- claude_mpm/utils/environment_context.py +1 -1
- claude_mpm/utils/error_handler.py +2 -2
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/log_cleanup.py +21 -7
- claude_mpm/validation/agent_validator.py +2 -2
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/METADATA +1 -1
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/RECORD +204 -191
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/WHEEL +0 -0
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/top_level.txt +0 -0
|
@@ -19,7 +19,7 @@ import threading
|
|
|
19
19
|
import time
|
|
20
20
|
from collections import deque
|
|
21
21
|
from dataclasses import asdict, dataclass
|
|
22
|
-
from datetime import datetime
|
|
22
|
+
from datetime import datetime, timezone
|
|
23
23
|
from typing import Any, Dict, List, Optional
|
|
24
24
|
|
|
25
25
|
try:
|
|
@@ -54,7 +54,7 @@ class CodeNodeEvent:
|
|
|
54
54
|
def to_dict(self) -> Dict[str, Any]:
|
|
55
55
|
"""Convert to dictionary for JSON serialization."""
|
|
56
56
|
data = asdict(self)
|
|
57
|
-
data["timestamp"] = datetime.
|
|
57
|
+
data["timestamp"] = datetime.now(timezone.utc).isoformat()
|
|
58
58
|
return data
|
|
59
59
|
|
|
60
60
|
|
|
@@ -157,7 +157,7 @@ class CodeTreeEventEmitter:
|
|
|
157
157
|
|
|
158
158
|
def start(self):
|
|
159
159
|
"""Start the event emitter and background tasks."""
|
|
160
|
-
self.stats["start_time"] = datetime.
|
|
160
|
+
self.stats["start_time"] = datetime.now(timezone.utc)
|
|
161
161
|
self._stop_event.clear()
|
|
162
162
|
|
|
163
163
|
# Start background emit task
|
|
@@ -168,7 +168,7 @@ class CodeTreeEventEmitter:
|
|
|
168
168
|
self.emit(
|
|
169
169
|
self.EVENT_ANALYSIS_START,
|
|
170
170
|
{
|
|
171
|
-
"timestamp": datetime.
|
|
171
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
172
172
|
"batch_size": self.batch_size,
|
|
173
173
|
"batch_timeout": self.batch_timeout,
|
|
174
174
|
},
|
|
@@ -183,9 +183,11 @@ class CodeTreeEventEmitter:
|
|
|
183
183
|
self.emit(
|
|
184
184
|
self.EVENT_ANALYSIS_COMPLETE,
|
|
185
185
|
{
|
|
186
|
-
"timestamp": datetime.
|
|
186
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
187
187
|
"duration": (
|
|
188
|
-
(
|
|
188
|
+
(
|
|
189
|
+
datetime.now(timezone.utc) - self.stats["start_time"]
|
|
190
|
+
).total_seconds()
|
|
189
191
|
if self.stats["start_time"]
|
|
190
192
|
else 0
|
|
191
193
|
),
|
|
@@ -213,7 +215,7 @@ class CodeTreeEventEmitter:
|
|
|
213
215
|
event = {
|
|
214
216
|
"type": event_type,
|
|
215
217
|
"data": data,
|
|
216
|
-
"timestamp": datetime.
|
|
218
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
217
219
|
}
|
|
218
220
|
|
|
219
221
|
if batch:
|
|
@@ -393,7 +395,7 @@ class CodeTreeEventEmitter:
|
|
|
393
395
|
"events": list(self.event_buffer),
|
|
394
396
|
"count": len(self.event_buffer),
|
|
395
397
|
},
|
|
396
|
-
"timestamp": datetime.
|
|
398
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
397
399
|
}
|
|
398
400
|
|
|
399
401
|
self._emit_event(batch_event)
|
|
@@ -13,7 +13,7 @@ import signal
|
|
|
13
13
|
import sys
|
|
14
14
|
import time
|
|
15
15
|
from dataclasses import dataclass, field
|
|
16
|
-
from datetime import datetime
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
17
|
from enum import Enum
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from typing import Any, Dict, List, Optional, Set
|
|
@@ -232,7 +232,7 @@ class SocketIODebugger:
|
|
|
232
232
|
|
|
233
233
|
def _display_event(self, data: Dict[str, Any]):
|
|
234
234
|
"""Display an event based on current mode."""
|
|
235
|
-
timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
|
235
|
+
timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f")[:-3]
|
|
236
236
|
event_type = data.get("type", "unknown")
|
|
237
237
|
event_data = data.get("data", {})
|
|
238
238
|
|
|
@@ -449,7 +449,7 @@ class SocketIODebugger:
|
|
|
449
449
|
if self.quiet and level not in ["error", "critical"]:
|
|
450
450
|
return
|
|
451
451
|
|
|
452
|
-
timestamp = datetime.now().strftime("%H:%M:%S")
|
|
452
|
+
timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S")
|
|
453
453
|
|
|
454
454
|
if RICH_AVAILABLE:
|
|
455
455
|
styles = {
|
|
@@ -107,7 +107,9 @@ class AgentDependencyLoader:
|
|
|
107
107
|
logger.info(f"Loaded dependencies for {len(agent_dependencies)} agents")
|
|
108
108
|
return agent_dependencies
|
|
109
109
|
|
|
110
|
-
def check_python_dependency(
|
|
110
|
+
def check_python_dependency(
|
|
111
|
+
self, package_spec: str
|
|
112
|
+
) -> Tuple[bool, Optional[str]]:
|
|
111
113
|
"""
|
|
112
114
|
Check if a Python package dependency is satisfied.
|
|
113
115
|
|
|
@@ -442,7 +444,9 @@ class AgentDependencyLoader:
|
|
|
442
444
|
|
|
443
445
|
return compatible, incompatible
|
|
444
446
|
|
|
445
|
-
def install_missing_dependencies(
|
|
447
|
+
def install_missing_dependencies(
|
|
448
|
+
self, dependencies: List[str]
|
|
449
|
+
) -> Tuple[bool, str]:
|
|
446
450
|
"""
|
|
447
451
|
Install missing Python dependencies using robust retry logic.
|
|
448
452
|
|
|
@@ -10,7 +10,7 @@ based on the execution context and user preferences.
|
|
|
10
10
|
import json
|
|
11
11
|
import os
|
|
12
12
|
import sys
|
|
13
|
-
from datetime import datetime, timedelta
|
|
13
|
+
from datetime import datetime, timedelta, timezone
|
|
14
14
|
from enum import Enum
|
|
15
15
|
from typing import Any, Dict, Optional, Tuple
|
|
16
16
|
|
|
@@ -160,7 +160,9 @@ class DependencyStrategy:
|
|
|
160
160
|
last_check = datetime.fromisoformat(cache.get("timestamp", ""))
|
|
161
161
|
|
|
162
162
|
# Check if cache is still valid
|
|
163
|
-
if datetime.now() - last_check < timedelta(
|
|
163
|
+
if datetime.now(timezone.utc) - last_check < timedelta(
|
|
164
|
+
seconds=cache_ttl
|
|
165
|
+
):
|
|
164
166
|
logger.debug(f"Using cached dependency check from {last_check}")
|
|
165
167
|
return False
|
|
166
168
|
|
|
@@ -179,7 +181,10 @@ class DependencyStrategy:
|
|
|
179
181
|
try:
|
|
180
182
|
self.cache_path.parent.mkdir(parents=True, exist_ok=True)
|
|
181
183
|
|
|
182
|
-
cache_data = {
|
|
184
|
+
cache_data = {
|
|
185
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
186
|
+
"results": results,
|
|
187
|
+
}
|
|
183
188
|
|
|
184
189
|
with open(self.cache_path, "w") as f:
|
|
185
190
|
json.dump(cache_data, f, indent=2)
|
|
@@ -6,7 +6,7 @@ Inspired by awesome-claude-code's comprehensive error handling approach.
|
|
|
6
6
|
|
|
7
7
|
import logging
|
|
8
8
|
import sys
|
|
9
|
-
from datetime import datetime
|
|
9
|
+
from datetime import datetime, timezone
|
|
10
10
|
from functools import wraps
|
|
11
11
|
from typing import Any, Callable, Dict, List, Optional, Type
|
|
12
12
|
|
|
@@ -26,7 +26,7 @@ class MPMError(Exception):
|
|
|
26
26
|
super().__init__(message)
|
|
27
27
|
self.details = details or {}
|
|
28
28
|
self.suggestions = suggestions or []
|
|
29
|
-
self.timestamp = datetime.now()
|
|
29
|
+
self.timestamp = datetime.now(timezone.utc)
|
|
30
30
|
|
|
31
31
|
def get_user_friendly_message(self) -> str:
|
|
32
32
|
"""Get a user-friendly error message."""
|
claude_mpm/utils/file_utils.py
CHANGED
claude_mpm/utils/log_cleanup.py
CHANGED
|
@@ -107,7 +107,9 @@ class LogCleanupUtility:
|
|
|
107
107
|
|
|
108
108
|
try:
|
|
109
109
|
# Check directory modification time
|
|
110
|
-
mtime = datetime.fromtimestamp(
|
|
110
|
+
mtime = datetime.fromtimestamp(
|
|
111
|
+
session_dir.stat().st_mtime, tz=timezone.utc
|
|
112
|
+
)
|
|
111
113
|
|
|
112
114
|
if mtime < cutoff_time:
|
|
113
115
|
# Calculate directory size
|
|
@@ -169,7 +171,9 @@ class LogCleanupUtility:
|
|
|
169
171
|
for ext in LogCleanupConfig.ARCHIVE_EXTENSIONS:
|
|
170
172
|
for archive_file in self.base_log_dir.rglob(f"*{ext}"):
|
|
171
173
|
try:
|
|
172
|
-
mtime = datetime.fromtimestamp(
|
|
174
|
+
mtime = datetime.fromtimestamp(
|
|
175
|
+
archive_file.stat().st_mtime, tz=timezone.utc
|
|
176
|
+
)
|
|
173
177
|
|
|
174
178
|
if mtime < cutoff_time:
|
|
175
179
|
file_size = archive_file.stat().st_size / (1024 * 1024) # MB
|
|
@@ -238,7 +242,9 @@ class LogCleanupUtility:
|
|
|
238
242
|
|
|
239
243
|
for log_file in log_dir.glob(pattern):
|
|
240
244
|
try:
|
|
241
|
-
mtime = datetime.fromtimestamp(
|
|
245
|
+
mtime = datetime.fromtimestamp(
|
|
246
|
+
log_file.stat().st_mtime, tz=timezone.utc
|
|
247
|
+
)
|
|
242
248
|
|
|
243
249
|
if mtime < cutoff_time:
|
|
244
250
|
file_size = log_file.stat().st_size / (1024 * 1024) # MB
|
|
@@ -283,7 +289,7 @@ class LogCleanupUtility:
|
|
|
283
289
|
removed_count = 0
|
|
284
290
|
|
|
285
291
|
# Walk bottom-up to remove empty parent directories
|
|
286
|
-
for root,
|
|
292
|
+
for root, _dirs, _files in os.walk(self.base_log_dir, topdown=False):
|
|
287
293
|
root_path = Path(root)
|
|
288
294
|
|
|
289
295
|
# Skip the base log directory itself
|
|
@@ -331,7 +337,9 @@ class LogCleanupUtility:
|
|
|
331
337
|
continue
|
|
332
338
|
|
|
333
339
|
try:
|
|
334
|
-
mtime = datetime.fromtimestamp(
|
|
340
|
+
mtime = datetime.fromtimestamp(
|
|
341
|
+
log_file.stat().st_mtime, tz=timezone.utc
|
|
342
|
+
)
|
|
335
343
|
|
|
336
344
|
if mtime < cutoff_time:
|
|
337
345
|
original_size = log_file.stat().st_size / (1024 * 1024) # MB
|
|
@@ -408,7 +416,10 @@ class LogCleanupUtility:
|
|
|
408
416
|
stats["oldest_session"] = {
|
|
409
417
|
"name": oldest.name,
|
|
410
418
|
"age_days": (
|
|
411
|
-
datetime.now(timezone.utc)
|
|
419
|
+
datetime.now(timezone.utc)
|
|
420
|
+
- datetime.fromtimestamp(
|
|
421
|
+
oldest.stat().st_mtime, tz=timezone.utc
|
|
422
|
+
)
|
|
412
423
|
).days,
|
|
413
424
|
}
|
|
414
425
|
|
|
@@ -429,7 +440,10 @@ class LogCleanupUtility:
|
|
|
429
440
|
"name": oldest_log.name,
|
|
430
441
|
"path": str(oldest_log.relative_to(self.base_log_dir)),
|
|
431
442
|
"age_days": (
|
|
432
|
-
datetime.now(timezone.utc)
|
|
443
|
+
datetime.now(timezone.utc)
|
|
444
|
+
- datetime.fromtimestamp(
|
|
445
|
+
oldest_log.stat().st_mtime, tz=timezone.utc
|
|
446
|
+
)
|
|
433
447
|
).days,
|
|
434
448
|
}
|
|
435
449
|
|
|
@@ -22,7 +22,7 @@ Security Considerations:
|
|
|
22
22
|
import json
|
|
23
23
|
import logging
|
|
24
24
|
from dataclasses import dataclass, field
|
|
25
|
-
from datetime import datetime
|
|
25
|
+
from datetime import datetime, timezone
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
from typing import Any, Dict, List, Optional, Tuple
|
|
28
28
|
|
|
@@ -182,7 +182,7 @@ class AgentValidator:
|
|
|
182
182
|
|
|
183
183
|
# Add metadata
|
|
184
184
|
result.metadata = {
|
|
185
|
-
"validated_at": datetime.
|
|
185
|
+
"validated_at": datetime.now(timezone.utc).isoformat(),
|
|
186
186
|
"schema_version": self.schema.get("version", "1.1.0"),
|
|
187
187
|
"agent_id": agent_data.get("id", "unknown"),
|
|
188
188
|
}
|