config

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 2, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const ActiveProviderEnv = "ZERO_PROVIDER"

ActiveProviderEnv selects the active provider profile by name (read in applyEnv).

View Source
const AnthropicBaseURL = "https://api.anthropic.com"
View Source
const GoogleBaseURL = "https://generativelanguage.googleapis.com"
View Source
const MaxTurnsCeiling = 500

MaxTurnsCeiling caps the per-run tool-turn budget so a stray env value or typo can't set an absurd ceiling. Shared between applyEnv (read site) and the /turns command (write site) so the bound holds even if the env is set by a raw shell.

View Source
const MaxTurnsEnv = "ZERO_MAX_TURNS"

MaxTurnsEnv overrides the per-run tool-turn budget by name (read in applyEnv).

View Source
const OpenAIBaseURL = "https://api.openai.com/v1"

Variables

This section is empty.

Functions

func ClearProviderKeyStored

func ClearProviderKeyStored(path, provider string) (bool, error)

ClearProviderKeyStored unsets the APIKeyStored marker for a provider in the config at path, so credential checks no longer claim a stored key after one is removed. No-op when path/provider is empty, the config is absent, or the marker is already unset.

func DefaultMCPServers

func DefaultMCPServers() map[string]MCPServerConfig

DefaultMCPServers returns the MCP servers Zero ships ENABLED by default so web search and scraping work out of the box with no setup and no API key. They are seeded before user/project config is merged (see ResolveMCP), so a user can override any field — for example point firecrawl at a self-hosted instance, or add an API-key header to lift the free-tier limit — or disable it entirely with `zero mcp disable <name>` (which writes `"disabled": true`).

Keyless Firecrawl routes requests through firecrawl.dev (1,000 free credits per month, no account). Self-host Firecrawl (AGPL-3.0) for unlimited and private use. Zero only calls it over the network, so Firecrawl's license never reaches into Zero's own code.

func DefaultUserConfigPath

func DefaultUserConfigPath() (string, error)

func ForgetProviderKey

func ForgetProviderKey(provider string) (bool, error)

ForgetProviderKey removes a provider's stored API key from the credential store, reporting whether one existed. Used by the lifecycle "remove key" / auth logout.

func HasProviderProfile

func HasProviderProfile(profile ProviderProfile) bool

func IsDefaultMCPServer

func IsDefaultMCPServer(name string) bool

IsDefaultMCPServer reports whether name is one of Zero's built-in default MCP servers. The config commands use it so a default can be disabled/enabled even though it is not written to the user's config file until overridden.

func MigratePlaintextProviderKeys

func MigratePlaintextProviderKeys(path string, store APIKeySetter) (int, error)

MigratePlaintextProviderKeys moves any inline plaintext API key in the config at path into the credential store, marking the profile APIKeyStored and stripping the inline secret — but ONLY after the store write succeeds, so a failed Set leaves the plaintext key in place and never strands a credential. Returns how many keys were migrated; a no-op (0, nil) when path is empty/absent or nothing needs migrating. Safe to run on every startup (idempotent).

func ProviderKeyStore

func ProviderKeyStore() (*credstore.Store, error)

ProviderKeyStore opens the credential store beside the default user config.

func ProviderKeyStoreAt

func ProviderKeyStoreAt(dir string) (*credstore.Store, error)

ProviderKeyStoreAt opens the encrypted credential store whose file backend lives in dir. The backend resolves keyring-first, then encrypted-file, with a plaintext opt-out via ZERO_CRED_STORAGE. The dir parameter exists so tests can point the file backend at a temp directory; production always uses the user config directory (ProviderKeyStore) because provider API keys are user-scoped by design — they are only ever captured under the user config, never project config (a cloned repo must not carry keys), so runtime lookups deliberately use the user store regardless of where a provider profile was resolved from.

func SetActiveProviderEnv

func SetActiveProviderEnv(name string)

SetActiveProviderEnv exports the active provider name to the process environment so a spawned child process (which inherits the environment) resolves the SAME provider profile — and therefore the same credentials (env key / stored key / OAuth) — as its parent. Without this a sub-agent re-resolves config.json's default provider and can land on one whose credentials don't match the parent's live selection, failing auth the instant it spawns. A blank name CLEARS the variable: switching back to an unnamed/default profile must not keep exporting a stale provider to children.

