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.
Files changed (204) hide show
  1. {language_model_common-2.0.76/language_model_common.egg-info → language_model_common-2.0.78}/PKG-INFO +3 -2
  2. language_model_common-2.0.78/VERSION +1 -0
  3. {language_model_common-2.0.76 → language_model_common-2.0.78/language_model_common.egg-info}/PKG-INFO +3 -2
  4. {language_model_common-2.0.76 → language_model_common-2.0.78}/language_model_common.egg-info/SOURCES.txt +11 -0
  5. {language_model_common-2.0.76 → language_model_common-2.0.78}/language_model_common.egg-info/requires.txt +2 -1
  6. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/github_directory_helper.py +11 -1
  7. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/container/container_factory.py +41 -0
  8. language_model_common-2.0.78/languagemodelcommon/github/token_provider.py +119 -0
  9. language_model_common-2.0.78/languagemodelcommon/pipeline/context.py +40 -0
  10. language_model_common-2.0.78/languagemodelcommon/pipeline/pipeline.py +100 -0
  11. language_model_common-2.0.78/languagemodelcommon/pipeline/step.py +11 -0
  12. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/environment/language_model_common_environment_variables.py +12 -0
  13. language_model_common-2.0.78/languagemodelcommon/utilities/security/__init__.py +0 -0
  14. language_model_common-2.0.78/languagemodelcommon/utilities/security/normalize.py +100 -0
  15. language_model_common-2.0.78/languagemodelcommon/utilities/security/off_topic_detector.py +96 -0
  16. language_model_common-2.0.78/languagemodelcommon/utilities/security/prompt_extraction_detector.py +69 -0
  17. language_model_common-2.0.78/languagemodelcommon/utilities/slash_command/__init__.py +0 -0
  18. language_model_common-2.0.78/languagemodelcommon/utilities/slash_command/handlers/__init__.py +0 -0
  19. language_model_common-2.0.78/languagemodelcommon/utilities/token_reducer/__init__.py +0 -0
  20. {language_model_common-2.0.76 → language_model_common-2.0.78}/pyproject.toml +3 -2
  21. language_model_common-2.0.76/VERSION +0 -1
  22. {language_model_common-2.0.76 → language_model_common-2.0.78}/LICENSE +0 -0
  23. {language_model_common-2.0.76 → language_model_common-2.0.78}/MANIFEST.in +0 -0
  24. {language_model_common-2.0.76 → language_model_common-2.0.78}/README.md +0 -0
  25. {language_model_common-2.0.76 → language_model_common-2.0.78}/language_model_common.egg-info/dependency_links.txt +0 -0
  26. {language_model_common-2.0.76 → language_model_common-2.0.78}/language_model_common.egg-info/top_level.txt +0 -0
  27. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/__init__.py +0 -0
  28. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/__init__.py +0 -0
  29. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/authenticator/__init__.py +0 -0
  30. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/exceptions/__init__.py +0 -0
  31. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/exceptions/authorization_mcp_tool_token_invalid_exception.py +0 -0
  32. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/exceptions/authorization_token_cache_item_expired_exception.py +0 -0
  33. {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
  34. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/models/__init__.py +0 -0
  35. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/models/token_cache_item.py +0 -0
  36. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/oauth_provider_registrar.py +0 -0
  37. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/pass_through_token_manager.py +0 -0
  38. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/token_exchange/__init__.py +0 -0
  39. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/token_exchange/token_exchange_manager.py +0 -0
  40. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/token_storage_auth_manager.py +0 -0
  41. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/tools/__init__.py +0 -0
  42. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/auth/tools/tool_auth_manager.py +0 -0
  43. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/aws/__init__.py +0 -0
  44. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/aws/aws_client_factory.py +0 -0
  45. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/__init__.py +0 -0
  46. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/__init__.py +0 -0
  47. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/config_reader.py +0 -0
  48. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/file_config_reader.py +0 -0
  49. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/github_directory_downloader.py +0 -0
  50. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/mcp_json_fetcher.py +0 -0
  51. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/mcp_json_reader.py +0 -0
  52. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/config_reader/s3_config_reader.py +0 -0
  53. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/prompt_library/__init__.py +0 -0
  54. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/prompt_library/prompt_library_environment_variables.py +0 -0
  55. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/prompt_library/prompt_library_manager.py +0 -0
  56. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/prompt_library/prompt_store.py +0 -0
  57. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/schemas/__init__.py +0 -0
  58. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/schemas/config_schema.py +0 -0
  59. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/configs/schemas/mcp_json_schema.py +0 -0
  60. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/container/__init__.py +0 -0
  61. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/context/__init__.py +0 -0
  62. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/context/request_context.py +0 -0
  63. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/__init__.py +0 -0
  64. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/langgraph_to_openai_converter.py +0 -0
  65. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/stream_buffer.py +0 -0
  66. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/stream_context_mixin.py +0 -0
  67. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/stream_debug_output_manager.py +0 -0
  68. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/streaming_formatters.py +0 -0
  69. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/streaming_manager.py +0 -0
  70. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/streaming_tool_node.py +0 -0
  71. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/converters/tool_event_handlers.py +0 -0
  72. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/exceptions/__init__.py +0 -0
  73. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/exceptions/bailey_exception.py +0 -0
  74. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/__init__.py +0 -0
  75. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/aws_s3_file_manager.py +0 -0
  76. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/file_manager.py +0 -0
  77. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/file_manager_factory.py +0 -0
  78. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/file_writer.py +0 -0
  79. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/file_managers/local_file_manager.py +0 -0
  80. {language_model_common-2.0.76/languagemodelcommon/graph → language_model_common-2.0.78/languagemodelcommon/github}/__init__.py +0 -0
  81. {language_model_common-2.0.76/languagemodelcommon/history → language_model_common-2.0.78/languagemodelcommon/graph}/__init__.py +0 -0
  82. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/graph/graph_builder.py +0 -0
  83. {language_model_common-2.0.76/languagemodelcommon/http → language_model_common-2.0.78/languagemodelcommon/history}/__init__.py +0 -0
  84. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/history/context_compactor.py +0 -0
  85. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/history/conversation_history_manager.py +0 -0
  86. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/history/smart_history_manager.py +0 -0
  87. {language_model_common-2.0.76/languagemodelcommon/image_generation → language_model_common-2.0.78/languagemodelcommon/http}/__init__.py +0 -0
  88. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/http/http_client_factory.py +0 -0
  89. {language_model_common-2.0.76/languagemodelcommon/image_generation/managers → language_model_common-2.0.78/languagemodelcommon/image_generation}/__init__.py +0 -0
  90. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/aws_image_generator.py +0 -0
  91. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/image_generator.py +0 -0
  92. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/image_generator_factory.py +0 -0
  93. {language_model_common-2.0.76/languagemodelcommon/image_generation/providers → language_model_common-2.0.78/languagemodelcommon/image_generation/managers}/__init__.py +0 -0
  94. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/managers/image_generation_manager.py +0 -0
  95. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/openai_image_generator.py +0 -0
  96. {language_model_common-2.0.76/languagemodelcommon/markdown → language_model_common-2.0.78/languagemodelcommon/image_generation/providers}/__init__.py +0 -0
  97. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/providers/base_image_generation_provider.py +0 -0
  98. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/image_generation/providers/image_generation_provider.py +0 -0
  99. {language_model_common-2.0.76/languagemodelcommon/mcp → language_model_common-2.0.78/languagemodelcommon/markdown}/__init__.py +0 -0
  100. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/markdown/html_to_markdown_converter.py +0 -0
  101. {language_model_common-2.0.76/languagemodelcommon/mcp/auth → language_model_common-2.0.78/languagemodelcommon/mcp}/__init__.py +0 -0
  102. {language_model_common-2.0.76/languagemodelcommon/mcp/exceptions → language_model_common-2.0.78/languagemodelcommon/mcp/auth}/__init__.py +0 -0
  103. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/auth/auth_server_metadata_discovery.py +0 -0
  104. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/auth/mcp_authorization_helper.py +0 -0
  105. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/callbacks.py +0 -0
  106. {language_model_common-2.0.76/languagemodelcommon/mcp/interceptors → language_model_common-2.0.78/languagemodelcommon/mcp/exceptions}/__init__.py +0 -0
  107. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/exceptions/mcp_tool_exception.py +0 -0
  108. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/exceptions/mcp_tool_not_found_exception.py +0 -0
  109. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/exceptions/mcp_tool_unauthorized_exception.py +0 -0
  110. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/exceptions/mcp_tool_unknown_exception.py +0 -0
  111. {language_model_common-2.0.76/languagemodelcommon/mcp/mcp_client → language_model_common-2.0.78/languagemodelcommon/mcp/interceptors}/__init__.py +0 -0
  112. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/interceptors/auth.py +0 -0
  113. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/interceptors/tracing.py +0 -0
  114. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/interceptors/truncation.py +0 -0
  115. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/interceptors/types.py +0 -0
  116. {language_model_common-2.0.76/languagemodelcommon/mocks → language_model_common-2.0.78/languagemodelcommon/mcp/mcp_client}/__init__.py +0 -0
  117. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/content_conversion.py +0 -0
  118. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/langchain_adapter.py +0 -0
  119. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/mcp_app_proxy.py +0 -0
  120. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/mcp_tool_list_store.py +0 -0
  121. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/server_card_discovery.py +0 -0
  122. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/session.py +0 -0
  123. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/session_pool.py +0 -0
  124. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/tool_invocation.py +0 -0
  125. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/tool_list_cache.py +0 -0
  126. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_client/ui_resource.py +0 -0
  127. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/mcp_tool_provider.py +0 -0
  128. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/tool_catalog.py +0 -0
  129. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mcp/tool_discovery_middleware.py +0 -0
  130. {language_model_common-2.0.76/languagemodelcommon/models → language_model_common-2.0.78/languagemodelcommon/mocks}/__init__.py +0 -0
  131. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mocks/mock_aws_client_factory.py +0 -0
  132. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mocks/mock_http_client_factory.py +0 -0
  133. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mocks/mock_image_generator.py +0 -0
  134. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/mocks/mock_image_generator_factory.py +0 -0
  135. {language_model_common-2.0.76/languagemodelcommon/ocr → language_model_common-2.0.78/languagemodelcommon/models}/__init__.py +0 -0
  136. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/models/bedrock_models.py +0 -0
  137. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/models/model_factory.py +0 -0
  138. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/models/sanitizing_bedrock_converse.py +0 -0
  139. {language_model_common-2.0.76/languagemodelcommon/persistence → language_model_common-2.0.78/languagemodelcommon/ocr}/__init__.py +0 -0
  140. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/ocr/aws_ocr_extractor.py +0 -0
  141. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/ocr/ocr_extractor.py +0 -0
  142. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/ocr/ocr_extractor_factory.py +0 -0
  143. {language_model_common-2.0.76/languagemodelcommon/schema → language_model_common-2.0.78/languagemodelcommon/persistence}/__init__.py +0 -0
  144. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/persistence/persistence_factory.py +0 -0
  145. {language_model_common-2.0.76/languagemodelcommon/schema/openai → language_model_common-2.0.78/languagemodelcommon/pipeline}/__init__.py +0 -0
  146. {language_model_common-2.0.76/languagemodelcommon/state → language_model_common-2.0.78/languagemodelcommon/pipeline/output}/__init__.py +0 -0
  147. {language_model_common-2.0.76/languagemodelcommon/structures → language_model_common-2.0.78/languagemodelcommon/pipeline/steps}/__init__.py +0 -0
  148. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/py.typed +0 -0
  149. {language_model_common-2.0.76/languagemodelcommon/structures/openai → language_model_common-2.0.78/languagemodelcommon/schema}/__init__.py +0 -0
  150. {language_model_common-2.0.76/languagemodelcommon/structures/openai/message → language_model_common-2.0.78/languagemodelcommon/schema/openai}/__init__.py +0 -0
  151. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/schema/openai/completions.py +0 -0
  152. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/schema/openai/image_generation.py +0 -0
  153. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/schema/openai/responses.py +0 -0
  154. {language_model_common-2.0.76/languagemodelcommon/structures/openai/request → language_model_common-2.0.78/languagemodelcommon/state}/__init__.py +0 -0
  155. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/state/messages_state.py +0 -0
  156. {language_model_common-2.0.76/languagemodelcommon/tools → language_model_common-2.0.78/languagemodelcommon/structures}/__init__.py +0 -0
  157. {language_model_common-2.0.76/languagemodelcommon/tools/mcp → language_model_common-2.0.78/languagemodelcommon/structures/openai}/__init__.py +0 -0
  158. {language_model_common-2.0.76/languagemodelcommon/utilities → language_model_common-2.0.78/languagemodelcommon/structures/openai/message}/__init__.py +0 -0
  159. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/message/chat_completion_api_message_wrapper.py +0 -0
  160. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/message/chat_message_wrapper.py +0 -0
  161. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/message/responses_api_message_wrapper.py +0 -0
  162. {language_model_common-2.0.76/languagemodelcommon/utilities/cache → language_model_common-2.0.78/languagemodelcommon/structures/openai/request}/__init__.py +0 -0
  163. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/request/chat_completion_api_request_wrapper.py +0 -0
  164. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/request/chat_request_wrapper.py +0 -0
  165. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/structures/openai/request/responses_api_request_wrapper.py +0 -0
  166. {language_model_common-2.0.76/languagemodelcommon/utilities/environment → language_model_common-2.0.78/languagemodelcommon/tools}/__init__.py +0 -0
  167. {language_model_common-2.0.76/languagemodelcommon/utilities/header_reader → language_model_common-2.0.78/languagemodelcommon/tools/mcp}/__init__.py +0 -0
  168. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/tools/mcp/call_tool_tool.py +0 -0
  169. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/tools/mcp/search_tools_tool.py +0 -0
  170. {language_model_common-2.0.76/languagemodelcommon/utilities/logger → language_model_common-2.0.78/languagemodelcommon/utilities}/__init__.py +0 -0
  171. {language_model_common-2.0.76/languagemodelcommon/utilities/message_preprocessing → language_model_common-2.0.78/languagemodelcommon/utilities/cache}/__init__.py +0 -0
  172. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/cache/advisory_lock.py +0 -0
  173. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/cache/model_config_cache_store.py +0 -0
  174. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/chat_message_helpers.py +0 -0
  175. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/config_substitution.py +0 -0
  176. {language_model_common-2.0.76/languagemodelcommon/utilities/openai → language_model_common-2.0.78/languagemodelcommon/utilities/environment}/__init__.py +0 -0
  177. {language_model_common-2.0.76/languagemodelcommon/utilities/security → language_model_common-2.0.78/languagemodelcommon/utilities/header_reader}/__init__.py +0 -0
  178. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/header_reader/header_reader.py +0 -0
  179. {language_model_common-2.0.76/languagemodelcommon/utilities/slash_command → language_model_common-2.0.78/languagemodelcommon/utilities/logger}/__init__.py +0 -0
  180. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/debug_configuration.py +0 -0
  181. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/exception_formatter.py +0 -0
  182. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/exception_logger.py +0 -0
  183. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/log_levels.py +0 -0
  184. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/logging_response.py +0 -0
  185. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/logger/logging_transport.py +0 -0
  186. {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
  187. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/message_preprocessing/composite_message_preprocessor.py +0 -0
  188. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/message_preprocessing/message_preprocessor.py +0 -0
  189. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/mongo_url_utils.py +0 -0
  190. {language_model_common-2.0.76/languagemodelcommon/utilities/token_reducer → language_model_common-2.0.78/languagemodelcommon/utilities/openai}/__init__.py +0 -0
  191. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/openai/responses_api_converter.py +0 -0
  192. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/request_information.py +0 -0
  193. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/s3_url.py +0 -0
  194. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/security/prompt_sanitizer.py +0 -0
  195. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/handlers/debug_command_handler.py +0 -0
  196. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/handlers/skill_command_handler.py +0 -0
  197. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/slash_command_handler.py +0 -0
  198. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/slash_command_parser.py +0 -0
  199. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/slash_command/slash_command_processor.py +0 -0
  200. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/text_humanizer.py +0 -0
  201. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/token_reducer/token_reducer.py +0 -0
  202. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/tool_display_name_mapper.py +0 -0
  203. {language_model_common-2.0.76 → language_model_common-2.0.78}/languagemodelcommon/utilities/url_parser.py +0 -0
  204. {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.76
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.11.0
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.76
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.11.0
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.0
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 = env.github_token if env else os.environ.get("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.
@@ -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