Saturday, May 30, 2026

BUILDING AN LLM-BASED AGENT FOR DOCKER AND KUBERNETES AUTOMATION WITH GO

 



INTRODUCTION AND PROBLEM ANALYSIS


Creating containerized applications and orchestrating them through Kubernetes requires deep expertise across multiple domains including container runtime configuration, networking, storage, security policies, and deployment strategies. Development teams often spend significant time writing Dockerfiles, Kubernetes manifests, Helm charts, and associated configuration files. An intelligent agent powered by Large Language Models can dramatically reduce this overhead by understanding natural language requirements and generating production-ready artifacts.


The core challenge involves building a system that can interpret user intentions expressed in natural language, maintain context about the application architecture, generate syntactically correct and semantically meaningful configuration files, and support iterative refinement. The agent must understand the relationships between different Kubernetes resources such as Deployments, Services, ConfigMaps, Secrets, Ingresses, and PersistentVolumeClaims. It must also generate appropriate Dockerfiles that follow best practices for layer caching, security, and minimal image sizes.


This article presents a comprehensive architecture for such an agent implemented in Go. The system supports both local and remote LLM providers, accommodates various GPU architectures including Intel, AMD ROCm, Apple Metal Performance Shaders, and Nvidia CUDA, and generates complete Docker and Kubernetes artifacts including Helm charts. The implementation follows clean architecture principles with clear separation of concerns, dependency injection, and comprehensive error handling.


ARCHITECTURAL OVERVIEW

The agent architecture consists of several key layers. The presentation layer handles user interactions through a command-line interface or API endpoints. The application layer contains the core business logic for interpreting requests, managing conversation context, and orchestrating artifact generation. The domain layer defines the entities and value objects representing Docker and Kubernetes concepts. The infrastructure layer provides adapters for different LLM providers, file system operations, and external tool integrations.


The system employs a plugin-based architecture for LLM providers, allowing seamless switching between local models running on various GPU architectures and remote API-based services. Each provider implements a common interface that abstracts the underlying communication protocol and response parsing. This design enables the agent to leverage the most appropriate model based on availability, cost, and performance requirements.


Context management is critical for maintaining coherent conversations across multiple interactions. The agent maintains a conversation history that includes user requests, generated artifacts, and validation results. This context allows the LLM to understand references to previously generated resources and make informed decisions about modifications and additions.


LLM PROVIDER ABSTRACTION


The foundation of the agent is a flexible abstraction for interacting with different LLM providers. This abstraction must handle the diversity of APIs, authentication mechanisms, and response formats while presenting a uniform interface to the application layer.


// Package llm provides abstractions for interacting with Large Language Models

package llm


import (

    "context"

    "time"

)


// Message represents a single message in a conversation

type Message struct {

    Role      string    // "system", "user", or "assistant"

    Content   string    // The message content

    Timestamp time.Time // When the message was created

}


// CompletionRequest encapsulates parameters for generating a completion

type CompletionRequest struct {

    Messages        []Message         // Conversation history

    MaxTokens       int               // Maximum tokens to generate

    Temperature     float64           // Sampling temperature (0.0 to 2.0)

    TopP            float64           // Nucleus sampling parameter

    StopSequences   []string          // Sequences that stop generation

    PresencePenalty float64           // Penalty for token presence

    Metadata        map[string]string // Additional provider-specific parameters

}


// CompletionResponse contains the generated completion and metadata

type CompletionResponse struct {

    Content       string            // Generated text

    FinishReason  string            // Why generation stopped

    TokensUsed    int               // Total tokens consumed

    PromptTokens  int               // Tokens in the prompt

    ModelUsed     string            // Actual model identifier

    Metadata      map[string]string // Provider-specific response data

}


// Provider defines the interface that all LLM providers must implement

type Provider interface {

    // GenerateCompletion sends a request and returns the completion

    GenerateCompletion(ctx context.Context, req CompletionRequest) (*CompletionResponse, error)

    

    // GetCapabilities returns information about what this provider supports

    GetCapabilities() ProviderCapabilities

    

    // HealthCheck verifies the provider is accessible and functional

    HealthCheck(ctx context.Context) error

    

    // Close releases any resources held by the provider

    Close() error

}


// ProviderCapabilities describes what a provider supports

type ProviderCapabilities struct {

    SupportsStreaming   bool     // Can stream responses

    MaxContextTokens    int      // Maximum context window size

    SupportedModalities []string // "text", "image", "audio"

    RequiresAPIKey      bool     // Whether authentication is needed

    GPUAccelerated      bool     // Whether GPU acceleration is available

}


This interface provides a clean contract that all provider implementations must fulfill. The Message structure captures the conversational context, while CompletionRequest and CompletionResponse handle the request-response cycle with comprehensive metadata. The ProviderCapabilities structure allows the application layer to make informed decisions about which provider to use based on requirements.


LOCAL LLM PROVIDER IMPLEMENTATION


Supporting local LLM execution requires interfacing with model serving frameworks that can leverage different GPU architectures. The implementation uses a unified approach that detects available hardware and configures the appropriate backend.


// Package locallm implements a provider for locally-hosted LLM inference

package locallm


import (

    "bytes"

    "context"

    "encoding/json"

    "fmt"

    "io"

    "net/http"

    "runtime"

    "time"

    

    "agent/llm"

)


// LocalProvider implements the Provider interface for local model serving

type LocalProvider struct {

    baseURL       string        // URL of the local inference server

    modelName     string        // Name of the loaded model

    client        *http.Client  // HTTP client for API calls

    gpuBackend    GPUBackend    // Detected GPU backend

    maxRetries    int           // Number of retry attempts

    retryDelay    time.Duration // Delay between retries

}


// GPUBackend represents the detected GPU acceleration backend

type GPUBackend string


const (

    GPUBackendCUDA   GPUBackend = "cuda"   // Nvidia CUDA

    GPUBackendROCm   GPUBackend = "rocm"   // AMD ROCm

    GPUBackendMPS    GPUBackend = "mps"    // Apple Metal Performance Shaders

    GPUBackendIntel  GPUBackend = "intel"  // Intel GPU

    GPUBackendCPU    GPUBackend = "cpu"    // CPU fallback

)


// LocalProviderConfig contains configuration for the local provider

type LocalProviderConfig struct {

    BaseURL       string

    ModelName     string

    Timeout       time.Duration

    MaxRetries    int

    RetryDelay    time.Duration

    ForceBackend  GPUBackend // Optional: force a specific backend

}


// NewLocalProvider creates a new local LLM provider instance

func NewLocalProvider(config LocalProviderConfig) (*LocalProvider, error) {

    if config.BaseURL == "" {

        return nil, fmt.Errorf("base URL is required")

    }

    

    if config.ModelName == "" {

        return nil, fmt.Errorf("model name is required")

    }

    

    if config.Timeout == 0 {

        config.Timeout = 120 * time.Second

    }

    

    if config.MaxRetries == 0 {

        config.MaxRetries = 3

    }

    

    if config.RetryDelay == 0 {

        config.RetryDelay = 2 * time.Second

    }

    

    backend := config.ForceBackend

    if backend == "" {

        backend = detectGPUBackend()

    }

    

    provider := &LocalProvider{

        baseURL:    config.BaseURL,

        modelName:  config.ModelName,

        gpuBackend: backend,

        maxRetries: config.MaxRetries,

        retryDelay: config.RetryDelay,

        client: &http.Client{

            Timeout: config.Timeout,

        },

    }

    

    return provider, nil

}


// detectGPUBackend attempts to detect the available GPU backend

func detectGPUBackend() GPUBackend {

    // Check operating system and available libraries

    switch runtime.GOOS {

    case "darwin":

        // macOS systems use Metal Performance Shaders

        return GPUBackendMPS

    case "linux", "windows":

        // Check for CUDA availability

        if checkCUDAAvailable() {

            return GPUBackendCUDA

        }

        // Check for ROCm availability

        if checkROCmAvailable() {

            return GPUBackendROCm

        }

        // Check for Intel GPU

        if checkIntelGPUAvailable() {

            return GPUBackendIntel

        }

    }

    

    // Fallback to CPU

    return GPUBackendCPU

}


// checkCUDAAvailable checks if CUDA is available on the system

func checkCUDAAvailable() bool {

    // Implementation would check for nvidia-smi or CUDA libraries

    // This is a simplified version

    return false // Placeholder for actual detection logic

}


// checkROCmAvailable checks if AMD ROCm is available

func checkROCmAvailable() bool {

    // Implementation would check for rocm-smi or ROCm libraries

    return false // Placeholder for actual detection logic

}


// checkIntelGPUAvailable checks if Intel GPU acceleration is available

func checkIntelGPUAvailable() bool {

    // Implementation would check for Intel GPU drivers and libraries

    return false // Placeholder for actual detection logic

}


// GenerateCompletion implements the Provider interface

func (p *LocalProvider) GenerateCompletion(ctx context.Context, req llm.CompletionRequest) (*llm.CompletionResponse, error) {

    // Convert our request format to the local server's API format

    apiRequest := map[string]interface{}{

        "model":             p.modelName,

        "messages":          convertMessages(req.Messages),

        "max_tokens":        req.MaxTokens,

        "temperature":       req.Temperature,

        "top_p":             req.TopP,

        "stop":              req.StopSequences,

        "presence_penalty":  req.PresencePenalty,

    }

    

    // Add any provider-specific metadata

    for key, value := range req.Metadata {

        apiRequest[key] = value

    }

    

    requestBody, err := json.Marshal(apiRequest)

    if err != nil {

        return nil, fmt.Errorf("failed to marshal request: %w", err)

    }

    

    // Execute the request with retry logic

    var lastErr error

    for attempt := 0; attempt <= p.maxRetries; attempt++ {

        if attempt > 0 {

            select {

            case <-ctx.Done():

                return nil, ctx.Err()

            case <-time.After(p.retryDelay):

            }

        }

        

        response, err := p.executeRequest(ctx, requestBody)

        if err == nil {

            return response, nil

        }

        

        lastErr = err

    }

    

    return nil, fmt.Errorf("failed after %d attempts: %w", p.maxRetries+1, lastErr)

}


// executeRequest performs a single HTTP request to the local server

func (p *LocalProvider) executeRequest(ctx context.Context, requestBody []byte) (*llm.CompletionResponse, error) {

    endpoint := fmt.Sprintf("%s/v1/chat/completions", p.baseURL)

    

    httpReq, err := http.NewRequestWithContext(ctx, "POST", endpoint, bytes.NewReader(requestBody))

    if err != nil {

        return nil, fmt.Errorf("failed to create request: %w", err)

    }

    

    httpReq.Header.Set("Content-Type", "application/json")

    

    httpResp, err := p.client.Do(httpReq)

    if err != nil {

        return nil, fmt.Errorf("request failed: %w", err)

    }

    defer httpResp.Body.Close()

    

    if httpResp.StatusCode != http.StatusOK {

        body, _ := io.ReadAll(httpResp.Body)

        return nil, fmt.Errorf("server returned status %d: %s", httpResp.StatusCode, string(body))

    }

    

    var apiResponse struct {

        Choices []struct {

            Message struct {

                Content string `json:"content"`

            } `json:"message"`

            FinishReason string `json:"finish_reason"`

        } `json:"choices"`

        Usage struct {

            PromptTokens     int `json:"prompt_tokens"`

            CompletionTokens int `json:"completion_tokens"`

            TotalTokens      int `json:"total_tokens"`

        } `json:"usage"`

        Model string `json:"model"`

    }

    

    if err := json.NewDecoder(httpResp.Body).Decode(&apiResponse); err != nil {

        return nil, fmt.Errorf("failed to decode response: %w", err)

    }

    

    if len(apiResponse.Choices) == 0 {

        return nil, fmt.Errorf("no choices in response")

    }

    

    return &llm.CompletionResponse{

        Content:      apiResponse.Choices[0].Message.Content,

        FinishReason: apiResponse.Choices[0].FinishReason,

        TokensUsed:   apiResponse.Usage.TotalTokens,

        PromptTokens: apiResponse.Usage.PromptTokens,

        ModelUsed:    apiResponse.Model,

        Metadata: map[string]string{

            "gpu_backend": string(p.gpuBackend),

        },

    }, nil

}


// convertMessages transforms our message format to the API format

func convertMessages(messages []llm.Message) []map[string]string {

    result := make([]map[string]string, len(messages))

    for i, msg := range messages {

        result[i] = map[string]string{

            "role":    msg.Role,

            "content": msg.Content,

        }

    }

    return result

}


// GetCapabilities returns the capabilities of this provider

func (p *LocalProvider) GetCapabilities() llm.ProviderCapabilities {

    return llm.ProviderCapabilities{

        SupportsStreaming:   false,

        MaxContextTokens:    8192, // This would be model-specific

        SupportedModalities: []string{"text"},

        RequiresAPIKey:      false,

        GPUAccelerated:      p.gpuBackend != GPUBackendCPU,

    }

}


// HealthCheck verifies the local server is accessible

func (p *LocalProvider) HealthCheck(ctx context.Context) error {

    endpoint := fmt.Sprintf("%s/health", p.baseURL)

    

    req, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil)

    if err != nil {

        return fmt.Errorf("failed to create health check request: %w", err)

    }

    

    resp, err := p.client.Do(req)

    if err != nil {

        return fmt.Errorf("health check failed: %w", err)

    }

    defer resp.Body.Close()

    

    if resp.StatusCode != http.StatusOK {

        return fmt.Errorf("health check returned status %d", resp.StatusCode)

    }

    

    return nil

}


// Close releases resources held by the provider

func (p *LocalProvider) Close() error {

    p.client.CloseIdleConnections()

    return nil

}


The LocalProvider implementation demonstrates several important patterns. The GPU backend detection logic allows the system to automatically configure itself based on available hardware. The retry mechanism with exponential backoff ensures resilience against transient failures. The health check endpoint enables the system to verify connectivity before attempting expensive operations.


REMOTE LLM PROVIDER IMPLEMENTATION


Remote LLM providers offer access to powerful models without requiring local infrastructure. The implementation must handle API authentication, rate limiting, and provider-specific response formats.


// Package remotellm implements providers for cloud-based LLM services

package remotellm


import (

    "bytes"

    "context"

    "encoding/json"

    "fmt"

    "io"

    "net/http"

    "time"

    

    "agent/llm"

)


// RemoteProvider implements the Provider interface for cloud-based LLMs

type RemoteProvider struct {

    apiKey         string

    baseURL        string

    modelName      string

    client         *http.Client

    rateLimiter    *RateLimiter

    maxRetries     int

    retryDelay     time.Duration

}


// RemoteProviderConfig contains configuration for remote providers

type RemoteProviderConfig struct {

    APIKey          string

    BaseURL         string

    ModelName       string

    Timeout         time.Duration

    MaxRetries      int

    RetryDelay      time.Duration

    RequestsPerMin  int // Rate limiting

}


// RateLimiter implements token bucket rate limiting

type RateLimiter struct {

    tokens         int

    maxTokens      int

    refillRate     time.Duration

    lastRefill     time.Time

}


// NewRateLimiter creates a new rate limiter

func NewRateLimiter(requestsPerMin int) *RateLimiter {

    return &RateLimiter{

        tokens:     requestsPerMin,

        maxTokens:  requestsPerMin,

        refillRate: time.Minute / time.Duration(requestsPerMin),

        lastRefill: time.Now(),

    }

}


// Wait blocks until a token is available

func (rl *RateLimiter) Wait(ctx context.Context) error {

    for {

        now := time.Now()

        elapsed := now.Sub(rl.lastRefill)

        tokensToAdd := int(elapsed / rl.refillRate)

        

        if tokensToAdd > 0 {

            rl.tokens += tokensToAdd

            if rl.tokens > rl.maxTokens {

                rl.tokens = rl.maxTokens

            }

            rl.lastRefill = now

        }

        

        if rl.tokens > 0 {

            rl.tokens--

            return nil

        }

        

        waitTime := rl.refillRate - (elapsed % rl.refillRate)

        select {

        case <-ctx.Done():

            return ctx.Err()

        case <-time.After(waitTime):

            continue

        }

    }

}


// NewRemoteProvider creates a new remote LLM provider

func NewRemoteProvider(config RemoteProviderConfig) (*RemoteProvider, error) {

    if config.APIKey == "" {

        return nil, fmt.Errorf("API key is required")

    }

    

    if config.BaseURL == "" {

        return nil, fmt.Errorf("base URL is required")

    }

    

    if config.ModelName == "" {

        return nil, fmt.Errorf("model name is required")

    }

    

    if config.Timeout == 0 {

        config.Timeout = 180 * time.Second

    }

    

    if config.MaxRetries == 0 {

        config.MaxRetries = 3

    }

    

    if config.RetryDelay == 0 {

        config.RetryDelay = 5 * time.Second

    }

    

    if config.RequestsPerMin == 0 {

        config.RequestsPerMin = 60

    }

    

    return &RemoteProvider{

        apiKey:      config.APIKey,

        baseURL:     config.BaseURL,

        modelName:   config.ModelName,

        maxRetries:  config.MaxRetries,

        retryDelay:  config.RetryDelay,

        rateLimiter: NewRateLimiter(config.RequestsPerMin),

        client: &http.Client{

            Timeout: config.Timeout,

        },

    }, nil

}


// GenerateCompletion implements the Provider interface

func (p *RemoteProvider) GenerateCompletion(ctx context.Context, req llm.CompletionRequest) (*llm.CompletionResponse, error) {

    // Wait for rate limiter

    if err := p.rateLimiter.Wait(ctx); err != nil {

        return nil, fmt.Errorf("rate limiter error: %w", err)

    }

    

    // Build the API request

    apiRequest := map[string]interface{}{

        "model":    p.modelName,

        "messages": convertMessagesToAPI(req.Messages),

    }

    

    if req.MaxTokens > 0 {

        apiRequest["max_tokens"] = req.MaxTokens

    }

    

    if req.Temperature > 0 {

        apiRequest["temperature"] = req.Temperature

    }

    

    if req.TopP > 0 {

        apiRequest["top_p"] = req.TopP

    }

    

    if len(req.StopSequences) > 0 {

        apiRequest["stop"] = req.StopSequences

    }

    

    if req.PresencePenalty != 0 {

        apiRequest["presence_penalty"] = req.PresencePenalty

    }

    

    requestBody, err := json.Marshal(apiRequest)

    if err != nil {

        return nil, fmt.Errorf("failed to marshal request: %w", err)

    }

    

    // Execute with retry logic

    var lastErr error

    for attempt := 0; attempt <= p.maxRetries; attempt++ {

        if attempt > 0 {

            select {

            case <-ctx.Done():

                return nil, ctx.Err()

            case <-time.After(p.retryDelay * time.Duration(attempt)):

            }

        }

        

        response, err := p.executeRemoteRequest(ctx, requestBody)

        if err == nil {

            return response, nil

        }

        

        lastErr = err

    }

    

    return nil, fmt.Errorf("failed after %d attempts: %w", p.maxRetries+1, lastErr)

}


// executeRemoteRequest performs a single API request

func (p *RemoteProvider) executeRemoteRequest(ctx context.Context, requestBody []byte) (*llm.CompletionResponse, error) {

    endpoint := fmt.Sprintf("%s/v1/chat/completions", p.baseURL)

    

    httpReq, err := http.NewRequestWithContext(ctx, "POST", endpoint, bytes.NewReader(requestBody))

    if err != nil {

        return nil, fmt.Errorf("failed to create request: %w", err)

    }

    

    httpReq.Header.Set("Content-Type", "application/json")

    httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", p.apiKey))

    

    httpResp, err := p.client.Do(httpReq)

    if err != nil {

        return nil, fmt.Errorf("request failed: %w", err)

    }

    defer httpResp.Body.Close()

    

    body, err := io.ReadAll(httpResp.Body)

    if err != nil {

        return nil, fmt.Errorf("failed to read response: %w", err)

    }

    

    if httpResp.StatusCode != http.StatusOK {

        return nil, fmt.Errorf("API returned status %d: %s", httpResp.StatusCode, string(body))

    }

    

    var apiResponse struct {

        Choices []struct {

            Message struct {

                Content string `json:"content"`

            } `json:"message"`

            FinishReason string `json:"finish_reason"`

        } `json:"choices"`

        Usage struct {

            PromptTokens     int `json:"prompt_tokens"`

            CompletionTokens int `json:"completion_tokens"`

            TotalTokens      int `json:"total_tokens"`

        } `json:"usage"`

        Model string `json:"model"`

    }

    

    if err := json.Unmarshal(body, &apiResponse); err != nil {

        return nil, fmt.Errorf("failed to decode response: %w", err)

    }

    

    if len(apiResponse.Choices) == 0 {

        return nil, fmt.Errorf("no choices in response")

    }

    

    return &llm.CompletionResponse{

        Content:      apiResponse.Choices[0].Message.Content,

        FinishReason: apiResponse.Choices[0].FinishReason,

        TokensUsed:   apiResponse.Usage.TotalTokens,

        PromptTokens: apiResponse.Usage.PromptTokens,

        ModelUsed:    apiResponse.Model,

    }, nil

}


// convertMessagesToAPI transforms messages to API format

func convertMessagesToAPI(messages []llm.Message) []map[string]string {

    result := make([]map[string]string, len(messages))

    for i, msg := range messages {

        result[i] = map[string]string{

            "role":    msg.Role,

            "content": msg.Content,

        }

    }

    return result

}


// GetCapabilities returns provider capabilities

func (p *RemoteProvider) GetCapabilities() llm.ProviderCapabilities {

    return llm.ProviderCapabilities{

        SupportsStreaming:   true,

        MaxContextTokens:    128000, // Model-specific

        SupportedModalities: []string{"text"},

        RequiresAPIKey:      true,

        GPUAccelerated:      true, // Cloud providers use GPUs

    }

}


// HealthCheck verifies API connectivity

func (p *RemoteProvider) HealthCheck(ctx context.Context) error {

    // Simple request to verify credentials and connectivity

    testReq := llm.CompletionRequest{

        Messages: []llm.Message{

            {Role: "user", Content: "Hello"},

        },

        MaxTokens: 5,

    }

    

    _, err := p.GenerateCompletion(ctx, testReq)

    return err

}


// Close releases resources

func (p *RemoteProvider) Close() error {

    p.client.CloseIdleConnections()

    return nil

}


The RemoteProvider implementation includes sophisticated rate limiting using a token bucket algorithm. This prevents the application from exceeding API quotas and incurring additional costs or service disruptions. The exponential backoff retry strategy handles transient network issues gracefully.


DOMAIN MODEL FOR DOCKER AND KUBERNETES ARTIFACTS


The domain model represents the various artifacts that the agent generates. These structures capture the essential properties of Dockerfiles, Kubernetes manifests, and Helm charts while providing methods for validation and serialization.


// Package domain defines the core domain entities for Docker and Kubernetes artifacts

package domain


import (

    "fmt"

    "strings"

)


// Dockerfile represents a complete Dockerfile with all instructions

type Dockerfile struct {

    BaseImage       string              // FROM instruction

    Maintainer      string              // LABEL maintainer

    WorkDir         string              // WORKDIR instruction

    Environment     map[string]string   // ENV instructions

    CopyInstructions []CopyInstruction  // COPY instructions

    RunCommands     []string            // RUN instructions

    ExposePort      []int               // EXPOSE instructions

    EntryPoint      []string            // ENTRYPOINT instruction

    Command         []string            // CMD instruction

    Volumes         []string            // VOLUME instructions

    User            string              // USER instruction

    Labels          map[string]string   // Additional LABEL instructions

    BuildArgs       map[string]string   // ARG instructions

    HealthCheck     *HealthCheck        // HEALTHCHECK instruction

}


// CopyInstruction represents a COPY or ADD instruction

type CopyInstruction struct {

    Source      string // Source path

    Destination string // Destination path

    Chown       string // Optional ownership specification

}


// HealthCheck represents a HEALTHCHECK instruction

type HealthCheck struct {

    Command     []string      // The command to run

    Interval    string        // How often to check

    Timeout     string        // How long to wait

    StartPeriod string        // Grace period

    Retries     int           // Number of retries

}


// Validate checks if the Dockerfile is valid

func (d *Dockerfile) Validate() error {

    if d.BaseImage == "" {

        return fmt.Errorf("base image is required")

    }

    

    if len(d.EntryPoint) == 0 && len(d.Command) == 0 {

        return fmt.Errorf("either ENTRYPOINT or CMD must be specified")

    }

    

    return nil

}


// ToDockerfileContent generates the actual Dockerfile content

func (d *Dockerfile) ToDockerfileContent() string {

    var builder strings.Builder

    

    // FROM instruction

    builder.WriteString(fmt.Sprintf("FROM %s\n\n", d.BaseImage))

    

    // Maintainer label

    if d.Maintainer != "" {

        builder.WriteString(fmt.Sprintf("LABEL maintainer=\"%s\"\n\n", d.Maintainer))

    }

    

    // Additional labels

    if len(d.Labels) > 0 {

        for key, value := range d.Labels {

            builder.WriteString(fmt.Sprintf("LABEL %s=\"%s\"\n", key, value))

        }

        builder.WriteString("\n")

    }

    

    // Build arguments

    if len(d.BuildArgs) > 0 {

        for key, value := range d.BuildArgs {

            builder.WriteString(fmt.Sprintf("ARG %s=%s\n", key, value))

        }

        builder.WriteString("\n")

    }

    

    // Environment variables

    if len(d.Environment) > 0 {

        for key, value := range d.Environment {

            builder.WriteString(fmt.Sprintf("ENV %s=%s\n", key, value))

        }

        builder.WriteString("\n")

    }

    

    // Working directory

    if d.WorkDir != "" {

        builder.WriteString(fmt.Sprintf("WORKDIR %s\n\n", d.WorkDir))

    }

    

    // COPY instructions

    for _, copy := range d.CopyInstructions {

        if copy.Chown != "" {

            builder.WriteString(fmt.Sprintf("COPY --chown=%s %s %s\n", copy.Chown, copy.Source, copy.Destination))

        } else {

            builder.WriteString(fmt.Sprintf("COPY %s %s\n", copy.Source, copy.Destination))

        }

    }

    if len(d.CopyInstructions) > 0 {

        builder.WriteString("\n")

    }

    

    // RUN commands

    for _, cmd := range d.RunCommands {

        builder.WriteString(fmt.Sprintf("RUN %s\n", cmd))

    }

    if len(d.RunCommands) > 0 {

        builder.WriteString("\n")

    }

    

    // Volumes

    for _, vol := range d.Volumes {

        builder.WriteString(fmt.Sprintf("VOLUME %s\n", vol))

    }

    if len(d.Volumes) > 0 {

        builder.WriteString("\n")

    }

    

    // Expose ports

    for _, port := range d.ExposePort {

        builder.WriteString(fmt.Sprintf("EXPOSE %d\n", port))

    }

    if len(d.ExposePort) > 0 {

        builder.WriteString("\n")

    }

    

    // User

    if d.User != "" {

        builder.WriteString(fmt.Sprintf("USER %s\n\n", d.User))

    }

    

    // Health check

    if d.HealthCheck != nil {

        builder.WriteString("HEALTHCHECK ")

        if d.HealthCheck.Interval != "" {

            builder.WriteString(fmt.Sprintf("--interval=%s ", d.HealthCheck.Interval))

        }

        if d.HealthCheck.Timeout != "" {

            builder.WriteString(fmt.Sprintf("--timeout=%s ", d.HealthCheck.Timeout))

        }

        if d.HealthCheck.StartPeriod != "" {

            builder.WriteString(fmt.Sprintf("--start-period=%s ", d.HealthCheck.StartPeriod))

        }

        if d.HealthCheck.Retries > 0 {

            builder.WriteString(fmt.Sprintf("--retries=%d ", d.HealthCheck.Retries))

        }

        builder.WriteString(fmt.Sprintf("CMD %s\n\n", strings.Join(d.HealthCheck.Command, " ")))

    }

    

    // Entrypoint

    if len(d.EntryPoint) > 0 {

        builder.WriteString(fmt.Sprintf("ENTRYPOINT [\"%s\"]\n", strings.Join(d.EntryPoint, "\", \"")))

    }

    

    // Command

    if len(d.Command) > 0 {

        builder.WriteString(fmt.Sprintf("CMD [\"%s\"]\n", strings.Join(d.Command, "\", \"")))

    }

    

    return builder.String()

}


// KubernetesDeployment represents a Kubernetes Deployment manifest

type KubernetesDeployment struct {

    APIVersion string                 // API version

    Kind       string                 // Resource kind

    Metadata   ObjectMeta             // Metadata

    Spec       DeploymentSpec         // Deployment specification

}


// ObjectMeta represents Kubernetes object metadata

type ObjectMeta struct {

    Name        string            // Object name

    Namespace   string            // Namespace

    Labels      map[string]string // Labels

    Annotations map[string]string // Annotations

}


// DeploymentSpec represents the deployment specification

type DeploymentSpec struct {

    Replicas int32                  // Number of replicas

    Selector *LabelSelector         // Label selector

    Template PodTemplateSpec        // Pod template

    Strategy DeploymentStrategy     // Update strategy

}


// LabelSelector represents a label selector

type LabelSelector struct {

    MatchLabels map[string]string // Labels to match

}


// PodTemplateSpec represents a pod template

type PodTemplateSpec struct {

    Metadata ObjectMeta  // Pod metadata

    Spec     PodSpec     // Pod specification

}


// PodSpec represents a pod specification

type PodSpec struct {

    Containers       []Container       // Containers

    InitContainers   []Container       // Init containers

    Volumes          []Volume          // Volumes

    ServiceAccount   string            // Service account name

    SecurityContext  *PodSecurityContext // Security context

    RestartPolicy    string            // Restart policy

}


// Container represents a container specification

type Container struct {

    Name            string              // Container name

    Image           string              // Container image

    ImagePullPolicy string              // Image pull policy

    Command         []string            // Entrypoint

    Args            []string            // Arguments

    Ports           []ContainerPort     // Exposed ports

    Env             []EnvVar            // Environment variables

    VolumeMounts    []VolumeMount       // Volume mounts

    Resources       ResourceRequirements // Resource requirements

    LivenessProbe   *Probe              // Liveness probe

    ReadinessProbe  *Probe              // Readiness probe

    SecurityContext *SecurityContext    // Security context

}


// ContainerPort represents a container port

type ContainerPort struct {

    Name          string // Port name

    ContainerPort int32  // Port number

    Protocol      string // Protocol (TCP/UDP)

}


// EnvVar represents an environment variable

type EnvVar struct {

    Name      string        // Variable name

    Value     string        // Variable value

    ValueFrom *EnvVarSource // Source for the value

}


// EnvVarSource represents a source for environment variable value

type EnvVarSource struct {

    ConfigMapKeyRef *ConfigMapKeySelector // ConfigMap reference

    SecretKeyRef    *SecretKeySelector    // Secret reference

    FieldRef        *FieldSelector        // Field reference

}


// ConfigMapKeySelector selects a key from a ConfigMap

type ConfigMapKeySelector struct {

    Name string // ConfigMap name

    Key  string // Key name

}


// SecretKeySelector selects a key from a Secret

type SecretKeySelector struct {

    Name string // Secret name

    Key  string // Key name

}


// FieldSelector selects a field from the pod

type FieldSelector struct {

    FieldPath string // Field path

}


// VolumeMount represents a volume mount

type VolumeMount struct {

    Name      string // Volume name

    MountPath string // Mount path

    ReadOnly  bool   // Read-only flag

    SubPath   string // Sub path

}


// ResourceRequirements represents resource requirements

type ResourceRequirements struct {

    Limits   map[string]string // Resource limits

    Requests map[string]string // Resource requests

}


// Probe represents a health probe

type Probe struct {

    HTTPGet             *HTTPGetAction // HTTP GET probe

    TCPSocket           *TCPSocketAction // TCP socket probe

    Exec                *ExecAction    // Exec probe

    InitialDelaySeconds int32          // Initial delay

    PeriodSeconds       int32          // Period

    TimeoutSeconds      int32          // Timeout

    SuccessThreshold    int32          // Success threshold

    FailureThreshold    int32          // Failure threshold

}


// HTTPGetAction represents an HTTP GET probe

type HTTPGetAction struct {

    Path   string            // URL path

    Port   int32             // Port number

    Scheme string            // Scheme (HTTP/HTTPS)

    Headers map[string]string // HTTP headers

}


// TCPSocketAction represents a TCP socket probe

type TCPSocketAction struct {

    Port int32 // Port number

}


// ExecAction represents an exec probe

type ExecAction struct {

    Command []string // Command to execute

}


// SecurityContext represents container security context

type SecurityContext struct {

    RunAsUser    *int64 // User ID

    RunAsGroup   *int64 // Group ID

    RunAsNonRoot *bool  // Run as non-root flag

    ReadOnlyRootFilesystem *bool // Read-only root filesystem

    Capabilities *Capabilities // Linux capabilities

}


// Capabilities represents Linux capabilities

type Capabilities struct {

    Add  []string // Capabilities to add

    Drop []string // Capabilities to drop

}


// PodSecurityContext represents pod-level security context

type PodSecurityContext struct {

    RunAsUser    *int64 // User ID

    RunAsGroup   *int64 // Group ID

    FSGroup      *int64 // Filesystem group

    RunAsNonRoot *bool  // Run as non-root flag

}


// Volume represents a volume

type Volume struct {

    Name         string              // Volume name

    ConfigMap    *ConfigMapVolume    // ConfigMap volume

    Secret       *SecretVolume       // Secret volume

    EmptyDir     *EmptyDirVolume     // EmptyDir volume

    PersistentVolumeClaim *PVCVolume // PVC volume

}


// ConfigMapVolume represents a ConfigMap volume

type ConfigMapVolume struct {

    Name string // ConfigMap name

}


// SecretVolume represents a Secret volume

type SecretVolume struct {

    SecretName string // Secret name

}


// EmptyDirVolume represents an EmptyDir volume

type EmptyDirVolume struct {

    Medium string // Storage medium

}


// PVCVolume represents a PersistentVolumeClaim volume

type PVCVolume struct {

    ClaimName string // PVC name

}


// DeploymentStrategy represents deployment strategy

type DeploymentStrategy struct {

    Type          string                 // Strategy type

    RollingUpdate *RollingUpdateStrategy // Rolling update parameters

}


// RollingUpdateStrategy represents rolling update parameters

type RollingUpdateStrategy struct {

    MaxUnavailable string // Max unavailable

    MaxSurge       string // Max surge

}


This comprehensive domain model captures the complexity of Kubernetes resources while maintaining type safety and validation capabilities. The structures mirror the actual Kubernetes API objects, ensuring that generated manifests conform to the expected schema.


ARTIFACT GENERATOR SERVICE


The artifact generator service orchestrates the interaction between the LLM provider and the domain model. It translates user requests into structured prompts, parses LLM responses into domain objects, and validates the generated artifacts.


// Package generator provides services for generating Docker and Kubernetes artifacts

package generator


import (

    "context"

    "encoding/json"

    "fmt"

    "strings"

    

    "agent/domain"

    "agent/llm"

)


// ArtifactGenerator generates Docker and Kubernetes artifacts using an LLM

type ArtifactGenerator struct {

    provider        llm.Provider

    systemPrompt    string

    conversationCtx *ConversationContext

}


// ConversationContext maintains the conversation history

type ConversationContext struct {

    Messages          []llm.Message

    GeneratedArtifacts map[string]interface{} // Artifacts generated in this session

}


// NewArtifactGenerator creates a new artifact generator

func NewArtifactGenerator(provider llm.Provider) *ArtifactGenerator {

    systemPrompt := `You are an expert in Docker and Kubernetes. Your task is to generate production-ready Docker and Kubernetes artifacts based on user requirements.


When generating Dockerfiles:

- Use multi-stage builds when appropriate

- Follow security best practices (non-root user, minimal base images)

- Optimize for layer caching

- Include health checks

- Use specific version tags, not 'latest'


When generating Kubernetes manifests:

- Include resource limits and requests

- Configure appropriate health probes

- Use security contexts

- Follow the principle of least privilege

- Include labels for organization


When generating Helm charts:

- Create well-structured templates

- Use values.yaml for configuration

- Include helpful comments

- Follow Helm best practices


Always respond with valid JSON containing the artifact structure. Use the following format:

{

  "artifact_type": "dockerfile|deployment|service|configmap|secret|helmchart",

  "content": { ... artifact structure ... }

}


Be precise, follow best practices, and ensure all generated artifacts are production-ready.`


    return &ArtifactGenerator{

        provider:     provider,

        systemPrompt: systemPrompt,

        conversationCtx: &ConversationContext{

            Messages: []llm.Message{

                {

                    Role:    "system",

                    Content: systemPrompt,

                },

            },

            GeneratedArtifacts: make(map[string]interface{}),

        },

    }

}


// GenerateDockerfile generates a Dockerfile based on user requirements

func (g *ArtifactGenerator) GenerateDockerfile(ctx context.Context, requirements string) (*domain.Dockerfile, error) {

    // Add user message to conversation

    userMessage := llm.Message{

        Role:    "user",

        Content: fmt.Sprintf("Generate a Dockerfile with the following requirements: %s", requirements),

    }

    

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, userMessage)

    

    // Request completion from LLM

    request := llm.CompletionRequest{

        Messages:    g.conversationCtx.Messages,

        MaxTokens:   2000,

        Temperature: 0.3, // Lower temperature for more deterministic output

        TopP:        0.9,

    }

    

    response, err := g.provider.GenerateCompletion(ctx, request)

    if err != nil {

        return nil, fmt.Errorf("failed to generate completion: %w", err)

    }

    

    // Add assistant response to conversation

    assistantMessage := llm.Message{

        Role:    "assistant",

        Content: response.Content,

    }

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, assistantMessage)

    

    // Parse the response

    dockerfile, err := g.parseDockerfileResponse(response.Content)

    if err != nil {

        return nil, fmt.Errorf("failed to parse Dockerfile response: %w", err)

    }

    

    // Validate the generated Dockerfile

    if err := dockerfile.Validate(); err != nil {

        return nil, fmt.Errorf("generated Dockerfile is invalid: %w", err)

    }

    

    // Store in conversation context

    g.conversationCtx.GeneratedArtifacts["dockerfile"] = dockerfile

    

    return dockerfile, nil

}


// parseDockerfileResponse parses the LLM response into a Dockerfile structure

func (g *ArtifactGenerator) parseDockerfileResponse(content string) (*domain.Dockerfile, error) {

    // Extract JSON from the response

    jsonContent := extractJSON(content)

    if jsonContent == "" {

        return nil, fmt.Errorf("no JSON found in response")

    }

    

    var response struct {

        ArtifactType string `json:"artifact_type"`

        Content      struct {

            BaseImage        string              `json:"base_image"`

            Maintainer       string              `json:"maintainer"`

            WorkDir          string              `json:"workdir"`

            Environment      map[string]string   `json:"environment"`

            CopyInstructions []struct {

                Source      string `json:"source"`

                Destination string `json:"destination"`

                Chown       string `json:"chown"`

            } `json:"copy_instructions"`

            RunCommands  []string          `json:"run_commands"`

            ExposePort   []int             `json:"expose_ports"`

            EntryPoint   []string          `json:"entrypoint"`

            Command      []string          `json:"command"`

            Volumes      []string          `json:"volumes"`

            User         string            `json:"user"`

            Labels       map[string]string `json:"labels"`

            BuildArgs    map[string]string `json:"build_args"`

            HealthCheck  *struct {

                Command     []string `json:"command"`

                Interval    string   `json:"interval"`

                Timeout     string   `json:"timeout"`

                StartPeriod string   `json:"start_period"`

                Retries     int      `json:"retries"`

            } `json:"healthcheck"`

        } `json:"content"`

    }

    

    if err := json.Unmarshal([]byte(jsonContent), &response); err != nil {

        return nil, fmt.Errorf("failed to unmarshal JSON: %w", err)

    }

    

    if response.ArtifactType != "dockerfile" {

        return nil, fmt.Errorf("expected dockerfile artifact, got %s", response.ArtifactType)

    }

    

    // Convert to domain model

    dockerfile := &domain.Dockerfile{

        BaseImage:   response.Content.BaseImage,

        Maintainer:  response.Content.Maintainer,

        WorkDir:     response.Content.WorkDir,

        Environment: response.Content.Environment,

        RunCommands: response.Content.RunCommands,

        ExposePort:  response.Content.ExposePort,

        EntryPoint:  response.Content.EntryPoint,

        Command:     response.Content.Command,

        Volumes:     response.Content.Volumes,

        User:        response.Content.User,

        Labels:      response.Content.Labels,

        BuildArgs:   response.Content.BuildArgs,

    }

    

    // Convert copy instructions

    for _, ci := range response.Content.CopyInstructions {

        dockerfile.CopyInstructions = append(dockerfile.CopyInstructions, domain.CopyInstruction{

            Source:      ci.Source,

            Destination: ci.Destination,

            Chown:       ci.Chown,

        })

    }

    

    // Convert health check

    if response.Content.HealthCheck != nil {

        dockerfile.HealthCheck = &domain.HealthCheck{

            Command:     response.Content.HealthCheck.Command,

            Interval:    response.Content.HealthCheck.Interval,

            Timeout:     response.Content.HealthCheck.Timeout,

            StartPeriod: response.Content.HealthCheck.StartPeriod,

            Retries:     response.Content.HealthCheck.Retries,

        }

    }

    

    return dockerfile, nil

}


// extractJSON extracts JSON content from a string that may contain other text

func extractJSON(content string) string {

    // Find the first '{' and last '}'

    start := strings.Index(content, "{")

    end := strings.LastIndex(content, "}")

    

    if start == -1 || end == -1 || start >= end {

        return ""

    }

    

    return content[start : end+1]

}


// GenerateDeployment generates a Kubernetes Deployment manifest

func (g *ArtifactGenerator) GenerateDeployment(ctx context.Context, requirements string) (*domain.KubernetesDeployment, error) {

    userMessage := llm.Message{

        Role:    "user",

        Content: fmt.Sprintf("Generate a Kubernetes Deployment manifest with the following requirements: %s", requirements),

    }

    

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, userMessage)

    

    request := llm.CompletionRequest{

        Messages:    g.conversationCtx.Messages,

        MaxTokens:   3000,

        Temperature: 0.3,

        TopP:        0.9,

    }

    

    response, err := g.provider.GenerateCompletion(ctx, request)

    if err != nil {

        return nil, fmt.Errorf("failed to generate completion: %w", err)

    }

    

    assistantMessage := llm.Message{

        Role:    "assistant",

        Content: response.Content,

    }

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, assistantMessage)

    

    deployment, err := g.parseDeploymentResponse(response.Content)

    if err != nil {

        return nil, fmt.Errorf("failed to parse Deployment response: %w", err)

    }

    

    g.conversationCtx.GeneratedArtifacts["deployment"] = deployment

    

    return deployment, nil

}


// parseDeploymentResponse parses the LLM response into a Deployment structure

func (g *ArtifactGenerator) parseDeploymentResponse(content string) (*domain.KubernetesDeployment, error) {

    jsonContent := extractJSON(content)

    if jsonContent == "" {

        return nil, fmt.Errorf("no JSON found in response")

    }

    

    var response struct {

        ArtifactType string                      `json:"artifact_type"`

        Content      domain.KubernetesDeployment `json:"content"`

    }

    

    if err := json.Unmarshal([]byte(jsonContent), &response); err != nil {

        return nil, fmt.Errorf("failed to unmarshal JSON: %w", err)

    }

    

    if response.ArtifactType != "deployment" {

        return nil, fmt.Errorf("expected deployment artifact, got %s", response.ArtifactType)

    }

    

    return &response.Content, nil

}


// RefineArtifact refines a previously generated artifact based on feedback

func (g *ArtifactGenerator) RefineArtifact(ctx context.Context, artifactType, feedback string) (interface{}, error) {

    userMessage := llm.Message{

        Role:    "user",

        Content: fmt.Sprintf("Please refine the %s based on this feedback: %s", artifactType, feedback),

    }

    

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, userMessage)

    

    request := llm.CompletionRequest{

        Messages:    g.conversationCtx.Messages,

        MaxTokens:   3000,

        Temperature: 0.3,

        TopP:        0.9,

    }

    

    response, err := g.provider.GenerateCompletion(ctx, request)

    if err != nil {

        return nil, fmt.Errorf("failed to generate completion: %w", err)

    }

    

    assistantMessage := llm.Message{

        Role:    "assistant",

        Content: response.Content,

    }

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, assistantMessage)

    

    // Parse based on artifact type

    switch artifactType {

    case "dockerfile":

        return g.parseDockerfileResponse(response.Content)

    case "deployment":

        return g.parseDeploymentResponse(response.Content)

    default:

        return nil, fmt.Errorf("unsupported artifact type: %s", artifactType)

    }

}


The ArtifactGenerator service demonstrates the power of maintaining conversational context. Each interaction builds upon previous exchanges, allowing the LLM to understand references and make coherent refinements. The JSON-based response format ensures structured output that can be reliably parsed into domain objects.


HELM CHART GENERATION


Helm charts package Kubernetes applications into reusable, configurable units. The agent must generate not only the template files but also the values file, Chart metadata, and helper templates.


// Package helm provides functionality for generating Helm charts

package helm


import (

    "context"

    "encoding/json"

    "fmt"

    "strings"

    

    "agent/llm"

)


// HelmChart represents a complete Helm chart structure

type HelmChart struct {

    ChartMetadata ChartMetadata         // Chart.yaml content

    Values        map[string]interface{} // values.yaml content

    Templates     map[string]string      // Template files

    Helpers       string                 // _helpers.tpl content

}


// ChartMetadata represents Chart.yaml

type ChartMetadata struct {

    APIVersion  string            `yaml:"apiVersion"`

    Name        string            `yaml:"name"`

    Version     string            `yaml:"version"`

    AppVersion  string            `yaml:"appVersion"`

    Description string            `yaml:"description"`

    Keywords    []string          `yaml:"keywords"`

    Maintainers []Maintainer      `yaml:"maintainers"`

    Dependencies []Dependency     `yaml:"dependencies"`

    Annotations map[string]string `yaml:"annotations"`

}


// Maintainer represents a chart maintainer

type Maintainer struct {

    Name  string `yaml:"name"`

    Email string `yaml:"email"`

}


// Dependency represents a chart dependency

type Dependency struct {

    Name       string `yaml:"name"`

    Version    string `yaml:"version"`

    Repository string `yaml:"repository"`

    Condition  string `yaml:"condition,omitempty"`

}


// HelmGenerator generates Helm charts using an LLM

type HelmGenerator struct {

    provider     llm.Provider

    systemPrompt string

}


// NewHelmGenerator creates a new Helm chart generator

func NewHelmGenerator(provider llm.Provider) *HelmGenerator {

    systemPrompt := `You are an expert in Helm chart development. Generate production-ready Helm charts following these principles:


1. Use semantic versioning for chart and app versions

2. Provide comprehensive values.yaml with sensible defaults

3. Include helper templates for common patterns

4. Use proper templating with conditionals and loops

5. Include NOTES.txt for post-installation instructions

6. Follow Helm best practices for naming and organization

7. Add comments explaining configuration options

8. Support common deployment scenarios through values


Always respond with valid JSON containing the complete chart structure:

{

  "chart_metadata": { ... Chart.yaml content ... },

  "values": { ... values.yaml content ... },

  "templates": {

    "deployment.yaml": "...",

    "service.yaml": "...",

    ...

  },

  "helpers": "... _helpers.tpl content ..."

}`


    return &HelmGenerator{

        provider:     provider,

        systemPrompt: systemPrompt,

    }

}


// GenerateChart generates a complete Helm chart based on requirements

func (g *HelmGenerator) GenerateChart(ctx context.Context, requirements string) (*HelmChart, error) {

    messages := []llm.Message{

        {

            Role:    "system",

            Content: g.systemPrompt,

        },

        {

            Role:    "user",

            Content: fmt.Sprintf("Generate a Helm chart with the following requirements: %s", requirements),

        },

    }

    

    request := llm.CompletionRequest{

        Messages:    messages,

        MaxTokens:   4000,

        Temperature: 0.3,

        TopP:        0.9,

    }

    

    response, err := g.provider.GenerateCompletion(ctx, request)

    if err != nil {

        return nil, fmt.Errorf("failed to generate completion: %w", err)

    }

    

    chart, err := g.parseChartResponse(response.Content)

    if err != nil {

        return nil, fmt.Errorf("failed to parse chart response: %w", err)

    }

    

    return chart, nil

}


// parseChartResponse parses the LLM response into a HelmChart structure

func (g *HelmGenerator) parseChartResponse(content string) (*HelmChart, error) {

    jsonContent := extractJSON(content)

    if jsonContent == "" {

        return nil, fmt.Errorf("no JSON found in response")

    }

    

    var response struct {

        ChartMetadata ChartMetadata         `json:"chart_metadata"`

        Values        map[string]interface{} `json:"values"`

        Templates     map[string]string      `json:"templates"`

        Helpers       string                 `json:"helpers"`

    }

    

    if err := json.Unmarshal([]byte(jsonContent), &response); err != nil {

        return nil, fmt.Errorf("failed to unmarshal JSON: %w", err)

    }

    

    return &HelmChart{

        ChartMetadata: response.ChartMetadata,

        Values:        response.Values,

        Templates:     response.Templates,

        Helpers:       response.Helpers,

    }, nil

}


// extractJSON extracts JSON from response content

func extractJSON(content string) string {

    start := strings.Index(content, "{")

    end := strings.LastIndex(content, "}")

    

    if start == -1 || end == -1 || start >= end {

        return ""

    }

    

    return content[start : end+1]

}


// ValidateChart performs basic validation on a Helm chart

func (g *HelmGenerator) ValidateChart(chart *HelmChart) error {

    if chart.ChartMetadata.Name == "" {

        return fmt.Errorf("chart name is required")

    }

    

    if chart.ChartMetadata.Version == "" {

        return fmt.Errorf("chart version is required")

    }

    

    if len(chart.Templates) == 0 {

        return fmt.Errorf("chart must contain at least one template")

    }

    

    // Check for required templates

    requiredTemplates := []string{"deployment.yaml", "service.yaml"}

    for _, tmpl := range requiredTemplates {

        if _, exists := chart.Templates[tmpl]; !exists {

            return fmt.Errorf("missing required template: %s", tmpl)

        }

    }

    

    return nil

}


The Helm generator creates complete, deployable charts with all necessary components. The structured approach ensures that generated charts follow Helm conventions and can be immediately used in production environments.


FILE SYSTEM OPERATIONS AND ARTIFACT PERSISTENCE


Generated artifacts must be persisted to the file system in the correct structure. This includes creating directory hierarchies for Helm charts and ensuring proper file permissions.


// Package filesystem provides utilities for persisting artifacts to disk

package filesystem


import (

    "fmt"

    "os"

    "path/filepath"

    

    "agent/domain"

    "agent/helm"

    "gopkg.in/yaml.v3"

)


// ArtifactWriter handles writing artifacts to the filesystem

type ArtifactWriter struct {

    baseDir string

}


// NewArtifactWriter creates a new artifact writer

func NewArtifactWriter(baseDir string) (*ArtifactWriter, error) {

    // Ensure base directory exists

    if err := os.MkdirAll(baseDir, 0755); err != nil {

        return nil, fmt.Errorf("failed to create base directory: %w", err)

    }

    

    return &ArtifactWriter{

        baseDir: baseDir,

    }, nil

}


// WriteDockerfile writes a Dockerfile to the filesystem

func (w *ArtifactWriter) WriteDockerfile(dockerfile *domain.Dockerfile, projectName string) error {

    projectDir := filepath.Join(w.baseDir, projectName)

    if err := os.MkdirAll(projectDir, 0755); err != nil {

        return fmt.Errorf("failed to create project directory: %w", err)

    }

    

    dockerfilePath := filepath.Join(projectDir, "Dockerfile")

    content := dockerfile.ToDockerfileContent()

    

    if err := os.WriteFile(dockerfilePath, []byte(content), 0644); err != nil {

        return fmt.Errorf("failed to write Dockerfile: %w", err)

    }

    

    return nil

}


// WriteKubernetesManifest writes a Kubernetes manifest to the filesystem

func (w *ArtifactWriter) WriteKubernetesManifest(manifest interface{}, projectName, filename string) error {

    manifestDir := filepath.Join(w.baseDir, projectName, "k8s")

    if err := os.MkdirAll(manifestDir, 0755); err != nil {

        return fmt.Errorf("failed to create manifest directory: %w", err)

    }

    

    manifestPath := filepath.Join(manifestDir, filename)

    

    yamlContent, err := yaml.Marshal(manifest)

    if err != nil {

        return fmt.Errorf("failed to marshal manifest to YAML: %w", err)

    }

    

    if err := os.WriteFile(manifestPath, yamlContent, 0644); err != nil {

        return fmt.Errorf("failed to write manifest: %w", err)

    }

    

    return nil

}


// WriteHelmChart writes a complete Helm chart to the filesystem

func (w *ArtifactWriter) WriteHelmChart(chart *helm.HelmChart, chartName string) error {

    chartDir := filepath.Join(w.baseDir, chartName)

    

    // Create chart directory structure

    dirs := []string{

        chartDir,

        filepath.Join(chartDir, "templates"),

        filepath.Join(chartDir, "charts"),

    }

    

    for _, dir := range dirs {

        if err := os.MkdirAll(dir, 0755); err != nil {

            return fmt.Errorf("failed to create directory %s: %w", dir, err)

        }

    }

    

    // Write Chart.yaml

    chartYAMLPath := filepath.Join(chartDir, "Chart.yaml")

    chartYAML, err := yaml.Marshal(chart.ChartMetadata)

    if err != nil {

        return fmt.Errorf("failed to marshal Chart.yaml: %w", err)

    }

    if err := os.WriteFile(chartYAMLPath, chartYAML, 0644); err != nil {

        return fmt.Errorf("failed to write Chart.yaml: %w", err)

    }

    

    // Write values.yaml

    valuesYAMLPath := filepath.Join(chartDir, "values.yaml")

    valuesYAML, err := yaml.Marshal(chart.Values)

    if err != nil {

        return fmt.Errorf("failed to marshal values.yaml: %w", err)

    }

    if err := os.WriteFile(valuesYAMLPath, valuesYAML, 0644); err != nil {

        return fmt.Errorf("failed to write values.yaml: %w", err)

    }

    

    // Write template files

    for filename, content := range chart.Templates {

        templatePath := filepath.Join(chartDir, "templates", filename)

        if err := os.WriteFile(templatePath, []byte(content), 0644); err != nil {

            return fmt.Errorf("failed to write template %s: %w", filename, err)

        }

    }

    

    // Write helpers

    if chart.Helpers != "" {

        helpersPath := filepath.Join(chartDir, "templates", "_helpers.tpl")

        if err := os.WriteFile(helpersPath, []byte(chart.Helpers), 0644); err != nil {

            return fmt.Errorf("failed to write _helpers.tpl: %w", err)

        }

    }

    

    return nil

}


// CreateProjectStructure creates a complete project structure

func (w *ArtifactWriter) CreateProjectStructure(projectName string) error {

    dirs := []string{

        filepath.Join(w.baseDir, projectName),

        filepath.Join(w.baseDir, projectName, "k8s"),

        filepath.Join(w.baseDir, projectName, "helm"),

        filepath.Join(w.baseDir, projectName, "configs"),

    }

    

    for _, dir := range dirs {

        if err := os.MkdirAll(dir, 0755); err != nil {

            return fmt.Errorf("failed to create directory %s: %w", dir, err)

        }

    }

    

    return nil

}


The filesystem operations maintain a clean project structure that follows industry conventions. Helm charts are placed in their own directories with the standard layout, while Kubernetes manifests are organized in a separate folder.


COMMAND LINE INTERFACE


The command-line interface provides the primary interaction mechanism for users. It must support various commands for generating different artifact types and managing the conversation context.


// Package cli provides the command-line interface for the agent

package cli


import (

    "context"

    "fmt"

    "os"

    "strings"

    

    "agent/filesystem"

    "agent/generator"

    "agent/helm"

    "agent/llm"

    "agent/locallm"

    "agent/remotellm"

)


// CLI represents the command-line interface

type CLI struct {

    generator      *generator.ArtifactGenerator

    helmGenerator  *helm.HelmGenerator

    writer         *filesystem.ArtifactWriter

    provider       llm.Provider

}


// Config contains CLI configuration

type Config struct {

    ProviderType   string // "local" or "remote"

    LocalURL       string

    LocalModel     string

    RemoteAPIKey   string

    RemoteURL      string

    RemoteModel    string

    OutputDir      string

}


// NewCLI creates a new CLI instance

func NewCLI(config Config) (*CLI, error) {

    var provider llm.Provider

    var err error

    

    // Initialize the appropriate provider

    switch config.ProviderType {

    case "local":

        provider, err = locallm.NewLocalProvider(locallm.LocalProviderConfig{

            BaseURL:    config.LocalURL,

            ModelName:  config.LocalModel,

            MaxRetries: 3,

        })

    case "remote":

        provider, err = remotellm.NewRemoteProvider(remotellm.RemoteProviderConfig{

            APIKey:         config.RemoteAPIKey,

            BaseURL:        config.RemoteURL,

            ModelName:      config.RemoteModel,

            MaxRetries:     3,

            RequestsPerMin: 60,

        })

    default:

        return nil, fmt.Errorf("unsupported provider type: %s", config.ProviderType)

    }

    

    if err != nil {

        return nil, fmt.Errorf("failed to initialize provider: %w", err)

    }

    

    // Verify provider health

    ctx := context.Background()

    if err := provider.HealthCheck(ctx); err != nil {

        return nil, fmt.Errorf("provider health check failed: %w", err)

    }

    

    writer, err := filesystem.NewArtifactWriter(config.OutputDir)

    if err != nil {

        return nil, fmt.Errorf("failed to initialize artifact writer: %w", err)

    }

    

    return &CLI{

        generator:     generator.NewArtifactGenerator(provider),

        helmGenerator: helm.NewHelmGenerator(provider),

        writer:        writer,

        provider:      provider,

    }, nil

}


// Run executes the CLI with the given arguments

func (c *CLI) Run(args []string) error {

    if len(args) < 2 {

        return c.printUsage()

    }

    

    command := args[1]

    ctx := context.Background()

    

    switch command {

    case "dockerfile":

        return c.handleDockerfile(ctx, args[2:])

    case "deployment":

        return c.handleDeployment(ctx, args[2:])

    case "helm":

        return c.handleHelm(ctx, args[2:])

    case "refine":

        return c.handleRefine(ctx, args[2:])

    default:

        return fmt.Errorf("unknown command: %s", command)

    }

}


// handleDockerfile handles Dockerfile generation

func (c *CLI) handleDockerfile(ctx context.Context, args []string) error {

    if len(args) < 2 {

        return fmt.Errorf("usage: dockerfile <project-name> <requirements>")

    }

    

    projectName := args[0]

    requirements := strings.Join(args[1:], " ")

    

    fmt.Printf("Generating Dockerfile for project '%s'...\n", projectName)

    

    dockerfile, err := c.generator.GenerateDockerfile(ctx, requirements)

    if err != nil {

        return fmt.Errorf("failed to generate Dockerfile: %w", err)

    }

    

    if err := c.writer.WriteDockerfile(dockerfile, projectName); err != nil {

        return fmt.Errorf("failed to write Dockerfile: %w", err)

    }

    

    fmt.Printf("Dockerfile generated successfully in %s/Dockerfile\n", projectName)

    fmt.Println("\nGenerated Dockerfile:")

    fmt.Println(dockerfile.ToDockerfileContent())

    

    return nil

}


// handleDeployment handles Kubernetes Deployment generation

func (c *CLI) handleDeployment(ctx context.Context, args []string) error {

    if len(args) < 2 {

        return fmt.Errorf("usage: deployment <project-name> <requirements>")

    }

    

    projectName := args[0]

    requirements := strings.Join(args[1:], " ")

    

    fmt.Printf("Generating Kubernetes Deployment for project '%s'...\n", projectName)

    

    deployment, err := c.generator.GenerateDeployment(ctx, requirements)

    if err != nil {

        return fmt.Errorf("failed to generate Deployment: %w", err)

    }

    

    if err := c.writer.WriteKubernetesManifest(deployment, projectName, "deployment.yaml"); err != nil {

        return fmt.Errorf("failed to write Deployment: %w", err)

    }

    

    fmt.Printf("Deployment manifest generated successfully in %s/k8s/deployment.yaml\n", projectName)

    

    return nil

}


// handleHelm handles Helm chart generation

func (c *CLI) handleHelm(ctx context.Context, args []string) error {

    if len(args) < 2 {

        return fmt.Errorf("usage: helm <chart-name> <requirements>")

    }

    

    chartName := args[0]

    requirements := strings.Join(args[1:], " ")

    

    fmt.Printf("Generating Helm chart '%s'...\n", chartName)

    

    chart, err := c.helmGenerator.GenerateChart(ctx, requirements)

    if err != nil {

        return fmt.Errorf("failed to generate Helm chart: %w", err)

    }

    

    if err := c.helmGenerator.ValidateChart(chart); err != nil {

        return fmt.Errorf("generated chart is invalid: %w", err)

    }

    

    if err := c.writer.WriteHelmChart(chart, chartName); err != nil {

        return fmt.Errorf("failed to write Helm chart: %w", err)

    }

    

    fmt.Printf("Helm chart generated successfully in %s/\n", chartName)

    

    return nil

}


// handleRefine handles artifact refinement

func (c *CLI) handleRefine(ctx context.Context, args []string) error {

    if len(args) < 2 {

        return fmt.Errorf("usage: refine <artifact-type> <feedback>")

    }

    

    artifactType := args[0]

    feedback := strings.Join(args[1:], " ")

    

    fmt.Printf("Refining %s based on feedback...\n", artifactType)

    

    refined, err := c.generator.RefineArtifact(ctx, artifactType, feedback)

    if err != nil {

        return fmt.Errorf("failed to refine artifact: %w", err)

    }

    

    fmt.Printf("Artifact refined successfully\n")

    fmt.Printf("Refined artifact: %+v\n", refined)

    

    return nil

}


// printUsage prints usage information

func (c *CLI) printUsage() error {

    usage := `Docker and Kubernetes Artifact Generator


Usage:

  agent dockerfile <project-name> <requirements>

  agent deployment <project-name> <requirements>

  agent helm <chart-name> <requirements>

  agent refine <artifact-type> <feedback>


Commands:

  dockerfile   Generate a Dockerfile

  deployment   Generate a Kubernetes Deployment manifest

  helm         Generate a complete Helm chart

  refine       Refine a previously generated artifact


Examples:

  agent dockerfile myapp "Go web application with PostgreSQL"

  agent deployment myapp "3 replicas, health checks, resource limits"

  agent helm myapp "microservice with database dependency"

  agent refine dockerfile "use Alpine base image instead"

`

    

    fmt.Println(usage)

    return nil

}


// Close releases resources

func (c *CLI) Close() error {

    return c.provider.Close()

}


The CLI provides a clean, intuitive interface for generating artifacts. Each command is self-contained and provides clear feedback to the user. Error messages are descriptive and guide users toward correct usage.


RUNNING EXAMPLE - COMPLETE PRODUCTION SYSTEM


The following section presents a complete, production-ready implementation that integrates all components discussed above. This system can generate Dockerfiles, Kubernetes manifests, and Helm charts for any application type.


// main.go - Entry point for the Docker and Kubernetes artifact generator agent

package main


import (

    "context"

    "encoding/json"

    "fmt"

    "log"

    "os"

    "path/filepath"

    "strings"

    "time"

    

    "gopkg.in/yaml.v3"

)


// ========== LLM PROVIDER INTERFACES AND TYPES ==========


type Message struct {

    Role      string

    Content   string

    Timestamp time.Time

}


type CompletionRequest struct {

    Messages        []Message

    MaxTokens       int

    Temperature     float64

    TopP            float64

    StopSequences   []string

    PresencePenalty float64

    Metadata        map[string]string

}


type CompletionResponse struct {

    Content       string

    FinishReason  string

    TokensUsed    int

    PromptTokens  int

    ModelUsed     string

    Metadata      map[string]string

}


type ProviderCapabilities struct {

    SupportsStreaming   bool

    MaxContextTokens    int

    SupportedModalities []string

    RequiresAPIKey      bool

    GPUAccelerated      bool

}


type Provider interface {

    GenerateCompletion(ctx context.Context, req CompletionRequest) (*CompletionResponse, error)

    GetCapabilities() ProviderCapabilities

    HealthCheck(ctx context.Context) error

    Close() error

}


// ========== DOMAIN MODELS ==========


type Dockerfile struct {

    BaseImage        string

    Maintainer       string

    WorkDir          string

    Environment      map[string]string

    CopyInstructions []CopyInstruction

    RunCommands      []string

    ExposePort       []int

    EntryPoint       []string

    Command          []string

    Volumes          []string

    User             string

    Labels           map[string]string

    BuildArgs        map[string]string

    HealthCheck      *HealthCheck

}


type CopyInstruction struct {

    Source      string

    Destination string

    Chown       string

}


type HealthCheck struct {

    Command     []string

    Interval    string

    Timeout     string

    StartPeriod string

    Retries     int

}


func (d *Dockerfile) Validate() error {

    if d.BaseImage == "" {

        return fmt.Errorf("base image is required")

    }

    if len(d.EntryPoint) == 0 && len(d.Command) == 0 {

        return fmt.Errorf("either ENTRYPOINT or CMD must be specified")

    }

    return nil

}


func (d *Dockerfile) ToDockerfileContent() string {

    var builder strings.Builder

    

    builder.WriteString(fmt.Sprintf("FROM %s\n\n", d.BaseImage))

    

    if d.Maintainer != "" {

        builder.WriteString(fmt.Sprintf("LABEL maintainer=\"%s\"\n\n", d.Maintainer))

    }

    

    if len(d.Labels) > 0 {

        for key, value := range d.Labels {

            builder.WriteString(fmt.Sprintf("LABEL %s=\"%s\"\n", key, value))

        }

        builder.WriteString("\n")

    }

    

    if len(d.BuildArgs) > 0 {

        for key, value := range d.BuildArgs {

            builder.WriteString(fmt.Sprintf("ARG %s=%s\n", key, value))

        }

        builder.WriteString("\n")

    }

    

    if len(d.Environment) > 0 {

        for key, value := range d.Environment {

            builder.WriteString(fmt.Sprintf("ENV %s=%s\n", key, value))

        }

        builder.WriteString("\n")

    }

    

    if d.WorkDir != "" {

        builder.WriteString(fmt.Sprintf("WORKDIR %s\n\n", d.WorkDir))

    }

    

    for _, copy := range d.CopyInstructions {

        if copy.Chown != "" {

            builder.WriteString(fmt.Sprintf("COPY --chown=%s %s %s\n", copy.Chown, copy.Source, copy.Destination))

        } else {

            builder.WriteString(fmt.Sprintf("COPY %s %s\n", copy.Source, copy.Destination))

        }

    }

    if len(d.CopyInstructions) > 0 {

        builder.WriteString("\n")

    }

    

    for _, cmd := range d.RunCommands {

        builder.WriteString(fmt.Sprintf("RUN %s\n", cmd))

    }

    if len(d.RunCommands) > 0 {

        builder.WriteString("\n")

    }

    

    for _, vol := range d.Volumes {

        builder.WriteString(fmt.Sprintf("VOLUME %s\n", vol))

    }

    if len(d.Volumes) > 0 {

        builder.WriteString("\n")

    }

    

    for _, port := range d.ExposePort {

        builder.WriteString(fmt.Sprintf("EXPOSE %d\n", port))

    }

    if len(d.ExposePort) > 0 {

        builder.WriteString("\n")

    }

    

    if d.User != "" {

        builder.WriteString(fmt.Sprintf("USER %s\n\n", d.User))

    }

    

    if d.HealthCheck != nil {

        builder.WriteString("HEALTHCHECK ")

        if d.HealthCheck.Interval != "" {

            builder.WriteString(fmt.Sprintf("--interval=%s ", d.HealthCheck.Interval))

        }

        if d.HealthCheck.Timeout != "" {

            builder.WriteString(fmt.Sprintf("--timeout=%s ", d.HealthCheck.Timeout))

        }

        if d.HealthCheck.StartPeriod != "" {

            builder.WriteString(fmt.Sprintf("--start-period=%s ", d.HealthCheck.StartPeriod))

        }

        if d.HealthCheck.Retries > 0 {

            builder.WriteString(fmt.Sprintf("--retries=%d ", d.HealthCheck.Retries))

        }

        builder.WriteString(fmt.Sprintf("CMD %s\n\n", strings.Join(d.HealthCheck.Command, " ")))

    }

    

    if len(d.EntryPoint) > 0 {

        builder.WriteString(fmt.Sprintf("ENTRYPOINT [\"%s\"]\n", strings.Join(d.EntryPoint, "\", \"")))

    }

    

    if len(d.Command) > 0 {

        builder.WriteString(fmt.Sprintf("CMD [\"%s\"]\n", strings.Join(d.Command, "\", \"")))

    }

    

    return builder.String()

}


type KubernetesDeployment struct {

    APIVersion string         `yaml:"apiVersion"`

    Kind       string         `yaml:"kind"`

    Metadata   ObjectMeta     `yaml:"metadata"`

    Spec       DeploymentSpec `yaml:"spec"`

}


type ObjectMeta struct {

    Name        string            `yaml:"name"`

    Namespace   string            `yaml:"namespace,omitempty"`

    Labels      map[string]string `yaml:"labels,omitempty"`

    Annotations map[string]string `yaml:"annotations,omitempty"`

}


type DeploymentSpec struct {

    Replicas int32              `yaml:"replicas"`

    Selector *LabelSelector     `yaml:"selector"`

    Template PodTemplateSpec    `yaml:"template"`

    Strategy DeploymentStrategy `yaml:"strategy,omitempty"`

}


type LabelSelector struct {

    MatchLabels map[string]string `yaml:"matchLabels"`

}


type PodTemplateSpec struct {

    Metadata ObjectMeta `yaml:"metadata"`

    Spec     PodSpec    `yaml:"spec"`

}


type PodSpec struct {

    Containers      []Container          `yaml:"containers"`

    InitContainers  []Container          `yaml:"initContainers,omitempty"`

    Volumes         []Volume             `yaml:"volumes,omitempty"`

    ServiceAccount  string               `yaml:"serviceAccountName,omitempty"`

    SecurityContext *PodSecurityContext  `yaml:"securityContext,omitempty"`

    RestartPolicy   string               `yaml:"restartPolicy,omitempty"`

}


type Container struct {

    Name            string               `yaml:"name"`

    Image           string               `yaml:"image"`

    ImagePullPolicy string               `yaml:"imagePullPolicy,omitempty"`

    Command         []string             `yaml:"command,omitempty"`

    Args            []string             `yaml:"args,omitempty"`

    Ports           []ContainerPort      `yaml:"ports,omitempty"`

    Env             []EnvVar             `yaml:"env,omitempty"`

    VolumeMounts    []VolumeMount        `yaml:"volumeMounts,omitempty"`

    Resources       ResourceRequirements `yaml:"resources,omitempty"`

    LivenessProbe   *Probe               `yaml:"livenessProbe,omitempty"`

    ReadinessProbe  *Probe               `yaml:"readinessProbe,omitempty"`

    SecurityContext *SecurityContext     `yaml:"securityContext,omitempty"`

}


type ContainerPort struct {

    Name          string `yaml:"name,omitempty"`

    ContainerPort int32  `yaml:"containerPort"`

    Protocol      string `yaml:"protocol,omitempty"`

}


type EnvVar struct {

    Name      string        `yaml:"name"`

    Value     string        `yaml:"value,omitempty"`

    ValueFrom *EnvVarSource `yaml:"valueFrom,omitempty"`

}


type EnvVarSource struct {

    ConfigMapKeyRef *ConfigMapKeySelector `yaml:"configMapKeyRef,omitempty"`

    SecretKeyRef    *SecretKeySelector    `yaml:"secretKeyRef,omitempty"`

    FieldRef        *FieldSelector        `yaml:"fieldRef,omitempty"`

}


type ConfigMapKeySelector struct {

    Name string `yaml:"name"`

    Key  string `yaml:"key"`

}


type SecretKeySelector struct {

    Name string `yaml:"name"`

    Key  string `yaml:"key"`

}


type FieldSelector struct {

    FieldPath string `yaml:"fieldPath"`

}


type VolumeMount struct {

    Name      string `yaml:"name"`

    MountPath string `yaml:"mountPath"`

    ReadOnly  bool   `yaml:"readOnly,omitempty"`

    SubPath   string `yaml:"subPath,omitempty"`

}


type ResourceRequirements struct {

    Limits   map[string]string `yaml:"limits,omitempty"`

    Requests map[string]string `yaml:"requests,omitempty"`

}


type Probe struct {

    HTTPGet             *HTTPGetAction   `yaml:"httpGet,omitempty"`

    TCPSocket           *TCPSocketAction `yaml:"tcpSocket,omitempty"`

    Exec                *ExecAction      `yaml:"exec,omitempty"`

    InitialDelaySeconds int32            `yaml:"initialDelaySeconds,omitempty"`

    PeriodSeconds       int32            `yaml:"periodSeconds,omitempty"`

    TimeoutSeconds      int32            `yaml:"timeoutSeconds,omitempty"`

    SuccessThreshold    int32            `yaml:"successThreshold,omitempty"`

    FailureThreshold    int32            `yaml:"failureThreshold,omitempty"`

}


type HTTPGetAction struct {

    Path    string            `yaml:"path"`

    Port    int32             `yaml:"port"`

    Scheme  string            `yaml:"scheme,omitempty"`

    Headers map[string]string `yaml:"httpHeaders,omitempty"`

}


type TCPSocketAction struct {

    Port int32 `yaml:"port"`

}


type ExecAction struct {

    Command []string `yaml:"command"`

}


type SecurityContext struct {

    RunAsUser              *int64        `yaml:"runAsUser,omitempty"`

    RunAsGroup             *int64        `yaml:"runAsGroup,omitempty"`

    RunAsNonRoot           *bool         `yaml:"runAsNonRoot,omitempty"`

    ReadOnlyRootFilesystem *bool         `yaml:"readOnlyRootFilesystem,omitempty"`

    Capabilities           *Capabilities `yaml:"capabilities,omitempty"`

}


type Capabilities struct {

    Add  []string `yaml:"add,omitempty"`

    Drop []string `yaml:"drop,omitempty"`

}


type PodSecurityContext struct {

    RunAsUser    *int64 `yaml:"runAsUser,omitempty"`

    RunAsGroup   *int64 `yaml:"runAsGroup,omitempty"`

    FSGroup      *int64 `yaml:"fsGroup,omitempty"`

    RunAsNonRoot *bool  `yaml:"runAsNonRoot,omitempty"`

}


type Volume struct {

    Name                  string                 `yaml:"name"`

    ConfigMap             *ConfigMapVolume       `yaml:"configMap,omitempty"`

    Secret                *SecretVolume          `yaml:"secret,omitempty"`

    EmptyDir              *EmptyDirVolume        `yaml:"emptyDir,omitempty"`

    PersistentVolumeClaim *PVCVolume             `yaml:"persistentVolumeClaim,omitempty"`

}


type ConfigMapVolume struct {

    Name string `yaml:"name"`

}


type SecretVolume struct {

    SecretName string `yaml:"secretName"`

}


type EmptyDirVolume struct {

    Medium string `yaml:"medium,omitempty"`

}


type PVCVolume struct {

    ClaimName string `yaml:"claimName"`

}


type DeploymentStrategy struct {

    Type          string                 `yaml:"type,omitempty"`

    RollingUpdate *RollingUpdateStrategy `yaml:"rollingUpdate,omitempty"`

}


type RollingUpdateStrategy struct {

    MaxUnavailable string `yaml:"maxUnavailable,omitempty"`

    MaxSurge       string `yaml:"maxSurge,omitempty"`

}


// ========== HELM CHART STRUCTURES ==========


type HelmChart struct {

    ChartMetadata ChartMetadata

    Values        map[string]interface{}

    Templates     map[string]string

    Helpers       string

}


type ChartMetadata struct {

    APIVersion   string            `yaml:"apiVersion"`

    Name         string            `yaml:"name"`

    Version      string            `yaml:"version"`

    AppVersion   string            `yaml:"appVersion"`

    Description  string            `yaml:"description"`

    Keywords     []string          `yaml:"keywords,omitempty"`

    Maintainers  []Maintainer      `yaml:"maintainers,omitempty"`

    Dependencies []Dependency      `yaml:"dependencies,omitempty"`

    Annotations  map[string]string `yaml:"annotations,omitempty"`

}


type Maintainer struct {

    Name  string `yaml:"name"`

    Email string `yaml:"email,omitempty"`

}


type Dependency struct {

    Name       string `yaml:"name"`

    Version    string `yaml:"version"`

    Repository string `yaml:"repository"`

    Condition  string `yaml:"condition,omitempty"`

}


// ========== MOCK LLM PROVIDER FOR DEMONSTRATION ==========


type MockProvider struct {

    capabilities ProviderCapabilities

}


func NewMockProvider() *MockProvider {

    return &MockProvider{

        capabilities: ProviderCapabilities{

            SupportsStreaming:   false,

            MaxContextTokens:    8192,

            SupportedModalities: []string{"text"},

            RequiresAPIKey:      false,

            GPUAccelerated:      true,

        },

    }

}


func (m *MockProvider) GenerateCompletion(ctx context.Context, req CompletionRequest) (*CompletionResponse, error) {

    // Analyze the request to determine what artifact to generate

    lastMessage := req.Messages[len(req.Messages)-1].Content

    

    var responseContent string

    

    if strings.Contains(strings.ToLower(lastMessage), "dockerfile") {

        responseContent = m.generateDockerfileResponse(lastMessage)

    } else if strings.Contains(strings.ToLower(lastMessage), "deployment") {

        responseContent = m.generateDeploymentResponse(lastMessage)

    } else if strings.Contains(strings.ToLower(lastMessage), "helm") {

        responseContent = m.generateHelmResponse(lastMessage)

    } else {

        responseContent = `{"artifact_type": "unknown", "content": {}}`

    }

    

    return &CompletionResponse{

        Content:      responseContent,

        FinishReason: "stop",

        TokensUsed:   500,

        PromptTokens: 200,

        ModelUsed:    "mock-model-v1",

        Metadata:     map[string]string{"gpu_backend": "cuda"},

    }, nil

}


func (m *MockProvider) generateDockerfileResponse(requirements string) string {

    // Generate a comprehensive Dockerfile based on requirements

    response := map[string]interface{}{

        "artifact_type": "dockerfile",

        "content": map[string]interface{}{

            "base_image":  "golang:1.21-alpine",

            "maintainer":  "devops@example.com",

            "workdir":     "/app",

            "environment": map[string]string{

                "GO111MODULE": "on",

                "CGO_ENABLED": "0",

            },

            "copy_instructions": []map[string]string{

                {"source": "go.mod", "destination": ".", "chown": ""},

                {"source": "go.sum", "destination": ".", "chown": ""},

                {"source": ".", "destination": ".", "chown": ""},

            },

            "run_commands": []string{

                "apk add --no-cache ca-certificates",

                "go mod download",

                "go build -o /app/server .",

            },

            "expose_ports": []int{8080},

            "entrypoint":   []string{"/app/server"},

            "command":      []string{},

            "volumes":      []string{},

            "user":         "nobody",

            "labels": map[string]string{

                "version":     "1.0.0",

                "description": "Production-ready Go application",

            },

            "build_args": map[string]string{

                "VERSION": "1.0.0",

            },

            "healthcheck": map[string]interface{}{

                "command":      []string{"CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1"},

                "interval":     "30s",

                "timeout":      "5s",

                "start_period": "10s",

                "retries":      3,

            },

        },

    }

    

    jsonBytes, _ := json.Marshal(response)

    return string(jsonBytes)

}


func (m *MockProvider) generateDeploymentResponse(requirements string) string {

    runAsNonRoot := true

    runAsUser := int64(1000)

    readOnlyRoot := true

    

    response := map[string]interface{}{

        "artifact_type": "deployment",

        "content": KubernetesDeployment{

            APIVersion: "apps/v1",

            Kind:       "Deployment",

            Metadata: ObjectMeta{

                Name:      "myapp",

                Namespace: "default",

                Labels: map[string]string{

                    "app":     "myapp",

                    "version": "v1",

                },

            },

            Spec: DeploymentSpec{

                Replicas: 3,

                Selector: &LabelSelector{

                    MatchLabels: map[string]string{

                        "app": "myapp",

                    },

                },

                Template: PodTemplateSpec{

                    Metadata: ObjectMeta{

                        Labels: map[string]string{

                            "app":     "myapp",

                            "version": "v1",

                        },

                    },

                    Spec: PodSpec{

                        Containers: []Container{

                            {

                                Name:            "myapp",

                                Image:           "myapp:1.0.0",

                                ImagePullPolicy: "IfNotPresent",

                                Ports: []ContainerPort{

                                    {

                                        Name:          "http",

                                        ContainerPort: 8080,

                                        Protocol:      "TCP",

                                    },

                                },

                                Env: []EnvVar{

                                    {

                                        Name:  "APP_ENV",

                                        Value: "production",

                                    },

                                },

                                Resources: ResourceRequirements{

                                    Limits: map[string]string{

                                        "cpu":    "500m",

                                        "memory": "512Mi",

                                    },

                                    Requests: map[string]string{

                                        "cpu":    "250m",

                                        "memory": "256Mi",

                                    },

                                },

                                LivenessProbe: &Probe{

                                    HTTPGet: &HTTPGetAction{

                                        Path:   "/health",

                                        Port:   8080,

                                        Scheme: "HTTP",

                                    },

                                    InitialDelaySeconds: 30,

                                    PeriodSeconds:       10,

                                    TimeoutSeconds:      5,

                                    FailureThreshold:    3,

                                },

                                ReadinessProbe: &Probe{

                                    HTTPGet: &HTTPGetAction{

                                        Path:   "/ready",

                                        Port:   8080,

                                        Scheme: "HTTP",

                                    },

                                    InitialDelaySeconds: 10,

                                    PeriodSeconds:       5,

                                    TimeoutSeconds:      3,

                                    FailureThreshold:    2,

                                },

                                SecurityContext: &SecurityContext{

                                    RunAsNonRoot:           &runAsNonRoot,

                                    RunAsUser:              &runAsUser,

                                    ReadOnlyRootFilesystem: &readOnlyRoot,

                                    Capabilities: &Capabilities{

                                        Drop: []string{"ALL"},

                                    },

                                },

                            },

                        },

                        SecurityContext: &PodSecurityContext{

                            RunAsNonRoot: &runAsNonRoot,

                            RunAsUser:    &runAsUser,

                        },

                    },

                },

                Strategy: DeploymentStrategy{

                    Type: "RollingUpdate",

                    RollingUpdate: &RollingUpdateStrategy{

                        MaxUnavailable: "1",

                        MaxSurge:       "1",

                    },

                },

            },

        },

    }

    

    jsonBytes, _ := json.Marshal(response)

    return string(jsonBytes)

}


func (m *MockProvider) generateHelmResponse(requirements string) string {

    response := map[string]interface{}{

        "chart_metadata": ChartMetadata{

            APIVersion:  "v2",

            Name:        "myapp",

            Version:     "1.0.0",

            AppVersion:  "1.0.0",

            Description: "A production-ready Helm chart for myapp",

            Keywords:    []string{"application", "microservice"},

            Maintainers: []Maintainer{

                {Name: "DevOps Team", Email: "devops@example.com"},

            },

        },

        "values": map[string]interface{}{

            "replicaCount": 3,

            "image": map[string]interface{}{

                "repository": "myapp",

                "tag":        "1.0.0",

                "pullPolicy": "IfNotPresent",

            },

            "service": map[string]interface{}{

                "type": "ClusterIP",

                "port": 80,

            },

            "resources": map[string]interface{}{

                "limits": map[string]string{

                    "cpu":    "500m",

                    "memory": "512Mi",

                },

                "requests": map[string]string{

                    "cpu":    "250m",

                    "memory": "256Mi",

                },

            },

        },

        "templates": map[string]string{

            "deployment.yaml": `apiVersion: apps/v1

kind: Deployment

metadata:

  name: {{ include "myapp.fullname" . }}

  labels:

    {{- include "myapp.labels" . | nindent 4 }}

spec:

  replicas: {{ .Values.replicaCount }}

  selector:

    matchLabels:

      {{- include "myapp.selectorLabels" . | nindent 6 }}

  template:

    metadata:

      labels:

        {{- include "myapp.selectorLabels" . | nindent 8 }}

    spec:

      containers:

      - name: {{ .Chart.Name }}

        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

        imagePullPolicy: {{ .Values.image.pullPolicy }}

        ports:

        - name: http

          containerPort: 8080

          protocol: TCP

        resources:

          {{- toYaml .Values.resources | nindent 10 }}`,

            "service.yaml": `apiVersion: v1

kind: Service

metadata:

  name: {{ include "myapp.fullname" . }}

  labels:

    {{- include "myapp.labels" . | nindent 4 }}

spec:

  type: {{ .Values.service.type }}

  ports:

  - port: {{ .Values.service.port }}

    targetPort: http

    protocol: TCP

    name: http

  selector:

    {{- include "myapp.selectorLabels" . | nindent 4 }}`,

        },

        "helpers": `{{- define "myapp.fullname" -}}

{{- .Release.Name }}-{{ .Chart.Name }}

{{- end }}


{{- define "myapp.labels" -}}

helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}

{{ include "myapp.selectorLabels" . }}

app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}

app.kubernetes.io/managed-by: {{ .Release.Service }}

{{- end }}


{{- define "myapp.selectorLabels" -}}

app.kubernetes.io/name: {{ .Chart.Name }}

app.kubernetes.io/instance: {{ .Release.Name }}

{{- end }}`,

    }

    

    jsonBytes, _ := json.Marshal(response)

    return string(jsonBytes)

}


func (m *MockProvider) GetCapabilities() ProviderCapabilities {

    return m.capabilities

}


func (m *MockProvider) HealthCheck(ctx context.Context) error {

    return nil

}


func (m *MockProvider) Close() error {

    return nil

}


// ========== ARTIFACT GENERATOR ==========


type ConversationContext struct {

    Messages           []Message

    GeneratedArtifacts map[string]interface{}

}


type ArtifactGenerator struct {

    provider        Provider

    systemPrompt    string

    conversationCtx *ConversationContext

}


func NewArtifactGenerator(provider Provider) *ArtifactGenerator {

    systemPrompt := `You are an expert in Docker and Kubernetes. Your task is to generate production-ready Docker and Kubernetes artifacts based on user requirements.


When generating Dockerfiles:

- Use multi-stage builds when appropriate

- Follow security best practices (non-root user, minimal base images)

- Optimize for layer caching

- Include health checks

- Use specific version tags, not 'latest'


When generating Kubernetes manifests:

- Include resource limits and requests

- Configure appropriate health probes

- Use security contexts

- Follow the principle of least privilege

- Include labels for organization


Always respond with valid JSON containing the artifact structure.`


    return &ArtifactGenerator{

        provider:     provider,

        systemPrompt: systemPrompt,

        conversationCtx: &ConversationContext{

            Messages: []Message{

                {Role: "system", Content: systemPrompt, Timestamp: time.Now()},

            },

            GeneratedArtifacts: make(map[string]interface{}),

        },

    }

}


func (g *ArtifactGenerator) GenerateDockerfile(ctx context.Context, requirements string) (*Dockerfile, error) {

    userMessage := Message{

        Role:      "user",

        Content:   fmt.Sprintf("Generate a Dockerfile with the following requirements: %s", requirements),

        Timestamp: time.Now(),

    }

    

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, userMessage)

    

    request := CompletionRequest{

        Messages:    g.conversationCtx.Messages,

        MaxTokens:   2000,

        Temperature: 0.3,

        TopP:        0.9,

    }

    

    response, err := g.provider.GenerateCompletion(ctx, request)

    if err != nil {

        return nil, fmt.Errorf("failed to generate completion: %w", err)

    }

    

    assistantMessage := Message{

        Role:      "assistant",

        Content:   response.Content,

        Timestamp: time.Now(),

    }

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, assistantMessage)

    

    dockerfile, err := parseDockerfileResponse(response.Content)

    if err != nil {

        return nil, fmt.Errorf("failed to parse Dockerfile response: %w", err)

    }

    

    if err := dockerfile.Validate(); err != nil {

        return nil, fmt.Errorf("generated Dockerfile is invalid: %w", err)

    }

    

    g.conversationCtx.GeneratedArtifacts["dockerfile"] = dockerfile

    

    return dockerfile, nil

}


func (g *ArtifactGenerator) GenerateDeployment(ctx context.Context, requirements string) (*KubernetesDeployment, error) {

    userMessage := Message{

        Role:      "user",

        Content:   fmt.Sprintf("Generate a Kubernetes Deployment manifest with the following requirements: %s", requirements),

        Timestamp: time.Now(),

    }

    

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, userMessage)

    

    request := CompletionRequest{

        Messages:    g.conversationCtx.Messages,

        MaxTokens:   3000,

        Temperature: 0.3,

        TopP:        0.9,

    }

    

    response, err := g.provider.GenerateCompletion(ctx, request)

    if err != nil {

        return nil, fmt.Errorf("failed to generate completion: %w", err)

    }

    

    assistantMessage := Message{

        Role:      "assistant",

        Content:   response.Content,

        Timestamp: time.Now(),

    }

    g.conversationCtx.Messages = append(g.conversationCtx.Messages, assistantMessage)

    

    deployment, err := parseDeploymentResponse(response.Content)

    if err != nil {

        return nil, fmt.Errorf("failed to parse Deployment response: %w", err)

    }

    

    g.conversationCtx.GeneratedArtifacts["deployment"] = deployment

    

    return deployment, nil

}


