claude-mpm 5.4.90__py3-none-any.whl → 5.4.91__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
- 5.4.90
1
+ 5.4.91
@@ -7,7 +7,7 @@ Shows welcome message, version info, ASCII art, and what's new section.
7
7
  import os
8
8
  import re
9
9
  import shutil
10
- import subprocess
10
+ import subprocess # nosec B404 - required for git operations
11
11
  from pathlib import Path
12
12
  from typing import List
13
13
 
@@ -65,8 +65,8 @@ def _get_recent_commits(max_commits: int = 3) -> List[str]:
65
65
  if not is_git_repository("."):
66
66
  return []
67
67
 
68
- # Run git log with custom format
69
- result = subprocess.run(
68
+ # Run git log with custom format (safe - no user input)
69
+ result = subprocess.run( # nosec B603 B607
70
70
  ["git", "log", "--format=%h • %ar • %s", f"-{max_commits}"],
71
71
  capture_output=True,
72
72
  text=True,
@@ -216,6 +216,59 @@ def _get_cwd_display(max_width: int = 40) -> str:
216
216
  return "..." + cwd[-(max_width - 3) :]
217
217
 
218
218
 
219
+ def _count_mpm_skills() -> int:
220
+ """
221
+ Count user-level MPM skills from ~/.claude/skills/.
222
+
223
+ Returns:
224
+ Number of skill directories with SKILL.md files
225
+ """
226
+ try:
227
+ user_skills_dir = Path.home() / ".claude" / "skills"
228
+ if not user_skills_dir.exists():
229
+ return 0
230
+
231
+ # Count directories with SKILL.md (skill directories)
232
+ skill_count = 0
233
+ for item in user_skills_dir.iterdir():
234
+ if item.is_dir():
235
+ skill_file = item / "SKILL.md"
236
+ if skill_file.exists():
237
+ skill_count += 1
238
+ # Also count standalone .md files (legacy format)
239
+ elif item.is_file() and item.suffix == ".md" and item.name != "README.md":
240
+ skill_count += 1
241
+
242
+ return skill_count
243
+ except Exception:
244
+ # Silent failure - return 0 if any error
245
+ return 0
246
+
247
+
248
+ def _count_deployed_agents() -> int:
249
+ """
250
+ Count deployed agents from .claude/agents/.
251
+
252
+ Returns:
253
+ Number of deployed agent files
254
+ """
255
+ try:
256
+ deploy_target = Path.cwd() / ".claude" / "agents"
257
+ if not deploy_target.exists():
258
+ return 0
259
+
260
+ # Count .md files, excluding README and other docs
261
+ agent_files = [
262
+ f
263
+ for f in deploy_target.glob("*.md")
264
+ if not f.name.startswith(("README", "INSTRUCTIONS", "."))
265
+ ]
266
+ return len(agent_files)
267
+ except Exception:
268
+ # Silent failure - return 0 if any error
269
+ return 0
270
+
271
+
219
272
  def _format_two_column_line(
220
273
  left: str, right: str, left_panel_width: int, right_panel_width: int
221
274
  ) -> str:
@@ -402,11 +455,25 @@ def display_startup_banner(version: str, logging_level: str) -> None:
402
455
  )
403
456
  )
404
457
 
405
- # Line 10: Model info | separator
458
+ # Line 10: Model info with counts | separator
406
459
  separator = "─" * right_panel_width
460
+ agent_count = _count_deployed_agents()
461
+ skill_count = _count_mpm_skills()
462
+
463
+ # Format: "Sonnet 4.5 · 44 agents, 19 skills"
464
+ if agent_count > 0 or skill_count > 0:
465
+ counts_text = []
466
+ if agent_count > 0:
467
+ counts_text.append(f"{agent_count} agent{'s' if agent_count != 1 else ''}")
468
+ if skill_count > 0:
469
+ counts_text.append(f"{skill_count} skill{'s' if skill_count != 1 else ''}")
470
+ model_info = f"Sonnet 4.5 · {', '.join(counts_text)}"
471
+ else:
472
+ model_info = "Sonnet 4.5 · Claude MPM"
473
+
407
474
  lines.append(
408
475
  _format_two_column_line(
409
- "Sonnet 4.5 · Claude MPM", separator, left_panel_width, right_panel_width
476
+ model_info, separator, left_panel_width, right_panel_width
410
477
  )
411
478
  )
412
479
 
