Skip to content

fix: align streaming terminal states and shared metadata#244

Merged
liujuanjuan1984 merged 9 commits into
mainfrom
bugfix/243-stream-completion-signal
Mar 20, 2026
Merged

fix: align streaming terminal states and shared metadata#244
liujuanjuan1984 merged 9 commits into
mainfrom
bugfix/243-stream-completion-signal

Conversation

@liujuanjuan1984
Copy link
Copy Markdown
Collaborator

@liujuanjuan1984 liujuanjuan1984 commented Mar 19, 2026

变更概览

本 PR 统一收敛 streaming 输出边界,合并处理流式完成判定、上游 in-band error 映射,以及 step/snapshot 事件的结构化下沉,修复以下四类问题:

  • message/stream 在上游真正结束前过早输出 completed
  • 上游已失败却仍被误报为成功完成
  • step-start / step-finish / snapshot 的内部快照字符串被误当成正文透传
  • shared.stream.source 曾暴露 part_text_diff 等内部归一化实现值

按模块说明

src/opencode_a2a_server/agent.py

  • 为流式执行引入显式的 terminal signal 等待逻辑,不再以 send_message() 返回作为成功完成条件。
  • 成功路径改为等待与目标 sessionID 对应的 session.idle
  • 失败路径改为等待与目标 sessionID 对应的 session.error,并将其映射为对应的 A2A 失败态。
  • 修复 session.error 之后仍继续发送 TaskState.completed 的状态覆盖问题,确保流式请求只产生一个最终终态。
  • 当 SSE 在未收到 session.idle / session.error 前提前结束时,显式按上游协议错误处理,避免静默空完成。
  • 增加最终 /session/{id}/message response.info.error 的失败映射,非流式和流式都不再把上游业务失败误报为完成态。
  • 增加对流内 message.updated -> info.error 的兜底处理,避免上游已显式报错但最终仍落成 completed
  • 收紧流式可见文本提取范围,只允许 text / reasoning part 输出到文本 artifact,不再把 step-start / step-finish / snapshot 这类内部快照直接当成正文透传。
  • step-start / step-finish / snapshot 增加结构化 metadata.shared.progress 输出,使这些事件像 usage / interrupt 一样以下游可消费的 shared metadata 形式暴露,而不是重新回退成正文。
  • 保留 metadata.shared.stream.source 兼容位,但对 artifact/update 场景仅暴露稳定公开值:文本/推理块统一为 stream,工具块为 tool_part_update,最终补发快照为 final_snapshot,不再向 shared 协议暴露 part_text_diffdelta_event 等内部实现值。
  • 对 status/update 场景继续通过 metadata.shared.stream.source 标记 status / progress / interrupt 等控制语义,保持现有 shared metadata 风格一致。
  • 进一步拆分内部 internal_source 与对外 shared_source 语义边界,避免服务端内部来源标签与下游 shared 协议字段继续共槽位混用。

src/opencode_a2a_server/text_parts.py

  • 收紧非流式文本提取逻辑,只从 text / reasoning part 汇总可见文本,不再回退到 snapshot 字段,避免 opaque snapshot/hash 在非流式场景中进入用户可见正文。

src/opencode_a2a_server/extension_contracts.py

  • 为 streaming 扩展契约新增 progress_metadata_fieldprogress_fields,公开 metadata.shared.progress 的结构化字段路径。

tests/test_streaming_output_contract.py

  • 增加回归测试,覆盖 send_message() 先返回、assistant 文本与 session.idle 后到的成功场景。
  • 增加回归测试,覆盖事件流在缺少 terminal signal 时应失败的场景。
  • 增加回归测试,覆盖 session.error 只产生单一失败终态、且不会再落成 completed 的场景。
  • 调整回归测试,验证 step-finish snapshot 不再作为可见文本 artifact 输出,但相关 usage 仍可保留。
  • 增加回归测试,覆盖 step-start / step-finish / snapshot 会以下游可消费的 shared.progress 形式输出。
  • 增加回归测试,覆盖 artifact 侧 shared source 只暴露稳定公开值,不再透出内部归一化来源。

tests/test_agent_errors.py

  • 增加回归测试,覆盖非流式 response.info.error 映射为失败态。
  • 增加回归测试,覆盖流式 response.info.error 映射为失败态并输出错误 artifact。
  • 增加回归测试,覆盖 session.error 映射为失败态。
  • 增加回归测试,覆盖流内 message.updated -> info.error 最终仍应输出失败态。

tests/test_text_parts.py

  • 调整回归测试,验证 snapshot part 不再作为正文回退来源。

tests/test_agent_card.py

  • 更新 agent card 断言,验证 streaming 扩展契约暴露 metadata.shared.progress

tests/test_metrics.py

  • 同步调整流式消费测试辅助调用,匹配新增的 terminal signal 参数,保持现有指标测试可运行。

文档

  • 本 PR 无落库文档变更;外部接口与使用方式不变,变更集中在流式终态判定、错误态映射、shared progress 元数据,以及 shared stream source 的稳定化。

提交记录

  • a6eec87 refactor: separate internal and shared stream sources #246
  • 8cd6734 fix: normalize shared stream source values #246
  • f18da97 feat: surface step events as shared progress metadata #246
  • 4e22c86 fix: suppress snapshot parts from visible text output
  • 5178f80 fix: map upstream in-band errors to failed task state #242
  • 50dd7d2 fix: preserve failed terminal state after session.error #243
  • 9372a84 fix: wait for session terminal signals before completing stream #243

最终决策

  • 可见正文只接受 text / reasoning
  • step-start / step-finish / snapshot 不再进入正文 artifact。
  • step-start / step-finish / snapshot 改为通过 metadata.shared.progress 暴露结构化阶段信息。
  • step-finish 仍保留 usage 提取职责,不与正文职责混用。
  • metadata.shared.stream.source 为兼容下游消费继续保留。
  • artifact/update 场景下,metadata.shared.stream.source 只承诺稳定公开值:streamfinal_snapshottool_part_update
  • status/update 场景下,metadata.shared.stream.source 继续用于控制语义标记,例如 statusprogressinterrupt
  • 服务端内部继续保留更细粒度的来源标签,但它们与 shared 协议字段已经解耦,不再通过二次映射共享同一个中间字段。

验证

  • uv run pre-commit run --all-files
  • uv run pytest

关联 Issue

Closes #242
Closes #243
Closes #246

@liujuanjuan1984 liujuanjuan1984 changed the title fix: honor stream terminal signals before completing tasks fix: wait for session terminal signals before completing stream Mar 19, 2026
@liujuanjuan1984 liujuanjuan1984 changed the title fix: wait for session terminal signals before completing stream fix: align stream completion with upstream terminal and in-band errors Mar 19, 2026
@liujuanjuan1984 liujuanjuan1984 changed the title fix: align stream completion with upstream terminal and in-band errors fix: normalize stream completion, errors, and progress metadata Mar 20, 2026
@liujuanjuan1984 liujuanjuan1984 changed the title fix: normalize stream completion, errors, and progress metadata fix: align streaming terminal states and shared metadata Mar 20, 2026
@liujuanjuan1984 liujuanjuan1984 marked this pull request as ready for review March 20, 2026 04:20
@liujuanjuan1984 liujuanjuan1984 merged commit 09ebbb7 into main Mar 20, 2026
3 checks passed
@liujuanjuan1984 liujuanjuan1984 deleted the bugfix/243-stream-completion-signal branch March 20, 2026 04:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant