Skip to content

feat(lark): 增强替身直通与干预模式#428

Open
mahongchaodev wants to merge 1 commit into
deepcoldy:masterfrom
mahongchaodev:feat/substitute-direct-proxy-squashed
Open

feat(lark): 增强替身直通与干预模式#428
mahongchaodev wants to merge 1 commit into
deepcoldy:masterfrom
mahongchaodev:feat/substitute-direct-proxy-squashed

Conversation

@mahongchaodev

@mahongchaodev mahongchaodev commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

变更概述

本 PR 在现有替身模式基础上增加直通模式和干预模式,并提供单聊中的群聊管理卡片。
替身模式默认行为保持不变:群里 @ 配置的替身对象时,bot 仍会自动代答。只有在单聊中对某个群开启直通或干预后,才改变该群的行为。

核心能力
单聊管理替身群聊
在单聊中发送 /substitute list,会返回一张群聊管理卡片,列出当前 bot 所在普通群。

每个群提供 4 个动态按钮:

替身开关:开启时显示“关闭替身”,关闭时显示“开启替身”。
直通:未开启时显示“进入直通”,已开启时显示“退出直通”。
干预:未开启时显示“进入干预”,已开启时显示“退出干预”。
退出群聊:让 bot 直接退出该群,退出后该群不再出现在列表中。

直通模式
对某个群开启直通后:

群里 @替身 的消息不再触发模型自动代答。
bot 会把该群消息转发到单聊。
单聊中发送的普通消息会直接转发回该群。
单聊 slash command 不会被转发,仍按命令处理。
回群消息使用与自动回复一致的飞书卡片样式。
回群文案使用单聊发送者的名字,格式为:我先代 {单聊发送者名字} 回复: ...

直通引用处理:

群消息转发到单聊时,会在转发消息中记录原群消息 message_id。
单聊中引用这条转发消息回复时,回群消息会引用原群消息。
如果原群消息已撤回,则 fallback 为普通群消息发送。

干预模式
对某个群开启干预后:

群里 @替身 仍保持自动代答。
单聊中发送的普通消息不会转发到群。
单聊消息会保存为干预上下文。
下一次该群 @替身 自动代答时,干预内容会注入模型上下文。
注入后会清空,避免重复使用。

干预内容会注入到 substitute_trigger 的 intervention_notes 中,供模型在本次替身代答时参考。

状态与权限
状态存储
新增直通/干预状态存储文件:substitute-direct-bindings.json。

状态模型:

以单聊操作者 openId 作为 binding key。
binding 中记录实际替身 target 身份,包括 targetOpenId、substituteUserId、substituteUnionId、targetName。
同一个单聊操作者同时只能有一个群处于直通或干预状态。
开启新的群直通/干预时,会自动替换旧状态。
权限规则
单聊控制入口仅允许 bot owner、allowedUsers 或当前配置的替身对象使用。

历史 binding 不再单独授予权限。

直通/干预生效前会重新检查 substituteMode.enabled、当前 target 配置、群维度替身开关和 canTalk 触发权限。
匹配规则
群里 @替身 时支持 openId、userId、unionId 和名称 fallback。

同时兼容旧 binding:如果旧 binding 缺少 targetOpenId,会 fallback 使用 substituteOpenId 作为 target openId。

Dashboard 与 Help

Dashboard 不新增替身处理方式配置项,仍只配置替身对象和披露方式。

Dashboard 文案补充说明:替身模式默认自动代答,直通/干预从单聊 /substitute list 进入。

/help 增加替身模式相关说明,包括群内 /substitute status|on|off,单聊 /substitute list,单聊进入直通、进入干预、退出,以及让 bot 退出群聊。

影响范围

主要涉及文件:

src/im/lark/substitute-command.ts
src/im/lark/substitute-direct.ts
src/services/substitute-direct-store.ts
src/im/lark/event-dispatcher.ts
src/im/lark/card-handler.ts
src/core/session-manager.ts
src/core/command-handler.ts
src/types.ts
src/i18n/zh.ts
src/i18n/en.ts
src/dashboard/web/i18n.ts

测试文件:

test/substitute-command.test.ts
test/event-dispatcher.test.ts
test/command-handler.test.ts

对其他模式的影响评估

不影响默认替身自动代答。未进入直通或干预的群仍自动代答。

不影响普通会话模式,包括普通群会话、话题群会话、单聊普通会话、reply-mode、oncall、grant。

新增逻辑只在 /substitute 命令、substitute_direct_* 卡片 action、群消息命中替身 target、单聊存在 active direct/intervene binding 时介入。

测试验证

聚焦测试命令:

./node_modules/.bin/vitest run --project unit test/event-dispatcher.test.ts test/substitute-command.test.ts test/command-handler.test.ts --testNamePattern "substitute|Substitute|/help|DAEMON_COMMANDS"

测试结果:

Test Files 3 passed (3)
Tests 52 passed | 328 skipped (380)

类型检查命令:

./node_modules/.bin/tsc --noEmit

结果:通过。

构建命令:

./node_modules/.bin/tsc
cp src/setup/lark-scopes.json dist/setup/
node scripts/build-dashboard.mjs
chmod +x dist/cli.js

结果:通过。

部署验证

已部署到 服务器。

远程进程状态:botmux-0 online,botmux-dashboard online。

远程 dist 已确认包含直通/干预状态存储、单聊管理卡片、群聊 @替身 到单聊转发、单聊到群聊卡片转发、单聊引用转发消息到群聊引用原消息、干预上下文注入、旧 binding 兼容、多身份匹配与名称 fallback。

分支与提交

分支:feat/substitute-direct-proxy-squashed

提交:edba1bf7 feat(lark): 增强替身直通与干预模式

@mahongchaodev mahongchaodev requested a review from deepcoldy as a code owner July 10, 2026 08:05
@mahongchaodev mahongchaodev force-pushed the feat/substitute-direct-proxy-squashed branch from edba1bf to f00576b Compare July 10, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant