flare-kernel 0.2.0__tar.gz → 0.2.2__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.
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/PKG-INFO +6 -1
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/README.md +5 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/pyproject.toml +1 -1
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/contracts/kernel_contract.py +42 -2
- flare_kernel-0.2.2/src/flare_kernel/router/__init__.py +45 -0
- flare_kernel-0.2.2/src/flare_kernel/router/action_payload.py +148 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_analysis.py +53 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_builder.py +82 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_checkpoint.py +102 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_context.py +88 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_context_analysis.py +159 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_context_inputs.py +117 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_context_session.py +90 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_flow.py +258 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_payload.py +190 -0
- flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_projection.py +137 -0
- flare_kernel-0.2.2/src/flare_kernel/router/completion_response_builder.py +139 -0
- flare_kernel-0.2.2/src/flare_kernel/router/completion_selection.py +55 -0
- flare_kernel-0.2.2/src/flare_kernel/router/endpoint_context.py +169 -0
- flare_kernel-0.2.2/src/flare_kernel/router/guided_completion.py +68 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_amount_quantity.py +163 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_answer.py +42 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_authority.py +81 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_authority_checkpoint.py +58 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_authority_hydration.py +126 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_authority_session.py +70 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_canonicalization.py +119 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_clarification.py +122 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_decision_rules.py +148 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_deployment_delivery.py +120 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_entry_policy.py +242 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_extraction.py +84 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_extraction_extractors.py +178 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_extraction_merge.py +85 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_projection.py +78 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_projection_entity.py +107 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_projection_payload.py +89 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_projection_source.py +60 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_scope.py +40 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_confirmed_updates.py +21 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_flags.py +40 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_followup.py +154 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_followup_work_item.py +113 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_open_fields.py +58 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_status.py +84 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_summary.py +26 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_inputs.py +119 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_node_state.py +83 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_numeric.py +126 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_payload_updates.py +109 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_readiness.py +88 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_state_persistence.py +81 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status.py +49 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status_chooser_stage.py +140 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status_guided_session.py +20 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status_projection.py +242 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status_schema.py +192 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_workflow_checkpoint.py +183 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/compat_aliases.py +75 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_classifier_utils.py +72 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_escalation_override.py +83 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_escalation_pipeline.py +95 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_escalation_signal.py +165 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_retrieval.py +101 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_routing.py +146 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/session_intent.py +133 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/session_intent_fields.py +103 -0
- flare_kernel-0.2.2/src/flare_kernel/router/intent/session_intent_small_talk.py +131 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel.py +122 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports.py +18 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/__init__.py +5 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/constants.py +29 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/domain.py +148 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/endpoint.py +50 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/facade.py +21 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/router_flow.py +95 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/runtime.py +30 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_constants.py +55 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_constants_intake.py +30 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_constants_intent.py +153 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_constants_patch.py +32 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_endpoint_handlers.py +29 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_endpoint_handlers_health.py +37 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_endpoint_handlers_knowledge.py +72 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_endpoint_handlers_turn.py +184 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_canonical_state.py +82 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_canonical_wrapper.py +133 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_dependency_resolution.py +272 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_helpers.py +30 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_orchestration.py +119 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_orchestration_wrappers.py +179 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_payload_enrichment.py +75 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_payload_wrapper.py +180 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_turn_context.py +176 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_turn_context_wrapper.py +161 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_utils.py +36 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_intent_query_flow.py +193 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_mode_flow.py +90 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_request_flow.py +754 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_route_action.py +121 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_route_execution.py +115 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_route_run.py +183 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_route_stream.py +149 -0
- flare_kernel-0.2.2/src/flare_kernel/router/kernel_session_intent_flow.py +133 -0
- flare_kernel-0.2.2/src/flare_kernel/router/mode_resolution.py +196 -0
- flare_kernel-0.2.2/src/flare_kernel/router/mode_switch.py +52 -0
- flare_kernel-0.2.2/src/flare_kernel/router/next_actions_guard.py +26 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_checkpoint_state.py +93 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_followup_state.py +77 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_builder.py +116 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_context.py +147 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_context_helpers.py +190 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_decision.py +96 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_projection.py +188 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_result.py +97 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_runtime_state.py +10 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state.py +86 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_context.py +29 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_decision.py +54 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_entry.py +43 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_flow.py +248 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_followup.py +94 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_intent.py +50 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_node.py +60 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_payload.py +96 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_unpack.py +39 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_trace.py +132 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_trace_projection.py +83 -0
- flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_trace_steps.py +139 -0
- flare_kernel-0.2.2/src/flare_kernel/router/patch_contract.py +36 -0
- flare_kernel-0.2.2/src/flare_kernel/router/payload_enrichment.py +235 -0
- flare_kernel-0.2.2/src/flare_kernel/router/prompting.py +98 -0
- flare_kernel-0.2.2/src/flare_kernel/router/request_identity.py +23 -0
- flare_kernel-0.2.2/src/flare_kernel/router/request_intent_resolution.py +68 -0
- flare_kernel-0.2.2/src/flare_kernel/router/retrieval/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_aliases.py +99 -0
- flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_field_queries.py +71 -0
- flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_projection.py +69 -0
- flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_query_builder.py +76 -0
- flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_search.py +47 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_completion.py +121 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_finalize.py +168 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_phase.py +163 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_phase_timing.py +39 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_post_completion.py +107 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_prologue.py +54 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_event_emitter.py +138 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_intake_phase.py +104 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_mode_event_payload.py +78 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_mode_events.py +89 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_bootstrap.py +111 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_builder.py +155 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_builder_transport.py +44 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_phases.py +453 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_runtime.py +90 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_retrieval_phase.py +105 -0
- flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_runtime_steps.py +63 -0
- flare_kernel-0.2.2/src/flare_kernel/router/text_safety.py +94 -0
- flare_kernel-0.2.2/src/flare_kernel/router/turn_context_builder.py +171 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/__init__.py +152 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/domain/__init__.py +1 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/domain}/domain_pack_loader.py +179 -10
- flare_kernel-0.2.2/src/flare_kernel/runtime/domain/profile_resolution.py +126 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/execution/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/infrastructure/__init__.py +1 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/infrastructure}/infrastructure.py +111 -39
- flare_kernel-0.2.2/src/flare_kernel/runtime/intent/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/__init__.py +7 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/decision.py +116 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/lexicon.py +151 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/preprocessing.py +47 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/signals.py +173 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation_classifier.py +82 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/llm/__init__.py +1 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/llm}/llm_provider.py +4 -4
- flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/canvas_sourcing_contract.py +19 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration}/decision_engine.py +107 -45
- flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/mode_orchestration.py +1616 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/mode_runtime.py +220 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/sourcing_event_payloads.py +186 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/__init__.py +1 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning.py +273 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_branching.py +184 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_branching_policy.py +190 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_context.py +256 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_hypothesis.py +211 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_planning.py +708 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_priority.py +127 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_question_extraction.py +191 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_readiness.py +428 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_shared.py +189 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/session/__init__.py +25 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/session/checkpoint_manager.py +360 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/session/intake_session_store.py +363 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/session/models.py +40 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_checkpoint_manager.py +118 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_intake_reasoning.py +747 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_intake_reasoning_split.py +87 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_intake_session_store.py +98 -0
- flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_kernel_runtime.py +735 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel.egg-info/PKG-INFO +6 -1
- flare_kernel-0.2.2/src/flare_kernel.egg-info/SOURCES.txt +349 -0
- flare_kernel-0.2.2/tests/test_action_payload.py +70 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_basics.py +22 -0
- flare_kernel-0.2.2/tests/test_builder_split_modules.py +311 -0
- flare_kernel-0.2.2/tests/test_business_hardcode_guard.py +68 -0
- flare_kernel-0.2.2/tests/test_canonical_state_context_analysis.py +54 -0
- flare_kernel-0.2.2/tests/test_canonical_state_context_inputs.py +27 -0
- flare_kernel-0.2.2/tests/test_canonical_state_context_session.py +49 -0
- flare_kernel-0.2.2/tests/test_canonical_state_flow.py +145 -0
- flare_kernel-0.2.2/tests/test_canonical_state_payload.py +90 -0
- flare_kernel-0.2.2/tests/test_canonical_state_projection.py +100 -0
- flare_kernel-0.2.2/tests/test_canvas_sourcing_contract_meta.py +36 -0
- flare_kernel-0.2.2/tests/test_compat_aliases.py +35 -0
- flare_kernel-0.2.2/tests/test_completion_response_builder.py +111 -0
- flare_kernel-0.2.2/tests/test_completion_selection.py +107 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_decision_engine.py +65 -7
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_domain_pack_loader.py +71 -3
- flare_kernel-0.2.2/tests/test_endpoint_context.py +137 -0
- flare_kernel-0.2.2/tests/test_flare_v1_patch_contract.py +601 -0
- flare_kernel-0.2.2/tests/test_guided_completion.py +37 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_infrastructure_helpers.py +1 -1
- flare_kernel-0.2.2/tests/test_infrastructure_knowledge.py +181 -0
- flare_kernel-0.2.2/tests/test_intake_amount_quantity.py +23 -0
- flare_kernel-0.2.2/tests/test_intake_answer.py +25 -0
- flare_kernel-0.2.2/tests/test_intake_authority.py +159 -0
- flare_kernel-0.2.2/tests/test_intake_authority_checkpoint.py +36 -0
- flare_kernel-0.2.2/tests/test_intake_authority_hydration.py +99 -0
- flare_kernel-0.2.2/tests/test_intake_authority_session.py +58 -0
- flare_kernel-0.2.2/tests/test_intake_canonicalization.py +44 -0
- flare_kernel-0.2.2/tests/test_intake_clarification.py +77 -0
- flare_kernel-0.2.2/tests/test_intake_decision_rules.py +118 -0
- flare_kernel-0.2.2/tests/test_intake_deployment_delivery.py +29 -0
- flare_kernel-0.2.2/tests/test_intake_entry_policy.py +73 -0
- flare_kernel-0.2.2/tests/test_intake_extraction.py +54 -0
- flare_kernel-0.2.2/tests/test_intake_extraction_extractors.py +35 -0
- flare_kernel-0.2.2/tests/test_intake_extraction_merge.py +36 -0
- flare_kernel-0.2.2/tests/test_intake_field_projection.py +69 -0
- flare_kernel-0.2.2/tests/test_intake_field_projection_entity.py +28 -0
- flare_kernel-0.2.2/tests/test_intake_field_projection_payload.py +18 -0
- flare_kernel-0.2.2/tests/test_intake_field_projection_source.py +29 -0
- flare_kernel-0.2.2/tests/test_intake_field_scope.py +20 -0
- flare_kernel-0.2.2/tests/test_intake_guided_confirmed_updates.py +18 -0
- flare_kernel-0.2.2/tests/test_intake_guided_flags.py +14 -0
- flare_kernel-0.2.2/tests/test_intake_guided_followup.py +185 -0
- flare_kernel-0.2.2/tests/test_intake_guided_followup_work_item.py +60 -0
- flare_kernel-0.2.2/tests/test_intake_guided_open_fields.py +27 -0
- flare_kernel-0.2.2/tests/test_intake_guided_status.py +23 -0
- flare_kernel-0.2.2/tests/test_intake_guided_summary.py +11 -0
- flare_kernel-0.2.2/tests/test_intake_inputs.py +85 -0
- flare_kernel-0.2.2/tests/test_intake_node_state.py +73 -0
- flare_kernel-0.2.2/tests/test_intake_numeric.py +26 -0
- flare_kernel-0.2.2/tests/test_intake_payload_updates.py +51 -0
- flare_kernel-0.2.2/tests/test_intake_readiness.py +74 -0
- flare_kernel-0.2.2/tests/test_intake_reasoning_priority.py +109 -0
- flare_kernel-0.2.2/tests/test_intake_state_persistence.py +70 -0
- flare_kernel-0.2.2/tests/test_intake_status.py +303 -0
- flare_kernel-0.2.2/tests/test_intake_status_guided_session.py +95 -0
- flare_kernel-0.2.2/tests/test_intake_status_projection.py +226 -0
- flare_kernel-0.2.2/tests/test_intake_status_schema.py +191 -0
- flare_kernel-0.2.2/tests/test_intake_status_stage.py +64 -0
- flare_kernel-0.2.2/tests/test_intake_workflow_checkpoint.py +23 -0
- flare_kernel-0.2.2/tests/test_intent_classifier_utils.py +44 -0
- flare_kernel-0.2.2/tests/test_intent_escalation_classifier.py +444 -0
- flare_kernel-0.2.2/tests/test_intent_escalation_override.py +65 -0
- flare_kernel-0.2.2/tests/test_intent_escalation_pipeline.py +83 -0
- flare_kernel-0.2.2/tests/test_intent_escalation_signal.py +88 -0
- flare_kernel-0.2.2/tests/test_intent_resolution.py +1745 -0
- flare_kernel-0.2.2/tests/test_intent_retrieval.py +110 -0
- flare_kernel-0.2.2/tests/test_intent_routing.py +106 -0
- flare_kernel-0.2.2/tests/test_intent_type_compat_aliases.py +19 -0
- flare_kernel-0.2.2/tests/test_kernel_alias_delegation.py +22 -0
- flare_kernel-0.2.2/tests/test_kernel_endpoint_handlers.py +218 -0
- flare_kernel-0.2.2/tests/test_kernel_facade_helpers.py +20 -0
- flare_kernel-0.2.2/tests/test_kernel_facade_turn_context.py +60 -0
- flare_kernel-0.2.2/tests/test_kernel_intent_query_flow.py +60 -0
- flare_kernel-0.2.2/tests/test_kernel_mode_flow.py +63 -0
- flare_kernel-0.2.2/tests/test_kernel_route_execution_wrappers.py +97 -0
- flare_kernel-0.2.2/tests/test_kernel_session_intent_flow.py +40 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_llm_provider.py +1 -1
- flare_kernel-0.2.2/tests/test_mode_orchestration_state_bridge.py +83 -0
- flare_kernel-0.2.2/tests/test_mode_resolution.py +169 -0
- flare_kernel-0.2.2/tests/test_mode_switch.py +40 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_model_router.py +1 -1
- flare_kernel-0.2.2/tests/test_new_flow_guard.py +29 -0
- flare_kernel-0.2.2/tests/test_orchestration_checkpoint_state.py +30 -0
- flare_kernel-0.2.2/tests/test_orchestration_followup_state.py +26 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_context.py +94 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_context_helpers.py +57 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_decision.py +71 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_projection.py +240 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_result.py +53 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_runtime_state.py +53 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_state_context.py +25 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_state_decision.py +43 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_state_entry.py +42 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_state_followup.py +64 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_state_intent.py +38 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_state_node.py +53 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_state_payload.py +54 -0
- flare_kernel-0.2.2/tests/test_orchestration_status_state_unpack.py +38 -0
- flare_kernel-0.2.2/tests/test_orchestration_trace.py +146 -0
- flare_kernel-0.2.2/tests/test_orchestration_trace_projection.py +17 -0
- flare_kernel-0.2.2/tests/test_orchestration_trace_steps.py +28 -0
- flare_kernel-0.2.2/tests/test_patch_contract.py +52 -0
- flare_kernel-0.2.2/tests/test_payload_enrichment.py +232 -0
- flare_kernel-0.2.2/tests/test_request_identity.py +24 -0
- flare_kernel-0.2.2/tests/test_request_intent_resolution.py +41 -0
- flare_kernel-0.2.2/tests/test_retrieval_aliases.py +71 -0
- flare_kernel-0.2.2/tests/test_retrieval_field_queries.py +25 -0
- flare_kernel-0.2.2/tests/test_retrieval_projection.py +63 -0
- flare_kernel-0.2.2/tests/test_retrieval_query_builder.py +48 -0
- flare_kernel-0.2.2/tests/test_retrieval_search.py +50 -0
- flare_kernel-0.2.2/tests/test_session_intent.py +98 -0
- flare_kernel-0.2.2/tests/test_session_intent_fields.py +67 -0
- flare_kernel-0.2.2/tests/test_session_intent_small_talk.py +43 -0
- flare_kernel-0.2.2/tests/test_streaming_draft_completion.py +101 -0
- flare_kernel-0.2.2/tests/test_streaming_draft_finalize.py +100 -0
- flare_kernel-0.2.2/tests/test_streaming_draft_phase.py +186 -0
- flare_kernel-0.2.2/tests/test_streaming_draft_post_completion.py +160 -0
- flare_kernel-0.2.2/tests/test_streaming_draft_prologue.py +45 -0
- flare_kernel-0.2.2/tests/test_streaming_event_emitter.py +72 -0
- flare_kernel-0.2.2/tests/test_streaming_intake_phase.py +83 -0
- flare_kernel-0.2.2/tests/test_streaming_mode_event_payload.py +85 -0
- flare_kernel-0.2.2/tests/test_streaming_mode_events.py +63 -0
- flare_kernel-0.2.2/tests/test_streaming_response_bootstrap.py +82 -0
- flare_kernel-0.2.2/tests/test_streaming_response_phases.py +168 -0
- flare_kernel-0.2.2/tests/test_streaming_response_runtime.py +83 -0
- flare_kernel-0.2.2/tests/test_streaming_retrieval_phase.py +69 -0
- flare_kernel-0.2.2/tests/test_streaming_runtime_steps.py +61 -0
- flare_kernel-0.2.2/tests/test_text_safety.py +34 -0
- flare_kernel-0.2.2/tests/test_turn_context_builder.py +116 -0
- flare_kernel-0.2.0/src/flare_kernel/router/__init__.py +0 -5
- flare_kernel-0.2.0/src/flare_kernel/router/kernel.py +0 -2657
- flare_kernel-0.2.0/src/flare_kernel/runtime/__init__.py +0 -79
- flare_kernel-0.2.0/src/flare_kernel/runtime/mode_orchestration.py +0 -760
- flare_kernel-0.2.0/src/flare_kernel/runtime/mode_runtime.py +0 -446
- flare_kernel-0.2.0/src/flare_kernel/runtime/tests/test_kernel_runtime.py +0 -319
- flare_kernel-0.2.0/src/flare_kernel.egg-info/SOURCES.txt +0 -34
- flare_kernel-0.2.0/tests/test_intent_resolution.py +0 -645
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/setup.cfg +0 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/__init__.py +0 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/app.py +0 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/contracts/__init__.py +0 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/main.py +0 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/execution}/agent_runtime.py +0 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/execution}/skill_runtime.py +0 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/infrastructure}/logging.py +0 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/infrastructure}/trace.py +0 -0
- {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/llm}/model_router.py +0 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel.egg-info/dependency_links.txt +0 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel.egg-info/requires.txt +0 -0
- {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flare-kernel
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: FLARE kernel runtime package
|
|
5
5
|
License: Proprietary
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -22,6 +22,11 @@ Requires-Dist: qdrant-client<2,>=1.9
|
|
|
22
22
|
|
|
23
23
|
通用编排与执行内核。
|
|
24
24
|
|
|
25
|
+
边界文档:
|
|
26
|
+
|
|
27
|
+
1. `packages/flare-kernel/docs/KERNEL-BOUNDARY.md`
|
|
28
|
+
2. `docs/contracts/agent-contract-v1.md`
|
|
29
|
+
|
|
25
30
|
职责:
|
|
26
31
|
|
|
27
32
|
1. Decision 路由与策略入口。
|
|
@@ -4,14 +4,48 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Any, Literal
|
|
6
6
|
|
|
7
|
-
from pydantic import BaseModel, Field
|
|
7
|
+
from pydantic import BaseModel, Field, model_validator
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class IntakeFieldValue(BaseModel):
|
|
11
|
+
kind: Literal["single_choice", "multi_choice", "free_text", "number", "range", "candidate_ref"]
|
|
12
|
+
value: Any = None
|
|
13
|
+
display_value: str | None = None
|
|
14
|
+
values: list[Any] | None = None
|
|
15
|
+
text: str | None = None
|
|
16
|
+
number: float | int | None = None
|
|
17
|
+
min: float | int | None = None
|
|
18
|
+
max: float | int | None = None
|
|
19
|
+
unit: str | None = None
|
|
20
|
+
currency: str | None = None
|
|
21
|
+
candidate_id: str | None = None
|
|
22
|
+
|
|
23
|
+
@model_validator(mode="after")
|
|
24
|
+
def validate_shape(self) -> "IntakeFieldValue":
|
|
25
|
+
if self.kind == "single_choice" and self.value in (None, ""):
|
|
26
|
+
raise ValueError("single_choice requires value")
|
|
27
|
+
if self.kind == "multi_choice" and not isinstance(self.values, list):
|
|
28
|
+
raise ValueError("multi_choice requires values[]")
|
|
29
|
+
if self.kind == "free_text" and not str(self.text or "").strip():
|
|
30
|
+
raise ValueError("free_text requires text")
|
|
31
|
+
if self.kind == "number" and self.number is None:
|
|
32
|
+
raise ValueError("number requires number")
|
|
33
|
+
if self.kind == "range" and (self.min is None or self.max is None):
|
|
34
|
+
raise ValueError("range requires min and max")
|
|
35
|
+
if self.kind == "candidate_ref" and not str(self.candidate_id or "").strip():
|
|
36
|
+
raise ValueError("candidate_ref requires candidate_id")
|
|
37
|
+
return self
|
|
8
38
|
|
|
9
39
|
|
|
10
40
|
class KernelRequest(BaseModel):
|
|
41
|
+
contract_version: str = "flare.v1"
|
|
42
|
+
client_request_id: str | None = None
|
|
11
43
|
tenant_id: str = "default"
|
|
12
44
|
instance_id: str = "default"
|
|
13
45
|
domain_pack_version: str = "v1"
|
|
14
|
-
session_id: str =
|
|
46
|
+
session_id: str | None = None
|
|
47
|
+
last_turn_id: str | None = None
|
|
48
|
+
command: str | None = None
|
|
15
49
|
intent: str = "default"
|
|
16
50
|
intent_override: str | None = None
|
|
17
51
|
mode: str | None = None
|
|
@@ -30,6 +64,9 @@ class KernelRequest(BaseModel):
|
|
|
30
64
|
action_status: str | None = None
|
|
31
65
|
action_reason: str | None = None
|
|
32
66
|
trace_id: str | None = None
|
|
67
|
+
question_id: str | None = None
|
|
68
|
+
field_key: str | None = None
|
|
69
|
+
field_value: IntakeFieldValue | None = None
|
|
33
70
|
|
|
34
71
|
|
|
35
72
|
class KernelResponse(BaseModel):
|
|
@@ -71,6 +108,9 @@ class KnowledgeIngestResponse(BaseModel):
|
|
|
71
108
|
chunk_count: int
|
|
72
109
|
status: Literal["stored", "partial", "failed"]
|
|
73
110
|
details: dict[str, Any] = Field(default_factory=dict)
|
|
111
|
+
source_id: str | None = None
|
|
112
|
+
error_code: str | None = None
|
|
113
|
+
error_message: str | None = None
|
|
74
114
|
|
|
75
115
|
|
|
76
116
|
class KnowledgeSearchRequest(BaseModel):
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Kernel routers.
|
|
2
|
+
|
|
3
|
+
This package keeps ``kernel_router`` as the public entrypoint and also provides
|
|
4
|
+
legacy module-name compatibility for recently grouped router modules.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import importlib
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from flare_kernel.router.kernel import router as kernel_router
|
|
13
|
+
|
|
14
|
+
__all__ = ["kernel_router"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _resolve_legacy_group(module_name: str) -> str | None:
|
|
18
|
+
if module_name.startswith("canonical_state_"):
|
|
19
|
+
return "canonical"
|
|
20
|
+
if module_name.startswith("orchestration_"):
|
|
21
|
+
return "orchestration"
|
|
22
|
+
if module_name.startswith("streaming_"):
|
|
23
|
+
return "streaming"
|
|
24
|
+
if module_name.startswith("intake_"):
|
|
25
|
+
return "intake"
|
|
26
|
+
if module_name == "session_intent" or module_name.startswith("session_intent_"):
|
|
27
|
+
return "intent"
|
|
28
|
+
if module_name.startswith("intent_"):
|
|
29
|
+
return "intent"
|
|
30
|
+
if module_name.startswith("retrieval_"):
|
|
31
|
+
return "retrieval"
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def __getattr__(name: str):
|
|
36
|
+
"""Resolve legacy ``flare_kernel.router.<module>`` access to grouped modules."""
|
|
37
|
+
group = _resolve_legacy_group(name)
|
|
38
|
+
if not group:
|
|
39
|
+
raise AttributeError(f"module 'flare_kernel.router' has no attribute {name!r}")
|
|
40
|
+
|
|
41
|
+
target = f"flare_kernel.router.{group}.{name}"
|
|
42
|
+
module = importlib.import_module(target)
|
|
43
|
+
# Register alias so direct imports by the legacy module path also resolve.
|
|
44
|
+
sys.modules.setdefault(f"flare_kernel.router.{name}", module)
|
|
45
|
+
return module
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Action target mode and payload shaping helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import Any, Callable
|
|
7
|
+
|
|
8
|
+
from flare_kernel.contracts import KernelRequest
|
|
9
|
+
|
|
10
|
+
_LEGACY_SOURCING_BASE_FIELDS_ENV = "FLARE_COMPAT_ENABLE_LEGACY_SOURCING_BASE_FIELDS"
|
|
11
|
+
_LEGACY_SOURCING_BASE_FIELDS = ("category", "region")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def resolve_action_target_mode(req: KernelRequest) -> str:
|
|
15
|
+
target_mode = req.target_mode
|
|
16
|
+
if isinstance(target_mode, str):
|
|
17
|
+
normalized = target_mode.strip()
|
|
18
|
+
if normalized in {"requirement_canvas", "intelligent_sourcing", "plan_mode"}:
|
|
19
|
+
return normalized
|
|
20
|
+
|
|
21
|
+
action_key = req.action_key if isinstance(req.action_key, str) else ""
|
|
22
|
+
if action_key == "handoff_to_sourcing":
|
|
23
|
+
return "intelligent_sourcing"
|
|
24
|
+
if action_key == "handoff_to_domain_flow":
|
|
25
|
+
return "intelligent_sourcing"
|
|
26
|
+
if action_key == "continue_collection":
|
|
27
|
+
return "requirement_canvas"
|
|
28
|
+
if action_key == "confirm_plan":
|
|
29
|
+
return "plan_mode"
|
|
30
|
+
if action_key == "confirm_sourcing":
|
|
31
|
+
return "intelligent_sourcing"
|
|
32
|
+
if action_key == "confirm_domain_flow":
|
|
33
|
+
return "intelligent_sourcing"
|
|
34
|
+
|
|
35
|
+
return req.intent if isinstance(req.intent, str) and req.intent.strip() else "default"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _normalize_key(value: Any) -> str:
|
|
39
|
+
if value is None:
|
|
40
|
+
return ""
|
|
41
|
+
return str(value).strip().lower().replace("-", "_").replace(" ", "_")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _extract_value(raw_value: Any) -> Any:
|
|
45
|
+
if isinstance(raw_value, dict):
|
|
46
|
+
for candidate in ("value", "content", "text"):
|
|
47
|
+
candidate_value = raw_value.get(candidate)
|
|
48
|
+
if candidate_value not in (None, "", [], {}):
|
|
49
|
+
return candidate_value
|
|
50
|
+
return raw_value
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _legacy_sourcing_base_fields_enabled() -> bool:
|
|
54
|
+
raw = os.getenv(_LEGACY_SOURCING_BASE_FIELDS_ENV)
|
|
55
|
+
if raw is None:
|
|
56
|
+
return False
|
|
57
|
+
value = raw.strip().lower()
|
|
58
|
+
return value not in {"0", "false", "off", "no"}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _resolve_sourcing_base_field_keys(payload: dict[str, Any]) -> tuple[str, ...]:
|
|
62
|
+
explicit = payload.get("sourcing_base_field_keys")
|
|
63
|
+
if isinstance(explicit, list):
|
|
64
|
+
normalized = [str(item).strip() for item in explicit if str(item).strip()]
|
|
65
|
+
if normalized:
|
|
66
|
+
return tuple(dict.fromkeys(normalized))
|
|
67
|
+
if _legacy_sourcing_base_fields_enabled():
|
|
68
|
+
return _LEGACY_SOURCING_BASE_FIELDS
|
|
69
|
+
return ()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def collect_sourcing_base_fields_from_payload(payload: dict[str, Any]) -> dict[str, Any]:
|
|
73
|
+
base_field_keys = _resolve_sourcing_base_field_keys(payload)
|
|
74
|
+
if not base_field_keys:
|
|
75
|
+
return {}
|
|
76
|
+
|
|
77
|
+
raw_base_fields = payload.get("base_fields")
|
|
78
|
+
if isinstance(raw_base_fields, dict):
|
|
79
|
+
return dict(raw_base_fields)
|
|
80
|
+
|
|
81
|
+
base_fields: dict[str, Any] = {}
|
|
82
|
+
raw_fields = payload.get("fields")
|
|
83
|
+
|
|
84
|
+
if isinstance(raw_fields, dict):
|
|
85
|
+
for key in base_field_keys:
|
|
86
|
+
if key not in raw_fields:
|
|
87
|
+
continue
|
|
88
|
+
value = _extract_value(raw_fields.get(key))
|
|
89
|
+
if value not in (None, "", [], {}):
|
|
90
|
+
base_fields[key] = value
|
|
91
|
+
elif isinstance(raw_fields, list):
|
|
92
|
+
for raw_item in raw_fields:
|
|
93
|
+
if not isinstance(raw_item, dict):
|
|
94
|
+
continue
|
|
95
|
+
field_key = ""
|
|
96
|
+
for candidate in ("field_key", "name", "id", "key", "label"):
|
|
97
|
+
candidate_value = raw_item.get(candidate)
|
|
98
|
+
if isinstance(candidate_value, str) and candidate_value.strip():
|
|
99
|
+
field_key = candidate_value.strip()
|
|
100
|
+
break
|
|
101
|
+
normalized_key = _normalize_key(field_key)
|
|
102
|
+
if normalized_key not in set(base_field_keys):
|
|
103
|
+
continue
|
|
104
|
+
value = _extract_value(raw_item.get("value", raw_item.get("content", raw_item.get("text"))))
|
|
105
|
+
if value not in (None, "", [], {}):
|
|
106
|
+
base_fields[normalized_key] = value
|
|
107
|
+
|
|
108
|
+
for key in base_field_keys:
|
|
109
|
+
if key in base_fields:
|
|
110
|
+
continue
|
|
111
|
+
value = payload.get(key)
|
|
112
|
+
if value not in (None, "", [], {}):
|
|
113
|
+
base_fields[key] = value
|
|
114
|
+
|
|
115
|
+
return base_fields
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def build_action_payload(
|
|
119
|
+
req: KernelRequest,
|
|
120
|
+
target_mode: str,
|
|
121
|
+
*,
|
|
122
|
+
collect_sourcing_base_fields: Callable[[dict[str, Any]], dict[str, Any]] | None = None,
|
|
123
|
+
) -> dict[str, Any]:
|
|
124
|
+
payload = dict(req.payload) if isinstance(req.payload, dict) else {}
|
|
125
|
+
payload["function_type"] = target_mode
|
|
126
|
+
payload["target_mode"] = target_mode
|
|
127
|
+
if isinstance(req.action_key, str) and req.action_key.strip():
|
|
128
|
+
payload["action_key"] = req.action_key.strip()
|
|
129
|
+
if isinstance(req.action_status, str) and req.action_status.strip():
|
|
130
|
+
payload["action_status"] = req.action_status.strip()
|
|
131
|
+
if isinstance(req.action_reason, str) and req.action_reason.strip():
|
|
132
|
+
payload["action_reason"] = req.action_reason.strip()
|
|
133
|
+
if isinstance(req.action_key, str) and req.action_key.strip() == "confirm_sourcing":
|
|
134
|
+
payload["sourcing_confirmed"] = True
|
|
135
|
+
if isinstance(req.retrieval_config, dict) and req.retrieval_config:
|
|
136
|
+
payload["retrieval_config"] = dict(req.retrieval_config)
|
|
137
|
+
if isinstance(req.canvas_config, dict) and req.canvas_config:
|
|
138
|
+
payload["canvas_config"] = dict(req.canvas_config)
|
|
139
|
+
if isinstance(req.plan_config, dict) and req.plan_config:
|
|
140
|
+
payload["plan_config"] = dict(req.plan_config)
|
|
141
|
+
|
|
142
|
+
if target_mode == "intelligent_sourcing":
|
|
143
|
+
collect_fn = collect_sourcing_base_fields or collect_sourcing_base_fields_from_payload
|
|
144
|
+
base_fields = collect_fn(payload)
|
|
145
|
+
if base_fields:
|
|
146
|
+
payload["base_fields"] = base_fields
|
|
147
|
+
|
|
148
|
+
return payload
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Router canonical module group."""
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Analysis/retrieval projection helpers for canonical state."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def apply_analysis_and_retrieval_projection(
|
|
9
|
+
*,
|
|
10
|
+
canonical: dict[str, Any],
|
|
11
|
+
command: str,
|
|
12
|
+
can_generate: bool,
|
|
13
|
+
assistant_text: str,
|
|
14
|
+
normalized_retrieved_knowledge: list[dict[str, Any]],
|
|
15
|
+
) -> None:
|
|
16
|
+
if command == "generate_analysis" and can_generate and assistant_text:
|
|
17
|
+
canonical["analysis"]["sections"].append({"id": "analysis", "title": "需求分析", "content": assistant_text})
|
|
18
|
+
if command == "generate_analysis" and normalized_retrieved_knowledge:
|
|
19
|
+
evidence_rows = normalized_retrieved_knowledge[:3]
|
|
20
|
+
evidence_titles = [str(item.get("title") or item.get("candidate_value") or item.get("snippet") or "证据") for item in evidence_rows]
|
|
21
|
+
evidence_summary = f"检索到 {len(normalized_retrieved_knowledge)} 条证据"
|
|
22
|
+
if evidence_titles:
|
|
23
|
+
evidence_summary = f"{evidence_summary},重点参考:{';'.join(evidence_titles[:3])}"
|
|
24
|
+
canonical["analysis"]["sections"].append(
|
|
25
|
+
{
|
|
26
|
+
"id": "evidence",
|
|
27
|
+
"title": "检索证据",
|
|
28
|
+
"content": evidence_summary,
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
if not normalized_retrieved_knowledge:
|
|
32
|
+
return
|
|
33
|
+
comparison_rows: list[dict[str, Any]] = []
|
|
34
|
+
for item in normalized_retrieved_knowledge[:3]:
|
|
35
|
+
comparison_rows.append(
|
|
36
|
+
{
|
|
37
|
+
"record_id": item.get("record_id"),
|
|
38
|
+
"chunk_id": item.get("chunk_id"),
|
|
39
|
+
"title": str(item.get("title") or item.get("candidate_value") or "证据条目"),
|
|
40
|
+
"source": str(item.get("source") or item.get("source_type") or "local"),
|
|
41
|
+
"score": item.get("score"),
|
|
42
|
+
"snippet": str(item.get("snippet") or item.get("content") or "")[:220],
|
|
43
|
+
"matched_field": str(item.get("matched_field") or ""),
|
|
44
|
+
"candidate_value": str(item.get("candidate_value") or ""),
|
|
45
|
+
"confidence": item.get("confidence"),
|
|
46
|
+
"why_relevant": str(item.get("why_relevant") or ""),
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
canonical["capabilities"]["field_retrieval"]["comparison_rows"] = comparison_rows
|
|
50
|
+
canonical["capabilities"]["field_retrieval"]["recommendation_summary"] = (
|
|
51
|
+
f"已检索到 {len(normalized_retrieved_knowledge)} 条候选证据,优先查看 "
|
|
52
|
+
+ ";".join(str(item.get("title") or item.get("candidate_value") or "证据条目") for item in comparison_rows)
|
|
53
|
+
)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Canonical state projection builder for router responses."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Callable
|
|
6
|
+
|
|
7
|
+
from flare_kernel.contracts import KernelRequest
|
|
8
|
+
from flare_kernel.router.canonical.canonical_state_context import (
|
|
9
|
+
resolve_canonical_state_context,
|
|
10
|
+
)
|
|
11
|
+
from flare_kernel.router.canonical.canonical_state_payload import (
|
|
12
|
+
build_canonical_payload,
|
|
13
|
+
)
|
|
14
|
+
from flare_kernel.router.canonical.canonical_state_projection import (
|
|
15
|
+
apply_analysis_and_retrieval_projection,
|
|
16
|
+
normalize_retrieved_knowledge,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def build_canonical_state(
|
|
21
|
+
*,
|
|
22
|
+
req: KernelRequest,
|
|
23
|
+
command: str,
|
|
24
|
+
resolved_intent: str,
|
|
25
|
+
resolved_mode: str,
|
|
26
|
+
mode_source: str,
|
|
27
|
+
orchestration_status: dict[str, Any],
|
|
28
|
+
runtime_snapshot: dict[str, Any],
|
|
29
|
+
assistant_text: str,
|
|
30
|
+
provider_status: str,
|
|
31
|
+
structured_retrieved_knowledge: list[dict[str, Any]] | None = None,
|
|
32
|
+
map_external_mode_fn: Callable[[str], str],
|
|
33
|
+
resolve_session_intent_stage_fn: Callable[..., str],
|
|
34
|
+
coerce_intent_escalation_policy_fn: Callable[[Any], dict[str, Any]],
|
|
35
|
+
normalize_stage_status_fn: Callable[..., tuple[str, str]],
|
|
36
|
+
build_confirmed_fields_schema_fn: Callable[[dict[str, Any], dict[str, Any]], dict[str, Any]],
|
|
37
|
+
build_missing_fields_schema_fn: Callable[[list[str]], dict[str, Any]],
|
|
38
|
+
is_field_entity_confirmed_fn: Callable[[Any], bool],
|
|
39
|
+
extract_user_message_fn: Callable[[dict[str, Any] | None], str],
|
|
40
|
+
normalize_intake_session_id_fn: Callable[[Any], str],
|
|
41
|
+
resolve_trace_id_fn: Callable[[str | None], str],
|
|
42
|
+
safe_session_id_fn: Callable[[Any], str],
|
|
43
|
+
) -> dict[str, Any]:
|
|
44
|
+
_ = runtime_snapshot
|
|
45
|
+
normalized_retrieved_knowledge = normalize_retrieved_knowledge(structured_retrieved_knowledge)
|
|
46
|
+
canonical_context = resolve_canonical_state_context(
|
|
47
|
+
req=req,
|
|
48
|
+
command=command,
|
|
49
|
+
resolved_intent=resolved_intent,
|
|
50
|
+
resolved_mode=resolved_mode,
|
|
51
|
+
mode_source=mode_source,
|
|
52
|
+
orchestration_status=orchestration_status,
|
|
53
|
+
assistant_text=assistant_text,
|
|
54
|
+
map_external_mode_fn=map_external_mode_fn,
|
|
55
|
+
resolve_session_intent_stage_fn=resolve_session_intent_stage_fn,
|
|
56
|
+
coerce_intent_escalation_policy_fn=coerce_intent_escalation_policy_fn,
|
|
57
|
+
normalize_stage_status_fn=normalize_stage_status_fn,
|
|
58
|
+
is_field_entity_confirmed_fn=is_field_entity_confirmed_fn,
|
|
59
|
+
extract_user_message_fn=extract_user_message_fn,
|
|
60
|
+
normalize_intake_session_id_fn=normalize_intake_session_id_fn,
|
|
61
|
+
)
|
|
62
|
+
canonical = build_canonical_payload(
|
|
63
|
+
req=req,
|
|
64
|
+
command=command,
|
|
65
|
+
mode_source=mode_source,
|
|
66
|
+
orchestration_status=orchestration_status,
|
|
67
|
+
assistant_text=assistant_text,
|
|
68
|
+
provider_status=provider_status,
|
|
69
|
+
canonical_context=canonical_context,
|
|
70
|
+
build_confirmed_fields_schema_fn=build_confirmed_fields_schema_fn,
|
|
71
|
+
build_missing_fields_schema_fn=build_missing_fields_schema_fn,
|
|
72
|
+
resolve_trace_id_fn=resolve_trace_id_fn,
|
|
73
|
+
safe_session_id_fn=safe_session_id_fn,
|
|
74
|
+
)
|
|
75
|
+
apply_analysis_and_retrieval_projection(
|
|
76
|
+
canonical=canonical,
|
|
77
|
+
command=command,
|
|
78
|
+
can_generate=bool(canonical_context.get("can_generate")),
|
|
79
|
+
assistant_text=assistant_text,
|
|
80
|
+
normalized_retrieved_knowledge=normalized_retrieved_knowledge,
|
|
81
|
+
)
|
|
82
|
+
return canonical
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Checkpoint projection helpers for canonical state."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def build_checkpoint_projection(
|
|
9
|
+
*,
|
|
10
|
+
orchestration_status: dict[str, Any],
|
|
11
|
+
intake_session_id: str,
|
|
12
|
+
status_key: str,
|
|
13
|
+
current_question: dict[str, Any] | None,
|
|
14
|
+
fields: dict[str, str],
|
|
15
|
+
required_missing: list[str],
|
|
16
|
+
session_id: str,
|
|
17
|
+
activated_mode: str,
|
|
18
|
+
) -> dict[str, Any]:
|
|
19
|
+
raw_checkpoint = (
|
|
20
|
+
orchestration_status.get("checkpoint")
|
|
21
|
+
if isinstance(orchestration_status.get("checkpoint"), dict)
|
|
22
|
+
else {}
|
|
23
|
+
)
|
|
24
|
+
try:
|
|
25
|
+
checkpoint_version = int(raw_checkpoint.get("version") or 1)
|
|
26
|
+
except (TypeError, ValueError):
|
|
27
|
+
checkpoint_version = 1
|
|
28
|
+
checkpoint = {
|
|
29
|
+
"checkpoint_id": str(raw_checkpoint.get("checkpoint_id") or "").strip(),
|
|
30
|
+
"intake_session_id": str(raw_checkpoint.get("intake_session_id") or intake_session_id or "").strip(),
|
|
31
|
+
"checkpoint_type": str(raw_checkpoint.get("checkpoint_type") or "").strip(),
|
|
32
|
+
"checkpoint_state": str(raw_checkpoint.get("checkpoint_state") or "").strip(),
|
|
33
|
+
"current_stage": str(raw_checkpoint.get("current_stage") or "").strip(),
|
|
34
|
+
"question_key": str(raw_checkpoint.get("question_key") or "").strip(),
|
|
35
|
+
"ready_for_submit": bool(raw_checkpoint.get("ready_for_submit")),
|
|
36
|
+
"decision_point_active": bool(raw_checkpoint.get("decision_point_active")),
|
|
37
|
+
"updated_at": str(raw_checkpoint.get("updated_at") or "").strip(),
|
|
38
|
+
"waiting_user": bool(
|
|
39
|
+
orchestration_status.get("checkpoint_waiting_user") is True
|
|
40
|
+
or str(raw_checkpoint.get("checkpoint_state") or "").strip().lower() == "waiting_user"
|
|
41
|
+
),
|
|
42
|
+
"workflow_id": str(raw_checkpoint.get("workflow_id") or "").strip(),
|
|
43
|
+
"session_id": str(raw_checkpoint.get("session_id") or session_id or "").strip(),
|
|
44
|
+
"mode": str(raw_checkpoint.get("mode") or activated_mode or "").strip(),
|
|
45
|
+
"status": str(raw_checkpoint.get("status") or "").strip(),
|
|
46
|
+
"active_checkpoint_id": str(raw_checkpoint.get("active_checkpoint_id") or raw_checkpoint.get("checkpoint_id") or "").strip(),
|
|
47
|
+
"version": max(1, checkpoint_version),
|
|
48
|
+
"checkpoints": (
|
|
49
|
+
[item for item in raw_checkpoint.get("checkpoints") if isinstance(item, dict)]
|
|
50
|
+
if isinstance(raw_checkpoint.get("checkpoints"), list)
|
|
51
|
+
else []
|
|
52
|
+
),
|
|
53
|
+
}
|
|
54
|
+
if not checkpoint["workflow_id"] and checkpoint["intake_session_id"]:
|
|
55
|
+
checkpoint["workflow_id"] = f"wf_{checkpoint['intake_session_id']}"
|
|
56
|
+
if not checkpoint["status"]:
|
|
57
|
+
if status_key == "ready_for_submit":
|
|
58
|
+
checkpoint["status"] = "succeeded"
|
|
59
|
+
elif status_key in {"collecting", "blocked"}:
|
|
60
|
+
checkpoint["status"] = "waiting_user"
|
|
61
|
+
else:
|
|
62
|
+
checkpoint["status"] = "queued"
|
|
63
|
+
if not checkpoint["checkpoints"] and checkpoint["checkpoint_id"]:
|
|
64
|
+
current_question_text = ""
|
|
65
|
+
current_question_field = ""
|
|
66
|
+
if isinstance(current_question, dict):
|
|
67
|
+
current_question_text = str(current_question.get("question_text") or "").strip()
|
|
68
|
+
current_question_field = str(current_question.get("field_key") or "").strip()
|
|
69
|
+
checkpoint["checkpoints"] = [
|
|
70
|
+
{
|
|
71
|
+
"checkpoint_id": checkpoint["checkpoint_id"],
|
|
72
|
+
"seq": 1,
|
|
73
|
+
"title": "需求梳理",
|
|
74
|
+
"stage": "clarification" if status_key in {"collecting", "blocked"} else "intake",
|
|
75
|
+
"status": checkpoint["status"],
|
|
76
|
+
"question": (
|
|
77
|
+
{
|
|
78
|
+
"question_id": f"question::{current_question_field}" if current_question_field else "",
|
|
79
|
+
"text": current_question_text,
|
|
80
|
+
"target_fields": [current_question_field] if current_question_field else [],
|
|
81
|
+
}
|
|
82
|
+
if current_question_text or current_question_field
|
|
83
|
+
else None
|
|
84
|
+
),
|
|
85
|
+
"confirmed_fields": [
|
|
86
|
+
{
|
|
87
|
+
"field_key": field_key,
|
|
88
|
+
"display_value": field_value,
|
|
89
|
+
"confidence": 0.85,
|
|
90
|
+
}
|
|
91
|
+
for field_key, field_value in fields.items()
|
|
92
|
+
],
|
|
93
|
+
"missing_fields": [
|
|
94
|
+
{"field_key": field_key, "reason": "required_missing", "blocks": True}
|
|
95
|
+
for field_key in required_missing
|
|
96
|
+
],
|
|
97
|
+
"child_tasks": [],
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
if not checkpoint["checkpoint_id"]:
|
|
101
|
+
return {}
|
|
102
|
+
return checkpoint
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Facade for canonical state context assembly.
|
|
2
|
+
|
|
3
|
+
This module keeps the public entrypoint stable while delegating the work into
|
|
4
|
+
three readable stages:
|
|
5
|
+
1. normalize the incoming context inputs
|
|
6
|
+
2. derive session-scoped context material
|
|
7
|
+
3. assemble the canonical output consumed by the state builder
|
|
8
|
+
|
|
9
|
+
The contract assumption is that each helper is pure with respect to the input
|
|
10
|
+
payloads it receives; this facade only wires the stage outputs together.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Any, Callable
|
|
16
|
+
|
|
17
|
+
from flare_kernel.contracts import KernelRequest
|
|
18
|
+
from flare_kernel.router.canonical.canonical_state_context_analysis import (
|
|
19
|
+
build_canonical_state_context_output,
|
|
20
|
+
)
|
|
21
|
+
from flare_kernel.router.canonical.canonical_state_context_inputs import (
|
|
22
|
+
resolve_canonical_state_context_inputs,
|
|
23
|
+
)
|
|
24
|
+
from flare_kernel.router.canonical.canonical_state_context_session import (
|
|
25
|
+
resolve_canonical_state_context_session,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def resolve_canonical_state_context(
|
|
30
|
+
*,
|
|
31
|
+
req: KernelRequest,
|
|
32
|
+
command: str,
|
|
33
|
+
resolved_intent: str,
|
|
34
|
+
resolved_mode: str,
|
|
35
|
+
mode_source: str,
|
|
36
|
+
orchestration_status: dict[str, Any],
|
|
37
|
+
assistant_text: str,
|
|
38
|
+
map_external_mode_fn: Callable[[str], str],
|
|
39
|
+
resolve_session_intent_stage_fn: Callable[..., str],
|
|
40
|
+
coerce_intent_escalation_policy_fn: Callable[[Any], dict[str, Any]],
|
|
41
|
+
normalize_stage_status_fn: Callable[..., tuple[str, str]],
|
|
42
|
+
is_field_entity_confirmed_fn: Callable[[Any], bool],
|
|
43
|
+
extract_user_message_fn: Callable[[dict[str, Any] | None], str],
|
|
44
|
+
normalize_intake_session_id_fn: Callable[[Any], str],
|
|
45
|
+
) -> dict[str, Any]:
|
|
46
|
+
"""Resolve the canonical context used by the canonical state builder.
|
|
47
|
+
|
|
48
|
+
The function is intentionally thin: it does not infer policy, only
|
|
49
|
+
sequences the normalization, session resolution, and output assembly
|
|
50
|
+
stages so downstream callers can treat the result as a canonical snapshot.
|
|
51
|
+
"""
|
|
52
|
+
# Stage 1: normalize the raw request and orchestration inputs into a
|
|
53
|
+
# compact context bundle that subsequent helpers can consume consistently.
|
|
54
|
+
context_inputs = resolve_canonical_state_context_inputs(
|
|
55
|
+
resolved_intent=resolved_intent,
|
|
56
|
+
resolved_mode=resolved_mode,
|
|
57
|
+
orchestration_status=orchestration_status,
|
|
58
|
+
map_external_mode_fn=map_external_mode_fn,
|
|
59
|
+
is_field_entity_confirmed_fn=is_field_entity_confirmed_fn,
|
|
60
|
+
)
|
|
61
|
+
# Stage 2: resolve the session-scoped fields that depend on the normalized
|
|
62
|
+
# context and request/session metadata.
|
|
63
|
+
context_session = resolve_canonical_state_context_session(
|
|
64
|
+
req=req,
|
|
65
|
+
command=command,
|
|
66
|
+
resolved_intent=resolved_intent,
|
|
67
|
+
mode_source=mode_source,
|
|
68
|
+
orchestration_status=orchestration_status,
|
|
69
|
+
assistant_text=assistant_text,
|
|
70
|
+
context_inputs=context_inputs,
|
|
71
|
+
map_external_mode_fn=map_external_mode_fn,
|
|
72
|
+
resolve_session_intent_stage_fn=resolve_session_intent_stage_fn,
|
|
73
|
+
coerce_intent_escalation_policy_fn=coerce_intent_escalation_policy_fn,
|
|
74
|
+
normalize_stage_status_fn=normalize_stage_status_fn,
|
|
75
|
+
extract_user_message_fn=extract_user_message_fn,
|
|
76
|
+
normalize_intake_session_id_fn=normalize_intake_session_id_fn,
|
|
77
|
+
)
|
|
78
|
+
# Stage 3: assemble the final canonical payload that the state builder
|
|
79
|
+
# consumes without having to re-run any normalization logic.
|
|
80
|
+
return build_canonical_state_context_output(
|
|
81
|
+
req=req,
|
|
82
|
+
command=command,
|
|
83
|
+
orchestration_status=orchestration_status,
|
|
84
|
+
assistant_text=assistant_text,
|
|
85
|
+
context_inputs=context_inputs,
|
|
86
|
+
context_session=context_session,
|
|
87
|
+
map_external_mode_fn=map_external_mode_fn,
|
|
88
|
+
)
|