claude-mpm 3.4.6__py3-none-any.whl → 3.4.9__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.
@@ -467,6 +467,7 @@ def _check_socketio_server_running(port, logger):
467
467
 
468
468
  DESIGN DECISION: We try multiple endpoints and connection methods to ensure
469
469
  robust detection. Some servers may be starting up and only partially ready.
470
+ Added retry logic to handle race conditions during server initialization.
470
471
 
471
472
  Args:
472
473
  port: Port number to check
@@ -483,34 +484,50 @@ def _check_socketio_server_running(port, logger):
483
484
  # First, do a basic TCP connection check
484
485
  try:
485
486
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
486
- s.settimeout(1.0)
487
+ s.settimeout(2.0) # Increased from 1.0s for slower connections
487
488
  result = s.connect_ex(('127.0.0.1', port))
488
489
  if result != 0:
489
- logger.debug(f"TCP connection to port {port} failed (not listening)")
490
+ logger.debug(f"TCP connection to port {port} failed (server not started yet)")
490
491
  return False
491
492
  except Exception as e:
492
493
  logger.debug(f"TCP socket check failed for port {port}: {e}")
493
494
  return False
494
495
 
495
- # If TCP connection succeeds, try HTTP health check
496
- try:
497
- response = urllib.request.urlopen(f'http://localhost:{port}/status', timeout=5)
498
-
499
- if response.getcode() == 200:
500
- content = response.read().decode()
501
- logger.debug(f"✅ Socket.IO server health check passed on port {port}")
502
- logger.debug(f"📄 Server response: {content[:100]}...")
503
- return True
504
- else:
505
- logger.debug(f"⚠️ HTTP response code {response.getcode()} from port {port}")
506
- return False
496
+ # If TCP connection succeeds, try HTTP health check with retries
497
+ # WHY: Even when TCP is accepting connections, the HTTP handler may not be ready
498
+ max_retries = 3
499
+ for retry in range(max_retries):
500
+ try:
501
+ response = urllib.request.urlopen(f'http://localhost:{port}/status', timeout=10) # Increased from 5s to 10s
507
502
 
508
- except urllib.error.HTTPError as e:
509
- logger.debug(f"⚠️ HTTP error {e.code} from server on port {port}")
510
- return False
511
- except urllib.error.URLError as e:
512
- logger.debug(f"⚠️ URL error connecting to port {port}: {e.reason}")
513
- return False
503
+ if response.getcode() == 200:
504
+ content = response.read().decode()
505
+ logger.debug(f"✅ Socket.IO server health check passed on port {port} (attempt {retry + 1})")
506
+ logger.debug(f"📄 Server response: {content[:100]}...")
507
+ return True
508
+ else:
509
+ logger.debug(f"⚠️ HTTP response code {response.getcode()} from port {port} (attempt {retry + 1})")
510
+ if retry < max_retries - 1:
511
+ time.sleep(0.5) # Brief pause before retry
512
+
513
+ except urllib.error.HTTPError as e:
514
+ logger.debug(f"⚠️ HTTP error {e.code} from server on port {port} (attempt {retry + 1})")
515
+ if retry < max_retries - 1 and e.code in [404, 503]: # Server starting but not ready
516
+ logger.debug("Server appears to be starting, retrying...")
517
+ time.sleep(0.5)
518
+ continue
519
+ return False
520
+ except urllib.error.URLError as e:
521
+ logger.debug(f"⚠️ URL error connecting to port {port} (attempt {retry + 1}): {e.reason}")
522
+ if retry < max_retries - 1:
523
+ logger.debug("Connection refused - server may still be initializing, retrying...")
524
+ time.sleep(0.5)
525
+ continue
526
+ return False
527
+
528
+ # All retries exhausted
529
+ logger.debug(f"Health check failed after {max_retries} attempts - server not fully ready")
530
+ return False
514
531
 
515
532
  except (ConnectionError, OSError) as e:
