bootstrap

package
v0.28.0 Latest Latest
Warning

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

Go to latest
Published: Aug 11, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

Package bootstrap wires up a complete agent session: tool registry, MCP, permissions, subagents, plan mode, skills, verify, and system prompt.

Both the CLI (cmd/moa) and the HTTP server (pkg/serve) call BuildSession to avoid duplicating the 14-step setup sequence.

runtime_config.go bridges bootstrap sessions with the bus/runtime layer.

This is the only file in package bootstrap that imports pkg/bus. The dependency direction is intentional: bootstrap already knows all the domain types (agent, permission, tasks, planmode, etc.) that constitute a RuntimeConfig. This file simply groups them into the struct that NewSessionRuntime expects, eliminating manual field mapping in every caller.

Index

Constants

View Source
const DefaultReviewThinking = "medium"

Default review thinking level for plan mode (shared between CLI and serve).

Variables

This section is empty.

Functions

func FormatBashNotification

func FormatBashNotification(jobID, command, status, output string) string

FormatBashNotification produces the text injected into the agent's conversation when an async background bash job completes. Mirrors FormatSubagentNotification so the CLI and serve reinjection paths stay symmetric. output is the job's full captured output (already capped at 50KB by BashJobs); it is truncated here to the trailing lines with a pointer to bash_status for the rest.

func FormatSubagentNotification

func FormatSubagentNotification(jobID, task, status, resultTail string, truncated bool) string

FormatSubagentNotification produces the text injected into the agent's conversation when an async subagent completes. Shared between CLI and serve. The truncated flag indicates that resultTail is only a portion of the full output.

func FullModelSpec

func FullModelSpec(model core.Model) string

FullModelSpec returns "provider/id" for the given model, or just "id".

Types

type Session

type Session struct {
	Agent         *agent.Agent
	ToolReg       *core.Registry
	TaskStore     *tasks.Store
	PlanMode      *planmode.PlanMode
	Goal          *goal.Goal
	AskBridge     *askuser.Bridge
	Gate          *permission.Gate
	MCPManager    *mcp.Manager
	MCPController *mcp.Controller
	MCPPolicy     core.MCPDisablePolicy
	PathPolicy    *tool.PathPolicy
	AgentsMD      string
	Skills        []skill.Skill
	SkillsIndex   string
	SystemPrompt  string
	// BuildBasePrompt regenerates the base system prompt from a tool-spec set,
	// capturing the same inputs (AgentsMD, CWD, verify, indexes) used at
	// construction. The MCP controller uses it to rebuild the prompt after a
	// server is enabled/disabled, so the model is never told about a tool that
	// is no longer registered.
	BuildBasePrompt   func([]core.ToolSpec) string
	MemoryStore       *memory.Store
	SessionCheckpoint *sessioncheckpoint.Slot
	HasVerify         bool
	Model             core.Model
	MoaCfg            core.MoaConfig
	CWD               string // workspace directory

	// UntrustedMCP is true when .mcp.json exists but CWD is not in TrustedMCPPaths.
	UntrustedMCP bool

	// Headless is true when the session was created in headless mode (no user
	// to approve permissions). Preserved so RuntimeConfig() can set GateConfig
	// correctly even when Gate is nil (yolo mode).
	Headless bool

	// Subagents is the handle onto the subagent job store, returned by
	// subagent.RegisterAll. Used for the init snapshot (reconnect), the agent
	// tray, and cancellation.
	Subagents *subagent.Jobs
	BashJobs  *tool.BashJobs
	// contains filtered or unexported fields
}

Session is a fully wired session ready for agent.Run/Send.

func BuildSession

func BuildSession(cfg SessionConfig) (*Session, error)

BuildSession wires up a complete agent session. The returned Session contains everything needed to run the agent. Caller owns cleanup: - MCPManager.Close() if non-nil - Context cancellation for subagent jobs

BuildSession does NOT create the agent — it returns all the pieces needed to create one. This allows callers to customize the AgentConfig (e.g., compose permission checks with plan mode filtering) before calling agent.New.

func (*Session) CurrentPermissionMode

func (s *Session) CurrentPermissionMode() string

CurrentPermissionMode returns the string representation of the current mode.

func (*Session) RuntimeConfig

func (s *Session) RuntimeConfig() bus.RuntimeConfig

RuntimeConfig returns a bus.RuntimeConfig pre-populated with all session dependencies that are common across frontends (CLI, TUI, serve).

Callers must set at minimum: SessionID, Ctx. They typically also set Bus, Checkpoints, ProviderFactory, and frontend-specific fields like Persister, SteerFilter, or InitialMessages.

type SessionConfig

type SessionConfig struct {
	// Required.
	CWD             string                                  // Working directory. Must exist and be a directory.
	Model           core.Model                              // Resolved LLM model.
	Provider        core.Provider                           // LLM provider for the primary model.
	ProviderFactory func(core.Model) (core.Provider, error) // Creates providers for subagents, plan review, etc.

	// Config overrides. When nil, loaded from disk via core.LoadMoaConfig(CWD).
	MoaCfg *core.MoaConfig

	// MCPDisableSources gives the provenance (global/project) of MCP disable
	// vetoes when MoaCfg is injected. The merged MoaCfg.DisabledMCPServers loses
	// which scope each name came from, so callers that inject MoaCfg should also
	// pass the resolved sources; otherwise a project-only veto would be
	// misattributed to global and could never be cleared by editing Project.
	// Ignored when MoaCfg is nil (bootstrap resolves provenance from disk).
	MCPDisableSources *core.MCPDisableSources

	// ExtraMCPServers are session-scoped MCP servers merged on top of the
	// configured ones. They come from the caller (the Automation API attaches
	// per-run servers this way), live and die with the session, and are never
	// written to any config file. A name already taken by a configured server is
	// the caller's responsibility to reject: the merge would silently override
	// operator config.
	ExtraMCPServers map[string]core.MCPServer

	// Context for MCP servers and subagent async jobs. Required.
	Ctx context.Context

	// Agent tuning. Zero values use package defaults.
	ThinkingLevel       string        // Default: "medium"
	MaxTurns            int           // 0 = unlimited (default). Overrides config.json.
	MaxToolCallsPerTurn int           // 0 = unlimited (default). Overrides config.json.
	MaxRunDuration      time.Duration // 0 = unlimited (default). Overrides config.json.
	MaxBudget           float64       // Default: from config. 0 = unlimited.
	DisableSandbox      bool          // Overrides config (OR'd). Deprecated: use PathScope.

	// PathScope override. Empty = derive from config/permissions.
	// Valid values: "workspace", "unrestricted".
	PathScope string
	// ExtraAllowedPaths are merged with config allowed_paths (from --allow-path flags).
	ExtraAllowedPaths []string

	// Permission mode override. Empty = from config or "yolo".
	PermissionMode string
	// Model spec for auto-mode AI evaluator. Empty = "haiku".
	PermissionEvalModel string
	// Headless denies unresolved permissions instead of blocking (no user to approve).
	Headless bool
	// ExtraAllowPatterns are merged with config allow patterns (from --allow flags).
	ExtraAllowPatterns []string

	// PlanMode session dir. If empty, uses CWD.
	PlanSessionDir string

	// Feature toggles. All default to true.
	EnableAskUser bool // Register ask_user tool. Default: true.

	// BeforeWrite is called before write/edit tools modify a file.
	// Used by the checkpoint system to capture pre-edit state.
	BeforeWrite func(path string) error

	// MaterializeContent rehydrates byte-free attachment references before a
	// provider request. Nil preserves legacy inline content unchanged.
	MaterializeContent func(context.Context, []core.Message) ([]core.Message, error)

	// Subagent callbacks. All optional (nil = no-op).
	OnAsyncJobChange func(count int)
	OnAsyncComplete  func(jobID, task, status, resultTail string, truncated bool)

	// OnSubagentStart/OnSubagentEvent/OnSubagentUsage/OnSubagentEnd are the
	// rich, per-child streaming sinks (subagent.Config.OnChildStart/
	// OnChildEvent/OnChildUsage/OnChildEnd). The caller wires these into its
	// own bus (see cmd/moa's preBus, pkg/serve's session_lifecycle closure)
	// since bootstrap has no bus reference of its own. All optional (nil =
	// no-op).
	OnSubagentStart func(jobID, task, model, thinking, originToolCallID string, async bool, startedAt time.Time, accentIndex int)
	OnSubagentEvent func(jobID string, inner any)
	OnSubagentUsage func(jobID string, usage *core.Usage, costUSD float64, contextPct int)
	OnSubagentEnd   func(jobID, task string, async bool, status, result, resultErr string, finishedAt time.Time, usage *core.Usage, costUSD float64)

	// Background bash callbacks feed the shared session bus/UI. Output is a
	// lossy live delta; end carries the authoritative bounded log.
	OnBashJobStart  func(job tool.BashJobInfo)
	OnBashJobOutput func(job tool.BashJobInfo, delta string)
	OnBashJobEnd    func(job tool.BashJobInfo)

	// SubagentTranscriptLoader loads a finished subagent's persisted transcript
	// (messages plus the model/thinking it ran under) by job ID, enabling the
	// subagent tool's "resume" parameter. Optional (nil = resume unsupported).
	// The caller wires this to its transcript store (see pkg/serve's
	// SubagentStore).
	SubagentTranscriptLoader func(jobID string) (subagent.ResumedTranscript, error)
}

SessionConfig configures a session build. Most fields have sensible defaults.

Jump to

Keyboard shortcuts

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