Documentation
¶
Overview ¶
Package forge implements VORTEX Forge (build plan M13): the autonomous app builder. A user request ("build me an Android app for cricket scores") is parsed into a structured build intent, dependencies are installed, code is generated by the AI gateway, the app is built and QA-gated, and the artifact is delivered back to the requesting chat. All orchestration is stdlib-only; the AI provider is reached through the agents.AIGateway interface.
This file parses a free-form user message into a structured BuildIntent.
Index ¶
- Variables
- func CheckCompiler(language string) (found bool, binary, hint string)
- func CompilerGate(userMsg string) (msg string, ok bool)
- func RequestedLanguage(userMsg string) string
- type AIIntentParser
- type AppType
- type BuildAgent
- type BuildConfig
- type BuildIntent
- type BuildOutput
- type ClarifyingQuestion
- type CodegenAgent
- type CodegenConfig
- type CompilerSpec
- type DeliveryAgent
- type DeliveryConfig
- type DepConfig
- type DependencyAgent
- type Forge
- type ForgeConfig
- type ForgeStatus
- type GeneratedFile
- type IntentParser
- type Job
- type JobManager
- type JobState
- type NotificationSender
- type QAAgent
- type QACheck
- type QAConfig
- type QAResult
- type RuleIntentParser
- type StackChoice
- type WebDeployer
Constants ¶
This section is empty.
Variables ¶
var ErrApprovalNeeded = errors.New("forge: dependency step requires approval (interpreter/package manager)")
ErrApprovalNeeded indicates a dependency step requires an interpreter/package manager (python3/npm/pip3) that the agent cannot run unattended; the caller must obtain human approval (the coordinator's ApprovalFunc) before proceeding.
Functions ¶
func CheckCompiler ¶
CheckCompiler reports whether a usable toolchain exists for language. found is true when one candidate binary is on PATH; binary is that binary; hint is the install hint (set when not found). Unknown languages return found=true (no known toolchain requirement to enforce).
func CompilerGate ¶
CompilerGate checks whether the language explicitly requested in userMsg has an available toolchain. When a compiled language is requested but its compiler is missing, it returns a user-facing message suggesting installed alternatives and ok=false (the orchestrator should NOT start a build). When no specific language is requested, or its compiler is present, ok=true.
func RequestedLanguage ¶
RequestedLanguage returns the explicit compiled language the user asked for (c, c++, rust, java), or "" when none is detected. It only matches languages that need a toolchain check; interpreted languages are not returned. Order matters: c++ is matched before c.
Types ¶
type AIIntentParser ¶
type AIIntentParser struct {
// contains filtered or unexported fields
}
AIIntentParser parses intent using the AI gateway.
func NewAIIntentParser ¶
func NewAIIntentParser(gateway agents.AIGateway) *AIIntentParser
NewAIIntentParser builds an AI-backed parser.
func (*AIIntentParser) Parse ¶
func (p *AIIntentParser) Parse(_ context.Context, userMsg string) (BuildIntent, error)
Parse asks the AI gateway to classify the request into a BuildIntent. The caller's context is intentionally not used for the provider call (see below).
type BuildAgent ¶
type BuildAgent struct {
// contains filtered or unexported fields
}
BuildAgent runs headless builds for a generated project.
func NewBuildAgent ¶
func NewBuildAgent(cfg BuildConfig) *BuildAgent
NewBuildAgent constructs the agent.
func (*BuildAgent) ArtifactPath ¶
func (b *BuildAgent) ArtifactPath() string
ArtifactPath returns the expected path of the build output for the stack.
func (*BuildAgent) Build ¶
func (b *BuildAgent) Build(ctx context.Context) (BuildOutput, error)
Build selects and runs the build command for the configured stack, capturing output. It returns an error when the sandbox is empty or the build fails.
type BuildConfig ¶
type BuildConfig struct {
SandboxDir string
Stack StackChoice
Timeout time.Duration // default 15m
CacheDir string // reserved for build caches
}
BuildConfig configures the build agent.
type BuildIntent ¶
type BuildIntent struct {
AppType AppType `json:"app_type"`
Description string `json:"description"`
Requirements []string `json:"requirements"`
DeliveryTargets []string `json:"delivery_targets"` // "apk"|"web"|"api"|"script"
Stack StackChoice `json:"stack"`
NeedsLiveData bool `json:"needs_live_data"`
ClarifyingQs []ClarifyingQuestion `json:"clarifying_questions"`
}
BuildIntent is the structured interpretation of a user request.
func (BuildIntent) ClarifyingTexts ¶
func (b BuildIntent) ClarifyingTexts() []string
ClarifyingTexts returns the question texts (legacy string view) — used by the progress stream which carries questions as "❓ <text>" lines.
type BuildOutput ¶
type BuildOutput struct {
Success bool `json:"success"`
ArtifactPath string `json:"artifact_path"`
ArtifactType string `json:"artifact_type"` // "apk"|"web-dist"|"binary"|"script"
Stdout string `json:"stdout"`
Stderr string `json:"stderr"`
DurationMs int64 `json:"duration_ms"`
}
BuildOutput is the result of a build.
type ClarifyingQuestion ¶
type ClarifyingQuestion struct {
Question string `json:"question"`
Options []string `json:"options,omitempty"` // empty → free text
Key string `json:"key"` // what this answer maps to
}
ClarifyingQuestion is a structured question the agent asks before building. When Options is non-empty it is rendered as a numbered selection (TUI) or inline buttons (Telegram); when empty it is a free-text question.
type CodegenAgent ¶
type CodegenAgent struct {
// contains filtered or unexported fields
}
CodegenAgent generates application code via the AI gateway and writes it into the sandbox.
func NewCodegenAgent ¶
func NewCodegenAgent(cfg CodegenConfig) *CodegenAgent
NewCodegenAgent constructs the agent.
func (*CodegenAgent) Fix ¶
func (c *CodegenAgent) Fix(ctx context.Context, files []GeneratedFile, errorOutput string) ([]GeneratedFile, error)
Fix asks the AI to repair the given files to resolve a build error, then overwrites them in the sandbox.
func (*CodegenAgent) Generate ¶
func (c *CodegenAgent) Generate(ctx context.Context, intent BuildIntent, spec string) ([]GeneratedFile, error)
Generate produces application code for the given intent and writes each file into the sandbox. Malformed JSON is retried up to MaxRetries.
type CodegenConfig ¶
type CodegenConfig struct {
SandboxDir string
AIGateway agents.AIGateway
MaxRetries int // default 3
}
CodegenConfig configures the code-generation agent.
type CompilerSpec ¶
type CompilerSpec struct {
Language string
Candidates []string // first found on PATH wins
InstallHint string
}
CompilerSpec describes the toolchain needed for a language: the candidate binaries (any one suffices) and an install hint shown when none is found.
type DeliveryAgent ¶
type DeliveryAgent struct {
// contains filtered or unexported fields
}
DeliveryAgent delivers build output to the requester's channels.
func NewDeliveryAgent ¶
func NewDeliveryAgent(cfg DeliveryConfig) *DeliveryAgent
NewDeliveryAgent constructs the agent.
func (*DeliveryAgent) Deliver ¶
func (d *DeliveryAgent) Deliver(ctx context.Context, result BuildOutput, intent BuildIntent, chatID int64, cost float64) error
Deliver routes the build output to each delivery target in the intent, then sends a summary message. Cost is the AI spend for the build (USD).
func (*DeliveryAgent) DeployWebApp ¶
DeployWebApp deploys a built web dist via the configured deployer, returning the public URL.
type DeliveryConfig ¶
type DeliveryConfig struct {
Sender NotificationSender
Deployer WebDeployer
ServeBase string // base directory web apps are copied into
}
DeliveryConfig configures the delivery agent.
type DepConfig ¶
type DepConfig struct {
SandboxDir string
Timeout time.Duration // per command; default 5m
CacheDir string // for caching downloads (reserved)
}
DepConfig configures the dependency agent.
type DependencyAgent ¶
type DependencyAgent struct {
// contains filtered or unexported fields
}
DependencyAgent installs the packages a build needs.
func NewDependencyAgent ¶
func NewDependencyAgent(cfg DepConfig) *DependencyAgent
NewDependencyAgent constructs the agent.
func (*DependencyAgent) CheckInstalled ¶
func (d *DependencyAgent) CheckInstalled(name string) (bool, string, error)
CheckInstalled reports whether a tool is installed and its version. It never returns an error for a simply-missing tool (installed=false, err=nil); an error is returned only for unexpected failures.
func (*DependencyAgent) Install ¶
func (d *DependencyAgent) Install(ctx context.Context, stack StackChoice) error
Install installs the packages implied by stack. Safe toolchains (Go modules, Flutter) are set up directly; stacks that require pip/npm return ErrApprovalNeeded so the orchestrator can gate them behind human approval. An empty stack is a no-op.
type Forge ¶
type Forge struct {
// contains filtered or unexported fields
}
Forge orchestrates the full autonomous build pipeline.
func NewForge ¶
func NewForge(cfg ForgeConfig) (*Forge, error)
NewForge constructs the orchestrator.
func (*Forge) Build ¶
func (f *Forge) Build(ctx context.Context, userMsg string, chatID int64, progressFn func(string)) error
Build runs the full pipeline for a user request. progressFn (optional) receives a message at each stage. It returns nil on a delivered build, or an error (the QA gate is never skipped — a failing QA after the fix cycles blocks delivery).
func (*Forge) Status ¶
func (f *Forge) Status() ForgeStatus
Status returns a snapshot of the current build state.
type ForgeConfig ¶
type ForgeConfig struct {
AIGateway agents.AIGateway
Bus *agents.Bus
SandboxBase string
CacheDir string
Delivery DeliveryConfig
// Optional injected steps (tests provide stubs; production leaves nil).
Intent intentStep
Deps depStep
Codegen func(sandbox string) codegenStep
Builder func(sandbox string, stack StackChoice) buildStep
QA func(sandbox string) qaStep
Delivery2 deliverStep
}
ForgeConfig configures the orchestrator. The step fields are optional; when nil, Forge builds the concrete agents from the AI gateway and sandbox.
type ForgeStatus ¶
type ForgeStatus struct {
Active bool `json:"active"`
CurrentBuild string `json:"current_build"`
Progress string `json:"progress"`
ProgressHistory []string `json:"progress_history"`
Result string `json:"result"`
DurationMs int64 `json:"duration_ms"`
Questions []ClarifyingQuestion `json:"questions,omitempty"`
}
ForgeStatus is a snapshot of the orchestrator's current activity.
type GeneratedFile ¶
type GeneratedFile struct {
Path string `json:"path"`
Content string `json:"content"`
Size int `json:"size"`
}
GeneratedFile is one file produced by the codegen agent.
type IntentParser ¶
type IntentParser interface {
Parse(ctx context.Context, userMsg string) (BuildIntent, error)
}
IntentParser turns a user message into a BuildIntent.
type Job ¶
type Job struct {
ID string `json:"id"`
Message string `json:"message"`
SessionID string `json:"session_id"`
ChatID int64 `json:"chat_id"`
State JobState `json:"state"`
Progress string `json:"progress"`
ProgressHistory []string `json:"progress_history,omitempty"`
Questions []ClarifyingQuestion `json:"questions,omitempty"`
Result string `json:"result,omitempty"`
DurationMs int64 `json:"duration_ms,omitempty"`
Error string `json:"error,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Job is one asynchronous build request.
type JobManager ¶
type JobManager struct {
// contains filtered or unexported fields
}
JobManager runs forge builds asynchronously and tracks their status. Builds are serialized (the Forge runs one build at a time) via runMu, so submitted jobs queue rather than colliding.
func NewJobManager ¶
func NewJobManager(f *Forge) *JobManager
NewJobManager constructs a manager over a Forge.
func (*JobManager) Get ¶
func (m *JobManager) Get(id string) (Job, bool)
Get returns a copy of the job by ID.
func (*JobManager) SessionClarifying ¶
func (m *JobManager) SessionClarifying(sessionID string) bool
SessionClarifying reports whether the most recent job for sessionID is in the needs-clarification state (so the coordinator treats the next message as an answer, not a new build request).
func (*JobManager) SessionPending ¶
func (m *JobManager) SessionPending(sessionID string) bool
SessionPending reports whether the latest job for a session is non-terminal (queued, running, or awaiting clarification). The coordinator uses this so a follow-up message is treated as an ANSWER while a build is still in flight — the build is async, so the job may not have reached needs_clarification yet when the user replies. Without this, the reply starts a new job (the loop).
type NotificationSender ¶
type NotificationSender interface {
// SendMessage sends a text summary to the requester.
SendMessage(ctx context.Context, chatID int64, text string) error
// SendFile delivers a file (e.g. an APK) to the requester.
SendFile(ctx context.Context, chatID int64, filename string, data []byte, caption string) error
}
NotificationSender delivers messages and files to the requesting chat. It is satisfied by an adapter over messaging.Router so forge stays decoupled from the messaging package.
type QAAgent ¶
type QAAgent struct {
// contains filtered or unexported fields
}
QAAgent runs the quality-assurance gate before delivery. The gate is never skipped: a failed QAResult must block delivery.
type QACheck ¶
type QACheck struct {
Name string `json:"name"`
Passed bool `json:"passed"`
Message string `json:"message"`
}
QACheck is the outcome of one check.
type QAResult ¶
type QAResult struct {
Passed bool `json:"passed"`
Checks []QACheck `json:"checks"`
Warnings []string `json:"warnings"`
}
QAResult aggregates all checks. Passed is true only if every check passed.
type RuleIntentParser ¶
type RuleIntentParser struct{}
RuleIntentParser is a keyword-based fallback used when no AI gateway is available. It is deterministic and needs no network.
func NewRuleIntentParser ¶
func NewRuleIntentParser() *RuleIntentParser
NewRuleIntentParser builds the rule-based parser.
func (RuleIntentParser) Parse ¶
func (RuleIntentParser) Parse(_ context.Context, userMsg string) (BuildIntent, error)
Parse classifies the message by keyword heuristics.
type StackChoice ¶
type StackChoice struct {
Backend string `json:"backend"` // "fastapi"|"express"|"go"|"none"
Frontend string `json:"frontend"` // "flutter"|"react"|"none"
ML string `json:"ml"` // "sklearn"|"pytorch"|"none"
Database string `json:"database"` // "sqlite"|"postgres"|"none"
}
StackChoice records the chosen technology stack for a build.