516
533
  logger.debug(f"🔌 Connection error checking port {port}: {e}")
@@ -569,13 +586,17 @@ def _start_standalone_socketio_server(port, logger):
569
586
  # 2. Event loop setup (~1s)
570
587
  # 3. aiohttp server binding (~2-5s)
571
588
  # 4. Socket.IO service initialization (~1-3s)
572
- # Total: up to 10 seconds for full readiness
573
- max_attempts = 20 # Increased from 10
574
- initial_delay = 0.5 # seconds
575
- max_delay = 2.0 # seconds
589
+ # Total: up to 15+ seconds for full readiness (especially on Python 3.13)
590
+ max_attempts = 30 # Increased from 20 to handle Python 3.13 slower initialization
591
+ initial_delay = 1.0 # Increased from 0.5s to give daemon more time to fork
592
+ max_delay = 3.0 # Increased from 2.0s for slower systems
576
593
 
577
594
  logger.info(f"Waiting up to {max_attempts * max_delay} seconds for server to be fully ready...")
578
595
 
596
+ # Give the daemon initial time to fork and start before checking
597
+ logger.debug("Allowing initial daemon startup time...")
598
+ time.sleep(0.5)
599
+
579
600
  for attempt in range(max_attempts):
580
601
  # Progressive delay - start fast, then slow down for socket binding
581
602
  if attempt < 5:
@@ -596,9 +617,14 @@ def _start_standalone_socketio_server(port, logger):
596
617
  else:
597
618
  logger.debug(f"Server not yet accepting connections on attempt {attempt + 1}")
598
619
 
599
- logger.error(f"❌ Socket.IO server failed to start properly on port {port} after {max_attempts} attempts")
600
- logger.error(f"💡 This may indicate a port conflict or dependency issue")
601
- logger.error(f"🔧 Try a different port with --websocket-port or check for conflicts")
620
+ logger.error(f"❌ Socket.IO server health check failed after {max_attempts} attempts ({max_attempts * max_delay:.1f}s)")
621
+ logger.warning(f"⏱️ Server may still be starting - initialization can take 15+ seconds on some systems")
622
+ logger.warning(f"💡 The daemon process might be running but not yet accepting HTTP connections")
623
+ logger.error(f"🔧 Troubleshooting steps:")
624
+ logger.error(f" - Wait a few more seconds and try again")
625
+ logger.error(f" - Check for port conflicts: lsof -i :{port}")
626
+ logger.error(f" - Try a different port with --websocket-port")
627
+ logger.error(f" - Verify dependencies: pip install python-socketio aiohttp")
602
628
  return False
603
629
 
604
630
  except Exception as e:
@@ -184,12 +184,8 @@ class ClaudeRunner:
184
184
  self.logger.warning(f"Failed to connect to Socket.IO server: {e}")
185
185
  self.websocket_server = None
186
186
 
187
- # Get version
188
- try:
189
- from claude_mpm import __version__
190
- version_str = f"v{__version__}"
191
- except:
192
- version_str = "v0.0.0"
187
+ # Get version with robust fallback mechanisms
188
+ version_str = self._get_version()
193
189
 
194
190
  # Print styled welcome box
195
191
  print("\033[32m╭───────────────────────────────────────────────────╮\033[0m")
@@ -750,6 +746,74 @@ class ClaudeRunner:
750
746
  except Exception as e:
751
747
  self.logger.debug(f"Failed to log session event: {e}")
752
748
 
