Skip to content

[codex] add Windows PC attach-window support to maa-cli#543

Open
Alphayellowcat wants to merge 5 commits into
MaaAssistantArknights:mainfrom
Alphayellowcat:codex/pc-attachwindow-support
Open

[codex] add Windows PC attach-window support to maa-cli#543
Alphayellowcat wants to merge 5 commits into
MaaAssistantArknights:mainfrom
Alphayellowcat:codex/pc-attachwindow-support

Conversation

@Alphayellowcat
Copy link
Copy Markdown

@Alphayellowcat Alphayellowcat commented May 6, 2026

Summary

This PR adds Windows PC-client support to maa-cli by exposing MaaCore's AttachWindow path through the CLI runtime and profile configuration.

It also updates maa init so users can generate a PC-oriented connection profile without hand-editing the config.

What changed

  • add a PC connection preset for Windows AttachWindow mode
  • add connection.window_title, screencap_method, mouse_method, and keyboard_method
  • route connection.type = "PC" through AsstAsyncAttachWindow instead of ADB connect
  • auto-load the PC platform-diff resource for this preset
  • add Win32 exact-title window discovery for the running game window
  • add --window-title override on the CLI
  • update the config schema and example profile
  • extend maa init so it can generate a PC preset with sensible defaults

Why

MaaCore already exposes AsstAsyncAttachWindow on Windows, but maa-cli only exposed ADB-style connection flows. That meant the GUI could drive the native Windows Arknights client while the CLI could not, even though the core capability already existed.

This closes that feature gap and makes the PC client a first-class connection mode in maa-cli.

User impact

Users on Windows can now configure:

[connection]
type = "PC"
window_title = "明日方舟"

and run maa-cli against the native PC client without going through emulator or ADB flows.

Validation

  • cargo +1.88.0 test -p maa-cli --quiet
    • 302 passed, 0 failed, 26 ignored
  • local runtime validation with a patched maa.exe
    • matched the running 明日方舟 window by title
    • entered the AttachWindow connection path successfully
    • previously verified real in-game screencap through MaaCore AttachWindow on the same setup

Notes

  • this PR is Windows-only for the PC preset
  • the PR is opened as draft because the core connection path is validated, but not every task flow has been exercised end-to-end on the PC client yet

Summary by Sourcery

为 maa-cli 新增 Windows PC AttachWindow 连接支持,并通过配置、CLI 和核心 API 全流程打通。

New Features:

  • 引入仅限 Windows 的 PC 连接预设,通过 Win32 AttachWindow 附着到原生明日方舟客户端,而不是使用 ADB。
  • 增加基于窗口的连接参数支持(window_titlescreencap_methodmouse_methodkeyboard_method),包括一个 --window-title CLI 覆盖参数。
  • 在 MaaCore 中暴露新的 async_attach_window API,并将其集成进 maa-cli 运行时以支持 PC 连接。
  • 实现通过窗口标题精确匹配的 Win32 窗口发现机制,在附着之前定位正在运行的游戏客户端。

Enhancements:

  • 扩展 maa 初始化模板、配置 schema 和示例配置文件,用于生成并文档化面向 PC 的连接配置和 platform-diff 资源。
  • 在使用 PC 连接预设时自动加载 PC 的 platform-diff 资源。
  • 改进安装器对 ETag 的处理,通过集中构造 .etag 文件路径来统一逻辑,并现代化 MaaCore 用户目录初始化流程。
  • 更新安装器 fixtures 路径,并调整连接失败时的提示信息,从特指 Android 设备改为笼统地指游戏客户端。

Tests:

  • 扩展配置和连接相关测试,涵盖新的 PC 预设、AttachWindow 参数构造以及 PC platform-diff 的自动加载。
  • 调整现有测试(包括密令执行和安装器清单)以适配平台差异和新增的配置字段。
Original summary in English

Summary by Sourcery

Add Windows PC AttachWindow connection support to maa-cli and wire it through config, CLI, and core APIs.

New Features:

  • Introduce a Windows-only PC connection preset that attaches to the native Arknights client via Win32 AttachWindow instead of ADB.
  • Add support for window-based connection parameters (window_title, screencap_method, mouse_method, keyboard_method) including a --window-title CLI override.
  • Expose a new async_attach_window API on MaaCore and integrate it into the maa-cli runtime for PC connections.
  • Implement Win32 window discovery by exact title to locate the running game client before attaching.

Enhancements:

  • Extend maa init templates, config schema, and example profiles to generate and document PC-oriented connection configs and platform-diff resources.
  • Automatically load the PC platform-diff resource when using the PC connection preset.
  • Improve installer ETag handling by centralizing .etag file path construction and modernize MaaCore user directory initialization.
  • Update installer fixtures paths and adjust connection failure messaging to refer generically to the game client rather than Android devices.

Tests:

  • Expand configuration and connection tests to cover the new PC preset, AttachWindow argument construction, and PC platform-diff auto-loading.
  • Adjust existing tests, including secret command execution and installer manifests, to accommodate platform differences and the new configuration fields.
Original summary in English

Summary by Sourcery

为 maa-cli 新增 Windows PC AttachWindow 连接支持,并通过配置、CLI 和核心 API 全流程打通。

New Features:

  • 引入仅限 Windows 的 PC 连接预设,通过 Win32 AttachWindow 附着到原生明日方舟客户端,而不是使用 ADB。
  • 增加基于窗口的连接参数支持(window_titlescreencap_methodmouse_methodkeyboard_method),包括一个 --window-title CLI 覆盖参数。
  • 在 MaaCore 中暴露新的 async_attach_window API,并将其集成进 maa-cli 运行时以支持 PC 连接。
  • 实现通过窗口标题精确匹配的 Win32 窗口发现机制,在附着之前定位正在运行的游戏客户端。

Enhancements:

  • 扩展 maa 初始化模板、配置 schema 和示例配置文件,用于生成并文档化面向 PC 的连接配置和 platform-diff 资源。
  • 在使用 PC 连接预设时自动加载 PC 的 platform-diff 资源。
  • 改进安装器对 ETag 的处理,通过集中构造 .etag 文件路径来统一逻辑,并现代化 MaaCore 用户目录初始化流程。
  • 更新安装器 fixtures 路径,并调整连接失败时的提示信息,从特指 Android 设备改为笼统地指游戏客户端。

Tests:

  • 扩展配置和连接相关测试,涵盖新的 PC 预设、AttachWindow 参数构造以及 PC platform-diff 的自动加载。
  • 调整现有测试(包括密令执行和安装器清单)以适配平台差异和新增的配置字段。
Original summary in English

Summary by Sourcery

Add Windows PC AttachWindow connection support to maa-cli and wire it through config, CLI, and core APIs.

New Features:

  • Introduce a Windows-only PC connection preset that attaches to the native Arknights client via Win32 AttachWindow instead of ADB.
  • Add support for window-based connection parameters (window_title, screencap_method, mouse_method, keyboard_method) including a --window-title CLI override.
  • Expose a new async_attach_window API on MaaCore and integrate it into the maa-cli runtime for PC connections.
  • Implement Win32 window discovery by exact title to locate the running game client before attaching.

Enhancements:

  • Extend maa init templates, config schema, and example profiles to generate and document PC-oriented connection configs and platform-diff resources.
  • Automatically load the PC platform-diff resource when using the PC connection preset.
  • Improve installer ETag handling by centralizing .etag file path construction and modernize MaaCore user directory initialization.
  • Update installer fixtures paths and adjust connection failure messaging to refer generically to the game client rather than Android devices.

Tests:

  • Expand configuration and connection tests to cover the new PC preset, AttachWindow argument construction, and PC platform-diff auto-loading.
  • Adjust existing tests, including secret command execution and installer manifests, to accommodate platform differences and the new configuration fields.

新功能:

  • 引入新的 PC 连接预设,通过 Win32 AttachWindow 附加到原生 Windows 明日方舟客户端,而不是使用 ADB。
  • 支持在连接配置中设置 window_titlescreencap_methodmouse_methodkeyboard_method,并可通过 --window-title CLI 参数覆盖窗口标题。
  • 新增仅适用于 Windows 的实现,通过精确匹配窗口标题定位游戏窗口,并使用从 MaaCore 暴露出的新的 async_attach_window API 进行连接。

