| 52 | } |
| 53 | |
| 54 | func NewAnthropic(cfg config.Anthropic, bedrockCfg *config.AWSBedrock) *Anthropic { |
| 55 | if cfg.Name == "" { |
| 56 | cfg.Name = config.ProviderAnthropic |
| 57 | } |
| 58 | if cfg.BaseURL == "" { |
| 59 | cfg.BaseURL = "https://api.anthropic.com/" |
| 60 | } |
| 61 | // Resolve centralized key configuration into KeyPool. |
| 62 | // Precedence: |
| 63 | // 1. cfg.KeyPool (explicit, highest priority). |
| 64 | // 2. cfg.Key (legacy single key). |
| 65 | // After this block cfg.Key is empty so it can only carry a |
| 66 | // BYOK X-Api-Key set per interception in CreateInterceptor. |
| 67 | // TODO(ssncferreira): simplify auth field resolution per |
| 68 | // https://github.com/coder/aibridge/issues/266. |
| 69 | if cfg.KeyPool == nil && cfg.Key != "" { |
| 70 | // keypool.New only fails on empty or duplicate keys, |
| 71 | // neither possible with a single non-empty key. |
| 72 | pool, err := keypool.New([]string{cfg.Key}, quartz.NewReal()) |
| 73 | if err != nil { |
| 74 | panic(fmt.Sprintf("anthropic provider: build single-key pool: %s", err)) |
| 75 | } |
| 76 | cfg.KeyPool = pool |
| 77 | } |
| 78 | cfg.Key = "" |
| 79 | if cfg.CircuitBreaker != nil { |
| 80 | cfg.CircuitBreaker.IsFailure = anthropicIsFailure |
| 81 | cfg.CircuitBreaker.OpenErrorResponse = anthropicOpenErrorResponse |
| 82 | } |
| 83 | |
| 84 | return &Anthropic{ |
| 85 | cfg: cfg, |
| 86 | bedrockCfg: bedrockCfg, |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | func (*Anthropic) Type() string { |
| 91 | return config.ProviderAnthropic |