@@ -10,12 +10,11 @@ package main
10
10
import (
11
11
"context"
12
12
"flag"
13
- "log "
13
+ "fmt "
14
14
"time"
15
15
16
- "github.com/google/uuid"
17
-
18
16
"trpc.group/trpc-go/trpc-a2a-go/client"
17
+ "trpc.group/trpc-go/trpc-a2a-go/log"
19
18
"trpc.group/trpc-go/trpc-a2a-go/protocol"
20
19
)
21
20
@@ -24,6 +23,7 @@ func main() {
24
23
agentURL := flag .String ("agent" , "http://localhost:8080/" , "Target A2A agent URL" )
25
24
timeout := flag .Duration ("timeout" , 30 * time .Second , "Request timeout (e.g., 30s, 1m)" )
26
25
message := flag .String ("message" , "Hello, world!" , "Message to send to the agent" )
26
+ streaming := flag .Bool ("streaming" , false , "Use streaming mode (message/stream)" )
27
27
flag .Parse ()
28
28
29
29
// Create A2A client.
@@ -33,56 +33,105 @@ func main() {
33
33
}
34
34
35
35
// Display connection information.
36
- log .Printf ("Connecting to agent: %s (Timeout: %v)" , * agentURL , * timeout )
37
-
38
- // Create a new unique message ID and context ID.
39
- contextID := uuid .New ().String ()
40
- log .Printf ("Context ID: %s" , contextID )
36
+ log .Infof ("Connecting to agent: %s (Timeout: %v)" , * agentURL , * timeout )
37
+ log .Infof ("Mode: %s" , map [bool ]string {true : "Streaming" , false : "Standard" }[* streaming ])
41
38
42
39
// Create the message to send using the new constructor.
43
- userMessage := protocol .NewMessageWithContext (
40
+ userMessage := protocol .NewMessage (
44
41
protocol .MessageRoleUser ,
45
42
[]protocol.Part {protocol .NewTextPart (* message )},
46
- nil , // taskID
47
- & contextID ,
48
43
)
49
44
50
45
// Create message parameters using the new SendMessageParams structure.
51
46
params := protocol.SendMessageParams {
52
47
Message : userMessage ,
53
48
Configuration : & protocol.SendMessageConfiguration {
54
- Blocking : boolPtr (true ), // Wait for completion
49
+ Blocking : boolPtr (false ), // Non-blocking for streaming, blocking for standard
55
50
},
56
51
}
57
52
58
- log .Printf ("Sending message with content: %s" , * message )
53
+ log .Infof ("Sending message with content: %s" , * message )
59
54
60
- // Send message to the agent using the new message API .
55
+ // Create context for the request .
61
56
ctx , cancel := context .WithTimeout (context .Background (), * timeout )
62
57
defer cancel ()
63
58
59
+ if * streaming {
60
+ // Use streaming mode
61
+ handleStreamingMode (ctx , a2aClient , params )
62
+ } else {
63
+ // Use standard mode
64
+ handleStandardMode (ctx , a2aClient , params )
65
+ }
66
+ }
67
+
68
+ // handleStreamingMode handles streaming message sending and event processing
69
+ func handleStreamingMode (ctx context.Context , a2aClient * client.A2AClient , params protocol.SendMessageParams ) {
70
+ log .Infof ("Starting streaming request..." )
71
+
72
+ // Send streaming message request
73
+ eventChan , err := a2aClient .StreamMessage (ctx , params )
74
+ if err != nil {
75
+ log .Fatalf ("Failed to start streaming: %v" , err )
76
+ }
77
+
78
+ log .Infof ("Processing streaming events..." )
79
+
80
+ eventCount := 0
81
+ var finalResult string
82
+
83
+ // Process streaming events
84
+ for {
85
+ select {
86
+ case event , ok := <- eventChan :
87
+ if ! ok {
88
+ log .Infof ("Stream completed. Total events received: %d" , eventCount )
89
+ if finalResult != "" {
90
+ log .Infof ("Final result: %s" , finalResult )
91
+ }
92
+ return
93
+ }
94
+
95
+ eventCount ++
96
+ log .Infof ("Event %d received: %s" , eventCount , getEventDescription (event ))
97
+
98
+ // Extract final result from completed events
99
+ if result := extractFinalResult (event ); result != "" {
100
+ finalResult = result
101
+ log .Infof ("Received msg: [Text: %s]" , result )
102
+ }
103
+
104
+ case <- ctx .Done ():
105
+ log .Infof ("Request timed out after receiving %d events" , eventCount )
106
+ return
107
+ }
108
+ }
109
+ }
110
+
111
+ // handleStandardMode handles standard (non-streaming) message sending
112
+ func handleStandardMode (ctx context.Context , a2aClient * client.A2AClient , params protocol.SendMessageParams ) {
64
113
messageResult , err := a2aClient .SendMessage (ctx , params )
65
114
if err != nil {
66
115
log .Fatalf ("Failed to send message: %v" , err )
67
116
}
68
117
69
118
// Display the result.
70
- log .Printf ("Message sent successfully" )
119
+ log .Infof ("Message sent successfully" )
71
120
72
121
// Handle the result based on its type
73
122
switch result := messageResult .Result .(type ) {
74
123
case * protocol.Message :
75
- log .Printf ("Received message response:" )
124
+ log .Infof ("Received message response:" )
76
125
printMessage (* result )
77
126
case * protocol.Task :
78
- log .Printf ("Received task response - ID: %s, State: %s" , result .ID , result .Status .State )
127
+ log .Infof ("Received task response - ID: %s, State: %s" , result .ID , result .Status .State )
79
128
80
129
// If task is not completed, wait and check again
81
130
if result .Status .State != protocol .TaskStateCompleted &&
82
131
result .Status .State != protocol .TaskStateFailed &&
83
132
result .Status .State != protocol .TaskStateCanceled {
84
133
85
- log .Printf ("Task %s is %s, fetching final state..." , result .ID , result .Status .State )
134
+ log .Infof ("Task %s is %s, fetching final state..." , result .ID , result .Status .State )
86
135
87
136
// Get the task's final state.
88
137
queryParams := protocol.TaskQueryParams {
@@ -97,65 +146,124 @@ func main() {
97
146
log .Fatalf ("Failed to get task status: %v" , err )
98
147
}
99
148
100
- log .Printf ("Task %s final state: %s" , task .ID , task .Status .State )
149
+ log .Infof ("Task %s final state: %s" , task .ID , task .Status .State )
101
150
printTaskResult (task )
102
151
} else {
103
152
printTaskResult (result )
104
153
}
105
154
default :
106
- log .Printf ("Received unknown result type: %T" , result )
155
+ log .Infof ("Received unknown result type: %T" , result )
156
+ }
157
+ }
158
+
159
+ // getEventDescription returns a human-readable description of the streaming event
160
+ func getEventDescription (event protocol.StreamingMessageEvent ) string {
161
+ switch result := event .Result .(type ) {
162
+ case * protocol.Message :
163
+ ctxID := "unknown"
164
+ if result .ContextID != nil {
165
+ ctxID = * result .ContextID
166
+ }
167
+ return fmt .Sprintf ("Message from %s, ContextID: %v" , result .Role , ctxID )
168
+ case * protocol.Task :
169
+ return fmt .Sprintf ("Task %s - State: %s, ContextID: %v" , result .ID , result .Status .State , result .ContextID )
170
+ case * protocol.TaskStatusUpdateEvent :
171
+ return fmt .Sprintf (
172
+ "Status Update - Task: %s, State: %s, ContextID: %v" ,
173
+ result .TaskID ,
174
+ result .Status .State ,
175
+ result .ContextID ,
176
+ )
177
+ case * protocol.TaskArtifactUpdateEvent :
178
+ artifactName := "Unnamed"
179
+ if result .Artifact .Name != nil {
180
+ artifactName = * result .Artifact .Name
181
+ }
182
+ return fmt .Sprintf ("Artifact Update - %s, ContextID: %v" , artifactName , result .ContextID )
183
+ default :
184
+ return fmt .Sprintf ("Unknown event type: %T" , result )
185
+ }
186
+ }
187
+
188
+ // extractFinalResult extracts the final text result from streaming events
189
+ func extractFinalResult (event protocol.StreamingMessageEvent ) string {
190
+ switch result := event .Result .(type ) {
191
+ case * protocol.Message :
192
+ // Extract text from message parts
193
+ for _ , part := range result .Parts {
194
+ if textPart , ok := part .(* protocol.TextPart ); ok {
195
+ return textPart .Text
196
+ }
197
+ }
198
+ case * protocol.Task :
199
+ // Extract text from task status message
200
+ if result .Status .Message != nil {
201
+ for _ , part := range result .Status .Message .Parts {
202
+ if textPart , ok := part .(* protocol.TextPart ); ok {
203
+ return textPart .Text
204
+ }
205
+ }
206
+ }
207
+ case * protocol.TaskArtifactUpdateEvent :
208
+ // Extract text from artifact parts
209
+ for _ , part := range result .Artifact .Parts {
210
+ if textPart , ok := part .(* protocol.TextPart ); ok {
211
+ return textPart .Text
212
+ }
213
+ }
107
214
}
215
+ return ""
108
216
}
109
217
110
218
// printMessage prints the contents of a message.
111
219
func printMessage (message protocol.Message ) {
112
- log .Printf ("Message ID: %s" , message .MessageID )
220
+ log .Infof ("Message ID: %s" , message .MessageID )
113
221
if message .ContextID != nil {
114
- log .Printf ("Context ID: %s" , * message .ContextID )
222
+ log .Infof ("Context ID: %s" , * message .ContextID )
115
223
}
116
- log .Printf ("Role: %s" , message .Role )
224
+ log .Infof ("Role: %s" , message .Role )
117
225
118
- log .Printf ("Message parts:" )
226
+ log .Infof ("Message parts:" )
119
227
for i , part := range message .Parts {
120
228
switch p := part .(type ) {
121
229
case * protocol.TextPart :
122
- log .Printf (" Part %d (text): %s" , i + 1 , p .Text )
230
+ log .Infof (" Part %d (text): %s" , i + 1 , p .Text )
123
231
case * protocol.FilePart :
124
- log .Printf (" Part %d (file): [file content]" , i + 1 )
232
+ log .Infof (" Part %d (file): [file content]" , i + 1 )
125
233
case * protocol.DataPart :
126
- log .Printf (" Part %d (data): %+v" , i + 1 , p .Data )
234
+ log .Infof (" Part %d (data): %+v" , i + 1 , p .Data )
127
235
default :
128
- log .Printf (" Part %d (unknown): %+v" , i + 1 , part )
236
+ log .Infof (" Part %d (unknown): %+v" , i + 1 , part )
129
237
}
130
238
}
131
239
}
132
240
133
241
// printTaskResult prints the contents of a task result.
134
242
func printTaskResult (task * protocol.Task ) {
135
243
if task .Status .Message != nil {
136
- log .Printf ("Task result message:" )
244
+ log .Infof ("Task result message:" )
137
245
printMessage (* task .Status .Message )
138
246
}
139
247
140
248
// Print artifacts if any
141
249
if len (task .Artifacts ) > 0 {
142
- log .Printf ("Task artifacts:" )
250
+ log .Infof ("Task artifacts:" )
143
251
for i , artifact := range task .Artifacts {
144
252
name := "Unnamed"
145
253
if artifact .Name != nil {
146
254
name = * artifact .Name
147
255
}
148
- log .Printf (" Artifact %d: %s" , i + 1 , name )
256
+ log .Infof (" Artifact %d: %s" , i + 1 , name )
149
257
for j , part := range artifact .Parts {
150
258
switch p := part .(type ) {
151
259
case * protocol.TextPart :
152
- log .Printf (" Part %d (text): %s" , j + 1 , p .Text )
260
+ log .Infof (" Part %d (text): %s" , j + 1 , p .Text )
153
261
case * protocol.FilePart :
154
- log .Printf (" Part %d (file): [file content]" , j + 1 )
262
+ log .Infof (" Part %d (file): [file content]" , j + 1 )
155
263
case * protocol.DataPart :
156
- log .Printf (" Part %d (data): %+v" , j + 1 , p .Data )
264
+ log .Infof (" Part %d (data): %+v" , j + 1 , p .Data )
157
265
default :
158
- log .Printf (" Part %d (unknown): %+v" , j + 1 , part )
266
+ log .Infof (" Part %d (unknown): %+v" , j + 1 , part )
159
267
}
160
268
}
161
269
}
0 commit comments