windsland52/maatutorial

maafw-pipeline

编写、修改与审查 MaaFramework(MaaFW)Pipeline——从零新建任务与子流程(大任务逐级拆分为嵌套复用的子流程、需求翻译成状态、资源文件与节点命名、识别/动作节点编写与 ROI 圈定、next 链分支/循环/[JumpBack]/[Anchor] 中断与失败路径设计、可达性自查)与存量重构(摸底可复用节点、改名前全库搜引用、坐标卫生与反模式审查)。Use when authoring, editing, or reviewing any pipeline JSON in a MaaFW p…

ソースを見る
リポジトリの原文

見出し、例、コード、表、リンク、参照画像を含む原文を表示しています。

MaaFW Pipeline 开发

编写全流程分两条动线,动手前先分轨:

  • 新建轨:从零新建流程(任务或子流程)——需求 → 拆分与状态清单(含探索取证)→ 文件结构与命名 → 素材准备 → 节点编写 → 流程组合 → 自查与交接。任务可大可小:大任务逐级拆成子流程,嵌套组合,每一层走同样的步骤。
  • 修改轨:在既有项目上改动、重构、审查——摸底 → 搜引用 → 修改 → 自查(见下),不按新建顺序硬套。

字段精确语义(字段名、参数、默认值、版本支持)不在本文复制,一律路由 MaaLLMWiki 的 3.1-任务流水线协议:版本锁定、引用回源、不可达时标记"未验证"(已安装 maallmwiki skill 时由其承载完整路由流程)。执行模型是下文一切推理的基础,在此给出最小版:

执行模型(最小心智模型)

节点是三段式:识别 → 动作 → next。引擎在节点间如此运转:

  1. 任务由入口节点名启动(post_task):引擎初始化为"当前节点 = 入口节点、轮询列表 = [入口节点]"——入口作为唯一候选被识别(通常 DirectHit 恒命中);若识别超时,用它自己的 timeout,未命中也走它自己的 on_error。
  2. 当前节点动作完成后,对它的 next 列表按顺序轮询识别:每轮依次尝试各候选;本轮全未命中,等 rate_limit 后再截图重试(本轮候选全为 DirectHit 时跳过截图,零画面开销)。
  3. 第一个命中的候选立即胜出(后续候选不再检测),进入该节点、执行其动作——动作成功则轮询它的 next 列表(回到第 2 步);动作失败走它的 on_error。
  4. 轮询超过当前节点的 timeout(缺省 20s)仍无命中 → 走当前节点的 onerror——想调整某节点**被识别**的等待时长或超时去向,改的是**它上一节点**的 `timeout` / `onerror`,不是它自己的。
  5. 异常状态:
  • 进入(三种):动作失败;轮询超时;被轮询列表中没有任何存在且启用的节点(不等 timeout、立即未命中——不存在的引用过不了加载校验,走到这一步的多为 enabled:false 节点或未设置的锚点)。
  • 进入后:onerror 列表接替 next 列表被同样轮询——onerror 为空时 next 立即为空、循环直接终止,任务以失败收场。
  • 解除:只由识别命中解除;命中后若动作失败,立即重新进入——因此结果上走出异常 = 命中且动作成功。
  • 异常期间收紧:再次未命中(onerror 轮询超时,或 onerror 列表没有任何存在且启用的节点——如恢复节点名拼错,不等超时、立即失败)不进 on_error、任务直接失败;执行链走空时若仍处于异常状态,已登记的 [JumpBack] 回跳不生效,任务以失败终止。
  1. 终止与成败:
  • 循环在 next 为空或外部 stop / StopTask 时终止;任务成败 = 终止时是否处于异常状态(正常态走空即成功)。
  • 唯一例外 `[JumpBack]`(仅正常态):子链走空不终止,重新轮询父节点的 next 列表(从头按序识别;父节点不经识别恢复为当前节点,超时与 on_error 归属随之回到它,动作不重跑)。例:A.next=["B","[JumpBack]C"]、C.next=["D"]、D.next=[]——C 命中执行后走 D,D 走空,接着轮询的就是 A.next。

on_error 归属:看当前处于哪个节点——候选被识别不算进入节点,命中后才算进入;进入后的执行动作与轮询 next 列表都发生在本节点内,失败就走本节点的 onerror:动作失败走动作所在节点的 onerror,轮询 next 列表超时走 next 列表所属节点的 on_error。

硬护栏(全程生效)

  1. 探索优先:要写的每个状态必须有真实观测证据(截图、OCR 文本、色值、box 等);凭文档、节点名或记忆推断的状态一律视为 guessed,guessed 状态不得落笔。细则:
  • 按转移推进:探索推进到哪个界面(以当前设备画面为准),就观测该界面的识别标志与点击目标;点击后实际观测到下一界面的标志出现(即 next 里的"出口"候选),这条转移即可落笔。弹窗处理节点同样只在见过该弹窗后写。写到哪、观测到哪,不必整个流程探索完再动笔;整段贯通与可重入不在写作门槛内,轮到自查与端到端验收去跑。
  • 点击最小化副作用:非必要的提交/领取类按钮不点;能靠关键帧确认的状态不主动触发。
  • 不可复现的状态(一次性奖励、首通引导、不可逆操作后的界面)无法主动到达,用留存的关键帧代替——工具暂存的重要变化帧同样算观测证据,写前逐帧核对;连关键帧都没有的仍按缺口处理。
  • 复用已有节点时,其入口前提同样是必须观测的状态。
  • 无法探索(无设备、无授权、会触发禁止的副作用)就停下报告缺口,不要硬写计划。
  • 实时性场景不适用:抢购、QTE 等毫秒级反应无法靠"观察→决策"的探索模式,也超出轮询模型的反应速度——直接说明做不到,不硬写。
  1. 坐标卫生:点击目标由识别结果推导。target 缺省 true(继承本节点识别 box),绝大多数节点不需要写它;要偏移用 target_offset 并注明依据;确需另指目标优先 string 引用(前置节点名 / [Anchor]锚点名,引用结果为空即动作失败);固定坐标数组视同硬编码,仅特殊场景(如负坐标从边缘计算)使用并注明理由——严禁 `DirectHit` + 硬编码 target 坐标。
  2. 不编造字段:字段名、参数、版本支持拿不准就路由,宁可少写用默认值;$ 开头 root 字段不解析、. 开头文件不读取。pipeline 文件按 jsonc 解析——行内与整行 // 注释直接可用;需要结构化注释时用 desc / _desc,占位提示用 code / _code(如 template_code 表示该参数在 interface.json/Custom 代码里统一配置),doc / _doc 亦同(尽量不用)——均为非协议字段(3.1 协议零记载),引擎对未知键静默忽略,作结构化注释属约定用法,纯说明优先 jsonc // 注释。
  3. 基准分辨率中立:运行基准从项目 controller 配置动态获取(缺省 720 短边,兼容横竖屏);量 ROI 的截图必须走框架截图链路,不用外部图片。
  4. 循环必须有终止论证:凡执行会回到已执行节点候选列表的写法([JumpBack] 回跳、next 回指成环),终止论证三选一并在注释说明。细则:
  • 限次:max_hit / timeout + on_error 上报;
  • 识别门控:候选带真实识别、动作以消除该识别为目标,动作可能失效时仍配兜底限次;
  • 挂机意图:显式声明的无限产出循环,退出靠外部停止或条件节点,环内每轮有真实进展,重置计数必须显式;
  • `timeout` 只管"目标界面一直没出现":管不了"一直命中、停不下来"——只要每轮都有候选命中,超时永远不会触发;
  • DirectHit 禁入循环:恒命中且无识别门控,禁止作为 [JumpBack] 自回环或循环体候选——全 DirectHit 候选列表还会跳过截图,连画面变化都观测不到。

新建轨

步骤 1–5 按段滚动推进:拆出的每个子流程各自走 1→5,探索一段、写一段,不必整个任务探索完再动笔;全部段落完成并自查后进第 6 步。

滚动推进必须伴随进度档案(跨会话的 working memory,外置成文件,放资源包外不被框架加载的位置):记录需求与拆分结论(子流程清单)、每段实现状态(计划中 / 已编写 / 已测试)、每个已观测状态的证据帧编号、当前断点(设备停在哪个界面)。关键帧与状态绑定归档——它同时是 observed 证据、复测识别的素材(节点测试模式:截图 + hits/box 期望)、模板裁剪的来源。

1. 需求 → 拆分与状态清单(含探索取证)

  • 先拆再翻(滚动拆分):需求可大可小,大任务先拆成子任务/子流程——每个子流程有明确的入口/出口边界(约定 Start/End 后缀),可跨任务复用的收进资源包内 pipeline/ 顶层共享文件(general.json),复用边界由文件归属与跨模块引用表达,不靠节点名前缀(见 references/project-structure.md);子流程内部再同法拆分,嵌套任意层。拆分边界:一段可独立观测与独立验证的界面段/业务段。拆分不必一次完成——先定子流程边界的大框架,屏内的状态与弹窗随推进滚动补进清单。
  • 屏内动线(先同屏、后出口):进入一个界面后,先写并即测该界面的异常处理节点——同屏内容不离开画面,写完就能测(屏内广度);出口最后写——写完测完人已在下一界面,顺接继续(屏间深度)。反序会先离开本屏,未适配的弹窗要整条流程重跑才能回来补测。
  • 把每个(子)流程翻译成状态而非动作清单:起始态、每个中间态(含可能的弹窗)、成功态、失败态。每个状态回答两个问题:
  • 用什么识别:固定图 → TemplateMatch;文本 → OCR(expected 用完整稳定文本);色块 → ColorMatch;无视觉变化的流程节点 → DirectHit;目标尺寸 / 缩放会变(模板匹配失配)→ FeatureMatch;模板 / 文本 / 颜色都不可行的复杂目标 → NeuralNetworkClassify / NeuralNetworkDetect(自训 ONNX 模型);多条件同屏 → And / Or;都表达不了 → Custom(交接 maafw-custom)。完整名单与精确参数路由 3.1-任务流水线协议核对。
  • 证据是 observed 还是 guessed:哪段要写,哪段的状态必须全部 observed(硬护栏 1);尚未探索的段留到写到时再探索。

2. 文件结构与命名

先定落位再写内容:

  • 新功能按模块拆文件/目录;文件组织两派选一固定:模块前缀式(AutoCollect/AutoCollectRoute1.json——文件名带模块前缀、模块多时配目录,排序聚簇)或功能平铺式(awards.json 平铺根目录,功能数适中时更轻),均有大项目实证;新建默认模块前缀式 + PascalCase 文件名(与节点 / 模板图大小写一套,目录从第一天起、无增长天花板),存量平铺项目照旧、增量新模块可开目录;细则见 references/naming.md。
  • pipeline JSON 有 v1 扁平与 v2 嵌套(recognition / action 收敛为 {type, param},v4.4.0+)两种等价写法,字段语义通用;新建默认 v2(识别/动作/流程参数命名空间分开,错位字段在结构上不可发生),存量跟随既有主流风格、不必整仓转换,项目内统一(依据见 references/flow-patterns.md 示例注)。
  • 节点名跨文件全局解析、大小写敏感;同资源包内重名即错误(跨包重名是渠道覆盖机制,见 references/naming.md);不以 $ 开头,方括号([ ])是 next / onerror 引用位的属性语法(`[` 开头条目按属性前缀解析),节点名约定不使用;入口/收尾节点用 `Start`/`End` 后缀(约定);节点名语义按词位公式组织(`任务界面对象角色_变体`,下划线分隔槽位,见 references/naming.md);复用边界不用节点名前缀表达。
  • image 按模块分目录,素材路径即引用键,改名必须同步改 pipeline 引用与 custom 代码内的读图调用(自定义识别 / 动作可自行加载图片)。
  • 仓库布局、多资源包见 references/project-structure.md;资源目录下文件夹名禁 _ 开头(Android 打包事故)。

3. 素材准备

从状态清单推导素材缺口,补齐再写节点:

  • 模板从基准分辨率的框架截图(无损原图缩放后)裁剪,裁剪源与识别输入保持同一图像空间。外部图片 / 游戏内截屏不一律禁用,判定标准是像素空间一致:模拟器自带截图在分辨率与控制器基准一致(或长宽比一致、可无损缩放到基准)、且无遮挡污染(通知栏 / 工具水印 / 有损压缩)时与框架截图同源同空间,可用;相机翻拍、比例不符、带污染的不可用。无论来源,一律过裁后自匹配复核兜底。
  • 素材获取按工作流选工具,硬要求不随工具变(像素空间一致 + 裁后自匹配复核,见上条):agent 自主工作流优先实时观测底座(如 maafw-live)——帧流常驻、裁剪与取色全程程序化,人不必盯屏:模板从留存的原始分辨率帧裁(crop,识别空间一致)、探色(color)、无模板时候选区域编号选点(annotate)、不可复现状态从关键帧库留存帧裁剪(含事后离线 crop --from-kf,不需要设备;产物带 L2 出处)。该工具的动线与判据读它自带的 skill(随包发布,本集合不重复):npx skills add https://github.com/Windsland52/maafw-live --skill maafw-live --global。无观测底座时也可自写脚本走框架截图链路截图后程序化裁剪;人工在场调试可用官方工具链(VSCode maa-support 插件、MFA 工具箱、MPE 等)交互式截取。
  • 裁后自匹配复核:新模板在其来源帧的来源位置应命中(位置正确优先于得分,纯色模板得分是噪声)——裁完即验,不等流程联调才发现素材问题。
  • 裁剪区域选稳定特征,避开动态数字/动效——动态内容使同一状态的每次捕获像素不同,模板命中不稳。

4. 节点编写

每态一个节点,先识别后动作:

  • 识别按状态清单的选型落字段;roi 收紧到目标实际出现区域(提速且防误命中),起点可取识别 box 外扩约 20px——过紧易失配、过松易误中,不稳时扫描几档。
  • 动作按意图选型,完整名单与精确参数路由 3.1-任务流水线协议核对:点击 Click / LongPress,滑动 Swipe / MultiSwipe / Scroll,按键 ClickKey / LongPressKey / KeyDown / KeyUp,输入 InputText,应用启停 StartApp / StopApp,流程 StopTask / DoNothing,系统能力 Command / Shell / Screencap,扩展 Custom。点击落点遵守坐标卫生(硬护栏 2)。
  • 要向用户展示节点消息(运行日志 / 轻提示 / 系统通知 / 弹窗)配节点 focus:按消息类型给模板({name} 等占位替换、支持 $ i18n),display 选展示渠道;trace 上报遥测需项目 interface.json 配置了 telemetry 才生效——字段定义路由 3.1,模板与渠道机制路由 3.3 协议「节点通知处理」节。
  • 参数起点:threshold 以实测为准(得分裕量规则仅 TemplateMatch 套用;OCR / ColorMatch 语义不同;FeatureMatch 无 threshold,严格度由 count 最少特征点数与 ratio KNN 距离比控制)——起点取目标位实测得分减约 0.1(换场景会掉),核对仍高于该屏误配最高分;两侧贴得太近是模板 / roi 问题,调阈值救不了;能用 *_wait_freezes 等待稳定的就不加 delay;拿不准的参数少写、用默认值(硬护栏 3)。
  • 写入纪律:增量插入而非整文件改写——JSONC 注释承载"为什么这么写",整写会毁掉它;缩进与字段顺序跟项目既有约定(常有格式化插件);坐标一律用框架缩放后坐标系的实测值。

