[Slice 2/4] arise 反应式核:自撤/改口 + 已发日志(Self-message Control) #3

Closed
opened 2026-07-07 02:50:44 +00:00 by KumaAgent · 0 comments
KumaAgent commented 2026-07-07 02:50:44 +00:00 (Migrated from codeberg.org)

Parent

拆自 #1(arise 反应式核 / Reactive Core PRD,Phase 1)。本片是该 PRD 的第 2/4 片,建立在 #2(Slice 1: Walking Skeleton)之上。

What to build

让机器人对自己发出的消息有控制力——撤回(self_recall)/改口(edit),端到端验证:模型调工具 → core 按句柄状态路由 → 平台侧产生正确的撤回/编辑(或降级)动作。

具体包含:

  • 能力值 edit:本片先以静态配置常量表达(不建完整能力探测 port,那是后续多模态切片的范围);OneBot v11 测试适配器场景下 edit=false(OneBot v11 只有 delete_msg、无原生 edit_msg)。
  • self_recall(handle) / edit(handle, new_content) 两个 core 工具,按句柄的 send-state 路由:
    • 句柄仍在 Outbox(未发)→ 直接丢弃/改写,零平台调用;
    • 句柄已发(有回填的平台 message_id)→ edit=true 走原生编辑;edit=false 降级为"撤回旧 + 重发新"(重发走一次新的 send_message,句柄重新回填)。
  • 已发日志(Sent Log):存储 port 新切片,记录 句柄 ↔ 平台 message_id / content / chat / time / send-state,是 send-state 路由判断的依据。本片先满足 self_recall/edit 寻址需要即可,不强求持久化到 Postgres(持久化 + 崩溃恢复的事务边界是 Slice 3 的范围)。
  • 结构性硬约束(必须满足,不接情感态/速率预算账本——那是运营治理层,本片不做):
    • 只能操作 bot 自己、当前会话内的消息;
    • 句柄无法解析时,工具调用直接失败、不产生任何平台调用(fail-closed:误撤比不撤更糟);
    • 每条消息 self_recall 至多一次、edit 至多 N 次(N 为静态配置,防止 edit↔recall↔resend 死循环)。

Acceptance criteria

  • 模型对一条已发出的消息调用 edit,在 edit=false(OneBot v11 测试适配器)场景下,断言产生 delete_msg + 新的 send_msg(而不是报错或静默失败),新消息句柄正确回填。
  • 模型对一条仍在 Outbox 未发的待发内容调用 self_recall/edit,断言零平台调用(纯 core 内部丢弃/改写)。
  • 模型对一个不存在/无法解析的句柄调用 self_recall,断言不产生任何平台调用(fail-closed)。
  • 同一条消息重复调用 self_recall 第二次 / edit 超过 N 次,断言被硬约束拒绝,不产生额外平台调用。
  • Sent Log 中能查到"句柄 ↔ 平台 message_id ↔ send-state"的对应记录,且在 self_recall/edit 后 send-state 正确更新。
  • 测试同样走 NoneBug + 假 provider 路线(延续 Slice 1 的测试基础设施),不需要新的测试脚手架。

Blocked by

  • #2(Slice 1: 需要 send_message 返回的句柄机制已经存在)
## Parent 拆自 [#1](https://codeberg.org/ProjectKuma/nonebot-plugin-arise/issues/1)(arise 反应式核 / Reactive Core PRD,Phase 1)。本片是该 PRD 的第 2/4 片,建立在 [#2](https://codeberg.org/ProjectKuma/nonebot-plugin-arise/issues/2)(Slice 1: Walking Skeleton)之上。 ## What to build 让机器人对**自己发出的消息**有控制力——撤回(`self_recall`)/改口(`edit`),端到端验证:模型调工具 → core 按句柄状态路由 → 平台侧产生正确的撤回/编辑(或降级)动作。 具体包含: - 能力值 `edit`:本片先以**静态配置常量**表达(不建完整能力探测 port,那是后续多模态切片的范围);OneBot v11 测试适配器场景下 `edit=false`(OneBot v11 只有 `delete_msg`、无原生 `edit_msg`)。 - `self_recall(handle)` / `edit(handle, new_content)` 两个 core 工具,按句柄的 **send-state** 路由: - 句柄仍在 Outbox(未发)→ 直接丢弃/改写,零平台调用; - 句柄已发(有回填的平台 `message_id`)→ `edit=true` 走原生编辑;`edit=false` 降级为"撤回旧 + 重发新"(重发走一次新的 `send_message`,句柄重新回填)。 - **已发日志(Sent Log)**:存储 port 新切片,记录 `句柄 ↔ 平台 message_id / content / chat / time / send-state`,是 send-state 路由判断的依据。本片先满足 self_recall/edit 寻址需要即可,不强求持久化到 Postgres(持久化 + 崩溃恢复的事务边界是 Slice 3 的范围)。 - 结构性硬约束(必须满足,不接情感态/速率预算账本——那是运营治理层,本片不做): - 只能操作 bot 自己、当前会话内的消息; - 句柄无法解析时,工具调用直接失败、不产生任何平台调用(**fail-closed**:误撤比不撤更糟); - 每条消息 `self_recall` 至多一次、`edit` 至多 N 次(N 为静态配置,防止 edit↔recall↔resend 死循环)。 ## Acceptance criteria - [ ] 模型对一条**已发出**的消息调用 `edit`,在 `edit=false`(OneBot v11 测试适配器)场景下,断言产生 `delete_msg` + 新的 `send_msg`(而不是报错或静默失败),新消息句柄正确回填。 - [ ] 模型对一条**仍在 Outbox 未发**的待发内容调用 `self_recall`/`edit`,断言零平台调用(纯 core 内部丢弃/改写)。 - [ ] 模型对一个**不存在/无法解析**的句柄调用 `self_recall`,断言不产生任何平台调用(fail-closed)。 - [ ] 同一条消息重复调用 `self_recall` 第二次 / `edit` 超过 N 次,断言被硬约束拒绝,不产生额外平台调用。 - [ ] Sent Log 中能查到"句柄 ↔ 平台 message_id ↔ send-state"的对应记录,且在 self_recall/edit 后 send-state 正确更新。 - [ ] 测试同样走 NoneBug + 假 provider 路线(延续 Slice 1 的测试基础设施),不需要新的测试脚手架。 ## Blocked by - [#2](https://codeberg.org/ProjectKuma/nonebot-plugin-arise/issues/2)(Slice 1: 需要 `send_message` 返回的句柄机制已经存在)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ProjectKuma/arise#3
No description provided.