claude-mpm 4.3.12__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/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 +46 -2
- claude_mpm/cli/commands/search.py +41 -34
- claude_mpm/cli/interactive/agent_wizard.py +2 -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 +3 -5
- claude_mpm/cli/utils.py +1 -1
- 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 +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/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 +2 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +9 -3
- 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/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_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 +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 +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 +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 +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.12.dist-info → claude_mpm-4.3.13.dist-info}/METADATA +1 -1
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/RECORD +199 -199
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/WHEEL +0 -0
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/top_level.txt +0 -0
|
@@ -138,7 +138,7 @@ def summarize_todos(todos: list) -> dict:
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
|
|
141
|
-
def classify_tool_operation(tool_name: str, tool_input: dict) -> str:
|
|
141
|
+
def classify_tool_operation(tool_name: str, tool_input: dict) -> str: # noqa: PLR0911
|
|
142
142
|
"""Classify the type of operation being performed."""
|
|
143
143
|
if tool_name in ["Read", "LS", "Glob", "Grep", "NotebookRead"]:
|
|
144
144
|
return "read"
|
|
@@ -155,7 +155,7 @@ def classify_tool_operation(tool_name: str, tool_input: dict) -> str:
|
|
|
155
155
|
return "other"
|
|
156
156
|
|
|
157
157
|
|
|
158
|
-
def assess_security_risk(tool_name: str, tool_input: dict) -> str:
|
|
158
|
+
def assess_security_risk(tool_name: str, tool_input: dict) -> str: # noqa: PLR0911
|
|
159
159
|
"""Assess the security risk level of the tool operation."""
|
|
160
160
|
if tool_name == "Bash":
|
|
161
161
|
command = tool_input.get("command", "").lower()
|
|
@@ -234,7 +234,7 @@ class MemoryPostDelegationHook(PostDelegationHook):
|
|
|
234
234
|
"context": "context", # Current Technical Context
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
def execute(self, context: HookContext) -> HookResult:
|
|
237
|
+
def execute(self, context: HookContext) -> HookResult: # noqa: PLR0911
|
|
238
238
|
"""Extract and store learnings from delegation result.
|
|
239
239
|
|
|
240
240
|
WHY: Capturing learnings immediately after task completion ensures we
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from collections import defaultdict
|
|
5
|
-
from datetime import datetime
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
6
|
from typing import Any, Dict, List, Optional
|
|
7
7
|
|
|
8
8
|
from claude_mpm.core.logger import get_logger
|
|
@@ -105,7 +105,7 @@ class ToolCallInterceptor:
|
|
|
105
105
|
"parameters": parameters.copy(), # Copy to avoid modifying original
|
|
106
106
|
},
|
|
107
107
|
metadata=metadata or {},
|
|
108
|
-
timestamp=datetime.now(),
|
|
108
|
+
timestamp=datetime.now(timezone.utc),
|
|
109
109
|
)
|
|
110
110
|
|
|
111
111
|
# Run hooks
|
|
@@ -13,7 +13,7 @@ chronological order for session replay and analysis.
|
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
15
|
from dataclasses import asdict, dataclass, field
|
|
16
|
-
from datetime import datetime
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
17
|
from enum import Enum
|
|
18
18
|
from typing import Any, Dict, List, Optional, Set
|
|
19
19
|
|
|
@@ -204,7 +204,7 @@ class AgentSession:
|
|
|
204
204
|
and metric updates.
|
|
205
205
|
"""
|
|
206
206
|
if timestamp is None:
|
|
207
|
-
timestamp = datetime.
|
|
207
|
+
timestamp = datetime.now(timezone.utc).isoformat() + "Z"
|
|
208
208
|
|
|
209
209
|
# Categorize the event
|
|
210
210
|
category = self._categorize_event(event_type, data)
|
|
@@ -232,7 +232,7 @@ class AgentSession:
|
|
|
232
232
|
|
|
233
233
|
return event
|
|
234
234
|
|
|
235
|
-
def _categorize_event(self, event_type: str, data: Dict[str, Any]) -> EventCategory:
|
|
235
|
+
def _categorize_event(self, event_type: str, data: Dict[str, Any]) -> EventCategory: # noqa: PLR0911
|
|
236
236
|
"""Categorize an event based on its type and data.
|
|
237
237
|
|
|
238
238
|
WHY: Categories help with filtering and analysis of related events.
|
|
@@ -338,7 +338,7 @@ class AgentSession:
|
|
|
338
338
|
event.timestamp.replace("Z", "+00:00")
|
|
339
339
|
)
|
|
340
340
|
tool_op.duration_ms = int((end - start).total_seconds() * 1000)
|
|
341
|
-
except:
|
|
341
|
+
except Exception:
|
|
342
342
|
pass
|
|
343
343
|
|
|
344
344
|
event.correlation_id = corr_id
|
|
@@ -393,7 +393,7 @@ class AgentSession:
|
|
|
393
393
|
self.metrics.session_duration_ms = int(
|
|
394
394
|
(end - start).total_seconds() * 1000
|
|
395
395
|
)
|
|
396
|
-
except:
|
|
396
|
+
except Exception:
|
|
397
397
|
pass
|
|
398
398
|
|
|
399
399
|
# Finalize any pending delegations
|
claude_mpm/services/__init__.py
CHANGED
|
@@ -13,7 +13,7 @@ New structure:
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
# Use lazy imports to prevent circular dependency issues
|
|
16
|
-
def __getattr__(name):
|
|
16
|
+
def __getattr__(name): # noqa: PLR0911
|
|
17
17
|
"""Lazy import to prevent circular dependencies."""
|
|
18
18
|
if name == "TicketManager":
|
|
19
19
|
from .ticket_manager import TicketManager
|
|
@@ -215,7 +215,7 @@ class AgentCapabilitiesService(BaseService, AgentCapabilitiesInterface):
|
|
|
215
215
|
self.logger.debug(f"Could not parse agent {agent_file}: {e}")
|
|
216
216
|
continue
|
|
217
217
|
|
|
218
|
-
def _categorize_agent(self, agent_id: str, content: str) -> str:
|
|
218
|
+
def _categorize_agent(self, agent_id: str, content: str) -> str: # noqa: PLR0911
|
|
219
219
|
"""Categorize an agent based on its ID and content."""
|
|
220
220
|
agent_id_lower = agent_id.lower()
|
|
221
221
|
content_lower = content.lower()
|
|
@@ -10,7 +10,7 @@ This service provides comprehensive agent lifecycle management including:
|
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
12
|
import re
|
|
13
|
-
from datetime import datetime
|
|
13
|
+
from datetime import datetime, timezone
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Any, Dict, List, Optional, Tuple
|
|
16
16
|
|
|
@@ -108,7 +108,7 @@ class AgentBuilderService:
|
|
|
108
108
|
agent_metadata = {
|
|
109
109
|
"description": description,
|
|
110
110
|
"version": "1.0.0",
|
|
111
|
-
"created": datetime.now().isoformat(),
|
|
111
|
+
"created": datetime.now(timezone.utc).isoformat(),
|
|
112
112
|
"author": "Agent Manager",
|
|
113
113
|
"category": "custom",
|
|
114
114
|
}
|
|
@@ -179,7 +179,7 @@ class AgentBuilderService:
|
|
|
179
179
|
{
|
|
180
180
|
"base_agent": base_agent_id,
|
|
181
181
|
"variant": True,
|
|
182
|
-
"variant_created": datetime.now().isoformat(),
|
|
182
|
+
"variant_created": datetime.now(timezone.utc).isoformat(),
|
|
183
183
|
}
|
|
184
184
|
)
|
|
185
185
|
|
|
@@ -799,7 +799,8 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
|
|
|
799
799
|
if filtered_agents and comparison_results.get("version_upgrades"):
|
|
800
800
|
# Filter upgrades to only those actually being deployed
|
|
801
801
|
deployed_upgrades = [
|
|
802
|
-
upgrade
|
|
802
|
+
upgrade
|
|
803
|
+
for upgrade in comparison_results["version_upgrades"]
|
|
803
804
|
if upgrade["name"] in filtered_agents
|
|
804
805
|
]
|
|
805
806
|
|
|
@@ -219,7 +219,9 @@ class AgentDiscoveryService:
|
|
|
219
219
|
# Handle capabilities as either dict or list
|
|
220
220
|
if isinstance(capabilities, list):
|
|
221
221
|
# If capabilities is a list (like in php-engineer.json), treat it as capabilities list
|
|
222
|
-
tools_list = template_data.get(
|
|
222
|
+
tools_list = template_data.get(
|
|
223
|
+
"tools", []
|
|
224
|
+
) # Look for tools at root level
|
|
223
225
|
model_value = template_data.get("model", "sonnet")
|
|
224
226
|
else:
|
|
225
227
|
# If capabilities is a dict, extract tools and model from it
|
|
@@ -228,9 +230,13 @@ class AgentDiscoveryService:
|
|
|
228
230
|
|
|
229
231
|
agent_info = {
|
|
230
232
|
"name": metadata.get("name", template_file.stem),
|
|
231
|
-
"description": metadata.get(
|
|
233
|
+
"description": metadata.get(
|
|
234
|
+
"description",
|
|
235
|
+
template_data.get("description", "No description available"),
|
|
236
|
+
),
|
|
232
237
|
"type": template_data.get(
|
|
233
|
-
"agent_type",
|
|
238
|
+
"agent_type",
|
|
239
|
+
metadata.get("category", template_data.get("category", "agent")),
|
|
234
240
|
), # Extract agent type
|
|
235
241
|
"version": template_data.get(
|
|
236
242
|
"agent_version",
|
|
@@ -183,9 +183,11 @@ class AgentFileSystemManager:
|
|
|
183
183
|
try:
|
|
184
184
|
# Generate backup directory name if not provided
|
|
185
185
|
if not backup_dir:
|
|
186
|
-
import datetime
|
|
186
|
+
from datetime import datetime, timezone
|
|
187
187
|
|
|
188
|
-
timestamp = datetime.
|
|
188
|
+
timestamp = datetime.now(timezone.utc).strftime(
|
|
189
|
+
"%Y%m%d_%H%M%S"
|
|
190
|
+
)
|
|
189
191
|
backup_dir = agents_dir.parent / f"agents_backup_{timestamp}"
|
|
190
192
|
|
|
191
193
|
# Create backup
|
|
@@ -324,7 +326,7 @@ class AgentFileSystemManager:
|
|
|
324
326
|
|
|
325
327
|
def _convert_yaml_to_markdown(self, yaml_content: str, agent_name: str) -> str:
|
|
326
328
|
"""Convert YAML agent content to Markdown format with frontmatter."""
|
|
327
|
-
from datetime import datetime
|
|
329
|
+
from datetime import datetime, timezone
|
|
328
330
|
|
|
329
331
|
# Extract YAML fields (simplified parsing)
|
|
330
332
|
name = self._extract_yaml_field(yaml_content, "name") or agent_name
|
|
@@ -356,8 +358,8 @@ name: {name}
|
|
|
356
358
|
description: "{description}"
|
|
357
359
|
version: "{version}"
|
|
358
360
|
author: "claude-mpm@anthropic.com"
|
|
359
|
-
created: "{datetime.now().isoformat()}Z"
|
|
360
|
-
updated: "{datetime.now().isoformat()}Z"
|
|
361
|
+
created: "{datetime.now(timezone.utc).isoformat()}Z"
|
|
362
|
+
updated: "{datetime.now(timezone.utc).isoformat()}Z"
|
|
361
363
|
tags: ["{agent_name}", "mpm-framework"]
|
|
362
364
|
tools: {tools_list}
|
|
363
365
|
model: "sonnet"
|
|
@@ -32,6 +32,7 @@ Created for ISS-0118: Agent Registry and Hierarchical Discovery System
|
|
|
32
32
|
|
|
33
33
|
import asyncio
|
|
34
34
|
import time
|
|
35
|
+
from datetime import datetime, timezone
|
|
35
36
|
from pathlib import Path
|
|
36
37
|
from typing import Any, Dict, List, Optional
|
|
37
38
|
|
|
@@ -52,6 +53,7 @@ from claude_mpm.services.agents.registry.modification_tracker import (
|
|
|
52
53
|
ModificationType,
|
|
53
54
|
)
|
|
54
55
|
from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
|
|
56
|
+
from claude_mpm.core.unified_paths import get_path_manager
|
|
55
57
|
from claude_mpm.utils.path_operations import path_ops
|
|
56
58
|
|
|
57
59
|
# Import extracted services
|
|
@@ -758,7 +760,7 @@ class AgentLifecycleManager(BaseService):
|
|
|
758
760
|
backup_dir = get_path_manager().get_tracking_dir() / "backups"
|
|
759
761
|
path_ops.ensure_dir(backup_dir)
|
|
760
762
|
|
|
761
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
763
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
762
764
|
backup_filename = f"{agent_name}_deleted_{timestamp}{source_path.suffix}"
|
|
763
765
|
backup_path = backup_dir / backup_filename
|
|
764
766
|
|
|
@@ -227,7 +227,7 @@ class AgentMetricsCollector:
|
|
|
227
227
|
return "validation_error"
|
|
228
228
|
return "other_error"
|
|
229
229
|
|
|
230
|
-
def _extract_agent_type(self, agent_name: str) -> str:
|
|
230
|
+
def _extract_agent_type(self, agent_name: str) -> str: # noqa: PLR0911
|
|
231
231
|
"""
|
|
232
232
|
Extract agent type from agent name for categorization.
|
|
233
233
|
|
|
@@ -479,9 +479,9 @@ class AgentOperationService(BaseService):
|
|
|
479
479
|
backup_dir = get_path_manager().get_tracking_dir() / "backups"
|
|
480
480
|
path_ops.ensure_dir(backup_dir)
|
|
481
481
|
|
|
482
|
-
from datetime import datetime
|
|
482
|
+
from datetime import datetime, timezone
|
|
483
483
|
|
|
484
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
484
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
485
485
|
backup_filename = f"{agent_name}_deleted_{timestamp}{source_path.suffix}"
|
|
486
486
|
backup_path = backup_dir / backup_filename
|
|
487
487
|
|
|
@@ -59,9 +59,9 @@ class AgentLifecycleRecord:
|
|
|
59
59
|
@property
|
|
60
60
|
def last_modified_datetime(self):
|
|
61
61
|
"""Get last modified as datetime."""
|
|
62
|
-
from datetime import datetime
|
|
62
|
+
from datetime import datetime, timezone
|
|
63
63
|
|
|
64
|
-
return datetime.fromtimestamp(self.last_modified)
|
|
64
|
+
return datetime.fromtimestamp(self.last_modified, tz=timezone.utc)
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
@dataclass
|
|
@@ -230,7 +230,7 @@ class AgentTemplateBuilder:
|
|
|
230
230
|
)
|
|
231
231
|
|
|
232
232
|
# Convert tools list to comma-separated string (without spaces for compatibility)
|
|
233
|
-
|
|
233
|
+
",".join(tools)
|
|
234
234
|
|
|
235
235
|
# Map model names to Claude Code format (as required)
|
|
236
236
|
model_map = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Temporary wrapper to provide backward compatibility for CLI commands."""
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Any, Dict
|
|
5
6
|
|
|
@@ -101,10 +102,8 @@ class DeploymentServiceWrapper:
|
|
|
101
102
|
# Extract frontmatter
|
|
102
103
|
parts = content.split("---", 2)
|
|
103
104
|
if len(parts) >= 2:
|
|
104
|
-
|
|
105
|
+
with contextlib.suppress(yaml.YAMLError):
|
|
105
106
|
metadata = yaml.safe_load(parts[1])
|
|
106
|
-
except yaml.YAMLError:
|
|
107
|
-
pass
|
|
108
107
|
|
|
109
108
|
return {
|
|
110
109
|
"name": agent_name,
|
|
@@ -24,7 +24,7 @@ import json
|
|
|
24
24
|
import logging
|
|
25
25
|
import os
|
|
26
26
|
from dataclasses import dataclass, field
|
|
27
|
-
from datetime import datetime
|
|
27
|
+
from datetime import datetime, timezone
|
|
28
28
|
from enum import Enum
|
|
29
29
|
from pathlib import Path
|
|
30
30
|
from typing import Any, Dict, List, Optional, Tuple
|
|
@@ -227,7 +227,9 @@ class AgentProfileLoader(BaseService):
|
|
|
227
227
|
# Check cache first
|
|
228
228
|
if use_cache and agent_name in self.profile_cache:
|
|
229
229
|
profile = self.profile_cache[agent_name]
|
|
230
|
-
if (
|
|
230
|
+
if (
|
|
231
|
+
datetime.now(timezone.utc) - profile.loaded_at
|
|
232
|
+
).seconds < self.cache_ttl:
|
|
231
233
|
self.load_metrics[f"{agent_name}_cache_hit"] = (
|
|
232
234
|
asyncio.get_event_loop().time() - start_time
|
|
233
235
|
)
|
|
@@ -322,7 +324,7 @@ class AgentProfileLoader(BaseService):
|
|
|
322
324
|
try:
|
|
323
325
|
data = yaml.safe_load(content)
|
|
324
326
|
instructions = data.get("instructions", "")
|
|
325
|
-
except:
|
|
327
|
+
except Exception:
|
|
326
328
|
data = json.loads(content)
|
|
327
329
|
instructions = data.get("instructions", "")
|
|
328
330
|
|
|
@@ -9,7 +9,7 @@ Enforces template structure and provides section-specific update methods.
|
|
|
9
9
|
|
|
10
10
|
import logging
|
|
11
11
|
from dataclasses import dataclass, field
|
|
12
|
-
from datetime import datetime
|
|
12
|
+
from datetime import datetime, timezone
|
|
13
13
|
from enum import Enum
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Any, Dict, List, Optional
|
|
@@ -358,7 +358,7 @@ class BaseAgentManager(ConfigServiceBase):
|
|
|
358
358
|
|
|
359
359
|
def _create_backup(self) -> Path:
|
|
360
360
|
"""Create a timestamped backup of base_agent.md."""
|
|
361
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
361
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
362
362
|
backup_path = self.base_agent_path.parent / f"base_agent_{timestamp}.backup"
|
|
363
363
|
|
|
364
364
|
if self.base_agent_path.exists():
|
|
@@ -15,7 +15,7 @@ Key Features:
|
|
|
15
15
|
|
|
16
16
|
import json
|
|
17
17
|
from dataclasses import dataclass
|
|
18
|
-
from datetime import datetime
|
|
18
|
+
from datetime import datetime, timezone
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
21
21
|
|
|
@@ -57,9 +57,9 @@ class LocalAgentTemplate:
|
|
|
57
57
|
if self.configuration is None:
|
|
58
58
|
self.configuration = {}
|
|
59
59
|
if self.created_at is None:
|
|
60
|
-
self.created_at = datetime.now().isoformat()
|
|
60
|
+
self.created_at = datetime.now(timezone.utc).isoformat()
|
|
61
61
|
if self.updated_at is None:
|
|
62
|
-
self.updated_at = datetime.now().isoformat()
|
|
62
|
+
self.updated_at = datetime.now(timezone.utc).isoformat()
|
|
63
63
|
|
|
64
64
|
# Ensure metadata has required fields
|
|
65
65
|
if "name" not in self.metadata:
|
|
@@ -303,7 +303,7 @@ class LocalAgentTemplateManager:
|
|
|
303
303
|
target_dir.mkdir(parents=True, exist_ok=True)
|
|
304
304
|
|
|
305
305
|
# Update timestamp
|
|
306
|
-
template.updated_at = datetime.now().isoformat()
|
|
306
|
+
template.updated_at = datetime.now(timezone.utc).isoformat()
|
|
307
307
|
|
|
308
308
|
# Save to JSON file
|
|
309
309
|
template_file = target_dir / f"{template.agent_id}.json"
|
|
@@ -455,7 +455,7 @@ class LocalAgentTemplateManager:
|
|
|
455
455
|
|
|
456
456
|
try:
|
|
457
457
|
# Create backup directory
|
|
458
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
458
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
459
459
|
backup_dir = (
|
|
460
460
|
self.working_directory
|
|
461
461
|
/ ".claude-mpm"
|
|
@@ -633,7 +633,7 @@ class LocalAgentTemplateManager:
|
|
|
633
633
|
|
|
634
634
|
# Update template version
|
|
635
635
|
template.agent_version = new_version
|
|
636
|
-
template.updated_at = datetime.now().isoformat()
|
|
636
|
+
template.updated_at = datetime.now(timezone.utc).isoformat()
|
|
637
637
|
|
|
638
638
|
# Save updated template
|
|
639
639
|
self.save_local_template(template)
|
|
@@ -13,7 +13,7 @@ Uses python-frontmatter and mistune for markdown parsing as recommended.
|
|
|
13
13
|
|
|
14
14
|
import logging
|
|
15
15
|
import re
|
|
16
|
-
from datetime import datetime
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
17
|
from typing import Any, Dict, List, Optional
|
|
18
18
|
|
|
19
19
|
import frontmatter
|
|
@@ -156,7 +156,7 @@ class AgentManager:
|
|
|
156
156
|
# Increment version if requested
|
|
157
157
|
if increment_version:
|
|
158
158
|
agent_def.metadata.increment_serial_version()
|
|
159
|
-
agent_def.metadata.last_updated = datetime.now()
|
|
159
|
+
agent_def.metadata.last_updated = datetime.now(timezone.utc)
|
|
160
160
|
|
|
161
161
|
# Write back
|
|
162
162
|
agent_path = self._find_agent_file(name)
|
|
@@ -234,7 +234,7 @@ class AgentManager:
|
|
|
234
234
|
# Increment version
|
|
235
235
|
if increment_version:
|
|
236
236
|
agent_def.metadata.increment_serial_version()
|
|
237
|
-
agent_def.metadata.last_updated = datetime.now()
|
|
237
|
+
agent_def.metadata.last_updated = datetime.now(timezone.utc)
|
|
238
238
|
|
|
239
239
|
# Write back
|
|
240
240
|
return self.update_agent(name, {}, increment_version=False)
|
|
@@ -14,7 +14,7 @@ This module provides:
|
|
|
14
14
|
|
|
15
15
|
import logging
|
|
16
16
|
import re
|
|
17
|
-
from datetime import datetime
|
|
17
|
+
from datetime import datetime, timezone
|
|
18
18
|
from difflib import SequenceMatcher
|
|
19
19
|
from typing import Any, Dict, List, Optional, Tuple
|
|
20
20
|
|
|
@@ -203,7 +203,7 @@ class MemoryContentManager:
|
|
|
203
203
|
Returns:
|
|
204
204
|
str: Content with updated timestamp
|
|
205
205
|
"""
|
|
206
|
-
timestamp = datetime.now().isoformat() + "Z"
|
|
206
|
+
timestamp = datetime.now(timezone.utc).isoformat() + "Z"
|
|
207
207
|
# Handle both old and new timestamp formats
|
|
208
208
|
content = re.sub(
|
|
209
209
|
r"<!-- Last Updated: .+? -->",
|
|
@@ -260,7 +260,7 @@ class MemoryContentManager:
|
|
|
260
260
|
|
|
261
261
|
if not has_timestamp:
|
|
262
262
|
new_lines.append(
|
|
263
|
-
f"<!-- Last Updated: {datetime.now().isoformat()}Z -->"
|
|
263
|
+
f"<!-- Last Updated: {datetime.now(timezone.utc).isoformat()}Z -->"
|
|
264
264
|
)
|
|
265
265
|
new_lines.append("")
|
|
266
266
|
else:
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import logging
|
|
5
5
|
import re
|
|
6
|
-
from datetime import datetime
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
7
|
from typing import Dict, List
|
|
8
8
|
|
|
9
9
|
|
|
@@ -26,7 +26,7 @@ class MemoryFormatService:
|
|
|
26
26
|
"""
|
|
27
27
|
# Build header
|
|
28
28
|
header = f"# {agent_id.title()} Agent Memory\n\n"
|
|
29
|
-
header += f"Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
|
|
29
|
+
header += f"Last Updated: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S')}\n\n"
|
|
30
30
|
header += "## Learnings\n\n"
|
|
31
31
|
|
|
32
32
|
# Build item list
|
|
@@ -13,7 +13,7 @@ This module provides:
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
import logging
|
|
16
|
-
from datetime import datetime
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import Any, Dict
|
|
19
19
|
|
|
@@ -58,7 +58,7 @@ class MemoryTemplateGenerator:
|
|
|
58
58
|
"""
|
|
59
59
|
# Convert agent_id to proper name, handling cases like "test_agent" -> "Test"
|
|
60
60
|
agent_id.replace("_agent", "").replace("_", " ").title()
|
|
61
|
-
datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
61
|
+
datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
|
|
62
62
|
|
|
63
63
|
# Create a simple template that agents will populate through learning
|
|
64
64
|
return self._create_basic_memory_template(agent_id, limits)
|
|
@@ -75,7 +75,7 @@ class MemoryTemplateGenerator:
|
|
|
75
75
|
Returns:
|
|
76
76
|
str: Basic memory template
|
|
77
77
|
"""
|
|
78
|
-
timestamp = datetime.now().isoformat() + "Z"
|
|
78
|
+
timestamp = datetime.now(timezone.utc).isoformat() + "Z"
|
|
79
79
|
|
|
80
80
|
return f"""# Agent Memory: {agent_id}
|
|
81
81
|
<!-- Last Updated: {timestamp} -->
|
|
@@ -4,8 +4,8 @@ from claude_mpm.core.unified_agent_registry import (
|
|
|
4
4
|
AgentMetadata,
|
|
5
5
|
AgentTier,
|
|
6
6
|
AgentType,
|
|
7
|
-
UnifiedAgentRegistry as AgentRegistry,
|
|
8
7
|
)
|
|
8
|
+
from claude_mpm.core.unified_agent_registry import UnifiedAgentRegistry as AgentRegistry
|
|
9
9
|
|
|
10
10
|
from .deployed_agent_discovery import DeployedAgentDiscovery
|
|
11
11
|
from .modification_tracker import (
|
|
@@ -30,7 +30,7 @@ import shutil
|
|
|
30
30
|
import time
|
|
31
31
|
import uuid
|
|
32
32
|
from dataclasses import asdict, dataclass, field
|
|
33
|
-
from datetime import datetime
|
|
33
|
+
from datetime import datetime, timezone
|
|
34
34
|
from enum import Enum
|
|
35
35
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple
|
|
36
36
|
|
|
@@ -90,7 +90,7 @@ class AgentModification:
|
|
|
90
90
|
@property
|
|
91
91
|
def modification_datetime(self) -> datetime:
|
|
92
92
|
"""Get modification timestamp as datetime."""
|
|
93
|
-
return datetime.fromtimestamp(self.timestamp)
|
|
93
|
+
return datetime.fromtimestamp(self.timestamp, tz=timezone.utc)
|
|
94
94
|
|
|
95
95
|
@property
|
|
96
96
|
def age_seconds(self) -> float:
|
|
@@ -22,7 +22,7 @@ import os
|
|
|
22
22
|
import sys
|
|
23
23
|
import time
|
|
24
24
|
from dataclasses import asdict, dataclass
|
|
25
|
-
from datetime import datetime
|
|
25
|
+
from datetime import datetime, timezone
|
|
26
26
|
from enum import Enum
|
|
27
27
|
from queue import Full, Queue
|
|
28
28
|
from threading import Lock, Thread
|
|
@@ -184,7 +184,7 @@ class AsyncSessionLogger:
|
|
|
184
184
|
return session_id
|
|
185
185
|
|
|
186
186
|
# Generate timestamp-based session ID
|
|
187
|
-
session_id = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
187
|
+
session_id = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
188
188
|
logger.info(f"Generated session ID: {session_id}")
|
|
189
189
|
return session_id
|
|
190
190
|
|
|
@@ -406,7 +406,7 @@ class AsyncSessionLogger:
|
|
|
406
406
|
agent_name = metadata["agent"].replace(" ", "_").lower()
|
|
407
407
|
|
|
408
408
|
# Create timestamp with microsecond precision
|
|
409
|
-
now = datetime.now()
|
|
409
|
+
now = datetime.now(timezone.utc)
|
|
410
410
|
timestamp = now.isoformat()
|
|
411
411
|
microseconds = now.microsecond
|
|
412
412
|
|
|
@@ -13,7 +13,7 @@ Configuration via .claude-mpm/configuration.yaml.
|
|
|
13
13
|
import json
|
|
14
14
|
import logging
|
|
15
15
|
import os
|
|
16
|
-
from datetime import datetime
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
17
|
from typing import Any, Dict, Optional
|
|
18
18
|
|
|
19
19
|
# Import configuration manager
|
|
@@ -133,7 +133,7 @@ class ClaudeSessionLogger:
|
|
|
133
133
|
# Generate a default based on timestamp if nothing found
|
|
134
134
|
if not session_id:
|
|
135
135
|
# Use a timestamp-based session ID as fallback
|
|
136
|
-
session_id = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
136
|
+
session_id = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
137
137
|
logger.info(f"No Claude session ID found, using generated: {session_id}")
|
|
138
138
|
else:
|
|
139
139
|
logger.info(f"Using Claude session ID: {session_id}")
|
|
@@ -156,7 +156,7 @@ class ClaudeSessionLogger:
|
|
|
156
156
|
agent_name = agent_name.replace(" ", "_").lower()
|
|
157
157
|
|
|
158
158
|
# Generate timestamp with microseconds for uniqueness
|
|
159
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
|
|
159
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S_%f")
|
|
160
160
|
|
|
161
161
|
# Create filename: session_id-agent-timestamp.json
|
|
162
162
|
return f"{self.session_id}-{agent_name}-{timestamp}.json"
|
|
@@ -216,7 +216,7 @@ class ClaudeSessionLogger:
|
|
|
216
216
|
|
|
217
217
|
# Prepare response data with standardized field names
|
|
218
218
|
response_data = {
|
|
219
|
-
"timestamp": datetime.now().isoformat(),
|
|
219
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
220
220
|
"session_id": self.session_id,
|
|
221
221
|
"request": request_summary, # Standardized field name
|
|
222
222
|
"response": response_content, # Already correct
|
|
@@ -336,7 +336,7 @@ class AgentListingService(IAgentListingService):
|
|
|
336
336
|
self.logger.error(f"Error listing agents by tier: {e}", exc_info=True)
|
|
337
337
|
return AgentTierInfo(project=[], user=[], system=[])
|
|
338
338
|
|
|
339
|
-
def get_agent_details(self, agent_name: str) -> Optional[Dict[str, Any]]:
|
|
339
|
+
def get_agent_details(self, agent_name: str) -> Optional[Dict[str, Any]]: # noqa: PLR0911
|
|
340
340
|
"""Get detailed information for a specific agent."""
|
|
341
341
|
cache_key = f"agent_details_{agent_name}"
|
|
342
342
|
cached = self._get_from_cache(cache_key)
|