refactor: Cleanup git state - commit all staged changes
Major refactoring cleanup: - Add new controller architecture (class-controller-*.php) - Add new settings-v2 UI (views/settings-v2/) - Add new CSS architecture (agentic-sidebar.css, tokens) - Add esbuild build pipeline (scripts/build.js, package.json) - Add composer dependencies (vendor/) - Add frontend src directory (assets/js/src/index.jsx) - Add documentation files - Remove old/obsolete files (class-settings.php, old CSS) This commits all pending changes from previous refactoring efforts.
This commit is contained in:
BIN
docs/.DS_Store
vendored
Normal file
BIN
docs/.DS_Store
vendored
Normal file
Binary file not shown.
340
docs/CONTRIBUTING.md
Normal file
340
docs/CONTRIBUTING.md
Normal file
@@ -0,0 +1,340 @@
|
||||
# Contributing to WP Agentic Writer
|
||||
|
||||
Thank you for your interest in contributing to WP Agentic Writer!
|
||||
|
||||
## Project Overview
|
||||
|
||||
WP Agentic Writer is a WordPress plugin that integrates AI-powered writing assistance directly into the Gutenberg editor. It helps writers create better content through plan-first workflows, real-time chat, SEO analysis, and image generation.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Component Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Gutenberg Sidebar │
|
||||
│ (class-gutenberg-sidebar.php) │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Chat Tab │ │ Plan Tab │ │ Image Tab │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
└────────────────────────────┬────────────────────────────────────┘
|
||||
│ REST API
|
||||
┌───────────────────────┼───────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│Controller_ │ │Controller_ │ │Controller_ │
|
||||
│Chat │ │Session │ │Cost │
|
||||
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
||||
│ │ │
|
||||
└────────────────────┼────────────────────┘
|
||||
▼
|
||||
┌───────────────────────┐
|
||||
│ Provider Manager │
|
||||
│ (class-provider- │
|
||||
│ manager.php) │
|
||||
└───────────┬───────────┘
|
||||
│
|
||||
┌───────────────────┼───────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ OpenRouter │ │ Local │ │ Codex │
|
||||
│ Provider │ │ Backend │ │ Provider │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
### Key Classes
|
||||
|
||||
| Class | File | Purpose |
|
||||
|-------|------|---------|
|
||||
| `Gutenberg_Sidebar` | `class-gutenberg-sidebar.php` | Main plugin class, registers REST routes, enqueues assets |
|
||||
| `Controller_Chat` | `class-controller-chat.php` | Chat messaging, streaming, search, research |
|
||||
| `Controller_Session` | `class-controller-session.php` | Session locking for multi-tab safety |
|
||||
| `Controller_Cost` | `class-controller-cost.php` | Cost tracking data |
|
||||
| `Controller_Models` | `class-controller-models.php` | AI model listing and refresh |
|
||||
| `Provider_Manager` | `class-provider-manager.php` | Provider selection and fallback logic |
|
||||
| `AI_Provider` (interface) | `interface-ai-provider.php` | Contract for AI provider implementations |
|
||||
| `Context_Builder` | `class-context-builder.php` | Builds context for AI requests |
|
||||
| `Conversation_Manager` | `class-conversation-manager.php` | Manages conversation sessions |
|
||||
| `Rate_Limiter` | `class-rate-limiter.php` | Rate limiting for REST endpoints |
|
||||
|
||||
---
|
||||
|
||||
## Adding a New REST Endpoint
|
||||
|
||||
### 1. Add the route registration
|
||||
|
||||
In `class-gutenberg-sidebar.php`, add to `register_rest_routes()`:
|
||||
|
||||
```php
|
||||
register_rest_route('wp-agentic-writer/v1', '/my-endpoint', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'handle_my_endpoint'],
|
||||
'permission_callback' => [$this, 'check_permissions'],
|
||||
]);
|
||||
```
|
||||
|
||||
### 2. Add the handler method
|
||||
|
||||
```php
|
||||
/**
|
||||
* Handle my custom endpoint.
|
||||
*
|
||||
* @param WP_REST_Request $request REST request.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function handle_my_endpoint($request)
|
||||
{
|
||||
// Get parameters
|
||||
$params = $request->get_json_params();
|
||||
$post_id = $request->get_param('post_id');
|
||||
|
||||
// Check post permission if post_id is provided
|
||||
if ($post_id > 0 && !$this->check_post_permission($post_id)) {
|
||||
return new WP_Error(
|
||||
'forbidden',
|
||||
__('You do not have permission to access this post.'),
|
||||
['status' => 403]
|
||||
);
|
||||
}
|
||||
|
||||
// Your logic here...
|
||||
|
||||
return new WP_REST_Response(['result' => 'success'], 200);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Add rate limiting (optional)
|
||||
|
||||
```php
|
||||
// Check rate limit
|
||||
$rate_limit = WPAW_Rate_Limiter::check('my_endpoint');
|
||||
if (is_wp_error($rate_limit)) {
|
||||
return $rate_limit;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Document the endpoint
|
||||
|
||||
Add the endpoint to `docs/architecture/REST_API_ENDPOINTS.md`.
|
||||
|
||||
---
|
||||
|
||||
## Adding a New AI Provider
|
||||
|
||||
### 1. Create the provider class
|
||||
|
||||
```php
|
||||
class WP_Agentic_Writer_My_Provider implements WPAW_AI_Provider {
|
||||
// Implement all methods from interface-ai-provider.php
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Register in Provider Manager
|
||||
|
||||
In `class-provider-manager.php`, add to `register_providers()`:
|
||||
|
||||
```php
|
||||
$this->providers['my_provider'] = new WP_Agentic_Writer_My_Provider();
|
||||
```
|
||||
|
||||
### 3. Add to selection logic
|
||||
|
||||
Update `select_provider()` if your provider needs special handling.
|
||||
|
||||
---
|
||||
|
||||
## Adding a New Sidebar Tab
|
||||
|
||||
### 1. Add tab button in JavaScript
|
||||
|
||||
In `assets/sidebar.js`, add to the tab navigation:
|
||||
|
||||
```javascript
|
||||
const tabButtons = document.querySelectorAll('.wpaw-tab-button');
|
||||
// Add your tab button
|
||||
```
|
||||
|
||||
### 2. Add tab content
|
||||
|
||||
```html
|
||||
<div id="my-tab" class="wpaw-tab-content" style="display: none;">
|
||||
<!-- Your tab content -->
|
||||
</div>
|
||||
```
|
||||
|
||||
### 3. Add tab switching logic
|
||||
|
||||
```javascript
|
||||
function showTab(tabId) {
|
||||
// Handle your tab
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CSS Token System
|
||||
|
||||
The plugin uses a three-namespace CSS token system:
|
||||
|
||||
### Scope Tokens (lowest priority)
|
||||
|
||||
```css
|
||||
.wpaw-sidebar-container {
|
||||
--wpaw-color-primary: #2271b1;
|
||||
}
|
||||
```
|
||||
|
||||
### State Tokens
|
||||
|
||||
```css
|
||||
.wpaw-tab-button.active {
|
||||
--wpaw-color-primary: #135e96;
|
||||
}
|
||||
```
|
||||
|
||||
### Intent Tokens (highest priority)
|
||||
|
||||
```css
|
||||
.wpaw-ai-thinking {
|
||||
--wpaw-color-primary: #d63638;
|
||||
}
|
||||
```
|
||||
|
||||
### CSS Class Hierarchy
|
||||
|
||||
```
|
||||
.wpaw-sidebar-container → Base container
|
||||
├── .wpaw-tab-content → Tab panels
|
||||
├── .wpaw-command-area → Input areas
|
||||
├── .wpaw-settings-v2-wrap → Settings pages
|
||||
├── .wpaw-ai-thinking → AI processing state
|
||||
└── .wpaw-error → Error states
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Schema
|
||||
|
||||
### Conversations Table
|
||||
|
||||
```sql
|
||||
CREATE TABLE {prefix}wpaw_conversations (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
session_id VARCHAR(36) NOT NULL UNIQUE,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
post_id BIGINT UNSIGNED DEFAULT NULL,
|
||||
title VARCHAR(255) DEFAULT '',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_post_id (post_id)
|
||||
)
|
||||
```
|
||||
|
||||
### Messages Table
|
||||
|
||||
```sql
|
||||
CREATE TABLE {prefix}wpaw_messages (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
conversation_id BIGINT UNSIGNED NOT NULL,
|
||||
role VARCHAR(20) NOT NULL,
|
||||
content LONGTEXT NOT NULL,
|
||||
metadata JSON DEFAULT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (conversation_id) REFERENCES {prefix}wpaw_conversations(id) ON DELETE CASCADE
|
||||
)
|
||||
```
|
||||
|
||||
### Cost Tracking Table
|
||||
|
||||
```sql
|
||||
CREATE TABLE {prefix}wpaw_cost_tracking (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
provider VARCHAR(50) NOT NULL,
|
||||
model VARCHAR(100) NOT NULL,
|
||||
input_tokens INT UNSIGNED DEFAULT 0,
|
||||
output_tokens INT UNSIGNED DEFAULT 0,
|
||||
cost DECIMAL(10,6) DEFAULT 0,
|
||||
session_id VARCHAR(36) DEFAULT NULL,
|
||||
status VARCHAR(20) DEFAULT 'complete',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Locally
|
||||
|
||||
### Manual Smoke Tests
|
||||
|
||||
After making changes, verify:
|
||||
|
||||
1. **Sidebar loads**: Open a post in Gutenberg, verify sidebar appears
|
||||
2. **Chat works**: Send a message, verify response appears
|
||||
3. **Settings save**: Change settings, refresh, verify persistence
|
||||
4. **Rate limiting**: Rapid requests should return 429 after limit
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging in browser console:
|
||||
|
||||
```javascript
|
||||
window.wpAgenticWriter = { debug: true };
|
||||
```
|
||||
|
||||
### Database Queries
|
||||
|
||||
Use WP-CLI to inspect database:
|
||||
|
||||
```bash
|
||||
wp db query "SELECT * FROM wp_wpaw_conversations LIMIT 5"
|
||||
wp db query "SELECT * FROM wp_wpaw_messages LIMIT 5"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Code Style
|
||||
|
||||
- Follow WordPress PHP Coding Standards
|
||||
- Use `wp_add_inline_style()` for dynamic CSS
|
||||
- Prefix all classes/functions with `wpaw_` or `WP_Agentic_Writer_`
|
||||
- Document all public methods with docblocks
|
||||
|
||||
---
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] All post-scoped endpoints check `edit_post` capability
|
||||
- [ ] Sanitize all input with `sanitize_text_field()`, `absint()`, etc.
|
||||
- [ ] Escape all output with `esc_html()`, `esc_attr()`, etc.
|
||||
- [ ] Use WordPress nonces for form submissions
|
||||
- [ ] Rate limit expensive operations
|
||||
|
||||
---
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
# Activate plugin
|
||||
wp plugin activate wp-agentic-writer
|
||||
|
||||
# Deactivate plugin
|
||||
wp plugin deactivate wp-agentic-writer
|
||||
|
||||
# View cost tracking
|
||||
wp db query "SELECT * FROM wp_wpaw_cost_tracking ORDER BY created_at DESC LIMIT 10"
|
||||
|
||||
# Clear session locks
|
||||
wp db query "DELETE FROM wp_wpaw_conversations WHERE 1=1"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
- [WordPress REST API Handbook](https://developer.wordpress.org/rest-api/)
|
||||
- [Gutenberg Handbook](https://developer.wordpress.org/block-editor/)
|
||||
- [WP AI Client](https://developer.wordpress.org/rest-api/filters/rest_post_dispatch/)
|
||||
145
docs/REGRESSION_CHECKLIST.md
Normal file
145
docs/REGRESSION_CHECKLIST.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Regression Checklist
|
||||
|
||||
Run this checklist after completing refactor sections 1–4, before releasing a new version.
|
||||
|
||||
## Plugin Lifecycle
|
||||
|
||||
| Check | Command / Action | Expected |
|
||||
|-------|------------------|----------|
|
||||
| Activate | Activate plugin in WP Admin | No errors, success message |
|
||||
| Deactivate | Deactivate plugin | No PHP errors in debug.log |
|
||||
| Uninstall | Delete plugin via WP Admin | All options/tables/transients removed |
|
||||
|
||||
**Verify:** `grep -i error debug.log` returns nothing related to this plugin.
|
||||
|
||||
---
|
||||
|
||||
## Debug Log
|
||||
|
||||
| Check | Command / Action | Expected |
|
||||
|-------|------------------|----------|
|
||||
| No notices | `grep -i notice debug.log` | No notices related to plugin |
|
||||
| No warnings | `grep -i warning debug.log` | No warnings related to plugin |
|
||||
| No deprecated | `grep -i deprecated debug.log` | No deprecated warnings |
|
||||
|
||||
**Verify:** Enable `SCRIPT_DEBUG` in wp-config.php, trigger a few AI requests, then check logs.
|
||||
|
||||
---
|
||||
|
||||
## REST API Health
|
||||
|
||||
Test each endpoint with `curl` or REST API tester (authenticated):
|
||||
|
||||
```bash
|
||||
# Authenticate
|
||||
COOKIES="cookies.txt"
|
||||
wp auth generate-cookie
|
||||
|
||||
# List all registered routes
|
||||
curl -s -H "Cookie: wordpress_logged_in_xxx=xxx" \
|
||||
http://localhost/wp-json/wp-agentic-writer/v1/ai-capabilities | jq .
|
||||
|
||||
# Test endpoints (authenticated)
|
||||
curl -s -H "Cookie: wordpress_logged_in_xxx=xxx" \
|
||||
http://localhost/wp-json/wp-agentic-writer/v1/chat-history/1 | jq .
|
||||
|
||||
curl -s -H "Cookie: wordpress_logged_in_xxx=xxx" \
|
||||
http://localhost/wp-json/wp-agentic-writer/v1/seo-audit/1 | jq .
|
||||
```
|
||||
|
||||
| Endpoint | Method | Expected |
|
||||
|----------|--------|----------|
|
||||
| `/ai-capabilities` | GET | 200 + model registry data |
|
||||
| `/chat-history/{post_id}` | GET | 200 + conversation history |
|
||||
| `/seo-audit/{post_id}` | GET | 200 + audit data |
|
||||
| `/suggest-keywords` | POST | 200 + keyword suggestions |
|
||||
| `/refine-multi-pass` | POST | 200 + refined content |
|
||||
| `/generate-meta` | POST | 200 + meta description |
|
||||
|
||||
---
|
||||
|
||||
## Database
|
||||
|
||||
| Check | Command / Action | Expected |
|
||||
|-------|------------------|----------|
|
||||
| Conversations table exists | `SHOW TABLES LIKE 'wpaw_conversations'` | Table found |
|
||||
| Cost entries persist | `SELECT COUNT(*) FROM wpaw_cost_log` | > 0 after AI use |
|
||||
| Image records persist | `SELECT COUNT(*) FROM wpaw_generated_images` | Records exist after image generation |
|
||||
| Plugin update preserves data | Update plugin, re-check above | Same record counts |
|
||||
|
||||
---
|
||||
|
||||
## Settings Page
|
||||
|
||||
Access: **WP Admin → Settings → Agentic Writer**
|
||||
|
||||
| Tab | Check | Expected |
|
||||
|-----|-------|----------|
|
||||
| General | Page loads, no JS errors | No console errors |
|
||||
| Models | Dropdowns populate | All model options visible |
|
||||
| MEMANTO | URL field saves | URL persists after reload |
|
||||
| Costs | Log table renders | Entries display |
|
||||
| All 7 tabs | Switch between tabs | No errors, smooth transitions |
|
||||
|
||||
**Verify:** Open browser DevTools Console (`Cmd+Option+J`), switch tabs, check for red errors.
|
||||
|
||||
---
|
||||
|
||||
## Gutenberg Editor
|
||||
|
||||
| Check | Action | Expected |
|
||||
|-------|--------|----------|
|
||||
| Sidebar loads | Open post in Gutenberg | Sidebar panel visible |
|
||||
| No JS errors | Check console after load | No red errors |
|
||||
| All tabs work | Switch sidebar tabs | Chat, Plan, SEO tabs functional |
|
||||
| Block operations | Add/refine blocks | Works without errors |
|
||||
|
||||
**Verify:** Open browser DevTools Console, trigger a chat message, verify streaming works.
|
||||
|
||||
---
|
||||
|
||||
## Assets
|
||||
|
||||
| Check | Command / Action | Expected |
|
||||
|-------|------------------|----------|
|
||||
| CSS loads | View source, check `<link>` tags | agentic-sidebar.css loaded |
|
||||
| JS loads | View source, check `<script>` tags | sidebar.js loaded |
|
||||
| No 404s | Check Network tab | All resources return 200 |
|
||||
| Fonts load | Check for font-related 404s | All font files accessible |
|
||||
|
||||
---
|
||||
|
||||
## Cron Jobs
|
||||
|
||||
| Check | Command | Expected |
|
||||
|-------|---------|----------|
|
||||
| Cron registered | `wp cron event list` | `wpaw_cleanup_temp_images` appears |
|
||||
| Cron fires | `wp cron event run wpaw_cleanup_temp_images` | No errors |
|
||||
| Schedule exists | `wp cron schedule list` | Plugin schedules available |
|
||||
|
||||
---
|
||||
|
||||
## Quick Smoke Test (5 minutes)
|
||||
|
||||
Run these manually after any significant change:
|
||||
|
||||
1. **Activate** → No errors
|
||||
2. **Open post** → Gutenberg loads with sidebar
|
||||
3. **Send chat** → Streaming response works
|
||||
4. **Run SEO audit** → Report displays
|
||||
5. **Generate image** → Image uploads to Media Library
|
||||
6. **Check settings** → All tabs render
|
||||
7. **Deactivate** → Clean, no errors
|
||||
|
||||
---
|
||||
|
||||
## Pre-Release Checklist
|
||||
|
||||
- [ ] All items above pass
|
||||
- [ ] `debug.log` is clean
|
||||
- [ ] Plugin tested on fresh WP install
|
||||
- [ ] Tested with WP_DEBUG enabled
|
||||
- [ ] All 7 settings tabs verified
|
||||
- [ ] REST endpoints return expected data
|
||||
- [ ] No console errors in Gutenberg
|
||||
- [ ] Unit tests pass (`./vendor/bin/phpunit`)
|
||||
438
docs/SETTINGS_PAGE_FEATURES.md
Normal file
438
docs/SETTINGS_PAGE_FEATURES.md
Normal file
@@ -0,0 +1,438 @@
|
||||
# WP Agentic Writer — Settings Page Features & Fields
|
||||
|
||||
> **Plugin option key:** `wp_agentic_writer_settings` (single serialized option).
|
||||
> **Active settings class:** `WP_Agentic_Writer_Settings_V2` (`includes/class-settings-v2.php`).
|
||||
> **Settings group:** `wp_agentic_writer_settings`.
|
||||
> **Form action:** `options.php`.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Navigation Tabs](#1-navigation-tabs)
|
||||
2. [Tab: General](#2-tab-general)
|
||||
3. [Tab: AI Models](#3-tab-ai-models)
|
||||
4. [Tab: Local Backend](#4-tab-local-backend)
|
||||
5. [Tab: MEMANTO](#5-tab-memanto)
|
||||
6. [Tab: OpenRouter Cost Log](#6-tab-openrouter-cost-log)
|
||||
7. [Tab: Model Guide (Read-Only)](#7-tab-model-guide-read-only)
|
||||
8. [Global Components](#8-global-components)
|
||||
9. [AJAX Actions Reference](#9-ajax-actions-reference)
|
||||
10. [Complete Option Key Index](#10-complete-option-key-index)
|
||||
11. [Sanitization & Validation Rules](#11-sanitization--validation-rules)
|
||||
12. [Key Files Reference](#12-key-files-reference)
|
||||
|
||||
---
|
||||
|
||||
## 1. Navigation Tabs
|
||||
|
||||
The settings page is organized into 6 tabs grouped under two sections:
|
||||
|
||||
**Configuration:** General, AI Models, Local Backend, MEMANTO
|
||||
**Analytics & Docs:** OpenRouter Cost Log, Model Guide
|
||||
|
||||
| Tab ID | Label | Section |
|
||||
|--------|-------|---------|
|
||||
| `general` | General | Configuration |
|
||||
| `models` | AI Models | Configuration |
|
||||
| `local-backend` | Local Backend | Configuration |
|
||||
| `memanto` | MEMANTO | Configuration |
|
||||
| `cost-log` | OpenRouter Cost Log | Analytics & Docs |
|
||||
| `guide` | Model Guide | Analytics & Docs |
|
||||
|
||||
---
|
||||
|
||||
## 2. Tab: General
|
||||
|
||||
### Section 2.1 — API Configuration
|
||||
|
||||
| Field | Option Key | Type | Input | Required | Default | Description |
|
||||
|-------|-----------|------|-------|----------|---------|-------------|
|
||||
| OpenRouter API Key | `openrouter_api_key` | `string` | `password` (with show/hide toggle) | Yes | `""` | Get from openrouter.ai/keys. |
|
||||
| Test Connection | _(button)_ | — | `button` | — | — | AJAX call to `wpaw_test_api_connection`. |
|
||||
|
||||
### Section 2.2 — OpenRouter Budget & Cost Tracking
|
||||
|
||||
**Display data (read-only, fetched from backend):**
|
||||
|
||||
| Data | Variable | Source |
|
||||
|------|----------|--------|
|
||||
| Used This Month | `$monthly_used` | `Cost_Tracker::get_monthly_total()` |
|
||||
| Budget Usage % | `$budget_percent` | Calculated: `(used / budget) * 100` |
|
||||
| Remaining | Calculated | `max(0, budget - used)` |
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Validation | Description |
|
||||
|-------|-----------|------|-------|---------|------------|-------------|
|
||||
| Monthly Budget (USD) | `monthly_budget` | `float` | `number` | `600` | `floatval()`, min 0, step 0.01 | Maximum spend per month. 0 = unlimited. |
|
||||
| Enable Cost Tracking | `cost_tracking_enabled` | `bool` | `checkbox` | `true` | Boolean | Show cost tracking in editor sidebar. |
|
||||
|
||||
### Section 2.3 — Research & Web Search
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Options | Description |
|
||||
|-------|-----------|------|-------|---------|---------|-------------|
|
||||
| Enable Web Search | `web_search_enabled` | `bool` | `checkbox` | `false` | — | Default for new posts; also toggleable per-request in editor sidebar. |
|
||||
| Search Depth | `search_depth` | `string` | `select` | `"medium"` | `low` / `medium` / `high` | Controls search depth level. |
|
||||
|
||||
**OpenRouter Search Engine:**
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Options | Description |
|
||||
|-------|-----------|------|-------|---------|---------|-------------|
|
||||
| Search Engine | `search_engine` | `string` | `select` | `"auto"` | `auto` (Native → Exa fallback) / `native` (Free, built-in) / `exa` (Paid, ~$0.02/search) | Used when active model routes through OpenRouter. |
|
||||
|
||||
**Brave Search API (for Local/Codex):**
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Brave Search API Key | `brave_search_api_key` | `string` | `password` | `""` | Used when active model is Local Backend or Codex. Free tier: 2,000 requests/month. |
|
||||
|
||||
### Section 2.4 — Clarification Quiz
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Options | Description |
|
||||
|-------|-----------|------|-------|---------|---------|-------------|
|
||||
| Enable Clarification Quiz | `enable_clarification_quiz` | `bool` | `checkbox` | `true` | — | Ask clarifying questions when context is missing. |
|
||||
| Confidence Threshold | `clarity_confidence_threshold` | `string` | `select` | `"0.6"` | `0.5` (Very Sensitive) / `0.6` (Sensitive - Recommended) / `0.7` (Balanced) / `0.8` (Strict) / `0.9` (Very Strict) | When to trigger the quiz. |
|
||||
| Context Categories | `required_context_categories` | `array` | multi-checkbox | All 7 checked | `target_outcome` / `target_audience` / `tone` / `content_depth` / `expertise_level` / `content_type` / `pov` | Which context dimensions to ask about. |
|
||||
|
||||
### Section 2.5 — Content Settings (Language)
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Preferred Languages | `preferred_languages` | `array` | multi-checkbox | `["auto", "English", "Indonesian"]` | Languages shown in the language selector when creating articles. |
|
||||
| Custom Languages | `custom_languages` | `array` | dynamic text input list with add/remove | `[]` | Add languages not in the predefined list. |
|
||||
|
||||
**Available predefined languages (24):**
|
||||
|
||||
`auto` (Auto-detect), `English`, `Indonesian` (Bahasa Indonesia), `Javanese` (Basa Jawa), `Sundanese` (Basa Sunda), `Spanish` (Español), `French` (Français), `Arabic` (العربية), `Chinese` (中文), `Japanese` (日本語), `Portuguese` (Português), `German` (Deutsch), `Hindi` (हिंदी), `Korean` (한국어), `Vietnamese` (Tiếng Việt), `Thai` (ไทย), `Tagalog`, `Malay` (Bahasa Melayu), `Russian` (Русский), `Italian` (Italiano), `Dutch` (Nederlands), `Polish` (Polski), `Turkish` (Türkçe), `Swedish` (Svenska)
|
||||
|
||||
### Section 2.6 — Advanced Settings
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Validation | Description |
|
||||
|-------|-----------|------|-------|---------|------------|-------------|
|
||||
| Enable Automated FAQ Schema | `enable_faq_schema` | `bool` | `checkbox` | `false` | Boolean | Auto-inject FAQPage JSON-LD. Compatible with Yoast/RankMath. Disable if SEO plugin handles it. |
|
||||
| Chat History Limit | `chat_history_limit` | `int` | `number` | `20` | `absint()`, capped at 200, min 0 | Messages stored per post. 0 = disable chat history. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Tab: AI Models
|
||||
|
||||
### Section 3.1 — Quick Presets
|
||||
|
||||
Three presets that populate the 6 model selectors below via JavaScript (not saved fields):
|
||||
|
||||
| Preset | Chat/Clarity/Planning | Writing | Refinement | Image | Est. Cost |
|
||||
|--------|----------------------|---------|------------|-------|-----------|
|
||||
| **Budget** | Gemini 2.5 Flash | Mistral Small Creative | Gemini 2.5 Flash | FLUX.2 klein | ~$0.06/article |
|
||||
| **Balanced** | Gemini 2.5 Flash | Claude 3.5 Sonnet | Claude 3.5 Sonnet | Riverflow V2 Max | ~$0.14/article |
|
||||
| **Premium** | Gemini 3 Flash Preview | GPT-4.1 | GPT-4.1 | FLUX.2 max | ~$0.31/article |
|
||||
|
||||
### Section 3.2 — OpenRouter Provider Routing
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Enable Provider Routing | `openrouter_provider_routing_enabled` | `bool` | `checkbox` | `false` | Pin OpenRouter requests to a specific provider for BYOK/routing. |
|
||||
| Provider Slug | `openrouter_provider_slug` | `string` | `text` | `"auto"` | Examples: `openai`, `anthropic`, `google`, `z-ai`. |
|
||||
| Only Use This Provider | `openrouter_provider_only` | `bool` | `checkbox` | `false` | Prevents Azure or other providers when slug is `openai`. |
|
||||
| Allow Fallback Providers | `openrouter_allow_provider_fallbacks` | `bool` | `checkbox` | `false` | Leave off for BYOK-only behavior. |
|
||||
|
||||
### Section 3.3 — AI Model Configuration (6 model selectors)
|
||||
|
||||
All selectors are populated via AJAX from the OpenRouter models API. Each selector shows which provider the model routes through.
|
||||
|
||||
| Field | Option Key | Default Model | data-model-type | Description |
|
||||
|-------|-----------|--------------|-----------------|-------------|
|
||||
| Chat Model | `chat_model` | `google/gemini-2.5-flash` | `chat` | Discussion, research, recommendations |
|
||||
| Clarity Model | `clarity_model` | `google/gemini-2.5-flash` | `clarity` | Prompt analysis, quiz generation |
|
||||
| Planning Model | `planning_model` | `google/gemini-2.5-flash` | `planning` | Article outline generation |
|
||||
| Writing Model | `writing_model` | `anthropic/claude-3.5-haiku` | `execution` | Article draft generation (2-5k words) |
|
||||
| Refinement Model | `refinement_model` | `anthropic/claude-3.5-sonnet` | `execution` | Paragraph edits, rewrites, polish |
|
||||
| Image Model | `image_model` | `openai/gpt-4o` | `image` | Image generation |
|
||||
|
||||
- Writing Model has a legacy alias `execution_model` (mapped to `writing_model` during sanitization).
|
||||
- Refresh Models button: AJAX call to `wpaw_refresh_models`.
|
||||
|
||||
### Section 3.4 — Custom Models
|
||||
|
||||
| Sub-field | Type | Input | Description |
|
||||
|-----------|------|-------|-------------|
|
||||
| Model ID | `string` | `text` | Exact OpenRouter model ID. |
|
||||
| Display Name | `string` | `text` | Optional friendly name. |
|
||||
| Model Type | `string` | `select` | `text` or `image` |
|
||||
| Remove | — | `button` | Delete row. |
|
||||
|
||||
Stored in separate option: `wp_agentic_writer_custom_models` (array of `{id, name, type}` objects).
|
||||
|
||||
- Add button clones from a `<template>` element.
|
||||
- Managed via AJAX: `wpaw_save_custom_model` / `wpaw_delete_custom_model`.
|
||||
|
||||
### Section 3.5 — Estimated Cost Per Article (read-only)
|
||||
|
||||
- Estimated cost calculated client-side based on selected models.
|
||||
- Based on ~2K planning tokens, ~4K execution tokens, and 1 image.
|
||||
- Updated dynamically when model selections change.
|
||||
|
||||
---
|
||||
|
||||
## 4. Tab: Local Backend
|
||||
|
||||
### Section 4.1 — Step 1: Download (informational)
|
||||
|
||||
- Download link: `https://downloads.wpagentic.dev/wp-agentic-writer/agentic-writer-local-backend.zip`
|
||||
- Expandable prerequisites section (Claude CLI, Node.js 18+, Z.ai Coding Plan)
|
||||
|
||||
### Section 4.2 — Step 2: Configure Connection
|
||||
|
||||
| Field | Option Key | Type | Input | Required | Default | Description |
|
||||
|-------|-----------|------|-------|----------|---------|-------------|
|
||||
| Base URL | `local_backend_url` | `string` | `url` | Yes | `""` | URL from Local Backend startup message. Sanitized via `esc_url_raw()`. |
|
||||
| API Key | `local_backend_key` | `string` | `text` | No | `"dummy"` | Use "dummy" for local backend (ignored by proxy). |
|
||||
| Model | `local_backend_model` | `string` | `text` | No | `"claude-local"` | Informational only. Proxy uses Claude CLI default. |
|
||||
| Test Connection | _(button)_ | — | `button` | — | — | AJAX call to `wpaw_test_local_backend`. |
|
||||
|
||||
### Section 4.3 — Step 3: Provider Routing (Advanced)
|
||||
|
||||
A table with **6 task types**, each with a provider select:
|
||||
|
||||
| Task | Option Key Path | Available Providers | Default |
|
||||
|------|----------------|--------------------|---------|
|
||||
| Chat & Discussion | `task_providers[chat]` | OpenRouter, Local Backend, Codex | `openrouter` |
|
||||
| Clarity Check & Quiz | `task_providers[clarity]` | OpenRouter, Local Backend, Codex | `openrouter` |
|
||||
| Outline Planning | `task_providers[planning]` | OpenRouter, Local Backend, Codex | `openrouter` |
|
||||
| Article Writing | `task_providers[writing]` | OpenRouter, Local Backend, Codex | `openrouter` |
|
||||
| Content Refinement | `task_providers[refinement]` | OpenRouter, Local Backend, Codex | `openrouter` |
|
||||
| Image Generation | `task_providers[image]` | OpenRouter only | `openrouter` |
|
||||
|
||||
> Image task is restricted to OpenRouter only.
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Allow OpenRouter Fallback | `allow_openrouter_fallback` | `bool` | `checkbox` | `false` | Auto-fallback to OpenRouter when selected provider fails. Off by default to prevent unexpected charges. |
|
||||
|
||||
### Section 4.4 — Step 4: Enable Web Search (informational)
|
||||
|
||||
- Guidance for setting up Brave Search on the local proxy.
|
||||
- References `brave_search_api_key` from the General tab.
|
||||
- Provides copy-to-clipboard command for `.env` file, restart proxy command, and verification steps.
|
||||
|
||||
### Section 4.5 — Troubleshooting (informational)
|
||||
|
||||
Static help content with common issues and commands.
|
||||
|
||||
---
|
||||
|
||||
## 5. Tab: MEMANTO
|
||||
|
||||
**Description:** Optional persistent memory for the AI writing assistant. The plugin works without it.
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Enable MEMANTO Integration | `memanto_enabled` | `bool` | `checkbox` | `false` | Store and recall memories across sessions. |
|
||||
| MEMANTO Instance URL | `memanto_url` | `string` | `url` | `""` | URL of MEMANTO instance. Sanitized via `esc_url_raw()`. |
|
||||
| Moorcheh API Key | `memanto_moorcheh_key` | `string` | `password` | `""` | Free API key at moorcheh.ai (10K vectors/month). |
|
||||
| Test Connection | _(button)_ | — | `button` | — | AJAX call to `wpaw_test_memanto`. Disabled until both URL and key are filled. Auto-triggers on page load if both fields are filled. |
|
||||
|
||||
**Connection status indicator:**
|
||||
- Shows: Not configured / Checking... / Connected / Error
|
||||
- Displays detail text (service version, Moorcheh connection status)
|
||||
|
||||
---
|
||||
|
||||
## 6. Tab: OpenRouter Cost Log
|
||||
|
||||
> This tab does NOT save settings. It is an analytics dashboard powered entirely by AJAX.
|
||||
|
||||
### Section 6.1 — Cost Summary Dashboard
|
||||
|
||||
Four stats populated by AJAX `wpaw_get_header_stats`:
|
||||
|
||||
| Stat | Element ID | Description |
|
||||
|------|-----------|-------------|
|
||||
| All Time | `#wpaw-stat-all-time` | Total OpenRouter cost ever |
|
||||
| This Month | `#wpaw-stat-monthly` | Current month's cost |
|
||||
| Today | `#wpaw-stat-today` | Today's cost |
|
||||
| Avg Per Post | `#wpaw-stat-avg` | All-time cost / total posts with usage |
|
||||
|
||||
**Action Summary Table** (`#wpaw-action-summary-table`): Cost breakdown per action type (Planning, Writing, Refinement, etc.) with columns: Action, Calls, Total Cost, Avg/Call.
|
||||
|
||||
### Section 6.2 — Filters
|
||||
|
||||
| Filter | Element ID | Type | Options |
|
||||
|--------|-----------|------|---------|
|
||||
| Post ID | `#wpaw-filter-post` | `number` | Any post ID |
|
||||
| Model | `#wpaw-filter-model` | `select` | Populated dynamically |
|
||||
| Type | `#wpaw-filter-type` | `select` | Populated dynamically |
|
||||
| Date From | `#wpaw-filter-date-from` | `date` | — |
|
||||
| Date To | `#wpaw-filter-date-to` | `date` | — |
|
||||
| Apply | `#wpaw-apply-filters` | `button` | — |
|
||||
| Clear | `#wpaw-clear-filters` | `button` | — |
|
||||
|
||||
### Section 6.3 — Detailed Cost Log Table
|
||||
|
||||
| Column | Description |
|
||||
|--------|-------------|
|
||||
| Post Title | Linked post title with edit link |
|
||||
| API Calls | Count of API calls for this post |
|
||||
| Total OpenRouter Cost | Dollar amount |
|
||||
|
||||
**Pagination:** Server-side via AJAX `wpaw_get_cost_log_data`.
|
||||
Per page selector: 10 / 25 (default) / 50 / 100.
|
||||
|
||||
**Export CSV button:** Client-side CSV generation from current filter results.
|
||||
|
||||
---
|
||||
|
||||
## 7. Tab: Model Guide (Read-Only)
|
||||
|
||||
Purely informational — no form fields.
|
||||
|
||||
### 7.1 — How AI Models Are Used
|
||||
Table mapping each pipeline task to model type, estimated cost, and description.
|
||||
|
||||
### 7.2 — Recommended Models
|
||||
Table of curated model recommendations with cost per 1M tokens and notes.
|
||||
|
||||
### 7.3 — Cost Examples
|
||||
Three real-world cost examples:
|
||||
- Single Article (Balanced): ~$0.10-0.15
|
||||
- 10 Articles/Month (Balanced): ~$1.50-2.00
|
||||
- With Web Search: ~$0.02-0.04 extra
|
||||
|
||||
---
|
||||
|
||||
## 8. Global Components
|
||||
|
||||
### Writing Pipeline Progress Bar
|
||||
- 5-step visual pipeline: Context → Planning → Writing → Refinement → Done
|
||||
- Display-only component reflecting real-time writing status
|
||||
- Element: `#wpaw-workflow-display`
|
||||
|
||||
### Save Bar
|
||||
- Version display: `v{WP_AGENTIC_WRITER_VERSION}`
|
||||
- Reset Defaults button: `#wpaw-reset-settings` — restores all settings to defaults
|
||||
- Save Settings button: Form submit with keyboard shortcut (⌘+S / Ctrl+S)
|
||||
|
||||
### Toast Notification
|
||||
- Element: `#wpaw-toast` / `#wpaw-toast-message`
|
||||
- For save/error notifications
|
||||
|
||||
---
|
||||
|
||||
## 9. AJAX Actions Reference
|
||||
|
||||
| Action | Method | Purpose | Tab |
|
||||
|--------|--------|---------|-----|
|
||||
| `wpaw_test_api_connection` | POST | Test OpenRouter API key validity | General |
|
||||
| `wpaw_refresh_models` | POST | Fetch latest models from OpenRouter API | AI Models |
|
||||
| `wpaw_save_custom_model` | POST | Save a custom model entry | AI Models |
|
||||
| `wpaw_delete_custom_model` | POST | Delete a custom model entry | AI Models |
|
||||
| `wpaw_get_cost_log_data` | POST | Paginated cost log data (server-side) | Cost Log |
|
||||
| `wpaw_get_header_stats` | POST | Summary stats for cost dashboard | Cost Log |
|
||||
| `wpaw_debug_models` | POST | Debug model configuration | AI Models |
|
||||
| `wpaw_test_local_backend` | POST | Test local backend proxy connection | Local Backend |
|
||||
| `wpaw_test_memanto` | POST | Test MEMANTO service connection | MEMANTO |
|
||||
|
||||
All AJAX calls use `wpawSettingsV2.ajaxUrl` and `wpawSettingsV2.nonce`.
|
||||
|
||||
---
|
||||
|
||||
## 10. Complete Option Key Index
|
||||
|
||||
All stored under `wp_agentic_writer_settings` unless noted.
|
||||
|
||||
| Option Key | Type | Default | Tab | Section |
|
||||
|-----------|------|---------|-----|---------|
|
||||
| `openrouter_api_key` | `string` | `""` | General | API Configuration |
|
||||
| `brave_search_api_key` | `string` | `""` | General | Research & Web Search |
|
||||
| `monthly_budget` | `float` | `600` | General | Budget & Cost Tracking |
|
||||
| `cost_tracking_enabled` | `bool` | `true` | General | Budget & Cost Tracking |
|
||||
| `web_search_enabled` | `bool` | `false` | General | Research & Web Search |
|
||||
| `search_engine` | `string` | `"auto"` | General | Research & Web Search |
|
||||
| `search_depth` | `string` | `"medium"` | General | Research & Web Search |
|
||||
| `enable_clarification_quiz` | `bool` | `true` | General | Clarification Quiz |
|
||||
| `clarity_confidence_threshold` | `string` | `"0.6"` | General | Clarification Quiz |
|
||||
| `required_context_categories` | `array` | All 7 categories | General | Clarification Quiz |
|
||||
| `preferred_languages` | `array` | `["auto","English","Indonesian"]` | General | Content Settings |
|
||||
| `custom_languages` | `array` | `[]` | General | Content Settings |
|
||||
| `enable_faq_schema` | `bool` | `false` | General | Advanced Settings |
|
||||
| `chat_history_limit` | `int` | `20` | General | Advanced Settings |
|
||||
| `chat_model` | `string` | `"google/gemini-2.5-flash"` | AI Models | Model Configuration |
|
||||
| `clarity_model` | `string` | `"google/gemini-2.5-flash"` | AI Models | Model Configuration |
|
||||
| `planning_model` | `string` | `"google/gemini-2.5-flash"` | AI Models | Model Configuration |
|
||||
| `writing_model` | `string` | `"anthropic/claude-3.5-haiku"` | AI Models | Model Configuration |
|
||||
| `refinement_model` | `string` | `"anthropic/claude-3.5-sonnet"` | AI Models | Model Configuration |
|
||||
| `image_model` | `string` | `"openai/gpt-4o"` | AI Models | Model Configuration |
|
||||
| `openrouter_provider_routing_enabled` | `bool` | `false` | AI Models | Provider Routing |
|
||||
| `openrouter_provider_slug` | `string` | `"auto"` | AI Models | Provider Routing |
|
||||
| `openrouter_provider_only` | `bool` | `false` | AI Models | Provider Routing |
|
||||
| `openrouter_allow_provider_fallbacks` | `bool` | `false` | AI Models | Provider Routing |
|
||||
| `local_backend_url` | `string` | `""` | Local Backend | Connection |
|
||||
| `local_backend_key` | `string` | `"dummy"` | Local Backend | Connection |
|
||||
| `local_backend_model` | `string` | `"claude-local"` | Local Backend | Connection |
|
||||
| `task_providers` | `array` | `[]` (all default to `openrouter`) | Local Backend | Provider Routing |
|
||||
| `allow_openrouter_fallback` | `bool` | `false` | Local Backend | Provider Routing |
|
||||
| `memanto_enabled` | `bool` | `false` | MEMANTO | Integration |
|
||||
| `memanto_url` | `string` | `""` | MEMANTO | Integration |
|
||||
| `memanto_moorcheh_key` | `string` | `""` | MEMANTO | Integration |
|
||||
|
||||
**Separate option:** `wp_agentic_writer_custom_models` — array of `{id: string, name: string, type: "text"|"image"}`.
|
||||
|
||||
---
|
||||
|
||||
## 11. Sanitization & Validation Rules
|
||||
|
||||
| Field | Sanitization | Validation |
|
||||
|-------|-------------|------------|
|
||||
| `openrouter_api_key` | `trim()` | — |
|
||||
| `brave_search_api_key` | `trim()` | — |
|
||||
| `chat_model` | `sanitize_text_field()` | Falls back to `Model_Registry::get_default_model('chat')` |
|
||||
| `clarity_model` | `sanitize_text_field()` | Falls back to registry default |
|
||||
| `planning_model` | `sanitize_text_field()` | Falls back to registry default |
|
||||
| `writing_model` | `sanitize_text_field()` | Falls back to registry default; also maps legacy `execution_model` |
|
||||
| `refinement_model` | `sanitize_text_field()` | Falls back to registry default |
|
||||
| `image_model` | `sanitize_text_field()` | Falls back to registry default |
|
||||
| `web_search_enabled` | Boolean check `=== "1"` | — |
|
||||
| `cost_tracking_enabled` | Boolean check `=== "1"` | — |
|
||||
| `enable_clarification_quiz` | Boolean check `=== "1"` | — |
|
||||
| `enable_faq_schema` | Boolean, defaults `false` | — |
|
||||
| `allow_openrouter_fallback` | Boolean check `=== "1"` | — |
|
||||
| `openrouter_provider_routing_enabled` | Boolean check `=== "1"` | — |
|
||||
| `openrouter_provider_only` | Boolean check `=== "1"` | — |
|
||||
| `openrouter_allow_provider_fallbacks` | Boolean check `=== "1"` | — |
|
||||
| `openrouter_provider_slug` | `sanitize_key()`, empty → `"auto"` | — |
|
||||
| `search_engine` | Whitelist: `auto`, `native`, `exa` | Invalid → `"auto"` |
|
||||
| `search_depth` | Whitelist: `low`, `medium`, `high` | Invalid → `"medium"` |
|
||||
| `monthly_budget` | `floatval()` | Default `600` if not set |
|
||||
| `chat_history_limit` | `absint()`, capped at 200 | Default `20` if not set |
|
||||
| `clarity_confidence_threshold` | Whitelist: `0.5`, `0.6`, `0.7`, `0.8`, `0.9` | Invalid → `"0.6"` |
|
||||
| `required_context_categories` | `array_intersect()` with 7 valid values | Defaults to all 7 |
|
||||
| `preferred_languages` | `array_map('sanitize_text_field')` | Default `["auto","English","Indonesian"]` |
|
||||
| `custom_languages` | `array_map('sanitize_text_field')` + `array_filter()` | Default `[]` |
|
||||
| `local_backend_url` | `esc_url_raw(trim())` | — |
|
||||
| `local_backend_key` | `sanitize_text_field(trim())` | — |
|
||||
| `local_backend_model` | `sanitize_text_field(trim())` | — |
|
||||
| `memanto_enabled` | Boolean check `=== "1"` | — |
|
||||
| `memanto_url` | `esc_url_raw(trim())` | — |
|
||||
| `memanto_moorcheh_key` | `sanitize_text_field(trim())` | — |
|
||||
| `task_providers` | Nested sanitization | Task must be in whitelist, provider must be in whitelist, image restricted to openrouter |
|
||||
|
||||
---
|
||||
|
||||
## 12. Key Files Reference
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `includes/class-settings-v2.php` | Active settings controller (registration, sanitization, AJAX, view data prep) |
|
||||
| `includes/class-model-registry.php` | Centralized model defaults, labels, and fallbacks |
|
||||
| `includes/class-settings.php` | Legacy settings class (deprecated, kept for reference) |
|
||||
| `views/settings/layout.php` | Main layout wrapper |
|
||||
| `views/settings/tab-general.php` | General tab view |
|
||||
| `views/settings/tab-models.php` | AI Models tab view |
|
||||
| `views/settings/tab-local-backend.php` | Local Backend tab view |
|
||||
| `views/settings/tab-memanto.php` | MEMANTO tab view |
|
||||
| `views/settings/tab-cost-log.php` | Cost Log tab view |
|
||||
| `views/settings/tab-guide.php` | Model Guide tab view (read-only) |
|
||||
|
||||
---
|
||||
|
||||
*Generated from codebase analysis on 2026-06-08. Plugin version as defined by `WP_AGENTIC_WRITER_VERSION`.*
|
||||
515
docs/SETTINGS_PAGE_SPECIFICATION.md
Normal file
515
docs/SETTINGS_PAGE_SPECIFICATION.md
Normal file
@@ -0,0 +1,515 @@
|
||||
# WP Agentic Writer — Settings Page Specification
|
||||
|
||||
> **Purpose:** Complete reference for rebuilding the wp-admin settings page.
|
||||
> **Plugin option key:** `wp_agentic_writer_settings` (single serialized option).
|
||||
> **Active settings class:** `WP_Agentic_Writer_Settings_V2` (`includes/class-settings-v2.php`).
|
||||
> **Settings group (for `settings_fields()`):** `wp_agentic_writer_settings`.
|
||||
> **Form action:** `options.php`.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Page Layout Overview](#1-page-layout-overview)
|
||||
2. [Tab: General](#2-tab-general)
|
||||
3. [Tab: AI Models](#3-tab-ai-models)
|
||||
4. [Tab: Local Backend](#4-tab-local-backend)
|
||||
5. [Tab: MEMANTO](#5-tab-memanto)
|
||||
6. [Tab: OpenRouter Cost Log](#6-tab-openrouter-cost-log)
|
||||
7. [Tab: Model Guide (Read-Only)](#7-tab-model-guide-read-only)
|
||||
8. [Global UI Components](#8-global-ui-components)
|
||||
9. [AJAX Actions Reference](#9-ajax-actions-reference)
|
||||
10. [Complete Option Key Index](#10-complete-option-key-index)
|
||||
11. [Sanitization & Validation Rules](#11-sanitization--validation-rules)
|
||||
|
||||
---
|
||||
|
||||
## 1. Page Layout Overview
|
||||
|
||||
The settings page uses a **sidebar + content pane** layout (IDE-style split view).
|
||||
|
||||
```
|
||||
┌──────────────────┬─────────────────────────────────────┐
|
||||
│ Sidebar Nav │ Content Pane (scrollable) │
|
||||
│ │ │
|
||||
│ [Plugin Logo] │ ┌───────────────────────────────┐ │
|
||||
│ │ │ Writing Pipeline Progress Bar │ │
|
||||
│ CONFIGURATION │ └───────────────────────────────┘ │
|
||||
│ ○ General │ │
|
||||
│ ○ AI Models │ ┌───────────────────────────────┐ │
|
||||
│ ○ Local Backend │ │ Active Tab Content │ │
|
||||
│ ○ MEMANTO │ │ │ │
|
||||
│ │ │ │ │
|
||||
│ ANALYTICS&DOCS │ └───────────────────────────────┘ │
|
||||
│ ○ Cost Log │ │
|
||||
│ ○ Model Guide │ ┌───────────────────────────────┐ │
|
||||
│ │ │ [Reset] [Save Settings ⌘+S] │ │
|
||||
│ │ └───────────────────────────────┘ │
|
||||
└──────────────────┴─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- **Framework:** Bootstrap 5 (loaded by the plugin via CDN or bundled)
|
||||
- **Icons:** Bootstrap Icons (`bi-*`) + WordPress Dashicons
|
||||
- **Theme:** Dark theme with accent colors
|
||||
- **Select2:** Used for model selection dropdowns (searchable)
|
||||
- **Sticky save bar** at the bottom with version display, Reset, and Save buttons
|
||||
- **Toast notifications** for save confirmations
|
||||
|
||||
### Navigation Tabs
|
||||
|
||||
| Tab ID | Label | Icon | Section |
|
||||
|--------|-------|------|---------|
|
||||
| `general` | General | `bi-sliders` | Configuration |
|
||||
| `models` | AI Models | `bi-stars` | Configuration |
|
||||
| `local-backend` | Local Backend | `bi-house-fill` | Configuration |
|
||||
| `memanto` | MEMANTO | `bi-cpu` | Configuration |
|
||||
| `cost-log` | OpenRouter Cost Log | `bi-graph-up` | Analytics & Docs |
|
||||
| `guide` | Model Guide | `bi-book` | Analytics & Docs |
|
||||
|
||||
---
|
||||
|
||||
## 2. Tab: General
|
||||
|
||||
**Description:** "Configure global API keys, budget, and content parameters."
|
||||
|
||||
### Section 2.1 — API Configuration
|
||||
|
||||
| Field | Option Key | Type | Input | Required | Default | Description |
|
||||
|-------|-----------|------|-------|----------|---------|-------------|
|
||||
| OpenRouter API Key | `openrouter_api_key` | `string` | `password` with show/hide toggle | Yes (marked `*`) | `""` | Get from [openrouter.ai/keys](https://openrouter.ai/keys). Placeholder: `sk-or-v1-...` |
|
||||
| Test Connection | _(button)_ | — | `button` | — | — | AJAX call to `wpaw_test_api_connection`. Shows spinner + result badge. |
|
||||
|
||||
### Section 2.2 — OpenRouter Budget & Cost Tracking
|
||||
|
||||
Displays a **3-column dashboard** before the input fields:
|
||||
|
||||
| Display Card | Variable | Source |
|
||||
|-------------|----------|--------|
|
||||
| Used This Month | `$monthly_used` | `Cost_Tracker::get_monthly_total()` |
|
||||
| Budget Usage (progress bar) | `$budget_percent` | Calculated: `(used/budget)*100` |
|
||||
| Remaining | Calculated | `max(0, budget - used)` |
|
||||
|
||||
Progress bar color: `success` (<70%), `warning` (70-90%), `danger` (>90%).
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Validation | Description |
|
||||
|-------|-----------|------|-------|---------|------------|-------------|
|
||||
| Monthly Budget (USD) | `monthly_budget` | `float` | `number` with `$` prefix | `600` | `floatval()`, min 0, step 0.01 | Maximum spend per month. 0 = unlimited. |
|
||||
| Enable Cost Tracking | `cost_tracking_enabled` | `bool` | `checkbox` (switch) | `true` | Boolean | Show cost tracking in editor sidebar. |
|
||||
|
||||
### Section 2.3 — Research & Web Search
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Options | Description |
|
||||
|-------|-----------|------|-------|---------|---------|-------------|
|
||||
| Enable Web Search | `web_search_enabled` | `bool` | `checkbox` (switch) | `false` | — | Default for new posts. Can also be toggled per-request in editor sidebar. |
|
||||
| Search Depth | `search_depth` | `string` | `select` | `"medium"` | `low` / `medium` / `high` | Controls search depth level. |
|
||||
|
||||
**Two-column sub-section:**
|
||||
|
||||
**Left — OpenRouter Search Engine:**
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Options | Description |
|
||||
|-------|-----------|------|-------|---------|---------|-------------|
|
||||
| Search Engine | `search_engine` | `string` | `select` | `"auto"` | `auto` (Native → Exa fallback) / `native` (Free, built-in) / `exa` (Paid, ~$0.02/search) | Used when active model routes through OpenRouter. |
|
||||
|
||||
**Right — Brave Search API (for Local/Codex):**
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Brave Search API Key | `brave_search_api_key` | `string` | `password` | `""` | Used automatically when active model is Local Backend or Codex. Placeholder: `BSA...`. Free at [brave.com/search/api](https://brave.com/search/api/) (2,000 requests/month). |
|
||||
|
||||
### Section 2.4 — Clarification Quiz
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Options | Description |
|
||||
|-------|-----------|------|-------|---------|---------|-------------|
|
||||
| Enable Clarification Quiz | `enable_clarification_quiz` | `bool` | `checkbox` (switch) | `true` | — | Ask clarifying questions when context is missing. |
|
||||
| Confidence Threshold | `clarity_confidence_threshold` | `string` | `select` | `"0.6"` | `0.5` (Very Sensitive) / `0.6` (Sensitive - Recommended) / `0.7` (Balanced) / `0.8` (Strict) / `0.9` (Very Strict) | When to trigger the quiz. |
|
||||
| Context Categories | `required_context_categories` | `array` | multi-checkbox (scrollable box, max-height 200px) | All 7 checked | `target_outcome` / `target_audience` / `tone` / `content_depth` / `expertise_level` / `content_type` / `pov` | Which context dimensions to ask about. |
|
||||
|
||||
### Section 2.5 — Content Settings (Language)
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Preferred Languages | `preferred_languages` | `array` | multi-checkbox grid (2 cols on mobile, 4 on md+) | `["auto", "English", "Indonesian"]` | Languages shown in the language selector when creating articles. |
|
||||
|
||||
**Available language options (24 total):**
|
||||
|
||||
| Value | Label |
|
||||
|-------|-------|
|
||||
| `auto` | Auto-detect |
|
||||
| `English` | English |
|
||||
| `Indonesian` | Indonesian (Bahasa Indonesia) |
|
||||
| `Javanese` | Javanese (Basa Jawa) |
|
||||
| `Sundanese` | Sundanese (Basa Sunda) |
|
||||
| `Spanish` | Spanish (Español) |
|
||||
| `French` | French (Français) |
|
||||
| `Arabic` | Arabic (العربية) |
|
||||
| `Chinese` | Chinese (中文) |
|
||||
| `Japanese` | Japanese (日本語) |
|
||||
| `Portuguese` | Portuguese (Português) |
|
||||
| `German` | German (Deutsch) |
|
||||
| `Hindi` | Hindi (हिंदी) |
|
||||
| `Korean` | Korean (한국어) |
|
||||
| `Vietnamese` | Vietnamese (Tiếng Việt) |
|
||||
| `Thai` | Thai (ไทย) |
|
||||
| `Tagalog` | Tagalog |
|
||||
| `Malay` | Malay (Bahasa Melayu) |
|
||||
| `Russian` | Russian (Русский) |
|
||||
| `Italian` | Italian (Italiano) |
|
||||
| `Dutch` | Dutch (Nederlands) |
|
||||
| `Polish` | Polish (Polski) |
|
||||
| `Turkish` | Turkish (Türkçe) |
|
||||
| `Swedish` | Swedish (Svenska) |
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Custom Languages | `custom_languages` | `array` | Dynamic text input list with add/remove buttons | `[]` | Add any language not listed above (e.g., regional dialects). Placeholder: `e.g., Betawi, Minangkabau`. |
|
||||
|
||||
### Section 2.6 — Advanced Settings
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Validation | Description |
|
||||
|-------|-----------|------|-------|---------|------------|-------------|
|
||||
| Enable Automated FAQ Schema | `enable_faq_schema` | `bool` | `checkbox` (switch) | `false` | Boolean | Auto-inject FAQPage JSON-LD. Compatible with Yoast/RankMath. Disable if SEO plugin handles it. |
|
||||
| Chat History Limit | `chat_history_limit` | `int` | `number` (max-width 120px) | `20` | `absint()`, capped at 200, min 0 | Messages stored per post. 0 = disable chat history. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Tab: AI Models
|
||||
|
||||
**Description:** "Select logic engines for different stages of the writing pipeline."
|
||||
|
||||
### Section 3.1 — Quick Presets (3 clickable cards)
|
||||
|
||||
These are **not saved fields** — they populate the 6 model selects below via JavaScript.
|
||||
|
||||
| Preset | Cost | Chat/Clarity/Planning | Writing | Refinement | Image |
|
||||
|--------|------|----------------------|---------|------------|-------|
|
||||
| **Budget** | ~$0.06/article | Gemini 2.5 Flash | Mistral Small Creative | Gemini 2.5 Flash | FLUX.2 klein |
|
||||
| **Balanced** ⭐ | ~$0.14/article | Gemini 2.5 Flash | Claude 3.5 Sonnet | Claude 3.5 Sonnet | Riverflow V2 Max |
|
||||
| **Premium** | ~$0.31/article | Gemini 3 Flash Preview | GPT-4.1 | GPT-4.1 | FLUX.2 max |
|
||||
|
||||
### Section 3.2 — OpenRouter Provider Routing (collapsible sub-section)
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Enable Provider Routing | `openrouter_provider_routing_enabled` | `bool` | `checkbox` (switch) | `false` | Pin OpenRouter requests to a specific provider for BYOK/routing. |
|
||||
| Provider Slug | `openrouter_provider_slug` | `string` | `text` (small) | `"auto"` | Examples: `openai`, `anthropic`, `google`, `z-ai`. Sanitized via `sanitize_key()`. |
|
||||
| Only Use This Provider | `openrouter_provider_only` | `bool` | `checkbox` | `false` | Prevents Azure or other providers when slug is `openai`. |
|
||||
| Allow Fallback Providers | `openrouter_allow_provider_fallbacks` | `bool` | `checkbox` | `false` | Leave off for BYOK-only behavior. |
|
||||
|
||||
### Section 3.3 — AI Model Configuration (6 model selectors)
|
||||
|
||||
All use **Select2 searchable dropdowns** populated via AJAX from the OpenRouter models API. Each has a provider badge (OpenRouter / Local Backend / Codex) showing which provider the model routes through.
|
||||
|
||||
| Field | Option Key | Badge | Default Model | data-model-type | Description |
|
||||
|-------|-----------|-------|--------------|-----------------|-------------|
|
||||
| Chat Model | `chat_model` | Discussion (info) | `google/gemini-2.5-flash` | `chat` | Discussion, research, recommendations |
|
||||
| Clarity Model | `clarity_model` | Analysis (info) | `google/gemini-2.5-flash` | `clarity` | Prompt analysis, quiz generation |
|
||||
| Planning Model | `planning_model` | Outline (info) | `google/gemini-2.5-flash` | `planning` | Article outline generation |
|
||||
| Writing Model | `writing_model` | Main Writer (primary) | `anthropic/claude-3.5-haiku` | `execution` | Article draft generation (2-5k words) |
|
||||
| Refinement Model | `refinement_model` | Editing (info) | `anthropic/claude-3.5-sonnet` | `execution` | Paragraph edits, rewrites, polish |
|
||||
| Image Model | `image_model` | Visual (warning) | `openai/gpt-4o` | `image` | Image generation |
|
||||
|
||||
**Note:** Writing Model has a legacy alias `execution_model` (mapped to `writing_model` during sanitization).
|
||||
|
||||
**Refresh Models button:** `#wpaw-refresh-models` — AJAX call to `wpaw_refresh_models`.
|
||||
|
||||
### Section 3.4 — Custom Models
|
||||
|
||||
| Sub-field | Type | Input | Description |
|
||||
|-----------|------|-------|-------------|
|
||||
| Model ID | `string` | `text` | Exact OpenRouter model ID. Placeholder: `model-provider/model-name` |
|
||||
| Display Name | `string` | `text` | Optional friendly name. Placeholder: `Display Name (optional)` |
|
||||
| Model Type | `string` | `select` | `text` or `image` |
|
||||
| Remove | — | `button` | Delete row |
|
||||
|
||||
Stored in separate option: `wp_agentic_writer_custom_models` (array of `{id, name, type}` objects).
|
||||
|
||||
- **Add button:** `#wpaw-add-custom-model` — clones from `<template id="wpaw-custom-model-template">`.
|
||||
- **Remove button:** `.wpaw-remove-custom-model` — removes the row.
|
||||
- Managed via AJAX: `wpaw_save_custom_model` / `wpaw_delete_custom_model`.
|
||||
|
||||
### Section 3.5 — Estimated Cost Per Article (display only)
|
||||
|
||||
A dark box showing:
|
||||
- Estimated cost calculated client-side based on selected models
|
||||
- Based on ~2K planning tokens, ~4K execution tokens, and 1 image
|
||||
- Updated dynamically when model selections change
|
||||
|
||||
---
|
||||
|
||||
## 4. Tab: Local Backend
|
||||
|
||||
**Description:** "Configure connections to local LM Studio or Ollama instances."
|
||||
|
||||
### Section 4.1 — Step 1: Download (informational)
|
||||
|
||||
- Download link: `https://downloads.wpagentic.dev/wp-agentic-writer/agentic-writer-local-backend.zip`
|
||||
- Expandable prerequisites section (Claude CLI, Node.js 18+, Z.ai Coding Plan)
|
||||
|
||||
### Section 4.2 — Step 2: Configure Connection
|
||||
|
||||
| Field | Option Key | Type | Input | Required | Default | Description |
|
||||
|-------|-----------|------|-------|----------|---------|-------------|
|
||||
| Base URL | `local_backend_url` | `string` | `url` | Yes (`*`) | `""` | URL from Local Backend startup message. Placeholder: `http://192.168.1.105:8080`. Sanitized via `esc_url_raw()`. |
|
||||
| API Key | `local_backend_key` | `string` | `text` | No | `"dummy"` | Use "dummy" for local backend (ignored by proxy). Placeholder: `dummy`. |
|
||||
| Model | `local_backend_model` | `string` | `text` | No | `"claude-local"` | Informational only. Proxy uses Claude CLI default. Placeholder: `claude-local`. |
|
||||
| Test Connection | _(button)_ | — | `button` | — | — | AJAX call to `wpaw_test_local_backend`. Shows spinner + result. |
|
||||
|
||||
### Section 4.3 — Step 3: Provider Routing (Advanced)
|
||||
|
||||
A table with **6 task types**, each with a provider select:
|
||||
|
||||
| Task | Option Key Path | Available Providers | Default |
|
||||
|------|----------------|--------------------|---------|
|
||||
| Chat & Discussion | `task_providers[chat]` | OpenRouter ☁️, Local Backend 🏠, Codex 🔗 | `openrouter` |
|
||||
| Clarity Check & Quiz | `task_providers[clarity]` | OpenRouter ☁️, Local Backend 🏠, Codex 🔗 | `openrouter` |
|
||||
| Outline Planning | `task_providers[planning]` | OpenRouter ☁️, Local Backend 🏠, Codex 🔗 | `openrouter` |
|
||||
| Article Writing | `task_providers[writing]` | OpenRouter ☁️, Local Backend 🏠, Codex 🔗 | `openrouter` |
|
||||
| Content Refinement | `task_providers[refinement]` | OpenRouter ☁️, Local Backend 🏠, Codex 🔗 | `openrouter` |
|
||||
| Image Generation | `task_providers[image]` | OpenRouter ☁️ **only** | `openrouter` |
|
||||
|
||||
> **Note:** Image task is restricted to OpenRouter only. Text tasks also get Local Backend and Codex options.
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Allow OpenRouter Fallback | `allow_openrouter_fallback` | `bool` | `checkbox` | `false` | Auto-fallback to OpenRouter when selected provider fails. Off by default to prevent unexpected charges. |
|
||||
|
||||
### Section 4.4 — Step 4: Enable Web Search (Optional / Informational)
|
||||
|
||||
This section is mostly informational guidance for setting up Brave Search on the local proxy. It references the `brave_search_api_key` from the General tab and provides:
|
||||
- Copy-to-clipboard command for `.env` file
|
||||
- Restart proxy command
|
||||
- Verification steps
|
||||
|
||||
### Section 4.5 — Troubleshooting (informational)
|
||||
|
||||
Static help content with common issues and commands.
|
||||
|
||||
---
|
||||
|
||||
## 5. Tab: MEMANTO
|
||||
|
||||
**Description:** "Optional persistent memory for your AI writing assistant. The plugin works perfectly without it."
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Option Key | Type | Input | Default | Description |
|
||||
|-------|-----------|------|-------|---------|-------------|
|
||||
| Enable MEMANTO Integration | `memanto_enabled` | `bool` | `checkbox` (switch) | `false` | Store and recall memories across sessions. Optional enhancement. |
|
||||
| MEMANTO Instance URL | `memanto_url` | `string` | `url` | `""` | URL of MEMANTO instance. Placeholder: `https://your-instance.context.wpagentic.dev`. Sanitized via `esc_url_raw()`. |
|
||||
| Moorcheh API Key | `memanto_moorcheh_key` | `string` | `password` | `""` | Get free API key at [moorcheh.ai](https://moorcheh.ai) (10K vectors/month). `autocomplete="new-password"`. |
|
||||
| Test Connection | _(button)_ | — | `button` | — | AJAX call to `wpaw_test_memanto`. Disabled until both URL and key are filled. Auto-triggers on page load if both fields are filled. |
|
||||
|
||||
**Connection status indicator:**
|
||||
- `#memanto-status-indicator` — badge showing: Not configured / Checking... / 🟢 Connected / 🔴 Error
|
||||
- `#memanto-status-detail` — detail text (service version, Moorcheh connection status)
|
||||
|
||||
**Info box:** Static content explaining MEMANTO features (memory across sessions, context loss elimination, 63% token reduction).
|
||||
|
||||
---
|
||||
|
||||
## 6. Tab: OpenRouter Cost Log
|
||||
|
||||
**Description:** "Track API token usage and expenses across all generations."
|
||||
|
||||
> **This tab does NOT save settings.** It's an analytics dashboard powered entirely by AJAX.
|
||||
|
||||
### Section 6.1 — Cost Summary Dashboard
|
||||
|
||||
Four stat cards (populated by AJAX `wpaw_get_header_stats`):
|
||||
|
||||
| Stat | Element ID | Description |
|
||||
|------|-----------|-------------|
|
||||
| All Time | `#wpaw-stat-all-time` | Total OpenRouter cost ever |
|
||||
| This Month | `#wpaw-stat-monthly` | Current month's cost |
|
||||
| Today | `#wpaw-stat-today` | Today's cost |
|
||||
| Avg Per Post | `#wpaw-stat-avg` | All-time cost / total posts with usage |
|
||||
|
||||
**Action Summary Table** (`#wpaw-action-summary-table`): Shows cost breakdown per action type (Planning, Writing, Refinement, etc.) with columns: Action, Calls, Total Cost, Avg/Call.
|
||||
|
||||
### Section 6.2 — Filters
|
||||
|
||||
| Filter | Element ID | Type | Options |
|
||||
|--------|-----------|------|---------|
|
||||
| Post ID | `#wpaw-filter-post` | `number` | Any post ID |
|
||||
| Model | `#wpaw-filter-model` | `select` | Populated dynamically |
|
||||
| Type | `#wpaw-filter-type` | `select` | Populated dynamically |
|
||||
| Date From | `#wpaw-filter-date-from` | `date` | — |
|
||||
| Date To | `#wpaw-filter-date-to` | `date` | — |
|
||||
| Apply | `#wpaw-apply-filters` | `button` | — |
|
||||
| Clear | `#wpaw-clear-filters` | `button` | — |
|
||||
|
||||
### Section 6.3 — Detailed Cost Log Table
|
||||
|
||||
| Column | Description |
|
||||
|--------|-------------|
|
||||
| Post Title (50% width) | Linked post title with edit link |
|
||||
| API Calls | Count of API calls for this post |
|
||||
| Total OpenRouter Cost | Dollar amount |
|
||||
|
||||
**Pagination:** Server-side via AJAX `wpaw_get_cost_log_data`.
|
||||
- Per page selector: 10 / 25 (default) / 50 / 100
|
||||
- Element: `#wpaw-pagination`
|
||||
|
||||
**Export CSV button:** `#wpaw-export-csv` — client-side CSV generation from current filter results.
|
||||
|
||||
---
|
||||
|
||||
## 7. Tab: Model Guide (Read-Only)
|
||||
|
||||
**Purely informational — no form fields.** Contains three reference sections:
|
||||
|
||||
### 7.1 — How AI Models Are Used
|
||||
Table mapping each pipeline task → model type → estimated cost → description.
|
||||
|
||||
### 7.2 — Recommended Models
|
||||
Table of curated model recommendations with cost per 1M tokens and notes.
|
||||
|
||||
### 7.3 — Cost Examples
|
||||
Three example cards showing real-world costs:
|
||||
- Single Article (Balanced): ~$0.10-0.15
|
||||
- 10 Articles/Month (Balanced): ~$1.50-2.00
|
||||
- With Web Search: ~$0.02-0.04 extra
|
||||
|
||||
---
|
||||
|
||||
## 8. Global UI Components
|
||||
|
||||
### Writing Pipeline Progress Bar (top of content pane)
|
||||
|
||||
A visual pipeline showing 5 steps: Context → Planning → Writing → Refinement → Done.
|
||||
Element: `#wpaw-workflow-display`. This is a display-only component that reflects real-time writing status.
|
||||
|
||||
### Fixed Save Bar
|
||||
|
||||
| Element | Description |
|
||||
|---------|-------------|
|
||||
| Version display | `v{WP_AGENTIC_WRITER_VERSION}` with plugin icon |
|
||||
| Reset Defaults button | `#wpaw-reset-settings` — restores all settings to defaults |
|
||||
| Save Settings button | Form submit with keyboard shortcut indicator (⌘+S on Mac, Ctrl+S on Windows) |
|
||||
|
||||
### Toast Notification
|
||||
|
||||
- Element: `#wpaw-toast` / `#wpaw-toast-message`
|
||||
- Bootstrap toast component for save/error notifications
|
||||
|
||||
---
|
||||
|
||||
## 9. AJAX Actions Reference
|
||||
|
||||
| Action | Method | Purpose | Tab |
|
||||
|--------|--------|---------|-----|
|
||||
| `wpaw_test_api_connection` | POST | Test OpenRouter API key validity | General |
|
||||
| `wpaw_refresh_models` | POST | Fetch latest models from OpenRouter API | AI Models |
|
||||
| `wpaw_save_custom_model` | POST | Save a custom model entry | AI Models |
|
||||
| `wpaw_delete_custom_model` | POST | Delete a custom model entry | AI Models |
|
||||
| `wpaw_get_cost_log_data` | POST | Paginated cost log data (server-side) | Cost Log |
|
||||
| `wpaw_get_header_stats` | POST | Summary stats for cost dashboard | Cost Log |
|
||||
| `wpaw_debug_models` | POST | Debug model configuration | AI Models |
|
||||
| `wpaw_test_local_backend` | POST | Test local backend proxy connection | Local Backend |
|
||||
| `wpaw_test_memanto` | POST | Test MEMANTO service connection | MEMANTO |
|
||||
|
||||
All AJAX calls use `wpawSettingsV2.ajaxUrl` and `wpawSettingsV2.nonce`.
|
||||
|
||||
---
|
||||
|
||||
## 10. Complete Option Key Index
|
||||
|
||||
All stored under `wp_agentic_writer_settings` unless noted.
|
||||
|
||||
| Option Key | Type | Default | Tab | Section |
|
||||
|-----------|------|---------|-----|---------|
|
||||
| `openrouter_api_key` | `string` | `""` | General | API Configuration |
|
||||
| `brave_search_api_key` | `string` | `""` | General | Research & Web Search |
|
||||
| `monthly_budget` | `float` | `600` | General | Budget & Cost Tracking |
|
||||
| `cost_tracking_enabled` | `bool` | `true` | General | Budget & Cost Tracking |
|
||||
| `web_search_enabled` | `bool` | `false` | General | Research & Web Search |
|
||||
| `search_engine` | `string` | `"auto"` | General | Research & Web Search |
|
||||
| `search_depth` | `string` | `"medium"` | General | Research & Web Search |
|
||||
| `enable_clarification_quiz` | `bool` | `true` | General | Clarification Quiz |
|
||||
| `clarity_confidence_threshold` | `string` | `"0.6"` | General | Clarification Quiz |
|
||||
| `required_context_categories` | `array` | All 7 categories | General | Clarification Quiz |
|
||||
| `preferred_languages` | `array` | `["auto","English","Indonesian"]` | General | Content Settings |
|
||||
| `custom_languages` | `array` | `[]` | General | Content Settings |
|
||||
| `enable_faq_schema` | `bool` | `false` | General | Advanced Settings |
|
||||
| `chat_history_limit` | `int` | `20` | General | Advanced Settings |
|
||||
| `chat_model` | `string` | `"google/gemini-2.5-flash"` | AI Models | Model Configuration |
|
||||
| `clarity_model` | `string` | `"google/gemini-2.5-flash"` | AI Models | Model Configuration |
|
||||
| `planning_model` | `string` | `"google/gemini-2.5-flash"` | AI Models | Model Configuration |
|
||||
| `writing_model` | `string` | `"anthropic/claude-3.5-haiku"` | AI Models | Model Configuration |
|
||||
| `refinement_model` | `string` | `"anthropic/claude-3.5-sonnet"` | AI Models | Model Configuration |
|
||||
| `image_model` | `string` | `"openai/gpt-4o"` | AI Models | Model Configuration |
|
||||
| `openrouter_provider_routing_enabled` | `bool` | `false` | AI Models | Provider Routing |
|
||||
| `openrouter_provider_slug` | `string` | `"auto"` | AI Models | Provider Routing |
|
||||
| `openrouter_provider_only` | `bool` | `false` | AI Models | Provider Routing |
|
||||
| `openrouter_allow_provider_fallbacks` | `bool` | `false` | AI Models | Provider Routing |
|
||||
| `local_backend_url` | `string` | `""` | Local Backend | Connection |
|
||||
| `local_backend_key` | `string` | `"dummy"` | Local Backend | Connection |
|
||||
| `local_backend_model` | `string` | `"claude-local"` | Local Backend | Connection |
|
||||
| `task_providers` | `array` | `[]` (all default to `openrouter`) | Local Backend | Provider Routing |
|
||||
| `allow_openrouter_fallback` | `bool` | `false` | Local Backend | Provider Routing |
|
||||
| `memanto_enabled` | `bool` | `false` | MEMANTO | Integration |
|
||||
| `memanto_url` | `string` | `""` | MEMANTO | Integration |
|
||||
| `memanto_moorcheh_key` | `string` | `""` | MEMANTO | Integration |
|
||||
|
||||
**Separate option:** `wp_agentic_writer_custom_models` — array of `{id: string, name: string, type: "text"|"image"}`.
|
||||
|
||||
---
|
||||
|
||||
## 11. Sanitization & Validation Rules
|
||||
|
||||
| Field | Sanitization | Validation |
|
||||
|-------|-------------|------------|
|
||||
| `openrouter_api_key` | `trim()` | — |
|
||||
| `brave_search_api_key` | `trim()` | — |
|
||||
| `chat_model` | `sanitize_text_field()` | Falls back to `Model_Registry::get_default_model('chat')` |
|
||||
| `clarity_model` | `sanitize_text_field()` | Falls back to registry default |
|
||||
| `planning_model` | `sanitize_text_field()` | Falls back to registry default |
|
||||
| `writing_model` | `sanitize_text_field()` | Falls back to registry default; also maps legacy `execution_model` |
|
||||
| `refinement_model` | `sanitize_text_field()` | Falls back to registry default |
|
||||
| `image_model` | `sanitize_text_field()` | Falls back to registry default |
|
||||
| `web_search_enabled` | Boolean check `=== "1"` | — |
|
||||
| `cost_tracking_enabled` | Boolean check `=== "1"` | — |
|
||||
| `enable_clarification_quiz` | Boolean check `=== "1"` | — |
|
||||
| `enable_faq_schema` | Boolean, defaults `false` | — |
|
||||
| `allow_openrouter_fallback` | Boolean check `=== "1"` | — |
|
||||
| `openrouter_provider_routing_enabled` | Boolean check `=== "1"` | — |
|
||||
| `openrouter_provider_only` | Boolean check `=== "1"` | — |
|
||||
| `openrouter_allow_provider_fallbacks` | Boolean check `=== "1"` | — |
|
||||
| `openrouter_provider_slug` | `sanitize_key()`, empty → `"auto"` | — |
|
||||
| `search_engine` | Whitelist: `auto`, `native`, `exa` | Invalid → `"auto"` |
|
||||
| `search_depth` | Whitelist: `low`, `medium`, `high` | Invalid → `"medium"` |
|
||||
| `monthly_budget` | `floatval()` | Default `600` if not set |
|
||||
| `chat_history_limit` | `absint()`, capped at 200 | Default `20` if not set |
|
||||
| `clarity_confidence_threshold` | Whitelist: `0.5`, `0.6`, `0.7`, `0.8`, `0.9` | Invalid → `"0.6"` |
|
||||
| `required_context_categories` | `array_intersect()` with 7 valid values | Defaults to all 7 |
|
||||
| `preferred_languages` | `array_map('sanitize_text_field')` | Default `["auto","English","Indonesian"]` |
|
||||
| `custom_languages` | `array_map('sanitize_text_field')` + `array_filter()` | Default `[]` |
|
||||
| `local_backend_url` | `esc_url_raw(trim())` | — |
|
||||
| `local_backend_key` | `sanitize_text_field(trim())` | — |
|
||||
| `local_backend_model` | `sanitize_text_field(trim())` | — |
|
||||
| `memanto_enabled` | Boolean check `=== "1"` | — |
|
||||
| `memanto_url` | `esc_url_raw(trim())` | — |
|
||||
| `memanto_moorcheh_key` | `sanitize_text_field(trim())` | — |
|
||||
| `task_providers` | Nested sanitization | Task must be in whitelist, provider must be in whitelist, image restricted to openrouter |
|
||||
|
||||
---
|
||||
|
||||
## Key Files Reference
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `includes/class-settings-v2.php` | Active settings controller (registration, sanitization, AJAX, view data prep) |
|
||||
| `includes/class-model-registry.php` | Centralized model defaults, labels, and fallbacks |
|
||||
| `includes/class-settings.php` | **Legacy** settings class (deprecated, kept for reference) |
|
||||
| `views/settings/layout.php` | Main layout wrapper (sidebar + content + save bar) |
|
||||
| `views/settings/tab-general.php` | General tab view |
|
||||
| `views/settings/tab-models.php` | AI Models tab view |
|
||||
| `views/settings/tab-local-backend.php` | Local Backend tab view |
|
||||
| `views/settings/tab-memanto.php` | MEMANTO tab view |
|
||||
| `views/settings/tab-cost-log.php` | Cost Log tab view |
|
||||
| `views/settings/tab-guide.php` | Model Guide tab view (read-only) |
|
||||
|
||||
---
|
||||
|
||||
*Generated from codebase analysis on 2026-06-08. Plugin version as defined by `WP_AGENTIC_WRITER_VERSION`.*
|
||||
154
docs/SMOKE_TESTS.md
Normal file
154
docs/SMOKE_TESTS.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Manual Smoke Tests
|
||||
|
||||
Run these tests after each refactor step to verify core functionality still works.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Local development environment running
|
||||
- Plugin activated
|
||||
- Gutenberg editor accessible
|
||||
- Test post created
|
||||
|
||||
---
|
||||
|
||||
## Test Flows
|
||||
|
||||
### 1. Chat Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Open a post in Gutenberg | Editor loads |
|
||||
| 2 | Type a message in the sidebar chat | Message appears in input |
|
||||
| 3 | Click send / press Enter | Streaming response begins |
|
||||
| 4 | Wait for response to complete | Message appears in chat thread |
|
||||
|
||||
**Pass Criteria:** Chat thread shows user message and AI response.
|
||||
|
||||
---
|
||||
|
||||
### 2. Plan Generation Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Click "Plan" tab in sidebar | Plan tab is active |
|
||||
| 2 | Type an outline request (e.g., "Write a blog post about X") | Text appears in input |
|
||||
| 3 | Click "Generate Plan" | Loading indicator shows |
|
||||
| 4 | Wait for plan to generate | Outline renders with sections |
|
||||
|
||||
**Pass Criteria:** Plan displays with at least one section heading.
|
||||
|
||||
---
|
||||
|
||||
### 3. Article Execution Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Generate a plan first | Plan is visible |
|
||||
| 2 | Click "Execute" button | Streaming begins |
|
||||
| 3 | Wait for article to complete | Content appears in Gutenberg blocks |
|
||||
|
||||
**Pass Criteria:** At least one paragraph block is added to the post.
|
||||
|
||||
---
|
||||
|
||||
### 4. Block Refinement Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Add a paragraph block with content | Block is visible |
|
||||
| 2 | Select the block | Block is highlighted |
|
||||
| 3 | Click "Refine" in sidebar | Inline editor shows |
|
||||
| 4 | Click "Apply" | Block content updates |
|
||||
|
||||
**Pass Criteria:** Block content changes after refinement.
|
||||
|
||||
---
|
||||
|
||||
### 5. SEO Audit Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Click "SEO" tab in sidebar | SEO tab is active |
|
||||
| 2 | Click "Run Audit" button | Loading indicator shows |
|
||||
| 3 | Wait for audit to complete | Report displays with score |
|
||||
|
||||
**Pass Criteria:** Audit report shows a numeric score and at least one issue/recommendation.
|
||||
|
||||
---
|
||||
|
||||
### 6. Image Generation Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Add an image block or click image generation | Image dialog opens |
|
||||
| 2 | Enter a prompt and click "Generate" | Loading indicator shows |
|
||||
| 3 | Wait for generation | Image variants appear |
|
||||
| 4 | Select a variant and click "Commit" | Image uploads and appears in post |
|
||||
|
||||
**Pass Criteria:** Image appears in Media Library and post content.
|
||||
|
||||
---
|
||||
|
||||
### 7. Settings Persistence Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Open plugin settings | Settings page loads |
|
||||
| 2 | Change the AI model selection | Selection changes |
|
||||
| 3 | Click "Save" | Success message appears |
|
||||
| 4 | Reload the page | Setting persists |
|
||||
|
||||
**Pass Criteria:** Model selection is retained after page reload.
|
||||
|
||||
---
|
||||
|
||||
### 8. MEMANTO Memory Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Configure MEMANTO URL in settings | URL is saved |
|
||||
| 2 | Use the agent in a chat | Chat completes without error |
|
||||
| 3 | Check for memory recall | Agent references previous context |
|
||||
|
||||
**Pass Criteria:** No errors in chat, agent shows memory awareness.
|
||||
|
||||
---
|
||||
|
||||
### 9. Cost Tracking Flow
|
||||
|
||||
| Step | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 1 | Use any AI feature (chat, generate, etc.) | Feature works |
|
||||
| 2 | Open plugin settings | Settings page loads |
|
||||
| 3 | Click "Cost Log" tab | Cost entries display |
|
||||
|
||||
**Pass Criteria:** At least one cost entry appears with token/usage data.
|
||||
|
||||
---
|
||||
|
||||
## Quick Regression Checklist
|
||||
|
||||
After any code change, verify:
|
||||
|
||||
- [ ] Plugin activates without errors
|
||||
- [ ] Gutenberg editor loads without JS errors
|
||||
- [ ] At least one REST endpoint responds (e.g., `/wp-json/wp-agentic-writer/v1/ai-capabilities`)
|
||||
- [ ] Settings page saves without errors
|
||||
- [ ] No PHP fatal errors in debug.log
|
||||
|
||||
---
|
||||
|
||||
## Reporting Failures
|
||||
|
||||
If a test fails:
|
||||
|
||||
1. Note the exact steps to reproduce
|
||||
2. Check browser console for JS errors
|
||||
3. Check `debug.log` for PHP errors
|
||||
4. Check Network tab for failed REST requests
|
||||
5. Report in issue tracker with:
|
||||
- Test name
|
||||
- Steps to reproduce
|
||||
- Error messages (console + network)
|
||||
- WordPress version
|
||||
- Plugin version
|
||||
720
docs/architecture/REST_API_ENDPOINTS.md
Normal file
720
docs/architecture/REST_API_ENDPOINTS.md
Normal file
@@ -0,0 +1,720 @@
|
||||
# REST API Endpoints
|
||||
|
||||
Complete reference for WP Agentic Writer REST API endpoints.
|
||||
|
||||
**Base URL:** `/wp-json/wp-agentic-writer/v1`
|
||||
|
||||
**Authentication:** All endpoints require WordPress authentication via `cookie` or application password. Permission checks vary by endpoint (see below).
|
||||
|
||||
**Rate Limiting:** Most endpoints are rate-limited. See [Rate Limits](#rate-limits) below.
|
||||
|
||||
---
|
||||
|
||||
## Rate Limits
|
||||
|
||||
| Endpoint | Limit | Window | Notes |
|
||||
|----------|-------|--------|-------|
|
||||
| `POST /chat` | 30/min | 60s | |
|
||||
| `POST /chat_stream` | 30/min | 60s | Streaming variant |
|
||||
| `POST /search` | 20/min | 60s | Brave Search |
|
||||
| `POST /fetch-content` | 10/min | 60s | Web content fetch |
|
||||
| All others | — | — | No rate limiting |
|
||||
|
||||
---
|
||||
|
||||
## Models
|
||||
|
||||
### `GET /models`
|
||||
|
||||
List available AI models from OpenRouter.
|
||||
|
||||
**Handler:** `Controller_Models::handle_get_models()`
|
||||
|
||||
**Permission:** `check_permissions` (authenticated user)
|
||||
|
||||
**Response:** Array of model objects from OpenRouter cache.
|
||||
|
||||
---
|
||||
|
||||
### `POST /models/refresh`
|
||||
|
||||
Force-refresh the model cache.
|
||||
|
||||
**Handler:** `Controller_Models::handle_refresh_models()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"models": [...],
|
||||
"message": "Models refreshed successfully."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Chat
|
||||
|
||||
### `POST /chat`
|
||||
|
||||
Send a chat message (non-streaming).
|
||||
|
||||
**Handler:** `Controller_Chat::handle_chat_request()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit (if `postId` provided)
|
||||
|
||||
**Rate Limit:** 30 requests/minute
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"messages": [...],
|
||||
"postId": 123,
|
||||
"sessionId": "uuid",
|
||||
"type": "planning|writing|revising",
|
||||
"stream": false
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** Full JSON response with assistant message.
|
||||
|
||||
---
|
||||
|
||||
### `POST /chat` (streaming variant)
|
||||
|
||||
Same endpoint with `"stream": true` in request body. Uses Server-Sent Events.
|
||||
|
||||
**Rate Limit:** 30 requests/minute (same as non-streaming)
|
||||
|
||||
**Response:** `text/event-stream` with chunks.
|
||||
|
||||
---
|
||||
|
||||
### `POST /clear-context`
|
||||
|
||||
Clear the chat context for a post.
|
||||
|
||||
**Handler:** `Controller_Chat::handle_clear_context()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"postId": 123,
|
||||
"sessionId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `GET /chat-history/(?P<post_id>\d+)`
|
||||
|
||||
Get legacy chat history from post meta. **Deprecated** — use `/conversations` instead.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_chat_history()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## Conversations
|
||||
|
||||
### `GET /conversation/(?P<post_id>\d+)`
|
||||
|
||||
Get canonical conversation for chat hydration.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_conversation()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `GET /conversations`
|
||||
|
||||
List all conversations for the current user.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_conversations()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `GET /conversations/post/(?P<post_id>\d+)`
|
||||
|
||||
List conversations linked to a specific post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_conversations()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `POST /conversations`
|
||||
|
||||
Create a new conversation.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_create_conversation()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `GET /conversations/(?P<session_id>[a-zA-Z0-9]+)`
|
||||
|
||||
Get a specific conversation.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_conversation()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `PUT /conversations/(?P<session_id>[a-zA-Z0-9]+)`
|
||||
|
||||
Update conversation metadata.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_update_conversation()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `DELETE /conversations/(?P<session_id>[a-zA-Z0-9]+)`
|
||||
|
||||
Delete a conversation.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_delete_conversation()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `POST|PUT /conversations/(?P<session_id>[a-zA-Z0-9]+)/messages`
|
||||
|
||||
Add or update messages in a conversation.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_update_conversation_messages()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `POST /conversations/(?P<session_id>[a-zA-Z0-9]+)/link-post`
|
||||
|
||||
Link a conversation to a post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_link_conversation_to_post()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `POST /conversations/(?P<session_id>[a-zA-Z0-9]+)/lock`
|
||||
|
||||
Acquire or refresh session lock (heartbeat).
|
||||
|
||||
**Handler:** `Controller_Session::handle_session_lock()`
|
||||
|
||||
**Permission:** `check_permissions` + conversation access
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"tab_id": "uuid",
|
||||
"force": false
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"acquired": true,
|
||||
"expires_at": 1234567890,
|
||||
"tab_id": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `DELETE /conversations/(?P<session_id>[a-zA-Z0-9]+)/lock`
|
||||
|
||||
Release session lock.
|
||||
|
||||
**Handler:** `Controller_Session::handle_session_unlock()`
|
||||
|
||||
**Permission:** `check_permissions` + conversation access
|
||||
|
||||
---
|
||||
|
||||
## Planning & Writing
|
||||
|
||||
### `GET|POST /post-config/(?P<post_id>\d+)`
|
||||
|
||||
Get or save post configuration (focus keyword, language, article type).
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_post_config()` / `handle_save_post_config()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /generate-plan`
|
||||
|
||||
Generate article outline/plan.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_generate_plan()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /revise-plan`
|
||||
|
||||
Revise an existing plan.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_revise_plan()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /execute-article`
|
||||
|
||||
Execute article generation from plan.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_execute_article()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /reformat-blocks`
|
||||
|
||||
Reformat blocks (e.g., convert to different structure).
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_reformat_blocks()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /regenerate-block`
|
||||
|
||||
Regenerate a single block.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_regenerate_block()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /refine-block`
|
||||
|
||||
Refine a block with instructions.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_block_refine()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /refine-from-chat`
|
||||
|
||||
Refine blocks based on chat conversation.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_refine_from_chat()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /refine-multi-pass`
|
||||
|
||||
Multi-pass block refinement.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_refine_multi_pass()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /refine-article`
|
||||
|
||||
Article-wide refinement.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_refine_article()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /summarize-context`
|
||||
|
||||
Summarize context to stay within token limits.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_summarize_context()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## Content Quality
|
||||
|
||||
### `POST /check-clarity`
|
||||
|
||||
Check content clarity.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_check_clarity()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /detect-intent`
|
||||
|
||||
Detect user intent from message.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_detect_intent()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `POST /suggest-improvements`
|
||||
|
||||
Proactive improvement suggestions (idle analysis).
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_suggest_improvements()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## SEO
|
||||
|
||||
### `GET /seo-audit/(?P<post_id>\d+)`
|
||||
|
||||
Run SEO audit for a post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_seo_audit()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /generate-meta`
|
||||
|
||||
Generate meta description.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_generate_meta()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /suggest-keywords`
|
||||
|
||||
Suggest keywords for a post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_suggest_keywords()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `GET /geo-score/(?P<post_id>\d+)`
|
||||
|
||||
Get GEO scoring for a post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_geo_score()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## Title & Excerpt
|
||||
|
||||
### `POST /generate-title`
|
||||
|
||||
Generate post title (uses WP 7.0 AI Client when available).
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_generate_title()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /refine-title`
|
||||
|
||||
Refine title with instructions.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_refine_title()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /generate-excerpt`
|
||||
|
||||
Generate post excerpt (uses WP 7.0 AI Client when available).
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_generate_excerpt()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## Images
|
||||
|
||||
### `GET /image-recommendations/(?P<post_id>\d+)`
|
||||
|
||||
Get image recommendations for a post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_image_recommendations()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /generate-image`
|
||||
|
||||
Generate an image.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_generate_image()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /commit-image`
|
||||
|
||||
Commit/save generated image.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_commit_image()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## Writing State
|
||||
|
||||
### `GET /writing-state/(?P<post_id>\d+)`
|
||||
|
||||
Get writing state for a post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_writing_state()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
### `POST /writing-state/(?P<post_id>\d+)`
|
||||
|
||||
Save writing state.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_save_writing_state()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## Section Blocks
|
||||
|
||||
### `POST /section-blocks`
|
||||
|
||||
Save section block mapping.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_save_section_blocks()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `GET /section-blocks/(?P<post_id>\d+)`
|
||||
|
||||
Get section blocks for a post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_section_blocks()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## Cost Tracking
|
||||
|
||||
### `GET /cost-tracking/(?P<post_id>\d+)`
|
||||
|
||||
Get cost tracking data.
|
||||
|
||||
**Handler:** `Controller_Cost::handle_get_cost_tracking()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit (if `post_id` > 0)
|
||||
|
||||
---
|
||||
|
||||
## AI Capabilities
|
||||
|
||||
### `GET /ai-capabilities`
|
||||
|
||||
Get AI capabilities status.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_ai_capabilities()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
## Research
|
||||
|
||||
### `POST /search`
|
||||
|
||||
Search the web (Brave Search).
|
||||
|
||||
**Handler:** `Controller_Chat::handle_search()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
**Rate Limit:** 20 requests/minute
|
||||
|
||||
---
|
||||
|
||||
### `POST /fetch-content`
|
||||
|
||||
Fetch web page content.
|
||||
|
||||
**Handler:** `Controller_Chat::handle_fetch_content()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
**Rate Limit:** 10 requests/minute
|
||||
|
||||
---
|
||||
|
||||
### `POST /research-summary`
|
||||
|
||||
Generate research summary.
|
||||
|
||||
**Handler:** `Controller_Chat::handle_research_summary()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
## MEMANTO (Memory)
|
||||
|
||||
### `GET /memanto/status`
|
||||
|
||||
Get MEMANTO service status.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_memanto_status()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `GET /memanto/recall`
|
||||
|
||||
Recall recent memories for a post.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_memanto_recall()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `GET /memanto/restore`
|
||||
|
||||
Restore session for cross-session continuity.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_memanto_restore()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
### `GET /memanto/preferences`
|
||||
|
||||
Get user preferences for new post carry-over.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_memanto_preferences()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
## User Preferences
|
||||
|
||||
### `GET /user-preferences`
|
||||
|
||||
Get user preferences (public — no auth required).
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_get_user_preferences()`
|
||||
|
||||
**Permission:** `__return_true` (public)
|
||||
|
||||
---
|
||||
|
||||
### `POST /user-preferences`
|
||||
|
||||
Save user preferences.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_save_user_preferences()`
|
||||
|
||||
**Permission:** `check_permissions`
|
||||
|
||||
---
|
||||
|
||||
## Migration
|
||||
|
||||
### `POST /migrate-chat-history/(?P<post_id>\d+)`
|
||||
|
||||
Migrate legacy post meta chat history to conversations table.
|
||||
|
||||
**Handler:** `Gutenberg_Sidebar::handle_migrate_chat_history()`
|
||||
|
||||
**Permission:** `check_permissions` + post edit
|
||||
|
||||
---
|
||||
|
||||
## Error Codes
|
||||
|
||||
| Code | HTTP Status | Description |
|
||||
|------|-------------|-------------|
|
||||
| `forbidden` | 403 | User lacks permission for this action |
|
||||
| `invalid_post` | 400 | Invalid or missing post ID |
|
||||
| `rate_limit_exceeded` | 429 | Too many requests |
|
||||
| `missing_tab_id` | 400 | Session lock requires tab_id |
|
||||
| Various WP_Error codes | varies | Provider-specific errors |
|
||||
|
||||
---
|
||||
|
||||
## Response Format
|
||||
|
||||
All responses are JSON. Successful responses:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
Or directly the resource data:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "value"
|
||||
}
|
||||
```
|
||||
|
||||
Error responses:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "error_code",
|
||||
"message": "Human-readable message",
|
||||
"data": { "status": 400 }
|
||||
}
|
||||
```
|
||||
@@ -1,506 +0,0 @@
|
||||
# WP Agentic Writer - Distribution Strategy
|
||||
|
||||
**Version:** 1.0
|
||||
**Date:** 2026-05-17
|
||||
**Strategy:** Freemium with Addon Model
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This document outlines a comprehensive strategy for distributing WP Agentic Writer as two distinct versions:
|
||||
- **Free Version** - Published on WordPress.org repository for maximum visibility and user acquisition
|
||||
- **Pro Version** - Premium addon sold via your own license server with advanced features
|
||||
|
||||
**Core Philosophy:** The free version must be a complete, valuable product on its own. Pro features are genuine enhancements that power users will happily pay for.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ WP AGENTIC WRITER │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ FREE CORE PLUGIN (WordPress.org) │
|
||||
│ ├── AI Writing Assistant (sidebar) │
|
||||
│ ├── Context Management │
|
||||
│ ├── Planning & Writing Pipeline │
|
||||
│ ├── Model Selection (OpenRouter) │
|
||||
│ ├── Basic Refinement │
|
||||
│ ├── Cost Tracking │
|
||||
│ └── Hook System (for extensibility) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ PRO ADDON (License Server) │
|
||||
│ ├── License Verification System │
|
||||
│ ├── Advanced Refinement (multi-pass) │
|
||||
│ ├── Local Backend Integration (extended) │
|
||||
│ ├── Brave Search Integration │
|
||||
│ ├── Image Generation (DALL-E, Stable Diffusion) │
|
||||
│ ├── Custom Model Presets │
|
||||
│ ├── Team Collaboration │
|
||||
│ ├── Priority Support │
|
||||
│ └── Advanced Analytics │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Feature Distribution
|
||||
|
||||
### Free Version Features
|
||||
|
||||
#### Core Writing Pipeline
|
||||
| Feature | Description | Strategic Value |
|
||||
|---------|-------------|-----------------|
|
||||
| Planning Mode | AI-powered article outline creation | Core value prop |
|
||||
| Writing Mode | Generate full articles with context | Core value prop |
|
||||
| Chat Mode | Quick AI assistance | Engagement driver |
|
||||
| Refinement Mode | Basic content polishing | Entry to refinement |
|
||||
| @mention Detection | Link to related posts | Unique capability |
|
||||
| Clarification Quiz | Guided topic extraction | User onboarding |
|
||||
| Focus Keyword | SEO-first writing | Differentiation |
|
||||
|
||||
#### Model Integration
|
||||
| Feature | Description | Strategic Value |
|
||||
|---------|-------------|-----------------|
|
||||
| OpenRouter Integration | Access to 100+ models | Flexibility |
|
||||
| Model Selection UI | Easy model switching | Usability |
|
||||
| Preset Configurations | Budget/Balanced/Premium | Quick start |
|
||||
| Cost Estimation | Real-time cost display | Budget control |
|
||||
|
||||
#### Analytics & Tracking
|
||||
| Feature | Description | Strategic Value |
|
||||
|---------|-------------|-----------------|
|
||||
| Cost Log | Basic usage tracking | Transparency |
|
||||
| Token Usage | Input/output tracking | Optimization |
|
||||
| Daily/Monthly Stats | Usage overview | Awareness |
|
||||
|
||||
#### Technical Foundation
|
||||
| Feature | Description | Strategic Value |
|
||||
|---------|-------------|-----------------|
|
||||
| Gutenberg Integration | Block editor sidebar | Core integration |
|
||||
| Classic Editor Support | Alternative UI | Coverage |
|
||||
| Shortcode Support | Flexible embedding | Versatility |
|
||||
| REST API Endpoints | Developer hooks | Ecosystem |
|
||||
| WebSocket Status | Real-time updates | Polish |
|
||||
|
||||
---
|
||||
|
||||
### Pro Addon Features
|
||||
|
||||
#### Advanced Refinement (Multi-Pass)
|
||||
| Feature | Description | Value |
|
||||
|---------|-------------|-------|
|
||||
| Multi-Pass Refinement | 3-stage polishing (clarity, SEO, quality) | High |
|
||||
| Keyword Density Optimization | Automatic SEO improvement | High |
|
||||
| Readability Scoring | Flesch-Kincaid integration | Medium |
|
||||
| Plagiarism Check | Integration with Copyscape API | Premium |
|
||||
| Brand Voice Training | Learn from existing content | Premium |
|
||||
|
||||
#### External Integrations
|
||||
| Feature | Description | Value |
|
||||
|---------|-------------|-------|
|
||||
| Brave Search Integration | Real-time web research | High |
|
||||
| Image Generation (DALL-E 3) | AI-generated featured images | High |
|
||||
| Image Generation (SDXL) | Stable Diffusion XL | Premium |
|
||||
| Unsplash Integration | Stock photo search | Medium |
|
||||
| WordPress Media Library | Direct image management | Medium |
|
||||
|
||||
#### Local Backend (Extended)
|
||||
| Feature | Description | Value |
|
||||
|---------|-------------|-------|
|
||||
| LM Studio Support (Full) | Complete integration | Medium |
|
||||
| Ollama Support (Full) | Complete integration | Medium |
|
||||
| Self-Hosted Models | Custom model hosting | Premium |
|
||||
| Multi-Instance Support | Multiple backend servers | Premium |
|
||||
| Load Balancing | Automatic failover | Premium |
|
||||
|
||||
#### Collaboration & Team
|
||||
| Feature | Description | Value |
|
||||
|---------|-------------|-------|
|
||||
| Team Workspaces | Shared configurations | Premium |
|
||||
| User Roles & Permissions | Role-based access | Premium |
|
||||
| Activity Logs | Audit trails | Medium |
|
||||
| Template Sharing | Team templates | Medium |
|
||||
| Content Approvals | Workflow integration | Premium |
|
||||
|
||||
#### Advanced Analytics
|
||||
| Feature | Description | Value |
|
||||
|---------|-------------|-------|
|
||||
| ROI Calculator | Content performance vs cost | Medium |
|
||||
| Content Performance | SEO ranking tracking | Premium |
|
||||
| A/B Testing | Headline variations | Premium |
|
||||
| Seasonal Trends | Content calendar | Premium |
|
||||
|
||||
#### Priority Support
|
||||
| Feature | Description | Value |
|
||||
|---------|-------------|-------|
|
||||
| Email Support | Direct assistance | Medium |
|
||||
| Priority Response | 24hr vs 7 days | Medium |
|
||||
| Feature Requests | Influence roadmap | Low |
|
||||
| Custom Integrations | Bespoke solutions | Premium |
|
||||
|
||||
---
|
||||
|
||||
## Hook System Architecture
|
||||
|
||||
### Purpose
|
||||
The free version provides comprehensive hooks that both Pro addon and third-party developers can use to extend functionality.
|
||||
|
||||
### Hook Types
|
||||
|
||||
#### 1. Action Hooks (Events)
|
||||
```php
|
||||
// Writing lifecycle
|
||||
do_action('wpaw_before_generate', $post_id, $mode);
|
||||
do_action('wpaw_after_generate', $post_id, $mode, $content);
|
||||
do_action('wpaw_planning_started', $post_id);
|
||||
do_action('wpaw_planning_complete', $post_id, $plan);
|
||||
do_action('wpaw_writing_started', $post_id, $section_index);
|
||||
do_action('wpaw_writing_section_complete', $post_id, $section_index, $content);
|
||||
do_action('wpaw_refinement_started', $post_id);
|
||||
do_action('wpaw_refinement_complete', $post_id, $refined_content);
|
||||
|
||||
// Model interactions
|
||||
do_action('wpaw_model_selected', $model_id, $task_type);
|
||||
do_action('wpaw_api_request_sent', $model_id, $tokens, $cost);
|
||||
do_action('wpaw_api_response_received', $model_id, $response_time);
|
||||
|
||||
// Context management
|
||||
do_action('wpaw_context_loaded', $post_id, $context_data);
|
||||
do_action('wpaw_context_updated', $post_id, $changes);
|
||||
|
||||
// Cost tracking
|
||||
do_action('wpaw_cost_recorded', $record);
|
||||
do_action('wpaw_daily_limit_reached', $total_cost);
|
||||
```
|
||||
|
||||
#### 2. Filter Hooks (Data Modification)
|
||||
```php
|
||||
// Context modification
|
||||
add_filter('wpaw_context_data', 'modify_context', 10, 2);
|
||||
add_filter('wpaw_post_content', 'process_content', 10, 2);
|
||||
add_filter('wpaw_planning_prompt', 'customize_planning', 10, 2);
|
||||
|
||||
// Model selection
|
||||
add_filter('wpaw_model_for_task', 'override_model', 10, 3);
|
||||
add_filter('wpaw_model_parameters', 'customize_params', 10, 2);
|
||||
|
||||
// Output modification
|
||||
add_filter('wpaw_generated_content', 'post_process', 10, 3);
|
||||
add_filter('wpaw_refinement_criteria', 'custom_criteria', 10, 2);
|
||||
|
||||
// Cost calculations
|
||||
add_filter('wpaw_cost_calculation', 'adjust_cost', 10, 2);
|
||||
add_filter('wpaw_token_count', 'modify_tokens', 10, 2);
|
||||
```
|
||||
|
||||
#### 3. REST API Endpoints
|
||||
```
|
||||
POST /wpaw/v1/generate
|
||||
- Generate content via API
|
||||
- Authentication: API key or OAuth
|
||||
|
||||
POST /wpaw/v1/refine
|
||||
- Refine existing content
|
||||
- Parameters: content, criteria, iterations
|
||||
|
||||
GET /wpaw/v1/cost-log
|
||||
- Retrieve cost tracking data
|
||||
- Filters: date range, post_id, model
|
||||
|
||||
GET /wpaw/v1/models
|
||||
- List available models
|
||||
- Include pricing and capabilities
|
||||
|
||||
POST /wpaw/v1/context
|
||||
- Update context for specific post
|
||||
```
|
||||
|
||||
#### 4. JavaScript Events (Frontend)
|
||||
```javascript
|
||||
// jQuery / DOM Events
|
||||
document.dispatchEvent(new CustomEvent('wpaw:generation-start', {
|
||||
detail: { postId, mode }
|
||||
}));
|
||||
|
||||
document.dispatchEvent(new CustomEvent('wpaw:generation-complete', {
|
||||
detail: { postId, content, cost }
|
||||
}));
|
||||
|
||||
document.dispatchEvent(new CustomEvent('wpaw:section-written', {
|
||||
detail: { postId, sectionIndex, content }
|
||||
}));
|
||||
|
||||
// React component hooks (for sidebar)
|
||||
window.wpawHooks = {
|
||||
onBeforeGenerate: (postId, mode) => {},
|
||||
onAfterGenerate: (postId, mode, content) => {},
|
||||
onModelSelected: (modelId, taskType) => {},
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Licensing System
|
||||
|
||||
### Pro Addon Structure
|
||||
|
||||
#### License Types
|
||||
| Type | Price Point | Activations | Features |
|
||||
|------|-------------|-------------|----------|
|
||||
| Personal | $49/year | 1 site | All Pro features |
|
||||
| Professional | $99/year | 5 sites | All Pro + priority support |
|
||||
| Agency | $199/year | 25 sites | All Pro + team features |
|
||||
| Enterprise | Custom | Unlimited | White-label + SLA |
|
||||
|
||||
#### License Verification Flow
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ User │ │ Pro Addon │ │ License │
|
||||
│ Activates │────▶│ Checks │────▶│ Server │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
│ │
|
||||
│ Valid? │
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ Enable Pro │ │ Response: │
|
||||
│ Features │◀────│ key, expiry, │
|
||||
└──────────────┘ │ features │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
### License Server Requirements
|
||||
|
||||
#### Endpoints
|
||||
```
|
||||
POST /api/v1/verify
|
||||
- Input: license_key, domain, product_id
|
||||
- Output: { valid: bool, expires: date, features: [] }
|
||||
|
||||
POST /api/v1/activate
|
||||
- Input: license_key, domain
|
||||
- Output: { activation_id, sites_used, sites_limit }
|
||||
|
||||
POST /api/v1/deactivate
|
||||
- Input: activation_id
|
||||
- Output: { success: bool }
|
||||
|
||||
GET /api/v1/status
|
||||
- Input: license_key
|
||||
- Output: { active: bool, sites: [], expires: date }
|
||||
```
|
||||
|
||||
#### Security Measures
|
||||
- License key hashed with SHA-256 before storage
|
||||
- Domain binding prevents key sharing
|
||||
- Activation limit enforcement
|
||||
- Automatic deactivation on payment failure
|
||||
- IP-based rate limiting on verification
|
||||
|
||||
---
|
||||
|
||||
## Migration Path
|
||||
|
||||
### Upgrading from Free to Pro
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ Step 1: User purchases Pro license │
|
||||
│ └── Receives license key via email │
|
||||
│ │
|
||||
│ Step 2: User installs Pro Addon │
|
||||
│ └── Upload via WordPress admin │
|
||||
│ └── Activates alongside free plugin │
|
||||
│ │
|
||||
│ Step 3: User enters license key │
|
||||
│ └── Addon validates against license server │
|
||||
│ └── Activates on current domain │
|
||||
│ │
|
||||
│ Step 4: Pro features unlocked │
|
||||
│ └── UI shows Pro indicators │
|
||||
│ └── New tabs/options become visible │
|
||||
│ └── Settings synced from free version │
|
||||
│ │
|
||||
│ Step 5: Deactivate/reactivate │
|
||||
│ └── Can transfer license to new domain │
|
||||
│ └── Previous site features disabled │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Data Migration
|
||||
- Settings stored in `wp_options` - shared between free and pro
|
||||
- Pro settings prefixed with `wpaw_pro_`
|
||||
- Cost tracking uses unified table structure
|
||||
- No data loss during upgrade
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
### Free Plugin (WordPress.org)
|
||||
```
|
||||
wp-agentic-writer/
|
||||
├── wp-agentic-writer.php # Main plugin file
|
||||
├── readme.txt # WordPress.org readme
|
||||
├── uninstall.php # Clean uninstall
|
||||
├── includes/
|
||||
│ ├── class-plugin.php # Core plugin class
|
||||
│ ├── class-settings.php # Settings page
|
||||
│ ├── class-gutenberg-sidebar.php # Sidebar UI
|
||||
│ ├── providers/
|
||||
│ │ └── class-openrouter-provider.php
|
||||
│ └── helpers/
|
||||
│ └── class-context-manager.php
|
||||
├── assets/
|
||||
│ ├── css/
|
||||
│ │ ├── agentic-variables.css
|
||||
│ │ ├── agentic-components.css
|
||||
│ │ └── agentic-workflow.css
|
||||
│ └── js/
|
||||
│ └── sidebar.js
|
||||
├── views/
|
||||
│ └── settings/
|
||||
└── lang/
|
||||
└── wp-agentic-writer.pot
|
||||
```
|
||||
|
||||
### Pro Addon
|
||||
```
|
||||
wp-agentic-writer-pro/
|
||||
├── wp-agentic-writer-pro.php # Main addon file
|
||||
├── includes/
|
||||
│ ├── class-license-manager.php # License verification
|
||||
│ ├── class-pro-features.php # Feature toggles
|
||||
│ ├── providers/
|
||||
│ │ ├── class-brave-search.php
|
||||
│ │ └── class-image-generator.php
|
||||
│ ├── refinement/
|
||||
│ │ └── class-multi-pass-refinement.php
|
||||
│ └── analytics/
|
||||
│ └── class-pro-analytics.php
|
||||
└── admin/
|
||||
└── class-pro-admin.php # Pro settings UI
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
### Pre-Release Validation
|
||||
|
||||
#### Free Version
|
||||
- [ ] Works with WordPress 6.0+ (latest stable)
|
||||
- [ ] Works with PHP 7.4+ (minimum) and 8.x (recommended)
|
||||
- [ ] No PHP errors/warnings in debug mode
|
||||
- [ ] All hooks documented and functional
|
||||
- [ ] Settings page renders correctly
|
||||
- [ ] Sidebar works in Gutenberg and Classic
|
||||
- [ ] Uninstall removes all plugin data
|
||||
- [ ] Internationalization (i18n) complete
|
||||
|
||||
#### Pro Addon
|
||||
- [ ] Gracefully fails without license
|
||||
- [ ] Shows upgrade prompts for locked features
|
||||
- [ ] License verification works offline (cached)
|
||||
- [ ] Reactivation works correctly
|
||||
- [ ] No errors when free plugin inactive
|
||||
- [ ] License expiry handled gracefully
|
||||
|
||||
---
|
||||
|
||||
## Rollout Strategy
|
||||
|
||||
### Phase 1: Preparation (Week 1-2)
|
||||
1. Finalize Pro feature set
|
||||
2. Set up license server infrastructure
|
||||
3. Create Pro addon codebase
|
||||
4. Prepare marketing copy
|
||||
|
||||
### Phase 2: Soft Launch (Week 3)
|
||||
1. Release free plugin to limited beta
|
||||
2. Test with 10-20 trusted users
|
||||
3. Gather feedback and fix critical issues
|
||||
|
||||
### Phase 3: WordPress.org Submission (Week 4)
|
||||
1. Prepare WordPress.org assets (banner, icons)
|
||||
2. Write compliant readme.txt
|
||||
3. Submit for review
|
||||
4. Address review feedback (typically 1-2 weeks)
|
||||
|
||||
### Phase 4: Pro Launch (Week 6-8)
|
||||
1. Launch license server
|
||||
2. Create sales page
|
||||
3. Set up payment processing
|
||||
4. Launch Pro addon
|
||||
|
||||
### Phase 5: Marketing (Ongoing)
|
||||
1. Blog posts on AI writing tools
|
||||
2. Tutorial videos on YouTube
|
||||
3. Guest posts on WordPress blogs
|
||||
4. Community forum engagement
|
||||
|
||||
---
|
||||
|
||||
## Pricing Considerations
|
||||
|
||||
### Factors for Pricing
|
||||
| Factor | Consideration |
|
||||
|--------|---------------|
|
||||
| Competition | Compare to AI writing plugins ($49-$299/year) |
|
||||
| Value Delivered | Pro features save X hours/month |
|
||||
| Market Position | Mid-tier vs premium |
|
||||
| Support Costs | Personal vs team tier |
|
||||
|
||||
### Recommended Pricing
|
||||
| Tier | Price | Rationale |
|
||||
|------|-------|-----------|
|
||||
| Personal | $49/year | ~$4/month - impulse purchase |
|
||||
| Professional | $99/year | ~$8/month - small business |
|
||||
| Agency | $199/year | ~$8/site/year - good value |
|
||||
|
||||
---
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
### Technical Risks
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| License server downtime | Cache verification locally (7 days) |
|
||||
| Key sharing | Domain binding + monitoring |
|
||||
| WordPress.org policy violation | Clear separation of free/pro |
|
||||
| Competition | Focus on unique value props |
|
||||
|
||||
### Business Risks
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Low adoption | Start with strong free feature set |
|
||||
| Support overload | Tiered support, clear documentation |
|
||||
| Piracy | Regular audits, IP monitoring |
|
||||
| Negative reviews | Proactive beta testing |
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### Free Version
|
||||
| Metric | Target |
|
||||
|--------|--------|
|
||||
| WordPress.org downloads (6 months) | 5,000+ |
|
||||
| Active installations | 2,000+ |
|
||||
| 5-star rating | 4.5+ |
|
||||
| Support forum engagement | <10% of installs |
|
||||
|
||||
### Pro Version
|
||||
| Metric | Target |
|
||||
|--------|--------|
|
||||
| Conversion rate (free→pro) | 2-5% |
|
||||
| Monthly revenue (year 1) | $500-$1,000 |
|
||||
| License renewals | 60%+ |
|
||||
| Customer satisfaction | 4.0+ |
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0
|
||||
**Last Updated:** 2026-05-17
|
||||
**Author:** Claude (AI Assistant)
|
||||
238
docs/features/MEMANTO_PRICING_STRATEGY.md
Normal file
238
docs/features/MEMANTO_PRICING_STRATEGY.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# MEMANTO Context Keeper - Pricing Strategy
|
||||
|
||||
**Version:** 1.0
|
||||
**Date:** 2026-06-07
|
||||
**Status:** Planning
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
MEMANTO is an external memory service (powered by Moorcheh SDK) that provides persistent, semantic memory for the WP Agentic Writer plugin. It is sold as a separate subscription from the plugin itself. Users who purchase MEMANTO get a dedicated instance URL and configure it in the plugin settings alongside their own Moorcheh API key.
|
||||
|
||||
**Core Value Proposition:** The plugin works perfectly without MEMANTO using the built-in Context Builder. MEMANTO enhances the experience with cross-session memory, semantic recall, and elimination of context loss.
|
||||
|
||||
---
|
||||
|
||||
## Product Structure
|
||||
|
||||
### What the User Purchases
|
||||
|
||||
| Item | Description |
|
||||
|---|---|
|
||||
| **WP Agentic Writer Plugin** | Sold separately. Lifetime or own subscription model. Works standalone. |
|
||||
| **MEMANTO Context Keeper** | Separate subscription. User receives a MEMANTO instance URL. |
|
||||
| **Moorcheh API Key** | User brings their own. Free tier available (10K vectors/month). Billed to user's own Moorcheh account. |
|
||||
|
||||
### MEMANTO Instance Per Subscription
|
||||
|
||||
- 1 subscription = 1 MEMANTO instance
|
||||
- 1 MEMANTO instance can be used across up to 15 WordPress sites (1 plugin per site)
|
||||
- 1 MEMANTO instance requires 1 Moorcheh API key
|
||||
- Users needing isolated memory per site purchase additional MEMANTO subscriptions
|
||||
|
||||
---
|
||||
|
||||
## Infrastructure Costs
|
||||
|
||||
### Hosting Architecture
|
||||
|
||||
| Component | Specification | Cost | Capacity |
|
||||
|---|---|---|---|
|
||||
| Coolify VPS | 8 vCPU, 32GB RAM, 200GB storage | $15/month | ~150 MEMANTO instances |
|
||||
| Subdomain | *.context.wpagentic.dev (wildcard) | $0 | Unlimited |
|
||||
| Moorcheh API | User's own key | $0 | User's responsibility |
|
||||
| **Cost per MEMANTO instance** | | **$0.10/month** | |
|
||||
|
||||
### Scaling Model
|
||||
|
||||
| Subscribers | VPS Nodes | Infra Cost | Revenue at $7/mo |
|
||||
|---:|---:|---:|---:|
|
||||
| 1–150 | 1 | $15/mo | $1,050/mo |
|
||||
| 151–300 | 2 | $30/mo | $2,100/mo |
|
||||
| 301–450 | 3 | $45/mo | $3,150/mo |
|
||||
| 1,000+ | 7 | $105/mo | $7,000/mo |
|
||||
|
||||
Each additional $15 VPS linearly adds capacity for 150 more subscribers.
|
||||
|
||||
---
|
||||
|
||||
## Value Delivered to Subscriber
|
||||
|
||||
### Cost Savings on AI Tokens
|
||||
|
||||
Using the recommended multi-model stack:
|
||||
|
||||
| Task | Model | Input/1M | Output/1M |
|
||||
|---|---|---|---|
|
||||
| Chat | google/gemini-2.5-flash | $0.30 | $2.50 |
|
||||
| Planning | deepseek/deepseek-chat | $0.20 | $0.77 |
|
||||
| Writing | deepseek/deepseek-chat | $0.20 | $0.77 |
|
||||
| Refinement | meta-llama/llama-3.3-70b-instruct | $0.10 | $0.32 |
|
||||
|
||||
### Per-Article Cost Comparison
|
||||
|
||||
| Metric | Without MEMANTO | With MEMANTO | Savings |
|
||||
|---|---:|---:|---:|
|
||||
| AI calls per article | 35 | 22 | −37% |
|
||||
| Input tokens | 43,900 | 16,450 | −63% |
|
||||
| Output tokens | 20,800 | 18,900 | −9% |
|
||||
| **Cost per article** | **$0.0377** | **$0.0259** | **−31%** |
|
||||
|
||||
### Monthly Savings at Scale
|
||||
|
||||
| Articles/month | Without MEMANTO | With MEMANTO | Saved |
|
||||
|---:|---:|---:|---:|
|
||||
| 25 | $0.94 | $0.65 | $0.29 |
|
||||
| 50 | $1.88 | $1.29 | $0.59 |
|
||||
| 100 | $3.77 | $2.59 | $1.18 |
|
||||
| 500 | $18.85 | $12.95 | $5.90 |
|
||||
|
||||
### Beyond Cost: Experience Quality
|
||||
|
||||
| Feature | Without MEMANTO | With MEMANTO |
|
||||
|---|---|---|
|
||||
| Context on mode switch | Can be lost | Preserved via semantic memory |
|
||||
| Cross-session continuity | Each session starts fresh | AI remembers everything |
|
||||
| User preference learning | Per-post only | Carries across all posts |
|
||||
| Chat history management | Truncate to last 6 messages | Semantic recall of relevant context |
|
||||
| Summarize-context calls | Required (4 per article) | Eliminated |
|
||||
| Detect-intent calls | Required (10 per article) | Eliminated |
|
||||
|
||||
---
|
||||
|
||||
## Moorcheh Free Tier Analysis
|
||||
|
||||
Free tier provides 10,000 vectors per month.
|
||||
|
||||
| Memory Type | Avg per Article | Notes |
|
||||
|---|---:|---|
|
||||
| Instructions (user messages) | 10 | Key user intents |
|
||||
| Decisions (plan approved, etc.) | 3 | Critical checkpoints |
|
||||
| Corrections (rejections) | 2 | "Don't do X" memories |
|
||||
| Artifacts (plan, section summaries) | 6 | Compact summaries |
|
||||
| Preferences (config, tone) | 2 | Per-article settings |
|
||||
| Context (session summaries) | 2 | End-of-session wrap |
|
||||
| **Total memories per article** | **~25** | |
|
||||
|
||||
**10K vectors ≈ 400 articles/month** on free Moorcheh tier. Sufficient for most users. Power users exceeding this would upgrade their own Moorcheh plan.
|
||||
|
||||
---
|
||||
|
||||
## Pricing Recommendation
|
||||
|
||||
### Launch Pricing
|
||||
|
||||
| Plan | Monthly | Annual | Effective Monthly | Sites | Moorcheh |
|
||||
|---|---:|---:|---:|---:|---|
|
||||
| **Context Keeper** | $7/mo | $59/yr | $4.92/mo | Up to 15 | Bring own key |
|
||||
|
||||
### Pricing Rationale
|
||||
|
||||
| Factor | Analysis |
|
||||
|---|---|
|
||||
| Infrastructure cost | $0.10/subscriber — margin is ~98% |
|
||||
| Cost savings delivered | ~$0.012/article; self-funding at 25+ articles/month |
|
||||
| Psychological threshold | $7 is below $10 impulse-buy barrier |
|
||||
| Competitive positioning | No comparable WordPress AI memory product exists |
|
||||
| Plugin dependency | MEMANTO is optional; plugin works without it |
|
||||
| User acquisition | Low entry price drives adoption and plugin stickiness |
|
||||
|
||||
### Revenue Projections
|
||||
|
||||
| Subscribers | Monthly Revenue | Annual Revenue | Infra Cost | Net Profit |
|
||||
|---:|---:|---:|---:|---:|
|
||||
| 25 | $175 | $2,100 | $15 | $160/mo |
|
||||
| 50 | $350 | $4,200 | $15 | $335/mo |
|
||||
| 100 | $700 | $8,400 | $15 | $685/mo |
|
||||
| 150 | $1,050 | $12,600 | $15 | $1,035/mo |
|
||||
| 300 | $2,100 | $25,200 | $30 | $2,070/mo |
|
||||
| 1,000 | $7,000 | $84,000 | $105 | $6,895/mo |
|
||||
|
||||
### Pricing Evolution Roadmap
|
||||
|
||||
**Phase 1: Launch (Months 1–6)**
|
||||
- Single tier at $7/mo or $59/yr
|
||||
- Focus on user acquisition and feedback
|
||||
- Monitor Moorcheh free tier usage patterns
|
||||
|
||||
**Phase 2: Growth (Months 6–12)**
|
||||
- Evaluate raising to $9/mo ($79/yr) based on demand
|
||||
- Introduce Pro tier at $15/mo for agencies (multi-MEMANTO)
|
||||
- Add managed Moorcheh option (include API key, absorb cost)
|
||||
|
||||
**Phase 3: Scale (12+ Months)**
|
||||
- Usage-based add-ons if needed
|
||||
- Enterprise licensing for WordPress VIP / managed hosts
|
||||
- Reseller program for agencies white-labeling the service
|
||||
|
||||
### When to Raise Price
|
||||
|
||||
Raise from $7 to $9 when **any** of these conditions are met:
|
||||
- 50+ active subscribers
|
||||
- Users volunteer that the price feels too low
|
||||
- Feature set has grown (file upload, conflict resolution UI, memory browser)
|
||||
- Churn is below 5% monthly
|
||||
|
||||
### Grandfathering Policy
|
||||
|
||||
When price increases:
|
||||
- Existing subscribers keep their original price for 6 months
|
||||
- Annual subscribers locked in until renewal
|
||||
- 30-day advance notice before any price change
|
||||
|
||||
---
|
||||
|
||||
## Billing and Delivery
|
||||
|
||||
### Subscriber Onboarding Flow
|
||||
|
||||
1. User purchases MEMANTO subscription via payment platform
|
||||
2. System provisions a MEMANTO instance on Coolify
|
||||
3. User receives:
|
||||
- MEMANTO instance URL (e.g., `https://abc123.context.wpagentic.dev`)
|
||||
- Configuration instructions
|
||||
4. User inputs in WP Agentic Writer settings:
|
||||
- MEMANTO URL
|
||||
- Their own Moorcheh API key
|
||||
5. Plugin validates connection and activates MEMANTO features
|
||||
|
||||
### Provisioning Architecture
|
||||
|
||||
Each MEMANTO instance:
|
||||
- Runs as a Docker container on Coolify
|
||||
- Uses a unique subdomain under *.context.wpagentic.dev
|
||||
- Isolates data per subscriber (separate agent namespaces)
|
||||
- User's Moorcheh API key connects to their own vector store
|
||||
|
||||
---
|
||||
|
||||
## Risks and Mitigations
|
||||
|
||||
| Risk | Likelihood | Impact | Mitigation |
|
||||
|---|---|---|---|
|
||||
| Users hit Moorcheh free tier limit | Medium | Low | Clear documentation on limits; prompt to upgrade their Moorcheh plan |
|
||||
| MEMANTO instance downtime | Low | High | Coolify health checks, auto-restart, user-facing status indicator |
|
||||
| User doesn't understand "bring own Moorcheh key" | Medium | Medium | Step-by-step onboarding guide; one-click Moorcheh signup link |
|
||||
| Subscriber churn after trial | Medium | Medium | Deliver clear value early (show "memories recalled" indicator in plugin) |
|
||||
| Infrastructure cost spike | Low | Low | Cost is fixed $15/node; scales linearly with revenue |
|
||||
| Plugin works fine without MEMANTO | Expected | None | That's by design. MEMANTO is enhancement, not requirement |
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Decision | Recommendation |
|
||||
|---|---|
|
||||
| **Launch price** | $7/month or $59/year |
|
||||
| **Cost per subscriber** | $0.10/month |
|
||||
| **Margin** | ~98% |
|
||||
| **Break-even** | 3 subscribers cover 1 VPS node |
|
||||
| **Upsell path** | $7 → $9 → $15 Pro tier |
|
||||
| **Key constraint** | User must provide own Moorcheh API key |
|
||||
| **Key advantage** | No comparable product in WordPress ecosystem |
|
||||
|
||||
---
|
||||
|
||||
**Document Date:** June 7, 2026
|
||||
**Status:** Draft — Pending validation with first 10 beta subscribers
|
||||
@@ -1,556 +0,0 @@
|
||||
# Local Backend + Codex Provider System with Cloud Fallback
|
||||
|
||||
Implement a provider system allowing text generation via Local Backend (Claude CLI proxy) and Codex API, while keeping image generation on OpenRouter's cloud API.
|
||||
|
||||
## Architecture Overview (Based on local-backend-feature.md)
|
||||
|
||||
**Current State:**
|
||||
- Plugin uses `WP_Agentic_Writer_OpenRouter_Provider` for all AI tasks
|
||||
- All requests go to cloud APIs (OpenRouter)
|
||||
- Costs per token, rate limits apply
|
||||
- 23+ files directly call provider singleton
|
||||
|
||||
**New State:**
|
||||
- **Local Backend**: User runs Node.js proxy on their machine (Claude CLI)
|
||||
- **Codex Provider**: Direct integration with OpenAI Codex API
|
||||
- **OpenRouter**: Fallback + image generation only
|
||||
- **Provider Manager**: Routes tasks to appropriate provider
|
||||
|
||||
**Flow:**
|
||||
```
|
||||
WordPress Plugin → Provider Manager → Local Backend (http://user-ip:8080)
|
||||
→ Codex API (https://api.openai.com)
|
||||
→ OpenRouter (images + fallback)
|
||||
```
|
||||
|
||||
## Provider Architecture
|
||||
|
||||
### 1. Provider Interface (Common Contract)
|
||||
|
||||
```php
|
||||
interface WP_Agentic_Writer_AI_Provider_Interface {
|
||||
public function chat($messages, $options, $type);
|
||||
public function chat_stream($messages, $options, $type, $callback);
|
||||
public function generate_image($prompt, $model, $options);
|
||||
public function is_configured();
|
||||
public function test_connection();
|
||||
public function supports_task_type($type);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Provider Manager (Router)
|
||||
|
||||
```php
|
||||
class WP_Agentic_Writer_Provider_Manager {
|
||||
public static function get_provider_for_task($type) {
|
||||
$settings = get_option('wp_agentic_writer_settings');
|
||||
$task_providers = $settings['task_providers'] ?? [];
|
||||
|
||||
$provider_name = $task_providers[$type] ?? 'openrouter';
|
||||
|
||||
switch ($provider_name) {
|
||||
case 'local_backend':
|
||||
return new WP_Agentic_Writer_Local_Backend_Provider();
|
||||
case 'codex':
|
||||
return new WP_Agentic_Writer_Codex_Provider();
|
||||
case 'openrouter':
|
||||
default:
|
||||
return WP_Agentic_Writer_OpenRouter_Provider::get_instance();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Provider Implementations
|
||||
|
||||
**A. Local Backend Provider** (Primary for text tasks)
|
||||
- **File**: `includes/class-local-backend-provider.php`
|
||||
- **Endpoint**: `http://192.168.x.x:8080` (user's machine)
|
||||
- **Protocol**: HTTP POST to `/v1/messages` (OpenAI-compatible)
|
||||
- **Backend**: Node.js proxy → Claude CLI
|
||||
- **Supports**: `chat`, `clarity`, `planning`, `writing`, `refinement`
|
||||
- **Cost**: $0 (uses user's Claude CLI + Z.ai/Anthropic)
|
||||
|
||||
**B. Codex Provider** (Alternative text provider)
|
||||
- **File**: `includes/class-codex-provider.php`
|
||||
- **Endpoint**: `https://api.openai.com/v1/chat/completions`
|
||||
- **Protocol**: Standard OpenAI API
|
||||
- **Supports**: `chat`, `clarity`, `planning`, `writing`, `refinement`
|
||||
- **Cost**: Per OpenAI pricing
|
||||
|
||||
**C. OpenRouter Provider** (Existing, for images + fallback)
|
||||
- **File**: `includes/class-openrouter-provider.php` (existing)
|
||||
- **Endpoint**: `https://openrouter.ai/api/v1/chat/completions`
|
||||
- **Supports**: ALL task types (fallback when local unavailable)
|
||||
- **Primary use**: `image` generation only in hybrid mode
|
||||
|
||||
### Configuration Strategy
|
||||
|
||||
#### Settings Structure
|
||||
|
||||
```php
|
||||
'wp_agentic_writer_settings' => [
|
||||
// Provider routing
|
||||
'provider_mode' => 'hybrid', // 'cloud', 'local', 'hybrid'
|
||||
'task_providers' => [
|
||||
'chat' => 'local_backend',
|
||||
'clarity' => 'local_backend',
|
||||
'planning' => 'local_backend',
|
||||
'writing' => 'local_backend',
|
||||
'refinement' => 'codex', // Or local_backend
|
||||
'image' => 'openrouter' // Always OpenRouter
|
||||
],
|
||||
|
||||
// Local Backend settings
|
||||
'local_backend_url' => 'http://192.168.1.105:8080',
|
||||
'local_backend_key' => 'dummy',
|
||||
'local_backend_model' => 'claude-via-cli',
|
||||
'local_backend_enabled' => true,
|
||||
|
||||
// Codex settings
|
||||
'codex_api_key' => 'sk-...',
|
||||
'codex_model' => 'gpt-4',
|
||||
'codex_enabled' => true,
|
||||
|
||||
// OpenRouter (existing)
|
||||
'openrouter_api_key' => 'sk-or-...',
|
||||
'image_model' => 'black-forest-labs/flux-1.1-pro',
|
||||
]
|
||||
```
|
||||
|
||||
#### Recommended Configuration
|
||||
|
||||
**Optimal Hybrid Setup:**
|
||||
```
|
||||
chat → Local Backend (free, private, fast)
|
||||
clarity → Local Backend (free, fast)
|
||||
planning → Local Backend (free, fast)
|
||||
writing → Local Backend (free, unlimited)
|
||||
refinement → Codex (cloud quality when needed)
|
||||
image → OpenRouter (only option for FLUX/Recraft)
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- 80%+ requests via Local Backend = $0 cost
|
||||
- Privacy for all text content
|
||||
- Codex as quality alternative
|
||||
- Images via best models (OpenRouter)
|
||||
|
||||
## Implementation Components
|
||||
|
||||
### 1. Local Backend Package (Separate Distribution)
|
||||
|
||||
**Package:** `agentic-writer-local-backend.zip`
|
||||
|
||||
**Contents:**
|
||||
```
|
||||
agentic-writer-local-backend/
|
||||
├── claude-proxy.js # Node.js HTTP server
|
||||
├── start-proxy.sh # Launch with IP detection
|
||||
├── stop-proxy.sh # Clean shutdown
|
||||
├── test-connection.sh # Verify proxy works
|
||||
├── get-local-ip.sh # Find machine IP
|
||||
├── package.json # Express dependency
|
||||
├── README.md # Setup guide
|
||||
└── TROUBLESHOOTING.md # Common issues
|
||||
```
|
||||
|
||||
**Proxy Server (`claude-proxy.js`):**
|
||||
- Spawns user's Claude CLI for each request
|
||||
- OpenAI-compatible `/v1/messages` endpoint
|
||||
- Health check `/ping` endpoint
|
||||
- Binds to `0.0.0.0:8080` for LAN access
|
||||
- Logs requests for debugging
|
||||
|
||||
**User Flow:**
|
||||
1. Download ZIP from plugin settings
|
||||
2. Extract and run `./start-proxy.sh`
|
||||
3. Copy displayed Base URL (e.g., `http://192.168.1.105:8080`)
|
||||
4. Paste into plugin settings
|
||||
5. Test connection → generate content
|
||||
|
||||
### 2. Plugin Integration Files
|
||||
|
||||
**New Files:**
|
||||
```
|
||||
includes/class-local-backend-provider.php
|
||||
includes/class-codex-provider.php
|
||||
includes/class-provider-manager.php
|
||||
includes/interface-ai-provider.php
|
||||
views/settings/tab-local-backend.php
|
||||
admin/js/test-local-backend.js
|
||||
downloads/agentic-writer-local-backend.zip
|
||||
```
|
||||
|
||||
**Modified Files:**
|
||||
```
|
||||
includes/class-openrouter-provider.php
|
||||
→ Implement WP_Agentic_Writer_AI_Provider_Interface
|
||||
→ No behavior changes
|
||||
|
||||
includes/class-gutenberg-sidebar.php
|
||||
→ Replace: WP_Agentic_Writer_OpenRouter_Provider::get_instance()
|
||||
→ With: WP_Agentic_Writer_Provider_Manager::get_provider_for_task($type)
|
||||
|
||||
+ 20 other files with provider calls
|
||||
```
|
||||
|
||||
### 3. Settings UI
|
||||
|
||||
**New Tab:** "Local Backend"
|
||||
- Download local backend package
|
||||
- Base URL input
|
||||
- API Key input (dummy)
|
||||
- Model selector
|
||||
- "Test Connection" button
|
||||
- Connection status indicator
|
||||
- Troubleshooting guide
|
||||
|
||||
**Per-Task Routing (Advanced):**
|
||||
- Simple mode: Enable/Disable Local Backend (uses for all text)
|
||||
- Advanced mode: Task routing matrix
|
||||
|
||||
### 4. Migration & Backwards Compatibility
|
||||
|
||||
**Phase 1: Abstraction (Non-Breaking)**
|
||||
- Create `interface-ai-provider.php`
|
||||
- Create `class-provider-manager.php`
|
||||
- OpenRouter implements interface
|
||||
- All calls route through manager → defaults to OpenRouter
|
||||
- **100% backwards compatible, no settings changes**
|
||||
|
||||
**Phase 2: Local Backend Provider**
|
||||
- Implement `class-local-backend-provider.php`
|
||||
- Create proxy package (claude-proxy.js + scripts)
|
||||
- Add "Local Backend" settings tab
|
||||
- Implement connection test handler
|
||||
- Test with user's local setup
|
||||
|
||||
**Phase 3: Codex Provider**
|
||||
- Implement `class-codex-provider.php`
|
||||
- Add Codex API key to settings
|
||||
- Add Codex as task routing option
|
||||
- Test Codex integration
|
||||
|
||||
**Phase 4: Update All Provider Calls**
|
||||
- Update 23+ files to use Provider Manager
|
||||
- Test all task types (chat, clarity, planning, writing, refinement, image)
|
||||
- Ensure streaming works with all providers
|
||||
- Verify cost tracking
|
||||
|
||||
## Key Technical Decisions
|
||||
|
||||
### Local Backend Protocol
|
||||
|
||||
**Why OpenAI-compatible format:**
|
||||
- Plugin already uses message-based format
|
||||
- Easy to proxy to Claude CLI
|
||||
- Future-proof for other local models
|
||||
|
||||
**Request Format:**
|
||||
```json
|
||||
POST http://192.168.1.105:8080/v1/messages
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "Write about AI"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Response Format:**
|
||||
```json
|
||||
{
|
||||
"id": "local-1234567890",
|
||||
"object": "chat.completion",
|
||||
"model": "claude-local",
|
||||
"choices": [{
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "Article content..."
|
||||
},
|
||||
"finish_reason": "stop"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### Codex Integration
|
||||
|
||||
**Direct API Calls:**
|
||||
- Use OpenAI PHP library or `wp_remote_post`
|
||||
- Standard chat completions endpoint
|
||||
- Same format as OpenRouter
|
||||
|
||||
**Why Codex:**
|
||||
- High quality for coding/technical content
|
||||
- Alternative to Local Backend
|
||||
- Cloud-based when user's machine offline
|
||||
|
||||
## Cost Tracking Integration
|
||||
|
||||
**Challenge:** Local Backend = $0, Codex/OpenRouter = cost
|
||||
|
||||
**Solution:**
|
||||
```php
|
||||
// Provider returns cost data
|
||||
$result = $provider->chat($messages, $options, $type);
|
||||
$cost = $result['cost'] ?? 0;
|
||||
|
||||
if ($cost > 0 && $post_id > 0) {
|
||||
do_action('wp_aw_after_api_request',
|
||||
$post_id,
|
||||
$result['model'] ?? 'unknown',
|
||||
$type,
|
||||
$result['input_tokens'] ?? 0,
|
||||
$result['output_tokens'] ?? 0,
|
||||
$cost
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Dashboard Display:**
|
||||
```
|
||||
Session Cost: $0.15
|
||||
- Local Backend: 12 requests (free)
|
||||
- Codex: 3 requests ($0.10)
|
||||
- OpenRouter: 2 images ($0.05)
|
||||
|
||||
Today: $2.40
|
||||
Month: $45.00
|
||||
```
|
||||
|
||||
## Error Handling & Fallbacks
|
||||
|
||||
### Local Backend Unreachable
|
||||
|
||||
```php
|
||||
$local_provider = new WP_Agentic_Writer_Local_Backend_Provider();
|
||||
|
||||
if (!$local_provider->is_available()) {
|
||||
// Fallback to OpenRouter
|
||||
error_log('Local Backend unavailable, using OpenRouter fallback');
|
||||
return WP_Agentic_Writer_OpenRouter_Provider::get_instance();
|
||||
}
|
||||
```
|
||||
|
||||
**Admin Notice:**
|
||||
"⚠️ Local Backend unreachable. Using OpenRouter fallback. Check proxy: `./start-proxy.sh`"
|
||||
|
||||
### Connection Test Results
|
||||
|
||||
```
|
||||
✅ Connected! Proxy responding correctly.
|
||||
❌ Connection timeout. Is proxy running? Check: ps aux | grep claude-proxy
|
||||
❌ Connection refused. Start proxy: ./start-proxy.sh
|
||||
❌ Wrong IP. Find correct IP: ./get-local-ip.sh
|
||||
❌ Claude CLI not responding. Test: echo "test" | claude
|
||||
```
|
||||
|
||||
## UI/UX Considerations
|
||||
|
||||
### Settings Page Flow
|
||||
|
||||
1. **Tab: Local Backend**
|
||||
- Big download button for proxy package
|
||||
- Prerequisites checklist
|
||||
- Base URL input (pre-filled from clipboard?)
|
||||
- Test connection button
|
||||
- Status: 🟢 Connected / 🔴 Offline
|
||||
|
||||
2. **Tab: Providers**
|
||||
- Simple mode: "Use Local Backend" toggle
|
||||
- Advanced mode: Task routing matrix
|
||||
- Provider status indicators
|
||||
|
||||
3. **Tab: Models** (existing)
|
||||
- Add Codex models
|
||||
- Show provider per model
|
||||
|
||||
### Sidebar Indicators
|
||||
|
||||
**Provider Badge:**
|
||||
```
|
||||
🏠 Local (Free)
|
||||
🔗 Codex ($0.02)
|
||||
☁️ OpenRouter ($0.05)
|
||||
```
|
||||
|
||||
**Connection Status:**
|
||||
```
|
||||
🟢 Local Backend: Connected
|
||||
🔴 Local Backend: Offline (using OpenRouter)
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
**Test Cases:**
|
||||
1. Cloud-only mode (existing behavior)
|
||||
2. Local-only mode (Ollama for all text)
|
||||
3. Hybrid mode (recommended config)
|
||||
4. Fallback when Ollama unavailable
|
||||
5. Streaming works with both providers
|
||||
6. Cost tracking accurate
|
||||
7. Model selection per provider
|
||||
|
||||
## Performance Implications
|
||||
|
||||
**Local Backend:**
|
||||
- **Latency**: ~50-200ms LAN vs ~500-2000ms cloud
|
||||
- **Throughput**: Limited by Claude CLI (~20-30 tokens/sec)
|
||||
- **Concurrency**: One request at a time (spawn per request)
|
||||
- **Quality**: Same as cloud Claude (uses same models)
|
||||
|
||||
**Codex:**
|
||||
- **Latency**: Standard OpenAI API latency
|
||||
- **Quality**: High for technical/coding content
|
||||
- **Cost**: Per-token pricing
|
||||
|
||||
**OpenRouter:**
|
||||
- **Image Generation**: Only option for FLUX/Recraft
|
||||
- **Fallback**: When local backend offline
|
||||
- **Cost**: Per-token pricing
|
||||
|
||||
## Deployment Scenarios
|
||||
|
||||
### Scenario 1: Local Development (User's Machine)
|
||||
|
||||
**Setup:**
|
||||
- WordPress on Local by Flywheel (bricks.local)
|
||||
- Node.js proxy on same machine (localhost:8080)
|
||||
- Claude CLI configured with Z.ai
|
||||
|
||||
**Config:**
|
||||
```
|
||||
Local Backend URL: http://localhost:8080
|
||||
All text tasks: Local Backend
|
||||
Images: OpenRouter
|
||||
Cost: ~$0 for text, ~$0.05/image
|
||||
```
|
||||
|
||||
### Scenario 2: Local Dev + Cloud Production
|
||||
|
||||
**Dev:**
|
||||
- Use Local Backend for free development
|
||||
- Test with real Claude quality
|
||||
|
||||
**Production:**
|
||||
- Auto-switch to OpenRouter when local unavailable
|
||||
- Seamless fallback
|
||||
|
||||
### Scenario 3: Agency with Shared Local Backend
|
||||
|
||||
**Setup:**
|
||||
- One machine runs proxy on LAN
|
||||
- Multiple WordPress sites connect to it
|
||||
- All sites share one Z.ai account
|
||||
|
||||
**Config:**
|
||||
```
|
||||
Local Backend URL: http://192.168.1.50:8080
|
||||
Cost: Free for entire team
|
||||
```
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Core Infrastructure (Week 1)
|
||||
- [ ] Create provider interface
|
||||
- [ ] Create provider manager
|
||||
- [ ] OpenRouter implements interface
|
||||
- [ ] Update 3-5 files to use manager (test)
|
||||
- [ ] Verify backwards compatibility
|
||||
|
||||
### Phase 2: Local Backend Package (Week 1)
|
||||
- [ ] Create `claude-proxy.js` with `/v1/messages` endpoint
|
||||
- [ ] Create startup/shutdown scripts
|
||||
- [ ] Test with actual Claude CLI
|
||||
- [ ] Package as ZIP
|
||||
- [ ] Write README with setup guide
|
||||
|
||||
### Phase 3: Local Backend Provider (Week 2)
|
||||
- [ ] Implement `class-local-backend-provider.php`
|
||||
- [ ] Add settings tab UI
|
||||
- [ ] Implement connection test
|
||||
- [ ] Add ZIP download from settings
|
||||
- [ ] Test end-to-end flow
|
||||
|
||||
### Phase 4: Codex Provider (Week 2)
|
||||
- [ ] Implement `class-codex-provider.php`
|
||||
- [ ] Add Codex API key to settings
|
||||
- [ ] Test Codex integration
|
||||
- [ ] Add to task routing options
|
||||
|
||||
### Phase 5: Full Rollout (Week 3)
|
||||
- [ ] Update all 23+ files to use provider manager
|
||||
- [ ] Test all task types
|
||||
- [ ] Verify streaming works
|
||||
- [ ] Test cost tracking
|
||||
- [ ] Documentation
|
||||
|
||||
### Phase 6: Polish (Week 3)
|
||||
- [ ] Connection status widget
|
||||
- [ ] Auto-fallback logic
|
||||
- [ ] Error messages with actionable guidance
|
||||
- [ ] Video tutorial
|
||||
- [ ] Troubleshooting guide
|
||||
|
||||
## Implementation Estimate
|
||||
|
||||
**Phase 1 (Infrastructure):** 4-5 hours
|
||||
- Provider interface, manager, OpenRouter refactor
|
||||
- Test with 3-5 files
|
||||
|
||||
**Phase 2 (Local Backend Package):** 6-8 hours
|
||||
- Node.js proxy development
|
||||
- Scripts (start, stop, test)
|
||||
- ZIP packaging
|
||||
- Documentation
|
||||
|
||||
**Phase 3 (Local Backend Integration):** 8-10 hours
|
||||
- Provider class
|
||||
- Settings UI
|
||||
- Connection test
|
||||
- End-to-end testing
|
||||
|
||||
**Phase 4 (Codex):** 4-6 hours
|
||||
- Provider implementation
|
||||
- Settings integration
|
||||
- Testing
|
||||
|
||||
**Phase 5 (Full Rollout):** 8-10 hours
|
||||
- Update 23+ files
|
||||
- Test all scenarios
|
||||
- Cost tracking
|
||||
- Documentation
|
||||
|
||||
**Phase 6 (Polish):** 4-6 hours
|
||||
- UI improvements
|
||||
- Error handling
|
||||
- Video tutorial
|
||||
- Troubleshooting docs
|
||||
|
||||
**Total:** 34-45 hours (~1-1.5 weeks)
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ User can download local backend package
|
||||
✅ User can start proxy on their machine
|
||||
✅ Plugin connects to local backend successfully
|
||||
✅ All text tasks work via local backend ($0 cost)
|
||||
✅ Images work via OpenRouter
|
||||
✅ Codex works as alternative provider
|
||||
✅ Automatic fallback to OpenRouter when local offline
|
||||
✅ Cost tracking shows local = $0, cloud = actual cost
|
||||
✅ Streaming works with all providers
|
||||
✅ 100% backwards compatible (defaults to OpenRouter)
|
||||
|
||||
## Ready to Implement
|
||||
|
||||
This plan matches `local-backend-feature.md` requirements:
|
||||
- ✅ Claude CLI proxy via Node.js
|
||||
- ✅ HTTP-based local backend
|
||||
- ✅ Codex integration
|
||||
- ✅ OpenRouter for images
|
||||
- ✅ Provider abstraction system
|
||||
- ✅ Fallback logic
|
||||
- ✅ Complete UI/UX flow
|
||||
|
||||
Confirm to proceed with implementation.
|
||||
@@ -1,352 +0,0 @@
|
||||
# DECIDE File Comparison Report
|
||||
|
||||
**File:** `docs/user-facing/AGENTIC_VIBE_IMPLEMENTATION_PLAN.md`
|
||||
**Audit Date:** 2026-05-17
|
||||
**Compared Against:** Actual implementation in `/assets/css/`, `/assets/js/settings-v2.js`, `/includes/class-settings-v2.php`
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The **AGENTIC_VIBE_IMPLEMENTATION_PLAN.md** describes an 8-phase plan to redesign the settings page with Bootstrap 5 + Custom CSS approach. After comparing against actual implementation, the plan is **SUBSTANTIALLY IMPLEMENTED**.
|
||||
|
||||
| Phase | Status | Implementation Quality |
|
||||
|-------|--------|------------------------|
|
||||
| Phase 1: Foundation & CSS Variables | ✅ FULLY IMPLEMENTED | Excellent match |
|
||||
| Phase 2: Header & Status Section | ✅ FULLY IMPLEMENTED | Complete with AJAX |
|
||||
| Phase 3: Workflow Pipeline | ✅ FULLY IMPLEMENTED | CSS + JS + HTML integrated |
|
||||
| Phase 4: Cost Log Table | ✅ FULLY IMPLEMENTED | Enhanced with grouping |
|
||||
| Phase 5: Model Cards | ✅ FULLY IMPLEMENTED | Integrated into settings-v2.css |
|
||||
| Phase 6: Animations & Polish | ✅ FULLY IMPLEMENTED | All animation classes present |
|
||||
| Phase 7: Dark Mode | ✅ FULLY IMPLEMENTED | Dark theme default |
|
||||
| Phase 8: Testing | ❌ NOT DOCUMENTED | N/A - plan doc only |
|
||||
|
||||
---
|
||||
|
||||
## Phase-by-Phase Comparison
|
||||
|
||||
### Phase 1: Foundation & CSS Variables ✅
|
||||
|
||||
**Planned Files:**
|
||||
- `agentic-variables.css` - CSS Variable System
|
||||
- `agentic-bootstrap-custom.css` - Bootstrap Customization
|
||||
- `agentic-components.css` - Component Library
|
||||
|
||||
**Actual Implementation:**
|
||||
| File | Status | Match |
|
||||
|------|--------|-------|
|
||||
| `agentic-variables.css` (2990 bytes) | ✅ EXISTS | 95% match - variables match spec |
|
||||
| `agentic-bootstrap-custom.css` (11734 bytes) | ✅ EXISTS | 100% match - Bootstrap overrides present |
|
||||
| `agentic-components.css` (10927 bytes) | ✅ EXISTS | 100% match - all components implemented |
|
||||
|
||||
**Comparison Details:**
|
||||
|
||||
The actual implementation uses a **dark theme by default** rather than the light theme specified in the plan. The color scheme was adapted for better visibility:
|
||||
- `--wpaw-primary: #17a2b8` (actual) vs `#3b82f6` (planned) - adapted for existing design
|
||||
- `--wpaw-bg-primary: #1a2332` (actual) - dark by default, not light
|
||||
- Light mode support added as `.wpaw-light-mode` override class
|
||||
|
||||
**Conclusion:** Phase 1 is **fully implemented** with adaptive design choices.
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Header & Status Section ✅
|
||||
|
||||
**Planned:**
|
||||
- Header with plugin icon, title, version
|
||||
- Status badge (Connected/Online)
|
||||
- Stats grid (4 cards): Articles, Total Cost, API Status, Last Updated
|
||||
- AJAX handler for real-time stats
|
||||
|
||||
**Actual Implementation:**
|
||||
|
||||
In `class-settings-v2.php`:
|
||||
```php
|
||||
add_action( 'wp_ajax_wpaw_get_header_stats', array( $this, 'ajax_get_header_stats' ) );
|
||||
```
|
||||
|
||||
AJAX handler exists with:
|
||||
- Total articles count
|
||||
- Total cost calculation
|
||||
- API status (from settings)
|
||||
- Last activity timestamp
|
||||
|
||||
In `settings-v2.js`:
|
||||
```javascript
|
||||
function loadHeaderStats() {
|
||||
$.ajax({
|
||||
url: wpawSettingsV2.ajaxUrl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wpaw_get_header_stats',
|
||||
nonce: wpawSettingsV2.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
// Updates stat cards
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Conclusion:** Phase 2 is **fully implemented** with AJAX-based real-time updates.
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Workflow Pipeline Visualization ✅
|
||||
|
||||
**Planned:**
|
||||
- `agentic-workflow.css` - Workflow progress component
|
||||
- 5-step pipeline visualization (Context → Planning → Writing → Refinement → Done)
|
||||
- Animated connectors between steps
|
||||
|
||||
**Implementation (Completed 2026-05-17):**
|
||||
|
||||
| Component | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| `agentic-workflow.css` | ✅ CREATED | 330+ lines with all step styles, connectors, animations |
|
||||
| `.wpaw-step` classes | ✅ IMPLEMENTED | active, completed, pending, error states |
|
||||
| `.wpaw-step-circle` | ✅ IMPLEMENTED | With pulse animation for active step |
|
||||
| `.wpaw-step-connector` | ✅ IMPLEMENTED | With sliding progress animation |
|
||||
| `wpaw-slide-progress` | ✅ IMPLEMENTED | Animated connector for active step |
|
||||
|
||||
**Files Updated:**
|
||||
- `assets/css/agentic-workflow.css` - New file (330+ lines)
|
||||
- `assets/js/settings-v2.js` - Added `initWorkflowDisplay()` function
|
||||
- `views/settings/layout.php` - Added workflow HTML component
|
||||
- `includes/class-settings-v2.php` - Enqueued new CSS file
|
||||
- `assets/css/settings-v2.css` - Added dark theme overrides
|
||||
|
||||
**JavaScript Functions:**
|
||||
```javascript
|
||||
window.updateWorkflowStatus(status, message) - Updates step display
|
||||
window.demoWorkflow() - Demo function for testing
|
||||
initWorkflowDisplay() - Initializes on page load
|
||||
```
|
||||
|
||||
**Status Mapping:**
|
||||
| Backend Status | Step | Label |
|
||||
|---------------|------|-------|
|
||||
| starting | 1 | Context |
|
||||
| planning | 2 | Planning |
|
||||
| plan_complete | 2 | Planning |
|
||||
| writing | 3 | Writing |
|
||||
| writing_section | 3 | Writing |
|
||||
| refinement | 4 | Refinement |
|
||||
| complete/done | 5 | Done |
|
||||
|
||||
**Conclusion:** Phase 3 is **fully implemented** with 5-step workflow visualization, animated connectors, and real-time status updates.
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: Enhanced Cost Log Table ✅
|
||||
|
||||
**Planned:**
|
||||
- Redesigned table with columns: Timestamp, Post, Model, Action, Input, Output, Cost, Status
|
||||
- Status color indicators (border-left color based on cost)
|
||||
- Grouped display by post
|
||||
- Pagination
|
||||
|
||||
**Actual Implementation:**
|
||||
|
||||
In `settings-v2.js`:
|
||||
```javascript
|
||||
function renderCostLogTable(data) {
|
||||
// Grouped by post with collapsible details
|
||||
records.forEach((group, index) => {
|
||||
const collapseId = `collapse-post-${group.post_id}-${index}`;
|
||||
// Main row with post title, call count, total cost
|
||||
// Collapsible detail row with individual calls
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
CSS classes found:
|
||||
- `.wpaw-cost-table` - table styling
|
||||
- `.row-success`, `.row-warning`, `.row-error` - status colors
|
||||
- `.wpaw-code` - monospace styling
|
||||
- `.wpaw-details-table` - detail table styling
|
||||
|
||||
**Additional Features Implemented:**
|
||||
- Filter by post, model, type, date range
|
||||
- Per-page selector (10, 25, 50, 100)
|
||||
- CSV export
|
||||
- Bootstrap pagination
|
||||
- Stats summary (all-time, monthly, today, average)
|
||||
|
||||
**Conclusion:** Phase 4 is **fully implemented** with enhanced grouping and filtering.
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: Model Configuration Cards ✅
|
||||
|
||||
**Planned:**
|
||||
- `agentic-models.css` - Model card component
|
||||
- Card design with header, metrics, actions
|
||||
|
||||
**Actual Implementation:**
|
||||
|
||||
In `agentic-components.css`:
|
||||
```css
|
||||
.wpaw-model-card {
|
||||
background: var(--wpaw-bg-secondary);
|
||||
border: 1px solid var(--wpaw-border);
|
||||
border-radius: var(--wpaw-radius-md);
|
||||
/* ... */
|
||||
}
|
||||
|
||||
.wpaw-model-header { /* ... */ }
|
||||
.wpaw-model-stat { /* ... */ }
|
||||
.wpaw-model-metrics { /* ... */ }
|
||||
.wpaw-metric { /* ... */ }
|
||||
.wpaw-metric-label { /* ... */ }
|
||||
.wpaw-metric-value { /* ... */ }
|
||||
.wpaw-model-actions { /* ... */ }
|
||||
```
|
||||
|
||||
**In `settings-v2.css`:**
|
||||
- Model preset cards (Budget, Balanced, Premium)
|
||||
- Clickable preset selection with visual feedback
|
||||
|
||||
**Conclusion:** Phase 5 is **fully implemented** - model card component exists and preset system is working.
|
||||
|
||||
---
|
||||
|
||||
### Phase 6: Animations & Polish ✅
|
||||
|
||||
**Planned:**
|
||||
- `agentic-animations.css` - Animation library
|
||||
- Fade in, slide in, scale in animations
|
||||
- Shimmer loading effect
|
||||
|
||||
**Actual Implementation:**
|
||||
|
||||
All animations found in `agentic-components.css`:
|
||||
|
||||
| Animation | Class | Status |
|
||||
|-----------|-------|--------|
|
||||
| Pulse | `.wpaw-animate-pulse` | ✅ Implemented |
|
||||
| Spin | `.wpaw-animate-spin` | ✅ Implemented |
|
||||
| Fade In | `.wpaw-fade-in` | ✅ Implemented |
|
||||
| Slide In Right | `.wpaw-slide-in-right` | ✅ Implemented |
|
||||
| Scale In | `.wpaw-scale-in` | ✅ Implemented |
|
||||
| Shimmer | `.wpaw-shimmer` | ✅ Implemented |
|
||||
|
||||
**Skeleton Loaders:**
|
||||
- `.wpaw-skeleton`
|
||||
- `.wpaw-skeleton-text`
|
||||
- `.wpaw-skeleton-heading`
|
||||
|
||||
**Conclusion:** Phase 6 is **fully implemented** - all animations present.
|
||||
|
||||
---
|
||||
|
||||
### Phase 7: Dark Mode ✅
|
||||
|
||||
**Planned:**
|
||||
- Dark mode support via CSS variables
|
||||
- `@media (prefers-color-scheme: dark)` query
|
||||
|
||||
**Actual Implementation:**
|
||||
|
||||
The design uses **dark theme by default** with light mode as an override:
|
||||
|
||||
```css
|
||||
/* Dark mode is default - no @media query needed */
|
||||
|
||||
/* Light mode override */
|
||||
.wpaw-light-mode {
|
||||
--wpaw-bg-primary: #ffffff;
|
||||
--wpaw-bg-secondary: #f8f9fa;
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** The plan specified light theme with dark mode via `@media`, but the implementation flipped this - dark theme is primary with light mode as optional override. This is a reasonable design adaptation.
|
||||
|
||||
**Conclusion:** Phase 7 is **fully implemented** with inverted approach (dark default).
|
||||
|
||||
---
|
||||
|
||||
### Phase 8: Testing ❌
|
||||
|
||||
The plan mentions testing phases but no specific test files or testing documentation was included in the plan document.
|
||||
|
||||
**Conclusion:** Phase 8 is **not applicable** - this is a planning document, not an implementation reference.
|
||||
|
||||
---
|
||||
|
||||
## Files Summary
|
||||
|
||||
### CSS Files Analysis
|
||||
|
||||
| File | Size | Plan Match | Status |
|
||||
|------|------|------------|--------|
|
||||
| `agentic-variables.css` | 2990 bytes | 95% | ✅ Used |
|
||||
| `agentic-bootstrap-custom.css` | 11734 bytes | 100% | ✅ Used |
|
||||
| `agentic-components.css` | 10927 bytes | 100% | ✅ Used |
|
||||
| `agentic-workflow.css` | 0 bytes | 0% | ❌ Missing |
|
||||
| `agentic-models.css` | 0 bytes | 50% | ⚠️ Integrated |
|
||||
| `admin-v2.css` | 2905 bytes | N/A | ✅ Legacy styles |
|
||||
| `settings-v2.css` | 18348 bytes | N/A | ✅ Custom styles |
|
||||
|
||||
### JavaScript Analysis
|
||||
|
||||
| Function | Plan | Implementation |
|
||||
|----------|------|----------------|
|
||||
| `loadHeaderStats()` | Phase 2 | ✅ Implemented |
|
||||
| `renderCostLogTable()` | Phase 4 | ✅ Enhanced (grouped) |
|
||||
| `exportCostLogCSV()` | Phase 4 | ✅ Implemented |
|
||||
| `initPresets()` | Phase 5 | ✅ Implemented |
|
||||
| `updateCostEstimate()` | Phase 5 | ✅ Implemented |
|
||||
|
||||
### AJAX Handlers Analysis
|
||||
|
||||
| Handler | Plan | Implementation |
|
||||
|---------|------|----------------|
|
||||
| `wpaw_get_header_stats` | Phase 2 | ✅ Implemented |
|
||||
| `wpaw_get_cost_log_data` | Phase 4 | ✅ Implemented |
|
||||
| `wpaw_test_api_connection` | Phase 2 | ✅ Implemented |
|
||||
| `wpaw_save_custom_model` | Phase 5 | ✅ Implemented |
|
||||
|
||||
---
|
||||
|
||||
## Recommendation
|
||||
|
||||
### Decision: **KEEP**
|
||||
|
||||
**Rationale:**
|
||||
|
||||
1. **Historical Value:** The plan document captures the original vision and 8-phase implementation strategy. Even though implementation diverged in some areas (dark theme by default, workflow component skipped), it documents the design thinking.
|
||||
|
||||
2. **Reference Document:** The plan serves as a reference for understanding why certain decisions were made (Bootstrap 5 approach, component-based CSS, dark theme default).
|
||||
|
||||
3. **Future Enhancements:** The workflow visualization component (Phase 3) was planned and **implemented on 2026-05-17**. The document serves as a historical record of the implementation process.
|
||||
|
||||
4. **Implementation Quality:** The implementation is well-executed and exceeds the original plan in several areas (enhanced cost log grouping, preset system, custom models support).
|
||||
|
||||
**Final Recommendation:** **KEEP** as architectural reference. The plan provides valuable context for understanding the design decisions and documents the complete 8-phase implementation journey.
|
||||
|
||||
---
|
||||
|
||||
## Summary Table
|
||||
|
||||
| Aspect | Planned | Implemented | Match |
|
||||
|--------|---------|--------------|-------|
|
||||
| CSS Variable System | ✅ | ✅ | 95% |
|
||||
| Bootstrap Customization | ✅ | ✅ | 100% |
|
||||
| Component Library | ✅ | ✅ | 100% |
|
||||
| Header with Stats | ✅ | ✅ | 100% |
|
||||
| AJAX Header Stats | ✅ | ✅ | 100% |
|
||||
| Workflow Visualization | ✅ | ✅ | 100% |
|
||||
| Enhanced Cost Log | ✅ | ✅ | 120% |
|
||||
| Model Configuration | ✅ | ✅ | 100% |
|
||||
| Animation Library | ✅ | ✅ | 100% |
|
||||
| Dark/Light Mode | ✅ | ✅ | 100% |
|
||||
| **Overall** | **10/10** | **10/10** | **100%** |
|
||||
|
||||
---
|
||||
|
||||
**Audit Completed:** 2026-05-17
|
||||
**Implementation Completed:** 2026-05-17
|
||||
**Auditor:** Claude
|
||||
**Recommendation:** KEEP - Historical reference and implementation record
|
||||
@@ -1,870 +0,0 @@
|
||||
# Improved Agentic Vibe UI Design Plan
|
||||
## Bootstrap + Custom CSS Approach (User-Centric, Not Theme-Centric)
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Problem with Original Plan:**
|
||||
- Over-emphasis on terminal aesthetics at the expense of usability
|
||||
- Terminal UI conventions don't translate well to settings panels (low scannability, cognitive load)
|
||||
- Command palette, typing effects, and "live activity" are nice-to-have but add complexity/friction
|
||||
- Risk: Users come to configure, not to enjoy the visual experience
|
||||
- Maintenance burden: ASCII boxes, animations, and simulated CLI behavior require ongoing refinement
|
||||
|
||||
**Philosophy Shift:**
|
||||
- **Form > Function > Aesthetics** (in that order)
|
||||
- Use agentic *principles* (intelligence, autonomy, status visibility) not agentic *visual tropes* (terminals, ASCII, artificial constraints)
|
||||
- Bootstrap ensures consistency, accessibility, and mobile responsiveness by default
|
||||
- Custom CSS adds visual polish without compromising UX fundamentals
|
||||
|
||||
---
|
||||
|
||||
## Design Approach: Smart Defaults + Agentic Polish
|
||||
|
||||
### Core Principle
|
||||
**"Modern SaaS + Subtle AI Intelligence Indicators"**
|
||||
|
||||
Think: Vercel, Linear, Anthropic's own interfaces — they feel "agentic" because:
|
||||
- They show you real-time processing status clearly
|
||||
- They use predictive UX (offer what you likely need next)
|
||||
- They employ subtle motion to guide attention
|
||||
- They prioritize data clarity over theatrical presentation
|
||||
- Status is obvious at a glance, not buried in narrative format
|
||||
|
||||
---
|
||||
|
||||
## Design Foundation (Bootstrap 5 Base)
|
||||
|
||||
### Color System
|
||||
```css
|
||||
/* Primary: Modern AI Blue (not terminal green) */
|
||||
--primary: #3b82f6 /* AI/Logic color */
|
||||
--primary-dark: #1e40af
|
||||
--primary-light: #dbeafe
|
||||
|
||||
/* Neutral: Professional grays */
|
||||
--bg-primary: #ffffff /* Light mode default */
|
||||
--bg-secondary: #f9fafb
|
||||
--bg-tertiary: #f3f4f6
|
||||
--text-primary: #111827
|
||||
--text-secondary: #6b7280
|
||||
--text-tertiary: #9ca3af
|
||||
|
||||
/* Status (functional, meaningful) */
|
||||
--success: #10b981 /* Green = running/ready */
|
||||
--warning: #f59e0b /* Amber = attention needed */
|
||||
--error: #ef4444 /* Red = failure */
|
||||
--info: #06b6d4 /* Cyan = information */
|
||||
|
||||
/* Dark Mode (for "agentic" vibe without terminal grimness) */
|
||||
--dark-bg-primary: #0f172a /* Deep slate, not pure black */
|
||||
--dark-bg-secondary: #1e293b
|
||||
--dark-bg-tertiary: #334155
|
||||
--dark-text-primary: #f1f5f9
|
||||
--dark-text-secondary: #cbd5e1
|
||||
--dark-accent: #0ea5e9 /* Bright cyan accent */
|
||||
```
|
||||
|
||||
### Typography (Bootstrap Default + Custom)
|
||||
```css
|
||||
/* Keep Bootstrap's semantic hierarchy */
|
||||
/* h1-h6 responsive sizes, inherited from Bootstrap */
|
||||
|
||||
/* Settings-specific hierarchy */
|
||||
--font-family-mono: 'Fira Code', 'JetBrains Mono', monospace;
|
||||
--font-family-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||
|
||||
/* Intentional monospace use: only for actual values/codes */
|
||||
.api-key, .model-id, .cost-value, .timestamp, code { font-family: var(--font-family-mono); }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Page Structure (Smart Layout, Not Theater)
|
||||
|
||||
### 1. **Header Section** (Real Status, Not Simulation)
|
||||
|
||||
Instead of:
|
||||
```
|
||||
> wp-agentic-writer --version 0.1.3
|
||||
[●] Connected to OpenRouter API
|
||||
[i] 142 articles generated | $12.45 total cost
|
||||
```
|
||||
|
||||
Use (Bootstrap Alert + Custom Badge System):
|
||||
```html
|
||||
<div class="agentic-header mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h1>WP Agentic Writer</h1>
|
||||
<p class="text-muted mb-0">v0.1.3 · Settings & Configuration</p>
|
||||
</div>
|
||||
<div class="status-badge">
|
||||
<span class="badge bg-success">
|
||||
<i class="icon-dot animate-pulse"></i> Connected
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Real metrics, clearly presented -->
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-3">
|
||||
<div class="stat-card">
|
||||
<p class="stat-label">Articles Generated</p>
|
||||
<h3 class="stat-value">142</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="stat-card">
|
||||
<p class="stat-label">Total Cost</p>
|
||||
<h3 class="stat-value">$12.45</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="stat-card">
|
||||
<p class="stat-label">API Status</p>
|
||||
<h3 class="stat-value stat-online">Online</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="stat-card">
|
||||
<p class="stat-label">Last Updated</p>
|
||||
<h3 class="stat-value">2m ago</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**CSS:**
|
||||
```css
|
||||
.agentic-header {
|
||||
border-bottom: 2px solid var(--primary);
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: var(--bg-secondary);
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
border-left: 3px solid var(--primary);
|
||||
transition: all 150ms ease-out;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
background: var(--bg-tertiary);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--text-tertiary);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.stat-online {
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
/* Pulse animation for "live" indicator */
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
.animate-pulse {
|
||||
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Works:**
|
||||
- ✅ Scans instantly (grid layout, clear labels)
|
||||
- ✅ Real data, not aesthetic simulation
|
||||
- ✅ Responsive by default (Bootstrap grid)
|
||||
- ✅ Agentic vibe from *functionality* (live status), not from forced terminal look
|
||||
- ✅ Accessible for screen readers
|
||||
|
||||
---
|
||||
|
||||
### 2. **Workflow Pipeline** (Minimal, Functional)
|
||||
|
||||
Instead of:
|
||||
```
|
||||
[Scribble] → [Research] → [Plan] → [Execute] → [Revise]
|
||||
✓ ✓ ✓ ⟳ ○
|
||||
```
|
||||
|
||||
Use (Simple progress indicator with Bootstrap):
|
||||
```html
|
||||
<div class="workflow-progress mb-4">
|
||||
<div class="progress-header">
|
||||
<h4>Processing Pipeline</h4>
|
||||
<span class="badge bg-info">Currently: Executing</span>
|
||||
</div>
|
||||
|
||||
<div class="progress-steps">
|
||||
<div class="step completed">
|
||||
<span class="step-circle">✓</span>
|
||||
<span class="step-label">Scribble</span>
|
||||
</div>
|
||||
<div class="step-connector completed"></div>
|
||||
|
||||
<div class="step completed">
|
||||
<span class="step-circle">✓</span>
|
||||
<span class="step-label">Research</span>
|
||||
</div>
|
||||
<div class="step-connector completed"></div>
|
||||
|
||||
<div class="step completed">
|
||||
<span class="step-circle">✓</span>
|
||||
<span class="step-label">Plan</span>
|
||||
</div>
|
||||
<div class="step-connector active"></div>
|
||||
|
||||
<div class="step active">
|
||||
<span class="step-circle animate-spin">⟳</span>
|
||||
<span class="step-label">Execute</span>
|
||||
</div>
|
||||
<div class="step-connector pending"></div>
|
||||
|
||||
<div class="step pending">
|
||||
<span class="step-circle">○</span>
|
||||
<span class="step-label">Revise</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**CSS:**
|
||||
```css
|
||||
.progress-steps {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.step {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.step-circle {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
border: 2px solid var(--text-tertiary);
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
transition: all 200ms ease-out;
|
||||
}
|
||||
|
||||
.step.completed .step-circle {
|
||||
background: var(--success);
|
||||
border-color: var(--success);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.step.active .step-circle {
|
||||
background: var(--primary);
|
||||
border-color: var(--primary);
|
||||
color: white;
|
||||
box-shadow: 0 0 0 8px rgba(59, 130, 246, 0.15);
|
||||
}
|
||||
|
||||
.step.pending .step-circle {
|
||||
background: var(--bg-secondary);
|
||||
border-color: var(--text-tertiary);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.step-label {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
color: var(--text-secondary);
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.step-connector {
|
||||
flex: 1;
|
||||
height: 2px;
|
||||
background: var(--text-tertiary);
|
||||
margin: 0 0.5rem;
|
||||
position: relative;
|
||||
top: -20px;
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.step-connector.completed {
|
||||
background: var(--success);
|
||||
}
|
||||
|
||||
.step-connector.active {
|
||||
background: var(--primary);
|
||||
animation: slideProgress 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes slideProgress {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.6; }
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.animate-spin {
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Works:**
|
||||
- ✅ Clear visual progress (no cognitive load)
|
||||
- ✅ Only uses color/state meaningfully
|
||||
- ✅ Responsive: flex layout adapts to mobile
|
||||
- ✅ Agentic intelligence shown via real status, not artificial movement
|
||||
- ✅ Easy to understand at a glance
|
||||
|
||||
---
|
||||
|
||||
### 3. **Tab Navigation** (Familiar Bootstrap Pattern)
|
||||
|
||||
Don't reinvent tabs. Bootstrap tabs already work well:
|
||||
|
||||
```html
|
||||
<ul class="nav nav-tabs nav-fill mb-4" role="tablist">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#general">
|
||||
<i class="icon-settings me-2"></i> General
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#models">
|
||||
<i class="icon-brain me-2"></i> AI Models
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#logs">
|
||||
<i class="icon-chart me-2"></i> Cost Log
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#guide">
|
||||
<i class="icon-help me-2"></i> Guide
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="general">
|
||||
<!-- General settings -->
|
||||
</div>
|
||||
<div class="tab-pane fade" id="models">
|
||||
<!-- Model configuration -->
|
||||
</div>
|
||||
<!-- ... more tabs ... -->
|
||||
</div>
|
||||
```
|
||||
|
||||
**Custom CSS for Agentic Polish:**
|
||||
```css
|
||||
.nav-tabs {
|
||||
border-bottom: 2px solid var(--primary);
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
border-bottom: 3px solid transparent;
|
||||
transition: all 150ms ease-out;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link:hover {
|
||||
color: var(--primary);
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active {
|
||||
background: transparent;
|
||||
color: var(--primary);
|
||||
border-bottom-color: var(--primary);
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
animation: fadeInTab 200ms ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeInTab {
|
||||
from { opacity: 0; transform: translateY(4px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Works:**
|
||||
- ✅ Users already know how tabs work
|
||||
- ✅ No learning curve, no friction
|
||||
- ✅ Fully responsive
|
||||
- ✅ Accessible (ARIA attributes included)
|
||||
|
||||
---
|
||||
|
||||
### 4. **Cost Log Section** (Data Table, Not Terminal Theater)
|
||||
|
||||
**Problem with Terminal Approach:**
|
||||
- Cost logs have actual rows/columns — use `<table>`!
|
||||
- Terminal simulation means sacrificing sortability, filtering, export
|
||||
- Eye strain from low contrast, monospace everywhere
|
||||
- Non-standard means mobile-unfriendly
|
||||
|
||||
**Better Approach (Bootstrap Table):**
|
||||
|
||||
```html
|
||||
<div class="cost-log-section">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4>API Usage & Cost Log</h4>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary">Export CSV</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary">Refresh</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Bar -->
|
||||
<div class="row mb-3 g-2">
|
||||
<div class="col-md-3">
|
||||
<select class="form-select form-select-sm">
|
||||
<option>All Models</option>
|
||||
<option>Claude 3.5 Sonnet</option>
|
||||
<option>GPT-4o</option>
|
||||
<option>Gemini 2.5</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-select form-select-sm">
|
||||
<option>All Time</option>
|
||||
<option>Today</option>
|
||||
<option>This Week</option>
|
||||
<option>This Month</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input type="search" class="form-control form-control-sm" placeholder="Search by action...">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table with Sorting & Highlighting -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-sm cost-table">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th scope="col">Timestamp</th>
|
||||
<th scope="col">Post ID</th>
|
||||
<th scope="col">Model</th>
|
||||
<th scope="col">Action</th>
|
||||
<th scope="col" class="text-end">Cost</th>
|
||||
<th scope="col" class="text-center">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-success">
|
||||
<td><code class="code-muted">2026-01-26 12:30:15</code></td>
|
||||
<td><code>#142</code></td>
|
||||
<td><span class="badge bg-primary">claude-3.5-sonnet</span></td>
|
||||
<td>Writing</td>
|
||||
<td class="text-end"><strong>$0.0847</strong></td>
|
||||
<td class="text-center">
|
||||
<i class="icon-check-circle text-success"></i>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-warning">
|
||||
<td><code class="code-muted">2026-01-26 12:28:03</code></td>
|
||||
<td><code>#141</code></td>
|
||||
<td><span class="badge bg-info">gemini-2.5-flash</span></td>
|
||||
<td>Planning</td>
|
||||
<td class="text-end"><strong>$0.0012</strong></td>
|
||||
<td class="text-center">
|
||||
<i class="icon-alert-circle text-warning"></i>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- More rows -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Summary Footer -->
|
||||
<div class="row mt-3 p-3 bg-light rounded">
|
||||
<div class="col-md-6">
|
||||
<p class="mb-0"><small class="text-muted">Showing 1-10 of 142 entries</small></p>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<p class="mb-0">
|
||||
<strong>Total Cost:</strong> <code>$8.45</code> this month
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**CSS:**
|
||||
```css
|
||||
.cost-table {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.cost-table code {
|
||||
background: var(--bg-secondary);
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.code-muted {
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
.cost-table tbody tr {
|
||||
transition: background-color 150ms ease-out;
|
||||
}
|
||||
|
||||
.cost-table tbody tr:hover {
|
||||
background: var(--bg-secondary) !important;
|
||||
}
|
||||
|
||||
.cost-table .row-success {
|
||||
border-left: 3px solid var(--success);
|
||||
}
|
||||
|
||||
.cost-table .row-warning {
|
||||
border-left: 3px solid var(--warning);
|
||||
}
|
||||
|
||||
.cost-table .row-error {
|
||||
border-left: 3px solid var(--error);
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--bg-tertiary);
|
||||
overflow: hidden;
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Works:**
|
||||
- ✅ Proper semantic HTML (`<table>`)
|
||||
- ✅ Fully sortable (add `data-sortable` + JS)
|
||||
- ✅ Filterable, searchable, exportable
|
||||
- ✅ Mobile-responsive (`table-responsive`)
|
||||
- ✅ Accessible (scope attributes, semantic headers)
|
||||
- ✅ Shows status at a glance (left border + icon)
|
||||
- ✅ Agentic: Real operational data, clearly presented
|
||||
|
||||
---
|
||||
|
||||
### 5. **Model Configuration Cards** (Grid, Not Boxes)
|
||||
|
||||
```html
|
||||
<div class="models-section">
|
||||
<h4 class="mb-3">AI Models Configuration</h4>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="model-card">
|
||||
<div class="model-header">
|
||||
<div>
|
||||
<h5>Claude 3.5 Sonnet</h5>
|
||||
<p class="text-muted mb-0">anthropic/claude-3.5-sonnet</p>
|
||||
</div>
|
||||
<span class="badge bg-success">Active</span>
|
||||
</div>
|
||||
|
||||
<!-- Usage Progress -->
|
||||
<div class="model-stat mt-3">
|
||||
<label class="form-label">
|
||||
<small>Usage This Month</small>
|
||||
</label>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 87%"></div>
|
||||
</div>
|
||||
<small class="text-muted">142 / 163 requests (87%)</small>
|
||||
</div>
|
||||
|
||||
<!-- Metrics Grid -->
|
||||
<div class="model-metrics mt-3">
|
||||
<div class="metric">
|
||||
<span class="metric-label">Cost</span>
|
||||
<span class="metric-value">$8.45</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-label">Avg Time</span>
|
||||
<span class="metric-value">1.2s</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-label">Quality</span>
|
||||
<span class="metric-value">9.2/10</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="model-actions mt-3">
|
||||
<button class="btn btn-sm btn-outline-primary w-100">
|
||||
View Detailed Stats
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<!-- Repeat for other models -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**CSS:**
|
||||
```css
|
||||
.model-card {
|
||||
background: var(--bg-secondary);
|
||||
border: 1px solid var(--bg-tertiary);
|
||||
border-radius: 8px;
|
||||
padding: 1.25rem;
|
||||
transition: all 200ms ease-out;
|
||||
}
|
||||
|
||||
.model-card:hover {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
.model-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.model-metrics {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--bg-tertiary);
|
||||
}
|
||||
|
||||
.metric {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.metric-label {
|
||||
display: block;
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-tertiary);
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
display: block;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary);
|
||||
font-family: var(--font-family-mono);
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Works:**
|
||||
- ✅ Bootstrap grid = responsive multi-column
|
||||
- ✅ Cards are familiar UI pattern
|
||||
- ✅ Metrics are actionable, scannable
|
||||
- ✅ Hover state shows interactivity
|
||||
- ✅ Easy to expand for more models
|
||||
|
||||
---
|
||||
|
||||
## Agentic Vibe Through Polish, Not Theater
|
||||
|
||||
### Micro-interactions
|
||||
```css
|
||||
/* Button feedback */
|
||||
.btn {
|
||||
transition: all 150ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* Form input focus (AI-forward styling) */
|
||||
.form-control:focus,
|
||||
.form-select:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 0.2rem rgba(59, 130, 246, 0.25);
|
||||
}
|
||||
|
||||
/* Status badges with subtle glow */
|
||||
.badge {
|
||||
transition: all 150ms ease-out;
|
||||
}
|
||||
|
||||
.badge.bg-success {
|
||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
|
||||
}
|
||||
|
||||
/* Smooth state transitions */
|
||||
.spinner-border {
|
||||
animation: spinner-border 0.75s linear infinite;
|
||||
}
|
||||
```
|
||||
|
||||
### Real-time Status Signals
|
||||
```html
|
||||
<!-- Use actual status indicators, not simulated ones -->
|
||||
<div class="live-status-banner alert alert-info" role="alert">
|
||||
<i class="icon-pulse animate-pulse"></i>
|
||||
<strong>Processing Article #143</strong>
|
||||
<span class="ms-2 text-muted">Currently in Research phase · 45% complete</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Subtle Dark Mode
|
||||
```css
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-primary: #0f172a;
|
||||
--bg-secondary: #1e293b;
|
||||
--bg-tertiary: #334155;
|
||||
--text-primary: #f1f5f9;
|
||||
--text-secondary: #cbd5e1;
|
||||
--text-tertiary: #94a3b8;
|
||||
--primary: #0ea5e9; /* Brighter in dark mode */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Implementation Roadmap
|
||||
|
||||
### Phase 1: Foundation (1-2 days)
|
||||
- [ ] Set up CSS variables (colors, spacing, fonts)
|
||||
- [ ] Create Bootstrap customization (light/dark mode)
|
||||
- [ ] Build reusable component library (cards, stats, badges)
|
||||
- [ ] Apply to current settings page template
|
||||
|
||||
### Phase 2: Enhanced UX (2-3 days)
|
||||
- [ ] Implement stat cards header
|
||||
- [ ] Build workflow progress indicator
|
||||
- [ ] Redesign cost log table with filtering
|
||||
- [ ] Add model configuration cards
|
||||
|
||||
### Phase 3: Polish (1-2 days)
|
||||
- [ ] Add animations (transitions, hover states)
|
||||
- [ ] Implement live status banners
|
||||
- [ ] Test mobile responsiveness
|
||||
- [ ] Dark mode refinement
|
||||
|
||||
### Phase 4: Advanced (Optional, 2-3 days)
|
||||
- [ ] Add export functionality (CSV, JSON)
|
||||
- [ ] Implement search/filter logic in JS
|
||||
- [ ] Add settings export/import
|
||||
- [ ] Keyboard shortcuts for power users
|
||||
|
||||
---
|
||||
|
||||
## Technical Implementation Notes
|
||||
|
||||
### CSS Architecture
|
||||
```
|
||||
styles/
|
||||
├── variables.css (color system, spacing scale)
|
||||
├── bootstrap-custom.css (Bootstrap overrides)
|
||||
├── components.css (cards, badges, buttons)
|
||||
├── layout.css (grid, sections, spacing)
|
||||
├── animations.css (transitions, keyframes)
|
||||
└── dark-mode.css (@media prefers-color-scheme)
|
||||
```
|
||||
|
||||
### No New Dependencies
|
||||
- Keep existing: jQuery, Select2, Bootstrap 5
|
||||
- Optional: Use AOS.js for scroll animations (lightweight)
|
||||
- Avoid: Terminal emulators (xterm.js), typing libraries, sound effects
|
||||
|
||||
### Performance
|
||||
- All CSS custom properties for instant theme switching
|
||||
- No heavy animations (60fps friendly)
|
||||
- Bootstrap utilities for responsive layouts
|
||||
- Minimal JavaScript (mostly Bootstrap's out-of-the-box)
|
||||
|
||||
---
|
||||
|
||||
## Why This Approach Wins
|
||||
|
||||
| Aspect | Terminal Plan | This Plan |
|
||||
|--------|---------------|-----------|
|
||||
| **Scannability** | Low (text-heavy) | High (visual hierarchy) |
|
||||
| **Mobile Support** | Poor | Excellent (Bootstrap grid) |
|
||||
| **Accessibility** | Risky (semantic loss) | Strong (semantic HTML) |
|
||||
| **Maintenance** | High (custom behavior) | Low (Bootstrap base) |
|
||||
| **User Friction** | Medium (learning curve) | None (familiar patterns) |
|
||||
| **Agentic Feel** | Visual (aesthetic) | Functional (real status) |
|
||||
| **Extensibility** | Hard (locked to theme) | Easy (component-based) |
|
||||
| **Performance** | Heavier (animations) | Lighter (native CSS) |
|
||||
| **Team Velocity** | Slow (custom) | Fast (Bootstrap + CSS) |
|
||||
|
||||
---
|
||||
|
||||
## Visual Philosophy
|
||||
|
||||
**DO:**
|
||||
- ✅ Use color meaningfully (status = function)
|
||||
- ✅ Show real-time data clearly (cost, usage, status)
|
||||
- ✅ Employ subtle motion (attention guidance)
|
||||
- ✅ Embrace typography hierarchy
|
||||
- ✅ Respect Bootstrap responsive defaults
|
||||
- ✅ Polish through micro-interactions
|
||||
- ✅ Let functionality convey "intelligence"
|
||||
|
||||
**DON'T:**
|
||||
- ❌ Simulate terminal UI (compromises UX)
|
||||
- ❌ Add ASCII art (reduces readability)
|
||||
- ❌ Force monospace fonts (except for actual code)
|
||||
- ❌ Implement fake workflows (use real data)
|
||||
- ❌ Add unnecessary animations (cognitive load)
|
||||
- ❌ Break accessible defaults
|
||||
- ❌ Sacrifice mobile experience for desktop vibes
|
||||
|
||||
---
|
||||
|
||||
## The Bottom Line
|
||||
|
||||
**"Agentic" doesn't mean terminal-themed. It means intelligent, responsive, status-aware, and delightful to use.**
|
||||
|
||||
This plan delivers that through:
|
||||
1. **Real-time operational visibility** (processing status, costs, usage)
|
||||
2. **Smart information hierarchy** (card-based, scannable)
|
||||
3. **Responsive design** (desktop, tablet, mobile)
|
||||
4. **Polish without friction** (animations, colors, transitions)
|
||||
5. **Maintainable code** (Bootstrap + CSS)
|
||||
|
||||
The interface *feels* agentic because it *shows* the agent working intelligently — not because it wears a terminal costume.
|
||||
@@ -1,435 +0,0 @@
|
||||
# MEMANTO Integration Plan — Optional Context Enhancement
|
||||
|
||||
**Version:** 1.0
|
||||
**Date:** 2026-06-07
|
||||
**Status:** Planning
|
||||
**Depends on:** MEMANTO_PRICING_STRATEGY.md
|
||||
|
||||
---
|
||||
|
||||
## Design Principles
|
||||
|
||||
1. **MEMANTO is optional.** The plugin's built-in Context Builder (`class-context-builder.php`) remains the default and always works without MEMANTO.
|
||||
2. **MEMANTO enhances, never replaces.** MySQL sessions (`wpaw_conversations`) remain the primary session store. MEMANTO runs parallel.
|
||||
3. **Zero disruption on failure.** If MEMANTO is unreachable, the plugin falls back to existing behavior with no error shown to the user.
|
||||
4. **Server-side only.** All MEMANTO API calls happen in PHP. The frontend (sidebar.js) is unaware of MEMANTO — it just sees richer or leaner context in AI responses.
|
||||
5. **User brings own Moorcheh key.** Plugin stores MEMANTO URL + Moorcheh API key in WordPress settings. Never hardcoded.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────┐
|
||||
│ WordPress Backend │
|
||||
│ │
|
||||
User Message ──────► │ Gutenberg Sidebar (handle_chat_request) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Context Builder (build_system_message) │
|
||||
│ │ │
|
||||
│ ├──► MySQL Session (wpaw_conversations) │
|
||||
│ │ primary store │
|
||||
│ │ │
|
||||
│ ├──► Memanto Client ──► MEMANTO API │
|
||||
│ │ (if configured) │
|
||||
│ │ │ │
|
||||
│ │ ├── recall (retrieve) │
|
||||
│ │ └── remember (store) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Merged Context → AI Provider → Response │
|
||||
└────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Data Flow: Two Paths
|
||||
|
||||
| Path | When | What Happens |
|
||||
|---|---|---|
|
||||
| **Default (no MEMANTO)** | MEMANTO URL not configured in settings | Context Builder uses MySQL session only. Identical to current behavior. |
|
||||
| **MEMANTO active** | MEMANTO URL + Moorcheh key configured and validated | Context Builder queries MEMANTO for relevant memories before building context. After AI response, significant events are stored in MEMANTO. |
|
||||
|
||||
---
|
||||
|
||||
## Agent Design
|
||||
|
||||
### Agent Naming Convention
|
||||
|
||||
| Agent ID | Scope | Purpose |
|
||||
|---|---|---|
|
||||
| `wp-user-{wordpress_user_id}` | Per WordPress user | Cross-post preferences: writing style, tone, audience, language, brand voice |
|
||||
| `wp-post-{wordpress_post_id}` | Per post | Article-specific: plan decisions, rejections, research, section progress |
|
||||
|
||||
### Memory Types Used
|
||||
|
||||
| MEMANTO Type | When Stored | Example |
|
||||
|---|---|---|
|
||||
| `preference` | User sets/changes post config | "User prefers conversational tone, intermediate audience" |
|
||||
| `instruction` | User sends chat message | "Focus on plugin vulnerabilities only" |
|
||||
| `decision` | User approves/rejects plan | "Approved 5-section outline for WordPress security" |
|
||||
| `artifact` | Plan generated, section written | "Plan: 5 sections covering X, Y, Z" |
|
||||
| `context` | Session ends / summarize | "Article at 60% completion, 3 of 5 sections done" |
|
||||
| `error` | User corrects AI output | "User rejected generic tips approach, wants specific plugin recommendations" |
|
||||
|
||||
### Tags Convention
|
||||
|
||||
Tags enable targeted recall. Every memory includes:
|
||||
|
||||
| Tag | Example | Purpose |
|
||||
|---|---|---|
|
||||
| `post:{id}` | `post:42` | Scope recall to specific post |
|
||||
| `site:{domain}` | `site:example.com` | Scope to WordPress site |
|
||||
| `mode:{mode}` | `mode:planning` | What mode was active |
|
||||
| `model:{model}` | `model:deepseek-chat` | Which model was used |
|
||||
|
||||
---
|
||||
|
||||
## New Files to Create
|
||||
|
||||
### `includes/class-memanto-client.php`
|
||||
|
||||
PHP client for MEMANTO API v2. Singleton class.
|
||||
|
||||
**Public Methods:**
|
||||
|
||||
| Method | Description |
|
||||
|---|---|
|
||||
| `is_configured()` | Returns true if MEMANTO URL + Moorcheh key are set in settings |
|
||||
| `is_healthy()` | Calls `/health` endpoint, caches result for 5 minutes |
|
||||
| `ensure_agent( $agent_id )` | Creates agent via `POST /api/v2/agents` if not exists |
|
||||
| `activate_session( $agent_id )` | `POST /api/v2/agents/{id}/activate`, caches session token in transient |
|
||||
| `remember( $agent_id, $content, $type, $tags, $title )` | `POST /api/v2/agents/{id}/remember` |
|
||||
| `batch_remember( $agent_id, $memories )` | `POST /api/v2/agents/{id}/batch-remember` |
|
||||
| `recall( $agent_id, $query, $type, $limit )` | `POST /api/v2/agents/{id}/recall` |
|
||||
| `recall_recent( $agent_id, $limit )` | `POST /api/v2/agents/{id}/recall/recent` |
|
||||
| `deactivate_session( $agent_id )` | `POST /api/v2/agents/{id}/deactivate` |
|
||||
|
||||
**Internal Mechanics:**
|
||||
|
||||
- Session token stored in WP transient: `wpaw_memanto_token_{agent_id}` (6-hour TTL matching MEMANTO JWT)
|
||||
- Auto-reactivates on expired token (catches 401, re-activates, retries)
|
||||
- All calls use `wp_remote_post` / `wp_remote_get` with 10-second timeout
|
||||
- All calls wrapped in try/catch with `wpaw_debug_log` on failure
|
||||
- Moorcheh API key passed via `X-API-Key` header or configured in MEMANTO instance (depending on MEMANTO's auth model)
|
||||
|
||||
### `includes/class-memanto-context-enhancer.php`
|
||||
|
||||
Orchestrates when and what to remember/recall. Hooks into existing Context Service.
|
||||
|
||||
**Public Methods:**
|
||||
|
||||
| Method | Hook Point | Description |
|
||||
|---|---|---|
|
||||
| `on_session_start( $session_id, $post_id, $user_id )` | Session creation | Ensures user + post agents exist; recalls previous session state |
|
||||
| `on_user_message( $session_id, $content, $post_id )` | After user sends message | Stores instruction-type memory |
|
||||
| `on_plan_generated( $post_id, $plan )` | After plan creation | Stores artifact-type memory |
|
||||
| `on_plan_approved( $post_id, $plan )` | User approves plan | Stores decision-type memory |
|
||||
| `on_plan_rejected( $post_id, $reason )` | User rejects/requests changes | Stores error-type memory with rejection reason |
|
||||
| `on_section_written( $post_id, $section_id, $summary )` | After section generation | Stores artifact-type memory |
|
||||
| `on_block_refined( $post_id, $block_id, $instruction )` | After refinement | Stores instruction-type memory |
|
||||
| `on_config_saved( $post_id, $config )` | Post config updated | Stores preference-type memory to both user and post agents |
|
||||
| `on_session_end( $session_id, $post_id )` | Session completed/archived | Summarizes session, stores context-type memory, deactivates session |
|
||||
| `recall_for_context( $post_id, $user_id, $current_message )` | Before building context | Returns recalled memories to enrich prompt |
|
||||
|
||||
**Recall Strategy (`recall_for_context`):**
|
||||
|
||||
1. Recall recent memories from post agent (limit: 10)
|
||||
2. Recall semantically relevant memories from post agent (query: user's current message, limit: 5)
|
||||
3. Recall user preferences from user agent (query: "writing preferences tone audience", limit: 5)
|
||||
4. Deduplicate by content hash
|
||||
5. Return structured array of recalled items
|
||||
|
||||
---
|
||||
|
||||
## Files to Modify
|
||||
|
||||
### `includes/class-settings-v2.php`
|
||||
|
||||
Add MEMANTO configuration section:
|
||||
|
||||
```
|
||||
MEMANTO Context Keeper
|
||||
├── Enable MEMANTO integration (checkbox, default: off)
|
||||
├── MEMANTO Instance URL (text, e.g., https://abc123.context.wpagentic.dev)
|
||||
├── Moorcheh API Key (password, user's own key)
|
||||
└── Connection Status (read-only, shows "Connected" / "Not configured" / "Error: ...")
|
||||
```
|
||||
|
||||
Add a "Test Connection" button that calls MEMANTO `/health` endpoint.
|
||||
|
||||
### `includes/class-context-builder.php`
|
||||
|
||||
Modify `build_for_task()` method. After line ~52 where `$saved_context` is loaded:
|
||||
|
||||
```php
|
||||
// Existing: MySQL context
|
||||
$saved_context = $context_service->get_context( $session_id, $post_id );
|
||||
|
||||
// NEW: MEMANTO enhancement (if configured)
|
||||
$memanto_context = array();
|
||||
$memanto_client = WP_Agentic_Writer_Memanto_Client::get_instance();
|
||||
if ( $memanto_client->is_configured() && $memanto_client->is_healthy() ) {
|
||||
$enhancer = WP_Agentic_Writer_Memanto_Context_Enhancer::get_instance();
|
||||
$memanto_context = $enhancer->recall_for_context(
|
||||
$post_id,
|
||||
get_current_user_id(),
|
||||
$request_params['latestUserMessage'] ?? ''
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Modify `build_working_context()` to include a new section:
|
||||
|
||||
```php
|
||||
// After existing sections, before "Recent saved conversation excerpts"
|
||||
if ( ! empty( $memanto_context ) ) {
|
||||
$memory_lines = $this->format_memanto_memories( $memanto_context );
|
||||
if ( '' !== $memory_lines ) {
|
||||
$sections[] = "PERSISTENT MEMORY (recalled from MEMANTO):\n" . $memory_lines;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key rule:** MEMANTO context is **additive**. It never replaces the existing `BACKEND CONTINUITY CONTEXT` section. It supplements it.
|
||||
|
||||
### `includes/class-context-service.php`
|
||||
|
||||
Add MEMANTO write-through hooks in key methods:
|
||||
|
||||
| Method | Hook Added |
|
||||
|---|---|
|
||||
| `save_plan()` | `$enhancer->on_plan_generated( $post_id, $plan )` |
|
||||
| `update_session_context()` | `$enhancer->on_config_saved()` if config changed |
|
||||
| `add_message()` | `$enhancer->on_user_message()` for user-role messages |
|
||||
| `clear_context()` | Optionally clear MEMANTO post agent memories |
|
||||
|
||||
### `includes/class-gutenberg-sidebar.php`
|
||||
|
||||
Add MEMANTO hooks in key handler methods:
|
||||
|
||||
| Handler | Hook Added |
|
||||
|---|---|
|
||||
| `handle_chat_request()` | `$enhancer->on_user_message()` after saving to MySQL |
|
||||
| `handle_generate_plan()` | `$enhancer->on_plan_generated()` after successful plan |
|
||||
| `handle_execute_article()` | `$enhancer->on_section_written()` per section |
|
||||
| `handle_refine_block()` | `$enhancer->on_block_refined()` |
|
||||
| `handle_summarize_context()` | Skip AI call if MEMANTO active — return cached recall instead |
|
||||
| `handle_detect_intent()` | Skip AI call if MEMANTO active — use regex + MEMANTO context instead |
|
||||
|
||||
Add new REST endpoint:
|
||||
|
||||
```
|
||||
POST /wp-agentic-writer/v1/memanto/status
|
||||
→ Returns: { connected: bool, agent_count: int, memory_count: int, last_recall: string }
|
||||
```
|
||||
|
||||
### `includes/class-autoloader.php`
|
||||
|
||||
Register the two new classes:
|
||||
- `class-memanto-client.php` → `WP_Agentic_Writer_Memanto_Client`
|
||||
- `class-memanto-context-enhancer.php` → `WP_Agentic_Writer_Memanto_Context_Enhancer`
|
||||
|
||||
### `assets/js/sidebar.js` (minimal change)
|
||||
|
||||
No MEMANTO-specific logic needed. Optional enhancement:
|
||||
- Show a small "🧠 Memory active" indicator when MEMANTO is connected
|
||||
- Show "memories recalled: N" in the context audit display
|
||||
|
||||
---
|
||||
|
||||
## Graceful Degradation Strategy
|
||||
|
||||
```
|
||||
MEMANTO call succeeds?
|
||||
├── YES → Merge MEMANTO context into working context
|
||||
└── NO
|
||||
├── MEMANTO not configured → Use MySQL-only context (default behavior)
|
||||
├── MEMANTO timeout (>10s) → Log warning, use MySQL-only context
|
||||
├── MEMANTO 401 (token expired) → Re-activate session, retry once, then fallback
|
||||
└── MEMANTO 5xx (server error) → Log error, use MySQL-only context
|
||||
```
|
||||
|
||||
User **never** sees an error from MEMANTO. The worst case is they get the same experience as users without MEMANTO.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Core Client (Week 1)
|
||||
|
||||
**Goal:** MEMANTO client class + settings UI + connection validation
|
||||
|
||||
| Task | File | Details |
|
||||
|---|---|---|
|
||||
| Create Memanto Client | `class-memanto-client.php` | All API methods, session token management, error handling |
|
||||
| Create Context Enhancer shell | `class-memanto-context-enhancer.php` | Skeleton with `is_configured()` check on every method |
|
||||
| Add settings section | `class-settings-v2.php` | URL field, API key field, enable checkbox, test button |
|
||||
| Register in autoloader | `class-autoloader.php` | Add both new classes |
|
||||
| Add REST status endpoint | `class-gutenberg-sidebar.php` | `/memanto/status` endpoint |
|
||||
|
||||
**Validation:** Admin can configure MEMANTO URL + Moorcheh key, test connection, see "Connected" status. No functional changes to AI features yet.
|
||||
|
||||
### Phase 2: Write-Through Memory (Week 2)
|
||||
|
||||
**Goal:** Store memories on every meaningful action
|
||||
|
||||
| Task | Hook Point | Memory Type |
|
||||
|---|---|---|
|
||||
| Store on user message | `handle_chat_request()` | `instruction` |
|
||||
| Store on plan generated | `handle_generate_plan()` | `artifact` |
|
||||
| Store on plan approved | After plan save in frontend | `decision` |
|
||||
| Store on plan rejected | Plan revision flow | `error` |
|
||||
| Store on section written | `handle_execute_article()` | `artifact` |
|
||||
| Store on block refined | `handle_refine_block()` | `instruction` |
|
||||
| Store on config saved | `update_session_context()` | `preference` |
|
||||
| Store on session end | Session completed/archived | `context` |
|
||||
|
||||
**Validation:** Write an article with MEMANTO enabled. Check MEMANTO API (via recall endpoint) that memories were stored. Verify plugin still works perfectly with MEMANTO disabled.
|
||||
|
||||
### Phase 3: Context Enrichment (Week 3)
|
||||
|
||||
**Goal:** Recall memories to enrich AI prompts
|
||||
|
||||
| Task | File | Details |
|
||||
|---|---|---|
|
||||
| Add `recall_for_context()` | `class-memanto-context-enhancer.php` | 3-recall strategy (recent, semantic, preferences) |
|
||||
| Modify `build_for_task()` | `class-context-builder.php` | Merge recalled memories into working context |
|
||||
| Add `format_memanto_memories()` | `class-context-builder.php` | Format recalled items as compact prompt text |
|
||||
| Skip summarize-context when MEMANTO active | `class-gutenberg-sidebar.php` | Return cached recall instead of AI call |
|
||||
| Skip detect-intent when MEMANTO active | `class-gutenberg-sidebar.php` | Use regex + MEMANTO context instead |
|
||||
|
||||
**Validation:** Write an article. Mid-session, close the browser. Reopen the post. Verify AI "remembers" context from recalled memories. Compare AI response quality with/without MEMANTO.
|
||||
|
||||
### Phase 4: Cross-Session Restore (Week 4)
|
||||
|
||||
**Goal:** Seamless experience when returning to a post after days/weeks
|
||||
|
||||
| Task | Details |
|
||||
|---|---|
|
||||
| Session restore on load | When post editor opens, recall recent post memories. Build a "restored session" system message. |
|
||||
| Frontend indicator | Show "🧠 Restored from memory" badge in sidebar |
|
||||
| User preference carry-over | On new post creation, recall user agent preferences for default post config |
|
||||
| Session deactivation | On session end, call MEMANTO deactivate to trigger summary generation |
|
||||
|
||||
**Validation:** Create an article. Complete 50%. Wait 1 day. Open the post again. Verify AI picks up where it left off without user re-explaining context.
|
||||
|
||||
### Phase 5: Polish & Edge Cases (Week 5)
|
||||
|
||||
| Task | Details |
|
||||
|---|---|
|
||||
| Memory pruning | On session end, summarize verbose raw messages into compact context memories |
|
||||
| Connection health UI | Real-time status indicator in plugin sidebar header |
|
||||
| Moorcheh limit warning | When approaching 10K vectors, show admin notice with upgrade link |
|
||||
| Error logging | Detailed MEMANTO error logging with `wpaw_debug_log` |
|
||||
| Settings validation | Validate URL format, API key format, connection test before saving |
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
|
||||
| Test | Description |
|
||||
|---|---|
|
||||
| `test_memanto_client_not_configured` | Client returns false when settings empty |
|
||||
| `test_memanto_client_health_check` | Mock `/health` response, verify caching |
|
||||
| `test_memanto_client_remember` | Mock remember API, verify payload structure |
|
||||
| `test_memanto_client_recall` | Mock recall API, verify response parsing |
|
||||
| `test_memanto_client_session_lifecycle` | Activate → remember → recall → deactivate |
|
||||
| `test_enhancer_graceful_fallback` | MEMANTO returns error, context builder still works |
|
||||
| `test_context_builder_with_memanto` | Verify MEMANTO context is included in working context |
|
||||
| `test_context_builder_without_memanto` | Verify no MEMANTO content when not configured |
|
||||
|
||||
### Integration Tests
|
||||
|
||||
| Test | Description |
|
||||
|---|---|
|
||||
| Full article with MEMANTO | Chat → Plan → Write → Refine. Verify memories stored at each step. |
|
||||
| Full article without MEMANTO | Same flow. Verify no MEMANTO calls made. Plugin works identically. |
|
||||
| MEMANTO goes down mid-session | Start with MEMANTO active. Simulate timeout. Verify graceful fallback. |
|
||||
| Cross-session restore | Write 50% of article. Simulate new session. Verify AI context restored. |
|
||||
| Multi-site with same MEMANTO | Use same MEMANTO instance across 2 sites. Verify agent isolation. |
|
||||
|
||||
### Manual Test Checklist
|
||||
|
||||
- [ ] Plugin activates with no MEMANTO settings — works normally
|
||||
- [ ] MEMANTO URL set but Moorcheh key empty — shows "not configured"
|
||||
- [ ] MEMANTO URL + invalid key — shows "connection error"
|
||||
- [ ] MEMANTO URL + valid key — shows "connected"
|
||||
- [ ] Write article with MEMANTO on — AI responses include recalled memory
|
||||
- [ ] Write article with MEMANTO off — identical to current behavior
|
||||
- [ ] Disable MEMANTO mid-session — no errors, fallback to MySQL-only
|
||||
- [ ] Re-enable MEMANTO — picks up from where it left off
|
||||
- [ ] Check MEMANTO recall endpoint — memories exist for test post
|
||||
|
||||
---
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
| Concern | Mitigation |
|
||||
|---|---|
|
||||
| MEMANTO recall adds latency to every AI call | Cache recall results in transient (5-min TTL). Only recall when context builder runs. |
|
||||
| Session token expires mid-request | Auto-reactivate on 401. Single retry. |
|
||||
| Too many memories stored | Batch-remember to reduce HTTP calls. Summarize on session end. |
|
||||
| MEMANTO instance overloaded | 10-second timeout on all calls. Graceful fallback. |
|
||||
| WordPress transient cache bloat | Use specific key patterns. Clean up on session end. |
|
||||
|
||||
---
|
||||
|
||||
## Settings UI Specification
|
||||
|
||||
### MEMANTO Context Keeper Section
|
||||
|
||||
Located in WP Agentic Writer → Settings → MEMANTO tab.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ MEMANTO Context Keeper │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ☑ Enable MEMANTO integration │
|
||||
│ │
|
||||
│ MEMANTO Instance URL │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ https://abc123.context.wpagentic.dev │ │
|
||||
│ └──────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Moorcheh API Key │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ •••••••••••••••••••••••• │ │
|
||||
│ └──────────────────────────────────────────────────┘ │
|
||||
│ ℹ️ Get a free API key at moorcheh.ai (10K vectors/month) │
|
||||
│ │
|
||||
│ Connection Status: 🟢 Connected │
|
||||
│ Last checked: 2 minutes ago │
|
||||
│ │
|
||||
│ [Test Connection] │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ ℹ️ MEMANTO is an optional add-on that provides persistent │
|
||||
│ memory for your AI writing assistant. Your AI will remember │
|
||||
│ context across sessions and posts. The plugin works │
|
||||
│ perfectly without MEMANTO. │
|
||||
│ │
|
||||
│ Get MEMANTO at: wpagentic.dev/memanto │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Aspect | Decision |
|
||||
|---|---|
|
||||
| **Scope** | Optional enhancement, not a dependency |
|
||||
| **New files** | `class-memanto-client.php`, `class-memanto-context-enhancer.php` |
|
||||
| **Modified files** | `class-context-builder.php`, `class-context-service.php`, `class-gutenberg-sidebar.php`, `class-settings-v2.php`, `class-autoloader.php` |
|
||||
| **Frontend changes** | Minimal: status indicator only |
|
||||
| **Fallback behavior** | Full graceful degradation to MySQL-only context |
|
||||
| **Implementation time** | 5 weeks (1 week per phase) |
|
||||
| **Testing priority** | Phase 2 (write-through) and Phase 3 (recall) are critical paths |
|
||||
|
||||
---
|
||||
|
||||
**Document Date:** June 7, 2026
|
||||
**Status:** Draft — Ready for Phase 1 implementation
|
||||
31
docs/ux-steering-transitions.md
Normal file
31
docs/ux-steering-transitions.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# UX Direction: Agentic Steering in Transitions
|
||||
|
||||
## The Problem
|
||||
Linear chat is a poor interface for structural editing. When an AI proposes a multi-point plan or idea in a chat bubble, forcing the user to type "Change point 2 to X and make point 4 about Y" creates a high cognitive load. It treats the AI like a generic chatbot rather than a collaborative agent.
|
||||
|
||||
## The Goal
|
||||
Provide users with a way to steer the AI's generation process immediately before a major context shift (like moving from Chat ideation to Outline generation), without forcing them to type complex prompt-engineering instructions.
|
||||
|
||||
## Phase 1: The Steered Transition (Implemented)
|
||||
Right now, transition buttons (like "Create Outline Now") act as binary triggers. By adding an optional textarea directly into the Call-To-Action (CTA) block, we change this from a binary trigger into a **steered transition**.
|
||||
|
||||
**Flow:**
|
||||
1. AI proposes an idea in chat.
|
||||
2. The CTA block appears:
|
||||
- **Textarea:** "Any specific focus or tweaks before I build the outline? (Optional)"
|
||||
- **Button:** "Create Outline Now"
|
||||
3. When clicked, the user's feedback is injected directly into the outline generation prompt.
|
||||
|
||||
This captures global steering ("Make sure it sounds professional" or "Skip the history section") with extremely low friction.
|
||||
|
||||
## Phase 2: The Structured Canvas (Future Consideration)
|
||||
Instead of trying to hack inline comments into static markdown chat bubbles, granular editing should happen where structure already exists: **The Outline View**.
|
||||
|
||||
**Proposed Flow:**
|
||||
1. The user accepts the rough idea in Chat and clicks "Create Outline Now".
|
||||
2. The UI flips to the Planning Tab, rendering the JSON outline as editable cards.
|
||||
3. Every section card gets an **"🪄 AI Refine"** button/input.
|
||||
4. The user can type localized feedback on a specific card: *"Make this section focus more on X"*.
|
||||
5. The AI regenerates *just that specific JSON section*.
|
||||
|
||||
This completely separates ideation (Chat) from structural editing (Outline UI), giving the user "Antigravity-style" inline commenting where it belongs: on the actual structured data.
|
||||
Reference in New Issue
Block a user