From 9cc00245a27b4372d65408064ade51ccf028bfbc Mon Sep 17 00:00:00 2001 From: Molecule AI Fullstack Engineer Date: Tue, 12 May 2026 15:13:11 +0000 Subject: [PATCH 1/2] =?UTF-8?q?test(handlers/delegation):=20add=20extractR?= =?UTF-8?q?esponseText=20coverage=20=E2=80=94=2010=20cases=20for=20A2A=20r?= =?UTF-8?q?esponse=20text=20extraction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit extractResponseText in delegation.go had no unit tests. It extracts text from A2A JSON-RPC response bodies by walking result.parts and result.artifacts[*].parts arrays. Tests cover: non-JSON fallback, valid JSON with no result, result is not a map, parts with text kind, parts with non-text kind (image skipped → raw body), multiple parts (returns first text), artifacts with nested text parts, artifacts with non-text kind, empty parts/artifacts arrays, and empty text string. Co-Authored-By: Claude Opus 4.7 --- .../internal/handlers/delegation_test.go | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/workspace-server/internal/handlers/delegation_test.go b/workspace-server/internal/handlers/delegation_test.go index b53652cf..14c447bf 100644 --- a/workspace-server/internal/handlers/delegation_test.go +++ b/workspace-server/internal/handlers/delegation_test.go @@ -1287,3 +1287,84 @@ func TestExecuteDelegation_CleanProxyResponse_Unchanged(t *testing.T) { t.Errorf("unmet sqlmock expectations: %v", err) } } + +// ---------- extractResponseText ---------- + +func TestExtractResponseText_NonJSON(t *testing.T) { + got := extractResponseText([]byte("not json at all")) + if got != "not json at all" { + t.Errorf("non-JSON: got %q, want %q", got, "not json at all") + } +} + +func TestExtractResponseText_ValidJSONNoResult(t *testing.T) { + got := extractResponseText([]byte(`{"id":"1","error":{"code":-32601,"message":"method not found"}}`)) + if got != `{"id":"1","error":{"code":-32601,"message":"method not found"}}` { + t.Errorf("no result key: got %q, want raw body", got) + } +} + +func TestExtractResponseText_ResultNotMap(t *testing.T) { + got := extractResponseText([]byte(`{"result": "just a string"}`)) + if got != `{"result": "just a string"}` { + t.Errorf("result is string: got %q, want raw body", got) + } +} + +func TestExtractResponseText_PartsTextKind(t *testing.T) { + body := []byte(`{"result":{"parts":[{"kind":"text","text":"Hello from agent"}]}}`) + got := extractResponseText(body) + if got != "Hello from agent" { + t.Errorf("parts text: got %q, want %q", got, "Hello from agent") + } +} + +func TestExtractResponseText_PartsNonTextKind(t *testing.T) { + // kind="image" is skipped; falls through to raw body since no artifacts + body := []byte(`{"result":{"parts":[{"kind":"image","text":"should not return"}]}}`) + got := extractResponseText(body) + if got != string(body) { + t.Errorf("parts non-text: got %q, want raw body", got) + } +} + +func TestExtractResponseText_PartsMultipleWithTextFirst(t *testing.T) { + body := []byte(`{"result":{"parts":[{"kind":"text","text":"first"},{"kind":"text","text":"second"}]}}`) + got := extractResponseText(body) + // Returns first text part found + if got != "first" { + t.Errorf("parts first match: got %q, want %q", got, "first") + } +} + +func TestExtractResponseText_ArtifactsTextKind(t *testing.T) { + body := []byte(`{"result":{"artifacts":[{"parts":[{"kind":"text","text":"artifact text here"}]}]}}`) + got := extractResponseText(body) + if got != "artifact text here" { + t.Errorf("artifacts text: got %q, want %q", got, "artifact text here") + } +} + +func TestExtractResponseText_ArtifactsNonTextKind(t *testing.T) { + body := []byte(`{"result":{"artifacts":[{"parts":[{"kind":"image","text":"hidden"}]}]}}`) + got := extractResponseText(body) + if got != string(body) { + t.Errorf("artifacts non-text: got %q, want raw body", got) + } +} + +func TestExtractResponseText_EmptyPartsAndArtifacts(t *testing.T) { + body := []byte(`{"result":{"parts":[],"artifacts":[]}}`) + got := extractResponseText(body) + if got != string(body) { + t.Errorf("empty parts/artifacts: got %q, want raw body", got) + } +} + +func TestExtractResponseText_EmptyText(t *testing.T) { + body := []byte(`{"result":{"parts":[{"kind":"text","text":""}]}}`) + got := extractResponseText(body) + if got != "" { + t.Errorf("empty text: got %q, want %q", got, "") + } +} -- 2.45.2 From 5427fa39e286d59ff0e50dab53cef00c248f8212 Mon Sep 17 00:00:00 2001 From: core-devops Date: Tue, 12 May 2026 20:51:30 +0000 Subject: [PATCH 2/2] ci: rerun after mc#724 all-required fix lands -- 2.45.2