provider

package
v0.1.644 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2026 License: MIT Imports: 61 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 (
	MoveMoving = "moving" // under way, or cut short (put back at the next try)
	MovePlugin = "plugin" // the plugin has the id
	MovedBack  = "back"   // the user moved it back: it stays built-in
	MoveFailed = "failed" // the last try failed: the built-in carries on
)

A migration's states.

View Source
const (
	SuffixOn  = "on"
	SuffixOwn = "own"
	SuffixOff = "off"
)

The ways the agents' lists name models (SuffixMode): every name with its provider's after it, as by default; all but the names the user gave models (#92); or none (#335).

View Source
const (
	Ordered   = "order"
	Rotate    = "rotate"
	LeastUsed = "usage"
	Pace      = "pace"
)

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 BlockedHint = "the provider's network firewall blocked requests from this IP; wait a while, or switch to another network or proxy"

BlockedHint is what a vendor's edge firewall blocking magpie's address means, in plain words: Alibaba Cloud's (ESA, in front of zcode.z.ai) answers a 405 HTML page, "Sorry, your request has been blocked due to unusual activity", linking errors.aliyun.com. Nothing in the request is at fault and magpie changes nothing about it: the address is.

View Source
const ClaudeRisk = "" /* 228-byte string literal not displayed */

ClaudeRisk is what magpie says before a Claude account is added, as the window does.

View Source
const ClineVersion = "3.5.54"

ClineVersion is the Cline desktop release magpie says it is to the Cline API.

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 CommandCodeMaxOutput = 200_000

CommandCodeMaxOutput is the most max_tokens Command Code takes at /alpha/generate, for any model: more is refused ("Too big: expected number to be <=200000 at params.max_tokens"). models.dev gives some of its models more (DeepSeek V4's 384000, MiniMax M3's 512000).

View Source
const CommandCodePlanID = "commandcode-plan"

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

View Source
const ConversationHeader = "X-Magpie-Conversation"

ConversationHeader carries the conversation a request belongs to, to a plugin's chat.headers hook as its session; it goes no further.

View Source
const CopilotAuto = "auto"

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

View Source
const DrawersHeader = "X-Magpie-Drawers"

DrawersHeader asks a magpie's model list for its image models as well.

View Source
const EffortAuto = "auto"

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

View Source
const FastWord = "fast"

FastWord is the last part of a member typed to be sent fast.

View Source
const FreshPace = 100 / (7 * 24.0)

FreshPace is the pace of an account with a whole week ahead of it: what one not known counts as.

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 KiloVersion = "7.8.3"

KiloVersion is the Kilo CLI release magpie says it is to the Kilo Gateway.

View Source
const Manual = "manual"

Manual is a group's routing when the user picks which member it uses, as CC Switch has one provider on at a time (#317): every request goes to the member picked (Group.Pick), over its own keys or accounts; the others, and the rules, wait until another is picked or the group is routed otherwise. The pick is changed on the group's card, in a click.

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 OpenCodeStub = "Not available in this session. Never call this tool."

OpenCodeStub describes a tool offered only for Zen's free tier to see, which the client doesn't have.

View Source
const OpenCodeVersion = "1.18.34"

OpenCodeVersion is the OpenCode release magpie says it is to OpenCode's gateway. Zen's free tier turns away anything older than 1.18.0 (426 "OpenCode 1.18.0 or newer is required to use the free tier").

View Source
const QoderCNID = qoder.CNProviderKey

QoderCNID is the Qoder CN subscription's id, the same as Qoder CN's agent.

View Source
const RemoteMagpiePreset = "remote-magpie"

RemoteMagpiePreset is the preset's id.

View Source
const Scheme = "magpie"

Scheme is the URL scheme magpie registers with the system.

View Source
const SignInHeader = "X-Magpie-Sign-In"

SignInHeader is how a plugin says what its answer means for the account's sign-in, whatever its status, so it can answer with the status its built-in did: "expired" marks the account lapsed, as a built-in whose vendor refused the sign-in marked it, though the status be a 502; "kept" leaves the account as it is, as a built-in answering a 401 of the vendor's without its sign-in refused did; "renewed" clears the mark, as a built-in whose sign-in renewed took it off whatever the request then met. Without it a 401 marks the account and a success clears the mark.

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 WBRefusedHint = "" /* 147-byte string literal not displayed */

WBRefusedHint is what the user can do about WorkBuddy's "Illegal API invocation from an unapproved channel": both builds (the CodeBuddy plan) answer it to a chat whose system prompt is Codex's or Claude Code's own (#182), whatever the headers. magpie never rewrites that prompt; the agent is told to use WorkBuddy from another agent instead.

View Source
const WorkBuddyAIID = "workbuddy-ai"

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

View Source
const ZCodeStartBlockedHint = "" /* 248-byte string literal not displayed */

ZCodeStartBlockedHint is what the Start Plan's "request has been blocked due to unusual activity" (HTTP 405, code 3012 "method not allowed") means (#425): zcode.z.ai looks at what a request carries and turns away one that isn't the ZCode app's own, its system prompt and all, as zcode2api found, so magpie sends it as the app does (zcode_client.go). One turned away still is Alibaba Cloud's firewall blocking the address (BlockedHint), or ZCode checking for something magpie doesn't send.

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 ErrUnreadable = errors.New("providers.json can't be read")

ErrUnreadable is a providers.json that is there but can't be read or decoded: never an empty catalog, to list as none, back up or write over.

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 GrokBase = "https://cli-chat-proxy.grok.com/v1"

GrokBase is the CLI's backend; 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.

View Source
var OpenCodeTools = []string{"bash", "read"}

OpenCodeTools are the tools Zen's free tier wants offered, by name.

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

View Source
var Retiring = []string{}

Retiring are the built-ins magpie moves onto their plugins by itself, at start-up; the rest move only when the user asks.

View Source
var SearchVendors = []SearchVendor{
	{ID: "tavily", Name: "Tavily", Base: "https://api.tavily.com", KeysURL: "https://app.tavily.com/home"},
	{ID: "brave", Name: "Brave Search", Base: "https://api.search.brave.com", KeysURL: "https://api-dashboard.search.brave.com/app/keys"},
	{ID: "exa", Name: "Exa", Base: "https://api.exa.ai", KeysURL: "https://dashboard.exa.ai/api-keys"},
	{ID: "firecrawl", Name: "Firecrawl", Base: "https://api.firecrawl.dev", KeysURL: "https://www.firecrawl.dev/app/api-keys"},
	{ID: "searxng", Name: "SearXNG"},
}

SearchVendors are the search APIs magpie can ask, in the order offered.

View Source
var Weekdays = []string{"sun", "mon", "tue", "wed", "thu", "fri", "sat"}

Weekdays are the days a TimeWindow names, as time.Weekday counts them.

Functions

func APIError

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

APIError pulls the human message out of an error body when there is one. A firewall's block page is put in plain words (BlockedHint); Google's "verify your account" refusal also says what to do about it, with the link it gave.

func AccountModelsOf added in v0.1.610

func AccountModelsOf(id, ref string) (string, []string, error)

AccountModelsOf is the models the account or key ref of the provider id alone serves, and the account or key as AccountModels knows it; no models when it serves all the provider's.

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 AddCopy added in v0.1.455

func AddCopy(p Provider, from string) (string, error)

AddCopy adds p, a copy the user made of the provider from (#268), beside it: what the form doesn't carry — the keys, the balance token, how requests spread over the keys, where they fall back to — is from's where p leaves it out. The same key on the same host is taken, the copy being asked for (another model list, another endpoint). A signed-in account is never copied: its sign-in is the agent's.

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 Adopt added in v0.1.642

func Adopt(ctx context.Context, id string) error

Adopt puts the built-in id onto its plugin before any account of it is signed in: the plugin installed, and the subscription signs in through it from now on, as a moved one does. One with accounts is moved instead.

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 AntigravitySentID added in v0.1.560

func AntigravitySentID(model, effort string) string

AntigravitySentID is the id a request for model goes out under at that effort on an Antigravity account: the variant of the family the effort picks, at the level of that family nearest the effort asked for; with no effort asked for, the family's own default. One of the family's own variant ids — an id a pick or an agent's model list kept from before the families were one model — goes as it is when no effort is asked for, and at the level the effort picks otherwise, since the effort the client asks for wins, as it does for the family. Any other id goes as it is.

The gateway sends the envelope under this and the ledger judges what the vendor answered against it, so there is one of it rather than one each: a reply naming the id a call went out under is that model answering, and read against the family instead every level of it reads as another model having swapped in, in the routing view and in the ledger alike.

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 AnyPriceKey added in v0.1.581

func AnyPriceKey(model string) string

AnyPriceKey is the key a price for a model from any provider is stored at: its id lower-cased, the way a session's bare model is looked up.

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 AskClaudeUsage added in v0.1.558

func AskClaudeUsage()

AskClaudeUsage is the user asking to see Claude's usage — opening the Usage page, refreshing it, `magpie quota` — so Claude Code's /usage is run at once rather than when the next unasked reading is due (claudeUsageWait); the next SubscriptionUsage waits for it.

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 AutoGroupID added in v0.1.603

func AutoGroupID(model string) string

AutoGroupID is the id of the group magpie finds for a model, however a vendor spells it: "auto-claude-opus-5-5" for claude-opus-5.5.

func AutoGroupsOn added in v0.1.603

func AutoGroupsOn() bool

AutoGroupsOn reports whether magpie finds groups on its own: a model more than one provider serves is a group of them (autoGroups). It is on until the user turns it off.

func AutoResets added in v0.1.514

func AutoResets(agent, user string) bool

AutoResets says whether agent's account user spends its resets by itself; only a Codex account does.

func AutoStandIn added in v0.1.603

func AutoStandIn(id string) (string, bool)

AutoStandIn is the model a request for a group magpie found goes to while such groups are off (SetAutoGroups): its model, from the first provider that serves it, as "provider/model". An agent set to the group, or a session begun on it, keeps working, on one provider. ok is false for any other id, a group the user has of that id, or while found groups are on.

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 BalanceNumber added in v0.1.540

func BalanceNumber(s string) (float64, bool)

BalanceNumber is the amount a balance as a vendor tells it holds: "$12.34", "¥1,024.50", "CNY 8", "12.3k credits". A share ("45%"), or text with no number, is none.

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 CanFast added in v0.1.577

func CanFast(p Provider, model string) bool

CanFast reports whether model, as p serves it, has a fast mode magpie can ask for: a ChatGPT account's GPT models (Codex's Fast), Cursor's models with a -fast one, an OpenAI key's GPT and o-series models on its Responses API (priority processing), and an Anthropic key's Opus models with fast mode. A Claude subscription runs Claude Code itself, and a relay or a cloud (Bedrock, Vertex) may refuse the field, so neither is.

func CancelSignIn added in v0.1.14

func CancelSignIn(id string)

CancelSignIn stops waiting for the browser.

func ClaudeFast added in v0.1.577

func ClaudeFast(model string) bool

ClaudeFast reports whether a Claude model has fast mode.

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 CleanLevels added in v0.1.477

func CleanLevels(in []string) ([]string, error)

CleanLevels are the reasoning levels a group names for itself (Group.Levels) as they are kept: lowercase, each once, lowest first. Only the levels magpie knows are taken.

func ClineClient added in v0.1.630

func ClineClient(h http.Header)

ClineClient makes a request to the Cline API carry the desktop app's headers.

func CodexAutoReset added in v0.1.507

func CodexAutoReset(user string) bool

CodexAutoReset says whether the Codex account user spends a reset by itself once its week is used up.

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 CodexListTag added in v0.1.460

func CodexListTag() string

CodexListTag names the list Codex is handed, for its ETag: magpie's models and the account's own taken out of it, so either changing has Codex ask for the list again.

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 CodexNativeHidden added in v0.1.460

func CodexNativeHidden() map[string]bool

CodexNativeHidden is the ChatGPT account's own model slugs the user took out of Codex's list (HiddenModels): the backend lists them, and the gateway drops them from its /models answer as it does the ones not picked.

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.

A provider switched off picks nothing, as it serves no agent anything (Provider.Off): its picks are kept for when it is switched on again and are not a narrowing now.

func CodexSignedIn added in v0.1.507

func CodexSignedIn() (string, bool)

CodexSignedIn is the ChatGPT account Codex is signed in to now.

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 CommandCodeOutputOf added in v0.1.612

func CommandCodeOutputOf(model string) int

CommandCodeOutputOf is the most a reply of a Command Code model may be asked for: the model's own limit, as models.dev gives it, within CommandCodeMaxOutput.

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, a built-in's or a plugin's, is only hidden from magpie (its accounts and model picks kept, shown again from Hidden or by signing in); signing out is each account's Remove.

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 DropContext added in v0.1.532

func DropContext(p Provider, model string) (bool, error)

DropContext takes a window off one of a provider's models and reports whether there was one there to take away, as DropModelPrice and DropModelOutput do: a removal over a window that is not there leaves the provider in the state it was already in, but only the caller can tell the user so, and a ✓ over a window that was never set says there was one. Nothing is saved in that case, and so the agents are not told either — a provider saved over a window that did not change rewrites every agent's model lists for nothing, which is the one round the removal itself earns.

Save is what tells the agents here (store), so it is the save, and not a Touched of its own, that has to happen exactly once.

func DropModelOutput added in v0.1.532

func DropModelOutput(id string) (string, bool, error)

DropModelOutput takes a user's reply limit away under the key it is stored at, and hands that key back, so a caller left without a provider to name it by can still say which entry it cleared. It does not ask whether the provider is still there: a reply limit outlives the provider it was set for, and that provider can be deleted — the entry then sits in the settings answering for a model nothing serves, and a removal that resolved the provider first would leave the user no way to take it away, the file being the only other place it is in. Which key that is comes from the spelling as given before anything is looked up (outputKeyOf), so that a provider which has since taken the name of one that is gone is not the one the entry is cleared under. A key holding no limit is no error: there is nothing there to take away, which is the state the entry is left in either way, and writing it out again would rewrite the settings and every agent's model lists over a limit that did not change.

It reports whether there was a limit there to take away, as DropModelPrice does, and by neither saving nor telling the agents when there was none: only the caller can put that to the user, and a ✓ over a limit that was never set says the model had one.

func DropModelPrice added in v0.1.504

func DropModelPrice(key string) (bool, error)

DropModelPrice takes a user's price away under the key it is stored at, without asking whether the provider is still there, and reports whether there was one there to take away. A price outlives the provider it was set for: that provider can be deleted, and `magpie model prices` still lists the price and usage is still counted at it, so a removal that resolved the provider first would leave the user no way to take it away. Which of the keys a price is ever kept under this one is, is PriceKey's to say.

A key holding no price is still no error — there is nothing there to take away, which is the state it is left in either way — but saying so is what tells a mistyped id from a price that was cleared: `magpie model price -- reset` over a price still in the file would have the user believe it gone.

func DropUpstreamName added in v0.1.560

func DropUpstreamName(key string) (bool, error)

DropUpstreamName takes a name off under the key it is stored at, and says whether there was one to take. A name outlives the provider it was given for: that provider can be deleted, and the name is then in force for whichever provider takes that id next — its requests would go out renamed to a vendor that never heard of it, and nothing would say so — so a removal that resolved the provider first would leave the user no way to take away the one name doing that. A key holding no name is not an error: there is nothing there to take away, which is the state it is left in either way, and false says so to a caller that has something else to say.

Which key a ref is taken at is wireKey's: the name comes off from where it is really kept, rather than from under whichever provider the ref names now.

func EdgeBlocked added in v0.1.570

func EdgeBlocked(b []byte) bool

EdgeBlocked says whether an error body is a firewall's block page rather than the vendor's API answering, or one already put in plain words.

func EffectivePrice added in v0.1.504

func EffectivePrice(providerID, model string) (catalog.Price, bool)

EffectivePrice is what a call to a provider's model costs the user: the price they set for that model, or for every model of that provider, or for that model from any provider (settings' ModelPrices), else the provider's own list price, else its maker's. The second return is false only when no price is known at all, which is not the same as a price of zero: that one is set, deliberately.

A price here is the provider's tariff, not the model's: the same model through two relays is two prices, and neither is what models.dev lists.

func EffectivePriceIn added in v0.1.504

func EffectivePriceIn(s settings.Settings, providerID, model string) (catalog.Price, bool)

EffectivePriceIn is EffectivePrice at the settings given, for a caller pricing a whole list of models at one read of the file rather than one read per model: every model of that list is priced at the same copy, so the list is one snapshot of the prices rather than a reading per row, and a price changed while it is read takes effect in the next call.

func EffortFamily added in v0.1.603

func EffortFamily(id string) string

EffortFamily is the model an id with an effort word after it is a level of ("gemini-3.8-flash-medium" is gemini-3.8-flash), and the id itself when it has none.

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 ErrorType added in v0.1.579

func ErrorType(b []byte) string

ErrorType is the kind of error a vendor's body names — the error's type (rate_limit_error, usage_limit_reached), else its code — or "" when it names none: what to set beside the status when a request failed.

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 FetchNewSoon added in v0.1.591

func FetchNewSoon(timeout time.Duration)

FetchNewSoon is FetchNew in the background, for a page that shouldn't wait on vendors (the panel, whose model picker otherwise kept an account's fallback list until the Providers page was opened). It does nothing while one runs or within newSoonEvery of the last.

func FileError added in v0.1.587

func FileError() error

FileError is why providers.json can't be read, nil when it can or isn't there: for what lists the providers to say so, not "none yet".

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 FlatName added in v0.1.572

func FlatName(namespace, name string) string

FlatName is the name a namespaced tool is offered to a model under, which takes one flat name: namespace__name, as Codex names an MCP server's tools. A name longer than the 64 characters APIs allow is cut and made unique by a hash of the whole.

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 HasUpstreamName added in v0.1.560

func HasUpstreamName(key string) bool

HasUpstreamName reports whether a name is kept under exactly the key it is given, the provider's part spelled as it is. No other spelling of the provider is tried: a caller deciding whether to remove a name by this key has to know that this key is the one a name is kept under, which is the one question wireKey's order is about.

A key spelled as an agent spells one — with magpie/ in front of it, and the spaces a ref is typed with — is that same key, as it is for a removal (DropUpstreamName): a name kept under it is there whichever way it is spelled, and a check that answered for one spelling only would say a name was not kept where it is. The one caller has had that prefix taken off already (splitModelRef), so nothing depends on it yet.

func HasWorkBuddy added in v0.1.356

func HasWorkBuddy() bool

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

func HiddenModels added in v0.1.460

func HiddenModels(agent string) map[string]bool

HiddenModels are the ids of the entries taken out of agent's lists.

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 InUseLogin added in v0.1.504

func InUseLogin(agent string) string

InUseLogin is the account of an agent's the gateway goes to first: the one the agent is signed in to, unless it is paused, else the first other one on; "" when the agent has none.

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, configDir 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 KeepRetiringMoved added in v0.1.506

func KeepRetiringMoved(ctx context.Context)

KeepRetiringMoved moves the built-ins being retired, run by the magpie serving the gateway (one magpie, never two at once): a little after it starts, then every hour, so a failed move is tried again once moveRetry has gone. It also keeps each moved built-in's plugin up to date.

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 KiloClient added in v0.1.635

func KiloClient(h http.Header, key, session string)

KiloClient makes a request to the Kilo Gateway carry what the Kilo CLI sends it (Kilo-Org/kilocode packages/opencode/src/session/llm/request.ts and kilocode/const.ts, packages/kilo-gateway/src/headers.ts): Kilo Code's attribution and User-Agent, the editor it runs in, its mode, and the session as the task, which the gateway keys its prompt cache on. session names the conversation, made into one of the CLI's ids (ses_…) as for OpenCode; none leaves the session headers out. A provider with no key sends no Authorization at all: the gateway answers a free model to a caller with no credential as anonymous (by IP, 200 requests an hour), and refuses a bearer it can't verify with 401 (Kilo-Org/cloud web-shared/src/lib/tokens.ts, ai-gateway/handlers/llm-proxy.ts). Kilo's clients still send "Bearer anonymous", which the gateway reads as none only until no released client sends it, so it is not copied here.

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 Labels added in v0.1.516

func Labels(es []Entry) []string

Labels are how an agent's list names each of es, in order: as Label, or, when the user wants names plain (settings' PlainNames, #335), by the name alone — but for two or more the list would call the same, as a routing group found for a model is called with that model left in the list, which keep their provider's after it to tell them apart. With their own names plain (PlainOwnNames, #92), a name the user gave a model is that name just as they wrote it, and the vendor's keep Label's.

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 MemberFast added in v0.1.577

func MemberFast(id string) (member string, fast bool)

MemberFast splits a member typed with ":fast" after it into the member and true: "a/m:high:fast" is a/m:high, fast, unless a has a model "m:high:fast" of its own.

func MemberGroups added in v0.1.572

func MemberGroups() map[string][]string

MemberGroups are the routing groups each model is in, as "group/<id>", by the model's "provider/model" id; a member fixed at an effort counts as its model, and a group removed is none. A provider kept for routing groups (Provider.Unlisted) reaches agents through these alone: a model of it in none of them is used by nothing.

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 MirrorOrder added in v0.1.638

func MirrorOrder(order []string) error

MirrorOrder makes the providers' order the one another computer has, as sync brings it: its ids first, as it has them, then the ones named here alone (a signed-in account only this computer has), in the order they have here. None, as from a magpie before the order was synced or one never arranged, leaves the order here as it is.

func MirrorSearchAPIs added in v0.1.587

func MirrorSearchAPIs(as []SearchAPI) error

MirrorSearchAPIs makes the search APIs exactly these, as sync brings them; one that came without a key keeps the key 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 Movable added in v0.1.506

func Movable(id string) bool

Movable is whether the built-in id has a plugin it can move to.

func MovableIDs added in v0.1.628

func MovableIDs() []string

MovableIDs are the built-ins that have a plugin to move to, by id: the page marks them deprecated, moved or not.

func Move added in v0.1.506

func Move(ctx context.Context, id string) error

Move puts the built-in id's accounts onto its plugin (see above). An error leaves the built-in as it was.

func MoveBack added in v0.1.506

func MoveBack(ctx context.Context, id string) error

MoveBack gives the id back to the built-in: its accounts as they were set aside, with what the plugin has of them now (newer tokens, accounts signed in to since), in the plugin's order; then the plugin signs out.

func MovePackage added in v0.1.506

func MovePackage(id string) string

MovePackage is the plugin the built-in id moves to.

func MoveRetiring added in v0.1.506

func MoveRetiring(ctx context.Context) map[string]error

MoveRetiring moves the built-ins being retired that have accounts, at start-up: once, or again moveRetry after one failed. One the user moved back stays.

func Moved added in v0.1.506

func Moved(id string) bool

Moved is whether the built-in id's accounts are its plugin's now.

func MovedOnto added in v0.1.538

func MovedOnto(name string) []string

MovedOnto are the built-ins moved onto the plugin named (its spec or package name).

func NextLogin added in v0.1.402

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

NextLogin is the account agent should be signed in to instead of the one it is on: the account magpie moved it off, once that has room again (back); else, when the one it is on 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 OnPlugins added in v0.1.506

func OnPlugins() []string

OnPlugins are the built-ins moved onto their plugins.

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 OpenCodeClient added in v0.1.615

