@@ -5,6 +5,7 @@ import { Header3 } from "~/components/primitives/Headers";
55import { Paragraph } from "~/components/primitives/Paragraph" ;
66import { TabButton , TabContainer } from "~/components/primitives/Tabs" ;
77import { useHasAdminAccess } from "~/hooks/useUser" ;
8+ import { CodeBlock } from "~/components/code/CodeBlock" ;
89import { AIChatMessages , AssistantResponse , ChatBubble } from "./AIChatMessages" ;
910import { AIStatsSummary , AITagsRow } from "./AIModelSummary" ;
1011import { AIToolsInventory } from "./AIToolsInventory" ;
@@ -76,15 +77,13 @@ export function AISpanDetails({
7677}
7778
7879function OverviewTab ( { aiData } : { aiData : AISpanData } ) {
79- const { userText, outputText, outputToolNames } = extractInputOutput ( aiData ) ;
80+ const { userText, outputText, outputObject , outputToolNames } = extractInputOutput ( aiData ) ;
8081
8182 return (
8283 < div className = "flex flex-col px-3" >
83- { /* Tags + Stats */ }
8484 < AITagsRow aiData = { aiData } />
8585 < AIStatsSummary aiData = { aiData } />
8686
87- { /* Input (last user prompt) */ }
8887 { userText && (
8988 < div className = "flex flex-col gap-1.5 py-2.5" >
9089 < Header3 > Input</ Header3 >
@@ -94,9 +93,20 @@ function OverviewTab({ aiData }: { aiData: AISpanData }) {
9493 </ div >
9594 ) }
9695
97- { /* Output (assistant response or tool calls) */ }
9896 { outputText && < AssistantResponse text = { outputText } headerLabel = "Output" /> }
99- { outputToolNames . length > 0 && ! outputText && (
97+ { ! outputText && outputObject && (
98+ < div className = "flex flex-col gap-1.5 py-2.5" >
99+ < Header3 > Output</ Header3 >
100+ < CodeBlock
101+ code = { outputObject }
102+ maxLines = { 20 }
103+ showLineNumbers = { false }
104+ showCopyButton
105+ language = "json"
106+ />
107+ </ div >
108+ ) }
109+ { outputToolNames . length > 0 && ! outputText && ! outputObject && (
100110 < div className = "flex flex-col gap-1.5 py-2.5" >
101111 < Header3 > Output</ Header3 >
102112 < ChatBubble >
@@ -112,12 +122,26 @@ function OverviewTab({ aiData }: { aiData: AISpanData }) {
112122}
113123
114124function MessagesTab ( { aiData } : { aiData : AISpanData } ) {
125+ const showFallbackText = aiData . responseText && ! hasAssistantItem ( aiData . items ) ;
126+ const showFallbackObject =
127+ ! showFallbackText && aiData . responseObject && ! hasAssistantItem ( aiData . items ) ;
128+
115129 return (
116130 < div className = "px-3" >
117131 < div className = "flex flex-col" >
118132 { aiData . items && aiData . items . length > 0 && < AIChatMessages items = { aiData . items } /> }
119- { aiData . responseText && ! hasAssistantItem ( aiData . items ) && (
120- < AssistantResponse text = { aiData . responseText } />
133+ { showFallbackText && < AssistantResponse text = { aiData . responseText ! } /> }
134+ { showFallbackObject && (
135+ < div className = "flex flex-col gap-1.5 py-2.5" >
136+ < Header3 > Assistant</ Header3 >
137+ < CodeBlock
138+ code = { aiData . responseObject ! }
139+ maxLines = { 20 }
140+ showLineNumbers = { false }
141+ showCopyButton
142+ language = "json"
143+ />
144+ </ div >
121145 ) }
122146 </ div >
123147 </ div >
@@ -158,22 +182,21 @@ function CopyRawFooter({ rawProperties }: { rawProperties: string }) {
158182function extractInputOutput ( aiData : AISpanData ) : {
159183 userText : string | undefined ;
160184 outputText : string | undefined ;
185+ outputObject : string | undefined ;
161186 outputToolNames : string [ ] ;
162187} {
163188 let userText : string | undefined ;
164189 let outputText : string | undefined ;
165190 const outputToolNames : string [ ] = [ ] ;
166191
167192 if ( aiData . items ) {
168- // Find the last user message
169193 for ( let i = aiData . items . length - 1 ; i >= 0 ; i -- ) {
170194 if ( aiData . items [ i ] . type === "user" ) {
171195 userText = ( aiData . items [ i ] as { type : "user" ; text : string } ) . text ;
172196 break ;
173197 }
174198 }
175199
176- // Find the last assistant or tool-use item as the output
177200 for ( let i = aiData . items . length - 1 ; i >= 0 ; i -- ) {
178201 const item = aiData . items [ i ] ;
179202 if ( item . type === "assistant" ) {
@@ -189,12 +212,11 @@ function extractInputOutput(aiData: AISpanData): {
189212 }
190213 }
191214
192- // Fall back to responseText if no assistant item found
193215 if ( ! outputText && aiData . responseText ) {
194216 outputText = aiData . responseText ;
195217 }
196218
197- return { userText, outputText, outputToolNames } ;
219+ return { userText, outputText, outputObject : aiData . responseObject , outputToolNames } ;
198220}
199221
200222function hasAssistantItem ( items : DisplayItem [ ] | undefined ) : boolean {
0 commit comments