Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
DROP INDEX idx_chat_messages_compressed_summary_boundary;

CREATE INDEX idx_chat_messages_compressed_summary_boundary
ON chat_messages(chat_id, created_at DESC, id DESC)
WHERE compressed = TRUE
AND role = 'system'
AND visibility IN ('model', 'both');
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- The predicate required role = 'system', but compaction writes its summary
-- with the user role, so this index has never matched a row. Rebuild it to
-- match GetChatMessagesForPromptByChatID's boundary lookup, which orders by id.
DROP INDEX idx_chat_messages_compressed_summary_boundary;

CREATE INDEX idx_chat_messages_compressed_summary_boundary
ON chat_messages(chat_id, id DESC)
WHERE compressed = TRUE
AND deleted = false
AND visibility = 'model';
2 changes: 2 additions & 0 deletions coderd/database/querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 48 additions & 13 deletions coderd/database/querier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12346,7 +12346,7 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {

// This test exercises a complex CTE query for prompt
// reconstruction after compaction. It requires Postgres.
db, _ := dbtestutil.NewDB(t)
db, _, sqlDB := dbtestutil.NewDBWithSQLDB(t)
ctx := context.Background()

// Helper: create a chat model config (required FK for chats).
Expand Down Expand Up @@ -12426,14 +12426,49 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {
return database.ChatMessage(results[0])
}

msgIDs := func(msgs []database.ChatMessage) []int64 {
ids := make([]int64, len(msgs))
for i, m := range msgs {
ids[i] = m.ID
}
return ids
invertCreatedAt := func(t *testing.T, chatID uuid.UUID) {
t.Helper()
_, err := sqlDB.ExecContext(ctx,
"UPDATE chat_messages SET created_at = now() - (id || ' seconds')::interval WHERE chat_id = $1",
chatID)
require.NoError(t, err)
}

t.Run("OrdersByIDWhenTimestampsDisagree", func(t *testing.T) {
t.Parallel()
chat := newChat(t)

sys := insertMsg(t, chat.ID, database.ChatMessageRoleSystem, database.ChatMessageVisibilityModel, false, "system prompt")
usr := insertMsg(t, chat.ID, database.ChatMessageRoleUser, database.ChatMessageVisibilityBoth, false, "question")
ast := insertMsg(t, chat.ID, database.ChatMessageRoleAssistant, database.ChatMessageVisibilityBoth, false, "tool call")
tool := insertMsg(t, chat.ID, database.ChatMessageRoleTool, database.ChatMessageVisibilityBoth, false, "tool result")
invertCreatedAt(t, chat.ID)

got, err := db.GetChatMessagesForPromptByChatID(ctx, chat.ID)
require.NoError(t, err)
require.Equal(t, []int64{sys.ID, usr.ID, ast.ID, tool.ID}, chatMessageIDs(got),
"the prompt must keep append order so a tool result follows its assistant call")
})

t.Run("CompactionBoundaryUsesID", func(t *testing.T) {
t.Parallel()
chat := newChat(t)

sys := insertMsg(t, chat.ID, database.ChatMessageRoleSystem, database.ChatMessageVisibilityModel, false, "system prompt")
insertMsg(t, chat.ID, database.ChatMessageRoleUser, database.ChatMessageVisibilityBoth, false, "before first summary")
staleSummary := insertMsg(t, chat.ID, database.ChatMessageRoleUser, database.ChatMessageVisibilityModel, true, "first summary")
insertMsg(t, chat.ID, database.ChatMessageRoleUser, database.ChatMessageVisibilityBoth, false, "between summaries")
latestSummary := insertMsg(t, chat.ID, database.ChatMessageRoleUser, database.ChatMessageVisibilityModel, true, "second summary")
afterLatest := insertMsg(t, chat.ID, database.ChatMessageRoleUser, database.ChatMessageVisibilityBoth, false, "after second summary")
invertCreatedAt(t, chat.ID)

got, err := db.GetChatMessagesForPromptByChatID(ctx, chat.ID)
require.NoError(t, err)
require.Equal(t, []int64{sys.ID, latestSummary.ID, afterLatest.ID}, chatMessageIDs(got),
"the boundary is compared with id, so it must also be selected by id")
require.NotContains(t, chatMessageIDs(got), staleSummary.ID)
})

t.Run("NoCompaction", func(t *testing.T) {
t.Parallel()
chat := newChat(t)
Expand All @@ -12444,7 +12479,7 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {

got, err := db.GetChatMessagesForPromptByChatID(ctx, chat.ID)
require.NoError(t, err)
require.Equal(t, []int64{sys.ID, usr.ID, ast.ID}, msgIDs(got))
require.Equal(t, []int64{sys.ID, usr.ID, ast.ID}, chatMessageIDs(got))
})

t.Run("UserOnlyVisibilityExcluded", func(t *testing.T) {
Expand All @@ -12463,7 +12498,7 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {
require.NotEqual(t, database.ChatMessageVisibilityUser, m.Visibility,
"visibility=user messages should not appear in the prompt")
}
require.Contains(t, msgIDs(got), usr.ID)
require.Contains(t, chatMessageIDs(got), usr.ID)
})

t.Run("AfterCompaction", func(t *testing.T) {
Expand All @@ -12490,7 +12525,7 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {
got, err := db.GetChatMessagesForPromptByChatID(ctx, chat.ID)
require.NoError(t, err)

gotIDs := msgIDs(got)
gotIDs := chatMessageIDs(got)

// Must include: system prompt, summary, post-compaction.
require.Contains(t, gotIDs, sys.ID, "system prompt must be included")
Expand Down Expand Up @@ -12529,8 +12564,8 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {
}
require.True(t, hasNonSystem,
"prompt must contain at least one non-system message after compaction")
require.Contains(t, msgIDs(got), summary.ID)
require.Contains(t, msgIDs(got), newUsr.ID)
require.Contains(t, chatMessageIDs(got), summary.ID)
require.Contains(t, chatMessageIDs(got), newUsr.ID)
})

t.Run("CompressedToolResultNotPickedAsSummary", func(t *testing.T) {
Expand All @@ -12549,7 +12584,7 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {
got, err := db.GetChatMessagesForPromptByChatID(ctx, chat.ID)
require.NoError(t, err)

gotIDs := msgIDs(got)
gotIDs := chatMessageIDs(got)
require.Contains(t, gotIDs, summary.ID, "real summary must be included")
require.NotContains(t, gotIDs, compressedTool.ID,
"compressed tool result must not be included")
Expand Down
4 changes: 2 additions & 2 deletions coderd/database/queries.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions coderd/database/queries/chats.sql
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ LIMIT
COALESCE(NULLIF(@limit_val::int, 0), 500);

-- name: GetChatMessagesForPromptByChatID :many
-- The compaction boundary and final ordering must use the same key so tool
-- results remain after their assistant calls.
WITH latest_compressed_summary AS (
SELECT
id
Expand All @@ -495,7 +497,6 @@ WITH latest_compressed_summary AS (
AND deleted = false
AND visibility = 'model'
ORDER BY
created_at DESC,
id DESC
Comment thread
ibetitsmike marked this conversation as resolved.
Comment thread
ibetitsmike marked this conversation as resolved.
LIMIT
1
Expand Down Expand Up @@ -538,7 +539,6 @@ WHERE
)
)
ORDER BY
created_at ASC,
id ASC;

-- name: GetChats :many
Expand Down
Loading