func OpenCodeClient(h http.Header, session string)

OpenCodeClient makes a request to OpenCode's gateway (Zen or Go) carry what OpenCode itself sends there (packages/opencode/src/session/llm/ request.ts, for a provider whose id starts with "opencode"): its User-Agent, the session in x-opencode-session, the turn in x-opencode-request, and x-opencode-client and x-opencode-project. Zen's free models are served to no one else ("OpenCode's free tier can only be used from within OpenCode"). session names the conversation; one already in OpenCode's form (ses_…) goes as it is, any other becomes one, the same for the same conversation, which Zen routes and caches by.

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 ParseDay added in v0.1.570

func ParseDay(s string) (string, bool)

ParseDay reads a day of the week, "mon" or "Monday", as Weekdays has it.

func ParseDays added in v0.1.570

func ParseDays(v string) ([]string, error)

ParseDays reads days of the week: "mon-fri", "sat,sun", "mon,wed-fri"; a range may run past Sunday (fri-mon).

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 PluginAPIKey added in v0.1.479

func PluginAPIKey(ctx context.Context, id string, method int, inputs map[string]string, key string) (string, error)

PluginAPIKey signs in to a plugin's provider with a key, as its "api" method does, beside the accounts signed in already; it gives the provider's magpie id.

func PluginID added in v0.1.479

func PluginID(id string) string

PluginID is the id magpie gives the provider OpenCode calls id: the same, unless a preset or a built-in subscription has it (google, openai, anthropic), when it is id-plugin — but for a built-in moved onto the plugin, whose id the plugin has now.

func PluginIcon added in v0.1.553

func PluginIcon(pp plugin.Provider) string

PluginIcon is the icon a plugin's provider shows: the picture its plugin gives it (the auth hook's icon, or package.json's magpie.icon), kept as a picture given by hand is, else the one the plugin market gives it.

func PluginOf added in v0.1.479

func PluginOf(id string) (plugin.Provider, bool)

PluginOf is the plugin provider magpie's provider id is, when it is one.

func PriceKey added in v0.1.504

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

PriceKey is the key a price for pid's model is stored at, and whether the provider naming that key is still there at all.

The spelling that was given comes first, because a price outlives the provider it was set for and nothing rewrites the key when that provider goes: "b/vendor/m" can still be where a price is held while a provider of some other id answers to "b" as its display name. Resolving that name first would take the second provider's price away instead — none is stored under it, so nothing would change, the caller would be told it had, and the price the user meant would stay in the file to be counted at. Only where nothing is stored under the spelling is the provider looked for, by the id it has or the one it was renamed from: that is where SetModelPrice keeps a price set through a display name, and the same resolution EffectivePrice reads it back under.

func PricedName added in v0.1.418

func PricedName(model string) string

PricedName is the catalog ID used for a list-price estimate. Prefer a directly listed model before falling back to a documented alias.

func ProbeClaudeVia added in v0.1.551

func ProbeClaudeVia(f func(ctx context.Context, configDir, model string) error)

ProbeClaudeVia sets how a Claude account's test runs Claude Code.

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)

QoderAuthURL starts a sign-in on the global site.

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 on the global site.

func QoderCredentialOf added in v0.1.528

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

QoderCredentialOf is QoderCredential for the site agent names ("qoder" or "qoder-cn").

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 QoderModelOf added in v0.1.528

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

QoderModelOf is QoderModel for the site agent names.

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 RemovePlugin added in v0.1.538

func RemovePlugin(ctx context.Context, name string) error

RemovePlugin removes the plugin named, the built-ins moved onto it moved back to themselves first.

func RemoveSearchAPI added in v0.1.587

func RemoveSearchAPI(vendor string) error

RemoveSearchAPI takes the vendor's search API away.

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 RestoreSearchAPIs added in v0.1.587

func RestoreSearchAPIs(as []SearchAPI) error

RestoreSearchAPIs puts search APIs from a backup in, each replacing the one of its vendor here; one that came without a key keeps the key here.

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 SentNameIn added in v0.1.560

func SentNameIn(wires map[string]string, pid, model, effort string) string

SentNameIn is the name a call on the provider's model goes out under at that effort: the name the vendor would be asked for now, which is the one magpie knows the model by unless the user gave one. It is UpstreamNameAs for the id that call asks for, which is not the model magpie knows everywhere: on an Antigravity account it is the variant of it that effort picks, so a name given for the provider asks for each level by its own id, and a ledger reading a record back reads the vendor's reply against the name that really went out — the same one the gateway sent — rather than against the family it is one level of.

The effort is the one the gateway sent, already fitted to the model's own levels, which is what a record keeps of it, so a level of the model's own is one of its variants and goes out as that one. An effort that is no level of the family names the same id the gateway asked for all the same: the level of the family's own nearest (AntigravitySentID), which is where the envelope went out.

It is SentNameOnIn for the caller that has nothing but the id — a record in the ledger, which keeps the id the call went out on and nothing else. A provider that is an account is built with that account's own id as its own (googleProvider and the rest of the account providers), so the id says which account it was, and a provider of the user's own is no account's whatever its id is. A record's provider need not even be signed in now, which is why nothing here goes looking for the account behind the id: the id a call went out on is all a record has and all it can be read by.

func SentNameOnIn added in v0.1.560

func SentNameOnIn(wires map[string]string, pid, account, model, effort string) string

SentNameOnIn is SentNameIn for a caller holding the provider itself, and so the account behind it: the call goes out on that account, and it is the account the id the effort picks is a question about. A provider's id is that account's own id today (googleProvider and the rest of the account providers build each one with it), so passing the id for the account reads the same — but the two are one id by construction rather than by rule, and a provider of the user's own has no account at all whatever its id is. So the route, which is holding the provider, asks about the account and lets the gateway's dispatch (codeAssistID, on the same agent) be the one rule.

func ServesModel added in v0.1.560

func ServesModel(p Provider, model string) bool

ServesModel is whether the provider really serves model, listed or exposed: the question SetUpstreamName asks before it keeps a name for one, and the same one, since a name given for a model the provider does not serve is a request magpie would never send it. It is the answer a caller told to take a name off needs as well: a model the provider has nothing like is not asked for by any name, so reporting which one is in force for it would say magpie asks for a model it does not know.

func SetAccountModels added in v0.1.610

func SetAccountModels(id, ref string, models []string) error

SetAccountModels gives the account or key ref of the provider id the models it alone serves; none gives it every model the provider has again.

func SetAccountOrder added in v0.1.605

func SetAccountOrder(id string, order []string) error

SetAccountOrder changes the order used by routing, not just its presentation. The first enabled account becomes first through the same switch used by Make first. Disabled accounts can be moved, but never silently enabled by a drag.

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 SetAutoGroups added in v0.1.603

func SetAutoGroups(on bool) error

SetAutoGroups turns the groups magpie finds on its own on or off, all of them at once (蓝猫 on Discord: they could only be removed one by one). Off, none is listed or served; the groups the user made or changed, one found included, stay, and so do the records of those removed, so that on again brings back the found groups as they were. A found group one of the user's has in it, or classifies with, keeps them on until it is taken out, as DeleteGroup keeps it: the user's group would lose it unsaid.

func SetCodexAutoReset added in v0.1.507

func SetCodexAutoReset(user string, on bool) error

SetCodexAutoReset turns that on or off for user.

func SetContext added in v0.1.532

func SetContext(p Provider, model string, n int) error

SetContext is how long a request one of a provider's models takes, in tokens, over what the vendor's list and models.dev say; 0 takes the user's away, which DropContext does, and "*" is every model of that provider. As with a reply limit, setting one has to name a model the provider serves, and a removal may name one it no longer does.

This is the provider's own Contexts, kept as the one value both the gateway advertises and the routing rules read — a context is a routing input, not only a number agents are shown: at 95% of a held member's window a request moves to a member that takes more (internal/gateway/rules.go). Saving it tells the agents (catalog.Touched), as for any change of the catalog: a window is a number they keep in files of their own — Pi's contextWindow, OpenCode's limit — and read at start-up, so a session already running keeps the window it began with while the gateway's own /models is right at once.

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 SetHiddenModels added in v0.1.460

func SetHiddenModels(agent string, ids []string) error

SetHiddenModels takes these entries out of agent's lists, and puts back every other; none shows it every model its visibility gives it. The agents that keep the models in files of their own are told.

func SetKeepLogin added in v0.1.641

func SetKeepLogin(id string, keep bool) error

SetKeepLogin keeps Codex or Claude Code signed in to the account the user made first (Provider.KeepLogin), or lets magpie move it on again.

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 SetModelOutput added in v0.1.532

func SetModelOutput(id string, n int) error

SetModelOutput is the most a reply of a provider's model may hold, in tokens, over what the vendor's list and models.dev say; 0 takes the user's away, which DropModelOutput does. The id is spelled "provider/model", or "provider/*" for every model of that provider; setting one has to name a model the provider serves, as one no lookup would ever match reads as set and is not. A removal may name a model that has since gone, or a provider that has: that is the entry left to be cleared.

The agents are told of it (catalog.Touched), as for any change of the catalog: a reply limit is a number they keep in files of their own — Pi's maxTokens, OpenCode's limit — and read at start-up, so one only the gateway knew would leave every agent a reply limit behind.

func SetModelPrice added in v0.1.504

func SetModelPrice(id string, p *catalog.Price) error

SetModelPrice is what a provider's model costs the user, in USD per million tokens, kept in settings' ModelPrices the way a name is. A nil price takes the user's away, leaving the model at what its provider lists and only then at its maker's on models.dev; a price of zero is not that, but a model served at no cost. A price no vendor could charge is refused, naming the part that is wrong.

Unlike the other model preferences this does not tell the agents. What a call costs is not what an agent picks a model by, and the model lists magpie keeps in the agents' own files are not its to rewrite over a number in a cost report.

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 SetOrder added in v0.1.627

func SetOrder(ids []string) error

SetOrder saves the order the providers are listed and tried in, by id. Every id must be a provider's, once; the ones left out follow those named, as they are now, so a provider added later goes after them all.

func SetPlainNames added in v0.1.516

func SetPlainNames(on bool) error

SetPlainNames has the agents' model lists name models by their names alone (see Labels), or with their providers' again, and the agents told.

func SetPluginOff added in v0.1.538

func SetPluginOff(ctx context.Context, name string, off bool) error

SetPluginOff turns the plugin named off, the built-ins moved onto it moved back to themselves first, or back on.

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 SetSearchAPI added in v0.1.587

func SetSearchAPI(a SearchAPI) error

SetSearchAPI adds a search API, last, or changes the one of its vendor where it is; a change with no key keeps the key it has.

func SetSuffixMode added in v0.1.595

func SetSuffixMode(mode string) error

SetSuffixMode has the agents' model lists name models as mode says (see Labels), and the agents told when it changes.

func SetUpstreamName added in v0.1.560

func SetUpstreamName(ref, name string) error

SetUpstreamName is the name to send a provider for one of its models; an empty name takes the user's away and sends the one magpie knows. A name is only given for a model the provider really serves: a relay lists the model under the id magpie knows it by and asks for it under the vendor's own, and one it does not list is a request magpie would never send, so naming it is refused here, as a price and a limit are for the same id. A "*" stands for every model of the provider rather than for one, and a removal is exempt, so an entry left for a model that has since gone can still be taken away.

A provider magpie asks through an agent's own backend has no model field to put a name in — the request goes out carrying the id the agent knows — so a name given for one of its models would never be sent (asksOwnBackend).

The ref is taken as the provider it names, by its id now, and the name is kept under that id: a ref is as likely to be spelled with an id the provider had before a rename (Was) or with the name it is shown by, and every lookup of a wire name goes by the id the provider has (UpstreamName). A name under any other spelling of the provider is one no lookup will ever match — a name the provider is never asked for, and a removal that takes away nothing.

The key is checked here, where it is given, and not as the whole settings are written: a hand-edited key no lookup will ever match is a no-op of the user's own making, and must not keep every other setting from being saved.

Kept in settings, and saved without telling the agents, like a price: which model an agent picks, and what it is called, have not changed — only the name the request goes out under.

A removal goes to DropUpstreamName, which works off the key rather than off this provider, so that taking a name away is the same operation whether or not the provider it was given for is still there.

A blank name is a removal, and whether there was a name there to take away is DropUpstreamName's to say, not this one's: a caller with something of its own to say about a name that was not there — `magpie model wire -- reset`, which tells a mistyped id from a model already asked for by the name magpie knows it by — asks DropUpstreamName for the removal itself, the way `magpie model price --reset` asks DropModelPrice. A caller that only wants the model left as it is has nothing to tell the user either way, which is why a blank name is an error and not a second answer.

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 SpentShareOf added in v0.1.641

func SpentShareOf(routing string) float64

SpentShareOf is the share past which routing counts an account spent: SpentShare, but In order sends requests to the first until a window of it is used up or the vendor refuses it, so there an account at 98% is still tried in its turn (#530).

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 StoredOrder added in v0.1.638

func StoredOrder() ([]string, error)

StoredOrder is the order the user put the providers in, as saved; as with Stored, a file that can't be read is an error.

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 — the address the browser ended on, pasted — or a plugin's with the code its page showed.

func SuffixMode added in v0.1.595

func SuffixMode() string

SuffixMode is how the agents' lists name models: SuffixOn, SuffixOwn or SuffixOff.

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, or back to the one it moved off once that has room (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 TookOpenedURL added in v0.1.574

func TookOpenedURL(args []string) bool

TookOpenedURL is magpie run as the browser of a `claude auth login` it started: the page is written down for magpie's window to open, and nothing else runs.

func UpstreamName added in v0.1.560

func UpstreamName(p Provider, model string) string

UpstreamName is the name to send a provider for one of its models: the one the user gave, for the model or for every model of that provider, else the name magpie knows the model by. Every "*" in the name the user gave is that model, wherever it stands: "vendor-c/*" for a provider's every model sends vendor-c/model-3 for model-3, so one name covers a relay that namespaces its models and still asks for each of them by its own, and "vendor/*/pro" sends vendor/model-3/pro. A name with no "*" in it is that one name for every model of the key, which is the right answer only for a relay that does serve them all alike.

The two are deliberately different things. Everything a user or an agent sees — the catalog, the routing groups' membership, what a call is recorded and priced as — is in magpie's name for the model, so a rename upstream never renames a model here. Only the request that goes out carries the vendor's name, and what a reply says answered is compared with it, so a model asked for by the name the vendor serves it under is not read as another one.

func UpstreamNameAs added in v0.1.560

func UpstreamNameAs(p Provider, model, sent string) string

UpstreamNameAs is UpstreamName for a request that goes out asking for sent, which is not always the model magpie knows: an Antigravity account is asked for the variant of it the effort picks, and that is the id the body carries. The two levels of the lookup are kept apart, since they are about different things. A name given for the model itself is the model's, whichever variant answers for it, so a "*" in it is that model and not the variant: the vendor is asked for the model by the name its owner gave, as it is everywhere else in magpie, and not for a "*" it never heard of. A "*" in the provider's own name is whatever the request is going out under, so one name for a provider asks for gemini-3.7-flash-high and gemini-3.7-flash-low each by its own, rather than for the one id whatever level the effort picked.

func UpstreamNameAsIn added in v0.1.560

func UpstreamNameAsIn(wires map[string]string, pid, model, sent string) string

UpstreamNameAsIn is UpstreamNameAs over a settings' ModelWires already read. A name that is only whitespace is no name, as it is in UpstreamNameIn: the lookup falls through to the level below it, and a request with no name at all goes out under the id it was built with.

func UpstreamNameIn added in v0.1.560

func UpstreamNameIn(wires map[string]string, pid, model string) string

UpstreamNameIn is UpstreamName over a settings' ModelWires already read, for a caller that walks a whole ledger of models in a row. A name that is only whitespace — one an older magpie stored, or one hand-edited into the file — is no name, as it is where one is given.

func UsageClaudeVia added in v0.1.558

func UsageClaudeVia(f func(ctx context.Context) (string, error))

UsageClaudeVia sets how Claude Code's /usage runs.

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 WatchQuotas added in v0.1.540

func WatchQuotas(ctx context.Context, wake <-chan struct{}, send func(QuotaAlert))

WatchQuotas reads every allowance and balance while an alert is set, and hands send each one due, until ctx ends. wake, when it gets a value, has it look at once (an alert just turned on).

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 ZedBody added in v0.1.632

func ZedBody(body []byte) []byte

Zed's cloud reads an OpenAI model's request into its own Responses types (zed-industries/zed, crates/open_ai/src/responses.rs) before it goes on to OpenAI, and turns the whole request away over anything they don't name: "failed to parse OpenAI Responses API request: unknown variant `developer`, expected one of `user`, `assistant`, `system`, `tool`" on Codex's developer messages. What they take:

  • input items tagged by type: message, function_call, function_call_output, custom_tool_call, custom_tool_call_output, reasoning, compaction, compaction_trigger;
  • a message's role: user, assistant, system, tool; its content a list;
  • a reasoning item's content a list, if there (serde's default is for a missing field, not a null one);
  • tools of type function or custom;
  • include: reasoning.encrypted_content alone;
  • reasoning.summary: auto, concise, detailed.

ZedBody is a Responses request fitted to those, Codex's above all; a request in another API (one with no input list) goes as it came.

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) Levels added in v0.1.635

