github baileyh8/hermes-feishu-streaming-card v5.0.23

38 minutes ago

v5.0.23:完成通知门槛、身份路由与有界分段

变更范围

  • #502 通知最短时长:新增 completion_notify.min_duration_seconds。该门槛只作用于单独 message 完成通知,且前提是 completion_notify.enabled 已显式设为 true(默认关闭);placement: card 的卡内完成呈现不经过这道门槛。低于阈值的轮次不发通知,重放的 message.completed 也不会补发。时长优先取 Hermes 上报的本轮耗时,缺失时回退会话记录的实际存活时间。min_duration_seconds: 0(默认)表示不按时长过滤。
  • #508 sender 身份路由:较新网关事件的 message.completed 只带租户 user_id。mention 开启时通过 contact API 按需解析 open_id 并缓存成功结果,失败不缓存、通知仍以无 @ 形式发出。合成回合(后台进程/队列完成)不发通知;事件声称非法 sender id 视为伪造信号,整条不发。话题投递保持严格 guard:缺 reply anchor 时不做 top-level 兜底发送。
  • #513 有界分段:新增 card.over_limit: segmented(默认 native)。终态答案在所有卡内降级后仍超预算时,投递一张主卡(开头正文+统计+可折叠过程面板)加编号续卡;总卡数不超过 5(含主卡),续卡按整节边界切分、逐卡过预算校验。任一续卡不可行或投递失败时回退既有 native 全文 handoff,已发出的续卡允许与全文回退并存。delivery_key 保证同一终态事件重投不重复发卡;这不构成永久 exactly-once。流式期间仍是单张实时卡。

验收与限制

完整 CI、发行资产和公开安装的最终结果见下方“本版实际验收记录”。真实飞书 API 已验证合成上报 12 秒轮次静默、61 秒轮次通知、合法 open_id 的 @ 呈现、解析失败时无 @ 发送、同话题投递和四卡有界分段。解析失败分支由本地注入,通知本身经真实 API 发送;这部分由合成 Hermes 事件驱动,不等于实际 Gateway/model 回合。用户提供的桌面截图确认话题内完成卡片和 @ 通知显示正常。

按维护者明确限定的本轮范围,以下仍为未验证:长答续卡的客户端视觉、@ 实际点击、Android/iOS、实际 Hermes Gateway/model 回合,以及租户 user_id 到 open_id 转换的真实现场(当前测试机器人缺相应权限)。未知 upstream main 构建不在本版兼容承诺内。

配置示例见 README 配置段与 user-guide;enabled 默认 false,启用后单独通知按上文 #502/#508 规则发送。安装包契约与目录布局不变。

贡献记录

感谢 tidytorch 在 #513 提交有界分段投递(4 个原始提交保留),Cassius0924 在 #508 提交 mention fallback 身份路由(4 个原始提交保留),jackwude 在 #502 提交通知最短时长门槛。代码署名以 Git 原始提交为准;历史贡献记录保留。


v5.0.23: notification threshold, identity routing and bounded segmentation

Changes

  • #502 notification minimum duration: add completion_notify.min_duration_seconds. The threshold applies only to the standalone message completion notification and only when completion_notify.enabled is explicitly true (default false); the in-card completion presentation with placement: card does not pass through this gate. Turns shorter than the threshold stay quiet, and a replayed message.completed cannot re-notify later. The turn duration prefers the value Hermes reports and falls back to the session record's actual age when the report is missing. min_duration_seconds: 0 (default) means no duration filtering.
  • #508 sender identity routing: newer gateway message.completed events carry only the tenant user_id. With mention enabled, the mention target's open_id is resolved on demand through the contact API and successful lookups are cached; a failed lookup is not cached and the notice still sends unmentioned. Synthetic turns (background-process and queue completions) never notify, and a claimed-but-invalid sender id is treated as a spoof signal that sends nothing. Topic placement keeps the strict guard: no top-level fallback send when the reply anchor is missing.
  • #513 bounded segmentation: add opt-in card.over_limit: segmented (default native). When a terminal answer still exceeds the safe card budget after every in-card degradation, deliver one main card (bounded lead, statistics, collapsible process panel) plus numbered continuation cards with a hard cap of five cards in total (main card included). Segments break at section boundaries and each segment is verified against the card budget. Any infeasible or failed segment falls back to the existing native full-text handoff; already-sent continuation cards may coexist with that fallback. Delivery keys prevent duplicate cards when the same terminal event is redelivered; this is not a permanent exactly-once guarantee. Streaming still updates a single live card.

