Documentation
¶
Overview ¶
Package cx is a second, independent agent engine for tomo, shaped after the way a strong coding agent works a bug: ground the whole problem with one wide search, read the real source, converge on a single root-cause fix, then run the project's own tests to verify before finishing. It reuses tomo's standard tools and provider, and the default engine's Sink and Gate types, so a caller can select it in place of the default engine without any other change. It carries its own system prompt (prompts/system.md), its own tool descriptions (tools.go), and its own convergence governor (governor.go), so the two engines stay fully independent and either can change without touching the other.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CompactFromEnv ¶
func CompactFromEnv() (tail, minBytes, budgetTokens int)
CompactFromEnv reads the compaction knobs an operator can set to match the gate to the model in play. All default to zero, which leaves compaction off and the loop re-sending the full transcript exactly as before, so a plain build is unchanged. TOMO_COMPACT_TAIL sets the recent window kept verbatim, TOMO_COMPACT_BUDGET_TOKENS keys shedding to the model's context length (elide only past this estimate), and TOMO_COMPACT_MIN_BYTES sets the size a result must exceed to be elided. The env is the seam an A/B arm selects without a rebuild; a construction site copies the three into the Engine fields.
func Retune ¶
Retune returns a copy of the given tools with cx-specific descriptions applied to the ones cx rewords, leaving every other field (Name, Class, Schema, Run) and every other tool untouched. The input slice is not modified, so the caller (and the default engine) keep the original builtin descriptions.
func SystemPrompt ¶
func SystemPrompt(now time.Time, workspace, persona, memoryIndex, skillsIndex string, offline bool) string
SystemPrompt renders the cx engine's system prompt for a run. It mirrors the signature of the default engine's builder so the two are drop-in swappable at the call site. When offline is set it renders the checked-out-tree-only variant, which forbids reaching the answer from outside the source.
Types ¶
type Engine ¶
type Engine struct {
Provider provider.Provider
Model string
System string
Tools *tool.Registry
Gate agent.Gate
// Workspace is the working directory of the file and shell tools. When it is
// a git repo, the loop uses it to catch a turn that rewrote a test instead of
// fixing the code under test and nudge it back. Empty disables that check.
Workspace string
// MaxRounds caps the model calls in one turn. Zero means unbounded, the normal
// mode: the convergence governor, not a fixed length, decides when a productive
// run ends. A positive value is a hard budget, used to bound a probe or A/B run
// so the loop stops after a set number of rounds instead of playing out in full.
MaxRounds int
// Compaction shapes the transcript put on the wire so an older tool result is
// not re-sent whole on every later round (see compact.go). All three default to
// zero, which leaves compaction off and the full transcript sent as before, so
// a plain build is unchanged. CompactTail is the recent-window floor kept
// verbatim; CompactMinBytes is the size a result must exceed to be eligible;
// CompactBudgetTokens, when positive, only sheds while the transcript estimate
// exceeds that budget (context-length-aware), else shedding is unconditional.
CompactTail int
CompactMinBytes int
CompactBudgetTokens int
}
Engine binds a provider, a toolset, and the policy gate for the cx turn loop. Its fields mirror the default engine so wiring is a straight swap. It reuses agent.Sink and agent.Gate rather than redeclaring them, so a single call site can drive either engine through one interface.
func (*Engine) Turn ¶
func (e *Engine) Turn(ctx context.Context, history []provider.Message, user provider.Message, sink agent.Sink) ([]provider.Message, error)
Turn runs one user turn to completion and returns every message it generated, the user message first, so the caller can persist them. On error the messages so far come back too, so a partial turn is not lost. The loop is the codex rhythm made mechanical: it never bounds a productive run by length, only steps in when the run stops converging (see governor.go).