5. 流程组合

  • 主干:最短可成功路径排成线性 next 链。细则:
  • 等待目标出现:界面切换用"等待目标出现"节点表达,不用长 delay 凑;
  • 参数保持缺省:pre_delay / post_delay / 节点级 timeout(next 轮询超时)尽量保持缺省;
  • wait_freezes 的 `timeout` 例外:只在必须等画面稳定时用 pre_wait_freezes / post_wait_freezes,其自身 timeout 不属于"保持缺省"之列——默认 20s,等待区域有持续动画时等满才继续,常配 1~2s 小值兜底。
  • 分支:next 列表顺序即优先级,第一个命中执行。排序两原则:
  • 遮蔽约束优先:某候选出现时另一候选也必然命中,前者必须排在前;排反了后者永远轮不到(功能错乱),若被遮蔽的恰是出口、遮蔽者的动作又消不掉自己的触发条件,就构成"一直命中"的死循环,timeout 救不了(硬护栏 5 的预防端在此);
  • 命中频次降序:其余候选按频次降序排,每轮按序识别,高频在前平均每轮少做识别,全局资源消耗最优;
  • 表达手段:互斥分支用顺序表达;按位置/得分排序用 order_by,组合条件用 And/Or。
  • 循环与中断。细则:
  • 循环:循环体 + 出口节点放同一列表,max_hit 限次防死磕(终止论证三选一见硬护栏 5);
  • 弹窗 / 加载处理器:随时可能弹的界面(公告、奖励、断线)做独立处理节点,以 [JumpBack] 挂在关键等待点(回跳只在正常态兑现,异常态下链走空即任务失败);
  • 跨分支汇合用 `anchor`——引用未设置的锚点会被静默跳过。
  • 等待与重试分层。细则:
  • 等待用参数表达,不写结构:next: ["目标"] 本身已在等待,节奏由 timeout / *_wait_freezes / rate_limit 调,自指 next 对"等下一屏出现"零增益;
  • 重试需证据:动作重试只在遥测显示真实失效率后添加;
  • 自指重试优先:线性流程用单节点自指 + 自身 max_hit 即可(预算含首次进入、跨引用点全程累计),不建克隆节点;
  • 克隆的门槛与纪律:确需独立重试预算或策略升级(重试前等待、长按替单击)才克隆;Retry / Fallback 后缀与源同前缀保持可搜;desc 注明克隆自哪个节点、与源刻意差异的字段(差异面)——差异面之外的字段与源不一致即漂移 bug,改源节点时差异面之外的字段有同步义务;
  • 共享处理器例外:被多处引用的节点在 max_hit 累计语义下不能用小值,防线是严格识别门控;max_hit 用尽的候选静默退场(识别时跳过、不报错),列表照常轮询——再无可命中候选时空转至超时、走宿主节点的 on_error,耗尽本身不是失败信号;
  • 审查基线:无证据的自指 / 自回环在审查时视为待删项。
  • 失败路径:每个 next 列表问一遍"全没命中怎么办"。细则:
  • 兜底结构:timeout(-1 无限慎用,v5.5+)+ on_error 兜底(回退/重试/上报),重试配 max_hit 限次;
  • on_error 链自身必须能稳定命中——异常状态里再失败没有二次兜底,任务直接终止;
  • on_error 只做异常恢复:不当正常流程的控制流(比如拿来实现 if-else 效果);
  • 重试与 `max_hit` 是安全带不是修复:反复失败先修根因(识别不稳/逻辑缺陷);
  • 禁无识别门控的盲目重试:"没反应就原地点第二次"(第二次点击可能已落到下一界面的其他元素上);重新识别到按钮仍在才再点的有限重试是合法恢复手段;
  • 动作失败走收敛:动作失败(框架报错)不以自指或自回环重试——持续的动作失败是缺陷不是抖动,让 on_error 收敛(上报 / 回退 / 重入子流程入口重跑识别),瞬态恢复须显式有界。

模式示例 JSON 与稳定性法则(识别→操作→再识别、少用硬延迟)见 references/flow-patterns.md。

6. 自查与交接

  • 可达性:无孤立节点、无 anchor 断链、无未解析引用;完备性四问——主线能跑?弹窗能处理?加载能等过去?不在目标场景时的行为已显式定义(自动跳过还是失败上报,是项目的产品决策,不能默认漏掉)?
  • 有节点测试基建的项目(如带 tests/ 目录与截图期望的)为新增识别节点补用例。
  • 交接:单节点验证与端到端验收 → maafw-debug;task 入口与选项接线 → maafw-interface;JSON 表达不了的逻辑 → maafw-custom。

修改轨(存量项目入口)

