store

package
v0.7.1 Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

View Source
const CurrentSchemaVersion = 4
View Source
const (
	DefaultAgentName = "opencode"
)

UI defaults and bounds. normalize clamps/coerces out-of-range or unknown on-disk values so a hand-edited or corrupt config can never feed an invalid value downstream (F44).

Variables

View Source
var ErrReadOnly = errors.New("store: config loaded from a newer schema is read-only")

ErrReadOnly is returned by Save/Update when asked to write a config loaded from a newer on-disk schema. Refusing the write prevents an older binary from clobbering fields it does not understand (F33).

Functions

func DefaultPath

func DefaultPath() string

func Key

func Key(agent, id string) string

func PruneOld

func PruneOld(cfg *Config, maxAge time.Duration, exists func(string) bool)

func ShortID

func ShortID(id string) string

func ValidProviderSessionID

func ValidProviderSessionID(id string) bool

ValidProviderSessionID is the schema-v3 provider identity grammar. Runtime discovery must use this same boundary so it cannot persist a value that a later load would reject by dropping the containing session record.

func ValidateProfile

func ValidateProfile(profile Profile) error

func ValidateProfileName

func ValidateProfileName(name string) error

func ValidateSessionProfileOverrides

func ValidateSessionProfileOverrides(overrides SessionProfileOverrides) error

Types

type Config

type Config struct {
	SchemaVersion  int                      `json:"schema_version"`
	DefaultAgent   string                   `json:"default_agent"`
	DefaultProfile string                   `json:"default_profile"`
	Profiles       map[string]Profile       `json:"profiles"`
	Sessions       map[string]SessionRecord `json:"sessions"`
	UI             UISettings               `json:"ui"`

	// ReadOnly is set when the on-disk file declares a SchemaVersion newer than
	// this binary understands. The app must not write such a config (doing so
	// would drop fields it does not model), so Save/Update refuse it (F33). It
	// is in-memory only and never serialized.
	ReadOnly bool
	// contains filtered or unexported fields
}

func DefaultConfig

func DefaultConfig() Config

func (Config) MarshalJSON

func (c Config) MarshalJSON() ([]byte, error)

func (*Config) PutSession

func (c *Config) PutSession(key string, rec SessionRecord) bool

PutSession inserts or updates rec under key with a guard against the 8-char ShortID map key collapsing two distinct full IDs into one slot (F22). The short key carries only 32 bits of entropy, so two same-agent sessions can collide; without this guard the second write would silently clobber the first, orphaning a live session whose only handle is that record. It returns true on a successful write (no record, or the same full ID) and false (with a log) when an existing record under key carries a different non-empty full ID.

func (*Config) UnmarshalJSON

func (c *Config) UnmarshalJSON(data []byte) error

type Mode

type Mode string
const (
	ModeYolo Mode = "yolo"
	ModeSafe Mode = "safe"
)

type MousePolicy

type MousePolicy string
const (
	MousePolicyAuto MousePolicy = "auto"
	MousePolicyOn   MousePolicy = "on"
	MousePolicyOff  MousePolicy = "off"
)

type PRRecord

type PRRecord struct {
	URL         string    `json:"url"`
	Number      int       `json:"number"`
	LastStatus  string    `json:"last_status"`
	LastChecked time.Time `json:"last_checked"`
}

type Profile

type Profile struct {
	Provider        *string      `json:"provider,omitempty"`
	Mode            *Mode        `json:"mode,omitempty"`
	CommandAlias    *string      `json:"command_alias,omitempty"`
	Mouse           *MousePolicy `json:"mouse,omitempty"`
	ControlPrefix   *string      `json:"control_prefix,omitempty"`
	BackDetach      *bool        `json:"back_detach,omitempty"`
	ScrollbackLines *int         `json:"scrollback_lines,omitempty"`
	// contains filtered or unexported fields
}

func (Profile) MarshalJSON

func (p Profile) MarshalJSON() ([]byte, error)

func (*Profile) UnmarshalJSON

func (p *Profile) UnmarshalJSON(data []byte) error

type SessionExit

type SessionExit struct {
	SessionName       string
	ProviderSessionID string
	ExitCode          int
	UAMInitiated      bool
}

SessionExit describes how a provider process left its native session host. UAMInitiated is true only for an explicit UAM stop/restart request; terminal provider exits and externally delivered signals remain natural exits.

type SessionProfileOverrides

type SessionProfileOverrides struct {
	Mode            *Mode        `json:"mode,omitempty"`
	CommandAlias    *string      `json:"command_alias,omitempty"`
	Mouse           *MousePolicy `json:"mouse,omitempty"`
	ControlPrefix   *string      `json:"control_prefix,omitempty"`
	BackDetach      *bool        `json:"back_detach,omitempty"`
	ScrollbackLines *int         `json:"scrollback_lines,omitempty"`
	// contains filtered or unexported fields
}

