Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export interface ExplorerAutofixState {
*/
interface ExplorerAutofixResponse {
autofix: ExplorerAutofixState | null;
formatted?: {content: string; format: string};
}

const POLL_INTERVAL = 1000;
Expand All @@ -170,7 +171,7 @@ function explorerAutofixApiOptions(orgSlug: string, groupId: string) {
'/organizations/$organizationIdOrSlug/issues/$issueId/autofix/',
{
path: {organizationIdOrSlug: orgSlug, issueId: groupId},
query: {mode: 'explorer'},
query: {mode: 'explorer', llmFormat: 'markdown'},
staleTime: 0,
}
);
Expand Down Expand Up @@ -810,6 +811,10 @@ export function useExplorerAutofix(
* Current autofix run state, or null if no run exists.
*/
runState,
/**
* Formatted markdown for LLM prompts
*/
autofixFormatted: apiData?.formatted?.content ?? null,
/**
* Whether the initial data fetch is pending.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ function makePR(overrides: Partial<RepoPRState> = {}): RepoPRState {

const mockAutofix: ReturnType<typeof useExplorerAutofix> = {
runState: null,
autofixFormatted: null,
isLoading: false,
isPolling: false,
startStep: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function makeAutofix(
): ReturnType<typeof useExplorerAutofix> {
const base: ReturnType<typeof useExplorerAutofix> = {
runState: {run_id: 1} as any,
autofixFormatted: null,
startStep: jest.fn(),
createPR: jest.fn(),
reset: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function makeAutofix(
): ReturnType<typeof useExplorerAutofix> {
return {
runState: {run_id: 1, blocks: []} as any,
autofixFormatted: null,
startStep: jest.fn().mockResolvedValue(undefined),
createPR: jest.fn(),
reset: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ function makeAutofix(
): ReturnType<typeof useExplorerAutofix> {
const base: ReturnType<typeof useExplorerAutofix> = {
runState: null,
autofixFormatted: null,
startStep: jest.fn(),
createPR: jest.fn(),
reset: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function makeAutofix(
): ReturnType<typeof useExplorerAutofix> {
const base: ReturnType<typeof useExplorerAutofix> = {
runState: null,
autofixFormatted: null,
startStep: jest.fn(),
createPR: jest.fn(),
reset: jest.fn(),
Expand Down
1 change: 1 addition & 0 deletions static/app/types/event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ interface EventBase {
dateCreated?: string;
device?: Record<string, any>;
endTimestamp?: number;
formatted?: {content: string; format: string};
groupID?: string;
groupingConfig?: {
enhancements: string;
Expand Down
7 changes: 5 additions & 2 deletions static/app/views/issueDetails/eventNavigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ export function IssueEventNavigation({event, group}: IssueEventNavigationProps)
const activeThreadId = useActiveThreadId();

// Get data for markdown copy functionality
const {runState: autofixData} = useExplorerAutofix(group.id, {enabled: false});
const {runState: autofixData, autofixFormatted} = useExplorerAutofix(group.id, {
enabled: false,
});

const handleCopyMarkdown = useCallback(() => {
const markdownText = issueAndEventToMarkdown({
Expand All @@ -124,6 +126,7 @@ export function IssueEventNavigation({event, group}: IssueEventNavigationProps)
autofixData,
activeThreadId,
organization,
autofixFormatted,
});

trackAnalytics('issue_details.copy_issue_details_as_markdown', {
Expand All @@ -134,7 +137,7 @@ export function IssueEventNavigation({event, group}: IssueEventNavigationProps)
});

return markdownText;
}, [activeThreadId, event, group, autofixData, organization]);
}, [activeThreadId, event, group, autofixData, organization, autofixFormatted]);

return (
<EventNavigationWrapper role="navigation" ref={navigationRef}>
Expand Down
25 changes: 23 additions & 2 deletions static/app/views/issueDetails/hooks/useCopyIssueDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ interface IssueAndEventToMarkdownOptions {
organization: Organization;
activeThreadId?: number;
autofixData?: ExplorerAutofixState | null;
autofixFormatted?: string | null;
event?: Event | null;
}

Expand All @@ -265,7 +266,24 @@ export const issueAndEventToMarkdown = ({
autofixData,
activeThreadId,
organization,
autofixFormatted,
}: IssueAndEventToMarkdownOptions): string => {
const formatted = event?.formatted?.content;
if (formatted) {
let llmMarkdown = `**Issue ID:** ${group.id}\n`;
if (group.project?.slug) {
llmMarkdown += `**Project:** ${group.project.slug}\n`;
}
if (typeof event?.dateCreated === 'string') {
llmMarkdown += `**Date:** ${new Date(event.dateCreated).toLocaleString()}\n`;
}
llmMarkdown += `\n${formatted}`;
if (autofixFormatted) {
llmMarkdown += `\n\n${autofixFormatted}`;
}
return llmMarkdown;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Server path drops autofix content

Medium Severity

When event.formatted is present, issueAndEventToMarkdown returns early and only appends autofixFormatted, ignoring autofixData. If server-formatted autofix is missing while cached autofix state still has root cause or solution content, that Seer analysis is omitted from the copied markdown.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7a5ecc6. Configure here.


// Format the basic issue information
let markdownText = `# ${group.title}\n\n`;
markdownText += `**Issue ID:** ${group.id}\n`;
Expand Down Expand Up @@ -323,7 +341,9 @@ export const issueAndEventToMarkdown = ({
export const useCopyIssueDetails = (group: Group, event?: Event) => {
const organization = useOrganization();

const {runState: autofixData} = useExplorerAutofix(group.id, {enabled: false});
const {runState: autofixData, autofixFormatted} = useExplorerAutofix(group.id, {
enabled: false,
});
const activeThreadId = useActiveThreadId();

const text = useMemo(() => {
Expand All @@ -333,8 +353,9 @@ export const useCopyIssueDetails = (group: Group, event?: Event) => {
autofixData,
activeThreadId,
organization,
autofixFormatted,
});
}, [group, event, autofixData, activeThreadId, organization]);
}, [group, event, autofixData, activeThreadId, organization, autofixFormatted]);

const {copy} = useCopyToClipboard();

Expand Down
1 change: 1 addition & 0 deletions static/app/views/issueDetails/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ function getGroupEventDetailsQueryData({
}): Record<string, string | string[]> {
const params: Record<string, string | string[]> = {
collapse: ['fullRelease'],
llmFormat: 'markdown',
};

if (query) {
Expand Down
Loading