Skip to content

Conversation

@MistEO
Copy link
Member

@MistEO MistEO commented Nov 28, 2025

Summary by Sourcery

为新的 MaaFW v5.1 节点级 API 和自定义列表添加绑定和通知,并扩展上下文和资源接口以暴露新的框架能力。

新功能:

  • 引入用于节点级通知的 pipeline、recognition 和 action 节点消息常量。
  • 为 pipeline、recognition 和 action 节点添加通知明细记录和注册表事件,包括更新后的下一节点列表负载。
  • 暴露新的 IMaaContext API,用于管理节点锚点和命中计数。
  • 在代理客户端和资源绑定上暴露自定义识别和动作列表访问器。

增强内容:

  • 扩展通知处理程序路由和辅助工具,以支持新的节点消息类型。
  • 更新互操作层,以封装新的 MaaContext、MaaAgentClient 和 MaaResource 本地函数。
  • 扩展通知序列化上下文,以覆盖新的明细和列表项类型。
Original summary in English

Summary by Sourcery

Add bindings and notifications for new MaaFW v5.1 node-level APIs and custom lists, and extend context and resource interfaces to expose new framework capabilities.

New Features:

  • Introduce pipeline, recognition, and action node message constants for node-level notifications.
  • Add notification detail records and registry events for pipeline, recognition, and action nodes, including updated next-node list payloads.
  • Expose new IMaaContext APIs to manage node anchors and hit counts.
  • Expose custom recognition and action list accessors on agent client and resource bindings.

Enhancements:

  • Extend notification handler routing and helpers to support the new node message types.
  • Update interop layer to wrap new MaaContext, MaaAgentClient, and MaaResource native functions.
  • Expand notification serialization context to cover new detail and list item types.

@MistEO MistEO requested review from Copilot and moomiji November 28, 2025 03:07
@sourcery-ai
Copy link

sourcery-ai bot commented Nov 28, 2025

Reviewer's Guide

通过为流水线 / 识别 / 动作节点新增节点级通知类型、丰富 NextList 载荷、公开新的上下文 / Agent / 资源 API(锚点、命中次数和自定义节点列表),并将它们贯穿打通到 interop、通知和处理器层,以同步 MaaFramework .NET 绑定到 MaaFW v5.1。

节点流水线通知处理的时序图

sequenceDiagram
    participant NativeFramework as Native_framework
    participant ManagedBinding as MaaCallback
    participant Registry as NotificationHandlerRegistry
    participant Nodes as NodeRegistry
    participant Pipeline as PipelineNodeRegistry
    participant UserHandler as User_subscriber

    NativeFramework->>ManagedBinding: MaaCallback(caller, message, details)
    ManagedBinding->>Registry: OnCallback(sender, MaaCallbackEventArgs)
    Registry->>Registry: switch Message
    Registry->>Nodes: Node.PipelineNode.OnStarting(sender, details)
    Nodes->>Pipeline: OnStarting(sender, details)
    Pipeline->>Pipeline: JsonSerializer.Deserialize(details, NodePipelineNodeDetail)
    Pipeline-->>UserHandler: Starting(sender, NodePipelineNodeDetail)
    activate UserHandler
    UserHandler-->>Pipeline: handle event
    deactivate UserHandler
Loading

新增节点通知消息和详情的类图

classDiagram
    namespace MaaMsg_Node {
        class Task_Node {
        }

        class Node_PipelineNode {
            <<static>>
            +string Starting
            +string Prefix
            +string Succeeded
            +string Failed
        }

        class Node_RecognitionNode {
            <<static>>
            +string Starting
            +string Prefix
            +string Succeeded
            +string Failed
        }

        class Node_ActionNode {
            <<static>>
            +string Starting
            +string Prefix
            +string Succeeded
            +string Failed
        }
    }

    namespace Notification_Detail {
        class NodePipelineNodeDetail {
            +int TaskId
            +int NodeId
            +string Name
            +JsonElement Focus
        }

        class NodeRecognitionNodeDetail {
            +int TaskId
            +int NodeId
            +string Name
            +JsonElement Focus
        }

        class NodeActionNodeDetail {
            +int TaskId
            +int NodeId
            +string Name
            +JsonElement Focus
        }

        class NextListItem {
            +string Name
            +bool JumpBack
            +bool Anchor
        }

        class NodeNextListDetail {
            +int TaskId
            +string Name
            +IReadOnlyList~NextListItem~ NextList
            +JsonElement Focus
        }
    }

    MaaMsg_Node.Node_PipelineNode ..> Notification_Detail.NodePipelineNodeDetail : details_json
    MaaMsg_Node.Node_RecognitionNode ..> Notification_Detail.NodeRecognitionNodeDetail : details_json
    MaaMsg_Node.Node_ActionNode ..> Notification_Detail.NodeActionNodeDetail : details_json
    Notification_Detail.NodeNextListDetail o--> Notification_Detail.NextListItem : list
Loading

通知处理器注册扩展的类图

classDiagram
    class NotificationHandlerRegistry {
        +OnCallback(object sender, MaaCallbackEventArgs e) void
        +NodeRegistry Node
    }

    class MaaCallbackEventArgs {
        +string Message
        +string Details
    }

    class NodeRegistry {
        +PipelineNodeRegistry PipelineNode
        +RecognitionNodeRegistry RecognitionNode
        +ActionNodeRegistry ActionNode
        +NextListRegistry NextList
    }

    class PipelineNodeRegistry {
        +event EventHandler~NodePipelineNodeDetail~ Starting
        +event EventHandler~NodePipelineNodeDetail~ Succeeded
        +event EventHandler~NodePipelineNodeDetail~ Failed
        +OnStarting(object sender, string details) void
        +OnSucceeded(object sender, string details) void
        +OnFailed(object sender, string details) void
    }

    class RecognitionNodeRegistry {
        +event EventHandler~NodeRecognitionNodeDetail~ Starting
        +event EventHandler~NodeRecognitionNodeDetail~ Succeeded
        +event EventHandler~NodeRecognitionNodeDetail~ Failed
        +OnStarting(object sender, string details) void
        +OnSucceeded(object sender, string details) void
        +OnFailed(object sender, string details) void
    }

    class ActionNodeRegistry {
        +event EventHandler~NodeActionNodeDetail~ Starting
        +event EventHandler~NodeActionNodeDetail~ Succeeded
        +event EventHandler~NodeActionNodeDetail~ Failed
        +OnStarting(object sender, string details) void
        +OnSucceeded(object sender, string details) void
        +OnFailed(object sender, string details) void
    }

    class NextListRegistry {
        +event EventHandler~NodeNextListDetail~ Starting
        +event EventHandler~NodeNextListDetail~ Succeeded
        +event EventHandler~NodeNextListDetail~ Failed
        +OnStarting(object sender, string details) void
        +OnSucceeded(object sender, string details) void
        +OnFailed(object sender, string details) void
    }

    class NotificationDetailContext {
        +NodePipelineNodeDetail NodePipelineNodeDetail
        +NodeRecognitionNodeDetail NodeRecognitionNodeDetail
        +NodeActionNodeDetail NodeActionNodeDetail
        +NextListItem NextListItem
        +NodeNextListDetail NodeNextListDetail
    }

    class NodePipelineNodeDetail
    class NodeRecognitionNodeDetail
    class NodeActionNodeDetail
    class NodeNextListDetail
    class NextListItem

    NotificationHandlerRegistry --> NodeRegistry : has
    NodeRegistry --> PipelineNodeRegistry : exposes
    NodeRegistry --> RecognitionNodeRegistry : exposes
    NodeRegistry --> ActionNodeRegistry : exposes
    NodeRegistry --> NextListRegistry : exposes

    PipelineNodeRegistry ..> NodePipelineNodeDetail : deserialize
    RecognitionNodeRegistry ..> NodeRecognitionNodeDetail : deserialize
    ActionNodeRegistry ..> NodeActionNodeDetail : deserialize
    NextListRegistry ..> NodeNextListDetail : deserialize

    PipelineNodeRegistry ..> NotificationDetailContext : uses
    RecognitionNodeRegistry ..> NotificationDetailContext : uses
    ActionNodeRegistry ..> NotificationDetailContext : uses
    NextListRegistry ..> NotificationDetailContext : uses
Loading

上下文、Agent 客户端、资源与 interop 新增内容的类图

