mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Chat Dropdown: reusable parts. #955
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import type { SxProps } from '@mui/joy/styles/types';
|
||||
import { IconButton } from '@mui/joy';
|
||||
|
||||
import { DebouncedInputMemo } from '~/common/components/DebouncedInput';
|
||||
import { StarredState } from '~/common/components/StarIcons';
|
||||
|
||||
|
||||
const _styles = {
|
||||
filterBox: {
|
||||
m: 1.5,
|
||||
mb: 1,
|
||||
backgroundColor: 'background.level1',
|
||||
'&:focus-within': { backgroundColor: 'background.popup' },
|
||||
},
|
||||
} as const satisfies Record<string, SxProps>;
|
||||
|
||||
|
||||
/**
|
||||
* Model Selection Dropdowns: Shared search input with starred filter toggle
|
||||
*/
|
||||
export const LLMSearchFilterInput = React.memo(function LLMSearchFilterInput(props: {
|
||||
size?: 'sm' | 'md' | 'lg',
|
||||
llmsCount: number,
|
||||
onSearch: (search: string | null) => void,
|
||||
onStarredToggle?: () => void, // if provided, shows the starred filter button
|
||||
showStarredOnly?: boolean,
|
||||
}) {
|
||||
return (
|
||||
<DebouncedInputMemo
|
||||
size={props.size}
|
||||
aggressiveRefocus
|
||||
debounceTimeout={300}
|
||||
onDebounce={props.onSearch}
|
||||
placeholder={`Search ${props.llmsCount} models...`}
|
||||
startDecorator={props.onStarredToggle ? (
|
||||
<IconButton
|
||||
size='sm'
|
||||
variant='plain'
|
||||
aria-label='Filter starred models'
|
||||
onClick={props.onStarredToggle}
|
||||
>
|
||||
<StarredState isStarred={!!props.showStarredOnly} />
|
||||
{/*<StarIconUnstyled isStarred={showStarredOnly} />*/}
|
||||
</IconButton>
|
||||
) : undefined}
|
||||
sx={_styles.filterBox}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import { findModelVendor } from '~/modules/llms/vendors/vendors.registry';
|
||||
|
||||
import type { DLLM, DLLMId } from '../llms.types';
|
||||
import type { DModelsServiceId } from '../llms.service.types';
|
||||
import { findModelsServiceOrNull } from '../store-llms';
|
||||
import { isLLMVisible } from '../llms.types';
|
||||
|
||||
|
||||
/**
|
||||
* Filter LLMs for dropdown display.
|
||||
* Always includes the current model, respects starred/search/visibility filters.
|
||||
*/
|
||||
export function filterLLMsForDropdown(
|
||||
llms: ReadonlyArray<DLLM>,
|
||||
options: {
|
||||
currentModelId?: DLLMId | null,
|
||||
searchString?: string | null,
|
||||
starredOnly?: boolean,
|
||||
},
|
||||
): DLLM[] {
|
||||
const lcSearch = options.searchString?.toLowerCase();
|
||||
return llms.filter(llm => {
|
||||
// Always include the currently selected model
|
||||
if (options.currentModelId && llm.id === options.currentModelId) return true;
|
||||
|
||||
// Filter by starred status
|
||||
if (options.starredOnly && !llm.userStarred) return false;
|
||||
|
||||
// Filter by search string
|
||||
if (lcSearch && !llm.label.toLowerCase().includes(lcSearch)) return false;
|
||||
|
||||
// Show visible models, or all if actively searching
|
||||
return lcSearch ? true : isLLMVisible(llm);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export interface LLMServiceGroup {
|
||||
serviceId: DModelsServiceId;
|
||||
serviceLabel: string;
|
||||
models: DLLM[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Group LLMs by service, resolving service display labels.
|
||||
*/
|
||||
export function groupLLMsByService(llms: ReadonlyArray<DLLM>): LLMServiceGroup[] {
|
||||
const groups: LLMServiceGroup[] = [];
|
||||
let currentGroup: LLMServiceGroup | null = null;
|
||||
|
||||
for (const llm of llms) {
|
||||
if (!currentGroup || currentGroup.serviceId !== llm.sId) {
|
||||
const vendor = findModelVendor(llm.vId);
|
||||
const serviceLabel = findModelsServiceOrNull(llm.sId)?.label || vendor?.name || llm.sId;
|
||||
currentGroup = { serviceId: llm.sId, serviceLabel, models: [] };
|
||||
groups.push(currentGroup);
|
||||
}
|
||||
currentGroup.models.push(llm);
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
Reference in New Issue
Block a user