🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

尖塔控制台 enderzcx/spire-ctl

DeepSeek Harness
enderzcx43 天前有提交已提供中文文档扫描:含敏感能力

读取游戏状态并合法执行智能体决策动作

28/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/11 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add enderzcx/spire-ctl
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]!
实装验证未通过(dependency_conflict),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
数据截至 2026/10/11·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/03·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 43 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

⚠︎ 实装验证未通过(dependency_conflict · 2026/10/11) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件读取剪贴板或密钥环境变量
查看扫描证据(共 35 处,展示前 35 条)
  • 读取密钥环境变量
    src/controller.mjs:13
    runtimeDir=process.env.SPIRE_RUNTIME_DIR??'.runtime',apiKey=process.env.TYPESAFE_API_KEY,
  • 读取本地文件
    src/controller.mjs:25
    try{await access(join(dir,name));throw Error('Legacy controller state exists; inspect pending actions before migrating');}
  • 删除本地文件
    src/controller.mjs:42
    await rm(join(control,'HALTED'),{force:true});return{cleared:true,...envelope(s)};
  • 读取本地文件
    bin/spire.mjs:14
    return controller.plan(JSON.parse(await readFile(args[0],'utf8')));
  • 读取本地文件
    bin/spire.mjs:19
    const payload=JSON.parse(await readFile(args[1],'utf8'));
  • 读取本地文件
    bin/spire.mjs:29
    const steps=JSON.parse(await readFile(file,'utf8'));
  • 读取本地文件
    bin/spire.mjs:55
    return controller.saveStrategy(JSON.parse(await readFile(args[0],'utf8')));
  • 读取本地文件
    src/dispatch.mjs:10
    export const CORE_VERSION=JSON.parse(readFileSync(new URL('../package.json',import.meta.url),'utf8')).version;
  • 写入本地文件
    src/dispatch.mjs:23
    await mkdir(dir,{recursive:true});const lock=join(dir,'execution.lock');
  • 写入本地文件
    src/dispatch.mjs:24
    try{await mkdir(lock);}catch(e){if(e.code==='EEXIST')throw Error('Another controller owns execution; do not run two agents at once');throw e;}
  • 删除本地文件递归
    src/dispatch.mjs:25
    try{return await fn();}finally{await rm(lock,{recursive:true});}
  • 写入本地文件
    src/dispatch.mjs:28
    export function recorder(dir){return async data=>{await mkdir(dir,{recursive:true});await appendFile(join(dir,'events.jsonl'),JSON.stringify({at:new D
  • 写入本地文件
    src/dispatch.mjs:28
    export function recorder(dir){return async data=>{await mkdir(dir,{recursive:true});await appendFile(join(dir,'events.jsonl'),JSON.stringify({at:new D
  • 写入本地文件
    src/dispatch.mjs:31
    await writeFile(join(control,'HALTED'),JSON.stringify(payload));
  • 读取本地文件
    src/dispatch.mjs:35
    try{await readFile(join(control,'HALTED'));throw Error('Previous action outcome unknown: inspect game and clear the halt explicitly');}
  • 写入本地文件
    src/dispatch.mjs:41
    await writeFile(join(control,'HALTED'),JSON.stringify({reason:'in_flight',expectedId,option}),{flag:'wx'});
  • 删除本地文件
    src/dispatch.mjs:54
    await rm(join(control,'HALTED'));
  • 读取密钥环境变量
    src/jev.mjs:18
    export async function choose(state,options,{apiKey=process.env.TYPESAFE_API_KEY,fetcher=fetch,signal,
  • 读取本地文件
    src/strategy.mjs:114
    try{strategy=JSON.parse(await readFile(strategyFile(dir),'utf8'));}
  • 写入本地文件
    src/strategy.mjs:126
    await mkdir(dir,{recursive:true});
  • 写入本地文件
    src/strategy.mjs:127
    await writeFile(strategyFile(dir),JSON.stringify(strategy,null,2));
  • 删除本地文件
    src/strategy.mjs:131
    await rm(strategyFile(dir),{force:true});
  • 写入本地文件
    src/strategy.mjs:156
    await mkdir(dir,{recursive:true});
  • 读取本地文件
    src/strategy.mjs:158
    try{journal=JSON.parse(await readFile(journalFile(dir),'utf8'));}catch(error){if(error.code!=='ENOENT')throw error;}
  • 写入本地文件
    src/strategy.mjs:164
    await writeFile(journalFile(dir),JSON.stringify(journal,null,2));
  • 读取本地文件
    src/strategy.mjs:170
    const journal=JSON.parse(await readFile(journalFile(dir),'utf8'));
  • 删除本地文件
    src/strategy.mjs:176
    await rm(journalFile(dir),{force:true});
  • 写入本地文件
    src/strategy.mjs:190
    await mkdir(dir,{recursive:true});
  • 读取本地文件
    src/strategy.mjs:192
    try{store=JSON.parse(await readFile(guardFile(dir),'utf8'));}catch(error){if(error.code!=='ENOENT')throw error;}
  • 写入本地文件
    src/strategy.mjs:195
    await writeFile(guardFile(dir),JSON.stringify(store,null,2));
  • 删除本地文件
    src/strategy.mjs:200
    await rm(guardFile(dir),{force:true});
  • 读取本地文件
    src/effects.mjs:46
    try{return {...SEED,...JSON.parse(await readFile(fileFor(dir),'utf8'))};}
  • 读取本地文件
    src/effects.mjs:53
    try{store=JSON.parse(await readFile(path,'utf8'));}catch(error){if(error.code!=='ENOENT')throw error;}
  • 写入本地文件
    src/effects.mjs:62
    if(changed){await mkdir(dir,{recursive:true});await writeFile(path,JSON.stringify(store,null,2));}
  • 写入本地文件
    src/effects.mjs:62
    if(changed){await mkdir(dir,{recursive:true});await writeFile(path,JSON.stringify(store,null,2));}
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 读取游戏状态
  • 执行合法动作
  • 无重放执行

为 Slay the Spire 2 提供经过验证的控制面:JSON 状态契约、合法动作,以及面向任意智能体框架的无重放执行。零 npm 依赖。

README

由 DeepSeek 最新模型翻译生成
spire-ctl 给智能体用的《杀戮尖塔 2》控制面。 一个 JSON 状态契约、一份合法动作清单、一套不会重放的执行层——任何能跑命令、读 JSON 的 harness 都能驱动游戏。零 npm 依赖。 不截图、不做视觉识别、不模拟点击:通过本地 Mod 读结构化状态,调用游戏原有的动作队列。 你的智能体(任何 harness) ↓ state / act / seq spire-ctl:合法动作枚举 → 校验发送 → 结算核对 ↓ 游戏原有动作队列 STS2 本地桥接(Mod) 最省事的安装方式 把 安装提示词 整段复制给你的智能体,它自己装完并验证。 dsh plugin --profile web add github:enderzcx/spire-ctl # 控制器(同时是 CLI 和 DSH 插件) node bin/spire.mjs doctor # 体检:找不到游戏/Mod 没装/桥接没起,都会说清楚 Mod 是唯一需要写进游戏目录的一步,doctor --install-mod 会先给计划、校验 SHA256、并拒绝在游戏运行时写入。
展开完整文档(README 剩余 1 节)
spire-ctl

给智能体用的《杀戮尖塔 2》控制面。 一个 JSON 状态契约、一份合法动作清单、一套不会重放的执行层——任何能跑命令、读 JSON 的 harness 都能驱动游戏。零 npm 依赖。

不截图、不做视觉识别、不模拟点击:通过本地 Mod 读结构化状态,调用游戏原有的动作队列。

你的智能体(任何 harness) ↓ state / act / seq spire-ctl:合法动作枚举 → 校验发送 → 结算核对 ↓ 游戏原有动作队列 STS2 本地桥接(Mod)

最省事的安装方式

把 安装提示词 整段复制给你的智能体,它自己装完并验证。

dsh plugin --profile web add github:enderzcx/spire-ctl # 控制器(同时是 CLI 和 DSH 插件)
node bin/spire.mjs doctor # 体检:找不到游戏/Mod 没装/桥接没起,都会说清楚

Mod 是唯一需要写进游戏目录的一步,doctor --install-mod 会先给计划、校验 SHA256、并拒绝在游戏运行时写入。

它保证什么

这个项目的价值不在"能玩",而在出错时的行为:

| 保证 | 含义 |
| 拒绝旧状态 | 状态一变,旧标识立即失效,不能沿用上一轮的手牌索引 |
| 单写者锁 | 同一端口只允许一个操作者;两个智能体不会同时出牌 |
| 不自动重试 | 发送失败或结果无法确认 → 持久停止,等人核实,绝不重发 |
| 结算核对 | 每个动作读回确认;没确认就不算完成 |
| 非法动作发不出去 | 动作只来自游戏自己广告的选项,不自造 ID |
| 算不清就停 | 未知机制、空意图、无法覆盖的致命攻击 → 交回调用方,不猜 |

它不承诺什么

不是自动通关机器人。 决策归你(或你的模型),spire-ctl 只保证"决定下来的动作被合法、可核对地执行"。默认没有取胜策略,也没有胜率保证。

快速开始

1. Mod(必需)

下载 sts2-bridge Releases 里对应平台的包,按 INSTALL.txt 放进 Mod 目录。先关闭游戏并备份存档。

验证桥接:

curl --noproxy '*' http://127.0.0.1:15526/
{"message":"Hello from STS2 MCP v0.4.0","status":"ok"}

Mod 只绑定回环地址。不要把端口转发到公网。

2. 控制器

git clone https://github.com/enderzcx/spire-ctl.git && cd spire-ctl
node bin/spire.mjs state # 只读:当前局面、可选动作、状态标识

state 不改变任何东西。先读 操作合同。

3. 接管

node bin/spire.mjs seq STEPS.json # 一次提交一整回合的既定动作
node bin/spire.mjs act STATE_ID OPTION_ID

CLI 全部命令:

| 命令 | 用途 |
| state | 读状态、合法动作、路由原因、本次状态标识 |
| act STATE_ID OPTION_ID | 执行一个动作 |
| seq STEPS.json | 执行一串已决定的动作,逐步重读逐步校验 |
| plan PLAN.json | 带预测的多卡前缀(预测不符即停) |
| battle [MAX] [STRATEGY.json] | 交给可选的快速决策模型连续打 |
| advance [MAX] | 只做机械推进(领金币、推进对话、固定按钮) |
| clear-halt STATE_ID | 核实实际局面后,清除停止标记 |
| strategy / save-strategy | 查看/保存显式续行条件 |

seq:为什么它比逐张 act 好

逐张出牌 = 每张一次进程启动 + 一次 HTTP + 调用方重读一遍完整 JSON。而且 card_index 是位置——打掉一张,后面所有索引都会漂移(实测踩过:本想打剑柄打击,落到了灰烬打击上)。

seq 让你一次提交整回合,并且按卡牌 id 指定而不是位置:

{
"expected_state_id": "…",
"steps": [
{"card": "FLAME_BARRIER"},
{"card": "TOXIC"},
{"card": "DEFEND_IRONCLAD"},
{"action": "end_turn"}
]
}

每一步都从新的已结算状态重新解析、重新匹配游戏广告的动作,再走和 act 完全相同的事务(旧状态拒绝、单写锁、停止标记、结算核对)。任何一步不再被广告——牌离手了、目标死了、回合结束了——序列在打出任何东西之前停下,并把当时的可用动作返回给你。

它也适用于非战斗界面:一次买齐商店、一趟领完奖励。

分工

程序负责算术与合法性,调用方负责决定:

| 场景 | 谁 |
| 等待动画结算、核对旧状态 | 程序 |
| 动作是否合法、目标是否存在、能量是否够 | 程序 |
| 精确伤害/格挡/斩杀线(基于游戏自己算好的意图) | 程序 |
| 出哪张牌、打哪个敌人、药水取舍、路线、构筑 | 调用方 |
| 陌生意图、可能致命且挡不下、结果无法确认 | 程序停下,交回调用方 |

battle 里可以挂一个可选的快速决策模型(默认 TypeSafe Jev)来接管普通战斗回合;不用它完全可以——state + act + seq 就是完整闭环。详见 docs/AGENT.md 与 决策层级。

在 DeepSeek Harness 里用(可选)

同一个包既是 CLI 也是 DSH 插件,一条命令:

sh
dsh plugin --profile web add github:enderzcx/spire-ctl

装完 spire_state / spire_act / spire_seq / spire_advance 等原生工具就能直接调用,不用拼 shell 命令。

核心运行时不依赖 DSH。 bin/ 与 src/ 从不 import 适配器,@deepseek-ai/dsh-tools 是可选 peer 依赖——所以别的 harness(Claude Code、纯 shell、自己的 agent)照样能只用命令行。这条边界由 test/boundary.test.mjs 守住。

其他 harness 照旧: sh
node bin/spire.mjs state

从终局开新局

正规入口,不碰存档、不碰设置、不进多人: sh
node bin/spire.mjs state # game_over → 只有 main_menu
node bin/spire.mjs act STATE 0 # 回主菜单

依次 singleplayer → standard → 选角色 → embark

menu 只广告安全动作:continue/singleplayer/compendium/settings、standard/back、已解锁角色与 confirm/embark/back。abandon_run、quit、multiplayer、daily、custom 和锁定时间线一律不出现。

工程

- src/game.mjs — 状态 → 合法动作广告;route() 决定谁来决策
- src/dispatch.mjs —唯一的发送事务:锁、停止标记、结算核对、事件日志
- src/runner.mjs — battle / advance / sequence 三个循环
- src/combat.mjs — 已知/未知效果与结果推演的唯一算术
- src/contract.mjs — 面向消费者的稳定状态契约(如商店条目统一命名)
- src/decision.mjs + src/jev.mjs —可选的快速决策模型适配
- bin/spire.mjs — 通用 JSON 命令行
- scripts/probe-api.mjs — 只读接口探针:逐界面核对决策所需字段是否齐全 sh
npm test # 离线回归
npm run check # 语法与静态检查
node scripts/probe-api.mjs # 需要游戏在跑
node scripts/metrics-jsonl.mjs .runtime/events.jsonl --turns 6

metrics-jsonl 区分 turn_ms(首次出牌到结算)、action_ms(游戏动画)与 agent_gap_ms(出牌之间等模型/编排),并统计本地决策的类别与原因。

离线测试不能证明游戏兼容性。 每个真实局面都只能对着跑起来的游戏验证。

多处调用可以并发读,但只能有一个操作者。锁只防本项目自己;它挡不住你手动出牌或其他工具直接操作游戏。

兼容性

在 macOS arm64、游戏 v0.107.1 上验证。游戏或上游 Mod 的 API 变化可能让字段改名——那样控制器会明确报错而不是静默继续。支持范围与未验证场景见 验证记录。

卸载

关闭游戏,移走 Mod 文件,从 Steam 重启。不要拿旧存档覆盖新进度;备份只为确认需要的恢复。

来源与许可证

MIT。Mod 是 sts2-bridge,基于 Yikun Ji 的 STS2MCP(MIT)并附一个补丁。

本仓库不包含游戏程序集、游戏素材、个人存档或任何凭据。 日志里不含 API key。
预览分享卡片长什么样 ↓enderzcx/spire-ctl
分享 · DeepSeek Harness Hub
enderzcx/spire-ctl

读取游戏状态并合法执行智能体决策动作

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部