Install
Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/bestony/ultra-provider/releases/download/0.0.1/ultra-provider-0.0.1.zipA WordPress plugin that lets an administrator register any OpenAI-compatible API endpoint as a provider for the WordPress AI Client, pull its model list, and choose which models the site's AI features may use.
The other provider plugins in this family ship one hard-coded provider each. Ultra Provider makes the provider registry user-extensible.
What it does
- Registers user-defined providers — every enabled entry becomes a real AI Client provider, so
it appears on the Connectors screen, in the AI plugin's model pickers, in the
/ai/v1/providersREST route and in Bestony's AI Settings. - Delegates credentials to the Connectors API — the API key lives in the standard
connectors_ai_{id}_api_keyoption, with the usual masking, validation and{ID}_API_KEYconstant/environment override. The provider is only "connected" while the endpoint actually answers. - Pulls and curates models —
GET /modelsis fetched from the admin screen; the administrator ticks models and labels each as text, text + vision, or image generation. Manual entry is available for endpoints that hide models. - Applies user-chosen defaults — the selected text, vision and image models are moved to the
front of the
wpai_preferred_*_modelslists. - Handles per-endpoint quirks — structured output mode, token parameter name, extra headers
(with a
{key}placeholder), request timeouts, and key-less local endpoints.
Requirements
- WordPress 7.0 or later (the bundled AI Client and Connectors API).
- PHP 7.4 or later.
Install
Copy this directory to wp-content/plugins/ultra-provider/ and activate the plugin. The
Ultra Provider menu appears in the admin sidebar.
Usage
- Add provider — name, provider ID (the AI Client provider ID and connector ID; derived from
the name when left empty), API base URL such as
https://api.example.com/v1, optional description, credentials URL, authentication mode, structured output mode, token parameter name and extra headers. - Save the API key on Settings > Connectors. The key field, its constant name and its environment variable follow core's connector conventions automatically. Key-less endpoints (Ollama, LM Studio) use authentication mode "None" and skip this step.
- Fetch models on the provider's Models screen, tick the models to expose, and pick each
model's capability:
- Text generation — chat, history, tools and JSON output.
- Text generation + vision — same, plus image input.
- Image generation — the OpenAI images endpoint.
- A model that is not usable can be left unticked.
- Optional defaults — set a default text, vision and image model so AI features prefer them.
Models can be filtered by capability in every picker: an image feature is never offered a chat model, a vision feature only sees models declared with image input.
How it works
ultra-provider.php bootstrap: init 5 registration, init 25 auth backfill, preferences, admin
src/
├── Admin/SettingsPage.php list / add-edit / models / defaults screens, admin-post handlers
├── Config/Repository.php option store: validation, slots, preferences, header parsing
├── Runtime/
│ ├── Slots.php 20 tiny provider classes (ProviderSlot01 … ProviderSlot20)
│ ├── AbstractDynamicProvider.php
│ ├── CuratedModelMetadataDirectory.php
│ ├── DynamicProviderAvailability.php
│ ├── ProviderAuthentication.php
│ ├── RequestTrait.php
│ ├── DynamicTextGenerationModel.php
│ └── DynamicImageGenerationModel.php
└── Util/ Keys, Http, AllowedHosts, ModelCatalog, Preferences
Dynamic classes. The AI Client identifies a provider by its class, and a class's
metadata() is static, so one class is needed per provider. The plugin ships twenty tiny slots;
each slot class carries only its slot number and reads the configuration assigned to that slot.
No eval(), no generated files, and a class is loaded only while its slot is in use.
Registration order. Providers register on init priority 5; WordPress core builds Connectors
cards at priority 15 from the registry, so the entries appear automatically. At priority 25 the
plugin makes sure every registered provider has an authentication instance — an empty one for
key-less endpoints, because the OpenAI-compatible SDK base classes always call
getRequestAuthentication().
Curated catalog. CuratedModelMetadataDirectory reads the selected models from the option
store on every call: no network request, no 24-hour metadata cache, and edits are visible on the
next request.
Availability. DynamicProviderAvailability verifies a provider with GET /models (one-token
chat completion fallback), cached per slot and credential — a success for an hour, a failure for
five minutes. This drives the Connectors "connected" state, the key validation when an admin saves
a key, and the model-preference checks.
Safe requests. The AI Client sends everything through wp_safe_remote_request(), which blocks
loopback/private hosts and non-standard ports. Util\AllowedHosts opts in exactly the hosts and
ports of enabled providers; no other private address is ever allowed.
Options
| Option | Purpose |
|---|---|
ultra_provider_providers |
Provider configurations, keyed by provider ID, including slot and the curated model map. |
ultra_provider_preferences |
Preferred default text / vision / image models. |
Per-provider credentials are stored by the Connectors API, not by this plugin.
Development
No build step and no dependencies; the PSR-4 autoloader is a 20-line file.
php scripts/selfcheck.php
php scripts/selfcheck.php --sdk=/path/to/wp-includes/php-ai-client
The self-check stubs the WordPress functions it needs and covers the option store (slots,
validation, headers, preferences), the model catalog and request construction (structured output
modes, token parameter, custom {key} headers, image response shapes), the availability probe,
the safe-request allowances and the preference filters. It exits non-zero on the first failure
count.
Limitations
- OpenAI-compatible protocol only. Anthropic-style messages APIs and Google's native API are not supported.
- Twenty providers per site; remove one to free its slot.
- Chat and image models are separate. One model ID cannot be both, matching the AI Client's capability model.
- A provider ID that collides with another plugin's provider or connector is refused; the other plugin wins.
License
GPL-2.0-or-later.
Releases
1 release. Each count is every asset in that release; expand a row for the breakdown.