Issue #3586522: Keep token usage in the chat() Fiber branch

Problem / Motivation

Non-streamed chat calls executed inside a PHP Fiber lose all token usage data. Since core 11.x wraps every web request in a Fiber (Renderer::executeInRenderContext()), this affects virtually every non-streamed chat call made in a web context, against any provider extending OpenAiBasedProviderClientBase.

The Fiber branch of chat() consumes the stream and reconstructs the final output, but only keeps getNormalized() — the token usage that reconstructChatOutput() had correctly captured is thrown away, and the returned ChatOutput carries an empty TokenUsageDto.

Closes #3586522

Changes

  • src/Base/OpenAiBasedProviderClientBase.php: the Fiber branch now keeps the reconstructed ChatOutput and passes its TokenUsageDto to the final ChatOutput (4th constructor argument). The raw response object kept in the output is unchanged.
  • tests/src/Unit/Base/OpenAiBasedProviderClientBaseTest.php: regression test testFiberBranchKeepsTokenUsage() — runs chat() inside a real \Fiber against a stubbed SDK client that streams two content chunks plus a trailing usage chunk (the OpenAI stream_options.include_usage shape), and asserts the returned ChatOutput carries the usage.

Testing

  1. Before the fix: testFiberBranchKeepsTokenUsage fails with Failed asserting that null is identical to 10.
  2. After the fix: all 10 tests in the file pass.
  3. PHPCS (Drupal, DrupalPractice): 0 errors. PHPStan (module config): 0 errors.

Manual check: a non-streamed chat call from a web request (e.g. AI Chat Explorer, streaming disabled) now returns populated getTokenUsage(), matching what the same call returns via Drush.

AI-Generated: Yes (Claude, fix implementation and regression test scaffolding; bug diagnosed, code reviewed and validated manually).

Edited by Jérôme Tchania

Merge request reports

Loading