Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ graph TD
- Primary language is Simplified Chinese; add English when practical.
- One paragraph per line; use `<br>` for line breaks only when needed; no trailing spaces.
- Markdown is linted by `markdownlint-cli2`.
- End-user / agent usage of the installed `maa` CLI lives in `skills/maa-cli/` (`SKILL.md`, `setup.md`, `reference.md`). This file is for contributing to the crates.
- Unimplemented product designs live in `docs/design/`. Do not describe them in `skills/maa-cli/` as if the commands exist; the skill may link to a design to say they do not.
- When changing commands, task types, connection presets, or installer behavior, update `skills/maa-cli/` in the same change. When the task is to install, connect, or run maa-cli, read `skills/maa-cli/SKILL.md` instead of this file.

## MISC

Expand Down
1 change: 1 addition & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,4 @@ graph TD
- 文档以简体中文为主,英文为辅,其他语言(繁体、韩文、日文)尽量翻译,无法翻译时可用简体中文占位。
- 所有文档为 Markdown 格式,使用 [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) 检查。
- 段落内不换行,每段仅一行,段落间空行分隔。非段落换行请用 `<br>`,不要用尾随空格。
- 尚未实现、需要跨 MaaCore / maa-cli 讨论的方案放在 [`docs/design/`](docs/design/)(例如 [信息查询面](docs/design/query-surface.md)),不要写进用户手册或 `skills/maa-cli/` 当成已有命令。
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- [使用](crates/maa-cli/docs/zh-CN/usage.md)
- [配置](crates/maa-cli/docs/zh-CN/config.md)
- [常见问题](crates/maa-cli/docs/zh-CN/faq.md)
- [Agent 技能](skills/maa-cli/SKILL.md)

[maa-home]: https://github.com/MaaAssistantArknights/MaaAssistantArknights/

Expand Down
1 change: 1 addition & 0 deletions crates/maa-cli/docs/zh-CN/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
- [使用](usage.md)
- [配置](config.md)
- [常见问题](faq.md)
- [Agent 技能](../../../../skills/maa-cli/SKILL.md)

[maa-home]: https://github.com/MaaAssistantArknights/MaaAssistantArknights/
115 changes: 115 additions & 0 deletions docs/design/query-surface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# 信息查询面(中期)

状态:提案。未实现。文中的 `maa snapshot` / `maa query` 不存在,只是切面草图。

本文写给要改 maa-cli / 对接 MaaCore 的人。用户手册在 `crates/maa-cli/docs/`。当前 CLI 怎么用在 `skills/maa-cli/`。

## 要解决什么

MAA 现在是执行器:识别界面、点按钮、把 callback 打进日志。maa-cli 把任务交出去,自己不识图,也不把结果收成 agent 能反复引用的事实。

Agent 接上之后,真正缺的不是再写一套自动点击,而是**这个号现在是什么状态**——按需、带来源、缺了就说缺。有了这层,才能做比「按名单点下去」更复杂的决策:这周期红票换书还是换芯片、绿票要不要兑许可、专精材料刷关还是等店、公招许可还够不够撑到下次刷新。

所以中期要扩的是信息查询面,不是某一个推荐功能。两块一起做:

1. **OCR / 只读扫描**:把现在扫不到、扫不稳、或不落盘的界面状态读出来。包括但不限于各种票据、凭证店本期限购,以及干员箱里仍缺的养成字段。
2. **Agent 友好的查询切面**:按需取 detail,输出带 `source` / `as_of` 的 JSON。静态表(货盘、掉率、养成消耗)和 OCR 事实分开,不让模型记价格,也不把「没扫到」补成 0。

购买清单、公招规划、刷关 vs 兑换,都是这层之上的**消费者**。第一期可以拿红/绿票店当试金石,但不能把产品做成「商店购买推荐」。

## 现在停在哪

|能力|今天做什么|查询面缺什么|
|---|---|---|
|`Depot`|材料页模板匹配;部分 Core 再扫「全部」里少数货币|票类不是一等公民;结果只打日志,不落盘|
|`OperBox`|干员列表:`id` / 精英 / 等级 / 潜能 / 稀有度|技能等级、专精、模组、信赖不在结果里|
|`Mall`|按名单**真实购买**信用店|不解释为什么;不管凭证店|
|`Recruit` / `Fight` / `Infrast`|执行公招、作战、基建|callback 里有片段(理智、公招结果),没有按需查询|
|maa-cli|派任务、打日志|没有 snapshot,没有 `query`,agent 只能从日志里抠|

信用商店已经有执行器,高价值状态(票、限购、养成细节)既不扫全,也不供查询。卡点不是「OCR 读不了」,而是 Core 很少把只读扫描当成任务,cli 也没有给 agent 的事实层。

## 非目标

- 不把 Depot 扩成万能背包。票、许可、黄票、情报凭证和材料不是同一套 OCR 模板;硬扩仓库会把「没识别」混进「数量为零」。
- 不做通用「OCR 任意界面大脑」。按界面拆扫描器,查询切面再组合。
- 不替代 `Mall`。信用店货每天随机,按 `buy_first` / `blacklist` 下单是规则执行,不是查询。
- 不在 Core 或 cli 里跑模型做养成规划。表负责数值,agent 负责把事实和用户目标翻成决策。
- 不把建议或代操作写成已经存在的子命令。高代价动作(凭证店下单、源石)默认不 click;apply 若要做,必须和查询分开。

## OCR:按事实选界面

一条事实从它自然出现的页面读。不要假设「扫一次仓库就有一切」。

|要读的事实|自然界面|现状|
|---|---|---|
|材料数量|仓库「材料」|`Depot` 已有|
|红票 / 源石 / 合成玉 / 龙门币 / 赤金|仓库「全部」或部分商店顶栏|部分 Core 已扫;以当前日志为准|
|绿票、黄票、情报凭证、寻访凭证、招聘许可|仓库「全部」或对应商店顶栏|默认不稳或不全|
|凭证店还能买几次|该商店货架(例如芯片助剂 2/2)|没有只读扫描任务|
|信用点|信用商店|走 `Mall` 执行过程,不是查询|
|干员技能 / 专精 / 模组|干员详情,不是列表页|`OperBox` 没有|
|理智|作战前后|`SanityBeforeStage` 等 callback,不是独立查询|

凭证店「库存」不是全服货量,而是这个号本周期的限购余量。OCR 商店页读到的是「还能买几次」。货盘本身多半是静态表(GameData 商店表,例如 `shop_client_table`),多数时候不必 OCR 整页商品名。

票据同理:数量是 OCR,物品定义走 `item_index.json`。常用 ID:黄票 `4004`、绿票 `4005`、红票 `4006`、情报凭证 `REP_COIN`。

## 查询切面:按需、可引用、可组合

Agent 一次决策往往只要几条 detail,而不是整局游戏的 dump。切面按资源分,而不是按「推荐场景」分。

草图(实现时再定名):

```text
maa snapshot tickets # 票/凭证余量
maa snapshot shop red|green # 本期限购余量
maa snapshot depot # 材料
maa snapshot operators # 干员箱;以后可加技能/专精
maa query tickets
maa query shop --shop red
maa query operator --id <char>
maa query depot --item 30012
```

约定:

- `snapshot`:跑只读扫描,写出带时间戳的 JSON。可以贵,所以按需,不默认全量。
- `query`:读已有 snapshot + 静态表。没有快照就说没有,不要默默再扫一遍;需要刷新时显式 snapshot。
- 每条字段带 `source`(`ocr` / `table` / `callback` / `user`)和 `as_of`。缺测用缺测,禁止用 0 填充。
- 执行类结果若要暴露,也走同一形状,并标明 `side_effect`(例如 `Mall` 已经买过)。查询切面默认无副作用。

静态表不走 OCR:货盘与兑换价、企鹅掉率、技能专精消耗、经验规则。查询输出里表数据与账号状态并列,让 agent 能区分「游戏里还剩几次」和「表上这件值多少票」。

## 决策是消费者,不是切面本身

查询面给的是事实。复杂决策在 agent(或以后可选的纯函数)里做。下面只说明**为什么切面必须比单一推荐更宽**,不是第一期要交货的产品列表。

凭证店是一个典型组合:用户缺口 × 本周期性价比 × 余票 × 限购余量。没有票余量和限购,推荐只能猜;没有材料 Depot,不知道缺什么;没有表,模型会编价格。MAA 故意不自动买红/绿票店,因为买错代价高——查询面默认只建议、不代操作,和这条一致。

同一组事实还能支撑别的决策,例如:绿票 + 招聘许可限购 + 公招目标 → 要不要兑许可;红票 + 技能书库存 + 专精表 → 兑书还是刷关;干员专精缺口 + 芯片库存 + 芯片助剂限购 → 这期店该不该动。这些都不该各自做一套 OCR。

若以后要 `recommend` 入口,它是读 query JSON 的纯函数,可以先放在仓库外或脚本里,不一定进二进制。Apply(按清单代点)更往后,且必须和建议、查询分开:查询可旧,建议可错,代买不能默默错。

## 分层

|层|做什么|不做什么|
|---|---|---|
|MaaCore|按界面增加只读扫描,稳定 callback / 结构化结果|不在 Core 里做养成规划;只读任务默认不点击购买|
|maa-cli|查询切面:收 snapshot、按需 query、标明来源与时间|不把日志当 API;不用模型算性价比|
|表 / 外部数据|货盘、兑换价、掉率、养成消耗|不靠截图推数值|
|Agent|组合事实与用户目标,输出可解释决策|不把缺测补成 0;高代价动作先问再执行|

## 分期

第一期把**查询面的形状**做对,并补上最常用、现在又最残的 OCR:票据余量(红/绿优先,黄票与许可跟上),以及红票店、绿票店的限购余量。`snapshot` JSON 带 `source` / `as_of`;`query` 可以先是读文件的约定,不一定立刻进 CLI。

紧接着把 `query` 做成真正的无副作用入口,并决定 OperBox 要不要扩技能/专精/模组(可能是另一套详情扫描,而不是给列表页加字段)。

第二期再扩黄票店、情报凭证店、活动店,以及把更多 callback(理智、公招)收进同一套 query 形状。决策辅助(商店清单、材料缺口)作为消费者接入,仍然默认不代操作。

## 为什么这样切

把 Depot 做成万能背包,看起来一次扫完,实际是把不同界面的失败模式叠进一个「已读到」。票余量可以在仓库「全部」或商店顶栏;限购只在商店货架上;技能等级在干员详情。查询切面按事实组合,扫描器按界面拆开。

先做某一个推荐功能,会把 API 绑死在「买不买」上,后面的公招、专精、刷关规划都要另起炉灶。先做 OCR + 按需 query,推荐只是其中一个调用方,才配得上 agent 要做的复杂决策。
93 changes: 93 additions & 0 deletions skills/maa-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
name: maa-cli
description: >-
Operate MaaAssistantArknights maa-cli (`maa` / `maa-cli`) for 明日方舟 automation.
Use when installing or running maa-cli, connecting via PlayCover / Waydroid / ADB,
or diagnosing a failed game connection. Do not use for the MAA desktop GUI,
non-Arknights games, or this repo's Rust/CI work.
license: AGPL-3.0-only
metadata:
author: MaaAssistantArknights
version: "0.2.2"
tags: arknights maa-cli maacore
---

# maa-cli

maa-cli 只服务《明日方舟》。它把任务交给已安装的 MaaCore,自己不识图、不点屏幕。
本机命令多数是 `maa`;Windows winget 安装后是 `maa-cli`。先 `command -v maa`,没有再试 `maa-cli`。下文示例写 `maa`。
旗标以 `maa help` / `maa help <command>` 为准。

**会点击购买或消耗源石的操作,先得到用户明确同意。**

## 三层

会操作游戏的命令要求三层同时就绪。缺哪一层就补哪一层。

1. **maa-cli**:PATH 上的 `maa` 或 `maa-cli`。
2. **MaaCore + 资源**:`maa install`(已装则 `maa update`)。热更新资源用 `maa hot-update`。Nix 已捆绑 Core。包管理器装的 cli 用包管理器升级。
3. **游戏运行时**:Android 走 ADB(模拟器、真机、Waydroid);macOS 上的 iOS 包走 PlayCover + PlayTools。maa-cli 不安装模拟器、PlayCover 或游戏。

数量、余量、限购只引用命令日志或用户给出的数字。物品 ID 查已装资源的 `item_index.json`(`maa dir resource`)。

## 冷启动

完成标准:`maa version` 同时打出 cli 与 Core;`maa dir config` 能打印路径;若要跑游戏,profile 的 preset/地址与当前运行时一致,且目标命令 `--dry-run` 通过。

1. 跑 `maa version`。命令不存在 → 读 [setup.md](setup.md) 的「安装 maa-cli」,装到 `maa version` 能跑。没有 Core → `maa install`(Windows 先装 VC++)。**完成:** 输出版本里同时有 cli 和 Core。
2. `maa dir config` 打印配置目录(`MAA_CONFIG_DIR` 可覆盖)。**完成:** 得到一条真实路径。
3. 要操作游戏且运行时不明:问用户是 PlayCover、哪家模拟器、Waydroid 还是真机,再按 [setup.md](setup.md) 写 `$MAA_CONFIG_DIR/profiles/default.toml`。有人在场可用 `maa init`;无人值守直接写文件。**完成:** profile 的 preset/地址与当前客户端一致,或用户只要安装、不连游戏。
4. `maa startup --dry-run`(或目标任务加 `--dry-run`)。连不上走 setup 的连通性检查。**完成:** dry-run 退出码为 0。
5. 任务文件有输入项时加 `--batch`。**完成:** 不会在提示符上卡住。

## 连接怎么选

选 `preset` 用下表。写入文件的完整模板、分平台依赖、排错见 [setup.md](setup.md) 对应平台小节和「写连接 profile」。

|本机|游戏怎么跑|`connection.preset`|默认地址|
|---|---|---|---|
|macOS|PlayCover 安装的 iOS 包|`PlayCover`|`127.0.0.1:1717`(以窗口标题 `[host:port]` 为准)|
|macOS|MuMu Player Pro|`MuMuPro`|`127.0.0.1:16384`|
|Windows|腾讯 Androws|`Androws`|`127.0.0.1:5555`|
|Linux|Waydroid|`Waydroid`|`waydroid`|
|任意|其它 Android 模拟器或真机|`ADB`|`adb devices` 的 serial,找不到则 `emulator-5554`|

PlayCover 预设强制 `MacPlayTools`,并加载 iOS 资源。窗口保持可见。B 服没有 iOS 包。
本次运行覆盖地址:`maa fight 1-7 --addr 127.0.0.1:1717`。

## 命令怎么路由

|用户要|去做|
|---|---|
|装 / 更新 Core|`maa install` / `maa update`|
|热更新资源|`maa hot-update`|
|路径 / 版本 / 活动表|`maa dir …` / `maa version` / `maa activity`|
|启动、作战、抄作业、肉鸽、生息|预定义子命令:`startup` `closedown` `fight` `copilot` `ssscopilot` `paradoxcopilot` `roguelike` `reclamation`|
|基建、公招、信用商店、领奖、仓库、干员箱|自定义任务的 `type`,`maa run <文件名不含扩展名>`|

预定义例子:`maa startup Official && maa fight BB-7 -m 3 && maa closedown`
作业 URI 用 `prts://<id>` 或 `prts://s<id>`,或本地 JSON。
自定义任务放 `$MAA_CONFIG_DIR/tasks/`。类型名与识别边界见 [reference.md](reference.md)。
`Mall` 的 `buy_first` / `blacklist` 会在信用商店真实下单。

## 何时读哪份文件

- 缺 cli / Core、要写 profile、连不上:读 [setup.md](setup.md) 里对应当前 OS 的那一节。
- 自定义 `type`、URI、仓库/干员箱能扫到什么:读 [reference.md](reference.md) 对应小节。

仓库内用户手册:

- 安装:[install.md](../../crates/maa-cli/docs/zh-CN/install.md)
- 使用:[usage.md](../../crates/maa-cli/docs/zh-CN/usage.md)
- 配置:[config.md](../../crates/maa-cli/docs/zh-CN/config.md)

## 常见错误

|错|改成|
|---|---|
|把 `Infrast` / `Recruit` / `Mall` / `Depot` 当成子命令|自定义任务 `type` + `maa run …`|
|只装了 cli 就开打|`maa version` 看到 Core 之后再连|
|macOS 默认 ADB 去连 PlayCover|preset `PlayCover`,地址用标题栏端口|
|作业写成 `maa://`|`prts://`|
|把 `Mall` 名单当成推荐清单|先确认再跑;名单里的东西会被买掉|
|把 `maa activity` 当成背包|活动表来自已装资源;背包走 `Depot` 任务日志|
Loading
Loading