config

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package config holds the bee runtime configuration schema and loader.

Layered resolution: Defaults() < ~/.bee/config.toml < env vars. Profiles (tiny/normal/large) overlay budgets onto the top-level fields so the rest of the codebase only ever reads flat values.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConfigPath

func ConfigPath() string

ConfigPath returns the resolved path to bee's TOML config. Override with BEE_CONFIG; otherwise ~/.bee/config.toml.

func FastModelOf

func FastModelOf(c Config) string

FastModelOf resolves the cheap side-eval model: cfg.FastModel when set, otherwise the default model.

func IsLocalProvider

func IsLocalProvider(name string) bool

IsLocalProvider returns true when the named provider runs on-host. Local providers skip cost rendering, skip the auto-mode classifier, and use a 32k context floor when the model registry has no window.

func IsLoopbackURL

func IsLoopbackURL(u string) bool

IsLoopbackURL returns true when u points at localhost / 127.x.x.x / ::1.

func ResolveAutoProfile

func ResolveAutoProfile(model string) string

ResolveAutoProfile picks a profile name from a model id alone. Kept for back-compat; prefer ResolveAutoProfileForProvider so local providers (ollama / lmstudio) get the tiny surface regardless of model size.

func ResolveAutoProfileForProvider

func ResolveAutoProfileForProvider(provider, model string) string

ResolveAutoProfileForProvider picks a profile name from provider + model. Local providers (ollama, lmstudio) always resolve to tiny — even a 35b local model fumbles a wide tool surface and benefits from plain-english prompts. Heuristic, not exhaustive; falls back to "normal".

Why: small local models work best with a narrow, plain-named tool set (read/bash/edit/write) described in normal english. Local runs get that surface; richer surfaces stay for frontier hosted models.

Types

type BrowserConfig

type BrowserConfig struct {
	Enabled    bool                `toml:"enabled"`
	Headless   bool                `toml:"headless"`    // default false: headful so the user can watch
	ChromePath string              `toml:"chrome_path"` // empty -> auto-detect
	Vision     BrowserVisionConfig `toml:"vision"`
}

BrowserConfig gates and configures the native browser tools. Off by default to keep the tool surface lean for tiny-context profiles; flip via config or the --browser flag.

type BrowserVisionConfig

type BrowserVisionConfig struct {
	Model    string `toml:"model"`
	Endpoint string `toml:"endpoint"` // ollama base url, e.g. http://localhost:11434
}

BrowserVisionConfig points browser_screenshot at a local vision model. Model empty -> the screenshot tool is not registered.

type CompactionConfig

type CompactionConfig struct {
	Enabled   bool    `toml:"enabled"`
	Threshold float64 `toml:"threshold"` // 0.0–1.0
}

CompactionConfig controls auto-summarization of long histories. Threshold is the fraction of the total context budget at which the loop auto-compacts.

type Config

