Documentation
¶
Index ¶
- Constants
- Variables
- func ClearProviderKeyStored(path, provider string) (bool, error)
- func DefaultMCPServers() map[string]MCPServerConfig
- func DefaultUserConfigPath() (string, error)
- func ForgetProviderKey(provider string) (bool, error)
- func HasProviderProfile(profile ProviderProfile) bool
- func IsDefaultMCPServer(name string) bool
- func IsUnconfiguredDefault(name string, server MCPServerConfig) bool
- func MarkProviderAPIKeyStored(path string, provider string) error
- func MigratePlaintextProviderKeys(path string, store APIKeySetter) (int, error)
- func ProviderKeyStore() (*credstore.Store, error)
- func ProviderKeyStoreAt(dir string) (*credstore.Store, error)
- func SetActiveProviderEnv(name string)
- func SetMaxTurnsEnv(n int)
- func UserConfigDir() (string, error)
- func ValidateBytes(data []byte) (FileConfig, []Issue)
- func ValidateFile(path string) (FileConfig, []Issue)
- type APIKeyGetter
- type APIKeySetter
- type EnsuredProvider
- type FileConfig
- func EditProvider(path string, edit ProviderEdit) (FileConfig, error)
- func LoadProviderCommand(command string) (FileConfig, error)
- func RemoveProvider(path string, name string) (FileConfig, error)
- func RenameProvider(path string, oldName string, newName string) (FileConfig, error)
- func SetActiveProvider(path string, name string) (FileConfig, error)
- func SetFavoriteModels(path string, models []string) (FileConfig, error)
- func SetProviderDescription(path string, name string, description string) (FileConfig, error)
- func SetProviderModel(path string, name string, model string) (FileConfig, error)
- func SetRecapsEnabled(path string, enabled bool) (FileConfig, error)
- func SetRecentModels(path string, entries []RecentModelEntry) (FileConfig, error)
- func SetSTTLocalEngine(path, binary, serverBinary, modelPath string, streaming bool) (FileConfig, error)
- func SetSTTModel(path string, provider STTProviderKind, model string) (FileConfig, error)
- func SetSTTProvider(path string, provider STTProviderKind) (FileConfig, error)
- func SetTheme(path string, theme string) (FileConfig, error)
- func UpsertProvider(path string, profile ProviderProfile, setActive bool) (FileConfig, error)
- type Issue
- type KeyBindingDef
- type KeyBindingsConfig
- type LocalControlConfig
- func (cfg LocalControlConfig) BrowserEnabled() bool
- func (cfg LocalControlConfig) DesktopEnabled() bool
- func (cfg LocalControlConfig) Disabled() bool
- func (cfg LocalControlConfig) Empty() bool
- func (cfg LocalControlConfig) MarshalJSON() ([]byte, error)
- func (cfg LocalControlConfig) TerminalEnabled() bool
- func (cfg *LocalControlConfig) UnmarshalJSON(data []byte) error
- type LocalControlDriverConfig
- type MCPConfig
- type MCPOAuthConfig
- type MCPServerConfig
- type NotifyConfig
- type Overrides
- type PreferencesConfig
- type ProviderEdit
- type ProviderKind
- type ProviderProfile
- type RecentModelEntry
- type ResolveOptions
- type ResolvedConfig
- type STTConfig
- type STTProviderKind
- type SandboxConfig
- type SwarmConfig
- type ToolsConfig
Constants ¶
const ActiveProviderEnv = "ZERO_PROVIDER"
ActiveProviderEnv selects the active provider profile by name (read in applyEnv).
const AnthropicBaseURL = "https://api.anthropic.com"
const GoogleBaseURL = "https://generativelanguage.googleapis.com"
const MaxRecentModels = 5
MaxRecentModels caps the persisted/displayed recent-selection history.
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.
const MaxTurnsEnv = "ZERO_MAX_TURNS"
MaxTurnsEnv overrides the per-run tool-turn budget by name (read in applyEnv).
const OpenAIBaseURL = "https://api.openai.com/v1"
Variables ¶
var ErrNoActiveProvider = errors.New("no active provider configured")
ErrNoActiveProvider marks a resolve failure caused solely by a missing or unresolvable active provider. The interactive TUI treats this as "needs onboarding" (drop into the setup wizard) rather than a fatal config error.
var ErrProviderRequiresModel = errors.New("provider requires model")
ErrProviderRequiresModel marks a resolve failure caused solely by the active provider missing a model with no catalog default to fall back on (custom openai-/anthropic-compatible endpoints — Zero cannot guess a gateway's model). Like ErrNoActiveProvider, the interactive TUI treats it as "needs onboarding" and drops into the setup wizard so the user can fix it; headless commands (zero config, zero exec) still fail with the actionable message.
Functions ¶
func ClearProviderKeyStored ¶
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 ForgetProviderKey ¶
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 ¶
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 IsUnconfiguredDefault ¶ added in v0.3.0
func IsUnconfiguredDefault(name string, server MCPServerConfig) bool
IsUnconfiguredDefault reports whether server is one of Zero's built-in defaults that the user never wrote an entry for in their config — i.e. it is running with whatever Zero ships (e.g. keyless Firecrawl, no credentials).
Both conditions below must hold:
- !server.configured: the user's JSON never declared an object for this server key at all (set by MCPServerConfig.UnmarshalJSON only when it actually ran for this key). Any explicit action — including a disable/enable toggle like `zero mcp enable firecrawl` that leaves the resolved value unchanged — sets configured, so it always counts as user-configured, even though the value comparison below could not tell the difference on its own.
- reflect.DeepEqual(def, server): the value still matches the default. This is the fallback for callers that construct MCPServerConfig directly rather than through the JSON/merge pipeline (server.configured is then always false) — without it, any hand-built config with different field values would be misreported as unconfigured.
Callers use this to tell "server we turned on for the user" apart from "server the user configured themselves," e.g. to avoid warning loudly when an out-of-the-box default that was never given credentials fails to connect.
func MarkProviderAPIKeyStored ¶ added in v0.3.0
MarkProviderAPIKeyStored records that provider's API key now lives in the credential store. It also clears inline/env key fields so the stored key is the runtime credential; an old apiKeyEnv value must not keep overriding a freshly captured key from `zero auth openrouter` or provider setup.
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 ¶
ProviderKeyStore opens the credential store beside the default user config.
func ProviderKeyStoreAt ¶
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 UserConfigDir ¶ added in v0.2.0
UserConfigDir returns the base directory Zero stores per-user config under. It mirrors os.UserConfigDir everywhere except macOS: there Go defaults to ~/Library/Application Support, but Zero deliberately uses ~/.config (XDG-style, matching Linux and Claude Code) so a single config path works cross-platform. $XDG_CONFIG_HOME still wins on macOS when set.
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 ¶
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 ¶
APIKeySetter is the write surface of the credential store.
type EnsuredProvider ¶ added in v0.3.0
EnsuredProvider reports the outcome of EnsureCatalogProvider: the profile name that serves the catalog entry, whether it was newly created, and which provider is active after the call (unchanged unless it was blank).
func EnsureCatalogProvider ¶ added in v0.3.0
func EnsureCatalogProvider(path string, catalogID string) (EnsuredProvider, error)
EnsureCatalogProvider guarantees a provider profile exists in the config at path for the given catalog entry. OAuth login flows call this right after storing a token: a login is only reachable from the provider list and `zero providers use` when a profile exists, but a login must never replace or deactivate the user's current active provider — so an existing profile whose Name or CatalogID already matches is left completely untouched (its name, credentials, and model are the user's), and a created profile is NOT marked active unless no provider was active at all.
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"`
KeyBindings KeyBindingsConfig `json:"keybindings,omitempty"`
LocalControl LocalControlConfig `json:"localControl,omitempty"`
STT STTConfig `json:"stt,omitempty"`
}
func EditProvider ¶ added in v0.3.0
func EditProvider(path string, edit ProviderEdit) (FileConfig, error)
EditProvider applies a provider edit in ONE read-modify-write: rename (activeProvider follows; a stored key migrates, with a best-effort rollback if the config write fails), field updates, the stored-key marker, and the verbatim description. A single write keeps the operation atomic — the previous rename+upsert+describe sequence could fail halfway and leave config.json renamed while every in-memory consumer still held the old name — and, unlike UpsertProvider's exact-name merge, the case-insensitive match here makes a case-only rename (groq -> Groq) an in-place update instead of an appended duplicate profile.
func LoadProviderCommand ¶
func LoadProviderCommand(command string) (FileConfig, error)
func RemoveProvider ¶ added in v0.3.0
func RemoveProvider(path string, name string) (FileConfig, error)
RemoveProvider deletes the named provider profile from the config at path. When the removed profile was active, activeProvider hands off to the first remaining provider (or clears when none remain) so the config never points at a profile that no longer exists. The caller owns cleaning up the credential store entry — config stays pure of secret I/O on the read path, and remove keeps that symmetry by only touching config.json.
func RenameProvider ¶ added in v0.3.0
func RenameProvider(path string, oldName string, newName string) (FileConfig, error)
RenameProvider renames a provider profile, keeping everything keyed by the profile name consistent: the activeProvider pointer follows the rename, and a key in the encrypted credential store (APIKeyStored) is migrated to the new name BEFORE the config is rewritten — the store write must succeed first so a failed migration never strands the config pointing at a key that no longer resolves. OAuth tokens are deliberately not migrated: the runtime's login candidates fall back to the profile's CatalogID, which every OAuth-capable catalog profile carries, so a rename keeps the login reachable.
func SetActiveProvider ¶
func SetActiveProvider(path string, name string) (FileConfig, error)
func SetFavoriteModels ¶
func SetFavoriteModels(path string, models []string) (FileConfig, error)
func SetProviderDescription ¶ added in v0.3.0
func SetProviderDescription(path string, name string, description string) (FileConfig, error)
SetProviderDescription sets a provider's description VERBATIM — including to empty. The generic UpsertProvider merge treats empty fields as "leave unchanged", so clearing a description needs this dedicated setter.
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 SetRecentModels ¶ added in v0.3.0
func SetRecentModels(path string, entries []RecentModelEntry) (FileConfig, error)
SetRecentModels persists the automatic recent-model-switch history, mirroring SetFavoriteModels (read-modify-atomic-write). Unlike favorites, order is preserved (newest first) rather than sorted, since it reflects switch recency, not an alphabetical preference list.
func SetSTTLocalEngine ¶ added in v0.3.0
func SetSTTLocalEngine(path, binary, serverBinary, modelPath string, streaming bool) (FileConfig, error)
SetSTTLocalEngine persists the paths of an auto-downloaded local engine + model and switches dictation to the local provider, mirroring SetTheme (read-modify-atomic-write). streaming selects the pipeline matching the downloaded model (a streaming transducer vs a batch model). Called after a download completes.
func SetSTTModel ¶ added in v0.3.0
func SetSTTModel(path string, provider STTProviderKind, model string) (FileConfig, error)
SetSTTModel persists the dictation model and its provider, mirroring SetTheme (read-modify-atomic-write). provider must be one of the known STT provider kinds; a local provider stores the model as stt.localModelPath, otherwise as stt.model. A blank model clears the stored value for that slot.
func SetSTTProvider ¶ added in v0.3.0
func SetSTTProvider(path string, provider STTProviderKind) (FileConfig, error)
SetSTTProvider persists just the dictation batch provider, mirroring SetTheme.
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 ¶
Issue is a single structured problem found while validating a config file. Message is already routed through the package secret redaction.
type KeyBindingDef ¶ added in v0.2.0
type KeyBindingDef string
KeyBindingDef defines one key binding string (e.g. "ctrl+o") that the TUI can remap. An empty string means "use the built-in default" for that action.
type KeyBindingsConfig ¶ added in v0.2.0
type KeyBindingsConfig struct {
// ToggleDetailed toggles the detailed transcript view (default: ctrl+o).
ToggleDetailed KeyBindingDef `json:"toggleDetailed,omitempty"`
// ToggleMouse toggles mouse capture release (default: ctrl+e).
ToggleMouse KeyBindingDef `json:"toggleMouse,omitempty"`
// CycleReasoning cycles through reasoning effort levels (default: ctrl+t).
CycleReasoning KeyBindingDef `json:"cycleReasoning,omitempty"`
// TogglePlan toggles the plan panel expansion (default: ctrl+p).
TogglePlan KeyBindingDef `json:"togglePlan,omitempty"`
// ToggleSidebar toggles the right context sidebar (default: ctrl+b).
ToggleSidebar KeyBindingDef `json:"toggleSidebar,omitempty"`
}
KeyBindingsConfig holds the subset of TUI keybindings that users may remap via config.json. Each field defaults to a sensible built-in when empty.
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 Overrides ¶
type Overrides struct {
ActiveProvider string
Providers []ProviderProfile
Provider ProviderProfile
MaxTurns int
MCP MCPConfig
Sandbox SandboxConfig
Notify NotifyConfig
Tools ToolsConfig
KeyBindings KeyBindingsConfig
LocalControl LocalControlConfig
STT STTConfig
}
type PreferencesConfig ¶
type PreferencesConfig struct {
FavoriteModels []string `json:"favoriteModels,omitempty"`
// RecentModels is the short automatic history of provider+model pairs the
// user has switched to via /model, newest first. Unlike FavoriteModels
// (manual pins), this list is maintained automatically on every switch and
// capped to MaxRecentModels entries. See RecentModelEntry.
RecentModels []RecentModelEntry `json:"recentModels,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 ProviderEdit ¶ added in v0.3.0
type ProviderEdit struct {
Name string
NewName string
BaseURL string
Model string
APIKey string
APIKeyStored bool
Description string
}
ProviderEdit is a field-level edit of one saved provider, applied by EditProvider in a single atomic write. Name is the CURRENT profile name (matched case-insensitively); NewName renames (case-only renames included). Empty BaseURL/Model/APIKey mean "leave unchanged"; Description is applied VERBATIM (the editor always knows the full desired text, so clearing works).
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) MissingCredentialEnv ¶ added in v0.3.0
func (profile ProviderProfile) MissingCredentialEnv() (string, bool)
MissingCredentialEnv reports the environment variable this profile is expected to read an API key from, and whether that expectation is currently unmet. It is the single source of truth for "does this saved provider need a credential it doesn't have" — the CLI (`providers check`, `usableSavedProviders`) and TUI (`/providers` status, provider wizard summary) surfaces all delegate here so they never disagree about a profile's status.
For the catalog's two "bring your own endpoint" descriptors (custom-openai-compatible, custom-anthropic-compatible), RequiresAuth is just a wizard template default, not a fact about the user's actual endpoint: a custom target may need no auth at all. So for those two only, a credential is expected exclusively when this profile carries its own explicit APIKeyEnv that differs from the catalog's guessed default — a value matching that default is indistinguishable from the wizard's old auto-stamp bug (issue #555) and is treated the same as unset, which also self-heals profiles saved before that bug was fixed.
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 RecentModelEntry ¶ added in v0.3.0
RecentModelEntry is one provider-qualified model selection recorded in Preferences.RecentModels. Provider is the saved provider profile's Name (not a display label), so a recent entry can be resolved back to a concrete profile the same way the /model picker's cross-provider rows are.
func NormalizeRecentModels ¶ added in v0.3.0
func NormalizeRecentModels(entries []RecentModelEntry) []RecentModelEntry
NormalizeRecentModels trims, drops entries with no model id, de-duplicates by provider+model pair (keeping the first/newest occurrence), and caps the result to MaxRecentModels. Order is preserved — the caller is responsible for passing entries newest-first. Exported so callers outside this package (e.g. the TUI, which keeps its own in-memory copy of recent history) apply the exact same normalization rules as the persisted config, instead of maintaining a second, independently-drifting copy of this logic.
type ResolveOptions ¶
type ResolveOptions struct {
UserConfigPath string
ProjectConfigPath string
ProviderCommand string
Env map[string]string
Overrides Overrides
// ExcludeProject drops the project config layer (ProjectConfigPath) from MCP
// resolution when the workspace is untrusted, so a cloned repo's ./.zero/config.json
// cannot spawn stdio MCP servers. It is fail-closed: only a trusted workspace sets
// it false. Mirrors the ExcludeProject option hooks and plugins already honor.
ExcludeProject bool
}
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
KeyBindings KeyBindingsConfig
LocalControl LocalControlConfig
STT STTConfig
}
func Resolve ¶
func Resolve(options ResolveOptions) (ResolvedConfig, error)
type STTConfig ¶ added in v0.3.0
type STTConfig struct {
// Provider is the batch transcription backend: "local" (sherpa-onnx-offline,
// the default), "groq", or "openai". Termux and the fallback everywhere use
// this path.
Provider STTProviderKind `json:"provider,omitempty"`
// StreamProvider is the streaming backend on desktop: "local" (sherpa-onnx
// websocket server, default), "deepgram", or "openai" (Realtime).
StreamProvider STTProviderKind `json:"streamProvider,omitempty"`
// Streaming enables the live-transcript pipeline on platforms that support
// it (desktop). Defaults to on; set false to always use the batch pipeline.
Streaming *bool `json:"streaming,omitempty"`
// Model overrides the cloud batch model (e.g. "whisper-large-v3-turbo" for
// Groq, "whisper-1" for OpenAI). Empty uses the provider default.
Model string `json:"model,omitempty"`
// StreamModel overrides the cloud streaming model (Deepgram/OpenAI Realtime).
StreamModel string `json:"streamModel,omitempty"`
// LocalModelPath is the sherpa-onnx model directory for local transcription
// (batch and streaming). Required to use a local provider.
LocalModelPath string `json:"localModelPath,omitempty"`
// LocalBinary overrides the offline binary name/path (default
// "sherpa-onnx-offline"); LocalServerBinary overrides the streaming server
// (default "sherpa-onnx-online-websocket-server"). Both looked up on PATH.
LocalBinary string `json:"localBinary,omitempty"`
LocalServerBinary string `json:"localServerBinary,omitempty"`
// LocalServerPort is the localhost port for the sherpa-onnx websocket server
// (default 6006).
LocalServerPort int `json:"localServerPort,omitempty"`
// EngineVersion selects the sherpa-onnx release the auto-download fetches
// ("" → a pinned known-good default; "latest" or any release tag also works,
// so a newer engine needs no Zero update). Verified against the release's
// published SHA256 digest either way.
EngineVersion string `json:"engineVersion,omitempty"`
// NumThreads sets the local engine's thread count (0 = engine default).
NumThreads int `json:"numThreads,omitempty"`
// Language optionally constrains recognition (ISO-639-1, e.g. "en"). Empty =
// auto-detect.
Language string `json:"language,omitempty"`
// MaxDurationSeconds is the hard runaway-recording cap on every platform
// (0 = default 300s).
MaxDurationSeconds int `json:"maxDurationSeconds,omitempty"`
// SilenceAutoStop ends a recording ~2s after the signal goes quiet, as a
// backstop for a forgotten manual stop (not VAD-triggered start). Defaults on.
SilenceAutoStop *bool `json:"silenceAutoStop,omitempty"`
// AutoSubmit fires the transcript at the agent instead of inserting it for
// review. Defaults OFF — insert-for-review is the safety net for a misheard
// prompt (§3).
AutoSubmit *bool `json:"autoSubmit,omitempty"`
// WindowsAudioDevice names the dshow capture device (auto-detected when empty).
WindowsAudioDevice string `json:"windowsAudioDevice,omitempty"`
}
STTConfig configures speech-to-text dictation. All fields are optional; empty values take the documented defaults. Booleans that need a real tri-state (distinguishing "unset" from "false") use *bool, matching PreferencesConfig.Recaps.
func (STTConfig) AutoSubmitEnabled ¶ added in v0.3.0
AutoSubmitEnabled reports whether transcripts are auto-fired. Unset defaults OFF.
func (STTConfig) Empty ¶ added in v0.3.0
Empty reports whether the STT config carries no user-set values (so it can be omitted from a marshaled config).
func (STTConfig) STTProvider ¶ added in v0.3.0
func (c STTConfig) STTProvider() STTProviderKind
STTProvider returns the configured batch provider, defaulting to local.
func (STTConfig) STTStreamProvider ¶ added in v0.3.0
func (c STTConfig) STTStreamProvider() STTProviderKind
STTStreamProvider returns the configured streaming provider, defaulting to local.
func (STTConfig) SilenceAutoStopEnabled ¶ added in v0.3.0
SilenceAutoStopEnabled reports whether trailing-silence auto-stop is on. Unset defaults ON.
func (STTConfig) StreamingEnabled ¶ added in v0.3.0
StreamingEnabled reports whether the live pipeline is on. Unset defaults ON.
type STTProviderKind ¶ added in v0.3.0
type STTProviderKind string
STTProviderKind is the batch (or streaming) transcription backend selector. Validated at config load time against the known set, so a typo fails loudly with the valid options rather than silently falling back to a default.
const ( STTProviderLocal STTProviderKind = "local" STTProviderGroq STTProviderKind = "groq" STTProviderOpenAI STTProviderKind = "openai" STTProviderDeepgram STTProviderKind = "deepgram" )
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