From 50bf779d4882a69c608e66ad16f6119a4485ccfe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:55:11 +0000 Subject: [PATCH 1/5] Initial plan From 818b9059cb375f9d57a75a319fc6a78cf8e1e6e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 7 Dec 2025 15:05:06 +0000 Subject: [PATCH 2/5] Add WP AI Client support with credentials management Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- README.md | 33 ++++++++- ai-command.php | 1 + composer.json | 3 +- src/AI/WpAiClient.php | 137 +++++++++++++++++++++++++++++++++++ src/AiCommand.php | 24 +++++-- src/CredentialsCommand.php | 142 +++++++++++++++++++++++++++++++++++++ 6 files changed, 332 insertions(+), 8 deletions(-) create mode 100644 src/AI/WpAiClient.php create mode 100644 src/CredentialsCommand.php diff --git a/README.md b/README.md index 0ab8420..4342333 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,38 @@ To install the latest development version of this package, use the following com wp package install mcp-wp/ai-command:dev-main ``` -Right now, the plugin requires a WordPress site with the [AI Services plugin](https://wordpress.org/plugins/ai-services) installed. +This package supports two AI backends: + +1. **WP AI Client** (recommended, available in WordPress 7.0+): The official WordPress AI client library, bundled with the AI plugin. +2. **AI Services plugin** (fallback): A third-party plugin available from the WordPress plugin directory. + +The command will automatically use WP AI Client if available, falling back to AI Services if not. + +### Configuration + +#### Using WP AI Client + +If you're using WordPress 7.0+ or have the AI plugin installed: + +```bash +# Configure credentials for AI providers +wp ai credentials set openai sk-proj-YOUR-API-KEY +wp ai credentials set anthropic sk-ant-YOUR-API-KEY +wp ai credentials set google YOUR-GOOGLE-API-KEY + +# List configured credentials +wp ai credentials list +``` + +#### Using AI Services Plugin + +If WP AI Client is not available, install the [AI Services plugin](https://wordpress.org/plugins/ai-services): + +```bash +wp plugin install ai-services --activate +``` + +Then configure your API keys through the WordPress admin or using environment variables. ### Reporting a bug diff --git a/ai-command.php b/ai-command.php index d959925..fb8c19a 100644 --- a/ai-command.php +++ b/ai-command.php @@ -13,6 +13,7 @@ } WP_CLI::add_command( 'ai', AiCommand::class ); +WP_CLI::add_command( 'ai credentials', CredentialsCommand::class ); WP_CLI::add_command( 'mcp prompt', AiCommand::class ); WP_CLI::add_command( 'mcp', McpCommand::class ); WP_CLI::add_command( 'mcp server', McpServerCommand::class ); diff --git a/composer.json b/composer.json index fdc41c4..718bb24 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,8 @@ "roave/security-advisories": "dev-latest", "wp-cli/extension-command": "^2.1", "wp-cli/wp-cli-tests": "^v4.3.9", - "wpackagist-plugin/ai-services": "^0.6.0" + "wpackagist-plugin/ai-services": "^0.6.0", + "wordpress/wp-ai-client": "^0.2.1" }, "repositories":[ { diff --git a/src/AI/WpAiClient.php b/src/AI/WpAiClient.php new file mode 100644 index 0000000..ba7394f --- /dev/null +++ b/src/AI/WpAiClient.php @@ -0,0 +1,137 @@ +>, server: string, callback: callable} + */ +class WpAiClient { + private bool $needs_approval = true; + + /** + * @param array $tools List of tools. + * @param bool $approval_mode Whether tool usage needs to be approved. + * @param string|null $service Service to use. + * @param string|null $model Model to use. + * + * @phpstan-param ToolDefinition[] $tools + */ + public function __construct( + private readonly array $tools, + private readonly bool $approval_mode, + private readonly ?string $service, + private readonly ?string $model + ) {} + + /** + * Calls a given tool. + * + * @param string $tool_name Tool name. + * @param mixed $tool_args Tool args. + * @return mixed + */ + private function call_tool( string $tool_name, mixed $tool_args ): mixed { + foreach ( $this->tools as $tool ) { + if ( $tool_name === $tool['name'] ) { + return call_user_func( $tool['callback'], $tool_args ); + } + } + + throw new InvalidArgumentException( 'Tool "' . $tool_name . '" not found.' ); + } + + /** + * Returns the name of the server a given tool is coming from. + * + * @param string $tool_name Tool name. + * @return mixed + */ + private function get_tool_server_name( string $tool_name ): mixed { + foreach ( $this->tools as $tool ) { + if ( $tool_name === $tool['name'] ) { + return $tool['server']; + } + } + + throw new InvalidArgumentException( 'Tool "' . $tool_name . '" not found.' ); + } + + /** + * Calls AI service with a prompt. + * + * @param string $prompt The prompt to send. + */ + public function call_ai_service_with_prompt( string $prompt ): void { + try { + // Initialize WP AI Client if not already done. + if ( ! did_action( 'init' ) ) { + do_action( 'init' ); + } + + \WordPress\AI_Client\AI_Client::init(); + + // Create a prompt builder. + $prompt_builder = \WordPress\AI_Client\AI_Client::prompt( $prompt ); + + // Apply model preference if specified. + if ( $this->service && $this->model ) { + $prompt_builder = $prompt_builder->using_model_preference( [ $this->service, $this->model ] ); + } elseif ( $this->model ) { + // If only model is specified, try to use it as a preference. + $prompt_builder = $prompt_builder->using_model_preference( [ 'anthropic', $this->model ], [ 'openai', $this->model ], [ 'google', $this->model ] ); + } + + // Generate text response. + $text = $prompt_builder->generate_text(); + + // Output the response. + WP_CLI::line( WP_CLI::colorize( "%G$text%n" ) ); + + // Keep the session open for follow-up questions. + $this->continue_conversation( $prompt, $text ); + + } catch ( Exception $e ) { + WP_CLI::error( $e->getMessage() ); + } + } + + /** + * Continues the conversation with follow-up prompts. + * + * @param string $initial_prompt The initial prompt. + * @param string $response The AI response. + */ + private function continue_conversation( string $initial_prompt, string $response ): void { + $user_response = prompt( '', false, '' ); + + if ( empty( $user_response ) ) { + return; + } + + try { + $prompt_builder = \WordPress\AI_Client\AI_Client::prompt( $user_response ); + + if ( $this->service && $this->model ) { + $prompt_builder = $prompt_builder->using_model_preference( [ $this->service, $this->model ] ); + } + + $text = $prompt_builder->generate_text(); + + WP_CLI::line( WP_CLI::colorize( "%G$text%n" ) ); + + $this->continue_conversation( $user_response, $text ); + } catch ( Exception $e ) { + WP_CLI::error( $e->getMessage() ); + } + } +} diff --git a/src/AiCommand.php b/src/AiCommand.php index 6e2ca5d..ec53e9e 100644 --- a/src/AiCommand.php +++ b/src/AiCommand.php @@ -75,19 +75,31 @@ public function __invoke( array $args, array $assoc_args ): void { WP_CLI::error( 'Not implemented yet.' ); } - if ( ! function_exists( '\ai_services' ) ) { - WP_CLI::error( 'This command currently requires the AI Services plugin. You can install it with `wp plugin install ai-services --activate`.' ); + // Check if WP AI Client is available (preferred). + $use_wp_ai_client = class_exists( '\WordPress\AI_Client\AI_Client' ); + + // Fallback to AI Services if WP AI Client is not available. + if ( ! $use_wp_ai_client && ! function_exists( '\ai_services' ) ) { + WP_CLI::error( 'This command requires either the WP AI Client (WordPress 7.0+) or the AI Services plugin. You can install the AI Services plugin with `wp plugin install ai-services --activate`.' ); } + $approval_mode = (bool) Utils\get_flag_value( $assoc_args, 'approval-mode', false ); + $service = Utils\get_flag_value( $assoc_args, 'service' ); + $model = Utils\get_flag_value( $assoc_args, 'model' ); + + // If using WP AI Client and no MCP tools are needed, use simplified path. + if ( $use_wp_ai_client && ! $approval_mode ) { + $ai_client = new AI\WpAiClient( [], $approval_mode, $service, $model ); + $ai_client->call_ai_service_with_prompt( $args[0] ); + return; + } + + // Otherwise, use the full MCP integration with AI Services. $skip_builtin_servers = Utils\get_flag_value( $assoc_args, 'skip-builtin-servers', 'all' ); $sessions = $this->get_sessions( $with_wordpress && 'cli' === $skip_builtin_servers, 'wp' === $skip_builtin_servers ); $tools = $this->get_tools( $sessions ); - $approval_mode = (bool) Utils\get_flag_value( $assoc_args, 'approval-mode', false ); - $service = Utils\get_flag_value( $assoc_args, 'service' ); - $model = Utils\get_flag_value( $assoc_args, 'model' ); - $ai_client = new AiClient( $tools, $approval_mode, $service, $model ); $ai_client->call_ai_service_with_prompt( $args[0] ); diff --git a/src/CredentialsCommand.php b/src/CredentialsCommand.php new file mode 100644 index 0000000..0853b67 --- /dev/null +++ b/src/CredentialsCommand.php @@ -0,0 +1,142 @@ + $assoc_args Associative arguments. + */ + public function list( array $args, array $assoc_args ): void { + $this->ensure_wp_ai_client_available(); + + WP_CLI::get_runner()->load_wordpress(); + + $credentials = get_option( 'wp_ai_client_provider_credentials', [] ); + + if ( empty( $credentials ) ) { + WP_CLI::log( 'No credentials configured.' ); + return; + } + + $rows = []; + foreach ( $credentials as $provider => $data ) { + $rows[] = [ + 'provider' => $provider, + 'status' => ! empty( $data['api_key'] ) ? 'configured' : 'not configured', + ]; + } + + Utils\format_items( 'table', $rows, [ 'provider', 'status' ] ); + } + + /** + * Set credentials for an AI provider. + * + * ## OPTIONS + * + * + * : The AI provider to configure (e.g., 'openai', 'anthropic', 'google'). + * + * + * : The API key for the provider. + * + * ## EXAMPLES + * + * # Set OpenAI credentials + * $ wp ai credentials set openai sk-proj-... + * Success: Credentials for 'openai' saved. + * + * @when before_wp_load + * + * @param string[] $args Indexed array of positional arguments. + * @param array $assoc_args Associative arguments. + */ + public function set( array $args, array $assoc_args ): void { + $this->ensure_wp_ai_client_available(); + + WP_CLI::get_runner()->load_wordpress(); + + $provider = $args[0]; + $api_key = $args[1]; + + $credentials = get_option( 'wp_ai_client_provider_credentials', [] ); + $credentials[ $provider ] = [ 'api_key' => $api_key ]; + + update_option( 'wp_ai_client_provider_credentials', $credentials ); + + WP_CLI::success( "Credentials for '$provider' saved." ); + } + + /** + * Delete credentials for an AI provider. + * + * ## OPTIONS + * + * + * : The AI provider to remove credentials for. + * + * ## EXAMPLES + * + * # Delete OpenAI credentials + * $ wp ai credentials delete openai + * Success: Credentials for 'openai' deleted. + * + * @when before_wp_load + * + * @param string[] $args Indexed array of positional arguments. + * @param array $assoc_args Associative arguments. + */ + public function delete( array $args, array $assoc_args ): void { + $this->ensure_wp_ai_client_available(); + + WP_CLI::get_runner()->load_wordpress(); + + $provider = $args[0]; + + $credentials = get_option( 'wp_ai_client_provider_credentials', [] ); + + if ( ! isset( $credentials[ $provider ] ) ) { + WP_CLI::error( "No credentials found for '$provider'." ); + } + + unset( $credentials[ $provider ] ); + update_option( 'wp_ai_client_provider_credentials', $credentials ); + + WP_CLI::success( "Credentials for '$provider' deleted." ); + } + + /** + * Ensures the WP AI Client is available. + */ + private function ensure_wp_ai_client_available(): void { + if ( ! class_exists( '\WordPress\AI_Client\AI_Client' ) ) { + WP_CLI::error( 'The WP AI Client is not available. Please ensure the WP AI plugin is installed and activated.' ); + } + } +} From c195bc1dd53fa3a4bbe3d45254c2f79c8c2ce91f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 7 Dec 2025 15:06:40 +0000 Subject: [PATCH 3/5] Improve backward compatibility and add tests Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- composer.json | 3 +++ features/ai-credentials.feature | 12 ++++++++++++ features/ai.feature | 2 +- src/AiCommand.php | 29 ++++++++++++++++------------- 4 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 features/ai-credentials.feature diff --git a/composer.json b/composer.json index 718bb24..507539a 100644 --- a/composer.json +++ b/composer.json @@ -50,6 +50,9 @@ "bundled": false, "commands": [ "ai", + "ai credentials list", + "ai credentials set", + "ai credentials delete", "mcp prompt", "mcp server add", "mcp server list", diff --git a/features/ai-credentials.feature b/features/ai-credentials.feature new file mode 100644 index 0000000..13f8565 --- /dev/null +++ b/features/ai-credentials.feature @@ -0,0 +1,12 @@ +Feature: AI Credentials command + Scenario: Credentials management with WP AI Client + Given a WP installation + + When I try `wp ai credentials list` + Then STDERR should contain: + """ + The WP AI Client is not available. + """ + + # TODO: Add tests for when WP AI Client is available + # This would require installing the AI plugin or WordPress 7.0+ diff --git a/features/ai.feature b/features/ai.feature index ffbeab4..299419d 100644 --- a/features/ai.feature +++ b/features/ai.feature @@ -16,7 +16,7 @@ Feature: AI command When I try `wp ai "Hello World"` Then STDERR should contain: """ - This command currently requires the AI Services plugin. + This command requires the AI Services plugin for MCP tool integration. """ When I run `wp plugin install ai-services --activate` diff --git a/src/AiCommand.php b/src/AiCommand.php index ec53e9e..0ccc4c5 100644 --- a/src/AiCommand.php +++ b/src/AiCommand.php @@ -75,26 +75,29 @@ public function __invoke( array $args, array $assoc_args ): void { WP_CLI::error( 'Not implemented yet.' ); } - // Check if WP AI Client is available (preferred). - $use_wp_ai_client = class_exists( '\WordPress\AI_Client\AI_Client' ); - - // Fallback to AI Services if WP AI Client is not available. - if ( ! $use_wp_ai_client && ! function_exists( '\ai_services' ) ) { - WP_CLI::error( 'This command requires either the WP AI Client (WordPress 7.0+) or the AI Services plugin. You can install the AI Services plugin with `wp plugin install ai-services --activate`.' ); - } - $approval_mode = (bool) Utils\get_flag_value( $assoc_args, 'approval-mode', false ); $service = Utils\get_flag_value( $assoc_args, 'service' ); $model = Utils\get_flag_value( $assoc_args, 'model' ); - // If using WP AI Client and no MCP tools are needed, use simplified path. + // Check if WP AI Client is available (preferred for simple prompts). + $use_wp_ai_client = class_exists( '\WordPress\AI_Client\AI_Client' ); + + // If using WP AI Client and no MCP tools/approval is needed, use simplified path. if ( $use_wp_ai_client && ! $approval_mode ) { - $ai_client = new AI\WpAiClient( [], $approval_mode, $service, $model ); - $ai_client->call_ai_service_with_prompt( $args[0] ); - return; + $skip_builtin_servers = Utils\get_flag_value( $assoc_args, 'skip-builtin-servers' ); + // Only use WP AI Client if MCP servers are skipped. + if ( $skip_builtin_servers ) { + $ai_client = new AI\WpAiClient( [], $approval_mode, $service, $model ); + $ai_client->call_ai_service_with_prompt( $args[0] ); + return; + } + } + + // Otherwise, use the full MCP integration with AI Services (required for tools). + if ( ! function_exists( '\ai_services' ) ) { + WP_CLI::error( 'This command requires the AI Services plugin for MCP tool integration. You can install it with `wp plugin install ai-services --activate`. Alternatively, use `--skip-builtin-servers=all` to use WP AI Client without MCP tools.' ); } - // Otherwise, use the full MCP integration with AI Services. $skip_builtin_servers = Utils\get_flag_value( $assoc_args, 'skip-builtin-servers', 'all' ); $sessions = $this->get_sessions( $with_wordpress && 'cli' === $skip_builtin_servers, 'wp' === $skip_builtin_servers ); From f807a05156965605aa1b4054dd083fdf27b41cb2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 7 Dec 2025 15:09:54 +0000 Subject: [PATCH 4/5] Address code review feedback Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- ai-command.php | 10 +++++----- src/AI/WpAiClient.php | 11 +++++++++-- src/AiCommand.php | 3 ++- src/CredentialsCommand.php | 12 ++++++------ 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/ai-command.php b/ai-command.php index fb8c19a..9a64f8d 100644 --- a/ai-command.php +++ b/ai-command.php @@ -12,8 +12,8 @@ require_once __DIR__ . '/vendor/autoload.php'; } -WP_CLI::add_command( 'ai', AiCommand::class ); -WP_CLI::add_command( 'ai credentials', CredentialsCommand::class ); -WP_CLI::add_command( 'mcp prompt', AiCommand::class ); -WP_CLI::add_command( 'mcp', McpCommand::class ); -WP_CLI::add_command( 'mcp server', McpServerCommand::class ); +WP_CLI::add_command( 'ai', \McpWp\AiCommand\AiCommand::class ); +WP_CLI::add_command( 'ai credentials', \McpWp\AiCommand\CredentialsCommand::class ); +WP_CLI::add_command( 'mcp prompt', \McpWp\AiCommand\AiCommand::class ); +WP_CLI::add_command( 'mcp', \McpWp\AiCommand\McpCommand::class ); +WP_CLI::add_command( 'mcp server', \McpWp\AiCommand\McpServerCommand::class ); diff --git a/src/AI/WpAiClient.php b/src/AI/WpAiClient.php index ba7394f..49b3236 100644 --- a/src/AI/WpAiClient.php +++ b/src/AI/WpAiClient.php @@ -87,8 +87,15 @@ public function call_ai_service_with_prompt( string $prompt ): void { if ( $this->service && $this->model ) { $prompt_builder = $prompt_builder->using_model_preference( [ $this->service, $this->model ] ); } elseif ( $this->model ) { - // If only model is specified, try to use it as a preference. - $prompt_builder = $prompt_builder->using_model_preference( [ 'anthropic', $this->model ], [ 'openai', $this->model ], [ 'google', $this->model ] ); + // If only model is specified without a service, try common providers. + // This provides a reasonable fallback that works with most configurations. + // The WP AI Client will automatically use the first available provider + // that has the specified model and is properly configured. + $prompt_builder = $prompt_builder->using_model_preference( + [ 'anthropic', $this->model ], + [ 'openai', $this->model ], + [ 'google', $this->model ] + ); } // Generate text response. diff --git a/src/AiCommand.php b/src/AiCommand.php index 0ccc4c5..fcfafe8 100644 --- a/src/AiCommand.php +++ b/src/AiCommand.php @@ -4,6 +4,7 @@ use Mcp\Client\ClientSession; use McpWp\AiCommand\AI\AiClient; +use McpWp\AiCommand\AI\WpAiClient; use McpWp\AiCommand\MCP\Client; use McpWp\AiCommand\Utils\CliLogger; use McpWp\AiCommand\Utils\McpConfig; @@ -87,7 +88,7 @@ public function __invoke( array $args, array $assoc_args ): void { $skip_builtin_servers = Utils\get_flag_value( $assoc_args, 'skip-builtin-servers' ); // Only use WP AI Client if MCP servers are skipped. if ( $skip_builtin_servers ) { - $ai_client = new AI\WpAiClient( [], $approval_mode, $service, $model ); + $ai_client = new WpAiClient( [], $approval_mode, $service, $model ); $ai_client->call_ai_service_with_prompt( $args[0] ); return; } diff --git a/src/CredentialsCommand.php b/src/CredentialsCommand.php index 0853b67..bfa90c8 100644 --- a/src/CredentialsCommand.php +++ b/src/CredentialsCommand.php @@ -20,12 +20,12 @@ class CredentialsCommand extends WP_CLI_Command { * * # List all credentials * $ wp ai credentials list - * +----------+------------+ - * | Provider | Status | - * +----------+------------+ - * | openai | configured | - * | anthropic| configured | - * +----------+------------+ + * +-----------+------------+ + * | Provider | Status | + * +-----------+------------+ + * | openai | configured | + * | anthropic | configured | + * +-----------+------------+ * * @when before_wp_load * From ca652fc8222c01787ee49e4b9f0c0e135fc258b7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 7 Dec 2025 16:30:25 +0000 Subject: [PATCH 5/5] Remove AI Services backward compatibility, use only WP AI Client Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- README.md | 21 ++------------ composer.json | 1 - features/ai.feature | 11 ++------ src/AiCommand.php | 69 +++++++++------------------------------------ 4 files changed, 19 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 4342333..3166a55 100644 --- a/README.md +++ b/README.md @@ -21,18 +21,11 @@ To install the latest development version of this package, use the following com wp package install mcp-wp/ai-command:dev-main ``` -This package supports two AI backends: - -1. **WP AI Client** (recommended, available in WordPress 7.0+): The official WordPress AI client library, bundled with the AI plugin. -2. **AI Services plugin** (fallback): A third-party plugin available from the WordPress plugin directory. - -The command will automatically use WP AI Client if available, falling back to AI Services if not. +This package uses the **WP AI Client** (available in WordPress 7.0+ or via the AI plugin) for AI functionality. ### Configuration -#### Using WP AI Client - -If you're using WordPress 7.0+ or have the AI plugin installed: +Configure credentials for AI providers: ```bash # Configure credentials for AI providers @@ -44,15 +37,7 @@ wp ai credentials set google YOUR-GOOGLE-API-KEY wp ai credentials list ``` -#### Using AI Services Plugin - -If WP AI Client is not available, install the [AI Services plugin](https://wordpress.org/plugins/ai-services): - -```bash -wp plugin install ai-services --activate -``` - -Then configure your API keys through the WordPress admin or using environment variables. +Credentials are stored in the WordPress database and can also be managed through the WordPress admin settings screen. ### Reporting a bug diff --git a/composer.json b/composer.json index 507539a..52412eb 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,6 @@ "roave/security-advisories": "dev-latest", "wp-cli/extension-command": "^2.1", "wp-cli/wp-cli-tests": "^v4.3.9", - "wpackagist-plugin/ai-services": "^0.6.0", "wordpress/wp-ai-client": "^0.2.1" }, "repositories":[ diff --git a/features/ai.feature b/features/ai.feature index 299419d..38655c6 100644 --- a/features/ai.feature +++ b/features/ai.feature @@ -1,5 +1,5 @@ Feature: AI command - Scenario: Missing AI Services plugin + Scenario: Missing WP AI Client When I try `wp ai "Hello World"` Then STDERR should contain: """ @@ -16,12 +16,5 @@ Feature: AI command When I try `wp ai "Hello World"` Then STDERR should contain: """ - This command requires the AI Services plugin for MCP tool integration. - """ - - When I run `wp plugin install ai-services --activate` - When I try `wp ai "Hello World"` - Then STDERR should contain: - """ - No service satisfying the given arguments is registered and available. + This command requires the WP AI Client. """ diff --git a/src/AiCommand.php b/src/AiCommand.php index fcfafe8..270cdef 100644 --- a/src/AiCommand.php +++ b/src/AiCommand.php @@ -2,13 +2,7 @@ namespace McpWp\AiCommand; -use Mcp\Client\ClientSession; -use McpWp\AiCommand\AI\AiClient; use McpWp\AiCommand\AI\WpAiClient; -use McpWp\AiCommand\MCP\Client; -use McpWp\AiCommand\Utils\CliLogger; -use McpWp\AiCommand\Utils\McpConfig; -use McpWp\MCP\Servers\WordPress\WordPress; use WP_CLI; use WP_CLI\Utils; use WP_CLI_Command; @@ -16,9 +10,7 @@ /** * AI command class. * - * Allows interacting with an LLM using MCP. - * - * @phpstan-import-type ToolDefinition from AiClient + * Allows interacting with an LLM using the WP AI Client. */ class AiCommand extends WP_CLI_Command { @@ -30,38 +22,26 @@ class AiCommand extends WP_CLI_Command { * * : AI prompt. * - * [--skip-builtin-servers[=]] - * : Skip loading the built-in servers for WP-CLI and the current WordPress site. - * Can be set to 'all' (skip both), 'cli' (skip the WP-CLI server), - * or 'wp' (skip the WordPress server). - * * [--skip-wordpress] * : Run command without loading WordPress. (Not implemented yet) * - * [--approval-mode] - * : Approve tool usage before running. - * * [--service=] * : Manually specify the AI service to use. - * Depends on the available AI services. * Examples: 'google', 'anthropic', 'openai'. * * [--model=] * : Manually specify the LLM model that should be used. - * Depends on the available AI services. - * Examples: 'gemini-2.0-flash', 'gpt-4o'. + * Examples: 'gemini-2.0-flash', 'gpt-4o', 'claude-sonnet-4-5'. * * ## EXAMPLES * - * # Get data from WordPress - * $ wp ai "What are the titles of my last three posts?" - * - Hello world - * - My awesome post - * - Another post + * # Ask a simple question + * $ wp ai "Explain WordPress in one sentence" + * WordPress is a free and open-source content management system... * - * # Interact with multiple MCP servers. - * $ wp ai "Take file foo.txt and create a new blog post from it" - * Success: Blog post created. + * # Use a specific model + * $ wp ai "Summarize the history of WordPress" --model=gpt-4o + * WordPress was created in 2003... * * @when before_wp_load * @@ -76,36 +56,15 @@ public function __invoke( array $args, array $assoc_args ): void { WP_CLI::error( 'Not implemented yet.' ); } - $approval_mode = (bool) Utils\get_flag_value( $assoc_args, 'approval-mode', false ); - $service = Utils\get_flag_value( $assoc_args, 'service' ); - $model = Utils\get_flag_value( $assoc_args, 'model' ); - - // Check if WP AI Client is available (preferred for simple prompts). - $use_wp_ai_client = class_exists( '\WordPress\AI_Client\AI_Client' ); - - // If using WP AI Client and no MCP tools/approval is needed, use simplified path. - if ( $use_wp_ai_client && ! $approval_mode ) { - $skip_builtin_servers = Utils\get_flag_value( $assoc_args, 'skip-builtin-servers' ); - // Only use WP AI Client if MCP servers are skipped. - if ( $skip_builtin_servers ) { - $ai_client = new WpAiClient( [], $approval_mode, $service, $model ); - $ai_client->call_ai_service_with_prompt( $args[0] ); - return; - } - } - - // Otherwise, use the full MCP integration with AI Services (required for tools). - if ( ! function_exists( '\ai_services' ) ) { - WP_CLI::error( 'This command requires the AI Services plugin for MCP tool integration. You can install it with `wp plugin install ai-services --activate`. Alternatively, use `--skip-builtin-servers=all` to use WP AI Client without MCP tools.' ); + // Ensure WP AI Client is available. + if ( ! class_exists( '\WordPress\AI_Client\AI_Client' ) ) { + WP_CLI::error( 'This command requires the WP AI Client. Please ensure WordPress 7.0+ or the AI plugin is installed and activated.' ); } - $skip_builtin_servers = Utils\get_flag_value( $assoc_args, 'skip-builtin-servers', 'all' ); - - $sessions = $this->get_sessions( $with_wordpress && 'cli' === $skip_builtin_servers, 'wp' === $skip_builtin_servers ); - $tools = $this->get_tools( $sessions ); - - $ai_client = new AiClient( $tools, $approval_mode, $service, $model ); + $service = Utils\get_flag_value( $assoc_args, 'service' ); + $model = Utils\get_flag_value( $assoc_args, 'model' ); + $ai_client = new WpAiClient( [], false, $service, $model ); $ai_client->call_ai_service_with_prompt( $args[0] ); }