@@ -29,18 +29,23 @@ import type {
2929 TraceSpan ,
3030} from "../api-client/types" ;
3131import { logIssue } from "../telem/logging" ;
32+ import {
33+ type CodeLocation ,
34+ findMostRelevantInAppFrame ,
35+ formatCodeLocation ,
36+ } from "./code-location" ;
37+ import {
38+ type AIConversationReference ,
39+ formatAIConversationActionInstructions ,
40+ } from "./tool-helpers/ai-conversation-actions" ;
3241import {
3342 getAutofixArtifactSummaries ,
3443 getStatusDisplayName ,
3544 isTerminalStatus ,
3645} from "./tool-helpers/seer" ;
3746import { formatToolCallInstruction } from "./tool-helpers/tool-call-formatting" ;
38- import {
39- formatAIConversationActionInstructions ,
40- type AIConversationReference ,
41- } from "./tool-helpers/ai-conversation-actions" ;
42- import { formatUserGeoSummary } from "./user-formatting" ;
4347import { isPlainObject } from "./type-guards" ;
48+ import { formatUserGeoSummary } from "./user-formatting" ;
4449
4550/**
4651 * Convert Seer fixability score to actionability label.
@@ -416,12 +421,12 @@ function formatExceptionInterfaceOutput(
416421
417422 // Only show enhanced frame for the first (outermost) exception to avoid overwhelming output
418423 if ( index === 0 ) {
419- const firstInAppFrame = findFirstInAppFrame ( frames ) ;
424+ const relevantFrame = findMostRelevantInAppFrame ( frames ) ;
420425 if (
421- firstInAppFrame &&
422- ( firstInAppFrame . context ?. length || firstInAppFrame . vars )
426+ relevantFrame &&
427+ ( relevantFrame . context ?. length || relevantFrame . vars )
423428 ) {
424- parts . push ( renderEnhancedFrame ( firstInAppFrame , event ) ) ;
429+ parts . push ( renderEnhancedFrame ( relevantFrame , event ) ) ;
425430 parts . push ( "" ) ;
426431 parts . push ( "**Full Stacktrace:**" ) ;
427432 parts . push ( "────────────────" ) ;
@@ -590,13 +595,10 @@ function formatThreadsInterfaceOutput(
590595
591596 const frames = crashedThread . stacktrace . frames ;
592597
593- // Find and format the first in-app frame with enhanced view
594- const firstInAppFrame = findFirstInAppFrame ( frames ) ;
595- if (
596- firstInAppFrame &&
597- ( firstInAppFrame . context ?. length || firstInAppFrame . vars )
598- ) {
599- parts . push ( renderEnhancedFrame ( firstInAppFrame , event ) ) ;
598+ // Find and format the most relevant in-app frame with enhanced view
599+ const relevantFrame = findMostRelevantInAppFrame ( frames ) ;
600+ if ( relevantFrame && ( relevantFrame . context ?. length || relevantFrame . vars ) ) {
601+ parts . push ( renderEnhancedFrame ( relevantFrame , event ) ) ;
600602 parts . push ( "" ) ;
601603 parts . push ( "**Full Stacktrace:**" ) ;
602604 parts . push ( "────────────────" ) ;
@@ -725,12 +727,9 @@ export function formatThreadStacktraceOutput({
725727 parts . push ( "" ) ;
726728 }
727729
728- const firstInAppFrame = findFirstInAppFrame ( frames ) ;
729- if (
730- firstInAppFrame &&
731- ( firstInAppFrame . context ?. length || firstInAppFrame . vars )
732- ) {
733- parts . push ( renderEnhancedFrame ( firstInAppFrame , event ) ) ;
730+ const relevantFrame = findMostRelevantInAppFrame ( frames ) ;
731+ if ( relevantFrame && ( relevantFrame . context ?. length || relevantFrame . vars ) ) {
732+ parts . push ( renderEnhancedFrame ( relevantFrame , event ) ) ;
734733 parts . push ( "" ) ;
735734 parts . push ( "**Full Stacktrace:**" ) ;
736735 parts . push ( "────────────────" ) ;
@@ -886,27 +885,6 @@ function renderVariablesTable(vars: Record<string, unknown>): string {
886885 return lines . join ( "\n" ) ;
887886}
888887
889- /**
890- * Finds the first application frame (in_app) in a stack trace.
891- * Searches from the bottom of the stack (oldest frame) to find the first
892- * frame that belongs to the user's application code rather than libraries.
893- *
894- * @param frames - Array of stack frames, typically in reverse chronological order
895- * @returns The first in-app frame found, or undefined if none exist
896- */
897- function findFirstInAppFrame (
898- frames : z . infer < typeof FrameInterface > [ ] ,
899- ) : z . infer < typeof FrameInterface > | undefined {
900- // Frames are usually in reverse order (most recent first)
901- // We want the first in-app frame from the bottom
902- for ( let i = frames . length - 1 ; i >= 0 ; i -- ) {
903- if ( frames [ i ] . inApp === true ) {
904- return frames [ i ] ;
905- }
906- }
907- return undefined ;
908- }
909-
910888/**
911889 * Constants for performance issue formatting
912890 */
@@ -1979,6 +1957,7 @@ export function formatIssueOutput({
19791957 externalIssues,
19801958 relatedReplayIds,
19811959 aiConversations,
1960+ codeLocation,
19821961 experimentalMode,
19831962 availableToolNames,
19841963 directToolNames,
@@ -1992,6 +1971,7 @@ export function formatIssueOutput({
19921971 externalIssues ?: ExternalIssueList ;
19931972 relatedReplayIds ?: string [ ] ;
19941973 aiConversations ?: AIConversationReference [ ] ;
1974+ codeLocation ?: CodeLocation ;
19951975 experimentalMode ?: boolean ;
19961976 availableToolNames ?: ReadonlySet < string > ;
19971977 directToolNames ?: ReadonlySet < string > ;
@@ -2066,6 +2046,11 @@ export function formatIssueOutput({
20662046 output += `**Project**: ${ issue . project . name } \n` ;
20672047 output += `**URL**: ${ apiService . getIssueUrl ( organizationSlug , issue . shortId ) } \n` ;
20682048 output += "\n" ;
2049+
2050+ if ( codeLocation ) {
2051+ output += formatCodeLocation ( codeLocation ) ;
2052+ }
2053+
20692054 output += "## Event Details\n\n" ;
20702055
20712056 // Check if this is an unsupported event type
0 commit comments