package store type Message struct { ID int64 RoomID string Agent string Role string Content string Filename string Title string GroupID *int64 CreatedAt string PartType string } type FileVersion struct { ID int64 RoomID string Filename string Content string Agent string Version int CreatedAt string } func (s *Store) InsertMessage(msg *Message) (int64, error) { s.mu.Lock() defer s.mu.Unlock() partType := msg.PartType if partType == "" { partType = "text" } res, err := s.db.Exec( `INSERT INTO messages (room_id, agent, role, content, filename, title, group_id, part_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, msg.RoomID, msg.Agent, msg.Role, msg.Content, nilIfEmpty(msg.Filename), nilIfEmpty(msg.Title), msg.GroupID, partType, ) if err != nil { return 0, err } return res.LastInsertId() } func (s *Store) GetMessages(roomID string, limit, offset int) ([]Message, error) { if limit <= 0 { limit = 200 } rows, err := s.db.Query( `SELECT id, room_id, agent, role, content, COALESCE(filename,''), COALESCE(title,''), group_id, created_at, COALESCE(part_type,'text') FROM messages WHERE room_id = ? ORDER BY created_at ASC, id ASC LIMIT ? OFFSET ?`, roomID, limit, offset, ) if err != nil { return nil, err } defer rows.Close() var msgs []Message for rows.Next() { var m Message if err := rows.Scan(&m.ID, &m.RoomID, &m.Agent, &m.Role, &m.Content, &m.Filename, &m.Title, &m.GroupID, &m.CreatedAt, &m.PartType); err != nil { return nil, err } msgs = append(msgs, m) } return msgs, nil } func (s *Store) InsertFileVersion(roomID, filename, content, agent string) (int64, error) { s.mu.Lock() defer s.mu.Unlock() // 获取当前最大版本号 var maxVer int s.db.QueryRow(`SELECT COALESCE(MAX(version), 0) FROM file_versions WHERE room_id = ? AND filename = ?`, roomID, filename).Scan(&maxVer) res, err := s.db.Exec( `INSERT INTO file_versions (room_id, filename, content, agent, version) VALUES (?, ?, ?, ?, ?)`, roomID, filename, content, agent, maxVer+1, ) if err != nil { return 0, err } return res.LastInsertId() } func (s *Store) GetFileVersions(roomID, filename string) ([]FileVersion, error) { rows, err := s.db.Query( `SELECT id, room_id, filename, content, agent, version, created_at FROM file_versions WHERE room_id = ? AND filename = ? ORDER BY version DESC`, roomID, filename, ) if err != nil { return nil, err } defer rows.Close() var versions []FileVersion for rows.Next() { var v FileVersion if err := rows.Scan(&v.ID, &v.RoomID, &v.Filename, &v.Content, &v.Agent, &v.Version, &v.CreatedAt); err != nil { return nil, err } versions = append(versions, v) } return versions, nil } func (s *Store) GetFileVersion(roomID, filename string, version int) (*FileVersion, error) { var v FileVersion err := s.db.QueryRow( `SELECT id, room_id, filename, content, agent, version, created_at FROM file_versions WHERE room_id = ? AND filename = ? AND version = ?`, roomID, filename, version, ).Scan(&v.ID, &v.RoomID, &v.Filename, &v.Content, &v.Agent, &v.Version, &v.CreatedAt) if err != nil { return nil, err } return &v, nil } func nilIfEmpty(s string) interface{} { if s == "" { return nil } return s }