Skip to content

feat(reminder): 支持会话 Owner 定时提醒 - #911

Open
afjun wants to merge 5 commits into
deepcoldy:masterfrom
afjun:feat/session-owner-reminders
Open

feat(reminder): 支持会话 Owner 定时提醒#911
afjun wants to merge 5 commits into
deepcoldy:masterfrom
afjun:feat/session-owner-reminders

Conversation

@afjun

@afjun afjun commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

改了什么

新增按 Bot 配置的会话 Owner 定时提醒能力。

启用后,当话题会话持续处于指定状态时,daemon 会在原飞书话题中自动 @ 会话 Owner,并按照配置的时间间隔重复提醒。

Dashboard 的 Bot 默认设置中新增提醒配置,支持:

  • 开启或关闭定时提醒
  • 设置提醒间隔,范围为 1~10080 分钟
  • 自定义提醒文本
  • 选择触发提醒的会话状态:
    • CLI 常驻但空闲
    • CLI 已释放、会话休眠
    • 等待选择仓库
    • 等待 TUI 选择
    • Agent 主动请求关注
    • 使用额度受限

提醒功能默认关闭;未配置时不会改变现有行为。

实现说明

  • 新增提醒状态投影和定时扫描控制器
  • 按 Bot 隔离提醒配置和会话计时记录
  • daemon 启动后立即扫描,随后每分钟扫描一次
  • 收到新消息或运行时状态发生变化后重新计算等待时间
  • 发送失败时保留当前提醒周期,并使用退避策略重试
  • 同一提醒周期复用稳定的消息 UUID,降低重复投递概率
  • 关闭功能或会话不再符合条件时清理对应计时记录
  • 抽取统一的 Owner 话题通知服务,并复用到 Dashboard 的“定位 Owner”功能
  • 新增 Dashboard API、配置持久化、双语文案和窄屏响应式布局

生效范围

仅对同时满足以下条件的会话生效:

  • 会话处于 active 状态
  • 属于飞书话题会话
  • 已记录 Owner Open ID
  • 当前 Bot 和会话具备飞书消息发送能力
  • 当前运行状态命中配置中选择的提醒状态

以下场景不会触发提醒:

  • 普通群会话或其他非话题会话
  • 排队中或已关闭的会话
  • 未记录 Owner 的会话
  • API-only Bot
  • HTTP 虚拟会话等没有飞书传输通道的会话

影响面评估

  • 公共层:涉及 daemon 编排、Bot 配置、Dashboard IPC/API 和公共会话状态读取
  • 跨 CLI:未修改具体 CLI 适配器,提醒逻辑基于统一的 DaemonSession 状态,不绑定特定 CLI
  • 跨后端:不依赖特定 backend API;测试用例覆盖 PTY 和 tmux 会话
  • 跨会话类型:仅话题会话生效,群会话、排队会话、关闭会话和无传输通道会话均会被过滤
  • 跨平台:使用 Node.js 文件系统、路径和加密 API,没有新增平台专属 shell、PTY 或进程逻辑
  • 跨 Bot:配置及提醒计时记录按 Bot 隔离,各 daemon 独立处理所属会话

测试覆盖

新增及扩充测试,覆盖:

  • 提醒配置规范化与非法配置拒绝
  • Owner mention 和稳定消息 UUID
  • 六种提醒状态的运行时投影
  • 首次等待、重复提醒及新活动重置计时
  • 发送失败后的退避和重试
  • PTY、tmux 会话提醒流程
  • 非话题、排队、无 Owner、关闭及无传输通道会话过滤
  • 提醒记录持久化及损坏文件降级
  • Bot 配置持久化和注册表热更新
  • Dashboard payload、布局和中英文文案

实际验证

  • pnpm build:通过
  • pnpm switch:here && pnpm daemon:restart:通过
  • daemon 重启后两个 Bot 进程及 Dashboard 进程均为 online

@afjun
afjun requested a review from deepcoldy as a code owner August 18, 2026 07:46
@deepcoldy

Copy link
Copy Markdown
Owner

感谢贡献!我先做了一轮初步评审,把功能逻辑和几个建议整理如下(这是自动评审流程的初步意见,最终以维护者审阅为准)。

功能读下来很清晰

按 Bot 可选开启:其名下话题会话长时间卡在选定的 actionable 状态(idle / dormant / pending_repo / tui_prompt / agent_attention / limited)无人处理时,daemon 每隔 N 分钟在原话题 @ 会话 Owner。默认关闭、不配不改变现有行为。状态投影、扫描控制器、按 Bot 落盘计时、失败退避、稳定 UUID 去重、状态迁移重置计时,拆分都很干净;把「定位 Owner」的发送逻辑抽成公共封装复用也很合理。本地跑 pnpm build、新增的 session-owner-reminder.test.ts(8/8)及相关测试均通过。

两点建议,方便的话先处理下再合入

1. 分支需要 rebase(当前对 master 有冲突)

这个 fork 是从较早的 master 切出来的,5 个 commit 里有 4 个(connector 模板、字段提取器等)其实已经在 master 上了,真正的新代码是最上面那个 reminder commit。当前对 master 有 3 处冲突(src/bot-registry.tssrc/dashboard.tstest/dashboard-bot-defaults-layout.test.ts),都是 #902(dsh 单轮超时)在相同位置新增字段/路由造成的纯相邻冲突,rebase 后 keep-both 即可,没有语义冲突。rebase 到最新 master 能让 diff 只剩真正的新增,也方便 review。

2. PR 描述里补一下夹带的邮箱解析改动

分支里还包含一段 src/im/lark/identity-cache.ts 的改动(给身份缓存增加 email 字段、contact:user.email:readonly 邮箱解析和负缓存)。这段在当前 master 上还不存在、会随本 PR 一起被引入,但 PR 说明里没有提到。功能本身小、向后兼容、也不危险,主要是希望描述能覆盖到,或者考虑拆成独立 PR,方便追溯。

reminder 功能本身这轮没有发现阻断性问题。上面两点更多是可维护性 / 透明度层面的建议 🙏

@deepcoldy

Copy link
Copy Markdown
Owner

补充一条评审意见(承接上一条,仅追加新增项,不重复 rebase / email 建议)。依旧是自动评审的初步意见,最终以维护者审阅为准。

建议再修一处时序缺口(P2):同类信号「换代」不重置计时

src/core/session-owner-reminder.ts 中,重置沉默计时的判据是:

stateFingerprint = projectedStates.join(',')   // 只含 6 个状态「名字」
record 重置条件 = fingerprint 变化 或 lastMessageAt 变新

stateFingerprint 只捕获状态标签名,不含 agentAttention.at / tuiPromptCardId 这类实例标识。而运行时这两个字段会被原地替换为新实例(daemon.ts 每次 attention 写新的 {kind, reason, at}worker-pool.ts clear 旧 tuiPromptCardId 再设新值)。

于是:旧的 attention/TUI 信号处理完、紧接着来了个全新同类信号,但投影标签名没变(还是 agent_attention / tui_prompt),扫描会继续沿用旧信号的计时,可能在新信号刚出现没多久就 @ Owner——与"给 N 分钟处理这件事再提醒"的承诺相悖。

本地复现(间隔 30min):t0 建 agent_attention 记录;t+29min 换成全新 attention 实例(新 .at、新 reason);t+30min 扫描仍会发送,尽管信号此刻只出现 1 分钟。

修改建议 + 验收口径(写得很短):

  1. 新的 agentAttention.at 或新的 tuiPromptCardId 出现后,必须重新等待完整配置间隔
  2. 注意别破坏现有去重stateFingerprint 同时喂给 sessionOwnerReminderDeliveryUuid,同一提醒周期内发送失败后的重试要复用原 UUID——引入"实例指纹"时不能让周期内的失败重试重算出不同指纹,否则会破坏现有的稳定去重语义;
  3. 回归测试同时覆盖 attention 换代与 TUI prompt 换代两种情形。

定级 P2(非数据/安全问题,是"提前打扰"体验缺陷),非硬阻断,但建议一并处理。

另外两个小项

  • PR 描述缺 UI 截图:改动含 Dashboard 配置区(开关/间隔/文本/状态勾选 + 窄屏响应式),建议附截图。
  • 验证清单补 pnpm test:描述列了 pnpm build 与 daemon 重启,但没列测试结果;本地跑下来提醒相关测试全绿,建议在 PR 中体现。

感谢!🙏

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.

2 participants