Models list: display free models

This commit is contained in:
Enrico Ros
2025-04-05 12:01:30 -07:00
parent a703edab58
commit dd24b33cce
+63 -29
View File
@@ -3,7 +3,6 @@ import * as React from 'react';
import type { SxProps } from '@mui/joy/styles/types';
import { Box, Chip, IconButton, List, ListItem, ListItemButton, Typography } from '@mui/joy';
import PsychologyOutlinedIcon from '@mui/icons-material/PsychologyOutlined';
import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined';
import SdCardOutlinedIcon from '@mui/icons-material/SdCardOutlined';
import TextsmsOutlinedIcon from '@mui/icons-material/TextsmsOutlined';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
@@ -12,6 +11,7 @@ import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
import type { DModelsServiceId } from '~/common/stores/llms/llms.service.types';
import { DLLM, DLLMId, LLM_IF_ANT_PromptCaching, LLM_IF_GEM_CodeExecution, LLM_IF_OAI_Chat, LLM_IF_OAI_Complete, LLM_IF_OAI_Fn, LLM_IF_OAI_Json, LLM_IF_OAI_PromptCaching, LLM_IF_OAI_Realtime, LLM_IF_OAI_Reasoning, LLM_IF_OAI_Vision } from '~/common/stores/llms/llms.types';
import { GoodTooltip } from '~/common/components/GoodTooltip';
import { PhGearSixIcon } from '~/common/components/icons/phosphor/PhGearSixIcon';
import { findModelsServiceOrNull, llmsStoreActions } from '~/common/stores/llms/store-llms';
import { useLLMsByService } from '~/common/stores/llms/llms.hooks';
import { useIsMobile } from '~/common/components/useMatchMedia';
@@ -27,6 +27,36 @@ const SHOW_LLM_INTERFACES = false;
const absorbListPadding: SxProps = { my: 'calc(var(--ListItem-paddingY) / -2)' };
const styles = {
liButton: {
border: 'none',
width: '100%',
display: 'flex',
alignItems: 'center',
gap: {
xs: 0.5,
md: 1,
} as const,
} as const,
modelText: {
flex: 1,
wordBreak: 'break-all',
} as const,
modelHiddenText: {
flex: 1,
wordBreak: 'break-all',
color: 'neutral.plainDisabledColor',
} as const,
chip: {
// boxShadow: 'sm',
} as const,
chipFree: {
// boxShadow: 'sm',
boxShadow: 'md',
} as const,
} as const;
function ModelItem(props: {
llm: DLLM,
serviceLabel: string,
@@ -43,6 +73,9 @@ function ModelItem(props: {
// derived
const { llm, onModelClicked, onModelSetHidden /*, onModelSetStarred*/ } = props;
const seemsFree = !!llm.pricing?.chat?._isFree;
const handleLLMConfigure = React.useCallback((event: React.MouseEvent) => {
event.stopPropagation();
if (event.shiftKey) {
@@ -83,7 +116,7 @@ function ModelItem(props: {
tooltip += ' / ' + llm.maxOutputTokens.toLocaleString() + ' max output tokens';
} else
tooltip += ' · token count not provided';
if (llm.pricing?.chat?._isFree)
if (seemsFree)
tooltip += '\n\n🎁 Free model - refresh to check for pricing updates';
const chipsComponentsMemo = React.useMemo(() => {
@@ -115,26 +148,23 @@ function ModelItem(props: {
<ListItem>
<ListItemButton
aria-label='Configure LLM'
// color={(seemsFree && !llm.hidden) ? 'success' : undefined}
// variant={(seemsFree && !llm.hidden) ? 'soft' : undefined}
onClick={handleLLMConfigure}
tabIndex={-1}
sx={{
width: '100%',
display: 'flex', alignItems: 'center', gap: { xs: 0.5, md: 1 },
}}
sx={styles.liButton}
>
{/* Model Name */}
<GoodTooltip title={tooltip}>
<Box sx={{
flex: 1,
color: llm.hidden ? 'neutral.plainDisabledColor' : 'text.primary',
wordBreak: 'break-all',
}}>
<Box sx={llm.hidden ? styles.modelHiddenText : styles.modelText} className='agi-ellipsize'>
{(/*props.isMobile &&*/ llm.userStarred) ? `${llm.label}` : llm.label}
{/*{labelWithoutDate}{labelDate && <Box component='span' sx={{ typography: 'body-sm',color: llm.hidden ? 'neutral.plainDisabledColor' : undefined }}> · ({labelDate})</Box>}*/}
</Box>
</GoodTooltip>
{seemsFree && !llm.label.startsWith('🔗') && <Chip size='sm' color='success' variant='plain' sx={styles.chipFree}>free</Chip>}
{/* Chips */}
{SHOW_LLM_INTERFACES ? (chipsComponentsMemo && (
<Box sx={{
@@ -146,30 +176,34 @@ function ModelItem(props: {
{chipsComponentsMemo}
</Box>
)) : <>
{props.chipChat && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>chat</Chip>}
{props.chipCode && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>code</Chip>}
{props.chipFast && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>fast</Chip>}
{props.chipChat && <Chip size='sm' variant='outlined' sx={styles.chip}>chat</Chip>}
{props.chipCode && <Chip size='sm' variant='outlined' sx={styles.chip}>code</Chip>}
{props.chipFast && <Chip size='sm' variant='outlined' sx={styles.chip}>fast</Chip>}
</>}
{/* Action Buttons */}
{/*{!props.isMobile && <GoodTooltip title={llm.userStarred ? 'Unstar' : 'Star this model'}>*/}
{/* <IconButton size='sm' onClick={handleLLMToggleStar} sx={absorbListPadding}>*/}
{/* {llm.userStarred ? <StarIcon sx={{ color: '#fad857' }} /> : <StarBorderIcon sx={{ opacity: 0.5, fontSize: 'md' }} />}*/}
{/* </IconButton>*/}
{/*</GoodTooltip>}*/}
<Box sx={{ display: 'flex', gap: 1 }}>
{!props.isMobile && <GoodTooltip title={llm.hidden ? 'Hidden' : 'Shown in Chat'}>
<IconButton aria-label={llm.hidden ? 'Unhide' : 'Hide in Chat'} size='sm' onClick={llm.hidden ? handleLLMUnhide : handleLLMHide} sx={absorbListPadding}>
{llm.hidden ? <VisibilityOffOutlinedIcon sx={{ opacity: 0.5, fontSize: 'md' }} /> : <VisibilityOutlinedIcon />}
</IconButton>
</GoodTooltip>}
{/*{!props.isMobile && <GoodTooltip title={llm.userStarred ? 'Unstar' : 'Star this model'}>*/}
{/* <IconButton size='sm' onClick={handleLLMToggleStar} sx={absorbListPadding}>*/}
{/* {llm.userStarred ? <StarIcon sx={{ color: '#fad857' }} /> : <StarBorderIcon sx={{ opacity: 0.5, fontSize: 'md' }} />}*/}
{/* </IconButton>*/}
{/*</GoodTooltip>}*/}
<GoodTooltip title='Options'>
<IconButton aria-label='Configure LLM' size='sm' sx={absorbListPadding} onClick={handleLLMConfigure}>
<SettingsOutlinedIcon />
</IconButton>
</GoodTooltip>
{!props.isMobile && <GoodTooltip title={llm.hidden ? 'Hidden' : 'Shown in Chat'}>
<IconButton aria-label={llm.hidden ? 'Unhide' : 'Hide in Chat'} size='sm' onClick={llm.hidden ? handleLLMUnhide : handleLLMHide} sx={absorbListPadding}>
{llm.hidden ? <VisibilityOffOutlinedIcon sx={{ opacity: 0.5, fontSize: 'md' }} /> : <VisibilityOutlinedIcon />}
</IconButton>
</GoodTooltip>}
<GoodTooltip title='Options'>
<IconButton aria-label='Configure LLM' size='sm' sx={absorbListPadding} onClick={handleLLMConfigure}>
<PhGearSixIcon />
</IconButton>
</GoodTooltip>
</Box>
</ListItemButton>
</ListItem>