'GET', 'callback' => [ $this, 'get_agents' ], 'permission_callback' => [ $this, 'check_permission' ], ], [ 'methods' => 'POST', 'callback' => [ $this, 'create_agent' ], 'permission_callback' => [ $this, 'check_permission' ], 'args' => $this->get_create_args(), ], ] ); register_rest_route( self::NAMESPACE, '/agents/(?P\d+)', [ [ 'methods' => 'GET', 'callback' => [ $this, 'get_agent' ], 'permission_callback' => [ $this, 'check_permission' ], ], [ 'methods' => 'PUT', 'callback' => [ $this, 'update_agent' ], 'permission_callback' => [ $this, 'check_permission' ], 'args' => $this->get_create_args(), ], [ 'methods' => 'DELETE', 'callback' => [ $this, 'delete_agent' ], 'permission_callback' => [ $this, 'check_permission' ], ], ] ); // Agent actions. register_rest_route( self::NAMESPACE, '/agents/(?P\d+)/toggle', [ 'methods' => 'POST', 'callback' => [ $this, 'toggle_status' ], 'permission_callback' => [ $this, 'check_permission' ], ] ); register_rest_route( self::NAMESPACE, '/agents/(?P\d+)/run', [ 'methods' => 'POST', 'callback' => [ $this, 'run_agent' ], 'permission_callback' => [ $this, 'check_permission' ], ] ); register_rest_route( self::NAMESPACE, '/agents/(?P\d+)/duplicate', [ 'methods' => 'POST', 'callback' => [ $this, 'duplicate_agent' ], 'permission_callback' => [ $this, 'check_permission' ], ] ); // Logs. register_rest_route( self::NAMESPACE, '/logs', [ 'methods' => 'GET', 'callback' => [ $this, 'get_logs' ], 'permission_callback' => [ $this, 'check_permission' ], ] ); // Models/providers. register_rest_route( self::NAMESPACE, '/models', [ 'methods' => 'GET', 'callback' => [ $this, 'get_models' ], 'permission_callback' => [ $this, 'check_permission' ], ] ); // API key validation. register_rest_route( self::NAMESPACE, '/validate-key', [ 'methods' => 'POST', 'callback' => [ $this, 'validate_api_key' ], 'permission_callback' => [ $this, 'check_permission' ], ] ); // Settings. register_rest_route( self::NAMESPACE, '/settings', [ [ 'methods' => 'GET', 'callback' => [ $this, 'get_settings' ], 'permission_callback' => [ $this, 'check_permission' ], ], [ 'methods' => 'POST', 'callback' => [ $this, 'save_settings' ], 'permission_callback' => [ $this, 'check_permission' ], ], ] ); // Stats. register_rest_route( self::NAMESPACE, '/stats', [ 'methods' => 'GET', 'callback' => [ $this, 'get_stats' ], 'permission_callback' => [ $this, 'check_permission' ], ] ); // Categories. register_rest_route( self::NAMESPACE, '/categories', [ 'methods' => 'GET', 'callback' => [ $this, 'get_categories' ], 'permission_callback' => [ $this, 'check_permission' ], ] ); } public function check_permission(): bool { return current_user_can( 'manage_options' ); } public function get_agents( \WP_REST_Request $request ): \WP_REST_Response { $agents = Agent::get_all(); $data = array_map( fn( $agent ) => $agent->to_array(), $agents ); return new \WP_REST_Response( $data, 200 ); } public function get_agent( \WP_REST_Request $request ): \WP_REST_Response { $agent = new Agent( (int) $request->get_param( 'id' ) ); if ( ! $agent->exists() ) { return new \WP_REST_Response( ['error' => 'Agent not found'], 404 ); } return new \WP_REST_Response( $agent->to_array(), 200 ); } public function create_agent( \WP_REST_Request $request ): \WP_REST_Response { $data = $request->get_json_params(); $id = Agent::create( $data ); if ( is_wp_error( $id ) ) { return new \WP_REST_Response( ['error' => $id->get_error_message()], 400 ); } $agent = new Agent( $id ); return new \WP_REST_Response( $agent->to_array(), 201 ); } public function update_agent( \WP_REST_Request $request ): \WP_REST_Response { $agent = new Agent( (int) $request->get_param( 'id' ) ); if ( ! $agent->exists() ) { return new \WP_REST_Response( ['error' => 'Agent not found'], 404 ); } $data = $request->get_json_params(); $result = $agent->update( $data ); if ( is_wp_error( $result ) ) { return new \WP_REST_Response( ['error' => $result->get_error_message()], 400 ); } return new \WP_REST_Response( $agent->to_array(), 200 ); } public function delete_agent( \WP_REST_Request $request ): \WP_REST_Response { $agent = new Agent( (int) $request->get_param( 'id' ) ); if ( ! $agent->exists() ) { return new \WP_REST_Response( ['error' => 'Agent not found'], 404 ); } $agent->delete(); return new \WP_REST_Response( ['success' => true], 200 ); } public function toggle_status( \WP_REST_Request $request ): \WP_REST_Response { $agent = new Agent( (int) $request->get_param( 'id' ) ); if ( ! $agent->exists() ) { return new \WP_REST_Response( ['error' => 'Agent not found'], 404 ); } $new_status = $agent->toggle_status(); return new \WP_REST_Response( [ 'status' => $new_status, 'active' => $new_status === 'active', ], 200 ); } public function run_agent( \WP_REST_Request $request ): \WP_REST_Response { $agent_id = (int) $request->get_param( 'id' ); $agent = new Agent( $agent_id ); if ( ! $agent->exists() ) { return new \WP_REST_Response( ['error' => 'Agent not found'], 404 ); } try { $post_id = AI::generate_post( $agent_id ); if ( $post_id ) { $agent->increment_run(); return new \WP_REST_Response( [ 'success' => true, 'post_id' => $post_id, ], 200 ); } return new \WP_REST_Response( ['error' => 'Generation failed'], 500 ); } catch ( \Exception $e ) { return new \WP_REST_Response( ['error' => $e->getMessage()], 500 ); } } public function duplicate_agent( \WP_REST_Request $request ): \WP_REST_Response { $agent = new Agent( (int) $request->get_param( 'id' ) ); if ( ! $agent->exists() ) { return new \WP_REST_Response( ['error' => 'Agent not found'], 404 ); } $data = $agent->to_array(); $data['title'] = $data['title'] . ' (Copy)'; unset( $data['id'] ); $new_id = Agent::create( $data ); if ( is_wp_error( $new_id ) ) { return new \WP_REST_Response( ['error' => $new_id->get_error_message()], 400 ); } $new_agent = new Agent( $new_id ); return new \WP_REST_Response( $new_agent->to_array(), 201 ); } public function get_logs( \WP_REST_Request $request ): \WP_REST_Response { $agent_id = (int) $request->get_param( 'agent_id' ); $limit = (int) $request->get_param( 'per_page' ) ?: 50; $offset = (int) $request->get_param( 'offset' ) ?: 0; $logs = ActivityLog::get_logs( $agent_id, $limit, $offset ); return new \WP_REST_Response( $logs, 200 ); } public function get_models( \WP_REST_Request $request ): \WP_REST_Response { return new \WP_REST_Response( AI::get_all_models(), 200 ); } public function validate_api_key( \WP_REST_Request $request ): \WP_REST_Response { $data = $request->get_json_params(); $provider = AI::get_provider( sanitize_text_field( $data['provider'] ?? '' ) ); $api_key = sanitize_text_field( $data['api_key'] ?? '' ); if ( ! $provider ) { return new \WP_REST_Response( ['error' => 'Unknown provider'], 400 ); } $valid = $provider->validate_key( $api_key ); return new \WP_REST_Response( ['valid' => $valid], 200 ); } public function get_settings( \WP_REST_Request $request ): \WP_REST_Response { $options = get_option( 'aibp_settings', [] ); // Mask API keys for security. foreach ( [ 'openai_api_key', 'google_api_key', 'grok_api_key', 'deepseek_api_key' ] as $key ) { if ( ! empty( $options[ $key ] ) ) { $options[ $key ] = '***' . substr( $options[ $key ], -4 ); } } return new \WP_REST_Response( $options, 200 ); } public function save_settings( \WP_REST_Request $request ): \WP_REST_Response { $data = $request->get_json_params(); $existing = get_option( 'aibp_settings', [] ); $sanitized = $existing; if ( isset( $data['openai_api_key'] ) && $data['openai_api_key'] !== '' ) { $sanitized['openai_api_key'] = sanitize_text_field( $data['openai_api_key'] ); } if ( isset( $data['google_api_key'] ) && $data['google_api_key'] !== '' ) { $sanitized['google_api_key'] = sanitize_text_field( $data['google_api_key'] ); } if ( isset( $data['grok_api_key'] ) && $data['grok_api_key'] !== '' ) { $sanitized['grok_api_key'] = sanitize_text_field( $data['grok_api_key'] ); } if ( isset( $data['deepseek_api_key'] ) && $data['deepseek_api_key'] !== '' ) { $sanitized['deepseek_api_key'] = sanitize_text_field( $data['deepseek_api_key'] ); } $sanitized['default_post_status'] = sanitize_text_field( $data['default_post_status'] ?? $existing['default_post_status'] ?? 'publish' ); $sanitized['default_post_type'] = sanitize_text_field( $data['default_post_type'] ?? $existing['default_post_type'] ?? 'post' ); $sanitized['log_retention'] = absint( $data['log_retention'] ?? $existing['log_retention'] ?? 90 ); update_option( 'aibp_settings', $sanitized ); return new \WP_REST_Response( ['success' => true], 200 ); } public function get_categories( \WP_REST_Request $request ): \WP_REST_Response { return new \WP_REST_Response( Helper::get_categories(), 200 ); } public function get_stats( \WP_REST_Request $request ): \WP_REST_Response { $total_agents = Agent::count(); $active_agents = Agent::count( [ 'meta_query' => [ ['key' => 'aibp_status', 'value' => 'active'], ], ] ); // Get total posts generated. global $wpdb; $cache_key = 'aibp_total_posts'; $total_posts = wp_cache_get( $cache_key, 'aibp' ); if ( false === $total_posts ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $total_posts = (int) $wpdb->get_var( $wpdb->prepare( "SELECT SUM(CAST(meta_value AS UNSIGNED)) FROM {$wpdb->postmeta} WHERE meta_key = %s", 'aibp_count' ) ); wp_cache_set( $cache_key, $total_posts ?: 0, 'aibp', 300 ); } return new \WP_REST_Response( [ 'total_agents' => $total_agents, 'active_agents' => $active_agents, 'total_posts' => $total_posts ?: 0, ], 200 ); } private function get_create_args(): array { return [ 'title' => ['required' => true, 'type' => 'string'], 'provider' => ['type' => 'string'], 'model' => ['type' => 'string'], 'subject' => ['type' => 'string'], 'length' => ['type' => 'integer'], 'prompt_title' => ['type' => 'string'], 'prompt_content' => ['type' => 'string'], 'recurrence_type' => ['type' => 'string'], 'recurrence_interval' => ['type' => 'integer'], 'recurrence_days' => ['type' => 'array'], 'recurrence_time' => ['type' => 'string'], 'post_type' => ['type' => 'string'], 'post_status' => ['type' => 'string'], 'categories' => ['type' => 'array'], 'temperature' => ['type' => 'number'], 'max_tokens' => ['type' => 'integer'], ]; } }