Task configuration:
{"task_id": "03", "task_name": "open_file_and_fold_block", "description": "\u5728vscode\u5de5\u4f5c\u533a\u4e2d\u6253\u5f00\u6587\u4ef6\u5e76\u4e14\u6298\u53e0\u6240\u6709\u4ee3\u7801\u5757", "application_info": {"name": "vscode", "executable_path": "/usr/share/code/code", "args": ["--no-sandbox", "--user-data-dir=/root/vscode_user_data_dir/"]}, "task_parameters": {"file_name": "binary_search.cpp", "expected_file_path": "/root/C-Plus-Plus/search/binary_search.cpp"}, "instruction_template": "\u5728vscode\u5f53\u524d\u5de5\u4f5c\u533a\u4e2d\u6253\u5f00\u540d\u4e3a ${file_name} \u7684\u6587\u4ef6, \u5e76\u4e14\u6298\u53e0\u6587\u4ef6\u5185\u6240\u6709\u7684\u4ee3\u7801\u5757", "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": 2, "preconditions": {"vscode_running": true}, "events": {"evaluate_on_completion": {"description": "\u5728\u4efb\u52a1\u7ed3\u675f\u65f6\u5224\u65ad\u5de5\u4f5c\u533a\u72b6\u6001\u662f\u5426\u7b26\u5408\u9884\u671f", "is_key_step": true, "key_step_index": 2, "key_step_name": "\u5728\u4efb\u52a1\u7ed3\u675f\u65f6\u5224\u65ad\u5f53\u524d\u9875\u9762\u7684\u72b6\u6001"}, "open_file": {"description": "\u6253\u5f00\u6587\u4ef6", "is_key_step": true, "key_step_index": 1, "key_step_name": "\u5728vscode\u4e2d\u6253\u5f00\u6587\u4ef6"}}, "mcp_servers": [{"command": "mcp-proxy", "args": ["http://127.0.0.1:6010/sse"]}], "context_data": [{"from": "tests/context_data/vscode/user_data", "to": "/root/vscode_user_data_dir"}, {"from": "tests/context_data/vscode/extensions", "to": "/root/.vscode/"}, {"from": "tests/context_data/vscode/C-Plus-Plus", "to": "/root/C-Plus-Plus"}]}

Hook script:
/**
 * Checks if a file is open and if all its code blocks are folded
 * @returns {Promise<{isFileOpen: boolean, fileName: string | null, areAllBlocksFolded: boolean}>}
 */
async function checkFileStatus() {
    let isFileOpen = false;
    let fileName = null;
    let areAllBlocksFolded = false;

    // Check if any file is currently open
    const activeEditor = vscode.window.activeTextEditor;
    if (activeEditor) {
        isFileOpen = true;
        fileName = activeEditor.document.fileName; // Get only the file name

        // Get folding ranges for the document
        const foldingRanges = await vscode.commands.executeCommand(
            'vscode.executeFoldingRangeProvider',
            activeEditor.document.uri
        );

        if (foldingRanges && foldingRanges.length > 0) {
            areAllBlocksFolded = true; // Assume all folded until proven otherwise

            for (const range of foldingRanges) {
                // Check if any line in the folding range (beyond start) is visible
                for (let line = range.start + 1; line <= range.end; line++) {
                    const isLineVisible = activeEditor.visibleRanges.some(visibleRange =>
                        line >= visibleRange.start.line && line <= visibleRange.end.line
                    );

                    // If any line in the folding range is visible, the range is not folded
                    if (isLineVisible) {
                        areAllBlocksFolded = false;
                        break;
                    }
                }

                if (!areAllBlocksFolded) {
                    break; // No need to check further ranges
                }
            }
        } else {
            // If no folding ranges exist, consider all blocks folded (vacuous truth)
            areAllBlocksFolded = true;
        }
    }

    return { isFileOpen, fileName, areAllBlocksFolded };
}

// vscode.window.showInformationMessage(`代码成功注入`);

// Listen for 'evaluate' event
socket.on('evaluate', async () => {
    const { isFileOpen, fileName, areAllBlocksFolded } = await checkFileStatus();
    let message1 = isFileOpen ? `${fileName}文件被成功打开` : `没有文件被打开`;
    let message2 = areAllBlocksFolded ? `所有的代码块都被成功折叠` : `代码块没有被成功折叠`;
    // vscode.window.showInformationMessage(message1);
    // vscode.window.showInformationMessage(message2);
    socket.emit("send", {
        'event_type': "evaluate_on_completion",
        'message': message1+`, `+message2,
        'isFileOpen': isFileOpen,
        'fileName': fileName,
        'areBlockFolded': areAllBlocksFolded
    });
});

// Register a listener for when a text document is opened
vscode.workspace.onDidOpenTextDocument(async (document) => {
    const filePath = document.uri.fsPath;
    socket.emit("send", {
        event_type: "open_file",
        message: "打开文件",
        path: filePath,
        scheme: document.uri.scheme
    });
});

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

from typing import Dict, Any, Optional, Callable, 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)
    expected_file_name = task_parameter.get("expected_file_path", "/root/C-Plus-Plus/search/binary_search.cpp")
    if event_type == "evaluate_on_completion":
        is_file_opend = message.get("isFileOpen")
        file_name = message.get("fileName")
        are_block_folded = message.get("areBlockFolded")
        if is_file_opend and file_name == expected_file_name and are_block_folded:
            return [
                {"status": "key_step", "index": 2},
                {"status": "success", "reason": f"文件成功打开并且代码块全部折叠"}
            ]
        else:
            return [{"status": "error", "type": "evaluate_on_completion", "message": "任务没有完成"}]
    elif event_type == "open_file":
        file_path = message.get("path")
        if message.get("scheme") == "git":
            file_path = file_path[:-4]
        if file_path == expected_file_name:
            return [{"status": "key_step", "index": 1}]
    return None