// Package usecase provides application use cases that orchestrate domain services. package usecase import ( "context" "github.com/router-for-me/CLIProxyAPI/v6/internal/application/dto" "github.com/router-for-me/CLIProxyAPI/v6/internal/application/mapper" "github.com/router-for-me/CLIProxyAPI/v6/internal/domain/errors" "github.com/router-for-me/CLIProxyAPI/v6/internal/domain/ports" ) // Logger interface for logging type Logger interface { Debug(ctx context.Context, message string) Info(ctx context.Context, message string) Warn(ctx context.Context, message string) Error(ctx context.Context, message string, err error) Debugf(ctx context.Context, format string, args ...interface{}) Infof(ctx context.Context, format string, args ...interface{}) } // ConfigUseCase orchestrates configuration-related operations type ConfigUseCase struct { configService ports.ConfigService logger Logger } // NewConfigUseCase creates a new ConfigUseCase func NewConfigUseCase(configService ports.ConfigService, logger Logger) *ConfigUseCase { return &ConfigUseCase{ configService: configService, logger: logger, } } // GetConfig retrieves the current configuration func (uc *ConfigUseCase) GetConfig(ctx context.Context) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: getting config") } cfg, err := uc.configService.GetConfig(ctx) if err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to get config", err) } return nil, err } return mapper.ToConfigResponse(cfg), nil } // GetConfigYAML retrieves the raw configuration as YAML bytes func (uc *ConfigUseCase) GetConfigYAML(ctx context.Context) ([]byte, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: getting config YAML") } // This would need to be implemented in the repository // For now, return an error indicating not implemented return nil, errors.New(errors.InternalError, "GetConfigYAML not implemented in use case") } // UpdateConfig updates the entire configuration func (uc *ConfigUseCase) UpdateConfig(ctx context.Context, req *dto.UpdateConfigRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating config") } if req == nil { return nil, errors.New(errors.InvalidInput, "request is nil") } cfg := mapper.ToConfig(req) if err := uc.configService.UpdateConfig(ctx, cfg); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update config", err) } return nil, err } return mapper.ToConfigResponse(cfg), nil } // UpdateField updates a single configuration field func (uc *ConfigUseCase) UpdateField(ctx context.Context, field string, value interface{}) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating field %s", field) } if err := uc.configService.UpdateField(ctx, field, value); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update field", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateAPIKeys updates the API keys func (uc *ConfigUseCase) UpdateAPIKeys(ctx context.Context, req *dto.UpdateAPIKeysRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating API keys") } if err := uc.configService.UpdateAPIKeys(ctx, req.Keys); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update API keys", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateGeminiKeys updates the Gemini keys func (uc *ConfigUseCase) UpdateGeminiKeys(ctx context.Context, req *dto.UpdateGeminiKeysRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating Gemini keys") } if err := uc.configService.UpdateGeminiKeys(ctx, req.Keys); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update Gemini keys", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateClaudeKeys updates the Claude keys func (uc *ConfigUseCase) UpdateClaudeKeys(ctx context.Context, req *dto.UpdateClaudeKeysRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating Claude keys") } if err := uc.configService.UpdateClaudeKeys(ctx, req.Keys); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update Claude keys", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateCodexKeys updates the Codex keys func (uc *ConfigUseCase) UpdateCodexKeys(ctx context.Context, req *dto.UpdateCodexKeysRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating Codex keys") } if err := uc.configService.UpdateCodexKeys(ctx, req.Keys); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update Codex keys", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateOpenAICompatibility updates the OpenAI compatibility entries func (uc *ConfigUseCase) UpdateOpenAICompatibility(ctx context.Context, req *dto.UpdateOpenAICompatRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating OpenAI compatibility") } if err := uc.configService.UpdateOpenAICompatibility(ctx, req.Entries); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update OpenAI compatibility", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateVertexCompatKeys updates the Vertex compatibility keys func (uc *ConfigUseCase) UpdateVertexCompatKeys(ctx context.Context, req *dto.UpdateVertexCompatKeysRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating Vertex compatibility keys") } if err := uc.configService.UpdateVertexCompatKeys(ctx, req.Keys); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update Vertex compatibility keys", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateKiroKeys updates the Kiro keys func (uc *ConfigUseCase) UpdateKiroKeys(ctx context.Context, req *dto.UpdateKiroKeysRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating Kiro keys") } if err := uc.configService.UpdateKiroKeys(ctx, req.Keys); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update Kiro keys", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateOAuthExcludedModels updates OAuth excluded models func (uc *ConfigUseCase) UpdateOAuthExcludedModels(ctx context.Context, req *dto.UpdateOAuthExcludedModelsRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating OAuth excluded models") } if err := uc.configService.UpdateOAuthExcludedModels(ctx, req.Models); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update OAuth excluded models", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateOAuthModelAlias updates OAuth model aliases func (uc *ConfigUseCase) UpdateOAuthModelAlias(ctx context.Context, req *dto.UpdateOAuthModelAliasRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating OAuth model aliases") } if err := uc.configService.UpdateOAuthModelAlias(ctx, req.Aliases); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update OAuth model aliases", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateAmpCode updates the AmpCode configuration func (uc *ConfigUseCase) UpdateAmpCode(ctx context.Context, req *dto.UpdateAmpCodeRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating AmpCode") } if err := uc.configService.UpdateAmpCode(ctx, req.AmpCode); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update AmpCode", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateAmpUpstreamURL updates the Amp upstream URL func (uc *ConfigUseCase) UpdateAmpUpstreamURL(ctx context.Context, url string) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating Amp upstream URL") } if err := uc.configService.UpdateAmpUpstreamURL(ctx, url); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update Amp upstream URL", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateAmpModelMappings updates Amp model mappings func (uc *ConfigUseCase) UpdateAmpModelMappings(ctx context.Context, req *dto.UpdateAmpModelMappingsRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating Amp model mappings") } if err := uc.configService.UpdateAmpModelMappings(ctx, req.Mappings); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update Amp model mappings", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateAmpUpstreamAPIKeys updates Amp upstream API keys func (uc *ConfigUseCase) UpdateAmpUpstreamAPIKeys(ctx context.Context, req *dto.UpdateAmpUpstreamAPIKeysRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating Amp upstream API keys") } if err := uc.configService.UpdateAmpUpstreamAPIKeys(ctx, req.Keys); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update Amp upstream API keys", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateDebug updates the debug setting func (uc *ConfigUseCase) UpdateDebug(ctx context.Context, enabled bool) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating debug to %v", enabled) } if err := uc.configService.UpdateDebug(ctx, enabled); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update debug", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateUsageStatisticsEnabled updates the usage statistics enabled setting func (uc *ConfigUseCase) UpdateUsageStatisticsEnabled(ctx context.Context, enabled bool) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating usage statistics enabled to %v", enabled) } if err := uc.configService.UpdateUsageStatisticsEnabled(ctx, enabled); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update usage statistics enabled", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateLoggingToFile updates the logging to file setting func (uc *ConfigUseCase) UpdateLoggingToFile(ctx context.Context, enabled bool) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating logging to file to %v", enabled) } if err := uc.configService.UpdateLoggingToFile(ctx, enabled); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update logging to file", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateLogsMaxTotalSizeMB updates the max log size func (uc *ConfigUseCase) UpdateLogsMaxTotalSizeMB(ctx context.Context, sizeMB int) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating logs max total size to %d MB", sizeMB) } if err := uc.configService.UpdateLogsMaxTotalSizeMB(ctx, sizeMB); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update logs max total size", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateRequestLog updates the request log setting func (uc *ConfigUseCase) UpdateRequestLog(ctx context.Context, enabled bool) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating request log to %v", enabled) } if err := uc.configService.UpdateRequestLog(ctx, enabled); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update request log", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateWebsocketAuth updates the websocket auth setting func (uc *ConfigUseCase) UpdateWebsocketAuth(ctx context.Context, enabled bool) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating websocket auth to %v", enabled) } if err := uc.configService.UpdateWebsocketAuth(ctx, enabled); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update websocket auth", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateRequestRetry updates the request retry count func (uc *ConfigUseCase) UpdateRequestRetry(ctx context.Context, retry int) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating request retry to %d", retry) } if err := uc.configService.UpdateRequestRetry(ctx, retry); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update request retry", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateMaxRetryInterval updates the max retry interval func (uc *ConfigUseCase) UpdateMaxRetryInterval(ctx context.Context, interval int) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating max retry interval to %d", interval) } if err := uc.configService.UpdateMaxRetryInterval(ctx, interval); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update max retry interval", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateForceModelPrefix updates the force model prefix setting func (uc *ConfigUseCase) UpdateForceModelPrefix(ctx context.Context, enabled bool) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating force model prefix to %v", enabled) } if err := uc.configService.UpdateForceModelPrefix(ctx, enabled); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update force model prefix", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateRoutingStrategy updates the routing strategy func (uc *ConfigUseCase) UpdateRoutingStrategy(ctx context.Context, strategy string) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating routing strategy to %s", strategy) } if err := uc.configService.UpdateRoutingStrategy(ctx, strategy); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update routing strategy", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateProxyURL updates the proxy URL func (uc *ConfigUseCase) UpdateProxyURL(ctx context.Context, url string) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debugf(ctx, "usecase: updating proxy URL to %s", url) } if err := uc.configService.UpdateProxyURL(ctx, url); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update proxy URL", err) } return nil, err } return uc.GetConfig(ctx) } // DeleteProxyURL clears the proxy URL func (uc *ConfigUseCase) DeleteProxyURL(ctx context.Context) (*dto.ConfigResponse, error) { return uc.UpdateProxyURL(ctx, "") } // UpdateRemoteManagement updates the remote management settings func (uc *ConfigUseCase) UpdateRemoteManagement(ctx context.Context, req *dto.UpdateRemoteManagementRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating remote management settings") } if err := uc.configService.UpdateRemoteManagement(ctx, req.AllowRemote, req.SecretHash); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update remote management settings", err) } return nil, err } return uc.GetConfig(ctx) } // UpdateQuotaExceeded updates the quota exceeded settings func (uc *ConfigUseCase) UpdateQuotaExceeded(ctx context.Context, req *dto.UpdateQuotaExceededRequest) (*dto.ConfigResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: updating quota exceeded settings") } if err := uc.configService.UpdateQuotaExceeded(ctx, req.SwitchProject, req.SwitchPreviewModel); err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to update quota exceeded settings", err) } return nil, err } return uc.GetConfig(ctx) } // GetLatestVersion retrieves the latest version from GitHub func (uc *ConfigUseCase) GetLatestVersion(ctx context.Context) (*dto.VersionResponse, error) { if uc.logger != nil { uc.logger.Debug(ctx, "usecase: getting latest version") } version, err := uc.configService.GetLatestVersion(ctx) if err != nil { if uc.logger != nil { uc.logger.Error(ctx, "usecase: failed to get latest version", err) } return nil, err } return &dto.VersionResponse{ LatestVersion: version, }, nil }