[wp-trac] [WordPress Trac] #64935: Hooks do not fire for wp_ai_client_prompt() flows.

WordPress Trac noreply at wordpress.org
Mon Mar 23 22:28:52 UTC 2026


#64935: Hooks do not fire for wp_ai_client_prompt() flows.
--------------------------+-----------------------------
 Reporter:  shadyvb       |      Owner:  (none)
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  AI            |    Version:
 Severity:  normal        |   Keywords:  has-patch
  Focuses:                |
--------------------------+-----------------------------
 **TL;DR:** Actions `wp_ai_client_before_generate_result` and
 `wp_ai_client_after_generate_result` do not fire for
 `wp_ai_client_prompt()` flows. They do fire for `AiClient::prompt()` (or
 any `PromptBuilder` constructed with the third argument).

 **Summary**

 Core registers a PSR-14 event dispatcher on `WordPress\AiClient\AiClient`
 and ships `WP_AI_Client_Event_Dispatcher`, which maps SDK lifecycle events
 to the documented actions `wp_ai_client_before_generate_result` and
 `wp_ai_client_after_generate_result`.

 The documented PHP entry point `wp_ai_client_prompt()` returns
 `WP_AI_Client_Prompt_Builder`, which constructs
 `WordPress\AiClient\Builders\PromptBuilder` without the optional third
 constructor argument (`EventDispatcherInterface`). The SDK only dispatches
 lifecycle events when that per-instance property is non-null; it does not
 fall back to `AiClient::getEventDispatcher()`.

 Result: for the primary WordPress API (`wp_ai_client_prompt()` →
 `generate_*`), the before/after actions never run, contradicting the
 docblocks on `WP_AI_Client_Event_Dispatcher` and developer expectations.

 Using `AiClient::prompt()` (SDK) does pass `self::$eventDispatcher` into
 `PromptBuilder`, so the same global dispatcher works there — the bug is
 specific to the core wrapper path.

 **Execution flow (now)**

 - `wp-settings.php` calls
 `WordPress\AiClient\AiClient::setEventDispatcher( new
 WP_AI_Client_Event_Dispatcher() );` — static dispatcher is set.
 - `wp_ai_client_prompt( $prompt )` (`wp-includes/ai-client.php`) does `new
 WP_AI_Client_Prompt_Builder( AiClient::defaultRegistry(), $prompt )`.
 - `WP_AI_Client_Prompt_Builder::__construct()` does `new PromptBuilder(
 $registry, $prompt )` — two arguments only (no event dispatcher instance)
 (and the same in the catch path with `new PromptBuilder( $registry ))`.
 - `PromptBuilder::generateResult()` calls `dispatchEvent()` which no-ops
 when `$this->eventDispatcher === null`.
 - `WP_AI_Client_Event_Dispatcher::dispatch()` is never invoked for this
 path → do_action( 'wp_ai_client_before_generate_result' ) /
 wp_ai_client_after_generate_result never run.

 In contrast: `AiClient::prompt()` does: `new PromptBuilder( $registry ??
 self::defaultRegistry(), $prompt, self::$eventDispatcher );`, and then
 those actions are fired.

 **Expected behavior**

 Any code path documented for extension via
 `wp_ai_client_before_generate_result` /
 `wp_ai_client_after_generate_result` should fire when using
 `wp_ai_client_prompt()` and terminating generation methods
 (`generate_text_result()`, etc.), assuming core has bootstrapped the
 default dispatcher (as in `wp-settings.php`).

 **Actual behavior**

 Hooks do not fire for `wp_ai_client_prompt()` flows. They do fire for
 `AiClient::prompt()` (or any `PromptBuilder` constructed with the third
 argument).



 **Steps to reproduce**

 - Use WordPress 7.0+ trunk/beta with AI connectors configured so a simple
 text generation succeeds.
 - In a small mu-plugin or wp shell:

 {{{#!php
 <?php
 add_action( 'wp_ai_client_before_generate_result', static function () {
         error_log( 'before_generate FIRED' );
 }, 10, 1 );

 add_action( 'wp_ai_client_after_generate_result', static function () {
         error_log( 'after_generate FIRED' );
 }, 10, 1 );

 $result = wp_ai_client_prompt( 'Say hello in one word.'
 )->generate_text_result();
 // Optional: inspect $result; generation may succeed while hooks never
 ran.
 }}}

 - Check WP_DEBUG_LOG (or equivalent): no log lines appear.
 - For comparison, temporarily use:

 {{{#!php
 <?php
 $result = \WordPress\AiClient\AiClient::prompt( 'Say hello in one word.'
 )->generateTextResult();
 }}}

 - Observe before/after log lines do appear (same dispatcher, correct
 PromptBuilder wiring).

 **Proposed fix (minimal)**

 In `WP_AI_Client_Prompt_Builder::__construct()`:

 {{{#!php
 <?php
 // Pass the dispatcher into the SDK builder, e.g.
 new PromptBuilder( $registry, $prompt, AiClient::getEventDispatcher() )
 // and in the catch branch
 new PromptBuilder( $registry, null, AiClient::getEventDispatcher() )
 }}}

 This aligns the WordPress wrapper with AiClient::prompt() and with core’s
 existing setEventDispatcher() bootstrap.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/64935>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list