func SetMaxTurnsEnv

func SetMaxTurnsEnv(n int)

SetMaxTurnsEnv exports the per-run tool-turn budget to the process environment so a spawned child (sub-agent / swarm member, which inherits the environment) runs with the SAME budget the user set via /turns. Without it a child re-resolves config.json's default and a large delegated task can exhaust its turns mid-run (exit 4 / max-turns). No-op for n <= 0.

func ValidateBytes

func ValidateBytes(data []byte) (FileConfig, []Issue)

ValidateBytes parses data as a Zero FileConfig and runs the same semantic provider/model rules as ValidateFile. It returns the parsed config (zero value on parse failure) plus any structured issues. A parse failure yields a single issue whose Message wraps the underlying JSON error (path-less form: "invalid config JSON: <err>") so callers can extract *json.SyntaxError / *json.UnmarshalTypeError offsets via errors.As.

func ValidateFile

func ValidateFile(path string) (FileConfig, []Issue)

ValidateFile reads and parses path as a Zero FileConfig and runs the same semantic provider/model rules used during resolution. It returns the parsed config (zero value on parse failure) plus any structured issues. A parse failure yields a single issue whose Message wraps the underlying JSON error so callers can extract *json.SyntaxError / *json.UnmarshalTypeError offsets via errors.As.

Types

type APIKeyGetter

type APIKeyGetter interface {
	Get(provider string) (string, bool, error)
}

APIKeyGetter is the read surface of the credential store; *credstore.Store satisfies it. Kept here so callers can inject a fake in tests.

type APIKeySetter

type APIKeySetter interface {
	Set(provider, key string) error
}

APIKeySetter is the write surface of the credential store.

type FileConfig

type FileConfig struct {
	ActiveProvider string             `json:"activeProvider,omitempty"`
	Providers      []ProviderProfile  `json:"providers,omitempty"`
	MaxTurns       int                `json:"maxTurns,omitempty"`
	MCP            MCPConfig          `json:"mcp,omitempty"`
	Sandbox        SandboxConfig      `json:"sandbox,omitempty"`
	Notify         NotifyConfig       `json:"notify,omitempty"`
	Tools          ToolsConfig        `json:"tools,omitempty"`
	Swarm          SwarmConfig        `json:"swarm,omitempty"`
	Preferences    PreferencesConfig  `json:"preferences,omitempty"`
	LocalControl   LocalControlConfig `json:"localControl,omitempty"`
}

func LoadProviderCommand

func LoadProviderCommand(command string) (FileConfig, error)

func SetActiveProvider

func SetActiveProvider(path string, name string) (FileConfig, error)

func SetFavoriteModels

func SetFavoriteModels(path string, models []string) (FileConfig, error)

func SetProviderModel

func SetProviderModel(path string, name string, model string) (FileConfig, error)

func SetRecapsEnabled

func SetRecapsEnabled(path string, enabled bool) (FileConfig, error)

SetRecapsEnabled persists the post-turn recap preference, mirroring SetFavoriteModels (read-modify-atomic-write).

func SetTheme

func SetTheme(path string, theme string) (FileConfig, error)

SetTheme persists the TUI theme preference, mirroring SetFavoriteModels (read-modify-atomic-write). A blank theme clears the stored preference.

func UpsertProvider

func UpsertProvider(path string, profile ProviderProfile, setActive bool) (FileConfig, error)

func (FileConfig) MarshalJSON

func (cfg FileConfig) MarshalJSON() ([]byte, error)

func (*FileConfig) UnmarshalJSON

func (cfg *FileConfig) UnmarshalJSON(data []byte) error

type Issue

type Issue struct {
	FieldPath string `json:"fieldPath,omitempty"`
	Message   string `json:"message"`
}

Issue is a single structured problem found while validating a config file. Message is already routed through the package secret redaction.

type LocalControlConfig

type LocalControlConfig struct {
	Enabled      bool                     `json:"enabled,omitempty"`
	Browser      LocalControlDriverConfig `json:"browser,omitempty"`
	Desktop      LocalControlDriverConfig `json:"desktop,omitempty"`
	Terminal     LocalControlDriverConfig `json:"terminal,omitempty"`
	ArtifactsDir string                   `json:"artifactsDir,omitempty"`
	// contains filtered or unexported fields
}

