Documentation
¶
Overview ¶
Package builder implements the agent build and upgrade pipeline.
Index ¶
- Variables
- func CommitAndPush(workDir, message string) (string, error)
- func CommitScaffold(repoPath, agentID string, data scaffold.ScaffoldData) (string, error)
- func CreateBranch(repoPath, branch string) error
- func CreateUpgradeBranch(repoPath, agentID, runID string) error
- func InitMonorepo(path string) error
- func MergeBranch(repoPath, branch string) error
- func RemoveAgentCode(repoPath, agentID string) error
- func SparseCheckout(repoPath, branch, agentID, targetDir string) error
- type BuildInput
- type BuildService
- func (b *BuildService) AcquireUpgradeLock(ctx context.Context, agentID string) error
- func (b *BuildService) Build(_ context.Context, input BuildInput) error
- func (b *BuildService) CancelBuild(agentID string) bool
- func (b *BuildService) MonorepoPath() string
- func (b *BuildService) RecoverStuckOperations(ctx context.Context) error
- func (b *BuildService) RunUpgrade(_ context.Context, input UpgradeInput)
- func (b *BuildService) SetEventPublisher(ep EventPublisher)
- func (b *BuildService) SetUpgradeNotifier(n PostUpgradeNotifier)
- func (b *BuildService) WarmBuildCache(ctx context.Context)
- func (b *BuildService) WarmRuntimeCaches(ctx context.Context)
- type BuilderPromptData
- type EventPublisher
- type LibsPaths
- type PostUpgradeNotifier
- type UpgradeInput
Constants ¶
This section is empty.
Variables ¶
var ErrUpgradeInProgress = errors.New("upgrade already in progress")
ErrUpgradeInProgress is returned when an upgrade is already running for the agent.
Functions ¶
func CommitAndPush ¶
CommitAndPush commits all changes on the current branch in workDir, pushes to origin. Returns commit hash.
func CommitScaffold ¶
func CommitScaffold(repoPath, agentID string, data scaffold.ScaffoldData) (string, error)
CommitScaffold creates branch build/{agentID}/init, materializes scaffold, commits. Returns the commit hash. Safe to call on retry — deletes a stale branch if it exists.
func CreateBranch ¶
CreateBranch creates a new branch from main/master.
func CreateUpgradeBranch ¶
CreateUpgradeBranch creates branch upgrade/{agentID}/{runID} from main.
func InitMonorepo ¶
InitMonorepo initializes a bare git repo at path if it doesn't exist.
func MergeBranch ¶
MergeBranch fast-forward merges branch into main, rebasing the branch onto current main first if a parallel build advanced main while this branch's work was running. Cross-agent rebases never conflict (each agent lives under its own agents/<id>/), and the per-agent build lock prevents same-agent races, so the rebase is safe in practice.
func RemoveAgentCode ¶
RemoveAgentCode deletes the agent directory from the monorepo and commits.
func SparseCheckout ¶
SparseCheckout clones the repo into targetDir with only agents/{agentID}/ checked out.
Types ¶
type BuildInput ¶
type BuildInput struct {
AgentID string
Name string
Slug string
UserID string
BuildModel string // stored on agent for future upgrades
Instructions string // optional: when non-empty, run Sol code generation after scaffold
}
BuildInput describes what to build.
type BuildService ¶
type BuildService struct {
// contains filtered or unexported fields
}
BuildService orchestrates the agent build and upgrade pipeline.
func New ¶
func New(cfg *config.Config, database *db.DB, containers container.ContainerManager, encryptor *crypto.Encryptor, logger *zap.Logger) *BuildService
New creates a BuildService. Panics if any dependency is nil.
func (*BuildService) AcquireUpgradeLock ¶
func (b *BuildService) AcquireUpgradeLock(ctx context.Context, agentID string) error
Upgrade runs the upgrade pipeline for an existing agent. This is synchronous — caller should run in a goroutine if needed. AcquireUpgradeLock atomically checks that no upgrade is running for the agent and sets upgrade_status to "building". Returns ErrUpgradeInProgress if an upgrade is already active. Call RunUpgrade after a successful lock.
func (*BuildService) Build ¶
func (b *BuildService) Build(_ context.Context, input BuildInput) error
Build runs the full build pipeline: scaffold → Sol code gen → compile → containerize → deploy. This is synchronous — caller should run in a goroutine if needed. If input.AgentID is set, uses the existing agent record (created by the API handler for async 202 responses). If empty, creates a new agent record.
func (*BuildService) CancelBuild ¶
func (b *BuildService) CancelBuild(agentID string) bool
CancelBuild cancels a running build/upgrade for the given agent. Returns true if a build was running and cancelled.
func (*BuildService) MonorepoPath ¶
func (b *BuildService) MonorepoPath() string
MonorepoPath returns the agent monorepo path.
func (*BuildService) RecoverStuckOperations ¶
func (b *BuildService) RecoverStuckOperations(ctx context.Context) error
RecoverStuckOperations resets any builds or upgrades left in progress after an unclean shutdown. Should be called on startup.
func (*BuildService) RunUpgrade ¶
func (b *BuildService) RunUpgrade(_ context.Context, input UpgradeInput)
RunUpgrade executes the upgrade pipeline for an agent that already has its upgrade_status set to "building" via AcquireUpgradeLock.
func (*BuildService) SetEventPublisher ¶
func (b *BuildService) SetEventPublisher(ep EventPublisher)
SetEventPublisher sets the event publisher for build/upgrade lifecycle events.
func (*BuildService) SetUpgradeNotifier ¶
func (b *BuildService) SetUpgradeNotifier(n PostUpgradeNotifier)
SetUpgradeNotifier sets the notifier called after successful upgrades to notify the originating conversation.
func (*BuildService) WarmBuildCache ¶
func (b *BuildService) WarmBuildCache(ctx context.Context)
WarmBuildCache pre-downloads Go module dependencies so that the first real agent build hits a warm cache. Materializes a real scaffold and runs a full docker build (same Dockerfile.tmpl + go.mod.tmpl as real builds), then removes the throwaway image. The cache mounts persist.
func (*BuildService) WarmRuntimeCaches ¶
func (b *BuildService) WarmRuntimeCaches(ctx context.Context)
WarmRuntimeCaches seeds the named volumes that the build-prompt loop's direct `go mod tidy` / `go build` invocations consume — distinct from the BuildKit cache mount that WarmBuildCache populates. The agent-builder container at runtime sets GOMODCACHE=/tmp/go-mod and GOCACHE=/tmp/go-cache (see container/docker.go) backed by the airlock-go-mod-cache and airlock-go-build-cache Docker named volumes. Without this seed, the first build-prompt iteration pays full download cost for ~25 modules in agentsdk+sol's transitive dep tree. The volumes persist across airlock restarts.
type BuilderPromptData ¶
type BuilderPromptData struct {
HasWebSearch bool
}
BuilderPromptData holds template data for the builder system prompt.
type EventPublisher ¶
type EventPublisher interface {
PublishBuildEvent(ctx context.Context, agentID, buildID uuid.UUID, status, errMsg string)
PublishBuildLogLine(ctx context.Context, agentID, buildID uuid.UUID, seq int64, stream, line string)
}
EventPublisher publishes build/upgrade lifecycle events. Implemented by realtime.PubSub via an adapter.
type LibsPaths ¶
type LibsPaths struct {
// Owned is the directory containing agentsdk/goai/sol. Either the
// operator's AGENT_LIBS_PATH (live dev source) or the extracted cache.
Owned string
// Ext is the directory containing goose/templ. Always the extracted
// cache (devs don't edit these).
Ext string
}
LibsPaths is what callers need to wire up the per-agent docker build's two BuildKit contexts (libs-owned + libs-ext) and the toolserver's bind-mount overlay (Owned).
func EnsureLibs ¶
func EnsureLibs(ctx context.Context, image, explicitPath, cacheDir string, logger *zap.Logger) (LibsPaths, error)
EnsureLibs guarantees that:
- The agent-builder image's full /libs/* set is materialized on the host under <cacheDir>/<image-id>/, cached by image ID so a tag bump triggers re-extraction.
- If explicitPath (AGENT_LIBS_PATH) is set, the owned subdirs all exist there. Owned then points at explicitPath; Ext at the cache.
- If explicitPath is empty (prod), both Owned and Ext point at the cache.
type PostUpgradeNotifier ¶
type PostUpgradeNotifier interface {
NotifyUpgradeComplete(ctx context.Context, agentID uuid.UUID, conversationID, status, message string) error
}
PostUpgradeNotifier is called after an upgrade finishes (success or failure) to post a single message into the originating conversation.
status is "success" or "error". message is the human-readable text to surface — typically sourced from the agent-builder's exit tool on success, or the underlying failure reason on error. The notifier posts exactly ONE message and does not trigger a follow-up LLM turn — the agent's own exit-tool summary already describes the outcome, so re-prompting just produces redundant text.
type UpgradeInput ¶
type UpgradeInput struct {
AgentID string
RunID string // the run that triggered the upgrade
Reason string // "llm_request", "auto_fix", "manual"
Description string // what to change
ConversationID string // conversation that triggered the upgrade (for post-upgrade reply)
ErrorMessage string // from failed run (auto_fix)
PanicTrace string // from failed run (auto_fix)
InputPayload string // JSON of failed run input (auto_fix)
Actions string // JSON of recorded actions before failure (auto_fix)
Messages string // conversation messages from the failed run
}
UpgradeInput describes an upgrade request.