dialectical-framework 2.0.8__tar.gz → 2.0.11__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-2.0.8 → dialectical_framework-2.0.11}/PKG-INFO +1 -1
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/pyproject.toml +1 -1
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/consultant/consultant.py +15 -2
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/conversation_facilitator.py +12 -1
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/transformation_sketch.py +39 -5
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/settings.py +26 -2
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/settings_context.py +2 -2
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/bedrock_provider.py +56 -22
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/format_compat.py +11 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/use_brain.py +98 -6
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/LICENSE +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/PATENTS +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/README.md +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/advisor.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/build_policy.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/migration.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/reply_hygiene.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/system_prompts.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/anchor.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/deepen.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/explore.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/ingest.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/note.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/record_decision.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/scoped.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/advisor/tools/sync.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/agent_context.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/analyst.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/skills/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/skills/anchor_theses.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/skills/edit_perspective.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/skills/expand_polarities.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/skills/find_polarities.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/skills/introduce_polarity.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/skills/sketch_tetrad.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/skills/surface_theses.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/system_prompts.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/tools/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/analyst/tools/place_statement.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/app_spec.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/apps.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/consultant/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/execution_report.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/explorer.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/skills/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/skills/build_wheels.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/skills/explore_transformations.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/skills/generate_synthesis.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/system_prompts.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/tools/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/tools/create_nexus.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/tools/expand_nexus.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/tools/generate_synthesis.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/explorer/tools/present_exploration.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/add_input.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/audit_feasibility.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/create_dx_input.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/digest_input.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/discard.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/get_schema.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/inspect_node.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/present_analysis.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/query_graph.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/read_digest.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/orchestrator/tools/read_input.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/reasonable_concern.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/stream_events.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/toolsets.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/agents/turn_timing.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/ac_re_taxonomy.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/action_extraction.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/add_input.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/ai_dto/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/ai_dto/statement_dto.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/ai_dto/statements_deck_dto.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/antithesis_classification.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/antithesis_extraction.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/antithetical_thesis_detection.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/aspect_classification.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/aspect_generation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/build_status.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/causality_estimator.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/causality_estimator_balanced.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/causality_estimator_criteria.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/causality_estimator_desirable.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/causality_estimator_feasible.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/causality_estimator_realistic.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/causality_normalizer.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality/estimator_resolver.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/causality_estimation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/control_statements_check.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/create_dx_input.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/create_nexus.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/decision_coherence_check.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/decision_confirmation_check.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/diagonal_oppositions_check.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/dialectical_context.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/discard.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/display_text_edit.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/expand_nexus.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/perspective_combination.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/perspective_validation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/positive_ac_re_apex_derivation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/record_decision.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/scoring_scales.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/source_digest.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/statement_classification.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/statement_deduplication.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/statement_headline.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/statement_placement.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/synthesis_generation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/tetrad_candidates.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/tetrad_grounding.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/tetrad_sketch.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/thesis_extraction.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/transformation_audit.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/transformation_generation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/concerns/view_sketch.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/dialectical_reasoning.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/enums/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/enums/causality_preset.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/enums/di.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/events/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/events/graph_event.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/events/graph_event_bus.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/events/progress_event.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/exceptions/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/exceptions/node_errors.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/exceptions/provider_errors.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/exceptions/resolver_errors.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/composite_input_resolver.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/dialexity_input_resolver.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/estimation_manager.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/mixins/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/mixins/incremental_build_mixin.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/mixins/intent_mixin.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/mixins/persistable_mixin.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/assessable_entity.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/base_node.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/case.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/cycle.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/decision.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/estimation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/ideas.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/input.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/nexus.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/note.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/perspective.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/polarity.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/rationale.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/statement.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/synthesis.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/transformation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/transition.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/nodes/wheel.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationship_manager.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/action_reflection_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/belongs_to_cycle_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/belongs_to_nexus_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/changed_to_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/contradiction_of_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/critiques_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/distilled_to_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/estimates_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/explains_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/grounded_in_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/has_input_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/has_statement_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/has_wheel_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/immutable_structure.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/is_source_of_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/is_target_of_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/negative_side_of_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/opposite_direction_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/opposite_of_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/polarity_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/positive_side_of_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/provides_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/relationships/synthesis_of_relationship.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/rendering.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/case_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/cycle_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/decision_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/input_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/nexus_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/node_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/note_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/perspective_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/polarity_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/schema_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/statement_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/transformation_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/repositories/wheel_repository.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/scope_context.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/verbatim_input_resolver.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/views.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/wheel_segment.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/graph/wheel_segment_polar_pair.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/protocols/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/protocols/has_config.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/protocols/input_resolver.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/py.typed +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/__init__.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/async_drain.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/call_census.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/chunking.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/concurrency.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/dc_replace.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/decompose_probability_uniformly.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/edge_context.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/effect_logger.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/input_context.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/order_transitions.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/progress.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/retry_accounting.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/sequence_generation.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/thinking_compat.py +0 -0
- {dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/utils/utterance.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dialectical-framework
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.11
|
|
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 = "2.0.
|
|
3
|
+
version = "2.0.11"
|
|
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"
|
|
@@ -42,6 +42,7 @@ from contextlib import aclosing
|
|
|
42
42
|
from typing import Any, AsyncGenerator, Optional
|
|
43
43
|
|
|
44
44
|
from mirascope import llm
|
|
45
|
+
from mirascope.llm.exceptions import ProviderError
|
|
45
46
|
|
|
46
47
|
from dialectical_framework.agents.advisor.advisor import ChatResponse
|
|
47
48
|
from dialectical_framework.agents.advisor.system_prompts import (
|
|
@@ -145,9 +146,21 @@ _TOOL_TOKENS = (
|
|
|
145
146
|
|
|
146
147
|
def _failed_draw(error: BaseException) -> FailedDrawView:
|
|
147
148
|
"""A failed draw's record: the exception's type, the provider's refusal
|
|
148
|
-
category when it is a `ModelRefusal` that carries one, and its text.
|
|
149
|
+
category when it is a `ModelRefusal` that carries one, and its text.
|
|
150
|
+
|
|
151
|
+
The type is the PROVIDER's where Mirascope wrapped one: its `ProviderError`
|
|
152
|
+
subclasses carry the SDK exception as `original_exception`, and that is
|
|
153
|
+
the name a host counts by (`APITimeoutError` for a stalled draw, where the
|
|
154
|
+
wrapper says only `TimeoutError` — the builtin's name too). `ParseError`
|
|
155
|
+
is not a `ProviderError` and keeps its own name.
|
|
156
|
+
"""
|
|
157
|
+
original = (
|
|
158
|
+
getattr(error, "original_exception", None)
|
|
159
|
+
if isinstance(error, ProviderError)
|
|
160
|
+
else None
|
|
161
|
+
)
|
|
149
162
|
return FailedDrawView(
|
|
150
|
-
kind=type(error).__name__,
|
|
163
|
+
kind=type(original if isinstance(original, BaseException) else error).__name__,
|
|
151
164
|
category=getattr(error, "category", None) if isinstance(error, ModelRefusal) else None,
|
|
152
165
|
message=str(error) or None,
|
|
153
166
|
)
|
|
@@ -567,8 +567,19 @@ class ConversationFacilitator(SettingsAware):
|
|
|
567
567
|
self._strip_caller_from_messages(response.messages)
|
|
568
568
|
# The continuation is a conversational round too (and it is
|
|
569
569
|
# Mirascope's own request, so nothing in `use_brain` marks it).
|
|
570
|
+
# Retried like the streamed resume (`_start_stream_round`):
|
|
571
|
+
# since the Bedrock client's own retry went to 0
|
|
572
|
+
# (`bedrock_provider._SDK_MAX_RETRIES`) this is the one
|
|
573
|
+
# provider request with no other retry layer. Safe to re-ask
|
|
574
|
+
# — `resume_async` is `response.messages + [user(outputs)]`
|
|
575
|
+
# with no mutation of the response — and the tools have
|
|
576
|
+
# already run, so a retry re-sends their outputs, never
|
|
577
|
+
# re-executes them.
|
|
570
578
|
with conversational_round():
|
|
571
|
-
|
|
579
|
+
resuming = response
|
|
580
|
+
response = await retry_transient(
|
|
581
|
+
lambda: resuming.resume(tool_outputs), what="Resume"
|
|
582
|
+
)
|
|
572
583
|
# Mirascope's own request, below `use_brain`: a provider that
|
|
573
584
|
# does not raise on a refusal itself only says so here.
|
|
574
585
|
if getattr(response, "finish_reason", None) == FinishReason.REFUSAL:
|
|
@@ -53,8 +53,30 @@ one-shot can replace it there is a separate, gated measurement
|
|
|
53
53
|
(`one-shot-transformation.md`, "Open"). Texts only, nothing persisted, no
|
|
54
54
|
scores — a number here would be an unchecked guess.
|
|
55
55
|
|
|
56
|
-
Unthinking, like every concern
|
|
57
|
-
|
|
56
|
+
Unthinking, like every concern. Measured once, on Sonnet 5.5 under the
|
|
57
|
+
structured-output constraint (2026-10-09, `probe_structured_s_minus.py`, 100
|
|
58
|
+
pairs): the same call thinking at `low` (`format_mode="json", thinking="low"`)
|
|
59
|
+
kept Ac- (+4, within noise) where the in-turn wording alone cost it a little
|
|
60
|
+
(−8 / −4 over two runs), at no latency on that model (4.7 s against 4.4 s a
|
|
61
|
+
write); on S- it added nothing beyond the wording (+15 either way). Not wired:
|
|
62
|
+
on a model that keeps forced tool use it would also move this call to JSON
|
|
63
|
+
mode, where no figure for it was taken. The next lever, if Ac- under the
|
|
64
|
+
constraint needs one.
|
|
65
|
+
|
|
66
|
+
THE CONSTRAINT AND S- (2026-10-09)
|
|
67
|
+
=================================
|
|
68
|
+
On a model whose structured calls carry `output_config.format`
|
|
69
|
+
(`format_compat.structured_output_format`; Sonnet 5.5 first), the reply comes
|
|
70
|
+
back as one compact line with terser texts — no prose, no thinking, the same
|
|
71
|
+
request otherwise (`probe_structured_wire.py`) — and S- came back as the two
|
|
72
|
+
traps IN TURN: a distinct third failure in 42% of 100 (four runs: 42/44/41/42)
|
|
73
|
+
against 57% for the same call without the constraint (+15, CI +2..+28), which
|
|
74
|
+
is what the first app measured on its cards (63% → 41% / 33%). Ac-/Re- were
|
|
75
|
+
not hurt; the constraint helps them (96-98% valid against 91-93%). The rule
|
|
76
|
+
now names the in-turn forms (`SYNTHESIS_SHAPE`), which restores S- to the
|
|
77
|
+
unconstrained level under the constraint and is neutral without it. The
|
|
78
|
+
constraint stays: it ended the parse re-asks, and the loss was a shape the
|
|
79
|
+
rule did not name.
|
|
58
80
|
|
|
59
81
|
SELECTION: AVAILABLE, OFF BY DEFAULT
|
|
60
82
|
====================================
|
|
@@ -99,8 +121,19 @@ TRANSFORMATION_POSITIONS = """1. The action (Ac): the concrete move that carries
|
|
|
99
121
|
|
|
100
122
|
#: What the developments produce together. The S- sentences are the measured
|
|
101
123
|
#: fix (`one-shot-transformation.md`: third-trap 4/17 → 12/17 on graph-built
|
|
102
|
-
#: wheels once the synthesis prompt carried them) and are kept word for word
|
|
103
|
-
|
|
124
|
+
#: wheels once the synthesis prompt carried them) and are kept word for word,
|
|
125
|
+
#: with the two IN-TURN forms added on 2026-10-09: a writer under a structured-
|
|
126
|
+
#: output constraint (Sonnet 5.5, `format_compat.structured_output_format`)
|
|
127
|
+
#: wrote S- as the two traps in sequence ("X, then Y", "X alternating with Y")
|
|
128
|
+
#: in 13-14 of ~58 failures per 100 against 4 of 43 without the constraint,
|
|
129
|
+
#: and the rule named only the side-by-side forms. With them named: S- as a
|
|
130
|
+
#: distinct third failure 42% → 57% on 100 pairs, twice (+15 / +16, both clear
|
|
131
|
+
#: of noise), back to the unconstrained writer's 57%; neutral on Sonnet 5
|
|
132
|
+
#: (−1, 100 pairs). Price: a pairwise "which S- is more specific" judge
|
|
133
|
+
#: prefers the trap-restating headline (30-48 against this wording; an arm
|
|
134
|
+
#: that asked for particulars won that read 60-19 and lost the whole shape
|
|
135
|
+
#: gain), so that read is not a shape read. `tests/e2e/probe_structured_s_minus.py`.
|
|
136
|
+
SYNTHESIS_SHAPE = """S+ is what emerges only when Ac+ and Re+ run together — a gain in dimension, not a middle: not "both", not the two strengths listed side by side. S- is the ONE named state Ac- and Re- produce together: a single way of failing that is neither trap on its own and not a choice between them. "Either X or Y", "X versus Y", "X while Y", "X, then Y" and "X alternating with Y" with X and Y the two traps are the inputs listed, side by side or in turn, not the collapse named."""
|
|
104
137
|
|
|
105
138
|
#: How a one-shot call builds it: the poles FIRST, because a degraded action
|
|
106
139
|
#: needs an action to degrade (the measured order), then the developments,
|
|
@@ -236,7 +269,8 @@ class TransformationSketchDto(BaseModel):
|
|
|
236
269
|
s_minus: str = Field(
|
|
237
270
|
description=(
|
|
238
271
|
"S- — what Ac- and Re- running together collapse into: ONE named way of "
|
|
239
|
-
"failing that is neither T- nor A- on its own. Never 'either X or Y'
|
|
272
|
+
"failing that is neither T- nor A- on its own. Never 'either X or Y', "
|
|
273
|
+
"'X then Y' or 'X alternating with Y'."
|
|
240
274
|
)
|
|
241
275
|
)
|
|
242
276
|
|
{dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/src/dialectical_framework/settings.py
RENAMED
|
@@ -40,8 +40,8 @@ class Settings(BaseModel):
|
|
|
40
40
|
|
|
41
41
|
Per process (read once, from the base `DialecticalReasoning.setup()` installs;
|
|
42
42
|
a value inside `using_settings` has no effect): `graph_db_*` (the connection is
|
|
43
|
-
a Singleton), `llm_connect_timeout_s` (the provider
|
|
44
|
-
`effect_log_dir` (installed in `setup`). `DIALEXITY_MAX_CONCURRENT_LLM_CALLS`
|
|
43
|
+
a Singleton), `llm_connect_timeout_s` and `llm_read_timeout_s` (the provider
|
|
44
|
+
is registered once), `effect_log_dir` (installed in `setup`). `DIALEXITY_MAX_CONCURRENT_LLM_CALLS`
|
|
45
45
|
is not a field at all: an env var behind one process-wide semaphore.
|
|
46
46
|
"""
|
|
47
47
|
|
|
@@ -276,6 +276,29 @@ class Settings(BaseModel):
|
|
|
276
276
|
# slow generation is not the problem being solved here.
|
|
277
277
|
llm_connect_timeout_s: float = Field(default=30.0, description="TCP/TLS connect timeout for LLM calls, in seconds. Raise on slow or high-latency links.")
|
|
278
278
|
|
|
279
|
+
# Read timeout for the Bedrock client, in seconds: how long one provider
|
|
280
|
+
# call may go without a byte arriving before it raises (`APITimeoutError`,
|
|
281
|
+
# which the ladder retries ONCE — `use_brain._STALL_RETRY_MAX`).
|
|
282
|
+
#
|
|
283
|
+
# The SDK's default is 600s, and the client used to keep it, so a stalled
|
|
284
|
+
# call held whatever was waiting on it for ten minutes with no error and no
|
|
285
|
+
# retry on record (a 610s turn, `prompt-vs-machinery`; the handoff that set
|
|
286
|
+
# this field: one of three gathered draws hung a 20-31s card for 300s,
|
|
287
|
+
# 2026-10-09, Sonnet 5.5). On a NON-streamed call the body arrives whole,
|
|
288
|
+
# so this is a ceiling on one generation; on a streamed round it is the gap
|
|
289
|
+
# between two chunks, and a thinking turn streams its deltas (the
|
|
290
|
+
# facilitator asks for `include_thoughts`), so the long silence is the
|
|
291
|
+
# non-streamed case only. 120s clears every unstalled generation in the
|
|
292
|
+
# archive (the longest measured conversational rounds sit under a minute on
|
|
293
|
+
# Sonnet 5 with thinking) while cutting a stall from 600s to two minutes. A
|
|
294
|
+
# host whose calls are short sets it lower: the first app's draws run ~15s,
|
|
295
|
+
# texts ~8s, structured calls ~3s on Sonnet 5.5, and it runs at 30s. Too
|
|
296
|
+
# low, and a legitimately long generation (a digest of a 40k-character
|
|
297
|
+
# part, an Opus round with a large dump) is cut and re-asked — the retry
|
|
298
|
+
# does not help a call that needed the time. Read once, with the connect
|
|
299
|
+
# timeout, when the provider registers.
|
|
300
|
+
llm_read_timeout_s: float = Field(default=120.0, description="Read timeout for LLM calls, in seconds: the longest one call may wait for the provider's next byte. Lower where every call is short; a stall then surfaces as a timeout instead of holding the caller.")
|
|
301
|
+
|
|
279
302
|
@classmethod
|
|
280
303
|
def from_partial(cls, partial_settings: Optional[Settings] = None) -> Self:
|
|
281
304
|
"""
|
|
@@ -353,5 +376,6 @@ class Settings(BaseModel):
|
|
|
353
376
|
# something. `**` on an empty dict sends nothing.
|
|
354
377
|
**_env_thinking_level(),
|
|
355
378
|
llm_connect_timeout_s=float(os.getenv("DIALEXITY_LLM_CONNECT_TIMEOUT_S", 30.0)),
|
|
379
|
+
llm_read_timeout_s=float(os.getenv("DIALEXITY_LLM_READ_TIMEOUT_S", 120.0)),
|
|
356
380
|
effect_log_dir=os.getenv("DIALEXITY_GRAPH_LOG_DIR"),
|
|
357
381
|
)
|
|
@@ -31,8 +31,8 @@ TWO TIERS, as the code already treats them (see `Settings`):
|
|
|
31
31
|
through `SettingsAware.settings` (word limits, thinking level, the Advisor's
|
|
32
32
|
floors and caps, the audit switches);
|
|
33
33
|
- read ONCE per process, from the base only: `graph_db_*` (the connection is a
|
|
34
|
-
Singleton), `llm_connect_timeout_s` (the provider is
|
|
35
|
-
`effect_log_dir` (installed in `setup`). A value for these inside
|
|
34
|
+
Singleton), `llm_connect_timeout_s` and `llm_read_timeout_s` (the provider is
|
|
35
|
+
registered once), `effect_log_dir` (installed in `setup`). A value for these inside
|
|
36
36
|
`using_settings` has no effect, by construction, not by accident.
|
|
37
37
|
|
|
38
38
|
`container.settings.override(...)` RAISES: it would replace this provider with one
|
|
@@ -36,27 +36,51 @@ if TYPE_CHECKING:
|
|
|
36
36
|
from mirascope.llm.tools import AsyncToolkit, Toolkit
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
def
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
def _client_timeout(
|
|
40
|
+
connect_timeout_s: float | None, read_timeout_s: float | None = None
|
|
41
|
+
) -> httpx.Timeout:
|
|
42
|
+
"""SDK default timeouts with the CONNECT and READ phases set by the framework.
|
|
43
|
+
|
|
44
|
+
Connect: the SDK's 5s assumes a warm datacenter link. A cold TLS handshake
|
|
45
|
+
over a tethered/VPN/mobile connection measured 7.7s, so the first call on
|
|
46
|
+
every fresh connection failed — and the parallel stages failed hardest,
|
|
47
|
+
since each concurrent call opens its own cold connection while a sequential
|
|
48
|
+
one reuses a handshaked socket.
|
|
49
|
+
|
|
50
|
+
Read: the SDK's 600s is the length of a stall nobody asked for. A provider
|
|
51
|
+
call that stops sending holds its caller for ten minutes with no error, and
|
|
52
|
+
where callers are gathered (the view turn's best-of-3) one stalled draw
|
|
53
|
+
holds the two that finished (a 300s card where the same case took 20-31s,
|
|
54
|
+
2026-10-09). `Settings.llm_read_timeout_s` sets it; a timeout raises
|
|
55
|
+
`APITimeoutError`, which the ladder classifies as a stall and re-asks once.
|
|
56
|
+
Write and pool keep the SDK defaults: nothing has stalled on either.
|
|
49
57
|
"""
|
|
50
|
-
|
|
58
|
+
connect = connect_timeout_s if connect_timeout_s is not None else 30.0
|
|
59
|
+
read = read_timeout_s if read_timeout_s is not None else 120.0
|
|
51
60
|
default = DEFAULT_TIMEOUT
|
|
52
61
|
return httpx.Timeout(
|
|
53
|
-
connect=
|
|
54
|
-
read=
|
|
62
|
+
connect=connect,
|
|
63
|
+
read=read,
|
|
55
64
|
write=default.write,
|
|
56
65
|
pool=default.pool,
|
|
57
66
|
)
|
|
58
67
|
|
|
59
68
|
|
|
69
|
+
#: The Anthropic SDK's own retry is OFF: every retry the framework makes is one
|
|
70
|
+
#: it can see. The SDK defaults to two retries of a timeout, a connection error
|
|
71
|
+
#: or a 408/409/429/5xx with its own backoff, BELOW `use_brain`'s ladder and
|
|
72
|
+
#: `retry_transient` — so a stalled call cost three read timeouts before the
|
|
73
|
+
#: ladder saw one failure, and `retry_accounting`/`call_census` recorded none of
|
|
74
|
+
#: it (a 610s turn with `retry_count` 0, `prompt-vs-machinery`). With this at 0
|
|
75
|
+
#: the bound on one call is the ladder's: a stall is (`_STALL_RETRY_MAX`) × the
|
|
76
|
+
#: read timeout plus its flat delay, and the retry is on the account. Every
|
|
77
|
+
#: provider request the framework makes passes a retry layer of its own — the
|
|
78
|
+
#: ladder (`use_brain`), the streamed open and resume (`retry_transient` in
|
|
79
|
+
#: `_start_stream_round`) and, since this went to 0, the awaited resume too
|
|
80
|
+
#: (`ConversationFacilitator.submit`), which until then had only the SDK's.
|
|
81
|
+
_SDK_MAX_RETRIES = 0
|
|
82
|
+
|
|
83
|
+
|
|
60
84
|
#: Start of the Advisor's mutable graph dump inside its system prompt.
|
|
61
85
|
#:
|
|
62
86
|
#: `_CONTEXT_SLOT` (`agents/advisor/system_prompts.py`) is the LAST section and the
|
|
@@ -361,11 +385,19 @@ class BedrockAnthropicProvider(AnthropicProvider):
|
|
|
361
385
|
id = "bedrock"
|
|
362
386
|
default_scope = "bedrock/"
|
|
363
387
|
|
|
364
|
-
def __init__(
|
|
388
|
+
def __init__(
|
|
389
|
+
self,
|
|
390
|
+
*,
|
|
391
|
+
connect_timeout_s: float | None = None,
|
|
392
|
+
read_timeout_s: float | None = None,
|
|
393
|
+
**kwargs, # noqa: ARG002
|
|
394
|
+
) -> None:
|
|
365
395
|
# Skip super().__init__() — parent creates Anthropic/AsyncAnthropic clients we don't need
|
|
366
|
-
timeout =
|
|
367
|
-
self.client = AnthropicBedrock(timeout=timeout)
|
|
368
|
-
self.async_client = AsyncAnthropicBedrock(
|
|
396
|
+
timeout = _client_timeout(connect_timeout_s, read_timeout_s)
|
|
397
|
+
self.client = AnthropicBedrock(timeout=timeout, max_retries=_SDK_MAX_RETRIES)
|
|
398
|
+
self.async_client = AsyncAnthropicBedrock(
|
|
399
|
+
timeout=timeout, max_retries=_SDK_MAX_RETRIES
|
|
400
|
+
)
|
|
369
401
|
self._beta_provider = None
|
|
370
402
|
|
|
371
403
|
@staticmethod
|
|
@@ -594,17 +626,19 @@ def ensure_bedrock_provider(
|
|
|
594
626
|
) -> None:
|
|
595
627
|
"""Register the bedrock provider if not already registered. Idempotent.
|
|
596
628
|
|
|
597
|
-
Registration happens on the first call, so `llm_connect_timeout_s`
|
|
598
|
-
from DI here rather than in `__init__`
|
|
599
|
-
no arguments). Consequence of the
|
|
600
|
-
the first LLM call of the
|
|
629
|
+
Registration happens on the first call, so `llm_connect_timeout_s` and
|
|
630
|
+
`llm_read_timeout_s` are read from DI here rather than in `__init__`
|
|
631
|
+
(Mirascope constructs providers with no arguments). Consequence of the
|
|
632
|
+
idempotence: changing either setting after the first LLM call of the
|
|
633
|
+
process has no effect.
|
|
601
634
|
"""
|
|
602
635
|
global _registered
|
|
603
636
|
if _registered:
|
|
604
637
|
return
|
|
605
638
|
llm.register_provider(
|
|
606
639
|
BedrockAnthropicProvider(
|
|
607
|
-
connect_timeout_s=getattr(settings, "llm_connect_timeout_s", None)
|
|
640
|
+
connect_timeout_s=getattr(settings, "llm_connect_timeout_s", None),
|
|
641
|
+
read_timeout_s=getattr(settings, "llm_read_timeout_s", None),
|
|
608
642
|
),
|
|
609
643
|
scope="bedrock/",
|
|
610
644
|
)
|
|
@@ -38,6 +38,17 @@ refuse forced tool use — the ones whose structured calls go in JSON mode in
|
|
|
38
38
|
the first place, explicitly (`format_mode="json"`) or by substitution — and
|
|
39
39
|
to no other: Sonnet 5 / Opus 5 took it too in the probe, but every judged
|
|
40
40
|
figure there was taken without it, so widening it is a measurement.
|
|
41
|
+
|
|
42
|
+
**The constraint changes what is written, not only how it parses.** Under it
|
|
43
|
+
the reply is one compact line with terser texts (`tests/e2e/
|
|
44
|
+
probe_structured_wire.py`), and `TransformationSketch`'s S- came back as the
|
|
45
|
+
two traps in turn: a distinct third failure 42% against 57% unconstrained on
|
|
46
|
+
Sonnet 5.5 (100 pairs, +15 clear of noise; the first app saw 63% → 33-41%),
|
|
47
|
+
while Ac-/Re- validity rose. The repair was the prompt, not the constraint:
|
|
48
|
+
`SYNTHESIS_SHAPE` names the in-turn forms since 2026-10-09 and S- is back at
|
|
49
|
+
57% with the constraint on (`tests/e2e/probe_structured_s_minus.py`, the gate
|
|
50
|
+
for this seam on the transformation layer). A judged figure taken on a
|
|
51
|
+
forced-tool model does not transfer to the constrained call by itself.
|
|
41
52
|
"""
|
|
42
53
|
|
|
43
54
|
from __future__ import annotations
|
|
@@ -86,7 +86,8 @@ def use_brain(
|
|
|
86
86
|
Retries on ParseError (validation failures) with a FLAT delay — waiting does
|
|
87
87
|
not fix a wrong shape, see `_PARSE_RETRY_DELAY_S` — and on rate limits /
|
|
88
88
|
throttling, transient connection failures and transient 5xx with exponential
|
|
89
|
-
backoff (each with its own curve — see `_is_connection_error`)
|
|
89
|
+
backoff (each with its own curve — see `_is_connection_error`); a provider
|
|
90
|
+
STALL (read timeout) is re-asked once (`_STALL_RETRY_MAX`).
|
|
90
91
|
Automatically traces all LLM calls via Langfuse when configured.
|
|
91
92
|
|
|
92
93
|
When ``format`` is provided, returns the parsed model instance.
|
|
@@ -192,6 +193,7 @@ def use_brain(
|
|
|
192
193
|
rate_delay = _RATE_LIMIT_BASE_S
|
|
193
194
|
connect_delay = _CONNECT_RETRY_BASE_S
|
|
194
195
|
connect_attempts = 0
|
|
196
|
+
stall_attempts = 0
|
|
195
197
|
server_delay = _SERVER_RETRY_BASE_S
|
|
196
198
|
server_attempts = 0
|
|
197
199
|
last_error: Exception | None = None
|
|
@@ -325,6 +327,33 @@ def use_brain(
|
|
|
325
327
|
)
|
|
326
328
|
await asyncio.sleep(rate_delay)
|
|
327
329
|
rate_delay = min(rate_delay * 2.0, _RATE_LIMIT_CAP_S)
|
|
330
|
+
elif _is_stall_error(e):
|
|
331
|
+
# Checked BEFORE the connection branch: a read timeout is
|
|
332
|
+
# a connection error by class, and it must not get that
|
|
333
|
+
# curve's three attempts. Every stalled attempt has
|
|
334
|
+
# already cost the whole read timeout, so the bound on
|
|
335
|
+
# one call is `_STALL_RETRY_MAX` × that timeout plus one
|
|
336
|
+
# flat delay — the figure `Settings.llm_read_timeout_s`
|
|
337
|
+
# promises.
|
|
338
|
+
stall_attempts += 1
|
|
339
|
+
if stall_attempts >= _STALL_RETRY_MAX:
|
|
340
|
+
raise
|
|
341
|
+
last_error = e
|
|
342
|
+
logging.getLogger(__name__).warning(
|
|
343
|
+
"Provider stalled on %s (attempt %d/%d, %.0fs waited), "
|
|
344
|
+
"re-asking in %.0fs: %s",
|
|
345
|
+
format_name or method.__qualname__,
|
|
346
|
+
stall_attempts, _STALL_RETRY_MAX,
|
|
347
|
+
time.monotonic() - attempt_started, _STALL_RETRY_BASE_S, e,
|
|
348
|
+
)
|
|
349
|
+
if attempt < attempts - 1:
|
|
350
|
+
slept_s += _STALL_RETRY_BASE_S
|
|
351
|
+
record_retry(
|
|
352
|
+
"stall",
|
|
353
|
+
sleep_s=_STALL_RETRY_BASE_S,
|
|
354
|
+
attempt_s=time.monotonic() - attempt_started,
|
|
355
|
+
)
|
|
356
|
+
await asyncio.sleep(_STALL_RETRY_BASE_S)
|
|
328
357
|
elif _is_connection_error(e):
|
|
329
358
|
# Bounded separately from `attempts`: a down endpoint must
|
|
330
359
|
# surface as an error, not consume the whole retry budget.
|
|
@@ -783,8 +812,61 @@ _CONNECT_RETRY_MAX = 3
|
|
|
783
812
|
_CONNECT_RETRY_BASE_S = 2.0
|
|
784
813
|
|
|
785
814
|
|
|
815
|
+
#: A STALL — the provider accepted the request and then stopped sending — is
|
|
816
|
+
#: retried once, not on the connection curve. The two look alike by class (both
|
|
817
|
+
#: arrive as the SDK's `APITimeoutError`, Mirascope's `TimeoutError`) and differ
|
|
818
|
+
#: in what an attempt costs: a connect failure fails in milliseconds, a stall
|
|
819
|
+
#: fails after the WHOLE read timeout (`Settings.llm_read_timeout_s`). Three
|
|
820
|
+
#: attempts of that is three read timeouts before the caller hears anything,
|
|
821
|
+
#: and where callers are gathered (the view turn's best-of-3) every finished
|
|
822
|
+
#: draw waits for it. One re-ask is worth it — a stall is usually one bad
|
|
823
|
+
#: backend instance and a fresh request lands elsewhere — and a second stall in
|
|
824
|
+
#: a row is the ceiling. The delay is flat: waiting does not un-stall a server.
|
|
825
|
+
#: Bound on one call, in full: `_STALL_RETRY_MAX` × read timeout + the delay.
|
|
826
|
+
_STALL_RETRY_MAX = 2
|
|
827
|
+
_STALL_RETRY_BASE_S = 2.0
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
def _exception_chain(e: BaseException) -> Iterator[BaseException]:
|
|
831
|
+
"""The exception and what it wraps: Mirascope's `original_exception`, then
|
|
832
|
+
`__cause__`/`__context__`. The SDK raises `APITimeoutError from
|
|
833
|
+
httpx.ReadTimeout` and Mirascope raises its `TimeoutError from` that, so the
|
|
834
|
+
phase that timed out is two links down."""
|
|
835
|
+
seen: set[int] = set()
|
|
836
|
+
pending: list[BaseException | None] = [e]
|
|
837
|
+
while pending:
|
|
838
|
+
current = pending.pop(0)
|
|
839
|
+
if current is None or id(current) in seen or len(seen) >= 10:
|
|
840
|
+
continue
|
|
841
|
+
seen.add(id(current))
|
|
842
|
+
yield current
|
|
843
|
+
pending.append(getattr(current, "original_exception", None))
|
|
844
|
+
pending.append(current.__cause__)
|
|
845
|
+
pending.append(current.__context__)
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
def _is_stall_error(e: Exception) -> bool:
|
|
849
|
+
"""Detect a READ timeout: the request was sent and the provider went quiet.
|
|
850
|
+
|
|
851
|
+
Decided by the httpx phase class in the chain. `ReadTimeout` is a stall;
|
|
852
|
+
`ConnectTimeout`/`WriteTimeout`/`PoolTimeout` are the link, left to
|
|
853
|
+
`_is_connection_error`. A timeout class with no phase in its chain (the
|
|
854
|
+
SDK's `APITimeoutError` or Mirascope's `TimeoutError` raised bare) is read
|
|
855
|
+
as a stall too — the shorter budget is the safe guess.
|
|
856
|
+
"""
|
|
857
|
+
names = [type(x).__name__ for x in _exception_chain(e)]
|
|
858
|
+
if any(name.endswith("ReadTimeout") for name in names):
|
|
859
|
+
return True
|
|
860
|
+
if any(
|
|
861
|
+
name.endswith(("ConnectTimeout", "WriteTimeout", "PoolTimeout"))
|
|
862
|
+
for name in names
|
|
863
|
+
):
|
|
864
|
+
return False
|
|
865
|
+
return any(name in ("APITimeoutError", "TimeoutError") for name in names)
|
|
866
|
+
|
|
867
|
+
|
|
786
868
|
def _is_connection_error(e: Exception) -> bool:
|
|
787
|
-
"""Detect transient network failures worth retrying.
|
|
869
|
+
"""Detect transient network failures worth retrying — a stall excluded.
|
|
788
870
|
|
|
789
871
|
Real failure this catches: the framework's parallel stages
|
|
790
872
|
(ExplorationPipeline, ExploreTransformations) open many connections at once,
|
|
@@ -795,13 +877,18 @@ def _is_connection_error(e: Exception) -> bool:
|
|
|
795
877
|
Matched by class name, not by import: Mirascope re-raises provider
|
|
796
878
|
exceptions as its own `mirascope.llm.exceptions.ConnectionError`/`TimeoutError`,
|
|
797
879
|
and importing those shadows the builtins in this module.
|
|
880
|
+
|
|
881
|
+
Exclusive with `_is_stall_error`, by construction: a read timeout is a
|
|
882
|
+
timeout by class but gets the stall budget, not this curve's three.
|
|
798
883
|
"""
|
|
884
|
+
if _is_stall_error(e):
|
|
885
|
+
return False
|
|
799
886
|
name = type(e).__name__
|
|
800
887
|
if name in ("ConnectionError", "TimeoutError", "APIConnectionError", "APITimeoutError"):
|
|
801
888
|
return True
|
|
802
889
|
# httpx raises distinct classes per phase (ConnectTimeout, ReadTimeout,
|
|
803
890
|
# ConnectError, RemoteProtocolError); the shared suffix is the reliable tell.
|
|
804
|
-
return name.endswith(("ConnectError", "ConnectTimeout"
|
|
891
|
+
return name.endswith(("ConnectError", "ConnectTimeout"))
|
|
805
892
|
|
|
806
893
|
|
|
807
894
|
#: Provider-side transient failures: the request was well-formed and the service
|
|
@@ -898,6 +985,8 @@ def _transient_kind(e: Exception) -> Optional[str]:
|
|
|
898
985
|
return None
|
|
899
986
|
if _is_rate_limit_error(e):
|
|
900
987
|
return "rate_limit"
|
|
988
|
+
if _is_stall_error(e):
|
|
989
|
+
return "stall"
|
|
901
990
|
if _is_connection_error(e):
|
|
902
991
|
return "connection"
|
|
903
992
|
if _is_transient_server_error(e):
|
|
@@ -930,9 +1019,10 @@ async def retry_transient(
|
|
|
930
1019
|
deterministic answer.
|
|
931
1020
|
|
|
932
1021
|
Bounded per kind, with no overall ceiling, so the worst case is not any single
|
|
933
|
-
curve: a failure sequence that keeps CHANGING kind gets each budget in full,
|
|
934
|
-
attempts and ~
|
|
935
|
-
"30s" is the throttle-only
|
|
1022
|
+
curve: a failure sequence that keeps CHANGING kind gets each budget in full, 8
|
|
1023
|
+
attempts and ~53s of sleep before it surfaces (plus a read timeout for the one
|
|
1024
|
+
stalled attempt). Bounded is what matters here, but "30s" is the throttle-only
|
|
1025
|
+
figure and not the promise.
|
|
936
1026
|
|
|
937
1027
|
`operation` must be safe to call again. That is a real precondition and not a
|
|
938
1028
|
formality: the caller re-sends a whole prompt, so it must have no side effects
|
|
@@ -946,6 +1036,7 @@ async def retry_transient(
|
|
|
946
1036
|
"""
|
|
947
1037
|
delay = {
|
|
948
1038
|
"rate_limit": _RATE_LIMIT_BASE_S,
|
|
1039
|
+
"stall": _STALL_RETRY_BASE_S,
|
|
949
1040
|
"connection": _CONNECT_RETRY_BASE_S,
|
|
950
1041
|
"server": _SERVER_RETRY_BASE_S,
|
|
951
1042
|
}
|
|
@@ -960,6 +1051,7 @@ async def retry_transient(
|
|
|
960
1051
|
#: surface as an error instead of spending a throttle-sized budget on it.
|
|
961
1052
|
budget = {
|
|
962
1053
|
"rate_limit": _RATE_LIMIT_RETRY_MAX,
|
|
1054
|
+
"stall": _STALL_RETRY_MAX,
|
|
963
1055
|
"connection": _CONNECT_RETRY_MAX,
|
|
964
1056
|
"server": _SERVER_RETRY_MAX,
|
|
965
1057
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dialectical_framework-2.0.8 → dialectical_framework-2.0.11}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|