Documentation
¶
Overview ¶
Package generate is the pipeline behind "baum internal generate": it assembles the generation bundle for a pull request, unpacks the checkout into a private run directory, runs the shared generate-and-repair loop (agent.Generator) with a model backend, and finishes the document the way the hosted worker does: output redaction, secret rejection, derived fields, the generator block and a strict check of the stored form.
Its sources and the backend are interfaces, so a test runs the whole pipeline against a fake clone, a fake GitHub and a stub backend. Run never writes the document anywhere: it returns it, and nothing is returned for a run that was rejected, so a caller cannot publish a partial result.
Every failure is an *Error naming a Category, which the command line maps to an exit code.
Index ¶
- Constants
- Variables
- func BoundPasses(backend agent.Backend, timeout time.Duration) agent.Backend
- func CheckExplicitPath(name config.Backend, path string) error
- func ConcurrentCalls(backend agent.Backend) bool
- func DesktopBackend(b config.Backend) bool
- func Gaps(document []byte) ([]string, bool)
- func NotOfferedError(b config.Backend) error
- func RemoveTree(dir string)
- func RunTask(ctx context.Context, o TaskOptions) (agent.Outcome, []byte, error)
- func WriteDiagnostics(path string, runErr error, outcome agent.Outcome) error
- func WriteFileAtomic(path string, data []byte) (err error)
- type Assembler
- type Backends
- type Category
- type CheckedBackend
- type Error
- type ExplicitPathError
- type Group
- type GroupMember
- type Options
- type Result
- type Selected
- type TaskOptions
- type Versions
Constants ¶
const MaxGroupMembers = 8
MaxGroupMembers bounds a group; internal/reviewgroups enforces it on definitions.
Variables ¶
var AutoOrder = []config.Backend{config.BackendClaude, config.BackendCodex, config.BackendAnthropic}
AutoOrder is the order in which auto tries the backends. The model a run names applies to the first only. cursor-agent is left out on purpose: it must be chosen explicitly (see SECURITY.md, "The cursor-agent backend").
var DesktopAutoOrder = []config.Backend{config.BackendClaude, config.BackendCodex}
DesktopAutoOrder is the order in which auto tries the backends in the desktop app and its daemon: Claude Code, then Codex. auto never spends money through the Anthropic API there.
var ErrBackendNotOffered = errors.New("the baum desktop app does not run jobs with this backend")
ErrBackendNotOffered is a backend the desktop app does not run jobs with.
var ErrCannotComplete = errors.New("the backend cannot make a single structured call")
ErrCannotComplete is a backend without single-call completions (agent.Completer): cursor-agent.
var ErrHeadChanged = errors.New("pull request head changed")
ErrHeadChanged: a pull request's head moved after the run was prepared, so its evidence would not be what was confirmed.
Functions ¶
func BoundPasses ¶
passBounded applies the per-call timeout to a backend. BoundPasses bounds each call of backend by timeout as a review's pass_timeout does: a call that runs out fails with the budget "pass_timeout", which the loop does not retry. Zero leaves it unbounded.
func CheckExplicitPath ¶
CheckExplicitPath returns an ExplicitPathError when path is not an executable file, and nil for an empty path.
func ConcurrentCalls ¶
ConcurrentCalls reports whether backend may run several calls over one run directory at once (agent.ConcurrentCaller). A host's wrapper of a backend forwards it, or a staged review runs its stages in turn.
func DesktopBackend ¶
DesktopBackend reports whether the desktop app and its daemon run jobs with b: auto, claude and codex. The cursor-agent and anthropic backends stay available to the baum command line only.
func Gaps ¶
Gaps names the sections of a completed staged document published without their details, and reports whether it has no context. A stale section, carried from an earlier version, is not one: nothing writes its details again.
func NotOfferedError ¶
NotOfferedError reports a job whose backend, such as one set in config.toml, the desktop app does not run. It never switches to another backend.
func RemoveTree ¶
func RemoveTree(dir string)
RemoveTree removes a directory whose subdirectories may be read-only, as an unpacked checkout's are.
func RunTask ¶
RunTask runs a task through the review harness's loop, as Run runs a review: the wall clock and pass bounds apply, what the loop returned is masked (agent.RedactTaskOutput) on every path before it is returned, and a failure is an *Error of its category. A reply the schema or the task's check still rejected after the repairs is a CategoryValidation error, and no document is returned with an error. The Outcome is returned on every path, for the ledger.
func WriteDiagnostics ¶
WriteDiagnostics writes the run's end state to path: ok or failed, the category and the (already redacted) error text of a failure, and the outcome, whose size the loop bounds (at most agent.MaxDiagnostics events and a retained document of at most agent.MaxRetainedDocumentBytes).
func WriteFileAtomic ¶
WriteFileAtomic writes data to path through a temporary file beside it, so a failed run leaves no partial file. The file is readable by its owner only: it can hold session text.
Types ¶
type Assembler ¶
type Assembler interface {
Assemble(ctx context.Context, req assemble.Request) (assemble.Result, error)
}
Assembler builds the bundle and the archives of one pull request; *assemble.Assembler implements it.
type Backends ¶
type Backends struct {
Claude func(model string) CheckedBackend
Codex func(model string) CheckedBackend
CursorAgent func(model string) CheckedBackend
Anthropic func(model string) CheckedBackend
}
Backends builds the local backends. DefaultBackends and DefaultBackendsFor are the only production implementations: the user's installed CLIs under their own login, in the profiles meant for a person's machine, and the Anthropic API under their own key. Tests substitute fakes.
func DefaultBackends ¶
func DefaultBackends() Backends
DefaultBackends builds Claude Code with the User profile, Codex with the Local profile and the Cursor Agent CLI, which run in the user's environment, finding each on PATH, and the Anthropic API with the key from ANTHROPIC_API_KEY. The Isolated and Container profiles belong to hosted runs and are never built here.
func DefaultBackendsFor ¶
DefaultBackendsFor is DefaultBackends with the executables cfg names in BackendPaths and the variables of its AgentEnv. A named path replaces the PATH lookup: when it cannot be run, the backend fails naming backend_paths.<name> and PATH is not searched.
type Category ¶
type Category string
Category classifies why a run failed.
const ( // CategoryInput is a failure of what the run needs: the pull request, its // commits in the clone, GitHub, or a bundle or checkout over its caps. CategoryInput Category = "input" // CategoryBackend is a backend that is missing, too old, cannot sandbox, // failed or whose provider was unavailable. CategoryBackend Category = "backend" // CategoryBudget is a spent call, token or wall-clock budget. CategoryBudget Category = "budget" // CategoryValidation is a document the validator rejected after the // repairs, or one that held a secret. Nothing is written for it. CategoryValidation Category = "validation" // CategoryInterrupted is a run stopped by SIGINT or SIGTERM. CategoryInterrupted Category = "interrupted" // CategoryInternal is a failure of baum's own steps, such as masking the // output. The hosted worker treats it as a plain failure, not a rejected // document, so it exits with the generic code. CategoryInternal Category = "internal" )
func CategoryOf ¶
CategoryOf returns the category of err, or "" when it is not an *Error.
type CheckedBackend ¶
type CheckedBackend interface {
agent.Backend
// Check returns the installed version.
Check(ctx context.Context) (version string, err error)
}
CheckedBackend is a backend that can verify, before any work is done, that it is installed, recent enough and able to run.
type Error ¶
Error is a failure of one category. Its text never holds a secret the model or the backend wrote: it is redacted before it is built.
type ExplicitPathError ¶
ExplicitPathError reports a backend_paths entry that names a file which cannot be run. Err is why.
func (*ExplicitPathError) Error ¶
func (e *ExplicitPathError) Error() string
func (*ExplicitPathError) Unwrap ¶
func (e *ExplicitPathError) Unwrap() error
type Group ¶
type Group struct {
// Name is the group's name, the document's stack title unless
// GeneratedName.
Name string
// GeneratedName gives the document's stack title the name the model
// writes for the group, when it wrote a usable one: a stack group's,
// whose name is baum's. A group the person named keeps Name.
GeneratedName bool
// Members are the group's pull requests in group order.
Members []GroupMember
// MemberReviews is written to the run directory as members.json, the
// members' own reviews in brief for the model to read.
MemberReviews []byte
}
Group asks Run for a review group's combined review instead of one pull request's: Request names the repository and the limits, and its Number is ignored. See internal/reviewgroups.
type GroupMember ¶
type GroupMember struct {
Number int
// Head, when not empty, is the head the run was confirmed for: a member
// whose head moved fails the run before any model call.
Head string
// ReviewVersion is the member's saved review version the run reads,
// recorded in the document's stack; at least 1.
ReviewVersion int
}
GroupMember is one pull request of a group.
type Options ¶
type Options struct {
PriceList *pricing.List
Assembler Assembler
// Request names the pull request and the limits. Run sets its Checkout and
// Attachments writers.
Request assemble.Request
Backend agent.Backend
// BackendVersion is the installed backend's version, for the progress line.
BackendVersion string
Model string
Budgets agent.Budgets
// PassTimeout bounds each backend call; zero leaves it to the wall clock.
PassTimeout time.Duration
// TileKinds is the tile allow-list; empty offers no tiles.
TileKinds []string
// Prompts defaults to this module's public prompt.
Prompts agent.Prompts
// Staged writes a single pull request's review in stages
// (agent.Generator.StagedReview) instead of in one pass: the outline,
// then the sections' details and the context. A section whose details
// fail is published without them and a context that fails is left out;
// only a failed outline (or no section with details) fails the run. A
// review group is always written in one pass.
Staged bool
// StagedPrompts defaults to this module's public staged prompt.
StagedPrompts agent.StagedPrompts
// OnDraft, for a staged run, receives the review so far each time a
// stage result lands, masked and completed as the published document is
// (CompleteStaged) but with the sections still being written pending.
// It is never a version. Calls come one at a time, from a goroutine of
// the run, and the last one returns before Run does.
OnDraft func(document []byte)
// Continue, for a staged run, is the saved version to complete instead
// of writing a new one: the latest version, some of whose sections
// failed. Only the details of those sections are written again
// (agent.StagedRun.Outline), against the version's head, base and merge
// base, and the result is the same version with its metadata, model,
// prompt version and generation time. Request.Previous must be the
// version before it, which it was reconciled with. Nothing is kept for
// a chat.
Continue *store.Version
Validator *review.DocumentValidator
Redactor *bundle.Redactor
// Progress receives one line per step; nil discards them. The document is
// never written to it.
Progress io.Writer
// OnRepairs receives the validation repairs made so far after each
// validation, over every stage of a staged run, without model text.
OnRepairs func(repairs int)
// KeepRunDir keeps the run directory and reports its path on Progress.
KeepRunDir bool
// KeepSession persists the backend's session and keeps the run directory,
// under SessionRoot, when the run succeeds with a session id, and records
// both in the version's Metadata.Session so a later chat can continue the
// session in the same directory. A failed run, a missing session id and a
// group review remove the directory as usual. Only a local Claude Code or
// Codex backend supports it.
KeepSession bool
// SessionRoot is the directory kept runs are made in; empty is
// reviewruns.DefaultRoot.
SessionRoot string
// Stored, for Publish, runs once the version is stored, with its metadata.
// The version is already published: an error is a warning on Progress.
Stored func(ctx context.Context, key store.Key, m store.Metadata) error
// BundleOut, when not empty, receives the exact bundle the model was given.
BundleOut string
// DiagnosticsOut, when not empty, receives the run's redacted outcome as
// JSON: usage, repairs, findings and at most agent.MaxDiagnostics events.
// It is written for failed runs too.
DiagnosticsOut string
// Now defaults to time.Now.
Now func() time.Time
// Group, when set, generates a review group's combined review of the
// pull requests it names instead of the one Request names; Prompts then
// defaults to the public group prompt.
Group *Group
}
Options are the inputs of one run.
type Result ¶
type Result struct {
Attachments []store.Attachment
// Document is the finished, strictly valid document. Nil on any failure.
Document []byte
Metadata store.Metadata
Outcome agent.Outcome
// RunDir is the run directory when KeepRunDir or KeepSession kept it.
RunDir string
// Elapsed is the wall time of the run.
Elapsed time.Duration
// FailedSections, for a staged run, are the sections the document holds
// without their details, and ContextFailed says it has no context.
FailedSections []string
ContextFailed bool
}
Result is a finished run.
func Publish ¶
func Publish(ctx context.Context, versions Versions, key store.Key, o Options, cost func(Result) *float64) (result Result, err error)
Publish runs the same validation/repair pipeline for CLI and queued jobs and atomically appends only a completed document to the version store. Once the version is stored the call succeeds: the version is already visible, so a failure to record the run's outcome, or of o.Stored, afterwards is a warning on o.Progress.
type Selected ¶
type Selected struct {
Backend CheckedBackend
Version string
// Model is the model the backend was built with; empty is its default.
Model string
}
Selected is the backend a run uses.
func Select ¶
func Select(ctx context.Context, requested config.Backend, model string, backends Backends, skipped io.Writer) (Selected, error)
Select resolves the requested backend, checking that it can run.
auto tries, in order, claude, codex and anthropic, each when it passes its checks (anthropic's is that ANTHROPIC_API_KEY is set), and fails naming every reason when none does. It never picks cursor-agent, which cannot be held to read-only as reliably as the others: that backend runs only when named. A backend named explicitly fails with its own check's reason.
A model names a model of one backend, so with auto it applies to the first choice, claude, only: a backend auto falls back to runs with its own default model, and skipped says so. skipped also receives why each earlier choice was skipped; nil discards both. anthropic's default model is resolved here (anthropic.DefaultModel), so Selected.Model names it and the run's cost at API prices can be worked out from it.
func SelectDesktop ¶
func SelectDesktop(ctx context.Context, requested config.Backend, model string, backends Backends, skipped io.Writer) (Selected, error)
SelectDesktop is Select for the desktop app and its daemon. It refuses a known backend other than auto, claude and codex (ErrBackendNotOffered), and auto tries DesktopAutoOrder only, so no job reaches cursor-agent or the Anthropic API.
type TaskOptions ¶
type TaskOptions struct {
Backend agent.Backend
// Task is the task; its Budgets' WallClock bounds the whole run.
Task agent.Task
// PassTimeout bounds each backend call; zero leaves it to the wall clock.
PassTimeout time.Duration
Redactor *bundle.Redactor
Logger *slog.Logger
}
TaskOptions are the inputs of one agent task (agent.Task) besides a review, such as feature discovery.
type Versions ¶
type Versions interface {
Latest(context.Context, store.Key) (store.Version, error)
BeginRun(context.Context, store.Key, time.Time) (int64, error)
HeartbeatRun(context.Context, int64, time.Time) error
FinishRun(context.Context, int64, string) error
Put(context.Context, store.Key, store.Version, store.Version) error
}
Versions is the part of *store.Store that Publish uses.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package generatetest is a stub model backend for tests of "baum internal generate": it returns canned documents without calling a model, and records the run directories it was given.
|
Package generatetest is a stub model backend for tests of "baum internal generate": it returns canned documents without calling a model, and records the run directories it was given. |