Skip to content

Connectors: Dynamically register providers from WP AI Client registry#11080

Open
gziolo wants to merge 13 commits intoWordPress:trunkfrom
gziolo:update/connectors-dynamic-providers
Open

Connectors: Dynamically register providers from WP AI Client registry#11080
gziolo wants to merge 13 commits intoWordPress:trunkfrom
gziolo:update/connectors-dynamic-providers

Conversation

@gziolo
Copy link
Member

@gziolo gziolo commented Feb 27, 2026

Trac ticket: https://core.trac.wordpress.org/ticket/64730

Follow-up for #11056.
Synced from WordPress/gutenberg#76014.

Summary

  • Expand _wp_connectors_get_provider_settings() to dynamically fetch registered providers from the AI Client registry, in addition to the three hardcoded featured providers (Gemini, OpenAI, Claude).
  • Restructure the return value to be keyed by provider ID with name, description, credentials_url at the top level and settings as a nested array.
  • Filter out providers whose authentication method is not api_key.
  • Update all consumer functions (_wp_connectors_validate_keys_in_rest, _wp_register_default_connector_settings, _wp_connectors_pass_default_keys_to_ai_client) to use the new structure.
  • Update and expand unit tests to cover dynamically registered providers using the mock provider trait.

Test plan

  • Verify npm run test:php -- --group connectors passes (14 tests, 64 assertions).
  • Confirm the three featured providers (google, openai, anthropic) still appear with correct names, descriptions, and credentials URLs.
  • Confirm a third-party provider plugin registered via AiClient::defaultRegistry()->registerProvider() with API key auth appears in the settings.
  • Confirm providers without API key authentication are excluded from the settings.

🤖 Generated with Claude Code

@gziolo
Copy link
Member Author

gziolo commented Feb 27, 2026

@felixarntz, there are still some things to address, but it's close to ready to include all basic metadata that we could expose to the client to automatically expose their cards for registered plugins that implement AI providers.

We would always show 3 featured AI providers by default, but their metadata would be replaced as soon as the corresponding plugin gets installed. For all other AI providers, they would show up on the Connectors screen only after they get installed, solely based on the metadata used during registration.

@github-actions
Copy link

github-actions bot commented Feb 27, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props gziolo, jorgefilipecosta, justlevine, ellatrix.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@gziolo gziolo self-assigned this Feb 27, 2026
@github-actions
Copy link

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

gziolo added a commit to WordPress/gutenberg that referenced this pull request Feb 27, 2026
Polyfills WordPress/wordpress-develop#11080 for the Gutenberg plugin:

- Expand `_gutenberg_get_provider_settings()` to dynamically fetch
  registered providers from the AI Client registry, in addition to the
  three hardcoded featured providers (Gemini, OpenAI, Claude).
- Restructure the return value to be keyed by provider ID with `name`,
  `description`, `credentials_url` at the top level and `settings` as a
  nested array.
- Filter out providers whose authentication method is not `api_key`.
- Update all consumer functions to use the new structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gziolo gziolo force-pushed the update/connectors-dynamic-providers branch 3 times, most recently from 3d53c9c to e625773 Compare March 2, 2026 13:03
@gziolo
Copy link
Member Author

gziolo commented Mar 2, 2026

I synced changes from WordPress/gutenberg#76014 based on the feedback provided there. To land these changes, we will have to sync the JS changes applied in the Gutenberg plugin, too.

@gziolo gziolo force-pushed the update/connectors-dynamic-providers branch from e625773 to b78d7dd Compare March 2, 2026 13:17
Copy link
Member

@jorgefilipecosta jorgefilipecosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work here things tested well for me.
In order to test with the JS/TS changes I applied the following patch:

