Documentation
¶
Overview ¶
Package agent describes every coding agent magpie can drive: where its config lives, which fields matter (model, effort, …) and which values to offer.
Index ¶
- Constants
- Variables
- func AgyLaunch(model string) string
- func CLIs(wait time.Duration) (out map[string]CLI, pending bool)
- func CindyLink(url string) string
- func CodexDaemonRestarted()
- func CodexOwnOnly() bool
- func CodexSubAgentsV1Warning() string
- func CursorLocalLaunch(app, gw string) string
- func DesktopConfigs3p(home string) []string
- func DryRun(id string) error
- func DshPatchFiles(dir string) []string
- func EndCodexFailover() error
- func FakeWSL(probes, roots map[string]string) func()
- func KeepCodexDaemonCurrent(ctx context.Context)
- func KeepCursorLocalEnv(context.Context)
- func KeepDshWired(ctx context.Context)
- func KeyAt(gw string) string
- func KimiDir(home string) (dir string, legacy bool)
- func MiniMaxDir(home string) string
- func ModelIcon(model string) string
- func MoveAntigravityEfforts()
- func MoveCursorEfforts()
- func MoveOffAccountIDs()
- func Newer(a, b string) bool
- func Notices() []string
- func Own(o Option) bool
- func PluginAgentOf(spec string) string
- func PluginErrors() map[string]string
- func PluginPath(p string) string
- func Rekey(as []*Agent) (moved []string, err error)
- func RenameLegacy()
- func RenameProvider(from, to string) ([]string, error)
- func Rescan()
- func Rewire(as []*Agent) (moved []string, err error)
- func StandIn(agent, model string) string
- func StopFakeWSL(name string)
- func SyncCatalog()
- func Taken(p string) bool
- func TuneApply(home, agent, knob, model, value string) error
- func TuneUndo(home, agent, knob, model string) error
- func WSLRunning(distro string) bool
- type AdminError
- type Agent
- func (a *Agent) AppVersion() string
- func (a *Agent) Apply(key, v string) error
- func (a *Agent) CLI() (c CLI, ok bool)
- func (a *Agent) CLIMissing() bool
- func (a *Agent) Connect() error
- func (a *Agent) ConnectHow() (Connection, error)
- func (a *Agent) Detected() bool
- func (a *Agent) Disconnect() error
- func (a *Agent) DisconnectOffline() error
- func (a *Agent) Disconnected() bool
- func (a *Agent) Drift() *Drift
- func (a *Agent) FailoverSaid() string
- func (a *Agent) Field(key string) *Field
- func (a *Agent) HasApp() bool
- func (a *Agent) InstalledVersion() string
- func (a *Agent) Keep()
- func (a *Agent) ListsFor() string
- func (a *Agent) Models() []string
- func (a *Agent) OwnModels(cur map[string]string) bool
- func (a *Agent) Pick(key, v string) error
- func (a *Agent) Picks(f Field, cur map[string]string) []Option
- func (a *Agent) Reapply() error
- func (a *Agent) Source() string
- func (a *Agent) Spell(key, v string) (string, error)
- func (a *Agent) Stale() int
- func (a *Agent) StaleCopies() []StaleCopy
- func (a *Agent) UpdateCLI() (CLI, error)
- func (a *Agent) Values() map[string]string
- func (a *Agent) Wired() bool
- type CLI
- type Connection
- type DisconnectPlan
- type Drift
- type Field
- type FileChange
- type Install
- type InstallCmd
- type LineDiff
- type Move
- type NativeConnection
- type NativeField
- type NativeState
- type NoModelsError
- type OfflineAction
- type Option
- type PlannedFile
- type PlannedSetting
- type RuntimeUnavailableError
- type StaleCopy
- type TuneSetting
Constants ¶
const ( TuneCompact = "compact" // when the agent compacts its conversation, in tokens TuneCache = "cache_ttl" // Claude Code: the main conversation's cache, 5m or 1h TuneSubCache = "subagent_cache_ttl" // Claude Code: its subagents', workflows' and helpers' )
The settings tune knows.
const CindyScheme = "cindy://provider/import?"
CindyScheme begins every Cindy import link.
const CursorLocalID = "cursor-local"
CursorLocalID is the agent's id, which its key names (TokenFor).
const DryRunArg = "agent-disconnect-dry-run"
DryRunArg is the command line's first word for the process that disconnects an agent on a copy of its files (main.go).
const RoutingGroups = "Routing groups"
RoutingGroups is the picker's group of routing groups.
Variables ¶
var Running = func(patterns ...string) bool { if runtime.GOOS == "windows" { return len(patterns) > 0 } for _, pat := range patterns { if err := proc.Command("pgrep", "-f", pat).Run(); err == nil { return true } } return false }
Running reports whether a process whose command line matches any pattern (an extended regexp, as for pgrep -f) is alive. Windows can't be asked what runs, so anything may be: every caller is the advice an agent's own lists need after magpie changed what it reads at start ("restart Codex", "open a new dsh session"), and a Windows that answered no here dropped that advice silently — a model picked in magpie looked like it had done nothing at all. claudeRunning and Pencil's own check already say they can't be told, and say yes for the same reason. A var so tests can say what runs, as claudeRunning is: magpie's own CLI tests printed "restart the Codex app" on a Mac with Codex open, and on every Windows.
Functions ¶
func AgyLaunch ¶ added in v0.1.404
AgyLaunch is the command that starts agy on magpie's gateway and one of its custom models, in the shell of this system. Its key names agy: its requests go out as Google's Gemini SDK's (User-Agent google-genai-sdk/…), with nothing of agy's own, so the gateway knows them by the key (x-goog-api-key) alone. A command copied before, with the plain token, still reaches magpie.
func CLIs ¶ added in v0.1.397
CLIs is every detected agent's CLI, as far as it is known within wait; pending says some are still being asked, and will be ready next time.
func CindyLink ¶ added in v0.1.281
CindyLink is the link that adds the gateway at url to Cindy as the provider Magpie, keyed so that its requests are counted as Cindy's.
func CodexDaemonRestarted ¶ added in v0.1.1151
func CodexDaemonRestarted()
CodexDaemonRestarted forgets the daemon last found behind, once the user has restarted it.
func CodexOwnOnly ¶ added in v0.1.1138
func CodexOwnOnly() bool
CodexOwnOnly reports whether the Codex that asks the gateway for its model list there (/backend-api/codex/models) reaches magpie for account failover alone (FailingOver), to be handed only its own models (#1385). That is this machine's Codex; a request doesn't say whether it came from a Codex in a WSL distro instead, so one there connected to magpie (what magpie set on it, or its joined/beside mark in the stash) keeps magpie's models in the list. No distro is probed for it.
func CodexSubAgentsV1Warning ¶ added in v0.1.1224
func CodexSubAgentsV1Warning() string
CodexSubAgentsV1Warning is codexSubAgentsV1Warning for the Codex config here, as the Settings row asks it (the page can't reach the config itself). "" when there is no Codex, or no conflict.
func CursorLocalLaunch ¶ added in v0.1.877
CursorLocalLaunch is the command that starts the build at app on the gateway at gw, in the shell of this system. Started so, from a shell, the app has the variables; opened from the Dock or Finder it has only the login shell's.
func DesktopConfigs3p ¶ added in v0.1.1156
DesktopConfigs3p are the claude_desktop_config.json files Claude Desktop reads in its 3p mode: there its whole userData is Claude-3p, its MCP servers too (%LOCALAPPDATA%\Claude-3p on Windows, and the MSIX package's; Claude-3p beside Claude elsewhere).
func DryRun ¶ added in v0.1.780
DryRun disconnects an agent in the process DisconnectPreview starts, on the copy under its temporary home.
func DshPatchFiles ¶ added in v0.1.182
DshPatchFiles are the patch lists of the dsh whose home is dir, as magpie writes them: every profile's (web's first), else config.yaml.
func EndCodexFailover ¶ added in v0.1.1193
func EndCodexFailover() error
EndCodexFailover takes account failover out of this machine's Codex as the magpie serving its gateway quits (EndFailover): Codex goes straight to OpenAI again rather than retrying a gateway that's gone. The app-server codex sessions share read the old base URL as it started and keeps it, and KeepCodexDaemonCurrent ends with magpie, so it is restarted here, when no session is on it (thisisvainxx on X: back on its own config, Codex took "several restarts").
func FakeWSL ¶ added in v0.1.512
FakeWSL, for other packages' tests, stands in for wsl.exe on any system: each distro named in probes is installed and running, answers the probe with what probes has for it (wslProbeScript's output: "home:/ home/me\ndir:.codex\n…") and is opened at roots' folder for it. What magpie remembers of WSL is forgotten, before and after; the returned func puts everything back.
func KeepCodexDaemonCurrent ¶ added in v0.1.1151
KeepCodexDaemonCurrent restarts this machine's Codex daemon whenever it is behind what Codex reads at start and no codex session is on it, looking every so often until ctx ends.
func KeepCursorLocalEnv ¶ added in v0.1.885
KeepCursorLocalEnv sets the variables again when the gateway is served, with its address now, while Cursor Private Inference is connected: the Mac's launchctl ones are gone after a restart, and the port may have changed. The app takes them when it is next opened.
func KeepDshWired ¶ added in v0.1.641
KeepDshWired keeps magpie's route in dsh's patch lists as magpie's catalog is now, for as long as magpie serves the gateway. dsh reads a patch list live, so one left behind by something else writing the file — dsh's own Models page, an older magpie — fails every session there with no such configured model until the route is written again. What is written is magpie's own list, never the model a session starts on.
func KeyAt ¶ added in v0.1.1159
KeyAt is keyAt, for what else magpie gives an agent that reaches the gateway at gw (the library's MCP servers relayed through it).
func KimiDir ¶ added in v0.1.470
KimiDir is the folder Kimi Code keeps its config.toml in, and whether it is the old kimi-cli's. kimi-cli (1.50 on) hands over to the new Kimi Code, which reads only ~/.kimi-code: it offers to copy ~/.kimi's config over when it first starts, and once that's done never reads ~/.kimi again, so a model written there is one it never sees (#290). ~/.kimi is kimi-cli's only where the new one isn't: no ~/.kimi-code, nor $KIMI_CODE_HOME.
func MiniMaxDir ¶ added in v0.1.535
MiniMaxDir is the folder MiniMax Code keeps its config.yaml in.
func ModelIcon ¶ added in v0.1.466
ModelIcon is the logo of a model's maker, known by its id's (or name's) family alone; "" when it isn't one of them.
func MoveAntigravityEfforts ¶ added in v0.1.299
func MoveAntigravityEfforts()
MoveAntigravityEfforts does the same for Antigravity's ids at a level (antigravity/gemini-3.7-flash-high → antigravity/gemini-3.7-flash, at high when the agent's effort is unset and it has that one).
func MoveCursorEfforts ¶ added in v0.1.297
func MoveCursorEfforts()
MoveCursorEfforts moves an agent set to one of Cursor's ids at an effort (cursor/grok-4.7-low), from before magpie offered each family as one model, to that model (cursor/grok-4.7) spelled the same way, and — when the agent's effort is unset and it has that one — to the effort the id was at. A model the picker doesn't offer is left: the gateway still takes Cursor's id. It runs at start-up; errors are swallowed as RenameLegacy's.
func MoveOffAccountIDs ¶ added in v0.1.399
func MoveOffAccountIDs()
MoveOffAccountIDs moves each of the user's providers saved on a subscription's id (provider.OnAccountIDs) to a free one, the agents on it with it, so the subscription is listed once signed in: a "WorkBuddy" key saved as workbuddy before WorkBuddy's plan was a subscription hid it, and signing in to it said "signed in, but magpie can't list it". Run at start-up; errors are swallowed as RenameLegacy's are.
func Newer ¶ added in v0.1.397
Newer says whether version a is after b: by their numbers, then a release after its pre-releases (1.0.87 after 1.0.87-0).
func Notices ¶ added in v0.1.1171
func Notices() []string
Notices are the templates of every notice magpie's own agents give.
func Own ¶ added in v0.1.1199
Own reports whether o is a model the agent reaches on its own, not one of magpie's catalog: what Picks leaves out on the user's word.
func PluginAgentOf ¶ added in v0.1.1161
PluginAgentOf is the id of the agent the plugin spec adds, "" for none.
func PluginErrors ¶ added in v0.1.1161
PluginErrors is why an agent a plugin adds isn't listed, by plugin spec: its module didn't load, or its id is a built-in agent's.
func PluginPath ¶ added in v0.1.1178
PluginPath is a path an agent plugin gives, as it reads its config's: ~ and $VAR expanded against this user's home.
func Rekey ¶ added in v0.1.1169
Rekey sets again those of as, taken by OnGateway before LAN sharing was turned on or off or its key made anew, that reach the gateway from beyond loopback (an agent in a WSL distro under NAT): the key they send there is the sharing key while sharing is on (keyAt), so it changed with it. One connected while nothing was shared kept gateway.Token, which the gateway turns away from beyond loopback, after sharing was turned on for it.
func RenameLegacy ¶
func RenameLegacy()
RenameLegacy rewrites what an older dial left in the agents' files so it says magpie: a model spelled dial/… becomes magpie/… (which also writes the magpie provider entry the agent needs), and then the dial entry, Codex's table and catalog file, and Claude Code's token go. It runs at start-up; once nothing says dial any more it changes nothing. Errors are swallowed on purpose — a file magpie cannot rewrite is one the user can still fix from the picker.
func RenameProvider ¶ added in v0.1.125
RenameProvider gives a provider another id (provider.Rename) and moves the agents on one of its models to the same model by the new id, each spelled the way the agent spells it, and what else in their configs names it (RenameRefs). It answers the agents it moved.
func Rescan ¶ added in v0.1.937
func Rescan()
Rescan forgets what was found of the agents on this machine a while ago, so the next read of them looks again at once: the reader asked for it with the Agents page's refresh (#844), having just installed an agent, or removed one, or changed its settings outside magpie. What is read from an agent's files every time needs nothing forgotten; these are the answers kept for a while because asking was slow (the apps folder, wsl.exe, Alma's server), and where each command was found on PATH (proc.LookPath).
func Rewire ¶ added in v0.1.950
Rewire puts the gateway's address now into the configs of agents, taken by OnGateway before it moved: each one whose wiring is off now is set again, an agent joined to magpie beside its own models (Codex signed in with ChatGPT) joined again. It says the names of those it moved, and what one it couldn't move failed with. Cursor Private Inference's variables and dsh's routes, which magpie keeps on its own, follow too.
func StandIn ¶ added in v0.1.241
StandIn is the model Claude Code is set to use in place of one it named that magpie doesn't serve: claude-haiku-4-5-… for a title or a small task goes to its haiku tier's model, and a name of no tier to its main model. For Codex, the model it is set to (codexStandIn). "" when the agent isn't routed through magpie or is neither. For gateway.StandIn.
func StopFakeWSL ¶ added in v0.1.1080
func StopFakeWSL(name string)
StopFakeWSL, for other packages' tests, has FakeWSL's distro name stop, as the user stopping it (wsl --shutdown) does: wsl.exe lists it as not running from now on.
func SyncCatalog ¶ added in v0.1.54
func SyncCatalog()
SyncCatalog brings every model list magpie wrote into an agent's files up to the catalog as it is now. It is what catalog.Changed is set to, so a provider saved or removed, or a vendor's list fetched anew, reaches the agents; one already running asks for another round rather than waiting. Errors are left for the picker: a file magpie can't write now is one the next change, or a pick, writes.
func Taken ¶ added in v0.1.469
Taken reports whether something that isn't a folder is where the folder p, or one it is in, would be: nothing can be written under it.
func TuneApply ¶ added in v0.1.1158
TuneApply puts value in as an agent's setting, on the user's say. What was there before is kept, the first time only, for TuneUndo. A variable that takes precedence is an error: the setting would change nothing.
func TuneUndo ¶ added in v0.1.1158
TuneUndo puts back what a setting was before tune put one in, unless the user has changed it since: then it is theirs, and only forgotten.
func WSLRunning ¶ added in v0.1.1080
WSLRunning is whether the WSL distro runs now (wslUp); false off Windows. What another package does in a distro on its own, rather than at the user's asking, asks it first.
Types ¶
type AdminError ¶ added in v0.1.1174
AdminError is an install or update that needs an administrator and didn't get one: the prompt declined (Canceled), or none to be had (Err). The command never ran. Agent is what it installs (an agent, or RTK); Prefix the folder only an administrator can change, "" when not known; Via the tool, npm or winget, whose fix is said.
func (*AdminError) Error ¶ added in v0.1.1174
func (e *AdminError) Error() string
func (*AdminError) Unwrap ¶ added in v0.1.1174
func (e *AdminError) Unwrap() error
type Agent ¶
type Agent struct {
ID string
Name string
Icon string // bundled icon name (internal/gui/assets/icons)
Aliases []string
Bin string // executable name, used for detection
Dir string // config directory, used for detection
Path string // config file magpie edits
// Plugin is the spec of the plugin that adds this agent (plugged.go),
// "" for magpie's own
Plugin string
Fields []Field
Native *NativeConnection
// Notice, if set, is advice worth showing after a change: agents that
// read their config once at start-up need a restart to see it.
Notice func() string
// UA is what the agent's User-Agent begins with, lower-case: how the
// gateway tells its requests from others'
UA []string
// ListsModels: the agent's own model menu is magpie's models as picked
// on the Agents page for it (settings.HiddenModels, PickedModels),
// though no field of its picks among the catalog: the gateway's
// /v1/models as asked with its key (Cursor Private Inference), or the
// list magpie writes into its files, magpieModels(id), where its only
// field puts magpie in its picker (ZCode, Pencil: #1508)
ListsModels bool
// NoNames: the agent's own list doesn't name magpie's models as
// Names in agents' lists says (provider.Labels): magpie hands it the
// models' ids alone, its format having no name for one (Goose, Hermes,
// jcode …), it lists no models of magpie's at all (Gemini CLI, Snow),
// or it reads the gateway's /v1/models itself, whose display_name is
// the name alone (Empryo, Cursor Private Inference). The setting says
// so for each one connected, rather than seeming to do nothing.
NoNames bool
// Sync, for an agent that reads magpie's models from a file of its own
// rather than asking the gateway, rewrites that list as the catalog is
// now — where magpie wrote one; nothing else changes (see SyncCatalog).
Sync func() error
// Unwire, for an agent whose fields' default is the agent as installed
// rather than what it had before magpie (Codex, Claude Code, Gemini
// CLI), takes magpie out of its config and puts back what the stash
// kept: the endpoint, provider and model the user had. Disconnect runs
// it before the fields' defaults.
Unwire func() error
// Restore, for an agent whose files magpie copied aside before its
// first write (beforeMagpie), puts them back as they were where what
// Disconnect left says the same. Disconnect runs it last.
Restore func() error
// Join, for an agent that can have magpie's models in its own list
// while it stays on the model it was on (Codex signed in with ChatGPT),
// connects it so, its model left as its own last pick; false where it
// can't, and Connect then picks one of magpie's.
Join func() (bool, error)
// Joined reports an agent Join connected: magpie is in its config
// though no field is on one of magpie's models.
Joined func() bool
// Beside reports an agent set on one of magpie's models beside its own
// (Codex by the base URL beside its ChatGPT sign-in), now on one of its
// own written in by the agent: still connected, as joined, though the
// change is told as drift (#940).
Beside func() bool
// OwnVia is the catalog id magpie serves one of the agent's own models
// by on a sign-in of the user's, which its model field lists as its
// own rather than as magpie's ("codex/gpt-5.5" for Codex's gpt-5.5),
// "" for none: Connect keeps the agent on that model through magpie
// where it can't Join (#940: Codex went to an unrelated model).
OwnVia func(model string) string
// Routed reports that the agent's config sends whatever model it
// names to magpie's gateway (Codex's openai_base_url or magpie as its
// provider), so a model's name the gateway takes as a routing group
// is that group's (#750).
Routed func() bool
// FailingOver reports an agent that isn't connected whose requests
// still go through magpie's gateway, for account failover alone (Codex
// signed in to ChatGPT with more of its accounts on in magpie, #1385):
// the Agents page says so and what turns it off, and the gateway lists
// it only its own models.
FailingOver func() bool
// EndFailover takes out what account failover wrote, for magpie
// quitting: left there, the agent would be pointed at a gateway that
// no longer answers, and retry till magpie is open again (Leon920717
// on X). The next start's Sync writes it again.
EndFailover func() error
// Follow, for an agent whose own picker moves its main model where
// magpie keeps other settings following it (Claude Code's /model and
// its tiers), brings those along to the model picked there. Run as the
// Agents page is drawn.
Follow func() error
// RenameRefs, for an agent whose config names magpie's models beyond
// its fields (omp's other roles and fallback chains), moves those names
// off provider from onto to, the rest of each kept; it answers whether
// any moved. The fields themselves are RenameProvider's.
RenameRefs func(from, to string) (bool, error)
// Check, for an agent magpie wires in beyond its model field, says what
// of that wiring is gone while the model is still one of magpie's —
// something else rewrote the config — or "" when it is all there
// (see Drift).
Check func() string
// LastUsed, for an agent that keeps a log of its own prompts, is when
// it was last used — each prompt a request the gateway should have
// seen, so one it didn't went round magpie (see Drift). Zero if unknown.
LastUsed func() time.Time
// Reached, for an agent that logs where its model requests go, is its
// newest one since a time: when, the address it went to, and whether
// nothing answered there. Zero if there is none.
Reached func(since time.Time) (at time.Time, to string, refused bool)
// WSL is the distro an agent inside WSL lives in, "" for this
// machine's own (see wsl.go).
WSL string
// Home is a WSL agent's $HOME in its distro as magpie opens it
// (\\wsl.localhost\<distro>\home\me), where its other files are; ""
// for this machine's, and while the distro is stopped: opening it
// would start it.
Home string
// Gateway is the gateway's address as the agent reaches it, a WSL
// distro's own way to it; nil is gateway.URL.
Gateway func() string
// Import, for an app that takes magpie only through an import link of
// its own, which the user confirms there (Cindy), is that link; the app
// has no fields magpie sets. Added says whether it has magpie already.
Import func() string
Added func() bool
// Launch, for an agent that takes the gateway only from its
// environment (agy), is the command that starts it on magpie, while
// it is on one of magpie's models; "" otherwise.
Launch func() string
// SplitSuffix, for an agent whose model values carry something of its
// own after the model that varies from value to value (omp's thinking
// level, "…:max"), splits a value into the model the picker offers and
// that suffix, "" when there is none. What matches a value against the
// picker (drift, Reseat, RenameProvider, Spell) matches the model and
// puts the suffix back after the one it moves to. A mark that is always
// the same for a model (Claude Code's [1m]) rides on the option instead.
// one is false for a value that is no one model but a list the agent
// falls back through (omp's "a,b"): that is the user's own whatever it
// names, never taken for one of magpie's models nor moved by what
// matches the picker (RenameRefs moves the names in it).
SplitSuffix func(v string) (model, suffix string, one bool)
// Spelled, when set, says whether a value of the agent's fields is
// spelled as one of magpie's there (prefixed: it starts with
// "magpie/", its provider in the agent): one that isn't is a model of
// one of the agent's own providers, never magpie's, even when magpie
// has a provider of the same name (OpenHanako's own
// deepseek/deepseek-v4-pro read as magpie's deepseek, #835).
Spelled func(v string) bool
// ModelAliases are the names the agent's model takes besides ids
// (Claude Code's opus, best, opusplan). One that names a field as well
// is the model's on the command line: magpie claude opus sets the
// model, where another field's name alone shows that field.
ModelAliases []string
// contains filtered or unexported fields
}
Agent is one supported coding agent.
func All ¶
func All() []*Agent
All returns every agent magpie knows about, detected or not: its own, then those plugins add.
func Clients ¶ added in v0.1.43
func Clients() []*Agent
Clients is everyone whose requests the gateway knows by name: every agent, detected or not, and the others. It is what the Usage and Routing views draw a request's client with.
func Detected ¶
func Detected() []*Agent
Detected returns the agents present on this machine, in display order.
func OnGateway ¶ added in v0.1.950
func OnGateway() []*Agent
OnGateway are the agents connected to magpie whose configs reach the gateway at its address now: none of their wiring is off.
func (*Agent) AppVersion ¶ added in v0.1.1123
AppVersion is the version of the agent's desktop app installed here, "" for an agent without one magpie knows, one not installed, or an Info.plist that doesn't say (a binary one isn't read).
func (*Agent) Apply ¶ added in v0.1.91
Apply sets one of the agent's fields and remembers it as magpie's, so it can be told apart from what something else writes there later. Every setting of a field by the user goes through here. A field magpie set before that this one moves too is magpie's doing as well: Claude Code's Default takes its tiers and subagent model out with magpie's endpoint, which read as changed outside magpie, and the drift kept the row up among the connected ones while it said Not connected (#834).
func (*Agent) CLI ¶ added in v0.1.397
CLI is the agent's CLI: its version, the newest, and whether magpie can update it, with its desktop app's version. ok is false for an agent with neither a CLI magpie knows nor its app.
func (*Agent) CLIMissing ¶ added in v0.1.936
CLIMissing reports an agent that is here by its settings alone: its folder or config is, its command-line program isn't — not on PATH nor where users' tools go (proc.FindTool), as after an uninstall that left ~/.dsh behind (#843). Only for an agent that is its CLI and that magpie knows an install command for, so the Agents page can offer it again; one whose desktop app is installed (HasApp) is that app's settings, which need no CLI (DeepSeek Harness Desktop, star on Discord).
func (*Agent) ConnectHow ¶ added in v0.1.806
func (a *Agent) ConnectHow() (Connection, error)
ConnectHow is Connect, saying how the model was chosen.
func (*Agent) Disconnect ¶ added in v0.1.682
Disconnect takes magpie out of the agent's config and puts back what the user had, the Agents page's "Disconnect from magpie" (Fate on Discord: picking the agent's default did it, but nothing said so). Unwire first, for an agent whose default would leave it as installed; then each field still on magpie goes to its default, as picking it does, and so does each one magpie set that reads as magpie set it (an effort). What magpie remembered setting is forgotten.
func (*Agent) DisconnectOffline ¶ added in v0.1.972
DisconnectOffline restores a native agent's saved files only after an explicit offline choice. Legacy callers of Disconnect keep live semantics.
func (*Agent) Disconnected ¶ added in v0.1.1162
Disconnected reports whether the user disconnected the agent and hasn't connected it since.
func (*Agent) Drift ¶ added in v0.1.91
Drift says what, if anything, keeps the agent off what magpie set: its config first (wiring, then each field against magpie's record), then — the config being right — whether its latest use actually came through. A field moved from one magpie model to another (the agent's own picker) isn't drift; one moved off magpie is.
func (*Agent) FailoverSaid ¶ added in v0.1.1138
FailoverSaid is, for an agent not connected whose requests still go through magpie for account failover alone (FailingOver), what the CLI and the TUI say of it, the Agents page's line in words of their own: why it goes through magpie, and what turns that off (#1385). "" when it doesn't.
func (*Agent) Field ¶
Field looks a field up by key, in any case, as Find looks an agent up (magpie codex Model was written as the model).
func (*Agent) HasApp ¶ added in v0.1.1135
HasApp reports whether the agent's desktop app is installed here: its bundle on macOS (AppVersion), its executable on Windows.
func (*Agent) InstalledVersion ¶ added in v0.1.443
InstalledVersion is what the agent's CLI on PATH says its version is: "" for an agent without a CLI magpie knows, one not on PATH, or one that didn't say. Asked once per binary, like CLI's; nothing is fetched.
func (*Agent) Keep ¶ added in v0.1.91
func (a *Agent) Keep()
Keep takes the agent's config as it is now: what magpie set before is forgotten, and no longer said to have been changed.
func (*Agent) ListsFor ¶ added in v0.1.1051
ListsFor is whose model lists an agent's are (provider.CatalogFor): its own id's, or, for one in a WSL distro, its Windows twin's (claude for claude@wsl:Ubuntu). A distro's agent is written magpie's models under that id and sends the gateway that id's key, so the models picked for its row are the ones it is shown only when kept under that id too (#927).
func (*Agent) Models ¶ added in v0.1.1118
Models are magpie's models the agent is set to, as catalog ids (provider/model, group/<id>), each once: the agent's own models aside. Usage stats count them (internal/stats).
func (*Agent) OwnModels ¶ added in v0.1.1199
OwnModels reports whether one of a's pickers that picks among magpie's catalog offers models of the agent's own too, which Picks can leave out.
func (*Agent) Pick ¶ added in v0.1.780
Pick sets a field from the Agents page's model picker. One of magpie's models picked on an agent not connected yet connects it first, as its switch does, then starts it on that model (the owner: the switch, and a model picked in magpie in one click, both): the agent gets magpie's whole list, and Disconnect puts back what it had before.
func (*Agent) Picks ¶ added in v0.1.1199
Picks are the options f's picker offers: all of them, unless the user asked a's pickers to offer magpie's models alone (#1642, MizuIro-H). Then a field that picks among magpie's catalog leaves out the models the agent reaches on its own (DeepSeek Harness's DeepSeek ones), but for its default and the one it is set to.
func (*Agent) Reapply ¶ added in v0.1.91
Reapply sets again what magpie set on the agent: what drifted, else its fields as they read now — for a config taken off magpie in a way no check catches. A replaced field brings back the others magpie set with it. Either way the record is renewed, so a use before now no longer counts.
func (*Agent) Source ¶ added in v0.1.780
Source is what an agent not connected to magpie runs on now: "sub" (a Claude subscription), "chatgpt" (a ChatGPT sign-in), "key" (an API key of its own), "providers:N" (N providers of its own); "" when unknown.
With account discovery off (#1535) no sign-in is read for it: Claude Code's account in .claude.json, Codex's auth.json and OpenCode's are left alone, and only what the agent's own settings say is told.
func (*Agent) Spell ¶ added in v0.1.41
Spell puts a value typed for field key the way this agent spells it: a catalog model is "copilot/gpt-6" in some agents and "magpie/copilot/gpt-6" in others, and either is taken in both. A value the picker offers as is stays, and so does one it doesn't know (a model the agent reaches on its own that isn't listed); a "magpie/…" value the catalog doesn't have is an error rather than a model the agent would ask its own vendor for. The agent's suffix after the model (SplitSuffix) stays as typed, and so does a list of models, the user's own.
func (*Agent) Stale ¶ added in v0.1.780
Stale is how many copies of the agent are running that started before magpie last changed what it reads at start: they still have the list they started with until reopened. On Windows only the Codex daemon is told.
func (*Agent) StaleCopies ¶ added in v0.1.1110
StaleCopies are the copies Stale counts. Reopening one kind doesn't end another: on macOS the Codex app keeps running, its app-server with it, when its window is closed (its window-all-closed doesn't quit a packaged app on darwin), an editor's Codex runs until the editor's window is reloaded, and the CLI's managed daemon runs on with ppid 1 until it is restarted itself. So each is told apart for the row to say which one is left. One app's processes (its app-server, its exec-server) are one copy. One run from another home's agent dir (an app-server daemon Codex left running for a CODEX_HOME of its own, under its packages) reads other files, and isn't counted.
type CLI ¶ added in v0.1.397
type CLI struct {
Version string `json:"version,omitempty"`
// Latest is the newest there is, from where it would be updated:
// Homebrew's for one Homebrew installed, npm's otherwise
Latest string `json:"latest,omitempty"`
// Via is what updates it: npm, bun, pnpm, brew, or self (its own
// updater); "" when magpie can't tell how it was installed
Via string `json:"via,omitempty"`
// Command is the update as a person would type it
Command string `json:"command,omitempty"`
// Update: Latest is after Version, and magpie knows how to get it
Update bool `json:"update,omitempty"`
// App is the version of the agent's desktop app installed beside it
// (the Codex app, AppVersion); shown even with no CLI on PATH
App string `json:"app,omitempty"`
// Admin: the update needs an administrator, which Windows asks for
// first (npm's global folder under Program Files)
Admin bool `json:"admin,omitempty"`
// Path is where the CLI was found: the file magpie runs, as PATH
// reached it
Path string `json:"path,omitempty"`
// OffPath says the CLI was found in a folder magpie adds to its own
// PATH (proc.UserPath: ~/.local/bin, npm's prefixes, nvm's default
// Node, bun, Homebrew, ...) that a terminal opened now doesn't have,
// so that `which` there doesn't find it. A row of an agent the user
// believed uninstalled, with a version and nothing to say where it
// came from, read as magpie making it up (悠悠哥 on Discord: Codex
// 0.162.1 listed with no codex on PATH and no ~/.codex). False when
// the terminal's PATH can't be told.
OffPath bool `json:"offPath,omitempty"`
}
CLI is what magpie knows of an agent's command-line program.
type Connection ¶ added in v0.1.806
type Connection struct {
How string `json:"how"`
Field string `json:"field,omitempty"`
Value string `json:"value,omitempty"`
}
Connection is how Connect chose the model an agent starts on, for the Agents page to say it (#726: Codex showed its last pick, Claude Code a Sonnet through magpie and Antigravity some model, with nothing saying why). How is one of:
- "kept": it was connected already, left as it was
- "again": the models it was on when it was switched off, put back
- "joined": the model it is on stays its own (Codex signed in with ChatGPT), magpie's models join its list
- "magpie": an app whose one setting is magpie as its provider
- "same": the model it is on now, through magpie
- "alike": the model its alias (opus) stands for, through magpie
- "default": on its own default with no model set: the first of its own models in its list (the newest, for Claude Code), through magpie
- "first": magpie has none of the model it is on: the first on the account it is signed in to, else a subscription's, else the first
Field and Value are the field set and what it was set to, where Connect picked one model ("" for kept, again and joined).
type DisconnectPlan ¶ added in v0.1.972
type DisconnectPlan struct {
Files []PlannedFile
Settings []PlannedSetting
}
func (*DisconnectPlan) CheckFiles ¶ added in v0.1.972
func (p *DisconnectPlan) CheckFiles() error
func (*DisconnectPlan) Preview ¶ added in v0.1.972
func (p *DisconnectPlan) Preview() []FileChange
func (*DisconnectPlan) Revision ¶ added in v0.1.972
func (p *DisconnectPlan) Revision(agent string) string
Revision binds confirmation to file preconditions and restoration values, without accepting a serialized plan from the client.
type Drift ¶ added in v0.1.91
type Drift struct {
// Kind says what is off:
// "unwired" the model is magpie's but the config no longer sends it
// through magpie (Check);
// "replaced" a magpie model magpie set was replaced by the agent's own;
// "bypassed" the config is right, yet the agent was used since and
// nothing of it reached the gateway — it runs on an old
// config, or something outside the file overrides it;
// "unreachable" the config is right, but the address off loopback
// it names the gateway at doesn't answer (#1013);
// "proxied" the config is right, but the agent sends its requests
// for the gateway through a proxy (Addr) that doesn't
// pass them on to it (codex_proxy.go).
Kind string `json:"kind"`
Field string `json:"field"` // the field it shows on
Now string `json:"now,omitempty"` // what that field says now
Want string `json:"want"` // what setting it again sets
Detail string `json:"detail"` // what exactly is off, for a tooltip
// Addr is where an unreachable agent is pointed; Move, when set, the
// address WSL reaches Windows at now, which Reapply points it at.
Addr string `json:"addr,omitempty"`
Move string `json:"move,omitempty"`
}
Drift is how an agent differs from what magpie set on it.
type Field ¶
type Field struct {
Key string
Label string
Get func() string
Set func(string) error
Options func(cur map[string]string) []Option
// Quiet fields are left out of listings while empty: they follow
// another field until set (Claude Code's per-tier models).
Quiet bool
// Follows is the key of the field a Quiet one takes after while empty
// ("model" for Claude Code's tiers and subagents): a profile's details
// say so, and Drift reads the field as on that one's model (#1050).
Follows string
}
Field is one tunable setting of an agent. Set with an empty value puts the field back to the agent's own default: anything magpie wired in (the gateway as a provider, its model catalog) comes out and the key is removed.
type FileChange ¶ added in v0.1.780
type FileChange struct {
Path string `json:"path"` // as the user knows it, ~ for home
Removed bool `json:"removed,omitempty"` // the file goes
Created bool `json:"created,omitempty"` // the file is made
Lines []LineDiff `json:"lines,omitempty"`
}
FileChange is how disconnecting changes one of the agent's files.
func DisconnectPreview ¶ added in v0.1.780
func DisconnectPreview(a *Agent, exe string) ([]FileChange, error)
DisconnectPreview is what Disconnect would change in the agent's files, found by running it on a copy. An error is a preview not to be had (the agent's files outside home, a WSL agent): the dialog then says it in words.
type Install ¶ added in v0.1.801
type Install struct {
ID string `json:"id"`
Name string `json:"name"`
Icon string `json:"icon,omitempty"`
Commands []InstallCmd `json:"commands"`
// Missing: the agent's settings are here but its CLI isn't (CLIMissing),
// so it is listed on the Agents page and offered here again too
Missing bool `json:"missing,omitempty"`
}
Install is an agent not on this machine, and how to install it.
type InstallCmd ¶ added in v0.1.801
type InstallCmd struct {
// Via is what runs it: script (the vendor's installer, in a shell),
// powershell (the vendor's installer, on Windows), brew or npm
Via string `json:"via"`
Command string `json:"command"`
// Node is how the command installs Node.js before npm, where none is
// here: nvm (Linux), nvm-mac (a Mac, where nvm's installer wants the
// Xcode Command Line Tools) or winget (Windows); "" when it doesn't
Node string `json:"node,omitempty"`
// Admin is npm's global folder, for an npm command run where only an
// administrator can change it (Windows' Program Files); "" otherwise
Admin string `json:"admin,omitempty"`
}
InstallCmd is one way to install an agent's CLI.
type LineDiff ¶ added in v0.1.780
type LineDiff struct {
Op string `json:"op"`
Text string `json:"text"`
Was string `json:"was,omitempty"`
}
LineDiff is a line of a file disconnecting changes: Op is "-" for a line taken out, "+" for one put in, "~" for a line whose value goes back to another (Was is the line now).
type Move ¶ added in v0.1.397
type Move struct {
Agent string `json:"agent"` // the agent's name
Field string `json:"field"` // model, or a tier (Claude Code's haiku …)
From string `json:"from"` // the catalog model it was on
To string `json:"to"` // the one it is on now; "" its own default
// Error is why the agent couldn't be moved (its file unwritable, say):
// it stays on From, which magpie no longer serves
Error string `json:"error,omitempty"`
}
Move is one of an agent's fields moved off a model magpie no longer serves.
func Reseat ¶ added in v0.1.397
Reseat makes a change to the providers (change) and moves every agent whose model it stopped serving: to that model from another provider that serves it, else to the agent's own default. It answers the moves. Its error is the change's alone: once the change is made, an agent that can't be moved is a move with its Error and the others are still moved. An error then would say the change failed when it was made — the panel, told so, kept a removed provider's editor open and listed, and a second Remove said there was no such provider.
type NativeConnection ¶ added in v0.1.972
type NativeConnection struct {
Read func() NativeState
Connect func() error
Apply func(key, value string) error
Stage func(key, value string) error
Disconnect func() (*DisconnectPlan, error)
Execute func(*DisconnectPlan) error
ExecuteOffline func(*DisconnectPlan) error
}
NativeConnection registers a provider independently of model selection. Its plan describes file and runtime changes without performing either.
type NativeField ¶ added in v0.1.972
type NativeState ¶ added in v0.1.972
type NativeState struct {
Provider string `json:"provider"`
Detail string `json:"detail,omitempty"`
Runtime string `json:"runtime"`
Fields map[string]NativeField `json:"fields"`
}
type NoModelsError ¶ added in v0.1.1024
type NoModelsError struct{ Agent string }
Connect puts magpie into the agent's config, the Agents page's switch (the owner: an agent is connected to magpie, and its models are picked in the agent): the agent's main field goes to one of magpie's models — the one serving the model it is on now, else the first — or to magpie itself for an app whose one setting is magpie as its provider. Setting it writes the provider and the whole catalog in, so the agent's own model list has every one of magpie's models. An agent that can keep the model it is on (Join) keeps it. An agent already connected is left as it is. NoModelsError is Connect's answer while magpie has no models to give the agent: no provider or subscription has been added yet. The GUI says it in the reader's language by its code (no_models).
func (*NoModelsError) Error ¶ added in v0.1.1024
func (e *NoModelsError) Error() string
type OfflineAction ¶ added in v0.1.972
type OfflineAction string
const ( OfflineStage OfflineAction = "stage" OfflineDisconnect OfflineAction = "disconnect" )
type Option ¶
type Option struct {
Value string `json:"value"`
Label string `json:"label,omitempty"` // display name, when the value is an id
Note string `json:"note"`
Icon string `json:"icon,omitempty"` // bundled icon name
Icons []string `json:"icons,omitempty"` // a routing group's providers' icons, stacked
Group string `json:"group,omitempty"` // section header in the picker
// GroupIcon is the group's own logo in the picker's rail, when it is
// not the first model's (a provider serving other vendors' models)
GroupIcon string `json:"groupIcon,omitempty"`
Ref string `json:"ref,omitempty"` // the catalog model, the same in every agent
Free bool `json:"free,omitempty"` // costs its subscription nothing
// Rate and RateWas are the credits a request costs its subscription,
// as a multiple, and before a discount running now (Qoder's 0.5×,
// WorkBuddy's x0.03), when its vendor lists them
Rate float64 `json:"rate,omitempty"`
RateWas float64 `json:"rateWas,omitempty"`
// Context is the tokens the model takes, when known; the picker marks
// the large ones
Context int `json:"context,omitempty"`
// Takes, on an effort field's default (Value ""), is the level the
// agent takes for the model with none set (Codex: the catalog entry's
// default_reasoning_level), shown beside "default"
Takes string `json:"takes,omitempty"`
// Direct names who the agent asks for this model itself, on its own
// sign-in or key, with magpie not in the way ("Anthropic"): its config
// then names no magpie endpoint, which is right, not a failed setup
Direct string `json:"direct,omitempty"`
// Via is a model of the agent's own it asks through magpie's gateway,
// on its own sign-in all the same (Codex's while routed by its base
// URL): the picker says via magpie by it, as by a catalog model's
Via bool `json:"via,omitempty"`
// Same is a model magpie serves on the very account the agent is
// signed in to itself, so the agent reaches it on its own too: the
// picker folds these into one row a click opens (Claude Code, #496)
Same bool `json:"same,omitempty"`
// Alias is the value of the option a dated id is another name of
// (claude-opus-4-5-20251101 → claude-opus-4-5): the picker shows one
// row for the two, the alias, unless the dated one is the value set
Alias string `json:"alias,omitempty"`
// FastFor is the agent a catalog model with a fast mode (provider.
// CanFast) is switched fast or not for, by the model in the picker
// (#954): the one whose requests the gateway sends it on; Fast is
// whether it is now (provider.IsFastPick)
FastFor string `json:"fastFor,omitempty"`
Fast bool `json:"fast,omitempty"`
// OwnFast: its fast mode is a GPT model's on a provider the user added
// by its address (provider.OwnFast, #1615), asked for there as OpenAI's
// priority, which the provider may or may not serve
OwnFast bool `json:"ownFast,omitempty"`
// contains filtered or unexported fields
}
Option is one value the picker offers for a field.
type PlannedFile ¶ added in v0.1.972
type PlannedSetting ¶ added in v0.1.972
type PlannedSetting struct {
Key string
Before json.RawMessage
After json.RawMessage
}
type RuntimeUnavailableError ¶ added in v0.1.972
type RuntimeUnavailableError struct {
}
RuntimeUnavailableError is created only for an initial runtime read, before the operation has written either runtime settings or local files.
func (*RuntimeUnavailableError) Error ¶ added in v0.1.972
func (e *RuntimeUnavailableError) Error() string
func (*RuntimeUnavailableError) Unwrap ¶ added in v0.1.972
func (e *RuntimeUnavailableError) Unwrap() error
type StaleCopy ¶ added in v0.1.1110
type StaleCopy struct {
// Kind, for Codex: "app" (the ChatGPT or Codex desktop app, its
// app-server and helpers), "ide" (an editor extension's), "daemon"
// (the background app-server the CLI leaves running), "helper" (a
// subcommand the daemon spawns beside itself, no copy to reopen) or
// "cli"; "" for other agents; "embedded" is another app's own Codex,
// named by App
Kind string `json:"kind,omitempty"`
App string `json:"app,omitempty"`
Since time.Time `json:"since"`
}
StaleCopy is a copy of an agent still running on the list it started with: what kind of copy it is, which says how it is reopened, and when it started.
type TuneSetting ¶ added in v0.1.1158
type TuneSetting struct {
Value string `json:"value,omitempty"` // "" when nothing sets it
// Where Value comes from: settings (the agent's own config file),
// model (Claude Code's modelSettings for the model), env
Source string `json:"source,omitempty"`
// Locked names the variable that takes precedence over the setting,
// which tune leaves as it is: putting the advice in would change nothing
Locked string `json:"locked,omitempty"`
// Ours: tune put Value in, and Undo puts back what was there
Ours bool `json:"ours,omitempty"`
}
TuneSetting is one of those settings as an agent has it now.
func TuneRead ¶ added in v0.1.1158
func TuneRead(home, agent, knob, model string) (TuneSetting, error)
TuneRead is how an agent has a setting tune advises now.
Source Files
¶
- agent.go
- agents.go
- agy.go
- air.go
- alma.go
- ante.go
- applied.go
- aside.go
- aside_account.go
- aside_native.go
- aside_stage.go
- astrbot.go
- atomcode.go
- cindy.go
- claude.go
- claudedesktop.go
- cline.go
- cliupdate.go
- cliupdate_shim.go
- codebuddy.go
- codex.go
- codex_daemon.go
- codex_proxy.go
- commandcode.go
- connectinfo.go
- copilotjetbrains.go
- cursorlocal.go
- cursorlocal_env_other.go
- cursorlocal_installs_other.go
- desktopapp.go
- desktopapp_other.go
- devin.go
- droid.go
- dsh.go
- dsh_search.go
- empryo.go
- fx.go
- gatewaykey.go
- gemini.go
- goose.go
- grok.go
- grokapp.go
- hanako.go
- hermes.go
- icons.go
- install.go
- inuse.go
- jcode.go
- keptaway.go
- kimi.go
- legacy.go
- minimax.go
- morph.go
- muse.go
- native.go
- nativemodels.go
- notice.go
- omo.go
- omp.go
- omp_scope.go
- openchamber.go
- pencil.go
- pi.go
- plugged.go
- preview.go
- primeagent.go
- qoder.go
- qwen.go
- reach.go
- reasonix.go
- reasonix_detect.go
- reasonix_detect_other.go
- reasonix_studio.go
- rename.go
- rescan.go
- reseat.go
- rewire.go
- route.go
- snow.go
- stash.go
- stepcode.go
- sync.go
- t3code.go
- tune.go
- vscode.go
- workbuddy.go
- writable_other.go
- wsl.go
- wsl_fake.go
- zcode.go
- zed.go
- zed_credential_other.go