storage

package
v0.181.0 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrJobNotFound = errors.New("scheduled job not found")

ErrJobNotFound is returned by ScheduledJobStorage when a job ID is not found.

Functions

This section is empty.

Types

type ConversationStorage

type ConversationStorage interface {
	// SaveConversation saves a conversation with a unique ID
	SaveConversation(ctx context.Context, conversationID string, entries []convdomain.ConversationEntry, metadata convdomain.ConversationMetadata) error

	// LoadConversation loads a conversation by its ID
	LoadConversation(ctx context.Context, conversationID string) ([]convdomain.ConversationEntry, convdomain.ConversationMetadata, error)

	// ListConversations returns a list of conversation summaries
	ListConversations(ctx context.Context, limit, offset int) ([]convdomain.ConversationSummary, error)

	// DeleteConversation removes a conversation by its ID
	DeleteConversation(ctx context.Context, conversationID string) error

	// UpdateConversationMetadata updates metadata for a conversation
	UpdateConversationMetadata(ctx context.Context, conversationID string, metadata convdomain.ConversationMetadata) error

	// ListConversationsNeedingTitles returns conversations that need title generation
	ListConversationsNeedingTitles(ctx context.Context, limit int) ([]convdomain.ConversationSummary, error)

	// Close closes the storage connection
	Close() error

	// Health checks if the storage is healthy and reachable
	Health(ctx context.Context) error
}

ConversationStorage defines the interface for persistent conversation storage

type D1Config

type D1Config struct {
	AccountID  string `json:"account_id" yaml:"account_id"`
	DatabaseID string `json:"database_id" yaml:"database_id"`
	APIToken   string `json:"api_token" yaml:"api_token"`
	BaseURL    string `json:"base_url,omitempty" yaml:"base_url,omitempty"`
}

D1Config contains Cloudflare D1-specific configuration. D1 is SQLite exposed over an HTTP query API, so the driver writes the same schema as SQLite but over the network instead of a local file handle.

type D1Storage

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

D1Storage implements ConversationStorage and SessionGroupStorage on top of Cloudflare D1. D1 is SQLite exposed over an HTTP query API, so this driver issues the exact same SQL as SQLiteStorage but ships it over the network via POST /accounts/{account}/d1/database/{database}/query instead of a local file handle. Timestamps are stored as UTC RFC3339 strings so ORDER BY sorts chronologically regardless of the runner's timezone and external readers get unambiguous ISO-8601 values.

func NewD1Storage

func NewD1Storage(config D1Config) (*D1Storage, error)

NewD1Storage creates a new Cloudflare D1 storage instance and ensures the schema exists (idempotent CREATE ... IF NOT EXISTS, byte-for-byte identical to the SQLite migrations).

func (*D1Storage) AppendHistory

func (s *D1Storage) AppendHistory(ctx context.Context, command string) error

AppendHistory appends a command to the shell history.

func (*D1Storage) Close

func (s *D1Storage) Close() error

Close releases resources. D1 holds no persistent connection, so this is a no-op.

func (*D1Storage) DeleteConversation

func (s *D1Storage) DeleteConversation(ctx context.Context, conversationID string) error

DeleteConversation removes a conversation by its ID.

func (*D1Storage) DeleteJob

func (s *D1Storage) DeleteJob(ctx context.Context, id string) error

DeleteJob removes a job by ID.

func (*D1Storage) DeletePlan

func (s *D1Storage) DeletePlan(ctx context.Context, id string) error

DeletePlan removes a plan by ID.

func (*D1Storage) GetSessionGroup

func (s *D1Storage) GetSessionGroup(ctx context.Context, groupKey string) (SessionGroupEntry, bool, error)

GetSessionGroup returns the entry for groupKey or (_, false, nil) if missing.

func (*D1Storage) Health

func (s *D1Storage) Health(ctx context.Context) error

Health checks that the D1 database is reachable and answering queries.

func (*D1Storage) ListConversations

func (s *D1Storage) ListConversations(ctx context.Context, limit, offset int) ([]convdomain.ConversationSummary, error)

ListConversations returns a list of conversation summaries (lean: no models/tags/title fields).

func (*D1Storage) ListConversationsNeedingTitles

func (s *D1Storage) ListConversationsNeedingTitles(ctx context.Context, limit int) ([]convdomain.ConversationSummary, error)

ListConversationsNeedingTitles returns conversations that need title generation. It carries Model/Tags/TitleGenerated/TitleInvalidated/TitleGenerationTime (the title-generation batch path needs them) and therefore uses a dedicated mapper rather than the lean ListConversations one.

func (*D1Storage) ListJobs

func (s *D1Storage) ListJobs(ctx context.Context) ([]*scheddomain.ScheduledJob, error)

ListJobs returns all jobs sorted by CreatedAt ascending.

func (*D1Storage) ListPlans

func (s *D1Storage) ListPlans(ctx context.Context) ([]*PlanRecord, error)

ListPlans returns all plans sorted by CreatedAt descending.

func (*D1Storage) ListRuns

func (s *D1Storage) ListRuns(ctx context.Context, jobID string) ([]*scheddomain.RunRecord, error)

ListRuns returns run records sorted by StartedAt descending.

func (*D1Storage) ListSessionGroups

func (s *D1Storage) ListSessionGroups(ctx context.Context) (map[string]SessionGroupEntry, error)

ListSessionGroups returns all session-group entries.

func (*D1Storage) LoadConversation

func (s *D1Storage) LoadConversation(ctx context.Context, conversationID string) ([]convdomain.ConversationEntry, convdomain.ConversationMetadata, error)

LoadConversation loads a conversation by its ID using the simplified schema.

func (*D1Storage) LoadHistory

func (s *D1Storage) LoadHistory(ctx context.Context, limit int) ([]string, error)

LoadHistory returns the most recent commands up to limit in chronological order; limit <= 0 returns everything.

func (*D1Storage) LoadJob

func (s *D1Storage) LoadJob(ctx context.Context, id string) (*scheddomain.ScheduledJob, error)

LoadJob returns a job by ID.

func (*D1Storage) LoadPlan

func (s *D1Storage) LoadPlan(ctx context.Context, id string) (*PlanRecord, error)

LoadPlan returns a plan by ID.

func (*D1Storage) PruneRuns

func (s *D1Storage) PruneRuns(ctx context.Context, keep int) error

PruneRuns deletes all but the newest keep run records.

func (*D1Storage) PutSessionGroup

func (s *D1Storage) PutSessionGroup(ctx context.Context, groupKey string, entry SessionGroupEntry) error

PutSessionGroup creates or replaces the entry for groupKey via UPSERT.

func (*D1Storage) SaveConversation

func (s *D1Storage) SaveConversation(ctx context.Context, conversationID string, entries []convdomain.ConversationEntry, metadata convdomain.ConversationMetadata) error

SaveConversation saves a conversation with its entries using the simplified schema.

func (*D1Storage) SaveJob

func (s *D1Storage) SaveJob(ctx context.Context, job *scheddomain.ScheduledJob) error

SaveJob creates or updates a scheduled job via UPSERT.

func (*D1Storage) SavePlan

func (s *D1Storage) SavePlan(ctx context.Context, plan *PlanRecord) error

SavePlan creates a plan record via UPSERT.

func (*D1Storage) SaveRun

func (s *D1Storage) SaveRun(ctx context.Context, run *scheddomain.RunRecord) error

SaveRun creates or updates a run record via UPSERT.

func (*D1Storage) UpdateConversationMetadata

func (s *D1Storage) UpdateConversationMetadata(ctx context.Context, conversationID string, metadata convdomain.ConversationMetadata) error

UpdateConversationMetadata updates metadata for a conversation.

type EntryLine

type EntryLine struct {
	Type  string                       `json:"type"`
	Index int                          `json:"index"`
	Entry convdomain.ConversationEntry `json:"entry"`
}

EntryLine represents an entry line in v2 format

type JsonlStorage

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

JsonlStorage implements ConversationStorage using JSONL files

func NewJsonlStorage

func NewJsonlStorage(config JsonlStorageConfig) (*JsonlStorage, error)

NewJsonlStorage creates a new JSONL storage instance

func (*JsonlStorage) AppendHistory

func (s *JsonlStorage) AppendHistory(_ context.Context, command string) error

AppendHistory appends a command to the shell history file.

func (*JsonlStorage) Close

func (s *JsonlStorage) Close() error

Close closes the storage (no-op for JSONL)

func (*JsonlStorage) DeleteConversation

func (s *JsonlStorage) DeleteConversation(ctx context.Context, conversationID string) error

DeleteConversation removes a conversation file

func (*JsonlStorage) DeleteJob

func (s *JsonlStorage) DeleteJob(_ context.Context, id string) error

DeleteJob removes a job by ID. Returns ErrJobNotFound if it did not exist.

func (*JsonlStorage) DeletePlan

func (s *JsonlStorage) DeletePlan(_ context.Context, id string) error

DeletePlan removes a plan by ID.

func (*JsonlStorage) GetSessionGroup

func (s *JsonlStorage) GetSessionGroup(_ context.Context, groupKey string) (SessionGroupEntry, bool, error)

GetSessionGroup returns the entry for groupKey, or (_, false, nil) if missing.

func (*JsonlStorage) Health

func (s *JsonlStorage) Health(ctx context.Context) error

Health checks if the storage is accessible

func (*JsonlStorage) ListConversations

func (s *JsonlStorage) ListConversations(ctx context.Context, limit, offset int) ([]convdomain.ConversationSummary, error)

ListConversations returns a list of conversation summaries

func (*JsonlStorage) ListConversationsNeedingTitles

func (s *JsonlStorage) ListConversationsNeedingTitles(ctx context.Context, limit int) ([]convdomain.ConversationSummary, error)

ListConversationsNeedingTitles returns conversations that need title generation

func (*JsonlStorage) ListJobs

ListJobs returns all jobs sorted by CreatedAt ascending.

func (*JsonlStorage) ListPlans

func (s *JsonlStorage) ListPlans(_ context.Context) ([]*PlanRecord, error)

ListPlans returns all plans sorted by CreatedAt descending.

func (*JsonlStorage) ListRuns

func (s *JsonlStorage) ListRuns(_ context.Context, jobID string) ([]*scheddomain.RunRecord, error)

ListRuns returns run records sorted by StartedAt descending.

func (*JsonlStorage) ListSessionGroups

func (s *JsonlStorage) ListSessionGroups(_ context.Context) (map[string]SessionGroupEntry, error)

ListSessionGroups returns all entries from the on-disk index.

func (*JsonlStorage) LoadConversation

func (s *JsonlStorage) LoadConversation(ctx context.Context, conversationID string) ([]convdomain.ConversationEntry, convdomain.ConversationMetadata, error)

LoadConversation loads a conversation from a JSONL file Supports both v1 format (2-line: metadata + entries array) and v2 format (entry lines + trailing metadata, append-only)

func (*JsonlStorage) LoadHistory

func (s *JsonlStorage) LoadHistory(_ context.Context, limit int) ([]string, error)

LoadHistory returns the most recent commands up to limit.

func (*JsonlStorage) LoadJob

LoadJob reads a single job by ID. Returns ErrJobNotFound if the file does not exist.

func (*JsonlStorage) LoadPlan

func (s *JsonlStorage) LoadPlan(_ context.Context, id string) (*PlanRecord, error)

LoadPlan returns a plan by ID. For JSONL, the ID is the filename stem.

func (*JsonlStorage) PruneRuns

func (s *JsonlStorage) PruneRuns(ctx context.Context, keep int) error

PruneRuns deletes all but the newest keep run records.

func (*JsonlStorage) PutSessionGroup

func (s *JsonlStorage) PutSessionGroup(_ context.Context, groupKey string, entry SessionGroupEntry) error

PutSessionGroup creates or replaces the entry for groupKey using an atomic temp-file + rename so concurrent agent subprocesses don't see a partially written file.

func (*JsonlStorage) SaveConversation

func (s *JsonlStorage) SaveConversation(ctx context.Context, conversationID string, entries []convdomain.ConversationEntry, metadata convdomain.ConversationMetadata) error

SaveConversation saves a conversation to a JSONL file

func (*JsonlStorage) SaveJob

SaveJob writes the job to disk atomically as YAML.

func (*JsonlStorage) SavePlan

func (s *JsonlStorage) SavePlan(_ context.Context, plan *PlanRecord) error

SavePlan writes the plan as a markdown file named after the plan ID.

func (*JsonlStorage) SaveRun

func (s *JsonlStorage) SaveRun(_ context.Context, run *scheddomain.RunRecord) error

SaveRun writes the run record to disk atomically as YAML.

func (*JsonlStorage) UpdateConversationMetadata

func (s *JsonlStorage) UpdateConversationMetadata(ctx context.Context, conversationID string, metadata convdomain.ConversationMetadata) error

UpdateConversationMetadata updates only the metadata of a conversation For both v1 and v2 formats, this requires a full rewrite of the file (v2 format is used for the output regardless of input format)

type JsonlStorageConfig

type JsonlStorageConfig struct {
	Path string `json:"path" yaml:"path"`
	// PlansPath is the directory plan markdown files are stored in. When
	// empty, plans land next to the conversations directory (dir(Path)/plans).
	PlansPath string `json:"plans_path,omitempty" yaml:"plans_path,omitempty"`
}

JsonlStorageConfig contains JSONL-specific configuration

type MemoryStorage

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

MemoryStorage implements ConversationStorage using in-memory storage This allows conversation history features to work without persistent storage

func NewMemoryStorage

func NewMemoryStorage() *MemoryStorage

NewMemoryStorage creates a new in-memory storage instance

func (*MemoryStorage) AppendHistory

func (m *MemoryStorage) AppendHistory(ctx context.Context, command string) error

AppendHistory appends a command to the shell history.

func (*MemoryStorage) Close

func (m *MemoryStorage) Close() error

Close closes the storage connection (no-op for memory storage)

func (*MemoryStorage) DeleteConversation

func (m *MemoryStorage) DeleteConversation(ctx context.Context, conversationID string) error

DeleteConversation removes a conversation by its ID

func (*MemoryStorage) DeleteJob

func (m *MemoryStorage) DeleteJob(ctx context.Context, id string) error

DeleteJob removes a job by ID.

func (*MemoryStorage) DeletePlan

func (m *MemoryStorage) DeletePlan(ctx context.Context, id string) error

DeletePlan removes a plan by ID.

func (*MemoryStorage) GetSessionGroup

func (m *MemoryStorage) GetSessionGroup(_ context.Context, groupKey string) (SessionGroupEntry, bool, error)

GetSessionGroup returns the entry for groupKey or (_, false, nil) if missing.

func (*MemoryStorage) Health

func (m *MemoryStorage) Health(ctx context.Context) error

Health checks if the storage is healthy and reachable

func (*MemoryStorage) ListConversations

func (m *MemoryStorage) ListConversations(ctx context.Context, limit, offset int) ([]convdomain.ConversationSummary, error)

ListConversations returns a list of conversation summaries

func (*MemoryStorage) ListConversationsNeedingTitles

func (m *MemoryStorage) ListConversationsNeedingTitles(ctx context.Context, limit int) ([]convdomain.ConversationSummary, error)

ListConversationsNeedingTitles returns conversations that need title generation

func (*MemoryStorage) ListJobs

func (m *MemoryStorage) ListJobs(ctx context.Context) ([]*scheddomain.ScheduledJob, error)

ListJobs returns copies of all jobs sorted by CreatedAt ascending.

func (*MemoryStorage) ListPlans

func (m *MemoryStorage) ListPlans(ctx context.Context) ([]*PlanRecord, error)

ListPlans returns copies of all plans sorted by CreatedAt descending.

func (*MemoryStorage) ListRuns

func (m *MemoryStorage) ListRuns(ctx context.Context, jobID string) ([]*scheddomain.RunRecord, error)