LocalControlConfig controls local browser/desktop/terminal automation helpers. Helpers are discovered lazily by the tool that needs them; no setup command or background probe is required during startup.

func (LocalControlConfig) BrowserEnabled

func (cfg LocalControlConfig) BrowserEnabled() bool

func (LocalControlConfig) DesktopEnabled

func (cfg LocalControlConfig) DesktopEnabled() bool

func (LocalControlConfig) Disabled

func (cfg LocalControlConfig) Disabled() bool

func (LocalControlConfig) Empty

func (cfg LocalControlConfig) Empty() bool

func (LocalControlConfig) MarshalJSON

func (cfg LocalControlConfig) MarshalJSON() ([]byte, error)

func (LocalControlConfig) TerminalEnabled

func (cfg LocalControlConfig) TerminalEnabled() bool

func (*LocalControlConfig) UnmarshalJSON

func (cfg *LocalControlConfig) UnmarshalJSON(data []byte) error

type LocalControlDriverConfig

type LocalControlDriverConfig struct {
	Enabled    bool   `json:"enabled,omitempty"`
	HelperPath string `json:"helperPath,omitempty"`
	Driver     string `json:"driver,omitempty"`
	// contains filtered or unexported fields
}

func (LocalControlDriverConfig) Empty

func (cfg LocalControlDriverConfig) Empty() bool

func (LocalControlDriverConfig) MarshalJSON

func (cfg LocalControlDriverConfig) MarshalJSON() ([]byte, error)

func (*LocalControlDriverConfig) UnmarshalJSON

func (cfg *LocalControlDriverConfig) UnmarshalJSON(data []byte) error

type MCPConfig

type MCPConfig struct {
	Servers map[string]MCPServerConfig `json:"servers,omitempty"`
}

func ResolveMCP

func ResolveMCP(options ResolveOptions) (MCPConfig, error)

type MCPOAuthConfig

type MCPOAuthConfig struct {
	ClientID              string   `json:"clientID,omitempty"`
	ClientSecret          string   `json:"clientSecret,omitempty"`
	Scopes                []string `json:"scopes,omitempty"`
	AuthorizationEndpoint string   `json:"authorizationEndpoint,omitempty"`
	TokenEndpoint         string   `json:"tokenEndpoint,omitempty"`
	RegistrationEndpoint  string   `json:"registrationEndpoint,omitempty"`
	IssuerURL             string   `json:"issuerURL,omitempty"`
}

MCPOAuthConfig describes how to authenticate to a remote MCP server using an OAuth 2.0 + PKCE authorization-code flow. Endpoints may be discovered from the authorization server's metadata document; explicit values here override or fill in anything discovery cannot provide. Client credentials are optional when the server supports dynamic client registration.

type MCPServerConfig

type MCPServerConfig struct {
	Type     string            `json:"type,omitempty"`
	Command  string            `json:"command,omitempty"`
	Args     []string          `json:"args,omitempty"`
	Env      map[string]string `json:"env,omitempty"`
	URL      string            `json:"url,omitempty"`
	Headers  map[string]string `json:"headers,omitempty"`
	Auth     string            `json:"auth,omitempty"`
	OAuth    *MCPOAuthConfig   `json:"oauth,omitempty"`
	Disabled bool              `json:"disabled,omitempty"`
	// contains filtered or unexported fields
}

func (*MCPServerConfig) UnmarshalJSON

func (server *MCPServerConfig) UnmarshalJSON(data []byte) error

type NotifyConfig

type NotifyConfig struct {
	Mode      string `json:"mode,omitempty"`
	FocusMode string `json:"focusMode,omitempty"`
}

type Overrides

type Overrides struct {
	ActiveProvider string
	Providers      []ProviderProfile
	Provider       ProviderProfile
	MaxTurns       int
	MCP            MCPConfig
	Sandbox        SandboxConfig
	Notify         NotifyConfig
	Tools          ToolsConfig
	LocalControl   LocalControlConfig
}

type PreferencesConfig

type PreferencesConfig struct {
	FavoriteModels []string `json:"favoriteModels,omitempty"`
	// Theme is the persisted TUI palette preference — "auto" or a registered theme
	// name (e.g. "dracula"). Applied at startup below the --theme flag and
	// ZERO_THEME, so a /theme choice survives restart. Empty = unset (defaults auto).
	Theme string `json:"theme,omitempty"`
	// Recaps is a tri-state: nil (unset) defaults to ON; an explicit false means
	// the user turned post-turn recaps off. A *bool is its own tri-state, so no
	// custom unmarshal is needed (unlike ToolsConfig.DeferThreshold's int).
	Recaps *bool `json:"recaps,omitempty"`
}

