Provider interface 

interface ProviderInterface
Fully qualified name
\Netresearch\NrLlm\Provider\Contract\ProviderInterface

Contract for LLM providers.

getName(): string

Get human-readable provider name.

getIdentifier(): string

Get provider identifier for configuration.

configure(array $config): void

Configure the provider with its Vault credential identifier and settings.

param array $config

Configuration key-value pairs

isAvailable(): bool

Check if provider is available and configured.

supportsFeature(string|ModelCapability $feature): bool

Check if provider supports a specific feature.

chatCompletion(array $messages, array $options = []): CompletionResponse

Execute chat completion.

param array $messages

A list of typed ChatMessage values or legacy arrays with role and content. Rich provider-specific arrays retain their additional fields, including tool results and multimodal content. Implementations normalize typed messages with toArray().

complete(string $prompt, array $options = []): CompletionResponse

Execute simple completion from a prompt.

embeddings(string|array $input, array $options = []): EmbeddingResponse

Generate embeddings for text.

getAvailableModels(): array

Get list of available models.

getDefaultModel(): string

Get the default model identifier.

testConnection(): array

Test the connection to the provider.

throws

ProviderConnectionException

Returns

array{success, message, models?}

Synchronous Gemini text and thinking 

For Gemini chatCompletion() and chatCompletionWithTools(), all string text parts of the first candidate contribute in their original order. Native parts with thought: true populate CompletionResponse::$thinking; other text parts populate $content. Neither sequence gains an invented separator, and native text keeps its whitespace.

The joined visible text then uses the existing <think>...</think> extraction once, including a delimiter split across parts. Inline blocks keep their existing trimming and whitespace normalization. If native and inline thinking both contribute, $thinking contains native text, one newline and inline thinking. With neither contribution, it is null. Native-only responses have empty visible content. This does not change streaming or vision parsing, and preserves tool calls, response fields and the unmodified native parts used by the existing response capture or replay behavior. See ADR-223: Gemini separates native thoughts from text.

interface VisionCapableInterface
Fully qualified name
\Netresearch\NrLlm\Provider\Contract\VisionCapableInterface

Contract for providers supporting vision/image analysis.

analyzeImage(array $content, array $options = []): VisionResponse

Analyze an image.

param array $content

A list of typed VisionContent values. LlmServiceManager::vision() normalizes legacy content-part arrays before calling the provider; direct adapter calls use typed values.

param array $options

Optional configuration

Returns

VisionResponse

supportsVision(): bool

Check if vision is supported.

getSupportedImageFormats(): array

Get supported image formats.

getMaxImageSize(): int

Get maximum image size in bytes.

interface StreamingCapableInterface
Fully qualified name
\Netresearch\NrLlm\Provider\Contract\StreamingCapableInterface

Contract for providers supporting streaming.

streamChatCompletion(array $messages, array $options = []): Generator

Stream chat completion.

supportsStreaming(): bool

Check if streaming is supported.

interface ToolCapableInterface
Fully qualified name
\Netresearch\NrLlm\Provider\Contract\ToolCapableInterface

Contract for providers supporting tool/function calling.

chatCompletionWithTools(array $messages, array $tools, array $options = []): CompletionResponse

Chat with tool calling. Messages support multimodal content (string or array of content blocks).

param array $messages

Typed ChatMessage values or provider-specific legacy message arrays

param array $tools

A list of typed ToolSpec values. LlmServiceManager::chatWithTools() normalizes legacy tool arrays before calling the provider.

supportsTools(): bool

Check if tool calling is supported.

interface DocumentCapableInterface
Fully qualified name
\Netresearch\NrLlm\Provider\Contract\DocumentCapableInterface

Optional capability for Base64 inline document content in chat messages. It adds capability discovery, not a separate completion method.

supportsDocuments(): bool

Check if inline document input is supported.

getSupportedDocumentFormats(): array

Return supported document formats, for example ['pdf'].

interface DecisionCapableInterface
Fully qualified name
\Netresearch\NrLlm\Provider\Contract\DecisionCapableInterface

Optional capability for providers that natively answer typed questions about a screened subject (ADR-211).

decide(DecisionSubject $subject, array $questions, array $options = []): DecisionResponse
param DecisionSubject $subject

Typed subject to evaluate

param array $questions

A list of DecisionQuestion values

param array $options

Configuration call options, including model

throws

InvalidDecisionResponseException for malformed answers; ProviderException for other provider failures

Returns

Typed answers with one valid answer per question

Gemini known JSON-object slots 

Gemini requests encode FunctionCall.args and FunctionResponse.response as JSON objects, including empty and numeric-key maps. This applies to plain chat, tool chat and streaming requests that carry existing assistant turns, including Gemini-owned replay parts restored after an approval resume. The public ToolCall.arguments PHP array and the saved replay carrier remain unchanged; conversion occurs in the final request copy.

Decoded list results retain their values under numeric object keys. Scalar or invalid JSON tool results retain the existing result string fallback. Only these two known object slots are restored. Arbitrary nested object/list kinds already lost by associative decoding remain an open limitation; nested lists retain their current shape. See ADR-224.