summaryrefslogtreecommitdiffhomepage
path: root/packages/tui/internal/attachment/attachment.go
blob: 3ecd861983837b79300d74efb11e034a0b3ecf4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package attachment

import (
	"github.com/google/uuid"
)

type TextSource struct {
	Value string `toml:"value"`
}

type FileSource struct {
	Path string `toml:"path"`
	Mime string `toml:"mime"`
	Data []byte `toml:"data,omitempty"` // Optional for image data
}

type SymbolSource struct {
	Path  string      `toml:"path"`
	Name  string      `toml:"name"`
	Kind  int         `toml:"kind"`
	Range SymbolRange `toml:"range"`
}

type SymbolRange struct {
	Start Position `toml:"start"`
	End   Position `toml:"end"`
}

type AgentSource struct {
	Name string `toml:"name"`
}

type Position struct {
	Line int `toml:"line"`
	Char int `toml:"char"`
}

type Attachment struct {
	ID         string `toml:"id"`
	Type       string `toml:"type"`
	Display    string `toml:"display"`
	URL        string `toml:"url"`
	Filename   string `toml:"filename"`
	MediaType  string `toml:"media_type"`
	StartIndex int    `toml:"start_index"`
	EndIndex   int    `toml:"end_index"`
	Source     any    `toml:"source,omitempty"`
}

// NewAttachment creates a new attachment with a unique ID
func NewAttachment() *Attachment {
	return &Attachment{
		ID: uuid.NewString(),
	}
}

func (a *Attachment) GetTextSource() (*TextSource, bool) {
	if a.Type != "text" {
		return nil, false
	}
	ts, ok := a.Source.(*TextSource)
	return ts, ok
}

// GetFileSource returns the source as FileSource if the attachment is a file type
func (a *Attachment) GetFileSource() (*FileSource, bool) {
	if a.Type != "file" {
		return nil, false
	}
	fs, ok := a.Source.(*FileSource)
	return fs, ok
}

// GetSymbolSource returns the source as SymbolSource if the attachment is a symbol type
func (a *Attachment) GetSymbolSource() (*SymbolSource, bool) {
	if a.Type != "symbol" {
		return nil, false
	}
	ss, ok := a.Source.(*SymbolSource)
	return ss, ok
}

// GetAgentSource returns the source as AgentSource if the attachment is an agent type
func (a *Attachment) GetAgentSource() (*AgentSource, bool) {
	if a.Type != "agent" {
		return nil, false
	}
	as, ok := a.Source.(*AgentSource)
	return as, ok
}

// FromMap creates a TextSource from a map[string]any
func (ts *TextSource) FromMap(sourceMap map[string]any) {
	if value, ok := sourceMap["value"].(string); ok {
		ts.Value = value
	}
}

// FromMap creates a FileSource from a map[string]any
func (fs *FileSource) FromMap(sourceMap map[string]any) {
	if path, ok := sourceMap["path"].(string); ok {
		fs.Path = path
	}
	if mime, ok := sourceMap["mime"].(string); ok {
		fs.Mime = mime
	}
	if data, ok := sourceMap["data"].([]byte); ok {
		fs.Data = data
	}
}

// FromMap creates a SymbolSource from a map[string]any
func (ss *SymbolSource) FromMap(sourceMap map[string]any) {
	if path, ok := sourceMap["path"].(string); ok {
		ss.Path = path
	}
	if name, ok := sourceMap["name"].(string); ok {
		ss.Name = name
	}
	if kind, ok := sourceMap["kind"].(int); ok {
		ss.Kind = kind
	}
	if rangeMap, ok := sourceMap["range"].(map[string]any); ok {
		ss.Range = SymbolRange{}
		if startMap, ok := rangeMap["start"].(map[string]any); ok {
			if line, ok := startMap["line"].(int); ok {
				ss.Range.Start.Line = line
			}
			if char, ok := startMap["char"].(int); ok {
				ss.Range.Start.Char = char
			}
		}
		if endMap, ok := rangeMap["end"].(map[string]any); ok {
			if line, ok := endMap["line"].(int); ok {
				ss.Range.End.Line = line
			}
			if char, ok := endMap["char"].(int); ok {
				ss.Range.End.Char = char
			}
		}
	}
}

// FromMap creates an AgentSource from a map[string]any
func (as *AgentSource) FromMap(sourceMap map[string]any) {
	if name, ok := sourceMap["name"].(string); ok {
		as.Name = name
	}
}

// RestoreSourceType converts a map[string]any source back to the proper type
func (a *Attachment) RestoreSourceType() {
	if a.Source == nil {
		return
	}

	// Check if Source is a map[string]any
	if sourceMap, ok := a.Source.(map[string]any); ok {
		switch a.Type {
		case "text":
			ts := &TextSource{}
			ts.FromMap(sourceMap)
			a.Source = ts
		case "file":
			fs := &FileSource{}
			fs.FromMap(sourceMap)
			a.Source = fs
		case "symbol":
			ss := &SymbolSource{}
			ss.FromMap(sourceMap)
			a.Source = ss
		case "agent":
			as := &AgentSource{}
			as.FromMap(sourceMap)
			a.Source = as
		}
	}
}