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
@@ -0,0 +1,212 @@
1
+ """Git worktree manager for session isolation."""
2
+
3
+ import logging
4
+ import subprocess # nosec B404 - subprocess needed for git commands
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ @dataclass
13
+ class WorktreeInfo:
14
+ """Info about a git worktree."""
15
+
16
+ name: str
17
+ path: Path
18
+ branch: str
19
+ base_path: Path # Original repo path
20
+
21
+
22
+ class WorktreeManager:
23
+ """Manages git worktrees for session isolation."""
24
+
25
+ def __init__(self, base_path: Path):
26
+ """Initialize with base project path."""
27
+ self.base_path = Path(base_path)
28
+ self.worktrees_dir = self.base_path.parent / f".worktrees-{self.base_path.name}"
29
+
30
+ def create(self, name: str, branch: Optional[str] = None) -> WorktreeInfo:
31
+ """Create a worktree for a session.
32
+
33
+ Args:
34
+ name: Session/worktree name (e.g., "izzie")
35
+ branch: Branch name, defaults to session-{name}
36
+
37
+ Returns:
38
+ WorktreeInfo with path and branch details
39
+ """
40
+ branch = branch or f"session-{name}"
41
+ worktree_path = self.worktrees_dir / name
42
+
43
+ # Ensure worktrees directory exists
44
+ self.worktrees_dir.mkdir(parents=True, exist_ok=True)
45
+
46
+ # Check if worktree already exists
47
+ if worktree_path.exists():
48
+ logger.info(f"Worktree '{name}' already exists at {worktree_path}")
49
+ return self._get_worktree_info(name, worktree_path)
50
+
51
+ # Create new branch if it doesn't exist
52
+ try:
53
+ subprocess.run( # nosec B603 B607 - git command with safe args
54
+ ["git", "branch", branch],
55
+ cwd=self.base_path,
56
+ capture_output=True,
57
+ check=False, # Branch may already exist
58
+ )
59
+ except Exception as e:
60
+ logger.warning(f"Could not create branch {branch}: {e}")
61
+
62
+ # Create worktree
63
+ result = subprocess.run( # nosec B603 B607 - git command with safe args
64
+ ["git", "worktree", "add", str(worktree_path), branch],
65
+ check=False,
66
+ cwd=self.base_path,
67
+ capture_output=True,
68
+ text=True,
69
+ )
70
+
71
+ if result.returncode != 0:
72
+ raise RuntimeError(f"Failed to create worktree: {result.stderr}")
73
+
74
+ logger.info(f"Created worktree '{name}' at {worktree_path} on branch {branch}")
75
+ return WorktreeInfo(
76
+ name=name, path=worktree_path, branch=branch, base_path=self.base_path
77
+ )
78
+
79
+ def _get_worktree_info(self, name: str, path: Path) -> WorktreeInfo:
80
+ """Get info for existing worktree."""
81
+ result = subprocess.run( # nosec B603 B607 - git command with safe args
82
+ ["git", "branch", "--show-current"],
83
+ check=False,
84
+ cwd=path,
85
+ capture_output=True,
86
+ text=True,
87
+ )
88
+ branch = result.stdout.strip() or f"session-{name}"
89
+ return WorktreeInfo(
90
+ name=name, path=path, branch=branch, base_path=self.base_path
91
+ )
92
+
93
+ def list(self) -> list[WorktreeInfo]:
94
+ """List all worktrees for this project."""
95
+ result = subprocess.run( # nosec B603 B607 - git command with safe args
96
+ ["git", "worktree", "list", "--porcelain"],
97
+ check=False,
98
+ cwd=self.base_path,
99
+ capture_output=True,
100
+ text=True,
101
+ )
102
+
103
+ worktrees = []
104
+ current_path = None
105
+ current_branch = None
106
+
107
+ for line in result.stdout.strip().split("\n"):
108
+ if line.startswith("worktree "):
109
+ current_path = Path(line.split(" ", 1)[1])
110
+ elif line.startswith("branch "):
111
+ current_branch = line.split("/")[-1] # refs/heads/branch -> branch
112
+ elif line == "":
113
+ if current_path and str(self.worktrees_dir) in str(current_path):
114
+ name = current_path.name
115
+ worktrees.append(
116
+ WorktreeInfo(
117
+ name=name,
118
+ path=current_path,
119
+ branch=current_branch or f"session-{name}",
120
+ base_path=self.base_path,
121
+ )
122
+ )
123
+ current_path = None
124
+ current_branch = None
125
+
126
+ return worktrees
127
+
128
+ def remove(self, name: str, force: bool = False) -> bool:
129
+ """Remove a worktree."""
130
+ worktree_path = self.worktrees_dir / name
131
+
132
+ if not worktree_path.exists():
133
+ return False
134
+
135
+ args = ["git", "worktree", "remove", str(worktree_path)]
136
+ if force:
137
+ args.insert(3, "--force")
138
+
139
+ result = subprocess.run( # nosec B603 B607 - git command with safe args
140
+ args, check=False, cwd=self.base_path, capture_output=True, text=True
141
+ )
142
+ return result.returncode == 0
143
+
144
+ def get(self, name: str) -> Optional[WorktreeInfo]:
145
+ """Get worktree by name."""
146
+ worktree_path = self.worktrees_dir / name
147
+ if worktree_path.exists():
148
+ return self._get_worktree_info(name, worktree_path)
149
+ return None
150
+
151
+ def merge_to_main(self, name: str, delete_after: bool = True) -> tuple[bool, str]:
152
+ """Merge worktree branch back to main and optionally delete worktree.
153
+
154
+ Args:
155
+ name: Worktree name to merge
156
+ delete_after: Remove worktree after merge (default True)
157
+
158
+ Returns:
159
+ Tuple of (success, message)
160
+ """
161
+ worktree = self.get(name)
162
+ if not worktree:
163
+ return False, f"Worktree '{name}' not found"
164
+
165
+ # Get main branch name
166
+ result = subprocess.run( # nosec B603 B607 - git command with safe args
167
+ ["git", "symbolic-ref", "refs/remotes/origin/HEAD"],
168
+ check=False,
169
+ cwd=self.base_path,
170
+ capture_output=True,
171
+ text=True,
172
+ )
173
+ main_branch = (
174
+ result.stdout.strip().split("/")[-1] if result.returncode == 0 else "main"
175
+ )
176
+
177
+ # Checkout main in base repo
178
+ checkout_result = subprocess.run( # nosec B603 B607 - git command with safe args
179
+ ["git", "checkout", main_branch],
180
+ check=False,
181
+ cwd=self.base_path,
182
+ capture_output=True,
183
+ text=True,
184
+ )
185
+ if checkout_result.returncode != 0:
186
+ return False, f"Failed to checkout {main_branch}: {checkout_result.stderr}"
187
+
188
+ # Merge worktree branch
189
+ merge_result = subprocess.run( # nosec B603 B607 - git command with safe args
190
+ ["git", "merge", worktree.branch, "--no-edit"],
191
+ check=False,
192
+ cwd=self.base_path,
193
+ capture_output=True,
194
+ text=True,
195
+ )
196
+
197
+ if merge_result.returncode != 0:
198
+ return False, f"Merge failed: {merge_result.stderr}"
199
+
200
+ # Delete worktree if requested
201
+ if delete_after:
202
+ self.remove(name, force=True)
203
+ # Delete branch
204
+ subprocess.run( # nosec B603 B607 - git command with safe args
205
+ ["git", "branch", "-d", worktree.branch],
206
+ check=False,
207
+ cwd=self.base_path,
208
+ capture_output=True,
209
+ )
210
+
211
+ logger.info(f"Merged '{worktree.branch}' to {main_branch}")
212
+ return True, f"Merged '{worktree.branch}' to {main_branch}"