claude-mpm 4.1.6__py3-none-any.whl → 4.1.8__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/OUTPUT_STYLE.md +73 -0
- claude_mpm/agents/templates/agent-manager.json +1 -1
- claude_mpm/agents/templates/agent-manager.md +349 -34
- claude_mpm/cli/commands/configure.py +151 -2
- claude_mpm/cli/commands/configure_tui.py +5 -1
- claude_mpm/cli/parsers/configure_parser.py +23 -0
- claude_mpm/config/socketio_config.py +33 -4
- claude_mpm/dashboard/static/js/socket-client.js +40 -16
- claude_mpm/hooks/claude_hooks/installer.py +455 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +17 -0
- claude_mpm/services/agents/deployment/agent_config_provider.py +127 -27
- claude_mpm/services/diagnostics/checks/instructions_check.py +1 -3
- claude_mpm/services/event_bus/direct_relay.py +146 -11
- claude_mpm/services/socketio/handlers/connection_handler.py +3 -18
- claude_mpm/services/socketio/server/connection_manager.py +124 -63
- claude_mpm/services/socketio/server/core.py +34 -7
- claude_mpm/services/socketio/server/main.py +83 -21
- {claude_mpm-4.1.6.dist-info → claude_mpm-4.1.8.dist-info}/METADATA +1 -1
- {claude_mpm-4.1.6.dist-info → claude_mpm-4.1.8.dist-info}/RECORD +24 -22
- {claude_mpm-4.1.6.dist-info → claude_mpm-4.1.8.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.6.dist-info → claude_mpm-4.1.8.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.6.dist-info → claude_mpm-4.1.8.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.6.dist-info → claude_mpm-4.1.8.dist-info}/top_level.txt +0 -0
|
@@ -71,20 +71,28 @@ class ClientConnection:
|
|
|
71
71
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
72
72
|
|
|
73
73
|
def is_healthy(self, timeout: float = 90.0) -> bool:
|
|
74
|
-
"""Check if connection is healthy based on activity.
|
|
74
|
+
"""Check if connection is healthy based on activity.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
timeout: Seconds before considering connection unhealthy (default 90s)
|
|
78
|
+
"""
|
|
75
79
|
if self.state != ConnectionState.CONNECTED:
|
|
76
80
|
return False
|
|
77
81
|
|
|
78
82
|
now = time.time()
|
|
79
83
|
|
|
80
84
|
# Check last activity (ping, pong, or event)
|
|
85
|
+
# Include metrics.last_activity for more comprehensive tracking
|
|
81
86
|
last_activity = max(
|
|
82
87
|
self.last_ping or 0,
|
|
83
88
|
self.last_pong or 0,
|
|
84
89
|
self.last_event or 0,
|
|
90
|
+
self.metrics.last_activity or 0,
|
|
85
91
|
self.connected_at,
|
|
86
92
|
)
|
|
87
93
|
|
|
94
|
+
# More aggressive timeout for stale detection (no grace period)
|
|
95
|
+
# This helps identify truly stale connections faster
|
|
88
96
|
return (now - last_activity) < timeout
|
|
89
97
|
|
|
90
98
|
def calculate_quality(self) -> float:
|
|
@@ -140,22 +148,28 @@ class ConnectionManager:
|
|
|
140
148
|
- Automatic event replay on reconnection
|
|
141
149
|
"""
|
|
142
150
|
|
|
143
|
-
def __init__(self, max_buffer_size: int =
|
|
151
|
+
def __init__(self, max_buffer_size: int = None, event_ttl: int = None):
|
|
144
152
|
"""
|
|
145
|
-
Initialize connection manager.
|
|
153
|
+
Initialize connection manager with centralized configuration.
|
|
146
154
|
|
|
147
155
|
Args:
|
|
148
|
-
max_buffer_size: Maximum events to buffer per client
|
|
149
|
-
event_ttl: Time-to-live for buffered events in seconds
|
|
156
|
+
max_buffer_size: Maximum events to buffer per client (uses config if None)
|
|
157
|
+
event_ttl: Time-to-live for buffered events in seconds (uses config if None)
|
|
150
158
|
"""
|
|
159
|
+
from ....config.socketio_config import CONNECTION_CONFIG
|
|
160
|
+
|
|
151
161
|
self.logger = get_logger(__name__)
|
|
152
162
|
self.connections: Dict[str, ClientConnection] = {}
|
|
153
163
|
self.client_mapping: Dict[str, str] = {} # client_id -> current sid
|
|
154
|
-
|
|
155
|
-
|
|
164
|
+
|
|
165
|
+
# Use centralized configuration with optional overrides
|
|
166
|
+
self.max_buffer_size = max_buffer_size or CONNECTION_CONFIG["max_events_buffer"]
|
|
167
|
+
self.event_ttl = event_ttl or CONNECTION_CONFIG["event_ttl"]
|
|
156
168
|
self.global_sequence = 0
|
|
157
|
-
self.health_check_interval =
|
|
158
|
-
|
|
169
|
+
self.health_check_interval = CONNECTION_CONFIG[
|
|
170
|
+
"health_check_interval"
|
|
171
|
+
] # 30 seconds
|
|
172
|
+
self.stale_timeout = CONNECTION_CONFIG["stale_timeout"] # 180 seconds (was 90)
|
|
159
173
|
self.health_task = None
|
|
160
174
|
self._lock = asyncio.Lock()
|
|
161
175
|
|
|
@@ -163,7 +177,7 @@ class ConnectionManager:
|
|
|
163
177
|
self, sid: str, client_id: Optional[str] = None
|
|
164
178
|
) -> ClientConnection:
|
|
165
179
|
"""
|
|
166
|
-
Register a new connection or reconnection.
|
|
180
|
+
Register a new connection or reconnection with retry logic.
|
|
167
181
|
|
|
168
182
|
Args:
|
|
169
183
|
sid: Socket ID
|
|
@@ -172,54 +186,83 @@ class ConnectionManager:
|
|
|
172
186
|
Returns:
|
|
173
187
|
ClientConnection object
|
|
174
188
|
"""
|
|
175
|
-
|
|
176
|
-
|
|
189
|
+
max_retries = 3
|
|
190
|
+
retry_delay = 0.1 # Start with 100ms
|
|
177
191
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
192
|
+
for attempt in range(max_retries):
|
|
193
|
+
try:
|
|
194
|
+
async with self._lock:
|
|
195
|
+
now = time.time()
|
|
196
|
+
|
|
197
|
+
# Check if this is a reconnection
|
|
198
|
+
if client_id and client_id in self.client_mapping:
|
|
199
|
+
old_sid = self.client_mapping[client_id]
|
|
200
|
+
if old_sid in self.connections:
|
|
201
|
+
old_conn = self.connections[old_sid]
|
|
202
|
+
|
|
203
|
+
# Create new connection with history
|
|
204
|
+
conn = ClientConnection(
|
|
205
|
+
sid=sid,
|
|
206
|
+
client_id=client_id,
|
|
207
|
+
state=ConnectionState.CONNECTED,
|
|
208
|
+
connected_at=now,
|
|
209
|
+
event_buffer=old_conn.event_buffer,
|
|
210
|
+
event_sequence=old_conn.event_sequence,
|
|
211
|
+
last_acked_sequence=old_conn.last_acked_sequence,
|
|
212
|
+
metrics=old_conn.metrics,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Update metrics
|
|
216
|
+
conn.metrics.reconnect_count += 1
|
|
217
|
+
conn.metrics.connect_count += 1
|
|
218
|
+
if old_conn.disconnected_at:
|
|
219
|
+
conn.metrics.total_downtime += (
|
|
220
|
+
now - old_conn.disconnected_at
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
# Clean up old connection
|
|
224
|
+
del self.connections[old_sid]
|
|
225
|
+
|
|
226
|
+
self.logger.info(
|
|
227
|
+
f"Client {client_id} reconnected (new sid: {sid}, "
|
|
228
|
+
f"buffered events: {len(conn.event_buffer)})"
|
|
229
|
+
)
|
|
230
|
+
else:
|
|
231
|
+
# No old connection found, create new
|
|
232
|
+
client_id = client_id or str(uuid4())
|
|
233
|
+
conn = self._create_new_connection(sid, client_id, now)
|
|
234
|
+
else:
|
|
235
|
+
# New client
|
|
236
|
+
client_id = client_id or str(uuid4())
|
|
237
|
+
conn = self._create_new_connection(sid, client_id, now)
|
|
183
238
|
|
|
184
|
-
#
|
|
239
|
+
# Register connection with validation
|
|
240
|
+
if conn and conn.state == ConnectionState.CONNECTED:
|
|
241
|
+
self.connections[sid] = conn
|
|
242
|
+
self.client_mapping[client_id] = sid
|
|
243
|
+
return conn
|
|
244
|
+
raise ValueError(f"Invalid connection state for {sid}")
|
|
245
|
+
|
|
246
|
+
except Exception as e:
|
|
247
|
+
self.logger.warning(
|
|
248
|
+
f"Failed to register connection {sid} (attempt {attempt + 1}/{max_retries}): {e}"
|
|
249
|
+
)
|
|
250
|
+
if attempt < max_retries - 1:
|
|
251
|
+
await asyncio.sleep(retry_delay)
|
|
252
|
+
retry_delay *= 2 # Exponential backoff
|
|
253
|
+
else:
|
|
254
|
+
# Final attempt failed, create minimal connection
|
|
255
|
+
self.logger.error(
|
|
256
|
+
f"All attempts failed for {sid}, creating minimal connection"
|
|
257
|
+
)
|
|
185
258
|
conn = ClientConnection(
|
|
186
259
|
sid=sid,
|
|
187
|
-
client_id=client_id,
|
|
260
|
+
client_id=client_id or str(uuid4()),
|
|
188
261
|
state=ConnectionState.CONNECTED,
|
|
189
|
-
connected_at=
|
|
190
|
-
event_buffer=old_conn.event_buffer,
|
|
191
|
-
event_sequence=old_conn.event_sequence,
|
|
192
|
-
last_acked_sequence=old_conn.last_acked_sequence,
|
|
193
|
-
metrics=old_conn.metrics,
|
|
262
|
+
connected_at=time.time(),
|
|
194
263
|
)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
conn.metrics.reconnect_count += 1
|
|
198
|
-
conn.metrics.connect_count += 1
|
|
199
|
-
if old_conn.disconnected_at:
|
|
200
|
-
conn.metrics.total_downtime += now - old_conn.disconnected_at
|
|
201
|
-
|
|
202
|
-
# Clean up old connection
|
|
203
|
-
del self.connections[old_sid]
|
|
204
|
-
|
|
205
|
-
self.logger.info(
|
|
206
|
-
f"Client {client_id} reconnected (new sid: {sid}, "
|
|
207
|
-
f"buffered events: {len(conn.event_buffer)})"
|
|
208
|
-
)
|
|
209
|
-
else:
|
|
210
|
-
# No old connection found, create new
|
|
211
|
-
client_id = client_id or str(uuid4())
|
|
212
|
-
conn = self._create_new_connection(sid, client_id, now)
|
|
213
|
-
else:
|
|
214
|
-
# New client
|
|
215
|
-
client_id = client_id or str(uuid4())
|
|
216
|
-
conn = self._create_new_connection(sid, client_id, now)
|
|
217
|
-
|
|
218
|
-
# Register connection
|
|
219
|
-
self.connections[sid] = conn
|
|
220
|
-
self.client_mapping[client_id] = sid
|
|
221
|
-
|
|
222
|
-
return conn
|
|
264
|
+
self.connections[sid] = conn
|
|
265
|
+
return conn
|
|
223
266
|
|
|
224
267
|
def _create_new_connection(
|
|
225
268
|
self, sid: str, client_id: str, now: float
|
|
@@ -439,21 +482,39 @@ class ConnectionManager:
|
|
|
439
482
|
if conn.is_healthy(self.stale_timeout):
|
|
440
483
|
report["healthy"] += 1
|
|
441
484
|
else:
|
|
442
|
-
# Mark as stale
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
485
|
+
# Mark as stale only if really stale (no grace period activity)
|
|
486
|
+
last_activity = max(
|
|
487
|
+
conn.last_ping or 0,
|
|
488
|
+
conn.last_pong or 0,
|
|
489
|
+
conn.last_event or 0,
|
|
490
|
+
conn.metrics.last_activity or 0,
|
|
491
|
+
conn.connected_at,
|
|
448
492
|
)
|
|
493
|
+
time_since_activity = now - last_activity
|
|
494
|
+
|
|
495
|
+
# Only mark as stale if significantly over timeout (2x)
|
|
496
|
+
if time_since_activity > (self.stale_timeout * 2):
|
|
497
|
+
conn.state = ConnectionState.STALE
|
|
498
|
+
report["stale"] += 1
|
|
499
|
+
self.logger.warning(
|
|
500
|
+
f"Connection {conn.client_id} marked as stale "
|
|
501
|
+
f"(last activity: {time_since_activity:.1f}s ago)"
|
|
502
|
+
)
|
|
503
|
+
else:
|
|
504
|
+
# Connection is borderline - keep it alive but log
|
|
505
|
+
report["healthy"] += 1
|
|
506
|
+
self.logger.debug(
|
|
507
|
+
f"Connection {conn.client_id} borderline "
|
|
508
|
+
f"(last activity: {time_since_activity:.1f}s ago)"
|
|
509
|
+
)
|
|
510
|
+
|
|
449
511
|
elif conn.state == ConnectionState.DISCONNECTED:
|
|
450
512
|
report["disconnected"] += 1
|
|
451
513
|
|
|
452
|
-
# Clean up old disconnected connections
|
|
453
|
-
if (
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
):
|
|
514
|
+
# Clean up old disconnected connections (be conservative)
|
|
515
|
+
if conn.disconnected_at and (now - conn.disconnected_at) > (
|
|
516
|
+
self.event_ttl * 2
|
|
517
|
+
): # Double the TTL
|
|
457
518
|
to_clean.append(sid)
|
|
458
519
|
|
|
459
520
|
# Clean up old connections
|
|
@@ -158,20 +158,40 @@ class SocketIOServerCore:
|
|
|
158
158
|
async def _start_server(self):
|
|
159
159
|
"""Start the Socket.IO server with aiohttp."""
|
|
160
160
|
try:
|
|
161
|
-
#
|
|
161
|
+
# Import centralized configuration for consistency
|
|
162
|
+
from ....config.socketio_config import CONNECTION_CONFIG
|
|
163
|
+
|
|
164
|
+
# Create Socket.IO server with centralized configuration
|
|
165
|
+
# CRITICAL: These values MUST match client settings to prevent disconnections
|
|
162
166
|
self.sio = socketio.AsyncServer(
|
|
163
167
|
cors_allowed_origins="*",
|
|
164
168
|
logger=False, # Disable Socket.IO's own logging
|
|
165
169
|
engineio_logger=False,
|
|
166
|
-
ping_interval=
|
|
167
|
-
|
|
168
|
-
|
|
170
|
+
ping_interval=CONNECTION_CONFIG[
|
|
171
|
+
"ping_interval"
|
|
172
|
+
], # 45 seconds from config
|
|
173
|
+
ping_timeout=CONNECTION_CONFIG[
|
|
174
|
+
"ping_timeout"
|
|
175
|
+
], # 20 seconds from config
|
|
176
|
+
max_http_buffer_size=CONNECTION_CONFIG[
|
|
177
|
+
"max_http_buffer_size"
|
|
178
|
+
], # 100MB from config
|
|
169
179
|
)
|
|
170
180
|
|
|
171
181
|
# Create aiohttp application
|
|
172
182
|
self.app = web.Application()
|
|
173
183
|
self.sio.attach(self.app)
|
|
174
184
|
|
|
185
|
+
# CRITICAL: Register event handlers BEFORE starting the server
|
|
186
|
+
# This ensures handlers are ready when clients connect
|
|
187
|
+
if self.main_server and hasattr(self.main_server, "_register_events_async"):
|
|
188
|
+
self.logger.info(
|
|
189
|
+
"Registering Socket.IO event handlers before server start"
|
|
190
|
+
)
|
|
191
|
+
await self.main_server._register_events_async()
|
|
192
|
+
else:
|
|
193
|
+
self.logger.warning("Main server not available for event registration")
|
|
194
|
+
|
|
175
195
|
# Setup HTTP API endpoints for receiving events from hook handlers
|
|
176
196
|
self._setup_http_api()
|
|
177
197
|
|
|
@@ -196,9 +216,16 @@ class SocketIOServerCore:
|
|
|
196
216
|
if self.static_path:
|
|
197
217
|
self.logger.info(f"Serving static files from: {self.static_path}")
|
|
198
218
|
|
|
199
|
-
#
|
|
200
|
-
|
|
201
|
-
|
|
219
|
+
# Conditionally start heartbeat task based on configuration
|
|
220
|
+
from ....config.socketio_config import CONNECTION_CONFIG
|
|
221
|
+
|
|
222
|
+
if CONNECTION_CONFIG.get("enable_extra_heartbeat", False):
|
|
223
|
+
self.heartbeat_task = asyncio.create_task(self._heartbeat_loop())
|
|
224
|
+
self.logger.info("Started system heartbeat task")
|
|
225
|
+
else:
|
|
226
|
+
self.logger.info(
|
|
227
|
+
"System heartbeat disabled (using Socket.IO ping/pong instead)"
|
|
228
|
+
)
|
|
202
229
|
|
|
203
230
|
# Keep the server running
|
|
204
231
|
while self.running:
|
|
@@ -111,7 +111,8 @@ class SocketIOServer(SocketIOServiceInterface):
|
|
|
111
111
|
flush=True,
|
|
112
112
|
)
|
|
113
113
|
|
|
114
|
-
# Start the core server
|
|
114
|
+
# CRITICAL: Start the core server first to create sio instance
|
|
115
|
+
# Event handlers will be registered inside _start_server before accepting connections
|
|
115
116
|
self.core.start_sync()
|
|
116
117
|
|
|
117
118
|
# Initialize connection manager for robust connection tracking
|
|
@@ -163,8 +164,9 @@ class SocketIOServer(SocketIOServiceInterface):
|
|
|
163
164
|
self.connection_manager.start_health_monitoring(), self.core.loop
|
|
164
165
|
)
|
|
165
166
|
|
|
166
|
-
# Register events
|
|
167
|
-
self.
|
|
167
|
+
# Register events if not already done in async context
|
|
168
|
+
if self.core.sio and not self.event_registry:
|
|
169
|
+
self._register_events()
|
|
168
170
|
|
|
169
171
|
# Setup EventBus integration
|
|
170
172
|
# WHY: This connects the EventBus to the Socket.IO server, allowing
|
|
@@ -173,35 +175,64 @@ class SocketIOServer(SocketIOServiceInterface):
|
|
|
173
175
|
f"[{datetime.now().isoformat()}] Setting up EventBus integration...",
|
|
174
176
|
flush=True,
|
|
175
177
|
)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
+
|
|
179
|
+
# CRITICAL: Ensure broadcaster is fully initialized before setting up EventBus
|
|
180
|
+
# The relay needs the broadcaster to be ready to relay events
|
|
181
|
+
if not self.broadcaster:
|
|
182
|
+
self.logger.error(
|
|
183
|
+
"Broadcaster not initialized - cannot setup EventBus integration"
|
|
184
|
+
)
|
|
185
|
+
print(
|
|
186
|
+
f"[{datetime.now().isoformat()}] ERROR: Broadcaster not initialized",
|
|
187
|
+
flush=True,
|
|
188
|
+
)
|
|
189
|
+
else:
|
|
178
190
|
print(
|
|
179
|
-
f"[{datetime.now().isoformat()}]
|
|
191
|
+
f"[{datetime.now().isoformat()}] Broadcaster ready, proceeding with EventBus setup",
|
|
180
192
|
flush=True,
|
|
181
193
|
)
|
|
182
194
|
|
|
183
|
-
|
|
184
|
-
self.
|
|
195
|
+
try:
|
|
196
|
+
self.eventbus_integration = EventBusIntegration(self)
|
|
185
197
|
print(
|
|
186
|
-
f"[{datetime.now().isoformat()}]
|
|
198
|
+
f"[{datetime.now().isoformat()}] EventBusIntegration instance created",
|
|
187
199
|
flush=True,
|
|
188
200
|
)
|
|
189
|
-
|
|
190
|
-
self.
|
|
201
|
+
|
|
202
|
+
if self.eventbus_integration.setup(self.port):
|
|
203
|
+
self.logger.info("EventBus integration setup successful")
|
|
204
|
+
print(
|
|
205
|
+
f"[{datetime.now().isoformat()}] EventBus integration setup successful",
|
|
206
|
+
flush=True,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Verify relay is connected and has broadcaster
|
|
210
|
+
if (
|
|
211
|
+
hasattr(self.eventbus_integration, "relay")
|
|
212
|
+
and self.eventbus_integration.relay
|
|
213
|
+
):
|
|
214
|
+
relay_stats = self.eventbus_integration.relay.get_stats()
|
|
215
|
+
self.logger.info(f"EventBus relay stats: {relay_stats}")
|
|
216
|
+
print(
|
|
217
|
+
f"[{datetime.now().isoformat()}] EventBus relay stats: {relay_stats}",
|
|
218
|
+
flush=True,
|
|
219
|
+
)
|
|
220
|
+
else:
|
|
221
|
+
self.logger.warning("EventBus integration setup failed or disabled")
|
|
222
|
+
print(
|
|
223
|
+
f"[{datetime.now().isoformat()}] EventBus integration setup failed or disabled",
|
|
224
|
+
flush=True,
|
|
225
|
+
)
|
|
226
|
+
except Exception as e:
|
|
227
|
+
self.logger.error(f"Failed to setup EventBus integration: {e}")
|
|
191
228
|
print(
|
|
192
|
-
f"[{datetime.now().isoformat()}]
|
|
229
|
+
f"[{datetime.now().isoformat()}] Failed to setup EventBus integration: {e}",
|
|
193
230
|
flush=True,
|
|
194
231
|
)
|
|
195
|
-
|
|
196
|
-
self.logger.error(f"Failed to setup EventBus integration: {e}")
|
|
197
|
-
print(
|
|
198
|
-
f"[{datetime.now().isoformat()}] Failed to setup EventBus integration: {e}",
|
|
199
|
-
flush=True,
|
|
200
|
-
)
|
|
201
|
-
import traceback
|
|
232
|
+
import traceback
|
|
202
233
|
|
|
203
|
-
|
|
204
|
-
|
|
234
|
+
traceback.print_exc()
|
|
235
|
+
self.eventbus_integration = None
|
|
205
236
|
|
|
206
237
|
# Update running state
|
|
207
238
|
self.running = self.core.running
|
|
@@ -252,6 +283,12 @@ class SocketIOServer(SocketIOServiceInterface):
|
|
|
252
283
|
handlers in a modular way. Each handler focuses on a specific domain,
|
|
253
284
|
reducing complexity and improving maintainability.
|
|
254
285
|
"""
|
|
286
|
+
if not self.core.sio:
|
|
287
|
+
self.logger.error(
|
|
288
|
+
"Cannot register events - Socket.IO server not initialized"
|
|
289
|
+
)
|
|
290
|
+
return
|
|
291
|
+
|
|
255
292
|
# Initialize the event handler registry
|
|
256
293
|
self.event_registry = EventHandlerRegistry(self)
|
|
257
294
|
self.event_registry.initialize()
|
|
@@ -265,6 +302,31 @@ class SocketIOServer(SocketIOServiceInterface):
|
|
|
265
302
|
|
|
266
303
|
self.logger.info("All Socket.IO events registered via handler system")
|
|
267
304
|
|
|
305
|
+
async def _register_events_async(self):
|
|
306
|
+
"""Async version of event registration for calling from async context.
|
|
307
|
+
|
|
308
|
+
WHY: This allows us to register events from within the async _start_server
|
|
309
|
+
method before the server starts accepting connections.
|
|
310
|
+
"""
|
|
311
|
+
if not self.core.sio:
|
|
312
|
+
self.logger.error(
|
|
313
|
+
"Cannot register events - Socket.IO server not initialized"
|
|
314
|
+
)
|
|
315
|
+
return
|
|
316
|
+
|
|
317
|
+
# Initialize the event handler registry
|
|
318
|
+
self.event_registry = EventHandlerRegistry(self)
|
|
319
|
+
self.event_registry.initialize()
|
|
320
|
+
|
|
321
|
+
# Register all events from all handlers
|
|
322
|
+
self.event_registry.register_all_events()
|
|
323
|
+
|
|
324
|
+
# Keep handler instances for HTTP endpoint compatibility
|
|
325
|
+
self.file_handler = self.event_registry.get_handler(FileEventHandler)
|
|
326
|
+
self.git_handler = self.event_registry.get_handler(GitEventHandler)
|
|
327
|
+
|
|
328
|
+
self.logger.info("All Socket.IO events registered via handler system (async)")
|
|
329
|
+
|
|
268
330
|
# Delegate broadcasting methods to the broadcaster
|
|
269
331
|
def broadcast_event(self, event_type: str, data: Dict[str, Any]):
|
|
270
332
|
"""Broadcast an event to all connected clients."""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=toytnNjkIKPgQaGwDqQdC1rpNTAdSEc6Vja50d7Ovug,4
|
|
2
|
-
claude_mpm/VERSION,sha256=
|
|
2
|
+
claude_mpm/VERSION,sha256=9_cjWZcnvxfj2ollTh4zoGcoRfdahIWrvGWSvtEA1e4,6
|
|
3
3
|
claude_mpm/__init__.py,sha256=lyTZAYGH4DTaFGLRNWJKk5Q5oTjzN5I6AXmfVX-Jff0,1512
|
|
4
4
|
claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
|
|
5
5
|
claude_mpm/constants.py,sha256=5-k9ZbfDRe3WpGfHx3R0iTXokuOaZY-NcWcx1xkLTws,5678
|
|
@@ -9,6 +9,7 @@ claude_mpm/agents/BASE_AGENT_TEMPLATE.md,sha256=aK9qxS1FRpm_8VaB5GI2I6YA9Wr8dGHu
|
|
|
9
9
|
claude_mpm/agents/BASE_PM.md,sha256=OMWebRWA4ZDk9z3H9DxvksNYqfG4ZExFVNF2vUirUBo,9299
|
|
10
10
|
claude_mpm/agents/INSTRUCTIONS.md,sha256=bTTlGVJwcYjdQ51PMsJXPW6FIEg15wItyHY2u0BYJSU,10777
|
|
11
11
|
claude_mpm/agents/MEMORY.md,sha256=EeY1MwnrhaAij5_pUCt_lcOc2-coo3EYkWRyRbPyJmM,3181
|
|
12
|
+
claude_mpm/agents/OUTPUT_STYLE.md,sha256=HZ5GhiTwMWj9G_uefmMguH4Ukhs2CQqa8u5FQ6HBrbo,2538
|
|
12
13
|
claude_mpm/agents/WORKFLOW.md,sha256=y-tYNbSqJ4D4ND5TMc5bvcnq_mYw3Gwq9bnpz-LzwvQ,7972
|
|
13
14
|
claude_mpm/agents/__init__.py,sha256=jRFxvV_DIZ-NdENa-703Xu3YpwvlQj6yv-mQ6FgmldM,3220
|
|
14
15
|
claude_mpm/agents/agent-template.yaml,sha256=mRlz5Yd0SmknTeoJWgFkZXzEF5T7OmGBJGs2-KPT93k,1969
|
|
@@ -22,8 +23,8 @@ claude_mpm/agents/frontmatter_validator.py,sha256=GiCxr13b-SFwvZNbNHDO0lFH9dFhsQ
|
|
|
22
23
|
claude_mpm/agents/system_agent_config.py,sha256=HBDrtRld1ruPqrThA0j4vtMr4cBt0fT7qjDeCR79bps,24105
|
|
23
24
|
claude_mpm/agents/schema/agent_schema.json,sha256=3p-_vcEAz5Py0ik7LPSJB9CQyE9L_zHhC82J0eCfn78,8784
|
|
24
25
|
claude_mpm/agents/templates/__init__.py,sha256=kghxAWs3KvcAA9Esk3NI7caumYgW6fiW8vRO1-MEndU,2735
|
|
25
|
-
claude_mpm/agents/templates/agent-manager.json,sha256=
|
|
26
|
-
claude_mpm/agents/templates/agent-manager.md,sha256=
|
|
26
|
+
claude_mpm/agents/templates/agent-manager.json,sha256=nX7kfxb1AjbUXqi2tHKgNnWVVB-eLRUHV3O7gqHxjEk,628
|
|
27
|
+
claude_mpm/agents/templates/agent-manager.md,sha256=rWQ7MREoMdQtJhMujEPVYud6N-fGvicMuBvYIdRo22w,19418
|
|
27
28
|
claude_mpm/agents/templates/api_qa.json,sha256=hTdeNOgA2tzADCb2V9ExguFSvAv267yQYqa26AnOQHk,5786
|
|
28
29
|
claude_mpm/agents/templates/code_analyzer.json,sha256=UOTXl6VTmzx1OoF5M4Bc9lQGriLf6Jq84rz30J77tEM,4718
|
|
29
30
|
claude_mpm/agents/templates/data_engineer.json,sha256=rP3ffuaHwe0xGVpXShhVHTn1jEVMV2aAlnNGZL8j3jc,5629
|
|
@@ -55,8 +56,8 @@ claude_mpm/cli/commands/aggregate.py,sha256=rLwZxXmIyTPuDUYKTooVtTgiW4mU3vw4_383
|
|
|
55
56
|
claude_mpm/cli/commands/cleanup.py,sha256=c4QyAs9odx7__rSM9RDy2r9iwPlrfeIzx2vINbl7WaA,19694
|
|
56
57
|
claude_mpm/cli/commands/cleanup_orphaned_agents.py,sha256=JR8crvgrz7Sa6d-SI-gKywok5S9rwc_DzDVk_h85sVs,4467
|
|
57
58
|
claude_mpm/cli/commands/config.py,sha256=Yfi8WO-10_MYz2QipFw-yEzVvHKNQ6iSQXeyW5J85Cg,18559
|
|
58
|
-
claude_mpm/cli/commands/configure.py,sha256=
|
|
59
|
-
claude_mpm/cli/commands/configure_tui.py,sha256=
|
|
59
|
+
claude_mpm/cli/commands/configure.py,sha256=SBWh4ZMxEvB8yIXk4SiJjkcZ845XvYXVhxwqNLtemJg,53003
|
|
60
|
+
claude_mpm/cli/commands/configure_tui.py,sha256=dTghSkJqvY1xdbDyCeNy5gxmyQOVCCr01cH_4aUVe4I,66929
|
|
60
61
|
claude_mpm/cli/commands/doctor.py,sha256=bOZzDNxEMNMZYrJnu_V82tyZ12r5FiBRQNLVfSVvRIQ,5774
|
|
61
62
|
claude_mpm/cli/commands/info.py,sha256=_hWH7uNv9VLO0eZh9Ua6qc5L1Z66kYj9ATzU4Q8UkSM,7377
|
|
62
63
|
claude_mpm/cli/commands/mcp.py,sha256=f4PmzAt89cmXXHBJAul2nFh7-EStDY97_J4vaL690CE,7029
|
|
@@ -76,7 +77,7 @@ claude_mpm/cli/parsers/agent_manager_parser.py,sha256=8HuGpTnHSOnTOqOHriBTzi8EzK
|
|
|
76
77
|
claude_mpm/cli/parsers/agents_parser.py,sha256=DxAZMotptyaJbROqbRbTipOKLLJ96ATrXhwiFK6Dbm0,5450
|
|
77
78
|
claude_mpm/cli/parsers/base_parser.py,sha256=eIh4IOO8eSV971Z3paYmq10CBLRfm9ionv7Z1Hxg4FI,12346
|
|
78
79
|
claude_mpm/cli/parsers/config_parser.py,sha256=wp6NbV8_p9txP28MXFcQrri0JDIfGFM7u4aJbYJXcYQ,2699
|
|
79
|
-
claude_mpm/cli/parsers/configure_parser.py,sha256=
|
|
80
|
+
claude_mpm/cli/parsers/configure_parser.py,sha256=cg3VXrnSqi9QLhMihJXeKDjtp1sS5jSHZNM_prgm0S4,4598
|
|
80
81
|
claude_mpm/cli/parsers/mcp_parser.py,sha256=zW4wClYOGf_o8yRediJkQRxgta2RI6S3IG_QDgAkp-k,5992
|
|
81
82
|
claude_mpm/cli/parsers/memory_parser.py,sha256=ZwCDxJEgp-w03L-1tZsWTgisiwamP42s424bA5bvDJc,4760
|
|
82
83
|
claude_mpm/cli/parsers/monitor_parser.py,sha256=Go78VOFQCts2fouv33tKfd303w0mVPpJiuBbRBGK5x0,4525
|
|
@@ -95,7 +96,7 @@ claude_mpm/config/__init__.py,sha256=V2dyJQ8_gVCpNiCg8zYTQqE1RSeON5Zm8n5Ndkqhp1g
|
|
|
95
96
|
claude_mpm/config/agent_config.py,sha256=d_cHE4HMkeZZrGjDGpBP655llV64p_E8DRDPPdsO1jg,14829
|
|
96
97
|
claude_mpm/config/experimental_features.py,sha256=ma-Va7CVqOYrUEGZW6A4gdMRLHOpovHf8pHgP_3-xr0,7481
|
|
97
98
|
claude_mpm/config/paths.py,sha256=Dl35_QF0kfC2I6Fy7ETcNjz7jlumNGt45qlRKqsPJrk,7611
|
|
98
|
-
claude_mpm/config/socketio_config.py,sha256=
|
|
99
|
+
claude_mpm/config/socketio_config.py,sha256=Kv5vxQ-UAKAFsa_FukkrujnBzFAwOi2KbEa3mFX3UXQ,11343
|
|
99
100
|
claude_mpm/core/__init__.py,sha256=QhEX_NpiCprUp87bV75FnMapblMeqC5soNVJXVvZObc,887
|
|
100
101
|
claude_mpm/core/agent_name_normalizer.py,sha256=_h92sTPltmvqevCjdKQ7EsOz-CAm1-hd8GOubWjuRgw,8907
|
|
101
102
|
claude_mpm/core/agent_registry.py,sha256=cPQsOSIyrspr3KpS-P9MQ6Dv_BLXa9BWhs9RM0iu4C4,18798
|
|
@@ -178,7 +179,7 @@ claude_mpm/dashboard/static/dist/components/working-directory.js,sha256=7V1pBeux
|
|
|
178
179
|
claude_mpm/dashboard/static/js/connection-manager.js,sha256=IJrtihUCQqkECXhiqy53vAJIdxNp7pJVIsV2ocos3As,17981
|
|
179
180
|
claude_mpm/dashboard/static/js/dashboard.js,sha256=bacYhLFaxQIVOeRaUZProQ0Px6CeZFZmgnwZoHjKWls,71535
|
|
180
181
|
claude_mpm/dashboard/static/js/extension-error-handler.js,sha256=DZHrJ3gbfv4nsjmZpNMj-Sc3GKjVJ5ds8lgoaLRnq5I,6274
|
|
181
|
-
claude_mpm/dashboard/static/js/socket-client.js,sha256=
|
|
182
|
+
claude_mpm/dashboard/static/js/socket-client.js,sha256=eXVTR3EQ6uK9PEjjmwT_8EpPDPPpCRbWiNBK5fS5CJk,37436
|
|
182
183
|
claude_mpm/dashboard/static/js/components/agent-hierarchy.js,sha256=Xihxog_vJrk8VBEkDogV_wbye2GIFWmH71VQ1lETOHk,28243
|
|
183
184
|
claude_mpm/dashboard/static/js/components/agent-inference.js,sha256=RUVZ_fLOyDkHYjrROen_Pzzay79Bh29eXp_GRIPbIRg,37493
|
|
184
185
|
claude_mpm/dashboard/static/js/components/build-tracker.js,sha256=IBfKpoSKWD5QMPN4tOZl-E84Q3QADYVsZ76ickrKW8E,11485
|
|
@@ -212,11 +213,12 @@ claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py,sha256=IZKE3cJok_gb4UGFEt
|
|
|
212
213
|
claude_mpm/hooks/claude_hooks/hook_handler_original.py,sha256=AOcGOf2WiA_aaRsaENKBvaj3Vi_UzeL_zaEgN3zxCrk,42964
|
|
213
214
|
claude_mpm/hooks/claude_hooks/hook_handler_refactored.py,sha256=e8phCM18f-IcovV9_xVNYSV8nndVKdzmFJa-xjKGkq8,12983
|
|
214
215
|
claude_mpm/hooks/claude_hooks/hook_wrapper.sh,sha256=4lG3TlLVoVfTJipPj1X_ICUlS-KpnkbUp1U3oSq80Bw,2476
|
|
216
|
+
claude_mpm/hooks/claude_hooks/installer.py,sha256=IZ95d0lxRneUYQ3hIeHtzzDsEc-DqLaiwcwGEEqg-7A,15684
|
|
215
217
|
claude_mpm/hooks/claude_hooks/memory_integration.py,sha256=TXLavDM9eEoakPX_n2WtnfXyqGn80N-xgAvcYgvoW8s,8832
|
|
216
218
|
claude_mpm/hooks/claude_hooks/response_tracking.py,sha256=4RcM54LyYeINf3A_toaSOPuD3oXS6jZtiRstHxgSOao,14990
|
|
217
219
|
claude_mpm/hooks/claude_hooks/tool_analysis.py,sha256=3_o2PP9D7wEMwLriCtIBOw0cj2fSZfepN7lI4P1meSQ,7862
|
|
218
220
|
claude_mpm/hooks/claude_hooks/services/__init__.py,sha256=OIYOKsUNw1BHYawOCp-KFK5kmQKuj92cCqCEPO0nwo0,585
|
|
219
|
-
claude_mpm/hooks/claude_hooks/services/connection_manager.py,sha256=
|
|
221
|
+
claude_mpm/hooks/claude_hooks/services/connection_manager.py,sha256=brj_FrSRwusbzyQo8a8DRGruTRqucfNWZNSDiNkbLe8,8290
|
|
220
222
|
claude_mpm/hooks/claude_hooks/services/connection_manager_http.py,sha256=-DZ2seh1tpdo_RQPo5qkkJBcbjEkSpIFWOMMij1V0So,7686
|
|
221
223
|
claude_mpm/hooks/claude_hooks/services/duplicate_detector.py,sha256=Fh9LmEMsVmQM9t0U1v2l_fuBwvNpVkl_0EF8Wu5KLHQ,3882
|
|
222
224
|
claude_mpm/hooks/claude_hooks/services/state_manager.py,sha256=c7OldfemaMU37YGJxgO2uEcTOuPc-C80SRhzEH07j7I,11072
|
|
@@ -258,7 +260,7 @@ claude_mpm/services/version_service.py,sha256=Ql2HKB9OoHGdqkfWyFFLSSVBwShap0dFIj
|
|
|
258
260
|
claude_mpm/services/agents/__init__.py,sha256=8cRLDOXq_CGH3uVl6Uk816wsx7VY8HSDOYms2MPaFBA,2175
|
|
259
261
|
claude_mpm/services/agents/agent_builder.py,sha256=l5scGcTeJcGwe-i1VUcrzWEwub_mcruZBn6Q51ZDaCM,14803
|
|
260
262
|
claude_mpm/services/agents/deployment/__init__.py,sha256=iprW-Ww3LBtWu9pVFjAX45_CswfSqnPMoG0QoFPd1Dg,539
|
|
261
|
-
claude_mpm/services/agents/deployment/agent_config_provider.py,sha256=
|
|
263
|
+
claude_mpm/services/agents/deployment/agent_config_provider.py,sha256=gtQcbGr0GspZYplbeRkGXd3BAXl3_pWhKSsbfiSVTww,15234
|
|
262
264
|
claude_mpm/services/agents/deployment/agent_configuration_manager.py,sha256=5nf69hfo7lUa3_55sDcU5WfpzBtOZCMSTPYGr2dlIdY,12173
|
|
263
265
|
claude_mpm/services/agents/deployment/agent_definition_factory.py,sha256=DaJ__b3-ADinfd-qNnW6LKWfclOaZbkBBcfuHgqlUic,2697
|
|
264
266
|
claude_mpm/services/agents/deployment/agent_deployment.py,sha256=6YFg1ZcAMI_cb7xGhSm0e3qdPOrVNoQ_-o1qoc_PM2k,35514
|
|
@@ -385,13 +387,13 @@ claude_mpm/services/diagnostics/checks/common_issues_check.py,sha256=Yi73_1yGNcQ
|
|
|
385
387
|
claude_mpm/services/diagnostics/checks/configuration_check.py,sha256=mgqFsyr4W73gFGMF7kz5u4lloUMhTty5BHuErf0I0Uo,11176
|
|
386
388
|
claude_mpm/services/diagnostics/checks/filesystem_check.py,sha256=V5HoHDYlSuoK2lFv946Jhd81LrA0om71NWugnRxFvSE,8296
|
|
387
389
|
claude_mpm/services/diagnostics/checks/installation_check.py,sha256=beGk3r-Kwdy-DaodBl-7z0zA1hqLwBNNxAhYkDw7Qr8,16064
|
|
388
|
-
claude_mpm/services/diagnostics/checks/instructions_check.py,sha256=
|
|
390
|
+
claude_mpm/services/diagnostics/checks/instructions_check.py,sha256=6AgotHjLi2QgCshDfXAK5Bb-eTWU1SfWBUwpjUSSi9E,16317
|
|
389
391
|
claude_mpm/services/diagnostics/checks/mcp_check.py,sha256=_eM210SIyHwAcWi1AxUeRoessxumpTrSeVdHVJK5ja0,12191
|
|
390
392
|
claude_mpm/services/diagnostics/checks/monitor_check.py,sha256=NUx5G1yjHWlukZmwhUz4o8STRWgsQEx01YjIMReNC0A,10096
|
|
391
393
|
claude_mpm/services/diagnostics/checks/startup_log_check.py,sha256=DrXdml2rHvmhFBdb_sntE3xmwaP_DZIKjdVbCn8Dy7E,12258
|
|
392
394
|
claude_mpm/services/event_bus/__init__.py,sha256=ETCo4a6puIeyVWAv55uCDjjhzNyUwbVAHEcAVkVapx8,688
|
|
393
395
|
claude_mpm/services/event_bus/config.py,sha256=MJdOBK3XgLpW66N81tetThslnKsFIWYtbqRamyTDxlU,4943
|
|
394
|
-
claude_mpm/services/event_bus/direct_relay.py,sha256=
|
|
396
|
+
claude_mpm/services/event_bus/direct_relay.py,sha256=HvI6pSvP-DFZCrUH1gprhQS0rrf3eYAw6rAtyZJXnhE,13490
|
|
395
397
|
claude_mpm/services/event_bus/event_bus.py,sha256=KQ8FpbHGsEVlygZj6CTYgugXL7Ht6KGlf1FAT4WJKEI,11920
|
|
396
398
|
claude_mpm/services/event_bus/relay.py,sha256=yQ6Ow2rOj3dtNtYi2Vh4ToTouo-1eOiigtjnBM2w2Wo,9352
|
|
397
399
|
claude_mpm/services/events/__init__.py,sha256=dna3DFYCxt9Y1jgK-0f2KPlX-jFo4n2dJyy9WKZkNlA,1092
|
|
@@ -495,7 +497,7 @@ claude_mpm/services/socketio/migration_utils.py,sha256=1pK_zGZ8Pd57pCg1O-3gKT8i7
|
|
|
495
497
|
claude_mpm/services/socketio/handlers/__init__.py,sha256=zc1eo5hR5xDtnOZCeX38JNo8j9Vs10kV1cxZF20ZS4A,789
|
|
496
498
|
claude_mpm/services/socketio/handlers/base.py,sha256=DjUODCOLTQSsC_-NP9yr-8g77arawmsRrM5KC06aDmw,4845
|
|
497
499
|
claude_mpm/services/socketio/handlers/connection.py,sha256=sa6Rg5Y9tcf-e4PEb6f4fNhFQcpZ9WbwdiGXmkzlFTs,26781
|
|
498
|
-
claude_mpm/services/socketio/handlers/connection_handler.py,sha256=
|
|
500
|
+
claude_mpm/services/socketio/handlers/connection_handler.py,sha256=DTY0pa--HQu4C6-WCgE1zskvHm3gVuEKWwaSFNBAoec,13287
|
|
499
501
|
claude_mpm/services/socketio/handlers/file.py,sha256=itpPa5OAow5_OXrTOXk0vsyuEYm4iVmxwN9xowy7jiY,8341
|
|
500
502
|
claude_mpm/services/socketio/handlers/git.py,sha256=xIjGGShyVNXzCtJfydbbnFTJhqzXwHLzGhLrqgy0JGQ,37934
|
|
501
503
|
claude_mpm/services/socketio/handlers/hook.py,sha256=JVQufL_u85z3r-n3fnKExuziheJ2lzY6d0GDoUB9iXs,7786
|
|
@@ -504,10 +506,10 @@ claude_mpm/services/socketio/handlers/project.py,sha256=yYqWlPfPanA7zH7dgQnP3EpO
|
|
|
504
506
|
claude_mpm/services/socketio/handlers/registry.py,sha256=f4eELY04c23F0S8A5cxm9PDfSiGFumnfNgg7Ua0TsGU,7946
|
|
505
507
|
claude_mpm/services/socketio/server/__init__.py,sha256=S486w-i-hBo3rNW_AtzxbasEgP32By-uI9zz7hzKz-o,640
|
|
506
508
|
claude_mpm/services/socketio/server/broadcaster.py,sha256=y_D-fDhSD2NZI0cP9wuoB2nlI7VkKjzW_EjVmP-xd5Y,21375
|
|
507
|
-
claude_mpm/services/socketio/server/connection_manager.py,sha256=
|
|
508
|
-
claude_mpm/services/socketio/server/core.py,sha256=
|
|
509
|
+
claude_mpm/services/socketio/server/connection_manager.py,sha256=ovta_Ar9dPskBPTnY4YZtiDAx0PpHQL_1ThTXLpbM4E,21181
|
|
510
|
+
claude_mpm/services/socketio/server/core.py,sha256=yCTky7zBeiz_eLFMPLNwAm-sV0CVornBeIAhxIenkE8,22593
|
|
509
511
|
claude_mpm/services/socketio/server/eventbus_integration.py,sha256=6LkK8W9wTiNd8d9KoAH2IY1b4osyGGgGaJ0DmwIwnVM,7790
|
|
510
|
-
claude_mpm/services/socketio/server/main.py,sha256=
|
|
512
|
+
claude_mpm/services/socketio/server/main.py,sha256=nDkdMF96-PvXD8x69LAFSz-y35u58wVl0UwxSfAapZY,19226
|
|
511
513
|
claude_mpm/services/ticket_services/__init__.py,sha256=I01W25n-tBWwZ0TD-dPA63nqzCU2KnpOvbqeysmaa2E,798
|
|
512
514
|
claude_mpm/services/ticket_services/crud_service.py,sha256=4Ab1HONY219QSdRaLTgRInm6DNJXIUKiihyAree8y8A,11193
|
|
513
515
|
claude_mpm/services/ticket_services/formatter_service.py,sha256=MQ981yaFuvXWUDLpHHiasc8BIFdeIeMS7Us0CgZHJ0A,9101
|
|
@@ -542,9 +544,9 @@ claude_mpm/utils/subprocess_utils.py,sha256=zgiwLqh_17WxHpySvUPH65pb4bzIeUGOAYUJ
|
|
|
542
544
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
|
543
545
|
claude_mpm/validation/agent_validator.py,sha256=3Lo6LK-Mw9IdnL_bd3zl_R6FkgSVDYKUUM7EeVVD3jc,20865
|
|
544
546
|
claude_mpm/validation/frontmatter_validator.py,sha256=u8g4Eyd_9O6ugj7Un47oSGh3kqv4wMkuks2i_CtWRvM,7028
|
|
545
|
-
claude_mpm-4.1.
|
|
546
|
-
claude_mpm-4.1.
|
|
547
|
-
claude_mpm-4.1.
|
|
548
|
-
claude_mpm-4.1.
|
|
549
|
-
claude_mpm-4.1.
|
|
550
|
-
claude_mpm-4.1.
|
|
547
|
+
claude_mpm-4.1.8.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
|
|
548
|
+
claude_mpm-4.1.8.dist-info/METADATA,sha256=aibiLTs5vPDFdsedewGyRvNB8Geo6-89Su9iHskowTU,13386
|
|
549
|
+
claude_mpm-4.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
550
|
+
claude_mpm-4.1.8.dist-info/entry_points.txt,sha256=FDPZgz8JOvD-6iuXY2l9Zbo9zYVRuE4uz4Qr0vLeGOk,471
|
|
551
|
+
claude_mpm-4.1.8.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
|
552
|
+
claude_mpm-4.1.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|