Acceptance and limits

The final CI, release-asset and public-install results appear in the verified release evidence below. Real Feishu API checks passed for quiet turns reporting 12 seconds, notices for turns reporting 61 seconds, direct open_id mentions, unmentioned notices after resolution failure, same-topic delivery and bounded four-card segmentation. Resolution failure was injected locally and the resulting notice used the real API. These checks use synthetic Hermes events, not actual Gateway/model turns. A user-supplied desktop screenshot confirms the topic completion card and mention notice render normally.

Under the maintainer's explicitly narrowed scope, the following remain unverified this round: continuation-card client visuals, actual mention clicks, Android/iOS, actual Hermes Gateway/model turns, and a real tenant user_id-to-open_id conversion (the test bot lacks the required permission). Unknown upstream main builds remain outside this release's compatibility claims.

Configuration examples live in the README configuration section and the user guide; enabled defaults to false, and the standalone notification follows the #502/#508 rules above once enabled. Archive contracts and directory layout are unchanged.

Credits

Thanks to tidytorch for bounded segmented delivery in #513 (4 original commits preserved), Cassius0924 for the mention-fallback identity routing in #508 (4 original commits preserved), and jackwude for the notification minimum-duration gate in #502. Code authorship follows the original Git commits; historical credits are retained.

本版实际验收记录 / Verified release evidence

  • Commit: 3c0acebd66c1d77a8ebf16fa85936460b3704f36; annotated tag v5.0.23 (object 21542751c3d0837eb3dbe0a1245028fbece0965b).
  • PR complete CI, exact-main complete CI, exact-main CodeQL, immutable-tag release gate: passed. Main 61/61, tag 63/63; all supported Python 3.9–3.14, macOS/Windows, SDK, Docker, PowerShell and pinned-upstream coverage is retained.
  • Public Git-tag non-editable installation passed in an isolated environment and real child process. VCS commit matches the tested merge; all 164 package resources match Git. No checkout import, editable package or test injection was used. Installation/restore contracts are covered by the linked full matrix; production was not upgraded.
  • Real Feishu API checks passed for notification thresholds, direct mentions and resolution-failure fallback, same-topic card/notice routing and four-card segmented delivery. One confirmed payload/UUID replay returned the same message id; this is a bounded check, not a permanent exactly-once claim. The resolution-failure branch was induced locally; its notice used the real API. These checks use synthetic Hermes events, not actual Gateway/model turns.
  • All four draft assets passed checksums and full manifests. Archives have one version/platform top-level directory, normalized ownership/modes, and no links or path escapes. Actual macOS BSD tar extraction into private 0700/1777 destinations preserved the parent inode/owner/mode and sentinel, with exact file bytes/modes. Linux GNU tar root/non-root checks passed in the linked release gate.
  • 桌面话题截图确认完成卡片和 @ 通知可读;长答续卡视觉、@ 实际点击、Android/iOS、实际 Gateway/model 和租户 ID 转换现场仍为未验证,按维护者明确限定的范围发布。 / The user-supplied desktop topic screenshot confirms readable cards and mention notices. Continuation-card visuals, actual mention clicks, Android/iOS, actual Gateway/model turns and real tenant-ID conversion remain unverified under the explicitly narrowed release scope.
  • 17 条本轮测试消息已核对归属并撤回、确认 deleted;正式配置保持不变。 / All 17 test messages were owner-checked, recalled and confirmed deleted; the formal configuration is unchanged.
  • 公开后匿名下载的四资产与已验收 draft、GitHub SHA-256 digest 完全一致;再次实际解压通过,annotated tag 绑定未变。 / All four anonymous public downloads match the audited draft and GitHub SHA-256 digests; actual extraction passed again and the annotated-tag binding is unchanged.

Don't miss a new hermes-feishu-streaming-card release

NewReleases is sending notifications on new releases.