claude-mpm 5.4.22__py3-none-any.whl → 5.6.34__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/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +374 -1257
- claude_mpm/agents/WORKFLOW.md +6 -253
- claude_mpm/agents/agent_loader.py +1 -1
- claude_mpm/agents/base_agent.json +31 -0
- claude_mpm/agents/frontmatter_validator.py +2 -2
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agent_state_manager.py +10 -10
- claude_mpm/cli/commands/agents.py +11 -13
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/auto_configure.py +4 -4
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/configure.py +621 -22
- claude_mpm/cli/commands/configure_agent_display.py +12 -0
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +72 -0
- claude_mpm/cli/commands/postmortem.py +1 -1
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +182 -32
- claude_mpm/cli/executor.py +130 -16
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +32 -52
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +83 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -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 +2 -3
- claude_mpm/cli/startup.py +690 -386
- claude_mpm/cli/startup_display.py +74 -6
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -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 +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +146 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -0
- claude_mpm/commander/config.py +51 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +603 -0
- claude_mpm/commander/env_loader.py +59 -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 +146 -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 +450 -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/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -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 +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -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 +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +20 -249
- claude_mpm/commands/mpm-doctor.md +16 -21
- claude_mpm/commands/mpm-help.md +12 -205
- claude_mpm/commands/mpm-init.md +88 -506
- claude_mpm/commands/mpm-monitor.md +22 -401
- claude_mpm/commands/mpm-organize.md +70 -442
- claude_mpm/commands/mpm-postmortem.md +13 -107
- claude_mpm/commands/mpm-session-resume.md +20 -363
- claude_mpm/commands/mpm-status.md +13 -69
- claude_mpm/commands/mpm-ticket-view.md +60 -495
- claude_mpm/commands/mpm-version.md +13 -107
- 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/constants.py +1 -0
- claude_mpm/core/claude_runner.py +154 -2
- claude_mpm/core/config.py +37 -26
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/framework/loaders/agent_loader.py +1 -1
- claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/interactive_session.py +12 -11
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/optimized_startup.py +61 -0
- claude_mpm/core/output_style_manager.py +66 -18
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_agent_registry.py +1 -1
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DR8nis88.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.RgBboRvH.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +527 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +313 -99
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +206 -36
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.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__/container.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +67 -32
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +310 -0
- claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +276 -0
- claude_mpm/models/git_repository.py +3 -3
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +7 -7
- claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -2
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +39 -19
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +169 -26
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +101 -75
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +23 -4
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +6 -6
- claude_mpm/services/agents/sources/git_source_sync_service.py +121 -10
- claude_mpm/services/agents/startup_sync.py +27 -4
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +31 -1
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/git/git_operations_service.py +8 -8
- claude_mpm/services/hook_installer_service.py +77 -8
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +15 -3
- claude_mpm/services/monitor/server.py +571 -11
- claude_mpm/services/pm_skills_deployer.py +884 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/skills/git_skill_source_manager.py +281 -20
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +192 -70
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +37 -6
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/core.py +262 -123
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/__init__.py +2 -1
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -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-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -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-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +112 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +98 -3
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +115 -4
- claude_mpm/utils/agent_filters.py +1 -1
- claude_mpm/utils/migration.py +4 -4
- claude_mpm/utils/robust_installer.py +86 -21
- claude_mpm-5.6.34.dist-info/METADATA +393 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/RECORD +486 -145
- claude_mpm-5.4.22.dist-info/METADATA +0 -996
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Auto-pause handler for Claude Code hooks.
|
|
3
|
+
|
|
4
|
+
WHY: Automatically pause Claude sessions when context usage reaches 90% to prevent
|
|
5
|
+
context window exhaustion. Integrates with existing hook infrastructure to monitor
|
|
6
|
+
token usage and trigger incremental pause capture.
|
|
7
|
+
|
|
8
|
+
DESIGN DECISIONS:
|
|
9
|
+
- Integrates with ContextUsageTracker for token tracking across hook invocations
|
|
10
|
+
- Uses IncrementalPauseManager for capturing actions during pause mode
|
|
11
|
+
- Thread-safe - handles hook calls from multiple processes via file-based state
|
|
12
|
+
- Emits warnings to stderr for visibility without breaking hook flow
|
|
13
|
+
- Only triggers auto-pause on NEW threshold crossings (prevents duplicate warnings)
|
|
14
|
+
- Graceful error handling - auto-pause failures don't break main hook processing
|
|
15
|
+
|
|
16
|
+
USAGE:
|
|
17
|
+
# Initialize handler in hook handler
|
|
18
|
+
auto_pause = AutoPauseHandler()
|
|
19
|
+
|
|
20
|
+
# Monitor token usage from API responses
|
|
21
|
+
if "usage" in metadata:
|
|
22
|
+
threshold_crossed = auto_pause.on_usage_update(metadata["usage"])
|
|
23
|
+
if threshold_crossed:
|
|
24
|
+
warning = auto_pause.emit_threshold_warning(threshold_crossed)
|
|
25
|
+
_log(f"\n⚠️ {warning}")
|
|
26
|
+
|
|
27
|
+
# Record actions during pause mode
|
|
28
|
+
if auto_pause.is_pause_active():
|
|
29
|
+
auto_pause.on_tool_call(tool_name, tool_args)
|
|
30
|
+
auto_pause.on_assistant_response(response_summary)
|
|
31
|
+
|
|
32
|
+
# Finalize on session end
|
|
33
|
+
session_file = auto_pause.on_session_end()
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
import os
|
|
37
|
+
from datetime import datetime, timezone
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
from typing import Any, Dict, Optional
|
|
40
|
+
|
|
41
|
+
from claude_mpm.core.logger import get_logger
|
|
42
|
+
from claude_mpm.services.cli.incremental_pause_manager import IncrementalPauseManager
|
|
43
|
+
from claude_mpm.services.infrastructure.context_usage_tracker import (
|
|
44
|
+
ContextUsageTracker,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Try to import _log from hook_handler, fall back to no-op
|
|
48
|
+
try:
|
|
49
|
+
from claude_mpm.hooks.claude_hooks.hook_handler import _log
|
|
50
|
+
except ImportError:
|
|
51
|
+
|
|
52
|
+
def _log(msg: str) -> None:
|
|
53
|
+
pass # Silent fallback
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
logger = get_logger(__name__)
|
|
57
|
+
|
|
58
|
+
# Debug mode
|
|
59
|
+
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "false").lower() == "true"
|
|
60
|
+
|
|
61
|
+
# Warning messages for threshold crossings
|
|
62
|
+
THRESHOLD_WARNINGS = {
|
|
63
|
+
"caution": "Context usage at 70%. Consider wrapping up current work.",
|
|
64
|
+
"warning": "Context usage at 85%. Session nearing capacity.",
|
|
65
|
+
"auto_pause": "Context usage at 90%. Auto-pause activated. Actions are being recorded for session continuity.",
|
|
66
|
+
"critical": "Context usage at 95%. Session nearly exhausted. Wrapping up...",
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Maximum length for summaries to avoid storing full responses
|
|
70
|
+
MAX_SUMMARY_LENGTH = 500
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class AutoPauseHandler:
|
|
74
|
+
"""Handler for automatic session pausing based on context usage thresholds.
|
|
75
|
+
|
|
76
|
+
Integrates with Claude Code hooks to:
|
|
77
|
+
1. Track cumulative token usage from API responses
|
|
78
|
+
2. Trigger auto-pause when 90% context used
|
|
79
|
+
3. Capture all subsequent actions during pause mode
|
|
80
|
+
4. Emit warnings/notifications to user
|
|
81
|
+
|
|
82
|
+
Features:
|
|
83
|
+
- File-based state persistence (works across hook process restarts)
|
|
84
|
+
- Thread-safe through atomic file operations
|
|
85
|
+
- Graceful error handling (failures don't break main hook flow)
|
|
86
|
+
- Only emits warnings on NEW threshold crossings
|
|
87
|
+
- Summarizes long content to prevent memory bloat
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
def __init__(self, project_path: Optional[Path] = None):
|
|
91
|
+
"""Initialize auto-pause handler.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
project_path: Project root path (default: current directory)
|
|
95
|
+
"""
|
|
96
|
+
self.project_path = (project_path or Path.cwd()).resolve()
|
|
97
|
+
|
|
98
|
+
# Initialize services
|
|
99
|
+
self.tracker = ContextUsageTracker(self.project_path)
|
|
100
|
+
self.pause_manager = IncrementalPauseManager(self.project_path)
|
|
101
|
+
|
|
102
|
+
# Track previous threshold to detect NEW crossings
|
|
103
|
+
self._previous_threshold: Optional[str] = None
|
|
104
|
+
|
|
105
|
+
# Load initial state
|
|
106
|
+
try:
|
|
107
|
+
current_state = self.tracker.get_current_state()
|
|
108
|
+
self._previous_threshold = current_state.threshold_reached
|
|
109
|
+
|
|
110
|
+
if DEBUG:
|
|
111
|
+
_log(
|
|
112
|
+
f"AutoPauseHandler initialized: "
|
|
113
|
+
f"{current_state.percentage_used:.1f}% context used, "
|
|
114
|
+
f"threshold: {current_state.threshold_reached}"
|
|
115
|
+
)
|
|
116
|
+
except Exception as e:
|
|
117
|
+
logger.error(f"Failed to initialize AutoPauseHandler: {e}")
|
|
118
|
+
# Continue with None - will initialize on first update
|
|
119
|
+
|
|
120
|
+
def on_usage_update(self, usage: Dict[str, Any]) -> Optional[str]:
|
|
121
|
+
"""Process token usage from a Claude API response.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
usage: Dict with 'input_tokens', 'output_tokens',
|
|
125
|
+
'cache_creation_input_tokens', 'cache_read_input_tokens'
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Threshold name if a NEW threshold was crossed ('caution', 'warning',
|
|
129
|
+
'auto_pause', 'critical'), or None if no new threshold crossed.
|
|
130
|
+
|
|
131
|
+
Raises:
|
|
132
|
+
ValueError: If usage data is invalid
|
|
133
|
+
"""
|
|
134
|
+
try:
|
|
135
|
+
# Extract token counts
|
|
136
|
+
input_tokens = usage.get("input_tokens", 0)
|
|
137
|
+
output_tokens = usage.get("output_tokens", 0)
|
|
138
|
+
cache_creation = usage.get("cache_creation_input_tokens", 0)
|
|
139
|
+
cache_read = usage.get("cache_read_input_tokens", 0)
|
|
140
|
+
|
|
141
|
+
# Validate token counts
|
|
142
|
+
if any(
|
|
143
|
+
t < 0 for t in [input_tokens, output_tokens, cache_creation, cache_read]
|
|
144
|
+
):
|
|
145
|
+
raise ValueError("Token counts cannot be negative")
|
|
146
|
+
|
|
147
|
+
# Update cumulative usage
|
|
148
|
+
state = self.tracker.update_usage(
|
|
149
|
+
input_tokens=input_tokens,
|
|
150
|
+
output_tokens=output_tokens,
|
|
151
|
+
cache_creation=cache_creation,
|
|
152
|
+
cache_read=cache_read,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Check if we crossed a NEW threshold
|
|
156
|
+
current_threshold = state.threshold_reached
|
|
157
|
+
new_threshold_crossed = None
|
|
158
|
+
|
|
159
|
+
if current_threshold != self._previous_threshold:
|
|
160
|
+
# Determine if this is a higher threshold
|
|
161
|
+
threshold_order = ["caution", "warning", "auto_pause", "critical"]
|
|
162
|
+
|
|
163
|
+
prev_idx = (
|
|
164
|
+
threshold_order.index(self._previous_threshold)
|
|
165
|
+
if self._previous_threshold in threshold_order
|
|
166
|
+
else -1
|
|
167
|
+
)
|
|
168
|
+
curr_idx = (
|
|
169
|
+
threshold_order.index(current_threshold)
|
|
170
|
+
if current_threshold in threshold_order
|
|
171
|
+
else -1
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if curr_idx > prev_idx:
|
|
175
|
+
new_threshold_crossed = current_threshold
|
|
176
|
+
self._previous_threshold = current_threshold
|
|
177
|
+
|
|
178
|
+
if DEBUG:
|
|
179
|
+
_log(
|
|
180
|
+
f"Context threshold crossed: {current_threshold} "
|
|
181
|
+
f"({state.percentage_used:.1f}%)"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Trigger auto-pause if threshold reached
|
|
185
|
+
if current_threshold in ["auto_pause", "critical"]:
|
|
186
|
+
self._trigger_auto_pause(state)
|
|
187
|
+
|
|
188
|
+
return new_threshold_crossed
|
|
189
|
+
|
|
190
|
+
except Exception as e:
|
|
191
|
+
logger.error(f"Failed to update usage: {e}")
|
|
192
|
+
if DEBUG:
|
|
193
|
+
_log(f"❌ Usage update failed: {e}")
|
|
194
|
+
# Don't propagate error - auto-pause is optional
|
|
195
|
+
return None
|
|
196
|
+
|
|
197
|
+
def on_tool_call(self, tool_name: str, tool_args: Dict[str, Any]) -> None:
|
|
198
|
+
"""Record a tool call if auto-pause is active.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
tool_name: Name of the tool being called
|
|
202
|
+
tool_args: Tool arguments dictionary
|
|
203
|
+
|
|
204
|
+
Raises:
|
|
205
|
+
RuntimeError: If append operation fails (optional, logged only)
|
|
206
|
+
"""
|
|
207
|
+
if not self.is_pause_active():
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
try:
|
|
211
|
+
# Summarize tool args to avoid storing large data
|
|
212
|
+
args_summary = self._summarize_dict(tool_args)
|
|
213
|
+
|
|
214
|
+
# Get current context percentage
|
|
215
|
+
state = self.tracker.get_current_state()
|
|
216
|
+
|
|
217
|
+
# Record action
|
|
218
|
+
self.pause_manager.append_action(
|
|
219
|
+
action_type="tool_call",
|
|
220
|
+
action_data={
|
|
221
|
+
"tool": tool_name,
|
|
222
|
+
"args_summary": args_summary,
|
|
223
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
224
|
+
},
|
|
225
|
+
context_percentage=state.percentage_used / 100,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
if DEBUG:
|
|
229
|
+
_log(f"Recorded tool call during pause: {tool_name}")
|
|
230
|
+
|
|
231
|
+
except Exception as e:
|
|
232
|
+
logger.error(f"Failed to record tool call: {e}")
|
|
233
|
+
if DEBUG:
|
|
234
|
+
_log(f"❌ Failed to record tool call: {e}")
|
|
235
|
+
|
|
236
|
+
def on_assistant_response(self, response_summary: str) -> None:
|
|
237
|
+
"""Record an assistant response if auto-pause is active.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
response_summary: Summary of assistant response (will be truncated)
|
|
241
|
+
|
|
242
|
+
Raises:
|
|
243
|
+
RuntimeError: If append operation fails (optional, logged only)
|
|
244
|
+
"""
|
|
245
|
+
if not self.is_pause_active():
|
|
246
|
+
return
|
|
247
|
+
|
|
248
|
+
try:
|
|
249
|
+
# Truncate long responses
|
|
250
|
+
summary = self._truncate_text(response_summary, MAX_SUMMARY_LENGTH)
|
|
251
|
+
|
|
252
|
+
# Get current context percentage
|
|
253
|
+
state = self.tracker.get_current_state()
|
|
254
|
+
|
|
255
|
+
# Record action
|
|
256
|
+
self.pause_manager.append_action(
|
|
257
|
+
action_type="assistant_response",
|
|
258
|
+
action_data={
|
|
259
|
+
"summary": summary,
|
|
260
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
261
|
+
},
|
|
262
|
+
context_percentage=state.percentage_used / 100,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
if DEBUG:
|
|
266
|
+
_log(
|
|
267
|
+
f"Recorded assistant response during pause (length: {len(summary)})"
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
except Exception as e:
|
|
271
|
+
logger.error(f"Failed to record assistant response: {e}")
|
|
272
|
+
if DEBUG:
|
|
273
|
+
_log(f"❌ Failed to record assistant response: {e}")
|
|
274
|
+
|
|
275
|
+
def on_user_message(self, message_summary: str) -> None:
|
|
276
|
+
"""Record a user message if auto-pause is active.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
message_summary: Summary of user message (will be truncated)
|
|
280
|
+
|
|
281
|
+
Raises:
|
|
282
|
+
RuntimeError: If append operation fails (optional, logged only)
|
|
283
|
+
"""
|
|
284
|
+
if not self.is_pause_active():
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
try:
|
|
288
|
+
# Truncate long messages
|
|
289
|
+
summary = self._truncate_text(message_summary, MAX_SUMMARY_LENGTH)
|
|
290
|
+
|
|
291
|
+
# Get current context percentage
|
|
292
|
+
state = self.tracker.get_current_state()
|
|
293
|
+
|
|
294
|
+
# Record action
|
|
295
|
+
self.pause_manager.append_action(
|
|
296
|
+
action_type="user_message",
|
|
297
|
+
action_data={
|
|
298
|
+
"summary": summary,
|
|
299
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
300
|
+
},
|
|
301
|
+
context_percentage=state.percentage_used / 100,
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
if DEBUG:
|
|
305
|
+
_log(f"Recorded user message during pause (length: {len(summary)})")
|
|
306
|
+
|
|
307
|
+
except Exception as e:
|
|
308
|
+
logger.error(f"Failed to record user message: {e}")
|
|
309
|
+
if DEBUG:
|
|
310
|
+
_log(f"❌ Failed to record user message: {e}")
|
|
311
|
+
|
|
312
|
+
def on_session_end(self) -> Optional[Path]:
|
|
313
|
+
"""Called when session ends. Finalizes any active pause.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
Path to finalized session file, or None if no pause was active.
|
|
317
|
+
|
|
318
|
+
Raises:
|
|
319
|
+
RuntimeError: If finalization fails
|
|
320
|
+
"""
|
|
321
|
+
if not self.is_pause_active():
|
|
322
|
+
if DEBUG:
|
|
323
|
+
_log("No active pause to finalize")
|
|
324
|
+
return None
|
|
325
|
+
|
|
326
|
+
try:
|
|
327
|
+
# Finalize the pause session
|
|
328
|
+
session_path = self.pause_manager.finalize_pause(create_full_snapshot=True)
|
|
329
|
+
|
|
330
|
+
if session_path and DEBUG:
|
|
331
|
+
_log(f"✅ Session finalized: {session_path.name}")
|
|
332
|
+
|
|
333
|
+
return session_path
|
|
334
|
+
|
|
335
|
+
except Exception as e:
|
|
336
|
+
logger.error(f"Failed to finalize pause session: {e}")
|
|
337
|
+
if DEBUG:
|
|
338
|
+
_log(f"❌ Failed to finalize pause: {e}")
|
|
339
|
+
raise
|
|
340
|
+
|
|
341
|
+
def is_pause_active(self) -> bool:
|
|
342
|
+
"""Check if auto-pause mode is currently active.
|
|
343
|
+
|
|
344
|
+
Returns:
|
|
345
|
+
True if auto-pause has been triggered and is capturing actions
|
|
346
|
+
"""
|
|
347
|
+
return self.pause_manager.is_pause_active()
|
|
348
|
+
|
|
349
|
+
def get_status(self) -> Dict[str, Any]:
|
|
350
|
+
"""Get current status for display/logging.
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
Dict with: context_percentage, threshold_reached,
|
|
354
|
+
pause_active, actions_recorded, etc.
|
|
355
|
+
"""
|
|
356
|
+
try:
|
|
357
|
+
state = self.tracker.get_current_state()
|
|
358
|
+
pause_summary = self.pause_manager.get_pause_summary()
|
|
359
|
+
|
|
360
|
+
status = {
|
|
361
|
+
"context_percentage": round(state.percentage_used, 2),
|
|
362
|
+
"threshold_reached": state.threshold_reached,
|
|
363
|
+
"auto_pause_active": state.auto_pause_active,
|
|
364
|
+
"pause_active": self.is_pause_active(),
|
|
365
|
+
"session_id": state.session_id,
|
|
366
|
+
"total_tokens": (
|
|
367
|
+
state.cumulative_input_tokens + state.cumulative_output_tokens
|
|
368
|
+
),
|
|
369
|
+
"budget": ContextUsageTracker.CONTEXT_BUDGET,
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
# Add pause details if active
|
|
373
|
+
if pause_summary:
|
|
374
|
+
status["pause_details"] = {
|
|
375
|
+
"action_count": pause_summary["action_count"],
|
|
376
|
+
"duration_seconds": pause_summary["duration_seconds"],
|
|
377
|
+
"context_range": pause_summary["context_range"],
|
|
378
|
+
"last_action_type": pause_summary["last_action_type"],
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return status
|
|
382
|
+
|
|
383
|
+
except Exception as e:
|
|
384
|
+
logger.error(f"Failed to get status: {e}")
|
|
385
|
+
return {"error": str(e)}
|
|
386
|
+
|
|
387
|
+
def emit_threshold_warning(self, threshold: str) -> str:
|
|
388
|
+
"""Generate a warning message for threshold crossing.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
threshold: Threshold name ('caution', 'warning', 'auto_pause', 'critical')
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
User-friendly warning message string
|
|
395
|
+
"""
|
|
396
|
+
warning = THRESHOLD_WARNINGS.get(
|
|
397
|
+
threshold, f"Context usage threshold reached: {threshold}"
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
# Add context percentage to warning
|
|
401
|
+
try:
|
|
402
|
+
state = self.tracker.get_current_state()
|
|
403
|
+
warning = f"{warning} ({state.percentage_used:.1f}%)"
|
|
404
|
+
except Exception:
|
|
405
|
+
pass # nosec B110 - Intentionally ignore formatting errors, warning is already constructed
|
|
406
|
+
|
|
407
|
+
return warning
|
|
408
|
+
|
|
409
|
+
def _trigger_auto_pause(self, state) -> None:
|
|
410
|
+
"""Trigger auto-pause and start recording actions.
|
|
411
|
+
|
|
412
|
+
Args:
|
|
413
|
+
state: Current context usage state
|
|
414
|
+
|
|
415
|
+
Raises:
|
|
416
|
+
RuntimeError: If pause cannot be started
|
|
417
|
+
"""
|
|
418
|
+
try:
|
|
419
|
+
# Check if pause is already active
|
|
420
|
+
if self.is_pause_active():
|
|
421
|
+
if DEBUG:
|
|
422
|
+
_log("Auto-pause already active, skipping trigger")
|
|
423
|
+
return
|
|
424
|
+
|
|
425
|
+
# Start incremental pause
|
|
426
|
+
session_id = self.pause_manager.start_incremental_pause(
|
|
427
|
+
context_percentage=state.percentage_used / 100,
|
|
428
|
+
initial_state=state.__dict__,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
if DEBUG:
|
|
432
|
+
_log(
|
|
433
|
+
f"✅ Auto-pause triggered: {session_id} "
|
|
434
|
+
f"({state.percentage_used:.1f}% context used)"
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
except Exception as e:
|
|
438
|
+
logger.error(f"Failed to trigger auto-pause: {e}")
|
|
439
|
+
if DEBUG:
|
|
440
|
+
_log(f"❌ Failed to trigger auto-pause: {e}")
|
|
441
|
+
# Don't propagate - auto-pause is optional
|
|
442
|
+
|
|
443
|
+
def _summarize_dict(
|
|
444
|
+
self, data: Dict[str, Any], max_items: int = 10
|
|
445
|
+
) -> Dict[str, Any]:
|
|
446
|
+
"""Create a summary of a dictionary by limiting items and truncating values.
|
|
447
|
+
|
|
448
|
+
Args:
|
|
449
|
+
data: Dictionary to summarize
|
|
450
|
+
max_items: Maximum number of items to include
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
Summarized dictionary
|
|
454
|
+
"""
|
|
455
|
+
summary = {}
|
|
456
|
+
|
|
457
|
+
for i, (key, value) in enumerate(data.items()):
|
|
458
|
+
if i >= max_items:
|
|
459
|
+
summary["..."] = f"({len(data) - max_items} more items)"
|
|
460
|
+
break
|
|
461
|
+
|
|
462
|
+
# Truncate string values
|
|
463
|
+
if isinstance(value, str):
|
|
464
|
+
summary[key] = self._truncate_text(value, 100)
|
|
465
|
+
elif isinstance(value, (list, dict)):
|
|
466
|
+
summary[key] = f"<{type(value).__name__} with {len(value)} items>"
|
|
467
|
+
else:
|
|
468
|
+
summary[key] = str(value)[:100]
|
|
469
|
+
|
|
470
|
+
return summary
|
|
471
|
+
|
|
472
|
+
def _truncate_text(self, text: str, max_length: int) -> str:
|
|
473
|
+
"""Truncate text to maximum length with ellipsis.
|
|
474
|
+
|
|
475
|
+
Args:
|
|
476
|
+
text: Text to truncate
|
|
477
|
+
max_length: Maximum length
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
Truncated text with "..." suffix if truncated
|
|
481
|
+
"""
|
|
482
|
+
if len(text) <= max_length:
|
|
483
|
+
return text
|
|
484
|
+
|
|
485
|
+
return text[: max_length - 3] + "..."
|