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.
10 KiB
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():
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
/**
* 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)
// 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
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():
$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:
const tabButtons = document.querySelectorAll('.wpaw-tab-button');
// Add your tab button
2. Add tab content
<div id="my-tab" class="wpaw-tab-content" style="display: none;">
<!-- Your tab content -->
</div>
3. Add tab switching logic
function showTab(tabId) {
// Handle your tab
}
CSS Token System
The plugin uses a three-namespace CSS token system:
Scope Tokens (lowest priority)
.wpaw-sidebar-container {
--wpaw-color-primary: #2271b1;
}
State Tokens
.wpaw-tab-button.active {
--wpaw-color-primary: #135e96;
}
Intent Tokens (highest priority)
.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
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
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
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:
- Sidebar loads: Open a post in Gutenberg, verify sidebar appears
- Chat works: Send a message, verify response appears
- Settings save: Change settings, refresh, verify persistence
- Rate limiting: Rapid requests should return 429 after limit
Debug Mode
Enable debug logging in browser console:
window.wpAgenticWriter = { debug: true };
Database Queries
Use WP-CLI to inspect database:
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_orWP_Agentic_Writer_ - Document all public methods with docblocks
Security Checklist
- All post-scoped endpoints check
edit_postcapability - 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
# 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"