diff options
| author | Kujtim Hoxha <[email protected]> | 2025-04-03 15:20:15 +0200 |
|---|---|---|
| committer | Kujtim Hoxha <[email protected]> | 2025-04-03 17:23:41 +0200 |
| commit | cfdd687216799cb5b47f099f1e7cd5dd16b3bdd0 (patch) | |
| tree | a822bfde1463a7080c0ea06dd17796d7a1617d3d /internal/message/content.go | |
| parent | afd9ad0560d76c2a6d161dad52553b10ff428905 (diff) | |
| download | opencode-cfdd687216799cb5b47f099f1e7cd5dd16b3bdd0.tar.gz opencode-cfdd687216799cb5b47f099f1e7cd5dd16b3bdd0.zip | |
add initial lsp support
Diffstat (limited to 'internal/message/content.go')
| -rw-r--r-- | internal/message/content.go | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/internal/message/content.go b/internal/message/content.go new file mode 100644 index 000000000..2604cd68a --- /dev/null +++ b/internal/message/content.go @@ -0,0 +1,244 @@ +package message + +import ( + "encoding/base64" +) + +type MessageRole string + +const ( + Assistant MessageRole = "assistant" + User MessageRole = "user" + System MessageRole = "system" + Tool MessageRole = "tool" +) + +type ContentPart interface { + isPart() +} + +type ReasoningContent struct { + Thinking string `json:"thinking"` +} + +func (tc ReasoningContent) String() string { + return tc.Thinking +} +func (ReasoningContent) isPart() {} + +type TextContent struct { + Text string `json:"text"` +} + +func (tc TextContent) String() string { + return tc.Text +} + +func (TextContent) isPart() {} + +type ImageURLContent struct { + URL string `json:"url"` + Detail string `json:"detail,omitempty"` +} + +func (iuc ImageURLContent) String() string { + return iuc.URL +} + +func (ImageURLContent) isPart() {} + +type BinaryContent struct { + MIMEType string + Data []byte +} + +func (bc BinaryContent) String() string { + base64Encoded := base64.StdEncoding.EncodeToString(bc.Data) + return "data:" + bc.MIMEType + ";base64," + base64Encoded +} + +func (BinaryContent) isPart() {} + +type ToolCall struct { + ID string `json:"id"` + Name string `json:"name"` + Input string `json:"input"` + Type string `json:"type"` + Finished bool `json:"finished"` +} + +func (ToolCall) isPart() {} + +type ToolResult struct { + ToolCallID string `json:"tool_call_id"` + Name string `json:"name"` + Content string `json:"content"` + IsError bool `json:"is_error"` +} + +func (ToolResult) isPart() {} + +type Finish struct { + Reason string `json:"reason"` +} + +func (Finish) isPart() {} + +type Message struct { + ID string + Role MessageRole + SessionID string + Parts []ContentPart + + CreatedAt int64 + UpdatedAt int64 +} + +func (m *Message) Content() TextContent { + for _, part := range m.Parts { + if c, ok := part.(TextContent); ok { + return c + } + } + return TextContent{} +} + +func (m *Message) ReasoningContent() ReasoningContent { + for _, part := range m.Parts { + if c, ok := part.(ReasoningContent); ok { + return c + } + } + return ReasoningContent{} +} + +func (m *Message) ImageURLContent() []ImageURLContent { + imageURLContents := make([]ImageURLContent, 0) + for _, part := range m.Parts { + if c, ok := part.(ImageURLContent); ok { + imageURLContents = append(imageURLContents, c) + } + } + return imageURLContents +} + +func (m *Message) BinaryContent() []BinaryContent { + binaryContents := make([]BinaryContent, 0) + for _, part := range m.Parts { + if c, ok := part.(BinaryContent); ok { + binaryContents = append(binaryContents, c) + } + } + return binaryContents +} + +func (m *Message) ToolCalls() []ToolCall { + toolCalls := make([]ToolCall, 0) + for _, part := range m.Parts { + if c, ok := part.(ToolCall); ok { + toolCalls = append(toolCalls, c) + } + } + return toolCalls +} + +func (m *Message) ToolResults() []ToolResult { + toolResults := make([]ToolResult, 0) + for _, part := range m.Parts { + if c, ok := part.(ToolResult); ok { + toolResults = append(toolResults, c) + } + } + return toolResults +} + +func (m *Message) IsFinished() bool { + for _, part := range m.Parts { + if _, ok := part.(Finish); ok { + return true + } + } + return false +} + +func (m *Message) FinishReason() string { + for _, part := range m.Parts { + if c, ok := part.(Finish); ok { + return c.Reason + } + } + return "" +} + +func (m *Message) IsThinking() bool { + if m.ReasoningContent().Thinking != "" && m.Content().Text == "" && !m.IsFinished() { + return true + } + return false +} + +func (m *Message) AppendContent(delta string) { + found := false + for i, part := range m.Parts { + if c, ok := part.(TextContent); ok { + m.Parts[i] = TextContent{Text: c.Text + delta} + found = true + } + } + if !found { + m.Parts = append(m.Parts, TextContent{Text: delta}) + } +} + +func (m *Message) AppendReasoningContent(delta string) { + found := false + for i, part := range m.Parts { + if c, ok := part.(ReasoningContent); ok { + m.Parts[i] = ReasoningContent{Thinking: c.Thinking + delta} + found = true + } + } + if !found { + m.Parts = append(m.Parts, ReasoningContent{Thinking: delta}) + } +} + +func (m *Message) AddToolCall(tc ToolCall) { + for i, part := range m.Parts { + if c, ok := part.(ToolCall); ok { + if c.ID == tc.ID { + m.Parts[i] = tc + return + } + } + } + m.Parts = append(m.Parts, tc) +} + +func (m *Message) SetToolCalls(tc []ToolCall) { + for _, toolCall := range tc { + m.Parts = append(m.Parts, toolCall) + } +} + +func (m *Message) AddToolResult(tr ToolResult) { + m.Parts = append(m.Parts, tr) +} + +func (m *Message) SetToolResults(tr []ToolResult) { + for _, toolResult := range tr { + m.Parts = append(m.Parts, toolResult) + } +} + +func (m *Message) AddFinish(reason string) { + m.Parts = append(m.Parts, Finish{Reason: reason}) +} + +func (m *Message) AddImageURL(url, detail string) { + m.Parts = append(m.Parts, ImageURLContent{URL: url, Detail: detail}) +} + +func (m *Message) AddBinary(mimeType string, data []byte) { + m.Parts = append(m.Parts, BinaryContent{MIMEType: mimeType, Data: data}) +} |
