deploy

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Mar 2, 2026 License: MIT Imports: 17 Imported by: 0

README

Deploy Intelligence Pipeline

This package powers the clanker deploy intelligence flow from user query to plan/apply.

Query → Deploy (Current Flow)

  1. Input + context setup

    • cmd/deploy.go parses flags, provider/profile, and AI settings.
    • Repo is cloned and profiled (CloneAndAnalyze) for language, framework, ports, Docker/Compose, env hints.
  2. Intelligence pipeline (RunIntelligence)

    • Phase 0: Explore repo (explorer.go) — agentic file reads to gather missing context.
    • Phase 1: Deep analysis (intelligence.go) — app behavior, services, startup/build commands, env requirements.
    • Phase 1.25: Docker analysis (docker_agent.go) — Docker/Compose topology, primary port, container runtime hints.
    • Phase 1.5: Infra scan (infra_scan.go, cf_infra_scan.go) — existing cloud resources to reuse.
    • Phase 2: Architecture decision (intelligence.go) — method/provider recommendation (e.g. EC2 for OpenClaw).
    • Produces EnrichedPrompt for planning.
  3. Skeleton + hydrate plan generation (skeleton_plan.go) — primary path

    • Phase 3a: Skeleton — single LLM call produces a lightweight PlanSkeleton (service, operation, reason, produces, dependsOn per step). No real CLI args yet.
    • Skeleton is validated (validateSkeleton): checks required launch ops are present, flags duplicates using a composite key of (service, operation, produces, dependsOn).
    • Phase 3b: Hydrate — skeleton steps are batched (max 5 consecutive independent steps per batch) and each batch is hydrated into real maker.Command structs via separate LLM calls.
    • Hydrate prompts enforce resource name consistency across steps (e.g. ECR repo names in user-data must match earlier ecr create-repository commands).
    • If skeleton or hydration fails, falls back to the paged plan generation path.

    3b. Paged plan generation (paged_plan.go) — fallback path

    • Plan is generated in small command pages instead of one large response.
    • Each page is parsed (ParsePlanPage), normalized via maker.ParsePlan, and appended with dedupe (AppendPlanPage).
    • Parser tolerates either a page object or a plain command array ([]commands) from the LLM.
    • Page prompts include current command tail + produced bindings + required launch operations + unresolved hard issues.
    • When both skeleton and paged plans exist, the one with fewer deterministic issues wins.
  4. Generic plan autofix (plan_autofix.go)

    • Runs after plan generation (both skeleton and paged paths).
    • SSM semantic dedup — deduplicates SSM send-command / put-parameter steps that do the same thing.
    • Launch cycle dedup — removes redundant run-instances cycles within the same project.
    • Read-only dedup — collapses repeated read-only commands (describe/get/list).
    • Orphan placeholder pruning — removes commands that reference <PLACEHOLDER> values never produced by any earlier command. Accepts externalBindings (user-provided env var names) so user env vars are treated as "produced" and not orphan-pruned.
    • User-data placeholder normalization — rewrites <USER_DATA_*> variants to canonical <USER_DATA>.
    • Critical command protectionrun-instances, create-load-balancer, create-distribution are never removed by autofix.
  5. Deterministic guardrails (plan_preflight_validate.go)

    • Deterministic checks run for hard failures:
      • launch step missing,
      • OpenClaw onboarding/compose requirements,
      • missing compose-required env vars,
      • secret inlining,
      • AWS wiring sanity checks.
    • Waiter/order sanity for AWS runtime wiring (ec2 wait instance-running before target registration, elbv2 wait load-balancer-available before listener creation).
    • CloudFront command-shape sanity (create-distribution must not carry --tags) and OpenClaw output contract (CLOUDFRONT_DOMAIN + full HTTPS_URL with https://).
    • User-data vs plan cross-check (crossCheckUserDataVsPlan) — decodes base64 user-data from run-instances commands, extracts ECR image references, and verifies they match ECR repositories created in the plan. Catches hallucinated repo name mismatches.
    • Bulk invariant checks:
      • non-empty command list, no unresolved placeholders,
      • IAM instance-profile readiness before EC2 launch,
      • user-data quote sanity (detects unterminated quote breakages).
    • Project overlay invariants:
      • OpenClaw: HTTPS pairing URL via CloudFront, onboarding before gateway start.
    • Stuck detection fails fast in --apply; in plan-only mode it logs warnings and returns best-effort output.
  6. Deterministic repair + triage

    • If planning ends with deterministic issues, repair rounds (plan_repair_agent.go) patch the plan JSON and re-validate.
    • Findings are triaged (plan_issue_triage.go) into hard-fixable, likely-noise, and context-needed.
    • Repair prompts enforce strict contract: preserve valid commands, minimal diff, fix only listed issues.
    • User-data micro-repair — targeted LLM fix for user-data script issues without touching the rest of the plan.
  7. Conservative sanitizer (plan_sanitize.go)

    • Sanitization is fail-open: original vs sanitized plans are compared via deterministic issue count.
    • Sanitized plan is used only when it is not worse than original.
    • Includes generic arg normalization and safe command cleanup across providers.
  8. LLM validation + repair (ValidatePlan)

    • Once deterministic checks pass, the LLM validator reviews ordering/missing steps/port/env/IAM chaining.
    • If invalid, repair rounds rewrite plan JSON and re-validate.
    • Repair/review parsing uses LLM JSON-repair helpers (llm_plan_integrity.go) before giving up on a candidate.
    • Retention guard is issue-driven: allows focused removals when issues/fixes justify them, blocks broad command collapse.
  9. Final review + integrity passes

    • Review agent (plan_review_agent.go) — non-blocking pass that can append missing commands.
    • Generic integrity pass (llm_plan_integrity.go) — provider-agnostic minimal-diff fixes (tokenization, waiter usage, run-instances flag/script boundary, CloudFront config shape) without architecture drift.
  10. Plan finalize + apply orchestration

    • Placeholder/binding resolution and provider-specific enrichment.
    • In --apply, execution is staged (infra → build/push → workload launch → verification).
    • OpenClaw apply path seeds runtime env bindings from collected config and process env.
    • --enforce-image-deploy forces ECR image-based deploy (build/push + pull/run).
    • SSH safety rule: plans with SSH ingress on port 22 need explicit CIDR or fall back to SSM-only.
    • Auto-remediation prompts include deployment intent so self-heal stays aligned.

Compact Sequence Diagram

sequenceDiagram
    autonumber
    participant U as User
    participant C as cmd/deploy.go
    participant I as RunIntelligence
    participant S as Skeleton+Hydrate
    participant P as Paged Planner (fallback)
    participant A as Generic Autofix
    participant D as Deterministic Validator
    participant R as Plan Repair Agent
    participant V as LLM Validator
    participant E as Maker Executor

    U->>C: clanker deploy <repo>
    C->>C: Clone + static profile
    C->>I: RunIntelligence(profile, provider)
    I-->>C: enriched prompt + architecture + infra hints

    C->>S: GeneratePlanSkeleton (1 LLM call)
    S-->>C: PlanSkeleton (steps + placeholders)
    C->>S: HydrateSkeleton (batched LLM calls)
    S-->>C: hydrated plan commands

    alt skeleton/hydrate failed
      loop page 1..N
        C->>P: BuildPlanPagePrompt(current state)
        P-->>C: {done, commands[]}
      end
    end

    C->>A: ApplyGenericPlanAutofix(plan, externalBindings)
    A-->>C: deduped + pruned plan

    C->>D: deterministic validate (+ crossCheckUserDataVsPlan)
    D-->>C: hard issues / pass

    alt deterministic issues
      C->>R: user-data micro-repair / full repair
      R-->>C: patched plan
      C->>D: re-validate
    end

    C->>C: SanitizePlanConservative

    C->>V: LLM validate + repair loop
    V-->>C: validated plan

    alt --apply
      C->>E: execute staged plan
      E-->>U: deploy result + outputs
    else plan-only
      C-->>U: plan JSON + warnings
    end

Key Files

  • skeleton_plan.go — two-phase skeleton+hydrate plan generation (primary path)
  • paged_plan.go — paginated planning protocol (fallback path)
  • plan_autofix.go — generic plan autofix (dedup, orphan pruning, critical command protection)
  • plan_preflight_validate.go — deterministic hard checks + user-data vs plan cross-check
  • plan_repair_agent.go — plan rewrite/repair agent
  • plan_issue_triage.go — triage for hard-fixable vs noise/context findings
  • plan_sanitize.go — conservative fail-open plan sanitizer
  • plan_review_agent.go — final non-blocking plan reviewer pass
  • llm_plan_integrity.go — LLM JSON repair + generic integrity pass
  • intelligence.go — multi-phase intelligence + LLM validation
  • explorer.go — agentic file exploration
  • docker_agent.go — Docker/Compose understanding
  • infra_scan.go / cf_infra_scan.go — cloud inventory snapshots
  • openclaw_plan_autofix.go — OpenClaw-specific autofix (HTTPS_URL, compose hints)
  • userdata_autofix.go / userdata_fixups.go / userdata_repair.go — user-data fixups
  • resolve.go — placeholder/binding resolution
  • nodejs_userdata.go — Node.js user-data generation

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AllPlaceholdersAreProduced

func AllPlaceholdersAreProduced(plan *maker.Plan, placeholders []string) bool

AllPlaceholdersAreProduced returns true when every placeholder token is expected to be provided by an earlier command via `produces` bindings.

func AppendOpenClawDeploymentRequirements

func AppendOpenClawDeploymentRequirements(b *strings.Builder, p *RepoProfile, deep *DeepAnalysis) bool

func AppendPlanPage

func AppendPlanPage(plan *maker.Plan, page *PlanPage) int

func AppendWordPressDeploymentRequirements

func AppendWordPressDeploymentRequirements(b *strings.Builder, p *RepoProfile, deep *DeepAnalysis) bool

func ApplyEnvVarBindings

func ApplyEnvVarBindings(plan *maker.Plan, envVars map[string]string) *maker.Plan

ApplyEnvVarBindings deterministically resolves env-var placeholders like <DISCORD_BOT_TOKEN> using the actual values the user provided. This avoids relying on the LLM to map them (which fails when the API times out).

func ApplyGenericPlanAutofix

func ApplyGenericPlanAutofix(plan *maker.Plan, logf func(string, ...any), externalBindings ...string) *maker.Plan

ApplyGenericPlanAutofix runs provider-agnostic dedup/cleanup passes. externalBindings are placeholder names provided externally (e.g. user env vars) that should NOT be treated as orphaned even though no command produces them.

func ApplyOpenClawArchitectureDefaults

func ApplyOpenClawArchitectureDefaults(targetProvider string, opts *DeployOptions, p *RepoProfile, deep *DeepAnalysis, arch *ArchitectDecision) bool

func ApplyOpenClawPlanAutofix

func ApplyOpenClawPlanAutofix(plan *maker.Plan, profile *RepoProfile, deep *DeepAnalysis, logf func(string, ...any)) *maker.Plan

func ApplyStaticInfraBindings

func ApplyStaticInfraBindings(plan *maker.Plan, infraSnap *InfraSnapshot) *maker.Plan

ApplyStaticInfraBindings applies only the "static" infrastructure bindings that are always known regardless of whether a new VPC is being created. This includes AMI_ID, ACCOUNT_ID, and REGION which come from the infra scan. This function should be called even when --new-vpc is used.

func ApplyWordPressArchitectureDefaults

func ApplyWordPressArchitectureDefaults(targetProvider string, opts *DeployOptions, p *RepoProfile, deep *DeepAnalysis, arch *ArchitectDecision) bool

func ArchitectPrompt

func ArchitectPrompt(p *RepoProfile) string

ArchitectPrompt builds the prompt for the architect LLM call

func Base64EncodeEC2UserDataScripts

func Base64EncodeEC2UserDataScripts(plan *maker.Plan) *maker.Plan

Base64EncodeEC2UserDataScripts ensures any literal user-data scripts are base64 encoded. This avoids downstream placeholder scanners misinterpreting heredoc markers (e.g. <<EOF) and improves AWS CLI reliability.

func BuildPlanPagePrompt

func BuildPlanPagePrompt(provider string, enrichedPrompt string, currentPlan *maker.Plan, requiredLaunchOps []string, mustFixIssues []string, maxCommands int, formatHint string) string

func BuildPrompt

func BuildPrompt(p *RepoProfile, strat DeployStrategy, archDecision *ArchitectDecision) string

BuildPrompt generates the enriched natural-language prompt that feeds into maker.PlanPrompt. If archDecision is non-nil, it incorporates the LLM architect's reasoning.

func ClassifyUserDataIssues

func ClassifyUserDataIssues(issues []string) (userDataIssues, structuralIssues []string)

ClassifyUserDataIssues separates validation issues into user-data-specific and plan-structural categories.

func FixEC2UserDataScripts

func FixEC2UserDataScripts(plan *maker.Plan, logf func(string, ...any)) *maker.Plan

FixEC2UserDataScripts decodes base64 user-data in ec2 run-instances, applies common LLM-generated path and command typo corrections, and re-encodes. Runs before validation so deterministic fixes prevent issues from reaching the repair LLM.

func GenerateNodeJSUserData

func GenerateNodeJSUserData(repoURL string, deep *DeepAnalysis, config *UserConfig) string

GenerateNodeJSUserData creates EC2 user-data for native Node.js deployment. This handles any Node.js app: clones repo, installs deps, runs with PM2.

func GetUnresolvedPlaceholders

func GetUnresolvedPlaceholders(plan *maker.Plan) []string

GetUnresolvedPlaceholders returns the list of unresolved placeholder tokens in a plan.

func HasOpenClawCloudFront

func HasOpenClawCloudFront(planJSON string) bool

func HasUnresolvedPlaceholders

func HasUnresolvedPlaceholders(plan *maker.Plan) bool

HasUnresolvedPlaceholders checks if a plan still has unresolved placeholder tokens.

func HydrateSkeleton

func HydrateSkeleton(
	ctx context.Context,
	ask AskFunc,
	clean CleanFunc,
	provider string,
	enrichedPrompt string,
	skeleton *PlanSkeleton,
	logf func(string, ...any),
) (*maker.Plan, error)

HydrateSkeleton fills in the CLI args for each skeleton step via per-step LLM calls. Each call gets: the full skeleton (for context), the specific step to detail, and all commands generated so far (for consistency).

func IsOpenClawRepo

func IsOpenClawRepo(p *RepoProfile, deep *DeepAnalysis) bool

func IsWordPressRepo

func IsWordPressRepo(p *RepoProfile, deep *DeepAnalysis) bool

func OpenClawArchitectPromptAzure

func OpenClawArchitectPromptAzure() string

func OpenClawArchitectPromptGCP

func OpenClawArchitectPromptGCP() string

func OpenClawAzureVMPrompt

func OpenClawAzureVMPrompt(p *RepoProfile, deep *DeepAnalysis, opts *DeployOptions) string

func OpenClawComposeHardEnvVars

func OpenClawComposeHardEnvVars() []string

func OpenClawGCPComputeEnginePrompt

func OpenClawGCPComputeEnginePrompt(p *RepoProfile, deep *DeepAnalysis, opts *DeployOptions) string

func OpenClawPreferredBootstrapScripts

func OpenClawPreferredBootstrapScripts() []string

func PromptForEnvVarValues

func PromptForEnvVarValues(names []string) (map[string]string, error)

PromptForEnvVarValues prompts the user for values for the given env var names. It is used as a fallback when DeepAnalysis does not provide requiredEnvVars.

func RepairPlanJSONWithLLM

func RepairPlanJSONWithLLM(
	ctx context.Context,
	ask AskFunc,
	clean CleanFunc,
	deploymentIntent string,
	projectSummary string,
	raw string,
	baselinePlanJSON string,
	issues []string,
	requiredLaunchOps []string,
	logf func(string, ...any),
) (*maker.Plan, error)

func RepairUserDataWithLLM

func RepairUserDataWithLLM(
	ctx context.Context,
	plan *maker.Plan,
	issues []string,
	fixes []string,
	ask AskFunc,
	clean CleanFunc,
	logf func(string, ...any),
) (*maker.Plan, error)

RepairUserDataWithLLM performs a targeted micro-repair on user-data scripts inside ec2 run-instances commands. Instead of sending the full plan to the repair LLM (which causes full rewrites), we extract the script, send ONLY the script + relevant issues, and splice the fix back into the plan. Returns the patched plan and nil error on success. Returns the original plan unchanged if no user-data issues are found or repair fails.

func ResolvePlanPlaceholders

func ResolvePlanPlaceholders(
	ctx context.Context,
	plan *maker.Plan,
	infraSnap *InfraSnapshot,
	ask AskFunc,
	clean CleanFunc,
	logf func(string, ...any),
) (*maker.Plan, []string, error)

ResolvePlanPlaceholders attempts to replace placeholder tokens in the plan with actual values. It first tries to map from the InfraSnapshot, then calls the LLM for any remaining placeholders. Returns the modified plan and a list of any placeholders that could not be resolved.

func RunGenericPlanIntegrityPassWithLLM

func RunGenericPlanIntegrityPassWithLLM(
	ctx context.Context,
	ask AskFunc,
	clean CleanFunc,
	plan *maker.Plan,
	deploymentIntent string,
	projectSummary string,
	requiredLaunchOps []string,
	logf func(string, ...any),
) (*maker.Plan, error)

func SanitizePlan

func SanitizePlan(plan *maker.Plan) *maker.Plan

func SanitizePlanConservative

func SanitizePlanConservative(plan *maker.Plan, profile *RepoProfile, deep *DeepAnalysis, docker *DockerAnalysis, logf func(string, ...any)) *maker.Plan

SanitizePlanConservative applies sanitization in a fail-open way: it evaluates original vs sanitized with deterministic validation and never picks a candidate with more deterministic issues than the original.

func WordPressEC2Prompt

func WordPressEC2Prompt(p *RepoProfile, opts *DeployOptions) string

WordPressEC2Prompt returns a detailed EC2 deployment prompt for WordPress. Unlike generic EC2, WordPress pulls images from Docker Hub (no ECR).

Types

type ArchitectDecision

type ArchitectDecision struct {
	Provider      string   `json:"provider"`                // aws, cloudflare
	Method        string   `json:"method"`                  // ecs-fargate, ec2, eks, lambda, s3-cloudfront, cf-pages, cf-workers, cf-containers
	Reasoning     string   `json:"reasoning"`               // why this architecture
	BuildSteps    []string `json:"buildSteps"`              // how to build it
	RunCmd        string   `json:"runCmd"`                  // simplest way to start it locally
	Notes         []string `json:"notes"`                   // gotchas, warnings
	CpuMemory     string   `json:"cpuMemory"`               // e.g. "256/512", "512/1024", or instance type for EC2
	NeedsALB      bool     `json:"needsAlb"`                // whether to put an ALB in front
	UseAPIGateway bool     `json:"useApiGateway"`           // whether to use API Gateway instead of ALB
	NeedsDB       bool     `json:"needsDb"`                 // whether to provision a managed DB
	DBService     string   `json:"dbService"`               // rds-postgres, elasticache-redis, etc
	EstMonthly    string   `json:"estMonthly"`              // estimated monthly cost e.g. "$15-25"
	CostBreakdown []string `json:"costBreakdown,omitempty"` // per-service cost breakdown
}

ArchitectDecision is the structured JSON response from the architect LLM call

func ParseArchitectDecision

func ParseArchitectDecision(raw string) (*ArchitectDecision, error)

ParseArchitectDecision parses the LLM response into an ArchitectDecision

type AskFunc

type AskFunc func(ctx context.Context, prompt string) (string, error)

AskFunc is the LLM call interface — matches ai.Client.AskPrompt signature

type CFInfraSnapshot

type CFInfraSnapshot struct {
	AccountID     string   `json:"accountId,omitempty"`
	Workers       []string `json:"workers,omitempty"`       // existing worker names
	PagesProjects []string `json:"pagesProjects,omitempty"` // existing pages projects
	KVNamespaces  []string `json:"kvNamespaces,omitempty"`  // existing KV namespaces
	D1Databases   []string `json:"d1Databases,omitempty"`   // existing D1 databases
	R2Buckets     []string `json:"r2Buckets,omitempty"`     // existing R2 buckets
}

CFInfraSnapshot holds existing Cloudflare resources

func ScanCFInfra

func ScanCFInfra(ctx context.Context, logf func(string, ...any)) *CFInfraSnapshot

ScanCFInfra queries the Cloudflare account for existing resources via wrangler

func (*CFInfraSnapshot) FormatCFForPrompt

func (s *CFInfraSnapshot) FormatCFForPrompt() string

FormatCFForPrompt formats the CF infra snapshot for LLM context

type CleanFunc

type CleanFunc func(response string) string

CleanFunc strips markdown fences from LLM JSON responses

type DeepAnalysis

type DeepAnalysis struct {
	AppDescription string   `json:"appDescription"` // what does this app do
	Services       []string `json:"services"`       // list of services/components
	ExternalDeps   []string `json:"externalDeps"`   // external APIs, databases, etc
	BuildPipeline  string   `json:"buildPipeline"`  // how to actually build this thing
	RunLocally     string   `json:"runLocally"`     // simplest way to run locally
	Complexity     string   `json:"complexity"`     // simple, moderate, complex
	Concerns       []string `json:"concerns"`       // things that could go wrong

	// Node.js app characteristics (detected from README and code)
	ListeningPort int    `json:"listeningPort"` // port the app listens on
	StartCommand  string `json:"startCommand"`  // how to start: "npm start", "node index.js"
	BuildCommand  string `json:"buildCommand"`  // build step if needed: "npm run build"
	NodeVersion   string `json:"nodeVersion"`   // required Node version

	// Config requirements (extracted from README and .env files)
	RequiredEnvVars []EnvVarSpec `json:"requiredEnvVars"` // MUST have values to run
	OptionalEnvVars []EnvVarSpec `json:"optionalEnvVars"` // nice to have, has defaults

	// Health verification
	HealthEndpoint string `json:"healthEndpoint"` // e.g., "/health", "/api/status"
	ExposesHTTP    bool   `json:"exposesHTTP"`    // does it serve HTTP?

	// Deployment method
	PreferDocker  bool   `json:"preferDocker"`  // true if Dockerfile exists and is recommended
	GlobalInstall string `json:"globalInstall"` // e.g., "npm install -g appname"
}

DeepAnalysis is the LLM's understanding of what the app actually does

type DeployOptions

type DeployOptions struct {
	Target       string // fargate, ec2, eks
	InstanceType string // for ec2: t3.small, t3.medium, etc.
	NewVPC       bool   // create new VPC instead of using default
	DeployID     string // run-specific id for unique resource naming
}

DeployOptions contains user-specified deployment preferences

type DeployStrategy

type DeployStrategy struct {
	Provider  string // aws, cloudflare
	Method    string // ecs-fargate, ec2, lambda, s3-cloudfront, cf-pages, cf-workers, cf-containers
	Region    string
	Reasoning string // LLM's reasoning for the choice
}

DeployStrategy controls how we deploy

func DefaultStrategy

func DefaultStrategy(p *RepoProfile) DeployStrategy

DefaultStrategy picks the best deployment method based on the repo profile

func StrategyFromArchitect

func StrategyFromArchitect(d *ArchitectDecision) DeployStrategy

StrategyFromArchitect converts an ArchitectDecision into a DeployStrategy

type DockerAnalysis

type DockerAnalysis struct {
	HasDockerfile       bool     `json:"hasDockerfile"`
	HasCompose          bool     `json:"hasCompose"`
	BuildUsesMultiStage bool     `json:"buildUsesMultiStage"`
	HasPlatformPin      bool     `json:"hasPlatformPin"`
	PlatformPins        []string `json:"platformPins,omitempty"`
	ComposeServices     []string `json:"composeServices,omitempty"`
	ExposedPorts        []int    `json:"exposedPorts,omitempty"`
	PublishedPorts      []int    `json:"publishedPorts,omitempty"`
	PrimaryPort         int      `json:"primaryPort,omitempty"`
	HasHealthcheck      bool     `json:"hasHealthcheck"`
	HealthcheckHint     string   `json:"healthcheckHint,omitempty"`
	VolumeMounts        []string `json:"volumeMounts,omitempty"`
	EnvFiles            []string `json:"envFiles,omitempty"`
	ReferencedEnvVars   []string `json:"referencedEnvVars,omitempty"`
	HardRequiredEnvVars []string `json:"hardRequiredEnvVars,omitempty"`
	BuildCommand        string   `json:"buildCommand,omitempty"`
	RunCommand          string   `json:"runCommand,omitempty"`
	Warnings            []string `json:"warnings,omitempty"`
}

func AnalyzeDockerAgent

func AnalyzeDockerAgent(profile *RepoProfile) *DockerAnalysis

func (*DockerAnalysis) FormatForPrompt

func (d *DockerAnalysis) FormatForPrompt() string

type EnvVarSpec

type EnvVarSpec struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Required    bool   `json:"required"`
	Default     string `json:"default"` // default value if known
	Example     string `json:"example"`
}

EnvVarSpec describes a required or optional environment variable

type ExplorationResult

type ExplorationResult struct {
	FilesRead map[string]string // all files read during exploration
	Rounds    int               // how many exploration rounds
	Analysis  string            // LLM's analysis after reading everything
}

ExplorationResult is the output of the agentic exploration

func ExploreRepo

func ExploreRepo(ctx context.Context, profile *RepoProfile, ask AskFunc, clean CleanFunc, logf func(string, ...any)) (*ExplorationResult, error)

ExploreRepo runs agentic file exploration: LLM sees the tree → requests files → we read them → LLM requests more → done

type FileRequest

type FileRequest struct {
	Files    []string `json:"files"`    // files it wants to read
	Reason   string   `json:"reason"`   // why it needs them
	Done     bool     `json:"done"`     // true = has enough context
	Analysis string   `json:"analysis"` // partial analysis so far (when done=true)
}

FileRequest is what the LLM asks for during exploration

type InfraSnapshot

type InfraSnapshot struct {
	AccountID                  string   `json:"accountId,omitempty"`
	Region                     string   `json:"region"`
	VPC                        *VPCInfo `json:"vpc,omitempty"`
	ECRRepos                   []string `json:"ecrRepos,omitempty"`                   // existing ECR repos
	CloudFrontDists            []string `json:"cloudFrontDists,omitempty"`            // existing CloudFront distribution domains
	LightsailInstances         []string `json:"lightsailInstances,omitempty"`         // existing Lightsail instances
	LightsailContainerServices []string `json:"lightsailContainerServices,omitempty"` // existing Lightsail container services
	LightsailDistributions     []string `json:"lightsailDistributions,omitempty"`     // existing Lightsail CDN distributions
	ECSClusters                []string `json:"ecsClusters,omitempty"`                // existing ECS clusters
	ALBs                       []string `json:"albs,omitempty"`                       // existing ALBs
	RDSInstances               []string `json:"rdsInstances,omitempty"`               // existing RDS instances
	SecurityGroups             []SGInfo `json:"securityGroups,omitempty"`             // existing SGs in default VPC
	LatestAMI                  string   `json:"latestAmi,omitempty"`                  // latest Amazon Linux 2023 AMI ID
	Summary                    string   `json:"summary"`
}

