Repository navigation
feat(minimax-bot): 群接力的跳数上限与摘要交接(默认关闭) - #68
Apageoflove wants to merge 1 commit into
Conversation
MyPrototypeWhat
left a comment
There was a problem hiding this comment.
感谢这个 PR。两道护栏默认关闭、只放在面板里,relay-guard.mjs 写成纯函数,测试也补齐了。我在本地拉了 711fa19 跑了一遍,下面是几点意见。
需要修改
1. 护栏关闭时,英文界面下的群常驻简报不再逐字一致
我实际生成了护栏全关时的群常驻简报,拿 711fa19 和 main(0.7.8)的输出逐字节比较:英文下多了一个空格(main 是 "...from a private chat.\n\n## Team",这个 PR 是 "...from a private chat. \n\n## Team"),中文一致。原因在 plugins/minimax-ai/minimax-bot/miniapp/node/engine.mjs:381:数组末尾总会追加 relayGuard ? t('brief.groupOneOwner') : '',然后整体 join(t('brief.sentenceJoin'))。中文的 brief.sentenceJoin 是空串(strings.mjs:245),英文是一个空格(strings.mjs:554),所以护栏关闭时英文末尾会多一个空格。这和 PR 描述里"护栏关着时与官方版逐字一致"的说法不符,已有会话升级后也会看到简报变化。群提示词(groupPrompt)本身中英文都一致。
建议只在需要时才把这一句放进数组,例如:
[
t('brief.groupNoPost'),
...(relayGuard ? [t('brief.groupOneOwner')] : []),
].join(t('brief.sentenceJoin'))另外,tests/relay-guard.test.mjs:169 那条"逐字一致"的测试比较的是同一份新代码在开/关两种状态下的输出,所以没能发现这个问题。建议补一个断言:护栏关闭时简报不以空格结尾(或者直接和一份 0.7.8 的基准字符串比较),中英文各测一次。
可选建议
- 收口回合实际是第 N+1 回合,而且没带 taskId:描述和
README.md:36说收口"替代被拦下的那一跳,不是额外多一轮"。但看实现,到上限时被拦下的那一跳并没有执行(engine.mjs:1177、engine.mjs:1217),而convergeGroup会让最后发言的 Bot 再跑一次模型回合(engine.mjs:341),所以一轮实际跑 limit+1 次模型回合;README.md:105写的 "spends one extra Agent turn" 反而更贴近实现。另外,链里其他回合都会传taskId: options.taskId(engine.mjs:1190),收口回合的调用(engine.mjs:341,参数从 engine.mjs:1230 传入)没有带taskId,由任务派发进来的群接力,收口这一回合就不会挂在原任务下。建议把描述/README 统一成一种说法,并给收口回合也带上taskId。 - 服务端没有上限:面板
panels.js里的输入框写了max: 20,但relay-guard.mjs:58的hopLimit只处理了下限,通过 HTTP 接口直接 PATCH 一个很大的数也会被接受。可以在hopLimit里也夹一下上限,和面板保持一致。 - replyMode 为 all 时的行为:engine.mjs:1177 的检查在队列里还有人时就会收口。"所有人回复"模式下初始队列本身就有多个成员,这时上限会截掉后面的成员,并让最后一个发言的成员做收口。如果这是有意为之,在面板提示或 README 里提一句会比较清楚;如果不是,可以只统计由 @ 交接产生的跳数。
- 交接内容可能重复:上一位的回复本身已经出现在下一位提示词的"新消息"里(groupPrompt 会列出来),交接块又把它的尾部带了一遍。这不影响正确性,只是在描述里说明一下交接块的定位(强调结论),能帮使用者判断要不要打开它。
- 版本号:这个 PR 把版本升到 0.7.9,#56 目前也是 0.7.9。两者谁后合入,谁就需要再升一个版本(plugin.json、package.json、mcp.mjs 里的 serverInfo 以及 README 的版本小节),这里先提个醒。
我这边核对过的
- 改动只在插件目录内,没有读写 dataDir 以外的东西,没有新增文件读写或网络调用。
- 模型这一侧改不了这两个设置:MCP 的
create_group/update_group都没有新增参数(mcp.mjs 里的 schema 和参数转发都没变),list_team返回的字段也没变,硬塞max_hops/handover不会生效,测试里也覆盖到了。面板走的 HTTPPATCH /api/groups/:id(server.mjs:615)会把请求体原样交给updateGroup,和其他群字段一样,这是面板自己的写入路径。 - 护栏关闭时
groupPrompt不加任何内容,接力循环的行为和之前一致(limit 为 0 时两处新判断都不会触发)。 - 新测试放在插件自己的
tests/里,仓库根目录test/没有改动。 - 本地结果(Node 22):先在插件的
tests/里执行npm ci,再跑node --test tests/*.test.mjs,231/231 通过;不装依赖时会有 7 个 UI/jsdom 相关的测试文件失败,main 上也是同样这 7 个。仓库根目录npm run check通过 validate,69 条测试全部通过。
主要就是第 1 点,改完我再看一眼。
给群接力加两道护栏,都是群自己的字段,默认都是关的:maxHops 填 0 表示不限,和现在完全一样;handover 默认 false。
跳数上限说的是一条消息引发的接力链最多几个 Bot 说话。到上限时不再 @ 别人,群里给一条系统提示(已达接力上限(N 跳),本轮讨论在此收口),并让刚说话的那个 Bot 收个口。这个收口是一个模型回合,替代被拦下的那一跳,不是额外多一轮。
摘要交接是把上一位的结论放进下一位的提示词里,做法是把上一位回复的尾部带过去。下一位因此不用再翻一遍工具重新挖同一件事。它只是提示词里的一段文本,不额外起模型回合、不额外调工具、不写记忆。
这两个设置是面板专属的:我在群设置里填,MCP 的 update_group 里没有这两个参数,模型即使硬塞也不生效。理由是上限属于成本与安全的设定,不该由正在接力的那一方自己决定要不要继续接。相应地,模型能看到的工具目录与 list_team 的返回,跟改之前逐字节相同。
为什么做这个:官方 README 自己写着 There is no fixed reply cap。我在 mcode 里对官方版跑了一套 8 步对照,第 4 步只是群里 @ 了一个成员问标题怎么起,结果一轮接力跑了 4 跳(考据→执笔→考据→执笔)、313 秒、6 次工具调用,最后也没落到一个能用的标题上。
测过什么:上游 0.7.8 自己的 216 条测试,214 过。另外 2 条(头像库的并发上传、写入失败后重试)在我这台机器上单独跑通过、全量跑失败,上游原版全量跑也是同样这 2 条,所以不是这次改动带来的。我给这个功能补了 15 个测试用例:上限填 0 等于不限,写坏的值读作不限而不是把群静音,护栏关着时群里的常驻简报与官方版逐字一致(整段群提示词我也逐段比对过,同样一致),maxHops=2 时四跳链只跳两跳并收口,收口那一回合自己失败时链路照样停在两跳、通知仍在,模型改不了这两个设置。
边界:宿主 permissionMode 是 bypassPermissions,工具权限的执行门一次都不会触发,这套护栏是行为约束,不是安全边界。我只核了上游 0.7.8 的代码,其他版本未验证。默认跳数给多少、收口时要不要在群里明说,这是我仅个人判断、不是结论,需要确认——我在 issue #66 问过。实跑环境:zcode 里的 m3.1 flash 迭代代码,在 mcode 里对着官方 bot 和自己改的 bot-lab 做 8 步对照,机器是 linux-ubuntu-24.04。
Need help on this PR? Tag
@codesmith-botwith what you need.