Add AI writing assistant plugin with local backend, brave search, and image generation support

- Implement local backend AI provider with Ollama integration
- Add Brave Search API integration for real-time search suggestions
- Add image generation manager with multiple AI providers
- Create hybrid provider system with local/cloud fallback
- Add comprehensive settings UI with provider management
- Implement Gutenberg sidebar with writing assistance controls
- Add SEO schema generation for AI-generated content
- Multiple provider support: OpenRouter, local backend, Codex
This commit is contained in:
Dwindi Ramadhana
2026-05-17 10:48:05 +07:00
parent 97426d5ab1
commit d2c10756ab
61 changed files with 18725 additions and 806 deletions

View File

@@ -31,8 +31,8 @@ $available_languages = $settings_instance->get_available_languages();
<div class="row g-4">
<!-- API Configuration -->
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="card border-0 ">
<div class="card-header border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2"><i class="bi bi-key-fill text-warning"></i><?php esc_html_e( 'API Configuration', 'wp-agentic-writer' ); ?></h5>
@@ -71,11 +71,11 @@ $available_languages = $settings_instance->get_available_languages();
<!-- Budget & Cost Tracking -->
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="card border-0 ">
<div class="card-header border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2"><i class="bi bi-currency-dollar text-warning"></i><?php esc_html_e( 'Budget & Cost Tracking', 'wp-agentic-writer' ); ?></h5>
<h5 class="card-title mb-1 d-flex align-items-center gap-2"><i class="bi bi-currency-dollar text-warning"></i><?php esc_html_e( 'OpenRouter Budget & Cost Tracking', 'wp-agentic-writer' ); ?></h5>
<p class="text-muted small mb-0"><?php esc_html_e( 'Monitor and control your API spending', 'wp-agentic-writer' ); ?></p>
</div>
</div>
@@ -84,13 +84,13 @@ $available_languages = $settings_instance->get_available_languages();
<!-- Budget Overview -->
<div class="row mb-4">
<div class="col-md-4">
<div class="p-3 rounded bg-light text-center">
<div class="p-3 rounded border text-center">
<div class="fs-3 fw-bold text-primary">$<?php echo number_format( $monthly_used, 2 ); ?></div>
<div class="text-muted small"><?php esc_html_e( 'Used This Month', 'wp-agentic-writer' ); ?></div>
</div>
</div>
<div class="col-md-4">
<div class="p-3">
<div class="p-3 border">
<div class="d-flex justify-content-between mb-1">
<span class="small text-muted"><?php esc_html_e( 'Budget Usage', 'wp-agentic-writer' ); ?></span>
<span class="small fw-semibold"><?php echo number_format( $budget_percent, 1 ); ?>%</span>
@@ -104,7 +104,7 @@ $available_languages = $settings_instance->get_available_languages();
</div>
</div>
<div class="col-md-4">
<div class="p-3 rounded bg-light text-center">
<div class="p-3 rounded border text-center">
<div class="fs-3 fw-bold text-success">$<?php echo number_format( max( 0, $monthly_budget - $monthly_used ), 2 ); ?></div>
<div class="text-muted small"><?php esc_html_e( 'Remaining', 'wp-agentic-writer' ); ?></div>
</div>
@@ -122,7 +122,7 @@ $available_languages = $settings_instance->get_available_languages();
<div class="form-text"><?php esc_html_e( 'Maximum spend per month. Set to 0 for unlimited.', 'wp-agentic-writer' ); ?></div>
</div>
<div class="col-md-6">
<label class="form-label fw-semibold"><?php esc_html_e( 'Cost Tracking', 'wp-agentic-writer' ); ?></label>
<label class="form-label fw-semibold"><?php esc_html_e( 'OpenRouter Cost Tracking', 'wp-agentic-writer' ); ?></label>
<div class="form-check form-switch d-flex align-items-center gap-2">
<input class="form-check-input" type="checkbox" id="cost_tracking_enabled" name="wp_agentic_writer_settings[cost_tracking_enabled]" value="1" <?php checked( $cost_tracking_enabled ); ?> />
<label class="form-check-label" for="cost_tracking_enabled">
@@ -137,12 +137,12 @@ $available_languages = $settings_instance->get_available_languages();
<!-- Research & Web Search -->
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="card border-0 ">
<div class="card-header border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2"><i class="bi bi-search text-warning"></i><?php esc_html_e( 'Research & Web Search', 'wp-agentic-writer' ); ?></h5>
<p class="text-muted small mb-0"><?php esc_html_e( 'Configure web search for up-to-date content', 'wp-agentic-writer' ); ?></p>
<p class="text-muted small mb-0"><?php esc_html_e( 'When enabled, the plugin auto-selects the search method based on your active provider.', 'wp-agentic-writer' ); ?></p>
</div>
</div>
</div>
@@ -152,19 +152,10 @@ $available_languages = $settings_instance->get_available_languages();
<div class="form-check form-switch d-flex align-items-center gap-2">
<input class="form-check-input" type="checkbox" id="web_search_enabled" name="wp_agentic_writer_settings[web_search_enabled]" value="1" <?php checked( $web_search_enabled ); ?> />
<label class="form-check-label" for="web_search_enabled">
<?php esc_html_e( 'Enable Web Search', 'wp-agentic-writer' ); ?>
<span class="badge text-bg-warning ms-2">~$0.02 per search</span>
<?php esc_html_e( 'Enable Web Search (default for new posts)', 'wp-agentic-writer' ); ?>
</label>
</div>
<div class="form-text"><?php esc_html_e( 'Search the web for current information. Can be toggled per-request in sidebar.', 'wp-agentic-writer' ); ?></div>
</div>
<div class="col-md-6">
<label for="search_engine" class="form-label fw-semibold"><?php esc_html_e( 'Search Engine', 'wp-agentic-writer' ); ?></label>
<select class="form-select" id="search_engine" name="wp_agentic_writer_settings[search_engine]">
<option value="auto" <?php selected( $search_engine, 'auto' ); ?>><?php esc_html_e( 'Auto (Native if available, Exa fallback)', 'wp-agentic-writer' ); ?></option>
<option value="native" <?php selected( $search_engine, 'native' ); ?>><?php esc_html_e( 'Native (Provider\'s built-in search)', 'wp-agentic-writer' ); ?></option>
<option value="exa" <?php selected( $search_engine, 'exa' ); ?>><?php esc_html_e( 'Exa (Always use Exa search)', 'wp-agentic-writer' ); ?></option>
</select>
<div class="form-text"><?php esc_html_e( 'Can also be toggled per-request in the editor sidebar.', 'wp-agentic-writer' ); ?></div>
</div>
<div class="col-md-6">
<label for="search_depth" class="form-label fw-semibold"><?php esc_html_e( 'Search Depth', 'wp-agentic-writer' ); ?></label>
@@ -175,14 +166,49 @@ $available_languages = $settings_instance->get_available_languages();
</select>
</div>
</div>
<!-- Two-column: OpenRouter vs Brave -->
<div class="row g-3 mt-4 border-top pt-4 border-secondary border-opacity-25">
<!-- Left Column: OpenRouter Search -->
<div class="col-md-6">
<div class="p-3 border rounded" style="border-color: rgba(255,255,255,.1) !important">
<h6 class="fw-semibold mb-1 d-flex align-items-center gap-2">
<span class="badge text-bg-primary">OpenRouter</span>
<?php esc_html_e( 'Search Engine', 'wp-agentic-writer' ); ?>
</h6>
<p class="text-muted small mb-2"><?php esc_html_e( 'Used when the active model is routed through OpenRouter.', 'wp-agentic-writer' ); ?></p>
<select class="form-select" id="search_engine" name="wp_agentic_writer_settings[search_engine]">
<option value="auto" <?php selected( $search_engine, 'auto' ); ?>><?php esc_html_e( 'Auto (Native → Exa fallback)', 'wp-agentic-writer' ); ?></option>
<option value="native" <?php selected( $search_engine, 'native' ); ?>><?php esc_html_e( 'Native (Free, built-in)', 'wp-agentic-writer' ); ?></option>
<option value="exa" <?php selected( $search_engine, 'exa' ); ?>><?php esc_html_e( 'Exa (Paid, ~$0.02/search)', 'wp-agentic-writer' ); ?></option>
</select>
</div>
</div>
<!-- Right Column: Brave Search -->
<div class="col-md-6">
<div class="p-3 border rounded" style="border-color: rgba(255,255,255,.1) !important">
<h6 class="fw-semibold mb-1 d-flex align-items-center gap-2">
<span class="badge text-bg-success">Local / Codex</span>
<?php esc_html_e( 'Brave Search API', 'wp-agentic-writer' ); ?>
</h6>
<p class="text-muted small mb-2"><?php esc_html_e( 'Used automatically when the active model is Local Backend or Codex.', 'wp-agentic-writer' ); ?></p>
<input type="password" class="form-control" id="brave_search_api_key" name="wp_agentic_writer_settings[brave_search_api_key]" value="<?php echo esc_attr( $brave_search_api_key ); ?>" placeholder="BSA...">
<div class="form-text mt-2">
<?php printf( wp_kses_post( __( '<a href="%s" target="_blank" class="text-info text-decoration-none border-bottom border-info">Get free API Key</a> — 2,000 requests/month on the free tier.', 'wp-agentic-writer' ) ), 'https://brave.com/search/api/' ); ?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Clarification Quiz -->
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="card border-0 ">
<div class="card-header border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2"><i class="bi bi-question-circle text-warning"></i><?php esc_html_e( 'Clarification Quiz', 'wp-agentic-writer' ); ?></h5>
@@ -240,8 +266,8 @@ $available_languages = $settings_instance->get_available_languages();
<!-- Content Settings / Language -->
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="card border-0 ">
<div class="card-header border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2"><i class="bi bi-globe text-warning"></i><?php esc_html_e( 'Content Settings', 'wp-agentic-writer' ); ?></h5>
@@ -292,8 +318,8 @@ $available_languages = $settings_instance->get_available_languages();
<!-- Advanced Settings -->
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="card border-0 ">
<div class="card-header border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2"><i class="bi bi-gear text-warning"></i><?php esc_html_e( 'Advanced Settings', 'wp-agentic-writer' ); ?></h5>
@@ -303,6 +329,15 @@ $available_languages = $settings_instance->get_available_languages();
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-12">
<div class="form-check form-switch d-flex align-items-center gap-2">
<input class="form-check-input" type="checkbox" id="enable_faq_schema" name="wp_agentic_writer_settings[enable_faq_schema]" value="1" <?php checked( $enable_faq_schema ?? false ); ?> />
<label class="form-check-label" for="enable_faq_schema">
<?php esc_html_e( 'Enable Automated FAQ Schema (Optional)', 'wp-agentic-writer' ); ?>
</label>
</div>
<div class="form-text"><?php esc_html_e( 'Automatically injects FAQPage JSON-LD into posts when Q&A headings are detected. Compatible with Yoast SEO and RankMath. Disable if your SEO plugin already handles FAQ schema.', 'wp-agentic-writer' ); ?></div>
</div>
<div class="col-md-6">
<label for="chat_history_limit" class="form-label fw-semibold"><?php esc_html_e( 'Chat History Limit', 'wp-agentic-writer' ); ?></label>
<input type="number" class="form-control" id="chat_history_limit" name="wp_agentic_writer_settings[chat_history_limit]" value="<?php echo esc_attr( $chat_history_limit ); ?>" min="0" max="200" style="max-width: 120px;" />