// Package cmd provides command-line interface functionality for the CLI Proxy API server. // It includes authentication flows for various AI service providers, service startup, // and other command-line operations. package cmd import ( "context" "errors" "os/signal" "syscall" "time" "github.com/router-for-me/CLIProxyAPI/v6/internal/api" "github.com/router-for-me/CLIProxyAPI/v6/internal/config" "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy" log "github.com/sirupsen/logrus" ) // StartService builds and runs the proxy service using the exported SDK. // It creates a new proxy service instance, sets up signal handling for graceful shutdown, // and starts the service with the provided configuration. // // Parameters: // - cfg: The application configuration // - configPath: The path to the configuration file // - localPassword: Optional password accepted for local management requests func StartService(cfg *config.Config, configPath string, localPassword string) { builder := cliproxy.NewBuilder(). WithConfig(cfg). WithConfigPath(configPath). WithLocalManagementPassword(localPassword) ctxSignal, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer cancel() runCtx := ctxSignal if localPassword != "" { var keepAliveCancel context.CancelFunc runCtx, keepAliveCancel = context.WithCancel(ctxSignal) builder = builder.WithServerOptions(api.WithKeepAliveEndpoint(10*time.Second, func() { log.Warn("keep-alive endpoint idle for 10s, shutting down") keepAliveCancel() })) } service, err := builder.Build() if err != nil { log.Fatalf("failed to build proxy service: %v", err) } err = service.Run(runCtx) if err != nil && !errors.Is(err, context.Canceled) { log.Fatalf("proxy service exited with error: %v", err) } } // WaitForCloudDeploy waits indefinitely for shutdown signals in cloud deploy mode // when no configuration file is available. func WaitForCloudDeploy() { // Clarify that we are intentionally idle for configuration and not running the API server. log.Info("Cloud deploy mode: No config found; standing by for configuration. API server is not started. Press Ctrl+C to exit.") ctxSignal, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer cancel() // Block until shutdown signal is received <-ctxSignal.Done() log.Info("Cloud deploy mode: Shutdown signal received; exiting") }