本文へ移動
cccskills
無料GitHub で公開

pipeline-option

Add runtime UI options (select/checkbox/switch/input) to MaaFramework option surfaces such as `assets/interface.json` or `assets/resource/tasks/**/*.json`. Use when adding a user-facing toggle, selector, checkbox, or input; wiring options to `pipeline_override`; aligning option paths with Python `context.get_node_data()` or CustomAction params; or reviewing option behavior across Pipeline JSON and Python.

インストール方法を見る

含まれるファイル(5)

  • SKILL.md27.5 KB
  • evals/evals.json1.3 KB
  • maahub_meta.json589 B
  • README.md436 B
  • references/protocol.md8.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Pipeline Option 工作流

TL;DR:先识别 option surface

新增一个 UI 选项需要先识别本项目使用的 option surface。MaaGumballs 主要是 assets/interface.json,M9A 同时使用 assets/interface.json 与 assets/resource/tasks/**/*.json。不要假设所有 Maa 项目只有一种入口。

常见联动点如下,按项目实际协议取用,缺关键点会导致 UI 看不到选项或运行时读不到值:

#位置内容
1option 定义处assets/interface.json 的 option 字典,或 assets/resource/tasks/**/*.json 里的 task option 定义
2task 注册处interface.json task 的 option: [],或 tasks JSON 的任务/预设引用
3assets/resource/base/pipeline/*.json预定义目标节点(pipeline_override 不会创建节点)
4Python 代码(仅 Python 需要读取或执行 Custom 时必需)context.get_node_data()、argv.custom_action_param、argv.custom_recognition_param 与 option 路径保持一致

⚠️ pipeline_override 只做属性合并,不会凭空创建节点。 少了第 3 步,context.get_node_data() 会返回 None,运行时静默失败。

完整协议参考(嵌套 option、global_option、controller/resource 限制、占位符注入):references/protocol.md

历史校正

  • 不要把 pure override 当成唯一最佳解:只改已有节点字段时 pure override 最小;但涉及运行时事件库、计数、动态目标、识别后处理、失败策略、跨节点状态时,CustomAction/CustomRecognition 更合适。
  • 不要把 Flag 节点当成唯一配置入口:M9A 的 v5 object-form 里,参数经常通过 action.param.custom_action_param、custom_action_param_code、recognition.param.custom_recognition_param 进入 Custom;这和 context.get_node_data("Flag") 是不同通道。
  • 字段路径必须闭环:UI 写哪条路径,Python 就读哪条路径;pure override 则 Python 不读,直接观察运行时行为。
  • enabled/enable 不是审美选择:MaaFramework 原生启停用 enabled;历史项目若已有 enable helper,可沿用并兼容,否则优先 enabled。

4 种 type 速查

type选择override 字段节点预定义形态
select单选互斥expectedrecognition: "OCR" + expected: [...]
switch二元 Yes/Noenabled(或项目已有的 enable){"enabled": bool} / {"enable": bool}
input自由文本{name} 占位符可注入目标字段按最终读取方预定义 expected 或 action.param.custom_action_param
checkbox多选enabled{"enabled": false}

选哪个模式?

你的需求推荐模式
启用/禁用一个 Python 业务函数A(switch + Flag 节点 + Python 读 flag)
从多个互斥选项里选一个值B(select + OCR 节点)
同时启用多个独立的功能模块C(checkbox + 多个 Flag 节点)
用户输入自定义文本D(input + 占位符注入)
切换行为(点哪个按钮 / 走哪条 next 链)但不想改 PythonE(pure override 现有节点字段)

经验法则:行为只等于“覆盖已有节点字段”时优先 pure override;一旦需要运行时数据、计数、动态识别、失败策略或跨节点状态,改用 Flag + Python / CustomAction / CustomRecognition。目标是让改动面和逻辑复杂度匹配。

先确认代码读取路径

加选项前先 rg "get_node_data|_node_enabled|Flag_" agent assets,确认这次配置到底由谁读取。

常见对应关系:

UI override 写什么Python 应该读什么备注
{ "Flag_X": { "enabled": true } }node.get("enabled")MaaFramework 标准启停字段
{ "Flag_X": { "enable": true } }node.get("enable") 或兼容 helper仅用于已有项目约定/历史字段
{ "SomeOCR": { "expected": ["A"] } }node["recognition"]["param"]["expected"][0]节点必须预定义为 OCR
{ "SomeNode": { "next": ["A"] } }不读,直接由 pipeline 行为生效pure override 模式

不要字段错位:例如 UI 写 AutoSky_CloneConfig.enable,Python 却调用读取 expected 的函数;或 UI 写 expected,Python 只看 enabled。这种错误不会报 JSON 语法错,但运行时会表现为"选项没生效"。

启停节点必须短路调用

如果同一个节点既保存 enable/enabled 开关,又是可执行的 Recognition/Action 节点,先读取开关,只有开启时才调用它。关闭节点后继续检查同级候选分支,不能调用已关闭节点,也不能因为开关值直接 continue 整个事件扫描。

if _node_enabled(context, "OptionalNode"):
    result = context.run_recognition("OptionalNode", image)
    if result and result.hit:
        context.run_task("OptionalNode")
        continue

# OptionalNode 关闭或未命中,继续识别 CombatNode、ExploreNode 等同级分支。

模式 A:开关(switch + Flag 节点)— 最常用

适用:开启/关闭某个功能。

interface.json

"开启5月城堡相亲": {
    "type": "switch",
    "description": "是否开启5月自动相亲",
    "default_case": "Yes",
    "cases": [
        {
            "name": "Yes",
            "pipeline_override": { "Flag_EnableMarryTask": { "enabled": true } }
        },
        {
            "name": "No",
            "pipeline_override": { "Flag_EnableMarryTask": { "enabled": false } }
        }
    ]
}

配套 pipeline 节点(必须预定义!)

"Flag_EnableMarryTask": { "enabled": true }

若项目历史节点使用 enable 而非 enabled,必须同时保证 Python 侧有兼容读取,例如 node.get("enable", node.get("enabled", True))。否则优先使用协议字段 enabled。

注册到 task

"task": [{
    "name": "推年计划",
    "entry": "Auto_YearlyTask",
    "option": ["开启5月城堡相亲", /* 其他选项 */]
}]