func (a *Account) Levels(model string) (levels []string, ok bool)

Levels are the reasoning levels the account's own list gives the model — a Free ChatGPT plan's may be fewer than a Plus one's — and ok is false when that list wasn't fetched, doesn't have the model or gives it none.

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) StandIn added in v0.1.623

func (a *Account) StandIn() bool

StandIn says the account is a saved one served in the place of the agent's own sign-in, which is signed out.

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 — for a Claude account, the config directory Claude Code runs on it in; ok is false for the agent's own, which the agent signs itself.

func (*Account) UsageAgent added in v0.1.514

func (a *Account) UsageAgent() string

UsageAgent is the agent an account's allowance is asked for by (LoginUsage, Allowances): a plugin's accounts by their provider's.

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.

func (Allowance) Pace added in v0.1.644

func (a Allowance) Pace(model string, now time.Time) (pace float64, due time.Time)

Pace is the share of its week an account has left for model, per hour until that week renews: the rate it would have to be used at to spend the week just in time, so the account with the highest has the most to lose at its reset. Of several budget windows that count the model (Opus's own beside the general), the tightest; due is when that one renews, zero when it isn't known. A window not started, or whose reset isn't known, is taken to run its whole span from now; one that doesn't say how long it runs (a plugin may not) is a budget, for as long as its reset says, else a week. The hours until a reset are never taken as fewer than one, or a window a minute from renewing would outweigh all the rest. An account whose vendor tells no budget window (Claude's own usage command gives the five hours alone) is taken to have a week not started with the share its fullest window has used: those go by what they have used, among the rest as the fresh are.

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 BalancePart added in v0.1.587

type BalancePart struct {
	Label   string   `json:"label,omitempty"`
	Text    string   `json:"text"`
	Percent *float64 `json:"percent,omitempty"`
}

BalancePart is one amount of a balance field, for a card to show each of several on a line of its own, its label apart from its figure, rather than all of them run together: Percent is its share, 0 to 100, when it was asked as one ("%" after it), for a meter.

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"`
	// Shared are a group's levels its members have in common: its Efforts,
	// unless the group names its own (Group.Levels).
	Shared []string `json:"-"`
	// Reasoning is set on a model that thinks, levels or not: one with a
	// thinking switch alone has it and no Efforts (a group's: every
	// member thinks).
	Reasoning bool `json:"reasoning,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): its visibility's, less the models taken out of its lists one by one (HiddenModels).

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 EntryOf added in v0.1.532

func EntryOf(id string) (Entry, bool)

EntryOf is the model as the agents see it, by the id they ask for. It is the catalog's own entry, so the window and reply limit it carries are the ones a request is routed and metered against, with whatever the user set already applied.

func ListedFor added in v0.1.460

func ListedFor(agent string) (listed, kept []Entry)

ListedFor is the catalog agent's visibility gives it, the models it may pick to show or not among, and what the visibility keeps from it.

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 ServedEntryOf added in v0.1.532

func ServedEntryOf(id string) (Entry, bool)

ServedEntryOf is the model a limit may be set on, by the id the user typed: any model its provider serves, not only the catalog's own entry. The setters ask serves — the provider's own models deciding, switched off or not — so a provider kept unlisted, still served through a routing group, takes a window and a reply limit all the same, and a provider switched off is served again as soon as it is on, keeping what it was given. Both keep it in the entry they answer with, so a query that said "is not a model this provider serves" about such an id would contradict the command run right after it, which stores one.

func Unlisted added in v0.1.572

func Unlisted() []Entry

Unlisted are the models Served has and Catalog doesn't: those of the providers kept for routing groups (Provider.Unlisted), which agents aren't offered.

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"`
	// Users names those saved accounts (no secrets), so they can be
	// removed from magpie while none of them is offered.
	Users []string `json:"users,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; or Manual
	Affinity string   `json:"affinity,omitempty"` // as Provider.Affinity
	// Pick is the member a Manual group sends every request to, as the
	// user picked it on the group's card; "" is its first. It is kept
	// while the group routes otherwise, for when it is manual again.
	Pick string `json:"pick,omitempty"`
	// 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"`
	// Levels are the reasoning levels agents are offered for the group,
	// lowest first, when the user names them (#295): rather than those
	// every member has, so that a member with few doesn't take the rest
	// from the others. A member without the level a request asks for is
	// sent the one it has nearest, as ever. Empty offers the members'
	// shared levels.
	Levels []string `json:"levels,omitempty"`
	// Fast are the members (as Members spells them) sent in their
	// vendor's fast mode, where the model has one (see CanFast). Kept
	// beside Members, not in their ids, so a version before it still
	// routes to them, only not fast.
	Fast []string `json:"fast,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, error)

StoredGroups is the groups as saved: the user's own, and the found ones the user removed. As with Stored, a file that can't be read is an error.

func (Group) IsFast added in v0.1.577

func (g Group) IsFast(id string) bool

IsFast reports whether the group sends its member id fast.

func (Group) Live added in v0.1.498

func (g Group) Live() Group

Live is the group as the gateway routes it: a manual group's rules wait (the member picked is all it sends to), though they are kept.

func (Group) Picked added in v0.1.498

func (g Group) Picked() string

Picked is the member a manual group sends to: the one the user picked while it is in the group, else its first.

func (*Group) RenameMember added in v0.1.577

func (g *Group) RenameMember(from, to string)

RenameMember has the group's member from go by to (its effort changed): its rules, its pick and its fast mode follow it.

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.

func (*Group) SetMemberFast added in v0.1.577

func (g *Group) SetMemberFast(id string, fast bool)

SetMemberFast sends the group's member id fast, or not, where it is in the group.

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 ImportFactoryKeys added in v0.1.638

func ImportFactoryKeys(ctx context.Context, texts []string) ([]ImportedAccount, error)

ImportFactoryKeys adds Factory accounts by their API keys, found in the pasted texts, each checked with whoami first, and says what became of each.

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"`
	// Paused is the account the agent is signed in to, passed over by the
	// gateway while another is on (savedLogin.Paused).
	Paused bool `json:"paused,omitempty"`
	// Returns is the account magpie signed the agent out of when it was
	// spent, and signs it back in to once it has room again (#408).
	Returns bool `json:"returns,omitempty"`
	// contains filtered or unexported fields
}

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
	// Fast is set on a member the group sends in its vendor's fast mode
	// (Group.Fast), where its model has one.
	Fast bool
}

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 Migration added in v0.1.506

