频道生命周期状态适配器
日期:2026-07-01
目标
通过前四个频道适配器暴露任务生命周期状态:
- Telegram
- Weixin
- DingTalk
- Feishu
这是对频道身份和生命周期元数据工作的 P1.1 后续跟进。 目标是让每个受支持的频道显示可用的最佳原生状态展示面,而无需再次更改共享频道契约。
非目标
- 不实现 Slack 行为。
- 不实现 QQ Bot 行为。
- 不更新 mock/plugin 示例。
- 不为 DingTalk 添加终止状态 emoji。
- 不为一轮特定于适配器的映射引入共享的状态渲染抽象。
参考与对齐
设计首先遵循当前 Qwen 频道适配器的能力。 生命周期语义与本仓库中已使用的现有任务/会话状态模型保持一致:任务可以启动、运行、完成、被取消或失败。 在此范围内不引入额外的外部状态模型,因为每个频道对这些状态都已有清晰的原生状态展示面。
当前状态
| 频道 | 现有状态展示面 | 当前行为 |
|---|---|---|
| Telegram | 输入中指示器 | 在 prompt 开始时开始输入,在 prompt 结束时停止输入。 |
| Weixin | 输入中指示器 | 在 prompt 开始时开始输入,在 prompt 结束时停止输入。 |
| DingTalk | 消息表情回应 | 在 prompt 开始时添加“眼睛”表情回应,在 prompt 结束时撤回。 |
| Feishu | 流式卡片 | 显示并更新流式卡片,包含完成和错误处理路径。 |
提议的设计
保持实现局限于适配器内部。每个适配器消费生命周期事件钩子,并将事件映射到平台现有的原生状态展示面。
| 生命周期事件 | Telegram | Weixin | DingTalk | Feishu |
|---|---|---|---|---|
started | 开始输入。 | 开始输入。 | 添加“眼睛”表情回应。 | 显示/更新卡片为运行中。 |
text_chunk | 忽略。 | 忽略。 | 忽略。 | 在生命周期钩子中忽略。内容流式传输保持在现有的响应/卡片流路径上。 |
tool_call | 忽略。 | 忽略。 | 忽略。 | 在 UI 中忽略。 |
completed | 停止输入。 | 停止输入。 | 撤回“眼睛”表情回应。 | 标记卡片为已完成。 |
cancelled | 停止输入。 | 停止输入。 | 撤回“眼睛”表情回应。 | 标记卡片为已取消。 |
failed | 停止输入。 | 停止输入。 | 撤回“眼睛”表情回应。 | 标记卡片为已失败。 |
Telegram
Telegram 保留现有的输入实现。生命周期钩子应将 started 映射到现有的输入开始路径,并将所有终止事件映射到现有的输入停止路径。
text_chunk 和 tool_call 不需要更改 Telegram UI。
Weixin
Weixin 遵循与 Telegram 相同的模式。生命周期钩子应将 started 映射为 setTyping(true),并将终止事件映射为 setTyping(false)。
不发送额外的消息。
DingTalk
DingTalk 保留现有的“眼睛”表情回应行为:
started:附加现有的“眼睛”表情回应。completed、cancelled、failed:撤回现有的“眼睛”表情回应。
此范围内不包含终止状态 emoji。失败和取消的任务不应发送额外的状态消息,除非现有的错误路径已经这样做了。
Feishu
Feishu 保留流式卡片作为状态展示面,并在卡片内容中明确显示终止状态:
| 状态 | 卡片标签 |
|---|---|
| 运行中 | 运行中... |
| 已完成 | 已完成 |
| 已取消 | 已取消 |
| 已失败 | 已失败,请重试 |
卡片仍然像今天一样通过现有的响应/卡片流钩子流式传输回答内容。在此范围内,适配器不直接消费生命周期 text_chunk,这取代了早期使用生命周期 chunk 追加卡片内容的适配器局部想法。在此范围内,tool_call 仍然对卡片 UI 隐藏。
如果需要,markdown/卡片辅助函数可以接受一个极简的状态标签选项,但不应发展成一个通用的渲染框架。
数据流
- 频道执行从基础频道层发出生命周期事件。
- 选定的适配器通过其生命周期钩子接收事件。
- 适配器将事件映射到平台状态展示面。
- 平台状态更新尽最大努力执行(best-effort),且不影响任务执行。
生命周期事件有效载荷应提供足够的现有上下文以识别频道消息/会话。如果缺少特定于平台的标识符,适配器将跳过状态更新。
错误处理
平台状态更新是非关键性的。失败的输入、表情回应或卡片状态更新应根据适配器现有的风格进行记录或静默处理,且绝不能导致任务失败。
终止事件对于消息/会话应该是幂等的。重复的终止事件不应创建重复的状态更新,也不应留下过期的运行中指示器。
Feishu 需要特别处理,因为它已经有卡片完成、错误和停止按钮流程。生命周期映射应重用现有的卡片会话状态,并避免相互竞争的更新覆盖更具体的终止状态。
测试计划
在受影响的频道包中添加针对性的单元测试覆盖:
- Telegram:生命周期
started开始输入;终止事件停止输入;不引入重复的输入间隔。 - Weixin:生命周期
started调用setTyping(true);终止事件调用setTyping(false)。 - DingTalk:生命周期
started附加“眼睛”表情回应;终止事件撤回它;不发送终止状态 emoji。 - Feishu:运行中、已完成、已取消和已失败的卡片状态渲染预期的标签;生命周期
text_chunk仍由现有的流路径拥有,而不是生命周期钩子;tool_call不添加 UI 输出。
验证应在提交 PR 之前,针对受影响的适配器运行包内的 Vitest 命令,然后进行项目构建和类型检查。
未决事项
无。当前范围有意保持狭窄,并遵循现有的适配器能力。