@@ -1422,6 +1422,7 @@ <h3>Cost Breakdown</h3>
14221422 let expandedThinking = new Set ( ) ;
14231423 let expandedToolInputs = new Set ( ) ;
14241424 let expandedOutputs = new Set ( ) ;
1425+ let turnsSearchQuery = '' ;
14251426
14261427 function fmtTime ( iso ) {
14271428 if ( ! iso ) return '' ;
@@ -1451,15 +1452,43 @@ <h3>Cost Breakdown</h3>
14511452 const d = selectedDetail ;
14521453 if ( ! d ) return ;
14531454
1454- const turns = d . turns || [ ] ;
1455- if ( turns . length === 0 ) {
1455+ const allTurns = d . turns || [ ] ;
1456+ if ( allTurns . length === 0 ) {
14561457 document . getElementById ( 'tab-turns' ) . innerHTML =
14571458 '<div style="padding:20px;text-align:center;color:var(--text-muted)">No turns in this session.</div>' ;
14581459 return ;
14591460 }
14601461
1461- let html = '<div class="turn-list">' ;
1462- turns . forEach ( ( t , idx ) => {
1462+ // Filter by search query
1463+ const query = turnsSearchQuery . toLowerCase ( ) ;
1464+ const turns = query
1465+ ? allTurns . filter ( t => {
1466+ // Search in text content, tool names, tool inputs, and results
1467+ for ( const c of ( t . content || [ ] ) ) {
1468+ if ( c . text && c . text . toLowerCase ( ) . includes ( query ) ) return true ;
1469+ if ( c . toolName && c . toolName . toLowerCase ( ) . includes ( query ) ) return true ;
1470+ if ( c . toolInput && JSON . stringify ( c . toolInput ) . toLowerCase ( ) . includes ( query ) ) return true ;
1471+ if ( c . toolResult ) {
1472+ if ( c . toolResult . stdout && c . toolResult . stdout . toLowerCase ( ) . includes ( query ) ) return true ;
1473+ if ( c . toolResult . stderr && c . toolResult . stderr . toLowerCase ( ) . includes ( query ) ) return true ;
1474+ }
1475+ }
1476+ if ( t . toolCalls && t . toolCalls . some ( tc => tc . toLowerCase ( ) . includes ( query ) ) ) return true ;
1477+ return false ;
1478+ } )
1479+ : allTurns ;
1480+
1481+ // Reverse: newest first
1482+ const reversed = [ ...turns ] . reverse ( ) ;
1483+
1484+ let html = '' ;
1485+ html += `<div class="turns-search" style="padding:8px 12px;border-bottom:1px solid var(--border-color);">` ;
1486+ html += `<input type="text" id="turns-search-input" placeholder="Search turns..." value="${ escHtml ( turnsSearchQuery ) } " style="width:100%;padding:6px 10px;border:1px solid var(--border-color);border-radius:6px;background:var(--bg-secondary);color:var(--text-primary);font-size:13px;">` ;
1487+ if ( query ) html += `<div style="font-size:11px;color:var(--text-muted);margin-top:4px;">${ turns . length } of ${ allTurns . length } turns match</div>` ;
1488+ html += `</div>` ;
1489+
1490+ html += '<div class="turn-list">' ;
1491+ reversed . forEach ( ( t , idx ) => {
14631492 const isExpanded = expandedTurns . has ( t . number ) ;
14641493 const roleClass = t . role === 'user' ? 'role-user' : 'role-assistant' ;
14651494 const durClass = durationClass ( t . durationMs ) ;
@@ -1634,6 +1663,18 @@ <h3>Cost Breakdown</h3>
16341663 renderTurns ( ) ;
16351664 } ) ;
16361665 } ) ;
1666+
1667+ // Search input
1668+ const searchInput = document . getElementById ( 'turns-search-input' ) ;
1669+ if ( searchInput ) {
1670+ searchInput . addEventListener ( 'input' , ( e ) => {
1671+ turnsSearchQuery = e . target . value ;
1672+ renderTurns ( ) ;
1673+ // Re-focus and restore cursor position
1674+ const el = document . getElementById ( 'turns-search-input' ) ;
1675+ if ( el ) { el . focus ( ) ; el . selectionStart = el . selectionEnd = el . value . length ; }
1676+ } ) ;
1677+ }
16371678 }
16381679
16391680 // ---- Tools Tab ----
0 commit comments