OptionalbaseURL: stringProtected_Protected property to store additional provider-specific settings
ProtectedthinkingState tracking for streaming thinking extraction Providers should initialize this if they support thinking models
Get the current additional settings
ProtectedapiOnly sub-classes can access the API key
Read only getter method to get the OpenAI instance
Whether this LLM provider supports assistant prefill (pre-seeding the start of the model's response). Providers that support prefill should override this to return true. This is used as a code-level default when database metadata (AIModelType/AIModel/AIModelVendor.SupportsPrefill) is null. Database values of true/false override this getter.
OpenAI supports streaming
OpenAI natively supports tool calling (tools / tool_calls / tool role messages).
Subclasses targeting OpenAI-compatible gateways inherit this; one whose endpoint does NOT
accept a tools array should override it back to false.
ProtectedaddAdd thinking content to a chat completion message
OptionalthinkingContent: stringProtectedapplyAdds the native tool-calling fields to an outgoing request when the caller declared tools.
OpenAI's tool_choice vocabulary is nearly the neutral one — 'auto' | 'none' | 'required'
pass through unchanged; only the named form is reshaped. Parallelism is a top-level request
field here, unlike Anthropic where it hangs off the choice object.
The request body being assembled (mutated in place)
The chat params for this request
ProtectedBuildThe result of a cancelled request, the same for every driver: a failed result with no choices,
statusText 'cancelled', and an errorInfo that says Cancelled (Fatal, never failed over) —
or, when the signal was aborted by a timeout, a retriable NetworkError.
Optionaloptions: { error?: unknown; message?: string; signal?: AbortSignal }Optionalerror?: unknownThe error the abort raised, kept on exception.
Optionalmessage?: stringThe message to report; defaults to one naming the signal's reason.
Optionalsignal?: AbortSignalThe request's abort signal, read for why it was aborted.
ProtectedbuildPer-request options handed to the OpenAI SDK as the SECOND argument of
chat.completions.create(body, options) — distinct from the request BODY.
The only option we set today is signal, which carries ChatParams.cancellationToken
down to the SDK's fetch call so an abort (caller cancellation or an AIPromptRunner
timeout) actually tears down the HTTP socket instead of merely abandoning the promise.
This is honored on BOTH the streaming and non-streaming paths.
The SDK's own retry loop checks options.signal.aborted before every attempt and throws
APIUserAbortError rather than retrying, so a cancelled request stays cancelled.
Returned as a structural literal (rather than the SDK's RequestOptions, which is not
exported from the package root) — every field of RequestOptions is optional, so this is
assignable to it.
Process a chat completion request. If streaming is enabled and supported, this will route to the streaming implementation.
Process multiple chat completion requests in parallel. This is useful for:
Array of chat completion parameter objects
Optionalcallbacks: ParallelChatCompletionsCallbacksOptional callbacks for progress and individual completions
Promise resolving to an array of ChatResults in the same order as the input params
Classification through a driver method is deprecated along with the legacy AI
Actions system, its only caller, and will be removed in the next major version. Most drivers
do not implement it. Run an AI Prompt through AIPromptRunner (@memberjunction/ai-prompts)
instead, which adds model selection, failover and cost tracking.
Clear all additional settings This is useful for resetting the state of the provider or when switching between different configurations.
Utility method to map a MemberJunction role to OpenAI role
ProtectedcreateProtectedextractExtract thinking content from non-streaming content This method handles case-insensitive extraction of thinking blocks
ProtectedfinalizeCreate the final response from streaming results for OpenAI
ProtectedflushReturns (and clears) any user-visible content the thinking-tag stripper is still holding back at
the end of a stream. Mid-stream, processStreamChunkWithThinking holds back a trailing
fragment that could be the start of a <think>/</think> tag so a split tag never leaks as
partial text; once the stream ends, such a fragment is real content and must be emitted (bug A5).
Only flushes when NOT inside a thinking block: an unterminated <think> block's buffered text is
reasoning, not answer, and is left held back (never surfaced as visible content). Returns ''
when thinking extraction isn't active (no state) or there's nothing to flush.
OpenAI supports image file inputs natively via vision.
Values reflect OpenAI's documented chat-completions vision API hard limits (https://platform.openai.com/docs/guides/images-vision):
Note: the docs specify NO per-image size cap — only the request-level payload ceiling. We therefore set MaxFileSize to the same 512 MB value so this layer never rejects a single file OpenAI would accept; the effective constraint is that the SUM of all files in a request stays under 512 MB, which callers must enforce.
These are API-level constraints — consistent across vision-capable chat models (gpt-4o, gpt-4.1, gpt-4-turbo, etc.), not per-model — so returning them from the shared driver is correct. Subclasses/wrappers that target non-standard endpoints (Azure OpenAI with its 50 MB cap, OpenAI-compatible gateways, etc.) should override this method if their limits differ.
ProtectedgetExtra request-body params merged into BOTH the streaming and non-streaming ChatCompletion
requests, beyond the standard OpenAI schema. Default is none. Subclasses targeting
OpenAI-compatible gateways override this to opt into provider extensions the OpenAI SDK
passes through verbatim — e.g. OpenRouter returns usage.cost / usage.cost_details only
when usage: { include: true } is sent on the request.
ProtectedgetGet the thinking tag format for this provider Providers can override this to customize the thinking tag format
ProtectedhandleTemplate method for handling streaming chat completion This implements the common pattern across providers while delegating provider-specific logic to abstract methods.
ProtectedinitializeInitialize thinking stream state for streaming extraction
ProtectedIsWhether a request ended because it was aborted: its signal is aborted, the error is an abort by
name (AbortError, APIUserAbortError, RequestAbortedError), or IsProviderAbortError
recognizes it.
Optionalsignal: AbortSignalProtectedIsRecognizes an abort error the shared names miss. A driver whose SDK raises its own class for an aborted request overrides this. Default: false.
ProtectedisWhether a message is framework-authored volatile state for this request only: the loop agent's trailing runtime-state fragment (date/time, scratchpad, payload, a relocated specialization), which is rebuilt every iteration and must never sit inside a provider's cached prefix.
The base test is the VolatileStateMessageMetadata.volatileState flag the agent layer
sets. A driver may override to recognise the message by other means (Anthropic also accepts
the fragment's tag literal for callers that pass plain text), but should call super first.
ProtectednonImplementation of non-streaming chat completion for OpenAI
ProtectedprocessProcess streaming chunk with thinking extraction This method handles case-insensitive extraction across chunk boundaries
ProtectedprocessProcess a streaming chunk from OpenAI
ProtectedresetReset streaming state for a new request. Overrides the base-class hook so
BaseLLM.handleStreamingChatCompletion calls this both at the start of a
request AND in its finally block — releasing accumulated reasoning/
thinking buffers and preventing state from a prior request bleeding into
the next. Inheriting providers (Cerebras, Fireworks, Groq, xAI, Zhipu,
Inception, LlamaCpp, etc.) automatically benefit from this override. See
audit R2-C5.
ProtectedresetReset thinking stream state
Set additional provider-specific settings Subclasses should override this method to validate required settings
Provider-specific settings
ProtectedsplitSplits an outgoing request around its trailing volatile-state message, so a driver can place
its cache boundary on the last message of head and send tail uncached. Returns null when the
request has no trailing volatile state, in which case the driver formats the whole list as usual.
Neither array is a copy of the input's messages; only the list is new.
Summarization through a driver method is deprecated along with the legacy AI
Actions system, its only caller, and will be removed in the next major version. Run a
summarization AI Prompt through AIPromptRunner (@memberjunction/ai-prompts) instead,
which adds model selection, failover and cost tracking.
ProtectedsupportsCheck if the provider supports thinking models Providers should override this to return true if they support thinking extraction
ProtectedtrailingIndex of the trailing volatile-state message in an outgoing request, or -1 when there is none. The fragment is the LAST message, or the one before it when an assistant prefill has been appended after it. -1 is also returned when nothing precedes the fragment, because then there is no stable history for a provider to cache ahead of it.
Base class for all LLM sub-class implementations. Not all sub-classes will support all methods. If a method is not supported an exception will be thrown.