diff --git a/package.json b/package.json
index acbe679d2f..1ada94f47c 100644
--- a/package.json
+++ b/package.json
@@ -6,9 +6,9 @@
		"type": "svn",
		"url": "https://develop.svn.wordpress.org/trunk"
	},
	"gutenberg": {
-		"ref": "022d8dd3d461f91b15c1f0410649d3ebb027207f"
+		"ref": "853d89e66761c1bc60c2fae1c239261fc8c3b9cf"
	},
	"engines": {
		"node": ">=20.10.0",
		"npm": ">=10.2.3"

Left just some minor comments which can be considered before the merge.

gziolo added a commit to WordPress/gutenberg that referenced this pull request Mar 3, 2026
Polyfills WordPress/wordpress-develop#11080 for the Gutenberg plugin:

- Expand `_gutenberg_get_provider_settings()` to dynamically fetch
  registered providers from the AI Client registry, in addition to the
  three hardcoded featured providers (Gemini, OpenAI, Claude).
- Restructure the return value to be keyed by provider ID with `name`,
  `description`, `credentials_url` at the top level and `settings` as a
  nested array.
- Filter out providers whose authentication method is not `api_key`.
- Update all consumer functions to use the new structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gziolo added a commit to WordPress/gutenberg that referenced this pull request Mar 3, 2026
…#76014)

* Connectors: Dynamically register providers from WP AI Client registry

Polyfills WordPress/wordpress-develop#11080 for the Gutenberg plugin:

- Expand `_gutenberg_get_provider_settings()` to dynamically fetch
  registered providers from the AI Client registry, in addition to the
  three hardcoded featured providers (Gemini, OpenAI, Claude).
- Restructure the return value to be keyed by provider ID with `name`,
  `description`, `credentials_url` at the top level and `settings` as a
  nested array.
- Filter out providers whose authentication method is not `api_key`.
- Update all consumer functions to use the new structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Expose provider settings to the script module

Pass provider data (name, description, credentials URL, setting keys)
to the `connectors-wp-admin` script module via the
`script_module_data` filter, making it available as inline JSON for
the frontend to consume.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Register connectors dynamically from server-provided data

Replace hardcoded per-provider connector components with a single
dynamic loop that reads provider data from the script module data
JSON tag. Known providers retain their SVG logos via a client-side
map; third-party providers from the registry render without a logo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Use ucwords fallback for empty provider name

When a third-party provider from the AI Client registry has no name,
fall back to ucwords( $provider_id ) for a reasonable display label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add authentication_method to provider data structure

Expose authentication_method ('api_key' or 'none') in provider settings
instead of silently filtering out non-API-key providers. This makes the
public-facing interfaces extensible for future authentication methods
while still only implementing api_key support for now.

- Include all registered providers regardless of auth method
- Conditionally generate settings sub-array only for api_key providers
- Expose authenticationMethod in script module data for the frontend
- Skip non-api_key providers in the frontend registration loop
- Rename ProviderConnector to ApiKeyProviderConnector for clarity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add type field to distinguish AI providers from other connectors

Add a 'type' field ('ai_provider') to the provider data structure so
credentials are only passed to the WP AI Client for AI providers. The
frontend also filters by type, only rendering connectors for AI
providers. This separates AI providers from future non-AI connectors
and makes the intent of the API explicit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Group authentication fields into sub-object and eliminate settings duplication

Restructure provider data so credentials_url, setting_name, and method
live together in an authentication sub-object rather than as flat
top-level fields. Remove the redundant settings array from
_gutenberg_get_provider_settings() and move register_setting logic
(label, description, sanitize) into the consumer function. Update all
PHP consumers to read from authentication directly. On the frontend,
change ProviderAuthentication to a discriminated union type for
type-safe access after narrowing on method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename _gutenberg_get_provider_settings to _gutenberg_get_connector_settings

Use the domain term "connector" consistently with the rest of the
codebase (settings group, option names, script module filter).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Clarify authentication docblock for none method

Document that credentials_url and setting_name are only present when
method is 'api_key' and absent when method is 'none'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use URL hostname for help label instead of regex stripping

Replace manual regex URL stripping with new URL().hostname for a
cleaner, more robust extraction of the domain name used as the help
link label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use type-based namespace for connector names

Derive the connector name namespace from data.type instead of
hardcoding 'core/'. Sanitize both parts to only allow letters, numbers,
and hyphens. This produces names like 'ai-provider/google'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename ApiKeyProviderConnector and derive helpLabel internally

Rename ApiKeyProviderConnector to ApiKeyConnector and move helpLabel
derivation from the registration loop into the component itself, since
it already receives helpUrl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Rename _gutenberg_is_api_key_valid to _gutenberg_is_ai_api_key_valid

The function is AI-provider-specific, so the name should reflect that.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Move sanitize helper outside the loop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Pass plugin data from server instead of deriving slug client-side

Hardcode plugin slugs for the three featured AI providers in PHP within
a `plugin` sub-object and pass them to the client via script module data.
When no plugin data is provided (e.g. dynamically registered providers),
the install/activate UI is skipped and the connector assumes the plugin
is already active.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add backport changelog entry for Core PR #11080

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add remove_filter for Core script module data function

Ensures the Gutenberg version overrides the equivalent Core function
(_wp_connectors_get_connector_script_module_data), consistent with the
pattern used by the other connector functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Felix Arntz <flixos90@gmail.com>

Co-authored-by: gziolo <gziolo@git.wordpress.org>
Co-authored-by: raftaar1191 <raftaar1191@git.wordpress.org>
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: felixarntz <flixos90@git.wordpress.org>
gutenbergplugin pushed a commit to WordPress/gutenberg that referenced this pull request Mar 3, 2026
…#76014)

* Connectors: Dynamically register providers from WP AI Client registry

Polyfills WordPress/wordpress-develop#11080 for the Gutenberg plugin:

- Expand `_gutenberg_get_provider_settings()` to dynamically fetch
  registered providers from the AI Client registry, in addition to the
  three hardcoded featured providers (Gemini, OpenAI, Claude).
- Restructure the return value to be keyed by provider ID with `name`,
  `description`, `credentials_url` at the top level and `settings` as a
  nested array.
- Filter out providers whose authentication method is not `api_key`.
- Update all consumer functions to use the new structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Expose provider settings to the script module

Pass provider data (name, description, credentials URL, setting keys)
to the `connectors-wp-admin` script module via the
`script_module_data` filter, making it available as inline JSON for
the frontend to consume.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Register connectors dynamically from server-provided data

Replace hardcoded per-provider connector components with a single
dynamic loop that reads provider data from the script module data
JSON tag. Known providers retain their SVG logos via a client-side
map; third-party providers from the registry render without a logo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Use ucwords fallback for empty provider name

When a third-party provider from the AI Client registry has no name,
fall back to ucwords( $provider_id ) for a reasonable display label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add authentication_method to provider data structure

Expose authentication_method ('api_key' or 'none') in provider settings
instead of silently filtering out non-API-key providers. This makes the
public-facing interfaces extensible for future authentication methods
while still only implementing api_key support for now.

- Include all registered providers regardless of auth method
- Conditionally generate settings sub-array only for api_key providers
- Expose authenticationMethod in script module data for the frontend
- Skip non-api_key providers in the frontend registration loop
- Rename ProviderConnector to ApiKeyProviderConnector for clarity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add type field to distinguish AI providers from other connectors

Add a 'type' field ('ai_provider') to the provider data structure so
credentials are only passed to the WP AI Client for AI providers. The
frontend also filters by type, only rendering connectors for AI
providers. This separates AI providers from future non-AI connectors
and makes the intent of the API explicit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Group authentication fields into sub-object and eliminate settings duplication

Restructure provider data so credentials_url, setting_name, and method
live together in an authentication sub-object rather than as flat
top-level fields. Remove the redundant settings array from
_gutenberg_get_provider_settings() and move register_setting logic
(label, description, sanitize) into the consumer function. Update all
PHP consumers to read from authentication directly. On the frontend,
change ProviderAuthentication to a discriminated union type for
type-safe access after narrowing on method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename _gutenberg_get_provider_settings to _gutenberg_get_connector_settings

Use the domain term "connector" consistently with the rest of the
codebase (settings group, option names, script module filter).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Clarify authentication docblock for none method

Document that credentials_url and setting_name are only present when
method is 'api_key' and absent when method is 'none'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use URL hostname for help label instead of regex stripping

Replace manual regex URL stripping with new URL().hostname for a
cleaner, more robust extraction of the domain name used as the help
link label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use type-based namespace for connector names

Derive the connector name namespace from data.type instead of
hardcoding 'core/'. Sanitize both parts to only allow letters, numbers,
and hyphens. This produces names like 'ai-provider/google'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename ApiKeyProviderConnector and derive helpLabel internally

Rename ApiKeyProviderConnector to ApiKeyConnector and move helpLabel
derivation from the registration loop into the component itself, since
it already receives helpUrl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Rename _gutenberg_is_api_key_valid to _gutenberg_is_ai_api_key_valid

The function is AI-provider-specific, so the name should reflect that.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Move sanitize helper outside the loop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Pass plugin data from server instead of deriving slug client-side

Hardcode plugin slugs for the three featured AI providers in PHP within
a `plugin` sub-object and pass them to the client via script module data.
When no plugin data is provided (e.g. dynamically registered providers),
the install/activate UI is skipped and the connector assumes the plugin
is already active.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add backport changelog entry for Core PR #11080

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add remove_filter for Core script module data function

Ensures the Gutenberg version overrides the equivalent Core function
(_wp_connectors_get_connector_script_module_data), consistent with the
pattern used by the other connector functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Felix Arntz <flixos90@gmail.com>

Co-authored-by: gziolo <gziolo@git.wordpress.org>
Co-authored-by: raftaar1191 <raftaar1191@git.wordpress.org>
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: felixarntz <flixos90@git.wordpress.org>
gziolo and others added 7 commits March 3, 2026 12:40
Expand `_wp_connectors_get_provider_settings()` to fetch registered
providers from the AI Client registry alongside the hardcoded featured
providers. Restructure the return value to be keyed by provider ID with
`name`, `description`, `credentials_url`, and nested `settings`. Filter
out providers that don't use API key authentication. Update all consumer
functions and tests accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…callback.

Filter out empty registry values before merging so hardcoded fallbacks
(e.g. credentials_url, description) are preserved when the registry
doesn't provide them. Replace per-setting $config['mask'] references
with direct '_wp_connectors_mask_api_key' calls since the callback is
always the same. Make REST settings test resilient to dynamically
registered connector providers by querying get_registered_settings().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…and expose to script module.

Polyfills WordPress/gutenberg#76014:

- Rename _wp_connectors_get_provider_settings() to
  _wp_connectors_get_connector_settings() with a restructured return
  format: type field, authentication sub-object (method, credentials_url,
  setting_name) replacing the nested settings array.
- Include all registered providers regardless of auth method (api_key
  or none) instead of filtering out non-API-key providers.
- Move label, description, and sanitize logic into consumer functions.
- Add ucwords() fallback for providers with no name.
- Add _wp_connectors_get_connector_script_module_data() to expose
  connector data to the connectors-wp-admin script module.
- Update all consumer functions and tests to use the new structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
getDescription() is now part of the provider metadata API contract,
so the defensive method_exists() guard is no longer needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rovider names.

- Add plugin sub-object with WordPress.org slugs to featured connector
  definitions for install/activate UI support.
- Expose plugin data in script module output for the frontend.
- Rename _wp_connectors_is_api_key_valid to
  _wp_connectors_is_ai_api_key_valid to reflect AI-provider scope.
- Update provider names and descriptions to match Gutenberg PR #76014.
- Add type check for 'ai_provider' in REST validation function.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Renames Tests_Connectors_WpConnectorsGetProviderSettings to
Tests_Connectors_WpConnectorsGetConnectorSettings and the file from
wpConnectorsGetProviderSettings.php to wpConnectorsGetConnectorSettings.php
to match the renamed _wp_connectors_get_connector_settings() function.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gziolo gziolo force-pushed the update/connectors-dynamic-providers branch from a5a5d22 to 3d72894 Compare March 3, 2026 11:41
gziolo and others added 3 commits March 3, 2026 12:44
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…om fixtures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rity 20.

This ensures plugins registering AI providers at default priority have
completed before connector settings are built from the registry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gziolo
Copy link
Member Author

gziolo commented Mar 3, 2026

@jorgefilipecosta, I synced all the changes from the Gutenberg plugin merged with WordPress/gutenberg#76014, and addressed all your feedback.

Screenshot 2026-03-03 at 13 21 24

@gziolo
Copy link
Member Author

gziolo commented Mar 3, 2026

@ellatrix, would it be possible to sync Gutenberg plugin changes (WordPress/gutenberg@3763f32) as part of this PR? They are necessary so these changes continue to work.

@gziolo gziolo requested a review from ellatrix March 3, 2026 12:24
@ellatrix
Copy link
Member

ellatrix commented Mar 3, 2026

Yes, but if you can, I'd do an update up until (and excluding) the commit you need that includes a log of all changes that were made in Gutenberg. Then you could update the sha as part of this PR that just bumps it by one commit. We currently don't have a good process for this because it's all new. How would we have done it for packages? Cc @desrosj because I know you really like to have the changelog in the commit message.

alecgeatches pushed a commit to Automattic/gutenberg that referenced this pull request Mar 3, 2026
…WordPress#76014)

* Connectors: Dynamically register providers from WP AI Client registry

Polyfills WordPress/wordpress-develop#11080 for the Gutenberg plugin:

- Expand `_gutenberg_get_provider_settings()` to dynamically fetch
  registered providers from the AI Client registry, in addition to the
  three hardcoded featured providers (Gemini, OpenAI, Claude).
- Restructure the return value to be keyed by provider ID with `name`,
  `description`, `credentials_url` at the top level and `settings` as a
  nested array.
- Filter out providers whose authentication method is not `api_key`.
- Update all consumer functions to use the new structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Expose provider settings to the script module

Pass provider data (name, description, credentials URL, setting keys)
to the `connectors-wp-admin` script module via the
`script_module_data` filter, making it available as inline JSON for
the frontend to consume.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Register connectors dynamically from server-provided data

Replace hardcoded per-provider connector components with a single
dynamic loop that reads provider data from the script module data
JSON tag. Known providers retain their SVG logos via a client-side
map; third-party providers from the registry render without a logo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Use ucwords fallback for empty provider name

When a third-party provider from the AI Client registry has no name,
fall back to ucwords( $provider_id ) for a reasonable display label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add authentication_method to provider data structure

Expose authentication_method ('api_key' or 'none') in provider settings
instead of silently filtering out non-API-key providers. This makes the
public-facing interfaces extensible for future authentication methods
while still only implementing api_key support for now.

- Include all registered providers regardless of auth method
- Conditionally generate settings sub-array only for api_key providers
- Expose authenticationMethod in script module data for the frontend
- Skip non-api_key providers in the frontend registration loop
- Rename ProviderConnector to ApiKeyProviderConnector for clarity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add type field to distinguish AI providers from other connectors

Add a 'type' field ('ai_provider') to the provider data structure so
credentials are only passed to the WP AI Client for AI providers. The
frontend also filters by type, only rendering connectors for AI
providers. This separates AI providers from future non-AI connectors
and makes the intent of the API explicit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Group authentication fields into sub-object and eliminate settings duplication

Restructure provider data so credentials_url, setting_name, and method
live together in an authentication sub-object rather than as flat
top-level fields. Remove the redundant settings array from
_gutenberg_get_provider_settings() and move register_setting logic
(label, description, sanitize) into the consumer function. Update all
PHP consumers to read from authentication directly. On the frontend,
change ProviderAuthentication to a discriminated union type for
type-safe access after narrowing on method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename _gutenberg_get_provider_settings to _gutenberg_get_connector_settings

Use the domain term "connector" consistently with the rest of the
codebase (settings group, option names, script module filter).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Clarify authentication docblock for none method

Document that credentials_url and setting_name are only present when
method is 'api_key' and absent when method is 'none'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use URL hostname for help label instead of regex stripping

Replace manual regex URL stripping with new URL().hostname for a
cleaner, more robust extraction of the domain name used as the help
link label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use type-based namespace for connector names

Derive the connector name namespace from data.type instead of
hardcoding 'core/'. Sanitize both parts to only allow letters, numbers,
and hyphens. This produces names like 'ai-provider/google'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename ApiKeyProviderConnector and derive helpLabel internally

Rename ApiKeyProviderConnector to ApiKeyConnector and move helpLabel
derivation from the registration loop into the component itself, since
it already receives helpUrl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Rename _gutenberg_is_api_key_valid to _gutenberg_is_ai_api_key_valid

The function is AI-provider-specific, so the name should reflect that.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Move sanitize helper outside the loop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Pass plugin data from server instead of deriving slug client-side

Hardcode plugin slugs for the three featured AI providers in PHP within
a `plugin` sub-object and pass them to the client via script module data.
When no plugin data is provided (e.g. dynamically registered providers),
the install/activate UI is skipped and the connector assumes the plugin
is already active.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add backport changelog entry for Core PR WordPress#11080

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add remove_filter for Core script module data function

Ensures the Gutenberg version overrides the equivalent Core function
(_wp_connectors_get_connector_script_module_data), consistent with the
pattern used by the other connector functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Felix Arntz <flixos90@gmail.com>

Co-authored-by: gziolo <gziolo@git.wordpress.org>
Co-authored-by: raftaar1191 <raftaar1191@git.wordpress.org>
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: felixarntz <flixos90@git.wordpress.org>
peterwilsoncc pushed a commit to peterwilsoncc/gutenberg-build that referenced this pull request Mar 3, 2026
… (#76014)

* Connectors: Dynamically register providers from WP AI Client registry

Polyfills WordPress/wordpress-develop#11080 for the Gutenberg plugin:

- Expand `_gutenberg_get_provider_settings()` to dynamically fetch
  registered providers from the AI Client registry, in addition to the
  three hardcoded featured providers (Gemini, OpenAI, Claude).
- Restructure the return value to be keyed by provider ID with `name`,
  `description`, `credentials_url` at the top level and `settings` as a
  nested array.
- Filter out providers whose authentication method is not `api_key`.
- Update all consumer functions to use the new structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Expose provider settings to the script module

Pass provider data (name, description, credentials URL, setting keys)
to the `connectors-wp-admin` script module via the
`script_module_data` filter, making it available as inline JSON for
the frontend to consume.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Register connectors dynamically from server-provided data

Replace hardcoded per-provider connector components with a single
dynamic loop that reads provider data from the script module data
JSON tag. Known providers retain their SVG logos via a client-side
map; third-party providers from the registry render without a logo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Use ucwords fallback for empty provider name

When a third-party provider from the AI Client registry has no name,
fall back to ucwords( $provider_id ) for a reasonable display label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add authentication_method to provider data structure

Expose authentication_method ('api_key' or 'none') in provider settings
instead of silently filtering out non-API-key providers. This makes the
public-facing interfaces extensible for future authentication methods
while still only implementing api_key support for now.

- Include all registered providers regardless of auth method
- Conditionally generate settings sub-array only for api_key providers
- Expose authenticationMethod in script module data for the frontend
- Skip non-api_key providers in the frontend registration loop
- Rename ProviderConnector to ApiKeyProviderConnector for clarity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add type field to distinguish AI providers from other connectors

Add a 'type' field ('ai_provider') to the provider data structure so
credentials are only passed to the WP AI Client for AI providers. The
frontend also filters by type, only rendering connectors for AI
providers. This separates AI providers from future non-AI connectors
and makes the intent of the API explicit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Group authentication fields into sub-object and eliminate settings duplication

Restructure provider data so credentials_url, setting_name, and method
live together in an authentication sub-object rather than as flat
top-level fields. Remove the redundant settings array from
_gutenberg_get_provider_settings() and move register_setting logic
(label, description, sanitize) into the consumer function. Update all
PHP consumers to read from authentication directly. On the frontend,
change ProviderAuthentication to a discriminated union type for
type-safe access after narrowing on method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename _gutenberg_get_provider_settings to _gutenberg_get_connector_settings

Use the domain term "connector" consistently with the rest of the
codebase (settings group, option names, script module filter).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Clarify authentication docblock for none method

Document that credentials_url and setting_name are only present when
method is 'api_key' and absent when method is 'none'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use URL hostname for help label instead of regex stripping

Replace manual regex URL stripping with new URL().hostname for a
cleaner, more robust extraction of the domain name used as the help
link label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use type-based namespace for connector names

Derive the connector name namespace from data.type instead of
hardcoding 'core/'. Sanitize both parts to only allow letters, numbers,
and hyphens. This produces names like 'ai-provider/google'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename ApiKeyProviderConnector and derive helpLabel internally

Rename ApiKeyProviderConnector to ApiKeyConnector and move helpLabel
derivation from the registration loop into the component itself, since
it already receives helpUrl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Rename _gutenberg_is_api_key_valid to _gutenberg_is_ai_api_key_valid

The function is AI-provider-specific, so the name should reflect that.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Move sanitize helper outside the loop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Pass plugin data from server instead of deriving slug client-side

Hardcode plugin slugs for the three featured AI providers in PHP within
a `plugin` sub-object and pass them to the client via script module data.
When no plugin data is provided (e.g. dynamically registered providers),
the install/activate UI is skipped and the connector assumes the plugin
is already active.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add backport changelog entry for Core PR #11080

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add remove_filter for Core script module data function

Ensures the Gutenberg version overrides the equivalent Core function
(_wp_connectors_get_connector_script_module_data), consistent with the
pattern used by the other connector functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Felix Arntz <flixos90@gmail.com>

Co-authored-by: gziolo <gziolo@git.wordpress.org>
Co-authored-by: raftaar1191 <raftaar1191@git.wordpress.org>
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: felixarntz <flixos90@git.wordpress.org>

Source: WordPress/gutenberg@7f7f2ea
peterwilsoncc pushed a commit to peterwilsoncc/gutenberg-build that referenced this pull request Mar 3, 2026
… (#76014)

* Connectors: Dynamically register providers from WP AI Client registry

Polyfills WordPress/wordpress-develop#11080 for the Gutenberg plugin:

- Expand `_gutenberg_get_provider_settings()` to dynamically fetch
  registered providers from the AI Client registry, in addition to the
  three hardcoded featured providers (Gemini, OpenAI, Claude).
- Restructure the return value to be keyed by provider ID with `name`,
  `description`, `credentials_url` at the top level and `settings` as a
  nested array.
- Filter out providers whose authentication method is not `api_key`.
- Update all consumer functions to use the new structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Expose provider settings to the script module

Pass provider data (name, description, credentials URL, setting keys)
to the `connectors-wp-admin` script module via the
`script_module_data` filter, making it available as inline JSON for
the frontend to consume.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Register connectors dynamically from server-provided data

Replace hardcoded per-provider connector components with a single
dynamic loop that reads provider data from the script module data
JSON tag. Known providers retain their SVG logos via a client-side
map; third-party providers from the registry render without a logo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Use ucwords fallback for empty provider name

When a third-party provider from the AI Client registry has no name,
fall back to ucwords( $provider_id ) for a reasonable display label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add authentication_method to provider data structure

Expose authentication_method ('api_key' or 'none') in provider settings
instead of silently filtering out non-API-key providers. This makes the
public-facing interfaces extensible for future authentication methods
while still only implementing api_key support for now.

- Include all registered providers regardless of auth method
- Conditionally generate settings sub-array only for api_key providers
- Expose authenticationMethod in script module data for the frontend
- Skip non-api_key providers in the frontend registration loop
- Rename ProviderConnector to ApiKeyProviderConnector for clarity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add type field to distinguish AI providers from other connectors

Add a 'type' field ('ai_provider') to the provider data structure so
credentials are only passed to the WP AI Client for AI providers. The
frontend also filters by type, only rendering connectors for AI
providers. This separates AI providers from future non-AI connectors
and makes the intent of the API explicit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Group authentication fields into sub-object and eliminate settings duplication

Restructure provider data so credentials_url, setting_name, and method
live together in an authentication sub-object rather than as flat
top-level fields. Remove the redundant settings array from
_gutenberg_get_provider_settings() and move register_setting logic
(label, description, sanitize) into the consumer function. Update all
PHP consumers to read from authentication directly. On the frontend,
change ProviderAuthentication to a discriminated union type for
type-safe access after narrowing on method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename _gutenberg_get_provider_settings to _gutenberg_get_connector_settings

Use the domain term "connector" consistently with the rest of the
codebase (settings group, option names, script module filter).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Clarify authentication docblock for none method

Document that credentials_url and setting_name are only present when
method is 'api_key' and absent when method is 'none'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use URL hostname for help label instead of regex stripping

Replace manual regex URL stripping with new URL().hostname for a
cleaner, more robust extraction of the domain name used as the help
link label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Use type-based namespace for connector names

Derive the connector name namespace from data.type instead of
hardcoding 'core/'. Sanitize both parts to only allow letters, numbers,
and hyphens. This produces names like 'ai-provider/google'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Rename ApiKeyProviderConnector and derive helpLabel internally

Rename ApiKeyProviderConnector to ApiKeyConnector and move helpLabel
derivation from the registration loop into the component itself, since
it already receives helpUrl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Update lib/experimental/connectors/default-connectors.php

Co-authored-by: Felix Arntz <flixos90@gmail.com>

* Connectors: Rename _gutenberg_is_api_key_valid to _gutenberg_is_ai_api_key_valid

The function is AI-provider-specific, so the name should reflect that.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Move sanitize helper outside the loop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Pass plugin data from server instead of deriving slug client-side

Hardcode plugin slugs for the three featured AI providers in PHP within
a `plugin` sub-object and pass them to the client via script module data.
When no plugin data is provided (e.g. dynamically registered providers),
the install/activate UI is skipped and the connector assumes the plugin
is already active.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add backport changelog entry for Core PR #11080

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Connectors: Add remove_filter for Core script module data function

Ensures the Gutenberg version overrides the equivalent Core function
(_wp_connectors_get_connector_script_module_data), consistent with the
pattern used by the other connector functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Felix Arntz <flixos90@gmail.com>

Co-authored-by: gziolo <gziolo@git.wordpress.org>
Co-authored-by: raftaar1191 <raftaar1191@git.wordpress.org>
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: felixarntz <flixos90@git.wordpress.org>

Source: WordPress/gutenberg@3763f32
* @return bool|null True if valid, false if invalid, null if unable to determine.
*/
function _wp_connectors_is_api_key_valid( string $key, string $provider_id ): ?bool {
function _wp_connectors_is_ai_api_key_valid( string $key, string $provider_id ): ?bool {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious: are we expecting other type of _wp_connectors_* API keys? we're going to need to handle?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not yet - or at least there is not generally applicable way to validate API keys. This function only exists because for AI provider API keys specifically, we can validate them by using the PHP AI Client SDK abstraction.

@justlevine
Copy link

justlevine commented Mar 3, 2026

@jorgefilipecosta, I synced all the changes from the Gutenberg plugin merged with WordPress/gutenberg#76014, and addressed all your feedback.

@gziolo @jorgefilipecosta I'm catching up - did the rest of the feedback from the initial WordPress/gutenberg#75833 make it in too?

Particularly on my mind is the unencrypted API key storage.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @gziolo for bringing this over here, and all the iterations.

LGTM, except for a few notes. Once you've address these, I think this is good to commit. I'm preemptively approving.

$providers = array(
function _wp_connectors_get_connector_settings(): array {
$connectors = array(
'google' => array(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we sort these alphabetically? Just to be neutral. should be Anthropic, Google, OpenAI

}
return $provider_settings;

return $connectors;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to the above: We should probably sort alphabetically by key here too, so that any registered providers are also integrated properly into the list.

Alternatively, if we want to keep the primary / "official" ones first, we could keep them first, and only sort any additional ones to be alphabetically listed after that.

Copy link

@justlevine justlevine Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to sorting all, and not just the unofficial ones.

}
foreach ( _wp_connectors_get_connector_settings() as $connector_id => $connector_data ) {
$auth = $connector_data['authentication'];
if ( 'api_key' !== $auth['method'] || empty( $auth['setting_name'] ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sanitize_callback and the description below are also only correct for AI providers. So I think here we need to add the check for ai_provider type too.

Probably makes sense anyway, because we only really support these at the moment - prevents future errors by accident.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants