claude-mpm 3.4.3__py3-none-any.whl → 3.4.6__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/agents/INSTRUCTIONS.md +20 -3
- claude_mpm/agents/backups/INSTRUCTIONS.md +119 -5
- claude_mpm/cli/__init__.py +3 -1
- claude_mpm/cli/commands/__init__.py +3 -1
- claude_mpm/cli/commands/monitor.py +328 -0
- claude_mpm/cli/commands/run.py +9 -17
- claude_mpm/cli/parser.py +69 -1
- claude_mpm/constants.py +9 -0
- claude_mpm/ticket_wrapper.py +29 -0
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.6.dist-info}/METADATA +1 -1
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.6.dist-info}/RECORD +15 -23
- claude_mpm/scripts/__init__.py +0 -1
- claude_mpm/scripts/claude-mpm-socketio +0 -32
- claude_mpm/scripts/claude_mpm_monitor.html +0 -567
- claude_mpm/scripts/install_socketio_server.py +0 -407
- claude_mpm/scripts/launch_monitor.py +0 -132
- claude_mpm/scripts/launch_socketio_dashboard.py +0 -261
- claude_mpm/scripts/manage_version.py +0 -479
- claude_mpm/scripts/socketio_daemon.py +0 -221
- claude_mpm/scripts/socketio_server_manager.py +0 -753
- claude_mpm/scripts/ticket.py +0 -269
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.6.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.6.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.6.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.6.dist-info}/top_level.txt +0 -0
|
@@ -1,407 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Socket.IO Server Installation Script.
|
|
3
|
-
|
|
4
|
-
This script handles installation and setup of the Socket.IO server
|
|
5
|
-
across different deployment scenarios and platforms.
|
|
6
|
-
|
|
7
|
-
Features:
|
|
8
|
-
- Automatic dependency detection and installation
|
|
9
|
-
- Platform-specific installation (Linux, macOS, Windows)
|
|
10
|
-
- Service/daemon installation for persistent operation
|
|
11
|
-
- Configuration file generation
|
|
12
|
-
- Validation and testing
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
import argparse
|
|
16
|
-
import json
|
|
17
|
-
import os
|
|
18
|
-
import platform
|
|
19
|
-
import shutil
|
|
20
|
-
import subprocess
|
|
21
|
-
import sys
|
|
22
|
-
from pathlib import Path
|
|
23
|
-
from typing import Dict, List, Optional, Tuple
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class SocketIOInstaller:
|
|
27
|
-
"""Handles installation of Socket.IO server across different platforms."""
|
|
28
|
-
|
|
29
|
-
def __init__(self):
|
|
30
|
-
self.platform = platform.system().lower()
|
|
31
|
-
self.script_dir = Path(__file__).parent
|
|
32
|
-
self.project_root = self.script_dir.parent
|
|
33
|
-
self.python_executable = sys.executable
|
|
34
|
-
|
|
35
|
-
# Installation paths by platform
|
|
36
|
-
if self.platform == 'linux':
|
|
37
|
-
self.service_dir = Path('/etc/systemd/system')
|
|
38
|
-
self.bin_dir = Path('/usr/local/bin')
|
|
39
|
-
self.config_dir = Path('/etc/claude-mpm')
|
|
40
|
-
elif self.platform == 'darwin': # macOS
|
|
41
|
-
self.service_dir = Path.home() / 'Library' / 'LaunchAgents'
|
|
42
|
-
self.bin_dir = Path('/usr/local/bin')
|
|
43
|
-
self.config_dir = Path.home() / '.claude-mpm'
|
|
44
|
-
elif self.platform == 'windows':
|
|
45
|
-
self.service_dir = None # Windows services handled differently
|
|
46
|
-
self.bin_dir = Path(os.environ.get('USERPROFILE', '')) / 'AppData' / 'Local' / 'claude-mpm' / 'bin'
|
|
47
|
-
self.config_dir = Path(os.environ.get('APPDATA', '')) / 'claude-mpm'
|
|
48
|
-
else:
|
|
49
|
-
raise RuntimeError(f"Unsupported platform: {self.platform}")
|
|
50
|
-
|
|
51
|
-
def check_dependencies(self) -> Tuple[bool, List[str]]:
|
|
52
|
-
"""Check if required dependencies are installed."""
|
|
53
|
-
required_packages = [
|
|
54
|
-
'python-socketio>=5.11.0',
|
|
55
|
-
'aiohttp>=3.9.0',
|
|
56
|
-
'requests>=2.25.0'
|
|
57
|
-
]
|
|
58
|
-
|
|
59
|
-
missing = []
|
|
60
|
-
|
|
61
|
-
for package in required_packages:
|
|
62
|
-
package_name = package.split('>=')[0]
|
|
63
|
-
try:
|
|
64
|
-
__import__(package_name.replace('-', '_'))
|
|
65
|
-
except ImportError:
|
|
66
|
-
missing.append(package)
|
|
67
|
-
|
|
68
|
-
return len(missing) == 0, missing
|
|
69
|
-
|
|
70
|
-
def install_dependencies(self, missing_packages: List[str]) -> bool:
|
|
71
|
-
"""Install missing dependencies."""
|
|
72
|
-
print("Installing required dependencies...")
|
|
73
|
-
|
|
74
|
-
try:
|
|
75
|
-
cmd = [self.python_executable, '-m', 'pip', 'install'] + missing_packages
|
|
76
|
-
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
77
|
-
|
|
78
|
-
if result.returncode == 0:
|
|
79
|
-
print("✅ Dependencies installed successfully")
|
|
80
|
-
return True
|
|
81
|
-
else:
|
|
82
|
-
print(f"❌ Failed to install dependencies: {result.stderr}")
|
|
83
|
-
return False
|
|
84
|
-
|
|
85
|
-
except Exception as e:
|
|
86
|
-
print(f"❌ Error installing dependencies: {e}")
|
|
87
|
-
return False
|
|
88
|
-
|
|
89
|
-
def create_startup_script(self, install_dir: Path) -> bool:
|
|
90
|
-
"""Create startup script for the Socket.IO server."""
|
|
91
|
-
|
|
92
|
-
# Create the script content
|
|
93
|
-
if self.platform == 'windows':
|
|
94
|
-
script_name = 'claude-mpm-socketio.bat'
|
|
95
|
-
script_content = f'''@echo off
|
|
96
|
-
REM Claude MPM Socket.IO Server Startup Script
|
|
97
|
-
"{self.python_executable}" -m claude_mpm.services.standalone_socketio_server %*
|
|
98
|
-
'''
|
|
99
|
-
else:
|
|
100
|
-
script_name = 'claude-mpm-socketio'
|
|
101
|
-
script_content = f'''#!/bin/bash
|
|
102
|
-
# Claude MPM Socket.IO Server Startup Script
|
|
103
|
-
exec "{self.python_executable}" -m claude_mpm.services.standalone_socketio_server "$@"
|
|
104
|
-
'''
|
|
105
|
-
|
|
106
|
-
script_path = install_dir / script_name
|
|
107
|
-
|
|
108
|
-
try:
|
|
109
|
-
install_dir.mkdir(parents=True, exist_ok=True)
|
|
110
|
-
|
|
111
|
-
with open(script_path, 'w') as f:
|
|
112
|
-
f.write(script_content)
|
|
113
|
-
|
|
114
|
-
if self.platform != 'windows':
|
|
115
|
-
os.chmod(script_path, 0o755)
|
|
116
|
-
|
|
117
|
-
print(f"✅ Created startup script: {script_path}")
|
|
118
|
-
return True
|
|
119
|
-
|
|
120
|
-
except Exception as e:
|
|
121
|
-
print(f"❌ Failed to create startup script: {e}")
|
|
122
|
-
return False
|
|
123
|
-
|
|
124
|
-
def create_service_file(self, user_mode: bool = True) -> bool:
|
|
125
|
-
"""Create system service file for persistent operation."""
|
|
126
|
-
|
|
127
|
-
if self.platform == 'linux':
|
|
128
|
-
return self._create_systemd_service(user_mode)
|
|
129
|
-
elif self.platform == 'darwin':
|
|
130
|
-
return self._create_launchd_service()
|
|
131
|
-
elif self.platform == 'windows':
|
|
132
|
-
return self._create_windows_service()
|
|
133
|
-
else:
|
|
134
|
-
print(f"⚠️ Service installation not supported on {self.platform}")
|
|
135
|
-
return False
|
|
136
|
-
|
|
137
|
-
def _create_systemd_service(self, user_mode: bool) -> bool:
|
|
138
|
-
"""Create systemd service file for Linux."""
|
|
139
|
-
|
|
140
|
-
service_content = f'''[Unit]
|
|
141
|
-
Description=Claude MPM Socket.IO Server
|
|
142
|
-
After=network.target
|
|
143
|
-
Wants=network.target
|
|
144
|
-
|
|
145
|
-
[Service]
|
|
146
|
-
Type=simple
|
|
147
|
-
ExecStart={self.python_executable} -m claude_mpm.services.standalone_socketio_server
|
|
148
|
-
Restart=always
|
|
149
|
-
RestartSec=5
|
|
150
|
-
Environment=PYTHONPATH={self.project_root / "src"}
|
|
151
|
-
WorkingDirectory={self.project_root}
|
|
152
|
-
|
|
153
|
-
[Install]
|
|
154
|
-
WantedBy={"default.target" if user_mode else "multi-user.target"}
|
|
155
|
-
'''
|
|
156
|
-
|
|
157
|
-
if user_mode:
|
|
158
|
-
service_dir = Path.home() / '.config' / 'systemd' / 'user'
|
|
159
|
-
service_name = 'claude-mpm-socketio.service'
|
|
160
|
-
else:
|
|
161
|
-
service_dir = self.service_dir
|
|
162
|
-
service_name = 'claude-mpm-socketio.service'
|
|
163
|
-
|
|
164
|
-
service_path = service_dir / service_name
|
|
165
|
-
|
|
166
|
-
try:
|
|
167
|
-
service_dir.mkdir(parents=True, exist_ok=True)
|
|
168
|
-
|
|
169
|
-
with open(service_path, 'w') as f:
|
|
170
|
-
f.write(service_content)
|
|
171
|
-
|
|
172
|
-
print(f"✅ Created systemd service: {service_path}")
|
|
173
|
-
|
|
174
|
-
# Enable and start the service
|
|
175
|
-
if user_mode:
|
|
176
|
-
subprocess.run(['systemctl', '--user', 'daemon-reload'], check=True)
|
|
177
|
-
subprocess.run(['systemctl', '--user', 'enable', service_name], check=True)
|
|
178
|
-
print(f"✅ Service enabled. Start with: systemctl --user start {service_name}")
|
|
179
|
-
else:
|
|
180
|
-
subprocess.run(['sudo', 'systemctl', 'daemon-reload'], check=True)
|
|
181
|
-
subprocess.run(['sudo', 'systemctl', 'enable', service_name], check=True)
|
|
182
|
-
print(f"✅ Service enabled. Start with: sudo systemctl start {service_name}")
|
|
183
|
-
|
|
184
|
-
return True
|
|
185
|
-
|
|
186
|
-
except Exception as e:
|
|
187
|
-
print(f"❌ Failed to create systemd service: {e}")
|
|
188
|
-
return False
|
|
189
|
-
|
|
190
|
-
def _create_launchd_service(self) -> bool:
|
|
191
|
-
"""Create launchd service file for macOS."""
|
|
192
|
-
|
|
193
|
-
service_content = {
|
|
194
|
-
"Label": "com.claude-mpm.socketio",
|
|
195
|
-
"ProgramArguments": [
|
|
196
|
-
self.python_executable,
|
|
197
|
-
"-m", "claude_mpm.services.standalone_socketio_server"
|
|
198
|
-
],
|
|
199
|
-
"RunAtLoad": True,
|
|
200
|
-
"KeepAlive": True,
|
|
201
|
-
"WorkingDirectory": str(self.project_root),
|
|
202
|
-
"EnvironmentVariables": {
|
|
203
|
-
"PYTHONPATH": str(self.project_root / "src")
|
|
204
|
-
},
|
|
205
|
-
"StandardOutPath": str(Path.home() / "Library" / "Logs" / "claude-mpm-socketio.log"),
|
|
206
|
-
"StandardErrorPath": str(Path.home() / "Library" / "Logs" / "claude-mpm-socketio-error.log")
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
service_path = self.service_dir / 'com.claude-mpm.socketio.plist'
|
|
210
|
-
|
|
211
|
-
try:
|
|
212
|
-
self.service_dir.mkdir(parents=True, exist_ok=True)
|
|
213
|
-
|
|
214
|
-
import plistlib
|
|
215
|
-
with open(service_path, 'wb') as f:
|
|
216
|
-
plistlib.dump(service_content, f)
|
|
217
|
-
|
|
218
|
-
print(f"✅ Created launchd service: {service_path}")
|
|
219
|
-
print(f"✅ Load with: launchctl load {service_path}")
|
|
220
|
-
|
|
221
|
-
return True
|
|
222
|
-
|
|
223
|
-
except Exception as e:
|
|
224
|
-
print(f"❌ Failed to create launchd service: {e}")
|
|
225
|
-
return False
|
|
226
|
-
|
|
227
|
-
def _create_windows_service(self) -> bool:
|
|
228
|
-
"""Create Windows service (placeholder - requires additional tools)."""
|
|
229
|
-
print("⚠️ Windows service installation requires additional tools like NSSM or WinSW")
|
|
230
|
-
print(" For now, you can run the server manually or use Task Scheduler")
|
|
231
|
-
|
|
232
|
-
# Create a basic batch file for manual startup
|
|
233
|
-
startup_script = self.bin_dir / 'start-claude-mpm-socketio.bat'
|
|
234
|
-
|
|
235
|
-
script_content = f'''@echo off
|
|
236
|
-
title Claude MPM Socket.IO Server
|
|
237
|
-
cd /d "{self.project_root}"
|
|
238
|
-
"{self.python_executable}" -m claude_mpm.services.standalone_socketio_server
|
|
239
|
-
pause
|
|
240
|
-
'''
|
|
241
|
-
|
|
242
|
-
try:
|
|
243
|
-
self.bin_dir.mkdir(parents=True, exist_ok=True)
|
|
244
|
-
|
|
245
|
-
with open(startup_script, 'w') as f:
|
|
246
|
-
f.write(script_content)
|
|
247
|
-
|
|
248
|
-
print(f"✅ Created startup script: {startup_script}")
|
|
249
|
-
return True
|
|
250
|
-
|
|
251
|
-
except Exception as e:
|
|
252
|
-
print(f"❌ Failed to create startup script: {e}")
|
|
253
|
-
return False
|
|
254
|
-
|
|
255
|
-
def create_config_file(self, environment: str = "production") -> bool:
|
|
256
|
-
"""Create configuration file."""
|
|
257
|
-
|
|
258
|
-
try:
|
|
259
|
-
# Import config module
|
|
260
|
-
sys.path.insert(0, str(self.project_root / "src"))
|
|
261
|
-
from claude_mpm.config.socketio_config import SocketIOConfig
|
|
262
|
-
|
|
263
|
-
if environment == "production":
|
|
264
|
-
config = SocketIOConfig.for_production()
|
|
265
|
-
elif environment == "docker":
|
|
266
|
-
config = SocketIOConfig.for_docker()
|
|
267
|
-
else:
|
|
268
|
-
config = SocketIOConfig.for_development()
|
|
269
|
-
|
|
270
|
-
self.config_dir.mkdir(parents=True, exist_ok=True)
|
|
271
|
-
config_path = self.config_dir / 'socketio_config.json'
|
|
272
|
-
|
|
273
|
-
with open(config_path, 'w') as f:
|
|
274
|
-
json.dump(config.to_dict(), f, indent=2)
|
|
275
|
-
|
|
276
|
-
print(f"✅ Created configuration file: {config_path}")
|
|
277
|
-
return True
|
|
278
|
-
|
|
279
|
-
except Exception as e:
|
|
280
|
-
print(f"❌ Failed to create configuration file: {e}")
|
|
281
|
-
return False
|
|
282
|
-
|
|
283
|
-
def test_installation(self) -> bool:
|
|
284
|
-
"""Test the installation by checking imports and dependencies."""
|
|
285
|
-
print("Testing installation...")
|
|
286
|
-
|
|
287
|
-
try:
|
|
288
|
-
# Try to import the server module
|
|
289
|
-
sys.path.insert(0, str(self.project_root / "src"))
|
|
290
|
-
from claude_mpm.services.standalone_socketio_server import StandaloneSocketIOServer, SOCKETIO_AVAILABLE
|
|
291
|
-
|
|
292
|
-
if not SOCKETIO_AVAILABLE:
|
|
293
|
-
print("❌ Socket.IO dependencies not available")
|
|
294
|
-
return False
|
|
295
|
-
|
|
296
|
-
# Create a test server instance (this only tests initialization, not startup)
|
|
297
|
-
server = StandaloneSocketIOServer(port=8766) # Use different port for testing
|
|
298
|
-
|
|
299
|
-
# Check that the server was created properly
|
|
300
|
-
if server.server_version != "1.0.0":
|
|
301
|
-
print(f"❌ Unexpected server version: {server.server_version}")
|
|
302
|
-
return False
|
|
303
|
-
|
|
304
|
-
# Test that we can import client manager
|
|
305
|
-
from claude_mpm.services.socketio_client_manager import SocketIOClientManager
|
|
306
|
-
client_manager = SocketIOClientManager()
|
|
307
|
-
|
|
308
|
-
# Test configuration
|
|
309
|
-
from claude_mpm.config.socketio_config import get_config
|
|
310
|
-
config = get_config()
|
|
311
|
-
|
|
312
|
-
print("✅ Server module loads correctly")
|
|
313
|
-
print("✅ Client manager loads correctly")
|
|
314
|
-
print("✅ Configuration system works")
|
|
315
|
-
print("✅ Dependencies are properly installed")
|
|
316
|
-
return True
|
|
317
|
-
|
|
318
|
-
except ImportError as e:
|
|
319
|
-
print(f"❌ Import error - missing dependencies: {e}")
|
|
320
|
-
return False
|
|
321
|
-
except Exception as e:
|
|
322
|
-
print(f"❌ Installation test failed: {e}")
|
|
323
|
-
return False
|
|
324
|
-
|
|
325
|
-
def install(self, mode: str = "user", environment: str = "production",
|
|
326
|
-
create_service: bool = True) -> bool:
|
|
327
|
-
"""Perform complete installation."""
|
|
328
|
-
|
|
329
|
-
print(f"Installing Claude MPM Socket.IO Server for {self.platform}...")
|
|
330
|
-
print(f"Mode: {mode}, Environment: {environment}")
|
|
331
|
-
print()
|
|
332
|
-
|
|
333
|
-
# Step 1: Check and install dependencies
|
|
334
|
-
deps_ok, missing = self.check_dependencies()
|
|
335
|
-
if not deps_ok:
|
|
336
|
-
print(f"Missing dependencies: {missing}")
|
|
337
|
-
if not self.install_dependencies(missing):
|
|
338
|
-
return False
|
|
339
|
-
else:
|
|
340
|
-
print("✅ All dependencies are already installed")
|
|
341
|
-
|
|
342
|
-
# Step 2: Create startup script
|
|
343
|
-
if not self.create_startup_script(self.bin_dir):
|
|
344
|
-
return False
|
|
345
|
-
|
|
346
|
-
# Step 3: Create configuration file
|
|
347
|
-
if not self.create_config_file(environment):
|
|
348
|
-
return False
|
|
349
|
-
|
|
350
|
-
# Step 4: Create service file (optional)
|
|
351
|
-
if create_service:
|
|
352
|
-
user_mode = (mode == "user")
|
|
353
|
-
self.create_service_file(user_mode)
|
|
354
|
-
|
|
355
|
-
# Step 5: Test installation
|
|
356
|
-
if not self.test_installation():
|
|
357
|
-
print("⚠️ Installation completed but tests failed")
|
|
358
|
-
return False
|
|
359
|
-
|
|
360
|
-
print()
|
|
361
|
-
print("✅ Installation completed successfully!")
|
|
362
|
-
print()
|
|
363
|
-
print("Next steps:")
|
|
364
|
-
print(f" 1. Review configuration: {self.config_dir / 'socketio_config.json'}")
|
|
365
|
-
print(f" 2. Start server: {self.bin_dir / 'claude-mpm-socketio'}")
|
|
366
|
-
|
|
367
|
-
if create_service:
|
|
368
|
-
if self.platform == 'linux':
|
|
369
|
-
service_cmd = "systemctl --user start claude-mpm-socketio" if mode == "user" else "sudo systemctl start claude-mpm-socketio"
|
|
370
|
-
print(f" 3. Or start as service: {service_cmd}")
|
|
371
|
-
elif self.platform == 'darwin':
|
|
372
|
-
print(f" 3. Or load service: launchctl load {self.service_dir / 'com.claude-mpm.socketio.plist'}")
|
|
373
|
-
|
|
374
|
-
return True
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
def main():
|
|
378
|
-
"""Main CLI entry point."""
|
|
379
|
-
parser = argparse.ArgumentParser(description="Install Claude MPM Socket.IO Server")
|
|
380
|
-
|
|
381
|
-
parser.add_argument('--mode', choices=['user', 'system'], default='user',
|
|
382
|
-
help='Installation mode (user or system)')
|
|
383
|
-
parser.add_argument('--environment', choices=['development', 'production', 'docker'],
|
|
384
|
-
default='production', help='Target environment')
|
|
385
|
-
parser.add_argument('--no-service', action='store_true',
|
|
386
|
-
help='Skip service file creation')
|
|
387
|
-
parser.add_argument('--test-only', action='store_true',
|
|
388
|
-
help='Only test dependencies and installation')
|
|
389
|
-
|
|
390
|
-
args = parser.parse_args()
|
|
391
|
-
|
|
392
|
-
installer = SocketIOInstaller()
|
|
393
|
-
|
|
394
|
-
if args.test_only:
|
|
395
|
-
success = installer.test_installation()
|
|
396
|
-
else:
|
|
397
|
-
success = installer.install(
|
|
398
|
-
mode=args.mode,
|
|
399
|
-
environment=args.environment,
|
|
400
|
-
create_service=not args.no_service
|
|
401
|
-
)
|
|
402
|
-
|
|
403
|
-
sys.exit(0 if success else 1)
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
if __name__ == "__main__":
|
|
407
|
-
main()
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Simple monitor launcher for Claude MPM.
|
|
3
|
-
|
|
4
|
-
WHY: This script provides a streamlined solution for opening the static HTML
|
|
5
|
-
monitor that connects to any Socket.IO server. It eliminates server confusion
|
|
6
|
-
by separating the monitor client from the server.
|
|
7
|
-
|
|
8
|
-
DESIGN DECISION: Uses a static HTML file that can be opened directly in
|
|
9
|
-
the browser, connecting to whatever Socket.IO server is running. This
|
|
10
|
-
eliminates all confusion about which server serves what.
|
|
11
|
-
|
|
12
|
-
The script handles:
|
|
13
|
-
1. Opening the static HTML file in browser
|
|
14
|
-
2. Passing port as URL parameter
|
|
15
|
-
3. Port detection if server is running
|
|
16
|
-
4. Fallback to file:// protocol if needed
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
import argparse
|
|
20
|
-
import os
|
|
21
|
-
import sys
|
|
22
|
-
import webbrowser
|
|
23
|
-
import socket
|
|
24
|
-
from pathlib import Path
|
|
25
|
-
|
|
26
|
-
# Get script directory for relative paths
|
|
27
|
-
SCRIPT_DIR = Path(__file__).parent
|
|
28
|
-
MONITOR_HTML = SCRIPT_DIR / "claude_mpm_monitor.html"
|
|
29
|
-
|
|
30
|
-
def find_running_server():
|
|
31
|
-
"""Find any running Socket.IO server on common ports.
|
|
32
|
-
|
|
33
|
-
WHY: If a server is already running, we want to connect to it
|
|
34
|
-
automatically rather than requiring users to specify the port.
|
|
35
|
-
|
|
36
|
-
Returns:
|
|
37
|
-
int: Port number of running server, or None if not found
|
|
38
|
-
"""
|
|
39
|
-
common_ports = [8080, 8081, 8082, 3000, 3001, 5000]
|
|
40
|
-
|
|
41
|
-
for port in common_ports:
|
|
42
|
-
try:
|
|
43
|
-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
44
|
-
s.settimeout(0.5)
|
|
45
|
-
result = s.connect_ex(('127.0.0.1', port))
|
|
46
|
-
if result == 0:
|
|
47
|
-
print(f"✓ Found Socket.IO server on port {port}")
|
|
48
|
-
return port
|
|
49
|
-
except Exception:
|
|
50
|
-
continue
|
|
51
|
-
|
|
52
|
-
return None
|
|
53
|
-
|
|
54
|
-
def open_monitor(port: int = None):
|
|
55
|
-
"""Open the monitoring dashboard in browser.
|
|
56
|
-
|
|
57
|
-
WHY: Users need easy access to the monitoring dashboard. This function
|
|
58
|
-
handles URL construction and browser opening with the static HTML file.
|
|
59
|
-
|
|
60
|
-
Args:
|
|
61
|
-
port: Port number for the Socket.IO server (optional)
|
|
62
|
-
"""
|
|
63
|
-
if not MONITOR_HTML.exists():
|
|
64
|
-
print(f"❌ Monitor HTML file not found: {MONITOR_HTML}")
|
|
65
|
-
print(" Please ensure claude_mpm_monitor.html exists in the scripts directory")
|
|
66
|
-
sys.exit(1)
|
|
67
|
-
|
|
68
|
-
# Construct URL with port parameter if provided
|
|
69
|
-
file_url = f"file://{MONITOR_HTML.absolute()}"
|
|
70
|
-
if port:
|
|
71
|
-
file_url += f"?port={port}"
|
|
72
|
-
|
|
73
|
-
try:
|
|
74
|
-
print(f"🌐 Opening monitor: {file_url}")
|
|
75
|
-
webbrowser.open(file_url)
|
|
76
|
-
|
|
77
|
-
if port:
|
|
78
|
-
print(f"📊 Monitor will connect to Socket.IO server on port {port}")
|
|
79
|
-
else:
|
|
80
|
-
print(f"📊 Monitor opened - you can specify server port in the UI")
|
|
81
|
-
|
|
82
|
-
except Exception as e:
|
|
83
|
-
print(f"⚠️ Failed to open browser automatically: {e}")
|
|
84
|
-
print(f"📊 Please open manually: {file_url}")
|
|
85
|
-
|
|
86
|
-
def main():
|
|
87
|
-
"""Main entry point for the monitor launcher.
|
|
88
|
-
|
|
89
|
-
WHY: This provides a simple interface for opening the monitoring dashboard
|
|
90
|
-
with automatic server detection and port handling.
|
|
91
|
-
"""
|
|
92
|
-
parser = argparse.ArgumentParser(
|
|
93
|
-
description="Launch static HTML monitor for Claude MPM Socket.IO server",
|
|
94
|
-
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
95
|
-
epilog='''
|
|
96
|
-
Examples:
|
|
97
|
-
python launch_monitor.py # Auto-detect server or open with UI
|
|
98
|
-
python launch_monitor.py --port 8080 # Connect to specific port
|
|
99
|
-
python launch_monitor.py --no-detect # Skip auto-detection
|
|
100
|
-
'''
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
parser.add_argument('--port', type=int,
|
|
104
|
-
help='Socket.IO server port to connect to')
|
|
105
|
-
parser.add_argument('--no-detect', action='store_true',
|
|
106
|
-
help='Skip automatic server detection')
|
|
107
|
-
|
|
108
|
-
args = parser.parse_args()
|
|
109
|
-
|
|
110
|
-
print("📊 Claude MPM Monitor Launcher")
|
|
111
|
-
print("=" * 35)
|
|
112
|
-
|
|
113
|
-
port = args.port
|
|
114
|
-
|
|
115
|
-
# Auto-detect running server if no port specified
|
|
116
|
-
if not port and not args.no_detect:
|
|
117
|
-
print("🔍 Looking for running Socket.IO server...")
|
|
118
|
-
port = find_running_server()
|
|
119
|
-
|
|
120
|
-
if not port:
|
|
121
|
-
print("ℹ️ No running server detected - you can specify port in the UI")
|
|
122
|
-
|
|
123
|
-
# Open the monitor
|
|
124
|
-
open_monitor(port)
|
|
125
|
-
|
|
126
|
-
print("\n✅ Monitor launched successfully")
|
|
127
|
-
if port:
|
|
128
|
-
print(f" Connecting to: http://localhost:{port}")
|
|
129
|
-
print(f" HTML file: {MONITOR_HTML}")
|
|
130
|
-
|
|
131
|
-
if __name__ == "__main__":
|
|
132
|
-
main()
|