LatestUserInputParts returns the most recent user-role input as a single A2A Part - i.e. what the AX user just typed. The walk goes backward from the end of msgs and returns as soon as it finds a user-role message with usable content (text/file/data).
(msgs []*proto.Message)
| 48 | // from the end of msgs and returns as soon as it finds a user-role |
| 49 | // message with usable content (text/file/data). |
| 50 | func LatestUserInputParts(msgs []*proto.Message) []*a2a.Part { |
| 51 | for i := len(msgs) - 1; i >= 0; i-- { |
| 52 | msg := msgs[i] |
| 53 | if msg == nil || msg.Role != "user" || msg.Content == nil { |
| 54 | continue |
| 55 | } |
| 56 | if isStateMarkerMessage(msg) { |
| 57 | continue |
| 58 | } |
| 59 | switch msg.Content.Type.(type) { |
| 60 | case *proto.Content_Confirmation, |
| 61 | *proto.Content_ToolCall, |
| 62 | *proto.Content_ToolResult, |
| 63 | *proto.Content_Thought: |
| 64 | continue |
| 65 | } |
| 66 | if p := contentToA2APart(msg.Content); p != nil { |
| 67 | return []*a2a.Part{p} |
| 68 | } |
| 69 | } |
| 70 | return nil |
| 71 | } |
| 72 | |
| 73 | // contentToA2APart converts a single AX Content variant into an A2A Part. |
| 74 | func contentToA2APart(content *proto.Content) *a2a.Part { |