Files
wp-agentic-writer/FRONTEND_AND_CHAT_FIX_SUMMARY.md
Dwindi Ramadhana d3f142222c feat: Add connection test caching and reasoning content support
Backend improvements:
- Add cache auto-clear on settings save (class-settings-v2.php)
  - Hooks updated_option action
  - Clears connection test transients when local backend settings change
- Add reasoning_content streaming support (class-local-backend-provider.php)
  - Handles thinking models like Claude extended thinking
  - Captures chunk['choices'][0]['delta']['reasoning_content']

Documentation:
- Add FRONTEND_AND_CHAT_FIX_SUMMARY.md with all fixes
- Add FRONTEND-REFACTOR-PHASE2.md with modularization plan

Note: Splitting effort deferred - will continue iterating on monolith
Next: Fix session history not appearing bug
2026-06-17 05:26:12 +07:00

7.1 KiB
Raw Blame History

WP Agentic Writer Fix Summary: Chat & Frontend Build

Date: 2026-06-16 (original) / 2026-06-17 (updates) Status: 🟢 RESOLVED

This document serves as a hands-off record of the debugging steps, root causes, and fixes applied to resolve the "empty chat response" issue and establish a proper frontend build pipeline.


Updates (2026-06-17)

Additional Backend Improvements

  1. Connection Test Caching - Already existed in class-provider-manager.php (5-min TTL via transients)
  2. Cache Auto-Clear on Settings Save - Added to class-settings-v2.php
    • Hooks to updated_option action
    • Clears connection test cache when local backend settings change
  3. Reasoning Content Parsing - Added to class-local-backend-provider.php
    • Captures reasoning_content from thinking models
    • Debug logging included

Build Validation

Check Result
npm run build Passes
PHP syntax (all files) Passes
Build output dist/sidebar.js (169 KB)

Important: Two sidebar.js Files

File Loaded by PHP?
assets/js/sidebar.js (438 KB) Legacy, NOT loaded
assets/js/dist/sidebar.js (169 KB) Current, loaded

Original Fixes (2026-06-16)


1. Frontend Build Pipeline Established

Problem: The PHP plugin explicitly loads assets/js/dist/sidebar.js. However, ongoing refactoring work was occurring in assets/js/src/index.jsx. Because there was no active build process, changes made in index.jsx were not reflecting in the application.

Solution:

  • Created package.json with esbuild to handle fast JSX compilation.
  • Added scripts/build.js configured specifically for WordPress Gutenberg (using wp.element.createElement and wp.element.Fragment).
  • Critical Fix: Ensured the esbuild configuration wraps the output in an anonymous IIFE (format: "iife") without defining a globalName: "wp". A named global would have caused the compiled script to overwrite WordPress's native window.wp object with undefined, breaking the editor.

Usage:

  • Run npm run build to compile src/index.jsx -> dist/sidebar.js.
  • Run npm run build:watch during active development.

2. Backend Fix: PHP Fatal Error on Connection Test

Problem: When the local backend provider received an HTTP 4xx/5xx error (e.g., when trying to test a connection to a rate-limited or failing model), the entire REST request crashed, resulting in a 500 server error and breaking the chat flow entirely.

Root Cause: In includes/class-local-backend-provider.php (line 882), a double-quoted string was used for a sprintf format: __("API Error (HTTP %1$d): %2$s", "wp-agentic-writer") Because it was double-quoted, PHP attempted to interpolate $d and $s as variables, resolving them to empty strings. The resulting string API Error (HTTP %1): %2 caused sprintf to throw a fatal ValueError: Unknown format specifier ")".

Fix: Changed the double quotes to single quotes to prevent PHP variable interpolation, preserving the intended positional specifiers: __('API Error (HTTP %1$d): %2$s', "wp-agentic-writer") Scanned the rest of the codebase and confirmed this dangerous pattern does not exist anywhere else.


3. Backend Fix: Agentic Models Returning "Empty Responses"

Problem: The user experienced intermittent "empty chat response" errors even when the API connection was successful (HTTP 200).

Root Cause: The configured models (e.g., dough/kr/claude-sonnet-4.5-thinking and ag/gemini-3-flash-agent) are agentic/tool-calling models. When fed a large WordPress system prompt asking for plain prose, these models burned all their tokens on internal "reasoning", attempted to emit a function/tool call, failed (finish_reason: "malformed_function_call"), and returned zero text content. Because the streaming buffer received no content, it fell back to non-streaming, which also yielded zero content, triggering a generic "empty response" error.

Fix:

  1. Better Error Surfacing: Updated the streaming and fallback logic in class-local-backend-provider.php to actively capture the finish_reason payload.
  2. If the provider returns empty content but has a finish reason of malformed_function_call, tool_calls, or function_call, the backend now intercepts this and throws a highly specific, actionable error:

    "The selected model [Model Name] returned no text (finish reason: tool/function call). This usually means an agentic/coding model is being used for prose. Choose a standard chat model (without an -agent or -agentic suffix) in Settings."

  3. Config Alignment: Used WP-CLI to update the WordPress options table, switching the local backend models from the agentic variants to the standard gemini/gemini-3-flash-preview for all prose tasks (chat, writing, planning, etc.).

Summary of Touched Files

  • package.json (New)
  • scripts/build.js (New)
  • assets/js/dist/sidebar.js (Rebuilt)
  • includes/class-local-backend-provider.php (Fixed string interpolation, added finish_reason edge-case handling, added error payload parsing).

The chat functionality is now robust, gracefully handles agentic model failures, and the React frontend can be reliably compiled from index.jsx.


4. Next Recommendations

With the frontend build pipeline established and the critical backend crashes resolved, the foundation is stable. Here are the recommended next steps:

  1. Complete the React File Splitting (Refactor Phase 2) ⚠️ IN PROGRESS

    • Now that index.jsx compiles successfully to dist/sidebar.js, the massive 11,000+ line index.jsx should be split into modular React components.
    • See FRONTEND-REFACTOR-PHASE2.md for the detailed modularization plan.
    • The new esbuild setup natively supports resolving local imports, meaning you can safely extract components into a src/components/ directory and import them into index.jsx without changing the PHP backend.
    • Key clarification: The source is src/index.jsx, which compiles to dist/sidebar.js. We are NOT creating a new sidebar.jsx source file - we are modularizing the existing index.jsx.
  2. Optimize test_connection() in the Provider Manager COMPLETED

    • Implemented connection test caching using WordPress transients with 5-minute TTL in class-provider-manager.php.
    • Added automatic cache clearing in class-settings-v2.php when local backend settings are saved (URL, API key, model changes).
    • This eliminates redundant connection tests on every chat request, significantly reducing latency.
  3. Handle Reasoning Tokens for Thinking Models COMPLETED

    • Added reasoning_content parsing to chat_stream() method in class-local-backend-provider.php.
    • The streaming parser now captures chunk["choices"][0]["delta"]["reasoning_content"] from thinking models like Claude extended thinking.
    • Reasoning content is passed through the callback so the frontend can optionally display it in a collapsible section.
    • Debug logging added to help identify when reasoning chunks are received.