Architecture 3 Providers - djvolz/coda-code-assistant GitHub Wiki
- Primary implementation:
coda/providers/base.py - Registry system:
coda/providers/registry.py - LiteLLM provider:
coda/providers/litellm_provider.py - Ollama provider:
coda/providers/ollama_provider.py - OCI GenAI provider:
coda/providers/oci_genai.py - Mock provider:
coda/providers/mock_provider.py - Utilities:
coda/providers/utils.py - Tests:
tests/unit/test_providers.py,tests/providers/
The Providers module abstracts different AI model providers behind a common interface, allowing Coda Code Assistant to work with multiple LLM backends. The module implements a provider registry system with factory pattern for consistent provider creation and management. The base interface is defined in coda/providers/base.py.
coda/providers/
├── __init__.py # Module exports (verified)
├── base.py # Abstract base provider and data models (verified)
├── registry.py # Provider registration and factory (verified)
├── litellm_provider.py # LiteLLM integration (100+ providers) (verified)
├── ollama_provider.py # Ollama local models (verified)
├── oci_genai.py # Oracle Cloud Infrastructure GenAI (verified)
├── mock_provider.py # Mock provider for testing (verified)
└── utils.py # Shared utilities (verified)
Location: coda/providers/base.py
Purpose: Defines the abstract interface all providers must implement
Core Methods:
-
name(property): Provider identifier -
chat(): Synchronous chat completion -
chat_stream(): Streaming chat completion -
achat(): Async chat completion -
achat_stream(): Async streaming completion -
list_models(): Available model discovery
Location: coda/providers/registry.py
Purpose: Manages provider registration and instance caching
Key Features:
- Static class-level registry
- Singleton instance caching
- Config-based cache key generation
Location: coda/providers/registry.py
Purpose: Creates provider instances with merged configuration
Key Methods:
-
__init__(): Initialize with global config -
create(): Create provider with config merging
Location: coda/providers/base.py
Purpose: Common data structures for provider communication
Key Classes:
-
Message: Chat message with role and content -
Tool: Tool definition -
ToolCall: Tool invocation request -
ChatCompletion: Non-streaming response -
ChatCompletionChunk: Streaming response chunk
Implementation: coda/providers/base.py and coda/providers/registry.py
class BaseProvider(ABC):
"""Abstract base class for all providers."""
@abstractmethod
async def achat(self, messages: List[Message], ...) -> ChatCompletion:
"""Abstract method all providers must implement."""Implementation: coda/providers/registry.py
class ProviderRegistry:
"""Registry for managing provider classes and instances."""
_providers: Dict[str, Type[BaseProvider]] = {}
_instances: Dict[str, BaseProvider] = {}
@classmethod
def register(cls, name: str, provider_class: Type[BaseProvider]) -> None:
"""Register a provider class."""
cls._providers[name] = provider_classImplementation: coda/providers/registry.py
# Generate cache key from config
config_key = f"{name}_{cls._hash_config(kwargs)}"
if config_key in cls._instances:
return cls._instances[config_key]sequenceDiagram
participant CLI
participant ProviderFactory
participant ProviderRegistry
participant Provider
participant LLM Service
CLI->>ProviderFactory: create(provider_name)
ProviderFactory->>ProviderFactory: Merge configs
ProviderFactory->>ProviderRegistry: get_provider(name, config)
alt Provider cached
ProviderRegistry->>CLI: Return cached instance
else New provider
ProviderRegistry->>Provider: Create instance
Provider->>Provider: Initialize client
Provider->>LLM Service: Test connection
ProviderRegistry->>ProviderRegistry: Cache instance
ProviderRegistry->>CLI: Return new instance
end
CLI->>Provider: list_models()
Provider->>LLM Service: Fetch models
LLM Service->>Provider: Model list
Provider->>CLI: Return filtered models
Location: coda/providers/litellm_provider.py
Features:
- Gateway to 100+ LLM providers
- Unified interface for OpenAI, Anthropic, Google, etc.
- Full async and streaming support
- Tool/function calling support
Location: coda/providers/ollama_provider.py
Features:
- Local model execution
- HTTP client using httpx
- Model management commands (pull, delete)
- Custom streaming parser
Location: coda/providers/oci_genai.py
Features:
- Oracle Cloud integration
- Model discovery with caching
- Provider-specific formatting (Cohere vs Generic)
- Tool calling for Cohere models
Location: coda/providers/mock_provider.py
Features:
- Testing and development
- Context-aware responses
- Simulated streaming
- Configurable behaviors
Config File: ~/.config/coda/config.toml
Config Class: coda/configuration.py:CodaConfig
- Method parameters (highest priority)
- Provider-specific config section
- Factory configuration
- Global configuration
- Environment variables (lowest priority)
# From config.example.toml
[providers.oci_genai]
compartment_id = "ocid1.compartment.oc1.."
model = "cohere.command-r-plus"
[providers.ollama]
base_url = "http://localhost:11434"
model = "llama3"
[providers.litellm]
model = "gpt-4"
api_key = "${OPENAI_API_KEY}"-
coda.configuration: Config management (used in all providers) -
coda.constants: Provider name constants
-
httpx>=0.24.0: HTTP client for Ollama -
litellm>=1.0.0: Multi-provider gateway -
oci>=2.88.0: Oracle Cloud SDK -
pydantic>=2.0: Data validation
- Unit tests:
tests/unit/test_providers.py - Provider tests:
tests/providers/test_*.py - Integration tests:
tests/integration/test_*_integration.py
- Registry Tests: Provider registration and caching
- Mock Provider: Comprehensive behavior testing
- Streaming Tests: Streaming response handling
class ProviderError(Exception):
"""Base exception for provider errors."""
class ModelNotFoundError(ProviderError):
"""Raised when requested model is not available."""
class AuthenticationError(ProviderError):
"""Raised when authentication fails."""except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
raise ModelNotFoundError(
f"Model '{model}' not found. "
f"Run 'ollama pull {model}' first."
)- Instance Caching: Providers cached by config hash
- Model List Caching: 24-hour cache for OCI models
- Connection Pooling: HTTP clients reused
- Async First: All providers support async operations
- Credential Management: API keys from environment variables
- OCI Authentication: Uses OCI config file (~/.oci/config)
- No Credential Storage: Keys never persisted to disk
- Secure Defaults: HTTPS preferred for all connections
from coda.providers import ProviderFactory
factory = ProviderFactory(config)
provider = factory.create("ollama", model="llama3")
response = await provider.achat([
{"role": "user", "content": "Hello!"}
])async for chunk in provider.achat_stream(messages):
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")-
CLI Module: Provider initialization in
provider_manager.py - Agent Module: Providers used for AI completions
- Session Module: Provider responses stored in message history
-
New Providers: Extend
BaseProviderand register -
Custom Models: Override
list_models()for filtering - Response Processing: Override chat methods for custom logic
- Tool Calling: Only supported by some providers (see provider docs)
- Model Names: Must match provider's expected format
- Streaming Variability: Chunk sizes vary by provider
All files referenced in this document: