Skip to content

Commit 1452c36

Browse files
committed
docs(spec): document the Responses stream termination patch and E2E-248
1 parent cece324 commit 1452c36

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

docs/spec/03-runtime/11-provider-model-system.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,19 @@ model-level pin the provider-wide style applies unchanged.
610610

611611
This is the **universal escape hatch** guaranteeing market coverage beyond native integrations.
612612

613+
### 16.1 Responses stream termination (pi-ai patch)
614+
615+
The OpenAI Responses adapter must treat `response.completed` (and
616+
`response.incomplete`) as the end of the stream: after finalizing the
617+
response, it stops consuming the stream instead of awaiting the server's
618+
TCP FIN. Upstream pi-ai keeps iterating until the server closes the
619+
connection, which hangs the turn behind reverse proxies that hold the idle
620+
connection open. Until the fix ships upstream, `patches/` carries a pnpm
621+
patch on `@earendil-works/pi-ai@0.85.1` that breaks the event loop on the
622+
terminal event (the OpenAI SDK aborts the underlying request when the
623+
consumer stops iterating). Drop the patch once a pi-ai release includes the
624+
fix.
625+
613626
## 17. Multi-provider product rules
614627

615628
1. Multiple providers of the same `vendorKey` are allowed and independent (for

docs/spec/06-delivery/04-e2e-test-plan.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,29 @@ Each scenario is documented in this format:
660660
- **Status**: Unit-covered (preset matching, catalog aliases, Completions
661661
compat); rendered UI scenario Draft
662662

663+
#### E2E-248: Responses turn completes without waiting for the server to close the connection
664+
665+
- **Preconditions**: A provider whose model pins `api: "openai-responses"` (or
666+
a provider with `apiStyle: "responses"`) is configured; the endpoint is
667+
fronted by a proxy that holds the HTTP connection open after the final
668+
SSE event (a local reverse proxy or a stub server that never sends FIN).
669+
- **Steps**: 1) Start a session with that model and send a short prompt. 2)
670+
Capture the SSE frames and confirm the server emitted
671+
`response.completed` with `status: "completed"` and usage. 3) Keep the
672+
stub/proxy connection open without sending a TCP FIN. 4) Observe the
673+
assistant turn state and send a follow-up prompt.
674+
- **Expected**: The turn completes as soon as `response.completed` is
675+
finalized: usage is recorded, `stopReason` is `stop`, and the client stops
676+
consuming the stream (the underlying request is aborted) instead of
677+
blocking on the idle connection. The composer becomes idle immediately and
678+
the follow-up turn starts normally. The stream must not hang when the
679+
server never closes the connection.
680+
- **Specs linked**: `03-runtime/11-provider-model-system.md` (§16.1)
681+
- **Acceptance**: B (provider Responses compatibility)
682+
- **Milestone**: M2
683+
- **Status**: Unit-covered (stream processor terminates on the terminal
684+
event via the pi-ai patch); live-proxy scenario Draft
685+
663686
#### E2E-005E: DeepSeek thinking replay includes reasoning_content on aggregator endpoints
664687

665688
- **Preconditions**: An OpenAI-compatible provider whose base URL is not

docs/zh-CN/spec/03-runtime/11-provider-model-system.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,17 @@ UI 可能会显示层级提示,但默认情况下不得硬阻止未知模型
542542

543543
目录条目还可以额外固定模型级 wire API(例如 `api: "openai-responses"`)。存在时它优先于 provider`apiStyle`,因此 `opencode_go` 下的 responses-only 模型会走 Responses adapter 而非 Chat Completions;没有模型级固定时保持 provider 级风格不变。
544544

545+
### 16.1 Responses 流终止(pi-ai 补丁)
546+
547+
OpenAI Responses 适配器必须把 `response.completed`(以及
548+
`response.incomplete`)视为流的终点:完成响应收尾后即停止消费流,
549+
而不是继续等待服务端的 TCP FIN。上游 pi-ai 会一直迭代直到服务端关闭
550+
连接,在保持空闲连接不关的反向代理后面会导致整个回合挂起。在该修复
551+
随上游发布之前,`patches/` 通过 pnpm patch 修改
552+
`@earendil-works/pi-ai@0.85.1`,在终态事件处跳出事件循环(消费方停止
553+
迭代时 OpenAI SDK 会中止底层请求)。待 pi-ai 发布包含该修复的版本后
554+
移除补丁。
555+
545556
## 17. 多提供商产品规则
546557

547558
1. 允许多个提供商具有相同的供应商密钥(例如两个 OpenRouter 帐户)。

0 commit comments

Comments
 (0)