You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As part of the ongoing AI work, we want core to stream AI responses so tokens can be shown as they arrive, instead of waiting for the whole response to finish. We cannot do this today because Requests offers no readable response body you can pull from incrementally. By default it accumulates the entire body in memory before returning (cURL, fsockopen). The only ways to touch bytes mid-transfer are push-only and run entirely inside the blocking request call: the request.progress hook (which still buffers the whole body and cannot abort), and writing to a handle through filename (write-only, no readable stream). Neither yields a stream the AI SDK can pull from.
This blocks the AI client SDK. Its streaming support (WordPress/php-ai-client#255) reads the response body as a stream and pulls from it as data arrives, so it needs an HTTP client that can return a body that is read incrementally. WordPress cannot provide one today, because the HTTP client underneath buffers the response and only returns it once it is complete.
Describe the solution you'd like
Add an opt-in way to read a response body incrementally as it arrives, without holding the whole body in memory.
The shape the SDK needs is a body that can be pulled from while the response is still streaming, so a PSR-18 adapter over WP_Http can expose it as a readable stream. Rough shape:
$response = Requests::request($url, $headers, $data, $type, ['stream' => true]);
while (!$response->eof()) {
$chunk = $response->read(8192); // returns data as it arrives off the connection// handle each chunk
}
When streaming is not requested, nothing changes and behavior stays exactly as it is today. This gives core the primitive it needs to extend WP_Http and let the AI client stream on WordPress.
Describe alternatives you've considered
The existing request.progress hook, which both transports dispatch (cURL, fsockopen), and which WordPress re-emits as the requests-request.progress action. It can observe chunks today, but it cannot back a real streaming feature: the full body is still buffered and returned regardless, the transfer cannot be stopped from it, it is a global action with no per-request context so a caller cannot tell which request a chunk belongs to, and it is only clean on cURL. It also cannot feed the SDK, which pulls from a readable body rather than receiving pushed chunks.
Writing to a custom stream wrapper or php://output through filename. This does deliver chunks without buffering, but it is a write-only sink with no readable stream to pull from, and it runs entirely inside the blocking call. WP_Http also rejects targets like these, since it requires the stream destination to be a writable directory. So it cannot give the SDK a readable body either.
A pull-based readable body is a larger change than a push callback, since it needs the transport to read in steps rather than in one blocking call. The callback is smaller, but it does not satisfy the SDK's pull model on its own, which is why the readable body is the primary ask.
The SDK reads the body as a PSR-7 stream and pulls until the end of the stream, so it needs a body that can be read incrementally, not one pushed through a hook.
I intend to create a pull request to implement this feature myself.
Is your feature request related to a problem?
As part of the ongoing AI work, we want core to stream AI responses so tokens can be shown as they arrive, instead of waiting for the whole response to finish. We cannot do this today because Requests offers no readable response body you can pull from incrementally. By default it accumulates the entire body in memory before returning (cURL, fsockopen). The only ways to touch bytes mid-transfer are push-only and run entirely inside the blocking request call: the
request.progresshook (which still buffers the whole body and cannot abort), and writing to a handle throughfilename(write-only, no readable stream). Neither yields a stream the AI SDK can pull from.This blocks the AI client SDK. Its streaming support (WordPress/php-ai-client#255) reads the response body as a stream and pulls from it as data arrives, so it needs an HTTP client that can return a body that is read incrementally. WordPress cannot provide one today, because the HTTP client underneath buffers the response and only returns it once it is complete.
Describe the solution you'd like
Add an opt-in way to read a response body incrementally as it arrives, without holding the whole body in memory.
The shape the SDK needs is a body that can be pulled from while the response is still streaming, so a PSR-18 adapter over
WP_Httpcan expose it as a readable stream. Rough shape:When streaming is not requested, nothing changes and behavior stays exactly as it is today. This gives core the primitive it needs to extend
WP_Httpand let the AI client stream on WordPress.Describe alternatives you've considered
request.progresshook, which both transports dispatch (cURL, fsockopen), and which WordPress re-emits as therequests-request.progressaction. It can observe chunks today, but it cannot back a real streaming feature: the full body is still buffered and returned regardless, the transfer cannot be stopped from it, it is a global action with no per-request context so a caller cannot tell which request a chunk belongs to, and it is only clean on cURL. It also cannot feed the SDK, which pulls from a readable body rather than receiving pushed chunks.php://outputthroughfilename. This does deliver chunks without buffering, but it is a write-only sink with no readable stream to pull from, and it runs entirely inside the blocking call.WP_Httpalso rejects targets like these, since it requires the stream destination to be a writable directory. So it cannot give the SDK a readable body either.Additional context (optional)
AI SDK streaming PR: Add support for streaming php-ai-client#255
The SDK reads the body as a PSR-7 stream and pulls until the end of the stream, so it needs a body that can be read incrementally, not one pushed through a hook.
I intend to create a pull request to implement this feature myself.