abstractcore 2.4.3__tar.gz → 2.4.4__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 (149) hide show
  1. {abstractcore-2.4.3 → abstractcore-2.4.4}/PKG-INFO +1 -1
  2. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/base.py +97 -0
  3. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/huggingface_provider.py +17 -8
  4. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/utils/version.py +1 -1
  5. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore.egg-info/PKG-INFO +1 -1
  6. {abstractcore-2.4.3 → abstractcore-2.4.4}/LICENSE +0 -0
  7. {abstractcore-2.4.3 → abstractcore-2.4.4}/README.md +0 -0
  8. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/__init__.py +0 -0
  9. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/apps/__init__.py +0 -0
  10. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/apps/__main__.py +0 -0
  11. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/apps/app_config_utils.py +0 -0
  12. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/apps/extractor.py +0 -0
  13. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/apps/judge.py +0 -0
  14. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/apps/summarizer.py +0 -0
  15. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/architectures/__init__.py +0 -0
  16. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/architectures/detection.py +0 -0
  17. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/architectures/enums.py +0 -0
  18. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/assets/architecture_formats.json +0 -0
  19. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/assets/model_capabilities.json +0 -0
  20. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/assets/session_schema.json +0 -0
  21. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/core/__init__.py +0 -0
  22. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/core/enums.py +0 -0
  23. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/core/factory.py +0 -0
  24. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/core/interface.py +0 -0
  25. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/core/retry.py +0 -0
  26. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/core/session.py +0 -0
  27. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/core/types.py +0 -0
  28. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/embeddings/__init__.py +0 -0
  29. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/embeddings/manager.py +0 -0
  30. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/embeddings/models.py +0 -0
  31. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/events/__init__.py +0 -0
  32. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/exceptions/__init__.py +0 -0
  33. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/media/__init__.py +0 -0
  34. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/media/auto_handler.py +0 -0
  35. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/media/base.py +0 -0
  36. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/media/capabilities.py +0 -0
  37. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/media/types.py +0 -0
  38. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/media/vision_fallback.py +0 -0
  39. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/processing/__init__.py +0 -0
  40. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/processing/basic_extractor.py +0 -0
  41. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/processing/basic_judge.py +0 -0
  42. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/processing/basic_summarizer.py +0 -0
  43. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/__init__.py +0 -0
  44. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/anthropic_provider.py +0 -0
  45. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/lmstudio_provider.py +0 -0
  46. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/mlx_provider.py +0 -0
  47. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/mock_provider.py +0 -0
  48. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/ollama_provider.py +0 -0
  49. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/openai_provider.py +0 -0
  50. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/registry.py +0 -0
  51. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/providers/streaming.py +0 -0
  52. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/server/__init__.py +0 -0
  53. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/server/app.py +0 -0
  54. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/structured/__init__.py +0 -0
  55. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/structured/handler.py +0 -0
  56. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/structured/retry.py +0 -0
  57. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/tools/__init__.py +0 -0
  58. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/tools/common_tools.py +0 -0
  59. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/tools/core.py +0 -0
  60. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/tools/handler.py +0 -0
  61. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/tools/parser.py +0 -0
  62. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/tools/registry.py +0 -0
  63. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/tools/syntax_rewriter.py +0 -0
  64. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/tools/tag_rewriter.py +0 -0
  65. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/utils/__init__.py +0 -0
  66. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/utils/cli.py +0 -0
  67. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/utils/message_preprocessor.py +0 -0
  68. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/utils/self_fixes.py +0 -0
  69. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/utils/structured_logging.py +0 -0
  70. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore/utils/token_utils.py +0 -0
  71. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore.egg-info/SOURCES.txt +0 -0
  72. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore.egg-info/dependency_links.txt +0 -0
  73. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore.egg-info/entry_points.txt +0 -0
  74. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore.egg-info/requires.txt +0 -0
  75. {abstractcore-2.4.3 → abstractcore-2.4.4}/abstractcore.egg-info/top_level.txt +0 -0
  76. {abstractcore-2.4.3 → abstractcore-2.4.4}/pyproject.toml +0 -0
  77. {abstractcore-2.4.3 → abstractcore-2.4.4}/setup.cfg +0 -0
  78. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_agentic_cli_compatibility.py +0 -0
  79. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_all_specified_providers.py +0 -0
  80. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_basic_session.py +0 -0
  81. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_basic_summarizer.py +0 -0
  82. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_cli_media.py +0 -0
  83. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_complete_integration.py +0 -0
  84. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_comprehensive_events.py +0 -0
  85. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_consistency.py +0 -0
  86. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_core_components.py +0 -0
  87. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_critical_streaming_tool_fix.py +0 -0
  88. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_debug_server.py +0 -0
  89. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_direct_vs_server.py +0 -0
  90. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_embeddings.py +0 -0
  91. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_embeddings_integration.py +0 -0
  92. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_embeddings_llm_integration.py +0 -0
  93. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_embeddings_matrix_operations.py +0 -0
  94. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_embeddings_no_mock.py +0 -0
  95. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_embeddings_real.py +0 -0
  96. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_embeddings_semantic_validation.py +0 -0
  97. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_embeddings_simple.py +0 -0
  98. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_enhanced_prompt.py +0 -0
  99. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_environment_variable_tool_call_tags.py +0 -0
  100. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_factory.py +0 -0
  101. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_final_accuracy.py +0 -0
  102. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_final_comprehensive.py +0 -0
  103. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_final_graceful_errors.py +0 -0
  104. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_fixed_media.py +0 -0
  105. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_fixed_prompt.py +0 -0
  106. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_graceful_fallback.py +0 -0
  107. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_import_debug.py +0 -0
  108. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_integrated_functionality.py +0 -0
  109. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_lmstudio_context.py +0 -0
  110. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_media_import.py +0 -0
  111. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_media_server.py +0 -0
  112. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_ollama_tool_role_fix.py +0 -0
  113. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_openai_conversion_manual.py +0 -0
  114. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_openai_format_bug.py +0 -0
  115. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_openai_format_conversion.py +0 -0
  116. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_openai_media_integration.py +0 -0
  117. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_progressive_complexity.py +0 -0
  118. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_provider_basic_session.py +0 -0
  119. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_provider_connectivity.py +0 -0
  120. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_provider_simple_generation.py +0 -0
  121. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_provider_streaming.py +0 -0
  122. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_provider_token_translation.py +0 -0
  123. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_provider_tool_detection.py +0 -0
  124. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_providers.py +0 -0
  125. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_providers_comprehensive.py +0 -0
  126. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_providers_simple.py +0 -0
  127. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_real_models_comprehensive.py +0 -0
  128. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_retry_observability.py +0 -0
  129. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_retry_strategy.py +0 -0
  130. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_sensory_prompting.py +0 -0
  131. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_server_debug.py +0 -0
  132. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_server_embeddings_real.py +0 -0
  133. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_server_integration.py +0 -0
  134. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_stream_tool_calling.py +0 -0
  135. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_streaming_enhancements.py +0 -0
  136. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_streaming_tag_rewriting.py +0 -0
  137. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_structured_integration.py +0 -0
  138. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_structured_output.py +0 -0
  139. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_syntax_rewriter.py +0 -0
  140. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_text_only_model_experience.py +0 -0
  141. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_tool_calling.py +0 -0
  142. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_tool_execution_separation.py +0 -0
  143. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_unified_streaming.py +0 -0
  144. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_unload_memory.py +0 -0
  145. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_user_scenario_validation.py +0 -0
  146. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_vision_accuracy.py +0 -0
  147. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_vision_comprehensive.py +0 -0
  148. {abstractcore-2.4.3 → abstractcore-2.4.4}/tests/test_vision_fallback_improvement.py +0 -0
  149. {abstractcore-2.4.3 → abstractcore-2.4.4}/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.3
