Просмотр исходного кода

docs(apiproxy): record that a pending question dies with the host

The pending-question registry holds the awaiting tool call's own
resolve/reject, so it is host-process memory. events.mux replays every
still-pending question on reopen, which covers a browser reload or a
reconnect, but a host restart takes the awaiting turn with it and the
reopened Session offers no composer for that question.
Yichen Jiang 1 месяц назад
Родитель
Сommit
4562616c9b

+ 2 - 2
packages/host/apiproxy/README.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write packages/host/apiproxy/README.md
-README.md: 27efe5a75eb6947d71f95c0a60e590c15a35887c
-README.zh.md: 71f4e63a013170c6822a5c8dae28bc5f899b271a
+README.md: a9fb07519c1d8b3b2e2d759bd9138dac60f2306f
+README.zh.md: 9bde3583b0f5e6ce172bfe145f440150aabfa230

+ 1 - 0
packages/host/apiproxy/README.md

@@ -76,6 +76,7 @@ None; this package neither assembles nor sends a provider request.
 
 - **Forwarded Remote events are parasitic on this legacy frame union** — `host/remote-event` lives in `HostFrame` so the delivery path could reuse the existing host stream instead of opening a third downlink, which makes it read as if this package owned the Remote event contract. It does not: the allowlist is `dsh-api-remotes`' and the consumer verb is `ctx.remote.$on`. When the host stream moves off this package, the frame moves with it and the consumer contract is unaffected ([rationale](../../../.agents/notes/implemented/architecture/2026-08-10-remote-event-delivery.md)).
 - **Pending-interaction state is host-side** — the wire uses POST `/api/respond` plus `RpcReceipt`; the table in `src/api-proxy.ts` handles questions only and has no approval entries.
+- **A pending question does not survive a host restart** — the registry holds the awaiting tool call's own `resolve`/`reject`, so it is host-process memory. `events.mux` replays every still-pending question on each reopen, which covers a browser reload or a reconnect; a host restart takes the awaiting turn with it, and the reopened Session offers no composer for that question. Restoring one across a host restart needs a durable pending-interaction record and is deferred.
 - **Reserved seams stay out of `RpcMethodMap`** — `prompt.mode: 'inject'`, `job.list`, and a describe `hostInstanceId` are documented reservations; model discovery uses `llm.models`. An unknown method fails loud at envelope parse rather than getting a not-implemented code.
 - **No protocol version field** — client and host ship together; `host.describe` gains a version negotiation field only when an independently released client exists.
 - **Search failures include provider diagnostics** — the gateway is a single-user local service. A carrier that exposes it to multiple users must replace internal search details with a public-safe diagnostic.

+ 1 - 0
packages/host/apiproxy/README.zh.md

@@ -76,6 +76,7 @@ Workspace 列表与 Session 列表是相互独立的重连基线。`workspace.cr
 
 - **转发的 Remote 事件寄居在这套 legacy 帧联合里**:`host/remote-event` 住在 `HostFrame` 中,是为了让投递路径复用现有宿主流、不必新开第三条下行通道,因此读起来像是本包拥有 Remote 事件契约。并非如此:名单归 `dsh-api-remotes`,消费端动词是 `ctx.remote.$on`。将来宿主流整体搬离本包时,该帧随之搬走,消费端契约不受影响([原委](../../../.agents/notes/implemented/architecture/2026-08-10-remote-event-delivery.md))。
 - **待处理交互状态位于宿主侧**:wire 使用 POST `/api/respond` 加 `RpcReceipt`;`src/api-proxy.ts` 中的表只处理问题,不包含审批条目。
+- **待回答的提问无法跨宿主重启存活**:登记表持有等待中那次工具调用自身的 `resolve`/`reject`,因此它是宿主进程内存。`events.mux` 在每次重开时重放所有仍在等待的提问,这覆盖了浏览器刷新与重连;宿主重启则把等待中的 turn 一并带走,重新打开的 Session 不会为该提问提供任何作答界面。要让它跨宿主重启恢复,需要一份持久化的待处理交互记录,此项暂缓。
 - **预留 seam 不进入 `RpcMethodMap`**:`prompt.mode: 'inject'`、`job.list` 和描述字段 `hostInstanceId` 都是已记录的预留项;模型发现使用 `llm.models`。未知方法会在信封解析时直接失败,而不会返回「尚未实现」错误码。
 - **没有协议版本字段**:客户端与宿主一同发布;只有出现独立发布的客户端后,`host.describe` 才会增加版本协商字段。
 - **搜索失败会包含提供方诊断信息**:网关是单用户本地服务。将其暴露给多名用户的载体必须用可安全公开的诊断信息替代内部搜索细节。