From 99c9f3069cf7f523201f80f5b23ff25e95fe5596 Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Mon, 8 Sep 2025 22:36:44 +0800 Subject: [PATCH] Fixed bug #38 Add support for API key indexing in OpenAI compatibility clients - Updated `NewOpenAICompatibilityClient` to accept `apiKeyIndex` for managing multiple API keys. - Modified client instantiation loops to initialize one client per API key. - Adjusted client ID format to include `apiKeyIndex` for unique identification. - Removed API key rotation logic within `GetCurrentAPIKey`. - Updated `.gitignore` to include `AGENTS.md`. --- .gitignore | 1 + internal/client/openai-compatibility_client.go | 12 +++++++----- internal/cmd/run.go | 16 +++++++++------- internal/watcher/watcher.go | 14 ++++++++------ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index d6906ed5..ee4c3373 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ docs/* logs/* auths/* !auths/.gitkeep +AGENTS.md \ No newline at end of file diff --git a/internal/client/openai-compatibility_client.go b/internal/client/openai-compatibility_client.go index 0e9a08b4..ae2fc144 100644 --- a/internal/client/openai-compatibility_client.go +++ b/internal/client/openai-compatibility_client.go @@ -44,7 +44,7 @@ type OpenAICompatibilityClient struct { // Returns: // - *OpenAICompatibilityClient: A new OpenAI compatibility client instance. // - error: An error if the client creation fails. -func NewOpenAICompatibilityClient(cfg *config.Config, compatConfig *config.OpenAICompatibility) (*OpenAICompatibilityClient, error) { +func NewOpenAICompatibilityClient(cfg *config.Config, compatConfig *config.OpenAICompatibility, apiKeyIndex int) (*OpenAICompatibilityClient, error) { if compatConfig == nil { return nil, fmt.Errorf("compatibility configuration is required") } @@ -53,10 +53,14 @@ func NewOpenAICompatibilityClient(cfg *config.Config, compatConfig *config.OpenA return nil, fmt.Errorf("at least one API key is required for OpenAI compatibility provider: %s", compatConfig.Name) } + if len(compatConfig.APIKeys) <= apiKeyIndex { + return nil, fmt.Errorf("invalid API key index for OpenAI compatibility provider: %s", compatConfig.Name) + } + httpClient := util.SetProxy(cfg, &http.Client{}) // Generate unique client ID - clientID := fmt.Sprintf("openai-compatibility-%s-%d", compatConfig.Name, time.Now().UnixNano()) + clientID := fmt.Sprintf("openai-compatibility-%s-%d-%d", compatConfig.Name, apiKeyIndex, time.Now().UnixNano()) client := &OpenAICompatibilityClient{ ClientBase: ClientBase{ @@ -66,7 +70,7 @@ func NewOpenAICompatibilityClient(cfg *config.Config, compatConfig *config.OpenA modelQuotaExceeded: make(map[string]*time.Time), }, compatConfig: compatConfig, - currentAPIKeyIndex: 0, + currentAPIKeyIndex: apiKeyIndex, } // Initialize model registry @@ -134,8 +138,6 @@ func (c *OpenAICompatibilityClient) GetCurrentAPIKey() string { } key := c.compatConfig.APIKeys[c.currentAPIKeyIndex] - // Rotate to next key for load balancing - c.currentAPIKeyIndex = (c.currentAPIKeyIndex + 1) % len(c.compatConfig.APIKeys) return key } diff --git a/internal/cmd/run.go b/internal/cmd/run.go index 07b57d57..7cfaa155 100644 --- a/internal/cmd/run.go +++ b/internal/cmd/run.go @@ -335,14 +335,16 @@ func buildAPIKeyClients(cfg *config.Config) (map[string]interfaces.Client, int, if len(cfg.OpenAICompatibility) > 0 { for _, compatConfig := range cfg.OpenAICompatibility { - log.Debugf("Initializing OpenAI compatibility client for provider: %s", compatConfig.Name) - compatClient, errClient := client.NewOpenAICompatibilityClient(cfg, &compatConfig) - if errClient != nil { - log.Errorf("failed to create OpenAI compatibility client for %s: %v", compatConfig.Name, errClient) - continue + for i := 0; i < len(compatConfig.APIKeys); i++ { + log.Debugf("Initializing OpenAI compatibility client for provider: %s", compatConfig.Name) + compatClient, errClient := client.NewOpenAICompatibilityClient(cfg, &compatConfig, i) + if errClient != nil { + log.Errorf("failed to create OpenAI compatibility client for %s: %v", compatConfig.Name, errClient) + continue + } + apiKeyClients[compatClient.GetClientID()] = compatClient + openAICompatCount++ } - apiKeyClients[compatClient.GetClientID()] = compatClient - openAICompatCount++ } } diff --git a/internal/watcher/watcher.go b/internal/watcher/watcher.go index 78d17af4..b8750017 100644 --- a/internal/watcher/watcher.go +++ b/internal/watcher/watcher.go @@ -549,13 +549,15 @@ func buildAPIKeyClients(cfg *config.Config) (map[string]interfaces.Client, int, } if len(cfg.OpenAICompatibility) > 0 { for _, compatConfig := range cfg.OpenAICompatibility { - compatClient, errClient := client.NewOpenAICompatibilityClient(cfg, &compatConfig) - if errClient != nil { - log.Errorf("failed to create OpenAI-compatibility client for %s: %v", compatConfig.Name, errClient) - continue + for i := 0; i < len(compatConfig.APIKeys); i++ { + compatClient, errClient := client.NewOpenAICompatibilityClient(cfg, &compatConfig, i) + if errClient != nil { + log.Errorf("failed to create OpenAI-compatibility client for %s: %v", compatConfig.Name, errClient) + continue + } + apiKeyClients[compatClient.GetClientID()] = compatClient + openAICompatCount++ } - apiKeyClients[compatClient.GetClientID()] = compatClient - openAICompatCount++ } } return apiKeyClients, glAPIKeyCount, claudeAPIKeyCount, codexAPIKeyCount, openAICompatCount