# 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/)