provider

package
v0.1.453 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2026 License: MIT Imports: 50 Imported by: 0

Documentation

Overview

Package provider holds the model vendors magpie can reach: where each one lives, which protocols it speaks, the API key the user typed in, and which of its models should show up in the agents' pickers.

Provider keys are never read from environment variables. A provider is exactly what the user entered, kept in ~/.config/magpie/providers.json (mode 0600).

Index

Constants

View Source
const (
	ViaSystemOne  = "systemone"
	ViaVercel     = "vercel"
	ViaVercelEval = "vercel-eval"
	ViaCloudflare = "cloudflare"
)

The ways a decision API is asked, by where it is (DecideVia): TypeSafe's own System One; Vercel's AI Gateway, at its TypeSafe API (System One's questions and answers, with its own name for Jev) or, where an older setup points, at the AI SDK's evaluation models (a boolean for a noul and probabilities for a confidence); or Workers AI (System One's questions and answers, in Cloudflare's envelope and at an account's address).

View Source
const (
	AffinitySession = "session"
	AffinityTurn    = "turn"
	AffinityOff     = "off"
)
View Source
const (
	Ordered   = "order"
	Rotate    = "rotate"
	LeastUsed = "usage"
)

The routings besides the default, smart, in order.

View Source
const (
	CheckinClaimed    = "claimed"    // claimed by magpie
	CheckinDone       = "done"       // in already, pressed in WorkBuddy or before
	CheckinIneligible = "ineligible" // the account can't take part
	CheckinInactive   = "inactive"   // no event running, or it has ended
	CheckinFailed     = "failed"     // no answer; tried again later that day
)

What came of a day's check-in, WorkBuddyCheckin.Outcome.

View Source
const AntigravityRisk = "Google may suspend an Antigravity account it sees used outside Antigravity. Use one you can afford to lose."

AntigravityRisk is what magpie says before an Antigravity account is added.

View Source
const AzurePreset = "azure"

AzurePreset is the preset's id.

View Source
const CodexDaemonRestart = "codex app-server daemon restart"

CodexDaemonRestart is the command that restarts Codex's app-server, for the user to run themselves.

View Source
const CommandCodePlanID = "commandcode-plan"

CommandCodePlanID is the subscription's id, and its sign-in's.

View Source
const CopilotAuto = "auto"

CopilotAuto is the model id that has Copilot pick the model.

View Source
const EffortAuto = "auto"

EffortAuto is a group whose classifier picks each turn's reasoning effort (Group.Effort).

View Source
const GroupPrefix = "group/"

GroupPrefix starts a group's id in the catalog: "group/<id>".

View Source
const JevLatest = "jev-latest"

JevLatest is the Jev a decision provider is asked with when the user picked none: TypeSafe's latest stable one.

View Source
const MaxIcon = 1 << 20

MaxIcon is the largest picture magpie keeps for a provider.

View Source
const MaxIntent = 200

MaxIntent is how long an intent may be, in characters.

View Source
const MiMoID = "mimo-app"

MiMoID is the MiMo subscription's id, as a provider and in logins.json.

View Source
const Scheme = "magpie"

Scheme is the URL scheme magpie registers with the system.

View Source
const SpentShare = 98

SpentShare is the share of an allowance past which an account is all but used up: Smart routing keeps it for when no other can take a request, and the agent signed in to it is signed in to another.

View Source
const UnknownRuleWord = "unknown "

UnknownRuleWord starts the error for a word ParseRule doesn't know.

View Source
const WorkBuddyAIID = "workbuddy-ai"

WorkBuddyAIID is WorkBuddy AI's subscription, the international build's.

Variables

View Source
var (
	ZCodeZaiBase      = "https://api.z.ai/api/anthropic"
	ZCodeBigModelBase = "https://open.bigmodel.cn/api/anthropic"
)

Where ZCode's coding plan and its sign-in are; vars so tests can point them elsewhere.

Affinities are how long a conversation stays with the key or account that answered it: "" auto, as long as what the vendor cached of it is worth keeping; for the whole session; within a turn only, free to move when the user speaks again; or never.

View Source
var CodexBase = "https://chatgpt.com/backend-api/codex"

CodexBase is where a ChatGPT account's Codex requests go; a var so tests can point it elsewhere.

View Source
var CopilotTokenURL = "https://api.github.com/copilot_internal/v2/token"

CopilotTokenURL trades the GitHub OAuth token for a short-lived Copilot session token; a var so tests can point it elsewhere.

View Source
var CopilotUserURL = "https://api.github.com/copilot_internal/user"

CopilotUserURL says where an account's Copilot API is; a var so tests can point it elsewhere.

View Source
var CursorExecutable = func() string {
	for _, name := range []string{"cursor-agent", "agent"} {
		if p, err := exec.LookPath(name); err == nil && (name == "cursor-agent" || isCursorAgent(p)) {
			return p
		}
	}
	home, _ := os.UserHomeDir()
	for _, p := range []string{filepath.Join(home, ".local", "bin", "cursor-agent"), "/usr/local/bin/cursor-agent", "/opt/homebrew/bin/cursor-agent"} {
		if st, err := os.Stat(p); err == nil && !st.IsDir() {
			return p
		}
	}
	return ""
}

CursorExecutable finds the cursor-agent CLI; a var so tests can fake it.

View Source
var DevinExecutable = func() string {
	if p, err := exec.LookPath("devin"); err == nil {
		return p
	}
	home, _ := os.UserHomeDir()
	for _, p := range []string{filepath.Join(home, ".local", "bin", "devin"), "/usr/local/bin/devin", "/opt/homebrew/bin/devin"} {
		if st, err := os.Stat(p); err == nil && !st.IsDir() {
			return p
		}
	}
	return ""
}

DevinExecutable finds the devin CLI; a var so tests can fake it.

View Source
var Efforts = []string{"low", "medium", "high", "xhigh", "max"}

Efforts are the reasoning levels a rule can ask for, lowest first.

View Source
var ErrMiMoSignIn = errors.New("the Xiaomi MiMo sign-in has expired — sign in again")

ErrMiMoSignIn is an account Xiaomi no longer signs in: it must be signed in again.

View Source
var ErrQoderSignIn = errors.New("Qoder sign-in")

ErrQoderSignIn is under every error that says the Qoder sign-in itself is gone — not signed in, unreadable, or its refresh refused — as against a refresh that timed out or never reached Qoder, which may pass.

View Source
var ErrZedSignIn = errors.New("the Zed sign-in has expired — sign in again")

ErrZedSignIn is an account Zed no longer takes: it must be signed in again.

View Source
var GitHubUserURL = "https://api.github.com/user"

GitHubUserURL says whose a GitHub token is; a var so tests can point it elsewhere.

View Source
var GrokExecutable = func() string {
	home, _ := os.UserHomeDir()
	path := append(filepath.SplitList(os.Getenv("PATH")), registryPath()...)
	for _, c := range grokCandidates(runtime.GOOS, home, GrokHome(), os.Getenv("GROK_BIN_DIR"), path) {
		if isFile(c.path) && (c.own || isGrokBuild(c.path)) {
			return c.path
		}
	}
	return ""
}

GrokExecutable finds the Grok Build CLI; a var so tests can fake it.

View Source
var KiroExecutable = func() string {
	if p, err := exec.LookPath("kiro-cli"); err == nil {
		return p
	}
	home, _ := os.UserHomeDir()
	for _, p := range []string{filepath.Join(home, ".local", "bin", "kiro-cli"),
		"/Applications/Kiro CLI.app/Contents/MacOS/kiro-cli", "/usr/local/bin/kiro-cli", "/opt/homebrew/bin/kiro-cli"} {
		if st, err := os.Stat(p); err == nil && !st.IsDir() {
			return p
		}
	}
	return ""
}

KiroExecutable finds kiro-cli, which refreshes its own sign-in; a var so tests can fake it. The installer puts it in ~/.local/bin, and on macOS inside Kiro CLI.app as well.

View Source
var Levels = []string{"none", "minimal", "low", "medium", "high", "xhigh", "max"}

Levels are the reasoning levels a model whose own aren't known can be given.

View Source
var MemberEfforts = []string{"none", "minimal", "low", "medium", "high", "xhigh", "max"}

MemberEfforts are the levels a group's member may be fixed at, lowest first: the words agents and vendors use for reasoning effort.

View Source
var OnSubscriptionUsage func()

OnSubscriptionUsage is told when a refresh has landed, for what shows a stale copy meanwhile (the menu bar's text) to read the new one.

Protocols in the order magpie prefers them when it has to translate.

Functions

func APIError

func APIError(b []byte, fallback string) string

APIError pulls the human message out of an error body when there is one. Google's "verify your account" refusal also says what to do about it, with the link it gave.

func Add added in v0.1.50

func Add(p Provider) (string, error)

Add saves a provider the user just added, beside those already here: an id in use — the preset's, or the one its name slugs to — moves on to the next free one (anthropic-2), and a name in use gets the same number, so a second key of a vendor, or one key for another workspace, is a provider of its own rather than one replacing the first. It answers the id saved.

func AddKey added in v0.1.14

func AddKey(id, name, key string, proto Protocol) error

AddKey saves one more key for a provider, on: it takes requests after the ones before it. It becomes the first when the provider has none.

func Allowances added in v0.1.29

func Allowances(agent string) map[string]Allowance

Allowances is each of an agent's accounts' allowance by user, as last known, asked for again in the background when that was over a minute ago. Only the very first ask waits, and not for long. An account missing is one not known yet.

func AntigravityBase added in v0.1.299

func AntigravityBase(id string) (base, effort string, ok bool)

AntigravityBase is the model magpie offers for one of Antigravity's ids at a level ("gemini-3.7-flash-low" is gemini-3.7-flash at low), and that level; ok is false for an id that is itself a model magpie offers, or that no family has. Picks and agents' models saved before the families were one model still name these ids.

func AntigravityVariants added in v0.1.299

func AntigravityVariants(model string) (map[string]string, bool)

AntigravityVariants are Antigravity's ids a model magpie offers stands for, by level, "" the default; ok is false for a model that stands for none, which goes to Antigravity as it is.

func ApplyImage added in v0.1.413

func ApplyImage(pid, model string, images bool, known *bool) (bool, *bool)

ApplyImage is what magpie tells of model: the user's answer when they gave one, else images as the vendor's list has it (known is that list's explicit answer, nil when it didn't say).

func AuthHeaders

func AuthHeaders(p Provider, proto Protocol) map[string]string

AuthHeaders is how a request to the vendor proves who it is. Anthropic's own API wants x-api-key alone, and so does Bedrock's, which turns away a request with both (#176); other compatible vendors take either, so both. Azure OpenAI takes a key in api-key alone: a Bearer there is an Entra ID token, and the key sent as one is turned away.

func AzureBase added in v0.1.419

func AzureBase(raw string) (string, bool)

AzureBase is the v1 API base of the resource an endpoint names, as it was pasted from the portal or another app — the bare resource (https://r.openai.azure.com), …/openai, …/openai/v1, a classic deployment's URL with its api-version, or only the resource's name — and ok false when it names no Azure resource.

func AzureHost added in v0.1.419

func AzureHost(host string) bool

AzureHost reports whether host is an Azure OpenAI resource's.

func Balance added in v0.1.37

func Balance(ctx context.Context, p Provider) (amount string, ok bool, err error)

Balance asks the vendor what is left on the provider's key in use. ok is false when there is no way to ask it.

func CCSwitchSkillOrigin added in v0.1.83

func CCSwitchSkillOrigin(dir string) (repo, branch string, ok bool)

CCSwitchSkillOrigin is the GitHub repository (owner/name) and branch CC Switch installed the skill in its folder dir from, as its database records it.

func CCSwitchSkillsDir added in v0.1.83

func CCSwitchSkillsDir() string

CCSwitchSkillsDir is the folder CC Switch keeps the skills it installs in.

func CancelSignIn added in v0.1.14

func CancelSignIn(id string)

CancelSignIn stops waiting for the browser.

func ClaudeWarmed added in v0.1.223

func ClaudeWarmed() map[string]time.Time

ClaudeWarmed is when magpie last started a window of each Claude account, by user as kept (lower-cased).

func CodexDaemonStale added in v0.1.368

func CodexDaemonStale() string

CodexDaemonStale answers the account Codex's app-server is still signed in to when Codex has been switched to another since it started, "" when it isn't running or is on the account Codex is.

func CodexListed added in v0.1.54

func CodexListed() []catalog.Model

CodexListed is the catalog as a Codex signed in to ChatGPT is handed it, after the backend's own models: all but a ChatGPT account's in magpie, which the backend lists already. A group answers for its first member but is not that provider's.

func CodexNativePicked added in v0.1.292

func CodexNativePicked() (map[string]bool, bool)

CodexNativePicked is the set of the ChatGPT account's own model slugs the user kept, and whether they narrowed that list at all. The backend lists every model the account can reach; when the user has picked among them on the codex provider, the gateway keeps its /models answer to those (see codexModels). Not narrowed — the account's list is left whole.

func CodexUsedUp added in v0.1.44

func CodexUsedUp(ctx context.Context) bool

CodexUsedUp reports whether the ChatGPT account Codex is signed in to has used up its allowance for now; false when that isn't known.

func CodexWarmed added in v0.1.182

func CodexWarmed() map[string]time.Time

CodexWarmed is when magpie last started a window of each ChatGPT account, by user as kept (lower-cased).

func CommandCodeGenerate added in v0.1.434

func CommandCodeGenerate(ctx context.Context, p Provider) (api, key string, ok bool)

CommandCodeGenerate says whether p is a Command Code account on the Go plan, which is asked at api+"/alpha/generate" in the CLI's own format rather than on the Provider API, with key; ok is false for every other account and provider.

func CursorBase added in v0.1.297

func CursorBase(id string) (base, effort string, ok bool)

CursorBase is the model magpie offers for one of Cursor's ids at an effort ("grok-4.7-low" is grok-4.7 at low, "grok-4.7-low-fast" grok-4.7-fast at low), and that effort; ok is false for an id that is itself a model magpie offers, or that no family has. Picks and agents' models saved before the families were one model still name these ids.

func CursorClientVersion added in v0.1.198

func CursorClientVersion() string

CursorClientVersion is the cursor-agent the API is told it is talking to, "cli-<version>": the installed one, as the API turns away a version it no longer supports.

func CursorToken added in v0.1.198

func CursorToken() (string, error)

CursorToken is the token to call Cursor's API with. One about to run out is renewed by cursor-agent, which does that whenever it runs.

func CursorVariants added in v0.1.268

func CursorVariants(model string) (map[string]string, bool)

CursorVariants are Cursor's ids a model magpie offers stands for, by effort, "" the default; ok is false for a model that stands for none, which goes to Cursor as it is.

func DecideRouteStatus added in v0.1.411

func DecideRouteStatus(err error) int

DecideRouteStatus is the HTTP status a System One request gets for err from RouteDecider: 400 when the model is named badly, 404 when magpie has no such Jev provider.

func Delete

func Delete(id string) error

Delete removes a provider. An account is only hidden from magpie (its model picks kept); signing out is the agent's job.

func DeleteGroup added in v0.1.38

func DeleteGroup(id string) error

DeleteGroup removes a group of the user's; one magpie found is hidden, to come back with ShowGroup. A group another has in it, or classifies with, stays until it is taken out of that one.

func DevinAuth added in v0.1.175

func DevinAuth() (key, server string, err error)

DevinAuth is the key the CLI signed in with and the server its API is on, read from credentials.toml; WINDSURF_API_SERVER_URL moves the server, as it does the CLI's.

func DevinAuthAt added in v0.1.386

func DevinAuthAt(home string) (key, server string, err error)

DevinAuthAt is DevinAuth for the account signed in in home, "" for the CLI's own.

func DevinCredentialsPath added in v0.1.45

func DevinCredentialsPath() string

DevinCredentialsPath is where the CLI keeps its sign-in.

func DevinNoWait added in v0.1.424

func DevinNoWait(ctx context.Context) context.Context

DevinNoWait marks a context whose caller must not wait on the devin CLI: the window's state, drawn after every click. DevinFamilies then answers with what it knows (or an error while nothing is known) and asks the CLI in the background, so the next state has it.

func DevinOffered added in v0.1.380

func DevinOffered(families []DevinFamily) []catalog.Model

DevinOffered is Devin's list as an agent's picker offers it: each family one model with the efforts its variants are at, as the provider lists it (devinModels), and Adaptive and Fusion — which Devin's own agent runs, though the API doesn't serve them — as the one model each.

func DevinPick added in v0.1.380

func DevinPick(families []DevinFamily, model, effort string) string

DevinPick is the id to give Devin's config for a model and effort picked as magpie offers them (DevinSplit the other way round): a family's variant at the effort, or the nearest it has; the family's own id with no effort, so that it keeps following the family's default; a fast run's variant at the effort, or at the family's default one. Any other id goes as it is.

func DevinSplit added in v0.1.380

func DevinSplit(families []DevinFamily, id string) (model, effort string)

DevinSplit is an id Devin's config holds taken apart as magpie offers it: the model (a family, or a family's fast run) and the effort the id is at. A family's own id is at none — it follows the family's default — and an id no family has at an effort (glm-5-2-1m, one Devin no longer lists) is itself, at none.

func DevinVariant added in v0.1.175

func DevinVariant(ctx context.Context, model, effort string) string

DevinVariant is the model to ask Devin's API for: a family's name follows its newest model, which the API takes only as one of its variants — the one at the effort asked for, or at the nearest effort the family has; with none asked, the family's default. A family's fast run (claude-opus-5-5-fast) is likewise its fast variant at that effort (claude-opus-5-5-high-fast). A variant's own id (swe-2-medium, one an agent was set to) goes as it is, whatever effort is asked: its id is the effort it runs at.

func DismissCodexDaemon added in v0.1.368

func DismissCodexDaemon()

DismissCodexDaemon stops saying the app-server is on another account.

func EffortsOf added in v0.1.137

func EffortsOf(m catalog.Model) []string

EffortsOf is the reasoning levels one of a provider's listed models has, before any the user left out.

func Families added in v0.1.111

func Families() []string

Families are the families providers and groups are tagged with, sorted.

func FaviconFor added in v0.1.186

func FaviconFor(ctx context.Context, base string) (string, error)

FaviconFor finds the site behind a provider's base URL and keeps its icon like a picture picked by hand (#12). The API's own host is asked first, then the domains it sits under (api.deepseek.com, then deepseek.com), since an API host seldom has a page of its own. On each, the home page's <link rel="icon"> pictures come before /favicon.ico. Only public https hosts are reached, as for an import link's icon.

func FetchIcon added in v0.1.21

func FetchIcon(ctx context.Context, rawURL string) (string, error)

FetchIcon downloads the picture an import link named and keeps it like any other, returning the Icon value that points at it. It runs when the user confirms the import, never at parse time; the URL is re-checked here so a crafted request can't point magpie at anything but a public https picture, and the read stops one byte past MaxIcon so a huge body is refused rather than buffered.

func FetchNew added in v0.1.402

func FetchNew(timeout time.Duration)

FetchNew asks each signed-in account whose vendor list magpie hasn't fetched yet for it, each for at most timeout. Start-up does this for the accounts there then; an account signed in while magpie runs (in magpie or in the agent's own app) otherwise showed magpie's built-in list, fewer models than the vendor serves, until Refresh was clicked (#204). One that fails is asked again after newFetchRetry, not each time.

func FindGroup added in v0.1.38

func FindGroup(id string) (Group, []Member, bool)

FindGroup looks a group up by its catalog id ("group/<id>") and resolves its members; one not ready now is left out.

func ForgetAccounts added in v0.1.362

func ForgetAccounts()

ForgetAccounts makes the next look at the accounts read them afresh, for a caller that changed a sign-in behind magpie's back (a test's home).

func ForgetBalances added in v0.1.90

func ForgetBalances()

ForgetBalances has the next KeyBalances ask again, after a provider's key or balance token changed.

func ForgetLogin added in v0.1.11

func ForgetLogin(agent, user string) error

ForgetLogin drops a remembered account. The one an agent is signed in to now can't be forgotten; it would only be remembered again.

func FreeID added in v0.1.399

func FreeID(id string) string

FreeID is id, or id-2, id-3… whichever no provider or subscription has.

func GrokHome added in v0.1.22

func GrokHome() string

GrokHome is where the CLI keeps its sign-in and settings.

func GrokUser added in v0.1.22

func GrokUser(home string) (string, bool)

GrokUser is who the grok with this home is signed in to.

func GroupFinder added in v0.1.133

func GroupFinder() func(id string) (Group, []Member, bool)

GroupFinder is FindGroup for looking up many: every provider's models are read once, when the first group is looked up, not again for each.

func GroupFor added in v0.1.136

func GroupFor(id string) (string, bool)

GroupFor is the group a model's id without a provider in it names, as "group/<id>": the group of that id, else the group of that model however a vendor spells it ("grok-4.7" is the group grok-4-7 or auto-grok-4-7). A request for the model is the group's then, as it would be for the group's own id; ok is false when no group has it. An id with a provider in it ("a/m") names that provider's model, never a group.

func GroupMember added in v0.1.136

func GroupMember(g Group, in string) (string, error)

GroupMember is the group's member a typed model names: its id, its model id without the provider, or the model's last name — each with the effort fixed on the member ("m:high") or, when only one member is of that model, without it.

func HasWorkBuddy added in v0.1.356

func HasWorkBuddy() bool

HasWorkBuddy says whether a WorkBuddy (China) account is signed in.

func HostOf

func HostOf(u string) string

HostOf pulls the host out of a URL, for display.

func IDs

func IDs() []string

IDs lists the catalog ids, for error messages.

func IconDir added in v0.1.10

func IconDir() string

IconDir is where pictures given to providers are kept.

func IconFile added in v0.1.10

func IconFile(name string) string

IconFile is the path of a stored picture, for a name as StoreIcon made it; "" for anything else, so a request can't reach outside the folder.

func IconForCatalog

func IconForCatalog(catalogID string) string

IconForCatalog names the logo of the vendor behind a models.dev provider id, or "" when no preset covers it.

func ImageOverride added in v0.1.413

func ImageOverride(pid, model string) (bool, bool)

ImageOverride is the user's answer for whether pid's model takes images.

func ImportFromApps added in v0.1.25

func ImportFromApps(picks []AppPick) ([]string, error)

ImportFromApps adds what the user picked, reading the sources again so keys never pass through the window. It answers the names added.

func Intents added in v0.1.95

func Intents(rules []Rule, q RuleRequest) []string

Intents are the intents the classifier is to choose among for q: those of the rules that match it but for their intent, up to the first that matches outright (a rule after it could never be the first to match). None when no rule before that one has an intent — the classifier then isn't asked. Each is given once, as the first rule has it.

func IsDecider added in v0.1.142

func IsDecider(id string) bool

IsDecider reports whether a classifier ("provider/model") is a decision provider's model.

func KeepClaudeWindowsWarm added in v0.1.223

func KeepClaudeWindowsWarm(ctx context.Context, send func(ctx context.Context, oauth string) error)

KeepClaudeWindowsWarm starts the Claude accounts' windows as they reset, while settings say to, each with one request send makes.

func KeepCodexWindowsWarm added in v0.1.182

func KeepCodexWindowsWarm(ctx context.Context)

KeepCodexWindowsWarm starts the ChatGPT accounts' windows as they reset, while settings say to, two minutes after it starts and every codexWarmEvery after that, until ctx ends.

func KeepLoginsAlive added in v0.1.75

func KeepLoginsAlive(ctx context.Context)

KeepLoginsAlive renews the saved sign-ins that are due, a minute after it starts and every hour after that — a computer that slept through a day catches up within the hour of waking — until ctx ends.

func KeepOnAnAccountWithRoom added in v0.1.402

func KeepOnAnAccountWithRoom(ctx context.Context)

KeepOnAnAccountWithRoom runs SwitchWhenSpent for Codex and Claude Code a minute after it starts and every loginSwitchEvery after that, until ctx ends.

func KeepWorkBuddyCheckedIn added in v0.1.356

func KeepWorkBuddyCheckedIn(ctx context.Context)

KeepWorkBuddyCheckedIn checks the WorkBuddy accounts in each day while settings say to: two minutes after it starts, every wbCheckinEvery after that, and as the Beijing day turns, until ctx ends.

func KeyID added in v0.1.14

func KeyID(key string) string

KeyID is the fingerprint a key is named by, in lists and in the gateway.

func KiroModel added in v0.1.141

func KiroModel(id string) (context int, images bool)

KiroModel is what Kiro last said of one of its models: how many tokens a prompt may hold, and whether it takes images; zero and false when it hasn't said.

func LoginUsage added in v0.1.14

func LoginUsage(ctx context.Context, agent string) map[string]SubscriptionQuota

LoginUsage is the allowance used by each of an agent's accounts, by user. What was fetched less than a minute ago comes from the cache; the rest is asked for at once, as long as ctx allows.

func MakerPrice added in v0.1.411

func MakerPrice(model string) (catalog.Price, bool)

MakerPrice is a model's list price as the first vendor among the presets that makes the models it serves lists it; for a call whose provider has gone since.

func Mask

func Mask(s string) string

Mask hides all but the ends of a secret.

func MatchRule added in v0.1.94

func MatchRule(rules []Rule, q RuleRequest) int

MatchRule is the first of rules the request matches, -1 for none.

func MemberEffort added in v0.1.379

func MemberEffort(id string) (model, effort string)

MemberEffort splits a group's member into the model it names and the effort fixed on it ("" for none): "a/m:high" is a/m at high, unless a has a model "m:high" of its own. A group in the group ("group/<id>") takes none; one typed with one comes back split, for SaveGroup to refuse.

func Mirror added in v0.1.76

func Mirror(ps []Provider, gs []Group) error

Mirror makes the providers and groups exactly these, as sync brings them from another computer: one not among them goes, one that came without keys keeps the keys it has here.

func ModelName added in v0.1.137

func ModelName(pid, model string) (string, bool)

ModelName is the name the user gave a provider's model, if any.

func NextLogin added in v0.1.402

func NextLogin(ctx context.Context, agent string) (from, to string, ok bool)

NextLogin is the account agent should be signed in to instead of the one it is on, when that one is spent: the first of its other accounts that are on in magpie, in the order they were saved, whose allowance is known and not spent. ok is false when the agent should stay.

func NoteClaudeLimits added in v0.1.199

func NoteClaudeLimits(user string, ls []ClaudeLimit)

NoteClaudeLimits keeps what Claude Code said of user's allowance as it answered, in place of the windows of the same names last read, and has routing weigh the account by it.

func OnAccountIDs added in v0.1.399

func OnAccountIDs() []string

OnAccountIDs are the user's own providers saved on a subscription's id, which hide that subscription once it is signed in (All lists the one saved): made before the id was a subscription's, as a WorkBuddy key was before WorkBuddy's plan was one. MoveOffAccountIDs moves them.

func OnRenewed added in v0.1.289

func OnRenewed(f func(agent, user string))

OnRenewed has f told when an account's usage windows were started again (a Codex reset spent), so what sat out waiting for them can come back.

func OpenReadOnly added in v0.1.92

func OpenReadOnly(path string) (*sql.DB, error)

OpenReadOnly opens another app's SQLite database without writing to it.

func ParseTokens added in v0.1.136

func ParseTokens(v string) (int, error)

ParseTokens reads 200000, 200k, 1.5m.

func Path

func Path() string

Path is the file the user's providers live in.

func PlanTerm added in v0.1.209

func PlanTerm(until *time.Time, renew string) string

PlanTerm says when a plan's paid time ends, "renews Oct 18", "expires Oct 18" or "until Oct 18" when the vendor doesn't say which; "" when it isn't known.

func PricedName added in v0.1.418

func PricedName(model string) string

PricedName is the id a model is priced by where it's looked up by maker directly (the Sessions page): a Grok id at an effort is its model.

func ProxyOf added in v0.1.418

func ProxyOf(id string) string

ProxyOf is the own proxy of the provider or signed-in account with id, "" when it follows the global one.

func ProxyOfLogin added in v0.1.427

func ProxyOfLogin(id, user string) string

ProxyOfLogin is the proxy requests made on behalf of the account user of the subscription id go through (gakki: one Codex account through one proxy, another through another): the account's own, or else the subscription's (ProxyOf); "" follows the global one.

func QoderAuthURL added in v0.1.392

func QoderAuthURL() (url string, flow *qoderFlow, err error)

func QoderCompleteSignIn added in v0.1.392

func QoderCompleteSignIn(ctx context.Context, fl *qoderFlow) (user string, err error)

func QoderCredential added in v0.1.392

func QoderCredential(ctx context.Context, user string) (*qoder.Credential, error)

QoderCredential returns an independent snapshot for the selected account.

func QoderModel added in v0.1.392

func QoderModel(ctx context.Context, user, key string) (qoder.ModelInfo, error)

QoderModel accepts only an enabled model in this account's own model list.

func QoderSignedIn added in v0.1.392

func QoderSignedIn() bool

func QuietAccount added in v0.1.204

func QuietAccount(id string) error

QuietAccount stops reminding the user of an account they removed: its "Add it back" line goes, and it is offered only from the Add sheet.

func RemoveKey added in v0.1.14

func RemoveKey(id, keyRef string) error

RemoveKey forgets a key. The last key in use stays: turn another on first.

func RemovedGroups added in v0.1.92

func RemovedGroups() []string

RemovedGroups are the found groups the user removed, whether or not magpie finds them now: each is a record in providers.json ({"id", "hidden": true}) that keeps it removed when two providers serve its model again.

func Rename added in v0.1.125

func Rename(from, to string) error

Rename gives a provider another id, the one its models are picked by (<id>/<model>). What magpie keeps that names it by id follows: the routing groups it is in and their rules and classifiers, the other providers' fallbacks, and which agents are shown it. The old id stays with it (Was), so an agent still running on a config that names it the old way reaches it, and its usage so far is counted with it; the agents' own files are the agent package's to rewrite (agent.RenameProvider). A signed-in account keeps the id of its agent.

func RenameGroup added in v0.1.105

func RenameGroup(from, to string) error

RenameGroup gives a group another id, the one agents pick it by (group/<id>). A group magpie found becomes the user's under the new id, the found one kept removed so it doesn't come back beside it. The groups that have it in them, and their rules, name it by the new id.

func RenameKey added in v0.1.14

func RenameKey(id, keyRef, name string) error

RenameKey names one of a provider's keys, "Personal", "Team".

func Renamed added in v0.1.125

func Renamed() map[string]string

Renamed maps the ids providers had to the ones they have now.

func RenamedRef added in v0.1.125

func RenamedRef(ref string) string

RenamedRef is ref with the provider it names by an id the provider had named by the id it has now.

func ResetClock added in v0.1.211

func ResetClock(at, now time.Time) string

ResetClock is when a window starts again, on the clock: "14:30" today, "tomorrow 09:00", "Wed 14:30" within the week, else "Oct 3 14:30".

func RestartCodexDaemon added in v0.1.368

func RestartCodexDaemon(ctx context.Context) error

RestartCodexDaemon has Codex restart its app-server, which reads the sign-in again: `codex app-server daemon restart`, run with the codex CLI magpie finds and the Codex home it signs Codex in through. The Codex sessions attached to it are ended.

func Restore added in v0.1.28

func Restore(ps []Provider) (added, replaced int, err error)

Restore puts providers from a backup in. Each replaces the one here with its id; one that came without keys keeps the keys already here. It returns how many were new and how many replaced one here.

func RestoreGroups added in v0.1.76

func RestoreGroups(gs []Group) error

RestoreGroups puts groups from a backup in, each replacing the one here with its id.

func RuleWords added in v0.1.136

func RuleWords(line string) []string

RuleWords splits a typed line into its words, a "quoted" part in one: intent="a quick question".

func Save

func Save(p Provider) error

Save adds or replaces a provider.

func SaveGroup added in v0.1.38

func SaveGroup(g Group) error

SaveGroup adds or replaces a group of the user's. Changing one magpie found makes it the user's.

func SaveStepFunPaste added in v0.1.389

func SaveStepFunPaste(ctx context.Context, site, text string) error

SaveStepFunPaste keeps the session the user pasted for the site: what the bookmarklet copied, or the Oasis-Token cookie as the browser's developer tools show it (the access token, three dots, the refresh one).

func SaveStepFunSession added in v0.1.389

func SaveStepFunSession(ctx context.Context, site, access, refresh, webID string) error

SaveStepFunSession keeps the session the sign-in page ended in, once the platform has taken it: a page that isn't signed in yet has an anonymous one, which is refused here.

func SawCodexClient added in v0.1.441

func SawCodexClient(h http.Header)

SawCodexClient notes the version a Codex client's request says it is — its `version` header, else the one in its User-Agent (codex_cli_rs/0.159.0, Codex Desktop/0.159.0) — when the request is Codex's (it names an originator, or its User-Agent is codex_…).

func SetAffinity added in v0.1.38

func SetAffinity(id, affinity string) error

SetAffinity changes how long a provider's conversations stay with the key or account that answered them.

func SetGoogleProject added in v0.1.63

func SetGoogleProject(agent, user, project string) error

SetGoogleProject names the Google Cloud project an account's requests go to, "" to let Code Assist pick; Code Assist Standard and Enterprise need one.

func SetKeyOn added in v0.1.14

func SetKeyOn(id, keyRef string, on bool) error

SetKeyOn turns a key on or off. The last key that's on stays on.

func SetKeyProtocol added in v0.1.15

func SetKeyProtocol(id, keyRef string, proto Protocol) error

SetKeyProtocol says which one protocol a key works with; empty is any.

func SetLoginOn added in v0.1.14

func SetLoginOn(agent, user string, on bool) error

SetLoginOn puts a saved account in use beside the agent's own, or takes it out. The account the agent is signed in to is always in use.

func SetModelEfforts added in v0.1.137

func SetModelEfforts(ref string, efforts []string) error

SetModelEfforts keeps only these of a provider's model's reasoning levels in the lists magpie hands out; none, or all it has, offers them all again. They must be levels the model has — or, for a model whose levels aren't known, any of Levels, which it is given; none takes them away.

func SetModelImage added in v0.1.413

func SetModelImage(ref string, images *bool) error

SetModelImage says whether a provider's model takes images, in place of what its vendor's list says. nil gives that answer back.

func SetModelName added in v0.1.137

func SetModelName(ref, name string) error

SetModelName names a provider's model, spelled "provider/model"; an empty name gives it back its own. The agents that keep the models in files of their own are told (catalog.Touched), as for any other change of the catalog.

func SetOff added in v0.1.346

func SetOff(id string, off bool) error

SetOff switches a provider off, or on again (see Provider.Off). Saving it brings the model lists written into agents' files up to date.

func SetRouting added in v0.1.25

func SetRouting(id, routing string) error

SetRouting changes how a provider's requests spread over its keys or accounts.

func ShowAccount added in v0.1.31

func ShowAccount(id string) error

ShowAccount brings back the signed-in account of an agent the user had removed from magpie.

func ShowGroup added in v0.1.38

func ShowGroup(id string) error

ShowGroup brings back a group magpie found that the user had removed.

func Shows added in v0.1.111

func Shows(names []string, e Entry) bool

Shows reports whether a visibility shows e.

func SignOutStepFun added in v0.1.389

func SignOutStepFun(site string) error

SignOutStepFun forgets the site's sign-in.

func Slug

func Slug(name string) string

Slug derives an id from a name: "My Relay" → "my-relay".

func StaleAllowance added in v0.1.38

func StaleAllowance(agent, user string)

StaleAllowance makes the next Allowances ask the vendor again for user's allowance rather than trust what it last said: the account just answered that it has run out.

func StepFunBookmarklet added in v0.1.389

func StepFunBookmarklet() string

StepFunBookmarklet is the bookmarklet the user runs on a StepFun platform page they are signed in on: it renews the session as the page does, on either site, and copies it to be pasted into magpie.

func StepFunOrigin added in v0.1.389

func StepFunOrigin(site string) string

StepFunOrigin is the site's platform.

func StepFunSignInURL added in v0.1.389

func StepFunSignInURL(site string) string

StepFunSignInURL is the page the user signs in on, for the site.

func StepFunSignedIn added in v0.1.389

func StepFunSignedIn(site string) bool

StepFunSignedIn reports whether magpie has a sign-in on the site.

func StepFunSite added in v0.1.389

func StepFunSite(p Provider) string

StepFunSite is which of StepFun's platforms the provider's key is for, "ai" or "com", or "" for another vendor.

func StoreIcon added in v0.1.10

func StoreIcon(data []byte) (string, error)

StoreIcon keeps a picture (PNG, JPEG, GIF, WebP, ICO or SVG) and returns the Icon value that points at it. The same picture is stored once.

func StoreIconFile added in v0.1.10

func StoreIconFile(path string) (string, error)

StoreIconFile is StoreIcon for a picture on disk.

func SubmitSignInCallback added in v0.1.415

func SubmitSignInCallback(id, raw string) error

SubmitSignInCallback finishes a browser sign-in whose callback could not reach this machine. Invalid input leaves the pending sign-in open to retry.

func SwitchLogin added in v0.1.11

func SwitchLogin(agent, user string) error

SwitchLogin signs an agent in to a remembered account. Sessions of the agent that are already running keep the account they started with until they restart; so does Codex's background app-server, which new Codex sessions attach to (CodexDaemonStale says when it is).

func SwitchWhenSpent added in v0.1.402

func SwitchWhenSpent(ctx context.Context, agent string) (string, error)

SwitchWhenSpent signs agent in to the next of its accounts when the one it is on is spent (NextLogin), and answers the account it signed it in to, "" when it stayed.

func TakesBalanceToken added in v0.1.90

func TakesBalanceToken(p Provider) bool

TakesBalanceToken says the provider's vendor tells the account's balance to a token of its own (BalanceToken), which the editor then asks for.

func TakesZhipuTeam added in v0.1.431

func TakesZhipuTeam(p Provider) bool

TakesZhipuTeam says p is a key of Zhipu's or Z.ai's, whose editor then offers the team's organization and project (#236).

func ThenUses added in v0.1.196

func ThenUses(rules []Rule, q RuleRequest, n int, use string) []string

ThenUses are the members the rules after the n-th (from 1) that also match q send to, each once and in the rules' order, leaving out use: who a request a rule sent to use fails over to before the group's others (#112).

func UseKey added in v0.1.14

func UseKey(id, keyRef string) error

UseKey makes one of a provider's keys the first, and turns it on; the one it replaces stays on, next in line.

func Verification added in v0.1.304

func Verification(b []byte) (link string, ok bool)

Verification says whether an error body is Google's refusal of an account it wants verified first — Cloud Code Assist's 403 whose details say VALIDATION_REQUIRED with a validation_url in their metadata (#152) — and the https link to verify it at, when the body has one.

func VerifyMessage added in v0.1.304

func VerifyMessage(said, link string) string

VerifyMessage is a verification refusal as the agent and the app show it: the vendor's words, then what to do.

func Via added in v0.1.418

func Via(ctx context.Context, id string) context.Context

Via is ctx for requests made on behalf of the provider or signed-in account with id (see Provider.Via).

func ViaLogin added in v0.1.427

func ViaLogin(ctx context.Context, id, user string) context.Context

ViaLogin is ctx for requests made on behalf of the account user of the subscription id (ProxyOfLogin).

func ViaSignedIn added in v0.1.427

func ViaSignedIn(ctx context.Context, id string) context.Context

ViaSignedIn is ctx for requests made with the sign-in an agent has now (Codex's own, relayed as it came): through the proxy of the account it is signed in to.

func VisibleTo added in v0.1.111

func VisibleTo(agent string) ([]string, bool)

VisibleTo is what agent's lists are narrowed to, and whether they are.

func WithMemberEffort added in v0.1.379

func WithMemberEffort(model, effort string) string

WithMemberEffort is the member id of model at effort: the model itself for "".

func ZedCloud added in v0.1.423

func ZedCloud() string

ZedCloud is where the gateway asks an account's models.

func ZedProviderOf added in v0.1.423

func ZedProviderOf(user, model string) string

ZedProviderOf is the provider (anthropic, open_ai, google, x_ai) whose API a model is asked in, as the account's list said, else guessed from its id.

func ZedToken added in v0.1.423

func ZedToken(ctx context.Context, user string, renew bool) (string, error)

ZedToken is a live model token for an account, minted anew when renew is set (the last one was refused) or none is kept.

Types

type Account

type Account struct {
	Agent string `json:"agent"`          // the agent's id: codex, copilot
	User  string `json:"user"`           // who is signed in: an email, a GitHub login
	Plan  string `json:"plan,omitempty"` // the subscription, when the agent says

	// Stream is set when the backend only streams; magpie then translates
	// a non-streaming request instead of relaying it.
	Stream bool `json:"-"`

	// Home is where a Grok, Kiro or Devin account keeps its sign-in: the
	// agent's own (the CLI's home for Grok, "" for Kiro and Devin), or one
	// of magpie's for a further account (grok_accounts.go, kiro_accounts.go,
	// devin_accounts.go).
	Home string `json:"-"`
	// contains filtered or unexported fields
}

Account is the signed-in agent behind a provider.

func (*Account) Lists added in v0.1.35

func (a *Account) Lists(model string) bool

Lists reports whether the account's plan has the model, as far as magpie knows: one whose list was never fetched is taken to have them all.

func (*Account) Token added in v0.1.14

func (a *Account) Token(ctx context.Context) (tok string, ok bool, err error)

Token is the access token of a saved account in use beside the agent's own; ok is false for the agent's own, which the agent signs itself.

type Allowance added in v0.1.29

type Allowance []Limit

Allowance is an account's allowance windows as last known.

func (Allowance) For added in v0.1.38

func (a Allowance) For(model string, now time.Time) (used float64, renews []time.Time)

For is what an allowance leaves a request for model at now: the share used of the fullest window that counts it, and when those windows renew, the biggest first — the longest, the week before the five hours in it. A window whose reset has passed is empty again, its next reset not known.

func (Allowance) Full added in v0.1.38

func (a Allowance) Full(model string, share float64, now time.Time) time.Time

Full is when an account used up for model can take it again: the last reset of its windows that are full, zero when none is or it isn't known.

type AppImport added in v0.1.25

type AppImport struct {
	Ref      string   `json:"ref"`            // stable within its source
	From     string   `json:"from,omitempty"` // where in the app: Claude Code, Codex…
	Provider Provider `json:"provider"`
	// Status is "new", "same" (magpie has it already: same endpoint and
	// key) or "taken" (its id is another provider's here).
	Status   string `json:"status"`
	Existing string `json:"existing,omitempty"` // the magpie provider it matches or collides with
	// KeyOf is a magpie provider at the same address with another key:
	// this one can join it as one more key instead of being a provider
	// of its own.
	KeyOf string `json:"keyOf,omitempty"`
	Off   string `json:"off,omitempty"`  // why it isn't picked by default
	Skip  string `json:"skip,omitempty"` // why it can't be imported at all
}

AppImport is one provider an app holds, as magpie would add it.

type AppPick added in v0.1.25

type AppPick struct {
	Source string `json:"source"`
	Ref    string `json:"ref"`
	Mode   string `json:"mode,omitempty"`
}

AppPick is one entry the user chose, and how it comes in: as a provider ("add", beside any with its id), in place of the one with its id ("replace"), or as one more key of the provider KeyOf names ("key").

type AppSource added in v0.1.25

type AppSource struct {
	ID    string      `json:"id"`   // cc-switch, alma
	Name  string      `json:"name"` // as the app calls itself
	Path  string      `json:"path"` // the file read
	Found bool        `json:"found"`
	Error string      `json:"error,omitempty"`
	Items []AppImport `json:"items"`
}

AppSource is one app magpie can import from, with what it holds.

func ImportSources added in v0.1.25

func ImportSources() []AppSource

ImportSources reads every app magpie can import from.

type ClaudeLimit added in v0.1.199

type ClaudeLimit struct {
	Kind     string
	Used     float64
	ResetsAt int64
}

ClaudeLimit is one allowance window as Claude Code tells it: its kind (five_hour, seven_day, seven_day_opus, seven_day_sonnet, seven_day_overage_included), the share used, 0–1, and when it renews, in Unix seconds (0 when not said).

type CodexWarm added in v0.1.182

type CodexWarm struct {
	User    string   `json:"user"`
	Windows []string `json:"windows"`
	Err     string   `json:"error,omitempty"`
}

CodexWarm is what came of looking at one account: the windows it was sent a request for, and why that failed.

type DevinFamily added in v0.1.45

type DevinFamily struct {
	UID     string
	Label   string
	Aliases []string
	Models  []catalog.Model
}

DevinFamily is one entry of `devin models list`: a name that follows the family's newest model, and the pinned variants under it.

func DevinFamilies added in v0.1.45

func DevinFamilies(ctx context.Context) ([]DevinFamily, error)

DevinFamilies is the CLI's model list, kept a few minutes: the picker and the provider ask for it often and `devin models list` spawns a process that takes seconds (switching Claude Code's model took 5–10s while every state asked it anew). A list past its time is served as it is while it is read again in the background; only a caller with nothing known yet waits, and not one marked DevinNoWait.

type Entry

type Entry struct {
	ID         string   `json:"id"`                // what the agent sends magpie
	Model      string   `json:"model"`             // what magpie sends the vendor
	Name       string   `json:"name"`              // the user's name for it, when they gave one (SetModelName)
	Default    string   `json:"default,omitempty"` // the model's own name, when the user gave it another
	Efforts    []string `json:"efforts,omitempty"`
	Provider   Provider `json:"-"`                // a group's: its first member's
	Group      string   `json:"group,omitempty"`  // set on a routing group (group.go)
	Icons      []string `json:"-"`                // a group's: its providers' icons, one per provider
	Images     bool     `json:"images,omitempty"` // takes images as input (a group's: every member does)
	ImageInput *bool    `json:"-"`                // explicit answer, nil when unknown
	// Context is the tokens a prompt may hold, when known (a group's: the
	// least of its members')
	Context int `json:"context,omitempty"`
	// Output is the most tokens a reply may hold, when known (a group's:
	// the least of its members')
	Output int `json:"output,omitempty"`
	// Family is the provider's or group's tag (see Visible).
	Family string `json:"family,omitempty"`
	// Free is set on a model its subscription serves at no cost to it.
	Free bool `json:"free,omitempty"`
}

Entry is one model as the agents see it.

func Catalog

func Catalog() []Entry

Catalog lists the routing groups, then every exposed model of every ready provider not kept unlisted. A provider switched off has none in it.

func CatalogFor added in v0.1.111

func CatalogFor(agent string) (shown, hidden []Entry)

CatalogFor is the catalog as agent is shown it, and what is kept from it (none when its lists aren't narrowed).

func Deciders added in v0.1.142

func Deciders() []Entry

Deciders are the models of the decision providers ready now, as a group's classifier names them.

func Served added in v0.1.77

func Served() []Entry

Served is the catalog with the unlisted providers' models as well: every model a routing group can be made of, or a request can name.

func (Entry) Label added in v0.1.137

func (e Entry) Label() string

Label is how an agent's list names the entry: its name (the user's own, when they gave one, else the vendor's) with its provider's after it, or "routing group" for a group's — dropped only when a name of the user's own already carries the provider's, so it isn't said twice.

func (Entry) Names added in v0.1.111

func (e Entry) Names() []string

Names are what an entry answers to in a visibility: its family, and its provider's id or its group's id (as group/<id> too).

type Exclusion

type Exclusion struct {
	Agent    string `json:"agent"`
	Provider string `json:"provider,omitempty"` // set when the user removed it; saving it brings it back
	Why      string `json:"why"`
	// SignedOut: the agent has accounts saved in magpie but isn't signed
	// in where magpie looks, and so none of them is offered.
	SignedOut bool `json:"signedOut,omitempty"`
	// Quiet: the user asked not to be reminded of it; only the Add sheet
	// offers it back.
	Quiet bool `json:"quiet,omitempty"`
}

Exclusion is a sign-in magpie found but will not offer as a provider.

func Excluded

func Excluded() []Exclusion

Excluded lists sign-ins magpie detects but leaves out: the accounts the user removed from magpie, and the saved accounts of an agent that isn't signed in here (a magpie serve under another HOME, say).

type Group added in v0.1.38

type Group struct {
	ID       string   `json:"id"`
	Name     string   `json:"name"`
	Members  []string `json:"members"`            // "provider/model[:effort]" or "group/<id>", in order (see MemberEffort)
	Routing  string   `json:"routing,omitempty"`  // as Provider.Routing, over all the members' keys and accounts
	Affinity string   `json:"affinity,omitempty"` // as Provider.Affinity
	// Rules send the requests they match to one member first, in order:
	// the first that matches decides (see Rule).
	Rules []Rule `json:"rules,omitempty"`
	// Classifier is the model ("provider/model") asked which of the rules'
	// intents a user's message is, or a group ("group/<id>", never this
	// one) whose models are asked in turn, failing over as for any request.
	// Rules with an intent need one; a small, fast model without reasoning
	// does.
	Classifier string `json:"classifier,omitempty"`
	// Effort "auto" has the classifier — Jev, from TypeSafe's decision API,
	// or any model, asked in words — judge how hard each turn is to think
	// about as it begins, and the turn asks its model for that much
	// reasoning, where the agent asked for some (see EffortAuto).
	Effort string `json:"effort,omitempty"`
	// Context is how long a request the user says the group takes, in
	// tokens: agents are told it rather than its shortest member's.
	Context int `json:"context,omitempty"`
	// Family is a tag the group goes by in which agents are shown it
	// (settings' Visible), with its id.
	Family string `json:"family,omitempty"`
	// Auto is set on a group magpie found: one model served by several
	// providers. It is derived, never stored.
	Auto bool `json:"auto,omitempty"`
	// Hidden is stored for a found group the user removed.
	Hidden bool `json:"hidden,omitempty"`
}

Group is a routing group.

func Groups added in v0.1.38

func Groups() []Group

Groups lists the user's groups, then those magpie found, hidden ones too (marked so).

func GroupsWith added in v0.1.102

func GroupsWith(id string) []Group

GroupsWith are the groups that have the group id in them as a member.

func StoredGroups added in v0.1.76

func StoredGroups() []Group

StoredGroups is the groups as saved: the user's own, and the found ones the user removed.

func (Group) Ruled added in v0.1.142

func (g Group) Ruled() bool

Ruled reports whether the group decides anything as a user's turn begins: a rule to put a member first, or the turn's effort.

type ImportedAccount added in v0.1.326

type ImportedAccount struct {
	// User is the account's email, or "#n" (its place in the file) when
	// the file doesn't say and Google wasn't asked or didn't answer.
	User string `json:"user"`
	// Status: "added", "updated" (in magpie already, now with this
	// sign-in), "exists" (in magpie already with this very sign-in),
	// "failed".
	Status string `json:"status"`
	Plan   string `json:"plan,omitempty"`
	Error  string `json:"error,omitempty"`
}

ImportedAccount is what became of one account in an import.

func ImportGoogleAccounts added in v0.1.326

func ImportGoogleAccounts(ctx context.Context, agent string, files []string) ([]ImportedAccount, error)

ImportGoogleAccounts brings in the accounts in exports from other tools (see above), each file's text one element of files, and says what became of each.

func ImportLogins added in v0.1.401

func ImportLogins(ctx context.Context, agent string, files []string) ([]ImportedAccount, error)

ImportLogins brings in ChatGPT (agent "codex") or Claude ("claude") accounts from other tools' files (see above), each file's text one element of files, and says what became of each.

type KeyAccount added in v0.1.14

type KeyAccount struct {
	Name string `json:"name,omitempty"`
	Key  string `json:"key"`
	Off  bool   `json:"off,omitempty"`
	// Protocol, when set, is the only one the key works with: some relays
	// give out one key for Anthropic and another for OpenAI. Empty is any.
	Protocol Protocol `json:"protocol,omitempty"`
}

KeyAccount is a saved key after the first. Off keeps it without using it.

type KeyInfo added in v0.1.14

type KeyInfo struct {
	ID     string `json:"id"` // a fingerprint, to name it in a switch
	Name   string `json:"name,omitempty"`
	Masked string `json:"masked"`
	Active bool   `json:"active"` // the first, where requests go
	On     bool   `json:"on"`     // in use: the first, or next in line

	Protocol Protocol `json:"protocol,omitempty"` // the only one it works with
}

KeyInfo describes one of a provider's keys without giving it away.

type Kind

type Kind string

Kind groups presets in the picker.

const (
	KindVendor Kind = "vendor" // the model's own maker
	KindRelay  Kind = "relay"  // an aggregator / API relay reselling many vendors
	KindLocal  Kind = "local"  // something running on this machine
)

type KiroAuth added in v0.1.141

type KiroAuth struct {
	Token     string
	TokenType string // the tokentype header: API_KEY, EXTERNAL_IDP, or none
	Profile   string // the profile ARN
	Region    string // where the account's API is
}

KiroAuth is what a call to Kiro's API is made with.

func KiroAuthOf added in v0.1.141

func KiroAuthOf(ctx context.Context, key, home string, stale bool) (KiroAuth, error)

KiroAuthOf is a Kiro account's credentials: those of the key saved on the provider, of the account magpie signed in in home, or of Kiro's own sign-in when both are "". A token about to expire is refreshed first; stale, after Kiro turned one down, refreshes it now.

func (KiroAuth) Header added in v0.1.141

func (a KiroAuth) Header(h http.Header)

Header sets the headers that say who is calling.

type Limit added in v0.1.38

type Limit struct {
	Used   float64       // share used, 0–100
	Resets time.Time     // zero when not known
	Span   time.Duration // how long the window runs; zero when not known
	Model  string        // the only models it counts, by a word in their ids
	// contains filtered or unexported fields
}

Limit is one window of an allowance.

type Login added in v0.1.11

type Login struct {
	Agent  string    `json:"agent"`
	User   string    `json:"user"`
	Plan   string    `json:"plan,omitempty"`
	Seen   time.Time `json:"seen"`
	Active bool      `json:"active"` // the agent is signed in to this one now
	On     bool      `json:"on"`     // in use: the active one, or next in line
	// Lapsed says the vendor refused to refresh a saved account's sign-in:
	// it has to be signed in again before it can be used.
	Lapsed string `json:"lapsed,omitempty"`
	// Own is the agent's own sign-in, which magpie only reads: removed, it
	// is hidden rather than deleted (side_logins.go).
	Own bool `json:"own,omitempty"`
}

Login is a remembered subscription account, without its secrets.

func Logins added in v0.1.11

func Logins(agent string) []Login

Logins lists the remembered accounts of an agent ("" for every one), the active one flagged.

type Member added in v0.1.38

type Member struct {
	ID string // the group's member it is: the model, or the group in the group it is of
	// Path is the members from the group's own down to the model: [ID] for
	// a model the group names itself, ["group/fast", "a/m"] for one of
	// its group fast, and so on down.
	Path []string
	// Via are the groups in the group it is of, the outermost first: the
	// group each of Path's members but the last names.
	Via      []Group
	Provider Provider
	Model    string // what the vendor is asked for
	// Effort is the reasoning the member is fixed at ("provider/model:low"),
	// asked of the model whatever the agent or the group's classifier
	// asked; "" follows the group.
	Effort string
}

Member is one of a group's models as it resolves now.

func (Member) Below added in v0.1.102

func (m Member) Below(depth int) Member

Below is the member as the group at depth (0 the group itself, 1 the group in it Path[0] names, …) has it.

func (Member) Groups added in v0.1.102

func (m Member) Groups() []string

Groups are the ids of the groups in the group the model is of, the outermost first.

type PresetDef

type PresetDef struct {
	ID        string   `json:"id"`
	Name      string   `json:"name"`
	Icon      string   `json:"icon"`
	Kind      Kind     `json:"kind"`
	Chat      string   `json:"chat,omitempty"`
	Responses string   `json:"responses,omitempty"`
	Anthropic string   `json:"anthropic,omitempty"`
	Decide    string   `json:"decide,omitempty"` // a decision API: the provider only routes (see decide.go)
	Catalog   string   `json:"catalog,omitempty"`
	Website   string   `json:"website,omitempty"`
	KeysURL   string   `json:"keysUrl,omitempty"`
	NoKey     bool     `json:"noKey,omitempty"`     // local servers: a key is optional
	Sponsored bool     `json:"sponsored,omitempty"` // shown first, with a tag
	Note      string   `json:"note,omitempty"`      // one line under the name
	Short     string   `json:"short,omitempty"`     // the add sheet's name for it, when Name is long
	Regions   []Region `json:"regions,omitempty"`   // base-URL choices (a relay's regional endpoints, a vendor's plans)
	// RegionLabel names what the Regions choose between, "Region" if unset.
	RegionLabel string `json:"regionLabel,omitempty"`
	// HeaderHints name optional request headers the vendor documents, which
	// the editor offers to add; their values are the user's to fill in.
	HeaderHints []string `json:"headerHints,omitempty"`
	// Only, for a plan behind a key that also buys much else, is what its
	// models' ids start with: the rest of the vendor's list is left out.
	// Models are the plan's, for when the list has none of them.
	Only   string   `json:"only,omitempty"`
	Models []string `json:"models,omitempty"`
	// NoList: the vendor has no list of models to ask for (Bedrock's
	// runtime serves no /models), so Models are its list
	NoList bool `json:"noList,omitempty"`
	// Endpoint, for a vendor reached at the user's own resource (Azure
	// OpenAI), is an example of its address: the preset gives no URL, and
	// the editor asks for the one the user's resource is at, with
	// EndpointHint under it.
	Endpoint     string `json:"endpoint,omitempty"`
	EndpointHint string `json:"endpointHint,omitempty"`
	// Hosts: a vendor serving other makers' models as well as its own
	// (Groq, Ollama Cloud), whose list is no maker's word on theirs
	Hosts bool `json:"-"`
}

PresetDef describes one preset.

func Preset

func Preset(id string) *PresetDef

Preset finds a preset by id. The id the qianfan preset carried its first day (qianfan-token-plan, v0.1.394) names it still.

func Presets

func Presets() []PresetDef

Presets lists every preset, sponsored ones first within their kind.

type Protocol

type Protocol string

Protocol is a wire API magpie can speak to an upstream.

const (
	Chat      Protocol = "chat"      // OpenAI Chat Completions
	Responses Protocol = "responses" // OpenAI Responses
	Anthropic Protocol = "anthropic" // Anthropic Messages
	Gemini    Protocol = "gemini"    // Google Gemini; only served to clients, never spoken upstream
)
const CodeAssist Protocol = "codeassist"

CodeAssist is Google's Code Assist API, which magpie only speaks upstream, to a Gemini CLI or Antigravity account. Not in Protocols: no other provider serves it.

type Provider

type Provider struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	// Was are ids the provider had before it was renamed (see Rename):
	// a model still picked by one of them reaches it.
	Was    []string `json:"was,omitempty"`
	Icon   string   `json:"icon,omitempty"`
	Preset string   `json:"preset,omitempty"` // preset this was created from, if any
	Key    string   `json:"key"`              // API key, as typed by the user

	// KeyName names the key in use, and Keys are the provider's other
	// accounts: keys saved to switch to (see keys.go).
	KeyName string       `json:"keyName,omitempty"`
	Keys    []KeyAccount `json:"keys,omitempty"`
	// KeyProtocol, when set, is the one protocol the first key is good
	// for: a relay that hands out one key for Anthropic and another for
	// OpenAI (see KeyAccount.Protocol).
	KeyProtocol Protocol `json:"keyProtocol,omitempty"`

	// Base URLs, one per protocol the vendor serves natively. magpie appends
	// the usual paths: chat/responses bases end in /v1 (OpenAI style),
	// the Anthropic base is the root (what ANTHROPIC_BASE_URL takes).
	Chat      string `json:"chat,omitempty"`
	Responses string `json:"responses,omitempty"`
	Anthropic string `json:"anthropic,omitempty"`
	// Decide is the base of a decision API (TypeSafe's System One, which
	// Jev answers): a provider with it serves no conversation, only the
	// routing groups' choices of model and effort (see decide.go).
	Decide string `json:"decide,omitempty"`

	// Fallback is where a request goes when this provider can't take it —
	// out of quota, rate limited, overloaded or down — before any of the
	// reply has been sent: models as agents pick them (provider/model),
	// tried in order.
	Fallback []string `json:"fallback,omitempty"`

	// Routing is how requests spread over the keys or accounts it has on:
	// "" smart, the first while it has quota to spare, then whichever has
	// the most; "order" in order, the next one only when the one before
	// can't take it; "rotate" each in turn; "usage" the least used first.
	// Whichever it is, one out of credit, out of quota, rate limited or
	// failing is passed over for as long as that lasts.
	Routing string `json:"routing,omitempty"`

	// Affinity is how long a conversation stays with the key or account
	// that answered it, so the vendor's prompt cache it filled is read
	// again rather than lost (see Affinities): "" auto, "session",
	// "turn", "off".
	Affinity string `json:"affinity,omitempty"`

	// Headers are extra HTTP request headers sent to the vendor, exactly as
	// the user typed them. They ride on every request magpie makes to a plain
	// key+URL provider — forwarded calls, connectivity tests, and model-list
	// fetches — applied after the auth headers, so the user can override those
	// when a gateway insists on a private scheme. Signed-in agent accounts
	// ignore them: their auth is the agent's own.
	Headers map[string]string `json:"headers,omitempty"`

	// Proxy is the proxy magpie's requests to this provider go through
	// (#237: Codex through one, a vendor at home without): "" follows
	// the global one (Settings' Proxy, the environment's, the system's),
	// "direct" none, anything else the proxy's address (http://, https://,
	// socks5://; host:port means http). Signed-in accounts keep it too.
	Proxy string `json:"proxy,omitempty"`
	// AccountProxies is, for a subscription holding several accounts
	// (Codex's, Claude Code's…), the proxy of each account that has one
	// of its own, by its name in lower case, as Proxy takes one; an
	// account not in it follows Proxy (see ProxyChoice).
	AccountProxies map[string]string `json:"accountProxies,omitempty"`

	// BalanceURL, when set, is where the vendor tells what is left on a
	// key, asked with the key the way a chat request carries it; BalancePath
	// picks the amount out of the JSON reply (see balance.go). The vendors
	// magpie knows need neither.
	BalanceURL  string `json:"balanceURL,omitempty"`
	BalancePath string `json:"balancePath,omitempty"`
	// BalanceToken is what a vendor tells the whole account's balance to,
	// where a key is told only what is left on itself: AiHubMix's system
	// access token, or a new-api relay's for its /api/user/self named in
	// BalanceURL (see TakesBalanceToken). It is asked with nothing else but
	// the provider's headers, when the endpoint is one named.
	BalanceToken string `json:"balanceToken,omitempty"`
	// ZhipuTeam, for a Zhipu or Z.ai key on a team's GLM Coding Plan, is
	// the team's organization and project, from the BigModel console: the
	// team's windows are told to the key only with them (see
	// zhipuKeyTeamWindows). nil for a key of the user's own plan.
	ZhipuTeam *ZhipuTeam `json:"zhipuTeam,omitempty"`

	// ModelsURL, when set, is where the vendor lists its models, for one
	// that lists them away from the base URL requests go to (Xiaomi MiMo's
	// plans are served at their own hosts, the list at api.xiaomimimo.com).
	ModelsURL string `json:"modelsURL,omitempty"`

	// Models the user chose to expose. Empty means "the preset's picks, or
	// everything the vendor lists when that list is short".
	Models []string `json:"models,omitempty"`
	// Unlisted keeps the provider's own models out of the list agents see:
	// it serves only through the routing groups it is in, and by its
	// "provider/model" ids.
	Unlisted bool `json:"unlisted,omitempty"`
	// Off switches the provider off without removing it: its keys and
	// settings stay, but agents aren't given its models, no request,
	// routing group or fallback goes to it, and its balance isn't asked,
	// until it is switched on again (#163) — for a key out of quota.
	Off bool `json:"off,omitempty"`
	// Contexts is how long a request the user says a model takes, in
	// tokens, over what the vendor or models.dev says: by model id, "*"
	// for all the provider's models. Agents are told it.
	Contexts map[string]int `json:"contexts,omitempty"`
	// Family is a tag the provider's models go by in which agents are
	// shown them (settings' Visible), with the provider's id.
	Family string `json:"family,omitempty"`

	Catalog string `json:"catalog,omitempty"` // models.dev id, for names and reasoning levels
	Website string `json:"website,omitempty"`
	KeysURL string `json:"keysUrl,omitempty"`

	// IconURL is a picture the vendor named in an import link, to be fetched
	// once the user confirms. It is only a carrier between parsing and that
	// fetch: Save drops it, so it never reaches providers.json.
	IconURL string `json:"iconUrl,omitempty"`

	// Hidden is set on an account the user removed from magpie; the
	// agent stays signed in, magpie just leaves it alone.
	Hidden bool `json:"hidden,omitempty"`
	// Quiet is set on a removed account whose "Add it back" line the user
	// dismissed: it is offered again only from the Add sheet (#116).
	Quiet bool `json:"quiet,omitempty"`

	// Account is set when the provider is an agent the user signed in to
	// (see account.go); it is derived, never stored.
	Account *Account `json:"-"`
}

Provider is one configured vendor.

func Accounts

func Accounts() []Provider

Accounts lists the signed-in agents as providers.

func All

func All() []Provider

All lists the configured providers in the order they were added, then the signed-in agents. An entry in the file with no URL is only the model picks for one of those accounts.

func Find

func Find(id string) (*Provider, error)

Find looks a provider up by id (or name, case-insensitively).

func FromPreset

func FromPreset(id string) (Provider, error)

FromPreset builds a provider from a preset; the caller adds the key.

func Hidden added in v0.1.9

func Hidden() []Provider

Hidden lists the signed-in accounts the user removed from magpie.

func ParseImport added in v0.1.8

func ParseImport(link string) (Provider, error)

ParseImport reads an import link into the provider it describes.

func Resolve

func Resolve(id string) (Provider, string, bool)

Resolve maps an id an agent sent to a provider and the vendor's model id. It accepts catalog ids, "provider/model" for any model (exposed or not), and the bare model id when exactly one provider serves it. A group's id resolves to its first member.

func RouteDecider added in v0.1.411

func RouteDecider(model string) (Provider, string, error)

RouteDecider is the decision provider a System One model names, and the model that provider is asked with. The name's prefix is the provider (gptload-jev/jev-latest, vercel-jev/typesafe-ai/jev). A bare Jev id goes to the only provider that can answer it, as that provider names Jev.

func Stored added in v0.1.28

func Stored() []Provider

Stored is the providers as providers.json keeps them: keys included, signed-in accounts only as the model picks the user made for them.

func SwitchedOff added in v0.1.346

func SwitchedOff(id string) (Provider, bool)

SwitchedOff is the provider switched off in magpie that a model id names: as "provider/model", or a model only switched-off providers list. A request for it is refused as that, not as a model magpie doesn't know.

func (Provider) APIs added in v0.1.40

func (p Provider) APIs(model string) []Protocol

APIs lists the APIs model is served on, as the provider's last model list said: Copilot serves its GPT models on Responses alone and its Claude models on Chat and Anthropic's. nil is not known, and every API the provider speaks may be tried.

func (Provider) AlsoOn added in v0.1.14

func (p Provider) AlsoOn() []Provider

AlsoOn is a signed-in agent's other accounts that are on, each as a provider of its own, in the order they were saved.

func (Provider) Available

func (p Provider) Available() []catalog.Model

Available lists every model the vendor is known to serve: the list fetched from the vendor itself when there is one, over the models.dev catalog (or, for an account, whatever the agent's own sign-in can see).

func (Provider) Base

func (p Provider) Base(proto Protocol) string

Base returns the base URL for a protocol, or "" when the vendor lacks it.

func (Provider) Catalogs added in v0.1.13

func (p Provider) Catalogs() []string

Catalogs are the models.dev ids the provider's models are looked up in, first match wins: a gateway that resells several vendors names them all ("openai, deepseek").

func (Provider) Chosen

func (p Provider) Chosen(id string) bool

Chosen reports whether a model is exposed.

func (Provider) ContextOf added in v0.1.107

func (p Provider) ContextOf(model string) int

ContextOf is the context the user set for the provider's model: its own, else the provider's "*"; 0 when none is set.

func (Provider) DecideURL added in v0.1.218

func (p Provider) DecideURL(ctx context.Context) (string, error)

DecideURL is where a question for p's decision API is posted. Workers AI's is under an account: the one its base names, else the one the token belongs to, looked up once.

func (Provider) DecideVia added in v0.1.218

func (p Provider) DecideVia() string

DecideVia is the way p's decision API is asked, known by its host or by the gateway's own path (Vercel's /typesafe or /v4/ai, Cloudflare's /client/v4).

func (Provider) Decides added in v0.1.142

func (p Provider) Decides() bool

Decides reports whether the provider is a decision API.

func (Provider) Efforts added in v0.1.59

func (p Provider) Efforts(model string) []string

Efforts are the reasoning levels the model takes, when known: its own, or those the user gave it when it has none known.

func (Provider) Explain added in v0.1.447

func (p Provider) Explain(msg string, status int, body []byte) string

Explain is the error a refusal is passed on as: msg, with what the user can do about it when the account knows.

func (Provider) Exposed

func (p Provider) Exposed() []catalog.Model

Exposed lists the models magpie offers to agents for this provider: the user's picks; else the preset's; else everything, when that is few.

func (Provider) Fetch

func (p Provider) Fetch(ctx context.Context) ([]catalog.Model, error)

Fetch asks the vendor which models it serves and remembers the answer.

func (Provider) Fetched

func (p Provider) Fetched() (time.Time, bool)

Fetched reports when the vendor's own list was last fetched.

func (Provider) Host

func (p Provider) Host() string

Host is the vendor's API host, for display.

func (Provider) IsAzure added in v0.1.419

func (p Provider) IsAzure() bool

IsAzure reports whether the provider is Azure OpenAI: made from its preset, or at a resource's host.

func (Provider) IsBedrock added in v0.1.364

func (p Provider) IsBedrock() bool

IsBedrock reports whether the provider is Amazon Bedrock's runtime: made from its preset, or at its host.

func (Provider) IsOpenCode added in v0.1.7

func (p Provider) IsOpenCode() bool

IsOpenCode reports whether the provider is OpenCode's gateway (Zen or Go), which routes and caches by conversation and turns away requests that do not name one in x-opencode-session.

func (Provider) Jev added in v0.1.218

func (p Provider) Jev() string

Jev is the model a decision provider is asked with when the user picked none: TypeSafe's latest stable one, or the one Jev a gateway serves.

func (Provider) KeyList added in v0.1.14

func (p Provider) KeyList() []KeyInfo

KeyList is a provider's keys, in the order requests try them.

func (Provider) KeysOn added in v0.1.14

func (p Provider) KeysOn() []KeyAccount

KeysOn is the keys in use, first to last: the first key, then every saved one that's on.

func (Provider) Known added in v0.1.161

func (p Provider) Known(model string) []string

Known are the model's own reasoning levels, when known.

func (Provider) Levelless added in v0.1.404

func (p Provider) Levelless(model string) bool

Levelless reports whether the model is known to have no reasoning levels to pick from, as against not known to have any: its vendor or its maker lists it with a thinking switch alone, or nothing (Xiaomi's mimo-v2.6-flash), and the user gave it none.

func (Provider) ListPrice added in v0.1.411

func (p Provider) ListPrice(model string) (catalog.Price, bool)

ListPrice is a model's list price as its vendor's models.dev entry gives it, else as its maker's does (#224): a subscription (Codex's ChatGPT account, Copilot) or a relay with no models.dev id of its own is priced at gpt-6-astra's or gemini-3.8-flash's maker's price, as a Claude account is at Anthropic's.

func (Provider) ModelEfforts added in v0.1.137

func (p Provider) ModelEfforts() map[string][]string

ModelEfforts are the reasoning levels the user kept of the provider's models, by model id.

func (Provider) ModelNames added in v0.1.137

func (p Provider) ModelNames() map[string]string

ModelNames are the names the user gave the provider's models, by model id.

func (Provider) Native added in v0.1.300

func (p Provider) Native(model string) Protocol

Native is the API model is best asked on at this provider: one it serves the model on itself, so a request on it is relayed as it is rather than translated — Responses for a ChatGPT sign-in, or an OpenAI model on OpenAI's API or Copilot's; Chat where that is served. "" when every request is translated anyway: a sign-in served through its agent's own API (Claude Code's binary, Cursor, Devin, Kiro, Code Assist).

func (Provider) On added in v0.1.346

func (p Provider) On() bool

On is whether the provider takes requests: ready, and not switched off.

func (Provider) Prepare

func (p Provider) Prepare(body []byte) []byte

Prepare adjusts a request body the way the backend wants it.

func (Provider) ProxyChoice added in v0.1.427

func (p Provider) ProxyChoice() string

ProxyChoice is the proxy requests made on the provider's behalf go through, as netproxy.With takes it: for one account of a subscription that holds several, that account's own (AccountProxies), else the provider's (Proxy); "" follows the global one. An account in use beside the agent's own is made afresh by some agents (AlsoOn), without the provider's settings: those are read from providers.json.

func (Provider) Ready

func (p Provider) Ready() bool

Ready reports whether the provider can be used: it has a key, needs none, or is a signed-in agent.

func (Provider) RejectsTemperature

func (p Provider) RejectsTemperature(model string) bool

RejectsTemperature reports whether the model is known to refuse temperature and top_p. The answer comes from the catalog — models.dev plus the vendor's own list — so a model released after this binary was built is handled without a code change.

func (Provider) ResolveAuto added in v0.1.444

func (p Provider) ResolveAuto(ctx context.Context, model string) (context.Context, string, error)

ResolveAuto turns a request for a model the account picks itself (Copilot's Auto) into one for the model it picked: ctx then carries what the request is signed with. Any other model comes back as it was.

func (Provider) ResponsesFirst added in v0.1.300

func (p Provider) ResponsesFirst(model string) bool

ResponsesFirst: an OpenAI model on OpenAI's API, Copilot's or Bedrock's, which is best asked on the Responses API though Chat serves it too.

func (Provider) Retries added in v0.1.438

func (p Provider) Retries() bool

Retries is whether the account can mend a refusal (Retry), so the refusal's body is worth reading before it is passed on.

func (Provider) Retry added in v0.1.438

func (p Provider) Retry(ctx context.Context, status int, body []byte) bool

Retry is whether a request the backend refused with status and body is worth sending once more, the account having mended what it named.

func (Provider) Serves added in v0.1.38

func (p Provider) Serves(k KeyAccount, model string) bool

Serves reports whether key k can be asked for model: false only when the vendor's lists say another of the provider's keys sees it and k doesn't.

func (Provider) Sign

func (p Provider) Sign(ctx context.Context, req *http.Request, proto Protocol, body []byte) error

Sign authenticates a request to the provider, refreshing what needs it. Plain providers get their key; accounts get the agent's tokens.

func (Provider) Speaks

func (p Provider) Speaks() []Protocol

Speaks lists the protocols the vendor serves natively, preferred first.

func (Provider) Test

func (p Provider) Test(ctx context.Context) []Result

Test sends the smallest possible request to each endpoint the vendor serves, signed with a key made for it and asking for a model that key sees, and reports what came back.

func (Provider) TestModels added in v0.1.163

func (p Provider) TestModels(ctx context.Context, models []string) []Result

TestModels sends each of models the smallest request, a few at a time, on the endpoint it's served on and with a key that sees it: whether each answers, not only whether the vendor does. Results are in models' order.

func (Provider) Via added in v0.1.418

func (p Provider) Via(ctx context.Context) context.Context

Via is ctx for requests made on the provider's behalf: they go through its own proxy (ProxyChoice), or the global one when it has none.

func (Provider) Where added in v0.1.122

func (p Provider) Where() string

Where is what the provider's calls go to, as usage keeps it: the API's host, and for a subscription who is signed in there too. The id alone can't tell: it can be given to another vendor or account later.

func (Provider) WithKey added in v0.1.15

func (p Provider) WithKey(k KeyAccount) Provider

WithKey is p using key k: its endpoints narrowed to k's protocol when k has one. It has none left when p doesn't serve that protocol.

type Quota added in v0.1.114

type Quota struct {
	Provider string      `json:"provider"`
	Name     string      `json:"name"`
	Kind     string      `json:"kind"` // subscription, plan (bought with a key) or balance (a key's money)
	Plan     string      `json:"plan,omitempty"`
	User     string      `json:"user,omitempty"`
	Windows  []QuotaSpan `json:"windows"`
	Balance  string      `json:"balance,omitempty"`
	Error    string      `json:"error,omitempty"`
	// Until is when the plan's paid time ends, renewed then when Renew is
	// "auto", over when "off", either when "".
	Until *time.Time `json:"until,omitempty"`
	Renew string     `json:"renew,omitempty"`
	// Resets are a Codex account's rate-limit resets, when it holds any.
	Resets *ResetCredits `json:"resets,omitempty"`
}

Quota is one account's or key's allowance as magpie quota --json and the gateway's GET /v1/magpie/quotas tell it, for an agent choosing where to send its work: Provider is the first part of the models' ids (provider/model) for a key's plan or balance, the agent for a subscription.

func QuotaReport added in v0.1.114

func QuotaReport(ctx context.Context, now time.Time) []Quota

QuotaReport is Quotas as Quota, the reset times made absolute from now.

type QuotaSpan added in v0.1.114

type QuotaSpan struct {
	Name      string     `json:"name"`
	Used      float64    `json:"used"`
	Remaining float64    `json:"remaining"`
	ResetsAt  *time.Time `json:"resetsAt,omitempty"`
	Display   string     `json:"display,omitempty"` // the vendor's own count, "1.2k / 3k"
}

QuotaSpan is one window of an allowance: how much of it is used and left, in percent, and when it starts again.

type QuotaWindow

type QuotaWindow struct {
	Name      string     `json:"name"`
	Used      float64    `json:"used"`
	ResetsAt  *time.Time `json:"resetsAt,omitempty"`
	ResetSecs int64      `json:"resetSecs,omitempty"`
	Display   string     `json:"display,omitempty"`

	// For routing (see Allowances): how long the window runs, zero when
	// not known; the only models it counts, by a word in their ids
	// ("opus"), when it doesn't count them all; and Aside when using it up
	// doesn't stop the account — on-demand spending past the allowance,
	// or Copilot's code completions, which no request here makes.
	Span  time.Duration `json:"-"`
	Model string        `json:"-"`
	Aside bool          `json:"-"`
	// contains filtered or unexported fields
}

QuotaWindow is one rolling allowance reported by a subscription provider.

type Region

type Region struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Chat      string `json:"chat,omitempty"`
	Responses string `json:"responses,omitempty"`
	Anthropic string `json:"anthropic,omitempty"`
	// Lists is set on a region that serves a model list although the
	// preset as a whole has none to ask for (NoList): a provider at its
	// endpoints is asked for it. KeysURL, when the region's keys are made
	// on another page than the preset's, is where its Get-a-key link goes.
	Lists   bool   `json:"lists,omitempty"`
	KeysURL string `json:"keysUrl,omitempty"`
}

Region is one base-URL option of a preset that offers several. The first is the default; picking another in the editor swaps the endpoints.

type Renewal added in v0.1.75

type Renewal struct {
	Agent string `json:"agent"`
	User  string `json:"user"`
	// Renewed is false when it wasn't due; Err is why it failed, and Lapsed
	// whether the sign-in is gone (the vendor refused it) or may yet renew.
	Renewed bool   `json:"renewed"`
	Err     string `json:"error,omitempty"`
	Lapsed  bool   `json:"lapsed,omitempty"`
}

Renewal is what came of renewing one saved account.

func RenewLogins added in v0.1.75

func RenewLogins(ctx context.Context, every time.Duration) []Renewal

RenewLogins renews the saved Claude and ChatGPT sign-ins not in the agent's hands that have gone every or longer without it; every 0 renews all of them.

type ResetCredits added in v0.1.282

type ResetCredits struct {
	Count int        `json:"count"`
	Until *time.Time `json:"until,omitempty"`
	// ByWindow: each reset is for one window, FiveHour of the five hours'
	// and Weekly of the week's, and is spent on the vendor's own page (a
	// GLM Coding team plan's, zcode_team.go), not from magpie
	ByWindow bool `json:"byWindow,omitempty"`
	FiveHour int  `json:"fiveHour,omitempty"`
	Weekly   int  `json:"weekly,omitempty"`
}

ResetCredits is how many rate-limit resets an account holds and the soonest one of them runs out; Until is nil when none does, or when that couldn't be read.

func (ResetCredits) Words added in v0.1.425

func (r ResetCredits) Words() string

Words are the resets counted: "2 resets", or by window, "2 five-hour resets · 1 weekly reset".

type ResetOutcome added in v0.1.282

type ResetOutcome struct {
	Code    string `json:"code"`
	Windows int    `json:"windows"`
}

ResetOutcome is what spending a reset did: Code is the vendor's word for it (reset, nothing_to_reset, no_credit, already_redeemed) and Windows how many windows started again.

func UseCodexReset added in v0.1.282

func UseCodexReset(ctx context.Context, user string) (ResetOutcome, error)

UseCodexReset spends one of the rate-limit resets of the Codex account user (the one Codex is signed in to when ""), starting its current usage windows again: the one that runs out first, so none that would last longer goes before it. It can't be undone: callers ask first. The account's usage is read afresh after.

func (ResetOutcome) Text added in v0.1.282

func (o ResetOutcome) Text() string

Text says an outcome in words.

type Result

type Result struct {
	Protocol Protocol `json:"protocol"`
	OK       bool     `json:"ok"`
	Status   int      `json:"status,omitempty"`
	Millis   int64    `json:"ms"`
	Model    string   `json:"model,omitempty"`
	Error    string   `json:"error,omitempty"`
}

Result is what a probe of one endpoint came back with.

type Rule added in v0.1.94

type Rule struct {
	Use string `json:"use"` // the member, as the group names it: "provider/model"
	// Tokens: the request is at least this long, in tokens — the larger of
	// an estimate from its size and what the vendor counted for the
	// conversation's last request.
	Tokens int `json:"tokens,omitempty"`
	// Images: the request carries an image, in this turn or before.
	Images bool `json:"images,omitempty"`
	// Effort: the agent asked for reasoning at least this level (one of
	// Efforts), or "on" for any reasoning at all.
	Effort string `json:"effort,omitempty"`
	// Agents: the request is from one of these agents (usage.AgentOf ids).
	Agents []string `json:"agents,omitempty"`
	// Intent: the user's message at the turn's start is of this kind, as
	// the group's Classifier judges it — "writing or fixing tests",
	// "a quick question". When the classifier can't say, it doesn't match.
	Intent string `json:"intent,omitempty"`
	// Compact: the agent is compacting its conversation — asking a model to
	// summarize it so it can go on in less room (Claude Code's /compact,
	// Codex's, OpenCode's, Pi's…) — which a cheaper, faster model can do
	// in place of the one the conversation is on.
	Compact bool `json:"compact,omitempty"`
}

Rule sends the requests it matches to one of its group's members first. Every condition set must hold; a rule sets at least one.

func ParseRule added in v0.1.136

func ParseRule(g Group, words []string) (r Rule, at int, classifier string, err error)

ParseRule makes a rule of k=v words; the model is resolved among the group's members. classifier is the group's classifier when one was given, at the place asked for (from 1) when one was.

func (Rule) Conditions added in v0.1.94

func (r Rule) Conditions() []string

Conditions says what a rule matches, for a list or a trace.

func (Rule) Line added in v0.1.136

func (r Rule) Line() string

Line is the rule as ParseRule reads it back.

func (Rule) Matches added in v0.1.94

func (r Rule) Matches(q RuleRequest) bool

Matches reports whether the request is one the rule is for.

func (Rule) MatchesBesidesIntent added in v0.1.95

func (r Rule) MatchesBesidesIntent(q RuleRequest) bool

MatchesBesidesIntent is Matches but for the rule's intent: whether the classifier's answer is all it waits on.

type RuleRequest added in v0.1.94

type RuleRequest struct {
	Tokens   int
	Images   bool
	Thinking bool   // the agent asked for reasoning
	Effort   string // at what level, when it said
	Agent    string
	// Intent is the one of the rules' intents the classifier said the
	// user's message is; "" when none, or it wasn't asked.
	Intent string
	// Compact: the request is the agent compacting its conversation.
	Compact bool
}

RuleRequest is what a rule looks at in a request.

type SignInState added in v0.1.14

type SignInState struct {
	ID            string `json:"id"`
	Agent         string `json:"agent"`
	URL           string `json:"url"`                     // the vendor's page, to open or copy
	Code          string `json:"code,omitempty"`          // what to type there, for a device code
	State         string `json:"state"`                   // installing, waiting, done, failed or canceled
	PasteCallback bool   `json:"pasteCallback,omitempty"` // a callback URL can also finish this sign-in
	// Installing is the CLI being installed before the sign-in can start
	Installing string `json:"installing,omitempty"`
	User       string `json:"user,omitempty"`  // the account, once done
	Plan       string `json:"plan,omitempty"`  //
	Using      bool   `json:"using,omitempty"` // the agent was signed in to it too
	Error      string `json:"error,omitempty"`
}

SignInState is where a sign-in stands, for the window to show.

func SignInStatus added in v0.1.14

func SignInStatus(id string) (SignInState, bool)

SignInStatus reports on a sign-in StartSignIn began.

func StartSignIn added in v0.1.14

func StartSignIn(agent string) (SignInState, error)

StartSignIn begins adding an account to an agent: open the returned URL in a browser and the rest happens on its own; SignInStatus follows it.

An agent signed in with a CLI that isn't installed has it installed first: the sign-in is then "installing", and gets its URL when that is done.

func StartSignInAt added in v0.1.425

func StartSignInAt(agent, site string) (SignInState, error)

StartSignInAt is StartSignIn on one of the sites an agent signs in on: ZCode's "zai" (the default) or "bigmodel".

func WaitSignIn added in v0.1.14

func WaitSignIn(ctx context.Context, id string) (SignInState, error)

WaitSignIn blocks until a sign-in is over, for the command line.

type SubscriptionQuota

type SubscriptionQuota struct {
	Provider string        `json:"provider"`
	Name     string        `json:"name"`
	Icon     string        `json:"icon"`
	Plan     string        `json:"plan,omitempty"`
	User     string        `json:"user,omitempty"` // the account, so two of one vendor tell apart
	Windows  []QuotaWindow `json:"windows"`
	Balance  string        `json:"balance,omitempty"` // what is left on an API key, instead of windows
	// Until is when the plan's paid time ends: it renews then when Renew
	// is "auto", is over when "off", and either when "" (the vendor
	// doesn't say which).
	Until *time.Time `json:"until,omitempty"`
	Renew string     `json:"renew,omitempty"`
	Error string     `json:"error,omitempty"`
	// AsOf is when an allowance shown in place of one that couldn't be
	// read was read (see keepLast); nil for a reading just made.
	AsOf *time.Time `json:"asOf,omitempty"`
	// Resets are the rate-limit resets a Codex account holds, nil when
	// it holds none (codex_resets.go).
	Resets *ResetCredits `json:"resets,omitempty"`
}

SubscriptionQuota is provider-reported allowance usage. This is separate from Dial's local token log: vendors expose percentages, not token totals.

func KeyBalances added in v0.1.37

func KeyBalances(ctx context.Context) []SubscriptionQuota

KeyBalances is the balance of every provider magpie can ask one of, the key in use and each other key it has on — or its account's, once, when it has a token for that — as cards beside the subscriptions' allowances. What was asked less than a minute ago is not asked again, unless the providers were saved since (ForgetBalances).

func PlanQuotas added in v0.1.86

func PlanQuotas(ctx context.Context) []SubscriptionQuota

PlanQuotas is the windows of every plan magpie has a key for, each key on a card of its own when a provider has several. What was asked less than a minute ago is not asked again.

func Quotas added in v0.1.114

func Quotas(ctx context.Context) []SubscriptionQuota

Quotas is what is left everywhere magpie can ask: the signed-in subscriptions' windows, the plans bought with a key, and the keys' balances, as the Usage page shows them. The vendors are asked at once; what doesn't answer before ctx ends comes back with an error.

func SubscriptionUsage

func SubscriptionUsage(ctx context.Context) []SubscriptionQuota

SubscriptionUsage returns rolling quotas for signed-in first-party agents. Results are cached because these private account endpoints are aggressively rate limited when several CLI sessions are active. Once there is something cached it comes back at once, and a stale copy is refreshed in the background; only the very first call waits, for as long as ctx allows.

type WorkBuddyCheckin added in v0.1.356

type WorkBuddyCheckin struct {
	User    string    `json:"user,omitempty"` // as listed now; never kept
	Day     string    `json:"day"`
	At      time.Time `json:"at"`
	Outcome string    `json:"outcome"`
	Credit  float64   `json:"credit,omitempty"`
	Streak  int       `json:"streak,omitempty"`
	Msg     string    `json:"msg,omitempty"`
	// Offline is a failure that never reached WorkBuddy, and Tries how
	// many before it the same day did the same.
	Offline bool `json:"offline,omitempty"`
	Tries   int  `json:"tries,omitempty"`
	// Asked is true of one checked in on this run, not one read back.
	Asked bool `json:"-"`
}

WorkBuddyCheckin is what came of a WorkBuddy account's check-in on Day (Beijing): the credits it gave and the streak it made, or why none.

func CheckInWorkBuddy added in v0.1.356

func CheckInWorkBuddy(ctx context.Context) []WorkBuddyCheckin

CheckInWorkBuddy checks each WorkBuddy (China) account in use in for today now, those not in yet, and says how each stands.

func WorkBuddyCheckins added in v0.1.356

func WorkBuddyCheckins() []WorkBuddyCheckin

WorkBuddyCheckins is each WorkBuddy (China) account's last check-in, as kept, by its name now; asks nothing.

func (WorkBuddyCheckin) Checked added in v0.1.356

func (r WorkBuddyCheckin) Checked() bool

Checked says whether the day's credits are in, claimed now or before.

type ZhipuTeam added in v0.1.431

type ZhipuTeam struct {
	Org     string `json:"org,omitempty"`
	Project string `json:"project,omitempty"`
}

ZhipuTeam is the team a Zhipu or Z.ai key's GLM Coding Plan belongs to: its organization and project IDs, as the BigModel console shows them.

Jump to

Keyboard shortcuts

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