| package synthesizer |
|
|
| import ( |
| "fmt" |
| "strconv" |
| "strings" |
|
|
| "github.com/router-for-me/CLIProxyAPI/v6/internal/watcher/diff" |
| coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" |
| ) |
|
|
| |
| |
| type ConfigSynthesizer struct{} |
|
|
| |
| func NewConfigSynthesizer() *ConfigSynthesizer { |
| return &ConfigSynthesizer{} |
| } |
|
|
| |
| func (s *ConfigSynthesizer) Synthesize(ctx *SynthesisContext) ([]*coreauth.Auth, error) { |
| out := make([]*coreauth.Auth, 0, 32) |
| if ctx == nil || ctx.Config == nil { |
| return out, nil |
| } |
|
|
| |
| out = append(out, s.synthesizeGeminiKeys(ctx)...) |
| |
| out = append(out, s.synthesizeClaudeKeys(ctx)...) |
| |
| out = append(out, s.synthesizeCodexKeys(ctx)...) |
| |
| out = append(out, s.synthesizeOpenAICompat(ctx)...) |
| |
| out = append(out, s.synthesizeVertexCompat(ctx)...) |
| |
| out = append(out, s.synthesizeKiroKeys(ctx)...) |
|
|
| return out, nil |
| } |
|
|
| |
| func (s *ConfigSynthesizer) synthesizeKiroKeys(ctx *SynthesisContext) []*coreauth.Auth { |
| cfg := ctx.Config |
| now := ctx.Now |
| idGen := ctx.IDGenerator |
|
|
| out := make([]*coreauth.Auth, 0, len(cfg.KiroKey)) |
| for i := range cfg.KiroKey { |
| entry := cfg.KiroKey[i] |
| token := strings.TrimSpace(entry.RefreshToken) |
| if token == "" { |
| continue |
| } |
| prefix := strings.TrimSpace(entry.Prefix) |
| proxyURL := strings.TrimSpace(entry.ProxyURL) |
|
|
| id, suffix := idGen.Next("kiro:apikey", token) |
|
|
| |
| metadata := map[string]any{ |
| "refresh_token": token, |
| } |
| if entry.ProfileARN != "" { |
| metadata["profile_arn"] = strings.TrimSpace(entry.ProfileARN) |
| } |
| if entry.Region != "" { |
| metadata["region"] = strings.TrimSpace(entry.Region) |
| } |
| if entry.CredentialsFile != "" { |
| metadata["credentials_file"] = strings.TrimSpace(entry.CredentialsFile) |
| } |
| if entry.KiroCliDBFile != "" { |
| metadata["kiro_cli_db_file"] = strings.TrimSpace(entry.KiroCliDBFile) |
| } |
|
|
| attrs := map[string]string{ |
| "source": fmt.Sprintf("config:kiro[%s]", suffix), |
| } |
| if entry.Priority != 0 { |
| attrs["priority"] = strconv.Itoa(entry.Priority) |
| } |
| addConfigHeadersToAttrs(entry.Headers, attrs) |
|
|
| a := &coreauth.Auth{ |
| ID: id, |
| Provider: "kiro", |
| Label: "kiro-apikey", |
| Prefix: prefix, |
| Status: coreauth.StatusActive, |
| ProxyURL: proxyURL, |
| Attributes: attrs, |
| Metadata: metadata, |
| CreatedAt: now, |
| UpdatedAt: now, |
| } |
| ApplyAuthExcludedModelsMeta(a, cfg, entry.ExcludedModels, "apikey") |
| out = append(out, a) |
| } |
| return out |
| } |
|
|
| |
| func (s *ConfigSynthesizer) synthesizeGeminiKeys(ctx *SynthesisContext) []*coreauth.Auth { |
| cfg := ctx.Config |
| now := ctx.Now |
| idGen := ctx.IDGenerator |
|
|
| out := make([]*coreauth.Auth, 0, len(cfg.GeminiKey)) |
| for i := range cfg.GeminiKey { |
| entry := cfg.GeminiKey[i] |
| key := strings.TrimSpace(entry.APIKey) |
| if key == "" { |
| continue |
| } |
| prefix := strings.TrimSpace(entry.Prefix) |
| base := strings.TrimSpace(entry.BaseURL) |
| proxyURL := strings.TrimSpace(entry.ProxyURL) |
| id, token := idGen.Next("gemini:apikey", key, base) |
| attrs := map[string]string{ |
| "source": fmt.Sprintf("config:gemini[%s]", token), |
| "api_key": key, |
| } |
| if entry.Priority != 0 { |
| attrs["priority"] = strconv.Itoa(entry.Priority) |
| } |
| if base != "" { |
| attrs["base_url"] = base |
| } |
| if hash := diff.ComputeGeminiModelsHash(entry.Models); hash != "" { |
| attrs["models_hash"] = hash |
| } |
| addConfigHeadersToAttrs(entry.Headers, attrs) |
| a := &coreauth.Auth{ |
| ID: id, |
| Provider: "gemini", |
| Label: "gemini-apikey", |
| Prefix: prefix, |
| Status: coreauth.StatusActive, |
| ProxyURL: proxyURL, |
| Attributes: attrs, |
| CreatedAt: now, |
| UpdatedAt: now, |
| } |
| ApplyAuthExcludedModelsMeta(a, cfg, entry.ExcludedModels, "apikey") |
| out = append(out, a) |
| } |
| return out |
| } |
|
|
| |
| func (s *ConfigSynthesizer) synthesizeClaudeKeys(ctx *SynthesisContext) []*coreauth.Auth { |
| cfg := ctx.Config |
| now := ctx.Now |
| idGen := ctx.IDGenerator |
|
|
| out := make([]*coreauth.Auth, 0) |
| for i := range cfg.ClaudeKey { |
| ck := cfg.ClaudeKey[i] |
| prefix := strings.TrimSpace(ck.Prefix) |
| base := strings.TrimSpace(ck.BaseURL) |
|
|
| |
| createdEntries := 0 |
| for j := range ck.APIKeyEntries { |
| entry := &ck.APIKeyEntries[j] |
| key := strings.TrimSpace(entry.APIKey) |
| if key == "" { |
| continue |
| } |
| |
| proxyURL := strings.TrimSpace(entry.ProxyURL) |
| if proxyURL == "" { |
| proxyURL = strings.TrimSpace(ck.ProxyURL) |
| } |
|
|
| id, token := idGen.Next("claude:apikey", key, base, proxyURL) |
| attrs := map[string]string{ |
| "source": fmt.Sprintf("config:claude[%s]", token), |
| "api_key": key, |
| } |
| if ck.Priority != 0 { |
| attrs["priority"] = strconv.Itoa(ck.Priority) |
| } |
| if base != "" { |
| attrs["base_url"] = base |
| } |
| if hash := diff.ComputeClaudeModelsHash(ck.Models); hash != "" { |
| attrs["models_hash"] = hash |
| } |
| addConfigHeadersToAttrs(ck.Headers, attrs) |
| a := &coreauth.Auth{ |
| ID: id, |
| Provider: "claude", |
| Label: "claude-apikey", |
| Prefix: prefix, |
| Status: coreauth.StatusActive, |
| ProxyURL: proxyURL, |
| Attributes: attrs, |
| CreatedAt: now, |
| UpdatedAt: now, |
| } |
| ApplyAuthExcludedModelsMeta(a, cfg, ck.ExcludedModels, "apikey") |
| out = append(out, a) |
| createdEntries++ |
| } |
|
|
| |
| if createdEntries == 0 { |
| key := strings.TrimSpace(ck.APIKey) |
| if key == "" { |
| continue |
| } |
| proxyURL := strings.TrimSpace(ck.ProxyURL) |
| id, token := idGen.Next("claude:apikey", key, base, proxyURL) |
| attrs := map[string]string{ |
| "source": fmt.Sprintf("config:claude[%s]", token), |
| "api_key": key, |
| } |
| if ck.Priority != 0 { |
| attrs["priority"] = strconv.Itoa(ck.Priority) |
| } |
| if base != "" { |
| attrs["base_url"] = base |
| } |
| if hash := diff.ComputeClaudeModelsHash(ck.Models); hash != "" { |
| attrs["models_hash"] = hash |
| } |
| addConfigHeadersToAttrs(ck.Headers, attrs) |
| a := &coreauth.Auth{ |
| ID: id, |
| Provider: "claude", |
| Label: "claude-apikey", |
| Prefix: prefix, |
| Status: coreauth.StatusActive, |
| ProxyURL: proxyURL, |
| Attributes: attrs, |
| CreatedAt: now, |
| UpdatedAt: now, |
| } |
| ApplyAuthExcludedModelsMeta(a, cfg, ck.ExcludedModels, "apikey") |
| out = append(out, a) |
| } |
| } |
| return out |
| } |
|
|
| |
| func (s *ConfigSynthesizer) synthesizeCodexKeys(ctx *SynthesisContext) []*coreauth.Auth { |
| cfg := ctx.Config |
| now := ctx.Now |
| idGen := ctx.IDGenerator |
|
|
| out := make([]*coreauth.Auth, 0, len(cfg.CodexKey)) |
| for i := range cfg.CodexKey { |
| ck := cfg.CodexKey[i] |
| key := strings.TrimSpace(ck.APIKey) |
| if key == "" { |
| continue |
| } |
| prefix := strings.TrimSpace(ck.Prefix) |
| id, token := idGen.Next("codex:apikey", key, ck.BaseURL) |
| attrs := map[string]string{ |
| "source": fmt.Sprintf("config:codex[%s]", token), |
| "api_key": key, |
| } |
| if ck.Priority != 0 { |
| attrs["priority"] = strconv.Itoa(ck.Priority) |
| } |
| if ck.BaseURL != "" { |
| attrs["base_url"] = ck.BaseURL |
| } |
| if hash := diff.ComputeCodexModelsHash(ck.Models); hash != "" { |
| attrs["models_hash"] = hash |
| } |
| addConfigHeadersToAttrs(ck.Headers, attrs) |
| proxyURL := strings.TrimSpace(ck.ProxyURL) |
| a := &coreauth.Auth{ |
| ID: id, |
| Provider: "codex", |
| Label: "codex-apikey", |
| Prefix: prefix, |
| Status: coreauth.StatusActive, |
| ProxyURL: proxyURL, |
| Attributes: attrs, |
| CreatedAt: now, |
| UpdatedAt: now, |
| } |
| ApplyAuthExcludedModelsMeta(a, cfg, ck.ExcludedModels, "apikey") |
| out = append(out, a) |
| } |
| return out |
| } |
|
|
| |
| func (s *ConfigSynthesizer) synthesizeOpenAICompat(ctx *SynthesisContext) []*coreauth.Auth { |
| cfg := ctx.Config |
| now := ctx.Now |
| idGen := ctx.IDGenerator |
|
|
| out := make([]*coreauth.Auth, 0) |
| for i := range cfg.OpenAICompatibility { |
| compat := &cfg.OpenAICompatibility[i] |
| prefix := strings.TrimSpace(compat.Prefix) |
| providerName := strings.ToLower(strings.TrimSpace(compat.Name)) |
| if providerName == "" { |
| providerName = "openai-compatibility" |
| } |
| base := strings.TrimSpace(compat.BaseURL) |
|
|
| |
| createdEntries := 0 |
| for j := range compat.APIKeyEntries { |
| entry := &compat.APIKeyEntries[j] |
| key := strings.TrimSpace(entry.APIKey) |
| proxyURL := strings.TrimSpace(entry.ProxyURL) |
| idKind := fmt.Sprintf("openai-compatibility:%s", providerName) |
| id, token := idGen.Next(idKind, key, base, proxyURL) |
| attrs := map[string]string{ |
| "source": fmt.Sprintf("config:%s[%s]", providerName, token), |
| "base_url": base, |
| "compat_name": compat.Name, |
| "provider_key": providerName, |
| } |
| if compat.Priority != 0 { |
| attrs["priority"] = strconv.Itoa(compat.Priority) |
| } |
| if key != "" { |
| attrs["api_key"] = key |
| } |
| if hash := diff.ComputeOpenAICompatModelsHash(compat.Models); hash != "" { |
| attrs["models_hash"] = hash |
| } |
| addConfigHeadersToAttrs(compat.Headers, attrs) |
| a := &coreauth.Auth{ |
| ID: id, |
| Provider: providerName, |
| Label: compat.Name, |
| Prefix: prefix, |
| Status: coreauth.StatusActive, |
| ProxyURL: proxyURL, |
| Attributes: attrs, |
| CreatedAt: now, |
| UpdatedAt: now, |
| } |
| out = append(out, a) |
| createdEntries++ |
| } |
| |
| if createdEntries == 0 { |
| idKind := fmt.Sprintf("openai-compatibility:%s", providerName) |
| id, token := idGen.Next(idKind, base) |
| attrs := map[string]string{ |
| "source": fmt.Sprintf("config:%s[%s]", providerName, token), |
| "base_url": base, |
| "compat_name": compat.Name, |
| "provider_key": providerName, |
| } |
| if compat.Priority != 0 { |
| attrs["priority"] = strconv.Itoa(compat.Priority) |
| } |
| if hash := diff.ComputeOpenAICompatModelsHash(compat.Models); hash != "" { |
| attrs["models_hash"] = hash |
| } |
| addConfigHeadersToAttrs(compat.Headers, attrs) |
| a := &coreauth.Auth{ |
| ID: id, |
| Provider: providerName, |
| Label: compat.Name, |
| Prefix: prefix, |
| Status: coreauth.StatusActive, |
| Attributes: attrs, |
| CreatedAt: now, |
| UpdatedAt: now, |
| } |
| out = append(out, a) |
| } |
| } |
| return out |
| } |
|
|
| |
| func (s *ConfigSynthesizer) synthesizeVertexCompat(ctx *SynthesisContext) []*coreauth.Auth { |
| cfg := ctx.Config |
| now := ctx.Now |
| idGen := ctx.IDGenerator |
|
|
| out := make([]*coreauth.Auth, 0, len(cfg.VertexCompatAPIKey)) |
| for i := range cfg.VertexCompatAPIKey { |
| compat := &cfg.VertexCompatAPIKey[i] |
| providerName := "vertex" |
| base := strings.TrimSpace(compat.BaseURL) |
|
|
| key := strings.TrimSpace(compat.APIKey) |
| prefix := strings.TrimSpace(compat.Prefix) |
| proxyURL := strings.TrimSpace(compat.ProxyURL) |
| idKind := "vertex:apikey" |
| id, token := idGen.Next(idKind, key, base, proxyURL) |
| attrs := map[string]string{ |
| "source": fmt.Sprintf("config:vertex-apikey[%s]", token), |
| "base_url": base, |
| "provider_key": providerName, |
| } |
| if compat.Priority != 0 { |
| attrs["priority"] = strconv.Itoa(compat.Priority) |
| } |
| if key != "" { |
| attrs["api_key"] = key |
| } |
| if hash := diff.ComputeVertexCompatModelsHash(compat.Models); hash != "" { |
| attrs["models_hash"] = hash |
| } |
| addConfigHeadersToAttrs(compat.Headers, attrs) |
| a := &coreauth.Auth{ |
| ID: id, |
| Provider: providerName, |
| Label: "vertex-apikey", |
| Prefix: prefix, |
| Status: coreauth.StatusActive, |
| ProxyURL: proxyURL, |
| Attributes: attrs, |
| CreatedAt: now, |
| UpdatedAt: now, |
| } |
| ApplyAuthExcludedModelsMeta(a, cfg, nil, "apikey") |
| out = append(out, a) |
| } |
| return out |
| } |
|
|