From 756ffb97afebb04e7debe0e8b726ec6f7b866494 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Sun, 27 Sep 2026 22:15:10 +0200 Subject: [PATCH] feat: add a collapse_assistant_steps user preference (#29416) ## Stack context Bottom of a six-PR stack that adds the **Collapse assistant steps** chat preference (Agents > Settings, off by default). With it on, each turn's consecutive tool-step rows fold into one disclosure: "Worked for 2m 14s (7 steps)" once the turn completes, or a ticking "Working for 12s" while it runs. The stack was split out of #29115 for review size; #29115 now sits at the top with the full feature description and the UAT record. 1. #29416 feat: add a collapse_assistant_steps user preference (this PR) 2. #29417 feat(site): group assistant steps into working blocks 3. #29418 feat(site): add the working block disclosure 4. #29419 feat(site): fold assistant steps in the conversation timeline 5. #29420 fix(site): keep streaming text alive inside expanded working blocks 6. #29115 feat(site): add the collapse assistant steps chat preference ## Why The chat UI reads a per-user boolean to decide whether to fold steps. This layer stores it and exposes it through the preference settings API and SDK. `collapse_assistant_steps` follows the existing `task_notification_alert_dismissed` boolean pattern: a `user_configs` key with dbauthz wrappers, no migration. The generated API docs and TypeScript types are regenerated, and the frontend preference mocks gain the new required field. > This PR was prepared by Xum, an AI coding agent, on behalf of @ibetitsmike. --- coderd/apidoc/docs.go | 6 +++ coderd/apidoc/swagger.json | 6 +++ coderd/database/dbauthz/dbauthz.go | 22 ++++++++++ coderd/database/dbauthz/dbauthz_test.go | 13 ++++++ coderd/database/dbmetrics/querymetrics.go | 16 +++++++ coderd/database/dbmock/dbmock.go | 30 +++++++++++++ coderd/database/querier.go | 2 + coderd/database/queries.sql.go | 44 +++++++++++++++++++ coderd/database/queries/users.sql | 23 ++++++++++ coderd/users.go | 35 +++++++++++++-- coderd/users_test.go | 30 +++++++++++++ codersdk/users.go | 18 ++++---- docs/reference/api/schemas.md | 4 ++ docs/reference/api/users.md | 3 ++ site/src/api/typesGenerated.ts | 2 + .../AgentSettingsGeneralPageView.stories.tsx | 1 + site/src/testHelpers/entities.ts | 1 + 17 files changed, 244 insertions(+), 12 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 9b62119367..c49d897ba6 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -30588,6 +30588,9 @@ const docTemplate = `{ "code_diff_display_mode": { "$ref": "#/definitions/codersdk.AgentDisplayMode" }, + "collapse_assistant_steps": { + "type": "boolean" + }, "shell_tool_display_mode": { "$ref": "#/definitions/codersdk.AgentDisplayMode" }, @@ -31285,6 +31288,9 @@ const docTemplate = `{ "code_diff_display_mode": { "$ref": "#/definitions/codersdk.AgentDisplayMode" }, + "collapse_assistant_steps": { + "type": "boolean" + }, "shell_tool_display_mode": { "$ref": "#/definitions/codersdk.AgentDisplayMode" }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 7289e202ae..3c0cd6a6f5 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -28187,6 +28187,9 @@ "code_diff_display_mode": { "$ref": "#/definitions/codersdk.AgentDisplayMode" }, + "collapse_assistant_steps": { + "type": "boolean" + }, "shell_tool_display_mode": { "$ref": "#/definitions/codersdk.AgentDisplayMode" }, @@ -28858,6 +28861,9 @@ "code_diff_display_mode": { "$ref": "#/definitions/codersdk.AgentDisplayMode" }, + "collapse_assistant_steps": { + "type": "boolean" + }, "shell_tool_display_mode": { "$ref": "#/definitions/codersdk.AgentDisplayMode" }, diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 815639806e..d112731431 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -5321,6 +5321,17 @@ func (q *querier) GetUserCodeDiffDisplayMode(ctx context.Context, userID uuid.UU return q.db.GetUserCodeDiffDisplayMode(ctx, userID) } +func (q *querier) GetUserCollapseAssistantSteps(ctx context.Context, userID uuid.UUID) (bool, error) { + user, err := q.db.GetUserByID(ctx, userID) + if err != nil { + return false, err + } + if err := q.authorizeContext(ctx, policy.ActionReadPersonal, user); err != nil { + return false, err + } + return q.db.GetUserCollapseAssistantSteps(ctx, userID) +} + func (q *querier) GetUserCount(ctx context.Context, includeSystem bool) (int64, error) { // If you can read every user, then you can read the count of users. if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceUser); err != nil { @@ -8400,6 +8411,17 @@ func (q *querier) UpdateUserCodeDiffDisplayMode(ctx context.Context, arg databas return q.db.UpdateUserCodeDiffDisplayMode(ctx, arg) } +func (q *querier) UpdateUserCollapseAssistantSteps(ctx context.Context, arg database.UpdateUserCollapseAssistantStepsParams) (bool, error) { + user, err := q.db.GetUserByID(ctx, arg.UserID) + if err != nil { + return false, err + } + if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, user); err != nil { + return false, err + } + return q.db.UpdateUserCollapseAssistantSteps(ctx, arg) +} + func (q *querier) UpdateUserDeletedByID(ctx context.Context, id uuid.UUID) error { return deleteQ(q.log, q.auth, q.db.GetUserByID, q.db.UpdateUserDeletedByID)(ctx, id) } diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index 04e0ea4ab1..06ae19eefc 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -3432,6 +3432,19 @@ func (s *MethodTestSuite) TestUser() { dbm.EXPECT().UpdateUserCodeDiffDisplayMode(gomock.Any(), arg).Return("always_collapsed", nil).AnyTimes() check.Args(arg).Asserts(u, policy.ActionUpdatePersonal).Returns("always_collapsed") })) + s.Run("GetUserCollapseAssistantSteps", 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().GetUserCollapseAssistantSteps(gomock.Any(), u.ID).Return(false, nil).AnyTimes() + check.Args(u.ID).Asserts(u, policy.ActionReadPersonal).Returns(false) + })) + s.Run("UpdateUserCollapseAssistantSteps", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) { + u := testutil.Fake(s.T(), faker, database.User{}) + arg := database.UpdateUserCollapseAssistantStepsParams{UserID: u.ID, CollapseAssistantSteps: true} + dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes() + dbm.EXPECT().UpdateUserCollapseAssistantSteps(gomock.Any(), arg).Return(true, nil).AnyTimes() + check.Args(arg).Asserts(u, policy.ActionUpdatePersonal).Returns(true) + })) s.Run("GetUserAgentChatSendShortcut", 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() diff --git a/coderd/database/dbmetrics/querymetrics.go b/coderd/database/dbmetrics/querymetrics.go index ec8f1b93a1..ca97f760af 100644 --- a/coderd/database/dbmetrics/querymetrics.go +++ b/coderd/database/dbmetrics/querymetrics.go @@ -3384,6 +3384,14 @@ func (m queryMetricsStore) GetUserCodeDiffDisplayMode(ctx context.Context, userI return r0, r1 } +func (m queryMetricsStore) GetUserCollapseAssistantSteps(ctx context.Context, userID uuid.UUID) (bool, error) { + start := time.Now() + r0, r1 := m.s.GetUserCollapseAssistantSteps(ctx, userID) + m.queryLatencies.WithLabelValues("GetUserCollapseAssistantSteps").Observe(time.Since(start).Seconds()) + m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetUserCollapseAssistantSteps").Inc() + return r0, r1 +} + func (m queryMetricsStore) GetUserCount(ctx context.Context, includeSystem bool) (int64, error) { start := time.Now() r0, r1 := m.s.GetUserCount(ctx, includeSystem) @@ -5848,6 +5856,14 @@ func (m queryMetricsStore) UpdateUserCodeDiffDisplayMode(ctx context.Context, ar return r0, r1 } +func (m queryMetricsStore) UpdateUserCollapseAssistantSteps(ctx context.Context, arg database.UpdateUserCollapseAssistantStepsParams) (bool, error) { + start := time.Now() + r0, r1 := m.s.UpdateUserCollapseAssistantSteps(ctx, arg) + m.queryLatencies.WithLabelValues("UpdateUserCollapseAssistantSteps").Observe(time.Since(start).Seconds()) + m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpdateUserCollapseAssistantSteps").Inc() + return r0, r1 +} + func (m queryMetricsStore) UpdateUserDeletedByID(ctx context.Context, id uuid.UUID) error { start := time.Now() r0 := m.s.UpdateUserDeletedByID(ctx, id) diff --git a/coderd/database/dbmock/dbmock.go b/coderd/database/dbmock/dbmock.go index 743e1190a5..31ea71d725 100644 --- a/coderd/database/dbmock/dbmock.go +++ b/coderd/database/dbmock/dbmock.go @@ -6373,6 +6373,21 @@ func (mr *MockStoreMockRecorder) GetUserCodeDiffDisplayMode(ctx, userID any) *go return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserCodeDiffDisplayMode", reflect.TypeOf((*MockStore)(nil).GetUserCodeDiffDisplayMode), ctx, userID) } +// GetUserCollapseAssistantSteps mocks base method. +func (m *MockStore) GetUserCollapseAssistantSteps(ctx context.Context, userID uuid.UUID) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUserCollapseAssistantSteps", ctx, userID) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetUserCollapseAssistantSteps indicates an expected call of GetUserCollapseAssistantSteps. +func (mr *MockStoreMockRecorder) GetUserCollapseAssistantSteps(ctx, userID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserCollapseAssistantSteps", reflect.TypeOf((*MockStore)(nil).GetUserCollapseAssistantSteps), ctx, userID) +} + // GetUserCount mocks base method. func (m *MockStore) GetUserCount(ctx context.Context, includeSystem bool) (int64, error) { m.ctrl.T.Helper() @@ -11050,6 +11065,21 @@ func (mr *MockStoreMockRecorder) UpdateUserCodeDiffDisplayMode(ctx, arg any) *go return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserCodeDiffDisplayMode", reflect.TypeOf((*MockStore)(nil).UpdateUserCodeDiffDisplayMode), ctx, arg) } +// UpdateUserCollapseAssistantSteps mocks base method. +func (m *MockStore) UpdateUserCollapseAssistantSteps(ctx context.Context, arg database.UpdateUserCollapseAssistantStepsParams) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateUserCollapseAssistantSteps", ctx, arg) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateUserCollapseAssistantSteps indicates an expected call of UpdateUserCollapseAssistantSteps. +func (mr *MockStoreMockRecorder) UpdateUserCollapseAssistantSteps(ctx, arg any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserCollapseAssistantSteps", reflect.TypeOf((*MockStore)(nil).UpdateUserCollapseAssistantSteps), ctx, arg) +} + // UpdateUserDeletedByID mocks base method. func (m *MockStore) UpdateUserDeletedByID(ctx context.Context, id uuid.UUID) error { m.ctrl.T.Helper() diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 334f3fef19..ad44900dc1 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -961,6 +961,7 @@ type sqlcQuerier interface { GetUserChatCustomPrompt(ctx context.Context, userID uuid.UUID) (string, error) GetUserChatDebugLoggingEnabled(ctx context.Context, userID uuid.UUID) (bool, error) GetUserCodeDiffDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) + GetUserCollapseAssistantSteps(ctx context.Context, userID uuid.UUID) (bool, error) GetUserCount(ctx context.Context, includeSystem bool) (int64, error) // Returns the "Everyone" group (id == organization_id) to attribute a user's // spend to when no override or budgeted group applies. Prefers the default org, @@ -1606,6 +1607,7 @@ type sqlcQuerier interface { UpdateUserChatCompactionThreshold(ctx context.Context, arg UpdateUserChatCompactionThresholdParams) (UserConfig, error) UpdateUserChatCustomPrompt(ctx context.Context, arg UpdateUserChatCustomPromptParams) (UserConfig, error) UpdateUserCodeDiffDisplayMode(ctx context.Context, arg UpdateUserCodeDiffDisplayModeParams) (string, error) + UpdateUserCollapseAssistantSteps(ctx context.Context, arg UpdateUserCollapseAssistantStepsParams) (bool, error) UpdateUserDeletedByID(ctx context.Context, id uuid.UUID) error UpdateUserEmail(ctx context.Context, arg UpdateUserEmailParams) (User, error) UpdateUserGithubComUserID(ctx context.Context, arg UpdateUserGithubComUserIDParams) error diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index bba88ef7b0..5f2adba75d 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -31787,6 +31787,23 @@ func (q *sqlQuerier) GetUserCodeDiffDisplayMode(ctx context.Context, userID uuid return code_diff_display_mode, err } +const getUserCollapseAssistantSteps = `-- name: GetUserCollapseAssistantSteps :one +SELECT + value::boolean as collapse_assistant_steps +FROM + user_configs +WHERE + user_id = $1 + AND key = 'preference_collapse_assistant_steps' +` + +func (q *sqlQuerier) GetUserCollapseAssistantSteps(ctx context.Context, userID uuid.UUID) (bool, error) { + row := q.db.QueryRowContext(ctx, getUserCollapseAssistantSteps, userID) + var collapse_assistant_steps bool + err := row.Scan(&collapse_assistant_steps) + return collapse_assistant_steps, err +} + const getUserCount = `-- name: GetUserCount :one SELECT COUNT(*) @@ -32421,6 +32438,33 @@ func (q *sqlQuerier) UpdateUserCodeDiffDisplayMode(ctx context.Context, arg Upda return code_diff_display_mode, err } +const updateUserCollapseAssistantSteps = `-- name: UpdateUserCollapseAssistantSteps :one +INSERT INTO + user_configs (user_id, key, value) +VALUES + ($1, 'preference_collapse_assistant_steps', ($2::boolean)::text) +ON CONFLICT + ON CONSTRAINT user_configs_pkey +DO UPDATE +SET + value = $2 +WHERE user_configs.user_id = $1 + AND user_configs.key = 'preference_collapse_assistant_steps' +RETURNING value::boolean AS collapse_assistant_steps +` + +type UpdateUserCollapseAssistantStepsParams struct { + UserID uuid.UUID `db:"user_id" json:"user_id"` + CollapseAssistantSteps bool `db:"collapse_assistant_steps" json:"collapse_assistant_steps"` +} + +func (q *sqlQuerier) UpdateUserCollapseAssistantSteps(ctx context.Context, arg UpdateUserCollapseAssistantStepsParams) (bool, error) { + row := q.db.QueryRowContext(ctx, updateUserCollapseAssistantSteps, arg.UserID, arg.CollapseAssistantSteps) + var collapse_assistant_steps bool + err := row.Scan(&collapse_assistant_steps) + return collapse_assistant_steps, err +} + const updateUserDeletedByID = `-- name: UpdateUserDeletedByID :exec UPDATE users diff --git a/coderd/database/queries/users.sql b/coderd/database/queries/users.sql index e04d54e0c8..4aefa0e315 100644 --- a/coderd/database/queries/users.sql +++ b/coderd/database/queries/users.sql @@ -376,6 +376,29 @@ WHERE user_configs.user_id = @user_id AND user_configs.key = 'preference_agent_chat_send_shortcut' RETURNING value AS agent_chat_send_shortcut; +-- name: GetUserCollapseAssistantSteps :one +SELECT + value::boolean as collapse_assistant_steps +FROM + user_configs +WHERE + user_id = @user_id + AND key = 'preference_collapse_assistant_steps'; + +-- name: UpdateUserCollapseAssistantSteps :one +INSERT INTO + user_configs (user_id, key, value) +VALUES + (@user_id, 'preference_collapse_assistant_steps', (@collapse_assistant_steps::boolean)::text) +ON CONFLICT + ON CONSTRAINT user_configs_pkey +DO UPDATE +SET + value = @collapse_assistant_steps +WHERE user_configs.user_id = @user_id + AND user_configs.key = 'preference_collapse_assistant_steps' +RETURNING value::boolean AS collapse_assistant_steps; + -- name: UpdateUserRoles :one UPDATE users diff --git a/coderd/users.go b/coderd/users.go index 942cd4a1fe..4fe355f477 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -1485,6 +1485,15 @@ func (api *API) userPreferenceSettings(rw http.ResponseWriter, r *http.Request) return } + collapseAssistantSteps, err := api.Database.GetUserCollapseAssistantSteps(ctx, user.ID) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Error reading user preference settings.", + Detail: err.Error(), + }) + return + } + agentChatSendShortcut, err := api.Database.GetUserAgentChatSendShortcut(ctx, user.ID) if err != nil && !errors.Is(err, sql.ErrNoRows) { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ @@ -1495,10 +1504,11 @@ func (api *API) userPreferenceSettings(rw http.ResponseWriter, r *http.Request) } httpapi.Write(ctx, rw, http.StatusOK, codersdk.UserPreferenceSettings{ - ThinkingDisplayMode: sanitizeThinkingDisplayMode(thinkingMode), - ShellToolDisplayMode: sanitizeShellToolDisplayMode(shellToolMode), - CodeDiffDisplayMode: sanitizeAgentDisplayMode(codeDiffMode), - AgentChatSendShortcut: sanitizeAgentChatSendShortcut(agentChatSendShortcut), + ThinkingDisplayMode: sanitizeThinkingDisplayMode(thinkingMode), + ShellToolDisplayMode: sanitizeShellToolDisplayMode(shellToolMode), + CodeDiffDisplayMode: sanitizeAgentDisplayMode(codeDiffMode), + CollapseAssistantSteps: collapseAssistantSteps, + AgentChatSendShortcut: sanitizeAgentChatSendShortcut(agentChatSendShortcut), }) } @@ -1616,6 +1626,23 @@ func (api *API) putUserPreferenceSettings(rw http.ResponseWriter, r *http.Reques settings.CodeDiffDisplayMode = sanitizeAgentDisplayMode(stored) } + if params.CollapseAssistantSteps != nil { + updated, err := tx.UpdateUserCollapseAssistantSteps(ctx, database.UpdateUserCollapseAssistantStepsParams{ + UserID: user.ID, + CollapseAssistantSteps: *params.CollapseAssistantSteps, + }) + if err != nil { + return newUserPreferenceSettingsAPIError("Internal error updating user collapse assistant steps.", err) + } + settings.CollapseAssistantSteps = updated + } else { + stored, err := tx.GetUserCollapseAssistantSteps(ctx, user.ID) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return newUserPreferenceSettingsAPIError("Error reading collapse assistant steps.", err) + } + settings.CollapseAssistantSteps = stored + } + if params.AgentChatSendShortcut != "" { updated, err := tx.UpdateUserAgentChatSendShortcut(ctx, database.UpdateUserAgentChatSendShortcutParams{ UserID: user.ID, diff --git a/coderd/users_test.go b/coderd/users_test.go index 245a523770..6faf8de48c 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -2627,6 +2627,36 @@ func TestUserThemeMode(t *testing.T) { }) } +func TestUserCollapseAssistantSteps(t *testing.T) { + t.Parallel() + + client := coderdtest.New(t, nil) + coderdtest.CreateFirstUser(t, client) + ctx := testutil.Context(t, testutil.WaitShort) + + settings, err := client.GetUserPreferenceSettings(ctx, codersdk.Me) + require.NoError(t, err) + require.False(t, settings.CollapseAssistantSteps) + + for _, collapse := range []bool{true, false} { + updated, err := client.UpdateUserPreferenceSettings(ctx, codersdk.Me, codersdk.UpdateUserPreferenceSettingsRequest{ + CollapseAssistantSteps: &collapse, + }) + require.NoError(t, err) + require.Equal(t, collapse, updated.CollapseAssistantSteps) + + settings, err := client.GetUserPreferenceSettings(ctx, codersdk.Me) + require.NoError(t, err) + require.Equal(t, collapse, settings.CollapseAssistantSteps) + + updated, err = client.UpdateUserPreferenceSettings(ctx, codersdk.Me, codersdk.UpdateUserPreferenceSettingsRequest{ + ThinkingDisplayMode: codersdk.ThinkingDisplayModePreview, + }) + require.NoError(t, err) + require.Equal(t, collapse, updated.CollapseAssistantSteps) + } +} + func TestThinkingDisplayMode(t *testing.T) { t.Parallel() diff --git a/codersdk/users.go b/codersdk/users.go index 76ec0127db..8b59163c06 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -279,17 +279,19 @@ type UpdateUserAppearanceSettingsRequest struct { } type UserPreferenceSettings struct { - ThinkingDisplayMode ThinkingDisplayMode `json:"thinking_display_mode"` - ShellToolDisplayMode AgentDisplayMode `json:"shell_tool_display_mode"` - CodeDiffDisplayMode AgentDisplayMode `json:"code_diff_display_mode"` - AgentChatSendShortcut AgentChatSendShortcut `json:"agent_chat_send_shortcut"` + ThinkingDisplayMode ThinkingDisplayMode `json:"thinking_display_mode"` + ShellToolDisplayMode AgentDisplayMode `json:"shell_tool_display_mode"` + CodeDiffDisplayMode AgentDisplayMode `json:"code_diff_display_mode"` + CollapseAssistantSteps bool `json:"collapse_assistant_steps"` + AgentChatSendShortcut AgentChatSendShortcut `json:"agent_chat_send_shortcut"` } type UpdateUserPreferenceSettingsRequest struct { - ThinkingDisplayMode ThinkingDisplayMode `json:"thinking_display_mode,omitempty"` - ShellToolDisplayMode AgentDisplayMode `json:"shell_tool_display_mode,omitempty"` - CodeDiffDisplayMode AgentDisplayMode `json:"code_diff_display_mode,omitempty"` - AgentChatSendShortcut AgentChatSendShortcut `json:"agent_chat_send_shortcut,omitempty"` + ThinkingDisplayMode ThinkingDisplayMode `json:"thinking_display_mode,omitempty"` + ShellToolDisplayMode AgentDisplayMode `json:"shell_tool_display_mode,omitempty"` + CodeDiffDisplayMode AgentDisplayMode `json:"code_diff_display_mode,omitempty"` + CollapseAssistantSteps *bool `json:"collapse_assistant_steps,omitempty"` + AgentChatSendShortcut AgentChatSendShortcut `json:"agent_chat_send_shortcut,omitempty"` } type AgentChatSendShortcut string diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index a0323bfed4..8ea5b9a892 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -16536,6 +16536,7 @@ Restarts will only happen on weekdays in this list on weeks which line up with W { "agent_chat_send_shortcut": "enter", "code_diff_display_mode": "auto", + "collapse_assistant_steps": true, "shell_tool_display_mode": "auto", "thinking_display_mode": "auto" } @@ -16547,6 +16548,7 @@ Restarts will only happen on weekdays in this list on weeks which line up with W |----------------------------|------------------------------------------------------------------|----------|--------------|-------------| | `agent_chat_send_shortcut` | [codersdk.AgentChatSendShortcut](#codersdkagentchatsendshortcut) | false | | | | `code_diff_display_mode` | [codersdk.AgentDisplayMode](#codersdkagentdisplaymode) | false | | | +| `collapse_assistant_steps` | boolean | false | | | | `shell_tool_display_mode` | [codersdk.AgentDisplayMode](#codersdkagentdisplaymode) | false | | | | `thinking_display_mode` | [codersdk.ThinkingDisplayMode](#codersdkthinkingdisplaymode) | false | | | @@ -17406,6 +17408,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| { "agent_chat_send_shortcut": "enter", "code_diff_display_mode": "auto", + "collapse_assistant_steps": true, "shell_tool_display_mode": "auto", "thinking_display_mode": "auto" } @@ -17417,6 +17420,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| |----------------------------|------------------------------------------------------------------|----------|--------------|-------------| | `agent_chat_send_shortcut` | [codersdk.AgentChatSendShortcut](#codersdkagentchatsendshortcut) | false | | | | `code_diff_display_mode` | [codersdk.AgentDisplayMode](#codersdkagentdisplaymode) | false | | | +| `collapse_assistant_steps` | boolean | false | | | | `shell_tool_display_mode` | [codersdk.AgentDisplayMode](#codersdkagentdisplaymode) | false | | | | `thinking_display_mode` | [codersdk.ThinkingDisplayMode](#codersdkthinkingdisplaymode) | false | | | diff --git a/docs/reference/api/users.md b/docs/reference/api/users.md index b2dc005794..a3c68c400c 100644 --- a/docs/reference/api/users.md +++ b/docs/reference/api/users.md @@ -1324,6 +1324,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/preferences \ { "agent_chat_send_shortcut": "enter", "code_diff_display_mode": "auto", + "collapse_assistant_steps": true, "shell_tool_display_mode": "auto", "thinking_display_mode": "auto" } @@ -1357,6 +1358,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/preferences \ { "agent_chat_send_shortcut": "enter", "code_diff_display_mode": "auto", + "collapse_assistant_steps": true, "shell_tool_display_mode": "auto", "thinking_display_mode": "auto" } @@ -1377,6 +1379,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/preferences \ { "agent_chat_send_shortcut": "enter", "code_diff_display_mode": "auto", + "collapse_assistant_steps": true, "shell_tool_display_mode": "auto", "thinking_display_mode": "auto" } diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index cb23d0fbeb..b607cac34b 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -10556,6 +10556,7 @@ export interface UpdateUserPreferenceSettingsRequest { readonly thinking_display_mode?: ThinkingDisplayMode; readonly shell_tool_display_mode?: AgentDisplayMode; readonly code_diff_display_mode?: AgentDisplayMode; + readonly collapse_assistant_steps?: boolean; readonly agent_chat_send_shortcut?: AgentChatSendShortcut; } @@ -11078,6 +11079,7 @@ export interface UserPreferenceSettings { readonly thinking_display_mode: ThinkingDisplayMode; readonly shell_tool_display_mode: AgentDisplayMode; readonly code_diff_display_mode: AgentDisplayMode; + readonly collapse_assistant_steps: boolean; readonly agent_chat_send_shortcut: AgentChatSendShortcut; } diff --git a/site/src/pages/AgentsPage/AgentSettingsGeneralPageView.stories.tsx b/site/src/pages/AgentsPage/AgentSettingsGeneralPageView.stories.tsx index 01f57c51c3..4cd8e5fd1c 100644 --- a/site/src/pages/AgentsPage/AgentSettingsGeneralPageView.stories.tsx +++ b/site/src/pages/AgentsPage/AgentSettingsGeneralPageView.stories.tsx @@ -11,6 +11,7 @@ const preferencesData = { thinking_display_mode: "auto" as const, shell_tool_display_mode: "auto" as const, code_diff_display_mode: "auto" as const, + collapse_assistant_steps: false, agent_chat_send_shortcut: "enter" as const, }; diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index c7e619ac9a..33c3e8e5a5 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -510,6 +510,7 @@ export const MockUserPreferenceSettings: TypesGen.UserPreferenceSettings = { thinking_display_mode: "auto", shell_tool_display_mode: "auto", code_diff_display_mode: "auto", + collapse_assistant_steps: false, agent_chat_send_shortcut: "enter", };