func (SessionProfileOverrides) MarshalJSON

func (o SessionProfileOverrides) MarshalJSON() ([]byte, error)

func (*SessionProfileOverrides) UnmarshalJSON

func (o *SessionProfileOverrides) UnmarshalJSON(data []byte) error

type SessionRecord

type SessionRecord struct {
	ID           string `json:"id"`
	Agent        string `json:"agent"`
	CommandAlias string `json:"command_alias,omitempty"`
	Name         string `json:"name"`
	Prompt       string `json:"prompt,omitempty"`
	Mode         Mode   `json:"mode"`
	Workdir      string `json:"workdir"`
	// SessionName is the backend session name ("uam-<agent>-<id>"). The JSON
	// key keeps its historical "tmux_session" spelling so configs written by
	// tmux-backed releases load unchanged.
	SessionName string    `json:"tmux_session"`
	CreatedAt   time.Time `json:"created_at"`
	LastSeenAt  time.Time `json:"last_seen_at"`
	Pinned      bool      `json:"pinned"`
	Group       string    `json:"group"`
	SortIndex   int       `json:"sort_index"`
	Status      Status    `json:"status,omitempty"`
	// ProviderSessionID is the agent CLI's own session id, recorded when the
	// provider lets uam seed it at dispatch (e.g. claude --session-id). A
	// resume can then target the exact provider session instead of the
	// provider's "most recent" heuristic.
	ProviderSessionID string `json:"provider_session_id,omitempty"`
	// LastExitCode records the agent process's exit status from the most
	// recent close (-1 when it died on a signal). Pointer so records from
	// older schemas stay distinguishable from a real exit 0.
	LastExitCode     *int                     `json:"last_exit_code,omitempty"`
	PR               *PRRecord                `json:"pr,omitempty"`
	Profile          string                   `json:"profile,omitempty"`
	ProfileOverrides *SessionProfileOverrides `json:"profile_overrides,omitempty"`
	// contains filtered or unexported fields
}

func (SessionRecord) MarshalJSON

func (r SessionRecord) MarshalJSON() ([]byte, error)

func (*SessionRecord) UnmarshalJSON

func (r *SessionRecord) UnmarshalJSON(data []byte) error

type Status

type Status string

Status distinguishes records that should keep behaving as live sessions (StatusActive — recoverable on attach) from records the user deliberately retired (StatusClosedByUser).

const (
	StatusActive       Status = "active"
	StatusClosedByUser Status = "closed_by_user"
)

type Store

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

func Open

func Open(path string) (*Store, error)

func (*Store) Load

func (s *Store) Load() (Config, error)

func (*Store) MarkSessionClosed

func (s *Store) MarkSessionClosed(sessionName string, exitCode int) error

MarkSessionClosed flags the record whose backend session name matches as user-closed and records the agent's exit code. It is what a session host calls when its agent exits — the native replacement for the tmux session-closed hook driving `uam notify-closed`. Idempotent and a no-op when no record matches (e.g. uam already deleted it via `uam rm`).

func (*Store) Path

func (s *Store) Path() string

func (*Store) Save

func (s *Store) Save(cfg Config) error

func (*Store) SetSessionProbe

func (s *Store) SetSessionProbe(exists func(string) bool)

SetSessionProbe injects a callback that reports whether a backend session name is still live. Migration uses it to tell a reboot-survivor (live -> stays Active) apart from a user-stopped session (dead -> closed-by-user). When unset, migration conservatively keeps the legacy Active behavior (F07).

func (*Store) TryMarkSessionClosed

func (s *Store) TryMarkSessionClosed(sessionName string, exitCode int) (bool, error)

TryMarkSessionClosed is the compatibility entry point for older callers. It records an explicit UAM stop and returns whether a durable record matched.

func (*Store) TryRecordSessionExit

func (s *Store) TryRecordSessionExit(exit SessionExit) (bool, error)

TryRecordSessionExit records the provider's latest exit while preserving resumability for natural exits. Only an explicit UAM stop/restart retires the record into the closed-by-user group.

func (*Store) Update

func (s *Store) Update(fn func(*Config) error) error

type UISettings

type UISettings struct {
	GroupByDir bool `json:"group_by_dir"`
	// Sort and PeekWidth are retained schema-v3 compatibility fields. They are
	// normalized and round-tripped even when the TUI exposes no direct control.
	Sort      string `json:"sort"`
	PeekWidth int    `json:"peek_width"`
}

Jump to

Keyboard shortcuts

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