mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor: separate aibridge provider and interceptor configs (#26092)
## Description Separates the aibridge provider configuration from the per-request configuration an interceptor actually needs, and introduces a single `Credential` type that each provider resolves per request. Previously a provider handed its full config to the interceptor (including fields the interceptor didn't use) while other request data was passed as loose arguments, and authentication was spread across config fields and arguments. ## Changes - Add `intercept.Config`: the per-request, provider-agnostic configuration an interceptor needs (`ProviderName`, `BaseURL`, `APIDumpDir`, `SendActorHeaders`). - Introduce a single `Credential` interface (`BYOK` and `Centralized`) that each provider resolves per request in `resolveCredential`, and have interceptors route on the credential kind. - Fail fast with `ErrNoCredential` when a request is neither BYOK nor backed by a centralized key pool. - Remove unused provider config fields (`Key`, `BYOKBearerToken`, `ExtraHeaders`). Closes: coder/aibridge#266 Closes: https://linear.app/codercom/issue/AIGOV-221/refactor-separate-provider-and-interceptor-configs > [!NOTE] > Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
This commit is contained in:
@@ -18,14 +18,24 @@ import (
|
||||
"cdr.dev/slog/v3/sloggers/slogtest"
|
||||
"github.com/coder/coder/v2/aibridge"
|
||||
"github.com/coder/coder/v2/aibridge/intercept"
|
||||
"github.com/coder/coder/v2/aibridge/keypool"
|
||||
agplaibridge "github.com/coder/coder/v2/coderd/aibridge"
|
||||
"github.com/coder/coder/v2/coderd/aibridged"
|
||||
mock "github.com/coder/coder/v2/coderd/aibridged/aibridgedmock"
|
||||
"github.com/coder/coder/v2/coderd/aibridged/proto"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
"github.com/coder/quartz"
|
||||
)
|
||||
|
||||
// singleKeyPool builds a centralized key pool containing a single key.
|
||||
func singleKeyPool(t *testing.T, name, key string) *keypool.Pool {
|
||||
t.Helper()
|
||||
pool, err := keypool.New(name, []string{key}, quartz.NewReal(), nil)
|
||||
require.NoError(t, err)
|
||||
return pool
|
||||
}
|
||||
|
||||
func newTestServer(t *testing.T) (*aibridged.Server, *mock.MockDRPCClient, *mock.MockPooler) {
|
||||
t.Helper()
|
||||
|
||||
@@ -646,10 +656,12 @@ func TestServeHTTP_ActorHeaders(t *testing.T) {
|
||||
providers := []aibridge.Provider{
|
||||
aibridge.NewOpenAIProvider(aibridge.OpenAIConfig{
|
||||
BaseURL: upstreamSrv.URL,
|
||||
KeyPool: singleKeyPool(t, "openai", "test-key"),
|
||||
SendActorHeaders: true,
|
||||
}),
|
||||
aibridge.NewAnthropicProvider(aibridge.AnthropicConfig{
|
||||
BaseURL: upstreamSrv.URL,
|
||||
KeyPool: singleKeyPool(t, "anthropic", "test-key"),
|
||||
SendActorHeaders: true,
|
||||
}, nil),
|
||||
}
|
||||
@@ -753,8 +765,8 @@ func TestRouting(t *testing.T) {
|
||||
client := mock.NewMockDRPCClient(ctrl)
|
||||
|
||||
providers := []aibridge.Provider{
|
||||
aibridge.NewOpenAIProvider(aibridge.OpenAIConfig{BaseURL: openaiSrv.URL}),
|
||||
aibridge.NewAnthropicProvider(aibridge.AnthropicConfig{BaseURL: antSrv.URL}, nil),
|
||||
aibridge.NewOpenAIProvider(aibridge.OpenAIConfig{BaseURL: openaiSrv.URL, KeyPool: singleKeyPool(t, "openai", "test-key")}),
|
||||
aibridge.NewAnthropicProvider(aibridge.AnthropicConfig{BaseURL: antSrv.URL, KeyPool: singleKeyPool(t, "anthropic", "test-key")}, nil),
|
||||
}
|
||||
pool, err := aibridged.NewCachedBridgePool(aibridged.DefaultPoolOptions, providers, logger, nil, testTracer)
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user