InfraSnapshot is a snapshot of existing AWS infrastructure

func ScanInfra

func ScanInfra(ctx context.Context, profile, region string, logf func(string, ...any)) *InfraSnapshot

ScanInfra queries the AWS account to see what's already there. Uses the provided profile and region. Fails gracefully on permission errors.

func (*InfraSnapshot) FormatForPrompt

func (s *InfraSnapshot) FormatForPrompt() string

FormatForPrompt formats the infra snapshot as text for the LLM prompt

type IntelligenceResult

type IntelligenceResult struct {
	Exploration  *ExplorationResult `json:"exploration,omitempty"`
	DeepAnalysis *DeepAnalysis      `json:"deepAnalysis"`
	Docker       *DockerAnalysis    `json:"docker,omitempty"`
	Preflight    *PreflightReport   `json:"preflight,omitempty"`
	InfraSnap    *InfraSnapshot     `json:"infraSnapshot,omitempty"`
	CFInfraSnap  *CFInfraSnapshot   `json:"cfInfraSnapshot,omitempty"`
	Architecture *ArchitectDecision `json:"architecture"`
	Validation   *PlanValidation    `json:"validation,omitempty"`
	// final enriched prompt for maker pipeline
	EnrichedPrompt string `json:"enrichedPrompt"`
}

IntelligenceResult is the final output of the multi-phase reasoning pipeline

func RunIntelligence

func RunIntelligence(ctx context.Context, profile *RepoProfile, ask AskFunc, clean CleanFunc, debug bool, targetProvider, awsProfile, awsRegion string, opts *DeployOptions, logf func(string, ...any)) (*IntelligenceResult, error)

RunIntelligence executes the multi-phase recursive reasoning pipeline. Phase 0: Agentic file exploration (LLM requests files it needs) Phase 1: Deep Understanding (LLM analyzes all gathered context) Phase 1.5: AWS infra scan (query account for existing resources) Phase 2: Architecture Decision + Cost Estimation (LLM picks best option) Both phases feed into the final enriched prompt for the maker plan generator.

type PlanPage

type PlanPage struct {
	Done     bool            `json:"done"`
	Commands []maker.Command `json:"commands"`
	Summary  string          `json:"summary,omitempty"`
	Notes    []string        `json:"notes,omitempty"`
}

PlanPage is a paginated chunk of commands used to build a full maker.Plan incrementally. It is intentionally small to avoid LLM output truncation.

func ParsePlanPage

func ParsePlanPage(cleanedJSON string) (*PlanPage, error)

func RepairPlanPageWithLLM

func RepairPlanPageWithLLM(
	ctx context.Context,
	ask AskFunc,
	clean CleanFunc,
	provider string,
	deploymentIntent string,
	projectSummary string,
	raw string,
	formatHint string,
	logf func(string, ...any),
) (*PlanPage, string, error)

type PlanRepairAgent

type PlanRepairAgent struct {
	// contains filtered or unexported fields
}

func NewPlanRepairAgent

func NewPlanRepairAgent(ask AskFunc, clean CleanFunc, logf func(string, ...any)) *PlanRepairAgent

func (*PlanRepairAgent) Repair

type PlanRepairContext

type PlanRepairContext struct {
	Provider   string
	Method     string
	RepoURL    string
	LLMContext string

	GCPProject          string
	AzureSubscriptionID string
	CloudflareAccountID string

	// App/runtime hints (kept compact)
	Ports               []int
	ComposeHardEnvVars  []string
	RequiredEnvVarNames []string
	// RequiredLaunchOps constrains the repair to include at least one workload "launch" step.
	// Each entry is "<service> <operation>" (e.g. "ec2 run-instances", "ecs create-service").
	RequiredLaunchOps []string

	// AWS infra hints (optional)
	Region  string
	Account string
	VPCID   string
	Subnets []string
	AMIID   string
}

type PlanReviewAgent

type PlanReviewAgent struct {
	// contains filtered or unexported fields
}

func NewPlanReviewAgent

func NewPlanReviewAgent(ask AskFunc, clean CleanFunc, logf func(string, ...any)) *PlanReviewAgent

func (*PlanReviewAgent) Review

