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,630 +1,630 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Context7 Review Enhancer - Integrates Context7 lookups into review workflow.
|
|
3
|
-
|
|
4
|
-
Provides library-specific recommendations and pattern guidance from Context7.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import asyncio
|
|
8
|
-
import logging
|
|
9
|
-
from dataclasses import dataclass
|
|
10
|
-
from typing import Optional
|
|
11
|
-
|
|
12
|
-
from ...context7.agent_integration import Context7AgentHelper
|
|
13
|
-
from .pattern_detector import PatternMatch
|
|
14
|
-
|
|
15
|
-
logger = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@dataclass
|
|
19
|
-
class LibraryRecommendation:
|
|
20
|
-
"""Library-specific recommendations from Context7."""
|
|
21
|
-
library_name: str
|
|
22
|
-
best_practices: list[str]
|
|
23
|
-
common_mistakes: list[str]
|
|
24
|
-
usage_examples: list[str]
|
|
25
|
-
source: str # "context7" or "cache"
|
|
26
|
-
cached: bool = False
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@dataclass
|
|
30
|
-
class PatternGuidance:
|
|
31
|
-
"""Pattern-specific guidance from Context7."""
|
|
32
|
-
pattern_name: str
|
|
33
|
-
recommendations: list[str]
|
|
34
|
-
best_practices: list[str]
|
|
35
|
-
source: str # "context7" or "cache"
|
|
36
|
-
cached: bool = False
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class Context7ReviewEnhancer:
|
|
40
|
-
"""
|
|
41
|
-
Enhances review with Context7 library documentation and pattern guidance.
|
|
42
|
-
|
|
43
|
-
Responsibilities:
|
|
44
|
-
- Lookup library documentation from Context7
|
|
45
|
-
- Extract best practices and common mistakes
|
|
46
|
-
- Provide pattern-specific guidance
|
|
47
|
-
- Cache responses to avoid duplicate lookups
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
def __init__(
|
|
51
|
-
self,
|
|
52
|
-
context7_helper: Context7AgentHelper,
|
|
53
|
-
timeout: int = 30,
|
|
54
|
-
cache_enabled: bool = True
|
|
55
|
-
):
|
|
56
|
-
"""
|
|
57
|
-
Initialize Context7 review enhancer.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
context7_helper: Context7AgentHelper instance
|
|
61
|
-
timeout: Timeout for Context7 lookups (seconds)
|
|
62
|
-
cache_enabled: Whether to cache Context7 responses
|
|
63
|
-
"""
|
|
64
|
-
self.context7_helper = context7_helper
|
|
65
|
-
self.timeout = timeout
|
|
66
|
-
self.cache_enabled = cache_enabled
|
|
67
|
-
self._cache: dict[str, LibraryRecommendation | PatternGuidance] = {}
|
|
68
|
-
|
|
69
|
-
async def get_library_recommendations(
|
|
70
|
-
self,
|
|
71
|
-
libraries: list[str]
|
|
72
|
-
) -> dict[str, LibraryRecommendation]:
|
|
73
|
-
"""
|
|
74
|
-
Get Context7 recommendations for detected libraries.
|
|
75
|
-
|
|
76
|
-
Args:
|
|
77
|
-
libraries: List of library names
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
Dictionary mapping library names to LibraryRecommendation objects
|
|
81
|
-
"""
|
|
82
|
-
if not libraries:
|
|
83
|
-
return {}
|
|
84
|
-
|
|
85
|
-
recommendations = {}
|
|
86
|
-
|
|
87
|
-
# Batch lookups with timeout
|
|
88
|
-
tasks = [
|
|
89
|
-
self._lookup_library_docs(lib) for lib in libraries
|
|
90
|
-
]
|
|
91
|
-
|
|
92
|
-
try:
|
|
93
|
-
results = await asyncio.wait_for(
|
|
94
|
-
asyncio.gather(*tasks, return_exceptions=True),
|
|
95
|
-
timeout=self.timeout * len(libraries) # Total timeout for all lookups
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
for lib, result in zip(libraries, results):
|
|
99
|
-
if isinstance(result, Exception):
|
|
100
|
-
logger.warning(f"Context7 lookup failed for library {lib}: {result}")
|
|
101
|
-
continue
|
|
102
|
-
|
|
103
|
-
if result:
|
|
104
|
-
recommendations[lib] = result
|
|
105
|
-
except asyncio.TimeoutError:
|
|
106
|
-
logger.warning(f"Context7 lookup timeout for libraries: {libraries}")
|
|
107
|
-
except Exception as e:
|
|
108
|
-
logger.warning(f"Context7 lookup error: {e}")
|
|
109
|
-
|
|
110
|
-
return recommendations
|
|
111
|
-
|
|
112
|
-
async def get_pattern_guidance(
|
|
113
|
-
self,
|
|
114
|
-
patterns: list[PatternMatch]
|
|
115
|
-
) -> dict[str, PatternGuidance]:
|
|
116
|
-
"""
|
|
117
|
-
Get Context7 guidance for detected patterns.
|
|
118
|
-
|
|
119
|
-
Args:
|
|
120
|
-
patterns: List of PatternMatch objects
|
|
121
|
-
|
|
122
|
-
Returns:
|
|
123
|
-
Dictionary mapping pattern names to PatternGuidance objects
|
|
124
|
-
"""
|
|
125
|
-
if not patterns:
|
|
126
|
-
return {}
|
|
127
|
-
|
|
128
|
-
guidance = {}
|
|
129
|
-
|
|
130
|
-
# Lookup guidance for each pattern
|
|
131
|
-
for pattern in patterns:
|
|
132
|
-
try:
|
|
133
|
-
result = await asyncio.wait_for(
|
|
134
|
-
self._lookup_pattern_docs(pattern),
|
|
135
|
-
timeout=self.timeout
|
|
136
|
-
)
|
|
137
|
-
if result:
|
|
138
|
-
guidance[pattern.pattern_name] = result
|
|
139
|
-
except asyncio.TimeoutError:
|
|
140
|
-
logger.warning(f"Context7 lookup timeout for pattern: {pattern.pattern_name}")
|
|
141
|
-
except Exception as e:
|
|
142
|
-
logger.warning(f"Context7 lookup error for pattern {pattern.pattern_name}: {e}")
|
|
143
|
-
|
|
144
|
-
return guidance
|
|
145
|
-
|
|
146
|
-
async def _lookup_library_docs(
|
|
147
|
-
self,
|
|
148
|
-
library: str
|
|
149
|
-
) -> Optional[LibraryRecommendation]:
|
|
150
|
-
"""
|
|
151
|
-
Lookup library documentation from Context7.
|
|
152
|
-
|
|
153
|
-
Args:
|
|
154
|
-
library: Library name
|
|
155
|
-
|
|
156
|
-
Returns:
|
|
157
|
-
LibraryRecommendation if successful, None otherwise
|
|
158
|
-
"""
|
|
159
|
-
# Check cache first
|
|
160
|
-
cache_key = f"library:{library}"
|
|
161
|
-
if self.cache_enabled and cache_key in self._cache:
|
|
162
|
-
cached = self._cache[cache_key]
|
|
163
|
-
if isinstance(cached, LibraryRecommendation):
|
|
164
|
-
return cached
|
|
165
|
-
|
|
166
|
-
try:
|
|
167
|
-
# Use Context7AgentHelper to lookup docs
|
|
168
|
-
# Try multiple topics to get comprehensive information
|
|
169
|
-
topics = ["best-practices", "common-mistakes", "usage", "examples"]
|
|
170
|
-
|
|
171
|
-
all_content = []
|
|
172
|
-
for topic in topics:
|
|
173
|
-
try:
|
|
174
|
-
docs = await asyncio.wait_for(
|
|
175
|
-
self.context7_helper.get_documentation(
|
|
176
|
-
library=library,
|
|
177
|
-
topic=topic,
|
|
178
|
-
use_fuzzy_match=True
|
|
179
|
-
),
|
|
180
|
-
timeout=self.timeout
|
|
181
|
-
)
|
|
182
|
-
if docs and docs.get("content"):
|
|
183
|
-
all_content.append(docs["content"])
|
|
184
|
-
except asyncio.TimeoutError:
|
|
185
|
-
logger.debug(f"Context7 lookup timeout for {library} topic {topic}")
|
|
186
|
-
except Exception as e:
|
|
187
|
-
logger.debug(f"Context7 lookup error for {library} topic {topic}: {e}")
|
|
188
|
-
|
|
189
|
-
if not all_content:
|
|
190
|
-
# Try without topic (general documentation)
|
|
191
|
-
try:
|
|
192
|
-
docs = await asyncio.wait_for(
|
|
193
|
-
self.context7_helper.get_documentation(
|
|
194
|
-
library=library,
|
|
195
|
-
topic=None,
|
|
196
|
-
use_fuzzy_match=True
|
|
197
|
-
),
|
|
198
|
-
timeout=self.timeout
|
|
199
|
-
)
|
|
200
|
-
if docs and docs.get("content"):
|
|
201
|
-
all_content.append(docs["content"])
|
|
202
|
-
except Exception as e:
|
|
203
|
-
logger.debug(f"Context7 lookup error for {library}: {e}")
|
|
204
|
-
|
|
205
|
-
if not all_content:
|
|
206
|
-
return None
|
|
207
|
-
|
|
208
|
-
# Combine all content
|
|
209
|
-
combined_content = "\n\n".join(all_content)
|
|
210
|
-
|
|
211
|
-
# Extract structured data from Context7 response
|
|
212
|
-
recommendation = LibraryRecommendation(
|
|
213
|
-
library_name=library,
|
|
214
|
-
best_practices=self._extract_best_practices(combined_content),
|
|
215
|
-
common_mistakes=self._extract_common_mistakes(combined_content),
|
|
216
|
-
usage_examples=self._extract_examples(combined_content),
|
|
217
|
-
source="context7"
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
# Cache result
|
|
221
|
-
if self.cache_enabled:
|
|
222
|
-
self._cache[cache_key] = recommendation
|
|
223
|
-
|
|
224
|
-
return recommendation
|
|
225
|
-
|
|
226
|
-
except asyncio.TimeoutError:
|
|
227
|
-
logger.warning(f"Context7 lookup timeout for library: {library}")
|
|
228
|
-
return None
|
|
229
|
-
except Exception as e:
|
|
230
|
-
logger.warning(f"Context7 lookup failed for library {library}: {e}")
|
|
231
|
-
return None
|
|
232
|
-
|
|
233
|
-
async def _lookup_pattern_docs(
|
|
234
|
-
self,
|
|
235
|
-
pattern: PatternMatch
|
|
236
|
-
) -> Optional[PatternGuidance]:
|
|
237
|
-
"""
|
|
238
|
-
Lookup pattern guidance from Context7.
|
|
239
|
-
|
|
240
|
-
Args:
|
|
241
|
-
pattern: PatternMatch object
|
|
242
|
-
|
|
243
|
-
Returns:
|
|
244
|
-
PatternGuidance if successful, None otherwise
|
|
245
|
-
"""
|
|
246
|
-
# Check cache first
|
|
247
|
-
cache_key = f"pattern:{pattern.pattern_name}"
|
|
248
|
-
if self.cache_enabled and cache_key in self._cache:
|
|
249
|
-
cached = self._cache[cache_key]
|
|
250
|
-
if isinstance(cached, PatternGuidance):
|
|
251
|
-
return cached
|
|
252
|
-
|
|
253
|
-
try:
|
|
254
|
-
# Lookup pattern-specific documentation
|
|
255
|
-
# Map pattern names to Context7 search terms
|
|
256
|
-
search_terms = {
|
|
257
|
-
"rag_system": "RAG retrieval augmented generation",
|
|
258
|
-
"multi_agent": "multi-agent expert systems",
|
|
259
|
-
"weighted_decision": "weighted decision making"
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
search_term = search_terms.get(pattern.pattern_name, pattern.pattern_name)
|
|
263
|
-
|
|
264
|
-
docs = await asyncio.wait_for(
|
|
265
|
-
self.context7_helper.get_documentation(
|
|
266
|
-
library=search_term,
|
|
267
|
-
topic="best-practices",
|
|
268
|
-
use_fuzzy_match=True
|
|
269
|
-
),
|
|
270
|
-
timeout=self.timeout
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
if not docs or not docs.get("content"):
|
|
274
|
-
return None
|
|
275
|
-
|
|
276
|
-
content = docs["content"]
|
|
277
|
-
|
|
278
|
-
# Extract guidance from Context7 response
|
|
279
|
-
guidance = PatternGuidance(
|
|
280
|
-
pattern_name=pattern.pattern_name,
|
|
281
|
-
recommendations=self._extract_recommendations(content),
|
|
282
|
-
best_practices=self._extract_best_practices(content),
|
|
283
|
-
source="context7"
|
|
284
|
-
)
|
|
285
|
-
|
|
286
|
-
# Cache result
|
|
287
|
-
if self.cache_enabled:
|
|
288
|
-
self._cache[cache_key] = guidance
|
|
289
|
-
|
|
290
|
-
return guidance
|
|
291
|
-
|
|
292
|
-
except asyncio.TimeoutError:
|
|
293
|
-
logger.warning(f"Context7 lookup timeout for pattern: {pattern.pattern_name}")
|
|
294
|
-
return None
|
|
295
|
-
except Exception as e:
|
|
296
|
-
logger.warning(f"Context7 lookup failed for pattern {pattern.pattern_name}: {e}")
|
|
297
|
-
return None
|
|
298
|
-
|
|
299
|
-
def _extract_best_practices(self, content: str) -> list[str]:
|
|
300
|
-
"""
|
|
301
|
-
Extract best practices from Context7 content with enhanced parsing.
|
|
302
|
-
|
|
303
|
-
Enhanced approach:
|
|
304
|
-
1. Try to find section by header (## Best Practices, etc.)
|
|
305
|
-
2. Extract from section with better parsing
|
|
306
|
-
3. Fallback to keyword-based extraction if section not found
|
|
307
|
-
"""
|
|
308
|
-
try:
|
|
309
|
-
# Enhanced: Try to find section by header
|
|
310
|
-
section = self._find_section_by_header(
|
|
311
|
-
content,
|
|
312
|
-
["best practice", "best practices", "recommendation", "recommendations", "tip", "tips"]
|
|
313
|
-
)
|
|
314
|
-
|
|
315
|
-
if section:
|
|
316
|
-
# Extract from section
|
|
317
|
-
practices = self._extract_from_section(section, content)
|
|
318
|
-
return self._filter_and_limit(practices, max_items=5)
|
|
319
|
-
except Exception as e:
|
|
320
|
-
logger.debug(f"Enhanced extraction failed, using fallback: {e}")
|
|
321
|
-
|
|
322
|
-
# Fallback to simple keyword-based extraction
|
|
323
|
-
return self._extract_best_practices_simple(content)
|
|
324
|
-
|
|
325
|
-
def _extract_best_practices_simple(self, content: str) -> list[str]:
|
|
326
|
-
"""Simple keyword-based extraction (fallback method)."""
|
|
327
|
-
practices = []
|
|
328
|
-
lines = content.split('\n')
|
|
329
|
-
in_best_practices = False
|
|
330
|
-
|
|
331
|
-
for line in lines:
|
|
332
|
-
line_lower = line.lower()
|
|
333
|
-
if any(keyword in line_lower for keyword in ["best practice", "recommendation", "tip"]):
|
|
334
|
-
in_best_practices = True
|
|
335
|
-
continue
|
|
336
|
-
|
|
337
|
-
if in_best_practices:
|
|
338
|
-
stripped = line.strip()
|
|
339
|
-
if stripped.startswith(('-', '*', '•', '1.', '2.', '3.')):
|
|
340
|
-
practice = stripped.lstrip('-*•1234567890. ').strip()
|
|
341
|
-
if practice and len(practice) > 10:
|
|
342
|
-
practices.append(practice)
|
|
343
|
-
elif stripped and not stripped.startswith('#'):
|
|
344
|
-
if any(keyword in line_lower for keyword in ["should", "recommend", "best", "use"]):
|
|
345
|
-
practices.append(stripped)
|
|
346
|
-
|
|
347
|
-
if line.startswith('#') and in_best_practices:
|
|
348
|
-
in_best_practices = False
|
|
349
|
-
|
|
350
|
-
return practices[:5]
|
|
351
|
-
|
|
352
|
-
def _extract_common_mistakes(self, content: str) -> list[str]:
|
|
353
|
-
"""
|
|
354
|
-
Extract common mistakes from Context7 content with enhanced parsing.
|
|
355
|
-
|
|
356
|
-
Enhanced approach:
|
|
357
|
-
1. Try to find section by header
|
|
358
|
-
2. Extract from section with better parsing
|
|
359
|
-
3. Fallback to keyword-based extraction
|
|
360
|
-
"""
|
|
361
|
-
try:
|
|
362
|
-
# Enhanced: Try to find section by header
|
|
363
|
-
section = self._find_section_by_header(
|
|
364
|
-
content,
|
|
365
|
-
["common mistake", "common mistakes", "pitfall", "pitfalls", "avoid", "anti-pattern", "anti-patterns"]
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
if section:
|
|
369
|
-
# Extract from section
|
|
370
|
-
mistakes = self._extract_from_section(section, content)
|
|
371
|
-
return self._filter_and_limit(mistakes, max_items=5)
|
|
372
|
-
except Exception as e:
|
|
373
|
-
logger.debug(f"Enhanced extraction failed, using fallback: {e}")
|
|
374
|
-
|
|
375
|
-
# Fallback to simple keyword-based extraction
|
|
376
|
-
return self._extract_common_mistakes_simple(content)
|
|
377
|
-
|
|
378
|
-
def _extract_common_mistakes_simple(self, content: str) -> list[str]:
|
|
379
|
-
"""Simple keyword-based extraction (fallback method)."""
|
|
380
|
-
mistakes = []
|
|
381
|
-
lines = content.split('\n')
|
|
382
|
-
in_mistakes = False
|
|
383
|
-
|
|
384
|
-
for line in lines:
|
|
385
|
-
line_lower = line.lower()
|
|
386
|
-
if any(keyword in line_lower for keyword in ["common mistake", "pitfall", "avoid", "don't", "anti-pattern"]):
|
|
387
|
-
in_mistakes = True
|
|
388
|
-
continue
|
|
389
|
-
|
|
390
|
-
if in_mistakes:
|
|
391
|
-
stripped = line.strip()
|
|
392
|
-
if stripped.startswith(('-', '*', '•', '1.', '2.', '3.')):
|
|
393
|
-
mistake = stripped.lstrip('-*•1234567890. ').strip()
|
|
394
|
-
if mistake and len(mistake) > 10:
|
|
395
|
-
mistakes.append(mistake)
|
|
396
|
-
elif stripped and not stripped.startswith('#'):
|
|
397
|
-
if any(keyword in line_lower for keyword in ["avoid", "don't", "never", "mistake"]):
|
|
398
|
-
mistakes.append(stripped)
|
|
399
|
-
|
|
400
|
-
if line.startswith('#') and in_mistakes:
|
|
401
|
-
in_mistakes = False
|
|
402
|
-
|
|
403
|
-
return mistakes[:5]
|
|
404
|
-
|
|
405
|
-
def _extract_examples(self, content: str) -> list[str]:
|
|
406
|
-
"""
|
|
407
|
-
Extract usage examples from Context7 content with enhanced parsing.
|
|
408
|
-
|
|
409
|
-
Enhanced approach:
|
|
410
|
-
1. Try to find "Examples" section by header
|
|
411
|
-
2. Extract code blocks from section if found
|
|
412
|
-
3. Fallback to extracting all code blocks
|
|
413
|
-
"""
|
|
414
|
-
try:
|
|
415
|
-
# Enhanced: Try to find "Examples" section
|
|
416
|
-
section = self._find_section_by_header(
|
|
417
|
-
content,
|
|
418
|
-
["example", "examples", "usage", "code example", "code examples"]
|
|
419
|
-
)
|
|
420
|
-
|
|
421
|
-
if section:
|
|
422
|
-
# Extract code blocks from section
|
|
423
|
-
examples = self._extract_code_blocks_from_section(section, content)
|
|
424
|
-
return examples[:3]
|
|
425
|
-
except Exception as e:
|
|
426
|
-
logger.debug(f"Enhanced extraction failed, using fallback: {e}")
|
|
427
|
-
|
|
428
|
-
# Fallback: Extract all code blocks
|
|
429
|
-
return self._extract_all_code_blocks(content)[:3]
|
|
430
|
-
|
|
431
|
-
def _extract_recommendations(self, content: str) -> list[str]:
|
|
432
|
-
"""Extract recommendations from Context7 content."""
|
|
433
|
-
# Similar to best practices extraction
|
|
434
|
-
return self._extract_best_practices(content)
|
|
435
|
-
|
|
436
|
-
def _find_section_by_header(
|
|
437
|
-
self,
|
|
438
|
-
content: str,
|
|
439
|
-
keywords: list[str]
|
|
440
|
-
) -> Optional[tuple[int, int]]:
|
|
441
|
-
"""
|
|
442
|
-
Find section by header keywords.
|
|
443
|
-
|
|
444
|
-
Enhanced section detection that looks for markdown headers (##, ###, etc.)
|
|
445
|
-
containing the specified keywords.
|
|
446
|
-
|
|
447
|
-
Args:
|
|
448
|
-
content: Markdown content
|
|
449
|
-
keywords: List of keywords to search for in headers
|
|
450
|
-
|
|
451
|
-
Returns:
|
|
452
|
-
Tuple of (start_line, end_line) if found, None otherwise
|
|
453
|
-
"""
|
|
454
|
-
lines = content.split('\n')
|
|
455
|
-
in_section = False
|
|
456
|
-
start_line = None
|
|
457
|
-
current_level = None
|
|
458
|
-
|
|
459
|
-
for i, line in enumerate(lines):
|
|
460
|
-
stripped = line.strip()
|
|
461
|
-
|
|
462
|
-
# Check if line is a header (starts with #)
|
|
463
|
-
if stripped.startswith('#'):
|
|
464
|
-
# Extract header level and text
|
|
465
|
-
header_level = len(stripped) - len(stripped.lstrip('#'))
|
|
466
|
-
header_text = stripped.lstrip('#').strip().lower()
|
|
467
|
-
|
|
468
|
-
# Check if header contains any keyword
|
|
469
|
-
if any(keyword in header_text for keyword in keywords):
|
|
470
|
-
in_section = True
|
|
471
|
-
start_line = i
|
|
472
|
-
current_level = header_level
|
|
473
|
-
elif in_section:
|
|
474
|
-
# Found next header at same or higher level, end of section
|
|
475
|
-
if header_level <= current_level:
|
|
476
|
-
return (start_line, i - 1)
|
|
477
|
-
|
|
478
|
-
# If we're still in a section at the end, return to end of content
|
|
479
|
-
if in_section:
|
|
480
|
-
return (start_line, len(lines) - 1)
|
|
481
|
-
|
|
482
|
-
return None
|
|
483
|
-
|
|
484
|
-
def _extract_from_section(
|
|
485
|
-
self,
|
|
486
|
-
section: tuple[int, int],
|
|
487
|
-
content: str
|
|
488
|
-
) -> list[str]:
|
|
489
|
-
"""
|
|
490
|
-
Extract content from a section.
|
|
491
|
-
|
|
492
|
-
Enhanced extraction that handles:
|
|
493
|
-
- List items (bulleted and numbered)
|
|
494
|
-
- Nested lists
|
|
495
|
-
- Paragraph text
|
|
496
|
-
|
|
497
|
-
Args:
|
|
498
|
-
section: Tuple of (start_line, end_line)
|
|
499
|
-
content: Full markdown content
|
|
500
|
-
|
|
501
|
-
Returns:
|
|
502
|
-
List of extracted items
|
|
503
|
-
"""
|
|
504
|
-
lines = content.split('\n')
|
|
505
|
-
start, end = section
|
|
506
|
-
section_lines = lines[start:end + 1]
|
|
507
|
-
|
|
508
|
-
items = []
|
|
509
|
-
for line in section_lines:
|
|
510
|
-
stripped = line.strip()
|
|
511
|
-
|
|
512
|
-
# Skip empty lines and headers
|
|
513
|
-
if not stripped or stripped.startswith('#'):
|
|
514
|
-
continue
|
|
515
|
-
|
|
516
|
-
# Extract list items (bulleted)
|
|
517
|
-
if stripped.startswith(('-', '*', '•')):
|
|
518
|
-
item = stripped.lstrip('-*• ').strip()
|
|
519
|
-
if item and len(item) > 10:
|
|
520
|
-
items.append(item)
|
|
521
|
-
# Extract numbered list items
|
|
522
|
-
elif stripped and stripped[0].isdigit() and '.' in stripped[:5]:
|
|
523
|
-
# Handle numbered lists: "1. Item", "2. Item", etc.
|
|
524
|
-
parts = stripped.split('.', 1)
|
|
525
|
-
if len(parts) == 2:
|
|
526
|
-
item = parts[1].strip()
|
|
527
|
-
if item and len(item) > 10:
|
|
528
|
-
items.append(item)
|
|
529
|
-
# Extract substantial paragraph text
|
|
530
|
-
elif stripped and not stripped.startswith('```') and len(stripped) > 20:
|
|
531
|
-
# Only add if it looks like a recommendation/practice
|
|
532
|
-
if any(keyword in stripped.lower() for keyword in
|
|
533
|
-
["should", "recommend", "best", "use", "avoid", "don't", "never"]):
|
|
534
|
-
items.append(stripped)
|
|
535
|
-
|
|
536
|
-
return items
|
|
537
|
-
|
|
538
|
-
def _extract_code_blocks_from_section(
|
|
539
|
-
self,
|
|
540
|
-
section: tuple[int, int],
|
|
541
|
-
content: str
|
|
542
|
-
) -> list[str]:
|
|
543
|
-
"""
|
|
544
|
-
Extract code blocks from a section.
|
|
545
|
-
|
|
546
|
-
Args:
|
|
547
|
-
section: Tuple of (start_line, end_line)
|
|
548
|
-
content: Full markdown content
|
|
549
|
-
|
|
550
|
-
Returns:
|
|
551
|
-
List of code block contents
|
|
552
|
-
"""
|
|
553
|
-
lines = content.split('\n')
|
|
554
|
-
start, end = section
|
|
555
|
-
section_content = '\n'.join(lines[start:end + 1])
|
|
556
|
-
|
|
557
|
-
return self._extract_all_code_blocks(section_content)
|
|
558
|
-
|
|
559
|
-
def _extract_all_code_blocks(self, content: str) -> list[str]:
|
|
560
|
-
"""
|
|
561
|
-
Extract all code blocks from content.
|
|
562
|
-
|
|
563
|
-
Enhanced to handle language tags and preserve formatting.
|
|
564
|
-
|
|
565
|
-
Args:
|
|
566
|
-
content: Markdown content
|
|
567
|
-
|
|
568
|
-
Returns:
|
|
569
|
-
List of code block contents
|
|
570
|
-
"""
|
|
571
|
-
examples = []
|
|
572
|
-
in_code_block = False
|
|
573
|
-
code_block = []
|
|
574
|
-
|
|
575
|
-
for line in content.split('\n'):
|
|
576
|
-
stripped = line.strip()
|
|
577
|
-
|
|
578
|
-
if stripped.startswith('```'):
|
|
579
|
-
if in_code_block:
|
|
580
|
-
# End of code block
|
|
581
|
-
if code_block:
|
|
582
|
-
examples.append('\n'.join(code_block))
|
|
583
|
-
code_block = []
|
|
584
|
-
in_code_block = False
|
|
585
|
-
else:
|
|
586
|
-
# Start of code block
|
|
587
|
-
in_code_block = True
|
|
588
|
-
# Language tag is on the same line (```python), skip it
|
|
589
|
-
elif in_code_block:
|
|
590
|
-
code_block.append(line)
|
|
591
|
-
|
|
592
|
-
# Handle unclosed code block
|
|
593
|
-
if code_block:
|
|
594
|
-
examples.append('\n'.join(code_block))
|
|
595
|
-
|
|
596
|
-
return examples
|
|
597
|
-
|
|
598
|
-
def _filter_and_limit(
|
|
599
|
-
self,
|
|
600
|
-
items: list[str],
|
|
601
|
-
max_items: int = 5,
|
|
602
|
-
min_length: int = 10
|
|
603
|
-
) -> list[str]:
|
|
604
|
-
"""
|
|
605
|
-
Filter and limit extracted items.
|
|
606
|
-
|
|
607
|
-
Removes duplicates (case-insensitive) and filters by length.
|
|
608
|
-
|
|
609
|
-
Args:
|
|
610
|
-
items: List of extracted items
|
|
611
|
-
max_items: Maximum number of items to return
|
|
612
|
-
min_length: Minimum length for an item
|
|
613
|
-
|
|
614
|
-
Returns:
|
|
615
|
-
Filtered and limited list
|
|
616
|
-
"""
|
|
617
|
-
# Filter by length
|
|
618
|
-
filtered = [item for item in items if len(item.strip()) >= min_length]
|
|
619
|
-
|
|
620
|
-
# Remove duplicates (case-insensitive)
|
|
621
|
-
seen = set()
|
|
622
|
-
unique = []
|
|
623
|
-
for item in filtered:
|
|
624
|
-
item_lower = item.lower().strip()
|
|
625
|
-
if item_lower not in seen:
|
|
626
|
-
seen.add(item_lower)
|
|
627
|
-
unique.append(item)
|
|
628
|
-
|
|
629
|
-
# Limit
|
|
630
|
-
return unique[:max_items]
|
|
1
|
+
"""
|
|
2
|
+
Context7 Review Enhancer - Integrates Context7 lookups into review workflow.
|
|
3
|
+
|
|
4
|
+
Provides library-specific recommendations and pattern guidance from Context7.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
from ...context7.agent_integration import Context7AgentHelper
|
|
13
|
+
from .pattern_detector import PatternMatch
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class LibraryRecommendation:
|
|
20
|
+
"""Library-specific recommendations from Context7."""
|
|
21
|
+
library_name: str
|
|
22
|
+
best_practices: list[str]
|
|
23
|
+
common_mistakes: list[str]
|
|
24
|
+
usage_examples: list[str]
|
|
25
|
+
source: str # "context7" or "cache"
|
|
26
|
+
cached: bool = False
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class PatternGuidance:
|
|
31
|
+
"""Pattern-specific guidance from Context7."""
|
|
32
|
+
pattern_name: str
|
|
33
|
+
recommendations: list[str]
|
|
34
|
+
best_practices: list[str]
|
|
35
|
+
source: str # "context7" or "cache"
|
|
36
|
+
cached: bool = False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Context7ReviewEnhancer:
|
|
40
|
+
"""
|
|
41
|
+
Enhances review with Context7 library documentation and pattern guidance.
|
|
42
|
+
|
|
43
|
+
Responsibilities:
|
|
44
|
+
- Lookup library documentation from Context7
|
|
45
|
+
- Extract best practices and common mistakes
|
|
46
|
+
- Provide pattern-specific guidance
|
|
47
|
+
- Cache responses to avoid duplicate lookups
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
context7_helper: Context7AgentHelper,
|
|
53
|
+
timeout: int = 30,
|
|
54
|
+
cache_enabled: bool = True
|
|
55
|
+
):
|
|
56
|
+
"""
|
|
57
|
+
Initialize Context7 review enhancer.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
context7_helper: Context7AgentHelper instance
|
|
61
|
+
timeout: Timeout for Context7 lookups (seconds)
|
|
62
|
+
cache_enabled: Whether to cache Context7 responses
|
|
63
|
+
"""
|
|
64
|
+
self.context7_helper = context7_helper
|
|
65
|
+
self.timeout = timeout
|
|
66
|
+
self.cache_enabled = cache_enabled
|
|
67
|
+
self._cache: dict[str, LibraryRecommendation | PatternGuidance] = {}
|
|
68
|
+
|
|
69
|
+
async def get_library_recommendations(
|
|
70
|
+
self,
|
|
71
|
+
libraries: list[str]
|
|
72
|
+
) -> dict[str, LibraryRecommendation]:
|
|
73
|
+
"""
|
|
74
|
+
Get Context7 recommendations for detected libraries.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
libraries: List of library names
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Dictionary mapping library names to LibraryRecommendation objects
|
|
81
|
+
"""
|
|
82
|
+
if not libraries:
|
|
83
|
+
return {}
|
|
84
|
+
|
|
85
|
+
recommendations = {}
|
|
86
|
+
|
|
87
|
+
# Batch lookups with timeout
|
|
88
|
+
tasks = [
|
|
89
|
+
self._lookup_library_docs(lib) for lib in libraries
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
results = await asyncio.wait_for(
|
|
94
|
+
asyncio.gather(*tasks, return_exceptions=True),
|
|
95
|
+
timeout=self.timeout * len(libraries) # Total timeout for all lookups
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
for lib, result in zip(libraries, results):
|
|
99
|
+
if isinstance(result, Exception):
|
|
100
|
+
logger.warning(f"Context7 lookup failed for library {lib}: {result}")
|
|
101
|
+
continue
|
|
102
|
+
|
|
103
|
+
if result:
|
|
104
|
+
recommendations[lib] = result
|
|
105
|
+
except asyncio.TimeoutError:
|
|
106
|
+
logger.warning(f"Context7 lookup timeout for libraries: {libraries}")
|
|
107
|
+
except Exception as e:
|
|
108
|
+
logger.warning(f"Context7 lookup error: {e}")
|
|
109
|
+
|
|
110
|
+
return recommendations
|
|
111
|
+
|
|
112
|
+
async def get_pattern_guidance(
|
|
113
|
+
self,
|
|
114
|
+
patterns: list[PatternMatch]
|
|
115
|
+
) -> dict[str, PatternGuidance]:
|
|
116
|
+
"""
|
|
117
|
+
Get Context7 guidance for detected patterns.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
patterns: List of PatternMatch objects
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Dictionary mapping pattern names to PatternGuidance objects
|
|
124
|
+
"""
|
|
125
|
+
if not patterns:
|
|
126
|
+
return {}
|
|
127
|
+
|
|
128
|
+
guidance = {}
|
|
129
|
+
|
|
130
|
+
# Lookup guidance for each pattern
|
|
131
|
+
for pattern in patterns:
|
|
132
|
+
try:
|
|
133
|
+
result = await asyncio.wait_for(
|
|
134
|
+
self._lookup_pattern_docs(pattern),
|
|
135
|
+
timeout=self.timeout
|
|
136
|
+
)
|
|
137
|
+
if result:
|
|
138
|
+
guidance[pattern.pattern_name] = result
|
|
139
|
+
except asyncio.TimeoutError:
|
|
140
|
+
logger.warning(f"Context7 lookup timeout for pattern: {pattern.pattern_name}")
|
|
141
|
+
except Exception as e:
|
|
142
|
+
logger.warning(f"Context7 lookup error for pattern {pattern.pattern_name}: {e}")
|
|
143
|
+
|
|
144
|
+
return guidance
|
|
145
|
+
|
|
146
|
+
async def _lookup_library_docs(
|
|
147
|
+
self,
|
|
148
|
+
library: str
|
|
149
|
+
) -> Optional[LibraryRecommendation]:
|
|
150
|
+
"""
|
|
151
|
+
Lookup library documentation from Context7.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
library: Library name
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
LibraryRecommendation if successful, None otherwise
|
|
158
|
+
"""
|
|
159
|
+
# Check cache first
|
|
160
|
+
cache_key = f"library:{library}"
|
|
161
|
+
if self.cache_enabled and cache_key in self._cache:
|
|
162
|
+
cached = self._cache[cache_key]
|
|
163
|
+
if isinstance(cached, LibraryRecommendation):
|
|
164
|
+
return cached
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
# Use Context7AgentHelper to lookup docs
|
|
168
|
+
# Try multiple topics to get comprehensive information
|
|
169
|
+
topics = ["best-practices", "common-mistakes", "usage", "examples"]
|
|
170
|
+
|
|
171
|
+
all_content = []
|
|
172
|
+
for topic in topics:
|
|
173
|
+
try:
|
|
174
|
+
docs = await asyncio.wait_for(
|
|
175
|
+
self.context7_helper.get_documentation(
|
|
176
|
+
library=library,
|
|
177
|
+
topic=topic,
|
|
178
|
+
use_fuzzy_match=True
|
|
179
|
+
),
|
|
180
|
+
timeout=self.timeout
|
|
181
|
+
)
|
|
182
|
+
if docs and docs.get("content"):
|
|
183
|
+
all_content.append(docs["content"])
|
|
184
|
+
except asyncio.TimeoutError:
|
|
185
|
+
logger.debug(f"Context7 lookup timeout for {library} topic {topic}")
|
|
186
|
+
except Exception as e:
|
|
187
|
+
logger.debug(f"Context7 lookup error for {library} topic {topic}: {e}")
|
|
188
|
+
|
|
189
|
+
if not all_content:
|
|
190
|
+
# Try without topic (general documentation)
|
|
191
|
+
try:
|
|
192
|
+
docs = await asyncio.wait_for(
|
|
193
|
+
self.context7_helper.get_documentation(
|
|
194
|
+
library=library,
|
|
195
|
+
topic=None,
|
|
196
|
+
use_fuzzy_match=True
|
|
197
|
+
),
|
|
198
|
+
timeout=self.timeout
|
|
199
|
+
)
|
|
200
|
+
if docs and docs.get("content"):
|
|
201
|
+
all_content.append(docs["content"])
|
|
202
|
+
except Exception as e:
|
|
203
|
+
logger.debug(f"Context7 lookup error for {library}: {e}")
|
|
204
|
+
|
|
205
|
+
if not all_content:
|
|
206
|
+
return None
|
|
207
|
+
|
|
208
|
+
# Combine all content
|
|
209
|
+
combined_content = "\n\n".join(all_content)
|
|
210
|
+
|
|
211
|
+
# Extract structured data from Context7 response
|
|
212
|
+
recommendation = LibraryRecommendation(
|
|
213
|
+
library_name=library,
|
|
214
|
+
best_practices=self._extract_best_practices(combined_content),
|
|
215
|
+
common_mistakes=self._extract_common_mistakes(combined_content),
|
|
216
|
+
usage_examples=self._extract_examples(combined_content),
|
|
217
|
+
source="context7"
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Cache result
|
|
221
|
+
if self.cache_enabled:
|
|
222
|
+
self._cache[cache_key] = recommendation
|
|
223
|
+
|
|
224
|
+
return recommendation
|
|
225
|
+
|
|
226
|
+
except asyncio.TimeoutError:
|
|
227
|
+
logger.warning(f"Context7 lookup timeout for library: {library}")
|
|
228
|
+
return None
|
|
229
|
+
except Exception as e:
|
|
230
|
+
logger.warning(f"Context7 lookup failed for library {library}: {e}")
|
|
231
|
+
return None
|
|
232
|
+
|
|
233
|
+
async def _lookup_pattern_docs(
|
|
234
|
+
self,
|
|
235
|
+
pattern: PatternMatch
|
|
236
|
+
) -> Optional[PatternGuidance]:
|
|
237
|
+
"""
|
|
238
|
+
Lookup pattern guidance from Context7.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
pattern: PatternMatch object
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
PatternGuidance if successful, None otherwise
|
|
245
|
+
"""
|
|
246
|
+
# Check cache first
|
|
247
|
+
cache_key = f"pattern:{pattern.pattern_name}"
|
|
248
|
+
if self.cache_enabled and cache_key in self._cache:
|
|
249
|
+
cached = self._cache[cache_key]
|
|
250
|
+
if isinstance(cached, PatternGuidance):
|
|
251
|
+
return cached
|
|
252
|
+
|
|
253
|
+
try:
|
|
254
|
+
# Lookup pattern-specific documentation
|
|
255
|
+
# Map pattern names to Context7 search terms
|
|
256
|
+
search_terms = {
|
|
257
|
+
"rag_system": "RAG retrieval augmented generation",
|
|
258
|
+
"multi_agent": "multi-agent expert systems",
|
|
259
|
+
"weighted_decision": "weighted decision making"
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
search_term = search_terms.get(pattern.pattern_name, pattern.pattern_name)
|
|
263
|
+
|
|
264
|
+
docs = await asyncio.wait_for(
|
|
265
|
+
self.context7_helper.get_documentation(
|
|
266
|
+
library=search_term,
|
|
267
|
+
topic="best-practices",
|
|
268
|
+
use_fuzzy_match=True
|
|
269
|
+
),
|
|
270
|
+
timeout=self.timeout
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
if not docs or not docs.get("content"):
|
|
274
|
+
return None
|
|
275
|
+
|
|
276
|
+
content = docs["content"]
|
|
277
|
+
|
|
278
|
+
# Extract guidance from Context7 response
|
|
279
|
+
guidance = PatternGuidance(
|
|
280
|
+
pattern_name=pattern.pattern_name,
|
|
281
|
+
recommendations=self._extract_recommendations(content),
|
|
282
|
+
best_practices=self._extract_best_practices(content),
|
|
283
|
+
source="context7"
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Cache result
|
|
287
|
+
if self.cache_enabled:
|
|
288
|
+
self._cache[cache_key] = guidance
|
|
289
|
+
|
|
290
|
+
return guidance
|
|
291
|
+
|
|
292
|
+
except asyncio.TimeoutError:
|
|
293
|
+
logger.warning(f"Context7 lookup timeout for pattern: {pattern.pattern_name}")
|
|
294
|
+
return None
|
|
295
|
+
except Exception as e:
|
|
296
|
+
logger.warning(f"Context7 lookup failed for pattern {pattern.pattern_name}: {e}")
|
|
297
|
+
return None
|
|
298
|
+
|
|
299
|
+
def _extract_best_practices(self, content: str) -> list[str]:
|
|
300
|
+
"""
|
|
301
|
+
Extract best practices from Context7 content with enhanced parsing.
|
|
302
|
+
|
|
303
|
+
Enhanced approach:
|
|
304
|
+
1. Try to find section by header (## Best Practices, etc.)
|
|
305
|
+
2. Extract from section with better parsing
|
|
306
|
+
3. Fallback to keyword-based extraction if section not found
|
|
307
|
+
"""
|
|
308
|
+
try:
|
|
309
|
+
# Enhanced: Try to find section by header
|
|
310
|
+
section = self._find_section_by_header(
|
|
311
|
+
content,
|
|
312
|
+
["best practice", "best practices", "recommendation", "recommendations", "tip", "tips"]
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
if section:
|
|
316
|
+
# Extract from section
|
|
317
|
+
practices = self._extract_from_section(section, content)
|
|
318
|
+
return self._filter_and_limit(practices, max_items=5)
|
|
319
|
+
except Exception as e:
|
|
320
|
+
logger.debug(f"Enhanced extraction failed, using fallback: {e}")
|
|
321
|
+
|
|
322
|
+
# Fallback to simple keyword-based extraction
|
|
323
|
+
return self._extract_best_practices_simple(content)
|
|
324
|
+
|
|
325
|
+
def _extract_best_practices_simple(self, content: str) -> list[str]:
|
|
326
|
+
"""Simple keyword-based extraction (fallback method)."""
|
|
327
|
+
practices = []
|
|
328
|
+
lines = content.split('\n')
|
|
329
|
+
in_best_practices = False
|
|
330
|
+
|
|
331
|
+
for line in lines:
|
|
332
|
+
line_lower = line.lower()
|
|
333
|
+
if any(keyword in line_lower for keyword in ["best practice", "recommendation", "tip"]):
|
|
334
|
+
in_best_practices = True
|
|
335
|
+
continue
|
|
336
|
+
|
|
337
|
+
if in_best_practices:
|
|
338
|
+
stripped = line.strip()
|
|
339
|
+
if stripped.startswith(('-', '*', '•', '1.', '2.', '3.')):
|
|
340
|
+
practice = stripped.lstrip('-*•1234567890. ').strip()
|
|
341
|
+
if practice and len(practice) > 10:
|
|
342
|
+
practices.append(practice)
|
|
343
|
+
elif stripped and not stripped.startswith('#'):
|
|
344
|
+
if any(keyword in line_lower for keyword in ["should", "recommend", "best", "use"]):
|
|
345
|
+
practices.append(stripped)
|
|
346
|
+
|
|
347
|
+
if line.startswith('#') and in_best_practices:
|
|
348
|
+
in_best_practices = False
|
|
349
|
+
|
|
350
|
+
return practices[:5]
|
|
351
|
+
|
|
352
|
+
def _extract_common_mistakes(self, content: str) -> list[str]:
|
|
353
|
+
"""
|
|
354
|
+
Extract common mistakes from Context7 content with enhanced parsing.
|
|
355
|
+
|
|
356
|
+
Enhanced approach:
|
|
357
|
+
1. Try to find section by header
|
|
358
|
+
2. Extract from section with better parsing
|
|
359
|
+
3. Fallback to keyword-based extraction
|
|
360
|
+
"""
|
|
361
|
+
try:
|
|
362
|
+
# Enhanced: Try to find section by header
|
|
363
|
+
section = self._find_section_by_header(
|
|
364
|
+
content,
|
|
365
|
+
["common mistake", "common mistakes", "pitfall", "pitfalls", "avoid", "anti-pattern", "anti-patterns"]
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
if section:
|
|
369
|
+
# Extract from section
|
|
370
|
+
mistakes = self._extract_from_section(section, content)
|
|
371
|
+
return self._filter_and_limit(mistakes, max_items=5)
|
|
372
|
+
except Exception as e:
|
|
373
|
+
logger.debug(f"Enhanced extraction failed, using fallback: {e}")
|
|
374
|
+
|
|
375
|
+
# Fallback to simple keyword-based extraction
|
|
376
|
+
return self._extract_common_mistakes_simple(content)
|
|
377
|
+
|
|
378
|
+
def _extract_common_mistakes_simple(self, content: str) -> list[str]:
|
|
379
|
+
"""Simple keyword-based extraction (fallback method)."""
|
|
380
|
+
mistakes = []
|
|
381
|
+
lines = content.split('\n')
|
|
382
|
+
in_mistakes = False
|
|
383
|
+
|
|
384
|
+
for line in lines:
|
|
385
|
+
line_lower = line.lower()
|
|
386
|
+
if any(keyword in line_lower for keyword in ["common mistake", "pitfall", "avoid", "don't", "anti-pattern"]):
|
|
387
|
+
in_mistakes = True
|
|
388
|
+
continue
|
|
389
|
+
|
|
390
|
+
if in_mistakes:
|
|
391
|
+
stripped = line.strip()
|
|
392
|
+
if stripped.startswith(('-', '*', '•', '1.', '2.', '3.')):
|
|
393
|
+
mistake = stripped.lstrip('-*•1234567890. ').strip()
|
|
394
|
+
if mistake and len(mistake) > 10:
|
|
395
|
+
mistakes.append(mistake)
|
|
396
|
+
elif stripped and not stripped.startswith('#'):
|
|
397
|
+
if any(keyword in line_lower for keyword in ["avoid", "don't", "never", "mistake"]):
|
|
398
|
+
mistakes.append(stripped)
|
|
399
|
+
|
|
400
|
+
if line.startswith('#') and in_mistakes:
|
|
401
|
+
in_mistakes = False
|
|
402
|
+
|
|
403
|
+
return mistakes[:5]
|
|
404
|
+
|
|
405
|
+
def _extract_examples(self, content: str) -> list[str]:
|
|
406
|
+
"""
|
|
407
|
+
Extract usage examples from Context7 content with enhanced parsing.
|
|
408
|
+
|
|
409
|
+
Enhanced approach:
|
|
410
|
+
1. Try to find "Examples" section by header
|
|
411
|
+
2. Extract code blocks from section if found
|
|
412
|
+
3. Fallback to extracting all code blocks
|
|
413
|
+
"""
|
|
414
|
+
try:
|
|
415
|
+
# Enhanced: Try to find "Examples" section
|
|
416
|
+
section = self._find_section_by_header(
|
|
417
|
+
content,
|
|
418
|
+
["example", "examples", "usage", "code example", "code examples"]
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
if section:
|
|
422
|
+
# Extract code blocks from section
|
|
423
|
+
examples = self._extract_code_blocks_from_section(section, content)
|
|
424
|
+
return examples[:3]
|
|
425
|
+
except Exception as e:
|
|
426
|
+
logger.debug(f"Enhanced extraction failed, using fallback: {e}")
|
|
427
|
+
|
|
428
|
+
# Fallback: Extract all code blocks
|
|
429
|
+
return self._extract_all_code_blocks(content)[:3]
|
|
430
|
+
|
|
431
|
+
def _extract_recommendations(self, content: str) -> list[str]:
|
|
432
|
+
"""Extract recommendations from Context7 content."""
|
|
433
|
+
# Similar to best practices extraction
|
|
434
|
+
return self._extract_best_practices(content)
|
|
435
|
+
|
|
436
|
+
def _find_section_by_header(
|
|
437
|
+
self,
|
|
438
|
+
content: str,
|
|
439
|
+
keywords: list[str]
|
|
440
|
+
) -> Optional[tuple[int, int]]:
|
|
441
|
+
"""
|
|
442
|
+
Find section by header keywords.
|
|
443
|
+
|
|
444
|
+
Enhanced section detection that looks for markdown headers (##, ###, etc.)
|
|
445
|
+
containing the specified keywords.
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
content: Markdown content
|
|
449
|
+
keywords: List of keywords to search for in headers
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
Tuple of (start_line, end_line) if found, None otherwise
|
|
453
|
+
"""
|
|
454
|
+
lines = content.split('\n')
|
|
455
|
+
in_section = False
|
|
456
|
+
start_line = None
|
|
457
|
+
current_level = None
|
|
458
|
+
|
|
459
|
+
for i, line in enumerate(lines):
|
|
460
|
+
stripped = line.strip()
|
|
461
|
+
|
|
462
|
+
# Check if line is a header (starts with #)
|
|
463
|
+
if stripped.startswith('#'):
|
|
464
|
+
# Extract header level and text
|
|
465
|
+
header_level = len(stripped) - len(stripped.lstrip('#'))
|
|
466
|
+
header_text = stripped.lstrip('#').strip().lower()
|
|
467
|
+
|
|
468
|
+
# Check if header contains any keyword
|
|
469
|
+
if any(keyword in header_text for keyword in keywords):
|
|
470
|
+
in_section = True
|
|
471
|
+
start_line = i
|
|
472
|
+
current_level = header_level
|
|
473
|
+
elif in_section:
|
|
474
|
+
# Found next header at same or higher level, end of section
|
|
475
|
+
if header_level <= current_level:
|
|
476
|
+
return (start_line, i - 1)
|
|
477
|
+
|
|
478
|
+
# If we're still in a section at the end, return to end of content
|
|
479
|
+
if in_section:
|
|
480
|
+
return (start_line, len(lines) - 1)
|
|
481
|
+
|
|
482
|
+
return None
|
|
483
|
+
|
|
484
|
+
def _extract_from_section(
|
|
485
|
+
self,
|
|
486
|
+
section: tuple[int, int],
|
|
487
|
+
content: str
|
|
488
|
+
) -> list[str]:
|
|
489
|
+
"""
|
|
490
|
+
Extract content from a section.
|
|
491
|
+
|
|
492
|
+
Enhanced extraction that handles:
|
|
493
|
+
- List items (bulleted and numbered)
|
|
494
|
+
- Nested lists
|
|
495
|
+
- Paragraph text
|
|
496
|
+
|
|
497
|
+
Args:
|
|
498
|
+
section: Tuple of (start_line, end_line)
|
|
499
|
+
content: Full markdown content
|
|
500
|
+
|
|
501
|
+
Returns:
|
|
502
|
+
List of extracted items
|
|
503
|
+
"""
|
|
504
|
+
lines = content.split('\n')
|
|
505
|
+
start, end = section
|
|
506
|
+
section_lines = lines[start:end + 1]
|
|
507
|
+
|
|
508
|
+
items = []
|
|
509
|
+
for line in section_lines:
|
|
510
|
+
stripped = line.strip()
|
|
511
|
+
|
|
512
|
+
# Skip empty lines and headers
|
|
513
|
+
if not stripped or stripped.startswith('#'):
|
|
514
|
+
continue
|
|
515
|
+
|
|
516
|
+
# Extract list items (bulleted)
|
|
517
|
+
if stripped.startswith(('-', '*', '•')):
|
|
518
|
+
item = stripped.lstrip('-*• ').strip()
|
|
519
|
+
if item and len(item) > 10:
|
|
520
|
+
items.append(item)
|
|
521
|
+
# Extract numbered list items
|
|
522
|
+
elif stripped and stripped[0].isdigit() and '.' in stripped[:5]:
|
|
523
|
+
# Handle numbered lists: "1. Item", "2. Item", etc.
|
|
524
|
+
parts = stripped.split('.', 1)
|
|
525
|
+
if len(parts) == 2:
|
|
526
|
+
item = parts[1].strip()
|
|
527
|
+
if item and len(item) > 10:
|
|
528
|
+
items.append(item)
|
|
529
|
+
# Extract substantial paragraph text
|
|
530
|
+
elif stripped and not stripped.startswith('```') and len(stripped) > 20:
|
|
531
|
+
# Only add if it looks like a recommendation/practice
|
|
532
|
+
if any(keyword in stripped.lower() for keyword in
|
|
533
|
+
["should", "recommend", "best", "use", "avoid", "don't", "never"]):
|
|
534
|
+
items.append(stripped)
|
|
535
|
+
|
|
536
|
+
return items
|
|
537
|
+
|
|
538
|
+
def _extract_code_blocks_from_section(
|
|
539
|
+
self,
|
|
540
|
+
section: tuple[int, int],
|
|
541
|
+
content: str
|
|
542
|
+
) -> list[str]:
|
|
543
|
+
"""
|
|
544
|
+
Extract code blocks from a section.
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
section: Tuple of (start_line, end_line)
|
|
548
|
+
content: Full markdown content
|
|
549
|
+
|
|
550
|
+
Returns:
|
|
551
|
+
List of code block contents
|
|
552
|
+
"""
|
|
553
|
+
lines = content.split('\n')
|
|
554
|
+
start, end = section
|
|
555
|
+
section_content = '\n'.join(lines[start:end + 1])
|
|
556
|
+
|
|
557
|
+
return self._extract_all_code_blocks(section_content)
|
|
558
|
+
|
|
559
|
+
def _extract_all_code_blocks(self, content: str) -> list[str]:
|
|
560
|
+
"""
|
|
561
|
+
Extract all code blocks from content.
|
|
562
|
+
|
|
563
|
+
Enhanced to handle language tags and preserve formatting.
|
|
564
|
+
|
|
565
|
+
Args:
|
|
566
|
+
content: Markdown content
|
|
567
|
+
|
|
568
|
+
Returns:
|
|
569
|
+
List of code block contents
|
|
570
|
+
"""
|
|
571
|
+
examples = []
|
|
572
|
+
in_code_block = False
|
|
573
|
+
code_block = []
|
|
574
|
+
|
|
575
|
+
for line in content.split('\n'):
|
|
576
|
+
stripped = line.strip()
|
|
577
|
+
|
|
578
|
+
if stripped.startswith('```'):
|
|
579
|
+
if in_code_block:
|
|
580
|
+
# End of code block
|
|
581
|
+
if code_block:
|
|
582
|
+
examples.append('\n'.join(code_block))
|
|
583
|
+
code_block = []
|
|
584
|
+
in_code_block = False
|
|
585
|
+
else:
|
|
586
|
+
# Start of code block
|
|
587
|
+
in_code_block = True
|
|
588
|
+
# Language tag is on the same line (```python), skip it
|
|
589
|
+
elif in_code_block:
|
|
590
|
+
code_block.append(line)
|
|
591
|
+
|
|
592
|
+
# Handle unclosed code block
|
|
593
|
+
if code_block:
|
|
594
|
+
examples.append('\n'.join(code_block))
|
|
595
|
+
|
|
596
|
+
return examples
|
|
597
|
+
|
|
598
|
+
def _filter_and_limit(
|
|
599
|
+
self,
|
|
600
|
+
items: list[str],
|
|
601
|
+
max_items: int = 5,
|
|
602
|
+
min_length: int = 10
|
|
603
|
+
) -> list[str]:
|
|
604
|
+
"""
|
|
605
|
+
Filter and limit extracted items.
|
|
606
|
+
|
|
607
|
+
Removes duplicates (case-insensitive) and filters by length.
|
|
608
|
+
|
|
609
|
+
Args:
|
|
610
|
+
items: List of extracted items
|
|
611
|
+
max_items: Maximum number of items to return
|
|
612
|
+
min_length: Minimum length for an item
|
|
613
|
+
|
|
614
|
+
Returns:
|
|
615
|
+
Filtered and limited list
|
|
616
|
+
"""
|
|
617
|
+
# Filter by length
|
|
618
|
+
filtered = [item for item in items if len(item.strip()) >= min_length]
|
|
619
|
+
|
|
620
|
+
# Remove duplicates (case-insensitive)
|
|
621
|
+
seen = set()
|
|
622
|
+
unique = []
|
|
623
|
+
for item in filtered:
|
|
624
|
+
item_lower = item.lower().strip()
|
|
625
|
+
if item_lower not in seen:
|
|
626
|
+
seen.add(item_lower)
|
|
627
|
+
unique.append(item)
|
|
628
|
+
|
|
629
|
+
# Limit
|
|
630
|
+
return unique[:max_items]
|