func (PreferencesConfig) RecapsEnabled

func (p PreferencesConfig) RecapsEnabled() bool

RecapsEnabled reports whether post-turn recaps are on. Unset defaults to ON.

type ProviderKind

type ProviderKind string
const (
	ProviderKindOpenAI           ProviderKind = "openai"
	ProviderKindAnthropic        ProviderKind = "anthropic"
	ProviderKindAnthropicCompat  ProviderKind = "anthropic-compatible"
	ProviderKindGoogle           ProviderKind = "google"
	ProviderKindOpenAICompatible ProviderKind = "openai-compatible"
)

type ProviderProfile

type ProviderProfile struct {
	Name         string       `json:"name"`
	Provider     string       `json:"provider,omitempty"`
	ProviderKind ProviderKind `json:"provider_kind,omitempty"`
	CatalogID    string       `json:"catalogID,omitempty"`
	BaseURL      string       `json:"baseURL,omitempty"`
	APIKey       string       `json:"apiKey,omitempty"`
	APIKeyEnv    string       `json:"apiKeyEnv,omitempty"`
	// APIKeyStored marks that this provider's API key lives in the encrypted
	// credential store (internal/credstore), not inline in APIKey. The effective
	// key is loaded from the store at provider-build time; config.json holds only
	// this marker, never the secret.
	APIKeyStored    bool              `json:"apiKeyStored,omitempty"`
	APIFormat       string            `json:"apiFormat,omitempty"`
	AuthHeader      string            `json:"authHeader,omitempty"`
	AuthScheme      string            `json:"authScheme,omitempty"`
	AuthHeaderValue string            `json:"authHeaderValue,omitempty"`
	CustomHeaders   map[string]string `json:"customHeaders,omitempty"`
	Model           string            `json:"model,omitempty"`
	ParseThinkTags  *bool             `json:"parseThinkTags,omitempty"`
	Description     string            `json:"description,omitempty"`
}

func ApplyStoredAPIKey

func ApplyStoredAPIKey(profile ProviderProfile, store APIKeyGetter) ProviderProfile

ApplyStoredAPIKey fills profile.APIKey from the credential store when it is not already resolved — an inline config key or a resolved APIKeyEnv always wins, so this only supplies a key for providers whose secret lives in the store. A nil store, a miss, or a store error leaves the profile unchanged.

func SecureProviderProfile

func SecureProviderProfile(profile ProviderProfile, configPath string) ProviderProfile

SecureProviderProfile moves an inline APIKey on the profile into the credential store co-located with configPath, returning a profile with APIKeyStored set and APIKey cleared so the secret is never written to config.json. On any store error (e.g. no keyring) it returns the profile unchanged — the inline key persists and the startup migration retries later — so capturing a provider never fails on a flaky credential backend.

func (ProviderProfile) HasConfiguredCredential

func (profile ProviderProfile) HasConfiguredCredential() bool

HasConfiguredCredential reports whether the profile is set up to authenticate with its own API key (inline, stored, or a raw auth header). It is the single definition of "this profile is key-authed", shared by OAuthLoginCandidates and the cli/tui setup surfaces so they never disagree about whether a profile is keyed. APIKeyEnv is deliberately NOT included: an env var may be unset at runtime while the profile actually relies on an OAuth login, so an env-configured-but-empty profile must still be allowed to resolve a token.

func (ProviderProfile) OAuthLoginCandidates

func (profile ProviderProfile) OAuthLoginCandidates() []string

OAuthLoginCandidates returns the login names to try, in order, when resolving this profile's OAuth token — used by the runtime bearer resolver, the Codex account-header resolver, and the onboarding presence check so all three agree.

It returns NO candidates for a profile that carries its own configured credential: attaching an OAuth resolver to such a profile makes withBearer erase the key the instant a token resolves, silently routing/billing the call through the OAuth account instead of the intended key (the cross-profile override the review caught — and, via the profile name, a same-name login overriding an explicit key). A stored-key profile that reaches this keyless (e.g. a transiently unreadable keyring) is likewise treated as key-auth, so it fails with a clear missing-credential error rather than silently borrowing an unrelated OAuth login. APIKeyEnv is intentionally not part of that gate (an env var may be unset while the profile relies on OAuth).

