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.
Files changed (359) hide show
  1. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/PKG-INFO +6 -1
  2. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/README.md +5 -0
  3. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/pyproject.toml +1 -1
  4. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/contracts/kernel_contract.py +42 -2
  5. flare_kernel-0.2.2/src/flare_kernel/router/__init__.py +45 -0
  6. flare_kernel-0.2.2/src/flare_kernel/router/action_payload.py +148 -0
  7. flare_kernel-0.2.2/src/flare_kernel/router/canonical/__init__.py +1 -0
  8. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_analysis.py +53 -0
  9. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_builder.py +82 -0
  10. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_checkpoint.py +102 -0
  11. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_context.py +88 -0
  12. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_context_analysis.py +159 -0
  13. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_context_inputs.py +117 -0
  14. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_context_session.py +90 -0
  15. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_flow.py +258 -0
  16. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_payload.py +190 -0
  17. flare_kernel-0.2.2/src/flare_kernel/router/canonical/canonical_state_projection.py +137 -0
  18. flare_kernel-0.2.2/src/flare_kernel/router/completion_response_builder.py +139 -0
  19. flare_kernel-0.2.2/src/flare_kernel/router/completion_selection.py +55 -0
  20. flare_kernel-0.2.2/src/flare_kernel/router/endpoint_context.py +169 -0
  21. flare_kernel-0.2.2/src/flare_kernel/router/guided_completion.py +68 -0
  22. flare_kernel-0.2.2/src/flare_kernel/router/intake/__init__.py +1 -0
  23. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_amount_quantity.py +163 -0
  24. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_answer.py +42 -0
  25. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_authority.py +81 -0
  26. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_authority_checkpoint.py +58 -0
  27. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_authority_hydration.py +126 -0
  28. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_authority_session.py +70 -0
  29. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_canonicalization.py +119 -0
  30. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_clarification.py +122 -0
  31. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_decision_rules.py +148 -0
  32. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_deployment_delivery.py +120 -0
  33. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_entry_policy.py +242 -0
  34. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_extraction.py +84 -0
  35. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_extraction_extractors.py +178 -0
  36. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_extraction_merge.py +85 -0
  37. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_projection.py +78 -0
  38. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_projection_entity.py +107 -0
  39. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_projection_payload.py +89 -0
  40. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_projection_source.py +60 -0
  41. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_field_scope.py +40 -0
  42. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_confirmed_updates.py +21 -0
  43. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_flags.py +40 -0
  44. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_followup.py +154 -0
  45. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_followup_work_item.py +113 -0
  46. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_open_fields.py +58 -0
  47. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_status.py +84 -0
  48. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_guided_summary.py +26 -0
  49. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_inputs.py +119 -0
  50. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_node_state.py +83 -0
  51. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_numeric.py +126 -0
  52. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_payload_updates.py +109 -0
  53. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_readiness.py +88 -0
  54. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_state_persistence.py +81 -0
  55. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status.py +49 -0
  56. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status_chooser_stage.py +140 -0
  57. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status_guided_session.py +20 -0
  58. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status_projection.py +242 -0
  59. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_status_schema.py +192 -0
  60. flare_kernel-0.2.2/src/flare_kernel/router/intake/intake_workflow_checkpoint.py +183 -0
  61. flare_kernel-0.2.2/src/flare_kernel/router/intent/__init__.py +1 -0
  62. flare_kernel-0.2.2/src/flare_kernel/router/intent/compat_aliases.py +75 -0
  63. flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_classifier_utils.py +72 -0
  64. flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_escalation_override.py +83 -0
  65. flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_escalation_pipeline.py +95 -0
  66. flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_escalation_signal.py +165 -0
  67. flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_retrieval.py +101 -0
  68. flare_kernel-0.2.2/src/flare_kernel/router/intent/intent_routing.py +146 -0
  69. flare_kernel-0.2.2/src/flare_kernel/router/intent/session_intent.py +133 -0
  70. flare_kernel-0.2.2/src/flare_kernel/router/intent/session_intent_fields.py +103 -0
  71. flare_kernel-0.2.2/src/flare_kernel/router/intent/session_intent_small_talk.py +131 -0
  72. flare_kernel-0.2.2/src/flare_kernel/router/kernel.py +122 -0
  73. flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports.py +18 -0
  74. flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/__init__.py +5 -0
  75. flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/constants.py +29 -0
  76. flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/domain.py +148 -0
  77. flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/endpoint.py +50 -0
  78. flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/facade.py +21 -0
  79. flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/router_flow.py +95 -0
  80. flare_kernel-0.2.2/src/flare_kernel/router/kernel_compat_exports_parts/runtime.py +30 -0
  81. flare_kernel-0.2.2/src/flare_kernel/router/kernel_constants.py +55 -0
  82. flare_kernel-0.2.2/src/flare_kernel/router/kernel_constants_intake.py +30 -0
  83. flare_kernel-0.2.2/src/flare_kernel/router/kernel_constants_intent.py +153 -0
  84. flare_kernel-0.2.2/src/flare_kernel/router/kernel_constants_patch.py +32 -0
  85. flare_kernel-0.2.2/src/flare_kernel/router/kernel_endpoint_handlers.py +29 -0
  86. flare_kernel-0.2.2/src/flare_kernel/router/kernel_endpoint_handlers_health.py +37 -0
  87. flare_kernel-0.2.2/src/flare_kernel/router/kernel_endpoint_handlers_knowledge.py +72 -0
  88. flare_kernel-0.2.2/src/flare_kernel/router/kernel_endpoint_handlers_turn.py +184 -0
  89. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_canonical_state.py +82 -0
  90. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_canonical_wrapper.py +133 -0
  91. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_dependency_resolution.py +272 -0
  92. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_helpers.py +30 -0
  93. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_orchestration.py +119 -0
  94. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_orchestration_wrappers.py +179 -0
  95. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_payload_enrichment.py +75 -0
  96. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_payload_wrapper.py +180 -0
  97. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_turn_context.py +176 -0
  98. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_turn_context_wrapper.py +161 -0
  99. flare_kernel-0.2.2/src/flare_kernel/router/kernel_facade_utils.py +36 -0
  100. flare_kernel-0.2.2/src/flare_kernel/router/kernel_intent_query_flow.py +193 -0
  101. flare_kernel-0.2.2/src/flare_kernel/router/kernel_mode_flow.py +90 -0
  102. flare_kernel-0.2.2/src/flare_kernel/router/kernel_request_flow.py +754 -0
  103. flare_kernel-0.2.2/src/flare_kernel/router/kernel_route_action.py +121 -0
  104. flare_kernel-0.2.2/src/flare_kernel/router/kernel_route_execution.py +115 -0
  105. flare_kernel-0.2.2/src/flare_kernel/router/kernel_route_run.py +183 -0
  106. flare_kernel-0.2.2/src/flare_kernel/router/kernel_route_stream.py +149 -0
  107. flare_kernel-0.2.2/src/flare_kernel/router/kernel_session_intent_flow.py +133 -0
  108. flare_kernel-0.2.2/src/flare_kernel/router/mode_resolution.py +196 -0
  109. flare_kernel-0.2.2/src/flare_kernel/router/mode_switch.py +52 -0
  110. flare_kernel-0.2.2/src/flare_kernel/router/next_actions_guard.py +26 -0
  111. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/__init__.py +1 -0
  112. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_checkpoint_state.py +93 -0
  113. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_followup_state.py +77 -0
  114. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_builder.py +116 -0
  115. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_context.py +147 -0
  116. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_context_helpers.py +190 -0
  117. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_decision.py +96 -0
  118. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_projection.py +188 -0
  119. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_result.py +97 -0
  120. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_runtime_state.py +10 -0
  121. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state.py +86 -0
  122. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_context.py +29 -0
  123. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_decision.py +54 -0
  124. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_entry.py +43 -0
  125. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_flow.py +248 -0
  126. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_followup.py +94 -0
  127. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_intent.py +50 -0
  128. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_node.py +60 -0
  129. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_payload.py +96 -0
  130. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_status_state_unpack.py +39 -0
  131. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_trace.py +132 -0
  132. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_trace_projection.py +83 -0
  133. flare_kernel-0.2.2/src/flare_kernel/router/orchestration/orchestration_trace_steps.py +139 -0
  134. flare_kernel-0.2.2/src/flare_kernel/router/patch_contract.py +36 -0
  135. flare_kernel-0.2.2/src/flare_kernel/router/payload_enrichment.py +235 -0
  136. flare_kernel-0.2.2/src/flare_kernel/router/prompting.py +98 -0
  137. flare_kernel-0.2.2/src/flare_kernel/router/request_identity.py +23 -0
  138. flare_kernel-0.2.2/src/flare_kernel/router/request_intent_resolution.py +68 -0
  139. flare_kernel-0.2.2/src/flare_kernel/router/retrieval/__init__.py +1 -0
  140. flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_aliases.py +99 -0
  141. flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_field_queries.py +71 -0
  142. flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_projection.py +69 -0
  143. flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_query_builder.py +76 -0
  144. flare_kernel-0.2.2/src/flare_kernel/router/retrieval/retrieval_search.py +47 -0
  145. flare_kernel-0.2.2/src/flare_kernel/router/streaming/__init__.py +1 -0
  146. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_completion.py +121 -0
  147. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_finalize.py +168 -0
  148. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_phase.py +163 -0
  149. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_phase_timing.py +39 -0
  150. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_post_completion.py +107 -0
  151. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_draft_prologue.py +54 -0
  152. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_event_emitter.py +138 -0
  153. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_intake_phase.py +104 -0
  154. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_mode_event_payload.py +78 -0
  155. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_mode_events.py +89 -0
  156. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_bootstrap.py +111 -0
  157. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_builder.py +155 -0
  158. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_builder_transport.py +44 -0
  159. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_phases.py +453 -0
  160. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_response_runtime.py +90 -0
  161. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_retrieval_phase.py +105 -0
  162. flare_kernel-0.2.2/src/flare_kernel/router/streaming/streaming_runtime_steps.py +63 -0
  163. flare_kernel-0.2.2/src/flare_kernel/router/text_safety.py +94 -0
  164. flare_kernel-0.2.2/src/flare_kernel/router/turn_context_builder.py +171 -0
  165. flare_kernel-0.2.2/src/flare_kernel/runtime/__init__.py +152 -0
  166. flare_kernel-0.2.2/src/flare_kernel/runtime/domain/__init__.py +1 -0
  167. {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
  168. flare_kernel-0.2.2/src/flare_kernel/runtime/domain/profile_resolution.py +126 -0
  169. flare_kernel-0.2.2/src/flare_kernel/runtime/execution/__init__.py +1 -0
  170. flare_kernel-0.2.2/src/flare_kernel/runtime/infrastructure/__init__.py +1 -0
  171. {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/infrastructure}/infrastructure.py +111 -39
  172. flare_kernel-0.2.2/src/flare_kernel/runtime/intent/__init__.py +1 -0
  173. flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/__init__.py +7 -0
  174. flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/decision.py +116 -0
  175. flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/lexicon.py +151 -0
  176. flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/preprocessing.py +47 -0
  177. flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation/signals.py +173 -0
  178. flare_kernel-0.2.2/src/flare_kernel/runtime/intent/intent_and_escalation_classifier.py +82 -0
  179. flare_kernel-0.2.2/src/flare_kernel/runtime/llm/__init__.py +1 -0
  180. {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/llm}/llm_provider.py +4 -4
  181. flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/__init__.py +1 -0
  182. flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/canvas_sourcing_contract.py +19 -0
  183. {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration}/decision_engine.py +107 -45
  184. flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/mode_orchestration.py +1616 -0
  185. flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/mode_runtime.py +220 -0
  186. flare_kernel-0.2.2/src/flare_kernel/runtime/orchestration/sourcing_event_payloads.py +186 -0
  187. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/__init__.py +1 -0
  188. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning.py +273 -0
  189. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_branching.py +184 -0
  190. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_branching_policy.py +190 -0
  191. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_context.py +256 -0
  192. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_hypothesis.py +211 -0
  193. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_planning.py +708 -0
  194. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_priority.py +127 -0
  195. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_question_extraction.py +191 -0
  196. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_readiness.py +428 -0
  197. flare_kernel-0.2.2/src/flare_kernel/runtime/reasoning/intake_reasoning_shared.py +189 -0
  198. flare_kernel-0.2.2/src/flare_kernel/runtime/session/__init__.py +25 -0
  199. flare_kernel-0.2.2/src/flare_kernel/runtime/session/checkpoint_manager.py +360 -0
  200. flare_kernel-0.2.2/src/flare_kernel/runtime/session/intake_session_store.py +363 -0
  201. flare_kernel-0.2.2/src/flare_kernel/runtime/session/models.py +40 -0
  202. flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_checkpoint_manager.py +118 -0
  203. flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_intake_reasoning.py +747 -0
  204. flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_intake_reasoning_split.py +87 -0
  205. flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_intake_session_store.py +98 -0
  206. flare_kernel-0.2.2/src/flare_kernel/runtime/tests/test_kernel_runtime.py +735 -0
  207. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel.egg-info/PKG-INFO +6 -1
  208. flare_kernel-0.2.2/src/flare_kernel.egg-info/SOURCES.txt +349 -0
  209. flare_kernel-0.2.2/tests/test_action_payload.py +70 -0
  210. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_basics.py +22 -0
  211. flare_kernel-0.2.2/tests/test_builder_split_modules.py +311 -0
  212. flare_kernel-0.2.2/tests/test_business_hardcode_guard.py +68 -0
  213. flare_kernel-0.2.2/tests/test_canonical_state_context_analysis.py +54 -0
  214. flare_kernel-0.2.2/tests/test_canonical_state_context_inputs.py +27 -0
  215. flare_kernel-0.2.2/tests/test_canonical_state_context_session.py +49 -0
  216. flare_kernel-0.2.2/tests/test_canonical_state_flow.py +145 -0
  217. flare_kernel-0.2.2/tests/test_canonical_state_payload.py +90 -0
  218. flare_kernel-0.2.2/tests/test_canonical_state_projection.py +100 -0
  219. flare_kernel-0.2.2/tests/test_canvas_sourcing_contract_meta.py +36 -0
  220. flare_kernel-0.2.2/tests/test_compat_aliases.py +35 -0
  221. flare_kernel-0.2.2/tests/test_completion_response_builder.py +111 -0
  222. flare_kernel-0.2.2/tests/test_completion_selection.py +107 -0
  223. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_decision_engine.py +65 -7
  224. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_domain_pack_loader.py +71 -3
  225. flare_kernel-0.2.2/tests/test_endpoint_context.py +137 -0
  226. flare_kernel-0.2.2/tests/test_flare_v1_patch_contract.py +601 -0
  227. flare_kernel-0.2.2/tests/test_guided_completion.py +37 -0
  228. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_infrastructure_helpers.py +1 -1
  229. flare_kernel-0.2.2/tests/test_infrastructure_knowledge.py +181 -0
  230. flare_kernel-0.2.2/tests/test_intake_amount_quantity.py +23 -0
  231. flare_kernel-0.2.2/tests/test_intake_answer.py +25 -0
  232. flare_kernel-0.2.2/tests/test_intake_authority.py +159 -0
  233. flare_kernel-0.2.2/tests/test_intake_authority_checkpoint.py +36 -0
  234. flare_kernel-0.2.2/tests/test_intake_authority_hydration.py +99 -0
  235. flare_kernel-0.2.2/tests/test_intake_authority_session.py +58 -0
  236. flare_kernel-0.2.2/tests/test_intake_canonicalization.py +44 -0
  237. flare_kernel-0.2.2/tests/test_intake_clarification.py +77 -0
  238. flare_kernel-0.2.2/tests/test_intake_decision_rules.py +118 -0
  239. flare_kernel-0.2.2/tests/test_intake_deployment_delivery.py +29 -0
  240. flare_kernel-0.2.2/tests/test_intake_entry_policy.py +73 -0
  241. flare_kernel-0.2.2/tests/test_intake_extraction.py +54 -0
  242. flare_kernel-0.2.2/tests/test_intake_extraction_extractors.py +35 -0
  243. flare_kernel-0.2.2/tests/test_intake_extraction_merge.py +36 -0
  244. flare_kernel-0.2.2/tests/test_intake_field_projection.py +69 -0
  245. flare_kernel-0.2.2/tests/test_intake_field_projection_entity.py +28 -0
  246. flare_kernel-0.2.2/tests/test_intake_field_projection_payload.py +18 -0
  247. flare_kernel-0.2.2/tests/test_intake_field_projection_source.py +29 -0
  248. flare_kernel-0.2.2/tests/test_intake_field_scope.py +20 -0
  249. flare_kernel-0.2.2/tests/test_intake_guided_confirmed_updates.py +18 -0
  250. flare_kernel-0.2.2/tests/test_intake_guided_flags.py +14 -0
  251. flare_kernel-0.2.2/tests/test_intake_guided_followup.py +185 -0
  252. flare_kernel-0.2.2/tests/test_intake_guided_followup_work_item.py +60 -0
  253. flare_kernel-0.2.2/tests/test_intake_guided_open_fields.py +27 -0
  254. flare_kernel-0.2.2/tests/test_intake_guided_status.py +23 -0
  255. flare_kernel-0.2.2/tests/test_intake_guided_summary.py +11 -0
  256. flare_kernel-0.2.2/tests/test_intake_inputs.py +85 -0
  257. flare_kernel-0.2.2/tests/test_intake_node_state.py +73 -0
  258. flare_kernel-0.2.2/tests/test_intake_numeric.py +26 -0
  259. flare_kernel-0.2.2/tests/test_intake_payload_updates.py +51 -0
  260. flare_kernel-0.2.2/tests/test_intake_readiness.py +74 -0
  261. flare_kernel-0.2.2/tests/test_intake_reasoning_priority.py +109 -0
  262. flare_kernel-0.2.2/tests/test_intake_state_persistence.py +70 -0
  263. flare_kernel-0.2.2/tests/test_intake_status.py +303 -0
  264. flare_kernel-0.2.2/tests/test_intake_status_guided_session.py +95 -0
  265. flare_kernel-0.2.2/tests/test_intake_status_projection.py +226 -0
  266. flare_kernel-0.2.2/tests/test_intake_status_schema.py +191 -0
  267. flare_kernel-0.2.2/tests/test_intake_status_stage.py +64 -0
  268. flare_kernel-0.2.2/tests/test_intake_workflow_checkpoint.py +23 -0
  269. flare_kernel-0.2.2/tests/test_intent_classifier_utils.py +44 -0
  270. flare_kernel-0.2.2/tests/test_intent_escalation_classifier.py +444 -0
  271. flare_kernel-0.2.2/tests/test_intent_escalation_override.py +65 -0
  272. flare_kernel-0.2.2/tests/test_intent_escalation_pipeline.py +83 -0
  273. flare_kernel-0.2.2/tests/test_intent_escalation_signal.py +88 -0
  274. flare_kernel-0.2.2/tests/test_intent_resolution.py +1745 -0
  275. flare_kernel-0.2.2/tests/test_intent_retrieval.py +110 -0
  276. flare_kernel-0.2.2/tests/test_intent_routing.py +106 -0
  277. flare_kernel-0.2.2/tests/test_intent_type_compat_aliases.py +19 -0
  278. flare_kernel-0.2.2/tests/test_kernel_alias_delegation.py +22 -0
  279. flare_kernel-0.2.2/tests/test_kernel_endpoint_handlers.py +218 -0
  280. flare_kernel-0.2.2/tests/test_kernel_facade_helpers.py +20 -0
  281. flare_kernel-0.2.2/tests/test_kernel_facade_turn_context.py +60 -0
  282. flare_kernel-0.2.2/tests/test_kernel_intent_query_flow.py +60 -0
  283. flare_kernel-0.2.2/tests/test_kernel_mode_flow.py +63 -0
  284. flare_kernel-0.2.2/tests/test_kernel_route_execution_wrappers.py +97 -0
  285. flare_kernel-0.2.2/tests/test_kernel_session_intent_flow.py +40 -0
  286. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_llm_provider.py +1 -1
  287. flare_kernel-0.2.2/tests/test_mode_orchestration_state_bridge.py +83 -0
  288. flare_kernel-0.2.2/tests/test_mode_resolution.py +169 -0
  289. flare_kernel-0.2.2/tests/test_mode_switch.py +40 -0
  290. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/tests/test_model_router.py +1 -1
  291. flare_kernel-0.2.2/tests/test_new_flow_guard.py +29 -0
  292. flare_kernel-0.2.2/tests/test_orchestration_checkpoint_state.py +30 -0
  293. flare_kernel-0.2.2/tests/test_orchestration_followup_state.py +26 -0
  294. flare_kernel-0.2.2/tests/test_orchestration_status_context.py +94 -0
  295. flare_kernel-0.2.2/tests/test_orchestration_status_context_helpers.py +57 -0
  296. flare_kernel-0.2.2/tests/test_orchestration_status_decision.py +71 -0
  297. flare_kernel-0.2.2/tests/test_orchestration_status_projection.py +240 -0
  298. flare_kernel-0.2.2/tests/test_orchestration_status_result.py +53 -0
  299. flare_kernel-0.2.2/tests/test_orchestration_status_runtime_state.py +53 -0
  300. flare_kernel-0.2.2/tests/test_orchestration_status_state_context.py +25 -0
  301. flare_kernel-0.2.2/tests/test_orchestration_status_state_decision.py +43 -0
  302. flare_kernel-0.2.2/tests/test_orchestration_status_state_entry.py +42 -0
  303. flare_kernel-0.2.2/tests/test_orchestration_status_state_followup.py +64 -0
  304. flare_kernel-0.2.2/tests/test_orchestration_status_state_intent.py +38 -0
  305. flare_kernel-0.2.2/tests/test_orchestration_status_state_node.py +53 -0
  306. flare_kernel-0.2.2/tests/test_orchestration_status_state_payload.py +54 -0
  307. flare_kernel-0.2.2/tests/test_orchestration_status_state_unpack.py +38 -0
  308. flare_kernel-0.2.2/tests/test_orchestration_trace.py +146 -0
  309. flare_kernel-0.2.2/tests/test_orchestration_trace_projection.py +17 -0
  310. flare_kernel-0.2.2/tests/test_orchestration_trace_steps.py +28 -0
  311. flare_kernel-0.2.2/tests/test_patch_contract.py +52 -0
  312. flare_kernel-0.2.2/tests/test_payload_enrichment.py +232 -0
  313. flare_kernel-0.2.2/tests/test_request_identity.py +24 -0
  314. flare_kernel-0.2.2/tests/test_request_intent_resolution.py +41 -0
  315. flare_kernel-0.2.2/tests/test_retrieval_aliases.py +71 -0
  316. flare_kernel-0.2.2/tests/test_retrieval_field_queries.py +25 -0
  317. flare_kernel-0.2.2/tests/test_retrieval_projection.py +63 -0
  318. flare_kernel-0.2.2/tests/test_retrieval_query_builder.py +48 -0
  319. flare_kernel-0.2.2/tests/test_retrieval_search.py +50 -0
  320. flare_kernel-0.2.2/tests/test_session_intent.py +98 -0
  321. flare_kernel-0.2.2/tests/test_session_intent_fields.py +67 -0
  322. flare_kernel-0.2.2/tests/test_session_intent_small_talk.py +43 -0
  323. flare_kernel-0.2.2/tests/test_streaming_draft_completion.py +101 -0
  324. flare_kernel-0.2.2/tests/test_streaming_draft_finalize.py +100 -0
  325. flare_kernel-0.2.2/tests/test_streaming_draft_phase.py +186 -0
  326. flare_kernel-0.2.2/tests/test_streaming_draft_post_completion.py +160 -0
  327. flare_kernel-0.2.2/tests/test_streaming_draft_prologue.py +45 -0
  328. flare_kernel-0.2.2/tests/test_streaming_event_emitter.py +72 -0
  329. flare_kernel-0.2.2/tests/test_streaming_intake_phase.py +83 -0
  330. flare_kernel-0.2.2/tests/test_streaming_mode_event_payload.py +85 -0
  331. flare_kernel-0.2.2/tests/test_streaming_mode_events.py +63 -0
  332. flare_kernel-0.2.2/tests/test_streaming_response_bootstrap.py +82 -0
  333. flare_kernel-0.2.2/tests/test_streaming_response_phases.py +168 -0
  334. flare_kernel-0.2.2/tests/test_streaming_response_runtime.py +83 -0
  335. flare_kernel-0.2.2/tests/test_streaming_retrieval_phase.py +69 -0
  336. flare_kernel-0.2.2/tests/test_streaming_runtime_steps.py +61 -0
  337. flare_kernel-0.2.2/tests/test_text_safety.py +34 -0
  338. flare_kernel-0.2.2/tests/test_turn_context_builder.py +116 -0
  339. flare_kernel-0.2.0/src/flare_kernel/router/__init__.py +0 -5
  340. flare_kernel-0.2.0/src/flare_kernel/router/kernel.py +0 -2657
  341. flare_kernel-0.2.0/src/flare_kernel/runtime/__init__.py +0 -79
  342. flare_kernel-0.2.0/src/flare_kernel/runtime/mode_orchestration.py +0 -760
  343. flare_kernel-0.2.0/src/flare_kernel/runtime/mode_runtime.py +0 -446
  344. flare_kernel-0.2.0/src/flare_kernel/runtime/tests/test_kernel_runtime.py +0 -319
  345. flare_kernel-0.2.0/src/flare_kernel.egg-info/SOURCES.txt +0 -34
  346. flare_kernel-0.2.0/tests/test_intent_resolution.py +0 -645
  347. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/setup.cfg +0 -0
  348. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/__init__.py +0 -0
  349. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/app.py +0 -0
  350. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/contracts/__init__.py +0 -0
  351. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel/main.py +0 -0
  352. {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/execution}/agent_runtime.py +0 -0
  353. {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/execution}/skill_runtime.py +0 -0
  354. {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/infrastructure}/logging.py +0 -0
  355. {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/infrastructure}/trace.py +0 -0
  356. {flare_kernel-0.2.0/src/flare_kernel/runtime → flare_kernel-0.2.2/src/flare_kernel/runtime/llm}/model_router.py +0 -0
  357. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel.egg-info/dependency_links.txt +0 -0
  358. {flare_kernel-0.2.0 → flare_kernel-0.2.2}/src/flare_kernel.egg-info/requires.txt +0 -0
  359. {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.0
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 路由与策略入口。
@@ -2,6 +2,11 @@
2
2
 
3
3
  通用编排与执行内核。
4
4
 
5
+ 边界文档:
6
+
7
+ 1. `packages/flare-kernel/docs/KERNEL-BOUNDARY.md`
8
+ 2. `docs/contracts/agent-contract-v1.md`
9
+
5
10
  职责:
6
11
 
7
12
  1. Decision 路由与策略入口。
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "flare-kernel"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "FLARE kernel runtime package"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -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 = "default"
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
+ )