# AI Provider for Mistral

A third-party provider for [Mistral](https://mistral.ai/) in the [PHP AI Client](https://github.com/WordPress/php-ai-client) SDK. Works as both a Composer package and a WordPress plugin.

This project is independent and is not affiliated with, endorsed by, or sponsored by Mistral AI.

## Requirements

- PHP 7.4 or higher
- [wordpress/php-ai-client](https://github.com/WordPress/php-ai-client) must be installed

## Installation

### As a Composer Package

```bash
composer require saarnilauri/ai-provider-for-mistral
```

The Composer distribution is intended for library usage and excludes `ai-provider-for-mistral.php`.

### As a WordPress Plugin

1. Download `ai-provider-for-mistral.zip` from [GitHub Releases](https://github.com/saarnilauri/ai-provider-for-mistral/releases) (do not use GitHub "Source code" archives)
2. Upload the ZIP in WordPress admin via Plugins > Add New Plugin > Upload Plugin
3. Ensure the PHP AI Client plugin is installed and activated
4. Activate the plugin through the WordPress admin

#### Installing with WP-CLI

Use the release ZIP URL from GitHub Releases — **not** the auto-generated `main.zip` source archive, which is missing the bundled dependencies:

```bash
wp plugin install https://github.com/saarnilauri/ai-provider-for-mistral/releases/download/v1.0.1/ai-provider-for-mistral.zip --activate
```

Replace `v1.0.1` with the desired release tag.

## Building the Plugin ZIP

Build a distributable plugin archive locally:

```bash
make dist
# or:
./scripts/build-plugin-zip.sh
```

The ZIP is created at `dist/ai-provider-for-mistral.zip` and includes `ai-provider-for-mistral.php`.

## Testing

Install development dependencies:

```bash
composer install
```

Run unit tests:

```bash
composer test
# or:
composer test:unit
```

Run integration tests (requires `MISTRAL_API_KEY`):

```bash
composer test:integration
```

## Release Workflow

This repository includes a GitHub Actions workflow at `.github/workflows/release-plugin-zip.yml`:

- On tag pushes matching `v*`, it builds `dist/ai-provider-for-mistral.zip`
- For tagged releases, it derives the version from the tag (for example `v0.1.0` -> `0.1.0`) and validates committed metadata:
  - `readme.txt` `Stable tag` must match the tag version
  - `ai-provider-for-mistral.php` `Version` must match the tag version
- If versions do not match, the workflow fails
- It uploads the ZIP as a workflow artifact
- It attaches the ZIP to the GitHub release for that tag

## Usage

### With WordPress

The provider automatically registers itself with the PHP AI Client on the `init` hook. Simply ensure both plugins are active and configure your API key:

```php
// Set your Mistral API key (or use the MISTRAL_API_KEY environment variable)
putenv('MISTRAL_API_KEY=your-api-key');

// Use the provider
$result = AiClient::prompt('Hello, world!')
    ->usingProvider('mistral')
    ->generateTextResult();
```

### As a Standalone Package

```php
use WordPress\AiClient\AiClient;
use SaarniLauri\AiProviderForMistral\Provider\ProviderForMistral;

// Register the provider
$registry = AiClient::defaultRegistry();
$registry->registerProvider(ProviderForMistral::class);

// Set your API key
putenv('MISTRAL_API_KEY=your-api-key');

// Generate text
$result = AiClient::prompt('Explain quantum computing')
    ->usingProvider('mistral')
    ->generateTextResult();

echo $result->toText();
```

### Image Generation

Mistral supports image generation through its [Agents API](https://docs.mistral.ai/agents/tools/built-in/image_generation). The provider handles the multi-step flow (agent creation, conversation, file download) automatically:

```php
$result = AiClient::prompt('A red apple on a white background')
    ->usingProvider('mistral')
    ->generateImageResult();

// Get the generated image as base64-encoded PNG
$file = $result->getCandidates()[0]->getMessage()->getParts()[0]->getFile();
$binaryData = base64_decode($file->getBase64Data(), true);
file_put_contents('apple.png', $binaryData);
```

### Text-to-Speech

Mistral's Voxtral TTS models convert text into speech. Choose a voice with `asOutputSpeechVoice()`, using a [preset voice](https://docs.mistral.ai/studio/audio/text-to-speech/voices) or the ID of a voice saved in your workspace. Without a voice, an English preset voice is used.

```php
$file = AiClient::prompt('Your order shipped this morning and should arrive on Thursday.')
    ->usingModel(ProviderForMistral::model('voxtral-mini-tts-3-0'))
    ->asOutputSpeechVoice('voice_485')
    ->convertTextToSpeech();

file_put_contents('order-update.mp3', base64_decode($file->getBase64Data(), true));
```

- **Format:** MP3 by default. Request another format with `asOutputMimeType()`: `audio/wav`, `audio/flac`, `audio/ogg` (Opus), or `audio/pcm` (raw 32-bit float samples at 24 kHz).
- **Voice cloning:** add a short recording to the prompt as an inline audio file, and Mistral narrates the text in that voice for this request only.
- **Long text:** text over 2000 characters is split at paragraph and sentence boundaries, narrated in several requests, and joined into one file. Joining works for MP3 and PCM only, so other formats throw an exception for long text. Change the limit with the `ai_provider_for_mistral_tts_max_text_length` filter.
- **Volume on long text:** Voxtral TTS 3 currently gets quieter over longer passages and jumps back up at each new segment, which Mistral has confirmed as a known limitation. For long-form narration, use `voxtral-mini-tts-2603`. When the provider picks the model, it uses `voxtral-mini-tts-latest`, which points to that model for now.
- **Other options:** pass Mistral parameters such as `expressiveness` or `phoneme_hints` with `usingModelConfig()` custom options. Emotion and pace tags go inline in the text.

## Supported Models

Available models are dynamically discovered from the Mistral API. This includes text models and, for compatible models, vision and function-calling capabilities. Image generation is supported through models like `mistral-medium-2505`, and text-to-speech through the Voxtral TTS models such as `voxtral-mini-tts-3-0`. See the [Mistral documentation](https://docs.mistral.ai/) for the full list of available models.

## Configuration

The provider uses the `MISTRAL_API_KEY` environment variable for authentication. You can set this in your environment or via PHP:

```php
putenv('MISTRAL_API_KEY=your-api-key');
```

## External Services

This plugin connects to the [Mistral AI API](https://api.mistral.ai/v1) to provide AI text generation, image generation, and text-to-speech capabilities.

Data is sent to the Mistral API when your application code makes AI generation requests through the PHP AI Client. The data sent includes your prompts, model configuration, and API key. No data is sent automatically — requests only occur when explicitly triggered by code using the PHP AI Client SDK.

This service is provided by [Mistral AI](https://mistral.ai/):
- [Terms of Service](https://mistral.ai/terms/)
- [Privacy Policy](https://mistral.ai/terms/#privacy-policy)

## License

GPL-2.0-or-later
