session

package
v0.57.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 26, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package session persists agent conversation history across runs.

Sessions enable multi-turn conversations: a user runs a task, the agent responds, and the user continues the conversation with "odek continue", picking up the full message history from the previous turn.

Storage: ~/.odek/sessions/<id>.json. Each file is a full conversation transcript including system messages, user turns, assistant responses, tool calls, and tool results. Sessions are loaded by ID for continuation or by listing metadata for browsing.

The Store is intentionally minimal — it's a JSON file manager, not a database. Session struct fields are all public, so callers can mutate the session directly and call Save(). This makes advanced operations (editing, truncating, merging sessions) trivial at the CLI layer.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ValidateSessionID

func ValidateSessionID(id string) error

ValidateSessionID validates that a session ID is safe for filesystem use. Rejects empty strings, path separators, traversal patterns, and dot names.

Types

type IndexEntry

type IndexEntry struct {
	ID        string    `json:"id"`
	Title     string    `json:"title"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
	Turns     int       `json:"turns"`
}

IndexEntry holds minimal session metadata for the session index. This avoids loading every session file just to list or find the latest.

type Session

type Session struct {
	ID        string        `json:"id"`               // e.g. "20260518-abc123"
	CreatedAt time.Time     `json:"created_at"`       // first message time
	UpdatedAt time.Time     `json:"updated_at"`       // last append time
	Model     string        `json:"model"`            // model name used
	Turns     int           `json:"turns"`            // number of user turns
	Task      string        `json:"task"`             // first user message (label)
	Sandbox   bool          `json:"sandbox"`          // was sandboxed — auto-apply on resume
	Messages  []llm.Message `json:"messages"`         // full conversation history
	Buffer    []string      `json:"buffer,omitempty"` // last N turn summaries (memory tier 2)
}

Session represents a single multi-turn conversation with the agent. All fields are exported for direct manipulation at the CLI layer.

func (*Session) GetMessages

func (s *Session) GetMessages() []llm.Message

GetMessages returns the session's message slice. Nil-safe. Returns an empty (non-nil) slice for a session with no messages.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store manages session files in a directory on disk. Operations are simple file reads/writes — no locking, no caching.

func NewStore

func NewStore() (*Store, error)

NewStore creates a session store rooted at ~/.odek/sessions/. The directory is created if it doesn't exist.

func (*Store) Append

func (s *Store) Append(id string, newMsgs []llm.Message) error

Append adds new messages to an existing session, updates timestamps and turn counts, and saves the result atomically. The full read-modify-write is serialized by s.mu to prevent both concurrent-write data loss and symlink-swap TOCTOU attacks.

func (*Store) Cleanup

func (s *Store) Cleanup(before time.Time) (int, error)

Cleanup deletes all sessions whose UpdatedAt is before the given time. Returns the count of deleted sessions. Idempotent — nonexistent files are skipped silently. Uses the session index for efficient batch operations. Falls back to scanning individual session files when no index exists (backward compat).

func (*Store) Create

func (s *Store) Create(messages []llm.Message, model, task string) (*Session, error)

Create persists a new session with the given messages and metadata. It generates an ID, sets timestamps, counts user turns, and saves.

func (*Store) Delete

func (s *Store) Delete(id string) error

Delete removes a session file from disk and removes its entry from the session index. Returns nil if the file doesn't exist (idempotent delete).

func (*Store) Dir

func (s *Store) Dir() string

Dir returns the session store directory path. Exported for testing and debugging.

func (*Store) Latest

func (s *Store) Latest() (*Session, error)

Latest returns the most recently updated session, or nil if no sessions exist. Returns an error when no sessions exist. Uses the session index for O(1) lookups. Falls back to scanning individual session files when no index exists (backward compat).

func (*Store) List

func (s *Store) List(limit int) ([]Session, error)

List returns session summaries ordered by UpdatedAt descending (most recent first). limit caps the number returned (0 = all). Only metadata fields are populated — Messages is nil to keep listings lightweight. Uses the session index for O(n) reads (n = session count, but no JSON parsing per session). Falls back to loading each session file when no index exists (backward compat).

func (*Store) Load

func (s *Store) Load(id string) (*Session, error)

Load reads a session from disk by ID. Returns an error if the file doesn't exist or can't be parsed.

func (*Store) Path

func (s *Store) Path(id string) string

Path returns the absolute filesystem path for a session file. Exported for testing and debugging.

func (*Store) Save

func (s *Store) Save(sess *Session) error

Save writes a session to disk atomically using a temp-file + rename strategy. This prevents:

  • Partial writes from crashes (rename is atomic on POSIX)
  • Symlink-following TOCTOU attacks (os.Rename replaces the directory entry itself — it does NOT follow symlinks)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL