import { Button, Container, Row, Separator, StringSelectMenu, TextDisplay, type ComponentData, type MessagePayloadObject, type TopLevelComponents, } from "@buape/carbon"; import type { APISelectMenuOption } from "discord-api-types/v10"; import { ButtonStyle } from "discord-api-types/v10"; import { normalizeProviderId } from "../../agents/model-selection.js"; import { buildModelsProviderData, type ModelsProviderData, } from "../../auto-reply/reply/commands-models.js"; import type { OpenClawConfig } from "../../config/config.js"; export const DISCORD_MODEL_PICKER_CUSTOM_ID_KEY = "mdlpk"; export const DISCORD_CUSTOM_ID_MAX_CHARS = 100; // Discord component limits. export const DISCORD_COMPONENT_MAX_ROWS = 5; export const DISCORD_COMPONENT_MAX_BUTTONS_PER_ROW = 5; export const DISCORD_COMPONENT_MAX_SELECT_OPTIONS = 25; // Reserve one row for navigation/utility buttons when rendering providers. export const DISCORD_MODEL_PICKER_PROVIDER_PAGE_SIZE = DISCORD_COMPONENT_MAX_BUTTONS_PER_ROW * (DISCORD_COMPONENT_MAX_ROWS - 1); // When providers fit in one page, we can use all button rows and hide nav controls. export const DISCORD_MODEL_PICKER_PROVIDER_SINGLE_PAGE_MAX = DISCORD_COMPONENT_MAX_BUTTONS_PER_ROW * DISCORD_COMPONENT_MAX_ROWS; export const DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE = DISCORD_COMPONENT_MAX_SELECT_OPTIONS; const DISCORD_PROVIDER_BUTTON_LABEL_MAX_CHARS = 18; const COMMAND_CONTEXTS = ["model", "models"] as const; const PICKER_ACTIONS = [ "open", "provider", "model", "submit", "quick", "back", "reset", "cancel", "recents", ] as const; const PICKER_VIEWS = ["providers", "models", "recents"] as const; export type DiscordModelPickerCommandContext = (typeof COMMAND_CONTEXTS)[number]; export type DiscordModelPickerAction = (typeof PICKER_ACTIONS)[number]; export type DiscordModelPickerView = (typeof PICKER_VIEWS)[number]; export type DiscordModelPickerState = { command: DiscordModelPickerCommandContext; action: DiscordModelPickerAction; view: DiscordModelPickerView; userId: string; provider?: string; page: number; providerPage?: number; modelIndex?: number; recentSlot?: number; }; export type DiscordModelPickerProviderItem = { id: string; count: number; }; export type DiscordModelPickerPage = { items: T[]; page: number; pageSize: number; totalPages: number; totalItems: number; hasPrev: boolean; hasNext: boolean; }; export type DiscordModelPickerModelPage = DiscordModelPickerPage & { provider: string; }; export type DiscordModelPickerLayout = "v2" | "classic"; type DiscordModelPickerButtonOptions = { label: string; customId: string; style?: ButtonStyle; disabled?: boolean; }; type DiscordModelPickerCurrentModelRef = { provider: string; model: string; }; type DiscordModelPickerRow = Row