store

package
v0.22.1 Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	PairPending = "pending"
	PairAllowed = "allowed"
	PairDenied  = "denied"
)

Message pair states: the owner has not decided yet, allowed messages, or declined them (sticky until the owner resets the pair).

View Source
const (
	MaxMessagePairs    = 32
	MaxPairMessages    = 20
	MaxHeldMessageText = 16 << 10
)

Bounds of the stored message pairs.

View Source
const (
	ScheduleDaily    = "daily"
	ScheduleWeekdays = "weekdays"
	ScheduleHours    = "hours"
	ScheduleWeekly   = "weekly"
)

Routine schedule kinds: daily at a time, Monday to Friday at a time, every N hours, or weekly on one day at a time. Times are the service's local time.

View Source
const (
	MaxRoutineHours      = 24
	MaxRoutineRunsPerDay = 100
	MaxRoutineMinutes    = 720
	MaxRoutineRuns       = 100
)

Routine bounds: every N hours takes 1 to MaxRoutineHours; a day allows 1 to MaxRoutineRunsPerDay runs, and a run 1 to MaxRoutineMinutes minutes. MaxRoutineRuns is how many runs a routine's history keeps, newest last.

View Source
const (
	MinCompactionThreshold     = 50
	MaxCompactionThreshold     = 90
	DefaultCompactionThreshold = 80
)

The bounds of WebSettings.CompactionThreshold, in percent.

View Source
const (
	MaxCustomModels         = 100
	MaxCustomModelNameBytes = 64
	MaxCustomModelURLBytes  = 512
	MaxCustomModelKeyBytes  = 4096
	// CustomModelKeyPrefix starts every custom model's key variable name.
	CustomModelKeyPrefix = "UAM_BYOM_"
)

Custom model limits: models, and bytes per field.

View Source
const (
	MaxHiddenModels     = 200
	MaxHiddenModelBytes = 128
)

Hidden model limits: IDs per provider, and bytes per ID.

View Source
const (
	WebSendSteer = "steer"
	WebSendQueue = "queue"
)

The values of WebSettings.SendDefault.

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

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).

View Source
const DefaultUtilityDailyLimit = 400

DefaultUtilityDailyLimit is WebSettings.UtilityDailyLimit when unset.

View Source
const SurfaceWeb = "web"

SurfaceWeb marks records owned by the `uam web` service.

View Source
const WebTitleModelNone = "none"

WebTitleModelNone is the WebSettings.TitleModel value that opts a provider out of the Utility model, so UAM makes no AI call of its own for it.

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).

View Source
var ErrSetAside = errors.New("store: the config file could not be read and was set aside; changes are not saved")

ErrSetAside is returned by every write once this Store set the file aside after an earlier load had returned its records: the caller's in-memory state came from that file, and saving onto fresh defaults would drop it unseen.

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)

PruneOld drops long-stale terminal records whose session is gone. Records owned by another surface are never pruned here: their liveness is not a terminal session host, so the probe cannot speak for them.

func ShortID

func ShortID(id string) string

func UniqueModelIDs added in v0.16.0

func UniqueModelIDs(ids []string) []string

UniqueModelIDs returns ids in order, each once.

func ValidCustomModel added in v0.9.0

func ValidCustomModel(m WebCustomModel) error

ValidCustomModel reports why m cannot be stored, or nil. BaseURL is an http or https URL without credentials, query or fragment, so no secret can ride in it.

func ValidCustomModels added in v0.9.0

func ValidCustomModels(list []WebCustomModel) error

ValidCustomModels reports why list cannot be stored, or nil: at most MaxCustomModels valid entries, each selection ID once, and one connection (base URL, wire API, key variable) per provider name.

func ValidHiddenModel added in v0.8.0

func ValidHiddenModel(id string) bool

ValidHiddenModel reports whether id can be stored as a hidden model ID: 1 to MaxHiddenModelBytes bytes of UTF-8 without control characters, as stored model IDs are checked.

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 ValidTokenPriceModel added in v0.14.0

func ValidTokenPriceModel(model string) bool

ValidTokenPriceModel accepts a model ID or the full selection ID of a custom model.

func ValidateProfile

func ValidateProfile(profile Profile) error

Types

type AccountLink struct {
	Login    string    `json:"login"`
	Host     string    `json:"host,omitempty"`
	LinkedAt time.Time `json:"linked_at"`
}

AccountLink is the account a provider's runtime must be signed in as: the first sign-in links it, and a sign-in as another account is refused until it is unlinked.

type Budget added in v0.20.4

type Budget struct {
	Credits      float64 `json:"credits,omitempty"`
	From         float64 `json:"from,omitempty"`
	QuotaPercent float64 `json:"quota_percent,omitempty"`
	Reached      bool    `json:"reached,omitempty"`
	WrapUp       bool    `json:"wrap_up,omitempty"`
}

Budget limits what a Thread may spend: Credits more AI units from the conversation total From it had when the budget was set, and the account quota used up to QuotaPercent. A zero limit is no limit. Reached is set once either is met, and holds until the owner changes the budget. WrapUp is set while the Thread, at its limit, writes its handoff; a Thread loaded with it set was interrupted in its wrap-up.

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"`
	// WebProjects holds the web interface's Projects, keyed by Project ID.
	WebProjects map[string]WebProject `json:"web_projects,omitempty"`
	// WebSettings are the web interface's settings, shared by every browser.
	WebSettings WebSettings `json:"web_settings,omitzero"`
	// WebRoutines holds the web interface's routines, keyed by routine ID.
	WebRoutines map[string]WebRoutine `json:"web_routines,omitempty"`
	// WebAccountLinks holds the one account each provider is linked to,
	// keyed by provider name. Only the service sets it; no settings PATCH.
	WebAccountLinks map[string]AccountLink `json:"web_account_links,omitempty"`
	// WebForks reserves native fork requests before their RPC. Only unresolved
	// requests stay here; registered Tasks carry their own exact receipt.
	WebForks map[string]WebFork `json:"web_forks,omitempty"`
	// WebGitLab records commits made by Tasks and the investigation reserved
	// for each pipeline. Receipts remain after an investigation Task is deleted.
	WebGitLab map[string]WebGitLabCommit `json:"web_gitlab,omitempty"`
	// WebMessagePairs holds the owner's decisions about messages between
	// Threads, keyed by pair ID (message_pairs.go).
	WebMessagePairs map[string]WebMessagePair `json:"web_message_pairs,omitempty"`

	// 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 ForkLineage added in v0.18.3

type ForkLineage struct {
	SourceTaskID string `json:"source_task_id"`
	UserItemID   string `json:"user_item_id"`
	UserEventID  string `json:"user_event_id"`
	ToEventID    string `json:"to_event_id,omitempty"`
	RequestID    string `json:"request_id"`
	Model        string `json:"model"`
}

ForkLineage also makes a successfully registered fork request idempotent after a restart, even when the target's selected model later changes.

type Mode

type Mode string
const (
	ModeYolo Mode = "yolo"
	ModeSafe Mode = "safe"
	// ModeAssisted is a web Task's opt-in provider review of permission
	// requests; Task defaults, profiles and routines never use it.
	ModeAssisted Mode = "assisted"
)

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 RoutineSchedule added in v0.13.0

type RoutineSchedule struct {
	Kind    string `json:"kind"`
	Time    string `json:"time,omitempty"`
	Hours   int    `json:"hours,omitempty"`
	Weekday int    `json:"weekday"`
}

RoutineSchedule is when a routine runs. Time is "HH:MM" (24-hour) for every kind but hours; Hours is set only for hours, and Weekday (0 Sunday to 6 Saturday) only for weekly. Weekday is always written: 0 is Sunday.

func (RoutineSchedule) Clock added in v0.13.0

func (s RoutineSchedule) Clock() (hour, minute int, err error)

Clock returns the schedule's hour and minute.

func (RoutineSchedule) Validate added in v0.13.0

func (s RoutineSchedule) Validate() error

Validate reports why s is not a schedule a routine can have.

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"`
	// Surface names the owner of a record. Empty means a terminal session host;
	// SurfaceWeb means the web service. Terminal commands never list, attach,
	// resume or prune records with a non-empty Surface, and the web service
	// only opens its own, so neither takes over the other's conversations.
	Surface string `json:"surface,omitempty"`
	// Web is the web service's durable state for a SurfaceWeb record.
	Web *WebState `json:"web,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 TodoCounts added in v0.18.0

type TodoCounts struct {
	Done       int `json:"done,omitempty"`
	Total      int `json:"total,omitempty"`
	Blocked    int `json:"blocked,omitempty"`
	InProgress int `json:"in_progress,omitempty"`
	Pending    int `json:"pending,omitempty"`
	Open       int `json:"open,omitempty"`
	Omitted    int `json:"omitted,omitempty"`
}

TodoCounts counts the rows of a conversation's todo list by status: Open is InProgress plus Pending, the only split counts written before those two were (so Open past their sum is rows of either), and Omitted the rows a bounded copy left out.

type TurnChangeCounts added in v0.18.3

type TurnChangeCounts struct {
	Status    string `json:"status"`
	EventID   string `json:"event_id,omitempty"`
	Files     int64  `json:"files,omitempty"`
	Additions int64  `json:"additions,omitempty"`
	Deletions int64  `json:"deletions,omitempty"`
	Omitted   int64  `json:"omitted,omitempty"`
}

TurnChangeCounts retains no file rows or patches. Rows are read on demand from the Task's bounded turn-changes snapshot file. Missing means the Task did not request native capture; unavailable status never claims zero.

type TurnPeer added in v0.21.20

type TurnPeer struct {
	Pair        string `json:"pair"`
	Message     string `json:"message"`
	From        string `json:"from"`
	FromName    string `json:"from_name,omitempty"`
	FromProject string `json:"from_project,omitempty"`
	Reply       bool   `json:"reply,omitempty"`
}

TurnPeer marks a turn another Thread's message started: Message is that message's ID and From the sending Thread, with its name and Project as they were. Reply is set for the automatic reply to a message this Thread sent.

type TurnTiming added in v0.8.0

type TurnTiming struct {
	ID         string    `json:"id"`
	UserItemID string    `json:"user_item_id,omitempty"`
	StartedAt  time.Time `json:"started_at"`
	EndedAt    time.Time `json:"ended_at,omitzero"`
	PausedAt   time.Time `json:"paused_at,omitzero"`
	PausedMS   int64     `json:"paused_ms,omitempty"`
	State      string    `json:"state"`
	// Token usage the provider reported for the turn's model calls (the main
	// agent and its subagents), summed as the calls report: tokens in and out,
	// and the calls' own duration, so a reader can tell generation speed from
	// wall time spent in tools or waiting.
	InputTokens     int64   `json:"input_tokens,omitempty"`
	OutputTokens    int64   `json:"output_tokens,omitempty"`
	GenerationMS    int64   `json:"generation_ms,omitempty"`
	Model           string  `json:"model,omitempty"`
	CacheReadTokens int64   `json:"cache_read_tokens,omitempty"`
	Calls           int     `json:"calls,omitempty"`
	NanoAIU         int64   `json:"nano_aiu,omitempty"`
	PremiumCost     float64 `json:"premium_cost,omitempty"`
	// Todo counts the todo list as the turn left it, for a turn that
	// changed it; its rows are kept beside the Task's uploads.
	Todo TodoCounts `json:"todo,omitzero"`
	// Native captured changes as this finalized owner turn left them.
	Changes *TurnChangeCounts `json:"changes,omitempty"`
	// Peer is set when another Thread's message, or the reply to this
	// Thread's message, started the turn.
	Peer *TurnPeer `json:"peer,omitempty"`
}

TurnTiming records foreground boundaries observed by the web service. An unfinished observation becomes unknown after its runtime connection is lost.

func CloneTurnTimings added in v0.18.3

func CloneTurnTimings(timings []TurnTiming) []TurnTiming

CloneTurnTimings gives each snapshot its own optional metadata.

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"`
}

type WebBadge added in v0.8.0

type WebBadge struct {
	Text  string `json:"text"`
	Color string `json:"color"`
}

WebBadge is a Project's badge: Text is two uppercase ASCII letters or digits, Color a palette key the browser maps to a colour.

type WebChart added in v0.13.0

type WebChart struct {
	ID       string    `json:"id"`
	Title    string    `json:"title"`
	Kind     string    `json:"kind"`
	XLabel   string    `json:"x_label,omitempty"`
	YLabel   string    `json:"y_label,omitempty"`
	Command  string    `json:"command,omitempty"`
	Format   string    `json:"format,omitempty"`
	X        string    `json:"x"`
	Y        []string  `json:"y"`
	PinnedAt time.Time `json:"pinned_at"`
	// TaskID and CallID name the Task's chart it was pinned from.
	TaskID string `json:"task_id,omitempty"`
	CallID string `json:"call_id,omitempty"`
}

WebChart is a chart pinned to a Project. Command, when set, is the shell command the owner approved by pinning it: Refresh runs it again in the Project directory and reads Format (csv or json) for the field X and the fields Y. A chart without a Command is a snapshot of its rows.

type WebCoAuthor added in v0.21.7

type WebCoAuthor struct {
	Enabled bool   `json:"enabled,omitempty"`
	Name    string `json:"name,omitempty"`
}

WebCoAuthor is the co-author setting: whether agents' commits carry a Co-authored-by trailer, and its value; the provider picks one when empty.

type WebContext added in v0.21.4

type WebContext struct {
	Used   int64 `json:"used"`
	Limit  int64 `json:"limit"`
	Prompt int64 `json:"prompt,omitempty"`
	Cached int64 `json:"cached,omitempty"`
}

WebContext is a conversation's context usage report, the fields of agentapi.Context.

type WebCustomModel added in v0.9.0

type WebCustomModel struct {
	Name        string `json:"name"`
	DisplayName string `json:"display_name,omitempty"`
	BaseURL     string `json:"base_url"`
	ModelID     string `json:"model_id"`
	Vision      bool   `json:"vision,omitempty"`
	// WireAPI is "", "completions" (the default) or "responses".
	WireAPI   string `json:"wire_api,omitempty"`
	APIKeyEnv string `json:"api_key_env"`
	// APIKey is the saved key in clear; the state file holds it encrypted
	// (sealed_keys.go). After a load, SealedKey keeps a stored key this
	// process could not decrypt, so a save does not drop it, and KeyError
	// says why it is not available.
	APIKey    string `json:"api_key,omitempty"`
	SealedKey string `json:"-"`
	KeyError  string `json:"-"`
}

WebCustomModel is one OpenAI-compatible model. Name names its provider connection, and models with the same Name share BaseURL, WireAPI and APIKeyEnv; the selection ID is Name + "/" + ModelID.

type WebDrawIO added in v0.21.0

type WebDrawIO struct {
	Origin  string `json:"origin,omitempty"`
	Enabled bool   `json:"enabled,omitempty"`
}

WebDrawIO is the draw.io editor setting.

type WebFork added in v0.18.3

type WebFork struct {
	ID                   string      `json:"id"`
	Provider             string      `json:"provider"`
	SourceConversationID string      `json:"source_conversation_id"`
	ProviderSessionID    string      `json:"provider_session_id,omitempty"`
	ProjectID            string      `json:"project_id"`
	Workdir              string      `json:"workdir"`
	Effort               string      `json:"effort,omitempty"`
	ContextSize          string      `json:"context_size"`
	Agent                string      `json:"agent,omitempty"`
	Mode                 Mode        `json:"mode"`
	CreatedAt            time.Time   `json:"created_at"`
	TailEventID          string      `json:"tail_event_id"`
	Lineage              ForkLineage `json:"lineage"`
	// Place and Folder are the new worktree a branch of a Thread in its own
	// worktree runs in, and its folder there; Workdir stays the Project's.
	// Start is the commit its branch was made at.
	Place  *WebPlace `json:"place,omitempty"`
	Folder string    `json:"folder,omitempty"`
	Start  string    `json:"start,omitempty"`
}

WebFork is the small durable reservation of a UAM target identity. Empty ProviderSessionID means the native result is unknown; it must never cause another fork RPC. A returned exact identity allows registration to retry.

type WebGitLabCommit added in v0.19.2

type WebGitLabCommit struct {
	TaskID         string                            `json:"task_id"`
	ProjectID      string                            `json:"project_id"`
	Host           string                            `json:"host"`
	Path           string                            `json:"path"`
	SHA            string                            `json:"sha"`
	Branch         string                            `json:"branch"`
	CreatedAt      time.Time                         `json:"created_at"`
	Investigations map[string]WebGitLabInvestigation `json:"investigations,omitempty"`
	// Failures holds what each failed job of the commit's pipelines failed
	// on, keyed by job ID, so each job log is read once. An empty Kind means
	// the log was read and nothing was recognised.
	Failures map[int64]WebGitLabFailure `json:"failures,omitempty"`
}

WebGitLabCommit ties a repository commit to the Task that made it.

type WebGitLabFailure added in v0.20.18

type WebGitLabFailure struct {
	Kind   string `json:"kind,omitempty"`
	Detail string `json:"detail,omitempty"`
}

WebGitLabFailure is a failed job's failure kind ("tests", "infra") and a short detail such as "2 tests". It never holds job log text.

type WebGitLabInvestigation added in v0.19.2

type WebGitLabInvestigation struct {
	TaskID     string `json:"task_id"`
	Registered bool   `json:"registered,omitempty"`
}

WebGitLabInvestigation reserves one Task for a numeric project ID and pipeline ID. Registered distinguishes a deleted Task from an interrupted creation that can still use its reserved ID.

type WebHandoff added in v0.20.9

type WebHandoff struct {
	At      time.Time `json:"at"`
	ReplyID string    `json:"reply_id,omitempty"`
	NoReply string    `json:"no_reply,omitempty"`
	Facts   string    `json:"facts"`
}

WebHandoff is a Thread's handoff at its budget: ReplyID is the main agent's reply that is the handoff, empty when it wrote none (NoReply says why), and Facts is the Markdown uam wrote from its own records.

type WebHeldMessage added in v0.21.20

type WebHeldMessage struct {
	ID     string    `json:"id"`
	From   string    `json:"from"`
	To     string    `json:"to"`
	Text   string    `json:"text"`
	CallID string    `json:"call_id,omitempty"`
	Reason string    `json:"reason"`
	At     time.Time `json:"at"`
}

WebHeldMessage is a message waiting for the owner: Reason is "first" (the pair's first message), "limit" (the pair used its deliveries) or "link" (a Thread is unattended, so the owner must link the pair).

type WebMemoryNote added in v0.21.14

type WebMemoryNote struct {
	Kind   string    `json:"kind"`
	Quote  string    `json:"quote"`
	ItemID string    `json:"item_id"`
	At     time.Time `json:"at"`
}

WebMemoryNote is one memory note: Kind is "constraint", "decision" or "fact"; Quote is copied from the conversation item ItemID.

type WebMessagePair added in v0.21.20

type WebMessagePair struct {
	ID        string           `json:"id"`
	A         string           `json:"a"`
	B         string           `json:"b"`
	State     string           `json:"state"`
	Linked    bool             `json:"linked,omitempty"`
	Allowance int              `json:"allowance,omitempty"`
	Used      int              `json:"used"`
	Limit     int              `json:"limit"`
	Held      *WebHeldMessage  `json:"held,omitempty"`
	Messages  []WebPeerMessage `json:"messages"`
	UpdatedAt time.Time        `json:"updated_at"`
}

WebMessagePair is the owner's decision about messages between two Threads (uam_send): A and B are their IDs, sorted. Allowance numbers the owner's allows; Used counts the deliveries the current one reserved, Limit how many it covers. Held is the message waiting for the owner; Messages are the newest messages, oldest first.

type WebNativePaths added in v0.21.20

type WebNativePaths struct {
	Paths []string  `json:"paths"`
	At    time.Time `json:"at"`
}

WebNativePaths is a native session diff read: the files it listed, with a renamed file's old path too, and when a read first listed them.

type WebOutputStyle added in v0.21.18

type WebOutputStyle struct {
	Name string `json:"name"`
	Text string `json:"text"`
}

WebProject is a directory the web interface groups Tasks under. There is at most one per Dir. WebOutputStyle is one named response style: Text replaces the provider's own style instructions.

type WebPeerMessage added in v0.21.20

type WebPeerMessage struct {
	ID        string    `json:"id"`
	From      string    `json:"from"`
	To        string    `json:"to"`
	CallID    string    `json:"call_id,omitempty"`
	Allowance int       `json:"allowance,omitempty"`
	Status    string    `json:"status"`
	Detail    string    `json:"detail,omitempty"`
	At        time.Time `json:"at"`
	UpdatedAt time.Time `json:"updated_at"`
}

WebPeerMessage is one message between the Threads of a pair and what became of it (held, queued, working, replied, stopped, failed, interrupted, cancelled, declined or undelivered). Allowance is the pair's allowance it reserved its deliveries from; 0 while held.

type WebPlace added in v0.19.4

type WebPlace struct {
	Mode     string `json:"mode"`
	Branch   string `json:"branch"`
	Base     string `json:"base,omitempty"`
	Worktree string `json:"worktree,omitempty"`
	Named    bool   `json:"named,omitempty"`
}

WebPlace is where a Thread runs when it is not on its Project's current branch: Mode "branch" made Branch in the Project's folder; Mode "worktree" made Branch from Base in the worktree folder Worktree. Named is set once the branch took the Thread's title, or was left as it was because it had been pushed.

type WebProject added in v0.8.0

type WebProject struct {
	ID        string    `json:"id"`
	Name      string    `json:"name"`
	Dir       string    `json:"dir"`
	CreatedAt time.Time `json:"created_at"`
	// LegacyDefaults are the per-Project Task defaults of versions before
	// WebSettings.TaskDefaults. Load reads them once, adopts the newest valid
	// ones as the setting when it is unset, and clears them, so the next save
	// drops the key. Nothing writes them.
	LegacyDefaults WebTaskDefaults `json:"defaults,omitzero"`
	// Badge is zero until the web service assigns one; it also replaces an
	// invalid one on load.
	Badge WebBadge `json:"badge,omitzero"`
	// Charts are the charts the owner pinned to the Project, oldest first.
	// The web service shows, and counts, only the ones it can check, and
	// keeps their rows elsewhere.
	Charts []WebChart `json:"charts,omitempty"`
	// BranchLink is the Project's branch link: absent until detected or
	// set, empty once the owner cleared it.
	BranchLink *string `json:"branch_link,omitempty"`
	// OutputStyle names the Project's style for its Threads; "" uses the
	// default.
	OutputStyle string `json:"output_style,omitempty"`
	// contains filtered or unexported fields
}

func (WebProject) MarshalJSON added in v0.8.0

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

func (*WebProject) UnmarshalJSON added in v0.8.0

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

type WebRewind added in v0.18.3

type WebRewind struct {
	RequestID   string          `json:"request_id"`
	UserItemID  string          `json:"user_item_id"`
	UserEventID string          `json:"user_event_id"`
	Mode        string          `json:"mode"`
	State       string          `json:"state"`
	Discarded   []string        `json:"discarded,omitempty"`
	Result      json.RawMessage `json:"result,omitempty"`
	// ReconcileFailed marks a reconcile that could not reread the record;
	// only then may the owner release the hold. Released records that the
	// hold was cleared without knowing what the rewind did.
	ReconcileFailed bool      `json:"reconcile_failed,omitempty"`
	Released        bool      `json:"released,omitempty"`
	CreatedAt       time.Time `json:"created_at"`
}

WebRewind is a Task's native rewind receipt. It is saved before the native request, which has no idempotency key, so a lost result or restart never repeats it. State is pending, applied, uncertain or done. Discarded lists only the Task's own turn timings' owner items in the discarded suffix.

func (*WebRewind) Clone added in v0.18.3

func (r *WebRewind) Clone() *WebRewind

Clone gives each holder its own lists.

type WebRoutine added in v0.13.0

type WebRoutine struct {
	ID            string          `json:"id"`
	ProjectID     string          `json:"project_id"`
	Name          string          `json:"name"`
	Prompt        string          `json:"prompt"`
	Provider      string          `json:"provider"`
	Model         string          `json:"model"`
	Schedule      RoutineSchedule `json:"schedule"`
	Enabled       bool            `json:"enabled"`
	Mode          Mode            `json:"mode"`
	Autopilot     bool            `json:"autopilot,omitempty"`
	MaxRunsPerDay int             `json:"max_runs_per_day"`
	MaxMinutes    int             `json:"max_minutes"`
	Place         *WebPlace       `json:"place,omitempty"`
	CreatedAt     time.Time       `json:"created_at"`
	NextRun       time.Time       `json:"next_run,omitzero"`
	Runs          []WebRoutineRun `json:"runs,omitempty"`
	// contains filtered or unexported fields
}

WebRoutine is recurring work in a Project: on its schedule, the web service starts a Task with Prompt on Model. NextRun is the next due firing, zero while paused; Runs is the newest MaxRoutineRuns firings, oldest first. Autopilot turns autopilot on in each run's Task: it keeps working until the agent calls task_complete or the run's time limit stops it. Place is where each run's Task works: nil is the Project's folder; Mode "worktree" is a new worktree and branch for every run, started from Base ("" starts where a new Task's worktree does). Its Branch, Worktree and Named are a made place's and stay empty.

func (WebRoutine) MarshalJSON added in v0.13.0

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

func (*WebRoutine) UnmarshalJSON added in v0.13.0

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

type WebRoutineRun added in v0.13.0

type WebRoutineRun struct {
	ID      string    `json:"id"`
	At      time.Time `json:"at"`
	Trigger string    `json:"trigger"`
	TaskID  string    `json:"task_id,omitempty"`
	Outcome string    `json:"outcome"`
	Reason  string    `json:"reason,omitempty"`
	EndedAt time.Time `json:"ended_at,omitzero"`
}

WebRoutineRun is one firing of a routine: when, what started it, the Task it created and how it ended. Outcome is running until the run ends; Reason explains a skip or a failure.

type WebSettings added in v0.8.0

type WebSettings struct {
	TokenPrices map[string]map[string]WebTokenPrice `json:"token_prices,omitempty"`
	// SendDefault is what Enter does while a turn runs: WebSendSteer or
	// WebSendQueue. Empty or unrecognised values mean steer at runtime.
	SendDefault string `json:"send_default,omitempty"`
	// DefaultProjectDir is where project folder browsing starts on this instance. Empty uses home.
	DefaultProjectDir string `json:"default_project_dir,omitempty"`
	// Terminal turns on the web terminal: a shell as the service user for
	// anyone signed in. Off when absent.
	Terminal bool `json:"terminal,omitempty"`
	// HiddenModels lists, by provider, the model IDs the browser does not
	// offer: sorted, without duplicates, at most MaxHiddenModels each. It is
	// a display preference, never a check on requests.
	HiddenModels map[string][]string `json:"hidden_models,omitempty"`
	// SubagentModels lists, by provider, the model IDs its subagents may use,
	// the fallback first: without duplicates, valid as hidden model IDs are,
	// at most MaxHiddenModels each. A provider without an entry is not limited.
	SubagentModels map[string][]string `json:"subagent_models,omitempty"`
	// TitleModel maps a provider to its Utility model: the model UAM uses for
	// its own small AI jobs, such as titling new Tasks. The key keeps its
	// first name, title_model. A provider without an entry uses its cheapest
	// priced model; WebTitleModelNone opts it out (it keeps its own title).
	TitleModel map[string]string `json:"title_model,omitempty"`
	// CustomModels are the OpenAI-compatible models the owner brought
	// (BYOM), valid as ValidCustomModels checks. Direct keys are kept in this
	// private store, encrypted with the key file beside it; environment-backed
	// keys store only the variable name.
	CustomModels []WebCustomModel `json:"custom_models,omitempty"`
	// TaskDefaults are the settings a new Task starts with; zero when unset.
	TaskDefaults WebTaskDefaults `json:"task_defaults,omitzero"`
	// UtilityDailyLimit is how many Utility model calls UAM makes a day, 0
	// to make none; nil means DefaultUtilityDailyLimit.
	UtilityDailyLimit *int `json:"utility_daily_limit,omitempty"`
	// UtilityUnlimited lifts the daily limit: Utility calls are not counted
	// against UtilityDailyLimit, which is kept for when it is turned off.
	UtilityUnlimited bool `json:"utility_unlimited,omitempty"`
	// SuggestReplies, when false, stops suggesting replies after a turn;
	// absent means on.
	SuggestReplies *bool `json:"suggest_replies,omitempty"`
	// CompactionThreshold is the share of the context, in percent, at which
	// a Task's conversation starts compacting, MinCompactionThreshold to
	// MaxCompactionThreshold; nil means the provider default
	// (DefaultCompactionThreshold).
	CompactionThreshold *int `json:"compact_threshold,omitempty"`
	// GitHubMCP lets Tasks start the provider's built-in GitHub MCP server.
	// Off when absent.
	GitHubMCP bool `json:"github_mcp,omitempty"`
	// ThreadMessages lets Threads message each other (uam_send). Off when
	// absent.
	ThreadMessages bool `json:"thread_messages,omitempty"`
	// GitLabAutoInvestigate starts an investigation when a Task's own
	// GitLab pipeline fails. Off when absent.
	GitLabAutoInvestigate bool `json:"gitlab_auto_investigate,omitempty"`
	// GitLabMRPrompt is the instructions for pull and merge requests, which
	// also write GitLab merge request descriptions; the built-in ones when
	// empty.
	GitLabMRPrompt string `json:"gitlab_mr_prompt,omitempty"`
	// CommitPrompt is the instructions for commit messages; the built-in
	// ones when empty.
	CommitPrompt string `json:"commit_prompt,omitempty"`
	// OutputStyles is the owner's library of response styles, by unique
	// name; OutputStyle names the default one, "" for the provider's own.
	OutputStyles []WebOutputStyle `json:"output_styles,omitempty"`
	OutputStyle  string           `json:"output_style,omitempty"`
	// CoAuthor is the co-author trailer of agents' commits. Off when absent.
	CoAuthor WebCoAuthor `json:"coauthor,omitzero"`
	// WorktreesDir is the absolute folder new Thread worktrees go in;
	// ~/.uam/worktrees when empty.
	WorktreesDir string `json:"worktrees_dir,omitempty"`
	// WorktreeRoots are the folders new worktrees went in before
	// WorktreesDir last changed; the worktrees left there are still listed.
	WorktreeRoots []string `json:"worktree_roots,omitempty"`
	// DrawIO is the opt-in draw.io editor: its origin and whether it is
	// enabled. Unset when absent.
	DrawIO WebDrawIO `json:"drawio,omitzero"`
	// contains filtered or unexported fields
}

WebSettings are the web interface's settings. The zero value writes no web_settings key.

func (WebSettings) MarshalJSON added in v0.8.0

func (w WebSettings) MarshalJSON() ([]byte, error)

func (*WebSettings) UnmarshalJSON added in v0.8.0

func (w *WebSettings) UnmarshalJSON(data []byte) error

type WebState added in v0.8.0

type WebState struct {
	// NativeChanges records capture requested before this Task's first turn.
	// It is not inferred when an older/imported conversation is resumed.
	NativeChanges bool `json:"native_changes,omitempty"`
	// Turn is the last known session state (for example "working" or
	// "completed").
	Turn        string       `json:"turn,omitempty"`
	TurnTimings []TurnTiming `json:"turn_timings,omitempty"`
	// RequestID is the client-generated ID of the last prompt submission.
	RequestID string `json:"request_id,omitempty"`
	// RequestStatus is that submission's outcome: accepted, rejected or
	// uncertain.
	RequestStatus      string          `json:"request_status,omitempty"`
	CommandResult      json.RawMessage `json:"command_result,omitempty"`
	CommandSubmissions json.RawMessage `json:"command_submissions,omitempty"`
	UpdatedAt          time.Time       `json:"updated_at"`
	// Detail is a sanitized, short explanation of the state (usually an error).
	Detail string `json:"detail,omitempty"`
	// ProjectID is the WebProject the session (a Task) belongs to.
	ProjectID string `json:"project_id,omitempty"`
	// Model is the selected model ID; empty means the provider default.
	Model       string `json:"model,omitempty"`
	Effort      string `json:"effort,omitempty"`
	ContextSize string `json:"context_size,omitempty"`
	// Agent is the ID of the selected custom agent; empty means the
	// provider's default agent.
	Agent string `json:"agent,omitempty"`
	// OutputStyle names the Thread's own style; "" uses its Project's.
	OutputStyle string `json:"output_style,omitempty"`
	// Title is the provider-generated conversation title, sanitized and
	// bounded.
	Title string `json:"title,omitempty"`
	// Stage is the Task's lifecycle stage: "" (active), "settled" or
	// "archived". Records written before stages existed are active.
	Stage string `json:"stage,omitempty"`
	// SettledAt is when the Task was settled; zero unless it is settled, or
	// was settled before it was archived.
	SettledAt time.Time `json:"settled_at,omitzero"`
	// SettledBy is "auto" when the Task settled itself after a quiet week,
	// "merged" when it did once its branch landed on the default branch,
	// "reviewed" when an older version settled it once the owner saw a reply
	// checked done; empty when the owner settled it.
	SettledBy string `json:"settled_by,omitempty"`
	// ArchivedAt is when the Task was archived.
	ArchivedAt time.Time `json:"archived_at,omitzero"`
	// TerminalSession is the ID of the terminal session record tied to the
	// same provider conversation when the Task was imported. That record
	// stays the terminal's.
	TerminalSession string `json:"terminal_session,omitempty"`
	// Imported marks a conversation created outside this web service.
	Imported bool `json:"imported,omitempty"`
	// SpawnedBy is the ID of the Task whose uam_create_task call created
	// this one; empty for a Task the owner created or imported.
	SpawnedBy string `json:"spawned_by,omitempty"`
	// RoutineID is the routine whose run created this Task; empty
	// otherwise.
	RoutineID string `json:"routine_id,omitempty"`
	// RerunOf is the ID of the Task whose last message this one runs again
	// (Run again, Try with another model); empty otherwise.
	RerunOf string `json:"rerun_of,omitempty"`
	// Fork records a native prefix branch separately from a last-message rerun.
	Fork *ForkLineage `json:"fork,omitempty"`
	// Rewind is the latest native history rewind receipt.
	Rewind *WebRewind `json:"rewind,omitempty"`
	// Outcome is the one-line summary of the last completed turn.
	Outcome string `json:"outcome,omitempty"`
	// Suggestions are the replies suggested after the last completed turn.
	Suggestions *WebSuggestions `json:"suggestions,omitempty"`
	// SubagentLabels are the Utility model's short names of the Thread's
	// subagents, by agent ID.
	SubagentLabels map[string]string `json:"subagent_labels,omitempty"`
	// UnseenEnd marks a Task that failed or was interrupted while no page
	// showed it, and that no page has opened since.
	UnseenEnd bool `json:"unseen_end,omitempty"`
	// InterruptedAt is when uam's own stop interrupted the Thread's turn,
	// while it stays interrupted; zero otherwise, also after a crash.
	InterruptedAt time.Time `json:"interrupted_at,omitzero"`
	// StopReason says why the last turn was cancelled (owner, time_limit,
	// credit_limit, budget, remote or mcp); empty otherwise.
	StopReason string `json:"stop_reason,omitempty"`
	// FailureKind is the provider's category for the error that failed the
	// last turn (an agentapi.ErrorKind); empty otherwise.
	FailureKind string `json:"failure_kind,omitempty"`
	// Budget is the owner's spending limit for the Thread; nil without one.
	Budget *Budget `json:"budget,omitempty"`
	// Handoff is what the Thread left for whoever continues its work when it
	// reached its budget; nil without one, and cleared by its next turn.
	Handoff *WebHandoff `json:"handoff,omitempty"`
	// MemoryNotes are the Thread's notes uam re-pins after a compaction:
	// verbatim quotes of its conversation the Utility model picked.
	MemoryNotes []WebMemoryNote `json:"memory_notes,omitempty"`
	// Place is the branch or worktree the Thread was started in; nil for a
	// Thread on its Project's current branch.
	Place *WebPlace `json:"place,omitempty"`
	// Context is the conversation's last context usage report, kept so a
	// reopened Thread shows it until the next one; nil before the first.
	Context *WebContext `json:"context,omitempty"`
	// NativePaths is the latest read of the conversation's native session
	// diff, kept so a closed Thread's Settle guard and file links still know
	// the files only that diff lists after a restart; nil before the first.
	NativePaths *WebNativePaths `json:"native_paths,omitempty"`
	// MessageOutcomes are the messages to or from the Thread that were not
	// delivered because settling or archiving one of the pair dropped their
	// pair, oldest first; the other Thread keeps the same records.
	MessageOutcomes []WebPeerMessage `json:"message_outcomes,omitempty"`
	// Queue is the owner's prompts that wait for the Thread's turn, oldest
	// first, as the web service holds them: the text, the files and stored
	// attachments by reference, and the settings chosen when each was queued.
	Queue json.RawMessage `json:"queue,omitempty"`
	// contains filtered or unexported fields
}

WebState is the small durable part of a web session. Transcripts stay with the provider; lifecycle metadata and request outcomes survive a service restart.

func (WebState) MarshalJSON added in v0.8.0

func (w WebState) MarshalJSON() ([]byte, error)

func (*WebState) UnmarshalJSON added in v0.8.0

func (w *WebState) UnmarshalJSON(data []byte) error

func (*WebState) Update added in v0.8.0

func (w *WebState) Update(v WebState)

Update sets every field this version models to v's and keeps the fields a newer uam wrote, so a writer never drops them.

type WebSuggestions added in v0.13.0

type WebSuggestions struct {
	ItemID  string   `json:"item_id"`
	Replies []string `json:"replies"`
}

WebSuggestions are the replies suggested to the owner once the Task's main transcript ended with the item ItemID; Replies may be empty when none came. They are kept so the same state is never asked for again.

type WebTaskDefaults added in v0.8.0

type WebTaskDefaults struct {
	Provider    string `json:"provider"`
	Model       string `json:"model"`
	Effort      string `json:"effort"`
	ContextSize string `json:"context_size"`
	Mode        string `json:"mode"`
}

WebTaskDefaults are the settings a new Task starts with, shared by every browser. ContextSize is "default" unless a tier is chosen; Mode is safe or yolo. The zero value means unset: the browser then starts from the provider's own defaults.

type WebTokenPrice added in v0.14.0

type WebTokenPrice struct {
	Input      *float64 `json:"input"`
	Output     *float64 `json:"output"`
	CacheRead  *float64 `json:"cache_read,omitempty"`
	CacheWrite *float64 `json:"cache_write,omitempty"`
}

WebTokenPrice is an estimate in USD per million tokens. Input and output are required, including explicit zero prices. Cache rates are optional; absent cache rates use the input price.

func (WebTokenPrice) Valid added in v0.14.0

func (p WebTokenPrice) Valid() bool

Jump to

Keyboard shortcuts

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