claude-mpm 5.6.1__py3-none-any.whl → 5.6.76__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 (131) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/PM_INSTRUCTIONS.md +8 -3
  3. claude_mpm/auth/__init__.py +35 -0
  4. claude_mpm/auth/callback_server.py +328 -0
  5. claude_mpm/auth/models.py +104 -0
  6. claude_mpm/auth/oauth_manager.py +266 -0
  7. claude_mpm/auth/providers/__init__.py +12 -0
  8. claude_mpm/auth/providers/base.py +165 -0
  9. claude_mpm/auth/providers/google.py +261 -0
  10. claude_mpm/auth/token_storage.py +252 -0
  11. claude_mpm/cli/commands/commander.py +174 -4
  12. claude_mpm/cli/commands/mcp.py +29 -17
  13. claude_mpm/cli/commands/mcp_command_router.py +39 -0
  14. claude_mpm/cli/commands/mcp_service_commands.py +304 -0
  15. claude_mpm/cli/commands/oauth.py +481 -0
  16. claude_mpm/cli/commands/skill_source.py +51 -2
  17. claude_mpm/cli/commands/skills.py +5 -3
  18. claude_mpm/cli/executor.py +9 -0
  19. claude_mpm/cli/helpers.py +1 -1
  20. claude_mpm/cli/parsers/base_parser.py +13 -0
  21. claude_mpm/cli/parsers/commander_parser.py +43 -10
  22. claude_mpm/cli/parsers/mcp_parser.py +79 -0
  23. claude_mpm/cli/parsers/oauth_parser.py +165 -0
  24. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  25. claude_mpm/cli/parsers/skills_parser.py +5 -0
  26. claude_mpm/cli/startup.py +300 -33
  27. claude_mpm/cli/startup_display.py +4 -2
  28. claude_mpm/cli/startup_migrations.py +236 -0
  29. claude_mpm/commander/__init__.py +6 -0
  30. claude_mpm/commander/adapters/__init__.py +32 -3
  31. claude_mpm/commander/adapters/auggie.py +260 -0
  32. claude_mpm/commander/adapters/base.py +98 -1
  33. claude_mpm/commander/adapters/claude_code.py +32 -1
  34. claude_mpm/commander/adapters/codex.py +237 -0
  35. claude_mpm/commander/adapters/example_usage.py +310 -0
  36. claude_mpm/commander/adapters/mpm.py +389 -0
  37. claude_mpm/commander/adapters/registry.py +204 -0
  38. claude_mpm/commander/api/app.py +32 -16
  39. claude_mpm/commander/api/errors.py +21 -0
  40. claude_mpm/commander/api/routes/messages.py +11 -11
  41. claude_mpm/commander/api/routes/projects.py +20 -20
  42. claude_mpm/commander/api/routes/sessions.py +37 -26
  43. claude_mpm/commander/api/routes/work.py +86 -50
  44. claude_mpm/commander/api/schemas.py +4 -0
  45. claude_mpm/commander/chat/cli.py +47 -5
  46. claude_mpm/commander/chat/commands.py +44 -16
  47. claude_mpm/commander/chat/repl.py +1729 -82
  48. claude_mpm/commander/config.py +5 -3
  49. claude_mpm/commander/core/__init__.py +10 -0
  50. claude_mpm/commander/core/block_manager.py +325 -0
  51. claude_mpm/commander/core/response_manager.py +323 -0
  52. claude_mpm/commander/daemon.py +215 -10
  53. claude_mpm/commander/env_loader.py +59 -0
  54. claude_mpm/commander/events/manager.py +61 -1
  55. claude_mpm/commander/frameworks/base.py +91 -1
  56. claude_mpm/commander/frameworks/mpm.py +9 -14
  57. claude_mpm/commander/git/__init__.py +5 -0
  58. claude_mpm/commander/git/worktree_manager.py +212 -0
  59. claude_mpm/commander/instance_manager.py +546 -15
  60. claude_mpm/commander/memory/__init__.py +45 -0
  61. claude_mpm/commander/memory/compression.py +347 -0
  62. claude_mpm/commander/memory/embeddings.py +230 -0
  63. claude_mpm/commander/memory/entities.py +310 -0
  64. claude_mpm/commander/memory/example_usage.py +290 -0
  65. claude_mpm/commander/memory/integration.py +325 -0
  66. claude_mpm/commander/memory/search.py +381 -0
  67. claude_mpm/commander/memory/store.py +657 -0
  68. claude_mpm/commander/models/events.py +6 -0
  69. claude_mpm/commander/persistence/state_store.py +95 -1
  70. claude_mpm/commander/registry.py +10 -4
  71. claude_mpm/commander/runtime/monitor.py +32 -2
  72. claude_mpm/commander/tmux_orchestrator.py +3 -2
  73. claude_mpm/commander/work/executor.py +38 -20
  74. claude_mpm/commander/workflow/event_handler.py +25 -3
  75. claude_mpm/config/skill_sources.py +16 -0
  76. claude_mpm/constants.py +5 -0
  77. claude_mpm/core/claude_runner.py +152 -0
  78. claude_mpm/core/config.py +30 -22
  79. claude_mpm/core/config_constants.py +74 -9
  80. claude_mpm/core/constants.py +56 -12
  81. claude_mpm/core/hook_manager.py +2 -1
  82. claude_mpm/core/interactive_session.py +5 -4
  83. claude_mpm/core/logger.py +16 -2
  84. claude_mpm/core/logging_utils.py +40 -16
  85. claude_mpm/core/network_config.py +148 -0
  86. claude_mpm/core/oneshot_session.py +7 -6
  87. claude_mpm/core/output_style_manager.py +37 -7
  88. claude_mpm/core/socketio_pool.py +47 -15
  89. claude_mpm/core/unified_paths.py +68 -80
  90. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +30 -31
  91. claude_mpm/hooks/claude_hooks/event_handlers.py +285 -194
  92. claude_mpm/hooks/claude_hooks/hook_handler.py +115 -32
  93. claude_mpm/hooks/claude_hooks/installer.py +222 -54
  94. claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
  95. claude_mpm/hooks/claude_hooks/response_tracking.py +40 -59
  96. claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
  97. claude_mpm/hooks/claude_hooks/services/connection_manager.py +25 -30
  98. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +24 -28
  99. claude_mpm/hooks/claude_hooks/services/container.py +326 -0
  100. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  101. claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
  102. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +49 -75
  103. claude_mpm/hooks/session_resume_hook.py +22 -18
  104. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  105. claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
  106. claude_mpm/init.py +21 -14
  107. claude_mpm/mcp/__init__.py +9 -0
  108. claude_mpm/mcp/google_workspace_server.py +610 -0
  109. claude_mpm/scripts/claude-hook-handler.sh +10 -9
  110. claude_mpm/services/agents/agent_selection_service.py +2 -2
  111. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  112. claude_mpm/services/command_deployment_service.py +44 -26
  113. claude_mpm/services/hook_installer_service.py +77 -8
  114. claude_mpm/services/mcp_config_manager.py +99 -19
  115. claude_mpm/services/mcp_service_registry.py +294 -0
  116. claude_mpm/services/monitor/server.py +6 -1
  117. claude_mpm/services/pm_skills_deployer.py +5 -3
  118. claude_mpm/services/skills/git_skill_source_manager.py +79 -8
  119. claude_mpm/services/skills/selective_skill_deployer.py +28 -0
  120. claude_mpm/services/skills/skill_discovery_service.py +17 -1
  121. claude_mpm/services/skills_deployer.py +31 -5
  122. claude_mpm/skills/__init__.py +2 -1
  123. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  124. claude_mpm/skills/registry.py +295 -90
  125. {claude_mpm-5.6.1.dist-info → claude_mpm-5.6.76.dist-info}/METADATA +28 -3
  126. {claude_mpm-5.6.1.dist-info → claude_mpm-5.6.76.dist-info}/RECORD +131 -93
  127. {claude_mpm-5.6.1.dist-info → claude_mpm-5.6.76.dist-info}/WHEEL +1 -1
  128. {claude_mpm-5.6.1.dist-info → claude_mpm-5.6.76.dist-info}/entry_points.txt +2 -0
  129. {claude_mpm-5.6.1.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE +0 -0
  130. {claude_mpm-5.6.1.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  131. {claude_mpm-5.6.1.dist-info → claude_mpm-5.6.76.dist-info}/top_level.txt +0 -0
@@ -2,9 +2,11 @@
2
2
 
3
3
  import asyncio
4
4
  import logging
5
+ from dataclasses import dataclass
5
6
  from pathlib import Path
6
7
  from typing import Optional
7
8
 
9
+ from claude_mpm.commander.env_loader import load_env
8
10
  from claude_mpm.commander.instance_manager import InstanceManager
9
11
  from claude_mpm.commander.llm.openrouter_client import (
10
12
  OpenRouterClient,
@@ -19,28 +21,61 @@ from claude_mpm.commander.tmux_orchestrator import TmuxOrchestrator
19
21
 
20
22
  from .repl import CommanderREPL
21
23
 
24
+ # Load environment variables at module import
25
+ load_env()
26
+
22
27
  logger = logging.getLogger(__name__)
23
28
 
24
29
 
30
+ @dataclass
31
+ class CommanderCLIConfig:
32
+ """Configuration for Commander CLI mode.
33
+
34
+ Attributes:
35
+ summarize_responses: Whether to use LLM to summarize instance responses
36
+ port: Port for internal services (reserved for future use)
37
+ state_dir: Directory for state persistence (optional)
38
+
39
+ Example:
40
+ >>> config = CommanderCLIConfig(summarize_responses=False)
41
+ """
42
+
43
+ summarize_responses: bool = True
44
+ port: int = 8765
45
+ state_dir: Optional[Path] = None
46
+
47
+
25
48
  async def run_commander(
26
49
  port: int = 8765,
27
50
  state_dir: Optional[Path] = None,
51
+ config: Optional[CommanderCLIConfig] = None,
28
52
  ) -> None:
29
53
  """Run Commander in interactive mode.
30
54
 
31
55
  Args:
32
56
  port: Port for internal services (unused currently).
33
57
  state_dir: Directory for state persistence (optional).
58
+ config: Commander CLI configuration (optional, uses defaults if None).
34
59
 
35
60
  Example:
36
61
  >>> asyncio.run(run_commander())
37
62
  # Starts interactive Commander REPL
63
+ >>> config = CommanderCLIConfig(summarize_responses=False)
64
+ >>> asyncio.run(run_commander(config=config))
65
+ # Starts Commander without response summarization
38
66
  """
39
- # Setup logging
67
+ # Use default config if not provided
68
+ if config is None:
69
+ config = CommanderCLIConfig(port=port, state_dir=state_dir)
70
+
71
+ # Setup logging - suppress noisy libraries
40
72
  logging.basicConfig(
41
73
  level=logging.INFO,
42
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
74
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
43
75
  )
76
+ # Suppress httpx request logging (very verbose)
77
+ logging.getLogger("httpx").setLevel(logging.WARNING)
78
+ logging.getLogger("httpcore").setLevel(logging.WARNING)
44
79
 
45
80
  # Initialize components
46
81
  logger.info("Initializing Commander...")
@@ -57,8 +92,8 @@ async def run_commander(
57
92
  # Try to initialize LLM client (optional)
58
93
  llm_client: Optional[OpenRouterClient] = None
59
94
  try:
60
- config = OpenRouterConfig()
61
- llm_client = OpenRouterClient(config)
95
+ llm_config = OpenRouterConfig()
96
+ llm_client = OpenRouterClient(llm_config)
62
97
  logger.info("LLM client initialized")
63
98
  except ValueError as e:
64
99
  logger.warning(f"LLM client not available: {e}")
@@ -68,7 +103,14 @@ async def run_commander(
68
103
  output_relay: Optional[OutputRelay] = None
69
104
  if llm_client:
70
105
  try:
71
- summarizer = OutputSummarizer(llm_client)
106
+ # Only create summarizer if summarize_responses is enabled
107
+ summarizer = None
108
+ if config.summarize_responses:
109
+ summarizer = OutputSummarizer(llm_client)
110
+ logger.info("Response summarization enabled")
111
+ else:
112
+ logger.info("Response summarization disabled")
113
+
72
114
  handler = OutputHandler(orchestrator, summarizer)
73
115
  formatter = OutputFormatter()
74
116
  output_relay = OutputRelay(handler, formatter)
@@ -11,12 +11,19 @@ class CommandType(Enum):
11
11
  LIST = "list"
12
12
  START = "start"
13
13
  STOP = "stop"
14
+ CLOSE = "close"
15
+ REGISTER = "register"
14
16
  CONNECT = "connect"
15
17
  DISCONNECT = "disconnect"
18
+ SAVED = "saved"
19
+ FORGET = "forget"
16
20
  STATUS = "status"
17
21
  HELP = "help"
18
22
  EXIT = "exit"
19
23
  INSTANCES = "instances" # alias for list
24
+ MPM_OAUTH = "mpm-oauth"
25
+ CLEANUP = "cleanup"
26
+ SEND = "send"
20
27
 
21
28
 
22
29
  @dataclass
@@ -31,27 +38,44 @@ class Command:
31
38
  class CommandParser:
32
39
  """Parses user input into commands."""
33
40
 
34
- ALIASES = {
41
+ # Map slash command names to CommandType
42
+ SLASH_COMMANDS = {
43
+ "register": CommandType.REGISTER,
44
+ "start": CommandType.START,
45
+ "stop": CommandType.STOP,
46
+ "close": CommandType.CLOSE,
47
+ "connect": CommandType.CONNECT,
48
+ "disconnect": CommandType.DISCONNECT,
49
+ "switch": CommandType.CONNECT, # alias for connect
50
+ "list": CommandType.LIST,
35
51
  "ls": CommandType.LIST,
36
- "instances": CommandType.LIST,
52
+ "saved": CommandType.SAVED,
53
+ "forget": CommandType.FORGET,
54
+ "status": CommandType.STATUS,
55
+ "help": CommandType.HELP,
56
+ "exit": CommandType.EXIT,
37
57
  "quit": CommandType.EXIT,
38
58
  "q": CommandType.EXIT,
59
+ "mpm-oauth": CommandType.MPM_OAUTH,
60
+ "cleanup": CommandType.CLEANUP,
61
+ "send": CommandType.SEND,
39
62
  }
40
63
 
41
64
  def parse(self, input_text: str) -> Optional[Command]:
42
65
  """Parse input into a Command.
43
66
 
44
- Returns None if input is not a built-in command (natural language).
67
+ Returns None if input is not a slash command (natural language).
68
+ System commands must start with '/'.
45
69
 
46
70
  Args:
47
71
  input_text: Raw user input.
48
72
 
49
73
  Returns:
50
- Command if input is a built-in command, None otherwise.
74
+ Command if input is a slash command, None otherwise.
51
75
 
52
76
  Example:
53
77
  >>> parser = CommandParser()
54
- >>> cmd = parser.parse("list")
78
+ >>> cmd = parser.parse("/list")
55
79
  >>> cmd.type
56
80
  <CommandType.LIST: 'list'>
57
81
  >>> parser.parse("tell me about the code")
@@ -60,22 +84,26 @@ class CommandParser:
60
84
  if not input_text:
61
85
  return None
62
86
 
63
- parts = input_text.split()
87
+ # System commands must start with /
88
+ if not input_text.startswith("/"):
89
+ return None
90
+
91
+ # Remove the leading / and parse
92
+ cmd_line = input_text[1:]
93
+ parts = cmd_line.split()
94
+ if not parts:
95
+ return None
96
+
64
97
  command_str = parts[0].lower()
65
98
  args = parts[1:] if len(parts) > 1 else []
66
99
 
67
- # Check if it's an alias
68
- if command_str in self.ALIASES:
69
- cmd_type = self.ALIASES[command_str]
100
+ # Check if it's a valid slash command
101
+ if command_str in self.SLASH_COMMANDS:
102
+ cmd_type = self.SLASH_COMMANDS[command_str]
70
103
  return Command(type=cmd_type, args=args, raw=input_text)
71
104
 
72
- # Check if it's a direct command
73
- try:
74
- cmd_type = CommandType(command_str)
75
- return Command(type=cmd_type, args=args, raw=input_text)
76
- except ValueError:
77
- # Not a built-in command
78
- return None
105
+ # Unknown slash command
106
+ return None
79
107
 
80
108
  def is_command(self, input_text: str) -> bool:
81
109
  """Check if input is a built-in command.