attune-ai 2.0.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.
- attune/__init__.py +358 -0
- attune/adaptive/__init__.py +13 -0
- attune/adaptive/task_complexity.py +127 -0
- attune/agent_monitoring.py +414 -0
- attune/cache/__init__.py +117 -0
- attune/cache/base.py +166 -0
- attune/cache/dependency_manager.py +256 -0
- attune/cache/hash_only.py +251 -0
- attune/cache/hybrid.py +457 -0
- attune/cache/storage.py +285 -0
- attune/cache_monitor.py +356 -0
- attune/cache_stats.py +298 -0
- attune/cli/__init__.py +152 -0
- attune/cli/__main__.py +12 -0
- attune/cli/commands/__init__.py +1 -0
- attune/cli/commands/batch.py +264 -0
- attune/cli/commands/cache.py +248 -0
- attune/cli/commands/help.py +331 -0
- attune/cli/commands/info.py +140 -0
- attune/cli/commands/inspect.py +436 -0
- attune/cli/commands/inspection.py +57 -0
- attune/cli/commands/memory.py +48 -0
- attune/cli/commands/metrics.py +92 -0
- attune/cli/commands/orchestrate.py +184 -0
- attune/cli/commands/patterns.py +207 -0
- attune/cli/commands/profiling.py +202 -0
- attune/cli/commands/provider.py +98 -0
- attune/cli/commands/routing.py +285 -0
- attune/cli/commands/setup.py +96 -0
- attune/cli/commands/status.py +235 -0
- attune/cli/commands/sync.py +166 -0
- attune/cli/commands/tier.py +121 -0
- attune/cli/commands/utilities.py +114 -0
- attune/cli/commands/workflow.py +579 -0
- attune/cli/core.py +32 -0
- attune/cli/parsers/__init__.py +68 -0
- attune/cli/parsers/batch.py +118 -0
- attune/cli/parsers/cache.py +65 -0
- attune/cli/parsers/help.py +41 -0
- attune/cli/parsers/info.py +26 -0
- attune/cli/parsers/inspect.py +66 -0
- attune/cli/parsers/metrics.py +42 -0
- attune/cli/parsers/orchestrate.py +61 -0
- attune/cli/parsers/patterns.py +54 -0
- attune/cli/parsers/provider.py +40 -0
- attune/cli/parsers/routing.py +110 -0
- attune/cli/parsers/setup.py +42 -0
- attune/cli/parsers/status.py +47 -0
- attune/cli/parsers/sync.py +31 -0
- attune/cli/parsers/tier.py +33 -0
- attune/cli/parsers/workflow.py +77 -0
- attune/cli/utils/__init__.py +1 -0
- attune/cli/utils/data.py +242 -0
- attune/cli/utils/helpers.py +68 -0
- attune/cli_legacy.py +3957 -0
- attune/cli_minimal.py +1159 -0
- attune/cli_router.py +437 -0
- attune/cli_unified.py +814 -0
- attune/config/__init__.py +66 -0
- attune/config/xml_config.py +286 -0
- attune/config.py +545 -0
- attune/coordination.py +870 -0
- attune/core.py +1511 -0
- attune/core_modules/__init__.py +15 -0
- attune/cost_tracker.py +626 -0
- attune/dashboard/__init__.py +41 -0
- attune/dashboard/app.py +512 -0
- attune/dashboard/simple_server.py +435 -0
- attune/dashboard/standalone_server.py +547 -0
- attune/discovery.py +306 -0
- attune/emergence.py +306 -0
- attune/exceptions.py +123 -0
- attune/feedback_loops.py +373 -0
- attune/hot_reload/README.md +473 -0
- attune/hot_reload/__init__.py +62 -0
- attune/hot_reload/config.py +83 -0
- attune/hot_reload/integration.py +229 -0
- attune/hot_reload/reloader.py +298 -0
- attune/hot_reload/watcher.py +183 -0
- attune/hot_reload/websocket.py +177 -0
- attune/levels.py +577 -0
- attune/leverage_points.py +441 -0
- attune/logging_config.py +261 -0
- attune/mcp/__init__.py +10 -0
- attune/mcp/server.py +506 -0
- attune/memory/__init__.py +237 -0
- attune/memory/claude_memory.py +469 -0
- attune/memory/config.py +224 -0
- attune/memory/control_panel.py +1290 -0
- attune/memory/control_panel_support.py +145 -0
- attune/memory/cross_session.py +845 -0
- attune/memory/edges.py +179 -0
- attune/memory/encryption.py +159 -0
- attune/memory/file_session.py +770 -0
- attune/memory/graph.py +570 -0
- attune/memory/long_term.py +913 -0
- attune/memory/long_term_types.py +99 -0
- attune/memory/mixins/__init__.py +25 -0
- attune/memory/mixins/backend_init_mixin.py +249 -0
- attune/memory/mixins/capabilities_mixin.py +208 -0
- attune/memory/mixins/handoff_mixin.py +208 -0
- attune/memory/mixins/lifecycle_mixin.py +49 -0
- attune/memory/mixins/long_term_mixin.py +352 -0
- attune/memory/mixins/promotion_mixin.py +109 -0
- attune/memory/mixins/short_term_mixin.py +182 -0
- attune/memory/nodes.py +179 -0
- attune/memory/redis_bootstrap.py +540 -0
- attune/memory/security/__init__.py +31 -0
- attune/memory/security/audit_logger.py +932 -0
- attune/memory/security/pii_scrubber.py +640 -0
- attune/memory/security/secrets_detector.py +678 -0
- attune/memory/short_term.py +2192 -0
- attune/memory/simple_storage.py +302 -0
- attune/memory/storage/__init__.py +15 -0
- attune/memory/storage_backend.py +167 -0
- attune/memory/summary_index.py +583 -0
- attune/memory/types.py +446 -0
- attune/memory/unified.py +182 -0
- attune/meta_workflows/__init__.py +74 -0
- attune/meta_workflows/agent_creator.py +248 -0
- attune/meta_workflows/builtin_templates.py +567 -0
- attune/meta_workflows/cli_commands/__init__.py +56 -0
- attune/meta_workflows/cli_commands/agent_commands.py +321 -0
- attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
- attune/meta_workflows/cli_commands/config_commands.py +232 -0
- attune/meta_workflows/cli_commands/memory_commands.py +182 -0
- attune/meta_workflows/cli_commands/template_commands.py +354 -0
- attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
- attune/meta_workflows/cli_meta_workflows.py +59 -0
- attune/meta_workflows/form_engine.py +292 -0
- attune/meta_workflows/intent_detector.py +409 -0
- attune/meta_workflows/models.py +569 -0
- attune/meta_workflows/pattern_learner.py +738 -0
- attune/meta_workflows/plan_generator.py +384 -0
- attune/meta_workflows/session_context.py +397 -0
- attune/meta_workflows/template_registry.py +229 -0
- attune/meta_workflows/workflow.py +984 -0
- attune/metrics/__init__.py +12 -0
- attune/metrics/collector.py +31 -0
- attune/metrics/prompt_metrics.py +194 -0
- attune/models/__init__.py +172 -0
- attune/models/__main__.py +13 -0
- attune/models/adaptive_routing.py +437 -0
- attune/models/auth_cli.py +444 -0
- attune/models/auth_strategy.py +450 -0
- attune/models/cli.py +655 -0
- attune/models/empathy_executor.py +354 -0
- attune/models/executor.py +257 -0
- attune/models/fallback.py +762 -0
- attune/models/provider_config.py +282 -0
- attune/models/registry.py +472 -0
- attune/models/tasks.py +359 -0
- attune/models/telemetry/__init__.py +71 -0
- attune/models/telemetry/analytics.py +594 -0
- attune/models/telemetry/backend.py +196 -0
- attune/models/telemetry/data_models.py +431 -0
- attune/models/telemetry/storage.py +489 -0
- attune/models/token_estimator.py +420 -0
- attune/models/validation.py +280 -0
- attune/monitoring/__init__.py +52 -0
- attune/monitoring/alerts.py +946 -0
- attune/monitoring/alerts_cli.py +448 -0
- attune/monitoring/multi_backend.py +271 -0
- attune/monitoring/otel_backend.py +362 -0
- attune/optimization/__init__.py +19 -0
- attune/optimization/context_optimizer.py +272 -0
- attune/orchestration/__init__.py +67 -0
- attune/orchestration/agent_templates.py +707 -0
- attune/orchestration/config_store.py +499 -0
- attune/orchestration/execution_strategies.py +2111 -0
- attune/orchestration/meta_orchestrator.py +1168 -0
- attune/orchestration/pattern_learner.py +696 -0
- attune/orchestration/real_tools.py +931 -0
- attune/pattern_cache.py +187 -0
- attune/pattern_library.py +542 -0
- attune/patterns/debugging/all_patterns.json +81 -0
- attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
- attune/patterns/refactoring_memory.json +89 -0
- attune/persistence.py +564 -0
- attune/platform_utils.py +265 -0
- attune/plugins/__init__.py +28 -0
- attune/plugins/base.py +361 -0
- attune/plugins/registry.py +268 -0
- attune/project_index/__init__.py +32 -0
- attune/project_index/cli.py +335 -0
- attune/project_index/index.py +667 -0
- attune/project_index/models.py +504 -0
- attune/project_index/reports.py +474 -0
- attune/project_index/scanner.py +777 -0
- attune/project_index/scanner_parallel.py +291 -0
- attune/prompts/__init__.py +61 -0
- attune/prompts/config.py +77 -0
- attune/prompts/context.py +177 -0
- attune/prompts/parser.py +285 -0
- attune/prompts/registry.py +313 -0
- attune/prompts/templates.py +208 -0
- attune/redis_config.py +302 -0
- attune/redis_memory.py +799 -0
- attune/resilience/__init__.py +56 -0
- attune/resilience/circuit_breaker.py +256 -0
- attune/resilience/fallback.py +179 -0
- attune/resilience/health.py +300 -0
- attune/resilience/retry.py +209 -0
- attune/resilience/timeout.py +135 -0
- attune/routing/__init__.py +43 -0
- attune/routing/chain_executor.py +433 -0
- attune/routing/classifier.py +217 -0
- attune/routing/smart_router.py +234 -0
- attune/routing/workflow_registry.py +343 -0
- attune/scaffolding/README.md +589 -0
- attune/scaffolding/__init__.py +35 -0
- attune/scaffolding/__main__.py +14 -0
- attune/scaffolding/cli.py +240 -0
- attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
- attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
- attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
- attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
- attune/socratic/__init__.py +256 -0
- attune/socratic/ab_testing.py +958 -0
- attune/socratic/blueprint.py +533 -0
- attune/socratic/cli.py +703 -0
- attune/socratic/collaboration.py +1114 -0
- attune/socratic/domain_templates.py +924 -0
- attune/socratic/embeddings.py +738 -0
- attune/socratic/engine.py +794 -0
- attune/socratic/explainer.py +682 -0
- attune/socratic/feedback.py +772 -0
- attune/socratic/forms.py +629 -0
- attune/socratic/generator.py +732 -0
- attune/socratic/llm_analyzer.py +637 -0
- attune/socratic/mcp_server.py +702 -0
- attune/socratic/session.py +312 -0
- attune/socratic/storage.py +667 -0
- attune/socratic/success.py +730 -0
- attune/socratic/visual_editor.py +860 -0
- attune/socratic/web_ui.py +958 -0
- attune/telemetry/__init__.py +39 -0
- attune/telemetry/agent_coordination.py +475 -0
- attune/telemetry/agent_tracking.py +367 -0
- attune/telemetry/approval_gates.py +545 -0
- attune/telemetry/cli.py +1231 -0
- attune/telemetry/commands/__init__.py +14 -0
- attune/telemetry/commands/dashboard_commands.py +696 -0
- attune/telemetry/event_streaming.py +409 -0
- attune/telemetry/feedback_loop.py +567 -0
- attune/telemetry/usage_tracker.py +591 -0
- attune/templates.py +754 -0
- attune/test_generator/__init__.py +38 -0
- attune/test_generator/__main__.py +14 -0
- attune/test_generator/cli.py +234 -0
- attune/test_generator/generator.py +355 -0
- attune/test_generator/risk_analyzer.py +216 -0
- attune/test_generator/templates/unit_test.py.jinja2 +272 -0
- attune/tier_recommender.py +384 -0
- attune/tools.py +183 -0
- attune/trust/__init__.py +28 -0
- attune/trust/circuit_breaker.py +579 -0
- attune/trust_building.py +527 -0
- attune/validation/__init__.py +19 -0
- attune/validation/xml_validator.py +281 -0
- attune/vscode_bridge.py +173 -0
- attune/workflow_commands.py +780 -0
- attune/workflow_patterns/__init__.py +33 -0
- attune/workflow_patterns/behavior.py +249 -0
- attune/workflow_patterns/core.py +76 -0
- attune/workflow_patterns/output.py +99 -0
- attune/workflow_patterns/registry.py +255 -0
- attune/workflow_patterns/structural.py +288 -0
- attune/workflows/__init__.py +539 -0
- attune/workflows/autonomous_test_gen.py +1268 -0
- attune/workflows/base.py +2667 -0
- attune/workflows/batch_processing.py +342 -0
- attune/workflows/bug_predict.py +1084 -0
- attune/workflows/builder.py +273 -0
- attune/workflows/caching.py +253 -0
- attune/workflows/code_review.py +1048 -0
- attune/workflows/code_review_adapters.py +312 -0
- attune/workflows/code_review_pipeline.py +722 -0
- attune/workflows/config.py +645 -0
- attune/workflows/dependency_check.py +644 -0
- attune/workflows/document_gen/__init__.py +25 -0
- attune/workflows/document_gen/config.py +30 -0
- attune/workflows/document_gen/report_formatter.py +162 -0
- attune/workflows/document_gen/workflow.py +1426 -0
- attune/workflows/document_manager.py +216 -0
- attune/workflows/document_manager_README.md +134 -0
- attune/workflows/documentation_orchestrator.py +1205 -0
- attune/workflows/history.py +510 -0
- attune/workflows/keyboard_shortcuts/__init__.py +39 -0
- attune/workflows/keyboard_shortcuts/generators.py +391 -0
- attune/workflows/keyboard_shortcuts/parsers.py +416 -0
- attune/workflows/keyboard_shortcuts/prompts.py +295 -0
- attune/workflows/keyboard_shortcuts/schema.py +193 -0
- attune/workflows/keyboard_shortcuts/workflow.py +509 -0
- attune/workflows/llm_base.py +363 -0
- attune/workflows/manage_docs.py +87 -0
- attune/workflows/manage_docs_README.md +134 -0
- attune/workflows/manage_documentation.py +821 -0
- attune/workflows/new_sample_workflow1.py +149 -0
- attune/workflows/new_sample_workflow1_README.md +150 -0
- attune/workflows/orchestrated_health_check.py +849 -0
- attune/workflows/orchestrated_release_prep.py +600 -0
- attune/workflows/output.py +413 -0
- attune/workflows/perf_audit.py +863 -0
- attune/workflows/pr_review.py +762 -0
- attune/workflows/progress.py +785 -0
- attune/workflows/progress_server.py +322 -0
- attune/workflows/progressive/README 2.md +454 -0
- attune/workflows/progressive/README.md +454 -0
- attune/workflows/progressive/__init__.py +82 -0
- attune/workflows/progressive/cli.py +219 -0
- attune/workflows/progressive/core.py +488 -0
- attune/workflows/progressive/orchestrator.py +723 -0
- attune/workflows/progressive/reports.py +520 -0
- attune/workflows/progressive/telemetry.py +274 -0
- attune/workflows/progressive/test_gen.py +495 -0
- attune/workflows/progressive/workflow.py +589 -0
- attune/workflows/refactor_plan.py +694 -0
- attune/workflows/release_prep.py +895 -0
- attune/workflows/release_prep_crew.py +969 -0
- attune/workflows/research_synthesis.py +404 -0
- attune/workflows/routing.py +168 -0
- attune/workflows/secure_release.py +593 -0
- attune/workflows/security_adapters.py +297 -0
- attune/workflows/security_audit.py +1329 -0
- attune/workflows/security_audit_phase3.py +355 -0
- attune/workflows/seo_optimization.py +633 -0
- attune/workflows/step_config.py +234 -0
- attune/workflows/telemetry_mixin.py +269 -0
- attune/workflows/test5.py +125 -0
- attune/workflows/test5_README.md +158 -0
- attune/workflows/test_coverage_boost_crew.py +849 -0
- attune/workflows/test_gen/__init__.py +52 -0
- attune/workflows/test_gen/ast_analyzer.py +249 -0
- attune/workflows/test_gen/config.py +88 -0
- attune/workflows/test_gen/data_models.py +38 -0
- attune/workflows/test_gen/report_formatter.py +289 -0
- attune/workflows/test_gen/test_templates.py +381 -0
- attune/workflows/test_gen/workflow.py +655 -0
- attune/workflows/test_gen.py +54 -0
- attune/workflows/test_gen_behavioral.py +477 -0
- attune/workflows/test_gen_parallel.py +341 -0
- attune/workflows/test_lifecycle.py +526 -0
- attune/workflows/test_maintenance.py +627 -0
- attune/workflows/test_maintenance_cli.py +590 -0
- attune/workflows/test_maintenance_crew.py +840 -0
- attune/workflows/test_runner.py +622 -0
- attune/workflows/tier_tracking.py +531 -0
- attune/workflows/xml_enhanced_crew.py +285 -0
- attune_ai-2.0.0.dist-info/METADATA +1026 -0
- attune_ai-2.0.0.dist-info/RECORD +457 -0
- attune_ai-2.0.0.dist-info/WHEEL +5 -0
- attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
- attune_ai-2.0.0.dist-info/top_level.txt +5 -0
- attune_healthcare/__init__.py +13 -0
- attune_healthcare/monitors/__init__.py +9 -0
- attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
- attune_healthcare/monitors/monitoring/__init__.py +44 -0
- attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
- attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
- attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
- attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
- attune_llm/README.md +553 -0
- attune_llm/__init__.py +28 -0
- attune_llm/agent_factory/__init__.py +53 -0
- attune_llm/agent_factory/adapters/__init__.py +85 -0
- attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
- attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
- attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
- attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
- attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
- attune_llm/agent_factory/adapters/native.py +228 -0
- attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
- attune_llm/agent_factory/base.py +305 -0
- attune_llm/agent_factory/crews/__init__.py +67 -0
- attune_llm/agent_factory/crews/code_review.py +1113 -0
- attune_llm/agent_factory/crews/health_check.py +1262 -0
- attune_llm/agent_factory/crews/refactoring.py +1128 -0
- attune_llm/agent_factory/crews/security_audit.py +1018 -0
- attune_llm/agent_factory/decorators.py +287 -0
- attune_llm/agent_factory/factory.py +558 -0
- attune_llm/agent_factory/framework.py +193 -0
- attune_llm/agent_factory/memory_integration.py +328 -0
- attune_llm/agent_factory/resilient.py +320 -0
- attune_llm/agents_md/__init__.py +22 -0
- attune_llm/agents_md/loader.py +218 -0
- attune_llm/agents_md/parser.py +271 -0
- attune_llm/agents_md/registry.py +307 -0
- attune_llm/claude_memory.py +466 -0
- attune_llm/cli/__init__.py +8 -0
- attune_llm/cli/sync_claude.py +487 -0
- attune_llm/code_health.py +1313 -0
- attune_llm/commands/__init__.py +51 -0
- attune_llm/commands/context.py +375 -0
- attune_llm/commands/loader.py +301 -0
- attune_llm/commands/models.py +231 -0
- attune_llm/commands/parser.py +371 -0
- attune_llm/commands/registry.py +429 -0
- attune_llm/config/__init__.py +29 -0
- attune_llm/config/unified.py +291 -0
- attune_llm/context/__init__.py +22 -0
- attune_llm/context/compaction.py +455 -0
- attune_llm/context/manager.py +434 -0
- attune_llm/contextual_patterns.py +361 -0
- attune_llm/core.py +907 -0
- attune_llm/git_pattern_extractor.py +435 -0
- attune_llm/hooks/__init__.py +24 -0
- attune_llm/hooks/config.py +306 -0
- attune_llm/hooks/executor.py +289 -0
- attune_llm/hooks/registry.py +302 -0
- attune_llm/hooks/scripts/__init__.py +39 -0
- attune_llm/hooks/scripts/evaluate_session.py +201 -0
- attune_llm/hooks/scripts/first_time_init.py +285 -0
- attune_llm/hooks/scripts/pre_compact.py +207 -0
- attune_llm/hooks/scripts/session_end.py +183 -0
- attune_llm/hooks/scripts/session_start.py +163 -0
- attune_llm/hooks/scripts/suggest_compact.py +225 -0
- attune_llm/learning/__init__.py +30 -0
- attune_llm/learning/evaluator.py +438 -0
- attune_llm/learning/extractor.py +514 -0
- attune_llm/learning/storage.py +560 -0
- attune_llm/levels.py +227 -0
- attune_llm/pattern_confidence.py +414 -0
- attune_llm/pattern_resolver.py +272 -0
- attune_llm/pattern_summary.py +350 -0
- attune_llm/providers.py +967 -0
- attune_llm/routing/__init__.py +32 -0
- attune_llm/routing/model_router.py +362 -0
- attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
- attune_llm/security/PHASE2_COMPLETE.md +384 -0
- attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- attune_llm/security/QUICK_REFERENCE.md +316 -0
- attune_llm/security/README.md +262 -0
- attune_llm/security/__init__.py +62 -0
- attune_llm/security/audit_logger.py +929 -0
- attune_llm/security/audit_logger_example.py +152 -0
- attune_llm/security/pii_scrubber.py +640 -0
- attune_llm/security/secrets_detector.py +678 -0
- attune_llm/security/secrets_detector_example.py +304 -0
- attune_llm/security/secure_memdocs.py +1192 -0
- attune_llm/security/secure_memdocs_example.py +278 -0
- attune_llm/session_status.py +745 -0
- attune_llm/state.py +246 -0
- attune_llm/utils/__init__.py +5 -0
- attune_llm/utils/tokens.py +349 -0
- attune_software/SOFTWARE_PLUGIN_README.md +57 -0
- attune_software/__init__.py +13 -0
- attune_software/cli/__init__.py +120 -0
- attune_software/cli/inspect.py +362 -0
- attune_software/cli.py +574 -0
- attune_software/plugin.py +188 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- workflow_scaffolding/generator.py +265 -0
attune/prompts/parser.py
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"""XML Response Parser
|
|
2
|
+
|
|
3
|
+
Parses structured XML responses from LLMs for dashboard display
|
|
4
|
+
and workflow automation.
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart-AI-Memory
|
|
7
|
+
Licensed under Fair Source License 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import re
|
|
13
|
+
import xml.etree.ElementTree as ET
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
import defusedxml.ElementTree as DefusedET
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class Finding:
|
|
22
|
+
"""Structured finding from XML response.
|
|
23
|
+
|
|
24
|
+
Represents a single issue, vulnerability, or code review comment
|
|
25
|
+
extracted from an LLM response.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
severity: str # critical, high, medium, low, info
|
|
29
|
+
title: str
|
|
30
|
+
location: str | None = None
|
|
31
|
+
details: str = ""
|
|
32
|
+
fix: str = ""
|
|
33
|
+
|
|
34
|
+
def to_dict(self) -> dict[str, Any]:
|
|
35
|
+
"""Convert to dictionary for serialization."""
|
|
36
|
+
return {
|
|
37
|
+
"severity": self.severity,
|
|
38
|
+
"title": self.title,
|
|
39
|
+
"location": self.location,
|
|
40
|
+
"details": self.details,
|
|
41
|
+
"fix": self.fix,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@classmethod
|
|
45
|
+
def from_dict(cls, data: dict[str, Any]) -> Finding:
|
|
46
|
+
"""Create Finding from dictionary."""
|
|
47
|
+
return cls(
|
|
48
|
+
severity=data.get("severity", "medium"),
|
|
49
|
+
title=data.get("title", ""),
|
|
50
|
+
location=data.get("location"),
|
|
51
|
+
details=data.get("details", ""),
|
|
52
|
+
fix=data.get("fix", ""),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class ParsedResponse:
|
|
58
|
+
"""Result of parsing an XML response.
|
|
59
|
+
|
|
60
|
+
Contains extracted structured data or fallback raw text
|
|
61
|
+
if parsing fails.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
success: bool
|
|
65
|
+
raw: str
|
|
66
|
+
summary: str | None = None
|
|
67
|
+
findings: list[Finding] = field(default_factory=list)
|
|
68
|
+
checklist: list[str] = field(default_factory=list)
|
|
69
|
+
errors: list[str] = field(default_factory=list)
|
|
70
|
+
extra: dict[str, Any] = field(default_factory=dict)
|
|
71
|
+
|
|
72
|
+
def to_dict(self) -> dict[str, Any]:
|
|
73
|
+
"""Convert to dictionary for serialization."""
|
|
74
|
+
return {
|
|
75
|
+
"success": self.success,
|
|
76
|
+
"raw": self.raw,
|
|
77
|
+
"summary": self.summary,
|
|
78
|
+
"findings": [f.to_dict() for f in self.findings],
|
|
79
|
+
"checklist": self.checklist,
|
|
80
|
+
"errors": self.errors,
|
|
81
|
+
"extra": self.extra,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def from_dict(cls, data: dict[str, Any]) -> ParsedResponse:
|
|
86
|
+
"""Create ParsedResponse from dictionary."""
|
|
87
|
+
findings = [Finding.from_dict(f) for f in data.get("findings", [])]
|
|
88
|
+
return cls(
|
|
89
|
+
success=data.get("success", False),
|
|
90
|
+
raw=data.get("raw", ""),
|
|
91
|
+
summary=data.get("summary"),
|
|
92
|
+
findings=findings,
|
|
93
|
+
checklist=data.get("checklist", []),
|
|
94
|
+
errors=data.get("errors", []),
|
|
95
|
+
extra=data.get("extra", {}),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def from_raw(cls, raw: str, errors: list[str] | None = None) -> ParsedResponse:
|
|
100
|
+
"""Create a fallback ParsedResponse from raw text."""
|
|
101
|
+
return cls(
|
|
102
|
+
success=False,
|
|
103
|
+
raw=raw,
|
|
104
|
+
summary=raw[:500] if raw else None,
|
|
105
|
+
errors=errors or ["No XML content found"],
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class XmlResponseParser:
|
|
110
|
+
"""Parse LLM responses containing XML.
|
|
111
|
+
|
|
112
|
+
Extracts structured data from XML-formatted responses while
|
|
113
|
+
gracefully handling malformed or missing XML.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(self, fallback_on_error: bool = True):
|
|
117
|
+
"""Initialize the parser.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
fallback_on_error: If True, return raw text on parse failure
|
|
121
|
+
instead of raising an exception.
|
|
122
|
+
|
|
123
|
+
"""
|
|
124
|
+
self.fallback_on_error = fallback_on_error
|
|
125
|
+
|
|
126
|
+
def parse(self, response: str) -> ParsedResponse:
|
|
127
|
+
"""Parse XML response, with graceful fallback.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
response: The LLM response text, potentially containing XML.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
ParsedResponse with extracted data or fallback raw text.
|
|
134
|
+
|
|
135
|
+
"""
|
|
136
|
+
if not response:
|
|
137
|
+
return ParsedResponse.from_raw("", ["Empty response"])
|
|
138
|
+
|
|
139
|
+
# Extract XML from response (may be wrapped in markdown)
|
|
140
|
+
xml_content = self._extract_xml(response)
|
|
141
|
+
|
|
142
|
+
if not xml_content:
|
|
143
|
+
if self.fallback_on_error:
|
|
144
|
+
return ParsedResponse.from_raw(response, ["No XML content found"])
|
|
145
|
+
raise ValueError("No XML content in response")
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
# Use defusedxml for safe XML parsing (prevents XXE attacks)
|
|
149
|
+
root = DefusedET.fromstring(xml_content)
|
|
150
|
+
|
|
151
|
+
return ParsedResponse(
|
|
152
|
+
success=True,
|
|
153
|
+
raw=response,
|
|
154
|
+
summary=self._extract_text(root, "summary"),
|
|
155
|
+
findings=self._extract_findings(root),
|
|
156
|
+
checklist=self._extract_checklist(root),
|
|
157
|
+
extra=self._extract_extra(root),
|
|
158
|
+
)
|
|
159
|
+
except ET.ParseError as e:
|
|
160
|
+
if self.fallback_on_error:
|
|
161
|
+
return ParsedResponse.from_raw(response, [f"XML parse error: {e}"])
|
|
162
|
+
raise
|
|
163
|
+
|
|
164
|
+
def _extract_xml(self, response: str) -> str | None:
|
|
165
|
+
"""Extract XML content from response.
|
|
166
|
+
|
|
167
|
+
Handles various formats:
|
|
168
|
+
- Direct XML
|
|
169
|
+
- XML in markdown code blocks
|
|
170
|
+
- XML mixed with other text
|
|
171
|
+
"""
|
|
172
|
+
# Handle markdown code blocks with xml tag
|
|
173
|
+
xml_block = re.search(r"```xml\s*(.*?)\s*```", response, re.DOTALL)
|
|
174
|
+
if xml_block:
|
|
175
|
+
return xml_block.group(1).strip()
|
|
176
|
+
|
|
177
|
+
# Handle generic markdown code blocks
|
|
178
|
+
code_block = re.search(r"```\s*(.*?)\s*```", response, re.DOTALL)
|
|
179
|
+
if code_block:
|
|
180
|
+
content = code_block.group(1).strip()
|
|
181
|
+
if content.startswith("<"):
|
|
182
|
+
return content
|
|
183
|
+
|
|
184
|
+
# Try to find <response> tags
|
|
185
|
+
response_match = re.search(r"<response\b[^>]*>.*?</response>", response, re.DOTALL)
|
|
186
|
+
if response_match:
|
|
187
|
+
return response_match.group(0)
|
|
188
|
+
|
|
189
|
+
# Try to find any root XML element
|
|
190
|
+
xml_match = re.search(r"<(\w+)\b[^>]*>.*?</\1>", response, re.DOTALL)
|
|
191
|
+
if xml_match:
|
|
192
|
+
return xml_match.group(0)
|
|
193
|
+
|
|
194
|
+
# If response itself looks like XML
|
|
195
|
+
stripped = response.strip()
|
|
196
|
+
if stripped.startswith("<") and stripped.endswith(">"):
|
|
197
|
+
return stripped
|
|
198
|
+
|
|
199
|
+
return None
|
|
200
|
+
|
|
201
|
+
def _extract_text(self, root: ET.Element, tag: str) -> str | None:
|
|
202
|
+
"""Extract text content from a tag."""
|
|
203
|
+
element = root.find(f".//{tag}")
|
|
204
|
+
if element is not None and element.text:
|
|
205
|
+
return element.text.strip()
|
|
206
|
+
return None
|
|
207
|
+
|
|
208
|
+
def _extract_findings(self, root: ET.Element) -> list[Finding]:
|
|
209
|
+
"""Extract findings from parsed XML."""
|
|
210
|
+
findings = []
|
|
211
|
+
|
|
212
|
+
# Look for findings in various possible locations
|
|
213
|
+
for finding_el in root.findall(".//finding"):
|
|
214
|
+
findings.append(self._parse_finding(finding_el))
|
|
215
|
+
|
|
216
|
+
# Also check for <item> inside <findings>
|
|
217
|
+
findings_container = root.find(".//findings")
|
|
218
|
+
if findings_container is not None:
|
|
219
|
+
for item_el in findings_container.findall("item"):
|
|
220
|
+
findings.append(self._parse_finding(item_el))
|
|
221
|
+
|
|
222
|
+
return findings
|
|
223
|
+
|
|
224
|
+
def _parse_finding(self, element: ET.Element) -> Finding:
|
|
225
|
+
"""Parse a single finding element."""
|
|
226
|
+
title = self._extract_text(element, "title") or element.get("title") or ""
|
|
227
|
+
return Finding(
|
|
228
|
+
severity=element.get("severity") or "medium",
|
|
229
|
+
title=title,
|
|
230
|
+
location=self._extract_text(element, "location"),
|
|
231
|
+
details=self._extract_text(element, "details") or "",
|
|
232
|
+
fix=self._extract_text(element, "fix") or "",
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def _extract_checklist(self, root: ET.Element) -> list[str]:
|
|
236
|
+
"""Extract checklist items from parsed XML."""
|
|
237
|
+
items = []
|
|
238
|
+
|
|
239
|
+
# Look for remediation-checklist
|
|
240
|
+
checklist = root.find(".//remediation-checklist")
|
|
241
|
+
if checklist is not None:
|
|
242
|
+
for item in checklist.findall("item"):
|
|
243
|
+
if item.text:
|
|
244
|
+
items.append(item.text.strip())
|
|
245
|
+
|
|
246
|
+
# Also check for generic checklist
|
|
247
|
+
if not items:
|
|
248
|
+
checklist = root.find(".//checklist")
|
|
249
|
+
if checklist is not None:
|
|
250
|
+
for item in checklist.findall("item"):
|
|
251
|
+
if item.text:
|
|
252
|
+
items.append(item.text.strip())
|
|
253
|
+
|
|
254
|
+
return items
|
|
255
|
+
|
|
256
|
+
def _extract_extra(self, root: ET.Element) -> dict[str, Any]:
|
|
257
|
+
"""Extract additional fields from the response."""
|
|
258
|
+
extra: dict[str, Any] = {}
|
|
259
|
+
|
|
260
|
+
# Extract verdict (for code review)
|
|
261
|
+
verdict = self._extract_text(root, "verdict")
|
|
262
|
+
if verdict:
|
|
263
|
+
extra["verdict"] = verdict
|
|
264
|
+
|
|
265
|
+
# Extract confidence (for research)
|
|
266
|
+
confidence = root.find(".//confidence")
|
|
267
|
+
if confidence is not None:
|
|
268
|
+
extra["confidence"] = {
|
|
269
|
+
"level": confidence.get("level", "medium"),
|
|
270
|
+
"reasoning": confidence.text.strip() if confidence.text else "",
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
# Extract key insights (for research)
|
|
274
|
+
insights = root.find(".//key-insights")
|
|
275
|
+
if insights is not None:
|
|
276
|
+
extra["key_insights"] = [i.text.strip() for i in insights.findall("insight") if i.text]
|
|
277
|
+
|
|
278
|
+
# Extract suggestions (for code review)
|
|
279
|
+
suggestions = root.find(".//suggestions")
|
|
280
|
+
if suggestions is not None:
|
|
281
|
+
extra["suggestions"] = [
|
|
282
|
+
s.text.strip() for s in suggestions.findall("suggestion") if s.text
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
return extra
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"""Built-in XML Prompt Templates Registry
|
|
2
|
+
|
|
3
|
+
Provides pre-configured XML templates for common workflows.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from .templates import XmlPromptTemplate
|
|
12
|
+
|
|
13
|
+
# =============================================================================
|
|
14
|
+
# Response Format Definitions
|
|
15
|
+
# =============================================================================
|
|
16
|
+
|
|
17
|
+
SECURITY_AUDIT_RESPONSE = """<response>
|
|
18
|
+
<summary>Brief overall security assessment (1-2 sentences)</summary>
|
|
19
|
+
<findings>
|
|
20
|
+
<finding severity="critical|high|medium|low|info">
|
|
21
|
+
<title>Issue title</title>
|
|
22
|
+
<location>file:line or component</location>
|
|
23
|
+
<details>Description of the vulnerability and potential impact</details>
|
|
24
|
+
<fix>Specific remediation steps with code example if applicable</fix>
|
|
25
|
+
</finding>
|
|
26
|
+
<!-- Additional findings... -->
|
|
27
|
+
</findings>
|
|
28
|
+
<remediation-checklist>
|
|
29
|
+
<item>Priority action item 1</item>
|
|
30
|
+
<item>Priority action item 2</item>
|
|
31
|
+
<!-- Additional items... -->
|
|
32
|
+
</remediation-checklist>
|
|
33
|
+
</response>"""
|
|
34
|
+
|
|
35
|
+
CODE_REVIEW_RESPONSE = """<response>
|
|
36
|
+
<summary>Brief review summary (1-2 sentences)</summary>
|
|
37
|
+
<verdict>approve|approve_with_suggestions|request_changes|reject</verdict>
|
|
38
|
+
<findings>
|
|
39
|
+
<finding severity="critical|high|medium|low|info">
|
|
40
|
+
<title>Issue title</title>
|
|
41
|
+
<location>file:line</location>
|
|
42
|
+
<details>Description of the issue</details>
|
|
43
|
+
<fix>Suggested fix or improvement</fix>
|
|
44
|
+
</finding>
|
|
45
|
+
<!-- Additional findings... -->
|
|
46
|
+
</findings>
|
|
47
|
+
<suggestions>
|
|
48
|
+
<suggestion>Optional improvement suggestion</suggestion>
|
|
49
|
+
<!-- Additional suggestions... -->
|
|
50
|
+
</suggestions>
|
|
51
|
+
<remediation-checklist>
|
|
52
|
+
<item>Required change 1</item>
|
|
53
|
+
<item>Required change 2</item>
|
|
54
|
+
<!-- Additional items if request_changes... -->
|
|
55
|
+
</remediation-checklist>
|
|
56
|
+
</response>"""
|
|
57
|
+
|
|
58
|
+
RESEARCH_RESPONSE = """<response>
|
|
59
|
+
<summary>Research synthesis summary (2-3 sentences)</summary>
|
|
60
|
+
<key-insights>
|
|
61
|
+
<insight>Key insight or finding 1</insight>
|
|
62
|
+
<insight>Key insight or finding 2</insight>
|
|
63
|
+
<!-- Additional insights... -->
|
|
64
|
+
</key-insights>
|
|
65
|
+
<findings>
|
|
66
|
+
<finding severity="info">
|
|
67
|
+
<title>Topic or concept</title>
|
|
68
|
+
<details>Explanation with context</details>
|
|
69
|
+
</finding>
|
|
70
|
+
<!-- Additional topics if needed... -->
|
|
71
|
+
</findings>
|
|
72
|
+
<confidence level="high|medium|low">Reasoning for confidence level</confidence>
|
|
73
|
+
<remediation-checklist>
|
|
74
|
+
<item>Recommended next step 1</item>
|
|
75
|
+
<item>Recommended next step 2</item>
|
|
76
|
+
</remediation-checklist>
|
|
77
|
+
</response>"""
|
|
78
|
+
|
|
79
|
+
BUG_ANALYSIS_RESPONSE = """<response>
|
|
80
|
+
<summary>Root cause summary (1-2 sentences)</summary>
|
|
81
|
+
<findings>
|
|
82
|
+
<finding severity="critical|high|medium|low">
|
|
83
|
+
<title>Bug description</title>
|
|
84
|
+
<location>file:line where issue originates</location>
|
|
85
|
+
<details>Root cause analysis</details>
|
|
86
|
+
<fix>Recommended fix with code</fix>
|
|
87
|
+
</finding>
|
|
88
|
+
</findings>
|
|
89
|
+
<remediation-checklist>
|
|
90
|
+
<item>Fix step 1</item>
|
|
91
|
+
<item>Verification step</item>
|
|
92
|
+
<item>Test to add</item>
|
|
93
|
+
</remediation-checklist>
|
|
94
|
+
</response>"""
|
|
95
|
+
|
|
96
|
+
PERF_AUDIT_RESPONSE = """<response>
|
|
97
|
+
<summary>Performance assessment summary (1-2 sentences)</summary>
|
|
98
|
+
<performance-score>0-100</performance-score>
|
|
99
|
+
<findings>
|
|
100
|
+
<finding severity="critical|high|medium|low">
|
|
101
|
+
<title>Performance issue title</title>
|
|
102
|
+
<location>file:line or component</location>
|
|
103
|
+
<details>Description of the bottleneck and its impact</details>
|
|
104
|
+
<fix>Optimization recommendation with code example</fix>
|
|
105
|
+
</finding>
|
|
106
|
+
</findings>
|
|
107
|
+
<remediation-checklist>
|
|
108
|
+
<item>Optimization priority 1</item>
|
|
109
|
+
<item>Optimization priority 2</item>
|
|
110
|
+
</remediation-checklist>
|
|
111
|
+
</response>"""
|
|
112
|
+
|
|
113
|
+
REFACTOR_PLAN_RESPONSE = """<response>
|
|
114
|
+
<summary>Tech debt assessment (1-2 sentences)</summary>
|
|
115
|
+
<trajectory>increasing|stable|decreasing</trajectory>
|
|
116
|
+
<findings>
|
|
117
|
+
<finding severity="high|medium|low">
|
|
118
|
+
<title>Debt item description</title>
|
|
119
|
+
<location>file:line</location>
|
|
120
|
+
<details>Impact and complexity assessment</details>
|
|
121
|
+
<fix>Refactoring approach</fix>
|
|
122
|
+
</finding>
|
|
123
|
+
</findings>
|
|
124
|
+
<roadmap>
|
|
125
|
+
<phase priority="1|2|3">
|
|
126
|
+
<name>Phase name</name>
|
|
127
|
+
<description>What to accomplish</description>
|
|
128
|
+
<effort>high|medium|low</effort>
|
|
129
|
+
</phase>
|
|
130
|
+
</roadmap>
|
|
131
|
+
<remediation-checklist>
|
|
132
|
+
<item>Immediate action 1</item>
|
|
133
|
+
<item>Immediate action 2</item>
|
|
134
|
+
</remediation-checklist>
|
|
135
|
+
</response>"""
|
|
136
|
+
|
|
137
|
+
TEST_GEN_RESPONSE = """<response>
|
|
138
|
+
<summary>Test generation summary (1-2 sentences)</summary>
|
|
139
|
+
<coverage-improvement>Estimated coverage improvement</coverage-improvement>
|
|
140
|
+
<findings>
|
|
141
|
+
<finding severity="info">
|
|
142
|
+
<title>Untested area</title>
|
|
143
|
+
<location>file:function or class</location>
|
|
144
|
+
<details>Why this needs testing</details>
|
|
145
|
+
<fix>Test approach recommendation</fix>
|
|
146
|
+
</finding>
|
|
147
|
+
</findings>
|
|
148
|
+
<tests>
|
|
149
|
+
<test target="function or class name">
|
|
150
|
+
<type>unit|integration|edge-case</type>
|
|
151
|
+
<description>What this test verifies</description>
|
|
152
|
+
<code><![CDATA[
|
|
153
|
+
def test_example():
|
|
154
|
+
# Test code here
|
|
155
|
+
pass
|
|
156
|
+
]]></code>
|
|
157
|
+
</test>
|
|
158
|
+
</tests>
|
|
159
|
+
<remediation-checklist>
|
|
160
|
+
<item>Test to add first</item>
|
|
161
|
+
<item>Test to add second</item>
|
|
162
|
+
</remediation-checklist>
|
|
163
|
+
</response>"""
|
|
164
|
+
|
|
165
|
+
DOC_GEN_RESPONSE = """<response>
|
|
166
|
+
<summary>Documentation summary (1-2 sentences)</summary>
|
|
167
|
+
<sections>
|
|
168
|
+
<section name="Section Title">
|
|
169
|
+
<content>Section content in markdown</content>
|
|
170
|
+
</section>
|
|
171
|
+
</sections>
|
|
172
|
+
<findings>
|
|
173
|
+
<finding severity="info">
|
|
174
|
+
<title>Documentation gap or improvement</title>
|
|
175
|
+
<details>What needs documentation</details>
|
|
176
|
+
</finding>
|
|
177
|
+
</findings>
|
|
178
|
+
<remediation-checklist>
|
|
179
|
+
<item>Documentation improvement 1</item>
|
|
180
|
+
<item>Documentation improvement 2</item>
|
|
181
|
+
</remediation-checklist>
|
|
182
|
+
</response>"""
|
|
183
|
+
|
|
184
|
+
RELEASE_PREP_RESPONSE = """<response>
|
|
185
|
+
<summary>Release readiness assessment (1-2 sentences)</summary>
|
|
186
|
+
<verdict>approved|blocked|needs-review</verdict>
|
|
187
|
+
<confidence>high|medium|low</confidence>
|
|
188
|
+
<findings>
|
|
189
|
+
<finding severity="blocker|warning|info">
|
|
190
|
+
<title>Issue title</title>
|
|
191
|
+
<location>Component or area</location>
|
|
192
|
+
<details>Description of the issue</details>
|
|
193
|
+
<fix>Required action before release</fix>
|
|
194
|
+
</finding>
|
|
195
|
+
</findings>
|
|
196
|
+
<checklist>
|
|
197
|
+
<item status="pass|fail|skip">Check description</item>
|
|
198
|
+
</checklist>
|
|
199
|
+
<remediation-checklist>
|
|
200
|
+
<item>Pre-release action 1</item>
|
|
201
|
+
<item>Pre-release action 2</item>
|
|
202
|
+
</remediation-checklist>
|
|
203
|
+
</response>"""
|
|
204
|
+
|
|
205
|
+
DEPENDENCY_CHECK_RESPONSE = """<response>
|
|
206
|
+
<summary>Dependency security assessment (1-2 sentences)</summary>
|
|
207
|
+
<risk-level>critical|high|medium|low</risk-level>
|
|
208
|
+
<risk-score>0-100</risk-score>
|
|
209
|
+
<findings>
|
|
210
|
+
<finding severity="critical|high|medium|low">
|
|
211
|
+
<title>Vulnerability or issue</title>
|
|
212
|
+
<location>package@version</location>
|
|
213
|
+
<details>CVE or issue description</details>
|
|
214
|
+
<fix>Upgrade or mitigation recommendation</fix>
|
|
215
|
+
</finding>
|
|
216
|
+
</findings>
|
|
217
|
+
<remediation-checklist>
|
|
218
|
+
<item>Upgrade package X to version Y</item>
|
|
219
|
+
<item>Review dependency Z</item>
|
|
220
|
+
</remediation-checklist>
|
|
221
|
+
</response>"""
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
# =============================================================================
|
|
225
|
+
# Built-in Templates
|
|
226
|
+
# =============================================================================
|
|
227
|
+
|
|
228
|
+
BUILTIN_TEMPLATES: dict[str, XmlPromptTemplate] = {
|
|
229
|
+
"security-audit": XmlPromptTemplate(
|
|
230
|
+
name="security-audit",
|
|
231
|
+
schema_version="1.0",
|
|
232
|
+
response_format=SECURITY_AUDIT_RESPONSE,
|
|
233
|
+
),
|
|
234
|
+
"code-review": XmlPromptTemplate(
|
|
235
|
+
name="code-review",
|
|
236
|
+
schema_version="1.0",
|
|
237
|
+
response_format=CODE_REVIEW_RESPONSE,
|
|
238
|
+
),
|
|
239
|
+
"research": XmlPromptTemplate(
|
|
240
|
+
name="research",
|
|
241
|
+
schema_version="1.0",
|
|
242
|
+
response_format=RESEARCH_RESPONSE,
|
|
243
|
+
),
|
|
244
|
+
"bug-analysis": XmlPromptTemplate(
|
|
245
|
+
name="bug-analysis",
|
|
246
|
+
schema_version="1.0",
|
|
247
|
+
response_format=BUG_ANALYSIS_RESPONSE,
|
|
248
|
+
),
|
|
249
|
+
"perf-audit": XmlPromptTemplate(
|
|
250
|
+
name="perf-audit",
|
|
251
|
+
schema_version="1.0",
|
|
252
|
+
response_format=PERF_AUDIT_RESPONSE,
|
|
253
|
+
),
|
|
254
|
+
"refactor-plan": XmlPromptTemplate(
|
|
255
|
+
name="refactor-plan",
|
|
256
|
+
schema_version="1.0",
|
|
257
|
+
response_format=REFACTOR_PLAN_RESPONSE,
|
|
258
|
+
),
|
|
259
|
+
"test-gen": XmlPromptTemplate(
|
|
260
|
+
name="test-gen",
|
|
261
|
+
schema_version="1.0",
|
|
262
|
+
response_format=TEST_GEN_RESPONSE,
|
|
263
|
+
),
|
|
264
|
+
"doc-gen": XmlPromptTemplate(
|
|
265
|
+
name="doc-gen",
|
|
266
|
+
schema_version="1.0",
|
|
267
|
+
response_format=DOC_GEN_RESPONSE,
|
|
268
|
+
),
|
|
269
|
+
"release-prep": XmlPromptTemplate(
|
|
270
|
+
name="release-prep",
|
|
271
|
+
schema_version="1.0",
|
|
272
|
+
response_format=RELEASE_PREP_RESPONSE,
|
|
273
|
+
),
|
|
274
|
+
"dependency-check": XmlPromptTemplate(
|
|
275
|
+
name="dependency-check",
|
|
276
|
+
schema_version="1.0",
|
|
277
|
+
response_format=DEPENDENCY_CHECK_RESPONSE,
|
|
278
|
+
),
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def get_template(name: str) -> XmlPromptTemplate | None:
|
|
283
|
+
"""Get a built-in template by name.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
name: Template name (e.g., "security-audit", "code-review").
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
XmlPromptTemplate if found, None otherwise.
|
|
290
|
+
|
|
291
|
+
"""
|
|
292
|
+
return BUILTIN_TEMPLATES.get(name)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def list_templates() -> list[str]:
|
|
296
|
+
"""List all available built-in template names.
|
|
297
|
+
|
|
298
|
+
Returns:
|
|
299
|
+
List of template names.
|
|
300
|
+
|
|
301
|
+
"""
|
|
302
|
+
return list(BUILTIN_TEMPLATES.keys())
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def register_template(name: str, template: XmlPromptTemplate) -> None:
|
|
306
|
+
"""Register a custom template.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
name: Template name for lookup.
|
|
310
|
+
template: XmlPromptTemplate instance.
|
|
311
|
+
|
|
312
|
+
"""
|
|
313
|
+
BUILTIN_TEMPLATES[name] = template
|