claude-mpm 4.0.20__py3-none-any.whl → 4.0.22__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.
Files changed (36) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/agents/INSTRUCTIONS.md +74 -0
  4. claude_mpm/agents/WORKFLOW.md +308 -4
  5. claude_mpm/agents/agents_metadata.py +52 -0
  6. claude_mpm/agents/base_agent_loader.py +75 -19
  7. claude_mpm/agents/templates/__init__.py +4 -0
  8. claude_mpm/agents/templates/api_qa.json +206 -0
  9. claude_mpm/agents/templates/research.json +24 -16
  10. claude_mpm/agents/templates/ticketing.json +18 -5
  11. claude_mpm/agents/templates/vercel_ops_agent.json +281 -0
  12. claude_mpm/agents/templates/vercel_ops_instructions.md +582 -0
  13. claude_mpm/cli/commands/mcp_command_router.py +87 -1
  14. claude_mpm/cli/commands/mcp_install_commands.py +207 -26
  15. claude_mpm/cli/parsers/mcp_parser.py +23 -0
  16. claude_mpm/constants.py +1 -0
  17. claude_mpm/core/base_service.py +7 -1
  18. claude_mpm/core/config.py +64 -39
  19. claude_mpm/core/framework_loader.py +68 -28
  20. claude_mpm/core/interactive_session.py +28 -17
  21. claude_mpm/scripts/socketio_daemon.py +67 -7
  22. claude_mpm/scripts/socketio_daemon_hardened.py +897 -0
  23. claude_mpm/services/agents/deployment/agent_deployment.py +65 -3
  24. claude_mpm/services/agents/deployment/async_agent_deployment.py +65 -1
  25. claude_mpm/services/agents/memory/agent_memory_manager.py +42 -203
  26. claude_mpm/services/memory_hook_service.py +62 -4
  27. claude_mpm/services/runner_configuration_service.py +5 -9
  28. claude_mpm/services/socketio/server/broadcaster.py +32 -1
  29. claude_mpm/services/socketio/server/core.py +4 -0
  30. claude_mpm/services/socketio/server/main.py +23 -4
  31. {claude_mpm-4.0.20.dist-info → claude_mpm-4.0.22.dist-info}/METADATA +1 -1
  32. {claude_mpm-4.0.20.dist-info → claude_mpm-4.0.22.dist-info}/RECORD +36 -32
  33. {claude_mpm-4.0.20.dist-info → claude_mpm-4.0.22.dist-info}/WHEEL +0 -0
  34. {claude_mpm-4.0.20.dist-info → claude_mpm-4.0.22.dist-info}/entry_points.txt +0 -0
  35. {claude_mpm-4.0.20.dist-info → claude_mpm-4.0.22.dist-info}/licenses/LICENSE +0 -0
  36. {claude_mpm-4.0.20.dist-info → claude_mpm-4.0.22.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,3 @@
1
- from pathlib import Path
2
-
3
1
  #!/usr/bin/env python3
4
2
  """
5
3
  Pure Python daemon management for Socket.IO server.
@@ -12,6 +10,64 @@ import signal
12
10
  import subprocess
13
11
  import sys
14
12
  import time
13
+ from pathlib import Path
14
+
15
+ # Detect and use virtual environment Python if available
16
+ def get_python_executable():
17
+ """
18
+ Get the appropriate Python executable, preferring virtual environment.
19
+
20
+ WHY: The daemon must use the same Python environment as the parent process
21
+ to ensure all dependencies are available. System Python won't have the
22
+ required packages installed.
23
+ """
24
+ # First, check if we're already in a virtual environment
25
+ if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix):
26
+ # We're in a virtual environment, use its Python
27
+ return sys.executable
28
+
29
+ # Check for common virtual environment indicators
30
+ # 1. VIRTUAL_ENV environment variable (most common)
31
+ venv_path = os.environ.get('VIRTUAL_ENV')
32
+ if venv_path:
33
+ venv_python = Path(venv_path) / 'bin' / 'python'
34
+ if venv_python.exists():
35
+ return str(venv_python)
36
+
37
+ # 2. Check if current executable is in a venv directory structure
38
+ exe_path = Path(sys.executable).resolve()
39
+ for parent in exe_path.parents:
40
+ # Check for common venv directory names
41
+ if parent.name in ('venv', '.venv', 'env', '.env'):
42
+ # This looks like a virtual environment
43
+ return sys.executable
44
+
45
+ # Check for typical venv structure (bin/python or Scripts/python.exe)
46
+ if parent.name == 'bin' and (parent.parent / 'pyvenv.cfg').exists():
47
+ return sys.executable
48
+ if parent.name == 'Scripts' and (parent.parent / 'pyvenv.cfg').exists():
49
+ return sys.executable
50
+
51
+ # 3. Try to detect project-specific venv
52
+ # Look for venv in the project root (going up from script location)
53
+ script_path = Path(__file__).resolve()
54
+ for parent in script_path.parents:
55
+ # Stop at src or when we've gone too far up
56
+ if parent.name == 'src' or not (parent / 'src').exists():
57
+ # Check for venv directories
58
+ for venv_name in ('venv', '.venv', 'env', '.env'):
59
+ venv_dir = parent / venv_name
60
+ if venv_dir.exists():
61
+ venv_python = venv_dir / 'bin' / 'python'
62
+ if venv_python.exists():
63
+ return str(venv_python)
64
+ break
65
+
66
+ # Fall back to current Python executable
67
+ return sys.executable
68
+
69
+ # Store the detected Python executable for daemon usage
70
+ PYTHON_EXECUTABLE = get_python_executable()
15
71
 
16
72
  import psutil
17
73
 
@@ -145,11 +201,12 @@ def start_server():
145
201
 
146
202
  ensure_dirs()
147
203
 
148
- # Fork to create daemon
204
+ # Fork to create daemon using the correct Python environment
149
205
  pid = os.fork()
150
206
  if pid > 0:
151
207
  # Parent process
152
208
  print(f"Starting Socket.IO server on port {selected_port} (PID: {pid})...")
209
+ print(f"Using Python: {PYTHON_EXECUTABLE}")
153
210
 
154
211
  # Register the instance
155
212
  instance_id = port_manager.register_instance(selected_port, pid)
@@ -179,10 +236,13 @@ def start_server():
179
236
  os.dup2(log.fileno(), sys.stdout.fileno())
180
237
  os.dup2(log.fileno(), sys.stderr.fileno())
181
238
 
182
- # Start server
239
+ # Log environment information for debugging
183
240
  print(
184
241
  f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Starting Socket.IO server on port {selected_port}..."
185
242
  )
243
+ print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Python executable: {sys.executable}")
244
+ print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Python version: {sys.version}")
245
+ print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Python path: {sys.path[:3]}...") # Show first 3 entries
186
246
  server = SocketIOServer(host="localhost", port=selected_port)
187
247
 
188
248
  # Handle signals
@@ -384,12 +444,12 @@ def main():
384
444
 
385
445
 
386
446
  if __name__ == "__main__":
387
- # Install psutil if not available
447
+ # Install psutil if not available (using correct Python)
388
448
  try:
389
449
  import psutil
390
450
  except ImportError:
391
- print("Installing psutil...")
392
- subprocess.check_call([sys.executable, "-m", "pip", "install", "psutil"])
451
+ print(f"Installing psutil using {PYTHON_EXECUTABLE}...")
452
+ subprocess.check_call([PYTHON_EXECUTABLE, "-m", "pip", "install", "psutil"])
393
453
  import psutil
394
454
 
395
455
  main()