改动、重构、审查既有 pipeline 时走此轨:

  1. 摸底(规模随改动伸缩,走索引不通读)。细则:
  • 小修(bug、调字段、ROI 微调):定位目标节点及其定义与直接上下游即可;
  • 结构性改动(新增功能、重构、动复用面)才摸复用面——先看地图(目录树 + interface.json 任务清单)→ 节点名索引用脚本提取(逐文件列 root key,勿逐文件通读)→ 按能力关键词检索、命中文件才读全文(词位命名的语义名即检索索引,共享件先查 general.json);
  • 素材:按 image/ 目录结构按需检索;
  • 无论规模:先明确改动边界(哪些节点动、哪些只引用)。
  1. 搜引用:改节点名或素材路径前全库搜索引用点——漏改的后果按引用位置分档,并非都是静默:next / onerror 漏改**加载期即失败**(非锚点引用的存在性校验,能抓住;interface 的 pipelineoverride 注入的悬空引用同样被拦);roi / target 引用、custom 的 runtask、template 素材路径漏改**运行期失败**(目标解析空即动作失败 / 任务不存在 / 模板懒加载缺图);`[Anchor]` 条目(校验跳过锚点名)与 option 的 pipelineoverride(override 落空)才是静默失联。引用点清单:
  • 节点引用:next / onerror 的三种写法(裸字符串、`[JumpBack]X` 前缀、`{name:"X"}` 对象)、roi / target 的 string 引用、`[Anchor]`、option 的 pipelineoverride、custom 的 runtask / overridenext;
  • 素材路径:pipeline 的 template 与 custom 代码内的读图调用(自定义识别 / 动作可自行加载 image/ 下的图);
  • 同前缀克隆:改识别 / 动作参数前另搜 Retry / Fallback 后缀——克隆与源静默漂移,同样不报错;
  • 跨语言引用:custom / agent 代码内写节点名(语言不限——C++ / Python / Node.js / Go 等)按入口分两类——run_task / run_recognition / run_action 的 entry 按原始字符串查节点,传 "[Anchor]X" 只会去找字面叫这个名字的节点并失败,锚点跳转先 get_anchor 取实名再传入;override_next 的 next 列表与 pipeline 引用位同解析,[JumpBack] / [Anchor] 属性语法可用。锚点本身可经 context API 读写(set_anchor / get_anchor,C API / agent RPC / 各绑定均暴露);写实名 + 改名前全库搜引用仍是基线防线。
  1. 修改:按需对齐新建轨 2–5 的同等标准写新内容。
  2. 自查:可达性检查 + 反模式清单逐项核对(references/anti-patterns.md——坐标卫生、timeout/-1 滥用、循环限次、版本兼容)。

深入阅读(按需)

同じリポジトリから

関連する Skills

すべての Skills
windsland52
コミュニティ

maafw-custom

编写、注册与调试 MaaFramework Custom 识别/动作——何时上 Custom 的判据、宿主与注册路径、binding 实现与注册、参数解析与校验、复用 pipeline 节点、Agent 子进程模式与工程规范。Use when implementing MaaFW custom recognition or action logic, deciding registration path for your host, registering customs, parsing customactionparam/customrecognitionparam, reusing pipeline nodes inside custom code, or setting up the agent child process mode.

導入数
4
GitHub Stars
2
更新日
10月8日
windsland52
コミュニティ

maafw-debug

调试与验收 MaaFramework(MaaFW)应用(开发态、设备在线)——节点识别失败、点击不落点(识别成功 ≠ 点击生效)、ROI 校准与阈值调参、单节点运行验证、流程卡死与 controller 连接排查、端到端验收与 pipelineoverride 生效验证;按配置/识别/动作/流程/验收五层分诊,产出定位结论与证据,修复交接回 maafw-pipeline / maafw-interface / maafw-custom。Use when debugging or acceptance-testing a MaaFW application with a device attached — node recognition failures, clicks that miss, ROI calibration and threshold tuning, single-node run verification, stuck flows and controller connection issues, end-to-end acceptance, or pipelineo

導入数
4
GitHub Stars
2
更新日
10月8日
windsland52
コミュニティ

maafw-interface

编写、修改与审查 MaaFramework interface.json(Project Interface V2)——任务入口声明、controller/resource 配置、GUI 选项接线(pipelineoverride 与覆盖顺序)、preset 预设、pretask 启动前任务、agent 子进程配置、import 拆分与结构排错。Use when creating, editing, or reviewing an interface.json for a MaaFW project, adding user-facing options or presets, wiring pipelineoverride, configuring pretask or agent child processes, splitting interface files via import, or diagnosing interface structure errors.

導入数
4
GitHub Stars
2
更新日
10月8日