chore: initial commit

This commit is contained in:
whlaoding
2026-02-21 23:01:39 +08:00
commit c2bebb3457
21 changed files with 1913 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
package memory
import "strings"
func CompressForPrompt(messages []Message, maxChars int) string {
if maxChars <= 0 {
maxChars = 8000
}
builder := strings.Builder{}
for _, msg := range messages {
line := msg.Role + ": " + msg.Content + "\n"
if builder.Len()+len(line) > maxChars {
break
}
builder.WriteString(line)
}
return builder.String()
}

View File

@@ -0,0 +1,132 @@
package memory
import (
"database/sql"
"fmt"
"os"
"path/filepath"
"time"
"laodingbot/internal/logger"
_ "modernc.org/sqlite"
)
type Message struct {
ID int64
ChatID string
UserID string
Role string
Content string
CreatedAt time.Time
}
type SQLiteStore struct {
db *sql.DB
log *logger.Logger
}
func NewSQLiteStore(path string, log *logger.Logger) (*SQLiteStore, error) {
abs, err := filepath.Abs(path)
if err != nil {
return nil, err
}
if err := os.MkdirAll(filepath.Dir(abs), 0o755); err != nil {
return nil, err
}
db, err := sql.Open("sqlite", abs)
if err != nil {
return nil, err
}
store := &SQLiteStore{db: db, log: log}
if err := store.migrate(); err != nil {
_ = db.Close()
return nil, err
}
if log != nil {
log.Infof("sqlite store initialized path=%s", abs)
}
return store, nil
}
func (s *SQLiteStore) Close() error {
return s.db.Close()
}
func (s *SQLiteStore) SaveMessage(chatID, userID, role, content string) error {
if s.log != nil {
s.log.Debugf("save message chat_id=%s role=%s content_len=%d", chatID, role, len(content))
}
_, err := s.db.Exec(`
INSERT INTO messages(chat_id, user_id, role, content, created_at)
VALUES (?, ?, ?, ?, ?)
`, chatID, userID, role, content, time.Now().UTC())
if err != nil && s.log != nil {
s.log.Errorf("save message failed chat_id=%s role=%s err=%v", chatID, role, err)
}
return err
}
func (s *SQLiteStore) LoadRecent(chatID string, limit int) ([]Message, error) {
if limit <= 0 {
limit = 20
}
rows, err := s.db.Query(`
SELECT id, chat_id, user_id, role, content, created_at
FROM messages
WHERE chat_id = ?
ORDER BY id DESC
LIMIT ?
`, chatID, limit)
if err != nil {
if s.log != nil {
s.log.Errorf("load recent query failed chat_id=%s err=%v", chatID, err)
}
return nil, err
}
defer rows.Close()
messages := make([]Message, 0, limit)
for rows.Next() {
var m Message
if err := rows.Scan(&m.ID, &m.ChatID, &m.UserID, &m.Role, &m.Content, &m.CreatedAt); err != nil {
return nil, err
}
messages = append(messages, m)
}
if err := rows.Err(); err != nil {
if s.log != nil {
s.log.Errorf("load recent row iteration failed chat_id=%s err=%v", chatID, err)
}
return nil, err
}
for left, right := 0, len(messages)-1; left < right; left, right = left+1, right-1 {
messages[left], messages[right] = messages[right], messages[left]
}
if s.log != nil {
s.log.Debugf("load recent success chat_id=%s count=%d", chatID, len(messages))
}
return messages, nil
}
func (s *SQLiteStore) migrate() error {
stmt := `
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
chat_id TEXT NOT NULL,
user_id TEXT NOT NULL,
role TEXT NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_messages_chat_id_id ON messages(chat_id, id);
`
if _, err := s.db.Exec(stmt); err != nil {
return fmt.Errorf("migrate schema: %w", err)
}
if s.log != nil {
s.log.Infof("sqlite schema migration completed")
}
return nil
}