Documentation
¶
Overview ¶
Package harness detects, installs, updates, and logs in to the vendor agent CLIs, and lists their models. The vendor facts come from agent-wire.
Index ¶
- Variables
- type AuthMode
- type AuthState
- type Facts
- type FileContent
- type Harness
- type HomeFile
- type Launch
- type LimitWindow
- type Limits
- type Login
- type LoginPhase
- type LoginSpec
- type Manager
- func (m *Manager) Busy() bool
- func (m *Manager) CancelLogin(ctx context.Context, name string)
- func (m *Manager) Check(ctx context.Context)
- func (m *Manager) Close(ctx context.Context) error
- func (m *Manager) Files(ctx context.Context, name string) ([]HomeFile, error)
- func (m *Manager) Harness(ctx context.Context, name string) (Harness, error)
- func (m *Manager) Install(ctx context.Context, name, version string) (Harness, error)
- func (m *Manager) Launch(ctx context.Context, name string) (Launch, error)
- func (m *Manager) List(ctx context.Context) ([]Harness, error)
- func (m *Manager) Login(ctx context.Context, name string, spec LoginSpec) (Login, error)
- func (m *Manager) LoginCode(ctx context.Context, name, code string) (Login, error)
- func (m *Manager) LoginState(name string) (Login, bool)
- func (m *Manager) LoginToken(ctx context.Context, name, token string) (Harness, error)
- func (m *Manager) Logout(ctx context.Context, name string) error
- func (m *Manager) Models(ctx context.Context, name string) ([]Model, error)
- func (m *Manager) OwnFile(ctx context.Context, name, key string, start OwnStart) (HomeFile, error)
- func (m *Manager) ReadFile(ctx context.Context, name, key, side string) (FileContent, error)
- func (m *Manager) Run(ctx context.Context)
- func (m *Manager) SetAuthMode(ctx context.Context, name string, mode AuthMode) (Harness, error)
- func (m *Manager) SetEnv(_ context.Context, name string, env map[string]string) error
- func (m *Manager) SetLimits(ctx context.Context, name string, l Limits)
- func (m *Manager) SetUpdates(ctx context.Context, name string, mode UpdateMode, version string) (Harness, error)
- func (m *Manager) ShareFile(ctx context.Context, name, key string) (HomeFile, error)
- func (m *Manager) TrustDir(name, dir string) error
- func (m *Manager) Update(ctx context.Context, name, version string) (Harness, error)
- func (m *Manager) WriteFile(ctx context.Context, name, key, content, ifMatch string) (FileContent, error)
- type Model
- type Options
- type OwnStart
- type Policy
- type Source
- type Terminal
- type Update
- type UpdateMode
- type Wire
Constants ¶
This section is empty.
Variables ¶
var ( // ErrStale is a write with an old etag. ErrStale = errors.New("harness: the file changed since the read") // ErrNoBackup means that no backup of the own copy exists. ErrNoBackup = errors.New("harness: no backup") )
Home file errors.
var ( ErrNotFound = errors.New("harness: not found") ErrInvalid = errors.New("harness: invalid request") ErrState = errors.New("harness: wrong state") ErrBusy = errors.New("harness: busy") ErrUnsupported = errors.New("harness: not supported") )
Errors.
Functions ¶
This section is empty.
Types ¶
type Facts ¶
type Facts struct {
Recipe func(h agentwire.Harness) (agentwire.InstallRecipe, bool)
LoginCommand func(h agentwire.Harness, o agentwire.LoginOptions) ([]string, error)
LogoutCommand func(h agentwire.Harness) []string
LoginEnv func(h agentwire.Harness, home string) map[string]string
CredentialFiles func(h agentwire.Harness) []string
AuthStatus func(ctx context.Context, h agentwire.Harness, home string) (agentwire.AuthState, error)
// Binary finds the program of a harness that agent-wire does not find,
// such as a test harness of the product. Nil finds none.
Binary func(h agentwire.Harness) string
}
Facts are the vendor facts with no runtime. A nil field uses agent-wire. Tests replace them.
type FileContent ¶ added in v0.2.0
type FileContent struct {
Key string `json:"key"`
Side string `json:"side"`
Content string `json:"content"`
ETag string `json:"etag"`
}
FileContent is the content of one side of a home file.
type Harness ¶
type Harness struct {
Name string `json:"name"`
Installed bool `json:"installed"`
Version string `json:"version,omitempty"`
// Latest is the newest vendor release, when known.
Latest string `json:"latest,omitempty"`
Path string `json:"path,omitempty"`
Source Source `json:"source,omitempty"`
// Installs are the versions that the visor installed, oldest first.
Installs []string `json:"installs,omitempty"`
// Installable means that the visor can install its own copy.
Installable bool `json:"installable"`
// Supported means that the installed version meets the agent-wire floor.
Supported bool `json:"supported"`
// Detail tells why the harness is not usable.
Detail string `json:"detail,omitempty"`
AuthMode AuthMode `json:"auth_mode"`
Auth AuthState `json:"auth"`
// EnvKeys lists the harness env keys. The values never leave the visor.
EnvKeys []string `json:"env_keys,omitempty"`
Limits *Limits `json:"limits,omitempty"`
// Updates is the update mode. KeptAt is when keep mode started.
Updates UpdateMode `json:"updates"`
KeptAt *time.Time `json:"kept_at,omitempty"`
// Pending means that an update waits for the end of the live sessions.
Pending bool `json:"pending,omitempty"`
Updating bool `json:"updating,omitempty"`
// History holds the last version changes, oldest first.
History []Update `json:"history,omitempty"`
// Models is the fixed model list. Manager.Models gives the live list.
Models []Model `json:"models,omitempty"`
// Login is the login that runs now, or nil.
Login *Login `json:"login,omitempty"`
}
Harness is one vendor agent CLI on this machine.
type HomeFile ¶ added in v0.2.0
type HomeFile struct {
Key string `json:"key"`
Kind agentwire.HomeFileKind `json:"kind"`
Format string `json:"format,omitempty"`
// its own copy.
Shared bool `json:"shared"`
// Login marks a login file. The auth mode decides its share.
Login bool `json:"login,omitempty"`
// Hooks marks a file that holds user hooks.
Hooks bool `json:"hooks,omitempty"`
// Locked means that the policy or the auth mode decides the share.
Locked bool `json:"locked,omitempty"`
// Blocked means that the home holds a real file where a shared file
// links to the user file. The home uses its own copy until the user
// removes it.
Blocked bool `json:"blocked,omitempty"`
UserPath string `json:"user_path"`
HomePath string `json:"home_path"`
UserExists bool `json:"user_exists"`
UserModAt *time.Time `json:"user_modified_at,omitempty"`
// OwnSince is when the home made its own copy.
OwnSince *time.Time `json:"own_since,omitempty"`
// UserChanged means that the user file changed after OwnSince.
UserChanged bool `json:"user_changed_since_own,omitempty"`
// BackupUntil is when the newest backup of an own copy expires.
BackupUntil *time.Time `json:"backup_until,omitempty"`
}
HomeFile is one file or folder of a harness home that can share the user's own setup.
type Launch ¶
type Launch struct {
// Binary is the visor copy. Empty searches PATH.
Binary string
// Home is the harness home that the visor builds. Empty uses the user
// home of the harness.
Home string
// Env is the harness env layer.
Env map[string]string
// Args are launch args that the harness needs, before the session args.
Args []string
}
Launch is what a session start needs from the harness.
type LimitWindow ¶
type LimitWindow struct {
Key string `json:"key"`
Scope string `json:"scope,omitempty"`
Minutes int `json:"minutes,omitempty"`
UsedPercent float64 `json:"used_percent"`
ResetsAt time.Time `json:"resets_at,omitzero"`
}
LimitWindow is the use of one plan limit window.
type Limits ¶
type Limits struct {
Plan string `json:"plan,omitempty"`
Rejected bool `json:"rejected,omitempty"`
Windows []LimitWindow `json:"windows,omitempty"`
}
Limits is the plan limit state of the account behind a harness.
type Login ¶
type Login struct {
Harness string `json:"harness"`
Phase LoginPhase `json:"phase"`
// URL is the address that the user opens.
URL string `json:"url,omitempty"`
// Code is the device code that the user types on that page.
Code string `json:"code,omitempty"`
// AwaitCode means that the vendor asks for a pasted code. A terminal
// login takes it with LoginCode; a pipe login cannot.
AwaitCode bool `json:"await_code,omitempty"`
// InApp means that the harness logs in only inside its own terminal
// view. No login process runs.
InApp bool `json:"in_app,omitempty"`
Error string `json:"error,omitempty"`
Hint string `json:"hint,omitempty"`
// Session is the terminal session of the login, when the visor runs
// it in a terminal. A client can attach to it.
Session string `json:"session,omitempty"`
// Screen is the end of the login screen.
Screen string `json:"screen,omitempty"`
// Done means that the login process ended.
Done bool `json:"done,omitempty"`
StartedAt time.Time `json:"started_at,omitzero"`
EndedAt time.Time `json:"ended_at,omitzero"`
}
Login is the state of a vendor login. A token that the vendor prints never goes in it.
type LoginPhase ¶ added in v0.2.0
type LoginPhase string
LoginPhase is the step of a login.
const ( LoginStarting LoginPhase = "starting" LoginBrowser LoginPhase = "awaiting_browser" LoginCode LoginPhase = "awaiting_code" LoginVerifying LoginPhase = "verifying" LoginDone LoginPhase = "done" LoginFailed LoginPhase = "failed" )
Login phases.
type LoginSpec ¶ added in v0.2.0
type LoginSpec struct {
// Provider is the model provider of a harness with many providers.
Provider string `json:"provider,omitempty"`
}
LoginSpec asks for a login.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager keeps the harness inventory of one visor.
func (*Manager) CancelLogin ¶ added in v0.2.0
CancelLogin stops a running login.
func (*Manager) Install ¶
Install installs a visor copy of the harness in bin/<name>/<version>/ and moves the current link to it. An empty version is the latest release. A harness with no npm recipe runs the vendor install instead, and gets the latest release. A failed install leaves the current link as it was. It returns ErrBusy when a live session uses the harness, because the switch must not change the binary under a running session.
func (*Manager) Launch ¶
Launch gives what a session of the harness needs. An unknown harness gives the zero Launch, so a session with no inventory entry still starts.
func (*Manager) Login ¶
Login starts the vendor login of the harness, in the login home of its auth mode. It returns when the vendor shows a URL or a code, when the process ends, or after Options.LoginWait. The process runs on until the user ends the login, or until Options.LoginTimeout. A second call while a login runs gives the same login. At the end, the visor checks the login.
func (*Manager) LoginState ¶ added in v0.2.0
LoginState gives the login that runs, or the last one for a minute after its end.
func (*Manager) LoginToken ¶ added in v0.2.0
LoginToken keeps a token or an API key as the login of the harness. It goes into the harness env.
func (*Manager) Logout ¶
Logout runs the vendor logout in the login home of the auth mode. With no vendor logout, a separate login removes its credential files. A token in the harness env goes too.
func (*Manager) Models ¶
Models lists the models of a harness: the live list when the harness gives one, else the fixed list.
func (*Manager) OwnFile ¶ added in v0.2.0
OwnFile makes an own copy of a home file. The copy starts from the user file, from nothing, or from the newest backup.
func (*Manager) ReadFile ¶ added in v0.2.0
ReadFile reads one side of a home file. An empty side is the one that a session uses.
func (*Manager) Run ¶ added in v0.2.0
Run checks the harnesses each minute until ctx ends: it looks for a new release each Options.CheckEvery, records an update outside the visor, and runs the auto and the waiting updates.
func (*Manager) SetAuthMode ¶
SetAuthMode moves the harness to a shared or a separate login. A live session keeps its login; the next session gets the new one.
func (*Manager) SetEnv ¶
SetEnv replaces the env of a harness. An empty env removes it. The file has mode 0600.
func (*Manager) SetUpdates ¶ added in v0.2.0
func (m *Manager) SetUpdates(ctx context.Context, name string, mode UpdateMode, version string) (Harness, error)
SetUpdates sets the update mode. Keep with a version moves to that version first; an empty version keeps the version that runs now.
func (*Manager) ShareFile ¶ added in v0.2.0
ShareFile makes the home use the user file again. An own copy moves to the backups for 30 days.
func (*Manager) TrustDir ¶ added in v0.4.2
TrustDir marks dir as a trusted folder in the separate home of a harness, so that the vendor CLI shows no folder trust dialog there. The start of a session in dir is the approval. A harness with no trust file changes nothing.
func (*Manager) Update ¶
Update updates the harness. A visor copy gets a new visor copy. A system install runs the vendor update, after a copy of the old program. A check after the update needs a version and, when the login worked before, a working login. A failed check goes back to the old program. When a live session uses the harness, the update waits for its end and Update returns ErrBusy.
type Model ¶
type Model struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Default bool `json:"default,omitempty"`
// Efforts are the effort levels, from low to high.
Efforts []string `json:"efforts,omitempty"`
}
Model is one model that a harness offers.
type Options ¶
type Options struct {
// Names are the harnesses that the manager knows. Empty means each
// agent-wire harness with an install recipe.
Names []string
// Path is the search path for the install tools, such as npm. Empty
// uses PATH.
Path string
Facts Facts
// LoginWait is how long Login waits for a URL or a code. Zero is 20 s.
LoginWait time.Duration
// LoginTimeout stops a login that does not end. Zero is 10 min.
LoginTimeout time.Duration
// InUse reports that a live session uses the harness. The visor sets it.
InUse func(name string) bool
// Enabled reports that the visor checks and updates a harness, also a
// binary that the visor did not install. Nil checks only the visor
// copies.
Enabled func(name string) bool
// CheckEvery is the time between two looks for a new release. Zero is
// 6 h.
CheckEvery time.Duration
// Terminal runs the logins in terminal sessions. Nil runs them with a
// pipe, which cannot take a pasted code.
Terminal Terminal
// OnChange gets the name of a harness that changed. The visor sets it.
OnChange func(name string)
// Policy is the product policy for the harness homes.
Policy Policy
// UserHome is the home folder of the user. Empty uses the home of the
// process user.
UserHome string
Logger *slog.Logger
}
Options configures a Manager.
type Policy ¶ added in v0.2.0
type Policy struct {
// MCPServers go into the MCP file of each harness home.
MCPServers []agentwire.MCPServer
// NoUserHooks keeps the user hooks out of the harness homes.
NoUserHooks bool
Share map[string]map[string]bool
// Keys are values that the home files must hold, by harness.
Keys map[string][]agentwire.HomeKey
// Files gives the product files of a harness home, by path relative to
// the home. The visor writes a file when its content changes. The
// function can read the home. It runs on each launch.
Files func(name, home string) map[string][]byte
}
Policy is the product policy for the harness homes.
type Terminal ¶ added in v0.2.0
type Terminal interface {
Start(ctx context.Context, name string, argv []string, dir string, env map[string]string) (string, error)
// Screen gives the screen text and whether the session still runs.
Screen(ctx context.Context, id string) (string, bool, error)
Send(ctx context.Context, id, text string) error
Stop(ctx context.Context, id string) error
}
Terminal runs a login in a terminal session. The visor sets it.
type Update ¶ added in v0.2.0
type Update struct {
At time.Time `json:"at"`
From string `json:"from,omitempty"`
To string `json:"to,omitempty"`
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
// Outside means that the harness changed outside the visor.
Outside bool `json:"outside,omitempty"`
}
Update is one version change of a harness.
type UpdateMode ¶ added in v0.2.0
type UpdateMode string
UpdateMode tells how the visor updates a harness.
const ( // UpdatesAuto updates to each new release when no session uses the // harness. UpdatesAuto UpdateMode = "auto" // UpdatesKeep keeps the version. A system install runs from a kept // copy, so the vendor update cannot change it. UpdatesKeep UpdateMode = "keep" )
Update modes.
type Wire ¶
type Wire interface {
Detect(ctx context.Context, h agentwire.Harness) (agentwire.Detection, error)
Version(ctx context.Context, bin string) string
Models(ctx context.Context, h agentwire.Harness, q agentwire.ModelQuery) ([]agentwire.ModelInfo, error)
LatestVersion(ctx context.Context, h agentwire.Harness) (string, error)
InvalidateModels(h agentwire.Harness)
}
Wire is what the manager needs from the agent-wire runtime.