mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
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)
118 lines
3.3 KiB
Go
118 lines
3.3 KiB
Go
package coderd
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/sqlc-dev/pqtype"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/mock/gomock"
|
|
|
|
"cdr.dev/slog/v3/sloggers/slogtest"
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/database/dbgen"
|
|
"github.com/coder/coder/v2/coderd/database/dbmock"
|
|
"github.com/coder/coder/v2/codersdk"
|
|
)
|
|
|
|
func TestUpdateAgentChatLastInjectedContextFromMessagesUsesMessageIDTieBreaker(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctrl := gomock.NewController(t)
|
|
db := dbmock.NewMockStore(ctrl)
|
|
chatID := uuid.New()
|
|
createdAt := time.Date(2026, time.April, 9, 13, 0, 0, 0, time.UTC)
|
|
oldAgentID := uuid.New()
|
|
newAgentID := uuid.New()
|
|
|
|
oldContent, err := json.Marshal([]codersdk.ChatMessagePart{{
|
|
Type: codersdk.ChatMessagePartTypeContextFile,
|
|
ContextFilePath: "/old/AGENTS.md",
|
|
ContextFileContent: "old instructions",
|
|
ContextFileAgentID: uuid.NullUUID{UUID: oldAgentID, Valid: true},
|
|
}})
|
|
require.NoError(t, err)
|
|
newContent, err := json.Marshal([]codersdk.ChatMessagePart{{
|
|
Type: codersdk.ChatMessagePartTypeContextFile,
|
|
ContextFilePath: "/new/AGENTS.md",
|
|
ContextFileContent: "new instructions",
|
|
ContextFileAgentID: uuid.NullUUID{UUID: newAgentID, Valid: true},
|
|
}})
|
|
require.NoError(t, err)
|
|
|
|
db.EXPECT().GetChatMessagesByChatID(gomock.Any(), database.GetChatMessagesByChatIDParams{
|
|
ChatID: chatID,
|
|
AfterID: 0,
|
|
}).Return([]database.ChatMessage{
|
|
{
|
|
ID: 2,
|
|
CreatedAt: createdAt,
|
|
Content: pqtype.NullRawMessage{
|
|
RawMessage: newContent,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
ID: 1,
|
|
CreatedAt: createdAt,
|
|
Content: pqtype.NullRawMessage{
|
|
RawMessage: oldContent,
|
|
Valid: true,
|
|
},
|
|
},
|
|
}, nil)
|
|
|
|
db.EXPECT().UpdateChatLastInjectedContext(gomock.Any(), gomock.Any()).DoAndReturn(
|
|
func(_ context.Context, arg database.UpdateChatLastInjectedContextParams) (database.Chat, error) {
|
|
require.Equal(t, chatID, arg.ID)
|
|
require.True(t, arg.LastInjectedContext.Valid)
|
|
var cached []codersdk.ChatMessagePart
|
|
require.NoError(t, json.Unmarshal(arg.LastInjectedContext.RawMessage, &cached))
|
|
require.Len(t, cached, 1)
|
|
require.Equal(t, "/new/AGENTS.md", cached[0].ContextFilePath)
|
|
require.Equal(t, uuid.NullUUID{UUID: newAgentID, Valid: true}, cached[0].ContextFileAgentID)
|
|
return database.Chat{}, nil
|
|
},
|
|
)
|
|
|
|
err = updateAgentChatLastInjectedContextFromMessages(
|
|
context.Background(),
|
|
slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}),
|
|
db,
|
|
chatID,
|
|
)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func insertAgentChatTestModelConfig(
|
|
t testing.TB,
|
|
db database.Store,
|
|
userID uuid.UUID,
|
|
) database.ChatModelConfig {
|
|
t.Helper()
|
|
|
|
createdBy := uuid.NullUUID{UUID: userID, Valid: true}
|
|
|
|
provider := dbgen.AIProvider(t, db, database.AIProvider{
|
|
Type: database.AIProviderTypeOpenai,
|
|
Name: "test-openai",
|
|
DisplayName: sql.NullString{String: "OpenAI", Valid: true},
|
|
})
|
|
dbgen.AIProviderKey(t, db, database.AIProviderKey{
|
|
ProviderID: provider.ID,
|
|
APIKey: "test-api-key",
|
|
})
|
|
|
|
return dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
|
|
Provider: "openai",
|
|
AIProviderID: uuid.NullUUID{UUID: provider.ID, Valid: true},
|
|
CreatedBy: createdBy,
|
|
UpdatedBy: createdBy,
|
|
IsDefault: true,
|
|
})
|
|
}
|