claude-mpm 4.24.0__py3-none-any.whl → 5.4.41__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/__init__.py +4 -0
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +3 -48
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +735 -925
- claude_mpm/agents/WORKFLOW.md +5 -254
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +14 -48
- claude_mpm/agents/base_agent.json +7 -4
- claude_mpm/agents/frontmatter_validator.py +71 -3
- claude_mpm/agents/templates/circuit-breakers.md +1391 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +48 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/cli/__init__.py +37 -2
- claude_mpm/cli/__main__.py +4 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +180 -31
- claude_mpm/cli/commands/agents.py +1116 -55
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/analyze.py +3 -3
- claude_mpm/cli/commands/auto_configure.py +725 -242
- claude_mpm/cli/commands/config.py +95 -6
- claude_mpm/cli/commands/configure.py +1875 -46
- claude_mpm/cli/commands/configure_agent_display.py +29 -10
- claude_mpm/cli/commands/configure_navigation.py +63 -46
- claude_mpm/cli/commands/debug.py +12 -12
- claude_mpm/cli/commands/doctor.py +10 -2
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/local_deploy.py +1 -4
- claude_mpm/cli/commands/mcp_install_commands.py +1 -1
- claude_mpm/cli/commands/mpm_init/core.py +229 -2
- claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +286 -6
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/profile.py +277 -0
- claude_mpm/cli/commands/run.py +123 -165
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +782 -20
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/executor.py +96 -3
- claude_mpm/cli/interactive/agent_wizard.py +1030 -45
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +307 -10
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
- claude_mpm/cli/parsers/base_parser.py +65 -0
- claude_mpm/cli/parsers/config_parser.py +162 -39
- claude_mpm/cli/parsers/profile_parser.py +148 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +146 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +1280 -118
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/cli_module/commands.py +1 -1
- claude_mpm/commands/mpm-config.md +21 -134
- claude_mpm/commands/mpm-doctor.md +16 -20
- claude_mpm/commands/mpm-help.md +13 -283
- claude_mpm/commands/mpm-init.md +88 -489
- claude_mpm/commands/mpm-monitor.md +23 -401
- claude_mpm/commands/mpm-organize.md +72 -247
- claude_mpm/commands/mpm-postmortem.md +21 -0
- claude_mpm/commands/mpm-session-resume.md +30 -0
- claude_mpm/commands/mpm-status.md +13 -68
- claude_mpm/commands/mpm-ticket-view.md +109 -0
- claude_mpm/commands/mpm-version.md +13 -106
- claude_mpm/commands/mpm.md +10 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +352 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/constants.py +13 -0
- claude_mpm/core/claude_runner.py +5 -34
- claude_mpm/core/config.py +15 -1
- claude_mpm/core/constants.py +1 -1
- claude_mpm/core/framework/__init__.py +3 -16
- claude_mpm/core/framework/formatters/content_formatter.py +3 -13
- claude_mpm/core/framework/loaders/agent_loader.py +8 -5
- claude_mpm/core/framework/loaders/file_loader.py +54 -101
- claude_mpm/core/framework/loaders/instruction_loader.py +66 -5
- claude_mpm/core/framework_loader.py +4 -2
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +41 -2
- claude_mpm/core/interactive_session.py +91 -10
- claude_mpm/core/logger.py +16 -1
- claude_mpm/core/oneshot_session.py +71 -8
- claude_mpm/core/optimized_startup.py +59 -0
- claude_mpm/core/output_style_manager.py +173 -43
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/shared/config_loader.py +1 -1
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/socketio_pool.py +3 -3
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/unified_agent_registry.py +134 -16
- claude_mpm/core/unified_config.py +22 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -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/experimental/cli_enhancements.py +1 -5
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.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__/installer.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/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +214 -79
- claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
- claude_mpm/hooks/claude_hooks/installer.py +33 -10
- claude_mpm/hooks/claude_hooks/memory_integration.py +28 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.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__/duplicate_detector.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 +30 -6
- claude_mpm/hooks/failure_learning/__init__.py +2 -8
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
- claude_mpm/hooks/kuzu_response_hook.py +1 -5
- claude_mpm/hooks/memory_integration_hook.py +46 -1
- claude_mpm/init.py +63 -19
- claude_mpm/models/agent_definition.py +7 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/scripts/claude-hook-handler.sh +60 -20
- claude_mpm/scripts/launch_monitor.py +93 -13
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/agents/agent_builder.py +48 -12
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +148 -2
- claude_mpm/services/agents/deployment/agent_discovery_service.py +104 -73
- claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
- claude_mpm/services/agents/deployment/agent_template_builder.py +238 -15
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
- claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +422 -31
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +841 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
- claude_mpm/services/agents/git_source_manager.py +663 -0
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
- claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
- claude_mpm/services/agents/local_template_manager.py +50 -10
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1094 -0
- claude_mpm/services/agents/startup_sync.py +259 -0
- claude_mpm/services/agents/toolchain_detector.py +478 -0
- claude_mpm/services/analysis/__init__.py +35 -0
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/cli/session_pause_manager.py +1 -1
- claude_mpm/services/command_deployment_service.py +271 -6
- claude_mpm/services/core/base.py +7 -2
- claude_mpm/services/core/interfaces/__init__.py +1 -3
- claude_mpm/services/core/interfaces/health.py +1 -4
- claude_mpm/services/core/models/__init__.py +2 -11
- claude_mpm/services/diagnostics/checks/__init__.py +4 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -4
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
- claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
- claude_mpm/services/event_bus/config.py +3 -1
- claude_mpm/services/event_bus/direct_relay.py +3 -3
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +579 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
- claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +3 -13
- claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
- claude_mpm/services/local_ops/health_manager.py +1 -4
- claude_mpm/services/local_ops/resource_monitor.py +1 -1
- claude_mpm/services/mcp_config_manager.py +75 -145
- claude_mpm/services/mcp_service_verifier.py +6 -3
- claude_mpm/services/model/model_router.py +1 -2
- claude_mpm/services/monitor/daemon.py +38 -11
- claude_mpm/services/monitor/daemon_manager.py +134 -21
- claude_mpm/services/monitor/management/lifecycle.py +8 -1
- claude_mpm/services/monitor/server.py +700 -24
- claude_mpm/services/pm_skills_deployer.py +676 -0
- claude_mpm/services/port_manager.py +1 -1
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/profile_manager.py +331 -0
- claude_mpm/services/project/documentation_manager.py +2 -1
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/project/toolchain_analyzer.py +3 -1
- claude_mpm/services/runner_configuration_service.py +16 -3
- claude_mpm/services/self_upgrade_service.py +120 -12
- claude_mpm/services/session_management_service.py +16 -4
- claude_mpm/services/skills/__init__.py +21 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1297 -0
- claude_mpm/services/skills/selective_skill_deployer.py +704 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +1072 -0
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +51 -6
- claude_mpm/services/socketio/handlers/connection.py +1 -1
- claude_mpm/services/socketio/handlers/git.py +1 -1
- claude_mpm/services/socketio/server/core.py +387 -112
- claude_mpm/services/socketio/server/main.py +1 -3
- claude_mpm/services/system_instructions_service.py +1 -3
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
- claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
- claude_mpm/services/unified/unified_deployment.py +1 -5
- claude_mpm/services/version_control/conflict_resolution.py +6 -4
- claude_mpm/services/version_control/git_operations.py +103 -0
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
- claude_mpm/skills/skill_manager.py +92 -3
- claude_mpm/skills/skills_registry.py +0 -1
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/tools/__main__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +91 -12
- claude_mpm/utils/agent_filters.py +261 -0
- claude_mpm/utils/dependency_cache.py +3 -1
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +49 -7
- claude_mpm/utils/structured_questions.py +619 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.4.41.dist-info}/METADATA +445 -122
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.4.41.dist-info}/RECORD +298 -503
- claude_mpm-5.4.41.dist-info/entry_points.txt +5 -0
- claude_mpm-5.4.41.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.41.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
- claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
- claude_mpm/agents/BASE_OPS.md +0 -219
- claude_mpm/agents/BASE_PM.md +0 -468
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
- claude_mpm/agents/BASE_QA.md +0 -167
- claude_mpm/agents/BASE_RESEARCH.md +0 -53
- claude_mpm/agents/base_agent_loader.py +0 -626
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
- claude_mpm/agents/templates/agent-manager.json +0 -273
- claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
- claude_mpm/agents/templates/api_qa.json +0 -183
- claude_mpm/agents/templates/circuit_breakers.md +0 -638
- claude_mpm/agents/templates/clerk-ops.json +0 -235
- claude_mpm/agents/templates/code_analyzer.json +0 -101
- claude_mpm/agents/templates/content-agent.json +0 -358
- claude_mpm/agents/templates/dart_engineer.json +0 -307
- claude_mpm/agents/templates/data_engineer.json +0 -225
- claude_mpm/agents/templates/documentation.json +0 -238
- claude_mpm/agents/templates/engineer.json +0 -210
- claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
- claude_mpm/agents/templates/golang_engineer.json +0 -270
- claude_mpm/agents/templates/imagemagick.json +0 -264
- claude_mpm/agents/templates/java_engineer.json +0 -346
- claude_mpm/agents/templates/javascript_engineer_agent.json +0 -380
- claude_mpm/agents/templates/local_ops_agent.json +0 -1840
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
- claude_mpm/agents/templates/memory_manager.json +0 -158
- claude_mpm/agents/templates/nextjs_engineer.json +0 -285
- claude_mpm/agents/templates/ops.json +0 -185
- claude_mpm/agents/templates/php-engineer.json +0 -287
- claude_mpm/agents/templates/product_owner.json +0 -338
- claude_mpm/agents/templates/project_organizer.json +0 -144
- claude_mpm/agents/templates/prompt-engineer.json +0 -737
- claude_mpm/agents/templates/python_engineer.json +0 -387
- claude_mpm/agents/templates/qa.json +0 -243
- claude_mpm/agents/templates/react_engineer.json +0 -239
- claude_mpm/agents/templates/refactoring_engineer.json +0 -276
- claude_mpm/agents/templates/research.json +0 -188
- claude_mpm/agents/templates/ruby-engineer.json +0 -280
- claude_mpm/agents/templates/rust_engineer.json +0 -275
- claude_mpm/agents/templates/security.json +0 -202
- claude_mpm/agents/templates/svelte-engineer.json +0 -225
- claude_mpm/agents/templates/tauri_engineer.json +0 -274
- claude_mpm/agents/templates/ticketing.json +0 -178
- claude_mpm/agents/templates/typescript_engineer.json +0 -285
- claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
- claude_mpm/agents/templates/version_control.json +0 -159
- claude_mpm/agents/templates/web_qa.json +0 -400
- claude_mpm/agents/templates/web_ui.json +0 -189
- claude_mpm/cli/commands/agents_detect.py +0 -380
- claude_mpm/cli/commands/agents_recommend.py +0 -309
- claude_mpm/cli/ticket_cli.py +0 -35
- claude_mpm/commands/mpm-agents-detect.md +0 -168
- claude_mpm/commands/mpm-agents-recommend.md +0 -214
- claude_mpm/commands/mpm-agents.md +0 -122
- claude_mpm/commands/mpm-auto-configure.md +0 -269
- claude_mpm/commands/mpm-resume.md +0 -372
- claude_mpm/commands/mpm-tickets.md +0 -151
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- claude_mpm/dashboard/analysis_runner.py +0 -455
- claude_mpm/dashboard/index.html +0 -13
- claude_mpm/dashboard/open_dashboard.py +0 -66
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
- claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
- claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
- claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
- claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
- claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
- claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
- claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
- claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/connection-manager.js +0 -536
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/built/react/events.js +0 -30
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
- claude_mpm/dashboard/static/built/shared/logger.js +0 -385
- claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/built/socket-client.js +0 -2
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/css/activity.css +0 -1958
- claude_mpm/dashboard/static/css/connection-status.css +0 -370
- claude_mpm/dashboard/static/css/dashboard.css +0 -4701
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/dist/dashboard.js +0 -2
- claude_mpm/dashboard/static/dist/react/events.js +0 -30
- claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- claude_mpm/dashboard/static/events.html +0 -607
- claude_mpm/dashboard/static/index.html +0 -635
- claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
- claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
- claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
- claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
- claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
- claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
- claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
- claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
- claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
- claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
- claude_mpm/dashboard/static/js/connection-manager.js +0 -536
- claude_mpm/dashboard/static/js/dashboard.js +0 -1896
- claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/js/shared/logger.js +0 -385
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/js/socket-client.js +0 -1457
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/legacy/activity.html +0 -736
- claude_mpm/dashboard/static/legacy/agents.html +0 -786
- claude_mpm/dashboard/static/legacy/files.html +0 -747
- claude_mpm/dashboard/static/legacy/tools.html +0 -831
- claude_mpm/dashboard/static/monitors.html +0 -431
- claude_mpm/dashboard/static/production/events.html +0 -659
- claude_mpm/dashboard/static/production/main.html +0 -698
- claude_mpm/dashboard/static/production/monitors.html +0 -483
- claude_mpm/dashboard/static/socket.io.min.js +0 -7
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
- claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
- claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
- claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
- claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
- claude_mpm/dashboard/templates/code_simple.html +0 -153
- claude_mpm/dashboard/templates/index.html +0 -606
- claude_mpm/dashboard/test_dashboard.html +0 -372
- claude_mpm/scripts/mcp_server.py +0 -75
- claude_mpm/scripts/mcp_wrapper.py +0 -39
- claude_mpm/services/mcp_gateway/__init__.py +0 -159
- claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
- claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
- claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
- claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
- claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
- claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
- claude_mpm/services/mcp_gateway/core/base.py +0 -312
- claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
- claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
- claude_mpm/services/mcp_gateway/core/process_pool.py +0 -971
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
- claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
- claude_mpm/services/mcp_gateway/main.py +0 -589
- claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
- claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
- claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -419
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -714
- claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
- claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -551
- claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
- claude_mpm-4.24.0.dist-info/entry_points.txt +0 -10
- claude_mpm-4.24.0.dist-info/licenses/LICENSE +0 -21
- /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
- /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
- /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
- /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.4.41.dist-info}/WHEEL +0 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.4.41.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Git source sync services for agent templates.
|
|
2
|
+
|
|
3
|
+
This module provides services for syncing agent templates from remote
|
|
4
|
+
Git repositories, with ETag-based caching for efficient updates and
|
|
5
|
+
SQLite-based state tracking.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from claude_mpm.services.agents.sources.agent_sync_state import AgentSyncState
|
|
9
|
+
from claude_mpm.services.agents.sources.git_source_sync_service import (
|
|
10
|
+
GitSourceSyncService,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = ["AgentSyncState", "GitSourceSyncService"]
|
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
"""SQLite-based state tracking for agent sync operations.
|
|
2
|
+
|
|
3
|
+
This service manages sync state for agent files from Git sources, providing:
|
|
4
|
+
- Per-file SHA-256 content hash tracking
|
|
5
|
+
- Source metadata (URLs, last commit SHA, ETags)
|
|
6
|
+
- Complete sync history audit trail
|
|
7
|
+
- Change detection for efficient incremental updates
|
|
8
|
+
|
|
9
|
+
Database Location: ~/.config/claude-mpm/agent_sync.db
|
|
10
|
+
Thread Safety: Uses connection-per-operation pattern (safe for single-threaded use)
|
|
11
|
+
Performance: Optimized with indexes; expected <10ms per operation
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
import sqlite3
|
|
16
|
+
from contextlib import contextmanager
|
|
17
|
+
from datetime import datetime, timedelta, timezone
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any, Dict, List, Optional
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AgentSyncStateError(Exception):
|
|
25
|
+
"""Base exception for sync state errors."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class DatabaseError(AgentSyncStateError):
|
|
29
|
+
"""Database operation errors."""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AgentSyncState:
|
|
33
|
+
"""Service for tracking agent sync state in SQLite database.
|
|
34
|
+
|
|
35
|
+
Responsibilities:
|
|
36
|
+
- Manage SQLite connection lifecycle
|
|
37
|
+
- Track per-file content hashes (SHA-256)
|
|
38
|
+
- Record sync history with timestamps
|
|
39
|
+
- Query file change status
|
|
40
|
+
- Provide migration utilities
|
|
41
|
+
|
|
42
|
+
Design Decision: Connection-per-operation pattern
|
|
43
|
+
|
|
44
|
+
Rationale: Simplifies connection management and prevents connection leaks.
|
|
45
|
+
SQLite allows concurrent reads but serializes writes, so connection pooling
|
|
46
|
+
provides minimal benefit for our read-heavy workload.
|
|
47
|
+
|
|
48
|
+
Trade-offs:
|
|
49
|
+
- Simplicity: No pool management overhead
|
|
50
|
+
- Safety: Automatic cleanup via context manager
|
|
51
|
+
- Performance: Negligible overhead (<1ms per connection)
|
|
52
|
+
|
|
53
|
+
Extension Points: Can add connection pooling if multi-threaded access needed.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
# Schema version for migrations
|
|
57
|
+
SCHEMA_VERSION = 1
|
|
58
|
+
|
|
59
|
+
def __init__(self, db_path: Optional[Path] = None):
|
|
60
|
+
"""Initialize sync state service.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
db_path: Path to SQLite database (defaults to ~/.config/claude-mpm/agent_sync.db)
|
|
64
|
+
"""
|
|
65
|
+
if db_path:
|
|
66
|
+
self.db_path = Path(db_path)
|
|
67
|
+
else:
|
|
68
|
+
# Default location: ~/.config/claude-mpm/agent_sync.db
|
|
69
|
+
config_dir = Path.home() / ".config" / "claude-mpm"
|
|
70
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
71
|
+
self.db_path = config_dir / "agent_sync.db"
|
|
72
|
+
|
|
73
|
+
# Initialize database
|
|
74
|
+
self._initialize_database()
|
|
75
|
+
|
|
76
|
+
@contextmanager
|
|
77
|
+
def _get_connection(self):
|
|
78
|
+
"""Context manager for database connections.
|
|
79
|
+
|
|
80
|
+
Yields:
|
|
81
|
+
sqlite3.Connection with foreign keys enabled and row factory
|
|
82
|
+
|
|
83
|
+
Error Handling:
|
|
84
|
+
- Exception during transaction: Rolls back automatically
|
|
85
|
+
- Connection errors: Propagates to caller
|
|
86
|
+
- Cleanup: Always closes connection
|
|
87
|
+
"""
|
|
88
|
+
conn = sqlite3.connect(str(self.db_path))
|
|
89
|
+
conn.row_factory = sqlite3.Row # Enable dict-like access
|
|
90
|
+
conn.execute("PRAGMA foreign_keys = ON") # Enable FK constraints
|
|
91
|
+
try:
|
|
92
|
+
yield conn
|
|
93
|
+
conn.commit()
|
|
94
|
+
except Exception:
|
|
95
|
+
conn.rollback()
|
|
96
|
+
raise
|
|
97
|
+
finally:
|
|
98
|
+
conn.close()
|
|
99
|
+
|
|
100
|
+
def _initialize_database(self):
|
|
101
|
+
"""Initialize database schema if not exists.
|
|
102
|
+
|
|
103
|
+
Creates all tables, indexes, and metadata on first run.
|
|
104
|
+
Verifies schema version on subsequent runs.
|
|
105
|
+
"""
|
|
106
|
+
with self._get_connection() as conn:
|
|
107
|
+
# Check if database exists and has schema
|
|
108
|
+
cursor = conn.execute(
|
|
109
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name='sources'"
|
|
110
|
+
)
|
|
111
|
+
if cursor.fetchone() is None:
|
|
112
|
+
# Database is new, create schema
|
|
113
|
+
self._create_schema(conn)
|
|
114
|
+
logger.info(f"Initialized sync state database: {self.db_path}")
|
|
115
|
+
else:
|
|
116
|
+
# Verify schema version
|
|
117
|
+
version = self._get_schema_version(conn)
|
|
118
|
+
if version != self.SCHEMA_VERSION:
|
|
119
|
+
logger.warning(
|
|
120
|
+
f"Schema version mismatch: expected {self.SCHEMA_VERSION}, found {version}"
|
|
121
|
+
)
|
|
122
|
+
# TODO: Implement migration in future ticket
|
|
123
|
+
|
|
124
|
+
def _create_schema(self, conn: sqlite3.Connection):
|
|
125
|
+
"""Create database schema with all tables and indexes.
|
|
126
|
+
|
|
127
|
+
Schema Design:
|
|
128
|
+
- sources: Track Git repositories or file sources
|
|
129
|
+
- agent_files: Track individual files and content hashes
|
|
130
|
+
- sync_history: Audit trail of all sync operations
|
|
131
|
+
- schema_metadata: Schema versioning for migrations
|
|
132
|
+
"""
|
|
133
|
+
conn.executescript(
|
|
134
|
+
"""
|
|
135
|
+
-- Sources table: Track Git repositories or file sources
|
|
136
|
+
CREATE TABLE sources (
|
|
137
|
+
id TEXT PRIMARY KEY, -- Source identifier (e.g., "github-remote", "local-project")
|
|
138
|
+
url TEXT NOT NULL, -- Source URL or file path
|
|
139
|
+
last_sha TEXT, -- Last synced commit SHA (Git sources only)
|
|
140
|
+
last_sync_time TEXT, -- ISO 8601 timestamp of last sync
|
|
141
|
+
etag TEXT, -- HTTP ETag for GitHub raw URLs
|
|
142
|
+
enabled INTEGER DEFAULT 1, -- 0=disabled, 1=enabled
|
|
143
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
144
|
+
updated_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
-- Agent files table: Track individual files and content hashes
|
|
148
|
+
CREATE TABLE agent_files (
|
|
149
|
+
source_id TEXT NOT NULL, -- FK to sources.id
|
|
150
|
+
file_path TEXT NOT NULL, -- Relative path (e.g., "research.md")
|
|
151
|
+
content_sha TEXT NOT NULL, -- SHA-256 hash of file content
|
|
152
|
+
local_path TEXT, -- Absolute path to cached file
|
|
153
|
+
synced_at TEXT NOT NULL, -- ISO 8601 timestamp when file was synced
|
|
154
|
+
file_size INTEGER, -- File size in bytes
|
|
155
|
+
PRIMARY KEY (source_id, file_path),
|
|
156
|
+
FOREIGN KEY (source_id) REFERENCES sources(id) ON DELETE CASCADE
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
-- Sync history table: Audit trail of all sync operations
|
|
160
|
+
CREATE TABLE sync_history (
|
|
161
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
162
|
+
source_id TEXT NOT NULL, -- FK to sources.id
|
|
163
|
+
sync_time TEXT NOT NULL, -- ISO 8601 timestamp
|
|
164
|
+
status TEXT NOT NULL, -- 'success', 'partial', 'error'
|
|
165
|
+
files_synced INTEGER DEFAULT 0, -- Number of files downloaded
|
|
166
|
+
files_cached INTEGER DEFAULT 0, -- Number of cache hits
|
|
167
|
+
files_failed INTEGER DEFAULT 0, -- Number of failed downloads
|
|
168
|
+
error_message TEXT, -- Error details if status='error'
|
|
169
|
+
duration_ms INTEGER, -- Sync duration in milliseconds
|
|
170
|
+
FOREIGN KEY (source_id) REFERENCES sources(id) ON DELETE CASCADE
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
-- Performance indexes
|
|
174
|
+
CREATE INDEX idx_agent_files_source ON agent_files(source_id);
|
|
175
|
+
CREATE INDEX idx_agent_files_path ON agent_files(file_path);
|
|
176
|
+
CREATE INDEX idx_sync_history_source_time ON sync_history(source_id, sync_time DESC);
|
|
177
|
+
CREATE INDEX idx_sync_history_status ON sync_history(status);
|
|
178
|
+
|
|
179
|
+
-- Metadata table for schema versioning
|
|
180
|
+
CREATE TABLE schema_metadata (
|
|
181
|
+
key TEXT PRIMARY KEY,
|
|
182
|
+
value TEXT NOT NULL
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
INSERT INTO schema_metadata (key, value) VALUES ('version', '1');
|
|
186
|
+
INSERT INTO schema_metadata (key, value) VALUES ('created_at', datetime('now'));
|
|
187
|
+
"""
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def _get_schema_version(self, conn: sqlite3.Connection) -> int:
|
|
191
|
+
"""Get current schema version.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
conn: Database connection
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Schema version number (0 if schema_metadata table doesn't exist)
|
|
198
|
+
"""
|
|
199
|
+
try:
|
|
200
|
+
cursor = conn.execute(
|
|
201
|
+
"SELECT value FROM schema_metadata WHERE key = 'version'"
|
|
202
|
+
)
|
|
203
|
+
row = cursor.fetchone()
|
|
204
|
+
return int(row[0]) if row else 0
|
|
205
|
+
except sqlite3.OperationalError:
|
|
206
|
+
return 0
|
|
207
|
+
|
|
208
|
+
# ==============================================================================
|
|
209
|
+
# SOURCE MANAGEMENT
|
|
210
|
+
# ==============================================================================
|
|
211
|
+
|
|
212
|
+
def register_source(self, source_id: str, url: str, enabled: bool = True) -> None:
|
|
213
|
+
"""Register or update a sync source.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
source_id: Unique source identifier (e.g., "github-remote")
|
|
217
|
+
url: Source URL or file path
|
|
218
|
+
enabled: Whether source is enabled for sync
|
|
219
|
+
|
|
220
|
+
Example:
|
|
221
|
+
sync_state.register_source(
|
|
222
|
+
source_id="github-remote",
|
|
223
|
+
url="https://raw.githubusercontent.com/bobmatnyc/claude-mpm-agents/main",
|
|
224
|
+
enabled=True
|
|
225
|
+
)
|
|
226
|
+
"""
|
|
227
|
+
with self._get_connection() as conn:
|
|
228
|
+
conn.execute(
|
|
229
|
+
"""
|
|
230
|
+
INSERT INTO sources (id, url, enabled, updated_at)
|
|
231
|
+
VALUES (?, ?, ?, ?)
|
|
232
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
233
|
+
url = excluded.url,
|
|
234
|
+
enabled = excluded.enabled,
|
|
235
|
+
updated_at = excluded.updated_at
|
|
236
|
+
""",
|
|
237
|
+
(source_id, url, int(enabled), datetime.now(timezone.utc).isoformat()),
|
|
238
|
+
)
|
|
239
|
+
logger.debug(f"Registered source: {source_id} -> {url}")
|
|
240
|
+
|
|
241
|
+
def update_source_sync_metadata(
|
|
242
|
+
self,
|
|
243
|
+
source_id: str,
|
|
244
|
+
last_sha: Optional[str] = None,
|
|
245
|
+
etag: Optional[str] = None,
|
|
246
|
+
) -> None:
|
|
247
|
+
"""Update source sync metadata (commit SHA, ETag).
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
source_id: Source identifier
|
|
251
|
+
last_sha: Latest commit SHA (Git sources)
|
|
252
|
+
etag: HTTP ETag (GitHub raw URLs)
|
|
253
|
+
|
|
254
|
+
Example:
|
|
255
|
+
sync_state.update_source_sync_metadata(
|
|
256
|
+
source_id="github-remote",
|
|
257
|
+
last_sha="abc123def456",
|
|
258
|
+
etag='"W/abc123"'
|
|
259
|
+
)
|
|
260
|
+
"""
|
|
261
|
+
with self._get_connection() as conn:
|
|
262
|
+
conn.execute(
|
|
263
|
+
"""
|
|
264
|
+
UPDATE sources
|
|
265
|
+
SET last_sha = ?, etag = ?, last_sync_time = ?, updated_at = ?
|
|
266
|
+
WHERE id = ?
|
|
267
|
+
""",
|
|
268
|
+
(
|
|
269
|
+
last_sha,
|
|
270
|
+
etag,
|
|
271
|
+
datetime.now(timezone.utc).isoformat(),
|
|
272
|
+
datetime.now(timezone.utc).isoformat(),
|
|
273
|
+
source_id,
|
|
274
|
+
),
|
|
275
|
+
)
|
|
276
|
+
logger.debug(f"Updated source metadata: {source_id}")
|
|
277
|
+
|
|
278
|
+
def get_source_info(self, source_id: str) -> Optional[Dict[str, Any]]:
|
|
279
|
+
"""Get source metadata.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
source_id: Source identifier
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
Source metadata dict or None if not found
|
|
286
|
+
|
|
287
|
+
Example:
|
|
288
|
+
>>> info = sync_state.get_source_info("github-remote")
|
|
289
|
+
>>> print(info["url"])
|
|
290
|
+
https://raw.githubusercontent.com/...
|
|
291
|
+
"""
|
|
292
|
+
with self._get_connection() as conn:
|
|
293
|
+
cursor = conn.execute("SELECT * FROM sources WHERE id = ?", (source_id,))
|
|
294
|
+
row = cursor.fetchone()
|
|
295
|
+
return dict(row) if row else None
|
|
296
|
+
|
|
297
|
+
def get_all_sources(self, enabled_only: bool = False) -> List[Dict[str, Any]]:
|
|
298
|
+
"""Get all registered sources.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
enabled_only: Only return enabled sources
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
List of source metadata dicts
|
|
305
|
+
"""
|
|
306
|
+
with self._get_connection() as conn:
|
|
307
|
+
query = "SELECT * FROM sources"
|
|
308
|
+
if enabled_only:
|
|
309
|
+
query += " WHERE enabled = 1"
|
|
310
|
+
cursor = conn.execute(query)
|
|
311
|
+
return [dict(row) for row in cursor.fetchall()]
|
|
312
|
+
|
|
313
|
+
# ==============================================================================
|
|
314
|
+
# FILE TRACKING
|
|
315
|
+
# ==============================================================================
|
|
316
|
+
|
|
317
|
+
def track_file(
|
|
318
|
+
self,
|
|
319
|
+
source_id: str,
|
|
320
|
+
file_path: str,
|
|
321
|
+
content_sha: str,
|
|
322
|
+
local_path: Optional[str] = None,
|
|
323
|
+
file_size: Optional[int] = None,
|
|
324
|
+
) -> None:
|
|
325
|
+
"""Track agent file with content hash.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
source_id: Source identifier
|
|
329
|
+
file_path: Relative file path (e.g., "research.md")
|
|
330
|
+
content_sha: SHA-256 hash of file content
|
|
331
|
+
local_path: Absolute path to cached file
|
|
332
|
+
file_size: File size in bytes
|
|
333
|
+
|
|
334
|
+
Example:
|
|
335
|
+
sync_state.track_file(
|
|
336
|
+
source_id="github-remote",
|
|
337
|
+
file_path="research.md",
|
|
338
|
+
content_sha="abc123def456...",
|
|
339
|
+
local_path="/home/user/.claude-mpm/cache/research.md",
|
|
340
|
+
file_size=2048
|
|
341
|
+
)
|
|
342
|
+
"""
|
|
343
|
+
with self._get_connection() as conn:
|
|
344
|
+
conn.execute(
|
|
345
|
+
"""
|
|
346
|
+
INSERT INTO agent_files (source_id, file_path, content_sha, local_path, synced_at, file_size)
|
|
347
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
348
|
+
ON CONFLICT(source_id, file_path) DO UPDATE SET
|
|
349
|
+
content_sha = excluded.content_sha,
|
|
350
|
+
local_path = excluded.local_path,
|
|
351
|
+
synced_at = excluded.synced_at,
|
|
352
|
+
file_size = excluded.file_size
|
|
353
|
+
""",
|
|
354
|
+
(
|
|
355
|
+
source_id,
|
|
356
|
+
file_path,
|
|
357
|
+
content_sha,
|
|
358
|
+
local_path,
|
|
359
|
+
datetime.now(timezone.utc).isoformat(),
|
|
360
|
+
file_size,
|
|
361
|
+
),
|
|
362
|
+
)
|
|
363
|
+
logger.debug(f"Tracked file: {source_id}/{file_path} -> {content_sha[:8]}...")
|
|
364
|
+
|
|
365
|
+
def get_file_hash(self, source_id: str, file_path: str) -> Optional[str]:
|
|
366
|
+
"""Get stored content hash for file.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
source_id: Source identifier
|
|
370
|
+
file_path: Relative file path
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
SHA-256 hash or None if not tracked
|
|
374
|
+
"""
|
|
375
|
+
with self._get_connection() as conn:
|
|
376
|
+
cursor = conn.execute(
|
|
377
|
+
"SELECT content_sha FROM agent_files WHERE source_id = ? AND file_path = ?",
|
|
378
|
+
(source_id, file_path),
|
|
379
|
+
)
|
|
380
|
+
row = cursor.fetchone()
|
|
381
|
+
return row["content_sha"] if row else None
|
|
382
|
+
|
|
383
|
+
def has_file_changed(
|
|
384
|
+
self, source_id: str, file_path: str, current_sha: str
|
|
385
|
+
) -> bool:
|
|
386
|
+
"""Check if file content has changed.
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
source_id: Source identifier
|
|
390
|
+
file_path: Relative file path
|
|
391
|
+
current_sha: Current SHA-256 hash
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
True if changed or not tracked, False if unchanged
|
|
395
|
+
|
|
396
|
+
Example:
|
|
397
|
+
>>> changed = sync_state.has_file_changed(
|
|
398
|
+
... "github-remote", "research.md", "abc123..."
|
|
399
|
+
... )
|
|
400
|
+
>>> if changed:
|
|
401
|
+
... print("File needs update")
|
|
402
|
+
"""
|
|
403
|
+
stored_sha = self.get_file_hash(source_id, file_path)
|
|
404
|
+
if stored_sha is None:
|
|
405
|
+
return True # Not tracked = changed
|
|
406
|
+
return stored_sha != current_sha
|
|
407
|
+
|
|
408
|
+
# ==============================================================================
|
|
409
|
+
# SYNC HISTORY
|
|
410
|
+
# ==============================================================================
|
|
411
|
+
|
|
412
|
+
def record_sync_result(
|
|
413
|
+
self,
|
|
414
|
+
source_id: str,
|
|
415
|
+
status: str,
|
|
416
|
+
files_synced: int = 0,
|
|
417
|
+
files_cached: int = 0,
|
|
418
|
+
files_failed: int = 0,
|
|
419
|
+
error_message: Optional[str] = None,
|
|
420
|
+
duration_ms: Optional[int] = None,
|
|
421
|
+
) -> int:
|
|
422
|
+
"""Record sync operation result.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
source_id: Source identifier
|
|
426
|
+
status: 'success', 'partial', or 'error'
|
|
427
|
+
files_synced: Number of files downloaded
|
|
428
|
+
files_cached: Number of cache hits
|
|
429
|
+
files_failed: Number of failed downloads
|
|
430
|
+
error_message: Error details if status='error'
|
|
431
|
+
duration_ms: Sync duration in milliseconds
|
|
432
|
+
|
|
433
|
+
Returns:
|
|
434
|
+
Sync history record ID
|
|
435
|
+
|
|
436
|
+
Example:
|
|
437
|
+
record_id = sync_state.record_sync_result(
|
|
438
|
+
source_id="github-remote",
|
|
439
|
+
status="success",
|
|
440
|
+
files_synced=5,
|
|
441
|
+
files_cached=3,
|
|
442
|
+
duration_ms=1500
|
|
443
|
+
)
|
|
444
|
+
"""
|
|
445
|
+
with self._get_connection() as conn:
|
|
446
|
+
cursor = conn.execute(
|
|
447
|
+
"""
|
|
448
|
+
INSERT INTO sync_history (
|
|
449
|
+
source_id, sync_time, status, files_synced, files_cached,
|
|
450
|
+
files_failed, error_message, duration_ms
|
|
451
|
+
)
|
|
452
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
453
|
+
""",
|
|
454
|
+
(
|
|
455
|
+
source_id,
|
|
456
|
+
datetime.now(timezone.utc).isoformat(),
|
|
457
|
+
status,
|
|
458
|
+
files_synced,
|
|
459
|
+
files_cached,
|
|
460
|
+
files_failed,
|
|
461
|
+
error_message,
|
|
462
|
+
duration_ms,
|
|
463
|
+
),
|
|
464
|
+
)
|
|
465
|
+
return cursor.lastrowid
|
|
466
|
+
|
|
467
|
+
def get_sync_history(self, source_id: str, limit: int = 10) -> List[Dict[str, Any]]:
|
|
468
|
+
"""Get recent sync history for source.
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
source_id: Source identifier
|
|
472
|
+
limit: Maximum number of records
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
List of sync history records (most recent first)
|
|
476
|
+
|
|
477
|
+
Example:
|
|
478
|
+
>>> history = sync_state.get_sync_history("github-remote", limit=5)
|
|
479
|
+
>>> for record in history:
|
|
480
|
+
... print(f"{record['sync_time']}: {record['status']}")
|
|
481
|
+
"""
|
|
482
|
+
with self._get_connection() as conn:
|
|
483
|
+
cursor = conn.execute(
|
|
484
|
+
"""
|
|
485
|
+
SELECT * FROM sync_history
|
|
486
|
+
WHERE source_id = ?
|
|
487
|
+
ORDER BY sync_time DESC
|
|
488
|
+
LIMIT ?
|
|
489
|
+
""",
|
|
490
|
+
(source_id, limit),
|
|
491
|
+
)
|
|
492
|
+
return [dict(row) for row in cursor.fetchall()]
|
|
493
|
+
|
|
494
|
+
def cleanup_old_history(self, days: int = 30) -> int:
|
|
495
|
+
"""Remove sync history older than specified days.
|
|
496
|
+
|
|
497
|
+
Args:
|
|
498
|
+
days: Number of days to retain
|
|
499
|
+
|
|
500
|
+
Returns:
|
|
501
|
+
Number of records deleted
|
|
502
|
+
|
|
503
|
+
Example:
|
|
504
|
+
deleted = sync_state.cleanup_old_history(days=30)
|
|
505
|
+
print(f"Cleaned up {deleted} old sync records")
|
|
506
|
+
"""
|
|
507
|
+
cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()
|
|
508
|
+
|
|
509
|
+
with self._get_connection() as conn:
|
|
510
|
+
cursor = conn.execute(
|
|
511
|
+
"DELETE FROM sync_history WHERE sync_time < ?", (cutoff,)
|
|
512
|
+
)
|
|
513
|
+
deleted = cursor.rowcount
|
|
514
|
+
|
|
515
|
+
logger.info(f"Cleaned up {deleted} sync history records older than {days} days")
|
|
516
|
+
return deleted
|