abstractcore 2.6.0__py3-none-any.whl → 2.6.2__py3-none-any.whl

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.
@@ -7,4 +7,27 @@ Provides configuration management and command-line interface for AbstractCore.
7
7
  from .vision_config import handle_vision_commands, add_vision_arguments
8
8
  from .manager import get_config_manager
9
9
 
10
- __all__ = ['handle_vision_commands', 'add_vision_arguments', 'get_config_manager']
10
+
11
+ def configure_provider(provider: str, **kwargs) -> None:
12
+ """Configure runtime settings for a provider."""
13
+ get_config_manager().configure_provider(provider, **kwargs)
14
+
15
+
16
+ def get_provider_config(provider: str) -> dict:
17
+ """Get runtime configuration for a provider."""
18
+ return get_config_manager().get_provider_config(provider)
19
+
20
+
21
+ def clear_provider_config(provider: str = None) -> None:
22
+ """Clear runtime provider configuration."""
23
+ get_config_manager().clear_provider_config(provider)
24
+
25
+
26
+ __all__ = [
27
+ 'handle_vision_commands',
28
+ 'add_vision_arguments',
29
+ 'get_config_manager',
30
+ 'configure_provider',
31
+ 'get_provider_config',
32
+ 'clear_provider_config'
33
+ ]
@@ -136,6 +136,7 @@ class ConfigurationManager:
136
136
  self.config_dir = Path.home() / ".abstractcore" / "config"
137
137
  self.config_file = self.config_dir / "abstractcore.json"
138
138
  self.config = self._load_config()
139
+ self._provider_config: Dict[str, Dict[str, Any]] = {} # Runtime config (not persisted)
139
140
 
140
141
  def _load_config(self) -> AbstractCoreConfig:
141
142
  """Load configuration from file or create default."""
@@ -437,6 +438,52 @@ class ConfigurationManager:
437
438
  """Check if local_files_only should be forced for transformers."""
438
439
  return self.config.offline.force_local_files_only
439
440
 
441
+ def configure_provider(self, provider: str, **kwargs) -> None:
442
+ """
443
+ Configure runtime settings for a provider.
444
+
445
+ Args:
446
+ provider: Provider name ('ollama', 'lmstudio', 'openai', 'anthropic')
447
+ **kwargs: Configuration options (base_url, timeout, etc.)
448
+
449
+ Example:
450
+ configure_provider('ollama', base_url='http://192.168.1.100:11434')
451
+ """
452
+ provider = provider.lower()
453
+ if provider not in self._provider_config:
454
+ self._provider_config[provider] = {}
455
+
456
+ for key, value in kwargs.items():
457
+ if value is None:
458
+ # Remove config (revert to env var / default)
459
+ self._provider_config[provider].pop(key, None)
460
+ else:
461
+ self._provider_config[provider][key] = value
462
+
463
+ def get_provider_config(self, provider: str) -> Dict[str, Any]:
464
+ """
465
+ Get runtime configuration for a provider.
466
+
467
+ Args:
468
+ provider: Provider name
469
+
470
+ Returns:
471
+ Dict with configured settings, or empty dict if no config
472
+ """
473
+ return self._provider_config.get(provider.lower(), {}).copy()
474
+
475
+ def clear_provider_config(self, provider: Optional[str] = None) -> None:
476
+ """
477
+ Clear runtime provider configuration.
478
+
479
+ Args:
480
+ provider: Provider name, or None to clear all
481
+ """
482
+ if provider is None:
483
+ self._provider_config.clear()
484
+ else:
485
+ self._provider_config.pop(provider.lower(), None)
486
+
440
487
 
441
488
  # Global instance
442
489
  _config_manager = None
@@ -2,6 +2,7 @@
2
2
  LM Studio provider implementation (OpenAI-compatible API).
3
3
  """
4
4
 
5
+ import os
5
6
  import httpx
6
7
  import json
7
8
  import time
@@ -23,14 +24,19 @@ from ..events import EventType
23
24
  class LMStudioProvider(BaseProvider):
24
25
  """LM Studio provider using OpenAI-compatible API"""
25
26
 
26
- def __init__(self, model: str = "local-model", base_url: str = "http://localhost:1234/v1", **kwargs):
27
+ def __init__(self, model: str = "local-model", base_url: Optional[str] = None, **kwargs):
27
28
  super().__init__(model, **kwargs)
28
29
  self.provider = "lmstudio"
29
30
 
30
31
  # Initialize tool handler
31
32
  self.tool_handler = UniversalToolHandler(model)
32
33
 
33
- self.base_url = base_url.rstrip('/')
34
+ # Base URL priority: parameter > LMSTUDIO_BASE_URL > default
35
+ self.base_url = (
36
+ base_url or
37
+ os.getenv("LMSTUDIO_BASE_URL") or
38
+ "http://localhost:1234/v1"
39
+ ).rstrip('/')
34
40
 
35
41
  # Get timeout value - None means unlimited timeout
36
42
  timeout_value = getattr(self, '_timeout', None)
@@ -3,6 +3,7 @@ Ollama provider implementation.
3
3
  """
