Problem
ProviderRegistry currently derives provider authentication from ProviderMetadata::getAuthenticationMethod(), and RequestAuthenticationMethod only maps to ApiKeyRequestAuthentication.
That works for API-key providers, but it makes provider-owned OAuth or token-refresh authentication awkward. A provider that needs to add dynamic bearer tokens or provider-specific headers has to pretend to be API-key based, e.g. by subclassing ApiKeyRequestAuthentication, even when the credential is not an API key.
Concrete case
I tested a local WordPress proof for ChatGPT/Codex-backed OpenAI access via wp-ai-client:
- registered a provider through
AiClient::defaultRegistry()
- refreshed a ChatGPT/Codex OAuth access token
- sent a request to the Codex Responses backend
- normalized the response into
GenerativeAiResult
The live WordPress proof succeeded and returned the expected model text.
The runtime did not need WordPress Core Connectors to execute. The awkward part was only the auth shape: the provider had to expose RequestAuthenticationMethod::apiKey() so the registry would accept the request auth object, even though the auth object was actually OAuth/token-refresh backed and added provider-specific headers.
Why this belongs in php-ai-client
php-ai-client is the runtime layer that knows how providers are registered, how models receive request auth, and how request auth objects are validated. WordPress Connectors can later own configuration, credential UI, and storage, but providers need a clean runtime primitive first.
Suggested direction
Add a provider-owned/custom request authentication path that allows providers to supply a RequestAuthenticationInterface implementation without requiring it to be one of the hard-coded enum-backed auth implementations.
Possible shapes:
- Add a
custom authentication method whose implementation class is supplied by provider metadata.
- Allow providers to create/default their own
RequestAuthenticationInterface instance through a static factory or provider contract.
- Relax
ProviderRegistry::setRequestAuthenticationForProvider() so provider metadata can explicitly declare a custom request auth class.
The key requirement is that a provider can say: "this provider authenticates requests with this request-auth object", without misrepresenting OAuth/device-flow/session credentials as an API key.
Non-goals
- This is not asking WordPress Core Connectors to support OAuth UI/storage yet.
- This is not asking
php-ai-client to support true streaming over WordPress HTTP. WordPress Core HTTP is buffered; providers that must send stream=true can still parse a fully buffered text/event-stream response in their own model implementation.
- This is not asking for OpenAI/Codex-specific code in
php-ai-client.
Related
Problem
ProviderRegistrycurrently derives provider authentication fromProviderMetadata::getAuthenticationMethod(), andRequestAuthenticationMethodonly maps toApiKeyRequestAuthentication.That works for API-key providers, but it makes provider-owned OAuth or token-refresh authentication awkward. A provider that needs to add dynamic bearer tokens or provider-specific headers has to pretend to be API-key based, e.g. by subclassing
ApiKeyRequestAuthentication, even when the credential is not an API key.Concrete case
I tested a local WordPress proof for ChatGPT/Codex-backed OpenAI access via
wp-ai-client:AiClient::defaultRegistry()GenerativeAiResultThe live WordPress proof succeeded and returned the expected model text.
The runtime did not need WordPress Core Connectors to execute. The awkward part was only the auth shape: the provider had to expose
RequestAuthenticationMethod::apiKey()so the registry would accept the request auth object, even though the auth object was actually OAuth/token-refresh backed and added provider-specific headers.Why this belongs in php-ai-client
php-ai-clientis the runtime layer that knows how providers are registered, how models receive request auth, and how request auth objects are validated. WordPress Connectors can later own configuration, credential UI, and storage, but providers need a clean runtime primitive first.Suggested direction
Add a provider-owned/custom request authentication path that allows providers to supply a
RequestAuthenticationInterfaceimplementation without requiring it to be one of the hard-coded enum-backed auth implementations.Possible shapes:
customauthentication method whose implementation class is supplied by provider metadata.RequestAuthenticationInterfaceinstance through a static factory or provider contract.ProviderRegistry::setRequestAuthenticationForProvider()so provider metadata can explicitly declare a custom request auth class.The key requirement is that a provider can say: "this provider authenticates requests with this request-auth object", without misrepresenting OAuth/device-flow/session credentials as an API key.
Non-goals
php-ai-clientto support true streaming over WordPress HTTP. WordPress Core HTTP is buffered; providers that must sendstream=truecan still parse a fully bufferedtext/event-streamresponse in their own model implementation.php-ai-client.Related