Documentation
¶
Overview ¶
Package repos stores explicitly registered local clones and repository settings.
Index ¶
- Constants
- Variables
- func Path() (string, error)
- func ValidateTimeLimit(minutes int) error
- type AppearancePreferences
- type Clone
- type CurrentName
- type DecisionPreferences
- type PlanUsagePreferences
- type Preferences
- func (p Preferences) Concurrency() int
- func (p Preferences) Covers(authored, requested bool) bool
- func (p Preferences) Resolve(global config.Config) config.Config
- func (p Preferences) ResolveExtraction(cfg config.Config) config.Config
- func (p Preferences) ResolveFix(review config.Config) config.Config
- func (p Preferences) Validate() error
- func (p Preferences) ValidateChange(prev Preferences) error
- type PromptEntry
- type PromptOverride
- type PromptSafetyRule
- type PromptSource
- type Registry
- func (r *Registry) Add(ctx context.Context, path string, settings *Settings) (Clone, error)
- func (r *Registry) AddFor(ctx context.Context, path, repository string, settings *Settings) (Clone, error)
- func (r *Registry) AddForwarded(ctx context.Context, path, repository, alias string, settings *Settings) (Clone, error)
- func (r *Registry) AddPatch(ctx context.Context, path string, edit func(Settings) (Settings, error)) (Clone, error)
- func (r *Registry) AttachFound(ctx context.Context, path, repository string) (Clone, error)
- func (r *Registry) CloneRows(ctx context.Context) ([]Clone, error)
- func (r *Registry) Close() error
- func (r *Registry) DeletePromptOverride(ctx context.Context, repository string, id prompt.ID) error
- func (r *Registry) Handler() http.Handler
- func (r *Registry) HandlerWith(current CurrentName) http.Handler
- func (r *Registry) List(ctx context.Context) ([]Clone, error)
- func (r *Registry) Pick(ctx context.Context, repository string, settings *Settings) (Repository, error)
- func (r *Registry) PickedWithoutClones(ctx context.Context) ([]string, error)
- func (r *Registry) Preferences(ctx context.Context) (Preferences, error)
- func (r *Registry) PromptEntries(ctx context.Context, repository string) ([]PromptEntry, error)
- func (r *Registry) PromptOverrides(ctx context.Context, repository string) (map[prompt.ID]PromptOverride, error)
- func (r *Registry) RecheckAliases(ctx context.Context, repository string, ...) (unconfirmed []string, err error)
- func (r *Registry) Remove(ctx context.Context, idOrPath string) error
- func (r *Registry) Repositories(ctx context.Context) ([]Repository, error)
- func (r *Registry) RepositoryRows(ctx context.Context) ([]Repository, error)
- func (r *Registry) RepositorySettings(ctx context.Context, repository string) (Settings, bool, error)
- func (r *Registry) ResolvePrompts(ctx context.Context, repository string) (prompt.Overrides, map[prompt.ID]PromptSource, error)
- func (r *Registry) ServePromptPut(w http.ResponseWriter, req *http.Request, repository, id string)
- func (r *Registry) ServePrompts(w http.ResponseWriter, req *http.Request, repository string)
- func (r *Registry) SetPromptOverride(ctx context.Context, repository string, id prompt.ID, text string) (PromptOverride, error)
- func (r *Registry) Unpick(ctx context.Context, repository string) error
- func (r *Registry) Update(ctx context.Context, id string, s Settings) error
- func (r *Registry) UpdatePreferences(ctx context.Context, edit func(Preferences) Preferences) (Preferences, error)
- func (r *Registry) UpdateRepository(ctx context.Context, repository string, s Settings) error
- type RemoteMismatchError
- type Repository
- type Settings
Constants ¶
const ( PullRequestsAuthored = "authored" PullRequestsRequested = "requested" // PullRequestsAll covers every open pull request in the repository. PullRequestsAll = "all" )
The PullRequests choices besides both.
const GlobalPrompts = ""
GlobalPrompts is the repository argument naming the global scope.
const MaxJobConcurrency = 4
MaxJobConcurrency is the most jobs the daemon runs at once besides questions to a review's agent, and the default. A person lowers it when parallel agents load the computer too much.
const MaxTimeLimit = 240
MaxTimeLimit is the longest time limit, in minutes, the app sets.
const ProbeMaxAge = 5 * time.Minute
ProbeMaxAge bounds how long a clone's availability is reused while nothing it is read from changed: a change only global git configuration makes, such as a url.insteadOf rewrite, shows within this time.
Variables ¶
var ( // ErrNotPicked reports a repository that is not picked. ErrNotPicked = errors.New("repository is not picked") // ErrClonedElsewhere reports a working tree, or a repository directory, // already registered to another repository. ErrClonedElsewhere = errors.New("clone is registered to another repository") )
Errors of AttachFound.
var ErrInvalidPrompt = errors.New("invalid prompt")
ErrInvalidPrompt wraps the reason prompt.Validate (or an unknown id) rejected a custom prompt, fit to show the author; a host maps it to 400.
var ErrInvalidRepository = errors.New("repository must be a github.com owner/name")
ErrInvalidRepository reports a name that is not a github.com owner/name.
var ErrNoMatchingRemote = errors.New("working tree has no remote for that repository")
ErrNoMatchingRemote reports a working tree none of whose GitHub remotes names the requested repository.
var ErrNotFound = errors.New("registered clone or picked repository not found")
ErrNotFound reports a clone or picked repository the registry does not hold.
var ErrNotWorkingTree = errors.New("path is unavailable or is not a git working tree")
ErrNotWorkingTree reports a path that is missing or not in a git working tree.
Functions ¶
func ValidateTimeLimit ¶
ValidateTimeLimit accepts zero (the config file's) or 1 to MaxTimeLimit minutes.
Types ¶
type AppearancePreferences ¶
type AppearancePreferences struct {
Theme string `json:"theme,omitempty"`
KeyHints *bool `json:"key_hints,omitempty"`
// PageModifier is the key held with 1 to 8 to open the sidebar's pages:
// "meta", "ctrl" or "alt"; empty is the platform's command key.
PageModifier string `json:"page_modifier,omitempty"`
}
AppearancePreferences are device choices kept independently of the daemon HTTP origin.
type Clone ¶
type CurrentName ¶
CurrentName is the lower-case owner/name a github.com repository has now; the daemon asks GitHub, which answers an earlier name it forwards with the current one. The registry itself contacts nothing.
type DecisionPreferences ¶
type DecisionPreferences struct {
Enabled *bool `json:"enabled,omitempty"`
Backend *config.Backend `json:"backend,omitempty"`
Model *string `json:"model,omitempty"`
Effort *string `json:"effort,omitempty"`
}
DecisionPreferences are the global choices for local decision capture and the feature log, the data extraction the app's settings name. A nil Enabled is on. A nil Backend follows the reviews' backend. Model, when set, replaces the backend's default decision model. Effort is the reasoning effort (config.Efforts), empty or nil for the harness's own.
type PlanUsagePreferences ¶
PlanUsagePreferences are the plans the person chose to show or hide in plan usage, by provider ("claude", "codex"). A provider with no entry follows the backends baum uses, so a choice survives backend changes.
type Preferences ¶
type Preferences struct {
// Automatic is the default for repositories without an explicit choice.
Automatic bool `json:"automatic"`
// Backend and Model, when set, replace the config file's for generation
// in the app; a repository's own settings still override them.
Backend *config.Backend `json:"backend,omitempty"`
Model *string `json:"model,omitempty"`
// Effort is the reviews' reasoning effort (config.Efforts), empty or nil
// for the harness's own.
Effort *string `json:"effort,omitempty"`
// FixBackend, FixModel and FixEffort choose the agent that fixes pull
// requests (ResolveFix). A nil FixBackend means the same as reviews; an
// empty FixModel is the fix backend's default model and an empty
// FixEffort its own effort.
FixBackend *config.Backend `json:"fix_backend,omitempty"`
FixModel *string `json:"fix_model,omitempty"`
FixEffort *string `json:"fix_effort,omitempty"`
// PullRequests narrows which pull requests get automatic reviews:
// PullRequestsAuthored, PullRequestsRequested, PullRequestsAll, or empty
// for both authored and requested.
PullRequests string `json:"pull_requests,omitempty"`
// AgentEnv, when it sets any variable, replaces the config file's
// agent_env (config.Config.AgentEnv).
AgentEnv map[string]string `json:"agent_env,omitempty"`
// Appearance survives daemon restarts and changes to its loopback origin.
Appearance AppearancePreferences `json:"appearance,omitzero"`
// Decisions configures local decision capture.
Decisions DecisionPreferences `json:"decisions,omitzero"`
// PlanUsage chooses which plans plan usage shows.
PlanUsage PlanUsagePreferences `json:"plan_usage,omitzero"`
// JobConcurrency, when set, is how many jobs the daemon runs at once
// besides questions to a review's agent; Concurrency resolves it.
JobConcurrency int `json:"job_concurrency,omitempty"`
// ReviewTimeLimit and RunTimeLimit, in minutes, when set replace the
// config file's review_timeout and run_timeout (Resolve): how long a
// review, and any other agent run, may take.
ReviewTimeLimit int `json:"review_time_limit_minutes,omitempty"`
RunTimeLimit int `json:"run_time_limit_minutes,omitempty"`
}
Preferences are the registry's global choices, edited in the app. Fields an older baum saved and this one dropped, such as cursor_agent_acknowledged, are ignored on read and gone after the next write.
func DefaultPreferences ¶
func DefaultPreferences() Preferences
DefaultPreferences apply until the user changes them: automatic generation on.
func (Preferences) Concurrency ¶
func (p Preferences) Concurrency() int
Concurrency is how many jobs run at once: JobConcurrency, or MaxJobConcurrency when it is unset or out of range (a hand edit, or a newer baum's).
func (Preferences) Covers ¶
func (p Preferences) Covers(authored, requested bool) bool
Covers reports whether automatic reviews cover a pull request the viewer authored or was asked to review, as PullRequests chooses.
func (Preferences) Resolve ¶
func (p Preferences) Resolve(global config.Config) config.Config
Resolve overlays the app's backend, model, agent environment and time limits on the config file's.
func (Preferences) ResolveExtraction ¶
func (p Preferences) ResolveExtraction(cfg config.Config) config.Config
ResolveExtraction gives the config data extraction runs with, from cfg, the config resolved for reviews: the extraction's own effort. Its backend and model are decisionlog's to resolve.
func (Preferences) ResolveFix ¶
func (p Preferences) ResolveFix(review config.Config) config.Config
ResolveFix gives the config a fix runs with, from review, the config already resolved for reviews. A set FixBackend replaces the review backend, model and effort, and takes FixModel and FixEffort (empty for the backend's own); without one the fix follows the reviews.
func (Preferences) Validate ¶
func (p Preferences) Validate() error
Validate accepts an empty Model, unlike Settings: it means the backend's default even when the config file names a model.
func (Preferences) ValidateChange ¶
func (p Preferences) ValidateChange(prev Preferences) error
ValidateChange is Validate for preferences saved over prev: the desktop app offers Claude Code and Codex only, so a backend chosen now must be one of them. A retired backend already stored (cursor-agent or anthropic, from a pre-release version) does not block saving other settings; the daemon refuses the jobs that use it.
type PromptEntry ¶ added in v0.2.0
type PromptEntry struct {
ID string `json:"id"`
Title string `json:"title"`
Group string `json:"group"`
UsedBy string `json:"used_by"`
DefaultText string `json:"default_text"`
DefaultVersion string `json:"default_version"`
CustomText *string `json:"custom_text"`
BasedOn *string `json:"based_on"`
Outdated bool `json:"outdated"`
// Invalid marks a stored text that no longer passes validation: it is
// shown but not used by runs.
Invalid bool `json:"invalid"`
InvalidReason *string `json:"invalid_reason"`
SafetyRules []PromptSafetyRule `json:"safety_rules"`
MissingRules []string `json:"missing_safety_rules"`
Source PromptSource `json:"source,omitempty"`
InheritedText *string `json:"inherited_text,omitempty"`
}
PromptEntry is one catalogue prompt as the app shows it in a scope: the global one, or one repository's (then Source and InheritedText are set).
type PromptOverride ¶ added in v0.2.0
type PromptOverride struct {
ID prompt.ID
Text string
// BasedOn is the built-in version (Entry.DefaultVersion) current when the
// text was saved, so a later change of the built-in can be flagged.
BasedOn string
UpdatedAt time.Time
}
PromptOverride is a custom prompt text stored locally for one scope.
type PromptSafetyRule ¶ added in v0.2.0
type PromptSafetyRule struct {
ID string `json:"id"`
Label string `json:"label"`
Text string `json:"text"`
}
PromptSafetyRule is a safety rule of a prompt, for display.
type PromptSource ¶ added in v0.2.0
type PromptSource string
PromptSource says where a prompt's effective text comes from.
const ( PromptSourceDefault PromptSource = "default" PromptSourceGlobal PromptSource = "global" PromptSourceRepository PromptSource = "repository" )
type Registry ¶
type Registry struct {
// Registered, when set, is called with each clone a registration stored
// (Add, AddFor, AddForwarded and AttachFound), after it is stored. It
// must not block: the daemon uses it to start work on the new clone. A
// registry the CLI opens has none.
Registered func(Clone)
// Removed, when set, is called with each clone Remove or Unpick deleted,
// after it is deleted, and must not block.
Removed func(Clone)
// contains filtered or unexported fields
}
func OpenReadOnly ¶
OpenReadOnly opens an existing registry only to list it. Unlike Open it creates no directory, database or table and changes no file mode, and SQLite opens the file read-only, so it never writes it. In WAL mode SQLite creates its -shm and -wal coordination files beside the database when missing (see appdb.Open). A missing file is an error wrapping fs.ErrNotExist; a file without tables lists no clones.
func (*Registry) Add ¶
Add registers an existing clone. Nil settings preserve existing settings; explicit settings replace the settings shared by all its repository's clones.
func (*Registry) AddFor ¶
func (r *Registry) AddFor(ctx context.Context, path, repository string, settings *Settings) (Clone, error)
AddFor registers an existing clone for repository (github.com owner/name) when any of its GitHub remotes names it, not only origin: a fork clone whose upstream remote is the repository is filed under the repository, and the fork's own repository is neither registered nor picked. It fails with ErrNoMatchingRemote when no remote names the repository. Settings are as for Add.
func (*Registry) AddForwarded ¶
func (r *Registry) AddForwarded(ctx context.Context, path, repository, alias string, settings *Settings) (Clone, error)
AddForwarded registers a clone for repository, as AddFor does, whose remote uses alias, an earlier name GitHub forwards to repository, which the caller has checked. The alias is recorded first: from then on remote URLs using it read as repository (gitlocal.RenamedTo), so the clone stays a clone of repository everywhere, until RecheckAliases finds GitHub no longer forwards it.
func (*Registry) AddPatch ¶
func (r *Registry) AddPatch(ctx context.Context, path string, edit func(Settings) (Settings, error)) (Clone, error)
AddPatch atomically registers a clone and applies a settings edit. The edit runs under the writer transaction, so omitted fields cannot lose another process's concurrent edits. It must not call back into the registry.
func (*Registry) AttachFound ¶
AttachFound registers a clone the daemon found for a picked repository, as AddFor does, but never changes what is already stored: it fails with ErrNotPicked unless the repository is picked (checked in the same transaction, so an unpick in between is not undone) and with ErrClonedElsewhere when the path or its repository directory is registered to another repository, which AddFor would move.
func (*Registry) CloneRows ¶
CloneRows lists the registered clones exactly as stored, without probing them: Available is false throughout. It runs no git.
func (*Registry) DeletePromptOverride ¶ added in v0.2.0
DeletePromptOverride removes the override of id for a scope; a missing one is not an error. An unknown id fails with ErrInvalidPrompt and a non-empty repository must be picked (ErrNotPicked).
func (*Registry) Handler ¶
Handler exposes the registry API for the future local UI host. It does not listen or authenticate: the host MUST mount it behind its authenticated, host/origin-checked middleware. Never mount this on the public view server.
func (*Registry) HandlerWith ¶
func (r *Registry) HandlerWith(current CurrentName) http.Handler
HandlerWith is Handler, also registering a folder for a repository when its remote uses an earlier name that current reports GitHub forwards to it.
func (*Registry) Pick ¶
func (r *Registry) Pick(ctx context.Context, repository string, settings *Settings) (Repository, error)
Pick registers a github.com repository by owner/name without a local clone. Nil settings keep the existing settings, or the default for a new repository; explicit settings replace them. Picking again is a no-op.
func (*Registry) PickedWithoutClones ¶
PickedWithoutClones lists the picked repositories that have no clone registered. It reads the registry only and runs no git, so it is cheap enough to ask for every hook event.
func (*Registry) Preferences ¶
func (r *Registry) Preferences(ctx context.Context) (Preferences, error)
Preferences reads the global preferences: DefaultPreferences until saved.
func (*Registry) PromptEntries ¶ added in v0.2.0
PromptEntries builds the entries of a scope ("" is global), one per catalogue id in catalogue order. custom_text, based_on and outdated come from that scope's own rows. For a repository, inherited_text is the global override's text, else the built-in text, and source says which text a run uses. The repository must be picked (ErrNotPicked).
func (*Registry) PromptOverrides ¶ added in v0.2.0
func (r *Registry) PromptOverrides(ctx context.Context, repository string) (map[prompt.ID]PromptOverride, error)
PromptOverrides reads the overrides stored for one scope: repository "" is the global scope. A database without the table has none.
func (*Registry) RecheckAliases ¶
func (r *Registry) RecheckAliases(ctx context.Context, repository string, current func(context.Context, github.Repository) (string, error)) (unconfirmed []string, err error)
RecheckAliases asks GitHub (current) again about the recorded earlier names of repository, or of every repository when it is "", and drops each one it now answers with another repository than the recorded one does, as when a new repository took the name: remotes using it then name that one. One it could not check or does not show the token is kept, and returned as unconfirmed: a repository the token cannot see may have taken it.
func (*Registry) Repositories ¶
func (r *Registry) Repositories(ctx context.Context) ([]Repository, error)
Repositories lists every picked repository by identity, with its clones probed for availability as List does.
func (*Registry) RepositoryRows ¶
func (r *Registry) RepositoryRows(ctx context.Context) ([]Repository, error)
RepositoryRows is Repositories without probing the clones: Available is false throughout. It runs no git.
func (*Registry) RepositorySettings ¶
func (r *Registry) RepositorySettings(ctx context.Context, repository string) (Settings, bool, error)
RepositorySettings reads one repository's shared settings without probing its clones; false means the repository is not picked.
func (*Registry) ResolvePrompts ¶ added in v0.2.0
func (r *Registry) ResolvePrompts(ctx context.Context, repository string) (prompt.Overrides, map[prompt.ID]PromptSource, error)
ResolvePrompts picks, for every catalogue prompt, the repository's override, else the global one, else the built-in text. Overrides holds only the overridden prompts; sources has every catalogue id. A repository that is not picked (or "") gets only the global overrides: its rows, kept after an unpick, apply again once it is picked. Stored texts that fail prompt.Validate are skipped. Pass the repository's current lower-case name; earlier alias names are not followed.
func (*Registry) ServePromptPut ¶ added in v0.2.0
ServePromptPut answers PUT .../prompts/{id} for a scope ("" is global): it stores the text, or resets the prompt for null or "", and answers the updated entry. An unknown id and an unpicked repository are 404, a body that is too large 413, a malformed one (unknown or missing fields, trailing data) or an invalid text 400, each with {"message": ...}.
func (*Registry) ServePrompts ¶ added in v0.2.0
ServePrompts answers GET .../prompts for a scope ("" is global) with {"prompts": [...]}; an unpicked repository is a 404.
func (*Registry) SetPromptOverride ¶ added in v0.2.0
func (r *Registry) SetPromptOverride(ctx context.Context, repository string, id prompt.ID, text string) (PromptOverride, error)
SetPromptOverride validates and stores text as the override of id for a scope ("" is global), recording the current built-in version as BasedOn. A non-empty repository must be picked (ErrNotPicked). A rejected text fails with an error wrapping ErrInvalidPrompt.
func (*Registry) Unpick ¶
Unpick removes a picked repository's clones and its picked row. The repositories row stays, as in Remove, so its settings survive a later pick.
func (*Registry) Update ¶
Update replaces shared repository settings without needing an available clone.
func (*Registry) UpdatePreferences ¶
func (r *Registry) UpdatePreferences(ctx context.Context, edit func(Preferences) Preferences) (Preferences, error)
UpdatePreferences atomically edits the global preferences. The edit runs under the writer transaction and must not call back into the registry.
type RemoteMismatchError ¶
type RemoteMismatchError struct {
Repository string
Remotes []string
// Unchecked is set when GitHub could not be asked whether a remote uses
// an earlier name of Repository.
Unchecked bool
}
RemoteMismatchError is ErrNoMatchingRemote, naming the repositories the working tree's GitHub remotes name instead, origin's first; none when it has no GitHub remote.
func (*RemoteMismatchError) Error ¶
func (e *RemoteMismatchError) Error() string
func (*RemoteMismatchError) Is ¶
func (e *RemoteMismatchError) Is(target error) bool
type Repository ¶
type Repository struct {
Repository string `json:"repository"`
Settings Settings `json:"settings"`
Clones []Clone `json:"clones"`
// EarlierNames are recorded names GitHub forwards to the repository that
// a clone's remote still uses, read from the clones' configuration on
// each listing (AddForwarded records them).
EarlierNames []string `json:"earlier_names,omitempty"`
}
Repository is a picked repository with its settings and registered clones, of which there may be none.
type Settings ¶
type Settings struct {
Automatic *bool `json:"automatic"`
// Decisions is the repository's choice for local decision capture under
// the global switches (see DecisionsEnabled): nil and true follow them,
// false turns the repository off.
Decisions *bool `json:"decisions,omitempty"`
}
Settings are shared by all clones of a repository. Automatic is the repository's choice under the global master switch (see AutomaticEnabled): nil follows it, false turns the repository off, true is an explicit on that still stops while the global switch is off. Registration itself starts no generation. A daily_cap, backend or model an older baum stored is ignored on read and dropped on the next write: baum sets no spending limits, since it cannot price what a subscription bills, and the harnesses and models are global (Preferences).
func (Settings) AutomaticEnabled ¶
func (s Settings) AutomaticEnabled(p Preferences) bool
AutomaticEnabled reports whether the daemon generates reviews of this repository automatically. The global preference is a master switch: off stops every repository, whatever its choice; on, only an explicit false turns a repository off.
func (Settings) DecisionsEnabled ¶
func (s Settings) DecisionsEnabled(p Preferences) bool
DecisionsEnabled reports whether the daemon captures the decisions of this repository's agent sessions: the automatic master switch (which the tray's pause turns off) and the decisions switch are both on, and the repository has not turned capture off.