refactor: rename Ai* database identifiers to AI* (AIGOV-369) (#26327)

Adds `ai` to sqlc's `gen.go.initialisms` in `coderd/database/sqlc.yaml`
so the generated DB code follows Go's initialism convention. Adds the
matching `ai` -> `AI` case to the dbgen PascalCase helper
(`scripts/dbgen/main.go`) so the corresponding `dbmem` / mock
identifiers stay in sync. `make gen` regenerates the rest; hand-written
call sites that consume DB-generated identifiers
(`enterprise/audit/table.go`, `coderd/database/modelmethods.go`,
`enterprise/coderd/aigatewaykeys.go`, `coderd/database/dbauthz/*`, etc.)
are updated to match.

Scope is deliberately limited to the database layer:

- `coderd/rbac/*` (resource and scope generators) is untouched —
`ResourceAi*` / `ScopeAi*` constants stay on main's casing.
- `codersdk/*` (Go SDK) is untouched — `codersdk.ResourceAi*` /
`codersdk.APIKeyScopeAi*` constants stay on main's casing, so external
Go SDK consumers see no source-level break.
- `Aibridge*` identifiers (one SQL token `aibridge`, not `ai_bridge`)
are out of scope.

On-the-wire values are unchanged: enum strings, RBAC resource type
strings, API key scope strings, and JSON tags all stay the same. The
HTTP/JSON surface is unaffected.

Refs:
[AIGOV-369](https://linear.app/codercom/issue/AIGOV-369/change-ai-references-in-coderddatabasemodelsgo-to-ai)

🤖 Generated with [Coder Agents](https://coder.com)
This commit is contained in:
Danny Kopping
2026-06-16 09:01:43 +00:00
committed by GitHub
parent 00a08f35cc
commit a1330e3a8c
53 changed files with 612 additions and 605 deletions
+3 -3
View File
@@ -325,8 +325,8 @@ func (api *API) aiProvidersUpdate(rw http.ResponseWriter, r *http.Request) {
// misconfiguration from sitting silently in the encrypted
// blob.
if existing.Bedrock != nil &&
old.Type != database.AiProviderTypeAnthropic &&
old.Type != database.AiProviderTypeBedrock {
old.Type != database.AIProviderTypeAnthropic &&
old.Type != database.AIProviderTypeBedrock {
return errAIProviderBedrockTypeMismatch
}
settings, err := encodeAIProviderSettings(existing)
@@ -340,7 +340,7 @@ func (api *API) aiProvidersUpdate(rw http.ResponseWriter, r *http.Request) {
return errBedrockRejectsAPIKeys
}
if req.APIKeys != nil && old.Type == database.AiProviderTypeCopilot && len(*req.APIKeys) > 0 {
if req.APIKeys != nil && old.Type == database.AIProviderTypeCopilot && len(*req.APIKeys) > 0 {
return errCopilotRejectsAPIKeys
}
+2 -2
View File
@@ -32,7 +32,7 @@ func BackfillBedrockProviderType(ctx context.Context, db database.Store, logger
}
var promoted int
for _, provider := range providers {
if provider.Type != database.AiProviderTypeAnthropic {
if provider.Type != database.AIProviderTypeAnthropic {
continue
}
settings, err := db2sdk.AIProviderSettings(provider.Settings)
@@ -46,7 +46,7 @@ func BackfillBedrockProviderType(ctx context.Context, db database.Store, logger
}
_, err = db.UpdateAIProvider(sysCtx, database.UpdateAIProviderParams{
ID: provider.ID,
Type: database.AiProviderTypeBedrock,
Type: database.AIProviderTypeBedrock,
DisplayName: provider.DisplayName,
Enabled: provider.Enabled,
BaseUrl: provider.BaseUrl,
+31 -31
View File
@@ -49,16 +49,16 @@ func TestBackfillBedrockProviderType(t *testing.T) {
t.Run("PromotesLegacyRow", func(t *testing.T) {
legacy := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Settings: bedrockSettings,
})
require.Equal(t, database.AiProviderTypeAnthropic, legacy.Type, "pre-condition: row must start as anthropic")
require.Equal(t, database.AIProviderTypeAnthropic, legacy.Type, "pre-condition: row must start as anthropic")
coderd.BackfillBedrockProviderType(ctx, db, logger)
row, err := db.GetAIProviderByName(ctx, legacy.Name)
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeBedrock, row.Type)
require.Equal(t, database.AIProviderTypeBedrock, row.Type)
})
t.Run("Idempotent", func(t *testing.T) {
@@ -70,7 +70,7 @@ func TestBackfillBedrockProviderType(t *testing.T) {
})
require.NoError(t, err)
for _, r := range before {
require.Equal(t, database.AiProviderTypeBedrock, r.Type,
require.Equal(t, database.AIProviderTypeBedrock, r.Type,
"pre-condition: all rows must already be promoted before testing idempotency")
}
@@ -89,37 +89,37 @@ func TestBackfillBedrockProviderType(t *testing.T) {
t.Run("PreservesNativeAnthropicRow", func(t *testing.T) {
native := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
})
require.Equal(t, database.AiProviderTypeAnthropic, native.Type, "pre-condition")
require.Equal(t, database.AIProviderTypeAnthropic, native.Type, "pre-condition")
coderd.BackfillBedrockProviderType(ctx, db, logger)
row, err := db.GetAIProviderByName(ctx, native.Name)
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeAnthropic, row.Type)
require.Equal(t, database.AIProviderTypeAnthropic, row.Type)
})
t.Run("PreservesNativeBedrockRow", func(t *testing.T) {
native := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeBedrock,
Type: database.AIProviderTypeBedrock,
Settings: bedrockSettings,
})
require.Equal(t, database.AiProviderTypeBedrock, native.Type, "pre-condition")
require.Equal(t, database.AIProviderTypeBedrock, native.Type, "pre-condition")
coderd.BackfillBedrockProviderType(ctx, db, logger)
row, err := db.GetAIProviderByName(ctx, native.Name)
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeBedrock, row.Type)
require.Equal(t, database.AIProviderTypeBedrock, row.Type)
})
t.Run("SkipsDeletedRows", func(t *testing.T) {
deleted := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Settings: bedrockSettings,
})
require.Equal(t, database.AiProviderTypeAnthropic, deleted.Type, "pre-condition")
require.Equal(t, database.AIProviderTypeAnthropic, deleted.Type, "pre-condition")
require.NoError(t, db.DeleteAIProviderByID(ctx, deleted.ID))
coderd.BackfillBedrockProviderType(ctx, db, logger)
@@ -133,7 +133,7 @@ func TestBackfillBedrockProviderType(t *testing.T) {
for _, r := range row {
if r.ID == deleted.ID {
found = true
require.Equal(t, database.AiProviderTypeAnthropic, r.Type, "deleted row must not be promoted")
require.Equal(t, database.AIProviderTypeAnthropic, r.Type, "deleted row must not be promoted")
}
}
require.True(t, found, "deleted row must appear in IncludeDeleted result set")
@@ -141,17 +141,17 @@ func TestBackfillBedrockProviderType(t *testing.T) {
t.Run("IncludesDisabledRows", func(t *testing.T) {
disabled := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Enabled: false,
Settings: bedrockSettings,
})
require.Equal(t, database.AiProviderTypeAnthropic, disabled.Type, "pre-condition")
require.Equal(t, database.AIProviderTypeAnthropic, disabled.Type, "pre-condition")
coderd.BackfillBedrockProviderType(ctx, db, logger)
row, err := db.GetAIProviderByName(ctx, disabled.Name)
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeBedrock, row.Type, "disabled legacy row must be promoted")
require.Equal(t, database.AIProviderTypeBedrock, row.Type, "disabled legacy row must be promoted")
})
t.Run("PreservesAnthropicRowWithNonBedrockSettings", func(t *testing.T) {
@@ -159,39 +159,39 @@ func TestBackfillBedrockProviderType(t *testing.T) {
// and the row is skipped via the unparsable-settings path, not the
// settings.Bedrock == nil guard. Either way the row must stay anthropic.
nonBedrock := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Settings: sql.NullString{String: "{}", Valid: true},
})
require.Equal(t, database.AiProviderTypeAnthropic, nonBedrock.Type, "pre-condition")
require.Equal(t, database.AIProviderTypeAnthropic, nonBedrock.Type, "pre-condition")
coderd.BackfillBedrockProviderType(ctx, db, logger)
row, err := db.GetAIProviderByName(ctx, nonBedrock.Name)
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeAnthropic, row.Type, "anthropic row with non-bedrock settings must not be promoted")
require.Equal(t, database.AIProviderTypeAnthropic, row.Type, "anthropic row with non-bedrock settings must not be promoted")
})
t.Run("SkipsUnparsableSettings", func(t *testing.T) {
malformed := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Settings: sql.NullString{String: "{", Valid: true},
})
require.Equal(t, database.AiProviderTypeAnthropic, malformed.Type, "pre-condition")
require.Equal(t, database.AIProviderTypeAnthropic, malformed.Type, "pre-condition")
good := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Settings: bedrockSettings,
})
require.Equal(t, database.AiProviderTypeAnthropic, good.Type, "pre-condition")
require.Equal(t, database.AIProviderTypeAnthropic, good.Type, "pre-condition")
coderd.BackfillBedrockProviderType(ctx, db, logger)
malformedRow, err := db.GetAIProviderByName(ctx, malformed.Name)
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeAnthropic, malformedRow.Type, "row with unparsable settings must not be touched")
require.Equal(t, database.AIProviderTypeAnthropic, malformedRow.Type, "row with unparsable settings must not be touched")
goodRow, err := db.GetAIProviderByName(ctx, good.Name)
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeBedrock, goodRow.Type, "valid row alongside unparsable one must still be promoted")
require.Equal(t, database.AIProviderTypeBedrock, goodRow.Type, "valid row alongside unparsable one must still be promoted")
})
// --- chat_model_configs.provider backfill ---
@@ -203,7 +203,7 @@ func TestBackfillBedrockProviderType(t *testing.T) {
// type=anthropic. The stored provider string is "anthropic" but the
// linked provider row now has type=bedrock.
bedrockProvider := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeBedrock,
Type: database.AIProviderTypeBedrock,
Settings: bedrockSettings,
})
staleConfig := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
@@ -240,7 +240,7 @@ func TestBackfillBedrockProviderType(t *testing.T) {
// A model config with provider="openai" linked to a Bedrock provider
// must not be touched. Only "anthropic" → "bedrock" is in scope.
bedrockProvider := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeBedrock,
Type: database.AIProviderTypeBedrock,
Settings: bedrockSettings,
})
openAIConfig := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
@@ -261,7 +261,7 @@ func TestBackfillBedrockProviderType(t *testing.T) {
// the linked provider is deleted and therefore excluded by the
// AND deleted = FALSE condition in the query.
deletedProvider := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeBedrock,
Type: database.AIProviderTypeBedrock,
Settings: bedrockSettings,
})
staleConfig := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
@@ -281,7 +281,7 @@ func TestBackfillBedrockProviderType(t *testing.T) {
// The SQL query guards on deleted = FALSE. Capture the config ID
// before deletion so we delete the right row regardless of ordering.
bedrockProvider := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeBedrock,
Type: database.AIProviderTypeBedrock,
Settings: bedrockSettings,
})
cfg := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
@@ -323,7 +323,7 @@ func TestBackfillBedrockProviderType(t *testing.T) {
db.EXPECT().
GetAIProviders(gomock.Any(), gomock.Any()).
Return([]database.AIProvider{{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Settings: bedrockSettings,
}}, nil)
db.EXPECT().
@@ -342,7 +342,7 @@ func TestBackfillBedrockProviderType(t *testing.T) {
db.EXPECT().
GetAIProviders(gomock.Any(), gomock.Any()).
Return([]database.AIProvider{{
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Settings: bedrockSettings,
}}, nil)
db.EXPECT().
+7 -7
View File
@@ -130,8 +130,8 @@ func SeedAIProvidersFromEnv(
// type=anthropic to type=bedrock by the startup backfill
// is not mistaken for drift on the next startup.
existingType := existing.Type
if existingSettings.Bedrock != nil && existing.Type == database.AiProviderTypeAnthropic {
existingType = database.AiProviderTypeBedrock
if existingSettings.Bedrock != nil && existing.Type == database.AIProviderTypeAnthropic {
existingType = database.AIProviderTypeBedrock
}
existingDP := desiredAIProvider{
Type: existingType,
@@ -309,7 +309,7 @@ func providersFromEnv(ctx context.Context, cfg codersdk.AIBridgeConfig, logger s
if cfg.LegacyOpenAI.Key.String() != "" {
dp := desiredAIProvider{
Name: aibridge.ProviderOpenAI,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
BaseURL: cfg.LegacyOpenAI.BaseURL.String(),
Keys: []string{cfg.LegacyOpenAI.Key.String()},
}
@@ -334,10 +334,10 @@ func providersFromEnv(ctx context.Context, cfg codersdk.AIBridgeConfig, logger s
if hasAnthropicKey || hasLegacyBedrock {
dp := desiredAIProvider{
Name: aibridge.ProviderAnthropic,
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
}
if hasLegacyBedrock {
dp.Type = database.AiProviderTypeBedrock
dp.Type = database.AIProviderTypeBedrock
if hasAnthropicKey {
logger.Warn(ctx, "ignoring legacy Anthropic API key because Bedrock credentials are configured; Bedrock authenticates via access keys or credential chain",
slog.F("provider", aibridge.ProviderAnthropic),
@@ -389,7 +389,7 @@ func providersFromEnv(ctx context.Context, cfg codersdk.AIBridgeConfig, logger s
// AIProviderBedrockSettings.IsConfigured() so the legacy and
// indexed paths agree on what counts as a Bedrock provider.
isBedrock := false
if dp.Type == database.AiProviderTypeAnthropic || dp.Type == database.AiProviderTypeBedrock {
if dp.Type == database.AIProviderTypeAnthropic || dp.Type == database.AIProviderTypeBedrock {
var accessKey, accessKeySecret string
if len(p.BedrockAccessKeys) > 0 {
accessKey = p.BedrockAccessKeys[0]
@@ -426,7 +426,7 @@ func providersFromEnv(ctx context.Context, cfg codersdk.AIBridgeConfig, logger s
slog.F("ignored_key_count", len(p.Keys)),
)
}
case dp.Type == database.AiProviderTypeCopilot:
case dp.Type == database.AIProviderTypeCopilot:
if len(p.Keys) > 0 {
logger.Warn(ctx, "ignoring bearer keys configured on Copilot AI provider; Copilot authenticates via request-time GitHub OAuth tokens",
slog.F("name", name),
+6 -6
View File
@@ -47,7 +47,7 @@ func TestSeedAIProvidersFromEnv(t *testing.T) {
// One row exists for "openai".
row, err := db.GetAIProviderByName(ctx, "openai")
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeOpenai, row.Type)
require.Equal(t, database.AIProviderTypeOpenai, row.Type)
require.Equal(t, "https://api.openai.com/v1", row.BaseUrl)
require.True(t, row.Enabled)
@@ -161,7 +161,7 @@ func TestSeedAIProvidersFromEnv(t *testing.T) {
row, err := db.GetAIProviderByName(ctx, "anthropic")
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeBedrock, row.Type)
require.Equal(t, database.AIProviderTypeBedrock, row.Type)
require.Contains(t, row.Settings.String, "us-west-2")
require.Contains(t, row.Settings.String, "anthropic.claude-3-5-sonnet")
require.Contains(t, row.Settings.String, "anthropic.claude-3-5-haiku")
@@ -280,7 +280,7 @@ func TestSeedAIProvidersFromEnv(t *testing.T) {
oa, err := db.GetAIProviderByName(ctx, "primary-openai")
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeOpenai, oa.Type)
require.Equal(t, database.AIProviderTypeOpenai, oa.Type)
oaKeys, err := db.GetAIProviderKeysByProviderID(ctx, oa.ID)
require.NoError(t, err)
require.Len(t, oaKeys, 2)
@@ -289,7 +289,7 @@ func TestSeedAIProvidersFromEnv(t *testing.T) {
an, err := db.GetAIProviderByName(ctx, "primary-anthropic")
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeAnthropic, an.Type)
require.Equal(t, database.AIProviderTypeAnthropic, an.Type)
// Plain bearer-token Anthropic with no Bedrock fields: no
// settings blob, one bearer key.
require.False(t, an.Settings.Valid, "no settings blob for bearer-token Anthropic")
@@ -625,7 +625,7 @@ func TestSeedAIProvidersFromEnv(t *testing.T) {
require.NoError(t, err)
_, err = db.UpdateAIProvider(ctx, database.UpdateAIProviderParams{
ID: row.ID,
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
DisplayName: row.DisplayName,
Enabled: row.Enabled,
BaseUrl: row.BaseUrl,
@@ -635,7 +635,7 @@ func TestSeedAIProvidersFromEnv(t *testing.T) {
require.NoError(t, err)
row, err = db.GetAIProviderByName(ctx, "anthropic")
require.NoError(t, err)
require.Equal(t, database.AiProviderTypeAnthropic, row.Type, "pre-condition: row must be anthropic before seed runs")
require.Equal(t, database.AIProviderTypeAnthropic, row.Type, "pre-condition: row must be anthropic before seed runs")
require.NoError(t, coderd.SeedAIProvidersFromEnv(ctx, db, cfg, testLogger(t)))
})
+3 -3
View File
@@ -11,18 +11,18 @@ import (
)
type Reason struct {
EventType database.AiSeatUsageReason
EventType database.AISeatUsageReason
Description string
}
// ReasonAIBridge constructs a reason for usage originating from AI Bridge.
func ReasonAIBridge(description string) Reason {
return Reason{EventType: database.AiSeatUsageReasonAibridge, Description: description}
return Reason{EventType: database.AISeatUsageReasonAibridge, Description: description}
}
// ReasonTask constructs a reason for usage originating from tasks.
func ReasonTask(description string) Reason {
return Reason{EventType: database.AiSeatUsageReasonTask, Description: description}
return Reason{EventType: database.AISeatUsageReasonTask, Description: description}
}
// SeatTracker records AI seat consumption state.
+2 -2
View File
@@ -608,7 +608,7 @@ func (api *API) auditLogResourceLink(ctx context.Context, alog database.GetAudit
// TODO(PLAT-102): point at the user secrets management page once
// it ships. Until then, the audit row links nowhere.
return ""
case database.ResourceTypeGroupAiBudget:
case database.ResourceTypeGroupAIBudget:
// The resource_id is the group's UUID; link to the group's
// settings page.
group, err := api.Database.GetGroupByID(ctx, alog.AuditLog.ResourceID)
@@ -620,7 +620,7 @@ func (api *API) auditLogResourceLink(ctx context.Context, alog database.GetAudit
return ""
}
return fmt.Sprintf("/organizations/%s/groups/%s", org.Name, group.Name)
case database.ResourceTypeUserAiBudgetOverride:
case database.ResourceTypeUserAIBudgetOverride:
// TODO: point at the user's AI budget override management page
// once it ships. Until then, the audit row links nowhere.
return ""
+3 -3
View File
@@ -33,13 +33,13 @@ type Auditable interface {
idpsync.GroupSyncSettings |
idpsync.RoleSyncSettings |
database.TaskTable |
database.AiSeatState |
database.AISeatState |
database.AIProvider |
database.AIProviderKey |
database.AIGatewayKey |
database.Chat |
database.AuditableGroupAiBudget |
database.AuditableUserAiBudgetOverride |
database.AuditableGroupAIBudget |
database.AuditableUserAIBudgetOverride |
database.UserSecret |
database.UserSkill
}
+15 -15
View File
@@ -132,7 +132,7 @@ func ResourceTarget[T Auditable](tgt T) string {
return "Organization Role Sync"
case database.TaskTable:
return typed.Name
case database.AiSeatState:
case database.AISeatState:
return "AI Seat"
case database.AIProvider:
return typed.Name
@@ -140,9 +140,9 @@ func ResourceTarget[T Auditable](tgt T) string {
return typed.ID.String()
case database.AIGatewayKey:
return typed.Name
case database.AuditableGroupAiBudget:
case database.AuditableGroupAIBudget:
return typed.GroupName
case database.AuditableUserAiBudgetOverride:
case database.AuditableUserAIBudgetOverride:
return typed.Username
case database.Chat:
// Chat titles can contain sensitive content (secrets, internal
@@ -220,7 +220,7 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
return noID // Org field on audit log has org id
case database.TaskTable:
return typed.ID
case database.AiSeatState:
case database.AISeatState:
return typed.UserID
case database.AIProvider:
return typed.ID
@@ -228,9 +228,9 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
return typed.ID
case database.AIGatewayKey:
return typed.ID
case database.AuditableGroupAiBudget:
case database.AuditableGroupAIBudget:
return typed.GroupID
case database.AuditableUserAiBudgetOverride:
case database.AuditableUserAIBudgetOverride:
return typed.UserID
case database.Chat:
return typed.ID
@@ -293,18 +293,18 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
return database.ResourceTypeIdpSyncSettingsGroup
case database.TaskTable:
return database.ResourceTypeTask
case database.AiSeatState:
return database.ResourceTypeAiSeat
case database.AISeatState:
return database.ResourceTypeAISeat
case database.AIProvider:
return database.ResourceTypeAIProvider
case database.AIProviderKey:
return database.ResourceTypeAIProviderKey
case database.AIGatewayKey:
return database.ResourceTypeAIGatewayKey
case database.AuditableGroupAiBudget:
return database.ResourceTypeGroupAiBudget
case database.AuditableUserAiBudgetOverride:
return database.ResourceTypeUserAiBudgetOverride
case database.AuditableGroupAIBudget:
return database.ResourceTypeGroupAIBudget
case database.AuditableUserAIBudgetOverride:
return database.ResourceTypeUserAIBudgetOverride
case database.Chat:
return database.ResourceTypeChat
case database.UserSecret:
@@ -369,7 +369,7 @@ func ResourceRequiresOrgID[T Auditable]() bool {
return true
case database.TaskTable:
return true
case database.AiSeatState:
case database.AISeatState:
return false
case database.AIProvider:
// AI providers are deployment-scoped, not org-scoped.
@@ -381,10 +381,10 @@ func ResourceRequiresOrgID[T Auditable]() bool {
case database.AIGatewayKey:
// AI Gateway keys are deployment-scoped, not org-scoped.
return false
case database.AuditableGroupAiBudget:
case database.AuditableGroupAIBudget:
// Group AI budgets are org-scoped through their parent group.
return true
case database.AuditableUserAiBudgetOverride:
case database.AuditableUserAIBudgetOverride:
// User AI budget overrides are org-scoped through their
// attributed group.
return true
+12 -12
View File
@@ -6,17 +6,17 @@ type CheckConstraint string
// CheckConstraint enums.
const (
CheckAiGatewayKeysHashedSecretCheck CheckConstraint = "ai_gateway_keys_hashed_secret_check" // ai_gateway_keys
CheckAiGatewayKeysNameCheck CheckConstraint = "ai_gateway_keys_name_check" // ai_gateway_keys
CheckAiGatewayKeysSecretPrefixCheck CheckConstraint = "ai_gateway_keys_secret_prefix_check" // ai_gateway_keys
CheckAiModelPricesCacheReadPriceCheck CheckConstraint = "ai_model_prices_cache_read_price_check" // ai_model_prices
CheckAiModelPricesCacheWritePriceCheck CheckConstraint = "ai_model_prices_cache_write_price_check" // ai_model_prices
CheckAiModelPricesInputPriceCheck CheckConstraint = "ai_model_prices_input_price_check" // ai_model_prices
CheckAiModelPricesOutputPriceCheck CheckConstraint = "ai_model_prices_output_price_check" // ai_model_prices
CheckAiProvidersNameCheck CheckConstraint = "ai_providers_name_check" // ai_providers
CheckAIGatewayKeysHashedSecretCheck CheckConstraint = "ai_gateway_keys_hashed_secret_check" // ai_gateway_keys
CheckAIGatewayKeysNameCheck CheckConstraint = "ai_gateway_keys_name_check" // ai_gateway_keys
CheckAIGatewayKeysSecretPrefixCheck CheckConstraint = "ai_gateway_keys_secret_prefix_check" // ai_gateway_keys
CheckAIModelPricesCacheReadPriceCheck CheckConstraint = "ai_model_prices_cache_read_price_check" // ai_model_prices
CheckAIModelPricesCacheWritePriceCheck CheckConstraint = "ai_model_prices_cache_write_price_check" // ai_model_prices
CheckAIModelPricesInputPriceCheck CheckConstraint = "ai_model_prices_input_price_check" // ai_model_prices
CheckAIModelPricesOutputPriceCheck CheckConstraint = "ai_model_prices_output_price_check" // ai_model_prices
CheckAIProvidersNameCheck CheckConstraint = "ai_providers_name_check" // ai_providers
CheckAPIKeysAllowListNotEmpty CheckConstraint = "api_keys_allow_list_not_empty" // api_keys
CheckBoundaryLogsSequenceNumberCheck CheckConstraint = "boundary_logs_sequence_number_check" // boundary_logs
CheckChatModelConfigsAiProviderRequiredWhenActive CheckConstraint = "chat_model_configs_ai_provider_required_when_active" // chat_model_configs
CheckChatModelConfigsAIProviderRequiredWhenActive CheckConstraint = "chat_model_configs_ai_provider_required_when_active" // chat_model_configs
CheckChatModelConfigsCompressionThresholdCheck CheckConstraint = "chat_model_configs_compression_threshold_check" // chat_model_configs
CheckChatModelConfigsContextLimitCheck CheckConstraint = "chat_model_configs_context_limit_check" // chat_model_configs
CheckChatUsageLimitConfigDefaultLimitMicrosCheck CheckConstraint = "chat_usage_limit_config_default_limit_micros_check" // chat_usage_limit_config
@@ -33,7 +33,7 @@ const (
CheckUsersServiceAccountLoginType CheckConstraint = "users_service_account_login_type" // users
CheckUsersUsernameMinLength CheckConstraint = "users_username_min_length" // users
CheckOrganizationIDNotZero CheckConstraint = "organization_id_not_zero" // custom_roles
CheckGroupAiBudgetsSpendLimitMicrosCheck CheckConstraint = "group_ai_budgets_spend_limit_micros_check" // group_ai_budgets
CheckGroupAIBudgetsSpendLimitMicrosCheck CheckConstraint = "group_ai_budgets_spend_limit_micros_check" // group_ai_budgets
CheckGroupsChatSpendLimitMicrosCheck CheckConstraint = "groups_chat_spend_limit_micros_check" // groups
CheckMcpServerConfigsAuthTypeCheck CheckConstraint = "mcp_server_configs_auth_type_check" // mcp_server_configs
CheckMcpServerConfigsAvailabilityCheck CheckConstraint = "mcp_server_configs_availability_check" // mcp_server_configs
@@ -47,8 +47,8 @@ const (
CheckTelemetryLockEventTypeConstraint CheckConstraint = "telemetry_lock_event_type_constraint" // telemetry_locks
CheckValidationMonotonicOrder CheckConstraint = "validation_monotonic_order" // template_version_parameters
CheckUsageEventTypeCheck CheckConstraint = "usage_event_type_check" // usage_events
CheckUserAiBudgetOverridesSpendLimitMicrosCheck CheckConstraint = "user_ai_budget_overrides_spend_limit_micros_check" // user_ai_budget_overrides
CheckUserAiProviderKeysAPIKeyCheck CheckConstraint = "user_ai_provider_keys_api_key_check" // user_ai_provider_keys
CheckUserAIBudgetOverridesSpendLimitMicrosCheck CheckConstraint = "user_ai_budget_overrides_spend_limit_micros_check" // user_ai_budget_overrides
CheckUserAIProviderKeysAPIKeyCheck CheckConstraint = "user_ai_provider_keys_api_key_check" // user_ai_provider_keys
CheckUserSkillsContentSize CheckConstraint = "user_skills_content_size" // user_skills
CheckUserSkillsDescriptionSize CheckConstraint = "user_skills_description_size" // user_skills
CheckUserSkillsNameFormat CheckConstraint = "user_skills_name_format" // user_skills
+2 -2
View File
@@ -1421,7 +1421,7 @@ func flattenAndSum(sums map[string]int64, prefix string, m map[string]json.RawMe
}
}
func GroupAIBudget(b database.GroupAiBudget) codersdk.GroupAIBudget {
func GroupAIBudget(b database.GroupAIBudget) codersdk.GroupAIBudget {
return codersdk.GroupAIBudget{
GroupID: b.GroupID,
SpendLimitMicros: b.SpendLimitMicros,
@@ -1430,7 +1430,7 @@ func GroupAIBudget(b database.GroupAiBudget) codersdk.GroupAIBudget {
}
}
func UserAIBudgetOverride(o database.UserAiBudgetOverride) codersdk.UserAIBudgetOverride {
func UserAIBudgetOverride(o database.UserAIBudgetOverride) codersdk.UserAIBudgetOverride {
return codersdk.UserAIBudgetOverride{
UserID: o.UserID,
GroupID: o.GroupID,
+37 -37
View File
@@ -2171,14 +2171,14 @@ func (q *querier) DeleteExternalAuthLink(ctx context.Context, arg database.Delet
}, q.db.DeleteExternalAuthLink)(ctx, arg)
}
func (q *querier) DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAiBudget, error) {
func (q *querier) DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAIBudget, error) {
// Removing a group's AI budget counts as updating the group.
group, err := q.db.GetGroupByID(ctx, groupID)
if err != nil {
return database.GroupAiBudget{}, err
return database.GroupAIBudget{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, group); err != nil {
return database.GroupAiBudget{}, err
return database.GroupAIBudget{}, err
}
return q.db.DeleteGroupAIBudget(ctx, groupID)
}
@@ -2439,28 +2439,28 @@ func (q *querier) DeleteTask(ctx context.Context, arg database.DeleteTaskParams)
return q.db.DeleteTask(ctx, arg)
}
func (q *querier) DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAiBudgetOverride, error) {
func (q *querier) DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAIBudgetOverride, error) {
// Removing a user's AI budget override affects both the user (clearing
// their per-user spend cap) and the group it was attributed to.
u, err := q.db.GetUserByID(ctx, userID)
if err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, u); err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
// Fetch the existing override to learn which group it attributes spend to,
// so we can authorize the caller against that group as well.
userOverride, err := q.db.GetUserAIBudgetOverride(ctx, userID)
if err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
g, err := q.db.GetGroupByID(ctx, userOverride.GroupID)
if err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, g); err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
return q.db.DeleteUserAIBudgetOverride(ctx, userID)
}
@@ -2727,9 +2727,9 @@ func (q *querier) GetAIBridgeUserPromptsByInterceptionID(ctx context.Context, in
return q.db.GetAIBridgeUserPromptsByInterceptionID(ctx, interceptionID)
}
func (q *querier) GetAIModelPriceByProviderModel(ctx context.Context, arg database.GetAIModelPriceByProviderModelParams) (database.AiModelPrice, error) {
func (q *querier) GetAIModelPriceByProviderModel(ctx context.Context, arg database.GetAIModelPriceByProviderModelParams) (database.AIModelPrice, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceAiModelPrice); err != nil {
return database.AiModelPrice{}, err
return database.AIModelPrice{}, err
}
return q.db.GetAIModelPriceByProviderModel(ctx, arg)
}
@@ -3737,14 +3737,14 @@ func (q *querier) GetGitSSHKey(ctx context.Context, userID uuid.UUID) (database.
return fetchWithAction(q.log, q.auth, policy.ActionReadPersonal, q.db.GetGitSSHKey)(ctx, userID)
}
func (q *querier) GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAiBudget, error) {
func (q *querier) GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAIBudget, error) {
// Reading a group's AI budget requires read on the parent group.
group, err := q.db.GetGroupByID(ctx, groupID)
if err != nil {
return database.GroupAiBudget{}, err
return database.GroupAIBudget{}, err
}
if err := q.authorizeContext(ctx, policy.ActionRead, group); err != nil {
return database.GroupAiBudget{}, err
return database.GroupAIBudget{}, err
}
return q.db.GetGroupAIBudget(ctx, groupID)
}
@@ -4794,32 +4794,32 @@ func (q *querier) GetUnexpiredLicenses(ctx context.Context) ([]database.License,
return q.db.GetUnexpiredLicenses(ctx)
}
func (q *querier) GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAiBudgetOverride, error) {
func (q *querier) GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAIBudgetOverride, error) {
if _, err := q.GetUserByID(ctx, userID); err != nil { // AuthZ check
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
return q.db.GetUserAIBudgetOverride(ctx, userID)
}
func (q *querier) GetUserAIProviderKeyByProviderID(ctx context.Context, arg database.GetUserAIProviderKeyByProviderIDParams) (database.UserAiProviderKey, error) {
func (q *querier) GetUserAIProviderKeyByProviderID(ctx context.Context, arg database.GetUserAIProviderKeyByProviderIDParams) (database.UserAIProviderKey, error) {
u, err := q.db.GetUserByID(ctx, arg.UserID)
if err != nil {
return database.UserAiProviderKey{}, err
return database.UserAIProviderKey{}, err
}
if err := q.authorizeContext(ctx, policy.ActionReadPersonal, u); err != nil {
return database.UserAiProviderKey{}, err
return database.UserAIProviderKey{}, err
}
return q.db.GetUserAIProviderKeyByProviderID(ctx, arg)
}
func (q *querier) GetUserAIProviderKeys(ctx context.Context) ([]database.UserAiProviderKey, error) {
func (q *querier) GetUserAIProviderKeys(ctx context.Context) ([]database.UserAIProviderKey, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceAIProvider); err != nil {
return nil, err
}
return q.db.GetUserAIProviderKeys(ctx)
}
func (q *querier) GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]database.UserAiProviderKey, error) {
func (q *querier) GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]database.UserAIProviderKey, error) {
u, err := q.db.GetUserByID(ctx, userID)
if err != nil {
return nil, err
@@ -7295,12 +7295,12 @@ func (q *querier) UpdateEncryptedAIProviderSettings(ctx context.Context, arg dat
return q.db.UpdateEncryptedAIProviderSettings(ctx, arg)
}
func (q *querier) UpdateEncryptedUserAIProviderKey(ctx context.Context, arg database.UpdateEncryptedUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (q *querier) UpdateEncryptedUserAIProviderKey(ctx context.Context, arg database.UpdateEncryptedUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
// Encrypted user-owned provider keys can be rewritten on any row so
// dbcrypt rotation can move every key to a new digest. This is a
// maintenance path, not the self-service user key API.
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceAIProvider); err != nil {
return database.UserAiProviderKey{}, err
return database.UserAIProviderKey{}, err
}
return q.db.UpdateEncryptedUserAIProviderKey(ctx, arg)
}
@@ -7831,13 +7831,13 @@ func (q *querier) UpdateUsageEventsPostPublish(ctx context.Context, arg database
return q.db.UpdateUsageEventsPostPublish(ctx, arg)
}
func (q *querier) UpdateUserAIProviderKey(ctx context.Context, arg database.UpdateUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (q *querier) UpdateUserAIProviderKey(ctx context.Context, arg database.UpdateUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
u, err := q.db.GetUserByID(ctx, arg.UserID)
if err != nil {
return database.UserAiProviderKey{}, err
return database.UserAIProviderKey{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, u); err != nil {
return database.UserAiProviderKey{}, err
return database.UserAIProviderKey{}, err
}
return q.db.UpdateUserAIProviderKey(ctx, arg)
}
@@ -8645,14 +8645,14 @@ func (q *querier) UpsertDefaultProxy(ctx context.Context, arg database.UpsertDef
return q.db.UpsertDefaultProxy(ctx, arg)
}
func (q *querier) UpsertGroupAIBudget(ctx context.Context, arg database.UpsertGroupAIBudgetParams) (database.GroupAiBudget, error) {
func (q *querier) UpsertGroupAIBudget(ctx context.Context, arg database.UpsertGroupAIBudgetParams) (database.GroupAIBudget, error) {
// Setting a group's AI budget counts as updating the group.
group, err := q.db.GetGroupByID(ctx, arg.GroupID)
if err != nil {
return database.GroupAiBudget{}, err
return database.GroupAIBudget{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, group); err != nil {
return database.GroupAiBudget{}, err
return database.GroupAIBudget{}, err
}
return q.db.UpsertGroupAIBudget(ctx, arg)
}
@@ -8792,33 +8792,33 @@ func (q *querier) UpsertTemplateUsageStats(ctx context.Context) error {
return q.db.UpsertTemplateUsageStats(ctx)
}
func (q *querier) UpsertUserAIBudgetOverride(ctx context.Context, arg database.UpsertUserAIBudgetOverrideParams) (database.UserAiBudgetOverride, error) {
func (q *querier) UpsertUserAIBudgetOverride(ctx context.Context, arg database.UpsertUserAIBudgetOverrideParams) (database.UserAIBudgetOverride, error) {
// Setting a user's AI budget override affects both the user (their
// per-user spend cap) and the group (spend attribution).
u, err := q.db.GetUserByID(ctx, arg.UserID)
if err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, u); err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
g, err := q.db.GetGroupByID(ctx, arg.GroupID)
if err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, g); err != nil {
return database.UserAiBudgetOverride{}, err
return database.UserAIBudgetOverride{}, err
}
return q.db.UpsertUserAIBudgetOverride(ctx, arg)
}
func (q *querier) UpsertUserAIProviderKey(ctx context.Context, arg database.UpsertUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (q *querier) UpsertUserAIProviderKey(ctx context.Context, arg database.UpsertUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
u, err := q.db.GetUserByID(ctx, arg.UserID)
if err != nil {
return database.UserAiProviderKey{}, err
return database.UserAIProviderKey{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, u); err != nil {
return database.UserAiProviderKey{}, err
return database.UserAIProviderKey{}, err
}
return q.db.UpsertUserAIProviderKey(ctx, arg)
}
+19 -19
View File
@@ -3134,17 +3134,17 @@ func (s *MethodTestSuite) TestUser() {
s.Run("GetUserAIProviderKeyByProviderID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
arg := database.GetUserAIProviderKeyByProviderIDParams{UserID: u.ID, AIProviderID: uuid.New()}
key := testutil.Fake(s.T(), faker, database.UserAiProviderKey{UserID: u.ID, AIProviderID: arg.AIProviderID})
key := testutil.Fake(s.T(), faker, database.UserAIProviderKey{UserID: u.ID, AIProviderID: arg.AIProviderID})
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
dbm.EXPECT().GetUserAIProviderKeyByProviderID(gomock.Any(), arg).Return(key, nil).AnyTimes()
check.Args(arg).Asserts(u, policy.ActionReadPersonal).Returns(key)
}))
s.Run("GetUserAIProviderKeysByUserID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
key := testutil.Fake(s.T(), faker, database.UserAiProviderKey{UserID: u.ID})
key := testutil.Fake(s.T(), faker, database.UserAIProviderKey{UserID: u.ID})
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
dbm.EXPECT().GetUserAIProviderKeysByUserID(gomock.Any(), u.ID).Return([]database.UserAiProviderKey{key}, nil).AnyTimes()
check.Args(u.ID).Asserts(u, policy.ActionReadPersonal).Returns([]database.UserAiProviderKey{key})
dbm.EXPECT().GetUserAIProviderKeysByUserID(gomock.Any(), u.ID).Return([]database.UserAIProviderKey{key}, nil).AnyTimes()
check.Args(u.ID).Asserts(u, policy.ActionReadPersonal).Returns([]database.UserAIProviderKey{key})
}))
s.Run("DeleteUserAIProviderKeysByProviderID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
providerID := uuid.New()
@@ -3161,7 +3161,7 @@ func (s *MethodTestSuite) TestUser() {
s.Run("UpdateUserAIProviderKey", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
arg := database.UpdateUserAIProviderKeyParams{UserID: u.ID, AIProviderID: uuid.New(), APIKey: "updated-api-key"}
key := testutil.Fake(s.T(), faker, database.UserAiProviderKey{UserID: u.ID, AIProviderID: arg.AIProviderID, APIKey: arg.APIKey})
key := testutil.Fake(s.T(), faker, database.UserAIProviderKey{UserID: u.ID, AIProviderID: arg.AIProviderID, APIKey: arg.APIKey})
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
dbm.EXPECT().UpdateUserAIProviderKey(gomock.Any(), arg).Return(key, nil).AnyTimes()
check.Args(arg).Asserts(u, policy.ActionUpdatePersonal).Returns(key)
@@ -3169,7 +3169,7 @@ func (s *MethodTestSuite) TestUser() {
s.Run("UpsertUserAIProviderKey", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
arg := database.UpsertUserAIProviderKeyParams{UserID: u.ID, AIProviderID: uuid.New(), APIKey: "upserted-api-key"}
key := testutil.Fake(s.T(), faker, database.UserAiProviderKey{UserID: u.ID, AIProviderID: arg.AIProviderID, APIKey: arg.APIKey})
key := testutil.Fake(s.T(), faker, database.UserAIProviderKey{UserID: u.ID, AIProviderID: arg.AIProviderID, APIKey: arg.APIKey})
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
dbm.EXPECT().UpsertUserAIProviderKey(gomock.Any(), arg).Return(key, nil).AnyTimes()
check.Args(arg).Asserts(u, policy.ActionUpdatePersonal).Returns(key)
@@ -6681,13 +6681,13 @@ func (s *MethodTestSuite) TestAIBridge() {
}))
s.Run("GetAIModelPriceByProviderModel", s.Mocked(func(db *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
db.EXPECT().GetAIModelPriceByProviderModel(gomock.Any(), gomock.Any()).Return(database.AiModelPrice{}, nil).AnyTimes()
db.EXPECT().GetAIModelPriceByProviderModel(gomock.Any(), gomock.Any()).Return(database.AIModelPrice{}, nil).AnyTimes()
check.Args(database.GetAIModelPriceByProviderModelParams{}).Asserts(rbac.ResourceAiModelPrice, policy.ActionRead)
}))
s.Run("GetGroupAIBudget", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
g := testutil.Fake(s.T(), faker, database.Group{})
b := testutil.Fake(s.T(), faker, database.GroupAiBudget{GroupID: g.ID})
b := testutil.Fake(s.T(), faker, database.GroupAIBudget{GroupID: g.ID})
dbm.EXPECT().GetGroupByID(gomock.Any(), g.ID).Return(g, nil).AnyTimes()
dbm.EXPECT().GetGroupAIBudget(gomock.Any(), g.ID).Return(b, nil).AnyTimes()
check.Args(g.ID).Asserts(g, policy.ActionRead).Returns(b)
@@ -6695,7 +6695,7 @@ func (s *MethodTestSuite) TestAIBridge() {
s.Run("UpsertGroupAIBudget", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
g := testutil.Fake(s.T(), faker, database.Group{})
b := testutil.Fake(s.T(), faker, database.GroupAiBudget{GroupID: g.ID})
b := testutil.Fake(s.T(), faker, database.GroupAIBudget{GroupID: g.ID})
arg := database.UpsertGroupAIBudgetParams{GroupID: g.ID, SpendLimitMicros: b.SpendLimitMicros}
dbm.EXPECT().GetGroupByID(gomock.Any(), g.ID).Return(g, nil).AnyTimes()
dbm.EXPECT().UpsertGroupAIBudget(gomock.Any(), arg).Return(b, nil).AnyTimes()
@@ -6704,7 +6704,7 @@ func (s *MethodTestSuite) TestAIBridge() {
s.Run("DeleteGroupAIBudget", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
g := testutil.Fake(s.T(), faker, database.Group{})
b := testutil.Fake(s.T(), faker, database.GroupAiBudget{GroupID: g.ID})
b := testutil.Fake(s.T(), faker, database.GroupAIBudget{GroupID: g.ID})
dbm.EXPECT().GetGroupByID(gomock.Any(), g.ID).Return(g, nil).AnyTimes()
dbm.EXPECT().DeleteGroupAIBudget(gomock.Any(), g.ID).Return(b, nil).AnyTimes()
check.Args(g.ID).Asserts(g, policy.ActionUpdate).Returns(b)
@@ -6712,7 +6712,7 @@ func (s *MethodTestSuite) TestAIBridge() {
s.Run("GetUserAIBudgetOverride", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
user := testutil.Fake(s.T(), faker, database.User{})
override := testutil.Fake(s.T(), faker, database.UserAiBudgetOverride{UserID: user.ID})
override := testutil.Fake(s.T(), faker, database.UserAIBudgetOverride{UserID: user.ID})
dbm.EXPECT().GetUserByID(gomock.Any(), user.ID).Return(user, nil).AnyTimes()
dbm.EXPECT().GetUserAIBudgetOverride(gomock.Any(), user.ID).Return(override, nil).AnyTimes()
check.Args(user.ID).Asserts(user, policy.ActionRead).Returns(override)
@@ -6729,7 +6729,7 @@ func (s *MethodTestSuite) TestAIBridge() {
s.Run("UpsertUserAIBudgetOverride", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
user := testutil.Fake(s.T(), faker, database.User{})
group := testutil.Fake(s.T(), faker, database.Group{})
override := testutil.Fake(s.T(), faker, database.UserAiBudgetOverride{UserID: user.ID, GroupID: group.ID})
override := testutil.Fake(s.T(), faker, database.UserAIBudgetOverride{UserID: user.ID, GroupID: group.ID})
arg := database.UpsertUserAIBudgetOverrideParams{UserID: user.ID, GroupID: group.ID, SpendLimitMicros: override.SpendLimitMicros}
dbm.EXPECT().GetUserByID(gomock.Any(), user.ID).Return(user, nil).AnyTimes()
dbm.EXPECT().GetGroupByID(gomock.Any(), group.ID).Return(group, nil).AnyTimes()
@@ -6740,7 +6740,7 @@ func (s *MethodTestSuite) TestAIBridge() {
s.Run("DeleteUserAIBudgetOverride", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
user := testutil.Fake(s.T(), faker, database.User{})
group := testutil.Fake(s.T(), faker, database.Group{})
override := testutil.Fake(s.T(), faker, database.UserAiBudgetOverride{UserID: user.ID, GroupID: group.ID})
override := testutil.Fake(s.T(), faker, database.UserAIBudgetOverride{UserID: user.ID, GroupID: group.ID})
dbm.EXPECT().GetUserByID(gomock.Any(), user.ID).Return(user, nil).AnyTimes()
dbm.EXPECT().GetUserAIBudgetOverride(gomock.Any(), user.ID).Return(override, nil).AnyTimes()
dbm.EXPECT().GetGroupByID(gomock.Any(), group.ID).Return(group, nil).AnyTimes()
@@ -6773,7 +6773,7 @@ func (s *MethodTestSuite) TestAIBridge() {
s.Run("InsertAIProvider", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
arg := database.InsertAIProviderParams{
ID: uuid.New(),
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Name: "test-provider",
Enabled: true,
BaseUrl: "https://api.example.com/",
@@ -6876,13 +6876,13 @@ func (s *MethodTestSuite) TestAIBridge() {
check.Args(arg).Asserts(rbac.ResourceAIProvider, policy.ActionUpdate).Returns(key)
}))
s.Run("GetUserAIProviderKeys", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
keyA := testutil.Fake(s.T(), faker, database.UserAiProviderKey{})
keyB := testutil.Fake(s.T(), faker, database.UserAiProviderKey{})
dbm.EXPECT().GetUserAIProviderKeys(gomock.Any()).Return([]database.UserAiProviderKey{keyA, keyB}, nil).AnyTimes()
check.Args().Asserts(rbac.ResourceAIProvider, policy.ActionRead).Returns([]database.UserAiProviderKey{keyA, keyB})
keyA := testutil.Fake(s.T(), faker, database.UserAIProviderKey{})
keyB := testutil.Fake(s.T(), faker, database.UserAIProviderKey{})
dbm.EXPECT().GetUserAIProviderKeys(gomock.Any()).Return([]database.UserAIProviderKey{keyA, keyB}, nil).AnyTimes()
check.Args().Asserts(rbac.ResourceAIProvider, policy.ActionRead).Returns([]database.UserAIProviderKey{keyA, keyB})
}))
s.Run("UpdateEncryptedUserAIProviderKey", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
key := testutil.Fake(s.T(), faker, database.UserAiProviderKey{})
key := testutil.Fake(s.T(), faker, database.UserAIProviderKey{})
arg := database.UpdateEncryptedUserAIProviderKeyParams{
ID: key.ID,
APIKey: "encrypted-api-key",
+1 -1
View File
@@ -210,7 +210,7 @@ func AIProvider(t testing.TB, db database.Store, seed database.AIProvider, munge
}
provType := seed.Type
if provType == "" {
provType = database.AiProviderTypeOpenai
provType = database.AIProviderTypeOpenai
}
name := takeFirst(seed.Name, testutil.GetRandomNameHyphenated(t))
displayName := seed.DisplayName
+13 -13
View File
@@ -594,7 +594,7 @@ func (m queryMetricsStore) DeleteExternalAuthLink(ctx context.Context, arg datab
return r0
}
func (m queryMetricsStore) DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAiBudget, error) {
func (m queryMetricsStore) DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAIBudget, error) {
start := time.Now()
r0, r1 := m.s.DeleteGroupAIBudget(ctx, groupID)
m.queryLatencies.WithLabelValues("DeleteGroupAIBudget").Observe(time.Since(start).Seconds())
@@ -866,7 +866,7 @@ func (m queryMetricsStore) DeleteTask(ctx context.Context, arg database.DeleteTa
return r0, r1
}
func (m queryMetricsStore) DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAiBudgetOverride, error) {
func (m queryMetricsStore) DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAIBudgetOverride, error) {
start := time.Now()
r0, r1 := m.s.DeleteUserAIBudgetOverride(ctx, userID)
m.queryLatencies.WithLabelValues("DeleteUserAIBudgetOverride").Observe(time.Since(start).Seconds())
@@ -1106,7 +1106,7 @@ func (m queryMetricsStore) GetAIBridgeUserPromptsByInterceptionID(ctx context.Co
return r0, r1
}
func (m queryMetricsStore) GetAIModelPriceByProviderModel(ctx context.Context, arg database.GetAIModelPriceByProviderModelParams) (database.AiModelPrice, error) {
func (m queryMetricsStore) GetAIModelPriceByProviderModel(ctx context.Context, arg database.GetAIModelPriceByProviderModelParams) (database.AIModelPrice, error) {
start := time.Now()
r0, r1 := m.s.GetAIModelPriceByProviderModel(ctx, arg)
m.queryLatencies.WithLabelValues("GetAIModelPriceByProviderModel").Observe(time.Since(start).Seconds())
@@ -2082,7 +2082,7 @@ func (m queryMetricsStore) GetGitSSHKey(ctx context.Context, userID uuid.UUID) (
return r0, r1
}
func (m queryMetricsStore) GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAiBudget, error) {
func (m queryMetricsStore) GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAIBudget, error) {
start := time.Now()
r0, r1 := m.s.GetGroupAIBudget(ctx, groupID)
m.queryLatencies.WithLabelValues("GetGroupAIBudget").Observe(time.Since(start).Seconds())
@@ -3106,7 +3106,7 @@ func (m queryMetricsStore) GetUnexpiredLicenses(ctx context.Context) ([]database
return r0, r1
}
func (m queryMetricsStore) GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAiBudgetOverride, error) {
func (m queryMetricsStore) GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAIBudgetOverride, error) {
start := time.Now()
r0, r1 := m.s.GetUserAIBudgetOverride(ctx, userID)
m.queryLatencies.WithLabelValues("GetUserAIBudgetOverride").Observe(time.Since(start).Seconds())
@@ -3114,7 +3114,7 @@ func (m queryMetricsStore) GetUserAIBudgetOverride(ctx context.Context, userID u
return r0, r1
}
func (m queryMetricsStore) GetUserAIProviderKeyByProviderID(ctx context.Context, arg database.GetUserAIProviderKeyByProviderIDParams) (database.UserAiProviderKey, error) {
func (m queryMetricsStore) GetUserAIProviderKeyByProviderID(ctx context.Context, arg database.GetUserAIProviderKeyByProviderIDParams) (database.UserAIProviderKey, error) {
start := time.Now()
r0, r1 := m.s.GetUserAIProviderKeyByProviderID(ctx, arg)
m.queryLatencies.WithLabelValues("GetUserAIProviderKeyByProviderID").Observe(time.Since(start).Seconds())
@@ -3122,7 +3122,7 @@ func (m queryMetricsStore) GetUserAIProviderKeyByProviderID(ctx context.Context,
return r0, r1
}
func (m queryMetricsStore) GetUserAIProviderKeys(ctx context.Context) ([]database.UserAiProviderKey, error) {
func (m queryMetricsStore) GetUserAIProviderKeys(ctx context.Context) ([]database.UserAIProviderKey, error) {
start := time.Now()
r0, r1 := m.s.GetUserAIProviderKeys(ctx)
m.queryLatencies.WithLabelValues("GetUserAIProviderKeys").Observe(time.Since(start).Seconds())
@@ -3130,7 +3130,7 @@ func (m queryMetricsStore) GetUserAIProviderKeys(ctx context.Context) ([]databas
return r0, r1
}
func (m queryMetricsStore) GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]database.UserAiProviderKey, error) {
func (m queryMetricsStore) GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]database.UserAIProviderKey, error) {
start := time.Now()
r0, r1 := m.s.GetUserAIProviderKeysByUserID(ctx, userID)
m.queryLatencies.WithLabelValues("GetUserAIProviderKeysByUserID").Observe(time.Since(start).Seconds())
@@ -5234,7 +5234,7 @@ func (m queryMetricsStore) UpdateEncryptedAIProviderSettings(ctx context.Context
return r0, r1
}
func (m queryMetricsStore) UpdateEncryptedUserAIProviderKey(ctx context.Context, arg database.UpdateEncryptedUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (m queryMetricsStore) UpdateEncryptedUserAIProviderKey(ctx context.Context, arg database.UpdateEncryptedUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
start := time.Now()
r0, r1 := m.s.UpdateEncryptedUserAIProviderKey(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateEncryptedUserAIProviderKey").Observe(time.Since(start).Seconds())
@@ -5570,7 +5570,7 @@ func (m queryMetricsStore) UpdateUsageEventsPostPublish(ctx context.Context, arg
return r0
}
func (m queryMetricsStore) UpdateUserAIProviderKey(ctx context.Context, arg database.UpdateUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (m queryMetricsStore) UpdateUserAIProviderKey(ctx context.Context, arg database.UpdateUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
start := time.Now()
r0, r1 := m.s.UpdateUserAIProviderKey(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateUserAIProviderKey").Observe(time.Since(start).Seconds())
@@ -6226,7 +6226,7 @@ func (m queryMetricsStore) UpsertDefaultProxy(ctx context.Context, arg database.
return r0
}
func (m queryMetricsStore) UpsertGroupAIBudget(ctx context.Context, arg database.UpsertGroupAIBudgetParams) (database.GroupAiBudget, error) {
func (m queryMetricsStore) UpsertGroupAIBudget(ctx context.Context, arg database.UpsertGroupAIBudgetParams) (database.GroupAIBudget, error) {
start := time.Now()
r0, r1 := m.s.UpsertGroupAIBudget(ctx, arg)
m.queryLatencies.WithLabelValues("UpsertGroupAIBudget").Observe(time.Since(start).Seconds())
@@ -6370,7 +6370,7 @@ func (m queryMetricsStore) UpsertTemplateUsageStats(ctx context.Context) error {
return r0
}
func (m queryMetricsStore) UpsertUserAIBudgetOverride(ctx context.Context, arg database.UpsertUserAIBudgetOverrideParams) (database.UserAiBudgetOverride, error) {
func (m queryMetricsStore) UpsertUserAIBudgetOverride(ctx context.Context, arg database.UpsertUserAIBudgetOverrideParams) (database.UserAIBudgetOverride, error) {
start := time.Now()
r0, r1 := m.s.UpsertUserAIBudgetOverride(ctx, arg)
m.queryLatencies.WithLabelValues("UpsertUserAIBudgetOverride").Observe(time.Since(start).Seconds())
@@ -6378,7 +6378,7 @@ func (m queryMetricsStore) UpsertUserAIBudgetOverride(ctx context.Context, arg d
return r0, r1
}
func (m queryMetricsStore) UpsertUserAIProviderKey(ctx context.Context, arg database.UpsertUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (m queryMetricsStore) UpsertUserAIProviderKey(ctx context.Context, arg database.UpsertUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
start := time.Now()
r0, r1 := m.s.UpsertUserAIProviderKey(ctx, arg)
m.queryLatencies.WithLabelValues("UpsertUserAIProviderKey").Observe(time.Since(start).Seconds())
+26 -26
View File
@@ -978,10 +978,10 @@ func (mr *MockStoreMockRecorder) DeleteExternalAuthLink(ctx, arg any) *gomock.Ca
}
// DeleteGroupAIBudget mocks base method.
func (m *MockStore) DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAiBudget, error) {
func (m *MockStore) DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAIBudget, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteGroupAIBudget", ctx, groupID)
ret0, _ := ret[0].(database.GroupAiBudget)
ret0, _ := ret[0].(database.GroupAIBudget)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -1468,10 +1468,10 @@ func (mr *MockStoreMockRecorder) DeleteTask(ctx, arg any) *gomock.Call {
}
// DeleteUserAIBudgetOverride mocks base method.
func (m *MockStore) DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAiBudgetOverride, error) {
func (m *MockStore) DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAIBudgetOverride, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteUserAIBudgetOverride", ctx, userID)
ret0, _ := ret[0].(database.UserAiBudgetOverride)
ret0, _ := ret[0].(database.UserAIBudgetOverride)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -1904,10 +1904,10 @@ func (mr *MockStoreMockRecorder) GetAIBridgeUserPromptsByInterceptionID(ctx, int
}
// GetAIModelPriceByProviderModel mocks base method.
func (m *MockStore) GetAIModelPriceByProviderModel(ctx context.Context, arg database.GetAIModelPriceByProviderModelParams) (database.AiModelPrice, error) {
func (m *MockStore) GetAIModelPriceByProviderModel(ctx context.Context, arg database.GetAIModelPriceByProviderModelParams) (database.AIModelPrice, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAIModelPriceByProviderModel", ctx, arg)
ret0, _ := ret[0].(database.AiModelPrice)
ret0, _ := ret[0].(database.AIModelPrice)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -3854,10 +3854,10 @@ func (mr *MockStoreMockRecorder) GetGitSSHKey(ctx, userID any) *gomock.Call {
}
// GetGroupAIBudget mocks base method.
func (m *MockStore) GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAiBudget, error) {
func (m *MockStore) GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (database.GroupAIBudget, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetGroupAIBudget", ctx, groupID)
ret0, _ := ret[0].(database.GroupAiBudget)
ret0, _ := ret[0].(database.GroupAIBudget)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -5804,10 +5804,10 @@ func (mr *MockStoreMockRecorder) GetUnexpiredLicenses(ctx any) *gomock.Call {
}
// GetUserAIBudgetOverride mocks base method.
func (m *MockStore) GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAiBudgetOverride, error) {
func (m *MockStore) GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (database.UserAIBudgetOverride, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUserAIBudgetOverride", ctx, userID)
ret0, _ := ret[0].(database.UserAiBudgetOverride)
ret0, _ := ret[0].(database.UserAIBudgetOverride)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -5819,10 +5819,10 @@ func (mr *MockStoreMockRecorder) GetUserAIBudgetOverride(ctx, userID any) *gomoc
}
// GetUserAIProviderKeyByProviderID mocks base method.
func (m *MockStore) GetUserAIProviderKeyByProviderID(ctx context.Context, arg database.GetUserAIProviderKeyByProviderIDParams) (database.UserAiProviderKey, error) {
func (m *MockStore) GetUserAIProviderKeyByProviderID(ctx context.Context, arg database.GetUserAIProviderKeyByProviderIDParams) (database.UserAIProviderKey, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUserAIProviderKeyByProviderID", ctx, arg)
ret0, _ := ret[0].(database.UserAiProviderKey)
ret0, _ := ret[0].(database.UserAIProviderKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -5834,10 +5834,10 @@ func (mr *MockStoreMockRecorder) GetUserAIProviderKeyByProviderID(ctx, arg any)
}
// GetUserAIProviderKeys mocks base method.
func (m *MockStore) GetUserAIProviderKeys(ctx context.Context) ([]database.UserAiProviderKey, error) {
func (m *MockStore) GetUserAIProviderKeys(ctx context.Context) ([]database.UserAIProviderKey, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUserAIProviderKeys", ctx)
ret0, _ := ret[0].([]database.UserAiProviderKey)
ret0, _ := ret[0].([]database.UserAIProviderKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -5849,10 +5849,10 @@ func (mr *MockStoreMockRecorder) GetUserAIProviderKeys(ctx any) *gomock.Call {
}
// GetUserAIProviderKeysByUserID mocks base method.
func (m *MockStore) GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]database.UserAiProviderKey, error) {
func (m *MockStore) GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]database.UserAIProviderKey, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUserAIProviderKeysByUserID", ctx, userID)
ret0, _ := ret[0].([]database.UserAiProviderKey)
ret0, _ := ret[0].([]database.UserAIProviderKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -9862,10 +9862,10 @@ func (mr *MockStoreMockRecorder) UpdateEncryptedAIProviderSettings(ctx, arg any)
}
// UpdateEncryptedUserAIProviderKey mocks base method.
func (m *MockStore) UpdateEncryptedUserAIProviderKey(ctx context.Context, arg database.UpdateEncryptedUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (m *MockStore) UpdateEncryptedUserAIProviderKey(ctx context.Context, arg database.UpdateEncryptedUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateEncryptedUserAIProviderKey", ctx, arg)
ret0, _ := ret[0].(database.UserAiProviderKey)
ret0, _ := ret[0].(database.UserAIProviderKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -10468,10 +10468,10 @@ func (mr *MockStoreMockRecorder) UpdateUsageEventsPostPublish(ctx, arg any) *gom
}
// UpdateUserAIProviderKey mocks base method.
func (m *MockStore) UpdateUserAIProviderKey(ctx context.Context, arg database.UpdateUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (m *MockStore) UpdateUserAIProviderKey(ctx context.Context, arg database.UpdateUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateUserAIProviderKey", ctx, arg)
ret0, _ := ret[0].(database.UserAiProviderKey)
ret0, _ := ret[0].(database.UserAIProviderKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -11651,10 +11651,10 @@ func (mr *MockStoreMockRecorder) UpsertDefaultProxy(ctx, arg any) *gomock.Call {
}
// UpsertGroupAIBudget mocks base method.
func (m *MockStore) UpsertGroupAIBudget(ctx context.Context, arg database.UpsertGroupAIBudgetParams) (database.GroupAiBudget, error) {
func (m *MockStore) UpsertGroupAIBudget(ctx context.Context, arg database.UpsertGroupAIBudgetParams) (database.GroupAIBudget, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpsertGroupAIBudget", ctx, arg)
ret0, _ := ret[0].(database.GroupAiBudget)
ret0, _ := ret[0].(database.GroupAIBudget)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -11910,10 +11910,10 @@ func (mr *MockStoreMockRecorder) UpsertTemplateUsageStats(ctx any) *gomock.Call
}
// UpsertUserAIBudgetOverride mocks base method.
func (m *MockStore) UpsertUserAIBudgetOverride(ctx context.Context, arg database.UpsertUserAIBudgetOverrideParams) (database.UserAiBudgetOverride, error) {
func (m *MockStore) UpsertUserAIBudgetOverride(ctx context.Context, arg database.UpsertUserAIBudgetOverrideParams) (database.UserAIBudgetOverride, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpsertUserAIBudgetOverride", ctx, arg)
ret0, _ := ret[0].(database.UserAiBudgetOverride)
ret0, _ := ret[0].(database.UserAIBudgetOverride)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -11925,10 +11925,10 @@ func (mr *MockStoreMockRecorder) UpsertUserAIBudgetOverride(ctx, arg any) *gomoc
}
// UpsertUserAIProviderKey mocks base method.
func (m *MockStore) UpsertUserAIProviderKey(ctx context.Context, arg database.UpsertUserAIProviderKeyParams) (database.UserAiProviderKey, error) {
func (m *MockStore) UpsertUserAIProviderKey(ctx context.Context, arg database.UpsertUserAIProviderKeyParams) (database.UserAIProviderKey, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpsertUserAIProviderKey", ctx, arg)
ret0, _ := ret[0].(database.UserAiProviderKey)
ret0, _ := ret[0].(database.UserAIProviderKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
+11 -11
View File
@@ -6,10 +6,10 @@ type ForeignKeyConstraint string
// ForeignKeyConstraint enums.
const (
ForeignKeyAiProviderKeysAPIKeyKeyID ForeignKeyConstraint = "ai_provider_keys_api_key_key_id_fkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_api_key_key_id_fkey FOREIGN KEY (api_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
ForeignKeyAiProviderKeysProviderID ForeignKeyConstraint = "ai_provider_keys_provider_id_fkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES ai_providers(id) ON DELETE CASCADE;
ForeignKeyAiProvidersSettingsKeyID ForeignKeyConstraint = "ai_providers_settings_key_id_fkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_settings_key_id_fkey FOREIGN KEY (settings_key_id) REFERENCES dbcrypt_keys(active_key_digest);
ForeignKeyAiSeatStateUserID ForeignKeyConstraint = "ai_seat_state_user_id_fkey" // ALTER TABLE ONLY ai_seat_state ADD CONSTRAINT ai_seat_state_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyAIProviderKeysAPIKeyKeyID ForeignKeyConstraint = "ai_provider_keys_api_key_key_id_fkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_api_key_key_id_fkey FOREIGN KEY (api_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
ForeignKeyAIProviderKeysProviderID ForeignKeyConstraint = "ai_provider_keys_provider_id_fkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES ai_providers(id) ON DELETE CASCADE;
ForeignKeyAIProvidersSettingsKeyID ForeignKeyConstraint = "ai_providers_settings_key_id_fkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_settings_key_id_fkey FOREIGN KEY (settings_key_id) REFERENCES dbcrypt_keys(active_key_digest);
ForeignKeyAISeatStateUserID ForeignKeyConstraint = "ai_seat_state_user_id_fkey" // ALTER TABLE ONLY ai_seat_state ADD CONSTRAINT ai_seat_state_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyAibridgeInterceptionsInitiatorID ForeignKeyConstraint = "aibridge_interceptions_initiator_id_fkey" // ALTER TABLE ONLY aibridge_interceptions ADD CONSTRAINT aibridge_interceptions_initiator_id_fkey FOREIGN KEY (initiator_id) REFERENCES users(id);
ForeignKeyAPIKeysUserIDUUID ForeignKeyConstraint = "api_keys_user_id_uuid_fkey" // ALTER TABLE ONLY api_keys ADD CONSTRAINT api_keys_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyBoundarySessionsOwnerID ForeignKeyConstraint = "boundary_sessions_owner_id_fkey" // ALTER TABLE ONLY boundary_sessions ADD CONSTRAINT boundary_sessions_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -25,7 +25,7 @@ const (
ForeignKeyChatMessagesAPIKeyID ForeignKeyConstraint = "chat_messages_api_key_id_fkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE SET NULL;
ForeignKeyChatMessagesChatID ForeignKeyConstraint = "chat_messages_chat_id_fkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
ForeignKeyChatMessagesModelConfigID ForeignKeyConstraint = "chat_messages_model_config_id_fkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_model_config_id_fkey FOREIGN KEY (model_config_id) REFERENCES chat_model_configs(id);
ForeignKeyChatModelConfigsAiProviderID ForeignKeyConstraint = "chat_model_configs_ai_provider_id_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_ai_provider_id_fkey FOREIGN KEY (ai_provider_id) REFERENCES ai_providers(id);
ForeignKeyChatModelConfigsAIProviderID ForeignKeyConstraint = "chat_model_configs_ai_provider_id_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_ai_provider_id_fkey FOREIGN KEY (ai_provider_id) REFERENCES ai_providers(id);
ForeignKeyChatModelConfigsCreatedBy ForeignKeyConstraint = "chat_model_configs_created_by_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id);
ForeignKeyChatModelConfigsUpdatedBy ForeignKeyConstraint = "chat_model_configs_updated_by_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES users(id);
ForeignKeyChatQueuedMessagesAPIKeyID ForeignKeyConstraint = "chat_queued_messages_api_key_id_fkey" // ALTER TABLE ONLY chat_queued_messages ADD CONSTRAINT chat_queued_messages_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE SET NULL;
@@ -48,7 +48,7 @@ const (
ForeignKeyGitAuthLinksOauthRefreshTokenKeyID ForeignKeyConstraint = "git_auth_links_oauth_refresh_token_key_id_fkey" // ALTER TABLE ONLY external_auth_links ADD CONSTRAINT git_auth_links_oauth_refresh_token_key_id_fkey FOREIGN KEY (oauth_refresh_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
ForeignKeyGitSSHKeysPrivateKeyKeyID ForeignKeyConstraint = "gitsshkeys_private_key_key_id_fkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_private_key_key_id_fkey FOREIGN KEY (private_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
ForeignKeyGitSSHKeysUserID ForeignKeyConstraint = "gitsshkeys_user_id_fkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
ForeignKeyGroupAiBudgetsGroupID ForeignKeyConstraint = "group_ai_budgets_group_id_fkey" // ALTER TABLE ONLY group_ai_budgets ADD CONSTRAINT group_ai_budgets_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
ForeignKeyGroupAIBudgetsGroupID ForeignKeyConstraint = "group_ai_budgets_group_id_fkey" // ALTER TABLE ONLY group_ai_budgets ADD CONSTRAINT group_ai_budgets_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
ForeignKeyGroupMembersGroupID ForeignKeyConstraint = "group_members_group_id_fkey" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
ForeignKeyGroupMembersUserID ForeignKeyConstraint = "group_members_user_id_fkey" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyGroupsOrganizationID ForeignKeyConstraint = "groups_organization_id_fkey" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
@@ -106,11 +106,11 @@ const (
ForeignKeyTemplateVersionsTemplateID ForeignKeyConstraint = "template_versions_template_id_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_fkey FOREIGN KEY (template_id) REFERENCES templates(id) ON DELETE CASCADE;
ForeignKeyTemplatesCreatedBy ForeignKeyConstraint = "templates_created_by_fkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT;
ForeignKeyTemplatesOrganizationID ForeignKeyConstraint = "templates_organization_id_fkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
ForeignKeyUserAiBudgetOverridesGroupID ForeignKeyConstraint = "user_ai_budget_overrides_group_id_fkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
ForeignKeyUserAiBudgetOverridesUserID ForeignKeyConstraint = "user_ai_budget_overrides_user_id_fkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyUserAiProviderKeysAiProviderID ForeignKeyConstraint = "user_ai_provider_keys_ai_provider_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_ai_provider_id_fkey FOREIGN KEY (ai_provider_id) REFERENCES ai_providers(id) ON DELETE CASCADE;
ForeignKeyUserAiProviderKeysAPIKeyKeyID ForeignKeyConstraint = "user_ai_provider_keys_api_key_key_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_api_key_key_id_fkey FOREIGN KEY (api_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
ForeignKeyUserAiProviderKeysUserID ForeignKeyConstraint = "user_ai_provider_keys_user_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyUserAIBudgetOverridesGroupID ForeignKeyConstraint = "user_ai_budget_overrides_group_id_fkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
ForeignKeyUserAIBudgetOverridesUserID ForeignKeyConstraint = "user_ai_budget_overrides_user_id_fkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyUserAIProviderKeysAIProviderID ForeignKeyConstraint = "user_ai_provider_keys_ai_provider_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_ai_provider_id_fkey FOREIGN KEY (ai_provider_id) REFERENCES ai_providers(id) ON DELETE CASCADE;
ForeignKeyUserAIProviderKeysAPIKeyKeyID ForeignKeyConstraint = "user_ai_provider_keys_api_key_key_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_api_key_key_id_fkey FOREIGN KEY (api_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
ForeignKeyUserAIProviderKeysUserID ForeignKeyConstraint = "user_ai_provider_keys_user_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyUserConfigsUserID ForeignKeyConstraint = "user_configs_user_id_fkey" // ALTER TABLE ONLY user_configs ADD CONSTRAINT user_configs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ForeignKeyUserDeletedUserID ForeignKeyConstraint = "user_deleted_user_id_fkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
ForeignKeyUserLinksOauthAccessTokenKeyID ForeignKeyConstraint = "user_links_oauth_access_token_key_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_oauth_access_token_key_id_fkey FOREIGN KEY (oauth_access_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
+13 -13
View File
@@ -84,38 +84,38 @@ type AuditableGroup struct {
Members []GroupMemberTable `json:"members"`
}
// AuditableGroupAiBudget is the audit-log representation of GroupAiBudget.
// AuditableGroupAIBudget is the audit-log representation of GroupAIBudget.
// It enriches the raw record with the group's name and a human-readable
// spend limit so audit entries can display meaningful values instead of
// UUIDs and micros.
type AuditableGroupAiBudget struct {
GroupAiBudget
type AuditableGroupAIBudget struct {
GroupAIBudget
GroupName string `json:"group_name"`
SpendLimit string `json:"spend_limit"`
}
func (b GroupAiBudget) Auditable(groupName string) AuditableGroupAiBudget {
return AuditableGroupAiBudget{
GroupAiBudget: b,
func (b GroupAIBudget) Auditable(groupName string) AuditableGroupAIBudget {
return AuditableGroupAIBudget{
GroupAIBudget: b,
GroupName: groupName,
SpendLimit: fmt.Sprintf("$%.2f", float64(b.SpendLimitMicros)/1_000_000),
}
}
// AuditableUserAiBudgetOverride is the audit-log representation of
// UserAiBudgetOverride. It enriches the raw record with the username, the
// AuditableUserAIBudgetOverride is the audit-log representation of
// UserAIBudgetOverride. It enriches the raw record with the username, the
// attributed group's name, and a human-readable spend limit so audit
// entries can display meaningful values instead of UUIDs and micros.
type AuditableUserAiBudgetOverride struct {
UserAiBudgetOverride
type AuditableUserAIBudgetOverride struct {
UserAIBudgetOverride
Username string `json:"username"`
GroupName string `json:"group_name"`
SpendLimit string `json:"spend_limit"`
}
func (o UserAiBudgetOverride) Auditable(username, groupName string) AuditableUserAiBudgetOverride {
return AuditableUserAiBudgetOverride{
UserAiBudgetOverride: o,
func (o UserAIBudgetOverride) Auditable(username, groupName string) AuditableUserAIBudgetOverride {
return AuditableUserAIBudgetOverride{
UserAIBudgetOverride: o,
Username: username,
GroupName: groupName,
SpendLimit: fmt.Sprintf("$%.2f", float64(o.SpendLimitMicros)/1_000_000),
+163 -163
View File
@@ -19,15 +19,15 @@ import (
type AIProviderType string
const (
AiProviderTypeOpenai AIProviderType = "openai"
AiProviderTypeAnthropic AIProviderType = "anthropic"
AiProviderTypeAzure AIProviderType = "azure"
AiProviderTypeBedrock AIProviderType = "bedrock"
AiProviderTypeGoogle AIProviderType = "google"
AiProviderTypeOpenaiCompat AIProviderType = "openai-compat"
AiProviderTypeOpenrouter AIProviderType = "openrouter"
AiProviderTypeVercel AIProviderType = "vercel"
AiProviderTypeCopilot AIProviderType = "copilot"
AIProviderTypeOpenai AIProviderType = "openai"
AIProviderTypeAnthropic AIProviderType = "anthropic"
AIProviderTypeAzure AIProviderType = "azure"
AIProviderTypeBedrock AIProviderType = "bedrock"
AIProviderTypeGoogle AIProviderType = "google"
AIProviderTypeOpenaiCompat AIProviderType = "openai-compat"
AIProviderTypeOpenrouter AIProviderType = "openrouter"
AIProviderTypeVercel AIProviderType = "vercel"
AIProviderTypeCopilot AIProviderType = "copilot"
)
func (e *AIProviderType) Scan(src interface{}) error {
@@ -67,15 +67,15 @@ func (ns NullAIProviderType) Value() (driver.Value, error) {
func (e AIProviderType) Valid() bool {
switch e {
case AiProviderTypeOpenai,
AiProviderTypeAnthropic,
AiProviderTypeAzure,
AiProviderTypeBedrock,
AiProviderTypeGoogle,
AiProviderTypeOpenaiCompat,
AiProviderTypeOpenrouter,
AiProviderTypeVercel,
AiProviderTypeCopilot:
case AIProviderTypeOpenai,
AIProviderTypeAnthropic,
AIProviderTypeAzure,
AIProviderTypeBedrock,
AIProviderTypeGoogle,
AIProviderTypeOpenaiCompat,
AIProviderTypeOpenrouter,
AIProviderTypeVercel,
AIProviderTypeCopilot:
return true
}
return false
@@ -83,15 +83,73 @@ func (e AIProviderType) Valid() bool {
func AllAIProviderTypeValues() []AIProviderType {
return []AIProviderType{
AiProviderTypeOpenai,
AiProviderTypeAnthropic,
AiProviderTypeAzure,
AiProviderTypeBedrock,
AiProviderTypeGoogle,
AiProviderTypeOpenaiCompat,
AiProviderTypeOpenrouter,
AiProviderTypeVercel,
AiProviderTypeCopilot,
AIProviderTypeOpenai,
AIProviderTypeAnthropic,
AIProviderTypeAzure,
AIProviderTypeBedrock,
AIProviderTypeGoogle,
AIProviderTypeOpenaiCompat,
AIProviderTypeOpenrouter,
AIProviderTypeVercel,
AIProviderTypeCopilot,
}
}
type AISeatUsageReason string
const (
AISeatUsageReasonAibridge AISeatUsageReason = "aibridge"
AISeatUsageReasonTask AISeatUsageReason = "task"
)
func (e *AISeatUsageReason) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = AISeatUsageReason(s)
case string:
*e = AISeatUsageReason(s)
default:
return fmt.Errorf("unsupported scan type for AISeatUsageReason: %T", src)
}
return nil
}
type NullAISeatUsageReason struct {
AISeatUsageReason AISeatUsageReason `json:"ai_seat_usage_reason"`
Valid bool `json:"valid"` // Valid is true if AISeatUsageReason is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullAISeatUsageReason) Scan(value interface{}) error {
if value == nil {
ns.AISeatUsageReason, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.AISeatUsageReason.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullAISeatUsageReason) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.AISeatUsageReason), nil
}
func (e AISeatUsageReason) Valid() bool {
switch e {
case AISeatUsageReasonAibridge,
AISeatUsageReasonTask:
return true
}
return false
}
func AllAISeatUsageReasonValues() []AISeatUsageReason {
return []AISeatUsageReason{
AISeatUsageReasonAibridge,
AISeatUsageReasonTask,
}
}
@@ -303,17 +361,17 @@ const (
ApiKeyScopeChatUpdate APIKeyScope = "chat:update"
ApiKeyScopeChatDelete APIKeyScope = "chat:delete"
ApiKeyScopeChat APIKeyScope = "chat:*"
ApiKeyScopeAiSeat APIKeyScope = "ai_seat:*"
ApiKeyScopeAiSeatCreate APIKeyScope = "ai_seat:create"
ApiKeyScopeAiSeatRead APIKeyScope = "ai_seat:read"
ApiKeyScopeAiModelPrice APIKeyScope = "ai_model_price:*"
ApiKeyScopeAiModelPriceRead APIKeyScope = "ai_model_price:read"
ApiKeyScopeAiModelPriceUpdate APIKeyScope = "ai_model_price:update"
ApiKeyScopeAiProvider APIKeyScope = "ai_provider:*"
ApiKeyScopeAiProviderCreate APIKeyScope = "ai_provider:create"
ApiKeyScopeAiProviderDelete APIKeyScope = "ai_provider:delete"
ApiKeyScopeAiProviderRead APIKeyScope = "ai_provider:read"
ApiKeyScopeAiProviderUpdate APIKeyScope = "ai_provider:update"
ApiKeyScopeAISeat APIKeyScope = "ai_seat:*"
ApiKeyScopeAISeatCreate APIKeyScope = "ai_seat:create"
ApiKeyScopeAISeatRead APIKeyScope = "ai_seat:read"
ApiKeyScopeAIModelPrice APIKeyScope = "ai_model_price:*"
ApiKeyScopeAIModelPriceRead APIKeyScope = "ai_model_price:read"
ApiKeyScopeAIModelPriceUpdate APIKeyScope = "ai_model_price:update"
ApiKeyScopeAIProvider APIKeyScope = "ai_provider:*"
ApiKeyScopeAIProviderCreate APIKeyScope = "ai_provider:create"
ApiKeyScopeAIProviderDelete APIKeyScope = "ai_provider:delete"
ApiKeyScopeAIProviderRead APIKeyScope = "ai_provider:read"
ApiKeyScopeAIProviderUpdate APIKeyScope = "ai_provider:update"
ApiKeyScopeChatShare APIKeyScope = "chat:share"
ApiKeyScopeUserSkillCreate APIKeyScope = "user_skill:create"
ApiKeyScopeUserSkillRead APIKeyScope = "user_skill:read"
@@ -324,10 +382,10 @@ const (
ApiKeyScopeBoundaryLogCreate APIKeyScope = "boundary_log:create"
ApiKeyScopeBoundaryLogDelete APIKeyScope = "boundary_log:delete"
ApiKeyScopeBoundaryLogRead APIKeyScope = "boundary_log:read"
ApiKeyScopeAiGatewayKey APIKeyScope = "ai_gateway_key:*"
ApiKeyScopeAiGatewayKeyCreate APIKeyScope = "ai_gateway_key:create"
ApiKeyScopeAiGatewayKeyDelete APIKeyScope = "ai_gateway_key:delete"
ApiKeyScopeAiGatewayKeyRead APIKeyScope = "ai_gateway_key:read"
ApiKeyScopeAIGatewayKey APIKeyScope = "ai_gateway_key:*"
ApiKeyScopeAIGatewayKeyCreate APIKeyScope = "ai_gateway_key:create"
ApiKeyScopeAIGatewayKeyDelete APIKeyScope = "ai_gateway_key:delete"
ApiKeyScopeAIGatewayKeyRead APIKeyScope = "ai_gateway_key:read"
)
func (e *APIKeyScope) Scan(src interface{}) error {
@@ -572,17 +630,17 @@ func (e APIKeyScope) Valid() bool {
ApiKeyScopeChatUpdate,
ApiKeyScopeChatDelete,
ApiKeyScopeChat,
ApiKeyScopeAiSeat,
ApiKeyScopeAiSeatCreate,
ApiKeyScopeAiSeatRead,
ApiKeyScopeAiModelPrice,
ApiKeyScopeAiModelPriceRead,
ApiKeyScopeAiModelPriceUpdate,
ApiKeyScopeAiProvider,
ApiKeyScopeAiProviderCreate,
ApiKeyScopeAiProviderDelete,
ApiKeyScopeAiProviderRead,
ApiKeyScopeAiProviderUpdate,
ApiKeyScopeAISeat,
ApiKeyScopeAISeatCreate,
ApiKeyScopeAISeatRead,
ApiKeyScopeAIModelPrice,
ApiKeyScopeAIModelPriceRead,
ApiKeyScopeAIModelPriceUpdate,
ApiKeyScopeAIProvider,
ApiKeyScopeAIProviderCreate,
ApiKeyScopeAIProviderDelete,
ApiKeyScopeAIProviderRead,
ApiKeyScopeAIProviderUpdate,
ApiKeyScopeChatShare,
ApiKeyScopeUserSkillCreate,
ApiKeyScopeUserSkillRead,
@@ -593,10 +651,10 @@ func (e APIKeyScope) Valid() bool {
ApiKeyScopeBoundaryLogCreate,
ApiKeyScopeBoundaryLogDelete,
ApiKeyScopeBoundaryLogRead,
ApiKeyScopeAiGatewayKey,
ApiKeyScopeAiGatewayKeyCreate,
ApiKeyScopeAiGatewayKeyDelete,
ApiKeyScopeAiGatewayKeyRead:
ApiKeyScopeAIGatewayKey,
ApiKeyScopeAIGatewayKeyCreate,
ApiKeyScopeAIGatewayKeyDelete,
ApiKeyScopeAIGatewayKeyRead:
return true
}
return false
@@ -809,17 +867,17 @@ func AllAPIKeyScopeValues() []APIKeyScope {
ApiKeyScopeChatUpdate,
ApiKeyScopeChatDelete,
ApiKeyScopeChat,
ApiKeyScopeAiSeat,
ApiKeyScopeAiSeatCreate,
ApiKeyScopeAiSeatRead,
ApiKeyScopeAiModelPrice,
ApiKeyScopeAiModelPriceRead,
ApiKeyScopeAiModelPriceUpdate,
ApiKeyScopeAiProvider,
ApiKeyScopeAiProviderCreate,
ApiKeyScopeAiProviderDelete,
ApiKeyScopeAiProviderRead,
ApiKeyScopeAiProviderUpdate,
ApiKeyScopeAISeat,
ApiKeyScopeAISeatCreate,
ApiKeyScopeAISeatRead,
ApiKeyScopeAIModelPrice,
ApiKeyScopeAIModelPriceRead,
ApiKeyScopeAIModelPriceUpdate,
ApiKeyScopeAIProvider,
ApiKeyScopeAIProviderCreate,
ApiKeyScopeAIProviderDelete,
ApiKeyScopeAIProviderRead,
ApiKeyScopeAIProviderUpdate,
ApiKeyScopeChatShare,
ApiKeyScopeUserSkillCreate,
ApiKeyScopeUserSkillRead,
@@ -830,10 +888,10 @@ func AllAPIKeyScopeValues() []APIKeyScope {
ApiKeyScopeBoundaryLogCreate,
ApiKeyScopeBoundaryLogDelete,
ApiKeyScopeBoundaryLogRead,
ApiKeyScopeAiGatewayKey,
ApiKeyScopeAiGatewayKeyCreate,
ApiKeyScopeAiGatewayKeyDelete,
ApiKeyScopeAiGatewayKeyRead,
ApiKeyScopeAIGatewayKey,
ApiKeyScopeAIGatewayKeyCreate,
ApiKeyScopeAIGatewayKeyDelete,
ApiKeyScopeAIGatewayKeyRead,
}
}
@@ -895,64 +953,6 @@ func AllAgentKeyScopeEnumValues() []AgentKeyScopeEnum {
}
}
type AiSeatUsageReason string
const (
AiSeatUsageReasonAibridge AiSeatUsageReason = "aibridge"
AiSeatUsageReasonTask AiSeatUsageReason = "task"
)
func (e *AiSeatUsageReason) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = AiSeatUsageReason(s)
case string:
*e = AiSeatUsageReason(s)
default:
return fmt.Errorf("unsupported scan type for AiSeatUsageReason: %T", src)
}
return nil
}
type NullAiSeatUsageReason struct {
AiSeatUsageReason AiSeatUsageReason `json:"ai_seat_usage_reason"`
Valid bool `json:"valid"` // Valid is true if AiSeatUsageReason is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullAiSeatUsageReason) Scan(value interface{}) error {
if value == nil {
ns.AiSeatUsageReason, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.AiSeatUsageReason.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullAiSeatUsageReason) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.AiSeatUsageReason), nil
}
func (e AiSeatUsageReason) Valid() bool {
switch e {
case AiSeatUsageReasonAibridge,
AiSeatUsageReasonTask:
return true
}
return false
}
func AllAiSeatUsageReasonValues() []AiSeatUsageReason {
return []AiSeatUsageReason{
AiSeatUsageReasonAibridge,
AiSeatUsageReasonTask,
}
}
type AppSharingLevel string
const (
@@ -3361,15 +3361,15 @@ const (
ResourceTypeWorkspaceApp ResourceType = "workspace_app"
ResourceTypePrebuildsSettings ResourceType = "prebuilds_settings"
ResourceTypeTask ResourceType = "task"
ResourceTypeAiSeat ResourceType = "ai_seat"
ResourceTypeAISeat ResourceType = "ai_seat"
ResourceTypeChat ResourceType = "chat"
ResourceTypeUserSecret ResourceType = "user_secret"
ResourceTypeAIProvider ResourceType = "ai_provider"
ResourceTypeAIProviderKey ResourceType = "ai_provider_key"
ResourceTypeGroupAiBudget ResourceType = "group_ai_budget"
ResourceTypeGroupAIBudget ResourceType = "group_ai_budget"
ResourceTypeUserSkill ResourceType = "user_skill"
ResourceTypeAIGatewayKey ResourceType = "ai_gateway_key"
ResourceTypeUserAiBudgetOverride ResourceType = "user_ai_budget_override"
ResourceTypeUserAIBudgetOverride ResourceType = "user_ai_budget_override"
)
func (e *ResourceType) Scan(src interface{}) error {
@@ -3435,15 +3435,15 @@ func (e ResourceType) Valid() bool {
ResourceTypeWorkspaceApp,
ResourceTypePrebuildsSettings,
ResourceTypeTask,
ResourceTypeAiSeat,
ResourceTypeAISeat,
ResourceTypeChat,
ResourceTypeUserSecret,
ResourceTypeAIProvider,
ResourceTypeAIProviderKey,
ResourceTypeGroupAiBudget,
ResourceTypeGroupAIBudget,
ResourceTypeUserSkill,
ResourceTypeAIGatewayKey,
ResourceTypeUserAiBudgetOverride:
ResourceTypeUserAIBudgetOverride:
return true
}
return false
@@ -3477,15 +3477,15 @@ func AllResourceTypeValues() []ResourceType {
ResourceTypeWorkspaceApp,
ResourceTypePrebuildsSettings,
ResourceTypeTask,
ResourceTypeAiSeat,
ResourceTypeAISeat,
ResourceTypeChat,
ResourceTypeUserSecret,
ResourceTypeAIProvider,
ResourceTypeAIProviderKey,
ResourceTypeGroupAiBudget,
ResourceTypeGroupAIBudget,
ResourceTypeUserSkill,
ResourceTypeAIGatewayKey,
ResourceTypeUserAiBudgetOverride,
ResourceTypeUserAIBudgetOverride,
}
}
@@ -4614,6 +4614,18 @@ type AIGatewayKey struct {
LastUsedAt sql.NullTime `db:"last_used_at" json:"last_used_at"`
}
// Per-model token prices used by AI Bridge to compute interception cost.
type AIModelPrice struct {
Provider string `db:"provider" json:"provider"`
Model string `db:"model" json:"model"`
InputPrice sql.NullInt64 `db:"input_price" json:"input_price"`
OutputPrice sql.NullInt64 `db:"output_price" json:"output_price"`
CacheReadPrice sql.NullInt64 `db:"cache_read_price" json:"cache_read_price"`
CacheWritePrice sql.NullInt64 `db:"cache_write_price" json:"cache_write_price"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
// Runtime configuration for AI providers. Authoritative source for the provider set served by aibridged. Replaces deployment-time CODER_AIBRIDGE_* environment variables.
type AIProvider struct {
ID uuid.UUID `db:"id" json:"id"`
@@ -4645,6 +4657,15 @@ type AIProviderKey struct {
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
type AISeatState struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
FirstUsedAt time.Time `db:"first_used_at" json:"first_used_at"`
LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"`
LastEventType AISeatUsageReason `db:"last_event_type" json:"last_event_type"`
LastEventDescription string `db:"last_event_description" json:"last_event_description"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
type APIKey struct {
ID string `db:"id" json:"id"`
// hashed_secret contains a SHA256 hash of the key secret. This is considered a secret and MUST NOT be returned from the API as it is used for API key encryption in app proxying code.
@@ -4662,27 +4683,6 @@ type APIKey struct {
AllowList AllowList `db:"allow_list" json:"allow_list"`
}
// Per-model token prices used by AI Bridge to compute interception cost.
type AiModelPrice struct {
Provider string `db:"provider" json:"provider"`
Model string `db:"model" json:"model"`
InputPrice sql.NullInt64 `db:"input_price" json:"input_price"`
OutputPrice sql.NullInt64 `db:"output_price" json:"output_price"`
CacheReadPrice sql.NullInt64 `db:"cache_read_price" json:"cache_read_price"`
CacheWritePrice sql.NullInt64 `db:"cache_write_price" json:"cache_write_price"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
type AiSeatState struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
FirstUsedAt time.Time `db:"first_used_at" json:"first_used_at"`
LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"`
LastEventType AiSeatUsageReason `db:"last_event_type" json:"last_event_type"`
LastEventDescription string `db:"last_event_description" json:"last_event_description"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
type AuditLog struct {
ID uuid.UUID `db:"id" json:"id"`
Time time.Time `db:"time" json:"time"`
@@ -5126,7 +5126,7 @@ type Group struct {
}
// Per-group AI spend limit applied to each member of the group. No row means no budget is enforced.
type GroupAiBudget struct {
type GroupAIBudget struct {
GroupID uuid.UUID `db:"group_id" json:"group_id"`
SpendLimitMicros int64 `db:"spend_limit_micros" json:"spend_limit_micros"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
@@ -5955,7 +5955,7 @@ type User struct {
}
// Per-user AI spend override that supersedes group budget resolution.
type UserAiBudgetOverride struct {
type UserAIBudgetOverride struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
GroupID uuid.UUID `db:"group_id" json:"group_id"`
SpendLimitMicros int64 `db:"spend_limit_micros" json:"spend_limit_micros"`
@@ -5964,7 +5964,7 @@ type UserAiBudgetOverride struct {
}
// User-owned API keys associated with AI providers. These keys are used only when BYOK is enabled.
type UserAiProviderKey struct {
type UserAIProviderKey struct {
ID uuid.UUID `db:"id" json:"id"`
UserID uuid.UUID `db:"user_id" json:"user_id"`
AIProviderID uuid.UUID `db:"ai_provider_id" json:"ai_provider_id"`
+13 -13
View File
@@ -153,7 +153,7 @@ type sqlcQuerier interface {
DeleteCustomRole(ctx context.Context, arg DeleteCustomRoleParams) error
DeleteExpiredAPIKeys(ctx context.Context, arg DeleteExpiredAPIKeysParams) (int64, error)
DeleteExternalAuthLink(ctx context.Context, arg DeleteExternalAuthLinkParams) error
DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (GroupAiBudget, error)
DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (GroupAIBudget, error)
DeleteGroupByID(ctx context.Context, id uuid.UUID) error
DeleteGroupMemberFromGroup(ctx context.Context, arg DeleteGroupMemberFromGroupParams) error
DeleteLicense(ctx context.Context, id int32) (int32, error)
@@ -223,7 +223,7 @@ type sqlcQuerier interface {
DeleteTailnetPeer(ctx context.Context, arg DeleteTailnetPeerParams) (DeleteTailnetPeerRow, error)
DeleteTailnetTunnel(ctx context.Context, arg DeleteTailnetTunnelParams) (DeleteTailnetTunnelRow, error)
DeleteTask(ctx context.Context, arg DeleteTaskParams) (uuid.UUID, error)
DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (UserAiBudgetOverride, error)
DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (UserAIBudgetOverride, error)
DeleteUserAIProviderKey(ctx context.Context, arg DeleteUserAIProviderKeyParams) error
DeleteUserAIProviderKeysByProviderID(ctx context.Context, aiProviderID uuid.UUID) error
DeleteUserChatCompactionThreshold(ctx context.Context, arg DeleteUserChatCompactionThresholdParams) error
@@ -290,7 +290,7 @@ type sqlcQuerier interface {
GetAIBridgeTokenUsagesByInterceptionID(ctx context.Context, interceptionID uuid.UUID) ([]AIBridgeTokenUsage, error)
GetAIBridgeToolUsagesByInterceptionID(ctx context.Context, interceptionID uuid.UUID) ([]AIBridgeToolUsage, error)
GetAIBridgeUserPromptsByInterceptionID(ctx context.Context, interceptionID uuid.UUID) ([]AIBridgeUserPrompt, error)
GetAIModelPriceByProviderModel(ctx context.Context, arg GetAIModelPriceByProviderModelParams) (AiModelPrice, error)
GetAIModelPriceByProviderModel(ctx context.Context, arg GetAIModelPriceByProviderModelParams) (AIModelPrice, error)
GetAIProviderByID(ctx context.Context, id uuid.UUID) (AIProvider, error)
// Lock the provider row until the model-config write completes. The
// transaction alone does not stop a concurrent soft-delete or disable
@@ -552,7 +552,7 @@ type sqlcQuerier interface {
GetFilteredInboxNotificationsByUserID(ctx context.Context, arg GetFilteredInboxNotificationsByUserIDParams) ([]InboxNotification, error)
GetForcedMCPServerConfigs(ctx context.Context) ([]MCPServerConfig, error)
GetGitSSHKey(ctx context.Context, userID uuid.UUID) (GitSSHKey, error)
GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (GroupAiBudget, error)
GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (GroupAIBudget, error)
GetGroupByID(ctx context.Context, id uuid.UUID) (Group, error)
GetGroupByOrgAndName(ctx context.Context, arg GetGroupByOrgAndNameParams) (Group, error)
GetGroupMembers(ctx context.Context, includeSystem bool) ([]GroupMember, error)
@@ -824,12 +824,12 @@ type sqlcQuerier interface {
// inclusive.
GetTotalUsageDCManagedAgentsV1(ctx context.Context, arg GetTotalUsageDCManagedAgentsV1Params) (int64, error)
GetUnexpiredLicenses(ctx context.Context) ([]License, error)
GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (UserAiBudgetOverride, error)
GetUserAIProviderKeyByProviderID(ctx context.Context, arg GetUserAIProviderKeyByProviderIDParams) (UserAiProviderKey, error)
GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (UserAIBudgetOverride, error)
GetUserAIProviderKeyByProviderID(ctx context.Context, arg GetUserAIProviderKeyByProviderIDParams) (UserAIProviderKey, error)
// GetUserAIProviderKeys is used by dbcrypt key rotation. Request paths should use
// user-scoped lookups instead of this bulk accessor.
GetUserAIProviderKeys(ctx context.Context) ([]UserAiProviderKey, error)
GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]UserAiProviderKey, error)
GetUserAIProviderKeys(ctx context.Context) ([]UserAIProviderKey, error)
GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]UserAIProviderKey, error)
// Returns user IDs from the provided list that are consuming an AI seat.
// Filters to active, non-deleted, non-system users to match the canonical
// seat count query (GetActiveAISeatCount).
@@ -1377,7 +1377,7 @@ type sqlcQuerier interface {
// Used by the dbcrypt key rotation utility to re-encrypt or decrypt
// rows in place.
UpdateEncryptedAIProviderSettings(ctx context.Context, arg UpdateEncryptedAIProviderSettingsParams) (AIProvider, error)
UpdateEncryptedUserAIProviderKey(ctx context.Context, arg UpdateEncryptedUserAIProviderKeyParams) (UserAiProviderKey, error)
UpdateEncryptedUserAIProviderKey(ctx context.Context, arg UpdateEncryptedUserAIProviderKeyParams) (UserAIProviderKey, error)
UpdateExternalAuthLink(ctx context.Context, arg UpdateExternalAuthLinkParams) (ExternalAuthLink, error)
// Optimistic lock: only update the row if the refresh token in the database
// still matches the one we read before attempting the refresh. This prevents
@@ -1426,7 +1426,7 @@ type sqlcQuerier interface {
UpdateTemplateVersionFlagsByJobID(ctx context.Context, arg UpdateTemplateVersionFlagsByJobIDParams) error
UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, arg UpdateTemplateWorkspacesLastUsedAtParams) error
UpdateUsageEventsPostPublish(ctx context.Context, arg UpdateUsageEventsPostPublishParams) error
UpdateUserAIProviderKey(ctx context.Context, arg UpdateUserAIProviderKeyParams) (UserAiProviderKey, error)
UpdateUserAIProviderKey(ctx context.Context, arg UpdateUserAIProviderKeyParams) (UserAIProviderKey, error)
UpdateUserAgentChatSendShortcut(ctx context.Context, arg UpdateUserAgentChatSendShortcutParams) (string, error)
UpdateUserChatCompactionThreshold(ctx context.Context, arg UpdateUserChatCompactionThresholdParams) (UserConfig, error)
UpdateUserChatCustomPrompt(ctx context.Context, arg UpdateUserChatCustomPromptParams) (UserConfig, error)
@@ -1532,7 +1532,7 @@ type sqlcQuerier interface {
// So we need to store it's configuration here for display purposes.
// The functional values are immutable and controlled implicitly.
UpsertDefaultProxy(ctx context.Context, arg UpsertDefaultProxyParams) error
UpsertGroupAIBudget(ctx context.Context, arg UpsertGroupAIBudgetParams) (GroupAiBudget, error)
UpsertGroupAIBudget(ctx context.Context, arg UpsertGroupAIBudgetParams) (GroupAIBudget, error)
UpsertHealthSettings(ctx context.Context, value string) error
UpsertLastUpdateCheck(ctx context.Context, value string) error
UpsertLogoURL(ctx context.Context, value string) error
@@ -1555,11 +1555,11 @@ type sqlcQuerier interface {
// used to store the data, and the minutes are summed for each user and template
// combination. The result is stored in the template_usage_stats table.
UpsertTemplateUsageStats(ctx context.Context) error
UpsertUserAIBudgetOverride(ctx context.Context, arg UpsertUserAIBudgetOverrideParams) (UserAiBudgetOverride, error)
UpsertUserAIBudgetOverride(ctx context.Context, arg UpsertUserAIBudgetOverrideParams) (UserAIBudgetOverride, error)
// UpsertUserAIProviderKey preserves the original id and created_at when the
// user/provider pair already exists. On conflict, callers provide id and
// created_at for the insert path only.
UpsertUserAIProviderKey(ctx context.Context, arg UpsertUserAIProviderKeyParams) (UserAiProviderKey, error)
UpsertUserAIProviderKey(ctx context.Context, arg UpsertUserAIProviderKeyParams) (UserAIProviderKey, error)
UpsertUserChatDebugLoggingEnabled(ctx context.Context, arg UpsertUserChatDebugLoggingEnabledParams) error
UpsertUserChatPersonalModelOverride(ctx context.Context, arg UpsertUserChatPersonalModelOverrideParams) error
UpsertWebpushVAPIDKeys(ctx context.Context, arg UpsertWebpushVAPIDKeysParams) error
+20 -20
View File
@@ -11087,11 +11087,11 @@ func TestGetEnabledChatModelConfigsUsesAIProviders(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
enabledProvider := dbgen.AIProvider(t, store, database.AIProvider{
Type: database.AiProviderTypeOpenrouter,
Type: database.AIProviderTypeOpenrouter,
Name: "openrouter-" + uuid.NewString(),
})
disabledProvider := dbgen.AIProvider(t, store, database.AIProvider{
Type: database.AiProviderTypeVercel,
Type: database.AIProviderTypeVercel,
Name: "vercel-" + uuid.NewString(),
}, func(params *database.InsertAIProviderParams) {
params.Enabled = false
@@ -11400,7 +11400,7 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {
// An AI provider row is required as a FK for model configs.
provider := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Name: "test-" + uuid.NewString(),
DisplayName: sql.NullString{String: "OpenAI", Valid: true},
Enabled: true,
@@ -11739,7 +11739,7 @@ func TestUpsertAISeats(t *testing.T) {
newRow, err := db.UpsertAISeatState(ctx, database.UpsertAISeatStateParams{
UserID: user.ID,
FirstUsedAt: now.Add(time.Hour * -24),
LastEventType: database.AiSeatUsageReasonTask,
LastEventType: database.AISeatUsageReasonTask,
})
require.NoError(t, err)
require.True(t, newRow)
@@ -11747,7 +11747,7 @@ func TestUpsertAISeats(t *testing.T) {
alreadyExists, err := db.UpsertAISeatState(ctx, database.UpsertAISeatStateParams{
UserID: user.ID,
FirstUsedAt: now.Add(time.Hour * -23),
LastEventType: database.AiSeatUsageReasonTask,
LastEventType: database.AISeatUsageReasonTask,
})
require.NoError(t, err)
require.False(t, alreadyExists)
@@ -11755,7 +11755,7 @@ func TestUpsertAISeats(t *testing.T) {
alreadyExists, err = db.UpsertAISeatState(ctx, database.UpsertAISeatStateParams{
UserID: user.ID,
FirstUsedAt: now,
LastEventType: database.AiSeatUsageReasonTask,
LastEventType: database.AISeatUsageReasonTask,
})
require.NoError(t, err)
require.False(t, alreadyExists)
@@ -14604,7 +14604,7 @@ func TestGetChatsFilter(t *testing.T) {
dbgen.OrganizationMember(t, store, database.OrganizationMember{UserID: user.ID, OrganizationID: org.ID})
provider := dbgen.AIProviderWithOptionalKey(t, store, database.AIProvider{
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
}, "test-key")
modelCfg, err := store.InsertChatModelConfig(ctx, database.InsertChatModelConfigParams{
@@ -15395,67 +15395,67 @@ func TestAIGatewayKeysTableConstraints(t *testing.T) {
{
name: "duplicate name",
params: aiGatewayKeyParams(preExisting.Name, "key_test002"),
expectUniqueErr: database.UniqueAiGatewayKeysNameIndex,
expectUniqueErr: database.UniqueAIGatewayKeysNameIndex,
},
{
name: "duplicate secret prefix",
params: aiGatewayKeyParams("different-key", preExisting.SecretPrefix),
expectUniqueErr: database.UniqueAiGatewayKeysSecretPrefixIndex,
expectUniqueErr: database.UniqueAIGatewayKeysSecretPrefixIndex,
},
{
name: "duplicate hashed secret",
params: database.InsertAIGatewayKeyParams{ID: uuid.New(), Name: "other-name", SecretPrefix: "key_1234567", HashedSecret: preExisting.HashedSecret},
expectUniqueErr: database.UniqueAiGatewayKeysHashedSecretIndex,
expectUniqueErr: database.UniqueAIGatewayKeysHashedSecretIndex,
},
{
name: "empty name",
params: aiGatewayKeyParams("", "key_empty__"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
expectCheckErr: database.CheckAIGatewayKeysNameCheck,
},
{
name: "name with trailing dash",
params: aiGatewayKeyParams("other-name-", "key_trail__"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
expectCheckErr: database.CheckAIGatewayKeysNameCheck,
},
{
name: "name with consecutive dashes",
params: aiGatewayKeyParams("other--name", "key_consec_"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
expectCheckErr: database.CheckAIGatewayKeysNameCheck,
},
{
name: "name with underscore",
params: aiGatewayKeyParams("other_name", "key_undersc"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
expectCheckErr: database.CheckAIGatewayKeysNameCheck,
},
{
name: "name with space",
params: aiGatewayKeyParams("other name", "key_spacen_"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
expectCheckErr: database.CheckAIGatewayKeysNameCheck,
},
{
name: "name with leading dash",
params: aiGatewayKeyParams("-other-name", "key_leadng_"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
expectCheckErr: database.CheckAIGatewayKeysNameCheck,
},
{
name: "name longer than 64 characters",
params: aiGatewayKeyParams(strings.Repeat("a", 65), "key_longna_"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
expectCheckErr: database.CheckAIGatewayKeysNameCheck,
},
{
name: "empty secret prefix",
params: aiGatewayKeyParams("check-empty-pfx", ""),
expectCheckErr: database.CheckAiGatewayKeysSecretPrefixCheck,
expectCheckErr: database.CheckAIGatewayKeysSecretPrefixCheck,
},
{
name: "invalid secret prefix length",
params: aiGatewayKeyParams("check-short-pfx", "key_short"),
expectCheckErr: database.CheckAiGatewayKeysSecretPrefixCheck,
expectCheckErr: database.CheckAIGatewayKeysSecretPrefixCheck,
},
{
name: "empty hashed secret",
params: database.InsertAIGatewayKeyParams{ID: uuid.New(), Name: "check-empty-hash", SecretPrefix: "key_ehash__", HashedSecret: []byte{}},
expectCheckErr: database.CheckAiGatewayKeysHashedSecretCheck,
expectCheckErr: database.CheckAIGatewayKeysHashedSecretCheck,
},
}
+29 -29
View File
@@ -2346,9 +2346,9 @@ const deleteGroupAIBudget = `-- name: DeleteGroupAIBudget :one
DELETE FROM group_ai_budgets WHERE group_id = $1 RETURNING group_id, spend_limit_micros, created_at, updated_at
`
func (q *sqlQuerier) DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (GroupAiBudget, error) {
func (q *sqlQuerier) DeleteGroupAIBudget(ctx context.Context, groupID uuid.UUID) (GroupAIBudget, error) {
row := q.db.QueryRowContext(ctx, deleteGroupAIBudget, groupID)
var i GroupAiBudget
var i GroupAIBudget
err := row.Scan(
&i.GroupID,
&i.SpendLimitMicros,
@@ -2362,9 +2362,9 @@ const deleteUserAIBudgetOverride = `-- name: DeleteUserAIBudgetOverride :one
DELETE FROM user_ai_budget_overrides WHERE user_id = $1 RETURNING user_id, group_id, spend_limit_micros, created_at, updated_at
`
func (q *sqlQuerier) DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (UserAiBudgetOverride, error) {
func (q *sqlQuerier) DeleteUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (UserAIBudgetOverride, error) {
row := q.db.QueryRowContext(ctx, deleteUserAIBudgetOverride, userID)
var i UserAiBudgetOverride
var i UserAIBudgetOverride
err := row.Scan(
&i.UserID,
&i.GroupID,
@@ -2386,9 +2386,9 @@ type GetAIModelPriceByProviderModelParams struct {
Model string `db:"model" json:"model"`
}
func (q *sqlQuerier) GetAIModelPriceByProviderModel(ctx context.Context, arg GetAIModelPriceByProviderModelParams) (AiModelPrice, error) {
func (q *sqlQuerier) GetAIModelPriceByProviderModel(ctx context.Context, arg GetAIModelPriceByProviderModelParams) (AIModelPrice, error) {
row := q.db.QueryRowContext(ctx, getAIModelPriceByProviderModel, arg.Provider, arg.Model)
var i AiModelPrice
var i AIModelPrice
err := row.Scan(
&i.Provider,
&i.Model,
@@ -2408,9 +2408,9 @@ FROM group_ai_budgets
WHERE group_id = $1
`
func (q *sqlQuerier) GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (GroupAiBudget, error) {
func (q *sqlQuerier) GetGroupAIBudget(ctx context.Context, groupID uuid.UUID) (GroupAIBudget, error) {
row := q.db.QueryRowContext(ctx, getGroupAIBudget, groupID)
var i GroupAiBudget
var i GroupAIBudget
err := row.Scan(
&i.GroupID,
&i.SpendLimitMicros,
@@ -2461,9 +2461,9 @@ FROM user_ai_budget_overrides
WHERE user_id = $1
`
func (q *sqlQuerier) GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (UserAiBudgetOverride, error) {
func (q *sqlQuerier) GetUserAIBudgetOverride(ctx context.Context, userID uuid.UUID) (UserAIBudgetOverride, error) {
row := q.db.QueryRowContext(ctx, getUserAIBudgetOverride, userID)
var i UserAiBudgetOverride
var i UserAIBudgetOverride
err := row.Scan(
&i.UserID,
&i.GroupID,
@@ -2516,9 +2516,9 @@ type UpsertGroupAIBudgetParams struct {
SpendLimitMicros int64 `db:"spend_limit_micros" json:"spend_limit_micros"`
}
func (q *sqlQuerier) UpsertGroupAIBudget(ctx context.Context, arg UpsertGroupAIBudgetParams) (GroupAiBudget, error) {
func (q *sqlQuerier) UpsertGroupAIBudget(ctx context.Context, arg UpsertGroupAIBudgetParams) (GroupAIBudget, error) {
row := q.db.QueryRowContext(ctx, upsertGroupAIBudget, arg.GroupID, arg.SpendLimitMicros)
var i GroupAiBudget
var i GroupAIBudget
err := row.Scan(
&i.GroupID,
&i.SpendLimitMicros,
@@ -2544,9 +2544,9 @@ type UpsertUserAIBudgetOverrideParams struct {
SpendLimitMicros int64 `db:"spend_limit_micros" json:"spend_limit_micros"`
}
func (q *sqlQuerier) UpsertUserAIBudgetOverride(ctx context.Context, arg UpsertUserAIBudgetOverrideParams) (UserAiBudgetOverride, error) {
func (q *sqlQuerier) UpsertUserAIBudgetOverride(ctx context.Context, arg UpsertUserAIBudgetOverrideParams) (UserAIBudgetOverride, error) {
row := q.db.QueryRowContext(ctx, upsertUserAIBudgetOverride, arg.UserID, arg.GroupID, arg.SpendLimitMicros)
var i UserAiBudgetOverride
var i UserAIBudgetOverride
err := row.Scan(
&i.UserID,
&i.GroupID,
@@ -2604,7 +2604,7 @@ RETURNING
type UpsertAISeatStateParams struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
FirstUsedAt time.Time `db:"first_used_at" json:"first_used_at"`
LastEventType AiSeatUsageReason `db:"last_event_type" json:"last_event_type"`
LastEventType AISeatUsageReason `db:"last_event_type" json:"last_event_type"`
LastEventDescription string `db:"last_event_description" json:"last_event_description"`
}
@@ -28593,9 +28593,9 @@ type GetUserAIProviderKeyByProviderIDParams struct {
AIProviderID uuid.UUID `db:"ai_provider_id" json:"ai_provider_id"`
}
func (q *sqlQuerier) GetUserAIProviderKeyByProviderID(ctx context.Context, arg GetUserAIProviderKeyByProviderIDParams) (UserAiProviderKey, error) {
func (q *sqlQuerier) GetUserAIProviderKeyByProviderID(ctx context.Context, arg GetUserAIProviderKeyByProviderIDParams) (UserAIProviderKey, error) {
row := q.db.QueryRowContext(ctx, getUserAIProviderKeyByProviderID, arg.UserID, arg.AIProviderID)
var i UserAiProviderKey
var i UserAIProviderKey
err := row.Scan(
&i.ID,
&i.UserID,
@@ -28622,15 +28622,15 @@ ORDER BY
// GetUserAIProviderKeys is used by dbcrypt key rotation. Request paths should use
// user-scoped lookups instead of this bulk accessor.
func (q *sqlQuerier) GetUserAIProviderKeys(ctx context.Context) ([]UserAiProviderKey, error) {
func (q *sqlQuerier) GetUserAIProviderKeys(ctx context.Context) ([]UserAIProviderKey, error) {
rows, err := q.db.QueryContext(ctx, getUserAIProviderKeys)
if err != nil {
return nil, err
}
defer rows.Close()
var items []UserAiProviderKey
var items []UserAIProviderKey
for rows.Next() {
var i UserAiProviderKey
var i UserAIProviderKey
if err := rows.Scan(
&i.ID,
&i.UserID,
@@ -28666,15 +28666,15 @@ ORDER BY
id ASC
`
func (q *sqlQuerier) GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]UserAiProviderKey, error) {
func (q *sqlQuerier) GetUserAIProviderKeysByUserID(ctx context.Context, userID uuid.UUID) ([]UserAIProviderKey, error) {
rows, err := q.db.QueryContext(ctx, getUserAIProviderKeysByUserID, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []UserAiProviderKey
var items []UserAIProviderKey
for rows.Next() {
var i UserAiProviderKey
var i UserAIProviderKey
if err := rows.Scan(
&i.ID,
&i.UserID,
@@ -28716,9 +28716,9 @@ type UpdateEncryptedUserAIProviderKeyParams struct {
ID uuid.UUID `db:"id" json:"id"`
}
func (q *sqlQuerier) UpdateEncryptedUserAIProviderKey(ctx context.Context, arg UpdateEncryptedUserAIProviderKeyParams) (UserAiProviderKey, error) {
func (q *sqlQuerier) UpdateEncryptedUserAIProviderKey(ctx context.Context, arg UpdateEncryptedUserAIProviderKeyParams) (UserAIProviderKey, error) {
row := q.db.QueryRowContext(ctx, updateEncryptedUserAIProviderKey, arg.APIKey, arg.ApiKeyKeyID, arg.ID)
var i UserAiProviderKey
var i UserAIProviderKey
err := row.Scan(
&i.ID,
&i.UserID,
@@ -28752,14 +28752,14 @@ type UpdateUserAIProviderKeyParams struct {
AIProviderID uuid.UUID `db:"ai_provider_id" json:"ai_provider_id"`
}
func (q *sqlQuerier) UpdateUserAIProviderKey(ctx context.Context, arg UpdateUserAIProviderKeyParams) (UserAiProviderKey, error) {
func (q *sqlQuerier) UpdateUserAIProviderKey(ctx context.Context, arg UpdateUserAIProviderKeyParams) (UserAIProviderKey, error) {
row := q.db.QueryRowContext(ctx, updateUserAIProviderKey,
arg.APIKey,
arg.ApiKeyKeyID,
arg.UserID,
arg.AIProviderID,
)
var i UserAiProviderKey
var i UserAIProviderKey
err := row.Scan(
&i.ID,
&i.UserID,
@@ -28812,7 +28812,7 @@ type UpsertUserAIProviderKeyParams struct {
// UpsertUserAIProviderKey preserves the original id and created_at when the
// user/provider pair already exists. On conflict, callers provide id and
// created_at for the insert path only.
func (q *sqlQuerier) UpsertUserAIProviderKey(ctx context.Context, arg UpsertUserAIProviderKeyParams) (UserAiProviderKey, error) {
func (q *sqlQuerier) UpsertUserAIProviderKey(ctx context.Context, arg UpsertUserAIProviderKeyParams) (UserAIProviderKey, error) {
row := q.db.QueryRowContext(ctx, upsertUserAIProviderKey,
arg.ID,
arg.UserID,
@@ -28822,7 +28822,7 @@ func (q *sqlQuerier) UpsertUserAIProviderKey(ctx context.Context, arg UpsertUser
arg.CreatedAt,
arg.UpdatedAt,
)
var i UserAiProviderKey
var i UserAIProviderKey
err := row.Scan(
&i.ID,
&i.UserID,
+5
View File
@@ -27,6 +27,11 @@ sql:
emit_db_tags: true
emit_enum_valid_method: true
emit_all_enum_values: true
initialisms:
# Keep the sqlc default initialism and add AI so generated
# identifiers follow Go naming conventions.
- id
- ai
overrides:
- column: "api_keys.scopes"
go_type:
+13 -13
View File
@@ -7,11 +7,11 @@ type UniqueConstraint string
// UniqueConstraint enums.
const (
UniqueAgentStatsPkey UniqueConstraint = "agent_stats_pkey" // ALTER TABLE ONLY workspace_agent_stats ADD CONSTRAINT agent_stats_pkey PRIMARY KEY (id);
UniqueAiGatewayKeysPkey UniqueConstraint = "ai_gateway_keys_pkey" // ALTER TABLE ONLY ai_gateway_keys ADD CONSTRAINT ai_gateway_keys_pkey PRIMARY KEY (id);
UniqueAiModelPricesPkey UniqueConstraint = "ai_model_prices_pkey" // ALTER TABLE ONLY ai_model_prices ADD CONSTRAINT ai_model_prices_pkey PRIMARY KEY (provider, model);
UniqueAiProviderKeysPkey UniqueConstraint = "ai_provider_keys_pkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_pkey PRIMARY KEY (id);
UniqueAiProvidersPkey UniqueConstraint = "ai_providers_pkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_pkey PRIMARY KEY (id);
UniqueAiSeatStatePkey UniqueConstraint = "ai_seat_state_pkey" // ALTER TABLE ONLY ai_seat_state ADD CONSTRAINT ai_seat_state_pkey PRIMARY KEY (user_id);
UniqueAIGatewayKeysPkey UniqueConstraint = "ai_gateway_keys_pkey" // ALTER TABLE ONLY ai_gateway_keys ADD CONSTRAINT ai_gateway_keys_pkey PRIMARY KEY (id);
UniqueAIModelPricesPkey UniqueConstraint = "ai_model_prices_pkey" // ALTER TABLE ONLY ai_model_prices ADD CONSTRAINT ai_model_prices_pkey PRIMARY KEY (provider, model);
UniqueAIProviderKeysPkey UniqueConstraint = "ai_provider_keys_pkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_pkey PRIMARY KEY (id);
UniqueAIProvidersPkey UniqueConstraint = "ai_providers_pkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_pkey PRIMARY KEY (id);
UniqueAISeatStatePkey UniqueConstraint = "ai_seat_state_pkey" // ALTER TABLE ONLY ai_seat_state ADD CONSTRAINT ai_seat_state_pkey PRIMARY KEY (user_id);
UniqueAibridgeInterceptionsPkey UniqueConstraint = "aibridge_interceptions_pkey" // ALTER TABLE ONLY aibridge_interceptions ADD CONSTRAINT aibridge_interceptions_pkey PRIMARY KEY (id);
UniqueAibridgeTokenUsagesPkey UniqueConstraint = "aibridge_token_usages_pkey" // ALTER TABLE ONLY aibridge_token_usages ADD CONSTRAINT aibridge_token_usages_pkey PRIMARY KEY (id);
UniqueAibridgeToolUsagesPkey UniqueConstraint = "aibridge_tool_usages_pkey" // ALTER TABLE ONLY aibridge_tool_usages ADD CONSTRAINT aibridge_tool_usages_pkey PRIMARY KEY (id);
@@ -43,7 +43,7 @@ const (
UniqueFilesPkey UniqueConstraint = "files_pkey" // ALTER TABLE ONLY files ADD CONSTRAINT files_pkey PRIMARY KEY (id);
UniqueGitAuthLinksProviderIDUserIDKey UniqueConstraint = "git_auth_links_provider_id_user_id_key" // ALTER TABLE ONLY external_auth_links ADD CONSTRAINT git_auth_links_provider_id_user_id_key UNIQUE (provider_id, user_id);
UniqueGitSSHKeysPkey UniqueConstraint = "gitsshkeys_pkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_pkey PRIMARY KEY (user_id);
UniqueGroupAiBudgetsPkey UniqueConstraint = "group_ai_budgets_pkey" // ALTER TABLE ONLY group_ai_budgets ADD CONSTRAINT group_ai_budgets_pkey PRIMARY KEY (group_id);
UniqueGroupAIBudgetsPkey UniqueConstraint = "group_ai_budgets_pkey" // ALTER TABLE ONLY group_ai_budgets ADD CONSTRAINT group_ai_budgets_pkey PRIMARY KEY (group_id);
UniqueGroupMembersUserIDGroupIDKey UniqueConstraint = "group_members_user_id_group_id_key" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_user_id_group_id_key UNIQUE (user_id, group_id);
UniqueGroupsNameOrganizationIDKey UniqueConstraint = "groups_name_organization_id_key" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_name_organization_id_key UNIQUE (name, organization_id);
UniqueGroupsPkey UniqueConstraint = "groups_pkey" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_pkey PRIMARY KEY (id);
@@ -99,9 +99,9 @@ const (
UniqueTemplatesPkey UniqueConstraint = "templates_pkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_pkey PRIMARY KEY (id);
UniqueUsageEventsDailyPkey UniqueConstraint = "usage_events_daily_pkey" // ALTER TABLE ONLY usage_events_daily ADD CONSTRAINT usage_events_daily_pkey PRIMARY KEY (day, event_type);
UniqueUsageEventsPkey UniqueConstraint = "usage_events_pkey" // ALTER TABLE ONLY usage_events ADD CONSTRAINT usage_events_pkey PRIMARY KEY (id);
UniqueUserAiBudgetOverridesPkey UniqueConstraint = "user_ai_budget_overrides_pkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_pkey PRIMARY KEY (user_id);
UniqueUserAiProviderKeysPkey UniqueConstraint = "user_ai_provider_keys_pkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_pkey PRIMARY KEY (id);
UniqueUserAiProviderKeysUserIDAiProviderIDKey UniqueConstraint = "user_ai_provider_keys_user_id_ai_provider_id_key" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_user_id_ai_provider_id_key UNIQUE (user_id, ai_provider_id);
UniqueUserAIBudgetOverridesPkey UniqueConstraint = "user_ai_budget_overrides_pkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_pkey PRIMARY KEY (user_id);
UniqueUserAIProviderKeysPkey UniqueConstraint = "user_ai_provider_keys_pkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_pkey PRIMARY KEY (id);
UniqueUserAIProviderKeysUserIDAIProviderIDKey UniqueConstraint = "user_ai_provider_keys_user_id_ai_provider_id_key" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_user_id_ai_provider_id_key UNIQUE (user_id, ai_provider_id);
UniqueUserConfigsPkey UniqueConstraint = "user_configs_pkey" // ALTER TABLE ONLY user_configs ADD CONSTRAINT user_configs_pkey PRIMARY KEY (user_id, key);
UniqueUserDeletedPkey UniqueConstraint = "user_deleted_pkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_pkey PRIMARY KEY (id);
UniqueUserLinksPkey UniqueConstraint = "user_links_pkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_pkey PRIMARY KEY (user_id, login_type);
@@ -139,10 +139,10 @@ const (
UniqueWorkspaceResourceMetadataPkey UniqueConstraint = "workspace_resource_metadata_pkey" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_pkey PRIMARY KEY (id);
UniqueWorkspaceResourcesPkey UniqueConstraint = "workspace_resources_pkey" // ALTER TABLE ONLY workspace_resources ADD CONSTRAINT workspace_resources_pkey PRIMARY KEY (id);
UniqueWorkspacesPkey UniqueConstraint = "workspaces_pkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_pkey PRIMARY KEY (id);
UniqueAiGatewayKeysHashedSecretIndex UniqueConstraint = "ai_gateway_keys_hashed_secret_idx" // CREATE UNIQUE INDEX ai_gateway_keys_hashed_secret_idx ON ai_gateway_keys USING btree (hashed_secret);
UniqueAiGatewayKeysNameIndex UniqueConstraint = "ai_gateway_keys_name_idx" // CREATE UNIQUE INDEX ai_gateway_keys_name_idx ON ai_gateway_keys USING btree (lower(name));
UniqueAiGatewayKeysSecretPrefixIndex UniqueConstraint = "ai_gateway_keys_secret_prefix_idx" // CREATE UNIQUE INDEX ai_gateway_keys_secret_prefix_idx ON ai_gateway_keys USING btree (secret_prefix);
UniqueAiProvidersNameUnique UniqueConstraint = "ai_providers_name_unique" // CREATE UNIQUE INDEX ai_providers_name_unique ON ai_providers USING btree (name) WHERE (deleted = false);
UniqueAIGatewayKeysHashedSecretIndex UniqueConstraint = "ai_gateway_keys_hashed_secret_idx" // CREATE UNIQUE INDEX ai_gateway_keys_hashed_secret_idx ON ai_gateway_keys USING btree (hashed_secret);
UniqueAIGatewayKeysNameIndex UniqueConstraint = "ai_gateway_keys_name_idx" // CREATE UNIQUE INDEX ai_gateway_keys_name_idx ON ai_gateway_keys USING btree (lower(name));
UniqueAIGatewayKeysSecretPrefixIndex UniqueConstraint = "ai_gateway_keys_secret_prefix_idx" // CREATE UNIQUE INDEX ai_gateway_keys_secret_prefix_idx ON ai_gateway_keys USING btree (secret_prefix);
UniqueAIProvidersNameUnique UniqueConstraint = "ai_providers_name_unique" // CREATE UNIQUE INDEX ai_providers_name_unique ON ai_providers USING btree (name) WHERE (deleted = false);
UniqueIndexAPIKeyName UniqueConstraint = "idx_api_key_name" // CREATE UNIQUE INDEX idx_api_key_name ON api_keys USING btree (user_id, token_name) WHERE (login_type = 'token'::login_type);
UniqueIndexChatDebugRunsIDChat UniqueConstraint = "idx_chat_debug_runs_id_chat" // CREATE UNIQUE INDEX idx_chat_debug_runs_id_chat ON chat_debug_runs USING btree (id, chat_id);
UniqueIndexChatDebugStepsRunStep UniqueConstraint = "idx_chat_debug_steps_run_step" // CREATE UNIQUE INDEX idx_chat_debug_steps_run_step ON chat_debug_steps USING btree (run_id, step_number);
+9 -9
View File
@@ -60,7 +60,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "anthropic/claude-opus-4.6",
provider: database.AIProvider{
Name: "openrouter",
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
},
wantErr: true,
wantDetail: "Change the AI provider type to openrouter or openai-compat.",
@@ -70,7 +70,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "anthropic/claude-opus-4.6",
provider: database.AIProvider{
Name: " OpenRouter ",
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
},
wantErr: true,
wantDetail: "Change the AI provider type to openrouter or openai-compat.",
@@ -80,7 +80,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "anthropic/claude-opus-4.6",
provider: database.AIProvider{
Name: "private-relay",
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
BaseUrl: "https://openrouter.ai/api/v1",
},
wantErr: true,
@@ -91,7 +91,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "anthropic/claude-opus-4.6",
provider: database.AIProvider{
Name: "private-relay",
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
BaseUrl: "https://openrouter.ai:443/api/v1",
},
wantErr: true,
@@ -102,7 +102,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "anthropic/claude-opus-4.6",
provider: database.AIProvider{
Name: "private-relay",
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
BaseUrl: "https://api.openrouter.ai/v1",
},
wantErr: true,
@@ -113,7 +113,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "anthropic/claude-opus-4.6",
provider: database.AIProvider{
Name: "openrouter",
Type: database.AiProviderTypeOpenrouter,
Type: database.AIProviderTypeOpenrouter,
},
},
{
@@ -121,7 +121,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "anthropic/claude-opus-4.6",
provider: database.AIProvider{
Name: "openrouter",
Type: database.AiProviderTypeOpenaiCompat,
Type: database.AIProviderTypeOpenaiCompat,
},
},
{
@@ -129,7 +129,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "anthropic/claude-opus-4.6",
provider: database.AIProvider{
Name: "private-relay",
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
BaseUrl: "https://llm-relay.internal/v1",
},
},
@@ -138,7 +138,7 @@ func TestValidateChatModelConfigProviderModel(t *testing.T) {
model: "gpt-4.1",
provider: database.AIProvider{
Name: "openrouter",
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
},
},
}
+2 -2
View File
@@ -1749,7 +1749,7 @@ func TestListChatModels(t *testing.T) {
client := newChatClient(t)
_ = coderdtest.CreateFirstUser(t, client.Client)
providerType := database.AiProviderTypeAnthropic
providerType := database.AIProviderTypeAnthropic
provider := createAIProviderForTest(t, client, string(providerType), "")
contextLimit := int64(4096)
@@ -3997,7 +3997,7 @@ func TestUpdateChatModelConfig(t *testing.T) {
require.NoError(t, err)
modelConfig := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
Provider: string(database.AiProviderTypeOpenai),
Provider: string(database.AIProviderTypeOpenai),
Model: "anthropic/claude-opus-4.6",
AIProviderID: uuid.NullUUID{UUID: aiProvider.ID, Valid: true},
})
@@ -98,7 +98,7 @@ func insertAgentChatTestModelConfig(
createdBy := uuid.NullUUID{UUID: userID, Valid: true}
provider := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Name: "test-openai",
DisplayName: sql.NullString{String: "OpenAI", Valid: true},
})
+3 -3
View File
@@ -294,7 +294,7 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
getAIProviders: func(context.Context, database.GetAIProvidersParams) ([]database.AIProvider, error) {
return []database.AIProvider{{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Enabled: true,
}}, nil
},
@@ -385,7 +385,7 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
getAIProviderByID: func(context.Context, uuid.UUID) (database.AIProvider, error) {
return database.AIProvider{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Enabled: true,
}, nil
},
@@ -434,7 +434,7 @@ func TestResolveAdvisorModelOverridePromotesAIBridgeErrors(t *testing.T) {
}, nil
},
getAIProviderByID: func(context.Context, uuid.UUID) (database.AIProvider, error) {
return database.AIProvider{ID: providerID, Type: database.AiProviderTypeOpenai, Name: "primary-openai", Enabled: true}, nil
return database.AIProvider{ID: providerID, Type: database.AIProviderTypeOpenai, Name: "primary-openai", Enabled: true}, nil
},
getAIProviderKeysByProviderID: func(context.Context, uuid.UUID) ([]database.AIProviderKey, error) {
return []database.AIProviderKey{{ProviderID: providerID, APIKey: "sk-selected"}}, nil
+1 -1
View File
@@ -321,7 +321,7 @@ func seedAnthropicChatDependencies(t *testing.T, db database.Store, baseURL stri
_ = testAPIKeyID(t, db, user.ID)
org := dbgen.Organization(t, db, database.Organization{})
dbgen.OrganizationMember(t, db, database.OrganizationMember{UserID: user.ID, OrganizationID: org.ID})
provider := dbgen.AIProvider(t, db, database.AIProvider{Type: database.AiProviderTypeAnthropic}, func(params *database.InsertAIProviderParams) {
provider := dbgen.AIProvider(t, db, database.AIProvider{Type: database.AIProviderTypeAnthropic}, func(params *database.InsertAIProviderParams) {
params.BaseUrl = baseURL
})
dbgen.AIProviderKey(t, db, database.AIProviderKey{ProviderID: provider.ID})
+8 -8
View File
@@ -182,8 +182,8 @@ func TestResolveUserProviderAPIKeysAndProviderForProviderTypeProviderMatch(t *te
providerID := uuid.New()
db.EXPECT().GetAIProviders(gomock.Any(), database.GetAIProvidersParams{}).Return([]database.AIProvider{
{ID: uuid.New(), Type: database.AiProviderTypeAnthropic, Enabled: true},
{ID: providerID, Type: database.AiProviderTypeOpenai, Enabled: true},
{ID: uuid.New(), Type: database.AIProviderTypeAnthropic, Enabled: true},
{ID: providerID, Type: database.AIProviderTypeOpenai, Enabled: true},
}, nil)
db.EXPECT().GetAIProviderKeysByProviderID(gomock.Any(), providerID).Return([]database.AIProviderKey{{
ProviderID: providerID,
@@ -200,7 +200,7 @@ func TestResolveUserProviderAPIKeysAndProviderForProviderTypeProviderMatch(t *te
require.Equal(t, "test-key", keys.APIKey(chattool.ComputerUseProviderOpenAI))
require.NotNil(t, aiProvider)
require.Equal(t, providerID, aiProvider.ID)
require.Equal(t, database.AiProviderTypeOpenai, aiProvider.Type)
require.Equal(t, database.AIProviderTypeOpenai, aiProvider.Type)
}
func TestResolveModelRouteForProviderTypeAIGatewayRequiresProvider(t *testing.T) {
@@ -864,7 +864,7 @@ func TestRegenerateChatTitle_PersistsAndBroadcasts(t *testing.T) {
providerID := uuid.New()
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Enabled: true,
BaseUrl: serverURL,
}}, nil)
@@ -1030,7 +1030,7 @@ func TestRegenerateChatTitle_PersistsAndBroadcasts_IdleChatReleasesManualLock(t
providerID := uuid.New()
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Enabled: true,
BaseUrl: serverURL,
}}, nil)
@@ -1181,7 +1181,7 @@ func TestResolveUserProviderAPIKeys_StripsDisabledFallbackKeys(t *testing.T) {
providerID := uuid.New()
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{
ID: providerID,
Type: database.AiProviderTypeAnthropic,
Type: database.AIProviderTypeAnthropic,
Enabled: true,
}}, nil)
db.EXPECT().GetAIProviderKeysByProviderIDs(gomock.Any(), []uuid.UUID{providerID}).Return(nil, nil)
@@ -1219,7 +1219,7 @@ func TestResolveUserProviderAPIKeys_SelectedAIProviderDoesNotUseDeploymentFallba
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(database.AIProvider{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Name: "agents-openai",
Enabled: true,
}, nil)
@@ -1258,7 +1258,7 @@ func TestResolveUserProviderAPIKeys_SkipsUserKeyLookupWhenNoProviderAllowsUserKe
providerID := uuid.New()
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Enabled: true,
}}, nil)
db.EXPECT().GetAIProviderKeysByProviderIDs(gomock.Any(), []uuid.UUID{providerID}).Return(nil, nil)
+3 -3
View File
@@ -8698,7 +8698,7 @@ func setOpenAIProviderBaseURL(
providers, err := db.GetAIProviders(ctx, database.GetAIProvidersParams{IncludeDisabled: true})
require.NoError(t, err)
for _, provider := range providers {
if provider.Type != database.AiProviderTypeOpenai {
if provider.Type != database.AIProviderTypeOpenai {
continue
}
_, err = db.UpdateAIProvider(ctx, database.UpdateAIProviderParams{
@@ -9785,12 +9785,12 @@ func seedAIGatewayOpenAITestDependencies(
OrganizationID: org.ID,
})
provider := dbgen.AIProvider(t, db, database.AIProvider{
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Name: "primary-openai-" + uuid.NewString(),
BaseUrl: openAIURL,
})
model := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
Provider: string(database.AiProviderTypeOpenai),
Provider: string(database.AIProviderTypeOpenai),
Model: "gpt-4o-mini",
IsDefault: true,
AIProviderID: uuid.NullUUID{UUID: provider.ID, Valid: true},
@@ -231,7 +231,7 @@ func TestDeriveFinalTurnRunResult(t *testing.T) {
})
// A disabled AI provider makes resolveChatModel fail, exercising the
// degraded path that still returns the re-derived text and IDs.
provider := insertInternalAIProvider(t, db, database.AiProviderTypeOpenai, "provider-api-key", false)
provider := insertInternalAIProvider(t, db, database.AIProviderTypeOpenai, "provider-api-key", false)
modelCfg := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
Provider: "openai",
Model: "gpt-4o-mini",
+4 -4
View File
@@ -91,7 +91,7 @@ func (t *aiGatewayRoundTripper) RoundTrip(req *http.Request) (*http.Response, er
// OpenRouter-like providers typed as openai, where the provider type
// strips the vendor prefix.
func ValidateAIGatewayProviderModel(provider database.AIProvider, model string) error {
if provider.Type != database.AiProviderTypeOpenai {
if provider.Type != database.AIProviderTypeOpenai {
return nil
}
if !isSlashNamespacedAIGatewayModel(model) || !isOpenRouterLikeAIGatewayProvider(provider) {
@@ -188,10 +188,10 @@ func fantasyConfigForAIBridge(providerType database.AIProviderType) aibridgeFant
var fantasyProvider string
baseURL := aibridgeLocalBaseURL + "/v1"
switch providerType {
case database.AiProviderTypeAnthropic, database.AiProviderTypeBedrock:
case database.AIProviderTypeAnthropic, database.AIProviderTypeBedrock:
fantasyProvider = fantasyanthropic.Name
baseURL = aibridgeLocalBaseURL
case database.AiProviderTypeOpenai:
case database.AIProviderTypeOpenai:
fantasyProvider = fantasyopenai.Name
default:
fantasyProvider = fantasyopenaicompat.Name
@@ -211,7 +211,7 @@ func fantasyConfigForAIBridge(providerType database.AIProviderType) aibridgeFant
func aiGatewayRequestFormatForProviderType(providerType database.AIProviderType) aiGatewayRequestFormat {
switch providerType {
case database.AiProviderTypeAnthropic, database.AiProviderTypeBedrock:
case database.AIProviderTypeAnthropic, database.AIProviderTypeBedrock:
return aiGatewayRequestFormatAnthropic
default:
return aiGatewayRequestFormatOpenAI
+22 -22
View File
@@ -85,10 +85,10 @@ func TestAIBridgeProviderFormatMapping(t *testing.T) {
wantProvider string
wantBaseURL string
}{
{name: "OpenAI", providerType: database.AiProviderTypeOpenai, wantProvider: "openai", wantBaseURL: "http://coder-aibridge/v1"},
{name: "Anthropic", providerType: database.AiProviderTypeAnthropic, wantProvider: "anthropic", wantBaseURL: "http://coder-aibridge"},
{name: "Bedrock", providerType: database.AiProviderTypeBedrock, wantProvider: "anthropic", wantBaseURL: "http://coder-aibridge"},
{name: "Google", providerType: database.AiProviderTypeGoogle, wantProvider: "openai-compat", wantBaseURL: "http://coder-aibridge/v1"},
{name: "OpenAI", providerType: database.AIProviderTypeOpenai, wantProvider: "openai", wantBaseURL: "http://coder-aibridge/v1"},
{name: "Anthropic", providerType: database.AIProviderTypeAnthropic, wantProvider: "anthropic", wantBaseURL: "http://coder-aibridge"},
{name: "Bedrock", providerType: database.AIProviderTypeBedrock, wantProvider: "anthropic", wantBaseURL: "http://coder-aibridge"},
{name: "Google", providerType: database.AIProviderTypeGoogle, wantProvider: "openai-compat", wantBaseURL: "http://coder-aibridge/v1"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -113,7 +113,7 @@ func TestResolveModelRouteForConfigPreservesBaseURL(t *testing.T) {
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(database.AIProvider{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Name: "primary-openai",
Enabled: true,
BaseUrl: baseURL,
@@ -141,7 +141,7 @@ func TestAIGatewayProviderAuthForUser(t *testing.T) {
ctx := t.Context()
ownerID := uuid.New()
providerID := uuid.New()
provider := database.AIProvider{ID: providerID, Type: database.AiProviderTypeOpenai, Enabled: true}
provider := database.AIProvider{ID: providerID, Type: database.AIProviderTypeOpenai, Enabled: true}
t.Run("OpenAIUserKey", func(t *testing.T) {
t.Parallel()
@@ -151,7 +151,7 @@ func TestAIGatewayProviderAuthForUser(t *testing.T) {
db.EXPECT().GetUserAIProviderKeyByProviderID(gomock.Any(), database.GetUserAIProviderKeyByProviderIDParams{
UserID: ownerID,
AIProviderID: providerID,
}).Return(database.UserAiProviderKey{APIKey: "sk-user"}, nil)
}).Return(database.UserAIProviderKey{APIKey: "sk-user"}, nil)
server := &Server{db: db, allowBYOK: true}
auth, err := server.aiGatewayProviderAuthForUser(ctx, ownerID, provider, aiGatewayRequestFormatOpenAI)
@@ -168,7 +168,7 @@ func TestAIGatewayProviderAuthForUser(t *testing.T) {
db.EXPECT().GetUserAIProviderKeyByProviderID(gomock.Any(), database.GetUserAIProviderKeyByProviderIDParams{
UserID: ownerID,
AIProviderID: providerID,
}).Return(database.UserAiProviderKey{APIKey: "sk-user"}, nil)
}).Return(database.UserAIProviderKey{APIKey: "sk-user"}, nil)
server := &Server{db: db, allowBYOK: true}
auth, err := server.aiGatewayProviderAuthForUser(ctx, ownerID, provider, aiGatewayRequestFormatAnthropic)
@@ -185,7 +185,7 @@ func TestAIGatewayProviderAuthForUser(t *testing.T) {
db.EXPECT().GetUserAIProviderKeyByProviderID(gomock.Any(), database.GetUserAIProviderKeyByProviderIDParams{
UserID: ownerID,
AIProviderID: providerID,
}).Return(database.UserAiProviderKey{}, sql.ErrNoRows)
}).Return(database.UserAIProviderKey{}, sql.ErrNoRows)
server := &Server{db: db, allowBYOK: true}
auth, err := server.aiGatewayProviderAuthForUser(ctx, ownerID, provider, aiGatewayRequestFormatOpenAI)
@@ -231,7 +231,7 @@ func TestResolveModelRouteForConfigAIGatewayProviderAuth(t *testing.T) {
providerID := uuid.New()
provider := database.AIProvider{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Name: "primary-openai",
Enabled: true,
}
@@ -251,7 +251,7 @@ func TestResolveModelRouteForConfigAIGatewayProviderAuth(t *testing.T) {
db.EXPECT().GetUserAIProviderKeyByProviderID(gomock.Any(), database.GetUserAIProviderKeyByProviderIDParams{
UserID: ownerID,
AIProviderID: providerID,
}).Return(database.UserAiProviderKey{APIKey: "sk-user"}, nil)
}).Return(database.UserAIProviderKey{APIKey: "sk-user"}, nil)
server := &Server{db: db, aiGatewayRoutingEnabled: true, allowBYOK: true}
route, err := server.resolveModelRouteForConfig(ctx, ownerID, modelConfig, chatprovider.ProviderAPIKeys{})
@@ -296,7 +296,7 @@ func TestAIGatewayModelForwardsProviderAuth(t *testing.T) {
path: req.URL.Path,
}
body := `{"id":"resp_test","object":"response","created_at":0,"status":"completed","model":"gpt-4","output":[{"id":"msg_test","type":"message","role":"assistant","content":[{"type":"output_text","text":"hello"}]}],"usage":{"input_tokens":1,"output_tokens":1,"total_tokens":2}}`
if provider.Type == database.AiProviderTypeAnthropic {
if provider.Type == database.AIProviderTypeAnthropic {
body = `{"id":"msg_test","type":"message","role":"assistant","model":"claude-haiku-4-5","content":[{"type":"text","text":"hello"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":1,"output_tokens":1}}`
}
return &http.Response{
@@ -318,7 +318,7 @@ func TestAIGatewayModelForwardsProviderAuth(t *testing.T) {
t.Parallel()
seen := make(chan seenRequest, 1)
provider := aibridgeTestAIProvider(uuid.New(), "primary-openai", database.AiProviderTypeOpenai)
provider := aibridgeTestAIProvider(uuid.New(), "primary-openai", database.AIProviderTypeOpenai)
server, route := newServer(t, provider, aiGatewayProviderAuth{
Headers: map[string]string{"Authorization": "Bearer sk-user"},
}, seen)
@@ -340,7 +340,7 @@ func TestAIGatewayModelForwardsProviderAuth(t *testing.T) {
t.Parallel()
seen := make(chan seenRequest, 1)
provider := aibridgeTestAIProvider(uuid.New(), "primary-anthropic", database.AiProviderTypeAnthropic)
provider := aibridgeTestAIProvider(uuid.New(), "primary-anthropic", database.AIProviderTypeAnthropic)
server, route := newServer(t, provider, aiGatewayProviderAuth{
Headers: map[string]string{"X-Api-Key": "sk-user"},
}, seen)
@@ -361,7 +361,7 @@ func TestAIGatewayModelForwardsProviderAuth(t *testing.T) {
t.Parallel()
seen := make(chan seenRequest, 1)
provider := aibridgeTestAIProvider(uuid.New(), "primary-openai", database.AiProviderTypeOpenai)
provider := aibridgeTestAIProvider(uuid.New(), "primary-openai", database.AIProviderTypeOpenai)
server, route := newServer(t, provider, aiGatewayProviderAuth{}, seen)
apiKeyID := uuid.NewString()
model, err := server.newModel(t.Context(), aibridgeTestRequest(database.Chat{ID: uuid.New(), OwnerID: uuid.New()}, "gpt-4"), route, modelBuildOptions{ActiveAPIKeyID: apiKeyID})
@@ -595,7 +595,7 @@ func TestAIBridgeRoutingFailClosed(t *testing.T) {
providerID := uuid.New()
chat := database.Chat{ID: uuid.New(), OwnerID: uuid.New()}
aiProvider := aibridgeTestAIProvider(providerID, "primary-openai", database.AiProviderTypeOpenai)
aiProvider := aibridgeTestAIProvider(providerID, "primary-openai", database.AIProviderTypeOpenai)
t.Run("NilFactory", func(t *testing.T) {
t.Parallel()
@@ -618,7 +618,7 @@ func TestAIBridgeRoutingFailClosed(t *testing.T) {
t.Run("MissingProviderName", func(t *testing.T) {
t.Parallel()
server := &Server{aiGatewayRoutingEnabled: true}
missingNameProvider := aibridgeTestAIProvider(providerID, "", database.AiProviderTypeOpenai)
missingNameProvider := aibridgeTestAIProvider(providerID, "", database.AIProviderTypeOpenai)
_, err := server.newModel(t.Context(), aibridgeTestRequest(chat, "gpt-4"), aibridgeTestRoute(missingNameProvider), modelBuildOptions{ActiveAPIKeyID: uuid.NewString()})
require.ErrorContains(t, err, "AI provider name")
})
@@ -652,7 +652,7 @@ func TestAIBridgeRoutingFailClosed(t *testing.T) {
aiGatewayRoutingEnabled: true,
aibridgeTransportFactory: aibridgeTestFactoryPointer(factory),
}
provider := aibridgeTestAIProvider(providerID, "openrouter", database.AiProviderTypeOpenai)
provider := aibridgeTestAIProvider(providerID, "openrouter", database.AIProviderTypeOpenai)
_, err := server.newModel(
t.Context(),
aibridgeTestRequest(chat, "anthropic/claude-opus-4.6"),
@@ -685,12 +685,12 @@ func TestAIBridgeGatewayProviderTypesPreserveSlashModelID(t *testing.T) {
{
name: "OpenRouter",
providerName: "openrouter",
providerType: database.AiProviderTypeOpenrouter,
providerType: database.AIProviderTypeOpenrouter,
},
{
name: "OpenAICompat",
providerName: "openai-compatible-relay",
providerType: database.AiProviderTypeOpenaiCompat,
providerType: database.AIProviderTypeOpenaiCompat,
},
}
@@ -814,7 +814,7 @@ func TestAIBridgeComputerUseModelUsesRoute(t *testing.T) {
model, debugEnabled, resolvedProvider, resolvedModel, err := server.resolveComputerUseModel(
ctx,
chat,
aibridgeTestRoute(aibridgeTestAIProvider(providerID, "primary-openai", database.AiProviderTypeOpenai)),
aibridgeTestRoute(aibridgeTestAIProvider(providerID, "primary-openai", database.AIProviderTypeOpenai)),
provider,
modelProvider,
modelName,
@@ -862,7 +862,7 @@ func TestAIBridgeDelegatedContextPropagation(t *testing.T) {
}
ctx := aibridge.WithDelegatedAPIKeyID(t.Context(), "context-key-must-be-ignored")
model, err := server.newModel(ctx, aibridgeTestRequest(chat, "gpt-4"), aibridgeTestRoute(aibridgeTestAIProvider(providerID, "primary-openai", database.AiProviderTypeOpenai)), modelBuildOptions{ActiveAPIKeyID: apiKeyID, RecordHTTP: true})
model, err := server.newModel(ctx, aibridgeTestRequest(chat, "gpt-4"), aibridgeTestRoute(aibridgeTestAIProvider(providerID, "primary-openai", database.AIProviderTypeOpenai)), modelBuildOptions{ActiveAPIKeyID: apiKeyID, RecordHTTP: true})
require.NoError(t, err)
_, err = model.Generate(t.Context(), fantasy.Call{Prompt: []fantasy.Message{{
Role: fantasy.MessageRoleUser,
+7 -7
View File
@@ -476,7 +476,7 @@ func TestResolveUserProviderAPIKeys_AIProvider(t *testing.T) {
server := newInternalTestServer(t, db, ps, chatprovider.ProviderAPIKeys{})
ctx := chatdTestContext(t)
user, _, _ := seedInternalChatDeps(t, db)
provider := insertInternalAIProvider(t, db, database.AiProviderTypeOpenai, "provider-api-key", true)
provider := insertInternalAIProvider(t, db, database.AIProviderTypeOpenai, "provider-api-key", true)
now := time.Now()
_, err := db.UpsertUserAIProviderKey(ctx, database.UpsertUserAIProviderKeyParams{
ID: uuid.New(),
@@ -502,7 +502,7 @@ func TestResolveUserProviderAPIKeys_AIProvider(t *testing.T) {
server.allowBYOK = false
ctx := chatdTestContext(t)
user, _, _ := seedInternalChatDeps(t, db)
provider := insertInternalAIProvider(t, db, database.AiProviderTypeOpenai, "provider-api-key", true)
provider := insertInternalAIProvider(t, db, database.AIProviderTypeOpenai, "provider-api-key", true)
now := time.Now()
_, err := db.UpsertUserAIProviderKey(ctx, database.UpsertUserAIProviderKeyParams{
ID: uuid.New(),
@@ -526,7 +526,7 @@ func TestResolveUserProviderAPIKeys_AIProvider(t *testing.T) {
server := newInternalTestServer(t, db, ps, chatprovider.ProviderAPIKeys{})
ctx := chatdTestContext(t)
user, _, _ := seedInternalChatDeps(t, db)
insertInternalAIProvider(t, db, database.AiProviderTypeAzure, "provider-api-key", true)
insertInternalAIProvider(t, db, database.AIProviderTypeAzure, "provider-api-key", true)
keys, err := server.resolveUserProviderAPIKeysForProviderType(ctx, user.ID, "azure")
require.NoError(t, err)
@@ -540,7 +540,7 @@ func TestResolveUserProviderAPIKeys_AIProvider(t *testing.T) {
server := newInternalTestServer(t, db, ps, chatprovider.ProviderAPIKeys{})
ctx := chatdTestContext(t)
user, _, _ := seedInternalChatDeps(t, db)
provider := insertInternalAIProvider(t, db, database.AiProviderTypeBedrock, "", true)
provider := insertInternalAIProvider(t, db, database.AIProviderTypeBedrock, "", true)
keys, err := server.resolveUserProviderAPIKeys(ctx, user.ID, provider.ID)
require.NoError(t, err)
@@ -555,8 +555,8 @@ func TestResolveUserProviderAPIKeys_AIProvider(t *testing.T) {
server := newInternalTestServer(t, db, ps, chatprovider.ProviderAPIKeys{})
ctx := chatdTestContext(t)
user, _, _ := seedInternalChatDeps(t, db)
insertInternalAIProvider(t, db, database.AiProviderTypeOpenai, "first-provider-api-key", true)
insertInternalAIProvider(t, db, database.AiProviderTypeOpenai, "second-provider-api-key", true)
insertInternalAIProvider(t, db, database.AIProviderTypeOpenai, "first-provider-api-key", true)
insertInternalAIProvider(t, db, database.AIProviderTypeOpenai, "second-provider-api-key", true)
keys, err := server.resolveUserProviderAPIKeys(ctx, user.ID, uuid.Nil)
require.ErrorContains(t, err, "multiple enabled AI providers use provider type")
@@ -570,7 +570,7 @@ func TestResolveChatModel_AIProviderDisabled(t *testing.T) {
ctx := chatdTestContext(t)
db, ps := dbtestutil.NewDB(t)
user, org, _ := seedInternalChatDeps(t, db)
provider := insertInternalAIProvider(t, db, database.AiProviderTypeOpenai, "provider-api-key", false)
provider := insertInternalAIProvider(t, db, database.AIProviderTypeOpenai, "provider-api-key", false)
modelConfig := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
Provider: "openai",
Model: "gpt-4o-mini",
@@ -253,7 +253,7 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideSetUsable(t *testing.T) {
})
provider := database.AIProvider{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Enabled: true,
BaseUrl: serverURL,
}
@@ -365,7 +365,7 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideCallFailureSkipsFallback(
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{Type: database.AiProviderTypeOpenai, Enabled: true}}, nil)
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{Type: database.AIProviderTypeOpenai, Enabled: true}}, nil)
db.EXPECT().GetAIProviderKeysByProviderIDs(gomock.Any(), []uuid.UUID{uuid.Nil}).Return(nil, nil)
generated := &generatedChatTitle{}
@@ -446,7 +446,7 @@ func TestResolveManualTitleModel_TitleGenerationOverrideUnsetAIProvider(t *testi
})
provider := database.AIProvider{
ID: providerID,
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Enabled: true,
BaseUrl: serverURL,
}
@@ -521,7 +521,7 @@ func TestResolveManualTitleModel_TitleGenerationOverrideSetUsable(t *testing.T)
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{Type: database.AiProviderTypeOpenai, Enabled: true}}, nil)
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{Type: database.AIProviderTypeOpenai, Enabled: true}}, nil)
db.EXPECT().GetAIProviderKeysByProviderIDs(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()
server := titleOverrideTestServer(db, logger)
@@ -549,7 +549,7 @@ func TestResolveManualTitleModel_TitleGenerationOverrideMissingCredentials(t *te
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{Type: database.AiProviderTypeOpenai, Enabled: true}}, nil)
db.EXPECT().GetAIProviders(gomock.Any(), gomock.Any()).Return([]database.AIProvider{{Type: database.AIProviderTypeOpenai, Enabled: true}}, nil)
db.EXPECT().GetAIProviderKeysByProviderIDs(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()
server := titleOverrideTestServer(db, logger)
@@ -619,7 +619,7 @@ func TestGenerateManualTitleCandidate_ActiveAPIKeyIDFallback(t *testing.T) {
provider := database.AIProvider{
ID: providerID,
Name: "primary-openai",
Type: database.AiProviderTypeOpenai,
Type: database.AIProviderTypeOpenai,
Enabled: true,
}
wantTitle := "Context title"