<?php

defined('ABSPATH') or die();

require_once (dirname(__FILE__) . "/aiomatic-agents-actions.php");
require_once (dirname(__FILE__) . "/aiomatic-agents-admin.php");
require_once (dirname(__FILE__) . "/aiomatic-agents-ajax.php");
require_once (dirname(__FILE__) . "/aiomatic-agents-helpers.php");
require_once (dirname(__FILE__) . "/aiomatic-agents-cli.php");

class Aiomatic_Agent {
    protected static $instances = [];

    private $agent_id;
    private $model;
    private $system_prompt;
    private $tools;
    private $config;
    private $cached_ltm = null;
    private $cached_ltm_query = null;
    private $short_memory = []; 
    private $step_retries = [];
    private $is_sub_agent = false;
    private $did_tool_call = false;
    const DB_VERSION = '1.0.0';
    const DEBUG_MODE = false;

    public function __construct($agent_id, $is_sub_agent = false) {
        $this->is_sub_agent = $is_sub_agent;
        $this->agent_id = $agent_id;
        $post = get_post($agent_id);
        if (!$post || $post->post_type !== 'aiomatic_agent') {
            throw new InvalidArgumentException('Invalid agent ID.');
        }
        $saved_config = get_post_meta($agent_id, '_agent_config', true);

        $defaults = $this->get_default_config();

        if (!is_array($saved_config)) {
            $this->config = $defaults;
        } else {
            $this->config = array_replace_recursive($defaults, $saved_config);
        }
        $this->model = get_post_meta($agent_id, '_model', true) ?: AIMOGEN_DEFAULT_MODEL;

        $this->tools = $this->filter_tools_by_config($this->get_agent_tools());

        $description = get_post_meta($agent_id, 'aiomatic_agent_description', true);
        $expertise   = get_post_meta($agent_id, 'aiomatic_agent_expertise', true);
        $identity_block = '';

        if (!empty($description) || !empty($expertise)) {
            $identity_block .= "AGENT IDENTITY:\n";

            if (!empty($description)) {
                $identity_block .= "- Description: $description\n";
            }

            if (!empty($expertise)) {
                $identity_block .= "- Expertise: $expertise\n";
            }

            $identity_block .= "\n";
        }

        $this->system_prompt =
            $identity_block .
            ($post->post_content ?: "You are a helpful autonomous AI agent.");
        $saved_short = get_post_meta($agent_id, '_agent_memory', true);
        $decoded = $saved_short ? json_decode($saved_short, true) : [];
        $this->short_memory = is_array($decoded) ? $decoded : [];
        self::$instances[$agent_id] = $this;
        register_shutdown_function([$this, 'handle_fatal_shutdown']);
    }
    public function is_debug_mode()
    {
        return Aiomatic_Agent::DEBUG_MODE;
    }
    public static function get_instance_by_id($agent_id)
    {
        return self::$instances[$agent_id] ?? null;
    }
    public function get_is_sub_agent()
    {
        return $this->is_sub_agent;
    }
    public function get_model()
    {
        return $this->model;
    }
    public function is_api_level_tool_execution_allowed()
    {
        return $this->config['tool_calls_enabled'];
    }
    private function filter_tools_by_config($tools) {

        if (!array_key_exists('allowed_tools', $this->config) || $this->config['allowed_tools'] === null) {
            return $tools;
        }

        if (empty($this->config['allowed_tools'])) {
            return [];
        }

        return array_intersect_key($tools, array_flip($this->config['allowed_tools']));
    }
    private function get_default_config() {
        return [
            'allowed_tools' => [],
            'max_steps' => 20,
            'allow_delegation' => true,
            'planning_enabled' => false,
            'planning_required' => false,
            'tool_calls_enabled' => true,
            'max_tool_retries' => 3,
            'short_term_memory_enabled' => true,
            'long_term_memory_enabled' => false,
        ];
    }
    public static function cleanup_agent_data($agent_id)
    {
        global $wpdb;

        $agent_id = (int) $agent_id;
        if ($agent_id <= 0) {
            return false;
        }

        $wpdb->delete($wpdb->prefix . 'aiomatic_agent_runs', ['agent_id' => $agent_id], ['%d']);

        delete_post_meta($agent_id, '_agent_memory');
        delete_post_meta($agent_id, '_agent_status');
        delete_post_meta($agent_id, '_current_task');
        delete_post_meta($agent_id, '_task_started_at');
        delete_post_meta($agent_id, '_task_finished_at');
        delete_post_meta($agent_id, '_task_result');
        delete_post_meta($agent_id, '_last_activity');
        delete_post_meta($agent_id, '_agent_current_step');
        delete_post_meta($agent_id, '_last_summary_time');

        unset(self::$instances[$agent_id]);

        if (!aiomatic_long_term_memory_available()) {
            return true;
        }

        $aiomatic_Main_Settings = get_option('aiomatic_Main_Settings', false);
        $appids = preg_split('/\r\n|\r|\n/', trim($aiomatic_Main_Settings['app_id'] ?? ''));
        $appids = array_filter($appids);

        if (empty($appids)) {
            return true;
        }

        $token = $appids[array_rand($appids)];
        $token = apply_filters('aimogen_openai_api_key', $token);
        $token = apply_filters('aiomatic_openai_api_key', $token);

        try {
            $embedding = new Aiomatic_Embeddings($token);
            $embedding->aiomatic_delete_namespace_embeddings('agents_' . $agent_id);

        } catch (\Throwable $e) {
            aiomatic_log_to_file('Failed to delete agent embeddings for agent #' . $agent_id . ': ' . $e->getMessage());
        }

        return true;
    }
    
    public static function install_schema() {
        global $wpdb;

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';

        $charset_collate = $wpdb->get_charset_collate();

        $table2 = $wpdb->prefix . 'aiomatic_agent_runs';
        $sql2 = "CREATE TABLE $table2 (
            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            agent_id BIGINT(20) UNSIGNED NOT NULL,
            step INT UNSIGNED NOT NULL,
            type VARCHAR(50) NOT NULL,
            tool_name VARCHAR(100) NULL,
            prompt LONGTEXT NULL,
            response LONGTEXT NULL,
            params LONGTEXT NULL,
            result LONGTEXT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY agent_lookup (agent_id, step)
        ) $charset_collate;";

