dialectical-framework 1.6.4__tar.gz → 1.6.5__tar.gz
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.
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/PKG-INFO +1 -1
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/pyproject.toml +1 -1
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/system_prompts.py +11 -3
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/apps.py +7 -3
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/conversation_facilitator.py +3 -2
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/aspect_generation.py +72 -20
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/source_digest.py +38 -9
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/composite_input_resolver.py +26 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/verbatim_input_resolver.py +75 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/protocols/input_resolver.py +28 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/LICENSE +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/PATENTS +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/README.md +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/advisor/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/advisor/advisor.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/advisor/system_prompts.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/advisor/tools/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/advisor/tools/anchor.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/advisor/tools/explore.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/advisor/tools/ingest.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/advisor/tools/sync.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/agent_context.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/analyst.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/skills/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/skills/anchor_theses.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/skills/edit_perspective.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/skills/expand_polarities.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/skills/find_polarities.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/skills/introduce_polarity.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/skills/surface_theses.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/tools/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/tools/create_dx_input.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/analyst/tools/place_statement.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/execution_report.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/explorer.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/skills/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/skills/build_wheels.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/skills/explore_transformations.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/skills/generate_synthesis.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/system_prompts.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/tools/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/tools/create_nexus.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/tools/expand_nexus.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/tools/generate_synthesis.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/explorer/tools/present_exploration.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/add_input.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/digest_input.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/discard.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/get_schema.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/inspect_node.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/present_analysis.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/query_graph.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/read_digest.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/orchestrator/tools/read_input.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/reasonable_concern.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/stream_events.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/ac_re_taxonomy.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/action_extraction.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/add_input.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/ai_dto/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/ai_dto/statement_dto.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/ai_dto/statements_deck_dto.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/antithesis_classification.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/antithesis_extraction.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/antithetical_thesis_detection.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/aspect_classification.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/causality_estimator.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/causality_estimator_balanced.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/causality_estimator_criteria.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/causality_estimator_desirable.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/causality_estimator_feasible.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/causality_estimator_realistic.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/causality_normalizer.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality/estimator_resolver.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/causality_estimation.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/control_statements_check.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/create_dx_input.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/create_nexus.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/diagonal_oppositions_check.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/dialectical_context.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/discard.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/display_text_edit.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/expand_nexus.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/perspective_combination.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/perspective_validation.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/positive_ac_re_apex_derivation.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/scoring_scales.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/statement_classification.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/statement_deduplication.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/statement_headline.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/statement_placement.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/synthesis_generation.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/thesis_extraction.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/transformation_audit.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/concerns/transformation_generation.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/dialectical_reasoning.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/enums/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/enums/causality_preset.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/enums/di.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/events/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/events/graph_event.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/events/graph_event_bus.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/exceptions/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/exceptions/node_errors.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/exceptions/resolver_errors.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/dialexity_input_resolver.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/estimation_manager.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/mixins/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/mixins/incremental_build_mixin.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/mixins/intent_mixin.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/mixins/persistable_mixin.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/assessable_entity.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/base_node.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/case.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/cycle.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/estimation.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/ideas.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/input.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/nexus.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/perspective.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/polarity.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/rationale.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/statement.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/synthesis.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/transformation.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/transition.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/nodes/wheel.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationship_manager.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/action_reflection_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/belongs_to_cycle_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/belongs_to_nexus_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/changed_to_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/contradiction_of_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/critiques_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/distilled_to_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/estimates_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/explains_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/has_input_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/has_statement_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/has_wheel_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/immutable_structure.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/is_source_of_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/is_target_of_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/negative_side_of_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/opposite_direction_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/opposite_of_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/polarity_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/positive_side_of_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/provides_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/relationships/synthesis_of_relationship.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/rendering.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/case_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/cycle_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/input_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/nexus_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/node_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/perspective_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/polarity_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/schema_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/statement_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/transformation_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/repositories/wheel_repository.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/scope_context.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/wheel_segment.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/graph/wheel_segment_polar_pair.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/protocols/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/protocols/has_config.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/settings.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/__init__.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/bedrock_provider.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/concurrency.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/dc_replace.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/decompose_probability_uniformly.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/edge_context.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/effect_logger.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/input_context.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/order_transitions.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/sequence_generation.py +0 -0
- {dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/utils/use_brain.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dialectical-framework
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.5
|
|
4
4
|
Summary: A dialectical framework for augmented intelligence. AI reasoning powered with dialectics supports humans in: system optimization (psychology, engineering, business, politics, etc.); dispute resolution (mediation, conflicts, negotiations, etc.); decision-making (dilemmas, challenging situations, win-win, etc.).
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: dialectics,dialectical-reasoning,synthesis,thesis-antithesis,ai,artificial-intelligence,llm,reasoning-framework,philosophy,logic,argumentation,conflict-resolution,decision-making,critical-thinking,semantic-graph,mirascope,pydantic,perspectives,polarity-reasoning
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "dialectical-framework"
|
|
3
|
-
version = "1.6.
|
|
3
|
+
version = "1.6.5"
|
|
4
4
|
description = "A dialectical framework for augmented intelligence. AI reasoning powered with dialectics supports humans in: system optimization (psychology, engineering, business, politics, etc.); dispute resolution (mediation, conflicts, negotiations, etc.); decision-making (dilemmas, challenging situations, win-win, etc.)."
|
|
5
5
|
authors = ["Evaldas Taroza <evaldas@dialexity.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -53,7 +53,7 @@ These words map to DIFFERENT tools depending on what's in scope:
|
|
|
53
53
|
|
|
54
54
|
## How to Work
|
|
55
55
|
|
|
56
|
-
Act on clear intent for analysis actions (analyze, find/expand, anchor) — never ask "shall I analyze this?", just do it. Nexus creation
|
|
56
|
+
Act on clear intent for analysis actions (analyze, find/expand, anchor) — never ask "shall I analyze this?", just do it. Nexus creation follows the same rule: create immediately when the perspectives to group are clear. Only pause when the request is genuinely underspecified or a similar exploration already exists (see Exploration Setup).
|
|
57
57
|
Always check resonance AFTER presenting results — but never before acting.
|
|
58
58
|
|
|
59
59
|
- If the user describes a situation: call `analyze` or `introduce_polarity` depending on whether a clear tension is stated
|
|
@@ -106,13 +106,21 @@ pull"), not raw numbers, unless the app preamble or the user asks for the figure
|
|
|
106
106
|
|
|
107
107
|
## Exploration Setup (Nexus)
|
|
108
108
|
|
|
109
|
+
"Nexus" is the internal name for what the user calls an **Exploration** — same
|
|
110
|
+
thing. Use "nexus" freely in your own reasoning and when referring to the
|
|
111
|
+
`create_nexus`/`expand_nexus` tools, but always say "exploration" in anything
|
|
112
|
+
the user reads.
|
|
113
|
+
|
|
109
114
|
When the user wants to explore interactions between perspectives:
|
|
110
115
|
|
|
111
116
|
**Before creating:**
|
|
112
117
|
1. Check existing nexuses via `present_analysis`.
|
|
113
118
|
2. If a nexus with similar intent exists — suggest `expand_nexus` to add perspectives to it.
|
|
114
119
|
Only create separate if user deliberately wants a different scope.
|
|
115
|
-
3.
|
|
120
|
+
3. Create immediately when the perspectives to group are clear (named or unambiguous
|
|
121
|
+
from context). Only pause to ask when the request is genuinely underspecified —
|
|
122
|
+
no perspectives identifiable — or when Deduplication below applies. Do NOT ask the
|
|
123
|
+
user to state an exploration intent: infer it internally (see Intent below).
|
|
116
124
|
|
|
117
125
|
**Grouping (which perspectives to combine):**
|
|
118
126
|
- Prefer perspectives from different polarities (different T-A oppositions). Transformations
|
|
@@ -130,7 +138,7 @@ When the user wants to explore interactions between perspectives:
|
|
|
130
138
|
- Derive a concise title (1-3 words) from the intent silently. No confirmation needed.
|
|
131
139
|
|
|
132
140
|
**Deduplication (always communicate to the user):**
|
|
133
|
-
- If a nexus with similar intent exists, tell the user: name the existing
|
|
141
|
+
- If a nexus with similar intent exists, tell the user: name the existing exploration, show its intent,
|
|
134
142
|
and ask whether to add perspectives there or create a separate exploration.
|
|
135
143
|
- Never silently redirect to `expand_nexus` — the user must see why and agree.
|
|
136
144
|
- Only skip the prompt if the user explicitly names the existing nexus themselves.
|
{dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/agents/apps.py
RENAMED
|
@@ -301,8 +301,9 @@ both angles and both blindspots together. A complete map of one tension.
|
|
|
301
301
|
|
|
302
302
|
### Exploration Phase
|
|
303
303
|
|
|
304
|
-
**Nexus** — the exploration space where positions interact.
|
|
305
|
-
exploration", "
|
|
304
|
+
**Nexus** — the exploration space where positions interact. Internal term;
|
|
305
|
+
say **"exploration"** to the user, never "nexus". Use: "this exploration",
|
|
306
|
+
"the exploration", "this group of positions".
|
|
306
307
|
|
|
307
308
|
**Wheel** — causal arrangement of positions into a cycle. Use: "wheel",
|
|
308
309
|
"causal arrangement", "how these positions connect causally".
|
|
@@ -369,8 +370,11 @@ The "blindspot" label belongs ONLY to A+ and A- (the opposition's territory).
|
|
|
369
370
|
T+ and T- are the holder's own visible territory — never label them as blindspots.
|
|
370
371
|
|
|
371
372
|
- Never mention tool names, pipelines, or graph operations.
|
|
372
|
-
- User-facing structural terms (Wheel,
|
|
373
|
+
- User-facing structural terms (Wheel, Cycle, Transformation, Position,
|
|
373
374
|
Polarity) are fine to use — these are part of the UX vocabulary.
|
|
375
|
+
- "Nexus" is an internal name for what the user calls an **Exploration** —
|
|
376
|
+
they are the same thing. Always say "exploration" to the user; never surface
|
|
377
|
+
the word "Nexus" (some power users know it, but default to "exploration").
|
|
374
378
|
- Position labels (T+, T-, A+, A-) can be introduced once the user understands
|
|
375
379
|
the structure, or when they make presentation clearer. Don't hide them
|
|
376
380
|
dogmatically — use them when they serve communication.
|
|
@@ -33,6 +33,7 @@ from dialectical_framework.utils.use_brain import use_brain
|
|
|
33
33
|
from mirascope.llm import TextChunk, ThoughtChunk
|
|
34
34
|
|
|
35
35
|
if TYPE_CHECKING:
|
|
36
|
+
from mirascope.llm import UserContent
|
|
36
37
|
from mirascope.llm.calls import AsyncCall
|
|
37
38
|
from mirascope.llm.responses import AsyncResponse
|
|
38
39
|
|
|
@@ -116,7 +117,7 @@ class ConversationFacilitator(SettingsAware):
|
|
|
116
117
|
async def submit(
|
|
117
118
|
self,
|
|
118
119
|
response_model: type[T],
|
|
119
|
-
user_content:
|
|
120
|
+
user_content: UserContent,
|
|
120
121
|
max_tool_rounds: int = 10,
|
|
121
122
|
) -> T:
|
|
122
123
|
"""
|
|
@@ -162,7 +163,7 @@ class ConversationFacilitator(SettingsAware):
|
|
|
162
163
|
async def submit_stream(
|
|
163
164
|
self,
|
|
164
165
|
response_model: type[T],
|
|
165
|
-
user_content:
|
|
166
|
+
user_content: UserContent,
|
|
166
167
|
max_tool_rounds: int = 10,
|
|
167
168
|
) -> AsyncGenerator[StreamEvent, None]:
|
|
168
169
|
"""
|
|
@@ -100,17 +100,17 @@ Your task is to generate aspects (T+, T-, A+, A-) for a thesis-antithesis pair.
|
|
|
100
100
|
|
|
101
101
|
## Examples
|
|
102
102
|
|
|
103
|
+
Each tetrad resolves into two diagonal contradiction pairs. A pair shares one
|
|
104
|
+
**axis** — a single dimension on which its two aspects sit at opposite ends, so
|
|
105
|
+
they cannot both hold at once. Name the axis first, then place each pole on it.
|
|
106
|
+
|
|
103
107
|
T = Love, A = Indifference:
|
|
104
|
-
- T+ = Bonding (love that
|
|
105
|
-
- T- = Enmeshment (love
|
|
106
|
-
- A+ = Autonomy (independence that also deepens the bond)
|
|
107
|
-
- A- = Alienation (independence overdeveloped, severing the bond)
|
|
108
|
+
- Axis "closeness": T+ = Bonding (love that makes room for autonomy) ⟷ A- = Alienation (independence severing the bond)
|
|
109
|
+
- Axis "self-standing": A+ = Autonomy (independence that deepens the bond) ⟷ T- = Enmeshment (love smothering autonomy)
|
|
108
110
|
|
|
109
111
|
T = Courage, A = Fear:
|
|
110
|
-
- T+ = Trust
|
|
111
|
-
- T- = Foolhardiness
|
|
112
|
-
- A+ = Prudence
|
|
113
|
-
- A- = Paranoia
|
|
112
|
+
- Axis "risk-taking": T+ = Trust ⟷ A- = Paranoia
|
|
113
|
+
- Axis "caution": A+ = Prudence ⟷ T- = Foolhardiness
|
|
114
114
|
|
|
115
115
|
Generate aspect statements that fit the semantic structure."""
|
|
116
116
|
|
|
@@ -139,19 +139,56 @@ class AspectDto(BaseModel):
|
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
class ContradictionPairDto(BaseModel):
|
|
142
|
-
"""Two aspects that form a contradiction pair.
|
|
142
|
+
"""Two aspects that form a diagonal contradiction pair.
|
|
143
|
+
|
|
144
|
+
The pair is defined by its `axis`: a single dimension on which the two
|
|
145
|
+
aspects sit at opposite ends, so they cannot both hold at once. The model
|
|
146
|
+
must name the axis first, which forces a genuine opposition rather than two
|
|
147
|
+
independently-plausible aspects.
|
|
148
|
+
"""
|
|
143
149
|
|
|
150
|
+
axis: str = Field(
|
|
151
|
+
description=(
|
|
152
|
+
"The single dimension on which the two aspects are opposite ends "
|
|
153
|
+
"(e.g. 'closeness', 'risk-taking'). If no such shared dimension "
|
|
154
|
+
"exists, the pair is not a genuine contradiction — say so here."
|
|
155
|
+
)
|
|
156
|
+
)
|
|
144
157
|
positive_aspect: AspectDto = Field(description="The positive aspect (T+ or A+)")
|
|
145
158
|
negative_aspect: AspectDto = Field(description="The negative aspect (A- or T-)")
|
|
146
159
|
|
|
147
160
|
|
|
148
161
|
class TetradDto(BaseModel):
|
|
149
|
-
"""Full tetrad
|
|
162
|
+
"""Full tetrad: four aspects grouped by the two axes they oppose along.
|
|
150
163
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
164
|
+
The four aspects stay as top-level fields (deep nesting made the model drop
|
|
165
|
+
a whole diagonal branch), but each diagonal pair leads with an explicit
|
|
166
|
+
`axis` field — the shared dimension its two poles sit at opposite ends of.
|
|
167
|
+
Naming the axis forces genuine diagonal contradiction into the output
|
|
168
|
+
instead of leaving it to a trailing constraint.
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
# --- Pair 1: T+ vs A- (thesis-constructive axis) ---
|
|
172
|
+
t_plus_vs_a_minus_axis: str = Field(
|
|
173
|
+
description=(
|
|
174
|
+
"The single dimension on which T+ and A- are opposite ends "
|
|
175
|
+
"(e.g. 'closeness'). If T and A share no such dimension, the pair "
|
|
176
|
+
"is not a genuine contradiction — say so here."
|
|
177
|
+
)
|
|
178
|
+
)
|
|
179
|
+
t_plus: AspectDto = Field(description="T+ - constructive thesis (positive end of the axis)")
|
|
180
|
+
a_minus: AspectDto = Field(description="A- - exaggerated antithesis (negative end of the axis)")
|
|
181
|
+
|
|
182
|
+
# --- Pair 2: A+ vs T- (antithesis-constructive axis) ---
|
|
183
|
+
a_plus_vs_t_minus_axis: str = Field(
|
|
184
|
+
description=(
|
|
185
|
+
"The single dimension on which A+ and T- are opposite ends. If A "
|
|
186
|
+
"and T share no such dimension, say so here rather than inventing "
|
|
187
|
+
"two unrelated aspects."
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
a_plus: AspectDto = Field(description="A+ - constructive antithesis (positive end of the axis)")
|
|
191
|
+
t_minus: AspectDto = Field(description="T- - exaggerated thesis (negative end of the axis)")
|
|
155
192
|
|
|
156
193
|
|
|
157
194
|
# --- Result ---
|
|
@@ -178,6 +215,17 @@ class AspectGeneration(ReasonableConcern[list[AspectResult]], SettingsAware):
|
|
|
178
215
|
|
|
179
216
|
Generates aspects with HS calculated against taxonomy apex and K values.
|
|
180
217
|
Contradiction pairs are generated together to ensure coherence.
|
|
218
|
+
|
|
219
|
+
Design decision — diagonal contradiction is enforced by the PROMPT here, not
|
|
220
|
+
by a post-hoc scorer. `TetradDto` makes each diagonal pair name the `axis`
|
|
221
|
+
it opposes along, which forces genuine contradiction into the output. We do
|
|
222
|
+
NOT run `DiagonalOppositionsCheck` on this path: generation is latency- and
|
|
223
|
+
cost-sensitive (it fans out across polarities × aspects), and the scorer
|
|
224
|
+
would add 2 LLM calls per perspective. `DiagonalOppositionsCheck` exists as
|
|
225
|
+
a safety net only where the prompt is bypassed — user edits in
|
|
226
|
+
`edit_perspective._validate_tetrad_coherence`. If a T/A pair is genuinely
|
|
227
|
+
not an opposition, that is caught upstream at polarity formation
|
|
228
|
+
(AntitheticalThesisDetection / the HS gate), not here.
|
|
181
229
|
"""
|
|
182
230
|
|
|
183
231
|
def __init__(self) -> None:
|
|
@@ -325,9 +373,9 @@ class AspectGeneration(ReasonableConcern[list[AspectResult]], SettingsAware):
|
|
|
325
373
|
results = []
|
|
326
374
|
position_to_dto = {
|
|
327
375
|
POSITION_T_PLUS: result.t_plus,
|
|
328
|
-
POSITION_T_MINUS: result.t_minus,
|
|
329
|
-
POSITION_A_PLUS: result.a_plus,
|
|
330
376
|
POSITION_A_MINUS: result.a_minus,
|
|
377
|
+
POSITION_A_PLUS: result.a_plus,
|
|
378
|
+
POSITION_T_MINUS: result.t_minus,
|
|
331
379
|
}
|
|
332
380
|
|
|
333
381
|
for pos in positions:
|
|
@@ -535,13 +583,17 @@ Taxonomy apex concepts for reference:
|
|
|
535
583
|
- A+ apex: {a_plus_apex}
|
|
536
584
|
- A- apex: {a_minus_apex}
|
|
537
585
|
{existing_section}{avoid_section}
|
|
586
|
+
Build the tetrad as its two diagonal contradiction pairs (T+ vs A-, A+ vs T-).
|
|
587
|
+
For each pair:
|
|
588
|
+
1. First name the **axis** — the single dimension on which the two aspects are opposite ends, so they cannot both hold at once.
|
|
589
|
+
2. Then place each aspect at an opposite end of that axis.
|
|
590
|
+
If T and A do not admit a genuine shared axis of opposition, say so in the pair's `axis` field rather than inventing two unrelated aspects.
|
|
591
|
+
|
|
538
592
|
Generate each aspect (1-{max_words} words) with:
|
|
539
593
|
|
|
540
594
|
{HS_SCALE}
|
|
541
595
|
|
|
542
|
-
{COMPLEMENTARITY_SCALE}
|
|
543
|
-
|
|
544
|
-
Ensure T+ contradicts A-, and A+ contradicts T-."""
|
|
596
|
+
{COMPLEMENTARITY_SCALE}"""
|
|
545
597
|
|
|
546
598
|
def _contradiction_pair_prompt(
|
|
547
599
|
self,
|
|
@@ -590,7 +642,7 @@ Generate each aspect (1-{max_words} words) with:
|
|
|
590
642
|
{COMPLEMENTARITY_SCALE}
|
|
591
643
|
|
|
592
644
|
The positive_aspect is {positive_pos}, the negative_aspect is {negative_pos}.
|
|
593
|
-
|
|
645
|
+
First name the **axis** — the single dimension on which they are opposite ends — then place each at an opposite end of it. They cannot both hold at once. If no such shared axis exists, say so in the `axis` field rather than inventing two unrelated aspects."""
|
|
594
646
|
|
|
595
647
|
def _single_aspect_prompt(self, position: str, existing_context: str) -> str:
|
|
596
648
|
"""Build prompt for single aspect generation."""
|
|
@@ -19,12 +19,15 @@ Programmatic usage:
|
|
|
19
19
|
|
|
20
20
|
from __future__ import annotations
|
|
21
21
|
|
|
22
|
-
from typing import Union
|
|
22
|
+
from typing import TYPE_CHECKING, Union
|
|
23
23
|
|
|
24
24
|
from dependency_injector.wiring import Provide, inject
|
|
25
25
|
from gqlalchemy import Memgraph, Neo4j
|
|
26
26
|
from pydantic import BaseModel, Field
|
|
27
27
|
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from mirascope.llm import UserContent
|
|
30
|
+
|
|
28
31
|
from dialectical_framework.agents.conversation_facilitator import \
|
|
29
32
|
ConversationFacilitator
|
|
30
33
|
from dialectical_framework.agents.reasonable_concern import ReasonableConcern
|
|
@@ -96,11 +99,20 @@ class SourceDigest(ReasonableConcern[Input], SettingsAware):
|
|
|
96
99
|
if not input_node:
|
|
97
100
|
raise ValueError(f"Input not found: {input_hash}")
|
|
98
101
|
|
|
99
|
-
resolved_content = await input_resolver.
|
|
102
|
+
resolved_content = await input_resolver.resolve_native(input_node)
|
|
100
103
|
if not resolved_content:
|
|
101
104
|
raise ValueError(f"Input {input_hash} has no resolvable content")
|
|
102
105
|
|
|
103
|
-
|
|
106
|
+
is_text = isinstance(resolved_content, str)
|
|
107
|
+
|
|
108
|
+
# Only text can be used verbatim as its own digest. Native media
|
|
109
|
+
# (image/PDF parts) must always go through the model's vision pass —
|
|
110
|
+
# there is no meaningful "raw content" to store as a digest.
|
|
111
|
+
if (
|
|
112
|
+
is_text
|
|
113
|
+
and len(resolved_content) <= DIGEST_THRESHOLD
|
|
114
|
+
and not input_node.digest
|
|
115
|
+
):
|
|
104
116
|
new_digest = resolved_content
|
|
105
117
|
self._report.summary = f"Content compact enough to use as digest for input {input_node.short_hash}"
|
|
106
118
|
else:
|
|
@@ -122,7 +134,7 @@ class SourceDigest(ReasonableConcern[Input], SettingsAware):
|
|
|
122
134
|
|
|
123
135
|
async def _generate_digest(
|
|
124
136
|
self,
|
|
125
|
-
content:
|
|
137
|
+
content: UserContent,
|
|
126
138
|
existing_digest: str | None = None,
|
|
127
139
|
context: str = "",
|
|
128
140
|
) -> str:
|
|
@@ -140,17 +152,23 @@ class SourceDigest(ReasonableConcern[Input], SettingsAware):
|
|
|
140
152
|
|
|
141
153
|
def _build_prompt(
|
|
142
154
|
self,
|
|
143
|
-
content:
|
|
155
|
+
content: UserContent,
|
|
144
156
|
existing_digest: str | None,
|
|
145
157
|
context: str,
|
|
146
|
-
) ->
|
|
158
|
+
) -> UserContent:
|
|
159
|
+
# Text sources are interpolated inline; native media (image/PDF parts)
|
|
160
|
+
# are appended as a separate content part with a text placeholder in the
|
|
161
|
+
# <source> slot so the model knows where the attached source belongs.
|
|
162
|
+
is_text = isinstance(content, str)
|
|
163
|
+
source_text = content if is_text else "(see the attached source below)"
|
|
164
|
+
|
|
147
165
|
sections = []
|
|
148
166
|
|
|
149
167
|
if existing_digest:
|
|
150
168
|
sections.append(f"<existing_digest>\n{existing_digest}\n</existing_digest>")
|
|
151
169
|
if context:
|
|
152
170
|
sections.append(f"<context>\n{context}\n</context>")
|
|
153
|
-
sections.append(f"<source>\n{
|
|
171
|
+
sections.append(f"<source>\n{source_text}\n</source>")
|
|
154
172
|
sections.append(
|
|
155
173
|
"Refine the existing digest incorporating the context provided. "
|
|
156
174
|
"Sharpen focus, add relevant details, remove irrelevant parts."
|
|
@@ -158,9 +176,20 @@ class SourceDigest(ReasonableConcern[Input], SettingsAware):
|
|
|
158
176
|
else:
|
|
159
177
|
if context:
|
|
160
178
|
sections.append(f"<context>\n{context}\n</context>")
|
|
161
|
-
sections.append(f"<source>\n{
|
|
179
|
+
sections.append(f"<source>\n{source_text}\n</source>")
|
|
162
180
|
sections.append(
|
|
163
181
|
"Generate an initial analytical digest of this source."
|
|
164
182
|
)
|
|
165
183
|
|
|
166
|
-
|
|
184
|
+
prompt_text = "\n\n".join(sections)
|
|
185
|
+
|
|
186
|
+
if is_text:
|
|
187
|
+
return prompt_text
|
|
188
|
+
|
|
189
|
+
# Multimodal: text instructions followed by the native source part(s).
|
|
190
|
+
parts: list = [prompt_text]
|
|
191
|
+
if isinstance(content, (list, tuple)):
|
|
192
|
+
parts.extend(content)
|
|
193
|
+
else:
|
|
194
|
+
parts.append(content)
|
|
195
|
+
return parts
|
|
@@ -17,6 +17,8 @@ from dialectical_framework.graph.verbatim_input_resolver import VerbatimInputRes
|
|
|
17
17
|
from dialectical_framework.protocols.input_resolver import InputResolver
|
|
18
18
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
|
+
from mirascope.llm import UserContent
|
|
21
|
+
|
|
20
22
|
from dialectical_framework.graph.nodes.case import Case
|
|
21
23
|
from dialectical_framework.graph.nodes.input import Input
|
|
22
24
|
|
|
@@ -88,6 +90,30 @@ class CompositeInputResolver(InputResolver):
|
|
|
88
90
|
# VerbatimInputResolver handles plain text and data: URIs
|
|
89
91
|
return await self._verbatim.resolve(input_node)
|
|
90
92
|
|
|
93
|
+
async def resolve_native(self, input_node: Input) -> UserContent:
|
|
94
|
+
"""
|
|
95
|
+
Resolve an Input to native model content, preserving image/PDF modality.
|
|
96
|
+
|
|
97
|
+
Delegates data: and plain-text content to the VerbatimInputResolver's
|
|
98
|
+
native path (which emits Image/Document parts for supported media). dx://
|
|
99
|
+
references resolve to graph-node text, so they stay text.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
input_node: Input node with content to resolve.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
`UserContent` — a media part for supported binary data: URIs,
|
|
106
|
+
otherwise the resolved text `str`.
|
|
107
|
+
"""
|
|
108
|
+
content = input_node.content
|
|
109
|
+
if not content:
|
|
110
|
+
return ""
|
|
111
|
+
|
|
112
|
+
if content.startswith("dx://"):
|
|
113
|
+
return await self._dialexity.resolve(content)
|
|
114
|
+
|
|
115
|
+
return await self._verbatim.resolve_native(input_node)
|
|
116
|
+
|
|
91
117
|
async def resolve_all(self, source: Union[Case, list[Input]]) -> str:
|
|
92
118
|
"""
|
|
93
119
|
Resolve multiple inputs to combined text content.
|
|
@@ -14,9 +14,18 @@ from urllib.parse import unquote
|
|
|
14
14
|
from dialectical_framework.protocols.input_resolver import InputResolver
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
|
+
from mirascope.llm import UserContent
|
|
18
|
+
|
|
17
19
|
from dialectical_framework.graph.nodes.case import Case
|
|
18
20
|
from dialectical_framework.graph.nodes.input import Input
|
|
19
21
|
|
|
22
|
+
# Mime types Mirascope accepts as native image/document parts. Anything else
|
|
23
|
+
# (text, unknown binary) falls back to text resolution.
|
|
24
|
+
_IMAGE_MIME_TYPES = frozenset(
|
|
25
|
+
{"image/png", "image/jpeg", "image/webp", "image/gif", "image/heic", "image/heif"}
|
|
26
|
+
)
|
|
27
|
+
_DOCUMENT_MIME_TYPES = frozenset({"application/pdf"})
|
|
28
|
+
|
|
20
29
|
|
|
21
30
|
class VerbatimInputResolver(InputResolver):
|
|
22
31
|
"""
|
|
@@ -68,6 +77,31 @@ class VerbatimInputResolver(InputResolver):
|
|
|
68
77
|
# Otherwise, treat as plain text
|
|
69
78
|
return content
|
|
70
79
|
|
|
80
|
+
async def resolve_native(self, input_node: Input) -> UserContent:
|
|
81
|
+
"""
|
|
82
|
+
Resolve content to native model content, preserving image/PDF modality.
|
|
83
|
+
|
|
84
|
+
For a `data:` URI whose mime type is a supported image or PDF format,
|
|
85
|
+
returns a Mirascope `Image` / `Document` part carrying the base64 bytes,
|
|
86
|
+
so the model reads the source natively instead of a transcription. All
|
|
87
|
+
other content (text, `data:text/*`, non-base64, unsupported binary)
|
|
88
|
+
falls back to `resolve()` text.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
input_node: Input node with content (plain text or data: URI).
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
A multimodal part (`Image`/`Document`) for supported binary media,
|
|
95
|
+
otherwise the resolved text `str`.
|
|
96
|
+
"""
|
|
97
|
+
content = input_node.content
|
|
98
|
+
if content and content.startswith("data:"):
|
|
99
|
+
part = self._decode_data_uri_native(content)
|
|
100
|
+
if part is not None:
|
|
101
|
+
return part
|
|
102
|
+
|
|
103
|
+
return await self.resolve(input_node)
|
|
104
|
+
|
|
71
105
|
async def resolve_all(self, source: Union[Case, list[Input]]) -> str:
|
|
72
106
|
"""
|
|
73
107
|
Resolve multiple inputs to combined text content.
|
|
@@ -106,6 +140,47 @@ class VerbatimInputResolver(InputResolver):
|
|
|
106
140
|
|
|
107
141
|
return "\n\n".join(parts)
|
|
108
142
|
|
|
143
|
+
@staticmethod
|
|
144
|
+
def _decode_data_uri_native(uri: str) -> UserContent | None:
|
|
145
|
+
"""
|
|
146
|
+
Build a native image/document part from a data: URI, if it is one.
|
|
147
|
+
|
|
148
|
+
Returns an `Image`/`Document` for a base64 data: URI whose mime type is a
|
|
149
|
+
supported image or PDF format. Returns None for anything that should be
|
|
150
|
+
handled as text (text mime types, non-base64 payloads, unsupported types),
|
|
151
|
+
letting the caller fall back to text resolution.
|
|
152
|
+
"""
|
|
153
|
+
# data:<mime>[;base64],<data>
|
|
154
|
+
content_part = uri[5:]
|
|
155
|
+
if "," not in content_part:
|
|
156
|
+
return None
|
|
157
|
+
|
|
158
|
+
metadata, data = content_part.split(",", 1)
|
|
159
|
+
if ";base64" not in metadata.lower():
|
|
160
|
+
# Text data: URIs (or non-base64 binary) are handled as text.
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
mime_type = metadata.split(";", 1)[0].strip().lower()
|
|
164
|
+
|
|
165
|
+
from mirascope.llm import (Base64DocumentSource, Base64ImageSource,
|
|
166
|
+
Document, Image)
|
|
167
|
+
|
|
168
|
+
if mime_type in _IMAGE_MIME_TYPES:
|
|
169
|
+
return Image(
|
|
170
|
+
source=Base64ImageSource(
|
|
171
|
+
type="base64_image_source", data=data, mime_type=mime_type
|
|
172
|
+
)
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
if mime_type in _DOCUMENT_MIME_TYPES:
|
|
176
|
+
return Document(
|
|
177
|
+
source=Base64DocumentSource(
|
|
178
|
+
type="base64_document_source", data=data, media_type=mime_type
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return None
|
|
183
|
+
|
|
109
184
|
@staticmethod
|
|
110
185
|
def _decode_data_uri(uri: str) -> str:
|
|
111
186
|
"""Decode a data: URI to text."""
|
|
@@ -8,6 +8,8 @@ from abc import ABC, abstractmethod
|
|
|
8
8
|
from typing import TYPE_CHECKING
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
+
from mirascope.llm import UserContent
|
|
12
|
+
|
|
11
13
|
from dialectical_framework.graph.nodes.case import Case
|
|
12
14
|
from dialectical_framework.graph.nodes.input import Input
|
|
13
15
|
|
|
@@ -51,6 +53,32 @@ class InputResolver(ABC):
|
|
|
51
53
|
"""
|
|
52
54
|
...
|
|
53
55
|
|
|
56
|
+
async def resolve_native(self, input_node: Input) -> UserContent:
|
|
57
|
+
"""
|
|
58
|
+
Resolve a single Input to native model content, preserving modality.
|
|
59
|
+
|
|
60
|
+
Unlike `resolve()`, which always flattens to text, this returns Mirascope
|
|
61
|
+
`UserContent` — either a plain `str` for text sources, or multimodal parts
|
|
62
|
+
(`Image`, `Document`, or a list mixing text and such parts) for images/PDFs.
|
|
63
|
+
Callers that pass content straight to the model (e.g. the `SourceDigest`
|
|
64
|
+
concern's vision pass) use this to let the model read the source natively
|
|
65
|
+
rather than a lossy transcription.
|
|
66
|
+
|
|
67
|
+
The default implementation delegates to `resolve()`, so text-only resolvers
|
|
68
|
+
need not override it. Resolvers that back image/PDF sources should override
|
|
69
|
+
this to emit the corresponding `Image`/`Document` parts.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
input_node: Input node with content to resolve.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
`UserContent` — a `str`, a single multimodal part, or a list of parts.
|
|
76
|
+
|
|
77
|
+
Raises:
|
|
78
|
+
ValueError: If content format is unsupported (implementation-dependent).
|
|
79
|
+
"""
|
|
80
|
+
return await self.resolve(input_node)
|
|
81
|
+
|
|
54
82
|
@abstractmethod
|
|
55
83
|
async def resolve_all(self, source: Case | list[Input]) -> str:
|
|
56
84
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dialectical_framework-1.6.4 → dialectical_framework-1.6.5}/src/dialectical_framework/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|