Task configuration:
{"task_id": "03", "task_name": "open_note", "description": "\u68c0\u67e5Joplin\u4e2d\u5f53\u524d\u6253\u5f00\u7684\u662f\u5426\u662f\u6307\u5b9a\u540d\u79f0\u7684\u7b14\u8bb0", "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": "hi"}, "instruction_template": "\u5728Joplin\u5f53\u524d\u7a97\u53e3\u6253\u5f00\u540d\u4e3a ${note_name} \u7684\u7b14\u8bb0", "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\u5f53\u524d\u6253\u5f00\u7684\u7b14\u8bb0\u662f\u5426\u7b26\u5408\u9884\u671f", "is_key_step": true, "key_step_index": 1, "key_step_name": "\u7b14\u8bb0\u68c0\u67e5\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('Task03_openNote---------------------------');
        
        // 监听 evaluate 事件
        socket.on("evaluate", async () => {
            try {
                // 获取当前选中的笔记ID
                const selectedNoteIds = await joplin.workspace.selectedNoteIds();
                
                if (selectedNoteIds.length === 0) {
                    console.log('No note is currently selected');
                    window.postMessage({
                        "event_type": "evaluate_on_completion",
                        "message": "当前没有打开的笔记",
                        "data": null
                    }, '*');
                    return;
                }

                // 获取当前笔记的详细信息
                const currentNoteId = selectedNoteIds[0];
                const note = await joplin.data.get(['notes', currentNoteId]);
                console.log('Current note:', note.title);
                
                // 使用 postMessage 发送评估消息
                window.postMessage({
                    "event_type": "evaluate_on_completion",
                    "message": "当前打开的笔记是: " + note.title,
                    "data": note.title
                }, '*');
                console.log('Evaluation result sent via postMessage');
            } 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 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":
        current_note = message.get("data")
        expected_note = task_parameter.get('note_name', "测试笔记")
        
        if current_note is None:
            return [{"status": "error", "type": "evaluate_on_completion", "message": "当前没有打开的笔记"}]
        
        if current_note == expected_note:
            return [
                {"status": "key_step", "index": 1},
                {"status": "success", "reason": f"成功找到名为 {expected_note} 的笔记"}
            ]
        else:
            return [{"status": "error", "type": "evaluate_on_completion", "message": f"当前打开的笔记不是 {expected_note}，而是 {current_note}"}]
    return None