feat: add collapsible thinking blocks with configurable display mode (#24635)

This commit is contained in:
Danielle Maywood
2026-04-24 11:29:08 +00:00
committed by GitHub
parent ce125831d3
commit 3a9a60dff8
26 changed files with 881 additions and 90 deletions
+22
View File
@@ -4403,6 +4403,17 @@ func (q *querier) GetUserThemePreference(ctx context.Context, userID uuid.UUID)
return q.db.GetUserThemePreference(ctx, userID)
}
func (q *querier) GetUserThinkingDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
user, err := q.db.GetUserByID(ctx, userID)
if err != nil {
return "", err
}
if err := q.authorizeContext(ctx, policy.ActionReadPersonal, user); err != nil {
return "", err
}
return q.db.GetUserThinkingDisplayMode(ctx, userID)
}
func (q *querier) GetUserWorkspaceBuildParameters(ctx context.Context, params database.GetUserWorkspaceBuildParametersParams) ([]database.GetUserWorkspaceBuildParametersRow, error) {
u, err := q.db.GetUserByID(ctx, params.OwnerID)
if err != nil {
@@ -7018,6 +7029,17 @@ func (q *querier) UpdateUserThemePreference(ctx context.Context, arg database.Up
return q.db.UpdateUserThemePreference(ctx, arg)
}
func (q *querier) UpdateUserThinkingDisplayMode(ctx context.Context, arg database.UpdateUserThinkingDisplayModeParams) (string, error) {
user, err := q.db.GetUserByID(ctx, arg.UserID)
if err != nil {
return "", err
}
if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, user); err != nil {
return "", err
}
return q.db.UpdateUserThinkingDisplayMode(ctx, arg)
}
func (q *querier) UpdateVolumeResourceMonitor(ctx context.Context, arg database.UpdateVolumeResourceMonitorParams) error {
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil {
return err
+13
View File
@@ -2714,6 +2714,19 @@ func (s *MethodTestSuite) TestUser() {
dbm.EXPECT().UpdateUserChatCustomPrompt(gomock.Any(), arg).Return(uc, nil).AnyTimes()
check.Args(arg).Asserts(u, policy.ActionUpdatePersonal).Returns(uc)
}))
s.Run("GetUserThinkingDisplayMode", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
dbm.EXPECT().GetUserThinkingDisplayMode(gomock.Any(), u.ID).Return("auto", nil).AnyTimes()
check.Args(u.ID).Asserts(u, policy.ActionReadPersonal).Returns("auto")
}))
s.Run("UpdateUserThinkingDisplayMode", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
arg := database.UpdateUserThinkingDisplayModeParams{UserID: u.ID, ThinkingDisplayMode: "always_expanded"}
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
dbm.EXPECT().UpdateUserThinkingDisplayMode(gomock.Any(), arg).Return("always_expanded", nil).AnyTimes()
check.Args(arg).Asserts(u, policy.ActionUpdatePersonal).Returns("always_expanded")
}))
s.Run("ListUserChatCompactionThresholds", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
uc := database.UserConfig{UserID: u.ID, Key: codersdk.ChatCompactionThresholdKeyPrefix + "00000000-0000-0000-0000-000000000001", Value: "75"}
+16
View File
@@ -2872,6 +2872,14 @@ func (m queryMetricsStore) GetUserThemePreference(ctx context.Context, userID uu
return r0, r1
}
func (m queryMetricsStore) GetUserThinkingDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
start := time.Now()
r0, r1 := m.s.GetUserThinkingDisplayMode(ctx, userID)
m.queryLatencies.WithLabelValues("GetUserThinkingDisplayMode").Observe(time.Since(start).Seconds())
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetUserThinkingDisplayMode").Inc()
return r0, r1
}
func (m queryMetricsStore) GetUserWorkspaceBuildParameters(ctx context.Context, arg database.GetUserWorkspaceBuildParametersParams) ([]database.GetUserWorkspaceBuildParametersRow, error) {
start := time.Now()
r0, r1 := m.s.GetUserWorkspaceBuildParameters(ctx, arg)
@@ -5016,6 +5024,14 @@ func (m queryMetricsStore) UpdateUserThemePreference(ctx context.Context, arg da
return r0, r1
}
func (m queryMetricsStore) UpdateUserThinkingDisplayMode(ctx context.Context, arg database.UpdateUserThinkingDisplayModeParams) (string, error) {
start := time.Now()
r0, r1 := m.s.UpdateUserThinkingDisplayMode(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateUserThinkingDisplayMode").Observe(time.Since(start).Seconds())
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpdateUserThinkingDisplayMode").Inc()
return r0, r1
}
func (m queryMetricsStore) UpdateVolumeResourceMonitor(ctx context.Context, arg database.UpdateVolumeResourceMonitorParams) error {
start := time.Now()
r0 := m.s.UpdateVolumeResourceMonitor(ctx, arg)
+30
View File
@@ -5371,6 +5371,21 @@ func (mr *MockStoreMockRecorder) GetUserThemePreference(ctx, userID any) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserThemePreference", reflect.TypeOf((*MockStore)(nil).GetUserThemePreference), ctx, userID)
}
// GetUserThinkingDisplayMode mocks base method.
func (m *MockStore) GetUserThinkingDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUserThinkingDisplayMode", ctx, userID)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetUserThinkingDisplayMode indicates an expected call of GetUserThinkingDisplayMode.
func (mr *MockStoreMockRecorder) GetUserThinkingDisplayMode(ctx, userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserThinkingDisplayMode", reflect.TypeOf((*MockStore)(nil).GetUserThinkingDisplayMode), ctx, userID)
}
// GetUserWorkspaceBuildParameters mocks base method.
func (m *MockStore) GetUserWorkspaceBuildParameters(ctx context.Context, arg database.GetUserWorkspaceBuildParametersParams) ([]database.GetUserWorkspaceBuildParametersRow, error) {
m.ctrl.T.Helper()
@@ -9450,6 +9465,21 @@ func (mr *MockStoreMockRecorder) UpdateUserThemePreference(ctx, arg any) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserThemePreference", reflect.TypeOf((*MockStore)(nil).UpdateUserThemePreference), ctx, arg)
}
// UpdateUserThinkingDisplayMode mocks base method.
func (m *MockStore) UpdateUserThinkingDisplayMode(ctx context.Context, arg database.UpdateUserThinkingDisplayModeParams) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateUserThinkingDisplayMode", ctx, arg)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UpdateUserThinkingDisplayMode indicates an expected call of UpdateUserThinkingDisplayMode.
func (mr *MockStoreMockRecorder) UpdateUserThinkingDisplayMode(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserThinkingDisplayMode", reflect.TypeOf((*MockStore)(nil).UpdateUserThinkingDisplayMode), ctx, arg)
}
// UpdateVolumeResourceMonitor mocks base method.
func (m *MockStore) UpdateVolumeResourceMonitor(ctx context.Context, arg database.UpdateVolumeResourceMonitorParams) error {
m.ctrl.T.Helper()
+2
View File
@@ -703,6 +703,7 @@ type sqlcQuerier interface {
GetUserTaskNotificationAlertDismissed(ctx context.Context, userID uuid.UUID) (bool, error)
GetUserTerminalFont(ctx context.Context, userID uuid.UUID) (string, error)
GetUserThemePreference(ctx context.Context, userID uuid.UUID) (string, error)
GetUserThinkingDisplayMode(ctx context.Context, userID uuid.UUID) (string, error)
GetUserWorkspaceBuildParameters(ctx context.Context, arg GetUserWorkspaceBuildParametersParams) ([]GetUserWorkspaceBuildParametersRow, error)
// This will never return deleted users.
GetUsers(ctx context.Context, arg GetUsersParams) ([]GetUsersRow, error)
@@ -1132,6 +1133,7 @@ type sqlcQuerier interface {
UpdateUserTaskNotificationAlertDismissed(ctx context.Context, arg UpdateUserTaskNotificationAlertDismissedParams) (bool, error)
UpdateUserTerminalFont(ctx context.Context, arg UpdateUserTerminalFontParams) (UserConfig, error)
UpdateUserThemePreference(ctx context.Context, arg UpdateUserThemePreferenceParams) (UserConfig, error)
UpdateUserThinkingDisplayMode(ctx context.Context, arg UpdateUserThinkingDisplayModeParams) (string, error)
UpdateVolumeResourceMonitor(ctx context.Context, arg UpdateVolumeResourceMonitorParams) error
UpdateWorkspace(ctx context.Context, arg UpdateWorkspaceParams) (WorkspaceTable, error)
UpdateWorkspaceACLByID(ctx context.Context, arg UpdateWorkspaceACLByIDParams) error
+44
View File
@@ -25122,6 +25122,23 @@ func (q *sqlQuerier) GetUserThemePreference(ctx context.Context, userID uuid.UUI
return theme_preference, err
}
const getUserThinkingDisplayMode = `-- name: GetUserThinkingDisplayMode :one
SELECT
value AS thinking_display_mode
FROM
user_configs
WHERE
user_id = $1
AND key = 'preference_thinking_display_mode'
`
func (q *sqlQuerier) GetUserThinkingDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
row := q.db.QueryRowContext(ctx, getUserThinkingDisplayMode, userID)
var thinking_display_mode string
err := row.Scan(&thinking_display_mode)
return thinking_display_mode, err
}
const getUsers = `-- name: GetUsers :many
SELECT
id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at, is_system, is_service_account, chat_spend_limit_micros, COUNT(*) OVER() AS count
@@ -26048,6 +26065,33 @@ func (q *sqlQuerier) UpdateUserThemePreference(ctx context.Context, arg UpdateUs
return i, err
}
const updateUserThinkingDisplayMode = `-- name: UpdateUserThinkingDisplayMode :one
INSERT INTO
user_configs (user_id, key, value)
VALUES
($1, 'preference_thinking_display_mode', $2::text)
ON CONFLICT
ON CONSTRAINT user_configs_pkey
DO UPDATE
SET
value = $2
WHERE user_configs.user_id = $1
AND user_configs.key = 'preference_thinking_display_mode'
RETURNING value AS thinking_display_mode
`
type UpdateUserThinkingDisplayModeParams struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
ThinkingDisplayMode string `db:"thinking_display_mode" json:"thinking_display_mode"`
}
func (q *sqlQuerier) UpdateUserThinkingDisplayMode(ctx context.Context, arg UpdateUserThinkingDisplayModeParams) (string, error) {
row := q.db.QueryRowContext(ctx, updateUserThinkingDisplayMode, arg.UserID, arg.ThinkingDisplayMode)
var thinking_display_mode string
err := row.Scan(&thinking_display_mode)
return thinking_display_mode, err
}
const upsertUserChatDebugLoggingEnabled = `-- name: UpsertUserChatDebugLoggingEnabled :exec
INSERT INTO user_configs (user_id, key, value)
VALUES (
+23
View File
@@ -263,6 +263,29 @@ WHERE user_configs.user_id = @user_id
AND user_configs.key = 'preference_task_notification_alert_dismissed'
RETURNING value::boolean AS task_notification_alert_dismissed;
-- name: GetUserThinkingDisplayMode :one
SELECT
value AS thinking_display_mode
FROM
user_configs
WHERE
user_id = @user_id
AND key = 'preference_thinking_display_mode';
-- name: UpdateUserThinkingDisplayMode :one
INSERT INTO
user_configs (user_id, key, value)
VALUES
(@user_id, 'preference_thinking_display_mode', @thinking_display_mode::text)
ON CONFLICT
ON CONSTRAINT user_configs_pkey
DO UPDATE
SET
value = @thinking_display_mode
WHERE user_configs.user_id = @user_id
AND user_configs.key = 'preference_thinking_display_mode'
RETURNING value AS thinking_display_mode;
-- name: UpdateUserRoles :one
UPDATE
users