boot

package
v0.1.5 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2026 License: MIT Imports: 39 Imported by: 0

Documentation

Overview

Package boot assembles a ready-to-drive control.Controller from configuration: it loads config, resolves the model(s), builds the tool registry (built-ins + plugins), wires the permission gate, and constructs the executor. It is the one place that turns "what the user configured" into "a Controller a frontend can drive", so every frontend — the terminal TUI, the HTTP/SSE server, the desktop webview — shares the exact same assembly instead of each re-deriving it. Frontends pass only a sink and a couple of run knobs; everything else comes from config.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnknownModel = errors.New("unknown model")

ErrUnknownModel is returned by Build when the configured model can't be resolved to a provider — e.g. a default_model left over from a renamed or removed provider. Callers can detect it (errors.Is) to re-run setup.

Functions

func Build

func Build(ctx context.Context, opts Options) (*control.Controller, error)

Build loads config, resolves the model(s), and returns a Controller wrapping a single Agent. The returned controller owns plugin subprocesses; call Close (via Controller.Close) to release them. to release them.

func GlobalBudget

func GlobalBudget() *provider.RequestBudget

GlobalBudget exposes the budget for the desktop layer (status display, cost estimates, and direct callers like RagAsk that talk HTTP outside the provider layer). May be nil when limiting is off.

func LSPSpecs

func LSPSpecs(cfg config.LSPConfig) map[string]lsp.ServerSpec

LSPSpecs returns the language → server map: the built-in defaults overlaid with any user overrides. A user entry may set only the fields it wants to change; empty fields keep the default for that language.

func MCPStartupNotice

func MCPStartupNotice(failures []plugin.Failure) (text string, ok bool)

MCPStartupNotice formats the warning shown when configured MCP servers failed to connect, naming the first few; ok is false when none failed.

func NewProvider

func NewProvider(e *config.ProviderEntry) (provider.Provider, error)

NewProvider builds a provider.Provider from a configured entry. Exported so custom assemblers (e.g. the ACP per-session factory) can reuse it without going through the full Build.

func NewProviderWithProxy

func NewProviderWithProxy(e *config.ProviderEntry, proxy netclient.ProxySpec, mainProvider bool) (provider.Provider, error)

NewProviderWithProxy builds a provider.Provider with the configured ordinary network proxy settings, and wraps it with the global request-budget decorator (when [llm] rpm > 0) so it shares the per-API-key RPM quota.

mainProvider marks the provider as the main-agent's (high-priority RPM slots, protected by reserve_main); background providers (subagents, classifiers, VLM, etc.) pass false. mainProvider is threaded explicitly so concurrent boot.Build calls don't race on a process-global "which provider is main" flag.

func PluginSpecs

func PluginSpecs(entries []config.PluginEntry) []plugin.Spec

PluginSpecs maps configured plugin entries to plugin.Spec, expanding ${VAR} references. Exported so custom assemblers can connect the config's plugins alongside their own (e.g. ACP's per-session MCP servers).

func RagAskBudgetKey

func RagAskBudgetKey(cfg *config.Config) string

RagAskBudgetKey returns the budget bucket key for a knowledge-base Q&A call, resolving from cfg the same model RagAsk uses (fast_task_model, then the default). Callers that talk /chat/completions directly (outside the provider layer) use this with GlobalBudget().Acquire so their calls share the per-minute quota of the model they target.

func RebindRAGBudget

func RebindRAGBudget(extractor any, cfg *config.Config)

RebindRAGBudget re-injects the current globalBudget into an extractor, so a runtime RPM change (settings rebuild) or the first boot.Build propagates to RAG extraction without an app restart. extractor may be nil or not implement rag.BudgetSetter (e.g. HE-based extraction), in which case nothing is rebound. Pass the loaded config so the RAG bucket key resolves to the extract model.

func SetBrowserUseClientProvider

func SetBrowserUseClientProvider(fn func() *browseruse.Client)

SetBrowserUseClientProvider injects the sidecar-client resolver. Called by the desktop app once its BrowserUseService is created.

Types

type Options

type Options struct {
	Model      string
	MaxSteps   int
	RequireKey bool
	Sink       event.Sink
	// EffortOverride is a session-local reasoning effort override. Nil means use
	// the resolved provider config; a non-nil empty string means provider default.
	EffortOverride *string
	// Stderr is the writer for diagnostic warnings and plugin subprocess
	// stderr output. When nil, defaults to os.Stderr. Set to io.Discard
	// during model switch inside a bubbletea session to prevent any output
	// from corrupting the TUI's terminal raw mode.
	Stderr io.Writer
	// WorkspaceRoot is the project root directory for config, skills, memory,
	// commands, hooks, and tool confinement. When empty, the current working
	// directory is used (CLI default). Desktop tabs pass their project root here
	// so each tab loads its own config/skills/hooks without changing the process
	// cwd — enabling concurrent multi-project sessions.
	WorkspaceRoot string
	// ExtraPlugins are session-scoped MCP servers supplied by a host transport
	// (for example ACP session/new). They are connected eagerly for this
	// controller but are not persisted to fairpeer.toml.
	ExtraPlugins []plugin.Spec
	// SessionDir overrides where persisted chat transcripts are written. When
	// empty, the shared CLI/global session directory is used.
	SessionDir string
	// Host is an externally-owned plugin.Host the controller should adopt instead
	// of allocating its own. When set, Build does NOT create or Close the host —
	// the caller owns its lifecycle (e.g. desktop shares one host per workspace
	// root across tabs so a multi-tab project doesn't spawn N codegraph
	// processes). The host still receives this session's configured plugins via
	// Add, but Close leaves it untouched. Nil (the default) keeps the legacy
	// per-session host that Build creates and closes.
	Host *plugin.Host
	// Profile layers product-mode overrides on top of the resolved config: a
	// different model/effort, an appended/replaced system prompt, a skill
	// whitelist/blacklist, and a plugin whitelist. It is the mechanism behind
	// app.SwitchProfile("cowork") — the same rebuild flow as model switching,
	// generalized to a bundle. Nil means "dev" / unprofiled behaviour (Model,
	// prompt, skills, plugins all come from config unchanged). When both Model
	// and Profile.Model are set, Model wins (caller's explicit knob beats the
	// profile default); same for EffortOverride vs Profile.Effort.
	Profile *config.Profile
}

Options carries the per-run knobs a frontend chooses; everything else is read from configuration. Model "" falls back to the configured default_model; MaxSteps 0 uses the config/default. RequireKey forces the executor's API key to be present (run/serve pass true so a missing key fails fast; chat/desktop pass false so the UI is reachable before a key is set). Sink receives the agent's typed event stream.

Jump to

Keyboard shortcuts

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