func parseDockerfileResponse(content string) (*Dockerfile, error) {

    jsonContent := extractJSON(content)

    if jsonContent == "" {

        return nil, fmt.Errorf("no JSON found in response")

    }

    

    var response struct {

        ArtifactType string `json:"artifact_type"`

        Content      struct {

            BaseImage        string              `json:"base_image"`

            Maintainer       string              `json:"maintainer"`

            WorkDir          string              `json:"workdir"`

            Environment      map[string]string   `json:"environment"`

            CopyInstructions []struct {

                Source      string `json:"source"`

                Destination string `json:"destination"`

                Chown       string `json:"chown"`

            } `json:"copy_instructions"`

            RunCommands  []string          `json:"run_commands"`

            ExposePort   []int             `json:"expose_ports"`

            EntryPoint   []string          `json:"entrypoint"`

            Command      []string          `json:"command"`

            Volumes      []string          `json:"volumes"`

            User         string            `json:"user"`

            Labels       map[string]string `json:"labels"`

            BuildArgs    map[string]string `json:"build_args"`

            HealthCheck  *struct {

                Command     []string `json:"command"`

                Interval    string   `json:"interval"`

                Timeout     string   `json:"timeout"`

                StartPeriod string   `json:"start_period"`

                Retries     int      `json:"retries"`

            } `json:"healthcheck"`

        } `json:"content"`

    }

    

    if err := json.Unmarshal([]byte(jsonContent), &response); err != nil {

        return nil, fmt.Errorf("failed to unmarshal JSON: %w", err)

    }

    

    dockerfile := &Dockerfile{

        BaseImage:   response.Content.BaseImage,

        Maintainer:  response.Content.Maintainer,

        WorkDir:     response.Content.WorkDir,

        Environment: response.Content.Environment,

        RunCommands: response.Content.RunCommands,

        ExposePort:  response.Content.ExposePort,

        EntryPoint:  response.Content.EntryPoint,

        Command:     response.Content.Command,

        Volumes:     response.Content.Volumes,

        User:        response.Content.User,

        Labels:      response.Content.Labels,

        BuildArgs:   response.Content.BuildArgs,

    }

    

    for _, ci := range response.Content.CopyInstructions {

        dockerfile.CopyInstructions = append(dockerfile.CopyInstructions, CopyInstruction{

            Source:      ci.Source,

            Destination: ci.Destination,

            Chown:       ci.Chown,

        })

    }

    

    if response.Content.HealthCheck != nil {

        dockerfile.HealthCheck = &HealthCheck{

            Command:     response.Content.HealthCheck.Command,

            Interval:    response.Content.HealthCheck.Interval,

            Timeout:     response.Content.HealthCheck.Timeout,

            StartPeriod: response.Content.HealthCheck.StartPeriod,

            Retries:     response.Content.HealthCheck.Retries,

        }

    }

    

    return dockerfile, nil

}


func parseDeploymentResponse(content string) (*KubernetesDeployment, error) {

    jsonContent := extractJSON(content)

    if jsonContent == "" {

        return nil, fmt.Errorf("no JSON found in response")

    }

    

    var response struct {

        ArtifactType string                `json:"artifact_type"`

        Content      KubernetesDeployment `json:"content"`

    }

    

    if err := json.Unmarshal([]byte(jsonContent), &response); err != nil {

        return nil, fmt.Errorf("failed to unmarshal JSON: %w", err)

    }

    

    return &response.Content, nil

}


func extractJSON(content string) string {

    start := strings.Index(content, "{")

    end := strings.LastIndex(content, "}")

    

    if start == -1 || end == -1 || start >= end {

        return ""

    }

    

    return content[start : end+1]

}


// ========== HELM GENERATOR ==========


type HelmGenerator struct {

    provider     Provider

    systemPrompt string

}


func NewHelmGenerator(provider Provider) *HelmGenerator {

    systemPrompt := `You are an expert in Helm chart development. Generate production-ready Helm charts following best practices.`

    

    return &HelmGenerator{

        provider:     provider,

        systemPrompt: systemPrompt,

    }

}


func (g *HelmGenerator) GenerateChart(ctx context.Context, requirements string) (*HelmChart, error) {

    messages := []Message{

        {Role: "system", Content: g.systemPrompt, Timestamp: time.Now()},

        {Role: "user", Content: fmt.Sprintf("Generate a Helm chart with the following requirements: %s", requirements), Timestamp: time.Now()},

    }

    

    request := CompletionRequest{

        Messages:    messages,

        MaxTokens:   4000,

        Temperature: 0.3,

        TopP:        0.9,

    }

    

    response, err := g.provider.GenerateCompletion(ctx, request)

    if err != nil {

        return nil, fmt.Errorf("failed to generate completion: %w", err)

    }

    

    chart, err := parseChartResponse(response.Content)

    if err != nil {

        return nil, fmt.Errorf("failed to parse chart response: %w", err)

    }

    

    return chart, nil

}


func parseChartResponse(content string) (*HelmChart, error) {

    jsonContent := extractJSON(content)

    if jsonContent == "" {

        return nil, fmt.Errorf("no JSON found in response")

    }

    

    var response struct {

        ChartMetadata ChartMetadata         `json:"chart_metadata"`

        Values        map[string]interface{} `json:"values"`

        Templates     map[string]string      `json:"templates"`

        Helpers       string                 `json:"helpers"`

    }

    

    if err := json.Unmarshal([]byte(jsonContent), &response); err != nil {

        return nil, fmt.Errorf("failed to unmarshal JSON: %w", err)

    }

    

    return &HelmChart{

        ChartMetadata: response.ChartMetadata,

        Values:        response.Values,

        Templates:     response.Templates,

        Helpers:       response.Helpers,

    }, nil

}


// ========== FILESYSTEM WRITER ==========


type ArtifactWriter struct {

    baseDir string

}


func NewArtifactWriter(baseDir string) (*ArtifactWriter, error) {

    if err := os.MkdirAll(baseDir, 0755); err != nil {

        return nil, fmt.Errorf("failed to create base directory: %w", err)

    }

    

    return &ArtifactWriter{baseDir: baseDir}, nil

}


func (w *ArtifactWriter) WriteDockerfile(dockerfile *Dockerfile, projectName string) error {

    projectDir := filepath.Join(w.baseDir, projectName)

    if err := os.MkdirAll(projectDir, 0755); err != nil {

        return fmt.Errorf("failed to create project directory: %w", err)

    }

    

    dockerfilePath := filepath.Join(projectDir, "Dockerfile")

    content := dockerfile.ToDockerfileContent()

    

    if err := os.WriteFile(dockerfilePath, []byte(content), 0644); err != nil {

        return fmt.Errorf("failed to write Dockerfile: %w", err)

    }

    

    return nil

}


func (w *ArtifactWriter) WriteKubernetesManifest(manifest interface{}, projectName, filename string) error {

    manifestDir := filepath.Join(w.baseDir, projectName, "k8s")

    if err := os.MkdirAll(manifestDir, 0755); err != nil {

        return fmt.Errorf("failed to create manifest directory: %w", err)

    }

    

    manifestPath := filepath.Join(manifestDir, filename)

    

    yamlContent, err := yaml.Marshal(manifest)

    if err != nil {

        return fmt.Errorf("failed to marshal manifest to YAML: %w", err)

    }

    

    if err := os.WriteFile(manifestPath, yamlContent, 0644); err != nil {

        return fmt.Errorf("failed to write manifest: %w", err)

    }

    

    return nil

}


func (w *ArtifactWriter) WriteHelmChart(chart *HelmChart, chartName string) error {

    chartDir := filepath.Join(w.baseDir, chartName)

    

    dirs := []string{

        chartDir,

        filepath.Join(chartDir, "templates"),

        filepath.Join(chartDir, "charts"),

    }

    

    for _, dir := range dirs {

        if err := os.MkdirAll(dir, 0755); err != nil {

            return fmt.Errorf("failed to create directory %s: %w", dir, err)

        }

    }

    

    chartYAMLPath := filepath.Join(chartDir, "Chart.yaml")

    chartYAML, err := yaml.Marshal(chart.ChartMetadata)

    if err != nil {

        return fmt.Errorf("failed to marshal Chart.yaml: %w", err)

    }

    if err := os.WriteFile(chartYAMLPath, chartYAML, 0644); err != nil {

        return fmt.Errorf("failed to write Chart.yaml: %w", err)

    }

    

    valuesYAMLPath := filepath.Join(chartDir, "values.yaml")

    valuesYAML, err := yaml.Marshal(chart.Values)

    if err != nil {

        return fmt.Errorf("failed to marshal values.yaml: %w", err)

    }

    if err := os.WriteFile(valuesYAMLPath, valuesYAML, 0644); err != nil {

        return fmt.Errorf("failed to write values.yaml: %w", err)

    }

    

    for filename, content := range chart.Templates {

        templatePath := filepath.Join(chartDir, "templates", filename)

        if err := os.WriteFile(templatePath, []byte(content), 0644); err != nil {

            return fmt.Errorf("failed to write template %s: %w", filename, err)

        }

    }

    

    if chart.Helpers != "" {

        helpersPath := filepath.Join(chartDir, "templates", "_helpers.tpl")

        if err := os.WriteFile(helpersPath, []byte(chart.Helpers), 0644); err != nil {

            return fmt.Errorf("failed to write _helpers.tpl: %w", err)

        }

    }

    

    return nil

}


// ========== MAIN APPLICATION ==========


func main() {

    if len(os.Args) < 2 {

        printUsage()

        os.Exit(1)

    }

    

    command := os.Args[1]

    

    provider := NewMockProvider()

    defer provider.Close()

    

    ctx := context.Background()

    

    if err := provider.HealthCheck(ctx); err != nil {

        log.Fatalf("Provider health check failed: %v", err)

    }

    

    generator := NewArtifactGenerator(provider)

    helmGenerator := NewHelmGenerator(provider)

    

    writer, err := NewArtifactWriter("./output")

    if err != nil {

        log.Fatalf("Failed to initialize artifact writer: %v", err)

    }

    

    switch command {

    case "dockerfile":

        if len(os.Args) < 4 {

            fmt.Println("Usage: agent dockerfile <project-name> <requirements>")

            os.Exit(1)

        }

        

        projectName := os.Args[2]

        requirements := strings.Join(os.Args[3:], " ")

        

        fmt.Printf("Generating Dockerfile for project '%s'...\n", projectName)

        

        dockerfile, err := generator.GenerateDockerfile(ctx, requirements)

        if err != nil {

            log.Fatalf("Failed to generate Dockerfile: %v", err)

        }

        

        if err := writer.WriteDockerfile(dockerfile, projectName); err != nil {

            log.Fatalf("Failed to write Dockerfile: %v", err)

        }

        

        fmt.Printf("Dockerfile generated successfully in output/%s/Dockerfile\n", projectName)

        fmt.Println("\nGenerated Dockerfile:")

        fmt.Println(dockerfile.ToDockerfileContent())

        

    case "deployment":

        if len(os.Args) < 4 {

            fmt.Println("Usage: agent deployment <project-name> <requirements>")

            os.Exit(1)

        }

        

        projectName := os.Args[2]

        requirements := strings.Join(os.Args[3:], " ")

        

        fmt.Printf("Generating Kubernetes Deployment for project '%s'...\n", projectName)

        

        deployment, err := generator.GenerateDeployment(ctx, requirements)

        if err != nil {

            log.Fatalf("Failed to generate Deployment: %v", err)

        }

        

        if err := writer.WriteKubernetesManifest(deployment, projectName, "deployment.yaml"); err != nil {

            log.Fatalf("Failed to write Deployment: %v", err)

        }

        

        fmt.Printf("Deployment manifest generated successfully in output/%s/k8s/deployment.yaml\n", projectName)

        

    case "helm":

        if len(os.Args) < 4 {

            fmt.Println("Usage: agent helm <chart-name> <requirements>")

            os.Exit(1)

        }

        

        chartName := os.Args[2]

        requirements := strings.Join(os.Args[3:], " ")

        

        fmt.Printf("Generating Helm chart '%s'...\n", chartName)

        

        chart, err := helmGenerator.GenerateChart(ctx, requirements)

        if err != nil {

            log.Fatalf("Failed to generate Helm chart: %v", err)

        }

        

        if err := writer.WriteHelmChart(chart, chartName); err != nil {

            log.Fatalf("Failed to write Helm chart: %v", err)

        }

        

        fmt.Printf("Helm chart generated successfully in output/%s/\n", chartName)

        

    default:

        fmt.Printf("Unknown command: %s\n", command)

        printUsage()

        os.Exit(1)

    }

}


func printUsage() {

    usage := `Docker and Kubernetes Artifact Generator


Usage:

  agent dockerfile <project-name> <requirements>

  agent deployment <project-name> <requirements>

  agent helm <chart-name> <requirements>


Commands:

  dockerfile   Generate a Dockerfile

  deployment   Generate a Kubernetes Deployment manifest

  helm         Generate a complete Helm chart


Examples:

  agent dockerfile myapp "Go web application with PostgreSQL"

  agent deployment myapp "3 replicas, health checks, resource limits"

  agent helm myapp "microservice with database dependency"

`

    

    fmt.Println(usage)

}


CONCLUSION AND DEPLOYMENT CONSIDERATIONS

This comprehensive implementation provides a production-ready system for generating Docker and Kubernetes artifacts using Large Language Models. The architecture supports both local and remote LLM providers, accommodates various GPU backends, and generates complete, validated artifacts that follow industry best practices.


The system can be extended to support additional artifact types such as ConfigMaps, Secrets, Services, Ingresses, and StatefulSets. The conversational context management allows for iterative refinement, enabling users to provide feedback and improve generated artifacts through natural language interactions.


For production deployment, consider implementing additional features such as artifact versioning, template libraries for common patterns, integration with CI/CD pipelines, and automated testing of generated configurations. The modular architecture facilitates these enhancements without requiring significant refactoring.


The GPU backend detection and provider abstraction ensure that the system can leverage the most appropriate computational resources available, whether running on developer workstations with various GPU architectures or in cloud environments with remote API access. This flexibility makes the system suitable for diverse deployment scenarios while maintaining consistent functionality and user experience.

No comments: