abstractcore 2.4.7__tar.gz → 2.4.8__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 (166) hide show
  1. {abstractcore-2.4.7 → abstractcore-2.4.8}/PKG-INFO +2 -2
  2. {abstractcore-2.4.7 → abstractcore-2.4.8}/README.md +1 -1
  3. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/core/factory.py +1 -1
  4. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/__init__.py +0 -2
  5. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/registry.py +1 -17
  6. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/server/app.py +0 -1
  7. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/utils/version.py +1 -1
  8. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore.egg-info/PKG-INFO +2 -2
  9. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore.egg-info/SOURCES.txt +0 -1
  10. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_basic_session.py +9 -6
  11. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_comprehensive_events.py +10 -4
  12. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_core_components.py +13 -7
  13. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_embeddings_integration.py +4 -1
  14. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_embeddings_llm_integration.py +13 -4
  15. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_embeddings_real.py +1 -1
  16. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_enhanced_prompt.py +3 -3
  17. abstractcore-2.4.8/tests/test_factory.py +54 -0
  18. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_provider_connectivity.py +8 -5
  19. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_provider_simple_generation.py +6 -3
  20. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_provider_streaming.py +18 -6
  21. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_providers.py +1 -1
  22. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_real_models_comprehensive.py +2 -2
  23. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_retry_strategy.py +13 -13
  24. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_seed_determinism.py +6 -6
  25. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_seed_temperature_basic.py +46 -18
  26. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_stream_tool_calling.py +1 -1
  27. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_structured_integration.py +5 -5
  28. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_structured_output.py +10 -10
  29. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_tool_calling.py +1 -1
  30. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_user_scenario_validation.py +6 -6
  31. abstractcore-2.4.7/abstractcore/providers/mock_provider.py +0 -167
  32. abstractcore-2.4.7/tests/test_factory.py +0 -35
  33. {abstractcore-2.4.7 → abstractcore-2.4.8}/LICENSE +0 -0
  34. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/__init__.py +0 -0
  35. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/apps/__init__.py +0 -0
  36. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/apps/__main__.py +0 -0
  37. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/apps/app_config_utils.py +0 -0
  38. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/apps/extractor.py +0 -0
  39. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/apps/judge.py +0 -0
  40. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/apps/summarizer.py +0 -0
  41. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/architectures/__init__.py +0 -0
  42. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/architectures/detection.py +0 -0
  43. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/architectures/enums.py +0 -0
  44. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/assets/architecture_formats.json +0 -0
  45. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/assets/model_capabilities.json +0 -0
  46. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/assets/session_schema.json +0 -0
  47. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/cli/__init__.py +0 -0
  48. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/cli/main.py +0 -0
  49. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/cli/vision_config.py +0 -0
  50. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/core/__init__.py +0 -0
  51. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/core/enums.py +0 -0
  52. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/core/interface.py +0 -0
  53. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/core/retry.py +0 -0
  54. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/core/session.py +0 -0
  55. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/core/types.py +0 -0
  56. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/embeddings/__init__.py +0 -0
  57. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/embeddings/manager.py +0 -0
  58. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/embeddings/models.py +0 -0
  59. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/events/__init__.py +0 -0
  60. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/exceptions/__init__.py +0 -0
  61. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/__init__.py +0 -0
  62. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/auto_handler.py +0 -0
  63. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/base.py +0 -0
  64. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/capabilities.py +0 -0
  65. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/handlers/__init__.py +0 -0
  66. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/handlers/anthropic_handler.py +0 -0
  67. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/handlers/local_handler.py +0 -0
  68. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/handlers/openai_handler.py +0 -0
  69. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/processors/__init__.py +0 -0
  70. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/processors/image_processor.py +0 -0
  71. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/processors/office_processor.py +0 -0
  72. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/processors/pdf_processor.py +0 -0
  73. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/processors/text_processor.py +0 -0
  74. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/types.py +0 -0
  75. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/utils/__init__.py +0 -0
  76. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/utils/image_scaler.py +0 -0
  77. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/media/vision_fallback.py +0 -0
  78. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/processing/__init__.py +0 -0
  79. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/processing/basic_extractor.py +0 -0
  80. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/processing/basic_judge.py +0 -0
  81. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/processing/basic_summarizer.py +0 -0
  82. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/anthropic_provider.py +0 -0
  83. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/base.py +0 -0
  84. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/huggingface_provider.py +0 -0
  85. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/lmstudio_provider.py +0 -0
  86. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/mlx_provider.py +0 -0
  87. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/ollama_provider.py +0 -0
  88. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/openai_provider.py +0 -0
  89. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/providers/streaming.py +0 -0
  90. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/server/__init__.py +0 -0
  91. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/structured/__init__.py +0 -0
  92. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/structured/handler.py +0 -0
  93. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/structured/retry.py +0 -0
  94. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/tools/__init__.py +0 -0
  95. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/tools/common_tools.py +0 -0
  96. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/tools/core.py +0 -0
  97. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/tools/handler.py +0 -0
  98. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/tools/parser.py +0 -0
  99. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/tools/registry.py +0 -0
  100. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/tools/syntax_rewriter.py +0 -0
  101. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/tools/tag_rewriter.py +0 -0
  102. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/utils/__init__.py +0 -0
  103. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/utils/cli.py +0 -0
  104. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/utils/message_preprocessor.py +0 -0
  105. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/utils/self_fixes.py +0 -0
  106. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/utils/structured_logging.py +0 -0
  107. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore/utils/token_utils.py +0 -0
  108. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore.egg-info/dependency_links.txt +0 -0
  109. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore.egg-info/entry_points.txt +0 -0
  110. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore.egg-info/requires.txt +0 -0
  111. {abstractcore-2.4.7 → abstractcore-2.4.8}/abstractcore.egg-info/top_level.txt +0 -0
  112. {abstractcore-2.4.7 → abstractcore-2.4.8}/pyproject.toml +0 -0
  113. {abstractcore-2.4.7 → abstractcore-2.4.8}/setup.cfg +0 -0
  114. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_agentic_cli_compatibility.py +0 -0
  115. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_all_specified_providers.py +0 -0
  116. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_basic_summarizer.py +0 -0
  117. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_cli_media.py +0 -0
  118. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_complete_integration.py +0 -0
  119. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_consistency.py +0 -0
  120. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_critical_streaming_tool_fix.py +0 -0
  121. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_debug_server.py +0 -0
  122. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_direct_vs_server.py +0 -0
  123. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_embeddings.py +0 -0
  124. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_embeddings_matrix_operations.py +0 -0
  125. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_embeddings_no_mock.py +0 -0
  126. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_embeddings_semantic_validation.py +0 -0
  127. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_embeddings_simple.py +0 -0
  128. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_environment_variable_tool_call_tags.py +0 -0
  129. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_final_accuracy.py +0 -0
  130. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_final_comprehensive.py +0 -0
  131. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_final_graceful_errors.py +0 -0
  132. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_fixed_media.py +0 -0
  133. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_fixed_prompt.py +0 -0
  134. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_graceful_fallback.py +0 -0
  135. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_import_debug.py +0 -0
  136. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_integrated_functionality.py +0 -0
  137. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_lmstudio_context.py +0 -0
  138. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_media_import.py +0 -0
  139. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_media_server.py +0 -0
  140. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_ollama_tool_role_fix.py +0 -0
  141. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_openai_conversion_manual.py +0 -0
  142. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_openai_format_bug.py +0 -0
  143. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_openai_format_conversion.py +0 -0
  144. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_openai_media_integration.py +0 -0
  145. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_progressive_complexity.py +0 -0
  146. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_provider_basic_session.py +0 -0
  147. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_provider_token_translation.py +0 -0
  148. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_provider_tool_detection.py +0 -0
  149. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_providers_comprehensive.py +0 -0
  150. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_providers_simple.py +0 -0
  151. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_retry_observability.py +0 -0
  152. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_sensory_prompting.py +0 -0
  153. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_server_debug.py +0 -0
  154. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_server_embeddings_real.py +0 -0
  155. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_server_integration.py +0 -0
  156. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_streaming_enhancements.py +0 -0
  157. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_streaming_tag_rewriting.py +0 -0
  158. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_syntax_rewriter.py +0 -0
  159. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_text_only_model_experience.py +0 -0
  160. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_tool_execution_separation.py +0 -0
  161. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_unified_streaming.py +0 -0
  162. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_unload_memory.py +0 -0
  163. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_vision_accuracy.py +0 -0
  164. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_vision_comprehensive.py +0 -0
  165. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_vision_fallback_improvement.py +0 -0
  166. {abstractcore-2.4.7 → abstractcore-2.4.8}/tests/test_wrong_model_fallback.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractcore
3
- Version: 2.4.7
3
+ Version: 2.4.8
4
4
  Summary: Unified interface to all LLM providers with essential infrastructure for tool calling, streaming, and model management
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
6
6
  Maintainer-email: Laurent-Philippe Albou <contact@abstractcore.ai>
@@ -195,7 +195,7 @@ print(f"Summary: {response.get_summary()}") # "Model: gpt-4o-mini | Toke
195
195
 
196
196
  **Token Count Sources:**
197
197
  - **Provider APIs**: OpenAI, Anthropic, LMStudio (native API token counts)
198
- - **AbstractCore Calculation**: MLX, HuggingFace, Mock (using `token_utils.py`)
198
+ - **AbstractCore Calculation**: MLX, HuggingFace (using `token_utils.py`)
199
199
  - **Mixed Sources**: Ollama (combination of provider and calculated tokens)
200
200
 
201
201
  **Backward Compatibility**: Legacy `prompt_tokens` and `completion_tokens` keys remain available in `response.usage` dictionary.
@@ -95,7 +95,7 @@ print(f"Summary: {response.get_summary()}") # "Model: gpt-4o-mini | Toke
95
95
 
96
96
  **Token Count Sources:**
97
97
  - **Provider APIs**: OpenAI, Anthropic, LMStudio (native API token counts)
98
- - **AbstractCore Calculation**: MLX, HuggingFace, Mock (using `token_utils.py`)
98
+ - **AbstractCore Calculation**: MLX, HuggingFace (using `token_utils.py`)
99
99
  - **Mixed Sources**: Ollama (combination of provider and calculated tokens)
100
100
 
101
101
  **Backward Compatibility**: Legacy `prompt_tokens` and `completion_tokens` keys remain available in `response.usage` dictionary.
@@ -12,7 +12,7 @@ def create_llm(provider: str, model: Optional[str] = None, **kwargs) -> Abstract
12
12
  Create an LLM provider instance with unified token parameter support.
13
13
 
14
14
  Args:
15
- provider: Provider name (openai, anthropic, ollama, huggingface, mlx, lmstudio, mock)
15
+ provider: Provider name (openai, anthropic, ollama, huggingface, mlx, lmstudio)
16
16
  model: Model name (optional, will use provider default)
17
17
  **kwargs: Additional configuration including token parameters
18
18
 
@@ -7,7 +7,6 @@ from .ollama_provider import OllamaProvider
7
7
  from .lmstudio_provider import LMStudioProvider
8
8
  from .huggingface_provider import HuggingFaceProvider
9
9
  from .mlx_provider import MLXProvider
10
- from .mock_provider import MockProvider
11
10
 
12
11
  # Provider registry for centralized provider discovery and management
13
12
  from .registry import (
@@ -32,7 +31,6 @@ __all__ = [
32
31
  'LMStudioProvider',
33
32
  'HuggingFaceProvider',
34
33
  'MLXProvider',
35
- 'MockProvider',
36
34
 
37
35
  # Provider registry
38
36
  'ProviderRegistry',
@@ -136,19 +136,6 @@ class ProviderRegistry:
136
136
  import_path="..providers.huggingface_provider"
137
137
  ))
138
138
 
139
- # Mock Provider
140
- self.register_provider(ProviderInfo(
141
- name="mock",
142
- display_name="Mock",
143
- provider_class=None,
144
- description="Testing provider for development and unit tests",
145
- default_model="mock-model",
146
- supported_features=["chat", "completion", "embeddings", "prompted_tools", "streaming", "testing"],
147
- authentication_required=False,
148
- local_provider=True,
149
- installation_extras=None,
150
- import_path="..providers.mock_provider"
151
- ))
152
139
 
153
140
  def register_provider(self, provider_info: ProviderInfo):
154
141
  """Register a provider in the registry."""
@@ -182,10 +169,7 @@ class ProviderRegistry:
182
169
  def _load_provider_class(self, provider_info: ProviderInfo):
183
170
  """Dynamically load a provider class."""
184
171
  try:
185
- if provider_info.name == "mock":
186
- from ..providers.mock_provider import MockProvider
187
- return MockProvider
188
- elif provider_info.name == "openai":
172
+ if provider_info.name == "openai":
189
173
  from ..providers.openai_provider import OpenAIProvider
190
174
  return OpenAIProvider
191
175
  elif provider_info.name == "anthropic":
@@ -1101,7 +1101,6 @@ async def list_providers():
1101
1101
  - **LMStudio**: Local model development and testing platform
1102
1102
  - **MLX**: Apple Silicon optimized local inference
1103
1103
  - **HuggingFace**: Access to HuggingFace models (transformers and embeddings)
1104
- - **Mock**: Testing provider for development
1105
1104
 
1106
1105
  **Use Cases:**
1107
1106
  - Discover available providers before making requests
@@ -11,4 +11,4 @@ including when the package is installed from PyPI where pyproject.toml is not av
11
11
 
12
12
  # Package version - update this when releasing new versions
13
13
  # This must be manually synchronized with the version in pyproject.toml
14
- __version__ = "2.4.7"
14
+ __version__ = "2.4.8"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractcore
3
- Version: 2.4.7
3
+ Version: 2.4.8
4
4
  Summary: Unified interface to all LLM providers with essential infrastructure for tool calling, streaming, and model management
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
6
6
  Maintainer-email: Laurent-Philippe Albou <contact@abstractcore.ai>
@@ -195,7 +195,7 @@ print(f"Summary: {response.get_summary()}") # "Model: gpt-4o-mini | Toke
195
195
 
196
196
  **Token Count Sources:**
197
197
  - **Provider APIs**: OpenAI, Anthropic, LMStudio (native API token counts)
198
- - **AbstractCore Calculation**: MLX, HuggingFace, Mock (using `token_utils.py`)
198
+ - **AbstractCore Calculation**: MLX, HuggingFace (using `token_utils.py`)
199
199
  - **Mixed Sources**: Ollama (combination of provider and calculated tokens)
200
200
 
201
201
  **Backward Compatibility**: Legacy `prompt_tokens` and `completion_tokens` keys remain available in `response.usage` dictionary.
@@ -62,7 +62,6 @@ abstractcore/providers/base.py
62
62
  abstractcore/providers/huggingface_provider.py
63
63
  abstractcore/providers/lmstudio_provider.py
64
64
  abstractcore/providers/mlx_provider.py
65
- abstractcore/providers/mock_provider.py
66
65
  abstractcore/providers/ollama_provider.py
67
66
  abstractcore/providers/openai_provider.py
68
67
  abstractcore/providers/registry.py
@@ -6,7 +6,7 @@ import pytest
6
6
  from datetime import datetime
7
7
  from abstractcore.core.session import BasicSession
8
8
  from abstractcore.core.types import Message
9
- from abstractcore.providers.mock_provider import MockProvider
9
+ from abstractcore.providers.openai_provider import OpenAIProvider
10
10
 
11
11
 
12
12
  class TestBasicSession:
@@ -65,14 +65,17 @@ class TestBasicSession:
65
65
  session.clear_history(keep_system=False)
66
66
  assert len(session.messages) == 0
67
67
 
68
- def test_generation_with_mock_provider(self):
69
- """Test generation with mock provider"""
70
- provider = MockProvider()
71
- session = BasicSession(provider=provider)
68
+ def test_generation_with_openai_provider(self):
69
+ """Test generation with OpenAI provider"""
70
+ try:
71
+ provider = OpenAIProvider()
72
+ session = BasicSession(provider=provider)
73
+ except ImportError:
74
+ pytest.skip("OpenAI provider not available")
72
75
 
73
76
  response = session.generate("Hello")
74
77
  assert response.content is not None
75
- assert "Mock response" in response.content
78
+ assert len(response.content) > 0
76
79
  assert len(session.messages) == 2 # user + assistant
77
80
 
78
81
  def test_persistence(self, tmp_path):
@@ -212,14 +212,17 @@ class TestEventHandlerPatterns:
212
212
  class TestProviderEvents:
213
213
  """Test events emitted by providers"""
214
214
 
215
- def test_mock_provider_events(self, event_capture):
216
- """Test that mock provider emits expected events"""
215
+ def test_openai_provider_events(self, event_capture):
216
+ """Test that OpenAI provider emits expected events"""
217
217
  # Register event listener for generation events only (PROVIDER_CREATED removed)
218
218
  on_global(EventType.GENERATION_STARTED, event_capture.capture_event)
219
219
  on_global(EventType.GENERATION_COMPLETED, event_capture.capture_event)
220
220
 
221
221
  # Create provider and generate response
222
- llm = create_llm("mock", model="test-model")
222
+ try:
223
+ llm = create_llm("openai", model="gpt-4o")
224
+ except ImportError:
225
+ pytest.skip("OpenAI provider not available")
223
226
  response = llm.generate("Test prompt")
224
227
 
225
228
  # Verify generation events were emitted
@@ -302,7 +305,10 @@ class TestStructuredOutputEvents:
302
305
  on_global(EventType.VALIDATION_FAILED, event_capture.capture_event)
303
306
 
304
307
  # Create provider and generate structured response
305
- llm = create_llm("mock", model="test-model")
308
+ try:
309
+ llm = create_llm("openai", model="gpt-4o")
310
+ except ImportError:
311
+ pytest.skip("OpenAI provider not available")
306
312
 
307
313
  # Test with invalid JSON to trigger validation failure
308
314
  with patch.object(llm, '_generate_internal') as mock_generate:
@@ -137,10 +137,13 @@ class TestBasicSession:
137
137
  class TestProviderFactory:
138
138
  """Test provider factory"""
139
139
 
140
- def test_create_mock_provider(self):
141
- """Test creating mock provider"""
142
- provider = create_llm("mock")
143
- assert provider is not None
140
+ def test_create_openai_provider(self):
141
+ """Test creating OpenAI provider"""
142
+ try:
143
+ provider = create_llm("openai")
144
+ assert provider is not None
145
+ except ImportError:
146
+ pytest.skip("OpenAI provider not available")
144
147
  assert isinstance(provider, AbstractCoreInterface)
145
148
 
146
149
  def test_create_ollama_provider(self):
@@ -303,9 +306,12 @@ class TestProviderIntegration:
303
306
  assert response.content is not None
304
307
 
305
308
  def test_session_with_provider(self):
306
- """Test session with mock provider"""
307
- provider = create_llm("mock")
308
- session = BasicSession(provider=provider, system_prompt="Test system")
309
+ """Test session with OpenAI provider"""
310
+ try:
311
+ provider = create_llm("openai")
312
+ session = BasicSession(provider=provider, system_prompt="Test system")
313
+ except ImportError:
314
+ pytest.skip("OpenAI provider not available")
309
315
 
310
316
  response = session.generate("Hello")
311
317
  assert response is not None
@@ -204,7 +204,10 @@ class TestLLMEmbeddingIntegration:
204
204
  mock_llm = mock_create_llm.return_value
205
205
  mock_llm.generate.return_value = "Mock response"
206
206
 
207
- llm = create_llm("mock", model="test")
207
+ try:
208
+ llm = create_llm("openai", model="gpt-4o")
209
+ except ImportError:
210
+ pytest.skip("OpenAI provider not available")
208
211
 
209
212
  # Use both independently
210
213
  embedding = embedder.embed("Test text")
@@ -43,8 +43,11 @@ class TestEmbeddingsLLMIntegration:
43
43
  assert len(embedding) == 384
44
44
  assert all(isinstance(x, (int, float)) for x in embedding)
45
45
 
46
- # Create LLM provider (mock to avoid API calls)
47
- llm = create_llm("mock")
46
+ # Create LLM provider (OpenAI if available)
47
+ try:
48
+ llm = create_llm("openai")
49
+ except ImportError:
50
+ pytest.skip("OpenAI provider not available")
48
51
 
49
52
  # Verify both work independently
50
53
  similarity = embedder.compute_similarity("test 1", "test 2")
@@ -73,7 +76,10 @@ class TestEmbeddingsLLMIntegration:
73
76
  model="sentence-transformers/all-MiniLM-L6-v2",
74
77
  cache_dir=self.cache_dir
75
78
  )
76
- llm = create_llm("mock")
79
+ try:
80
+ llm = create_llm("openai")
81
+ except ImportError:
82
+ pytest.skip("OpenAI provider not available")
77
83
 
78
84
  # Real knowledge base
79
85
  knowledge_base = [
@@ -221,7 +227,10 @@ Based on the provided context, please answer the question:"""
221
227
  model="sentence-transformers/all-MiniLM-L6-v2",
222
228
  cache_dir=self.cache_dir
223
229
  )
224
- llm = create_llm("mock")
230
+ try:
231
+ llm = create_llm("openai")
232
+ except ImportError:
233
+ pytest.skip("OpenAI provider not available")
225
234
  session = BasicSession(llm)
226
235
 
227
236
  # Test session with embedding-enhanced prompts
@@ -273,7 +273,7 @@ class TestLLMIntegrationReal:
273
273
  # Test that LLM creation doesn't interfere with embeddings
274
274
  try:
275
275
  # This might fail if no LLM providers are configured, which is fine
276
- llm = create_llm("mock") # Use mock provider to avoid API calls
276
+ llm = create_llm("openai") # Use OpenAI provider if available
277
277
  print("✅ LLM and embeddings can coexist")
278
278
  except Exception:
279
279
  print("✅ LLM creation failed as expected (no real providers configured)")
@@ -20,7 +20,7 @@ def test_enhanced_prompt_structure():
20
20
  # Create a test LocalMediaHandler for text-only model
21
21
  handler = LocalMediaHandler("ollama", {"vision_support": False})
22
22
 
23
- # Create mock MediaContent
23
+ # Create test MediaContent
24
24
  media_content = MediaContent(
25
25
  content="test-image-content",
26
26
  media_type=MediaType.IMAGE,
@@ -29,13 +29,13 @@ def test_enhanced_prompt_structure():
29
29
  metadata={"file_name": "arc_de_triomphe.jpg"}
30
30
  )
31
31
 
32
- # Set a mock file path
32
+ # Set a test file path
33
33
  media_content.file_path = "/tmp/test_image.jpg"
34
34
 
35
35
  print("1. Testing prompt construction...")
36
36
  print(" User question: 'What is in this image?'")
37
37
 
38
- # This would normally call the vision fallback, but we'll mock the result
38
+ # This would normally call the vision fallback, but we'll simulate the result
39
39
  # to show the prompt structure without actually processing an image
40
40
 
41
41
  print("\n2. Expected prompt structure sent to text-only model:")
@@ -0,0 +1,54 @@
1
+ """
2
+ Test the factory function.
3
+ """
4
+
5
+ import pytest
6
+ from abstractcore import create_llm
7
+ from abstractcore.providers.openai_provider import OpenAIProvider
8
+ from abstractcore.providers.anthropic_provider import AnthropicProvider
9
+
10
+
11
+ class TestFactory:
12
+ """Test create_llm factory function"""
13
+
14
+ def test_create_openai_provider(self):
15
+ """Test creating OpenAI provider"""
16
+ try:
17
+ llm = create_llm("openai")
18
+ assert isinstance(llm, OpenAIProvider)
19
+ assert llm.model == "gpt-5-nano-2025-08-07" # Default model
20
+ except ImportError:
21
+ pytest.skip("OpenAI dependencies not available")
22
+
23
+ def test_create_anthropic_provider(self):
24
+ """Test creating Anthropic provider"""
25
+ try:
26
+ llm = create_llm("anthropic")
27
+ assert isinstance(llm, AnthropicProvider)
28
+ assert llm.model == "claude-3-5-haiku-latest" # Default model
29
+ except ImportError:
30
+ pytest.skip("Anthropic dependencies not available")
31
+
32
+ def test_create_provider_with_custom_model(self):
33
+ """Test creating provider with custom model"""
34
+ try:
35
+ llm = create_llm("openai", model="gpt-4o")
36
+ assert llm.model == "gpt-4o"
37
+ except ImportError:
38
+ pytest.skip("OpenAI dependencies not available")
39
+
40
+ def test_unknown_provider_raises_error(self):
41
+ """Test unknown provider raises error"""
42
+ with pytest.raises(ValueError, match="Unknown provider"):
43
+ create_llm("nonexistent")
44
+
45
+ def test_provider_case_insensitive(self):
46
+ """Test provider names are case insensitive"""
47
+ try:
48
+ llm1 = create_llm("OPENAI")
49
+ llm2 = create_llm("OpenAI")
50
+ llm3 = create_llm("openai")
51
+
52
+ assert all(isinstance(llm, OpenAIProvider) for llm in [llm1, llm2, llm3])
53
+ except ImportError:
54
+ pytest.skip("OpenAI dependencies not available")
@@ -88,11 +88,14 @@ class TestProviderConnectivity:
88
88
  else:
89
89
  raise
90
90
 
91
- def test_mock_connectivity(self):
92
- """Test Mock provider can be created."""
93
- provider = create_llm("mock", model="test-model")
94
- assert provider is not None
95
- assert provider.model == "test-model"
91
+ def test_openai_connectivity(self):
92
+ """Test OpenAI provider can be created."""
93
+ try:
94
+ provider = create_llm("openai", model="gpt-4o")
95
+ assert provider is not None
96
+ except ImportError:
97
+ pytest.skip("OpenAI provider not available")
98
+ assert provider.model == "gpt-4o"
96
99
 
97
100
 
98
101
  if __name__ == "__main__":
@@ -148,9 +148,12 @@ class TestProviderSimpleGeneration:
148
148
  else:
149
149
  raise
150
150
 
151
- def test_mock_simple_generation(self):
152
- """Test Mock provider simple generation."""
153
- provider = create_llm("mock", model="test-model")
151
+ def test_openai_simple_generation(self):
152
+ """Test OpenAI provider simple generation."""
153
+ try:
154
+ provider = create_llm("openai", model="gpt-4o")
155
+ except ImportError:
156
+ pytest.skip("OpenAI provider not available")
154
157
 
155
158
  response = provider.generate("Who are you? Answer in one sentence.")
156
159
 
@@ -197,9 +197,12 @@ class TestProviderStreaming:
197
197
  else:
198
198
  raise
199
199
 
200
- def test_mock_streaming_basic(self):
201
- """Test Mock provider streaming functionality."""
202
- provider = create_llm("mock", model="test-model")
200
+ def test_openai_streaming_basic(self):
201
+ """Test OpenAI provider streaming functionality."""
202
+ try:
203
+ provider = create_llm("openai", model="gpt-4o")
204
+ except ImportError:
205
+ pytest.skip("OpenAI provider not available")
203
206
 
204
207
  # Test streaming
205
208
  stream = provider.generate(
@@ -304,7 +307,10 @@ class TestProviderStreaming:
304
307
 
305
308
  def test_streaming_chunk_structure(self):
306
309
  """Test that streaming chunks have proper structure."""
307
- provider = create_llm("mock", model="test-model")
310
+ try:
311
+ provider = create_llm("openai", model="gpt-4o")
312
+ except ImportError:
313
+ pytest.skip("OpenAI provider not available")
308
314
 
309
315
  stream = provider.generate("Test prompt", stream=True)
310
316
 
@@ -321,7 +327,10 @@ class TestProviderStreaming:
321
327
 
322
328
  def test_streaming_interruption(self):
323
329
  """Test that streaming can be interrupted gracefully."""
324
- provider = create_llm("mock", model="test-model")
330
+ try:
331
+ provider = create_llm("openai", model="gpt-4o")
332
+ except ImportError:
333
+ pytest.skip("OpenAI provider not available")
325
334
 
326
335
  stream = provider.generate("Long response test", stream=True)
327
336
 
@@ -337,7 +346,10 @@ class TestProviderStreaming:
337
346
 
338
347
  def test_streaming_empty_response(self):
339
348
  """Test streaming behavior with empty or minimal responses."""
340
- provider = create_llm("mock", model="test-model")
349
+ try:
350
+ provider = create_llm("openai", model="gpt-4o")
351
+ except ImportError:
352
+ pytest.skip("OpenAI provider not available")
341
353
 
342
354
  stream = provider.generate("", stream=True) # Empty prompt
343
355
 
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Test all providers with real implementations.
3
- No mocking - test actual provider connections.
3
+ No mocking - test actual provider connections and functionality.
4
4
  """
5
5
 
6
6
  import pytest
@@ -289,8 +289,8 @@ class TestRealLLMIntegration:
289
289
  cache_dir=self.cache_dir
290
290
  )
291
291
 
292
- # Use mock LLM to avoid API calls but test structure
293
- llm = create_llm("mock")
292
+ # Use OpenAI LLM for testing structure
293
+ llm = create_llm("openai")
294
294
 
295
295
  # Real knowledge base
296
296
  knowledge_base = [
@@ -420,8 +420,8 @@ class TestRetryManager:
420
420
  # No retry_success event in minimal approach - success is implicit
421
421
 
422
422
 
423
- class MockProvider(BaseProvider):
424
- """Mock provider for testing integration."""
423
+ class TestRetryProvider(BaseProvider):
424
+ """Test provider for retry integration testing."""
425
425
 
426
426
  def __init__(self, model: str = "test-model", **kwargs):
427
427
  super().__init__(model, **kwargs)
@@ -452,11 +452,11 @@ class TestBaseProviderIntegration:
452
452
 
453
453
  def test_provider_initialization_with_retry(self):
454
454
  """Test provider initializes with retry manager."""
455
- provider = MockProvider("test-model")
455
+ provider = TestRetryProvider("test-model")
456
456
 
457
457
  assert hasattr(provider, 'retry_manager')
458
458
  assert isinstance(provider.retry_manager, RetryManager)
459
- assert provider.provider_key == "MockProvider:test-model"
459
+ assert provider.provider_key == "TestRetryProvider:test-model"
460
460
 
461
461
  def test_structured_output_retry_strategy_parameter(self):
462
462
  """Test passing retry_strategy parameter to generate method."""
@@ -467,7 +467,7 @@ class TestBaseProviderIntegration:
467
467
  name: str
468
468
  value: int
469
469
 
470
- provider = MockProvider("test-model")
470
+ provider = TestRetryProvider("test-model")
471
471
  custom_retry = FeedbackRetry(max_attempts=5)
472
472
 
473
473
  # Test that we can pass retry_strategy parameter without error
@@ -500,7 +500,7 @@ class TestBaseProviderIntegration:
500
500
  name: str
501
501
  value: int
502
502
 
503
- provider = MockProvider("test-model")
503
+ provider = TestRetryProvider("test-model")
504
504
 
505
505
  def mock_generate(*args, **kwargs):
506
506
  return GenerateResponse(
@@ -524,14 +524,14 @@ class TestBaseProviderIntegration:
524
524
  def test_provider_custom_retry_config(self):
525
525
  """Test provider with custom retry configuration."""
526
526
  custom_config = RetryConfig(max_attempts=5)
527
- provider = MockProvider("test-model", retry_config=custom_config)
527
+ provider = TestRetryProvider("test-model", retry_config=custom_config)
528
528
 
529
529
  assert provider.retry_manager.config.max_attempts == 5
530
530
 
531
531
  @patch('abstractcore.providers.base.time.sleep')
532
532
  def test_provider_retry_on_failure(self, mock_sleep):
533
533
  """Test provider retries on API failures."""
534
- provider = MockProvider("test-model")
534
+ provider = TestRetryProvider("test-model")
535
535
 
536
536
  # Mock _generate_internal to fail then succeed
537
537
  original_generate = provider._generate_internal
@@ -555,7 +555,7 @@ class TestBaseProviderIntegration:
555
555
 
556
556
  def test_provider_no_retry_on_auth_error(self):
557
557
  """Test provider doesn't retry on authentication errors."""
558
- provider = MockProvider("test-model")
558
+ provider = TestRetryProvider("test-model")
559
559
 
560
560
  # Mock _generate_internal to always fail with auth error
561
561
  provider._generate_internal = Mock(side_effect=AuthenticationError("Invalid API key"))
@@ -569,7 +569,7 @@ class TestBaseProviderIntegration:
569
569
  @patch('abstractcore.events.emit_global')
570
570
  def test_provider_retry_events(self, mock_emit):
571
571
  """Test provider emits retry events."""
572
- provider = MockProvider("test-model")
572
+ provider = TestRetryProvider("test-model")
573
573
 
574
574
  # Mock _generate_internal to fail once then succeed
575
575
  call_count = 0
@@ -688,7 +688,7 @@ class TestIntegrationScenarios:
688
688
  @patch('abstractcore.events.emit_global')
689
689
  def test_rate_limit_recovery_scenario(self, mock_emit, mock_sleep):
690
690
  """Test realistic rate limit recovery scenario."""
691
- provider = MockProvider("gpt-4")
691
+ provider = TestRetryProvider("gpt-4")
692
692
 
693
693
  # Simulate rate limit that clears after retries
694
694
  call_count = 0
@@ -719,7 +719,7 @@ class TestIntegrationScenarios:
719
719
  def test_circuit_breaker_prevents_cascade_failure(self):
720
720
  """Test circuit breaker prevents cascade failures."""
721
721
  config = RetryConfig(failure_threshold=2, max_attempts=1)
722
- provider = MockProvider("failing-model", retry_config=config)
722
+ provider = TestRetryProvider("failing-model", retry_config=config)
723
723
 
724
724
  # Mock to always fail
725
725
  provider._generate_internal = Mock(side_effect=ProviderAPIError("Service down"))
@@ -740,7 +740,7 @@ class TestIntegrationScenarios:
740
740
 
741
741
  def test_mixed_error_types_scenario(self):
742
742
  """Test handling of mixed error types in sequence."""
743
- provider = MockProvider("mixed-errors")
743
+ provider = TestRetryProvider("mixed-errors")
744
744
 
745
745
  call_count = 0
746
746
  def mixed_errors(*args, **kwargs):
@@ -252,12 +252,12 @@ def test_ollama_seed_determinism():
252
252
 
253
253
  def test_session_seed_persistence():
254
254
  """Test that session-level seed parameters work correctly"""
255
- # Use mock provider for this test to avoid external dependencies
255
+ # Use OpenAI provider for this test if available
256
256
  try:
257
- from abstractcore.providers.mock_provider import MockProvider
257
+ from abstractcore.providers.openai_provider import OpenAIProvider
258
258
 
259
259
  # Create session with seed
260
- provider = MockProvider(model="mock-model", temperature=0.0, seed=42)
260
+ provider = OpenAIProvider(model="gpt-4o", temperature=0.0, seed=42)
261
261
  session = BasicSession(provider=provider, temperature=0.0, seed=42)
262
262
 
263
263
  # Generate multiple responses
@@ -266,11 +266,11 @@ def test_session_seed_persistence():
266
266
  response = session.generate("Test prompt")
267
267
  responses.append(response.content)
268
268
 
269
- # Mock provider should be consistent
270
- assert len(set(responses)) <= 2, "Session should maintain some consistency"
269
+ # With seed, responses should be deterministic
270
+ assert len(set(responses)) <= 2, "Session should maintain some consistency with seed"
271
271
 
272
272
  except ImportError:
273
- pytest.skip("MockProvider not available")
273
+ pytest.skip("OpenAI provider not available")
274
274
 
275
275
 
276
276
  def test_temperature_zero_consistency():