Help us shape the future of Go! Take the 2026 Go Developer Survey

gateway

package
v0.1.2657 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 115 Imported by: 0

Documentation

Overview

Package gateway is the local LLM endpoint agents talk to. It serves the wire APIs coding agents speak — OpenAI Chat Completions, OpenAI Responses, Anthropic Messages and Google Gemini — and forwards each call to whichever provider serves the requested model, translating between the APIs when the provider does not speak the one the agent used.

Index

Constants

View Source
const (
	CPUSeconds    = 30
	CPUMinSeconds = 5
	CPUMaxSeconds = 120
)

The seconds a CPU profile records: CPUSeconds unless the caller asks for others, from CPUMinSeconds to CPUMaxSeconds.

View Source
const (
	HubRootsMeta  = "magpie/roots"
	HubClientMeta = "magpie/client"
	HubModelMeta  = "magpie/model"
	// HubSessionMeta is the _meta key a call carries its caller's session
	// in (HubCaller.Session), to Magpie Browser and to another magpie's
	// router, which passes it on as its own caller's
	HubSessionMeta = "magpie/session"
)

The _meta keys a call of magpie's image server carries its caller in: the roots, a list of file URIs (an empty one when the agent has none here), and the client; and the one its result says the model it drew with in (provider/model), for the hub's row of the call.

View Source
const (
	PendingMeta = "usemagpie.ai/pending"
	FilesMeta   = "usemagpie.ai/files"
)

Under these keys of a tool result's _meta the image server tells a client that saves what it made (magpie tool) what its text tells an agent: the id to wait on with generation_result, and each file made, at its URL, and whether it is in the answer itself.

View Source
const (
	GenerateImageTool    = "generate_image"
	GenerateVideoTool    = "generate_video"
	GenerationResultTool = "generation_result"
)

The tools Magpie Image and the image MCP server have.

View Source
const (
	PartSystem  = "system"  // the agent's own prompt: system, developer and harness messages
	PartTools   = "tools"   // tool definitions
	PartSkills  = "skills"  // the skills the agent lists for the model to load
	PartMemory  = "memory"  // instruction files, reminders
	PartFiles   = "files"   // files and images the tools read in
	PartResults = "results" // the tools' other output
	PartChat    = "chat"    // what the user and the model said, the model's calls
)

The kinds of a prompt's parts, in the order they are shown.

View Source
const (
	AgentHeader = "X-Magpie-Agent"
	ViaHeader   = "X-Magpie-Via"
)

A request passed on to another computer's magpie (a Remote magpie provider) goes as magpie's own, with magpie's User-Agent and the other magpie's key, so that magpie knew it only as "magpie" (Jorben on Discord). It now names the agent it came from (AgentHeader) and the computer (ViaHeader), and the other magpie keeps them in its usage, as "Claude Code · via <computer>". They are a label and nothing more: what magpie does with the request — the models an agent is shown, its stand-ins, a routing group's rules — still goes by who sent it, and they are taken only from a magpie's request (its User-Agent), one a client on the network could send only with the key anyway, and could name itself any agent by its User-Agent as well. No vendor is ever sent them: they come off every request as it arrives, and go on only to a remote magpie.

View Source
const (
	SearcherGone   = "gone"    // no such provider any more
	SearcherOff    = "off"     // turned off, or signed out
	SearcherCant   = "cant"    // it can't search the web by itself
	SearcherNoneOf = "nomodel" // it lists no model to search with
)

Why the searcher Settings names isn't used, and magpie picks one itself.

View Source
const (
	TLSCertEnv = "MAGPIE_TLS_CERT"
	TLSKeyEnv  = "MAGPIE_TLS_KEY"
)

TLSCertEnv and TLSKeyEnv name the PEM certificate (its chain after it) and private key files the flags set.

View Source
const AccountHeader = "X-Magpie-Account"

AccountHeader pins a request to one of a subscription's accounts, by its user (an email, a login) or its id in the routing trace: only it is tried, and when it can't take the request the caller is told why rather than another account answering — a probe of one account needs that one. It goes no further than magpie.

View Source
const AllowIPsEnv = "MAGPIE_ALLOW_IPS"

AllowIPsEnv names the environment variable that sets the list, in place of Settings' (for Docker and `magpie web`).

View Source
const AlphaSearchPath = "/alpha/search"

AlphaSearchPath is where Codex's own web search, its web.run tool, goes: "alpha/search" under the model provider's base URL, so /v1/alpha/search on magpie's provider and CodexPath+"/alpha/search" when Codex is signed in to ChatGPT. Codex offers web.run since 0.143 for a provider that sends x-openai-actor-authorization, as magpie's does, on a model whose catalog entry says use_responses_lite, as a ChatGPT account's do in magpie (codexcat copies Codex's own entry). Unanswered, the 404 ended the turn: Codex takes any failure of web.run as fatal (anton on Discord).

View Source
const ArchiveHeader = "X-Magpie-Archive-Id"

ArchiveHeader carries a call's archive id on its response.

View Source
const BrowserExtensionPath = "/v1/magpie/browser/extension"

BrowserExtensionPath is where the extension connects.

View Source
const BrowserMCPPath = "/mcp/magpie/browser"

BrowserMCPPath is where the browser MCP server is served.

View Source
const BrowserSessionHeader = "X-Magpie-Browser-Session"

BrowserSessionHeader names the agent session a call is from, so each one goes on in the tab it was working in; `magpie mcp browser` sends one a process.

View Source
const BrowserStatusPath = "/v1/magpie/browser"

BrowserStatusPath tells whether the extension is connected.

View Source
const CPUPath = "/v1/magpie/cpu"

CPUPath is where the gateway answers a CPU profile.

View Source
const CPUStatsHeader = "X-Magpie-CPU-Stats"

CPUStatsHeader carries CPUStats, as JSON, beside the profile.

View Source
const ClaudeRunsPath = "/v1/magpie/claude-runs"

ClaudeRunsPath is where the gateway lists its Claude Code runs.

View Source
const CodexCatalogPath = "/v1/codex/models"

CodexCatalogPath is Codex's model list in its own shape, for a Codex that names magpie its model_provider (base_url <gateway>/v1) on another computer, with a gateway key (#1281): its model_catalog_url. /v1/models stays OpenAI's list, which Codex can't read, and CodexPath's list is the ChatGPT backend's, for a Codex signed in to ChatGPT here.

View Source
const CodexPath = "/backend-api/codex"

CodexPath is where Codex's built-in OpenAI provider reaches magpie, as its `openai_base_url`. Codex keeps its own sign-in and sends what it would send the ChatGPT backend: a request for one of its own models goes on there as it came, one for a magpie model (a catalog id, provider/model) is served like any other, and the model list is OpenAI's with magpie's added. Ending in /backend-api/codex keeps Codex treating it as that backend.

View Source
const DefaultAddr = "127.0.0.1:3425"

DefaultAddr is where the gateway listens unless Settings' port or MAGPIE_ADDR says otherwise.

View Source
const DrawAgent = "magpie-image/1"

DrawAgent is the User-Agent magpie's generate_image tool adds to its own.

View Source
const GoroutineStatsHeader = "X-Magpie-Goroutine-Stats"

GoroutineStatsHeader carries GoroutineStats, as JSON, beside the dump.

View Source
const GoroutinesPath = "/v1/magpie/goroutines"

GoroutinesPath is where the gateway answers a goroutine dump.

View Source
const HeapPath = "/v1/magpie/heap"

HeapPath is where the gateway answers a heap profile.

View Source
const HeapStatsHeader = "X-Magpie-Heap-Stats"

HeapStatsHeader carries HeapStats, as JSON, beside the profile.

View Source
const HubMCPAll = "/mcp/magpie/hub"

HubMCPAll is the hub for any other app (Cursor, VS Code, a script): one address with every server in the Library, ticked for an agent or not. It is the agent "" to Hub.

View Source
const HubMCPPath = "/mcp/magpie/hub/"

HubMCPPath is where the hub is served, the agent's id after it.

View Source
const ImageMCPFiles = ImageMCPPath + "/files/"

ImageMCPFiles is where the images it made are served from.

View Source
const ImageMCPPath = "/mcp/magpie/image"

ImageMCPPath is where the image generation MCP server is served.

View Source
const KeyPagePath = "/me"

KeyPagePath is the page a gateway key's holder opens in a browser at the address they reach the gateway at (zytszone on X: magpie shared with a whole department, whose people can't be given the admin's app). It asks for their key and shows, from keyInfo, that key's own name, limits, usage and models, and the setup to paste into Claude Code, Codex or an OpenAI-compatible client, with the address it was opened at as the base URL.

View Source
const KeysPath = "/v1/magpie/keys"

KeysPath issues short-lived gateway keys (xazaj on X: an orchestrator gives each sandboxed agent a key of its own that stops working by itself). POST issues one, GET lists those the caller issued, DELETE KeysPath/{id} revokes one early.

Who may issue: a gateway key the user let issue keys (Key.Issues, magpie gateway-key issuer <id> on), from wherever it is let in, every key it issues bounded by it (access.IssueKey); or, with no key, a program on this computer over loopback that carries no browser's marks (profileRefused's rule), which may already use every model and could run magpie gateway-key itself. A page in a browser, another machine without such a key, a held or read-only key and an issued key never may.

View Source
const KindDesktopCheck = "connection_check"

KindDesktopCheck is the kind a Claude Desktop check (desktopProbe) is recorded with, so the Routing page and the ledger tell it from a turn.

View Source
const MCPCalledMethod = "magpie/toolCalled"

MCPCalledMethod is the JSON-RPC method the Magpie Image server an agent runs tells the gateway's image MCP server of a tool call it answered: MCPCalled, as params. It is answered with an empty result.

View Source
const MediaModelMethod = "magpie/media_model"

MediaModelMethod is the image MCP server's JSON-RPC method, not a tool, that the stdio Magpie Image server asks which model a call's model argument stands for: {"tool": …, "model": …} → {"model": provider/model}, or an error naming those it may be.

View Source
const OIDCKeysPath = KeysPath + "/oidc"

OIDCKeysPath trades an OIDC token for a short-lived gateway key (#4531): a GitHub Actions job asks GitHub for a token with the rule's audience and POSTs it here as Authorization: Bearer <token>, with no gateway key, and gets a key issued under the rule's gateway key (package oidc). The body is optional: {"ttl": "30m", "models": […]}, each no more than the rule and its key allow.

It is answered from another machine only while the gateway is shared, past the allow list, as every route is (lanGuard); a token that isn't let in counts against the failed authentications another machine may make (tooManyAuthFails), as a wrong key does.

View Source
const OwnMCPPath = "/v1/magpie/mcp"

OwnMCPPath lists the MCP servers magpie serves itself (web search, image recognition, image generation, the plugins' tools) that are on now, for an app that gives a model the Library's servers and wants magpie's own beside them: the community chat page (ferock on Discord), which read only library.json. A server is listed while an agent that mounts it would get its tools to work: the search while plugins/search serves and something searches (canSearch), image recognition while a model sees (seer: not Off in Settings), image generation while a model draws (drawer: not Off), the plugin tools while plugins/tools serves and a plugin that is on gives a tool. Each is named as its own initialize names it, with its path on this gateway; nothing in it is a secret.

View Source
const PagePortHeader = "X-Magpie-Page-Port"

PagePortHeader marks a request `magpie web`'s page port handed to the gateway (FromPagePort). The page's port is the one put behind a proxy or a forward, and a raw TCP forward (frp's tcp, ssh -R, socat) or a proxy that adds no forwarding header reaches it from loopback with nothing to tell it from an agent here. So no request through it is local: each is judged as one from another machine, answered only while magpie is shared and with an enabled gateway key, whatever peer, Host or browser marks it has, and MAGPIE_TRUST_PROXY doesn't change that (reported privately by Coffemon). Agents here call the gateway's own port, which needs no key from loopback, as before the page's port answered client routes. The header only ever takes a request's locality away, so one a client sends itself costs nobody else; lanGuard moves it into the request's context, so it never goes on upstream.

View Source
const PromptKept = promptBodies

PromptKept is how many requests' text the trace keeps.

View Source
const ReadOnlyCode = "gateway_key_read_only"

ReadOnlyCode is the error code a read-only key is refused a route with.

View Source
const RestartPath = "/v1/magpie/restart"

RestartPath is where `magpie update`, once it has put a new version in, asks the magpie serving the gateway to restart into it (gaubeebangeel on X: an agent served by magpie runs the update at 4am, and the app stayed on the old version until someone quit and reopened it, which cut whatever the agents had in flight). The app restarts the way its own update does: on a Mac or Linux it hands the gateway to the new version, so the request that ran the update, and every other, goes on. Loopback only, from a program, never a page.

View Source
const RouterAgent = "magpie-router/1"

RouterAgent is the User-Agent magpie's own classifier calls carry.

View Source
const ScienceID = "claude-science"

ScienceID is Claude Science's agent id.

View Source
const SearchAgent = "magpie-search/1"

SearchAgent is the User-Agent of the searches magpie makes for a model.

View Source
const SearchMCPPath = "/mcp/magpie/web-search"

SearchMCPPath is where the web search MCP server is served. It has two segments under /mcp/, so it can't hide a signed-in server's /mcp/{name}.

View Source
const SearchingHeader = "X-Magpie-Searching"

SearchingHeader marks a request a magpie made to search for another model, to a remote magpie, which then searches only by the model itself.

View Source
const SessionHeader = "X-Magpie-Session"

SessionHeader names the session a call is part of, for the usage log to tell several sessions on one model apart; without it, the session an agent names itself in sessionHeaders is taken.

View Source
const Token = "magpie"

Token is the bearer token agents are told to use. The gateway only listens on loopback and accepts anything, but agents insist on one.

View Source
const ToolsMCPOne = ToolsMCPPath + "/"

ToolsMCPOne is where one plugin's tools are served, each by its own name, the plugin's short name (ToolPrefix) after it: the address of the Library server magpie gives each plugin with tools (library/plugin_tools.go), so it can be switched on per agent and put behind the MCP hub like any other.

View Source
const ToolsMCPPath = "/mcp/magpie/tools"

ToolsMCPPath is where the plugin tools MCP server is served.

View Source
const VisionAgent = "magpie-vision/1"

VisionAgent is the User-Agent of the descriptions magpie asks for.

View Source
const VisionMCPPath = "/mcp/magpie/vision"

VisionMCPPath is where the image recognition MCP server is served.

Variables

View Source
var (
	ImageStall   = time.Minute
	ImageLongest = 5 * time.Minute
)

ImageStall is how long an image being downloaded may send nothing before the download is given up, and ImageLongest how long it may take in all at the least: as long as drawTimeout where Settings gives drawing longer, as a vendor slow to draw can be as slow to hand the image over. A slow download goes on while it moves: a 4K PNG is 10 MB and more, and a cap on the whole of it (generate_image's was 2 minutes) lost one that was still coming (#1576).

View Source
var ArchiveBucket func() (Putter, bool)

ArchiveBucket is the bucket the archive goes to, and false when there is none (sync is off, or to a WebDAV folder): set by main to the S3 sync's. With none, the archive is this computer's (archiveDest).

View Source
var ClassifierStandIn func(agent, model string) string

ClassifierStandIn is the model Claude Code's auto mode classifier goes to in place of the tier's it named, while that tier follows a main model /model has moved since magpie wrote it; "" leaves it as asked. Set by main (agent.ClassifierStandIn).

View Source
var CodexDesktopChanged func()

CodexDesktopChanged is called when the backend's list for the Codex app changed, for the file to be written again (agent.SyncCatalogSoon).

View Source
var CodexOwnOnly func() bool

CodexOwnOnly reports whether the Codex asking for its model list at CodexPath reaches magpie for account failover alone, not connected to it (agent.CodexOwnOnly): it is then handed only its own models (#1385). Set by main; nil, every Codex gets magpie's models too.

View Source
var CodexSideModel func() string

CodexSideModel is the model this machine's Codex is set to when it is one of magpie's, picked beside Codex's ChatGPT sign-in, "" otherwise (agent.CodexSideModel).

View Source
var CodexSideSet func(which string) bool

CodexSideSet says whether Codex's own config names the model for a side call ("memories": [memories] extract_model or consolidation_model), true when the config can't be read; nil leaves every such call as Codex sent it (agent.CodexSideSet).

View Source
var DesktopTierNames = []string{"opus", "sonnet", "haiku", "fable"}

Claude Desktop's Code tab runs Claude Code with ANTHROPIC_DEFAULT_<TIER>_MODEL set to "" for every tier, unless the gateway's /v1/models tags a model with anthropic_family_tier (shortnameIdentityOverrides in its app.asar, 2.7032: the first so tagged, or the one also is_family_default). Untagged, a subagent on "sonnet" or "haiku" asked for Claude Code's own claude-sonnet-… and that, unserved, went to the chat's model: every subagent ran on it, whatever its tier (WilianWeng on Discord). The user picks a model per tier in magpie; a tier with none picked runs on the chat's model, or, when the chat is on a Claude model, on its provider's model of that tier (servedBeside).

View Source
var ErrNotArchived = errors.New("not in the archive on this computer")

ErrNotArchived is a name the archive on this computer has nothing at.

View Source
var Handover bool

Handover lets another process listen on the same address beside this one, for `make dev`: a restarted backend takes the gateway's port up before the one before it lets go, and that one finishes the streams it has instead of cutting them. Set before ListenAndServe; off, a second magpie can't bind the port, which is how it learns one already serves.

View Source
var OnMasked func(maskrec.Record)

OnMasked is told of each request's record as masking makes it, for the notification that a value was masked (Must2333 on X); set by the app, nil (magpie serve, the CLI) for none. It is on the request's way, so it only takes the record: which of its values are new is asked later (maskrec.Fresh). The record holds no value and no text around one.

View Source
var OwnMCPServers = []struct{ Name, Path string }{
	{"image", ImageMCPPath},
	{"vision", VisionMCPPath},
	{"web-search", SearchMCPPath},
	{"tools", ToolsMCPPath},
}

OwnMCPServers are the MCP servers the gateway serves itself, by the names `magpie tools` lists their tools under, in the order a tool name two of them have is looked for.

View Source
var RunMCP func(w http.ResponseWriter, r *http.Request, name string)

RunMCP serves /mcp/run/<server>: a server magpie runs by its command, for an agent on this computer given it that way (library's ServeRun); nil until the library sets it.

View Source
var Serves = "app"

Serves says how this process was started (app, tray, web, serve or tui): the Routing page of another magpie on this computer, which shows this one's routing, names it (#2606). Set by the cli.

View Source
var StandIn func(agent, model string) string

StandIn is the model an agent is set to use in place of one it named that magpie doesn't serve it: Claude Code asks for claude-haiku-… by name for its small tasks, whatever its haiku tier is set to, and that goes to the tier's model rather than to some provider that happens to list the name. "" leaves the model as asked. Set by main.

View Source
var TurnDone func(TurnEnd)

TurnDone is told of each such turn; set by the app, which notifies. Nil (magpie serve, the CLI) has turns not followed at all.

View Source
var Version = "dev"

Version is set by main.

View Source
var WSLNets = wslNets

WSLNets are the networks Windows has an address on that WSL distros reach it through: the IPv4 addresses of the vEthernet (WSL) adapters (named "vEthernet (WSL)" or, with the Hyper-V firewall, "vEthernet (WSL (Hyper-V firewall))"), there while WSL's VM runs. None off Windows. A var for the tests.

View Source
var WhileServing []func(context.Context)

WhileServing is work only the magpie serving the gateway does, begun once it is bound and ended with it: one of the magpies running, never two at once.

View Source
var Window bool

Window says this process shows the routing of the gateway it serves: the app's window (a tray's too, when opened) or magpie web's page, and not magpie serve, which has none. Set by the gui.

Functions

func AdaptiveThinking added in v0.1.317

func AdaptiveThinking(model string) bool

AdaptiveThinking is adaptiveOnly for agents told how to ask a model: a Claude that takes thinking.type=adaptive and an effort, never a budget.

func AdaptiveWithEffort added in v0.1.1416

func AdaptiveWithEffort(model string) bool

AdaptiveWithEffort is, for agents told how to ask a model, one of effortInOutputConfig's that takes thinking adaptive with its level in output_config.effort: Z.ai's GLM-5.2 and GLM-5.3 (tried live on GLM-5.3, 10-24: max thought about three times high's). An agent whose budget can't say max (pi-ai clamps it to high's) asks them so. MiniMax's M3.1-Flash isn't, until it is tried (#3496).

func Addr

func Addr() string

Addr is the listen address: MAGPIE_ADDR, else Settings' port on loopback (settings.GatewayAddr).

func AllowGuard added in v0.1.1214

func AllowGuard(next http.Handler) http.Handler

AllowGuard refuses a request from an address the allow list leaves out, 403, before anything else looks at it: the page `magpie web` serves.

func AllowIPs added in v0.1.1214

func AllowIPs() (list []string, fromEnv bool)

AllowIPs is the allow list in force, as written, and whether MAGPIE_ALLOW_IPS set it. Empty: no list, every address let in.

func AllowedFrom added in v0.1.1214

func AllowedFrom(a netip.Addr) bool

AllowedFrom: a request from a may reach magpie under the allow list — there is none, a is this computer's, or a is in it.

func ArchiveError added in v0.1.577

func ArchiveError() (string, time.Time)

ArchiveError is the last upload's failure, and when; "" once one after it went.

func ArchiveName added in v0.1.577

func ArchiveName(date, id string) (string, bool)

ArchiveName is where the archive keeps the call named "<date>/<id>", under the bucket's magpie folder; false for a name not of that shape, which is never one magpie made.

func AutoDrawer added in v0.1.338

func AutoDrawer() string

AutoDrawer is the model magpie draws with when the Settings name none: a ChatGPT account's, which its plan pays for, else the cheapest of the models the API keys set up can draw with, the newest of those whose price isn't known. "" when none can.

func AutoModeReviewable added in v0.1.1320

func AutoModeReviewable(p provider.Provider, model string) bool

AutoModeReviewable reports whether Claude Code, asking for model at p through magpie, can have its actions reviewed: AutoModeReviewed, on a route that reaches the Messages API. A Claude model p serves only on Chat or Responses (a relay with no Anthropic endpoint, or one the user set to be asked on another API) is asked translated, and a translation carries neither the safeguards nor their results (nexnull on Discord). The agent's wiring asks this before a request is made; serverReview, on the Messages route already, asks AutoModeReviewed.

func AutoModeReviewed added in v0.1.1213

func AutoModeReviewed(p provider.Provider, model string) bool

AutoModeReviewed reports whether a request for model on p can have its actions reviewed by Anthropic for Claude Code's auto mode: the Claude subscription (the bridge hands the review to Claude Code's own binary), a Claude model (Anthropic's API, a relay in front of it, Bedrock's or Vertex's names for it), or anything on Anthropic's own API. No other vendor runs Anthropic's classifier, and magpie answers none on its behalf: another subscription's or a plugin's Claude model (Copilot, Kiro, Cursor…) is that vendor's service, which turns the safeguards away (#1756) or drops them, so it isn't reviewed by its name alone.

func AutoSearcher added in v0.1.672

func AutoSearcher() string

AutoSearcher names the provider and model magpie picks to search with when Settings names none, "" when none can.

func AutoVideomaker added in v0.1.544

func AutoVideomaker() string

AutoVideomaker is the model a request that names none makes its video with: the first model of the first provider that makes any. "" when none can. A MiniMax API key's H3 comes after every other: it is paid by the second from the key's balance, and a key set up for chat would otherwise take videos a subscription made before.

func AutoVision added in v0.1.333

func AutoVision() string

AutoVision is the model magpie picks to describe images when the Settings name none: a small model that sees, of the models the user enabled on the providers switched on (smallModel) — a Claude account's, a Codex account's, the cheapest of an API key's, another account's. One with allowance left goes before one whose every account or key is out of it (smallReady), whatever their order: the one out is picked only when every model that sees is, so that agents are still told images are described (provider.Described), and askVisionWith says when it is back instead of asking (#1801). "" when no model sees.

func ByStrength added in v0.1.783

func ByStrength(efforts []string) []string

ByStrength is efforts weakest first, in effortRank's order; a level it doesn't know keeps its place among the others of its kind, after them.

func CanReadSearchQuota added in v0.1.1231

func CanReadSearchQuota(a provider.SearchAPI) bool

CanReadSearchQuota is whether magpie can read what a search API's keys have left: Tavily's, with a key.

func CanSearch added in v0.1.1045

func CanSearch() bool

CanSearch is canSearch for the agents' rows: whether a web_search server tool asked of any model here is answered.

func CheckTLS added in v0.1.1232

func CheckTLS() error

CheckTLS says why the files set can't be served: only one of the two, or a pair that doesn't load. nil with neither set.

func ClassifierFailure added in v0.1.1226

func ClassifierFailure(model string) (why string, at time.Time, ok bool)

ClassifierFailure is why model, a routing group's classifier, couldn't say which intent or effort a turn is the last time it was asked, and when; ok is false once it answers, and before it is asked. The Routing page says it on the group's card (#1929, versun): a classifier that fails at every turn otherwise only showed in each request's own details, while its group's rules with an intent quietly never matched.

func ClaudeMemRuns added in v0.1.1298

func ClaudeMemRuns() (int, string)

ClaudeMemRuns is how many Claude Code processes this machine's memory holds, and why; 0 when not bounded by it (`magpie claude-code runs`).

func ClientPath added in v0.1.1444

func ClientPath(p string) bool

ClientPath: p is one of the gateway's client routes, which `magpie web` answers on its own port too by handing it to the gateway, so one address (one reverse-proxy location) serves the page and the agents (zgcwkj on Discord). The page's own routes keep its key: /api/* is the page's, so the Ollama and Claude Desktop routes there, and the Claude helper's callbacks under /_magpie/, stay on the gateway's port alone. A path that isn't clean (a "..", a "//") is none, and stays behind the page's key.

func CodexDesktopCatalog added in v0.1.1728

func CodexDesktopCatalog() (b []byte, ok bool)

CodexDesktopCatalog is the list a Codex beside its ChatGPT sign-in is handed (/backend-api/codex/models), as a file Codex reads with model_catalog_json: the backend's entries as it sent them, narrowed and set as the codex provider has them, magpie's after them. ok is false while the backend's list is not known: none asked for yet, or none it gave. That is unknown, never an empty list, and the file as it was stands. The backend is asked again in the background when its list is old, CodexDesktopChanged told when it changed.

A sign-in the backend calls revoked, with no list of its from before, is handed Codex's last list of its own and magpie's models, as codexModels answers Codex then (#4308): the backend has said all it will for that sign-in, and without it the app's picker had none of magpie's models until the user signed in again.

func CodexRelay added in v0.1.2030

func CodexRelay() http.Handler

CodexRelay is what serves Codex's own ChatGPT sign-in at the gateway's address once magpie has quit, for the Codex threads still open then (codexrelay). magpie takes the failover base URL out of Codex's config at quit (agent.EndCodexFailover), but a thread open in the Codex app, and the app-server holding it, keep the URL they started with: every turn after went to a port nobody listened on, and a system proxy in between answered 503 "Unknown error" until magpie was opened again (idkatbro on X). The relay passes those turns on to the ChatGPT backend as the gateway does a turn on one of Codex's own models, signed by the caller's own Authorization; it adds no credential of its own. What only the running magpie could do is refused with a reason Codex shows: a magpie model, a turn on one of magpie's accounts, masking (Settings › Privacy) that would have masked it. Its answer at "/" never says it is magpie (ServedBy), so the next magpie starting asks it to leave.

func ContainerAddrs added in v0.1.553

func ContainerAddrs() bool

ContainerAddrs: the addresses magpie finds for itself are a container's, which other machines can't reach, and MAGPIE_PUBLIC_URL doesn't say the host's.

func DayTallies added in v0.1.2322

func DayTallies() map[string]Tally

DayTallies counts today's history per account or key, the Usage page's own source. The counts ride on the history read the live page already asks for, every 15s while it is open, so each look folds in only the lines added to today's files since the last: a busy day's file is hundreds of MB (#3383), read whole once at most. What it returns is a copy, written out after the lock is let go.

func DesktopCatalogID added in v0.1.685

func DesktopCatalogID(id string) string

DesktopCatalogID is the catalog id of a model as Claude Desktop names it: one of its aliases or the catalog id itself.

func DesktopID added in v0.1.592

func DesktopID(e provider.Entry) string

DesktopID is the id Claude Desktop is shown e by, and its Code tab hands Claude Code (claudeLooking).

func DesktopListed1M added in v0.1.1154

func DesktopListed1M(e provider.Entry) bool

DesktopListed1M says Claude Desktop is shown e by its "[1m]" id, which its Code tab hands Claude Code, so a session on it has the 1M window.

func DesktopNumber added in v0.1.1280

func DesktopNumber(e provider.Entry) string

DesktopNumber is the number Claude Desktop's menu says beside e, so the Providers page can say it too and a row of that menu be matched to its provider (#2578): "" for every model Desktop names by our display_name, which carries the provider already. Only a Claude model with reasoning levels, listed as magpie-<number>.anthropic.<model> (claudeLooking), is named after Desktop's own catalog ("Opus 5.5"), so two providers' rows read alike and the menu tells them apart by that id. Every other id is the model's own (no number) or an alias Desktop doesn't know (mythos-magpie-<n>, anthropic/magpie-<n>), named by display_name.

func DesktopTiers added in v0.1.685

func DesktopTiers() map[string]string

DesktopTiers is the catalog id picked for each of Claude Desktop's tiers.

func Drawer added in v0.1.1119

func Drawer() string

Drawer is the model a request that names none draws with (drawer), as provider/model: "" when image generation is off or no provider draws.

func DrawerHidden added in v0.1.2016

func DrawerHidden(ref string) bool

DrawerHidden is whether ref (provider/model), a model Settings › Images names, is one the user unticked in its provider's editor: it still draws, and the Settings row says it is hidden. A ChatGPT account's other GPT Image names stand for its one (ListedDrawer).

func DrawerMissing added in v0.1.1118

func DrawerMissing() string

DrawerMissing is the model Settings › Models › Image generation names when magpie can't find it any more, so that AutoDrawer's draws in its place, as VisionMissing is Image recognition's. "" when none is named, it is off, or it resolves.

func Drawers added in v0.1.338

func Drawers(p provider.Provider) []catalog.Model

Drawers are the models a provider can draw with: its catalogs' models that make images, those its own model list names that do, those of its own picks named for images, and those the user said draw (#1399), less those they said make videos; a ChatGPT account's GPT Image, a Grok subscription's Grok Imagine, a WorkBuddy plan's those its config lists.

func DrawersOf added in v0.1.2481

func DrawersOf(p provider.Provider, avail func() []catalog.Model) []catalog.Model

DrawersOf is Drawers with p's model list from avail, called only when it is wanted: the Providers page has each provider's list at hand, and reading it again for each was 15 MB of what twenty window polls allocated. What avail gives is only read.

func FetchImage added in v0.1.1184

func FetchImage(ctx context.Context, c *http.Client, url string) ([]byte, string, error)

FetchImage downloads the image at url with c: its bytes, and its type — what the bytes are, over what the server says. It gives up when nothing comes for ImageStall or it has taken imageLongest, and says which, and how much had come.

func FlushSticks added in v0.1.1291

func FlushSticks()

FlushSticks is flushSticks, for magpie ending on a signal before the gateway's own end.

func ForwardCallbacks added in v0.1.1354

func ForwardCallbacks(sock string)

ForwardCallbacks has a tool call for a Claude Code run this process doesn't know passed on to sock, where the magpie it took the gateway over from answers those of its own runs (ServeCallbacks): a turn under way there when the gateway changed hands still gets its tool results. "" stops it.

func FromPagePort added in v0.1.1695

func FromPagePort(r *http.Request) *http.Request

FromPagePort is r marked as handed over by the page's port: for the gateway this process serves (Front), or the header toGateway passes on.

func GroupClassifierFailure added in v0.1.2083

func GroupClassifierFailure(group, model string) (why string, at time.Time, ok bool)

GroupClassifierFailure is why group's classifier, model, couldn't say which intent or effort a turn of that group's was, the last time the group asked it, and when; ok is false once it answers the group, before the group asks it, and after the group's classifier changed. The Routing page says it on that group's card alone: keyed by the classifier, a group no request reached showed the failures of another group that shares its classifier, as though its own turns were being judged (jjt on Discord: "claude难易", not in use, said Claude Haiku's weekly limit).

func GroupDraws added in v0.1.2016

func GroupDraws(ref string) bool

GroupDraws is whether the routing group ref ("group/<id>") has a member that draws: a model among its provider's Drawers. Such a group may be picked in Settings › Images, and draws on those members in its routing's order, moving on while one fails (drawingGroup, #2005).

func HeldDir added in v0.1.2005

func HeldDir() string

HeldDir is the folder the reports of held requests are saved in.

func HeldReport added in v0.1.2005

func HeldReport(name string) (string, error)

HeldReport is the saved report named name, for the Routing page; a name that isn't a report's is refused, so nothing else in the folder or out of it is read.

func History added in v0.1.341

func History(day string) (days []HistoryDay, routes []Route, cut bool)

History is the days kept, newest first, and the routes of day, oldest first — its latest historyMax, and whether there were more.

func HistoryDir added in v0.1.341

func HistoryDir() string

HistoryDir is where the days are kept: ~/.config/magpie/routing.

func HostName added in v0.1.2573

func HostName() string

HostName is this computer's name, what the router says of itself to an agent on another computer when the user set no words of their own.

func HubLine added in v0.1.2612

func HubLine(ss []HubServer) string

HubLine is one line naming the servers behind the hub, each with what it is for cut to fit hubLineMax: "" when there is none.

func ImageToolProps added in v0.1.1461

func ImageToolProps(images string) map[string]any

ImageToolProps is generate_image's arguments but where to save: images says how an image to draw from may be given.

func InContainer added in v0.1.1132

func InContainer() bool

InContainer: this magpie runs in a container (Docker, Podman, a Kubernetes pod), whose image is what gets updated, not its binary.

func Inherit added in v0.1.1354

func Inherit(ln net.Listener, ack func())

Inherit has this process's gateway serve on ln, the socket the magpie it replaces listened on, rather than listening itself; ack is called once it serves.

func Inherited added in v0.1.1354

func Inherited() bool

Inherited is whether a listener handed over is waiting to be served: the gateway's port is then held by the magpie that handed it over, and is this process's to serve all the same.

func KeepsOut added in v0.1.1214

func KeepsOut(list []string, r *http.Request) (string, bool)

KeepsOut: the allow list list would refuse r, a request that came in from elsewhere; it names r's address.

func LANHosts added in v0.1.1892

func LANHosts() []string

LANHosts are this computer's IPv4 addresses other machines can reach it at, on every interface that is up: a private one, and a public one an ISP assigns to the network card itself. The gateway's addresses and `magpie web`'s links are both made from these, so the two list the same computer the same way (a static public address was in one and not the other). Private ones come first: in the interfaces' order the public one came first, and Settings offered it as the address under "Share on local network" (the same user, asking why sharing was on the internet). Of the private ones, RFC 1918's (a home or office network) come before carrier-grade NAT's (Tailscale). A proxy's TUN address is left out: 198.18.0.0/15 (netguard.FakeIP), which Clash, Mihomo, sing-box, Surge and Stash take for their TUN interfaces and fake-ip answers, and which no network hands out: no other device reaches this computer there, and Settings offered http://198.18.0.1 instead of 192.168.110.x (coeo91 on Discord). It goes by the address, not the interface's name: Tailscale's is a utun too, and its address is reached.

func LANURLs added in v0.1.168

func LANURLs() []string

LANURLs are the addresses other machines on the network reach the gateway at: MAGPIE_PUBLIC_URL when set, else one per IPv4 address this computer has there.

func ListedDrawer added in v0.1.1217

func ListedDrawer(ref string) string

ListedDrawer is the listed image model a picked one (provider/model) stands for: a ChatGPT account's gpt-image-2.5, or any other GPT Image name, is its one GPT Image, as its backend draws the same for any name (#1865). ref itself otherwise, and when its provider isn't found. The pick itself is kept as it was saved, and draws as before.

func Listen added in v0.1.291

func Listen(addr string) (net.Listener, error)

Listen listens on addr, beside another process when Handover is on; or takes the socket the magpie before this one handed over (Inherit) when it listens there.

func LocalArchiveCap added in v0.1.1401

func LocalArchiveCap() int64

LocalArchiveCap is how large the archive on this computer grows, in bytes: settings' RequestArchiveLocalMB, a GiB unless set.

func MaskRoute added in v0.1.2089

func MaskRoute(id string) bool

MaskRoute says id may be the model an agent's request goes to as written when masking would change it (settings.RedactRouteTo): it resolves, is on, holds a conversation, and every place it can go is one the user set to go unmasked (unredactedRoute), its fallbacks and a group's members too, so nothing of it reaches a vendor.

func ModelEfforts added in v0.1.1226

func ModelEfforts(model string) []string

ModelEfforts are the reasoning levels model ("<provider>/<model>") has, weakest first, for Settings to offer beside it; none for one whose levels aren't known, or a routing group.

func NamedSearchModel added in v0.1.1213

func NamedSearchModel() string

NamedSearchModel is the model the searcher Settings names searches with, as "<provider>/<model>": what an agent's own web search row asks, so a search goes to the searcher the user picked rather than first to the agent's model (dsh, 我只会玩单机 on Discord). "" when Settings names none, provider search is off, the one named can't be used, or it searches with no model (a Kimi Code plan's search service).

func OfferedDrawers added in v0.1.2016

func OfferedDrawers(p provider.Provider) []catalog.Model

OfferedDrawers are Drawers less those the user unticked in p's editor (provider.HiddenDrawers, 321sssrt on X): the image models a list offers to pick from and Automatic picks among. A request that names a hidden one still draws with it (resolveDrawing reads Drawers), as does a Settings › Images pick of one made before it was hidden.

func OnNetwork added in v0.1.1151

func OnNetwork() bool

OnNetwork: MAGPIE_ADDR puts the gateway beyond loopback (0.0.0.0 in the Docker image, a server's or one interface's address), so it is reached from other machines, and from a container's host, whether or not it is shared from Settings. Such callers need an enabled gateway key, as they do while it is shared: nothing that reaches it from elsewhere is let in on any key.

func OnWSLNet added in v0.1.1483

func OnWSLNet(base string) bool

OnWSLNet says base (an agent's gateway URL) names an address Windows has on a WSL network: where a distro under NAT reaches the gateway.

func OwnUnready added in v0.1.2550

func OwnUnready(name string) string

OwnUnready is why magpie's own server name (Magpie Web Search, Magpie Image Recognition, Magpie Image) can't answer yet, in English for the Library's Discover to say on its row: "" while ownMCP lists it, and for any other name. Its tools answer all the same, with how to set it up (matrix0487 on Discord: all three in Discover, never a dead tool).

func OwnerLanes added in v0.1.1294

func OwnerLanes() (map[string]Lane, bool)

OwnerLanes reads the lanes of the magpie serving the gateway's address, for a console that doesn't serve it (the providers' rows show the same pills wherever the gateway runs). ok is false when nothing answers there. It is asked on every state read, so it waits no longer than ServedBy does.

func PluginToolsOf added in v0.1.2222

func PluginToolsOf(ctx context.Context, name string) ([]plugin.Tool, error)

PluginToolsOf are the tools of the plugin called name (plugin.Name of its spec) while it is on and Plugin tools is served: what the MCP hub lists for its Library server.

func Port added in v0.1.168

func Port() string

Port is the gateway's port.

func PublicClient added in v0.1.1272

func PublicClient() *http.Client

PublicClient is publicClient, for a download outside the gateway of a URL magpie didn't choose (generate_image's of a vendor's image).

func PublicHost added in v0.1.553

func PublicHost() string

PublicHost is MAGPIE_PUBLIC_URL's host, "" when it isn't set.

func PublicIP added in v0.1.1908

func PublicIP(ip net.IP) bool

PublicIP: ip is an internet address, which any computer online may reach, not one on a private network.

func PublicURL added in v0.1.591

func PublicURL() string

PublicURL is MAGPIE_PUBLIC_URL, with a scheme; "" when it isn't set.

func PublicURLs added in v0.1.1908

func PublicURLs(urls []string) []string

PublicURLs are those of urls (LANURLs) at an internet address.

func RelaysSaidToSearch added in v0.1.672

func RelaysSaidToSearch() []provider.Provider

RelaysSaidToSearch are the providers on that are said to search by themselves but are not asked for another model unless Settings names them (#359).

func ResultToolProps added in v0.1.1461

func ResultToolProps() map[string]any

ResultToolProps is generation_result's arguments.

func RunPluginToolOf added in v0.1.2222

func RunPluginToolOf(ctx context.Context, name, tool string, args json.RawMessage, agent string) (string, error)

RunPluginToolOf runs tool of the plugin called name for agent, as the MCP hub calls it: the text it answered, or why it couldn't run. The hub has held the call to the caller's key limit already.

func Running

func Running() bool

Running reports whether a gateway answers at the address.

func SavedURL added in v0.1.950

func SavedURL() string

SavedURL is URL by Settings alone, MAGPIE_ADDR left aside: where the installed magpie, whose settings these are, is reached.

func Scheme added in v0.1.1232

func Scheme() string

Scheme is the gateway's scheme for other computers: https with TLS on.

func SearchEffortNow added in v0.1.1226

func SearchEffortNow() string

SearchEffortNow is the level the searcher in use is asked at, when one is picked in Settings.

func SearchEfforts added in v0.1.1226

func SearchEfforts() []string

SearchEfforts are the levels of the model that searches now: none for a Kimi Code plan's search service, which has no model.

func Searcher added in v0.1.587

func Searcher() string

Searcher names the provider and model magpie searches with for a model that can't, "" when none can.

func SearcherUnused added in v0.1.672

func SearcherUnused() string

SearcherUnused is why the searcher Settings names isn't used (one of the Searcher* reasons), "" when it is or none is named.

func ServeTLS added in v0.1.1232

func ServeTLS(ln net.Listener) (net.Listener, error)

ServeTLS wraps ln to serve TLS, with plain HTTP for this computer's own connections, when the files are set; ln as it is otherwise.

func ServedBusy added in v0.1.2529

func ServedBusy() (n int, ok bool)

ServedBusy is what the magpie serving the gateway has in flight, as its /v1/magpie/concurrency tells it: agent requests (those waiting for a slot among them) and Claude Code turns waiting on their caller's tools. ok is false when it doesn't say (a magpie from before 3b6ca0557, a refusal, no answer in time): unknown, which is never idle.

func Serving added in v0.1.191

func Serving() (running, window bool)

Serving asks the address what answers there: whether a magpie gateway does, and whether the magpie serving it has a window its routing can be watched in (#110).

func SetDesktopTier added in v0.1.685

func SetDesktopTier(tier, id string) error

SetDesktopTier picks the model (a catalog id) Claude Desktop runs a tier on; "" takes the pick away.

func SetRestarter added in v0.1.2323

func SetRestarter(f func(version string) RestartReply)

SetRestarter has RestartPath call f with the version `magpie update` put in; the gui's updater sets it. Without one the answer is "unsupported".

func SetTLS added in v0.1.1232

func SetTLS(cert, key string) error

SetTLS sets the files the flags name, as absolute paths (a service starts in another folder), after checking them as CheckTLS does.

func StopHub added in v0.1.1950

func StopHub()

StopHub ends the servers the hub started: magpie is stopping.

func TLSFiles added in v0.1.1232

func TLSFiles() (cert, key string)

TLSFiles are the certificate and key files set, "" for none.

func TLSOn added in v0.1.1232

func TLSOn() bool

TLSOn: the gateway serves other computers over HTTPS.

func TLSSummary added in v0.1.1232

func TLSSummary() string

TLSSummary says what the certificate served now is for and until when, for the serve banner: "" with TLS off or a pair that doesn't load.

func Taken added in v0.1.1231

func Taken() bool

Taken reports whether anything accepts connections at the gateway's address, whether or not it answers ServedBy's question in time: a magpie busy starting, or slow on a small server, still holds the port.

func ThinkingBudget added in v0.1.2520

func ThinkingBudget(effort string) int

ThinkingBudget is the Anthropic thinking budget the gateway reads an effort level as, for an agent's config that has to name one (ZCode's).

func ThinksOnlyWhenAsked added in v0.1.771

func ThinksOnlyWhenAsked(model string) bool

ThinksOnlyWhenAsked is a model that takes thinking turned off on the Messages API whatever its levels: one of Anthropic's own (anthropicModel, or a relay's opus-5.5). Another vendor's model there takes it off only when none is among its levels; without it, it always thinks, and GLM-5.3 turns thinking disabled away (#699).

func TokenFor added in v0.1.174

func TokenFor(agent string) string

TokenFor is the token an agent that says nothing of itself in its User-Agent is told to use, so the gateway still knows it: Alma's requests go out as the AI SDK's ("ai-sdk/openai/…"), with nothing of Alma's own.

func ToolNames added in v0.1.1257

func ToolNames(pts []plugin.PluginTools) map[string]map[string]string

ToolNames are the names the plugin tools MCP server gives pts' tools, by spec and the tool's own name, as the Plugins page shows them.

func ToolPrefix added in v0.1.2222

func ToolPrefix(spec string) string

ToolPrefix is the name a plugin's tools are under: its short name, in the characters MCP clients take.

func TurnFolder added in v0.1.1191

func TurnFolder(dir string) string

TurnFolder is the last part of a folder, for a notification.

func URL

func URL() string

URL is the base URL agents use, e.g. http://127.0.0.1:3425: a gateway listening on every interface is reached here on loopback.

func VendorPicksDrawer added in v0.1.1217

func VendorPicksDrawer(p provider.Provider) bool

VendorPicksDrawer is whether p's vendor picks the image model itself, whichever is named: a ChatGPT account's images backend (#1865).

func VideoToolProps added in v0.1.1461

func VideoToolProps(image, images string) map[string]any

VideoToolProps is generate_video's arguments but where to save: image says how the image to animate may be given, images how those its subjects are drawn from may.

func Videomakers added in v0.1.544

func Videomakers(p provider.Provider) []catalog.Model

Videomakers are the models a provider can make videos with: a Grok subscription's, another magpie's, a preset plan's models when magpie implements that vendor's video API, a MiniMax API key's H3 models (video_minimax.go), and those a provider's own model list marks as video models (customVideomakers).

func VisionEffortNow added in v0.1.1226

func VisionEffortNow() string

VisionEffortNow is the level the Image recognition model in use is asked at when one is picked in Settings ("" when none is): the picked one fitted to the model's levels, for the row to show.

func VisionEfforts added in v0.1.1226

func VisionEfforts() []string

VisionEfforts are the levels of the model that describes images now.

func VisionMissing added in v0.1.1118

func VisionMissing() string

VisionMissing is the model Settings › Models › Image recognition names when magpie can't find it any more, so that AutoVision's describes in its place. "" when none is named, Vision is off, or it resolves.

func WSLKey added in v0.1.1483

func WSLKey() string

WSLKey is the key magpie gives the agents of a WSL distro that reaches the gateway on the WSL network (OnWSLNet): made once, kept in magpie's folder, readable by this user only. "" when it can't be read or made, and the agent is given the gateway's token as before.

func WSLKeyMade added in v0.1.1483

func WSLKeyMade() string

WSLKeyMade is the WSL key when one was made, "" when not: for telling whether a key is it without making one.

func WithHubCaller added in v0.1.2263

func WithHubCaller(ctx context.Context, c HubCaller) context.Context

WithHubCaller is ctx carrying caller c.

Types

type Active added in v0.1.1241

type Active struct {
	ID       int64     `json:"id"`
	Agent    string    `json:"agent"`
	Model    string    `json:"model,omitempty"`
	Provider string    `json:"provider,omitempty"`
	Session  string    `json:"session,omitempty"`
	Started  time.Time `json:"started"`
	Millis   int64     `json:"ms"`
	Phase    string    `json:"phase,omitempty"`
	Route    int64     `json:"route,omitempty"` // its routing trace's id
}

Active is one agent request in flight, as /v1/magpie/concurrency lists it for a status bar's hover (#2132, bigbitbox): which agent asked, for which model, since when, and where it stands. It holds no prompt, reply or key. Model and Provider are the routing trace's, once the request has been routed; Phase is said only when the gateway knows it: "slot" while it waits in a key's or account's queue (MaxConcurrency), "rpm" while it waits for room in the minute (MaxRPM), "upstream" while a try is out at the vendor (the request sent, or its reply streaming), "redact" while it is masked (noteRedacting: the rules, and the local model with its wait for a turn). A request served another way (a subscription bridge, a title helper) has none.

type Affinity added in v0.1.38

type Affinity struct {
	Mode       string    `json:"mode"`             // the provider's or group's: "", session, turn, off
	Turn       int       `json:"turn"`             // the user's turns in the conversation so far
	Within     bool      `json:"within,omitempty"` // the agent sending tool results back: mid-turn
	Last       string    `json:"last,omitempty"`   // who answered the conversation last
	LastTurn   int       `json:"lastTurn,omitempty"`
	At         time.Time `json:"at,omitempty"`         // when
	CacheRead  int       `json:"cacheRead,omitempty"`  // tokens that answer read from the vendor's cache
	CacheWrite int       `json:"cacheWrite,omitempty"` // and wrote to it, or was sent where none is
	Kept       bool      `json:"kept,omitempty"`       // Last was put first for it
	// Why it was kept — "session", "turn", "cache" — or not: "off", "first"
	// (nobody has answered it yet), "new-turn", "no-cache" (the vendor
	// read and wrote too little of its cache to keep, or was sent too
	// little for a cache it keeps without saying so), "cold" (too long
	// ago), "resting", "spent", "gone" (no longer one to route to),
	// "main" (a provider's fallback answered it, and the provider's own
	// model is ready again: backToMain), "order" (a later member of a
	// group routed In order answered it, and a member ahead is ready
	// again at a new turn: backToFirst), "back" (a member of a group
	// routed any other way stood in for one listed ahead of it that
	// couldn't take the conversation, and a member ahead is ready first
	// at a new turn: backFromStandIn), "credits" (a Codex account gone
	// onto its credits answered it, set to spend them only after
	// everything else, and one not on its credits leads: lastBehind),
	// "busy" (its plugin says the model is busier than settings.BusyLoad
	// and one that isn't leads, at a new turn: busyBehind),
	// "strict" (Stays: Strict, kept whatever it is).
	Why string `json:"why"`
	// Main is, for a conversation kept strictly on a provider's fallback,
	// the provider's own key or account that is ready again: it would have
	// gone back to it ("main") but for Stays: Strict, which the Routing
	// page says.
	Main *Weighed `json:"main,omitempty"`
}

Affinity is what the trace tells of a request's conversation and whether it stayed with who answered it last.

type ArchivePart added in v0.1.577

type ArchivePart struct {
	Method  string              `json:"method,omitempty"`
	Path    string              `json:"path,omitempty"`
	Status  int                 `json:"status,omitempty"`
	Headers map[string][]string `json:"headers"`
	Body    string              `json:"body"`
	// Size is the whole body's, in bytes, as the gateway had it, before
	// its secrets were taken out; none in an archive from before #447
	Size int64 `json:"size,omitempty"`
	// Truncated: only the start of the body is kept — its first
	// RequestArchiveMaxMB, or, in an archive from before #447 (no Size),
	// its first 256 KB
	Truncated bool `json:"truncated,omitempty"`
}

ArchivePart is one way of a call: the request, or the response.

type Archived added in v0.1.577

type Archived struct {
	ID       string      `json:"id"`   // <date>/<id>
	Call     Call        `json:"call"` // as Recent calls has it, its bodies below
	Request  ArchivePart `json:"request"`
	Response ArchivePart `json:"response"`
}

Archived is a call as the archive keeps it.

type AutoReset added in v0.1.507

type AutoReset struct {
	Who   string `json:"who"`
	Text  string `json:"text"`
	Agent string `json:"agent,omitempty"` // the account's agent, as Account.Agent has it
}

AutoReset is a Codex reset spent by itself, on Who's account. (Claude's resets were taken out in 9bf6d4352 and aren't coming back: reading or spending one means magpie calling Anthropic with the account's token, #1972.)

type Busy added in v0.1.672

type Busy struct {
	Requests   int       `json:"requests"`
	Tools      int       `json:"tools"`
	Last       time.Time `json:"-"`
	Bridge     int       `json:"-"`
	BridgeLast time.Time `json:"-"`
}

Busy is what a restart of the magpie serving the gateway would cut short (#577): the agents' requests in flight — a reply streaming, an image being made — and the turns of Claude Code run through the subscription bridge waiting on their caller's tool results, whose Claude Code lives only in this process. A request in flight is one that does work (not a GET: the model lists, the info another magpie asks for every 15 s); the bridge's own helper calls are not counted apart, a turn waiting on them being in Tools. Last is when the last counted request ended, so a caller can tell a tool chain's gap — the agent running a tool between two requests — from the end of its turn.

Bridge and BridgeLast are the same for the bridge's turns alone, which a restart that hands the gateway over (handover.go) still waits for: their Claude Code lives in this process, and only here can the turn go on. Every other request finishes in the magpie that hands over while the new one takes the next.

func (Busy) Any added in v0.1.672

func (b Busy) Any() bool

Any is whether there is anything in flight.

type CPUStats added in v0.1.1280

type CPUStats struct {
	PID        int     `json:"pid"`
	Program    string  `json:"program"`
	Version    string  `json:"version"`
	Window     bool    `json:"window"` // the app's window or magpie web serves the gateway
	Uptime     string  `json:"uptime"`
	Seconds    float64 `json:"seconds"` // how long the profile recorded
	CPUKnown   bool    `json:"cpuKnown"`
	CPU        float64 `json:"cpu"`      // seconds of CPU used while recording
	CPUTotal   float64 `json:"cpuTotal"` // seconds of CPU used since the process started
	Goroutines int     `json:"goroutines"`
	NumCPU     int     `json:"numCPU"`
	GOMAXPROCS int     `json:"gomaxprocs"`
}

CPUStats is what the process used while the profile recorded. CPU is the process's own user and system time over those seconds, as the system counts it (all its threads, Go's or not), and CPUTotal since it started; both are 0 with CPUKnown false where the system doesn't say.

type Call

type Call struct {
	// ID numbers the call in the Recent-calls ring, from 1, for the page
	// to ask for its bodies by (the ring's summary leaves them out, #1521)
	ID uint64 `json:"id,omitempty"`
	// Route: the Routing page's request (Route.ID) this call is, for it
	// to ask for the call's bodies by while the ring still has them
	Route int64     `json:"route,omitempty"`
	Time  time.Time `json:"time"`
	Agent string    `json:"agent"`         // who called, from the client's User-Agent
	Via   string    `json:"via,omitempty"` // the computer a remote magpie's request came from (AgentHeader)
	// Kind: what the agent made the call for, when it isn't its turn —
	// a Codex subagent's (callKind) — "" for a turn
	Kind string `json:"kind,omitempty"`
	// For: the request a call of magpie's own (a web search) was made for
	For *CallFor `json:"for,omitempty"`
	// Masked: what masking swapped in it, nil for nothing
	Masked   *Masked           `json:"masked,omitempty"`
	Model    string            `json:"model"`
	Provider string            `json:"provider"`
	From     provider.Protocol `json:"from"`
	To       provider.Protocol `json:"to"`
	Status   int               `json:"status"`
	Millis   int64             `json:"ms"`
	// TTFT: ms from the request to its reply's first content — text,
	// reasoning or a tool call — and FirstText to its first text, when
	// it was streamed (#196)
	TTFT      int64 `json:"ttft,omitempty"`
	FirstText int64 `json:"firstText,omitempty"`
	// FirstReasoning is the start of paced visible reasoning, absent for hidden reasoning.
	FirstReasoning  int64 `json:"firstReasoning,omitempty"`
	ReasoningHidden bool  `json:"reasoningHidden,omitempty"`
	// Flow: the ms its content took to come, from where its speed is
	// counted (firstToken.flowMs): next to none for a reply that came in
	// a burst, so it tells no speed
	Flow              int64  `json:"flow,omitempty"`
	Error             string `json:"error,omitempty"`
	Fallback          string `json:"fallback,omitempty"` // providers that failed first, and why
	Usage             Usage  `json:"usage"`
	RequestBody       string `json:"requestBody,omitempty"`
	ResponseBody      string `json:"responseBody,omitempty"`
	RequestTruncated  bool   `json:"requestTruncated,omitempty"`
	ResponseTruncated bool   `json:"responseTruncated,omitempty"`
	// Archive: "<date>/<id>", where the request archive keeps the call,
	// when it was on (archive.go); wire what it keeps besides
	Archive string `json:"archive,omitempty"`
	// contains filtered or unexported fields
}

Call is one request the gateway handled, for the status views.

type CallFor added in v0.1.490

type CallFor struct {
	Agent string `json:"agent"`
	Model string `json:"model"`
	// Unknown, on an image's description, is that the model was counted
	// text-only because nothing magpie knows says whether it sees images
	// (blindTo), not because its list or the user says it takes text only.
	// The Routing view says which, so a user whose model does see knows
	// to say so (#1287).
	Unknown bool `json:"unknown,omitempty"`
	// Missing, on an image's description, is the Image recognition model
	// the user picked in Settings that magpie can't find any more: the
	// model that described is the one magpie picks in its place
	// (VisionMissing), and the Routing view names both.
	Missing string `json:"missing,omitempty"`
	// MCP, on a web search or an image's description, is that the agent
	// called magpie's MCP server (SearchMCPPath, VisionMCPPath) itself, for
	// no model of magpie's.
	MCP bool `json:"mcp,omitempty"`
	// Instead, on a web search, is the searcher asked first that failed
	// or found nothing (Why, NothingFound): the searcher that did search
	// was the next one magpie tried in its place, and the Routing view
	// says so. Picked is that the first was the one picked in Settings.
	// A fallback that said nothing read as magpie ignoring the pick
	// (Gearclickist on Discord: Grok picked, Codex's model searched).
	// NotSearched is that the first answered without searching at all
	// (errNotSearched), apart from searching and naming no page.
	Instead      string `json:"instead,omitempty"`
	Why          string `json:"why,omitempty"`
	NothingFound bool   `json:"nothingFound,omitempty"`
	NotSearched  bool   `json:"notSearched,omitempty"`
	Picked       bool   `json:"picked,omitempty"`
}

CallFor is the request a call magpie made on its own was made for: its agent, and the model that agent asked for.

type Classified added in v0.1.95

type Classified struct {
	By      string   `json:"by"`               // the classifier model
	Intents []string `json:"intents"`          // what it chose among
	Intent  string   `json:"intent,omitempty"` // what it said the message is; "" for none
	// Said: the answer as it said it — the number a chat model answered
	// with (0 for none), or the choice a decision model named, its own
	// "none of these" included — kept when no intent came of it, so
	// "none" is told from an answer no rule could take (#4598)
	Said   string  `json:"said,omitempty"`
	After  string  `json:"after,omitempty"`  // what it said the turn before was, which it was told
	Effort string  `json:"effort,omitempty"` // the reasoning it said the turn wants
	Score  float64 `json:"score,omitempty"`  // how hard it took the turn to be, 0 (low) to 3 (xhigh)
	Sure   float64 `json:"sure,omitempty"`   // how confident it was of the intent, 0 to 1
	Cached bool    `json:"cached,omitempty"` // said before, for the same message
	Ms     int     `json:"ms,omitempty"`     // how long asking it took
	Error  string  `json:"error,omitempty"`  // why it couldn't say: no intent matches then, unless Fallback
	// Fallback: "previous" when it couldn't say and the turn keeps the
	// intent the turn before had (After), rather than none
	Fallback string `json:"fallback,omitempty"`

	// AfterEffort: the reasoning picked for the turn before, which it was told
	AfterEffort string `json:"afterEffort,omitempty"`
}

Classified is what the classifier was asked as a turn began, and said.

type ClaudeLastRun added in v0.1.2443

type ClaudeLastRun struct {
	TUI bool      `json:"tui"`
	Why string    `json:"why,omitempty"`
	At  time.Time `json:"at"`
}

ClaudeLastRun is how one run went: Why is claudePrint's code ("off") when it was -p.

type ClaudeMode added in v0.1.2427

type ClaudeMode struct {
	TUI bool   `json:"tui"`
	Why string `json:"why,omitempty"`
	WSL bool   `json:"wsl,omitempty"` // Claude Code in WSL
	// how the last run since magpie started went (noteClaudeRun)
	Last *ClaudeLastRun `json:"last,omitempty"`
}

ClaudeMode is how a Claude subscription's runs are made on this machine, for the Claude Code provider page: TUI when Claude Code's interactive mode, else -p (turned off) or none (it can't run here), Why the code of claudeMachineWhy. With it on, a request only -p takes (claudePrint) is refused.

func ClaudeModeNow added in v0.1.2427

func ClaudeModeNow() ClaudeMode

ClaudeModeNow is ClaudeMode as of now.

type ClaudeRun added in v0.1.1724

type ClaudeRun struct {
	PID     int    `json:"pid"`
	Model   string `json:"model"`
	Account string `json:"account,omitempty"`
	// State is "answering" (a turn is under way), "idle" (kept for the
	// conversation's next turn) or "tools" (its reply called the client's
	// tools, whose results it waits for); Since is when it began to.
	State   string    `json:"state"`
	Since   time.Time `json:"since"`
	Started time.Time `json:"started"`
	// Ends is when magpie lets it go if nothing comes for it (its timer).
	Ends time.Time `json:"ends,omitzero"`
	// RSS is Claude Code's resident memory in bytes, 0 when not read.
	RSS int64 `json:"rss,omitempty"`
}

ClaudeRun is one Claude Code process a conversation runs on.

type ClaudeRuns added in v0.1.1724

type ClaudeRuns struct {
	Object string      `json:"object"` // "claude-runs"
	Runs   []ClaudeRun `json:"runs"`
	// Live is every Claude Code magpie has running, the runs and its
	// one-off asks (a test, a warm-up, a /usage read) together.
	Live int `json:"live"`
	// Most is how many may run at once (0: no bound), MostWhy what says so.
	Most    int    `json:"most"`
	MostWhy string `json:"mostWhy,omitempty"`
	// IdleMost runs are kept for a next turn, IdleFor each at most.
	IdleMost int           `json:"idleMost"`
	IdleFor  time.Duration `json:"idleFor"`
}

ClaudeRuns is what ClaudeRunsPath answers.

type DiskArchive added in v0.1.1401

type DiskArchive struct {
	Dir string
	// contains filtered or unexported fields
}

DiskArchive is the archive in a folder on this computer: Put as a bucket is, and Open to read a call back.

func LocalArchive added in v0.1.1401

func LocalArchive() *DiskArchive

LocalArchive is the archive in magpie's folder: request-archive under ~/.config/magpie, or a portable magpie's data folder.

func (*DiskArchive) Open added in v0.1.1401

func (d *DiskArchive) Open(_ context.Context, name string) (io.ReadCloser, int64, error)

Open is the call kept at name, as it is read, and its size; ErrNotArchived when there is none. The caller closes it.

func (*DiskArchive) Put added in v0.1.1401

func (d *DiskArchive) Put(_ context.Context, name string, data []byte) error

Put writes data at name: to a temporary file beside it first, renamed over it once whole, so a reader never sees half a call. Then the oldest calls are removed while the folder is over its size.

type Event

type Event struct {
	Kind   EventKind
	Status int // upstream HTTP status for KError, when known
	Text   string
	ID     string
	Name   string
	MsgID  string
	Model  string
	Stop   string // stop | length | tool | filter
	// Code: for KError, the source error or safety-filter code (rate_limit,
	// server_error, bio_policy, content_filter…); RequestID: the vendor's id for the
	// request the event is of, when it is known by then
	Code             string
	RequestID        string
	Usage            Usage
	Hits             []Hit
	SafeguardResults json.RawMessage
	// StopDetails: Anthropic's stop_details, what its classifier said of
	// a refusal (#1768), carried to the client as it came
	StopDetails json.RawMessage

	// Wait: for KError, how long the vendor said to wait before asking
	// again, when it said; sent on as Retry-After
	Wait time.Duration
	// Said: for KError, the vendor's own error as {"error":{…}}, when it
	// said the request itself is at fault; its code and param go to a
	// client answered whole (writeVendorError)
	Said json.RawMessage
}

Event is one thing a streaming reply said.

type EventKind

type EventKind int

EventKind is what a streamed event carries.

const (
	KStart     EventKind = iota // MsgID, Model, Usage (input side)
	KText                       // Text
	KThink                      // Text (reasoning)
	KSig                        // Text (thinking signature), Name the API that signed it if known
	KToolStart                  // ID, Name
	KToolArgs                   // Text (partial JSON of the arguments)
	KStop                       // Stop
	KUsage                      // Usage
	KError                      // Text
	KSearch                     // Text (the query), Hits: a web search run for the model
	KImage                      // Name (media type), Text (base64): an image the model made
	// KThinkStart: a new block of reasoning begins (Anthropic's thinking
	// block, a Responses reasoning item, ID its id): what follows is not
	// the one before's, even with nothing between them
	KThinkStart
	// KSealed: Text is reasoning the upstream sealed, whole as its API
	// wrote it, Name that API (Part.Sealed): Anthropic's redacted_thinking
	// block, a Responses reasoning item as it was done
	KSealed
	// KTextSig: Text is Gemini's thoughtSignature on the text before it
	KTextSig
	// KAlive: nothing of the reply, only that its provider is still heard
	// from (a keepalive, an event with nothing for the client) after
	// keepaliveGap of nothing else: a reply read in rounds (searchReply)
	// keeps its client alive with it as a translated stream does (#2316)
	KAlive
)

type Format added in v0.1.1110

type Format struct {
	// Type is "json_schema" (Schema holds the schema the answer fits) or
	// "json_object" (any JSON object).
	Type string
	// Name and Description are json_schema's, as OpenAI's APIs take them;
	// Name is "response" where the client's API has none.
	Name, Description string
	Schema            json.RawMessage
	// Strict is the client's strict, nil when it said none.
	Strict *bool
	// contains filtered or unexported fields
}

Format is the shape a client asked the answer to come in (structured output), read from whichever API it spoke: Responses' text.format, Chat's response_format, Anthropic's output_config.format, Gemini's generationConfig.responseMimeType with its schema. Each API it is built for again asks for it in its own words; one that can't is told it in the system prompt (inSystem).

type GoroutineStats added in v0.1.1404

type GoroutineStats struct {
	PID        int    `json:"pid"`
	Program    string `json:"program"`
	Version    string `json:"version"`
	Window     bool   `json:"window"` // the app's window or magpie web serves the gateway
	Uptime     string `json:"uptime"`
	Goroutines int    `json:"goroutines"`
}

GoroutineStats says which process the dump is of.

type GroupRef added in v0.1.38

type GroupRef struct {
	ID string `json:"id"`
	// Ref: the id agents pick it by (provider.Group.Ref), auto/<model>
	// for a group magpie found, which the Routing page names it by
	Ref      string   `json:"ref,omitempty"`
	Name     string   `json:"name"`
	Routing  string   `json:"routing"`
	Affinity string   `json:"affinity"`
	Auto     bool     `json:"auto,omitempty"`
	Sink     bool     `json:"sink,omitempty"` // provider.Group.Sink, as it applies
	Members  []string `json:"members"`        // those ready, as provider/model[:effort fixed on it]
	// Subs: the groups in the group, at any depth, outermost first
	Subs []SubGroup `json:"subs,omitempty"`
	// Via: for each of Members, the groups in the group it is of, as
	// "fast>cheap" ("" for the group's own), when it has groups in it
	Via []string `json:"via,omitempty"`
	// Fast: those of Members sent in their vendor's fast mode
	Fast []string `json:"fast,omitempty"`
	// Paused: the models a pause rule left out of the request, so not in
	// Members (provider.PausedOut)
	Paused []provider.Paused `json:"paused,omitempty"`
}

GroupRef is the routing group a request asked for.

type HeapStats added in v0.1.1279

type HeapStats struct {
	PID          int    `json:"pid"`
	Program      string `json:"program"`
	Version      string `json:"version"`
	Window       bool   `json:"window"` // the app's window or magpie web serves the gateway
	Uptime       string `json:"uptime"`
	HeapAlloc    uint64 `json:"heapAlloc"`
	HeapInuse    uint64 `json:"heapInuse"`
	HeapIdle     uint64 `json:"heapIdle"`
	HeapReleased uint64 `json:"heapReleased"`
	HeapSys      uint64 `json:"heapSys"`
	StackSys     uint64 `json:"stackSys"`
	Sys          uint64 `json:"sys"`
	LiveHeap     uint64 `json:"liveHeap"`
	NumGC        uint32 `json:"numGC"`
	Goroutines   int    `json:"goroutines"`
}

HeapStats is what Go's runtime says of the process's memory when the profile was taken. HeapAlloc and the others are read before the collection the profile runs; LiveHeap is HeapAlloc after it, what is still reachable. Sys is all Go took from the system, so a footprint far above it is memory outside Go (the webview, cgo).

type HistoryDay added in v0.1.341

type HistoryDay struct {
	Day      string `json:"day"`
	Requests int    `json:"requests"`
}

HistoryDay is a kept day, and how many requests it had.

type Hit added in v0.1.149

type Hit struct {
	Title string `json:"title"`
	URL   string `json:"url"`
	// PageAge is how old the search said the page is, "" when it didn't
	PageAge string `json:"page_age,omitempty"`
	// Cited is what the search said of the page (a search API's snippet,
	// the text a searcher's own citation quotes), which a citation of it
	// quotes (citesOf); "" when it said nothing of it alone
	Cited string `json:"cited_text,omitempty"`
}

Hit is a page a web search found.

type Hub added in v0.1.1950

type Hub interface {
	// On is whether the Library's switch is on: off, the hub lists no
	// tool and runs none
	On() bool
	// Tools are the tools of the servers ticked for agent (every server
	// in the Library for agent "", HubMCPAll's), but those turned off; a
	// server that couldn't be reached by ctx's end is left out
	Tools(ctx context.Context, agent string) []HubTool
	// Servers are the servers behind agent's tools, by name, each with
	// what it is for where magpie knows it; it starts none of them
	Servers(agent string) []HubServer
	// Call runs one tool of server for agent, and is its result as the
	// server gave it; an error is why it couldn't be run
	Call(ctx context.Context, agent, server, tool string, args json.RawMessage) (json.RawMessage, error)
	// Stop ends every server the hub started
	Stop()
	// Prune ends each server the hub started that the Library no longer
	// gives: the switch turned off, the server removed or edited, here or
	// by another magpie (the window, the CLI)
	Prune()
}

Hub is the servers behind the hub: the library's.

var MCPHub Hub

MCPHub is set by the library; nil, the hub has no server.

type HubCaller added in v0.1.2263

type HubCaller struct {
	Roots   []string
	Client  string
	Session string
}

HubCaller is who a call of a Roots tool is for: the folders the agent said are its, as file URIs (none for an agent on another machine, whose folders aren't here), and its User-Agent's product, the name the server's own requests go under.

Session is which of the hub's callers the call is from (hubSession), for a server that keeps something per caller: Magpie Browser's tab, which two agents behind one router would otherwise share, the router running one `magpie mcp browser` for all of them.

func HubCallerOf added in v0.1.2263

func HubCallerOf(ctx context.Context) HubCaller

HubCallerOf is the caller a hub call's ctx carries.

type HubServer added in v0.1.2612

type HubServer struct{ Name, About string }

HubServer is a server behind the hub as an agent is told of it: About is what it is for, "" when magpie doesn't know.

type HubTool added in v0.1.1950

type HubTool struct {
	Server string // the Library server's name
	Tool   string // the tool's name on that server
	// Spec is the tool as the server listed it: its description,
	// inputSchema and the rest go to the agent as they are, its name
	// replaced
	Spec map[string]json.RawMessage
	// Roots: the server writes into the agent's project (magpie-image),
	// so a call is made with the agent's folders (HubCaller)
	Roots bool
}

HubTool is one tool a Library server lists, as the hub gives it.

type Kind

type Kind string

Kind is what a part of a message holds.

const (
	Text       Kind = "text"
	Image      Kind = "image"
	File       Kind = "file"
	ToolCall   Kind = "tool_call"
	ToolResult Kind = "tool_result"
	Thinking   Kind = "thinking"
	Search     Kind = "web_search" // a web search run for the model: its query and hits
)

type Lane added in v0.1.633

type Lane struct {
	Busy    int `json:"busy"`
	Waiting int `json:"waiting"`
	Limit   int `json:"limit"`
}

Lane is how a key's or account's requests stand: out at the vendor, and waiting their turn.

type MCPCalled added in v0.1.2170

type MCPCalled struct {
	Tool string `json:"tool"`
	// Millis is how long the call took, to its answer
	Millis int64 `json:"ms"`
	// Model is what the gateway's answer named the model by: provider/model
	Model string `json:"model,omitempty"`
	// Error is what a failed call said
	Error string `json:"error,omitempty"`
}

MCPCalled is one tool call the Magpie Image server answered.

type MadeFile added in v0.1.1596

type MadeFile struct {
	URL    string `json:"url"`
	Inline bool   `json:"inline,omitempty"`
}

MadeFile is one file a tool result's FilesMeta names.

type Masked added in v0.1.1305

type Masked struct {
	N        int            `json:"n"`
	Distinct int            `json:"distinct"`
	Warned   int            `json:"warned,omitempty"` // places a value went as written, the user told
	Kinds    map[string]int `json:"kinds,omitempty"`  // different values by kind
	By       map[string]int `json:"by,omitempty"`     // different values by finder
	// Key is a string in JSON: nanoseconds are past what a JS number
	// holds exactly, and a rounded key finds no record
	Key int64 `json:"key,omitempty,string"`
}

Masked is what masking swapped in a request, for the Routing page and Recent calls to show: how many places, how many different values, of which kinds and found by which finder; Key is its record (maskrec).

type Message

type Message struct {
	Role  string // user | assistant; system | developer on Responses-to-Responses
	Parts []Part
}

Message is one turn.

type ModelMove added in v0.1.2373

type ModelMove struct {
	To  string `json:"to"`
	Why string `json:"why"`
}

Route is one request's way through routing. ModelMove is a stand-in that put a request on another model than the one it named: To, the model it went on (before a routing group's pick), and Why, a word the Routing page says it by. A Desktop's own call (desktopMove's reasons), Claude Code's tiers (movedClaudeTier, movedClassifier), an agent's configured stand-in (movedStandIn), Codex's last turn's model (movedCodexTurn) and Privacy's unmasked route (movedPrivacy). Without it a row read "asked for chatflowsai/claude-opus-5-5 → agentrouter" with nothing to say a title, not the user's turn, was put on the chat's model (Neo on Discord).

type NestedRule added in v0.1.102

type NestedRule struct {
	Group string   `json:"group"`
	Name  string   `json:"name"`
	Rule  *RuleHit `json:"rule"`
}

NestedRule is a group in the group's rules, as they decided.

type OwnMCP added in v0.1.2397

type OwnMCP struct {
	Name  string `json:"name"`
	Title string `json:"title"`
	Path  string `json:"path"` // on this gateway, Streamable HTTP
}

OwnMCP is one of magpie's own MCP servers, as OwnMCPPath lists it.

type Part

type Part struct {
	Kind Kind
	Text string // text, thinking, or a tool result's output

	// image or file
	MediaType string
	Data      string // base64
	URL       string
	// Detail is an image's detail as the client asked for it (low, high,
	// auto, or Responses' original), which a Chat or Responses upstream
	// is given back (chatDetail, responsesDetail)
	Detail string

	// tool_call
	ID   string
	Name string
	Args json.RawMessage // a JSON object

	// tool_result
	CallID     string
	IsError    bool
	Images     []Part         // the images the tool returned beside its text
	Standalone map[string]any // native Responses notification with no call ID
	// Loads are the tools a tool's result loads, by name: Claude Code's
	// ToolSearch answers with tool_reference blocks naming the deferred
	// tools it found (#2660)
	Loads []string

	// thinking: its signature (Anthropic's, or a Gemini thought's). On a
	// tool call, and on text, Gemini's thoughtSignature: a tool call's
	// comes only from Google, as gemini_signature.go carries it, and
	// text's only from a Gemini API (#1445)
	Signature string
	// SignedBy is the API that signed a thinking Part (sealAnthropic for
	// Claude's), empty when it isn't known: only Claude's signature goes
	// to a Responses client, in its reasoning item's encrypted_content
	// (claudeseal)
	SignedBy string
	// thinking an upstream sealed, as its API wrote it: Anthropic's
	// redacted_thinking block, a Responses reasoning item with its id,
	// summary and encrypted_content. Only that API's builder, encoder and
	// renderer write it, byte for byte; to any other it is reasoning with
	// no text, or Text's (#1445). SealedBy is the API (sealAnthropic,
	// sealResponses).
	Sealed   json.RawMessage
	SealedBy string

	// web_search: Text is the query
	Hits []Hit
	// contains filtered or unexported fields
}

Part is one block of a message.

type Prompt added in v0.1.1107

type Prompt struct {
	Window int `json:"window,omitempty"` // the context window of the model that answered, when known
	// Tokens: the prompt, as the vendor counted it when Counted, the parts
	// scaled to it; estimated from the body before that
	Tokens  int  `json:"tokens"`
	Counted bool `json:"counted,omitempty"`
	// Held: the request named a previous response, whose turns the vendor
	// holds; they are in Tokens once counted, as the conversation
	Held  bool         `json:"held,omitempty"`
	Turns int          `json:"turns,omitempty"` // the user's turns in it
	Parts []PromptPart `json:"parts"`
}

Prompt is a request's prompt, part by part.

type PromptEntry added in v0.1.1169

type PromptEntry struct {
	Name   string        `json:"name"`
	Tag    string        `json:"tag,omitempty"`
	N      int           `json:"n,omitempty"`
	Tokens int           `json:"tokens"`
	Pieces []PromptPiece `json:"pieces,omitempty"`
}

PromptEntry is one item of a prompt's part with its text: the card's item, unfolded — every turn and every tool, not the latest or largest promptItems.

type PromptItem added in v0.1.1107

type PromptItem struct {
	Name   string `json:"name"`
	Tag    string `json:"tag,omitempty"` // what it is: mcp, user, project, skills, reminder, image, read, shell, turn…
	N      int    `json:"n,omitempty"`   // how many it gathers: an MCP server's tools, a tool's results
	Tokens int    `json:"tokens"`
}

PromptItem is one thing in a part: a tool, an MCP server's tools, an instruction file, a file read, a turn.

type PromptPart added in v0.1.1107

type PromptPart struct {
	Kind   string       `json:"kind"`
	Tokens int          `json:"tokens"`
	Items  []PromptItem `json:"items,omitempty"` // largest first, promptItems at most
}

PromptPart is one kind of what a prompt holds.

type PromptPiece added in v0.1.1169

type PromptPiece struct {
	// Role: system, user, assistant, thinking, call, result, tool, image,
	// sealed; "" for text that is the item itself (an instruction file)
	Role string `json:"role,omitempty"`
	Name string `json:"name,omitempty"` // the tool called or defined
	Text string `json:"text,omitempty"`
	Size int    `json:"size,omitempty"` // a sealed piece's bytes
	// Src: an image's picture as a data: URL, when the request sent it
	// inline as a PNG, JPEG, GIF or WebP; a linked image stays a name
	Src string `json:"src,omitempty"`
	// contains filtered or unexported fields
}

PromptPiece is a stretch of an item's text as the request sent it: a message, a tool's definition, a call and its input, what a tool answered. Sealed reasoning is only named, with its size; an image is its picture when the request carried it inline (Src).

type PromptText added in v0.1.1169

type PromptText struct {
	ID    int64         `json:"id"`
	Kind  string        `json:"kind"`
	Items []PromptEntry `json:"items"`
	// Kept is how many requests' text is kept, for the GUI to say so
	Kept int `json:"kept"`
}

PromptText is a part of a request's prompt, item by item, with the text when an item is asked for.

type Putter added in v0.1.577

type Putter interface {
	Put(ctx context.Context, name string, data []byte) error
}

Putter is a bucket the archive is written to.

type Request

type Request struct {
	Model      string
	System     string
	Messages   []Message
	Tools      []Tool
	ToolChoice string // "" | auto | none | required | name:<tool>
	MaxTokens  int
	Temp       *float64
	TopP       *float64
	Stop       []string
	Stream     bool
	Effort     string // low | medium | high | xhigh | max, when the client asked
	Thinking   bool   // the client asked for visible reasoning
	// ThinkOff is the client turning reasoning off: effort "none" (which
	// Effort reads as low, for vendors with no way to turn it off) or an
	// Anthropic request with thinking disabled.
	ThinkOff  bool
	Parallel  *bool // parallel tool calls allowed
	WebSearch bool  // the client offered its provider's own web search
	Fast      bool  // the client asked for priority processing: service_tier priority (Codex's Fast mode)
	// Ultrafast is Codex's Ultrafast (service_tier "ultrafast"), which a
	// ChatGPT account on a plan with it offers on its models; Fast is set
	// with it, so where there is no Ultrafast the request goes fast
	Ultrafast bool
	// Tier is the service_tier the client sent, as it sent it. It goes on
	// as it is to a provider the user added by its address (OwnTier):
	// a relay of theirs may serve Fast and Ultrafast where magpie can't
	// tell (hsiangron on X: both were left out)
	Tier string
	// OwnTier is set for such a provider (gateway.go, as each attempt is
	// built); one that turns the field away is asked again without it
	// (optionalFields)
	OwnTier bool
	// OwnEffort is set when Effort is magpie's own ask, not the client's:
	// auto mode's classifier asked to reason least of a model whose levels
	// aren't known (fitAutoModeClassifier). An upstream that turns it away
	// is asked at low, or without it, as it would have been
	// (ownEffortRefused)
	OwnEffort bool
	// CacheKey is the client's prompt_cache_key (Codex sends its thread's
	// id), which OpenAI, and relays in front of it, route a conversation by
	// to where its prompt is cached.
	CacheKey string
	// Include is a Responses client's include, the extra output it asked
	// for (Codex's reasoning.encrypted_content), which a Responses upstream
	// is asked for too: a relay may refuse a request without it (#315).
	Include []string
	// ClientMetadata and Text are a Responses client's client_metadata
	// (Codex's installation and session ids, which a relay may check, #374)
	// and text (its verbosity), which go on as they were sent when the
	// request is built again for a Responses upstream; no other API takes
	// them. text's format is read into Format.
	ClientMetadata json.RawMessage
	Text           json.RawMessage
	// AccessPrograms is a client's access_programs, the program a request
	// asks the model under (OpenAI's Daybreak: {"cyber":"daybreak_blue"}),
	// which Codex CLI sends the ChatGPT backend on every turn it picked one
	// for (codex-rs's ResponsesApiRequest.access_programs). It goes on as it
	// was sent, null and all, when the request is built again for a
	// Responses upstream, whose answer to a value it doesn't take
	// (invalid_access_program) is the client's to read; no other API takes
	// it (magpie-releases#18). Only OpenAI's upstreams are sent it
	// (keepsAccessPrograms, #3172).
	AccessPrograms json.RawMessage
	// Metadata is an Anthropic client's metadata (Claude Code's user_id),
	// which goes on as it was sent when the request is built again for an
	// Anthropic upstream: a relay that serves only Claude Code turns a
	// request without it away (#359).
	Metadata json.RawMessage
	// ImageConfig is a Gemini client's generationConfig.imageConfig, the
	// size and shape it asks an image model to draw at (imageSize,
	// aspectRatio, and Vertex AI's fields beside them), which goes on as
	// it was sent when the request is built again for an upstream that
	// speaks Gemini, inside Code Assist's envelope too
	// (buildCodeAssistSent). Left out, the picture came back at the
	// model's default size (#3820). No other API is known to take it.
	ImageConfig json.RawMessage
	// Safeguards are the caller's safety context, opaque to the gateway.
	Safeguards    json.RawMessage
	SafeguardBeta string
	// Format is the shape the client asked the answer in (structured
	// output: format.go), nil for plain text. Text, a Responses client's,
	// holds it no more: it is asked for again in the upstream's own words.
	Format *Format
	// FormatTold is set when Format was told in the system prompt instead
	// (inSystem): the client still wants the answer as JSON.
	FormatTold bool
	// GeminiCompat is the upstream being Gemini's OpenAI-compatible API
	// (AI Studio's, or a proxy in front of it on this machine or the LAN),
	// which gives the model's thoughts only when asked in thinking_config.
	GeminiCompat bool
	// OffLevel is the level such an API is asked to think at when the
	// client turned reasoning off: Gemini 3 can't stop thinking, and thinks
	// least at minimal, or at its lowest level where it has no minimal or
	// turned minimal away (geminiLevels). "" is minimal.
	OffLevel string
	// Resume is set on a request built to go on with a reply the client
	// already has part of (continuation.go): its last message is that
	// part, an assistant message the model goes on from, not a turn
	// answered.
	Resume bool
	// LastIsTurn is set on a request from a client whose API reads a
	// conversation ending with the assistant's message as a turn already
	// said, to answer after (OpenAI's Chat and Responses), not one to go
	// on from (Anthropic's prefill): to a model that takes no prefill it
	// is asked with a user turn after it (prefill.go).
	LastIsTurn bool
	// Namespaced are the tools a Responses client offered inside a
	// namespace, by the flat name the model is offered them under.
	Namespaced map[string]nsTool
	// LoadedInPlace has a Responses upstream that takes an additional_tools
	// item (loadsInPlace) given a deferred tool a result loaded in such an
	// item right after that result, not in the top-level tools: the tools
	// and the conversation sent before stay as they were, so its prompt
	// cache does (#2660). Every other upstream gets them in tools.
	LoadedInPlace bool
	// CR is set when the model asked is one of the glm-5.3-flash* routes
	// whose replicas stitch CR into a call's arguments (#4256): the
	// arguments reach the client with the stitched CR dropped
	// (tool_args_cr.go).
	CR bool
	// contains filtered or unexported fields
}

Request is a call to a model, whichever API it arrived in.

type Rest added in v0.1.38

type Rest struct {
	Why    string    `json:"why"`    // failCredit, failQuota, failRate, failOther
	Status int       `json:"status"` // what it answered
	Until  time.Time `json:"until"`
	// By is what set how long: "credit" (half an hour, a key longer each
	// time again: creditLadder), "retry-after" (the
	// vendor's own headers), "resets" (the time Claude Code gave), "window"
	// (the allowance window it filled renews), "quota" (no word of when),
	// "cooldown" (a minute), "backoff" (longer each time it fails again,
	// or is rate limited again as soon as it is back), "restricted" (the
	// vendor restricted the account: two hours, or until lifted by hand),
	// "off" (no rest: its provider is set not to rest after an unknown
	// failure, provider.RestCapOff).
	By       string `json:"by"`
	Failures int    `json:"failures,omitempty"` // in a row, for a backoff
	// Key is what it rests by, for the app to lift the rest (Unrest)
	Key string `json:"key,omitempty"`
	// Model: the one model resting, when the account or key still
	// answers its others (a pooled allowance, a model it doesn't serve);
	// "" for the account or key as a whole. The app shows the rest on
	// that model's rows only (#1960: Antigravity's Claude & GPT pool used
	// up showed gemini-3.8-flash, in a pool of its own, as out too).
	Model string `json:"model,omitempty"`
	// Link: where the vendor said to verify the account, for failVerify
	Link string `json:"link,omitempty"`
	// Probed: a key resting after an outage that names no time (a 5xx, its
	// vendor unreachable) is asked again in the background, and its rest
	// lifted as soon as it answers (rest_probe.go)
	Probed bool `json:"probed,omitempty"`
	// Error: what the vendor said, for the app to show beside "failed"
	// (GanHei37443 on X: three WorkBuddy accounts each "failed · back in
	// 16s", and nothing on the row said why)
	Error string `json:"error,omitempty"`
	// contains filtered or unexported fields
}

Rest is why a candidate sits out after a failure, and until when.

func RestOf added in v0.1.930

func RestOf(key string) (Rest, bool)

RestOf is why what rests by key — a provider's id, or its id#key — is passed over now, while it is.

type RestartReply added in v0.1.2323

type RestartReply struct {
	// restarting: at once; waiting: once what a restart would cut short
	// (Busy) is done; current: this magpie wasn't the one updated (another
	// copy, or nothing put in); unsupported: this magpie (magpie serve)
	// doesn't restart itself, and is restarted the way it was started
	State string `json:"state"`
	// Version is this magpie's, the one restarting
	Version string `json:"version"`
	// Handover: the new version takes the gateway over while this one
	// finishes its requests (Busy is then the Claude subscription's turns)
	Handover bool  `json:"handover,omitempty"`
	Busy     *Busy `json:"busy,omitempty"`
}

RestartReply is what RestartPath answers.

type Result

type Result struct {
	ID               string
	Model            string
	Parts            []Part
	Stop             string
	Usage            Usage
	SafeguardResults json.RawMessage
	StopDetails      json.RawMessage
}

Result is a whole reply, for non-streaming clients.

type Route added in v0.1.38

type Route struct {
	Seq           int64        `json:"seq"` // the trace's count when it last changed
	ID            int64        `json:"id"`
	Time          time.Time    `json:"time"`
	Agent         string       `json:"agent"`
	ParentSession string       `json:"parentSession,omitempty"` // title helper's explicit originating chat; does not affect routing
	Session       string       `json:"session,omitempty"`       // the client's session id, never inferred from its model or account
	TitleLink     *TitleLink   `json:"titleLink,omitempty"`     // digests only; display evidence, never account affinity
	ParentMatched bool         `json:"parentMatched,omitempty"` // parent inferred for this view, not supplied by Codex
	Usage         []RouteUsage `json:"usage,omitempty"`         // token tiers of billable tries; priced when read
	Kind          string       `json:"kind,omitempty"`          // what the call is for, as Call's
	For           *CallFor     `json:"for,omitempty"`           // the request it was made for, as Call's
	Model         string       `json:"model"`                   // as the agent asked
	Effort        string       `json:"effort,omitempty"`        // the reasoning the agent asked for; "" for none
	Tier          string       `json:"tier,omitempty"`          // the service tier the agent asked for (bodyTier); "" for none
	Provider      string       `json:"provider"`                // the provider the model resolved to
	Group         *GroupRef    `json:"group,omitempty"`         // the routing group the agent asked for
	Rule          *RuleHit     `json:"rule,omitempty"`          // the group's rules for it, when it has any
	SealedTask    bool         `json:"sealedTask,omitempty"`    // only ChatGPT accounts can read this subagent's task
	LeadAccount   string       `json:"leadAccount,omitempty"`   // the parent account put first for a sealed task
	// Compaction: the key or account that sealed the native compaction
	// the request carries, the only one it went to (#1099): Routing says
	// so, not that it is the only one on for the model (#2639)
	Compaction string `json:"compaction,omitempty"`
	// Subagent is a Codex or Claude Desktop subagent's request put on
	// the model set for its subagents, or kept on the one asked for and why
	Subagent *SubagentPick `json:"subagent,omitempty"`
	// Moved: the request was served on another model than Model names,
	// by one of magpie's stand-ins, and why (ModelMove); nil when it went
	// where it asked, or to a routing group by its name
	Moved *ModelMove `json:"moved,omitempty"`
	// Sub: the Claude Code subagent the request is of (subagentOf), whose
	// session header is its conversation's; "" for the conversation's own
	Sub string `json:"sub,omitempty"`
	// SubagentEffort is Desktop's configured effort. Tries keep the actual
	// level after member overrides and fitting to the model.
	SubagentEffort string `json:"subagentEffort,omitempty"`
	// SubagentID is the Claude Code subagent whose turn this is
	// (subagentTurnOf), the id the ledger's Subagent keeps too. Claude Code
	// names no kind for it, so Kind stays empty and the Routing page tags
	// it as Codex's subagents are.
	SubagentID string `json:"subagentId,omitempty"`
	// Nested: the rules of the groups in the group, down the way to the
	// one that went first, each as it decided
	Nested   []NestedRule `json:"nested,omitempty"`
	Affinity *Affinity    `json:"affinity,omitempty"` // its conversation, and whether it stayed put
	Pinned   string       `json:"pinned,omitempty"`   // the account AccountHeader named: only it was tried
	Order    []Weighed    `json:"order"`              // who was to try it, first first
	Left     []Weighed    `json:"left,omitempty"`
	Tries    []Try        `json:"tries"`
	// Masked: what masking swapped in the request before it went, nil
	// for nothing (noteMasked)
	Masked *Masked `json:"masked,omitempty"`
	Done   bool    `json:"done"`
	Status int     `json:"status,omitempty"`
	Error  string  `json:"error,omitempty"`
	Millis int64   `json:"ms,omitempty"`
	Tokens int     `json:"tokens,omitempty"`
	Output int     `json:"out,omitempty"` // of Tokens, the reply's
	// Reasoning: of Output, the reply's reasoning, which its speed leaves
	// out (usage.DecodeOf)
	Reasoning int `json:"reasoning,omitempty"`
	// TTFT: ms from the request to its reply's first content (text,
	// reasoning or a tool call), FirstText to its first text, as Millis
	// counts: streamed replies only (#196)
	TTFT      int64 `json:"ttft,omitempty"`
	FirstText int64 `json:"firstText,omitempty"`
	// FirstReasoning is the start of paced visible reasoning, absent for hidden reasoning.
	FirstReasoning  int64 `json:"firstReasoning,omitempty"`
	ReasoningHidden bool  `json:"reasoningHidden,omitempty"`
	// Flow: the ms its content took to come (Call.Flow)
	Flow int64 `json:"flow,omitempty"`
	// Sent: ms from the request to its answering try's request written
	// to the vendor, and of it Own magpie's, Retried the tries that
	// failed first, Queued waiting for a slot, as the usage record has
	// them (Record.Sent); the rest of Sent is connecting and sending
	Sent    int64 `json:"sent,omitempty"`
	Own     int64 `json:"own,omitempty"`
	Retried int64 `json:"retried,omitempty"`
	Queued  int64 `json:"queued,omitempty"`
	// Phase: "redact" while it is being masked and not yet done
	// (noteRedacting), so its row says masking rather than routing;
	// Masking: the ms of Own that went on masking it, all of it when Own
	// is unknown (maskingMs)
	Phase   string `json:"phase,omitempty"`
	Masking int64  `json:"masking,omitempty"`
	// Held: the file name, in HeldDir, of the report saved of a request
	// magpie held too long before routing it and stopped (giveUp)
	Held string `json:"held,omitempty"`
	// Served: the model the reply says answered, as the last try has it;
	// Swapped: another than the one that try asked for; Routed: that try
	// asked another magpie's routing group, and Served is its member
	Served  string `json:"served,omitempty"`
	Swapped bool   `json:"swapped,omitempty"`
	Routed  bool   `json:"routed,omitempty"`
	// Upstream: the provider an aggregator said answered behind it
	Upstream string `json:"upstream,omitempty"`
	// Prompt: what the prompt held, part by part, and the window it went
	// into (prompt.go)
	Prompt *Prompt `json:"prompt,omitempty"`
	// Conv: the conversation a request without a session id is part of,
	// as a digest of its first user turn (conversationID)
	Conv string `json:"conv,omitempty"`
	// Folder: the last two levels of the folder its agent says it works
	// in (shortFolder), never the whole path; a request that says none
	// takes its session's, as said last (#1068)
	Folder string `json:"folder,omitempty"`
	// Archive: "<date>/<id>", where the request archive keeps the call,
	// when it was on (Call.Archive), for the page to read its bodies back
	// once the recent calls have let them go
	Archive string `json:"archive,omitempty"`
	// contains filtered or unexported fields
}

func HistoryRoute added in v0.1.572

func HistoryRoute(id int64, day time.Time) (Route, bool)

HistoryRoute searches the request's day and its neighbours (the browser and gateway may use different time zones), without holding up history writes.

type RouteTry added in v0.1.578

type RouteTry struct {
	Model  string `json:"model"` // provider/model
	Effort string `json:"effort,omitempty"`
	// Tier: the service tier it went out at; TierServed: the one its
	// reply said it ran at
	Tier       string `json:"tier,omitempty"`
	TierServed string `json:"tier_served,omitempty"`
	Done       bool   `json:"done"`
	Status     int    `json:"status,omitempty"`
	Fail       string `json:"fail,omitempty"` // why it failed, as the trace tells it
	Millis     int64  `json:"ms,omitempty"`
}

RouteTry is one member trying the request: each failed one was fallen over from.

type RouteUsage added in v0.1.591

type RouteUsage struct {
	Provider   string `json:"provider"`
	Model      string `json:"model"`
	Input      int    `json:"in"`
	Output     int    `json:"out"`
	CacheRead  int    `json:"cache_read,omitempty"`
	CacheWrite int    `json:"cache_write,omitempty"`
	Reasoning  int    `json:"reasoning,omitempty"`
	// CacheUnknown: the vendor counted no cache tokens, so the Routing
	// page shows no hit rate rather than 0% (Kiro, zeewell on X)
	CacheUnknown bool `json:"cache_unknown,omitempty"`
}

RouteUsage is one billable attempt's pricing inputs, kept in routing history. Its JSON keys also read the earlier history that stored full usage records.

func (RouteUsage) PricingRecord added in v0.1.591

func (u RouteUsage) PricingRecord() usage.Record

PricingRecord lets the routing view reuse the ledger's effective prices.

type RuleHit added in v0.1.94

type RuleHit struct {
	N   int    `json:"n"`             // the rule, from 1; 0 when none matched
	Use string `json:"use,omitempty"` // the member it puts first
	// More: the members the rule names after Use (provider.Rule.More), in
	// order: they go next, before Then
	More []string `json:"more,omitempty"`
	When []string `json:"when,omitempty"`
	Held bool     `json:"held,omitempty"` // decided when the turn began
	// Waits: the turn began before magpie saw it (or its rule was changed
	// since), so no rule moves it; the next turn is looked at afresh
	Waits bool `json:"waits,omitempty"`
	// Grown: within the turn the conversation grew past what the model it
	// was on can take, so the rules were looked at again — the one time a
	// turn moves
	Grown  bool   `json:"grown,omitempty"`
	Turn   int    `json:"turn"`             // the user's turns so far
	Tokens int    `json:"tokens"`           // how long the request was taken to be
	Images bool   `json:"images,omitempty"` // it carries an image
	Effort string `json:"effort,omitempty"` // the reasoning asked for: a level, or "on"
	// Folder: the working folder the agent said, looked at when a rule
	// is by folder; "" when it said none
	Folder string `json:"folder,omitempty"`
	// Unready: the member the rule names has nobody to take it now, and
	// the group routes the request as it would without the rule.
	Unready bool `json:"unready,omitempty"`
	// Then: the members the rules after it that match too send to, which
	// the request fails over to, in turn, before the group's others (#112)
	Then []string `json:"then,omitempty"`
	// Instead: the one of Then that went first, Use having nobody ready
	Instead string `json:"instead,omitempty"`
	// Classified: the group's classifier was asked which intent the
	// turn's first message is
	Classified *Classified `json:"classified,omitempty"`
	// Pick: the reasoning the group's decision model picked for the turn,
	// which its requests ask their model for (provider.EffortAuto)
	Pick string `json:"pick,omitempty"`
	// Wanted: the reasoning the decision model picked for the turn when
	// the conversation kept a higher one (Pick) for the vendor's cache of
	// it (#617) — sent instead where the change goes as an effort update
	// that keeps the cache (takesEffortUpdates)
	Wanted string `json:"wanted,omitempty"`
	// Compact: the request is the agent compacting its conversation, looked
	// at on its own; Small, the members of rules it matched that take less
	// than it is long, passed over
	Compact bool     `json:"compact,omitempty"`
	Small   []string `json:"small,omitempty"`
	// Bare: the group has no rules, only its effort picked
	Bare bool `json:"bare,omitempty"`
	// UseEffort: the reasoning the rule asks the member it names for
	// (provider.Rule.UseEffort, #2633), in place of the agent's
	UseEffort string `json:"useEffort,omitempty"`
	// contains filtered or unexported fields
}

RuleHit is what the trace tells of a group's rules for a request.

type SearchFailure added in v0.1.1216

type SearchFailure struct {
	Searcher     string // "<provider>/<model>", or "<provider>"
	Why          string // the error, when it neither found nothing nor didn't search
	NothingFound bool   // it searched and named no page
	NotSearched  bool   // it answered without searching (errNotSearched)
	// Instead is the searcher Settings names after it (SearcherThen) that
	// searched in its place, "" when none did
	Instead string
	At      time.Time
}

SearchFailure is a search the searcher Settings names didn't make: why, and when.

func SearcherFailed added in v0.1.1216

func SearcherFailed() (SearchFailure, bool)

SearcherFailed is the last search the searcher Settings names now didn't make, since it last searched; ok false when there is none.

type SearchKeyQuota added in v0.1.1231

type SearchKeyQuota struct {
	Key string `json:"key"` // masked (provider.MaskSearchKey)
	// Known: Used and Limit were read. Unlimited: read, and the key and
	// its plan have no limit (Used is what the key has used).
	Known     bool  `json:"known"`
	Unlimited bool  `json:"unlimited,omitempty"`
	Used      int64 `json:"used"`
	Limit     int64 `json:"limit"`
	// Of is what Limit is the limit of: "key", a limit set on the key
	// itself, or "plan", its account's plan (which every key of the
	// account spends)
	Of   string `json:"of,omitempty"`
	Plan string `json:"plan,omitempty"` // the plan's name
	// PaygoLeft is the pay-as-you-go credit still there past the plan's
	// limit, 0 when there is none
	PaygoLeft int64 `json:"paygoLeft,omitempty"`
	// UsedUp: Used reached Limit, with no pay-as-you-go credit left
	UsedUp bool `json:"usedUp,omitempty"`
	// Err is why it couldn't be read: Known is false
	Err string `json:"err,omitempty"`
	// Resting is why searches ask the key last now (searchKeyOrder), and
	// RestUntil until when; "" when they don't
	Resting   string    `json:"resting,omitempty"`
	RestUntil time.Time `json:"restUntil,omitzero"`
}

SearchKeyQuota is what one key of a search API has used of its limit.

func SearchQuotas added in v0.1.1231

func SearchQuotas(ctx context.Context, a provider.SearchAPI, fresh bool) []SearchKeyQuota

SearchQuotas reads what each of a search API's keys has left, in the order of its keys, nil for an API magpie can't ask (CanReadSearchQuota). A read newer than searchQuotaKeep is used again unless fresh is set. A key it finds used up rests (a search asks it last); one with credit that rests for being out of it wakes.

type SearcherChoice added in v0.1.672

type SearcherChoice struct {
	Provider provider.Provider
	Small    string // the model it searches with when none is named
	Models   []catalog.Model

	ManualOnly bool // a relay said to search, which only Settings may name
	// Service is a Kimi Code plan, which searches by its search service,
	// with no model (and no Small or Models)
	Service bool
	// Own is a Google sign-in, whose Gemini searches for the provider's
	// own models first, whoever is named (ownSearcher)
	Own bool
	// contains filtered or unexported fields
}

SearcherChoice is a provider Settings' Searcher may name.

func Searchers added in v0.1.672

func Searchers() []SearcherChoice

Searchers are the providers Settings' Searcher may name: those magpie would pick, then relays said to search, each with the model it would search with.

type SeatPrice added in v0.1.2235

type SeatPrice struct {
	Input     float64 `json:"input"`
	Output    float64 `json:"output"`
	CacheRead float64 `json:"cacheRead,omitempty"`
	Peak      bool    `json:"peak,omitempty"`
}

SeatPrice is what a weighed one's model costs on it at the request's time, as Cheapest first went by it: a million tokens each, in the catalog's dollars, Peak when that is its vendor's peak-hour price.

type Served added in v0.1.638

type Served struct {
	Running bool   // a magpie gateway answers
	Window  bool   // its routing can be watched in its window (#110)
	Version string // its version; "" from one that doesn't say
	Pid     int    // its process id; 0 from one that doesn't say
	Serves  string // how it was started: app, tray, web, serve or tui; "" from one that doesn't say
}

Served is what the magpie answering at the gateway's address says of itself.

func ServedBy added in v0.1.638

func ServedBy() Served

ServedBy asks the address which magpie answers there. Another magpie can keep the port after this one is updated (a magpie serve left running, a second copy, one that didn't quit), and every agent's request is then still that one's to send: in #506 a Factory 403 came worded as v0.1.550 and earlier word it to two people whose magpie said v0.1.630, so none of the fixes since reached their requests. Its version tells it apart.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the gateway.

func New

func New() *Server

New makes a gateway.

func (*Server) Active added in v0.1.1241

func (s *Server) Active() []Active

Active lists the agent requests in flight now, the oldest first; empty, never nil, when there are none.

func (*Server) Addr added in v0.1.1354

func (s *Server) Addr() string

Addr is where the gateway listens, "" before it does.

func (*Server) Busy added in v0.1.672

func (s *Server) Busy() Busy

Busy says what is in flight at the gateway now.

func (*Server) CodexBusy added in v0.1.1704

func (s *Server) CodexBusy() (int, time.Time)

CodexBusy is how many of Codex's requests are in flight and when its last ended: a turn of the Codex app's that a restart of its app-server would cut short (provider.KeepCodexAppOnItsProvider). Other agents' requests don't hold it.

func (*Server) Front added in v0.1.1444

func (s *Server) Front() http.Handler

Front is what the gateway's own listener serves: Handler behind lanGuard, built once. `magpie web`'s port hands the gateway's client routes (ClientPath) to it too, so a request there is judged exactly as one on the gateway's port: the allow list, a key from another machine or through a proxy, a rebound page's Host, and corsGuard's Origin rules.

func (*Server) HandOff added in v0.1.1354

func (s *Server) HandOff()

HandOff has the gateway stop accepting at once: the magpie it was handed to takes every connection from now on (one this one took as its end began was closed unanswered, #3568). Once its ctx ends, it waits for every request in flight to finish (handedOffDrain at most) rather than 2s.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler routes the client APIs.

func (*Server) Lanes added in v0.1.633

func (s *Server) Lanes() map[string]Lane

Lanes is how each key or account with requests out or waiting stands, limit or none (Limit 0), by its who (provider, provider#key, provider@account).

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(ctx context.Context) error

ListenAndServe runs the gateway until ctx ends, and returns once the requests in flight then have finished: within 2s, or, handing over, as long as a stream takes. A bind error means another magpie is already serving, which is fine for the caller to ignore.

func (*Server) ListenerFile added in v0.1.1354

func (s *Server) ListenerFile() (*os.File, error)

ListenerFile is a copy of the socket the gateway listens on, to hand to the magpie that takes it over; the caller closes it once sent.

func (*Server) PromptText added in v0.1.1169

func (s *Server) PromptText(id int64, kind string, withText bool) (PromptText, bool)

PromptText is the part kind of request id's prompt, item by item, in the card's order: the turns oldest first, the rest largest first. Each entry's text is there when withText; false when the request's body is no longer kept, or its prompt can't be read.

func (*Server) Recent

func (s *Server) Recent() []Call

Recent lists the last calls, newest first.

func (*Server) RecentCall added in v0.1.1172

func (s *Server) RecentCall(id uint64) (Call, bool)

RecentCall is the call numbered id while it is still in the ring.

func (*Server) Relisten added in v0.1.168

func (s *Server) Relisten() error

Relisten moves the gateway to where settings now say it listens — onto the network or back to loopback, or to another port. Requests in flight finish.

func (*Server) ResolveTitleParents added in v0.1.840

func (s *Server) ResolveTitleParents(rows []Route) []Route

ResolveTitleParents checks completed title replies against actual Codex name writes. It operates on copies for the GUI only, never on gateway routing. An explicit parent wins. Missing, conflicting or old evidence fails closed.

func (*Server) RouteCall added in v0.1.1265

func (s *Server) RouteCall(route int64) (Call, bool)

RouteCall is the call the Routing page's request route was, while it is still in the ring.

func (*Server) ServeCallbacks added in v0.1.1354

func (s *Server) ServeCallbacks(ln net.Listener) error

ServeCallbacks answers, on ln, the tool calls of the Claude Code runs this process started (claudeMCPPath): their MCP helper calls the gateway's port, which the magpie this one handed it to now serves, and that one passes on the calls of runs it doesn't have (ForwardCallbacks). It returns once ln is closed.

func (*Server) Trace added in v0.1.38

func (s *Server) Trace(ctx context.Context, after int64, wait time.Duration) TraceState

Trace is the routes changed after seq, oldest first. With none, it waits up to wait for one.

func (*Server) Unrest added in v0.1.304

func (s *Server) Unrest(key string) bool

Unrest lifts the rest of what rests by key — an account just verified with its vendor, say — so the next request asks it again: rate limited with Sink on, it is no longer sent to the back of the order either. The lift is told to the Routing page (TraceState.Lifted), wherever it was asked for. False when it wasn't resting.

func (*Server) UnrestAll added in v0.1.1220

func (s *Server) UnrestAll(key string) int

UnrestAll lifts every rest of what rests by key: its own and each of its models' (restID, key/model). A key whose value was replaced (#1869) is asked again for all of them. It returns how many it lifted.

type SessionRoute added in v0.1.578

type SessionRoute struct {
	ID          int64        `json:"id"`
	Time        time.Time    `json:"time"`
	Kind        string       `json:"kind,omitempty"`         // a side call's: a title, a subagent…
	Asked       string       `json:"asked"`                  // the model as the agent asked
	AskedEffort string       `json:"asked_effort,omitempty"` // the reasoning it asked for
	AskedTier   string       `json:"asked_tier,omitempty"`   // the service tier it asked for
	Group       string       `json:"group,omitempty"`        // the routing group's id, when it asked one
	Rule        *RuleHit     `json:"rule,omitempty"`         // the group's rules, as the Routing page has them
	Nested      []NestedRule `json:"nested,omitempty"`
	// Model and Effort: the try under way, or the last, as provider/model
	// and the reasoning it was sent at
	Model  string `json:"model,omitempty"`
	Effort string `json:"effort,omitempty"`
	// Tier and TierServed: the service tier that try went out at, and the
	// one its reply said it ran at, when it said one (#1784)
	Tier       string     `json:"tier,omitempty"`
	TierServed string     `json:"tier_served,omitempty"`
	Served     string     `json:"served,omitempty"` // the model the reply says answered
	Tries      []RouteTry `json:"tries"`
	Done       bool       `json:"done"`
	Status     int        `json:"status,omitempty"`
	Error      string     `json:"error,omitempty"`
	Millis     int64      `json:"ms,omitempty"`
	TTFT       int64      `json:"ttft_ms,omitempty"`
}

SessionRoute is a session's latest request as routing has it so far.

type SubGroup added in v0.1.102

type SubGroup struct {
	ID      string `json:"id"`
	Ref     string `json:"ref,omitempty"` // as GroupRef's
	Name    string `json:"name"`
	Routing string `json:"routing"`
	In      string `json:"in"`              // the group it is in
	Rules   int    `json:"rules,omitempty"` // how many rules it has
}

SubGroup is a routing group in the group a request asked for.

type SubagentPick added in v0.1.1142

type SubagentPick struct {
	Asked string `json:"asked"`
	To    string `json:"to"`
	Kept  string `json:"kept,omitempty"`
}

SubagentPick is a subagent's request put on the model the user set for its agent's subagents, in place of the one its lead asked for: Codex's (provider.CodexSubagentModel, willz on Discord) or Claude Desktop's (provider.DesktopSubagentModel). Kept says why it went on the model asked for instead, "" when it was put on To.

func (*SubagentPick) Moved added in v0.1.1142

func (p *SubagentPick) Moved() bool

Moved says the request went on To.

type Tally added in v0.1.2322

type Tally struct {
	ID       string         `json:"id"` // what rests after a failure, as Weighed has it
	Provider string         `json:"provider"`
	Name     string         `json:"name,omitempty"`
	Icon     string         `json:"icon,omitempty"`
	Preset   string         `json:"preset,omitempty"`
	Who      string         `json:"who,omitempty"`
	Kind     string         `json:"kind"`
	Agent    string         `json:"agent,omitempty"`
	Plan     string         `json:"plan,omitempty"`
	Model    string         `json:"model,omitempty"`
	Routing  string         `json:"routing,omitempty"`
	Rank     int            `json:"rank,omitempty"`
	Tried    int            `json:"tried"`
	OK       int            `json:"ok"`
	Fails    map[string]int `json:"fails,omitempty"`
	Last     int64          `json:"last,omitempty"` // ms, of its latest answer
	Models   []string       `json:"models,omitempty"`
	Rest     *Rest          `json:"rest,omitempty"`   // how its latest try left it
	RestAt   int64          `json:"restAt,omitempty"` // ms, of when it did
	// contains filtered or unexported fields
}

Tally is one account or key's day, as the day's history tells it: how often it was tried, answered and failed, its latest answer, the models that answered, and how its latest try left it. The Routing page's accounts and keys say these of a whole day (#3351), read from the same files the Usage page reads, where counting the trace would say only of the last few requests the gateway keeps. What the history cannot say — the readings its latest request was weighed by, one model resting alone — the page keeps from the trace.

type TitleLink struct {
	Scope  string `json:"scope"`
	Prompt string `json:"prompt"`
	Reply  string `json:"reply,omitempty"`
}

TitleLink contains only fingerprints. Native request IDs and account affinity are never changed by an inferred display association.

type Tool

type Tool struct {
	Name        string
	Description string
	Schema      json.RawMessage // JSON schema of the arguments
	Strict      bool            // the client asked for its arguments held to the schema
	// Deferred is a tool the client marked defer_loading: Claude Code's
	// tools that ToolSearch loads, offered from where they were loaded
	// (Part.Loads), not from the start (#2660)
	Deferred bool
}

Tool is a function the model may call.

type Totals added in v0.1.38

type Totals struct {
	Requests int `json:"requests"` // answered, one way or the other
	Rerouted int `json:"rerouted"` // tries that failed and handed the request on
	Errors   int `json:"errors"`   // requests whose agent got an error
}

Totals count the requests routed since the gateway started.

type TraceBy added in v0.1.1294

type TraceBy struct {
	Pid    int    `json:"pid"`
	Serves string `json:"serves"`
}

TraceBy names the magpie a trace was read from.

type TraceState added in v0.1.38

type TraceState struct {
	Seq    int64   `json:"seq"`
	Routes []Route `json:"routes"`
	Totals Totals  `json:"totals"`
	// IDs are every route the trace keeps now, changed or not: a page that
	// stopped reading while out of sight drops a request it last heard of
	// under way that has since ended and gone from the trace
	IDs []int64 `json:"ids,omitempty"`
	// By is the magpie whose routing this is, when it is another magpie's
	// (OwnerTrace): the console names it from here, so the name follows the
	// trace when another magpie takes the gateway over (#2606)
	By *TraceBy `json:"by,omitempty"`
	// Lifted is when each rest lifted before its time was lifted, by the
	// key it rested by (Rest.Key): the routes kept from before still say
	// it rested, and the page shows it resting no more
	Lifted map[string]time.Time `json:"lifted,omitempty"`
}

TraceState is the routes changed since a seq, and the totals.

func OwnerTrace added in v0.1.1294

func OwnerTrace(ctx context.Context, after int64, wait time.Duration) (TraceState, bool)

OwnerTrace reads the routing the magpie serving the gateway's address has decided, for a magpie on this computer that doesn't serve it: its console reads this and shows the same Routing page (#2606: the trace is the serving process's alone, so a second magpie showed none of it). ok is false when nothing answers there, or a magpie too old to tell its trace, or one that refuses: unknown, never an empty trace.

type Try added in v0.1.38

type Try struct {
	ID     string `json:"id"`
	Model  string `json:"model,omitempty"`  // the model it was asked for: a group's members may share a provider's keys
	Effort string `json:"effort,omitempty"` // the reasoning it was sent at, fitted to its model's levels; "" for none
	Picked bool   `json:"picked,omitempty"` // Effort is the turn's pick, in place of the agent's
	// Fixed: the effort the group's member it went to is fixed at, which
	// Effort is (fitted to the model's levels) whatever was asked
	Fixed string `json:"fixed,omitempty"`
	// RuleEffort: the reasoning the group's rule asks the member for
	// (Rule.UseEffort, #2633), which Effort is whatever was asked
	RuleEffort string    `json:"ruleEffort,omitempty"`
	Fast       bool      `json:"fast,omitempty"` // sent in its vendor's fast mode, as the group's member it went to is
	Start      time.Time `json:"start"`
	Done       bool      `json:"done"`
	Status     int       `json:"status,omitempty"`
	Millis     int64     `json:"ms,omitempty"`
	// TTFT: ms from Start to its reply's first content, FirstText to its
	// first text, when it streamed any (#196)
	TTFT      int64 `json:"ttft,omitempty"`
	FirstText int64 `json:"firstText,omitempty"`
	// SentBy: what sent its request to the vendor when magpie's own
	// client didn't, so it has no Net and the Routing page says why
	// (sentBy)
	SentBy string `json:"sentBy,omitempty"`
	// FirstReasoning is the start of paced visible reasoning, absent for hidden reasoning.
	FirstReasoning  int64 `json:"firstReasoning,omitempty"`
	ReasoningHidden bool  `json:"reasoningHidden,omitempty"`
	// Flow: the ms its content took to come (Call.Flow)
	Flow int64 `json:"flow,omitempty"`
	// Served: the model its reply said answered, when it named one;
	// Swapped: another model than Model, not just its dated name; Routed:
	// Model is another magpie's routing group, and Served the member it
	// routed to (usage.GroupRouted)
	Served  string `json:"served,omitempty"`
	Swapped bool   `json:"swapped,omitempty"`
	Routed  bool   `json:"routed,omitempty"`
	// Upstream: the provider an aggregator said answered behind it
	// (OpenRouter's DeepInfra, Novita …)
	Upstream string `json:"upstream,omitempty"`
	// Pin: the upstream the try asked the Cline API to serve it from
	// (provider.ClinePassAsked), "" when it asked for none
	Pin string `json:"pin,omitempty"`
	// Tier: the service tier it went out at, once a fast pick or an
	// account without Ultrafast had changed it; TierServed: the one its
	// reply said it ran at, when it said one (#1784)
	Tier       string `json:"tier,omitempty"`
	TierServed string `json:"tierServed,omitempty"`
	Fail       string `json:"fail,omitempty"` // why it failed, as rest tells it
	Error      string `json:"error,omitempty"`
	Rest       *Rest  `json:"rest,omitempty"`  // how long it now sits out; none when it was the last to try
	Again      int64  `json:"again,omitempty"` // ms waited before it was tried again, the last one left
	// Replan: every member had failed in a way that passes, so after
	// Again the Replan of them that may answer by then were asked again,
	// in turn, within the group's Patience (seconds) for the request
	// (#1418)
	Replan   int `json:"replan,omitempty"`
	Patience int `json:"patience,omitempty"`
	// Gone: the agent canceled the request in the pause Again was to be
	// waited, so nobody was asked again (#1894: the Routing page's story
	// otherwise ended on "tried again in 1s", a retry that never came)
	Gone bool `json:"gone,omitempty"`
	// Earlier: the last try, its allowance run out, whose error the agent
	// wasn't told: it got the first failure before it that wasn't an
	// allowance's (Discord, waroy). Whether a try went on is the next
	// try in Tries, which is appended only as it is asked (#2281)
	Earlier bool `json:"earlier,omitempty"`
	// Queued: ms it waited for one of its key's or account's slots, the
	// provider's MaxConcurrency out already (concurrency.go)
	Queued int64 `json:"queued,omitempty"`
	// Net: where its time went up to its reply's first byte (TryNet)
	Net *TryNet `json:"net,omitempty"`
	// Reset: its week used up and nobody else left, one of the account's
	// Codex resets was spent by itself (the user's setting) — on Who, and
	// what spending it did — and the request asked again
	Reset *AutoReset `json:"reset,omitempty"`
	// Credits: a Codex account that holds credits, refused as out of its
	// allowance, was asked again at once, for the vendor to spend its
	// credits on the turn (creditsAgain)
	Credits bool `json:"credits,omitempty"`
	// Auto: the models Copilot's Auto picked for it, in turn — where each
	// pick came from and Copilot's refusal of it — Model being "auto"
	Auto []provider.AutoPick `json:"auto,omitempty"`
}

Try is one candidate trying the request.

type TryNet added in v0.1.1260

type TryNet struct {
	// Own: magpie's, from the try's Start to its request going out, the
	// queue for a slot (Try.Queued) left out
	Own float64 `json:"own,omitempty"`
	// Before: requests made on the way before the last one, from the
	// first's going out to the last's (a token refreshed, a request
	// asked again); Asks counts them all, the last one too
	Before float64 `json:"before,omitempty"`
	Asks   int     `json:"asks,omitempty"`
	// Pool: waiting for a connection that wasn't dialed for it, the
	// client's limit per host out; DNS, Connect and TLS are a new
	// connection's; Reused: an open connection carried it, none of the
	// three spent
	Pool    float64 `json:"pool,omitempty"`
	DNS     float64 `json:"dns,omitempty"`
	Connect float64 `json:"connect,omitempty"`
	TLS     float64 `json:"tls,omitempty"`
	Reused  bool    `json:"reused,omitempty"`
	// Send: writing the request, headers and body, on the connection
	Send float64 `json:"send,omitempty"`
	// Wait: the vendor's, from the request written to its reply's first
	// byte (its headers)
	Wait float64 `json:"wait,omitempty"`
	// Head: from the try's Start to that first byte, which the try's TTFT
	// (to the reply's first content) is counted from too
	Head float64 `json:"head,omitempty"`
}

TryNet is where a try's time went up to its reply's first byte, as Go's HTTP client saw the request that went out to the vendor last (a sign-in refreshed or a request asked again on the way are Before): what was magpie's, the network's and the vendor's, so a slow turn says whose it was (Discord, Magic_zero: "网关连接提供商和回复到agent的速度 有点慢"). Each is in ms, to a tenth; absent for a try whose request went out some other way (a plugin's own fetch, an agent's app).

type TurnEnd added in v0.1.1191

type TurnEnd struct {
	Agent   string // magpie's id for it: claude, codex, opencode …
	Session string // the agent's session id, "" when it sends none
	Folder  string // the folder it says it works in, "" when it doesn't
	Took    time.Duration
}

TurnEnd is a turn that ran at least as long as Settings' TurnDoneAlert.

type Usage

type Usage struct {
	Input      int `json:"input"`
	Output     int `json:"output"`
	CacheRead  int `json:"cache_read"`
	CacheWrite int `json:"cache_write"`
	// CacheWrite1h is how many of the CacheWrite tokens were written to
	// be kept for an hour, which Anthropic bills at 2× input where a
	// 5-minute write is 1.25×, when its usage says so (cache_creation's
	// ephemeral_1h_input_tokens)
	CacheWrite1h int `json:"cache_write_1h,omitempty"`

	Reasoning int `json:"reasoning"`
	// Served: the model the vendor's reply says answered, when it named
	// one — which may not be the one it was asked for
	Served string `json:"served,omitempty"`
	// Upstream: the provider an aggregator says answered behind it
	// (OpenRouter's "provider": DeepInfra, Novita …), when it says one
	Upstream string `json:"upstream,omitempty"`
	// RequestID: the id the vendor gave the request, from its reply's
	// headers (Claude Code's own for a subscription); ErrType: what a
	// failed request's error body called the error
	RequestID string `json:"request_id,omitempty"`
	// ResponseID is the final client response ID, independent of request headers.
	ResponseID string `json:"response_id,omitempty"`
	ErrType    string `json:"err_type,omitempty"`
	// Stop is why the upstream said its reply ended, in its own words
	// (stop_reason, finish_reason, a Responses status): "" when it said
	// none, as a stream that just stops does (upstreamStop)
	Stop string `json:"stop,omitempty"`
	// Tier is the service tier the reply says it ran at (upstreamTier),
	// "" when it says none
	Tier string `json:"tier,omitempty"`
	// Deferred is what the reply counted of earlier requests of its
	// conversation, which their own replies couldn't (cUsage's
	// MagpieDeferred): billed with this one, never told as its prompt
	Deferred *Usage `json:"deferred,omitempty"`
	// Credits is what the reply said the request cost in its plan's own
	// credits, nil when it said none: WorkBuddy's usage.credit, the
	// figure its app shows on each reply as "Credits Consumed" (#2512)
	Credits *float64 `json:"credits,omitempty"`
	// contains filtered or unexported fields
}

Usage counts tokens.

type Weighed added in v0.1.38

type Weighed struct {
	ID       string  `json:"id"` // what rests after a failure
	Provider string  `json:"provider"`
	Name     string  `json:"name"` // the provider's
	Icon     string  `json:"icon,omitempty"`
	Preset   string  `json:"preset,omitempty"`
	Who      string  `json:"who,omitempty"` // the account, or the key's name or its masked self
	Kind     string  `json:"kind"`          // "account", "key", or "provider" when it has one
	Agent    string  `json:"agent,omitempty"`
	Plan     string  `json:"plan,omitempty"`
	Model    string  `json:"model"`
	Fixed    string  `json:"fixed,omitempty"` // the effort the group's member it is of is fixed at
	Fast     bool    `json:"fast,omitempty"`  // the group's member it is of is sent fast
	Routing  string  `json:"routing"`         // its provider's: "", order, rotate, usage
	Fallback bool    `json:"fallback,omitempty"`
	Shared   bool    `json:"shared,omitempty"` // its provider has more than one on
	Known    bool    `json:"known,omitempty"`  // the vendor said what the account has left
	Learns   bool    `json:"learns,omitempty"` // not known, but its answer will tell
	Used     float64 `json:"used"`             // share of the allowance counting the model, used
	// Amount of Limit in Unit: the count that share is of, when the
	// vendor counts it so (WorkBuddy's credits, #659)
	Amount float64 `json:"amount,omitempty"`
	Limit  float64 `json:"limit,omitempty"`
	Unit   string  `json:"unit,omitempty"`
	// Balance is a prepaid wallet's left in Unit (left.bal, #3950): the
	// Routing page tells the figure, not a share
	Balance  *float64          `json:"balance,omitempty"`
	Renews   []time.Time       `json:"renews,omitempty"`   // when those windows renew, the biggest first
	Pace     float64           `json:"pace,omitempty"`     // remaining allowance per hour until its window resets
	Due      *time.Time        `json:"due,omitempty"`      // when the allowance window used for pace resets
	Tokens   float64           `json:"tokens,omitempty"`   // least used: tokens it served lately
	Free     bool              `json:"free,omitempty"`     // its model costs nothing there (free first)
	LateTTFT float64           `json:"lateTtft,omitempty"` // speed first: its ms to the first token lately, 0 if not measured (speed.go)
	LateTPS  float64           `json:"lateTps,omitempty"`  // speed first: its tokens a second lately, 0 if not told
	Price    *SeatPrice        `json:"price,omitempty"`    // cheapest first: what its model costs on it now, nil if not known
	Turn     bool              `json:"turn,omitempty"`     // in turn: it was this one's turn
	Fit      int               `json:"fit,omitempty"`      // keyFit
	Speaks   provider.Protocol `json:"speaks,omitempty"`   // a key made for one protocol only
	Rest     *Rest             `json:"rest,omitempty"`     // resting after a failure, when the request came
	Unlisted bool              `json:"unlisted,omitempty"`
	// Window: left out as the request is longer than this, its model's
	// context window (roomy), unless every one with room is out of its
	// allowance (#3749)
	Window int `json:"window,omitempty"`
	// DueBy: "reset" when Due is when an auto-used Codex reset about to
	// run out starts the windows again, sooner than they renew (#717)
	DueBy string `json:"dueBy,omitempty"`
	// Restarts: when that reset starts them again, set when it is sooner
	// than its biggest window renews — Smart goes by it then (#718)
	Restarts *time.Time `json:"restarts,omitempty"`
	// Barred: left out as the user set it not to serve the model, its
	// own list of models leaving it out (#474)
	Barred bool `json:"barred,omitempty"`
	// Held: left out as the gateway key asking may not use its account or
	// key (#905), or a routing group it was reached through is held to
	// other accounts (Group.Accounts): HeldBy names that group
	Held   bool   `json:"held,omitempty"`
	HeldBy string `json:"heldBy,omitempty"`
	// Capped: left out as held at the usage cap the user set on the
	// account, this cap in percent; Used is then its fullest window's
	// share, CapBack when the last window at or past it renews
	Capped  int        `json:"capped,omitempty"`
	CapBack *time.Time `json:"capBack,omitempty"`
	// NoCredits: held at 100% (Capped), a Codex account the user set not
	// to spend its credits once its allowance is used up
	NoCredits bool `json:"noCredits,omitempty"`
	// Unread: held (Capped) by a careful provider as its usage can't be
	// told, why: not read yet, the read failed, or too old near its cap
	// (provider.Provider.CapCareful)
	Unread string `json:"unread,omitempty"`
	// Credits: a Codex account that goes on past its allowance on its
	// credits, and is let spend them: all but used up, it still answers,
	// and goes before those used up with nothing to go on with
	Credits bool `json:"credits,omitempty"`
	// CreditsLast: such an account, on its credits now, that the user set
	// to spend them only after everything else: tried after every
	// candidate not on its credits (restLast)
	CreditsLast bool `json:"creditsLast,omitempty"`
	// Busy: the load its plugin reported for the model, a percent over
	// the user's settings.BusyLoad, so it was tried after every ready
	// candidate that isn't (restLast)
	Busy float64 `json:"busy,omitempty"`
	// CreditsFirst: such an account (Credits) the user set to spend its
	// credits before another account: all but used up, it keeps its
	// place, new conversations and kept ones included
	CreditsFirst bool `json:"creditsFirst,omitempty"`
	// Rank: its place in its provider's own list of accounts or keys, the
	// order the provider's page shows and a drag sets (#217); routing may
	// weigh them in another
	Rank int `json:"rank,omitempty"`
	// Aside: a key made for another protocol than the keys routed over,
	// tried only after them
	Aside bool `json:"aside,omitempty"`
	// Reserve: an account or key held back, its provider's accounts at
	// once (provider.AtOnce, this many) taken by those before it in the
	// user's order: tried, aside, only after they all failed
	Reserve int `json:"reserve,omitempty"`
	// NoURL: its keys are all set to this protocol, which its provider has
	// no URL for, so it was tried on the URLs it has (#1702)
	NoURL provider.Protocol `json:"noURL,omitempty"`
	// Via: the groups in the group it is of, outermost first, when it is
	// of a group in the group asked for
	Via []string `json:"via,omitempty"`
	// UsedRenews: when the window Used is the share of renews, apart
	// from Renews' biggest first: a row says the two together, so of one
	// window, a Factory account's week and not its month (#1778)
	UsedRenews *time.Time `json:"usedRenews,omitempty"`
	// Sunk: when it was rate limited with quota left, sending it to the
	// back of an order that sinks (sink.go); nil when it didn't, or the
	// order doesn't sink
	Sunk *time.Time `json:"sunk,omitempty"`
}

Weighed is one account or key as routing weighed it.

Source Files

Jump to

Keyboard shortcuts

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