4
4
 
5
5
  import json
6
+ import os
6
7
  import httpx
7
8
  import time
8
9
  from typing import List, Dict, Any, Optional, Union, Iterator, AsyncIterator, Type
@@ -23,11 +24,17 @@ from ..events import EventType
23
24
  class OllamaProvider(BaseProvider):
24
25
  """Ollama provider for local models with full integration"""
25
26
 
26
- def __init__(self, model: str = "qwen3:4b-instruct-2507-q4_K_M", base_url: str = "http://localhost:11434", **kwargs):
27
+ def __init__(self, model: str = "qwen3:4b-instruct-2507-q4_K_M", base_url: Optional[str] = None, **kwargs):
27
28
  super().__init__(model, **kwargs)
28
29
  self.provider = "ollama"
29
30
 
30
- self.base_url = base_url.rstrip('/')
31
+ # Base URL priority: parameter > OLLAMA_BASE_URL > OLLAMA_HOST > default
32
+ self.base_url = (
33
+ base_url or
34
+ os.getenv("OLLAMA_BASE_URL") or
35
+ os.getenv("OLLAMA_HOST") or
36
+ "http://localhost:11434"
37
+ ).rstrip('/')
31
38
  self.client = httpx.Client(timeout=self._timeout)
32
39
  self._async_client = None # Lazy-loaded async client
33
40
 
@@ -354,6 +354,8 @@ class ProviderRegistry:
354
354
 
355
355
  This is used by the factory to create provider instances.
