Skip to content

Conversation

@felixarntz
Copy link
Member

@felixarntz felixarntz commented Sep 2, 2025

This PR implements the "API Credentials Management" point from #1.

  • Collects all registered providers from all loaded instances of the PHP AI Client SDK.
  • Registers a setting (WordPress option) to store AI provider API credentials.
  • Adds a basic settings screen to paste the API credentials.
  • Wires any provided API credentials into all loaded instances of the PHP AI Client SDK.

Important: It has to be considered that this package may be loaded multiple times within a single WordPress install, whether unprefixed (WordPress\AI_Client) or prefixed (e.g. Vendor\My_Plugin_Dependencies\WordPress\AI_Client). The implementation of this PR is meant to ensure that the setting and its UI are only registered once, regardless of how often this code is called. Additionally though (and this is probably the most tricky part), it still checks the ProviderRegistry for every instance of the package that is loaded, to ensure that every provider that is available anywhere has UI shown so that the user can provide the API credentials.

Note: The settings screen has very basic UI, simply using the classic WordPress Settings API. Eventually, to better productize this, we should consider replacing this with a more appealing design, including potentially usage of React for better interactivity as well as alignment with latest WordPress Core UI principles. But for a first pass, this UI is pragmatic and works.

Screenshot of the settings screen:
Screenshot 2025-10-21 at 9 16 23 AM

@felixarntz
Copy link
Member Author

We will need WordPress/php-ai-client#79 to be merged and released in order to complete the one TODO in this PR and properly support any registered provider.

Base automatically changed from add/wp-env to trunk September 2, 2025 13:48
@felixarntz
Copy link
Member Author

@JasonTheAdams This is now ready for a proper review.

@felixarntz felixarntz marked this pull request as ready for review October 21, 2025 16:18
Copy link
Member

@JasonTheAdams JasonTheAdams left a comment

Choose a reason for hiding this comment

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

All in all it's close to done! I left a handful of little suggestions. 👍


// If the provider was already found via another client class, just this client class name to the list.
if ( isset( $wp_ai_client_providers_metadata[ $provider_id ] ) ) {
$wp_ai_client_providers_metadata[ $provider_id ]['ai_client_classnames'][ AiClient::class ] = true;
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this fits the shape of the array defined above for this variable.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in 4dacba0, but for some reason that I can't figure out PHPStan is complaining. Do you have any hunch?

Copy link
Member

Choose a reason for hiding this comment

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

It seems like it's having trouble resolving the imported type. I'd double check the imported type name, and maybe try using a FQCN in the import.

Copy link
Member Author

Choose a reason for hiding this comment

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

Just tested, the import itself is working fine. I have no idea what's going on here. If I can't resolve this, I'm just going to redeclare the whole thing for now.

Copy link
Member

Choose a reason for hiding this comment

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

That's so weird. 🤷‍♂️

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed via workaround in 0b05a07

It seems intersection types (not union types!) in PHPStan are sort of like a 2nd-class citizen, but that's what we would need here. So I just went with declaring the full shape in one struct, which is okay enough, given it's only 3 properties from elsewhere duplicated here 🤷

@felixarntz felixarntz added this to the 0.1.0 milestone Oct 29, 2025
@felixarntz felixarntz added the [Feature] New feature to highlight in changelogs. label Oct 29, 2025
@jeffpaul
Copy link
Member

jeffpaul commented Nov 3, 2025

@felixarntz @JasonTheAdams it would be super helpful to get this PR to a done state and then a release in the repo so that the AI Experiments plugin can start to use that instead of checking out this specific branch to build functionality off of. Is there anything (besides time) that y'all need to help move things along?

Copy link
Member

@JasonTheAdams JasonTheAdams left a comment

Choose a reason for hiding this comment

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

Good work, @felixarntz! LGTM!

@felixarntz felixarntz merged commit bfa9e48 into trunk Nov 7, 2025
1 check passed
@felixarntz felixarntz mentioned this pull request Nov 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] New feature to highlight in changelogs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants