cli-anything-slay-the-spire-ii 实战指南:通过本地 Bridge Mod 以命令行与 Agent 控制真实《杀戮尖塔2》
【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything
导读
cli-anything-slay-the-spire-ii是 CLI-Anything 项目中面向《Slay the Spire 2》(杀戮尖塔 2)的智能体原生(Agent-Native)命令行桥接层:它通过一款运行在游戏进程内的STS2_Bridge模组,在http://localhost:15526暴露本地 HTTP API,从而让 CLI、脚本或 AI Agent 直接读取规范化游戏状态并下发战斗、地图导航、奖励领取、菜单管理等动作指令。本文基于仓库内 Skill 定义文档(SKILL.md)展开,结合 CLI 源码、状态/动作适配器与测试用例,完整讲解安装部署、全部命令组、决策状态机、配置项以及面向 Agent 的调用约定,帮助你用命令行接管真实游戏流程,而非依赖屏幕自动化或模拟器。
工作原理:真实游戏进程内的 HTTP 桥
与多数包装独立桌面应用的 CLI-Anything harness 不同,本项目不启动子进程、不做屏幕识别,而是依赖一个定制桥接模组在游戏进程内直接读取内部状态并执行动作。整条调用链路(架构见 agent-harness/STS2.md):
Slay the Spire 2 (Steam) 进程内 └── STS2_Bridge (.NET 9 mod) ├── 读取游戏状态(战斗、地图、菜单、奖励…) └── 在 http://localhost:15526/api/v1/singleplayer 暴露 API ▲ GET state → 返回原始 JSON ▼ POST action → 执行动作并返回结果 cli-anything-sts2(Click CLI + REPL)CLI 侧由三个核心模块支撑(源码目录 cli_anything/slay_the_spire_ii/):
- utils/sts2_backend.py:
Sts2RawClient,基于标准库urllib封装 GET/POST 请求,连接{base_url}/api/v1/singleplayer,失败时抛出带原因的ApiError; - core/state_adapter.py:
normalize_state()把桥接模组返回的原始 JSON 映射为带decision字段的规范化状态; - core/action_adapter.py:全部动作负载的工厂函数(如
play_card(card_index, target=None)),支持按名称分发。
从源码结构看,这种"游戏内 Mod + HTTP 桥"的设计翻译层极薄:桥直接访问游戏内部状态与动作 API,CLI 侧只需把命令映射为 JSON 负载,因此状态与动作的语义损耗很小。
安装与前置条件
环境要求
- Python 3.10+
- Steam 版《Slay the Spire 2》,且已启用
STS2_Bridge模组 .NET 9 SDK(仅构建桥接模组时需要)
第 1 步:安装 CLI
git clone https://github.com/HKUDS/CLI-Anything.git cd CLI-Anything/slay_the_spire_ii/agent-harness pip install -e .安装后即可获得cli-anything-sts2命令(入口见 slay_the_spire_ii_cli.py)。也可以直接使用 Python 模块方式运行:python -m cli_anything.slay_the_spire_ii。
第 2 步:构建并安装桥接模组
桥接模组是一个.NET 9插件,需要编译后装入游戏目录。仓库中构建脚本默认自动探测 macOS Steam 游戏数据目录:
cd CLI-Anything/slay_the_spire_ii/agent-harness/bridge/plugin ./build.sh cd ../install ./install_bridge.sh若自动探测失败,可显式指定游戏数据目录(目标目录需至少包含sts2.dll、GodotSharp.dll、0Harmony.dll):
STS2_GAME_DATA_DIR="/path/to/data_sts2" ./build.sh安装脚本同样支持显式传入游戏根目录,如./install_bridge.sh "/path/to/Slay the Spire 2"。
第 3 步:启用模组并验证连通
通过 Steam 启动游戏,在模组管理器中启用STS2_Bridge,然后执行:
cli-anything-sts2 state只要返回 JSON(而非连接错误),即表示 CLI 与桥已连通。常见的连接失败原因包括:游戏未运行、模组未安装/未启用、localhost:15526上的 API 尚未就绪。
基本命令与交互方式
# 读取规范化游戏状态(始终从这里开始) cli-anything-sts2 state # 无子命令时进入交互式 REPL(默认行为) cli-anything-sts2 # 查看全部可用命令 cli-anything-sts2 --helpREPL 模式在 slay_the_spire_ii_cli.py 中实现:cli组通过invoke_without_command=True在未指定子命令时自动进入repl。REPL 内部复用同一 Click 命令树——每行输入会被shlex.split后重新喂给cli.main(),因此REPL 内可用命令与命令行完全一致;支持help查看快捷键、quit/exit退出。会话内每行命令都会透传--base-url与--timeout上下文,保证与当前连接一致。
# 交互会话示例 # > slay_the_spire_ii [http://localhost:15526] ❯ state # > slay_the_spire_ii [http://localhost:15526] ❯ play-card 0 --target jaw_worm_0 # > slay_the_spire_ii [http://localhost:15526] ❯ end-turn命令组全览
状态检查
| 命令 | 说明 |
|---|---|
state | 返回带decision字段的规范化状态 |
raw-state | 返回桥接模组的原始 JSON |
state的实现是先调用client.get_state(format="json")拿到原始状态,再交给normalize_state()规范化(state_adapter.py);raw-state则直接透传原始 JSON,供调试或排查规范化问题使用。
主菜单
| 命令 | 说明 |
|---|---|
continue-game | 继续已保存的局 |
start-game --character IRONCLAD --ascension 0 | 开启新一局 |
abandon-game | 放弃当前存档 |
return-to-main-menu | 从任意界面返回主菜单 |
start-game两个参数均有默认值(--character默认IRONCLAD,--ascension默认0)。目前支持的角色为:IRONCLAD(铁甲战士)、SILENT(沉默猎手)、DEFECT(故障机器人)、NECROBINDER、REGENT。动作负载由action_adapter.start_new_game(character, ascension)构造,测试用例 test_core.py 验证了角色与进阶等级会被原样保留。
战斗
| 命令 | 说明 |
|---|---|
play-card <index> [--target <enemy_id>] | 打出手牌(按手牌序号) |
use-potion <slot> [--target <enemy_id>] | 使用药水(按槽位) |
end-turn | 结束当前回合 |
--target是可选参数:源码中play_card()仅在显式传入 target 时才向负载中加入target字段(见 action_adapter.py),这一点也被单测test_play_card_without_target_omits_target_field专门覆盖。enemy_id格式如jaw_worm_0,需要从state返回的enemies列表中读取。
地图与房间流转
| 命令 | 说明 |
|---|---|
choose-map <index> | 选择地图节点 |
proceed | 离开当前房间 |
choose-map对应动作choose_map_node,规范化地图状态中包含next_options(下一层可选节点)、current_position、visited、nodes与boss等信息。
奖励
| 命令 | 说明 |
|---|---|
claim-reward <index> | 领取战斗奖励 |
pick-card-reward <index> | 选择卡牌奖励 |
skip-card-reward | 跳过卡牌奖励 |
claim-treasure-relic <index> | 领取宝箱房遗物 |
select-relic <index> | 选择遗物 |
skip-relic-selection | 跳过遗物选择 |
事件与篝火
| 命令 | 说明 |
|---|---|
event <index> | 选择事件选项 |
advance-dialogue | 推进纯对话类事件 |
rest <index> | 选择篝火动作 |
规范化事件状态里in_dialogue/is_ancient两个布尔字段可以辅助判断应使用event还是advance-dialogue。
商店
| 命令 | 说明 |
|---|---|
shop-buy <index> | 购买商店物品 |
规范化商店状态会把条目按category拆分为cards、relics、potions与card_removal(删牌服务),便于 Agent 按类别直接取用对应索引。
卡牌/遗物选择覆盖层
| 命令 | 说明 |
|---|---|
select-card <index> | 在覆盖层中选择卡牌 |
confirm-selection | 确认当前选择 |
cancel-selection | 取消当前选择 |
combat-select-card <index> | 战斗中的卡牌覆盖层选择 |
combat-confirm-selection | 确认战斗卡牌选择 |
战斗内的hand_select与战斗外(如事件、宝箱)的card_select使用两套不同命令,分别对应combat_select_card/combat_confirm_selection与select_card/confirm_selection动作,使用时务必与decision字段匹配。
原始动作
| 命令 | 说明 |
|---|---|
action <name> --kv key=value | 发送任意桥接动作 |
这是 CLI 的逃生舱口,可发送未封装成高级命令的桥接动作。--kv可重复传入key=value,值会被自动做类型推断:纯数字转为int,true/false(不区分大小写)转为布尔,其余保留为字符串(见 slay_the_spire_ii_cli.py 的_parse_kv_pairs/_coerce_value)。例如:
cli-anything-sts2 action custom --kv floor=12 --kv urgent=trueE2E 测试 test_full_e2e.py 验证了action命令会向假桥服务器精确发送{"action": "custom", "floor": 12, "urgent": true}负载。
决策状态机:Agent 的路由依据
state返回的规范化 JSON 中decision字段标识当前游戏画面,是决定下一步命令的唯一依据。Skill 文档定义的决策类型与典型后续命令如下:
| 决策 | 含义 | 典型后续命令 |
|---|---|---|
menu | 主菜单 | continue-game、start-game |
combat_play | 战斗中、轮到你的回合 | play-card、use-potion、end-turn |
hand_select | 卡牌选择覆盖层(战斗中) | combat-select-card、combat-confirm-selection |
map_select | 地图节点选择 | choose-map |
game_over | 本局结束 | return-to-main-menu |
combat_rewards | 战斗后奖励 | claim-reward、proceed |
card_reward | 卡牌奖励选择 | pick-card-reward、skip-card-reward |
event_choice | 事件界面 | event、advance-dialogue |
rest_site | 篝火 | rest |
shop | 商店界面 | shop-buy、proceed |
card_select | 卡牌选择界面 | select-card、confirm-selection |
relic_select | 遗物选择 | select-relic、skip-relic-selection |
treasure | 宝箱房 | claim-treasure-relic、proceed |
从源码看,决策值由normalize_state()依据桥接模组返回的state_type分发映射产生(state_adapter.py):monster/elite/boss→combat_play,hand_select、card_reward、combat_rewards、map、event、rest_site、shop、card_select、relic_select、treasure、game_over、menu一一对应。除上述类型外还有两种附加决策:overlay(保留原始 overlay 负载的通用覆盖层)与unknown(未识别类型时回退,同时保留raw_state_type与完整raw负载便于调试)。
STS2.md中进一步汇总为 15 种决策类型:menu·combat_play·hand_select·map_select·game_over·combat_rewards·card_reward·event_choice·rest_site·shop·card_select·relic_select·treasure·overlay·unknown。
战斗状态的规范化输出(_normalize_combat)值得重点关注,它同时暴露了round、turn、is_play_phase、energy、max_energy、hand、enemies、draw_pile_count、discard_pile_count、exhaust_pile_count等关键字段——Agent 可以根据能量判断能否打出某张手牌,根据牌堆数量估算抽牌风险,再决定play-card或end-turn。
配置项
| 选项 | 默认值 | 说明 |
|---|---|---|
--base-url | http://localhost:15526 | 桥接 API 地址 |
--timeout | 10.0 | HTTP 超时(秒) |
两个选项由 Click 在 slay_the_spire_ii_cli.py 中定义,作用于整个命令树(REPL 会透传)。例如:
cli-anything-sts2 --base-url http://127.0.0.1:15526 --timeout 20 state--timeout会被传入Sts2RawClient并作用于每次urlopen调用;超时或连接失败时,sts2_backend.py会抛出包含诊断信息的ApiError(如提示"游戏是否已运行且模组已启用"),CLI 将其转换为非零退出码与 stderr 错误信息。
面向 AI Agent 的使用约定
Skill 文档为程序化调用总结出四条铁律,全部可从实现上得到印证:
- 始终先读
state获取decision字段,再决定动作——因为决策状态决定了当前可用的命令集合; - 每次动作后重新读
state——战斗中手牌序号、能量、敌方 ID 都会实时变化(如打出一张牌后hand列表长度减一,序号失效); - 检查返回码——0 表示成功,非零表示错误;CLI 的
main()会把ClickException输出到 stderr 并以对应退出码返回; - 解析 stdout 的 JSON——
state、raw-state、action等命令均将 JSON 以缩进格式输出到 stdout,ensure_ascii=False保证中文等字符不被转义。
除 Skill 文档外,包内 README(agent-harness 内 README.md)还补充了两条建议:涉及文件操作时使用绝对路径;以及优先使用state而非raw-state作为常规决策依据。
源码与测试佐证
项目用 14 个自动化测试(tests/TEST.md)锁定了核心行为,可作为二次开发或排障时的行为规范:
- 单元测试(test_core.py,9 个用例):覆盖动作负载工厂(
play-card的 target 条件包含、start-new-game参数保留、from_name分发与非法动作拒绝)以及状态适配器(战斗 →combat_play、商店条目分类拆分、菜单能力字段、覆盖层透传、未知类型回退到unknown)。 - E2E 测试(test_full_e2e.py,5 个用例):启动本地假 HTTP 服务器模拟桥接 API,验证
--help、raw-state、state、action --kv、continue-game的子进程行为,无需真实安装游戏即可运行。
这些测试同时示范了三种真实工作流场景:先raw-state再state的决策前检查、用action发送一次性桥接动作、以及用continue-game走类型化动作工厂。
故障排查速查
| 现象 | 排查方向 |
|---|---|
state无法连接 | 游戏未运行;STS2_Bridge未安装或未启用;localhost:15526API 未就绪 |
build.sh找不到游戏目录 | 确认游戏已安装后,用STS2_GAME_DATA_DIR="/path/to/data_sts2" ./build.sh显式指定 |
| 动作命令返回非零退出码 | 用raw-state检查当前decision是否支持该动作,必要时用action <name> --kv …直接调试桥接动作 |
结语
cli-anything-slay-the-spire-ii以"游戏内桥接模组 + 本地 HTTP API"的架构,把真实《杀戮尖塔 2》的全部关键交互面暴露为标准命令行与 JSON 状态,使脚本与 AI Agent 得以按"读状态 → 判决策 → 发动作"的循环稳定驱动游戏流程。本文覆盖的命令面、决策状态机与配置项均以 SKILL.md 为骨架、以仓库源码与测试为印证;更完整的桥接模组原始 API 说明可继续查阅 bridge/plugin/docs/raw_api.md 与 STS2.md。
【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考