Skip to content

Conversation

@JasonTheAdams
Copy link
Member

This PR will add the Client Adapter so that the PHP AI Client uses the WP functions to fulfill requests.

@JasonTheAdams JasonTheAdams self-assigned this Aug 30, 2025
@JasonTheAdams JasonTheAdams mentioned this pull request Aug 30, 2025
6 tasks
Copy link

@dkotter dkotter left a comment

Choose a reason for hiding this comment

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

In testing out implementing the PHP AI Client package in one of our plugins, ran into an issue where our E2E tests all fail. The issue for us is we install a test plugin during our E2E tests that hooks into pre_http_request and returns mocked responses (so we don't have to hit actual APIs every time we run tests).

This doesn't work when requests are sent by the PHP AI Client package as it doesn't use the WordPress HTTP API. I had thought that this PR might solve that but still getting the same problems while testing this. Apologies if I'm missing something obvious here but are there additional steps required to ensure this adapter is used?

@felixarntz
Copy link
Member

@dkotter You're on the bleeding edge 😆

This is all early WIP. This adapter is indeed supposed to fix the problem you mentioned. It's not a bug in the PHP AI Client SDK since it is WordPress agnostic, but that kind of thing is exactly why this package exists.

As far as I can tell, this PR implements the adapter but doesn't use it yet, but that will be added. Apologies for the confusion, but it might be a bit too early to test this package in particular as it's not meant to be usable just yet. That'll hopefully be different in a week or so :)

@dkotter
Copy link

dkotter commented Sep 4, 2025

It's not a bug in the PHP AI Client SDK since it is WordPress agnostic, but that kind of thing is exactly why this package exists.

Correct, not calling that out as a bug, just hadn't thought of that until I opened a PR and saw all our tests fail 😭

As far as I can tell, this PR implements the adapter but doesn't use it yet, but that will be added. Apologies for the confusion, but it might be a bit too early to test this package in particular as it's not meant to be usable just yet. That'll hopefully be different in a week or so

No worries, sounds good. Realize I'm jumping in early here, was just trying to help do some testing on this PR to help get it merged but realize there's lots of things still in progress across all these work streams

@JasonTheAdams JasonTheAdams marked this pull request as ready for review September 9, 2025 23:07
@JasonTheAdams
Copy link
Member Author

@felixarntz This is back to you for review! A couple things to note:

First, I updated the class names and such to reflect PSR-4, and I updated some types stuff to pass PHPStan. We'll simply have more use of @var and ignoring in this project to get things to play nicely between PSR and WordPress. It is what it is. 🤷‍♂️

Second, I added a DiscoveryStrategy implementing class. As far as I can tell, as it's not well documented, this is how to make this discoverable to the HTTPlug system. You'll notice WP_AI_Client_Discovery_Strategy has an init() method, which is what would be called to prepend this to the discovery system. I believe you said you'd like this to be ready for another system to call said methods instead of this package bootstrapping itself?

Third, I added the nyholm/psr7 package to provide a PSR17 factory. It seems to be the de facto lightweight solution and is PHP 7.2 compatible. My only concern is this issue (Nyholm/psr7#256) which points out some basic PHP 8.4 deprecation fixes that's been neglected.

What do you think? 😄

@neillmcshea neillmcshea added this to the 0.1.0 milestone Sep 10, 2025
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.

@JasonTheAdams Overall, this all makes sense to me. A bit of feedback regarding the WordPress specific implementation.

// TODO: Update to use PHP AI Client exceptions.
throw new \Exception(
$response->get_error_message(), // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
$response->get_error_code() ? (int) $response->get_error_code() : 0
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't work in 99% of scenarios, WordPress error codes are almost always strings with text.

What I would suggest is:

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's see if we can get the exception PR done soon and I'll use that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Finally resolved in de7de24!

Copy link
Member

Choose a reason for hiding this comment

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

My comment here is still relevant I think: What I'm saying is it doesn't make sense to interpret a WP_Error's error code as an integer, since it's meant to be a string.

Copy link
Member

Choose a reason for hiding this comment

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

Per the above, I think we should simply remove this line. There's no reasonable way to maintain the WordPress error code within the exception, unless we come up with a new exception class that can also store a string-shape as error code. But that's overkill IMO.

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.

@JasonTheAdams This looks excellent, great work!

A few questions, and two small things to ideally address before merge.

Comment on lines +60 to +61
// PSR-17 factories - Nyholm's Psr17Factory implements all of them.
$psr17_factories = array(
Copy link
Member

Choose a reason for hiding this comment

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

This is mostly a question for my own understanding: Why do we need this? Why wouldn't we be able to only inject our WordPress HTTP Client and leave the rest?

return array(
array(
'class' => Psr17Factory::class,
'condition' => Psr17Factory::class,
Copy link
Member

Choose a reason for hiding this comment

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

What is the condition field for? And why is it simply the same as class?

* @since n.e.x.t
* @return void
*/
public static function init() {
Copy link
Member

Choose a reason for hiding this comment

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

I assume this method is the entry point to all this? As in: Consuming code will need to call this static method to wire up our WordPress HTTP Client with the PHP AI Client SDK, and nothing else, right?

Comment on lines +72 to +76
$message = sprintf(
'Network error occurred while sending request to %s: %s',
$url,
$response->get_error_message()
);
Copy link
Member

Choose a reason for hiding this comment

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

Minor suggestion: Include the request method here as well.

Suggested change
$message = sprintf(
'Network error occurred while sending request to %s: %s',
$url,
$response->get_error_message()
);
$message = sprintf(
'Network error occurred while sending %s request to %s: %s',
$request->getMethod(),
$url,
$response->get_error_message()
);

// TODO: Update to use PHP AI Client exceptions.
throw new \Exception(
$response->get_error_message(), // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
$response->get_error_code() ? (int) $response->get_error_code() : 0
Copy link
Member

Choose a reason for hiding this comment

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

Per the above, I think we should simply remove this line. There's no reasonable way to maintain the WordPress error code within the exception, unless we come up with a new exception class that can also store a string-shape as error code. But that's overkill IMO.

@felixarntz felixarntz added the [Feature] New feature to highlight in changelogs. label Oct 29, 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.

5 participants