Task configuration:
{"task_id": "23", "task_name": "fix_error", "description": "\u5728vscode\u4e2d\u6253\u5f00\u6587\u4ef6, \u5e76\u4e14\u4fee\u590d\u6240\u6709\u7684\u62a5\u9519", "application_info": {"name": "vscode", "executable_path": "/usr/share/code/code", "args": ["--no-sandbox", "--user-data-dir=/root/vscode_user_data_dir/"]}, "task_parameters": {"filename": "fix_error.cpp", "expected_file_content": "#include<cmath>#include<complex>#include<iostream>#include<stdexcept>#include<vector>constdoublePI=3.14159265358979323846;classFftCalculator{private:voidbutterflyTransform(std::vector<std::complex<double>>&inputData,boolisInverse){size_tdataSize=inputData.size();if(dataSize<=1)return;if((dataSize&(dataSize-1))!=0){throwstd::invalid_argument(\"Inputsizemustbepowerof2\");}for(size_ti=0,j=0;i<dataSize;++i){if(j>i){std::swap(inputData[i],inputData[j]);}size_tm=dataSize;while(j&(m>>=1)){j&=~m;}j|=m;}for(size_tstage=1;stage<dataSize;stage<<=1){size_thalfSize=stage;size_tstepSize=stage<<1;doubleangleFactor=(isInverse?PI:-PI)/halfSize;for(size_ti=0;i<dataSize;i+=stepSize){for(size_tj=0;j<halfSize;++j){autotwiddleFactor=std::polar(1.0,angleFactor*j);autotemp=inputData[i+j+halfSize]*twiddleFactor;inputData[i+j+halfSize]=inputData[i+j]-temp;inputData[i+j]+=temp;}}}if(isInverse){for(auto&value:inputData){value/=dataSize;}}}public:std::vector<std::complex<double>>computeFft(conststd::vector<double>&inputSignal){size_tsignalSize=inputSignal.size();std::vector<std::complex<double>>complexInput(signalSize);for(size_ti=0;i<signalSize;++i){complexInput[i]=std::complex<double>(inputSignal[i],0.0);}butterflyTransform(complexInput,false);returncomplexInput;}std::vector<std::complex<double>>computeInverseFft(conststd::vector<std::complex<double>>&inputSpectrum){std::vector<std::complex<double>>result=inputSpectrum;butterflyTransform(result,true);returnresult;}};intmain(){try{FftCalculatorfftCalc;std::vector<double>testSignal={1.0,2.0,3.0,4.0,0.0,0.0,0.0,0.0};autofftResult=fftCalc.computeFft(testSignal);autoinverseResult=fftCalc.computeInverseFft(fftResult);for(size_ti=0;i<fftResult.size();++i){std::cout<<\"FFT[\"<<i<<\"]=\"<<fftResult[i]<<\",Inverse[\"<<i<<\"]=\"<<inverseResult[i]<<std::endl;}std::cout<<\"thelengthoftestSignalis\"<<std::endl;std::cout<<testSignal.size()<<std::endl;}catch(conststd::exception&e){std::cerr<<\"Error:\"<<e.what()<<std::endl;return1;}return0;}", "expected_file_path": "/root/C-Plus-Plus/agent_test/fix_error.cpp"}, "instruction_template": "\u5728vscode\u4e2d\u6253\u5f00\u540d\u4e3a ${filename} \u7684\u6587\u4ef6, \u5e76\u4e14\u7406\u89e3\u6587\u4ef6\u5185\u5bb9, \u4fee\u590d\u6240\u6709\u7684\u62a5\u9519, \u5305\u62ec\u51fd\u6570\u540d\u79f0\u9519\u8bef\u3001\u62fc\u5199\u9519\u8bef\u3001\u547d\u540d\u7a7a\u95f4\u9519\u8bef\u7b49\u7b49, \u4fee\u6539\u76f4\u5230\u6ca1\u6709\u4efb\u4f55vscode\u62a5\u9519\u63d0\u793a", "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\u67e5\u4efb\u52a1\u662f\u5426\u5b8c\u6210", "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:
/**
 * 检查当前打开的文件是否含有错误提示，并返回文件名和文件内容（包括未保存的修改）
 * @returns {Promise<{hasErrors: boolean, fileName: string | null, content: string | null}>} 返回对象包含错误状态、文件名和文件内容
 */
async function hasFileErrors() {
    // 获取当前活动编辑器
    const editor = vscode.window.activeTextEditor;
    if (!editor) {
        vscode.window.showInformationMessage('No active editor found.');
        return { hasErrors: false, fileName: null, content: null };
    }

    // 获取当前文件的 URI、文件名和内容
    const fileUri = editor.document.uri;
    const fileName = editor.document.fileName;
    const content = editor.document.getText(); // 获取当前文档内容，包括未保存的修改

    // 获取文件的诊断信息
    const diagnostics = vscode.languages.getDiagnostics(fileUri);

    // 检查是否有错误
    const hasErrors = diagnostics.some(diagnostic => 
        diagnostic.severity === vscode.DiagnosticSeverity.Error
    );

    return { hasErrors, fileName, content };
}

socket.on('evaluate', async () => {
    const hasErrors = await hasFileErrors();
    // vscode.window.showInformationMessage(message);
    socket.emit("send", {
        'event_type': "evaluate_on_completion",
        'message': "任务结束时检查打开的文件是否含有报错",
        'hasErrors': hasErrors
    });
});

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

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')
    info = message.get('hasErrors', {})
    fileName = info.get('fileName', None)
    hasErrors = info.get('hasErrors', None)
    content = info.get('content', None)
    expected_file_content = task_parameter.get("expected_file_content", "#include<cmath>#include<complex>#include<iostream>#include<stdexcept>#include<vector>constdoublePI=3.14159265358979323846;classFftCalculator{private:voidbutterflyTransform(std::vector<std::complex<double>>&inputData,boolisInverse){size_tdataSize=inputData.size();if(dataSize<=1)return;if((dataSize&(dataSize-1))!=0){throwstd::invalid_argument(\"Inputsizemustbepowerof2\");}for(size_ti=0,j=0;i<dataSize;++i){if(j>i){std::swap(inputData[i],inputData[j]);}size_tm=dataSize;while(j&(m>>=1)){j&=~m;}j|=m;}for(size_tstage=1;stage<dataSize;stage<<=1){size_thalfSize=stage;size_tstepSize=stage<<1;doubleangleFactor=(isInverse?PI:-PI)/halfSize;for(size_ti=0;i<dataSize;i+=stepSize){for(size_tj=0;j<halfSize;++j){autotwiddleFactor=std::polar(1.0,angleFactor*j);autotemp=inputData[i+j+halfSize]*twiddleFactor;inputData[i+j+halfSize]=inputData[i+j]-temp;inputData[i+j]+=temp;}}}if(isInverse){for(auto&value:inputData){value/=dataSize;}}}public:std::vector<std::complex<double>>computeFft(conststd::vector<double>&inputSignal){size_tsignalSize=inputSignal.size();std::vector<std::complex<double>>complexInput(signalSize);for(size_ti=0;i<signalSize;++i){complexInput[i]=std::complex<double>(inputSignal[i],0.0);}butterflyTransform(complexInput,false);returncomplexInput;}std::vector<std::complex<double>>computeInverseFft(conststd::vector<std::complex<double>>&inputSpectrum){std::vector<std::complex<double>>result=inputSpectrum;butterflyTransform(result,true);returnresult;}};intmain(){try{FftCalculatorfftCalc;std::vector<double>testSignal={1.0,2.0,3.0,4.0,0.0,0.0,0.0,0.0};autofftResult=fftCalc.computeFft(testSignal);autoinverseResult=fftCalc.computeInverseFft(fftResult);for(size_ti=0;i<fftResult.size();++i){std::cout<<\"FFT[\"<<i<<\"]=\"<<fftResult[i]<<\",Inverse[\"<<i<<\"]=\"<<inverseResult[i]<<std::endl;}std::cout<<\"thelengthoftestSignalis\"<<std::endl;std::cout<<testSignal.size()<<std::endl;}catch(conststd::exception&e){std::cerr<<\"Error:\"<<e.what()<<std::endl;return1;}return0;}")
    expected_file_path = task_parameter.get("expected_file_path", "/root/C-Plus-Plus/agent_test/fix_error.cpp")
    logger.info(message)
    if event_type == 'evaluate_on_completion' and fileName == expected_file_path and hasErrors == False:
        if ''.join(content.split()) == expected_file_content:
            return [
                {"status": "key_step", "index": 1},
                {"status": "success", "reason": f"任务成功完成"}
            ]
        else:
            return [{"status": "error", "type": "evaluate_on_completion", "message": "任务没有完成"}]
    return None