Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions go/cli/cmd/kagent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"syscall"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/kagent-dev/kagent/go/cli/internal/profiles"
"github.com/kagent-dev/kagent/go/cli/internal/tui"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func main() {
Expand Down Expand Up @@ -46,6 +48,12 @@ func main() {
rootCmd.PersistentFlags().StringVarP(&cfg.OutputFormat, "output-format", "o", "table", "Output format")
rootCmd.PersistentFlags().BoolVarP(&cfg.Verbose, "verbose", "v", false, "Verbose output")
rootCmd.PersistentFlags().DurationVar(&cfg.Timeout, "timeout", 300*time.Second, "Timeout")
rootCmd.PersistentFlags().StringVar(&cfg.Registry, "registry", "localhost:5001", "Default registry for local builds")

if err := viper.BindPFlag("registry", rootCmd.PersistentFlags().Lookup("registry")); err != nil {
log.Fatalf("Failed to bind pflag: %v", err)
}

installCfg := &cli.InstallCfg{
Config: cfg,
}
Expand Down Expand Up @@ -421,6 +429,24 @@ Examples:
os.Exit(1)
}

finalCfg, err := config.Get()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading final config: %v\n", err)
os.Exit(1)
}

cfg = finalCfg
if buildCfg != nil {
buildCfg.Registry = cfg.Registry
}
if deployCfg != nil {
deployCfg.Registry = cfg.Registry
}
if runCfg != nil {
runCfg.Registry = cfg.Registry
}


if err := rootCmd.ExecuteContext(ctx); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)

Expand Down
5 changes: 3 additions & 2 deletions go/cli/internal/cli/agent/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type BuildCfg struct {
Platform string
Config *config.Config
SkipMCPServers bool
Registry string
}

// BuildCmd builds a Docker image for an agent project
Expand Down Expand Up @@ -96,7 +97,7 @@ func constructImageName(cfg *BuildCfg) string {
}

// Construct full image name using common utility
return commonimage.ConstructImageName(cfg.Image, agentName)
return commonimage.ConstructImageName(cfg.Image, agentName, cfg.Registry)
}

// getAgentNameFromManifest attempts to load the agent name from kagent.yaml
Expand Down Expand Up @@ -202,5 +203,5 @@ func constructMcpServerImageName(cfg *BuildCfg, serverName string) string {
if agentName == "" {
agentName = filepath.Base(cfg.ProjectDir)
}
return commonimage.ConstructMCPServerImageName(agentName, serverName)
return commonimage.ConstructMCPServerImageName(agentName, serverName, cfg.Registry)
}
8 changes: 5 additions & 3 deletions go/cli/internal/cli/agent/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ type DeployCfg struct {

// DryRun when true, outputs YAML manifests without actually creating resources
DryRun bool

Registry string
}

// DeployCmd deploys an agent to Kubernetes
Expand Down Expand Up @@ -645,7 +647,7 @@ func createOrUpdateSecret(ctx context.Context, k8sClient client.Client, secret *

// createAgentCRD creates or updates the Agent CRD
func createAgentCRD(ctx context.Context, k8sClient client.Client, cfg *DeployCfg, manifest *common.AgentManifest, envData *envFileData, verbose bool) error {
imageName := determineImageName(cfg.Image, manifest.Name)
imageName := determineImageName(cfg.Image, manifest.Name, cfg.Config.Registry)
agent := buildAgentCRD(cfg.Config.Namespace, manifest, imageName, envData)

// In dry-run mode, just output the YAML
Expand All @@ -658,8 +660,8 @@ func createAgentCRD(ctx context.Context, k8sClient client.Client, cfg *DeployCfg
}

// determineImageName returns the image name to use, either from config or default
func determineImageName(configImage, agentName string) string {
return commonimage.ConstructImageName(configImage, agentName)
func determineImageName(configImage, agentName, registry string) string {
return commonimage.ConstructImageName(configImage, agentName, registry)
}

// buildAgentCRD constructs an Agent CRD object
Expand Down
3 changes: 2 additions & 1 deletion go/cli/internal/cli/agent/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import (
type RunCfg struct {
ProjectDir string
Config *config.Config
Build bool
Build bool
Registry string
}

// RunCmd starts docker-compose in the background and launches a chat session with the local agent
Expand Down
24 changes: 16 additions & 8 deletions go/cli/internal/common/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,25 @@ const (
// ConstructImageName constructs a Docker image name with default registry and tag.
// If configImage is provided (non-empty), it is returned as-is.
// Otherwise, constructs: DefaultRegistry/imageName:DefaultTag (e.g., "localhost:5001/my-agent:latest")
func ConstructImageName(configImage, imageName string) string {
if configImage != "" {
return configImage
}
return fmt.Sprintf("%s/%s:%s", DefaultRegistry, imageName, DefaultTag)
func ConstructImageName(configImage, imageName, registry string) string {
if configImage != "" {
return configImage
}

if registry == "" {
registry = DefaultRegistry
}

return fmt.Sprintf("%s/%s:%s", registry, imageName, DefaultTag)
}

// ConstructMCPServerImageName constructs a Docker image name for an MCP server.
// The image name follows the pattern: DefaultRegistry/agentName-serverName:DefaultTag
// (e.g., "localhost:5001/my-agent-github-server:latest")
func ConstructMCPServerImageName(agentName, serverName string) string {
imageName := fmt.Sprintf("%s-%s", agentName, serverName)
return fmt.Sprintf("%s/%s:%s", DefaultRegistry, imageName, DefaultTag)
func ConstructMCPServerImageName(agentName, serverName, registry string) string {
if registry == "" {
registry = DefaultRegistry
}
imageName := fmt.Sprintf("%s-%s", agentName, serverName)
return fmt.Sprintf("%s/%s:%s", registry, imageName, DefaultTag)
}
5 changes: 5 additions & 0 deletions go/cli/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Config struct {
OutputFormat string `mapstructure:"output_format"`
Verbose bool `mapstructure:"verbose"`
Timeout time.Duration `mapstructure:"timeout"`
Registry string `mapstructure:"registry"`
}

func (c *Config) Client() *kagentclient.ClientSet {
Expand Down Expand Up @@ -47,6 +48,10 @@ func Init() error {
viper.SetDefault("output_format", "table")
viper.SetDefault("namespace", "kagent")
viper.SetDefault("timeout", 300*time.Second)
viper.SetDefault("registry", "localhost:5001")
if err := viper.BindEnv("registry", "KAGENT_REGISTRY"); err != nil {
return fmt.Errorf("error binding KAGENT_REGISTRY: %w", err)
}
viper.MustBindEnv("USER_ID")

if err := viper.ReadInConfig(); err != nil {
Expand Down
Loading