Skip to content

Releases: yzi1b/whale-craft

v0.2.0-beta.3

Choose a tag to compare

@github-actions github-actions released this 18 Oct 09:38

whale_craft v0.2.0-beta.3

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.2.0-beta.3] - 2026-10-18

预览版,面向 DSH 0.2.0-rc.2 及以上(含 0.2.1-rc.2)。预览版可能存在未知问题,如遇到请向我们反馈。

0.2.0-beta.1 / beta.2 的用户建议升级到本版本。本版本修复了在 0.2.1-rc.2 版本的 DSH 上开始 MC / MC+ 模式会话会报错 unknown prompt variable "{{cwd}}" 的问题。

相较于 0.1 的变更,详见 0.2.0-beta.1 更新日志。

  • 【新增】联网搜索功能。可以在设置中选择是否启用,MC+模式不受限制
  • 【新增】网页抓取功能。可以在设置中调整是否启用,指定允许的域名和内容形式。支持下载图片
  • 【新增】策略获取工具 mc_kit_rules,助理可以知悉自己可以使用的MC指令和可抓取的网站及内容形式
  • 【新增】文件系统工具 mc_kit_fs,助理可以复制、移动、删除文件和新建目录,受权限策略限制
  • 【变更】桌面模式文件分享与网页端不同,指定端口分享文件
  • 【变更】移除长期记忆工具 mc_kit_memory。现在完全使用文件读写工具编辑记忆。记忆文件夹与既有记忆不受影响
  • 【变更】不再自动注入 .whale-craft/README.md 记忆索引,由助理主动读取
  • 【变更】调整MC模式dsh原生工具暴露面,现在允许调用的工具更多更标准化
  • 【修复】在 DSH 0.2.1-rc.2 上新建 MC / MC+ 模式会话直接报错 unknown prompt variable "{{cwd}}"。新版宿主提示词不再使用该变量

v0.2.0-beta.2

Choose a tag to compare

@github-actions github-actions released this 06 Oct 13:06

whale_craft v0.2.0-beta.2

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.2.0-beta.2] - 2026-10-06

预览版,面向 DSH 0.2.0-rc.2 及以上。相较于 0.1 的变更,详见 0.2.0-beta.1 更新日志。预览版可能存在未知问题,如遇到请向我们反馈。

0.2.0-beta.1 因存在致命问题无法使用,请使用此版本。

  • 【修复】从 npm 安装后插件完全不加载(启动只报 dsh: warning: 1 entry did not activate / failed to import)。根因在 DSH 宿主自身的模块解析器(与本插件无关),这一版在插件内加了绕过,registry 安装即可正常加载(issue #5)

v0.2.0-beta.1

Choose a tag to compare

@github-actions github-actions released this 06 Oct 11:52

whale_craft v0.2.0-beta.1

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.2.0-beta.1] - 2026-10-06

