# Provider Adapter

## Purpose

Teddy is **provider-independent**. Domain and Application code depend only on
`AiProviderInterface`. Concrete vendors (OpenAI, Google, Anthropic, …) are wired
through the WordPress AI Client adapters.

## Classes

| Role | Path |
|------|------|
| Domain contract | `src/Domain/Provider/AiProviderInterface.php` |
| Request / response VOs | `CompletionRequest`, `CompletionResponse` |
| WP AI Client adapter | `src/Infrastructure/Providers/WpAiClientAdapter.php` |
| Legacy manager | `src/Providers/ProviderManager.php` |
| Retry / cost | `ProviderRetryPolicy`, `TokenCostEstimator` |

## Streaming (v0.2)

- Interface: `AiProviderInterface::stream()` / `supports_streaming()`
- Implementation: `ProviderManager::stream()`
  - Prefer filter `teddy_stream_completion` (return a `Generator` of string chunks)
  - Else call native WP AI Client stream methods when/if exposed
  - Else buffered fallback: `complete()` then sentence-sized chunks
- REST: `POST /teddy/v1/chat/stream` (`StreamController`)
  - Legacy chat uses `ChatService::stream_turn()`
  - Agent pipeline buffers (tool loop) then emits chunks with `stream_mode=buffered`
- SSE meta includes `stream_mode`: `native` | `buffered`

### Custom native stream example

```php
add_filter( 'teddy_supports_streaming', '__return_true' );
add_filter( 'teddy_stream_completion', function ( $stream, $system, $messages ) {
    return (function () {
        yield 'Hello ';
        yield 'world';
    })();
}, 10, 3 );
```


## Embeddings

- `src/Embeddings/WpAiEmbeddingProvider.php`
- Hook `teddy_generate_embeddings` to supply vectors when the AI Client lacks embeddings
- Hook `teddy_embeddings_available` to mark a custom provider as ready

## Verification

Change provider in Teddy Settings → Model without redeploying code. Chat and
writer should continue to work once the Connectors credential is valid.

### Model discovery (v1.3.1)

- `ProviderManager::discover_text_generation_models()` reads model metadata from configured connectors via the WordPress AI Client registry
- Settings UI uses `ModelCatalog` for free-tier/local ordering and a `[ provider_id, model_id ]` preference tuple at runtime
- Customize ordering/labels with filters: `teddy_local_provider_ids`, `teddy_free_tier_model_candidates`, `teddy_model_display_meta`, `teddy_preferred_model`