Python 读取(建议放在业务函数入口)

def handle_marry_festival(context: Context) -> bool:
    """处理春林节相亲(5月)"""
    EnableMarryTask = context.get_node_data("Flag_EnableMarryTask").get("enabled")
    if not EnableMarryTask:
        logger.info("自动相亲已关闭,跳过")
        return True
    # ... 正常逻辑

模式 B:单选(select + OCR 节点)

适用:选择城市、关卡、模式等互斥选项。

interface.json

"选择刷取任务国家": {
    "type": "select",
    "description": "选择要刷取任务的目标城市",
    "default_case": "雄月城",
    "cases": [
        { "name": "王座堡", "pipeline_override": { "EnterCity": { "expected": ["王座堡"] } } },
        { "name": "雄月城", "pipeline_override": { "EnterCity": { "expected": ["雄月城"] } } }
    ]
}

配套 OCR 节点

"EnterCity": {
    "recognition": "OCR",          // ⚠️ 必须是 OCR,否则 expected 不生效
    "expected": ["王座堡", "圣盾堡", "雄月城", "翠庭"],
    "roi": [58, 320, 600, 682],
    "action": "Click"
}

Python 读取

data = context.get_node_data("EnterCity")
city = data.get("recognition", {}).get("param", {}).get("expected", ["王座堡"])[0]

模式 C:多选(checkbox + 多个 Flag 节点)

适用:多条件检测(好苗子条件)、可叠加的功能模块。

interface.json

"开启好娃提醒": {
    "type": "checkbox",
    "default_case": ["科内塔之怒"],
    "cases": [
        { "name": "科内塔之怒",   "pipeline_override": { "检测_科内塔之怒":     { "enabled": true } } },
        { "name": "太阳+科内塔之怒", "pipeline_override": { "检测_太阳+科内塔之怒": { "enabled": true } } }
    ]
}

配套节点(每个 case 一个,默认全 false)

"检测_科内塔之怒":      { "expected": ["koneita"],            "enabled": false },
"检测_太阳+科内塔之怒": { "expected": ["sun_and_koneita"],    "enabled": false }

Python 读取(遍历收集)

def _get_enabled_checks(context) -> list:
    enabled = []
    for key in ["检测_科内塔之怒", "检测_太阳+科内塔之怒"]:
        node = context.get_node_data(key)
        if node and node.get("enabled", False):
            expected = node.get("recognition", {}).get("param", {}).get("expected", [])
            if expected:
                enabled.append(expected[0])
    return enabled

模式 D:自由输入(input + 占位符注入)

适用:用户输入自定义关卡号、自定义黑名单任务等。input 只是 UI surface;占位符可以注入 expected 或 action.param.custom_action_param,最终路径由消费方决定。

interface.json

"自定义任务黑名单": {
    "type": "input",
    "inputs": [
        {
            "name": "任务名称",
            "pipeline_type": "string",
            "default": "",
            "verify": "^[^,,]*$",
            "pattern_msg": "不能包含逗号"
        }
    ],
    "pipeline_override": {
        "CustomTaskBlacklist": {
            "expected": ["{任务名称}"]   // {名称} 占位符被实际输入替换
        }
    }
}

Python 读取

data = context.get_node_data("CustomTaskBlacklist")
value = data.get("recognition", {}).get("param", {}).get("expected", [""])[0]

⚠️ 常见错误:混淆 get_node_data() 和 CustomAction 参数通道

custom_action_param 可以用,但要读对地方:

  • 如果参数是给当前 CustomAction 执行时使用,写入 action.param.custom_action_param,在 Python 里读 argv.custom_action_param。
  • 如果参数是给普通业务代码提前读取,写到一个预定义节点的 recognition.param.expected、enabled、enable 或其他明确字段,再用 context.get_node_data("Node") 读取对应路径。
  • 不要把用户输入塞到 pipeline_override.custom_action_param 后,再用 get_node_data("X").get("custom_action_param") 读顶层字段;这两个不是同一条通道。

错误信号:UI 显示已选择,但 Python 读到默认值或 None。排查时打印完整 context.get_node_data("X"),确认字段实际落点。


模式 E:行为覆盖(pure override 现有节点字段)— 最简

适用:行为切换映射到现有 pipeline 节点的单个字段(next 数组 / action 类型 / recognition 算法 / 任何可覆盖字段),且不需要 Python 判断。

核心思路:用户切换 UI 选项 → 改变 pipeline 节点的字段值 → 框架自身根据新值执行。Python 代码完全不动。

典型场景:开关决定点哪个按钮

"开启自动接受佣兵": {
    "type": "switch",
    "default_case": "No",
    "cases": [
        {
            "name": "Yes",
            "description": "直接点确认",
            "pipeline_override": {
                "Event_MercenaryJoin": {
                    "next": ["Event_MercenaryJoinConfirm"]
                }
            }
        },
        {
            "name": "No",
            "description": "直接点取消",
            "pipeline_override": {
                "Event_MercenaryJoin": {
                    "next": ["Event_MercenaryJoinCancel"]
                }
            }
        }
    ]
}

Event_MercenaryJoin 节点本身在 event_utils.json 里有完整定义(recognition / expected / roi / timeout 都在),pipeline_override 只覆盖 next 字段,其他字段保持原值。

next 数组的单元素 vs 多元素语义

写法语义何时用
["A"]强约束:只走 A行为已确定,单路径足够(模式 E 的典型形态)
["A", "B"]回退链:优先 A,A 失败走 B兜底机制("优先点确认,找不到才点取消")
["A", "B", "[JumpBack]C"]失败后跳回 C 节点重试复杂回退

可被 override 的字段

字段override 效果典型用途
next改变后续节点列表切换行为路径(模式 E 主力)
action改变点击/滑动/输入动作切换操作类型
recognition改变识别算法切换识别方式(OCR ↔ Template)
expected改变识别期望值配合 select 选值
roi改变识别区域适配不同界面尺寸
timeout改变超时时间适配不同网络/性能

关键认识:上面这些字段都是普通 JSON 值,pipeline_override 一视同仁做深合并。模式 A 用的 enabled 字段只是最常见的入口,不是唯一可 override 的字段。

模式 A vs 模式 E 对比

