Skip to content

Commit 784d76a

Browse files
authored
ref(seer): Refactor variables & types on Seer Settings pages (#106627)
This makes all pages use the same variable names, definitions, etc for the same thing. Also disables the `background agent` toggle on the Settings>Project>Seer list page in the same way as its disabled on the project-details page. Depends on #106615
1 parent 6b3edb8 commit 784d76a

10 files changed

Lines changed: 90 additions & 95 deletions

File tree

static/app/components/events/autofix/preferences/hooks/useBulkAutofixAutomationSettings.ts

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import {useCallback} from 'react';
1+
import {useCallback, useMemo} from 'react';
22

3+
import type {ProjectSeerPreferences} from 'sentry/components/events/autofix/types';
34
import useFetchSequentialPages from 'sentry/utils/api/useFetchSequentialPages';
45
import {
56
fetchMutation,
@@ -8,6 +9,7 @@ import {
89
type UseMutationOptions,
910
} from 'sentry/utils/queryClient';
1011
import useOrganization from 'sentry/utils/useOrganization';
12+
import useProjects from 'sentry/utils/useProjects';
1113

1214
type AutofixAutomationTuning =
1315
| 'off'
@@ -18,13 +20,6 @@ type AutofixAutomationTuning =
1820
| 'always' // deprecated
1921
| null; // deprecated
2022

21-
type AutomatedRunStoppingPoint =
22-
| 'root_cause'
23-
| 'solution'
24-
| 'code_changes'
25-
| 'open_pr'
26-
| 'background_agent';
27-
2823
// Mirrors the backend SeerRepoDefinition type
2924
export interface BackendRepository {
3025
external_id: string;
@@ -46,7 +41,8 @@ export interface BackendRepository {
4641

4742
export type AutofixAutomationSettings = {
4843
autofixAutomationTuning: AutofixAutomationTuning;
49-
automatedRunStoppingPoint: AutomatedRunStoppingPoint;
44+
automatedRunStoppingPoint: ProjectSeerPreferences['automated_run_stopping_point'];
45+
automationHandoff: ProjectSeerPreferences['automation_handoff'];
5046
projectId: string;
5147
reposCount: number;
5248
};
@@ -80,26 +76,30 @@ type AutofixAutomationUpdate =
8076
| {
8177
autofixAutomationTuning: AutofixAutomationTuning;
8278
projectIds: string[];
83-
automatedRunStoppingPoint?: never | AutomatedRunStoppingPoint;
79+
automatedRunStoppingPoint?:
80+
| never
81+
| ProjectSeerPreferences['automated_run_stopping_point'];
8482
projectRepoMappings?: never | Record<string, BackendRepository[]>;
8583
}
8684
| {
87-
automatedRunStoppingPoint: AutomatedRunStoppingPoint;
85+
automatedRunStoppingPoint: ProjectSeerPreferences['automated_run_stopping_point'];
8886
projectIds: string[];
8987
autofixAutomationTuning?: never | AutofixAutomationTuning;
9088
projectRepoMappings?: never | Record<string, BackendRepository[]>;
9189
}
9290
| {
9391
autofixAutomationTuning: AutofixAutomationTuning;
94-
automatedRunStoppingPoint: AutomatedRunStoppingPoint;
92+
automatedRunStoppingPoint: ProjectSeerPreferences['automated_run_stopping_point'];
9593
projectIds: string[];
9694
projectRepoMappings?: never | Record<string, BackendRepository[]>;
9795
}
9896
| {
9997
projectIds: string[];
10098
projectRepoMappings: Record<string, BackendRepository[]>;
10199
autofixAutomationTuning?: never | AutofixAutomationTuning;
102-
automatedRunStoppingPoint?: never | AutomatedRunStoppingPoint;
100+
automatedRunStoppingPoint?:
101+
| never
102+
| ProjectSeerPreferences['automated_run_stopping_point'];
103103
};
104104

105105
export function useUpdateBulkAutofixAutomationSettings(
@@ -111,6 +111,12 @@ export function useUpdateBulkAutofixAutomationSettings(
111111
const organization = useOrganization();
112112
const queryClient = useQueryClient();
113113

114+
const {projects} = useProjects();
115+
const projectsById = useMemo(
116+
() => new Map(projects.map(project => [project.id, project])),
117+
[projects]
118+
);
119+
114120
return useMutation<unknown, Error, AutofixAutomationUpdate, unknown>({
115121
mutationFn: (data: AutofixAutomationUpdate) => {
116122
return fetchMutation({
@@ -124,6 +130,22 @@ export function useUpdateBulkAutofixAutomationSettings(
124130
queryClient.invalidateQueries({
125131
queryKey: [`/organizations/${organization.slug}/autofix/automation-settings/`],
126132
});
133+
const [, , data] = args;
134+
data.projectIds.forEach(projectId => {
135+
const project = projectsById.get(projectId);
136+
if (!project) {
137+
return;
138+
}
139+
// Invalidate the query for ProjectOptions to Settings>Project>Seer details page
140+
queryClient.invalidateQueries({
141+
queryKey: [`/projects/${organization.slug}/${project.slug}/`],
142+
});
143+
// Invalidate the query for SeerPreferences to Settings>Project>Seer details page
144+
queryClient.invalidateQueries({
145+
queryKey: [`/projects/${organization.slug}/${project.slug}/seer/preferences/`],
146+
});
147+
});
148+
127149
options?.onSettled?.(...args);
128150
},
129151
});

static/app/components/events/autofix/preferences/hooks/useUpdateProjectSeerPreferences.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ export function useUpdateProjectSeerPreferences(project: Project) {
6868
},
6969
onSettled: () => {
7070
queryClient.invalidateQueries({queryKey});
71+
queryClient.invalidateQueries({
72+
queryKey: [`/organizations/${organization.slug}/autofix/automation-settings/`],
73+
});
7174
},
7275
});
7376
}

static/app/components/events/autofix/types.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -320,12 +320,7 @@ interface SeerAutomationHandoffConfiguration {
320320

321321
export interface ProjectSeerPreferences {
322322
repositories: SeerRepoDefinition[];
323-
automated_run_stopping_point?:
324-
| 'root_cause'
325-
| 'solution'
326-
| 'code_changes'
327-
| 'open_pr'
328-
| 'background_agent';
323+
automated_run_stopping_point?: 'root_cause' | 'solution' | 'code_changes' | 'open_pr';
329324
automation_handoff?: SeerAutomationHandoffConfiguration;
330325
}
331326

static/app/views/settings/projectSeer/autofixRepositories.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import {DropdownMenu} from 'sentry/components/dropdownMenu';
1111
import {useOrganizationRepositories} from 'sentry/components/events/autofix/preferences/hooks/useOrganizationRepositories';
1212
import {useProjectSeerPreferences} from 'sentry/components/events/autofix/preferences/hooks/useProjectSeerPreferences';
1313
import {useUpdateProjectSeerPreferences} from 'sentry/components/events/autofix/preferences/hooks/useUpdateProjectSeerPreferences';
14-
import type {RepoSettings} from 'sentry/components/events/autofix/types';
14+
import type {
15+
ProjectSeerPreferences,
16+
RepoSettings,
17+
} from 'sentry/components/events/autofix/types';
1518
import LoadingIndicator from 'sentry/components/loadingIndicator';
1619
import Panel from 'sentry/components/panels/panel';
1720
import PanelHeader from 'sentry/components/panels/panelHeader';
@@ -46,19 +49,16 @@ export function AutofixRepositories({project}: ProjectSeerProps) {
4649
const [repoSettings, setRepoSettings] = useState<Record<string, RepoSettings>>({});
4750
const [showSaveNotice, setShowSaveNotice] = useState(false);
4851

49-
const getDefaultStoppingPoint = useCallback(():
50-
| 'root_cause'
51-
| 'solution'
52-
| 'code_changes'
53-
| 'open_pr' => {
54-
if (organization.features.includes('seat-based-seer-enabled')) {
55-
return organization.autoOpenPrs ? 'open_pr' : 'code_changes';
56-
}
57-
return 'root_cause';
58-
}, [organization.features, organization.autoOpenPrs]);
52+
const getDefaultStoppingPoint =
53+
useCallback((): ProjectSeerPreferences['automated_run_stopping_point'] => {
54+
if (organization.features.includes('seat-based-seer-enabled')) {
55+
return organization.autoOpenPrs ? 'open_pr' : 'code_changes';
56+
}
57+
return 'root_cause';
58+
}, [organization.features, organization.autoOpenPrs]);
5959

6060
const [automatedRunStoppingPoint, setAutomatedRunStoppingPoint] = useState<
61-
'root_cause' | 'solution' | 'code_changes' | 'open_pr' | 'background_agent'
61+
ProjectSeerPreferences['automated_run_stopping_point']
6262
>(getDefaultStoppingPoint());
6363

6464
useEffect(() => {

static/gsApp/views/seerAutomation/components/projectDetails/autoTriggeredFixesToggle.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ interface Props {
1616
export default function AutoTriggeredFixesToggle({canWrite, project}: Props) {
1717
const {mutate: updateProject} = useUpdateProject(project);
1818

19-
const isEnabled = Boolean(
19+
const isAutoFixEnabled = Boolean(
2020
project.autofixAutomationTuning && project.autofixAutomationTuning !== 'off'
2121
);
2222

@@ -28,11 +28,10 @@ export default function AutoTriggeredFixesToggle({canWrite, project}: Props) {
2828
help={t(
2929
'Automatically analyze highly actionable issues, and create a root cause analysis without a user needing to prompt it.'
3030
)}
31-
value={isEnabled}
31+
value={isAutoFixEnabled}
3232
onChange={value => {
33-
const newValue: Project['autofixAutomationTuning'] = value ? 'medium' : 'off';
3433
updateProject(
35-
{autofixAutomationTuning: newValue},
34+
{autofixAutomationTuning: value ? 'medium' : 'off'},
3635
{
3736
onSuccess: () =>
3837
addSuccessMessage(

static/gsApp/views/seerAutomation/components/projectDetails/backgroundAgentFields.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,15 @@ function CursorIntegrationFields({
4848
}: Props) {
4949
const {mutate: updateProjectSeerPreferences} = useUpdateProjectSeerPreferences(project);
5050

51-
const isBackgroundAgentEnabled = Boolean(preference?.automation_handoff);
52-
const isAutoTriggeredFixesEnabled = Boolean(
51+
const isAutoFixEnabled = Boolean(
5352
project.autofixAutomationTuning && project.autofixAutomationTuning !== 'off'
5453
);
54+
const isBackgroundAgentEnabled = Boolean(preference?.automation_handoff);
5555

56-
const isDisabled =
57-
!canWrite || !isAutoTriggeredFixesEnabled || !isBackgroundAgentEnabled;
56+
const isDisabled = !canWrite || !isAutoFixEnabled || !isBackgroundAgentEnabled;
5857

5958
let disabledReason: string | null = null;
60-
if (!isAutoTriggeredFixesEnabled) {
59+
if (!isAutoFixEnabled) {
6160
disabledReason = t('Turn on Auto-Triggered Fixes to use this feature.');
6261
} else if (!isBackgroundAgentEnabled) {
6362
disabledReason = t('This setting is only available when using background agents.');

static/gsApp/views/seerAutomation/components/projectDetails/seerAgentSection.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,19 @@ interface Props {
2020
export default function SeerAgentSection({canWrite, project, preference}: Props) {
2121
const {mutate: updateProjectSeerPreferences} = useUpdateProjectSeerPreferences(project);
2222

23-
const isAutoCreatePREnabled = Boolean(
23+
const isAutoFixEnabled = Boolean(
24+
project.autofixAutomationTuning && project.autofixAutomationTuning !== 'off'
25+
);
26+
const isCreatePrEnabled = Boolean(
2427
preference?.automated_run_stopping_point &&
2528
preference.automated_run_stopping_point !== 'code_changes'
2629
);
27-
2830
const isBackgroundAgentEnabled = Boolean(preference?.automation_handoff);
29-
const isAutoTriggeredFixesEnabled = Boolean(
30-
project.autofixAutomationTuning && project.autofixAutomationTuning !== 'off'
31-
);
3231

33-
const isDisabled =
34-
!canWrite || !isAutoTriggeredFixesEnabled || isBackgroundAgentEnabled;
32+
const isDisabled = !canWrite || !isAutoFixEnabled || isBackgroundAgentEnabled;
3533

3634
let disabledReason: string | null = null;
37-
if (!isAutoTriggeredFixesEnabled) {
35+
if (!isAutoFixEnabled) {
3836
disabledReason = t('Turn on Auto-Triggered Fixes to use this feature.');
3937
} else if (isBackgroundAgentEnabled) {
4038
disabledReason = t('This setting is not available when using background agents.');
@@ -52,7 +50,7 @@ export default function SeerAgentSection({canWrite, project, preference}: Props)
5250
docsLink: <ExternalLink href="https://docs.sentry.io/product/ai-in-sentry/" />,
5351
}
5452
)}
55-
value={isAutoCreatePREnabled}
53+
value={isCreatePrEnabled}
5654
onChange={value => {
5755
const newValue: ProjectSeerPreferences['automated_run_stopping_point'] = value
5856
? 'open_pr'

static/gsApp/views/seerAutomation/components/projectTable/seerProjectTable.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,27 @@ import LoadingIndicator from 'sentry/components/loadingIndicator';
1515
import {SimpleTable} from 'sentry/components/tables/simpleTable';
1616
import {IconSearch} from 'sentry/icons/iconSearch';
1717
import {t, tct} from 'sentry/locale';
18-
import type {Organization} from 'sentry/types/organization';
1918
import type {Project} from 'sentry/types/project';
2019
import type {Sort} from 'sentry/utils/discover/fields';
2120
import {ListItemCheckboxProvider} from 'sentry/utils/list/useListItemCheckboxState';
2221
import type {ApiQueryKey} from 'sentry/utils/queryClient';
2322
import {parseAsSort} from 'sentry/utils/queryString';
24-
import useOrganization from 'sentry/utils/useOrganization';
2523
import useProjects from 'sentry/utils/useProjects';
2624

2725
import ProjectTableHeader from 'getsentry/views/seerAutomation/components/projectTable/seerProjectTableHeader';
2826
import SeerProjectTableRow from 'getsentry/views/seerAutomation/components/projectTable/seerProjectTableRow';
2927

30-
function getDefaultAutofixSettings(
31-
organization: Organization,
32-
projectId: string
33-
): AutofixAutomationSettings {
28+
function getDefaultAutofixSettings(projectId: string): AutofixAutomationSettings {
3429
return {
35-
autofixAutomationTuning: organization.defaultAutofixAutomationTuning ?? 'off',
36-
automatedRunStoppingPoint: organization.autoOpenPrs ? 'open_pr' : 'code_changes',
30+
autofixAutomationTuning: 'off',
31+
automatedRunStoppingPoint: 'code_changes',
32+
automationHandoff: undefined,
3733
projectId,
3834
reposCount: 0,
3935
};
4036
}
4137

4238
export default function SeerProjectTable() {
43-
const organization = useOrganization();
4439
const {projects, fetching, fetchError} = useProjects();
4540

4641
const {pages: autofixAutomationSettings, isFetching: isFetchingSettings} =
@@ -184,7 +179,7 @@ export default function SeerProjectTable() {
184179
project={project}
185180
isFetchingSettings={isFetchingSettings}
186181
autofixSettings={{
187-
...getDefaultAutofixSettings(organization, project.id),
182+
...getDefaultAutofixSettings(project.id),
188183
...autofixSettingsByProjectId.get(project.id),
189184
...mutationData[project.id],
190185
}}

static/gsApp/views/seerAutomation/components/projectTable/seerProjectTableHeader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ const COLUMNS = [
3333
{title: t('PR Creation'), key: 'pr_creation'},
3434
{
3535
title: (
36-
<Flex gap="sm">
36+
<Flex gap="sm" align="center">
3737
{t('Background Agent')}
3838
<QuestionTooltip
3939
title={t(
40-
'Background agent delegation can only be enabled on the individual project settings page. Background agents can have their own settings that are not shown here.'
40+
'Background agent delegation can only be changed on the individual project settings page. Background agents have more settings that are not shown here.'
4141
)}
4242
size="xs"
4343
/>

0 commit comments

Comments
 (0)