3
+ Version: 2.4.4
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>
@@ -867,6 +867,103 @@ class BaseProvider(AbstractCoreInterface, ABC):
867
867
  """
868
868
  pass
869
869
 
870
+ def health(self, timeout: Optional[float] = 5.0) -> Dict[str, Any]:
871
+ """
872
+ Check provider health and connectivity.
873
+
874
+ This method tests if the provider is online and accessible by attempting
875
+ to list available models. A successful model listing indicates the provider
876
+ is healthy and ready to serve requests.
877
+
878
+ Args:
879
+ timeout: Maximum time in seconds to wait for health check (default: 5.0).
880
+ None means unlimited timeout (not recommended for health checks).
881
+
882
+ Returns:
883
+ Dict with health status information:
884
+ {
885
+ "status": bool, # True if provider is healthy/online
886
+ "provider": str, # Provider class name (e.g., "OpenAIProvider")
887
+ "models": List[str] | None, # Available models if online, None if offline
888
+ "model_count": int, # Number of models available (0 if offline)
889
+ "error": str | None, # Error message if offline, None if healthy
890
+ "latency_ms": float # Time taken for health check in milliseconds
891
+ }
892
+
893
+ Example:
894
+ >>> provider = OllamaProvider(model="llama2")
895
+ >>> health = provider.health(timeout=3.0)
896
+ >>> if health["status"]:
897
+ >>> print(f"Healthy! {health['model_count']} models available")
898
+ >>> else:
899
+ >>> print(f"Offline: {health['error']}")
900
+
901
+ Note:
902
+ - This method never raises exceptions; errors are captured in the response
903
+ - Uses list_available_models() as the connectivity test
904
+ - Providers can override this method for custom health check logic
905
+ """
906
+ import time as time_module
907
+
908
+ start_time = time_module.time()
909
+ provider_name = self.__class__.__name__
910
+
911
+ try:
912
+ # Attempt to list models as connectivity test
913
+ # Store original timeout if provider has HTTP client
914
+ original_timeout = None
915
+ timeout_changed = False
916
+
917
+ if timeout is not None and hasattr(self, '_timeout'):
918
+ original_timeout = self._timeout
919
+ if original_timeout != timeout:
920
+ self.set_timeout(timeout)
921
+ timeout_changed = True
922
+
923
+ try:
924
+ models = self.list_available_models()
925
+
926
+ # Restore original timeout if changed
927
+ if timeout_changed and original_timeout is not None:
928
+ self.set_timeout(original_timeout)
929
+
930
+ latency_ms = (time_module.time() - start_time) * 1000
931
+
932
+ return {
933
+ "status": True,
934
+ "provider": provider_name,
935
+ "models": models,
936
+ "model_count": len(models) if models else 0,
937
+ "error": None,
938
+ "latency_ms": round(latency_ms, 2)
939
+ }
940
+
941
+ except Exception as e:
942
+ # Restore original timeout on error
943
+ if timeout_changed and original_timeout is not None:
944
+ try:
945
+ self.set_timeout(original_timeout)
946
+ except:
947
+ pass # Best effort restoration
948
+ raise # Re-raise to be caught by outer handler
949
+
950
+ except Exception as e:
951
+ latency_ms = (time_module.time() - start_time) * 1000
952
+
953
+ # Extract meaningful error message
954
+ error_message = str(e)
955
+ if not error_message:
956
+ error_message = f"{type(e).__name__} occurred during health check"
957
+
958
+ return {
959
+ "status": False,
960
+ "provider": provider_name,
961
+ "models": None,
962
+ "model_count": 0,
963
+ "error": error_message,
964
+ "latency_ms": round(latency_ms, 2)
965
+ }
966
+
870
967
  def _needs_tag_rewriting(self, tool_call_tags) -> bool:
871
968
  """Check if tag rewriting is needed (tags are non-standard)"""
872
969
  try:
@@ -864,19 +864,14 @@ class HuggingFaceProvider(BaseProvider):
864
864
  if outputs and len(outputs) > 0:
865
865
  response_text = outputs[0]['generated_text'].strip()
866
866
 
867
- # Calculate token usage
868
- input_tokens = len(self.tokenizer.encode(input_text))
869
- output_tokens = len(self.tokenizer.encode(response_text))
867
+ # Calculate token usage using centralized utilities
868
+ usage = self._calculate_usage(input_text, response_text)
870
869
 
871
870
  return GenerateResponse(
872
871
  content=response_text,
873
872
  model=self.model,
874
873
  finish_reason="stop",
875
- usage={
876
- "prompt_tokens": input_tokens,
877
- "completion_tokens": output_tokens,
878
- "total_tokens": input_tokens + output_tokens
879
- }
874
+ usage=usage
880
875
  )
881
876
  else:
882
877
  return GenerateResponse(
@@ -892,6 +887,20 @@ class HuggingFaceProvider(BaseProvider):
892
887
  finish_reason="error"
893
888
  )
894
889
 
890
+ def _calculate_usage(self, prompt: str, response: str) -> Dict[str, int]:
891
+ """Calculate token usage using centralized token utilities."""
892
+ from ..utils.token_utils import TokenUtils
893
+
894
+ prompt_tokens = TokenUtils.estimate_tokens(prompt, self.model)
895
+ completion_tokens = TokenUtils.estimate_tokens(response, self.model)
896
+ total_tokens = prompt_tokens + completion_tokens
897
+
898
+ return {
899
+ "prompt_tokens": prompt_tokens,
900
+ "completion_tokens": completion_tokens,
901
+ "total_tokens": total_tokens
902
+ }
903
+
895
904
  def _stream_generate_transformers(self, input_text: str, max_new_tokens: int,
896
905
  temperature: float, top_p: float, tool_call_tags: Optional[str] = None) -> Iterator[GenerateResponse]:
897
906
  """Stream response using transformers (simulated, original implementation) with tool tag rewriting support"""
@@ -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.3"
14
+ __version__ = "2.4.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractcore
3
- Version: 2.4.3
3
+ Version: 2.4.4
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>
File without changes
File without changes
File without changes