For a keyless profile the profile name comes first (a login under your own profile name is unambiguously yours), then the catalog ID as a FALLBACK (so a profile renamed away from its catalog ID — e.g. {name:"codex", catalogID:"chatgpt"} — still finds a `zero auth login chatgpt` token). Candidates are trimmed, blank-skipped, and de-duplicated CASE-SENSITIVELY — the OAuth token store is a case-sensitive map, so "ChatGPT" and "chatgpt" are distinct keys and both must survive.

func (*ProviderProfile) UnmarshalJSON

func (profile *ProviderProfile) UnmarshalJSON(data []byte) error

type ResolveOptions

type ResolveOptions struct {
	UserConfigPath    string
	ProjectConfigPath string
	ProviderCommand   string
	Env               map[string]string
	Overrides         Overrides
}

func DefaultResolveOptions

func DefaultResolveOptions(workspaceRoot string) (ResolveOptions, error)

DefaultResolveOptions builds config resolution inputs from the local process environment and workspace.

type ResolvedConfig

type ResolvedConfig struct {
	ActiveProvider string
	Providers      []ProviderProfile
	Provider       ProviderProfile
	MaxTurns       int
	MCP            MCPConfig
	Sandbox        SandboxConfig
	Notify         NotifyConfig
	Tools          ToolsConfig
	Swarm          SwarmConfig
	Preferences    PreferencesConfig
	LocalControl   LocalControlConfig
}

func Resolve

func Resolve(options ResolveOptions) (ResolvedConfig, error)

type SandboxConfig

type SandboxConfig struct {
	// Network controls whether shell commands classified as network-touching
	// (curl, git push, package installs, …) are allowed: "allow" or "deny".
	// Empty keeps the built-in default (deny). Without this knob the engine's
	// hard-coded NetworkDeny was unreachable from any config surface.
	Network string `json:"network,omitempty"`
	// AdditionalWriteRoots lists directories outside the workspace the sandbox
	// allows writes in. Each entry must be an existing directory; entries are
	// normalized (~-expanded, absolutized, symlink-resolved) at startup and an
	// invalid entry fails the run. Honored from the GLOBAL user config and CLI
	// flags only — deliberately not project config, so a cloned repo cannot
	// grant itself write access. Session-only grants use /add-dir instead.
	AdditionalWriteRoots []string `json:"additionalWriteRoots,omitempty"`
	// BlockUnixSockets, when true, asks the Linux sandbox helper to install a
	// best-effort seccomp filter that denies AF_UNIX socket creation inside the
	// sandboxed command. Off by default; ignored on non-Linux backends.
	BlockUnixSockets bool `json:"blockUnixSockets,omitempty"`
	// MonitorDenials, when true on macOS, tails the unified log for this run's
	// sandbox denials and appends them to a command's stderr so blocked operations
	// are visible to the agent. Off by default. No-op on platforms/OS versions that
	// do not deliver seatbelt denials to the queryable log.
	MonitorDenials bool `json:"monitorDenials,omitempty"`
}

type SwarmConfig

type SwarmConfig struct {
	MaxTeamSize int `json:"maxTeamSize,omitempty"`
}

SwarmConfig tunes the multi-agent swarm. MaxTeamSize caps how many members run concurrently per team; 0 uses the built-in default (8). Spawns past the cap queue and launch as slots free, so lowering it bounds parallelism (and provider load / rate-limit pressure) without dropping work.

type ToolsConfig

type ToolsConfig struct {
	DeferThreshold int `json:"deferThreshold,omitempty"`
	// contains filtered or unexported fields
}

func ToolsOverride

func ToolsOverride(deferThreshold int) ToolsConfig

ToolsOverride builds a ToolsConfig that explicitly overrides the deferred-tool threshold (including to 0, which disables deferral). Use this for programmatic Overrides — a bare ToolsConfig{DeferThreshold: 0} is indistinguishable from "unset" and will not override.

func (*ToolsConfig) UnmarshalJSON

func (cfg *ToolsConfig) UnmarshalJSON(data []byte) error

Jump to

Keyboard shortcuts

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