356
356
  """
357
+ from ..config import get_provider_config
358
+
357
359
  provider_info = self.get_provider_info(provider_name)
358
360
  if not provider_info:
359
361
  available_providers = ", ".join(self.list_provider_names())
@@ -362,8 +364,14 @@ class ProviderRegistry:
362
364
  provider_class = self.get_provider_class(provider_name)
363
365
  model = model or provider_info.default_model
364
366
 
367
+ # Get runtime config for this provider
368
+ runtime_config = get_provider_config(provider_name)
369
+
370
+ # Merge: runtime_config < kwargs (user kwargs take precedence)
371
+ merged_kwargs = {**runtime_config, **kwargs}
372
+
365
373
  try:
366
- return provider_class(model=model, **kwargs)
374
+ return provider_class(model=model, **merged_kwargs)
367
375
  except ImportError as e:
368
376
  # Re-raise import errors with helpful message
369
377
  if provider_info.installation_extras:
@@ -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.6.0"
14
+ __version__ = "2.6.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractcore
3
- Version: 2.6.0
3
+ Version: 2.6.2
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>
@@ -795,6 +795,66 @@ summarizer document.pdf --provider anthropic --model claude-3-5-sonnet
795
795
 
796
796
  **Complete guide**: [Centralized Configuration](docs/centralized-config.md)
797
797
 
798
+ ### Environment Variables
799
+
800
+ AbstractCore supports environment variables for provider base URLs, enabling remote servers, Docker deployments, and non-standard ports:
801
+
802
+ ```bash
803
+ # Ollama on remote server
804
+ export OLLAMA_BASE_URL="http://192.168.1.100:11434"
805
+ # Alternative: OLLAMA_HOST is also supported
806
+ export OLLAMA_HOST="http://192.168.1.100:11434"
807
+
808
+ # LMStudio on non-standard port
809
+ export LMSTUDIO_BASE_URL="http://localhost:1235/v1"
810
+
811
+ # OpenAI-compatible proxy
812
+ export OPENAI_BASE_URL="https://api.portkey.ai/v1"
813
+
814
+ # Anthropic proxy
815
+ export ANTHROPIC_BASE_URL="https://api.portkey.ai/v1"
816
+ ```
817
+
818
+ **Priority**: Programmatic `base_url` parameter > Runtime configuration > Environment variable > Default value
819
+
820
+ **Provider discovery**: `get_all_providers_with_models()` automatically respects these environment variables when checking provider availability.
821
+
822
+ ### Programmatic Configuration
823
+
824
+ Configure provider settings at runtime without environment variables:
825
+
826
+ ```python
827
+ from abstractcore.config import configure_provider, get_provider_config, clear_provider_config
828
+ from abstractcore import create_llm
829
+
830
+ # Set provider base URL programmatically
831
+ configure_provider('ollama', base_url='http://192.168.1.100:11434')
832
+
833
+ # All future create_llm() calls automatically use the configured URL
834
+ llm = create_llm('ollama', model='llama3:8b') # Uses http://192.168.1.100:11434
835
+
836
+ # Query current configuration
837
+ config = get_provider_config('ollama')
838
+ print(config) # {'base_url': 'http://192.168.1.100:11434'}
839
+
840
+ # Clear configuration (revert to env var / default)
841
+ configure_provider('ollama', base_url=None)
842
+ # Or clear all providers
843
+ clear_provider_config()
844
+ ```
845
+
846
+ **Use Cases**:
847
+ - **Web UI Settings**: Configure providers through settings pages
848
+ - **Docker Startup**: Read from custom env vars and configure programmatically
849
+ - **Testing**: Set mock server URLs for integration tests
850
+ - **Multi-tenant**: Configure different base URLs per tenant
851
+
852
+ **Priority System**:
853
+ 1. Constructor parameter (highest): `create_llm("ollama", base_url="...")`
854
+ 2. Runtime configuration: `configure_provider('ollama', base_url="...")`
855
+ 3. Environment variable: `OLLAMA_BASE_URL`
856
+ 4. Default value (lowest): `http://localhost:11434`
857
+
798
858
  ## Documentation
799
859
 
800
860
  **📚 Complete Documentation:** [docs/](docs/) - Full documentation index and navigation guide
@@ -26,9 +26,9 @@ abstractcore/compression/pil_text_renderer.py,sha256=IxVs5ZFXIJeXIQdS1hDQKJC6O2l
26
26
  abstractcore/compression/quality.py,sha256=bq7YI_5ywHfPnWSu1MmBRnV5Nxz8KBJGFvnfQOJSx5c,9415
27
27
  abstractcore/compression/text_formatter.py,sha256=5RE6JrLkHvYoDQlsYJSoqfbwAa3caMr2i_DXog6ovZs,27328
28
28
  abstractcore/compression/vision_compressor.py,sha256=5Ox3w_ee7fgPRDOpSQcooEGtuBKpQoAmWjwpLE2hoNU,12773
29
- abstractcore/config/__init__.py,sha256=4mHX5z5Sq8R8xh78tb9jjZLaz_oBNW1eh914OsdDTxs,318
29
+ abstractcore/config/__init__.py,sha256=JQ4feacJV_brzf6qNnNPo5VbmXhdjIxH088jYLTp1ik,919
30
30
  abstractcore/config/main.py,sha256=oQxnNxo_78CusCuDKGgwal2T3S8MDpo3yzLSB1wpYkU,35573
31
- abstractcore/config/manager.py,sha256=JTN_qoNqRGKQoPH66nVGn3PIjgt-eSgsG9BndYIC8Dg,16752
31
+ abstractcore/config/manager.py,sha256=O_zuskt4qe9bzaJ2dVoodYWJ3zbakaDu5ocbuGZuCoo,18388
32
32
  abstractcore/config/vision_config.py,sha256=jJzO4zBexh8SqSKp6YKOXdMDSv4AL4Ztl5Xi-5c4KyY,17869
33
33
  abstractcore/core/__init__.py,sha256=2h-86U4QkCQ4gzZ4iRusSTMlkODiUS6tKjZHiEXz6rM,684
34
34
  abstractcore/core/enums.py,sha256=BhkVnHC-X1_377JDmqd-2mnem9GdBLqixWlYzlP_FJU,695
@@ -71,12 +71,12 @@ abstractcore/providers/__init__.py,sha256=O7gmT4p_jbzMjoZPhi_6RIMHQm-IMFX1XfcgyS
71
71
  abstractcore/providers/anthropic_provider.py,sha256=0-qZb0Es6-VLuVVl2j7IUjOuyRlgjQdJFulWfpi4qb4,31740
72
72
  abstractcore/providers/base.py,sha256=nWF1pxeUlT4ozlUqKG0rWOmLkfo-zQgfU7fv3AUSI08,68452
73
73
  abstractcore/providers/huggingface_provider.py,sha256=v4UUmODrnWKtTygzPh-lm4jSCAPms5VYJE5v7PWB4Lo,79458
74
- abstractcore/providers/lmstudio_provider.py,sha256=e53EF1kyIK4rMRrHZqeE-RfFbxap05iQYWOq_jjxJSk,33935
74
+ abstractcore/providers/lmstudio_provider.py,sha256=92_vx7AVVt_oufJdHo3R0D_V2qyTKO2DKzi9-l4KzWs,34114
75
75
  abstractcore/providers/mlx_provider.py,sha256=afLCEwuw7r8OK4fD3OriyKMcWpxVIob_37ItmgAclfc,23123
76
76
  abstractcore/providers/model_capabilities.py,sha256=C4HIgvNTp9iIPiDeWyXo7vdzRkMdecRPoQi80yHSOL0,11955
77
- abstractcore/providers/ollama_provider.py,sha256=FoofSLtevTGxsjjiQw9Q7OWBjp4RJ8JHrFVefPnHyoA,33915
77
+ abstractcore/providers/ollama_provider.py,sha256=Kg5au_tia0xFTXqUlqDNrSvwVpt2lXvfnVFou9K2FGQ,34144
78
78
  abstractcore/providers/openai_provider.py,sha256=Y-79mAtgDiDw6SqF2LhnWtlfuC_e6TxeF_tqJWAAyWo,36364
79
- abstractcore/providers/registry.py,sha256=KG7qjP76Z5t6k5ZsmqoDEbe3A39RJhhvExKPvSKMEms,19442
79
+ abstractcore/providers/registry.py,sha256=z0FVaucJ6KmE6QAIkskH56jV-7hodWgj_G-u5_bcgp0,19732
80
80
  abstractcore/providers/streaming.py,sha256=HaGkoItPWXqgml3C-KiPc0hBNpztLzjl_ooECw11BHI,31370
81
81
  abstractcore/server/__init__.py,sha256=1DSAz_YhQtnKv7sNi5TMQV8GFujctDOabgvAdilQE0o,249
82
82
  abstractcore/server/app.py,sha256=ajG4yfMOHjqBafquLHeLTaMmEr01RXiBRxjFRTIT2j8,96602
@@ -98,11 +98,11 @@ abstractcore/utils/self_fixes.py,sha256=1VYxPq-q7_DtNl39NbrzUmyHpkhb9Q2SdnXUj4c0
98
98
  abstractcore/utils/structured_logging.py,sha256=Vm-HviSa42G9DJCWmaEv4a0QG3NMsADD3ictLOs4En0,19952
99
99
  abstractcore/utils/token_utils.py,sha256=eLwFmJ68p9WMFD_MHLMmeJRW6Oqx_4hKELB8FNQ2Mnk,21097
100
100
  abstractcore/utils/trace_export.py,sha256=MD1DHDWltpewy62cYzz_OSPAA6edZbZq7_pZbvxz_H8,9279
101
- abstractcore/utils/version.py,sha256=8FvB_bU--hAlMcCZyeDF2i2VlS9p4sYej4VBQOVtRR4,605
101
+ abstractcore/utils/version.py,sha256=5iDEPQNqduswVtnrBoEL5IucdXpHJ7JSu98Ep1PMYlM,605
102
102
  abstractcore/utils/vlm_token_calculator.py,sha256=VBmIji_oiqOQ13IvVhNkb8E246tYMIXWVVOnl86Ne94,27978
103
- abstractcore-2.6.0.dist-info/licenses/LICENSE,sha256=PI2v_4HMvd6050uDD_4AY_8PzBnu2asa3RKbdDjowTA,1078
104
- abstractcore-2.6.0.dist-info/METADATA,sha256=YuVAqs9CI7NP8wjIsa0W2sXLWpNLOC5JYj_VEqJL2N8,41304
105
- abstractcore-2.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
106
- abstractcore-2.6.0.dist-info/entry_points.txt,sha256=jXNdzeltVs23A2JM2e2HOiAHldHrsnud3EvPI5VffOs,658
107
- abstractcore-2.6.0.dist-info/top_level.txt,sha256=DiNHBI35SIawW3N9Z-z0y6cQYNbXd32pvBkW0RLfScs,13
108
- abstractcore-2.6.0.dist-info/RECORD,,
103
+ abstractcore-2.6.2.dist-info/licenses/LICENSE,sha256=PI2v_4HMvd6050uDD_4AY_8PzBnu2asa3RKbdDjowTA,1078
104
+ abstractcore-2.6.2.dist-info/METADATA,sha256=ULSMViuMcjCj-wIgJJ_AksUq0BFRjf33L-vpWxo-iJ0,43479
105
+ abstractcore-2.6.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
106
+ abstractcore-2.6.2.dist-info/entry_points.txt,sha256=jXNdzeltVs23A2JM2e2HOiAHldHrsnud3EvPI5VffOs,658
107
+ abstractcore-2.6.2.dist-info/top_level.txt,sha256=DiNHBI35SIawW3N9Z-z0y6cQYNbXd32pvBkW0RLfScs,13
108
+ abstractcore-2.6.2.dist-info/RECORD,,