config

package
v0.2.2-alpha.2 Latest Latest
Warning

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

Go to latest
Published: May 21, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package config carries the runtime configuration the evva agent and its bundled tools read at startup and during a session.

The package is brand-neutral: a Config is constructed via Load(appName, appHome, workdir) so downstream apps can choose their own home directory (e.g. ~/.myapp/) and binary name. LoadDefault preserves evva's historical behavior (~/.evva/) for the bundled CLI.

There is no package-level singleton. Callers construct one Config per process (or per agent, if running multiple agents with different configurations) and pass it through agent.New via WithConfig.

Index

Constants

View Source
const (
	DefaultAppName    = "evva"
	DefaultAppVersion = "0.1.0"
)

Default values that appear unchanged across all Config instances.

Variables

View Source
var BuildDate string

BuildDate is the UTC build timestamp injected at build time. Empty in dev builds.

View Source
var CommitSHA string

CommitSHA is the git commit hash injected at build time via ldflags. Empty in dev builds.

View Source
var Version string

Version is the canonical version string injected at build time via ldflags:

go build -ldflags "-X github.com/johnny1110/evva/pkg/config.Version=v1.2.3"

When empty (dev builds, go run), DefaultAppVersion is used as the fallback.

Functions

func DisplayVersion

func DisplayVersion() string

DisplayVersion returns the best available version string: the ldflags-injected Version, or DefaultAppVersion if not set, followed by the commit and build date when available. The result is meant for --version output.

func ResolveDefaultModel

func ResolveDefaultModel(provider, model string) (constant.LLMProvider, constant.Model, error)

ResolveDefaultModel parses the (provider name, model name) pair from the YAML and returns the typed constants. Validates that the model is actually one the provider lists — a typo or a model/provider mismatch fails fast at startup with a clear message rather than a confusing runtime "unknown model" from the LLM API.

func SaveFileConfig

func SaveFileConfig(path string, cfg FileConfig) error

SaveFileConfig writes cfg to path atomically (temp file + rename) so a crash mid-write never leaves a truncated YAML behind.

Types

type APIConfig

type APIConfig struct {
	ApiURL    string
	ApiSecret string
	Models    []constant.Model
}

APIConfig carries the per-provider credentials an LLM client needs to talk to its backend. The host (cmd/evva or a downstream consumer) constructs one APIConfig per provider from whatever config source it uses (YAML, env vars, secret manager) and passes it to the registry-resolved ClientFactory in pkg/llm.

Defined in pkg/config rather than pkg/llm to avoid a cycle: pkg/llm imports pkg/tools, pkg/tools imports pkg/config (for the State.Config() return type). pkg/config sits at the bottom and is imported by both pkg/llm (via alias) and pkg/tools.

type Config

type Config struct {
	// OS / runtime
	OS string

	// Logging
	LogLevel  string  // default: "info"
	LogFormat string  // default: "text"
	LogDir    *string // default: nil → stdout only

	// Application
	AppEnv     string // default: "development"
	AppName    string // default: "evva" — the binary / brand name; drives AppHome layout.
	AppVersion string

	// Per-user home dir layout
	AppHome            string
	AppHomeSkillsDir   string
	AppHomeUserProfile string
	AppHomeConfigFile  string // absolute path to <app>-config.yml under AppHome/config/

	AutoCompactThreshold float64

	// Workdir layout
	WorkDir          string
	WorkDirSkillsDir string

	// llm providers(from <app>-config.yml) key: provider name, value: provider APIConfig
	LLMProviderConfig map[string]APIConfig

	// DefaultProvider / DefaultModel are the (provider, model) the agent
	// boots with. Sourced from <app>-config.yml; the /model switch updates
	// them in-memory and persists via SaveFile().
	DefaultProvider constant.LLMProvider
	DefaultModel    constant.Model

	// DefaultEffort is the user-facing effort level name: low|medium|high|ultra.
	// Defaults to "medium". Sourced from <app>-config.yml; /effort updates it.
	DefaultEffort string

	// DefaultProfile is the persona the root agent boots into ("evva", "nono",
	// etc). Sourced from <app>-config.yml; /profile updates it. Empty falls
	// back to "evva" at bootstrap so old configs keep working.
	DefaultProfile string

	// PermissionMode is the startup permission stance: one of
	// default|accept_edits|plan|bypass|auto. The -permission-mode CLI flag
	// overrides this at boot; the TUI's Shift+Tab cycle mutates the
	// in-memory value via SetPermissionMode (not yet persisted).
	PermissionMode string

	// Loaded metadata
	LoadedAt time.Time
	// DefaultMaxIterations is the loop's safety cap. Hitting it emits a
	// KindIterLimit event and pauses the agent; the caller may invoke
	// Continue(ctx) to keep going.
	DefaultMaxIterations int
	// DefaultMaxTokens is the per-completion output-token cap passed to
	// the LLM. 0 → let the provider apply its own default.
	DefaultMaxTokens int

	// UI
	DisplayThinking bool

	// Auto-memory subsystem. When true (default), update_user_profile +
	// update_project_memory tools are registered on Main and the system
	// prompt carries the auto-memory guidance + project-memory index.
	// /config (or hand-edit) flips this; EVVA_AUTO_MEMORY=0 forces off at
	// boot regardless of the YAML.
	EnableAutoMemory bool

	// Web tools
	TavilyAPIKey  string // empty → web_search reports "not configured"
	FetchMaxBytes int    // cap on extracted text returned by web_fetch
	// contains filtered or unexported fields
}

