@@ -12,13 +12,13 @@ interface Props {
1212 itemName ?: string | null ;
1313}
1414
15- function formatScore ( score : number | null ) : string {
16- if ( score === null ) return "-" ;
15+ function formatScore ( score : number | null | undefined ) : string {
16+ if ( score == null ) return "-" ;
1717 return `${ Math . round ( score * 100 ) } %` ;
1818}
1919
20- function scoreColor ( score : number | null ) : string {
21- if ( score === null ) return "var(--text-muted)" ;
20+ function scoreColor ( score : number | null | undefined ) : string {
21+ if ( score == null ) return "var(--text-muted)" ;
2222 const pct = score * 100 ;
2323 if ( pct >= 80 ) return "var(--success)" ;
2424 if ( pct >= 50 ) return "var(--warning)" ;
@@ -71,6 +71,7 @@ export default function EvalRunResults({ evalRunId, itemName }: Props) {
7171
7272 const storeRun = useEvalStore ( ( s ) => s . evalRuns [ evalRunId ] ) ;
7373 const evaluators = useEvalStore ( ( s ) => s . evaluators ) ;
74+ const streamingItems = useEvalStore ( ( s ) => s . streamingResults [ evalRunId ] ) ;
7475
7576 useEffect ( ( ) => {
7677 setLoading ( true ) ;
@@ -97,9 +98,12 @@ export default function EvalRunResults({ evalRunId, itemName }: Props) {
9798 // Auto-select first completed item as results come in (when no item is in route)
9899 useEffect ( ( ) => {
99100 if ( itemName || ! detail ?. results ) return ;
100- const first = detail . results . find ( ( r ) => r . status === "completed" ) ?? detail . results [ 0 ] ;
101+ const results = streamingItems
102+ ? detail . results . map ( ( r ) => streamingItems [ r . name ] ?? r )
103+ : detail . results ;
104+ const first = results . find ( ( r ) => r . status === "completed" ) ?? results [ 0 ] ;
101105 if ( first ) navigate ( `#/evals/runs/${ evalRunId } /${ encodeURIComponent ( first . name ) } ` ) ;
102- } , [ detail ?. results ] ) ;
106+ } , [ detail ?. results , streamingItems ] ) ;
103107
104108 // --- Row resize (item list height) ---
105109 const onRowResizeStart = useCallback ( ( e : React . MouseEvent | React . TouchEvent ) => {
@@ -191,8 +195,21 @@ export default function EvalRunResults({ evalRunId, itemName }: Props) {
191195 const run = storeRun ?? detail ;
192196 const status = statusStyles [ run . status ] ?? statusStyles . pending ;
193197 const isRunning = run . status === "running" ;
194- const evaluatorIds = Object . keys ( run . evaluator_scores ?? { } ) ;
195- const selectedItem = detail . results . find ( ( r ) => r . name === selectedItemName ) ?? null ;
198+ // Derive evaluator IDs from run scores (set on completion) or from first streamed item
199+ const evaluatorIds = Object . keys ( run . evaluator_scores ?? { } ) . length > 0
200+ ? Object . keys ( run . evaluator_scores )
201+ : Object . keys (
202+ streamingItems
203+ ? Object . values ( streamingItems ) . find ( ( r ) => Object . keys ( r . scores ) . length > 0 ) ?. scores ?? { }
204+ : { } ,
205+ ) ;
206+
207+ // Merge streaming item results over the fetched detail results
208+ const mergedResults = streamingItems
209+ ? detail . results . map ( ( r ) => streamingItems [ r . name ] ?? r )
210+ : detail . results ;
211+
212+ const selectedItem = mergedResults . find ( ( r ) => r . name === selectedItemName ) ?? null ;
196213 const selectedTraces = ( selectedItem ?. traces ?? [ ] ) . map ( ( t ) => ( { ...t , run_id : "" } ) ) ;
197214
198215 return (
@@ -279,7 +296,7 @@ export default function EvalRunResults({ evalRunId, itemName }: Props) {
279296 </ div >
280297 { /* Scrollable item rows */ }
281298 < div className = "flex-1 overflow-y-auto" >
282- { detail . results . map ( ( item : EvalItemResult ) => {
299+ { mergedResults . map ( ( item : EvalItemResult ) => {
283300 const isPending = item . status === "pending" ;
284301 const isFailed = item . status === "failed" ;
285302 const isSelected = item . name === selectedItemName ;
@@ -337,7 +354,7 @@ export default function EvalRunResults({ evalRunId, itemName }: Props) {
337354 </ button >
338355 ) ;
339356 } ) }
340- { detail . results . length === 0 && (
357+ { mergedResults . length === 0 && (
341358 < div className = "flex items-center justify-center py-8 text-[var(--text-muted)] text-xs" >
342359 { isRunning ? "Waiting for results..." : "No results" }
343360 </ div >
0 commit comments