场景模式 A(Flag + Python)模式 E(pure override)
行为由 Python if 控制✅ 必须❌ 绕远路
行为由 pipeline 字段决定❌ 多此一举✅ 最简
需要运行时根据 flag 走不同代码分支✅ 唯一选择❌ 不行
改动 Python 代码✅ 需要❌ 不需要
需要新加 Flag 节点✅ 需要❌ 不需要

实战决策流程

要加新选项
│
├─ 行为切换对应到一个 pipeline 节点的某个字段?
│   └─ ✅ 用模式 E(pure override)
│       示例:佣兵加入时点"确认"还是"取消"
│
└─ ❌ 行为在 Python 业务逻辑里
    └─ 用模式 A(Flag 节点 + Python 读 flag)
        示例:跳过整个 handle_sailing_festival 函数

补充:能用状态机就别写 Python orchestration

MaaFramework 的 next + [JumpBack] 是为跨页面状态推进设计的原语。如果一个流程的步骤可以列举为有限个页面状态(入口 → A → B → C → 战斗),优先用 JSON 状态机;不要写 Python 把 context.run_task 串起来。

详见 .claude/skills/pipeline-guide/SKILL.md 的「跨页面状态机」典型模式。

状态机 vs Python orchestration 对比

场景状态机(推荐)Python orchestration(次选)
有限页面状态推进(如活动流程)✅ 链 next + [JumpBack]❌ 自己写 for/while 调度
按 flag 跳过整段函数❌ 不适合✅ 读 flag + 早返回
复杂的运行时分支逻辑❌ 难表达✅ Python 灵活

跨文件节点引用的测试陷阱

MaaFramework 全局加载时,所有 assets/resource/base/pipeline/*.json 会合并到同一命名空间,所以 [JumpBack]OtherFileNode 能解析。但 run_pipeline 测试工具只加载单文件,跨文件引用会报"加载 Pipeline 失败"。

应对:

  • 集成测试必须用 MaaFramework GUI / CLI 触发,不能依赖 run_pipeline
  • 单元测试每个节点用 run_pipeline 是 OK 的(无跨文件依赖)
  • 若某个流程有跨文件引用,本地调试时考虑用 MaaCli 跑全 bundle

补充:状态机驱动的「流程型选项」

如果一个 UI 选项代表的是进入某个跨页面流程(如"开启成长试炼"→ 大地图 → 难度选择 → 队伍 → 战斗),把选项的 pipeline_override 用于:

  1. 切换"是否启用流程"的 Flag 节点
  2. 注入该流程入口节点所需参数(如难度 expected)

而不要用 Python orchestration 串联流程中的每个节点。完整流程示例:

// 选项定义
"开启3月成长试炼": {
    "type": "switch",
    "default_case": "No",
    "cases": [
        {
            "name": "Yes",
            "pipeline_override": {
                "Flag_GrowthTrialMode": { "enabled": true },
                "GrowthTrial_Difficulty_Select": { "expected": ["噩梦"] }
            }
        },
        {
            "name": "No",
            "pipeline_override": {
                "Flag_GrowthTrialMode": { "enabled": false }
            }
        }
    ]
}
// 入口节点(路由)
"GrowthTrial_Start": {
    "next": [
        "GrowthTrial_TeamReady",                  // 已在队伍配置页
        "[JumpBack]GrowthTrial_Difficulty_Select", // 在难度选择页
        "[JumpBack]GrowthTrial_Enter"             // 在大地图
    ]
}

战斗入口自动接力:

"GrowthTrial_EnterBattle": {
    "action": "Click",
    "next": [
        "GrowthTrial_FightStart",                   // 战斗开始
        "[JumpBack]GrowthTrial_TravelSelect_Boat",  // 弹出旅行框
        "[JumpBack]GrowthTrial_TravelSelect_Walk"   // fallback
    ]
}

命名与默认值

命名约定

角色风格示例
option 名(用户可见)中文动词起头开启5月城堡相亲、选择刷取任务国家
节点名(pipeline)英文Flag_EnableMarryTask、EnterCity、检测_科内塔之怒
switch case 名严格 Yes / No不要用 true/false 或 是/否(Client 解析跨平台不一致)

默认值策略

保持现有行为是底线。 老用户不该因新选项而行为改变。

场景推荐 default
新开关让功能默认关闭No(明确告知用户"关了")
新开关让功能默认开启Yes(保留旧行为)
旧代码无条件开启Yes(兼容)
旧代码无条件关闭No(兼容)

读取位置

决策类型放哪读理由
是否执行某段流程业务函数入口 handle_xxx与现有同名函数风格一致,子函数自治
用哪个值做主逻辑任务入口 run 或 YearlyTaskProcessor一次读取、多次复用

反例:不要把"是否开启 X"的判断堆在通用 dispatch 函数(如 handle_festival_by_month)里。每加一个开关 dispatch 就多一个 if-elif,越来越臃肿。


✅ 推荐做法

  1. 先复用现有模式:参考同项目里现成的同类选项(开关 → 开启5月城堡相亲;选择 → 选择刷取任务国家)
  2. 3 处同步改完再跑:不要中途停下来"先编译试试"
  3. JSON 改完跑资源加载检查:本仓库与 M9A 的真实路径是 python tools/ci/check_resource.py assets/resource/base;如果目标项目路径不同,先用 Get-ChildItem tools -Recurse -Filter check_resource.py 发现真实脚本。pipeline 加载错误(如重复 key)会立刻报
  4. 默认值遵循现状:选项是"开"还是"关"取决于旧代码行为,不是你的偏好
  5. 在 task 的 doc 数组里加一行说明:用户能看懂每个选项的作用
  6. 让 option 通道匹配实际复杂度:行为只动已有 pipeline 字段时用 pure override;Python 需要做真实判断、计数、动态识别或安全策略时,用 Flag + Python / CustomAction / CustomRecognition,不要为了少写 Python 把复杂逻辑硬塞进 JSON。

❌ 不要做

1. 不要只通过 pipeline_override 定义节点

// ❌ 错:节点没在 pipeline JSON 中预定义 → 不会被加载 → get_node_data() 返回 None

// ✅ 对:在 pipeline JSON 里预定义
"Flag_EnableSailingFestivalPurchase": { "enabled": true }

验证方法:加完后跑 python tools/ci/check_resource.py assets/resource/base(或目标项目真实资源检查命令),并在 Python 里加个 None 兜底日志。

2. 不要忘了注册到 task 的 option 数组

// ❌ 错:option 定义了但 task 不引用 → UI 上看不到
"option": []

// ✅ 对:同步注册
"option": ["开启3月启航节购买"]

3. 不要把判断塞到 dispatch 函数

# ❌ 错:dispatch 越来越臃肿
def handle_festival_by_month(month):
    if month == 3 and not context.get_node_data("Flag_X").get("enabled"):
        return True
    if month == 3:
        return handle_sailing_festival(context)
    # ... 每加一个开关都得多一个 if

# ✅ 对:业务函数自治
def handle_sailing_festival(context):
    if not context.get_node_data("Flag_X").get("enabled"):
        return True
    # ... 正常逻辑

4. 不要混淆字段路径

用途字段路径备注
selectdata["recognition"]["param"]["expected"][0]节点必须 recognition: "OCR"
input 注入 CustomActiondata["action"]["param"]["custom_action_param"][key] 或执行时的 argv.custom_action_param取决于参数消费位置
input 注入普通节点字段读取被占位符覆盖的真实路径,如 recognition.param.expectedinput 不限定注入目标
switch / checkboxdata["enabled"]最简单
历史 enable 开关data.get("enable", data.get("enabled", default))仅在项目已有该字段时使用
模式 E 不读(不读,直接看 override 后节点的运行时行为)pure override 模式,Python 拿不到也不需要 flag

5. 不要用非 Yes/No 的 switch case 名

// ❌ 错:Client 解析可能不一致
{ "name": "true" } / { "name": "是" } / { "name": "ON" }

// ✅ 对:跨 Client 一致
{ "name": "Yes" } / { "name": "No" }

6. 不要让 input 注入路径和读取路径错位

input 的 {name} 占位符既可以注入 OCR expected,也可以注入 action.param.custom_action_param。选择哪条路径取决于最终消费方:普通 OCR/配置读取用实际节点字段,CustomAction 执行参数用 argv.custom_action_param。不要写入一条路径却从另一条路径读取。

7. 不要用中文做 pipeline 节点名

// ❌ 错:中文节点名 + 英文字段访问
"开启5月": { "enabled": true }

// ✅ 对:英文 Flag_ 命名
"Flag_EnableMarryTask": { "enabled": true }

中文做 option 名(用户可见),英文做 pipeline 节点名(代码访问)。混了会让代码和配置都对不上。

8. 不要在多文件 pipeline 里重复定义同名节点

parse_and_override_once 合并所有 pipeline JSON 时严格拒绝重复顶层 key。检查方法:

grep -rn "^\s*\"YourNodeName\":" assets/resource/base/pipeline/

两个文件都定义同一个顶层节点会直接让整个 check_resource.py 失败,且 Python json.load() 检测不出来(Python 会静默覆盖),必须用 C++ 解析器或 C++ 模拟检测。

9. 不要为了"配置统一"硬塞 Flag 节点

// ❌ 错:行为切换只动 pipeline 字段,但你硬加了 Flag 节点 + Python 分支
"Flag_AcceptMercenary": { "enabled": true },   // ← 不必要
def handle_mercenary_join(context):
    if not context.get_node_data("Flag_AcceptMercenary").get("enabled"):
        return True
    context.run_task("Event_MercenaryJoin")      # 实际行为由 Event_MercenaryJoin.next 决定

// ✅ 对:直接 override `next`,零 Python 改动
"开启自动接受佣兵": {
    "type": "switch",
    "pipeline_override": {
        "Event_MercenaryJoin": { "next": ["Event_MercenaryJoinConfirm"] }
    }
}

判断口诀:如果你的 Python 分支里只做了一件事(调用 run_task 让 pipeline 接手),那这个分支完全可以由 pipeline_override 替代。Flag 节点 + Python 分支只在你需要在 Python 侧做真正的条件逻辑(不只是转发)时才必要。

10. 不要用 Python orchestration 替代状态机

如果一个跨页面流程可以列举为有限个页面状态(A → B → C → D),优先用 MaaFramework 的 next + [JumpBack] 串起来。不要写 Python for 循环 + context.run_task() 调度。

// ✅ 对:纯 JSON 状态机(推荐)
"GrowthTrial_Start": {
    "next": [
        "GrowthTrial_TeamReady",                  // 已在队伍配置页
        "[JumpBack]GrowthTrial_Difficulty_Select", // 在难度选择页
        "[JumpBack]GrowthTrial_Enter"             // 在大地图
    ]
}

"GrowthTrial_Enter": {
    "next": [
        "GrowthTrial_Enter_Click",                  // 找到图标
        "[JumpBack]BigMap_Activity_Resident",       // 切"常驻"tab
        "[JumpBack]BigMap_Activity"                 // 打开活动页
    ]
}

"GrowthTrial_EnterBattle": {
    "action": "Click",
    "next": [
        "GrowthTrial_FightStart",                    // 战斗开始
        "[JumpBack]GrowthTrial_TravelSelect_Boat",   // 弹出旅行框
        "[JumpBack]GrowthTrial_TravelSelect_Walk"    // fallback
    ]
}
# ❌ 错:自己重新发明状态机
def enter_growth_trial(context):
    found = False
    for attempt in range(5):
        if context.run_recognition("BigMap_GrowthTrial_OCR", ...).hit:
            found = True
            break
        context.run_task("Map_SwipeUp_OnBigMap")
    if not found:
        return False
    context.run_task("GrowthTrial_Enter")
    # ... 又是 for/if 链
    return True

自检问题:

  • 我的 Python 代码里是否在调 run_task 把控制权交给 pipeline?是 → 考虑改用 next 链
  • 我的"流程推进"是否依赖显式的状态变量(如 found)?是 → 改用 [JumpBack] 让框架自动回退
  • 我的"流程"是否可以画成状态机图?是 → 用 JSON next 链

注意:MaaFramework 全局加载时跨文件节点引用会解析(main_ui.json 里的 BigMap_Activity* 能在 growth_trial.json 引用),但**run_pipeline 测试工具只加载单文件**——集成测试必须用 MaaFramework GUI/CLI 触发。

11. 不要让 UI override 字段和 Python 读取字段不一致

// ❌ 错:UI 写 enable
"开启克隆体": {
    "type": "switch",
    "cases": [
        { "name": "Yes", "pipeline_override": { "AutoSky_CloneConfig": { "enable": true } } }
    ]
}
# ❌ 错:代码却读 expected,永远读不到用户开关
self._clone_enabled = _read_expected_value(context, "AutoSky_CloneConfig")
# ✅ 对:读同一个字段,或提供 enable/enabled 兼容
self._clone_enabled = _node_enabled(context, "AutoSky_CloneConfig")

自检口诀:UI 写哪条路径,Python 就读哪条路径;pure override 则 Python 不读。


验证流程

改完一次完整流程,按顺序做这 4 步:

  1. JSON 语法检查

    python -c "import json; json.load(open('assets/interface.json', encoding='utf-8'))"
    python -c "import json; json.load(open('assets/resource/base/pipeline/auto_task.json', encoding='utf-8'))"
    
  2. 资源加载检查

    python tools/ci/check_resource.py assets/resource/base
    

    期望输出 All directories checked.

  3. Pipeline 节点测试(可选)

    data = context.get_node_data("Flag_EnableSailingFestivalPurchase")
    assert data is not None, "节点未预定义"
    assert "enabled" in data
    
  4. 端到端验证:用 Pipeline Testing Skill 跑一次实际流程


完整协议

更多 type 字段、嵌套 option、global_option、controller/resource 限制、{占位符} 注入机制等高级特性见 references/protocol.md。

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Generate MaaFramework Pipeline nodes and recognition snippets from screenshots or observed UI state. Use for OCR node generation, ROI sweep, choosing TemplateMatch/OCR/ColorMatch/CustomRecognition, preserving target-file schema style, and designing `next`/`[JumpBack]` links before merging generated nodes into pipeline JSON.

日本語の概要は準備中です。原文の説明を表示しています。

KhazixW2/MaaGumballs672026年10月2日 更新

生成 MaaFramework Pipeline 项目的可交互状态机图谱。当用户想"看 Pipeline 节点关系"、"画状态机图"、"画 Mermaid 图"、"看 node 间关系"、"找孤立节点 / orphan node"、"看 Python 怎么驱动 Pipeline"、"看 interface.json 入口"、"调试跨文件 next 引用"、"重构前理清架构" 时使用。**任何涉及 MaaFramework 节点关系可视化的需求都用这个 skill**,即便用户没明确说"画图"。

日本語の概要は準備中です。原文の説明を表示しています。

KhazixW2/MaaGumballs672026年10月2日 更新

Universal Pipeline JSON 编写指南。基于 MaaFramework Pipeline 协议,提供节点命名、识别算法、动作类型、流程控制、可复用节点等编码规范与模式参考。在编写、修改或审查 Pipeline JSON、设计节点流程、使用 TemplateMatch/OCR/Custom 识别或 Click/Swipe 动作时使用。

日本語の概要は準備中です。原文の説明を表示しています。

KhazixW2/MaaGumballs672026年10月2日 更新

Audit a MaaFramework/Maa-series project's Git history to learn how Pipeline JSON, interface options, Python AgentServer CustomAction code, and related data tables evolved. Use when asked to review a Maa project from initial commit through a target commit, map `action: Custom` pipeline nodes to `@AgentServer.custom_action(...)` implementations, find pipeline/custom/option patterns or breakages, and produce a report plus skill-improvement recommendations.

日本語の概要は準備中です。原文の説明を表示しています。

KhazixW2/MaaGumballs672026年10月2日 更新

Test and validate MaaFramework Pipeline JSON, recognition nodes, action nodes, CustomAction/CustomRecognition wiring, resource loading, and end-to-end task behavior. Use when running `run_pipeline`, checking OCR/TemplateMatch/ColorMatch ROI, validating `context.run_task()` results, auditing `action: Custom` or `recognition: Custom` registrations, or choosing the right resource-check command.

日本語の概要は準備中です。原文の説明を表示しています。

KhazixW2/MaaGumballs672026年10月2日 更新

KhazixW2 のスキルをすべて見る

このスキルの問題を報告する