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

@@ -17,7 +17,7 @@ if ( ! defined( 'ABSPATH' ) ) {
*
* @since 0.1.0
*/
class WP_Agentic_Writer_OpenRouter_Provider {
class WP_Agentic_Writer_OpenRouter_Provider implements WP_Agentic_Writer_AI_Provider_Interface {
/**
* API key.
@@ -598,51 +598,130 @@ class WP_Agentic_Writer_OpenRouter_Provider {
}
/**
* Generate image.
* Generate image using OpenRouter image generation API.
*
* @since 0.1.0
* @param string $prompt Image prompt.
* @return array|WP_Error Response array with image URL or WP_Error on failure.
* @param string $model Image model (optional, uses default if not provided).
* @param array $options Additional options (size, quality, n).
* @return array|WP_Error Response with image URL or error.
*/
public function generate_image( $prompt ) {
// Check API key.
public function generate_image( $prompt, $model = null, $options = array() ) {
if ( empty( $this->api_key ) ) {
return new WP_Error(
'no_api_key',
__( 'OpenRouter API key is not configured.', 'wp-agentic-writer' )
);
return new WP_Error( 'no_api_key', 'OpenRouter API key not configured' );
}
$messages = array(
$model = $model ?? $this->image_model;
$size = $options['size'] ?? '1024x576';
$quality = $options['quality'] ?? 'hd';
$n = $options['n'] ?? 1;
$start_time = microtime( true );
$response = wp_remote_post(
'https://openrouter.ai/api/v1/images/generations',
array(
'role' => 'user',
'content' => sprintf(
'Generate an image based on this prompt: %s. Return only the image URL.',
$prompt
'headers' => array(
'Authorization' => 'Bearer ' . $this->api_key,
'Content-Type' => 'application/json',
'HTTP-Referer' => home_url(),
'X-Title' => get_bloginfo( 'name' ),
),
),
'body' => wp_json_encode(
array(
'model' => $model,
'prompt' => $prompt,
'n' => $n,
'size' => $size,
'quality' => $quality,
)
),
'timeout' => 60,
)
);
$response = $this->chat( $messages, array( 'model' => $this->image_model ), 'image' );
$generation_time = microtime( true ) - $start_time;
if ( is_wp_error( $response ) ) {
return $response;
}
// Extract image URL from response.
$content = $response['content'];
$url = '';
$body = json_decode( wp_remote_retrieve_body( $response ), true );
// Try to extract URL from content.
if ( preg_match( '/https?:\/\/[^\s]+\.(?:png|jpg|jpeg|gif|webp)/i', $content, $matches ) ) {
$url = $matches[0];
if ( ! isset( $body['data'][0]['url'] ) ) {
return new WP_Error(
'image_generation_failed',
$body['error']['message'] ?? 'Unknown error'
);
}
return array(
'url' => $url,
'prompt' => $prompt,
'cost' => $response['cost'],
'model' => $response['model'],
'url' => $body['data'][0]['url'],
'cost' => $body['usage']['cost'] ?? 0.03,
'generation_time' => $generation_time,
'model' => $model,
'prompt' => $prompt,
);
}
/**
* Check if provider is configured
*
* @return bool True if API key is set.
*/
public function is_configured() {
return ! empty( $this->api_key );
}
/**
* Test connection to OpenRouter API
*
* @return array|WP_Error Success array or error.
*/
public function test_connection() {
if ( ! $this->is_configured() ) {
return new WP_Error( 'not_configured', 'OpenRouter API key not configured' );
}
$response = wp_remote_get(
'https://openrouter.ai/api/v1/models',
array(
'headers' => array(
'Authorization' => 'Bearer ' . $this->api_key,
),
'timeout' => 10,
)
);
if ( is_wp_error( $response ) ) {
return $response;
}
$code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $code ) {
return new WP_Error(
'connection_failed',
sprintf( 'OpenRouter API returned status %d', $code )
);
}
return array(
'success' => true,
'message' => 'Connected to OpenRouter successfully',
);
}
/**
* Check if provider supports task type
*
* @param string $type Task type.
* @return bool True (OpenRouter supports all task types).
*/
public function supports_task_type( $type ) {
return in_array(
$type,
array( 'chat', 'clarity', 'planning', 'writing', 'refinement', 'image' ),
true
);
}
}