ListRuns returns copies of run records sorted by StartedAt descending.

func (*MemoryStorage) ListSessionGroups

func (m *MemoryStorage) ListSessionGroups(_ context.Context) (map[string]SessionGroupEntry, error)

ListSessionGroups returns a copy of all session-group entries.

func (*MemoryStorage) LoadConversation

func (m *MemoryStorage) LoadConversation(ctx context.Context, conversationID string) ([]convdomain.ConversationEntry, convdomain.ConversationMetadata, error)

LoadConversation loads a conversation by its ID

func (*MemoryStorage) LoadHistory

func (m *MemoryStorage) LoadHistory(ctx context.Context, limit int) ([]string, error)

LoadHistory returns the most recent commands up to limit.

func (*MemoryStorage) LoadJob

LoadJob returns a copy of a job by ID, so callers can't mutate stored state.

func (*MemoryStorage) LoadPlan

func (m *MemoryStorage) LoadPlan(ctx context.Context, id string) (*PlanRecord, error)

LoadPlan returns a copy of a plan by ID.

func (*MemoryStorage) PruneRuns

func (m *MemoryStorage) PruneRuns(ctx context.Context, keep int) error

PruneRuns deletes all but the newest keep run records.

func (*MemoryStorage) PutSessionGroup

func (m *MemoryStorage) PutSessionGroup(_ context.Context, groupKey string, entry SessionGroupEntry) error

PutSessionGroup creates or replaces the entry for groupKey.

func (*MemoryStorage) SaveConversation

func (m *MemoryStorage) SaveConversation(ctx context.Context, conversationID string, entries []convdomain.ConversationEntry, metadata convdomain.ConversationMetadata) error

SaveConversation saves a conversation with a unique ID

func (*MemoryStorage) SaveJob

SaveJob creates or updates a scheduled job.

func (*MemoryStorage) SavePlan

func (m *MemoryStorage) SavePlan(ctx context.Context, plan *PlanRecord) error

SavePlan creates a plan record.

func (*MemoryStorage) SaveRun

func (m *MemoryStorage) SaveRun(ctx context.Context, run *scheddomain.RunRecord) error

SaveRun creates or updates a run record.

func (*MemoryStorage) UpdateConversationMetadata

func (m *MemoryStorage) UpdateConversationMetadata(ctx context.Context, conversationID string, metadata convdomain.ConversationMetadata) error

UpdateConversationMetadata updates metadata for a conversation

type MetadataLine

type MetadataLine struct {
	Version  int                             `json:"v"`
	Type     string                          `json:"type"`
	Metadata convdomain.ConversationMetadata `json:"metadata"`
}

MetadataLine represents the first line in v2 format

type PlanRecord

type PlanRecord struct {
	ID        string    `json:"id" yaml:"id"`
	Title     string    `json:"title" yaml:"title"`
	Body      string    `json:"body" yaml:"body"`
	CreatedAt time.Time `json:"created_at" yaml:"created_at"`
}

PlanRecord is a stored plan-mode plan. The ID is the filename stem "<UTC stamp>-<slug>" (e.g. "2026-07-17-153000-add-auth"), identical across backends, and Body is the raw plan markdown without the title H1.

type PlanStorage

type PlanStorage interface {
	// SavePlan creates or replaces a plan record. The ID must be set by the caller.
	SavePlan(ctx context.Context, plan *PlanRecord) error

	// LoadPlan returns a plan by ID. Returns an error when the plan does not exist.
	LoadPlan(ctx context.Context, id string) (*PlanRecord, error)

	// ListPlans returns all plans sorted by CreatedAt descending.
	ListPlans(ctx context.Context) ([]*PlanRecord, error)

	// DeletePlan removes a plan by ID. Returns an error when the plan does not exist.
	DeletePlan(ctx context.Context, id string) error
}

PlanStorage defines the interface for persisting plan-mode plans.

type PostgresConfig

type PostgresConfig struct {
	Host     string `json:"host" yaml:"host"`
	Port     int    `json:"port" yaml:"port"`
	Database string `json:"database" yaml:"database"`
	Username string `json:"username" yaml:"username"`
	Password string `json:"password" yaml:"password"`
	SSLMode  string `json:"ssl_mode" yaml:"ssl_mode"`
}

PostgresConfig contains Postgres-specific configuration

type PostgresStorage

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

PostgresStorage implements ConversationStorage on top of the shared sqlStore core. It speaks the same single-table schema as SQLite/D1 (see #839); only the placeholder style differs, which sqlStore.rebind normalizes.

func NewPostgresStorage

func NewPostgresStorage(config PostgresConfig) (*PostgresStorage, error)

NewPostgresStorage creates a new PostgreSQL storage instance

func (PostgresStorage) AppendHistory

func (s PostgresStorage) AppendHistory(ctx context.Context, command string) error

AppendHistory appends a command to the shell history log.

func (PostgresStorage) Close

func (s PostgresStorage) Close() error

Close closes the database connection.

func (PostgresStorage) DB

func (s PostgresStorage) DB() *sql.DB

DB returns the underlying database connection.

func (PostgresStorage) DeleteConversation

func (s PostgresStorage) DeleteConversation(ctx context.Context, conversationID string) error

DeleteConversation removes a conversation by its ID.

func (PostgresStorage) DeleteJob

func (s PostgresStorage) DeleteJob(ctx context.Context, id string) error

DeleteJob removes a job by ID. Returns ErrJobNotFound when the job does not exist.

func (PostgresStorage) DeletePlan

func (s PostgresStorage) DeletePlan(ctx context.Context, id string) error

DeletePlan removes a plan by ID.

func (PostgresStorage) GetSessionGroup

func (s PostgresStorage) GetSessionGroup(ctx context.Context, groupKey string) (SessionGroupEntry, bool, error)

GetSessionGroup returns the entry for groupKey or (_, false, nil) if missing.

func (PostgresStorage) Health

func (s PostgresStorage) Health(ctx context.Context) error

Health checks if the database is reachable and functional.

func (PostgresStorage) ListConversations

func (s PostgresStorage) ListConversations(ctx context.Context, limit, offset int) ([]convdomain.ConversationSummary, error)

ListConversations returns a list of conversation summaries.

func (PostgresStorage) ListConversationsNeedingTitles

func (s PostgresStorage) ListConversationsNeedingTitles(ctx context.Context, limit int) ([]convdomain.ConversationSummary, error)

ListConversationsNeedingTitles returns conversations that need title generation.

func (PostgresStorage) ListJobs

func (s PostgresStorage) ListJobs(ctx context.Context) ([]*scheddomain.ScheduledJob, error)

ListJobs returns all jobs sorted by CreatedAt ascending.

func (PostgresStorage) ListPlans

func (s PostgresStorage) ListPlans(ctx context.Context) ([]*PlanRecord, error)

ListPlans returns all plans sorted by CreatedAt descending.

func (PostgresStorage) ListRuns

func (s PostgresStorage) ListRuns(ctx context.Context, jobID string) ([]*scheddomain.RunRecord, error)

ListRuns returns run records sorted by StartedAt descending.

func (PostgresStorage) ListSessionGroups

func (s PostgresStorage) ListSessionGroups(ctx context.Context) (map[string]SessionGroupEntry, error)

ListSessionGroups returns all session-group entries.

func (PostgresStorage) LoadConversation

func (s PostgresStorage) LoadConversation(ctx context.Context, conversationID string) ([]convdomain.ConversationEntry, convdomain.ConversationMetadata, error)

LoadConversation loads a conversation by its ID.

func (PostgresStorage) LoadHistory

func (s PostgresStorage) LoadHistory(ctx context.Context, limit int) ([]string, error)

LoadHistory returns the most recent commands up to limit in chronological order; limit <= 0 returns everything.

func (PostgresStorage) LoadJob

func (s PostgresStorage) LoadJob(ctx context.Context, id string) (*scheddomain.ScheduledJob, error)

LoadJob returns a job by ID. Returns ErrJobNotFound when the job does not exist.

func (PostgresStorage) LoadPlan

func (s PostgresStorage) LoadPlan(ctx context.Context, id string) (*PlanRecord, error)

LoadPlan returns a plan by ID.

func (PostgresStorage) PruneRuns

func (s PostgresStorage) PruneRuns(ctx context.Context, keep int) error

PruneRuns deletes all but the newest keep run records.

func (PostgresStorage) PutSessionGroup

func (s PostgresStorage) PutSessionGroup(ctx context.Context, groupKey string, entry SessionGroupEntry) error

PutSessionGroup creates or replaces the entry for groupKey via UPSERT.

func (PostgresStorage) SaveConversation

func (s PostgresStorage) SaveConversation(ctx context.Context, conversationID string, entries []convdomain.ConversationEntry, metadata convdomain.ConversationMetadata) error

SaveConversation saves a conversation with its entries using the single-table schema (messages are stored as an embedded JSON blob).

func (PostgresStorage) SaveJob

func (s PostgresStorage) SaveJob(ctx context.Context, job *scheddomain.ScheduledJob) error

SaveJob creates or updates a scheduled job via UPSERT.

func (PostgresStorage) SavePlan

func (s PostgresStorage) SavePlan(ctx context.Context, plan *PlanRecord) error

SavePlan creates a plan record via UPSERT.

func (PostgresStorage) SaveRun

func (s PostgresStorage) SaveRun(ctx context.Context, run *scheddomain.RunRecord) error

SaveRun creates or updates a run record via UPSERT.

func (PostgresStorage) UpdateConversationMetadata

func (s PostgresStorage) UpdateConversationMetadata(ctx context.Context, conversationID string, metadata convdomain.ConversationMetadata) error

UpdateConversationMetadata updates metadata for a conversation.

type RedisConfig

type RedisConfig struct {
	Host     string `json:"host" yaml:"host"`
	Port     int    `json:"port" yaml:"port"`
	Database int    `json:"database" yaml:"database"`
	Password string `json:"password,omitempty" yaml:"password,omitempty"`
	Username string `json:"username,omitempty" yaml:"username,omitempty"`
	TTL      int    `json:"ttl,omitempty" yaml:"ttl,omitempty"` // TTL in seconds, 0 means no expiration
}

RedisConfig contains Redis-specific configuration

type RedisStorage

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

RedisStorage implements ConversationStorage using Redis

func NewRedisStorage

func NewRedisStorage(config RedisConfig) (*RedisStorage, error)

NewRedisStorage creates a new Redis storage instance

func (*RedisStorage) AppendHistory

func (s *RedisStorage) AppendHistory(ctx context.Context, command string) error

AppendHistory appends a command to the shell history list.

func (*RedisStorage) Close

func (s *RedisStorage) Close() error

Close closes the Redis connection

func (*RedisStorage) DeleteConversation

func (s *RedisStorage) DeleteConversation(ctx context.Context, conversationID string) error

DeleteConversation removes a conversation by its ID

func (*RedisStorage) DeleteJob

func (s *RedisStorage) DeleteJob(ctx context.Context, id string) error

DeleteJob removes a job by ID.

func (*RedisStorage) DeletePlan

func (s *RedisStorage) DeletePlan(ctx context.Context, id string) error

DeletePlan removes a plan by ID.

func (*RedisStorage) GetSessionGroup

func (s *RedisStorage) GetSessionGroup(ctx context.Context, groupKey string) (SessionGroupEntry, bool, error)

GetSessionGroup returns the entry for groupKey or (_, false, nil) if missing.

func (*RedisStorage) Health

func (s *RedisStorage) Health(ctx context.Context) error

Health checks if Redis is reachable and functional

func (*RedisStorage) ListConversations

func (s *RedisStorage) ListConversations(ctx context.Context, limit, offset int) ([]convdomain.ConversationSummary, error)

ListConversations returns a list of conversation summaries

func (*RedisStorage) ListConversationsNeedingTitles

func (s *RedisStorage) ListConversationsNeedingTitles(ctx context.Context, limit int) ([]convdomain.ConversationSummary, error)

ListConversationsNeedingTitles returns conversations that need title generation

func (*RedisStorage) ListJobs

func (s *RedisStorage) ListJobs(ctx context.Context) ([]*scheddomain.ScheduledJob, error)

ListJobs returns all jobs sorted by CreatedAt ascending.

func (*RedisStorage) ListPlans

func (s *RedisStorage) ListPlans(ctx context.Context) ([]*PlanRecord, error)

ListPlans returns all plans sorted by CreatedAt descending.

func (*RedisStorage) ListRuns

func (s *RedisStorage) ListRuns(ctx context.Context, jobID string) ([]*scheddomain.RunRecord, error)

ListRuns returns run records sorted by StartedAt descending.

func (*RedisStorage) ListSessionGroups

func (s *RedisStorage) ListSessionGroups(ctx context.Context) (map[string]SessionGroupEntry, error)

ListSessionGroups returns all entries from the session-groups hash.

func (*RedisStorage) LoadConversation

func (s *RedisStorage) LoadConversation(ctx context.Context, conversationID string) ([]convdomain.ConversationEntry, convdomain.ConversationMetadata, error)

LoadConversation loads a conversation by its ID

func (*RedisStorage) LoadHistory

func (s *RedisStorage) LoadHistory(ctx context.Context, limit int) ([]string, error)

LoadHistory returns the most recent commands up to limit.

func (*RedisStorage) LoadJob

LoadJob returns a job by ID.

func (*RedisStorage) LoadPlan

func (s *RedisStorage) LoadPlan(ctx context.Context, id string) (*PlanRecord, error)

LoadPlan returns a plan by ID.

func (*RedisStorage) PruneRuns

func (s *RedisStorage) PruneRuns(ctx context.Context, keep int) error

PruneRuns deletes all but the newest keep run records.

func (*RedisStorage) PutSessionGroup

func (s *RedisStorage) PutSessionGroup(ctx context.Context, groupKey string, entry SessionGroupEntry) error

PutSessionGroup creates or replaces the entry for groupKey via an atomic HSET. If a TTL is configured for this Redis backend, the TTL is refreshed on the parent hash so the index doesn't outlive the conversation data.

func (*RedisStorage) SaveConversation

func (s *RedisStorage) SaveConversation(ctx context.Context, conversationID string, entries []convdomain.ConversationEntry, metadata convdomain.ConversationMetadata) error

SaveConversation saves a conversation with its entries

func (*RedisStorage) SaveJob

func (s *RedisStorage) SaveJob(ctx context.Context, job *scheddomain.ScheduledJob) error

SaveJob creates or updates a scheduled job. The configured conversation TTL deliberately does not apply - a scheduled job must not silently expire.

func (*RedisStorage) SavePlan

func (s *RedisStorage) SavePlan(ctx context.Context, plan *PlanRecord) error

SavePlan creates a plan record. The configured conversation TTL deliberately does not apply - plans are an audit trail and must not silently expire.

func (*RedisStorage) SaveRun

func (s *RedisStorage) SaveRun(ctx context.Context, run *scheddomain.RunRecord) error

SaveRun creates or updates a run record. No TTL - retention is handled by PruneRuns so records don't silently expire mid-run.

func (*RedisStorage) UpdateConversationMetadata

func (s *RedisStorage) UpdateConversationMetadata(ctx context.Context, conversationID string, metadata convdomain.ConversationMetadata) error

UpdateConversationMetadata updates metadata for a conversation

type SQLiteConfig

type SQLiteConfig struct {
	Path string `json:"path" yaml:"path"`
}

SQLiteConfig contains SQLite-specific configuration

type SQLiteStorage

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

SQLiteStorage implements ConversationStorage on top of the shared sqlStore core, backed by a local pure-Go SQLite file.

func NewSQLiteStorage

func NewSQLiteStorage(config SQLiteConfig) (*SQLiteStorage, error)

NewSQLiteStorage creates a new SQLite storage instance.

func (SQLiteStorage) AppendHistory

func (s SQLiteStorage) AppendHistory(ctx context.Context, command string) error

AppendHistory appends a command to the shell history log.

func (SQLiteStorage) Close

func (s SQLiteStorage) Close() error

Close closes the database connection.

func (SQLiteStorage) DB

func (s SQLiteStorage) DB() *sql.DB

DB returns the underlying database connection.

func (SQLiteStorage) DeleteConversation

func (s SQLiteStorage) DeleteConversation(ctx context.Context, conversationID string) error

DeleteConversation removes a conversation by its ID.

func (SQLiteStorage) DeleteJob

func (s SQLiteStorage) DeleteJob(ctx context.Context, id string) error

DeleteJob removes a job by ID. Returns ErrJobNotFound when the job does not exist.

func (SQLiteStorage) DeletePlan

func (s SQLiteStorage) DeletePlan(ctx context.Context, id string) error

DeletePlan removes a plan by ID.

func (SQLiteStorage) GetSessionGroup

func (s SQLiteStorage) GetSessionGroup(ctx context.Context, groupKey string) (SessionGroupEntry, bool, error)

GetSessionGroup returns the entry for groupKey or (_, false, nil) if missing.

func (SQLiteStorage) Health

func (s SQLiteStorage) Health(ctx context.Context) error

Health checks if the database is reachable and functional.

func (SQLiteStorage) ListConversations

func (s SQLiteStorage) ListConversations(ctx context.Context, limit, offset int) ([]convdomain.ConversationSummary, error)

ListConversations returns a list of conversation summaries.

func (SQLiteStorage) ListConversationsNeedingTitles

func (s SQLiteStorage) ListConversationsNeedingTitles(ctx context.Context, limit int) ([]convdomain.ConversationSummary, error)

ListConversationsNeedingTitles returns conversations that need title generation.

func (SQLiteStorage) ListJobs

func (s SQLiteStorage) ListJobs(ctx context.Context) ([]*scheddomain.ScheduledJob, error)

ListJobs returns all jobs sorted by CreatedAt ascending.

func (SQLiteStorage) ListPlans

func (s SQLiteStorage) ListPlans(ctx context.Context) ([]*PlanRecord, error)

ListPlans returns all plans sorted by CreatedAt descending.

func (SQLiteStorage) ListRuns

func (s SQLiteStorage) ListRuns(ctx context.Context, jobID string) ([]*scheddomain.RunRecord, error)

ListRuns returns run records sorted by StartedAt descending.

func (SQLiteStorage) ListSessionGroups

func (s SQLiteStorage) ListSessionGroups(ctx context.Context) (map[string]SessionGroupEntry, error)

ListSessionGroups returns all session-group entries.

func (SQLiteStorage) LoadConversation

func (s SQLiteStorage) LoadConversation(ctx context.Context, conversationID string) ([]convdomain.ConversationEntry, convdomain.ConversationMetadata, error)

LoadConversation loads a conversation by its ID.

func (SQLiteStorage) LoadHistory

func (s SQLiteStorage) LoadHistory(ctx context.Context, limit int) ([]string, error)

LoadHistory returns the most recent commands up to limit in chronological order; limit <= 0 returns everything.

func (SQLiteStorage) LoadJob

func (s SQLiteStorage) LoadJob(ctx context.Context, id string) (*scheddomain.ScheduledJob, error)

LoadJob returns a job by ID. Returns ErrJobNotFound when the job does not exist.

func (SQLiteStorage) LoadPlan

func (s SQLiteStorage) LoadPlan(ctx context.Context, id string) (*PlanRecord, error)

LoadPlan returns a plan by ID.

func (SQLiteStorage) PruneRuns

func (s SQLiteStorage) PruneRuns(ctx context.Context, keep int) error

PruneRuns deletes all but the newest keep run records.

func (SQLiteStorage) PutSessionGroup

func (s SQLiteStorage) PutSessionGroup(ctx context.Context, groupKey string, entry SessionGroupEntry) error

PutSessionGroup creates or replaces the entry for groupKey via UPSERT.

func (SQLiteStorage) SaveConversation

func (s SQLiteStorage) SaveConversation(ctx context.Context, conversationID string, entries []convdomain.ConversationEntry, metadata convdomain.ConversationMetadata) error

SaveConversation saves a conversation with its entries using the single-table schema (messages are stored as an embedded JSON blob).

func (SQLiteStorage) SaveJob

func (s SQLiteStorage) SaveJob(ctx context.Context, job *scheddomain.ScheduledJob) error

SaveJob creates or updates a scheduled job via UPSERT.

func (SQLiteStorage) SavePlan

func (s SQLiteStorage) SavePlan(ctx context.Context, plan *PlanRecord) error

SavePlan creates a plan record via UPSERT.

func (SQLiteStorage) SaveRun

func (s SQLiteStorage) SaveRun(ctx context.Context, run *scheddomain.RunRecord) error

SaveRun creates or updates a run record via UPSERT.

func (SQLiteStorage) UpdateConversationMetadata

func (s SQLiteStorage) UpdateConversationMetadata(ctx context.Context, conversationID string, metadata convdomain.ConversationMetadata) error

UpdateConversationMetadata updates metadata for a conversation.

type ScheduledJobStorage

type ScheduledJobStorage interface {
	// SaveJob creates or updates a scheduled job.
	SaveJob(ctx context.Context, job *scheddomain.ScheduledJob) error

	// LoadJob returns a job by ID. Returns ErrJobNotFound when the job does not exist.
	LoadJob(ctx context.Context, id string) (*scheddomain.ScheduledJob, error)

	// ListJobs returns all jobs sorted by CreatedAt ascending.
	ListJobs(ctx context.Context) ([]*scheddomain.ScheduledJob, error)

	// DeleteJob removes a job by ID. Returns ErrJobNotFound when the job does not exist.
	DeleteJob(ctx context.Context, id string) error
}

ScheduledJobStorage defines the interface for persisting scheduled jobs. Implementations must be safe for concurrent access. Change notification is the consumer's job: the scheduler polls ListJobs and diffs (see internal/scheduler).

type ScheduledRunStorage

type ScheduledRunStorage interface {
	// SaveRun creates or updates a run record (upsert by SessionID).
	SaveRun(ctx context.Context, run *scheddomain.RunRecord) error

	// ListRuns returns run records sorted by StartedAt descending. An empty
	// jobID returns runs for all jobs.
	ListRuns(ctx context.Context, jobID string) ([]*scheddomain.RunRecord, error)

	// PruneRuns deletes all but the newest keep run records (across all jobs).
	PruneRuns(ctx context.Context, keep int) error
}

ScheduledRunStorage persists per-fire run records for scheduled jobs, keyed by SessionID (which doubles as the conversation ID of the agent run).

type SessionGroupEntry

type SessionGroupEntry struct {
	CurrentSessionID string    `json:"current_session_id"`
	History          []string  `json:"history,omitempty"`
	LastRollover     time.Time `json:"last_rollover,omitempty"`
	UpdatedAt        time.Time `json:"updated_at"`
}

SessionGroupEntry tracks the active session for a given group key plus a rollover history so old conversations can still be looked up via `infer conversations list`.

type SessionGroupStorage

type SessionGroupStorage interface {
	// GetSessionGroup returns the entry for groupKey. The bool is false when
	// no entry exists; the error is non-nil only on storage failure.
	GetSessionGroup(ctx context.Context, groupKey string) (SessionGroupEntry, bool, error)

	// PutSessionGroup creates or replaces the entry for groupKey atomically.
	PutSessionGroup(ctx context.Context, groupKey string, entry SessionGroupEntry) error

	// ListSessionGroups returns all entries keyed by their group key. Used by
	// administrative tooling and tests.
	ListSessionGroups(ctx context.Context) (map[string]SessionGroupEntry, error)
}

SessionGroupStorage defines the interface for persisting the session-group index that maps a stable channel/sender key (e.g. "channel-telegram-12345") to the current conversation session UUID for that key.

func NewMemorySessionGroupStorage

func NewMemorySessionGroupStorage() SessionGroupStorage

NewMemorySessionGroupStorage returns an in-memory SessionGroupStorage. Used as a fallback when conversation storage is disabled but the rollover manager still needs somewhere to keep group state for the lifetime of the process.

type ShellHistoryStorage

type ShellHistoryStorage interface {
	// AppendHistory appends a command to the history log.
	AppendHistory(ctx context.Context, command string) error

	// LoadHistory returns the most recent commands up to limit.
	LoadHistory(ctx context.Context, limit int) ([]string, error)
}

ShellHistoryStorage defines the interface for persisting shell command history.

type StorageConfig

type StorageConfig struct {
	// Type specifies the storage backend type (see config.StorageType* constants)
	Type config.StorageType `json:"type" yaml:"type"`

	// SQLite specific configuration
	SQLite SQLiteConfig `json:"sqlite,omitempty" yaml:"sqlite,omitempty"`

	// Postgres specific configuration
	Postgres PostgresConfig `json:"postgres,omitempty" yaml:"postgres,omitempty"`

	// Redis specific configuration
	Redis RedisConfig `json:"redis,omitempty" yaml:"redis,omitempty"`

	// JSONL specific configuration
	Jsonl JsonlStorageConfig `json:"jsonl,omitempty" yaml:"jsonl,omitempty"`

	// D1 specific configuration
	D1 D1Config `json:"d1,omitempty" yaml:"d1,omitempty"`
}

StorageConfig contains configuration for storage backends

func NewStorageFromConfig

func NewStorageFromConfig(cfg *config.Config) StorageConfig

NewStorageFromConfig creates a storage configuration from app config

type Stores

type Stores struct {
	Conversations ConversationStorage
	SessionGroups SessionGroupStorage
	ScheduledJobs ScheduledJobStorage
	ScheduledRuns ScheduledRunStorage
	Plans         PlanStorage
	ShellHistory  ShellHistoryStorage
}

Stores is the aggregate returned by NewStorage, holding all storage backends.

func NewStorage

func NewStorage(config StorageConfig) (*Stores, error)

NewStorage creates a new storage instance based on the provided configuration

type TrailingMetaLine

type TrailingMetaLine struct {
	Type     string                          `json:"type"`
	Metadata convdomain.ConversationMetadata `json:"metadata"`
}

TrailingMetaLine represents a metadata line without version (used after entries)

type V2EntryLine

type V2EntryLine struct {
	Version int                          `json:"v,omitempty"`
	Type    string                       `json:"type"`
	Index   int                          `json:"index"`
	Entry   convdomain.ConversationEntry `json:"entry"`
}

V2EntryLine represents an entry line in v2 format (first entry has version)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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