Task configuration:
{"task_id": "22", "task_name": "set_unit_system", "description": "In FreeCAD, first set the unit system to 3, then set it back to 0", "application_info": {"name": "FreeCAD", "executable_path": "/usr/local/bin/FreeCAD", "args": []}, "task_parameters": {"first_unit_system": 3, "final_unit_system": 0, "first_unit_system_name": "Imperial decimal", "final_unit_system_name": "Standard"}, "instruction_template": "The application is already open. In the FreeCAD application, using open first start setup, first set the unit system to no.${first_unit_system} which called ${final_unit_system_name}, then set it back to no.${final_unit_system} which called ${final_unit_system_name}", "evaluation_setup": {"scripts": [{"role": "hook", "path": "hooker.js"}, {"role": "handler", "path": "handler.py"}], "timeout": 120}, "preconditions": {"FreeCAD_running": true}, "total_key_steps": 2, "events": {"script_initialized": {"description": "Hook script initialization", "is_key_step": false}, "function_found": {"description": "Found unit system setting function", "is_key_step": false}, "function_called": {"description": "Unit system setting function was called", "is_key_step": false}, "first_unit_system_set": {"description": "First unit system setting detected", "is_key_step": true, "key_step_index": 1, "key_step_name": "Successfully set unit system to 3"}, "final_unit_system_set": {"description": "Final unit system setting detected", "is_key_step": true, "key_step_index": 2, "key_step_name": "Successfully set unit system back to 0"}, "error": {"description": "Error event", "is_key_step": false}}, "mcp_servers": [{"command": "python3", "args": ["/home/agent/.local/share/FreeCAD/Mod/freecad_mcp/src/freecad_bridge.py"]}]}

Hook script:
// FreeCAD Unit System Setting Monitoring Hook Script
// Used to monitor unit system setting operations in FreeCAD

(function() {
  // Script constants
  const FUNCTION_NAME = "_ZN4Base8UnitsApi9setSchemaENS_10UnitSystemE"
  const ORIGIN_FUNCTION_NAME = "Base::UnitsApi::setSchema"
  const FUNCTION_BEHAVIOR = "set unit system"

  const SCRIPT_INITIALIZED = "script_initialized"
  const FUNCTION_NOT_FOUND = "function_not_found"
  const FUNCTION_FOUND = "function_found"
  const FUNCTION_CALLED = "function_called"
  const FIRST_UNIT_SYSTEM_SET = "first_unit_system_set"
  const FINAL_UNIT_SYSTEM_SET = "final_unit_system_set"
  const ERROR = "error"
  const HOOK_INSTALLED = "hook_installed"

  const APP_NAME = "FreeCAD"
  
  // Global variables
  let funcFound = false;
  let firstUnitSystemDetected = false;
  let firstUnitSystem = 3;  // Expected first unit system value
  let finalUnitSystem = 0;  // Expected final unit system value
  
  // Send event to evaluation system
  function sendEvent(eventType, data = {}) {
      const payload = {
          event: eventType,
          ...data,
          timestamp: new Date().getTime()
      };
      send(payload);
  }
  
  // Find Base::UnitsApi::setSchema function
  function getFunction() {
      // Try to find directly through exported symbol
      let FuncAddr = DebugSymbol.getFunctionByName(FUNCTION_NAME);
      
      // If not found, report error
      if (!FuncAddr) {
          sendEvent(ERROR, {
              error_type: FUNCTION_NOT_FOUND,
              message: `Cannot find ${ORIGIN_FUNCTION_NAME} function`
          });
          return null;
      }
      
      // Report function found
      funcFound = true;
      sendEvent(FUNCTION_FOUND, {
          address: FuncAddr.toString(),
          message: `Found ${ORIGIN_FUNCTION_NAME} function`
      });
      
      return FuncAddr;
  }
  
  // Initialize hook and execute immediately
  function initHook() {
      sendEvent(SCRIPT_INITIALIZED, {
          message: `${APP_NAME} ${FUNCTION_BEHAVIOR} monitoring script started`
      });
      
      // Find unit system setting function
      const funcAddr = getFunction();
      if (!funcAddr) {
          return;
      }
      
      // Install unit system setting function hook
      Interceptor.attach(funcAddr, {
          onEnter: function(args) {
              try {
                  sendEvent(FUNCTION_CALLED, {
                      message: `Intercepted ${FUNCTION_BEHAVIOR} function call`
                  });
                  // args[0] is this pointer, args[1] is unit system enum value
                  this.unitSystem = parseInt(args[1]);
              } catch (error) {
                  sendEvent(ERROR, {
                      error_type: "general_error",
                      message: `Execution error: ${error.message}`
                  });
              }
          },

          onLeave: function(retval) {
              try {
                  // Detect if this is the first setting to 3
                  if (this.unitSystem === firstUnitSystem && !firstUnitSystemDetected) {
                      firstUnitSystemDetected = true;
                      sendEvent(FIRST_UNIT_SYSTEM_SET, {
                          message: `Detected first ${FUNCTION_BEHAVIOR} operation`,
                          unit_system: this.unitSystem
                      });
                  }
                  // Detect if this is the final setting to 0
                  else if (this.unitSystem === finalUnitSystem && firstUnitSystemDetected) {
                      sendEvent(FINAL_UNIT_SYSTEM_SET, {
                          message: `Detected final ${FUNCTION_BEHAVIOR} operation`,
                          unit_system: this.unitSystem
                      });
                  }
              } catch (error) {
                  sendEvent(ERROR, {
                      error_type: "general_error",
                      message: `Execution error: ${error.message}`
                  });
              }
          }
      });
      
      sendEvent(HOOK_INSTALLED, {
          message: `Hook installation complete, waiting for ${FUNCTION_BEHAVIOR} operation...`
      });
  }
  
  // 立即执行钩子初始化
  initHook();
})();