@@ -200,6 +200,23 @@ class EventHandlers:
200
200
 
201
201
  self.hook_handler._emit_socketio_event("", "pre_tool", pre_tool_data)
202
202
 
203
+ # Handle TodoWrite specially - emit dedicated todo_updated event
204
+ # WHY: Frontend expects todo_updated events for dashboard display
205
+ # The broadcaster.todo_updated() method exists but was never called
206
+ if tool_name == "TodoWrite" and tool_params.get("todos"):
207
+ todo_data = {
208
+ "todos": tool_params["todos"],
209
+ "total_count": len(tool_params["todos"]),
210
+ "session_id": session_id,
211
+ "timestamp": timestamp,
212
+ }
213
+ self.hook_handler._emit_socketio_event("", "todo_updated", todo_data)
214
+ if DEBUG:
215
+ print(
216
+ f" - Emitted todo_updated event with {len(tool_params['todos'])} todos for session {session_id[:8]}...",
217
+ file=sys.stderr,
218
+ )
219
+
203
220
  def _handle_task_delegation(
204
221
  self, tool_input: dict, pre_tool_data: dict, session_id: str
205
222
  ):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 5.4.90
3
+ Version: 5.4.91
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=9JfxhnDtr-8l3kCP2U5TVXSErptHoga8m7XA8zqgGOc,4
2
- claude_mpm/VERSION,sha256=PqwFkZ733iP3V1Gh-jpOeNrrbb-Ax7nlNJHcEfhxqfE,7
2
+ claude_mpm/VERSION,sha256=j_2QGTdwJ4XYtqJcjkXEc2EwMXakcra3ul1X6ZlsjiA,7
3
3
  claude_mpm/__init__.py,sha256=AGfh00BHKvLYD-UVFw7qbKtl7NMRIzRXOWw7vEuZ-h4,2214
4
4
  claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
5
5
  claude_mpm/constants.py,sha256=pz3lTrZZR5HhV3eZzYtIbtBwWo7iM6pkBHP_ixxmI6Y,6827
@@ -43,7 +43,7 @@ claude_mpm/cli/executor.py,sha256=1MQdNPNoIewSR1q8nXjJuES3zKEi_IqVcZQzt9bsxw8,10
43
43
  claude_mpm/cli/helpers.py,sha256=CypEhw0tbNH6_GzVTaQdi4w7ThCWO43Ep92YbJzPR4I,3638
44
44
  claude_mpm/cli/parser.py,sha256=Vqx9n-6Xo1uNhXR4rThmgWpZXTr0nOtkgDf3oMS9b0g,5855
45
45
  claude_mpm/cli/startup.py,sha256=pOFS4qtVAvfUEEsgSMi7vW9M_5b_mYtNwADXikoa2Y4,62961
46
- claude_mpm/cli/startup_display.py,sha256=R_QIamjfdaY5o_VxpIeymyYj1Qde2B9hPXy1P-KmUKI,14972
46
+ claude_mpm/cli/startup_display.py,sha256=2b7cIow39gUFdJyarh9lv4uvnicnCWml-onUbKnGGWY,17132
47
47
  claude_mpm/cli/startup_logging.py,sha256=RTuyd6CbhiFQz7Z07LDDhK_ZAnZfuJ9B0NghVSntHFI,29390
48
48
  claude_mpm/cli/utils.py,sha256=FSMPftBZM8MeUyTtiB63Lz7oFOgkzwTetQs58RbRb_Q,8785
49
49
  claude_mpm/cli/commands/__init__.py,sha256=-JkPmY_gq6ZZSyw1F9K0mc5CRXwZurVq1HXvxf2mhaI,1342
@@ -335,7 +335,7 @@ claude_mpm/hooks/claude_hooks/__init__.py,sha256=b4mud_g3S-3itHY_Dzpbb_SmdMEcJwt
335
335
  claude_mpm/hooks/claude_hooks/auto_pause_handler.py,sha256=xDAQZ33I5OhGvtWvA9mxwVSoir9tM-aCvrWkSRdnVmU,17465
336
336
  claude_mpm/hooks/claude_hooks/connection_pool.py,sha256=vpi-XbVf61GWhh85tHBzubbOgbJly_I-5-QmsleND2M,8658
337
337
  claude_mpm/hooks/claude_hooks/correlation_manager.py,sha256=3n-RxzqE8egG4max_NcpJgL9gzrBY6Ti529LrjleI1g,2033
338
- claude_mpm/hooks/claude_hooks/event_handlers.py,sha256=ec9arG0gOH5fc-2D2JE-MBqD8DbJ7sYYyx3pevRGPvw,39480
338
+ claude_mpm/hooks/claude_hooks/event_handlers.py,sha256=kcxIibd7K-1UKkT9DylEloQDRnN7tXp-Uzg2AgYk0cE,40305
339
339
  claude_mpm/hooks/claude_hooks/hook_handler.py,sha256=6PUlnglaV6wlR3TrAcmVUf5CpoSLaBw-tKEKpZGHxo8,28185
340
340
  claude_mpm/hooks/claude_hooks/hook_wrapper.sh,sha256=4lG3TlLVoVfTJipPj1X_ICUlS-KpnkbUp1U3oSq80Bw,2476
341
341
  claude_mpm/hooks/claude_hooks/installer.py,sha256=VbvVGMcrmCXQB3Pf9zOdjeGET2AFqbUDMHDy5KXuvz0,30463
@@ -345,7 +345,7 @@ claude_mpm/hooks/claude_hooks/tool_analysis.py,sha256=3_o2PP9D7wEMwLriCtIBOw0cj2
345
345
  claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc,sha256=EGpgXqhPM0iRRZtCqHaLVQ6wDH42OH_M7Gt5GiFLyro,346
346
346
  claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc,sha256=X7A8O4KPXkuDaLDFbF7Izi1qVDyS0tQjHVo1xy_HzNQ,21172
347
347
  claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc,sha256=SQX5iiP9bQZkLL-cj_2tlGH7lpAzarO0mYal7btj3tc,3521
348
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc,sha256=xS_cl5CFEHT4U_Za1vGhTTjKRayLvLoBvRfekvK-1gk,38986
348
+ claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc,sha256=VD6meHRZQDAXkW3rmzF3POI1rdefsczR-te5QE5foic,39651
349
349
  claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc,sha256=pA793fTKMsdmyho-jURwvJjHXfIy8AnC0Tjw3x9toro,30559
350
350
  claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc,sha256=YbwauQDKSGvXkT1972faalJLuxwyvq328DYQhkCnel0,10513
351
351
  claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc,sha256=YV5iCKSXtrON611Rp3S8PQGPz0H3RIBO6K_n1BAfGWw,17523
@@ -993,10 +993,10 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
993
993
  claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
994
994
  claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
995
995
  claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
996
- claude_mpm-5.4.90.dist-info/licenses/LICENSE,sha256=ca3y_Rk4aPrbF6f62z8Ht5MJM9OAvbGlHvEDcj9vUQ4,3867
997
- claude_mpm-5.4.90.dist-info/licenses/LICENSE-FAQ.md,sha256=TxfEkXVCK98RzDOer09puc7JVCP_q_bN4dHtZKHCMcM,5104
998
- claude_mpm-5.4.90.dist-info/METADATA,sha256=k2-qodY858TX6F1IukwiFKe2Mzzoc0sS6HChyU35Fs4,14185
999
- claude_mpm-5.4.90.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1000
- claude_mpm-5.4.90.dist-info/entry_points.txt,sha256=n-Uk4vwHPpuvu-g_I7-GHORzTnN_m6iyOsoLveKKD0E,228
1001
- claude_mpm-5.4.90.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
1002
- claude_mpm-5.4.90.dist-info/RECORD,,
996
+ claude_mpm-5.4.91.dist-info/licenses/LICENSE,sha256=ca3y_Rk4aPrbF6f62z8Ht5MJM9OAvbGlHvEDcj9vUQ4,3867
997
+ claude_mpm-5.4.91.dist-info/licenses/LICENSE-FAQ.md,sha256=TxfEkXVCK98RzDOer09puc7JVCP_q_bN4dHtZKHCMcM,5104
998
+ claude_mpm-5.4.91.dist-info/METADATA,sha256=bA1l0dQ-e3ZlRIABftvEA5reXhkFPzg_oOreXlic-lU,14185
999
+ claude_mpm-5.4.91.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1000
+ claude_mpm-5.4.91.dist-info/entry_points.txt,sha256=n-Uk4vwHPpuvu-g_I7-GHORzTnN_m6iyOsoLveKKD0E,228
1001
+ claude_mpm-5.4.91.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
1002
+ claude_mpm-5.4.91.dist-info/RECORD,,