Make WordPress Core

Opened 3 months ago

Closed 3 months ago

#64935 closed defect (bug) (fixed)

Hooks do not fire for wp_ai_client_prompt() flows.

Reported by: shadyvb's profile shadyvb Owned by: flixos90's profile flixos90
Milestone: 7.0 Priority: normal
Severity: normal Version:
Component: AI Keywords: has-patch has-unit-tests
Focuses: Cc:

Description

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
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
$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 
// 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.

Attachments (2)

wp-ai-client-prompt-builder-pass-event-dispatcher.diff (1.1 KB) - added by shadyvb 3 months ago.
Proposed patch
64935.diff (3.5 KB) - added by shadyvb 3 months ago.
patch with tests

Download all attachments as: .zip

Change History (8)

This ticket was mentioned in Slack in #core-ai by shadyvb. View the logs.


3 months ago

#2 @swissspidy
3 months ago

#64938 was marked as a duplicate.

@shadyvb
3 months ago

patch with tests

#3 @gziolo
3 months ago

  • Keywords has-unit-tests added
  • Milestone changed from Awaiting Review to 7.0

#4 @flixos90
3 months ago

  • Owner set to flixos90
  • Status changed from new to reviewing

#6 @flixos90
3 months ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 62101:

AI: Fix prompt lifecycle hooks not firing for wp_ai_client_prompt() flow.

This broke while porting over the relevant logic from the wp-ai-client package to Core.

With this changeset, the lifecycle hooks wp_ai_client_before_generate_result and wp_ai_client_after_generate_result fire as expected.

Props shadyvb, gziolo.
Fixes #64935.

Note: See TracTickets for help on using tickets.