749
+ def _get_version(self) -> str:
750
+ """
751
+ Robust version determination with multiple fallback mechanisms.
752
+
753
+ WHY: The version display is critical for debugging and user experience.
754
+ This implementation ensures we always show the correct version rather than
755
+ defaulting to v0.0.0, even in edge cases where imports might fail.
756
+
757
+ DESIGN DECISION: We try multiple methods in order of preference:
758
+ 1. Package import (__version__) - fastest for normal installations
759
+ 2. importlib.metadata - standard for installed packages
760
+ 3. VERSION file reading - fallback for development environments
761
+ 4. Only then default to v0.0.0 with detailed error logging
762
+
763
+ Returns version string formatted as "vX.Y.Z"
764
+ """
765
+ version = "0.0.0"
766
+ method_used = "default"
767
+
768
+ # Method 1: Try package import (fastest, most common)
769
+ try:
770
+ from claude_mpm import __version__
771
+ version = __version__
772
+ method_used = "package_import"
773
+ self.logger.debug(f"Version obtained via package import: {version}")
774
+ except ImportError as e:
775
+ self.logger.debug(f"Package import failed: {e}")
776
+ except Exception as e:
777
+ self.logger.warning(f"Unexpected error in package import: {e}")
778
+
779
+ # Method 2: Try importlib.metadata (standard for installed packages)
780
+ if version == "0.0.0":
781
+ try:
782
+ import importlib.metadata
783
+ version = importlib.metadata.version('claude-mpm')
784
+ method_used = "importlib_metadata"
785
+ self.logger.debug(f"Version obtained via importlib.metadata: {version}")
786
+ except importlib.metadata.PackageNotFoundError:
787
+ self.logger.debug("Package not found in importlib.metadata (likely development install)")
788
+ except ImportError:
789
+ self.logger.debug("importlib.metadata not available (Python < 3.8)")
790
+ except Exception as e:
791
+ self.logger.warning(f"Unexpected error in importlib.metadata: {e}")
792
+
793
+ # Method 3: Try reading VERSION file directly (development fallback)
794
+ if version == "0.0.0":
795
+ try:
796
+ # Calculate path relative to this file
797
+ version_file = Path(__file__).parent.parent.parent.parent / "VERSION"
798
+ if version_file.exists():
799
+ version = version_file.read_text().strip()
800
+ method_used = "version_file"
801
+ self.logger.debug(f"Version obtained via VERSION file: {version}")
802
+ else:
803
+ self.logger.debug(f"VERSION file not found at: {version_file}")
804
+ except Exception as e:
805
+ self.logger.warning(f"Failed to read VERSION file: {e}")
806
+
807
+ # Log final result
808
+ if version == "0.0.0":
809
+ self.logger.error(
810
+ "All version detection methods failed. This indicates a packaging or installation issue."
811
+ )
812
+ else:
813
+ self.logger.debug(f"Final version: {version} (method: {method_used})")
814
+
815
+ return f"v{version}"
816
+
753
817
  def _register_memory_hooks(self):
754
818
  """Register memory integration hooks with the hook service.
755
819
 
@@ -184,12 +184,8 @@ class ClaudeRunner:
184
184
  self.logger.warning(f"Failed to connect to Socket.IO server: {e}")
185
185
  self.websocket_server = None
186
186
 
187
- # Get version
188
- try:
189
- from claude_mpm import __version__
190
- version_str = f"v{__version__}"
191
- except:
192
- version_str = "v0.0.0"
187
+ # Get version with robust fallback mechanisms
188
+ version_str = self._get_version()
193
189
 
194
190
  # Print styled welcome box
195
191
  print("\033[32m╭───────────────────────────────────────────────────╮\033[0m")
@@ -750,6 +746,74 @@ class ClaudeRunner:
750
746
  except Exception as e:
751
747
  self.logger.debug(f"Failed to log session event: {e}")
752
748
 
749
+ def _get_version(self) -> str:
750
+ """
751
+ Robust version determination with multiple fallback mechanisms.
752
+
753
+ WHY: The version display is critical for debugging and user experience.
754
+ This implementation ensures we always show the correct version rather than
755
+ defaulting to v0.0.0, even in edge cases where imports might fail.
756
+
757
+ DESIGN DECISION: We try multiple methods in order of preference:
758
+ 1. Package import (__version__) - fastest for normal installations
759
+ 2. importlib.metadata - standard for installed packages
760
+ 3. VERSION file reading - fallback for development environments
761
+ 4. Only then default to v0.0.0 with detailed error logging
762
+
763
+ Returns version string formatted as "vX.Y.Z"
764
+ """
765
+ version = "0.0.0"
766
+ method_used = "default"
767
+
768
+ # Method 1: Try package import (fastest, most common)
769
+ try:
770
+ from claude_mpm import __version__
771
+ version = __version__
772
+ method_used = "package_import"
773
+ self.logger.debug(f"Version obtained via package import: {version}")
774
+ except ImportError as e:
775
+ self.logger.debug(f"Package import failed: {e}")
776
+ except Exception as e:
777
+ self.logger.warning(f"Unexpected error in package import: {e}")
778
+
779
+ # Method 2: Try importlib.metadata (standard for installed packages)
780
+ if version == "0.0.0":
781
+ try:
782
+ import importlib.metadata
783
+ version = importlib.metadata.version('claude-mpm')
784
+ method_used = "importlib_metadata"
785
+ self.logger.debug(f"Version obtained via importlib.metadata: {version}")
786
+ except importlib.metadata.PackageNotFoundError:
787
+ self.logger.debug("Package not found in importlib.metadata (likely development install)")
788
+ except ImportError:
789
+ self.logger.debug("importlib.metadata not available (Python < 3.8)")
790
+ except Exception as e:
791
+ self.logger.warning(f"Unexpected error in importlib.metadata: {e}")
792
+
793
+ # Method 3: Try reading VERSION file directly (development fallback)
794
+ if version == "0.0.0":
795
+ try:
796
+ # Calculate path relative to this file
797
+ version_file = Path(__file__).parent.parent.parent.parent / "VERSION"
798
+ if version_file.exists():
799
+ version = version_file.read_text().strip()
800
+ method_used = "version_file"
801
+ self.logger.debug(f"Version obtained via VERSION file: {version}")
802
+ else:
803
+ self.logger.debug(f"VERSION file not found at: {version_file}")
804
+ except Exception as e:
805
+ self.logger.warning(f"Failed to read VERSION file: {e}")
806
+
807
+ # Log final result
808
+ if version == "0.0.0":
809
+ self.logger.error(
810
+ "All version detection methods failed. This indicates a packaging or installation issue."
811
+ )
812
+ else:
813
+ self.logger.debug(f"Final version: {version} (method: {method_used})")
814
+
815
+ return f"v{version}"
816
+
753
817
  def _register_memory_hooks(self):
754
818
  """Register memory integration hooks with the hook service.
755
819
 
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Pure Python daemon management for Socket.IO server.
4
+ No external dependencies required.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import time
10
+ import signal
11
+ import subprocess
12
+ import psutil
13
+ import json
14
+ from pathlib import Path
15
+
16
+ # Handle imports for both development and installed scenarios
17
+ script_dir = Path(__file__).parent
18
+ try:
19
+ # When installed as package, this should work directly
20
+ from claude_mpm.services.socketio_server import SocketIOServer
21
+ except ImportError:
22
+ # When in development, add src to path
23
+ project_root = script_dir.parent.parent.parent # from scripts -> claude_mpm -> src -> project_root
24
+ src_path = project_root / "src"
25
+ if src_path.exists():
26
+ sys.path.insert(0, str(src_path))
27
+ from claude_mpm.services.socketio_server import SocketIOServer
28
+
29
+ PID_FILE = Path.home() / ".claude-mpm" / "socketio-server.pid"
30
+ LOG_FILE = Path.home() / ".claude-mpm" / "socketio-server.log"
31
+
32
+ def ensure_dirs():
33
+ """Ensure required directories exist."""
34
+ PID_FILE.parent.mkdir(parents=True, exist_ok=True)
35
+
36
+ def is_running():
37
+ """Check if server is already running."""
38
+ if not PID_FILE.exists():
39
+ return False
40
+
41
+ try:
42
+ with open(PID_FILE) as f:
43
+ pid = int(f.read().strip())
44
+
45
+ # Check if process exists
46
+ process = psutil.Process(pid)
47
+ return process.is_running()
48
+ except (ValueError, psutil.NoSuchProcess, psutil.AccessDenied):
49
+ # Clean up stale PID file
50
+ PID_FILE.unlink(missing_ok=True)
51
+ return False
52
+
53
+ def start_server():
54
+ """Start the Socket.IO server as a daemon with conflict detection."""
55
+ if is_running():
56
+ print("Socket.IO daemon server is already running.")
57
+ print(f"Use '{__file__} status' for details")
58
+ return
59
+
60
+ # Check for HTTP-managed server conflict
61
+ try:
62
+ import requests
63
+ response = requests.get("http://localhost:8765/health", timeout=1.0)
64
+ if response.status_code == 200:
65
+ data = response.json()
66
+ if 'server_id' in data:
67
+ print(f"⚠️ HTTP-managed server already running: {data.get('server_id')}")
68
+ print(f" Stop it first: socketio_server_manager.py stop --port 8765")
69
+ print(f" Or diagnose: socketio_server_manager.py diagnose")
70
+ return
71
+ except:
72
+ pass # No HTTP server, continue
73
+
74
+ ensure_dirs()
75
+
76
+ # Fork to create daemon
77
+ pid = os.fork()
78
+ if pid > 0:
79
+ # Parent process
80
+ print(f"Starting Socket.IO server (PID: {pid})...")
81
+ with open(PID_FILE, 'w') as f:
82
+ f.write(str(pid))
83
+ print("Socket.IO server started successfully.")
84
+ print(f"PID file: {PID_FILE}")
85
+ print(f"Log file: {LOG_FILE}")
86
+ sys.exit(0)
87
+
88
+ # Child process - become daemon
89
+ os.setsid()
90
+ os.umask(0)
91
+
92
+ # Redirect stdout/stderr to log file
93
+ with open(LOG_FILE, 'a') as log:
94
+ os.dup2(log.fileno(), sys.stdout.fileno())
95
+ os.dup2(log.fileno(), sys.stderr.fileno())
96
+
97
+ # Start server
98
+ print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Starting Socket.IO server...")
99
+ server = SocketIOServer(host="localhost", port=8765)
100
+
101
+ # Handle signals
102
+ def signal_handler(signum, frame):
103
+ print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Received signal {signum}, shutting down...")
104
+ server.stop()
105
+ PID_FILE.unlink(missing_ok=True)
106
+ sys.exit(0)
107
+
108
+ signal.signal(signal.SIGTERM, signal_handler)
109
+ signal.signal(signal.SIGINT, signal_handler)
110
+
111
+ # Start server
112
+ server.start()
113
+
114
+ # Keep running
115
+ try:
116
+ while True:
117
+ time.sleep(1)
118
+ except KeyboardInterrupt:
119
+ signal_handler(signal.SIGINT, None)
120
+
121
+ def stop_server():
122
+ """Stop the Socket.IO daemon server."""
123
+ if not is_running():
124
+ print("Socket.IO daemon server is not running.")
125
+ print(f"Check for other servers: socketio_server_manager.py status")
126
+ return
127
+
128
+ try:
129
+ with open(PID_FILE) as f:
130
+ pid = int(f.read().strip())
131
+
132
+ print(f"Stopping Socket.IO server (PID: {pid})...")
133
+ os.kill(pid, signal.SIGTERM)
134
+
135
+ # Wait for process to stop
136
+ for _ in range(10):
137
+ if not is_running():
138
+ print("Socket.IO server stopped successfully.")
139
+ PID_FILE.unlink(missing_ok=True)
140
+ return
141
+ time.sleep(0.5)
142
+
143
+ # Force kill if still running
144
+ print("Server didn't stop gracefully, forcing...")
145
+ os.kill(pid, signal.SIGKILL)
146
+ PID_FILE.unlink(missing_ok=True)
147
+
148
+ except Exception as e:
149
+ print(f"Error stopping server: {e}")
150
+
151
+ def status_server():
152
+ """Check server status with manager integration info."""
153
+ if is_running():
154
+ with open(PID_FILE) as f:
155
+ pid = int(f.read().strip())
156
+ print(f"Socket.IO daemon server is running (PID: {pid})")
157
+ print(f"PID file: {PID_FILE}")
158
+
159
+ # Check if port is listening
160
+ try:
161
+ import socket
162
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
163
+ result = sock.connect_ex(('localhost', 8765))
164
+ sock.close()
165
+ if result == 0:
166
+ print("✅ Server is listening on port 8765")
167
+ print("🔧 Management style: daemon")
168
+ else:
169
+ print("⚠️ WARNING: Server process exists but port 8765 is not accessible")
170
+ except:
171
+ pass
172
+
173
+ # Show management commands
174
+ print("\n🔧 Management Commands:")
175
+ print(f" • Stop: {__file__} stop")
176
+ print(f" • Restart: {__file__} restart")
177
+
178
+ # Check for manager conflicts
179
+ try:
180
+ import requests
181
+ response = requests.get("http://localhost:8765/health", timeout=1.0)
182
+ if response.status_code == 200:
183
+ data = response.json()
184
+ if 'server_id' in data and data.get('server_id') != 'daemon-socketio':
185
+ print(f"\n⚠️ POTENTIAL CONFLICT: HTTP-managed server also detected")
186
+ print(f" Server ID: {data.get('server_id')}")
187
+ print(f" Use 'socketio_server_manager.py diagnose' to resolve")
188
+ except:
189
+ pass
190
+
191
+ else:
192
+ print("Socket.IO daemon server is not running")
193
+ print(f"\n🔧 Start Commands:")
194
+ print(f" • Daemon: {__file__} start")
195
+ print(f" • HTTP-managed: socketio_server_manager.py start")
196
+
197
+ def main():
198
+ """Main entry point."""
199
+ if len(sys.argv) < 2:
200
+ print("Usage: socketio-daemon.py {start|stop|restart|status}")
201
+ sys.exit(1)
202
+
203
+ command = sys.argv[1]
204
+
205
+ if command == "start":
206
+ start_server()
207
+ elif command == "stop":
208
+ stop_server()
209
+ elif command == "restart":
210
+ stop_server()
211
+ time.sleep(1)
212
+ start_server()
213
+ elif command == "status":
214
+ status_server()
215
+ else:
216
+ print(f"Unknown command: {command}")
217
+ print("Usage: socketio-daemon.py {start|stop|restart|status}")
218
+ sys.exit(1)
219
+
220
+ if __name__ == "__main__":
221
+ # Install psutil if not available
222
+ try:
223
+ import psutil
224
+ except ImportError:
225
+ print("Installing psutil...")
226
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "psutil"])
227
+ import psutil
228
+
229
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 3.4.6
3
+ Version: 3.4.9
4
4
  Summary: Claude Multi-agent Project Manager - Clean orchestration with ticket management
5
5
  Home-page: https://github.com/bobmatnyc/claude-mpm
6
6
  Author: Claude MPM Team
@@ -43,7 +43,7 @@ claude_mpm/cli/commands/agents.py,sha256=FqqEQcfAfCxjz_E7fGQUtLznloJLz8fWQtnjQhk
43
43
  claude_mpm/cli/commands/info.py,sha256=ETL6jC08OTQVTPjs219Y0m3FzfKOUlI0-yI81AI8FXY,2990
44
44
  claude_mpm/cli/commands/memory.py,sha256=6jYD1bgfnWA0DvBpLJnZCPYMRoGAPBopAED8Qr-iIos,37357
45
45
  claude_mpm/cli/commands/monitor.py,sha256=80_tmSdfn_2cYpzxxPu9GnvFW0eixlSJ4wCqbn8VSCM,12407
46
- claude_mpm/cli/commands/run.py,sha256=j8kFTdx4fwCR400NH-I0ORMc76J62IxUeVDaaq_DG7E,28312
46
+ claude_mpm/cli/commands/run.py,sha256=Rv6RT2S9WN8KcqX5e9rtmALP8yiOSw8ojl_Qp7gugqg,30234
47
47
  claude_mpm/cli/commands/tickets.py,sha256=SXyGtHSyGJwTeJwDAHf7kRbdiG1DlZkXkod5UoNy7Ik,2150
48
48
  claude_mpm/cli/commands/ui.py,sha256=FhBQiOKW61cNduyryRu0UhC366d6o1eEkBgbPd7Au1w,1900
49
49
  claude_mpm/cli_module/__init__.py,sha256=CkMp4gzWKoZZF_qKyBDi2sQaZw_GLWZYLtKouv-4f8s,390
@@ -57,7 +57,7 @@ claude_mpm/core/agent_name_normalizer.py,sha256=-X68oz3_74t9BRbHA54NEGyjy0xjTsGp
57
57
  claude_mpm/core/agent_registry.py,sha256=4MAfc7xDlrYWWkHmDMRmWE8q32teuCmIcud9D0I0dLo,20496
58
58
  claude_mpm/core/agent_session_manager.py,sha256=6alXQr4gnMR-unT4J1ryEtTxJqQolA0-NgPQN6X3lqY,11212
59
59
  claude_mpm/core/base_service.py,sha256=qWI_rUybHmmKroptJxcE4rzPBhK8yeMKIt2JqnqJB7E,29125
60
- claude_mpm/core/claude_runner.py,sha256=kVfA_U1g-DKCEW7f_ZbscvrhVOj4DP_L7jSx8-_dkM8,40933
60
+ claude_mpm/core/claude_runner.py,sha256=qcbjmRSGD3R_Kt9OmHBexZMY8RpCRbtXRKZAJ31ZGUU,44076
61
61
  claude_mpm/core/config.py,sha256=lrgaTSHXw558AFwzEHElqPc7tUALFoXTZXisQ-_WRWo,20329
62
62
  claude_mpm/core/config_aliases.py,sha256=8eqA4wpWViIDm_9pL3f9j7cR_ssmhOYYiY2UzHrfUzg,10058
63
63
  claude_mpm/core/container.py,sha256=P4c4nSo_USSfHTxvpR1sQkVGNsgqozZBN27l3IXqiDc,12216
@@ -72,7 +72,7 @@ claude_mpm/core/mixins.py,sha256=rTEH-7FDpNiLB8oo6mSb0CLarJklv4fDJw1xM-gr5wI,559
72
72
  claude_mpm/core/pm_hook_interceptor.py,sha256=PRaloqgxn-Alt9HflrywYXRL2GL3Ixb8Wxov8GfAMMU,7173
73
73
  claude_mpm/core/service_registry.py,sha256=wKJUO1g4UFA4dUpE3RkIYz1Ek8kIh4XfvU1kFeLCl2Q,10529
74
74
  claude_mpm/core/session_manager.py,sha256=D6ZA7bHAgfdkv0nLKjza0FKDng5iqi___IESrb3nSuk,8292
75
- claude_mpm/core/simple_runner.py,sha256=kVfA_U1g-DKCEW7f_ZbscvrhVOj4DP_L7jSx8-_dkM8,40933
75
+ claude_mpm/core/simple_runner.py,sha256=qcbjmRSGD3R_Kt9OmHBexZMY8RpCRbtXRKZAJ31ZGUU,44076
76
76
  claude_mpm/core/socketio_pool.py,sha256=B83uDsmqRF5S0QDwwatyKS-m2SdTvotCVfc3_2uQxd8,22438
77
77
  claude_mpm/core/tool_access_control.py,sha256=htZbDhC8s7D7BVqfmk0BwRrYJnlnUAk8_NeJKOaeNlg,6632
78
78
  claude_mpm/dashboard/open_dashboard.py,sha256=aXUc6LzUMwmTQMkl_h2jjvICimr-ED4FPMHP_9mnrgQ,1108
@@ -113,6 +113,7 @@ claude_mpm/orchestration/archive/subprocess_orchestrator.py,sha256=TYTAHX6p4OpgB
113
113
  claude_mpm/orchestration/archive/system_prompt_orchestrator.py,sha256=R16sc-94kQVeGjJzTYmvKn0aYgj_9qxyzShDy1E5zpE,12853
114
114
  claude_mpm/orchestration/archive/wrapper_orchestrator.py,sha256=cvL0NJf9kCWf3QJl67ySwvtR1Hd9Rym28Ii8Rtsdi6Q,6806
115
115
  claude_mpm/schemas/workflow_validator.py,sha256=qRgGodJoIZQaLfZ8OzWz3Y9eVNz3ckrQwkJ2RvccxAs,17175
116
+ claude_mpm/scripts/socketio_daemon.py,sha256=xV2COFBtj2DZ2-hixfCw5beqz2dh4CEgynOtgmVsUdA,7459
116
117
  claude_mpm/services/__init__.py,sha256=dcZ5U4xQlk-zpAy8CLTuEcXzKDfHT0KdJf3bYSmZ1BM,1904
117
118
  claude_mpm/services/agent_capabilities_generator.py,sha256=hWG0zV2InmzrDMxSbQzjVBBTzEaxg0bFxl8tmTMJ8qA,6565
118
119
  claude_mpm/services/agent_deployment.py,sha256=DtK1BX2yCrutUkQdVPD01mYHm-ya36l3EPOnEcaDfog,67961
@@ -192,9 +193,9 @@ claude_mpm/utils/path_operations.py,sha256=6pLMnAWBVzHkgp6JyQHmHbGD-dWn-nX21yV4E
192
193
  claude_mpm/utils/paths.py,sha256=Xv0SZWdZRkRjN9e6clBcA165ya00GNQxt7SwMz51tfA,10153
193
194
  claude_mpm/validation/__init__.py,sha256=bJ19g9lnk7yIjtxzN8XPegp87HTFBzCrGQOpFgRTf3g,155
194
195
  claude_mpm/validation/agent_validator.py,sha256=GCA2b2rKhKDeaNyUqWxTiWIs3sDdWjD9cgOFRp9K6ic,18227
195
- claude_mpm-3.4.6.dist-info/licenses/LICENSE,sha256=cSdDfXjoTVhstrERrqme4zgxAu4GubU22zVEHsiXGxs,1071
196
- claude_mpm-3.4.6.dist-info/METADATA,sha256=yoTuc1u-MzevEMn4wfSEQK51A_nQodUAS4eGiBZ8Exg,6523
197
- claude_mpm-3.4.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
198
- claude_mpm-3.4.6.dist-info/entry_points.txt,sha256=3_d7wLrg9sRmQ1SfrFGWoTNL8Wrd6lQb2XVSYbTwRIg,324
199
- claude_mpm-3.4.6.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
200
- claude_mpm-3.4.6.dist-info/RECORD,,
196
+ claude_mpm-3.4.9.dist-info/licenses/LICENSE,sha256=cSdDfXjoTVhstrERrqme4zgxAu4GubU22zVEHsiXGxs,1071
197
+ claude_mpm-3.4.9.dist-info/METADATA,sha256=6pnWOA54pUJgoL2UxHpALQouGnq6ubiXkw633NzhHBw,6523
198
+ claude_mpm-3.4.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
199
+ claude_mpm-3.4.9.dist-info/entry_points.txt,sha256=3_d7wLrg9sRmQ1SfrFGWoTNL8Wrd6lQb2XVSYbTwRIg,324
200
+ claude_mpm-3.4.9.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
201
+ claude_mpm-3.4.9.dist-info/RECORD,,