claude-mpm 4.3.11__py3-none-any.whl → 4.3.13__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 +390 -28
- claude_mpm/agents/templates/data_engineer.json +39 -14
- claude_mpm/agents/templates/research.json +20 -8
- claude_mpm/agents/templates/web_qa.json +25 -10
- claude_mpm/cli/__init__.py +1 -0
- 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 +12 -1
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +93 -24
- claude_mpm/cli/commands/mcp_setup_external.py +870 -0
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init_handler.py +1 -1
- claude_mpm/cli/commands/run.py +114 -0
- claude_mpm/cli/commands/search.py +292 -0
- claude_mpm/cli/interactive/agent_wizard.py +2 -2
- claude_mpm/cli/parsers/base_parser.py +13 -0
- claude_mpm/cli/parsers/mcp_parser.py +15 -0
- claude_mpm/cli/parsers/run_parser.py +5 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/startup_logging.py +3 -5
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/constants.py +1 -0
- claude_mpm/core/agent_registry.py +12 -8
- claude_mpm/core/agent_session_manager.py +8 -8
- claude_mpm/core/api_validator.py +4 -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 +1 -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/logging_config.py +4 -2
- claude_mpm/core/oneshot_session.py +1 -1
- 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 +9 -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/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/connection_manager.py +5 -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 +5 -5
- 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 +29 -13
- claude_mpm/services/agents/deployment/agent_discovery_service.py +22 -6
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +7 -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/multi_source_deployment_service.py +6 -4
- 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/__init__.py +1 -1
- 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_cleanup_service.py +5 -0
- claude_mpm/services/cli/agent_listing_service.py +1 -1
- claude_mpm/services/cli/agent_validation_service.py +1 -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/cli/unified_dashboard_manager.py +1 -1
- claude_mpm/services/core/memory_manager.py +81 -23
- claude_mpm/services/core/path_resolver.py +2 -2
- 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 +439 -0
- 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 +18 -1
- claude_mpm/services/mcp_gateway/core/base.py +2 -2
- claude_mpm/services/mcp_gateway/main.py +52 -0
- 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 +4 -3
- 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 +443 -0
- 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 +17 -17
- 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/handlers/file.py +1 -1
- claude_mpm/services/monitor/management/lifecycle.py +1 -1
- claude_mpm/services/monitor/server.py +4 -4
- claude_mpm/services/monitor_build_service.py +2 -2
- claude_mpm/services/port_manager.py +2 -2
- 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 +12 -8
- 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/file.py +1 -1
- claude_mpm/services/socketio/handlers/git.py +1 -1
- 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 -11
- 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/ticket_services/validation_service.py +1 -1
- 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 +1 -1
- claude_mpm/storage/state_storage.py +1 -1
- claude_mpm/tools/code_tree_analyzer.py +19 -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 +2 -2
- claude_mpm/utils/dependency_strategies.py +8 -3
- claude_mpm/utils/environment_context.py +2 -2
- claude_mpm/utils/error_handler.py +2 -2
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/imports.py +1 -1
- claude_mpm/utils/log_cleanup.py +21 -7
- claude_mpm/validation/agent_validator.py +2 -2
- {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/METADATA +4 -1
- {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/RECORD +207 -200
- {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/WHEEL +0 -0
- {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/top_level.txt +0 -0
|
@@ -20,7 +20,7 @@ import subprocess
|
|
|
20
20
|
import sys
|
|
21
21
|
import threading
|
|
22
22
|
from dataclasses import asdict, dataclass
|
|
23
|
-
from datetime import datetime
|
|
23
|
+
from datetime import datetime, timezone
|
|
24
24
|
from pathlib import Path
|
|
25
25
|
from queue import Queue
|
|
26
26
|
from typing import Any, Dict, List, Optional
|
|
@@ -41,7 +41,7 @@ class AnalysisRequest:
|
|
|
41
41
|
|
|
42
42
|
def __post_init__(self):
|
|
43
43
|
if self.timestamp is None:
|
|
44
|
-
self.timestamp = datetime.
|
|
44
|
+
self.timestamp = datetime.now(timezone.utc)
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class CodeAnalysisRunner:
|
|
@@ -433,7 +433,7 @@ class CodeAnalysisRunner:
|
|
|
433
433
|
if self.server:
|
|
434
434
|
# Add timestamp if not present
|
|
435
435
|
if "timestamp" not in data:
|
|
436
|
-
data["timestamp"] = datetime.
|
|
436
|
+
data["timestamp"] = datetime.now(timezone.utc).isoformat()
|
|
437
437
|
|
|
438
438
|
# Broadcast to all clients
|
|
439
439
|
self.server.broadcast_event(event_type, data)
|
|
@@ -450,6 +450,6 @@ class CodeAnalysisRunner:
|
|
|
450
450
|
{
|
|
451
451
|
"request_id": request_id,
|
|
452
452
|
"message": message,
|
|
453
|
-
"timestamp": datetime.
|
|
453
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
454
454
|
},
|
|
455
455
|
)
|
|
@@ -129,7 +129,7 @@ def has_code_files(directory_path, max_depth=5, current_depth=0):
|
|
|
129
129
|
return False
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-
def should_show_item(item_name, item_path, is_directory):
|
|
132
|
+
def should_show_item(item_name, item_path, is_directory): # noqa: PLR0911
|
|
133
133
|
"""Determine if an item should be shown based on filtering rules"""
|
|
134
134
|
# Always hide system files
|
|
135
135
|
if item_name in {".DS_Store", "Thumbs.db", "desktop.ini"}:
|
|
@@ -7,7 +7,7 @@ Inspired by awesome-claude-code's template generation approach.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import re
|
|
10
|
-
from datetime import datetime
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
11
|
from typing import Any, Dict, Optional
|
|
12
12
|
|
|
13
13
|
import yaml
|
|
@@ -36,7 +36,9 @@ class AgentProfileGenerator:
|
|
|
36
36
|
"""Generate an agent profile from configuration."""
|
|
37
37
|
# Set default values
|
|
38
38
|
config.setdefault("VERSION", "1.0.0")
|
|
39
|
-
config.setdefault(
|
|
39
|
+
config.setdefault(
|
|
40
|
+
"CREATED_DATE", datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
|
41
|
+
)
|
|
40
42
|
config.setdefault("AUTHOR", "claude-mpm")
|
|
41
43
|
|
|
42
44
|
# Convert template to string
|
claude_mpm/hooks/base_hook.py
CHANGED
|
@@ -4,7 +4,7 @@ import asyncio
|
|
|
4
4
|
import logging
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
-
from datetime import datetime
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
8
|
from enum import Enum
|
|
9
9
|
from typing import Any, Dict, Optional
|
|
10
10
|
|
|
@@ -35,7 +35,7 @@ class HookContext:
|
|
|
35
35
|
def __post_init__(self):
|
|
36
36
|
"""Ensure timestamp is set."""
|
|
37
37
|
if not hasattr(self, "timestamp") or self.timestamp is None:
|
|
38
|
-
self.timestamp = datetime.now()
|
|
38
|
+
self.timestamp = datetime.now(timezone.utc)
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
@dataclass
|
|
@@ -131,7 +131,7 @@ class SocketIOConnectionPool:
|
|
|
131
131
|
"source": "connection_pool",
|
|
132
132
|
},
|
|
133
133
|
)
|
|
134
|
-
except:
|
|
134
|
+
except Exception:
|
|
135
135
|
pass # Ignore ping errors
|
|
136
136
|
return client
|
|
137
137
|
except Exception:
|
|
@@ -168,10 +168,10 @@ class SocketIOConnectionPool:
|
|
|
168
168
|
},
|
|
169
169
|
)
|
|
170
170
|
return True
|
|
171
|
-
except:
|
|
171
|
+
except Exception:
|
|
172
172
|
# If ping fails, connection might be dead
|
|
173
173
|
return client.connected # Fall back to basic check
|
|
174
|
-
except:
|
|
174
|
+
except Exception:
|
|
175
175
|
return False
|
|
176
176
|
|
|
177
177
|
def _close_connection(self, client: Any) -> None:
|
|
@@ -179,7 +179,7 @@ class SocketIOConnectionPool:
|
|
|
179
179
|
try:
|
|
180
180
|
if client:
|
|
181
181
|
client.disconnect()
|
|
182
|
-
except:
|
|
182
|
+
except Exception:
|
|
183
183
|
pass
|
|
184
184
|
|
|
185
185
|
def _cleanup_dead_connections(self) -> None:
|
|
@@ -9,7 +9,7 @@ import os
|
|
|
9
9
|
import re
|
|
10
10
|
import subprocess
|
|
11
11
|
import sys
|
|
12
|
-
from datetime import datetime
|
|
12
|
+
from datetime import datetime, timezone
|
|
13
13
|
from typing import Optional
|
|
14
14
|
|
|
15
15
|
# Import tool analysis with fallback for direct execution
|
|
@@ -77,7 +77,7 @@ class EventHandlers:
|
|
|
77
77
|
"session_id": event.get("session_id", ""),
|
|
78
78
|
"working_directory": working_dir,
|
|
79
79
|
"git_branch": git_branch,
|
|
80
|
-
"timestamp": datetime.now().isoformat(),
|
|
80
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
81
81
|
"is_command": prompt.startswith("/"),
|
|
82
82
|
"contains_code": "```" in prompt
|
|
83
83
|
or "python" in prompt.lower()
|
|
@@ -101,7 +101,7 @@ class EventHandlers:
|
|
|
101
101
|
if session_id:
|
|
102
102
|
self.hook_handler.pending_prompts[session_id] = {
|
|
103
103
|
"prompt": prompt,
|
|
104
|
-
"timestamp": datetime.now().isoformat(),
|
|
104
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
105
105
|
"working_directory": working_dir,
|
|
106
106
|
}
|
|
107
107
|
if DEBUG:
|
|
@@ -150,7 +150,7 @@ class EventHandlers:
|
|
|
150
150
|
"session_id": event.get("session_id", ""),
|
|
151
151
|
"working_directory": working_dir,
|
|
152
152
|
"git_branch": git_branch,
|
|
153
|
-
"timestamp": datetime.now().isoformat(),
|
|
153
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
154
154
|
"parameter_count": len(tool_input) if isinstance(tool_input, dict) else 0,
|
|
155
155
|
"is_file_operation": tool_name
|
|
156
156
|
in ["Write", "Edit", "MultiEdit", "Read", "LS", "Glob"],
|
|
@@ -249,7 +249,7 @@ class EventHandlers:
|
|
|
249
249
|
"session_id": session_id,
|
|
250
250
|
"prompt": tool_input.get("prompt", ""),
|
|
251
251
|
"description": tool_input.get("description", ""),
|
|
252
|
-
"timestamp": datetime.now().isoformat(),
|
|
252
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
253
253
|
"hook_event_name": "SubagentStart", # For dashboard compatibility
|
|
254
254
|
}
|
|
255
255
|
self.hook_handler._emit_socketio_event(
|
|
@@ -277,7 +277,7 @@ class EventHandlers:
|
|
|
277
277
|
"session_id": session_id,
|
|
278
278
|
"delegation_context": {
|
|
279
279
|
"description": tool_input.get("description", ""),
|
|
280
|
-
"timestamp": datetime.now().isoformat(),
|
|
280
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
281
281
|
},
|
|
282
282
|
}
|
|
283
283
|
|
|
@@ -312,7 +312,7 @@ class EventHandlers:
|
|
|
312
312
|
working_dir = os.getcwd()
|
|
313
313
|
|
|
314
314
|
# Check cache first (cache for 30 seconds)
|
|
315
|
-
current_time = datetime.now().timestamp()
|
|
315
|
+
current_time = datetime.now(timezone.utc).timestamp()
|
|
316
316
|
cache_key = working_dir
|
|
317
317
|
|
|
318
318
|
if (
|
|
@@ -397,7 +397,7 @@ class EventHandlers:
|
|
|
397
397
|
"session_id": event.get("session_id", ""),
|
|
398
398
|
"working_directory": working_dir,
|
|
399
399
|
"git_branch": git_branch,
|
|
400
|
-
"timestamp": datetime.now().isoformat(),
|
|
400
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
401
401
|
"has_output": bool(result_data.get("output")),
|
|
402
402
|
"has_error": bool(result_data.get("error")),
|
|
403
403
|
"output_size": (
|
|
@@ -448,7 +448,7 @@ class EventHandlers:
|
|
|
448
448
|
"session_id": event.get("session_id", ""),
|
|
449
449
|
"working_directory": working_dir,
|
|
450
450
|
"git_branch": git_branch,
|
|
451
|
-
"timestamp": datetime.now().isoformat(),
|
|
451
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
452
452
|
"is_user_input_request": "input" in message.lower()
|
|
453
453
|
or "waiting" in message.lower(),
|
|
454
454
|
"is_error_notification": "error" in message.lower()
|
|
@@ -492,7 +492,7 @@ class EventHandlers:
|
|
|
492
492
|
"""Extract metadata from stop event."""
|
|
493
493
|
working_dir = event.get("cwd", "")
|
|
494
494
|
return {
|
|
495
|
-
"timestamp": datetime.now().isoformat(),
|
|
495
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
496
496
|
"working_directory": working_dir,
|
|
497
497
|
"git_branch": (
|
|
498
498
|
self._get_git_branch(working_dir) if working_dir else "Unknown"
|
|
@@ -639,7 +639,7 @@ class EventHandlers:
|
|
|
639
639
|
"has_error": reason in ["error", "timeout", "failed", "blocked"],
|
|
640
640
|
"working_directory": working_dir,
|
|
641
641
|
"git_branch": git_branch,
|
|
642
|
-
"timestamp": datetime.now().isoformat(),
|
|
642
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
643
643
|
"event_type": "subagent_stop",
|
|
644
644
|
"reason": reason,
|
|
645
645
|
"original_request_timestamp": request_info.get("timestamp"),
|
|
@@ -715,7 +715,7 @@ class EventHandlers:
|
|
|
715
715
|
"session_id": session_id,
|
|
716
716
|
"working_directory": working_dir,
|
|
717
717
|
"git_branch": git_branch,
|
|
718
|
-
"timestamp": datetime.now().isoformat(),
|
|
718
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
719
719
|
"contains_code": "```" in response_text,
|
|
720
720
|
"contains_json": "```json" in response_text,
|
|
721
721
|
"hook_event_name": "AssistantResponse", # Explicitly set for dashboard
|
|
@@ -25,7 +25,7 @@ import signal
|
|
|
25
25
|
import subprocess
|
|
26
26
|
import sys
|
|
27
27
|
import threading
|
|
28
|
-
from datetime import datetime
|
|
28
|
+
from datetime import datetime, timezone
|
|
29
29
|
from typing import Optional, Tuple
|
|
30
30
|
|
|
31
31
|
# Import extracted modules with fallback for direct execution
|
|
@@ -284,7 +284,7 @@ class ClaudeHookHandler:
|
|
|
284
284
|
if self.duplicate_detector.is_duplicate(event):
|
|
285
285
|
if DEBUG:
|
|
286
286
|
print(
|
|
287
|
-
f"[{datetime.now().isoformat()}] Skipping duplicate event: {event.get('hook_event_name', 'unknown')} (PID: {os.getpid()})",
|
|
287
|
+
f"[{datetime.now(timezone.utc).isoformat()}] Skipping duplicate event: {event.get('hook_event_name', 'unknown')} (PID: {os.getpid()})",
|
|
288
288
|
file=sys.stderr,
|
|
289
289
|
)
|
|
290
290
|
# Still need to output continue for this invocation
|
|
@@ -297,7 +297,7 @@ class ClaudeHookHandler:
|
|
|
297
297
|
if DEBUG:
|
|
298
298
|
hook_type = event.get("hook_event_name", "unknown")
|
|
299
299
|
print(
|
|
300
|
-
f"\n[{datetime.now().isoformat()}] Processing hook event: {hook_type} (PID: {os.getpid()})",
|
|
300
|
+
f"\n[{datetime.now(timezone.utc).isoformat()}] Processing hook event: {hook_type} (PID: {os.getpid()})",
|
|
301
301
|
file=sys.stderr,
|
|
302
302
|
)
|
|
303
303
|
|
|
@@ -461,7 +461,7 @@ class ClaudeHookHandler:
|
|
|
461
461
|
if hasattr(self, "connection_manager") and self.connection_manager:
|
|
462
462
|
try:
|
|
463
463
|
self.connection_manager.cleanup()
|
|
464
|
-
except:
|
|
464
|
+
except Exception:
|
|
465
465
|
pass # Ignore cleanup errors during destruction
|
|
466
466
|
|
|
467
467
|
|
|
@@ -22,7 +22,7 @@ import sys
|
|
|
22
22
|
import threading
|
|
23
23
|
import time
|
|
24
24
|
from collections import deque
|
|
25
|
-
from datetime import datetime
|
|
25
|
+
from datetime import datetime, timezone
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
from typing import Optional
|
|
28
28
|
|
|
@@ -55,7 +55,7 @@ except ImportError:
|
|
|
55
55
|
"type": event_data.get("type", "unknown"),
|
|
56
56
|
"subtype": event_data.get("subtype", "generic"),
|
|
57
57
|
"timestamp": event_data.get(
|
|
58
|
-
"timestamp", datetime.now().isoformat()
|
|
58
|
+
"timestamp", datetime.now(timezone.utc).isoformat()
|
|
59
59
|
),
|
|
60
60
|
"data": event_data.get("data", event_data),
|
|
61
61
|
"source": source,
|
|
@@ -174,7 +174,7 @@ class HookHandler:
|
|
|
174
174
|
raw_event = {
|
|
175
175
|
"type": "hook",
|
|
176
176
|
"subtype": event_type,
|
|
177
|
-
"timestamp": datetime.now().isoformat(),
|
|
177
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
178
178
|
"data": data,
|
|
179
179
|
"source": "claude_hooks",
|
|
180
180
|
"session_id": data.get("sessionId", self.current_session_id),
|
|
@@ -21,7 +21,7 @@ import sys
|
|
|
21
21
|
import threading
|
|
22
22
|
import time
|
|
23
23
|
from collections import deque
|
|
24
|
-
from datetime import datetime
|
|
24
|
+
from datetime import datetime, timezone
|
|
25
25
|
from typing import Optional
|
|
26
26
|
|
|
27
27
|
# Import extracted modules with fallback for direct execution
|
|
@@ -71,7 +71,7 @@ except ImportError:
|
|
|
71
71
|
"type": event_data.get("type", "unknown"),
|
|
72
72
|
"subtype": event_data.get("subtype", "generic"),
|
|
73
73
|
"timestamp": event_data.get(
|
|
74
|
-
"timestamp", datetime.now().isoformat()
|
|
74
|
+
"timestamp", datetime.now(timezone.utc).isoformat()
|
|
75
75
|
),
|
|
76
76
|
"data": event_data.get("data", event_data),
|
|
77
77
|
}
|
|
@@ -216,7 +216,7 @@ class ClaudeHookHandler:
|
|
|
216
216
|
|
|
217
217
|
if session_id and agent_type and agent_type != "unknown":
|
|
218
218
|
self.active_delegations[session_id] = agent_type
|
|
219
|
-
key = f"{session_id}:{datetime.now().timestamp()}"
|
|
219
|
+
key = f"{session_id}:{datetime.now(timezone.utc).timestamp()}"
|
|
220
220
|
self.delegation_history.append((key, agent_type))
|
|
221
221
|
|
|
222
222
|
# Store request data for response tracking correlation
|
|
@@ -224,7 +224,7 @@ class ClaudeHookHandler:
|
|
|
224
224
|
self.delegation_requests[session_id] = {
|
|
225
225
|
"agent_type": agent_type,
|
|
226
226
|
"request": request_data,
|
|
227
|
-
"timestamp": datetime.now().isoformat(),
|
|
227
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
228
228
|
}
|
|
229
229
|
if DEBUG:
|
|
230
230
|
print(
|
|
@@ -237,7 +237,7 @@ class ClaudeHookHandler:
|
|
|
237
237
|
)
|
|
238
238
|
|
|
239
239
|
# Clean up old delegations (older than 5 minutes)
|
|
240
|
-
cutoff_time = datetime.now().timestamp() - 300
|
|
240
|
+
cutoff_time = datetime.now(timezone.utc).timestamp() - 300
|
|
241
241
|
keys_to_remove = []
|
|
242
242
|
for sid in list(self.active_delegations.keys()):
|
|
243
243
|
# Check if this is an old entry by looking in history
|
|
@@ -259,7 +259,7 @@ class ClaudeHookHandler:
|
|
|
259
259
|
|
|
260
260
|
def _cleanup_old_entries(self):
|
|
261
261
|
"""Clean up old entries to prevent memory growth."""
|
|
262
|
-
datetime.now().timestamp() - self.MAX_CACHE_AGE_SECONDS
|
|
262
|
+
datetime.now(timezone.utc).timestamp() - self.MAX_CACHE_AGE_SECONDS
|
|
263
263
|
|
|
264
264
|
# Clean up delegation tracking dictionaries
|
|
265
265
|
for storage in [self.active_delegations, self.delegation_requests]:
|
|
@@ -281,7 +281,8 @@ class ClaudeHookHandler:
|
|
|
281
281
|
expired_keys = [
|
|
282
282
|
key
|
|
283
283
|
for key, cache_time in self._git_branch_cache_time.items()
|
|
284
|
-
if datetime.now().timestamp() - cache_time
|
|
284
|
+
if datetime.now(timezone.utc).timestamp() - cache_time
|
|
285
|
+
> self.MAX_CACHE_AGE_SECONDS
|
|
285
286
|
]
|
|
286
287
|
for key in expired_keys:
|
|
287
288
|
self._git_branch_cache.pop(key, None)
|
|
@@ -315,7 +316,7 @@ class ClaudeHookHandler:
|
|
|
315
316
|
working_dir = os.getcwd()
|
|
316
317
|
|
|
317
318
|
# Check cache first (cache for 30 seconds)
|
|
318
|
-
current_time = datetime.now().timestamp()
|
|
319
|
+
current_time = datetime.now(timezone.utc).timestamp()
|
|
319
320
|
cache_key = working_dir
|
|
320
321
|
|
|
321
322
|
if (
|
|
@@ -413,7 +414,7 @@ class ClaudeHookHandler:
|
|
|
413
414
|
if recent_key == event_key and (current_time - recent_time) < 0.1:
|
|
414
415
|
if DEBUG:
|
|
415
416
|
print(
|
|
416
|
-
f"[{datetime.now().isoformat()}] Skipping duplicate event: {event.get('hook_event_name', 'unknown')} (PID: {os.getpid()})",
|
|
417
|
+
f"[{datetime.now(timezone.utc).isoformat()}] Skipping duplicate event: {event.get('hook_event_name', 'unknown')} (PID: {os.getpid()})",
|
|
417
418
|
file=sys.stderr,
|
|
418
419
|
)
|
|
419
420
|
# Still need to output continue for this invocation
|
|
@@ -429,7 +430,7 @@ class ClaudeHookHandler:
|
|
|
429
430
|
if DEBUG:
|
|
430
431
|
hook_type = event.get("hook_event_name", "unknown")
|
|
431
432
|
print(
|
|
432
|
-
f"\n[{datetime.now().isoformat()}] Processing hook event: {hook_type} (PID: {os.getpid()})",
|
|
433
|
+
f"\n[{datetime.now(timezone.utc).isoformat()}] Processing hook event: {hook_type} (PID: {os.getpid()})",
|
|
433
434
|
file=sys.stderr,
|
|
434
435
|
)
|
|
435
436
|
|
|
@@ -582,7 +583,7 @@ class ClaudeHookHandler:
|
|
|
582
583
|
raw_event = {
|
|
583
584
|
"type": "hook",
|
|
584
585
|
"subtype": event, # e.g., "user_prompt", "pre_tool", "subagent_stop"
|
|
585
|
-
"timestamp": datetime.now().isoformat(),
|
|
586
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
586
587
|
"data": data,
|
|
587
588
|
"source": "claude_hooks", # Identify the source
|
|
588
589
|
"session_id": data.get("sessionId"), # Include session if available
|
|
@@ -857,7 +858,7 @@ class ClaudeHookHandler:
|
|
|
857
858
|
"duration_ms": event.get("duration_ms"),
|
|
858
859
|
"working_directory": working_dir,
|
|
859
860
|
"git_branch": git_branch,
|
|
860
|
-
"timestamp": datetime.now().isoformat(),
|
|
861
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
861
862
|
"event_type": "subagent_stop",
|
|
862
863
|
"reason": reason,
|
|
863
864
|
"original_request_timestamp": request_info.get("timestamp"),
|
|
@@ -922,7 +923,7 @@ class ClaudeHookHandler:
|
|
|
922
923
|
"session_id": session_id,
|
|
923
924
|
"working_directory": working_dir,
|
|
924
925
|
"git_branch": git_branch,
|
|
925
|
-
"timestamp": datetime.now().isoformat(),
|
|
926
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
926
927
|
"is_successful_completion": reason in ["completed", "finished", "done"],
|
|
927
928
|
"is_error_termination": reason in ["error", "timeout", "failed", "blocked"],
|
|
928
929
|
"is_delegation_related": agent_type
|
|
@@ -971,7 +972,7 @@ class ClaudeHookHandler:
|
|
|
971
972
|
if hasattr(self, "connection_pool") and self.connection_pool:
|
|
972
973
|
try:
|
|
973
974
|
self.connection_pool.cleanup()
|
|
974
|
-
except:
|
|
975
|
+
except Exception:
|
|
975
976
|
pass # Ignore cleanup errors during destruction
|
|
976
977
|
|
|
977
978
|
|
|
@@ -20,7 +20,7 @@ import select
|
|
|
20
20
|
import signal
|
|
21
21
|
import sys
|
|
22
22
|
import threading
|
|
23
|
-
from datetime import datetime
|
|
23
|
+
from datetime import datetime, timezone
|
|
24
24
|
|
|
25
25
|
# Import extracted modules with fallback for direct execution
|
|
26
26
|
try:
|
|
@@ -127,7 +127,7 @@ class ClaudeHookHandler:
|
|
|
127
127
|
if self.duplicate_detector.is_duplicate(event):
|
|
128
128
|
if DEBUG:
|
|
129
129
|
print(
|
|
130
|
-
f"[{datetime.now().isoformat()}] Skipping duplicate event: {event.get('hook_event_name', 'unknown')} (PID: {os.getpid()})",
|
|
130
|
+
f"[{datetime.now(timezone.utc).isoformat()}] Skipping duplicate event: {event.get('hook_event_name', 'unknown')} (PID: {os.getpid()})",
|
|
131
131
|
file=sys.stderr,
|
|
132
132
|
)
|
|
133
133
|
# Still need to output continue for this invocation
|
|
@@ -140,7 +140,7 @@ class ClaudeHookHandler:
|
|
|
140
140
|
if DEBUG:
|
|
141
141
|
hook_type = event.get("hook_event_name", "unknown")
|
|
142
142
|
print(
|
|
143
|
-
f"\n[{datetime.now().isoformat()}] Processing hook event: {hook_type} (PID: {os.getpid()})",
|
|
143
|
+
f"\n[{datetime.now(timezone.utc).isoformat()}] Processing hook event: {hook_type} (PID: {os.getpid()})",
|
|
144
144
|
file=sys.stderr,
|
|
145
145
|
)
|
|
146
146
|
|
|
@@ -278,7 +278,7 @@ class ClaudeHookHandler:
|
|
|
278
278
|
if hasattr(self, "connection_manager") and self.connection_manager:
|
|
279
279
|
try:
|
|
280
280
|
self.connection_manager.cleanup()
|
|
281
|
-
except:
|
|
281
|
+
except Exception:
|
|
282
282
|
pass # Ignore cleanup errors during destruction
|
|
283
283
|
|
|
284
284
|
|
|
@@ -85,7 +85,7 @@ try:
|
|
|
85
85
|
else:
|
|
86
86
|
# Installed package - just return the package location
|
|
87
87
|
print(os.path.dirname(pkg_dir))
|
|
88
|
-
except:
|
|
88
|
+
except Exception:
|
|
89
89
|
pass
|
|
90
90
|
" 2>/dev/null)
|
|
91
91
|
|
|
@@ -714,7 +714,7 @@ main "$@"
|
|
|
714
714
|
if "hooks" in settings:
|
|
715
715
|
status["configured_events"] = list(settings["hooks"].keys())
|
|
716
716
|
configured_in_local = True
|
|
717
|
-
except:
|
|
717
|
+
except Exception:
|
|
718
718
|
pass
|
|
719
719
|
|
|
720
720
|
# Also check old settings file
|
|
@@ -728,7 +728,7 @@ main "$@"
|
|
|
728
728
|
status["warning"] = (
|
|
729
729
|
"Hooks found in settings.local.json but Claude Code reads from settings.json"
|
|
730
730
|
)
|
|
731
|
-
except:
|
|
731
|
+
except Exception:
|
|
732
732
|
pass
|
|
733
733
|
|
|
734
734
|
status["settings_location"] = (
|
|
@@ -7,7 +7,7 @@ including pre and post delegation hooks.
|
|
|
7
7
|
|
|
8
8
|
import os
|
|
9
9
|
import sys
|
|
10
|
-
from datetime import datetime
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
11
|
from typing import Optional
|
|
12
12
|
|
|
13
13
|
# Debug mode
|
|
@@ -122,7 +122,7 @@ class MemoryHookManager:
|
|
|
122
122
|
"session_id": session_id,
|
|
123
123
|
},
|
|
124
124
|
metadata={"source": "claude_hook_handler", "tool_name": "Task"},
|
|
125
|
-
timestamp=datetime.now().isoformat(),
|
|
125
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
126
126
|
session_id=session_id,
|
|
127
127
|
)
|
|
128
128
|
|
|
@@ -200,7 +200,7 @@ class MemoryHookManager:
|
|
|
200
200
|
"tool_name": "Task",
|
|
201
201
|
"duration_ms": event.get("duration_ms", 0),
|
|
202
202
|
},
|
|
203
|
-
timestamp=datetime.now().isoformat(),
|
|
203
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
204
204
|
session_id=session_id,
|
|
205
205
|
)
|
|
206
206
|
|
|
@@ -9,7 +9,7 @@ import json
|
|
|
9
9
|
import os
|
|
10
10
|
import re
|
|
11
11
|
import sys
|
|
12
|
-
from datetime import datetime
|
|
12
|
+
from datetime import datetime, timezone
|
|
13
13
|
from typing import Optional
|
|
14
14
|
|
|
15
15
|
# Debug mode
|
|
@@ -192,7 +192,7 @@ class ResponseTrackingManager:
|
|
|
192
192
|
"has_error": bool(event.get("error")),
|
|
193
193
|
"duration_ms": event.get("duration_ms"),
|
|
194
194
|
"working_directory": event.get("cwd", ""),
|
|
195
|
-
"timestamp": datetime.now().isoformat(),
|
|
195
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
196
196
|
"tool_name": "Task",
|
|
197
197
|
"original_request_timestamp": request_info.get("timestamp"),
|
|
198
198
|
}
|
|
@@ -344,7 +344,7 @@ class ResponseTrackingManager:
|
|
|
344
344
|
|
|
345
345
|
# Track the response
|
|
346
346
|
metadata = {
|
|
347
|
-
"timestamp": datetime.now().isoformat(),
|
|
347
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
348
348
|
"prompt_timestamp": prompt_data.get("timestamp"),
|
|
349
349
|
"working_directory": prompt_data.get("working_directory", ""),
|
|
350
350
|
"event_type": "assistant_response",
|
|
@@ -18,7 +18,7 @@ This service manages:
|
|
|
18
18
|
|
|
19
19
|
import os
|
|
20
20
|
import sys
|
|
21
|
-
from datetime import datetime
|
|
21
|
+
from datetime import datetime, timezone
|
|
22
22
|
|
|
23
23
|
# Debug mode is enabled by default for better visibility into hook processing
|
|
24
24
|
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
|
|
@@ -62,7 +62,7 @@ except ImportError:
|
|
|
62
62
|
"type": event_data.get("type", "unknown"),
|
|
63
63
|
"subtype": event_data.get("subtype", "generic"),
|
|
64
64
|
"timestamp": event_data.get(
|
|
65
|
-
"timestamp", datetime.now().isoformat()
|
|
65
|
+
"timestamp", datetime.now(timezone.utc).isoformat()
|
|
66
66
|
),
|
|
67
67
|
"data": event_data.get("data", event_data),
|
|
68
68
|
}
|
|
@@ -119,7 +119,7 @@ class ConnectionManagerService:
|
|
|
119
119
|
raw_event = {
|
|
120
120
|
"type": "hook",
|
|
121
121
|
"subtype": event, # e.g., "user_prompt", "pre_tool", "subagent_stop"
|
|
122
|
-
"timestamp": datetime.now().isoformat(),
|
|
122
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
123
123
|
"data": data,
|
|
124
124
|
"source": "claude_hooks", # Identify the source
|
|
125
125
|
"session_id": data.get("sessionId"), # Include session if available
|
|
@@ -190,7 +190,7 @@ class ConnectionManagerService:
|
|
|
190
190
|
|
|
191
191
|
# Warn if no emission method is available
|
|
192
192
|
if not self.connection_pool and DEBUG:
|
|
193
|
-
print(f"⚠️ No event emission method available for: {event}", file=sys.stderr)
|
|
193
|
+
print(f"⚠️ No event emission method available for: {claude_event_data.get('event', 'unknown')}", file=sys.stderr)
|
|
194
194
|
|
|
195
195
|
def cleanup(self):
|
|
196
196
|
"""Cleanup connections on service destruction."""
|
|
@@ -198,5 +198,5 @@ class ConnectionManagerService:
|
|
|
198
198
|
if self.connection_pool:
|
|
199
199
|
try:
|
|
200
200
|
self.connection_pool.cleanup()
|
|
201
|
-
except:
|
|
201
|
+
except Exception:
|
|
202
202
|
pass # Ignore cleanup errors during destruction
|
|
@@ -12,7 +12,7 @@ This eliminates disconnection issues and matches the process lifecycle.
|
|
|
12
12
|
import asyncio
|
|
13
13
|
import os
|
|
14
14
|
import sys
|
|
15
|
-
from datetime import datetime
|
|
15
|
+
from datetime import datetime, timezone
|
|
16
16
|
|
|
17
17
|
# Debug mode is enabled by default for better visibility into hook processing
|
|
18
18
|
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
|
|
@@ -52,7 +52,7 @@ except ImportError:
|
|
|
52
52
|
"type": event_data.get("type", "unknown"),
|
|
53
53
|
"subtype": event_data.get("subtype", "generic"),
|
|
54
54
|
"timestamp": event_data.get(
|
|
55
|
-
"timestamp", datetime.now().isoformat()
|
|
55
|
+
"timestamp", datetime.now(timezone.utc).isoformat()
|
|
56
56
|
),
|
|
57
57
|
"data": event_data.get("data", event_data),
|
|
58
58
|
}
|
|
@@ -101,7 +101,7 @@ class ConnectionManagerService:
|
|
|
101
101
|
raw_event = {
|
|
102
102
|
"type": "hook",
|
|
103
103
|
"subtype": event, # e.g., "user_prompt", "pre_tool", "subagent_stop"
|
|
104
|
-
"timestamp": datetime.now().isoformat(),
|
|
104
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
105
105
|
"data": data,
|
|
106
106
|
"source": "claude_hooks", # Identify the source
|
|
107
107
|
"session_id": data.get("sessionId"), # Include session if available
|
|
@@ -11,7 +11,7 @@ import os
|
|
|
11
11
|
import subprocess
|
|
12
12
|
import time
|
|
13
13
|
from collections import deque
|
|
14
|
-
from datetime import datetime
|
|
14
|
+
from datetime import datetime, timezone
|
|
15
15
|
from typing import Optional
|
|
16
16
|
|
|
17
17
|
# Import constants for configuration
|
|
@@ -77,7 +77,7 @@ class StateManagerService:
|
|
|
77
77
|
|
|
78
78
|
if session_id and agent_type and agent_type != "unknown":
|
|
79
79
|
self.active_delegations[session_id] = agent_type
|
|
80
|
-
key = f"{session_id}:{datetime.now().timestamp()}"
|
|
80
|
+
key = f"{session_id}:{datetime.now(timezone.utc).timestamp()}"
|
|
81
81
|
self.delegation_history.append((key, agent_type))
|
|
82
82
|
|
|
83
83
|
# Store request data for response tracking correlation
|
|
@@ -85,7 +85,7 @@ class StateManagerService:
|
|
|
85
85
|
self.delegation_requests[session_id] = {
|
|
86
86
|
"agent_type": agent_type,
|
|
87
87
|
"request": request_data,
|
|
88
|
-
"timestamp": datetime.now().isoformat(),
|
|
88
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
89
89
|
}
|
|
90
90
|
if DEBUG:
|
|
91
91
|
import sys
|
|
@@ -100,7 +100,7 @@ class StateManagerService:
|
|
|
100
100
|
)
|
|
101
101
|
|
|
102
102
|
# Clean up old delegations (older than 5 minutes)
|
|
103
|
-
cutoff_time = datetime.now().timestamp() - 300
|
|
103
|
+
cutoff_time = datetime.now(timezone.utc).timestamp() - 300
|
|
104
104
|
keys_to_remove = []
|
|
105
105
|
for sid in list(self.active_delegations.keys()):
|
|
106
106
|
# Check if this is an old entry by looking in history
|
|
@@ -136,7 +136,7 @@ class StateManagerService:
|
|
|
136
136
|
|
|
137
137
|
def cleanup_old_entries(self):
|
|
138
138
|
"""Clean up old entries to prevent memory growth."""
|
|
139
|
-
datetime.now().timestamp() - self.MAX_CACHE_AGE_SECONDS
|
|
139
|
+
datetime.now(timezone.utc).timestamp() - self.MAX_CACHE_AGE_SECONDS
|
|
140
140
|
|
|
141
141
|
# Clean up delegation tracking dictionaries
|
|
142
142
|
for storage in [self.active_delegations, self.delegation_requests]:
|
|
@@ -158,7 +158,8 @@ class StateManagerService:
|
|
|
158
158
|
expired_keys = [
|
|
159
159
|
key
|
|
160
160
|
for key, cache_time in self._git_branch_cache_time.items()
|
|
161
|
-
if datetime.now().timestamp() - cache_time
|
|
161
|
+
if datetime.now(timezone.utc).timestamp() - cache_time
|
|
162
|
+
> self.MAX_CACHE_AGE_SECONDS
|
|
162
163
|
]
|
|
163
164
|
for key in expired_keys:
|
|
164
165
|
self._git_branch_cache.pop(key, None)
|
|
@@ -178,7 +179,7 @@ class StateManagerService:
|
|
|
178
179
|
working_dir = os.getcwd()
|
|
179
180
|
|
|
180
181
|
# Check cache first (cache for 30 seconds)
|
|
181
|
-
current_time = datetime.now().timestamp()
|
|
182
|
+
current_time = datetime.now(timezone.utc).timestamp()
|
|
182
183
|
cache_key = working_dir
|
|
183
184
|
|
|
184
185
|
if (
|