dialectical-framework 1.1.3__tar.gz → 1.2.1__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.1.3 → dialectical_framework-1.2.1}/PKG-INFO +1 -1
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/pyproject.toml +1 -1
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/conversation_facilitator.py +20 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/explorer.py +18 -8
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/skills/explore_transformations.py +123 -40
- dialectical_framework-1.2.1/src/dialectical_framework/agents/explorer/skills/generate_synthesis.py +207 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/system_prompts.py +2 -0
- dialectical_framework-1.2.1/src/dialectical_framework/agents/explorer/tools/generate_synthesis.py +27 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/reasonable_concern.py +31 -0
- dialectical_framework-1.2.1/src/dialectical_framework/concerns/synthesis_generation.py +347 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/synthesis.py +3 -3
- dialectical_framework-1.2.1/src/dialectical_framework/utils/concurrency.py +37 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/use_brain.py +37 -9
- dialectical_framework-1.1.3/src/dialectical_framework/concerns/synthesis_generation.py +0 -227
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/LICENSE +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/README.md +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/agent_context.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/analyst.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/skills/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/skills/anchor_theses.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/skills/edit_perspective.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/skills/expand_polarities.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/skills/find_polarities.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/skills/introduce_polarity.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/skills/surface_theses.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/system_prompts.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/tools/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/tools/create_dx_input.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/analyst/tools/place_statement.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/apps.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/execution_report.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/skills/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/skills/build_wheels.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/tools/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/tools/create_nexus.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/tools/expand_nexus.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/explorer/tools/present_exploration.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/orchestrator/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/orchestrator/tools/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/orchestrator/tools/add_input.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/orchestrator/tools/discard.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/orchestrator/tools/get_schema.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/orchestrator/tools/inspect_node.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/orchestrator/tools/present_analysis.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/orchestrator/tools/query_graph.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/agents/stream_events.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/ac_re_taxonomy.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/action_extraction.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/ai_dto/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/ai_dto/statement_dto.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/ai_dto/statements_deck_dto.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/antithesis_classification.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/antithesis_extraction.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/aspect_classification.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/aspect_generation.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/causality_estimator.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/causality_estimator_balanced.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/causality_estimator_criteria.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/causality_estimator_desirable.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/causality_estimator_feasible.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/causality_estimator_realistic.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/causality_normalizer.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality/estimator_resolver.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/causality_estimation.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/control_statements_check.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/create_nexus.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/diagonal_oppositions_check.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/display_text_edit.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/expand_nexus.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/perspective_combination.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/perspective_validation.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/positive_ac_re_apex_derivation.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/statement_classification.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/statement_deduplication.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/statement_placement.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/thesis_extraction.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/transformation_audit.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/concerns/transformation_generation.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/dialectical_reasoning.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/enums/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/enums/causality_preset.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/enums/di.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/events/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/events/graph_event.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/events/graph_event_bus.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/exceptions/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/exceptions/node_errors.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/exceptions/resolver_errors.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/composite_input_resolver.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/dialexity_input_resolver.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/estimation_manager.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/mixins/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/mixins/incremental_build_mixin.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/mixins/intent_mixin.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/mixins/persistable_mixin.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/assessable_entity.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/base_node.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/case.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/cycle.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/estimation.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/ideas.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/input.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/nexus.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/perspective.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/polarity.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/rationale.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/statement.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/transformation.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/transition.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/nodes/wheel.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationship_manager.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/action_reflection_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/belongs_to_cycle_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/belongs_to_nexus_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/changed_to_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/contradiction_of_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/critiques_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/distilled_to_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/estimates_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/explains_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/has_input_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/has_statement_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/has_wheel_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/immutable_structure.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/is_source_of_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/is_target_of_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/negative_side_of_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/opposite_direction_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/opposite_of_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/polarity_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/positive_side_of_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/provides_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/relationships/synthesis_of_relationship.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/case_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/cycle_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/input_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/nexus_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/node_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/perspective_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/polarity_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/schema_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/statement_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/transformation_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/repositories/wheel_repository.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/scope_context.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/verbatim_input_resolver.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/wheel_segment.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/graph/wheel_segment_polar_pair.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/protocols/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/protocols/has_config.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/protocols/input_resolver.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/settings.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/__init__.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/bedrock_provider.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/dc_replace.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/decompose_probability_uniformly.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/edge_context.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/effect_logger.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/order_transitions.py +0 -0
- {dialectical_framework-1.1.3 → dialectical_framework-1.2.1}/src/dialectical_framework/utils/sequence_generation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dialectical-framework
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
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.1
|
|
3
|
+
version = "1.2.1"
|
|
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"
|
|
@@ -152,6 +152,7 @@ class ConversationFacilitator(SettingsAware):
|
|
|
152
152
|
|
|
153
153
|
# Sync full conversation history from the response chain
|
|
154
154
|
self._messages = list(response.messages)
|
|
155
|
+
self._strip_unsupported_input_fields()
|
|
155
156
|
|
|
156
157
|
# Extract structured response
|
|
157
158
|
return await self._call_with_response_model(response_model)
|
|
@@ -209,11 +210,30 @@ class ConversationFacilitator(SettingsAware):
|
|
|
209
210
|
stream = await stream.resume(tool_outputs)
|
|
210
211
|
|
|
211
212
|
self._messages = list(stream.messages)
|
|
213
|
+
self._strip_unsupported_input_fields()
|
|
212
214
|
result = await self._call_with_response_model(response_model)
|
|
213
215
|
yield ResponseComplete(result=result)
|
|
214
216
|
|
|
215
217
|
# --- Internal helpers ---
|
|
216
218
|
|
|
219
|
+
def _strip_unsupported_input_fields(self) -> None:
|
|
220
|
+
"""Strip output-only fields from raw_message before replaying to API.
|
|
221
|
+
|
|
222
|
+
Mirascope passes raw_message dicts back verbatim as input. If the API
|
|
223
|
+
added output-only fields (like 'caller' on tool_use blocks), they cause
|
|
224
|
+
400 errors on the next call. This strips them.
|
|
225
|
+
"""
|
|
226
|
+
for msg in self._messages:
|
|
227
|
+
raw = getattr(msg, "raw_message", None)
|
|
228
|
+
if not isinstance(raw, dict):
|
|
229
|
+
continue
|
|
230
|
+
content = raw.get("content")
|
|
231
|
+
if not isinstance(content, list):
|
|
232
|
+
continue
|
|
233
|
+
for block in content:
|
|
234
|
+
if isinstance(block, dict) and block.get("type") == "tool_use":
|
|
235
|
+
block.pop("caller", None)
|
|
236
|
+
|
|
217
237
|
@staticmethod
|
|
218
238
|
def _log_tool_calls(tool_calls: list) -> None:
|
|
219
239
|
"""Log tool invocations to the effect logger if configured."""
|
|
@@ -9,6 +9,7 @@ Also contains ExplorationPipeline — the headless pipeline for programmatic use
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
import asyncio
|
|
12
13
|
from typing import TYPE_CHECKING, Annotated, AsyncGenerator, Optional
|
|
13
14
|
|
|
14
15
|
from mirascope import llm
|
|
@@ -121,6 +122,8 @@ def _build_tools() -> list:
|
|
|
121
122
|
explore_transformations
|
|
122
123
|
from dialectical_framework.agents.explorer.tools.expand_nexus import \
|
|
123
124
|
expand_nexus
|
|
125
|
+
from dialectical_framework.agents.explorer.tools.generate_synthesis import \
|
|
126
|
+
generate_synthesis
|
|
124
127
|
from dialectical_framework.agents.explorer.tools.present_exploration import \
|
|
125
128
|
present_exploration
|
|
126
129
|
from dialectical_framework.agents.orchestrator.tools.get_schema import \
|
|
@@ -133,6 +136,7 @@ def _build_tools() -> list:
|
|
|
133
136
|
return [
|
|
134
137
|
build_wheels,
|
|
135
138
|
explore_transformations,
|
|
139
|
+
generate_synthesis,
|
|
136
140
|
expand_nexus,
|
|
137
141
|
present_exploration,
|
|
138
142
|
inspect_node,
|
|
@@ -227,21 +231,27 @@ class ExplorationPipeline(ReasonableConcern[ExplorationResult]):
|
|
|
227
231
|
|
|
228
232
|
transformation_count = 0
|
|
229
233
|
|
|
230
|
-
|
|
234
|
+
async def _explore_wheel(wheel_hash: str) -> tuple[int, Optional[StepError]]:
|
|
231
235
|
try:
|
|
232
236
|
explore_tr = ExploreTransformations(wheel_hash=wheel_hash)
|
|
233
237
|
tr_result = await explore_tr.resolve()
|
|
234
238
|
reports.append(explore_tr.report)
|
|
235
|
-
|
|
239
|
+
return len(tr_result.new), None
|
|
236
240
|
except Exception as e:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
hash=wheel_hash,
|
|
242
|
-
)
|
|
241
|
+
return 0, StepError(
|
|
242
|
+
step="explore_transformations",
|
|
243
|
+
message=str(e),
|
|
244
|
+
hash=wheel_hash,
|
|
243
245
|
)
|
|
244
246
|
|
|
247
|
+
wheel_results = await asyncio.gather(*[
|
|
248
|
+
_explore_wheel(wh) for wh in wheel_hashes
|
|
249
|
+
])
|
|
250
|
+
for count, error in wheel_results:
|
|
251
|
+
transformation_count += count
|
|
252
|
+
if error:
|
|
253
|
+
errors.append(error)
|
|
254
|
+
|
|
245
255
|
self._report.ok = True
|
|
246
256
|
self._report.summary = (
|
|
247
257
|
f"Exploration complete: {len(cycle_hashes)} cycles, "
|
|
@@ -22,8 +22,10 @@ Usage:
|
|
|
22
22
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
|
+
import asyncio
|
|
26
|
+
import logging
|
|
25
27
|
from dataclasses import dataclass, field
|
|
26
|
-
from typing import Annotated, Optional, TYPE_CHECKING
|
|
28
|
+
from typing import Annotated, Any, Optional, TYPE_CHECKING
|
|
27
29
|
|
|
28
30
|
from dependency_injector.wiring import Provide, inject
|
|
29
31
|
from mirascope import llm
|
|
@@ -116,27 +118,47 @@ class ExploreTransformations(ReasonableConcern[ExploreTransformationsResult]):
|
|
|
116
118
|
# 3. Get input text from scope
|
|
117
119
|
input_text = await self._get_input_text()
|
|
118
120
|
|
|
119
|
-
# 4. Process
|
|
121
|
+
# 4. Process edge pairs in parallel — both edges get Transformations
|
|
122
|
+
pair_results = await asyncio.gather(
|
|
123
|
+
*[
|
|
124
|
+
self._process_edge_pair(wheel, nexus, edge_a, edge_b, input_text)
|
|
125
|
+
for edge_a, edge_b in edge_pairs
|
|
126
|
+
],
|
|
127
|
+
return_exceptions=True,
|
|
128
|
+
)
|
|
129
|
+
|
|
120
130
|
all_existing: list[Transformation] = []
|
|
121
131
|
all_new: list[Transformation] = []
|
|
122
132
|
last_apexes: Optional[ApexDerivationResultDto] = None
|
|
123
133
|
|
|
124
|
-
for
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
for result in pair_results:
|
|
135
|
+
if isinstance(result, Exception):
|
|
136
|
+
logging.getLogger(__name__).warning("Edge pair failed: %s", result)
|
|
137
|
+
continue
|
|
138
|
+
existing, new, apexes = result
|
|
128
139
|
all_existing.extend(existing)
|
|
129
140
|
all_new.extend(new)
|
|
130
141
|
if apexes:
|
|
131
142
|
last_apexes = apexes
|
|
132
143
|
|
|
133
|
-
# 5. Audit new transformations
|
|
144
|
+
# 5. Audit new transformations in parallel
|
|
134
145
|
if all_new:
|
|
135
146
|
from dialectical_framework.concerns.transformation_audit import TransformationAudit
|
|
136
|
-
|
|
147
|
+
|
|
148
|
+
async def _audit_one(tr: Transformation) -> TransformationAudit:
|
|
137
149
|
auditor = TransformationAudit()
|
|
138
150
|
await auditor.resolve(tr, input_text)
|
|
139
|
-
|
|
151
|
+
return auditor
|
|
152
|
+
|
|
153
|
+
audit_results = await asyncio.gather(
|
|
154
|
+
*[_audit_one(tr) for tr in all_new],
|
|
155
|
+
return_exceptions=True,
|
|
156
|
+
)
|
|
157
|
+
for result in audit_results:
|
|
158
|
+
if isinstance(result, Exception):
|
|
159
|
+
logging.getLogger(__name__).warning("Audit failed: %s", result)
|
|
160
|
+
continue
|
|
161
|
+
self._report = self._report.merge(result.report)
|
|
140
162
|
|
|
141
163
|
# Summary
|
|
142
164
|
self._report.artifacts["wheel_hash"] = wheel.short_hash
|
|
@@ -166,8 +188,8 @@ class ExploreTransformations(ReasonableConcern[ExploreTransformationsResult]):
|
|
|
166
188
|
"""
|
|
167
189
|
Process a diametrically opposite edge pair.
|
|
168
190
|
|
|
169
|
-
Phase 1: Extract Ac+ candidates for both edges
|
|
170
|
-
Phase 2: Generate tetrads for
|
|
191
|
+
Phase 1: Extract Ac+ candidates for both edges in parallel.
|
|
192
|
+
Phase 2: Generate tetrads for all candidates in parallel.
|
|
171
193
|
|
|
172
194
|
Returns:
|
|
173
195
|
Tuple of (existing, new, apexes)
|
|
@@ -176,11 +198,12 @@ class ExploreTransformations(ReasonableConcern[ExploreTransformationsResult]):
|
|
|
176
198
|
|
|
177
199
|
tr_repo = TransformationRepository()
|
|
178
200
|
all_existing: list[Transformation] = []
|
|
179
|
-
all_new: list[Transformation] = []
|
|
180
201
|
last_apexes: Optional[ApexDerivationResultDto] = None
|
|
181
202
|
|
|
182
|
-
# Phase 1: Extract Ac+ for both edges (check existing first)
|
|
203
|
+
# Phase 1: Extract Ac+ for both edges in parallel (check existing first)
|
|
204
|
+
phase1_tasks: list[tuple[Transition, asyncio.Task]] = []
|
|
183
205
|
edge_data: dict[str, _EdgeProcessingData] = {}
|
|
206
|
+
|
|
184
207
|
for edge in (edge_a, edge_b):
|
|
185
208
|
assert edge.hash is not None
|
|
186
209
|
existing = tr_repo.find_by_edge(edge=edge)
|
|
@@ -198,43 +221,50 @@ class ExploreTransformations(ReasonableConcern[ExploreTransformationsResult]):
|
|
|
198
221
|
edge_data[edge.hash] = _EdgeProcessingData(skip=True)
|
|
199
222
|
continue
|
|
200
223
|
|
|
201
|
-
apex_service = ApexDerivation()
|
|
202
|
-
apexes = await apex_service.resolve(edge, input_text)
|
|
203
|
-
self._report = self._report.merge(apex_service.report)
|
|
204
|
-
last_apexes = apexes
|
|
205
|
-
|
|
206
|
-
extractor = ActionExtraction()
|
|
207
|
-
ac_candidates = await extractor.resolve(
|
|
208
|
-
edge, input_text,
|
|
209
|
-
not_like_these=wheel.transformations,
|
|
210
|
-
)
|
|
211
|
-
self._report = self._report.merge(extractor.report)
|
|
212
|
-
|
|
213
224
|
edge_data[edge.hash] = _EdgeProcessingData(
|
|
214
|
-
ac_candidates=ac_candidates or [],
|
|
215
|
-
apexes=apexes,
|
|
216
225
|
source_segment=source_segment,
|
|
217
226
|
target_segment=target_segment,
|
|
218
227
|
)
|
|
228
|
+
phase1_tasks.append((edge, asyncio.ensure_future(
|
|
229
|
+
self._phase1_for_edge(edge, wheel, input_text)
|
|
230
|
+
)))
|
|
231
|
+
|
|
232
|
+
# Await Phase 1 tasks in parallel
|
|
233
|
+
if phase1_tasks:
|
|
234
|
+
results = await asyncio.gather(
|
|
235
|
+
*[t for _, t in phase1_tasks],
|
|
236
|
+
return_exceptions=True,
|
|
237
|
+
)
|
|
238
|
+
for (edge, _), result in zip(phase1_tasks, results):
|
|
239
|
+
assert edge.hash is not None
|
|
240
|
+
if isinstance(result, Exception):
|
|
241
|
+
logging.getLogger(__name__).warning(
|
|
242
|
+
"Phase 1 failed for edge %s: %s", edge.short_hash, result
|
|
243
|
+
)
|
|
244
|
+
edge_data[edge.hash] = _EdgeProcessingData(skip=True)
|
|
245
|
+
continue
|
|
246
|
+
apexes, ac_candidates, report = result
|
|
247
|
+
self._report = self._report.merge(report)
|
|
248
|
+
if apexes:
|
|
249
|
+
last_apexes = apexes
|
|
250
|
+
data = edge_data[edge.hash]
|
|
251
|
+
data.apexes = apexes
|
|
252
|
+
data.ac_candidates = ac_candidates or []
|
|
253
|
+
|
|
254
|
+
# Phase 2: Generate tetrads in parallel
|
|
255
|
+
generation_tasks: list[tuple[Transition, _EdgeProcessingData, ActionCandidateResultDto, asyncio.Task]] = []
|
|
219
256
|
|
|
220
|
-
# Phase 2: Generate tetrads using opposite Ac+ for Re-side
|
|
221
257
|
for edge, opposite_edge in [(edge_a, edge_b), (edge_b, edge_a)]:
|
|
222
258
|
assert edge.hash is not None
|
|
223
259
|
assert opposite_edge.hash is not None
|
|
224
260
|
data = edge_data.get(edge.hash)
|
|
225
261
|
if not data or data.existing or data.skip:
|
|
226
262
|
continue
|
|
227
|
-
|
|
228
263
|
if not data.ac_candidates:
|
|
229
264
|
continue
|
|
230
|
-
|
|
231
|
-
source_segment = data.source_segment
|
|
232
|
-
target_segment = data.target_segment
|
|
233
|
-
apexes = data.apexes
|
|
234
|
-
if not source_segment or not target_segment or not apexes:
|
|
265
|
+
if not data.source_segment or not data.target_segment or not data.apexes:
|
|
235
266
|
continue
|
|
236
267
|
|
|
237
|
-
# Get opposite edge's Ac+ candidates for Re-side context
|
|
238
268
|
opp_data = edge_data.get(opposite_edge.hash)
|
|
239
269
|
opp_ac_candidates = opp_data.ac_candidates if opp_data else []
|
|
240
270
|
|
|
@@ -245,19 +275,72 @@ class ExploreTransformations(ReasonableConcern[ExploreTransformationsResult]):
|
|
|
245
275
|
if not opposite_ac:
|
|
246
276
|
continue
|
|
247
277
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
edge, ac_plus, opposite_ac, apexes, input_text
|
|
278
|
+
task = asyncio.ensure_future(
|
|
279
|
+
self._generate_tetrad(edge, ac_plus, opposite_ac, data.apexes, input_text)
|
|
251
280
|
)
|
|
252
|
-
|
|
281
|
+
generation_tasks.append((edge, data, ac_plus, task))
|
|
253
282
|
|
|
283
|
+
# Await all generation tasks and create graph nodes sequentially
|
|
284
|
+
all_new: list[Transformation] = []
|
|
285
|
+
if generation_tasks:
|
|
286
|
+
tetrad_results = await asyncio.gather(
|
|
287
|
+
*[t for _, _, _, t in generation_tasks],
|
|
288
|
+
return_exceptions=True,
|
|
289
|
+
)
|
|
290
|
+
for (edge, data, _, _), result in zip(generation_tasks, tetrad_results):
|
|
291
|
+
if isinstance(result, Exception):
|
|
292
|
+
logging.getLogger(__name__).warning(
|
|
293
|
+
"Tetrad generation failed for edge %s: %s", edge.short_hash, result
|
|
294
|
+
)
|
|
295
|
+
continue
|
|
296
|
+
tetrad, report = result
|
|
297
|
+
self._report = self._report.merge(report)
|
|
298
|
+
assert data.source_segment is not None
|
|
299
|
+
assert data.target_segment is not None
|
|
254
300
|
transformation = self._create_transformation(
|
|
255
|
-
nexus, edge, source_segment, target_segment, tetrad,
|
|
301
|
+
nexus, edge, data.source_segment, data.target_segment, tetrad,
|
|
256
302
|
)
|
|
257
303
|
all_new.append(transformation)
|
|
258
304
|
|
|
259
305
|
return all_existing, all_new, last_apexes
|
|
260
306
|
|
|
307
|
+
async def _phase1_for_edge(
|
|
308
|
+
self,
|
|
309
|
+
edge: Transition,
|
|
310
|
+
wheel: Wheel,
|
|
311
|
+
input_text: str,
|
|
312
|
+
) -> tuple[Optional[ApexDerivationResultDto], list[ActionCandidateResultDto], Any]:
|
|
313
|
+
"""Run ApexDerivation + ActionExtraction for a single edge. Returns (apexes, candidates, merged_report)."""
|
|
314
|
+
from dialectical_framework.agents.execution_report import ExecutionReport
|
|
315
|
+
|
|
316
|
+
merged_report = ExecutionReport(tool=self.__class__.__name__)
|
|
317
|
+
|
|
318
|
+
apex_service = ApexDerivation()
|
|
319
|
+
apexes = await apex_service.resolve(edge, input_text)
|
|
320
|
+
merged_report = merged_report.merge(apex_service.report)
|
|
321
|
+
|
|
322
|
+
extractor = ActionExtraction()
|
|
323
|
+
ac_candidates = await extractor.resolve(
|
|
324
|
+
edge, input_text,
|
|
325
|
+
not_like_these=wheel.transformations,
|
|
326
|
+
)
|
|
327
|
+
merged_report = merged_report.merge(extractor.report)
|
|
328
|
+
|
|
329
|
+
return apexes, ac_candidates or [], merged_report
|
|
330
|
+
|
|
331
|
+
async def _generate_tetrad(
|
|
332
|
+
self,
|
|
333
|
+
edge: Transition,
|
|
334
|
+
ac_plus: ActionCandidateResultDto,
|
|
335
|
+
opposite_ac: ActionCandidateResultDto,
|
|
336
|
+
apexes: ApexDerivationResultDto,
|
|
337
|
+
input_text: str,
|
|
338
|
+
) -> tuple[TransformationTetradDto, Any]:
|
|
339
|
+
"""Run TransformationGeneration for one candidate. Returns (tetrad, report)."""
|
|
340
|
+
generator = TransformationGeneration()
|
|
341
|
+
tetrad = await generator.resolve(edge, ac_plus, opposite_ac, apexes, input_text)
|
|
342
|
+
return tetrad, generator.report
|
|
343
|
+
|
|
261
344
|
@staticmethod
|
|
262
345
|
def _find_matching_category(
|
|
263
346
|
candidates: list[ActionCandidateResultDto],
|
dialectical_framework-1.2.1/src/dialectical_framework/agents/explorer/skills/generate_synthesis.py
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GenerateSynthesis: Skill for generating S+/S- synthesis from a Wheel.
|
|
3
|
+
|
|
4
|
+
Orchestrates: resolve wheel → verify transformations → gather lower-layer
|
|
5
|
+
context → call SynthesisGeneration concern → create Synthesis node → commit.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from itertools import combinations
|
|
12
|
+
from typing import Optional, TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
from dependency_injector.wiring import Provide, inject
|
|
15
|
+
|
|
16
|
+
from dialectical_framework.agents.reasonable_concern import ReasonableConcern
|
|
17
|
+
from dialectical_framework.concerns.synthesis_generation import (
|
|
18
|
+
SynthesisGeneration,
|
|
19
|
+
SynthesisResult,
|
|
20
|
+
)
|
|
21
|
+
from dialectical_framework.enums.di import DI
|
|
22
|
+
from dialectical_framework.graph.nodes.statement import Statement
|
|
23
|
+
from dialectical_framework.graph.nodes.synthesis import (
|
|
24
|
+
POSITION_S_MINUS,
|
|
25
|
+
POSITION_S_PLUS,
|
|
26
|
+
Synthesis,
|
|
27
|
+
)
|
|
28
|
+
from dialectical_framework.graph.relationships.polarity_relationship import (
|
|
29
|
+
SMinusRelationship,
|
|
30
|
+
SPlusRelationship,
|
|
31
|
+
)
|
|
32
|
+
from dialectical_framework.graph.relationships.synthesis_of_relationship import (
|
|
33
|
+
SynthesisOfRelationship,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
from dialectical_framework.graph.nodes.nexus import Nexus
|
|
38
|
+
from dialectical_framework.graph.nodes.perspective import Perspective
|
|
39
|
+
from dialectical_framework.graph.nodes.wheel import Wheel
|
|
40
|
+
from dialectical_framework.protocols.input_resolver import InputResolver
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class GenerateSynthesisResult:
|
|
45
|
+
"""Result from GenerateSynthesis skill."""
|
|
46
|
+
|
|
47
|
+
synthesis: Synthesis
|
|
48
|
+
is_new: bool = True
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class GenerateSynthesis(ReasonableConcern[GenerateSynthesisResult]):
|
|
52
|
+
"""
|
|
53
|
+
Skill for generating S+/S- synthesis from a Wheel's Transformations.
|
|
54
|
+
|
|
55
|
+
Idempotent: returns existing Synthesis if one already exists for the Wheel.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(self, wheel_hash: str) -> None:
|
|
59
|
+
self.wheel_hash = wheel_hash
|
|
60
|
+
|
|
61
|
+
async def resolve(self) -> GenerateSynthesisResult:
|
|
62
|
+
"""
|
|
63
|
+
Generate synthesis for a Wheel.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
GenerateSynthesisResult with the Synthesis node
|
|
67
|
+
|
|
68
|
+
Raises:
|
|
69
|
+
ValueError: If wheel not found or has no Transformations
|
|
70
|
+
"""
|
|
71
|
+
wheel = self._resolve_wheel()
|
|
72
|
+
|
|
73
|
+
# Check transformations exist
|
|
74
|
+
transformations = wheel.transformations
|
|
75
|
+
if not transformations:
|
|
76
|
+
raise ValueError(
|
|
77
|
+
f"Wheel {wheel.short_hash} has no Transformations — "
|
|
78
|
+
f"run explore_transformations first"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Idempotent: return existing synthesis
|
|
82
|
+
existing = self._find_existing_synthesis(wheel)
|
|
83
|
+
if existing:
|
|
84
|
+
self._report.summary = (
|
|
85
|
+
f"Synthesis already exists for Wheel {wheel.short_hash}"
|
|
86
|
+
)
|
|
87
|
+
self._report.artifacts["wheel"] = wheel.short_hash
|
|
88
|
+
self._report.artifacts["existing"] = True
|
|
89
|
+
return GenerateSynthesisResult(synthesis=existing, is_new=False)
|
|
90
|
+
|
|
91
|
+
# Gather context
|
|
92
|
+
input_text = await self._get_input_text()
|
|
93
|
+
lower_layer_context = self._build_lower_layer_context(wheel)
|
|
94
|
+
|
|
95
|
+
# Call the concern
|
|
96
|
+
concern = SynthesisGeneration()
|
|
97
|
+
result = await concern.resolve(
|
|
98
|
+
wheel=wheel,
|
|
99
|
+
input_text=input_text,
|
|
100
|
+
lower_layer_context=lower_layer_context,
|
|
101
|
+
)
|
|
102
|
+
self._report = self._report.merge(concern.report)
|
|
103
|
+
|
|
104
|
+
if result is None:
|
|
105
|
+
raise ValueError(
|
|
106
|
+
f"Synthesis generation failed for Wheel {wheel.short_hash}"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Create Synthesis node and wire up
|
|
110
|
+
synthesis = Synthesis()
|
|
111
|
+
synthesis.save()
|
|
112
|
+
|
|
113
|
+
synthesis.s_plus.connect(
|
|
114
|
+
result.s_plus_statement,
|
|
115
|
+
relationship=SPlusRelationship(
|
|
116
|
+
alias=POSITION_S_PLUS, heuristic_similarity=None
|
|
117
|
+
),
|
|
118
|
+
)
|
|
119
|
+
synthesis.s_minus.connect(
|
|
120
|
+
result.s_minus_statement,
|
|
121
|
+
relationship=SMinusRelationship(
|
|
122
|
+
alias=POSITION_S_MINUS, heuristic_similarity=None
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
synthesis.target.connect(wheel, relationship=SynthesisOfRelationship())
|
|
126
|
+
synthesis.commit()
|
|
127
|
+
|
|
128
|
+
# Report
|
|
129
|
+
self._report.node_created(synthesis)
|
|
130
|
+
self._report.artifacts["wheel"] = wheel.short_hash
|
|
131
|
+
self._report.artifacts["s_plus"] = result.s_plus_statement.text
|
|
132
|
+
self._report.artifacts["s_minus"] = result.s_minus_statement.text
|
|
133
|
+
self._report.summary = (
|
|
134
|
+
f"Generated synthesis for Wheel {wheel.short_hash}: "
|
|
135
|
+
f"S+ = \"{result.s_plus_statement.text}\", "
|
|
136
|
+
f"S- = \"{result.s_minus_statement.text}\""
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return GenerateSynthesisResult(synthesis=synthesis)
|
|
140
|
+
|
|
141
|
+
def _resolve_wheel(self) -> Wheel:
|
|
142
|
+
"""Resolve Wheel from hash or prefix."""
|
|
143
|
+
from dialectical_framework.graph.nodes.wheel import Wheel
|
|
144
|
+
from dialectical_framework.graph.repositories.node_repository import (
|
|
145
|
+
NodeRepository,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
repo = NodeRepository()
|
|
149
|
+
node = repo.find_by_hash(self.wheel_hash, node_type=Wheel)
|
|
150
|
+
if node is None:
|
|
151
|
+
raise ValueError(f"Wheel not found: {self.wheel_hash}")
|
|
152
|
+
return node
|
|
153
|
+
|
|
154
|
+
@staticmethod
|
|
155
|
+
def _find_existing_synthesis(wheel: Wheel) -> Optional[Synthesis]:
|
|
156
|
+
"""Check if the wheel already has a synthesis."""
|
|
157
|
+
existing = list(wheel.synthesis.all())
|
|
158
|
+
if existing:
|
|
159
|
+
return existing[0][0]
|
|
160
|
+
return None
|
|
161
|
+
|
|
162
|
+
@inject
|
|
163
|
+
async def _get_input_text(
|
|
164
|
+
self,
|
|
165
|
+
input_resolver: InputResolver = Provide[DI.input_resolver],
|
|
166
|
+
) -> str:
|
|
167
|
+
"""Get concatenated text from all inputs in scope."""
|
|
168
|
+
from dialectical_framework.graph.repositories.input_repository import (
|
|
169
|
+
InputRepository,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
repo = InputRepository()
|
|
173
|
+
inputs = repo.get_all()
|
|
174
|
+
|
|
175
|
+
if not inputs:
|
|
176
|
+
return ""
|
|
177
|
+
|
|
178
|
+
texts = []
|
|
179
|
+
for input_node in inputs:
|
|
180
|
+
resolved = await input_resolver.resolve(input_node)
|
|
181
|
+
texts.append(resolved)
|
|
182
|
+
|
|
183
|
+
return "\n\n---\n\n".join(texts)
|
|
184
|
+
|
|
185
|
+
def _build_lower_layer_context(self, wheel: Wheel) -> str:
|
|
186
|
+
"""Find synthesis from sub-wheels (lower PP layers) sharing perspectives."""
|
|
187
|
+
from dialectical_framework.graph.repositories.wheel_repository import (
|
|
188
|
+
WheelRepository,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
pps = wheel._perspectives
|
|
192
|
+
if len(pps) < 2:
|
|
193
|
+
return ""
|
|
194
|
+
|
|
195
|
+
wheel_repo = WheelRepository()
|
|
196
|
+
parts: list[str] = []
|
|
197
|
+
|
|
198
|
+
# Look one layer down (N-1 perspectives)
|
|
199
|
+
for combo in combinations(pps, len(pps) - 1):
|
|
200
|
+
sub_wheels = wheel_repo.find_by_layer(list(combo))
|
|
201
|
+
for sub_wheel in sub_wheels:
|
|
202
|
+
for synth, _ in sub_wheel.synthesis.all():
|
|
203
|
+
parts.append(
|
|
204
|
+
f"Sub-wheel [{sub_wheel.short_hash}]: {synth:positions:0}"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
return "\n".join(parts)
|
|
@@ -25,6 +25,7 @@ On first message (or when resuming):
|
|
|
25
25
|
- If wheels don't exist yet, call `build_wheels` to create them.
|
|
26
26
|
- If build_wheels yields no wheels (e.g., only one position), explain that exploration needs at least two positions interacting — suggest the user adds more via the analysis thread.
|
|
27
27
|
- If transformations don't exist yet, call `explore_transformations` for each wheel.
|
|
28
|
+
- After transformations exist, call `generate_synthesis` to derive S+/S- for each wheel.
|
|
28
29
|
|
|
29
30
|
When presenting transformations:
|
|
30
31
|
- Focus on the Ac+ (constructive action: T- -> A+) and Re+ (constructive reflection: A- -> T+).
|
|
@@ -48,6 +49,7 @@ When the user wants to go deeper on a specific transformation:
|
|
|
48
49
|
|
|
49
50
|
- `build_wheels` -- Generate causal structures (Cycles + Wheels) from this Nexus. Use nexus_hash: "{nexus_hash}".
|
|
50
51
|
- `explore_transformations` -- Generate Action-Reflection transformations for a Wheel.
|
|
52
|
+
- `generate_synthesis` -- Generate S+/S- synthesis for a Wheel. Requires transformations first.
|
|
51
53
|
- `present_exploration` -- Show current state of this Nexus: perspectives, wheels, transformations.
|
|
52
54
|
- `inspect_node` -- Deep-dive any node by hash.
|
|
53
55
|
- `query_graph` -- Raw Cypher for custom queries. Call `get_schema` first.
|
dialectical_framework-1.2.1/src/dialectical_framework/agents/explorer/tools/generate_synthesis.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""
|
|
2
|
+
generate_synthesis tool: thin LLM-facing wrapper around the GenerateSynthesis skill.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Annotated
|
|
8
|
+
|
|
9
|
+
from mirascope import llm
|
|
10
|
+
from pydantic import Field
|
|
11
|
+
|
|
12
|
+
from dialectical_framework.agents.explorer.skills.generate_synthesis import (
|
|
13
|
+
GenerateSynthesis,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@llm.tool
|
|
18
|
+
async def generate_synthesis(
|
|
19
|
+
wheel_hash: Annotated[
|
|
20
|
+
str,
|
|
21
|
+
Field(description="Hash of the Wheel to generate synthesis for"),
|
|
22
|
+
],
|
|
23
|
+
) -> str:
|
|
24
|
+
"""Generate S+/S- synthesis for a Wheel — the emergent properties arising from circular causality. S+ represents complementary harmony (1+1>2), S- represents reinforcing uniformity (1+1<2). The wheel must have transformations computed first."""
|
|
25
|
+
skill = GenerateSynthesis(wheel_hash=wheel_hash)
|
|
26
|
+
await skill.resolve()
|
|
27
|
+
return str(skill.report)
|
|
@@ -10,15 +10,40 @@ All three levels inherit from ReasonableConcern — same interface (resolve + re
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import asyncio
|
|
14
|
+
import inspect
|
|
13
15
|
from abc import ABC, abstractmethod
|
|
16
|
+
from functools import wraps
|
|
14
17
|
from typing import TYPE_CHECKING, Any, Generic, TypeVar
|
|
15
18
|
|
|
19
|
+
from langfuse import get_client, observe
|
|
20
|
+
|
|
16
21
|
if TYPE_CHECKING:
|
|
17
22
|
from dialectical_framework.agents.execution_report import ExecutionReport
|
|
18
23
|
|
|
19
24
|
R_co = TypeVar("R_co", covariant=True)
|
|
20
25
|
|
|
21
26
|
|
|
27
|
+
def _conditional_observe(name: str, fn: Any) -> Any:
|
|
28
|
+
"""Wrap fn with @observe only when an active Langfuse trace exists."""
|
|
29
|
+
observed = observe(name=name)(fn)
|
|
30
|
+
|
|
31
|
+
if asyncio.iscoroutinefunction(fn):
|
|
32
|
+
@wraps(fn)
|
|
33
|
+
async def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
34
|
+
if get_client().get_current_trace_id():
|
|
35
|
+
return await observed(*args, **kwargs)
|
|
36
|
+
return await fn(*args, **kwargs)
|
|
37
|
+
else:
|
|
38
|
+
@wraps(fn)
|
|
39
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
40
|
+
if get_client().get_current_trace_id():
|
|
41
|
+
return observed(*args, **kwargs)
|
|
42
|
+
return fn(*args, **kwargs)
|
|
43
|
+
|
|
44
|
+
return wrapper
|
|
45
|
+
|
|
46
|
+
|
|
22
47
|
class ReasonableConcern(ABC, Generic[R_co]):
|
|
23
48
|
"""
|
|
24
49
|
Base class for concerns, skills, and tools.
|
|
@@ -34,6 +59,12 @@ class ReasonableConcern(ABC, Generic[R_co]):
|
|
|
34
59
|
|
|
35
60
|
_report: ExecutionReport
|
|
36
61
|
|
|
62
|
+
def __init_subclass__(cls, **kwargs: Any) -> None:
|
|
63
|
+
super().__init_subclass__(**kwargs)
|
|
64
|
+
if "resolve" in cls.__dict__:
|
|
65
|
+
original = cls.__dict__["resolve"]
|
|
66
|
+
cls.resolve = _conditional_observe(cls.__name__, original) # type: ignore[assignment]
|
|
67
|
+
|
|
37
68
|
def __getattr__(self, name: str) -> Any:
|
|
38
69
|
if name == "_report":
|
|
39
70
|
from dialectical_framework.agents.execution_report import ExecutionReport
|