Task configuration:
{"task_id": "21", "task_name": "checkout_branch", "description": "\u5728vscode\u4e2d\u5207\u6362\u5f53\u524d\u5de5\u4f5c\u533a\u7684git\u5206\u652f", "application_info": {"name": "vscode", "executable_path": "/usr/share/code/code", "args": ["--no-sandbox", "--user-data-dir=/root/vscode_user_data_dir/"]}, "task_parameters": {"branch_name": "gh-pages", "commit_message": "temp commit for checkout", "origin_branch": "master"}, "instruction_template": "\u5728vscode\u5f53\u524d\u6253\u5f00\u7684\u5de5\u4f5c\u533a\u4e2d\u5207\u6362\u5f53\u524d\u5de5\u4f5c\u533a\u7684git\u5206\u652f\u4e3a ${branch_name}, \u5982\u679c\u5f53\u524d\u542b\u6709\u6ca1\u6709\u63d0\u4ea4\u7684\u4fee\u6539, \u5219\u5c06\u6240\u6709\u7684\u4fee\u6539\u63d0\u4ea4, \u63d0\u4ea4\u7684message\u586b\u5199 ${commit_message} (\u4f60\u9700\u8981\u786e\u5b9a\u5f53\u524dvscode\u6253\u5f00\u7684\u5de5\u4f5c\u76ee\u5f55\u8def\u5f84, \u8c03\u7528bash\u5e76\u4e0d\u4f1a\u5728\u5f53\u524dvscode\u7684\u5de5\u4f5c\u76ee\u5f55\u6267\u884c\u547d\u4ee4)", "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": {"vscode_running": true}, "events": {"evaluate_on_completion": {"description": "\u5728\u4efb\u52a1\u5b8c\u6210\u65f6\u68c0\u67e5git\u4fe1\u606f", "is_key_step": true, "key_step_index": 1, "key_step_name": "\u4efb\u52a1\u6210\u529f\u5b8c\u6210"}}, "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:
/**
 * Gets the current Git branch name using the VS Code Git extension API.
 * @param {string} workspacePath - The workspace directory path.
 * @returns {Promise<string | null>} The current branch name, or null if not available.
 */
async function getGitBranch(workspacePath) {
    try {
        // 获取当前工作区文件夹
        const workspaceFolders = vscode.workspace.workspaceFolders;
        if (!workspaceFolders || workspaceFolders.length === 0) {
            return { hasChanges: false, lastCommitMessage: null };
        }

        // 获取第一个工作区文件夹路径
        const workspacePath = workspaceFolders[0].uri.fsPath;

        // 使用VS Code内置的Git扩展API
        const gitExtension = vscode.extensions.getExtension('vscode.git')?.exports;
        if (!gitExtension) {
            return { hasChanges: false, lastCommitMessage: null };
        }

        const api = gitExtension.getAPI(1);
        const repository = api.getRepository(vscode.Uri.file(workspacePath));

        // Get the current branch from HEAD
        const branch = repository.state.HEAD?.name;
        if (!branch) {
            throw new Error('No active branch found (possibly in detached HEAD state).');
        }

        return branch;
    } catch (error) {
        socket.emit("send", {
            'event_type': "error",
            'message': `任务评估时获取仓库分支名称报错: ${error.message}`
        });
        console.error(`Error getting Git branch for ${workspacePath}: ${error.message}`);
        throw new Error(`Failed to get Git branch: ${error.message}`);
    }
}

try {
    // 获取当前工作区文件夹
    const workspaceFolders = vscode.workspace.workspaceFolders;
    if (!workspaceFolders || workspaceFolders.length === 0) {
        socket.emit("send", {
            'event_type': "error",
            'message': `没有打开工作区`
        });
    }
    
    // 获取第一个工作区文件夹路径
    const workspacePath = workspaceFolders[0].uri.fsPath;
    
    // 使用VS Code内置的Git扩展API
    const gitExtension = vscode.extensions.getExtension('vscode.git')?.exports;
    if (!gitExtension) {
        socket.emit("send", {
            'event_type': "error",
            'message': `无法获取vscode git扩展的API`
        });
    }
    
    const api = gitExtension.getAPI(1);
    const repository = api.getRepository(vscode.Uri.file(workspacePath));
    
    if (!repository) {
        socket.emit("send", {
            'event_type': "error",
            'message': `当前工作区不是git仓库`
        });
    }
    
    // 监听仓库变化
    const disposable = repository.state.onDidChange(async () => {
        // 检查是否有未提交的修改
        const hasChanges = repository.state.workingTreeChanges.length > 0 || 
                            repository.state.indexChanges.length > 0;
        // 获取最近的commit message
        let lastCommitMessage = null;
        const log = await repository.log({ maxEntries: 1 });
        if (log.length > 0) {
            lastCommitMessage = log[0].message;
        }
        const branchname = await getGitBranch();
        socket.emit("send", {
            'event_type': "repo_changed",
            'message': `检测到仓库出现了修改`,
            'haschanges': hasChanges,
            'lastcommit': lastCommitMessage,
            'branchname': branchname
        });
    });
} catch (error) {
    socket.emit("send", {
        'event_type': "error",
        'message': `在查看git仓库时出现了错误: ${error.message}`
    });
}

socket.on('evaluate', async () => {
    const branchname = await getGitBranch();
    // vscode.window.showInformationMessage(message);
    socket.emit("send", {
        'event_type': "evaluate_on_completion",
        'message': "任务结束时检查任务是否完成",
        'branchname': branchname
    });
});

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

from typing import Dict, Any, Optional, List

LAST_COMMIT = None
HAS_CHANGES = None

def message_handler(message: Dict[str, Any], logger, task_parameter: Dict[str, Any]) -> Optional[List[Dict[str, Any]]]:    
    global HAS_CHANGES, LAST_COMMIT
    event_type = message.get('event_type')
    # _EVALUATOR.logger.info(message)
    logger.info(message)
    expect_branchname = task_parameter.get("branch_name", "gh-pages")
    expect_commitmessage = task_parameter.get("commit_message", "temp commit for checkout")
    expect_origin_branch = task_parameter.get("origin_branch", "master")
    if event_type == 'repo_changed':
        has_changes = message.get('haschanges')
        lastcommit = message.get('lastcommit')
        branchname = message.get('branchname')
        if branchname == expect_origin_branch:
            LAST_COMMIT = lastcommit
            HAS_CHANGES = has_changes
    elif event_type == 'evaluate_on_completion':
        if expect_branchname == message.get('branchname', None) and not HAS_CHANGES and LAST_COMMIT == expect_commitmessage:
            return [
                {"status": "key_step", "index": 1},
                {"status": "success", "reason": f"任务成功完成"}
            ]
        else:
            return [{"status": "error", "type": "evaluate_on_completion", "message": "任务没有完成"}]
    return None