__( 'WebMCP', 'ai' ), 'description' => __( 'Lets an agent browser work in the block editor through WebMCP: set the title, insert and edit blocks, save and publish, with every change visible on the page as it happens.', 'ai' ), 'category' => Experiment_Category::EDITOR, 'capability' => 'none', 'usage' => array( 'trigger' => 'none', 'runs' => __( 'When an agent browser calls one of its tools in the block editor', 'ai' ), 'sends' => __( 'Nothing to your AI provider. Depending on the tool called, the post title, status, and a short text preview of each block go to the AI model the agent browser uses', 'ai' ), 'details' => __( 'Lets the agent browser read the post and change its title and blocks, save, and publish it', 'ai' ), ), ); } /** * {@inheritDoc} */ public function register(): void { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); } /** * Admin screens the bridge loads on. * * @since 1.5.0 * * @return list Hook suffixes. */ public function get_screens(): array { /** * Filters the admin screens (hook suffixes) the WebMCP bridge loads on. * * The editor tools only work where the editor stores exist. A screen * added here should register its own tools through the JavaScript * registry, or the bridge will have nothing to register. * * @since 1.5.0 * * @param list $screens Hook suffixes. Default the post editor screens. */ $defaults = array( 'post.php', 'post-new.php' ); $screens = apply_filters( 'wpai_webmcp_screens', $defaults ); // A filter that returns something other than an array is a mistake; // keep the default screens rather than fail on every admin page. if ( ! is_array( $screens ) ) { return $defaults; } return array_values( array_filter( $screens, 'is_string' ) ); } /** * Cap on tools registered per page. * * @since 1.5.0 * * @return int Cap, at least 1. */ public function get_max_tools(): int { /** * Filters how many tools one page may register with the browser. * * @since 1.5.0 * * @param int $max_tools Cap. Default 30. */ $max_tools = (int) apply_filters( 'wpai_webmcp_max_tools', self::DEFAULT_MAX_TOOLS ); return max( 1, $max_tools ); } /** * Loads the bridge on the editor screens. * * @since 1.5.0 * * @param string $hook_suffix Current admin page hook suffix. */ public function enqueue_assets( string $hook_suffix ): void { if ( ! in_array( $hook_suffix, $this->get_screens(), true ) ) { return; } Asset_Loader::enqueue_script( self::SCRIPT_HANDLE, 'experiments/webmcp' ); Asset_Loader::localize_script( self::SCRIPT_HANDLE, 'WebMCP', array( 'screen' => $hook_suffix, 'maxTools' => $this->get_max_tools(), ) ); } }