增强:

  • 扩展 maa init 和 asst 配置的 schema/示例配置,自动生成并文档化面向 PC 的连接配置以及 platform-diff 资源。
  • 改进安装器测试和 fixtures 路径,并调整错误消息,使其更笼统一致地指代“游戏客户端”,而不是特指 Android 设备。
  • 优化下载中的 ETag 处理,通过集中构造 .etag 辅助文件路径,并现代化 MaaCore 用户目录初始化流程。

测试:

  • 扩展配置和连接相关测试,覆盖新的 PC 预设、PC 默认方法、AttachWindow 参数构造,以及 PC 平台差异资源的自动加载。
  • 调整现有连接、资源、行为配置和密钥相关测试,以适配新增字段和跨平台命令差异。
Original summary in English

Summary by Sourcery

为 maa-cli 新增 Windows PC AttachWindow 连接支持,并通过配置、CLI 和核心 API 全流程打通。

New Features:

  • 引入仅限 Windows 的 PC 连接预设,通过 Win32 AttachWindow 附着到原生明日方舟客户端,而不是使用 ADB。
  • 增加基于窗口的连接参数支持(window_titlescreencap_methodmouse_methodkeyboard_method),包括一个 --window-title CLI 覆盖参数。
  • 在 MaaCore 中暴露新的 async_attach_window API,并将其集成进 maa-cli 运行时以支持 PC 连接。
  • 实现通过窗口标题精确匹配的 Win32 窗口发现机制,在附着之前定位正在运行的游戏客户端。

Enhancements:

  • 扩展 maa 初始化模板、配置 schema 和示例配置文件,用于生成并文档化面向 PC 的连接配置和 platform-diff 资源。
  • 在使用 PC 连接预设时自动加载 PC 的 platform-diff 资源。
  • 改进安装器对 ETag 的处理,通过集中构造 .etag 文件路径来统一逻辑,并现代化 MaaCore 用户目录初始化流程。
  • 更新安装器 fixtures 路径,并调整连接失败时的提示信息,从特指 Android 设备改为笼统地指游戏客户端。

Tests:

  • 扩展配置和连接相关测试,涵盖新的 PC 预设、AttachWindow 参数构造以及 PC platform-diff 的自动加载。
  • 调整现有测试(包括密令执行和安装器清单)以适配平台差异和新增的配置字段。
Original summary in English

Summary by Sourcery

Add Windows PC AttachWindow connection support to maa-cli and wire it through config, CLI, and core APIs.

New Features:

  • Introduce a Windows-only PC connection preset that attaches to the native Arknights client via Win32 AttachWindow instead of ADB.
  • Add support for window-based connection parameters (window_title, screencap_method, mouse_method, keyboard_method) including a --window-title CLI override.
  • Expose a new async_attach_window API on MaaCore and integrate it into the maa-cli runtime for PC connections.
  • Implement Win32 window discovery by exact title to locate the running game client before attaching.

Enhancements:

  • Extend maa init templates, config schema, and example profiles to generate and document PC-oriented connection configs and platform-diff resources.
  • Automatically load the PC platform-diff resource when using the PC connection preset.
  • Improve installer ETag handling by centralizing .etag file path construction and modernize MaaCore user directory initialization.
  • Update installer fixtures paths and adjust connection failure messaging to refer generically to the game client rather than Android devices.

Tests:

  • Expand configuration and connection tests to cover the new PC preset, AttachWindow argument construction, and PC platform-diff auto-loading.
  • Adjust existing tests, including secret command execution and installer manifests, to accommodate platform differences and the new configuration fields.
Original summary in English

Summary by Sourcery

为 maa-cli 新增 Windows PC AttachWindow 连接支持,并通过配置、CLI 和核心 API 全流程打通。

New Features:

  • 引入仅限 Windows 的 PC 连接预设,通过 Win32 AttachWindow 附着到原生明日方舟客户端,而不是使用 ADB。
  • 增加基于窗口的连接参数支持(window_titlescreencap_methodmouse_methodkeyboard_method),包括一个 --window-title CLI 覆盖参数。
  • 在 MaaCore 中暴露新的 async_attach_window API,并将其集成进 maa-cli 运行时以支持 PC 连接。
  • 实现通过窗口标题精确匹配的 Win32 窗口发现机制,在附着之前定位正在运行的游戏客户端。

Enhancements:

  • 扩展 maa 初始化模板、配置 schema 和示例配置文件,用于生成并文档化面向 PC 的连接配置和 platform-diff 资源。
  • 在使用 PC 连接预设时自动加载 PC 的 platform-diff 资源。
  • 改进安装器对 ETag 的处理,通过集中构造 .etag 文件路径来统一逻辑,并现代化 MaaCore 用户目录初始化流程。
  • 更新安装器 fixtures 路径,并调整连接失败时的提示信息,从特指 Android 设备改为笼统地指游戏客户端。

Tests:

  • 扩展配置和连接相关测试,涵盖新的 PC 预设、AttachWindow 参数构造以及 PC platform-diff 的自动加载。
  • 调整现有测试(包括密令执行和安装器清单)以适配平台差异和新增的配置字段。
Original summary in English

Summary by Sourcery

Add Windows PC AttachWindow connection support to maa-cli and wire it through config, CLI, and core APIs.

New Features:

  • Introduce a Windows-only PC connection preset that attaches to the native Arknights client via Win32 AttachWindow instead of ADB.
  • Add support for window-based connection parameters (window_title, screencap_method, mouse_method, keyboard_method) including a --window-title CLI override.
  • Expose a new async_attach_window API on MaaCore and integrate it into the maa-cli runtime for PC connections.
  • Implement Win32 window discovery by exact title to locate the running game client before attaching.

Enhancements:

  • Extend maa init templates, config schema, and example profiles to generate and document PC-oriented connection configs and platform-diff resources.
  • Automatically load the PC platform-diff resource when using the PC connection preset.
  • Improve installer ETag handling by centralizing .etag file path construction and modernize MaaCore user directory initialization.
  • Update installer fixtures paths and adjust connection failure messaging to refer generically to the game client rather than Android devices.

Tests:

  • Expand configuration and connection tests to cover the new PC preset, AttachWindow argument construction, and PC platform-diff auto-loading.
  • Adjust existing tests, including secret command execution and installer manifests, to accommodate platform differences and the new configuration fields.

@Alphayellowcat Alphayellowcat marked this pull request as ready for review May 6, 2026 08:45
@Alphayellowcat Alphayellowcat marked this pull request as draft May 6, 2026 08:46
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 - 我发现了两个问题,并给出了一些整体层面的反馈:

  • ConnectionConfig/AttachWindowArgs 里的 screencap_methodmouse_methodkeyboard_method 字段是 u64,但在 maa init 的交互提示中使用的是 i32;为了安全性和可读性,建议在配置、模板和 MaaCore 调用之间统一这些字段的整数位宽和有符号性。
  • 在 Windows 的 AttachWindow 路径中,你通过 API 直接传递了原始的 u64 方法 ID;建议为这些方法选择器引入轻量的 newtype 或枚举,使调用点具备自描述性,并降低交换或误用这些数值常量的风险。
给 AI Agent 的提示词
Please address the comments from this code review:

## Overall Comments
- The `screencap_method`, `mouse_method`, and `keyboard_method` fields are `u64` in `ConnectionConfig`/`AttachWindowArgs` but are prompted as `i32` in `maa init`; it would be safer and clearer to align these types to a single integer width/signedness across config, template, and MaaCore calls.
- In the Windows AttachWindow path you pass raw `u64` method IDs through the API; consider introducing small newtypes or enums for these method selectors to make call sites self-documenting and reduce the risk of swapping or misusing these numeric constants.

## Individual Comments

### Comment 1
<location path="crates/maa-cli/src/run/windows.rs" line_range="7" />
<code_context>
+    Foundation::{HWND, LPARAM},
+    UI::WindowsAndMessaging::{EnumWindows, GetWindowTextLengthW, GetWindowTextW, IsWindowVisible},
+};
+use windows_sys::core::BOOL;
+
+pub(super) struct WindowMatch {
</code_context>
<issue_to_address>
**issue (bug_risk):** Importing `BOOL` from `windows_sys::core` is likely incorrect and will not compile.

In `windows-sys`, `BOOL` is defined under `windows_sys::Win32::Foundation`, not `windows_sys::core`. Since you already import `HWND` and `LPARAM` from `Foundation`, import `BOOL` there as well:

```rust
use windows_sys::Win32::Foundation::{BOOL, HWND, LPARAM};
```

Then remove the `windows_sys::core::BOOL` import, which does not exist and will cause a compile error.
</issue_to_address>

### Comment 2
<location path="crates/maa-cli/src/config/init.rs" line_range="215-224" />
<code_context>
+                x => insert!(config, "window_title" => x),
+            };
+        }
+        if let Some(screencap_method) = obj.get("screencap_method") {
+            match screencap_method.as_int().unwrap() {
+                2 => {}
+                x => insert!(config, "screencap_method" => x),
+            };
+        }
+        if let Some(mouse_method) = obj.get("mouse_method") {
+            match mouse_method.as_int().unwrap() {
+                32 => {}
+                x => insert!(config, "mouse_method" => x),
+            };
+        }
+        if let Some(keyboard_method) = obj.get("keyboard_method") {
+            match keyboard_method.as_int().unwrap() {
+                2 => {}
+                x => insert!(config, "keyboard_method" => x),
+            };
+        }
</code_context>
<issue_to_address>
**issue (bug_risk):** PC input methods are typed as `u64` in config but initialized here via signed integers, which can produce invalid configs.

These fields are `Option<u64>` in `ConnectionConfig`, but the template uses `Input::<i32>` and writes `as_int()` results directly into TOML. If a user enters a negative value, the generated config will contain a negative integer and deserialization into `u64` will fail. Please either reject/guard against negative values here (e.g., bail or clamp on `x < 0`) or update the template to use an unsigned type consistent with the struct definition.
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得这些评审有帮助,请考虑分享给他人 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进今后的评审。
Original comment in English

Hey - I've found 2 issues, and left some high level feedback:

  • The screencap_method, mouse_method, and keyboard_method fields are u64 in ConnectionConfig/AttachWindowArgs but are prompted as i32 in maa init; it would be safer and clearer to align these types to a single integer width/signedness across config, template, and MaaCore calls.
  • In the Windows AttachWindow path you pass raw u64 method IDs through the API; consider introducing small newtypes or enums for these method selectors to make call sites self-documenting and reduce the risk of swapping or misusing these numeric constants.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `screencap_method`, `mouse_method`, and `keyboard_method` fields are `u64` in `ConnectionConfig`/`AttachWindowArgs` but are prompted as `i32` in `maa init`; it would be safer and clearer to align these types to a single integer width/signedness across config, template, and MaaCore calls.
- In the Windows AttachWindow path you pass raw `u64` method IDs through the API; consider introducing small newtypes or enums for these method selectors to make call sites self-documenting and reduce the risk of swapping or misusing these numeric constants.

## Individual Comments

### Comment 1
<location path="crates/maa-cli/src/run/windows.rs" line_range="7" />
<code_context>
+    Foundation::{HWND, LPARAM},
+    UI::WindowsAndMessaging::{EnumWindows, GetWindowTextLengthW, GetWindowTextW, IsWindowVisible},
+};
+use windows_sys::core::BOOL;
+
+pub(super) struct WindowMatch {
</code_context>
<issue_to_address>
**issue (bug_risk):** Importing `BOOL` from `windows_sys::core` is likely incorrect and will not compile.

In `windows-sys`, `BOOL` is defined under `windows_sys::Win32::Foundation`, not `windows_sys::core`. Since you already import `HWND` and `LPARAM` from `Foundation`, import `BOOL` there as well:

```rust
use windows_sys::Win32::Foundation::{BOOL, HWND, LPARAM};
```

Then remove the `windows_sys::core::BOOL` import, which does not exist and will cause a compile error.
</issue_to_address>

### Comment 2
<location path="crates/maa-cli/src/config/init.rs" line_range="215-224" />
<code_context>
+                x => insert!(config, "window_title" => x),
+            };
+        }
+        if let Some(screencap_method) = obj.get("screencap_method") {
+            match screencap_method.as_int().unwrap() {
+                2 => {}
+                x => insert!(config, "screencap_method" => x),
+            };
+        }
+        if let Some(mouse_method) = obj.get("mouse_method") {
+            match mouse_method.as_int().unwrap() {
+                32 => {}
+                x => insert!(config, "mouse_method" => x),
+            };
+        }
+        if let Some(keyboard_method) = obj.get("keyboard_method") {
+            match keyboard_method.as_int().unwrap() {
+                2 => {}
+                x => insert!(config, "keyboard_method" => x),
+            };
+        }
</code_context>
<issue_to_address>
**issue (bug_risk):** PC input methods are typed as `u64` in config but initialized here via signed integers, which can produce invalid configs.

These fields are `Option<u64>` in `ConnectionConfig`, but the template uses `Input::<i32>` and writes `as_int()` results directly into TOML. If a user enters a negative value, the generated config will contain a negative integer and deserialization into `u64` will fail. Please either reject/guard against negative values here (e.g., bail or clamp on `x < 0`) or update the template to use an unsigned type consistent with the struct definition.
</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.

Foundation::{HWND, LPARAM},
UI::WindowsAndMessaging::{EnumWindows, GetWindowTextLengthW, GetWindowTextW, IsWindowVisible},
};
use windows_sys::core::BOOL;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk):windows_sys::core 导入 BOOL 很可能是不正确的,并且会导致无法编译。

windows-sys 中,BOOL 定义在 windows_sys::Win32::Foundation 下,而不是 windows_sys::core。既然你已经从 Foundation 导入了 HWNDLPARAM,也请从这里一并导入 BOOL

use windows_sys::Win32::Foundation::{BOOL, HWND, LPARAM};

然后删除 windows_sys::core::BOOL 的导入;该符号并不存在,会导致编译错误。

Original comment in English

issue (bug_risk): Importing BOOL from windows_sys::core is likely incorrect and will not compile.

In windows-sys, BOOL is defined under windows_sys::Win32::Foundation, not windows_sys::core. Since you already import HWND and LPARAM from Foundation, import BOOL there as well:

use windows_sys::Win32::Foundation::{BOOL, HWND, LPARAM};

Then remove the windows_sys::core::BOOL import, which does not exist and will cause a compile error.

Comment thread crates/maa-cli/src/config/init.rs
@Alphayellowcat
Copy link
Copy Markdown
Author

Thanks for the review.

  • I addressed the signedness mismatch in f728873 (fix: validate PC attach-window method ids).
    • the config-side PC method fields are now consistently i32
    • negative values are rejected when generating profiles in maa init
    • the AttachWindow runtime path also validates these values before converting them to the u64 MaaCore API parameters
  • I also investigated the BOOL import suggestion. With the current windows-sys version used in this repository, moving BOOL to windows_sys::Win32::Foundation does not compile (no BOOL in Win32::Foundation). I verified this locally and kept windows_sys::core::BOOL unchanged for compatibility with the dependency version in this PR.

I did not introduce dedicated enums/newtypes for the method IDs in this patch so I could keep the PR focused on landing PC AttachWindow support and the validation fix. Happy to follow up on that refactor separately if maintainers would prefer it.

@Alphayellowcat Alphayellowcat marked this pull request as ready for review May 6, 2026 09:02
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 个问题,并给出了一些整体性的反馈:

  • PC 预设的默认值(窗口标题、截屏/鼠标/键盘方法)以及对非负方法的校验在 ConnectionConfig::attach_window_argsinit.rs 中都有重复;建议将这些常量和校验逻辑集中到一个单独的辅助函数中,以避免后续出现偏差。
  • run/windows.rs 中,EnumWindows 即使在找到完全匹配的标题后仍会继续枚举;如果实际只会使用第一个匹配项,可以在回调中在第一次精确匹配后提前返回,避免不必要的枚举开销。
给 AI Agent 的提示
Please address the comments from this code review:

## Overall Comments
- PC 预设的默认值(窗口标题、截屏/鼠标/键盘方法)以及对非负方法的校验在 `ConnectionConfig::attach_window_args``init.rs` 中都有重复;建议将这些常量和校验逻辑集中到一个单独的辅助函数中,以避免后续出现偏差。
-`run/windows.rs` 中,`EnumWindows` 即使在找到完全匹配的标题后仍会继续枚举;如果实际只会使用第一个匹配项,可以在回调中在第一次精确匹配后提前返回,避免不必要的枚举开销。

## Individual Comments

### Comment 1
<location path="crates/maa-cli/src/config/init.rs" line_range="215-224" />
<code_context>
+        if let Some(screencap_method) = obj.get("screencap_method") {
</code_context>
<issue_to_address>
**suggestion:** 避免为非负的 attach-window 方法重复编写校验逻辑。

对 `screencap_method``mouse_method``keyboard_method` 的非负检查与 `asst.rs` 中的 `validate_attach_window_method` 重复,这在规则变更时有产生不一致的风险。建议将这部分逻辑集中(例如放在 config 模块中的一个共享辅助函数里),这样交互式初始化和运行时解析就能始终使用同一套校验规则。

建议的实现方式:

```rust
        if let Some(screencap_method) = obj.get("screencap_method") {
            let x = screencap_method.as_int().unwrap();
            crate::config::validate_attach_window_method("connection.screencap_method", x)?;
            if x != 2 {
                insert!(config, "screencap_method" => x);
            }
        }

```

为了完整应用上述建议,并避免在代码库中重复校验逻辑,还需要:

1. 引入一个共享的辅助函数,例如放在 `crates/maa-cli/src/config/mod.rs`(或其他中心化的 config 模块)中,类似:
   ```rust
   pub fn validate_attach_window_method(key: &str, value: i64) -> anyhow::Result<()> {
       if value < 0 {
           bail!("{key} must be a non-negative integer, got {value}");
       }
       Ok(())
   }
   ```
2.`asst.rs` 中现有的运行时校验更新为调用新的 `validate_attach_window_method`,而不是在内部重新实现非负检查,这样交互式初始化和运行时解析就能共享同一套规则。
3. 在这个 `init.rs` 文件中,同样将 `mouse_method``keyboard_method` 的非负检查替换为调用 `crate::config::validate_attach_window_method("connection.mouse_method", x)?``crate::config::validate_attach_window_method("connection.keyboard_method", x)?`,同时保留现有的默认值处理逻辑(例如这里的 `2` 的情况)。
4. 确保添加/调整必要的 `use` 语句或使用全限定路径,使所有调用点都能顺利通过编译。
</issue_to_address>

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

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

  • The PC preset defaults (window title, screencap/mouse/keyboard methods) and validation for non-negative methods are duplicated between ConnectionConfig::attach_window_args and init.rs; consider centralizing these constants and the validation in a single helper to avoid drift.
  • In run/windows.rs, EnumWindows continues enumerating even after finding an exact title match; if only the first match is used, you could early-return from the callback after the first exact match to avoid unnecessary enumeration work.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The PC preset defaults (window title, screencap/mouse/keyboard methods) and validation for non-negative methods are duplicated between `ConnectionConfig::attach_window_args` and `init.rs`; consider centralizing these constants and the validation in a single helper to avoid drift.
- In `run/windows.rs`, `EnumWindows` continues enumerating even after finding an exact title match; if only the first match is used, you could early-return from the callback after the first exact match to avoid unnecessary enumeration work.

## Individual Comments

### Comment 1
<location path="crates/maa-cli/src/config/init.rs" line_range="215-224" />
<code_context>
+        if let Some(screencap_method) = obj.get("screencap_method") {
</code_context>
<issue_to_address>
**suggestion:** Avoid duplicating validation logic for non-negative attach-window methods.

The non-negative checks for `screencap_method`, `mouse_method`, and `keyboard_method` duplicate `validate_attach_window_method` in `asst.rs`, which risks them diverging if the rules change. Consider centralizing this (e.g., a shared helper in the config module) so interactive init and runtime parsing always use the same validation logic.

Suggested implementation:

```rust
        if let Some(screencap_method) = obj.get("screencap_method") {
            let x = screencap_method.as_int().unwrap();
            crate::config::validate_attach_window_method("connection.screencap_method", x)?;
            if x != 2 {
                insert!(config, "screencap_method" => x);
            }
        }

```

To fully apply your suggestion and avoid duplicated validation logic across the codebase, also:

1. Introduce a shared helper function, e.g. in `crates/maa-cli/src/config/mod.rs` (or another central config module), something like:
   ```rust
   pub fn validate_attach_window_method(key: &str, value: i64) -> anyhow::Result<()> {
       if value < 0 {
           bail!("{key} must be a non-negative integer, got {value}");
       }
       Ok(())
   }
   ```
2. Update the existing runtime validation in `asst.rs` to call this new `validate_attach_window_method` instead of inlining its own non-negative checks, so interactive init and runtime parsing share the same rules.
3. In this `init.rs` file, similarly replace the non-negative checks for `mouse_method` and `keyboard_method` with calls to `crate::config::validate_attach_window_method("connection.mouse_method", x)?` and `crate::config::validate_attach_window_method("connection.keyboard_method", x)?` respectively, preserving any existing default-value handling (like the `2` case here).
4. Ensure any necessary `use` statements or fully-qualified paths are added/adjusted so all call sites compile cleanly.
</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 crates/maa-cli/src/config/init.rs
@Alphayellowcat
Copy link
Copy Markdown
Author

Follow-up in 62dbec6 (refactor: share PC attach-window config defaults):

  • centralized the PC AttachWindow defaults in the shared config module
  • moved non-negative AttachWindow method validation to the shared config helper and reused it from both init.rs and the runtime path in asst.rs

I did not change the EnumWindows traversal to early-return on the first exact match. The current behavior is intentional so the CLI can still detect duplicate visible windows with the same title and emit a warning before selecting the first one.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 22.45%. Comparing base (7557252) to head (ac17b32).
⚠️ Report is 8 commits behind head on main.

❗ There is a different number of reports uploaded between BASE (7557252) and HEAD (ac17b32). Click for more details.

HEAD has 3 uploads less than BASE
Flag BASE (7557252) HEAD (ac17b32)
4 1
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #543       +/-   ##
===========================================
- Coverage   71.86%   22.45%   -49.41%     
===========================================
  Files          69        6       -63     
  Lines        6412      285     -6127     
  Branches     6412      285     -6127     
===========================================
- Hits         4608       64     -4544     
+ Misses       1477      220     -1257     
+ Partials      327        1      -326     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

check_interval: Option<time::Duration>,
) -> Result<()> {
let etag_file = dest.with_added_extension("etag");
let etag_file = etag_file_path(dest);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These changes should be unrelated, and I think dest.with_added_extension should work well. Can you discard them?

Comment on lines +10 to +12
pub(crate) const PC_SCREENCAP_METHOD_DEFAULT: i32 = 2;
pub(crate) const PC_MOUSE_METHOD_DEFAULT: i32 = 32;
pub(crate) const PC_KEYBOARD_METHOD_DEFAULT: i32 = 2;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you please add references for those numbers? If possible, make them enums, similar to what we do for other types in the maa-type crate.

use super::*;

const FIXTURE_JSON: &str = include_str!("../../fixtures/version/cli_version.json");
const FIXTURE_JSON: &str = include_str!("../../../maa-version/fixtures/cli_version.json");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is unrelated. Does the symlink not work on Windows?

/// The match is exact and case-sensitive, following MAA GUI behavior.
/// If omitted, `明日方舟` is used by default.
#[arg(long, verbatim_doc_comment)]
pub window_title: Option<String>,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this value change often? If not, consider setting it only in the configuration; there is no need to add a new CLI argument.

)?;
}
#[cfg(not(target_os = "windows"))]
crate::config::asst::Preset::Pc => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Considering cfg on Pc variants ensures the variants exist only on Windows, instead of creating a branch here.

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