tapps-agents 3.5.40__py3-none-any.whl → 3.6.0__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.
- tapps_agents/__init__.py +2 -2
- tapps_agents/agents/__init__.py +22 -22
- tapps_agents/agents/analyst/__init__.py +5 -5
- tapps_agents/agents/architect/__init__.py +5 -5
- tapps_agents/agents/architect/agent.py +1033 -1033
- tapps_agents/agents/architect/pattern_detector.py +75 -75
- tapps_agents/agents/cleanup/__init__.py +7 -7
- tapps_agents/agents/cleanup/agent.py +445 -445
- tapps_agents/agents/debugger/__init__.py +7 -7
- tapps_agents/agents/debugger/agent.py +310 -310
- tapps_agents/agents/debugger/error_analyzer.py +437 -437
- tapps_agents/agents/designer/__init__.py +5 -5
- tapps_agents/agents/designer/agent.py +786 -786
- tapps_agents/agents/designer/visual_designer.py +638 -638
- tapps_agents/agents/documenter/__init__.py +7 -7
- tapps_agents/agents/documenter/agent.py +531 -531
- tapps_agents/agents/documenter/doc_generator.py +472 -472
- tapps_agents/agents/documenter/doc_validator.py +393 -393
- tapps_agents/agents/documenter/framework_doc_updater.py +493 -493
- tapps_agents/agents/enhancer/__init__.py +7 -7
- tapps_agents/agents/evaluator/__init__.py +7 -7
- tapps_agents/agents/evaluator/agent.py +443 -443
- tapps_agents/agents/evaluator/priority_evaluator.py +641 -641
- tapps_agents/agents/evaluator/quality_analyzer.py +147 -147
- tapps_agents/agents/evaluator/report_generator.py +344 -344
- tapps_agents/agents/evaluator/usage_analyzer.py +192 -192
- tapps_agents/agents/evaluator/workflow_analyzer.py +189 -189
- tapps_agents/agents/implementer/__init__.py +7 -7
- tapps_agents/agents/implementer/agent.py +798 -798
- tapps_agents/agents/implementer/auto_fix.py +1119 -1119
- tapps_agents/agents/implementer/code_generator.py +73 -73
- tapps_agents/agents/improver/__init__.py +1 -1
- tapps_agents/agents/improver/agent.py +753 -753
- tapps_agents/agents/ops/__init__.py +1 -1
- tapps_agents/agents/ops/agent.py +619 -619
- tapps_agents/agents/ops/dependency_analyzer.py +600 -600
- tapps_agents/agents/orchestrator/__init__.py +5 -5
- tapps_agents/agents/orchestrator/agent.py +522 -522
- tapps_agents/agents/planner/__init__.py +7 -7
- tapps_agents/agents/planner/agent.py +1127 -1127
- tapps_agents/agents/reviewer/__init__.py +24 -24
- tapps_agents/agents/reviewer/agent.py +3513 -3513
- tapps_agents/agents/reviewer/aggregator.py +213 -213
- tapps_agents/agents/reviewer/batch_review.py +448 -448
- tapps_agents/agents/reviewer/cache.py +443 -443
- tapps_agents/agents/reviewer/context7_enhancer.py +630 -630
- tapps_agents/agents/reviewer/context_detector.py +203 -203
- tapps_agents/agents/reviewer/docker_compose_validator.py +158 -158
- tapps_agents/agents/reviewer/dockerfile_validator.py +176 -176
- tapps_agents/agents/reviewer/error_handling.py +126 -126
- tapps_agents/agents/reviewer/feedback_generator.py +490 -490
- tapps_agents/agents/reviewer/influxdb_validator.py +316 -316
- tapps_agents/agents/reviewer/issue_tracking.py +169 -169
- tapps_agents/agents/reviewer/library_detector.py +295 -295
- tapps_agents/agents/reviewer/library_patterns.py +268 -268
- tapps_agents/agents/reviewer/maintainability_scorer.py +593 -593
- tapps_agents/agents/reviewer/metric_strategies.py +276 -276
- tapps_agents/agents/reviewer/mqtt_validator.py +160 -160
- tapps_agents/agents/reviewer/output_enhancer.py +105 -105
- tapps_agents/agents/reviewer/pattern_detector.py +241 -241
- tapps_agents/agents/reviewer/performance_scorer.py +357 -357
- tapps_agents/agents/reviewer/phased_review.py +516 -516
- tapps_agents/agents/reviewer/progressive_review.py +435 -435
- tapps_agents/agents/reviewer/react_scorer.py +331 -331
- tapps_agents/agents/reviewer/score_constants.py +228 -228
- tapps_agents/agents/reviewer/score_validator.py +507 -507
- tapps_agents/agents/reviewer/scorer_registry.py +373 -373
- tapps_agents/agents/reviewer/scoring.py +1566 -1566
- tapps_agents/agents/reviewer/service_discovery.py +534 -534
- tapps_agents/agents/reviewer/tools/__init__.py +41 -41
- tapps_agents/agents/reviewer/tools/parallel_executor.py +581 -581
- tapps_agents/agents/reviewer/tools/ruff_grouping.py +250 -250
- tapps_agents/agents/reviewer/tools/scoped_mypy.py +284 -284
- tapps_agents/agents/reviewer/typescript_scorer.py +1142 -1142
- tapps_agents/agents/reviewer/validation.py +208 -208
- tapps_agents/agents/reviewer/websocket_validator.py +132 -132
- tapps_agents/agents/tester/__init__.py +7 -7
- tapps_agents/agents/tester/accessibility_auditor.py +309 -309
- tapps_agents/agents/tester/agent.py +1080 -1080
- tapps_agents/agents/tester/batch_generator.py +54 -54
- tapps_agents/agents/tester/context_learner.py +51 -51
- tapps_agents/agents/tester/coverage_analyzer.py +386 -386
- tapps_agents/agents/tester/coverage_test_generator.py +290 -290
- tapps_agents/agents/tester/debug_enhancer.py +238 -238
- tapps_agents/agents/tester/device_emulator.py +241 -241
- tapps_agents/agents/tester/integration_generator.py +62 -62
- tapps_agents/agents/tester/network_recorder.py +300 -300
- tapps_agents/agents/tester/performance_monitor.py +320 -320
- tapps_agents/agents/tester/test_fixer.py +316 -316
- tapps_agents/agents/tester/test_generator.py +632 -632
- tapps_agents/agents/tester/trace_manager.py +234 -234
- tapps_agents/agents/tester/visual_regression.py +291 -291
- tapps_agents/analysis/pattern_detector.py +36 -36
- tapps_agents/beads/hydration.py +213 -213
- tapps_agents/beads/parse.py +32 -32
- tapps_agents/beads/specs.py +206 -206
- tapps_agents/cli/__init__.py +9 -9
- tapps_agents/cli/__main__.py +8 -8
- tapps_agents/cli/base.py +478 -478
- tapps_agents/cli/command_classifier.py +72 -72
- tapps_agents/cli/commands/__init__.py +2 -2
- tapps_agents/cli/commands/analyst.py +173 -173
- tapps_agents/cli/commands/architect.py +109 -109
- tapps_agents/cli/commands/cleanup_agent.py +92 -92
- tapps_agents/cli/commands/common.py +126 -126
- tapps_agents/cli/commands/debugger.py +90 -90
- tapps_agents/cli/commands/designer.py +112 -112
- tapps_agents/cli/commands/documenter.py +136 -136
- tapps_agents/cli/commands/enhancer.py +110 -110
- tapps_agents/cli/commands/evaluator.py +255 -255
- tapps_agents/cli/commands/health.py +665 -665
- tapps_agents/cli/commands/implementer.py +301 -301
- tapps_agents/cli/commands/improver.py +91 -91
- tapps_agents/cli/commands/knowledge.py +111 -111
- tapps_agents/cli/commands/learning.py +172 -172
- tapps_agents/cli/commands/observability.py +283 -283
- tapps_agents/cli/commands/ops.py +135 -135
- tapps_agents/cli/commands/orchestrator.py +116 -116
- tapps_agents/cli/commands/planner.py +237 -237
- tapps_agents/cli/commands/reviewer.py +1872 -1872
- tapps_agents/cli/commands/status.py +285 -285
- tapps_agents/cli/commands/task.py +227 -219
- tapps_agents/cli/commands/tester.py +191 -191
- tapps_agents/cli/commands/top_level.py +3586 -3586
- tapps_agents/cli/feedback.py +936 -936
- tapps_agents/cli/formatters.py +608 -608
- tapps_agents/cli/help/__init__.py +7 -7
- tapps_agents/cli/help/static_help.py +425 -425
- tapps_agents/cli/network_detection.py +110 -110
- tapps_agents/cli/output_compactor.py +274 -274
- tapps_agents/cli/parsers/__init__.py +2 -2
- tapps_agents/cli/parsers/analyst.py +186 -186
- tapps_agents/cli/parsers/architect.py +167 -167
- tapps_agents/cli/parsers/cleanup_agent.py +228 -228
- tapps_agents/cli/parsers/debugger.py +116 -116
- tapps_agents/cli/parsers/designer.py +182 -182
- tapps_agents/cli/parsers/documenter.py +134 -134
- tapps_agents/cli/parsers/enhancer.py +113 -113
- tapps_agents/cli/parsers/evaluator.py +213 -213
- tapps_agents/cli/parsers/implementer.py +168 -168
- tapps_agents/cli/parsers/improver.py +132 -132
- tapps_agents/cli/parsers/ops.py +159 -159
- tapps_agents/cli/parsers/orchestrator.py +98 -98
- tapps_agents/cli/parsers/planner.py +145 -145
- tapps_agents/cli/parsers/reviewer.py +462 -462
- tapps_agents/cli/parsers/tester.py +124 -124
- tapps_agents/cli/progress_heartbeat.py +254 -254
- tapps_agents/cli/streaming_progress.py +336 -336
- tapps_agents/cli/utils/__init__.py +6 -6
- tapps_agents/cli/utils/agent_lifecycle.py +48 -48
- tapps_agents/cli/utils/error_formatter.py +82 -82
- tapps_agents/cli/utils/error_recovery.py +188 -188
- tapps_agents/cli/utils/output_handler.py +59 -59
- tapps_agents/cli/utils/prompt_enhancer.py +319 -319
- tapps_agents/cli/validators/__init__.py +9 -9
- tapps_agents/cli/validators/command_validator.py +81 -81
- tapps_agents/context7/__init__.py +112 -112
- tapps_agents/context7/agent_integration.py +869 -869
- tapps_agents/context7/analytics.py +382 -382
- tapps_agents/context7/analytics_dashboard.py +299 -299
- tapps_agents/context7/async_cache.py +681 -681
- tapps_agents/context7/backup_client.py +958 -958
- tapps_agents/context7/cache_locking.py +194 -194
- tapps_agents/context7/cache_metadata.py +214 -214
- tapps_agents/context7/cache_prewarm.py +488 -488
- tapps_agents/context7/cache_structure.py +168 -168
- tapps_agents/context7/cache_warming.py +604 -604
- tapps_agents/context7/circuit_breaker.py +376 -376
- tapps_agents/context7/cleanup.py +461 -461
- tapps_agents/context7/commands.py +858 -858
- tapps_agents/context7/credential_validation.py +276 -276
- tapps_agents/context7/cross_reference_resolver.py +168 -168
- tapps_agents/context7/cross_references.py +424 -424
- tapps_agents/context7/doc_manager.py +225 -225
- tapps_agents/context7/fuzzy_matcher.py +369 -369
- tapps_agents/context7/kb_cache.py +404 -404
- tapps_agents/context7/language_detector.py +219 -219
- tapps_agents/context7/library_detector.py +725 -725
- tapps_agents/context7/lookup.py +738 -738
- tapps_agents/context7/metadata.py +258 -258
- tapps_agents/context7/refresh_queue.py +300 -300
- tapps_agents/context7/security.py +373 -373
- tapps_agents/context7/staleness_policies.py +278 -278
- tapps_agents/context7/tiles_integration.py +47 -47
- tapps_agents/continuous_bug_fix/__init__.py +20 -20
- tapps_agents/continuous_bug_fix/bug_finder.py +306 -306
- tapps_agents/continuous_bug_fix/bug_fix_coordinator.py +177 -177
- tapps_agents/continuous_bug_fix/commit_manager.py +178 -178
- tapps_agents/continuous_bug_fix/continuous_bug_fixer.py +322 -322
- tapps_agents/continuous_bug_fix/proactive_bug_finder.py +285 -285
- tapps_agents/core/__init__.py +298 -298
- tapps_agents/core/adaptive_cache_config.py +432 -432
- tapps_agents/core/agent_base.py +647 -647
- tapps_agents/core/agent_cache.py +466 -466
- tapps_agents/core/agent_learning.py +1865 -1865
- tapps_agents/core/analytics_dashboard.py +563 -563
- tapps_agents/core/analytics_enhancements.py +597 -597
- tapps_agents/core/anonymization.py +274 -274
- tapps_agents/core/artifact_context_builder.py +293 -0
- tapps_agents/core/ast_parser.py +228 -228
- tapps_agents/core/async_file_ops.py +402 -402
- tapps_agents/core/best_practice_consultant.py +299 -299
- tapps_agents/core/brownfield_analyzer.py +299 -299
- tapps_agents/core/brownfield_review.py +541 -541
- tapps_agents/core/browser_controller.py +513 -513
- tapps_agents/core/capability_registry.py +418 -418
- tapps_agents/core/change_impact_analyzer.py +190 -190
- tapps_agents/core/checkpoint_manager.py +377 -377
- tapps_agents/core/code_generator.py +329 -329
- tapps_agents/core/code_validator.py +276 -276
- tapps_agents/core/command_registry.py +327 -327
- tapps_agents/core/config.py +33 -0
- tapps_agents/core/context_gathering/__init__.py +2 -2
- tapps_agents/core/context_gathering/repository_explorer.py +28 -28
- tapps_agents/core/context_intelligence/__init__.py +2 -2
- tapps_agents/core/context_intelligence/relevance_scorer.py +24 -24
- tapps_agents/core/context_intelligence/token_budget_manager.py +27 -27
- tapps_agents/core/context_manager.py +240 -240
- tapps_agents/core/cursor_feedback_monitor.py +146 -146
- tapps_agents/core/cursor_verification.py +290 -290
- tapps_agents/core/customization_loader.py +280 -280
- tapps_agents/core/customization_schema.py +260 -260
- tapps_agents/core/customization_template.py +238 -238
- tapps_agents/core/debug_logger.py +124 -124
- tapps_agents/core/design_validator.py +298 -298
- tapps_agents/core/diagram_generator.py +226 -226
- tapps_agents/core/docker_utils.py +232 -232
- tapps_agents/core/document_generator.py +617 -617
- tapps_agents/core/domain_detector.py +30 -30
- tapps_agents/core/error_envelope.py +454 -454
- tapps_agents/core/error_handler.py +270 -270
- tapps_agents/core/estimation_tracker.py +189 -189
- tapps_agents/core/eval_prompt_engine.py +116 -116
- tapps_agents/core/evaluation_base.py +119 -119
- tapps_agents/core/evaluation_models.py +320 -320
- tapps_agents/core/evaluation_orchestrator.py +225 -225
- tapps_agents/core/evaluators/__init__.py +7 -7
- tapps_agents/core/evaluators/architectural_evaluator.py +205 -205
- tapps_agents/core/evaluators/behavioral_evaluator.py +160 -160
- tapps_agents/core/evaluators/performance_profile_evaluator.py +160 -160
- tapps_agents/core/evaluators/security_posture_evaluator.py +148 -148
- tapps_agents/core/evaluators/spec_compliance_evaluator.py +181 -181
- tapps_agents/core/exceptions.py +107 -107
- tapps_agents/core/expert_config_generator.py +293 -293
- tapps_agents/core/export_schema.py +202 -202
- tapps_agents/core/external_feedback_models.py +102 -102
- tapps_agents/core/external_feedback_storage.py +213 -213
- tapps_agents/core/fallback_strategy.py +314 -314
- tapps_agents/core/feedback_analyzer.py +162 -162
- tapps_agents/core/feedback_collector.py +178 -178
- tapps_agents/core/git_operations.py +445 -445
- tapps_agents/core/hardware_profiler.py +151 -151
- tapps_agents/core/instructions.py +324 -324
- tapps_agents/core/io_guardrails.py +69 -69
- tapps_agents/core/issue_manifest.py +249 -249
- tapps_agents/core/issue_schema.py +139 -139
- tapps_agents/core/json_utils.py +128 -128
- tapps_agents/core/knowledge_graph.py +446 -446
- tapps_agents/core/language_detector.py +296 -296
- tapps_agents/core/learning_confidence.py +242 -242
- tapps_agents/core/learning_dashboard.py +246 -246
- tapps_agents/core/learning_decision.py +384 -384
- tapps_agents/core/learning_explainability.py +578 -578
- tapps_agents/core/learning_export.py +287 -287
- tapps_agents/core/learning_integration.py +228 -228
- tapps_agents/core/llm_behavior.py +232 -232
- tapps_agents/core/long_duration_support.py +786 -786
- tapps_agents/core/mcp_setup.py +106 -106
- tapps_agents/core/memory_integration.py +396 -396
- tapps_agents/core/meta_learning.py +666 -666
- tapps_agents/core/module_path_sanitizer.py +199 -199
- tapps_agents/core/multi_agent_orchestrator.py +382 -382
- tapps_agents/core/network_errors.py +125 -125
- tapps_agents/core/nfr_validator.py +336 -336
- tapps_agents/core/offline_mode.py +158 -158
- tapps_agents/core/output_contracts.py +300 -300
- tapps_agents/core/output_formatter.py +300 -300
- tapps_agents/core/path_normalizer.py +174 -174
- tapps_agents/core/path_validator.py +322 -322
- tapps_agents/core/pattern_library.py +250 -250
- tapps_agents/core/performance_benchmark.py +301 -301
- tapps_agents/core/performance_monitor.py +184 -184
- tapps_agents/core/playwright_mcp_controller.py +771 -771
- tapps_agents/core/policy_loader.py +135 -135
- tapps_agents/core/progress.py +166 -166
- tapps_agents/core/project_profile.py +354 -354
- tapps_agents/core/project_type_detector.py +454 -454
- tapps_agents/core/prompt_base.py +223 -223
- tapps_agents/core/prompt_learning/__init__.py +2 -2
- tapps_agents/core/prompt_learning/learning_loop.py +24 -24
- tapps_agents/core/prompt_learning/project_prompt_store.py +25 -25
- tapps_agents/core/prompt_learning/skills_prompt_analyzer.py +35 -35
- tapps_agents/core/prompt_optimization/__init__.py +6 -6
- tapps_agents/core/prompt_optimization/ab_tester.py +114 -114
- tapps_agents/core/prompt_optimization/correlation_analyzer.py +160 -160
- tapps_agents/core/prompt_optimization/progressive_refiner.py +129 -129
- tapps_agents/core/prompt_optimization/prompt_library.py +37 -37
- tapps_agents/core/requirements_evaluator.py +431 -431
- tapps_agents/core/resource_aware_executor.py +449 -449
- tapps_agents/core/resource_monitor.py +343 -343
- tapps_agents/core/resume_handler.py +298 -298
- tapps_agents/core/retry_handler.py +197 -197
- tapps_agents/core/review_checklists.py +479 -479
- tapps_agents/core/role_loader.py +201 -201
- tapps_agents/core/role_template_loader.py +201 -201
- tapps_agents/core/runtime_mode.py +60 -60
- tapps_agents/core/security_scanner.py +342 -342
- tapps_agents/core/skill_agent_registry.py +194 -194
- tapps_agents/core/skill_integration.py +208 -208
- tapps_agents/core/skill_loader.py +492 -492
- tapps_agents/core/skill_template.py +341 -341
- tapps_agents/core/skill_validator.py +478 -478
- tapps_agents/core/stack_analyzer.py +35 -35
- tapps_agents/core/startup.py +174 -174
- tapps_agents/core/storage_manager.py +397 -397
- tapps_agents/core/storage_models.py +166 -166
- tapps_agents/core/story_evaluator.py +410 -410
- tapps_agents/core/subprocess_utils.py +170 -170
- tapps_agents/core/task_duration.py +296 -296
- tapps_agents/core/task_memory.py +582 -582
- tapps_agents/core/task_state.py +226 -226
- tapps_agents/core/tech_stack_priorities.py +208 -208
- tapps_agents/core/temp_directory.py +194 -194
- tapps_agents/core/template_merger.py +600 -600
- tapps_agents/core/template_selector.py +280 -280
- tapps_agents/core/test_generator.py +286 -286
- tapps_agents/core/tiered_context.py +253 -253
- tapps_agents/core/token_monitor.py +345 -345
- tapps_agents/core/traceability.py +254 -254
- tapps_agents/core/trajectory_tracker.py +50 -50
- tapps_agents/core/unicode_safe.py +143 -143
- tapps_agents/core/unified_cache_config.py +170 -170
- tapps_agents/core/unified_state.py +324 -324
- tapps_agents/core/validate_cursor_setup.py +237 -237
- tapps_agents/core/validation_registry.py +136 -136
- tapps_agents/core/validators/__init__.py +4 -4
- tapps_agents/core/validators/python_validator.py +87 -87
- tapps_agents/core/verification_agent.py +90 -90
- tapps_agents/core/visual_feedback.py +644 -644
- tapps_agents/core/workflow_validator.py +197 -197
- tapps_agents/core/worktree.py +367 -367
- tapps_agents/docker/__init__.py +10 -10
- tapps_agents/docker/analyzer.py +186 -186
- tapps_agents/docker/debugger.py +229 -229
- tapps_agents/docker/error_patterns.py +216 -216
- tapps_agents/epic/__init__.py +22 -22
- tapps_agents/epic/beads_sync.py +115 -115
- tapps_agents/epic/markdown_sync.py +105 -105
- tapps_agents/epic/models.py +96 -96
- tapps_agents/experts/__init__.py +163 -163
- tapps_agents/experts/agent_integration.py +243 -243
- tapps_agents/experts/auto_generator.py +331 -331
- tapps_agents/experts/base_expert.py +536 -536
- tapps_agents/experts/builtin_registry.py +261 -261
- tapps_agents/experts/business_metrics.py +565 -565
- tapps_agents/experts/cache.py +266 -266
- tapps_agents/experts/confidence_breakdown.py +306 -306
- tapps_agents/experts/confidence_calculator.py +336 -336
- tapps_agents/experts/confidence_metrics.py +236 -236
- tapps_agents/experts/domain_config.py +311 -311
- tapps_agents/experts/domain_detector.py +550 -550
- tapps_agents/experts/domain_utils.py +84 -84
- tapps_agents/experts/expert_config.py +113 -113
- tapps_agents/experts/expert_engine.py +465 -465
- tapps_agents/experts/expert_registry.py +744 -744
- tapps_agents/experts/expert_synthesizer.py +70 -70
- tapps_agents/experts/governance.py +197 -197
- tapps_agents/experts/history_logger.py +312 -312
- tapps_agents/experts/knowledge/README.md +180 -180
- tapps_agents/experts/knowledge/accessibility/accessible-forms.md +331 -331
- tapps_agents/experts/knowledge/accessibility/aria-patterns.md +344 -344
- tapps_agents/experts/knowledge/accessibility/color-contrast.md +285 -285
- tapps_agents/experts/knowledge/accessibility/keyboard-navigation.md +332 -332
- tapps_agents/experts/knowledge/accessibility/screen-readers.md +282 -282
- tapps_agents/experts/knowledge/accessibility/semantic-html.md +355 -355
- tapps_agents/experts/knowledge/accessibility/testing-accessibility.md +369 -369
- tapps_agents/experts/knowledge/accessibility/wcag-2.1.md +296 -296
- tapps_agents/experts/knowledge/accessibility/wcag-2.2.md +211 -211
- tapps_agents/experts/knowledge/agent-learning/best-practices.md +715 -715
- tapps_agents/experts/knowledge/agent-learning/pattern-extraction.md +282 -282
- tapps_agents/experts/knowledge/agent-learning/prompt-optimization.md +320 -320
- tapps_agents/experts/knowledge/ai-frameworks/model-optimization.md +90 -90
- tapps_agents/experts/knowledge/ai-frameworks/openvino-patterns.md +260 -260
- tapps_agents/experts/knowledge/api-design-integration/api-gateway-patterns.md +309 -309
- tapps_agents/experts/knowledge/api-design-integration/api-security-patterns.md +521 -521
- tapps_agents/experts/knowledge/api-design-integration/api-versioning.md +421 -421
- tapps_agents/experts/knowledge/api-design-integration/async-protocol-patterns.md +61 -61
- tapps_agents/experts/knowledge/api-design-integration/contract-testing.md +221 -221
- tapps_agents/experts/knowledge/api-design-integration/external-api-integration.md +489 -489
- tapps_agents/experts/knowledge/api-design-integration/fastapi-patterns.md +360 -360
- tapps_agents/experts/knowledge/api-design-integration/fastapi-testing.md +262 -262
- tapps_agents/experts/knowledge/api-design-integration/graphql-patterns.md +582 -582
- tapps_agents/experts/knowledge/api-design-integration/grpc-best-practices.md +499 -499
- tapps_agents/experts/knowledge/api-design-integration/mqtt-patterns.md +455 -455
- tapps_agents/experts/knowledge/api-design-integration/rate-limiting.md +507 -507
- tapps_agents/experts/knowledge/api-design-integration/restful-api-design.md +618 -618
- tapps_agents/experts/knowledge/api-design-integration/websocket-patterns.md +480 -480
- tapps_agents/experts/knowledge/cloud-infrastructure/cloud-native-patterns.md +175 -175
- tapps_agents/experts/knowledge/cloud-infrastructure/container-health-checks.md +261 -261
- tapps_agents/experts/knowledge/cloud-infrastructure/containerization.md +222 -222
- tapps_agents/experts/knowledge/cloud-infrastructure/cost-optimization.md +122 -122
- tapps_agents/experts/knowledge/cloud-infrastructure/disaster-recovery.md +153 -153
- tapps_agents/experts/knowledge/cloud-infrastructure/dockerfile-patterns.md +285 -285
- tapps_agents/experts/knowledge/cloud-infrastructure/infrastructure-as-code.md +187 -187
- tapps_agents/experts/knowledge/cloud-infrastructure/kubernetes-patterns.md +253 -253
- tapps_agents/experts/knowledge/cloud-infrastructure/multi-cloud-strategies.md +155 -155
- tapps_agents/experts/knowledge/cloud-infrastructure/serverless-architecture.md +200 -200
- tapps_agents/experts/knowledge/code-quality-analysis/README.md +16 -16
- tapps_agents/experts/knowledge/code-quality-analysis/code-metrics.md +137 -137
- tapps_agents/experts/knowledge/code-quality-analysis/complexity-analysis.md +181 -181
- tapps_agents/experts/knowledge/code-quality-analysis/technical-debt-patterns.md +191 -191
- tapps_agents/experts/knowledge/data-privacy-compliance/anonymization.md +313 -313
- tapps_agents/experts/knowledge/data-privacy-compliance/ccpa.md +255 -255
- tapps_agents/experts/knowledge/data-privacy-compliance/consent-management.md +282 -282
- tapps_agents/experts/knowledge/data-privacy-compliance/data-minimization.md +275 -275
- tapps_agents/experts/knowledge/data-privacy-compliance/data-retention.md +297 -297
- tapps_agents/experts/knowledge/data-privacy-compliance/data-subject-rights.md +383 -383
- tapps_agents/experts/knowledge/data-privacy-compliance/encryption-privacy.md +285 -285
- tapps_agents/experts/knowledge/data-privacy-compliance/gdpr.md +344 -344
- tapps_agents/experts/knowledge/data-privacy-compliance/hipaa.md +385 -385
- tapps_agents/experts/knowledge/data-privacy-compliance/privacy-by-design.md +280 -280
- tapps_agents/experts/knowledge/database-data-management/acid-vs-cap.md +164 -164
- tapps_agents/experts/knowledge/database-data-management/backup-and-recovery.md +182 -182
- tapps_agents/experts/knowledge/database-data-management/data-modeling.md +172 -172
- tapps_agents/experts/knowledge/database-data-management/database-design.md +187 -187
- tapps_agents/experts/knowledge/database-data-management/flux-query-optimization.md +342 -342
- tapps_agents/experts/knowledge/database-data-management/influxdb-connection-patterns.md +432 -432
- tapps_agents/experts/knowledge/database-data-management/influxdb-patterns.md +442 -442
- tapps_agents/experts/knowledge/database-data-management/migration-strategies.md +216 -216
- tapps_agents/experts/knowledge/database-data-management/nosql-patterns.md +259 -259
- tapps_agents/experts/knowledge/database-data-management/scalability-patterns.md +184 -184
- tapps_agents/experts/knowledge/database-data-management/sql-optimization.md +175 -175
- tapps_agents/experts/knowledge/database-data-management/time-series-modeling.md +444 -444
- tapps_agents/experts/knowledge/development-workflow/README.md +16 -16
- tapps_agents/experts/knowledge/development-workflow/automation-best-practices.md +216 -216
- tapps_agents/experts/knowledge/development-workflow/build-strategies.md +198 -198
- tapps_agents/experts/knowledge/development-workflow/deployment-patterns.md +205 -205
- tapps_agents/experts/knowledge/development-workflow/git-workflows.md +205 -205
- tapps_agents/experts/knowledge/documentation-knowledge-management/README.md +16 -16
- tapps_agents/experts/knowledge/documentation-knowledge-management/api-documentation-patterns.md +231 -231
- tapps_agents/experts/knowledge/documentation-knowledge-management/documentation-standards.md +191 -191
- tapps_agents/experts/knowledge/documentation-knowledge-management/knowledge-management.md +171 -171
- tapps_agents/experts/knowledge/documentation-knowledge-management/technical-writing-guide.md +192 -192
- tapps_agents/experts/knowledge/observability-monitoring/alerting-patterns.md +461 -461
- tapps_agents/experts/knowledge/observability-monitoring/apm-tools.md +459 -459
- tapps_agents/experts/knowledge/observability-monitoring/distributed-tracing.md +367 -367
- tapps_agents/experts/knowledge/observability-monitoring/logging-strategies.md +478 -478
- tapps_agents/experts/knowledge/observability-monitoring/metrics-and-monitoring.md +510 -510
- tapps_agents/experts/knowledge/observability-monitoring/observability-best-practices.md +492 -492
- tapps_agents/experts/knowledge/observability-monitoring/open-telemetry.md +573 -573
- tapps_agents/experts/knowledge/observability-monitoring/slo-sli-sla.md +419 -419
- tapps_agents/experts/knowledge/performance/anti-patterns.md +284 -284
- tapps_agents/experts/knowledge/performance/api-performance.md +256 -256
- tapps_agents/experts/knowledge/performance/caching.md +327 -327
- tapps_agents/experts/knowledge/performance/database-performance.md +252 -252
- tapps_agents/experts/knowledge/performance/optimization-patterns.md +327 -327
- tapps_agents/experts/knowledge/performance/profiling.md +297 -297
- tapps_agents/experts/knowledge/performance/resource-management.md +293 -293
- tapps_agents/experts/knowledge/performance/scalability.md +306 -306
- tapps_agents/experts/knowledge/security/owasp-top10.md +209 -209
- tapps_agents/experts/knowledge/security/secure-coding-practices.md +207 -207
- tapps_agents/experts/knowledge/security/threat-modeling.md +220 -220
- tapps_agents/experts/knowledge/security/vulnerability-patterns.md +342 -342
- tapps_agents/experts/knowledge/software-architecture/docker-compose-patterns.md +314 -314
- tapps_agents/experts/knowledge/software-architecture/microservices-patterns.md +379 -379
- tapps_agents/experts/knowledge/software-architecture/service-communication.md +316 -316
- tapps_agents/experts/knowledge/testing/best-practices.md +310 -310
- tapps_agents/experts/knowledge/testing/coverage-analysis.md +293 -293
- tapps_agents/experts/knowledge/testing/mocking.md +256 -256
- tapps_agents/experts/knowledge/testing/test-automation.md +276 -276
- tapps_agents/experts/knowledge/testing/test-data.md +271 -271
- tapps_agents/experts/knowledge/testing/test-design-patterns.md +280 -280
- tapps_agents/experts/knowledge/testing/test-maintenance.md +236 -236
- tapps_agents/experts/knowledge/testing/test-strategies.md +311 -311
- tapps_agents/experts/knowledge/user-experience/information-architecture.md +325 -325
- tapps_agents/experts/knowledge/user-experience/interaction-design.md +363 -363
- tapps_agents/experts/knowledge/user-experience/prototyping.md +293 -293
- tapps_agents/experts/knowledge/user-experience/usability-heuristics.md +337 -337
- tapps_agents/experts/knowledge/user-experience/usability-testing.md +311 -311
- tapps_agents/experts/knowledge/user-experience/user-journeys.md +296 -296
- tapps_agents/experts/knowledge/user-experience/user-research.md +373 -373
- tapps_agents/experts/knowledge/user-experience/ux-principles.md +340 -340
- tapps_agents/experts/knowledge_freshness.py +321 -321
- tapps_agents/experts/knowledge_ingestion.py +438 -438
- tapps_agents/experts/knowledge_need_detector.py +93 -93
- tapps_agents/experts/knowledge_validator.py +382 -382
- tapps_agents/experts/observability.py +440 -440
- tapps_agents/experts/passive_notifier.py +238 -238
- tapps_agents/experts/proactive_orchestrator.py +32 -32
- tapps_agents/experts/rag_chunker.py +205 -205
- tapps_agents/experts/rag_embedder.py +152 -152
- tapps_agents/experts/rag_evaluation.py +299 -299
- tapps_agents/experts/rag_index.py +303 -303
- tapps_agents/experts/rag_metrics.py +293 -293
- tapps_agents/experts/rag_safety.py +263 -263
- tapps_agents/experts/report_generator.py +296 -296
- tapps_agents/experts/setup_wizard.py +441 -441
- tapps_agents/experts/simple_rag.py +431 -431
- tapps_agents/experts/vector_rag.py +354 -354
- tapps_agents/experts/weight_distributor.py +304 -304
- tapps_agents/health/__init__.py +24 -24
- tapps_agents/health/base.py +75 -75
- tapps_agents/health/checks/__init__.py +22 -22
- tapps_agents/health/checks/automation.py +127 -127
- tapps_agents/health/checks/context7_cache.py +210 -210
- tapps_agents/health/checks/environment.py +116 -116
- tapps_agents/health/checks/execution.py +170 -170
- tapps_agents/health/checks/knowledge_base.py +187 -187
- tapps_agents/health/checks/outcomes.py +324 -324
- tapps_agents/health/collector.py +280 -280
- tapps_agents/health/dashboard.py +137 -137
- tapps_agents/health/metrics.py +151 -151
- tapps_agents/health/orchestrator.py +271 -271
- tapps_agents/health/registry.py +166 -166
- tapps_agents/hooks/__init__.py +33 -33
- tapps_agents/hooks/config.py +140 -140
- tapps_agents/hooks/events.py +135 -135
- tapps_agents/hooks/executor.py +128 -128
- tapps_agents/hooks/manager.py +143 -143
- tapps_agents/integration/__init__.py +8 -8
- tapps_agents/integration/service_integrator.py +121 -121
- tapps_agents/integrations/__init__.py +10 -10
- tapps_agents/integrations/clawdbot.py +525 -525
- tapps_agents/integrations/memory_bridge.py +356 -356
- tapps_agents/mcp/__init__.py +18 -18
- tapps_agents/mcp/gateway.py +112 -112
- tapps_agents/mcp/servers/__init__.py +13 -13
- tapps_agents/mcp/servers/analysis.py +204 -204
- tapps_agents/mcp/servers/context7.py +198 -198
- tapps_agents/mcp/servers/filesystem.py +218 -218
- tapps_agents/mcp/servers/git.py +201 -201
- tapps_agents/mcp/tool_registry.py +115 -115
- tapps_agents/quality/__init__.py +54 -54
- tapps_agents/quality/coverage_analyzer.py +379 -379
- tapps_agents/quality/enforcement.py +82 -82
- tapps_agents/quality/gates/__init__.py +37 -37
- tapps_agents/quality/gates/approval_gate.py +255 -255
- tapps_agents/quality/gates/base.py +84 -84
- tapps_agents/quality/gates/exceptions.py +43 -43
- tapps_agents/quality/gates/policy_gate.py +195 -195
- tapps_agents/quality/gates/registry.py +239 -239
- tapps_agents/quality/gates/security_gate.py +156 -156
- tapps_agents/quality/quality_gates.py +369 -369
- tapps_agents/quality/secret_scanner.py +335 -335
- tapps_agents/session/__init__.py +19 -19
- tapps_agents/session/manager.py +256 -256
- tapps_agents/simple_mode/__init__.py +66 -66
- tapps_agents/simple_mode/agent_contracts.py +357 -357
- tapps_agents/simple_mode/beads_hooks.py +151 -151
- tapps_agents/simple_mode/code_snippet_handler.py +382 -382
- tapps_agents/simple_mode/documentation_manager.py +395 -395
- tapps_agents/simple_mode/documentation_reader.py +187 -187
- tapps_agents/simple_mode/file_inference.py +292 -292
- tapps_agents/simple_mode/framework_change_detector.py +268 -268
- tapps_agents/simple_mode/intent_parser.py +510 -510
- tapps_agents/simple_mode/learning_progression.py +358 -358
- tapps_agents/simple_mode/nl_handler.py +700 -700
- tapps_agents/simple_mode/onboarding.py +253 -253
- tapps_agents/simple_mode/orchestrators/__init__.py +38 -38
- tapps_agents/simple_mode/orchestrators/base.py +185 -185
- tapps_agents/simple_mode/orchestrators/breakdown_orchestrator.py +49 -49
- tapps_agents/simple_mode/orchestrators/brownfield_orchestrator.py +135 -135
- tapps_agents/simple_mode/orchestrators/build_orchestrator.py +2700 -2667
- tapps_agents/simple_mode/orchestrators/deliverable_checklist.py +349 -349
- tapps_agents/simple_mode/orchestrators/enhance_orchestrator.py +53 -53
- tapps_agents/simple_mode/orchestrators/epic_orchestrator.py +122 -122
- tapps_agents/simple_mode/orchestrators/explore_orchestrator.py +184 -184
- tapps_agents/simple_mode/orchestrators/fix_orchestrator.py +723 -723
- tapps_agents/simple_mode/orchestrators/plan_analysis_orchestrator.py +206 -206
- tapps_agents/simple_mode/orchestrators/pr_orchestrator.py +237 -237
- tapps_agents/simple_mode/orchestrators/refactor_orchestrator.py +222 -222
- tapps_agents/simple_mode/orchestrators/requirements_tracer.py +262 -262
- tapps_agents/simple_mode/orchestrators/resume_orchestrator.py +210 -210
- tapps_agents/simple_mode/orchestrators/review_orchestrator.py +161 -161
- tapps_agents/simple_mode/orchestrators/test_orchestrator.py +82 -82
- tapps_agents/simple_mode/output_aggregator.py +340 -340
- tapps_agents/simple_mode/result_formatters.py +598 -598
- tapps_agents/simple_mode/step_dependencies.py +382 -382
- tapps_agents/simple_mode/step_results.py +276 -276
- tapps_agents/simple_mode/streaming.py +388 -388
- tapps_agents/simple_mode/variations.py +129 -129
- tapps_agents/simple_mode/visual_feedback.py +238 -238
- tapps_agents/simple_mode/zero_config.py +274 -274
- tapps_agents/suggestions/__init__.py +8 -8
- tapps_agents/suggestions/inline_suggester.py +52 -52
- tapps_agents/templates/__init__.py +8 -8
- tapps_agents/templates/microservice_generator.py +274 -274
- tapps_agents/utils/env_validator.py +291 -291
- tapps_agents/workflow/__init__.py +171 -171
- tapps_agents/workflow/acceptance_verifier.py +132 -132
- tapps_agents/workflow/agent_handlers/__init__.py +41 -41
- tapps_agents/workflow/agent_handlers/analyst_handler.py +75 -75
- tapps_agents/workflow/agent_handlers/architect_handler.py +107 -107
- tapps_agents/workflow/agent_handlers/base.py +84 -84
- tapps_agents/workflow/agent_handlers/debugger_handler.py +100 -100
- tapps_agents/workflow/agent_handlers/designer_handler.py +110 -110
- tapps_agents/workflow/agent_handlers/documenter_handler.py +94 -94
- tapps_agents/workflow/agent_handlers/implementer_handler.py +235 -235
- tapps_agents/workflow/agent_handlers/ops_handler.py +62 -62
- tapps_agents/workflow/agent_handlers/orchestrator_handler.py +43 -43
- tapps_agents/workflow/agent_handlers/planner_handler.py +98 -98
- tapps_agents/workflow/agent_handlers/registry.py +119 -119
- tapps_agents/workflow/agent_handlers/reviewer_handler.py +119 -119
- tapps_agents/workflow/agent_handlers/tester_handler.py +69 -69
- tapps_agents/workflow/analytics_accessor.py +337 -337
- tapps_agents/workflow/analytics_alerts.py +416 -416
- tapps_agents/workflow/analytics_dashboard_cursor.py +281 -281
- tapps_agents/workflow/analytics_dual_write.py +103 -103
- tapps_agents/workflow/analytics_integration.py +119 -119
- tapps_agents/workflow/analytics_query_parser.py +278 -278
- tapps_agents/workflow/analytics_visualizer.py +259 -259
- tapps_agents/workflow/artifact_helper.py +204 -204
- tapps_agents/workflow/audit_logger.py +263 -263
- tapps_agents/workflow/auto_execution_config.py +340 -340
- tapps_agents/workflow/auto_progression.py +586 -586
- tapps_agents/workflow/branch_cleanup.py +349 -349
- tapps_agents/workflow/checkpoint.py +256 -256
- tapps_agents/workflow/checkpoint_manager.py +178 -178
- tapps_agents/workflow/code_artifact.py +179 -179
- tapps_agents/workflow/common_enums.py +96 -96
- tapps_agents/workflow/confirmation_handler.py +130 -130
- tapps_agents/workflow/context_analyzer.py +222 -222
- tapps_agents/workflow/context_artifact.py +230 -230
- tapps_agents/workflow/cursor_chat.py +94 -94
- tapps_agents/workflow/cursor_executor.py +2337 -2196
- tapps_agents/workflow/cursor_skill_helper.py +516 -516
- tapps_agents/workflow/dependency_resolver.py +244 -244
- tapps_agents/workflow/design_artifact.py +156 -156
- tapps_agents/workflow/detector.py +751 -751
- tapps_agents/workflow/direct_execution_fallback.py +301 -301
- tapps_agents/workflow/docs_artifact.py +168 -168
- tapps_agents/workflow/enforcer.py +389 -389
- tapps_agents/workflow/enhancement_artifact.py +142 -142
- tapps_agents/workflow/error_recovery.py +806 -806
- tapps_agents/workflow/event_bus.py +183 -183
- tapps_agents/workflow/event_log.py +612 -612
- tapps_agents/workflow/events.py +63 -63
- tapps_agents/workflow/exceptions.py +43 -43
- tapps_agents/workflow/execution_graph.py +498 -498
- tapps_agents/workflow/execution_plan.py +126 -126
- tapps_agents/workflow/file_utils.py +186 -186
- tapps_agents/workflow/gate_evaluator.py +182 -182
- tapps_agents/workflow/gate_integration.py +200 -200
- tapps_agents/workflow/graph_visualizer.py +130 -130
- tapps_agents/workflow/health_checker.py +206 -206
- tapps_agents/workflow/logging_helper.py +243 -243
- tapps_agents/workflow/manifest.py +582 -582
- tapps_agents/workflow/marker_writer.py +250 -250
- tapps_agents/workflow/message_formatter.py +188 -188
- tapps_agents/workflow/messaging.py +325 -325
- tapps_agents/workflow/metadata_models.py +91 -91
- tapps_agents/workflow/metrics_integration.py +226 -226
- tapps_agents/workflow/migration_utils.py +116 -116
- tapps_agents/workflow/models.py +148 -111
- tapps_agents/workflow/nlp_config.py +198 -198
- tapps_agents/workflow/nlp_error_handler.py +207 -207
- tapps_agents/workflow/nlp_executor.py +163 -163
- tapps_agents/workflow/nlp_parser.py +528 -528
- tapps_agents/workflow/observability_dashboard.py +451 -451
- tapps_agents/workflow/observer.py +170 -170
- tapps_agents/workflow/ops_artifact.py +257 -257
- tapps_agents/workflow/output_passing.py +214 -214
- tapps_agents/workflow/parallel_executor.py +463 -463
- tapps_agents/workflow/planning_artifact.py +179 -179
- tapps_agents/workflow/preset_loader.py +285 -285
- tapps_agents/workflow/preset_recommender.py +270 -270
- tapps_agents/workflow/progress_logger.py +145 -145
- tapps_agents/workflow/progress_manager.py +303 -303
- tapps_agents/workflow/progress_monitor.py +186 -186
- tapps_agents/workflow/progress_updates.py +423 -423
- tapps_agents/workflow/quality_artifact.py +158 -158
- tapps_agents/workflow/quality_loopback.py +101 -101
- tapps_agents/workflow/recommender.py +387 -387
- tapps_agents/workflow/remediation_loop.py +166 -166
- tapps_agents/workflow/result_aggregator.py +300 -300
- tapps_agents/workflow/review_artifact.py +185 -185
- tapps_agents/workflow/schema_validator.py +522 -522
- tapps_agents/workflow/session_handoff.py +178 -178
- tapps_agents/workflow/skill_invoker.py +648 -648
- tapps_agents/workflow/state_manager.py +756 -756
- tapps_agents/workflow/state_persistence_config.py +331 -331
- tapps_agents/workflow/status_monitor.py +449 -449
- tapps_agents/workflow/step_checkpoint.py +314 -314
- tapps_agents/workflow/step_details.py +201 -201
- tapps_agents/workflow/story_models.py +147 -147
- tapps_agents/workflow/streaming.py +416 -416
- tapps_agents/workflow/suggestion_engine.py +552 -552
- tapps_agents/workflow/testing_artifact.py +186 -186
- tapps_agents/workflow/timeline.py +158 -158
- tapps_agents/workflow/token_integration.py +209 -209
- tapps_agents/workflow/validation.py +217 -217
- tapps_agents/workflow/visual_feedback.py +391 -391
- tapps_agents/workflow/workflow_chain.py +95 -95
- tapps_agents/workflow/workflow_summary.py +219 -219
- tapps_agents/workflow/worktree_manager.py +724 -724
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/METADATA +672 -672
- tapps_agents-3.6.0.dist-info/RECORD +758 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/licenses/LICENSE +22 -22
- tapps_agents/health/checks/outcomes.backup_20260204_064058.py +0 -324
- tapps_agents/health/checks/outcomes.backup_20260204_064256.py +0 -324
- tapps_agents/health/checks/outcomes.backup_20260204_064600.py +0 -324
- tapps_agents-3.5.40.dist-info/RECORD +0 -760
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/WHEEL +0 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/entry_points.txt +0 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/top_level.txt +0 -0
|
@@ -1,492 +1,492 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Custom Skill Loader and Registry.
|
|
3
|
-
|
|
4
|
-
Discovers, loads, and manages custom Skills alongside built-in Skills.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import re
|
|
10
|
-
from dataclasses import dataclass, field
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
|
|
13
|
-
import yaml
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@dataclass
|
|
17
|
-
class SkillMetadata:
|
|
18
|
-
"""Metadata for a Skill with enhanced fields."""
|
|
19
|
-
|
|
20
|
-
name: str
|
|
21
|
-
path: Path
|
|
22
|
-
is_builtin: bool
|
|
23
|
-
is_custom: bool
|
|
24
|
-
description: str | None = None
|
|
25
|
-
allowed_tools: list[str] | None = None
|
|
26
|
-
model_profile: str | None = None
|
|
27
|
-
version: str | None = None
|
|
28
|
-
# Enhanced metadata fields
|
|
29
|
-
author: str | None = None
|
|
30
|
-
category: str | None = None
|
|
31
|
-
tags: list[str] = field(default_factory=list)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class SkillRegistry:
|
|
35
|
-
"""Registry for managing loaded Skills."""
|
|
36
|
-
|
|
37
|
-
def __init__(self):
|
|
38
|
-
"""Initialize empty registry."""
|
|
39
|
-
self._skills: dict[str, SkillMetadata] = {}
|
|
40
|
-
self._builtin_skill_names: set[str] = set()
|
|
41
|
-
|
|
42
|
-
def register_builtin_skills(self, skill_names: list[str]) -> None:
|
|
43
|
-
"""
|
|
44
|
-
Register list of built-in Skill names.
|
|
45
|
-
|
|
46
|
-
Args:
|
|
47
|
-
skill_names: List of built-in Skill names
|
|
48
|
-
"""
|
|
49
|
-
self._builtin_skill_names = set(skill_names)
|
|
50
|
-
|
|
51
|
-
def register_skill(
|
|
52
|
-
self, skill: SkillMetadata, priority: str = "custom"
|
|
53
|
-
) -> None:
|
|
54
|
-
"""
|
|
55
|
-
Register a Skill in the registry.
|
|
56
|
-
|
|
57
|
-
Args:
|
|
58
|
-
skill: Skill metadata
|
|
59
|
-
priority: Priority level ("custom" or "builtin")
|
|
60
|
-
"""
|
|
61
|
-
# Custom Skills override built-in Skills with the same name
|
|
62
|
-
if skill.name in self._skills:
|
|
63
|
-
existing = self._skills[skill.name]
|
|
64
|
-
if existing.is_builtin and skill.is_custom:
|
|
65
|
-
# Custom Skill overrides built-in
|
|
66
|
-
self._skills[skill.name] = skill
|
|
67
|
-
elif existing.is_custom and skill.is_builtin:
|
|
68
|
-
# Built-in doesn't override custom (keep existing)
|
|
69
|
-
pass
|
|
70
|
-
else:
|
|
71
|
-
# Same type, update
|
|
72
|
-
self._skills[skill.name] = skill
|
|
73
|
-
else:
|
|
74
|
-
self._skills[skill.name] = skill
|
|
75
|
-
|
|
76
|
-
def get_skill(self, name: str) -> SkillMetadata | None:
|
|
77
|
-
"""
|
|
78
|
-
Get Skill by name.
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
name: Skill name
|
|
82
|
-
|
|
83
|
-
Returns:
|
|
84
|
-
Skill metadata or None if not found
|
|
85
|
-
"""
|
|
86
|
-
return self._skills.get(name)
|
|
87
|
-
|
|
88
|
-
def list_skills(self, include_builtin: bool = True, include_custom: bool = True) -> list[SkillMetadata]:
|
|
89
|
-
"""
|
|
90
|
-
List all registered Skills.
|
|
91
|
-
|
|
92
|
-
Args:
|
|
93
|
-
include_builtin: Include built-in Skills
|
|
94
|
-
include_custom: Include custom Skills
|
|
95
|
-
|
|
96
|
-
Returns:
|
|
97
|
-
List of Skill metadata
|
|
98
|
-
"""
|
|
99
|
-
skills = []
|
|
100
|
-
for skill in self._skills.values():
|
|
101
|
-
if skill.is_builtin and include_builtin:
|
|
102
|
-
skills.append(skill)
|
|
103
|
-
elif skill.is_custom and include_custom:
|
|
104
|
-
skills.append(skill)
|
|
105
|
-
return skills
|
|
106
|
-
|
|
107
|
-
def get_custom_skills(self) -> list[SkillMetadata]:
|
|
108
|
-
"""
|
|
109
|
-
Get all custom Skills.
|
|
110
|
-
|
|
111
|
-
Returns:
|
|
112
|
-
List of custom Skill metadata
|
|
113
|
-
"""
|
|
114
|
-
return [skill for skill in self._skills.values() if skill.is_custom]
|
|
115
|
-
|
|
116
|
-
def get_builtin_skills(self) -> list[SkillMetadata]:
|
|
117
|
-
"""
|
|
118
|
-
Get all built-in Skills.
|
|
119
|
-
|
|
120
|
-
Returns:
|
|
121
|
-
List of built-in Skill metadata
|
|
122
|
-
"""
|
|
123
|
-
return [skill for skill in self._skills.values() if skill.is_builtin]
|
|
124
|
-
|
|
125
|
-
def has_skill(self, name: str) -> bool:
|
|
126
|
-
"""
|
|
127
|
-
Check if Skill is registered.
|
|
128
|
-
|
|
129
|
-
Args:
|
|
130
|
-
name: Skill name
|
|
131
|
-
|
|
132
|
-
Returns:
|
|
133
|
-
True if Skill is registered
|
|
134
|
-
"""
|
|
135
|
-
return name in self._skills
|
|
136
|
-
|
|
137
|
-
def get_conflicts(self) -> list[tuple[str, SkillMetadata, SkillMetadata]]:
|
|
138
|
-
"""
|
|
139
|
-
Get name conflicts between custom and built-in Skills.
|
|
140
|
-
|
|
141
|
-
Returns:
|
|
142
|
-
List of tuples (name, custom_skill, builtin_skill)
|
|
143
|
-
"""
|
|
144
|
-
conflicts = []
|
|
145
|
-
custom_skills = {s.name: s for s in self.get_custom_skills()}
|
|
146
|
-
builtin_skills = {s.name: s for s in self.get_builtin_skills()}
|
|
147
|
-
|
|
148
|
-
for name in custom_skills:
|
|
149
|
-
if name in builtin_skills:
|
|
150
|
-
conflicts.append((name, custom_skills[name], builtin_skills[name]))
|
|
151
|
-
|
|
152
|
-
return conflicts
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
class CustomSkillLoader:
|
|
156
|
-
"""Loader for discovering and loading custom Skills."""
|
|
157
|
-
|
|
158
|
-
def __init__(self, project_root: Path | None = None):
|
|
159
|
-
"""
|
|
160
|
-
Initialize loader.
|
|
161
|
-
|
|
162
|
-
Args:
|
|
163
|
-
project_root: Project root directory (defaults to current directory)
|
|
164
|
-
"""
|
|
165
|
-
if project_root is None:
|
|
166
|
-
project_root = Path.cwd()
|
|
167
|
-
self.project_root = project_root
|
|
168
|
-
self.skills_dir = project_root / ".claude" / "skills"
|
|
169
|
-
|
|
170
|
-
def get_builtin_skill_names(self) -> list[str]:
|
|
171
|
-
"""
|
|
172
|
-
Get list of built-in Skill names from framework.
|
|
173
|
-
|
|
174
|
-
Returns:
|
|
175
|
-
List of built-in Skill names
|
|
176
|
-
"""
|
|
177
|
-
# Try to get from packaged resources
|
|
178
|
-
from .init_project import _resource_at
|
|
179
|
-
|
|
180
|
-
packaged_skills = _resource_at("claude", "skills")
|
|
181
|
-
if packaged_skills is not None and packaged_skills.is_dir():
|
|
182
|
-
skill_names = [
|
|
183
|
-
skill_dir.name
|
|
184
|
-
for skill_dir in packaged_skills.iterdir()
|
|
185
|
-
if skill_dir.is_dir() and (skill_dir / "SKILL.md").exists()
|
|
186
|
-
]
|
|
187
|
-
return skill_names
|
|
188
|
-
|
|
189
|
-
# Fallback: try framework source directory
|
|
190
|
-
current_file = Path(__file__)
|
|
191
|
-
framework_root = current_file.parent.parent.parent
|
|
192
|
-
source_skills_dir = framework_root / ".claude" / "skills"
|
|
193
|
-
|
|
194
|
-
if source_skills_dir.exists():
|
|
195
|
-
skill_names = [
|
|
196
|
-
skill_dir.name
|
|
197
|
-
for skill_dir in source_skills_dir.iterdir()
|
|
198
|
-
if skill_dir.is_dir() and (skill_dir / "SKILL.md").exists()
|
|
199
|
-
]
|
|
200
|
-
return skill_names
|
|
201
|
-
|
|
202
|
-
return []
|
|
203
|
-
|
|
204
|
-
def discover_custom_skills(self) -> list[Path]:
|
|
205
|
-
"""
|
|
206
|
-
Discover custom Skills in project's .claude/skills/ directory.
|
|
207
|
-
|
|
208
|
-
Returns:
|
|
209
|
-
List of paths to custom Skill directories
|
|
210
|
-
"""
|
|
211
|
-
if not self.skills_dir.exists():
|
|
212
|
-
return []
|
|
213
|
-
|
|
214
|
-
custom_skills = []
|
|
215
|
-
builtin_names = set(self.get_builtin_skill_names())
|
|
216
|
-
|
|
217
|
-
for skill_dir in self.skills_dir.iterdir():
|
|
218
|
-
if not skill_dir.is_dir():
|
|
219
|
-
continue
|
|
220
|
-
|
|
221
|
-
skill_file = skill_dir / "SKILL.md"
|
|
222
|
-
if not skill_file.exists():
|
|
223
|
-
continue
|
|
224
|
-
|
|
225
|
-
# Check if this is a custom Skill (not in built-in list)
|
|
226
|
-
if skill_dir.name not in builtin_names:
|
|
227
|
-
custom_skills.append(skill_dir)
|
|
228
|
-
|
|
229
|
-
return custom_skills
|
|
230
|
-
|
|
231
|
-
def _get_package_skills_dir(self) -> Path:
|
|
232
|
-
"""Get package skills directory (SYSTEM scope).
|
|
233
|
-
|
|
234
|
-
Returns:
|
|
235
|
-
Path to package skills directory
|
|
236
|
-
"""
|
|
237
|
-
from .init_project import _resource_at
|
|
238
|
-
|
|
239
|
-
packaged_skills = _resource_at("claude", "skills")
|
|
240
|
-
if packaged_skills is not None and packaged_skills.is_dir():
|
|
241
|
-
return packaged_skills
|
|
242
|
-
|
|
243
|
-
# Fallback: framework source directory
|
|
244
|
-
current_file = Path(__file__)
|
|
245
|
-
framework_root = current_file.parent.parent.parent
|
|
246
|
-
return framework_root / "tapps_agents" / "resources" / "claude" / "skills"
|
|
247
|
-
|
|
248
|
-
def _find_git_root(self, start_path: Path) -> Path:
|
|
249
|
-
"""Find git root directory starting from start_path.
|
|
250
|
-
|
|
251
|
-
Args:
|
|
252
|
-
start_path: Starting directory path
|
|
253
|
-
|
|
254
|
-
Returns:
|
|
255
|
-
Git root directory, or start_path if not in git repo
|
|
256
|
-
"""
|
|
257
|
-
current = start_path.resolve()
|
|
258
|
-
while current != current.parent:
|
|
259
|
-
if (current / ".git").exists():
|
|
260
|
-
return current
|
|
261
|
-
current = current.parent
|
|
262
|
-
return start_path
|
|
263
|
-
|
|
264
|
-
def discover_skills_multi_scope(self, project_root: Path) -> list[SkillMetadata]:
|
|
265
|
-
"""Discover skills from multiple scopes with precedence.
|
|
266
|
-
|
|
267
|
-
Scopes (in order of precedence):
|
|
268
|
-
1. REPO (current): project_root/.claude/skills/
|
|
269
|
-
2. REPO (parent): project_root/../.claude/skills/
|
|
270
|
-
3. REPO (git root): git_root/.claude/skills/
|
|
271
|
-
4. USER: ~/.tapps-agents/skills/
|
|
272
|
-
5. SYSTEM: package_skills_dir/
|
|
273
|
-
|
|
274
|
-
Precedence: REPO > USER > SYSTEM (first scope wins)
|
|
275
|
-
|
|
276
|
-
Args:
|
|
277
|
-
project_root: Project root directory
|
|
278
|
-
|
|
279
|
-
Returns:
|
|
280
|
-
List of discovered Skill metadata
|
|
281
|
-
"""
|
|
282
|
-
git_root = self._find_git_root(project_root)
|
|
283
|
-
|
|
284
|
-
scopes = [
|
|
285
|
-
# REPO scopes (highest priority)
|
|
286
|
-
project_root / ".claude" / "skills",
|
|
287
|
-
project_root.parent / ".claude" / "skills",
|
|
288
|
-
git_root / ".claude" / "skills",
|
|
289
|
-
|
|
290
|
-
# USER scope (personal skills)
|
|
291
|
-
Path.home() / ".tapps-agents" / "skills",
|
|
292
|
-
|
|
293
|
-
# SYSTEM scope (built-in, lowest priority)
|
|
294
|
-
self._get_package_skills_dir(),
|
|
295
|
-
]
|
|
296
|
-
|
|
297
|
-
discovered_skills = {}
|
|
298
|
-
for scope in scopes:
|
|
299
|
-
if scope.exists() and scope.is_dir():
|
|
300
|
-
for skill_dir in scope.iterdir():
|
|
301
|
-
if skill_dir.is_dir() and (skill_dir / "SKILL.md").exists():
|
|
302
|
-
# REPO skills override USER/SYSTEM
|
|
303
|
-
if skill_dir.name not in discovered_skills:
|
|
304
|
-
metadata = self.parse_skill_metadata(skill_dir)
|
|
305
|
-
if metadata:
|
|
306
|
-
discovered_skills[skill_dir.name] = metadata
|
|
307
|
-
|
|
308
|
-
return list(discovered_skills.values())
|
|
309
|
-
|
|
310
|
-
def parse_skill_metadata(self, skill_dir: Path) -> SkillMetadata | None:
|
|
311
|
-
"""
|
|
312
|
-
Parse Skill metadata from SKILL.md file using progressive disclosure.
|
|
313
|
-
|
|
314
|
-
Only reads first 2KB of SKILL.md (enough for YAML frontmatter).
|
|
315
|
-
Full content is loaded by Cursor when skill is invoked.
|
|
316
|
-
|
|
317
|
-
Args:
|
|
318
|
-
skill_dir: Path to Skill directory
|
|
319
|
-
|
|
320
|
-
Returns:
|
|
321
|
-
Skill metadata or None if parsing fails
|
|
322
|
-
"""
|
|
323
|
-
skill_file = skill_dir / "SKILL.md"
|
|
324
|
-
if not skill_file.exists():
|
|
325
|
-
return None
|
|
326
|
-
|
|
327
|
-
try:
|
|
328
|
-
# PROGRESSIVE DISCLOSURE: Read only first 2KB
|
|
329
|
-
# Frontmatter is always at top, typically <500 bytes
|
|
330
|
-
content = skill_file.read_text(encoding="utf-8")[:2048]
|
|
331
|
-
|
|
332
|
-
# Parse YAML frontmatter
|
|
333
|
-
frontmatter_match = re.match(
|
|
334
|
-
r"^---\s*\n(.*?)\n---\s*\n", content, re.DOTALL
|
|
335
|
-
)
|
|
336
|
-
if not frontmatter_match:
|
|
337
|
-
return None
|
|
338
|
-
|
|
339
|
-
frontmatter_text = frontmatter_match.group(1)
|
|
340
|
-
metadata = yaml.safe_load(frontmatter_text)
|
|
341
|
-
|
|
342
|
-
if not isinstance(metadata, dict):
|
|
343
|
-
return None
|
|
344
|
-
|
|
345
|
-
# Extract metadata (existing + enhanced fields)
|
|
346
|
-
name = metadata.get("name", skill_dir.name)
|
|
347
|
-
description = metadata.get("description")
|
|
348
|
-
version = metadata.get("version")
|
|
349
|
-
author = metadata.get("author")
|
|
350
|
-
category = metadata.get("category")
|
|
351
|
-
tags = metadata.get("tags", [])
|
|
352
|
-
if isinstance(tags, str):
|
|
353
|
-
# Parse comma-separated string
|
|
354
|
-
tags = [tag.strip() for tag in tags.split(",")]
|
|
355
|
-
|
|
356
|
-
allowed_tools = metadata.get("allowed-tools")
|
|
357
|
-
if isinstance(allowed_tools, str):
|
|
358
|
-
# Parse comma-separated string
|
|
359
|
-
allowed_tools = [tool.strip() for tool in allowed_tools.split(",")]
|
|
360
|
-
model_profile = metadata.get("model_profile")
|
|
361
|
-
|
|
362
|
-
# Determine if built-in or custom
|
|
363
|
-
builtin_names = set(self.get_builtin_skill_names())
|
|
364
|
-
is_builtin = name in builtin_names or skill_dir.name in builtin_names
|
|
365
|
-
is_custom = not is_builtin
|
|
366
|
-
|
|
367
|
-
return SkillMetadata(
|
|
368
|
-
name=name,
|
|
369
|
-
path=skill_dir,
|
|
370
|
-
is_builtin=is_builtin,
|
|
371
|
-
is_custom=is_custom,
|
|
372
|
-
description=description,
|
|
373
|
-
version=version,
|
|
374
|
-
author=author,
|
|
375
|
-
category=category,
|
|
376
|
-
tags=tags,
|
|
377
|
-
allowed_tools=allowed_tools,
|
|
378
|
-
model_profile=model_profile,
|
|
379
|
-
)
|
|
380
|
-
except Exception:
|
|
381
|
-
# Parsing failed, return None
|
|
382
|
-
return None
|
|
383
|
-
|
|
384
|
-
def load_custom_skills(self, validate: bool = True) -> list[SkillMetadata]:
|
|
385
|
-
"""
|
|
386
|
-
Discover and load all custom Skills.
|
|
387
|
-
|
|
388
|
-
Args:
|
|
389
|
-
validate: If True, validate Skills before loading (default: True)
|
|
390
|
-
|
|
391
|
-
Returns:
|
|
392
|
-
List of custom Skill metadata
|
|
393
|
-
"""
|
|
394
|
-
from .skill_validator import SkillValidator
|
|
395
|
-
|
|
396
|
-
custom_skill_dirs = self.discover_custom_skills()
|
|
397
|
-
skills = []
|
|
398
|
-
|
|
399
|
-
validator = SkillValidator(project_root=self.project_root) if validate else None
|
|
400
|
-
|
|
401
|
-
for skill_dir in custom_skill_dirs:
|
|
402
|
-
# Validate if requested
|
|
403
|
-
if validator:
|
|
404
|
-
validation_result = validator.validate_skill(skill_dir)
|
|
405
|
-
if validation_result.has_errors():
|
|
406
|
-
# Skip invalid Skills but log warning
|
|
407
|
-
import logging
|
|
408
|
-
|
|
409
|
-
logger = logging.getLogger(__name__)
|
|
410
|
-
logger.warning(
|
|
411
|
-
f"Skipping invalid Skill '{skill_dir.name}': "
|
|
412
|
-
f"{validation_result.get_error_summary()}"
|
|
413
|
-
)
|
|
414
|
-
continue
|
|
415
|
-
|
|
416
|
-
metadata = self.parse_skill_metadata(skill_dir)
|
|
417
|
-
if metadata:
|
|
418
|
-
skills.append(metadata)
|
|
419
|
-
|
|
420
|
-
return skills
|
|
421
|
-
|
|
422
|
-
def load_all_skills(self) -> list[SkillMetadata]:
|
|
423
|
-
"""
|
|
424
|
-
Load both built-in and custom Skills.
|
|
425
|
-
|
|
426
|
-
Returns:
|
|
427
|
-
List of all Skill metadata
|
|
428
|
-
"""
|
|
429
|
-
all_skills = []
|
|
430
|
-
|
|
431
|
-
# Load built-in Skills
|
|
432
|
-
builtin_names = self.get_builtin_skill_names()
|
|
433
|
-
for skill_name in builtin_names:
|
|
434
|
-
skill_dir = self.skills_dir / skill_name
|
|
435
|
-
if skill_dir.exists() and (skill_dir / "SKILL.md").exists():
|
|
436
|
-
metadata = self.parse_skill_metadata(skill_dir)
|
|
437
|
-
if metadata:
|
|
438
|
-
all_skills.append(metadata)
|
|
439
|
-
|
|
440
|
-
# Load custom Skills
|
|
441
|
-
custom_skills = self.load_custom_skills()
|
|
442
|
-
all_skills.extend(custom_skills)
|
|
443
|
-
|
|
444
|
-
return all_skills
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
# Global registry instance
|
|
448
|
-
_global_registry: SkillRegistry | None = None
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
def get_skill_registry() -> SkillRegistry:
|
|
452
|
-
"""
|
|
453
|
-
Get global Skill registry instance.
|
|
454
|
-
|
|
455
|
-
Returns:
|
|
456
|
-
Global Skill registry
|
|
457
|
-
"""
|
|
458
|
-
global _global_registry
|
|
459
|
-
if _global_registry is None:
|
|
460
|
-
_global_registry = SkillRegistry()
|
|
461
|
-
return _global_registry
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
def initialize_skill_registry(project_root: Path | None = None) -> SkillRegistry:
|
|
465
|
-
"""
|
|
466
|
-
Initialize Skill registry with multi-scope discovery.
|
|
467
|
-
|
|
468
|
-
Args:
|
|
469
|
-
project_root: Project root directory (defaults to current directory)
|
|
470
|
-
|
|
471
|
-
Returns:
|
|
472
|
-
Initialized Skill registry
|
|
473
|
-
"""
|
|
474
|
-
registry = get_skill_registry()
|
|
475
|
-
loader = CustomSkillLoader(project_root=project_root)
|
|
476
|
-
|
|
477
|
-
# Register built-in Skill names (for is_builtin detection)
|
|
478
|
-
builtin_names = loader.get_builtin_skill_names()
|
|
479
|
-
registry.register_builtin_skills(builtin_names)
|
|
480
|
-
|
|
481
|
-
# Use multi-scope discovery instead of load_all_skills()
|
|
482
|
-
if project_root is None:
|
|
483
|
-
project_root = Path.cwd()
|
|
484
|
-
all_skills = loader.discover_skills_multi_scope(project_root)
|
|
485
|
-
|
|
486
|
-
# Register all discovered skills
|
|
487
|
-
for skill in all_skills:
|
|
488
|
-
priority = "custom" if skill.is_custom else "builtin"
|
|
489
|
-
registry.register_skill(skill, priority=priority)
|
|
490
|
-
|
|
491
|
-
return registry
|
|
492
|
-
|
|
1
|
+
"""
|
|
2
|
+
Custom Skill Loader and Registry.
|
|
3
|
+
|
|
4
|
+
Discovers, loads, and manages custom Skills alongside built-in Skills.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
import yaml
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class SkillMetadata:
|
|
18
|
+
"""Metadata for a Skill with enhanced fields."""
|
|
19
|
+
|
|
20
|
+
name: str
|
|
21
|
+
path: Path
|
|
22
|
+
is_builtin: bool
|
|
23
|
+
is_custom: bool
|
|
24
|
+
description: str | None = None
|
|
25
|
+
allowed_tools: list[str] | None = None
|
|
26
|
+
model_profile: str | None = None
|
|
27
|
+
version: str | None = None
|
|
28
|
+
# Enhanced metadata fields
|
|
29
|
+
author: str | None = None
|
|
30
|
+
category: str | None = None
|
|
31
|
+
tags: list[str] = field(default_factory=list)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class SkillRegistry:
|
|
35
|
+
"""Registry for managing loaded Skills."""
|
|
36
|
+
|
|
37
|
+
def __init__(self):
|
|
38
|
+
"""Initialize empty registry."""
|
|
39
|
+
self._skills: dict[str, SkillMetadata] = {}
|
|
40
|
+
self._builtin_skill_names: set[str] = set()
|
|
41
|
+
|
|
42
|
+
def register_builtin_skills(self, skill_names: list[str]) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Register list of built-in Skill names.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
skill_names: List of built-in Skill names
|
|
48
|
+
"""
|
|
49
|
+
self._builtin_skill_names = set(skill_names)
|
|
50
|
+
|
|
51
|
+
def register_skill(
|
|
52
|
+
self, skill: SkillMetadata, priority: str = "custom"
|
|
53
|
+
) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Register a Skill in the registry.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
skill: Skill metadata
|
|
59
|
+
priority: Priority level ("custom" or "builtin")
|
|
60
|
+
"""
|
|
61
|
+
# Custom Skills override built-in Skills with the same name
|
|
62
|
+
if skill.name in self._skills:
|
|
63
|
+
existing = self._skills[skill.name]
|
|
64
|
+
if existing.is_builtin and skill.is_custom:
|
|
65
|
+
# Custom Skill overrides built-in
|
|
66
|
+
self._skills[skill.name] = skill
|
|
67
|
+
elif existing.is_custom and skill.is_builtin:
|
|
68
|
+
# Built-in doesn't override custom (keep existing)
|
|
69
|
+
pass
|
|
70
|
+
else:
|
|
71
|
+
# Same type, update
|
|
72
|
+
self._skills[skill.name] = skill
|
|
73
|
+
else:
|
|
74
|
+
self._skills[skill.name] = skill
|
|
75
|
+
|
|
76
|
+
def get_skill(self, name: str) -> SkillMetadata | None:
|
|
77
|
+
"""
|
|
78
|
+
Get Skill by name.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
name: Skill name
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Skill metadata or None if not found
|
|
85
|
+
"""
|
|
86
|
+
return self._skills.get(name)
|
|
87
|
+
|
|
88
|
+
def list_skills(self, include_builtin: bool = True, include_custom: bool = True) -> list[SkillMetadata]:
|
|
89
|
+
"""
|
|
90
|
+
List all registered Skills.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
include_builtin: Include built-in Skills
|
|
94
|
+
include_custom: Include custom Skills
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
List of Skill metadata
|
|
98
|
+
"""
|
|
99
|
+
skills = []
|
|
100
|
+
for skill in self._skills.values():
|
|
101
|
+
if skill.is_builtin and include_builtin:
|
|
102
|
+
skills.append(skill)
|
|
103
|
+
elif skill.is_custom and include_custom:
|
|
104
|
+
skills.append(skill)
|
|
105
|
+
return skills
|
|
106
|
+
|
|
107
|
+
def get_custom_skills(self) -> list[SkillMetadata]:
|
|
108
|
+
"""
|
|
109
|
+
Get all custom Skills.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
List of custom Skill metadata
|
|
113
|
+
"""
|
|
114
|
+
return [skill for skill in self._skills.values() if skill.is_custom]
|
|
115
|
+
|
|
116
|
+
def get_builtin_skills(self) -> list[SkillMetadata]:
|
|
117
|
+
"""
|
|
118
|
+
Get all built-in Skills.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
List of built-in Skill metadata
|
|
122
|
+
"""
|
|
123
|
+
return [skill for skill in self._skills.values() if skill.is_builtin]
|
|
124
|
+
|
|
125
|
+
def has_skill(self, name: str) -> bool:
|
|
126
|
+
"""
|
|
127
|
+
Check if Skill is registered.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
name: Skill name
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
True if Skill is registered
|
|
134
|
+
"""
|
|
135
|
+
return name in self._skills
|
|
136
|
+
|
|
137
|
+
def get_conflicts(self) -> list[tuple[str, SkillMetadata, SkillMetadata]]:
|
|
138
|
+
"""
|
|
139
|
+
Get name conflicts between custom and built-in Skills.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
List of tuples (name, custom_skill, builtin_skill)
|
|
143
|
+
"""
|
|
144
|
+
conflicts = []
|
|
145
|
+
custom_skills = {s.name: s for s in self.get_custom_skills()}
|
|
146
|
+
builtin_skills = {s.name: s for s in self.get_builtin_skills()}
|
|
147
|
+
|
|
148
|
+
for name in custom_skills:
|
|
149
|
+
if name in builtin_skills:
|
|
150
|
+
conflicts.append((name, custom_skills[name], builtin_skills[name]))
|
|
151
|
+
|
|
152
|
+
return conflicts
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class CustomSkillLoader:
|
|
156
|
+
"""Loader for discovering and loading custom Skills."""
|
|
157
|
+
|
|
158
|
+
def __init__(self, project_root: Path | None = None):
|
|
159
|
+
"""
|
|
160
|
+
Initialize loader.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
project_root: Project root directory (defaults to current directory)
|
|
164
|
+
"""
|
|
165
|
+
if project_root is None:
|
|
166
|
+
project_root = Path.cwd()
|
|
167
|
+
self.project_root = project_root
|
|
168
|
+
self.skills_dir = project_root / ".claude" / "skills"
|
|
169
|
+
|
|
170
|
+
def get_builtin_skill_names(self) -> list[str]:
|
|
171
|
+
"""
|
|
172
|
+
Get list of built-in Skill names from framework.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
List of built-in Skill names
|
|
176
|
+
"""
|
|
177
|
+
# Try to get from packaged resources
|
|
178
|
+
from .init_project import _resource_at
|
|
179
|
+
|
|
180
|
+
packaged_skills = _resource_at("claude", "skills")
|
|
181
|
+
if packaged_skills is not None and packaged_skills.is_dir():
|
|
182
|
+
skill_names = [
|
|
183
|
+
skill_dir.name
|
|
184
|
+
for skill_dir in packaged_skills.iterdir()
|
|
185
|
+
if skill_dir.is_dir() and (skill_dir / "SKILL.md").exists()
|
|
186
|
+
]
|
|
187
|
+
return skill_names
|
|
188
|
+
|
|
189
|
+
# Fallback: try framework source directory
|
|
190
|
+
current_file = Path(__file__)
|
|
191
|
+
framework_root = current_file.parent.parent.parent
|
|
192
|
+
source_skills_dir = framework_root / ".claude" / "skills"
|
|
193
|
+
|
|
194
|
+
if source_skills_dir.exists():
|
|
195
|
+
skill_names = [
|
|
196
|
+
skill_dir.name
|
|
197
|
+
for skill_dir in source_skills_dir.iterdir()
|
|
198
|
+
if skill_dir.is_dir() and (skill_dir / "SKILL.md").exists()
|
|
199
|
+
]
|
|
200
|
+
return skill_names
|
|
201
|
+
|
|
202
|
+
return []
|
|
203
|
+
|
|
204
|
+
def discover_custom_skills(self) -> list[Path]:
|
|
205
|
+
"""
|
|
206
|
+
Discover custom Skills in project's .claude/skills/ directory.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
List of paths to custom Skill directories
|
|
210
|
+
"""
|
|
211
|
+
if not self.skills_dir.exists():
|
|
212
|
+
return []
|
|
213
|
+
|
|
214
|
+
custom_skills = []
|
|
215
|
+
builtin_names = set(self.get_builtin_skill_names())
|
|
216
|
+
|
|
217
|
+
for skill_dir in self.skills_dir.iterdir():
|
|
218
|
+
if not skill_dir.is_dir():
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
skill_file = skill_dir / "SKILL.md"
|
|
222
|
+
if not skill_file.exists():
|
|
223
|
+
continue
|
|
224
|
+
|
|
225
|
+
# Check if this is a custom Skill (not in built-in list)
|
|
226
|
+
if skill_dir.name not in builtin_names:
|
|
227
|
+
custom_skills.append(skill_dir)
|
|
228
|
+
|
|
229
|
+
return custom_skills
|
|
230
|
+
|
|
231
|
+
def _get_package_skills_dir(self) -> Path:
|
|
232
|
+
"""Get package skills directory (SYSTEM scope).
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
Path to package skills directory
|
|
236
|
+
"""
|
|
237
|
+
from .init_project import _resource_at
|
|
238
|
+
|
|
239
|
+
packaged_skills = _resource_at("claude", "skills")
|
|
240
|
+
if packaged_skills is not None and packaged_skills.is_dir():
|
|
241
|
+
return packaged_skills
|
|
242
|
+
|
|
243
|
+
# Fallback: framework source directory
|
|
244
|
+
current_file = Path(__file__)
|
|
245
|
+
framework_root = current_file.parent.parent.parent
|
|
246
|
+
return framework_root / "tapps_agents" / "resources" / "claude" / "skills"
|
|
247
|
+
|
|
248
|
+
def _find_git_root(self, start_path: Path) -> Path:
|
|
249
|
+
"""Find git root directory starting from start_path.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
start_path: Starting directory path
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
Git root directory, or start_path if not in git repo
|
|
256
|
+
"""
|
|
257
|
+
current = start_path.resolve()
|
|
258
|
+
while current != current.parent:
|
|
259
|
+
if (current / ".git").exists():
|
|
260
|
+
return current
|
|
261
|
+
current = current.parent
|
|
262
|
+
return start_path
|
|
263
|
+
|
|
264
|
+
def discover_skills_multi_scope(self, project_root: Path) -> list[SkillMetadata]:
|
|
265
|
+
"""Discover skills from multiple scopes with precedence.
|
|
266
|
+
|
|
267
|
+
Scopes (in order of precedence):
|
|
268
|
+
1. REPO (current): project_root/.claude/skills/
|
|
269
|
+
2. REPO (parent): project_root/../.claude/skills/
|
|
270
|
+
3. REPO (git root): git_root/.claude/skills/
|
|
271
|
+
4. USER: ~/.tapps-agents/skills/
|
|
272
|
+
5. SYSTEM: package_skills_dir/
|
|
273
|
+
|
|
274
|
+
Precedence: REPO > USER > SYSTEM (first scope wins)
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
project_root: Project root directory
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
List of discovered Skill metadata
|
|
281
|
+
"""
|
|
282
|
+
git_root = self._find_git_root(project_root)
|
|
283
|
+
|
|
284
|
+
scopes = [
|
|
285
|
+
# REPO scopes (highest priority)
|
|
286
|
+
project_root / ".claude" / "skills",
|
|
287
|
+
project_root.parent / ".claude" / "skills",
|
|
288
|
+
git_root / ".claude" / "skills",
|
|
289
|
+
|
|
290
|
+
# USER scope (personal skills)
|
|
291
|
+
Path.home() / ".tapps-agents" / "skills",
|
|
292
|
+
|
|
293
|
+
# SYSTEM scope (built-in, lowest priority)
|
|
294
|
+
self._get_package_skills_dir(),
|
|
295
|
+
]
|
|
296
|
+
|
|
297
|
+
discovered_skills = {}
|
|
298
|
+
for scope in scopes:
|
|
299
|
+
if scope.exists() and scope.is_dir():
|
|
300
|
+
for skill_dir in scope.iterdir():
|
|
301
|
+
if skill_dir.is_dir() and (skill_dir / "SKILL.md").exists():
|
|
302
|
+
# REPO skills override USER/SYSTEM
|
|
303
|
+
if skill_dir.name not in discovered_skills:
|
|
304
|
+
metadata = self.parse_skill_metadata(skill_dir)
|
|
305
|
+
if metadata:
|
|
306
|
+
discovered_skills[skill_dir.name] = metadata
|
|
307
|
+
|
|
308
|
+
return list(discovered_skills.values())
|
|
309
|
+
|
|
310
|
+
def parse_skill_metadata(self, skill_dir: Path) -> SkillMetadata | None:
|
|
311
|
+
"""
|
|
312
|
+
Parse Skill metadata from SKILL.md file using progressive disclosure.
|
|
313
|
+
|
|
314
|
+
Only reads first 2KB of SKILL.md (enough for YAML frontmatter).
|
|
315
|
+
Full content is loaded by Cursor when skill is invoked.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
skill_dir: Path to Skill directory
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
Skill metadata or None if parsing fails
|
|
322
|
+
"""
|
|
323
|
+
skill_file = skill_dir / "SKILL.md"
|
|
324
|
+
if not skill_file.exists():
|
|
325
|
+
return None
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
# PROGRESSIVE DISCLOSURE: Read only first 2KB
|
|
329
|
+
# Frontmatter is always at top, typically <500 bytes
|
|
330
|
+
content = skill_file.read_text(encoding="utf-8")[:2048]
|
|
331
|
+
|
|
332
|
+
# Parse YAML frontmatter
|
|
333
|
+
frontmatter_match = re.match(
|
|
334
|
+
r"^---\s*\n(.*?)\n---\s*\n", content, re.DOTALL
|
|
335
|
+
)
|
|
336
|
+
if not frontmatter_match:
|
|
337
|
+
return None
|
|
338
|
+
|
|
339
|
+
frontmatter_text = frontmatter_match.group(1)
|
|
340
|
+
metadata = yaml.safe_load(frontmatter_text)
|
|
341
|
+
|
|
342
|
+
if not isinstance(metadata, dict):
|
|
343
|
+
return None
|
|
344
|
+
|
|
345
|
+
# Extract metadata (existing + enhanced fields)
|
|
346
|
+
name = metadata.get("name", skill_dir.name)
|
|
347
|
+
description = metadata.get("description")
|
|
348
|
+
version = metadata.get("version")
|
|
349
|
+
author = metadata.get("author")
|
|
350
|
+
category = metadata.get("category")
|
|
351
|
+
tags = metadata.get("tags", [])
|
|
352
|
+
if isinstance(tags, str):
|
|
353
|
+
# Parse comma-separated string
|
|
354
|
+
tags = [tag.strip() for tag in tags.split(",")]
|
|
355
|
+
|
|
356
|
+
allowed_tools = metadata.get("allowed-tools")
|
|
357
|
+
if isinstance(allowed_tools, str):
|
|
358
|
+
# Parse comma-separated string
|
|
359
|
+
allowed_tools = [tool.strip() for tool in allowed_tools.split(",")]
|
|
360
|
+
model_profile = metadata.get("model_profile")
|
|
361
|
+
|
|
362
|
+
# Determine if built-in or custom
|
|
363
|
+
builtin_names = set(self.get_builtin_skill_names())
|
|
364
|
+
is_builtin = name in builtin_names or skill_dir.name in builtin_names
|
|
365
|
+
is_custom = not is_builtin
|
|
366
|
+
|
|
367
|
+
return SkillMetadata(
|
|
368
|
+
name=name,
|
|
369
|
+
path=skill_dir,
|
|
370
|
+
is_builtin=is_builtin,
|
|
371
|
+
is_custom=is_custom,
|
|
372
|
+
description=description,
|
|
373
|
+
version=version,
|
|
374
|
+
author=author,
|
|
375
|
+
category=category,
|
|
376
|
+
tags=tags,
|
|
377
|
+
allowed_tools=allowed_tools,
|
|
378
|
+
model_profile=model_profile,
|
|
379
|
+
)
|
|
380
|
+
except Exception:
|
|
381
|
+
# Parsing failed, return None
|
|
382
|
+
return None
|
|
383
|
+
|
|
384
|
+
def load_custom_skills(self, validate: bool = True) -> list[SkillMetadata]:
|
|
385
|
+
"""
|
|
386
|
+
Discover and load all custom Skills.
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
validate: If True, validate Skills before loading (default: True)
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
List of custom Skill metadata
|
|
393
|
+
"""
|
|
394
|
+
from .skill_validator import SkillValidator
|
|
395
|
+
|
|
396
|
+
custom_skill_dirs = self.discover_custom_skills()
|
|
397
|
+
skills = []
|
|
398
|
+
|
|
399
|
+
validator = SkillValidator(project_root=self.project_root) if validate else None
|
|
400
|
+
|
|
401
|
+
for skill_dir in custom_skill_dirs:
|
|
402
|
+
# Validate if requested
|
|
403
|
+
if validator:
|
|
404
|
+
validation_result = validator.validate_skill(skill_dir)
|
|
405
|
+
if validation_result.has_errors():
|
|
406
|
+
# Skip invalid Skills but log warning
|
|
407
|
+
import logging
|
|
408
|
+
|
|
409
|
+
logger = logging.getLogger(__name__)
|
|
410
|
+
logger.warning(
|
|
411
|
+
f"Skipping invalid Skill '{skill_dir.name}': "
|
|
412
|
+
f"{validation_result.get_error_summary()}"
|
|
413
|
+
)
|
|
414
|
+
continue
|
|
415
|
+
|
|
416
|
+
metadata = self.parse_skill_metadata(skill_dir)
|
|
417
|
+
if metadata:
|
|
418
|
+
skills.append(metadata)
|
|
419
|
+
|
|
420
|
+
return skills
|
|
421
|
+
|
|
422
|
+
def load_all_skills(self) -> list[SkillMetadata]:
|
|
423
|
+
"""
|
|
424
|
+
Load both built-in and custom Skills.
|
|
425
|
+
|
|
426
|
+
Returns:
|
|
427
|
+
List of all Skill metadata
|
|
428
|
+
"""
|
|
429
|
+
all_skills = []
|
|
430
|
+
|
|
431
|
+
# Load built-in Skills
|
|
432
|
+
builtin_names = self.get_builtin_skill_names()
|
|
433
|
+
for skill_name in builtin_names:
|
|
434
|
+
skill_dir = self.skills_dir / skill_name
|
|
435
|
+
if skill_dir.exists() and (skill_dir / "SKILL.md").exists():
|
|
436
|
+
metadata = self.parse_skill_metadata(skill_dir)
|
|
437
|
+
if metadata:
|
|
438
|
+
all_skills.append(metadata)
|
|
439
|
+
|
|
440
|
+
# Load custom Skills
|
|
441
|
+
custom_skills = self.load_custom_skills()
|
|
442
|
+
all_skills.extend(custom_skills)
|
|
443
|
+
|
|
444
|
+
return all_skills
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
# Global registry instance
|
|
448
|
+
_global_registry: SkillRegistry | None = None
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def get_skill_registry() -> SkillRegistry:
|
|
452
|
+
"""
|
|
453
|
+
Get global Skill registry instance.
|
|
454
|
+
|
|
455
|
+
Returns:
|
|
456
|
+
Global Skill registry
|
|
457
|
+
"""
|
|
458
|
+
global _global_registry
|
|
459
|
+
if _global_registry is None:
|
|
460
|
+
_global_registry = SkillRegistry()
|
|
461
|
+
return _global_registry
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def initialize_skill_registry(project_root: Path | None = None) -> SkillRegistry:
|
|
465
|
+
"""
|
|
466
|
+
Initialize Skill registry with multi-scope discovery.
|
|
467
|
+
|
|
468
|
+
Args:
|
|
469
|
+
project_root: Project root directory (defaults to current directory)
|
|
470
|
+
|
|
471
|
+
Returns:
|
|
472
|
+
Initialized Skill registry
|
|
473
|
+
"""
|
|
474
|
+
registry = get_skill_registry()
|
|
475
|
+
loader = CustomSkillLoader(project_root=project_root)
|
|
476
|
+
|
|
477
|
+
# Register built-in Skill names (for is_builtin detection)
|
|
478
|
+
builtin_names = loader.get_builtin_skill_names()
|
|
479
|
+
registry.register_builtin_skills(builtin_names)
|
|
480
|
+
|
|
481
|
+
# Use multi-scope discovery instead of load_all_skills()
|
|
482
|
+
if project_root is None:
|
|
483
|
+
project_root = Path.cwd()
|
|
484
|
+
all_skills = loader.discover_skills_multi_scope(project_root)
|
|
485
|
+
|
|
486
|
+
# Register all discovered skills
|
|
487
|
+
for skill in all_skills:
|
|
488
|
+
priority = "custom" if skill.is_custom else "builtin"
|
|
489
|
+
registry.register_skill(skill, priority=priority)
|
|
490
|
+
|
|
491
|
+
return registry
|
|
492
|
+
|