Task configuration:
{"task_id": "18", "task_name": "add_note_location", "description": "\u5728Joplin\u4e2d\u4e3a\u6307\u5b9a\u7b14\u8bb0\u6dfb\u52a0\u4f4d\u7f6e\u4fe1\u606f", "application_info": {"name": "joplin", "executable_path": "/workspace/PC-Canary/apps/joplin/Joplin-3.3.12.AppImage", "args": ["--env", "dev", "--profile", "/workspace/PC-Canary/apps/joplin/joplindev-desktop"]}, "task_parameters": {"note_name": "test_note", "latitude": "39.9042", "longitude": "116.4074"}, "instruction_template": "\u5728Joplin\u4e2d\u4e3a\u540d\u4e3a ${note_name} \u7684\u7b14\u8bb0\u6dfb\u52a0\u4f4d\u7f6e\u4fe1\u606f\uff1a\u7eac\u5ea6 ${latitude}\uff0c\u7ecf\u5ea6 ${longitude}", "evaluation_setup": {"scripts": [{"role": "hook", "path": "hooker.js"}, {"role": "handler", "path": "handler.py"}], "timeout": 120, "evaluator_type": "IpcInjector", "evaluate_on_completion": true}, "total_key_steps": 1, "preconditions": {"joplin_running": true}, "events": {"evaluate_on_completion": {"description": "\u5728\u4efb\u52a1\u7ed3\u675f\u65f6\u5224\u65ad\u6307\u5b9a\u7b14\u8bb0\u662f\u5426\u5df2\u6dfb\u52a0\u4f4d\u7f6e\u4fe1\u606f", "is_key_step": true, "key_step_index": 1, "key_step_name": "\u7b14\u8bb0\u4f4d\u7f6e\u4fe1\u606f\u6dfb\u52a0\u5b8c\u6210"}}, "mcp_servers": [{"command": "/home/user/.local/bin/uv", "args": ["--directory", "/home/user/Desktop/joplin-mcp-server", "run", "src/mcp/joplin_mcp.py"]}]}

Hook script:
// 使用 Joplin 插件 API 来处理通信
joplin.plugins.register({
    onStart: async function() {
        console.log('Joplin plugin started');
        
        // 监听 evaluate 事件
        socket.on("evaluate", async () => {
            console.log('Task18_addNoteLocation---------------------------');
            try {
                // 获取所有笔记
                const notes = await joplin.data.get(['notes']);
                const noteList = notes.items;
                
                // 获取指定笔记的位置信息
                const targetNote = noteList.find(note => note.title === 'test_note');
                let location = {};
                
                if (targetNote) {
                    // 获取笔记的完整信息，包括位置数据
                    const noteData = await joplin.data.get(['notes', targetNote.id], {
                        fields: ['id', 'title', 'latitude', 'longitude']
                    });
                    
                    location = {
                        latitude: noteData.latitude,
                        longitude: noteData.longitude
                    };
                }
                
                console.log('Note location:', location);
                
                // 使用 postMessage 发送评估消息
                window.postMessage({
                    "event_type": "evaluate_on_completion",
                    "message": "当前笔记位置信息：" + JSON.stringify(location),
                    "data": {
                        "location": location
                    }
                }, '*');
            } catch (error) {
                console.error('Error in evaluate handler:', error);
            }
        });
    }
}); 

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

"""
joplin添加笔记位置信息的事件处理器
负责处理钩子脚本产生的事件并更新评估指标
"""

from typing import Dict, Any, Optional, List

def get_integer_part(value: str) -> int:
    """获取数值的整数部分"""
    if value is None:
        return None
    try:
        return int(float(value))
    except (ValueError, TypeError):
        return None

def message_handler(message: Dict[str, Any], logger, task_parameter: Dict[str, Any]) -> Optional[List[Dict[str, Any]]]:    
    event_type = message.get('event_type')
    logger.info(message.get('message'))
    
    if event_type == "evaluate_on_completion":
        data = message.get("data", {})
        note_location = data.get("location", {})
        
        # 从task_parameter获取期望的位置信息
        expected_latitude = task_parameter.get('latitude')
        expected_longitude = task_parameter.get('longitude')
        
        # 获取实际的位置信息
        actual_latitude = note_location.get('latitude')
        actual_longitude = note_location.get('longitude')
        
        logger.info(f"期望的位置信息：纬度 {expected_latitude}，经度 {expected_longitude}")
        logger.info(f"实际的位置信息：纬度 {actual_latitude}，经度 {actual_longitude}")
        
        # 获取整数部分进行比较
        expected_lat_int = get_integer_part(expected_latitude)
        expected_lon_int = get_integer_part(expected_longitude)
        actual_lat_int = get_integer_part(actual_latitude)
        actual_lon_int = get_integer_part(actual_longitude)
        
        # 检查整数部分是否匹配
        if (expected_lat_int is not None and actual_lat_int is not None and
            expected_lon_int is not None and actual_lon_int is not None and
            expected_lat_int == actual_lat_int and 
            expected_lon_int == actual_lon_int):
            return [
                {"status": "key_step", "index": 1},
                {"status": "success", "reason": f"成功为笔记添加位置信息：纬度 {expected_latitude}，经度 {expected_longitude}"}
            ]
        else:
            return [{"status": "error", "type": "evaluate_on_completion", 
                    "message": f"位置信息不匹配，期望：纬度 {expected_latitude}，经度 {expected_longitude}，实际：纬度 {actual_latitude}，经度 {actual_longitude}"}]
    return None