type Config struct {
	DefaultProvider string `toml:"default_provider"`
	DefaultModel    string `toml:"default_model"`
	// FastModel is a cheap model for side evals like /goal completion checks;
	// empty => use default_model.
	FastModel string `toml:"fast_model"`
	Caveman   string `toml:"caveman"`
	Profile   string `toml:"profile"`
	Thinking  string `toml:"thinking"` // auto | off | low | medium | high
	// Mode gates how the agent reacts to user input. plan = read-only
	// research + proposed plan, no mutations. edit = full tool surface
	// (default). auto = side-LLM classifier picks plan|edit per turn.
	Mode       string                    `toml:"mode"` // plan | auto | edit
	Sandbox    SandboxConfig             `toml:"sandbox"`
	Shell      ShellConfig               `toml:"shell"`
	Memory     MemoryConfig              `toml:"memory"`
	Compaction CompactionConfig          `toml:"compaction"`
	Providers  map[string]ProviderConfig `toml:"providers"`
	Profiles   map[string]Profile        `toml:"profiles"`

	// APIKey is the resolved key for the active provider. Populated by Load
	// from os.Getenv(provider.EnvKey). Not persisted to disk.
	APIKey string `toml:"-"`

	// ShowBanner controls the ASCII/emoji bee logo printed at TUI startup
	// AND the braille intro animation. Toggle via /settings; takes effect
	// on next launch (intro is a one-shot startup animation).
	ShowBanner bool `toml:"show_banner"`

	// ShowLoader controls the braille "generating" animation shown while
	// the model is producing the next turn (pre-token loader + animated
	// caret). Default true. Toggle via /settings; persists across launches.
	ShowLoader bool `toml:"show_loader"`

	// MaxIterations caps tool-use rounds per Run. 0 = unlimited (loop until the
	// token-budget or read-only-stall guard fires). config.Defaults() seeds 50;
	// raise for tool-heavy agents, set 0 to lift the cap, lower to fail fast.
	MaxIterations int `toml:"max_iterations"`

	// Verbose unlocks full tool-output rendering in the TUI (compact one-line
	// preview otherwise). Toggle via /settings; persists across launches.
	Verbose bool `toml:"verbose"`

	// ShowThoughts controls whether BlockThinking chain-of-thought is rendered
	// in scrollback. Default true. Toggle via /settings; persists across launches.
	ShowThoughts bool `toml:"show_thoughts"`

	// ShowNudges controls whether synthetic `[nudge]` user messages — emitted
	// by the loop's reasoning-only stall recovery — appear in the transcript.
	// Default false (hidden). Toggle via /settings; persists across launches.
	// Loop behavior is unaffected; this is a render-time filter only.
	ShowNudges bool `toml:"show_nudges"`

	// ShowRecap enables a one-line post-turn recap synthesized by a cheap
	// side-LLM call against the freshly finished assistant message. Off by
	// default (extra tokens, off-fast-path). Toggle via /settings; persists
	// across launches. Disabled = no generation, no render.
	ShowRecap bool `toml:"show_recap"`

	// Compact strips the spacing layer from the TUI (no outer gutter, no
	// blank line between turns, no user bg-tint, no OSC 133 prompt zones).
	// Default false = clean mode. Set true on small terminals or for a
	// denser layout. Toggle via /settings; persists across launches.
	Compact bool `toml:"compact"`

	// ShowContextBar reveals the thin context-fill progress strip pinned to
	// the bottom edge. Default false because the bee-glyph hex fill in the
	// top bar already conveys window utilisation; the bottom strip just adds
	// a row of visual noise. Toggle via /settings; persists across launches.
	ShowContextBar bool `toml:"show_context_bar"`

	// Highlight gates syntax highlighting (chroma) on tool output, file
	// content, edit/write diffs, and bash command summaries. Default true.
	// Toggle via /settings; persists across launches.
	Highlight bool `toml:"highlight"`

	// ShellBangSilent flips the behavior of the inline shell prefix `!`.
	// Default true = `!cmd` runs locally and the output is NOT forwarded to
	// the LLM (silent). false restores the legacy behavior where `!cmd`
	// appends its output to a user turn. `!!cmd` always runs in the
	// opposite mode (escape hatch). Toggle via /settings.
	ShellBangSilent bool `toml:"shell_bang_silent"`

	// Editor is the command launched by ctrl+o and /edit. Empty resolves at
	// runtime: $VISUAL, then $EDITOR, then vim.
	Editor string `toml:"editor"`

	// Top-bar chrome toggles. Default true for each preserves the original
	// status-line look; flipping all five off collapses the entire top row.
	// Toggle via /settings; persists across launches.
	ShowBee         bool `toml:"show_bee"`          // 🐝 glyph
	ShowContextPct  bool `toml:"show_context_pct"`  // "4%" next to glyph
	ShowModel       bool `toml:"show_model"`        // provider/model label
	ShowCwd         bool `toml:"show_cwd"`          // current working dir
	ShowEffort      bool `toml:"show_effort"`       // "t:max" thinking level
	ShowTurnTimer   bool `toml:"show_turn_timer"`   // ⏱ live / final elapsed
	ShowGitBranch   bool `toml:"show_git_branch"`   // ⎇ current git branch
	ShowTotalTokens bool `toml:"show_total_tokens"` // Σ session tokens (in+out)

	// ExtraTools opts specific tools into the manifest beyond the active
	// profile's allowlist. Names match tool Spec().Name (e.g. "apply_patch",
	// "hashline_edit"). The default keeps the surface minimal; this is the
	// escape hatch for power users who want expert-mode mutators without
	// bumping to the `large` profile.
	ExtraTools []string `toml:"extra_tools"`

	// DisabledTools hides specific tools from the model regardless of profile
	// allowlists. Toggled via /tools. Names match tool Spec().Name.
	DisabledTools []string `toml:"disabled_tools"`

	// UserTools are caller-defined shell-alias tools. Each entry registers a
	// new tool whose Run executes a fixed bash command. Added via `/tools add`
	// and persisted to ~/.bee/config.toml.
	UserTools []UserTool `toml:"user_tools"`

	// Browser gates the native chromedp-backed browser tools.
	Browser BrowserConfig `toml:"browser"`

	// Vision configures a fallback multimodal model. When the main model lacks
	// vision, the loop routes image blocks to this model, gets text back, and
	// injects it so blind models can still work with screenshots/pasted images.
	Vision VisionConfig `toml:"vision"`

	// UpdateCheck gates the hourly upstream-update probe.
	//   "ask"  — probe and surface a modal when main has new commits (default)
	//   "auto" — probe and apply silently (notice surfaces via warn line)
	//   "off"  — no probe, no prompt
	// Picked from the modal's four buttons; persists across launches.
	UpdateCheck string `toml:"update_check"`

	// UpdateRepo lets forks point the probe at a different GitHub repo.
	// Empty = elhenro/bee.
	UpdateRepo string `toml:"update_repo"`

	// UpdateBranch is the branch to compare against. Empty = main.
	UpdateBranch string `toml:"update_branch"`
}

Config is the merged, post-resolution view of bee's settings. Adapters and the agent loop read from this; nothing else.

func ApplyProfile

func ApplyProfile(c Config) Config

ApplyProfile overlays the active profile onto top-level Config fields that are still zero. Explicit user choices win over profile defaults; the profile only fills gaps. Also resolves c.Profile == "auto" in place so downstream code sees the concrete name. Local providers (ollama / lmstudio) skip the auto-mode classifier — c.Mode falls back to "edit" because the classifier round-trip is wasteful on slow on-host models.

func Defaults

func Defaults() Config

Defaults returns the canonical out-of-the-box configuration: OpenRouter + deepseek-v4-flash, three profiles, caveman-full, workspace-write-net + on-request sandbox, memory enabled with top_k=3.

Zero-config startup: set OPENROUTER_API_KEY and bee runs.

func Load

func Load() (Config, error)

Load resolves the merged config: Defaults < ~/.bee/config.toml < env vars. Finally, looks up the active provider's EnvKey to populate APIKey; returns a clear error if the key is required but missing.

type MemoryConfig

type MemoryConfig struct {
	Enabled             bool `toml:"enabled"`
	TopK                int  `toml:"top_k"`
	BackgroundExtractor bool `toml:"background_extractor"`
}

MemoryConfig gates the heuristic memory loop. Enabled=false skips both scan and select on every turn.

type OAuthConfig

type OAuthConfig struct {
	ClientID          string `toml:"client_id"`
	AuthorizeEndpoint string `toml:"authorize_endpoint"`
	TokenEndpoint     string `toml:"token_endpoint"`
	Scope             string `toml:"scope"`
	// RedirectPath defaults to /callback when empty.
	RedirectPath string `toml:"redirect_path"`
	// RedirectPort pins the loopback to a fixed port. Some providers only
	// allow an EXACT redirect_uri match so a random port fails authorize.
	// 0 = random.
	RedirectPort int `toml:"redirect_port"`
	// ExtraAuthorizeParams are added to the authorize URL verbatim. Use for
	// vendor-specific knobs like audience, prompt, id_token_hint.
	ExtraAuthorizeParams map[string]string `toml:"extra_authorize_params"`
	// AccountIDHeader, when set, injects the per-account id from the saved
	// token's id_token claim into this header on every request. ChatGPT
	// backend requires "chatgpt-account-id".
	AccountIDHeader string `toml:"account_id_header"`
	// AccountIDClaim is the JWT claim name in id_token that holds the account
	// id. Default for openai is "https://api.openai.com/auth" -> ".chatgpt_account_id".
	AccountIDClaim string `toml:"account_id_claim"`
}

OAuthConfig configures a generic OAuth 2.0 PKCE flow for a provider. bee does not ship preconfigured client_ids for any vendor — users supply their own under [providers.<name>.oauth].

type Profile

type Profile struct {
	SystemPromptBudget       int    `toml:"system_prompt_budget"`
	MemoryTopK               int    `toml:"memory_top_k"`
	MemoryBodyChars          int    `toml:"memory_body_chars"` // per-memory body cap; 0 → unbounded
	ToolDescChars            int    `toml:"tool_desc_chars"`
	SkillManifestChars       int    `toml:"skill_manifest_chars"`
	Caveman                  string `toml:"caveman"`
	MaxIterations            int    `toml:"max_iterations"`              // iter cap override; 0 → inherit cfg.MaxIterations; negative → unlimited
	NoMutationStallThreshold int    `toml:"no_mutation_stall_threshold"` // streak threshold for stall warning; 0 → off (opt-in)
	// ToolFormat selects how tools are advertised. "" = native tool_calls
	// channel (default); "xml" = wrap inner provider with TextModeProvider
	// to inject a text-mode advert + parse `<name>{...}</name>` from the
	// assistant stream. Opt-in for local/tiny models that ignore tool_calls.
	ToolFormat string `toml:"tool_format"`
	// ToolOutputTokens caps a single tool-result payload in token estimates
	// (chars/4). 0 → fall back to per-tool default in internal/tools. Tiny
	// profile uses a much smaller cap so one fat `read` doesn't blow a 4-8k
	// local-model context in a single turn.
	ToolOutputTokens int `toml:"tool_output_tokens"`
	// SkipApplyPatch removes the apply_patch tool from the manifest. Tiny
	// models mis-emit unified diffs (wrong context lines, off-by-one hunks);
	// edit_diff + hashline_edit + write cover the same mutation surface
	// with shapes small models hit reliably.
	SkipApplyPatch bool `toml:"skip_apply_patch"`
	// ReadDefaultLines is the default line slice when the model omits `lines`.
	// 0 → tool's own default. Tiny uses 100 to stop one read torching the window.
	ReadDefaultLines int `toml:"read_default_lines"`
	// ReadMaxLines caps the largest slice a single read can return. 0 → tool default.
	ReadMaxLines int `toml:"read_max_lines"`
	// GrepMaxMatches caps grep result count per call. 0 → tool default.
	GrepMaxMatches int `toml:"grep_max_matches"`
	// Temperature / TopP pin sampling for this profile. Zero values mean
	// "use provider default". Tiny pins temperature=0 (deterministic tool
	// turns) with top_p=0.8 to keep 4-bit MoE outputs anchored.
	Temperature float64 `toml:"temperature"`
	TopP        float64 `toml:"top_p"`
	// ShowRecap, when non-nil, overrides Config.ShowRecap. Tiny sets false
	// so the side-LLM recap round-trip doesn't double turn latency on slow
	// local runs.
	ShowRecap *bool `toml:"show_recap"`

	// Safety carries per-profile calibration applied on top of the global
	// sandbox + approval config. Tiny profile defaults to requiring the user
	// to re-confirm destructive ops even after AllowSession was granted, so
	// a hallucinating small model can't piggyback on one "yes" to run more
	// destructive commands later. See safety.DefaultsForProfile.
	Safety ProfileSafety `toml:"safety"`

	// Escalation carries the optional "larger fallback model" wiring. The
	// engine itself never re-enters Run with this — handoff is caller-driven
	// (cmd/bee/run.go or the `bee escalate` subcommand). All fields default
	// to zero / off so this is fully opt-in.
	Escalation ProfileEscalation `toml:"escalation"`
}

Profile carries the small-model-friendly context budgets defined in PLAN §6b. Profile values are applied onto Config top-level fields by ApplyProfile.

func ActiveProfile

func ActiveProfile(c Config) Profile

ActiveProfile returns the profile named by c.Profile, falling back to "normal" and then to a zero Profile if neither exists. "auto" resolves to tiny/normal/large by provider + model class via ResolveAutoProfileForProvider.

func ScaleProfileForContext

func ScaleProfileForContext(p Profile, profileName string, ctxWindow int) Profile

ScaleProfileForContext widens tiny-profile budgets when the active model reports a context window much larger than the tiny default. Sparse MoE models like Qwen3.6-35B-A3B-4bit advertise 128k context but the canned tiny profile pins SystemPromptBudget=3000 / ToolOutputTokens=1500, leaving ~95% of the window unused.

Heuristic: at ctxWindow > 16k, scale SystemPromptBudget to min(ctx*0.05, 8000) and ToolOutputTokens to min(ctx*0.02, 4000). Caveman ultra stays on (reasoning depth doesn't grow with context); the 4-tool surface just gets room to breathe.

Returns the input unchanged when profile isn't tiny or ctxWindow ≤ 16k. Caller passes the resolved profile name (after "auto" → "tiny" mapping).

type ProfileEscalation

type ProfileEscalation struct {
	// Provider id from Config.Providers. Empty = no handoff configured.
	Provider string `toml:"provider"`
	// Model id understood by Provider. Empty = no handoff configured.
	Model string `toml:"model"`
}

ProfileEscalation configures the optional handoff path for when a tiny model wedges (two-strike) or calls the escalate tool. The model id is generic so this stays vendor-neutral.

type ProfileSafety

type ProfileSafety struct {
	WriteRoot             string   `toml:"write_root"`
	ExtraSafeCommands     []string `toml:"extra_safe_commands"`
	RequireApprovalKeys   []string `toml:"require_approval_keys"`
	WarnOnDuplicateWrites bool     `toml:"warn_on_duplicate_writes"`
}

ProfileSafety mirrors safety.ProfileSafety in the config schema. Kept here (rather than importing the safety package) so config has no upward dep on the safety package; defaults are seeded by safety.DefaultsForProfile via the bridge in defaults.go.

type ProviderConfig

type ProviderConfig struct {
	BaseURL      string       `toml:"base_url"`
	WireAPI      string       `toml:"wire_api"`
	EnvKey       string       `toml:"env_key"`
	DefaultModel string       `toml:"default_model"`
	OAuth        *OAuthConfig `toml:"oauth"` // optional; enables /login <provider>
	// KeyOptional marks providers whose api key is optional (e.g. omlx run
	// locally with admin-panel "skip localhost auth" enabled). When true,
	// Load won't error if EnvKey is set but unresolved and no key file is
	// stored — bee proceeds without an Authorization header.
	KeyOptional bool `toml:"key_optional"`
	// ChatTemplateKwargs flows into the MLX/vllm-extended chat completion body
	// as `chat_template_kwargs`. Used to flip Qwen3 / Hermes chat-template
	// switches like `enable_thinking=false` so the model emits canonical tool
	// envelopes instead of prose summaries. Omitted when empty.
	ChatTemplateKwargs map[string]any `toml:"chat_template_kwargs"`
}

ProviderConfig pairs a base_url with a wire_api selector. One adapter per wire format handles every OpenAI-compatible service.

type SandboxConfig

type SandboxConfig struct {
	Scope            string   `toml:"scope"`
	Approval         string   `toml:"approval"`
	CommandAllowlist []string `toml:"command_allowlist"`
}

SandboxConfig is a two-axis sandbox policy.

Scope: read-only | workspace-write | workspace-write-net | danger-full-access. Approval: untrusted | on-request | on-failure | never.

CommandAllowlist holds safety.DangerousPattern keys the user has granted AllowAlways. Loaded into the approval.Cache at startup; appended via PersistSetting when the user picks AllowAlways at a prompt.

type ShellConfig

type ShellConfig struct {
	UseUserRC bool   `toml:"use_user_rc"`
	Shell     string `toml:"shell"`   // override $SHELL (e.g. "/bin/zsh"); empty = autodetect
	RCFile    string `toml:"rc_file"` // override rc path; empty = .zshrc / .bashrc per shell
}

ShellConfig controls how the bash tool launches commands. Default keeps the hermetic `bash -c` shape (no rc files). UseUserRC=true sources the user's interactive rc file before each command so aliases and functions from .zshrc / .bashrc become available. Tradeoff: leaks rc-banner output into tool results, slower startup, breaks reproducibility — opt in only.

type UserTool

type UserTool struct {
	Name        string `toml:"name"`
	Command     string `toml:"command"`
	Description string `toml:"description"`
}

UserTool describes a custom shell-alias tool. Name becomes the tool id the model sees; Command is the bash command that runs on invocation. Optional arg fields let the model pass dynamic input appended to Command.

type VisionConfig

type VisionConfig struct {
	Model    string `toml:"model"`
	Endpoint string `toml:"endpoint"` // base url, e.g. http://localhost:8080/v1
	API      string `toml:"api"`      // "openai" (default) | "ollama"
	EnvKey   string `toml:"env_key"`  // env var holding the api key (optional for local)
	// Provider, when set, inherits base_url + env_key from that configured
	// [providers.<name>] entry, so a vision model served by the same backend
	// as the main model needs only `provider` + `model`. Explicit Endpoint /
	// EnvKey here still win.
	Provider string `toml:"provider"`
}

VisionConfig points the loop's vision fallback at a multimodal model. Model empty -> no fallback: images hitting a non-vision main model are dropped with a one-time hint to configure this or run /vision. API selects the wire shape: "openai" (default — omlx/LM Studio/vLLM/hosted qwen-VL) or "ollama".

Jump to

Keyboard shortcuts

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