language-model-common 4.0.0__tar.gz → 4.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. {language_model_common-4.0.0/language_model_common.egg-info → language_model_common-4.2.0}/PKG-INFO +3 -1
  2. language_model_common-4.2.0/VERSION +1 -0
  3. {language_model_common-4.0.0 → language_model_common-4.2.0/language_model_common.egg-info}/PKG-INFO +3 -1
  4. {language_model_common-4.0.0 → language_model_common-4.2.0}/language_model_common.egg-info/SOURCES.txt +4 -0
  5. {language_model_common-4.0.0 → language_model_common-4.2.0}/language_model_common.egg-info/requires.txt +2 -0
  6. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/config_reader/config_reader.py +382 -7
  7. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/config_reader/github_directory_downloader.py +44 -20
  8. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/config_reader/github_directory_helper.py +106 -12
  9. language_model_common-4.2.0/languagemodelcommon/configs/config_reader/override_config_cache.py +191 -0
  10. language_model_common-4.2.0/languagemodelcommon/configs/config_reader/override_read_result.py +29 -0
  11. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/container/container_factory.py +40 -0
  12. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/tool_event_handlers.py +62 -12
  13. language_model_common-4.2.0/languagemodelcommon/mcp/mcp_client/cached_output_validation.py +267 -0
  14. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/langchain_adapter.py +6 -0
  15. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/tool_invocation.py +41 -0
  16. language_model_common-4.2.0/languagemodelcommon/utilities/cache/model_config_cache_store.py +165 -0
  17. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/environment/language_model_common_environment_variables.py +73 -0
  18. language_model_common-4.2.0/languagemodelcommon/utilities/learned_title_store.py +161 -0
  19. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/tool_display_name_mapper.py +110 -4
  20. {language_model_common-4.0.0 → language_model_common-4.2.0}/pyproject.toml +2 -0
  21. language_model_common-4.0.0/VERSION +0 -1
  22. language_model_common-4.0.0/languagemodelcommon/utilities/cache/model_config_cache_store.py +0 -75
  23. {language_model_common-4.0.0 → language_model_common-4.2.0}/LICENSE +0 -0
  24. {language_model_common-4.0.0 → language_model_common-4.2.0}/MANIFEST.in +0 -0
  25. {language_model_common-4.0.0 → language_model_common-4.2.0}/README.md +0 -0
  26. {language_model_common-4.0.0 → language_model_common-4.2.0}/language_model_common.egg-info/dependency_links.txt +0 -0
  27. {language_model_common-4.0.0 → language_model_common-4.2.0}/language_model_common.egg-info/top_level.txt +0 -0
  28. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/__init__.py +0 -0
  29. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/auth/__init__.py +0 -0
  30. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/auth/authenticator/__init__.py +0 -0
  31. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/auth/exceptions/__init__.py +0 -0
  32. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/auth/models/__init__.py +0 -0
  33. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/aws/__init__.py +0 -0
  34. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/aws/aws_client_factory.py +0 -0
  35. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/__init__.py +0 -0
  36. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/config_reader/__init__.py +0 -0
  37. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/config_reader/file_config_reader.py +0 -0
  38. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/config_reader/mcp_json_fetcher.py +0 -0
  39. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/config_reader/mcp_json_reader.py +0 -0
  40. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/config_reader/s3_config_reader.py +0 -0
  41. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/prompt_library/__init__.py +0 -0
  42. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/prompt_library/prompt_library_environment_variables.py +0 -0
  43. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/prompt_library/prompt_library_manager.py +0 -0
  44. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/prompt_library/prompt_store.py +0 -0
  45. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/schemas/__init__.py +0 -0
  46. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/schemas/config_schema.py +0 -0
  47. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/configs/schemas/mcp_json_schema.py +0 -0
  48. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/container/__init__.py +0 -0
  49. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/context/__init__.py +0 -0
  50. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/context/request_context.py +0 -0
  51. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/__init__.py +0 -0
  52. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/history_cache_middleware.py +0 -0
  53. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/langgraph_to_openai_converter.py +0 -0
  54. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/stream_buffer.py +0 -0
  55. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/stream_context_mixin.py +0 -0
  56. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/stream_debug_output_manager.py +0 -0
  57. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/streaming_formatters.py +0 -0
  58. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/streaming_manager.py +0 -0
  59. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/converters/streaming_tool_node.py +0 -0
  60. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/exceptions/__init__.py +0 -0
  61. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/exceptions/bailey_exception.py +0 -0
  62. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/exceptions/rate_limit_exception.py +0 -0
  63. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/file_managers/__init__.py +0 -0
  64. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/file_managers/aws_s3_file_manager.py +0 -0
  65. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/file_managers/file_manager.py +0 -0
  66. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/file_managers/file_manager_factory.py +0 -0
  67. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/file_managers/file_writer.py +0 -0
  68. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/file_managers/local_file_manager.py +0 -0
  69. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/github/__init__.py +0 -0
  70. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/github/token_provider.py +0 -0
  71. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/graph/__init__.py +0 -0
  72. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/graph/graph_builder.py +0 -0
  73. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/history/__init__.py +0 -0
  74. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/history/context_compactor.py +0 -0
  75. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/history/conversation_history_manager.py +0 -0
  76. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/history/smart_history_manager.py +0 -0
  77. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/http/__init__.py +0 -0
  78. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/http/http_client_factory.py +0 -0
  79. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/__init__.py +0 -0
  80. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/aws_image_generator.py +0 -0
  81. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/image_generator.py +0 -0
  82. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/image_generator_factory.py +0 -0
  83. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/managers/__init__.py +0 -0
  84. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/managers/image_generation_manager.py +0 -0
  85. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/openai_image_generator.py +0 -0
  86. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/providers/__init__.py +0 -0
  87. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/providers/base_image_generation_provider.py +0 -0
  88. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/image_generation/providers/image_generation_provider.py +0 -0
  89. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/markdown/__init__.py +0 -0
  90. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/markdown/html_to_markdown_converter.py +0 -0
  91. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/__init__.py +0 -0
  92. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/auth/__init__.py +0 -0
  93. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/callbacks.py +0 -0
  94. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/exceptions/__init__.py +0 -0
  95. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/interceptors/__init__.py +0 -0
  96. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/interceptors/redaction.py +0 -0
  97. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/interceptors/tracing.py +0 -0
  98. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/interceptors/truncation.py +0 -0
  99. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/interceptors/types.py +0 -0
  100. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/__init__.py +0 -0
  101. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/content_conversion.py +0 -0
  102. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/mcp_tool_list_store.py +0 -0
  103. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/negotiation_mode.py +0 -0
  104. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/server_card_discovery.py +0 -0
  105. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/session.py +0 -0
  106. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/session_pool.py +0 -0
  107. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mcp/mcp_client/tool_list_cache.py +0 -0
  108. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mocks/__init__.py +0 -0
  109. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mocks/mock_aws_client_factory.py +0 -0
  110. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mocks/mock_http_client_factory.py +0 -0
  111. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mocks/mock_image_generator.py +0 -0
  112. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/mocks/mock_image_generator_factory.py +0 -0
  113. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/models/__init__.py +0 -0
  114. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/models/bedrock_models.py +0 -0
  115. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/models/model_factory.py +0 -0
  116. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/models/sanitizing_bedrock_converse.py +0 -0
  117. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/ocr/__init__.py +0 -0
  118. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/ocr/aws_ocr_extractor.py +0 -0
  119. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/ocr/ocr_extractor.py +0 -0
  120. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/ocr/ocr_extractor_factory.py +0 -0
  121. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/persistence/__init__.py +0 -0
  122. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/persistence/persistence_factory.py +0 -0
  123. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/pipeline/__init__.py +0 -0
  124. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/pipeline/context.py +0 -0
  125. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/pipeline/output/__init__.py +0 -0
  126. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/pipeline/pipeline.py +0 -0
  127. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/pipeline/step.py +0 -0
  128. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/pipeline/steps/__init__.py +0 -0
  129. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/py.typed +0 -0
  130. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/schema/__init__.py +0 -0
  131. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/schema/openai/__init__.py +0 -0
  132. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/schema/openai/completions.py +0 -0
  133. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/schema/openai/image_generation.py +0 -0
  134. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/schema/openai/responses.py +0 -0
  135. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/state/__init__.py +0 -0
  136. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/state/messages_state.py +0 -0
  137. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/__init__.py +0 -0
  138. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/__init__.py +0 -0
  139. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/message/__init__.py +0 -0
  140. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/message/chat_completion_api_message_wrapper.py +0 -0
  141. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/message/chat_message_wrapper.py +0 -0
  142. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/message/responses_api_message_wrapper.py +0 -0
  143. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/request/__init__.py +0 -0
  144. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/request/chat_completion_api_request_wrapper.py +0 -0
  145. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/request/chat_request_wrapper.py +0 -0
  146. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/structures/openai/request/responses_api_request_wrapper.py +0 -0
  147. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/tools/__init__.py +0 -0
  148. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/tools/mcp/__init__.py +0 -0
  149. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/__init__.py +0 -0
  150. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/cache/__init__.py +0 -0
  151. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/chat_message_helpers.py +0 -0
  152. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/config_substitution.py +0 -0
  153. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/environment/__init__.py +0 -0
  154. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/header_reader/__init__.py +0 -0
  155. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/header_reader/header_reader.py +0 -0
  156. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/logger/__init__.py +0 -0
  157. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/logger/debug_configuration.py +0 -0
  158. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/logger/exception_formatter.py +0 -0
  159. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/logger/exception_logger.py +0 -0
  160. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/logger/log_levels.py +0 -0
  161. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/logger/logging_response.py +0 -0
  162. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/logger/logging_transport.py +0 -0
  163. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/logger/summarization.py +0 -0
  164. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/message_preprocessing/__init__.py +0 -0
  165. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/message_preprocessing/composite_message_preprocessor.py +0 -0
  166. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/message_preprocessing/message_preprocessor.py +0 -0
  167. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/mongo_url_utils.py +0 -0
  168. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/openai/__init__.py +0 -0
  169. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/openai/responses_api_converter.py +0 -0
  170. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/ref_hash.py +0 -0
  171. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/request_information.py +0 -0
  172. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/s3_url.py +0 -0
  173. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/security/__init__.py +0 -0
  174. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/security/normalize.py +0 -0
  175. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/security/off_topic_detector.py +0 -0
  176. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/security/prompt_extraction_detector.py +0 -0
  177. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/security/prompt_sanitizer.py +0 -0
  178. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/security/url_validation.py +0 -0
  179. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/slash_command/__init__.py +0 -0
  180. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/slash_command/handlers/__init__.py +0 -0
  181. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/slash_command/handlers/debug_command_handler.py +0 -0
  182. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/slash_command/handlers/skill_command_handler.py +0 -0
  183. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/slash_command/slash_command_handler.py +0 -0
  184. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/slash_command/slash_command_parser.py +0 -0
  185. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/slash_command/slash_command_processor.py +0 -0
  186. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/text_humanizer.py +0 -0
  187. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/token_reducer/__init__.py +0 -0
  188. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/token_reducer/token_reducer.py +0 -0
  189. {language_model_common-4.0.0 → language_model_common-4.2.0}/languagemodelcommon/utilities/url_parser.py +0 -0
  190. {language_model_common-4.0.0 → language_model_common-4.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: language-model-common
3
- Version: 4.0.0
3
+ Version: 4.2.0
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
@@ -22,6 +22,8 @@ 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
24
  Requires-Dist: mcp>=2.3.0
25
+ Requires-Dist: jsonschema>=4.26.0
26
+ Requires-Dist: referencing>=0.37.0
25
27
  Requires-Dist: langgraph-checkpoint>=3.0.0
26
28
  Requires-Dist: langgraph-checkpoint-mongodb>=0.3.1
27
29
  Requires-Dist: langgraph-store-mongodb>=0.1.0
@@ -0,0 +1 @@
1
+ 4.2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: language-model-common
3
- Version: 4.0.0
3
+ Version: 4.2.0
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
@@ -22,6 +22,8 @@ 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
24
  Requires-Dist: mcp>=2.3.0
25
+ Requires-Dist: jsonschema>=4.26.0
26
+ Requires-Dist: referencing>=0.37.0
25
27
  Requires-Dist: langgraph-checkpoint>=3.0.0
26
28
  Requires-Dist: langgraph-checkpoint-mongodb>=0.3.1
27
29
  Requires-Dist: langgraph-store-mongodb>=0.1.0
@@ -24,6 +24,8 @@ languagemodelcommon/configs/config_reader/github_directory_downloader.py
24
24
  languagemodelcommon/configs/config_reader/github_directory_helper.py
25
25
  languagemodelcommon/configs/config_reader/mcp_json_fetcher.py
26
26
  languagemodelcommon/configs/config_reader/mcp_json_reader.py
27
+ languagemodelcommon/configs/config_reader/override_config_cache.py
28
+ languagemodelcommon/configs/config_reader/override_read_result.py
27
29
  languagemodelcommon/configs/config_reader/s3_config_reader.py
28
30
  languagemodelcommon/configs/prompt_library/__init__.py
29
31
  languagemodelcommon/configs/prompt_library/prompt_library_environment_variables.py
@@ -87,6 +89,7 @@ languagemodelcommon/mcp/interceptors/tracing.py
87
89
  languagemodelcommon/mcp/interceptors/truncation.py
88
90
  languagemodelcommon/mcp/interceptors/types.py
89
91
  languagemodelcommon/mcp/mcp_client/__init__.py
92
+ languagemodelcommon/mcp/mcp_client/cached_output_validation.py
90
93
  languagemodelcommon/mcp/mcp_client/content_conversion.py
91
94
  languagemodelcommon/mcp/mcp_client/langchain_adapter.py
92
95
  languagemodelcommon/mcp/mcp_client/mcp_tool_list_store.py
@@ -139,6 +142,7 @@ languagemodelcommon/tools/mcp/__init__.py
139
142
  languagemodelcommon/utilities/__init__.py
140
143
  languagemodelcommon/utilities/chat_message_helpers.py
141
144
  languagemodelcommon/utilities/config_substitution.py
145
+ languagemodelcommon/utilities/learned_title_store.py
142
146
  languagemodelcommon/utilities/mongo_url_utils.py
143
147
  languagemodelcommon/utilities/ref_hash.py
144
148
  languagemodelcommon/utilities/request_information.py
@@ -9,6 +9,8 @@ langchain-openai>=1.1.6
9
9
  langgraph>=1.0.0
10
10
  pydantic<3.0.0,>=2.0
11
11
  mcp>=2.3.0
12
+ jsonschema>=4.26.0
13
+ referencing>=0.37.0
12
14
  langgraph-checkpoint>=3.0.0
13
15
  langgraph-checkpoint-mongodb>=0.3.1
14
16
  langgraph-store-mongodb>=0.1.0
@@ -1,6 +1,9 @@
1
1
  import asyncio
2
2
  import logging
3
+ import re
4
+ import time
3
5
 
6
+ from hashlib import sha256
4
7
  from pathlib import Path
5
8
  from typing import Any, List, Optional, cast
6
9
  from uuid import UUID, uuid4
@@ -11,7 +14,17 @@ from languagemodelcommon.configs.config_reader.file_config_reader import (
11
14
  from languagemodelcommon.configs.config_reader.github_directory_helper import (
12
15
  GitHubDirectoryHelper,
13
16
  )
17
+ from languagemodelcommon.configs.config_reader.override_config_cache import (
18
+ CachedOverride,
19
+ ClientOverrideConfigCache,
20
+ )
21
+ from languagemodelcommon.configs.config_reader.override_read_result import (
22
+ DownloadLockHeldError,
23
+ OverrideOutcome,
24
+ OverrideReadResult,
25
+ )
14
26
  from languagemodelcommon.configs.config_reader.s3_config_reader import S3ConfigReader
27
+ from oidcauthlib.cache_gate.advisory_lock import AdvisoryLock
15
28
  from languagemodelcommon.configs.schemas.config_schema import (
16
29
  ChatModelConfig,
17
30
  PromptConfig,
@@ -34,6 +47,13 @@ from languagemodelcommon.configs.config_reader.mcp_json_reader import (
34
47
  logger = logging.getLogger(__name__)
35
48
  logger.setLevel(SRC_LOG_LEVELS.CONFIG)
36
49
 
50
+ _MAX_CLIENT_ID_LENGTH = 64
51
+ _COLD_MISS_TIMEOUT_SECONDS = 180.0
52
+ _OVERRIDE_PEER_POLL_INTERVAL_SECONDS = 0.05
53
+ _OVERRIDE_PEER_POLL_TIMEOUT_SECONDS = 3.0
54
+ _OVERRIDE_REFRESH_LOCK_TTL_SECONDS = 60
55
+ _OVERRIDE_REFRESH_RETRY_AFTER_SECONDS = 15.0
56
+
37
57
 
38
58
  class ConfigReader:
39
59
  SCHEMA_VERSION = 1
@@ -48,6 +68,7 @@ class ConfigReader:
48
68
  model_config_cache_store: BaseStore | None = None,
49
69
  file_config_reader: FileConfigReader | None = None,
50
70
  s3_config_reader: S3ConfigReader | None = None,
71
+ override_config_cache: ClientOverrideConfigCache | None = None,
51
72
  ) -> None:
52
73
  self._identifier: UUID = uuid4()
53
74
  self._lock: asyncio.Lock = asyncio.Lock()
@@ -65,6 +86,13 @@ class ConfigReader:
65
86
  self._model_config_cache_collection = (
66
87
  self._environment_variables.model_config_cache_collection_name
67
88
  )
89
+ self._override_config_cache = override_config_cache
90
+ # In-flight override refreshes by cache key, so concurrent requests in
91
+ # this process share one refresh. Holds tasks only, removed on completion;
92
+ # it is not a cache of config data.
93
+ self._inflight_override_refreshes: dict[
94
+ str, asyncio.Task[OverrideReadResult]
95
+ ] = {}
68
96
 
69
97
  async def read_model_configs_async(
70
98
  self, *, client_id: str | None = None
@@ -316,12 +344,76 @@ class ConfigReader:
316
344
  )
317
345
  if override_path is None:
318
346
  return []
347
+ cache = self._override_config_cache
348
+ if (
349
+ cache is None
350
+ or not self._environment_variables.model_config_override_cache_enabled
351
+ or not self._is_remote_config_path(config_path=config_path)
352
+ or not self._is_cacheable_client_id(client_id=client_id)
353
+ ):
354
+ # Flag off, no store, local path, or an id that must not become a
355
+ # cache key: read live exactly as before the cache existed.
356
+ result = await self._fetch_override_result(
357
+ override_path=override_path, confirm_absent=False
358
+ )
359
+ return list(result.models)
360
+ return await self._read_override_models_cached(
361
+ cache=cache,
362
+ config_path=config_path,
363
+ override_path=override_path,
364
+ client_id=client_id,
365
+ )
366
+
367
+ @staticmethod
368
+ def _is_cacheable_client_id(*, client_id: str) -> bool:
369
+ """Stricter than ``_is_valid_client_id``: applies only where a cache key
370
+ is built, so flag-off behaviour for existing ids is unchanged."""
371
+ return len(client_id) <= _MAX_CLIENT_ID_LENGTH and bool(
372
+ re.fullmatch(r"[a-zA-Z0-9_-]+", client_id)
373
+ )
374
+
375
+ @staticmethod
376
+ def _is_remote_config_path(*, config_path: str) -> bool:
377
+ return GitHubDirectoryHelper.is_github_path(
378
+ config_path
379
+ ) or config_path.startswith("s3")
380
+
381
+ async def _fetch_override_result(
382
+ self, *, override_path: str, confirm_absent: bool
383
+ ) -> OverrideReadResult:
384
+ """Read one override from its source and classify the outcome.
385
+
386
+ A bare ``FileNotFoundError`` is ambiguous (fsspec raises it for any
387
+ non-2xx reply, e.g. a bad token or rate limit). With ``confirm_absent``
388
+ it is classified ``ABSENT`` only after GitHub positively shows the
389
+ directory is missing; otherwise ``FAILED``.
390
+ """
319
391
  try:
320
- return await self.read_models_from_path_async(
321
- config_path=override_path, log_diagnostics_on_not_found=False
392
+ models = await self.read_models_from_path_async(
393
+ config_path=override_path,
394
+ log_diagnostics_on_not_found=False,
395
+ # Strict only on the cached path; flag-off keeps the pre-cache
396
+ # fallback to the pod-local copy when the lock is held.
397
+ raise_on_lock_held=confirm_absent,
322
398
  )
323
- except (FileNotFoundError, ValueError) as e:
324
- if "FileNotFoundError" in str(e) or isinstance(e, FileNotFoundError):
399
+ except DownloadLockHeldError:
400
+ logger.info(
401
+ "ConfigReader with id: %s override download lock held for %s",
402
+ self._identifier,
403
+ override_path,
404
+ )
405
+ return OverrideReadResult(outcome=OverrideOutcome.LOCK_HELD)
406
+ except FileNotFoundError:
407
+ logger.debug(
408
+ "No client overrides found at %s (path does not exist)", override_path
409
+ )
410
+ if confirm_absent and not await self._confirm_override_absent(
411
+ override_path=override_path
412
+ ):
413
+ return OverrideReadResult(outcome=OverrideOutcome.FAILED)
414
+ return OverrideReadResult(outcome=OverrideOutcome.ABSENT)
415
+ except ValueError as e:
416
+ if "FileNotFoundError" in str(e):
325
417
  logger.debug(
326
418
  "No client overrides found at %s (path does not exist)",
327
419
  override_path,
@@ -330,12 +422,285 @@ class ConfigReader:
330
422
  logger.warning(
331
423
  "Failed to load client overrides from %s: %s", override_path, e
332
424
  )
333
- return []
425
+ return OverrideReadResult(outcome=OverrideOutcome.FAILED)
334
426
  except Exception as e:
335
427
  logger.warning(
336
428
  "Failed to load client overrides from %s: %s", override_path, e
337
429
  )
430
+ return OverrideReadResult(outcome=OverrideOutcome.FAILED)
431
+ return OverrideReadResult(
432
+ outcome=OverrideOutcome.FOUND,
433
+ models=tuple(models),
434
+ has_unresolved_mcp=self._has_unresolved_mcp_servers(models),
435
+ )
436
+
437
+ async def _confirm_override_absent(self, *, override_path: str) -> bool:
438
+ if not GitHubDirectoryHelper.is_github_path(override_path):
439
+ return False
440
+ return await self._github_directory_helper.confirm_directory_absent(
441
+ github_uri=GitHubDirectoryHelper.to_github_uri(override_path)
442
+ )
443
+
444
+ async def _read_override_models_cached(
445
+ self,
446
+ *,
447
+ cache: ClientOverrideConfigCache,
448
+ config_path: str,
449
+ override_path: str,
450
+ client_id: str,
451
+ ) -> List[ChatModelConfig]:
452
+ """Read-through, stale-while-revalidate read of one client's override."""
453
+ started = time.monotonic()
454
+ cached = await self._safe_override_cache_get(
455
+ cache=cache, config_path=config_path, client_id=client_id
456
+ )
457
+ if cached is not None:
458
+ if cached.is_fresh:
459
+ outcome = (
460
+ "hit"
461
+ if cached.result.outcome == OverrideOutcome.FOUND
462
+ else "absent_hit"
463
+ )
464
+ else:
465
+ outcome = "stale"
466
+ self._start_override_refresh(
467
+ cache=cache,
468
+ config_path=config_path,
469
+ override_path=override_path,
470
+ client_id=client_id,
471
+ stale=cached,
472
+ )
473
+ self._log_override_read(
474
+ outcome=outcome,
475
+ client_id=client_id,
476
+ age=cached.age_seconds,
477
+ started=started,
478
+ )
479
+ return list(cached.result.models)
480
+
481
+ task = self._start_override_refresh(
482
+ cache=cache,
483
+ config_path=config_path,
484
+ override_path=override_path,
485
+ client_id=client_id,
486
+ stale=None,
487
+ )
488
+ # shield: a cancelled request must not cancel a refresh others share.
489
+ try:
490
+ result = await asyncio.wait_for(
491
+ asyncio.shield(task), timeout=_COLD_MISS_TIMEOUT_SECONDS
492
+ )
493
+ except asyncio.TimeoutError:
494
+ logger.warning(
495
+ "ConfigReader with id: %s override refresh for client %s exceeded %.0fs; "
496
+ "serving base config for this request",
497
+ self._identifier,
498
+ client_id,
499
+ _COLD_MISS_TIMEOUT_SECONDS,
500
+ )
338
501
  return []
502
+ self._log_override_read(
503
+ outcome="miss", client_id=client_id, age=0.0, started=started
504
+ )
505
+ return list(result.models)
506
+
507
+ def _start_override_refresh(
508
+ self,
509
+ *,
510
+ cache: ClientOverrideConfigCache,
511
+ config_path: str,
512
+ override_path: str,
513
+ client_id: str,
514
+ stale: CachedOverride | None,
515
+ ) -> "asyncio.Task[OverrideReadResult]":
516
+ key = cache.build_key(config_path=config_path, client_id=client_id)
517
+ existing = self._inflight_override_refreshes.get(key)
518
+ if existing is not None:
519
+ return existing
520
+ task = asyncio.ensure_future(
521
+ self._refresh_override(
522
+ cache=cache,
523
+ key=key,
524
+ config_path=config_path,
525
+ override_path=override_path,
526
+ client_id=client_id,
527
+ stale=stale,
528
+ )
529
+ )
530
+ self._inflight_override_refreshes[key] = task
531
+ task.add_done_callback(
532
+ lambda _t: self._inflight_override_refreshes.pop(key, None)
533
+ )
534
+ return task
535
+
536
+ async def _refresh_override(
537
+ self,
538
+ *,
539
+ cache: ClientOverrideConfigCache,
540
+ key: str,
541
+ config_path: str,
542
+ override_path: str,
543
+ client_id: str,
544
+ stale: CachedOverride | None,
545
+ ) -> OverrideReadResult:
546
+ """Refresh one override under a cross-worker advisory lock.
547
+
548
+ Never raises: a failure keeps stale data (if any) and returns the
549
+ classified result. LOCK_HELD and FAILED are never written to the cache.
550
+ """
551
+ try:
552
+ lock_name = (
553
+ f"override_refresh:{sha256(key.encode('utf-8')).hexdigest()[:16]}"
554
+ )
555
+ async with AdvisoryLock(
556
+ cache.store,
557
+ lock_name,
558
+ ttl_seconds=_OVERRIDE_REFRESH_LOCK_TTL_SECONDS,
559
+ ) as acquired:
560
+ if not acquired:
561
+ # Another worker is refreshing. Serve stale if we have it;
562
+ # else wait (bounded) for its row. There is no "fetch
563
+ # directly" bypass: the downloader has its own lock, so it
564
+ # would only return lock-held anyway. On timeout, return
565
+ # LOCK_HELD (no override for this request, nothing cached),
566
+ # the same outcome the uncached path gives.
567
+ if stale is not None:
568
+ return stale.result
569
+ peer = await self._await_peer_override(
570
+ cache=cache, config_path=config_path, client_id=client_id
571
+ )
572
+ if peer is not None:
573
+ return peer.result
574
+ return OverrideReadResult(outcome=OverrideOutcome.LOCK_HELD)
575
+ return await self._fetch_and_store_override(
576
+ cache=cache,
577
+ config_path=config_path,
578
+ override_path=override_path,
579
+ client_id=client_id,
580
+ stale=stale,
581
+ )
582
+ except Exception as e:
583
+ logger.warning(
584
+ "override_refresh unexpected error for client %s: [%s] %s",
585
+ client_id,
586
+ type(e).__name__,
587
+ e,
588
+ )
589
+ if stale is not None:
590
+ return stale.result
591
+ return OverrideReadResult(outcome=OverrideOutcome.FAILED)
592
+
593
+ async def _await_peer_override(
594
+ self,
595
+ *,
596
+ cache: ClientOverrideConfigCache,
597
+ config_path: str,
598
+ client_id: str,
599
+ ) -> CachedOverride | None:
600
+ """Poll briefly for the lock holder's row; None if it never appears."""
601
+ deadline = time.monotonic() + _OVERRIDE_PEER_POLL_TIMEOUT_SECONDS
602
+ while time.monotonic() < deadline:
603
+ await asyncio.sleep(_OVERRIDE_PEER_POLL_INTERVAL_SECONDS)
604
+ peer = await self._safe_override_cache_get(
605
+ cache=cache, config_path=config_path, client_id=client_id
606
+ )
607
+ if peer is not None:
608
+ return peer
609
+ return None
610
+
611
+ async def _fetch_and_store_override(
612
+ self,
613
+ *,
614
+ cache: ClientOverrideConfigCache,
615
+ config_path: str,
616
+ override_path: str,
617
+ client_id: str,
618
+ stale: CachedOverride | None,
619
+ ) -> OverrideReadResult:
620
+ started = time.monotonic()
621
+ result = await self._fetch_override_result(
622
+ override_path=override_path, confirm_absent=True
623
+ )
624
+ duration_ms = int((time.monotonic() - started) * 1000)
625
+ served_stale = False
626
+ try:
627
+ if result.outcome in (OverrideOutcome.FOUND, OverrideOutcome.ABSENT):
628
+ await cache.put(
629
+ config_path=config_path, client_id=client_id, result=result
630
+ )
631
+ elif stale is not None:
632
+ served_stale = True
633
+ await cache.defer_refresh(
634
+ config_path=config_path,
635
+ client_id=client_id,
636
+ cached=stale,
637
+ retry_after_seconds=_OVERRIDE_REFRESH_RETRY_AFTER_SECONDS,
638
+ )
639
+ except Exception as e:
640
+ logger.warning(
641
+ "override_cache write failed for client %s: [%s] %s",
642
+ client_id,
643
+ type(e).__name__,
644
+ e,
645
+ )
646
+ logger.info(
647
+ "override_refresh result=%s download_ms=%d served_stale=%s client_id=%s",
648
+ result.outcome.value,
649
+ duration_ms,
650
+ served_stale,
651
+ client_id,
652
+ )
653
+ if stale is not None and result.outcome in (
654
+ OverrideOutcome.FAILED,
655
+ OverrideOutcome.LOCK_HELD,
656
+ ):
657
+ return stale.result
658
+ return result
659
+
660
+ async def _safe_override_cache_get(
661
+ self,
662
+ *,
663
+ cache: ClientOverrideConfigCache,
664
+ config_path: str,
665
+ client_id: str,
666
+ ) -> CachedOverride | None:
667
+ """Cache read that degrades to a live read if the store errors.
668
+
669
+ The override cache is an optimisation layer, so a store or row
670
+ deserialisation error is logged and treated as a miss (unlike the base
671
+ model-config cache, which fails fast).
672
+ """
673
+ try:
674
+ return await cache.get(config_path=config_path, client_id=client_id)
675
+ except Exception as e:
676
+ logger.warning(
677
+ "override_cache read failed for client %s, using live read: [%s] %s",
678
+ client_id,
679
+ type(e).__name__,
680
+ e,
681
+ )
682
+ return None
683
+
684
+ def _log_override_read(
685
+ self, *, outcome: str, client_id: str, age: float, started: float
686
+ ) -> None:
687
+ logger.info(
688
+ "override_cache outcome=%s age_s=%.1f duration_ms=%d client_id=%s",
689
+ outcome,
690
+ age,
691
+ int((time.monotonic() - started) * 1000),
692
+ client_id,
693
+ )
694
+
695
+ async def clear_client_override(self, *, client_id: str) -> None:
696
+ """Drop one client's cached override so the next request re-reads it."""
697
+ cache = self._override_config_cache
698
+ if cache is None or not self._is_valid_client_id(client_id):
699
+ return
700
+ await cache.delete(
701
+ config_path=self._environment_variables.models_official_path,
702
+ client_id=client_id,
703
+ )
339
704
 
340
705
  async def read_models_from_path_async(
341
706
  self,
@@ -343,8 +708,13 @@ class ConfigReader:
343
708
  config_path: str,
344
709
  exclude_dirs: set[str] | None = None,
345
710
  log_diagnostics_on_not_found: bool = True,
711
+ raise_on_lock_held: bool = False,
346
712
  ) -> List[ChatModelConfig]:
347
713
  """
714
+ raise_on_lock_held (BAI-1380): when the GitHub download lock is held by
715
+ another worker, raise ``DownloadLockHeldError`` instead of returning
716
+ ``[]``, so callers can tell "nothing read" from "no models".
717
+
348
718
  log_diagnostics_on_not_found (BAI-941): pass ``False`` when a missing
349
719
  ``config_path`` is an expected, benign outcome for this caller (e.g.
350
720
  an optional per-client override) rather than a genuine failure worth
@@ -363,8 +733,11 @@ class ConfigReader:
363
733
  resolved = await self._github_directory_helper.resolve_github_path(
364
734
  config_path,
365
735
  log_diagnostics_on_not_found=log_diagnostics_on_not_found,
736
+ raise_on_lock_held=raise_on_lock_held,
366
737
  )
367
738
  if resolved is None:
739
+ if raise_on_lock_held:
740
+ raise DownloadLockHeldError(config_path)
368
741
  logger.info(
369
742
  "ConfigReader with id: %s download lock held for %s — using cache",
370
743
  self._identifier,
@@ -372,7 +745,8 @@ class ConfigReader:
372
745
  )
373
746
  return []
374
747
  local_config_path = str(resolved)
375
- models = self._file_config_reader.read_model_configs(
748
+ models = await asyncio.to_thread(
749
+ self._file_config_reader.read_model_configs,
376
750
  config_path=local_config_path,
377
751
  exclude_dirs=exclude_dirs,
378
752
  )
@@ -382,7 +756,8 @@ class ConfigReader:
382
756
  len(models),
383
757
  )
384
758
  else:
385
- models = self._file_config_reader.read_model_configs(
759
+ models = await asyncio.to_thread(
760
+ self._file_config_reader.read_model_configs,
386
761
  config_path=config_path,
387
762
  exclude_dirs=exclude_dirs,
388
763
  )