@@ -29,6 +29,7 @@ import {
2929} from "./model-picker.state.js" ;
3030
3131const DISCORD_PROVIDER_BUTTON_LABEL_MAX_CHARS = 18 ;
32+ const DISCORD_MODEL_PICKER_PAGE_INDICATOR_CUSTOM_ID = "mdlpk:nav-indicator" ;
3233
3334type DiscordModelPickerButtonOptions = {
3435 label : string ;
@@ -292,6 +293,63 @@ function buildProviderRows(params: {
292293 return rows ;
293294}
294295
296+ function buildPaginationRow ( params : {
297+ command : DiscordModelPickerCommandContext ;
298+ userId : string ;
299+ view : "providers" | "models" ;
300+ page : number ;
301+ totalPages : number ;
302+ hasPrev : boolean ;
303+ hasNext : boolean ;
304+ provider ?: string ;
305+ runtime ?: string ;
306+ providerPage ?: number ;
307+ modelIndex ?: number ;
308+ } ) : Row < Button > | null {
309+ if ( params . totalPages <= 1 ) {
310+ return null ;
311+ }
312+ const prevButton = createModelPickerButton ( {
313+ label : "◀ Prev" ,
314+ style : ButtonStyle . Secondary ,
315+ disabled : ! params . hasPrev ,
316+ customId : buildDiscordModelPickerCustomId ( {
317+ command : params . command ,
318+ action : "nav" ,
319+ view : params . view ,
320+ provider : params . provider ,
321+ runtime : params . runtime ,
322+ page : Math . max ( 1 , params . page - 1 ) ,
323+ providerPage : params . providerPage ,
324+ modelIndex : params . modelIndex ,
325+ userId : params . userId ,
326+ } ) ,
327+ } ) ;
328+ const indicatorButton = createModelPickerButton ( {
329+ label : `Page ${ params . page } /${ params . totalPages } ` ,
330+ style : ButtonStyle . Secondary ,
331+ disabled : true ,
332+ customId : DISCORD_MODEL_PICKER_PAGE_INDICATOR_CUSTOM_ID ,
333+ } ) ;
334+ const nextButton = createModelPickerButton ( {
335+ label : "Next ▶" ,
336+ style : ButtonStyle . Secondary ,
337+ disabled : ! params . hasNext ,
338+ customId : buildDiscordModelPickerCustomId ( {
339+ command : params . command ,
340+ action : "nav" ,
341+ view : params . view ,
342+ provider : params . provider ,
343+ runtime : params . runtime ,
344+ page : Math . min ( params . totalPages , params . page + 1 ) ,
345+ providerPage : params . providerPage ,
346+ modelIndex : params . modelIndex ,
347+ userId : params . userId ,
348+ } ) ,
349+ } ) ;
350+ return new Row ( [ prevButton , indicatorButton , nextButton ] ) ;
351+ }
352+
295353function buildModelRows ( params : {
296354 command : DiscordModelPickerCommandContext ;
297355 userId : string ;
@@ -415,6 +473,23 @@ function buildModelRows(params: {
415473 ] ) ,
416474 ) ;
417475
476+ const modelNavRow = buildPaginationRow ( {
477+ command : params . command ,
478+ userId : params . userId ,
479+ view : "models" ,
480+ page : params . modelPage . page ,
481+ totalPages : params . modelPage . totalPages ,
482+ hasPrev : params . modelPage . hasPrev ,
483+ hasNext : params . modelPage . hasNext ,
484+ provider : params . modelPage . provider ,
485+ runtime : stateRuntime ,
486+ providerPage : providerPage . page ,
487+ modelIndex : params . pendingModelIndex ,
488+ } ) ;
489+ if ( modelNavRow ) {
490+ rows . push ( modelNavRow ) ;
491+ }
492+
418493 const resolvedDefault = params . data . resolvedDefault ;
419494 const shouldDisableReset =
420495 Boolean ( parsedCurrentModel ) &&
@@ -505,23 +580,40 @@ export function renderDiscordModelPickerProvidersView(
505580) : DiscordModelPickerRenderedView {
506581 const page = getDiscordModelPickerProviderPage ( { data : params . data , page : params . page } ) ;
507582 const parsedCurrent = parseCurrentModelRef ( params . currentModel ) ;
508- const rows = buildProviderRows ( {
583+ const rows : DiscordModelPickerRow [ ] = buildProviderRows ( {
509584 command : params . command ,
510585 userId : params . userId ,
511586 page,
512587 currentProvider : parsedCurrent ?. provider ,
513588 } ) ;
514589
590+ const navRow = buildPaginationRow ( {
591+ command : params . command ,
592+ userId : params . userId ,
593+ view : "providers" ,
594+ page : page . page ,
595+ totalPages : page . totalPages ,
596+ hasPrev : page . hasPrev ,
597+ hasNext : page . hasNext ,
598+ } ) ;
599+ if ( navRow ) {
600+ rows . push ( navRow ) ;
601+ }
602+
515603 const detailLines = [
516604 formatCurrentModelLine ( params . currentModel ) ,
517605 `Select a provider (${ page . totalItems } available).` ,
518606 ] ;
607+ const footer =
608+ page . totalPages > 1
609+ ? `Showing page ${ page . page } /${ page . totalPages } · ${ page . totalItems } providers total`
610+ : `All ${ page . totalItems } providers shown` ;
519611 return buildRenderedShell ( {
520612 layout : params . layout ?? "v2" ,
521613 title : "Model Picker" ,
522614 detailLines,
523615 rows,
524- footer : `All ${ page . totalItems } providers shown` ,
616+ footer,
525617 } ) ;
526618}
527619
@@ -587,10 +679,17 @@ export function renderDiscordModelPickerModelsView(
587679 } ) } (press Submit)`
588680 : "Select a model, then press Submit." ;
589681
682+ const detailLines = [ formatCurrentModelLine ( params . currentModel ) , `Default: ${ defaultModel } ` ] ;
683+ if ( modelPage . totalPages > 1 ) {
684+ detailLines . push (
685+ `${ modelPage . provider } : page ${ modelPage . page } /${ modelPage . totalPages } · ${ modelPage . totalItems } models` ,
686+ ) ;
687+ }
688+
590689 return buildRenderedShell ( {
591690 layout : params . layout ?? "v2" ,
592691 title : "Model Picker" ,
593- detailLines : [ formatCurrentModelLine ( params . currentModel ) , `Default: ${ defaultModel } ` ] ,
692+ detailLines,
594693 preRowText : pendingLine ,
595694 rows,
596695 trailingRows : [ buttonRow ] ,
0 commit comments