























@@ -29,6 +29,7 @@ import {
2929} from "./model-picker.state.js";
30303131const DISCORD_PROVIDER_BUTTON_LABEL_MAX_CHARS = 18;
32+const DISCORD_MODEL_PICKER_PAGE_INDICATOR_CUSTOM_ID = "mdlpk:nav-indicator";
32333334type DiscordModelPickerButtonOptions = {
3435label: string;
@@ -292,6 +293,63 @@ function buildProviderRows(params: {
292293return rows;
293294}
294295296+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: {
296354command: DiscordModelPickerCommandContext;
297355userId: string;
@@ -415,6 +473,23 @@ function buildModelRows(params: {
415473]),
416474);
417475476+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+418493const resolvedDefault = params.data.resolvedDefault;
419494const shouldDisableReset =
420495Boolean(parsedCurrentModel) &&
@@ -505,23 +580,40 @@ export function renderDiscordModelPickerProvidersView(
505580): DiscordModelPickerRenderedView {
506581const page = getDiscordModelPickerProviderPage({ data: params.data, page: params.page });
507582const parsedCurrent = parseCurrentModelRef(params.currentModel);
508-const rows = buildProviderRows({
583+const rows: DiscordModelPickerRow[] = buildProviderRows({
509584command: params.command,
510585userId: params.userId,
511586 page,
512587currentProvider: parsedCurrent?.provider,
513588});
514589590+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+515603const detailLines = [
516604formatCurrentModelLine(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`;
519611return buildRenderedShell({
520612layout: params.layout ?? "v2",
521613title: "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.";
589681682+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+590689return buildRenderedShell({
591690layout: params.layout ?? "v2",
592691title: "Model Picker",
593-detailLines: [formatCurrentModelLine(params.currentModel), `Default: ${defaultModel}`],
692+ detailLines,
594693preRowText: pendingLine,
595694 rows,
596695trailingRows: [buttonRow],
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。