API reference
Everything lives in the namespace Darvis\LaravelAiGenerator.
AiGenerator
Darvis\LaravelAiGenerator\AiGenerator, a final class, bound in the container as a singleton and under the alias ai-generator.
generate()
public function generate(ContentRequest $request): ContentResult
- Fills the empty
language,tone,readingLevelandmaxWordsof the request from the config. An emptyimageStylebecomesphoto, an emptyimageAspectbecomes16:9. - Calls
generate()on the boundAiContentDriver, the default driver. - When that throws a
RuntimeExceptionandAI_GENERATOR_FALLBACKSlists drivers, tries them in order, skipping a built-in driver without an API key. When all fail, throwsEvery AI driver failed. ...with the first exception asgetPrevious(). - Trims
title,intro,text,seoTitle,seoDescriptionandimagePrompt.
Without fallbacks it throws whatever the driver throws. The built-in drivers throw a RuntimeException; see Exceptions.
use Darvis\LaravelAiGenerator\AiGenerator;
use Darvis\LaravelAiGenerator\ContentRequest;
$result = app(AiGenerator::class)->generate(new ContentRequest(
topic: 'Your topic',
includeImage: false,
));
using()
public function using(string $driver, ?string $model = null): AiGenerator
Returns a new generator that writes with another driver, and with $model instead of the configured text model when you pass one. $driver is openai, anthropic, gemini, xai, an alias (chatgpt, gpt, claude, google, grok) or a name registered with extend(). The returned generator never uses fallbacks. Throws Unsupported AI driver: ... for an unknown name.
AiGenerator::using('claude')->generate($request);
AiGenerator::using('openai', 'gpt-6-luna')->generate($request);
generateImage()
public function generateImage(string $prompt, string $style = 'photo', string $aspect = '16:9', ?string $driver = null): array
Makes only an image. The image comes from $driver when you pass one (openai, gemini or xai), or else from AI_GENERATOR_IMAGE_DRIVER, or else from the bound text driver when it can make images, or else from OpenAI. With the openai or anthropic driver, or a custom driver, that is the OpenAI image API with OPENAI_IMAGE_MODEL.
| Argument | Values |
|---|---|
$prompt | What the image shows, preferably in English. |
$style | photo, illustration, flat or 3d. The style becomes a prefix of the prompt and No text or watermarks. is added. Any other value sends the prompt unchanged. |
$aspect | 1:1, 4:5 or 16:9. Gemini gets the ratio; Grok gets it too, with 3:4 for 4:5. With OpenAI a GPT Image model gets 1536x1024 (16:9), 1024x1536 (4:5) or 1024x1024; a dall-e-3 model gets its own sizes; other models get 1024x1024. |
$driver | openai, gemini, xai or an alias, or null for the rules above. |
It returns an array and does not throw:
- on success
['url' => ?string, 'base64' => ?string], one of the two filled; - on failure
['error' => string], for exampleOPENAI_API_KEY is not set., orClaude (Anthropic) cannot generate images. Use openai, gemini or xai as image driver., orUnsupported AI driver: ....
The request waits up to 120 seconds, with 30 seconds to connect, and is tried once. The timeout of the provider does not apply here.
use Darvis\LaravelAiGenerator\AiGenerator;
use Illuminate\Support\Facades\Log;
$image = app(AiGenerator::class)->generateImage('A lighthouse at dusk', 'illustration');
if (isset($image['error'])) {
Log::warning($image['error']);
}
ContentRequest
Darvis\LaravelAiGenerator\ContentRequest, a final class with public readonly properties.
public function __construct(
string $topic,
?string $language = null,
?string $audience = null,
?string $tone = null,
?string $readingLevel = null,
?array $keywords = null,
?string $cta = null,
?string $brand = null,
?int $maxWords = null,
bool $includeImage = true,
?string $imageStyle = 'photo',
?string $imageAspect = '16:9',
)
Use named arguments. Usage explains every argument. Note that includeImage defaults to true.
ContentResult
Darvis\LaravelAiGenerator\ContentResult, a final class with public readonly properties.
public function __construct(
string $title,
string $intro,
string $text,
string $seoTitle,
string $seoDescription,
?string $imagePrompt = null,
?string $imageUrl = null,
?string $imageBase64 = null,
?string $errorMessage = null,
?string $driver = null,
?string $model = null,
)
driver and model say which built-in driver and text model wrote the text, for example anthropic and claude-sonnet-5. A custom driver leaves them null.
| Method | Returns |
|---|---|
hasError(): bool | true when errorMessage is not null. The text can still be complete. |
hasImage(): bool | true when imageUrl or imageBase64 is not null. |
Usage explains every property.
AiContentDriver
Darvis\LaravelAiGenerator\Contracts\AiContentDriver, the interface of a driver.
public function generate(ContentRequest $request): ContentResult;
The package binds it as a singleton to the driver the manager builds for the config key driver: OpenAiDriver, AnthropicDriver, GeminiDriver or XaiDriver in Darvis\LaravelAiGenerator\Drivers, or a driver registered with extend(). It throws Unsupported AI driver: ... for any other name. See Custom drivers for a driver of your own.
The built-in drivers extend Darvis\LaravelAiGenerator\Drivers\Driver, which is @internal: extend AiContentDriver for a driver of your own, not that class. OpenAiDriver::imagePayload() is public but @internal too. Don’t call either from your application.
AiImageDriver
Darvis\LaravelAiGenerator\Contracts\AiImageDriver, the interface of a driver that can make images. The OpenAI, Gemini and Grok drivers implement it; Claude does not.
public function generateImage(string $prompt, string $aspect = '16:9', ?int $timeout = null, int $attempts = 2): array;
$prompt is the complete prompt; the style prefix is added before this call. $timeout is in seconds per attempt, null for the timeout of the provider. It returns the same array as AiGenerator::generateImage() and never throws. A custom driver may implement it too; the manager then uses it for images when it is the text driver or the configured image driver.
AiGeneratorManager
Darvis\LaravelAiGenerator\AiGeneratorManager, a singleton that builds the drivers by name.
| Method | What it does |
|---|---|
driver(?string $name = null): AiContentDriver | The driver with this name, or the default driver. The instance is reused. |
build(string $name, ?string $model = null): AiContentDriver | A new instance, optionally with another text model. using() calls this when you pass a model. |
extend(string $name, Closure $creator): self | Registers a driver of your own. The closure gets the container and the model asked for with using(), or null. |
imageDriver(?string $name = null): ?AiImageDriver | The driver with this name when it can make images, else null. Without a name: the image driver of the default driver. |
imageDriverFor(AiContentDriver $textDriver): ?AiImageDriver | The image driver for a text driver: AI_GENERATOR_IMAGE_DRIVER, else the text driver when it can make images, else OpenAI. |
names(): list<string> | The built-in driver names and the names registered with extend(). |
normalize(string $name): string | Turns an alias such as claude into the driver name, anthropic. |
All of them except names() and normalize() throw Unsupported AI driver: ... for an unknown name.
use App\Services\AiDrivers\AcmeAiDriver;
use Darvis\LaravelAiGenerator\AiGeneratorManager;
app(AiGeneratorManager::class)->extend('acme', fn ($app, ?string $model) => new AcmeAiDriver);
Provider
Darvis\LaravelAiGenerator\Support\Provider, an enum of the providers the package ships a driver for: Provider::OpenAi (openai), Provider::Anthropic (anthropic), Provider::Gemini (gemini) and Provider::Xai (xai).
| Method | Returns, for example for Provider::Anthropic |
|---|---|
Provider::fromName(string $name): ?Provider | The case for a name or alias, null for an unknown name. |
label(): string | Claude (Anthropic) |
shortName(): string | Claude, as used in error messages. |
envPrefix(): string | ANTHROPIC |
apiKeyEnv(): string | ANTHROPIC_API_KEY |
apiKeyUrl(): string | The page where you create a key. |
defaultBaseUrl(): string | https://api.anthropic.com/v1 |
defaultModel(): string | claude-sonnet-5 |
defaultImageModel(): ?string | null: Claude makes no images. |
defaultTemperature(): ?float | null; 0.7 for OpenAI. |
supportsImages(): bool | false |
The facade
Darvis\LaravelAiGenerator\Facades\AiGenerator forwards to the AiGenerator singleton. It has no global alias, so import it.
use Darvis\LaravelAiGenerator\ContentRequest;
use Darvis\LaravelAiGenerator\Facades\AiGenerator;
AiGenerator::generate(new ContentRequest(topic: 'Your topic', includeImage: false));
AiGenerator::generateImage('A lighthouse at dusk', 'illustration', '1:1');
AiGenerator::using('anthropic')->generate(new ContentRequest(topic: 'Your topic', includeImage: false));
AiGeneratorConfig
Darvis\LaravelAiGenerator\Support\AiGeneratorConfig is the one class that reads the package config. Every method is static.
| Method | Returns | Config key | Default |
|---|---|---|---|
driver() | string | driver | openai |
defaultLanguage() | string | default_language | nl |
defaultMaxWords() | int | defaults.max_words | 900 |
defaultReadingLevel() | string | defaults.reading_level | general |
defaultTone() | string | defaults.tone | informal |
openAiApiKey() | ?string | drivers.openai.api_key | null, also for an empty string |
openAiBaseUrl() | string | drivers.openai.base_url | https://api.openai.com/v1, without a trailing slash |
openAiImageModel() | string | drivers.openai.image_model | gpt-image-2 |
openAiModel() | string | drivers.openai.model | gpt-4.1-mini |
openAiTemperature() | float | drivers.openai.temperature | 0.7 |
openAiTimeout() | int | drivers.openai.timeout | 45 |
apiKey(Provider $provider) | ?string | drivers.<driver>.api_key | null, also for an empty string |
baseUrl(Provider $provider) | string | drivers.<driver>.base_url | per provider, without a trailing slash |
model(Provider $provider) | string | drivers.<driver>.model | per provider, also for an empty string |
imageModel(Provider $provider) | ?string | drivers.<driver>.image_model | per provider; null for Claude |
temperature(Provider $provider) | ?float | drivers.<driver>.temperature | 0.7 for OpenAI, else null; an empty string gives null |
timeout(Provider $provider) | int | drivers.<driver>.timeout | 45 |
anthropicMaxTokens() | int | drivers.anthropic.max_tokens | 8192 |
anthropicVersion() | string | drivers.anthropic.version | 2023-06-01 |
imageDriver() | ?string | image_driver | null |
fallbacks() | list<string> | fallbacks | []; a comma separated string is split and trimmed |
mcpEnabled() | bool | mcp.enabled | true |
mcpHandle() | string | mcp.handle | ai-generator |
The openAi...() methods are kept for existing code; they return the same as the general ones with Provider::OpenAi.
Configuration has the environment variable of every key.
The service provider
Darvis\LaravelAiGenerator\AiGeneratorServiceProvider is discovered by Laravel. It merges the config under the key ai-generator, registers the manager, the driver and the generator as singletons and the alias, registers the two commands, and offers one publish tag:
php artisan vendor:publish --tag=ai-generator-config
When laravel/mcp is installed and AI_GENERATOR_MCP is not false, it registers the local MCP server Darvis\LaravelAiGenerator\Mcp\AiGeneratorServer under AI_GENERATOR_MCP_HANDLE.
The package has no routes, views, migrations, events or translations.
Commands
| Command | What it does | Billed |
|---|---|---|
php artisan ai-generator:install | The setup wizard: providers, keys (checked), models, default, image driver, fallbacks, defaults; writes .env. | no |
php artisan ai-generator:status | A table of the providers, their keys, models and a key check, plus the default driver, image driver, fallbacks and MCP. Fails when a key is refused. | no |
php artisan ai-generator:status --offline | The same without contacting any provider. | no |
php artisan ai-generator:status --test=anthropic | Also generates one short text with that driver, without an image. | yes, one call |
Exceptions
The package has no exception classes of its own. The drivers, the manager and the generator throw PHP’s RuntimeException with these messages. Provider stands for OpenAI, Claude, Gemini or Grok.
| Message | When |
|---|---|
OPENAI_API_KEY is not set. (or ANTHROPIC_API_KEY, GEMINI_API_KEY, XAI_API_KEY) | The API key of the driver is empty. Nothing was sent. |
Provider connection failed: ... | No connection or a timeout on the text request, on both attempts. |
Provider request failed: ... | A 4xx or 5xx status on the text request, on both attempts. |
Provider returned non-JSON output (unexpected). | The text of the answer is not a JSON object. |
OpenAI response did not include output_text. | The OpenAI answer has no output_text item. |
Claude response did not include a text block. | The Claude answer has no text block. |
Claude stopped before the answer was complete. Raise ANTHROPIC_MAX_TOKENS or lower maxWords. | Claude reached ANTHROPIC_MAX_TOKENS. |
Claude declined to write about this topic. | Claude refused. |
Gemini blocked the prompt: ... | Google’s safety filter blocked the prompt. |
Gemini response did not include text (finish reason: ...). | The Gemini answer has no text. |
Grok declined to write about this topic: ... | Grok refused. |
Grok response did not include message content. | The Grok answer has no message content. |
Every AI driver failed. ... | The default driver and every fallback driver failed. |
Unsupported AI driver: ... | No built-in or registered driver has this name. |
The previous exception, from Laravel’s HTTP client, is available through getPrevious() for the connection and request failures.
A failing image inside generate() does not throw. The result has errorMessage set to OpenAI Image Error: ..., Gemini Image Error: ... or Grok Image Error: ..., or to Provider cannot generate images. Set AI_GENERATOR_IMAGE_DRIVER to openai, gemini or xai. when the image driver cannot make images. Troubleshooting has the cause and the fix of every message.