package session import ( "bufio" "encoding/json" "os" "path/filepath" "sync" "chat-agent-system/internal/agentx/llm" ) // Store is an append-only JSONL transcript. Each line is one llm.Message. type Store struct { path string mu sync.Mutex } func Open(path string) (*Store, error) { if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return nil, err } f, err := os.OpenFile(path, os.O_CREATE, 0o644) if err != nil { return nil, err } _ = f.Close() return &Store{path: path}, nil } func (s *Store) Path() string { return s.path } func (s *Store) Append(msg llm.Message) error { s.mu.Lock() defer s.mu.Unlock() raw, err := json.Marshal(msg) if err != nil { return err } f, err := os.OpenFile(s.path, os.O_APPEND|os.O_WRONLY, 0o644) if err != nil { return err } defer f.Close() raw = append(raw, '\n') _, err = f.Write(raw) return err } func (s *Store) Load() ([]llm.Message, error) { s.mu.Lock() defer s.mu.Unlock() f, err := os.Open(s.path) if err != nil { return nil, err } defer f.Close() var out []llm.Message sc := bufio.NewScanner(f) sc.Buffer(make([]byte, 0, 64*1024), 8*1024*1024) for sc.Scan() { line := sc.Bytes() if len(line) == 0 { continue } var msg llm.Message if err := json.Unmarshal(line, &msg); err != nil { return nil, err } out = append(out, msg) } return out, sc.Err() }