agent: add SaveSession to Core interface for external persistence

- Add Backend/Model fields to PersistedSession for full restore metadata
- Add saveToFull() that includes backend/model in persisted state
- Add exported LoadPersistedSession(path) helper
- Add SaveSession(path) to Core interface, implemented on agent struct
- Existing saveTo() preserved as backward-compatible wrapper
This commit is contained in:
ollie 2026-07-14 20:41:38 +02:00
parent a50149d075
commit 451dc96d47
3 changed files with 39 additions and 1 deletions

View File

@ -709,6 +709,18 @@ func (s *agent) saveSession() {
}
}
// SaveSession writes the current session state to the given path, including
// backend and model metadata for external restore.
func (s *agent) SaveSession(path string) error {
s.mu.RLock()
defer s.mu.RUnlock()
if s.session == nil {
return fmt.Errorf("no active session")
}
return s.session.saveToFull(path, s.sessionID, s.agentName,
s.runtime.Backend.Name(), s.runtime.Backend.Model(), s.CWD())
}
func (s *agent) getActionCancel() context.CancelCauseFunc {
if a := s.currentAction.Load(); a != nil {
return a.cancel

View File

@ -37,6 +37,8 @@ Be concise. Capture what another LLM needs to seamlessly continue.`
type PersistedSession struct {
ID string `json:"id"`
Agent string `json:"agent,omitempty"`
Backend string `json:"backend,omitempty"`
Model string `json:"model,omitempty"`
CWD string `json:"cwd,omitempty"`
Messages []backend.Message `json:"messages"`
TaskState *TaskState `json:"taskState,omitempty"`
@ -81,11 +83,18 @@ func (ts *TaskState) render() string {
return sb.String()
}
// SaveTo writes the full message history to path as JSON.
// saveTo writes the full message history to path as JSON.
func (s *Session) saveTo(path, id, agentName, cwd string) error {
return s.saveToFull(path, id, agentName, "", "", cwd)
}
// saveToFull writes session state including backend/model info.
func (s *Session) saveToFull(path, id, agentName, backendName, modelName, cwd string) error {
ps := PersistedSession{
ID: id,
Agent: agentName,
Backend: backendName,
Model: modelName,
CWD: cwd,
Messages: s.messages,
TaskState: s.TaskState,
@ -97,6 +106,19 @@ func (s *Session) saveTo(path, id, agentName, cwd string) error {
return os.WriteFile(path, data, 0600)
}
// LoadPersistedSession reads a PersistedSession from a JSON file.
func LoadPersistedSession(path string) (*PersistedSession, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var ps PersistedSession
if err := json.Unmarshal(data, &ps); err != nil {
return nil, fmt.Errorf("parse session %s: %w", path, err)
}
return &ps, nil
}
// RestoreSession reconstructs a Session from a persisted message list.
func RestoreSession(messages []backend.Message) *Session {
s := &Session{messages: messages}

View File

@ -139,6 +139,10 @@ type Core interface {
// [ $(($(cat tcct) % 10)) -eq 0 ] && ...
ToolCallCount() int64
// SaveSession writes the current session state to the given path.
// The file includes all messages, agent/backend/model metadata, and task state.
SaveSession(path string) error
// Close releases resources associated with the session, including its
// temporary directory under /tmp/ollie/.
Close()