Skip to content

新增钓鱼 task,大量修改配置与格式#228

Open
op200 wants to merge 7 commits into
1bananachicken:devfrom
op200:dev
Open

新增钓鱼 task,大量修改配置与格式#228
op200 wants to merge 7 commits into
1bananachicken:devfrom
op200:dev

Conversation

@op200
Copy link
Copy Markdown

@op200 op200 commented May 27, 2026

Summary by Sourcery

添加增强的自动钓鱼任务及其配套工具,现代化 Python 类型标注和工具链,并优化构建、CI 与开发配置。

New Features:

  • 引入新的分叉版自动钓鱼自定义动作,支持可配置行为,并提供专用的流水线定义。
  • 添加用于 Windows 虚拟按键处理的共享工具,以及支持自定义动作的通用运行时类型检查工具。

Enhancements:

  • 使用更新的类型标注语法、清理导入、简化部分控制流,对代理动作和工具模块进行 Python 代码现代化改造。
  • 优化代理启动、节奏控制、俄罗斯方块、声音触发以及数据集采集等动作的日志与诊断信息,以提升可调试性。
  • 重新组织自定义动作的导出,确保可用动作保持一致并具有明确的顺序。
  • 调整构建和依赖配置,包括 Python embed 设置、maafw 版本约束,以及基于 pnpm 的前端工具链。
  • 采用 Ruff 作为 Python 的 linter/formatter,并提供项目级配置文件。

Build:

  • 更新嵌入式 Python 设置,目标版本调至 Python 3.14.5,并在 CI 脚本中统一平台处理逻辑。
  • 将 Node 工具链切换为 pnpm,更新开发依赖并移除未使用的 Prettier 插件。

CI:

  • 将 GitHub Actions 的 checkout 动作版本提升到 v6,并收紧安装流程步骤,用于依赖准备和发布创建。
  • 优化 git-cliff 配置,实现更细粒度的 conventional-commit 分组,并包含完整的提交正文。

Documentation:

  • 修改 README 中的开发指南,澄清 fork 流程、携带子模块的克隆方式、环境搭建步骤以及 MaaFramework 依赖处理方式。

Chores:

  • 添加 Ruff 配置,启用更广泛的静态检查,同时根据项目特点定制忽略规则。
Original summary in English

Summary by Sourcery

Add an enhanced automated fishing task and supporting utilities, modernize Python typing and tooling, and refine build, CI, and development configuration.

New Features:

  • Introduce a new forked auto-fishing custom action with configurable behavior and a dedicated pipeline definition.
  • Add shared utilities for Windows virtual key handling and generic runtime type checking to support custom actions.

Enhancements:

  • Modernize Python codebase with newer typing syntax, import cleanup, and minor control-flow simplifications across agent actions and utilities.
  • Refine logging and diagnostics for agent startup, rhythm, Tetris, sound trigger, and dataset collection actions to improve debuggability.
  • Reorganize custom action exports to keep available actions consistent and explicitly ordered.
  • Adjust build and dependency configuration, including Python embed setup, maafw version constraint, and pnpm-based frontend tooling.
  • Adopt Ruff as the Python linter/formatter with a project-wide configuration file.

Build:

  • Update embedded Python setup to target Python 3.14.5 and align platform handling in CI scripts.
  • Switch Node tooling to pnpm with updated dev dependencies and remove unused Prettier plugins.

CI:

  • Bump GitHub Actions checkout versions to v6 and tighten install workflow steps for dependency preparation and release creation.
  • Refine git-cliff configuration for more granular conventional-commit grouping and full commit body inclusion.

Documentation:

  • Revise the development guide in the README to clarify forking, cloning with submodules, environment setup, and MaaFramework dependency handling.

Chores:

  • Add Ruff configuration and enable broader static checks while tailoring ignore rules to the project.

op200 added 5 commits May 28, 2026 02:40
feat: 增加 task `钓鱼 分支 2`
fix: 修复部分代码 bug
ci: 修改打包 Python 版本为 `3.14.5`
ci: 修改 `cliff.toml`
perf: 移除非必要依赖
doc: 修正 readme 中对 Python 版本的指定错误
开发: 修改并统一代码格式化器,增加 `.ruff` 用于 Python 代码规范检查
doc: update readme 开发指南
开发: 增加 toml 格式化插件,修复上次提交误删的 json 保存时自动格式化选项
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 27, 2026

Reviewer's Guide

新增一个更高级的自动钓鱼任务(fish_fork_2),包含其独立的管线和共享工具模块,同时广泛重构 Python 代码风格与类型标注,更新工具链/配置(ruff、CI、构建脚本、包管理器),并改进若干自定义动作以及 i18n/构建工作流。

Fish_fork_2 自动钓鱼运行时循环时序图

sequenceDiagram
    participant User
    participant Fish_fork_2
    participant Context
    participant Tasker
    participant Controller

    User->>Fish_fork_2: invoke run(context, argv)
    Fish_fork_2->>Context: get_node_object(argv.node_name)
    Context-->>Fish_fork_2: node_object.attach
    Fish_fork_2->>Fish_fork_2: get_option(attach) -> Fish_option

    loop fishing loop
        Fish_fork_2->>Tasker: check Tasker.stopping
        alt 终止时间 reached
            Fish_fork_2-->>User: success True
            Fish_fork_2-->>Fish_fork_2: break
        end

        Fish_fork_2->>Tasker: tasker.controller
        Tasker-->>Fish_fork_2: Controller
        Fish_fork_2->>Controller: post_screencap().get()
        Controller-->>Fish_fork_2: img

        Fish_fork_2->>Context: reco_上鱼(img) via run_recognition
        alt 上鱼 detected
            Fish_fork_2->>Controller: 溜鱼(): post_key_down(A or D)
            Controller-->>Fish_fork_2: done
            Fish_fork_2->>Controller: post_screencap().get()
            Controller-->>Fish_fork_2: img
        end

        Fish_fork_2->>Context: reco_获鱼(img)
        alt 获鱼 detected
            Fish_fork_2->>Controller: post_click_key(VK_ESCAPE)
            Controller-->>Fish_fork_2: done
            Fish_fork_2-->>Fish_fork_2: continue
        end

        Fish_fork_2->>Context: reco_满舱_or_无饵(img)
        alt 渔获已满 or 鱼饵用完
            alt 卖鱼买换饵开关 == False
                Fish_fork_2-->>User: success True
                Fish_fork_2-->>Fish_fork_2: break
            else 卖鱼买换饵开关 == True
                Fish_fork_2->>Context: 卖鱼买换饵(买饵次数)
                Context-->>Fish_fork_2: bool ok
                alt not ok
                    Fish_fork_2-->>User: success False
                    Fish_fork_2-->>Fish_fork_2: break
                end
                Fish_fork_2-->>Fish_fork_2: continue
            end
        end

        Fish_fork_2->>Context: reco_钓鱼按钮(img)
        alt 钓鱼按钮 detected
            Fish_fork_2->>Controller: post_click_key(F)
            Controller-->>Fish_fork_2: done
            Fish_fork_2->>Fish_fork_2: fail_num = 0
        else none detected
            Fish_fork_2->>Controller: post_click_key(F)
            Fish_fork_2->>Fish_fork_2: fail_num++
            alt fail_num > FISH_RECO_FIAL_NUM_MAX
                Fish_fork_2-->>User: success False
                Fish_fork_2-->>Fish_fork_2: break
            end
        end
    end
Loading

File-Level Changes

Change Details Files
引入新的自动钓鱼实现 fish_fork_2,以及用于 Windows 虚拟按键和运行时类型检查的辅助工具。
  • 新增 agent/custom/action/AutoFish/auto_fish_fork_2.py,实现基于 OCR 状态检测的全新钓鱼状态机,从 node.attach 读取可配置选项,并支持自动买饵/卖鱼流程。
  • 新增 agent/utils/virtual_key.py,定义丰富的 Win_virtual_key 枚举封装,用于表示 Windows 虚拟按键码,并在新的钓鱼逻辑中广泛使用。
  • 新增 agent/utils/py_tools.py,提供 type_match 辅助函数,用于在运行时校验泛型集合(例如 OCRResult 序列)的类型。
  • 通过更新导入/__all__ 将新动作接入 action 包,并新增 Fish 管线 JSON(assets/resource/base/pipeline/Fish/FishFork2.json)以及任务/配置条目(assets/resource/tasks/Fish.jsoninterface.json 变更)。
agent/custom/action/AutoFish/auto_fish_fork_2.py
agent/utils/virtual_key.py
agent/utils/py_tools.py
agent/custom/action/__init__.py
assets/resource/base/pipeline/Fish/FishFork2.json
assets/resource/tasks/Fish.json
assets/interface.json
现代化 agent/custom 动作和工具中的 Python 类型标注、结构与日志记录,提升可读性与健壮性。
  • 在多处模块中,将旧的 typing 别名(List、Dict、Optional、Union、Tuple、Callable 等)替换为 PEP 604/585 风格(如 list[str]dict[...]X | Nonecollections.abc.Callable)。
  • 优化 agent 入口文件(agent/main.py)中的日志信息和错误流程,包括更好的 ImportError 追踪,以及更清晰的信息/警告文案。
  • 重构多个自定义动作(AutoFish、节奏/rhythm、SoundTrigger、Movement、dataset recorder、realtime_task、click、Tetris 等),改进控制流(使用提前返回替代多层嵌套 else)、统一导入风格,并整理过长的表达式/格式化字符串。
  • 调整配置辅助模块(agent/utils/pienv.pymaafocus.pylogger.py、i18n)以及 __all__ 导出顺序,使其更清晰并更易通过 lint 检查。
tools/i18n/sync_ocr_expected.py
agent/main.py
agent/custom/action/AutoFish/auto_fish.py
agent/custom/action/AutoFish/auto_buy_fish_bait.py
agent/custom/action/AutoFish/auto_fish_withoutCV.py
agent/custom/action/AutoFish/auto_sell_fish.py
agent/custom/action/rhythm/utils/song_selector.py
agent/custom/action/rhythm/utils/detector.py
agent/custom/action/rhythm/utils/config.py
agent/custom/action/rhythm/utils/lanes.py
agent/custom/action/rhythm/utils/presence.py
agent/custom/action/rhythm/feats/play.py
agent/custom/action/rhythm/feats/select_song.py
agent/custom/action/rhythm/feats/repeat_decision.py
agent/custom/action/rhythm/__init__.py
agent/custom/action/rhythm/feats/__init__.py
agent/custom/action/rhythm/utils/__init__.py
agent/custom/action/Common/click.py
agent/custom/action/Common/utils.py
agent/custom/action/Common/alt_click.py
agent/custom/action/Common/logger.py
agent/custom/action/realtime_task.py
agent/custom/action/Movement/mouse_move.py
agent/custom/action/Movement/character_move.py
agent/custom/action/Movement/__init__.py
agent/custom/action/SoundTrigger/DodgeCounterTrigger.py
agent/custom/action/SoundTrigger/SoundDodgeAction.py
agent/custom/action/SoundTrigger/SoundListener.py
agent/custom/action/SoundTrigger/__init__.py
agent/custom/action/Tetris/feats/play.py
agent/custom/action/Tetris/utils/scene_detector.py
agent/custom/action/auto_tetris.py
agent/custom/action/auto_make_coffee.py
agent/custom/action/auto_piano/action.py
agent/custom/action/auto_piano/maa_keyboard.py
agent/custom/action/auto_piano/player.py
agent/custom/action/furniture_claim.py
agent/custom/action/pinkpaw/pinkpaw_core1.py
agent/custom/action/pinkpaw/pinkpaw_core2.py
agent/custom/action/pinkpaw/pinkpaw_reward_logger.py
agent/custom/action/withdraw_money_choose_item.py
agent/custom/action/DatasetCollection/autonomous_driving_dataset_recorder.py
agent/custom/__init__.py
agent/utils/pienv.py
agent/utils/maafocus.py
agent/utils/logger.py
agent/utils/screen.py
agent/utils/__init__.py
agent/utils/i18n.py
更新构建、CI、工具链与打包配置(Python 版本、lint、changelog、GitHub Actions 和 JS 工具)。
  • tools/ci/setup_embed_python.py 中将内嵌 Python 目标版本提升到 3.14.5,并更新 python-build-standalone 标签,同时做了少量逻辑简化。
  • 新增 ruff.toml,提供全面的 lint 配置,并相应更新代码风格(如导入顺序、换行样式、target-version=py314)。
  • 更新 GitHub Actions workflow,使其使用较新的 actions/checkout@v6,并调整安装/构建步骤,同时在 .github/cliff.toml 中修改 changelog 配置(提交分组、解析行为)。
  • 将 Node 工具链切换为 pnpm,通过 packageManager 字段声明,更新开发依赖和锁文件(package.jsonpnpm-lock.yaml),并删除未使用的 Prettier/multiline-arrays 配置文件。
  • 微调 CI 辅助脚本(tools/ci/install_mxu.pytools/ci/configure.pytools/ci/download_deps.pytools/ci/install_mxu.py)以及构建脚本 build.py 的格式与参数解析,使其更一致。
tools/ci/setup_embed_python.py
tools/ci/install_mxu.py
tools/ci/configure.py
tools/ci/download_deps.py
build.py
.github/cliff.toml
.github/workflows/install.yml
.github/workflows/i18n-sync.yml
.github/workflows/sync_schema_files.yml
package.json
pnpm-lock.yaml
.prettierrc
.vscode/extensions.json
.vscode/settings.json
ruff.toml
调整依赖版本与 requirements 以匹配新的运行时/工具链要求。
  • 将 MaaFramework Python 包依赖从固定的 maafw==v5.10.4 放宽/提升为 maafw>=5.10.5,并依赖 scipy 的 numpy 依赖,而不再单独固定 numpy 版本。
  • 基本保持 requirements.txt 中其他 Python 依赖不变,但使其与新的 Python 版本和 ruff 设置保持一致。
requirements.txt
改进项目文档和元数据,以便贡献者参与开发和发布。
  • 重写 README 开发指南,明确 fork/clone 步骤、环境搭建、MaaFramework 依赖处理以及 VSCode 插件推荐。
  • 调整 Git-cliff 配置,细化提交分组、约定式提交标志以及 changelog 自动化的跳过规则。
  • 新增/调整编辑器配置文件(.vscode/*.json),并在工具链清理中删除废弃配置。
README.md
.github/cliff.toml
.vscode/extensions.json
.vscode/settings.json

Possibly linked issues

  • #:Issue 报告新的钓鱼任务不会按 F;本 PR 引入新的钓鱼任务(FishFork2)并调整钓鱼逻辑以修复该问题。
  • #:本 PR 中新的 FishFork2 逻辑在鱼饵用尽时会卖鱼并购买鱼饵,从而修复自动卖鱼不执行的问题。
  • #钓鱼任务无法使用:本 PR 新增 Fish_fork_2 自动钓鱼自定义动作和管线配置,修复“钓鱼任务无法使用”的问题。

Tips and commands

Interacting with 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 触发新审查!

Customizing Your Experience

前往你的 dashboard 以:

  • 启用或禁用审查功能,例如 Sourcery 自动生成的 pull request 总结、审查者指南等。
  • 修改审查语言。
  • 添加、删除或编辑自定义审查指令。
  • 调整其他审查相关设置。

Getting Help

Original review guide in English

Reviewer's Guide

Adds a new, more advanced auto fishing task (fish_fork_2) with its own pipeline and shared utilities, while broadly refactoring Python code style/type hints, updating tooling/config (ruff, CI, build scripts, package manager), and improving various custom actions and i18n/build workflows.

Sequence diagram for Fish_fork_2 auto fishing runtime loop

sequenceDiagram
    participant User
    participant Fish_fork_2
    participant Context
    participant Tasker
    participant Controller

    User->>Fish_fork_2: invoke run(context, argv)
    Fish_fork_2->>Context: get_node_object(argv.node_name)
    Context-->>Fish_fork_2: node_object.attach
    Fish_fork_2->>Fish_fork_2: get_option(attach) -> Fish_option

    loop fishing loop
        Fish_fork_2->>Tasker: check Tasker.stopping
        alt 终止时间 reached
            Fish_fork_2-->>User: success True
            Fish_fork_2-->>Fish_fork_2: break
        end

        Fish_fork_2->>Tasker: tasker.controller
        Tasker-->>Fish_fork_2: Controller
        Fish_fork_2->>Controller: post_screencap().get()
        Controller-->>Fish_fork_2: img

        Fish_fork_2->>Context: reco_上鱼(img) via run_recognition
        alt 上鱼 detected
            Fish_fork_2->>Controller: 溜鱼(): post_key_down(A or D)
            Controller-->>Fish_fork_2: done
            Fish_fork_2->>Controller: post_screencap().get()
            Controller-->>Fish_fork_2: img
        end

        Fish_fork_2->>Context: reco_获鱼(img)
        alt 获鱼 detected
            Fish_fork_2->>Controller: post_click_key(VK_ESCAPE)
            Controller-->>Fish_fork_2: done
            Fish_fork_2-->>Fish_fork_2: continue
        end

        Fish_fork_2->>Context: reco_满舱_or_无饵(img)
        alt 渔获已满 or 鱼饵用完
            alt 卖鱼买换饵开关 == False
                Fish_fork_2-->>User: success True
                Fish_fork_2-->>Fish_fork_2: break
            else 卖鱼买换饵开关 == True
                Fish_fork_2->>Context: 卖鱼买换饵(买饵次数)
                Context-->>Fish_fork_2: bool ok
                alt not ok
                    Fish_fork_2-->>User: success False
                    Fish_fork_2-->>Fish_fork_2: break
                end
                Fish_fork_2-->>Fish_fork_2: continue
            end
        end

        Fish_fork_2->>Context: reco_钓鱼按钮(img)
        alt 钓鱼按钮 detected
            Fish_fork_2->>Controller: post_click_key(F)
            Controller-->>Fish_fork_2: done
            Fish_fork_2->>Fish_fork_2: fail_num = 0
        else none detected
            Fish_fork_2->>Controller: post_click_key(F)
            Fish_fork_2->>Fish_fork_2: fail_num++
            alt fail_num > FISH_RECO_FIAL_NUM_MAX
                Fish_fork_2-->>User: success False
                Fish_fork_2-->>Fish_fork_2: break
            end
        end
    end
Loading

File-Level Changes

Change Details Files
Introduce new AutoFish implementation fish_fork_2 and supporting utilities for Windows virtual keys and runtime type checking.
  • Add agent/custom/action/AutoFish/auto_fish_fork_2.py implementing a new fishing state machine with OCR-based state detection, configurable options from node.attach, and automated bait buying/selling flow.
  • Add agent/utils/virtual_key.py defining a rich Win_virtual_key enum wrapper for Windows virtual key codes, used throughout the new fishing logic.
  • Add agent/utils/py_tools.py with a type_match helper to validate runtime types for generic collections (e.g., OCRResult sequences).
  • Wire the new action into the action package via updated imports/__all__ and add a new Fish pipeline JSON (assets/resource/base/pipeline/Fish/FishFork2.json) plus task/config entries (assets/resource/tasks/Fish.json, interface.json changes).
agent/custom/action/AutoFish/auto_fish_fork_2.py
agent/utils/virtual_key.py
agent/utils/py_tools.py
agent/custom/action/__init__.py
assets/resource/base/pipeline/Fish/FishFork2.json
assets/resource/tasks/Fish.json
assets/interface.json
Modernize Python typing, structure, and logging across agent/custom actions and utilities to improve readability and robustness.
  • Replace legacy typing aliases (List, Dict, Optional, Union, Tuple, Callable, Optional) with PEP 604/585 style (list[str], dict[...], `X
None, collections.abc.Callable) across many modules.</li><li>Refine logging messages and error flows in agent entrypoint (agent/main.py), including better ImportError tracing and clearer info/warning text.</li><li>Refactor various custom actions (AutoFish, rhythm, SoundTrigger, Movement, dataset recorder, realtime_task, click, Tetris, etc.) to improve control flow (early returns instead of nested else), use consistent imports, and tidy long expressions/format strings.</li><li>Adjust configuration helpers (agent/utils/pienv.py, maafocus.py, logger.py, i18n) and all` exports ordering for clarity and lint-friendliness.
Update build, CI, tooling, and packaging configuration (Python version, linting, changelog, GitHub Actions, and JS tooling).
  • Bump embedded Python target to 3.14.5 and update python-build-standalone tag in tools/ci/setup_embed_python.py, with minor logic simplifications.
  • Introduce ruff.toml with a comprehensive lint configuration and update code style accordingly (e.g., import order, line breaks, target-version=py314).
  • Update GitHub Actions workflows to use newer actions/checkout@v6 and adjust install/build steps, plus changelog configuration changes in .github/cliff.toml (commit groups, parser behavior).
  • Switch Node tooling to pnpm with packageManager field, update dev deps and lockfile (package.json, pnpm-lock.yaml), and drop unused Prettier/multiline-arrays config stubs.
  • Tweak CI helper scripts (tools/ci/install_mxu.py, tools/ci/configure.py, tools/ci/download_deps.py, tools/ci/install_mxu.py) and build script build.py formatting/arg parsing for consistency.
tools/ci/setup_embed_python.py
tools/ci/install_mxu.py
tools/ci/configure.py
tools/ci/download_deps.py
build.py
.github/cliff.toml
.github/workflows/install.yml
.github/workflows/i18n-sync.yml
.github/workflows/sync_schema_files.yml
package.json
pnpm-lock.yaml
.prettierrc
.vscode/extensions.json
.vscode/settings.json
ruff.toml
Adjust dependency versions and requirements to match new runtime/tooling expectations.
  • Relax/raise MaaFramework Python package requirement from fixed maafw==v5.10.4 to maafw>=5.10.5 and rely on scipy’s numpy dependency rather than pinning numpy directly.
  • Keep other Python deps in requirements.txt largely unchanged, but align them with the new Python version and ruff settings.
requirements.txt
Improve project documentation and metadata for contributors and releases.
  • Rework README development guide, clarifying fork/clone steps, environment setup, MaaFramework dependency handling, and VSCode plugin recommendations.
  • Adjust Git-cliff configuration to refine commit grouping, conventional commit flags, and skip rules for changelog automation.
  • Add/adjust editor config files (.vscode/*.json) and remove obsolete ones as part of tooling cleanup.
README.md
.github/cliff.toml
.vscode/extensions.json
.vscode/settings.json

Possibly linked issues

  • #: Issue reports new fishing task not pressing F; PR introduces a new fishing task (FishFork2) and fishing logic changes to address it.
  • #: PR’s new FishFork2 logic sells fish and buys bait when bait is empty, fixing auto-sell not executing.
  • #钓鱼任务无法使用: PR新增 Fish_fork_2 自动钓鱼自定义动作和管线配置,修复“钓鱼任务无法使用”的问题。

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
Copy Markdown

@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.

Hey - 我发现了 1 个安全问题、3 个其他问题,并留下了一些总体反馈:

Security issues:

  • 检测到对子进程函数 run 的调用,其参数不是静态字符串。如果这些数据可能被恶意行为者控制,这可能会造成命令注入风险。请审计该调用的使用方式,确保其参数不能被外部资源控制。你可以考虑使用 shlex.escape()。(link)

General comments:

  • 新增的 Fish_fork_2 自定义动作声明为 run(...)-> bool,并且当前直接返回 True/False,但 Maa 的自定义动作预期返回 CustomAction.RunResult;这会破坏动作约定,应修改为始终返回 RunResult(包括 Manual_stop 分支路径中)。
  • utils/py_tools.py 中的辅助函数 type_match 在很多情况下会回退为 True(并且没有正确处理 get_origintypes.UnionTypeX | Y 联合类型),这意味着它会在类型不匹配时静默通过。建议将默认分支改为返回 False,并为 Union/types.UnionType 添加显式处理逻辑,使检查能够真正捕获不正确的结构。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `Fish_fork_2` custom action declares `run(...)-> bool` and currently returns plain `True`/`False`, but Maa custom actions are expected to return `CustomAction.RunResult`; this will break the action contract and should be updated to return `RunResult` consistently (including in the `Manual_stop` path).
- The helper `type_match` in `utils/py_tools.py` falls back to `True` for many cases (and does not correctly handle `X | Y` unions where `get_origin` is `types.UnionType`), which means it can silently accept mismatched types; consider making the default branch return `False` and adding explicit handling for `Union`/`types.UnionType` so the checks actually catch incorrect structures.

## Individual Comments

### Comment 1
<location path="agent/custom/action/AutoFish/auto_fish_fork_2.py" line_range="33" />
<code_context>
+    pass
+
+
+type Img = np.typing.NDArray
+
+
</code_context>
<issue_to_address>
**issue (bug_risk):** np is only imported under TYPE_CHECKING, so this type alias will raise NameError at import time

To avoid this, either import the type directly at runtime (e.g. `from numpy.typing import NDArray` and use `type Img = NDArray`), or move the alias into the `TYPE_CHECKING` block and only reference it in type-only contexts (e.g. `if TYPE_CHECKING` or string annotations).
</issue_to_address>

### Comment 2
<location path="agent/custom/action/AutoFish/auto_fish_fork_2.py" line_range="500-507" />
<code_context>
+FISH_RECO_FIAL_NUM_MAX = 50
+
+
+@AgentServer.custom_action("fish_fork_2")
+class Fish_fork_2(CustomAction):
+    @override
+    def run(
+        self,
+        context: Context,
+        argv: CustomAction.RunArg,
+    ) -> bool:
+        option: Fish_option = get_option(context, argv)
+        logger.debug(f"{option=}")
</code_context>
<issue_to_address>
**issue (bug_risk):** CustomAction.run should return a RunResult, not a bare bool

`Fish_fork_2.run` is typed to return `bool` and currently returns raw `True`/`False`, but callers (and the Maa API) expect `CustomAction.RunResult`. This mismatch will likely break or confuse the caller. Please update the signature to `-> CustomAction.RunResult` and return `CustomAction.RunResult(success=True/False, ...)` consistently, aligned with other custom actions.
</issue_to_address>

### Comment 3
<location path="agent/utils/py_tools.py" line_range="4-13" />
<code_context>
+def type_match[T](val: Any, t: type[T]) -> TypeGuard[T]:
</code_context>
<issue_to_address>
**suggestion (bug_risk):** type_match’s Union handling and fallback behavior are looser than the docstring suggests

The docstring advertises support for Union/PEP 604 unions and nested generics, but the implementation only checks `typing.Union` via `t_org.__name__ == "Union"`. For `T1 | T2`, `get_origin` returns `types.UnionType`, so this case is missed and the function falls through to `return True`, even when the value doesn’t match. Likewise, for generics whose origins are in `collections.abc`, once the outer `isinstance` passes, element types are never validated. This makes the function a shallow check, not the deeper validator the docstring suggests. I’d recommend either handling `types.UnionType` and relevant `collections.abc` origins explicitly, or updating the docstring to describe the current shallow behavior more accurately.

Suggested implementation:

```python
from typing import Any, TypeGuard, get_args, get_origin
from types import UnionType
from collections.abc import Mapping, Sequence, Set as AbstractSet

```

```python
def type_match[T](val: Any, t: type[T]) -> TypeGuard[T]:
    """
    检查值是否匹配给定的类型(支持泛型,包含常见容器的“深度”检查)

    支持的类型包括:
    - 基本类型: int, str, list, dict, tuple, set
    - 泛型类型: list[str], dict[str, int], tuple[int, ...]
    - 联合类型: int | str, Union[int, str]
    - 可选类型: Optional[str] (Union[str, None] 形式)
    - 嵌套泛型: list[list[str]], dict[str, list[int]]
    - collections.abc 中的常见容器: Sequence[T], Mapping[K, V], Set[T] 等

    对于上述容器类型,会递归检查其内部元素是否满足对应的类型参数。
    """

    # Any 始终视为匹配
    if t is Any:
        return True  # type: ignore[return-value]

    origin = get_origin(t)
    args = get_args(t)

    # 处理 Union / PEP 604 联合类型 (T1 | T2)
    # - 对于 typing.Union[...] 和 T1 | T2,get_origin(...) 在 3.10+ 通常为 types.UnionType
    # - 额外使用 isinstance(t, UnionType) 兜底 PEP 604 形式
    if origin is UnionType or isinstance(t, UnionType):
        # Optional[T] 等价于 Union[T, None]
        for sub_t in args:
            if type_match(val, sub_t):
                return True  # type: ignore[return-value]
        return False  # type: ignore[return-value]

    # 无 origin,按普通类型处理
    if origin is None:
        try:
            return isinstance(val, t)  # type: ignore[arg-type,return-value]
        except TypeError:
            # 一些 typing 构造在某些版本下不支持直接 isinstance
            return False  # type: ignore[return-value]

    # 处理 Sequence[T] / list[T] 等序列类型(不包括 str/bytes)
    if origin in (list, Sequence):
        elem_type = args[0] if args else Any
        if not isinstance(val, Sequence) or isinstance(val, (str, bytes, bytearray)):
            return False  # type: ignore[return-value]
        return all(type_match(item, elem_type) for item in val)  # type: ignore[return-value]

    # 处理 Set[T] / set[T]
    if origin in (set, AbstractSet):
        elem_type = args[0] if args else Any
        if not isinstance(val, AbstractSet) or isinstance(val, (str, bytes, bytearray)):
            return False  # type: ignore[return-value]
        return all(type_match(item, elem_type) for item in val)  # type: ignore[return-value]

    # 处理 Mapping[K, V] / dict[K, V]
    if origin in (dict, Mapping):
        key_type = args[0] if len(args) > 0 else Any
        value_type = args[1] if len(args) > 1 else Any
        if not isinstance(val, Mapping):
            return False  # type: ignore[return-value]
        return all(
            type_match(k, key_type) and type_match(v, value_type)
            for k, v in val.items()
        )  # type: ignore[return-value]

    # 处理 tuple[...]:
    # - 固定长度: tuple[int, str]
    # - 可变长度: tuple[int, ...]
    if origin is tuple:
        if not isinstance(val, tuple):
            return False  # type: ignore[return-value]

        if not args:
            return True  # type: ignore[return-value]  # 无元素约束

        # 可变长度: tuple[T, ...]
        if len(args) == 2 and args[1] is Ellipsis:
            elem_type = args[0]
            return all(type_match(item, elem_type) for item in val)  # type: ignore[return-value]

        # 固定长度: tuple[T1, T2, ...]
        if len(val) != len(args):
            return False  # type: ignore[return-value]
        return all(type_match(item, sub_t) for item, sub_t in zip(val, args))  # type: ignore[return-value]

    # 其他有 origin 的泛型,先按其 origin 做浅检查
    try:
        if not isinstance(val, origin):  # type: ignore[arg-type]
            return False  # type: ignore[return-value]
    except TypeError:
        # 无法用于 isinstance 的 origin
        return False  # type: ignore[return-value]

    # 默认:对未显式支持的泛型,不做深度检查,仅检查外层类型
    return True  # type: ignore[return-value]

```
</issue_to_address>

### Comment 4
<location path="build.py" line_range="76" />
<code_context>
    result = subprocess.run(cmd, cwd=cwd or ROOT, capture_output=True, text=True)
</code_context>
<issue_to_address>
**security (python.lang.security.audit.dangerous-subprocess-use-audit):** Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

*Source: opengrep*
</issue_to_address>

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

Hey - I've found 1 security issue, 3 other issues, and left some high level feedback:

Security issues:

  • Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'. (link)

General comments:

  • The new Fish_fork_2 custom action declares run(...)-> bool and currently returns plain True/False, but Maa custom actions are expected to return CustomAction.RunResult; this will break the action contract and should be updated to return RunResult consistently (including in the Manual_stop path).
  • The helper type_match in utils/py_tools.py falls back to True for many cases (and does not correctly handle X | Y unions where get_origin is types.UnionType), which means it can silently accept mismatched types; consider making the default branch return False and adding explicit handling for Union/types.UnionType so the checks actually catch incorrect structures.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `Fish_fork_2` custom action declares `run(...)-> bool` and currently returns plain `True`/`False`, but Maa custom actions are expected to return `CustomAction.RunResult`; this will break the action contract and should be updated to return `RunResult` consistently (including in the `Manual_stop` path).
- The helper `type_match` in `utils/py_tools.py` falls back to `True` for many cases (and does not correctly handle `X | Y` unions where `get_origin` is `types.UnionType`), which means it can silently accept mismatched types; consider making the default branch return `False` and adding explicit handling for `Union`/`types.UnionType` so the checks actually catch incorrect structures.

## Individual Comments

### Comment 1
<location path="agent/custom/action/AutoFish/auto_fish_fork_2.py" line_range="33" />
<code_context>
+    pass
+
+
+type Img = np.typing.NDArray
+
+
</code_context>
<issue_to_address>
**issue (bug_risk):** np is only imported under TYPE_CHECKING, so this type alias will raise NameError at import time

To avoid this, either import the type directly at runtime (e.g. `from numpy.typing import NDArray` and use `type Img = NDArray`), or move the alias into the `TYPE_CHECKING` block and only reference it in type-only contexts (e.g. `if TYPE_CHECKING` or string annotations).
</issue_to_address>

### Comment 2
<location path="agent/custom/action/AutoFish/auto_fish_fork_2.py" line_range="500-507" />
<code_context>
+FISH_RECO_FIAL_NUM_MAX = 50
+
+
+@AgentServer.custom_action("fish_fork_2")
+class Fish_fork_2(CustomAction):
+    @override
+    def run(
+        self,
+        context: Context,
+        argv: CustomAction.RunArg,
+    ) -> bool:
+        option: Fish_option = get_option(context, argv)
+        logger.debug(f"{option=}")
</code_context>
<issue_to_address>
**issue (bug_risk):** CustomAction.run should return a RunResult, not a bare bool

`Fish_fork_2.run` is typed to return `bool` and currently returns raw `True`/`False`, but callers (and the Maa API) expect `CustomAction.RunResult`. This mismatch will likely break or confuse the caller. Please update the signature to `-> CustomAction.RunResult` and return `CustomAction.RunResult(success=True/False, ...)` consistently, aligned with other custom actions.
</issue_to_address>

### Comment 3
<location path="agent/utils/py_tools.py" line_range="4-13" />
<code_context>
+def type_match[T](val: Any, t: type[T]) -> TypeGuard[T]:
</code_context>
<issue_to_address>
**suggestion (bug_risk):** type_match’s Union handling and fallback behavior are looser than the docstring suggests

The docstring advertises support for Union/PEP 604 unions and nested generics, but the implementation only checks `typing.Union` via `t_org.__name__ == "Union"`. For `T1 | T2`, `get_origin` returns `types.UnionType`, so this case is missed and the function falls through to `return True`, even when the value doesn’t match. Likewise, for generics whose origins are in `collections.abc`, once the outer `isinstance` passes, element types are never validated. This makes the function a shallow check, not the deeper validator the docstring suggests. I’d recommend either handling `types.UnionType` and relevant `collections.abc` origins explicitly, or updating the docstring to describe the current shallow behavior more accurately.

Suggested implementation:

```python
from typing import Any, TypeGuard, get_args, get_origin
from types import UnionType
from collections.abc import Mapping, Sequence, Set as AbstractSet

```

```python
def type_match[T](val: Any, t: type[T]) -> TypeGuard[T]:
    """
    检查值是否匹配给定的类型(支持泛型,包含常见容器的“深度”检查)

    支持的类型包括:
    - 基本类型: int, str, list, dict, tuple, set
    - 泛型类型: list[str], dict[str, int], tuple[int, ...]
    - 联合类型: int | str, Union[int, str]
    - 可选类型: Optional[str] (Union[str, None] 形式)
    - 嵌套泛型: list[list[str]], dict[str, list[int]]
    - collections.abc 中的常见容器: Sequence[T], Mapping[K, V], Set[T] 等

    对于上述容器类型,会递归检查其内部元素是否满足对应的类型参数。
    """

    # Any 始终视为匹配
    if t is Any:
        return True  # type: ignore[return-value]

    origin = get_origin(t)
    args = get_args(t)

    # 处理 Union / PEP 604 联合类型 (T1 | T2)
    # - 对于 typing.Union[...] 和 T1 | T2,get_origin(...) 在 3.10+ 通常为 types.UnionType
    # - 额外使用 isinstance(t, UnionType) 兜底 PEP 604 形式
    if origin is UnionType or isinstance(t, UnionType):
        # Optional[T] 等价于 Union[T, None]
        for sub_t in args:
            if type_match(val, sub_t):
                return True  # type: ignore[return-value]
        return False  # type: ignore[return-value]

    # 无 origin,按普通类型处理
    if origin is None:
        try:
            return isinstance(val, t)  # type: ignore[arg-type,return-value]
        except TypeError:
            # 一些 typing 构造在某些版本下不支持直接 isinstance
            return False  # type: ignore[return-value]

    # 处理 Sequence[T] / list[T] 等序列类型(不包括 str/bytes)
    if origin in (list, Sequence):
        elem_type = args[0] if args else Any
        if not isinstance(val, Sequence) or isinstance(val, (str, bytes, bytearray)):
            return False  # type: ignore[return-value]
        return all(type_match(item, elem_type) for item in val)  # type: ignore[return-value]

    # 处理 Set[T] / set[T]
    if origin in (set, AbstractSet):
        elem_type = args[0] if args else Any
        if not isinstance(val, AbstractSet) or isinstance(val, (str, bytes, bytearray)):
            return False  # type: ignore[return-value]
        return all(type_match(item, elem_type) for item in val)  # type: ignore[return-value]

    # 处理 Mapping[K, V] / dict[K, V]
    if origin in (dict, Mapping):
        key_type = args[0] if len(args) > 0 else Any
        value_type = args[1] if len(args) > 1 else Any
        if not isinstance(val, Mapping):
            return False  # type: ignore[return-value]
        return all(
            type_match(k, key_type) and type_match(v, value_type)
            for k, v in val.items()
        )  # type: ignore[return-value]

    # 处理 tuple[...]:
    # - 固定长度: tuple[int, str]
    # - 可变长度: tuple[int, ...]
    if origin is tuple:
        if not isinstance(val, tuple):
            return False  # type: ignore[return-value]

        if not args:
            return True  # type: ignore[return-value]  # 无元素约束

        # 可变长度: tuple[T, ...]
        if len(args) == 2 and args[1] is Ellipsis:
            elem_type = args[0]
            return all(type_match(item, elem_type) for item in val)  # type: ignore[return-value]

        # 固定长度: tuple[T1, T2, ...]
        if len(val) != len(args):
            return False  # type: ignore[return-value]
        return all(type_match(item, sub_t) for item, sub_t in zip(val, args))  # type: ignore[return-value]

    # 其他有 origin 的泛型,先按其 origin 做浅检查
    try:
        if not isinstance(val, origin):  # type: ignore[arg-type]
            return False  # type: ignore[return-value]
    except TypeError:
        # 无法用于 isinstance 的 origin
        return False  # type: ignore[return-value]

    # 默认:对未显式支持的泛型,不做深度检查,仅检查外层类型
    return True  # type: ignore[return-value]

```
</issue_to_address>

### Comment 4
<location path="build.py" line_range="76" />
<code_context>
    result = subprocess.run(cmd, cwd=cwd or ROOT, capture_output=True, text=True)
</code_context>
<issue_to_address>
**security (python.lang.security.audit.dangerous-subprocess-use-audit):** Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

*Source: opengrep*
</issue_to_address>

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.

Comment thread agent/custom/action/AutoFish/auto_fish_fork_2.py
Comment thread agent/custom/action/AutoFish/auto_fish_fork_2.py
Comment thread agent/utils/py_tools.py
Comment thread build.py
@Watanabehato
Copy link
Copy Markdown
Collaborator

按本仓库的 python-action-guide / pipeline-guide / task-config 重新看了一遍,这个 PR 目前不建议直接合并,主要有几个会影响可用性的点:

  1. agent/custom/action/AutoFish/auto_fish_fork_2.pytype Img = np.typing.NDArray 会在模块导入时触发 NameError,因为 np 只在 TYPE_CHECKING 分支里 import。这个模块又会在 action 包导入时加载,所以可能导致 CustomAction 注册阶段直接失败。

  2. Fish_fork_2.run() 当前标注并返回裸 bool。按 MaaFW / 本仓库 CustomAction 规范,run() 应返回 CustomAction.RunResult(success=True/False),否则失败路径和 MaaFW 对 action 结果的处理会不可靠。

  3. assets/resource/tasks/Fish.json 新增的 FishFork2 任务里,label 写成了 "task_fish_fork_2_label",少了 $description 也是纯中文。按 task-config 规范,任务 label/description 应走 $i18n_key 并补齐所有 interface locale,否则 UI 可能显示字面量且多语言不完整。

  4. agent/custom/action/__init__.py 只是 import 了 auto_fish_fork_2 模块,但 __all__ 没有加入 Fish_fork_2。虽然装饰器可能因模块 import 被执行,但这和仓库的 CustomAction 注册/导出约定不一致,后续维护和排查会比较容易踩坑。

另外,当前 check 里 Sourcery review 是 failure,阻塞项指向 build.py:76 的动态 subprocess.run 安全审计问题。这个需要处理或明确解释为什么是 false positive。

建议先把以上阻塞项修掉,再考虑把本 PR 里混在一起的 FishFork2 功能、全仓 Python 格式化/Ruff、pnpm/CI/build 改动拆开,降低回归面。

@op200
Copy link
Copy Markdown
Author

op200 commented May 29, 2026

按本仓库的 python-action-guide / pipeline-guide / task-config 重新看了一遍,这个 PR 目前不建议直接合并,主要有几个会影响可用性的点:

1. `agent/custom/action/AutoFish/auto_fish_fork_2.py` 里 `type Img = np.typing.NDArray` 会在模块导入时触发 `NameError`,因为 `np` 只在 `TYPE_CHECKING` 分支里 import。这个模块又会在 action 包导入时加载,所以可能导致 CustomAction 注册阶段直接失败。

2. `Fish_fork_2.run()` 当前标注并返回裸 `bool`。按 MaaFW / 本仓库 CustomAction 规范,`run()` 应返回 `CustomAction.RunResult(success=True/False)`,否则失败路径和 MaaFW 对 action 结果的处理会不可靠。

3. `assets/resource/tasks/Fish.json` 新增的 `FishFork2` 任务里,`label` 写成了 `"task_fish_fork_2_label"`,少了 `$`,`description` 也是纯中文。按 task-config 规范,任务 label/description 应走 `$i18n_key` 并补齐所有 interface locale,否则 UI 可能显示字面量且多语言不完整。

4. `agent/custom/action/__init__.py` 只是 import 了 `auto_fish_fork_2` 模块,但 `__all__` 没有加入 `Fish_fork_2`。虽然装饰器可能因模块 import 被执行,但这和仓库的 CustomAction 注册/导出约定不一致,后续维护和排查会比较容易踩坑。

另外,当前 check 里 Sourcery review 是 failure,阻塞项指向 build.py:76 的动态 subprocess.run 安全审计问题。这个需要处理或明确解释为什么是 false positive。

建议先把以上阻塞项修掉,再考虑把本 PR 里混在一起的 FishFork2 功能、全仓 Python 格式化/Ruff、pnpm/CI/build 改动拆开,降低回归面。

如果了解 Python 语法,而不是让 AI 根据老数据库生成判断,很容易能判定 1 2 点是错的

3 各种 OCR 也都是基于简中的,钓鱼功能也还没公开测试,各种日志也都是简中的,只有 UI 支持多语言基本毫无用处了
我就直接用 AI 生成翻译了,目前仅将标题和描述增加多语言,达到正常显示目的

4 已修正
顺带一提,类注册用的是类装饰器,而不是读取 all,所以其他从文件 module import 对象的写法是错的
all 的唯一作用就是 import * 和 静态检查,且 import * 本身也是不符合规范的写法

5 AI 报 subprocess.run 导致的安全问题,看下源码就会知道原本的代码里用的就是 subprocess.run,这次提交正好格式化了这段,导致该行有修改记录

6 没有必要也不会考虑分开提交 钓鱼 和 项目格式依赖修改,因为一是这两个是同一个 commit 已经难以拆开了,二是 钓鱼 功能代码量小且不与其他功能耦合,没有分开 commit 的必要

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.

2 participants