From fe51a2adbff2eccfb483858fc6931f6698962416 Mon Sep 17 00:00:00 2001 From: Arthur Knaus Date: Fri, 7 Nov 2025 09:01:27 +0100 Subject: [PATCH 1/3] feat(agents): Show truncated messages info --- .../details/span/eapSections/aiInput.tsx | 19 ++++++++++++++++++- .../traceDrawer/details/span/index.tsx | 7 ++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx b/static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx index 85f00a48234430..132665e21cdbf7 100644 --- a/static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx +++ b/static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx @@ -2,13 +2,19 @@ import {Fragment, useEffect, useEffectEvent, useLayoutEffect, useState} from 're import styled from '@emotion/styled'; import * as Sentry from '@sentry/react'; +import {Alert} from '@sentry/scraps/alert'; +import {Container} from '@sentry/scraps/layout'; + import {Button} from 'sentry/components/core/button'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {EventTransaction} from 'sentry/types/event'; import {defined} from 'sentry/utils'; import usePrevious from 'sentry/utils/usePrevious'; -import type {TraceItemResponseAttribute} from 'sentry/views/explore/hooks/useTraceItemDetails'; +import type { + TraceItemDetailsMeta, + TraceItemResponseAttribute, +} from 'sentry/views/explore/hooks/useTraceItemDetails'; import { getIsAiNode, getTraceNodeAttribute, @@ -170,13 +176,17 @@ function useInvalidRoleDetection(roles: string[]) { export function AIInputSection({ node, attributes, + attributesMeta, event, }: { node: TraceTreeNode; attributes?: TraceItemResponseAttribute[]; + attributesMeta?: TraceItemDetailsMeta; event?: EventTransaction; }) { const shouldRender = getIsAiNode(node) && hasAIInputAttribute(node, attributes, event); + const messagesMeta = attributesMeta?.['gen_ai.request.messages']?.meta as any; + const isTruncated = messagesMeta?.['']?.len > 0; let promptMessages = shouldRender ? getTraceNodeAttribute('gen_ai.request.messages', node, event, attributes) @@ -221,6 +231,13 @@ export function AIInputSection({ title={t('Input')} disableCollapsePersistence > + {isTruncated ? ( + + + {t('Due to size limitations, the message history on this span is truncated.')} + + + ) : null} {/* If parsing fails, we'll just show the raw string */} {typeof messages === 'string' ? ( diff --git a/static/app/views/performance/newTraceDetails/traceDrawer/details/span/index.tsx b/static/app/views/performance/newTraceDetails/traceDrawer/details/span/index.tsx index 910456db51f7b3..e03f4d65b6371a 100644 --- a/static/app/views/performance/newTraceDetails/traceDrawer/details/span/index.tsx +++ b/static/app/views/performance/newTraceDetails/traceDrawer/details/span/index.tsx @@ -427,6 +427,7 @@ function EAPSpanNodeDetailsContent({ traceItemData: TraceItemDetailsResponse; }) { const attributes = traceItemData.attributes; + const attributesMeta = traceItemData.meta; const links = traceItemData.links; const isTransaction = isEAPTransactionNode(node) && !!eventTransaction; @@ -487,7 +488,11 @@ function EAPSpanNodeDetailsContent({ hideNodeActions={hideNodeActions} /> - + From 5258d6a41565eead77ceaee111a595e72c154860 Mon Sep 17 00:00:00 2001 From: Arthur Knaus Date: Fri, 7 Nov 2025 09:28:58 +0100 Subject: [PATCH 2/3] add link and message count --- .../details/span/eapSections/aiInput.tsx | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx b/static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx index 132665e21cdbf7..64c7e5b3b49caf 100644 --- a/static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx +++ b/static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx @@ -4,9 +4,10 @@ import * as Sentry from '@sentry/react'; import {Alert} from '@sentry/scraps/alert'; import {Container} from '@sentry/scraps/layout'; +import {ExternalLink} from '@sentry/scraps/link'; import {Button} from 'sentry/components/core/button'; -import {t} from 'sentry/locale'; +import {t, tct, tn} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {EventTransaction} from 'sentry/types/event'; import {defined} from 'sentry/utils'; @@ -186,7 +187,7 @@ export function AIInputSection({ }) { const shouldRender = getIsAiNode(node) && hasAIInputAttribute(node, attributes, event); const messagesMeta = attributesMeta?.['gen_ai.request.messages']?.meta as any; - const isTruncated = messagesMeta?.['']?.len > 0; + const originalMessagesLength: number | undefined = messagesMeta?.['']?.len; let promptMessages = shouldRender ? getTraceNodeAttribute('gen_ai.request.messages', node, event, attributes) @@ -231,20 +232,18 @@ export function AIInputSection({ title={t('Input')} disableCollapsePersistence > - {isTruncated ? ( - - - {t('Due to size limitations, the message history on this span is truncated.')} - - - ) : null} {/* If parsing fails, we'll just show the raw string */} {typeof messages === 'string' ? ( {messages} ) : null} - {Array.isArray(messages) ? : null} + {Array.isArray(messages) ? ( + + ) : null} {toolArgs ? ( ) : null} @@ -265,8 +264,16 @@ const MAX_MESSAGES_TO_SHOW = MAX_MESSAGES_AT_START + MAX_MESSAGES_AT_END; * 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) * and the last messages with the option to expand */ -function MessagesArrayRenderer({messages}: {messages: AIMessage[]}) { +function MessagesArrayRenderer({ + messages, + originalLength, +}: { + messages: AIMessage[]; + originalLength?: number; +}) { const [isExpanded, setIsExpanded] = useState(messages.length <= MAX_MESSAGES_TO_SHOW); + const truncatedMessages = originalLength ? originalLength - messages.length : 0; + const isTruncated = truncatedMessages > 0; // Reset the expanded state when the messages length changes const previousMessagesLength = usePrevious(messages.length); @@ -300,6 +307,21 @@ function MessagesArrayRenderer({messages}: {messages: AIMessage[]}) { return ( + {isTruncated ? ( + + + {tct( + 'Due to [link:size limitations], the oldest [count] got dropped from the history.', + { + count: tn('message', '%s messages', truncatedMessages), + link: ( + + ), + } + )} + + + ) : null} {messages.slice(0, MAX_MESSAGES_AT_START).map(renderMessage)}