language-model-common 2.0.76__tar.gz → 2.0.78__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.
- {language_model_common-2.0.76/language_model_common.egg-info → language_model_common-2.0.78}/PKG-INFO +3 -2
- language_model_common-2.0.78/VERSION +1 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78/language_model_common.egg-info}/PKG-INFO +3 -2
- {language_model_common-2.0.76 → language_model_common-2.0.78}/language_model_common.egg-info/SOURCES.txt +11 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/language_model_common.egg-info/requires.txt +2 -1
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/github_directory_helper.py +11 -1
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/container/container_factory.py +41 -0
- language_model_common-2.0.78/languagemodelcommon/github/token_provider.py +119 -0
- language_model_common-2.0.78/languagemodelcommon/pipeline/context.py +40 -0
- language_model_common-2.0.78/languagemodelcommon/pipeline/pipeline.py +100 -0
- language_model_common-2.0.78/languagemodelcommon/pipeline/step.py +11 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/environment/language_model_common_environment_variables.py +12 -0
- language_model_common-2.0.78/languagemodelcommon/utilities/security/__init__.py +0 -0
- language_model_common-2.0.78/languagemodelcommon/utilities/security/normalize.py +100 -0
- language_model_common-2.0.78/languagemodelcommon/utilities/security/off_topic_detector.py +96 -0
- language_model_common-2.0.78/languagemodelcommon/utilities/security/prompt_extraction_detector.py +69 -0
- language_model_common-2.0.78/languagemodelcommon/utilities/slash_command/__init__.py +0 -0
- language_model_common-2.0.78/languagemodelcommon/utilities/slash_command/handlers/__init__.py +0 -0
- language_model_common-2.0.78/languagemodelcommon/utilities/token_reducer/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/pyproject.toml +3 -2
- language_model_common-2.0.76/VERSION +0 -1
- {language_model_common-2.0.76 → language_model_common-2.0.78}/LICENSE +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/MANIFEST.in +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/README.md +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/language_model_common.egg-info/dependency_links.txt +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/language_model_common.egg-info/top_level.txt +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/authenticator/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/exceptions/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/exceptions/authorization_mcp_tool_token_invalid_exception.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/exceptions/authorization_token_cache_item_expired_exception.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/exceptions/authorization_token_cache_item_not_found_exception.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/models/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/models/token_cache_item.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/oauth_provider_registrar.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/pass_through_token_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/token_exchange/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/token_exchange/token_exchange_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/token_storage_auth_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/tools/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/tools/tool_auth_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/aws/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/aws/aws_client_factory.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/config_reader.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/file_config_reader.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/github_directory_downloader.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/mcp_json_fetcher.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/mcp_json_reader.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/s3_config_reader.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/prompt_library/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/prompt_library/prompt_library_environment_variables.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/prompt_library/prompt_library_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/prompt_library/prompt_store.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/schemas/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/schemas/config_schema.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/schemas/mcp_json_schema.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/container/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/context/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/context/request_context.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/langgraph_to_openai_converter.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/stream_buffer.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/stream_context_mixin.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/stream_debug_output_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/streaming_formatters.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/streaming_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/streaming_tool_node.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/tool_event_handlers.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/exceptions/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/exceptions/bailey_exception.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/aws_s3_file_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/file_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/file_manager_factory.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/file_writer.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/local_file_manager.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/graph → language_model_common-2.0.78/languagemodelcommon/github}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/history → language_model_common-2.0.78/languagemodelcommon/graph}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/graph/graph_builder.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/http → language_model_common-2.0.78/languagemodelcommon/history}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/history/context_compactor.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/history/conversation_history_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/history/smart_history_manager.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/image_generation → language_model_common-2.0.78/languagemodelcommon/http}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/http/http_client_factory.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/image_generation/managers → language_model_common-2.0.78/languagemodelcommon/image_generation}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/aws_image_generator.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/image_generator.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/image_generator_factory.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/image_generation/providers → language_model_common-2.0.78/languagemodelcommon/image_generation/managers}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/managers/image_generation_manager.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/openai_image_generator.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/markdown → language_model_common-2.0.78/languagemodelcommon/image_generation/providers}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/providers/base_image_generation_provider.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/providers/image_generation_provider.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/mcp → language_model_common-2.0.78/languagemodelcommon/markdown}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/markdown/html_to_markdown_converter.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/mcp/auth → language_model_common-2.0.78/languagemodelcommon/mcp}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/mcp/exceptions → language_model_common-2.0.78/languagemodelcommon/mcp/auth}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/auth/auth_server_metadata_discovery.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/auth/mcp_authorization_helper.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/callbacks.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/mcp/interceptors → language_model_common-2.0.78/languagemodelcommon/mcp/exceptions}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/exceptions/mcp_tool_exception.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/exceptions/mcp_tool_not_found_exception.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/exceptions/mcp_tool_unauthorized_exception.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/exceptions/mcp_tool_unknown_exception.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/mcp/mcp_client → language_model_common-2.0.78/languagemodelcommon/mcp/interceptors}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/interceptors/auth.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/interceptors/tracing.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/interceptors/truncation.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/interceptors/types.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/mocks → language_model_common-2.0.78/languagemodelcommon/mcp/mcp_client}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/content_conversion.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/langchain_adapter.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/mcp_app_proxy.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/mcp_tool_list_store.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/server_card_discovery.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/session.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/session_pool.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/tool_invocation.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/tool_list_cache.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/ui_resource.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_tool_provider.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/tool_catalog.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/tool_discovery_middleware.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/models → language_model_common-2.0.78/languagemodelcommon/mocks}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mocks/mock_aws_client_factory.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mocks/mock_http_client_factory.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mocks/mock_image_generator.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mocks/mock_image_generator_factory.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/ocr → language_model_common-2.0.78/languagemodelcommon/models}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/models/bedrock_models.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/models/model_factory.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/models/sanitizing_bedrock_converse.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/persistence → language_model_common-2.0.78/languagemodelcommon/ocr}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/ocr/aws_ocr_extractor.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/ocr/ocr_extractor.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/ocr/ocr_extractor_factory.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/schema → language_model_common-2.0.78/languagemodelcommon/persistence}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/persistence/persistence_factory.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/schema/openai → language_model_common-2.0.78/languagemodelcommon/pipeline}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/state → language_model_common-2.0.78/languagemodelcommon/pipeline/output}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/structures → language_model_common-2.0.78/languagemodelcommon/pipeline/steps}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/py.typed +0 -0
- {language_model_common-2.0.76/languagemodelcommon/structures/openai → language_model_common-2.0.78/languagemodelcommon/schema}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/structures/openai/message → language_model_common-2.0.78/languagemodelcommon/schema/openai}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/schema/openai/completions.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/schema/openai/image_generation.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/schema/openai/responses.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/structures/openai/request → language_model_common-2.0.78/languagemodelcommon/state}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/state/messages_state.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/tools → language_model_common-2.0.78/languagemodelcommon/structures}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/tools/mcp → language_model_common-2.0.78/languagemodelcommon/structures/openai}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities → language_model_common-2.0.78/languagemodelcommon/structures/openai/message}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/message/chat_completion_api_message_wrapper.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/message/chat_message_wrapper.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/message/responses_api_message_wrapper.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/cache → language_model_common-2.0.78/languagemodelcommon/structures/openai/request}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/request/chat_completion_api_request_wrapper.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/request/chat_request_wrapper.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/request/responses_api_request_wrapper.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/environment → language_model_common-2.0.78/languagemodelcommon/tools}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/header_reader → language_model_common-2.0.78/languagemodelcommon/tools/mcp}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/tools/mcp/call_tool_tool.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/tools/mcp/search_tools_tool.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/logger → language_model_common-2.0.78/languagemodelcommon/utilities}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/message_preprocessing → language_model_common-2.0.78/languagemodelcommon/utilities/cache}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/cache/advisory_lock.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/cache/model_config_cache_store.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/chat_message_helpers.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/config_substitution.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/openai → language_model_common-2.0.78/languagemodelcommon/utilities/environment}/__init__.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/security → language_model_common-2.0.78/languagemodelcommon/utilities/header_reader}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/header_reader/header_reader.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/slash_command → language_model_common-2.0.78/languagemodelcommon/utilities/logger}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/debug_configuration.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/exception_formatter.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/exception_logger.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/log_levels.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/logging_response.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/logging_transport.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/slash_command/handlers → language_model_common-2.0.78/languagemodelcommon/utilities/message_preprocessing}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/message_preprocessing/composite_message_preprocessor.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/message_preprocessing/message_preprocessor.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/mongo_url_utils.py +0 -0
- {language_model_common-2.0.76/languagemodelcommon/utilities/token_reducer → language_model_common-2.0.78/languagemodelcommon/utilities/openai}/__init__.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/openai/responses_api_converter.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/request_information.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/s3_url.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/security/prompt_sanitizer.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/handlers/debug_command_handler.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/handlers/skill_command_handler.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/slash_command_handler.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/slash_command_parser.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/slash_command_processor.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/text_humanizer.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/token_reducer/token_reducer.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/tool_display_name_mapper.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/url_parser.py +0 -0
- {language_model_common-2.0.76 → language_model_common-2.0.78}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: language-model-common
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.78
|
|
4
4
|
Summary: Provides the underlying framework to enhance langchain and add loading configurations
|
|
5
5
|
Author-email: Imran Qureshi <imran.qureshi@bwell.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -21,7 +21,7 @@ Requires-Dist: openai>=2.5.0
|
|
|
21
21
|
Requires-Dist: langchain-openai>=1.1.6
|
|
22
22
|
Requires-Dist: langgraph>=1.0.0
|
|
23
23
|
Requires-Dist: pydantic<3.0.0,>=2.0
|
|
24
|
-
Requires-Dist: mcp>=1.
|
|
24
|
+
Requires-Dist: mcp>=1.27.2
|
|
25
25
|
Requires-Dist: langgraph-checkpoint>=3.0.0
|
|
26
26
|
Requires-Dist: langgraph-checkpoint-mongodb>=0.3.1
|
|
27
27
|
Requires-Dist: langgraph-store-mongodb>=0.1.0
|
|
@@ -35,6 +35,7 @@ Requires-Dist: fsspec>=2026.2.0
|
|
|
35
35
|
Requires-Dist: authlib>=1.6.5
|
|
36
36
|
Requires-Dist: langchain-google-genai>=4.1.3
|
|
37
37
|
Requires-Dist: py-key-value-aio>=0.4.4
|
|
38
|
+
Requires-Dist: PyJWT[crypto]>=2.8.0
|
|
38
39
|
Dynamic: license-file
|
|
39
40
|
|
|
40
41
|
# language-model-common
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.0.78
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: language-model-common
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.78
|
|
4
4
|
Summary: Provides the underlying framework to enhance langchain and add loading configurations
|
|
5
5
|
Author-email: Imran Qureshi <imran.qureshi@bwell.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -21,7 +21,7 @@ Requires-Dist: openai>=2.5.0
|
|
|
21
21
|
Requires-Dist: langchain-openai>=1.1.6
|
|
22
22
|
Requires-Dist: langgraph>=1.0.0
|
|
23
23
|
Requires-Dist: pydantic<3.0.0,>=2.0
|
|
24
|
-
Requires-Dist: mcp>=1.
|
|
24
|
+
Requires-Dist: mcp>=1.27.2
|
|
25
25
|
Requires-Dist: langgraph-checkpoint>=3.0.0
|
|
26
26
|
Requires-Dist: langgraph-checkpoint-mongodb>=0.3.1
|
|
27
27
|
Requires-Dist: langgraph-store-mongodb>=0.1.0
|
|
@@ -35,6 +35,7 @@ Requires-Dist: fsspec>=2026.2.0
|
|
|
35
35
|
Requires-Dist: authlib>=1.6.5
|
|
36
36
|
Requires-Dist: langchain-google-genai>=4.1.3
|
|
37
37
|
Requires-Dist: py-key-value-aio>=0.4.4
|
|
38
|
+
Requires-Dist: PyJWT[crypto]>=2.8.0
|
|
38
39
|
Dynamic: license-file
|
|
39
40
|
|
|
40
41
|
# language-model-common
|
|
@@ -64,6 +64,8 @@ languagemodelcommon/file_managers/file_manager.py
|
|
|
64
64
|
languagemodelcommon/file_managers/file_manager_factory.py
|
|
65
65
|
languagemodelcommon/file_managers/file_writer.py
|
|
66
66
|
languagemodelcommon/file_managers/local_file_manager.py
|
|
67
|
+
languagemodelcommon/github/__init__.py
|
|
68
|
+
languagemodelcommon/github/token_provider.py
|
|
67
69
|
languagemodelcommon/graph/__init__.py
|
|
68
70
|
languagemodelcommon/graph/graph_builder.py
|
|
69
71
|
languagemodelcommon/history/__init__.py
|
|
@@ -128,6 +130,12 @@ languagemodelcommon/ocr/ocr_extractor.py
|
|
|
128
130
|
languagemodelcommon/ocr/ocr_extractor_factory.py
|
|
129
131
|
languagemodelcommon/persistence/__init__.py
|
|
130
132
|
languagemodelcommon/persistence/persistence_factory.py
|
|
133
|
+
languagemodelcommon/pipeline/__init__.py
|
|
134
|
+
languagemodelcommon/pipeline/context.py
|
|
135
|
+
languagemodelcommon/pipeline/pipeline.py
|
|
136
|
+
languagemodelcommon/pipeline/step.py
|
|
137
|
+
languagemodelcommon/pipeline/output/__init__.py
|
|
138
|
+
languagemodelcommon/pipeline/steps/__init__.py
|
|
131
139
|
languagemodelcommon/schema/__init__.py
|
|
132
140
|
languagemodelcommon/schema/openai/__init__.py
|
|
133
141
|
languagemodelcommon/schema/openai/completions.py
|
|
@@ -178,6 +186,9 @@ languagemodelcommon/utilities/message_preprocessing/message_preprocessor.py
|
|
|
178
186
|
languagemodelcommon/utilities/openai/__init__.py
|
|
179
187
|
languagemodelcommon/utilities/openai/responses_api_converter.py
|
|
180
188
|
languagemodelcommon/utilities/security/__init__.py
|
|
189
|
+
languagemodelcommon/utilities/security/normalize.py
|
|
190
|
+
languagemodelcommon/utilities/security/off_topic_detector.py
|
|
191
|
+
languagemodelcommon/utilities/security/prompt_extraction_detector.py
|
|
181
192
|
languagemodelcommon/utilities/security/prompt_sanitizer.py
|
|
182
193
|
languagemodelcommon/utilities/slash_command/__init__.py
|
|
183
194
|
languagemodelcommon/utilities/slash_command/slash_command_handler.py
|
|
@@ -8,7 +8,7 @@ openai>=2.5.0
|
|
|
8
8
|
langchain-openai>=1.1.6
|
|
9
9
|
langgraph>=1.0.0
|
|
10
10
|
pydantic<3.0.0,>=2.0
|
|
11
|
-
mcp>=1.
|
|
11
|
+
mcp>=1.27.2
|
|
12
12
|
langgraph-checkpoint>=3.0.0
|
|
13
13
|
langgraph-checkpoint-mongodb>=0.3.1
|
|
14
14
|
langgraph-store-mongodb>=0.1.0
|
|
@@ -22,3 +22,4 @@ fsspec>=2026.2.0
|
|
|
22
22
|
authlib>=1.6.5
|
|
23
23
|
langchain-google-genai>=4.1.3
|
|
24
24
|
py-key-value-aio>=0.4.4
|
|
25
|
+
PyJWT[crypto]>=2.8.0
|
|
@@ -16,6 +16,7 @@ from urllib.parse import unquote, urlsplit, urlunsplit
|
|
|
16
16
|
|
|
17
17
|
from key_value.aio.protocols.key_value import AsyncKeyValueProtocol
|
|
18
18
|
|
|
19
|
+
from languagemodelcommon.github.token_provider import GitHubTokenProvider
|
|
19
20
|
from languagemodelcommon.utilities.environment.language_model_common_environment_variables import (
|
|
20
21
|
LanguageModelCommonEnvironmentVariables,
|
|
21
22
|
)
|
|
@@ -43,9 +44,11 @@ class GitHubDirectoryHelper:
|
|
|
43
44
|
*,
|
|
44
45
|
environment_variables: LanguageModelCommonEnvironmentVariables | None = None,
|
|
45
46
|
store: AsyncKeyValueProtocol | None = None,
|
|
47
|
+
token_provider: GitHubTokenProvider | None = None,
|
|
46
48
|
) -> None:
|
|
47
49
|
self._environment_variables = environment_variables
|
|
48
50
|
self._store = store
|
|
51
|
+
self._token_provider = token_provider
|
|
49
52
|
|
|
50
53
|
# ------------------------------------------------------------------
|
|
51
54
|
# Pure / static helpers — no env vars or instance state needed
|
|
@@ -164,7 +167,14 @@ class GitHubDirectoryHelper:
|
|
|
164
167
|
|
|
165
168
|
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
166
169
|
|
|
167
|
-
github_token
|
|
170
|
+
github_token: str | None = None
|
|
171
|
+
if self._token_provider is not None:
|
|
172
|
+
github_token = await self._token_provider.get_token()
|
|
173
|
+
elif env:
|
|
174
|
+
github_token = env.github_token
|
|
175
|
+
else:
|
|
176
|
+
github_token = os.environ.get("GITHUB_TOKEN")
|
|
177
|
+
|
|
168
178
|
downloader = GithubDirectoryDownloader()
|
|
169
179
|
result = await downloader.download(
|
|
170
180
|
source_uri=github_uri,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from typing import Any
|
|
2
3
|
|
|
3
4
|
from simple_container.container.simple_container import SimpleContainer
|
|
@@ -8,6 +9,11 @@ from languagemodelcommon.configs.config_reader.github_directory_helper import (
|
|
|
8
9
|
GitHubDirectoryHelper,
|
|
9
10
|
)
|
|
10
11
|
from languagemodelcommon.configs.config_reader.mcp_json_fetcher import McpJsonFetcher
|
|
12
|
+
from languagemodelcommon.github.token_provider import (
|
|
13
|
+
GitHubAppTokenProvider,
|
|
14
|
+
GitHubTokenProvider,
|
|
15
|
+
StaticTokenProvider,
|
|
16
|
+
)
|
|
11
17
|
from languagemodelcommon.configs.prompt_library.prompt_library_manager import (
|
|
12
18
|
PromptLibraryManager,
|
|
13
19
|
)
|
|
@@ -50,6 +56,34 @@ from languagemodelcommon.utilities.tool_display_name_mapper import (
|
|
|
50
56
|
ToolDisplayNameMapper,
|
|
51
57
|
)
|
|
52
58
|
|
|
59
|
+
_logger = logging.getLogger(__name__)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _build_github_token_provider(
|
|
63
|
+
*,
|
|
64
|
+
env: LanguageModelCommonEnvironmentVariables,
|
|
65
|
+
) -> GitHubTokenProvider | None:
|
|
66
|
+
"""Build GitHub token provider: App credentials > static PAT > None."""
|
|
67
|
+
app_id = env.github_app_id
|
|
68
|
+
private_key = env.github_app_private_key
|
|
69
|
+
installation_id = env.github_app_installation_id
|
|
70
|
+
|
|
71
|
+
if app_id and private_key and installation_id:
|
|
72
|
+
_logger.info("GitHub authentication: using GitHub App (app_id=%s)", app_id)
|
|
73
|
+
return GitHubAppTokenProvider(
|
|
74
|
+
app_id=app_id,
|
|
75
|
+
private_key=private_key,
|
|
76
|
+
installation_id=installation_id,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
token = env.github_token
|
|
80
|
+
if token:
|
|
81
|
+
_logger.info("GitHub authentication: using static token (PAT)")
|
|
82
|
+
return StaticTokenProvider(token=token)
|
|
83
|
+
|
|
84
|
+
_logger.info("GitHub authentication: not configured")
|
|
85
|
+
return None
|
|
86
|
+
|
|
53
87
|
|
|
54
88
|
class LanguageModelCommonContainerFactory:
|
|
55
89
|
@staticmethod
|
|
@@ -82,6 +116,12 @@ class LanguageModelCommonContainerFactory:
|
|
|
82
116
|
).model_config_cache_collection_name,
|
|
83
117
|
),
|
|
84
118
|
)
|
|
119
|
+
container.singleton(
|
|
120
|
+
service_type=GitHubTokenProvider,
|
|
121
|
+
factory=lambda c: _build_github_token_provider(
|
|
122
|
+
env=c.resolve(LanguageModelCommonEnvironmentVariables),
|
|
123
|
+
),
|
|
124
|
+
)
|
|
85
125
|
container.singleton(
|
|
86
126
|
service_type=GitHubDirectoryHelper,
|
|
87
127
|
factory=lambda c: GitHubDirectoryHelper(
|
|
@@ -89,6 +129,7 @@ class LanguageModelCommonContainerFactory:
|
|
|
89
129
|
LanguageModelCommonEnvironmentVariables
|
|
90
130
|
),
|
|
91
131
|
store=c.resolve(KeyValueBaseStore),
|
|
132
|
+
token_provider=c.resolve(GitHubTokenProvider),
|
|
92
133
|
),
|
|
93
134
|
)
|
|
94
135
|
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
import time
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from typing import Protocol, runtime_checkable
|
|
8
|
+
|
|
9
|
+
import httpx
|
|
10
|
+
import jwt
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
_GITHUB_API_BASE = "https://api.github.com"
|
|
15
|
+
_TOKEN_EXPIRY_BUFFER_SECONDS = 300
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@runtime_checkable
|
|
19
|
+
class GitHubTokenProvider(Protocol):
|
|
20
|
+
"""Protocol for providing GitHub authentication tokens."""
|
|
21
|
+
|
|
22
|
+
async def get_token(self) -> str: ...
|
|
23
|
+
|
|
24
|
+
def get_token_sync(self) -> str: ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class StaticTokenProvider:
|
|
28
|
+
"""Returns a pre-configured token (PAT or pre-minted installation token)."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, *, token: str) -> None:
|
|
31
|
+
self._token = token
|
|
32
|
+
|
|
33
|
+
async def get_token(self) -> str:
|
|
34
|
+
return self._token
|
|
35
|
+
|
|
36
|
+
def get_token_sync(self) -> str:
|
|
37
|
+
return self._token
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class GitHubAppTokenProvider:
|
|
41
|
+
"""Mints short-lived installation tokens via GitHub App credentials.
|
|
42
|
+
|
|
43
|
+
Tokens are cached and automatically refreshed 5 minutes before expiry.
|
|
44
|
+
The async path is serialized via asyncio.Lock to prevent duplicate mints.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
*,
|
|
50
|
+
app_id: str,
|
|
51
|
+
private_key: str,
|
|
52
|
+
installation_id: str,
|
|
53
|
+
) -> None:
|
|
54
|
+
self._app_id = app_id
|
|
55
|
+
self._private_key = private_key
|
|
56
|
+
self._installation_id = installation_id
|
|
57
|
+
self._cached_token: str | None = None
|
|
58
|
+
self._cached_expires_at: float = 0.0
|
|
59
|
+
self._lock = asyncio.Lock()
|
|
60
|
+
|
|
61
|
+
async def get_token(self) -> str:
|
|
62
|
+
async with self._lock:
|
|
63
|
+
if self._is_token_valid():
|
|
64
|
+
return self._cached_token # type: ignore[return-value]
|
|
65
|
+
return await self._mint_token()
|
|
66
|
+
|
|
67
|
+
def get_token_sync(self) -> str:
|
|
68
|
+
if self._is_token_valid():
|
|
69
|
+
return self._cached_token # type: ignore[return-value]
|
|
70
|
+
return self._mint_token_sync()
|
|
71
|
+
|
|
72
|
+
def _is_token_valid(self) -> bool:
|
|
73
|
+
return (
|
|
74
|
+
self._cached_token is not None
|
|
75
|
+
and time.time() < self._cached_expires_at - _TOKEN_EXPIRY_BUFFER_SECONDS
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def _build_jwt(self) -> str:
|
|
79
|
+
now = int(time.time())
|
|
80
|
+
payload = {
|
|
81
|
+
"iat": now - 60,
|
|
82
|
+
"exp": now + 600,
|
|
83
|
+
"iss": self._app_id,
|
|
84
|
+
}
|
|
85
|
+
return jwt.encode(payload, self._private_key, algorithm="RS256")
|
|
86
|
+
|
|
87
|
+
def _request_url(self) -> str:
|
|
88
|
+
return f"{_GITHUB_API_BASE}/app/installations/{self._installation_id}/access_tokens"
|
|
89
|
+
|
|
90
|
+
def _request_headers(self) -> dict[str, str]:
|
|
91
|
+
return {
|
|
92
|
+
"Authorization": f"Bearer {self._build_jwt()}",
|
|
93
|
+
"Accept": "application/vnd.github+json",
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
def _cache_response(self, *, data: dict[str, str]) -> str:
|
|
97
|
+
self._cached_token = data["token"]
|
|
98
|
+
self._cached_expires_at = datetime.fromisoformat(
|
|
99
|
+
data["expires_at"].replace("Z", "+00:00")
|
|
100
|
+
).timestamp()
|
|
101
|
+
logger.debug(
|
|
102
|
+
"Minted new GitHub App installation token (expires %s)",
|
|
103
|
+
data["expires_at"],
|
|
104
|
+
)
|
|
105
|
+
return self._cached_token
|
|
106
|
+
|
|
107
|
+
async def _mint_token(self) -> str:
|
|
108
|
+
async with httpx.AsyncClient() as client:
|
|
109
|
+
response = await client.post(
|
|
110
|
+
self._request_url(), headers=self._request_headers()
|
|
111
|
+
)
|
|
112
|
+
response.raise_for_status()
|
|
113
|
+
return self._cache_response(data=response.json())
|
|
114
|
+
|
|
115
|
+
def _mint_token_sync(self) -> str:
|
|
116
|
+
with httpx.Client() as client:
|
|
117
|
+
response = client.post(self._request_url(), headers=self._request_headers())
|
|
118
|
+
response.raise_for_status()
|
|
119
|
+
return self._cache_response(data=response.json())
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any, AsyncGenerator
|
|
5
|
+
|
|
6
|
+
from langchain_core.messages import AnyMessage
|
|
7
|
+
from langchain_core.runnables import RunnableConfig
|
|
8
|
+
from langgraph.graph.state import CompiledStateGraph
|
|
9
|
+
|
|
10
|
+
from languagemodelcommon.state.messages_state import MyMessagesState
|
|
11
|
+
from languagemodelcommon.structures.openai.request.chat_request_wrapper import (
|
|
12
|
+
ChatRequestWrapper,
|
|
13
|
+
)
|
|
14
|
+
from languagemodelcommon.utilities.request_information import RequestInformation
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class PipelineContext:
|
|
19
|
+
"""Shared mutable state that flows through all pipeline steps."""
|
|
20
|
+
|
|
21
|
+
chat_request_wrapper: ChatRequestWrapper
|
|
22
|
+
request: Any = None
|
|
23
|
+
|
|
24
|
+
request_information: RequestInformation | None = None
|
|
25
|
+
|
|
26
|
+
messages: list[AnyMessage] = field(default_factory=list)
|
|
27
|
+
prior_messages: list[AnyMessage] = field(default_factory=list)
|
|
28
|
+
previous_context: dict[str, Any] | None = None
|
|
29
|
+
|
|
30
|
+
state: MyMessagesState | None = None
|
|
31
|
+
config: RunnableConfig | None = None
|
|
32
|
+
graph: CompiledStateGraph[MyMessagesState] | None = None
|
|
33
|
+
|
|
34
|
+
content_stream: AsyncGenerator[str, None] | None = None
|
|
35
|
+
|
|
36
|
+
accumulated_content: str = ""
|
|
37
|
+
response_messages: list[AnyMessage] = field(default_factory=list)
|
|
38
|
+
|
|
39
|
+
conversation_id: str = ""
|
|
40
|
+
user_id: str = ""
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Any, AsyncGenerator, Protocol
|
|
5
|
+
|
|
6
|
+
from languagemodelcommon.pipeline.context import PipelineContext
|
|
7
|
+
from languagemodelcommon.pipeline.step import PipelineStep
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class OutputStep(Protocol):
|
|
13
|
+
def format_response(self, *, context: PipelineContext) -> Any: ...
|
|
14
|
+
def stream_response(
|
|
15
|
+
self, *, context: PipelineContext
|
|
16
|
+
) -> AsyncGenerator[str, None]: ...
|
|
17
|
+
def format_error(self, *, context: PipelineContext, error: Exception) -> Any: ...
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Pipeline:
|
|
21
|
+
"""Runs an ordered list of steps against a shared PipelineContext."""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
*,
|
|
26
|
+
pre_execution_steps: list[PipelineStep],
|
|
27
|
+
execution_step: PipelineStep,
|
|
28
|
+
post_execution_steps: list[PipelineStep],
|
|
29
|
+
output_step: OutputStep,
|
|
30
|
+
) -> None:
|
|
31
|
+
self._pre_execution_steps = pre_execution_steps
|
|
32
|
+
self._execution_step = execution_step
|
|
33
|
+
self._post_execution_steps = post_execution_steps
|
|
34
|
+
self._output_step = output_step
|
|
35
|
+
|
|
36
|
+
async def run_non_streaming(self, *, context: PipelineContext) -> Any:
|
|
37
|
+
try:
|
|
38
|
+
for step in self._pre_execution_steps:
|
|
39
|
+
await step.run(context=context)
|
|
40
|
+
await self._execution_step.run(context=context)
|
|
41
|
+
await self._drain_stream(context=context)
|
|
42
|
+
for step in self._post_execution_steps:
|
|
43
|
+
await step.run(context=context)
|
|
44
|
+
return self._output_step.format_response(context=context)
|
|
45
|
+
except Exception as e:
|
|
46
|
+
return self._output_step.format_error(context=context, error=e)
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
async def _drain_stream(*, context: PipelineContext) -> None:
|
|
50
|
+
"""Consume content_stream fully, populating accumulated_content and response_messages."""
|
|
51
|
+
if context.content_stream is None:
|
|
52
|
+
return
|
|
53
|
+
import json as _json
|
|
54
|
+
|
|
55
|
+
from langchain_core.messages import AIMessage
|
|
56
|
+
|
|
57
|
+
async for chunk in context.content_stream:
|
|
58
|
+
for line in chunk.strip().splitlines():
|
|
59
|
+
if not line.startswith("data: "):
|
|
60
|
+
continue
|
|
61
|
+
payload = line[6:]
|
|
62
|
+
if payload == "[DONE]":
|
|
63
|
+
continue
|
|
64
|
+
try:
|
|
65
|
+
event = _json.loads(payload)
|
|
66
|
+
if "delta" in event and isinstance(event["delta"], str):
|
|
67
|
+
context.accumulated_content += event["delta"]
|
|
68
|
+
elif (
|
|
69
|
+
"choices" in event
|
|
70
|
+
and event["choices"]
|
|
71
|
+
and "delta" in event["choices"][0]
|
|
72
|
+
):
|
|
73
|
+
delta_content = event["choices"][0]["delta"].get("content", "")
|
|
74
|
+
if delta_content:
|
|
75
|
+
context.accumulated_content += delta_content
|
|
76
|
+
except (ValueError, KeyError, IndexError):
|
|
77
|
+
# Non-content SSE events (tool calls, metadata) don't match
|
|
78
|
+
# either delta format — safe to skip during stream draining.
|
|
79
|
+
logger.debug(
|
|
80
|
+
"Skipping non-content SSE event during drain: %s", payload[:100]
|
|
81
|
+
)
|
|
82
|
+
if context.accumulated_content:
|
|
83
|
+
context.response_messages = [AIMessage(content=context.accumulated_content)]
|
|
84
|
+
|
|
85
|
+
async def run_streaming(
|
|
86
|
+
self, *, context: PipelineContext
|
|
87
|
+
) -> AsyncGenerator[Any, None]:
|
|
88
|
+
try:
|
|
89
|
+
for step in self._pre_execution_steps:
|
|
90
|
+
await step.run(context=context)
|
|
91
|
+
await self._execution_step.run(context=context)
|
|
92
|
+
except Exception as e:
|
|
93
|
+
yield self._output_step.format_error(context=context, error=e)
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
async for chunk in self._output_step.stream_response(context=context):
|
|
97
|
+
yield chunk
|
|
98
|
+
|
|
99
|
+
for step in self._post_execution_steps:
|
|
100
|
+
await step.run(context=context)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Protocol
|
|
4
|
+
|
|
5
|
+
from languagemodelcommon.pipeline.context import PipelineContext
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PipelineStep(Protocol):
|
|
9
|
+
"""Protocol for a single step in the request processing pipeline."""
|
|
10
|
+
|
|
11
|
+
async def run(self, *, context: PipelineContext) -> None: ...
|
|
@@ -359,6 +359,18 @@ class LanguageModelCommonEnvironmentVariables(
|
|
|
359
359
|
def github_token(self) -> Optional[str]:
|
|
360
360
|
return os.environ.get("GITHUB_TOKEN")
|
|
361
361
|
|
|
362
|
+
@property
|
|
363
|
+
def github_app_id(self) -> Optional[str]:
|
|
364
|
+
return os.environ.get("GITHUB_APP_ID")
|
|
365
|
+
|
|
366
|
+
@property
|
|
367
|
+
def github_app_private_key(self) -> Optional[str]:
|
|
368
|
+
return os.environ.get("GITHUB_APP_PRIVATE_KEY")
|
|
369
|
+
|
|
370
|
+
@property
|
|
371
|
+
def github_app_installation_id(self) -> Optional[str]:
|
|
372
|
+
return os.environ.get("GITHUB_APP_INSTALLATION_ID")
|
|
373
|
+
|
|
362
374
|
@property
|
|
363
375
|
def plugins_mcp_server(self) -> Optional[str]:
|
|
364
376
|
"""URL of the MCP server that returns plugin MCP configs.
|
|
File without changes
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Input normalization for security detection.
|
|
2
|
+
|
|
3
|
+
Centralizes Unicode normalization, zero-width stripping, and homoglyph
|
|
4
|
+
mapping so both prompt_extraction_detector and off_topic_detector apply
|
|
5
|
+
consistent pre-processing before regex matching.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import re
|
|
9
|
+
import unicodedata
|
|
10
|
+
|
|
11
|
+
REFUSAL_MESSAGE = (
|
|
12
|
+
"I'm here to help you with your medical records. What can I help you with?"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_ZERO_WIDTH_RE = re.compile(
|
|
17
|
+
"[]" # nosec B613
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Cyrillic/Greek characters that visually resemble Latin letters.
|
|
21
|
+
# Covers the practical attack surface for trigger words in our patterns.
|
|
22
|
+
_HOMOGLYPH_MAP: dict[str, str] = {
|
|
23
|
+
# Cyrillic -> Latin
|
|
24
|
+
"А": "A", # А
|
|
25
|
+
"В": "B", # В
|
|
26
|
+
"С": "C", # С
|
|
27
|
+
"Е": "E", # Е
|
|
28
|
+
"Н": "H", # Н
|
|
29
|
+
"К": "K", # К
|
|
30
|
+
"М": "M", # М
|
|
31
|
+
"О": "O", # О
|
|
32
|
+
"Р": "P", # Р
|
|
33
|
+
"Т": "T", # Т
|
|
34
|
+
"Х": "X", # Х
|
|
35
|
+
"а": "a", # а
|
|
36
|
+
"е": "e", # е
|
|
37
|
+
"о": "o", # о
|
|
38
|
+
"р": "p", # р
|
|
39
|
+
"с": "c", # с
|
|
40
|
+
"у": "y", # у
|
|
41
|
+
"х": "x", # х
|
|
42
|
+
"ѕ": "s", # ѕ
|
|
43
|
+
"і": "i", # і
|
|
44
|
+
"ј": "j", # ј
|
|
45
|
+
"һ": "h", # һ
|
|
46
|
+
"ӏ": "l", # ӏ
|
|
47
|
+
# Greek -> Latin
|
|
48
|
+
"Α": "A", # Α
|
|
49
|
+
"Β": "B", # Β
|
|
50
|
+
"Ε": "E", # Ε
|
|
51
|
+
"Η": "H", # Η
|
|
52
|
+
"Ι": "I", # Ι
|
|
53
|
+
"Κ": "K", # Κ
|
|
54
|
+
"Μ": "M", # Μ
|
|
55
|
+
"Ν": "N", # Ν
|
|
56
|
+
"Ο": "O", # Ο
|
|
57
|
+
"Ρ": "P", # Ρ
|
|
58
|
+
"Τ": "T", # Τ
|
|
59
|
+
"Υ": "Y", # Υ
|
|
60
|
+
"Χ": "X", # Χ
|
|
61
|
+
"α": "a", # α (borderline but used in attacks)
|
|
62
|
+
"ο": "o", # ο
|
|
63
|
+
"ρ": "p", # ρ (lowercase rho)
|
|
64
|
+
# Fullwidth Latin -> ASCII Latin
|
|
65
|
+
# NFKC handles most of these, but belt-and-suspenders for the critical ones
|
|
66
|
+
"a": "a",
|
|
67
|
+
"b": "b",
|
|
68
|
+
"c": "c",
|
|
69
|
+
"d": "d",
|
|
70
|
+
"e": "e",
|
|
71
|
+
"i": "i",
|
|
72
|
+
"l": "l",
|
|
73
|
+
"m": "m",
|
|
74
|
+
"n": "n",
|
|
75
|
+
"o": "o",
|
|
76
|
+
"p": "p",
|
|
77
|
+
"r": "r",
|
|
78
|
+
"s": "s",
|
|
79
|
+
"t": "t",
|
|
80
|
+
"u": "u",
|
|
81
|
+
"y": "y",
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_HOMOGLYPH_TRANS = str.maketrans(_HOMOGLYPH_MAP)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def normalize_for_detection(*, text: str) -> str:
|
|
88
|
+
"""Normalize user input for security pattern matching.
|
|
89
|
+
|
|
90
|
+
Applies in order:
|
|
91
|
+
1. NFKC Unicode normalization (collapses compatibility equivalents)
|
|
92
|
+
2. Zero-width character removal
|
|
93
|
+
3. Homoglyph transliteration (Cyrillic/Greek -> Latin)
|
|
94
|
+
4. Whitespace collapse
|
|
95
|
+
"""
|
|
96
|
+
result = unicodedata.normalize("NFKC", text)
|
|
97
|
+
result = _ZERO_WIDTH_RE.sub("", result)
|
|
98
|
+
result = result.translate(_HOMOGLYPH_TRANS)
|
|
99
|
+
result = re.sub(r"\s+", " ", result)
|
|
100
|
+
return result
|