unique-toolkit 2026.26.0.dev12__tar.gz → 2026.28.0__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.
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/PKG-INFO +2 -2
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/pyproject.toml +2 -2
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/chunk_relevancy_sorter/service.py +1 -1
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/pydantic/rjsf_tags.py +16 -7
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/context_relevancy/service.py +1 -1
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/hallucination/constants.py +12 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +11 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/hallucination/utils.py +46 -5
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/schemas.py +10 -0
- unique_toolkit-2026.28.0/unique_toolkit/agentic/evaluation/tests/test_hallucination_external_context.py +122 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/tests/test_hallucination_utils.py +163 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/reference_manager/reference_manager.py +16 -0
- unique_toolkit-2026.28.0/unique_toolkit/agentic/reference_manager/tests/test_external_context.py +35 -0
- unique_toolkit-2026.28.0/unique_toolkit/agentic/tools/a2a/manager.py +93 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/tool/service.py +14 -6
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/config.py +69 -21
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/__init__.py +6 -0
- unique_toolkit-2026.28.0/unique_toolkit/agentic/tools/experimental/ask_user_tool/__init__.py +14 -0
- unique_toolkit-2026.28.0/unique_toolkit/agentic/tools/experimental/ask_user_tool/config.py +138 -0
- unique_toolkit-2026.28.0/unique_toolkit/agentic/tools/experimental/ask_user_tool/tool.py +165 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/retrieve_search_scope_tool/tool.py +1 -1
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/service.py +18 -2
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/mcp/manager.py +29 -8
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/mcp/tool_wrapper.py +15 -7
- unique_toolkit-2026.28.0/unique_toolkit/agentic/tools/run_context.py +24 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/tool.py +57 -5
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/tool_manager.py +207 -22
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic_table/schemas.py +62 -24
- unique_toolkit-2026.28.0/unique_toolkit/agentic_table/synthetic_chat_event.py +67 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/schemas.py +54 -15
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/unique_settings.py +83 -1
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/functions.py +40 -2
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/schemas.py +9 -1
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/content/schemas.py +22 -1
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/content/service.py +79 -40
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/elicitation/service.py +46 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/tool_call_event_handler.py +3 -3
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/subscribers/message_persister.py +14 -4
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/infos.py +115 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/service.py +21 -21
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/settings.py +1 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/services/chat_service.py +24 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/services/factory.py +10 -2
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/services/knowledge_base.py +2 -2
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/short_term_memory/service.py +27 -17
- unique_toolkit-2026.26.0.dev12/unique_toolkit/agentic/tools/a2a/manager.py +0 -55
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/README.md +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/_base_service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/_time_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/api_calling/human_verification_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/base_model_type_attribute.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/chunk_relevancy_sorter/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/chunk_relevancy_sorter/exception.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/README.md +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/__main__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/cli.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/differ.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/exporter.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/models.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/registry.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/config_checker/validator.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/default_language_model.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/docx_generator/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/docx_generator/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/docx_generator/pandoc_converter.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/docx_generator/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/docx_generator/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/endpoint_builder.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/endpoint_requestor.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/event_bus.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/exception.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/execution.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/endpoint_builder.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/endpoint_requestor.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/README.md +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/agent.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/examples/data.csv +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/examples/example_usage.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/exceptions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/exceptions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/system_prompt.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/user_prompt.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/default_template.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/exceptions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/experimental/write_up_agent/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/feature_flags/schema.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/metadata_filter_scope.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/pydantic_helpers.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/referencing.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/string_utilities.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/tests/test_referencing.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/tests/test_string_utilities.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/token/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/token/image_token_counting.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/token/token_counting.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/token/tokenizers/deepseek/tokenizer.json +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/token/tokenizers/qwen/tokenizer.json +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/files.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/image/encode.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/jinja/helpers.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/jinja/render.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/jinja/schema.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/jinja/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/structured_output/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/structured_output/schema.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/utils/write_configuration.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/validate_required_values.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/_common/validators.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/system_prompt.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/user_prompt.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/context_relevancy/schema.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/evaluation_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/exception.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/hallucination/prompts/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/hallucination/prompts/system_prompt.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/hallucination/prompts/user_prompt.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/hallucination/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/output_parser.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/tests/fixtures.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/tests/test_config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/tests/test_hallucination_constants.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/tests/test_output_parser.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/tests/test_prompt_loaders.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/evaluation/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/feature_flags/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/feature_flags/feature_flags.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/history_manager/history_construction_with_contents.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/history_manager/history_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/history_manager/loop_token_reducer.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/history_manager/settings.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/history_manager/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/_iteration_handler_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/_responses_iteration_handler_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/_responses_stream_handler_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/_stream_handler_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/base.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/middleware/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/middleware/planning/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/middleware/planning/planning.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/middleware/planning/schema.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/runners/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/runners/basic.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/runners/mistral/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/runners/mistral/mistral_runner.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/runners/qwen/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/runners/qwen/helpers.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/loop_runner/runners/qwen/qwen_runner.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/message_log_manager/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/message_log_manager/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/message_log_order.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/postprocessor/postprocessor_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/responses_api/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/responses_api/postprocessors/code_display.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/responses_api/stream_handler.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/thinking_manager/thinking_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/evaluation/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/display.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/references.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_references.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/prompts.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/response_watcher/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/tool/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/tool/_memory.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/tool/_schema.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/tool/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/a2a/tool/test/test_service_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/agent_chunks_hanlder.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/open_file_tool/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/open_file_tool/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/open_file_tool/runtime.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/open_file_tool/tool.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/retrieve_search_scope_tool/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/retrieve_search_scope_tool/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/prompts/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/prompts/execution_reminder.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/prompts/system_prompt.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/prompts/tool_description.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/prompts/verification_nudge.j2 +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/experimental/todo/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/factory.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/mcp/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/mcp/models.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/names.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/base.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/artifacts.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/code_display.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/generated_files.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/openai_builtin/manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/test/test_mcp_manager.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/tool_progress_reporter.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/utils/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/utils/source_handling/schema.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic_table/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/agentic_table/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/chat_event_filter_options_settings.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/dev_util.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/fast_api_factory.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/feature_flags.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/find_env_file.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/init_logging.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/init_sdk.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/performance/async_tasks.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/performance/async_wrapper.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/verification.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/app/webhook.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/cancellation.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/constants.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/deprecated/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/rendering.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/responses_api.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/state.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/chat/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/content/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/content/constants.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/content/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/content/smart_rules.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/content/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/README.md +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/augmented/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/augmented/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/base.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/basic/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/basic/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/basic/prompt.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/data_extraction/basic/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/elicitation/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/elicitation/constants.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/elicitation/exceptions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/elicitation/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/elicitation/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/embedding/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/embedding/constants.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/embedding/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/embedding/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/embedding/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/embedding/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/README.md +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/_internal/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/_internal/streaming/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/_internal/streaming/common.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/_internal/streaming/pattern_replacer.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/_base.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/content_tree/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/content_tree/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/content_tree/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/content_tree/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/base/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/base/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/base/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/base/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/base/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/chat/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/chat/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/chat/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/chat/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/knowledge_base/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/knowledge_base/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/knowledge_base/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/knowledge_base/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/post_processing/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/post_processing/config.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/components/internal_search/post_processing/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/content_tree/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/identity/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/_async_bridge.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/complete_with_references.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/stream_event_router.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/text_event_handler.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/tool_call_event_handler.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/events.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/protocols/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/protocols/chat_completions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/protocols/responses.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/code_interpreter_event_handler.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/complete_with_references.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/completed_event_handler.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/stream_event_router.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/text_delta_event_handler.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/subscribers/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/integrations/openai/streaming/event_routing/subscribers/progress_log_persister.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/content_folder/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/content_folder/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/content_folder/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/content_folder/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/facades/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/facades/identity/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/facades/identity/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/feature_flags/README.md +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/feature_flags/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/feature_flags/_graphql_client.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/feature_flags/_ttl_cache.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/feature_flags/client.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/feature_flags/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/feature_flags/settings.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/group/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/group/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/group/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/group/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/scheduled_task/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/scheduled_task/cron.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/scheduled_task/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/scheduled_task/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/scheduled_task/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/user/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/user/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/user/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/resources/user/service.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/experimental/testing/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/framework_utilities/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/framework_utilities/langchain/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/framework_utilities/langchain/client.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/framework_utilities/langchain/history.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/framework_utilities/openai/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/framework_utilities/openai/client.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/framework_utilities/openai/message_builder.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/framework_utilities/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/_responses_api_utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/builder.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/constants.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/default_language_model.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/prompt.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/reference.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/stream_transform.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/language_model/utils.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/monitoring/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/monitoring/gunicorn.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/monitoring/middleware.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/monitoring/registry.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/protocols/support.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/services/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/short_term_memory/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/short_term_memory/constants.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/short_term_memory/functions.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/short_term_memory/schemas.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/smart_rules/__init__.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/smart_rules/compile.py +0 -0
- {unique_toolkit-2026.26.0.dev12 → unique_toolkit-2026.28.0}/unique_toolkit/test_utilities/events.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-toolkit
|
|
3
|
-
Version: 2026.
|
|
3
|
+
Version: 2026.28.0
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Cedric Klinkert, Martin Fadler, Sadique Sheik, Fabian Schläpfer, Pascal Hauri, Ejiroghene Oki-Peter, Rami Azouz, Ricardo Visini, Sanzio Monti
|
|
6
6
|
Author-email: Cedric Klinkert <cedric.klinkert@unique.ch>, Martin Fadler <martin.fadler@unique.ch>, Sadique Sheik <sadique@unique.ch>, Fabian Schläpfer <fabian@unique.ch>, Pascal Hauri <pascal@unique.ch>, Ejiroghene Oki-Peter <oki-peter.ejiroghene@unique.ai>, Rami Azouz <rami.ext@unique.ch>, Ricardo Visini <ricardo.visini@unique.ch>, Sanzio Monti <sanzio.monti@unique.ai>
|
|
@@ -16,7 +16,7 @@ Requires-Dist: sseclient>=0.0.27,<0.0.28
|
|
|
16
16
|
Requires-Dist: openai>=1.105.0,<3
|
|
17
17
|
Requires-Dist: platformdirs>=4.0.0,<5
|
|
18
18
|
Requires-Dist: pillow>=12.1.1
|
|
19
|
-
Requires-Dist: unique-sdk>=2026.
|
|
19
|
+
Requires-Dist: unique-sdk>=2026.28.0
|
|
20
20
|
Requires-Dist: jambo>=0.1.2,<0.2
|
|
21
21
|
Requires-Dist: jinja2>=3.1.6,<4
|
|
22
22
|
Requires-Dist: docxtpl>=0.20.1,<0.21
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "unique_toolkit"
|
|
3
|
-
version = "2026.
|
|
3
|
+
version = "2026.28.0"
|
|
4
4
|
description = ""
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -28,7 +28,7 @@ dependencies = [
|
|
|
28
28
|
"openai>=1.105.0,<3",
|
|
29
29
|
"platformdirs>=4.0.0,<5",
|
|
30
30
|
"pillow>=12.1.1",
|
|
31
|
-
"unique-sdk>=2026.
|
|
31
|
+
"unique-sdk>=2026.28.0",
|
|
32
32
|
"jambo>=0.1.2,<0.2",
|
|
33
33
|
"jinja2>=3.1.6,<4",
|
|
34
34
|
"docxtpl>=0.20.1,<0.21",
|
|
@@ -71,7 +71,7 @@ class ChunkRelevancySorter:
|
|
|
71
71
|
company_id: str | None = None,
|
|
72
72
|
user_id: str | None = None,
|
|
73
73
|
):
|
|
74
|
-
if isinstance(event,
|
|
74
|
+
if isinstance(event, BaseEvent):
|
|
75
75
|
self.chunk_relevancy_evaluator = ContextRelevancyEvaluator.from_event(event)
|
|
76
76
|
else:
|
|
77
77
|
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
@@ -928,6 +928,7 @@ def ui_schema_for_model(
|
|
|
928
928
|
ui: dict[str, Any] = {}
|
|
929
929
|
|
|
930
930
|
for fname in model_cls.model_fields:
|
|
931
|
+
field_info = model_cls.model_fields[fname]
|
|
931
932
|
ann = hints[fname]
|
|
932
933
|
node: dict[str, Any] = {}
|
|
933
934
|
|
|
@@ -1019,13 +1020,21 @@ def ui_schema_for_model(
|
|
|
1019
1020
|
_maybe_set_string_empty_value(branch, alt_b, default_string_empty_value)
|
|
1020
1021
|
branches.append(branch)
|
|
1021
1022
|
if branches:
|
|
1022
|
-
#
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1023
|
+
# RJSF v6 selects the per-branch uiSchema using the SAME keyword
|
|
1024
|
+
# the JSON schema uses for the union: ``schema.oneOf`` reads
|
|
1025
|
+
# ``uiSchema.oneOf`` and ``schema.anyOf`` reads ``uiSchema.anyOf``
|
|
1026
|
+
# (see @rjsf/core ``AnyOfField``). Pydantic emits ``oneOf`` for a
|
|
1027
|
+
# *discriminated* union and ``anyOf`` otherwise, so the uiSchema
|
|
1028
|
+
# branch key MUST match the schema keyword — a ``oneOf`` schema
|
|
1029
|
+
# paired with an ``anyOf`` uiSchema makes RJSF silently drop every
|
|
1030
|
+
# per-branch widget and fall back to default widgets.
|
|
1031
|
+
branch_key = (
|
|
1032
|
+
"oneOf" if field_info.discriminator is not None else "anyOf"
|
|
1033
|
+
)
|
|
1034
|
+
# Keep any branch structure already supplied by a composer
|
|
1035
|
+
# (Optional/Union write their own ``anyOf`` into ``meta``).
|
|
1036
|
+
if "anyOf" not in node and "oneOf" not in node:
|
|
1037
|
+
node[branch_key] = branches
|
|
1029
1038
|
|
|
1030
1039
|
# Scalars: node already has metadata if any
|
|
1031
1040
|
_maybe_set_string_empty_value(node, base, default_string_empty_value)
|
|
@@ -81,7 +81,7 @@ class ContextRelevancyEvaluator:
|
|
|
81
81
|
company_id: str | None = None,
|
|
82
82
|
user_id: str | None = None,
|
|
83
83
|
):
|
|
84
|
-
if isinstance(event,
|
|
84
|
+
if isinstance(event, BaseEvent):
|
|
85
85
|
self.language_model_service = LanguageModelService.from_event(event)
|
|
86
86
|
else:
|
|
87
87
|
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
@@ -52,6 +52,18 @@ class HallucinationConfig(EvaluationMetricConfig):
|
|
|
52
52
|
default={},
|
|
53
53
|
description="Additional options to pass to the language model.",
|
|
54
54
|
)
|
|
55
|
+
max_external_context_chars_per_source: SkipJsonSchema[int] = Field(
|
|
56
|
+
default=20_000,
|
|
57
|
+
ge=0,
|
|
58
|
+
description=(
|
|
59
|
+
"Per-source character cap applied to external (non-chunk) "
|
|
60
|
+
"context texts, e.g. MCP tool output. Raw/large tool results "
|
|
61
|
+
"inflate the judge prompt and the eval-LLM call; each external "
|
|
62
|
+
"text is truncated to this many characters before being added "
|
|
63
|
+
"to the context. 0 disables truncation. Does not affect "
|
|
64
|
+
"chunk-derived context."
|
|
65
|
+
),
|
|
66
|
+
)
|
|
55
67
|
score_to_label: dict[str, str] = {
|
|
56
68
|
"LOW": "GREEN",
|
|
57
69
|
"MEDIUM": "YELLOW",
|
|
@@ -54,6 +54,17 @@ class HallucinationEvaluation(Evaluation):
|
|
|
54
54
|
reference_pattern=self.config.reference_pattern,
|
|
55
55
|
)
|
|
56
56
|
|
|
57
|
+
# Append non-chunk groundedness context (e.g. MCP tool output). These
|
|
58
|
+
# are added in full ("all retrieved output as context") rather than via
|
|
59
|
+
# source-marker selection, since they carry no [sourceN] markers.
|
|
60
|
+
external_context_texts = self._reference_manager.get_external_context_texts()
|
|
61
|
+
max_chars = self.config.max_external_context_chars_per_source
|
|
62
|
+
if max_chars > 0:
|
|
63
|
+
external_context_texts = [
|
|
64
|
+
text[:max_chars] for text in external_context_texts
|
|
65
|
+
]
|
|
66
|
+
context_texts = context_texts + external_context_texts
|
|
67
|
+
|
|
57
68
|
evaluation_result: EvaluationMetricResult = await check_hallucination(
|
|
58
69
|
company_id=self._company_id,
|
|
59
70
|
user_id=self._user_id,
|
|
@@ -16,6 +16,8 @@ from unique_toolkit.agentic.evaluation.schemas import (
|
|
|
16
16
|
)
|
|
17
17
|
from unique_toolkit.content import ContentReference
|
|
18
18
|
from unique_toolkit.content.schemas import ContentChunk
|
|
19
|
+
from unique_toolkit.language_model.builder import MessagesBuilder
|
|
20
|
+
from unique_toolkit.language_model.infos import ModelCapabilities
|
|
19
21
|
from unique_toolkit.language_model.schemas import (
|
|
20
22
|
LanguageModelMessages,
|
|
21
23
|
LanguageModelStreamResponse,
|
|
@@ -104,19 +106,28 @@ def _get_msgs(
|
|
|
104
106
|
"""
|
|
105
107
|
Composes the messages for hallucination analysis based on the provided input and configuration.
|
|
106
108
|
|
|
107
|
-
This method composes messages with or without context based on the availability of context texts
|
|
108
|
-
|
|
109
|
+
This method composes messages with or without context based on the availability of context texts,
|
|
110
|
+
history message texts, and (for vision-capable models) context images in the input.
|
|
109
111
|
|
|
110
112
|
Args:
|
|
111
|
-
input (EvaluationMetricInput): The input data that includes context texts
|
|
112
|
-
for the analysis.
|
|
113
|
+
input (EvaluationMetricInput): The input data that includes context texts, history message texts,
|
|
114
|
+
and context images for the analysis.
|
|
113
115
|
config (EvaluationMetricConfig): The configuration settings for composing messages.
|
|
114
116
|
logger (Optional[logging.Logger], optional): The logger used for logging debug information.
|
|
115
117
|
|
|
116
118
|
Returns:
|
|
117
119
|
The composed messages as per the provided input and configuration.
|
|
118
120
|
"""
|
|
119
|
-
|
|
121
|
+
# Context images only count as grounding when the model can actually consume
|
|
122
|
+
# them; otherwise _compose_msgs drops them and the message would be text-only.
|
|
123
|
+
model_supports_vision = (
|
|
124
|
+
ModelCapabilities.VISION in config.language_model.capabilities
|
|
125
|
+
)
|
|
126
|
+
has_context = bool(
|
|
127
|
+
input.context_texts
|
|
128
|
+
or input.history_messages
|
|
129
|
+
or (input.context_images and model_supports_vision)
|
|
130
|
+
)
|
|
120
131
|
|
|
121
132
|
if has_context:
|
|
122
133
|
_LOGGER.debug("Using context / history for hallucination evaluation.")
|
|
@@ -165,6 +176,36 @@ def _compose_msgs(
|
|
|
165
176
|
else None,
|
|
166
177
|
output_text=input.output_text,
|
|
167
178
|
)
|
|
179
|
+
|
|
180
|
+
# When images are provided AND the configured model is vision-capable, build
|
|
181
|
+
# a multimodal user message (rendered user text + one image part per data
|
|
182
|
+
# URL) so the model can ground the check against the rendered pages. If the
|
|
183
|
+
# model lacks VISION we drop the images and fall back to the text-only
|
|
184
|
+
# message: attaching images to a non-vision model would make the LLM call
|
|
185
|
+
# fail. Without images the message stays the exact text-only form, so
|
|
186
|
+
# existing callers are unaffected.
|
|
187
|
+
context_images = input.context_images or []
|
|
188
|
+
model_supports_vision = (
|
|
189
|
+
ModelCapabilities.VISION in config.language_model.capabilities
|
|
190
|
+
)
|
|
191
|
+
# When has_context is True for an images-only input, the caller already
|
|
192
|
+
# confirmed the model is vision-capable, so this branch stays unreachable in
|
|
193
|
+
# that case and only logs for a genuine non-vision misconfiguration.
|
|
194
|
+
if context_images and not model_supports_vision:
|
|
195
|
+
_LOGGER.warning(
|
|
196
|
+
"Hallucination model %s lacks VISION capability; ignoring "
|
|
197
|
+
"%d context image(s) and grounding on text only.",
|
|
198
|
+
config.language_model.name,
|
|
199
|
+
len(context_images),
|
|
200
|
+
)
|
|
201
|
+
if context_images and model_supports_vision:
|
|
202
|
+
return (
|
|
203
|
+
MessagesBuilder()
|
|
204
|
+
.append(system_msg)
|
|
205
|
+
.image_message_append(content=user_msg_content, images=context_images)
|
|
206
|
+
.build()
|
|
207
|
+
)
|
|
208
|
+
|
|
168
209
|
user_msg = LanguageModelUserMessage(content=user_msg_content)
|
|
169
210
|
|
|
170
211
|
return LanguageModelMessages([system_msg, user_msg])
|
|
@@ -34,6 +34,16 @@ class EvaluationMetricInput(BaseModel):
|
|
|
34
34
|
context_texts: Optional[list[str]] = None
|
|
35
35
|
history_messages: Optional[list[ChatMessage]] = None
|
|
36
36
|
output_text: Optional[str] = None
|
|
37
|
+
context_images: Optional[list[str]] = Field(
|
|
38
|
+
default=None,
|
|
39
|
+
description=(
|
|
40
|
+
"Optional base64 data URLs (e.g. 'data:image/png;base64,...') of "
|
|
41
|
+
"context the metric should evaluate against visually, in addition "
|
|
42
|
+
"to context_texts. Used by metrics that support a multimodal "
|
|
43
|
+
"(vision) check; ignored by metrics that do not. Defaults to None "
|
|
44
|
+
"so existing text-only callers are unaffected."
|
|
45
|
+
),
|
|
46
|
+
)
|
|
37
47
|
|
|
38
48
|
def get_joined_context_texts(self, tag_name: str = "reference") -> str:
|
|
39
49
|
"""
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Tests that HallucinationEvaluation grounds against non-chunk context.
|
|
2
|
+
|
|
3
|
+
UN-21951: external context texts (e.g. MCP tool output) registered on the
|
|
4
|
+
ReferenceManager must be appended to the evaluation context — in addition to
|
|
5
|
+
chunk-derived context, capped by ``max_external_context_chars_per_source`` —
|
|
6
|
+
without being converted to ContentChunks.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from types import SimpleNamespace
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
from unique_toolkit.agentic.evaluation.hallucination import (
|
|
14
|
+
hallucination_evaluation as he,
|
|
15
|
+
)
|
|
16
|
+
from unique_toolkit.agentic.evaluation.hallucination.constants import (
|
|
17
|
+
HallucinationConfig,
|
|
18
|
+
SourceSelectionMode,
|
|
19
|
+
)
|
|
20
|
+
from unique_toolkit.agentic.evaluation.schemas import (
|
|
21
|
+
EvaluationMetricName,
|
|
22
|
+
EvaluationMetricResult,
|
|
23
|
+
)
|
|
24
|
+
from unique_toolkit.agentic.reference_manager.reference_manager import (
|
|
25
|
+
ReferenceManager,
|
|
26
|
+
)
|
|
27
|
+
from unique_toolkit.chat.schemas import ChatMessageRole
|
|
28
|
+
from unique_toolkit.language_model.schemas import (
|
|
29
|
+
LanguageModelStreamResponse,
|
|
30
|
+
LanguageModelStreamResponseMessage,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _make_event() -> SimpleNamespace:
|
|
35
|
+
return SimpleNamespace(
|
|
36
|
+
company_id="company_1",
|
|
37
|
+
user_id="user_1",
|
|
38
|
+
payload=SimpleNamespace(
|
|
39
|
+
user_message=SimpleNamespace(text="what is ACME revenue?"),
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _make_response(text: str = "ACME revenue is 1M.") -> LanguageModelStreamResponse:
|
|
45
|
+
return LanguageModelStreamResponse(
|
|
46
|
+
message=LanguageModelStreamResponseMessage(
|
|
47
|
+
id="msg_1",
|
|
48
|
+
previous_message_id=None,
|
|
49
|
+
role=ChatMessageRole.ASSISTANT,
|
|
50
|
+
text=text,
|
|
51
|
+
chat_id="chat_1",
|
|
52
|
+
original_text=text,
|
|
53
|
+
references=None,
|
|
54
|
+
),
|
|
55
|
+
tool_calls=None,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@pytest.fixture
|
|
60
|
+
def captured_context(monkeypatch: pytest.MonkeyPatch) -> dict:
|
|
61
|
+
"""Patch check_hallucination to capture the context_texts it receives."""
|
|
62
|
+
captured: dict = {}
|
|
63
|
+
|
|
64
|
+
async def _fake_check_hallucination(*, company_id, user_id, input, config):
|
|
65
|
+
captured["context_texts"] = list(input.context_texts or [])
|
|
66
|
+
return EvaluationMetricResult(
|
|
67
|
+
name=EvaluationMetricName.HALLUCINATION,
|
|
68
|
+
value="LOW",
|
|
69
|
+
reason="grounded",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
monkeypatch.setattr(he, "check_hallucination", _fake_check_hallucination)
|
|
73
|
+
return captured
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
async def test_external_context_is_appended(captured_context: dict) -> None:
|
|
77
|
+
manager = ReferenceManager()
|
|
78
|
+
manager.add_external_context_texts(["ACME revenue: 1M"])
|
|
79
|
+
evaluation = he.HallucinationEvaluation(
|
|
80
|
+
HallucinationConfig(source_selection_mode=SourceSelectionMode.FROM_IDS),
|
|
81
|
+
_make_event(), # type: ignore[arg-type]
|
|
82
|
+
manager,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
result = await evaluation.run(_make_response())
|
|
86
|
+
|
|
87
|
+
# No chunks → context comes solely from the external (MCP) source.
|
|
88
|
+
assert captured_context["context_texts"] == ["ACME revenue: 1M"]
|
|
89
|
+
assert result.value == "LOW"
|
|
90
|
+
assert result.is_positive is True
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
async def test_external_context_is_truncated(captured_context: dict) -> None:
|
|
94
|
+
manager = ReferenceManager()
|
|
95
|
+
manager.add_external_context_texts(["x" * 100])
|
|
96
|
+
evaluation = he.HallucinationEvaluation(
|
|
97
|
+
HallucinationConfig(
|
|
98
|
+
source_selection_mode=SourceSelectionMode.FROM_IDS,
|
|
99
|
+
max_external_context_chars_per_source=10,
|
|
100
|
+
),
|
|
101
|
+
_make_event(), # type: ignore[arg-type]
|
|
102
|
+
manager,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
await evaluation.run(_make_response())
|
|
106
|
+
|
|
107
|
+
assert captured_context["context_texts"] == ["x" * 10]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
async def test_no_external_context_preserves_chunk_only_behaviour(
|
|
111
|
+
captured_context: dict,
|
|
112
|
+
) -> None:
|
|
113
|
+
manager = ReferenceManager() # no chunks, no external context
|
|
114
|
+
evaluation = he.HallucinationEvaluation(
|
|
115
|
+
HallucinationConfig(source_selection_mode=SourceSelectionMode.FROM_IDS),
|
|
116
|
+
_make_event(), # type: ignore[arg-type]
|
|
117
|
+
manager,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
await evaluation.run(_make_response())
|
|
121
|
+
|
|
122
|
+
assert captured_context["context_texts"] == []
|
|
@@ -20,6 +20,10 @@ from unique_toolkit.agentic.evaluation.schemas import EvaluationMetricInput
|
|
|
20
20
|
from unique_toolkit.chat.schemas import ChatMessage
|
|
21
21
|
from unique_toolkit.content import ContentReference
|
|
22
22
|
from unique_toolkit.content.schemas import ContentChunk
|
|
23
|
+
from unique_toolkit.language_model.infos import (
|
|
24
|
+
LanguageModelName,
|
|
25
|
+
ModelCapabilities,
|
|
26
|
+
)
|
|
23
27
|
from unique_toolkit.language_model.schemas import (
|
|
24
28
|
LanguageModelMessageRole,
|
|
25
29
|
LanguageModelMessages,
|
|
@@ -1013,3 +1017,162 @@ def test_compose_msgs__generates_non_empty_messages__from_config_prompts(
|
|
|
1013
1017
|
# Assert
|
|
1014
1018
|
assert len(result.root[0].content) > 0
|
|
1015
1019
|
assert len(result.root[1].content) > 0
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
_IMAGE_DATA_URL = "data:image/png;base64,QQ=="
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
@pytest.mark.ai
|
|
1026
|
+
def test_compose_msgs__builds_multimodal_user_message__with_context_images(
|
|
1027
|
+
hallucination_config: HallucinationConfig,
|
|
1028
|
+
) -> None:
|
|
1029
|
+
"""
|
|
1030
|
+
Purpose: Verify that context_images produce a multimodal user message.
|
|
1031
|
+
Why this matters: Vision faithfulness needs the rendered pages as image parts.
|
|
1032
|
+
Setup summary: Provide context_images, assert the user message carries text +
|
|
1033
|
+
one image part per data URL.
|
|
1034
|
+
"""
|
|
1035
|
+
# Arrange
|
|
1036
|
+
input_data: EvaluationMetricInput = EvaluationMetricInput(
|
|
1037
|
+
input_text="Question",
|
|
1038
|
+
output_text="Output",
|
|
1039
|
+
context_images=[_IMAGE_DATA_URL],
|
|
1040
|
+
)
|
|
1041
|
+
|
|
1042
|
+
# Act
|
|
1043
|
+
result: LanguageModelMessages = _compose_msgs(
|
|
1044
|
+
input_data, hallucination_config, has_context=True
|
|
1045
|
+
)
|
|
1046
|
+
|
|
1047
|
+
# Assert
|
|
1048
|
+
assert len(result.root) == 2
|
|
1049
|
+
user_content = result.root[1].content
|
|
1050
|
+
assert isinstance(user_content, list)
|
|
1051
|
+
text_parts = [p for p in user_content if p.get("type") == "text"]
|
|
1052
|
+
image_parts = [p for p in user_content if p.get("type") == "image_url"]
|
|
1053
|
+
assert len(text_parts) == 1
|
|
1054
|
+
assert len(image_parts) == 1
|
|
1055
|
+
assert image_parts[0]["imageUrl"]["url"] == _IMAGE_DATA_URL
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
@pytest.mark.ai
|
|
1059
|
+
def test_compose_msgs__stays_text_only__without_context_images(
|
|
1060
|
+
hallucination_config: HallucinationConfig,
|
|
1061
|
+
) -> None:
|
|
1062
|
+
"""
|
|
1063
|
+
Purpose: Verify that omitting context_images keeps the exact text-only message.
|
|
1064
|
+
Why this matters: Backward compatibility for all existing (non-vision) callers.
|
|
1065
|
+
Setup summary: No context_images -> user message content is a plain string.
|
|
1066
|
+
"""
|
|
1067
|
+
# Arrange
|
|
1068
|
+
input_data: EvaluationMetricInput = EvaluationMetricInput(
|
|
1069
|
+
input_text="Question",
|
|
1070
|
+
context_texts=["Context 1"],
|
|
1071
|
+
output_text="Output",
|
|
1072
|
+
)
|
|
1073
|
+
|
|
1074
|
+
# Act
|
|
1075
|
+
result: LanguageModelMessages = _compose_msgs(
|
|
1076
|
+
input_data, hallucination_config, has_context=True
|
|
1077
|
+
)
|
|
1078
|
+
|
|
1079
|
+
# Assert
|
|
1080
|
+
assert isinstance(result.root[1].content, str)
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
@pytest.mark.ai
|
|
1084
|
+
def test_compose_msgs__drops_images__when_model_lacks_vision() -> None:
|
|
1085
|
+
"""
|
|
1086
|
+
Purpose: Verify images are dropped when the configured model is not vision-capable.
|
|
1087
|
+
Why this matters: Attaching images to a non-vision model makes the LLM call fail;
|
|
1088
|
+
we must degrade gracefully to a text-only message instead.
|
|
1089
|
+
Setup summary: Configure a text-only model (no VISION capability) with
|
|
1090
|
+
context_images, assert the user message content stays a plain string.
|
|
1091
|
+
"""
|
|
1092
|
+
# Arrange
|
|
1093
|
+
text_only_config = HallucinationConfig(
|
|
1094
|
+
enabled=True,
|
|
1095
|
+
language_model=LanguageModelName.AZURE_GPT_4_0613,
|
|
1096
|
+
)
|
|
1097
|
+
assert ModelCapabilities.VISION not in (
|
|
1098
|
+
text_only_config.language_model.capabilities
|
|
1099
|
+
)
|
|
1100
|
+
input_data: EvaluationMetricInput = EvaluationMetricInput(
|
|
1101
|
+
input_text="Question",
|
|
1102
|
+
output_text="Output",
|
|
1103
|
+
context_images=[_IMAGE_DATA_URL],
|
|
1104
|
+
)
|
|
1105
|
+
|
|
1106
|
+
# Act
|
|
1107
|
+
result: LanguageModelMessages = _compose_msgs(
|
|
1108
|
+
input_data, text_only_config, has_context=True
|
|
1109
|
+
)
|
|
1110
|
+
|
|
1111
|
+
# Assert
|
|
1112
|
+
assert isinstance(result.root[1].content, str)
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
@pytest.mark.ai
|
|
1116
|
+
def test_get_msgs__treats_context_images_as_context(
|
|
1117
|
+
hallucination_config: HallucinationConfig,
|
|
1118
|
+
) -> None:
|
|
1119
|
+
"""
|
|
1120
|
+
Purpose: Verify that context_images alone count as context in _get_msgs.
|
|
1121
|
+
Why this matters: A vision-only turn must use the grounded (has_context) prompt
|
|
1122
|
+
and build the multimodal message.
|
|
1123
|
+
Setup summary: Provide only context_images; assert the system prompt matches the
|
|
1124
|
+
has_context variant and the user message is multimodal.
|
|
1125
|
+
"""
|
|
1126
|
+
# Arrange
|
|
1127
|
+
image_only: EvaluationMetricInput = EvaluationMetricInput(
|
|
1128
|
+
input_text="Question",
|
|
1129
|
+
output_text="Output",
|
|
1130
|
+
context_images=[_IMAGE_DATA_URL],
|
|
1131
|
+
)
|
|
1132
|
+
grounded: EvaluationMetricInput = EvaluationMetricInput(
|
|
1133
|
+
input_text="Question",
|
|
1134
|
+
context_texts=["Context 1"],
|
|
1135
|
+
output_text="Output",
|
|
1136
|
+
)
|
|
1137
|
+
|
|
1138
|
+
# Act
|
|
1139
|
+
result: LanguageModelMessages = _get_msgs(image_only, hallucination_config)
|
|
1140
|
+
grounded_result: LanguageModelMessages = _get_msgs(grounded, hallucination_config)
|
|
1141
|
+
|
|
1142
|
+
# Assert
|
|
1143
|
+
assert result.root[0].content == grounded_result.root[0].content
|
|
1144
|
+
assert isinstance(result.root[1].content, list)
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
@pytest.mark.ai
|
|
1148
|
+
def test_get_msgs__ignores_context_images__when_model_lacks_vision() -> None:
|
|
1149
|
+
"""
|
|
1150
|
+
Purpose: Verify image-only input is not treated as context for a non-vision model.
|
|
1151
|
+
Why this matters: _compose_msgs drops the images for a non-vision model, so the
|
|
1152
|
+
grounded prompt would otherwise claim references that are never sent. has_context
|
|
1153
|
+
must reflect the message actually delivered.
|
|
1154
|
+
Setup summary: Configure a text-only model with only context_images; assert the
|
|
1155
|
+
system prompt matches the ungrounded variant and the user message is text-only.
|
|
1156
|
+
"""
|
|
1157
|
+
# Arrange
|
|
1158
|
+
text_only_config = HallucinationConfig(
|
|
1159
|
+
enabled=True,
|
|
1160
|
+
language_model=LanguageModelName.AZURE_GPT_4_0613,
|
|
1161
|
+
)
|
|
1162
|
+
image_only: EvaluationMetricInput = EvaluationMetricInput(
|
|
1163
|
+
input_text="Question",
|
|
1164
|
+
output_text="Output",
|
|
1165
|
+
context_images=[_IMAGE_DATA_URL],
|
|
1166
|
+
)
|
|
1167
|
+
no_context: EvaluationMetricInput = EvaluationMetricInput(
|
|
1168
|
+
input_text="Question",
|
|
1169
|
+
output_text="Output",
|
|
1170
|
+
)
|
|
1171
|
+
|
|
1172
|
+
# Act
|
|
1173
|
+
result: LanguageModelMessages = _get_msgs(image_only, text_only_config)
|
|
1174
|
+
no_context_result: LanguageModelMessages = _get_msgs(no_context, text_only_config)
|
|
1175
|
+
|
|
1176
|
+
# Assert
|
|
1177
|
+
assert result.root[0].content == no_context_result.root[0].content
|
|
1178
|
+
assert isinstance(result.root[1].content, str)
|
|
@@ -32,6 +32,7 @@ class ReferenceManager:
|
|
|
32
32
|
self._tool_chunks: dict[str, tool_chunks] = {}
|
|
33
33
|
self._chunks: list[ContentChunk] = []
|
|
34
34
|
self._references: list[list[ContentReference]] = []
|
|
35
|
+
self._external_context_texts: list[str] = []
|
|
35
36
|
|
|
36
37
|
def extract_referenceable_chunks(
|
|
37
38
|
self, tool_responses: list[ToolCallResponse]
|
|
@@ -47,6 +48,21 @@ class ReferenceManager:
|
|
|
47
48
|
def get_chunks(self) -> list[ContentChunk]:
|
|
48
49
|
return self._chunks
|
|
49
50
|
|
|
51
|
+
def add_external_context_texts(self, texts: list[str]) -> None:
|
|
52
|
+
"""Register groundedness context that is not backed by ContentChunks.
|
|
53
|
+
|
|
54
|
+
Some retrieval sources (e.g. MCP tool output) provide text the answer
|
|
55
|
+
is built on but are deliberately *not* modelled as ContentChunks — they
|
|
56
|
+
are a different entity from ingested document chunks and must not flow
|
|
57
|
+
through the chunk/reference pipeline. They still need to ground the
|
|
58
|
+
hallucination check, so they are stored here and appended to the
|
|
59
|
+
evaluation context alongside the chunk-derived texts.
|
|
60
|
+
"""
|
|
61
|
+
self._external_context_texts.extend(text for text in texts if text)
|
|
62
|
+
|
|
63
|
+
def get_external_context_texts(self) -> list[str]:
|
|
64
|
+
return self._external_context_texts
|
|
65
|
+
|
|
50
66
|
def get_tool_chunks(self) -> dict[str, tool_chunks]:
|
|
51
67
|
return self._tool_chunks
|
|
52
68
|
|
unique_toolkit-2026.28.0/unique_toolkit/agentic/reference_manager/tests/test_external_context.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Tests for non-chunk groundedness context on the ReferenceManager.
|
|
2
|
+
|
|
3
|
+
External context texts (e.g. MCP tool output, UN-21951) ground the
|
|
4
|
+
hallucination check without being modelled as ContentChunks.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from unique_toolkit.agentic.reference_manager.reference_manager import (
|
|
8
|
+
ReferenceManager,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_external_context_starts_empty() -> None:
|
|
13
|
+
manager = ReferenceManager()
|
|
14
|
+
assert manager.get_external_context_texts() == []
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_add_external_context_texts_accumulates() -> None:
|
|
18
|
+
manager = ReferenceManager()
|
|
19
|
+
manager.add_external_context_texts(["a", "b"])
|
|
20
|
+
manager.add_external_context_texts(["c"])
|
|
21
|
+
assert manager.get_external_context_texts() == ["a", "b", "c"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_add_external_context_texts_drops_empty_strings() -> None:
|
|
25
|
+
manager = ReferenceManager()
|
|
26
|
+
manager.add_external_context_texts(["keep", "", "also"])
|
|
27
|
+
assert manager.get_external_context_texts() == ["keep", "also"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_external_context_is_independent_of_chunks() -> None:
|
|
31
|
+
manager = ReferenceManager()
|
|
32
|
+
manager.add_external_context_texts(["mcp output"])
|
|
33
|
+
# External context must not leak into the chunk pipeline.
|
|
34
|
+
assert manager.get_chunks() == []
|
|
35
|
+
assert manager.get_external_context_texts() == ["mcp output"]
|