type Migration struct {
	State   string    `json:"state"`
	Package string    `json:"package,omitempty"`
	At      time.Time `json:"at"`
	Err     string    `json:"error,omitempty"`
	// Accounts are the plugin's accounts the move made or took over.
	Accounts []movedAccount `json:"accounts,omitempty"`
	// Backup is the built-in's accounts as logins.json kept them.
	Backup []savedLogin `json:"backup,omitempty"`
	// Kept is what else of the built-in's the move set aside (Kiro's key).
	Kept json.RawMessage `json:"kept,omitempty"`
	// Installed is whether the move installed the plugin: going back takes
	// it away again when it serves nothing else.
	Installed bool `json:"installed,omitempty"`
	// Host is the built-in's API host, which the plugin's provider shows.
	Host string `json:"host,omitempty"`
	// Why is a failed move's reason, for the page to say in the user's
	// language.
	Why *MoveWhy `json:"why,omitempty"`
}

Migration is where one built-in's move stands.

func MigrationOf added in v0.1.506

func MigrationOf(id string) (Migration, bool)

MigrationOf is where the built-in id's move stands.

type MoveCandidate added in v0.1.552

type MoveCandidate struct {
	ID       string `json:"id"`
	Name     string `json:"name"`
	Package  string `json:"package"`
	Accounts int    `json:"accounts"`
}

MoveCandidate is a built-in with accounts its plugin could run instead.

func MoveCandidates added in v0.1.552

func MoveCandidates() []MoveCandidate

MoveCandidates are the built-ins not on their plugins that have accounts to move, by name.

type MoveWhy added in v0.1.552

type MoveWhy struct {
	Code string            `json:"code"`
	Args map[string]string `json:"args,omitempty"`
}

MoveWhy is why a move didn't go through: Code names the case, Args fill in its sentence.

offline   magpie couldn't reach npm (or Bun's download) to install the plugin
install   npm couldn't install it: line
lapsed    every account of name needs signing in again
unserved  the plugin doesn't serve models (their names)
account   user doesn't work through the plugin: error

func WhyOf added in v0.1.552

func WhyOf(err error) *MoveWhy

WhyOf is the reason a move failed, nil for one it has no words for.

type Moving added in v0.1.506

type Moving struct {
	User      string
	First, On bool
	// Lapsed is an account the vendor already refused: it goes along, but
	// isn't tried.
	Lapsed bool
	// Plan is the plan the account showed, kept beside it until the
	// plugin tells it anew.
	Plan string
	// Own is the agent's own sign-in (its CLI's, its app's), which the
	// plugin reads where the agent keeps it, as the built-in did.
	Own  bool
	Auth map[string]any
}

Moving is one of a built-in's accounts on its way to the plugin.

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
	KeyHint   string   `json:"keyHint,omitempty"`   // the key field's placeholder, when it says more than NoKey's
	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"`
	// EndpointNeeded is what the editor says when no endpoint was given.
	EndpointNeeded string `json:"endpointNeeded,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;
	// "pace" the one with the most of its week left per hour until it
	// renews first, so less of a week is lost at its reset.
	// 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"`

	// KeepLogin, on Codex's or Claude Code's subscription, keeps the agent
	// signed in to the account the user made first: magpie doesn't sign it
	// in to another when that one runs low or out (#524). The gateway still
	// spreads its requests over the accounts that are on, as Routing says.
	KeepLogin bool `json:"keepLogin,omitempty"`

	// MaxConcurrency is how many requests may be out at the vendor at once
	// on each of its keys or accounts (Discord, Lemon: a Codex account is
	// risk-controlled past five or six at once); the rest wait their turn,
	// in the order they came (see Concurrency). nil follows what a
	// plugin's provider says it takes, else none; 0 is no limit.
	MaxConcurrency *int `json:"maxConcurrency,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"`

	// Searches says the vendor answers a web search tool offered on its
	// Anthropic or Responses API by itself (web_search_20250305,
	// web_search): a relay in front of Anthropic's or OpenAI's API, which
	// magpie can't tell from its host. A request offering one then goes to
	// it as the client sent it, rather than given magpie's search (#359).
	Searches bool `json:"searches,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"`
	// AccountModels is, for a provider holding several accounts or keys,
	// the models each one the user narrowed serves, and no others (#474):
	// an account by its name in lower case, a key by its KeyID. One not in
	// it serves every model the provider does (see account_models.go).
	AccountModels map[string][]string `json:"accountModels,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, error)

Stored is the providers as providers.json keeps them: keys included, signed-in accounts only as the model picks the user made for them. A file that can't be read is an error, never none: a backup or a sync carrying none would take every provider away where it is put back.

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) AccountRefs added in v0.1.610

func (p Provider) AccountRefs() []string

AccountRefs are the provider's accounts, or keys, as AccountModels knows them: a signed-in account's name, a key's KeyID.

func (Provider) AccountServes added in v0.1.610

func (p Provider) AccountServes(ref, model string) bool

AccountServes says whether the account or key ref (a signed-in account's name, a key's KeyID) is let serve model: true when it has no list of its own.

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) Concurrency added in v0.1.633

func (p Provider) Concurrency() int

Concurrency is how many requests the gateway lets be out at the vendor at once on each of the provider's keys or accounts, 0 for no limit: the user's MaxConcurrency when they set one, else what the plugin giving the provider says it takes (its auth hook's maxConcurrency, or its package.json's magpie.maxConcurrency), else none.

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) Do added in v0.1.479

func (p Provider) Do(client *http.Client, req *http.Request) (*http.Response, error)

Do sends req, through the account's own transport when it has one (a plugin's) and client otherwise.

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) IsCline added in v0.1.630

func (p Provider) IsCline() bool

IsCline reports whether the provider is the Cline API: made from the ClinePass preset, or at Cline's host.

func (Provider) IsKilo added in v0.1.635

func (p Provider) IsKilo() bool

IsKilo reports whether the provider is the Kilo Gateway: made from its preset, or at Kilo's API 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) IsPlugin added in v0.1.479

func (p Provider) IsPlugin() bool

IsPlugin is whether the provider is a plugin's.

func (Provider) IsRemoteMagpie added in v0.1.527

func (p Provider) IsRemoteMagpie() bool

IsRemoteMagpie reports whether the provider is another magpie.

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) Listed added in v0.1.552

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

Listed is when the models listed now were had from the vendor: fetched for a built-in, listed by its plugin for a plugin'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) ModelTest added in v0.1.636

func (p Provider) ModelTest() string

ModelTest says why p's models can't each be sent a test request ("" when they can): "decide" for a decision API, whose models only classify and whose endpoint Test asks it for them; "own-api" for a sign-in reached through its agent's own API (Cursor, Devin, Kiro, Zed, Qoder, a Google sign-in), which the gateway translates every request for, so a probe has no endpoint to go to.

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) OpenCodeFree added in v0.1.616

func (p Provider) OpenCodeFree(model string) bool

OpenCodeFree says whether model is one of OpenCode Zen's free ones on p, which Zen serves only to what looks like OpenCode: besides the headers OpenCodeClient sets, a streamed request offering tools named bash and read (lowercase, by name alone; checked against Zen, October 2026). The gateway asks them so whoever the client is (gateway/zenfree.go), and the Test button's probe so (zenFreeProbe).

func (Provider) OwnPaused added in v0.1.455

func (p Provider) OwnPaused() bool

OwnPaused says the provider is the account a Claude Code or Codex agent is signed in to, paused while another of its accounts is on (#263): the gateway passes over it, the agent staying signed in to it.

func (Provider) PluginConcurrency added in v0.1.633

func (p Provider) PluginConcurrency() int

PluginConcurrency is what the plugin giving the provider says it takes at once, as it lists it now; 0 for none, or for a provider no plugin gives.

func (Provider) PluginProvider added in v0.1.584

func (p Provider) PluginProvider() string

PluginProvider is the id OpenCode knows the plugin's provider p is by (grok, kiro), whatever magpie names it; "" for one no plugin gives.

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, PipeLLM'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, sent []byte, status int, body []byte) bool

Retry is whether a request (sent) 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) UpstreamNames added in v0.1.560

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

UpstreamNames are the names the user gave the provider's models, by model id, with the one given for all of them under "*" — each as it will be sent, trimmed, "*" and all, which is what a list of them shows. A name that is only whitespace is none, and is not listed.

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"`
	AsOf     *time.Time  `json:"asOf,omitempty"` // the cached reading's time, nil for a new one
	// 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 QuotaAlert added in v0.1.540

