Agent Toolbelt (spec §5). Shows the ability checklist * (enable/disable, persisted to the plugin option), the audit-log table, and a * status line. The checklist is the only setting in v1 — defaults are the * product. */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'Agent_Toolbelt_Admin' ) ) { class Agent_Toolbelt_Admin { const NONCE_ACTION = 'agent_toolbelt_save'; const NONCE_FIELD = 'agent_toolbelt_nonce'; const AUDIT_LIMIT = 20; /** * Adds the Tools -> Agent Toolbelt submenu page. */ public static function register_menu() { add_management_page( __( 'Agent Toolbelt', 'agent-toolbelt' ), __( 'Agent Toolbelt', 'agent-toolbelt' ), 'manage_options', 'agent-toolbelt', array( __CLASS__, 'render_page' ) ); } /** * Renders the admin page: status line, ability checklist, audit table. */ public static function render_page() { if ( ! current_user_can( 'manage_options' ) ) { return; } $atb_saved = self::maybe_save(); echo '
' . esc_html__( 'Abilities updated.', 'agent-toolbelt' ) . '
';
echo esc_html__( 'Abilities API available:', 'agent-toolbelt' ) . ' ' . ( $atb_abilities_available ? esc_html__( 'yes', 'agent-toolbelt' ) : esc_html__( 'no', 'agent-toolbelt' ) ) . '
';
echo esc_html__( 'Kill switch (AGENT_TOOLBELT_DISABLED):', 'agent-toolbelt' ) . ' ' . ( $atb_kill_switch_active ? esc_html__( 'active', 'agent-toolbelt' ) : esc_html__( 'inactive', 'agent-toolbelt' ) ) . '';
echo '
' . esc_html__( 'This site does not expose the WordPress Abilities API (requires WordPress 6.9+). The operations still work via WP-CLI.', 'agent-toolbelt' ) . '
'; } if ( $atb_kill_switch_active ) { echo '' . esc_html__( 'The kill switch is on: no abilities are registered and agents cannot call any operation.', 'agent-toolbelt' ) . '
'; } // Accuracy note (2026-07): core ships the Abilities API and its // REST endpoints; MCP exposure needs a bridge plugin (the official // `ai` plugin lists MCP as upcoming). Don't promise a "core MCP adapter". echo '' . esc_html__( 'AI agents can call the enabled abilities below through the WordPress REST API (wp-abilities/v1, application-password auth) or through any MCP bridge that exposes WordPress Abilities. Only the enabled abilities are visible to them.', 'agent-toolbelt' ) . '
'; } /** * Ability checklist with risk badges and one-line descriptions. */ protected static function render_checklist() { echo '' . esc_html__( 'No operations have been recorded yet.', 'agent-toolbelt' ) . '
'; return; } echo '| ' . esc_html( $atb_head ) . ' | '; } echo '|||||||
|---|---|---|---|---|---|---|---|
| ' . esc_html( isset( $atb_row['created_at'] ) ? $atb_row['created_at'] : '' ) . ' | '; echo '' . esc_html( isset( $atb_row['ability'] ) ? $atb_row['ability'] : '' ) . ' | ';
echo '' . esc_html( isset( $atb_row['caller'] ) ? $atb_row['caller'] : '' ) . ' | '; echo '' . esc_html( isset( $atb_row['user_id'] ) ? $atb_row['user_id'] : '0' ) . ' | '; echo '' . ( empty( $atb_row['dry_run'] ) ? esc_html__( 'no', 'agent-toolbelt' ) : esc_html__( 'yes', 'agent-toolbelt' ) ) . ' | '; echo '' . esc_html( isset( $atb_row['result'] ) ? $atb_row['result'] : '' ) . ' | '; echo '' . esc_html( isset( $atb_row['duration_ms'] ) ? $atb_row['duration_ms'] : '0' ) . ' | '; echo '' . esc_html( isset( $atb_row['summary'] ) ? $atb_row['summary'] : '' ) . ' | '; echo '