        dbDelta($sql2);
    }
    public function get_execution_logs($limit = 100, $offset = 0, $step = null)
    {
        global $wpdb;

        $limit  = max(1, (int)$limit);
        $offset = max(0, (int)$offset);

        $table = $wpdb->prefix . 'aiomatic_agent_runs';

        $where = $wpdb->prepare("WHERE agent_id = %d", $this->agent_id);

        if ($step !== null) {
            $where .= $wpdb->prepare(" AND step = %d", (int)$step);
        }

        $query = "
            SELECT 
                id,
                step,
                type,
                tool_name,
                prompt,
                response,
                params,
                result,
                created_at
            FROM $table
            $where
            ORDER BY id DESC
            LIMIT %d OFFSET %d
        ";

        $results = $wpdb->get_results(
            $wpdb->prepare($query, $limit, $offset),
            ARRAY_A
        );

        if (!$results) {
            return [];
        }

        foreach ($results as &$row) {
            if (!empty($row['params'])) {
                $decoded = json_decode($row['params'], true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    $row['params'] = $decoded;
                }
            }

            if (!empty($row['result'])) {
                $decoded = json_decode($row['result'], true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    $row['result'] = $decoded;
                }
            }
        }

        return $results;
    }
    public function get_execution_timeline($limit_steps = 20)
    {
        $logs = $this->get_execution_logs(1000);

        if (empty($logs)) {
            return [];
        }

        $timeline = [];

        foreach ($logs as $row) {
            $step = $row['step'];

            if (!isset($timeline[$step])) {
                $timeline[$step] = [
                    'step' => $step,
                    'events' => []
                ];
            }

            $timeline[$step]['events'][] = [
                'type'       => $row['type'],
                'tool_name'  => $row['tool_name'],
                'prompt'     => $row['prompt'],
                'response'   => $row['response'],
                'params'     => $row['params'],
                'result'     => $row['result'],
                'created_at' => $row['created_at'],
            ];
        }
        krsort($timeline);
        return array_slice($timeline, 0, $limit_steps, true);
    }
    public static function get_agent_tools() {
        if (!function_exists('is_plugin_active')) {
            include_once(ABSPATH . 'wp-admin/includes/plugin.php');
        }
        $aiomatic_Chatbot_Settings = get_option('aiomatic_Chatbot_Settings', false);
        if (isset($aiomatic_Chatbot_Settings['database_command_types']) && is_array($aiomatic_Chatbot_Settings['database_command_types']) && !empty($aiomatic_Chatbot_Settings['database_command_types']))
        {
            $allowed_commands = $aiomatic_Chatbot_Settings['database_command_types'];
        }
        else
        {
            $allowed_commands = array('SELECT');
        }
        $allowed_commands = implode(',', $allowed_commands);
        $tools = [
            [
                'name' => 'aimogen_rules_engine',
                'description' => 'List or execute bulk post creator rules, to create posts using AI, in the Aimogen plugin.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'operation' => [
                            'type' => 'string',
                            'enum' => ['list', 'run'],
                            'description' => 'Operation to perform on rules'
                        ],
                        'rule_id' => [
                            'type' => 'integer',
                            'description' => 'The ID of the rule. Required for "run" operation.'
                        ],
                        'rule_type' => [
                            'type' => 'integer',
                            'enum' => [0,1,2,3,4,5,6,7,8],
                            'description' => 'Type of rule (0=keyword/topic based post creator,1=youtube based,2=amazon roundup,3=amazon review,4=csv based,5=omniblocks,6=listicles,7=forum,8=reply). Required for "run" operation.'
                        ]
                    ],
                    'required' => ['operation']
                ]
            ],
            [
                'name' => 'aimogen_content_editor_templates',
                'description' => 'Edit a post using AI, using the Aimogen plugin. List available AI Content Editor templates or apply a template to a WordPress post and edit it using it.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'operation' => [
                            'type' => 'string',
                            'enum' => ['list', 'run'],
                            'description' => 'The operation to perform on content editor templates'
                        ],
                        'post_id' => [
                            'type' => 'integer',
                            'description' => 'The WordPress post ID to process. Required for "run" operation.'
                        ],
                        'template_id' => [
                            'type' => 'integer',
                            'description' => 'The AI Content Editor template ID to apply. Optional for "run". If omitted, default/manual template logic is used.'
                        ]
                    ],
                    'required' => ['operation']
                ]
            ],
            [
                'name' => 'get_environment_info',
                'description' => 'Retrieve structured information about the current WordPress site. Includes environment, plugins, CPTs, taxonomies, and detected capabilities. Cannot be used to query posts.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'info_type' => [
                            'type' => 'string',
                            'enum' => [
                                'general',
                                'plugins',
                                'theme',
                                'stats',
                                'capabilities',
                                'post_types',
                                'taxonomies',
                                'all'
                            ],
                            'description' => 'What type of site information to retrieve.'
                        ]
                    ],
                    'required' => ['info_type']
                ]
            ],
            [
                'name' => 'generate_chart',
                'description' => 'Generate and display charts dynamically using the [aiomatic_chat_charts] shortcode. Supports Bar, Line, and Pie charts, rendered as images for compatibility with WordPress posts, pages, and chatbot interfaces.
Usage: [aiomatic_chat_charts type="bar/line/pie" title="ChartTitle" labels="Label1,Label2,Label3" data="Value1,Value2,Value3" colors="#RGB1,#RGB2,#RGB3"]',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'shortcode' => ['type' => 'string', 'description' => 'The complete [aiomatic_chat_charts] shortcode to render, including all needed attributes.']
                    ],
                    'required' => ['shortcode']
                ]
            ],
            [
                'name' => 'wp_send_email',
                'description' => 'Send an email to a specific recipient with a defined subject and HTML or text content. Use this when the task requires actually sending a message, not just drafting one.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'recipient_email' => ['type' => 'string', 'description' => 'The email address of the recipient.'],
                        'subject' => ['type' => 'string', 'description' => 'The subject line of the email.'],
                        'content' => ['type' => 'string', 'description' => 'The HTML or text content of the email.']
                    ],
                    'required' => ['recipient_email', 'subject', 'content']
                ]
            ],[
                'name' => 'website_scraper',
                'description' => 'Scrape and return the content of a specific website URL. Use this when you already have a target URL. Do not use for discovery or searching.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'url' => ['type' => 'string', 'description' => 'The full URL of the website to scrape.']
                    ],
                    'required' => ['url']
                ]
            ],
            [
                'name' => 'rss_feed_parser',
                'description' => 'Parse an RSS feed URL and return structured feed items. Use this when the task requires reading recent feed entries from a blog, news source or podcast feed.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'url' => ['type' => 'string', 'description' => 'The full URL of the RSS feed.']
                    ],
                    'required' => ['url']
                ]
            ],
            [
                'name' => 'google_results_parser',
                'description' => 'Search Google and return a list of search results including titles, snippets and URLs. Use this for discovery and finding relevant pages, not for scraping full page content.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'keywords' => [
                            'type' => 'string', 
                            'description' => 'The search query or keywords to look up on Google.'
                        ]
                    ],
                    'required' => ['keywords']
                ]
            ],
            [
                'name' => 'call_webhook',
                'description' => 'Call an external webhook using GET, POST, PUT or DELETE. Supports form_data or JSON payloads, plus optional custom headers. Use this when external automation or API communication is required.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'webhook_url' => ['type' => 'string', 'description' => 'The full URL of the webhook.'],
                        'method_selector' => [
                            'type' => 'string', 
                            'enum' => ['GET', 'POST', 'PUT', 'DELETE'],
                            'description' => 'The HTTP method to use.'
                        ],
                        'content_type' => [
                            'type' => 'string', 
                            'enum' => ['form_data', 'JSON'],
                            'description' => 'The format of the data being sent.'
                        ],
                        'data' => ['type' => 'string', 'description' => 'The data/body. If form_data, use "key=>value" lines. If JSON, provide valid JSON.'],
                        'headers' => ['type' => 'string', 'description' => 'Custom headers in "Key=>Value" format, one per line.']
                    ],
                    'required' => ['webhook_url', 'method_selector']
                ]
            ],
            [
                'name' => 'search_clickbank',
                'description' => 'Search ClickBank for affiliate products matching a keyword query and return a product listing. Use this for discovery and comparison of candidate affiliate products.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'query' => ['type' => 'string', 'description' => 'Product keywords or niche.']
                    ],
                    'required' => ['query']
                ]
            ],
            [
                'name' => 'search_amazon',
                'description' => 'Search Amazon for products matching a keyword query and return a product listing. Use this for discovery, comparison or finding candidate products, not for deep product specs.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'query' => ['type' => 'string', 'description' => 'Search terms or keywords.']
                    ],
                    'required' => ['query']
                ]
            ],
            [
                'name' => 'get_amazon_product_details',
                'description' => 'Retrieve detailed information for a specific Amazon product by ASIN or precise product query. Use this after narrowing down the product, when you need specs, price, manufacturer or reviews.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'query' => ['type' => 'string', 'description' => 'The ASIN or specific product name.']
                    ],
                    'required' => ['query']
                ]
            ],
            [
                'name' => 'get_post_structure',
                'description' => 'Analyze a WordPress post and return its structure including headings, paragraphs and sections. Use this before editing to understand how the post is organized.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'post_id' => [
                            'type' => 'integer',
                            'description' => 'The ID of the post to analyze.'
                        ]
                    ],
                    'required' => ['post_id']
                ]
            ],
            [
                'name' => 'edit_post_section',
                'description' => 'Edit a specific part of a WordPress post using an AI prompt. This tool modifies ONLY a defined section and preserves the rest of the content exactly as-is. Use this instead of rewriting entire posts.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'post_id' => [
                            'type' => 'integer',
                            'description' => 'The ID of the post to edit.'
                        ],
                        'section_selector' => [
                            'type' => 'string',
                            'description' => 'What part to edit. Examples: "first_paragraph", "last_paragraph", "h2:Conclusion", "paragraph:3", "full_content".'
                        ],
                        'instruction' => [
                            'type' => 'string',
                            'description' => 'What to change. Example: "Improve SEO", "Rewrite for clarity", "Add internal links", "Fix grammar".'
                        ]
                    ],
                    'required' => ['post_id', 'section_selector', 'instruction']
                ]
            ],
            [
                'name' => 'manage_wp_post',
                'description' => 'Create, update, trash, restore, delete, duplicate and otherwise manage WordPress posts or pages. This is a high-impact content action and should be used only when the task explicitly requires changing site content. For the Create operation: post_title and post_content are required parameters.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'operation' => [
                            'type' => 'string',
                            'enum' => [
                                'create',
                                'update',
                                'trash',
                                'untrash',
                                'delete',
                                'duplicate',
                                'append_content',
                                'prepend_content',
                                'set_featured_image',
                                'delete_featured_image',
                                'set_meta',
                                'delete_meta',
                                'set_terms'
                            ],
                            'description' => 'The post operation to perform.'
                        ],
                        'ID' => [
                            'type' => 'integer',
                            'description' => 'The post ID. Required for all operations except create.'
                        ],
                        'post_ids' => [
                            'type' => 'string',
                            'description' => 'Comma separated list of post IDs. Overrides ID if provided.',
                        ],
                        'post_type' => [
                            'type' => 'string',
                            'description' => 'The post type, for example post, page or product.'
                        ],
                        'post_title' => [
                            'type' => 'string',
                            'description' => 'The post title.'
                        ],
                        'post_content' => [
                            'type' => 'string',
                            'description' => 'The post content in HTML or plain text.'
                        ],
                        'post_excerpt' => [
                            'type' => 'string',
                            'description' => 'The post excerpt.'
                        ],
                        'post_status' => [
                            'type' => 'string',
                            'enum' => ['publish', 'draft', 'pending', 'private', 'future'],
                            'description' => 'The post status.'
                        ],
                        'post_name' => [
                            'type' => 'string',
                            'description' => 'The desired slug.'
                        ],
                        'post_parent' => [
                            'type' => 'integer',
                            'description' => 'Parent post ID, mainly for hierarchical post types.'
                        ],
                        'menu_order' => [
                            'type' => 'integer',
                            'description' => 'Menu order value.'
                        ],
                        'comment_status' => [
                            'type' => 'string',
                            'enum' => ['open', 'closed'],
                            'description' => 'Whether comments are open.'
                        ],
                        'image_url' => [
                            'type' => 'string',
                            'description' => 'Direct URL of an image to download and set as featured image. Use only with operation set_featured_image'
                        ],
                        'ping_status' => [
                            'type' => 'string',
                            'enum' => ['open', 'closed'],
                            'description' => 'Whether pings are open.'
                        ],
                        'featured_image_id' => [
                            'type' => 'integer',
                            'description' => 'Attachment ID to set as featured image.'
                        ],
                        'meta_key' => [
                            'type' => 'string',
                            'description' => 'Meta key for set_meta or delete_meta.'
                        ],
                        'meta_value' => [
                            'type' => 'string',
                            'description' => 'Meta value for set_meta.'
                        ],
                        'taxonomy' => [
                            'type' => 'string',
                            'description' => 'Taxonomy name for set_terms.'
                        ],
                        'terms' => [
                            'type' => 'string',
                            'description' => 'Comma separated list of term IDs.',
                        ]
                    ],
                    'required' => ['operation']
                ]
            ],
            [
                'name' => 'wp_taxonomy_discovery',
                'description' => 'Work with WordPress taxonomies and terms.

IMPORTANT RULES:
- Use ONLY one operation at a time.
- Use ONLY the parameters required for that operation.
- DO NOT include unused, empty, default, or irrelevant parameters.
- DO NOT invent new operation names.
- Valid operations are EXACTLY: list_taxonomies, list_terms, get_post_terms, create_term, set_post_terms.

OPERATION REQUIREMENTS:

1. list_taxonomies
- No additional parameters allowed.

2. list_terms
- Required: taxonomy
- Optional: hide_empty, limit

3. get_post_terms
- Required: taxonomy, post_id
- No other parameters allowed.

4. create_term
- Required: taxonomy, term_name
- No other parameters allowed.

5. set_post_terms
- Required: taxonomy, post_id, term_name
- term_name must be a comma-separated list of term NAMES (not IDs)
- This will assign terms to the post (existing terms will be reused, missing ones will be created automatically)
            ',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'operation' => [
                            'type' => 'string',
                            'enum' => ['list_taxonomies', 'list_terms', 'get_post_terms', 'create_term', 'set_post_terms'],
                            'description' => 'The operation to perform. Must be one of the allowed values.'
                        ],
                        'taxonomy' => [
                            'type' => 'string',
                            'description' => 'Taxonomy name (example: category, post_tag, product_cat). Required for list_terms, get_post_terms, create_term, set_post_terms.'
                        ],
                        'post_id' => [
                            'type' => 'integer',
                            'description' => 'Post ID. Required ONLY for get_post_terms.'
                        ],
                        'term_name' => [
                            'type' => 'string',
                            'description' => 'Term name. Required ONLY for create_term and set_post_terms.'
                        ],
                        'hide_empty' => [
                            'type' => 'boolean',
                            'description' => 'Used ONLY for list_terms. Do not include otherwise.'
                        ],
                        'limit' => [
                            'type' => 'integer',
                            'description' => 'Used ONLY for list_terms. Max 100. Do not include otherwise.'
                        ]
                    ],
                    'required' => ['operation'],
                    'additionalProperties' => false
                ]
            ],
            [
                'name' => 'wp_validate_post_state',
                'description' => 'Validate the current state of a WordPress post. Check if specific conditions are met such as having an excerpt, featured image, content length, status, or taxonomy.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'post_id' => ['type' => 'integer', 'description' => 'Post ID to validate.'],
                        'checks' => [
                            'type' => 'string',
                            'description' => 'List of checks to perform.',
                            'enum' => [
                                'exists',
                                'has_excerpt',
                                'has_featured_image',
                                'has_content',
                                'content_length',
                                'status',
                                'has_terms'
                            ]
                        ],
                        'taxonomy' => [
                            'type' => 'string',
                            'description' => 'Required when checking has_terms.'
                        ],
                        'min_content_length' => [
                            'type' => 'integer',
                            'description' => 'Minimum content length for validation.'
                        ],
                        'expected_status' => [
                            'type' => 'string',
                            'description' => 'Expected post status (publish, draft, etc).'
                        ]
                    ],
                    'required' => ['post_id', 'checks']
                ]
            ],
            [
                'name' => 'get_wp_post_data',
                'description' => 'Retrieve the content, status and metadata of an existing WordPress post or page. Use this when the task requires reading or analyzing already published or drafted site content.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'post_id' => ['type' => 'integer', 'description' => 'The ID of the post to read.']
                    ],
                    'required' => ['post_id']
                ]
            ],
            [
                'name' => 'process_and_transform_data',
                'description' => 'Safely transform structured data. Supports JSON parsing, extracting fields, filtering arrays, and simple mapping operations. No code execution.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'operation' => [
                            'type' => 'string',
                            'enum' => [
                                'parse_json',
                                'stringify_json',
                                'extract_field',
                                'filter_equals',
                                'list_keys'
                            ],
                            'description' => 'Transformation operation to perform.'
                        ],
                        'input' => [
                            'type' => 'string',
                            'description' => 'Input data (JSON string or text).'
                        ],
                        'field' => [
                            'type' => 'string',
                            'description' => 'Field name for extraction/filter.'
                        ],
                        'value' => [
                            'type' => 'string',
                            'description' => 'Value used for filtering.'
                        ]
                    ],
                    'required' => ['operation', 'input']
                ]
            ],
            [
                'name' => 'pause_execution',
                'description' => 'Pause execution for a number of seconds. Useful for rate limits, API delays, or sequencing actions.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'seconds' => [
                            'type' => 'integer',
                            'description' => 'Number of seconds to wait. Max 30.'
                        ]
                    ],
                    'required' => ['seconds']
                ]
            ],
            [
                'name' => 'search_site_posts',
                'description' => 'Search WordPress content with advanced filters. Use this to find drafts, missing images or custom field conditions. Include ONLY parameters that are explicitly required for the query. Do not include parameters with empty values, default values, or false unless the filter specifically requires false.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'query' => [
                            'type' => 'string',
                            'description' => 'Search keyword or phrase. Can be empty.'
                        ],
                        'post_type' => [
                            'type' => 'string',
                            'description' => 'Post type to search (post, page, product, etc).'
                        ],
                        'post_status' => [
                            'type' => 'string',
                            'description' => 'Post status (publish, draft, pending, etc).'
                        ],
                        'posts_per_page' => [
                            'type' => 'integer',
                            'description' => 'Maximum number of results to return.'
                        ],

                        'has_featured_image' => [
                            'type' => 'string',
                            'enum' => ['yes', 'no'],
                            'description' => 'Filter posts that have or do not have a featured image. Only include this field when explicitly filtering. Valid values: yes|no'
                        ],
                        'has_excerpt' => [
                            'type' => 'string',
                            'enum' => ['yes', 'no'],
                            'description' => 'Filter posts that have or do not have an excerpt. Only include this field when explicitly filtering. Valid values: yes|no'
                        ],

                        'date_after' => [
                            'type' => 'string',
                            'description' => 'Return posts published after this date (YYYY-MM-DD).'
                        ],
                        'date_before' => [
                            'type' => 'string',
                            'description' => 'Return posts published before this date (YYYY-MM-DD).'
                        ],

                        'taxonomy' => [
                            'type' => 'string',
                            'description' => 'Taxonomy name (category, post_tag, product_cat, etc).'
                        ],
                        'terms' => [
                            'type' => 'string',
                            'description' => 'Comma separated list of term IDs to filter by.'
                        ],

                        'meta_filters' => [
                            'type' => 'string',
                            'description' => 'Meta query filters. Format: key:value:compare | key:value:compare. Example: price:100:>= | stock:0:= | featured::EXISTS.'
                        ],

                        'orderby' => [
                            'type' => 'string',
                            'description' => 'Field to sort results by (date, title, meta_value, etc).'
                        ],
                        'order' => [
                            'type' => 'string',
                            'description' => 'Sort direction (ASC or DESC).'
                        ],
                        'meta_key' => [
                            'type' => 'string',
                            'description' => 'Meta key used when sorting by meta_value.'
                        ],

                        'min_content_length' => [
                            'type' => 'integer',
                            'description' => 'Minimum post content length in characters.'
                        ],
                        'max_content_length' => [
                            'type' => 'integer',
                            'description' => 'Maximum post content length in characters.'
                        ],

                        'author_id' => [
                            'type' => 'integer',
                            'description' => 'Filter posts by author ID.'
                        ],
                        'offset' => [
                            'type' => 'integer',
                            'description' => 'Number of results to skip (for pagination).'
                        ]
                    ],
                    'required' => ['query']
                ]
            ],
            [
                'name' => 'wp_sideload_media',
                'description' => 'Download an image from a remote URL and import it into the WordPress Media Library, optionally attaching it to a post.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'image_url' => ['type' => 'string', 'description' => 'The source URL of the image.'],
                        'post_id' => ['type' => 'integer', 'description' => 'Optional ID to attach the image to.']
                    ],
                    'required' => ['image_url']
                ]
            ],
            [
                'name' => 'get_wp_media_info',
                'description' => 'Retrieve media information for a post or attachment. Can check featured image, list attachments, and validate media presence.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'post_id' => ['type' => 'integer', 'description' => 'Post ID to inspect media for.'],
                        'attachment_id' => ['type' => 'integer', 'description' => 'Specific attachment ID (optional).'],
                        'include_attachments' => ['type' => 'boolean', 'description' => 'Whether to list attached media.'],
                    ]
                ]
            ],
            [
                'name' => 'query_wp_database',
                'description' => 'Execute a direct SQL query on the WordPress database. Allowed command types: ' . $allowed_commands . '. This is a sensitive high-impact operation and should only be used when database access is truly required. Avoid using this unless no other tool can retrieve the data.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'query' => ['type' => 'string', 'description' => 'The SQL query to execute.']
                    ],
                    'required' => ['query']
                ]
            ],
            [
                'name' => 'youtube_video_captions',
                'description' => 'Retrieve the transcript or captions of a specific YouTube video by URL. Use this when the task requires summarizing, analyzing or extracting information from video speech.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'url' => ['type' => 'string', 'description' => 'The full YouTube video URL.']
                    ],
                    'required' => ['url']
                ]
            ],
            [
                'name' => 'youtube_video_search',
                'description' => 'Search YouTube for videos based on a keyword phrase and return matching results. Use this to discover videos, then pass a chosen video URL to the captions tool if transcript analysis is needed.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'keyword' => ['type' => 'string', 'description' => 'The search term for finding videos.']
                    ],
                    'required' => ['keyword']
                ]
            ],
            [
                'name' => 'royalty_free_image_search',
                'description' => 'Search royalty free image sources using a short stock-photo keyword phrase, not an AI image prompt. Use 2-4 concrete words such as "domestic cat", "gaming laptop", or "team meeting".',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'keyword' => ['type' => 'string', 'description' => 'Short stock-photo keywords only, usually 2-4 words. Do not include style, lighting, composition, background, or art-direction instructions.']
                    ],
                    'required' => ['keyword']
                ]
            ],
        ];

        if (is_plugin_active('fbomatic-facebook-post-generator/fbomatic-facebook-post-generator.php')) {
            $tools[] = [
                'name' => 'publish_facebook_post',
                'description' => 'Publish a text post or link to a selected Facebook page.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'content' => ['type' => 'string', 'description' => 'The text content.'],
                        'url' => ['type' => 'string', 'description' => 'Optional URL.']
                    ],
                    'required' => ['content']
                ]
            ];
            $tools[] = [
                'name' => 'publish_facebook_image',
                'description' => 'Publish an image with a caption to a selected Facebook page.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'image_url' => ['type' => 'string', 'description' => 'The direct URL of the image to post.'],
                        'caption' => ['type' => 'string', 'description' => 'The caption text for the image.']
                    ],
                    'required' => ['image_url']
                ]
            ];
        }

        if (is_plugin_active('twitomatic-twitter-post-generator/twitomatic-twitter-post-generator.php')) {
            $tools[] = [
                'name' => 'publish_twitter_x_post',
                'description' => 'Publish a post to Twitter (X).',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'content' => ['type' => 'string', 'description' => 'The tweet text.'],
                        'image_url' => ['type' => 'string', 'description' => 'Optional image URL.']
                    ],
                    'required' => ['content']
                ]
            ];
        }

        if (is_plugin_active('threadsomatic-threads-auto-poster/threadsomatic-threads-auto-poster.php')) {
            $tools[] = [
                'name' => 'publish_threads_post',
                'description' => 'Publish a post to Instagram Threads.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'content' => ['type' => 'string', 'description' => 'The thread text content.'],
                        'image_url' => ['type' => 'string', 'description' => 'Optional image URL to attach.']
                    ],
                    'required' => ['content']
                ]
            ];
        }

        if (is_plugin_active('instamatic-instagram-post-generator/instamatic-instagram-post-generator.php')) {
            $tools[] = [
                'name' => 'publish_instagram_post',
                'description' => 'Publish a post to Instagram.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'image_url' => ['type' => 'string', 'description' => 'The image URL.'],
                        'content' => ['type' => 'string', 'description' => 'Optional Instagram post text.']
                    ],
                    'required' => ['image_url']
                ]
            ];
        }

        if (is_plugin_active('pinterestomatic-pinterest-post-generator/pinterestomatic-pinterest-post-generator.php')) {
            $tools[] = [
                'name' => 'publish_pinterest_post',
                'description' => 'Publish an image post to Pinterest boards.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'image_url' => ['type' => 'string', 'description' => 'The direct URL of the image to pin.'],
                        'title' => ['type' => 'string', 'description' => 'The title of the Pinterest pin.'],
                        'description' => ['type' => 'string', 'description' => 'The description or caption for the pin.'],
                        'pin_url' => ['type' => 'string', 'description' => 'Optional source URL the pin should link to.']
                    ],
                    'required' => ['image_url']
                ]
            ];
        }
        if (is_plugin_active('businessomatic-google-my-business-post-generator/businessomatic-google-my-business-post-generator.php')) {
            $tools[] = [
                'name' => 'publish_google_my_business_post',
                'description' => 'Publish a post with an image to Google My Business.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'image_url' => ['type' => 'string', 'description' => 'The direct URL of the image to include in the GMB post.'],
                        'content' => ['type' => 'string', 'description' => 'The text content of the Google My Business post.']
                    ],
                    'required' => ['image_url', 'content']
                ]
            ];
        }

        if (is_plugin_active('youtubomatic-youtube-post-generator/youtubomatic-youtube-post-generator.php')) {
            $tools[] = [
                'name' => 'publish_youtube_community_post',
                'description' => 'Publish a text or image post to the YouTube Community tab.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'post_type' => ['type' => 'string', 'description' => 'The type of post: "image" or "text".'],
                        'content' => ['type' => 'string', 'description' => 'The text content of the community post.'],
                        'image_url' => ['type' => 'string', 'description' => 'Optional image URL for image-type posts.']
                    ],
                    'required' => ['post_type', 'content']
                ]
            ];
        }

        if (is_plugin_active('redditomatic-reddit-post-generator/redditomatic-reddit-post-generator.php')) {
            $tools[] = [
                'name' => 'publish_reddit_post',
                'description' => 'Publish a new post to specified subreddits.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'title' => ['type' => 'string', 'description' => 'The title of the Reddit post.'],
                        'content' => ['type' => 'string', 'description' => 'The body text or content of the post.']
                    ],
                    'required' => ['title', 'content']
                ]
            ];
        }

        if (is_plugin_active('linkedinomatic-linkedin-post-generator/linkedinomatic-linkedin-post-generator.php')) {
            $tools[] = [
                'name' => 'publish_linkedin_post',
                'description' => 'Publish a post to LinkedIn with title, content and optional description, link and image. Use this only when the task explicitly requires posting to LinkedIn.',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'title' => ['type' => 'string', 'description' => 'The title of the LinkedIn post.'],
                        'content' => ['type' => 'string', 'description' => 'The main article or post content.'],
                        'description' => ['type' => 'string', 'description' => 'A short summary or description for the post link.'],
                        'link' => ['type' => 'string', 'description' => 'Optional URL to share in the post.'],
                        'image_url' => ['type' => 'string', 'description' => 'Optional direct URL of an image to attach.']
                    ],
                    'required' => ['title', 'content']
                ]
            ];
        }
        $aiomatic_Main_Settings = get_option('aiomatic_Main_Settings', false);
        $image_engines = [];
        if (!empty($aiomatic_Main_Settings['app_id']) && trim($aiomatic_Main_Settings['app_id']) !== '') {
            $image_engines[] = ['n' => 'generate_ai_image_openai', 'e' => 'OpenAI'];
        }
        if (!empty($aiomatic_Main_Settings['stability_app_id'])) {
            $image_engines[] = ['n' => 'generate_ai_image_stable_diffusion', 'e' => 'Stable Diffusion'];
        }
        if (!empty($aiomatic_Main_Settings['app_id_google'])) {
            $image_engines[] = ['n' => 'generate_ai_image_google', 'e' => 'Google Imagen'];
        }
        if (!empty($aiomatic_Main_Settings['midjourney_app_id'])) {
            $image_engines[] = ['n' => 'generate_ai_image_midjourney', 'e' => 'Midjourney'];
        }
        if (!empty($aiomatic_Main_Settings['replicate_app_id'])) {
            $image_engines[] = ['n' => 'generate_ai_image_replicate', 'e' => 'Replicate'];
        }
        if (!empty($aiomatic_Main_Settings['ideogram_app_id'])) {
            $image_engines[] = ['n' => 'generate_ai_image_ideogram', 'e' => 'Ideogram'];
        }
        if (!empty($aiomatic_Main_Settings['cloudflare_worker_url']) && !empty($aiomatic_Main_Settings['cloudflare_worker_secret'])) {
            $image_engines[] = ['n' => 'generate_ai_image_cloudflare', 'e' => 'Cloudflare Worker'];
        }
        foreach ($image_engines as $tool) {
            $tools[] = [
                'name' => $tool['n'],
                'description' => "Generate an image using {$tool['e']}.",
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'prompt' => [
                            'type' => 'string',
                            'description' => 'Visual description.'
                        ]
                    ],
                    'required' => ['prompt']
                ]
            ];
        }
        $tools[] = [
            'name' => 'list_available_ai_agents',
            'description' => 'Retrieve a list of all specialized sub-agents (e.g., SEO expert, Coder, Researcher) available for delegation.',
            'parameters' => [
                'type' => 'object',
                'properties' => [], 
            ]
        ];

        $tools[] = [
            'name' => 'delegate_to_ai_agent',
            'description' => 'Delegate a task to a more suitable agent if the task is outside your expertise. Use list_available_ai_agents first to discover available agents. When delegating a task, be as detailed as possible, also add any information you already have on the task, so the delegated agent will be able to handle it efficiently.',
            'parameters' => [
                'type' => 'object',
                'properties' => [
                    'agent_id' => ['type' => 'string', 'description' => 'The ID of the specialized agent to call.'],
                    'task' => ['type' => 'string', 'description' => 'The detailed prompt/instruction for the sub-agent.']
                ],
                'required' => ['agent_id', 'task']
            ]
        ];

        $tools[] = [
            'name' => 'read_server_file',
            'description' => 'Read the contents of a file on the server. Allowed file types: txt, csv, json, log. Use for reading data files, logs, or configurations.',
            'parameters' => [
                'type' => 'object',
                'properties' => [
                    'file_path' => ['type' => 'string', 'description' => 'The relative path from the WP root to the file.']
                ],
                'required' => ['file_path']
            ]
        ];

        $tools[] = [
            'name' => 'write_server_file',
            'description' => 'Write content to a secure sandbox folder inside uploads/aiomatic-exports. Only txt, log, csv, json, and md files are allowed. Use this for exporting reports, logs, datasets, or generated files.',
            'parameters' => [
                'type' => 'object',
                'properties' => [
                    'filename' => [
                        'type' => 'string',
                        'description' => 'The output filename only, without directories. Example: report.json'
                    ],
                    'content' => [
                        'type' => 'string',
                        'description' => 'The file content to write.'
                    ],
                    'overwrite' => [
                        'type' => 'boolean',
                        'description' => 'Whether to overwrite an existing file. Default is false.'
                    ]
                ],
                'required' => ['filename', 'content']
            ]
        ];
            
        $indexed = [];
        foreach ($tools as $tool) {
            $indexed[$tool['name']] = $tool;
        }
        return $indexed;
    }
    private function log_run($step, $type, $data = [])
    {
        global $wpdb;
        if($type === 'tool_call')
        {
            $this->did_tool_call = true;
        }
        $table = $wpdb->prefix . 'aiomatic_agent_runs';
        if(isset($data['result']) && is_array($data['result']))
        {
            $data['result'] = wp_json_encode($data['result']);
        }
        $wpdb->insert(
            $table,
            [
                'agent_id' => $this->agent_id,
                'step' => $step,
                'type' => $type,
                'tool_name' => $data['tool'] ?? null,
                'prompt' => isset($data['prompt']) ? substr($data['prompt'],0,4000) : null,
                'response' => isset($data['response']) ? substr($data['response'],0,4000) : null,
                'params' => isset($data['params']) ? wp_json_encode($data['params']) : null,
                'result' => isset($data['result']) ? substr($data['result'],0,4000) : null
            ],
            ['%d','%d','%s','%s','%s','%s','%s','%s']
        );
    }
    private function add_to_short_memory($role, $content) {
        if (!$this->config['short_term_memory_enabled']) {
            return;
        }
        if(is_array($content))
        {
            $content = wp_json_encode($content);
        }
        if(!is_string($content))
        {
            $content = (string) $content;
        }
        $last = end($this->short_memory);
        if ($last)
        {
            if ($last['role'] === $role && $last['content'] === $content) {
                return;
            }
            if($role === 'agent' && $last['role'] === 'system' && strstr($last['content'], 'TOOL RESULT [') !== false && strstr($last['content'], $content) !== false)
            {
                return;
            }
        }
        $this->short_memory[] = ['role' => $role, 'content' => $content];
        update_post_meta($this->agent_id, '_agent_memory', wp_json_encode($this->short_memory));
    }

    private function retrieve_relevant_memories($query, $top_k = 5)
    {
        if (!aiomatic_long_term_memory_available()) {
            $this->config['long_term_memory_enabled'] = false;
        }
        if (!$this->config['long_term_memory_enabled']) {
            return [];
        }
        $aiomatic_Main_Settings = get_option('aiomatic_Main_Settings', false);
        $appids = preg_split('/\r\n|\r|\n/', trim($aiomatic_Main_Settings['app_id']));
        $appids = array_filter($appids);
        if (empty($appids)) {
            return [];
        }
        $token = $appids[array_rand($appids)];
        $token = apply_filters('aimogen_openai_api_key', $token);$token = apply_filters('aiomatic_openai_api_key', $token);
        $namespace = 'agents_' . $this->agent_id;

        $embed_rez = aiomatic_embeddings_result($query, $token, $namespace);
        if (
            !is_array($embed_rez) ||
            !isset($embed_rez['status']) ||
            $embed_rez['status'] !== 'success' ||
            empty($embed_rez['data']) ||
            in_array($embed_rez['data'], [
                'No results found',
                'No data returned',
                'No embeddings are added in the plugin config!'
            ])
        ) {
            return [];
        }
        if ($embed_rez['status'] === 'success') {
            return [
                [
                    'score' => $embed_rez['score'] ?? 0.5,
                    'content' => $embed_rez['data']
                ]
            ];
        }

        return array_map(function($m){
            return ['score' => 0.5, 'content' => $m['content']];
        }, array_slice(array_reverse($this->short_memory), 0, $top_k));
    }
    
    private function trim_short_memory($trim_len = 20)
    {        
        if (count($this->short_memory) <= $trim_len) {
            return;
        }
        $keep_start = min(5, intval($trim_len / 4));
        $keep_end = $trim_len - $keep_start;

        if ($keep_end < 0) {
            $keep_end = 0;
        }
        $this->short_memory = array_merge(
            array_slice($this->short_memory, 0, $keep_start),
            array_slice($this->short_memory, -$keep_end)
        );

        update_post_meta($this->agent_id, '_agent_memory', wp_json_encode($this->short_memory));
    }
    private function add_to_long_term_memory($content)
    {
        if (!aiomatic_long_term_memory_available()) {
            $this->config['long_term_memory_enabled'] = false;
        }
        if (!$this->config['long_term_memory_enabled']) {
            return false;
        }
        $aiomatic_Main_Settings = get_option('aiomatic_Main_Settings', false);

        $appids = preg_split('/\r\n|\r|\n/', trim($aiomatic_Main_Settings['app_id'] ?? ''));
        $appids = array_filter($appids);

        if (empty($appids)) {
            return false;
        }

        $token = $appids[array_rand($appids)];
        $token = apply_filters('aimogen_openai_api_key', $token);
        $token = apply_filters('aiomatic_openai_api_key', $token);

        $namespace = 'agents_' . $this->agent_id;
        $embedding = new Aiomatic_Embeddings($token);

        $rez = $embedding->aiomatic_create_single_embedding_nojson($content, $namespace);

        if (!is_array($rez) || (is_array($rez) && isset($rez['status']) && $rez['status'] === 'error')) {
            aiomatic_log_to_file('Failed to store agent memory: ' . print_r($rez, true));
            return false;
        }

        return true;
    }

    private function summarize_old_memory($max_keep = 14, $summary_model = null)
    {
        $last_summary_time = get_post_meta($this->agent_id, '_last_summary_time', true);
        $now = current_time('timestamp');

        if ($last_summary_time && ($now - $last_summary_time < 300)) {
            return;
        }

        $total_messages = count($this->short_memory);

        if ($total_messages <= $max_keep) {
            return;
        }

        $model_for_summary = $summary_model ?? $this->model;

        $keep_recent = $max_keep - 1;

        $old_part = array_slice($this->short_memory, 0, -$keep_recent);
        $recent_part = array_slice($this->short_memory, -$keep_recent);

        $existing_summary = '';
        if (!empty($this->short_memory)) {
            $first = $this->short_memory[0];
            if (
                isset($first['role'], $first['content']) &&
                $first['role'] === 'system' &&
                strpos($first['content'], 'Summary of earlier') !== false
            ) {
                $existing_summary = $first['content'];
            }
        }

        $old_text = '';
        foreach ($old_part as $msg) {
            if (empty($msg['content'])) {
                continue;
            }

            $role = strtoupper($msg['role'] ?? 'UNKNOWN');

            $content = mb_substr($msg['content'], 0, 400);
            $content = preg_replace('/\s+\S*$/', '', $content);

            $old_text .= "$role: $content\n\n";
        }

        if (empty(trim($old_text))) {
            return;
        }

        $summary_prompt = "You are a memory summarizer.\n";

        if (!empty($existing_summary)) {
            if (aiomatic_strlen($existing_summary) > 3000) {
                $existing_summary = aiomatic_substr($existing_summary, -3000);
            }
            $summary_prompt .= "Existing summary:\n" . $existing_summary . "\n\n";
        }

        $summary_prompt .=
            "Summarize the following conversation history very concisely.\n" .
            "Keep only:\n" .
            "- key facts\n" .
            "- decisions\n" .
            "- tool results\n" .
            "- important observations\n" .
            "- unresolved questions\n\n" .
            "Ignore:\n" .
            "- chit-chat\n" .
            "- repetition\n" .
            "- formatting instructions\n\n" .
            $old_text . "\n\nUpdated Summary:";

        $aiomatic_Main_Settings = get_option('aiomatic_Main_Settings', false);
        $appids = array_filter(preg_split('/\r\n|\r|\n/', trim($aiomatic_Main_Settings['app_id'] ?? '')));
        $token = !empty($appids) ? $appids[array_rand($appids)] : '';
        $token = apply_filters('aiomatic_openai_api_key', $token);

        $query_token_count = count(aiomatic_encode($summary_prompt));
        $max_tokens = aimogenpro_get_max_tokens($model_for_summary);
        $available_tokens = aiomatic_compute_available_tokens(
            $model_for_summary,
            $max_tokens,
            $summary_prompt,
            $query_token_count
        );

        if ($available_tokens <= AIMOGEN_MINIMUM_TOKENS_FOR_COMPLETIONS) {
            $cut = intval(aiomatic_strlen($summary_prompt) / 2);
            $summary_prompt = trim(aiomatic_substr($summary_prompt, 0, -$cut));

            $query_token_count = count(aiomatic_encode($summary_prompt));
            $available_tokens = $max_tokens - $query_token_count;
        }

        $thread_id = '';
        $aierror = '';
        $finish_reason = '';
        if($this->is_debug_mode())
        {
            $this->debug_log('AI summary call: ' . print_r($summary_prompt, true));
        }
        $summary = aiomatic_generate_text($token, $model_for_summary, $summary_prompt, $available_tokens, 1, 1, 0, 0, false, 'agentsSummary', 0, $finish_reason, $aierror, false, false, false, '', '', 'user', '', $thread_id, '', 'disabled', '', false, false, array(), '', '', '');
        if($this->is_debug_mode())
        {
            $this->debug_log('AI summary response: ' . print_r($summary, true));
        }
        if ($summary === false) {
            aiomatic_log_to_file('Failed to summarize agent memory.');
            return;
        }

        $this->short_memory = array_merge(
            [[
                'role' => 'system',
                'content' => "Summary of earlier steps and knowledge:\n" . trim($summary)
            ]],
            $recent_part
        );

        update_post_meta($this->agent_id, '_agent_memory', wp_json_encode($this->short_memory));
        update_post_meta($this->agent_id, '_last_summary_time', $now);
    }
    public function debug_log($str)
    {
        if(function_exists('error_log'))
        {
            $d = date("j-M-Y H:i:s e", current_time( 'timestamp' ));
            $log_file = WP_CONTENT_DIR . '/agent_debug.log';
            error_log("[" . $d . "][" . $this->agent_id . "] " . $str . "<br/>\r\n", 3, $log_file);
        }
    }
    private function build_react_prompt($current_task) {
        if ($this->cached_ltm === null || $this->cached_ltm_query !== $current_task) {
            $this->cached_ltm = $this->retrieve_relevant_memories($current_task);
            $this->cached_ltm_query = $current_task;
        }
        $ltm = $this->cached_ltm;
        if(!empty($ltm))
        {
            $ltm_text = "LONG-TERM MEMORY (use when relevant):\n";
            foreach ($ltm as $item) {
                $ltm_text .= "- " . $item['content'] . "\n";
            }
        }
        else
        {
            $ltm_text = "";
        }

        $history = "";
        foreach ($this->short_memory as $msg) {
            $history .= ucfirst($msg['role']) . ": " . $msg['content'] . "\n\n";
        }

        $tools_json = wp_json_encode($this->tools);
        $task_data = json_decode($current_task, true);

        if (is_array($task_data)) {
            $info_added = false;
            if (!empty($task_data['goal'])) {
                $task_text = "GOAL:\n" . ($task_data['goal'] ?? '') . "\n\n";
                $info_added = true;
            }
            if (!empty($task_data['input'])) {
                $task_text .= "INPUT:\n" . $task_data['input'] . "\n\n";
                $info_added = true;
            }

            if (!empty($task_data['constraints'])) {
                $task_text .= "CONSTRAINTS:\n- " . implode("\n- ", $task_data['constraints']) . "\n\n";
                $info_added = true;
            }

            if (!empty($task_data['output_format'])) {
                $task_text .= "EXPECTED OUTPUT:\n" . $task_data['output_format'] . "\n\n";
                $info_added = true;
            }
            if(!$info_added)
            {
                $task_text = $current_task;
            }
        } else {
            $task_text = $current_task;
        }
        $ret_prompt = $this->system_prompt . "\n\n";
        if(!empty($ltm_text))
        {
            $ret_prompt .= $ltm_text . "\n\n";
        }
        if (!$this->config['tool_calls_enabled']) 
        {
            if(!empty($tools_json))
            {
                $ret_prompt .=
                "AVAILABLE TOOLS (JSON SCHEMA):\n" . $tools_json . "\n\n";
            }
        }
        if(!empty($history))
        {
            $ret_prompt .= "HISTORY:\n" . $history . "\n";
        }
        $ret_prompt .= "STRICT OUTPUT RULES:\n
- You MUST respond in EXACT format.\n
\n";
if ($this->config['tool_calls_enabled']) {
    $ret_prompt .= "- You can use tools if needed to accomplish the task. Use them wisely for tasks that require specific expertise, data retrieval, or actions beyond text generation.\n";
}
else
{
    $ret_prompt .= "If using a tool:\n
THOUGHT: ...\n
ACTION: tool_name\n
PARAMS: {valid JSON}\n
\n";
}
$ret_prompt .= "
If finishing:\n
FINAL ANSWER: ...\n
\n
Do NOT add extra text.\n
Do NOT explain format.\n
" . "PRIMARY OBJECTIVE (DO NOT CHANGE):\n" . $task_text . "\n\n";
        return $ret_prompt;
    }
    public function reset_and_run($new_input = null) {
        delete_post_meta($this->agent_id, '_agent_memory');
        delete_post_meta($this->agent_id, '_task_result');
        $this->reset_runtime_memory();
        update_post_meta($this->agent_id, '_agent_status', 'running');
        return $this->run($new_input);
    }
    public function start_task($task, $schedule_timestamp = 0)
    {
        if(get_post_status($this->agent_id) != 'publish')
        {
            return 'Agent is not published. Please publish it.';
        }
        if (empty($task)) {
            return 'Empty task.';
        }
        $status = get_post_meta($this->agent_id, '_agent_status', true);
        if ($status === 'running') {
            $last = (int) get_post_meta($this->agent_id, '_last_activity', true);

            if ($last && (time() - $last > 600)) {
                update_post_meta($this->agent_id, '_agent_status', 'idle');
            } else {
                return 'Agent already running.';
            }
        }
        if ($status === 'scheduled') {
            return 'Agent already scheduled.';
        }
        wp_clear_scheduled_hook('aiomatic_agent_run_single', [$this->agent_id, $task]);
        wp_clear_scheduled_hook('aiomatic_agent_recover', [$this->agent_id]);
        delete_post_meta($this->agent_id, '_agent_memory');
        delete_post_meta($this->agent_id, '_task_result');
        $this->reset_runtime_memory();
        update_post_meta($this->agent_id, '_current_task', $task);
        update_post_meta($this->agent_id, '_task_started_at', time());
        update_post_meta($this->agent_id, '_last_activity', time());
        update_post_meta($this->agent_id, '_agent_status', $schedule_timestamp > 0 ? 'scheduled' : 'running');
        delete_post_meta($this->agent_id, '_agent_recover_count');
        delete_post_meta($this->agent_id, '_agent_current_step');
        delete_post_meta($this->agent_id, '_agent_step_retries');
        $run_time = $schedule_timestamp > 0 ? $schedule_timestamp : time() + 1;
        wp_schedule_single_event($run_time, 'aiomatic_agent_run_single', [
            $this->agent_id,
            $task
        ]);
        if (!wp_next_scheduled('aiomatic_agents_watchdog')) {
            wp_schedule_event(time() + 600, 'aiomatic_cron', 'aiomatic_agents_watchdog');
        }
        if ($schedule_timestamp > 0) {
            return 'Task scheduled.';
        }
        return 'Task started.';
    }
    public function cancel_schedule()
    {
        wp_clear_scheduled_hook('aiomatic_agent_run_single', [$this->agent_id, get_post_meta($this->agent_id, '_current_task', true)]);
        wp_clear_scheduled_hook('aiomatic_agent_recover', [$this->agent_id]);
        update_post_meta($this->agent_id, '_agent_status', 'cancelled');
        update_post_meta($this->agent_id, '_task_finished_at', time());
        delete_post_meta($this->agent_id, '_current_task');
        update_post_meta($this->agent_id, '_last_activity', time());
        $this->log_run(999, 'task_cancelled', [
            'result' => 'Task schedule manually cancelled'
        ]);
    }
    public function stop_task()
    {
        wp_clear_scheduled_hook('aiomatic_agent_run_single', [$this->agent_id, get_post_meta($this->agent_id, '_current_task', true)]);
        wp_clear_scheduled_hook('aiomatic_agent_recover', [$this->agent_id]);
        update_post_meta($this->agent_id, '_agent_status', 'cancelled');
        update_post_meta($this->agent_id, '_task_finished_at', time());
        delete_post_meta($this->agent_id, '_current_task');
        update_post_meta($this->agent_id, '_last_activity', time());
        $this->log_run(999, 'task_cancelled', [
            'result' => 'Task manually stopped'
        ]);
        $this->add_to_short_memory('system', 'TASK CANCELLED: Task manually stopped.');
        $this->add_to_long_term_memory('TASK CANCELLED: Task manually stopped.');
    }
    public function get_current_task_info()
    {
        return [
            'task'     => get_post_meta($this->agent_id, '_current_task', true),
            'status'   => get_post_meta($this->agent_id, '_agent_status', true),
            'started'  => get_post_meta($this->agent_id, '_task_started_at', true),
            'finished' => get_post_meta($this->agent_id, '_task_finished_at', true),
            'result'   => get_post_meta($this->agent_id, '_task_result', true),
        ];
    }
    public function handle_fatal_shutdown() {
        $error = error_get_last();
        if (!$error) {
            return;
        }
        if (!in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR])) {
            return;
        }
        $status = get_post_meta($this->agent_id, '_agent_status', true);
        if (in_array($status, ['completed', 'failed', 'cancelled', 'paused', 'scheduled', 'idle'])) {
            return;
        }
        update_post_meta($this->agent_id, '_agent_status', 'interrupted');
        if (!wp_next_scheduled('aiomatic_agent_recover', [$this->agent_id])) {
            wp_schedule_single_event(time() + 5, 'aiomatic_agent_recover', [$this->agent_id]);
        }
    }
    public function aiomatic_resume_agent() 
    {
        $status = get_post_meta($this->agent_id, '_agent_status', true);
        if ($status !== 'paused' && $status !== 'interrupted') {
            return 'Agent is not paused.';
        }
        update_post_meta($this->agent_id, '_agent_status', 'running');
        $this->run();
    }
    public function run($input = null)
    {
        if('publish' !== get_post_status( $this->agent_id ))
        {
            $message = 'Agent is not published. Please publish the agent to run it.';
            $this->add_to_short_memory('system', $message);
            return $message;
        }
        if(is_array($input))
        {
            $input = wp_json_encode($input);
        }
        $status = get_post_meta($this->agent_id, '_agent_status', true);

        if ($status === 'completed' || $status === 'failed' || $status === 'paused') {
            $message = 'Agent already finished or paused.';
            $this->add_to_short_memory('system', $message);
            return $message;
        }
        aiomatic_set_last_activity(
            'agent',
            ['agent_id' => $this->agent_id]
        );
        $start_time = time();
        $time_limit = (int) ini_get('max_execution_time');
        if ($time_limit === 0) $time_limit = 60;

        if ($input) {
            $this->add_to_short_memory('user', $input);
            update_post_meta($this->agent_id, '_current_task', $input);
            update_post_meta($this->agent_id, '_last_activity', time());
        }
        $trim_len = aiomatic_long_term_memory_available() ? 20 : 40;
        $this->trim_short_memory($trim_len);
        $short_mem_trim = aiomatic_long_term_memory_available() ? 14 : 20;
        if (count($this->short_memory) > $short_mem_trim) {
            $this->summarize_old_memory($short_mem_trim);
        }
        if ($input) {
            $current_task = $input;
        }
        else
        {
            $current_task = get_post_meta($this->agent_id, '_current_task', true) ?: 'No task';
        }
        $saved_retries = get_post_meta($this->agent_id, '_agent_step_retries', true);
        $this->step_retries = is_array($saved_retries) ? $saved_retries : [];   
        $max_steps = (int) ($this->config['max_steps'] ?? 20);
        $aiomatic_Main_Settings    = get_option('aiomatic_Main_Settings', false);
        $appids = array_filter(preg_split('/\r\n|\r|\n/', trim($aiomatic_Main_Settings['app_id'] ?? '')));
        $token = !empty($appids) ? $appids[array_rand($appids)] : '';
        $token = apply_filters('aiomatic_openai_api_key', $token);
        if ($this->config['planning_enabled']) {

            $planning_prompt = "You are a planning module.\n".
                "Break the task into a clear step-by-step plan.\n".
                "Be concise.\n\nTask:\n" . $current_task . "\n\nPlan:";
            $query_token_count = count(aiomatic_encode($planning_prompt));
            $max_tokens = aimogenpro_get_max_tokens($this->model);
            $available_tokens = aiomatic_compute_available_tokens($this->model, $max_tokens, $planning_prompt, $query_token_count);
            if($available_tokens <= AIMOGEN_MINIMUM_TOKENS_FOR_COMPLETIONS)
            {
                $string_len = aiomatic_strlen($planning_prompt);
                $string_len = $string_len / 2;
                $string_len = intval(0 - $string_len);
                $planning_prompt = aiomatic_substr($planning_prompt, 0, $string_len);
                $planning_prompt = trim($planning_prompt);
                $query_token_count = count(aiomatic_encode($planning_prompt));
                $available_tokens = $max_tokens - $query_token_count;
            }
            $thread_id = '';
            $aierror = '';
            $finish_reason = '';
            if($this->is_debug_mode())
            {
                $this->debug_log('AI planning call: ' . print_r($planning_prompt, true));
            }
            $plan = aiomatic_generate_text($token, $this->model, $planning_prompt, $available_tokens, 1, 1, 0, 0, false, 'agentPlan', 0, $finish_reason, $aierror, false, false, false, '', '', 'user', '', $thread_id, '', 'disabled', '', false, false, array(), '', '', '');
            if($this->is_debug_mode())
            {
                $this->debug_log('AI planning response: ' . print_r($plan, true));
            }
            if ($plan) {
                $this->add_to_short_memory('system', "PLAN:\n" . $plan);

                if ($this->config['planning_required']) {
                    $current_task = "Follow this plan strictly:\n\n" . $plan . "\n\nOriginal task:\n" . $current_task;
                }
            }
        }
        if ($this->config['tool_calls_enabled']) {
            require_once(dirname(__FILE__) . "/../aiomatic-god-mode-parser-agents.php");
        }
        $no_action_steps = 0;
        $start_step = (int) get_post_meta($this->agent_id, '_agent_current_step', true);
        for ($step = $start_step; $step < $max_steps; $step++) {
            update_post_meta($this->agent_id, '_last_activity', time());
            update_post_meta($this->agent_id, '_agent_current_step', $step);
            update_post_meta($this->agent_id, '_agent_step_retries', $this->step_retries);
            $this->did_tool_call = false;
            $current_status = get_post_meta($this->agent_id, '_agent_status', true);
            if ($current_status === 'paused' || $current_status === 'cancelled') {
                $message = "Agent stopped: Status is currently $current_status.";
                $this->add_to_short_memory('system', $message);
                return $message;
            }

            $resumes = (int) get_post_meta($this->agent_id, '_agent_recover_count', true);
            if ($resumes >= 2) {
                update_post_meta($this->agent_id, '_agent_status', 'failed');
                $message = "Execution stopped after multiple resumes (limit reached).";
                $this->add_to_short_memory('system', $message);
                $this->add_to_long_term_memory('TASK ABORTED [' . $current_task . '] Reason: ' . $message);
                return $message;
            }

            $soft_limit = (int) ($time_limit * 0.8);
            if ((time() - $start_time) > $soft_limit) {
                update_post_meta($this->agent_id, '_agent_status', 'interrupted');
                update_post_meta($this->agent_id, '_agent_recover_count', $resumes + 1);
                if (!wp_next_scheduled('aiomatic_agent_recover', [$this->agent_id])) {
                    wp_schedule_single_event(time() + 10, 'aiomatic_agent_recover', [$this->agent_id]);
                }
                $message = "Execution paused to avoid timeout. Resume has been scheduled.";
                $this->add_to_short_memory('system', $message);
                $this->add_to_long_term_memory('TASK PAUSED [' . $current_task . '] Reason: ' . $message);
                return $message;
            }
            $prompt = $this->build_react_prompt($current_task);
            $this->log_run($step, 'model_prompt', [
                'prompt' => $prompt
            ]);

            $query_token_count = count(aiomatic_encode($prompt));
            $max_tokens = aimogenpro_get_max_tokens($this->model);
            $available_tokens = aiomatic_compute_available_tokens($this->model, $max_tokens, $prompt, $query_token_count);
            if($available_tokens <= AIMOGEN_MINIMUM_TOKENS_FOR_COMPLETIONS)
            {
                $string_len = aiomatic_strlen($prompt);
                $string_len = $string_len / 2;
                $string_len = intval(0 - $string_len);
                $prompt = aiomatic_substr($prompt, 0, $string_len);
                $prompt = trim($prompt);
                $query_token_count = count(aiomatic_encode($prompt));
                $available_tokens = $max_tokens - $query_token_count;
            }
            if ($this->config['tool_calls_enabled']) {
                add_filter('aiomatic_ai_functions', 'aiomatic_add_agent_tools', 999, 2);
                $forced_functions = $this->tools;
                $context_filter = function($ctx = []) use ($step) {
                    return [
                        'agent_id' => $this->agent_id,
                        'step'     => $step,
                    ];
                };

                add_filter('aiomatic_agent_context', $context_filter, 10, 1);

                $log_result = function($payload, $is_direct = true) {
                    $ctx = apply_filters('aiomatic_agent_context', []);

                    if (empty($ctx['agent_id'])) 
                    {
                        return;
                    }

                    $agent = Aiomatic_Agent::get_instance_by_id((int)$ctx['agent_id']);
                    if (!$agent) 
                    {
                        return;
                    }
                    $tool_name = $payload['tool_call_id'] ?? 'unknown';
                    $content   = $payload['content'] ?? '';
                    if(empty($content))
                    {
                        $content   = $payload['output'] ?? '';
                    }

                    $agent->log_native_tool_result(
                        $ctx['step'] ?? 0,
                        $tool_name,
                        $content,
                        $is_direct
                    );
                    if($agent->is_debug_mode())
                    {
                        $agent->debug_log('TOOL RESULT [' . $tool_name . ']: ' . print_r($content, true));
                    }
                };
                add_action('aiomatic_tool_result', $log_result, 10, 1);
                $tool_direct_logger = function($payload) use ($log_result) {
                    $log_result($payload, true);
                };
                add_action('aiomatic_tool_direct_message', $tool_direct_logger, 10, 1);
            }
            else
            {
                $forced_functions = [];
            }
            $thread_id = '';
            $aierror = '';
            $finish_reason = '';
            if($this->is_debug_mode())
            {
                $this->debug_log('Agent step call: ' . print_r($prompt, true));
            }
            $response = aiomatic_generate_text($token, $this->model, $prompt, $available_tokens, 1, 1, 0, 0, false, 'agentsStep', 0, $finish_reason, $aierror, false, false, false, '', '', 'user', '', $thread_id, '', 'disabled', '', false, false, $forced_functions, '', '', '');
            if($this->is_debug_mode())
            {
                $this->debug_log('Agent step response: ' . print_r($response, true));
            }
            if ($this->config['tool_calls_enabled']) {
                remove_filter('aiomatic_ai_functions', 'aiomatic_add_agent_tools', 999);
                remove_filter('aiomatic_agent_context', $context_filter, 10);
                remove_action('aiomatic_tool_result', $log_result, 10);
                remove_action('aiomatic_tool_direct_message', $tool_direct_logger, 10, 1);
            }
            if($response === false)
            {
                if(empty($aierror))
                {
                    $aierror = 'AI API call failed';
                }
                $this->log_run($step, 'model_error', ['response' => $aierror]);
                $this->add_to_short_memory('system', "Failed to call the AI: " . $aierror);
                continue;
            }
            $last_assistant = '';
            for ($i = count($this->short_memory) - 1; $i >= 0; $i--) {
                if (($this->short_memory[$i]['role'] ?? '') === 'agent') {
                    $last_assistant = (string) $this->short_memory[$i]['content'];
                    break;
                }
            }
            if (!empty($last_assistant) && trim($last_assistant) === trim($response)) {
                $this->add_to_short_memory('system', 'You are repeating yourself. Stop asking and proceed using reasonable assumptions.');
                continue;
            }
            $this->log_run($step, 'model_response', [
                'response' => $response
            ]);
            $this->add_to_short_memory('agent', $response);
            $has_final  = strpos($response, 'FINAL ANSWER:') !== false;
            $has_action = preg_match('/ACTION:\s*([a-zA-Z0-9_\-]+)/i', $response);

            if ($has_final) {
                $no_action_steps = 0;
            } else {
                if (!$this->did_tool_call && !$has_action) {
                    $no_action_steps++;
                } else {
                    $no_action_steps = 0;
                }
            }
            if ($no_action_steps >= 3) {

                $this->add_to_short_memory('system',
                    "You are stuck. You have not used any tools in the last 3 steps.\n" .
                    "Stop asking questions. Take action immediately.\n" .
                    "Use available tools to move forward and complete the task."
                );

                $no_action_steps = 0; 
                continue;
            }
            if (!$this->config['tool_calls_enabled']) 
            {
                $has_action = preg_match('/ACTION:/i', $response);
                if (!$has_action && !$has_final) {
                    $reminder = "STRICT OUTPUT RULES:\n
    - You MUST respond in EXACT format.\n";
    if ($this->config['tool_calls_enabled']) {
        $reminder .= "
        You can call tools if needed.\n
    ";
    }
    else
    {
        $reminder .= "
    - If using a tool:\n
    THOUGHT: ...\n
    ACTION: tool_name\n
    PARAMS: {valid JSON}\n";
    }
    $reminder .= "
    \n
    - If finishing:\n
    FINAL ANSWER: ...\n
    \n
    - Do NOT add extra text.\n
    - Do NOT explain format.\n";
    if (!$this->config['tool_calls_enabled']) {
        $reminder .= "THOUGHT: ...\nACTION: tool_name\nPARAMS: {...}\n\n" .
                                "or\n\nFINAL ANSWER: ...\n\n";
    }
    $reminder .= "This is a format violation. You MUST fix it.\n
    Previous response did not follow the required format. Try again.";
                    $this->add_to_short_memory('system', 'FORMAT ERROR: ' . $reminder);
                    continue;
                }
                if ($has_action &&
                    preg_match('/ACTION:\s*([a-zA-Z0-9_\-]+)/i', $response, $m) &&
                    preg_match('/PARAMS:\s*(?:```json)?\s*(\{[\s\S]*?\})\s*(?:```)?/', $response, $p)) {

                    $tool_name = trim($m[1]);
                    $params_raw = trim($p[1]);
                    $params = json_decode($params_raw, true);

                    if (json_last_error() !== JSON_ERROR_NONE) {
                        $this->add_to_short_memory('system', "Invalid JSON in PARAMS: " . json_last_error_msg() . "\nRaw input was: $params_raw\nPlease correct the JSON format.");
                        continue;
                    }

                    if (!isset($this->tools[$tool_name])) {
                        $this->add_to_short_memory('system', "Unknown tool: $tool_name. Available tools are listed above.");
                        continue;
                    }

                    $tool_key = "tool_" . $tool_name;
                    $max_retries = (int) ($this->config['max_tool_retries'] ?? 5);
                    if (($this->step_retries[$tool_key] ?? 0) >= $max_retries) {
                        $msg = "Tool '$tool_name' failed too many times. Try a different approach.";
                        $this->add_to_short_memory('system', $msg);
                        $this->add_to_long_term_memory($msg);
                        continue;
                    }

                    try {
                        $this->log_run($step, 'tool_call', [
                            'tool' => $tool_name,
                            'params' => $params
                        ]);
                        $this->add_to_short_memory(
                            'agent',
                            'TOOL CALL: ' . $tool_name . ' | PARAMS: ' . wp_json_encode($params)
                        );
                        if($this->is_debug_mode())
                        {
                            $this->debug_log('CALLING TOOL: ' . print_r($tool_name, true) . ' ' . print_r($params, true));
                        }
                        $result = $this->execute_tool($tool_name, $params);
                        $result_str = is_string($result) ? $result : wp_json_encode($result);
                        if (stripos($result_str, 'Error:') === 0) {
                            $this->step_retries[$tool_key] = ($this->step_retries[$tool_key] ?? 0) + 1;
                            update_post_meta($this->agent_id, '_agent_step_retries', $this->step_retries);
                        }
                        $this->log_run($step, 'tool_result', [
                            'tool' => $tool_name,
                            'params' => $params,
                            'result' => $result
                        ]);

                        $this->add_to_short_memory('system', "RESULT: " . $result_str);

                        if (strlen($result_str) > 30) {
                            $result_str = substr($result_str, 0, 2000);
                            $this->add_to_long_term_memory("TOOL RESULT [" . $tool_name . "]: " . $result_str);
                        }
                        if($this->is_debug_mode())
                        {
                            $this->debug_log('TOOL RESULT: ' . print_r($result_str, true));
                        }
                    } catch (\Throwable $e) {
                        $this->step_retries[$tool_key] = ($this->step_retries[$tool_key] ?? 0) + 1;
                        update_post_meta($this->agent_id, '_agent_step_retries', $this->step_retries);
                        $hint = $this->get_tool_retry_hint($tool_name, $e->getMessage());

                        $error_msg = "Tool '$tool_name' failed: " . $e->getMessage() .
                                    " (in " . $e->getFile() . ":" . $e->getLine() . ")";

                        $this->log_run($step, 'tool_error', [
                            'tool' => $tool_name,
                            'result' => $error_msg
                        ]);
                        $this->add_to_short_memory('system', $error_msg);
                        $this->add_to_short_memory('system', $hint);

                        if (stripos($error_msg, 'fatal') !== false || stripos($error_msg, 'permission') !== false) {
                            $this->add_to_long_term_memory('TOOL ERROR [' . $tool_name . ']: ' . $error_msg);
                        }
                    }

                    continue;
                }
            }
            if ($has_final) {
                preg_match('/FINAL ANSWER:\s*([\s\S]+)/i', $response, $final_m);
                $final = $final_m[1] ?? $response;
                $this->log_run($step, 'final', [
                    'result' => $final
                ]);
                $this->add_to_long_term_memory("TASK COMPLETED [" . $current_task . '] Result: ' . $final);
                update_post_meta($this->agent_id, '_agent_status', 'completed');
                delete_post_meta($this->agent_id, '_current_task');
                return $final;
            }
        }

        $failed_count = 0;
        foreach ($this->short_memory as $msg) {
            if (
                ($msg['role'] === 'system' || $msg['role'] === 'agent') &&
                (
                    stripos($msg['content'], 'TOOL ERROR') !== false ||
                    stripos($msg['content'], 'Tool failed') !== false ||
                    stripos($msg['content'], 'failed too many times') !== false
                )
            ) {
                $failed_count++;
            }
        }

        $msg = $failed_count >= 3
            ? "Agent stopped due to multiple tool failures."
            : "Max steps reached without final answer.";

        $summary = "$msg\nLast message: " . end($this->short_memory)['content'] . "\n" .
                "Consider simplifying the task, checking tool implementations or using a stronger model.";

        $this->add_to_long_term_memory("TASK ABORTED [" . $current_task . '] Reason: ' . $summary);
        update_post_meta($this->agent_id, '_agent_status', 'failed');
        $this->log_run($step, 'abort', [
            'result' => $summary
        ]);
        return $summary;
    }
    public function kill() {
        update_post_meta($this->agent_id, '_agent_status', 'paused');
        $this->log_run(999, 'system_kill', [
            'result' => 'Agent manually terminated by kill switch.'
        ]);
        $this->add_to_short_memory('system', 'TASK PAUSED: Agent manually terminated by kill switch.');
        $this->add_to_long_term_memory('TASK PAUSED: Agent manually terminated by kill switch.');
    }
    private function get_tool_retry_hint($tool_name, $error_message) {
        $tool_name = sanitize_key((string)$tool_name);
        $error_message = trim(wp_strip_all_tags((string)$error_message));

        $hints = [
            'aimogen_rules_engine' => 'Common issues: missing operation, invalid rule ID, wrong rule type, or the selected rule no longer exists. Verify operation, rule_id, and rule_type.',
            'aimogen_content_editor_templates' => 'Common issues: missing operation, invalid post ID, invalid template ID, or template not found. Check post_id and template_id.',
            'get_environment_info' => 'Common issues: invalid info_type. Use one of: general, plugins, theme, stats, capabilities, post_types, taxonomies, all.',
            'generate_chart' => 'Common issues: invalid shortcode syntax, missing labels/data, unsupported chart type, or malformed attributes. Rebuild the shortcode with valid type, labels, and data.',
            'wp_send_email' => 'Common issues: invalid recipient email, empty subject/content, blocked mail transport, or SMTP misconfiguration. Verify recipient_email, subject, and content.',
            'website_scraper' => 'Common issues: invalid URL, timeout, bot protection, SSL errors, or unreadable page structure. Verify the URL and try another source if needed.',
            'rss_feed_parser' => 'Common issues: invalid feed URL, unreachable feed, malformed XML, or feed blocked by the server. Verify the RSS URL and test another feed.',
            'google_results_parser' => 'Common issues: empty query, quota/rate limit, blocked request, or temporary provider failure. Retry with a simpler keyword query.',
            'call_webhook' => 'Common issues: invalid webhook URL, wrong HTTP method, malformed JSON/body, auth failure, or server rejection. Check URL, method, headers, and payload format.',
            'search_clickbank' => 'Common issues: empty query, no matching products, API/auth issue, or temporary upstream failure. Retry with broader niche keywords.',
            'search_amazon' => 'Common issues: empty query, no results, locale/API restrictions, or rate limiting. Retry with clearer product keywords.',
            'get_amazon_product_details' => 'Common issues: invalid ASIN, ambiguous product query, unavailable product, or API restriction. Retry with an exact ASIN or more precise product name.',
            'manage_wp_post' => 'Common issues: missing required fields, invalid post ID, invalid post status, permission denied, or bad taxonomy/meta input. Verify operation-specific parameters before retrying.',
            'wp_taxonomy_discovery' => 'Common issues: invalid operation, missing taxonomy, invalid post ID, or term already exists. Verify taxonomy name and required parameters.',
            'wp_validate_post_state' => 'Common issues: invalid post ID, unsupported check, missing taxonomy for has_terms, or missing expected validation values. Verify post_id and checks.',
            'get_wp_post_data' => 'Common issues: invalid post ID, post not found, or insufficient permission. Verify the post_id exists.',
            'process_and_transform_data' => 'Common issues: invalid JSON, missing field, wrong operation, or mismatched input structure. Validate the input and use the proper operation.',
            'pause_execution' => 'Common issues: missing seconds value or seconds outside allowed range. Use an integer between 1 and 30.',
            'search_site_posts' => 'Common issues: invalid filters, malformed meta_filters string, unsupported orderby, or no matching content. Simplify filters and retry.',
            'wp_sideload_media' => 'Common issues: invalid image URL, inaccessible file, unsupported file type, download failure, or media sideload restriction. Verify the direct image URL.',
            'get_wp_media_info' => 'Common issues: invalid post ID or attachment ID, missing target, or no media found. Verify the IDs and request scope.',
            'query_wp_database' => 'Common issues: SQL syntax error, disallowed command type, invalid table/field names, or permission restrictions. Use only allowed SQL commands and validate the query carefully.',
            'youtube_video_captions' => 'Common issues: invalid YouTube URL, captions unavailable, region restriction, or transcript fetch failure. Retry with a different video or ensure captions exist.',
            'youtube_video_search' => 'Common issues: empty keyword, quota/rate limit, or no matching videos. Retry with a broader or cleaner keyword.',
            'list_available_ai_agents' => 'Common issues: no sub-agents configured or temporary retrieval failure. Verify that specialized agents exist and are enabled.',
            'delegate_to_ai_agent' => 'Common issues: invalid agent_id, missing task, unavailable delegated agent, or delegation disabled. Call list_available_ai_agents first and verify the agent ID.',
            'edit_post_section' => 'Common issues: missing post_id, section_selector or instruction, selector not matching any paragraph or heading, empty post content, invalid or malformed HTML returned by AI, token limits truncating prompt, or DOM parsing/replace failures. Ensure selector exists (use get_post_structure first), keep instructions clear, and verify HTML output before retrying.',
            'get_post_structure' => 'Common issues: missing or invalid post_id, post not found, empty content, failure to normalize Gutenberg blocks, or HTML parsing errors. Ensure the post has valid content and retry if structure extraction fails.',
            'read_server_file' => 'Common issues: invalid path, file not found, disallowed file type, or permission denied. Use a valid relative path to an allowed file type.',
            'write_server_file' => 'Common issues: invalid filename, disallowed extension, file already exists, or write permission failure. Use a safe filename with an allowed extension and set overwrite if needed.',
            'royalty_free_image_search' => 'Common issues: too narrow search query.'
        ];

        $image_tools = [
            'generate_ai_image_openai',
            'generate_ai_image_stable_diffusion',
            'generate_ai_image_google',
            'generate_ai_image_midjourney',
            'generate_ai_image_replicate',
            'generate_ai_image_ideogram',
            'generate_ai_image_cloudflare',
        ];

        if (in_array($tool_name, $image_tools, true)) {
            $hints[$tool_name] = 'Common issues: invalid prompt, quota exceeded, content policy restriction, unavailable model, or provider-side generation error. Simplify the prompt and retry.';
        }

        $publish_tools = [
            'publish_facebook_post',
            'publish_facebook_image',
            'publish_twitter_x_post',
            'publish_threads_post',
            'publish_instagram_post',
            'publish_pinterest_post',
            'publish_google_my_business_post',
            'publish_youtube_community_post',
            'publish_reddit_post',
            'publish_linkedin_post',
        ];

        if (in_array($tool_name, $publish_tools, true)) {
            $hints[$tool_name] = 'Common issues: missing required content, invalid image URL, disconnected account, expired token, permission issue, or provider API rejection. Verify account connection and payload fields.';
        }

        $default = 'Tool failed. Check required parameters, permissions, network/provider availability, and input formatting. Retry with corrected input or choose a different tool.';

        $hint = $hints[$tool_name] ?? $default;

        return "Previous tool call failed: {$error_message}\nHint: {$hint}\nPlease correct and retry or choose a different tool.";
    }
    public function heartbeat() 
    {
        update_post_meta($this->agent_id, '_agent_status', 'running');
        return $this->run("Check for new tasks or run scheduled work using long-term memory.");
    }
    public function get_agent_id()
    {
        return $this->agent_id;
    }
    public function get_agent_status()
    {
        $status = get_post_meta($this->agent_id, '_agent_status', true);
        if(empty($status))
        {
            $status = 'idle';
        }
        return $status;
    }
    public function get_config()
    {
        return $this->config;
    }
    public function log_native_tool_call($step, $tool_name, $params = [])
    {
        $this->did_tool_call = true;
        $this->log_run($step, 'tool_call', [
            'tool' => $tool_name,
            'params' => $params
        ]);
        
        $param_text = is_array($params) ? wp_json_encode($params) : (string)$params;
        $this->add_to_short_memory('agent', 'TOOL CALL: ' . $tool_name . ' | PARAMS: ' . $param_text);
    }

    public function log_native_tool_result($step, $tool_name, $result = '', $is_direct_message = true)
    {
        if (is_array($result) || is_object($result)) {
            $result = wp_json_encode($result);
        }

        $result = (string)$result;

        $this->log_run($step, 'tool_result', [
            'tool' => $tool_name,
            'result' => $result
        ]);

        $prefix = $is_direct_message ? 'TOOL RESULT' : 'OBSERVATION';
        $this->add_to_short_memory('system', $prefix . ' [' . $tool_name . ']: ' . aiomatic_substr($result, 0, 4000));

        if (aiomatic_strlen($result) > 30) {
            $this->add_to_long_term_memory('TOOL RESULT [' . $tool_name . ']: ' . aiomatic_substr($result, 0, 2000));
        }
    }

    public function log_native_tool_error($step, $tool_name, $error = '')
    {
        $error = (string)$error;

        $this->log_run($step, 'tool_error', [
            'tool' => $tool_name,
            'result' => $error
        ]);

        $this->add_to_short_memory('system', 'TOOL ERROR [' . $tool_name . ']: ' . aiomatic_substr($error, 0, 4000));

        if (stripos($error, 'fatal') !== false || stripos($error, 'permission') !== false) {
            $this->add_to_long_term_memory('TOOL ERROR [' . $tool_name . ']: ' . aiomatic_substr($error, 0, 2000));
        }
    }
    private function reset_runtime_memory()
    {
        $this->short_memory = [];
        $this->cached_ltm = null;
        $this->cached_ltm_query = null;
    }
    public function aiomatic_call_agent($agent_id, $task, $max_steps = 10)
    {
        $agent_id = (int) $agent_id;
        $task = trim((string) $task);

        if (!$agent_id || $task === '') {
            return false;
        }

        $post = get_post($agent_id);
        if (!$post || $post->post_type !== 'aiomatic_agent') {
            return 'Error: Invalid agent ID.';
        }

        if ($agent_id === (int) $this->agent_id) {
            return 'Error: Cannot delegate task to itself.';
        }

        delete_post_meta($agent_id, '_agent_memory');
        delete_post_meta($agent_id, '_current_task');
        update_post_meta($agent_id, '_agent_status', 'running');

        $agent = new Aiomatic_Agent($agent_id, true);
        $agent->reset_runtime_memory();
        $agent->add_to_short_memory('user', $task);
        update_post_meta($agent_id, '_current_task', $task);

        $tool_retries = [];
        $aiomatic_Main_Settings    = get_option('aiomatic_Main_Settings', false);
        $appids = array_filter(preg_split('/\r\n|\r|\n/', trim($aiomatic_Main_Settings['app_id'] ?? '')));
        $token = !empty($appids) ? $appids[array_rand($appids)] : '';
        $token = apply_filters('aiomatic_openai_api_key', $token);
        if ($agent->config['tool_calls_enabled']) {
            require_once(dirname(__FILE__) . "/../aiomatic-god-mode-parser-agents.php");
        }
        for ($step = 0; $step < $max_steps; $step++) {
            update_post_meta($agent_id, '_last_activity', time());
            update_post_meta($agent_id, '_agent_current_step', $step);
            $current_task = get_post_meta($agent_id, '_current_task', true) ?: $task;
            $prompt = $agent->build_react_prompt($current_task);    
            $agent->log_run($step, 'model_prompt', [
                'prompt' => $prompt
            ]);
            $query_token_count = count(aiomatic_encode($prompt));
            $max_tokens = aimogenpro_get_max_tokens($agent->get_model());
            $available_tokens = aiomatic_compute_available_tokens($agent->get_model(), $max_tokens, $prompt, $query_token_count);
            if($available_tokens <= AIMOGEN_MINIMUM_TOKENS_FOR_COMPLETIONS)
            {
                $string_len = aiomatic_strlen($prompt);
                $string_len = $string_len / 2;
                $string_len = intval(0 - $string_len);
                $prompt = aiomatic_substr($prompt, 0, $string_len);
                $prompt = trim($prompt);
                $query_token_count = count(aiomatic_encode($prompt));
                $available_tokens = $max_tokens - $query_token_count;
            }
            if ($agent->config['tool_calls_enabled']) {
                add_filter('aiomatic_ai_functions', 'aiomatic_add_agent_tools', 999, 2);
                $forced_functions = $agent->tools;
                $context_filter = function($ctx = []) use ($step, $agent) {
                    return [
                        'agent_id' => $agent->get_agent_id(),
                        'step'     => $step,
                    ];
                };

                add_filter('aiomatic_agent_context', $context_filter, 10, 1);

                $log_result = function($payload, $is_direct = true) {
                    $ctx = apply_filters('aiomatic_agent_context', []);

                    if (empty($ctx['agent_id'])) 
                    {
                        return;
                    }

                    $agent = Aiomatic_Agent::get_instance_by_id((int)$ctx['agent_id']);
                    if (!$agent) 
                    {
                        return;
                    }
                    $tool_name = $payload['tool_call_id'] ?? 'unknown';
                    $content   = $payload['content'] ?? '';
                    if(empty($content))
                    {
                        $content   = $payload['output'] ?? '';
                    }

                    $agent->log_native_tool_result(
                        $ctx['step'] ?? 0,
                        $tool_name,
                        $content,
                        $is_direct
                    );
                    if($agent->is_debug_mode())
                    {
                        $agent->debug_log('TOOL RESULT [' . $tool_name . ']: ' . print_r($content, true));
                    }
                };
                add_action('aiomatic_tool_result', $log_result, 10, 1);
                $tool_direct_logger = function($payload) use ($log_result) {
                    $log_result($payload, true);
                };
                add_action('aiomatic_tool_direct_message', $tool_direct_logger, 10, 1);
            }
            else
            {
                $forced_functions = [];
            }
            $thread_id = '';
            $aierror = '';
            $finish_reason = '';
            if($agent->is_debug_mode())
            {
                $agent->debug_log('Delegated agent call: ' . print_r($prompt, true));
            }
            $response = aiomatic_generate_text($token, $agent->get_model(), $prompt, $available_tokens, 1, 1, 0, 0, false, 'agentsDelegate', 0, $finish_reason, $aierror, false, false, false, '', '', 'user', '', $thread_id, '', 'disabled', '', false, false, $forced_functions, '', '', '');
            if($agent->is_debug_mode())
            {
                $agent->debug_log('Delegated agent response: ' . print_r($response, true));
            }
            if ($agent->config['tool_calls_enabled']) {
                remove_filter('aiomatic_ai_functions', 'aiomatic_add_agent_tools', 999);
                remove_filter('aiomatic_agent_context', $context_filter, 10);
                remove_action('aiomatic_tool_result', $log_result, 10);
                remove_action('aiomatic_tool_direct_message', $tool_direct_logger, 10, 1);
            }
            if($response === false)
            {
                $agent->add_to_short_memory('system', "Failed to call the AI.");
                continue;
            }
            $agent->log_run($step, 'model_response', [
                'response' => $response
            ]);
            $agent->add_to_short_memory('agent', $response);

            if (strpos($response, 'FINAL ANSWER:') !== false) {
                preg_match('/FINAL ANSWER:\s*([\s\S]+)/i', $response, $m);
                $final = trim($m[1] ?? $response);
                $agent->log_run($step, 'final', [
                    'result' => $final
                ]);
                update_post_meta($agent_id, '_agent_status', 'completed');
                delete_post_meta($agent_id, '_current_task');
                $agent->add_to_long_term_memory('DELEGATED TASK COMPLETED [' . $current_task . '] Result: ' . $final);
                return $final;
            }
            if (!$agent->config['tool_calls_enabled']) {
                if (
                    preg_match('/ACTION:\s*([a-zA-Z0-9_\-]+)/i', $response, $m) &&
                    preg_match('/PARAMS:\s*(?:```json)?\s*(\{[\s\S]*?\})\s*(?:```)?/', $response, $p)
                ) {
                    $tool_name = trim($m[1]);
                    $params = json_decode(trim($p[1]), true);

                    if (json_last_error() !== JSON_ERROR_NONE || !is_array($params)) {
                        $agent->add_to_short_memory('system', 'Invalid JSON in PARAMS. Use valid JSON only.');
                        continue;
                    }

                    if (!isset($agent->tools[$tool_name])) {
                        $agent->add_to_short_memory('system', "Unknown tool: {$tool_name}");
                        continue;
                    }

                    $tool_key = 'tool_' . $tool_name;
                    if (($tool_retries[$tool_key] ?? 0) >= 3) {
                        $agent->add_to_short_memory('system', "Tool '{$tool_name}' failed too many times. Try a different approach.");
                        continue;
                    }
                    $agent->log_run($step, 'tool_call', [
                        'tool' => $tool_name,
                        'params' => $params
                    ]);
                    $agent->add_to_short_memory(
                        'agent',
                        'TOOL CALL: ' . $tool_name . ' | PARAMS: ' . wp_json_encode($params)
                    );
                    try {
                        $result = $agent->execute_tool($tool_name, $params);
                        $result_str = is_string($result) ? $result : wp_json_encode($result);
                        $agent->log_run($step, 'tool_result', [
                            'tool' => $tool_name,
                            'params' => $params,
                            'result' => $result
                        ]);
                        if (stripos($result_str, 'Error:') === 0) {
                            $tool_retries[$tool_key] = ($tool_retries[$tool_key] ?? 0) + 1;
                        }

                        $agent->add_to_short_memory('system', 'TOOL RESULT: ' . $result_str);

                        if (strlen($result_str) > 30) {
                            $agent->add_to_long_term_memory('TOOL RESULT [' . $tool_name . ']: ' . substr($result_str, 0, 2000));
                        }
                    } catch (\Throwable $e) {
                        $agent->log_run($step, 'tool_error', [
                            'tool' => $tool_name,
                            'result' => $e->getMessage()
                        ]);
                        $tool_retries[$tool_key] = ($tool_retries[$tool_key] ?? 0) + 1;
                        $hint = $agent->get_tool_retry_hint($tool_name, $e->getMessage());
                        $agent->add_to_short_memory('system', 'TOOL ERROR [' . $tool_name . ']: ' . $e->getMessage());
                        $agent->add_to_short_memory('system', $hint);
                        if (stripos($e->getMessage(), 'fatal') !== false || stripos($e->getMessage(), 'permission') !== false) {
                            $agent->add_to_long_term_memory('TOOL ERROR [' . $tool_name . ']: ' . aiomatic_substr($e->getMessage(), 0, 2000));
                        }
                    }

                    continue;
                }
                $agent->add_to_short_memory('system', 'Format invalid. Respond with ACTION/PARAMS or FINAL ANSWER.');
            }
        }
        $msg = 'Sub-agent stopped: max steps reached without final answer.';
        $agent->log_run($step ?? 0, 'abort', [
            'result' => $msg
        ]);
        update_post_meta($agent_id, '_agent_status', 'failed');
        $agent->add_to_short_memory('system', 'TASK ABORTED: ' . $msg);
        $agent->add_to_long_term_memory('TASK ABORTED [' . $task . '] Reason: ' . $msg);
        return 'Sub-agent stopped: max steps reached without final answer.';
    }
    
    protected function execute_tool($name, $params) {
        $aiomatic_Chatbot_Settings = get_option('aiomatic_Chatbot_Settings', false);
        $aiomatic_Main_Settings    = get_option('aiomatic_Main_Settings', false);
        switch ($name) {
            case 'google_results_parser':
                $keywords = $params['keywords'] ?? '';
                if (empty($keywords)) {
                    return 'Error: Empty keywords parameter provided.';
                }
                //settings hardcoded
                $max_google_items = 10;
                $google_template  = '[%%item_counter%%]: %%item_title%% - %%item_snippet%% (%%item_url%%)';
                $locale = $aiomatic_Main_Settings['internet_gl'] ?? 'us';
                $internet_rez = aiomatic_internet_result($keywords, true, $locale);

                if (empty($internet_rez) || !is_array($internet_rez)) {
                    return 'No results found on Google for: ' . $keywords;
                }
                $processed = 0;
                $final_res = "Search results for '$keywords':" . PHP_EOL;
                
                foreach ($internet_rez as $item) {
                    if ($processed >= $max_google_items) {
                        break;
                    }

                    $template_copy = $google_template;
                    $template_copy = str_replace('%%item_counter%%', $processed + 1, $template_copy);
                    $template_copy = str_replace('%%item_title%%',   $item['title']   ?? 'No Title', $template_copy);
                    $template_copy = str_replace('%%item_snippet%%', $item['snippet'] ?? 'No Snippet', $template_copy);
                    $template_copy = str_replace('%%item_url%%',     $item['link']    ?? 'No Link', $template_copy);
                    
                    $final_res .= $template_copy . PHP_EOL;
                    $processed++;
                }
                return mb_substr($final_res, 0, 5000);
            case 'query_wp_database':
                global $wpdb;
                $query = $params['query'] ?? '';

                if (empty($query)) {
                    return 'Error: Empty query parameter provided.';
                }
                
                //settings hardcoded
                $allowed_commands = ['SELECT'];

                preg_match('/^\s*(\w+)/i', $query, $matches);
                $query_type = strtoupper($matches[1] ?? '');

                if (!in_array($query_type, $allowed_commands, true)) {
                    return "Error: Query type '$query_type' is not allowed. Allowed: " . implode(', ', $allowed_commands);
                }

                try {
                    $lead_result = null;
                    
                    if ($query_type === 'SELECT') {
                        $lead_result = $wpdb->get_results($query, ARRAY_A);
                        
                        if (is_array($lead_result) && count($lead_result) > 100) {
                            $lead_result = array_slice($lead_result, 0, 100);
                            $note = "[Note: Result set truncated to 100 rows]";
                        }
                    } elseif (in_array($query_type, ['INSERT', 'UPDATE', 'DELETE'], true)) {
                        $lead_result = $wpdb->query($query);
                    }

                    if ($lead_result === null || $lead_result === false) {
                        return 'Error: Invalid query execution or database error: ' . $wpdb->last_error;
                    }

                    $json_res = wp_json_encode($lead_result);
                    return (isset($note)) ? $note . ' ' . $json_res : $json_res;

                } catch (Exception $e) {
                    return 'Exception during query: ' . $e->getMessage();
                }
            case 'generate_chart':
                $shortcode = $params['shortcode'] ?? '';

                if (empty($shortcode)) {
                    return 'Error: shortcode parameter was not provided.';
                }

                if (strpos($shortcode, '[') === false) {
                    $shortcode = '[' . $shortcode . ']';
                }

                $rendered_output = do_shortcode($shortcode);

                if (empty($rendered_output) || $rendered_output === $shortcode) {
                    return "Error: The shortcode '$shortcode' could not be processed or returned no data.";
                }

                return "Success: Chart shortcode processed. Output: " . mb_substr($rendered_output, 0, 2000);
            case 'wp_send_email':
                $subject         = $params['subject'] ?? '';
                $content         = $params['content'] ?? '';
                $recipient_email = $params['recipient_email'] ?? '';

                if (empty($subject) || empty($content) || empty($recipient_email)) {
                    return 'Error: subject, content, and recipient_email are all required.';
                }

                if (!is_email($recipient_email)) {
                    return "Error: '$recipient_email' is not a valid email address.";
                }

                $admin_mail = get_option('admin_email');
                $headers   = array();
                $headers[] = 'From: Aimogen Agent <' . $admin_mail . '>';
                $headers[] = 'Reply-To: ' . $admin_mail;
                $headers[] = 'Content-Type: text/html; charset=' . get_option('blog_charset', 'UTF-8');

                $sent = wp_mail($recipient_email, $subject, $content, $headers);

                if ($sent) {
                    return "Success: Email successfully sent to $recipient_email.";
                } else {
                    return "Error: WordPress failed to send the email. Check server SMTP settings.";
                }
            case 'website_scraper':
                $url = $params['url'] ?? '';

                if (empty($url)) {
                    return 'Error: URL parameter was not provided.';
                }
                $parsed = parse_url($url);
                $host = $parsed['host'] ?? '';

                if (
                    in_array($host, ['localhost', '127.0.0.1', '::1'], true) ||
                    preg_match('/^10\./', $host) ||
                    preg_match('/^192\.168\./', $host) ||
                    preg_match('/^172\.(1[6-9]|2[0-9]|3[0-1])\./', $host)
                ) {
                    return "Error: Local/internal network requests are not allowed.";
                }
                //settings hardcoded
                $scrape_method   = '0';
                $max_chars       = 5000;
                $strip_tags_bool = false;

                $scraped_data = aiomatic_scrape_page($url, $scrape_method, 'auto', '');

                if ($scraped_data === false || empty($scraped_data)) {
                    return "Error: Failed to scrape website content from URL: $url";
                }

                if ($strip_tags_bool) {
                    $scraped_data = wp_strip_all_tags($scraped_data);
                } else {
                    $scraped_data = aiomatic_fix_relative_links($scraped_data, $url);
                }

                $final_limit = (is_numeric($max_chars) && intval($max_chars) > 0) ? intval($max_chars) : 5000;
                
                $final_limit = min($final_limit, 20000); 

                return aiomatic_substr($scraped_data, 0, $final_limit);
            case 'rss_feed_parser':
                $url = $params['url'] ?? '';

                if (empty($url)) {
                    return 'Error: RSS feed URL parameter was not provided.';
                }
                
                //settings hardcoded
                $max_items = 10;
                $template  = "[%%item_counter%%]: %%item_title%% - %%item_description%% (%%item_url%%)";

                if (!class_exists('SimplePie', false)) {
                    $simplepie_path = dirname(__FILE__) . "/res/simplepie/autoloader.php";
                    global $wp_filesystem;
                    if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base') ){
                        include_once(ABSPATH . 'wp-admin/includes/file.php');$creds = request_filesystem_credentials( site_url() );
                        wp_filesystem($creds);
                    }
                    if ($wp_filesystem->exists($simplepie_path)) {
                        require_once($simplepie_path);
                    } else {
                        return 'Error: SimplePie library not found on the server.';
                    }
                }

                $feed = new SimplePie();
                $feed->set_feed_url($url);
                $feed->enable_cache(false);
                $feed->set_timeout(30);
                $feed->init();
                $feed->handle_content_type();

                if ($feed->error()) {
                    return 'Error parsing RSS feed: ' . $feed->error();
                }

                $final_res = "Feed results for: " . $feed->get_title() . PHP_EOL;
                $processed = 0;

                foreach ($feed->get_items() as $item) {
                    if ($processed >= $max_items) break;

                    $author_obj = $item->get_author();
                    $author_name = $author_obj ? $author_obj->get_name() : 'Unknown';
                    
                    $categories = array();
                    foreach ((array)$item->get_categories() as $cat) {
                        $categories[] = $cat->get_label();
                    }
                    $item_str = $template;
                    $item_str = str_replace('%%item_counter%%',     $processed + 1, $item_str);
                    $item_str = str_replace('%%item_title%%',       $item->get_title(), $item_str);
                    $item_str = str_replace('%%item_description%%', wp_strip_all_tags($item->get_description()), $item_str);
                    $item_str = str_replace('%%item_content%%',     wp_strip_all_tags($item->get_content()), $item_str);
                    $item_str = str_replace('%%item_url%%',         $item->get_permalink(), $item_str);
                    $item_str = str_replace('%%item_author%%',      $author_name, $item_str);
                    $item_str = str_replace('%%item_categories%%',  implode(', ', $categories), $item_str);

                    $final_res .= $item_str . PHP_EOL;
                    $processed++;
                }

                return mb_substr($final_res, 0, 10000);
            case 'call_webhook':
                $webhook_url    = $params['webhook_url'] ?? '';
                $webhook_method = strtoupper($params['method_selector'] ?? 'POST');
                $content_type   = $params['content_type'] ?? 'form_data';
                $post_data      = $params['data'] ?? '';
                $headers_raw    = $params['headers'] ?? '';

                if (empty($webhook_url)) {
                    return 'Error: webhook_url is required.';
                }
                $parsed = parse_url($webhook_url);
                $host = $parsed['host'] ?? '';

                if (
                    in_array($host, ['localhost', '127.0.0.1', '::1'], true) ||
                    preg_match('/^10\./', $host) ||
                    preg_match('/^192\.168\./', $host) ||
                    preg_match('/^172\.(1[6-9]|2[0-9]|3[0-1])\./', $host)
                ) {
                    return "Error: Local/internal network requests are not allowed.";
                }
                $headers = [];
                if (!empty($headers_raw)) {
                    $lines = preg_split('/\r\n|\r|\n/', trim($headers_raw));
                    foreach ($lines as $line) {
                        if (strpos($line, '=>') !== false) {
                            list($key, $val) = explode('=>', $line, 2);
                            $headers[] = trim($key) . ': ' . trim($val);
                        }
                    }
                }

                $content_params = [];
                if (!empty($post_data)) {
                    $lines = preg_split('/\r\n|\r|\n/', trim($post_data));
                    foreach ($lines as $line) {
                        if (strpos($line, '=>') !== false) {
                            list($key, $val) = explode('=>', $line, 2);
                            $content_params[trim($key)] = trim($val);
                        }
                    }
                }

                $ch = curl_init();
            
                if (!empty($aiomatic_Main_Settings['proxy_url'])) {
                    $proxies = explode(',', $aiomatic_Main_Settings['proxy_url']);
                    $random_proxy = trim($proxies[array_rand($proxies)]);
                    curl_setopt($ch, CURLOPT_PROXY, $random_proxy);
                }

                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

                if ($webhook_method === 'GET') {
                    if (!empty($content_params)) {
                        $webhook_url = add_query_arg($content_params, $webhook_url);
                    }
                } else {
                    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $webhook_method);
                    if ($content_type === 'JSON') {
                        $payload = wp_json_encode($content_params ?: $post_data);
                        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
                        $headers[] = 'Content-Type: application/json';
                    } else {
                        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($content_params));
                    }
                }

                curl_setopt($ch, CURLOPT_URL, $webhook_url);
                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

                $response   = curl_exec($ch);
                $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $curl_error = curl_error($ch);
                curl_close($ch);

                if ($response === false) {
                    return "Error: Connection failed - $curl_error";
                }

                return ($statusCode >= 200 && $statusCode <= 299) 
                    ? "Success: Webhook called. Status $statusCode." 
                    : "Error: Webhook returned status $statusCode. Response: " . substr($response, 0, 200);
            case 'search_clickbank':
                $query = $params['query'] ?? '';

                if (empty($query)) {
                    return 'Error: Search query parameter was not provided.';
                }

                $cb_affiliate_id  = trim($aiomatic_Chatbot_Settings['clickbank_affiliate_id'] ?? '');
                $max_prod_setting = '3-4';
                $listing_template = '%%product_counter%%. %%product_title%% - Link: %%product_url%%';

                if (strpos($max_prod_setting, '-') !== false) {
                    list($min, $max) = explode('-', $max_prod_setting);
                    $max_prod = rand((int)$min, (int)$max);
                } else {
                    $max_prod = is_numeric($max_prod_setting) ? (int)$max_prod_setting : 4;
                }
                $products = aiomatic_clickbank_get_post(
                    $cb_affiliate_id, 
                    $query, 
                    '', 'All', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 
                    $max_prod
                );

                if (!is_array($products) || empty($products)) {
                    return "No ClickBank products found for the query: " . $query;
                }

                $final_result = '';
                $counter = 1;

                foreach ($products as $product) {
                    $item_str = $listing_template;
                    
                    $clean_title = trim(preg_replace('/\s+/', ' ', $product->offer_title));
                    $clean_desc  = trim(preg_replace('/\s+/', ' ', $product->offer_desc));
                    $clean_url   = trim(preg_replace('/\s+/', ' ', $product->offer_url));

                    $replacements = [
                        '%%product_counter%%'     => $counter,
                        '%%product_title%%'       => $clean_title,
                        '%%product_description%%' => $clean_desc,
                        '%%product_url%%'         => $clean_url,
                        '%%product_price%%'       => $product->offer_price ?? 'N/A',
                        '%%product_image%%'       => $product->offer_img ?? '',
                        '%%product_rating%%'      => $product->rating ?? 'N/A'
                    ];

                    foreach ($replacements as $placeholder => $value) {
                        $item_str = str_replace($placeholder, $value, $item_str);
                    }

                    $final_result .= $item_str . PHP_EOL;
                    $counter++;
                }

                return aiomatic_substr($final_result, 0, 30000);
            case 'search_amazon':
                $query = $params['query'] ?? '';

                if (empty($query)) {
                    return 'Error: Empty search query provided.';
                }

                $aff_id           = trim($aiomatic_Chatbot_Settings['affiliate_id'] ?? '');
                $target_country   = $aiomatic_Chatbot_Settings['target_country'] ?? 'com';
                $max_prod_setting = '3-4';
                $amaz_sort        = 'none';
                $listing_template = '%%product_counter%%. %%product_title%% - Price: %%product_price%% - Link: %%product_url%%';

                if (strpos($max_prod_setting, '-') !== false) {
                    list($min, $max) = explode('-', $max_prod_setting);
                    $max_prod = rand((int)$min, (int)$max);
                } else {
                    $max_prod = is_numeric($max_prod_setting) ? (int)$max_prod_setting : 4;
                }

                $amazresult = aiomatic_amazon_get_post(
                    $query, 
                    $aff_id, 
                    $target_country, 
                    '', '', 
                    $amaz_sort, 
                    $max_prod, 
                    '1', 
                    array()
                );

                if (!is_array($amazresult) || empty($amazresult) || (isset($amazresult['status']) && $amazresult['status'] === 'nothing')) {
                    return "No Amazon products found for the query: " . $query;
                }

                $final_result = '';
                $counter = 1;

                foreach ($amazresult as $myprod) {
                    $item_str = $listing_template;

                    $replacements = [
                        '%%product_counter%%'     => $counter,
                        '%%product_title%%'       => trim(preg_replace('/\s+/', ' ', $myprod->offer_title)),
                        '%%product_description%%' => trim(preg_replace('/\s+/', ' ', $myprod->offer_desc)),
                        '%%product_url%%'         => trim(preg_replace('/\s+/', ' ', $myprod->offer_url)),
                        '%%product_price%%'       => trim(preg_replace('/\s+/', ' ', $myprod->offer_price)),
                        '%%product_image%%'       => trim(preg_replace('/\s+/', ' ', $myprod->offer_img)),
                        '%%product_rating%%'      => $myprod->rating ?? 'N/A'
                    ];

                    foreach ($replacements as $placeholder => $value) {
                        $item_str = str_replace($placeholder, $value, $item_str);
                    }

                    $final_result .= $item_str . PHP_EOL;
                    $counter++;
                }

                return aiomatic_substr($final_result, 0, 350000);
            case 'get_amazon_product_details':
                $asin = $params['query'] ?? '';

                if (empty($asin)) {
                    return 'Error: No ASIN or search query provided.';
                }

                $aff_id         = trim($aiomatic_Chatbot_Settings['affiliate_id'] ?? '');
                $target_country = $aiomatic_Chatbot_Settings['target_country'] ?? 'com';

                $amazresult = aiomatic_amazon_get_post($asin, $aff_id, $target_country, '', '', '', 1, '1', array());

                if (!is_array($amazresult) || empty($amazresult) || (isset($amazresult['status']) && $amazresult['status'] === 'nothing')) {
                    return "Could not find specific details for: " . $asin;
                }

                $product = $amazresult[0];
                
                $details = [
                    "Title: " . ($product->offer_title ?? 'N/A'),
                    "Price: " . ($product->offer_price ?? 'N/A'),
                    "Description: " . ($product->offer_desc ?? 'No description available'),
                    "Manufacturer: " . ($product->manufacturer ?? 'N/A'),
                    "Rating: " . ($product->rating ?? 'N/A'),
                    "Model: " . ($product->model ?? 'N/A'),
                    "Color: " . ($product->color ?? 'N/A'),
                    "Dimensions: " . ($product->dimensions ?? 'N/A'),
                    "Warranty: " . ($product->warranty ?? 'N/A'),
                    "URL: " . ($product->offer_url ?? 'N/A'),
                    "Image: " . ($product->offer_img ?? 'N/A')
                ];

                if (!empty($product->item_reviews) && is_array($product->item_reviews)) {
                    $details[] = "Top Reviews:\n- " . implode("\n- ", array_slice($product->item_reviews, 0, 3));
                }

                $final_result = implode("\n", $details);

                return aiomatic_substr($final_result, 0, 40000);
            case 'youtube_video_captions':
                $url = $params['url'] ?? '';

                if (empty($url)) {
                    return 'Error: No YouTube URL provided.';
                }

                $video_id = '';
                preg_match("/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user|shorts)\/))([^\?&\"'>]+)/", $url, $amatches);
                
                if (isset($amatches[1])) {
                    $video_id = $amatches[1];
                } else {
                    return "Error: Could not extract a valid Video ID from the URL: " . $url;
                }

                $caprez = false;
                try {
                    $caprez = aiomatic_get_video_transcript($video_id);
                } catch (Exception $e) {
                    try {
                        $caprez = aiomatic_get_video_transcript_2($video_id);
                    } catch (Exception $e) {
                        return "Error: Failed to retrieve subtitles for this video. It may have captions disabled.";
                    }
                }

                if (is_array($caprez) && isset($caprez['text'])) {
                    $returned_caption = $caprez['text'];
                    
                    $final_output = aiomatic_substr($returned_caption, 0, 40000);
                    return trim($final_output);
                }

                return "Error: Transcript data was empty or unparseable for video ID: " . $video_id;
            case 'youtube_video_search':
                $keyword = $params['keyword'] ?? '';

                if (empty($keyword)) {
                    return 'Error: No search keyword provided.';
                }

                $search_results = aiomatic_get_video($keyword, '', array());

                if (empty($search_results) || $search_results == '') {
                    return "No YouTube videos were found for the keyword: " . $keyword;
                }

                return $search_results;
            case 'publish_facebook_post':
                $content = $params['content'] ?? '';
                $url     = $params['url'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('fbomatic-facebook-post-generator/fbomatic-facebook-post-generator.php')) {
                    return 'Error: Required plugin (F-omatic) is not activated.';
                }

                if (empty($content)) {
                    return 'Error: No content provided for the Facebook post.';
                }

                $page_to_post = $aiomatic_Chatbot_Settings['facebook_post_select'] ?? '';

                if (empty($page_to_post)) {
                    return 'Error: No Facebook page target has been selected in the AIomatic settings.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'fbomatic-facebook-post-generator/fbomatic-facebook-post-generator.php' => [
                            'F-omatic Automatic Post Generator', 
                            'https://1.envato.market/fbomatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_to_facebook($card_type_found, $content, $url, $page_to_post);

                if (isset($result['error'])) {
                    return 'Facebook posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Failed to parse Facebook posting results (Empty response).';
                } else {
                    return 'Facebook posting successful: ' . wp_json_encode($result);
                }
            case 'publish_facebook_image':
                $image_url = $params['image_url'] ?? '';
                $caption   = $params['caption'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('fbomatic-facebook-post-generator/fbomatic-facebook-post-generator.php')) {
                    return 'Error: Required plugin (F-omatic) is not activated.';
                }

                if (empty($image_url)) {
                    return 'Error: No image URL provided.';
                }

                $page_to_post = $aiomatic_Chatbot_Settings['facebook_post_select'] ?? '';

                if (empty($page_to_post)) {
                    return 'Error: No Facebook page selected in AIomatic settings.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'fbomatic-facebook-post-generator/fbomatic-facebook-post-generator.php' => [
                            'F-omatic Automatic Post Generator', 
                            'https://1.envato.market/fbomatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_image_to_facebook($card_type_found, $caption, $image_url, $page_to_post);

                if (isset($result['error'])) {
                    return 'Facebook image posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Failed to parse Facebook image posting results.';
                } else {
                    return 'Facebook image posting successful: ' . wp_json_encode($result);
                }
            case 'publish_twitter_x_post':
                $content   = $params['content'] ?? '';
                $image_url = $params['image_url'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('twitomatic-twitter-post-generator/twitomatic-twitter-post-generator.php')) {
                    return 'Error: Required plugin (Twitomatic) is not activated.';
                }

                if (empty($content)) {
                    return 'Error: No content provided for the tweet.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'twitomatic-twitter-post-generator/twitomatic-twitter-post-generator.php' => [
                            'Twitomatic Automatic Post Generator', 
                            'https://1.envato.market/twitomatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_to_twitter($card_type_found, $content, $image_url);

                if (isset($result['error'])) {
                    return 'Twitter posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Failed to parse Twitter posting results (Empty response).';
                } else {
                    return 'Twitter posting successful: ' . wp_json_encode($result);
                }
            case 'publish_threads_post':
                $content   = $params['content'] ?? '';
                $image_url = $params['image_url'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('threadsomatic-threads-auto-poster/threadsomatic-threads-auto-poster.php')) {
                    return 'Error: Required plugin (Threadsomatic) is not activated.';
                }

                if (empty($content)) {
                    return 'Error: No content provided for the Threads post.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'threadsomatic-threads-auto-poster/threadsomatic-threads-auto-poster.php' => [
                            'Threadsomatic Threads Auto Poster', 
                            'https://wpbay.com/product/threadsomatic-threads-auto-poster/'
                        ]
                    ]
                ];

                $result = aiomatic_post_to_threads($card_type_found, $content, $image_url);

                if (isset($result['error'])) {
                    return 'Threads posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Received an empty response from the Threads API.';
                } else {
                    return 'Threads posting successful: ' . wp_json_encode($result);
                }
            case 'publish_instagram_post':
                $image_url = $params['image_url'] ?? '';
                $content   = $params['content'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('instamatic-instagram-post-generator/instamatic-instagram-post-generator.php')) {
                    return 'Error: Required plugin (Instamatic) is not activated.';
                }

                if (empty($image_url)) {
                    return 'Error: An image_url is required to post to Instagram.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'instamatic-instagram-post-generator/instamatic-instagram-post-generator.php' => [
                            'iMediamatic Automatic Post Generator', 
                            'https://1.envato.market/instamatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_image_to_instagram($card_type_found, $content, $image_url);

                if (isset($result['error'])) {
                    return 'Instagram posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Failed to parse Instagram posting results (Empty response).';
                } else {
                    return 'Instagram posting successful: ' . wp_json_encode($result);
                }
            case 'publish_pinterest_post':
                $image_url   = $params['image_url'] ?? '';
                $description = $params['description'] ?? '';
                $title       = $params['title'] ?? '';
                $pin_url     = $params['pin_url'] ?? ''; 

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('pinterestomatic-pinterest-post-generator/pinterestomatic-pinterest-post-generator.php')) {
                    return 'Error: Required plugin (Pinterestomatic) not activated.';
                }

                if (empty($image_url)) {
                    return 'Error: image_url is mandatory for Pinterest.';
                }

                $board_id = $aiomatic_Chatbot_Settings['pinterest_post_select'] ?? '';

                if (empty($board_id)) {
                    return 'Error: No Pinterest board selected in AIomatic settings.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'pinterestomatic-pinterest-post-generator/pinterestomatic-pinterest-post-generator.php' => [
                            'Pinterestomatic Automatic Post Generator', 
                            'https://1.envato.market/pinterestomatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_image_to_pinterest($card_type_found, $description, $title, $pin_url, $image_url, $board_id);

                if (isset($result['error'])) {
                    return 'Pinterest posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Received empty response from Pinterestomatic.';
                } else {
                    return 'Pinterest posting successful: ' . wp_json_encode($result);
                }
            case 'publish_google_my_business_post':
                $content   = $params['content'] ?? '';
                $image_url = $params['image_url'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('businessomatic-google-my-business-post-generator/businessomatic-google-my-business-post-generator.php')) {
                    return 'Error: Required plugin (Businessomatic) not activated.';
                }

                $page_to_post = $aiomatic_Chatbot_Settings['business_post_select'] ?? '';

                if (empty($page_to_post)) {
                    return 'Error: No Google Business pages selected in AIomatic settings.';
                }

                if (empty($content) || empty($image_url)) {
                    return 'Error: Both content and image_url are required for Google Business posts.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'businessomatic-google-my-business-post-generator/businessomatic-google-my-business-post-generator.php' => [
                            'Businessomatic Automatic Post Generator', 
                            'https://1.envato.market/businessomatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_to_gmb($card_type_found, $content, $image_url, $page_to_post);

                if (isset($result['error'])) {
                    return 'GMB posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Failed to parse GMB results (Empty response).';
                } else {
                    return 'GMB posting successful: ' . wp_json_encode($result);
                }
            case 'publish_youtube_community_post':
                $content   = $params['content'] ?? '';
                $post_type = $params['post_type'] ?? 'text';
                $image_url = $params['image_url'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('youtubomatic-youtube-post-generator/youtubomatic-youtube-post-generator.php')) {
                    return 'Error: Required plugin (Youtubomatic) is not activated.';
                }

                if (empty($content)) {
                    return 'Error: content is required for YouTube Community posts.';
                }

                $post_type = (trim($post_type) === 'image') ? 'image' : 'text';
                $media = (!empty($image_url)) ? [$image_url] : [];

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'youtubomatic-youtube-post-generator/youtubomatic-youtube-post-generator.php' => [
                            'Youtubomatic Automatic Post Generator', 
                            'https://1.envato.market/youtubomatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_to_youtube_community($card_type_found, $content, $post_type, $media);

                if (isset($result['error'])) {
                    return 'YouTube Community posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Received an empty response from Youtubomatic.';
                } else {
                    return 'YouTube Community posting successful: ' . wp_json_encode($result);
                }
            case 'publish_reddit_post':
                $title     = $params['title'] ?? '';
                $content   = $params['content'] ?? '';
                $image_url = $params['image_url'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('redditomatic-reddit-post-generator/redditomatic-reddit-post-generator.php')) {
                    return 'Error: Required plugin (Redditomatic) not activated.';
                }

                if (empty($title) || empty($content)) {
                    return 'Error: Both title and content are required for Reddit posts.';
                }

                $subreddits = $aiomatic_Chatbot_Settings['subreddits_list'] ?? '';

                if (empty($subreddits)) {
                    return 'Error: No target subreddits defined in AIomatic settings.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'redditomatic-reddit-post-generator/redditomatic-reddit-post-generator.php' => [
                            'Redditomatic Automatic Post Generator', 
                            'https://1.envato.market/redditomatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_to_reddit($card_type_found, $title, $content, 'auto', $subreddits);

                if (isset($result['error'])) {
                    return 'Reddit posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Failed to parse Reddit results (Empty response).';
                } else {
                    return 'Reddit posting successful: ' . wp_json_encode($result);
                }
            case 'publish_linkedin_post':
                $title       = $params['title'] ?? '';
                $content     = $params['content'] ?? '';
                $description = $params['description'] ?? '';
                $post_link   = $params['link'] ?? '';
                $image_url   = $params['image_url'] ?? '';

                if (!function_exists('is_plugin_active')) {
                    include_once(ABSPATH . 'wp-admin/includes/plugin.php');
                }

                if (!is_plugin_active('linkedinomatic-linkedin-post-generator/linkedinomatic-linkedin-post-generator.php')) {
                    return 'Error: Required plugin (Linkedinomatic) not activated.';
                }

                if (empty($title) || empty($content)) {
                    return 'Error: Title and content are mandatory for LinkedIn.';
                }

                $selected_pages = $aiomatic_Chatbot_Settings['linkedin_selected_pages'] ?? '';

                if (empty($selected_pages)) {
                    return 'Error: No LinkedIn pages/profiles selected in AIomatic settings.';
                }

                require_once(dirname(__FILE__) . "/aiomatic-socials.php");
                
                $card_type_found = [
                    'required_plugin' => [
                        'linkedinomatic-linkedin-post-generator/linkedinomatic-linkedin-post-generator.php' => [
                            'Linkedinomatic Automatic Post Generator', 
                            'https://1.envato.market/linkedinomatic'
                        ]
                    ]
                ];

                $result = aiomatic_post_to_linkedin($card_type_found, $content, $image_url, $title, $post_link, $description, '1', $selected_pages);

                if (isset($result['error'])) {
                    return 'LinkedIn posting failed: ' . $result['error'];
                } elseif (empty($result)) {
                    return 'Error: Received empty response from Linkedinomatic.';
                } else {
                    return 'LinkedIn posting successful: ' . wp_json_encode($result);
                }
            case 'generate_ai_image_openai':
                $prompt = $params['prompt'] ?? '';

                $appids = array_filter(preg_split('/\r\n|\r|\n/', trim($aiomatic_Main_Settings['app_id'] ?? '')));
                $token = !empty($appids) ? $appids[array_rand($appids)] : '';
                $token = apply_filters('aiomatic_openai_api_key', $token);

                if (empty($token)) {
                    return 'Error: No OpenAI API key found. Image generation is disabled.';
                }

                $image_size = $aiomatic_Chatbot_Settings['ai_image_size'] ?? '1024x1024';
                $model      = $aiomatic_Chatbot_Settings['ai_image_model'] ?? 'gpt-image-2';
                $aierror    = '';

                $result = aiomatic_generate_ai_image($token, 1, $prompt, $image_size, 'chatFunctionOpenAIImage', false, 0, $aierror, $model, $prompt);

                if ($result !== false && is_array($result)) {
                    return [
                        'echo'   => '<img class="image_max_w_ai" src="' . $result[0] . '">',
                        'output' => $result[0]
                    ];
                } else {
                    return 'Image generation failed: ' . $aierror;
                }
            case 'generate_ai_image_stable_diffusion':
                $prompt = $params['prompt'] ?? '';

                if (empty($prompt)) {
                    return 'Error: No prompt provided for Stable Diffusion.';
                }

                $image_size = $aiomatic_Chatbot_Settings['ai_image_size_stable'] ?? '1024x1024';
                
                $height = $width = '512';
                if ($image_size === '1024x1024') {
                    $height = $width = '1024';
                }

                $model = $aiomatic_Chatbot_Settings['stable_model'] ?? AIMOGEN_STABLE_DEFAULT_MODE;
                $aierror = '';

                $airesult = aiomatic_generate_stability_image($prompt, $height, $width, 'chatFunctionStableImage', 0, false, $aierror, false, $model, '', 0);

                if ($airesult !== false && isset($airesult[1])) {
                    return [
                        'echo' => '<img class="image_max_w_ai" src="' . $airesult[1] . '">',
                        'output' => $airesult[1]
                    ];
                } else {
                    return 'Stable Diffusion failed: ' . ($aierror ?: 'Unknown error');
                }
            case 'generate_ai_image_google':
                $prompt = $params['prompt'] ?? '';

                if (empty($prompt)) {
                    return 'Error: Empty prompt query provided';
                }

                $model = !empty($aiomatic_Main_Settings['google_ai_image_model']) 
                        ? trim($aiomatic_Main_Settings['google_ai_image_model']) 
                        : AIMOGEN_GOOGLE_IMAGE_DEFAULT_MODEL;

                $aierror = '';
                $airesult = aiomatic_generate_image_google($prompt, $model, 'chatFunctionGoogleImage', false, $aierror, false);

                if ($airesult !== false && isset($airesult[1])) {
                    return [
                        'echo' => '<img class="image_max_w_ai" src="' . $airesult[1] . '">',
                        'output' => $airesult[1]
                    ];
                } else {
                    aiomatic_log_to_file('Google Image Gen Failure: ' . $aierror);
                    return $aiomatic_Chatbot_Settings['god_mode_stable_failed'] ?? 'Image creation failed.';
                }
            case 'generate_ai_image_midjourney':
                $prompt = $params['prompt'] ?? '';

                if (empty($prompt)) {
                    return 'Error: Empty prompt query provided';
                }
                $height = '1024';
                $width = '1024';
                $aierror = '';

                $airesult = aiomatic_generate_ai_image_midjourney($prompt, $width, $height, 'chatFunctionMidjourneyImage', false, $aierror);

                if ($airesult !== false) {
                    return [
                        'echo' => '<img class="image_max_w_ai" src="' . $airesult . '">',
                        'output' => $airesult
                    ];
                } else {
                    aiomatic_log_to_file('Midjourney Error: ' . $aierror);
                    return 'Image creation failed, please try again later.';
                }
            case 'generate_ai_image_replicate':
                $prompt = $params['prompt'] ?? '';

                if (empty($prompt)) {
                    return 'Error: Empty prompt query provided';
                }

                $height = '1024';
                $width = '1024';
                $aierror = '';

                $airesult = aiomatic_generate_replicate_image($prompt, $width, $height, 'chatFunctionReplicateImage', false, $aierror);

                if ($airesult !== false) {
                    return [
                        'echo' => '<img class="image_max_w_ai" src="' . $airesult . '">',
                        'output' => $airesult
                    ];
                } else {
                    aiomatic_log_to_file('Replicate Gen Failure: ' . $aierror);
                    return 'Image creation failed, please try again later.';
                }
            case 'generate_ai_image_ideogram':
                $prompt = $params['prompt'] ?? '';

                if (empty($prompt)) {
                    return 'Error: Empty prompt query provided';
                }

                $height = '1024';
                $width = '1024';
                $aierror = '';

                $airesult = aiomatic_generate_ideogram_image($prompt, $width, $height, 'chatFunctionIdeogramImage', false, $aierror);

                if ($airesult !== false) {
                    return [
                        'echo' => '<img class="image_max_w_ai" src="' . $airesult . '">',
                        'output' => $airesult
                    ];
                } else {
                    aiomatic_log_to_file('Ideogram Gen Failure: ' . $aierror);
                    return 'Image creation failed, please try again later.';
                }
            case 'generate_ai_image_cloudflare':
                $prompt = $params['prompt'] ?? '';

                if (empty($prompt)) {
                    return 'Error: Empty prompt query provided';
                }

                $height = '1024';
                $width = '1024';
                $aierror = '';

                $airesult = aiomatic_generate_cloudflare_image($prompt, $width, $height, 'chatFunctionCloudflareWorkerImage', false, $aierror);

                if ($airesult !== false) {
                    return [
                        'echo' => '<img class="image_max_w_ai" src="' . $airesult . '">',
                        'output' => $airesult
                    ];
                } else {
                    aiomatic_log_to_file('Cloudflare Worker Gen Failure: ' . $aierror);
                    return 'Image creation failed, please try again later.';
                }
            case 'royalty_free_image_search':
                $keyword = $params['keyword'] ?? '';
                $keyword = function_exists('aiomatic_normalize_royalty_free_image_keyword')
                    ? aiomatic_normalize_royalty_free_image_keyword($keyword)
                    : sanitize_text_field(wp_strip_all_tags((string) $keyword));

                if (empty($keyword)) {
                    return 'Error: Empty keyword query provided';
                }
                $raw_img_list = array();
                $full_result_list = array();
                $result = '';
                $temp_img_attr = '';
                $attached_id = '';
                $temp_get_img = aiomatic_get_free_image($aiomatic_Main_Settings, $keyword, $temp_img_attr, $attached_id, 10, false, $raw_img_list, array(), $full_result_list);
                if(empty($temp_get_img))
                {
                    return 'Failed to get royalty free image for keyword: ' . $keyword;
                }
                else
                {
                    return [
                        'echo' => '<img class="image_max_w_ai" src="' . $temp_get_img . '">',
                        'output' => $temp_get_img
                    ];
                }
            case 'wp_taxonomy_discovery':
                $operation = $params['operation'] ?? '';

                if (empty($operation)) {
                    return 'Error: operation parameter was not provided.';
                }

                if (!in_array($operation, array('list_taxonomies', 'list_terms', 'get_post_terms', 'create_term', 'set_post_terms'), true)) {
                    return 'Error: Invalid operation parameter provided.';
                }

                switch ($operation) {
                    case 'list_taxonomies':
                        $taxonomies = get_taxonomies(array(), 'objects');

                        if (empty($taxonomies)) {
                            return 'No taxonomies found on this site.';
                        }

                        $results = array();

                        foreach ($taxonomies as $taxonomy) {
                            $results[] = sprintf(
                                "Name: %s | Label: %s | Public: %s | Hierarchical: %s | Object Types: %s",
                                $taxonomy->name,
                                $taxonomy->label,
                                !empty($taxonomy->public) ? 'yes' : 'no',
                                !empty($taxonomy->hierarchical) ? 'yes' : 'no',
                                !empty($taxonomy->object_type) ? implode(',', $taxonomy->object_type) : '-'
                            );
                        }

                        return aiomatic_substr("Available Taxonomies:\n\n" . implode("\n---\n", $results), 0, 45000);

                    case 'list_terms':
                        $taxonomy = $params['taxonomy'] ?? '';
                        $hide_empty = !empty($params['hide_empty']);
                        $limit = !empty($params['limit']) ? min((int)$params['limit'], 100) : 20;

                        if (empty($taxonomy)) {
                            return 'Error: taxonomy parameter was not provided.';
                        }

                        if (!taxonomy_exists($taxonomy)) {
                            return "Error: Taxonomy $taxonomy does not exist.";
                        }

                        $terms = get_terms(array(
                            'taxonomy'   => $taxonomy,
                            'hide_empty' => $hide_empty,
                            'number'     => $limit,
                        ));

                        if (is_wp_error($terms)) {
                            return 'Error: ' . $terms->get_error_message();
                        }

                        if (empty($terms)) {
                            return "No terms found for taxonomy: $taxonomy";
                        }

                        $results = array();

                        foreach ($terms as $term) {
                            $results[] = sprintf(
                                "ID: %d | Name: %s | Slug: %s | Count: %d | Description: %s",
                                $term->term_id,
                                $term->name,
                                $term->slug,
                                $term->count,
                                $term->description
                            );
                        }

                        return aiomatic_substr("Terms for taxonomy '$taxonomy':\n\n" . implode("\n---\n", $results), 0, 45000);

                    case 'get_post_terms':
                        $taxonomy = $params['taxonomy'] ?? '';
                        $post_id = !empty($params['post_id']) ? (int)$params['post_id'] : 0;

                        if (empty($taxonomy)) {
                            return 'Error: taxonomy parameter was not provided.';
                        }

                        if ($post_id <= 0) {
                            return 'Error: post_id parameter was not provided or invalid.';
                        }

                        if (!taxonomy_exists($taxonomy)) {
                            return "Error: Taxonomy $taxonomy does not exist.";
                        }

                        $post = get_post($post_id);
                        if (!$post) {
                            return "Error: Post with ID $post_id not found.";
                        }

                        $terms = get_the_terms($post_id, $taxonomy);

                        if (is_wp_error($terms)) {
                            return 'Error: ' . $terms->get_error_message();
                        }

                        if (empty($terms) || !is_array($terms)) {
                            return "No terms assigned in taxonomy '$taxonomy' for post ID $post_id.";
                        }

                        $results = array();

                        foreach ($terms as $term) {
                            $results[] = sprintf(
                                "ID: %d | Name: %s | Slug: %s",
                                $term->term_id,
                                $term->name,
                                $term->slug
                            );
                        }

                        return aiomatic_substr("Post $post_id terms in taxonomy '$taxonomy':\n\n" . implode("\n---\n", $results), 0, 45000);

                    case 'create_term':
                        $taxonomy = $params['taxonomy'] ?? '';
                        $term_name = $params['term_name'] ?? '';

                        if (empty($taxonomy)) {
                            return 'Error: taxonomy parameter was not provided.';
                        }

                        if (empty($term_name)) {
                            return 'Error: term_name parameter was not provided.';
                        }

                        if (!taxonomy_exists($taxonomy)) {
                            return "Error: Taxonomy $taxonomy does not exist.";
                        }

                        $existing = term_exists($term_name, $taxonomy);

                        if ($existing) {
                            $term_id = is_array($existing) && isset($existing['term_id']) ? $existing['term_id'] : $existing;
                            $term = get_term($term_id, $taxonomy);

                            if ($term && !is_wp_error($term)) {
                                return sprintf(
                                    "Term already exists. ID: %d | Name: %s | Slug: %s | Taxonomy: %s",
                                    $term->term_id,
                                    $term->name,
                                    $term->slug,
                                    $term->taxonomy
                                );
                            }

                            return "Term already exists in taxonomy '$taxonomy'.";
                        }

                        $created = wp_insert_term($term_name, $taxonomy);

                        if (is_wp_error($created)) {
                            return 'Error: ' . $created->get_error_message();
                        }

                        $term = get_term($created['term_id'], $taxonomy);

                        if (!$term || is_wp_error($term)) {
                            return "Success: Term created in taxonomy '$taxonomy', but term details could not be loaded.";
                        }

                        return sprintf(
                            "Success: Term created. ID: %d | Name: %s | Slug: %s | Taxonomy: %s",
                            $term->term_id,
                            $term->name,
                            $term->slug,
                            $term->taxonomy
                        );
                    case 'set_post_terms':

                        $taxonomy = $params['taxonomy'] ?? '';
                        $post_id  = !empty($params['post_id']) ? (int)$params['post_id'] : 0;
                        $terms    = $params['term_name'] ?? '';

                        if (empty($taxonomy) || $post_id <= 0 || empty($terms)) {
                            return 'Error: taxonomy, post_id and term_name are required.';
                        }

                        if (!taxonomy_exists($taxonomy)) {
                            return "Error: Taxonomy $taxonomy does not exist.";
                        }
                        $term_names = array_map('trim', explode(',', $terms));
                        $term_ids   = [];

                        foreach ($term_names as $name) {
                            if ($name === '') continue;

                            $existing = term_exists($name, $taxonomy);

                            if (!$existing) {
                                $created = wp_insert_term($name, $taxonomy);
                                if (!is_wp_error($created)) {
                                    $term_ids[] = (int)$created['term_id'];
                                }
                            } else {
                                $term_ids[] = is_array($existing) ? (int)$existing['term_id'] : (int)$existing;
                            }
                        }

                        wp_set_post_terms($post_id, $term_ids, $taxonomy, false);

                        return "Success: Assigned " . count($term_ids) . " terms to post $post_id.";
                    default:
                        return 'Error: Invalid operation.';
                }
            case 'pause_execution':

                $seconds = isset($params['seconds']) ? (int)$params['seconds'] : 0;

                if ($seconds <= 0) {
                    return 'Error: seconds must be greater than 0.';
                }

                if ($seconds > 30) {
                    $seconds = 30;
                }

                sleep($seconds);

                return "Waited $seconds seconds.";
            case 'wp_validate_post_state':

                $post_id = $params['post_id'] ?? 0;
                $checks  = $params['checks'] ?? [];

                if (empty($post_id)) {
                    return 'Error: post_id parameter missing.';
                }

                if (empty($checks) || !is_array($checks)) {
                    return 'Error: checks parameter missing or invalid.';
                }

                $post = get_post($post_id);

                $results = [];
                $all_passed = true;

                if (in_array('exists', $checks, true)) {
                    if ($post) {
                        $results[] = "exists: PASS";
                    } else {
                        $results[] = "exists: FAIL";
                        $all_passed = false;
                    }
                }

                if (!$post) {
                    return implode("\n", $results);
                }

                if (in_array('has_excerpt', $checks, true)) {
                    if (!empty($post->post_excerpt)) {
                        $results[] = "has_excerpt: PASS";
                    } else {
                        $results[] = "has_excerpt: FAIL";
                        $all_passed = false;
                    }
                }

                if (in_array('has_featured_image', $checks, true)) {
                    if (get_post_thumbnail_id($post_id)) {
                        $results[] = "has_featured_image: PASS";
                    } else {
                        $results[] = "has_featured_image: FAIL";
                        $all_passed = false;
                    }
                }

                if (in_array('has_content', $checks, true)) {
                    $clean = trim(wp_strip_all_tags($post->post_content));
                    if (!empty($clean)) {
                        $results[] = "has_content: PASS";
                    } else {
                        $results[] = "has_content: FAIL";
                        $all_passed = false;
                    }
                }

                if (in_array('content_length', $checks, true)) {
                    $min = isset($params['min_content_length']) ? (int)$params['min_content_length'] : 100;
                    $len = strlen(wp_strip_all_tags($post->post_content));

                    if ($len >= $min) {
                        $results[] = "content_length($len >= $min): PASS";
                    } else {
                        $results[] = "content_length($len < $min): FAIL";
                        $all_passed = false;
                    }
                }

                if (in_array('status', $checks, true)) {
                    $expected = $params['expected_status'] ?? '';
                    if (!empty($expected) && $post->post_status === $expected) {
                        $results[] = "status({$post->post_status}): PASS";
                    } else {
                        $results[] = "status({$post->post_status}): FAIL";
                        $all_passed = false;
                    }
                }

                if (in_array('has_terms', $checks, true)) {
                    $taxonomy = $params['taxonomy'] ?? '';
                    if (empty($taxonomy)) {
                        $results[] = "has_terms: FAIL (taxonomy missing)";
                        $all_passed = false;
                    } else {
                        $terms = get_the_terms($post_id, $taxonomy);
                        if (!empty($terms) && !is_wp_error($terms)) {
                            $results[] = "has_terms($taxonomy): PASS";
                        } else {
                            $results[] = "has_terms($taxonomy): FAIL";
                            $all_passed = false;
                        }
                    }
                }

                $summary = $all_passed ? "ALL CHECKS PASSED" : "SOME CHECKS FAILED";

                return $summary . "\n\n" . implode("\n", $results);
            case 'get_wp_post_data':
                $post_id = $params['post_id'] ?? '';

                if (empty($post_id)) {
                    return 'Error: No Post ID provided.';
                }

                $post = get_post($post_id);

                if (!$post) {
                    return "Error: Post with ID $post_id not found.";
                }

                $title   = $post->post_title;
                $content = $post->post_content;
                $excerpt = $post->post_excerpt;
                $status  = $post->post_status;
                $type    = $post->post_type;

                $clean_content = wp_strip_all_tags(strip_shortcodes($content));
                
                $final_output = "Post ID: $post_id\n";
                $final_output .= "Title: $title\n";
                $final_output .= "Status: $status\n";
                $final_output .= "Type: $type\n";
                $final_output .= "Excerpt: $excerpt\n";
                $final_output .= "--- CONTENT START ---\n";
                $final_output .= $clean_content;
                $final_output .= "\n--- CONTENT END ---";

                return aiomatic_substr($final_output, 0, 45000);
            case 'process_and_transform_data':

                $operation = $params['operation'] ?? '';
                $input     = $params['input'] ?? '';

                if (empty($operation) || empty($input)) {
                    return 'Error: operation and input are required.';
                }

                $decoded = json_decode($input, true);

                switch ($operation) {

                    case 'parse_json':

                        if ($decoded === null) {
                            return 'Error: Invalid JSON.';
                        }

                        return json_encode($decoded);

                    case 'stringify_json':

                        return json_encode($input);

                    case 'list_keys':

                        if (!is_array($decoded)) {
                            return 'Error: Input must be JSON object or array.';
                        }

                        return implode(', ', array_keys($decoded));

                    case 'extract_field':

                        $field = $params['field'] ?? '';

                        if (empty($field)) {
                            return 'Error: field parameter required.';
                        }

                        if (!is_array($decoded)) {
                            return 'Error: Input must be JSON.';
                        }

                        if (isset($decoded[$field])) {
                            return json_encode($decoded[$field]);
                        }

                        return 'Error: field not found.';

                    case 'filter_equals':

                        $field = $params['field'] ?? '';
                        $value = $params['value'] ?? '';

                        if (empty($field)) {
                            return 'Error: field parameter required.';
                        }

                        if (!is_array($decoded)) {
                            return 'Error: Input must be JSON array.';
                        }

                        $filtered = [];

                        foreach ($decoded as $item) {
                            if (is_array($item) && isset($item[$field]) && (string)$item[$field] === (string)$value) {
                                $filtered[] = $item;
                            }
                        }

                        return json_encode($filtered);

                    default:
                        return 'Error: Unknown operation.';
                }
            case 'manage_wp_post':
                $operation = isset($params['operation']) ? sanitize_text_field($params['operation']) : '';

                $allowed_operations = [
                    'create',
                    'update',
                    'trash',
                    'untrash',
                    'delete',
                    'duplicate',
                    'append_content',
                    'prepend_content',
                    'set_featured_image',
                    'delete_featured_image',
                    'set_meta',
                    'delete_meta',
                    'set_terms',
                ];

                if (!in_array($operation, $allowed_operations, true)) {
                    return 'Error: Invalid or missing operation.';
                }

                if ($operation === 'create') {
                    if (empty($params['post_title']) || empty($params['post_content'])) {
                        return 'Error: post_title and post_content are required for create.';
                    }

                    $post_data = [
                        'post_title'     => wp_strip_all_tags($params['post_title']),
                        'post_content'   => $params['post_content'],
                        'post_excerpt'   => $params['post_excerpt'] ?? '',
                        'post_status'    => $params['post_status'] ?? 'draft',
                        'post_type'      => $params['post_type'] ?? 'post',
                        'post_name'      => isset($params['post_name']) ? sanitize_title($params['post_name']) : '',
                        'post_parent'    => isset($params['post_parent']) ? (int)$params['post_parent'] : 0,
                        'menu_order'     => isset($params['menu_order']) ? (int)$params['menu_order'] : 0,
                        'comment_status' => $params['comment_status'] ?? 'closed',
                        'ping_status'    => $params['ping_status'] ?? 'closed',
                    ];

                    $new_id = wp_insert_post($post_data, true);
                    if (is_wp_error($new_id)) {
                        return 'Error creating post: ' . $new_id->get_error_message();
                    }

                    if (!empty($params['featured_image_id'])) {
                        set_post_thumbnail($new_id, (int)$params['featured_image_id']);
                    }

                    return "Success: Post created successfully. Post ID: $new_id. URL: " . get_permalink($new_id);
                }

                $post_ids = [];

                if (!empty($params['post_ids'])) {
                    $post_ids = array_map('intval', array_filter(array_map('trim', explode(',', $params['post_ids']))));
                } elseif (!empty($params['ID'])) {
                    $post_ids = [(int)$params['ID']];
                }

                if (empty($post_ids)) {
                    return 'Error: Missing or invalid post ID(s).';
                }

                $results = [];

                foreach ($post_ids as $post_id) {
                    $post = get_post($post_id);

                    if (!$post) {
                        $results[] = "Error: Post with ID $post_id not found.";
                        continue;
                    }

                    switch ($operation) {

                        case 'update':
                            $post_data = ['ID' => $post_id];

                            if (array_key_exists('post_title', $params)) {
                                $post_data['post_title'] = wp_strip_all_tags($params['post_title']);
                            }
                            if (array_key_exists('post_content', $params)) {
                                $post_data['post_content'] = $params['post_content'];
                            }
                            if (array_key_exists('post_excerpt', $params)) {
                                $post_data['post_excerpt'] = $params['post_excerpt'];
                            }
                            if (array_key_exists('post_status', $params)) {
                                $post_data['post_status'] = $params['post_status'];
                            }
                            if (array_key_exists('post_type', $params)) {
                                $post_data['post_type'] = $params['post_type'];
                            }
                            if (array_key_exists('post_name', $params)) {
                                $post_data['post_name'] = sanitize_title($params['post_name']);
                            }
                            if (array_key_exists('post_parent', $params)) {
                                $post_data['post_parent'] = (int)$params['post_parent'];
                            }
                            if (array_key_exists('menu_order', $params)) {
                                $post_data['menu_order'] = (int)$params['menu_order'];
                            }
                            if (array_key_exists('comment_status', $params)) {
                                $post_data['comment_status'] = $params['comment_status'];
                            }
                            if (array_key_exists('ping_status', $params)) {
                                $post_data['ping_status'] = $params['ping_status'];
                            }

                            $updated = wp_update_post($post_data, true);
                            if (is_wp_error($updated)) {
                                $results[] = "Error updating post $post_id: " . $updated->get_error_message();
                                continue 2;
                            }

                            if (array_key_exists('featured_image_id', $params)) {
                                $thumb_id = (int)$params['featured_image_id'];
                                if ($thumb_id > 0) {
                                    set_post_thumbnail($post_id, $thumb_id);
                                } else {
                                    delete_post_thumbnail($post_id);
                                }
                            }

                            $results[] = "Success: Post updated. ID: $post_id";
                            continue 2;

                        case 'trash':
                            $trashed = wp_trash_post($post_id);
                            $results[] = $trashed ? "Success: Trashed $post_id" : "Error: Failed trash $post_id";
                            continue 2;

                        case 'untrash':
                            $restored = wp_untrash_post($post_id);
                            $results[] = $restored ? "Success: Restored $post_id" : "Error: Failed restore $post_id";
                            continue 2;

                        case 'delete':
                            $deleted = wp_delete_post($post_id, true);
                            $results[] = $deleted ? "Success: Deleted $post_id" : "Error: Failed delete $post_id";
                            continue 2;

                        case 'duplicate':
                            $new_post = [
                                'post_title'     => $post->post_title . ' (Copy)',
                                'post_content'   => $post->post_content,
                                'post_excerpt'   => $post->post_excerpt,
                                'post_status'    => 'draft',
                                'post_type'      => $post->post_type,
                                'post_parent'    => $post->post_parent,
                                'menu_order'     => $post->menu_order,
                                'comment_status' => $post->comment_status,
                                'ping_status'    => $post->ping_status,
                            ];

                            $new_id = wp_insert_post($new_post, true);
                            if (is_wp_error($new_id)) {
                                $results[] = "Error duplicating $post_id: " . $new_id->get_error_message();
                                continue 2;
                            }

                            $thumb_id = get_post_thumbnail_id($post_id);
                            if ($thumb_id) {
                                set_post_thumbnail($new_id, $thumb_id);
                            }

                            $results[] = "Success: Duplicated $post_id → $new_id";
                            continue 2;

                        case 'append_content':
                            $content = isset($params['post_content']) ? (string)$params['post_content'] : '';
                            if ($content === '') {
                                $results[] = "Error: Missing content for $post_id";
                                continue 2;
                            }

                            $updated = wp_update_post([
                                'ID' => $post_id,
                                'post_content' => $post->post_content . $content,
                            ], true);

                            $results[] = is_wp_error($updated)
                                ? "Error append $post_id: " . $updated->get_error_message()
                                : "Success: Appended $post_id";
                            continue 2;

                        case 'prepend_content':
                            $content = isset($params['post_content']) ? (string)$params['post_content'] : '';
                            if ($content === '') {
                                $results[] = "Error: Missing content for $post_id";
                                continue 2;
                            }

                            $updated = wp_update_post([
                                'ID' => $post_id,
                                'post_content' => $content . $post->post_content,
                            ], true);

                            $results[] = is_wp_error($updated)
                                ? "Error prepend $post_id: " . $updated->get_error_message()
                                : "Success: Prepended $post_id";
                            continue 2;

                        case 'set_featured_image':

                            $thumb_id = isset($params['featured_image_id']) ? (int)$params['featured_image_id'] : 0;
                            $image_url = isset($params['image_url']) ? trim($params['image_url']) : '';

                            if ($thumb_id <= 0 && !empty($image_url)) {

                                require_once(ABSPATH . 'wp-admin/includes/media.php');
                                require_once(ABSPATH . 'wp-admin/includes/file.php');
                                require_once(ABSPATH . 'wp-admin/includes/image.php');

                                $sideloaded = media_sideload_image($image_url, $post_id, null, 'id');

                                if (is_wp_error($sideloaded)) {
                                    $results[] = "Error: Failed to sideload image for $post_id: " . $sideloaded->get_error_message();
                                    continue 2;
                                }

                                $thumb_id = (int)$sideloaded;
                            }

                            if ($thumb_id <= 0) {
                                $results[] = "Error: Missing featured_image_id or image_url for $post_id";
                                continue 2;
                            }

                            $set = set_post_thumbnail($post_id, $thumb_id);

                            $results[] = $set
                                ? "Success: Featured image set for $post_id (attachment $thumb_id)"
                                : "Error: Failed featured image $post_id";

                            continue 2;

                        case 'delete_featured_image':
                            delete_post_thumbnail($post_id);
                            $results[] = "Success: Removed featured image $post_id";
                            continue 2;

                        case 'set_meta':
                            $meta_key = isset($params['meta_key']) ? sanitize_key($params['meta_key']) : '';
                            if ($meta_key === '') {
                                $results[] = "Error: Missing meta_key for $post_id";
                                continue 2;
                            }

                            update_post_meta($post_id, $meta_key, $params['meta_value'] ?? '');
                            $results[] = "Success: Meta updated $post_id ($meta_key)";
                            continue 2;

                        case 'delete_meta':
                            $meta_key = isset($params['meta_key']) ? sanitize_key($params['meta_key']) : '';
                            if ($meta_key === '') {
                                $results[] = "Error: Missing meta_key for $post_id";
                                continue 2;
                            }

                            delete_post_meta($post_id, $meta_key);
                            $results[] = "Success: Meta deleted $post_id ($meta_key)";
                            continue 2;

                        case 'set_terms':
                            $taxonomy = isset($params['taxonomy']) ? sanitize_key($params['taxonomy']) : '';
                            $terms_raw = isset($params['terms']) ? $params['terms'] : '';

                            $terms = array_map('intval', array_filter(array_map('trim', explode(',', $terms_raw))));

                            if ($taxonomy === '' || empty($terms)) {
                                $results[] = "Error: Missing taxonomy/terms for $post_id";
                                continue 2;
                            }

                            $set = wp_set_object_terms($post_id, $terms, $taxonomy, false);

                            $results[] = is_wp_error($set)
                                ? "Error terms $post_id: " . $set->get_error_message()
                                : "Success: Terms set for $post_id";
                            continue 2;
                    }
                }

                return implode("\n", $results);
            case 'get_post_structure':

                $post_id = isset($params['post_id']) ? (int)$params['post_id'] : 0;

                if ($post_id <= 0) {
                    return 'Error: post_id is required.';
                }

                $post = get_post($post_id);

                if (!$post) {
                    return "Error: Post not found.";
                }

                $content = $post->post_content;

                if (empty($content)) {
                    return "Error: Empty content.";
                }

                $blocks = function_exists('parse_blocks') ? parse_blocks($content) : [];
                $html   = !empty($blocks) ? render_block_data_recursive($blocks) : $content;

                if (empty($html)) {
                    return "Error: Failed to normalize content.";
                }

                libxml_use_internal_errors(true);

                $dom = new DOMDocument();

                $loaded = $dom->loadHTML('<?xml encoding="utf-8" ?>' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

                libxml_clear_errors();

                if (!$loaded) {
                    return "Error: Failed parsing HTML.";
                }

                $xpath = new DOMXPath($dom);

                $structure = [];

                $headings = $xpath->query('//h2 | //h3 | //h4');

                if ($headings) {
                    foreach ($headings as $node) {

                        $text = trim(preg_replace('/\s+/', ' ', $node->textContent));

                        if ($text === '') {
                            continue;
                        }

                        $type = strtolower($node->nodeName);

                        $structure[] = [
                            'type'     => $type,
                            'text'     => $text,
                            'selector' => $type . ':' . $text
                        ];
                    }
                }

                $paragraphs = $xpath->query('//p');
                $paragraph_count = ($paragraphs) ? $paragraphs->length : 0;

                $suggested = array_map(function($s){
                    return $s['selector'];
                }, $structure);

                array_unshift($suggested, 'first_paragraph');
                $suggested[] = 'last_paragraph';

                $suggested = array_values(array_unique($suggested));

                return wp_json_encode([
                    'total_paragraphs'     => $paragraph_count,
                    'total_sections'       => count($structure),
                    'sections'             => $structure,
                    'suggested_selectors'  => $suggested
                ]);
            case 'edit_post_section':
                $post_id    = isset($params['post_id']) ? (int)$params['post_id'] : 0;
                $selector   = isset($params['section_selector']) ? sanitize_text_field($params['section_selector']) : '';
                $instruction = isset($params['instruction']) ? trim(wp_kses_post($params['instruction'])) : '';

                if ($post_id <= 0 || $selector === '' || $instruction === '') {
                    return 'Error: post_id, section_selector and instruction are required.';
                }

                $post = get_post($post_id);
                if (!$post) {
                    return "Error: Post with ID $post_id not found.";
                }

                $content = $post->post_content;
                if (trim($content) === '') {
                    return "Error: Post content is empty.";
                }

                $blocks = function_exists('parse_blocks') ? parse_blocks($content) : array();
                $is_block_editor = function_exists('has_blocks') ? has_blocks($content) : !empty($blocks);
                $html = ($is_block_editor && function_exists('render_block_data_recursive')) ? render_block_data_recursive($blocks) : $content;

                if (trim($html) === '') {
                    return "Error: Failed to prepare post HTML.";
                }

                libxml_use_internal_errors(true);
                $dom = new DOMDocument('1.0', 'UTF-8');

                $loaded = $dom->loadHTML(
                    '<?xml encoding="utf-8" ?><html><body>' . $html . '</body></html>',
                    LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
                );
                libxml_clear_errors();

                if (!$loaded) {
                    return "Error: Failed to parse post HTML.";
                }

                $body = $dom->getElementsByTagName('body')->item(0);
                if (!$body) {
                    return "Error: Failed to locate parsed HTML body.";
                }

                $xpath = new DOMXPath($dom);
                $target_node = null;

                if ($selector === 'full_content') {
                    $target_node = $body;
                }
                elseif ($selector === 'first_paragraph') {
                    $nodes = $xpath->query('//p');
                    if ($nodes && $nodes->length > 0) {
                        $target_node = $nodes->item(0);
                    }
                }
                elseif ($selector === 'last_paragraph') {
                    $nodes = $xpath->query('//p');
                    if ($nodes && $nodes->length > 0) {
                        $target_node = $nodes->item($nodes->length - 1);
                    }
                }
                elseif (strpos($selector, 'paragraph:') === 0) {
                    $num = max(0, ((int) str_replace('paragraph:', '', $selector)) - 1);
                    $nodes = $xpath->query('//p');
                    if ($nodes && $nodes->length > $num) {
                        $target_node = $nodes->item($num);
                    }
                }
                elseif (preg_match('/^h([2-4]):(.+)$/', $selector, $m)) {
                    $tag  = 'h' . $m[1];
                    $text = trim($m[2]);

                    $nodes = $xpath->query('//' . $tag);
                    if ($nodes) {
                        foreach ($nodes as $node) {
                            if (stripos(trim($node->textContent), $text) !== false) {
                                $target_node = $node;
                                break;
                            }
                        }
                    }
                }

                if (!$target_node) {
                    return "Error: Could not locate section for selector '$selector'.";
                }

                if ($selector === 'full_content') {
                    $target_html = '';
                    foreach ($body->childNodes as $child) {
                        $target_html .= $dom->saveHTML($child);
                    }
                } else {
                    $target_html = $dom->saveHTML($target_node);
                }

                if (trim($target_html) === '') {
                    return "Error: Failed extracting target content.";
                }

                $prompt = "You are editing HTML content.

            STRICT RULES:
            - Do NOT remove any existing content unless the instruction clearly asks for it
            - Do NOT shorten text unless the instruction clearly asks for it
            - Do NOT remove links or formatting
            - Keep all HTML tags valid
            - Return valid HTML only
            - Do NOT add explanations or comments

            Instruction:
            {$instruction}

            === ORIGINAL CONTENT START ===
            {$target_html}
            === ORIGINAL CONTENT END ===

            Return ONLY the edited HTML.";

                $model = $this->model;

                $aiomatic_Main_Settings = get_option('aiomatic_Main_Settings', false);
                $appids = array();

                if (is_array($aiomatic_Main_Settings) && !empty($aiomatic_Main_Settings['app_id'])) {
                    $appids = array_filter(preg_split('/\r\n|\r|\n/', trim($aiomatic_Main_Settings['app_id'])));
                }

                $token = !empty($appids) ? $appids[array_rand($appids)] : '';
                $token = apply_filters('aiomatic_openai_api_key', $token);

                if (empty($token)) {
                    return "Error: OpenAI API key is missing.";
                }

                $query_token_count = count(aiomatic_encode($prompt));
                $max_tokens = aimogenpro_get_max_tokens($model);

                $available_tokens = aiomatic_compute_available_tokens(
                    $model,
                    $max_tokens,
                    $prompt,
                    $query_token_count
                );

                if ($available_tokens <= AIMOGEN_MINIMUM_TOKENS_FOR_COMPLETIONS) {
                    $cut = intval(aiomatic_strlen($prompt) / 2);
                    $prompt = trim(aiomatic_substr($prompt, 0, -$cut));

                    $query_token_count = count(aiomatic_encode($prompt));
                    $available_tokens  = $max_tokens - $query_token_count;
                }

                if ($available_tokens <= AIMOGEN_MINIMUM_TOKENS_FOR_COMPLETIONS) {
                    return "Error: Not enough available tokens to edit this section.";
                }

                $thread_id     = '';
                $aierror       = '';
                $finish_reason = '';

                if ($this->is_debug_mode()) {
                    $this->debug_log('Editing post section: ' . print_r($prompt, true));
                }

                $edited = aiomatic_generate_text(
                    $token,
                    $model,
                    $prompt,
                    $available_tokens,
                    0.2,
                    1,
                    0,
                    0,
                    false,
                    'agentsEdit',
                    0,
                    $finish_reason,
                    $aierror,
                    false,
                    false,
                    false,
                    '',
                    '',
                    'user',
                    '',
                    $thread_id,
                    '',
                    'disabled',
                    '',
                    false,
                    false,
                    array(),
                    '',
                    '',
                    ''
                );

                if ($this->is_debug_mode()) {
                    $this->debug_log('Editing post section response: ' . print_r($edited, true));
                }

                if (!empty($aierror)) {
                    return "Error: AI error - " . $aierror;
                }

                if (empty($edited)) {
                    return "Error: AI returned empty result.";
                }

                $edited = trim($edited);
                $edited = preg_replace('/^\s*```(?:html)?\s*/i', '', $edited);
                $edited = preg_replace('/\s*```\s*$/', '', $edited);
                $edited = preg_replace('#</?(?:html|body)[^>]*>#i', '', $edited);
                $edited = trim($edited);

                if ($edited === '') {
                    return "Error: AI returned empty HTML after cleanup.";
                }

                $fragment = $dom->createDocumentFragment();

                if (!@$fragment->appendXML($edited)) {
                    $tmp = new DOMDocument('1.0', 'UTF-8');

                    libxml_use_internal_errors(true);

                    $tmp_loaded = $tmp->loadHTML(
                        '<?xml encoding="utf-8" ?><html><body><div id="aiomatic_tmp_wrapper">' . $edited . '</div></body></html>',
                        LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
                    );

                    libxml_clear_errors();

                    if (!$tmp_loaded) {
                        return "Error: Invalid HTML returned by AI.";
                    }

                    $tmp_xpath = new DOMXPath($tmp);
                    $wrapper   = $tmp_xpath->query('//*[@id="aiomatic_tmp_wrapper"]')->item(0);

                    if (!$wrapper) {
                        return "Error: Could not parse edited HTML wrapper.";
                    }

                    foreach ($wrapper->childNodes as $child) {
                        $fragment->appendChild($dom->importNode($child, true));
                    }

                    if (!$fragment->hasChildNodes()) {
                        return "Error: Edited HTML contains no usable nodes.";
                    }
                }

                if ($selector === 'full_content') {
                    while ($body->firstChild) {
                        $body->removeChild($body->firstChild);
                    }
                    $body->appendChild($fragment);
                } else {
                    if (!$target_node->parentNode) {
                        return "Error: Target node has no parent.";
                    }
                    $target_node->parentNode->replaceChild($fragment, $target_node);
                }

                $body = $dom->getElementsByTagName('body')->item(0);
                if (!$body) {
                    return "Error: Failed to rebuild post HTML body.";
                }

                $new_html = '';
                foreach ($body->childNodes as $child) {
                    $new_html .= $dom->saveHTML($child);
                }

                $new_html = trim($new_html);

                if ($new_html === '') {
                    return "Error: Edited content became empty. Update cancelled.";
                }

                if ($is_block_editor) {
                    $new_content = "<!-- wp:html -->\n" . $new_html . "\n<!-- /wp:html -->";
                } else {
                    $new_content = $new_html;
                }

                $updated = wp_update_post(array(
                    'ID'           => $post_id,
                    'post_content' => $new_content
                ), true);

                if (is_wp_error($updated)) {
                    return "Error updating post: " . $updated->get_error_message();
                }

                return "Success: post ID " . $post_id . " updated.";
            case 'aimogen_content_editor_templates':
                $operation = $params['operation'] ?? '';
                $post_id = isset($params['post_id']) ? intval($params['post_id']) : 0;
                $template_id = isset($params['template_id']) ? intval($params['template_id']) : 0;
                if (empty($operation)) {
                    if(empty($post_id) || empty($template_id))
                    {
                        return 'Error: operation parameter was not provided.';
                    }
                    else
                    {
                        $operation = 'run';
                    }
                }
                if ($operation !== 'list' && $operation !== 'run') {
                    return 'Error: Invalid operation parameter provided.';
                }
                switch ($operation) {
                    case 'list':
                        return aimogen_content_editor_templates_list();
                    case 'run':
                        if ($post_id <= 0) {
                            return 'Error: Missing or invalid post_id.';
                        }
                        $post_obj = get_post($post_id);
                        if (!$post_obj) {
                            return 'Error: Post not found.';
                        }
                        if ($template_id > 0) {
                            $template_post = get_post($template_id);
                            if (!$template_post || $template_post->post_type !== 'aiomatic_editor_temp') {
                                return 'Error: Invalid template_id.';
                            }
                            $template_to_run = $template_id;
                        } else {
                            $template_to_run = 'skip';
                        }
                        aiomatic_do_post($post_obj, true, $template_to_run, false);
                        if ($template_id > 0) {
                            return 'Success: AI Content Editor template applied successfully.';
                        }
                        return 'Success: AI Content Editor executed successfully using default/manual template logic.';
                    default:
                        return 'Error: Invalid operation.';
                }
            case 'get_environment_info':

                $type = isset($params['info_type']) ? sanitize_text_field($params['info_type']) : '';

                if (empty($type)) {
                    return 'Error: Missing info_type parameter.';
                }

                $allowed = ['general','plugins','theme','stats','capabilities','post_types','taxonomies','all'];

                if (!in_array($type, $allowed, true)) {
                    return 'Error: Invalid info_type parameter.';
                }

                $data = [];

                if ($type === 'general' || $type === 'all') {
                    $data['general'] = [
                        'site_url'   => site_url(),
                        'home_url'   => home_url(),
                        'name'       => get_bloginfo('name'),
                        'description'=> get_bloginfo('description'),
                        'admin_email'=> get_bloginfo('admin_email'),
                        'language'   => get_bloginfo('language'),
                        'wp_version' => get_bloginfo('version'),
                    ];
                }

                if ($type === 'theme' || $type === 'all') {
                    $theme = wp_get_theme();

                    $data['theme'] = [
                        'name'    => $theme->get('Name'),
                        'version' => $theme->get('Version'),
                        'author'  => $theme->get('Author'),
                    ];
                }

                $active_plugins = [];
                if ($type === 'plugins' || $type === 'all' || $type === 'capabilities') {

                    if (!function_exists('get_plugins')) {
                        require_once ABSPATH . 'wp-admin/includes/plugin.php';
                    }

                    $active = get_option('active_plugins', []);
                    $all_plugins = get_plugins();

                    foreach ($active as $plugin_file) {
                        if (isset($all_plugins[$plugin_file])) {
                            $active_plugins[] = [
                                'name'    => $all_plugins[$plugin_file]['Name'],
                                'version' => $all_plugins[$plugin_file]['Version'],
                                'file'    => $plugin_file
                            ];
                        }
                    }

                    if ($type === 'plugins' || $type === 'all') {
                        $data['plugins'] = $active_plugins;
                    }
                }

                if ($type === 'stats' || $type === 'all') {

                    $data['stats'] = [
                        'posts' => (int)(wp_count_posts('post')->publish ?? 0),
                        'pages' => (int)(wp_count_posts('page')->publish ?? 0),
                        'products' => post_type_exists('product')
                            ? (int)(wp_count_posts('product')->publish ?? 0)
                            : 0,
                        'users' => (int)(count_users()['total_users'] ?? 0)
                    ];
                }

                if ($type === 'post_types' || $type === 'all') {

                    $cpts = get_post_types(['public' => true], 'objects');

                    $list = [];
                    foreach ($cpts as $pt) {
                        $list[] = [
                            'name' => $pt->name,
                            'label'=> $pt->label
                        ];
                    }

                    $data['post_types'] = $list;
                }

                if ($type === 'taxonomies' || $type === 'all') {

                    $taxes = get_taxonomies(['public' => true], 'objects');

                    $list = [];
                    foreach ($taxes as $tx) {
                        $list[] = [
                            'name' => $tx->name,
                            'label'=> $tx->label,
                            'object_type' => $tx->object_type
                        ];
                    }

                    $data['taxonomies'] = $list;
                }

                if ($type === 'capabilities' || $type === 'all') {

                    $cap = [
                        'woocommerce_active' => class_exists('WooCommerce'),
                        'elementor_active'   => defined('ELEMENTOR_VERSION'),
                        'gutenberg'          => function_exists('register_block_type'),
                        'rest_api'           => function_exists('register_rest_route'),
                        'seo_plugins' => [
                            'yoast' => defined('WPSEO_VERSION'),
                            'rankmath' => defined('RANK_MATH_VERSION'),
                            'aioseo' => defined('AIOSEO_VERSION'),
                        ],
                        'acf_active' => class_exists('ACF'),
                        'custom_fields_supported' => post_type_supports('post', 'custom-fields'),
                        'featured_images_supported' => current_theme_supports('post-thumbnails'),
                        'has_products' => post_type_exists('product')
                    ];

                    $data['capabilities'] = $cap;
                }

                return json_encode($data);
            case 'aimogen_rules_engine':
                $operation = $params['operation'] ?? '';
                $rule_id = $params['rule_id'] ?? '';
                $rule_type = $params['rule_type'] ?? '';

                if (empty($operation)) {
                    if(empty($rule_type) || empty($rule_id))
                    {
                        return 'Error: operation parameter was not provided.';
                    }
                    else
                    {
                        $operation = 'run';
                    }
                }
                if ($operation != 'list' && $operation != 'run') {
                    return 'Error: Invalid operation parameter provided.';
                }
                switch ($operation)
                {
                    case 'list':
                        return aimogen_rules_engine_list();
                    case 'run':
                        if ($rule_id === null) {
                            return 'Error: Missing rule_id';
                        }
                        if ($rule_type === null) {
                            return 'Error: Missing rule_type';
                        }
                        $result = aiomatic_run_rule($rule_id, $rule_type, 0, 0, null, '', '', false, []);
                        if ($result === 'fail') {
                            return 'Error: Execution failed';
                        }
                        if ($result === 'nochange') {
                            return 'Error: No new content generated';
                        }
                        return "Success: Rule executed successfully";
                    default:
                        return 'Error: Invalid operation';
                }
            case 'search_site_posts':

                $search_query = $params['query'] ?? '';
                $post_type    = !empty($params['post_type']) ? (array)$params['post_type'] : ['post','page'];
                $post_status  = !empty($params['post_status']) ? sanitize_text_field($params['post_status']) : 'any';
                $limit        = !empty($params['posts_per_page']) ? min((int)$params['posts_per_page'], 20) : 5;
                $offset       = !empty($params['offset']) ? max((int)$params['offset'], 0) : 0;

                $args = [
                    'post_type'      => $post_type,
                    'post_status'    => $post_status,
                    'posts_per_page' => $limit,
                    'offset'         => $offset,
                    'orderby'        => 'date',
                    'order'          => 'DESC',
                    'no_found_rows'  => true
                ];

                if (!empty($search_query)) {
                    $args['s'] = sanitize_text_field($search_query);
                    $args['orderby'] = 'relevance';
                }

                if (!empty($params['orderby'])) {
                    $args['orderby'] = sanitize_text_field($params['orderby']);
                }

                if (!empty($params['order'])) {
                    $args['order'] = strtoupper($params['order']) === 'ASC' ? 'ASC' : 'DESC';
                }

                if (!empty($params['meta_key'])) {
                    $args['meta_key'] = sanitize_text_field($params['meta_key']);
                }

                if (!empty($params['author_id'])) {
                    $args['author'] = (int)$params['author_id'];
                }

                // Proper date_query
                if (!empty($params['date_after']) || !empty($params['date_before'])) {
                    $date_query = [];

                    if (!empty($params['date_after'])) {
                        $date_query['after'] = sanitize_text_field($params['date_after']);
                    }
                    if (!empty($params['date_before'])) {
                        $date_query['before'] = sanitize_text_field($params['date_before']);
                    }

                    $date_query['inclusive'] = true;
                    $args['date_query'] = [$date_query];
                }

                if (!empty($params['taxonomy']) && !empty($params['terms'])) {
                    $terms = array_map('intval', explode(',', $params['terms']));
                    $args['tax_query'] = [[
                        'taxonomy' => sanitize_text_field($params['taxonomy']),
                        'field'    => 'term_id',
                        'terms'    => $terms
                    ]];
                }

                $meta_query = ['relation' => 'AND'];

                if (isset($params['has_featured_image'])) {
                    if ($params['has_featured_image'] === 'yes') {
                        $meta_query[] = [
                            'key'     => '_thumbnail_id',
                            'compare' => 'EXISTS'
                        ];
                    } elseif ($params['has_featured_image'] === 'no') {
                        $meta_query[] = [
                            'relation' => 'OR',
                            [
                                'key'     => '_thumbnail_id',
                                'compare' => 'NOT EXISTS'
                            ],
                            [
                                'key'     => '_thumbnail_id',
                                'value'   => '',
                                'compare' => '='
                            ]
                        ];
                    }
                }

                if (!empty($params['meta_filters']) && is_string($params['meta_filters'])) {
                    $filters = explode('|', $params['meta_filters']);
                    $count = 0;

                    foreach ($filters as $raw_filter) {
                        if ($count >= 5) break;

                        $parts = array_map('trim', explode(':', trim($raw_filter)));

                        $key     = $parts[0] ?? '';
                        $value   = $parts[1] ?? '';
                        $compare = strtoupper($parts[2] ?? '=');

                        $allowed = ['=', '!=', '>', '>=', '<', '<=', 'LIKE', 'EXISTS', 'NOT EXISTS'];
                        if (!in_array($compare, $allowed, true)) {
                            $compare = '=';
                        }

                        if (empty($key)) continue;

                        if ($compare === 'EXISTS' || $compare === 'NOT EXISTS') {
                            $meta_query[] = [
                                'key'     => sanitize_text_field($key),
                                'compare' => $compare
                            ];
                        } else {
                            $meta_query[] = [
                                'key'     => sanitize_text_field($key),
                                'value'   => sanitize_text_field($value),
                                'compare' => $compare
                            ];
                        }

                        $count++;
                    }
                }

                if (count($meta_query) > 1) {
                    $args['meta_query'] = $meta_query;
                }

                $has_excerpt_filter = null;
                $excerpt_filter_cb  = null;

                if (isset($params['has_excerpt'])) {
                    if ($params['has_excerpt'] === 'yes') {
                        $has_excerpt_filter = 'yes';
                    } elseif ($params['has_excerpt'] === 'no') {
                        $has_excerpt_filter = 'no';
                    }
                }

                $length_filter_cb = null;

                $min_len = isset($params['min_content_length']) ? (int)$params['min_content_length'] : 0;
                $max_len = isset($params['max_content_length']) && (int)$params['max_content_length'] > 0
                    ? (int)$params['max_content_length']
                    : 0;

                if ($has_excerpt_filter !== null) {

                    $excerpt_filter_cb = function ($where) use ($has_excerpt_filter) {
                        global $wpdb;

                        if ($has_excerpt_filter === 'yes') {
                            $where .= " AND {$wpdb->posts}.post_excerpt != ''";
                        } elseif ($has_excerpt_filter === 'no') {
                            $where .= " AND ({$wpdb->posts}.post_excerpt = '' OR {$wpdb->posts}.post_excerpt IS NULL)";
                        }

                        return $where;
                    };

                    add_filter('posts_where', $excerpt_filter_cb);
                }
                if ($min_len > 0 || $max_len > 0) {

                    $length_filter_cb = function ($where) use ($min_len, $max_len) {
                        global $wpdb;

                        if ($min_len > 0) {
                            $where .= $wpdb->prepare(
                                " AND CHAR_LENGTH({$wpdb->posts}.post_content) >= %d",
                                $min_len
                            );
                        }

                        if ($max_len > 0) {
                            $where .= $wpdb->prepare(
                                " AND CHAR_LENGTH({$wpdb->posts}.post_content) <= %d",
                                $max_len
                            );
                        }

                        return $where;
                    };

                    add_filter('posts_where', $length_filter_cb);
                }
                $query = new WP_Query($args);
                if ($excerpt_filter_cb !== null) {
                    remove_filter('posts_where', $excerpt_filter_cb);
                }
                if ($length_filter_cb !== null) {
                    remove_filter('posts_where', $length_filter_cb);
                }
                $results = [];

                if ($query->have_posts()) {
                    foreach ($query->posts as $post) {
                        $content = wp_strip_all_tags($post->post_content);
                        $results[] = sprintf(
                            "ID: %d | Title: %s | Status: %s | Date: %s | Words: %d | Image: %s | Excerpt: %s",
                            $post->ID,
                            $post->post_title,
                            $post->post_status,
                            $post->post_date,
                            str_word_count($content),
                            has_post_thumbnail($post->ID) ? 'yes' : 'no',
                            !empty($post->post_excerpt) ? 'yes' : 'no'
                        );
                    }
                }

                wp_reset_postdata();

                if (empty($results)) {
                    return "No results found for the given filters.";
                }

                return aiomatic_substr("Filtered Search Results:\n\n" . implode("\n---\n", $results), 0, 40000);
            case 'get_wp_media_info':

                $post_id       = isset($params['post_id']) ? intval($params['post_id']) : 0;
                $attachment_id = isset($params['attachment_id']) ? intval($params['attachment_id']) : 0;
                $include_att   = !empty($params['include_attachments']);

                if ($post_id <= 0 && $attachment_id <= 0) {
                    return 'Error: Provide post_id or attachment_id.';
                }

                $output = [];

                if ($attachment_id > 0) {

                    $attachment = get_post($attachment_id);

                    if (!$attachment || $attachment->post_type !== 'attachment') {
                        return 'Error: Attachment not found.';
                    }

                    $file_path = get_attached_file($attachment_id);
                    $file_url  = wp_get_attachment_url($attachment_id);
                    $metadata  = wp_get_attachment_metadata($attachment_id);

                    $output[] = "Attachment ID: $attachment_id";
                    $output[] = "URL: $file_url";
                    $output[] = "Mime: {$attachment->post_mime_type}";
                    $output[] = "File: $file_path";

                    if (!empty($metadata['width']) && !empty($metadata['height'])) {
                        $output[] = "Dimensions: {$metadata['width']}x{$metadata['height']}";
                    }

                    return implode("\n", $output);
                }

                $post = get_post($post_id);

                if (!$post) {
                    return "Error: Post not found.";
                }

                $output[] = "Post ID: $post_id";
                $output[] = "Title: {$post->post_title}";

                $thumb_id = get_post_thumbnail_id($post_id);

                if ($thumb_id) {
                    $thumb_url = wp_get_attachment_url($thumb_id);
                    $meta      = wp_get_attachment_metadata($thumb_id);

                    $output[] = "Featured Image: YES";
                    $output[] = "Featured Image ID: $thumb_id";
                    $output[] = "Featured Image URL: $thumb_url";

                    if (!empty($meta['width']) && !empty($meta['height'])) {
                        $output[] = "Featured Image Size: {$meta['width']}x{$meta['height']}";
                    }
                } else {
                    $output[] = "Featured Image: NO";
                }

                if ($include_att) {

                    $attachments = get_children([
                        'post_parent' => $post_id,
                        'post_type'   => 'attachment',
                        'numberposts' => 10
                    ]);

                    if (!empty($attachments)) {

                        $output[] = "--- Attachments ---";

                        foreach ($attachments as $att) {

                            $att_id  = $att->ID;
                            $att_url = wp_get_attachment_url($att_id);
                            $meta    = wp_get_attachment_metadata($att_id);

                            $line = "ID: $att_id | Type: {$att->post_mime_type} | URL: $att_url";

                            if (!empty($meta['width']) && !empty($meta['height'])) {
                                $line .= " | {$meta['width']}x{$meta['height']}";
                            }

                            $output[] = $line;
                        }

                    } else {
                        $output[] = "Attachments: none";
                    }
                }

                return implode("\n", $output);
            case 'wp_sideload_media':
                $image_url = $params['image_url'] ?? '';
                $post_id   = $params['post_id'] ?? 0;

                if (empty($image_url)) {
                    return 'Error: No image URL provided.';
                }

                require_once(ABSPATH . 'wp-admin/includes/media.php');
                require_once(ABSPATH . 'wp-admin/includes/file.php');
                require_once(ABSPATH . 'wp-admin/includes/image.php');

                $desc = "Image sideloaded by AIomatic";
                $result = media_sideload_image($image_url, $post_id, $desc, 'id');

                if (is_wp_error($result)) {
                    return "Error sideloading image: " . $result->get_error_message();
                } else {
                    $attachment_url = wp_get_attachment_url($result);
                    return "Success! Image sideloaded. Attachment ID: $result. URL: $attachment_url";
                }
            case 'list_available_ai_agents':

                $agents_query = new WP_Query([
                    'post_type'      => 'aiomatic_agent',
                    'post_status'    => 'publish',
                    'posts_per_page' => -1,
                ]);

                $available_agents = [];

                if ($agents_query->have_posts()) {
                    $all_tools = Aiomatic_Agent::get_agent_tools();
                    $all_tool_names = array_keys($all_tools);
                    while ($agents_query->have_posts()) {
                        $agents_query->the_post();

                        $agent_id = get_the_ID();
                        if ((int) $agent_id === (int) $this->agent_id) {
                            continue;
                        }
                        $config = get_post_meta($agent_id, '_agent_config', true);
                        $allowed_tools = [];

                        if (is_array($config)) {
                            if (
                                array_key_exists('allowed_tools', $config) &&
                                is_array($config['allowed_tools']) &&
                                !empty($config['allowed_tools'])
                            ) {
                                $allowed_tools = array_values($config['allowed_tools']);
                            } else {
                                $allowed_tools = $all_tool_names;
                            }
                        } else {
                            $allowed_tools = $all_tool_names;
                        }
                        $allowed_tools = array_values(array_intersect($allowed_tools, $all_tool_names));
                        $available_agents[] = [
                            'agent_id'    => $agent_id,
                            'agent_name'  => get_the_title(),
                            'description' => get_post_meta($agent_id, 'aiomatic_agent_description', true),
                            'expertise'   => get_post_meta($agent_id, 'aiomatic_agent_expertise', true),
                            'tools'       => $allowed_tools,
                            'capabilities' => [
                                'can_publish' => (in_array('manage_wp_post', $allowed_tools) || in_array('edit_post_section', $allowed_tools)),
                                'can_research' => in_array('google_results_parser', $allowed_tools),
                                'can_scrape' => in_array('website_scraper', $allowed_tools),
                                'can_email' => in_array('wp_send_email', $allowed_tools),
                            ],
                            'max_steps' => isset($config['max_steps']) ? intval($config['max_steps']) : 20,
                            'model' => get_post_meta($agent_id, '_model', true),
                        ];
                    }
                    wp_reset_postdata();
                }

                if (empty($available_agents)) {
                    return 'No available agents found.';
                }
                return wp_json_encode($available_agents);
            case 'delegate_to_ai_agent':

                if (empty($this->config['allow_delegation'])) {
                    return [
                        'error' => 'delegation_disabled',
                        'instruction' => 'Delegation is not allowed. Continue solving the task yourself.'
                    ];
                }

                if ($this->is_sub_agent) {
                    return [
                        'error' => 'subagent_cannot_delegate',
                        'instruction' => 'Sub-agents cannot delegate further. Complete the task directly.'
                    ];
                }

                $agent_id = isset($params['agent_id']) ? trim((string)$params['agent_id']) : '';
                $task     = isset($params['task']) ? trim((string)$params['task']) : '';

                if ($agent_id === '' || $task === '') {
                    return [
                        'error' => 'missing_parameters',
                        'required' => ['agent_id', 'task'],
                        'instruction' => 'Call list_available_ai_agents first, select a valid agent_id, then call delegate_to_ai_agent again with both agent_id and task.'
                    ];
                }

                if ((int)$agent_id === (int)$this->agent_id) {
                    return [
                        'error' => 'invalid_target',
                        'instruction' => 'You cannot delegate to yourself. Choose a different agent_id.'
                    ];
                }

                $sub_agent_response = $this->aiomatic_call_agent($agent_id, $task);

                if (!empty($sub_agent_response)) {
                    return [
                        'output'  => $sub_agent_response,
                        'message' => "Sub-task completed by Agent #{$agent_id}.",
                        'next_step' => 'If the result is content intended for publishing, consider using manage_wp_post or edit_post_section.'
                    ];
                }

                return [
                    'error' => 'execution_failed',
                    'instruction' => 'The delegated agent failed. Retry or choose a different agent.'
                ];
            case 'read_server_file':
                $file_path = $params['file_path'] ?? '';

                $base_dir = WP_CONTENT_DIR; 
                $requested_path = ltrim($file_path, '/\\');
                $real_path = realpath(ABSPATH . $requested_path);

                if (!$real_path || strpos($real_path, $base_dir) !== 0) {
                    return "Error: Access denied. You can only read files within the wp-content directory.";
                }

                $allowed_extensions = ['txt', 'log', 'csv', 'json'];
                $file_info = pathinfo($real_path);
                
                if (!in_array($file_info['extension'], $allowed_extensions)) {
                    return "Error: File type .{$file_info['extension']} is not supported for reading.";
                }
                global $wp_filesystem;
                if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base') ){
                    include_once(ABSPATH . 'wp-admin/includes/file.php');$creds = request_filesystem_credentials( site_url() );
                    wp_filesystem($creds);
                }
                if ($wp_filesystem->exists($real_path)) {
                    $content = $wp_filesystem->get_contents($real_path);
                    
                    $truncated_content = substr($content, 0, 5000); 

                    return [
                        'output' => $truncated_content,
                        'message' => "Successfully read file: " . basename($real_path)
                    ];
                } else {
                    return "Error: File not found at the specified path.";
                }
            case 'write_server_file':
                $filename  = $params['filename'] ?? '';
                $content   = $params['content'] ?? '';
                $overwrite = !empty($params['overwrite']);

                if (empty($filename)) {
                    return "Error: filename parameter is required.";
                }

                if (!is_string($content)) {
                    return "Error: content parameter must be a string.";
                }

                $upload_dir = wp_upload_dir();
                $base_dir   = trailingslashit($upload_dir['basedir']) . 'aiomatic-exports/';
                global $wp_filesystem;
                if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base') ){
                    include_once(ABSPATH . 'wp-admin/includes/file.php');$creds = request_filesystem_credentials( site_url() );
                    wp_filesystem($creds);
                }
                if (!$wp_filesystem->exists($base_dir)) {
                    wp_mkdir_p($base_dir);
                }

                $index_file = $base_dir . 'index.php';
                if (!$wp_filesystem->exists($index_file)) {
                    $wp_filesystem->put_contents($index_file, "<?php\n// Silence is golden.\n");
                }

                $filename = sanitize_file_name($filename);

                if (empty($filename)) {
                    return "Error: Invalid filename provided.";
                }

                if (basename($filename) !== $filename) {
                    return "Error: Subdirectories are not allowed.";
                }

                $file_info = pathinfo($filename);
                $extension = strtolower($file_info['extension'] ?? '');

                $allowed_extensions = ['txt', 'log', 'csv', 'json', 'md'];

                if (empty($extension) || !in_array($extension, $allowed_extensions, true)) {
                    return "Error: File type ." . $extension . " is not allowed for writing.";
                }

                $max_size = 2 * 1024 * 1024;
                if (strlen($content) > $max_size) {
                    return "Error: Content exceeds the maximum allowed size of 2MB.";
                }

                $target_path = $base_dir . $filename;
                $real_base   = realpath($base_dir);
                $real_target_dir = realpath(dirname($target_path));

                if (!$real_base || !$real_target_dir || strpos($real_target_dir, $real_base) !== 0) {
                    return "Error: Invalid write target.";
                }

                if ($wp_filesystem->exists($target_path) && !$overwrite) {
                    return "Error: File already exists. Set overwrite=true to replace it.";
                }

                if ($extension === 'json') {
                    json_decode($content, true);
                    if (json_last_error() !== JSON_ERROR_NONE) {
                        return "Error: Invalid JSON content provided.";
                    }
                }
                
                $bytes = $wp_filesystem->put_contents($target_path, $content, LOCK_EX);

                if ($bytes === false) {
                    return "Error: Failed to write file.";
                }

                aiomatic_log_to_file('Agent wrote file: ' . $target_path);

                return [
                    'output' => 'Success: File written successfully.',
                    'message' => 'Saved file: ' . basename($target_path) . ' (' . size_format($bytes) . ')'
                ];
            default:
                return "Error: Tool '$name' not found.";
        }
    }
}
?>
