Connectors: Backport Gutenberg PR #75833 PHP integration#11056
Connectors: Backport Gutenberg PR #75833 PHP integration#11056jorgefilipecosta wants to merge 14 commits intoWordPress:trunkfrom
Conversation
|
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 Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe 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
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
felixarntz
left a comment
There was a problem hiding this comment.
@jorgefilipecosta Thanks for preparing this!
There are of course still several things in here that need iteration, but given it's all private and we need this in Beta 2 tomorrow, I think we can proceed.
I left a few minor comments, that (other than the registry related ones) would be great to address before commit. But overall I think it's good to go in.
We'll need to iron out the whole registry bit and improve DX of registering a connector for Beta 3.
src/wp-includes/connectors.php
Outdated
| * @param string $key The API key. | ||
| * @param string $provider_id The WP AI client provider ID. | ||
| */ | ||
| function _wp_connectors_set_provider_api_key( string $key, string $provider_id ): void { |
There was a problem hiding this comment.
I think this function should return bool, to have an idea whether it worked or not.
There was a problem hiding this comment.
Updated the method in 31ab71c. We might want to revisit this method if we are looking at supporting multiple auth methods. In that case, we might want something more like:
function _wp_connectors_set_provider_auth( string $provider_id, string $auth_type, array $auth_params ): void {This way we would have a general purpose util that devs can use elsewhere, too.
src/wp-includes/connectors.php
Outdated
| return array( | ||
| 'connectors_gemini_api_key' => array( | ||
| 'provider' => 'google', | ||
| 'mask' => '_wp_connectors_mask_gemini_api_key', | ||
| 'sanitize' => '_wp_connectors_sanitize_gemini_api_key', | ||
| ), | ||
| 'connectors_openai_api_key' => array( | ||
| 'provider' => 'openai', | ||
| 'mask' => '_wp_connectors_mask_openai_api_key', | ||
| 'sanitize' => '_wp_connectors_sanitize_openai_api_key', | ||
| ), | ||
| 'connectors_anthropic_api_key' => array( | ||
| 'provider' => 'anthropic', | ||
| 'mask' => '_wp_connectors_mask_anthropic_api_key', | ||
| 'sanitize' => '_wp_connectors_sanitize_anthropic_api_key', | ||
| ), | ||
| ); |
There was a problem hiding this comment.
This is fine for now (i.e. Beta 2), but as discussed earlier today we should enhance this to allow properly registering a provider with all its base information in PHP, and notably reduce the barrier of entry.
First of all, of course this will require a proper registry.
In terms of this function, we would then want to use the registry, and for the 3 ones here, they would continue to be hard-coded, but overridable by the registry. This will allow us to make updates to the provider plugins (which is more appropriate for timing, since we can't quickly ship a new Core release when some of the metadata might be worth a change), and the hard-coded Core references would only be "starting points" / "fallbacks" for when the provider plugins are not active yet.
For the AI connectors specifically, we should as much as possible rely on what the WordPress\AiClient\AiClient::defaultRegistry() already offers:
namedescription(coming in Adds optional description to providers php-ai-client#210)credentialsUrlauthenticationMethod(e.g. "api_key")
Ideally we can simply iterate through those providers and then register the connector for it based on this information. We could support a "merge" behavior, where it would still be allowed to pass in additional information for the provider that may not (yet) have a 1:1 mapping in the WordPress\AiClient provider registry.
We should be able to avoid the need to provide all these callbacks, ideally this is handled centrally in Core, based on the authenticationMethod given.
And as for React UI for the fields, there should be a built-in component that is automatically used based on the given authenticationMethod. For flexibility with more advanced processes (e.g. Jetpack might add some kind of one-button click flow for better UX), we should of course still allow using a custom render component. But for the regular AI provider connector, we need to simplify this so that a single PHP array is all that's needed.
None of this is a blocker for this PR. But wanted to capture it here.
cc @gziolo
There was a problem hiding this comment.
Cool, as noted in #11056 (comment), I plan to work on all the described changes. It seems like a viable path forward, which would make the dev experience for AI provider authors very compelling 💯
| 'connectors', | ||
| $option_name, | ||
| array( | ||
| 'type' => 'string', |
There was a problem hiding this comment.
This works for now, but is problematic and needs to be improved before stable release: Not every credential is a single string. A connector may require two fields (e.g. ID and secret, username and password, ...). We need to abstract this in a way that it's not enforcing a single option per provider usage - or at the very least, if we use a single option, it also needs to allow for more complex data, e.g. an object / associative array with multiple fields in it.
Once we have the connector registry, I think a good idea might be to have an settings field in there that allows an array and then handles these things. Or it could even be a register_settings PHP callback.
(Again, for some predefined authentication methods like "api_key" we could auto-populate this.)
cc @gziolo
There was a problem hiding this comment.
I refactored _wp_connectors_get_provider_settings(), so it generates all necessary settings for registered (hardcoded for now) providers. The current shape will allow us to iterate further while moving most of the logic to that function. I will continue working on it based on the proposed design after Beta 2.
- Change catch blocks from `\Error` to `Exception` (global namespace). - Add `_doing_it_wrong` when an unregistered provider ID is passed. - Add `wp_trigger_error` to surface exception messages in catch blocks. - Change `_wp_connectors_set_provider_api_key` to return `bool`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cks. Replace six identical per-provider mask/sanitize wrapper functions with `_wp_connectors_mask_api_key` used directly and sanitize closures built from a provider map in `_wp_connectors_get_connectors()`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… boilerplate. Rename `_wp_connectors_get_connectors` to `_wp_connectors_get_provider_settings` and dynamically assemble setting names, labels, and descriptions from a minimal provider slug/name map. Add `label` and `description` to `register_setting` calls so they appear in the REST API schema. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| mockedApiResponse.settings = { | ||
| "connectors_gemini_api_key": "", | ||
| "connectors_openai_api_key": "", | ||
| "connectors_anthropic_api_key": "", |
There was a problem hiding this comment.
I don't know if that matters that much, but we use Claude in the UI instead of Anthropic, similar to Gemini instead of Google. We could be more consistent, but it isn't a blocker to me.
There was a problem hiding this comment.
Great catch, I missed this. Actually, I think we should use Google, Anthropic, and OpenAI in the code.
I'm fine using Claude and Gemini in the UI because that's probably more intuitive to many users, but the providers are Anthropic and Google - no question there.
So I think on the code level we should consistently go with those names, i.e. the company names.
There was a problem hiding this comment.
This is exactly what @jorgefilipecosta did in 0b6f6c1, plus he prefixed it with _ai_ to avoid confusion about which service it ties to.
There was a problem hiding this comment.
Looks like that commit also changed the user-facing names though?
I'm personally fine with that, but on the Gutenberg PR it was discussed to use Claude and Gemini for the names in the UI, because more people know these names in relation to AI.
We should still use Anthropic and Google everywhere in the code, but potentially the user-facing name can be adjusted as such.
Since that was discussed on the Gutenberg PR, I wouldn't want to "silently" override that decision again here.
| * @access private | ||
| */ | ||
| function _wp_register_default_connector_settings(): void { | ||
| if ( ! class_exists( '\WordPress\AiClient\AiClient' ) ) { |
There was a problem hiding this comment.
@jorgefilipecosta, do we need this check in WP core? I bet we don't.
There was a problem hiding this comment.
Well we don't excatly "need" but I would prefer to be defensive here, in the same way code normally checks for the inclusion of build generated functions function_exists( 'wp_connectors_wp_admin_render_page' ), AI client also seems like an external lib we had conversations in the past about some constant that makes AI client not even load etc, so I think being defensive here may be good.
There was a problem hiding this comment.
WP AI Client development moves to the WP core. PHP AI Client is only treated as an external library.
|
I need to re-test the branch after all the refactoring applied based on the feedback provided, but it looks like we are good to go if it still works as expected 😅 |
Go for it. |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces a reusable mock provider trait for registering a controllable test provider in the AI Client registry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Uses snake_case parameter names in interface implementations and fixes array alignment in data provider. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@felixarntz and @JasonTheAdams, I added some basic testing coverage so we can iterate on the codebase with more confidence. The part with test trait for the AI provider (4c380a9) was modeled after tests for WP AI Client. I would appreciate a sanity check in case you discover some obvious mistakes or immediate room for improvement. I will take care of it in follow up commit, as I don't consider non-production code a blocker. |
Adds `wp-includes/connectors.php` (loaded from `wp-settings.php`) and registers a Settings > Connectors submenu when the AI client and Connectors admin page renderer are available. Registers connector API key settings in `/wp/v2/settings`, masks key values on option reads, validates keys against provider configuration, and returns `invalid_key` for explicitly requested connector fields when validation fails. Stored connector keys are also passed to the AI client registry on init. Gutenberg PR at WordPress/gutenberg#75833. Developed in #11056. Props jorgefilipecosta, gziolo, flixos90, justlevine, westonruter, jeffpaul, JasonTheAdams, audrasjb, shaunandrews, noruzzaman, mukesh27. Fixes #64730. git-svn-id: https://develop.svn.wordpress.org/trunk@61749 602fd350-edb4-49c9-b593-d223f7449a82
Adds `wp-includes/connectors.php` (loaded from `wp-settings.php`) and registers a Settings > Connectors submenu when the AI client and Connectors admin page renderer are available. Registers connector API key settings in `/wp/v2/settings`, masks key values on option reads, validates keys against provider configuration, and returns `invalid_key` for explicitly requested connector fields when validation fails. Stored connector keys are also passed to the AI client registry on init. Gutenberg PR at WordPress/gutenberg#75833. Developed in WordPress/wordpress-develop#11056. Props jorgefilipecosta, gziolo, flixos90, justlevine, westonruter, jeffpaul, JasonTheAdams, audrasjb, shaunandrews, noruzzaman, mukesh27. Fixes #64730. Built from https://develop.svn.wordpress.org/trunk@61749 git-svn-id: http://core.svn.wordpress.org/trunk@61055 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Trac ticket: https://core.trac.wordpress.org/ticket/64730
Summary
Notes
Testing Instructions
Visit wp-admin/options-general.php?page=connectors-wp-admin and verify the Connectors page appears under Settings.
Verify Connectors appears between General and Writing in the Settings submenu.
Install all AI provider plugins.
Set API keys for every supported provider.
Remove the key and set it again for every supported provider.
When a incorrect API key is provided then it isn't possible to save it.
API keys are properly masked on the frontend (including REST API response).
Deactivate the AI provider plugin from the Plugins screen and activate the plugin again from the Connectors screen.
Uninstall the AI provider plugin from the Plugins screen and install the plugin again from the Connectors screen.
Revoke a key that was valid on the provider website and veify the screen does not says connected anymore.