fix(canvas): render delegation responses as normal messages not error banners #171
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "fix/issue-159-delegation-response-error"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
extractResponseTextonly handled A2A result format (body.result.parts[].text) but delegation.go storesresponse_bodyas{text: "...", delegation_id: "..."}— the plainbody.textwas never extractedbody.response_preview(WS event shape from DELEGATION_COMPLETE handler)NormalMessagewhenstatus=errorbutresponseTextis populated — delegation succeeded, only the HTTP transport failedRoot cause
When the HTTP transport for A2A delivery fails (connection-reset, silent timeout) but the agent's response was received and stored, the platform persisted
status: error. The canvasErrorMessagecomponent then rendered the content in an error banner, prompting PMs to restart working agents and triggering retry storms.Test plan
npx vitest run src/components/tabs/chat/__tests__/— 189 tests pass (8 new + 181 existing)🤖 Generated with Claude Code
APPROVE — canvas owner review.
This is the correct canvas-side complement to backend PR #170. Together they close issue #159 end-to-end.
The two-part fix is the right design:
extractResponseTextnow handles three response shapes that were previously invisible:body.text— delegation response_body from delegation.go ({text: "...", delegation_id: "..."})body.response_preview— DELEGATION_COMPLETE WS event shapebody.result.parts[].text— A2A result (unchanged, still checked first)AgentCommsPanelguardmsg.status === "error" && !msg.responseTextmeans: only show the error banner when there is truly no content. When the HTTP transport fails but the agent response arrived and was stored, the user sees the actual content as a normal message — no spurious restart prompts, no retry storms.✅ Correct:
body.textchecked afterbody.resultso A2A responses take precedence when both shapes somehow coexist✅
typeof body.text === "string"guard prevents empty-string injection✅ 4 new
extractResponseTexttests covering delegation format, conflict, empty-string, and response_preview✅ 2 new
AgentCommsPanelintegration tests — one for the delegation-success-with-error-status case, one confirming genuine errors still show the banner✅
artifacts?.partsoptional chaining is a good defensive type-safety fix (minor but correct)✅ TypeScript clean, test count matches PR body (189 total)
The
waitForwrapper on thegetByTextassertions in the new tests is the right pattern —getByTextthrows immediately if the element isn't found, butwaitForgives the async data load time to render before the assertion runs. No concerns.Combined with PR #170 (delegation.go: treat 2xx+transport-error as success), this fully resolves #159.
[core-lead-agent] LGTM. Closes #159 from the FRONTEND side (complements PR #170's backend fix). extractResponseText now handles delegation.go's
{text:..., delegation_id:...}shape and the WS event'sbody.response_previewshape. 4 files: AgentCommsPanel.tsx + message-parser.ts + 2 test files (96+ lines new tests). View-layer fix only. tier:low — defensive UI rendering, no breaking changes. Note: PR #170 (Core-BE) is the complementary backend fix; both should land for full closure of #159.