Skip to content

[Bug] PipelineDumper 输出 sub_recognition 字段嵌套层级错误,parser 无法重新加载 dumper 自己的输出 #1314

@sunyink

Description

@sunyink

问题类型 / Issue Type

一般 Bug / General Bug

问题描述及复现步骤 / Problem Description & Reproduction Steps

1. 问题描述及复现步骤

预期行为

PipelineParserPipelineDumper 应当形成 round-trip 闭合:dumper 输出的 JSON 重新喂给 parser 应当能成功加载。

实际行为

对于含 recognition: "And"recognition: "Or" 的 task,dumper 输出的 sub_recognition 节点形态如下(错误):

{
    "recognition": {
        "type": "And",
        "param": {
            "all_of": [
                {
                    "sub_name": "Main_OCR",
                    "type": "OCR",                    ← 错位: 应在 recognition 子对象里
                    "param": { "expected": ["X"] }    ← 错位: 同上
                }
            ]
        }
    }
}

但 parser 期望的形态是:

{
    "recognition": {
        "type": "And",
        "param": {
            "all_of": [
                {
                    "sub_name": "Main_OCR",
                    "recognition": {                  ← 正确: 嵌套在 recognition 里
                        "type": "OCR",
                        "param": { "expected": ["X"] }
                    }
                }
            ]
        }
    }
}

把 dumper 的输出直接重新加载,parser 报错:

[ERR] failed to parse sub recognition in 'all_of'

复现步骤

  1. 准备一个含 recognition: "And"recognition: "Or" 的 pipeline JSON,sub 用 V2 嵌套写法
  2. Resource.post_pipeline() 加载(成功)
  3. Resource.get_node_data(name) 拿 dump 输出
  4. 把 dump 输出写到新文件,再 Resource.post_pipeline() 加载新文件
  5. 第二次加载失败

最小复现脚本

from maa.resource import Resource
import json, tempfile, pathlib

with tempfile.TemporaryDirectory() as tmp:
    p = pathlib.Path(tmp) / "test.json"
    p.write_text(json.dumps({
        "TaskAnd": {
            "recognition": {
                "type": "And",
                "param": {
                    "all_of": [{
                        "sub_name": "OCR1",
                        "recognition": {
                            "type": "OCR",
                            "param": {"expected": ["test"]}
                        }
                    }]
                }
            }
        }
    }), encoding="utf-8")
    
    res = Resource()
    res.post_pipeline(str(tmp)).wait()
    assert res.loaded, "first load should succeed"
    
    dumped = res.get_node_data("TaskAnd")
    print("Dump output:", json.dumps(dumped, indent=2))
    
    p.unlink()
    p2 = pathlib.Path(tmp) / "redumped.json"
    p2.write_text(json.dumps({"TaskAnd": dumped}), encoding="utf-8")
    
    res2 = Resource()
    res2.post_pipeline(str(tmp)).wait()
    print("Second load:", "succeeded" if res2.loaded else "FAILED")

2. 关于复现的其他信息

  • MaaFramework 版本: 5.10.0b2
  • Python 包: maafw 5.10.0b2 (PyPI)
  • 环境: Windows 10, Python 3.11
  • 影响范围: 我的测试样本 1364 task 中 116 task 受影响(约 8.5%,凡用 And/Or 的 task)
  • 相关源码位置:
    • parser 期望嵌套形态: PipelineParser.cppparse_sub_recognition 函数
    • dumper 输出位置: PipelineDumper.cpp 处理 sub_recognition 部分
  • 临时解决方案: dumper 输出后做字段重排(把 type/param 包装回 recognition 子对象)

背景

我在做一个第三方工具 MaaOWM (MaaFramework Overlay Workspace Manager),依赖 PipelineParser/Dumper 的 round-trip 闭合性。集成时发现这个问题。

MaaFramework 版本 / Version

maafw 5.10.0b2 (PyPI)

日志文件 / Log Files

Null

Pipeline JSON

崩溃 Dump 文件 / Crash Dump (仅崩溃问题 / Crash only)

No response

Draw 调试图片 / Draw Debug Images (仅识别问题 / Recognition only)

No response

模板图片 / Template Images (仅识别问题 / Recognition only)

No response

其他信息 / Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions