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
- func AgyLaunch(model string) string
- func CLIs(wait time.Duration) (out map[string]CLI, pending bool)
- func CindyLink(url string) string
- func DesktopConfig3p(home string) string
- func DryRun(id string) error
- func DshPatchFiles(dir string) []string
- func FakeWSL(probes, roots map[string]string) func()
- func KeepDshWired(ctx context.Context)
- 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 RenameLegacy()
- func RenameProvider(from, to string) ([]string, error)
- func Running(patterns ...string) bool
- func StandIn(agent, model string) string
- func SyncCatalog()
- func Taken(p string) bool
- type Agent
- func (a *Agent) Apply(key, v string) error
- func (a *Agent) CLI() (c CLI, ok bool)
- func (a *Agent) Connect() error
- func (a *Agent) Detected() bool
- func (a *Agent) Disconnect() error
- func (a *Agent) Drift() *Drift
- func (a *Agent) Field(key string) *Field
- func (a *Agent) InstalledVersion() string
- func (a *Agent) Keep()
- func (a *Agent) Pick(key, v string) error
- 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) UpdateCLI() (CLI, error)
- func (a *Agent) Values() map[string]string
- func (a *Agent) Wired() bool
- type CLI
- type Drift
- type Field
- type FileChange
- type LineDiff
- type Move
- type Option
Constants ¶
const CindyScheme = "cindy://provider/import?"
CindyScheme begins every Cindy import link.
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 ¶
This section is empty.
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 DesktopConfig3p ¶ added in v0.1.474
DesktopConfig3p is the claude_desktop_config.json Claude Desktop reads in its 3p mode: there its whole userData is Claude-3p, its MCP servers too (%LOCALAPPDATA%\Claude-3p on Windows, 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 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 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 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 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 Running ¶
Running reports whether a process whose command line matches any pattern (an extended regexp, as for pgrep -f) is alive. Unknown on Windows.
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 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.
Types ¶
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
Fields []Field
// 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
// 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
// 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
// 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)
// contains filtered or unexported fields
}
Agent is one supported coding agent.
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 (*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.
func (*Agent) CLI ¶ added in v0.1.397
CLI is the agent's CLI: its version, the newest, and whether magpie can update it. ok is false for an agent without a CLI magpie knows.
func (*Agent) Connect ¶ added in v0.1.780
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.
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) 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) 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) 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) 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.
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. Zero where it can't be told (Windows).
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"`
}
CLI is what magpie knows of an agent's command-line program.
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.
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
}
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), for a profile's details to say so.
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 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 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"`
// 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"`
// 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"`
// contains filtered or unexported fields
}
Option is one value the picker offers for a field.
Source Files
¶
- agent.go
- agents.go
- agy.go
- alma.go
- applied.go
- cindy.go
- claude.go
- claudedesktop.go
- cline.go
- cliupdate.go
- codex.go
- commandcode.go
- connectinfo.go
- devin.go
- droid.go
- dsh.go
- empryo.go
- fx.go
- gemini.go
- goose.go
- grok.go
- hanako.go
- hermes.go
- icons.go
- kimi.go
- legacy.go
- minimax.go
- muse.go
- nativemodels.go
- omo.go
- omp.go
- openchamber.go
- pencil.go
- pi.go
- preview.go
- qoder.go
- rename.go
- reseat.go
- route.go
- stash.go
- sync.go
- t3code.go
- workbuddy.go
- writable_other.go
- wsl.go
- wsl_fake.go
- zcode.go
- zed.go
- zed_credential_other.go