func (a *PlanReviewAgent) Review(ctx context.Context, planJSON string, c PlanReviewContext) (string, error)

type PlanReviewContext

type PlanReviewContext struct {
	Provider                  string
	Method                    string
	RepoURL                   string
	LLMContext                string
	ProjectSummary            string
	ProjectCharacteristics    []string
	RequiredLaunchOps         []string
	IsOpenClaw                bool
	OpenClawCloudFrontMissing bool
	IsWordPress               bool
	Issues                    []string
	Fixes                     []string
	Warnings                  []string
}

type PlanSkeleton

type PlanSkeleton struct {
	Steps []SkeletonStep `json:"steps"`
	Notes []string       `json:"notes,omitempty"`
}

PlanSkeleton is the high-level structure of a deployment plan. Generated in a single LLM call — just service/operation pairs, no full args.

func GeneratePlanSkeleton

func GeneratePlanSkeleton(
	ctx context.Context,
	ask AskFunc,
	clean CleanFunc,
	provider string,
	enrichedPrompt string,
	requiredLaunchOps []string,
	logf func(string, ...any),
) (*PlanSkeleton, error)

GeneratePlanSkeleton asks the LLM to produce only the plan structure. No CLI args, no JSON payloads — just the ordered list of service/operation pairs with placeholder dependency wiring.

type PlanValidation

type PlanValidation struct {
	IsValid                bool     `json:"isValid"`
	Issues                 []string `json:"issues"`                 // problems found
	Fixes                  []string `json:"fixes"`                  // suggested fixes
	Warnings               []string `json:"warnings"`               // non-blocking warnings
	UnresolvedPlaceholders []string `json:"unresolvedPlaceholders"` // placeholders that need resolution
}

PlanValidation is the LLM's review of its own generated plan

func CheckBulkRepairInvariants

func CheckBulkRepairInvariants(plan *maker.Plan, profile *RepoProfile, deep *DeepAnalysis) *PlanValidation

func CheckOpenClawBulkInvariants

func CheckOpenClawBulkInvariants(plan *maker.Plan, profile *RepoProfile, deep *DeepAnalysis) *PlanValidation

func DeterministicValidatePlan

func DeterministicValidatePlan(planJSON string, profile *RepoProfile, deep *DeepAnalysis, docker *DockerAnalysis) *PlanValidation

DeterministicValidatePlan runs only the deterministic validation checks and returns a PlanValidation. This is used for incremental / checkpointed plan generation to avoid repeated LLM validation calls.

func ValidatePlan

func ValidatePlan(ctx context.Context, planJSON string, profile *RepoProfile, deep *DeepAnalysis, docker *DockerAnalysis, requireDockerCommandsInPlan bool, ask AskFunc, clean CleanFunc, logf func(string, ...any)) (*PlanValidation, string, error)

ValidatePlan runs the LLM validation phase on a generated plan. Call this AFTER the maker plan is generated. Returns validation result and an optional revised prompt if issues were found.

type PreflightReport

