bootstrap

package
v0.37.1 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package bootstrap wires up a complete agent session: tool registry, MCP, permissions, subagents, 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, 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

This section is empty.

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".

func NewSkillFork added in v0.35.0

func NewSkillFork(sub core.Tool) skill.ForkFunc

NewSkillFork returns the callback load_skill uses to spawn an isolated child through the existing subagent tool. A forked skill is an ordinary subagent: it reports its result back the same way. Nested forks are refused in LaunchFork because every child already carries an AgentID.

Types

type Session

type Session struct {
	Agent         *agent.Agent
	ToolReg       *core.Registry
	TaskStore     *tasks.Store
	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,
	// reading the on-disk inputs (AGENTS.md, skill and memory indexes) through
	// Sources so a rebuild reflects a reload rather than the values the session
	// started with. The MCP controller uses it 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
	// Sources holds those on-disk inputs, so /reload can re-read them without
	// restarting the session.
	Sources           *agentcontext.Sources
	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) 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 (headless CLI, 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.

	// CompactSummarizer optionally routes compaction summaries to a different
	// model (the global `compact_model`). nil = summarize with the session's
	// own model, which is how compaction behaved before this existed.
	// Subagents inherit it: their compactions are summaries too.
	CompactSummarizer func(sessionModel core.Model) (core.Provider, core.Model, string)

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

	// SessionID identifies this conversation for prompt-cache routing on the
	// Responses providers. Empty (the default) sends no key, which is the
	// right behavior for one-off agents that have no conversation to pin.
	SessionID string

	// 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"
	Fast                bool          // Premium speed for this session when the model supports it.
	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

	// 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)

	// AttachmentScope is the session's attachment capability (store + owning
	// session ID) as ONE value. It is handed whole to the main agent and to the
	// subagent tool, so producing references and resolving them always travel
	// together and no constructor can wire one half only. Nil = inline.
	AttachmentScope *attachment.Scope

	// 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)
	SubagentTitleModel   core.Model
	SubagentTitleEnabled bool
	OnSubagentTitle      func(jobID, title string)

	// 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)

	// SnapshotTranscript freezes the parent's active conversation branch and
	// returns an absolute path the child can read. Nil in the CLI: a forked
	// skill that asks for parent-transcript: snapshot then errors instead of
	// inventing a complete history.
	SnapshotTranscript func() (path string, err 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