From 2452700d3715c5a398b6bb98bca9c97fdd80591e Mon Sep 17 00:00:00 2001 From: Molecule AI Backend Engineer Date: Fri, 17 Apr 2026 15:14:25 +0000 Subject: [PATCH] fix(a2a): restore delivery_confirmed body-read logic removed by hibernation commit (#689) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hibernation PR (7f5f74d) accidentally removed the delivery_confirmed fix that was introduced for issue #689. When io.ReadAll fails after the target has already responded with headers (200-399), the message WAS delivered — stripping delivery_confirmed from the error response caused callers to treat a successful send as a hard failure. Restore the full original body-read error block: - deliveryConfirmed flag (true when status 200-399) - log line with status/bytes_read context - logA2ASuccess call when deliveryConfirmed (audit trail accuracy) - proxyA2AError.Response includes "delivery_confirmed" field so callers can distinguish "not delivered" from "delivered, body lost" The hibernation auto-wake feature (resolveAgentURL status='hibernated' check) is orthogonal and untouched. Co-Authored-By: Claude Sonnet 4.6 --- platform/internal/handlers/a2a_proxy.go | 26 ++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/platform/internal/handlers/a2a_proxy.go b/platform/internal/handlers/a2a_proxy.go index f2d20717..ead4239c 100644 --- a/platform/internal/handlers/a2a_proxy.go +++ b/platform/internal/handlers/a2a_proxy.go @@ -274,12 +274,28 @@ func (h *WorkspaceHandler) proxyA2ARequest(ctx context.Context, workspaceID stri } defer resp.Body.Close() - // Read agent response (capped at 10MB) - respBody, err := io.ReadAll(io.LimitReader(resp.Body, maxProxyResponseBody)) - if err != nil { + // Read agent response (capped at 10MB). + // #689: Do() succeeded, which means the target received the request and sent + // back response headers — delivery is confirmed. The body couldn't be + // fully read (connection drop, timeout mid-stream). Surface + // delivery_confirmed so callers can distinguish "not delivered" from + // "delivered, but response body lost". When delivery is confirmed, + // log the activity as successful (delivery happened) rather than leaving + // a false "failed" entry in the audit trail. + respBody, readErr := io.ReadAll(io.LimitReader(resp.Body, maxProxyResponseBody)) + if readErr != nil { + deliveryConfirmed := resp.StatusCode >= 200 && resp.StatusCode < 400 + log.Printf("ProxyA2A: body read failed for %s (status=%d delivery_confirmed=%v bytes_read=%d): %v", + workspaceID, resp.StatusCode, deliveryConfirmed, len(respBody), readErr) + if logActivity && deliveryConfirmed { + h.logA2ASuccess(ctx, workspaceID, callerID, body, respBody, a2aMethod, resp.StatusCode, durationMs) + } return 0, nil, &proxyA2AError{ - Status: http.StatusBadGateway, - Response: gin.H{"error": "failed to read agent response"}, + Status: http.StatusBadGateway, + Response: gin.H{ + "error": "failed to read agent response", + "delivery_confirmed": deliveryConfirmed, + }, } }