74 lines
1.3 KiB
Go
74 lines
1.3 KiB
Go
package session
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
|
|
"agent-native/runtime/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()
|
|
}
|