| 109 | value = strings.TrimSpace(value) |
| 110 | if value == "" { |
| 111 | continue |
| 112 | } |
| 113 | if _, exists := seen[value]; exists { |
| 114 | continue |
| 115 | } |
| 116 | seen[value] = struct{}{} |
| 117 | result = append(result, value) |
| 118 | } |
| 119 | return result |
| 120 | } |
| 121 | |
| 122 | func visibleMessageText(content any) string { |
| 123 | if text, ok := content.(string); ok { |
| 124 | return strings.TrimSpace(text) |
| 125 | } |
| 126 | var parts []string |
| 127 | appendBlock := func(block map[string]any) { |
| 128 | if kind := strings.ToLower(stringFromAny(block["type"])); kind == "text" || kind == "output_text" { |
| 129 | if text := strings.TrimSpace(stringFromAny(block["text"])); text != "" { |
| 130 | parts = append(parts, text) |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | switch blocks := content.(type) { |
| 135 | case []map[string]any: |
| 136 | for _, block := range blocks { |
| 137 | appendBlock(block) |
| 138 | } |
| 139 | case []any: |
| 140 | for _, raw := range blocks { |
| 141 | if block, ok := raw.(map[string]any); ok { |
| 142 | appendBlock(block) |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | return strings.TrimSpace(strings.Join(parts, "\n")) |