settings

package
v0.1.1049 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package settings keeps the few preferences the desktop app has: which palette to paint with, which language to speak, how the agents are arranged. Everything else magpie knows is derived from the agents' own files.

The file is ~/.config/magpie/settings.json; a missing file means "follow the system" for both.

Index

Constants

View Source
const AnyProvider = "*/"

AnyProvider begins a ModelPrices key that prices a model whichever provider it came through, its id lower-cased after it.

View Source
const DefaultPort = 3425

DefaultPort is the gateway's port unless Settings or MAGPIE_ADDR say another.

View Source
const WorkingWindow = 272000

WorkingWindow is the context window Codex and Claude Code are told for a model with a larger one, unless FullContext: Codex's own for OpenAI's models that can take more.

Variables

View Source
var (
	Themes     = []string{"system", "light", "dark"}
	Langs      = []string{"system", "en", "zh", "ja", "de"}
	Trays      = []string{"panel", "window"}
	Currencies = []string{"usd", "cny"}
	// Warmups are CodexWarmup's and ClaudeWarmup's values, off as "".
	Warmups = []string{"", "week", "all"}
	// TrayEvery are TrayUsageEvery's values, in minutes.
	TrayEvery = []int{1, 3, 5, 10, 30}
	// UpdateEveries are UpdateEvery's values, in minutes.
	UpdateEveries = []int{30, 60, 360, 1440}
	// TextSizes are TextSize's values, in percent. None is under 100: the
	// webviews' zoom on Windows and Linux (Wails' SetZoom) goes no lower.
	TextSizes = []int{100, 110, 125, 150}
)

Themes and Langs are the accepted values, in the order the UI offers them.

View Source
var DefaultTextSize = func() int {
	if runtime.GOOS == "windows" || runtime.GOOS == "linux" {
		return 110
	}
	return 100
}

DefaultTextSize is the text size of settings that have never had one saved. Windows' and Linux's body text is 14px against magpie's 13px at 100%, a size smaller than what is around it there, so they start at 110% (#914); the Mac's is 13px, as magpie's. A size once saved, 100% too, is kept as it is. A var so tests can be any system.

Functions

func Arrange added in v0.1.60

func Arrange[T any](s Settings, items []T, id func(T) string) (shown, hidden []T)

Arrange puts items in the order the user gave the agents, those named first and the rest after in the order they came, and splits off the hidden ones, which keep that order too. id names an item's agent.

func CarryPerModel added in v0.1.496

func CarryPerModel(in, cur *Settings)

CarryPerModel puts cur's per-model maps into in's, whole as they are: the ones a page that sends only its own choices would otherwise save as nothing, and so lose. Every per-model map is carried, whichever page wrote it, so a map added to the settings later needs nothing said of it here.

func CheckModelKey added in v0.1.496

func CheckModelKey(what, key string) error

CheckModelKey is whether a key of one of the per-model maps names a model the way all of them do: "<provider id>/<model id>" — or "<provider id>/*" for all of that provider's models. A model id may have slashes of its own (vendor/model), so only the first one ends the provider's id. what names the setting being checked, for the error.

It is the one rule a model key is held to, and it lives here, beside the maps it keys. Every change that takes such a key from the user checks it here rather than spelling the shape out again, so what is written into a map and what is refused come out of the same rule — one rule, and not one each branch can drift from on its own.

func CheckModelPrice added in v0.1.504

func CheckModelPrice(key string, m ModelPrice) error

CheckModelPrice is whether a price the user gives is one magpie will bill a call at: the key names a model the way the per-model maps key one, and every part of the price is a number a vendor could charge, naming the first that is not. It is where a price is checked rather than in Save: one a hand edit left broken in the file is skipped where it is read, and must not stop an unrelated setting from being saved. That covers a part that is missing, which is what a file can be edited into: JSON has no NaN or Infinity, and Load discards the whole file rather than half of it, so neither reaches here. Both are still refused, from a price typed in or passed in.