type PreflightReport struct {
	PackageManager     string   `json:"packageManager"`
	IsMonorepo         bool     `json:"isMonorepo"`
	LockFiles          []string `json:"lockFiles,omitempty"`
	BootstrapScripts   []string `json:"bootstrapScripts,omitempty"`
	EnvExampleFiles    []string `json:"envExampleFiles,omitempty"`
	MigrationHints     []string `json:"migrationHints,omitempty"`
	NativeDeps         []string `json:"nativeDeps,omitempty"`
	BuildOutputDir     string   `json:"buildOutputDir,omitempty"`
	IsStaticSite       bool     `json:"isStaticSite"`
	ComposeHardEnvVars []string `json:"composeHardEnvVars,omitempty"`
	Warnings           []string `json:"warnings,omitempty"`
}

func BuildPreflightReport

func BuildPreflightReport(p *RepoProfile, docker *DockerAnalysis, deep *DeepAnalysis) *PreflightReport

func (*PreflightReport) FormatForPrompt

func (r *PreflightReport) FormatForPrompt() string

type RepairIssueTriage

type RepairIssueTriage struct {
	Hard          *PlanValidation
	LikelyNoise   []string
	ContextNeeded []string
}

func TriageValidationForRepair

func TriageValidationForRepair(v *PlanValidation) RepairIssueTriage

type RepoProfile

type RepoProfile struct {
	RepoURL          string            `json:"repoUrl"`
	ClonePath        string            `json:"clonePath"`
	Language         string            `json:"language"`       // go, python, node, rust, java, etc
	Framework        string            `json:"framework"`      // express, flask, fastapi, gin, fiber, nextjs, etc
	PackageManager   string            `json:"packageManager"` // npm, pnpm, yarn, bun, pip, cargo, go
	IsMonorepo       bool              `json:"isMonorepo"`
	HasDocker        bool              `json:"hasDocker"`
	HasCompose       bool              `json:"hasCompose"`                 // docker-compose.yml
	DeployHints      []string          `json:"deployHints"`                // fly.toml, render.yaml, etc
	BootstrapScripts []string          `json:"bootstrapScripts,omitempty"` // docker-setup.sh, setup scripts, onboard scripts
	EnvExampleFiles  []string          `json:"envExampleFiles,omitempty"`  // .env.example, etc
	MigrationHints   []string          `json:"migrationHints,omitempty"`   // detected migration tooling/files
	NativeDeps       []string          `json:"nativeDeps,omitempty"`       // node native deps that often need OS packages
	BuildOutputDir   string            `json:"buildOutputDir,omitempty"`   // dist/build/out/.next
	IsStaticSite     bool              `json:"isStaticSite"`               // likely static bundle deployable
	LockFiles        []string          `json:"lockFiles,omitempty"`        // pnpm-lock.yaml, yarn.lock, etc
	Ports            []int             `json:"ports"`
	EnvVars          []string          `json:"envVars"`    // required env vars detected
	EntryPoint       string            `json:"entryPoint"` // main.go, app.py, index.js, etc
	BuildCmd         string            `json:"buildCmd"`
	StartCmd         string            `json:"startCmd"`
	HasDB            bool              `json:"hasDb"`
	DBType           string            `json:"dbType"` // postgres, mysql, redis, mongo, etc
	Summary          string            `json:"summary"`
	KeyFiles         map[string]string `json:"keyFiles"` // filename → content (capped)
	FileTree         string            `json:"fileTree"` // top-level directory listing
}

RepoProfile is the result of analyzing a git repo

func Analyze

func Analyze(dir string) (*RepoProfile, error)

Analyze inspects a local directory

func CloneAndAnalyze

func CloneAndAnalyze(ctx context.Context, repoURL string) (*RepoProfile, error)

CloneAndAnalyze clones a repo and returns a profile

type SGInfo

type SGInfo struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

SGInfo is a security group summary

type SkeletonStep

type SkeletonStep struct {
	Service   string   `json:"service"`              // e.g. "iam", "ec2", "elbv2", "ssm", "secretsmanager"
	Operation string   `json:"operation"`            // e.g. "create-role", "run-instances"
	Reason    string   `json:"reason"`               // why this step exists
	Produces  []string `json:"produces,omitempty"`   // placeholder names this step outputs (e.g. ["ROLE_ARN"])
	DependsOn []string `json:"depends_on,omitempty"` // placeholder names required from earlier steps
}

SkeletonStep is one step in the skeleton — intentionally minimal.

type UserConfig

type UserConfig struct {
	EnvVars      map[string]string // all env vars (required + optional with values)
	AppPort      int               // confirmed listening port
	DeployMode   string            // docker or native
	StartCommand string            // confirmed start command
	BuildCommand string            // build command if needed
}

UserConfig holds user-provided deployment configuration

func DefaultUserConfig

func DefaultUserConfig(deep *DeepAnalysis, profile *RepoProfile) *UserConfig

DefaultUserConfig returns a default config when no prompting is needed

func PromptForConfig

func PromptForConfig(deep *DeepAnalysis, profile *RepoProfile) (*UserConfig, error)

PromptForConfig collects required configuration from user before deployment

type VPCInfo

type VPCInfo struct {
	VPCID     string   `json:"vpcId"`
	Subnets   []string `json:"subnets"` // subnet IDs
	IsDefault bool     `json:"isDefault"`
}

VPCInfo is the default VPC + subnets info

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL