claude-mpm 4.14.7__py3-none-any.whl → 4.14.8__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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (78) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/frontmatter_validator.py +284 -253
  3. claude_mpm/cli/__init__.py +34 -740
  4. claude_mpm/cli/commands/agent_manager.py +25 -12
  5. claude_mpm/cli/commands/agent_state_manager.py +186 -0
  6. claude_mpm/cli/commands/agents.py +204 -148
  7. claude_mpm/cli/commands/aggregate.py +7 -3
  8. claude_mpm/cli/commands/analyze.py +9 -4
  9. claude_mpm/cli/commands/analyze_code.py +7 -2
  10. claude_mpm/cli/commands/config.py +47 -13
  11. claude_mpm/cli/commands/configure.py +159 -1801
  12. claude_mpm/cli/commands/configure_agent_display.py +261 -0
  13. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  14. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  15. claude_mpm/cli/commands/configure_models.py +18 -0
  16. claude_mpm/cli/commands/configure_navigation.py +165 -0
  17. claude_mpm/cli/commands/configure_paths.py +104 -0
  18. claude_mpm/cli/commands/configure_persistence.py +254 -0
  19. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  20. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  21. claude_mpm/cli/commands/configure_validators.py +73 -0
  22. claude_mpm/cli/commands/memory.py +54 -20
  23. claude_mpm/cli/commands/mpm_init.py +35 -21
  24. claude_mpm/cli/executor.py +202 -0
  25. claude_mpm/cli/helpers.py +105 -0
  26. claude_mpm/cli/shared/output_formatters.py +28 -19
  27. claude_mpm/cli/startup.py +455 -0
  28. claude_mpm/core/enums.py +322 -0
  29. claude_mpm/core/instruction_reinforcement_hook.py +2 -1
  30. claude_mpm/core/interactive_session.py +6 -3
  31. claude_mpm/core/logging_config.py +6 -2
  32. claude_mpm/core/oneshot_session.py +8 -4
  33. claude_mpm/core/service_registry.py +5 -1
  34. claude_mpm/core/typing_utils.py +7 -6
  35. claude_mpm/hooks/instruction_reinforcement.py +7 -2
  36. claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
  37. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +3 -2
  38. claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
  39. claude_mpm/services/diagnostics/checks/installation_check.py +3 -2
  40. claude_mpm/services/diagnostics/checks/mcp_check.py +20 -6
  41. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +8 -7
  42. claude_mpm/services/memory_hook_service.py +4 -1
  43. claude_mpm/services/monitor/daemon_manager.py +3 -2
  44. claude_mpm/services/monitor/handlers/dashboard.py +2 -1
  45. claude_mpm/services/monitor/handlers/hooks.py +2 -1
  46. claude_mpm/services/monitor/management/lifecycle.py +3 -2
  47. claude_mpm/services/monitor/server.py +2 -1
  48. claude_mpm/services/session_management_service.py +3 -2
  49. claude_mpm/services/socketio/handlers/hook.py +3 -2
  50. claude_mpm/services/socketio/server/main.py +3 -1
  51. claude_mpm/services/subprocess_launcher_service.py +14 -5
  52. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +6 -5
  53. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +5 -4
  54. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +5 -4
  55. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +4 -3
  56. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +4 -3
  57. claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
  58. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
  59. claude_mpm/services/unified/deployment_strategies/local.py +3 -2
  60. claude_mpm/services/unified/deployment_strategies/utils.py +2 -1
  61. claude_mpm/services/unified/deployment_strategies/vercel.py +2 -1
  62. claude_mpm/services/unified/interfaces.py +3 -1
  63. claude_mpm/services/unified/unified_analyzer.py +7 -6
  64. claude_mpm/services/unified/unified_config.py +2 -1
  65. claude_mpm/services/unified/unified_deployment.py +7 -2
  66. claude_mpm/tools/code_tree_analyzer.py +177 -141
  67. claude_mpm/tools/code_tree_events.py +4 -2
  68. {claude_mpm-4.14.7.dist-info → claude_mpm-4.14.8.dist-info}/METADATA +1 -1
  69. {claude_mpm-4.14.7.dist-info → claude_mpm-4.14.8.dist-info}/RECORD +73 -63
  70. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
  71. claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
  72. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
  73. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
  74. claude_mpm/services/project/analyzer_refactored.py +0 -450
  75. {claude_mpm-4.14.7.dist-info → claude_mpm-4.14.8.dist-info}/WHEEL +0 -0
  76. {claude_mpm-4.14.7.dist-info → claude_mpm-4.14.8.dist-info}/entry_points.txt +0 -0
  77. {claude_mpm-4.14.7.dist-info → claude_mpm-4.14.8.dist-info}/licenses/LICENSE +0 -0
  78. {claude_mpm-4.14.7.dist-info → claude_mpm-4.14.8.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,455 @@
1
+ """
2
+ CLI Startup Functions
3
+ =====================
4
+
5
+ This module contains initialization functions that run on CLI startup,
6
+ including project registry, MCP configuration, and update checks.
7
+
8
+ Part of cli/__init__.py refactoring to reduce file size and improve modularity.
9
+ """
10
+
11
+ import os
12
+ import sys
13
+
14
+
15
+ def setup_early_environment(argv):
16
+ """
17
+ Set up early environment variables and logging suppression.
18
+
19
+ WHY: Some commands need special environment handling before any logging
20
+ or service initialization occurs.
21
+
22
+ Args:
23
+ argv: Command line arguments
24
+
25
+ Returns:
26
+ Processed argv list
27
+ """
28
+ # Disable telemetry and set cleanup flags early
29
+ os.environ.setdefault("DISABLE_TELEMETRY", "1")
30
+ os.environ.setdefault("CLAUDE_MPM_SKIP_CLEANUP", "0")
31
+
32
+ # EARLY CHECK: Suppress logging for configure command
33
+ if argv is None:
34
+ argv = sys.argv[1:]
35
+ if "configure" in argv or (len(argv) > 0 and argv[0] == "configure"):
36
+ import logging
37
+
38
+ logging.getLogger("claude_mpm").setLevel(logging.WARNING)
39
+ os.environ["CLAUDE_MPM_SKIP_CLEANUP"] = "1"
40
+
41
+ return argv
42
+
43
+
44
+ def should_skip_background_services(args, processed_argv):
45
+ """
46
+ Determine if background services should be skipped for this command.
47
+
48
+ WHY: Some commands (help, version, configure, doctor) don't need
49
+ background services and should start faster.
50
+
51
+ Args:
52
+ args: Parsed arguments
53
+ processed_argv: Processed command line arguments
54
+
55
+ Returns:
56
+ bool: True if background services should be skipped
57
+ """
58
+ skip_commands = ["--version", "-v", "--help", "-h"]
59
+ return any(cmd in (processed_argv or sys.argv[1:]) for cmd in skip_commands) or (
60
+ hasattr(args, "command")
61
+ and args.command in ["info", "doctor", "config", "mcp", "configure"]
62
+ )
63
+
64
+
65
+ def setup_configure_command_environment(args):
66
+ """
67
+ Set up special environment for configure command.
68
+
69
+ WHY: Configure command needs clean state without background services
70
+ and with suppressed logging.
71
+
72
+ Args:
73
+ args: Parsed arguments
74
+ """
75
+ if hasattr(args, "command") and args.command == "configure":
76
+ os.environ["CLAUDE_MPM_SKIP_CLEANUP"] = "1"
77
+ import logging
78
+
79
+ logging.getLogger("claude_mpm").setLevel(logging.WARNING)
80
+
81
+
82
+ def run_background_services():
83
+ """
84
+ Initialize all background services on startup.
85
+
86
+ WHY: Centralizes all startup service initialization for cleaner main().
87
+ """
88
+ initialize_project_registry()
89
+ check_mcp_auto_configuration()
90
+ verify_mcp_gateway_startup()
91
+ check_for_updates_async()
92
+
93
+
94
+ def setup_mcp_server_logging(args):
95
+ """
96
+ Configure minimal logging for MCP server mode.
97
+
98
+ WHY: MCP server needs minimal stderr-only logging to avoid interfering
99
+ with stdout protocol communication.
100
+
101
+ Args:
102
+ args: Parsed arguments
103
+
104
+ Returns:
105
+ Configured logger
106
+ """
107
+ import logging
108
+
109
+ from ..cli.utils import setup_logging
110
+ from ..constants import CLICommands
111
+
112
+ if (
113
+ args.command == CLICommands.MCP.value
114
+ and getattr(args, "mcp_command", None) == "start"
115
+ ):
116
+ if not getattr(args, "test", False) and not getattr(
117
+ args, "instructions", False
118
+ ):
119
+ # Production MCP mode - minimal logging
120
+ logging.basicConfig(
121
+ level=logging.ERROR,
122
+ format="%(message)s",
123
+ stream=sys.stderr,
124
+ force=True,
125
+ )
126
+ return logging.getLogger("claude_mpm")
127
+ # Test or instructions mode - normal logging
128
+ return setup_logging(args)
129
+ # Normal logging for all other commands
130
+ return setup_logging(args)
131
+
132
+
133
+ def initialize_project_registry():
134
+ """
135
+ Initialize or update the project registry for the current session.
136
+
137
+ WHY: The project registry tracks all claude-mpm projects and their metadata
138
+ across sessions. This function ensures the current project is properly
139
+ registered and updates session information.
140
+
141
+ DESIGN DECISION: Registry failures are logged but don't prevent startup
142
+ to ensure claude-mpm remains functional even if registry operations fail.
143
+ """
144
+ try:
145
+ from ..services.project.registry import ProjectRegistry
146
+
147
+ registry = ProjectRegistry()
148
+ registry.get_or_create_project_entry()
149
+ except Exception as e:
150
+ # Import logger here to avoid circular imports
151
+ from ..core.logger import get_logger
152
+
153
+ logger = get_logger("cli")
154
+ logger.debug(f"Failed to initialize project registry: {e}")
155
+ # Continue execution - registry failure shouldn't block startup
156
+
157
+
158
+ def check_mcp_auto_configuration():
159
+ """
160
+ Check and potentially auto-configure MCP for pipx installations.
161
+
162
+ WHY: Users installing via pipx should have MCP work out-of-the-box with
163
+ minimal friction. This function offers one-time auto-configuration with
164
+ user consent.
165
+
166
+ DESIGN DECISION: This is blocking but quick - it only runs once and has
167
+ a 10-second timeout. We want to catch users on first run for the best
168
+ experience.
169
+ """
170
+ try:
171
+ from ..services.mcp_gateway.auto_configure import check_and_configure_mcp
172
+
173
+ # This function handles all the logic:
174
+ # - Checks if already configured
175
+ # - Checks if pipx installation
176
+ # - Checks if already asked before
177
+ # - Prompts user if needed
178
+ # - Configures if user agrees
179
+ check_and_configure_mcp()
180
+
181
+ except Exception as e:
182
+ # Non-critical - log but don't fail
183
+ from ..core.logger import get_logger
184
+
185
+ logger = get_logger("cli")
186
+ logger.debug(f"MCP auto-configuration check failed: {e}")
187
+
188
+ # Skip MCP service fixes for the doctor and configure commands
189
+ # The doctor command performs its own comprehensive MCP service check
190
+ # The configure command allows users to configure which services to enable
191
+ # Running both would cause duplicate checks and log messages (9 seconds apart)
192
+ if len(sys.argv) > 1 and sys.argv[1] in ("doctor", "configure"):
193
+ return
194
+
195
+ # Also ensure MCP services are properly configured in ~/.claude.json
196
+ # This fixes incorrect paths and adds missing services
197
+ try:
198
+ from ..core.logger import get_logger
199
+ from ..services.mcp_config_manager import MCPConfigManager
200
+
201
+ logger = get_logger("cli")
202
+ mcp_manager = MCPConfigManager()
203
+
204
+ # Fix any corrupted installations first
205
+ fix_success, fix_message = mcp_manager.fix_mcp_service_issues()
206
+ if fix_message and "Fixed:" in fix_message:
207
+ logger.info(f"MCP service fixes applied: {fix_message}")
208
+
209
+ # Ensure all services are configured correctly
210
+ config_success, config_message = mcp_manager.ensure_mcp_services_configured()
211
+ if config_message and "Added MCP services" in config_message:
212
+ logger.info(f"MCP services configured: {config_message}")
213
+
214
+ except Exception as e:
215
+ # Non-critical - log but don't fail
216
+ from ..core.logger import get_logger
217
+
218
+ logger = get_logger("cli")
219
+ logger.debug(f"MCP services configuration update failed: {e}")
220
+
221
+
222
+ def verify_mcp_gateway_startup():
223
+ """
224
+ Verify MCP Gateway configuration on startup and pre-warm MCP services.
225
+
226
+ WHY: The MCP gateway should be automatically configured and verified on startup
227
+ to provide a seamless experience with diagnostic tools, file summarizer, and
228
+ ticket service. Pre-warming MCP services eliminates the 11.9s delay on first use.
229
+
230
+ DESIGN DECISION: This is non-blocking - failures are logged but don't prevent
231
+ startup to ensure claude-mpm remains functional even if MCP gateway has issues.
232
+ """
233
+ # Quick verification of MCP services installation
234
+ try:
235
+ from ..core.logger import get_logger
236
+ from ..services.mcp_service_verifier import verify_mcp_services_on_startup
237
+
238
+ logger = get_logger("mcp_verify")
239
+ all_ok, message = verify_mcp_services_on_startup()
240
+ if not all_ok:
241
+ logger.warning(message)
242
+ except Exception:
243
+ # Non-critical - continue with startup
244
+ pass
245
+
246
+ try:
247
+ import asyncio
248
+ import time
249
+
250
+ from ..core.logger import get_logger
251
+ from ..services.mcp_gateway.core.startup_verification import (
252
+ is_mcp_gateway_configured,
253
+ verify_mcp_gateway_on_startup,
254
+ )
255
+
256
+ logger = get_logger("mcp_prewarm")
257
+
258
+ # Quick check first - if already configured, skip detailed verification
259
+ gateway_configured = is_mcp_gateway_configured()
260
+
261
+ # DISABLED: Pre-warming MCP servers can interfere with Claude Code's MCP management
262
+ # This was causing issues with MCP server initialization and stderr handling
263
+ # def run_pre_warming():
264
+ # loop = None
265
+ # try:
266
+ # start_time = time.time()
267
+ # loop = asyncio.new_event_loop()
268
+ # asyncio.set_event_loop(loop)
269
+ #
270
+ # # Pre-warm MCP servers (especially vector search)
271
+ # logger.info("Pre-warming MCP servers to eliminate startup delay...")
272
+ # loop.run_until_complete(pre_warm_mcp_servers())
273
+ #
274
+ # pre_warm_time = time.time() - start_time
275
+ # if pre_warm_time > 1.0:
276
+ # logger.info(f"MCP servers pre-warmed in {pre_warm_time:.2f}s")
277
+
278
+ # Dummy function to maintain structure
279
+ def run_pre_warming():
280
+ loop = None
281
+ try:
282
+ time.time()
283
+ loop = asyncio.new_event_loop()
284
+ asyncio.set_event_loop(loop)
285
+
286
+ # Also run gateway verification if needed
287
+ if not gateway_configured:
288
+ loop.run_until_complete(verify_mcp_gateway_on_startup())
289
+
290
+ except Exception as e:
291
+ # Non-blocking - log but don't fail
292
+ logger.debug(f"MCP pre-warming error (non-critical): {e}")
293
+ finally:
294
+ # Properly clean up event loop to prevent kqueue warnings
295
+ if loop is not None:
296
+ try:
297
+ # Cancel all running tasks
298
+ pending = asyncio.all_tasks(loop)
299
+ for task in pending:
300
+ task.cancel()
301
+ # Wait for tasks to complete cancellation
302
+ if pending:
303
+ loop.run_until_complete(
304
+ asyncio.gather(*pending, return_exceptions=True)
305
+ )
306
+ except Exception:
307
+ pass # Ignore cleanup errors
308
+ finally:
309
+ loop.close()
310
+ # Clear the event loop reference to help with cleanup
311
+ asyncio.set_event_loop(None)
312
+
313
+ # Run pre-warming in background thread
314
+ import threading
315
+
316
+ pre_warm_thread = threading.Thread(target=run_pre_warming, daemon=True)
317
+ pre_warm_thread.start()
318
+
319
+ return
320
+
321
+ # Run detailed verification in background if not configured
322
+ if not gateway_configured:
323
+ # Note: We don't await this to avoid blocking startup
324
+ def run_verification():
325
+ loop = None
326
+ try:
327
+ loop = asyncio.new_event_loop()
328
+ asyncio.set_event_loop(loop)
329
+ results = loop.run_until_complete(verify_mcp_gateway_on_startup())
330
+
331
+ # Log results but don't block
332
+ from ..core.logger import get_logger
333
+
334
+ logger = get_logger("cli")
335
+
336
+ if results.get("gateway_configured"):
337
+ logger.debug("MCP Gateway verification completed successfully")
338
+ else:
339
+ logger.debug("MCP Gateway verification completed with warnings")
340
+
341
+ except Exception as e:
342
+ from ..core.logger import get_logger
343
+
344
+ logger = get_logger("cli")
345
+ logger.debug(f"MCP Gateway verification failed: {e}")
346
+ finally:
347
+ # Properly clean up event loop to prevent kqueue warnings
348
+ if loop is not None:
349
+ try:
350
+ # Cancel all running tasks
351
+ pending = asyncio.all_tasks(loop)
352
+ for task in pending:
353
+ task.cancel()
354
+ # Wait for tasks to complete cancellation
355
+ if pending:
356
+ loop.run_until_complete(
357
+ asyncio.gather(*pending, return_exceptions=True)
358
+ )
359
+ except Exception:
360
+ pass # Ignore cleanup errors
361
+ finally:
362
+ loop.close()
363
+ # Clear the event loop reference to help with cleanup
364
+ asyncio.set_event_loop(None)
365
+
366
+ # Run in background thread to avoid blocking startup
367
+ import threading
368
+
369
+ verification_thread = threading.Thread(target=run_verification, daemon=True)
370
+ verification_thread.start()
371
+
372
+ except Exception as e:
373
+ # Import logger here to avoid circular imports
374
+ from ..core.logger import get_logger
375
+
376
+ logger = get_logger("cli")
377
+ logger.debug(f"Failed to start MCP Gateway verification: {e}")
378
+ # Continue execution - MCP gateway issues shouldn't block startup
379
+
380
+
381
+ def check_for_updates_async():
382
+ """
383
+ Check for updates in background thread (non-blocking).
384
+
385
+ WHY: Users should be notified of new versions and have an easy way to upgrade
386
+ without manually checking PyPI/npm. This runs asynchronously on startup to avoid
387
+ blocking the CLI.
388
+
389
+ DESIGN DECISION: This is non-blocking and non-critical - failures are logged
390
+ but don't prevent startup. Only runs for pip/pipx/npm installations, skips
391
+ editable/development installations.
392
+ """
393
+
394
+ def run_update_check():
395
+ """Inner function to run in background thread."""
396
+ loop = None
397
+ try:
398
+ import asyncio
399
+
400
+ from ..core.logger import get_logger
401
+ from ..services.self_upgrade_service import SelfUpgradeService
402
+
403
+ logger = get_logger("upgrade_check")
404
+
405
+ # Create new event loop for this thread
406
+ loop = asyncio.new_event_loop()
407
+ asyncio.set_event_loop(loop)
408
+
409
+ # Create upgrade service and check for updates
410
+ upgrade_service = SelfUpgradeService()
411
+
412
+ # Skip for editable installs (development mode)
413
+ from ..services.self_upgrade_service import InstallationMethod
414
+
415
+ if upgrade_service.installation_method == InstallationMethod.EDITABLE:
416
+ logger.debug("Skipping version check for editable installation")
417
+ return
418
+
419
+ # Check and prompt for upgrade if available (non-blocking)
420
+ loop.run_until_complete(upgrade_service.check_and_prompt_on_startup())
421
+
422
+ except Exception as e:
423
+ # Non-critical - log but don't fail startup
424
+ try:
425
+ from ..core.logger import get_logger
426
+
427
+ logger = get_logger("upgrade_check")
428
+ logger.debug(f"Update check failed (non-critical): {e}")
429
+ except Exception:
430
+ pass # Avoid any errors in error handling
431
+ finally:
432
+ # Properly clean up event loop
433
+ if loop is not None:
434
+ try:
435
+ # Cancel all running tasks
436
+ pending = asyncio.all_tasks(loop)
437
+ for task in pending:
438
+ task.cancel()
439
+ # Wait for tasks to complete cancellation
440
+ if pending:
441
+ loop.run_until_complete(
442
+ asyncio.gather(*pending, return_exceptions=True)
443
+ )
444
+ except Exception:
445
+ pass # Ignore cleanup errors
446
+ finally:
447
+ loop.close()
448
+ # Clear the event loop reference to help with cleanup
449
+ asyncio.set_event_loop(None)
450
+
451
+ # Run update check in background thread to avoid blocking startup
452
+ import threading
453
+
454
+ update_check_thread = threading.Thread(target=run_update_check, daemon=True)
455
+ update_check_thread.start()