func CheckPort added in v0.1.950

func CheckPort(p int) error

CheckPort says what is wrong with a port for the gateway: one from 1024 to 65535 (below that a system wants an administrator to listen on it), or 0 for the default.

func CheckProxy added in v0.1.418

func CheckProxy(p string) error

CheckProxy says whether p is a proxy setting magpie takes: "" (follow), "direct", or an http://, https:// or socks5:// address (host:port meaning http). The global Proxy and a provider's own are both checked with it.

func Clock added in v0.1.289

func Clock(at string) (hour, min int, ok bool)

Clock reads a time of day, "06:00" (seconds, as a time field may send them, are dropped), as its hour and minute.

func Dir

func Dir() string

Dir is the folder every magpie file lives in: the data folder beside a portable magpie (appdir.Portable), else ~/.config/magpie.

func GatewayAddr added in v0.1.950

func GatewayAddr() string

GatewayAddr is where the gateway listens: MAGPIE_ADDR when it is set, else the port Settings has, on loopback (Magic_zero on Discord: 3425 was taken, and a port of one's own is easier to tell apart).

func Migrate

func Migrate()

Migrate carries the files of an install that predates the name over: ~/.config/dial and ~/.cache/dial become ~/.config/magpie and ~/.cache/magpie. It copies rather than moves, so a dial that is still running keeps working, and it only fills folders that do not exist yet. The old folders can be deleted once nothing uses them. A portable magpie has only its own data folder and copies nothing in.

func Path

func Path() string

Path is the settings file.

func PerModelKeys added in v0.1.496

func PerModelKeys(s *Settings, fn func(name string, m reflect.Value))

PerModelKeys calls fn with the name of every per-model map of s and the map itself, the settings' own values and not copies, so fn may change them (see ModelNames). A field that is not per-model is not passed; the name comes with the map so a caller that reports on the maps it was given can tell them apart.

func Portable added in v0.1.630

func Portable() string

Portable is the data folder of a portable magpie, or "" when installed.

func Save

func Save(s Settings) error

Save validates and writes the settings.

func SavedAddr added in v0.1.950

func SavedAddr() string

SavedAddr is GatewayAddr with MAGPIE_ADDR left aside: the address of the magpie whose settings these are, which one the variable moves (magpie-dev, a sandbox) runs beside.

Types

type ModelPrice added in v0.1.504

type ModelPrice struct {
	Input      *float64 `json:"input,omitempty"`
	Output     *float64 `json:"output,omitempty"`
	CacheRead  *float64 `json:"cache_read,omitempty"`
	CacheWrite *float64 `json:"cache_write,omitempty"`
	// CacheWrite1h is a 1-hour cache write's price, absent where none is
	// given: such a write is then counted at 2× input for a Claude model,
	// else at the 5-minute price (catalog.OneHourFor).
	CacheWrite1h *float64 `json:"cache_write_1h,omitempty"`
	// Tiers are the prices of a request whose input is over a size, each
	// whole: "magpie model price … --tier 272k …" (PAMI on Discord).
	Tiers []catalog.Tier `json:"tiers,omitempty"`
}

ModelPrice is the price of one model as the user states it. Each part is a pointer so that a file leaving one out is told so rather than billing that part of the call at zero: a model is priced whole or not at all.

func StatedPrice added in v0.1.1032

func StatedPrice(p catalog.Price) ModelPrice

StatedPrice is a price as ModelPrices keeps it: every part given, the 1-hour cache write only when it is.

func (ModelPrice) Price added in v0.1.504

func (m ModelPrice) Price() (catalog.Price, string)

Price is the price the user stated, when every part of it is given and is a number a vendor could charge. The second return names the first part that is not, empty when the price is usable.

type OTel added in v0.1.602

type OTel struct {
	Enabled  bool              `json:"enabled,omitempty"`
	Endpoint string            `json:"endpoint,omitempty"`
	Headers  map[string]string `json:"headers,omitempty"`
	Metrics  bool              `json:"metrics,omitempty"`
	// Sessions follows newly recorded local Codex and Pi interactions.
	Sessions bool `json:"sessions,omitempty"`
	// Bodies adds each call's request and reply, as the gateway captured
	// them (secrets masked, cut at 256 KiB), to its span as Langfuse's
	// observation input and output (#538); off, only metadata leaves
	Bodies bool `json:"bodies,omitempty"`
	// BodiesWhole keeps those bodies entire, not cut at 256 KiB: the reply
	// is written to a temporary file as it streams and read back for the
	// export, so a long prompt or reply reaches the trace whole. Only
	// meaningful with Bodies on
	BodiesWhole bool `json:"bodiesWhole,omitempty"`
}

OTel is the optional OTLP/HTTP metadata export. Endpoint is the base URL, including /api/public/otel for Langfuse; signals append /v1/traces or metrics.

func OTelExport added in v0.1.602

func OTelExport() (OTel, error)

OTelExport applies explicit MAGPIE_OTEL_* overrides without changing the saved preferences. Merely setting an endpoint never enables export.

func (OTel) Check added in v0.1.602

func (o OTel) Check() error

type Settings

type Settings struct {
	Theme string `json:"theme,omitempty"` // system | light | dark
	Lang  string `json:"lang,omitempty"`  // system | en | zh
	Tray  string `json:"tray,omitempty"`  // what clicking the tray icon opens: panel | window
	// SessionTerminal is the Mac app that opens a resumed session, by bundle
	// id. "" and "system" follow the .command file association.
	SessionTerminal string `json:"sessionTerminal,omitempty"`
	// Currency is what a cost — the Usage page's, the tray panel's, the
	// TUI's and the CLI's — is shown converted to: usd (its native
	// currency, list prices being in dollars) or cny, at a live exchange
	// rate (see internal/fx). A vendor's own balance, already in its own
	// currency (a Chinese relay's ¥), is never touched by this.
	Currency string `json:"currency,omitempty"`
	// ChineseUnits shortens a large count in 万 and 亿 when magpie speaks
	// Chinese (8000 万 rather than 80M); otherwise it is in K, M and B, as
	// prices per million tokens and context windows (200K, 1M) are, in
	// Chinese too (#740). It means nothing in English. It replaces
	// westernUnits, which asked for K/M/B: what that chose is now the
	// default, so an old file's is left unread.
	ChineseUnits bool `json:"chineseUnits,omitempty"`
	// Dock keeps magpie in the Mac's Dock as well as the menu bar, for a
	// menu bar too full to show its icon.
	Dock bool `json:"dock,omitempty"`
	// DockWindow shows it in the Dock only while its window is open, so
	// Cmd-Tab reaches the window without an icon kept there the rest of
	// the time. Dock wins over it.
	DockWindow bool `json:"dockWindow,omitempty"`
	// Proxy for magpie's own requests to vendors: "" follows the
	// environment and then the system, "direct" uses none, anything else
	// is the proxy (http://, https:// or socks5://; host:port means http).
	Proxy string `json:"proxy,omitempty"`
	OTel  OTel   `json:"otel,omitempty"`
	// GitHubToken is a GitHub token the library's requests to GitHub's
	// API carry, raising its rate limit from 60 requests an hour to 5,000.
	// It is a secret: the Settings page is told only a masked one, and a
	// backup or sync without keys leaves it out, as it does LANKey.
	GitHubToken string `json:"githubToken,omitempty"`
	// Redact keeps secrets in what agents send (API keys, private keys,
	// tokens, passwords) from the vendors behind magpie: they go as
	// placeholders, and come back as they were. RedactPersonal does the same
	// for emails, phone numbers and ID and bank card numbers, and
	// RedactWords for the user's own words. RedactRules are the user's own
	// rules for secrets magpie's don't know (a gateway's oc_sk_… key), a
	// prefix or a pattern each, masked with the secrets while Redact is on.
	Redact         bool          `json:"redact,omitempty"`
	RedactPersonal bool          `json:"redactPersonal,omitempty"`
	RedactWords    []string      `json:"redactWords,omitempty"`
	RedactRules    []redact.Rule `json:"redactRules,omitempty"`
	// LAN shares the gateway on the local network; remote callers must use
	// named caller keys. LANKey is retained for older Magpie versions.
	LAN    bool   `json:"lan,omitempty"`
	LANKey string `json:"lanKey,omitempty"`
	// Port is the gateway's port on this computer, 0 for DefaultPort.
	// MAGPIE_ADDR, where it is set, comes first (GatewayAddr).
	Port int `json:"port,omitempty"`
	// LANKeyID remembers the default named key created when sharing is enabled.
	LANKeyID string `json:"lanKeyId,omitempty"`
	// RequestArchive keeps each call the gateway serves — its headers and
	// bodies both ways, secrets taken out — in the S3 bucket sync keeps
	// its backup in (gateway/archive.go), for looking into a request later.
	RequestArchive bool `json:"requestArchive,omitempty"`
	// RequestArchiveMaxMB is how much of each body the archive keeps, in
	// MiB: 0 for 32, at most 1024 (#447)
	RequestArchiveMaxMB int `json:"requestArchiveMaxMB,omitempty"`
	// CodexWarmup starts a ChatGPT account's next window as soon as the
	// last one resets, with one tiny request, so it counts from then (a
	// Codex window starts at its first use): "" off, "week" the weekly
	// window, "all" the 5-hour one too.
	CodexWarmup string `json:"codexWarmup,omitempty"`
	// ClaudeWarmup is CodexWarmup for the Claude accounts, the request
	// sent through Claude Code.
	ClaudeWarmup string `json:"claudeWarmup,omitempty"`
	// CodexWarmAt starts each ChatGPT account's 5-hour window at a time of
	// day of the user's choosing, local "15:04", with the same tiny
	// request: an account whose 5-hour window isn't running then gets one,
	// so the windows line up with the day (06:00 gives three by 21:00, where
	// the first use at 9 gives two by the end of it); "" off. It works
	// with CodexWarmup or without it. ClaudeWarmAt is the Claude accounts'.
	CodexWarmAt  string `json:"codexWarmAt,omitempty"`
	ClaudeWarmAt string `json:"claudeWarmAt,omitempty"`
	// CodexAutoReset are the ChatGPT accounts (lower-case) that spend one
	// of their rate-limit resets by themselves once their weekly window is
	// used up and no other account can take the request: at most one a
	// week each (see provider.AutoUseCodexReset); and one about to run out
	// unused half an hour before it does, or at once when the account is
	// held up past then (provider.SpendExpiringCodexResets).
	CodexAutoReset []string `json:"codexAutoReset,omitempty"`
	// WorkBuddyCheckin presses WorkBuddy's daily check-in (签到) for each
	// signed-in WorkBuddy (China) account once a Beijing day, claiming the
	// credits it gives while its event runs.
	WorkBuddyCheckin bool `json:"workbuddyCheckin,omitempty"`
	// TraeCheckin presses Trae CN's daily check-in (每日签到) for each
	// signed-in Trae CN account (its plugin's) once a Beijing day, claiming
	// the credits it gives.
	TraeCheckin bool `json:"traeCheckin,omitempty"`
	// MiniMaxCheckin presses MiniMax Code's daily check-in (签到) for each
	// signed-in MiniMax Code (China) account (its plugin's) once a Beijing
	// day, claiming the credits it gives (#811).
	MiniMaxCheckin bool `json:"minimaxCheckin,omitempty"`
	// MemberModel has a reply's model name the routing group's member
	// that answered, as magpie's provider/model id (workbuddy/glm-5.3-flash),
	// rather than the vendor's own name for it, for agents that count
	// usage by the reply's model (#822). Claude Code, Claude Desktop and
	// Codex always get the vendor's name: they read it themselves.
	MemberModel bool `json:"memberModel,omitempty"`
	// NoStats stops the one event a day that counts magpie's users (see
	// internal/stats).
	NoStats bool `json:"noStats,omitempty"`
	// NoUpdatePill keeps the header's Update pill away when a newer magpie
	// is out; UpdateSkip is the one version it was hidden for, and a newer
	// one brings it back. Either way magpie still downloads the version and
	// puts it in as it quits, and Settings' version row still offers it.
	NoUpdatePill bool   `json:"noUpdatePill,omitempty"`
	UpdateSkip   string `json:"updateSkip,omitempty"`
	// NoAutoUpdate stops magpie asking for a newer version by itself, and
	// so downloading one (#472): only Settings' Check, or magpie update,
	// asks then. UpdateEvery is how often it asks otherwise, in minutes:
	// one of UpdateEveries, 0 for every six hours.
	NoAutoUpdate bool `json:"noAutoUpdate,omitempty"`
	UpdateEvery  int  `json:"updateEvery,omitempty"`
	// UpdateMirror is a GitHub download mirror an update's file is fetched
	// through, its prefix put before the release's github.com URL
	// (https://mirror.example/https://github.com/…): "" for none, which is
	// the default — magpie names no mirror of its own. The file is still
	// checked against the SHA-256 the update feed at usemagpie.ai gives,
	// never one from the mirror. magpie update mirror sets it.
	UpdateMirror string `json:"updateMirror,omitempty"`
	// Vision is the model that describes an image to a model that can't see
	// it: a model's id (provider/model, group/<id>), "off" to turn such an
	// image away, or empty for one magpie picks (see gateway.seer).
	Vision string `json:"vision,omitempty"`
	// ImageGen is the model magpie's generate_image tool draws with (the
	// gateway's /v1/images/generations when a request names no model): a
	// model's id, "off", or empty for one magpie picks (gateway.drawer).
	// "off" turns the video a request that names no model gets off too
	// (gateway.videomaker).
	ImageGen string `json:"imageGen,omitempty"`
	// Searcher is the provider that searches the web for a model that
	// can't: "<provider>" with the small model magpie picks of it,
	// "<provider>/<model>", or empty for the one magpie picks
	// (gateway.searcher). One that is gone, off or can't search gives way
	// to magpie's pick.
	Searcher string `json:"searcher,omitempty"`
	// TrayUsages are the subscriptions and plans whose windows are shown
	// beside the tray icon, in the order shown, each by its provider and
	// account ("claude|a@b.c"); none when empty.
	TrayUsages []string `json:"trayUsages,omitempty"`
	// TrayUsage is TrayUsages' first, all a magpie before them read: a file
	// with it and no TrayUsages shows that one, and it is kept written for
	// an older magpie to go on showing it.
	TrayUsage string `json:"trayUsage,omitempty"`
	// TrayUsageEvery is how often, in minutes, that text is brought up to
	// date; 0 is every 3 (one of TrayEvery).
	TrayUsageEvery int `json:"trayUsageEvery,omitempty"`
	// TrayNoLogos draws the Mac menu bar's cards without their logos: each
	// is its windows stacked alone, a thin line between one card and the
	// next.
	TrayNoLogos bool `json:"trayNoLogos,omitempty"`
	// TrayNoBird leaves magpie's bird out of the Mac menu bar while the
	// cards are there, the cards alone (KevinXC on Discord); a click on one
	// still opens the panel, and with no cards the bird is shown.
	TrayNoBird bool `json:"trayNoBird,omitempty"`
	// Lightweight lets the webview of a window closed — the tray panel or
	// the main window — go once it has stayed closed a while, and makes it
	// again when it is opened (#580): less memory, a moment's wait. This
	// computer's own (KeepOwn).
	Lightweight bool `json:"lightweight,omitempty"`
	// KeepAwake keeps this computer from going to sleep by itself while
	// agents work through the gateway and for a while after (xiao_wang24004
	// on X; internal/awake). This computer's own (KeepOwn).
	KeepAwake bool `json:"keepAwake,omitempty"`
	// GatewayMode is whether `magpie web` shows only what a gateway serving
	// other machines needs (Player on Discord): "on", "off", or "" to
	// decide by itself — on for `magpie web --gateway`, or with no agents
	// on this machine. This computer's own (KeepOwn).
	GatewayMode string `json:"gatewayMode,omitempty"`
	// QuotaLeft shows a subscription's windows by how much of each is left,
	// not used: the Usage page, the tray panel and the menu bar alike.
	QuotaLeft bool `json:"quotaLeft,omitempty"`
	// UsageAlert is how much of a subscription's or plan's window, in
	// percent, is used when magpie says so with a notification (#368):
	// once for each time the window runs, for every window routing counts
	// (not one set aside, as on-demand spending is); 0 is off.
	UsageAlert int `json:"usageAlert,omitempty"`
	// BalanceAlert is the balance a key or account has fallen to when
	// magpie says so, in that balance's own currency or credits, once until
	// it is topped up past it again; 0 is off.
	BalanceAlert float64 `json:"balanceAlert,omitempty"`
	// ResetReminder is how many hours before a renewal magpie says what
	// would be lost by it (#720): a weekly or monthly window with much of
	// it left before it renews, a reset credit unspent before it runs out;
	// once each. 0 is off.
	ResetReminder int `json:"resetReminder,omitempty"`
	// PlainNames has the model lists magpie gives agents name each model
	// by its name alone, without its provider's or "routing group" after it
	// (#335) — but for two in one list that would read the same, which keep
	// it (see provider.Labels).
	PlainNames bool `json:"plainNames,omitempty"`
	// PlainOwnNames, with PlainNames off, has those lists name a model the
	// user gave a name of their own by that name alone, just as they wrote
	// it (#92: "Opus 5.5", not "Opus 5.5 · Claude Code"), the vendor's names
	// keeping their provider's after them (see provider.Labels).
	PlainOwnNames bool `json:"plainOwnNames,omitempty"`
	// CodexAgentsV1 has the OpenAI models magpie hands Codex — the ChatGPT
	// account's own, their codex/ ids and the groups one is in — say
	// multi_agent_version "v1" (#141): their subagents are then handed
	// their tasks as text, which a magpie-served subagent can read, where
	// V2's are sealed by OpenAI's server. Codex's features.multi_agent_v2
	// still wins, and a thread keeps the version it started with.
	CodexAgentsV1 bool `json:"codexAgentsV1,omitempty"`
	// CodexTitles is where the requests Codex makes for a thread's title
	// (thread_title, thread_title_reconsideration: a hidden turn of their
	// own, on Codex's own model through its ChatGPT sign-in) go (#705): ""
	// as Codex sends them, "off" answered by magpie with no title and sent
	// nowhere, or a model's id (provider/model, group/<id>) that writes it.
	CodexTitles string `json:"codexTitles,omitempty"`
	// FullContext has Codex and Claude Code told a model's whole context
	// window. Off, a window above WorkingWindow is told as WorkingWindow,
	// so they compact a long conversation there instead of sending ever
	// more of it on every turn (X: Chen, a 1M DeepSeek model through
	// Codex and Claude Code took 70–90s to its first token at 550K):
	// what OpenAI does with its own models, 272K though they can take
	// more, and Anthropic with its, 200K unless a [1m] one is picked.
	FullContext bool `json:"fullContext,omitempty"`
	// CompactAt is the window told for a longer one when FullContext is
	// off, in tokens: 0 is WorkingWindow (#876: 272K was the only one).
	// A provider's or a model's own (ModelCompacts) comes before it.
	CompactAt int `json:"compactAt,omitempty"`
	// ChinaMirror is the Plugins page's 「国内镜像」 switch: the plugin list,
	// npm (the plugins' packages and what npm says of them) and Bun's
	// downloads are asked of mirrors in China first, and of their official
	// addresses after (see source.China).
	ChinaMirror bool `json:"chinaMirror,omitempty"`
	// TextSize is how large the window's and the tray panel's pages are
	// drawn, in percent (one of TextSizes): the webviews' own zoom, as a
	// browser's, so the text and everything around it grow together.
	TextSize int `json:"textSize,omitempty"`
	// How the agents are listed, by agent id. AgentOrder comes first, as
	// ordered; an agent it doesn't name (one installed since) follows in
	// magpie's own order. A hidden agent is folded away at the bottom of the
	// list; a shown one stays in view even while nothing is set on it, which
	// otherwise folds it away too. The agents' own files never hear of it.
	AgentOrder   []string `json:"agentOrder,omitempty"`
	AgentsHidden []string `json:"agentsHidden,omitempty"`
	AgentsShown  []string `json:"agentsShown,omitempty"`
	// UsageOrder is how the Usage page's cards are listed, by provider id,
	// as they were dragged there; one it doesn't name follows in magpie's
	// own order. Only the page's: the order providers are tried in is the
	// Providers page's.
	UsageOrder []string `json:"usageOrder,omitempty"`
	// Visible narrows the models an agent is shown, by agent id: the
	// families (the tag a provider or group is given), provider ids and
	// group ids its lists hold. An agent it doesn't name is shown them all.
	Visible map[string][]string `json:"visible,omitempty"`
	// HiddenModels are the catalog entries (their ids, "<provider>/<model>"
	// or a group's) taken out of an agent's lists one by one, by agent id,
	// after Visible: a model not named here, a new one among them, is shown.
	HiddenModels map[string][]string `json:"hiddenModels,omitempty"`
	// OrderedModels is the order an agent's lists put its models in, by
	// agent id and then entry id, as the user dragged them on the Agents
	// page (Codex's, #855): the ones named first, any other after them.
	OrderedModels map[string][]string `json:"orderedModels,omitempty"`

	// The three maps below, and every one added beside them, are the
	// per-model ones: a field named Model* whose type is a map[string]X,
	// keyed "<provider id>/<model id>" (or "<provider id>/*", for all of
	// that provider's models — CheckModelKey). That is the whole of the
	// convention, and it is what RenamePerModel and the GUI's saving of
	// the settings go by, each of them walking the fields by it rather
	// than by a list kept up to date by hand: a map added here later is
	// moved when a provider is renamed and kept when another page saves
	// the settings, with no line written for it in either place. A field
	// whose keys are not a model's is not one of these, and is not named
	// Model* — Visible, which is by agent id, among them.
	// ModelNames are the names the user gave models, by "<provider
	// id>/<model id>": agents, the gateway's model list and magpie itself
	// show them for the vendor's (see provider.SetModelName).
	ModelNames map[string]string `json:"modelNames,omitempty"`
	// ModelEfforts are the reasoning levels the user keeps of a model's,
	// by "<provider id>/<model id>": the lists magpie hands out offer only
	// those (see provider.SetModelEfforts).
	ModelEfforts map[string][]string `json:"modelEfforts,omitempty"`
	// ModelImages is whether the user said a model takes images, by
	// "<provider id>/<model id>". Absent leaves it to the vendor's list.
	ModelImages map[string]bool `json:"modelImages,omitempty"`
	// ModelPrices is what a model costs the user, in USD per million
	// tokens, by "<provider id>/<model id>", and "*" for every model of
	// that provider: a provider models.dev does not list, or one that
	// resells at a multiplier, is otherwise priced at whatever its maker's
	// list price is. "*/<model id>" (AnyProvider) is that model from any
	// provider not priced above, and a session's model named with no
	// provider at all: one whose provider is gone, or one models.dev no
	// longer lists.
	ModelPrices map[string]ModelPrice `json:"modelPrices,omitempty"`
	// ModelOutputs is the most a reply of a model may hold, by "<provider
	// id>/<model id>", and "*" for every model of that provider. Absent
	// leaves it to the vendor's own list and to models.dev, as a context
	// the user has not set is. A model's own value wins over its
	// provider's, and the agents' own files are told of either
	// (see provider.SetModelOutput).
	ModelOutputs map[string]int `json:"modelOutputs,omitempty"`
	// ModelCompacts is where Codex and Claude Code compact a conversation
	// on a model, by "<provider id>/<model id>", and "*" for every model
	// of that provider (#876): the window they are told when the model's
	// own is longer, over CompactAt and FullContext. One at or above the
	// model's window is its whole window.
	ModelCompacts map[string]int `json:"modelCompacts,omitempty"`
	// ModelWires is the name to send a vendor for a model magpie knows by
	// another, by "<provider id>/<model id>", and "*" for every model of that
	// provider. A "*" in the name is the model itself, so one name covers a
	// relay that namespaces its models — vendor-c/* asks for model-3 as
	// vendor-c/model-3 — while a name with no "*" in it sends every model of
	// that key under that one name. Everything else — the catalog agents see,
	// the routing groups, the usage records and what a call is priced at —
	// keeps the name magpie knows the model by.
	ModelWires map[string]string `json:"modelWires,omitempty"`
	// ModelAPIs is the one API a model is asked on at its provider, by
	// "<provider id>/<model id>": chat, responses or anthropic, for a relay
	// whose one key serves some models on one and others on another
	// (01huadalang on Discord). Absent leaves it to the vendor's list and
	// to each URL the provider has (see provider.SetModelAPI).
	ModelAPIs map[string]string `json:"modelAPIs,omitempty"`
	// ModelSameAs is the model another vendor sells under another name
	// that a model is, by "<provider id>/<model id>": the routing groups
	// magpie finds (provider's autoGroups) merge it with that one rather
	// than by its own id, for an id no rule of magpie's matches up
	// (kyzhouxu, #583). Absent leaves it to its id.
	ModelSameAs map[string]string `json:"modelSameAs,omitempty"`
	// The main window's size when it was last resized, width and height,
	// so it opens at it again after a restart.
	Window []int `json:"window,omitempty"`
}

Settings is what the user chose. "" and "system" both mean "follow the OS".

func Load

func Load() Settings

Load reads the settings; anything missing or unreadable is the default.

func (Settings) Compact added in v0.1.979

func (s Settings) Compact() int

Compact is where a conversation on a longer window is compacted when neither its model nor its provider says (ModelCompacts): CompactAt, else WorkingWindow, and 0 under FullContext, the model's whole window.

func (*Settings) KeepOwn added in v0.1.601

func (s *Settings) KeepOwn(cur Settings)

KeepOwn puts back cur's settings that are this computer's own, which a sync or a restored backup never brings from another: the window's size, the proxy, the gateway's port, the Dock, gateway mode, and what the menu bar or tray shows beside magpie's icon (yoooo on Discord: usage turned off on a Mac came back from a Windows box that shows it).

func (*Settings) RenamePerModel added in v0.1.496

func (s *Settings) RenamePerModel(from, to string) bool

RenamePerModel moves what the user said of a provider's models to the id it has now: in every per-model map (see ModelNames) each key beginning with from+"/" is rewritten to to+"/", and it says whether any key moved at all. A provider that changes its id keeps the names, levels, image answers and everything else given to its models, each map moved whether or not the ones before it moved anything.

func (Settings) Working added in v0.1.836

func (s Settings) Working(n int) int

Working is the context window an agent is told for a model with one of n tokens (see FullContext).

Jump to

Keyboard shortcuts

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