Documentation
¶
Overview ¶
Package config loads and resolves the on-disk configuration of baifo. See .agents/AGENTS.md and .agents/CONFIG.md for the full reference.
Index ¶
- Constants
- Variables
- func AgentsFilePath(dir string) string
- func DefaultDir() (string, error)
- func DiscoverDir(flagDir string) (string, error)
- func FilePath(dir string) string
- func ValidateAgents(agents []AgentTemplate) error
- type A2AConfig
- type A2ACredentials
- type AgentLLM
- type AgentTemplate
- type AgentsFile
- type BackoffConfig
- type Config
- type ContextGuardConfig
- type GuardrailsConfig
- type MCPAuth
- type MCPEntry
- type MCPOptions
- type ProviderEntry
- type RetryConfig
- func (r RetryConfig) Attempts() int
- func (r RetryConfig) InitialBackoffDuration() time.Duration
- func (r RetryConfig) JitterEnabled() bool
- func (r RetryConfig) MaxBackoffDuration() time.Duration
- func (r RetryConfig) MultiplierOr() float64
- func (r RetryConfig) RetryEnabled() bool
- func (r RetryConfig) StrategyOr() string
- type RuntimeConfig
- type SecretsConfig
- type SpawnConfig
- type ThemeConfig
- type TrimOversizedUserTextConfig
Constants ¶
const ( RetryStrategyBackoff = "backoff" RetryStrategyRetryAfter = "retry-after" )
Retry strategy identifiers for RetryConfig.Strategy.
const ( DefaultRetryMaxAttempts = 4 DefaultRetryInitialBackoff = time.Second DefaultRetryMaxBackoff = 30 * time.Second DefaultRetryMultiplier = 2.0 DefaultRetryStrategy = RetryStrategyBackoff )
Retry policy defaults. Exposed as constants so the decorator and the config accessors agree on the same numbers.
const ( // DefaultLimitExecOutputChars is the default per-stream (stdout / stderr) // character cap applied to the exec and process_status tools. DefaultLimitExecOutputChars = 48000 // DefaultLimitReadFileChars is the default total-character cap applied to // a single read_file call across all its fragments. DefaultLimitReadFileChars = 120000 // DefaultLimitSearchOutputChars is the default total-character cap applied // to a single search call across all its matches and their context. DefaultLimitSearchOutputChars = 50000 )
Output-cap defaults for the built-in filesystem MCP. These are the values returned by EffectiveExecOutputChars and EffectiveReadFileChars when the operator did not set a field explicitly (0 / absent).
const ( MCPRegistrationAuto = "auto" MCPRegistrationCIMD = "cimd" MCPRegistrationDCR = "dcr" )
MCP OAuth client-registration mode constants.
const ( MCPAuthKindNone = "none" MCPAuthKindOAuth = "oauth" )
MCP auth kind constants.
const ( SpawnModeNone = "none" SpawnModeStatic = "static" SpawnModeDynamic = "dynamic" SpawnModeBoth = "both" )
Spawn mode constants.
const AgentsFileName = "agents.yaml"
AgentsFileName is the canonical name of the static-worker templates file inside .baifo/.
const DefaultTrimOversizedUserTextMaxChars = 30000
DefaultTrimOversizedUserTextMaxChars is the per-part character cap used when MaxChars is 0 (absent / unset). Value: 30000.
const FileName = "baifo.yaml"
FileName is the canonical filename of the main config inside .baifo/.
Variables ¶
var ErrDirNotFound = errors.New(".baifo directory not found")
ErrDirNotFound is returned by DiscoverDir when no .baifo/ directory can be located using the resolution rules. Callers should treat it as the trigger for first-run initialisation.
Functions ¶
func AgentsFilePath ¶
AgentsFilePath returns the absolute path of agents.yaml inside dir.
func DefaultDir ¶
DefaultDir returns the path of the .baifo directory that the first-run wizard should create when no config is found anywhere.
func DiscoverDir ¶
DiscoverDir locates the .baifo/ configuration directory according to the priority order documented in DECISIONS.md #1:
- flagDir (--config-dir), if non-empty
- $BAIFO_HOME
- $PWD/.baifo/, walking up the tree
- $XDG_CONFIG_HOME/baifo/
- $HOME/.baifo/
The first hit wins. Returns ErrDirNotFound when nothing matches.
func ValidateAgents ¶
func ValidateAgents(agents []AgentTemplate) error
ValidateAgents is the exported wrapper around validateAgents so other packages (notably internal/app) can run the same schema rules without going through LoadAgents and disk I/O.
Types ¶
type A2AConfig ¶
type A2AConfig struct {
Enabled bool `yaml:"enabled"`
Host string `yaml:"host"`
Port int `yaml:"port"`
PublicURL string `yaml:"public_url"`
// Credentials gates incoming A2A requests. When empty the server
// is unauthenticated (the historical behaviour); when a token is
// set, every request must present it as a bearer token.
Credentials A2ACredentials `yaml:"credentials"`
}
A2AConfig describes the A2A server endpoint.
type A2ACredentials ¶
type A2ACredentials struct {
// Token is the expected bearer credential. A literal string is
// used verbatim; a ${secret:NAME} placeholder is expanded from
// the secrets store at boot so the token never lives in
// baifo.yaml in plaintext. Empty disables authentication.
Token string `yaml:"token"`
}
A2ACredentials carries the optional bearer token that protects the A2A endpoints. Auth is opt-in: set Token to turn it on, leave it empty to serve without authentication.
type AgentLLM ¶
type AgentLLM struct {
Provider string `yaml:"provider"`
Model string `yaml:"model"`
// Reasoning is the optional reasoning-effort knob for models that
// support it: one of "minimal" / "low" / "medium" / "high" (empty
// or "off" leaves the model's own default). Use list_models to see
// which models accept reasoning and at which levels. Applied to
// openai (reasoning_effort), gemini (thinking) and anthropic
// (extended-thinking budget).
Reasoning string `yaml:"reasoning"`
// ReasoningAPI optionally overrides which Anthropic reasoning API the
// model uses: "enabled" (classic budget-based, for Claude 3.7 /
// Sonnet 4 / Opus 4) or "adaptive" (effort-based, for Opus 4.5+).
// Empty auto-detects from the catalogue. Only anthropic uses it;
// other providers ignore it.
// Ref: https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
ReasoningAPI string `yaml:"reasoning_api"`
}
AgentLLM mirrors LLMRef and defines the provider and model settings. The effective value is exposed via the Provider accessor.
type AgentTemplate ¶
type AgentTemplate struct {
// Root marks the always-on entry-point agent. Exactly one
// entry in agents.yaml must set this to true; the loader
// rejects zero and more-than-one root setups. The flagged
// agent receives the spawn / memory / todos tools and a
// secrets allower of AllowAll regardless of AllowedSecrets;
// all other entries are treated as ordinary spawnable
// sub-agents.
Root bool `yaml:"root,omitempty"`
// Utility marks the background utility agent: the cheap model
// baifo uses for internal chores that don't deserve the root's
// (usually expensive) model — today, titling sessions and
// summarising conversations for context-window compaction. At
// most one entry may set it; when none does, those chores fall
// back to the root's LLM. The utility agent never chats, never
// receives tools and is not spawnable — only its llm block is
// consumed.
Utility bool `yaml:"utility,omitempty"`
Name string `yaml:"name"`
Description string `yaml:"description"`
Prompt string `yaml:"prompt"`
LLM AgentLLM `yaml:"llm"`
Skills []string `yaml:"skills"`
MCPs []string `yaml:"mcps"`
ContextGuard ContextGuardConfig `yaml:"context_guard"`
AllowedSecrets []string `yaml:"allowed_secrets"`
}
AgentTemplate is the on-disk definition of one agent in agents.yaml. Both the root agent (the one the user talks to in the TUI / over A2A) and the spawnable sub-agents share this shape. The single distinguishing flag is Root.
Field names follow CONFIG.md > agents.yaml. The LLM section uses `provider` (the baifo term, see Phase 2).
type AgentsFile ¶
type AgentsFile struct {
Version int `yaml:"version"`
Agents []AgentTemplate `yaml:"agents"`
}
AgentsFile is the root of agents.yaml.
func LoadAgents ¶
func LoadAgents(path string) (*AgentsFile, error)
LoadAgents reads and parses agents.yaml from path. Environment variables are expanded before parsing. A missing file yields an empty list (not an error) so installations without static workers boot cleanly.
func (*AgentsFile) RootAgent ¶
func (f *AgentsFile) RootAgent() *AgentTemplate
RootAgent returns a pointer to the entry flagged with root: true, or nil if the file has no agents at all (a fresh install before the wizard ran). Callers should treat a nil return as ErrNoRoot equivalent.
The loader's exactly-one-root validation guarantees that when the slice is non-empty there is exactly one matching entry, so we can stop at the first hit.
func (*AgentsFile) SubAgents ¶
func (f *AgentsFile) SubAgents() []AgentTemplate
SubAgents returns the entries that are NOT the root, in the same order they appear on disk. Useful for the spawn-tools machinery and for listing what the user can /agents talk to.
func (*AgentsFile) UtilityAgent ¶
func (f *AgentsFile) UtilityAgent() *AgentTemplate
UtilityAgent returns a pointer to the entry flagged utility: true, or nil when no entry opts in. Callers must treat nil (and an entry with an unset llm) as "fall back to the root's LLM" — the utility agent is an optional cost optimisation, never a requirement.
type BackoffConfig ¶
type BackoffConfig struct {
// Initial is the wait before the first retry (a duration string
// like "1s", "500ms"). Subsequent waits grow by Multiplier.
Initial string `yaml:"initial"`
// Max caps how long a single wait can grow to, so the exponential
// growth does not blow up to minutes. Duration string.
Max string `yaml:"max"`
// Multiplier is the exponential growth factor between attempts.
// Values <= 1 fall back to the default so the backoff still grows.
Multiplier float64 `yaml:"multiplier"`
// Jitter, when true, randomises each wait in the range
// [delay/2, delay] to avoid synchronised retry storms across
// concurrent workers. Default true.
Jitter *bool `yaml:"jitter"`
}
BackoffConfig groups the exponential-backoff tunables under the retry.backoff block. The delay before retry N is:
delay = min(Initial * Multiplier^(N-1), Max)
optionally jittered.
type Config ¶
type Config struct {
Version int `yaml:"version"`
EncryptionKey string `yaml:"encryption_key"`
Runtime RuntimeConfig `yaml:"runtime"`
Guardrails GuardrailsConfig `yaml:"guardrails"`
Theme ThemeConfig `yaml:"theme"`
A2A A2AConfig `yaml:"a2a"`
Providers []ProviderEntry `yaml:"providers"`
MCPs []MCPEntry `yaml:"mcps"`
Spawn SpawnConfig `yaml:"spawn"`
Secrets SecretsConfig `yaml:"secrets"`
}
Config is the root of baifo.yaml.
type ContextGuardConfig ¶
type ContextGuardConfig struct {
Enabled bool `yaml:"enabled"`
Strategy string `yaml:"strategy"`
MaxTokens int `yaml:"max_tokens"`
MaxTurns int `yaml:"max_turns"`
}
ContextGuardConfig wires the adk-utils-go context guard.
type GuardrailsConfig ¶
type GuardrailsConfig struct {
// TrimOversizedUserText truncates oversized user-role text parts
// in the request sent to the model. "User text" covers more than
// what the human types: when a session is resumed under a different
// agent name, the ADK injects the old transcript (tool dumps
// included) AS user-role text ("For context: [agent] ..."), which
// can flood the context window. Model turns and native tool-result
// blocks are never touched. The trim is ephemeral per-request; the
// stored session keeps full fidelity.
TrimOversizedUserText TrimOversizedUserTextConfig `yaml:"trim_oversized_user_text"`
}
GuardrailsConfig groups the optional protections baifo can apply around the model call. Each guardrail is independently toggleable and names the threat it mitigates. Guardrails are OPT-IN: every sub-block defaults to disabled when absent, because they may alter what the user's own content looks like to the model and that must never happen silently. (Producer-side caps — mcps[].options limit_* — are the always-on layer instead: they only bound tool outputs, which the model knows how to re-fetch.)
type MCPAuth ¶
type MCPAuth struct {
// Kind selects the auth mechanism: "none" (default), "oauth".
Kind string `yaml:"kind"`
// ClientID is the OAuth client identifier. Optional; empty enables
// CIMD/DCR discovery on first authenticate.
ClientID string `yaml:"client_id"`
// ClientSecretRef is the name of an entry in secrets.yaml whose
// value is the OAuth client secret. Never the secret itself.
ClientSecretRef string `yaml:"client_secret_ref"`
// Registration selects how baifo obtains an OAuth client when no
// pre-registered ClientID is set. One of:
//
// - "auto" (default): advertise both CIMD (Client ID Metadata
// Document) and DCR (RFC 7591). The MCP SDK prefers CIMD when
// the authorization server announces support for it, otherwise
// it registers dynamically.
// - "cimd": advertise ONLY CIMD. Use when you know the AS
// supports it and want to avoid creating a DCR client.
// - "dcr": advertise ONLY DCR. Use this when the AS announces
// CIMD support but rejects our client_id URL (e.g. the domain
// is not whitelisted in the IdP), which would otherwise make
// the SDK pick CIMD and fail without falling back.
//
// Ignored when ClientID/ClientSecretRef are set (those force the
// client_credentials grant).
Registration string `yaml:"registration"`
}
MCPAuth describes how baifo authenticates against an HTTP MCP. The zero value means no authentication. For oauth, leaving ClientID and ClientSecretRef empty opts into discovery: baifo first tries CIMD (its hardcoded Client ID Metadata Document URL) and falls back to Dynamic Client Registration (RFC 7591) if CIMD is not supported by the authorization server. When ClientID/ClientSecretRef are set, the OAuth client_credentials flow is used directly.
Scopes are NOT modelled here on purpose: they are discovered at authentication time from the protected resource metadata (RFC 9728, /.well-known/oauth-protected-resource).
func (MCPAuth) EffectiveKind ¶
EffectiveKind returns the auth kind with the documented default ("none") applied when the user left it blank.
func (MCPAuth) EffectiveRegistration ¶
EffectiveRegistration returns the registration mode with the documented default ("auto") applied when the user left it blank.
func (MCPAuth) UsesDiscovery ¶
UsesDiscovery reports whether this OAuth entry should try CIMD/DCR instead of using statically configured credentials. It returns true only for oauth entries with both ClientID and ClientSecretRef empty; anything else is treated as a pre-registered client.
type MCPEntry ¶
type MCPEntry struct {
Name string `yaml:"name"`
Type string `yaml:"type"`
// builtin
Builtin string `yaml:"builtin"`
// http
Endpoint string `yaml:"endpoint"`
Headers map[string]string `yaml:"headers"`
Insecure bool `yaml:"insecure"`
// stdio
Command string `yaml:"command"`
Args []string `yaml:"args"`
Env map[string]string `yaml:"env"`
Workdir string `yaml:"workdir"`
// Auth holds the optional authentication block. When absent or with
// kind=none, the MCP is treated as unauthenticated (Headers may still
// carry static tokens — they are orthogonal to auth.kind).
Auth MCPAuth `yaml:"auth"`
// Options carries per-entry tuning for builtin MCPs. Flat by design:
// option keys are prefixed by category (limit_*) instead of nested,
// so the block stays one level deep and easy to autocomplete. Only
// meaningful for type=builtin (each builtin reads the keys it knows;
// unknown-to-that-builtin keys are ignored).
Options MCPOptions `yaml:"options"`
}
MCPEntry is one MCP server declaration. Built-in MCPs use Type=builtin and a Builtin slug; HTTP and stdio MCPs use the corresponding fields.
type MCPOptions ¶
type MCPOptions struct {
// LimitExecOutputChars caps stdout and stderr (each, separately)
// returned by the exec and process_status tools of the builtin
// filesystem MCP. 0 = default (48000). -1 = unlimited.
LimitExecOutputChars int `yaml:"limit_exec_output_chars"`
// LimitReadFileChars caps the total content returned by a single
// read_file call of the builtin filesystem MCP. 0 = default
// (120000). -1 = unlimited.
LimitReadFileChars int `yaml:"limit_read_file_chars"`
// LimitSearchOutputChars caps the total content (matched lines plus
// their context) returned by a single search call of the builtin
// filesystem MCP. Independent of max_results, which only bounds the
// number of matches, not their size. 0 = default (50000).
// -1 = unlimited.
LimitSearchOutputChars int `yaml:"limit_search_output_chars"`
}
MCPOptions is the flat option set for builtin MCPs. The limit_* fields follow a three-state convention: 0 / absent = built-in default, positive = explicit cap in characters, -1 = unlimited (no cap). Disabling a single limit is done with -1; there is no per-option enabled flag (unlike guardrails) because granularity here is per-field.
func (MCPOptions) EffectiveExecOutputChars ¶
func (o MCPOptions) EffectiveExecOutputChars() int
EffectiveExecOutputChars returns the resolved stdout/stderr cap:
- 0 (absent/unset) → DefaultLimitExecOutputChars
- negative → 0, meaning unlimited
- positive → the value as-is
func (MCPOptions) EffectiveReadFileChars ¶
func (o MCPOptions) EffectiveReadFileChars() int
EffectiveReadFileChars returns the resolved read_file total-output cap:
- 0 (absent/unset) → DefaultLimitReadFileChars
- negative → 0, meaning unlimited
- positive → the value as-is
func (MCPOptions) EffectiveSearchOutputChars ¶ added in v0.2.0
func (o MCPOptions) EffectiveSearchOutputChars() int
EffectiveSearchOutputChars returns the resolved search total-output cap:
- 0 (absent/unset): DefaultLimitSearchOutputChars
- negative: 0, meaning unlimited
- positive: the value as-is
type ProviderEntry ¶
type ProviderEntry struct {
Name string `yaml:"name"`
Type string `yaml:"type"`
URL string `yaml:"url"`
Auth string `yaml:"auth"` // "api_key" (default) | "oauth"
APIKey string `yaml:"api_key"`
Headers map[string]string `yaml:"headers"`
// Streaming controls whether agents backed by this provider run
// in SSE streaming mode. A pointer so an omitted field means "use
// the default" (streaming ON) rather than the zero value. Set it
// to false only for OpenAI-compatible endpoints that do not
// implement Server-Sent Events; those reject a streaming request
// or hang. Streaming is required for long Anthropic turns (the API
// refuses non-streamed responses that may exceed 10 minutes, which
// high reasoning budgets can), so leave it on for Anthropic.
Streaming *bool `yaml:"streaming"`
}
ProviderEntry is one LLM provider declaration. Reference by `Name` from root.llm and agent specs.
func (ProviderEntry) StreamingEnabled ¶
func (p ProviderEntry) StreamingEnabled() bool
StreamingEnabled reports the resolved streaming setting: true unless the operator explicitly set streaming: false. Centralised so every consumer agrees on the default.
type RetryConfig ¶
type RetryConfig struct {
// Enabled turns retries on. Default false (no retries) when the
// whole block is absent; the loader flips it on when the user
// provides any retry field, so writing a block implies intent.
Enabled *bool `yaml:"enabled"`
// MaxAttempts is the TOTAL number of tries, including the first.
// 1 means "no retry". Values < 1 are treated as the default.
MaxAttempts int `yaml:"max_attempts"`
// Strategy selects how the wait before each retry is computed:
//
// "backoff" exponential backoff from the Backoff block (default).
// "retry-after" honour the provider's Retry-After header when the
// failure carries one (e.g. a 429 rate limit), and
// fall back to the exponential backoff otherwise.
Strategy string `yaml:"strategy"`
// Backoff holds the exponential-backoff knobs. They drive the
// "backoff" strategy and act as the fallback for "retry-after"
// when no header is present.
Backoff BackoffConfig `yaml:"backoff"`
}
RetryConfig describes the exponential-backoff retry policy applied to every LLM provider call. The delay before attempt N is:
delay = min(InitialBackoff * Multiplier^(N-1), MaxBackoff)
optionally jittered. With MaxAttempts=4, InitialBackoff=1s and Multiplier=2 the waits are roughly 1s, 2s, 4s before giving up — so a flaky provider gets several escalating chances before the turn fails.
func (RetryConfig) Attempts ¶
func (r RetryConfig) Attempts() int
Attempts returns the effective total attempt count, applying the default and a floor of 1.
func (RetryConfig) InitialBackoffDuration ¶
func (r RetryConfig) InitialBackoffDuration() time.Duration
InitialBackoffDuration parses the backoff initial wait, falling back to the default on empty or invalid input.
func (RetryConfig) JitterEnabled ¶
func (r RetryConfig) JitterEnabled() bool
JitterEnabled returns the effective jitter flag, defaulting to true.
func (RetryConfig) MaxBackoffDuration ¶
func (r RetryConfig) MaxBackoffDuration() time.Duration
MaxBackoffDuration parses the backoff cap, falling back to the default.
func (RetryConfig) MultiplierOr ¶
func (r RetryConfig) MultiplierOr() float64
MultiplierOr returns the effective multiplier, applying the default when the configured value would not grow the backoff (<= 1).
func (RetryConfig) RetryEnabled ¶
func (r RetryConfig) RetryEnabled() bool
RetryEnabled reports whether retries are on. A wholly-absent block is off; an explicit enabled flag wins; otherwise providing any field implies the user wants retries.
func (RetryConfig) StrategyOr ¶
func (r RetryConfig) StrategyOr() string
StrategyOr returns the effective retry strategy, normalising the input and falling back to the default on empty or unknown values.
type RuntimeConfig ¶
type RuntimeConfig struct {
LogLevel string `yaml:"log_level"`
LogFormat string `yaml:"log_format"`
LogFile string `yaml:"log_file"`
RedactLogs *bool `yaml:"redact_logs"`
AutoResumeSession *bool `yaml:"auto_resume_session"`
ChatAutoScroll *bool `yaml:"chat_auto_scroll"`
ChatKeepToolsExpanded *bool `yaml:"chat_keep_tools_expanded"`
// Retry controls how baifo retries failing LLM provider API calls
// (rate limits, overloads, transient network errors) with an
// incremental exponential backoff. Absent / disabled means no
// retries (the historical behaviour).
Retry RetryConfig `yaml:"retry"`
}
RuntimeConfig groups process-level knobs.
func (RuntimeConfig) AutoResumeSessionEnabled ¶
func (r RuntimeConfig) AutoResumeSessionEnabled() bool
AutoResumeSessionEnabled returns the effective value of AutoResumeSession, defaulting to true when the field is absent.
func (RuntimeConfig) ChatAutoScrollEnabled ¶
func (r RuntimeConfig) ChatAutoScrollEnabled() bool
ChatAutoScrollEnabled returns the effective value of ChatAutoScroll, defaulting to true when the field is absent. The TUI calls this to decide whether new events should pin the chat viewport to the bottom.
func (RuntimeConfig) ChatKeepToolsExpandedEnabled ¶
func (r RuntimeConfig) ChatKeepToolsExpandedEnabled() bool
ChatKeepToolsExpandedEnabled returns the effective value of ChatKeepToolsExpanded, defaulting to false when the field is absent.
func (RuntimeConfig) RedactLogsEnabled ¶
func (r RuntimeConfig) RedactLogsEnabled() bool
RedactLogsEnabled returns the effective value of RedactLogs, defaulting to true when the field is absent.
type SecretsConfig ¶
type SecretsConfig struct {
RedactInLogs *bool `yaml:"redact_in_logs"`
RedactInTUI *bool `yaml:"redact_in_tui"`
// ScrubToolResults toggles the comprehensive-redaction pass that
// runs after every tool call. The targeted pass (scrubbing the
// raw values the BeforeToolCallback just substituted) is always
// on; this knob controls the *additional* sweep that scans the
// result for ANY value currently in `secrets.yaml`, even ones
// the model never asked for.
//
// Recommended: leave it on. It defends against the "tools that
// emit secrets they were not given" class of leak — e.g. an MCP
// echoing a debug header that happens to contain the value of a
// secret stored under a different name. The cost is a small
// number of substring scans per tool call; for typical
// deployments (a few dozen secrets, tool results under a few
// hundred KB) it adds milliseconds.
//
// Default when omitted: true.
ScrubToolResults *bool `yaml:"scrub_tool_results"`
// MinScrubLength is the minimum length (in bytes) a stored
// secret value must have to be eligible for the comprehensive
// pass. Below this floor the value is skipped to avoid
// catastrophic false positives — e.g. a secret stored with
// value "1234" would otherwise redact every "1234" anywhere in
// any tool result, mangling file contents, JSON numbers, port
// numbers, you name it.
//
// Choose a floor high enough that legitimate substrings of that
// length almost never appear by accident in tool output, but
// not so high that real, short secrets stop being protected.
// The trade-off is direct: HIGHER values → FEWER false
// positives but MORE secrets bypassed; LOWER values → MORE
// values protected but MORE chance of redacting unrelated text.
//
// Reference points:
// - 8 bytes (default) — protects every API key worth
// protecting; lets values up to 7 bytes (PINs, short
// passwords) escape the comprehensive pass.
// - 12 bytes — most modern API keys fit (`ghp_*`, `sk-*`,
// `AKIA…`). Short personal secrets are filtered out.
// - 16 bytes — only long, high-entropy values are scanned.
//
// Short secrets (below the floor) remain protected by the
// targeted pass when the LLM explicitly references them via
// `${secret:NAME}`. Only the "leaked from nowhere" scenario is
// excluded for those values — which is generally acceptable
// because short, low-entropy secrets are not the threat model
// the comprehensive pass exists for.
//
// 0 or negative disables the floor entirely (every length is
// scrubbed). Documented as dangerous and not recommended.
//
// Default when omitted: 8.
MinScrubLength *int `yaml:"min_scrub_length"`
}
SecretsConfig groups runtime behaviour of the secrets pipeline.
func (SecretsConfig) EffectiveMinScrubLength ¶
func (c SecretsConfig) EffectiveMinScrubLength() int
EffectiveMinScrubLength returns the effective value of MinScrubLength, defaulting to 8 when the field is absent. The default balances real API keys (always 16+ bytes) against accidental matches on short values. Values below 8 are accepted but documented as dangerous because they raise the false-positive rate sharply.
func (SecretsConfig) LogRedactionEnabled ¶
func (c SecretsConfig) LogRedactionEnabled() bool
LogRedactionEnabled returns the effective value of RedactInLogs, defaulting to true when the field is absent.
func (SecretsConfig) ScrubToolResultsEnabled ¶
func (c SecretsConfig) ScrubToolResultsEnabled() bool
ScrubToolResultsEnabled returns the effective value of ScrubToolResults, defaulting to true when the field is absent. Defense in depth is the right default; operators opt out explicitly when a debugging session needs raw output.
func (SecretsConfig) TUIRedactionEnabled ¶
func (c SecretsConfig) TUIRedactionEnabled() bool
TUIRedactionEnabled returns the effective value of RedactInTUI, defaulting to true when the field is absent.
type SpawnConfig ¶
type SpawnConfig struct {
Mode string `yaml:"mode"`
CollectTimeout time.Duration `yaml:"collect_timeout"`
}
SpawnConfig governs which spawn tools the root agent receives. mode is one of: none, static, dynamic, both. See DECISIONS.md #6.
func (SpawnConfig) DynamicEnabled ¶
func (s SpawnConfig) DynamicEnabled() bool
DynamicEnabled reports whether the root should receive the dynamic spawn tools ("dynamic" or "both"). Dynamic tools land in Phase 6; the helper is exposed already so the wiring is symmetric.
func (SpawnConfig) EffectiveMode ¶
func (s SpawnConfig) EffectiveMode() string
EffectiveMode returns the spawn mode with the documented default ("both") applied when the user did not set one.
func (SpawnConfig) StaticEnabled ¶
func (s SpawnConfig) StaticEnabled() bool
StaticEnabled reports whether the root should receive the static spawn / supervise tools ("static" or "both").
type ThemeConfig ¶
type ThemeConfig struct {
NerdFonts bool `yaml:"nerd_fonts"`
}
ThemeConfig controls terminal-capability rendering options. The colour palette itself is fixed (the Canarias theme) and is NOT user-configurable; the only knob here is whether the terminal can render Nerd Font glyphs.
type TrimOversizedUserTextConfig ¶
type TrimOversizedUserTextConfig struct {
// Enabled toggles this guardrail. Default FALSE when absent:
// guardrails are opt-in (pointer-bool kept for symmetry with the
// rest of the config and so an explicit `enabled: false` is
// distinguishable from an absent block in future migrations).
Enabled *bool `yaml:"enabled"`
// MaxChars caps each user-role text part, in characters.
// 0 / absent = default (DefaultTrimOversizedUserTextMaxChars).
// Positive = explicit cap.
// Disabling is done via enabled: false, not via this field.
MaxChars int `yaml:"max_chars"`
}
TrimOversizedUserTextConfig controls the guardrail that caps oversized user-role text parts before each model call.
func (TrimOversizedUserTextConfig) EffectiveCap ¶
func (c TrimOversizedUserTextConfig) EffectiveCap() int
EffectiveCap returns 0 when the guardrail is disabled (IsEnabled()==false), and EffectiveMaxChars() otherwise. Callers can pass the single returned int to BuildContextTrimPlugin: 0 disables the plugin, positive caps it.
func (TrimOversizedUserTextConfig) EffectiveMaxChars ¶
func (c TrimOversizedUserTextConfig) EffectiveMaxChars() int
EffectiveMaxChars returns the resolved per-part cap:
- 0 / absent (unset) → DefaultTrimOversizedUserTextMaxChars
- negative → DefaultTrimOversizedUserTextMaxChars (negative no longer means disabled; use enabled: false for that)
- positive → the value as-is
func (TrimOversizedUserTextConfig) IsEnabled ¶
func (c TrimOversizedUserTextConfig) IsEnabled() bool
IsEnabled reports whether the trim_oversized_user_text guardrail is active. The default (nil Enabled pointer) is FALSE — guardrails are opt-in; the operator turns this one on with enabled: true.