diff --git a/data-machine.php b/data-machine.php index 397ee12cd..2428f2d07 100644 --- a/data-machine.php +++ b/data-machine.php @@ -123,6 +123,10 @@ function () { // Agent auth callback handler (receives tokens from external DM instances). new \DataMachine\Core\Auth\AgentAuthCallback(); + // Register ability categories first — must happen before any ability registration. + require_once __DIR__ . '/inc/Abilities/AbilityCategories.php'; + \DataMachine\Abilities\AbilityCategories::ensure_registered(); + // Load abilities require_once __DIR__ . '/inc/Abilities/AuthAbilities.php'; require_once __DIR__ . '/inc/Abilities/File/FileConstants.php'; diff --git a/inc/Abilities/AbilityCategories.php b/inc/Abilities/AbilityCategories.php new file mode 100644 index 000000000..bb040db4c --- /dev/null +++ b/inc/Abilities/AbilityCategories.php @@ -0,0 +1,159 @@ + array( + 'label' => __( 'Content', 'data-machine' ), + 'description' => __( 'Content querying, editing, searching, and block operations.', 'data-machine' ), + ), + self::MEDIA => array( + 'label' => __( 'Media', 'data-machine' ), + 'description' => __( 'Image generation, alt text, media upload, validation, and optimization.', 'data-machine' ), + ), + self::ANALYTICS => array( + 'label' => __( 'Analytics', 'data-machine' ), + 'description' => __( 'Google Analytics, Search Console, Bing Webmaster, and PageSpeed.', 'data-machine' ), + ), + self::SEO => array( + 'label' => __( 'SEO', 'data-machine' ), + 'description' => __( 'Internal linking, meta descriptions, and IndexNow.', 'data-machine' ), + ), + self::MEMORY => array( + 'label' => __( 'Memory', 'data-machine' ), + 'description' => __( 'Agent memory, daily journals, and agent file management.', 'data-machine' ), + ), + self::TAXONOMY => array( + 'label' => __( 'Taxonomy', 'data-machine' ), + 'description' => __( 'Taxonomy term CRUD and resolution.', 'data-machine' ), + ), + self::PUBLISHING => array( + 'label' => __( 'Publishing', 'data-machine' ), + 'description' => __( 'WordPress publishing, email sending, and post updates.', 'data-machine' ), + ), + self::FETCH => array( + 'label' => __( 'Fetch', 'data-machine' ), + 'description' => __( 'RSS, WordPress API, media, files, and email fetching.', 'data-machine' ), + ), + self::EMAIL => array( + 'label' => __( 'Email', 'data-machine' ), + 'description' => __( 'Email management — reply, delete, move, flag, unsubscribe.', 'data-machine' ), + ), + self::PIPELINE => array( + 'label' => __( 'Pipeline', 'data-machine' ), + 'description' => __( 'Pipeline CRUD, step management, handler and step-type discovery.', 'data-machine' ), + ), + self::FLOW => array( + 'label' => __( 'Flow', 'data-machine' ), + 'description' => __( 'Flow CRUD, scheduling, queue management, and webhook triggers.', 'data-machine' ), + ), + self::JOBS => array( + 'label' => __( 'Jobs', 'data-machine' ), + 'description' => __( 'Job management, health monitoring, recovery, and workflow execution.', 'data-machine' ), + ), + self::AGENT => array( + 'label' => __( 'Agent', 'data-machine' ), + 'description' => __( 'Agent CRUD, tokens, pings, duplicate checking, and processed items.', 'data-machine' ), + ), + self::SETTINGS => array( + 'label' => __( 'Settings', 'data-machine' ), + 'description' => __( 'Plugin settings, tool configuration, and handler defaults.', 'data-machine' ), + ), + self::AUTH => array( + 'label' => __( 'Auth', 'data-machine' ), + 'description' => __( 'OAuth provider management and authentication.', 'data-machine' ), + ), + self::LOGGING => array( + 'label' => __( 'Logging', 'data-machine' ), + 'description' => __( 'Log reading, writing, clearing, and metadata.', 'data-machine' ), + ), + self::SYSTEM => array( + 'label' => __( 'System', 'data-machine' ), + 'description' => __( 'System health, session titles, and background task execution.', 'data-machine' ), + ), + self::CHAT => array( + 'label' => __( 'Chat', 'data-machine' ), + 'description' => __( 'Chat session management and messaging.', 'data-machine' ), + ), + ); + + foreach ( $categories as $slug => $args ) { + wp_register_ability_category( $slug, $args ); + } + + self::$registered = true; + } + + /** + * Ensure categories are registered. + * + * Handles timing: if the categories_init hook already fired, registers + * immediately. Otherwise hooks into it. This mirrors the pattern used + * by individual ability classes. + */ + public static function ensure_registered(): void { + if ( self::$registered ) { + return; + } + + if ( did_action( 'wp_abilities_api_categories_init' ) ) { + self::register(); + } else { + add_action( 'wp_abilities_api_categories_init', array( self::class, 'register' ) ); + } + } +} diff --git a/inc/Abilities/AgentAbilities.php b/inc/Abilities/AgentAbilities.php index ab8db38c2..9519ba8f9 100644 --- a/inc/Abilities/AgentAbilities.php +++ b/inc/Abilities/AgentAbilities.php @@ -41,7 +41,7 @@ private function registerAbilities(): void { array( 'label' => 'Rename Agent', 'description' => 'Rename an agent slug — updates database and moves filesystem directory', - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'old_slug', 'new_slug' ), @@ -78,7 +78,7 @@ private function registerAbilities(): void { array( 'label' => 'List Agents', 'description' => 'List all registered agent identities', - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'properties' => new \stdClass(), @@ -113,7 +113,7 @@ private function registerAbilities(): void { array( 'label' => 'Create Agent', 'description' => 'Create a new agent identity with filesystem directory and owner access. Admins can create agents for any user. Non-admins with create_own_agent can create one agent for themselves.', - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'agent_slug' ), @@ -160,7 +160,7 @@ private function registerAbilities(): void { array( 'label' => 'Get Agent', 'description' => 'Retrieve a single agent by slug or ID with access grants and directory info', - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -199,7 +199,7 @@ private function registerAbilities(): void { array( 'label' => 'Update Agent', 'description' => 'Update an agent\'s mutable fields (name, config, status)', - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'agent_id' ), @@ -241,7 +241,7 @@ private function registerAbilities(): void { array( 'label' => 'Delete Agent', 'description' => 'Delete an agent record and access grants, optionally removing filesystem directory', - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/AgentMemoryAbilities.php b/inc/Abilities/AgentMemoryAbilities.php index be6644cab..5ca9291f3 100644 --- a/inc/Abilities/AgentMemoryAbilities.php +++ b/inc/Abilities/AgentMemoryAbilities.php @@ -41,7 +41,7 @@ private function registerAbilities(): void { array( 'label' => 'Get Agent Memory', 'description' => 'Read agent file content — full file or a specific section. Supports any agent file (MEMORY.md, SOUL.md, USER.md, etc.).', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -89,7 +89,7 @@ private function registerAbilities(): void { array( 'label' => 'Update Agent Memory', 'description' => 'Write to a specific section of an agent file — set (replace) or append. Supports any agent file.', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -141,7 +141,7 @@ private function registerAbilities(): void { array( 'label' => 'Search Agent Memory', 'description' => 'Search across agent file content. Returns matching lines with context, grouped by section. Supports any agent file.', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'query' ), @@ -201,7 +201,7 @@ private function registerAbilities(): void { array( 'label' => 'List Agent Memory Sections', 'description' => 'List all section headers in an agent file. Supports any agent file.', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/AgentPing/SendPingAbility.php b/inc/Abilities/AgentPing/SendPingAbility.php index d6c44df17..57c76d81e 100644 --- a/inc/Abilities/AgentPing/SendPingAbility.php +++ b/inc/Abilities/AgentPing/SendPingAbility.php @@ -32,7 +32,7 @@ private function registerAbility(): void { array( 'label' => __( 'Send Ping', 'data-machine' ), 'description' => __( 'Send pipeline context to webhook endpoints. Supports multiple URLs (one per line).', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'webhook_url' ), diff --git a/inc/Abilities/AgentTokenAbilities.php b/inc/Abilities/AgentTokenAbilities.php index de36844d9..fa36aeb81 100644 --- a/inc/Abilities/AgentTokenAbilities.php +++ b/inc/Abilities/AgentTokenAbilities.php @@ -49,7 +49,7 @@ private function registerCreateToken(): void { array( 'label' => __( 'Create Agent Token', 'data-machine' ), 'description' => __( 'Create a bearer token for agent runtime authentication. The raw token is only returned once.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'agent_id' ), @@ -96,7 +96,7 @@ private function registerRevokeToken(): void { array( 'label' => __( 'Revoke Agent Token', 'data-machine' ), 'description' => __( 'Revoke (delete) an agent bearer token. The token will immediately stop working.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'agent_id', 'token_id' ), @@ -132,7 +132,7 @@ private function registerListTokens(): void { array( 'label' => __( 'List Agent Tokens', 'data-machine' ), 'description' => __( 'List all tokens for an agent. Returns metadata only (never the token value).', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'agent_id' ), diff --git a/inc/Abilities/Analytics/BingWebmasterAbilities.php b/inc/Abilities/Analytics/BingWebmasterAbilities.php index c211fcf28..c12467226 100644 --- a/inc/Abilities/Analytics/BingWebmasterAbilities.php +++ b/inc/Abilities/Analytics/BingWebmasterAbilities.php @@ -77,7 +77,7 @@ private function registerAbilities(): void { array( 'label' => 'Bing Webmaster Tools', 'description' => 'Fetch search analytics data from Bing Webmaster Tools API', - 'category' => 'datamachine', + 'category' => 'datamachine/analytics', 'input_schema' => array( 'type' => 'object', 'required' => array( 'action' ), diff --git a/inc/Abilities/Analytics/GoogleAnalyticsAbilities.php b/inc/Abilities/Analytics/GoogleAnalyticsAbilities.php index a1244eb90..0116893c4 100644 --- a/inc/Abilities/Analytics/GoogleAnalyticsAbilities.php +++ b/inc/Abilities/Analytics/GoogleAnalyticsAbilities.php @@ -123,7 +123,7 @@ private function registerAbilities(): void { array( 'label' => 'Google Analytics', 'description' => 'Fetch visitor analytics data from Google Analytics (GA4) Data API', - 'category' => 'datamachine', + 'category' => 'datamachine/analytics', 'input_schema' => array( 'type' => 'object', 'required' => array( 'action' ), diff --git a/inc/Abilities/Analytics/GoogleSearchConsoleAbilities.php b/inc/Abilities/Analytics/GoogleSearchConsoleAbilities.php index 58372c9e7..d8a36a986 100644 --- a/inc/Abilities/Analytics/GoogleSearchConsoleAbilities.php +++ b/inc/Abilities/Analytics/GoogleSearchConsoleAbilities.php @@ -80,7 +80,7 @@ private function registerAbilities(): void { array( 'label' => 'Google Search Console', 'description' => 'Fetch search analytics data from Google Search Console API', - 'category' => 'datamachine', + 'category' => 'datamachine/analytics', 'input_schema' => array( 'type' => 'object', 'required' => array( 'action' ), diff --git a/inc/Abilities/Analytics/PageSpeedAbilities.php b/inc/Abilities/Analytics/PageSpeedAbilities.php index 92f1419ca..9a1391ae9 100644 --- a/inc/Abilities/Analytics/PageSpeedAbilities.php +++ b/inc/Abilities/Analytics/PageSpeedAbilities.php @@ -87,7 +87,7 @@ private function registerAbilities(): void { array( 'label' => 'PageSpeed Insights', 'description' => 'Run Lighthouse audits via PageSpeed Insights API for performance, accessibility, SEO, and best practices scores', - 'category' => 'datamachine', + 'category' => 'datamachine/analytics', 'input_schema' => array( 'type' => 'object', 'required' => array( 'action' ), diff --git a/inc/Abilities/AuthAbilities.php b/inc/Abilities/AuthAbilities.php index 516d85a2a..7caa54aa9 100644 --- a/inc/Abilities/AuthAbilities.php +++ b/inc/Abilities/AuthAbilities.php @@ -197,7 +197,7 @@ private function registerGetAuthStatus(): void { array( 'label' => __( 'Get Auth Status', 'data-machine' ), 'description' => __( 'Get OAuth/authentication status for a handler including authorization URL if applicable.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/auth', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug' ), @@ -234,7 +234,7 @@ private function registerDisconnectAuth(): void { array( 'label' => __( 'Disconnect Auth', 'data-machine' ), 'description' => __( 'Disconnect/revoke authentication for a handler.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/auth', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug' ), @@ -266,7 +266,7 @@ private function registerSaveAuthConfig(): void { array( 'label' => __( 'Save Auth Config', 'data-machine' ), 'description' => __( 'Save authentication configuration for a handler.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/auth', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug' ), @@ -302,7 +302,7 @@ private function registerSetAuthToken(): void { array( 'label' => __( 'Set Auth Token', 'data-machine' ), 'description' => __( 'Manually set authentication token and account data for a handler. Used for migration, CI, and headless auth setup.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/auth', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug', 'account_data' ), @@ -338,7 +338,7 @@ private function registerRefreshAuth(): void { array( 'label' => __( 'Refresh Auth Token', 'data-machine' ), 'description' => __( 'Force a token refresh for an OAuth2 handler. Only works for providers that support token refresh.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/auth', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug' ), @@ -371,7 +371,7 @@ private function registerListProviders(): void { array( 'label' => __( 'List Auth Providers', 'data-machine' ), 'description' => __( 'List all registered authentication providers with status, config fields, and account details.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/auth', 'input_schema' => array( 'type' => 'object', 'properties' => array(), diff --git a/inc/Abilities/Chat/CreateChatSessionAbility.php b/inc/Abilities/Chat/CreateChatSessionAbility.php index 9ec15b74f..a5a983537 100644 --- a/inc/Abilities/Chat/CreateChatSessionAbility.php +++ b/inc/Abilities/Chat/CreateChatSessionAbility.php @@ -37,7 +37,7 @@ private function registerAbility(): void { array( 'label' => __( 'Create Chat Session', 'data-machine' ), 'description' => __( 'Create a new chat session for a user.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/chat', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Chat/DeleteChatSessionAbility.php b/inc/Abilities/Chat/DeleteChatSessionAbility.php index 82883c563..08eb6ef6a 100644 --- a/inc/Abilities/Chat/DeleteChatSessionAbility.php +++ b/inc/Abilities/Chat/DeleteChatSessionAbility.php @@ -36,7 +36,7 @@ private function registerAbility(): void { array( 'label' => __( 'Delete Chat Session', 'data-machine' ), 'description' => __( 'Delete a chat session after verifying ownership.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/chat', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Chat/GetChatSessionAbility.php b/inc/Abilities/Chat/GetChatSessionAbility.php index d1476b168..515094f69 100644 --- a/inc/Abilities/Chat/GetChatSessionAbility.php +++ b/inc/Abilities/Chat/GetChatSessionAbility.php @@ -37,7 +37,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Chat Session', 'data-machine' ), 'description' => __( 'Retrieve a chat session with conversation and metadata.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/chat', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Chat/ListChatSessionsAbility.php b/inc/Abilities/Chat/ListChatSessionsAbility.php index 25c6e962a..3ceea8371 100644 --- a/inc/Abilities/Chat/ListChatSessionsAbility.php +++ b/inc/Abilities/Chat/ListChatSessionsAbility.php @@ -36,7 +36,7 @@ private function registerAbility(): void { array( 'label' => __( 'List Chat Sessions', 'data-machine' ), 'description' => __( 'List chat sessions for a user with pagination and context filtering.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/chat', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Chat/MarkSessionReadAbility.php b/inc/Abilities/Chat/MarkSessionReadAbility.php index 81beb28f0..eaa0178f2 100644 --- a/inc/Abilities/Chat/MarkSessionReadAbility.php +++ b/inc/Abilities/Chat/MarkSessionReadAbility.php @@ -38,7 +38,7 @@ private function registerAbility(): void { array( 'label' => __( 'Mark Session Read', 'data-machine' ), 'description' => __( 'Mark a chat session as read up to the current timestamp.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/chat', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Chat/SendMessageAbility.php b/inc/Abilities/Chat/SendMessageAbility.php index 0a1d5e893..2f583aa8d 100644 --- a/inc/Abilities/Chat/SendMessageAbility.php +++ b/inc/Abilities/Chat/SendMessageAbility.php @@ -42,7 +42,7 @@ private function registerAbility(): void { array( 'label' => __( 'Send Message', 'data-machine' ), 'description' => __( 'Send a user message to an AI agent and get a response. Creates a session if needed.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/chat', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Content/EditPostBlocksAbility.php b/inc/Abilities/Content/EditPostBlocksAbility.php index 377dace87..029816626 100644 --- a/inc/Abilities/Content/EditPostBlocksAbility.php +++ b/inc/Abilities/Content/EditPostBlocksAbility.php @@ -37,7 +37,7 @@ private function registerAbility(): void { array( 'label' => __( 'Edit Post Blocks', 'data-machine' ), 'description' => __( 'Surgical find/replace within specific Gutenberg blocks by index', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/content', 'input_schema' => array( 'type' => 'object', 'required' => array( 'post_id', 'edits' ), @@ -108,6 +108,7 @@ function ( $tools ) { $tools['edit_post_blocks'] = array( '_callable' => array( self::class, 'getChatTool' ), 'contexts' => array( 'chat' ), + 'ability' => 'datamachine/edit-post-blocks', ); return $tools; } diff --git a/inc/Abilities/Content/GetPostBlocksAbility.php b/inc/Abilities/Content/GetPostBlocksAbility.php index 981e81017..a63a53a0c 100644 --- a/inc/Abilities/Content/GetPostBlocksAbility.php +++ b/inc/Abilities/Content/GetPostBlocksAbility.php @@ -37,7 +37,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Post Blocks', 'data-machine' ), 'description' => __( 'Parse a post into Gutenberg blocks with optional filtering by type or content', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/content', 'input_schema' => array( 'type' => 'object', 'required' => array( 'post_id' ), @@ -98,6 +98,7 @@ function ( $tools ) { $tools['get_post_blocks'] = array( '_callable' => array( self::class, 'getChatTool' ), 'contexts' => array( 'chat' ), + 'ability' => 'datamachine/get-post-blocks', ); return $tools; } diff --git a/inc/Abilities/Content/InsertContentAbility.php b/inc/Abilities/Content/InsertContentAbility.php index 89a0695f4..725df3e37 100644 --- a/inc/Abilities/Content/InsertContentAbility.php +++ b/inc/Abilities/Content/InsertContentAbility.php @@ -39,7 +39,7 @@ private function register_ability(): void { wp_register_ability( 'datamachine/insert-content', array( 'label' => 'Insert Content', 'description' => 'Insert new content at a specific position in a post (beginning, end, or after a paragraph).', - 'category' => 'datamachine', + 'category' => 'datamachine/content', 'input_schema' => array( 'type' => 'object', 'required' => array( 'post_id', 'content', 'position' ), @@ -94,6 +94,7 @@ function ( $tools ) { $tools['insert_content'] = array( '_callable' => array( self::class, 'getChatTool' ), 'contexts' => array( 'chat', 'pipeline', 'system', 'editor' ), + 'ability' => 'datamachine/insert-content', ); return $tools; } diff --git a/inc/Abilities/Content/ReplacePostBlocksAbility.php b/inc/Abilities/Content/ReplacePostBlocksAbility.php index 1e0fb75cd..9b56be161 100644 --- a/inc/Abilities/Content/ReplacePostBlocksAbility.php +++ b/inc/Abilities/Content/ReplacePostBlocksAbility.php @@ -36,7 +36,7 @@ private function registerAbility(): void { array( 'label' => __( 'Replace Post Blocks', 'data-machine' ), 'description' => __( 'Replace entire block content by index. Use for AI-rewritten paragraphs.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/content', 'input_schema' => array( 'type' => 'object', 'required' => array( 'post_id', 'replacements' ), @@ -103,6 +103,7 @@ function ( $tools ) { $tools['replace_post_blocks'] = array( '_callable' => array( self::class, 'getChatTool' ), 'contexts' => array( 'chat' ), + 'ability' => 'datamachine/replace-post-blocks', ); return $tools; } diff --git a/inc/Abilities/Content/ResolveDiffAbility.php b/inc/Abilities/Content/ResolveDiffAbility.php index cb8078c41..4a4b50d00 100644 --- a/inc/Abilities/Content/ResolveDiffAbility.php +++ b/inc/Abilities/Content/ResolveDiffAbility.php @@ -41,7 +41,7 @@ private function register_ability(): void { wp_register_ability( 'datamachine/resolve-diff', array( 'label' => __( 'Resolve Diff', 'data-machine' ), 'description' => __( 'Accept or reject a pending content diff.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/content', 'input_schema' => array( 'type' => 'object', 'required' => array( 'diff_id', 'decision' ), diff --git a/inc/Abilities/DailyMemoryAbilities.php b/inc/Abilities/DailyMemoryAbilities.php index 75cf3474f..68c903f0e 100644 --- a/inc/Abilities/DailyMemoryAbilities.php +++ b/inc/Abilities/DailyMemoryAbilities.php @@ -87,7 +87,7 @@ private function registerAbilities(): void { array( 'label' => 'Read Daily Memory', 'description' => 'Read a daily memory file by date. Defaults to today if no date provided.', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -122,7 +122,7 @@ private function registerAbilities(): void { array( 'label' => 'Write Daily Memory', 'description' => 'Write or append to a daily memory file. Use mode "append" to add without replacing.', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -165,7 +165,7 @@ private function registerAbilities(): void { array( 'label' => 'List Daily Memory Files', 'description' => 'List all daily memory files grouped by month', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -197,7 +197,7 @@ private function registerAbilities(): void { array( 'label' => 'Search Daily Memory', 'description' => 'Search across daily memory files with optional date range. Returns matching lines with context.', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'query' ), @@ -252,7 +252,7 @@ private function registerAbilities(): void { array( 'label' => 'Delete Daily Memory', 'description' => 'Delete a daily memory file by date.', - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/DuplicateCheck/DuplicateCheckAbility.php b/inc/Abilities/DuplicateCheck/DuplicateCheckAbility.php index 891623445..e36f0ef4d 100644 --- a/inc/Abilities/DuplicateCheck/DuplicateCheckAbility.php +++ b/inc/Abilities/DuplicateCheck/DuplicateCheckAbility.php @@ -66,7 +66,7 @@ private function registerCheckDuplicate(): void { array( 'label' => __( 'Check Duplicate', 'data-machine' ), 'description' => __( 'Check if similar content already exists as a published post, in a queue, or via extension-registered strategies. Returns match details or clear verdict.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'title' ), @@ -236,7 +236,7 @@ private function registerTitlesMatch(): void { array( 'label' => __( 'Titles Match', 'data-machine' ), 'description' => __( 'Compare two titles for semantic equivalence using the unified similarity engine. Returns match result with score and strategy.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'title1', 'title2' ), diff --git a/inc/Abilities/Email/EmailAbilities.php b/inc/Abilities/Email/EmailAbilities.php index 2802ae05c..ce04ff0bb 100644 --- a/inc/Abilities/Email/EmailAbilities.php +++ b/inc/Abilities/Email/EmailAbilities.php @@ -42,7 +42,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Reply to Email', 'data-machine' ), 'description' => __( 'Send a reply to an email, maintaining thread headers', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'to', 'subject', 'body', 'in_reply_to' ), @@ -99,7 +99,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Delete Email', 'data-machine' ), 'description' => __( 'Delete (expunge) an email by UID from the IMAP server', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'uid' ), @@ -134,7 +134,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Move Email', 'data-machine' ), 'description' => __( 'Move an email to a different IMAP folder', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'uid', 'destination' ), @@ -173,7 +173,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Flag Email', 'data-machine' ), 'description' => __( 'Set or clear IMAP flags on an email (Seen, Flagged, etc.)', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'uid', 'flag' ), @@ -217,7 +217,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Batch Move Emails', 'data-machine' ), 'description' => __( 'Move all emails matching a search to a destination folder', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'search', 'destination' ), @@ -263,7 +263,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Batch Flag Emails', 'data-machine' ), 'description' => __( 'Set or clear a flag on all emails matching a search', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'search', 'flag' ), @@ -313,7 +313,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Batch Delete Emails', 'data-machine' ), 'description' => __( 'Delete all emails matching a search', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'search' ), @@ -355,7 +355,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Unsubscribe from Email', 'data-machine' ), 'description' => __( 'Unsubscribe from a mailing list using List-Unsubscribe headers', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'uid' ), @@ -391,7 +391,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Batch Unsubscribe', 'data-machine' ), 'description' => __( 'Unsubscribe from all mailing lists matching a search', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'required' => array( 'search' ), @@ -434,7 +434,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Test Email Connection', 'data-machine' ), 'description' => __( 'Test IMAP connection with stored credentials', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/email', 'input_schema' => array( 'type' => 'object', 'properties' => new \stdClass(), diff --git a/inc/Abilities/Engine/ExecuteStepAbility.php b/inc/Abilities/Engine/ExecuteStepAbility.php index 37767fd0d..ab0fc6ab0 100644 --- a/inc/Abilities/Engine/ExecuteStepAbility.php +++ b/inc/Abilities/Engine/ExecuteStepAbility.php @@ -47,7 +47,7 @@ private function registerAbility(): void { array( 'label' => __( 'Execute Step', 'data-machine' ), 'description' => __( 'Execute a single pipeline step. Resolves config, runs the step, routes to next step or completion.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'required' => array( 'job_id', 'flow_step_id' ), diff --git a/inc/Abilities/Engine/RunFlowAbility.php b/inc/Abilities/Engine/RunFlowAbility.php index 5c39a1640..154ac3c95 100644 --- a/inc/Abilities/Engine/RunFlowAbility.php +++ b/inc/Abilities/Engine/RunFlowAbility.php @@ -40,7 +40,7 @@ private function registerAbility(): void { array( 'label' => __( 'Run Flow', 'data-machine' ), 'description' => __( 'Execute a flow immediately. Loads configs, creates job if needed, schedules first step.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), diff --git a/inc/Abilities/Engine/ScheduleFlowAbility.php b/inc/Abilities/Engine/ScheduleFlowAbility.php index 57e5b3268..114eb8be5 100644 --- a/inc/Abilities/Engine/ScheduleFlowAbility.php +++ b/inc/Abilities/Engine/ScheduleFlowAbility.php @@ -40,7 +40,7 @@ private function registerAbility(): void { array( 'label' => __( 'Schedule Flow', 'data-machine' ), 'description' => __( 'Schedule flow execution: manual (clear), one-time timestamp, or recurring interval.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'interval_or_timestamp' ), diff --git a/inc/Abilities/Engine/ScheduleNextStepAbility.php b/inc/Abilities/Engine/ScheduleNextStepAbility.php index ad57516f0..3219c782f 100644 --- a/inc/Abilities/Engine/ScheduleNextStepAbility.php +++ b/inc/Abilities/Engine/ScheduleNextStepAbility.php @@ -42,7 +42,7 @@ private function registerAbility(): void { array( 'label' => __( 'Schedule Next Step', 'data-machine' ), 'description' => __( 'Store data packets and schedule the next pipeline step via Action Scheduler.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'required' => array( 'job_id', 'flow_step_id' ), diff --git a/inc/Abilities/Fetch/FetchEmailAbility.php b/inc/Abilities/Fetch/FetchEmailAbility.php index 800e90b23..9d03025fb 100644 --- a/inc/Abilities/Fetch/FetchEmailAbility.php +++ b/inc/Abilities/Fetch/FetchEmailAbility.php @@ -46,7 +46,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Fetch Emails', 'data-machine' ), 'description' => __( 'Retrieve emails from an IMAP inbox', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/fetch', 'input_schema' => array( 'type' => 'object', 'required' => array( 'imap_host', 'imap_user', 'imap_password' ), diff --git a/inc/Abilities/Fetch/FetchFilesAbility.php b/inc/Abilities/Fetch/FetchFilesAbility.php index d947f4cd5..83b4d7fe1 100644 --- a/inc/Abilities/Fetch/FetchFilesAbility.php +++ b/inc/Abilities/Fetch/FetchFilesAbility.php @@ -39,7 +39,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Fetch Files', 'data-machine' ), 'description' => __( 'Fetch files from the file repository with deduplication support', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/fetch', 'input_schema' => array( 'type' => 'object', 'required' => array( 'file_context' ), diff --git a/inc/Abilities/Fetch/FetchRssAbility.php b/inc/Abilities/Fetch/FetchRssAbility.php index 13c51f895..1d36ea7b3 100644 --- a/inc/Abilities/Fetch/FetchRssAbility.php +++ b/inc/Abilities/Fetch/FetchRssAbility.php @@ -38,7 +38,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Fetch RSS Feed', 'data-machine' ), 'description' => __( 'Fetch and parse RSS/Atom feeds with filtering', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/fetch', 'input_schema' => array( 'type' => 'object', 'required' => array( 'feed_url' ), diff --git a/inc/Abilities/Fetch/FetchWordPressApiAbility.php b/inc/Abilities/Fetch/FetchWordPressApiAbility.php index 4feae750f..5919fa032 100644 --- a/inc/Abilities/Fetch/FetchWordPressApiAbility.php +++ b/inc/Abilities/Fetch/FetchWordPressApiAbility.php @@ -39,7 +39,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Fetch WordPress REST API', 'data-machine' ), 'description' => __( 'Fetch posts from external WordPress sites via REST API', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/fetch', 'input_schema' => array( 'type' => 'object', 'required' => array( 'endpoint_url' ), diff --git a/inc/Abilities/Fetch/FetchWordPressMediaAbility.php b/inc/Abilities/Fetch/FetchWordPressMediaAbility.php index bc430fddd..1a7de2c72 100644 --- a/inc/Abilities/Fetch/FetchWordPressMediaAbility.php +++ b/inc/Abilities/Fetch/FetchWordPressMediaAbility.php @@ -38,7 +38,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Fetch WordPress Media', 'data-machine' ), 'description' => __( 'Fetch media attachments from WordPress media library with filtering', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/fetch', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Fetch/GetWordPressPostAbility.php b/inc/Abilities/Fetch/GetWordPressPostAbility.php index 85f4474a9..df9d72604 100644 --- a/inc/Abilities/Fetch/GetWordPressPostAbility.php +++ b/inc/Abilities/Fetch/GetWordPressPostAbility.php @@ -38,7 +38,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Get WordPress Post', 'data-machine' ), 'description' => __( 'Retrieve a single WordPress post by ID or URL with optional metadata', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/fetch', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Fetch/QueryWordPressPostsAbility.php b/inc/Abilities/Fetch/QueryWordPressPostsAbility.php index 5e2cb6deb..e148f6e22 100644 --- a/inc/Abilities/Fetch/QueryWordPressPostsAbility.php +++ b/inc/Abilities/Fetch/QueryWordPressPostsAbility.php @@ -38,7 +38,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Query WordPress Posts', 'data-machine' ), 'description' => __( 'Query WordPress posts with filtering for pipeline data fetching', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/fetch', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/File/AgentFileAbilities.php b/inc/Abilities/File/AgentFileAbilities.php index cd7ab6298..26785d7af 100644 --- a/inc/Abilities/File/AgentFileAbilities.php +++ b/inc/Abilities/File/AgentFileAbilities.php @@ -67,7 +67,7 @@ private function registerListAgentFiles(): void { array( 'label' => __( 'List Agent Files', 'data-machine' ), 'description' => __( 'List memory files from all layers (shared, agent, user).', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -99,7 +99,7 @@ private function registerGetAgentFile(): void { array( 'label' => __( 'Get Agent File', 'data-machine' ), 'description' => __( 'Get a single agent memory file with content.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'filename' ), @@ -136,7 +136,7 @@ private function registerWriteAgentFile(): void { array( 'label' => __( 'Write Agent File', 'data-machine' ), 'description' => __( 'Write or update content for a memory file. Layer is resolved from the registry, or can be explicitly specified.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'filename', 'content' ), @@ -183,7 +183,7 @@ private function registerDeleteAgentFile(): void { array( 'label' => __( 'Delete Agent File', 'data-machine' ), 'description' => __( 'Delete a memory file. Protected files cannot be deleted.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'filename' ), @@ -220,7 +220,7 @@ private function registerUploadAgentFile(): void { array( 'label' => __( 'Upload Agent File', 'data-machine' ), 'description' => __( 'Upload a file to a memory layer directory.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'file_data' ), diff --git a/inc/Abilities/File/FlowFileAbilities.php b/inc/Abilities/File/FlowFileAbilities.php index 9f48c4082..ee4428b50 100644 --- a/inc/Abilities/File/FlowFileAbilities.php +++ b/inc/Abilities/File/FlowFileAbilities.php @@ -69,7 +69,7 @@ private function registerListFlowFiles(): void { array( 'label' => __( 'List Flow Files', 'data-machine' ), 'description' => __( 'List uploaded files for a flow step.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_step_id' ), @@ -101,7 +101,7 @@ private function registerGetFlowFile(): void { array( 'label' => __( 'Get Flow File', 'data-machine' ), 'description' => __( 'Get metadata for a single flow file.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'filename', 'flow_step_id' ), @@ -137,7 +137,7 @@ private function registerDeleteFlowFile(): void { array( 'label' => __( 'Delete Flow File', 'data-machine' ), 'description' => __( 'Delete an uploaded file from a flow step.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'filename', 'flow_step_id' ), @@ -173,7 +173,7 @@ private function registerUploadFlowFile(): void { array( 'label' => __( 'Upload Flow File', 'data-machine' ), 'description' => __( 'Upload a file to a flow step.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'required' => array( 'file_data', 'flow_step_id' ), @@ -216,7 +216,7 @@ private function registerCleanupFlowFiles(): void { array( 'label' => __( 'Cleanup Flow Files', 'data-machine' ), 'description' => __( 'Cleanup data packets and temporary files for a job or flow.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/File/ScaffoldAbilities.php b/inc/Abilities/File/ScaffoldAbilities.php index 6f2e4988f..eeef180af 100644 --- a/inc/Abilities/File/ScaffoldAbilities.php +++ b/inc/Abilities/File/ScaffoldAbilities.php @@ -61,7 +61,7 @@ private function registerScaffoldMemoryFile(): void { array( 'label' => __( 'Scaffold Memory File', 'data-machine' ), 'description' => __( 'Create a missing memory file with default content generated from context. Never overwrites existing files. Supports registered files (USER.md, SOUL.md, etc.) and dynamic files (daily memory).', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/memory', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Flow/CreateFlowAbility.php b/inc/Abilities/Flow/CreateFlowAbility.php index ad5b0037e..433a87f05 100644 --- a/inc/Abilities/Flow/CreateFlowAbility.php +++ b/inc/Abilities/Flow/CreateFlowAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Create Flow', 'data-machine' ), 'description' => __( 'Create a new flow for a pipeline. Supports bulk mode via flows array.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Flow/DeleteFlowAbility.php b/inc/Abilities/Flow/DeleteFlowAbility.php index 4a9712744..559a220e1 100644 --- a/inc/Abilities/Flow/DeleteFlowAbility.php +++ b/inc/Abilities/Flow/DeleteFlowAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Delete Flow', 'data-machine' ), 'description' => __( 'Delete a flow and unschedule its actions.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), diff --git a/inc/Abilities/Flow/DuplicateFlowAbility.php b/inc/Abilities/Flow/DuplicateFlowAbility.php index 577ec566c..2deddfd0f 100644 --- a/inc/Abilities/Flow/DuplicateFlowAbility.php +++ b/inc/Abilities/Flow/DuplicateFlowAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Duplicate Flow', 'data-machine' ), 'description' => __( 'Duplicate a flow, optionally to a different pipeline.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'source_flow_id' ), diff --git a/inc/Abilities/Flow/GetFlowsAbility.php b/inc/Abilities/Flow/GetFlowsAbility.php index 307332873..0466a428b 100644 --- a/inc/Abilities/Flow/GetFlowsAbility.php +++ b/inc/Abilities/Flow/GetFlowsAbility.php @@ -38,7 +38,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Flows', 'data-machine' ), 'description' => __( 'Get flows with optional filtering by pipeline ID or handler slug. Supports single flow retrieval and flexible output modes.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Flow/PauseFlowAbility.php b/inc/Abilities/Flow/PauseFlowAbility.php index 577ad7149..2d3fe7319 100644 --- a/inc/Abilities/Flow/PauseFlowAbility.php +++ b/inc/Abilities/Flow/PauseFlowAbility.php @@ -42,7 +42,7 @@ private function registerAbility(): void { array( 'label' => __( 'Pause Flow', 'data-machine' ), 'description' => __( 'Pause one or more flows. Preserves schedule for later resume.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Flow/QueueAbility.php b/inc/Abilities/Flow/QueueAbility.php index bab09fee6..d35a702b6 100644 --- a/inc/Abilities/Flow/QueueAbility.php +++ b/inc/Abilities/Flow/QueueAbility.php @@ -60,7 +60,7 @@ private function registerQueueAdd(): void { array( 'label' => __( 'Add to Queue', 'data-machine' ), 'description' => __( 'Add a prompt to the flow queue.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'flow_step_id', 'prompt' ), @@ -118,7 +118,7 @@ private function registerQueueList(): void { array( 'label' => __( 'List Queue', 'data-machine' ), 'description' => __( 'List all prompts in the flow queue.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'flow_step_id' ), @@ -161,7 +161,7 @@ private function registerQueueClear(): void { array( 'label' => __( 'Clear Queue', 'data-machine' ), 'description' => __( 'Clear all prompts from the flow queue.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'flow_step_id' ), @@ -203,7 +203,7 @@ private function registerQueueRemove(): void { array( 'label' => __( 'Remove from Queue', 'data-machine' ), 'description' => __( 'Remove a specific prompt from the queue by index.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'flow_step_id', 'index' ), @@ -249,7 +249,7 @@ private function registerQueueUpdate(): void { array( 'label' => __( 'Update Queue Item', 'data-machine' ), 'description' => __( 'Update a prompt at a specific index in the flow queue.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'flow_step_id', 'index', 'prompt' ), @@ -300,7 +300,7 @@ private function registerQueueMove(): void { array( 'label' => __( 'Move Queue Item', 'data-machine' ), 'description' => __( 'Move a prompt from one position to another in the queue.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'flow_step_id', 'from_index', 'to_index' ), @@ -352,7 +352,7 @@ private function registerQueueSettings(): void { array( 'label' => __( 'Update Queue Settings', 'data-machine' ), 'description' => __( 'Update queue settings for a flow step.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'flow_step_id', 'queue_enabled' ), diff --git a/inc/Abilities/Flow/ResumeFlowAbility.php b/inc/Abilities/Flow/ResumeFlowAbility.php index b04cfd72a..207ec11e2 100644 --- a/inc/Abilities/Flow/ResumeFlowAbility.php +++ b/inc/Abilities/Flow/ResumeFlowAbility.php @@ -41,7 +41,7 @@ private function registerAbility(): void { array( 'label' => __( 'Resume Flow', 'data-machine' ), 'description' => __( 'Resume one or more paused flows. Re-registers schedules.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Flow/UpdateFlowAbility.php b/inc/Abilities/Flow/UpdateFlowAbility.php index d62ced806..ccba4ab64 100644 --- a/inc/Abilities/Flow/UpdateFlowAbility.php +++ b/inc/Abilities/Flow/UpdateFlowAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Update Flow', 'data-machine' ), 'description' => __( 'Update flow name or scheduling.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), diff --git a/inc/Abilities/Flow/WebhookTriggerAbility.php b/inc/Abilities/Flow/WebhookTriggerAbility.php index 1d5d25dfc..82ce933f7 100644 --- a/inc/Abilities/Flow/WebhookTriggerAbility.php +++ b/inc/Abilities/Flow/WebhookTriggerAbility.php @@ -47,7 +47,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Enable Webhook Trigger', 'data-machine' ), 'description' => __( 'Enable webhook trigger for a flow and generate a Bearer token. External services can POST to the trigger URL to start flow executions.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), @@ -80,7 +80,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Disable Webhook Trigger', 'data-machine' ), 'description' => __( 'Disable webhook trigger for a flow. Revokes the token and stops accepting inbound webhooks.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), @@ -111,7 +111,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Regenerate Webhook Token', 'data-machine' ), 'description' => __( 'Regenerate the webhook trigger token for a flow. The old token is immediately invalidated.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), @@ -144,7 +144,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Configure Webhook Rate Limit', 'data-machine' ), 'description' => __( 'Set rate limiting for a flow webhook trigger. Limits the number of requests per time window.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), @@ -190,7 +190,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Webhook Trigger Status', 'data-machine' ), 'description' => __( 'Get the webhook trigger status for a flow, including URL and whether it is enabled.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), diff --git a/inc/Abilities/FlowAbilities.php b/inc/Abilities/FlowAbilities.php index 87fc7df4e..1919ff05d 100644 --- a/inc/Abilities/FlowAbilities.php +++ b/inc/Abilities/FlowAbilities.php @@ -44,8 +44,6 @@ public function __construct() { return; } - $this->registerCategory(); - $this->queue = new QueueAbility(); $this->get_flows = new GetFlowsAbility(); $this->create_flow = new CreateFlowAbility(); @@ -59,27 +57,6 @@ public function __construct() { self::$registered = true; } - /** - * Register the datamachine ability category. - */ - private function registerCategory(): void { - $category_callback = function () { - wp_register_ability_category( - 'datamachine', - array( - 'label' => __( 'Data Machine', 'data-machine' ), - 'description' => __( 'Data Machine flow and pipeline operations', 'data-machine' ), - ) - ); - }; - - if ( did_action( 'wp_abilities_api_categories_init' ) ) { - $category_callback(); - } else { - add_action( 'wp_abilities_api_categories_init', $category_callback ); - } - } - /** * Permission callback for abilities. * diff --git a/inc/Abilities/FlowStep/ConfigureFlowStepsAbility.php b/inc/Abilities/FlowStep/ConfigureFlowStepsAbility.php index 7908a3933..8a0549b34 100644 --- a/inc/Abilities/FlowStep/ConfigureFlowStepsAbility.php +++ b/inc/Abilities/FlowStep/ConfigureFlowStepsAbility.php @@ -34,7 +34,7 @@ private function registerAbility(): void { array( 'label' => __( 'Configure Flow Steps', 'data-machine' ), 'description' => __( 'Bulk configure flow steps across a pipeline or globally. Supports handler switching with field mapping.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/FlowStep/GetFlowStepsAbility.php b/inc/Abilities/FlowStep/GetFlowStepsAbility.php index 2cf2100ce..07059c778 100644 --- a/inc/Abilities/FlowStep/GetFlowStepsAbility.php +++ b/inc/Abilities/FlowStep/GetFlowStepsAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Flow Steps', 'data-machine' ), 'description' => __( 'Get all step configurations for a flow, or a single step by ID.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/FlowStep/UpdateFlowStepAbility.php b/inc/Abilities/FlowStep/UpdateFlowStepAbility.php index d8ce47841..0070bd963 100644 --- a/inc/Abilities/FlowStep/UpdateFlowStepAbility.php +++ b/inc/Abilities/FlowStep/UpdateFlowStepAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Update Flow Step', 'data-machine' ), 'description' => __( 'Update a single flow step handler configuration or user message.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_step_id' ), diff --git a/inc/Abilities/FlowStep/ValidateFlowStepsConfigAbility.php b/inc/Abilities/FlowStep/ValidateFlowStepsConfigAbility.php index d7022c6d1..1c7828e6e 100644 --- a/inc/Abilities/FlowStep/ValidateFlowStepsConfigAbility.php +++ b/inc/Abilities/FlowStep/ValidateFlowStepsConfigAbility.php @@ -34,7 +34,7 @@ private function registerAbility(): void { array( 'label' => __( 'Validate Flow Steps Config', 'data-machine' ), 'description' => __( 'Dry-run validation for configure_flow_steps operations. Validates without executing.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/flow', 'input_schema' => array( 'type' => 'object', 'required' => array( 'pipeline_id' ), diff --git a/inc/Abilities/Handler/TestHandlerAbility.php b/inc/Abilities/Handler/TestHandlerAbility.php index 97b9a588f..cfd81032d 100644 --- a/inc/Abilities/Handler/TestHandlerAbility.php +++ b/inc/Abilities/Handler/TestHandlerAbility.php @@ -42,7 +42,7 @@ private function registerAbility(): void { array( 'label' => __( 'Test Handler', 'data-machine' ), 'description' => __( 'Dry-run any fetch handler with a config and return packet summaries.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/HandlerAbilities.php b/inc/Abilities/HandlerAbilities.php index 14e895b97..daf4d437f 100644 --- a/inc/Abilities/HandlerAbilities.php +++ b/inc/Abilities/HandlerAbilities.php @@ -98,7 +98,7 @@ private function registerGetHandlersAbility(): void { array( 'label' => __( 'Get Handlers', 'data-machine' ), 'description' => __( 'Get all registered handlers, optionally filtered by step type, or a single handler by slug.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -135,7 +135,7 @@ private function registerValidateHandlerAbility(): void { array( 'label' => __( 'Validate Handler', 'data-machine' ), 'description' => __( 'Validate that a handler slug exists.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug' ), @@ -171,7 +171,7 @@ private function registerGetHandlerConfigFieldsAbility(): void { array( 'label' => __( 'Get Handler Config Fields', 'data-machine' ), 'description' => __( 'Get configuration field definitions for a handler.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug' ), @@ -204,7 +204,7 @@ private function registerApplyHandlerDefaultsAbility(): void { array( 'label' => __( 'Apply Handler Defaults', 'data-machine' ), 'description' => __( 'Apply default values to handler configuration.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug', 'config' ), @@ -240,7 +240,7 @@ private function registerGetHandlerSiteDefaultsAbility(): void { array( 'label' => __( 'Get Handler Site Defaults', 'data-machine' ), 'description' => __( 'Get site-wide handler default configurations.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/InternalLinkingAbilities.php b/inc/Abilities/InternalLinkingAbilities.php index 15eb6fcf1..9b57dd9e1 100644 --- a/inc/Abilities/InternalLinkingAbilities.php +++ b/inc/Abilities/InternalLinkingAbilities.php @@ -59,7 +59,7 @@ private function registerAbilities(): void { array( 'label' => 'Internal Linking', 'description' => 'Queue system agent insertion of semantic internal links into posts', - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -113,7 +113,7 @@ private function registerAbilities(): void { array( 'label' => 'Diagnose Internal Links', 'description' => 'Report internal link coverage across published posts', - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array(), @@ -143,7 +143,7 @@ private function registerAbilities(): void { array( 'label' => 'Audit Internal Links', 'description' => 'Scan post content for internal links, build a link graph, and cache results. Does NOT check for broken links — use datamachine/check-broken-links for that.', - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -199,7 +199,7 @@ private function registerAbilities(): void { array( 'label' => 'Get Orphaned Posts', 'description' => 'Return posts with zero inbound internal links from the cached link graph. Runs audit automatically if no cache exists.', - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -239,7 +239,7 @@ private function registerAbilities(): void { array( 'label' => 'Check Broken Links', 'description' => 'HTTP HEAD check links from the cached link graph to find broken URLs. Supports internal, external, or all links via scope. External checks include per-domain rate limiting and HEAD→GET fallback.', - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -291,7 +291,7 @@ private function registerAbilities(): void { array( 'label' => 'Link Opportunities', 'description' => 'Rank internal linking opportunities by combining GSC traffic data with the link graph. High-traffic pages with few inbound links score highest.', - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Job/DeleteJobsAbility.php b/inc/Abilities/Job/DeleteJobsAbility.php index 4c317f840..8c13e3624 100644 --- a/inc/Abilities/Job/DeleteJobsAbility.php +++ b/inc/Abilities/Job/DeleteJobsAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Delete Jobs', 'data-machine' ), 'description' => __( 'Delete jobs by type (all or failed). Optionally cleanup processed items tracking.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'required' => array( 'type' ), diff --git a/inc/Abilities/Job/ExecuteWorkflowAbility.php b/inc/Abilities/Job/ExecuteWorkflowAbility.php index a61080b38..905c0f509 100644 --- a/inc/Abilities/Job/ExecuteWorkflowAbility.php +++ b/inc/Abilities/Job/ExecuteWorkflowAbility.php @@ -36,7 +36,7 @@ private function registerAbility(): void { array( 'label' => __( 'Execute Workflow', 'data-machine' ), 'description' => __( 'Execute an ephemeral workflow from raw JSON steps. For database flow execution, use datamachine/run-flow.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'required' => array( 'workflow' ), diff --git a/inc/Abilities/Job/FailJobAbility.php b/inc/Abilities/Job/FailJobAbility.php index 51e69b1a2..7e081ca93 100644 --- a/inc/Abilities/Job/FailJobAbility.php +++ b/inc/Abilities/Job/FailJobAbility.php @@ -36,7 +36,7 @@ private function registerAbility(): void { array( 'label' => __( 'Fail Job', 'data-machine' ), 'description' => __( 'Manually fail a processing job with an optional reason.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Job/FlowHealthAbility.php b/inc/Abilities/Job/FlowHealthAbility.php index f7619ef05..c048f0517 100644 --- a/inc/Abilities/Job/FlowHealthAbility.php +++ b/inc/Abilities/Job/FlowHealthAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Flow Health', 'data-machine' ), 'description' => __( 'Get health metrics for a flow including consecutive failures and no-items counts.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), diff --git a/inc/Abilities/Job/GetJobsAbility.php b/inc/Abilities/Job/GetJobsAbility.php index 08f53d794..b8610759d 100644 --- a/inc/Abilities/Job/GetJobsAbility.php +++ b/inc/Abilities/Job/GetJobsAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Jobs', 'data-machine' ), 'description' => __( 'List jobs with optional filtering by flow_id, pipeline_id, or status. Supports pagination, sorting, and single job lookup via job_id.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Job/JobsSummaryAbility.php b/inc/Abilities/Job/JobsSummaryAbility.php index a4c9e89cd..3f154a6ac 100644 --- a/inc/Abilities/Job/JobsSummaryAbility.php +++ b/inc/Abilities/Job/JobsSummaryAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Jobs Summary', 'data-machine' ), 'description' => __( 'Get job counts grouped by base status. Compound statuses are normalized to their base status.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'properties' => array(), diff --git a/inc/Abilities/Job/ProblemFlowsAbility.php b/inc/Abilities/Job/ProblemFlowsAbility.php index b70259b08..47a9283d8 100644 --- a/inc/Abilities/Job/ProblemFlowsAbility.php +++ b/inc/Abilities/Job/ProblemFlowsAbility.php @@ -41,7 +41,7 @@ private function registerAbility(): void { __( 'Identify flows with issues: consecutive failures (broken) or consecutive no-items runs (source exhausted). Default threshold: %d.', 'data-machine' ), $default_threshold ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Job/RecoverStuckJobsAbility.php b/inc/Abilities/Job/RecoverStuckJobsAbility.php index 9ed4195b7..95c5e6aff 100644 --- a/inc/Abilities/Job/RecoverStuckJobsAbility.php +++ b/inc/Abilities/Job/RecoverStuckJobsAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Recover Stuck Jobs', 'data-machine' ), 'description' => __( 'Recover jobs stuck in processing state: jobs with status override in engine_data, and jobs exceeding timeout threshold.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Job/RetryJobAbility.php b/inc/Abilities/Job/RetryJobAbility.php index f1eca1bb1..3a449791e 100644 --- a/inc/Abilities/Job/RetryJobAbility.php +++ b/inc/Abilities/Job/RetryJobAbility.php @@ -36,7 +36,7 @@ private function registerAbility(): void { array( 'label' => __( 'Retry Job', 'data-machine' ), 'description' => __( 'Retry a failed or stuck job by marking it failed and optionally requeuing its prompt.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/jobs', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/LocalSearchAbilities.php b/inc/Abilities/LocalSearchAbilities.php index cb8236526..46af3e8a5 100644 --- a/inc/Abilities/LocalSearchAbilities.php +++ b/inc/Abilities/LocalSearchAbilities.php @@ -42,7 +42,7 @@ private function registerAbility(): void { array( 'label' => __( 'Local Search', 'data-machine' ), 'description' => __( 'Search WordPress site for posts by title or content', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/content', 'input_schema' => array( 'type' => 'object', 'required' => array( 'query' ), diff --git a/inc/Abilities/LogAbilities.php b/inc/Abilities/LogAbilities.php index 0a3905cc6..09694f7f5 100644 --- a/inc/Abilities/LogAbilities.php +++ b/inc/Abilities/LogAbilities.php @@ -39,7 +39,7 @@ private function registerAbilities(): void { array( 'label' => 'Write to Data Machine Logs', 'description' => 'Write log entries to the database', - 'category' => 'datamachine', + 'category' => 'datamachine/logging', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -77,7 +77,7 @@ private function registerAbilities(): void { array( 'label' => 'Clear Data Machine Logs', 'description' => 'Clear log entries for a specific agent or all logs', - 'category' => 'datamachine', + 'category' => 'datamachine/logging', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -106,7 +106,7 @@ private function registerAbilities(): void { array( 'label' => 'Read Data Machine Logs', 'description' => 'Read log entries with filtering and pagination', - 'category' => 'datamachine', + 'category' => 'datamachine/logging', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -174,7 +174,7 @@ private function registerAbilities(): void { array( 'label' => 'Get Log Metadata', 'description' => 'Get log entry counts and time range', - 'category' => 'datamachine', + 'category' => 'datamachine/logging', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -205,7 +205,7 @@ private function registerAbilities(): void { array( 'label' => 'Read WordPress Debug Log', 'description' => 'Read PHP debug.log entries from wp-content/debug.log', - 'category' => 'datamachine', + 'category' => 'datamachine/logging', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Media/AltTextAbilities.php b/inc/Abilities/Media/AltTextAbilities.php index 4dd06e2af..a6350e82b 100644 --- a/inc/Abilities/Media/AltTextAbilities.php +++ b/inc/Abilities/Media/AltTextAbilities.php @@ -44,7 +44,7 @@ private function registerAbilities(): void { array( 'label' => 'Generate Alt Text', 'description' => 'Queue system agent generation of alt text for images', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -87,7 +87,7 @@ private function registerAbilities(): void { array( 'label' => 'Diagnose Alt Text', 'description' => 'Report alt text coverage for image attachments', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'properties' => array(), diff --git a/inc/Abilities/Media/ImageGenerationAbilities.php b/inc/Abilities/Media/ImageGenerationAbilities.php index e372a9a45..39e36b1f8 100644 --- a/inc/Abilities/Media/ImageGenerationAbilities.php +++ b/inc/Abilities/Media/ImageGenerationAbilities.php @@ -75,7 +75,7 @@ private function registerAbilities(): void { array( 'label' => 'Generate Image', 'description' => 'Generate an image using AI models via Replicate API', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'required' => array( 'prompt' ), diff --git a/inc/Abilities/Media/ImageOptimizationAbilities.php b/inc/Abilities/Media/ImageOptimizationAbilities.php index 6e534d2a9..16c6d71d1 100644 --- a/inc/Abilities/Media/ImageOptimizationAbilities.php +++ b/inc/Abilities/Media/ImageOptimizationAbilities.php @@ -51,7 +51,7 @@ private function registerAbilities(): void { array( 'label' => 'Diagnose Images', 'description' => 'Scan the media library for oversized images, missing WebP variants, and missing thumbnail sizes.', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -93,7 +93,7 @@ private function registerAbilities(): void { array( 'label' => 'Optimize Images', 'description' => 'Compress oversized images and generate WebP variants. Uses WordPress image editor (Imagick/GD). Batch-aware.', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Media/ImageTemplateAbilities.php b/inc/Abilities/Media/ImageTemplateAbilities.php index 581d69b7d..5f4937f81 100644 --- a/inc/Abilities/Media/ImageTemplateAbilities.php +++ b/inc/Abilities/Media/ImageTemplateAbilities.php @@ -38,7 +38,7 @@ private function registerAbilities(): void { array( 'label' => 'Render Image Template', 'description' => 'Generate branded graphics from registered GD templates', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'required' => array( 'template_id', 'data' ), @@ -90,7 +90,7 @@ private function registerAbilities(): void { array( 'label' => 'List Image Templates', 'description' => 'List all registered image generation templates', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'properties' => array(), diff --git a/inc/Abilities/Media/MediaAbilities.php b/inc/Abilities/Media/MediaAbilities.php index e11c511ed..d818cfc34 100644 --- a/inc/Abilities/Media/MediaAbilities.php +++ b/inc/Abilities/Media/MediaAbilities.php @@ -67,7 +67,7 @@ private function registerUploadMedia(): void { array( 'label' => 'Upload Media', 'description' => 'Upload or fetch a media file (image or video), store it in the repository, and return a reference (path, URL, or media ID). Automatically detects media type from MIME.', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -127,7 +127,7 @@ private function registerValidateMedia(): void { array( 'label' => 'Validate Media', 'description' => 'Validate a media file (image or video) against platform-specific constraints (duration, size, codec, aspect ratio, resolution). Auto-detects media type.', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'required' => array( 'path' ), @@ -175,7 +175,7 @@ private function registerVideoMetadata(): void { array( 'label' => 'Video Metadata', 'description' => 'Extract video metadata (duration, resolution, codec, bitrate, framerate) using ffprobe with graceful degradation', - 'category' => 'datamachine', + 'category' => 'datamachine/media', 'input_schema' => array( 'type' => 'object', 'required' => array( 'path' ), diff --git a/inc/Abilities/Pipeline/CreatePipelineAbility.php b/inc/Abilities/Pipeline/CreatePipelineAbility.php index 0ccab015c..1e61c9792 100644 --- a/inc/Abilities/Pipeline/CreatePipelineAbility.php +++ b/inc/Abilities/Pipeline/CreatePipelineAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Create Pipeline', 'data-machine' ), 'description' => __( 'Create a new pipeline with optional steps. Pass flow_config to also create a flow; omit it for pipeline-only creation. Supports bulk mode via pipelines array.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Pipeline/DeletePipelineAbility.php b/inc/Abilities/Pipeline/DeletePipelineAbility.php index a8331e0f3..796ba2be5 100644 --- a/inc/Abilities/Pipeline/DeletePipelineAbility.php +++ b/inc/Abilities/Pipeline/DeletePipelineAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Delete Pipeline', 'data-machine' ), 'description' => __( 'Delete a pipeline and all associated flows.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'pipeline_id' ), diff --git a/inc/Abilities/Pipeline/DuplicatePipelineAbility.php b/inc/Abilities/Pipeline/DuplicatePipelineAbility.php index 874f285dd..20df9e6df 100644 --- a/inc/Abilities/Pipeline/DuplicatePipelineAbility.php +++ b/inc/Abilities/Pipeline/DuplicatePipelineAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Duplicate Pipeline', 'data-machine' ), 'description' => __( 'Duplicate a pipeline with all its flows.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'pipeline_id' ), diff --git a/inc/Abilities/Pipeline/GetPipelinesAbility.php b/inc/Abilities/Pipeline/GetPipelinesAbility.php index 26b62496a..334eff386 100644 --- a/inc/Abilities/Pipeline/GetPipelinesAbility.php +++ b/inc/Abilities/Pipeline/GetPipelinesAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Pipelines', 'data-machine' ), 'description' => __( 'Get pipelines with optional pagination and filtering, or a single pipeline by ID.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Pipeline/ImportExportAbility.php b/inc/Abilities/Pipeline/ImportExportAbility.php index b66030103..08128c2bc 100644 --- a/inc/Abilities/Pipeline/ImportExportAbility.php +++ b/inc/Abilities/Pipeline/ImportExportAbility.php @@ -47,7 +47,7 @@ private function registerImportAbility(): void { array( 'label' => __( 'Import Pipelines', 'data-machine' ), 'description' => __( 'Import pipelines from CSV data.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'data' ), @@ -87,7 +87,7 @@ private function registerExportAbility(): void { array( 'label' => __( 'Export Pipelines', 'data-machine' ), 'description' => __( 'Export pipelines to CSV format.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Pipeline/UpdatePipelineAbility.php b/inc/Abilities/Pipeline/UpdatePipelineAbility.php index 1b268d097..115577a57 100644 --- a/inc/Abilities/Pipeline/UpdatePipelineAbility.php +++ b/inc/Abilities/Pipeline/UpdatePipelineAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Update Pipeline', 'data-machine' ), 'description' => __( 'Update pipeline name or configuration.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'pipeline_id' ), diff --git a/inc/Abilities/PipelineStepAbilities.php b/inc/Abilities/PipelineStepAbilities.php index da83a9f2a..15310d43b 100644 --- a/inc/Abilities/PipelineStepAbilities.php +++ b/inc/Abilities/PipelineStepAbilities.php @@ -62,7 +62,7 @@ private function registerGetPipelineStepsAbility(): void { array( 'label' => __( 'Get Pipeline Steps', 'data-machine' ), 'description' => __( 'Get all steps for a pipeline, or a single step by ID.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -103,7 +103,7 @@ private function registerAddPipelineStepAbility(): void { array( 'label' => __( 'Add Pipeline Step', 'data-machine' ), 'description' => __( 'Add a step to a pipeline. Automatically syncs to all flows on that pipeline.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'pipeline_id', 'step_type' ), @@ -149,7 +149,7 @@ private function registerUpdatePipelineStepAbility(): void { array( 'label' => __( 'Update Pipeline Step', 'data-machine' ), 'description' => __( 'Update pipeline step configuration (system prompt, disabled tools). Model/provider are configured via context_models setting.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'pipeline_step_id' ), @@ -195,7 +195,7 @@ private function registerDeletePipelineStepAbility(): void { array( 'label' => __( 'Delete Pipeline Step', 'data-machine' ), 'description' => __( 'Remove a step from a pipeline. Removes step from all flows on the pipeline.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'pipeline_id', 'pipeline_step_id' ), @@ -234,7 +234,7 @@ private function registerReorderPipelineStepsAbility(): void { array( 'label' => __( 'Reorder Pipeline Steps', 'data-machine' ), 'description' => __( 'Reorder steps within a pipeline.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'pipeline_id', 'step_order' ), diff --git a/inc/Abilities/PostQueryAbilities.php b/inc/Abilities/PostQueryAbilities.php index 4c404a71a..bc96b678a 100644 --- a/inc/Abilities/PostQueryAbilities.php +++ b/inc/Abilities/PostQueryAbilities.php @@ -60,7 +60,7 @@ private function registerAbility(): void { array( 'label' => __( 'Query Posts', 'data-machine' ), 'description' => __( 'Find posts created by Data Machine, filtered by handler, flow, or pipeline', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/content', 'input_schema' => array( 'type' => 'object', 'required' => array( 'filter_by', 'filter_value' ), @@ -116,7 +116,7 @@ private function registerAbility(): void { array( 'label' => __( 'List Posts', 'data-machine' ), 'description' => __( 'List Data Machine posts with combinable filters (handler, flow, pipeline)', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/content', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -193,6 +193,7 @@ function ( $tools ) { $tools['query_posts'] = array( '_callable' => array( $this, 'getQueryPostsTool' ), 'contexts' => array( 'chat' ), + 'ability' => 'datamachine/query-posts', ); return $tools; } diff --git a/inc/Abilities/ProcessedItemsAbilities.php b/inc/Abilities/ProcessedItemsAbilities.php index 01c90c9dd..a6696f065 100644 --- a/inc/Abilities/ProcessedItemsAbilities.php +++ b/inc/Abilities/ProcessedItemsAbilities.php @@ -62,7 +62,7 @@ private function registerClearProcessedItems(): void { array( 'label' => __( 'Clear Processed Items', 'data-machine' ), 'description' => __( 'Clear processed items tracking by pipeline or flow scope. Used to reset deduplication so items can be re-processed.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'clear_type', 'target_id' ), @@ -103,7 +103,7 @@ private function registerCheckProcessedItem(): void { array( 'label' => __( 'Check Processed Item', 'data-machine' ), 'description' => __( 'Check if a specific item has already been processed for a given flow step and source type.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_step_id', 'source_type', 'item_identifier' ), @@ -146,7 +146,7 @@ private function registerHasProcessedHistory(): void { array( 'label' => __( 'Has Processed History', 'data-machine' ), 'description' => __( 'Check if a flow step has any processed items history. Useful for distinguishing "no new items" from "first run with nothing".', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/agent', 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_step_id' ), diff --git a/inc/Abilities/Publish/PublishWordPressAbility.php b/inc/Abilities/Publish/PublishWordPressAbility.php index 7c5fe8c6f..1a8cad3e1 100644 --- a/inc/Abilities/Publish/PublishWordPressAbility.php +++ b/inc/Abilities/Publish/PublishWordPressAbility.php @@ -40,7 +40,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Publish WordPress Post', 'data-machine' ), 'description' => __( 'Create WordPress posts with taxonomy assignment and featured images', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/publishing', 'input_schema' => array( 'type' => 'object', 'required' => array( 'title', 'content', 'post_type' ), diff --git a/inc/Abilities/Publish/SendEmailAbility.php b/inc/Abilities/Publish/SendEmailAbility.php index 86998bfc9..210e59f3b 100644 --- a/inc/Abilities/Publish/SendEmailAbility.php +++ b/inc/Abilities/Publish/SendEmailAbility.php @@ -43,7 +43,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Send Email', 'data-machine' ), 'description' => __( 'Send an email with optional attachments via wp_mail()', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/publishing', 'input_schema' => array( 'type' => 'object', 'required' => array( 'to', 'subject', 'body' ), diff --git a/inc/Abilities/SEO/IndexNowAbilities.php b/inc/Abilities/SEO/IndexNowAbilities.php index 5adfb7034..2b045be9e 100644 --- a/inc/Abilities/SEO/IndexNowAbilities.php +++ b/inc/Abilities/SEO/IndexNowAbilities.php @@ -418,7 +418,7 @@ private function registerSubmitAbility(): void { array( 'label' => __( 'IndexNow Submit', 'data-machine' ), 'description' => __( 'Submit one or more URLs to IndexNow for instant search engine indexing.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'required' => array( 'urls' ), @@ -458,7 +458,7 @@ private function registerStatusAbility(): void { array( 'label' => __( 'IndexNow Status', 'data-machine' ), 'description' => __( 'Get IndexNow integration status including enabled state and API key.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array(), @@ -492,7 +492,7 @@ private function registerGenerateKeyAbility(): void { array( 'label' => __( 'IndexNow Generate Key', 'data-machine' ), 'description' => __( 'Generate a new IndexNow API key and save it to settings.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array(), @@ -524,7 +524,7 @@ private function registerVerifyKeyAbility(): void { array( 'label' => __( 'IndexNow Verify Key', 'data-machine' ), 'description' => __( 'Verify that the IndexNow key file is accessible and correct.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array(), diff --git a/inc/Abilities/SEO/MetaDescriptionAbilities.php b/inc/Abilities/SEO/MetaDescriptionAbilities.php index 8abe0dec0..3dfc536d2 100644 --- a/inc/Abilities/SEO/MetaDescriptionAbilities.php +++ b/inc/Abilities/SEO/MetaDescriptionAbilities.php @@ -44,7 +44,7 @@ private function registerAbilities(): void { array( 'label' => 'Generate Meta Description', 'description' => 'Queue system agent generation of meta descriptions (saved to post excerpt)', - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -93,7 +93,7 @@ private function registerAbilities(): void { array( 'label' => 'Diagnose Meta Descriptions', 'description' => 'Report post excerpt (meta description) coverage for posts', - 'category' => 'datamachine', + 'category' => 'datamachine/seo', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/SettingsAbilities.php b/inc/Abilities/SettingsAbilities.php index 06e43e515..c3ba3e6c9 100644 --- a/inc/Abilities/SettingsAbilities.php +++ b/inc/Abilities/SettingsAbilities.php @@ -63,7 +63,7 @@ private function registerGetSettings(): void { array( 'label' => __( 'Get Settings', 'data-machine' ), 'description' => __( 'Get all plugin settings including AI settings, enabled tools, and masked API keys.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/settings', 'input_schema' => array( 'type' => 'object', 'properties' => array(), @@ -92,7 +92,7 @@ private function registerUpdateSettings(): void { array( 'label' => __( 'Update Settings', 'data-machine' ), 'description' => __( 'Partial update of plugin settings. Only provided fields are updated.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/settings', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -156,7 +156,7 @@ private function registerGetSchedulingIntervals(): void { array( 'label' => __( 'Get Scheduling Intervals', 'data-machine' ), 'description' => __( 'Get available scheduling intervals for flow scheduling.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/settings', 'input_schema' => array( 'type' => 'object', 'properties' => array(), @@ -182,7 +182,7 @@ private function registerGetToolConfig(): void { array( 'label' => __( 'Get Tool Config', 'data-machine' ), 'description' => __( 'Get configuration for a specific tool including fields and current config values.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/settings', 'input_schema' => array( 'type' => 'object', 'required' => array( 'tool_id' ), @@ -220,7 +220,7 @@ private function registerSaveToolConfig(): void { array( 'label' => __( 'Save Tool Config', 'data-machine' ), 'description' => __( 'Save configuration for a specific tool. Fires tool-specific handler via action hook.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/settings', 'input_schema' => array( 'type' => 'object', 'required' => array( 'tool_id', 'config_data' ), @@ -257,7 +257,7 @@ private function registerGetHandlerDefaults(): void { array( 'label' => __( 'Get Handler Defaults', 'data-machine' ), 'description' => __( 'Get all handler defaults grouped by step type.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/settings', 'input_schema' => array( 'type' => 'object', 'properties' => array(), @@ -283,7 +283,7 @@ private function registerUpdateHandlerDefaults(): void { array( 'label' => __( 'Update Handler Defaults', 'data-machine' ), 'description' => __( 'Update defaults for a specific handler.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/settings', 'input_schema' => array( 'type' => 'object', 'required' => array( 'handler_slug', 'defaults' ), diff --git a/inc/Abilities/StepTypeAbilities.php b/inc/Abilities/StepTypeAbilities.php index a0778ef55..a4000c5a5 100644 --- a/inc/Abilities/StepTypeAbilities.php +++ b/inc/Abilities/StepTypeAbilities.php @@ -66,7 +66,7 @@ private function registerGetStepTypesAbility(): void { array( 'label' => __( 'Get Step Types', 'data-machine' ), 'description' => __( 'Get all registered step types, or a single step type by slug.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -98,7 +98,7 @@ private function registerValidateStepTypeAbility(): void { array( 'label' => __( 'Validate Step Type', 'data-machine' ), 'description' => __( 'Validate that a step type slug exists.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/pipeline', 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_type' ), diff --git a/inc/Abilities/SystemAbilities.php b/inc/Abilities/SystemAbilities.php index 5938dddc6..351646df6 100644 --- a/inc/Abilities/SystemAbilities.php +++ b/inc/Abilities/SystemAbilities.php @@ -60,7 +60,7 @@ private function registerSessionTitleAbility(): void { array( 'label' => 'Generate Session Title', 'description' => 'Generate an AI-powered title for a chat session based on conversation content', - 'category' => 'datamachine', + 'category' => 'datamachine/system', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -102,7 +102,7 @@ private function registerHealthCheckAbility(): void { array( 'label' => __( 'System Health Check', 'data-machine' ), 'description' => __( 'Unified health diagnostics for Data Machine and extensions', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/system', 'input_schema' => array( 'type' => 'object', 'properties' => array( @@ -299,7 +299,7 @@ private function registerRunTaskAbility(): void { array( 'label' => __( 'Run System Task', 'data-machine' ), 'description' => __( 'Manually trigger a registered system task for immediate execution.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/system', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Taxonomy/CreateTaxonomyTermAbility.php b/inc/Abilities/Taxonomy/CreateTaxonomyTermAbility.php index 1c43ed666..65f280386 100644 --- a/inc/Abilities/Taxonomy/CreateTaxonomyTermAbility.php +++ b/inc/Abilities/Taxonomy/CreateTaxonomyTermAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Create Taxonomy Term', 'data-machine' ), 'description' => __( 'Create a new taxonomy term. The term will be created if it does not already exist.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/taxonomy', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Taxonomy/DeleteTaxonomyTermAbility.php b/inc/Abilities/Taxonomy/DeleteTaxonomyTermAbility.php index ec352f480..e357aa659 100644 --- a/inc/Abilities/Taxonomy/DeleteTaxonomyTermAbility.php +++ b/inc/Abilities/Taxonomy/DeleteTaxonomyTermAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Delete Taxonomy Term', 'data-machine' ), 'description' => __( 'Delete an existing taxonomy term. Optionally reassign posts to another term.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/taxonomy', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Taxonomy/GetTaxonomyTermsAbility.php b/inc/Abilities/Taxonomy/GetTaxonomyTermsAbility.php index b928f391e..be98943f8 100644 --- a/inc/Abilities/Taxonomy/GetTaxonomyTermsAbility.php +++ b/inc/Abilities/Taxonomy/GetTaxonomyTermsAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Get Taxonomy Terms', 'data-machine' ), 'description' => __( 'Retrieve taxonomy terms with optional filtering by taxonomy, search, and pagination.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/taxonomy', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Taxonomy/ResolveTermAbility.php b/inc/Abilities/Taxonomy/ResolveTermAbility.php index 841a5aab1..db08c4f46 100644 --- a/inc/Abilities/Taxonomy/ResolveTermAbility.php +++ b/inc/Abilities/Taxonomy/ResolveTermAbility.php @@ -35,7 +35,7 @@ private function registerAbility(): void { array( 'label' => __( 'Resolve Term', 'data-machine' ), 'description' => __( 'Find or create a taxonomy term by ID, name, or slug. Single source of truth for term resolution.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/taxonomy', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Taxonomy/UpdateTaxonomyTermAbility.php b/inc/Abilities/Taxonomy/UpdateTaxonomyTermAbility.php index c872cab4d..5807ff7b6 100644 --- a/inc/Abilities/Taxonomy/UpdateTaxonomyTermAbility.php +++ b/inc/Abilities/Taxonomy/UpdateTaxonomyTermAbility.php @@ -33,7 +33,7 @@ private function registerAbility(): void { array( 'label' => __( 'Update Taxonomy Term', 'data-machine' ), 'description' => __( 'Update an existing taxonomy term. Supports updating name, slug, description, and parent.', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/taxonomy', 'input_schema' => array( 'type' => 'object', 'properties' => array( diff --git a/inc/Abilities/Update/UpdateWordPressAbility.php b/inc/Abilities/Update/UpdateWordPressAbility.php index 0337fb4ac..84348f72e 100644 --- a/inc/Abilities/Update/UpdateWordPressAbility.php +++ b/inc/Abilities/Update/UpdateWordPressAbility.php @@ -44,7 +44,7 @@ private function registerAbilities(): void { array( 'label' => __( 'Update WordPress Post', 'data-machine' ), 'description' => __( 'Update WordPress posts with surgical text edits, block-level edits, or full content replacement', 'data-machine' ), - 'category' => 'datamachine', + 'category' => 'datamachine/publishing', 'input_schema' => array( 'type' => 'object', 'required' => array( 'source_url' ), diff --git a/inc/Api/Chat/Tools/AddPipelineStep.php b/inc/Api/Chat/Tools/AddPipelineStep.php index 150ed6490..bb40b22e3 100644 --- a/inc/Api/Chat/Tools/AddPipelineStep.php +++ b/inc/Api/Chat/Tools/AddPipelineStep.php @@ -21,7 +21,7 @@ class AddPipelineStep extends BaseTool { public function __construct() { - $this->registerTool( 'add_pipeline_step', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'add_pipeline_step', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/add-pipeline-step' ) ); } private static function getValidStepTypes(): array { diff --git a/inc/Api/Chat/Tools/ApiQuery.php b/inc/Api/Chat/Tools/ApiQuery.php index b2508053d..2415c2a22 100644 --- a/inc/Api/Chat/Tools/ApiQuery.php +++ b/inc/Api/Chat/Tools/ApiQuery.php @@ -24,7 +24,7 @@ class ApiQuery extends BaseTool { public function __construct() { - $this->registerTool( 'api_query', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'api_query', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'access_level' => 'editor' ) ); } /** diff --git a/inc/Api/Chat/Tools/AssignTaxonomyTerm.php b/inc/Api/Chat/Tools/AssignTaxonomyTerm.php index b1e84ee55..6d9c395f5 100644 --- a/inc/Api/Chat/Tools/AssignTaxonomyTerm.php +++ b/inc/Api/Chat/Tools/AssignTaxonomyTerm.php @@ -21,7 +21,7 @@ class AssignTaxonomyTerm extends BaseTool { public function __construct() { - $this->registerTool( 'assign_taxonomy_term', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'assign_taxonomy_term', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'access_level' => 'editor' ) ); } public function getToolDefinition(): array { diff --git a/inc/Api/Chat/Tools/AuthenticateHandler.php b/inc/Api/Chat/Tools/AuthenticateHandler.php index 956312176..adbfe361c 100644 --- a/inc/Api/Chat/Tools/AuthenticateHandler.php +++ b/inc/Api/Chat/Tools/AuthenticateHandler.php @@ -23,7 +23,7 @@ class AuthenticateHandler extends BaseTool { public function __construct() { - $this->registerTool( 'authenticate_handler', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'authenticate_handler', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'abilities' => array( 'datamachine/get-handlers', 'datamachine/get-auth-status', 'datamachine/save-auth-config', 'datamachine/disconnect-auth' ) ) ); } /** diff --git a/inc/Api/Chat/Tools/ConfigureFlowSteps.php b/inc/Api/Chat/Tools/ConfigureFlowSteps.php index 05372415d..f3e3c58ae 100644 --- a/inc/Api/Chat/Tools/ConfigureFlowSteps.php +++ b/inc/Api/Chat/Tools/ConfigureFlowSteps.php @@ -21,7 +21,7 @@ class ConfigureFlowSteps extends BaseTool { public function __construct() { - $this->registerTool( 'configure_flow_steps', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'configure_flow_steps', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'abilities' => array( 'datamachine/update-flow-step', 'datamachine/validate-handler', 'datamachine/configure-flow-steps', 'datamachine/validate-flow-steps-config' ) ) ); } /** diff --git a/inc/Api/Chat/Tools/ConfigurePipelineStep.php b/inc/Api/Chat/Tools/ConfigurePipelineStep.php index 7a2a4f08d..64bc4a6de 100644 --- a/inc/Api/Chat/Tools/ConfigurePipelineStep.php +++ b/inc/Api/Chat/Tools/ConfigurePipelineStep.php @@ -20,7 +20,7 @@ class ConfigurePipelineStep extends BaseTool { public function __construct() { - $this->registerTool( 'configure_pipeline_step', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'configure_pipeline_step', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/update-pipeline-step' ) ); } /** diff --git a/inc/Api/Chat/Tools/CopyFlow.php b/inc/Api/Chat/Tools/CopyFlow.php index ecd31de9c..4fd99e457 100644 --- a/inc/Api/Chat/Tools/CopyFlow.php +++ b/inc/Api/Chat/Tools/CopyFlow.php @@ -21,7 +21,7 @@ class CopyFlow extends BaseTool { public function __construct() { - $this->registerTool( 'copy_flow', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'copy_flow', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/duplicate-flow' ) ); } /** diff --git a/inc/Api/Chat/Tools/CreateFlow.php b/inc/Api/Chat/Tools/CreateFlow.php index 0f6f59d98..8b3cad00c 100644 --- a/inc/Api/Chat/Tools/CreateFlow.php +++ b/inc/Api/Chat/Tools/CreateFlow.php @@ -21,7 +21,7 @@ class CreateFlow extends BaseTool { public function __construct() { - $this->registerTool( 'create_flow', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'create_flow', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'abilities' => array( 'datamachine/create-flow', 'datamachine/update-flow-step' ) ) ); } /** diff --git a/inc/Api/Chat/Tools/CreatePipeline.php b/inc/Api/Chat/Tools/CreatePipeline.php index ec4ca2b54..77262fb76 100644 --- a/inc/Api/Chat/Tools/CreatePipeline.php +++ b/inc/Api/Chat/Tools/CreatePipeline.php @@ -21,7 +21,7 @@ class CreatePipeline extends BaseTool { public function __construct() { - $this->registerTool( 'create_pipeline', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'create_pipeline', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/create-pipeline' ) ); } private static function getValidStepTypes(): array { diff --git a/inc/Api/Chat/Tools/CreateTaxonomyTerm.php b/inc/Api/Chat/Tools/CreateTaxonomyTerm.php index 029949297..1fd709537 100644 --- a/inc/Api/Chat/Tools/CreateTaxonomyTerm.php +++ b/inc/Api/Chat/Tools/CreateTaxonomyTerm.php @@ -21,7 +21,7 @@ class CreateTaxonomyTerm extends BaseTool { public function __construct() { - $this->registerTool( 'create_taxonomy_term', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'create_taxonomy_term', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'access_level' => 'editor' ) ); } public function getToolDefinition(): array { diff --git a/inc/Api/Chat/Tools/DeleteFile.php b/inc/Api/Chat/Tools/DeleteFile.php index 951a409d4..5260f6afe 100644 --- a/inc/Api/Chat/Tools/DeleteFile.php +++ b/inc/Api/Chat/Tools/DeleteFile.php @@ -19,7 +19,7 @@ class DeleteFile extends BaseTool { public function __construct() { - $this->registerTool( 'delete_file', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'delete_file', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/delete-flow-file' ) ); } /** diff --git a/inc/Api/Chat/Tools/DeleteFlow.php b/inc/Api/Chat/Tools/DeleteFlow.php index 0470cfec2..48b7a0075 100644 --- a/inc/Api/Chat/Tools/DeleteFlow.php +++ b/inc/Api/Chat/Tools/DeleteFlow.php @@ -18,7 +18,7 @@ class DeleteFlow extends BaseTool { public function __construct() { - $this->registerTool( 'delete_flow', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'delete_flow', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/delete-flow' ) ); } /** diff --git a/inc/Api/Chat/Tools/DeletePipeline.php b/inc/Api/Chat/Tools/DeletePipeline.php index 0e6602317..35dc8c09c 100644 --- a/inc/Api/Chat/Tools/DeletePipeline.php +++ b/inc/Api/Chat/Tools/DeletePipeline.php @@ -19,7 +19,7 @@ class DeletePipeline extends BaseTool { public function __construct() { - $this->registerTool( 'delete_pipeline', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'delete_pipeline', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/delete-pipeline' ) ); } /** diff --git a/inc/Api/Chat/Tools/DeletePipelineStep.php b/inc/Api/Chat/Tools/DeletePipelineStep.php index 453b425fa..f614b0d59 100644 --- a/inc/Api/Chat/Tools/DeletePipelineStep.php +++ b/inc/Api/Chat/Tools/DeletePipelineStep.php @@ -19,7 +19,7 @@ class DeletePipelineStep extends BaseTool { public function __construct() { - $this->registerTool( 'delete_pipeline_step', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'delete_pipeline_step', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/delete-pipeline-step' ) ); } /** diff --git a/inc/Api/Chat/Tools/ExecuteWorkflowTool.php b/inc/Api/Chat/Tools/ExecuteWorkflowTool.php index d0b4f1a5e..388dfc2d1 100644 --- a/inc/Api/Chat/Tools/ExecuteWorkflowTool.php +++ b/inc/Api/Chat/Tools/ExecuteWorkflowTool.php @@ -20,7 +20,7 @@ class ExecuteWorkflowTool extends BaseTool { public function __construct() { - $this->registerTool( 'execute_workflow', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'execute_workflow', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/execute-workflow' ) ); } /** diff --git a/inc/Api/Chat/Tools/GetHandlerDefaults.php b/inc/Api/Chat/Tools/GetHandlerDefaults.php index 6fe246328..d0adf6818 100644 --- a/inc/Api/Chat/Tools/GetHandlerDefaults.php +++ b/inc/Api/Chat/Tools/GetHandlerDefaults.php @@ -19,7 +19,7 @@ class GetHandlerDefaults extends BaseTool { public function __construct() { - $this->registerTool( 'get_handler_defaults', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'get_handler_defaults', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'abilities' => array( 'datamachine/get-handler-site-defaults', 'datamachine/get-handlers', 'datamachine/get-handler-config-fields' ) ) ); } public function getToolDefinition(): array { diff --git a/inc/Api/Chat/Tools/GetProblemFlows.php b/inc/Api/Chat/Tools/GetProblemFlows.php index 2f6b950c7..280902edd 100644 --- a/inc/Api/Chat/Tools/GetProblemFlows.php +++ b/inc/Api/Chat/Tools/GetProblemFlows.php @@ -24,7 +24,7 @@ class GetProblemFlows extends BaseTool { public function __construct() { - $this->registerTool( 'get_problem_flows', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'get_problem_flows', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/get-problem-flows' ) ); } /** diff --git a/inc/Api/Chat/Tools/ListFlows.php b/inc/Api/Chat/Tools/ListFlows.php index d5ef44bc8..76f253c7b 100644 --- a/inc/Api/Chat/Tools/ListFlows.php +++ b/inc/Api/Chat/Tools/ListFlows.php @@ -17,7 +17,7 @@ class ListFlows extends BaseTool { public function __construct() { - $this->registerTool( 'list_flows', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'list_flows', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/get-flows' ) ); } public function getToolDefinition(): array { diff --git a/inc/Api/Chat/Tools/ManageJobs.php b/inc/Api/Chat/Tools/ManageJobs.php index 44f7212c0..30377ba1d 100644 --- a/inc/Api/Chat/Tools/ManageJobs.php +++ b/inc/Api/Chat/Tools/ManageJobs.php @@ -19,7 +19,7 @@ class ManageJobs extends BaseTool { public function __construct() { - $this->registerTool( 'manage_jobs', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'manage_jobs', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'abilities' => array( 'datamachine/get-jobs', 'datamachine/get-jobs-summary', 'datamachine/delete-jobs', 'datamachine/fail-job', 'datamachine/retry-job', 'datamachine/recover-stuck-jobs' ) ) ); } /** diff --git a/inc/Api/Chat/Tools/ManageLogs.php b/inc/Api/Chat/Tools/ManageLogs.php index a14afc116..a5301ee80 100644 --- a/inc/Api/Chat/Tools/ManageLogs.php +++ b/inc/Api/Chat/Tools/ManageLogs.php @@ -20,7 +20,7 @@ class ManageLogs extends BaseTool { public function __construct() { - $this->registerTool( 'manage_logs', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'manage_logs', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'abilities' => array( 'datamachine/clear-logs', 'datamachine/get-log-metadata' ) ) ); } /** diff --git a/inc/Api/Chat/Tools/ManageQueue.php b/inc/Api/Chat/Tools/ManageQueue.php index 1a05dd898..fa7752529 100644 --- a/inc/Api/Chat/Tools/ManageQueue.php +++ b/inc/Api/Chat/Tools/ManageQueue.php @@ -20,7 +20,7 @@ class ManageQueue extends BaseTool { public function __construct() { - $this->registerTool( 'manage_queue', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'manage_queue', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'abilities' => array( 'datamachine/queue-add', 'datamachine/queue-list', 'datamachine/queue-clear', 'datamachine/queue-remove', 'datamachine/queue-update', 'datamachine/queue-move', 'datamachine/queue-settings' ) ) ); } /** diff --git a/inc/Api/Chat/Tools/MergeTaxonomyTerms.php b/inc/Api/Chat/Tools/MergeTaxonomyTerms.php index eda57ae89..735d9c093 100644 --- a/inc/Api/Chat/Tools/MergeTaxonomyTerms.php +++ b/inc/Api/Chat/Tools/MergeTaxonomyTerms.php @@ -20,7 +20,7 @@ class MergeTaxonomyTerms extends BaseTool { public function __construct() { - $this->registerTool( 'merge_taxonomy_terms', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'merge_taxonomy_terms', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'access_level' => 'editor' ) ); } public function getToolDefinition(): array { diff --git a/inc/Api/Chat/Tools/ReadLogs.php b/inc/Api/Chat/Tools/ReadLogs.php index a0857e479..2e5538252 100644 --- a/inc/Api/Chat/Tools/ReadLogs.php +++ b/inc/Api/Chat/Tools/ReadLogs.php @@ -20,7 +20,7 @@ class ReadLogs extends BaseTool { public function __construct() { - $this->registerTool( 'read_logs', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'read_logs', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/read-logs' ) ); } /** diff --git a/inc/Api/Chat/Tools/ReorderPipelineSteps.php b/inc/Api/Chat/Tools/ReorderPipelineSteps.php index 9c6eabbf6..d9d223b6f 100644 --- a/inc/Api/Chat/Tools/ReorderPipelineSteps.php +++ b/inc/Api/Chat/Tools/ReorderPipelineSteps.php @@ -19,7 +19,7 @@ class ReorderPipelineSteps extends BaseTool { public function __construct() { - $this->registerTool( 'reorder_pipeline_steps', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'reorder_pipeline_steps', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/reorder-pipeline-steps' ) ); } /** diff --git a/inc/Api/Chat/Tools/RunFlow.php b/inc/Api/Chat/Tools/RunFlow.php index 93bcaa241..c8b7f74f6 100644 --- a/inc/Api/Chat/Tools/RunFlow.php +++ b/inc/Api/Chat/Tools/RunFlow.php @@ -20,7 +20,7 @@ class RunFlow extends BaseTool { public function __construct() { - $this->registerTool( 'run_flow', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'run_flow', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'abilities' => array( 'datamachine/run-flow', 'datamachine/schedule-flow' ) ) ); } /** diff --git a/inc/Api/Chat/Tools/SearchTaxonomyTerms.php b/inc/Api/Chat/Tools/SearchTaxonomyTerms.php index 7e4858783..6aafb9f5c 100644 --- a/inc/Api/Chat/Tools/SearchTaxonomyTerms.php +++ b/inc/Api/Chat/Tools/SearchTaxonomyTerms.php @@ -20,7 +20,7 @@ class SearchTaxonomyTerms extends BaseTool { public function __construct() { - $this->registerTool( 'search_taxonomy_terms', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'search_taxonomy_terms', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'access_level' => 'editor' ) ); } public function getToolDefinition(): array { diff --git a/inc/Api/Chat/Tools/SendPing.php b/inc/Api/Chat/Tools/SendPing.php index 281f53984..1ed7b126d 100644 --- a/inc/Api/Chat/Tools/SendPing.php +++ b/inc/Api/Chat/Tools/SendPing.php @@ -19,7 +19,7 @@ class SendPing extends BaseTool { public function __construct() { - $this->registerTool( 'send_ping', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'send_ping', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/send-ping' ) ); } /** diff --git a/inc/Api/Chat/Tools/SetHandlerDefaults.php b/inc/Api/Chat/Tools/SetHandlerDefaults.php index c784bb25f..9a0ef6e4d 100644 --- a/inc/Api/Chat/Tools/SetHandlerDefaults.php +++ b/inc/Api/Chat/Tools/SetHandlerDefaults.php @@ -20,7 +20,7 @@ class SetHandlerDefaults extends BaseTool { public function __construct() { - $this->registerTool( 'set_handler_defaults', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'set_handler_defaults', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/update-handler-defaults' ) ); } public function getToolDefinition(): array { diff --git a/inc/Api/Chat/Tools/SystemHealthCheck.php b/inc/Api/Chat/Tools/SystemHealthCheck.php index e3a7e5fe9..99971653d 100644 --- a/inc/Api/Chat/Tools/SystemHealthCheck.php +++ b/inc/Api/Chat/Tools/SystemHealthCheck.php @@ -19,7 +19,7 @@ class SystemHealthCheck extends BaseTool { public function __construct() { - $this->registerTool( 'system_health_check', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'system_health_check', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/system-health-check' ) ); } /** diff --git a/inc/Api/Chat/Tools/UpdateFlow.php b/inc/Api/Chat/Tools/UpdateFlow.php index 10bae89c2..73bb0060a 100644 --- a/inc/Api/Chat/Tools/UpdateFlow.php +++ b/inc/Api/Chat/Tools/UpdateFlow.php @@ -18,7 +18,7 @@ class UpdateFlow extends BaseTool { public function __construct() { - $this->registerTool( 'update_flow', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'update_flow', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'ability' => 'datamachine/update-flow' ) ); } /** diff --git a/inc/Api/Chat/Tools/UpdateTaxonomyTerm.php b/inc/Api/Chat/Tools/UpdateTaxonomyTerm.php index 9ebd2820a..4454ec6fc 100644 --- a/inc/Api/Chat/Tools/UpdateTaxonomyTerm.php +++ b/inc/Api/Chat/Tools/UpdateTaxonomyTerm.php @@ -20,7 +20,7 @@ class UpdateTaxonomyTerm extends BaseTool { public function __construct() { - $this->registerTool( 'update_taxonomy_term', array( $this, 'getToolDefinition' ), array( 'chat' ) ); + $this->registerTool( 'update_taxonomy_term', array( $this, 'getToolDefinition' ), array( 'chat' ), array( 'access_level' => 'editor' ) ); } public function getToolDefinition(): array { diff --git a/inc/Core/Steps/AI/AIStep.php b/inc/Core/Steps/AI/AIStep.php index afa689013..b8d4076e1 100644 --- a/inc/Core/Steps/AI/AIStep.php +++ b/inc/Core/Steps/AI/AIStep.php @@ -252,6 +252,14 @@ protected function executeStep(): array { } $engine_data = $this->engine->all(); + + // Tool categories can be specified at the pipeline step level or pipeline level. + // This allows pipelines to declare which ability categories are relevant, + // reducing tool bloat by excluding irrelevant tools from the AI context. + $tool_categories = $pipeline_step_config['tool_categories'] + ?? $this->engine->get( 'pipeline_tool_categories' ) + ?? array(); + $resolver = new ToolPolicyResolver(); $available_tools = $resolver->resolve( array( 'context' => ToolPolicyResolver::CONTEXT_PIPELINE, @@ -260,6 +268,7 @@ protected function executeStep(): array { 'next_step_config' => $next_step_config, 'pipeline_step_id' => $pipeline_step_id, 'engine_data' => $engine_data, + 'categories' => $tool_categories, ) ); // Model/provider resolved exclusively via context system — pipeline config is ignored. diff --git a/inc/Engine/AI/Tools/Global/AgentDailyMemory.php b/inc/Engine/AI/Tools/Global/AgentDailyMemory.php index 21d9d9265..4dec8acaf 100644 --- a/inc/Engine/AI/Tools/Global/AgentDailyMemory.php +++ b/inc/Engine/AI/Tools/Global/AgentDailyMemory.php @@ -21,7 +21,7 @@ class AgentDailyMemory extends BaseTool { public function __construct() { - $this->registerTool( 'agent_daily_memory', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'agent_daily_memory', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'abilities' => array( 'datamachine/daily-memory-read', 'datamachine/daily-memory-write', 'datamachine/daily-memory-list', 'datamachine/search-daily-memory' ) ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/AgentMemory.php b/inc/Engine/AI/Tools/Global/AgentMemory.php index 43312d349..c312fc980 100644 --- a/inc/Engine/AI/Tools/Global/AgentMemory.php +++ b/inc/Engine/AI/Tools/Global/AgentMemory.php @@ -21,7 +21,7 @@ class AgentMemory extends BaseTool { public function __construct() { - $this->registerTool( 'agent_memory', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'agent_memory', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'abilities' => array( 'datamachine/get-agent-memory', 'datamachine/update-agent-memory', 'datamachine/list-agent-memory-sections' ) ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/AmazonAffiliateLink.php b/inc/Engine/AI/Tools/Global/AmazonAffiliateLink.php index 138fb84c4..ac19182ac 100644 --- a/inc/Engine/AI/Tools/Global/AmazonAffiliateLink.php +++ b/inc/Engine/AI/Tools/Global/AmazonAffiliateLink.php @@ -84,7 +84,7 @@ class AmazonAffiliateLink extends BaseTool { */ public function __construct() { $this->registerConfigurationHandlers( 'amazon_affiliate_link' ); - $this->registerTool( 'amazon_affiliate_link', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'amazon_affiliate_link', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'access_level' => 'admin' ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/BingWebmaster.php b/inc/Engine/AI/Tools/Global/BingWebmaster.php index 2eddeadcb..ccac73d96 100644 --- a/inc/Engine/AI/Tools/Global/BingWebmaster.php +++ b/inc/Engine/AI/Tools/Global/BingWebmaster.php @@ -19,7 +19,7 @@ class BingWebmaster extends BaseTool { public function __construct() { $this->registerConfigurationHandlers( 'bing_webmaster' ); - $this->registerTool( 'bing_webmaster', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'bing_webmaster', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'ability' => 'datamachine/bing-webmaster' ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/GoogleAnalytics.php b/inc/Engine/AI/Tools/Global/GoogleAnalytics.php index 6928472cc..5fb9a5307 100644 --- a/inc/Engine/AI/Tools/Global/GoogleAnalytics.php +++ b/inc/Engine/AI/Tools/Global/GoogleAnalytics.php @@ -20,7 +20,7 @@ class GoogleAnalytics extends BaseTool { public function __construct() { $this->registerConfigurationHandlers( 'google_analytics' ); - $this->registerTool( 'google_analytics', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'google_analytics', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'ability' => 'datamachine/google-analytics' ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/GoogleSearch.php b/inc/Engine/AI/Tools/Global/GoogleSearch.php index 9e10c71bc..0cd7cfeaf 100644 --- a/inc/Engine/AI/Tools/Global/GoogleSearch.php +++ b/inc/Engine/AI/Tools/Global/GoogleSearch.php @@ -16,7 +16,7 @@ class GoogleSearch extends BaseTool { public function __construct() { $this->registerConfigurationHandlers( 'google_search' ); - $this->registerTool( 'google_search', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'google_search', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'access_level' => 'admin' ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/GoogleSearchConsole.php b/inc/Engine/AI/Tools/Global/GoogleSearchConsole.php index 836328c06..48b94c0e4 100644 --- a/inc/Engine/AI/Tools/Global/GoogleSearchConsole.php +++ b/inc/Engine/AI/Tools/Global/GoogleSearchConsole.php @@ -19,7 +19,7 @@ class GoogleSearchConsole extends BaseTool { public function __construct() { $this->registerConfigurationHandlers( 'google_search_console' ); - $this->registerTool( 'google_search_console', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'google_search_console', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'ability' => 'datamachine/google-search-console' ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/ImageGeneration.php b/inc/Engine/AI/Tools/Global/ImageGeneration.php index 2ceb8b4f9..c088e7fa6 100644 --- a/inc/Engine/AI/Tools/Global/ImageGeneration.php +++ b/inc/Engine/AI/Tools/Global/ImageGeneration.php @@ -26,7 +26,7 @@ class ImageGeneration extends BaseTool { public function __construct() { $this->registerConfigurationHandlers( 'image_generation' ); - $this->registerTool( 'image_generation', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'image_generation', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'ability' => 'datamachine/generate-image' ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/InternalLinkAudit.php b/inc/Engine/AI/Tools/Global/InternalLinkAudit.php index 5392443d0..e78270ab6 100644 --- a/inc/Engine/AI/Tools/Global/InternalLinkAudit.php +++ b/inc/Engine/AI/Tools/Global/InternalLinkAudit.php @@ -23,7 +23,7 @@ class InternalLinkAudit extends BaseTool { public function __construct() { - $this->registerTool( 'internal_link_audit', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'internal_link_audit', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'abilities' => array( 'datamachine/audit-internal-links', 'datamachine/get-orphaned-posts', 'datamachine/check-broken-links' ) ) ); } public function handle_tool_call( array $parameters, array $tool_def = array() ): array { diff --git a/inc/Engine/AI/Tools/Global/LocalSearch.php b/inc/Engine/AI/Tools/Global/LocalSearch.php index 6241d1faa..c0bc9a131 100644 --- a/inc/Engine/AI/Tools/Global/LocalSearch.php +++ b/inc/Engine/AI/Tools/Global/LocalSearch.php @@ -17,7 +17,7 @@ class LocalSearch extends BaseTool { public function __construct() { - $this->registerTool( 'local_search', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'local_search', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'ability' => 'datamachine/local-search' ) ); } public function handle_tool_call( array $parameters, array $tool_def = array() ): array { diff --git a/inc/Engine/AI/Tools/Global/PageSpeed.php b/inc/Engine/AI/Tools/Global/PageSpeed.php index 3514378da..3b9058dea 100644 --- a/inc/Engine/AI/Tools/Global/PageSpeed.php +++ b/inc/Engine/AI/Tools/Global/PageSpeed.php @@ -20,7 +20,7 @@ class PageSpeed extends BaseTool { public function __construct() { $this->registerConfigurationHandlers( 'pagespeed' ); - $this->registerTool( 'pagespeed', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'pagespeed', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'ability' => 'datamachine/pagespeed' ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/QueueValidator.php b/inc/Engine/AI/Tools/Global/QueueValidator.php index a1caf8afe..6afa2effc 100644 --- a/inc/Engine/AI/Tools/Global/QueueValidator.php +++ b/inc/Engine/AI/Tools/Global/QueueValidator.php @@ -23,7 +23,7 @@ class QueueValidator extends BaseTool { public function __construct() { - $this->registerTool( 'queue_validator', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'queue_validator', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'access_level' => 'admin' ) ); } /** diff --git a/inc/Engine/AI/Tools/Global/WebFetch.php b/inc/Engine/AI/Tools/Global/WebFetch.php index e008665ad..fec20e3fc 100644 --- a/inc/Engine/AI/Tools/Global/WebFetch.php +++ b/inc/Engine/AI/Tools/Global/WebFetch.php @@ -14,7 +14,7 @@ class WebFetch extends BaseTool { public function __construct() { - $this->registerTool( 'web_fetch', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'web_fetch', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'access_level' => 'author' ) ); } public function handle_tool_call( array $parameters, array $tool_def = array() ): array { diff --git a/inc/Engine/AI/Tools/Global/WordPressPostReader.php b/inc/Engine/AI/Tools/Global/WordPressPostReader.php index 33d05345e..9b54d8676 100644 --- a/inc/Engine/AI/Tools/Global/WordPressPostReader.php +++ b/inc/Engine/AI/Tools/Global/WordPressPostReader.php @@ -17,7 +17,7 @@ class WordPressPostReader extends BaseTool { public function __construct() { - $this->registerTool( 'wordpress_post_reader', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ) ); + $this->registerTool( 'wordpress_post_reader', array( $this, 'getToolDefinition' ), array( 'chat', 'pipeline' ), array( 'ability' => 'datamachine/get-wordpress-post' ) ); } public function handle_tool_call( array $parameters, array $tool_def = array() ): array { diff --git a/inc/Engine/AI/Tools/ToolPolicyResolver.php b/inc/Engine/AI/Tools/ToolPolicyResolver.php index 744a97fe4..605f822db 100644 --- a/inc/Engine/AI/Tools/ToolPolicyResolver.php +++ b/inc/Engine/AI/Tools/ToolPolicyResolver.php @@ -9,11 +9,12 @@ * * Resolution precedence (highest to lowest): * 1. Explicit deny list (always wins) - * 2. Per-agent tool policy (deny/allow mode from agent_config) - * 3. Context-level allow_only (narrows to explicit subset) - * 4. Context preset (pipeline/chat/system) - * 5. Global enablement settings - * 6. Tool configuration requirements + * 2. Per-agent tool policy (deny/allow mode from agent_config, supports categories) + * 3. Ability category filter (narrows tools by their linked ability's category) + * 4. Context-level allow_only (narrows to explicit subset) + * 5. Context preset (pipeline/chat/system) + * 6. Global enablement settings + * 7. Tool configuration requirements * * @package DataMachine\Engine\AI\Tools * @since 0.39.0 @@ -65,6 +66,8 @@ public function __construct( ?ToolManager $tool_manager = null ) { * @type array $engine_data Engine data snapshot for dynamic tool generation. * @type array $deny Tool names to explicitly deny (highest precedence). * @type array $allow_only If set, only these tools are allowed (allowlist mode). + * @type array $categories If set, only tools whose linked ability belongs to one + * of these categories are included. Empty = no filtering. * @type string|null $cache_scope Scope key for tool cache (e.g. flow_step_id). * } * @return array Resolved tools array keyed by tool name. @@ -124,18 +127,25 @@ public function resolve( array $context ): array { $tools = $this->applyAgentPolicy( $tools, $agent_policy ); } - // 4. Apply allowlist if specified (narrows to explicit subset). + // 4. Filter by ability categories (narrows to tools whose linked ability + // belongs to one of the specified categories). + $categories = $context['categories'] ?? array(); + if ( ! empty( $categories ) ) { + $tools = $this->filterByAbilityCategories( $tools, $categories ); + } + + // 5. Apply allowlist if specified (narrows to explicit subset). $allow_only = $context['allow_only'] ?? array(); if ( ! empty( $allow_only ) ) { $tools = array_intersect_key( $tools, array_flip( $allow_only ) ); } - // 5. Apply deny list (always wins). + // 6. Apply deny list (always wins). if ( ! empty( $deny ) ) { $tools = array_diff_key( $tools, array_flip( $deny ) ); } - // 6. Allow external filtering of resolved tools. + // 7. Allow external filtering of resolved tools. $tools = apply_filters( 'datamachine_resolved_tools', $tools, $context_type, $context ); return $tools; @@ -364,6 +374,79 @@ private function gatherToolsForContext( string $context_type ): array { return $available_tools; } + /** + * Filter tools by their linked ability's category. + * + * For each tool, resolves its ability category via the Abilities API registry. + * Only tools whose ability belongs to one of the allowed categories pass through. + * + * Handler tools (those with a 'handler' key but no 'ability' key) are always + * included — they are dynamically scoped by the pipeline engine and should not + * be filtered by category. + * + * Tools without any ability linkage are excluded when category filtering is + * active, since they cannot be categorized. To include them, add their names + * to the context's `allow_only` list as an escape hatch. + * + * @since 0.55.0 + * + * @param array $tools Resolved tools array keyed by tool name. + * @param string[] $categories Allowed category slugs (e.g. 'datamachine/content'). + * @return array Filtered tools. + */ + private function filterByAbilityCategories( array $tools, array $categories ): array { + if ( empty( $categories ) ) { + return $tools; + } + + $registry = class_exists( 'WP_Abilities_Registry' ) ? \WP_Abilities_Registry::get_instance() : null; + $categories_flip = array_flip( $categories ); + $filtered = array(); + + foreach ( $tools as $name => $tool ) { + if ( ! is_array( $tool ) ) { + continue; + } + + // Handler tools bypass category filtering — they're already scoped + // by the pipeline engine to adjacent step handlers. + if ( isset( $tool['handler'] ) && ! isset( $tool['ability'] ) && ! isset( $tool['abilities'] ) ) { + $filtered[ $name ] = $tool; + continue; + } + + // Collect ability slugs from tool metadata. + $ability_slugs = array(); + + if ( ! empty( $tool['ability'] ) ) { + $ability_slugs[] = $tool['ability']; + } + + if ( ! empty( $tool['abilities'] ) && is_array( $tool['abilities'] ) ) { + $ability_slugs = array_merge( $ability_slugs, $tool['abilities'] ); + } + + // No ability linkage — cannot determine category, excluded. + if ( empty( $ability_slugs ) ) { + continue; + } + + // Check if ANY linked ability belongs to an allowed category. + if ( $registry ) { + foreach ( $ability_slugs as $slug ) { + $ability = $registry->get_registered( $slug ); + + if ( $ability && isset( $categories_flip[ $ability->get_category() ] ) ) { + $filtered[ $name ] = $tool; + break; + } + } + } + } + + return $filtered; + } + /** * Get tool policy from an agent's config. * @@ -394,8 +477,23 @@ public function getAgentToolPolicy( int $agent_id ): ?array { $policy = $config['tool_policy']; - // Validate structure: must have 'mode' and 'tools'. - if ( ! isset( $policy['mode'] ) || ! isset( $policy['tools'] ) || ! is_array( $policy['tools'] ) ) { + // Validate structure: must have 'mode' and at least 'tools' or 'categories'. + if ( ! isset( $policy['mode'] ) ) { + return null; + } + + // Ensure tools is present and an array (may be empty if only categories are used). + if ( ! isset( $policy['tools'] ) || ! is_array( $policy['tools'] ) ) { + $policy['tools'] = array(); + } + + // Normalize categories to an array. + if ( isset( $policy['categories'] ) && ! is_array( $policy['categories'] ) ) { + return null; + } + + // Must have at least tools or categories to be a valid policy. + if ( empty( $policy['tools'] ) && empty( $policy['categories'] ?? array() ) ) { return null; } @@ -410,11 +508,18 @@ public function getAgentToolPolicy( int $agent_id ): ?array { /** * Apply an agent's tool policy to a set of resolved tools. * - * - `deny` mode: agent can use everything EXCEPT listed tools. - * - `allow` mode: agent can ONLY use listed tools. + * - `deny` mode: agent can use everything EXCEPT listed tools/categories. + * - `allow` mode: agent can ONLY use listed tools/categories. * - No policy (null): no restrictions (backward compatible). * + * The policy supports both individual tool names (`tools` key) and ability + * categories (`categories` key). When both are present, they compose: + * - allow mode: tool passes if it matches a tool name OR a category. + * - deny mode: tool is excluded if it matches a tool name OR a category. + * * @since 0.42.0 + * @since 0.55.0 Added category support in tool policies. + * * @param array $tools Resolved tools array keyed by tool name. * @param array|null $policy Tool policy from getAgentToolPolicy(), or null for no restrictions. * @return array Filtered tools array. @@ -424,20 +529,62 @@ public function applyAgentPolicy( array $tools, ?array $policy ): array { return $tools; } - $mode = $policy['mode']; - $tool_names = $policy['tools']; + $mode = $policy['mode']; + $tool_names = $policy['tools'] ?? array(); + $policy_categories = $policy['categories'] ?? array(); - if ( empty( $tool_names ) ) { - // deny with empty list = no restrictions; allow with empty list = no tools. + // No tool names and no categories = no restrictions (deny) or no tools (allow). + if ( empty( $tool_names ) && empty( $policy_categories ) ) { return 'allow' === $mode ? array() : $tools; } - if ( 'deny' === $mode ) { - return array_diff_key( $tools, array_flip( $tool_names ) ); + // Simple case: no categories, just tool names (original behavior). + if ( empty( $policy_categories ) ) { + if ( 'deny' === $mode ) { + return array_diff_key( $tools, array_flip( $tool_names ) ); + } + return array_intersect_key( $tools, array_flip( $tool_names ) ); + } + + // Category-aware filtering: check both tool names and categories. + $registry = class_exists( 'WP_Abilities_Registry' ) ? \WP_Abilities_Registry::get_instance() : null; + $tool_names_flip = ! empty( $tool_names ) ? array_flip( $tool_names ) : array(); + $categories_flip = array_flip( $policy_categories ); + $filtered = array(); + + foreach ( $tools as $name => $tool ) { + $matches_tool = isset( $tool_names_flip[ $name ] ); + $matches_cat = false; + + if ( ! $matches_tool && is_array( $tool ) && $registry ) { + $ability_slugs = array(); + + if ( ! empty( $tool['ability'] ) ) { + $ability_slugs[] = $tool['ability']; + } + if ( ! empty( $tool['abilities'] ) && is_array( $tool['abilities'] ) ) { + $ability_slugs = array_merge( $ability_slugs, $tool['abilities'] ); + } + + foreach ( $ability_slugs as $slug ) { + $ability = $registry->get_registered( $slug ); + if ( $ability && isset( $categories_flip[ $ability->get_category() ] ) ) { + $matches_cat = true; + break; + } + } + } + + $matches = $matches_tool || $matches_cat; + + if ( 'allow' === $mode && $matches ) { + $filtered[ $name ] = $tool; + } elseif ( 'deny' === $mode && ! $matches ) { + $filtered[ $name ] = $tool; + } } - // 'allow' mode: only keep tools in the list. - return array_intersect_key( $tools, array_flip( $tool_names ) ); + return $filtered; } /** diff --git a/package-lock.json b/package-lock.json index 0a1d88481..52fdda20d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "datamachine", - "version": "0.65.0", + "version": "0.66.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "datamachine", - "version": "0.65.0", + "version": "0.66.0", "dependencies": { "@extrachill/chat": "github:Extra-Chill/chat", "@tanstack/react-query": "^5.90.12", diff --git a/tests/Unit/Abilities/AllAbilitiesRegisteredTest.php b/tests/Unit/Abilities/AllAbilitiesRegisteredTest.php index 50a14d008..30a716276 100644 --- a/tests/Unit/Abilities/AllAbilitiesRegisteredTest.php +++ b/tests/Unit/Abilities/AllAbilitiesRegisteredTest.php @@ -119,14 +119,38 @@ public function test_all_data_machine_abilities_registered(): void { } /** - * Test datamachine category is registered at boot. + * Test datamachine ability categories are registered at boot. */ - public function test_datamachine_category_registered(): void { + public function test_datamachine_categories_registered(): void { $categories = wp_get_ability_categories(); - $this->assertArrayHasKey( - 'datamachine', - $categories, - 'datamachine category should be registered during plugin boot' + + $expected_categories = array( + 'datamachine/content', + 'datamachine/media', + 'datamachine/analytics', + 'datamachine/seo', + 'datamachine/memory', + 'datamachine/taxonomy', + 'datamachine/publishing', + 'datamachine/fetch', + 'datamachine/email', + 'datamachine/pipeline', + 'datamachine/flow', + 'datamachine/jobs', + 'datamachine/agent', + 'datamachine/settings', + 'datamachine/auth', + 'datamachine/logging', + 'datamachine/system', + 'datamachine/chat', ); + + foreach ( $expected_categories as $slug ) { + $this->assertArrayHasKey( + $slug, + $categories, + "Ability category '{$slug}' should be registered during plugin boot" + ); + } } }