classDiagram
    class IMaaContext {
        +IMaaContext Clone()
        +bool SetAnchor(string anchorName, string nodeName)
        +bool GetAnchor(string anchorName, out string nodeName)
        +bool GetHitCount(string nodeName, out ulong count)
        +bool ClearHitCount(string nodeName)
    }

    class MaaContext {
        +MaaContext Clone()
        +bool SetAnchor(string anchorName, string nodeName)
        +bool GetAnchor(string anchorName, out string nodeName)
        +bool GetHitCount(string nodeName, out ulong count)
        +bool ClearHitCount(string nodeName)
    }

    class MaaContextInterop {
        +MaaContextClone(MaaContextHandle context) MaaContextHandle
        +MaaContextSetAnchor(MaaContextHandle context, string anchorName, string nodeName) bool
        +MaaContextGetAnchor(MaaContextHandle context, string anchorName, MaaStringBufferHandle buffer) bool
        +MaaContextGetHitCount(MaaContextHandle context, string nodeName, MaaSize count) bool
        +MaaContextClearHitCount(MaaContextHandle context, string nodeName) bool
    }

    class IMaaAgentClient {
        +Process AgentServerProcess
        +IList~string~ CustomRecognitionList
        +IList~string~ CustomActionList
    }

    class MaaAgentClient {
        +Process AgentServerProcess
        +IList~string~ CustomRecognitionList
        +IList~string~ CustomActionList
    }

    class MaaAgentClientInterop {
        +MaaAgentClientGetCustomRecognitionList(MaaAgentClientHandle client, MaaStringListBufferHandle buffer) bool
        +MaaAgentClientGetCustomActionList(MaaAgentClientHandle client, MaaStringListBufferHandle buffer) bool
    }

    class IMaaResource {
        +IList~string~ NodeList
        +IList~string~ CustomRecognitionList
        +IList~string~ CustomActionList
    }

    class MaaResource {
        +IList~string~ NodeList
        +IList~string~ CustomRecognitionList
        +IList~string~ CustomActionList
    }

    class MaaResourceInterop {
        +MaaResourceGetNodeList(MaaResourceHandle res, MaaStringListBufferHandle buffer) bool
        +MaaResourceGetCustomRecognitionList(MaaResourceHandle res, MaaStringListBufferHandle buffer) bool
        +MaaResourceGetCustomActionList(MaaResourceHandle res, MaaStringListBufferHandle buffer) bool
    }

    class MaaStringBuffer {
        +TryGetValue(out string value, Func~MaaStringBufferHandle,bool~ invoker) bool
    }

    class MaaStringListBuffer {
        +TryGetList(out IList~string~ list, Func~MaaStringListBufferHandle,bool~ invoker) bool
    }

    IMaaContext <|.. MaaContext
    MaaContext ..> MaaContextInterop : calls
    MaaContext ..> MaaStringBuffer : uses

    IMaaAgentClient <|.. MaaAgentClient
    MaaAgentClient ..> MaaAgentClientInterop : calls
    MaaAgentClient ..> MaaStringListBuffer : uses

    IMaaResource <|.. MaaResource
    MaaResource ..> MaaResourceInterop : calls
    MaaResource ..> MaaStringListBuffer : uses
Loading

富化后的 NextList 载荷流程图

flowchart LR
    A_NodeNextListDetail["NodeNextListDetail
    task_id, name, focus"] --> B_List["list
    IReadOnlyList<NextListItem>"]

    B_List --> C_NextListItem["NextListItem
    name"]
    B_List --> D_JumpBack["NextListItem
    jump_back"]
    B_List --> E_Anchor["NextListItem
    anchor"]

    A_NodeNextListDetail --> F_Consumer["Next list consumer
    (notification handlers, user code)"]
Loading

文件级变更

Change Details Files
为流水线、识别和动作节点添加强类型的通知消息和处理器。
  • 引入 MaaMsg.Node.PipelineNode/RecognitionNode/ActionNode 消息前缀以及 Starting/Succeeded/Failed 常量。
  • 扩展 NotificationHandlerRegistry.Node,添加针对新节点类型的嵌套注册表,包括事件和到强类型详情记录的 JSON 反序列化。
  • 在 NotificationHandlerRegistry.OnCallback 和 NotificationHandlerExtensions.ToCallback 中注册新的节点通知分支,实现统一的回调转换。
  • 新增 NodePipelineNodeDetail、NodeRecognitionNodeDetail 和 NodeActionNodeDetail 记录,并在 JsonSerializer 上下文中为它们注册条目。
src/MaaFramework.Binding/MaaMsg.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationHandlerRegistry.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationDetail.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationHandler.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationDetailContext.cs
将 NextList 通知载荷从字符串列表改为带 anchor/jump_back 元数据的结构化 NextListItem 记录列表。
  • 更新 MaaMsg.Node.NextList 的 XML 文档,描述包含 name、jump_back 和 anchor 字段的结构化列表条目。
  • 引入 NextListItem 记录,并将 NodeNextListDetail.list 属性类型切换为 IReadOnlyList<NextListItem>。
  • 在 NotificationDetailContext 中注册 NextListItem,以支持源生成的 JSON 序列化。
src/MaaFramework.Binding/MaaMsg.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationDetail.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationDetailContext.cs
暴露用于节点锚点和命中次数的新上下文 API,并将其绑定到原生 MaaContext interop 函数。
  • 在 IMaaContext 中扩展 SetAnchor、GetAnchor、GetHitCount 和 ClearHitCount 方法及其 XML 文档。
  • 在 MaaFramework.Binding.Native.MaaContext 中实现这些 IMaaContext 新方法,作为对原生 interop 调用的轻量封装,其中 GetAnchor 使用基于 MaaStringBuffer 的字符串获取。
  • 在 Interop/Framework/Instance/MaaContext.cs 中添加对应的 P/Invoke 签名:MaaContextSetAnchor、MaaContextGetAnchor、MaaContextGetHitCount 和 MaaContextClearHitCount。
src/MaaFramework.Binding/IMaaContext.cs
src/MaaFramework.Binding.Native/MaaContext.cs
src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaContext.cs
通过托管接口和原生 interop,从 Agent 客户端和资源对象中暴露自定义识别 / 动作列表。
  • 在 IMaaAgentClient 中扩展 CustomRecognitionList 和 CustomActionList 属性,并在 MaaAgentClient 中通过调用 MaaStringListBuffer.TryGetList 和相应的原生函数来实现。
  • 在 IMaaResource 中扩展 CustomRecognitionList 和 CustomActionList 属性,并在 MaaResource 中通过 MaaStringListBuffer.TryGetList 实现。
  • 在相应的 interop 类中添加 P/Invoke 签名 MaaAgentClientGetCustomRecognitionList/CustomActionList 和 MaaResourceGetCustomRecognitionList/CustomActionList。
src/MaaFramework.Binding/IMaaAgentClient.cs
src/MaaFramework.Binding.Native/MaaAgentClient.cs
src/MaaFramework.Binding.Native/Interop/AgentClient/MaaAgentClientAPI.cs
src/MaaFramework.Binding/IMaaResource.cs
src/MaaFramework.Binding.Native/MaaResource.cs
src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaResource.cs

技巧与命令

与 Sourcery 交互

  • 触发一次新的审查: 在 Pull Request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub Issue: 在某条审查评论下回复,请求 Sourcery 从该评论创建一个 issue。你也可以直接回复 @sourcery-ai issue,从该审查评论创建 issue。
  • 生成 Pull Request 标题: 在 Pull Request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。也可以在 Pull Request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 Pull Request 摘要: 在 Pull Request 正文任意位置写上 @sourcery-ai summary,可在指定位置生成 PR 摘要。也可以在 Pull Request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审查者指南: 在 Pull Request 中评论 @sourcery-ai guide,即可随时(重新)生成审查者指南。
  • 一次性解决所有 Sourcery 评论: 在 Pull Request 中评论 @sourcery-ai resolve,将所有 Sourcery 评论标记为已解决。如果你已经处理完所有评论且不想再看到它们,这非常有用。
  • 批量忽略所有 Sourcery 审查: 在 Pull Request 中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。此时如果你想重新开始一次新的审查,请记得再评论 @sourcery-ai review 触发新的审查!

自定义你的体验

访问你的 仪表盘 以:

  • 启用或禁用诸如 Sourcery 自动生成 PR 摘要、审查者指南等审查功能。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查指令。
  • 调整其他审查相关设置。

获取帮助

Original review guide in English

Reviewer's Guide

Syncs MaaFramework .NET bindings with MaaFW v5.1 by adding node-level notification types for pipeline/recognition/action nodes, enriching NextList payloads, exposing new context/agent/resource APIs (anchors, hit counts, and custom node lists), and wiring them through the interop, notification, and handler layers.

Sequence diagram for node pipeline notification handling

sequenceDiagram
    participant NativeFramework as Native_framework
    participant ManagedBinding as MaaCallback
    participant Registry as NotificationHandlerRegistry
    participant Nodes as NodeRegistry
    participant Pipeline as PipelineNodeRegistry
    participant UserHandler as User_subscriber

    NativeFramework->>ManagedBinding: MaaCallback(caller, message, details)
    ManagedBinding->>Registry: OnCallback(sender, MaaCallbackEventArgs)
    Registry->>Registry: switch Message
    Registry->>Nodes: Node.PipelineNode.OnStarting(sender, details)
    Nodes->>Pipeline: OnStarting(sender, details)
    Pipeline->>Pipeline: JsonSerializer.Deserialize(details, NodePipelineNodeDetail)
    Pipeline-->>UserHandler: Starting(sender, NodePipelineNodeDetail)
    activate UserHandler
    UserHandler-->>Pipeline: handle event
    deactivate UserHandler
Loading

Class diagram for new node notification messages and details

classDiagram
    namespace MaaMsg_Node {
        class Task_Node {
        }

        class Node_PipelineNode {
            <<static>>
            +string Starting
            +string Prefix
            +string Succeeded
            +string Failed
        }

        class Node_RecognitionNode {
            <<static>>
            +string Starting
            +string Prefix
            +string Succeeded
            +string Failed
        }

        class Node_ActionNode {
            <<static>>
            +string Starting
            +string Prefix
            +string Succeeded
            +string Failed
        }
    }

    namespace Notification_Detail {
        class NodePipelineNodeDetail {
            +int TaskId
            +int NodeId
            +string Name
            +JsonElement Focus
        }

        class NodeRecognitionNodeDetail {
            +int TaskId
            +int NodeId
            +string Name
            +JsonElement Focus
        }

        class NodeActionNodeDetail {
            +int TaskId
            +int NodeId
            +string Name
            +JsonElement Focus
        }

        class NextListItem {
            +string Name
            +bool JumpBack
            +bool Anchor
        }

        class NodeNextListDetail {
            +int TaskId
            +string Name
            +IReadOnlyList~NextListItem~ NextList
            +JsonElement Focus
        }
    }

    MaaMsg_Node.Node_PipelineNode ..> Notification_Detail.NodePipelineNodeDetail : details_json
    MaaMsg_Node.Node_RecognitionNode ..> Notification_Detail.NodeRecognitionNodeDetail : details_json
    MaaMsg_Node.Node_ActionNode ..> Notification_Detail.NodeActionNodeDetail : details_json
    Notification_Detail.NodeNextListDetail o--> Notification_Detail.NextListItem : list
Loading

Class diagram for notification handler registry extensions

classDiagram
    class NotificationHandlerRegistry {
        +OnCallback(object sender, MaaCallbackEventArgs e) void
        +NodeRegistry Node
    }

    class MaaCallbackEventArgs {
        +string Message
        +string Details
    }

    class NodeRegistry {
        +PipelineNodeRegistry PipelineNode
        +RecognitionNodeRegistry RecognitionNode
        +ActionNodeRegistry ActionNode
        +NextListRegistry NextList
    }

    class PipelineNodeRegistry {
        +event EventHandler~NodePipelineNodeDetail~ Starting
        +event EventHandler~NodePipelineNodeDetail~ Succeeded
        +event EventHandler~NodePipelineNodeDetail~ Failed
        +OnStarting(object sender, string details) void
        +OnSucceeded(object sender, string details) void
        +OnFailed(object sender, string details) void
    }

    class RecognitionNodeRegistry {
        +event EventHandler~NodeRecognitionNodeDetail~ Starting
        +event EventHandler~NodeRecognitionNodeDetail~ Succeeded
        +event EventHandler~NodeRecognitionNodeDetail~ Failed
        +OnStarting(object sender, string details) void
        +OnSucceeded(object sender, string details) void
        +OnFailed(object sender, string details) void
    }

    class ActionNodeRegistry {
        +event EventHandler~NodeActionNodeDetail~ Starting
        +event EventHandler~NodeActionNodeDetail~ Succeeded
        +event EventHandler~NodeActionNodeDetail~ Failed
        +OnStarting(object sender, string details) void
        +OnSucceeded(object sender, string details) void
        +OnFailed(object sender, string details) void
    }

    class NextListRegistry {
        +event EventHandler~NodeNextListDetail~ Starting
        +event EventHandler~NodeNextListDetail~ Succeeded
        +event EventHandler~NodeNextListDetail~ Failed
        +OnStarting(object sender, string details) void
        +OnSucceeded(object sender, string details) void
        +OnFailed(object sender, string details) void
    }

    class NotificationDetailContext {
        +NodePipelineNodeDetail NodePipelineNodeDetail
        +NodeRecognitionNodeDetail NodeRecognitionNodeDetail
        +NodeActionNodeDetail NodeActionNodeDetail
        +NextListItem NextListItem
        +NodeNextListDetail NodeNextListDetail
    }

    class NodePipelineNodeDetail
    class NodeRecognitionNodeDetail
    class NodeActionNodeDetail
    class NodeNextListDetail
    class NextListItem

    NotificationHandlerRegistry --> NodeRegistry : has
    NodeRegistry --> PipelineNodeRegistry : exposes
    NodeRegistry --> RecognitionNodeRegistry : exposes
    NodeRegistry --> ActionNodeRegistry : exposes
    NodeRegistry --> NextListRegistry : exposes

    PipelineNodeRegistry ..> NodePipelineNodeDetail : deserialize
    RecognitionNodeRegistry ..> NodeRecognitionNodeDetail : deserialize
    ActionNodeRegistry ..> NodeActionNodeDetail : deserialize
    NextListRegistry ..> NodeNextListDetail : deserialize

    PipelineNodeRegistry ..> NotificationDetailContext : uses
    RecognitionNodeRegistry ..> NotificationDetailContext : uses
    ActionNodeRegistry ..> NotificationDetailContext : uses
    NextListRegistry ..> NotificationDetailContext : uses
Loading

Class diagram for context, agent client, resource, and interop additions

classDiagram
    class IMaaContext {
        +IMaaContext Clone()
        +bool SetAnchor(string anchorName, string nodeName)
        +bool GetAnchor(string anchorName, out string nodeName)
        +bool GetHitCount(string nodeName, out ulong count)
        +bool ClearHitCount(string nodeName)
    }

    class MaaContext {
        +MaaContext Clone()
        +bool SetAnchor(string anchorName, string nodeName)
        +bool GetAnchor(string anchorName, out string nodeName)
        +bool GetHitCount(string nodeName, out ulong count)
        +bool ClearHitCount(string nodeName)
    }

    class MaaContextInterop {
        +MaaContextClone(MaaContextHandle context) MaaContextHandle
        +MaaContextSetAnchor(MaaContextHandle context, string anchorName, string nodeName) bool
        +MaaContextGetAnchor(MaaContextHandle context, string anchorName, MaaStringBufferHandle buffer) bool
        +MaaContextGetHitCount(MaaContextHandle context, string nodeName, MaaSize count) bool
        +MaaContextClearHitCount(MaaContextHandle context, string nodeName) bool
    }

    class IMaaAgentClient {
        +Process AgentServerProcess
        +IList~string~ CustomRecognitionList
        +IList~string~ CustomActionList
    }

    class MaaAgentClient {
        +Process AgentServerProcess
        +IList~string~ CustomRecognitionList
        +IList~string~ CustomActionList
    }

    class MaaAgentClientInterop {
        +MaaAgentClientGetCustomRecognitionList(MaaAgentClientHandle client, MaaStringListBufferHandle buffer) bool
        +MaaAgentClientGetCustomActionList(MaaAgentClientHandle client, MaaStringListBufferHandle buffer) bool
    }

    class IMaaResource {
        +IList~string~ NodeList
        +IList~string~ CustomRecognitionList
        +IList~string~ CustomActionList
    }

    class MaaResource {
        +IList~string~ NodeList
        +IList~string~ CustomRecognitionList
        +IList~string~ CustomActionList
    }

    class MaaResourceInterop {
        +MaaResourceGetNodeList(MaaResourceHandle res, MaaStringListBufferHandle buffer) bool
        +MaaResourceGetCustomRecognitionList(MaaResourceHandle res, MaaStringListBufferHandle buffer) bool
        +MaaResourceGetCustomActionList(MaaResourceHandle res, MaaStringListBufferHandle buffer) bool
    }

    class MaaStringBuffer {
        +TryGetValue(out string value, Func~MaaStringBufferHandle,bool~ invoker) bool
    }

    class MaaStringListBuffer {
        +TryGetList(out IList~string~ list, Func~MaaStringListBufferHandle,bool~ invoker) bool
    }

    IMaaContext <|.. MaaContext
    MaaContext ..> MaaContextInterop : calls
    MaaContext ..> MaaStringBuffer : uses

    IMaaAgentClient <|.. MaaAgentClient
    MaaAgentClient ..> MaaAgentClientInterop : calls
    MaaAgentClient ..> MaaStringListBuffer : uses

    IMaaResource <|.. MaaResource
    MaaResource ..> MaaResourceInterop : calls
    MaaResource ..> MaaStringListBuffer : uses
Loading

Flow diagram for NextList enriched payload

flowchart LR
    A_NodeNextListDetail["NodeNextListDetail
    task_id, name, focus"] --> B_List["list
    IReadOnlyList<NextListItem>"]

    B_List --> C_NextListItem["NextListItem
    name"]
    B_List --> D_JumpBack["NextListItem
    jump_back"]
    B_List --> E_Anchor["NextListItem
    anchor"]

    A_NodeNextListDetail --> F_Consumer["Next list consumer
    (notification handlers, user code)"]
Loading

File-Level Changes

Change Details Files
Add strongly-typed notification messages and handlers for pipeline, recognition, and action nodes.
  • Introduce MaaMsg.Node.PipelineNode/RecognitionNode/ActionNode message prefixes and Starting/Succeeded/Failed constants.
  • Extend NotificationHandlerRegistry.Node with nested registries for the new node types, including events and JSON deserialization to typed detail records.
  • Register new node notification cases in NotificationHandlerRegistry.OnCallback and NotificationHandlerExtensions.ToCallback for unified callback conversion.
  • Add NodePipelineNodeDetail, NodeRecognitionNodeDetail, and NodeActionNodeDetail records plus JsonSerializer context entries for them.
src/MaaFramework.Binding/MaaMsg.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationHandlerRegistry.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationDetail.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationHandler.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationDetailContext.cs
Change NextList notification payload from a list of strings to a structured list of NextListItem records with anchor/jump_back metadata.
  • Update MaaMsg.Node.NextList XML docs to describe structured list entries with name, jump_back, and anchor fields.
  • Introduce NextListItem record and switch NodeNextListDetail.list property type to IReadOnlyList.
  • Register NextListItem in NotificationDetailContext for source-generated JSON serialization.
src/MaaFramework.Binding/MaaMsg.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationDetail.cs
src/MaaFramework.Binding.Extensions/Notification/NotificationDetailContext.cs
Expose new context APIs for node anchors and hit counts and bind them to native MaaContext interop functions.
  • Extend IMaaContext with SetAnchor, GetAnchor, GetHitCount, and ClearHitCount methods and XML documentation.
  • Implement the new IMaaContext methods in MaaFramework.Binding.Native.MaaContext as thin wrappers around native interop calls, including MaaStringBuffer-based string retrieval for GetAnchor.
  • Add corresponding P/Invoke signatures MaaContextSetAnchor, MaaContextGetAnchor, MaaContextGetHitCount, and MaaContextClearHitCount in Interop/Framework/Instance/MaaContext.cs.
src/MaaFramework.Binding/IMaaContext.cs
src/MaaFramework.Binding.Native/MaaContext.cs
src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaContext.cs
Expose custom recognition/action lists from agent client and resource objects via managed interfaces and native interop.
  • Extend IMaaAgentClient with CustomRecognitionList and CustomActionList properties and implement them in MaaAgentClient using MaaStringListBuffer.TryGetList with the corresponding native calls.
  • Extend IMaaResource with CustomRecognitionList and CustomActionList properties and implement them in MaaResource using MaaStringListBuffer.TryGetList.
  • Add P/Invoke signatures MaaAgentClientGetCustomRecognitionList/CustomActionList and MaaResourceGetCustomRecognitionList/CustomActionList to their respective interop classes.
src/MaaFramework.Binding/IMaaAgentClient.cs
src/MaaFramework.Binding.Native/MaaAgentClient.cs
src/MaaFramework.Binding.Native/Interop/AgentClient/MaaAgentClientAPI.cs
src/MaaFramework.Binding/IMaaResource.cs
src/MaaFramework.Binding.Native/MaaResource.cs
src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaResource.cs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你好——我已经审阅了你的改动,这里有一些反馈:

  • 这三个节点明细记录(NodePipelineNodeDetailNodeRecognitionNodeDetailNodeActionNodeDetail)及其对应的 registry/handler 在结构上是完全相同的;可以考虑通过一个共享的 record 和/或泛型节点 registry 来进行抽象整合,以避免重复,并让后续对 schema 的修改可以集中在一个地方。
  • 对于 IMaaAgentClient/IMaaResource 上的 CustomRecognitionListCustomActionList,这些属性返回的是从底层 native 状态构建的新列表,但类型却是 IList<string>(这暗示修改该列表会影响底层的 agent/resource);可以考虑将其暴露为 IReadOnlyList<string>,或改为方法(例如 GetCustomRecognitionList()),以更好地体现其语义。
  • 在新的节点 registry 中,当 JsonSerializer.Deserialize 返回 null 时你会抛出 InvalidCastException;由于这其实是反序列化失败而不是类型转换问题,使用更具体的异常(例如 JsonExceptionInvalidDataException)会让调试更加容易,也更符合实际问题的性质。
给 AI Agent 的提示词
Please address the comments from this code review:

## Overall Comments
- The three node detail records (`NodePipelineNodeDetail`, `NodeRecognitionNodeDetail`, `NodeActionNodeDetail`) and their corresponding registries/handlers are structurally identical; consider consolidating them via a shared record and/or generic node registry to avoid duplication and keep future changes to the schema in one place.
- For `CustomRecognitionList` and `CustomActionList` on `IMaaAgentClient`/`IMaaResource`, the properties return a new list built from native state but are typed as `IList<string>` (suggesting mutability that affects the underlying agent/resource); consider exposing these as `IReadOnlyList<string>` or methods (e.g., `GetCustomRecognitionList()`) to better reflect their semantics.
- In the new node registries you throw `InvalidCastException` when `JsonSerializer.Deserialize` returns `null`; since this is a deserialization failure rather than a type-cast issue, a more specific exception (e.g., `JsonException` or `InvalidDataException`) would make debugging easier and better reflect the underlying problem.

Sourcery 对开源项目是免费的——如果你觉得我们的代码审查有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的代码审查。
Original comment in English

Hey there - I've reviewed your changes - here's some feedback:

  • The three node detail records (NodePipelineNodeDetail, NodeRecognitionNodeDetail, NodeActionNodeDetail) and their corresponding registries/handlers are structurally identical; consider consolidating them via a shared record and/or generic node registry to avoid duplication and keep future changes to the schema in one place.
  • For CustomRecognitionList and CustomActionList on IMaaAgentClient/IMaaResource, the properties return a new list built from native state but are typed as IList<string> (suggesting mutability that affects the underlying agent/resource); consider exposing these as IReadOnlyList<string> or methods (e.g., GetCustomRecognitionList()) to better reflect their semantics.
  • In the new node registries you throw InvalidCastException when JsonSerializer.Deserialize returns null; since this is a deserialization failure rather than a type-cast issue, a more specific exception (e.g., JsonException or InvalidDataException) would make debugging easier and better reflect the underlying problem.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The three node detail records (`NodePipelineNodeDetail`, `NodeRecognitionNodeDetail`, `NodeActionNodeDetail`) and their corresponding registries/handlers are structurally identical; consider consolidating them via a shared record and/or generic node registry to avoid duplication and keep future changes to the schema in one place.
- For `CustomRecognitionList` and `CustomActionList` on `IMaaAgentClient`/`IMaaResource`, the properties return a new list built from native state but are typed as `IList<string>` (suggesting mutability that affects the underlying agent/resource); consider exposing these as `IReadOnlyList<string>` or methods (e.g., `GetCustomRecognitionList()`) to better reflect their semantics.
- In the new node registries you throw `InvalidCastException` when `JsonSerializer.Deserialize` returns `null`; since this is a deserialization failure rather than a type-cast issue, a more specific exception (e.g., `JsonException` or `InvalidDataException`) would make debugging easier and better reflect the underlying problem.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR synchronizes the MaaFramework.Binding with MaaFW v5.1 interface changes, adding support for new node types, anchor/hit count management in pipeline contexts, and custom recognition/action list retrieval. The changes extend the callback notification system with three new node types (PipelineNode, RecognitionNode, ActionNode) while updating the NextList structure to include metadata about jump_back and anchor flags.

  • Adds three new node callback message types: PipelineNode, RecognitionNode, and ActionNode
  • Introduces anchor and hit count management methods to IMaaContext
  • Adds CustomRecognitionList and CustomActionList properties to IMaaResource and IMaaAgentClient

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/MaaFramework.Binding/MaaMsg.cs Defines new message constants for PipelineNode, RecognitionNode, and ActionNode; updates NextList JSON structure documentation
src/MaaFramework.Binding/IMaaResource.cs Adds CustomRecognitionList and CustomActionList property definitions
src/MaaFramework.Binding/IMaaContext.cs Adds anchor management (SetAnchor, GetAnchor) and hit count methods (GetHitCount, ClearHitCount)
src/MaaFramework.Binding/IMaaAgentClient.cs Adds CustomRecognitionList and CustomActionList property definitions
src/MaaFramework.Binding.Native/MaaResource.cs Implements CustomRecognitionList and CustomActionList properties
src/MaaFramework.Binding.Native/MaaContext.cs Implements anchor and hit count management methods
src/MaaFramework.Binding.Native/MaaAgentClient.cs Implements CustomRecognitionList and CustomActionList properties
src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaResource.cs Declares P/Invoke signatures for custom recognition/action list APIs
src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaContext.cs Declares P/Invoke signatures for anchor and hit count APIs
src/MaaFramework.Binding.Native/Interop/AgentClient/MaaAgentClientAPI.cs Declares P/Invoke signatures for agent client custom list APIs
src/MaaFramework.Binding.Extensions/Notification/NotificationHandlerRegistry.cs Adds handlers for new PipelineNode, RecognitionNode, and ActionNode events
src/MaaFramework.Binding.Extensions/Notification/NotificationHandler.cs Adds ToCallback extension methods for new node types
src/MaaFramework.Binding.Extensions/Notification/NotificationDetailContext.cs Registers new detail types for JSON serialization
src/MaaFramework.Binding.Extensions/Notification/NotificationDetail.cs Defines new record types for node details and NextListItem structure

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@moomiji
Copy link
Member

moomiji commented Nov 29, 2025

LGTM

@moomiji moomiji merged commit 7fdaae6 into main Nov 29, 2025
5 of 7 checks passed
@moomiji moomiji deleted the feat/maafw_5.1 branch November 29, 2025 14:59
@moomiji moomiji mentioned this pull request Dec 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants