test: migrate chatd tests to AI Gateway routing (#26658)

Refs CODAGT-681

Migrates all chatd tests from `AIGatewayRoutingEnabled = false` (direct
routing) to AI Gateway routing using the test helpers extracted in
#26639.

- `coderd/x/chatd/chatd_test.go` — 6 full-server tests migrated to
`NewWithAPI` + daemon, `directChatRoutingDeploymentValues` helper
deleted, 3 bare-chatd tests renamed
- `coderd/x/chatd/context_integration_test.go` — 2 tests migrated
- `coderd/exp_chats_test.go` — `chatDeploymentValues` helper deleted,
all 5 helper functions now use `NewWithAPI` + daemon internally (no call
site changes)
- `coderd/exp_chats_acl_test.go` — stale `chatDeploymentValues`
reference replaced
- `enterprise/coderd/exp_chats_test.go` — 9 sites across 5
`TestChatStreamRelay` subtests migrated
- `cli/exp_scaletest_chat_test.go` — 1 test migrated
- `coderd/x/chatd/model_routing_internal_test.go` — 1 direct-only test
removed
- `coderd/x/chatd/chatd_internal_test.go` — 1 direct-only test removed

> 🤖
This commit is contained in:
Cian Johnston
2026-06-30 12:17:42 +01:00
committed by GitHub
parent 33780758c1
commit e5b7e74847
8 changed files with 210 additions and 182 deletions
+1 -1
View File
@@ -465,7 +465,7 @@ func TestChatSharingDisabled(t *testing.T) {
})
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.DisableChatSharing = true
store, pubsub := dbtestutil.NewDB(t)
client := newChatClient(t, func(opts *coderdtest.Options) {
+85 -51
View File
@@ -25,8 +25,10 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"cdr.dev/slog/v3/sloggers/slogtest"
"github.com/coder/coder/v2/coderd"
"github.com/coder/coder/v2/coderd/aibridge"
"github.com/coder/coder/v2/coderd/aibridgedtest"
"github.com/coder/coder/v2/coderd/audit"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
@@ -56,14 +58,6 @@ const (
missingCentralKeyMessage = "API key is required when central API key is enabled."
)
func chatDeploymentValues(t testing.TB) *codersdk.DeploymentValues {
t.Helper()
values := coderdtest.DeploymentValues(t)
require.NoError(t, values.AI.Chat.AIGatewayRoutingEnabled.Set("false"))
return values
}
// newChatTestOptions builds coderdtest options for chat runtime tests. Unless
// a test sets ChatProviderAPIKeys explicitly, it installs a fake
// OpenAI-compatible provider before coderd starts so background chat work stays
@@ -91,16 +85,18 @@ func newChatTestOptions(
func newChatClient(t testing.TB, overrides ...func(*coderdtest.Options)) *codersdk.ExperimentalClient {
t.Helper()
opts := newChatTestOptions(t, chatDeploymentValues(t), overrides...)
client := coderdtest.New(t, opts)
opts := newChatTestOptions(t, coderdtest.DeploymentValues(t), overrides...)
client, _, api := coderdtest.NewWithAPI(t, opts)
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
return codersdk.NewExperimentalClient(client)
}
func newChatClientWithAPI(t testing.TB, overrides ...func(*coderdtest.Options)) (*codersdk.ExperimentalClient, *coderd.API) {
t.Helper()
opts := newChatTestOptions(t, chatDeploymentValues(t), overrides...)
opts := newChatTestOptions(t, coderdtest.DeploymentValues(t), overrides...)
client, _, api := coderdtest.NewWithAPI(t, opts)
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
return codersdk.NewExperimentalClient(client), api
}
@@ -111,23 +107,26 @@ func newChatClientWithDeploymentValues(
t.Helper()
opts := newChatTestOptions(t, values)
client := coderdtest.New(t, opts)
client, _, api := coderdtest.NewWithAPI(t, opts)
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
return codersdk.NewExperimentalClient(client)
}
func newChatClientWithDatabase(t testing.TB, overrides ...func(*coderdtest.Options)) (*codersdk.ExperimentalClient, database.Store) {
t.Helper()
opts := newChatTestOptions(t, chatDeploymentValues(t), overrides...)
client, db := coderdtest.NewWithDatabase(t, opts)
return codersdk.NewExperimentalClient(client), db
opts := newChatTestOptions(t, coderdtest.DeploymentValues(t), overrides...)
client, _, api := coderdtest.NewWithAPI(t, opts)
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
return codersdk.NewExperimentalClient(client), api.Database
}
func newChatClientWithAPIAndDatabase(t testing.TB, overrides ...func(*coderdtest.Options)) (*codersdk.ExperimentalClient, database.Store, *coderd.API) {
t.Helper()
opts := newChatTestOptions(t, chatDeploymentValues(t), overrides...)
opts := newChatTestOptions(t, coderdtest.DeploymentValues(t), overrides...)
client, _, api := coderdtest.NewWithAPI(t, opts)
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
return codersdk.NewExperimentalClient(client), api.Database, api
}
@@ -1847,7 +1846,7 @@ func TestListChatModels(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.AI.BridgeConfig.LegacyOpenAI.Key = serpent.String("deployment-openai-key")
client := newChatClientWithDeploymentValues(t, values)
_ = coderdtest.CreateFirstUser(t, client.Client)
@@ -1974,8 +1973,9 @@ func TestWatchChats(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitLong)
rawClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: chatDeploymentValues(t),
DeploymentValues: coderdtest.DeploymentValues(t),
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(rawClient)
db := api.Database
chatDaemon := api.ChatDaemonForTest()
@@ -2312,9 +2312,16 @@ func TestUserAIProviderKeys(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.AI.BridgeConfig.AllowBYOK = serpent.Bool(false)
client := newChatClientWithDeploymentValues(t, values)
// The aibridged reloader logs at error level when it sees a provider
// configured with no API key and BYOK disabled. That state is the
// scenario under test, so suppress its error logs here.
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
client := newChatClient(t, func(o *coderdtest.Options) {
o.DeploymentValues = values
o.Logger = &logger
})
_ = coderdtest.CreateFirstUser(t, client.Client)
provider := createOpenAIProvider(t, client, "test-byok-disabled-"+uuid.NewString(), true)
@@ -2364,7 +2371,7 @@ func TestListChatProviders(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.AI.BridgeConfig.LegacyOpenAI.Key = serpent.String("deployment-openai-key")
client := newChatClientWithDeploymentValues(t, values)
_ = coderdtest.CreateFirstUser(t, client.Client)
@@ -2613,7 +2620,7 @@ func TestCreateChatProvider(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.AI.BridgeConfig.LegacyOpenAI.Key = serpent.String("deployment-openai-key")
client := newChatClientWithDeploymentValues(t, values)
_ = coderdtest.CreateFirstUser(t, client.Client)
@@ -2844,7 +2851,7 @@ func TestUpdateChatProvider(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.AI.BridgeConfig.LegacyOpenAI.Key = serpent.String("deployment-openai-key")
client := newChatClientWithDeploymentValues(t, values)
_ = coderdtest.CreateFirstUser(t, client.Client)
@@ -3007,7 +3014,7 @@ func TestChatProviderAPIKeysFromDeploymentValues(t *testing.T) {
t.Run("DoesNotReuseBridgeConfig", func(t *testing.T) {
t.Parallel()
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.AI.BridgeConfig.LegacyOpenAI.Key = serpent.String("deployment-openai-key")
values.AI.BridgeConfig.LegacyAnthropic.Key = serpent.String("deployment-anthropic-key")
values.AI.BridgeConfig.LegacyOpenAI.BaseURL = serpent.String("https://custom-openai.example.com")
@@ -3213,7 +3220,7 @@ func TestUserChatProviderConfigs(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.AI.BridgeConfig.LegacyOpenAI.Key = serpent.String("deployment-openai-key")
client := newChatClientWithDeploymentValues(t, values)
_ = coderdtest.CreateFirstUser(t, client.Client)
@@ -4259,11 +4266,13 @@ func TestUpdateChatModelConfig(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitLong)
rawDB, pubsub := dbtestutil.NewDB(t)
store := newFailNextUpdateChatModelConfigStore(rawDB)
client := codersdk.NewExperimentalClient(coderdtest.New(t, &coderdtest.Options{
rawClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
Database: store,
Pubsub: pubsub,
DeploymentValues: chatDeploymentValues(t),
}))
DeploymentValues: coderdtest.DeploymentValues(t),
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(rawClient)
_ = coderdtest.CreateFirstUser(t, client.Client)
modelConfig := createChatModelConfig(t, client)
@@ -4282,11 +4291,13 @@ func TestUpdateChatModelConfig(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitLong)
rawDB, pubsub := dbtestutil.NewDB(t)
store := newFailNextUpdateChatModelConfigStore(rawDB)
client := codersdk.NewExperimentalClient(coderdtest.New(t, &coderdtest.Options{
rawClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
Database: store,
Pubsub: pubsub,
DeploymentValues: chatDeploymentValues(t),
}))
DeploymentValues: coderdtest.DeploymentValues(t),
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(rawClient)
_ = coderdtest.CreateFirstUser(t, client.Client)
defaultConfig := createChatModelConfig(t, client)
@@ -5549,11 +5560,12 @@ func TestPatchChat(t *testing.T) {
db, ps, sqlDB := dbtestutil.NewDBWithSQLDB(t)
providerKeys := coderdtest.FakeOpenAICompatProviderAPIKeys(t)
clientRaw, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: chatDeploymentValues(t),
DeploymentValues: coderdtest.DeploymentValues(t),
Database: db,
Pubsub: ps,
ChatProviderAPIKeys: &providerKeys,
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(clientRaw)
firstUser := coderdtest.CreateFirstUser(t, client.Client)
_ = createChatModelConfig(t, client)
@@ -5586,11 +5598,12 @@ func TestPatchChat(t *testing.T) {
db, ps, sqlDB := dbtestutil.NewDBWithSQLDB(t)
providerKeys := coderdtest.FakeOpenAICompatProviderAPIKeys(t)
clientRaw, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: chatDeploymentValues(t),
DeploymentValues: coderdtest.DeploymentValues(t),
Database: db,
Pubsub: ps,
ChatProviderAPIKeys: &providerKeys,
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(clientRaw)
firstUser := coderdtest.CreateFirstUser(t, client.Client)
_ = createChatModelConfig(t, client)
@@ -8382,7 +8395,7 @@ func TestRegenerateChatTitle(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
clientRaw, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
clientRaw, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
Authorizer: &coderdtest.FakeAuthorizer{
ConditionalReturn: func(_ context.Context, _ rbac.Subject, action policy.Action, object rbac.Object) error {
if action == policy.ActionUpdate && object.Type == rbac.ResourceChat.Type {
@@ -8391,8 +8404,10 @@ func TestRegenerateChatTitle(t *testing.T) {
return nil
},
},
DeploymentValues: chatDeploymentValues(t),
DeploymentValues: coderdtest.DeploymentValues(t),
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
db := api.Database
client := codersdk.NewExperimentalClient(clientRaw)
user := coderdtest.CreateFirstUser(t, client.Client)
modelConfig := createChatModelConfig(t, client)
@@ -8651,7 +8666,7 @@ func TestProposeChatTitle(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
clientRaw, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
clientRaw, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
Authorizer: &coderdtest.FakeAuthorizer{
ConditionalReturn: func(_ context.Context, _ rbac.Subject, action policy.Action, object rbac.Object) error {
if action == policy.ActionUpdate && object.Type == rbac.ResourceChat.Type {
@@ -8660,8 +8675,10 @@ func TestProposeChatTitle(t *testing.T) {
return nil
},
},
DeploymentValues: chatDeploymentValues(t),
DeploymentValues: coderdtest.DeploymentValues(t),
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
db := api.Database
client := codersdk.NewExperimentalClient(clientRaw)
user := coderdtest.CreateFirstUser(t, client.Client)
modelConfig := createChatModelConfig(t, client)
@@ -8737,7 +8754,7 @@ func TestManualTitleEndpointsPassCallerAPIKeyToAIGateway(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
require.NoError(t, values.AI.BridgeConfig.Enabled.Set("true"))
require.NoError(t, values.AI.Chat.AIGatewayRoutingEnabled.Set("true"))
client, db, api := newChatClientWithAPIAndDatabase(t, func(opts *coderdtest.Options) {
@@ -8851,7 +8868,7 @@ func TestGetChatDiffStatus(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitLong)
rawClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: chatDeploymentValues(t),
DeploymentValues: coderdtest.DeploymentValues(t),
ExternalAuthConfigs: []*externalauth.Config{
{
ID: "gitlab-test",
@@ -8860,6 +8877,7 @@ func TestGetChatDiffStatus(t *testing.T) {
},
},
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(rawClient)
db := api.Database
@@ -8972,7 +8990,7 @@ func TestGetChatDiffContents(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitLong)
rawClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: chatDeploymentValues(t),
DeploymentValues: coderdtest.DeploymentValues(t),
ExternalAuthConfigs: []*externalauth.Config{
{
ID: "gitlab-test",
@@ -8981,6 +8999,7 @@ func TestGetChatDiffContents(t *testing.T) {
},
},
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(rawClient)
db := api.Database
user := coderdtest.CreateFirstUser(t, client.Client)
@@ -10773,10 +10792,19 @@ func createAIProviderForTest(
t.Helper()
ctx := testutil.Context(t, testutil.WaitLong)
baseURL := aiProviderBaseURLForTest(provider)
// AI Gateway routing uses the provider's BaseURL from the DB row.
// For OpenAI-compatible providers, use a real mock server so the
// daemon can route chat requests. Other provider types (anthropic,
// bedrock, google) are only used for model config CRUD tests that
// never process chats through the daemon.
if provider == "openai" || provider == "openai-compat" {
baseURL = chattest.OpenAI(t)
}
req := codersdk.CreateAIProviderRequest{
Type: codersdk.AIProviderType(provider),
Name: "test-" + provider + "-" + uuid.NewString(),
BaseURL: aiProviderBaseURLForTest(provider),
BaseURL: baseURL,
Enabled: true,
}
if apiKey != "" {
@@ -11023,11 +11051,13 @@ If a workspace is needed, use list_templates before create_workspace and follow
rawDB, pubsub := dbtestutil.NewDB(t)
store := &failNextChatSystemPromptStore{Store: rawDB}
client := codersdk.NewExperimentalClient(coderdtest.New(t, &coderdtest.Options{
rawClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
Database: store,
Pubsub: pubsub,
DeploymentValues: chatDeploymentValues(t),
}))
DeploymentValues: coderdtest.DeploymentValues(t),
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(rawClient)
_ = coderdtest.CreateFirstUser(t, client.Client)
_ = createChatModelConfig(t, client)
@@ -11191,11 +11221,13 @@ If a workspace is needed, use list_templates before create_workspace and follow
rawDB, pubsub := dbtestutil.NewDB(t)
store := &failNextChatSystemPromptStore{Store: rawDB}
client := codersdk.NewExperimentalClient(coderdtest.New(t, &coderdtest.Options{
rawClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
Database: store,
Pubsub: pubsub,
DeploymentValues: chatDeploymentValues(t),
}))
DeploymentValues: coderdtest.DeploymentValues(t),
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(rawClient)
firstUser := coderdtest.CreateFirstUser(t, client.Client)
_ = createChatModelConfig(t, client)
@@ -11238,11 +11270,13 @@ If a workspace is needed, use list_templates before create_workspace and follow
rawDB, pubsub := dbtestutil.NewDB(t)
store := &failNextChatSystemPromptStore{Store: rawDB}
client := codersdk.NewExperimentalClient(coderdtest.New(t, &coderdtest.Options{
rawClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
Database: store,
Pubsub: pubsub,
DeploymentValues: chatDeploymentValues(t),
}))
DeploymentValues: coderdtest.DeploymentValues(t),
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
client := codersdk.NewExperimentalClient(rawClient)
firstUser := coderdtest.CreateFirstUser(t, client.Client)
_ = createChatModelConfig(t, client)
@@ -12569,7 +12603,7 @@ func TestChatDebugLoggingSettings(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := chatDeploymentValues(t)
values := coderdtest.DeploymentValues(t)
values.AI.Chat.DebugLoggingEnabled = serpent.Bool(true)
adminClient := newChatClientWithDeploymentValues(t, values)
firstUser := coderdtest.CreateFirstUser(t, adminClient.Client)
-27
View File
@@ -141,33 +141,6 @@ func TestComputerUseProviderAndModelFromConfig(t *testing.T) {
}
}
func TestResolveComputerUseModel_OpenAIMissingCredentials(t *testing.T) {
t.Parallel()
server := &Server{}
provider := chattool.ComputerUseProviderOpenAI
modelProvider, modelName, ok := chattool.DefaultComputerUseModel(provider)
require.True(t, ok)
model, debugEnabled, resolvedProvider, resolvedModel, err := server.resolveComputerUseModel(
context.Background(),
database.Chat{ID: uuid.New(), OwnerID: uuid.New()},
newDirectModelRoute(modelProvider, chatprovider.ProviderAPIKeys{}),
provider,
modelProvider,
modelName,
modelBuildOptions{},
)
require.Error(t, err)
require.Nil(t, model)
require.False(t, debugEnabled)
require.Empty(t, resolvedProvider)
require.Empty(t, resolvedModel)
require.Contains(t, err.Error(), `provider "openai" model "gpt-5.5"`)
require.Contains(t, err.Error(), "OPENAI_API_KEY is not set")
require.NotContains(t, err.Error(), "ANTHROPIC_API_KEY")
}
func TestResolveUserProviderAPIKeysAndProviderForProviderTypeProviderMatch(t *testing.T) {
t.Parallel()
+24 -29
View File
@@ -37,6 +37,7 @@ import (
"github.com/coder/coder/v2/agent/agentcontextconfig"
"github.com/coder/coder/v2/agent/agenttest"
"github.com/coder/coder/v2/coderd/aibridge"
"github.com/coder/coder/v2/coderd/aibridgedtest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/db2sdk"
@@ -83,14 +84,6 @@ func chatAIGatewayTransportFactoryPointer(factory aibridge.TransportFactory) *at
return &ptr
}
func directChatRoutingDeploymentValues(t testing.TB) *codersdk.DeploymentValues {
t.Helper()
values := coderdtest.DeploymentValues(t)
require.NoError(t, values.AI.Chat.AIGatewayRoutingEnabled.Set("false"))
return values
}
func openAIToolName(tool chattest.OpenAITool) string {
return cmp.Or(tool.Function.Name, tool.Name, tool.Type)
}
@@ -202,11 +195,11 @@ func TestSubagentChatExcludesWorkspaceProvisioningTools(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
deploymentValues := directChatRoutingDeploymentValues(t)
client := coderdtest.New(t, &coderdtest.Options{
DeploymentValues: deploymentValues,
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
IncludeProvisionerDaemon: true,
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
user := coderdtest.CreateFirstUser(t, client)
expClient := codersdk.NewExperimentalClient(client)
@@ -359,11 +352,11 @@ func TestPlanModeSubagentChatExcludesAskUserQuestion(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
deploymentValues := directChatRoutingDeploymentValues(t)
client := coderdtest.New(t, &coderdtest.Options{
DeploymentValues: deploymentValues,
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
IncludeProvisionerDaemon: true,
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
user := coderdtest.CreateFirstUser(t, client)
expClient := codersdk.NewExperimentalClient(client)
@@ -526,11 +519,12 @@ func TestExploreSubagentIsReadOnly(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
deploymentValues := directChatRoutingDeploymentValues(t)
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
DeploymentValues: deploymentValues,
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
IncludeProvisionerDaemon: true,
})
db := api.Database
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
user := coderdtest.CreateFirstUser(t, client)
expClient := codersdk.NewExperimentalClient(client)
@@ -4650,11 +4644,11 @@ func TestCreateWorkspaceTool_EndToEnd(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
deploymentValues := directChatRoutingDeploymentValues(t)
client := coderdtest.New(t, &coderdtest.Options{
DeploymentValues: deploymentValues,
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
IncludeProvisionerDaemon: true,
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
user := coderdtest.CreateFirstUser(t, client)
expClient := codersdk.NewExperimentalClient(client)
@@ -4815,11 +4809,11 @@ func TestStartWorkspaceTool_EndToEnd(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitSuperLong)
deploymentValues := directChatRoutingDeploymentValues(t)
client := coderdtest.New(t, &coderdtest.Options{
DeploymentValues: deploymentValues,
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
IncludeProvisionerDaemon: true,
})
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
user := coderdtest.CreateFirstUser(t, client)
expClient := codersdk.NewExperimentalClient(client)
@@ -5284,7 +5278,7 @@ func highUsageReadFileResponse(path string) chattest.AnthropicResponse {
return chattest.AnthropicStreamingResponse(chunks...)
}
func TestActiveServer_AIGatewayRoutingPreservesAPIKeyAfterCompaction(t *testing.T) {
func TestActiveServer_RoutingPreservesAPIKeyAfterCompaction(t *testing.T) {
t.Parallel()
const (
@@ -9694,7 +9688,7 @@ func seedAIGatewayOpenAITestDependencies(
return user, org, provider, model, apiKey
}
func TestProcessChat_AIGatewayRoutingUsesDelegatedAPIKey(t *testing.T) {
func TestProcessChat_RoutingUsesDelegatedAPIKey(t *testing.T) {
t.Parallel()
db, ps := dbtestutil.NewDB(t)
@@ -9758,7 +9752,7 @@ func TestProcessChat_AIGatewayRoutingUsesDelegatedAPIKey(t *testing.T) {
}
}
func TestProcessChat_AIGatewayRoutingPreservesAPIKeyAfterWorkspaceContext(t *testing.T) {
func TestProcessChat_RoutingPreservesAPIKeyAfterWorkspaceContext(t *testing.T) {
t.Parallel()
db, ps := dbtestutil.NewDB(t)
@@ -11264,12 +11258,13 @@ func TestAgentContextFilesAndSkillsLoadedIntoChat(t *testing.T) {
))
ctx := testutil.Context(t, testutil.WaitSuperLong)
deploymentValues := directChatRoutingDeploymentValues(t)
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
DeploymentValues: deploymentValues,
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
IncludeProvisionerDaemon: true,
ChatdInstructionLookupTimeout: testutil.WaitLong,
})
db := api.Database
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
user := coderdtest.CreateFirstUser(t, client)
expClient := codersdk.NewExperimentalClient(client)
+9 -4
View File
@@ -10,6 +10,7 @@ import (
"google.golang.org/protobuf/types/known/structpb"
agentproto "github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/coderd/aibridgedtest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
@@ -32,10 +33,12 @@ func TestChatContextDirtyFromAgentPush(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
DeploymentValues: directChatRoutingDeploymentValues(t),
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
IncludeProvisionerDaemon: true,
})
db := api.Database
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
user := coderdtest.CreateFirstUser(t, client)
expClient := codersdk.NewExperimentalClient(client)
@@ -284,10 +287,12 @@ func TestChatContextRefreshFromAgentToken(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
DeploymentValues: directChatRoutingDeploymentValues(t),
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
IncludeProvisionerDaemon: true,
})
db := api.Database
aibridgedtest.StartTestAIBridgeDaemon(t.Context(), t, api, nil)
user := coderdtest.CreateFirstUser(t, client)
expClient := codersdk.NewExperimentalClient(client)
+35 -13
View File
@@ -779,19 +779,6 @@ func TestAIBridgeGatewayProviderTypesPreserveSlashModelID(t *testing.T) {
}
}
func TestDirectModelBuildDoesNotRequireActiveAPIKeyID(t *testing.T) {
t.Parallel()
server := &Server{}
model, err := server.newModel(t.Context(), modelClientRequest{
Chat: database.Chat{ID: uuid.New(), OwnerID: uuid.New()},
ModelName: "gpt-4",
UserAgent: chatprovider.UserAgent(),
}, newDirectModelRoute("openai", chatprovider.ProviderAPIKeys{OpenAI: "sk-test"}), modelBuildOptions{})
require.NoError(t, err)
require.NotNil(t, model)
}
func TestAIBridgeComputerUseModelUsesRoute(t *testing.T) {
t.Parallel()
@@ -829,6 +816,41 @@ func TestAIBridgeComputerUseModelUsesRoute(t *testing.T) {
require.Equal(t, aibridge.SourceAgents, factory.source)
}
func TestResolveComputerUseModel_AIGatewayMissingAPIKeyID(t *testing.T) {
t.Parallel()
providerID := uuid.New()
factory := &aibridgeTestFactory{rt: roundTripFunc(func(*http.Request) (*http.Response, error) {
t.Fatal("transport must not be used without an API key ID")
return nil, xerrors.New("unreachable")
})}
chat := database.Chat{ID: uuid.New(), OwnerID: uuid.New()}
server := &Server{
aiGatewayRoutingEnabled: true,
aibridgeTransportFactory: aibridgeTestFactoryPointer(factory),
}
provider := chattool.ComputerUseProviderOpenAI
modelProvider, modelName, ok := chattool.DefaultComputerUseModel(provider)
require.True(t, ok)
model, debugEnabled, resolvedProvider, resolvedModel, err := server.resolveComputerUseModel(
t.Context(),
chat,
aibridgeTestRoute(aibridgeTestAIProvider(providerID, "primary-openai", database.AIProviderTypeOpenai)),
provider,
modelProvider,
modelName,
modelBuildOptions{}, // no ActiveAPIKeyID
)
require.Error(t, err)
require.Nil(t, model)
require.False(t, debugEnabled)
require.Empty(t, resolvedProvider)
require.Empty(t, resolvedModel)
require.Contains(t, err.Error(), `resolve computer use model for provider "openai" model "gpt-5.5"`)
require.Contains(t, err.Error(), "active turn API key ID")
}
func TestAIBridgeDelegatedContextPropagation(t *testing.T) {
t.Parallel()