Task configuration:
{"task_id": "23", "task_name": "\u65b0\u5efa\u4e00\u4e2a\u7b80\u5355\u6a21\u677f", "description": "\u7b80\u5355\u6a21\u677f\uff0c\u542b\u67093\u4e2a\u5b57\u6bb5\u3002\u7b2c\u4e00\u4e2a\u5b57\u6bb5\u4e3a\u95ee\u9898\uff0c\u7b2c\u4e8c\u4e2a\u5b57\u6bb5\u4e3a\u7b80\u7565\u7b54\u6848\uff0c\u7b2c\u4e09\u4e2a\u5b57\u6bb5\u4e3a\u8be6\u7ec6\u7b54\u6848\u3002", "application_info": {"name": "anki", "executable_path": "/home/agent/anki/out/pyenv/bin/python", "args": ["/home/agent/anki/tools/run.py"], "cwd": "/home/agent/anki"}, "task_parameters": {"name": "simple"}, "instruction_template": "\u521b\u5efa\u4e00\u4e2a\u53eb${name}\u7684\u6a21\u677f\uff0c\u542b\u67093\u4e2a\u5b57\u6bb5\u3002\u7b2c\u4e00\u4e2a\u5b57\u6bb5\u4e3aquestion\uff0c\u7b2c\u4e8c\u4e2a\u5b57\u6bb5\u4e3a\"short answer\"\uff0c\u7b2c\u4e09\u4e2a\u5b57\u6bb5\u4e3a\"long answer\"\u3002\u7b2c\u4e8c\u4e2a\u548c\u7b2c\u4e09\u4e2a\u5b57\u6bb5\u90fd\u5728\u80cc\u9762\uff0c\u5e76\u4e14\u7528\u4e24\u4e2a<br>\u5206\u5272\u5f00\u3002\u7b2c\u4e8c\u4e2a\u5b57\u6bb5\u9700\u8981\u4f7f\u7528\u7ea2\u8272\u3002", "evaluation_setup": {"scripts": [{"role": "hook", "path": "hooker.js", "dependency": ["../common/hooker_common.js"]}, {"role": "handler", "path": "handler.py"}], "timeout": 60}, "events": {"add_notetype": {"description": "\u6dfb\u52a0\u6210\u529f", "is_key_step": true, "key_step_index": 1, "key_step_name": "\u6dfb\u52a0\u6210\u529f"}, "notetype_field_corret": {"description": "\u5b57\u6bb5\u540d\u79f0\u6b63\u786e", "is_key_step": true, "key_step_index": 2, "key_step_name": "\u5b57\u6bb5\u540d\u79f0\u6b63\u786e"}, "notetype_field_wrong": {"description": "\u5b57\u6bb5\u540d\u79f0\u9519\u8bef", "is_key_step": false}, "notetype_format_correct": {"description": "\u5b57\u6bb5\u683c\u5f0f\u6b63\u786e", "is_key_step": false}, "notetype_format_wrong": {"description": "\u5b57\u6bb5\u683c\u5f0f\u9519\u8bef", "is_key_step": false}}, "sql_path": "/home/agent/.local/share/Anki2/sam/collection.anki2", "total_key_steps": 2, "mcp_servers": [{"command": "/home/agent/anki-mcp-server/.venv/bin/python", "args": ["/home/agent/anki-mcp-server/run_server.py"]}]}

Hook script:
const TRACE_FUNCTION = [
    "storage_update_notetypes"
]
function initHooks() {
    // iterate function name and addr, init it.
    for (const function_name of TRACE_FUNCTION){
        initHook(function_name, TRACE_MAPS[function_name]);
    }
}
initHooks();
sendLog("info", "add hooks done");

Evaluation handler:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
sys.path.append(os.path.dirname(__file__))
from common import *
import re


def handle_storage_update_notetypes(context: Context,message) -> Status:
    status = Status()
    notetype : Notetype = None
    time.sleep(0.3)
    context.update_database()
    for i in AnkiObjMap().array_by_type("notetype"):
        if i.name == tp.name:
            notetype = i
            if not context.monitor.is_event_triggered(EventAddNotetype()):
                status.emit(EventAddNotetype())
            break
    if notetype is None:
        return None
    if len(notetype.fields) == 3 and notetype.fields[0] == "question" and notetype.fields[1] == "short_answer" and notetype.fields[2] == "long_answer":
        status.emit(EventNotetypeFieldCorret())
   
    pattern = r'\{\{FrontSide\}\}.+\<div.+color:red.+\>\{\{short_answer\}\}.+\{\{long_answer\}\}'
    if  len(notetype.templates) == 2:
        if re.findall(pattern,notetype.templates[1],re.DOTALL):
            status.emit(EventNotetypeFormatCorrect())

    return status


TRACE_HANDLERS = {
    "storage_update_notetypes" : handle_storage_update_notetypes
}   
dependency_graph = {
    add_notetype_ : [],
    notetype_field_corret_ : [add_notetype_],
    notetype_format_correct_ : [add_notetype_],
}
finished_list = [
    notetype_field_corret_,notetype_format_correct_
]

bind_handlers(TRACE_HANDLERS,dependency_graph,finished_list)