1717
1818import { AsyncPipe , NgComponentOutlet , NgTemplateOutlet } from '@angular/common' ;
1919import { AfterViewInit , Component , DestroyRef , effect , EnvironmentInjector , inject , input , output , runInInjectionContext , signal , Type , viewChild , ViewContainerRef , type WritableSignal } from '@angular/core' ;
20+ import { toObservable } from '@angular/core/rxjs-interop' ;
2021import { FormControl , FormsModule , ReactiveFormsModule } from '@angular/forms' ;
2122import { MatMiniFabButton } from '@angular/material/button' ;
2223import { MatOption } from '@angular/material/core' ;
24+ import { MatFormField } from '@angular/material/form-field' ;
25+ import { MatInput } from '@angular/material/input' ;
2326import { MatIcon } from '@angular/material/icon' ;
2427import { MatPaginator , PageEvent } from '@angular/material/paginator' ;
2528import { MatProgressSpinner } from '@angular/material/progress-spinner' ;
@@ -29,7 +32,7 @@ import {MatTooltip} from '@angular/material/tooltip';
2932import { type SafeHtml } from '@angular/platform-browser' ;
3033import { NgxJsonViewerModule } from 'ngx-json-viewer' ;
3134import { combineLatest , Observable , of } from 'rxjs' ;
32- import { first , map } from 'rxjs/operators' ;
35+ import { first , map , startWith , switchMap } from 'rxjs/operators' ;
3336
3437import { EvalCase } from '../../core/models/Eval' ;
3538import { Session } from '../../core/models/Session' ;
@@ -77,6 +80,8 @@ import {SidePanelMessagesInjectionToken} from './side-panel.component.i18n';
7780 MatSelect ,
7881 ReactiveFormsModule ,
7982 MatProgressSpinner ,
83+ MatFormField ,
84+ MatInput ,
8085 ] ,
8186} )
8287export class SidePanelComponent implements AfterViewInit {
@@ -154,6 +159,27 @@ export class SidePanelComponent implements AfterViewInit {
154159 protected readonly isSessionsTabReorderingEnabledObs =
155160 this . featureFlagService . isSessionsTabReorderingEnabled ( ) ;
156161
162+ // Agent search
163+ readonly agentSearchControl = new FormControl ( '' , { nonNullable : true } ) ;
164+ readonly filteredApps$ : Observable < string [ ] | undefined > = toObservable ( this . apps$ ) . pipe (
165+ switchMap ( appsObservable =>
166+ combineLatest ( [
167+ appsObservable ,
168+ this . agentSearchControl . valueChanges . pipe ( startWith ( '' ) )
169+ ] )
170+ ) ,
171+ map ( ( [ apps , searchTerm ] ) => {
172+ if ( ! apps ) {
173+ return apps ;
174+ }
175+ if ( ! searchTerm || searchTerm . trim ( ) === '' ) {
176+ return apps ;
177+ }
178+ const lowerSearch = searchTerm . toLowerCase ( ) . trim ( ) ;
179+ return apps . filter ( app => app . toLowerCase ( ) . startsWith ( lowerSearch ) ) ;
180+ } )
181+ ) ;
182+
157183 ngAfterViewInit ( ) {
158184 // Wait one tick until the eval tab container is ready.
159185 setTimeout ( ( ) => {
0 commit comments