claude-mpm 5.4.96__py3-none-any.whl → 5.6.10__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/{CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md → CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md} +14 -6
- claude_mpm/agents/PM_INSTRUCTIONS.md +44 -10
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/commands/autotodos.py +45 -5
- claude_mpm/cli/commands/commander.py +46 -0
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +5 -3
- claude_mpm/cli/executor.py +32 -17
- claude_mpm/cli/parsers/base_parser.py +17 -0
- claude_mpm/cli/parsers/commander_parser.py +83 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +5 -0
- claude_mpm/cli/startup.py +20 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +72 -0
- claude_mpm/commander/adapters/__init__.py +31 -0
- claude_mpm/commander/adapters/base.py +191 -0
- claude_mpm/commander/adapters/claude_code.py +361 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +105 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +228 -0
- claude_mpm/commander/api/routes/work.py +260 -0
- claude_mpm/commander/api/schemas.py +182 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +107 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -0
- claude_mpm/commander/config.py +49 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/daemon.py +398 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +332 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +143 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +62 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +337 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +121 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +309 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +404 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +316 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +361 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +189 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +219 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +8 -0
- claude_mpm/commands/mpm-doctor.md +8 -0
- claude_mpm/commands/mpm-help.md +8 -0
- claude_mpm/commands/mpm-init.md +8 -0
- claude_mpm/commands/mpm-monitor.md +8 -0
- claude_mpm/commands/mpm-organize.md +8 -0
- claude_mpm/commands/mpm-postmortem.md +8 -0
- claude_mpm/commands/mpm-session-resume.md +8 -0
- claude_mpm/commands/mpm-status.md +8 -0
- claude_mpm/commands/mpm-ticket-view.md +8 -0
- claude_mpm/commands/mpm-version.md +8 -0
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/core/config.py +32 -19
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +35 -11
- claude_mpm/core/output_style_manager.py +15 -5
- claude_mpm/core/unified_config.py +10 -6
- claude_mpm/core/unified_paths.py +68 -80
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +29 -30
- claude_mpm/hooks/claude_hooks/event_handlers.py +90 -99
- claude_mpm/hooks/claude_hooks/hook_handler.py +81 -88
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +116 -8
- claude_mpm/hooks/claude_hooks/memory_integration.py +51 -31
- claude_mpm/hooks/claude_hooks/response_tracking.py +39 -58
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +23 -28
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +36 -103
- claude_mpm/hooks/claude_hooks/services/state_manager.py +23 -36
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +47 -73
- claude_mpm/hooks/session_resume_hook.py +22 -18
- claude_mpm/hooks/templates/pre_tool_use_template.py +10 -2
- claude_mpm/scripts/claude-hook-handler.sh +43 -16
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/event_log.py +8 -0
- claude_mpm/services/pm_skills_deployer.py +84 -6
- claude_mpm/services/skills/git_skill_source_manager.py +130 -10
- claude_mpm/services/skills/selective_skill_deployer.py +28 -0
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +31 -5
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/METADATA +18 -4
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/RECORD +190 -79
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/top_level.txt +0 -0
|
@@ -8,12 +8,20 @@ Claude Code hook events.
|
|
|
8
8
|
import os
|
|
9
9
|
import re
|
|
10
10
|
import subprocess # nosec B404 - subprocess used for safe claude CLI version checking only
|
|
11
|
-
import sys
|
|
12
11
|
import uuid
|
|
13
12
|
from datetime import datetime, timezone
|
|
14
13
|
from pathlib import Path
|
|
15
14
|
from typing import Optional
|
|
16
15
|
|
|
16
|
+
# Import _log helper to avoid stderr writes (which cause hook errors)
|
|
17
|
+
try:
|
|
18
|
+
from .hook_handler import _log
|
|
19
|
+
except ImportError:
|
|
20
|
+
# Fallback for direct execution
|
|
21
|
+
def _log(message: str) -> None:
|
|
22
|
+
"""Fallback logger when hook_handler not available."""
|
|
23
|
+
|
|
24
|
+
|
|
17
25
|
# Import tool analysis with fallback for direct execution
|
|
18
26
|
try:
|
|
19
27
|
# Try relative import first (when imported as module)
|
|
@@ -34,8 +42,8 @@ except ImportError:
|
|
|
34
42
|
extract_tool_results,
|
|
35
43
|
)
|
|
36
44
|
|
|
37
|
-
# Debug mode
|
|
38
|
-
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "
|
|
45
|
+
# Debug mode - MUST match hook_handler.py default (false) to prevent stderr writes
|
|
46
|
+
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "false").lower() == "true"
|
|
39
47
|
|
|
40
48
|
# Import constants for configuration
|
|
41
49
|
try:
|
|
@@ -111,9 +119,8 @@ class EventHandlers:
|
|
|
111
119
|
"working_directory": working_dir,
|
|
112
120
|
}
|
|
113
121
|
if DEBUG:
|
|
114
|
-
|
|
115
|
-
f"Stored prompt for comprehensive tracking: session {session_id[:8]}..."
|
|
116
|
-
file=sys.stderr,
|
|
122
|
+
_log(
|
|
123
|
+
f"Stored prompt for comprehensive tracking: session {session_id[:8]}..."
|
|
117
124
|
)
|
|
118
125
|
except Exception: # nosec B110
|
|
119
126
|
# Response tracking is optional - silently continue if it fails
|
|
@@ -133,11 +140,8 @@ class EventHandlers:
|
|
|
133
140
|
# Enhanced debug logging for session correlation
|
|
134
141
|
session_id = event.get("session_id", "")
|
|
135
142
|
if DEBUG:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
file=sys.stderr,
|
|
139
|
-
)
|
|
140
|
-
print(f" - event keys: {list(event.keys())}", file=sys.stderr)
|
|
143
|
+
_log(f" - session_id: {session_id[:16] if session_id else 'None'}...")
|
|
144
|
+
_log(f" - event keys: {list(event.keys())}")
|
|
141
145
|
|
|
142
146
|
tool_name = event.get("tool_name", "")
|
|
143
147
|
tool_input = event.get("tool_input", {})
|
|
@@ -180,9 +184,8 @@ class EventHandlers:
|
|
|
180
184
|
|
|
181
185
|
CorrelationManager.store(session_id, tool_call_id, tool_name)
|
|
182
186
|
if DEBUG:
|
|
183
|
-
|
|
184
|
-
f" - Generated tool_call_id: {tool_call_id[:8]}... for session {session_id[:8]}..."
|
|
185
|
-
file=sys.stderr,
|
|
187
|
+
_log(
|
|
188
|
+
f" - Generated tool_call_id: {tool_call_id[:8]}... for session {session_id[:8]}..."
|
|
186
189
|
)
|
|
187
190
|
|
|
188
191
|
# Add delegation-specific data if this is a Task tool
|
|
@@ -196,7 +199,7 @@ class EventHandlers:
|
|
|
196
199
|
auto_pause.on_tool_call(tool_name, tool_input)
|
|
197
200
|
except Exception as e:
|
|
198
201
|
if DEBUG:
|
|
199
|
-
|
|
202
|
+
_log(f"Auto-pause tool recording error: {e}")
|
|
200
203
|
|
|
201
204
|
self.hook_handler._emit_socketio_event("", "pre_tool", pre_tool_data)
|
|
202
205
|
|
|
@@ -212,9 +215,8 @@ class EventHandlers:
|
|
|
212
215
|
}
|
|
213
216
|
self.hook_handler._emit_socketio_event("", "todo_updated", todo_data)
|
|
214
217
|
if DEBUG:
|
|
215
|
-
|
|
216
|
-
f" - Emitted todo_updated event with {len(tool_params['todos'])} todos for session {session_id[:8]}..."
|
|
217
|
-
file=sys.stderr,
|
|
218
|
+
_log(
|
|
219
|
+
f" - Emitted todo_updated event with {len(tool_params['todos'])} todos for session {session_id[:8]}..."
|
|
218
220
|
)
|
|
219
221
|
|
|
220
222
|
def _handle_task_delegation(
|
|
@@ -255,12 +257,9 @@ class EventHandlers:
|
|
|
255
257
|
|
|
256
258
|
# Track this delegation for SubagentStop correlation and response tracking
|
|
257
259
|
if DEBUG:
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
)
|
|
262
|
-
print(f" - agent_type: {agent_type}", file=sys.stderr)
|
|
263
|
-
print(f" - raw_agent_type: {raw_agent_type}", file=sys.stderr)
|
|
260
|
+
_log(f" - session_id: {session_id[:16] if session_id else 'None'}...")
|
|
261
|
+
_log(f" - agent_type: {agent_type}")
|
|
262
|
+
_log(f" - raw_agent_type: {raw_agent_type}")
|
|
264
263
|
|
|
265
264
|
if session_id and agent_type != "unknown":
|
|
266
265
|
# Prepare request data for response tracking correlation
|
|
@@ -272,24 +271,17 @@ class EventHandlers:
|
|
|
272
271
|
self.hook_handler._track_delegation(session_id, agent_type, request_data)
|
|
273
272
|
|
|
274
273
|
if DEBUG:
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
f" - Request data keys: {list(request_data.keys())}",
|
|
278
|
-
file=sys.stderr,
|
|
279
|
-
)
|
|
274
|
+
_log(" - Delegation tracked successfully")
|
|
275
|
+
_log(f" - Request data keys: {list(request_data.keys())}")
|
|
280
276
|
delegation_requests = getattr(
|
|
281
277
|
self.hook_handler, "delegation_requests", {}
|
|
282
278
|
)
|
|
283
|
-
|
|
284
|
-
f" - delegation_requests size: {len(delegation_requests)}",
|
|
285
|
-
file=sys.stderr,
|
|
286
|
-
)
|
|
279
|
+
_log(f" - delegation_requests size: {len(delegation_requests)}")
|
|
287
280
|
|
|
288
281
|
# Log important delegations for debugging
|
|
289
282
|
if DEBUG or agent_type in ["research", "engineer", "qa", "documentation"]:
|
|
290
|
-
|
|
291
|
-
f"Hook handler: Task delegation started - agent: '{agent_type}', session: '{session_id}'"
|
|
292
|
-
file=sys.stderr,
|
|
283
|
+
_log(
|
|
284
|
+
f"Hook handler: Task delegation started - agent: '{agent_type}', session: '{session_id}'"
|
|
293
285
|
)
|
|
294
286
|
|
|
295
287
|
# Trigger memory pre-delegation hook
|
|
@@ -359,10 +351,10 @@ class EventHandlers:
|
|
|
359
351
|
)
|
|
360
352
|
|
|
361
353
|
if DEBUG:
|
|
362
|
-
|
|
354
|
+
_log(f" - Agent prompt logged for {agent_type}")
|
|
363
355
|
except Exception as e:
|
|
364
356
|
if DEBUG:
|
|
365
|
-
|
|
357
|
+
_log(f" - Could not log agent prompt: {e}")
|
|
366
358
|
|
|
367
359
|
def _get_git_branch(self, working_dir: Optional[str] = None) -> str:
|
|
368
360
|
"""Get git branch for the given directory with caching."""
|
|
@@ -450,9 +442,8 @@ class EventHandlers:
|
|
|
450
442
|
|
|
451
443
|
tool_call_id = CorrelationManager.retrieve(session_id) if session_id else None
|
|
452
444
|
if DEBUG and tool_call_id:
|
|
453
|
-
|
|
454
|
-
f" - Retrieved tool_call_id: {tool_call_id[:8]}... for session {session_id[:8]}..."
|
|
455
|
-
file=sys.stderr,
|
|
445
|
+
_log(
|
|
446
|
+
f" - Retrieved tool_call_id: {tool_call_id[:8]}... for session {session_id[:8]}..."
|
|
456
447
|
)
|
|
457
448
|
|
|
458
449
|
post_tool_data = {
|
|
@@ -598,19 +589,19 @@ class EventHandlers:
|
|
|
598
589
|
threshold_crossed = auto_pause.on_usage_update(metadata["usage"])
|
|
599
590
|
if threshold_crossed:
|
|
600
591
|
warning = auto_pause.emit_threshold_warning(threshold_crossed)
|
|
601
|
-
|
|
592
|
+
# CRITICAL: Never write to stderr unconditionally - causes hook errors
|
|
593
|
+
# Use _log() instead which only writes to file if DEBUG=true
|
|
594
|
+
from . import _log
|
|
595
|
+
|
|
596
|
+
_log(f"⚠️ Auto-pause threshold crossed: {warning}")
|
|
602
597
|
|
|
603
598
|
if DEBUG:
|
|
604
|
-
|
|
605
|
-
f" - Auto-pause threshold crossed: {threshold_crossed}"
|
|
606
|
-
file=sys.stderr,
|
|
599
|
+
_log(
|
|
600
|
+
f" - Auto-pause threshold crossed: {threshold_crossed}"
|
|
607
601
|
)
|
|
608
602
|
except Exception as e:
|
|
609
603
|
if DEBUG:
|
|
610
|
-
|
|
611
|
-
f"Auto-pause error in handle_stop_fast: {e}",
|
|
612
|
-
file=sys.stderr,
|
|
613
|
-
)
|
|
604
|
+
_log(f"Auto-pause error in handle_stop_fast: {e}")
|
|
614
605
|
|
|
615
606
|
# Track response if enabled
|
|
616
607
|
try:
|
|
@@ -652,24 +643,15 @@ class EventHandlers:
|
|
|
652
643
|
getattr(rtm, "response_tracker", None) is not None if rtm else False
|
|
653
644
|
)
|
|
654
645
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
file=sys.stderr,
|
|
658
|
-
)
|
|
659
|
-
print(
|
|
660
|
-
f" - response_tracker exists: {tracker_exists}",
|
|
661
|
-
file=sys.stderr,
|
|
662
|
-
)
|
|
646
|
+
_log(f" - response_tracking_enabled: {tracking_enabled}")
|
|
647
|
+
_log(f" - response_tracker exists: {tracker_exists}")
|
|
663
648
|
except Exception: # nosec B110
|
|
664
649
|
# If debug logging fails, just skip it
|
|
665
650
|
pass
|
|
666
651
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
)
|
|
671
|
-
print(f" - reason: {metadata['reason']}", file=sys.stderr)
|
|
672
|
-
print(f" - stop_type: {metadata['stop_type']}", file=sys.stderr)
|
|
652
|
+
_log(f" - session_id: {session_id[:8] if session_id else 'None'}...")
|
|
653
|
+
_log(f" - reason: {metadata['reason']}")
|
|
654
|
+
_log(f" - stop_type: {metadata['stop_type']}")
|
|
673
655
|
|
|
674
656
|
def _emit_stop_event(self, event: dict, session_id: str, metadata: dict) -> None:
|
|
675
657
|
"""Emit stop event data to Socket.IO."""
|
|
@@ -731,10 +713,7 @@ class EventHandlers:
|
|
|
731
713
|
# If exact match fails, try partial matching
|
|
732
714
|
if not request_info and session_id:
|
|
733
715
|
if DEBUG:
|
|
734
|
-
|
|
735
|
-
f" - Trying fuzzy match for session {session_id[:16]}...",
|
|
736
|
-
file=sys.stderr,
|
|
737
|
-
)
|
|
716
|
+
_log(f" - Trying fuzzy match for session {session_id[:16]}...")
|
|
738
717
|
# Try to find a session that matches the first 8-16 characters
|
|
739
718
|
for stored_sid in list(delegation_requests.keys()):
|
|
740
719
|
if (
|
|
@@ -747,10 +726,7 @@ class EventHandlers:
|
|
|
747
726
|
)
|
|
748
727
|
):
|
|
749
728
|
if DEBUG:
|
|
750
|
-
|
|
751
|
-
f" - ✅ Fuzzy match found: {stored_sid[:16]}...",
|
|
752
|
-
file=sys.stderr,
|
|
753
|
-
)
|
|
729
|
+
_log(f" - ✅ Fuzzy match found: {stored_sid[:16]}...")
|
|
754
730
|
request_info = delegation_requests.get(stored_sid) # nosec B113
|
|
755
731
|
# Update the key to use the current session_id for consistency
|
|
756
732
|
if request_info:
|
|
@@ -819,9 +795,8 @@ class EventHandlers:
|
|
|
819
795
|
)
|
|
820
796
|
|
|
821
797
|
if file_path and DEBUG:
|
|
822
|
-
|
|
823
|
-
f"✅ Tracked {agent_type} agent response on SubagentStop: {file_path.name}"
|
|
824
|
-
file=sys.stderr,
|
|
798
|
+
_log(
|
|
799
|
+
f"✅ Tracked {agent_type} agent response on SubagentStop: {file_path.name}"
|
|
825
800
|
)
|
|
826
801
|
|
|
827
802
|
# Clean up the request data
|
|
@@ -832,16 +807,13 @@ class EventHandlers:
|
|
|
832
807
|
del delegation_requests[session_id]
|
|
833
808
|
|
|
834
809
|
elif DEBUG:
|
|
835
|
-
|
|
836
|
-
f"No request data for SubagentStop session {session_id[:8]}..., agent: {agent_type}"
|
|
837
|
-
file=sys.stderr,
|
|
810
|
+
_log(
|
|
811
|
+
f"No request data for SubagentStop session {session_id[:8]}..., agent: {agent_type}"
|
|
838
812
|
)
|
|
839
813
|
|
|
840
814
|
except Exception as e:
|
|
841
815
|
if DEBUG:
|
|
842
|
-
|
|
843
|
-
f"❌ Failed to track response on SubagentStop: {e}", file=sys.stderr
|
|
844
|
-
)
|
|
816
|
+
_log(f"❌ Failed to track response on SubagentStop: {e}")
|
|
845
817
|
|
|
846
818
|
def handle_assistant_response(self, event):
|
|
847
819
|
"""Handle assistant response events for comprehensive response tracking.
|
|
@@ -868,7 +840,7 @@ class EventHandlers:
|
|
|
868
840
|
self._scan_for_delegation_patterns(event)
|
|
869
841
|
except Exception as e: # nosec B110
|
|
870
842
|
if DEBUG:
|
|
871
|
-
|
|
843
|
+
_log(f"Delegation scanning error: {e}")
|
|
872
844
|
|
|
873
845
|
# Get working directory and git branch
|
|
874
846
|
working_dir = event.get("cwd", "")
|
|
@@ -917,9 +889,8 @@ class EventHandlers:
|
|
|
917
889
|
|
|
918
890
|
# Debug logging
|
|
919
891
|
if DEBUG:
|
|
920
|
-
|
|
921
|
-
f"Hook handler: Processing AssistantResponse - session: '{session_id}', response_length: {len(response_text)}"
|
|
922
|
-
file=sys.stderr,
|
|
892
|
+
_log(
|
|
893
|
+
f"Hook handler: Processing AssistantResponse - session: '{session_id}', response_length: {len(response_text)}"
|
|
923
894
|
)
|
|
924
895
|
|
|
925
896
|
# Record assistant response for auto-pause if active
|
|
@@ -935,7 +906,7 @@ class EventHandlers:
|
|
|
935
906
|
auto_pause.on_assistant_response(summary)
|
|
936
907
|
except Exception as e:
|
|
937
908
|
if DEBUG:
|
|
938
|
-
|
|
909
|
+
_log(f"Auto-pause response recording error: {e}")
|
|
939
910
|
|
|
940
911
|
# Emit normalized event
|
|
941
912
|
self.hook_handler._emit_socketio_event(
|
|
@@ -949,6 +920,7 @@ class EventHandlers:
|
|
|
949
920
|
- Provides visibility into new conversation sessions
|
|
950
921
|
- Enables tracking of session lifecycle and duration
|
|
951
922
|
- Useful for monitoring concurrent sessions and resource usage
|
|
923
|
+
- Auto-inject pending autotodos if enabled in config
|
|
952
924
|
"""
|
|
953
925
|
session_id = event.get("session_id", "")
|
|
954
926
|
working_dir = event.get("cwd", "")
|
|
@@ -962,12 +934,36 @@ class EventHandlers:
|
|
|
962
934
|
"hook_event_name": "SessionStart",
|
|
963
935
|
}
|
|
964
936
|
|
|
937
|
+
# Auto-inject pending autotodos if enabled
|
|
938
|
+
try:
|
|
939
|
+
from pathlib import Path
|
|
940
|
+
|
|
941
|
+
from claude_mpm.cli.commands.autotodos import get_pending_todos
|
|
942
|
+
from claude_mpm.core.config import Config
|
|
943
|
+
|
|
944
|
+
config = Config()
|
|
945
|
+
auto_inject_enabled = config.get("autotodos.auto_inject_on_startup", True)
|
|
946
|
+
max_todos = config.get("autotodos.max_todos_per_session", 10)
|
|
947
|
+
|
|
948
|
+
if auto_inject_enabled:
|
|
949
|
+
# Pass working directory from event to avoid Path.cwd() issues
|
|
950
|
+
working_dir_param = None
|
|
951
|
+
if working_dir:
|
|
952
|
+
working_dir_param = Path(working_dir)
|
|
953
|
+
|
|
954
|
+
pending_todos = get_pending_todos(
|
|
955
|
+
max_todos=max_todos, working_dir=working_dir_param
|
|
956
|
+
)
|
|
957
|
+
if pending_todos:
|
|
958
|
+
session_start_data["pending_autotodos"] = pending_todos
|
|
959
|
+
session_start_data["autotodos_count"] = len(pending_todos)
|
|
960
|
+
_log(f" - Auto-injected {len(pending_todos)} pending autotodos")
|
|
961
|
+
except Exception as e: # nosec B110
|
|
962
|
+
# Auto-injection is optional - continue if it fails
|
|
963
|
+
_log(f" - Failed to auto-inject autotodos: {e}")
|
|
964
|
+
|
|
965
965
|
# Debug logging
|
|
966
|
-
|
|
967
|
-
print(
|
|
968
|
-
f"Hook handler: Processing SessionStart - session: '{session_id}'",
|
|
969
|
-
file=sys.stderr,
|
|
970
|
-
)
|
|
966
|
+
_log(f"Hook handler: Processing SessionStart - session: '{session_id}'")
|
|
971
967
|
|
|
972
968
|
# Emit normalized event
|
|
973
969
|
self.hook_handler._emit_socketio_event("", "session_start", session_start_data)
|
|
@@ -1010,10 +1006,8 @@ class EventHandlers:
|
|
|
1010
1006
|
|
|
1011
1007
|
# Debug logging
|
|
1012
1008
|
if DEBUG:
|
|
1013
|
-
|
|
1014
|
-
f"Hook handler: SubagentStart - agent_type='{agent_type}', "
|
|
1015
|
-
f"agent_id='{agent_id}', session_id='{session_id[:16]}...'",
|
|
1016
|
-
file=sys.stderr,
|
|
1009
|
+
_log(
|
|
1010
|
+
f"Hook handler: SubagentStart - agent_type='{agent_type}', agent_id='{agent_id}', session_id='{session_id[:16]}...'"
|
|
1017
1011
|
)
|
|
1018
1012
|
|
|
1019
1013
|
# Emit to /hook namespace as subagent_start (NOT session_start!)
|
|
@@ -1048,7 +1042,7 @@ class EventHandlers:
|
|
|
1048
1042
|
from claude_mpm.services.event_log import get_event_log
|
|
1049
1043
|
except ImportError:
|
|
1050
1044
|
if DEBUG:
|
|
1051
|
-
|
|
1045
|
+
_log("Delegation detector or event log not available")
|
|
1052
1046
|
return
|
|
1053
1047
|
|
|
1054
1048
|
response_text = event.get("response", "")
|
|
@@ -1087,7 +1081,4 @@ class EventHandlers:
|
|
|
1087
1081
|
)
|
|
1088
1082
|
|
|
1089
1083
|
if DEBUG:
|
|
1090
|
-
|
|
1091
|
-
f"⚠️ PM violation detected: {detection['original_text'][:60]}...",
|
|
1092
|
-
file=sys.stderr,
|
|
1093
|
-
)
|
|
1084
|
+
_log(f"⚠️ PM violation detected: {detection['original_text'][:60]}...")
|