Config holds all parsed runtime configuration. Most fields are populated once during Load and treated as read-only; the small subset that the /config and /model setters mutate at runtime is guarded by c.mu.

AppHome-prefixed paths point inside the per-user home dir (~/.<app>/) where skills, USER_PROFILE.md, evva-config.yml, and logs live. WorkDir-prefixed paths point inside the process's current working directory where workdir-local resources (skills, EVVA.md, plans) live.

func Get

func Get() *Config

Get returns a process-wide Config initialized lazily via LoadDefault. Subsequent calls return the same pointer.

Get is a host-side convenience for the bundled cmd/evva binary and for the reference TUI (which reads runtime settings without an injected pointer). Library code inside the agent loop and tools must NOT call Get — they receive *Config through dependency injection (agent.WithConfig, toolset.ToolState.SetConfig, function parameters).

Downstream hosts that want a non-default AppHome should call Load with explicit LoadOptions and pass the result into agent.WithConfig.

func Load

func Load(opts LoadOptions) (*Config, error)

Load parses env vars + the per-user YAML and returns a populated Config. Each LoadOptions field has a sensible default (see LoadOptions doc).

Unlike LoadDefault, Load returns an error instead of calling os.Exit so downstream hosts can surface it through their own error path.

func LoadDefault

func LoadDefault() *Config

LoadDefault returns a Config populated with evva's historical defaults: AppName="evva", AppHome=~/.evva/, WorkDir=os.Getwd(). Intended for the bundled cmd/evva binary and for backward-compatible callers.

Startup failures (missing/invalid YAML, unknown provider/model) bail with os.Exit so the user gets a clear single-line error rather than a panic stack from deep inside the agent boot path.

func (*Config) Effort

func (c *Config) Effort() string

Effort returns the current effort level name under the read lock.

func (*Config) GetAutoCompactThreshold

func (c *Config) GetAutoCompactThreshold() float64

GetAutoCompactThreshold returns the current threshold under the read lock. compact.go reads this every turn.

func (*Config) GetDisplayThinking

func (c *Config) GetDisplayThinking() bool

GetDisplayThinking returns the current DisplayThinking flag under the read lock. Agent code reads this every turn (state_machine.go, stream.go); the UI may write it via /config.

func (*Config) GetEnableAutoMemory

func (c *Config) GetEnableAutoMemory() bool

GetEnableAutoMemory returns the auto-memory flag under the read lock. Read by agent.Main (to decide whether to attach the memory tools) and by the sysprompt builder (to decide whether to inject the auto-memory guidance section).

func (*Config) IsDevelopment

func (c *Config) IsDevelopment() bool

IsDevelopment / IsProduction — semantic helpers so call sites don't hardcode string literals scattered across the codebase.

func (*Config) IsProduction

func (c *Config) IsProduction() bool

func (*Config) SaveFile

func (c *Config) SaveFile() error

SaveFile re-serializes the user-tunable subset to AppHomeConfigFile. The /config setters and the runtime /model switch both call this.

Snapshots all fields under c.mu.RLock, releases that lock before blocking on disk I/O, then takes c.saveMu so concurrent saves don't interleave on the file.

func (*Config) SetAutoCompactThreshold

func (c *Config) SetAutoCompactThreshold(v float64) error

SetAutoCompactThreshold validates 0 < v <= 1 and persists.

func (*Config) SetDefaultEffort

func (c *Config) SetDefaultEffort(level string) error

SetDefaultEffort validates the effort level name and persists it.

func (*Config) SetDefaultModel

func (c *Config) SetDefaultModel(provider constant.LLMProvider, model constant.Model) error

SetDefaultModel updates the (provider, model) pair the agent boots with and persists it. Phase-3's runtime /model swap calls this after rebuilding the Agent's llm.Client so next launch starts with the user's last choice. Validates that the model is actually offered by the provider.

func (*Config) SetDefaultProfile

func (c *Config) SetDefaultProfile(name string) error

