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:
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user