Skip to content

[feat] 对接 opencode-a2a-serve 流式新契约(channel 分流与去重) #94

@liujuanjuan1984

Description

@liujuanjuan1984

背景

opencode-a2a-serve 已对 message:stream 的流式输出契约做了升级(见上游 issue/PR):

本仓库(a2a-client-hub)需要完成消费端适配。

本需求明确:不考虑旧数据兼容。按新契约实施即可。

目标

将当前“把所有文本当单一流拼接”的消费方式,迁移为“按 channel 分流 + 正确处理 append + final snapshot 语义”的新实现,避免:

  1. 用户回显误展示
  2. reasoning / tool_call / final_answer 混杂
  3. 最终答复重复展示

上游新契约(消费端必须遵守)

1) 流事件通道化

TaskArtifactUpdateEvent.artifact.metadata.opencode.channel 取值:

  • reasoning
  • tool_call
  • final_answer

2) 多 artifact_id 并行

同一轮任务会出现多个 artifact:

  • final_answer{task_id}:stream
  • reasoning{task_id}:stream:reasoning
  • tool_call{task_id}:stream:tool_call

3) append 语义必须按“每个 artifact/channel”独立处理

  • append=true:追加到该 artifact 当前缓冲
  • append=false:重置该 artifact 当前缓冲为本次文本

禁止跨 channel/跨 artifact 拼接。

4) final snapshot 语义

source=final_snapshot(位于 artifact.metadata.opencode.source)表示收尾补发快照:

  • 仅在流内未形成等价 final answer 时才会出现
  • 可能与 append=falselast_chunk=true 同时出现

消费端应将其视为 final_answer 通道的一次“覆盖更新”,而不是新建一条独立回答。

5) message_id 关联前提

上游已开始丢弃缺失 message_id 的流事件,消费端可按新契约实现,不再为“缺失 message_id 的 chunk”保留兼容逻辑。

实施要求(建议拆任务)

  1. 流事件解析层重构
  • 统一提取:channel/source/event_type/message_id/role
  • 建立类型化内部模型(不要在 UI 层直接读原始 JSON)
  1. 渲染状态机重构
  • (task_id, artifact_id) 维护独立缓冲
  • final_answerreasoningtool_call 分通道渲染
  • final_snapshot 应覆盖 final_answer 当前视图,不重复追加
  1. 展示策略
  • final_answer:主展示区
  • reasoning:可折叠/次级展示
  • tool_call:结构化展示(至少与 final answer 分离)
  1. 删除旧路径
  • 移除“单一文本流拼接”逻辑
  • 移除对旧无 channel 数据的回退处理(本需求不做兼容)

验收标准

  • 单轮流式中,final_answer 不重复展示。
  • reasoningtool_callfinal_answer 可独立渲染,不互相污染。
  • append=false 被正确处理为覆盖,而非追加。
  • 遇到 source=final_snapshot 时,不会额外产生重复答案卡片/消息气泡。
  • 相关自动化测试覆盖并通过。

建议测试用例

  1. reasoning -> tool_call -> final_answer 顺序流,验证三通道独立。
  2. final_answer 增量后收到 final_snapshot,验证无重复。
  3. 同一任务多个 artifact 交错到达,验证状态机稳定。
  4. append=false 后再 append=true,验证覆盖后续拼接正确。

备注

若上游 PR #73 在联调窗口内尚未合并,请先以 feature flag 或 mock stream fixture 落地,待上游合并后切实流验证。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions