claude-mpm 3.4.2__py3-none-any.whl → 3.4.5__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.
@@ -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()