feat: add shell tool display mode preference (#25029)

This commit is contained in:
Danielle Maywood
2026-05-14 14:25:07 +01:00
committed by GitHub
parent 3a070a83dd
commit 25a803221e
30 changed files with 964 additions and 332 deletions
+22
View File
@@ -4546,6 +4546,17 @@ func (q *querier) GetUserSecretsTelemetrySummary(ctx context.Context) (database.
return q.db.GetUserSecretsTelemetrySummary(ctx)
}
func (q *querier) GetUserShellToolDisplayMode(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.GetUserShellToolDisplayMode(ctx, userID)
}
func (q *querier) GetUserStatusCounts(ctx context.Context, arg database.GetUserStatusCountsParams) ([]database.GetUserStatusCountsRow, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceUser); err != nil {
return nil, err
@@ -7213,6 +7224,17 @@ func (q *querier) UpdateUserSecretByUserIDAndName(ctx context.Context, arg datab
return q.db.UpdateUserSecretByUserIDAndName(ctx, arg)
}
func (q *querier) UpdateUserShellToolDisplayMode(ctx context.Context, arg database.UpdateUserShellToolDisplayModeParams) (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.UpdateUserShellToolDisplayMode(ctx, arg)
}
func (q *querier) UpdateUserStatus(ctx context.Context, arg database.UpdateUserStatusParams) (database.User, error) {
fetch := func(ctx context.Context, arg database.UpdateUserStatusParams) (database.User, error) {
return q.db.GetUserByID(ctx, arg.ID)
+13
View File
@@ -2862,6 +2862,19 @@ func (s *MethodTestSuite) TestUser() {
dbm.EXPECT().UpdateUserThinkingDisplayMode(gomock.Any(), arg).Return("always_expanded", nil).AnyTimes()
check.Args(arg).Asserts(u, policy.ActionUpdatePersonal).Returns("always_expanded")
}))
s.Run("GetUserShellToolDisplayMode", 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().GetUserShellToolDisplayMode(gomock.Any(), u.ID).Return("auto", nil).AnyTimes()
check.Args(u.ID).Asserts(u, policy.ActionReadPersonal).Returns("auto")
}))
s.Run("UpdateUserShellToolDisplayMode", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
arg := database.UpdateUserShellToolDisplayModeParams{UserID: u.ID, ShellToolDisplayMode: "always_collapsed"}
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
dbm.EXPECT().UpdateUserShellToolDisplayMode(gomock.Any(), arg).Return("always_collapsed", nil).AnyTimes()
check.Args(arg).Asserts(u, policy.ActionUpdatePersonal).Returns("always_collapsed")
}))
s.Run("GetUserCodeDiffDisplayMode", 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()
+16
View File
@@ -2969,6 +2969,14 @@ func (m queryMetricsStore) GetUserSecretsTelemetrySummary(ctx context.Context) (
return r0, r1
}
func (m queryMetricsStore) GetUserShellToolDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
start := time.Now()
r0, r1 := m.s.GetUserShellToolDisplayMode(ctx, userID)
m.queryLatencies.WithLabelValues("GetUserShellToolDisplayMode").Observe(time.Since(start).Seconds())
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetUserShellToolDisplayMode").Inc()
return r0, r1
}
func (m queryMetricsStore) GetUserStatusCounts(ctx context.Context, arg database.GetUserStatusCountsParams) ([]database.GetUserStatusCountsRow, error) {
start := time.Now()
r0, r1 := m.s.GetUserStatusCounts(ctx, arg)
@@ -5153,6 +5161,14 @@ func (m queryMetricsStore) UpdateUserSecretByUserIDAndName(ctx context.Context,
return r0, r1
}
func (m queryMetricsStore) UpdateUserShellToolDisplayMode(ctx context.Context, arg database.UpdateUserShellToolDisplayModeParams) (string, error) {
start := time.Now()
r0, r1 := m.s.UpdateUserShellToolDisplayMode(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateUserShellToolDisplayMode").Observe(time.Since(start).Seconds())
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpdateUserShellToolDisplayMode").Inc()
return r0, r1
}
func (m queryMetricsStore) UpdateUserStatus(ctx context.Context, arg database.UpdateUserStatusParams) (database.User, error) {
start := time.Now()
r0, r1 := m.s.UpdateUserStatus(ctx, arg)
+30
View File
@@ -5553,6 +5553,21 @@ func (mr *MockStoreMockRecorder) GetUserSecretsTelemetrySummary(ctx any) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserSecretsTelemetrySummary", reflect.TypeOf((*MockStore)(nil).GetUserSecretsTelemetrySummary), ctx)
}
// GetUserShellToolDisplayMode mocks base method.
func (m *MockStore) GetUserShellToolDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUserShellToolDisplayMode", ctx, userID)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetUserShellToolDisplayMode indicates an expected call of GetUserShellToolDisplayMode.
func (mr *MockStoreMockRecorder) GetUserShellToolDisplayMode(ctx, userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserShellToolDisplayMode", reflect.TypeOf((*MockStore)(nil).GetUserShellToolDisplayMode), ctx, userID)
}
// GetUserStatusCounts mocks base method.
func (m *MockStore) GetUserStatusCounts(ctx context.Context, arg database.GetUserStatusCountsParams) ([]database.GetUserStatusCountsRow, error) {
m.ctrl.T.Helper()
@@ -9708,6 +9723,21 @@ func (mr *MockStoreMockRecorder) UpdateUserSecretByUserIDAndName(ctx, arg any) *
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserSecretByUserIDAndName", reflect.TypeOf((*MockStore)(nil).UpdateUserSecretByUserIDAndName), ctx, arg)
}
// UpdateUserShellToolDisplayMode mocks base method.
func (m *MockStore) UpdateUserShellToolDisplayMode(ctx context.Context, arg database.UpdateUserShellToolDisplayModeParams) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateUserShellToolDisplayMode", ctx, arg)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UpdateUserShellToolDisplayMode indicates an expected call of UpdateUserShellToolDisplayMode.
func (mr *MockStoreMockRecorder) UpdateUserShellToolDisplayMode(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserShellToolDisplayMode", reflect.TypeOf((*MockStore)(nil).UpdateUserShellToolDisplayMode), ctx, arg)
}
// UpdateUserStatus mocks base method.
func (m *MockStore) UpdateUserStatus(ctx context.Context, arg database.UpdateUserStatusParams) (database.User, error) {
m.ctrl.T.Helper()
+2
View File
@@ -769,6 +769,7 @@ type sqlcQuerier interface {
// percentile_disc returns an actual integer count from the underlying
// values rather than interpolating between rows.
GetUserSecretsTelemetrySummary(ctx context.Context) (GetUserSecretsTelemetrySummaryRow, error)
GetUserShellToolDisplayMode(ctx context.Context, userID uuid.UUID) (string, error)
// GetUserStatusCounts returns the count of users in each status over time.
// The time range is inclusively defined by the start_time and end_time parameters.
GetUserStatusCounts(ctx context.Context, arg GetUserStatusCountsParams) ([]GetUserStatusCountsRow, error)
@@ -1223,6 +1224,7 @@ type sqlcQuerier interface {
UpdateUserQuietHoursSchedule(ctx context.Context, arg UpdateUserQuietHoursScheduleParams) (User, error)
UpdateUserRoles(ctx context.Context, arg UpdateUserRolesParams) (User, error)
UpdateUserSecretByUserIDAndName(ctx context.Context, arg UpdateUserSecretByUserIDAndNameParams) (UserSecret, error)
UpdateUserShellToolDisplayMode(ctx context.Context, arg UpdateUserShellToolDisplayModeParams) (string, error)
UpdateUserStatus(ctx context.Context, arg UpdateUserStatusParams) (User, error)
UpdateUserTaskNotificationAlertDismissed(ctx context.Context, arg UpdateUserTaskNotificationAlertDismissedParams) (bool, error)
UpdateUserTerminalFont(ctx context.Context, arg UpdateUserTerminalFontParams) (UserConfig, error)
+44
View File
@@ -25953,6 +25953,23 @@ func (q *sqlQuerier) GetUserCount(ctx context.Context, includeSystem bool) (int6
return count, err
}
const getUserShellToolDisplayMode = `-- name: GetUserShellToolDisplayMode :one
SELECT
value AS shell_tool_display_mode
FROM
user_configs
WHERE
user_id = $1
AND key = 'preference_shell_tool_display_mode'
`
func (q *sqlQuerier) GetUserShellToolDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
row := q.db.QueryRowContext(ctx, getUserShellToolDisplayMode, userID)
var shell_tool_display_mode string
err := row.Scan(&shell_tool_display_mode)
return shell_tool_display_mode, err
}
const getUserTaskNotificationAlertDismissed = `-- name: GetUserTaskNotificationAlertDismissed :one
SELECT
value::boolean as task_notification_alert_dismissed
@@ -26869,6 +26886,33 @@ func (q *sqlQuerier) UpdateUserRoles(ctx context.Context, arg UpdateUserRolesPar
return i, err
}
const updateUserShellToolDisplayMode = `-- name: UpdateUserShellToolDisplayMode :one
INSERT INTO
user_configs (user_id, key, value)
VALUES
($1, 'preference_shell_tool_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_shell_tool_display_mode'
RETURNING value AS shell_tool_display_mode
`
type UpdateUserShellToolDisplayModeParams struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
ShellToolDisplayMode string `db:"shell_tool_display_mode" json:"shell_tool_display_mode"`
}
func (q *sqlQuerier) UpdateUserShellToolDisplayMode(ctx context.Context, arg UpdateUserShellToolDisplayModeParams) (string, error) {
row := q.db.QueryRowContext(ctx, updateUserShellToolDisplayMode, arg.UserID, arg.ShellToolDisplayMode)
var shell_tool_display_mode string
err := row.Scan(&shell_tool_display_mode)
return shell_tool_display_mode, err
}
const updateUserStatus = `-- name: UpdateUserStatus :one
UPDATE
users
+23
View File
@@ -347,6 +347,29 @@ WHERE user_configs.user_id = @user_id
AND user_configs.key = 'preference_thinking_display_mode'
RETURNING value AS thinking_display_mode;
-- name: GetUserShellToolDisplayMode :one
SELECT
value AS shell_tool_display_mode
FROM
user_configs
WHERE
user_id = @user_id
AND key = 'preference_shell_tool_display_mode';
-- name: UpdateUserShellToolDisplayMode :one
INSERT INTO
user_configs (user_id, key, value)
VALUES
(@user_id, 'preference_shell_tool_display_mode', @shell_tool_display_mode::text)
ON CONFLICT
ON CONSTRAINT user_configs_pkey
DO UPDATE
SET
value = @shell_tool_display_mode
WHERE user_configs.user_id = @user_id
AND user_configs.key = 'preference_shell_tool_display_mode'
RETURNING value AS shell_tool_display_mode;
-- name: GetUserCodeDiffDisplayMode :one
SELECT
value AS code_diff_display_mode