type QuotaAlert struct {
	Provider string
	Name     string // the card's name, as the Usage page shows it
	User     string // the account or key, when the provider has several
	Window   string // the window's name
	Used     float64
	ResetsAt *time.Time
	Balance  string // the balance as the vendor tells it
}

QuotaAlert is one thing to tell the user: a window used past the share (Window set) or a balance at or under the amount (Balance set).

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"`
	// Family is the model family a per-model window belongs to (Antigravity's
	// "Gemini 3.1 Pro (High)" is Gemini's), for the GUI to show one figure a
	// family, the tightest; each window is still here, and routing reads
	// them one by one.
	Family string `json:"family,omitempty"`
	// Pool is the group of models that share one allowance (Antigravity's
	// "Gemini", "Claude & GPT"): on the group's own windows, a 5-hour and
	// a weekly, which name no Model, and on each per-model window drawing
	// on it, for the GUI to show the group's windows in place of its
	// models'.
	Pool string `json:"pool,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.

func PooledWindows added in v0.1.613

func PooledWindows(ws []QuotaWindow) []QuotaWindow

PooledWindows are ws as a page of text shows them: a pool's own windows, named with their pool ("Gemini · 7 days"), in place of the per-model windows drawing on it; ws as it is when it has no pool.

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 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; for Claude already_used, not_limited, cooldown, ineligible, unavailable too) and Windows how many windows started again.

func AutoUseCodexReset added in v0.1.507

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

AutoUseCodexReset spends one of the Codex account user's resets (the one Codex is signed in to when "") if the user turned that on for it, its weekly window is used up, it holds one, and none was spent by itself in this week yet. Code is "" when none was tried; the caller asks again only on "reset".

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"`
	// Time: the turn begins within these hours of the day, local time — a
	// vendor's peak-price hours sent to another, say.
	Time *TimeWindow `json:"time,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
	// At is when the request came, for a rule's hours; a zero time is in
	// none.
	At time.Time
}

RuleRequest is what a rule looks at in a request.

type SearchAPI added in v0.1.587

type SearchAPI struct {
	Vendor string `json:"vendor"` // one of SearchVendors
	Key    string `json:"key,omitempty"`
	// URL is where it is: a SearXNG's own, or another address for one of
	// the others (a Firecrawl run by the user); empty is the vendor's.
	URL string `json:"url,omitempty"`
}

SearchAPI is a web search API the user gave magpie a key to.

func SearchAPIs added in v0.1.587

func SearchAPIs() []SearchAPI

SearchAPIs are the search APIs that can be asked, in the order they are tried.

func StoredSearchAPIs added in v0.1.587

func StoredSearchAPIs() []SearchAPI

StoredSearchAPIs are the search APIs as saved, keys and all.

func (SearchAPI) Base added in v0.1.587

func (a SearchAPI) Base() string

Base is the address it is asked at, without a slash at its end.

func (SearchAPI) Name added in v0.1.587

func (a SearchAPI) Name() string

Name is the vendor's name.

func (SearchAPI) Ready added in v0.1.587

func (a SearchAPI) Ready() bool

Ready is whether it can be asked: a vendor magpie knows, at an address, with a key (a SearXNG may need none).

type SearchVendor added in v0.1.587

type SearchVendor struct {
	ID, Name string
	Base     string // its address, "" for one the user runs
	KeysURL  string // where its keys are made
}

SearchVendor is a search API magpie can ask.

func SearchVendorOf added in v0.1.587

func SearchVendorOf(id string) (SearchVendor, bool)

SearchVendorOf is the vendor by its id.

type SessionIdentity added in v0.1.579

type SessionIdentity struct {
	Agent, AccountID, UserID, OrganizationID, User string
	// OfficialLogin describes this account's recorded login method, not the
	// route or credentials used for any particular historical request.
	OfficialLogin bool
}

SessionIdentity is an account's public identity, without its credentials.

func SessionIdentities added in v0.1.579

func SessionIdentities(codexDir string) []SessionIdentity

SessionIdentities reads the agent's current identity and remembered identities. Callers must match the IDs recorded in a session; presence alone is not evidence that the account served that session's requests.

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
	// PasteCode is a plugin's sign-in finished by the code its page shows
	PasteCode bool `json:"pasteCode,omitempty"`
	// PasteKey is a sign-in an API key made on KeysURL also finishes
	// (Command Code's, whose page posts its key where a pasted address
	// can't carry it)
	PasteKey     bool   `json:"pasteKey,omitempty"`
	KeysURL      string `json:"keysURL,omitempty"`
	Instructions string `json:"instructions,omitempty"` // a plugin's words for its page
	// 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
	// Again is an account listed already: its sign-in was renewed rather
	// than a new account added (#413)
	Again bool   `json:"again,omitempty"`
	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 StartPluginSignIn added in v0.1.479

func StartPluginSignIn(id string, method int, inputs map[string]string) (SignInState, error)

StartPluginSignIn begins signing in to a plugin's provider (OpenCode's id) with its OAuth method, the method's questions answered: the page to open, then either the plugin notices on its own or the code the page shows is pasted back (SubmitSignInCallback). SignInStatus follows it, as it does a built-in sign-in; its Agent is the provider's magpie id. The account goes beside those signed in already, or replaces the one it is. A built-in moved onto its plugin installs the CLI it runs through first, as the built-in's sign-in did.

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
	// BalanceParts are the Balance's amounts each apart, when the balance
	// field the user wrote has several or a percent (cardParts)
	BalanceParts []BalancePart `json:"balanceParts,omitempty"`
	// 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"`
	// ReadAt is when a key's balance was read, which the minute it is
	// kept for (KeyBalances) leaves behind the page's asking.
	ReadAt *time.Time `json:"readAt,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 TimeWindow added in v0.1.570

type TimeWindow struct {
	From string   `json:"from"`
	To   string   `json:"to"`
	Days []string `json:"days,omitempty"`
}

TimeWindow is hours of the day, local time: From until To, "HH:MM" each, past midnight when To comes before From (22:00–08:00), the whole day when they are the same. Days, when set, are the days it holds on ("mon" … "sun"); a window past midnight is of the day it begins on, so Friday's 22:00–08:00 takes Saturday's early hours too.

func ParseTimeWindow added in v0.1.570

func ParseTimeWindow(v string) (*TimeWindow, error)

ParseTimeWindow reads hours of the day: 09:00-18:00, 22:00-08:00.

func (TimeWindow) DaysText added in v0.1.570

func (w TimeWindow) DaysText() string

DaysText is the window's days for a list: "Mon–Fri", "Sat,Sun", "Mon,Wed–Fri"; "" for every day.

func (TimeWindow) Holds added in v0.1.570

func (w TimeWindow) Holds(at time.Time) bool

Holds reports whether at is within the window, on the machine's clock.

func (TimeWindow) Text added in v0.1.570

func (w TimeWindow) Text() string

Text is the window as a rule's conditions show it: "09:00–18:00 Mon–Fri".

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.

Source Files

Jump to

Keyboard shortcuts

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