What
_runTurn handles a non-stream response with a chain that has no final else:
if (outcome.kind === 'json') {
if (outcome.status === 409) { ... }
else if (outcome.json?.error) { ... }
else if (outcome.json?.reply) { ... }
}
Anything else falls straight through: recover stays false, no bubble is pushed,
no error is shown, _loading clears and the composer re-enables. The user sent a
message and got nothing at all: no reply, no failure, no explanation.
Reachable whenever the response is JSON-shaped but not one of the three expected
shapes:
- a body that failed to parse, so
streamChat returns json: null (a proxy
error page, a truncated response)
- a 5xx whose body carries
{"message": ...} rather than {"error": ...}
- a 200 whose reply text is empty string (falsy, so the
reply branch is skipped)
- any future non-409 pre-stream refusal that reports its reason under a different
key
Why
Silence is the worst of the available outcomes. A wrong error message is
debuggable; nothing at all reads as "the app ignored me", and the natural response
(send it again) is also the response that would be wrong if the turn actually did
start server-side.
Every other branch of this method ends in either a reply, an error bubble, or a
recovery attempt. This one should too.
Acceptance criteria
What
_runTurnhandles a non-stream response with a chain that has no finalelse:Anything else falls straight through:
recoverstays false, no bubble is pushed,no error is shown,
_loadingclears and the composer re-enables. The user sent amessage and got nothing at all: no reply, no failure, no explanation.
Reachable whenever the response is JSON-shaped but not one of the three expected
shapes:
streamChatreturnsjson: null(a proxyerror page, a truncated response)
{"message": ...}rather than{"error": ...}replybranch is skipped)key
Why
Silence is the worst of the available outcomes. A wrong error message is
debuggable; nothing at all reads as "the app ignored me", and the natural response
(send it again) is also the response that would be wrong if the turn actually did
start server-side.
Every other branch of this method ends in either a reply, an error bubble, or a
recovery attempt. This one should too.
Acceptance criteria
failure only once the recovery proves there is nothing to collect (the same
path a dropped stream already takes)
{}, each end with either a reply or a visible failure, never with nothing