简体中文 · 繁體中文 · English · Español
DeepSeek Harness 插件,为《星露谷物语》提供 41 个操控工具,并补充 MCP 层无法覆盖的部署自检与游戏生命周期管理。
开发与维护约定(给 AI Agent)见 AGENTS.md。
本仓库是一个 dsh 组合包(bundle),作用于 DeepSeek Harness 的 profile 层。
游戏逻辑不在此实现。全部 41 个工具由 Junimo-MCP 的 junimo-mcp.exe(OCaml,单文件)提供,经官方 @deepseek-ai/dsh-mcp-client 以 stdio MCP 协议桥接,模型侧呈现为 mcp__junimo__<工具名>。本仓库不修改 Junimo-MCP 的任何代码。
插件自身承担四项职责:
- 装配 MCP 桥接,并提供
junimoPaths服务作为 exe、skill 目录的唯一真源 - 向系统提示词注入星露谷操作纪律,规避时序与存档类常见错误
- 注册 4 个原生工具:诊断、窗口聚焦、游戏启动、读档
- 在 dsh Web UI 右侧边栏注册一块只读的「季历面板」
第 3 项无法由 MCP 工具实现——mod 运行于游戏进程内部,不能启动自身进程,也不能将自身窗口置前。第 4 项由一条宿主路由加一份预构建的客户端 bundle 实现,见「季历面板」。
junimo-mcp.exe 已随包内置(bin/,v3.3.1,6 MB),安装插件后无需另行获取二进制。
模型 ──mcp__junimo__*──▶ dsh-mcp-client ──stdio──▶ junimo-mcp.exe ──HTTP──▶ 执行器 mod ──▶ 游戏
▲ ▲
dsh-junimo 装配 原样复用,未修改
+ 4 个原生工具
| 组成 | 提供方 | 说明 |
|---|---|---|
| 41 个游戏工具 | @deepseek-ai/dsh-mcp-client + 内置 exe |
感知、移动、交互、界面、农活、箱子、社交、节日、生计 |
| 4 个原生工具 | 本插件 | junimo_doctor / junimo_focus / junimo_game_launch / junimo_load_save |
| 提示词纪律 | 本插件 | 系统提示词段落 junimo:rules,约 1000 字符 |
| 随包 skill | @deepseek-ai/dsh-skill-filesystem |
skills/junimo/,按需加载,不占常驻上下文 |
| 参考文档 | 本插件 | reference/game-semantics.md,含工具速查表与已知边界 |
| 季历面板 | 本插件 | 右侧边栏只读面板:宿主路由 GET /junimo/panel + 预构建的 client/index.js |
| 项 | 要求 |
|---|---|
| 操作系统 | Windows(内核与插件、mod 三层的平台现状不同,见「平台支持」) |
| dsh | >= 0.2.1-rc.2(声明于 package.json 的 dsh.engines) |
| 游戏 | Stardew Valley 1.6.x |
| SMAPI | 4.x(junimo_game_launch 依赖它启动) |
| POSIX shell | Git for Windows 或 WSL 的 bash,用于启动游戏。缺失时退回 cmd,可正常启动,但会多出一个 SMAPI 控制台窗口 |
| 执行器 mod | JunimoBridge v0.3.2,安装至 Mods/JunimoBridge/(端口 7850);也兼容 NagiBridge-Remix(Mods/NagiBridge/,7842) |
SMAPI 与 mod 的安装步骤见 Junimo-MCP 的 AGENTS.md。
JunimoBridge 采用 MIT 许可(本项目的姊妹仓库,只实现真正在用的那批端点,报文与 NagiBridge 对齐)。NagiBridge-Remix 采用 PolyForm Noncommercial 1.0.0,个人与非商业用途免费。本项目不打包任何 mod 代码。原版 NagiBridge 与 Remix 的 UniqueID 不同,同时安装会争用 7842 端口,切换时需先移出旧目录。
# 本地 checkout
dsh plugin --profile web add link:/path/to/dsh-junimo
# 或直接从 GitHub 安装(纯 ESM 源码,无构建步骤)
dsh plugin --profile web add github:mlkgrnt/dsh-junimodsh plugin add 会初始化 profile,并将本包追加至 dsh.profile.bundles。重启 dsh 后生效。
安装后执行 junimo_doctor 完成链路检查。该工具输出 exe 路径与版本、7850 端口状态、mod 响应、存档就绪状态、SMAPI 与执行器 mod 文件完整性,以及 SMAPI 日志中的错误行。
从 GitHub 安装时若提示构建脚本未授权,将 pnpm 给出的包键加入 profile 的
pnpm-workspace.yaml的allowBuilds。本包不含构建步骤,通常不会触发。
| 变量 | 默认值 | 说明 |
|---|---|---|
JUNIMO_MCP_BIN |
内置 bin/junimo-mcp.exe |
覆盖内置 exe,用于升级、回退或使用自编译版本 |
STARDEW_GAME_DIR |
自动探测 | 含 Stardew Valley.exe 的目录;未设置时依次尝试 Steam 库与常见安装路径 |
STARDEW_API_URL |
http://localhost:7850 |
mod 端点。必须使用 localhost,127.0.0.1 会被系统拒绝 |
STARDEW_AUTO_MENU |
1 |
透传给 exe:自动应答无选项对话 |
STARDEW_AUTO_EVENT |
未设置 | 透传给 exe:自动跳过剧本事件,默认关闭 |
exe 自身的其余变量(STARDEW_HTTP、STARDEW_SETTLE 等)见 Junimo-MCP 的 README,同样可通过 cordis.patch.yml 中的 env 透传。
profile 的 cordis.patch.yml 按 id 覆盖插件行。patch 会整体替换 config,需完整重述所有键:
- insert:
- id: junimo-mcp
name: '@deepseek-ai/dsh-mcp-client'
inject: [junimoPaths]
config:
serverName: junimo
transport: stdio
command: 'D:\tools\junimo-mcp.exe'
args: []
env: { STARDEW_API_URL: 'http://localhost:7850' }
cwd: 'D:\tools'
toolCallTimeoutMs: 180000
failOnStartupError: true| 工具 | 用途 |
|---|---|
junimo_doctor |
链路诊断。只读,不执行修复。操作游戏前应首先调用 |
junimo_focus |
将游戏窗口置前。JunimoBridge ≥0.3.0 默认开启后台操控,最小化后照样能操作,日常不用调;只在排查焦点问题、或用旧执行器(NagiBridge)时才需要 |
junimo_game_launch |
通过 StardewModdingAPI.exe 启动游戏并等待 7850 响应;已在运行时不会重复启动。SMAPI 是控制台程序,直接 spawn 会秒退,因此优先经 bash 启动,找不到 bash 才退回 cmd |
junimo_load_save |
聚焦窗口 → 点击 Load → 点击存档格 → 轮询至 worldReady,失败时整轮重试 |
junimo_load_save 的难点在于时机而非坐标。TitleMenu.receiveLeftClick 在淡入与转场期间会静默丢弃点击,因此实现采用「等待界面稳定 → 点击 → 以 worldReady 判定 → 整轮重试」。坐标基于 1280×720 窗口模式的标题界面。
分工刻意分开,别把长文档塞进常驻提示词:
| 层 | 放什么 | 什么时候进上下文 |
|---|---|---|
MCP tools/list |
41 个工具的参数定义与描述 | 自动,模型调工具时本来就有 |
systemPrompt.section |
9 条时序纪律 + 一个指向长文档的路径指针 | 常驻,约 1KB |
reference/game-semantics.md |
「我想… → 用哪个工具」决策速查表、标准工作日、常见错误、原始端点逃生通道、已知边界 | 按需读,模型遇到相应任务才加载 |
skills/junimo/SKILL.md |
一页最短流程 + 三条最容易翻车的 | skill 命中时加载 |
所以不需要另附一份「各工具使用说明」:参数重复一遍只会加 token,真正有价值的是「什么时候用哪个、组合顺序、回执怎么读、哪些坑别踩」,都已经在 game-semantics.md 里。新增工具时同步那张速查表即可。
其中 story 的 choose 在 junimo-mcp.exe 内部采用两段式:默认路径先向游戏登记答案,若界面未推进则自动补发一次真实点击。实机验证(宠物领养事件)选完即推进到下一幕。调用方不需要、也不应再补第二发点击。
插件在 dsh Web UI 的右侧边栏注册一块只读观测面板「星露谷季历」,把游戏当前状态摊在对话旁边,便于人随时对照模型正在做什么。
展开右侧边栏(Ctrl+Shift+B)后点「星露谷季历」即可。面板分三块:
| 区块 | 内容 |
|---|---|
| 季节卡 | 季节、第几年、日期、星期、周数、天气图标、当前时刻,以及当日进度条 |
| 季历 | 4×7 排满一季 28 天;周末有底色,今日高亮,节日与赶不上的节日各有标记 |
| 状态卡 | 玩家名、所在地图与坐标、朝向、HP 与体力条、金钱、手持物、背包(水壶附水量);菜单打开时显示菜单类型,剧本事件进行中时显示剧情横幅 |
日历下方另给下一个节日的名称与倒计时(如「灵魂之夜 · 秋 27 日 5 天后」)。
浏览器打不通 http://localhost:7850:桌面端页面运行在 dsh-app:// 协议下,直连既不跨源,也会被该自定义协议拦下。因此面板数据由插件在宿主进程内代理:
浏览器 ──GET /junimo/panel──▶ dsh 宿主(本插件的 webServer 路由) ──HTTP──▶ 执行器 mod /state ──▶ 游戏
src/panel.js 把 mod 面向模型的中文长文本状态收成前端可直接渲染的小 DTO:数值字段一律兜住类型(mod 在部分阶段会给 null 或字符串),缺字段退化为空值而不抛错。
前端每 5 秒轮询一次,请求带 AbortSignal,面板卸载即取消。
面板是观测面,异常不该让浏览器拿到坏响应——路由任何情况下都返回 200 与可渲染的 JSON:
| 场景 | 表现 |
|---|---|
| 游戏未启动 / mod 未加载 | 头部灰化为「未连接」,日历仍按当前季节渲染,状态卡显示「连不上游戏(mod 没起来,或游戏没开)」 |
| 停在标题界面、尚未进档 | 同上,标注「未进档」 |
| mod 响应超时 | 仍返回 200,附 error 字段(默认 2.5 秒超时,模态界面下 mod 会挂住) |
面板路由挂在 ctx.inject(['webServer']) 里按需注册,不放进插件的顶层 inject。headless / tui profile 没有 webServer 服务,若在顶层声明这个依赖,整个插件——包括 41 个工具的装配与提示词段落——会一起激活不了;按需注入时缺服务只是这一条不生效。
客户端 bundle 由 package.json 的 dsh.client 字段声明(platform: web),依赖 dsh-client-ui-renderer / dsh-client-ui-tool / dsh-client-ui-sidebar-right;client/index.js 是预构建产物,安装后无需再构建。
node scripts/sync-binary.mjs # 取 Junimo-MCP 的最新 release
node scripts/sync-binary.mjs v3.3.1 # 或锁定指定 tag脚本下载 exe 与官方 SHA-256,本地校验通过后才覆盖 bin/,并同步更新 bin/BUNDLED_VERSION。完成后需 git add bin/ 并提交。
当前内置版本见 bin/BUNDLED_VERSION。
src/index.js 插件入口:junimoPaths 服务、提示词段落、4 个工具注册
src/paths.js exe / 游戏目录 / 包内资源的解析与探测
src/api.js 执行器 mod 的最小 HTTP 客户端(探活与时序兜底)
src/doctor.js junimo_doctor 的检查项与渲染
src/game.js 聚焦、启动、读档
src/panel.js 季历面板 DTO:把 mod 的 /state 收成前端可直接渲染的形状
client/index.js 季历面板的客户端 bundle(预构建,直接由宿主 serve)
docs/ README 用的截图
skills/ 随包 skill
reference/ 按需读取的长文档
scripts/ 维护脚本
test/ 冒烟与真机验证脚本
源码为纯 ESM JavaScript,无构建步骤,src/*.js 即发布产物。
node test/smoke.mjs # 离线冒烟,不需要游戏与 dsh 宿主
node test/verify-load-save.mjs # 真机:启动游戏、读档,校验 worldReady
node test/verify-load-save.mjs --existing # 游戏已手动启动时,仅验证读档
node test/panel-dto.mjs # 面板 DTO:各类畸形输入都退化成「没连上」
node test/client-bundle.mjs # 客户端 bundle 的结构与组件渲染断言
node test/render-panel.mjs out.html dark # 出静态预览(light | dark | offline)离线冒烟校验 junimoPaths 服务、提示词段落、4 个工具的注册结果、启动命令的转义、面板路由(GET 200 / POST 405),并执行一次 junimo_doctor。它依赖 node_modules/@deepseek-ai/dsh-tools 的本地 stub 以支持直接以 Node 运行;实际部署中该包由 dsh 宿主提供。
dsh plugin --profile <name> add link:/path/to/dsh-junimo
dsh --profile <name> --dump-config | grep -A8 junimo # 确认三层均已进入组合
dsh --profile <name> --no-open # 启动;出现 "entries did not activate" 即为异常本插件目前只在 Windows 上可用,但原因分布在三层,不是整块缺失。分清这一点对判断移植成本很重要:
| 层 | 平台现状 | 依据 |
|---|---|---|
OCaml 内核(junimo-mcp.exe 的内容) |
已跨平台,且已发布 macOS / Linux 产物 | 依赖只有 yojson + unix,源码无平台分支;CI 在 Linux / macOS / Windows 三个 runner 上跑通全部免游戏断言;产物发布前会在各自平台上再跑一遍 |
| 本插件(进程启动、窗口聚焦、路径探测) | 仅 Windows | 聚焦用 user32,启动走 PowerShell 与 bash,Steam 库按盘符探测 |
| 执行器 mod | 部分仅 Windows | JunimoBridge 的虚拟输入走进程内 InputState.UpdateStates 补丁(本身可移植),Win32 只用于 /focus 置前与前台判据;NagiBridge-Remix 的 /press_key / /click_tile 才走 keybd_event / mouse_event,/click 在有菜单或带 no_mouse 时走进程内调用 |
本插件随包只带 Windows 的 junimo-mcp.exe。macOS / Linux 用户可以从 Junimo-MCP Releases 取对应产物(junimo-mcp-macos-arm64 / junimo-mcp-linux-x86_64),用 JUNIMO_MCP_BIN 指过来即可使用 41 个工具中的大部分;junimo_doctor 在非 Windows 上会直接给出该平台对应的下载地址,而不是笼统地报「找不到 exe」。
但插件本身的 junimo_focus / junimo_game_launch / junimo_load_save 仍然只有 Windows 实现——这三个是插件存在的理由,想用它们需要自己补一份平台适配(聚焦换 osascript / xdotool,路径探测换各平台的 Steam 目录)。移植的边界就到这里。
- 插件目前仅 Windows 可用。窗口聚焦、进程启动与读档依赖 PowerShell 与 user32。但 Junimo-MCP 已有 macOS / Linux 二进制,可自行下载使用或按需移植插件三件套。
- 读档坐标绑定 1280×720 标题界面。已在窗口模式实机验证;其它分辨率需换算,参见
src/game.js注释。 - 内置的
junimo-mcp.exe为 Junimo-MCP 的发布产物(MIT)。本项目不打包任何 mod 代码。
MIT,见 LICENSE。内置的 junimo-mcp.exe 与执行器 mod 各自遵循其原许可。