预览版,面向 DSH 0.2.0-rc.2 及以上。0.2.0 正式版功能尚未全部完成,本版本先行发布已完成功能,以及支持 DSH 0.2.0-rc.2 和 DSH Desktop。预览版可能存在未知问题,如遇到请向我们反馈。

  • 【新增】现在提供“MC模式”和“MC+模式”。前者专注于MC游戏,只能调用游戏相关工具;后者既可以进行游戏,还可以完成编程等任务,可以另外调用标准模式全部工具
  • 【新增】“连接到MC”快速提示词投放功能。现在MC模式、MC+模式窗口中会有“连接到MC”按钮,点击后在打开的窗口中填入服务器信息(或选择本地服务器),选择用户,即可快速发送让助理进入服务器的指令
  • 【新增】MC模式和标准模式会话可以迁移到MC+模式。对应会话中末条助手回复下会有“方块”图案的“创建MC+分支”按钮,点击即可
  • 【新增】现在宿主“插件”页面可以看到本插件名称、描述等信息,提供“设置”按钮,点击可以进入设置
  • 【新增】获取游戏上下文 mc_context、获取在线玩家 mc_players、获取高度图 mc_height 三个工具
  • 【新增】MC设置页面在没有选择工作区时也可以进入(通过宿主插件设置页),与工作区有关的配置会标注出来
  • 【变更】DSH 版本范围要求 >=0.2.0-rc.2 <0.3.0
  • 【变更】MC / MC+ 之外的模式不再暴露 mc_* / mc_kit_* 工具
  • 【变更】工作区的配置现记录在 .whale-craft/config.json,该配置文件MC模式下的Agent不可更改。旧配置会自动迁移
  • 【变更】提示词注入设置现在下放到工作区
  • 【变更】mc_connect / mc_ping 工具参数调整,使用单 address 参数指定地址,版本自动探测
  • 【变更】mc_accounts 工具去掉 use action、mc_lan 去掉 mode 参数
  • 【变更】mc_map 工具参数调整,dist 写文件、reply 是否回上下文。取消默认输出目录
  • 【变更】mc_status 工具定位调整,现在作为获取连接信息的工具,另外也会返回游戏上下文
  • 【变更】移除 MC 26.2 按键上报兼容层,现在不支持 MC 26.2
  • 【变更】文件分享不再具有模式,只有开关(expressEnabled)决定是否开启
  • 【变更】调试工具改名 mc_debug_sessions / mc_debug_diag,由MC设置中“调试”>“开放助手调试工具”控制可见性,默认关闭
  • 【修复】工具组探针静默失效等 5 处(issue #1)
  • 【修复】干净安装 / 官方 dsh-desktop 启动报 failed to import(issue #5)
  • 【修复】v4 会话里提示词注入、看门狗唤醒整轮失败(PR #2 @swan3146)
  • 【修复】看门狗后台任务挂不上、「强制停止」管不到它(PR #2 @swan3146)
  • 【修复】其余小问题的修复与清理

破坏性变更

  1. 插件现要求DSH最低版本为 0.2.0-rc.2,不再支持更低版本。解决方案:将你的DSH升级至 0.2.0-rc.2 及以上版本。
  2. 除了MC和MC+模式外,其余模式无法再调用MC游戏相关工具。解决方案:将需要使用MC工具的会话迁移到MC+模式,找到助手的最后一个回答,点击“方块”图案的“创建MC+分支”按钮。
  3. 此前对Minecraft 26.2的临时支持已移除。解决方案:等待后续版本。MineFlayer支持Minecraft 26.2后,我们会及时跟进。

v0.1.7

Choose a tag to compare

@github-actions github-actions released this 20 Sep 02:06

whale_craft v0.1.7

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.1.7] - 2026-09-20

这一版在 0.1.6 之上修了三个真机问题(都是用户/其他使用者实测报上来的),并订正了几处"状态在撒谎"。
0.1.6 的内容(修皮肤站登录 400)与 0.1.5 的全部内容也都在这一版里,装 0.1.7 就都有了。

🔴 修复(断线后状态不同步:mc_status / 顶部状态条 / AI 都以为还连着)

  • 现象(用户):"连接断开了状态没有同步。mc_status 和顶部状态条都不知道连接断开了,AI 也以为连接还在。"
  • 三处根因(都在,缺一不可):
    1. core 从来不播报"断线":b.on('end') 里只写一行日志,不 emit 任何东西 ⇒ 上层根本没机会知道;
    2. 会话不转发:McSession 只把 spawn/death/reconnect/chat/system/damage 转进事件队列,
      没有断线这一类 ⇒ mc_events 里看不到、AI 也不会被叫醒;
    3. 看门狗没有这条唤醒项,断线后它照旧挂着(watch.armed 还说"在监听"),
      前端 active 也因此继续为真 —— 三处一起撒谎。
  • 修法:
    · core 在连接结束时 emit('offline', { reason, willReconnect, sub })(原因取 lastError,并判断还要不要自动重连);
    · 会话把它转进事件队列(mc_events 看得见);
    · 看门狗新增唤醒项 wakeOn.disconnect(默认开):
    会重连 → 叫醒 AI 说"连接断了(原因)——正在自动重连,先别再操作角色",
    不会重连 → 直接关掉看门狗(关闭通知本来就会告诉 AI"你已不在 MC 里、要用 mc_connect 重新进服");
    · 前端:/api/mc/status 的 active 把"正在自动重连"也算上(否则刚断线状态条整个消失,用户以为插件把状态忘了),
    状态条新增显示 "重连中…"(配 data-mc-reconnecting),不再假装"在游戏中";
    并用 reconnectPending(掉线置位 → 真重连成功 / 手动 mc_connect 成功才清)覆盖"正在尝试连接"那一段,
    否则那几十秒里状态条会从"重连中…"退回"未上线",看着像插件放弃了;
    · 顺手:断线时不再发心跳唤醒(否则会说"我还在游戏里",那是撒谎)。
  • 真实场景验收(本地官方 1.21.1 服务端,连上进服后把服务端进程杀掉):
    offline 事件 {reason:"read ECONNRESET", willReconnect:true} → status() 回
    online:false / ghost:true / reconnecting:true → 看门狗留档有 offline,并把
    「【MC 看门狗|disconnect】连接断了(read ECONNRESET)——插件正在自动重连…」真投给了 AI。
  • 自检:新增 10 条断言(唤醒矩阵有 disconnect / 会重连则排队唤醒 / 不会重连则自动关闭 /
    断线进留档 / 真 socket 断开时 core 确实发出 offline / 会话转队列 / modeView 与
    /api/mc/status 带 reconnecting / 状态条显示"重连中…")。

🔴 修复(mc_events {waitSec} 把唤醒堵住了:等到消息、提及了也不醒,用户空等很久)

  • 现象(用户实测):"等待有时候并不能唤醒!比如等到消息,但是发了消息,就算提及它也没有唤醒,
    让用户空等特别久。反倒是等完之后看门狗注入提示词。"
  • 根因:宿主的 agent.steer 语义是「运行中在下一次 step 边界消费」,
    而 step 边界要等当前这一步的工具调用返回才算到。
    于是 mc_events {waitSec:120} 一堵,看门狗 2 秒前就组好的唤醒文案被压在等待后面,
    直到等待超时才投出去 —— 等待堵住了它正在等的那件事。
  • 修法:
    · 等待逻辑抽成 src/wait.mjs(waitForEvents),多一条收工条件:被唤醒打断;
    · 看门狗在所有注入之前(唤醒 / 关闭通知 / 补提醒 / 心跳——都走 #inject 这一个口子)
    调 sess.interruptWait(kind) 置个标记;等待循环每 250ms 看一眼,见到立刻收工:
    工具一返回 → step 结束 → 唤醒文案当场投出去;
    · 工具返回里明确告诉 AI:interrupted: true + interruptReason +
    「看门狗命中唤醒条件…先别急着再 wait,等那条提示进来」。
  • 实测:被打断时等待 126ms 就返回(原来会把 30 秒/120 秒干等满)。
  • 顺带改掉描述里的一句谎:原描述写"看门狗记录的一切:…被传送、捡物、上下线",
    但那三类不在这个队列里(只在看门狗留档,用 mc_watch {action:"log"} 看)。
    现在描述写清了,并提醒 waitSec 只是兜底(看门狗会主动叫你)、建议 ≤30。
  • 自检:新增 8 条断言(等到事件立刻回 / 被唤醒打断立刻回 / 用户停止立刻回 / 到点才回 /
    看门狗注入前真的会打断(stub 会话记录调用)/ 工具侧接线 / 注入口接线 / 描述不再谎称)。

🔴 修复(连 1.21/1.21.1 进服成功、1 秒后被踢:Failed to decode packet 'accept_teleportation')

  • 现象(其他用户反馈,已本地用官方 1.21.1 服务端完整复现):进服完全成功(服务端日志
    logged in with entity id … + joined the game),紧接着就掉线,服务端报

    Internal Exception: io.netty.handler.codec.DecoderException:
        Failed to decode packet 'serverbound/minecraft:accept_teleportation'
    

    换端口 / 换地址(localhost、回环、局域网 IP)/ 换版本字符串都一样;而连 26.2 却完全正常。

  • 根因:我们的按键上报兼容层(为 26.2 加的、每 50ms 发一次 player_input)是无条件发的,
    但 1.21/1.21.1(协议 767)根本没有 player_input 这个包(1.21.3+ 才有)。
    而 minecraft-protocol 的 protodef 遇到未知包名不报错——实测它写出的字节是

    write('player_input')            → 02 00 00        ← id=0x00、body 为空
    write('definitely_not_a_packet') → 02 00 00        ← 和一个瞎编的包名一模一样
    write('teleport_confirm')        → 03 00 00 07     ← 正常包:id=0x00 + VarInt(7)
    

    服务端于是把 id 0x00 当成它自己注册表里的 accept_teleportation(1.21.x 里确认传送就是 0x00),
    去读 teleportId 时没有字节可读 ⇒ 抛 DecoderException ⇒ 立刻踢人。
    所以错误名与"我们真正发的包"毫无关系,极具误导性。

  • 修法:给 core 加一道"发之前先查这个版本的协议数据里有没有这个包"的护栏(#supportsPacket,
    带缓存),player_input 只在该版本真有它时才发;顺带在每次 tick 也复查一遍(重连可能换版本)。
    查不到的版本会记一行日志说明,而不是硬发。

  • 顺带修掉「幽灵在线」:被踢之后 mineflayer 的 bot.entity 会残留,而 online 只看 entity,
    于是死连接被报成"在线"(工具对着死 socket 干等、世界时间冻结、/list 零响应)。
    现在 online 要求连接没结束,status() 会明确回 ghost: true + 一句"要回游戏里请重新 mc_connect",
    requireBot() 也直接说"连接已结束(bot.entity 是残留)"。

  • 回归测试(自检 + 真机):
    · 自检断言:1.21.1 上一个包都不发、26.2 上照常发、源码里必须留着这道护栏,
    以及"幽灵在线"的三条(online 变 false / status() 标 ghost / requireBot() 明确报错)。
    · 真机复现与验收(本地官方 1.21.1 服务端):修前 1 秒被踢(错误与反馈逐字一致);
    修后稳坐 8 秒不掉线,player_input 发出 0 次、服务端日志再无 DecoderException。

v0.1.6

Choose a tag to compare

@github-actions github-actions released this 19 Sep 10:40

whale_craft v0.1.6

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.1.6] - 2026-09-19

这一版在 0.1.5 之上只加了一个修复。0.1.5 的全部内容(P0 崩溃修复 / mc_lan 只留广播 /
新增 mc_ping / 默认行事准则第五版)也都在这一版里,装 0.1.6 就都有了。

🔴 修复(某个皮肤站账号登录一直 400:authenticate 少了 Yggdrasil 必填的 agent 字段)

  • 现象(用户实测):某个皮肤站的账户怎么都登不上,一直"认证失败 HTTP 400";
    另一个皮肤站(自建、老实现)同一个插件、同一个流程却没事。

  • 根因:/authserver/authenticate 的请求体里少了 agent ——
    它是 Yggdrasil 官方协议里 authenticate 的必填字段(authlib-injector 与官方客户端都会发)。
    我们一直没发,老实现容忍缺省,但换成新实现 Yggdrasil Connect 的皮肤站不容忍:
    缺字段直接回 400(而不是 401/403),于是错误码落在"认证失败 HTTP 400"上,
    看起来像"密码错",其实请求根本没被当成一次登录。

  • 实测对照(2026-09-19,真发请求,同一地址只差这一个字段):

    认证服 缺 agent 带 agent(假账号)
    出问题的那个(Yggdrasil Connect) 400 403(正常走完凭据校验)
    一直正常的那个(老实现) 403 401

    即:"通不通"的差别就在这一个字段上。

  • 修法:authenticate 请求体补上 agent: { name: 'Minecraft', version: 1 }(标准值,官方客户端同款),
    并给 400 单独补了一句人话提示(区分"请求不合规"与"账号密码不对")。
    另外在代码里留了这条事故的说明,防止后人又把 agent 删掉。

  • 回归测试:自检里那个"桩掉 fetch、抓真实请求体"的用例加了两条断言 ——
    请求体必须带 agent(name=Minecraft / version=1)、且源码里保留"缺 agent 会 400"的说明。
    另外真机端到端验过:走插件自己的认证代码打那个皮肤站,现在拿到的是 403(凭据校验),不再是 400。

v0.1.5

Choose a tag to compare

@github-actions github-actions released this 18 Sep 11:54

whale_craft v0.1.5

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.1.5] - 2026-09-18

🔴🔴 修复(P0:连一个不存在的服务器会把整个 DSH 进程搞崩)

  • 现象(用户实测):对 AI 说连一个根本没开的服务器(127.0.0.1:61631),宿主进程直接死:

    Error: connect ECONNREFUSED 127.0.0.1:61631
    Emitted 'error' event on McBot instance at: src/core.mjs:671
    node:events:486   throw er; // Unhandled 'error' event
    

    ——工具报错可以,但绝不能把宿主带走。

  • 根因:McBot extends EventEmitter,而 EventEmitter 的语义是「emit('error') 时若没有监听者就 throw」。
    原来那行把 bot 的网络错误原样转发到 McBot 上:

    b.on('error', (e) => { this.lastError = e.message; this.emit('error', e) })   // ❌

    而 McBot 通常没有 'error' 监听者(工具层是 await 抛错返回,不订阅 error)
    ⇒ 一个"服务器没开"这种再普通不过的错误,就把整个进程带走了。
    另一处(认证阶段)写的是 try { this.emit('error', err) } catch {} —— 假保护:
    抛出来的就是这次 emit 自己,try/catch 拦不住它。
    (与 2026-09-17 那次"未处理 Promise 拒绝 → 宿主 fail-loud exit(1)"是同一族:插件里的错误绝不能漏到宿主。)

  • 修法:把"上报错误"收敛成唯一一个口子 #reportError(e),它保证:

    1. 记 lastError(工具层据此给用户一句人话);
    2. 记一行日志(mc_diag / 日志能看到);
    3. 只在真有监听者时才 emit(listenerCount('error') > 0)—— 没人听就到此为止,绝不 throw;
    4. 自己再兜一层 try/catch(监听者回调里抛错也不该带走进程)。
      两处调用点(bot 的 error 转发、认证阶段 connect() 的 rejection)都改走它。
  • 回归测试(自检里真连一个刚关掉的端口,且故意不订阅 'error' —— 真实工具路径就是这样):
    断言"以普通错误结束"、lastError 带得上 ECONNREFUSED、并且走到后面的断言 = 进程没被带走;
    另加静态断言:代码里每一处 this.emit('error') 都必须带"有监听者才发"的保护
    (注释里的事故引用不计)。

默认行事准则(.whale-craft/RULES.md)第五版:新增「较长思考」整节

  • 内容换成用户给的全文(第四版 2318 字 → 第五版 5911 字节 / 87 行,十个分节):
    宗旨 · 称呼 · 记忆 · 边界信息 · 登录游戏 · 看门狗 · 聊天 · 建筑须知 · 较长思考 · 硬规矩。
  • 新加的整节「较长思考」:长时间思考不给响应会让用户以为你卡住了;
    建议偶尔简短汇报想法——一方面是给用户交代,另一方面这样事件提示词才有注入时机(否则错过新情况)。
  • 「建筑须知」补三条:先把大体结构做完再抠细节 · 每阶段完成要给用户响应并说明还在继续 ·
    建造完成后必须复盘(完整性 / 美观 / 与环境融合),发现问题先修再认定任务完成。
  • 自检同步:断言"第五版十个分节都在"、"建筑须知补的三条都在"、"较长思考讲到
    『长思考要偶尔汇报』『这样事件提示词才有注入时机』"。
  • ⚠️ 想立刻用上这一版:本次发版会带着 0.1.5 的版本号,"随版本更新"(默认开)会自动替换你工作区里那份;
    也可以在「MC设置 → 提示词」里点恢复默认。

🔴 mc_lan 砍掉扫网段:只保留原版那一件事(听局域网公告)

  • 起因(用户):"原版都没有,我们凭什么加!一个工具调用半天,用户又说慢!"
  • 删掉的行为:曾用"① 听多播公告 + ② 扫本机 /24 的 25565-25569 + 手写 STATUS ping"两条路。
    第 ② 条是一个 8.2 秒(实测一个 /24)起步的动作,最坏情况(网段里 TCP 通、但不回 MC 协议)
    单个 /24 可到 100 秒级、多网段可到分钟级——而 defineTool 的 timeoutMs 在宿主里只是元数据、
    没有任何地方真正拿它包超时
    ,所以慢就是真慢。
  • 为什么删得起:它多给的"版本 / MOTD / 人数",在 mc_connect 进服时本来就会拿到
    (mineflayer 传 version:false → minecraft-protocol 的 autoVersion 内部就是同一条 STATUS ping);
    唯一不可替代的"没开公告的服务器",原版客户端自己也找不到 —— 让用户报地址即可。
  • 现在的 mc_lan:只听 224.0.2.60:4445 上"对局域网开放"的公告
    ([MOTD]…[/MOTD][AD]端口[/AD],原版/复刻实现的重发周期 1.5 秒),不扫端口、不主动发包,
    参数只剩 mode(只有 broadcast)与 seconds(默认 3、上限 15)——
    恒定在 seconds 秒内返回,不再是网络扫描器,也再没有分钟级的调用。
  • 顺带:src/lan.mjs 从 313 行缩到 ~80 行,连 node:net 都不再 import(只剩 node:dgram);
    默认行事准则里那句"先扫描局域网服务器"改成"可以先听一下公告,找不到就直接问用户地址"。
  • 回归测试:断言 7 个扫描相关导出全部消失、lan.mjs 里不再出现 TCP/扫描字样、
    工具参数只剩 mode/seconds、返回里没有 scanned 字段;
    并在回环上真发三条公告(合法 / 垃圾 / 重复)验证"听得到 + 垃圾被丢 + 同 host:port 去重",
    以及 seconds=1 到点就返回、seconds=999 被夹到 15 秒。

✨ 新增 mc_ping:已知地址时的单地址探测(通不通 / 版本 / MOTD / 人数 / 延迟)

  • 起因(用户):"有没有 ping 的工具?已知地址,测试通透性和 motd 等信息,单地址。"
    —— 砍掉扫段之后,"知道地址、但想先看一眼再进服"这件事确实没有工具可用。
  • 做什么:发一次 Minecraft STATUS ping(握手 nextState=1 + ping_start),拿到:
    通不通(能不能拿到状态响应)/ 版本 / 协议号 / MOTD(颜色码已去)/ 在线与上限人数 /
    延迟(写 ping 到收 pong 的往返)。🔴 不登录、不用账户、不进服,拿到就断。
  • 和别的工具的分工:mc_lan = 不知道地址时听局域网公告;mc_ping = 知道地址时主动探一次;
    mc_connect = 真进服(要账户、会掉线重连)。默认行事准则里加了「有明确地址时先 mc_ping 探一下再进服」。
  • 为什么不直接用上游的 mc.ping()(踩过的坑,写下来免得后人再踩):
    ① 它不暴露 client,想在超时时真掐掉连接就得覆盖 options.connect ——
    而 ping.js 结尾正是 options.connect(client),覆盖掉它 = 谁都不建 socket:
    实测四种场景(通的 / 端口没人听 / 只 accept 不回包 / 域名错)全都只能干等自己的硬超时;
    ② 它的超时是 closeTimeout,默认 120 秒,对一次工具调用太长。
    所以改成用同一套底层(Client + states + tcpDns,锚在解析到的 mineflayer 上)自己走一遍包序,
    超时与清理自己掌握(默认 5 秒、上限 30 秒;无论成功/失败/超时都 end() + destroy())。
  • 错误说人话:ECONNREFUSED=端口没人听 · ENOTFOUND=域名解析不了 · ETIMEDOUT=连上了没回应 ·
    ECONNRESET=被服务端重置……认不出的原样回。任何失败都收敛成 {ok:false, error, hint},
    绝不把异常冒泡
    (工具报错可以,带走宿主不行——就是 0.1.5 那条 P0 的教训)。
  • 回归测试(自检里真起一个 MC 服务端):起一个 minecraft-protocol 服务端(离线模式、1.21.4、
    MOTD 带颜色码、max-players=7)在回环上,断言 ping 到版本 1.21.4/协议 769/人数 0/7/
    MOTD 颜色码已去;另外断言"端口没人听 → 立刻 ECONNREFUSED"、"黑洞连接 → 1.2 秒被硬超时掐掉
    (不是等上游 120 秒)"、"域名解析不了 → 指向 DNS";以及地址解析的合法/非法各 4 种写法。

🧹 「MC设置 → 提示词」页去掉两条多余提示

  • 起因(用户):"提示词页『还没到投递时机(提示词在发起请求之前现场判定并投递;这个会话还没发过消息)|
    「注入工作区 AGENTS.md」是关的』这个提示框多余了,删掉。"
  • 那行判据里,本会话注入:MC模式 ✓/✗ | 本提示词 ✓/✗ | 工作区 AGENTS.md ✓/✗ 已经把答案摆出来了;
    再说一遍"还没到投递时机 / 开关是关的"是重复信息。
  • 留下的(这些是看不出来、又真的影响投递的原因,不能删):没有 agent 上下文 · 这个会话没选工作区 ·
    不是 MC 模式(连 preset 名一起说)· 工作区根目录里根本没有 AGENTS.md 这个文件 ·
    preset 的 persona 压掉了宿主运行期上下文(带怎么修)。
  • 于是正常情况那一行整行不再渲染(前端对 notes.length === 0 本来就不渲染)。

v0.1.4

Choose a tag to compare

@github-actions github-actions released this 18 Sep 09:20

whale_craft v0.1.4

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.1.4] - 2026-09-18

默认行事准则(.whale-craft/RULES.md)第二版:新增「建筑须知」整节

  • 默认内容换成新一版(1821 → 2318 字):新增整节 「建筑须知」 ——
    与环境相互影响/避让改造 · 方块属性与 NBT(楼梯方向、台阶、火把灯笼附着)· 多部分方块(门窗床)·
    受连接影响的方块(栅栏栏杆墙)· 细节与功能连通性 · 建成后复盘。
  • 「聊天」补明:游戏中用户在聊天时第一时间回复,之后再做深度思考与行动。
  • ⚠️ 版本号没变 ⇒ 插件自带的「随版本更新」不会自动替换你工作区里那份。
    想立刻用上这一版:在「MC设置 → 提示词」里点恢复默认(或手动覆盖 .whale-craft/RULES.md)。

🔴 修复(提示词晚一步才注入:跟用户那句不在同一批)

  • 现象(真机):会话里能看到提示词,但是 LLM 已经跑起来之后才出现的——
    用户的原话是"两个全都是 LLM 运行了一半才后知后觉地注入,根本不是用户发送第一条信息后注入"。
  • 根因:上一版把投递挂在 agent/pre-step,但塞进了 inbox.nextStep 队列。
    而宿主的顺序是 preStep() 里先 inbox.claim()(把这一步的消息领走)再跑
    agent/pre-step 瀑布(core/agent-loop/src/agent.ts:244 → :249)——
    所以那一步塞进队列的提示行这一步用不上,要等下一步才被领走。会话日志实测:
    step/start step=1 → 用户那句 → next-step -3 → step/start step=2 → 三条提示行。
  • 修法:照宿主官方插件 agent-instructions 的写法,改写 decision.messages
    (context/agent-instructions/src/index.ts:313-338):交棒拿回 decision 后,把提示行
    并进本步消息的最前面。宿主紧接着在 agent.ts:373-377 把 decision.messages
    逐条落成会话日志的 user/message 并作为请求里的那批消息 —— 既是正规通道(可持久化、可重放),
    又能当场生效:提示行与用户那句同一批送给模型,模型第一眼就看到规矩。
  • 顺带修掉两个自己埋的 bug(都会被 catch 吞掉、表现成"静默不注入",极难查):
    • reconcileNotices 的几处提前返回漏了 todo 字段 ⇒ enterWithNotices 读 .length 抛 TypeError;
    • 用了没导入的 versionPromptHash ⇒ ReferenceError。
  • 另修:切出 MC 模式时无条件清投递台账(老代码按"队列非空"判断,而现在提示行在本步就送出、
    队列通常是空的 ⇒ 漏清 ⇒ 切回来再也不投);并给会话日志划一条"切出时刻"的线,
    这样"切出 → 再切回"能正常重投,不会被日志里的旧投递记录误判成"已经投过"。

改进(「MC设置」入口:选中 MC 模式就显示,工作区改到点击时检查)

  • 以前:MC 模式但没选工作区时,插件会把「MC设置」入口藏起来——用户只看到"没有按钮",
    不知道是为什么。起因是更早的规则"没有工作区就拒绝 MC 模式会话与设置"。
  • 现在:只要选中了 MC 模式就显示按钮(有没有工作区都显示),工作区改到点按钮那一刻再检查:
    • 有工作区 → 正常打开设置;
    • 没工作区 → 弹一句原生提示,告诉用户"请先在这个对话里选择一个工作区",
      并说明原因(记忆与提示词都放在工作区的 .whale-craft 目录里,没有工作区就没地方放)。
  • 两个入口(新对话页模式芯片右边、已有会话标题条)口径统一;顺带去掉了一条
    "服务端说不显示就不显示"的网络依赖。
  • 服务端行为没变:没工作区仍然不套工具白名单、不注入提示词、不建 .whale-craft/;
    设置接口在没有工作区时仍然拒绝(400 + 明确原因)。变的只是入口可见性。
  • /api/mc/mode 现在额外报 hasWorkspace,并且不再因为"没工作区"把 mcMode 压成 false
    (那正是前端藏入口的旧依据);诊断里仍写 reason: 'no-workspace'。

🔴 修复(P0:装了这个版本,所有模式的所有会话每一轮都失败)

  • 现象:随便发一句话,界面显示 本轮运行失败 Cannot read properties of undefined (reading 'kind');
    标准模式、MC 模式一视同仁,等于装了插件就没法对话。会话日志里 turn/start 之后直接 turn/end{kind:"error"},
    连 step/start 都没有。

  • 根因(0.1.4 引入):0.1.4 把提示词注入挂到了 agent/pre-step,而这条事件是 cordis 的 waterfall,
    监听器必须调用 next() 交棒。0.1.4 的写法只声明了一个形参、函数体也没有 return next():

    // ❌ 0.1.4(事故写法)
    ctx.on('agent/pre-step', ({ agent } = {}) => { reconcileNotices(agent) })

    cordis 的契约是明确的(@deepseek-ai/cordis 的 waterfall() 注释原话):
    "a listener that does not call next() vetoes the rest of the chain, including the built-in behavior"
    —— 不交棒 ⇒ 否决后面所有监听器和宿主内置行为,且 waterfall 的返回值就是那个监听器的返回值(undefined)。
    宿主拿到 undefined 后紧接着读 decision.kind ⇒ TypeError ⇒ 整轮失败。

  • 修法:接第二个形参并交棒,且交棒不受对账结果影响(对账挂在 next() 返回值的 finally 上,
    内层无论成功失败都保证先交过棒;next 不接受参数、载荷沿用原 args,所以原样返回内层结果即可):

    // ✅ 0.1.5
    ctx.on('agent/pre-step', ({ agent } = {}, next) => {
      const inner = next()
      ...
      return inner.finally(() => { try { reconcileNotices(agent) } catch { ... } })
    })
  • 为什么自检没拦住(补上了):原来的自检全部在插件自己的进程里直接调函数,绕开了宿主的编排,
    所以"契约违规"测不出来。现在补了三层:

    1. 替身按宿主契约行事 —— agent/pre-step 的替身在监听器没交棒时当场抛错,
      任何一项用到它的断言都会红(旧写法必挂);
    2. 横切静态检查 —— 扫描源码里所有 ctx.on('<事件>', …),凡是宿主已登记的 waterfall 事件
      (agent/pre-step、agent/request、tools/execute、system-prompt/assemble 等 14 个)
      都必须接 next 并调用它;并带负向验证(把事故写法喂给同一判据,必须判违规);
    3. 真 cordis 集成探针 —— 用宿主实际装的那份 cordis 起一个真 Context,注册插件的监听器,
      走一遍 waterfall(),断言内层被执行、返回值不是 undefined 且带 kind。
  • 教训:挂到 waterfall 之前先读那个 dispatch 模式的契约,别只看事件签名;"抛错"和"不交棒"一样致命。

修复(提示词注入的挂载点搬到了正确的地方)

  • 背景:DSH 的「模式」(agent preset)只允许在对话开始前切换——第一轮一旦跑过,
    宿主就拒绝换(agent-preset/locked)。也就是说,模式的最终值是在你发出第一句话、马上要送给模型
    的那一刻才定下来的。而插件此前是在会话刚建立 / 你点模式芯片的那一瞬间就把提示词排进了投递队列,
    比"定下来"早了一步。
  • 后果:在空白会话里先点「MC模式」、又说一句话都没发就点回「普通模式」时,
    那三条提示词已经排在队列里等着了 —— 你随后第一次开口,它们就注进了一个普通模式会话
    ("MC 行事准则 + 版本提示 + 记忆索引"出现在标准模式的对话里,而且会一直留在历史里)。
  • 现在:提示词改在 agent/pre-step(宿主那条"消息已被取走、系统提示词已装好、这一步马上发给模型"
    的流水线)现场对账后投递 —— 投出去的每一份都对应发起这次请求时这个会话真正在用的模式,
    串模式从根上不再可能。
    • 不是 MC 模式 ⇒ 一条都不投;是 MC 模式且这个模式还没投过 ⇒ 投三条。
    • 幂等:按模式记账(同一个模式只投一次)+回读会话日志(进程重启 / 插件重载后,台账没了,
      也不会把已经注过的再注一遍)+队列里已有同名提示行就不重复入队;正文变了(改了行事准则 / 记忆索引更新 /
      换了插件版本)则就地替换队列里那一条,不会新旧两份同时出现。
    • 顺带删掉了旧实现里那段"已经注过的补一条作废声明"的圆场逻辑 —— 不再需要了。

修复(切出模式时漏清投递台账,会导致提示词再也不投)

  • 自检里逮到的真 bug:切出 MC 模式时清掉了待投递队列,却没清投递台账 ⇒ 再切回 MC 模式时,
    插件误判"这个模式已经投过了",一个字都不再投。现在两者一起清。

修复(🔴 提示词一条都没注入:依赖里少了 @deepseek-ai/dsh-llm)

  • 现象(真机报的):npm 装到另一台机器上之后,工具一切正常,但提示词注入了没有 ——
    AI 自己都说"没看到",对话窗口里也没有那几行。
  • 原因:插件用宿主提供的 createUserMessage() 来构造那几条"插件提示行",而这个函数来自
    @deepseek-ai/dsh-llm —— 它当时根本没写进依赖声明。在开发机上碰巧能解析到(那份
    node_modules 里有指向宿主源码的链接),别人正常 npm i 装出来的插件目录里没有这个包、
    往上也找不到 ⇒ 函数拿不到 ⇒ 提示行一条都建不出来。
    而"工具白名单/文件边界"那两道只用插件上下文、不碰任何宿主包 ——
    所以症状精确地是"工具都在、提示词全无"。更糟的是旧代码在拿不到函数时静默返回,
    只在日志里留一行,界面上完全看不出来。
  • 修法(两条腿):
    1. 不再依赖宿主包:消息构造统一收到 src/user-message.mjs —— 优先用宿主实现,
      拿不到就用插件自带的等价实现(字段与宿主 UserMessage 逐个对齐:
      role / content / source / id)。提示词注入从此与环境无关;拿不到时明确记一行日志。
    2. 依赖声明补上 @deepseek-ai/dsh-llm(optional peer + devDependency,范围 *),
      让有宿主包的环境走宿主实现。
  • 同一次事故还有第二处:mc_watch(看门狗)用同一招构造"有人喊你/你被打了一下"的提示行,
    拿不到宿主包时它会退化去调 sessionController.prompt —— 那是用户来源消息,
    会在对话里冒充你说话。现在它也走 user-message.mjs,不再有那条退化路径。
  • 自检新增断言:共用模块必须在 · 自带等价实现必须在 · 形状对齐 · 仍优先宿主实现 ·
    看门狗也用同一个模块 · 并报出本次跑的是宿主实现还是自带实现。
  • 验证方式:造了一个"只有 dsh-llm 缺失"的环境(正是那台机器的情形)跑完整自检 ——
    全绿(修之前那里有 9 条红:看门狗退化成用户消息),关键投递断言照样通过。

改进(投递失败不再静默)

  • 拿不到宿主的消息构造函数时,以前只是静默返回(表现成"工具都好使、提示词一条都没有",
    还查不出原因);现在会明确记一行日志说明原因。

v0.1.3

Choose a tag to compare

@github-actions github-actions released this 17 Sep 11:00

whale_craft v0.1.3

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.1.3] - 2026-09-17

默认行事准则(.whale-craft/RULES.md)更新

  • 「称呼」不再写死:默认叫 Master,用户指定了就按用户指定的来("以记忆为准"那条保留)。
  • 对 DSH 这个称呼/缩写同样敏感(以前只写"AI 相关称呼")。
  • 「看门狗」里的错字改正("一遍在用户提到你时…" → "以便在用户提到你时…")。
  • 「聊天」新增一条:用户在游戏里跟你说话时,第一时间先回一句,别让他干等;
    之后再做深度思考和行动,必要时干完再回一次。
  • 其余不变(记忆、边界信息、登录流程、看门狗单通道、硬规矩)。

修复(部分 DSH 版本上「切不进 MC 模式」)

  • 插件自动创建的「MC模式」在部分 DSH 版本上加载失败,切换时报:
    无法切换到「MC 模式」:… persona (@deepseek-ai/dsh-persona): invalid config: - $text missing required value。
    原因:persona 的"人设正文"字段名跨 DSH 版本变过 —— 老版是 text,新版是 prefix,
    而此前我们写死了 prefix。
  • 现在两种都支持:键名跟着你那份 DSH 自带的源 preset 走(源用 text 就用 text,源用 prefix
    就用 prefix),我们只替换它的正文值;绝不新增对方 schema 里没有的键;认不出结构就一行都不动并记日志。
  • 启动自检 + 自动修复:每次启动都检查插件自己建的那份 preset,发现 persona 键名与本版本不符
    (或 complete: true 还在)就自动改对 —— 升级插件即可修好老环境,不必手工编辑 preset 文件。
    (自建规格 MC_PRESET_SPEC 升到 6:升级时会把旧规格建的 preset 重建一遍。)
  • 边界不变:只有插件自己建的 preset 会被动;你手写/改过的那份(无自建标记或组成被改过)一律不碰。

修复(切出 MC 模式后,工具白名单不会撤销)

  • 从「MC模式」切回普通模式后,那个会话的工具面仍然停留在 MC 白名单上 —— 表现是普通模式的会话
    连 shell 都没有(没有 pwsh,也没有 subagent / workflow 这些),看起来像"标准模式坏了、
    命令执行不了"。原因:tools.restrict() 造成的可见性限制是黏的(挂在会话自己的 scope 上,
    会话不死就不消失),而插件此前只"套用"、从不"撤销"(restrict() 返回的撤销手柄被丢掉了)。
  • 现在双向:切进 MC模式 → 套白名单;切出 → 撤销,并把该会话从"MC 模式"兜底名单里移出;
    再切回来还能重新套上(不会一次撤销就永久不管了)。
  • 「管理工具硬锁」与「文件只能读写 .whale-craft/」那两道本来就在每次调用现场判定,
    切出模式即刻失效;只有工具白名单是黏的,这次补上了与它对称的撤销。

修复(切出 MC 模式后,MC 提示词与游戏事件仍会灌进普通会话)

  • 切到「MC模式」再切回普通模式,MC 的行事准则 / 版本提示 / 记忆索引照样会被注入。
    原因:这几条是排队投递的(放进会话的"待投递"队列,到下一条消息进来时才真正投递)。
    "切到 MC模式 → 一句话没发 → 切回普通模式"的会话,那几条还躺在队列里等着,你一开口就投进了一个
    普通模式的会话。
  • 现在切出 MC 模式时撤回它们:还在队列里的直接删掉;已经进过对话(摘不掉)的,
    补一条一行作废声明("本会话已退出 MC 模式,上面那条行事准则自此刻起作废"),
    免得模型继续按 MC 的规矩办事。切回 MC 模式会重新投递(不是一次撤销就永久不管)。
  • 看门狗不再往已退出 MC 模式的会话里灌游戏事件:狗是"黏"的(挂载状态在会话上,切模式不会自动关),
    以前切回普通模式后它仍会把"有人叫你 / 你被打了一下"注进会话。现在加了一道模式闸门:
    切出即闭嘴、切回自动恢复(不必重新挂载)。
  • 说明:bot 本身不会被自动踢下线(避免切一下模式就断开你正在玩的游戏)。
    退出 MC 模式后想下线,说一声或调 mc_disconnect。

v0.1.2

Choose a tag to compare

@github-actions github-actions released this 17 Sep 05:33

whale_craft v0.1.2

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.1.2] - 2026-09-17

修复(重要:0.1.1 里有一条会把整个 DSH 带崩的路径)

  • 一条没人接的 Promise 拒绝会让 DSH 进程直接退出(控制台表现:dsh: fatal load failure: Error: ForbiddenOperationException,然后进程没了)。两个成因都堵掉了:
    • 离线账户被当成"有凭据":连接时会把假令牌递给会话服务器,被认证服拒绝。现在按账户类型给开关:
      离线账户不报备(haveCredentials=false),只有皮肤站账户才带令牌去会话服务器。
    • 第三方库的回调 / Promise 不兼容:皮肤站令牌失效时,minecraft-protocol 用老式回调调
      yggdrasil 的会话 join,而新版 join 是 async 且不调那个回调 ⇒ 拒绝无人接管。
      插件侧补了一层兼容:替它把回调调起来,并保证不再有悬空拒绝。
    • 同类风险一并处理:登录后回写账户信息、启动刷凭据索引、preset 自建自检这三处"顺带做的事"
      现在都有兜底,失败只记日志。
  • 认证被拒时给出可执行的指引:不再是天书异常,而是"这个账户的登录状态已失效 ——
    请到「MC设置」重新登录它(或点「刷新」)"。
  • 新增**"遗言"记录**:万一宿主仍因未处理拒绝退出,插件会在它退出前把那条拒绝的调用栈写进插件日志,
    下次不必再靠猜。

其它

  • 仓库新增本机发版工具(npm run publish:npm)与 RELEASING.md;CI 的发布工作流不再碰 npm,
    产物改 zip、Release 正文取自本文件(不再自动生成 diff 链接)。

v0.1.1

Choose a tag to compare

@github-actions github-actions released this 17 Sep 04:57

whale_craft v0.1.1

dsh plugin --profile web add github:yzi1b/whale-craft   # 或解压附件后:dsh plugin --profile web add link:<目录>

装完重启 DSH(服务端插件不热重载)。

[0.1.1] - 2026-09-17

新增

「文件分享」:发布区里的文件怎么给你

  • 「MC设置」多了一页「文件分享」,两种模式(默认关闭):
    • 关闭:AI 调 mc_kit_express 时只会得到一句提示,于是把文件的绝对路径告诉你,你自己打开;
    • 在线:AI 得到完整 URL,图片可以直接在对话里显示。
  • 分享地址改为 <base>/api/whale-craft/express/<工作区 uuid>/<相对 .express 的路径>。
    用 DSH 工作区注册表里的稳定 id,而不再是目录名 —— 不同父目录下的同名工作区不会撞,
    目录改名后链接也不失效,URL 里也不暴露目录名。
  • 在线模式需要填 base(你访问这台 DSH 用的地址)。base 那一行有「获取当前」:
    一键用你现在访问页面的地址填好并保存;切到「在线」而 base 还空着时也会自动填一次。
    不切模式、不点按钮,则不会去动它。
  • 「清除分享数据」:二次确认后清空当前工作区 .express/ 里的所有文件(目录本身重建)。与分享模式无关,随时可点。
  • 只有「在线」模式会开启那条访问路由;关闭模式下访问一律 404。

「随版本更新」:提示词跟着插件版本走

  • 「MC设置 → 提示词」新增开关,默认开启:插件升级后,用新版本的默认行事准则替换
    <工作区>/.whale-craft/RULES.md(会覆盖你的修改)。判定靠记忆目录里的 .rules-version 标记。
  • 想长期保留自己那份,把它关掉即可:关掉后插件永不动它,而且不会"攒着"——
    以后再打开也不会突然覆盖。
  • 从 0.1.0 升级到 0.1.1 这一次不会替换你的文件(第一次遇到这个开关只记下版本号)。

修复

  • GET /api/mc/presets 在真机上一直返回 404(漏在了设置接口的分派名单之外),
    导致界面只能靠内置兜底名单判断哪些 preset 算 MC 模式。现在可达。
  • mc_map 的工具说明不再声称"返回值里带现成的 markdown"——那个字段早已移除,
    取交付一律走 mc_kit_express。

变更(不兼容)

  • 「文件分享」的旧地址 /api/mc/whale-craft/<工作区目录名>/… 已停用(一律 404),
    旧链接请让 AI 重新取一次。
  • 原先的「Windows 本地」模式已移除(它只是把绝对路径原样回给 AI,而前端不认本地路径,
    点不开也内联不了)——只剩「关闭」和「在线」。
  • AI 拿到的交付内容只来自 mc_kit_express 那一行;别的工具返回值里不再有任何分享字段。

自检

  • 离线断言 512 → 594 条:新增文件分享两种模式、工作区 uuid 解析与查找、
    「随版本更新」的四种情形、发布区新路由与信任栅栏、clientOrigin 精准取值等。