fix(web,gateway): close P3 re-review#4 findings — sanitize all executor catches; lock pre-start turn boundary (wire turnId deferred)
This commit is contained in:
@@ -586,6 +586,13 @@ function reduce(state: ChatConnectionState, action: Action): ChatConnectionState
|
||||
// still in-flight (or already-finalized) current turn.
|
||||
return next;
|
||||
}
|
||||
// Reaching here means turnPhase is 'active' — but AgentEndPayload
|
||||
// carries only a conversationId, no turn/message identity. In-order
|
||||
// delivery proves the boundary enforced above (a same-conversation end
|
||||
// arriving before this turn's own agent:start is provably stale); once
|
||||
// 'active', a genuine end for this turn and a same-conversation
|
||||
// stale/duplicate end are indistinguishable here. This residual is
|
||||
// accepted — full correlation requires a wire turnId, deferred to P5.
|
||||
const hasContent = next.text.length > 0 || next.thinking.length > 0;
|
||||
const messages = hasContent
|
||||
? capPush(
|
||||
@@ -751,6 +758,13 @@ function reduce(state: ChatConnectionState, action: Action): ChatConnectionState
|
||||
// nothing further remains in flight for it — so a scoped error seen
|
||||
// while turnPhase is 'pending' or 'active' can only belong to THIS
|
||||
// turn, and must settle and release the lock.
|
||||
//
|
||||
// Same wire limitation as agent:end above: ErrorPayload also carries
|
||||
// only a conversationId, no turn identity. A pre-ack ('pending') error
|
||||
// is accepted as current by design, per the reasoning above. Once
|
||||
// 'active', a genuine error for this turn and a same-conversation
|
||||
// stale/duplicate error are equally indistinguishable — accepted
|
||||
// residual; full correlation needs a wire turnId, deferred to P5.
|
||||
return {
|
||||
...next,
|
||||
error: asString(payload.error, 'An error occurred.'),
|
||||
|
||||
Reference in New Issue
Block a user