claude-mpm 4.7.4__py3-none-any.whl → 4.18.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
- claude_mpm/agents/BASE_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +106 -1
- claude_mpm/agents/OUTPUT_STYLE.md +329 -11
- claude_mpm/agents/PM_INSTRUCTIONS.md +397 -459
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/agent-manager.json +4 -1
- claude_mpm/agents/templates/agentic-coder-optimizer.json +13 -3
- claude_mpm/agents/templates/api_qa.json +11 -2
- claude_mpm/agents/templates/circuit_breakers.md +638 -0
- claude_mpm/agents/templates/clerk-ops.json +12 -2
- claude_mpm/agents/templates/code_analyzer.json +8 -2
- claude_mpm/agents/templates/content-agent.json +358 -0
- claude_mpm/agents/templates/dart_engineer.json +15 -2
- claude_mpm/agents/templates/data_engineer.json +15 -2
- claude_mpm/agents/templates/documentation.json +10 -2
- claude_mpm/agents/templates/engineer.json +21 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +12 -2
- claude_mpm/agents/templates/git_file_tracking.md +584 -0
- claude_mpm/agents/templates/golang_engineer.json +270 -0
- claude_mpm/agents/templates/imagemagick.json +4 -1
- claude_mpm/agents/templates/java_engineer.json +346 -0
- claude_mpm/agents/templates/local_ops_agent.json +1227 -6
- claude_mpm/agents/templates/memory_manager.json +4 -1
- claude_mpm/agents/templates/nextjs_engineer.json +141 -133
- claude_mpm/agents/templates/ops.json +12 -2
- claude_mpm/agents/templates/php-engineer.json +270 -174
- claude_mpm/agents/templates/pm_examples.md +474 -0
- claude_mpm/agents/templates/pm_red_flags.md +240 -0
- claude_mpm/agents/templates/product_owner.json +338 -0
- claude_mpm/agents/templates/project_organizer.json +14 -4
- claude_mpm/agents/templates/prompt-engineer.json +13 -2
- claude_mpm/agents/templates/python_engineer.json +174 -81
- claude_mpm/agents/templates/qa.json +11 -2
- claude_mpm/agents/templates/react_engineer.json +16 -3
- claude_mpm/agents/templates/refactoring_engineer.json +12 -2
- claude_mpm/agents/templates/research.json +34 -21
- claude_mpm/agents/templates/response_format.md +583 -0
- claude_mpm/agents/templates/ruby-engineer.json +129 -192
- claude_mpm/agents/templates/rust_engineer.json +270 -0
- claude_mpm/agents/templates/security.json +10 -2
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +10 -2
- claude_mpm/agents/templates/typescript_engineer.json +116 -125
- claude_mpm/agents/templates/validation_templates.md +312 -0
- claude_mpm/agents/templates/vercel_ops_agent.json +12 -2
- claude_mpm/agents/templates/version_control.json +12 -2
- claude_mpm/agents/templates/web_qa.json +11 -2
- claude_mpm/agents/templates/web_ui.json +15 -2
- claude_mpm/cli/__init__.py +34 -614
- claude_mpm/cli/commands/agent_manager.py +25 -12
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +235 -148
- claude_mpm/cli/commands/agents_detect.py +380 -0
- claude_mpm/cli/commands/agents_recommend.py +309 -0
- claude_mpm/cli/commands/aggregate.py +7 -3
- claude_mpm/cli/commands/analyze.py +9 -4
- claude_mpm/cli/commands/analyze_code.py +7 -2
- claude_mpm/cli/commands/auto_configure.py +570 -0
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +419 -1571
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +167 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/local_deploy.py +537 -0
- claude_mpm/cli/commands/memory.py +54 -20
- claude_mpm/cli/commands/mpm_init.py +585 -196
- claude_mpm/cli/commands/mpm_init_handler.py +37 -3
- claude_mpm/cli/commands/search.py +170 -4
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/executor.py +202 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +3 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parsers/__init__.py +7 -1
- claude_mpm/cli/parsers/agents_parser.py +9 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
- claude_mpm/cli/parsers/base_parser.py +110 -3
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +65 -5
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +481 -0
- claude_mpm/cli/utils.py +52 -1
- claude_mpm/commands/mpm-agents-detect.md +168 -0
- claude_mpm/commands/mpm-agents-recommend.md +214 -0
- claude_mpm/commands/mpm-agents.md +75 -1
- claude_mpm/commands/mpm-auto-configure.md +217 -0
- claude_mpm/commands/mpm-help.md +163 -0
- claude_mpm/commands/mpm-init.md +148 -3
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/base_service.py +13 -12
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/instruction_reinforcement_hook.py +2 -1
- claude_mpm/core/interactive_session.py +9 -3
- claude_mpm/core/log_manager.py +2 -0
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/oneshot_session.py +8 -4
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/service_registry.py +5 -1
- claude_mpm/core/types.py +2 -9
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/dashboard/static/js/dashboard.js +0 -14
- claude_mpm/dashboard/templates/index.html +3 -41
- claude_mpm/hooks/__init__.py +20 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +4 -2
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +23 -2
- claude_mpm/hooks/failure_learning/__init__.py +60 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +37 -12
- claude_mpm/hooks/kuzu_response_hook.py +183 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/__init__.py +18 -5
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +568 -0
- claude_mpm/services/agents/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/__init__.py +33 -1
- claude_mpm/services/core/interfaces/__init__.py +90 -3
- claude_mpm/services/core/interfaces/agent.py +184 -0
- claude_mpm/services/core/interfaces/health.py +172 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/memory_manager.py +11 -24
- claude_mpm/services/core/models/__init__.py +79 -0
- claude_mpm/services/core/models/agent_config.py +381 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +235 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +23 -7
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
- claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
- claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
- claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
- claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +38 -33
- claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
- claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
- claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
- claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
- claude_mpm/services/diagnostics/models.py +19 -24
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
- claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +163 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +430 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +9 -4
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +18 -31
- claude_mpm/services/mcp_gateway/main.py +30 -0
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +206 -32
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +25 -5
- claude_mpm/services/mcp_service_verifier.py +1 -1
- claude_mpm/services/memory/failure_tracker.py +563 -0
- claude_mpm/services/memory_hook_service.py +165 -4
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +453 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/daemon_manager.py +3 -2
- claude_mpm/services/monitor/handlers/dashboard.py +2 -1
- claude_mpm/services/monitor/handlers/hooks.py +2 -1
- claude_mpm/services/monitor/management/lifecycle.py +3 -2
- claude_mpm/services/monitor/server.py +2 -1
- claude_mpm/services/project/__init__.py +23 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/toolchain_analyzer.py +581 -0
- claude_mpm/services/self_upgrade_service.py +342 -0
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/hook.py +13 -2
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/server/main.py +10 -8
- claude_mpm/services/subprocess_launcher_service.py +14 -5
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
- claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
- claude_mpm/services/unified/deployment_strategies/local.py +6 -5
- claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
- claude_mpm/services/unified/interfaces.py +3 -1
- claude_mpm/services/unified/unified_analyzer.py +14 -10
- claude_mpm/services/unified/unified_config.py +2 -1
- claude_mpm/services/unified/unified_deployment.py +9 -4
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/storage/state_storage.py +15 -15
- claude_mpm/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +40 -20
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/robust_installer.py +73 -19
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +129 -12
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +295 -193
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- claude_mpm/dashboard/static/index-hub-backup.html +0 -713
- claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
skill_id: xlsx
|
|
3
|
+
skill_version: 0.1.0
|
|
4
|
+
description: Working with Excel files programmatically.
|
|
5
|
+
updated_at: 2025-10-30T17:00:00Z
|
|
6
|
+
tags: [excel, xlsx, spreadsheet, data]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Excel/XLSX Manipulation
|
|
10
|
+
|
|
11
|
+
Working with Excel files programmatically.
|
|
12
|
+
|
|
13
|
+
## Python (openpyxl)
|
|
14
|
+
|
|
15
|
+
### Reading Excel
|
|
16
|
+
```python
|
|
17
|
+
from openpyxl import load_workbook
|
|
18
|
+
|
|
19
|
+
wb = load_workbook('data.xlsx')
|
|
20
|
+
ws = wb.active # Get active sheet
|
|
21
|
+
|
|
22
|
+
# Read cell
|
|
23
|
+
value = ws['A1'].value
|
|
24
|
+
|
|
25
|
+
# Iterate rows
|
|
26
|
+
for row in ws.iter_rows(min_row=2, values_only=True):
|
|
27
|
+
print(row)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Writing Excel
|
|
31
|
+
```python
|
|
32
|
+
from openpyxl import Workbook
|
|
33
|
+
|
|
34
|
+
wb = Workbook()
|
|
35
|
+
ws = wb.active
|
|
36
|
+
ws.title = "Data"
|
|
37
|
+
|
|
38
|
+
# Write data
|
|
39
|
+
ws['A1'] = 'Name'
|
|
40
|
+
ws['B1'] = 'Age'
|
|
41
|
+
ws.append(['John', 30])
|
|
42
|
+
ws.append(['Jane', 25])
|
|
43
|
+
|
|
44
|
+
wb.save('output.xlsx')
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Formatting
|
|
48
|
+
```python
|
|
49
|
+
from openpyxl.styles import Font, PatternFill
|
|
50
|
+
|
|
51
|
+
# Bold header
|
|
52
|
+
ws['A1'].font = Font(bold=True)
|
|
53
|
+
|
|
54
|
+
# Background color
|
|
55
|
+
ws['A1'].fill = PatternFill(start_color="FFFF00", fill_type="solid")
|
|
56
|
+
|
|
57
|
+
# Number format
|
|
58
|
+
ws['B2'].number_format = '0.00' # Two decimals
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Formulas
|
|
62
|
+
```python
|
|
63
|
+
# Add formula
|
|
64
|
+
ws['C2'] = '=A2+B2'
|
|
65
|
+
|
|
66
|
+
# Sum column
|
|
67
|
+
ws['D10'] = '=SUM(D2:D9)'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Python (pandas)
|
|
71
|
+
|
|
72
|
+
### Reading Excel
|
|
73
|
+
```python
|
|
74
|
+
import pandas as pd
|
|
75
|
+
|
|
76
|
+
# Read sheet
|
|
77
|
+
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
|
|
78
|
+
|
|
79
|
+
# Read multiple sheets
|
|
80
|
+
dfs = pd.read_excel('data.xlsx', sheet_name=None)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Writing Excel
|
|
84
|
+
```python
|
|
85
|
+
# Write DataFrame
|
|
86
|
+
df.to_excel('output.xlsx', index=False)
|
|
87
|
+
|
|
88
|
+
# Multiple sheets
|
|
89
|
+
with pd.ExcelWriter('output.xlsx') as writer:
|
|
90
|
+
df1.to_excel(writer, sheet_name='Sheet1')
|
|
91
|
+
df2.to_excel(writer, sheet_name='Sheet2')
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Data Transformation
|
|
95
|
+
```python
|
|
96
|
+
# Filter
|
|
97
|
+
filtered = df[df['Age'] > 25]
|
|
98
|
+
|
|
99
|
+
# Group by
|
|
100
|
+
grouped = df.groupby('Department')['Salary'].mean()
|
|
101
|
+
|
|
102
|
+
# Pivot
|
|
103
|
+
pivot = df.pivot_table(values='Sales', index='Region', columns='Product')
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## JavaScript (xlsx)
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
import XLSX from 'xlsx';
|
|
110
|
+
|
|
111
|
+
// Read file
|
|
112
|
+
const workbook = XLSX.readFile('data.xlsx');
|
|
113
|
+
const sheetName = workbook.SheetNames[0];
|
|
114
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
115
|
+
|
|
116
|
+
// Convert to JSON
|
|
117
|
+
const data = XLSX.utils.sheet_to_json(worksheet);
|
|
118
|
+
|
|
119
|
+
// Write file
|
|
120
|
+
const newWorksheet = XLSX.utils.json_to_sheet(data);
|
|
121
|
+
const newWorkbook = XLSX.utils.book_new();
|
|
122
|
+
XLSX.utils.book_append_sheet(newWorkbook, newWorksheet, 'Data');
|
|
123
|
+
XLSX.writeFile(newWorkbook, 'output.xlsx');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Common Operations
|
|
127
|
+
|
|
128
|
+
### CSV to Excel
|
|
129
|
+
```python
|
|
130
|
+
import pandas as pd
|
|
131
|
+
|
|
132
|
+
df = pd.read_csv('data.csv')
|
|
133
|
+
df.to_excel('data.xlsx', index=False)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Excel to CSV
|
|
137
|
+
```python
|
|
138
|
+
df = pd.read_excel('data.xlsx')
|
|
139
|
+
df.to_csv('data.csv', index=False)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Merging Excel Files
|
|
143
|
+
```python
|
|
144
|
+
dfs = []
|
|
145
|
+
for file in ['file1.xlsx', 'file2.xlsx', 'file3.xlsx']:
|
|
146
|
+
df = pd.read_excel(file)
|
|
147
|
+
dfs.append(df)
|
|
148
|
+
|
|
149
|
+
combined = pd.concat(dfs, ignore_index=True)
|
|
150
|
+
combined.to_excel('merged.xlsx', index=False)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Remember
|
|
154
|
+
- Close workbooks after use
|
|
155
|
+
- Handle large files in chunks
|
|
156
|
+
- Validate data before writing
|
|
157
|
+
- Use pandas for data analysis, openpyxl for formatting
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"""Skills registry - manages bundled and discovered skills."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
import yaml
|
|
9
|
+
|
|
10
|
+
from claude_mpm.core.logging_utils import get_logger
|
|
11
|
+
|
|
12
|
+
logger = get_logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class Skill:
|
|
17
|
+
"""Represents a skill that can be used by agents."""
|
|
18
|
+
|
|
19
|
+
name: str
|
|
20
|
+
path: Path
|
|
21
|
+
content: str
|
|
22
|
+
source: str # 'bundled', 'user', or 'project'
|
|
23
|
+
|
|
24
|
+
# Version tracking fields
|
|
25
|
+
version: str = "0.1.0"
|
|
26
|
+
skill_id: str = "" # defaults to name if not provided
|
|
27
|
+
|
|
28
|
+
# Existing fields
|
|
29
|
+
description: str = ""
|
|
30
|
+
agent_types: List[str] = None # Which agent types can use this skill
|
|
31
|
+
|
|
32
|
+
# Optional metadata
|
|
33
|
+
updated_at: Optional[str] = None
|
|
34
|
+
tags: List[str] = None
|
|
35
|
+
|
|
36
|
+
def __post_init__(self):
|
|
37
|
+
"""Initialize default values if not provided."""
|
|
38
|
+
if self.agent_types is None:
|
|
39
|
+
self.agent_types = []
|
|
40
|
+
if self.tags is None:
|
|
41
|
+
self.tags = []
|
|
42
|
+
if not self.skill_id:
|
|
43
|
+
self.skill_id = self.name
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class SkillsRegistry:
|
|
47
|
+
"""Registry for managing skills across all tiers."""
|
|
48
|
+
|
|
49
|
+
def __init__(self):
|
|
50
|
+
"""Initialize the skills registry."""
|
|
51
|
+
self.skills: Dict[str, Skill] = {}
|
|
52
|
+
self._load_bundled_skills()
|
|
53
|
+
self._load_user_skills()
|
|
54
|
+
self._load_project_skills()
|
|
55
|
+
|
|
56
|
+
def _parse_skill_frontmatter(self, content: str) -> Dict[str, Any]:
|
|
57
|
+
"""Parse YAML frontmatter from skill markdown file.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Dict with frontmatter fields or empty dict if no frontmatter
|
|
61
|
+
"""
|
|
62
|
+
# Check for YAML frontmatter
|
|
63
|
+
if not content.startswith("---"):
|
|
64
|
+
return {}
|
|
65
|
+
|
|
66
|
+
# Extract frontmatter (match: ---\n...yaml...\n---\nrest)
|
|
67
|
+
match = re.match(r"^---\n(.*?)\n---\n(.*)$", content, re.DOTALL)
|
|
68
|
+
if not match:
|
|
69
|
+
return {}
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
frontmatter = yaml.safe_load(match.group(1))
|
|
73
|
+
return frontmatter or {}
|
|
74
|
+
except yaml.YAMLError as e:
|
|
75
|
+
logger.warning(f"Failed to parse skill frontmatter: {e}")
|
|
76
|
+
return {}
|
|
77
|
+
|
|
78
|
+
def _load_bundled_skills(self):
|
|
79
|
+
"""Load skills bundled with MPM."""
|
|
80
|
+
bundled_dir = Path(__file__).parent / "bundled"
|
|
81
|
+
if not bundled_dir.exists():
|
|
82
|
+
logger.warning(f"Bundled skills directory not found: {bundled_dir}")
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
skill_count = 0
|
|
86
|
+
for skill_file in bundled_dir.glob("*.md"):
|
|
87
|
+
try:
|
|
88
|
+
skill_name = skill_file.stem
|
|
89
|
+
content = skill_file.read_text(encoding="utf-8")
|
|
90
|
+
|
|
91
|
+
# Parse frontmatter
|
|
92
|
+
frontmatter = self._parse_skill_frontmatter(content)
|
|
93
|
+
|
|
94
|
+
# Extract version fields from frontmatter
|
|
95
|
+
version = frontmatter.get("skill_version", "0.1.0")
|
|
96
|
+
skill_id = frontmatter.get("skill_id", skill_name)
|
|
97
|
+
updated_at = frontmatter.get("updated_at")
|
|
98
|
+
tags = frontmatter.get("tags", [])
|
|
99
|
+
|
|
100
|
+
# Extract description (from frontmatter or fallback to content parsing)
|
|
101
|
+
description = frontmatter.get("description", "")
|
|
102
|
+
if not description:
|
|
103
|
+
description = self._extract_description(content)
|
|
104
|
+
|
|
105
|
+
self.skills[skill_name] = Skill(
|
|
106
|
+
name=skill_name,
|
|
107
|
+
path=skill_file,
|
|
108
|
+
content=content,
|
|
109
|
+
source="bundled",
|
|
110
|
+
version=version,
|
|
111
|
+
skill_id=skill_id,
|
|
112
|
+
description=description,
|
|
113
|
+
updated_at=updated_at,
|
|
114
|
+
tags=tags,
|
|
115
|
+
)
|
|
116
|
+
skill_count += 1
|
|
117
|
+
except Exception as e:
|
|
118
|
+
logger.error(f"Error loading bundled skill {skill_file}: {e}")
|
|
119
|
+
|
|
120
|
+
logger.debug(f"Loaded {skill_count} bundled skills")
|
|
121
|
+
|
|
122
|
+
def _load_user_skills(self):
|
|
123
|
+
"""Load user-installed skills from ~/.claude/skills/"""
|
|
124
|
+
user_skills_dir = Path.home() / ".claude" / "skills"
|
|
125
|
+
if not user_skills_dir.exists():
|
|
126
|
+
logger.debug("User skills directory not found, skipping")
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
skill_count = 0
|
|
130
|
+
for skill_file in user_skills_dir.glob("*.md"):
|
|
131
|
+
try:
|
|
132
|
+
skill_name = skill_file.stem
|
|
133
|
+
# User skills override bundled skills
|
|
134
|
+
content = skill_file.read_text(encoding="utf-8")
|
|
135
|
+
|
|
136
|
+
# Parse frontmatter
|
|
137
|
+
frontmatter = self._parse_skill_frontmatter(content)
|
|
138
|
+
|
|
139
|
+
# Extract version fields from frontmatter
|
|
140
|
+
version = frontmatter.get("skill_version", "0.1.0")
|
|
141
|
+
skill_id = frontmatter.get("skill_id", skill_name)
|
|
142
|
+
updated_at = frontmatter.get("updated_at")
|
|
143
|
+
tags = frontmatter.get("tags", [])
|
|
144
|
+
|
|
145
|
+
# Extract description (from frontmatter or fallback to content parsing)
|
|
146
|
+
description = frontmatter.get("description", "")
|
|
147
|
+
if not description:
|
|
148
|
+
description = self._extract_description(content)
|
|
149
|
+
|
|
150
|
+
self.skills[skill_name] = Skill(
|
|
151
|
+
name=skill_name,
|
|
152
|
+
path=skill_file,
|
|
153
|
+
content=content,
|
|
154
|
+
source="user",
|
|
155
|
+
version=version,
|
|
156
|
+
skill_id=skill_id,
|
|
157
|
+
description=description,
|
|
158
|
+
updated_at=updated_at,
|
|
159
|
+
tags=tags,
|
|
160
|
+
)
|
|
161
|
+
skill_count += 1
|
|
162
|
+
logger.debug(f"User skill '{skill_name}' overrides bundled version")
|
|
163
|
+
except Exception as e:
|
|
164
|
+
logger.error(f"Error loading user skill {skill_file}: {e}")
|
|
165
|
+
|
|
166
|
+
if skill_count > 0:
|
|
167
|
+
logger.debug(f"Loaded {skill_count} user skills")
|
|
168
|
+
|
|
169
|
+
def _load_project_skills(self):
|
|
170
|
+
"""Load project-specific skills from .claude/skills/"""
|
|
171
|
+
project_skills_dir = Path.cwd() / ".claude" / "skills"
|
|
172
|
+
if not project_skills_dir.exists():
|
|
173
|
+
logger.debug("Project skills directory not found, skipping")
|
|
174
|
+
return
|
|
175
|
+
|
|
176
|
+
skill_count = 0
|
|
177
|
+
for skill_file in project_skills_dir.glob("*.md"):
|
|
178
|
+
try:
|
|
179
|
+
skill_name = skill_file.stem
|
|
180
|
+
# Project skills override both user and bundled skills
|
|
181
|
+
content = skill_file.read_text(encoding="utf-8")
|
|
182
|
+
|
|
183
|
+
# Parse frontmatter
|
|
184
|
+
frontmatter = self._parse_skill_frontmatter(content)
|
|
185
|
+
|
|
186
|
+
# Extract version fields from frontmatter
|
|
187
|
+
version = frontmatter.get("skill_version", "0.1.0")
|
|
188
|
+
skill_id = frontmatter.get("skill_id", skill_name)
|
|
189
|
+
updated_at = frontmatter.get("updated_at")
|
|
190
|
+
tags = frontmatter.get("tags", [])
|
|
191
|
+
|
|
192
|
+
# Extract description (from frontmatter or fallback to content parsing)
|
|
193
|
+
description = frontmatter.get("description", "")
|
|
194
|
+
if not description:
|
|
195
|
+
description = self._extract_description(content)
|
|
196
|
+
|
|
197
|
+
self.skills[skill_name] = Skill(
|
|
198
|
+
name=skill_name,
|
|
199
|
+
path=skill_file,
|
|
200
|
+
content=content,
|
|
201
|
+
source="project",
|
|
202
|
+
version=version,
|
|
203
|
+
skill_id=skill_id,
|
|
204
|
+
description=description,
|
|
205
|
+
updated_at=updated_at,
|
|
206
|
+
tags=tags,
|
|
207
|
+
)
|
|
208
|
+
skill_count += 1
|
|
209
|
+
logger.debug(f"Project skill '{skill_name}' overrides other versions")
|
|
210
|
+
except Exception as e:
|
|
211
|
+
logger.error(f"Error loading project skill {skill_file}: {e}")
|
|
212
|
+
|
|
213
|
+
if skill_count > 0:
|
|
214
|
+
logger.debug(f"Loaded {skill_count} project skills")
|
|
215
|
+
|
|
216
|
+
def _extract_description(self, content: str) -> str:
|
|
217
|
+
"""Extract description from skill content (first paragraph or summary)."""
|
|
218
|
+
lines = content.strip().split("\n")
|
|
219
|
+
description_lines = []
|
|
220
|
+
|
|
221
|
+
# Skip title (first line starting with #)
|
|
222
|
+
start_idx = 0
|
|
223
|
+
if lines and lines[0].startswith("#"):
|
|
224
|
+
start_idx = 1
|
|
225
|
+
|
|
226
|
+
# Find first non-empty paragraph
|
|
227
|
+
for line in lines[start_idx:]:
|
|
228
|
+
line = line.strip()
|
|
229
|
+
if not line:
|
|
230
|
+
if description_lines:
|
|
231
|
+
break
|
|
232
|
+
continue
|
|
233
|
+
if line.startswith("#"):
|
|
234
|
+
break
|
|
235
|
+
description_lines.append(line)
|
|
236
|
+
|
|
237
|
+
return " ".join(description_lines)[:200] # Limit to 200 chars
|
|
238
|
+
|
|
239
|
+
def get_skill(self, name: str) -> Optional[Skill]:
|
|
240
|
+
"""Get a skill by name."""
|
|
241
|
+
return self.skills.get(name)
|
|
242
|
+
|
|
243
|
+
def list_skills(self, source: Optional[str] = None) -> List[Skill]:
|
|
244
|
+
"""List all skills, optionally filtered by source."""
|
|
245
|
+
if source:
|
|
246
|
+
return [s for s in self.skills.values() if s.source == source]
|
|
247
|
+
return list(self.skills.values())
|
|
248
|
+
|
|
249
|
+
def get_skills_for_agent(self, agent_type: str) -> List[Skill]:
|
|
250
|
+
"""
|
|
251
|
+
Get skills mapped to a specific agent type.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
agent_type: Agent type/ID (e.g., 'engineer', 'python_engineer')
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
List of skills applicable to this agent type
|
|
258
|
+
"""
|
|
259
|
+
# Filter skills that explicitly list this agent type
|
|
260
|
+
# If a skill has no agent_types specified, it's available to all agents
|
|
261
|
+
return [
|
|
262
|
+
skill
|
|
263
|
+
for skill in self.skills.values()
|
|
264
|
+
if not skill.agent_types or agent_type in skill.agent_types
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
def reload(self):
|
|
268
|
+
"""Reload all skills from disk."""
|
|
269
|
+
logger.info("Reloading skills registry...")
|
|
270
|
+
self.skills.clear()
|
|
271
|
+
self._load_bundled_skills()
|
|
272
|
+
self._load_user_skills()
|
|
273
|
+
self._load_project_skills()
|
|
274
|
+
logger.info(f"Skills registry reloaded with {len(self.skills)} skills")
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
# Global registry instance (singleton pattern)
|
|
278
|
+
_registry: Optional[SkillsRegistry] = None
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def get_registry() -> SkillsRegistry:
|
|
282
|
+
"""Get the global skills registry (singleton)."""
|
|
283
|
+
global _registry
|
|
284
|
+
if _registry is None:
|
|
285
|
+
_registry = SkillsRegistry()
|
|
286
|
+
return _registry
|