empathy-framework 2.4.0__py3-none-any.whl → 3.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coach_wizards/__init__.py +13 -12
- coach_wizards/accessibility_wizard.py +12 -12
- coach_wizards/api_wizard.py +12 -12
- coach_wizards/base_wizard.py +26 -20
- coach_wizards/cicd_wizard.py +15 -13
- coach_wizards/code_reviewer_README.md +60 -0
- coach_wizards/code_reviewer_wizard.py +180 -0
- coach_wizards/compliance_wizard.py +12 -12
- coach_wizards/database_wizard.py +12 -12
- coach_wizards/debugging_wizard.py +12 -12
- coach_wizards/documentation_wizard.py +12 -12
- coach_wizards/generate_wizards.py +1 -2
- coach_wizards/localization_wizard.py +101 -19
- coach_wizards/migration_wizard.py +12 -12
- coach_wizards/monitoring_wizard.py +12 -12
- coach_wizards/observability_wizard.py +12 -12
- coach_wizards/performance_wizard.py +12 -12
- coach_wizards/prompt_engineering_wizard.py +661 -0
- coach_wizards/refactoring_wizard.py +12 -12
- coach_wizards/scaling_wizard.py +12 -12
- coach_wizards/security_wizard.py +12 -12
- coach_wizards/testing_wizard.py +12 -12
- empathy_framework-3.8.2.dist-info/METADATA +1176 -0
- empathy_framework-3.8.2.dist-info/RECORD +333 -0
- empathy_framework-3.8.2.dist-info/entry_points.txt +22 -0
- {empathy_framework-2.4.0.dist-info → empathy_framework-3.8.2.dist-info}/top_level.txt +5 -1
- empathy_healthcare_plugin/__init__.py +1 -2
- empathy_healthcare_plugin/monitors/__init__.py +9 -0
- empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py +315 -0
- empathy_healthcare_plugin/monitors/monitoring/__init__.py +44 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_checker.py +300 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_loader.py +214 -0
- empathy_healthcare_plugin/monitors/monitoring/sensor_parsers.py +306 -0
- empathy_healthcare_plugin/monitors/monitoring/trajectory_analyzer.py +389 -0
- empathy_llm_toolkit/__init__.py +7 -7
- empathy_llm_toolkit/agent_factory/__init__.py +53 -0
- empathy_llm_toolkit/agent_factory/adapters/__init__.py +85 -0
- empathy_llm_toolkit/agent_factory/adapters/autogen_adapter.py +312 -0
- empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +454 -0
- empathy_llm_toolkit/agent_factory/adapters/haystack_adapter.py +298 -0
- empathy_llm_toolkit/agent_factory/adapters/langchain_adapter.py +362 -0
- empathy_llm_toolkit/agent_factory/adapters/langgraph_adapter.py +333 -0
- empathy_llm_toolkit/agent_factory/adapters/native.py +228 -0
- empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +426 -0
- empathy_llm_toolkit/agent_factory/base.py +305 -0
- empathy_llm_toolkit/agent_factory/crews/__init__.py +67 -0
- empathy_llm_toolkit/agent_factory/crews/code_review.py +1113 -0
- empathy_llm_toolkit/agent_factory/crews/health_check.py +1246 -0
- empathy_llm_toolkit/agent_factory/crews/refactoring.py +1128 -0
- empathy_llm_toolkit/agent_factory/crews/security_audit.py +1018 -0
- empathy_llm_toolkit/agent_factory/decorators.py +286 -0
- empathy_llm_toolkit/agent_factory/factory.py +558 -0
- empathy_llm_toolkit/agent_factory/framework.py +192 -0
- empathy_llm_toolkit/agent_factory/memory_integration.py +324 -0
- empathy_llm_toolkit/agent_factory/resilient.py +320 -0
- empathy_llm_toolkit/claude_memory.py +14 -15
- empathy_llm_toolkit/cli/__init__.py +8 -0
- empathy_llm_toolkit/cli/sync_claude.py +487 -0
- empathy_llm_toolkit/code_health.py +186 -28
- empathy_llm_toolkit/config/__init__.py +29 -0
- empathy_llm_toolkit/config/unified.py +295 -0
- empathy_llm_toolkit/contextual_patterns.py +11 -12
- empathy_llm_toolkit/core.py +168 -53
- empathy_llm_toolkit/git_pattern_extractor.py +17 -13
- empathy_llm_toolkit/levels.py +6 -13
- empathy_llm_toolkit/pattern_confidence.py +14 -18
- empathy_llm_toolkit/pattern_resolver.py +10 -12
- empathy_llm_toolkit/pattern_summary.py +16 -14
- empathy_llm_toolkit/providers.py +194 -28
- empathy_llm_toolkit/routing/__init__.py +32 -0
- empathy_llm_toolkit/routing/model_router.py +362 -0
- empathy_llm_toolkit/security/IMPLEMENTATION_SUMMARY.md +413 -0
- empathy_llm_toolkit/security/PHASE2_COMPLETE.md +384 -0
- empathy_llm_toolkit/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- empathy_llm_toolkit/security/QUICK_REFERENCE.md +316 -0
- empathy_llm_toolkit/security/README.md +262 -0
- empathy_llm_toolkit/security/__init__.py +62 -0
- empathy_llm_toolkit/security/audit_logger.py +929 -0
- empathy_llm_toolkit/security/audit_logger_example.py +152 -0
- empathy_llm_toolkit/security/pii_scrubber.py +640 -0
- empathy_llm_toolkit/security/secrets_detector.py +678 -0
- empathy_llm_toolkit/security/secrets_detector_example.py +304 -0
- empathy_llm_toolkit/security/secure_memdocs.py +1192 -0
- empathy_llm_toolkit/security/secure_memdocs_example.py +278 -0
- empathy_llm_toolkit/session_status.py +20 -22
- empathy_llm_toolkit/state.py +28 -21
- empathy_llm_toolkit/wizards/__init__.py +38 -0
- empathy_llm_toolkit/wizards/base_wizard.py +364 -0
- empathy_llm_toolkit/wizards/customer_support_wizard.py +190 -0
- empathy_llm_toolkit/wizards/healthcare_wizard.py +362 -0
- empathy_llm_toolkit/wizards/patient_assessment_README.md +64 -0
- empathy_llm_toolkit/wizards/patient_assessment_wizard.py +193 -0
- empathy_llm_toolkit/wizards/technology_wizard.py +194 -0
- empathy_os/__init__.py +125 -84
- empathy_os/adaptive/__init__.py +13 -0
- empathy_os/adaptive/task_complexity.py +127 -0
- empathy_os/{monitoring.py → agent_monitoring.py} +28 -28
- empathy_os/cache/__init__.py +117 -0
- empathy_os/cache/base.py +166 -0
- empathy_os/cache/dependency_manager.py +253 -0
- empathy_os/cache/hash_only.py +248 -0
- empathy_os/cache/hybrid.py +390 -0
- empathy_os/cache/storage.py +282 -0
- empathy_os/cli.py +1516 -70
- empathy_os/cli_unified.py +597 -0
- empathy_os/config/__init__.py +63 -0
- empathy_os/config/xml_config.py +239 -0
- empathy_os/config.py +95 -37
- empathy_os/coordination.py +72 -68
- empathy_os/core.py +94 -107
- empathy_os/cost_tracker.py +74 -55
- empathy_os/dashboard/__init__.py +15 -0
- empathy_os/dashboard/server.py +743 -0
- empathy_os/discovery.py +17 -14
- empathy_os/emergence.py +21 -22
- empathy_os/exceptions.py +18 -30
- empathy_os/feedback_loops.py +30 -33
- empathy_os/levels.py +32 -35
- empathy_os/leverage_points.py +31 -32
- empathy_os/logging_config.py +19 -16
- empathy_os/memory/__init__.py +195 -0
- empathy_os/memory/claude_memory.py +466 -0
- empathy_os/memory/config.py +224 -0
- empathy_os/memory/control_panel.py +1298 -0
- empathy_os/memory/edges.py +179 -0
- empathy_os/memory/graph.py +567 -0
- empathy_os/memory/long_term.py +1194 -0
- empathy_os/memory/nodes.py +179 -0
- empathy_os/memory/redis_bootstrap.py +540 -0
- empathy_os/memory/security/__init__.py +31 -0
- empathy_os/memory/security/audit_logger.py +930 -0
- empathy_os/memory/security/pii_scrubber.py +640 -0
- empathy_os/memory/security/secrets_detector.py +678 -0
- empathy_os/memory/short_term.py +2119 -0
- empathy_os/memory/storage/__init__.py +15 -0
- empathy_os/memory/summary_index.py +583 -0
- empathy_os/memory/unified.py +619 -0
- empathy_os/metrics/__init__.py +12 -0
- empathy_os/metrics/prompt_metrics.py +190 -0
- empathy_os/models/__init__.py +136 -0
- empathy_os/models/__main__.py +13 -0
- empathy_os/models/cli.py +655 -0
- empathy_os/models/empathy_executor.py +354 -0
- empathy_os/models/executor.py +252 -0
- empathy_os/models/fallback.py +671 -0
- empathy_os/models/provider_config.py +563 -0
- empathy_os/models/registry.py +382 -0
- empathy_os/models/tasks.py +302 -0
- empathy_os/models/telemetry.py +548 -0
- empathy_os/models/token_estimator.py +378 -0
- empathy_os/models/validation.py +274 -0
- empathy_os/monitoring/__init__.py +52 -0
- empathy_os/monitoring/alerts.py +23 -0
- empathy_os/monitoring/alerts_cli.py +268 -0
- empathy_os/monitoring/multi_backend.py +271 -0
- empathy_os/monitoring/otel_backend.py +363 -0
- empathy_os/optimization/__init__.py +19 -0
- empathy_os/optimization/context_optimizer.py +272 -0
- empathy_os/pattern_library.py +30 -29
- empathy_os/persistence.py +35 -37
- empathy_os/platform_utils.py +261 -0
- empathy_os/plugins/__init__.py +28 -0
- empathy_os/plugins/base.py +361 -0
- empathy_os/plugins/registry.py +268 -0
- empathy_os/project_index/__init__.py +30 -0
- empathy_os/project_index/cli.py +335 -0
- empathy_os/project_index/crew_integration.py +430 -0
- empathy_os/project_index/index.py +425 -0
- empathy_os/project_index/models.py +501 -0
- empathy_os/project_index/reports.py +473 -0
- empathy_os/project_index/scanner.py +538 -0
- empathy_os/prompts/__init__.py +61 -0
- empathy_os/prompts/config.py +77 -0
- empathy_os/prompts/context.py +177 -0
- empathy_os/prompts/parser.py +285 -0
- empathy_os/prompts/registry.py +313 -0
- empathy_os/prompts/templates.py +208 -0
- empathy_os/redis_config.py +144 -58
- empathy_os/redis_memory.py +79 -77
- empathy_os/resilience/__init__.py +56 -0
- empathy_os/resilience/circuit_breaker.py +256 -0
- empathy_os/resilience/fallback.py +179 -0
- empathy_os/resilience/health.py +300 -0
- empathy_os/resilience/retry.py +209 -0
- empathy_os/resilience/timeout.py +135 -0
- empathy_os/routing/__init__.py +43 -0
- empathy_os/routing/chain_executor.py +433 -0
- empathy_os/routing/classifier.py +217 -0
- empathy_os/routing/smart_router.py +234 -0
- empathy_os/routing/wizard_registry.py +307 -0
- empathy_os/templates.py +19 -14
- empathy_os/trust/__init__.py +28 -0
- empathy_os/trust/circuit_breaker.py +579 -0
- empathy_os/trust_building.py +67 -58
- empathy_os/validation/__init__.py +19 -0
- empathy_os/validation/xml_validator.py +281 -0
- empathy_os/wizard_factory_cli.py +170 -0
- empathy_os/{workflows.py → workflow_commands.py} +131 -37
- empathy_os/workflows/__init__.py +360 -0
- empathy_os/workflows/base.py +1660 -0
- empathy_os/workflows/bug_predict.py +962 -0
- empathy_os/workflows/code_review.py +960 -0
- empathy_os/workflows/code_review_adapters.py +310 -0
- empathy_os/workflows/code_review_pipeline.py +720 -0
- empathy_os/workflows/config.py +600 -0
- empathy_os/workflows/dependency_check.py +648 -0
- empathy_os/workflows/document_gen.py +1069 -0
- empathy_os/workflows/documentation_orchestrator.py +1205 -0
- empathy_os/workflows/health_check.py +679 -0
- empathy_os/workflows/keyboard_shortcuts/__init__.py +39 -0
- empathy_os/workflows/keyboard_shortcuts/generators.py +386 -0
- empathy_os/workflows/keyboard_shortcuts/parsers.py +414 -0
- empathy_os/workflows/keyboard_shortcuts/prompts.py +295 -0
- empathy_os/workflows/keyboard_shortcuts/schema.py +193 -0
- empathy_os/workflows/keyboard_shortcuts/workflow.py +505 -0
- empathy_os/workflows/manage_documentation.py +804 -0
- empathy_os/workflows/new_sample_workflow1.py +146 -0
- empathy_os/workflows/new_sample_workflow1_README.md +150 -0
- empathy_os/workflows/perf_audit.py +687 -0
- empathy_os/workflows/pr_review.py +748 -0
- empathy_os/workflows/progress.py +445 -0
- empathy_os/workflows/progress_server.py +322 -0
- empathy_os/workflows/refactor_plan.py +693 -0
- empathy_os/workflows/release_prep.py +808 -0
- empathy_os/workflows/research_synthesis.py +404 -0
- empathy_os/workflows/secure_release.py +585 -0
- empathy_os/workflows/security_adapters.py +297 -0
- empathy_os/workflows/security_audit.py +1046 -0
- empathy_os/workflows/step_config.py +234 -0
- empathy_os/workflows/test5.py +125 -0
- empathy_os/workflows/test5_README.md +158 -0
- empathy_os/workflows/test_gen.py +1855 -0
- empathy_os/workflows/test_lifecycle.py +526 -0
- empathy_os/workflows/test_maintenance.py +626 -0
- empathy_os/workflows/test_maintenance_cli.py +590 -0
- empathy_os/workflows/test_maintenance_crew.py +821 -0
- empathy_os/workflows/xml_enhanced_crew.py +285 -0
- empathy_software_plugin/__init__.py +1 -2
- empathy_software_plugin/cli/__init__.py +120 -0
- empathy_software_plugin/cli/inspect.py +362 -0
- empathy_software_plugin/cli.py +49 -27
- empathy_software_plugin/plugin.py +4 -8
- empathy_software_plugin/wizards/__init__.py +42 -0
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +392 -0
- empathy_software_plugin/wizards/agent_orchestration_wizard.py +511 -0
- empathy_software_plugin/wizards/ai_collaboration_wizard.py +503 -0
- empathy_software_plugin/wizards/ai_context_wizard.py +441 -0
- empathy_software_plugin/wizards/ai_documentation_wizard.py +503 -0
- empathy_software_plugin/wizards/base_wizard.py +288 -0
- empathy_software_plugin/wizards/book_chapter_wizard.py +519 -0
- empathy_software_plugin/wizards/code_review_wizard.py +606 -0
- empathy_software_plugin/wizards/debugging/__init__.py +50 -0
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +414 -0
- empathy_software_plugin/wizards/debugging/config_loaders.py +442 -0
- empathy_software_plugin/wizards/debugging/fix_applier.py +469 -0
- empathy_software_plugin/wizards/debugging/language_patterns.py +383 -0
- empathy_software_plugin/wizards/debugging/linter_parsers.py +470 -0
- empathy_software_plugin/wizards/debugging/verification.py +369 -0
- empathy_software_plugin/wizards/enhanced_testing_wizard.py +537 -0
- empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +816 -0
- empathy_software_plugin/wizards/multi_model_wizard.py +501 -0
- empathy_software_plugin/wizards/pattern_extraction_wizard.py +422 -0
- empathy_software_plugin/wizards/pattern_retriever_wizard.py +400 -0
- empathy_software_plugin/wizards/performance/__init__.py +9 -0
- empathy_software_plugin/wizards/performance/bottleneck_detector.py +221 -0
- empathy_software_plugin/wizards/performance/profiler_parsers.py +278 -0
- empathy_software_plugin/wizards/performance/trajectory_analyzer.py +429 -0
- empathy_software_plugin/wizards/performance_profiling_wizard.py +305 -0
- empathy_software_plugin/wizards/prompt_engineering_wizard.py +425 -0
- empathy_software_plugin/wizards/rag_pattern_wizard.py +461 -0
- empathy_software_plugin/wizards/security/__init__.py +32 -0
- empathy_software_plugin/wizards/security/exploit_analyzer.py +290 -0
- empathy_software_plugin/wizards/security/owasp_patterns.py +241 -0
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +604 -0
- empathy_software_plugin/wizards/security_analysis_wizard.py +322 -0
- empathy_software_plugin/wizards/security_learning_wizard.py +740 -0
- empathy_software_plugin/wizards/tech_debt_wizard.py +726 -0
- empathy_software_plugin/wizards/testing/__init__.py +27 -0
- empathy_software_plugin/wizards/testing/coverage_analyzer.py +459 -0
- empathy_software_plugin/wizards/testing/quality_analyzer.py +531 -0
- empathy_software_plugin/wizards/testing/test_suggester.py +533 -0
- empathy_software_plugin/wizards/testing_wizard.py +274 -0
- hot_reload/README.md +473 -0
- hot_reload/__init__.py +62 -0
- hot_reload/config.py +84 -0
- hot_reload/integration.py +228 -0
- hot_reload/reloader.py +298 -0
- hot_reload/watcher.py +179 -0
- hot_reload/websocket.py +176 -0
- scaffolding/README.md +589 -0
- scaffolding/__init__.py +35 -0
- scaffolding/__main__.py +14 -0
- scaffolding/cli.py +240 -0
- test_generator/__init__.py +38 -0
- test_generator/__main__.py +14 -0
- test_generator/cli.py +226 -0
- test_generator/generator.py +325 -0
- test_generator/risk_analyzer.py +216 -0
- workflow_patterns/__init__.py +33 -0
- workflow_patterns/behavior.py +249 -0
- workflow_patterns/core.py +76 -0
- workflow_patterns/output.py +99 -0
- workflow_patterns/registry.py +255 -0
- workflow_patterns/structural.py +288 -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
- agents/code_inspection/patterns/inspection/recurring_B112.json +0 -18
- agents/code_inspection/patterns/inspection/recurring_F541.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_FORMAT.json +0 -25
- agents/code_inspection/patterns/inspection/recurring_bug_20250822_def456.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20250915_abc123.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_3c5b9951.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_97c0f72f.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a0871d53.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a9b6ec41.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_null_001.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_builtin.json +0 -16
- agents/compliance_anticipation_agent.py +0 -1427
- agents/epic_integration_wizard.py +0 -541
- agents/trust_building_behaviors.py +0 -891
- empathy_framework-2.4.0.dist-info/METADATA +0 -485
- empathy_framework-2.4.0.dist-info/RECORD +0 -102
- empathy_framework-2.4.0.dist-info/entry_points.txt +0 -6
- empathy_llm_toolkit/htmlcov/status.json +0 -1
- empathy_llm_toolkit/security/htmlcov/status.json +0 -1
- {empathy_framework-2.4.0.dist-info → empathy_framework-3.8.2.dist-info}/WHEEL +0 -0
- {empathy_framework-2.4.0.dist-info → empathy_framework-3.8.2.dist-info}/licenses/LICENSE +0 -0
empathy_os/trust_building.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Trust-Building Behaviors for Anticipatory AI Agents
|
|
1
|
+
"""Trust-Building Behaviors for Anticipatory AI Agents
|
|
3
2
|
|
|
4
3
|
Implements behaviors that build trust through anticipatory actions:
|
|
5
4
|
- Pre-format data for handoffs (reduce cognitive load)
|
|
@@ -29,8 +28,7 @@ logger = logging.getLogger(__name__)
|
|
|
29
28
|
|
|
30
29
|
@dataclass
|
|
31
30
|
class TrustSignal:
|
|
32
|
-
"""
|
|
33
|
-
A signal that indicates trust is building or eroding
|
|
31
|
+
"""A signal that indicates trust is building or eroding
|
|
34
32
|
|
|
35
33
|
Trust signals help track how trust evolves over time based on
|
|
36
34
|
observable behaviors and outcomes.
|
|
@@ -44,8 +42,7 @@ class TrustSignal:
|
|
|
44
42
|
|
|
45
43
|
|
|
46
44
|
class TrustBuildingBehaviors:
|
|
47
|
-
"""
|
|
48
|
-
Level 4 Anticipatory trust-building behaviors
|
|
45
|
+
"""Level 4 Anticipatory trust-building behaviors
|
|
49
46
|
|
|
50
47
|
Philosophy: Trust is earned through consistent, helpful actions that
|
|
51
48
|
demonstrate understanding of collaboration dynamics and proactive
|
|
@@ -76,6 +73,7 @@ class TrustBuildingBehaviors:
|
|
|
76
73
|
... instruction=instruction,
|
|
77
74
|
... ambiguities=["which system?", "what changes?"]
|
|
78
75
|
... )
|
|
76
|
+
|
|
79
77
|
"""
|
|
80
78
|
|
|
81
79
|
def __init__(self):
|
|
@@ -83,10 +81,12 @@ class TrustBuildingBehaviors:
|
|
|
83
81
|
self.trust_signals: list[TrustSignal] = []
|
|
84
82
|
|
|
85
83
|
def pre_format_for_handoff(
|
|
86
|
-
self,
|
|
84
|
+
self,
|
|
85
|
+
data: dict[str, Any],
|
|
86
|
+
recipient_role: str,
|
|
87
|
+
context: str,
|
|
87
88
|
) -> dict[str, Any]:
|
|
88
|
-
"""
|
|
89
|
-
Pre-format data for handoff to reduce recipient's cognitive load
|
|
89
|
+
"""Pre-format data for handoff to reduce recipient's cognitive load
|
|
90
90
|
|
|
91
91
|
**Trust Built:**
|
|
92
92
|
- "This AI understands my workflow"
|
|
@@ -109,6 +109,7 @@ class TrustBuildingBehaviors:
|
|
|
109
109
|
... context="board_meeting"
|
|
110
110
|
... )
|
|
111
111
|
>>> # Returns: executive summary format with key highlights
|
|
112
|
+
|
|
112
113
|
"""
|
|
113
114
|
logger.info(f"Pre-formatting data for handoff to {recipient_role} (context: {context})")
|
|
114
115
|
|
|
@@ -148,8 +149,7 @@ class TrustBuildingBehaviors:
|
|
|
148
149
|
detected_ambiguities: list[str],
|
|
149
150
|
context: dict[str, Any] | None = None,
|
|
150
151
|
) -> dict[str, Any]:
|
|
151
|
-
"""
|
|
152
|
-
Clarify ambiguous instructions before execution to prevent wasted effort
|
|
152
|
+
"""Clarify ambiguous instructions before execution to prevent wasted effort
|
|
153
153
|
|
|
154
154
|
**Trust Built:**
|
|
155
155
|
- "This AI doesn't make dangerous assumptions"
|
|
@@ -171,14 +171,16 @@ class TrustBuildingBehaviors:
|
|
|
171
171
|
... instruction=instruction,
|
|
172
172
|
... detected_ambiguities=ambiguities
|
|
173
173
|
... )
|
|
174
|
+
|
|
174
175
|
"""
|
|
175
176
|
logger.info(f"Clarifying ambiguous instruction: {instruction}")
|
|
176
177
|
|
|
177
|
-
|
|
178
|
+
clarifying_questions: list[dict[str, str]] = []
|
|
179
|
+
clarification: dict[str, Any] = {
|
|
178
180
|
"original_instruction": instruction,
|
|
179
181
|
"status": "needs_clarification",
|
|
180
182
|
"ambiguities_detected": detected_ambiguities,
|
|
181
|
-
"clarifying_questions":
|
|
183
|
+
"clarifying_questions": clarifying_questions,
|
|
182
184
|
"reasoning": (
|
|
183
185
|
"Detected ambiguities in instruction. Clarifying before acting "
|
|
184
186
|
"to prevent wasted effort or incorrect execution."
|
|
@@ -189,7 +191,7 @@ class TrustBuildingBehaviors:
|
|
|
189
191
|
# Generate specific clarifying questions
|
|
190
192
|
for ambiguity in detected_ambiguities:
|
|
191
193
|
question = self._generate_clarifying_question(instruction, ambiguity, context)
|
|
192
|
-
|
|
194
|
+
clarifying_questions.append(question)
|
|
193
195
|
|
|
194
196
|
# Record trust signal
|
|
195
197
|
self._record_trust_signal(
|
|
@@ -201,10 +203,11 @@ class TrustBuildingBehaviors:
|
|
|
201
203
|
return clarification
|
|
202
204
|
|
|
203
205
|
def volunteer_structure_during_stress(
|
|
204
|
-
self,
|
|
206
|
+
self,
|
|
207
|
+
stress_indicators: dict[str, Any],
|
|
208
|
+
available_scaffolding: list[str],
|
|
205
209
|
) -> dict[str, Any]:
|
|
206
|
-
"""
|
|
207
|
-
Volunteer structure/scaffolding during stressful situations
|
|
210
|
+
"""Volunteer structure/scaffolding during stressful situations
|
|
208
211
|
|
|
209
212
|
**Not pep talks, actual structural help:**
|
|
210
213
|
- Break down overwhelming tasks
|
|
@@ -231,14 +234,16 @@ class TrustBuildingBehaviors:
|
|
|
231
234
|
... stress_indicators=stress,
|
|
232
235
|
... available_scaffolding=scaffolding
|
|
233
236
|
... )
|
|
237
|
+
|
|
234
238
|
"""
|
|
235
239
|
logger.info("Volunteering structure during detected stress")
|
|
236
240
|
|
|
237
241
|
stress_level = self._assess_stress_level(stress_indicators)
|
|
238
242
|
|
|
239
|
-
|
|
243
|
+
offered_support: list[dict[str, Any]] = []
|
|
244
|
+
support: dict[str, Any] = {
|
|
240
245
|
"stress_assessment": {"level": stress_level, "indicators": stress_indicators},
|
|
241
|
-
"offered_support":
|
|
246
|
+
"offered_support": offered_support,
|
|
242
247
|
"reasoning": (
|
|
243
248
|
f"Detected {stress_level} stress. Volunteering structural support "
|
|
244
249
|
"to reduce cognitive load and provide actionable scaffolding."
|
|
@@ -249,30 +254,30 @@ class TrustBuildingBehaviors:
|
|
|
249
254
|
# Offer appropriate scaffolding based on stress level
|
|
250
255
|
if stress_level in ["high", "critical"]:
|
|
251
256
|
if "prioritization" in available_scaffolding:
|
|
252
|
-
|
|
257
|
+
offered_support.append(
|
|
253
258
|
{
|
|
254
259
|
"type": "prioritization",
|
|
255
260
|
"description": "Help prioritize tasks using urgency-importance matrix",
|
|
256
261
|
"immediate": True,
|
|
257
|
-
}
|
|
262
|
+
},
|
|
258
263
|
)
|
|
259
264
|
|
|
260
265
|
if "breakdown" in available_scaffolding:
|
|
261
|
-
|
|
266
|
+
offered_support.append(
|
|
262
267
|
{
|
|
263
268
|
"type": "task_breakdown",
|
|
264
269
|
"description": "Break overwhelming tasks into smaller, manageable steps",
|
|
265
270
|
"immediate": True,
|
|
266
|
-
}
|
|
271
|
+
},
|
|
267
272
|
)
|
|
268
273
|
|
|
269
274
|
if "templates" in available_scaffolding:
|
|
270
|
-
|
|
275
|
+
offered_support.append(
|
|
271
276
|
{
|
|
272
277
|
"type": "templates",
|
|
273
278
|
"description": "Provide templates to reduce creation effort",
|
|
274
279
|
"immediate": False,
|
|
275
|
-
}
|
|
280
|
+
},
|
|
276
281
|
)
|
|
277
282
|
|
|
278
283
|
# Record trust signal
|
|
@@ -285,10 +290,11 @@ class TrustBuildingBehaviors:
|
|
|
285
290
|
return support
|
|
286
291
|
|
|
287
292
|
def offer_proactive_help(
|
|
288
|
-
self,
|
|
293
|
+
self,
|
|
294
|
+
struggle_indicators: dict[str, Any],
|
|
295
|
+
available_help: list[str],
|
|
289
296
|
) -> dict[str, Any]:
|
|
290
|
-
"""
|
|
291
|
-
Proactively offer help when collaborator is struggling
|
|
297
|
+
"""Proactively offer help when collaborator is struggling
|
|
292
298
|
|
|
293
299
|
**Trust Built:**
|
|
294
300
|
- "This AI notices when I'm stuck"
|
|
@@ -309,14 +315,16 @@ class TrustBuildingBehaviors:
|
|
|
309
315
|
... struggle_indicators=indicators,
|
|
310
316
|
... available_help=help_types
|
|
311
317
|
... )
|
|
318
|
+
|
|
312
319
|
"""
|
|
313
320
|
logger.info("Offering proactive help based on struggle indicators")
|
|
314
321
|
|
|
315
322
|
struggle_type = self._classify_struggle(struggle_indicators)
|
|
316
323
|
|
|
317
|
-
|
|
324
|
+
help_offered: list[dict[str, str]] = []
|
|
325
|
+
offer: dict[str, Any] = {
|
|
318
326
|
"struggle_assessment": {"type": struggle_type, "indicators": struggle_indicators},
|
|
319
|
-
"help_offered":
|
|
327
|
+
"help_offered": help_offered,
|
|
320
328
|
"tone": "supportive_not_condescending",
|
|
321
329
|
"reasoning": (
|
|
322
330
|
f"Detected {struggle_type} struggle pattern. Offering relevant help "
|
|
@@ -328,22 +336,21 @@ class TrustBuildingBehaviors:
|
|
|
328
336
|
# Offer appropriate help based on struggle type
|
|
329
337
|
if struggle_type == "comprehension":
|
|
330
338
|
if "explanation" in available_help:
|
|
331
|
-
|
|
332
|
-
{
|
|
339
|
+
help_offered.append(
|
|
340
|
+
{
|
|
341
|
+
"type": "explanation",
|
|
342
|
+
"description": "Provide clearer explanation of concept",
|
|
343
|
+
},
|
|
333
344
|
)
|
|
334
345
|
if "examples" in available_help:
|
|
335
|
-
|
|
336
|
-
{"type": "examples", "description": "Show concrete examples"}
|
|
337
|
-
)
|
|
346
|
+
help_offered.append({"type": "examples", "description": "Show concrete examples"})
|
|
338
347
|
|
|
339
348
|
elif struggle_type == "execution":
|
|
340
349
|
if "debugging" in available_help:
|
|
341
|
-
|
|
342
|
-
{"type": "debugging", "description": "Help debug the issue"}
|
|
343
|
-
)
|
|
350
|
+
help_offered.append({"type": "debugging", "description": "Help debug the issue"})
|
|
344
351
|
if "guidance" in available_help:
|
|
345
|
-
|
|
346
|
-
{"type": "step_by_step", "description": "Provide step-by-step guidance"}
|
|
352
|
+
help_offered.append(
|
|
353
|
+
{"type": "step_by_step", "description": "Provide step-by-step guidance"},
|
|
347
354
|
)
|
|
348
355
|
|
|
349
356
|
# Record trust signal
|
|
@@ -356,11 +363,11 @@ class TrustBuildingBehaviors:
|
|
|
356
363
|
return offer
|
|
357
364
|
|
|
358
365
|
def get_trust_trajectory(self) -> dict[str, Any]:
|
|
359
|
-
"""
|
|
360
|
-
Get trust trajectory based on recorded signals
|
|
366
|
+
"""Get trust trajectory based on recorded signals
|
|
361
367
|
|
|
362
368
|
Returns:
|
|
363
369
|
Analysis of trust evolution over time
|
|
370
|
+
|
|
364
371
|
"""
|
|
365
372
|
if not self.trust_signals:
|
|
366
373
|
return {"status": "insufficient_data", "trajectory": "unknown", "signal_count": 0}
|
|
@@ -396,12 +403,11 @@ class TrustBuildingBehaviors:
|
|
|
396
403
|
"""Determine appropriate format based on role and context"""
|
|
397
404
|
if role in ["executive", "manager", "director"]:
|
|
398
405
|
return "executive_summary"
|
|
399
|
-
|
|
406
|
+
if role in ["developer", "engineer", "analyst"]:
|
|
400
407
|
return "technical_detail"
|
|
401
|
-
|
|
408
|
+
if role in ["team_lead", "coordinator"]:
|
|
402
409
|
return "action_oriented"
|
|
403
|
-
|
|
404
|
-
return "general"
|
|
410
|
+
return "general"
|
|
405
411
|
|
|
406
412
|
def _create_executive_summary(self, data: dict, context: str) -> dict:
|
|
407
413
|
"""Create executive summary format"""
|
|
@@ -455,20 +461,25 @@ class TrustBuildingBehaviors:
|
|
|
455
461
|
"""Extract technical notes"""
|
|
456
462
|
return [f"Data structure: {type(data).__name__}"]
|
|
457
463
|
|
|
458
|
-
def _extract_immediate_actions(self, data: dict) -> list[str]:
|
|
464
|
+
def _extract_immediate_actions(self, data: dict[str, Any]) -> list[str]:
|
|
459
465
|
"""Extract immediate actions"""
|
|
460
466
|
if "actions" in data:
|
|
461
|
-
|
|
467
|
+
actions: list[str] = data["actions"][:5]
|
|
468
|
+
return actions
|
|
462
469
|
return ["Review data and determine next steps"]
|
|
463
470
|
|
|
464
|
-
def _extract_priorities(self, data: dict) -> list[str]:
|
|
471
|
+
def _extract_priorities(self, data: dict[str, Any]) -> list[str]:
|
|
465
472
|
"""Extract priorities"""
|
|
466
473
|
if "priorities" in data:
|
|
467
|
-
|
|
474
|
+
priorities: list[str] = data["priorities"]
|
|
475
|
+
return priorities
|
|
468
476
|
return []
|
|
469
477
|
|
|
470
478
|
def _generate_clarifying_question(
|
|
471
|
-
self,
|
|
479
|
+
self,
|
|
480
|
+
instruction: str,
|
|
481
|
+
ambiguity: str,
|
|
482
|
+
context: dict | None,
|
|
472
483
|
) -> dict[str, str]:
|
|
473
484
|
"""Generate a specific clarifying question"""
|
|
474
485
|
return {
|
|
@@ -484,21 +495,19 @@ class TrustBuildingBehaviors:
|
|
|
484
495
|
|
|
485
496
|
if stress_score >= 4:
|
|
486
497
|
return "critical"
|
|
487
|
-
|
|
498
|
+
if stress_score >= 3:
|
|
488
499
|
return "high"
|
|
489
|
-
|
|
500
|
+
if stress_score >= 2:
|
|
490
501
|
return "moderate"
|
|
491
|
-
|
|
492
|
-
return "low"
|
|
502
|
+
return "low"
|
|
493
503
|
|
|
494
504
|
def _classify_struggle(self, indicators: dict) -> str:
|
|
495
505
|
"""Classify type of struggle"""
|
|
496
506
|
if "repeated_errors" in indicators:
|
|
497
507
|
return "execution"
|
|
498
|
-
|
|
508
|
+
if "time_on_task" in indicators:
|
|
499
509
|
return "comprehension"
|
|
500
|
-
|
|
501
|
-
return "general"
|
|
510
|
+
return "general"
|
|
502
511
|
|
|
503
512
|
def _record_trust_signal(self, signal_type: str, behavior: str, evidence: str | None = None):
|
|
504
513
|
"""Record a trust signal"""
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""XML validation for XML-enhanced prompts.
|
|
2
|
+
|
|
3
|
+
Provides schema validation and graceful fallbacks.
|
|
4
|
+
|
|
5
|
+
Copyright 2026 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from empathy_os.validation.xml_validator import (
|
|
10
|
+
ValidationResult,
|
|
11
|
+
XMLValidator,
|
|
12
|
+
validate_xml_response,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"XMLValidator",
|
|
17
|
+
"ValidationResult",
|
|
18
|
+
"validate_xml_response",
|
|
19
|
+
]
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""XML validation for response verification.
|
|
2
|
+
|
|
3
|
+
Validates XML-structured responses with graceful fallbacks.
|
|
4
|
+
|
|
5
|
+
Copyright 2026 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import xml.etree.ElementTree as ET
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class ValidationResult:
|
|
17
|
+
"""Result of XML validation.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
is_valid: Whether XML is valid
|
|
21
|
+
error_message: Error message if invalid
|
|
22
|
+
parsed_data: Parsed data if valid
|
|
23
|
+
fallback_used: Whether fallback parsing was used
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
is_valid: bool
|
|
27
|
+
error_message: str | None = None
|
|
28
|
+
parsed_data: dict[str, Any] | None = None
|
|
29
|
+
fallback_used: bool = False
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class XMLValidator:
|
|
33
|
+
"""Validates XML responses with graceful fallbacks.
|
|
34
|
+
|
|
35
|
+
Supports:
|
|
36
|
+
- Well-formedness validation
|
|
37
|
+
- XSD schema validation (optional)
|
|
38
|
+
- Graceful fallback on validation errors
|
|
39
|
+
- Schema caching for performance
|
|
40
|
+
|
|
41
|
+
Usage:
|
|
42
|
+
validator = XMLValidator()
|
|
43
|
+
result = validator.validate("<thinking>...</thinking>")
|
|
44
|
+
|
|
45
|
+
if result.is_valid:
|
|
46
|
+
data = result.parsed_data
|
|
47
|
+
else:
|
|
48
|
+
# Use fallback parsing
|
|
49
|
+
data = fallback_parse(response)
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
schema_dir: str = ".empathy/schemas",
|
|
55
|
+
strict: bool = False,
|
|
56
|
+
enable_xsd: bool = False,
|
|
57
|
+
):
|
|
58
|
+
"""Initialize validator.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
schema_dir: Directory containing XSD schemas
|
|
62
|
+
strict: If True, fail on validation errors. If False, use fallback.
|
|
63
|
+
enable_xsd: Enable XSD schema validation (requires lxml)
|
|
64
|
+
"""
|
|
65
|
+
self.schema_dir = Path(schema_dir)
|
|
66
|
+
self.strict = strict
|
|
67
|
+
self.enable_xsd = enable_xsd
|
|
68
|
+
self._schema_cache: dict[str, Any] = {}
|
|
69
|
+
|
|
70
|
+
# Try to import lxml for XSD validation
|
|
71
|
+
self._lxml_available = False
|
|
72
|
+
if enable_xsd:
|
|
73
|
+
try:
|
|
74
|
+
from lxml import etree as lxml_etree # noqa: F401
|
|
75
|
+
|
|
76
|
+
self._lxml_available = True
|
|
77
|
+
except ImportError:
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
def validate(self, xml_string: str, schema_name: str | None = None) -> ValidationResult:
|
|
81
|
+
"""Validate XML string.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
xml_string: XML content to validate
|
|
85
|
+
schema_name: Optional XSD schema name (e.g., "agent_response")
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
ValidationResult with validation status and parsed data
|
|
89
|
+
"""
|
|
90
|
+
# Step 1: Well-formedness validation
|
|
91
|
+
try:
|
|
92
|
+
root = ET.fromstring(xml_string) # nosec B314 - parsing trusted LLM responses
|
|
93
|
+
except ET.ParseError as e:
|
|
94
|
+
if self.strict:
|
|
95
|
+
return ValidationResult(
|
|
96
|
+
is_valid=False,
|
|
97
|
+
error_message=f"XML parsing failed: {e}",
|
|
98
|
+
fallback_used=False,
|
|
99
|
+
)
|
|
100
|
+
# Try fallback parsing
|
|
101
|
+
return self._fallback_parse(xml_string, str(e))
|
|
102
|
+
|
|
103
|
+
# Step 2: XSD schema validation (optional)
|
|
104
|
+
if schema_name and self.enable_xsd and self._lxml_available:
|
|
105
|
+
schema_result = self._validate_with_xsd(xml_string, schema_name)
|
|
106
|
+
if not schema_result.is_valid:
|
|
107
|
+
if self.strict:
|
|
108
|
+
return schema_result
|
|
109
|
+
# Continue with parsed data despite schema error
|
|
110
|
+
return ValidationResult(
|
|
111
|
+
is_valid=True,
|
|
112
|
+
parsed_data=self._extract_data(root),
|
|
113
|
+
fallback_used=True,
|
|
114
|
+
error_message=f"Schema validation failed: {schema_result.error_message}",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Step 3: Extract structured data
|
|
118
|
+
parsed_data = self._extract_data(root)
|
|
119
|
+
|
|
120
|
+
return ValidationResult(
|
|
121
|
+
is_valid=True,
|
|
122
|
+
parsed_data=parsed_data,
|
|
123
|
+
fallback_used=False,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
def _validate_with_xsd(self, xml_string: str, schema_name: str) -> ValidationResult:
|
|
127
|
+
"""Validate XML against XSD schema.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
xml_string: XML content
|
|
131
|
+
schema_name: Schema file name (without .xsd extension)
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
ValidationResult
|
|
135
|
+
"""
|
|
136
|
+
if not self._lxml_available:
|
|
137
|
+
return ValidationResult(
|
|
138
|
+
is_valid=False,
|
|
139
|
+
error_message="lxml not available for XSD validation",
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
from lxml import etree as lxml_etree
|
|
144
|
+
except ImportError:
|
|
145
|
+
return ValidationResult(
|
|
146
|
+
is_valid=False,
|
|
147
|
+
error_message="lxml import failed",
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# Load schema
|
|
151
|
+
schema_path = self.schema_dir / f"{schema_name}.xsd"
|
|
152
|
+
if not schema_path.exists():
|
|
153
|
+
return ValidationResult(
|
|
154
|
+
is_valid=False,
|
|
155
|
+
error_message=f"Schema not found: {schema_path}",
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Check cache
|
|
159
|
+
if schema_name not in self._schema_cache:
|
|
160
|
+
try:
|
|
161
|
+
schema_doc = lxml_etree.parse(str(schema_path))
|
|
162
|
+
self._schema_cache[schema_name] = lxml_etree.XMLSchema(schema_doc)
|
|
163
|
+
except Exception as e:
|
|
164
|
+
return ValidationResult(
|
|
165
|
+
is_valid=False,
|
|
166
|
+
error_message=f"Schema loading failed: {e}",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
schema = self._schema_cache[schema_name]
|
|
170
|
+
|
|
171
|
+
# Validate
|
|
172
|
+
try:
|
|
173
|
+
xml_doc = lxml_etree.fromstring(xml_string.encode("utf-8"))
|
|
174
|
+
is_valid = schema.validate(xml_doc)
|
|
175
|
+
|
|
176
|
+
if not is_valid:
|
|
177
|
+
error_log = schema.error_log
|
|
178
|
+
return ValidationResult(
|
|
179
|
+
is_valid=False,
|
|
180
|
+
error_message=f"Schema validation failed: {error_log}",
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
return ValidationResult(is_valid=True)
|
|
184
|
+
|
|
185
|
+
except Exception as e:
|
|
186
|
+
return ValidationResult(
|
|
187
|
+
is_valid=False,
|
|
188
|
+
error_message=f"Validation error: {e}",
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
def _fallback_parse(self, xml_string: str, error: str) -> ValidationResult:
|
|
192
|
+
"""Attempt fallback parsing of malformed XML.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
xml_string: XML string that failed to parse
|
|
196
|
+
error: Parse error message
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
ValidationResult with fallback data
|
|
200
|
+
"""
|
|
201
|
+
# Try to extract data using regex patterns
|
|
202
|
+
import re
|
|
203
|
+
|
|
204
|
+
data: dict[str, Any] = {}
|
|
205
|
+
|
|
206
|
+
# Extract thinking content
|
|
207
|
+
thinking_match = re.search(r"<thinking[^>]*>(.*?)</thinking>", xml_string, re.DOTALL)
|
|
208
|
+
if thinking_match:
|
|
209
|
+
data["thinking"] = thinking_match.group(1).strip()
|
|
210
|
+
|
|
211
|
+
# Extract answer content
|
|
212
|
+
answer_match = re.search(r"<answer[^>]*>(.*?)</answer>", xml_string, re.DOTALL)
|
|
213
|
+
if answer_match:
|
|
214
|
+
data["answer"] = answer_match.group(1).strip()
|
|
215
|
+
|
|
216
|
+
# If we extracted something, consider it a partial success
|
|
217
|
+
if data:
|
|
218
|
+
return ValidationResult(
|
|
219
|
+
is_valid=True,
|
|
220
|
+
parsed_data=data,
|
|
221
|
+
fallback_used=True,
|
|
222
|
+
error_message=f"XML parsing failed, used fallback: {error}",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Complete failure
|
|
226
|
+
return ValidationResult(
|
|
227
|
+
is_valid=False,
|
|
228
|
+
error_message=f"XML parsing and fallback failed: {error}",
|
|
229
|
+
fallback_used=True,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
def _extract_data(self, root: ET.Element) -> dict[str, Any]:
|
|
233
|
+
"""Extract structured data from parsed XML.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
root: Parsed XML root element
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Dictionary with extracted data
|
|
240
|
+
"""
|
|
241
|
+
data: dict[str, Any] = {}
|
|
242
|
+
|
|
243
|
+
# Extract all child elements
|
|
244
|
+
for child in root:
|
|
245
|
+
# Handle nested elements
|
|
246
|
+
if len(child):
|
|
247
|
+
data[child.tag] = self._extract_data(child)
|
|
248
|
+
else:
|
|
249
|
+
# Leaf node - get text content
|
|
250
|
+
data[child.tag] = child.text if child.text else ""
|
|
251
|
+
|
|
252
|
+
# Also store root attributes
|
|
253
|
+
if root.attrib:
|
|
254
|
+
data["_attributes"] = dict(root.attrib)
|
|
255
|
+
|
|
256
|
+
return data
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def validate_xml_response(
|
|
260
|
+
response: str,
|
|
261
|
+
schema_name: str | None = None,
|
|
262
|
+
strict: bool = False,
|
|
263
|
+
) -> ValidationResult:
|
|
264
|
+
"""Convenience function to validate XML response.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
response: XML response string
|
|
268
|
+
schema_name: Optional XSD schema name
|
|
269
|
+
strict: If True, fail on validation errors
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
ValidationResult
|
|
273
|
+
|
|
274
|
+
Example:
|
|
275
|
+
>>> response = "<thinking>Analysis</thinking><answer>Result</answer>"
|
|
276
|
+
>>> result = validate_xml_response(response)
|
|
277
|
+
>>> if result.is_valid:
|
|
278
|
+
... print(result.parsed_data)
|
|
279
|
+
"""
|
|
280
|
+
validator = XMLValidator(strict=strict)
|
|
281
|
+
return validator.validate(response, schema_name)
|