Client

Generate text or structured JSON from any PHP context with one method call – CLI commands, hooks, custom controllers.

Generate AI content from PHP with one method call. The Client resolves your configured provider from johannschopplich.copilot options and dispatches text or structured-output requests – reaching the same providers with the same credentials as the Panel, over its own server-side transport.

use JohannSchopplich\Copilot\AI\Client;

$result = Client::instance()->generateObject(
    messages: [
        ['role' => 'user', 'content' => "What's 2+2?"],
    ],
    schema: ['type' => 'object', 'properties' => ['answer' => ['type' => 'integer']], 'required' => ['answer']],
);

Construction

use JohannSchopplich\Copilot\AI\Client;

$client = Client::instance();

The singleton reads johannschopplich.copilot options once and reuses them until you call Client::reset().

Methods

generateObject

public function generateObject(array $messages, array $schema): array
messages
list<array{role: string, content: string}>
Chat messages. Every system message is forwarded – Anthropic concatenates them into its top-level system field, while the OpenAI-compatible providers pass the list through unchanged.
schema
array<string, mixed>
JSON Schema for the response. The provider enforces it via the appropriate structured-output mechanism for its API.

Returns the decoded JSON response as an associative array. Throws ProviderException on any failure.

generateText

public function generateText(array $messages): string
messages
list<array{role: string, content: string}>
Chat messages. Every system message is forwarded – Anthropic concatenates them into its top-level system field, while the OpenAI-compatible providers pass the list through unchanged.

Returns the response text as a plain string. Throws ProviderException on any failure.

requireApiKey

public function requireApiKey(): void

Asserts that the configured default provider has an API key. Throws Kirby\Exception\AuthException with a message pointing to the missing config path. Useful as a preflight before kicking off a long batch operation.

The check applies to the resolved default provider only. A client constructed with an explicit provider instance returns early, since that provider carries its own credentials – the key check then happens on the first request.

reset (static)

public static function reset(): void

Clear the cached singleton. Call this in tests that swap config between cases.

Error Handling

use JohannSchopplich\Copilot\AI\Client;
use JohannSchopplich\Copilot\AI\Exception\ProviderException;
use Kirby\Exception\AuthException;

try {
    $client = Client::instance();
    $client->requireApiKey();

    $result = $client->generateObject($messages, $schema);
} catch (AuthException $error) {
    // Missing API key
} catch (ProviderException $error) {
    // Upstream failure – $error->getDetails() carries provider/model/response context
}
See Exceptions for the full ProviderException payload.

Forcing a Provider for One Call

The resolver always dispatches to the provider set at johannschopplich.copilot.provider. To force a different one for a single call, use providerOverride:

use JohannSchopplich\Copilot\AI\Client;
use JohannSchopplich\Copilot\AI\Providers\AnthropicProvider;
use JohannSchopplich\Copilot\AI\Resolver;
use JohannSchopplich\Copilot\AI\ProviderName;

$config = Resolver::fromKirbyOptions()->forProvider(ProviderName::Anthropic);
$client = new Client(providerOverride: new AnthropicProvider($config));

$result = $client->generateObject($messages, $schema);

Use From a Sister Plugin

The Copilot AI strategy in Content Translator is a working example of consuming Client::generateObject() from another plugin. See the AI Strategy CLI script for a complete page-translation workflow that selects the AI strategy at call time.