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
This commit is contained in:
122
FRONTEND_AND_CHAT_FIX_SUMMARY.md
Normal file
122
FRONTEND_AND_CHAT_FIX_SUMMARY.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user