claude-mpm 4.2.9__py3-none-any.whl → 4.2.11__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/cli/commands/dashboard.py +59 -126
- claude_mpm/cli/commands/monitor.py +71 -212
- claude_mpm/cli/commands/run.py +33 -33
- claude_mpm/dashboard/static/css/code-tree.css +8 -16
- claude_mpm/dashboard/static/dist/components/code-tree.js +1 -1
- claude_mpm/dashboard/static/dist/components/file-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/dashboard.js +1 -1
- claude_mpm/dashboard/static/dist/socket-client.js +1 -1
- claude_mpm/dashboard/static/js/components/code-tree.js +692 -114
- claude_mpm/dashboard/static/js/components/file-viewer.js +538 -0
- claude_mpm/dashboard/static/js/components/module-viewer.js +26 -0
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +166 -14
- claude_mpm/dashboard/static/js/dashboard.js +108 -91
- claude_mpm/dashboard/static/js/socket-client.js +9 -7
- claude_mpm/dashboard/templates/index.html +2 -7
- claude_mpm/hooks/claude_hooks/hook_handler.py +1 -11
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +54 -59
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +112 -72
- claude_mpm/services/agents/deployment/agent_template_builder.py +0 -1
- claude_mpm/services/cli/unified_dashboard_manager.py +354 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +256 -0
- claude_mpm/services/monitor/event_emitter.py +279 -0
- claude_mpm/services/monitor/handlers/__init__.py +20 -0
- claude_mpm/services/monitor/handlers/code_analysis.py +334 -0
- claude_mpm/services/monitor/handlers/dashboard.py +298 -0
- claude_mpm/services/monitor/handlers/hooks.py +491 -0
- claude_mpm/services/monitor/management/__init__.py +18 -0
- claude_mpm/services/monitor/management/health.py +124 -0
- claude_mpm/services/monitor/management/lifecycle.py +298 -0
- claude_mpm/services/monitor/server.py +442 -0
- claude_mpm/tools/code_tree_analyzer.py +33 -17
- {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/METADATA +1 -1
- {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/RECORD +41 -36
- claude_mpm/cli/commands/socketio_monitor.py +0 -233
- claude_mpm/scripts/socketio_daemon.py +0 -571
- claude_mpm/scripts/socketio_daemon_hardened.py +0 -937
- claude_mpm/scripts/socketio_daemon_wrapper.py +0 -78
- claude_mpm/scripts/socketio_server_manager.py +0 -349
- claude_mpm/services/cli/dashboard_launcher.py +0 -423
- claude_mpm/services/cli/socketio_manager.py +0 -595
- claude_mpm/services/dashboard/stable_server.py +0 -1020
- claude_mpm/services/socketio/monitor_server.py +0 -505
- {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/WHEEL +0 -0
- {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/top_level.txt +0 -0
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Wrapper script to use the hardened daemon by default while maintaining compatibility.
|
|
4
|
-
|
|
5
|
-
WHY: Provides a smooth transition path from the original daemon to the hardened version
|
|
6
|
-
without breaking existing workflows or scripts.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import os
|
|
10
|
-
import subprocess
|
|
11
|
-
import sys
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
|
|
14
|
-
# Determine which daemon to use
|
|
15
|
-
USE_HARDENED = os.environ.get("SOCKETIO_USE_HARDENED", "true").lower() == "true"
|
|
16
|
-
|
|
17
|
-
# Find the appropriate daemon script using proper resource resolution
|
|
18
|
-
try:
|
|
19
|
-
# Try using importlib.resources for proper package resource access
|
|
20
|
-
try:
|
|
21
|
-
from importlib import resources
|
|
22
|
-
|
|
23
|
-
# We're in the same package, so try direct import
|
|
24
|
-
import claude_mpm.scripts
|
|
25
|
-
|
|
26
|
-
scripts_package = claude_mpm.scripts
|
|
27
|
-
|
|
28
|
-
if USE_HARDENED:
|
|
29
|
-
try:
|
|
30
|
-
with resources.path(
|
|
31
|
-
scripts_package, "socketio_daemon_hardened.py"
|
|
32
|
-
) as p:
|
|
33
|
-
daemon_script = p
|
|
34
|
-
print("Using hardened Socket.IO daemon for improved reliability")
|
|
35
|
-
except (FileNotFoundError, ModuleNotFoundError):
|
|
36
|
-
# Fall back to original if hardened doesn't exist
|
|
37
|
-
with resources.path(scripts_package, "socketio_daemon.py") as p:
|
|
38
|
-
daemon_script = p
|
|
39
|
-
else:
|
|
40
|
-
with resources.path(scripts_package, "socketio_daemon.py") as p:
|
|
41
|
-
daemon_script = p
|
|
42
|
-
print(
|
|
43
|
-
"Using original Socket.IO daemon (set SOCKETIO_USE_HARDENED=true for hardened version)"
|
|
44
|
-
)
|
|
45
|
-
except (ImportError, AttributeError, ModuleNotFoundError):
|
|
46
|
-
# Fallback for older Python versions or if resources not available
|
|
47
|
-
script_dir = Path(__file__).parent
|
|
48
|
-
|
|
49
|
-
if USE_HARDENED:
|
|
50
|
-
daemon_script = script_dir / "socketio_daemon_hardened.py"
|
|
51
|
-
if not daemon_script.exists():
|
|
52
|
-
# Fall back to original if hardened doesn't exist
|
|
53
|
-
daemon_script = script_dir / "socketio_daemon.py"
|
|
54
|
-
else:
|
|
55
|
-
print("Using hardened Socket.IO daemon for improved reliability")
|
|
56
|
-
else:
|
|
57
|
-
daemon_script = script_dir / "socketio_daemon.py"
|
|
58
|
-
print(
|
|
59
|
-
"Using original Socket.IO daemon (set SOCKETIO_USE_HARDENED=true for hardened version)"
|
|
60
|
-
)
|
|
61
|
-
except Exception:
|
|
62
|
-
# Ultimate fallback - try relative to current file
|
|
63
|
-
script_dir = Path(__file__).parent
|
|
64
|
-
daemon_script = script_dir / (
|
|
65
|
-
"socketio_daemon_hardened.py" if USE_HARDENED else "socketio_daemon.py"
|
|
66
|
-
)
|
|
67
|
-
if not daemon_script.exists():
|
|
68
|
-
daemon_script = script_dir / "socketio_daemon.py"
|
|
69
|
-
|
|
70
|
-
# Pass through all arguments to the selected daemon
|
|
71
|
-
if daemon_script.exists():
|
|
72
|
-
result = subprocess.run(
|
|
73
|
-
[sys.executable, str(daemon_script)] + sys.argv[1:], check=False
|
|
74
|
-
)
|
|
75
|
-
sys.exit(result.returncode)
|
|
76
|
-
else:
|
|
77
|
-
print(f"Error: Daemon script not found at {daemon_script}")
|
|
78
|
-
sys.exit(1)
|
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Socket.IO Server Manager wrapper for claude-mpm.
|
|
4
|
-
|
|
5
|
-
WHY: This module provides a wrapper around the ServerManager class from
|
|
6
|
-
tools/admin/socketio_server_manager.py to make it accessible from the
|
|
7
|
-
scripts directory as expected by the CLI monitor command.
|
|
8
|
-
|
|
9
|
-
DESIGN DECISION: Rather than duplicating code, we import and re-export
|
|
10
|
-
the ServerManager class from its actual location in tools/admin. This
|
|
11
|
-
ensures consistency and maintainability.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
import sys
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
|
|
17
|
-
# Add the tools/admin directory to Python path to import ServerManager
|
|
18
|
-
script_dir = Path(__file__).parent
|
|
19
|
-
project_root = script_dir.parent.parent.parent # Up to project root
|
|
20
|
-
tools_admin_dir = project_root / "tools" / "admin"
|
|
21
|
-
|
|
22
|
-
if tools_admin_dir.exists() and str(tools_admin_dir) not in sys.path:
|
|
23
|
-
sys.path.insert(0, str(tools_admin_dir))
|
|
24
|
-
|
|
25
|
-
try:
|
|
26
|
-
# Import ServerManager from the actual implementation
|
|
27
|
-
import subprocess
|
|
28
|
-
|
|
29
|
-
from socketio_server_manager import ServerManager as BaseServerManager
|
|
30
|
-
|
|
31
|
-
# Patch the ServerManager to use project-local PID file and daemon
|
|
32
|
-
class ServerManager(BaseServerManager):
|
|
33
|
-
"""Patched ServerManager that uses project-local PID file and daemon.
|
|
34
|
-
|
|
35
|
-
WHY: The daemon stores its PID file in the project's .claude-mpm
|
|
36
|
-
directory, not in the home directory. This patch ensures the
|
|
37
|
-
ServerManager looks in the correct location and uses the daemon
|
|
38
|
-
for starting servers when the standalone module is not available.
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
def __init__(self):
|
|
42
|
-
super().__init__()
|
|
43
|
-
# Override the daemon PID file path to use project root
|
|
44
|
-
from claude_mpm.core.unified_paths import get_project_root
|
|
45
|
-
|
|
46
|
-
self.daemon_pidfile_path = (
|
|
47
|
-
get_project_root() / ".claude-mpm" / "socketio-server.pid"
|
|
48
|
-
)
|
|
49
|
-
self.daemon_script = script_dir / "socketio_daemon.py"
|
|
50
|
-
|
|
51
|
-
def start_server(
|
|
52
|
-
self, port: int = None, host: str = "localhost", server_id: str = None
|
|
53
|
-
) -> bool:
|
|
54
|
-
"""Start Socket.IO server, preferring daemon over standalone.
|
|
55
|
-
|
|
56
|
-
WHY: When the standalone_socketio_server module is not available,
|
|
57
|
-
we fallback to using the daemon script which is always present.
|
|
58
|
-
"""
|
|
59
|
-
# First check if the daemon is already running
|
|
60
|
-
if self.daemon_pidfile_path.exists():
|
|
61
|
-
try:
|
|
62
|
-
with open(self.daemon_pidfile_path) as f:
|
|
63
|
-
pid = int(f.read().strip())
|
|
64
|
-
# Check if process is running
|
|
65
|
-
import psutil
|
|
66
|
-
|
|
67
|
-
process = psutil.Process(pid)
|
|
68
|
-
if process.is_running():
|
|
69
|
-
print(
|
|
70
|
-
f"Socket.IO daemon server is already running (PID: {pid})"
|
|
71
|
-
)
|
|
72
|
-
return True
|
|
73
|
-
except:
|
|
74
|
-
pass
|
|
75
|
-
|
|
76
|
-
# Try to use the daemon script for starting
|
|
77
|
-
if self.daemon_script.exists():
|
|
78
|
-
print(
|
|
79
|
-
f"Starting server on {host}:{port or self.base_port} using daemon..."
|
|
80
|
-
)
|
|
81
|
-
try:
|
|
82
|
-
result = subprocess.run(
|
|
83
|
-
[sys.executable, str(self.daemon_script), "start"],
|
|
84
|
-
capture_output=True,
|
|
85
|
-
text=True,
|
|
86
|
-
check=False,
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
if result.returncode == 0:
|
|
90
|
-
# Check if output contains success message
|
|
91
|
-
if "started successfully" in result.stdout.lower():
|
|
92
|
-
print(result.stdout)
|
|
93
|
-
return True
|
|
94
|
-
# Even if no explicit success message, check if process is running
|
|
95
|
-
if self.daemon_pidfile_path.exists():
|
|
96
|
-
print("Socket.IO daemon server started")
|
|
97
|
-
return True
|
|
98
|
-
else:
|
|
99
|
-
# If daemon fails, try parent's start_server method
|
|
100
|
-
if result.stderr:
|
|
101
|
-
print(f"Daemon error: {result.stderr}")
|
|
102
|
-
print("Trying standalone method...")
|
|
103
|
-
except Exception as e:
|
|
104
|
-
print(f"Error running daemon: {e}")
|
|
105
|
-
|
|
106
|
-
# Fall back to parent implementation
|
|
107
|
-
return super().start_server(port=port, host=host, server_id=server_id)
|
|
108
|
-
|
|
109
|
-
def stop_server(self, port: int = None) -> bool:
|
|
110
|
-
"""Stop Socket.IO server, handling daemon-style servers.
|
|
111
|
-
|
|
112
|
-
WHY: The daemon server needs special handling for stopping.
|
|
113
|
-
"""
|
|
114
|
-
# Check if daemon is running
|
|
115
|
-
if self.daemon_pidfile_path.exists():
|
|
116
|
-
print("🔄 Stopping daemon server", end="")
|
|
117
|
-
try:
|
|
118
|
-
with open(self.daemon_pidfile_path) as f:
|
|
119
|
-
pid = int(f.read().strip())
|
|
120
|
-
print(f" (PID: {pid})...")
|
|
121
|
-
|
|
122
|
-
result = subprocess.run(
|
|
123
|
-
[sys.executable, str(self.daemon_script), "stop"],
|
|
124
|
-
capture_output=True,
|
|
125
|
-
text=True,
|
|
126
|
-
check=False,
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
if result.returncode == 0:
|
|
130
|
-
print("✅ Daemon server stopped successfully")
|
|
131
|
-
return True
|
|
132
|
-
print(f"❌ Failed to stop daemon: {result.stderr}")
|
|
133
|
-
except Exception as e:
|
|
134
|
-
print(f"❌ Error stopping daemon: {e}")
|
|
135
|
-
|
|
136
|
-
# Fall back to parent implementation for non-daemon servers
|
|
137
|
-
return super().stop_server(port=port)
|
|
138
|
-
|
|
139
|
-
def restart_server(self, port: int = None) -> bool:
|
|
140
|
-
"""Restart Socket.IO server, handling daemon-style servers.
|
|
141
|
-
|
|
142
|
-
WHY: The daemon server needs special handling for restarting.
|
|
143
|
-
"""
|
|
144
|
-
# Check if daemon is running
|
|
145
|
-
if self.daemon_pidfile_path.exists():
|
|
146
|
-
try:
|
|
147
|
-
with open(self.daemon_pidfile_path) as f:
|
|
148
|
-
pid = int(f.read().strip())
|
|
149
|
-
|
|
150
|
-
print(f"🔄 Stopping daemon server (PID: {pid})...")
|
|
151
|
-
|
|
152
|
-
# Stop the daemon
|
|
153
|
-
result = subprocess.run(
|
|
154
|
-
[sys.executable, str(self.daemon_script), "stop"],
|
|
155
|
-
capture_output=True,
|
|
156
|
-
text=True,
|
|
157
|
-
check=False,
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
if result.returncode == 0:
|
|
161
|
-
print("✅ Daemon server stopped successfully")
|
|
162
|
-
# Wait a moment for clean shutdown
|
|
163
|
-
import time
|
|
164
|
-
|
|
165
|
-
time.sleep(1)
|
|
166
|
-
|
|
167
|
-
# Start it again
|
|
168
|
-
return self.start_server(port=port)
|
|
169
|
-
print(f"❌ Failed to stop daemon: {result.stderr}")
|
|
170
|
-
return False
|
|
171
|
-
|
|
172
|
-
except Exception as e:
|
|
173
|
-
print(f"❌ Error restarting daemon: {e}")
|
|
174
|
-
return False
|
|
175
|
-
else:
|
|
176
|
-
print(
|
|
177
|
-
f"❌ No daemon server found (no PID file at {self.daemon_pidfile_path})"
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
# Fall back to parent implementation for non-daemon servers
|
|
181
|
-
return super().restart_server(port=port)
|
|
182
|
-
|
|
183
|
-
# Re-export for use by CLI
|
|
184
|
-
__all__ = ["ServerManager"]
|
|
185
|
-
|
|
186
|
-
except ImportError:
|
|
187
|
-
# Fallback: If tools/admin version not available, provide basic implementation
|
|
188
|
-
# that delegates to socketio_daemon.py
|
|
189
|
-
|
|
190
|
-
import subprocess
|
|
191
|
-
from typing import Any, Dict, List, Optional
|
|
192
|
-
|
|
193
|
-
class ServerManager:
|
|
194
|
-
"""Fallback ServerManager that uses socketio_daemon.py.
|
|
195
|
-
|
|
196
|
-
WHY: This fallback ensures the monitor CLI command works even if
|
|
197
|
-
the full ServerManager from tools/admin is not available. It provides
|
|
198
|
-
basic functionality by delegating to the socketio_daemon.py script.
|
|
199
|
-
"""
|
|
200
|
-
|
|
201
|
-
def __init__(self):
|
|
202
|
-
self.daemon_script = script_dir / "socketio_daemon.py"
|
|
203
|
-
self.base_port = 8765
|
|
204
|
-
|
|
205
|
-
def start_server(
|
|
206
|
-
self,
|
|
207
|
-
port: Optional[int] = None,
|
|
208
|
-
host: str = "localhost",
|
|
209
|
-
server_id: Optional[str] = None,
|
|
210
|
-
) -> bool:
|
|
211
|
-
"""Start the Socket.IO server using daemon script.
|
|
212
|
-
|
|
213
|
-
WHY: The daemon script handles port selection and process management,
|
|
214
|
-
so we delegate to it for starting servers.
|
|
215
|
-
"""
|
|
216
|
-
if port and port != self.base_port:
|
|
217
|
-
print(f"Note: Daemon only supports default port {self.base_port}")
|
|
218
|
-
print(f"Starting on port {self.base_port} instead...")
|
|
219
|
-
|
|
220
|
-
try:
|
|
221
|
-
result = subprocess.run(
|
|
222
|
-
[sys.executable, str(self.daemon_script), "start"],
|
|
223
|
-
capture_output=True,
|
|
224
|
-
text=True,
|
|
225
|
-
check=False,
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
if result.returncode == 0:
|
|
229
|
-
print("Socket.IO server started successfully")
|
|
230
|
-
return True
|
|
231
|
-
print(f"Failed to start server: {result.stderr}")
|
|
232
|
-
return False
|
|
233
|
-
|
|
234
|
-
except Exception as e:
|
|
235
|
-
print(f"Error starting server: {e}")
|
|
236
|
-
return False
|
|
237
|
-
|
|
238
|
-
def stop_server(self, port: Optional[int] = None) -> bool:
|
|
239
|
-
"""Stop the Socket.IO server using daemon script."""
|
|
240
|
-
if port and port != self.base_port:
|
|
241
|
-
print(f"Note: Daemon only supports default port {self.base_port}")
|
|
242
|
-
|
|
243
|
-
try:
|
|
244
|
-
result = subprocess.run(
|
|
245
|
-
[sys.executable, str(self.daemon_script), "stop"],
|
|
246
|
-
capture_output=True,
|
|
247
|
-
text=True,
|
|
248
|
-
check=False,
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
if result.returncode == 0:
|
|
252
|
-
print("Socket.IO server stopped successfully")
|
|
253
|
-
return True
|
|
254
|
-
print(f"Failed to stop server: {result.stderr}")
|
|
255
|
-
return False
|
|
256
|
-
|
|
257
|
-
except Exception as e:
|
|
258
|
-
print(f"Error stopping server: {e}")
|
|
259
|
-
return False
|
|
260
|
-
|
|
261
|
-
def restart_server(self, port: Optional[int] = None) -> bool:
|
|
262
|
-
"""Restart the Socket.IO server using daemon script."""
|
|
263
|
-
if port and port != self.base_port:
|
|
264
|
-
print(f"Note: Daemon only supports default port {self.base_port}")
|
|
265
|
-
|
|
266
|
-
try:
|
|
267
|
-
result = subprocess.run(
|
|
268
|
-
[sys.executable, str(self.daemon_script), "restart"],
|
|
269
|
-
capture_output=True,
|
|
270
|
-
text=True,
|
|
271
|
-
check=False,
|
|
272
|
-
)
|
|
273
|
-
|
|
274
|
-
if result.returncode == 0:
|
|
275
|
-
print("Socket.IO server restarted successfully")
|
|
276
|
-
return True
|
|
277
|
-
print(f"Failed to restart server: {result.stderr}")
|
|
278
|
-
return False
|
|
279
|
-
|
|
280
|
-
except Exception as e:
|
|
281
|
-
print(f"Error restarting server: {e}")
|
|
282
|
-
return False
|
|
283
|
-
|
|
284
|
-
def list_running_servers(self) -> List[Dict[str, Any]]:
|
|
285
|
-
"""List running servers using daemon script status."""
|
|
286
|
-
try:
|
|
287
|
-
result = subprocess.run(
|
|
288
|
-
[sys.executable, str(self.daemon_script), "status"],
|
|
289
|
-
capture_output=True,
|
|
290
|
-
text=True,
|
|
291
|
-
check=False,
|
|
292
|
-
)
|
|
293
|
-
|
|
294
|
-
# Parse status output to determine if server is running
|
|
295
|
-
if "is running" in result.stdout:
|
|
296
|
-
# Extract port from output if possible
|
|
297
|
-
port = self.base_port
|
|
298
|
-
for line in result.stdout.split("\n"):
|
|
299
|
-
if "port" in line.lower():
|
|
300
|
-
try:
|
|
301
|
-
# Try to extract port number
|
|
302
|
-
import re
|
|
303
|
-
|
|
304
|
-
match = re.search(r"port\s+(\d+)", line.lower())
|
|
305
|
-
if match:
|
|
306
|
-
port = int(match.group(1))
|
|
307
|
-
except:
|
|
308
|
-
pass
|
|
309
|
-
|
|
310
|
-
return [
|
|
311
|
-
{
|
|
312
|
-
"port": port,
|
|
313
|
-
"server_id": "daemon-socketio",
|
|
314
|
-
"status": "running",
|
|
315
|
-
}
|
|
316
|
-
]
|
|
317
|
-
return []
|
|
318
|
-
|
|
319
|
-
except Exception as e:
|
|
320
|
-
print(f"Error checking server status: {e}")
|
|
321
|
-
return []
|
|
322
|
-
|
|
323
|
-
def get_server_info(self, port: int) -> Optional[Dict[str, Any]]:
|
|
324
|
-
"""Get information about a server on a specific port."""
|
|
325
|
-
servers = self.list_running_servers()
|
|
326
|
-
for server in servers:
|
|
327
|
-
if server.get("port") == port:
|
|
328
|
-
return server
|
|
329
|
-
return None
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
# If running as a script, delegate to the actual socketio_server_manager.py
|
|
333
|
-
if __name__ == "__main__":
|
|
334
|
-
try:
|
|
335
|
-
# Try to run the actual script from tools/admin
|
|
336
|
-
import subprocess
|
|
337
|
-
|
|
338
|
-
tools_script = tools_admin_dir / "socketio_server_manager.py"
|
|
339
|
-
if tools_script.exists():
|
|
340
|
-
subprocess.run(
|
|
341
|
-
[sys.executable, str(tools_script)] + sys.argv[1:], check=False
|
|
342
|
-
)
|
|
343
|
-
else:
|
|
344
|
-
print("Socket.IO server manager not found in tools/admin")
|
|
345
|
-
print("Please ensure claude-mpm is properly installed")
|
|
346
|
-
sys.exit(1)
|
|
347
|
-
except Exception as e:
|
|
348
|
-
print(f"Error running server manager: {e}")
|
|
349
|
-
sys.exit(1)
|