thread2md/thread/messages.go

99 lines
1.8 KiB
Go

package thread
import (
"encoding/json"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
"time"
"git.wntrmute.dev/kyle/goutils/die"
)
const timeFormat = "2006-01-02 15:04"
type Message struct {
ID string `json:"id"`
ThreadID string `json:"thread_id"`
Role string `json:"role"`
Status string `json:"status"`
Created int64 `json:"created"`
Updated int64 `json:"updated"`
Object string `json:"object"`
Content []struct {
Type string `json:"type"`
Text struct {
Value string `json:"value"`
Annotations []any `json:"annotations"`
} `json:"text"`
} `json:"content"`
}
func (m *Message) Date() time.Time {
return time.Unix(m.Created/1000, 0)
}
func (m *Message) Header() string {
role := m.Role
switch role {
case "user":
role = strings.ToTitle(os.Getenv("USER"))
case "assistant":
role = "LLM"
default:
// nothing
}
return fmt.Sprintf("[%s] **%s**\n", m.Date().Format(timeFormat), m.Role)
}
func (m *Message) Body() string {
content := []string{}
for _, contentItem := range m.Content {
// TODO: handle different content types
if contentItem.Type != "text" {
continue
}
if contentItem.Text.Annotations != nil {
log.Print("warning: annotation in content not supported")
}
content = append(content, contentItem.Text.Value)
}
return strings.Join(content, "\n\n")
}
func LoadMessages(path string) ([]*Message, error) {
messagesPath := filepath.Join(path, "messages.jsonl")
file, err := os.Open(messagesPath)
die.If(err)
defer file.Close()
jsonParser := json.NewDecoder(file)
var messages []*Message
for err == nil {
var message Message
err = jsonParser.Decode(&message)
if err == nil {
messages = append(messages, &message)
}
}
if err != io.EOF {
return nil, err
}
return messages, nil
}
func (m *Message) String() string {
return m.Header() + m.Body() + "\n"
}