Skip to content

Commit 3876aea

Browse files
authored
Merge pull request #1954 from dgageot/board/bump-google-golang-org-adk-fix-what-need-73b9256a
bump google.golang.org/adk from v0.4.0 to v0.5.0
2 parents c58fef0 + 8f5ae25 commit 3876aea

File tree

3 files changed

+77
-135
lines changed

3 files changed

+77
-135
lines changed

e2e/cagent_a2a_test.go

Lines changed: 74 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,38 @@ import (
1818
"github.com/docker/cagent/pkg/config"
1919
)
2020

21-
type Response struct {
22-
Jsonrpc string `json:"jsonrpc"`
23-
ID string `json:"id"`
24-
Result *Result `json:"result,omitempty"`
25-
Error any `json:"error,omitempty"`
21+
// a2aResponse is a simplified representation of a JSON-RPC response
22+
// that only captures the fields we care about in tests.
23+
type a2aResponse struct {
24+
Jsonrpc string `json:"jsonrpc"`
25+
ID string `json:"id"`
26+
Error any `json:"error,omitempty"`
27+
28+
// Result holds the task with its artifacts.
29+
Result *struct {
30+
Artifacts []struct {
31+
Parts []struct {
32+
Kind string `json:"kind"`
33+
Text string `json:"text"`
34+
} `json:"parts"`
35+
} `json:"artifacts"`
36+
} `json:"result,omitempty"`
2637
}
2738

28-
type Result struct {
29-
Artifacts []Artifact `json:"artifacts"`
30-
}
31-
32-
type Artifact struct {
33-
Parts []Part `json:"parts"`
34-
}
35-
36-
type Part struct {
37-
Kind string `json:"kind"`
38-
Text string `json:"text"`
39+
// textParts returns all text parts across every artifact in the response.
40+
func (r *a2aResponse) textParts() []string {
41+
if r.Result == nil {
42+
return nil
43+
}
44+
var texts []string
45+
for _, a := range r.Result.Artifacts {
46+
for _, p := range a.Parts {
47+
if p.Kind == "text" {
48+
texts = append(texts, p.Text)
49+
}
50+
}
51+
}
52+
return texts
3953
}
4054

4155
func TestA2AServer_AgentCard(t *testing.T) {
@@ -58,55 +72,18 @@ func TestA2AServer_Invoke(t *testing.T) {
5872
_, runConfig := startRecordingAIProxy(t)
5973
agentCard := startA2AServer(t, "testdata/basic.yaml", runConfig)
6074

61-
requestID := "test-request-1"
62-
jsonRPCRequest := map[string]any{
63-
"jsonrpc": "2.0",
64-
"id": requestID,
65-
"method": "message/send",
66-
"params": map[string]any{
67-
"message": map[string]any{
68-
"messageId": "msg-1",
69-
"role": "user",
70-
"parts": []map[string]any{
71-
{
72-
"kind": "text",
73-
"text": "What is 2+2? Answer with just the number.",
74-
},
75-
},
76-
},
77-
},
78-
}
79-
80-
requestBody, err := json.Marshal(jsonRPCRequest)
81-
require.NoError(t, err)
82-
83-
req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, agentCard.URL, bytes.NewReader(requestBody))
84-
require.NoError(t, err)
85-
req.Header.Set("Content-Type", "application/json")
86-
87-
resp, err := http.DefaultClient.Do(req)
88-
require.NoError(t, err)
89-
defer resp.Body.Close()
90-
91-
assert.Equal(t, http.StatusOK, resp.StatusCode)
92-
93-
responseBody, err := io.ReadAll(resp.Body)
94-
require.NoError(t, err)
75+
resp := sendA2AMessage(t, agentCard.URL, "test-request-1", "msg-1", "What is 2+2? Answer with just the number.")
9576

96-
var jsonRPCResponse Response
97-
err = json.Unmarshal(responseBody, &jsonRPCResponse)
98-
require.NoError(t, err)
77+
assert.Equal(t, "2.0", resp.Jsonrpc)
78+
assert.Equal(t, "test-request-1", resp.ID)
79+
assert.Nil(t, resp.Error)
80+
require.NotNil(t, resp.Result)
9981

100-
assert.Equal(t, "2.0", jsonRPCResponse.Jsonrpc)
101-
assert.Equal(t, requestID, jsonRPCResponse.ID)
102-
assert.Nil(t, jsonRPCResponse.Error)
103-
require.NotNil(t, jsonRPCResponse.Result)
104-
assert.Len(t, jsonRPCResponse.Result.Artifacts, 1)
105-
assert.Len(t, jsonRPCResponse.Result.Artifacts[0].Parts, 2)
106-
assert.Equal(t, "text", jsonRPCResponse.Result.Artifacts[0].Parts[0].Kind)
107-
assert.Equal(t, "4", jsonRPCResponse.Result.Artifacts[0].Parts[0].Text)
108-
assert.Equal(t, "text", jsonRPCResponse.Result.Artifacts[0].Parts[1].Kind)
109-
assert.Equal(t, "4", jsonRPCResponse.Result.Artifacts[0].Parts[1].Text)
82+
texts := resp.textParts()
83+
require.NotEmpty(t, texts)
84+
for _, text := range texts {
85+
assert.Equal(t, "4", text)
86+
}
11087
}
11188

11289
func TestA2AServer_MultipleRequests(t *testing.T) {
@@ -123,47 +100,13 @@ func TestA2AServer_MultipleRequests(t *testing.T) {
123100
for i, message := range messages {
124101
t.Run(fmt.Sprintf("request_%d", i), func(t *testing.T) {
125102
requestID := fmt.Sprintf("test-request-%d", i)
126-
jsonRPCRequest := map[string]any{
127-
"jsonrpc": "2.0",
128-
"id": requestID,
129-
"method": "message/send",
130-
"params": map[string]any{
131-
"message": map[string]any{
132-
"messageId": fmt.Sprintf("msg-%d", i),
133-
"role": "user",
134-
"parts": []map[string]any{
135-
{
136-
"kind": "text",
137-
"text": message,
138-
},
139-
},
140-
},
141-
},
142-
}
143-
144-
requestBody, err := json.Marshal(jsonRPCRequest)
145-
require.NoError(t, err)
103+
msgID := fmt.Sprintf("msg-%d", i)
146104

147-
req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, agentCard.URL, bytes.NewReader(requestBody))
148-
require.NoError(t, err)
149-
req.Header.Set("Content-Type", "application/json")
105+
resp := sendA2AMessage(t, agentCard.URL, requestID, msgID, message)
150106

151-
resp, err := http.DefaultClient.Do(req)
152-
require.NoError(t, err)
153-
defer resp.Body.Close()
154-
155-
assert.Equal(t, http.StatusOK, resp.StatusCode)
156-
157-
responseBody, err := io.ReadAll(resp.Body)
158-
require.NoError(t, err)
159-
160-
var jsonRPCResponse Response
161-
err = json.Unmarshal(responseBody, &jsonRPCResponse)
162-
require.NoError(t, err)
163-
164-
assert.Equal(t, requestID, jsonRPCResponse.ID)
165-
assert.Nil(t, jsonRPCResponse.Error)
166-
assert.NotNil(t, jsonRPCResponse.Result)
107+
assert.Equal(t, requestID, resp.ID)
108+
assert.Nil(t, resp.Error)
109+
assert.NotNil(t, resp.Result)
167110
})
168111
}
169112
}
@@ -174,63 +117,59 @@ func TestA2AServer_MultiAgent(t *testing.T) {
174117
_, runConfig := startRecordingAIProxy(t)
175118
agentCard := startA2AServer(t, "testdata/multi.yaml", runConfig)
176119

177-
requestID := "test-multi-1"
178-
jsonRPCRequest := map[string]any{
120+
resp := sendA2AMessage(t, agentCard.URL, "test-multi-1", "msg-multi-1", "Say hello.")
121+
122+
assert.Equal(t, "test-multi-1", resp.ID)
123+
assert.Nil(t, resp.Error)
124+
require.NotNil(t, resp.Result)
125+
126+
texts := resp.textParts()
127+
require.NotEmpty(t, texts)
128+
assert.Contains(t, texts[len(texts)-1], "Hello")
129+
}
130+
131+
// sendA2AMessage sends a message/send JSON-RPC request and returns the parsed response.
132+
func sendA2AMessage(t *testing.T, url, requestID, messageID, text string) a2aResponse {
133+
t.Helper()
134+
135+
body, err := json.Marshal(map[string]any{
179136
"jsonrpc": "2.0",
180137
"id": requestID,
181138
"method": "message/send",
182139
"params": map[string]any{
183140
"message": map[string]any{
184-
"messageId": "msg-multi-1",
141+
"messageId": messageID,
185142
"role": "user",
186-
"parts": []map[string]any{
187-
{
188-
"kind": "text",
189-
"text": "Say hello.",
190-
},
191-
},
143+
"parts": []map[string]any{{"kind": "text", "text": text}},
192144
},
193145
},
194-
}
195-
196-
requestBody, err := json.Marshal(jsonRPCRequest)
146+
})
197147
require.NoError(t, err)
198148

199-
req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, agentCard.URL, bytes.NewReader(requestBody))
149+
req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, url, bytes.NewReader(body))
200150
require.NoError(t, err)
201151
req.Header.Set("Content-Type", "application/json")
202152

203153
resp, err := http.DefaultClient.Do(req)
204154
require.NoError(t, err)
205155
defer resp.Body.Close()
206156

207-
assert.Equal(t, http.StatusOK, resp.StatusCode)
208-
209-
responseBody, err := io.ReadAll(resp.Body)
210-
require.NoError(t, err)
157+
require.Equal(t, http.StatusOK, resp.StatusCode)
211158

212-
var jsonRPCResponse Response
213-
err = json.Unmarshal(responseBody, &jsonRPCResponse)
159+
data, err := io.ReadAll(resp.Body)
214160
require.NoError(t, err)
215161

216-
assert.Equal(t, requestID, jsonRPCResponse.ID)
217-
assert.Nil(t, jsonRPCResponse.Error)
218-
require.NotNil(t, jsonRPCResponse.Result)
219-
require.Len(t, jsonRPCResponse.Result.Artifacts, 1)
220-
require.NotEmpty(t, jsonRPCResponse.Result.Artifacts[0].Parts)
162+
var parsed a2aResponse
163+
require.NoError(t, json.Unmarshal(data, &parsed))
221164

222-
// The last part contains the complete response text
223-
lastPart := jsonRPCResponse.Result.Artifacts[0].Parts[len(jsonRPCResponse.Result.Artifacts[0].Parts)-1]
224-
assert.Equal(t, "text", lastPart.Kind)
225-
assert.Contains(t, lastPart.Text, "Hello")
165+
return parsed
226166
}
227167

228168
func startA2AServer(t *testing.T, agentFile string, runConfig *config.RuntimeConfig) a2a.AgentCard {
229169
t.Helper()
230170

231171
var lc net.ListenConfig
232172
ln, err := lc.Listen(t.Context(), "tcp", ":0")
233-
234173
require.NoError(t, err)
235174

236175
go func() {
@@ -240,7 +179,10 @@ func startA2AServer(t *testing.T, agentFile string, runConfig *config.RuntimeCon
240179
port := ln.Addr().(*net.TCPAddr).Port
241180
serverURL := fmt.Sprintf("http://localhost:%d", port)
242181

243-
resp, err := http.Get(serverURL + a2asrv.WellKnownAgentCardPath)
182+
cardReq, err := http.NewRequestWithContext(t.Context(), http.MethodGet, serverURL+a2asrv.WellKnownAgentCardPath, http.NoBody)
183+
require.NoError(t, err)
184+
185+
resp, err := http.DefaultClient.Do(cardReq)
244186
require.NoError(t, err)
245187
defer resp.Body.Close()
246188

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ require (
6666
golang.org/x/sync v0.19.0
6767
golang.org/x/sys v0.41.0
6868
golang.org/x/term v0.40.0
69-
google.golang.org/adk v0.4.0
69+
google.golang.org/adk v0.5.0
7070
google.golang.org/genai v1.48.0
7171
google.golang.org/protobuf v1.36.11
7272
gopkg.in/dnaeon/go-vcr.v4 v4.0.6

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,8 @@ golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
576576
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
577577
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
578578
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
579-
google.golang.org/adk v0.4.0 h1:CJ31nyxkqRfEgKuttR4h3o6QFok94Ty4UpbefUn21h8=
580-
google.golang.org/adk v0.4.0/go.mod h1:jVeb7Ir53+3XKTncdY7k3pVdPneKcm5+60sXpxHQnao=
579+
google.golang.org/adk v0.5.0 h1:VFwJU8uX+S/wBZH6OatzyIrK6fd0oebVT9TnISb82FA=
580+
google.golang.org/adk v0.5.0/go.mod h1:W0RyHt+JXfZHA1VnxeGALRZeqAlp54nv2cw7Sn7M5Jc=
581581
google.golang.org/genai v1.48.0 h1:1vb15G291wAjJJueisMDpUhssljhEdJU2t5qTidrVPs=
582582
google.golang.org/genai v1.48.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk=
583583
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0=

0 commit comments

Comments
 (0)