claude-mpm 4.2.25__py3-none-any.whl → 4.2.26__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 CHANGED
@@ -1 +1 @@
1
- 4.2.25
1
+ 4.2.26
@@ -151,7 +151,7 @@ class MonitorCommand(BaseCommand):
151
151
 
152
152
  def _stop_monitor(self, args) -> CommandResult:
153
153
  """Stop the unified monitor daemon."""
154
- self.logger.info("Stopping unified monitor daemon")
154
+ # Don't log here - the daemon will log when it stops
155
155
 
156
156
  # Get parameters from args or use defaults
157
157
  port = getattr(args, "port", None)
@@ -61,9 +61,20 @@ set -e
61
61
  # Get the directory where this script is located
62
62
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
63
63
 
64
- # Determine the claude-mpm root
65
- # The script is at src/claude_mpm/scripts/, so we go up 3 levels
66
- CLAUDE_MPM_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
64
+ # Determine the claude-mpm root based on installation type
65
+ # Check if we're in a pipx installation
66
+ if [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
67
+ # pipx installation - script is at lib/python*/site-packages/claude_mpm/scripts/
68
+ # The venv root is what we need for Python detection
69
+ CLAUDE_MPM_ROOT="$(echo "$SCRIPT_DIR" | sed 's|/lib/python.*/site-packages/.*||')"
70
+ elif [[ "$SCRIPT_DIR" == *"/site-packages/claude_mpm/scripts"* ]]; then
71
+ # Regular pip installation - script is in site-packages
72
+ # Use the Python environment root
73
+ CLAUDE_MPM_ROOT="$(python3 -c 'import sys; print(sys.prefix)')"
74
+ else
75
+ # Development installation - script is at src/claude_mpm/scripts/, so we go up 3 levels
76
+ CLAUDE_MPM_ROOT="$(cd "$SCRIPT_DIR/../../.." 2>/dev/null && pwd || echo "$SCRIPT_DIR")"
77
+ fi
67
78
 
68
79
  # Debug logging (can be enabled via environment variable)
69
80
  if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
@@ -102,7 +113,16 @@ fi
102
113
  # Absolute path to Python executable with claude-mpm dependencies
103
114
  #
104
115
  find_python_command() {
105
- # 1. Check for project-local virtual environment (common in development)
116
+ # 1. Check if we're in a pipx installation first
117
+ if [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
118
+ # pipx installation - use the pipx venv's Python directly
119
+ if [ -f "$CLAUDE_MPM_ROOT/bin/python" ]; then
120
+ echo "$CLAUDE_MPM_ROOT/bin/python"
121
+ return
122
+ fi
123
+ fi
124
+
125
+ # 2. Check for project-local virtual environment (common in development)
106
126
  if [ -f "$CLAUDE_MPM_ROOT/venv/bin/activate" ]; then
107
127
  source "$CLAUDE_MPM_ROOT/venv/bin/activate"
108
128
  echo "$CLAUDE_MPM_ROOT/venv/bin/python"
@@ -122,8 +142,14 @@ find_python_command() {
122
142
  # Set up Python command
123
143
  PYTHON_CMD=$(find_python_command)
124
144
 
125
- # Check if we're in a development environment (has src directory)
126
- if [ -d "$CLAUDE_MPM_ROOT/src" ]; then
145
+ # Check installation type and set PYTHONPATH accordingly
146
+ if [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
147
+ # pipx installation - claude_mpm is already in the venv's site-packages
148
+ # No need to modify PYTHONPATH
149
+ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
150
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] pipx installation detected" >> /tmp/claude-mpm-hook.log
151
+ fi
152
+ elif [ -d "$CLAUDE_MPM_ROOT/src" ]; then
127
153
  # Development install - add src to PYTHONPATH
128
154
  export PYTHONPATH="$CLAUDE_MPM_ROOT/src:$PYTHONPATH"
129
155
 
@@ -131,7 +157,7 @@ if [ -d "$CLAUDE_MPM_ROOT/src" ]; then
131
157
  echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Development environment detected" >> /tmp/claude-mpm-hook.log
132
158
  fi
133
159
  else
134
- # Pip install - claude_mpm should be in site-packages
160
+ # Regular pip install - claude_mpm should be in site-packages
135
161
  # No need to modify PYTHONPATH
136
162
  if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
137
163
  echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Pip installation detected" >> /tmp/claude-mpm-hook.log
@@ -102,6 +102,87 @@ class UnifiedMonitorDaemon:
102
102
  self.logger.error(f"Failed to start unified monitor daemon: {e}")
103
103
  return False
104
104
 
105
+ def _cleanup_port_conflicts(self) -> bool:
106
+ """Try to clean up any processes using our port.
107
+
108
+ Returns:
109
+ True if cleanup was successful, False otherwise
110
+ """
111
+ try:
112
+ # Find process using the port
113
+ import subprocess
114
+ result = subprocess.run(
115
+ ["lsof", "-ti", f":{self.port}"],
116
+ capture_output=True,
117
+ text=True
118
+ )
119
+
120
+ if result.returncode == 0 and result.stdout.strip():
121
+ pids = result.stdout.strip().split('\n')
122
+ for pid_str in pids:
123
+ try:
124
+ pid = int(pid_str.strip())
125
+ self.logger.info(f"Found process {pid} using port {self.port}")
126
+
127
+ # Check if it's a claude-mpm process
128
+ process_info = subprocess.run(
129
+ ["ps", "-p", str(pid), "-o", "comm="],
130
+ capture_output=True,
131
+ text=True
132
+ )
133
+
134
+ if "python" in process_info.stdout.lower() or "claude" in process_info.stdout.lower():
135
+ self.logger.info(f"Killing process {pid} (appears to be Python/Claude related)")
136
+ os.kill(pid, signal.SIGTERM)
137
+ time.sleep(1)
138
+
139
+ # Check if still alive
140
+ try:
141
+ os.kill(pid, 0)
142
+ # Still alive, force kill
143
+ self.logger.warning(f"Process {pid} didn't terminate, force killing")
144
+ os.kill(pid, signal.SIGKILL)
145
+ time.sleep(1)
146
+ except ProcessLookupError:
147
+ pass
148
+ else:
149
+ self.logger.warning(f"Process {pid} is not a Claude MPM process: {process_info.stdout}")
150
+ return False
151
+ except (ValueError, ProcessLookupError) as e:
152
+ self.logger.debug(f"Error handling PID {pid_str}: {e}")
153
+ continue
154
+
155
+ return True
156
+
157
+ except FileNotFoundError:
158
+ # lsof not available, try alternative method
159
+ self.logger.debug("lsof not available, using alternative cleanup")
160
+
161
+ # Check if there's an orphaned service we can identify
162
+ is_ours, pid = self.lifecycle.is_our_service(self.host)
163
+ if is_ours and pid:
164
+ try:
165
+ self.logger.info(f"Killing orphaned Claude MPM service (PID: {pid})")
166
+ os.kill(pid, signal.SIGTERM)
167
+ time.sleep(1)
168
+
169
+ # Check if still alive
170
+ try:
171
+ os.kill(pid, 0)
172
+ os.kill(pid, signal.SIGKILL)
173
+ time.sleep(1)
174
+ except ProcessLookupError:
175
+ pass
176
+
177
+ return True
178
+ except Exception as e:
179
+ self.logger.error(f"Failed to kill process: {e}")
180
+
181
+ except Exception as e:
182
+ self.logger.error(f"Error during port cleanup: {e}")
183
+
184
+ return False
185
+
105
186
  def _start_daemon(self, force_restart: bool = False) -> bool:
106
187
  """Start as background daemon process.
107
188
 
@@ -172,12 +253,26 @@ class UnifiedMonitorDaemon:
172
253
  self.logger.error(f"Failed to kill orphaned process: {e}")
173
254
  return False
174
255
 
175
- # Verify port is available before forking
256
+ # Check port availability and clean up if needed
176
257
  port_available, error_msg = self.lifecycle.verify_port_available(self.host)
177
258
  if not port_available:
178
- self.logger.error(error_msg)
179
- print(f"Error: {error_msg}", file=sys.stderr)
180
- return False
259
+ self.logger.warning(f"Port {self.port} is not available: {error_msg}")
260
+
261
+ # Try to identify and kill any process using the port
262
+ self.logger.info("Attempting to clean up processes on port...")
263
+ cleaned = self._cleanup_port_conflicts()
264
+
265
+ if cleaned:
266
+ # Wait a moment for port to be released
267
+ time.sleep(2)
268
+ # Check again
269
+ port_available, error_msg = self.lifecycle.verify_port_available(self.host)
270
+
271
+ if not port_available:
272
+ self.logger.error(f"Port {self.port} is still not available after cleanup: {error_msg}")
273
+ print(f"Error: {error_msg}", file=sys.stderr)
274
+ print(f"Try 'claude-mpm monitor stop' or use --force flag", file=sys.stderr)
275
+ return False
181
276
 
182
277
  # Wait for any pre-warming threads to complete before forking
183
278
  self._wait_for_prewarm_completion()
@@ -374,7 +469,7 @@ class UnifiedMonitorDaemon:
374
469
  pid = self.lifecycle.get_pid()
375
470
  if pid and pid != os.getpid():
376
471
  # We're not the daemon process, so stop it via signal
377
- self.logger.info(f"Stopping daemon process with PID {pid}")
472
+ # Don't log here - lifecycle.stop_daemon will log
378
473
  success = self.lifecycle.stop_daemon()
379
474
  if success:
380
475
  # Clean up our local state
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 4.2.25
3
+ Version: 4.2.26
4
4
  Summary: Claude Multi-Agent Project Manager - Orchestrate Claude with agent delegation and ticket tracking
5
5
  Author-email: Bob Matsuoka <bob@matsuoka.com>
6
6
  Maintainer: Claude MPM Team
@@ -1,5 +1,5 @@
1
1
  claude_mpm/BUILD_NUMBER,sha256=toytnNjkIKPgQaGwDqQdC1rpNTAdSEc6Vja50d7Ovug,4
2
- claude_mpm/VERSION,sha256=F3kdy3vpJ9R8KozaXUZLvXVrxx_9agbYiGj68dHh6gA,7
2
+ claude_mpm/VERSION,sha256=SQgB6WkCfQ-PDwm6SAsbMLZRb40PTP081FhoVTi1sfg,7
3
3
  claude_mpm/__init__.py,sha256=lyTZAYGH4DTaFGLRNWJKk5Q5oTjzN5I6AXmfVX-Jff0,1512
4
4
  claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
5
5
  claude_mpm/constants.py,sha256=I946iCQzIIPRZVVJ8aO7lA4euiyDnNw2IX7EelAOkIE,5915
@@ -83,7 +83,7 @@ claude_mpm/cli/commands/mcp_pipx_config.py,sha256=sE62VD6Q1CcO2k1nlbIhHMfAJFQTZf
83
83
  claude_mpm/cli/commands/mcp_server_commands.py,sha256=-1G_2Y5ScTvzDd-kY8fTAao2H6FH7DnsLimleF1rVqQ,6197
84
84
  claude_mpm/cli/commands/mcp_tool_commands.py,sha256=q17GzlFT3JiLTrDqwPO2tz1-fKmPO5QU449syTnKTz4,1283
85
85
  claude_mpm/cli/commands/memory.py,sha256=Yzfs3_oiKciv3sfOoDm2lJL4M9idG7ARV3-sNw1ge_g,26186
86
- claude_mpm/cli/commands/monitor.py,sha256=Is1b8l-hmMoGVwWyFHWrNztYf1Hsk5LVkaf3xHVazRc,9555
86
+ claude_mpm/cli/commands/monitor.py,sha256=Y4on91KW6Ye5NIglHnMVG8hhzw8ZRslBm1oMm6KC48s,9556
87
87
  claude_mpm/cli/commands/mpm_init.py,sha256=lO7N91ZHn_n18XbchUUcYoyme7L5NLcXVnhWm5F_Gq8,22367
88
88
  claude_mpm/cli/commands/mpm_init_handler.py,sha256=-pCB0XL3KipqGtnta8CC7Lg5TPMwstEhMFBcgF4aaa4,2919
89
89
  claude_mpm/cli/commands/run.py,sha256=qS3eolLiDrE8EXLQJioB6kL1ONr_l0c3OE3qMUJCqbA,43489
@@ -299,7 +299,7 @@ claude_mpm/models/agent_definition.py,sha256=LC7EwihixF2Gw4QqOxiCNchsEzzyQJPR6Ag
299
299
  claude_mpm/models/agent_session.py,sha256=7YU9oklwqEDyH3PTKUQ52yh6N9C9eJX8GJKhxDCpDj0,19988
300
300
  claude_mpm/schemas/__init__.py,sha256=2SLpkojJq34KnwPkVxrsVmw_cEI66872i75QBT1C2To,446
301
301
  claude_mpm/scripts/__init__.py,sha256=IffMdVD99Pxyw85yluRa0VDPi4dRQecIWce764pcfZE,553
302
- claude_mpm/scripts/claude-hook-handler.sh,sha256=86Ywf4lHpF9wTXmxo3lhFmcFS0wk1G3cSyHA71N8imI,6552
302
+ claude_mpm/scripts/claude-hook-handler.sh,sha256=xe6dKubrjK1JDO0SJdc1-tA6C7YSb5YazhwKhOYBQvw,7905
303
303
  claude_mpm/scripts/launch_monitor.py,sha256=Q7hN4Wurw45veLWPSXk0WfvkKxQ1Snz7TjZsV_pNWQc,2418
304
304
  claude_mpm/scripts/mcp_server.py,sha256=_i9ydtI7AcO-Eb7gzbIDbcJY4PKRQRYNobB8eMailI4,2259
305
305
  claude_mpm/scripts/mcp_wrapper.py,sha256=PvfHJShcsQHGJZD-RN3RnwLOzemAKYZ2kW_QfTkGzkk,1105
@@ -550,7 +550,7 @@ claude_mpm/services/memory/cache/__init__.py,sha256=6M6-P8ParyxX8vOgp_IxHgLMvacr
550
550
  claude_mpm/services/memory/cache/shared_prompt_cache.py,sha256=crnYPUT8zcS7TvoE1vW7pyaf4T77N5rJ1wUf_YQ2vvo,28704
551
551
  claude_mpm/services/memory/cache/simple_cache.py,sha256=qsTjbcsPxj-kNfaod9VN_uE5NioIwpfkUin_mMVUJCg,10218
552
552
  claude_mpm/services/monitor/__init__.py,sha256=X7gxSLUm9Fg_zEsX6LtCHP2ipF0qj6Emkun20h2So7g,745
553
- claude_mpm/services/monitor/daemon.py,sha256=R3w19ZLOFOO4PzRSZtP_ssM5LtNIzU8t5VpsvmBa7HA,23426
553
+ claude_mpm/services/monitor/daemon.py,sha256=pZqn_-1PBMf9gfIq8Zo55gXoXInB0gKNyOZpWGkdrxw,27731
554
554
  claude_mpm/services/monitor/event_emitter.py,sha256=JzRLNg8PUJ5s3ulNnq_D4yqCPItvidJzu8DmFxriieQ,12224
555
555
  claude_mpm/services/monitor/server.py,sha256=m98Eyv9caxRywJ4JtAdOuv5EB__z7vd2hYRZPwcqFLg,28498
556
556
  claude_mpm/services/monitor/handlers/__init__.py,sha256=jgPIf4IJVERm_tAeD9834tfx9IcxtlHj5r9rhEWpkfM,701
@@ -641,9 +641,9 @@ claude_mpm/utils/subprocess_utils.py,sha256=zgiwLqh_17WxHpySvUPH65pb4bzIeUGOAYUJ
641
641
  claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
642
642
  claude_mpm/validation/agent_validator.py,sha256=3Lo6LK-Mw9IdnL_bd3zl_R6FkgSVDYKUUM7EeVVD3jc,20865
643
643
  claude_mpm/validation/frontmatter_validator.py,sha256=u8g4Eyd_9O6ugj7Un47oSGh3kqv4wMkuks2i_CtWRvM,7028
644
- claude_mpm-4.2.25.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
645
- claude_mpm-4.2.25.dist-info/METADATA,sha256=pzcy651WgJLxqn8_pksv0ToWQXFCI8tLUqaCXw0h6dg,14451
646
- claude_mpm-4.2.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
647
- claude_mpm-4.2.25.dist-info/entry_points.txt,sha256=FDPZgz8JOvD-6iuXY2l9Zbo9zYVRuE4uz4Qr0vLeGOk,471
648
- claude_mpm-4.2.25.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
649
- claude_mpm-4.2.25.dist-info/RECORD,,
644
+ claude_mpm-4.2.26.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
645
+ claude_mpm-4.2.26.dist-info/METADATA,sha256=_oxZGDtNFYz4VX0vwQhEKz5cQFyw1bl3gcpiYXohypI,14451
646
+ claude_mpm-4.2.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
647
+ claude_mpm-4.2.26.dist-info/entry_points.txt,sha256=FDPZgz8JOvD-6iuXY2l9Zbo9zYVRuE4uz4Qr0vLeGOk,471
648
+ claude_mpm-4.2.26.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
649
+ claude_mpm-4.2.26.dist-info/RECORD,,