Evaluation handler:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
FreeCAD Event Handler
Responsible for processing events generated by the hook script and determining if the task is completed
"""

import os
from typing import Dict, Any, Optional, List

# 事件类型常量
SCRIPT_INITIALIZED = "script_initialized"
FUNCTION_NOT_FOUND = "function_not_found"
FUNCTION_FOUND = "function_found"
FUNCTION_CALLED = "function_called"
FIRST_UNIT_SYSTEM_SET = "first_unit_system_set"
FINAL_UNIT_SYSTEM_SET = "final_unit_system_set"
ERROR = "error"
HOOK_INSTALLED = "hook_installed"

# 关键字相关常量
KEY = "unit_system"
KEY_WORDS = [KEY]

def message_handler(message: Dict[str, Any], logger: Any, task_parameter: Dict[str, Any]) -> Optional[List[Dict[str, Any]]]:
    """
    Process messages received from the hook script
    
    Args:
        message: Frida message object
        logger: Logger
        task_parameter: Task parameters
        
    Returns:
        List[Dict[str, Any]]: List of dictionaries containing status updates, or None if no updates
    """
    # Process the message
    if message.get('type') == 'send' and 'payload' in message:
        payload = message['payload']
        
        # Check if it contains an event type
        if 'event' in payload:
            event_type = payload['event']
            logger.debug(f"Event received: {event_type}")
            
            # Handle specific events
            if event_type == SCRIPT_INITIALIZED:
                logger.info(f"Hook script initialized: {payload.get('message', '')}")
                return None
                
            elif event_type == FUNCTION_FOUND:
                logger.info(f"Function found: {payload.get('address', '')}")
                return None
                
            elif event_type == FUNCTION_CALLED: 
                logger.info(f"Function called: {payload.get('message', '')}")
                return None
                
            elif event_type == FIRST_UNIT_SYSTEM_SET:
                log_info = f"Function detected first unit system setting: {payload.get('message', '')}"
                for key in KEY_WORDS:
                    if key in payload:
                        log_info += f", {key}: {payload.get(key, '')}"
                logger.info(log_info)

                expected_unit_system = task_parameter.get("first_unit_system", 3)
                actual_unit_system = int(payload.get(KEY, -1))
                logger.debug(f"Expected unit system: {expected_unit_system}, Actual unit system: {actual_unit_system}")

                if actual_unit_system == expected_unit_system:
                    # Create status update list
                    updates = []
                    
                    # Report key step completed
                    updates.append({
                        'status': 'key_step',
                        'index': 1,
                        'name': f'Successfully set unit system to {expected_unit_system}'
                    })
                    
                    logger.info(f"First step completed!")
                    return updates
                
            elif event_type == FINAL_UNIT_SYSTEM_SET:
                log_info = f"Function detected final unit system setting: {payload.get('message', '')}"
                for key in KEY_WORDS:
                    if key in payload:
                        log_info += f", {key}: {payload.get(key, '')}"
                logger.info(log_info)

                expected_unit_system = task_parameter.get("final_unit_system", 0)
                actual_unit_system = int(payload.get(KEY, -1))
                logger.debug(f"Expected unit system: {expected_unit_system}, Actual unit system: {actual_unit_system}")

                if actual_unit_system == expected_unit_system:
                    # Create status update list
                    updates = []
                    
                    # Report key step completed
                    updates.append({
                        'status': 'key_step',
                        'index': 2,
                        'name': f'Successfully set unit system back to {expected_unit_system}'
                    })
                    
                    # Report task success
                    updates.append({
                        'status': 'success',
                        'reason': f'Successfully completed unit system setting task'
                    })
                    
                    logger.info(f"Task successfully completed!")
                    return updates
                
            elif event_type == ERROR:
                error_type = payload.get("error_type", "unknown")
                error_message = payload.get("message", "Unknown error")
                
                logger.error(f"Hook script error ({error_type}): {error_message}")
                
                return [{
                    'status': 'error',
                    'type': error_type,
                    'message': error_message
                }]
                
    elif message.get('type') == 'error':
        logger.error(f"Hook script error: {message.get('stack', '')}")
        
        return [{
            'status': 'error',
            'type': 'script_error',
            'message': message.get('stack', 'Unknown error')
        }]
    
    return None