@@ -118,6 +118,25 @@ function Dashboard({
118118 const [ modelPicker , setModelPicker ] = useState ( false ) ;
119119 const [ modelOptions , setModelOptions ] = useState < SelectOption [ ] > ( [ ] ) ;
120120 const [ fetchingModels , setFetchingModels ] = useState ( false ) ;
121+ const [ query , setQuery ] = useState ( "" ) ;
122+ const [ cursorOn , setCursorOn ] = useState ( true ) ;
123+
124+ useEffect ( ( ) => {
125+ if ( ! modelPicker ) return ;
126+ const id = setInterval ( ( ) => setCursorOn ( ( v ) => ! v ) , 500 ) ;
127+ return ( ) => clearInterval ( id ) ;
128+ } , [ modelPicker ] ) ;
129+
130+ const q = query . toLowerCase ( ) ;
131+ const visibleOptions = q
132+ ? modelOptions . filter (
133+ ( o ) =>
134+ o . value !== SEPARATOR_VALUE &&
135+ ( o . name . toLowerCase ( ) . includes ( q ) ||
136+ ( typeof o . description === "string" &&
137+ o . description . toLowerCase ( ) . includes ( q ) ) ) ,
138+ )
139+ : modelOptions ;
121140
122141 const refresh = useCallback (
123142 async ( nextIndex = selectedIndex ) => {
@@ -160,8 +179,24 @@ function Dashboard({
160179
161180 useKeyboard ( ( key ) => {
162181 if ( modelPicker ) {
163- if ( key . name === "escape" || key . name === "q" ) {
182+ if ( key . name === "escape" ) {
164183 setModelPicker ( false ) ;
184+ setQuery ( "" ) ;
185+ return ;
186+ }
187+ if ( key . name === "backspace" ) {
188+ setQuery ( ( prev ) => prev . slice ( 0 , - 1 ) ) ;
189+ return ;
190+ }
191+ if (
192+ ! key . ctrl &&
193+ ! key . meta &&
194+ typeof key . sequence === "string" &&
195+ key . sequence . length === 1 &&
196+ key . sequence >= " " &&
197+ key . sequence <= "~"
198+ ) {
199+ setQuery ( ( prev ) => prev + key . sequence ) ;
165200 }
166201 return ;
167202 }
@@ -177,6 +212,7 @@ function Dashboard({
177212 }
178213
179214 if ( key . name === "m" && ! fetchingModels ) {
215+ setQuery ( "" ) ;
180216 setFetchingModels ( true ) ;
181217 void fetchModelOptions ( )
182218 . then ( ( options ) => {
@@ -222,16 +258,36 @@ function Dashboard({
222258 if ( modelPicker ) {
223259 return (
224260 < box flexDirection = "column" flexGrow = { 1 } padding = { 1 } >
225- < box flexDirection = "column" marginBottom = { 1 } >
261+ < box
262+ flexDirection = "row"
263+ justifyContent = "space-between"
264+ marginBottom = { 1 }
265+ >
226266 < text attributes = { TextAttributes . BOLD } > Select Model</ text >
227- < text attributes = { TextAttributes . DIM } >
228- { `${ modelOptions . length } models available — esc: cancel` }
229- </ text >
267+ < text attributes = { TextAttributes . DIM } > esc</ text >
268+ </ box >
269+ < box
270+ border
271+ borderStyle = "single"
272+ borderColor = "#666"
273+ paddingLeft = { 1 }
274+ paddingRight = { 1 }
275+ marginBottom = { 1 }
276+ height = { 3 }
277+ >
278+ { query ? (
279+ < text > { `${ query } ${ cursorOn ? "\u2588" : " " } ` } </ text >
280+ ) : (
281+ < text attributes = { TextAttributes . DIM } >
282+ { `${ cursorOn ? "\u2588" : "S" } earch` }
283+ </ text >
284+ ) }
230285 </ box >
231286 < select
287+ key = { query }
232288 focused
233289 flexGrow = { 1 }
234- options = { modelOptions }
290+ options = { visibleOptions }
235291 showDescription
236292 showScrollIndicator
237293 wrapSelection
0 commit comments