SetDefaultProfile persists the chosen persona name. Validation against the agent registry happens at the call site (AgentRegistry lives in internal/agent, which can't be imported from config without a cycle). Empty string is accepted — bootstrap interprets "" as "fall back to evva".

func (*Config) SetDisplayThinking

func (c *Config) SetDisplayThinking(v bool) error

SetDisplayThinking mutates the in-memory flag and persists to disk.

func (*Config) SetEnableAutoMemory

func (c *Config) SetEnableAutoMemory(v bool) error

SetEnableAutoMemory toggles the auto-memory subsystem and persists. Takes effect for the prompt and tool registration on next agent boot.

func (*Config) SetFetchMaxBytes

func (c *Config) SetFetchMaxBytes(n int) error

SetFetchMaxBytes validates > 0 and persists.

func (*Config) SetMaxIterations

func (c *Config) SetMaxIterations(n int) error

SetMaxIterations validates >0 and persists. NOTE: this only updates the YAML default; the live cap on a running agent is on Agent itself — call Controller.SetMaxIterations to mutate it.

func (*Config) SetMaxTokens

func (c *Config) SetMaxTokens(n int) error

SetMaxTokens validates >=0 and persists. 0 means "provider default". Effective on next launch — the agent's profile snapshots this at construction.

func (*Config) SetProviderAPIKey

func (c *Config) SetProviderAPIKey(name, key string) error

SetProviderAPIKey installs an api key for the named provider and persists. Empty key removes the provider from LLMProviderConfig (cloud providers require a key to be listed). The constant.LLMProvider must already be known.

func (*Config) SetProviderAPIURL

func (c *Config) SetProviderAPIURL(name, url string) error

SetProviderAPIURL overrides the api_url for the named provider. Empty resets to the provider's built-in default.

func (*Config) SetTavilyAPIKey

func (c *Config) SetTavilyAPIKey(s string) error

SetTavilyAPIKey persists the key. Empty string disables web_search.

type FileConfig

type FileConfig struct {
	MaxIterations        int     `yaml:"max_iterations"`
	MaxTokens            int     `yaml:"max_tokens"`
	AutoCompactThreshold float64 `yaml:"auto_compact_threshold"`
	DisplayThinking      bool    `yaml:"display_thinking"`

	// DefaultProvider / DefaultModel are the (provider, model) pair the
	// agent boots with. Phase 3's /model switch will mutate these and call
	// Save to persist across launches.
	DefaultProvider string `yaml:"default_provider"`
	DefaultModel    string `yaml:"default_model"`

	DefaultEffort string `yaml:"default_effort"`

	// DefaultProfile is the persona the root agent boots into. Phase 6's
	// /profile switch mutates this and calls Save to persist across launches.
	// Empty falls back to "evva" at bootstrap.
	DefaultProfile string `yaml:"default_profile"`

	// PermissionMode is the agent's startup stance. One of:
	// "default" | "accept_edits" | "plan" | "bypass" | "auto". Defaults to
	// "default" when omitted. The -permission-mode CLI flag overrides this.
	PermissionMode string `yaml:"permission_mode"`

	FetchMaxBytes int    `yaml:"fetch_max_bytes"`
	TavilyAPIKey  string `yaml:"tavily_api_key"`

	// EnableAutoMemory gates the auto-memory subsystem (update_user_profile,
	// update_project_memory tools + the per-session prompt section). Default
	// true; users opt out via /config or by setting this to false. Pointer so
	// missing-key in YAML preserves the default rather than zeroing.
	EnableAutoMemory *bool `yaml:"enable_auto_memory,omitempty"`

	Providers map[string]FileProviderConfig `yaml:"providers"`
}

FileConfig is the on-disk schema for $EvvaHome/config/evva-config.yml. It owns the user-tunable subset of configuration; deployment knobs (LOG_LEVEL, APP_ENV, ...) stay in .env.

func LoadFileConfig

func LoadFileConfig(path string) (FileConfig, bool, error)

LoadFileConfig reads the YAML at path. Returns (cfg, created, err):

  • created=true means the file didn't exist and was just written with defaults; callers can use this to surface a one-time first-launch notice.
  • Missing keys in an existing file fall back to defaultFileConfig() values via pre-population, so partial YAML never crashes startup.

type FileProviderConfig

type FileProviderConfig struct {
	APIKey string `yaml:"api_key"`
	APIURL string `yaml:"api_url"`
}

FileProviderConfig carries per-provider credentials. Empty ApiURL falls back to the constant's built-in default.

type LoadOptions

type LoadOptions struct {
	AppName    string // brand identifier; drives the AppHome layout. Defaults to "evva".
	AppHome    string // absolute path; defaults to ~/.<AppName>/.
	WorkDir    string // process cwd; defaults to os.Getwd().
	AppVersion string // version string for diagnostics; defaults to DefaultAppVersion.
}

LoadOptions tunes Load. Zero-value fields fall back to LoadDefault behavior — AppName="evva", AppHome=~/.evva/, WorkDir=os.Getwd(), AppVersion=DefaultAppVersion. Downstream apps that want a different home dir or app name fill in the relevant fields.

Jump to

Keyboard shortcuts

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