Skip to content

bug(web): Provider 运行失败后错误消失,界面没有失败提示 #469

Description

@tt-a1i

解决什么问题

Web 中,模型运行期间通过 Pi assistant message 返回的失败会丢失错误原因。重试耗尽或 Provider 返回错误后,界面从“运行中”恢复为普通输入状态,可能只剩用户消息,用户无法判断任务为何停止、是否需要重试或调整配置。

这与缺少模型、凭据等启动前检查错误不同:后者可以走 prompt_failed;这里的问题是 Pi 已启动模型调用,并将错误记录为 stopReason: "error" 的正常消息结果。

价值是什么

让外部用户能区分成功完成、模型失败、取消和结果不确定。限流、Provider 服务异常等失败必须留下可回看的原因,已有部分回答也不能被默认为完整结果。

已验证的复现

验证日期:2026-09-08。源码固定为 ed9dbc1018f890fd54375f5371990ddfee8af5df。使用干净的相同源码 checkout、独立临时 Pi agent 目录,pi list 中唯一 OpenPI 来源指向该 checkout。

  1. 启动真实 Pi 和 Web Host,将一个合成测试模型连接到本机 HTTP Provider fixture;不使用真实 Provider 凭据或付费模型。
  2. 在真实浏览器输入合成消息 AUDIT_ERROR。
  3. 本地 fixture 返回 HTTP 400,错误标记为 AUDIT_PROVIDER_ERROR。
  4. 等待本轮结束,检查 Pi Session JSONL、Web snapshot 和浏览器。

观察到:

  • Pi JSONL 保存了 assistant 消息及其 stopReason: "error"、errorMessage。
  • Web snapshot 中相应 assistant 的 content 为空,错误原因未投影,runtime 已回到 idle。
  • 真实浏览器最终只显示用户的 AUDIT_ERROR 和普通空输入框,没有错误、失败提示或原因。

另有直接导入当前源码的最小事件探针:输入 { role: "assistant", content: [], stopReason: "error", errorMessage: "synthetic provider error" },最终 Store 为 notice: null、livePhase: "idle"、turnTerminalStatus: "failed";真实 React 组件渲染普通发送提示。

这证明了真实 Pi → Web 协议 → 浏览器的错误呈现缺陷;本地 Provider 是协议 fixture,不代表任何线上 Provider 的可用性测试。全部输入和错误均为合成内容,没有公开凭据或私人 Session。

方法与根因

建议保留有界、可安全显示的规范错误信息及停止原因,由同一事实来源驱动实时状态和持久记录。不要只添加临时 toast,也不要将显示标签作为执行事实。

最小验收

  • Provider 返回错误时,Web 明确显示本轮失败及有界错误原因。
  • 流式输出部分内容后失败,已有内容保留,同时明确标记回答未正常完成。
  • 自动重试耗尽后显示最终失败;重试期间与最终状态不互相覆盖。
  • 刷新或重新进入 Session 后仍可看到失败事实和原因。
  • 成功、取消、失败、未知保持独立状态;启动前拒绝路径继续工作。
  • 用本地协议 fixture 覆盖真实 Pi → snapshot/SSE → 浏览器的链路;相关专项测试、bun run check、bun run test 通过。

Activity

  1. testikun commented on Sep 8, 2026

    @testikun
    Collaborator

    我来认领 Web Provider 运行失败证据丢失切片。

    技术方案:在 Pi assistant stopReason=error 的 authoritative runtime boundary 生成稳定的 failure receipt,保留 sanitized provider error、request/turn identity、已产生的部分输出和 retry/limit 信息;snapshot、SSE replay 与 Transcript 显式渲染失败态,不把它降级成普通 idle 或 no-output。启动前 prompt_failed、用户取消和未知终态继续走各自合同;补充 fixture Provider、重试耗尽、部分响应、刷新/重连测试。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions