(exchange []map[string]any)
| 67 | } |
| 68 | |
| 69 | func projectExchange(exchange []map[string]any) *ProjectedExchange { |
| 70 | if len(exchange) == 0 { |
| 71 | return nil |
| 72 | } |
| 73 | |
| 74 | proj := &ProjectedExchange{ |
| 75 | ToolCalls: []string{}, |
| 76 | KeyOutputs: []string{}, |
| 77 | } |
| 78 | |
| 79 | for _, msg := range exchange { |
| 80 | role, _ := msg["role"].(string) |
| 81 | if proj.Role == "" { |
| 82 | proj.Role = role |
| 83 | } |
| 84 | |
| 85 | content, ok := contentBlocks(msg["content"]) |
| 86 | if !ok { |
| 87 | continue |
| 88 | } |
| 89 | |
| 90 | for _, block := range content { |
| 91 | blockType, _ := block["type"].(string) |
| 92 | |
| 93 | switch blockType { |
| 94 | case "text": |
| 95 | text, _ := block["text"].(string) |
| 96 | if text != "" && len([]rune(text)) > 10 { |
| 97 | firstSent := strings.TrimSpace(strings.Split(text, ".")[0]) |
| 98 | firstSent = TruncateRunes(firstSent, 200) |
| 99 | |
| 100 | if proj.Summary == "" { |
| 101 | proj.Summary = firstSent |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | case "tool_use": |
| 106 | toolName, _ := block["name"].(string) |
| 107 | if toolName != "" { |
| 108 | proj.ToolCalls = append(proj.ToolCalls, toolName) |
| 109 | } |
| 110 | |
| 111 | case "tool_result": |
| 112 | result, _ := block["content"].(string) |
| 113 | if result != "" { |
| 114 | firstLine := strings.Split(strings.TrimSpace(result), "\n")[0] |
| 115 | firstLine = TruncateRunes(firstLine, 150) |
| 116 | |
| 117 | if firstLine != "" { |
| 118 | proj.KeyOutputs = append(proj.KeyOutputs, firstLine) |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | if proj.Summary == "" && len(proj.ToolCalls) == 0 { |
| 126 | return nil |
no test coverage detected