config.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package config
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "github.com/spf13/viper"
  7. )
  8. const (
  9. ConfigDirName = ".letta-switchboard"
  10. ConfigFileName = "config"
  11. )
  12. // Config holds the CLI configuration
  13. type Config struct {
  14. APIKey string `mapstructure:"api_key"`
  15. BaseURL string `mapstructure:"base_url"`
  16. }
  17. // GetConfigDir returns the config directory path
  18. func GetConfigDir() (string, error) {
  19. home, err := os.UserHomeDir()
  20. if err != nil {
  21. return "", fmt.Errorf("failed to get home directory: %w", err)
  22. }
  23. return filepath.Join(home, ConfigDirName), nil
  24. }
  25. // InitConfig initializes the configuration
  26. func InitConfig() error {
  27. configDir, err := GetConfigDir()
  28. if err != nil {
  29. return err
  30. }
  31. // Create config directory if it doesn't exist
  32. if err := os.MkdirAll(configDir, 0755); err != nil {
  33. return fmt.Errorf("failed to create config directory: %w", err)
  34. }
  35. viper.SetConfigName(ConfigFileName)
  36. viper.SetConfigType("yaml")
  37. viper.AddConfigPath(configDir)
  38. // Set defaults
  39. viper.SetDefault("base_url", "https://letta--switchboard-api.modal.run")
  40. // Read config file if it exists
  41. if err := viper.ReadInConfig(); err != nil {
  42. if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
  43. return fmt.Errorf("failed to read config: %w", err)
  44. }
  45. }
  46. return nil
  47. }
  48. // Load loads the current configuration
  49. func Load() (*Config, error) {
  50. var cfg Config
  51. if err := viper.Unmarshal(&cfg); err != nil {
  52. return nil, fmt.Errorf("failed to unmarshal config: %w", err)
  53. }
  54. return &cfg, nil
  55. }
  56. // SetAPIKey sets the API key in the config
  57. func SetAPIKey(apiKey string) error {
  58. viper.Set("api_key", apiKey)
  59. return saveConfig()
  60. }
  61. // SetBaseURL sets the base URL in the config
  62. func SetBaseURL(baseURL string) error {
  63. viper.Set("base_url", baseURL)
  64. return saveConfig()
  65. }
  66. // saveConfig saves the current configuration to disk
  67. func saveConfig() error {
  68. configDir, err := GetConfigDir()
  69. if err != nil {
  70. return err
  71. }
  72. configPath := filepath.Join(configDir, ConfigFileName+".yaml")
  73. if err := viper.WriteConfigAs(configPath); err != nil {
  74. return fmt.Errorf("failed to write config: %w", err)
  75. }
  76. return nil
  77. }
  78. // Validate checks if the configuration is valid
  79. func (c *Config) Validate() error {
  80. if c.APIKey == "" {
  81. return fmt.Errorf("API key not set. Run 'letta-switchboard config set-api-key <key>'")
  82. }
  83. if c.BaseURL == "" {
  84. return fmt.Errorf("base URL not set. Run 'letta-switchboard config set-url <url>'")
  85. }
  86. return nil
  87. }