@@ -2,13 +2,20 @@ import {Fragment, useEffect, useEffectEvent, useLayoutEffect, useState} from 're
22import styled from '@emotion/styled' ;
33import * as Sentry from '@sentry/react' ;
44
5+ import { Alert } from '@sentry/scraps/alert' ;
6+ import { Container } from '@sentry/scraps/layout' ;
7+ import { ExternalLink } from '@sentry/scraps/link' ;
8+
59import { Button } from 'sentry/components/core/button' ;
6- import { t } from 'sentry/locale' ;
10+ import { t , tct , tn } from 'sentry/locale' ;
711import { space } from 'sentry/styles/space' ;
812import type { EventTransaction } from 'sentry/types/event' ;
913import { defined } from 'sentry/utils' ;
1014import usePrevious from 'sentry/utils/usePrevious' ;
11- import type { TraceItemResponseAttribute } from 'sentry/views/explore/hooks/useTraceItemDetails' ;
15+ import type {
16+ TraceItemDetailsMeta ,
17+ TraceItemResponseAttribute ,
18+ } from 'sentry/views/explore/hooks/useTraceItemDetails' ;
1219import {
1320 getIsAiNode ,
1421 getTraceNodeAttribute ,
@@ -170,13 +177,17 @@ function useInvalidRoleDetection(roles: string[]) {
170177export function AIInputSection ( {
171178 node,
172179 attributes,
180+ attributesMeta,
173181 event,
174182} : {
175183 node : TraceTreeNode < TraceTree . EAPSpan | TraceTree . Span | TraceTree . Transaction > ;
176184 attributes ?: TraceItemResponseAttribute [ ] ;
185+ attributesMeta ?: TraceItemDetailsMeta ;
177186 event ?: EventTransaction ;
178187} ) {
179188 const shouldRender = getIsAiNode ( node ) && hasAIInputAttribute ( node , attributes , event ) ;
189+ const messagesMeta = attributesMeta ?. [ 'gen_ai.request.messages' ] ?. meta as any ;
190+ const originalMessagesLength : number | undefined = messagesMeta ?. [ '' ] ?. len ;
180191
181192 let promptMessages = shouldRender
182193 ? getTraceNodeAttribute ( 'gen_ai.request.messages' , node , event , attributes )
@@ -227,7 +238,12 @@ export function AIInputSection({
227238 { messages }
228239 </ TraceDrawerComponents . MultilineText >
229240 ) : null }
230- { Array . isArray ( messages ) ? < MessagesArrayRenderer messages = { messages } /> : null }
241+ { Array . isArray ( messages ) ? (
242+ < MessagesArrayRenderer
243+ messages = { messages }
244+ originalLength = { originalMessagesLength }
245+ />
246+ ) : null }
231247 { toolArgs ? (
232248 < TraceDrawerComponents . MultilineJSON value = { toolArgs } maxDefaultDepth = { 1 } />
233249 ) : null }
@@ -248,8 +264,16 @@ const MAX_MESSAGES_TO_SHOW = MAX_MESSAGES_AT_START + MAX_MESSAGES_AT_END;
248264 * As the whole message history takes up too much space we only show the first two (as those often contain the system and initial user prompt)
249265 * and the last messages with the option to expand
250266 */
251- function MessagesArrayRenderer ( { messages} : { messages : AIMessage [ ] } ) {
267+ function MessagesArrayRenderer ( {
268+ messages,
269+ originalLength,
270+ } : {
271+ messages : AIMessage [ ] ;
272+ originalLength ?: number ;
273+ } ) {
252274 const [ isExpanded , setIsExpanded ] = useState ( messages . length <= MAX_MESSAGES_TO_SHOW ) ;
275+ const truncatedMessages = originalLength ? originalLength - messages . length : 0 ;
276+ const isTruncated = truncatedMessages > 0 ;
253277
254278 // Reset the expanded state when the messages length changes
255279 const previousMessagesLength = usePrevious ( messages . length ) ;
@@ -259,6 +283,22 @@ function MessagesArrayRenderer({messages}: {messages: AIMessage[]}) {
259283 }
260284 } , [ messages . length , previousMessagesLength ] ) ;
261285
286+ const truncationAlert = isTruncated ? (
287+ < Container paddingBottom = "lg" >
288+ < Alert type = "muted" >
289+ { tct (
290+ 'Due to [link:size limitations], the oldest [count] got dropped from the history.' ,
291+ {
292+ count : tn ( 'message' , '%s messages' , truncatedMessages ) ,
293+ link : (
294+ < ExternalLink href = "https://develop.sentry.dev/sdk/expected-features/data-handling/#variable-size" />
295+ ) ,
296+ }
297+ ) }
298+ </ Alert >
299+ </ Container >
300+ ) : null ;
301+
262302 const renderMessage = ( message : AIMessage , index : number ) => {
263303 return (
264304 < Fragment key = { index } >
@@ -278,11 +318,17 @@ function MessagesArrayRenderer({messages}: {messages: AIMessage[]}) {
278318 } ;
279319
280320 if ( isExpanded ) {
281- return messages . map ( renderMessage ) ;
321+ return (
322+ < Fragment >
323+ { truncationAlert }
324+ { messages . map ( renderMessage ) }
325+ </ Fragment >
326+ ) ;
282327 }
283328
284329 return (
285330 < Fragment >
331+ { truncationAlert }
286332 { messages . slice ( 0 , MAX_MESSAGES_AT_START ) . map ( renderMessage ) }
287333 < ButtonDivider >
288334 < Button onClick = { ( ) => setIsExpanded ( true ) } size = "xs" >
0 commit comments